aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CREDITS3
-rw-r--r--Documentation/00-INDEX2
-rw-r--r--Documentation/Changes2
-rw-r--r--Documentation/DMA-API.txt2
-rw-r--r--Documentation/DMA-ISA-LPC.txt2
-rw-r--r--Documentation/DocBook/writing_usb_driver.tmpl3
-rw-r--r--Documentation/MSI-HOWTO.txt2
-rw-r--r--Documentation/accounting/taskstats.txt10
-rw-r--r--Documentation/block/biodoc.txt10
-rw-r--r--Documentation/cpu-freq/cpufreq-nforce2.txt4
-rw-r--r--Documentation/cpu-hotplug.txt4
-rw-r--r--Documentation/devices.txt8
-rw-r--r--Documentation/driver-model/platform.txt204
-rw-r--r--Documentation/driver-model/porting.txt2
-rw-r--r--Documentation/dvb/ci.txt4
-rw-r--r--Documentation/eisa.txt2
-rw-r--r--Documentation/feature-removal-schedule.txt38
-rw-r--r--Documentation/filesystems/adfs.txt2
-rw-r--r--Documentation/filesystems/configfs/configfs.txt4
-rw-r--r--Documentation/filesystems/fuse.txt4
-rw-r--r--Documentation/filesystems/hpfs.txt2
-rw-r--r--Documentation/filesystems/ntfs.txt4
-rw-r--r--Documentation/filesystems/ocfs2.txt2
-rw-r--r--Documentation/filesystems/proc.txt10
-rw-r--r--Documentation/filesystems/spufs.txt2
-rw-r--r--Documentation/ftape.txt307
-rw-r--r--Documentation/fujitsu/frv/gdbstub.txt2
-rw-r--r--Documentation/fujitsu/frv/kernel-ABI.txt2
-rw-r--r--Documentation/ide.txt2
-rw-r--r--Documentation/input/amijoy.txt4
-rw-r--r--Documentation/input/atarikbd.txt12
-rw-r--r--Documentation/input/yealink.txt2
-rw-r--r--Documentation/ioctl/cdrom.txt2
-rw-r--r--Documentation/kbuild/makefiles.txt10
-rw-r--r--Documentation/kernel-parameters.txt3
-rw-r--r--Documentation/keys.txt2
-rw-r--r--Documentation/laptop-mode.txt8
-rw-r--r--Documentation/memory-barriers.txt2
-rw-r--r--Documentation/networking/NAPI_HOWTO.txt26
-rw-r--r--Documentation/networking/cs89x0.txt6
-rw-r--r--Documentation/networking/dccp.txt84
-rw-r--r--Documentation/networking/e1000.txt451
-rw-r--r--Documentation/networking/ip-sysctl.txt347
-rw-r--r--Documentation/networking/iphase.txt2
-rw-r--r--Documentation/networking/packet_mmap.txt2
-rw-r--r--Documentation/networking/phy.txt13
-rw-r--r--Documentation/networking/pktgen.txt6
-rw-r--r--Documentation/networking/proc_net_tcp.txt2
-rw-r--r--Documentation/networking/sk98lin.txt2
-rw-r--r--Documentation/networking/slicecom.txt2
-rw-r--r--Documentation/networking/udplite.txt281
-rw-r--r--Documentation/networking/wan-router.txt8
-rw-r--r--Documentation/networking/xfrm_sync.txt5
-rw-r--r--Documentation/pnp.txt2
-rw-r--r--Documentation/power/pci.txt4
-rw-r--r--Documentation/power/states.txt2
-rw-r--r--Documentation/power/swsusp.txt2
-rw-r--r--Documentation/powerpc/booting-without-of.txt8
-rw-r--r--Documentation/robust-futex-ABI.txt2
-rw-r--r--Documentation/robust-futexes.txt2
-rw-r--r--Documentation/rtc.txt463
-rw-r--r--Documentation/s390/crypto/crypto-API.txt4
-rw-r--r--Documentation/scsi/aic79xx.txt4
-rw-r--r--Documentation/scsi/aic7xxx_old.txt4
-rw-r--r--Documentation/scsi/ibmmca.txt14
-rw-r--r--Documentation/scsi/in2000.txt2
-rw-r--r--Documentation/scsi/libsas.txt2
-rw-r--r--Documentation/scsi/ncr53c8xx.txt2
-rw-r--r--Documentation/scsi/scsi-changer.txt4
-rw-r--r--Documentation/scsi/scsi_eh.txt2
-rw-r--r--Documentation/scsi/st.txt2
-rw-r--r--Documentation/scsi/sym53c8xx_2.txt2
-rw-r--r--Documentation/sharedsubtree.txt4
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt2
-rw-r--r--Documentation/sound/alsa/Audigy-mixer.txt2
-rw-r--r--Documentation/sound/alsa/SB-Live-mixer.txt2
-rw-r--r--Documentation/stable_kernel_rules.txt2
-rw-r--r--Documentation/sysctl/fs.txt2
-rw-r--r--Documentation/sysctl/vm.txt2
-rw-r--r--Documentation/uml/UserModeLinux-HOWTO.txt2
-rw-r--r--Documentation/usb/hiddev.txt2
-rw-r--r--Documentation/usb/rio.txt4
-rw-r--r--Documentation/usb/usb-serial.txt8
-rw-r--r--Documentation/watchdog/watchdog-api.txt2
-rw-r--r--MAINTAINERS169
-rw-r--r--Makefile2
-rw-r--r--arch/alpha/lib/checksum.c37
-rw-r--r--arch/alpha/lib/csum_partial_copy.c31
-rw-r--r--arch/arm/Kconfig2
-rw-r--r--arch/arm/configs/assabet_defconfig1
-rw-r--r--arch/arm/configs/cerfcube_defconfig1
-rw-r--r--arch/arm/configs/corgi_defconfig1
-rw-r--r--arch/arm/configs/h3600_defconfig1
-rw-r--r--arch/arm/configs/integrator_defconfig1
-rw-r--r--arch/arm/configs/jornada720_defconfig1
-rw-r--r--arch/arm/configs/lart_defconfig1
-rw-r--r--arch/arm/configs/neponset_defconfig1
-rw-r--r--arch/arm/configs/simpad_defconfig1
-rw-r--r--arch/arm/configs/spitz_defconfig1
-rw-r--r--arch/arm/kernel/smp.c1
-rw-r--r--arch/arm/mach-ebsa110/io.c8
-rw-r--r--arch/arm/mach-ixp4xx/Kconfig2
-rw-r--r--arch/arm/mach-lh7a40x/Kconfig2
-rw-r--r--arch/arm/mach-s3c2410/Kconfig2
-rw-r--r--arch/arm/mm/Kconfig2
-rw-r--r--arch/arm/mm/consistent.c3
-rw-r--r--arch/cris/arch-v10/Kconfig2
-rw-r--r--arch/cris/arch-v10/drivers/Kconfig2
-rw-r--r--arch/cris/arch-v10/drivers/eeprom.c6
-rw-r--r--arch/cris/arch-v10/drivers/i2c.c2
-rw-r--r--arch/cris/arch-v10/kernel/kgdb.c2
-rw-r--r--arch/cris/arch-v10/lib/old_checksum.c62
-rw-r--r--arch/cris/arch-v32/drivers/Kconfig8
-rw-r--r--arch/frv/lib/checksum.c25
-rw-r--r--arch/h8300/kernel/h8300_ksyms.c2
-rw-r--r--arch/h8300/lib/checksum.c29
-rw-r--r--arch/i386/kernel/acpi/boot.c10
-rw-r--r--arch/i386/kernel/cpuid.c20
-rw-r--r--arch/i386/kernel/msr.c20
-rw-r--r--arch/i386/kernel/pci-dma.c4
-rw-r--r--arch/i386/pci/common.c2
-rw-r--r--arch/i386/pci/fixup.c46
-rw-r--r--arch/i386/pci/i386.c64
-rw-r--r--arch/i386/pci/irq.c6
-rw-r--r--arch/ia64/hp/common/sba_iommu.c8
-rw-r--r--arch/ia64/lib/checksum.c38
-rw-r--r--arch/ia64/lib/csum_partial_copy.c31
-rw-r--r--arch/ia64/pci/pci.c75
-rw-r--r--arch/ia64/sn/kernel/Makefile5
-rw-r--r--arch/ia64/sn/kernel/io_acpi_init.c231
-rw-r--r--arch/ia64/sn/kernel/io_common.c613
-rw-r--r--arch/ia64/sn/kernel/io_init.c633
-rw-r--r--arch/ia64/sn/kernel/iomv.c11
-rw-r--r--arch/ia64/sn/kernel/setup.c18
-rw-r--r--arch/ia64/sn/kernel/tiocx.c2
-rw-r--r--arch/ia64/sn/pci/pcibr/pcibr_provider.c17
-rw-r--r--arch/ia64/sn/pci/tioce_provider.c18
-rw-r--r--arch/m32r/lib/csum_partial_copy.c12
-rw-r--r--arch/m68k/lib/checksum.c13
-rw-r--r--arch/m68knommu/Kconfig4
-rw-r--r--arch/m68knommu/kernel/m68k_ksyms.c2
-rw-r--r--arch/m68knommu/lib/checksum.c28
-rw-r--r--arch/mips/Kconfig32
-rw-r--r--arch/mips/Makefile4
-rw-r--r--arch/mips/au1000/common/irq.c63
-rw-r--r--arch/mips/au1000/pb1200/board_setup.c8
-rw-r--r--arch/mips/cobalt/irq.c31
-rw-r--r--arch/mips/cobalt/setup.c16
-rw-r--r--arch/mips/ddb5xxx/ddb5477/irq_5477.c23
-rw-r--r--arch/mips/dec/ecc-berr.c6
-rw-r--r--arch/mips/dec/int-handler.S2
-rw-r--r--arch/mips/dec/ioasic-irq.c74
-rw-r--r--arch/mips/dec/kn02-irq.c53
-rw-r--r--arch/mips/dec/setup.c6
-rw-r--r--arch/mips/dec/time.c4
-rw-r--r--arch/mips/emma2rh/common/irq_emma2rh.c35
-rw-r--r--arch/mips/emma2rh/markeins/irq_markeins.c56
-rw-r--r--arch/mips/gt64120/ev64120/irq.c40
-rw-r--r--arch/mips/jazz/irq.c27
-rw-r--r--arch/mips/jmr3927/rbhma3100/irq.c32
-rw-r--r--arch/mips/jmr3927/rbhma3100/setup.c4
-rw-r--r--arch/mips/kernel/Makefile5
-rw-r--r--arch/mips/kernel/cpu-probe.c19
-rw-r--r--arch/mips/kernel/dma-no-isa.c28
-rw-r--r--arch/mips/kernel/genex.S63
-rw-r--r--arch/mips/kernel/head.S3
-rw-r--r--arch/mips/kernel/i8259.c21
-rw-r--r--arch/mips/kernel/irq-msc01.c47
-rw-r--r--arch/mips/kernel/irq-mv6434x.c54
-rw-r--r--arch/mips/kernel/irq-rm7000.c54
-rw-r--r--arch/mips/kernel/irq-rm9000.c47
-rw-r--r--arch/mips/kernel/irq.c32
-rw-r--r--arch/mips/kernel/irq_cpu.c80
-rw-r--r--arch/mips/kernel/machine_kexec.c85
-rw-r--r--arch/mips/kernel/module.c15
-rw-r--r--arch/mips/kernel/relocate_kernel.S80
-rw-r--r--arch/mips/kernel/scall32-o32.S2
-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.c87
-rw-r--r--arch/mips/kernel/signal_n32.c1
-rw-r--r--arch/mips/kernel/smp-mt.c2
-rw-r--r--arch/mips/kernel/smp.c23
-rw-r--r--arch/mips/kernel/smtc.c1
-rw-r--r--arch/mips/kernel/time.c64
-rw-r--r--arch/mips/kernel/topology.c29
-rw-r--r--arch/mips/kernel/traps.c72
-rw-r--r--arch/mips/lasat/interrupt.c36
-rw-r--r--arch/mips/lib/csum_partial_copy.c8
-rw-r--r--arch/mips/mips-boards/atlas/atlas_int.c29
-rw-r--r--arch/mips/mips-boards/generic/time.c1
-rw-r--r--arch/mips/mips-boards/malta/malta_setup.c2
-rw-r--r--arch/mips/mips-boards/sim/sim_time.c18
-rw-r--r--arch/mips/mm/c-r4k.c22
-rw-r--r--arch/mips/mm/c-sb1.c22
-rw-r--r--arch/mips/mm/fault.c4
-rw-r--r--arch/mips/mm/init.c42
-rw-r--r--arch/mips/mm/pgtable-64.c3
-rw-r--r--arch/mips/mm/tlbex.c55
-rw-r--r--arch/mips/momentum/ocelot_c/cpci-irq.c53
-rw-r--r--arch/mips/momentum/ocelot_c/uart-irq.c56
-rw-r--r--arch/mips/oprofile/Makefile1
-rw-r--r--arch/mips/oprofile/common.c3
-rw-r--r--arch/mips/oprofile/op_model_mipsxx.c32
-rw-r--r--arch/mips/pci/fixup-cobalt.c11
-rw-r--r--arch/mips/pci/ops-gt64111.c16
-rw-r--r--arch/mips/philips/pnx8550/common/int.c68
-rw-r--r--arch/mips/pmc-sierra/yosemite/smp.c2
-rw-r--r--arch/mips/sgi-ip22/ip22-eisa.c33
-rw-r--r--arch/mips/sgi-ip22/ip22-int.c109
-rw-r--r--arch/mips/sgi-ip27/ip27-irq.c17
-rw-r--r--arch/mips/sgi-ip27/ip27-timer.c32
-rw-r--r--arch/mips/sgi-ip32/ip32-irq.c133
-rw-r--r--arch/mips/sibyte/bcm1480/irq.c30
-rw-r--r--arch/mips/sibyte/bcm1480/time.c6
-rw-r--r--arch/mips/sibyte/sb1250/irq.c30
-rw-r--r--arch/mips/sibyte/sb1250/time.c8
-rw-r--r--arch/mips/sni/irq.c40
-rw-r--r--arch/mips/tx4927/common/tx4927_irq.c164
-rw-r--r--arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c184
-rw-r--r--arch/mips/tx4938/common/irq.c115
-rw-r--r--arch/mips/tx4938/common/setup.c1
-rw-r--r--arch/mips/tx4938/toshiba_rbtx4938/irq.c54
-rw-r--r--arch/mips/vr41xx/common/icu.c48
-rw-r--r--arch/mips/vr41xx/nec-cmbvr4133/irq.c20
-rw-r--r--arch/parisc/lib/checksum.c17
-rw-r--r--arch/powerpc/Kconfig2
-rw-r--r--arch/powerpc/platforms/83xx/Kconfig4
-rw-r--r--arch/powerpc/platforms/powermac/pci.c1
-rw-r--r--arch/ppc/Kconfig2
-rw-r--r--arch/sh/Kconfig2
-rw-r--r--arch/sh/kernel/sh_ksyms.c1
-rw-r--r--arch/sh64/kernel/sh_ksyms.c2
-rw-r--r--arch/sh64/lib/c-checksum.c49
-rw-r--r--arch/sh64/lib/dbg.c2
-rw-r--r--arch/sparc/Kconfig4
-rw-r--r--arch/sparc64/kernel/pci.c9
-rw-r--r--arch/um/drivers/chan_user.c2
-rw-r--r--arch/um/include/os.h2
-rw-r--r--arch/um/include/sysdep-i386/checksum.h74
-rw-r--r--arch/um/include/sysdep-x86_64/checksum.h47
-rw-r--r--arch/um/os-Linux/Makefile10
-rw-r--r--arch/um/os-Linux/execvp.c149
-rw-r--r--arch/um/os-Linux/helper.c14
-rw-r--r--arch/v850/kernel/v850_ksyms.c2
-rw-r--r--arch/v850/lib/checksum.c26
-rw-r--r--arch/x86_64/kernel/early_printk.c2
-rw-r--r--arch/x86_64/kernel/io_apic.c2
-rw-r--r--arch/x86_64/kernel/traps.c10
-rw-r--r--arch/x86_64/lib/csum-partial.c7
-rw-r--r--arch/x86_64/lib/csum-wrappers.c37
-rw-r--r--block/as-iosched.c2
-rw-r--r--block/blktrace.c57
-rw-r--r--block/cfq-iosched.c9
-rw-r--r--block/deadline-iosched.c2
-rw-r--r--block/elevator.c4
-rw-r--r--block/ll_rw_blk.c166
-rw-r--r--block/noop-iosched.c2
-rw-r--r--block/scsi_ioctl.c53
-rw-r--r--drivers/acpi/glue.c20
-rw-r--r--drivers/acpi/processor_perflib.c4
-rw-r--r--drivers/ata/ahci.c38
-rw-r--r--drivers/ata/ata_generic.c1
-rw-r--r--drivers/ata/libata-scsi.c21
-rw-r--r--drivers/ata/pata_ali.c1
-rw-r--r--drivers/ata/pata_amd.c1
-rw-r--r--drivers/ata/pata_artop.c1
-rw-r--r--drivers/ata/pata_atiixp.c1
-rw-r--r--drivers/ata/pata_cmd64x.c1
-rw-r--r--drivers/ata/pata_cs5520.c1
-rw-r--r--drivers/ata/pata_cs5530.c1
-rw-r--r--drivers/ata/pata_cs5535.c1
-rw-r--r--drivers/ata/pata_cypress.c1
-rw-r--r--drivers/ata/pata_efar.c1
-rw-r--r--drivers/ata/pata_hpt366.c1
-rw-r--r--drivers/ata/pata_hpt37x.c1
-rw-r--r--drivers/ata/pata_hpt3x2n.c1
-rw-r--r--drivers/ata/pata_hpt3x3.c1
-rw-r--r--drivers/ata/pata_isapnp.c1
-rw-r--r--drivers/ata/pata_it821x.c1
-rw-r--r--drivers/ata/pata_jmicron.c1
-rw-r--r--drivers/ata/pata_legacy.c1
-rw-r--r--drivers/ata/pata_mpiix.c1
-rw-r--r--drivers/ata/pata_netcell.c1
-rw-r--r--drivers/ata/pata_ns87410.c1
-rw-r--r--drivers/ata/pata_oldpiix.c1
-rw-r--r--drivers/ata/pata_opti.c1
-rw-r--r--drivers/ata/pata_optidma.c1
-rw-r--r--drivers/ata/pata_pcmcia.c1
-rw-r--r--drivers/ata/pata_pdc2027x.c1
-rw-r--r--drivers/ata/pata_pdc202xx_old.c1
-rw-r--r--drivers/ata/pata_qdi.c1
-rw-r--r--drivers/ata/pata_radisys.c1
-rw-r--r--drivers/ata/pata_rz1000.c1
-rw-r--r--drivers/ata/pata_sc1200.c1
-rw-r--r--drivers/ata/pata_serverworks.c1
-rw-r--r--drivers/ata/pata_sil680.c1
-rw-r--r--drivers/ata/pata_sis.c1
-rw-r--r--drivers/ata/pata_sl82c105.c1
-rw-r--r--drivers/ata/pata_triflex.c1
-rw-r--r--drivers/ata/pata_via.c1
-rw-r--r--drivers/atm/ambassador.c2
-rw-r--r--drivers/atm/firestream.c2
-rw-r--r--drivers/atm/iphase.c2
-rw-r--r--drivers/base/bus.c34
-rw-r--r--drivers/base/class.c166
-rw-r--r--drivers/base/core.c241
-rw-r--r--drivers/base/dd.c92
-rw-r--r--drivers/base/firmware_class.c119
-rw-r--r--drivers/base/platform.c48
-rw-r--r--drivers/base/topology.c55
-rw-r--r--drivers/cdrom/cdrom.c6
-rw-r--r--drivers/char/Kconfig35
-rw-r--r--drivers/char/Makefile1
-rw-r--r--drivers/char/agp/generic.c2
-rw-r--r--drivers/char/agp/intel-agp.c33
-rw-r--r--drivers/char/ftape/Kconfig330
-rw-r--r--drivers/char/ftape/Makefile28
-rw-r--r--drivers/char/ftape/README.PCI81
-rw-r--r--drivers/char/ftape/RELEASE-NOTES966
-rw-r--r--drivers/char/ftape/compressor/Makefile31
-rw-r--r--drivers/char/ftape/compressor/lzrw3.c743
-rw-r--r--drivers/char/ftape/compressor/lzrw3.h253
-rw-r--r--drivers/char/ftape/compressor/zftape-compress.c1203
-rw-r--r--drivers/char/ftape/compressor/zftape-compress.h83
-rw-r--r--drivers/char/ftape/lowlevel/Makefile43
-rw-r--r--drivers/char/ftape/lowlevel/fc-10.c175
-rw-r--r--drivers/char/ftape/lowlevel/fc-10.h39
-rw-r--r--drivers/char/ftape/lowlevel/fdc-io.c1349
-rw-r--r--drivers/char/ftape/lowlevel/fdc-io.h252
-rw-r--r--drivers/char/ftape/lowlevel/fdc-isr.c1170
-rw-r--r--drivers/char/ftape/lowlevel/fdc-isr.h55
-rw-r--r--drivers/char/ftape/lowlevel/ftape-bsm.c491
-rw-r--r--drivers/char/ftape/lowlevel/ftape-bsm.h66
-rw-r--r--drivers/char/ftape/lowlevel/ftape-buffer.c130
-rw-r--r--drivers/char/ftape/lowlevel/ftape-buffer.h32
-rw-r--r--drivers/char/ftape/lowlevel/ftape-calibr.c275
-rw-r--r--drivers/char/ftape/lowlevel/ftape-calibr.h37
-rw-r--r--drivers/char/ftape/lowlevel/ftape-ctl.c896
-rw-r--r--drivers/char/ftape/lowlevel/ftape-ctl.h162
-rw-r--r--drivers/char/ftape/lowlevel/ftape-ecc.c853
-rw-r--r--drivers/char/ftape/lowlevel/ftape-ecc.h84
-rw-r--r--drivers/char/ftape/lowlevel/ftape-format.c344
-rw-r--r--drivers/char/ftape/lowlevel/ftape-format.h37
-rw-r--r--drivers/char/ftape/lowlevel/ftape-init.c160
-rw-r--r--drivers/char/ftape/lowlevel/ftape-init.h43
-rw-r--r--drivers/char/ftape/lowlevel/ftape-io.c992
-rw-r--r--drivers/char/ftape/lowlevel/ftape-io.h90
-rw-r--r--drivers/char/ftape/lowlevel/ftape-proc.c214
-rw-r--r--drivers/char/ftape/lowlevel/ftape-proc.h35
-rw-r--r--drivers/char/ftape/lowlevel/ftape-read.c621
-rw-r--r--drivers/char/ftape/lowlevel/ftape-read.h51
-rw-r--r--drivers/char/ftape/lowlevel/ftape-rw.c1092
-rw-r--r--drivers/char/ftape/lowlevel/ftape-rw.h111
-rw-r--r--drivers/char/ftape/lowlevel/ftape-setup.c104
-rw-r--r--drivers/char/ftape/lowlevel/ftape-tracing.c118
-rw-r--r--drivers/char/ftape/lowlevel/ftape-tracing.h179
-rw-r--r--drivers/char/ftape/lowlevel/ftape-write.c336
-rw-r--r--drivers/char/ftape/lowlevel/ftape-write.h53
-rw-r--r--drivers/char/ftape/lowlevel/ftape_syms.c87
-rw-r--r--drivers/char/ftape/zftape/Makefile36
-rw-r--r--drivers/char/ftape/zftape/zftape-buffers.c149
-rw-r--r--drivers/char/ftape/zftape/zftape-buffers.h55
-rw-r--r--drivers/char/ftape/zftape/zftape-ctl.c1417
-rw-r--r--drivers/char/ftape/zftape/zftape-ctl.h58
-rw-r--r--drivers/char/ftape/zftape/zftape-eof.c199
-rw-r--r--drivers/char/ftape/zftape/zftape-eof.h52
-rw-r--r--drivers/char/ftape/zftape/zftape-init.c377
-rw-r--r--drivers/char/ftape/zftape/zftape-init.h77
-rw-r--r--drivers/char/ftape/zftape/zftape-read.c377
-rw-r--r--drivers/char/ftape/zftape/zftape-read.h53
-rw-r--r--drivers/char/ftape/zftape/zftape-rw.c375
-rw-r--r--drivers/char/ftape/zftape/zftape-rw.h101
-rw-r--r--drivers/char/ftape/zftape/zftape-vtbl.c757
-rw-r--r--drivers/char/ftape/zftape/zftape-vtbl.h227
-rw-r--r--drivers/char/ftape/zftape/zftape-write.c483
-rw-r--r--drivers/char/ftape/zftape/zftape-write.h38
-rw-r--r--drivers/char/ftape/zftape/zftape_syms.c43
-rw-r--r--drivers/char/hw_random/core.c38
-rw-r--r--drivers/char/mem.c8
-rw-r--r--drivers/char/misc.c13
-rw-r--r--drivers/char/ppdev.c6
-rw-r--r--drivers/char/random.c48
-rw-r--r--drivers/char/raw.c12
-rw-r--r--drivers/char/rio/riocmd.c2
-rw-r--r--drivers/char/rio/rioinit.c2
-rw-r--r--drivers/char/rio/rioparam.c6
-rw-r--r--drivers/char/tlclk.c5
-rw-r--r--drivers/char/tpm/tpm.c2
-rw-r--r--drivers/char/tty_io.c19
-rw-r--r--drivers/char/vc_screen.c16
-rw-r--r--drivers/char/vt.c81
-rw-r--r--drivers/char/watchdog/Kconfig32
-rw-r--r--drivers/char/watchdog/Makefile4
-rw-r--r--drivers/char/watchdog/iTCO_vendor_support.c307
-rw-r--r--drivers/char/watchdog/iTCO_wdt.c29
-rw-r--r--drivers/char/watchdog/pc87413_wdt.c635
-rw-r--r--drivers/char/watchdog/pcwd_usb.c3
-rw-r--r--drivers/char/watchdog/rm9k_wdt.c420
-rw-r--r--drivers/i2c/busses/Kconfig1
-rw-r--r--drivers/i2c/busses/i2c-i801.c2
-rw-r--r--drivers/i2c/busses/i2c-ixp4xx.c2
-rw-r--r--drivers/i2c/i2c-dev.c26
-rw-r--r--drivers/ide/ide-floppy.c2
-rw-r--r--drivers/ide/pci/sgiioc4.c7
-rw-r--r--drivers/infiniband/core/addr.c19
-rw-r--r--drivers/infiniband/core/cm.c121
-rw-r--r--drivers/infiniband/core/cma.c49
-rw-r--r--drivers/infiniband/core/iwcm.c44
-rw-r--r--drivers/infiniband/core/mad.c2
-rw-r--r--drivers/infiniband/core/ucm.c20
-rw-r--r--drivers/infiniband/hw/amso1100/c2.h2
-rw-r--r--drivers/infiniband/hw/amso1100/c2_qp.c36
-rw-r--r--drivers/infiniband/hw/amso1100/c2_rnic.c4
-rw-r--r--drivers/infiniband/hw/ehca/ehca_main.c4
-rw-r--r--drivers/infiniband/hw/ehca/ehca_qp.c22
-rw-r--r--drivers/infiniband/hw/ehca/ipz_pt_fn.c13
-rw-r--r--drivers/infiniband/hw/ehca/ipz_pt_fn.h15
-rw-r--r--drivers/infiniband/hw/ipath/ipath_verbs.c2
-rw-r--r--drivers/infiniband/hw/mthca/mthca_av.c3
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cq.c3
-rw-r--r--drivers/infiniband/hw/mthca/mthca_eq.c21
-rw-r--r--drivers/infiniband/hw/mthca/mthca_mad.c2
-rw-r--r--drivers/infiniband/hw/mthca/mthca_main.c29
-rw-r--r--drivers/infiniband/hw/mthca/mthca_mcg.c3
-rw-r--r--drivers/infiniband/hw/mthca/mthca_mr.c5
-rw-r--r--drivers/infiniband/hw/mthca/mthca_pd.c3
-rw-r--r--drivers/infiniband/hw/mthca/mthca_provider.c3
-rw-r--r--drivers/infiniband/hw/mthca/mthca_qp.c3
-rw-r--r--drivers/infiniband/hw/mthca/mthca_srq.c4
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h2
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c19
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c2
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.h2
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c11
-rw-r--r--drivers/input/joystick/iforce/iforce-usb.c6
-rw-r--r--drivers/input/serio/serio_raw.c2
-rw-r--r--drivers/isdn/gigaset/common.c2
-rw-r--r--drivers/isdn/gigaset/gigaset.h2
-rw-r--r--drivers/isdn/gigaset/interface.c10
-rw-r--r--drivers/isdn/gigaset/proc.c19
-rw-r--r--drivers/isdn/gigaset/usb-gigaset.c15
-rw-r--r--drivers/isdn/hardware/eicon/os_4bri.c2
-rw-r--r--drivers/isdn/hisax/hfc4s8s_l1.h2
-rw-r--r--drivers/isdn/hisax/isdnl2.c20
-rw-r--r--drivers/media/dvb/cinergyT2/cinergyT2.c6
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.c2
-rw-r--r--drivers/media/dvb/frontends/tda10086.c4
-rw-r--r--drivers/media/dvb/ttpci/budget-patch.c8
-rw-r--r--drivers/media/dvb/ttpci/budget.c9
-rw-r--r--drivers/media/dvb/ttusb-dec/ttusb_dec.c3
-rw-r--r--drivers/media/video/Kconfig2
-rw-r--r--drivers/media/video/et61x251/et61x251_core.c3
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw.c10
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-io.c2
-rw-r--r--drivers/media/video/pwc/pwc-if.c9
-rw-r--r--drivers/media/video/saa6588.c4
-rw-r--r--drivers/media/video/saa7115.c9
-rw-r--r--drivers/media/video/sn9c102/sn9c102_core.c5
-rw-r--r--drivers/media/video/usbvideo/quickcam_messenger.c3
-rw-r--r--drivers/media/video/zc0301/zc0301_core.c2
-rw-r--r--drivers/message/fusion/mptbase.c2
-rw-r--r--drivers/message/i2o/pci.c15
-rw-r--r--drivers/mmc/Kconfig2
-rw-r--r--drivers/mmc/at91_mci.c2
-rw-r--r--drivers/mmc/au1xmmc.c2
-rw-r--r--drivers/mmc/imxmmc.c2
-rw-r--r--drivers/mmc/mmc.c294
-rw-r--r--drivers/mmc/mmc_block.c15
-rw-r--r--drivers/mmc/mmc_queue.c67
-rw-r--r--drivers/mmc/mmc_queue.h3
-rw-r--r--drivers/mmc/mmc_sysfs.c20
-rw-r--r--drivers/mmc/mmci.c2
-rw-r--r--drivers/mmc/omap.c275
-rw-r--r--drivers/mmc/omap.h55
-rw-r--r--drivers/mmc/pxamci.c2
-rw-r--r--drivers/mmc/sdhci.c17
-rw-r--r--drivers/mmc/sdhci.h2
-rw-r--r--drivers/mmc/wbsd.c8
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0001.c2
-rw-r--r--drivers/mtd/maps/Kconfig2
-rw-r--r--drivers/mtd/maps/cfi_flagadm.c2
-rw-r--r--drivers/net/8390.c1080
-rw-r--r--drivers/net/8390.h37
-rw-r--r--drivers/net/Kconfig47
-rw-r--r--drivers/net/Makefile13
-rw-r--r--drivers/net/Space.c1
-rw-r--r--drivers/net/amd8111e.c27
-rw-r--r--drivers/net/amd8111e.h4
-rw-r--r--drivers/net/arm/etherh.c39
-rw-r--r--drivers/net/au1000_eth.c3
-rw-r--r--drivers/net/bnx2.c689
-rw-r--r--drivers/net/bnx2.h2940
-rw-r--r--drivers/net/bnx2_fw.h1234
-rw-r--r--drivers/net/bnx2_fw2.h4086
-rw-r--r--drivers/net/bonding/bond_main.c63
-rw-r--r--drivers/net/cassini.c2
-rw-r--r--drivers/net/chelsio/Makefile8
-rw-r--r--drivers/net/chelsio/common.h105
-rw-r--r--drivers/net/chelsio/cphy.h24
-rw-r--r--drivers/net/chelsio/cpl5_cmd.h510
-rw-r--r--drivers/net/chelsio/cxgb2.c591
-rw-r--r--drivers/net/chelsio/elmer0.h7
-rw-r--r--drivers/net/chelsio/espi.c205
-rw-r--r--drivers/net/chelsio/espi.h1
-rw-r--r--drivers/net/chelsio/fpga_defs.h232
-rw-r--r--drivers/net/chelsio/gmac.h5
-rw-r--r--drivers/net/chelsio/ixf1010.c485
-rw-r--r--drivers/net/chelsio/mac.c368
-rw-r--r--drivers/net/chelsio/mv88e1xxx.c397
-rw-r--r--drivers/net/chelsio/mv88e1xxx.h127
-rw-r--r--drivers/net/chelsio/mv88x201x.c36
-rw-r--r--drivers/net/chelsio/my3126.c204
-rw-r--r--drivers/net/chelsio/pm3393.c125
-rw-r--r--drivers/net/chelsio/regs.h1718
-rw-r--r--drivers/net/chelsio/sge.c867
-rw-r--r--drivers/net/chelsio/sge.h33
-rw-r--r--drivers/net/chelsio/subr.c494
-rw-r--r--drivers/net/chelsio/suni1x10gexp_regs.h1430
-rw-r--r--drivers/net/chelsio/tp.c178
-rw-r--r--drivers/net/chelsio/tp.h73
-rw-r--r--drivers/net/chelsio/vsc7326.c725
-rw-r--r--drivers/net/chelsio/vsc7326_reg.h286
-rw-r--r--drivers/net/chelsio/vsc8244.c368
-rw-r--r--drivers/net/chelsio/vsc8244_reg.h172
-rw-r--r--drivers/net/cs89x0.c4
-rw-r--r--drivers/net/defxx.c39
-rw-r--r--drivers/net/defxx.h15
-rw-r--r--drivers/net/depca.c28
-rw-r--r--drivers/net/e100.c2
-rw-r--r--drivers/net/e1000/e1000.h17
-rw-r--r--drivers/net/e1000/e1000_ethtool.c36
-rw-r--r--drivers/net/e1000/e1000_hw.c139
-rw-r--r--drivers/net/e1000/e1000_hw.h90
-rw-r--r--drivers/net/e1000/e1000_main.c490
-rw-r--r--drivers/net/e1000/e1000_osdep.h9
-rw-r--r--drivers/net/e1000/e1000_param.c98
-rw-r--r--drivers/net/forcedeth.c290
-rw-r--r--drivers/net/fs_enet/fs_enet-main.c3
-rw-r--r--drivers/net/gianfar.c72
-rw-r--r--drivers/net/gianfar.h3
-rw-r--r--drivers/net/hamradio/6pack.c2
-rw-r--r--drivers/net/hydra.c23
-rw-r--r--drivers/net/ioc3-eth.c1
-rw-r--r--drivers/net/irda/irda-usb.c6
-rw-r--r--drivers/net/ixgb/ixgb_main.c2
-rw-r--r--drivers/net/lib8390.c1097
-rw-r--r--drivers/net/mac8390.c26
-rw-r--r--drivers/net/macb.c1210
-rw-r--r--drivers/net/macb.h387
-rw-r--r--drivers/net/meth.c1
-rw-r--r--drivers/net/myri10ge/myri10ge.c2
-rw-r--r--drivers/net/myri_sbus.c1
-rw-r--r--drivers/net/ne-h8300.c23
-rw-r--r--drivers/net/netconsole.c8
-rw-r--r--drivers/net/netxen/Makefile35
-rw-r--r--drivers/net/netxen/netxen_nic.h1028
-rw-r--r--drivers/net/netxen/netxen_nic_ethtool.c741
-rw-r--r--drivers/net/netxen/netxen_nic_hdr.h678
-rw-r--r--drivers/net/netxen/netxen_nic_hw.c1010
-rw-r--r--drivers/net/netxen/netxen_nic_hw.h482
-rw-r--r--drivers/net/netxen/netxen_nic_init.c1304
-rw-r--r--drivers/net/netxen/netxen_nic_ioctl.h77
-rw-r--r--drivers/net/netxen/netxen_nic_isr.c215
-rw-r--r--drivers/net/netxen/netxen_nic_main.c1161
-rw-r--r--drivers/net/netxen/netxen_nic_niu.c894
-rw-r--r--drivers/net/netxen/netxen_nic_phan_reg.h215
-rw-r--r--drivers/net/pcmcia/pcnet_cs.c1
-rw-r--r--drivers/net/phy/Kconfig10
-rw-r--r--drivers/net/phy/Makefile1
-rw-r--r--drivers/net/phy/broadcom.c175
-rw-r--r--drivers/net/phy/phy.c113
-rw-r--r--drivers/net/phy/phy_device.c30
-rw-r--r--drivers/net/ppp_generic.c4
-rw-r--r--drivers/net/pppoe.c2
-rw-r--r--drivers/net/r8169.c26
-rw-r--r--drivers/net/sk98lin/h/skdrv2nd.h2
-rw-r--r--drivers/net/sk98lin/skdim.c4
-rw-r--r--drivers/net/sk98lin/skethtool.c26
-rw-r--r--drivers/net/sk98lin/skge.c58
-rw-r--r--drivers/net/skge.c8
-rw-r--r--drivers/net/sky2.c41
-rw-r--r--drivers/net/sky2.h11
-rw-r--r--drivers/net/spider_net.c20
-rw-r--r--drivers/net/spider_net.h8
-rw-r--r--drivers/net/sundance.c58
-rw-r--r--drivers/net/sungem.c2
-rw-r--r--drivers/net/sunhme.c2
-rw-r--r--drivers/net/tokenring/olympic.c2
-rw-r--r--drivers/net/tsi108_eth.c1708
-rw-r--r--drivers/net/tsi108_eth.h365
-rw-r--r--drivers/net/tulip/de2104x.c4
-rw-r--r--drivers/net/tulip/dmfe.c9
-rw-r--r--drivers/net/typhoon.c1
-rw-r--r--drivers/net/ucc_geth.c6
-rw-r--r--drivers/net/wan/Kconfig76
-rw-r--r--drivers/net/wireless/atmel.c36
-rw-r--r--drivers/net/wireless/atmel_cs.c74
-rw-r--r--drivers/net/wireless/atmel_pci.c10
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx.h32
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_main.c207
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_power.c28
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_wx.c4
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_xmit.c18
-rw-r--r--drivers/net/wireless/hostap/hostap_pci.c8
-rw-r--r--drivers/net/wireless/ipw2100.c25
-rw-r--r--drivers/net/wireless/ipw2200.c12
-rw-r--r--drivers/net/wireless/orinoco_pci.h7
-rw-r--r--drivers/net/wireless/prism54/isl_38xx.c17
-rw-r--r--drivers/net/wireless/prism54/isl_38xx.h7
-rw-r--r--drivers/net/wireless/prism54/isl_ioctl.c61
-rw-r--r--drivers/net/wireless/prism54/isl_ioctl.h1
-rw-r--r--drivers/net/wireless/prism54/isl_oid.h48
-rw-r--r--drivers/net/wireless/prism54/islpci_dev.c13
-rw-r--r--drivers/net/wireless/prism54/islpci_dev.h11
-rw-r--r--drivers/net/wireless/prism54/islpci_eth.c28
-rw-r--r--drivers/net/wireless/prism54/islpci_eth.h1
-rw-r--r--drivers/net/wireless/prism54/islpci_hotplug.c43
-rw-r--r--drivers/net/wireless/prism54/islpci_mgt.c3
-rw-r--r--drivers/net/wireless/prism54/islpci_mgt.h5
-rw-r--r--drivers/net/wireless/prism54/oid_mgt.c6
-rw-r--r--drivers/net/wireless/prism54/prismcompat.h4
-rw-r--r--drivers/net/wireless/zd1201.c6
-rw-r--r--drivers/net/wireless/zd1211rw/zd_chip.c38
-rw-r--r--drivers/net/wireless/zd1211rw/zd_chip.h104
-rw-r--r--drivers/net/wireless/zd1211rw/zd_def.h1
-rw-r--r--drivers/net/wireless/zd1211rw/zd_ieee80211.c10
-rw-r--r--drivers/net/wireless/zd1211rw/zd_ieee80211.h3
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c404
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.h38
-rw-r--r--drivers/net/wireless/zd1211rw/zd_netdev.c13
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.c45
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.h14
-rw-r--r--drivers/net/zorro8390.c24
-rw-r--r--drivers/parisc/ccio-dma.c2
-rw-r--r--drivers/parisc/iosapic.c6
-rw-r--r--drivers/pci/Kconfig6
-rw-r--r--drivers/pci/access.c75
-rw-r--r--drivers/pci/hotplug/acpiphp.h4
-rw-r--r--drivers/pci/hotplug/acpiphp_core.c39
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c8
-rw-r--r--drivers/pci/hotplug/ibmphp_hpc.c2
-rw-r--r--drivers/pci/hotplug/ibmphp_pci.c4
-rw-r--r--drivers/pci/hotplug/pciehp_core.c7
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c2
-rw-r--r--drivers/pci/hotplug/rpadlpar_core.c2
-rw-r--r--drivers/pci/hotplug/rpaphp_core.c2
-rw-r--r--drivers/pci/hotplug/sgi_hotplug.c35
-rw-r--r--drivers/pci/msi.h8
-rw-r--r--drivers/pci/pci-acpi.c10
-rw-r--r--drivers/pci/pci-driver.c11
-rw-r--r--drivers/pci/pci-sysfs.c33
-rw-r--r--drivers/pci/pci.c123
-rw-r--r--drivers/pci/pci.h1
-rw-r--r--drivers/pci/probe.c27
-rw-r--r--drivers/pci/quirks.c59
-rw-r--r--drivers/pci/rom.c9
-rw-r--r--drivers/pcmcia/ds.c2
-rw-r--r--drivers/rtc/interface.c16
-rw-r--r--drivers/rtc/rtc-at91.c3
-rw-r--r--drivers/rtc/rtc-dev.c25
-rw-r--r--drivers/rtc/rtc-ds1553.c3
-rw-r--r--drivers/rtc/rtc-rs5c372.c6
-rw-r--r--drivers/rtc/rtc-test.c2
-rw-r--r--drivers/s390/net/claw.h2
-rw-r--r--drivers/s390/net/lcs.c2
-rw-r--r--drivers/s390/net/lcs.h4
-rw-r--r--drivers/s390/net/qeth_eddp.c40
-rw-r--r--drivers/s390/net/qeth_eddp.h2
-rw-r--r--drivers/scsi/aic94xx/aic94xx_reg_def.h2
-rw-r--r--drivers/scsi/aic94xx/aic94xx_sds.c4
-rw-r--r--drivers/scsi/ncr53c8xx.c14
-rw-r--r--drivers/scsi/ncr53c8xx.h6
-rw-r--r--drivers/spi/Kconfig2
-rw-r--r--drivers/usb/atm/speedtch.c4
-rw-r--r--drivers/usb/atm/ueagle-atm.c10
-rw-r--r--drivers/usb/class/cdc-acm.c2
-rw-r--r--drivers/usb/core/Kconfig15
-rw-r--r--drivers/usb/core/devices.c9
-rw-r--r--drivers/usb/core/devio.c4
-rw-r--r--drivers/usb/core/driver.c304
-rw-r--r--drivers/usb/core/endpoint.c98
-rw-r--r--drivers/usb/core/hcd.c4
-rw-r--r--drivers/usb/core/hub.c234
-rw-r--r--drivers/usb/core/hub.h41
-rw-r--r--drivers/usb/core/message.c8
-rw-r--r--drivers/usb/core/usb.c160
-rw-r--r--drivers/usb/core/usb.h9
-rw-r--r--drivers/usb/gadget/ether.c4
-rw-r--r--drivers/usb/gadget/lh7a40x_udc.c1
-rw-r--r--drivers/usb/gadget/net2280.c8
-rw-r--r--drivers/usb/gadget/net2280.h3
-rw-r--r--drivers/usb/gadget/pxa2xx_udc.c2
-rw-r--r--drivers/usb/host/Kconfig2
-rw-r--r--drivers/usb/host/ehci-hcd.c16
-rw-r--r--drivers/usb/host/ehci-hub.c104
-rw-r--r--drivers/usb/host/ehci-pci.c40
-rw-r--r--drivers/usb/host/ehci.h1
-rw-r--r--drivers/usb/host/ohci-hcd.c10
-rw-r--r--drivers/usb/host/ohci-hub.c172
-rw-r--r--drivers/usb/host/u132-hcd.c14
-rw-r--r--drivers/usb/image/microtek.c8
-rw-r--r--drivers/usb/input/Kconfig6
-rw-r--r--drivers/usb/input/ati_remote.c17
-rw-r--r--drivers/usb/input/ati_remote2.c3
-rw-r--r--drivers/usb/input/hid-core.c91
-rw-r--r--drivers/usb/input/hid.h1
-rw-r--r--drivers/usb/input/usbkbd.c10
-rw-r--r--drivers/usb/input/usbmouse.c4
-rw-r--r--drivers/usb/input/usbtouchscreen.c96
-rw-r--r--drivers/usb/input/wacom.h1
-rw-r--r--drivers/usb/input/wacom_sys.c2
-rw-r--r--drivers/usb/input/yealink.c6
-rw-r--r--drivers/usb/misc/Makefile1
-rw-r--r--drivers/usb/misc/appledisplay.c5
-rw-r--r--drivers/usb/misc/auerswald.c7
-rw-r--r--drivers/usb/misc/emi26.c3
-rw-r--r--drivers/usb/misc/emi62.c3
-rw-r--r--drivers/usb/misc/ftdi-elan.c20
-rw-r--r--drivers/usb/misc/idmouse.c22
-rw-r--r--drivers/usb/misc/legousbtower.c31
-rw-r--r--drivers/usb/misc/phidgetkit.c5
-rw-r--r--drivers/usb/misc/phidgetmotorcontrol.c5
-rw-r--r--drivers/usb/misc/usb_u132.h6
-rw-r--r--drivers/usb/misc/usbtest.c4
-rw-r--r--drivers/usb/net/asix.c6
-rw-r--r--drivers/usb/net/catc.c12
-rw-r--r--drivers/usb/net/cdc_ether.c3
-rw-r--r--drivers/usb/net/net1080.c4
-rw-r--r--drivers/usb/net/pegasus.c1
-rw-r--r--drivers/usb/net/usbnet.c4
-rw-r--r--drivers/usb/serial/Kconfig11
-rw-r--r--drivers/usb/serial/Makefile1
-rw-r--r--drivers/usb/serial/aircable.c9
-rw-r--r--drivers/usb/serial/airprime.c1
-rw-r--r--drivers/usb/serial/ark3116.c3
-rw-r--r--drivers/usb/serial/console.c6
-rw-r--r--drivers/usb/serial/cypress_m8.c9
-rw-r--r--drivers/usb/serial/digi_acceleport.c2
-rw-r--r--drivers/usb/serial/ezusb.c3
-rw-r--r--drivers/usb/serial/ftdi_sio.c3
-rw-r--r--drivers/usb/serial/garmin_gps.c3
-rw-r--r--drivers/usb/serial/io_edgeport.c4
-rw-r--r--drivers/usb/serial/ipw.c3
-rw-r--r--drivers/usb/serial/keyspan.c18
-rw-r--r--drivers/usb/serial/kobil_sct.c9
-rw-r--r--drivers/usb/serial/mct_u232.c6
-rw-r--r--drivers/usb/serial/mos7840.c3
-rw-r--r--drivers/usb/serial/navman.c3
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c5
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.h1
-rw-r--r--drivers/usb/serial/usb-serial.c12
-rw-r--r--drivers/usb/serial/usb_debug.c65
-rw-r--r--drivers/usb/serial/visor.c3
-rw-r--r--drivers/usb/storage/onetouch.c5
-rw-r--r--drivers/usb/storage/unusual_devs.h10
-rw-r--r--drivers/usb/storage/usb.c8
-rw-r--r--drivers/video/fbmem.c16
-rw-r--r--drivers/video/fbsysfs.c163
-rw-r--r--fs/Kconfig4
-rw-r--r--fs/aio.c6
-rw-r--r--fs/bio.c23
-rw-r--r--fs/cifs/inode.c6
-rw-r--r--fs/cifs/link.c33
-rw-r--r--fs/debugfs/inode.c1
-rw-r--r--fs/ecryptfs/crypto.c3
-rw-r--r--fs/fuse/dir.c52
-rw-r--r--fs/jfs/jfs_filsys.h2
-rw-r--r--fs/nfs/nfsroot.c13
-rw-r--r--fs/proc/base.c3
-rw-r--r--fs/reiserfs/file.c3
-rw-r--r--fs/reiserfs/journal.c6
-rw-r--r--fs/reiserfs/xattr.c2
-rw-r--r--fs/sysfs/dir.c45
-rw-r--r--fs/sysfs/file.c3
-rw-r--r--include/acpi/acpi_bus.h2
-rw-r--r--include/asm-alpha/checksum.h34
-rw-r--r--include/asm-alpha/device.h7
-rw-r--r--include/asm-arm/arch-ebsa110/io.h16
-rw-r--r--include/asm-arm/arch-pxa/udc.h17
-rw-r--r--include/asm-arm/checksum.h83
-rw-r--r--include/asm-arm/device.h7
-rw-r--r--include/asm-arm/dma-mapping.h4
-rw-r--r--include/asm-arm/mach/udc_pxa2xx.h26
-rw-r--r--include/asm-arm26/checksum.h63
-rw-r--r--include/asm-arm26/device.h7
-rw-r--r--include/asm-avr32/checksum.h40
-rw-r--r--include/asm-avr32/device.h7
-rw-r--r--include/asm-cris/arch-v10/checksum.h10
-rw-r--r--include/asm-cris/arch-v32/checksum.h10
-rw-r--r--include/asm-cris/checksum.h34
-rw-r--r--include/asm-cris/device.h7
-rw-r--r--include/asm-frv/checksum.h41
-rw-r--r--include/asm-frv/device.h7
-rw-r--r--include/asm-generic/device.h12
-rw-r--r--include/asm-h8300/checksum.h31
-rw-r--r--include/asm-h8300/device.h7
-rw-r--r--include/asm-i386/checksum.h65
-rw-r--r--include/asm-i386/device.h15
-rw-r--r--include/asm-i386/mach-summit/mach_apic.h4
-rw-r--r--include/asm-ia64/checksum.h31
-rw-r--r--include/asm-ia64/device.h15
-rw-r--r--include/asm-ia64/io.h2
-rw-r--r--include/asm-ia64/machvec.h12
-rw-r--r--include/asm-ia64/machvec_sn2.h2
-rw-r--r--include/asm-ia64/pci.h21
-rw-r--r--include/asm-ia64/sn/acpi.h16
-rw-r--r--include/asm-ia64/sn/pcidev.h22
-rw-r--r--include/asm-ia64/sn/sn_feature_sets.h6
-rw-r--r--include/asm-ia64/sn/sn_sal.h1
-rw-r--r--include/asm-m32r/checksum.h52
-rw-r--r--include/asm-m32r/device.h7
-rw-r--r--include/asm-m68k/checksum.h46
-rw-r--r--include/asm-m68k/device.h7
-rw-r--r--include/asm-m68knommu/checksum.h46
-rw-r--r--include/asm-m68knommu/device.h7
-rw-r--r--include/asm-m68knommu/mcfmbus.h2
-rw-r--r--include/asm-mips/addrspace.h40
-rw-r--r--include/asm-mips/atomic.h10
-rw-r--r--include/asm-mips/bitops.h65
-rw-r--r--include/asm-mips/bug.h12
-rw-r--r--include/asm-mips/checksum.h55
-rw-r--r--include/asm-mips/cpu-info.h10
-rw-r--r--include/asm-mips/dec/kn02.h2
-rw-r--r--include/asm-mips/device.h7
-rw-r--r--include/asm-mips/dma.h2
-rw-r--r--include/asm-mips/gt64120.h14
-rw-r--r--include/asm-mips/io.h2
-rw-r--r--include/asm-mips/irq.h8
-rw-r--r--include/asm-mips/kexec.h32
-rw-r--r--include/asm-mips/mach-au1x00/au1xxx_ide.h6
-rw-r--r--include/asm-mips/mach-cobalt/cobalt.h29
-rw-r--r--include/asm-mips/mach-cobalt/mach-gt64120.h28
-rw-r--r--include/asm-mips/mipsregs.h56
-rw-r--r--include/asm-mips/page.h16
-rw-r--r--include/asm-mips/pgtable-64.h13
-rw-r--r--include/asm-mips/pgtable.h2
-rw-r--r--include/asm-mips/ptrace.h2
-rw-r--r--include/asm-mips/time.h9
-rw-r--r--include/asm-parisc/checksum.h55
-rw-r--r--include/asm-parisc/device.h7
-rw-r--r--include/asm-parisc/dma.h6
-rw-r--r--include/asm-parisc/pci.h2
-rw-r--r--include/asm-parisc/ropes.h2
-rw-r--r--include/asm-parisc/semaphore.h6
-rw-r--r--include/asm-powerpc/checksum.h59
-rw-r--r--include/asm-powerpc/device.h7
-rw-r--r--include/asm-powerpc/pci.h20
-rw-r--r--include/asm-ppc/device.h7
-rw-r--r--include/asm-s390/checksum.h45
-rw-r--r--include/asm-s390/device.h7
-rw-r--r--include/asm-sh/checksum.h59
-rw-r--r--include/asm-sh/device.h7
-rw-r--r--include/asm-sh64/checksum.h41
-rw-r--r--include/asm-sh64/device.h7
-rw-r--r--include/asm-sparc/checksum.h103
-rw-r--r--include/asm-sparc/device.h7
-rw-r--r--include/asm-sparc64/checksum.h77
-rw-r--r--include/asm-sparc64/device.h7
-rw-r--r--include/asm-sparc64/pci.h6
-rw-r--r--include/asm-um/device.h7
-rw-r--r--include/asm-v850/checksum.h38
-rw-r--r--include/asm-v850/device.h7
-rw-r--r--include/asm-x86_64/checksum.h54
-rw-r--r--include/asm-x86_64/device.h15
-rw-r--r--include/asm-xtensa/checksum.h64
-rw-r--r--include/asm-xtensa/device.h7
-rw-r--r--include/linux/Kbuild5
-rw-r--r--include/linux/atmarp.h2
-rw-r--r--include/linux/atmbr2684.h4
-rw-r--r--include/linux/atmmpc.h16
-rw-r--r--include/linux/blkdev.h7
-rw-r--r--include/linux/blktrace_api.h12
-rw-r--r--include/linux/dccp.h63
-rw-r--r--include/linux/device.h35
-rw-r--r--include/linux/divert.h132
-rw-r--r--include/linux/elevator.h4
-rw-r--r--include/linux/fb.h8
-rw-r--r--include/linux/fib_rules.h3
-rw-r--r--include/linux/ftape-header-segment.h122
-rw-r--r--include/linux/ftape-vendors.h137
-rw-r--r--include/linux/ftape.h201
-rw-r--r--include/linux/icmp.h2
-rw-r--r--include/linux/icmpv6.h12
-rw-r--r--include/linux/if_packet.h6
-rw-r--r--include/linux/if_tunnel.h8
-rw-r--r--include/linux/igmp.h2
-rw-r--r--include/linux/in.h1
-rw-r--r--include/linux/in6.h4
-rw-r--r--include/linux/inet.h4
-rw-r--r--include/linux/inetdevice.h14
-rw-r--r--include/linux/ioport.h1
-rw-r--r--include/linux/ip.h2
-rw-r--r--include/linux/ip6_tunnel.h2
-rw-r--r--include/linux/ipv6.h2
-rw-r--r--include/linux/ixjuser.h2
-rw-r--r--include/linux/jiffies.h2
-rw-r--r--include/linux/kernel.h6
-rw-r--r--include/linux/kexec.h2
-rw-r--r--include/linux/kobject.h8
-rw-r--r--include/linux/miscdevice.h5
-rw-r--r--include/linux/mmc/card.h13
-rw-r--r--include/linux/mmc/host.h8
-rw-r--r--include/linux/mmc/protocol.h74
-rw-r--r--include/linux/module.h1
-rw-r--r--include/linux/mqueue.h2
-rw-r--r--include/linux/mv643xx.h4
-rw-r--r--include/linux/net.h2
-rw-r--r--include/linux/netdevice.h18
-rw-r--r--include/linux/netfilter.h44
-rw-r--r--include/linux/netfilter/Kbuild2
-rw-r--r--include/linux/netfilter/nf_conntrack_amanda.h10
-rw-r--r--include/linux/netfilter/nf_conntrack_ftp.h20
-rw-r--r--include/linux/netfilter/nf_conntrack_h323.h92
-rw-r--r--include/linux/netfilter/nf_conntrack_h323_asn1.h (renamed from include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h)10
-rw-r--r--include/linux/netfilter/nf_conntrack_h323_types.h (renamed from include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h)12
-rw-r--r--include/linux/netfilter/nf_conntrack_irc.h15
-rw-r--r--include/linux/netfilter/nf_conntrack_pptp.h321
-rw-r--r--include/linux/netfilter/nf_conntrack_proto_gre.h112
-rw-r--r--include/linux/netfilter/nf_conntrack_sctp.h2
-rw-r--r--include/linux/netfilter/nf_conntrack_sip.h41
-rw-r--r--include/linux/netfilter/nf_conntrack_tftp.h20
-rw-r--r--include/linux/netfilter/nfnetlink.h2
-rw-r--r--include/linux/netfilter/nfnetlink_log.h12
-rw-r--r--include/linux/netfilter/nfnetlink_queue.h19
-rw-r--r--include/linux/netfilter/xt_NFLOG.h18
-rw-r--r--include/linux/netfilter/xt_conntrack.h4
-rw-r--r--include/linux/netfilter/xt_hashlimit.h40
-rw-r--r--include/linux/netfilter/xt_policy.h2
-rw-r--r--include/linux/netfilter_bridge.h2
-rw-r--r--include/linux/netfilter_bridge/ebt_802_3.h10
-rw-r--r--include/linux/netfilter_bridge/ebt_among.h2
-rw-r--r--include/linux/netfilter_bridge/ebt_arp.h14
-rw-r--r--include/linux/netfilter_bridge/ebt_ip.h8
-rw-r--r--include/linux/netfilter_bridge/ebt_nat.h1
-rw-r--r--include/linux/netfilter_bridge/ebt_vlan.h2
-rw-r--r--include/linux/netfilter_bridge/ebtables.h25
-rw-r--r--include/linux/netfilter_ipv4.h2
-rw-r--r--include/linux/netfilter_ipv4/Kbuild2
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack.h2
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_ftp.h40
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_h323.h2
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h4
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_sip.h34
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_tftp.h2
-rw-r--r--include/linux/netfilter_ipv4/ipt_LOG.h2
-rw-r--r--include/linux/netfilter_ipv4/ipt_hashlimit.h42
-rw-r--r--include/linux/netfilter_ipv6.h2
-rw-r--r--include/linux/netfilter_ipv6/ip6t_LOG.h2
-rw-r--r--include/linux/netlink.h2
-rw-r--r--include/linux/netpoll.h15
-rw-r--r--include/linux/nfs_fs.h2
-rw-r--r--include/linux/nsproxy.h4
-rw-r--r--include/linux/pci.h3
-rw-r--r--include/linux/pci_ids.h12
-rw-r--r--include/linux/pci_regs.h6
-rw-r--r--include/linux/pfkeyv2.h4
-rw-r--r--include/linux/phy.h30
-rw-r--r--include/linux/platform_device.h6
-rw-r--r--include/linux/random.h20
-rw-r--r--include/linux/reiserfs_fs_sb.h2
-rw-r--r--include/linux/rtnetlink.h5
-rw-r--r--include/linux/sctp.h72
-rw-r--r--include/linux/security.h56
-rw-r--r--include/linux/skbuff.h26
-rw-r--r--include/linux/socket.h3
-rw-r--r--include/linux/sockios.h4
-rw-r--r--include/linux/spinlock.h14
-rw-r--r--include/linux/spinlock_api_smp.h2
-rw-r--r--include/linux/sunrpc/xdr.h2
-rw-r--r--include/linux/sysctl.h12
-rw-r--r--include/linux/sysfs.h8
-rw-r--r--include/linux/tcp.h190
-rw-r--r--include/linux/textsearch.h4
-rw-r--r--include/linux/tfrc.h20
-rw-r--r--include/linux/tipc_config.h32
-rw-r--r--include/linux/tty.h5
-rw-r--r--include/linux/types.h4
-rw-r--r--include/linux/udp.h14
-rw-r--r--include/linux/usb.h181
-rw-r--r--include/linux/wireless.h2
-rw-r--r--include/linux/xfrm.h6
-rw-r--r--include/linux/zftape.h87
-rw-r--r--include/net/addrconf.h8
-rw-r--r--include/net/arp.h2
-rw-r--r--include/net/atmclip.h2
-rw-r--r--include/net/bluetooth/rfcomm.h4
-rw-r--r--include/net/checksum.h43
-rw-r--r--include/net/cipso_ipv4.h4
-rw-r--r--include/net/dsfield.h10
-rw-r--r--include/net/fib_rules.h10
-rw-r--r--include/net/flow.h9
-rw-r--r--include/net/genetlink.h54
-rw-r--r--include/net/ieee80211.h6
-rw-r--r--include/net/if_inet6.h1
-rw-r--r--include/net/inet6_connection_sock.h4
-rw-r--r--include/net/inet6_hashtables.h16
-rw-r--r--include/net/inet_connection_sock.h7
-rw-r--r--include/net/inet_ecn.h10
-rw-r--r--include/net/ip.h21
-rw-r--r--include/net/ip6_checksum.h76
-rw-r--r--include/net/ip6_fib.h5
-rw-r--r--include/net/ip6_route.h2
-rw-r--r--include/net/ip_fib.h2
-rw-r--r--include/net/ip_mp_alg.h4
-rw-r--r--include/net/ip_vs.h16
-rw-r--r--include/net/ipconfig.h8
-rw-r--r--include/net/ipip.h6
-rw-r--r--include/net/ipv6.h62
-rw-r--r--include/net/irda/irlap_frame.h16
-rw-r--r--include/net/llc_pdu.h10
-rw-r--r--include/net/ndisc.h4
-rw-r--r--include/net/netfilter/ipv4/nf_conntrack_ipv4.h29
-rw-r--r--include/net/netfilter/ipv6/nf_conntrack_ipv6.h25
-rw-r--r--include/net/netfilter/nf_conntrack.h171
-rw-r--r--include/net/netfilter/nf_conntrack_core.h16
-rw-r--r--include/net/netfilter/nf_conntrack_ecache.h95
-rw-r--r--include/net/netfilter/nf_conntrack_expect.h80
-rw-r--r--include/net/netfilter/nf_conntrack_helper.h22
-rw-r--r--include/net/netfilter/nf_conntrack_l3proto.h15
-rw-r--r--include/net/netfilter/nf_conntrack_l4proto.h (renamed from include/net/netfilter/nf_conntrack_protocol.h)49
-rw-r--r--include/net/netfilter/nf_conntrack_tuple.h34
-rw-r--r--include/net/netfilter/nf_nat.h77
-rw-r--r--include/net/netfilter/nf_nat_core.h27
-rw-r--r--include/net/netfilter/nf_nat_helper.h32
-rw-r--r--include/net/netfilter/nf_nat_protocol.h70
-rw-r--r--include/net/netfilter/nf_nat_rule.h35
-rw-r--r--include/net/netlabel.h123
-rw-r--r--include/net/netlink.h21
-rw-r--r--include/net/protocol.h4
-rw-r--r--include/net/rawv6.h2
-rw-r--r--include/net/request_sock.h12
-rw-r--r--include/net/sch_generic.h6
-rw-r--r--include/net/sctp/command.h4
-rw-r--r--include/net/sctp/constants.h2
-rw-r--r--include/net/sctp/sctp.h2
-rw-r--r--include/net/sctp/sm.h6
-rw-r--r--include/net/sctp/structs.h21
-rw-r--r--include/net/sctp/tsnmap.h4
-rw-r--r--include/net/sock.h28
-rw-r--r--include/net/tcp.h159
-rw-r--r--include/net/timewait_sock.h3
-rw-r--r--include/net/tipc/tipc_bearer.h2
-rw-r--r--include/net/tipc/tipc_msg.h2
-rw-r--r--include/net/transp_v6.h2
-rw-r--r--include/net/udp.h96
-rw-r--r--include/net/udplite.h151
-rw-r--r--include/net/xfrm.h66
-rw-r--r--include/rdma/ib_cm.h16
-rw-r--r--include/rdma/ib_user_cm.h7
-rw-r--r--include/scsi/libsas.h1
-rw-r--r--include/sound/core.h8
-rw-r--r--include/sound/version.h2
-rw-r--r--init/Kconfig20
-rw-r--r--kernel/fork.c5
-rw-r--r--kernel/irq/handle.c4
-rw-r--r--kernel/irq/spurious.c6
-rw-r--r--kernel/kmod.c8
-rw-r--r--kernel/module.c31
-rw-r--r--kernel/spinlock.c21
-rw-r--r--kernel/taskstats.c11
-rw-r--r--kernel/unwind.c9
-rw-r--r--lib/kobject.c50
-rw-r--r--lib/kobject_uevent.c28
-rw-r--r--lib/textsearch.c2
-rw-r--r--mm/page_alloc.c6
-rw-r--r--net/802/hippi.c1
-rw-r--r--net/Kconfig29
-rw-r--r--net/atm/Makefile3
-rw-r--r--net/atm/br2684.c30
-rw-r--r--net/atm/clip.c39
-rw-r--r--net/atm/ipcommon.c63
-rw-r--r--net/atm/ipcommon.h22
-rw-r--r--net/atm/lec.c16
-rw-r--r--net/atm/lec.h6
-rw-r--r--net/atm/mpc.c29
-rw-r--r--net/atm/mpc.h6
-rw-r--r--net/atm/mpoa_caches.c20
-rw-r--r--net/atm/mpoa_caches.h16
-rw-r--r--net/atm/mpoa_proc.c6
-rw-r--r--net/ax25/af_ax25.c6
-rw-r--r--net/ax25/ax25_out.c4
-rw-r--r--net/ax25/ax25_route.c5
-rw-r--r--net/ax25/sysctl_net_ax25.c5
-rw-r--r--net/bluetooth/bnep/bnep.h4
-rw-r--r--net/bluetooth/bnep/core.c28
-rw-r--r--net/bluetooth/bnep/netdev.c11
-rw-r--r--net/bluetooth/l2cap.c4
-rw-r--r--net/bluetooth/rfcomm/core.c18
-rw-r--r--net/bridge/br_ioctl.c9
-rw-r--r--net/bridge/br_netfilter.c3
-rw-r--r--net/bridge/br_netlink.c113
-rw-r--r--net/bridge/netfilter/ebt_802_3.c2
-rw-r--r--net/bridge/netfilter/ebt_among.c22
-rw-r--r--net/bridge/netfilter/ebt_arp.c6
-rw-r--r--net/bridge/netfilter/ebt_ip.c4
-rw-r--r--net/bridge/netfilter/ebt_log.c6
-rw-r--r--net/bridge/netfilter/ebt_mark.c14
-rw-r--r--net/bridge/netfilter/ebt_mark_m.c4
-rw-r--r--net/bridge/netfilter/ebt_snat.c27
-rw-r--r--net/bridge/netfilter/ebt_ulog.c2
-rw-r--r--net/bridge/netfilter/ebt_vlan.c2
-rw-r--r--net/bridge/netfilter/ebtable_broute.c2
-rw-r--r--net/bridge/netfilter/ebtable_filter.c2
-rw-r--r--net/bridge/netfilter/ebtable_nat.c2
-rw-r--r--net/bridge/netfilter/ebtables.c222
-rw-r--r--net/core/Makefile1
-rw-r--r--net/core/datagram.c16
-rw-r--r--net/core/dev.c39
-rw-r--r--net/core/dv.c546
-rw-r--r--net/core/fib_rules.c71
-rw-r--r--net/core/filter.c6
-rw-r--r--net/core/iovec.c4
-rw-r--r--net/core/neighbour.c24
-rw-r--r--net/core/netpoll.c327
-rw-r--r--net/core/pktgen.c68
-rw-r--r--net/core/request_sock.c35
-rw-r--r--net/core/rtnetlink.c60
-rw-r--r--net/core/skbuff.c26
-rw-r--r--net/core/sock.c13
-rw-r--r--net/core/sysctl_net_core.c14
-rw-r--r--net/core/utils.c10
-rw-r--r--net/dccp/Kconfig5
-rw-r--r--net/dccp/Makefile8
-rw-r--r--net/dccp/ackvec.c116
-rw-r--r--net/dccp/ackvec.h20
-rw-r--r--net/dccp/ccid.h12
-rw-r--r--net/dccp/ccids/Kconfig25
-rw-r--r--net/dccp/ccids/ccid2.c45
-rw-r--r--net/dccp/ccids/ccid2.h3
-rw-r--r--net/dccp/ccids/ccid3.c549
-rw-r--r--net/dccp/ccids/ccid3.h119
-rw-r--r--net/dccp/ccids/lib/loss_interval.c6
-rw-r--r--net/dccp/ccids/lib/tfrc_equation.c7
-rw-r--r--net/dccp/dccp.h110
-rw-r--r--net/dccp/feat.c131
-rw-r--r--net/dccp/feat.h48
-rw-r--r--net/dccp/input.c63
-rw-r--r--net/dccp/ipv4.c537
-rw-r--r--net/dccp/ipv6.c613
-rw-r--r--net/dccp/minisocks.c48
-rw-r--r--net/dccp/options.c61
-rw-r--r--net/dccp/output.c84
-rw-r--r--net/dccp/probe.c8
-rw-r--r--net/dccp/proto.c64
-rw-r--r--net/dccp/sysctl.c60
-rw-r--r--net/dccp/timer.c134
-rw-r--r--net/decnet/Kconfig8
-rw-r--r--net/decnet/dn_dev.c173
-rw-r--r--net/decnet/dn_neigh.c1
-rw-r--r--net/decnet/dn_nsp_in.c2
-rw-r--r--net/decnet/dn_route.c46
-rw-r--r--net/decnet/dn_rules.c43
-rw-r--r--net/decnet/dn_table.c42
-rw-r--r--net/ethernet/eth.c1
-rw-r--r--net/ieee80211/ieee80211_module.c25
-rw-r--r--net/ieee80211/ieee80211_rx.c68
-rw-r--r--net/ieee80211/ieee80211_tx.c4
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_auth.c24
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_scan.c7
-rw-r--r--net/ipv4/Kconfig19
-rw-r--r--net/ipv4/Makefile3
-rw-r--r--net/ipv4/af_inet.c16
-rw-r--r--net/ipv4/ah4.c4
-rw-r--r--net/ipv4/arp.c2
-rw-r--r--net/ipv4/cipso_ipv4.c813
-rw-r--r--net/ipv4/devinet.c32
-rw-r--r--net/ipv4/esp4.c4
-rw-r--r--net/ipv4/fib_frontend.c5
-rw-r--r--net/ipv4/fib_rules.c53
-rw-r--r--net/ipv4/fib_semantics.c36
-rw-r--r--net/ipv4/icmp.c6
-rw-r--r--net/ipv4/igmp.c2
-rw-r--r--net/ipv4/inet_connection_sock.c2
-rw-r--r--net/ipv4/ip_gre.c56
-rw-r--r--net/ipv4/ip_output.c19
-rw-r--r--net/ipv4/ip_sockglue.c2
-rw-r--r--net/ipv4/ipconfig.c105
-rw-r--r--net/ipv4/ipip.c16
-rw-r--r--net/ipv4/ipmr.c2
-rw-r--r--net/ipv4/ipvs/ip_vs_app.c3
-rw-r--r--net/ipv4/ipvs/ip_vs_core.c4
-rw-r--r--net/ipv4/ipvs/ip_vs_proto.c8
-rw-r--r--net/ipv4/ipvs/ip_vs_proto_tcp.c16
-rw-r--r--net/ipv4/ipvs/ip_vs_proto_udp.c22
-rw-r--r--net/ipv4/netfilter.c10
-rw-r--r--net/ipv4/netfilter/Kconfig138
-rw-r--r--net/ipv4/netfilter/Makefile30
-rw-r--r--net/ipv4/netfilter/ip_conntrack_amanda.c11
-rw-r--r--net/ipv4/netfilter/ip_conntrack_core.c14
-rw-r--r--net/ipv4/netfilter/ip_conntrack_ftp.c8
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_h323.c172
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_pptp.c33
-rw-r--r--net/ipv4/netfilter/ip_conntrack_irc.c12
-rw-r--r--net/ipv4/netfilter/ip_conntrack_netlink.c66
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_gre.c2
-rw-r--r--net/ipv4/netfilter/ip_conntrack_sip.c118
-rw-r--r--net/ipv4/netfilter/ip_conntrack_standalone.c6
-rw-r--r--net/ipv4/netfilter/ip_conntrack_tftp.c6
-rw-r--r--net/ipv4/netfilter/ip_nat_amanda.c9
-rw-r--r--net/ipv4/netfilter/ip_nat_core.c6
-rw-r--r--net/ipv4/netfilter/ip_nat_ftp.c9
-rw-r--r--net/ipv4/netfilter/ip_nat_helper.c32
-rw-r--r--net/ipv4/netfilter/ip_nat_helper_h323.c58
-rw-r--r--net/ipv4/netfilter/ip_nat_helper_pptp.c29
-rw-r--r--net/ipv4/netfilter/ip_nat_irc.c9
-rw-r--r--net/ipv4/netfilter/ip_nat_proto_gre.c8
-rw-r--r--net/ipv4/netfilter/ip_nat_proto_icmp.c10
-rw-r--r--net/ipv4/netfilter/ip_nat_proto_tcp.c5
-rw-r--r--net/ipv4/netfilter/ip_nat_proto_udp.c9
-rw-r--r--net/ipv4/netfilter/ip_nat_sip.c199
-rw-r--r--net/ipv4/netfilter/ip_nat_snmp_basic.c85
-rw-r--r--net/ipv4/netfilter/ip_nat_standalone.c6
-rw-r--r--net/ipv4/netfilter/ip_nat_tftp.c9
-rw-r--r--net/ipv4/netfilter/ip_queue.c2
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c25
-rw-r--r--net/ipv4/netfilter/ipt_ECN.c11
-rw-r--r--net/ipv4/netfilter/ipt_LOG.c20
-rw-r--r--net/ipv4/netfilter/ipt_MASQUERADE.c29
-rw-r--r--net/ipv4/netfilter/ipt_NETMAP.c4
-rw-r--r--net/ipv4/netfilter/ipt_REDIRECT.c6
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c18
-rw-r--r--net/ipv4/netfilter/ipt_SAME.c12
-rw-r--r--net/ipv4/netfilter/ipt_TCPMSS.c24
-rw-r--r--net/ipv4/netfilter/ipt_TOS.c5
-rw-r--r--net/ipv4/netfilter/ipt_TTL.c5
-rw-r--r--net/ipv4/netfilter/ipt_ULOG.c2
-rw-r--r--net/ipv4/netfilter/iptable_mangle.c8
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c137
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c412
-rw-r--r--net/ipv4/netfilter/nf_conntrack_proto_icmp.c57
-rw-r--r--net/ipv4/netfilter/nf_nat_amanda.c78
-rw-r--r--net/ipv4/netfilter/nf_nat_core.c647
-rw-r--r--net/ipv4/netfilter/nf_nat_ftp.c179
-rw-r--r--net/ipv4/netfilter/nf_nat_h323.c596
-rw-r--r--net/ipv4/netfilter/nf_nat_helper.c433
-rw-r--r--net/ipv4/netfilter/nf_nat_irc.c101
-rw-r--r--net/ipv4/netfilter/nf_nat_pptp.c315
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_gre.c179
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_icmp.c86
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_tcp.c148
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_udp.c138
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_unknown.c54
-rw-r--r--net/ipv4/netfilter/nf_nat_rule.c343
-rw-r--r--net/ipv4/netfilter/nf_nat_sip.c283
-rw-r--r--net/ipv4/netfilter/nf_nat_snmp_basic.c1332
-rw-r--r--net/ipv4/netfilter/nf_nat_standalone.c406
-rw-r--r--net/ipv4/netfilter/nf_nat_tftp.c52
-rw-r--r--net/ipv4/proc.c13
-rw-r--r--net/ipv4/raw.c4
-rw-r--r--net/ipv4/route.c66
-rw-r--r--net/ipv4/syncookies.c18
-rw-r--r--net/ipv4/sysctl_net_ipv4.c76
-rw-r--r--net/ipv4/tcp.c156
-rw-r--r--net/ipv4/tcp_cong.c91
-rw-r--r--net/ipv4/tcp_htcp.c4
-rw-r--r--net/ipv4/tcp_input.c14
-rw-r--r--net/ipv4/tcp_ipv4.c713
-rw-r--r--net/ipv4/tcp_minisocks.c69
-rw-r--r--net/ipv4/tcp_output.c122
-rw-r--r--net/ipv4/tcp_probe.c2
-rw-r--r--net/ipv4/tcp_timer.c2
-rw-r--r--net/ipv4/tcp_vegas.c4
-rw-r--r--net/ipv4/udp.c558
-rw-r--r--net/ipv4/udp_impl.h38
-rw-r--r--net/ipv4/udplite.c119
-rw-r--r--net/ipv4/xfrm4_policy.c7
-rw-r--r--net/ipv6/Kconfig7
-rw-r--r--net/ipv6/Makefile4
-rw-r--r--net/ipv6/addrconf.c190
-rw-r--r--net/ipv6/af_inet6.c27
-rw-r--r--net/ipv6/ah6.c5
-rw-r--r--net/ipv6/datagram.c16
-rw-r--r--net/ipv6/esp6.c2
-rw-r--r--net/ipv6/exthdrs.c59
-rw-r--r--net/ipv6/exthdrs_core.c2
-rw-r--r--net/ipv6/fib6_rules.c60
-rw-r--r--net/ipv6/icmp.c23
-rw-r--r--net/ipv6/inet6_connection_sock.c17
-rw-r--r--net/ipv6/inet6_hashtables.c6
-rw-r--r--net/ipv6/ip6_fib.c8
-rw-r--r--net/ipv6/ip6_flowlabel.c8
-rw-r--r--net/ipv6/ip6_input.c42
-rw-r--r--net/ipv6/ip6_output.c84
-rw-r--r--net/ipv6/ip6_tunnel.c296
-rw-r--r--net/ipv6/ipcomp6.c2
-rw-r--r--net/ipv6/ipv6_sockglue.c11
-rw-r--r--net/ipv6/mcast.c36
-rw-r--r--net/ipv6/mip6.c4
-rw-r--r--net/ipv6/ndisc.c29
-rw-r--r--net/ipv6/netfilter.c11
-rw-r--r--net/ipv6/netfilter/Kconfig2
-rw-r--r--net/ipv6/netfilter/ip6_queue.c4
-rw-r--r--net/ipv6/netfilter/ip6_tables.c3
-rw-r--r--net/ipv6/netfilter/ip6t_LOG.c23
-rw-r--r--net/ipv6/netfilter/ip6table_mangle.c9
-rw-r--r--net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c93
-rw-r--r--net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c40
-rw-r--r--net/ipv6/netfilter/nf_conntrack_reasm.c26
-rw-r--r--net/ipv6/proc.c18
-rw-r--r--net/ipv6/raw.c25
-rw-r--r--net/ipv6/reassembly.c87
-rw-r--r--net/ipv6/route.c97
-rw-r--r--net/ipv6/sit.c22
-rw-r--r--net/ipv6/tcp_ipv6.c607
-rw-r--r--net/ipv6/tunnel6.c2
-rw-r--r--net/ipv6/udp.c426
-rw-r--r--net/ipv6/udp_impl.h34
-rw-r--r--net/ipv6/udplite.c105
-rw-r--r--net/ipv6/xfrm6_policy.c3
-rw-r--r--net/ipv6/xfrm6_tunnel.c8
-rw-r--r--net/irda/iriap.c11
-rw-r--r--net/irda/irias_object.c4
-rw-r--r--net/irda/irlan/irlan_common.c2
-rw-r--r--net/irda/irlmp.c4
-rw-r--r--net/irda/irqueue.c3
-rw-r--r--net/irda/irttp.c4
-rw-r--r--net/key/af_key.c42
-rw-r--r--net/llc/af_llc.c2
-rw-r--r--net/llc/llc_input.c4
-rw-r--r--net/netfilter/Kconfig193
-rw-r--r--net/netfilter/Makefile17
-rw-r--r--net/netfilter/core.c31
-rw-r--r--net/netfilter/nf_conntrack_amanda.c238
-rw-r--r--net/netfilter/nf_conntrack_core.c699
-rw-r--r--net/netfilter/nf_conntrack_ecache.c93
-rw-r--r--net/netfilter/nf_conntrack_expect.c442
-rw-r--r--net/netfilter/nf_conntrack_ftp.c42
-rw-r--r--net/netfilter/nf_conntrack_h323_asn1.c (renamed from net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c)4
-rw-r--r--net/netfilter/nf_conntrack_h323_main.c1856
-rw-r--r--net/netfilter/nf_conntrack_h323_types.c (renamed from net/ipv4/netfilter/ip_conntrack_helper_h323_types.c)7
-rw-r--r--net/netfilter/nf_conntrack_helper.c155
-rw-r--r--net/netfilter/nf_conntrack_irc.c281
-rw-r--r--net/netfilter/nf_conntrack_l3proto_generic.c7
-rw-r--r--net/netfilter/nf_conntrack_netbios_ns.c126
-rw-r--r--net/netfilter/nf_conntrack_netlink.c214
-rw-r--r--net/netfilter/nf_conntrack_pptp.c607
-rw-r--r--net/netfilter/nf_conntrack_proto.c410
-rw-r--r--net/netfilter/nf_conntrack_proto_generic.c47
-rw-r--r--net/netfilter/nf_conntrack_proto_gre.c305
-rw-r--r--net/netfilter/nf_conntrack_proto_sctp.c182
-rw-r--r--net/netfilter/nf_conntrack_proto_tcp.c275
-rw-r--r--net/netfilter/nf_conntrack_proto_udp.c83
-rw-r--r--net/netfilter/nf_conntrack_sip.c531
-rw-r--r--net/netfilter/nf_conntrack_standalone.c444
-rw-r--r--net/netfilter/nf_conntrack_tftp.c160
-rw-r--r--net/netfilter/nf_sysctl.c134
-rw-r--r--net/netfilter/nfnetlink_log.c45
-rw-r--r--net/netfilter/nfnetlink_queue.c23
-rw-r--r--net/netfilter/xt_CONNMARK.c13
-rw-r--r--net/netfilter/xt_MARK.c12
-rw-r--r--net/netfilter/xt_NFLOG.c86
-rw-r--r--net/netfilter/xt_hashlimit.c (renamed from net/ipv4/netfilter/ipt_hashlimit.c)511
-rw-r--r--net/netfilter/xt_mark.c2
-rw-r--r--net/netfilter/xt_multiport.c9
-rw-r--r--net/netfilter/xt_sctp.c2
-rw-r--r--net/netfilter/xt_tcpudp.c20
-rw-r--r--net/netlabel/netlabel_cipso_v4.c47
-rw-r--r--net/netlabel/netlabel_domainhash.c48
-rw-r--r--net/netlabel/netlabel_kapi.c212
-rw-r--r--net/netlabel/netlabel_mgmt.c42
-rw-r--r--net/netlabel/netlabel_unlabeled.c48
-rw-r--r--net/netlabel/netlabel_user.c7
-rw-r--r--net/netlabel/netlabel_user.h31
-rw-r--r--net/netlink/af_netlink.c14
-rw-r--r--net/netlink/genetlink.c70
-rw-r--r--net/netrom/nr_route.c12
-rw-r--r--net/packet/af_packet.c18
-rw-r--r--net/rose/rose_route.c4
-rw-r--r--net/rxrpc/transport.c1
-rw-r--r--net/sched/Kconfig6
-rw-r--r--net/sched/Makefile3
-rw-r--r--net/sched/act_gact.c4
-rw-r--r--net/sched/act_ipt.c6
-rw-r--r--net/sched/act_police.c26
-rw-r--r--net/sched/act_simple.c3
-rw-r--r--net/sched/cls_api.c3
-rw-r--r--net/sched/cls_fw.c6
-rw-r--r--net/sched/cls_rsvp.h16
-rw-r--r--net/sched/cls_u32.c2
-rw-r--r--net/sched/em_meta.c13
-rw-r--r--net/sched/em_nbyte.c4
-rw-r--r--net/sched/ematch.c3
-rw-r--r--net/sched/sch_api.c41
-rw-r--r--net/sched/sch_atm.c5
-rw-r--r--net/sched/sch_cbq.c10
-rw-r--r--net/sched/sch_dsmark.c9
-rw-r--r--net/sched/sch_generic.c10
-rw-r--r--net/sched/sch_hfsc.c27
-rw-r--r--net/sched/sch_htb.c36
-rw-r--r--net/sched/sch_netem.c10
-rw-r--r--net/sched/sch_prio.c14
-rw-r--r--net/sched/sch_red.c14
-rw-r--r--net/sched/sch_sfq.c3
-rw-r--r--net/sched/sch_tbf.c16
-rw-r--r--net/sctp/associola.c22
-rw-r--r--net/sctp/bind_addr.c4
-rw-r--r--net/sctp/endpointola.c11
-rw-r--r--net/sctp/input.c6
-rw-r--r--net/sctp/ipv6.c24
-rw-r--r--net/sctp/outqueue.c4
-rw-r--r--net/sctp/proc.c6
-rw-r--r--net/sctp/protocol.c24
-rw-r--r--net/sctp/sm_make_chunk.c65
-rw-r--r--net/sctp/sm_sideeffect.c8
-rw-r--r--net/sctp/sm_statefuns.c55
-rw-r--r--net/sctp/sm_statetable.c696
-rw-r--r--net/sctp/socket.c77
-rw-r--r--net/sctp/tsnmap.c9
-rw-r--r--net/sctp/ulpevent.c2
-rw-r--r--net/socket.c6
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c3
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_mech.c3
-rw-r--r--net/sunrpc/auth_gss/gss_spkm3_mech.c3
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c7
-rw-r--r--net/sunrpc/clnt.c3
-rw-r--r--net/sunrpc/socklib.c7
-rw-r--r--net/sunrpc/svcauth_unix.c8
-rw-r--r--net/tipc/bcast.c6
-rw-r--r--net/tipc/config.c32
-rw-r--r--net/tipc/dbg.c3
-rw-r--r--net/tipc/name_distr.c10
-rw-r--r--net/tipc/node.c12
-rw-r--r--net/tipc/subscr.c3
-rw-r--r--net/unix/af_unix.c3
-rw-r--r--net/wanrouter/af_wanpipe.c4
-rw-r--r--net/wanrouter/wanmain.c2
-rw-r--r--net/xfrm/xfrm_policy.c38
-rw-r--r--net/xfrm/xfrm_state.c2
-rw-r--r--net/xfrm/xfrm_user.c58
-rw-r--r--scripts/gen_initramfs_list.sh3
-rw-r--r--scripts/kconfig/lxdialog/util.c16
-rw-r--r--scripts/kconfig/qconf.cc1
-rw-r--r--security/dummy.c17
-rw-r--r--security/selinux/avc.c23
-rw-r--r--security/selinux/hooks.c155
-rw-r--r--security/selinux/include/av_inherit.h1
-rw-r--r--security/selinux/include/av_perm_to_string.h8
-rw-r--r--security/selinux/include/av_permissions.h32
-rw-r--r--security/selinux/include/avc_ss.h24
-rw-r--r--security/selinux/include/class_to_string.h2
-rw-r--r--security/selinux/include/flask.h2
-rw-r--r--security/selinux/include/objsec.h2
-rw-r--r--security/selinux/include/security.h4
-rw-r--r--security/selinux/include/selinux_netlabel.h43
-rw-r--r--security/selinux/include/xfrm.h28
-rw-r--r--security/selinux/nlmsgtab.c1
-rw-r--r--security/selinux/ss/ebitmap.c198
-rw-r--r--security/selinux/ss/ebitmap.h26
-rw-r--r--security/selinux/ss/hashtab.c6
-rw-r--r--security/selinux/ss/hashtab.h10
-rw-r--r--security/selinux/ss/mls.c156
-rw-r--r--security/selinux/ss/mls.h46
-rw-r--r--security/selinux/ss/policydb.c6
-rw-r--r--security/selinux/ss/services.c437
-rw-r--r--security/selinux/ss/symtab.c8
-rw-r--r--security/selinux/xfrm.c207
-rw-r--r--sound/Kconfig4
-rw-r--r--sound/aoa/codecs/snd-aoa-codec-tas.c13
-rw-r--r--sound/core/init.c8
-rw-r--r--sound/core/oss/pcm_oss.c3
-rw-r--r--sound/core/pcm.c7
-rw-r--r--sound/core/pcm_native.c6
-rw-r--r--sound/core/rtctimer.c20
-rw-r--r--sound/core/sound.c22
-rw-r--r--sound/oss/cs46xx.c6
-rw-r--r--sound/oss/soundcard.c16
-rw-r--r--sound/pci/emu10k1/emu10k1_main.c1
-rw-r--r--sound/pci/hda/patch_realtek.c2
-rw-r--r--sound/pci/hda/patch_sigmatel.c14
-rw-r--r--sound/sound_core.c6
-rw-r--r--sound/usb/usbaudio.c3
-rw-r--r--sound/usb/usbmidi.c2
-rw-r--r--sound/usb/usbmixer.c9
-rw-r--r--usr/Makefile2
1476 files changed, 67631 insertions, 41020 deletions
diff --git a/CREDITS b/CREDITS
index ccd4f9f4dd71..d0880082c19b 100644
--- a/CREDITS
+++ b/CREDITS
@@ -2598,6 +2598,9 @@ S: Ucitelska 1576
S: Prague 8
S: 182 00 Czech Republic
+N: Rick Payne
+D: RFC2385 Support for TCP
+
N: Barak A. Pearlmutter
E: bap@cs.unm.edu
W: http://www.cs.unm.edu/~bap/
diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX
index 02457ec9c94f..f08ca9535733 100644
--- a/Documentation/00-INDEX
+++ b/Documentation/00-INDEX
@@ -104,8 +104,6 @@ firmware_class/
- request_firmware() hotplug interface info.
floppy.txt
- notes and driver options for the floppy disk driver.
-ftape.txt
- - notes about the floppy tape device driver.
hayes-esp.txt
- info on using the Hayes ESP serial driver.
highuid.txt
diff --git a/Documentation/Changes b/Documentation/Changes
index abee7f58c1ed..73a8617f1861 100644
--- a/Documentation/Changes
+++ b/Documentation/Changes
@@ -201,7 +201,7 @@ udev
----
udev is a userspace application for populating /dev dynamically with
only entries for devices actually present. udev replaces the basic
-functionality of devfs, while allowing persistant device naming for
+functionality of devfs, while allowing persistent device naming for
devices.
FUSE
diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index 2ffb0d62f0fe..05431621c861 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -489,7 +489,7 @@ size is the size of the area (must be multiples of PAGE_SIZE).
flags can be or'd together and are
DMA_MEMORY_MAP - request that the memory returned from
-dma_alloc_coherent() be directly writeable.
+dma_alloc_coherent() be directly writable.
DMA_MEMORY_IO - request that the memory returned from
dma_alloc_coherent() be addressable using read/write/memcpy_toio etc.
diff --git a/Documentation/DMA-ISA-LPC.txt b/Documentation/DMA-ISA-LPC.txt
index 705f6be92bdb..e767805b4182 100644
--- a/Documentation/DMA-ISA-LPC.txt
+++ b/Documentation/DMA-ISA-LPC.txt
@@ -110,7 +110,7 @@ lock.
Once the DMA transfer is finished (or timed out) you should disable
the channel again. You should also check get_dma_residue() to make
-sure that all data has been transfered.
+sure that all data has been transferred.
Example:
diff --git a/Documentation/DocBook/writing_usb_driver.tmpl b/Documentation/DocBook/writing_usb_driver.tmpl
index 07cd34c1940b..d4188d4ff535 100644
--- a/Documentation/DocBook/writing_usb_driver.tmpl
+++ b/Documentation/DocBook/writing_usb_driver.tmpl
@@ -345,8 +345,7 @@ static inline void skel_delete (struct usb_skel *dev)
usb_buffer_free (dev->udev, dev->bulk_out_size,
dev->bulk_out_buffer,
dev->write_urb->transfer_dma);
- if (dev->write_urb != NULL)
- usb_free_urb (dev->write_urb);
+ usb_free_urb (dev->write_urb);
kfree (dev);
}
</programlisting>
diff --git a/Documentation/MSI-HOWTO.txt b/Documentation/MSI-HOWTO.txt
index 5c34910665d1..d389388c733e 100644
--- a/Documentation/MSI-HOWTO.txt
+++ b/Documentation/MSI-HOWTO.txt
@@ -219,7 +219,7 @@ into the field vector of each element contained in a second argument.
Note that the pre-assigned IOAPIC dev->irq is valid only if the device
operates in PIN-IRQ assertion mode. In MSI-X mode, any attempt at
using dev->irq by the device driver to request for interrupt service
-may result unpredictabe behavior.
+may result in unpredictable behavior.
For each MSI-X vector granted, a device driver is responsible for calling
other functions like request_irq(), enable_irq(), etc. to enable
diff --git a/Documentation/accounting/taskstats.txt b/Documentation/accounting/taskstats.txt
index 92ebf29e9041..ff06b738bb88 100644
--- a/Documentation/accounting/taskstats.txt
+++ b/Documentation/accounting/taskstats.txt
@@ -96,9 +96,9 @@ a) TASKSTATS_TYPE_AGGR_PID/TGID : attribute containing no payload but indicates
a pid/tgid will be followed by some stats.
b) TASKSTATS_TYPE_PID/TGID: attribute whose payload is the pid/tgid whose stats
-is being returned.
+are being returned.
-c) TASKSTATS_TYPE_STATS: attribute with a struct taskstsats as payload. The
+c) TASKSTATS_TYPE_STATS: attribute with a struct taskstats as payload. The
same structure is used for both per-pid and per-tgid stats.
3. New message sent by kernel whenever a task exits. The payload consists of a
@@ -122,12 +122,12 @@ of atomicity).
However, maintaining per-process, in addition to per-task stats, within the
kernel has space and time overheads. To address this, the taskstats code
-accumalates each exiting task's statistics into a process-wide data structure.
-When the last task of a process exits, the process level data accumalated also
+accumulates each exiting task's statistics into a process-wide data structure.
+When the last task of a process exits, the process level data accumulated also
gets sent to userspace (along with the per-task data).
When a user queries to get per-tgid data, the sum of all other live threads in
-the group is added up and added to the accumalated total for previously exited
+the group is added up and added to the accumulated total for previously exited
threads of the same thread group.
Extending taskstats
diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt
index 34bf8f60d8f8..c6c9a9c10d7f 100644
--- a/Documentation/block/biodoc.txt
+++ b/Documentation/block/biodoc.txt
@@ -183,7 +183,7 @@ it, the pci dma mapping routines and associated data structures have now been
modified to accomplish a direct page -> bus translation, without requiring
a virtual address mapping (unlike the earlier scheme of virtual address
-> bus translation). So this works uniformly for high-memory pages (which
-do not have a correponding kernel virtual address space mapping) and
+do not have a corresponding kernel virtual address space mapping) and
low-memory pages.
Note: Please refer to DMA-mapping.txt for a discussion on PCI high mem DMA
@@ -391,7 +391,7 @@ forced such requests to be broken up into small chunks before being passed
on to the generic block layer, only to be merged by the i/o scheduler
when the underlying device was capable of handling the i/o in one shot.
Also, using the buffer head as an i/o structure for i/os that didn't originate
-from the buffer cache unecessarily added to the weight of the descriptors
+from the buffer cache unnecessarily added to the weight of the descriptors
which were generated for each such chunk.
The following were some of the goals and expectations considered in the
@@ -403,14 +403,14 @@ i. Should be appropriate as a descriptor for both raw and buffered i/o -
for raw i/o.
ii. Ability to represent high-memory buffers (which do not have a virtual
address mapping in kernel address space).
-iii.Ability to represent large i/os w/o unecessarily breaking them up (i.e
+iii.Ability to represent large i/os w/o unnecessarily breaking them up (i.e
greater than PAGE_SIZE chunks in one shot)
iv. At the same time, ability to retain independent identity of i/os from
different sources or i/o units requiring individual completion (e.g. for
latency reasons)
v. Ability to represent an i/o involving multiple physical memory segments
(including non-page aligned page fragments, as specified via readv/writev)
- without unecessarily breaking it up, if the underlying device is capable of
+ without unnecessarily breaking it up, if the underlying device is capable of
handling it.
vi. Preferably should be based on a memory descriptor structure that can be
passed around different types of subsystems or layers, maybe even
@@ -1013,7 +1013,7 @@ Characteristics:
i. Binary tree
AS and deadline i/o schedulers use red black binary trees for disk position
sorting and searching, and a fifo linked list for time-based searching. This
-gives good scalability and good availablility of information. Requests are
+gives good scalability and good availability of information. Requests are
almost always dispatched in disk sort order, so a cache is kept of the next
request in sort order to prevent binary tree lookups.
diff --git a/Documentation/cpu-freq/cpufreq-nforce2.txt b/Documentation/cpu-freq/cpufreq-nforce2.txt
index 9188337d8f6b..babce1315026 100644
--- a/Documentation/cpu-freq/cpufreq-nforce2.txt
+++ b/Documentation/cpu-freq/cpufreq-nforce2.txt
@@ -1,7 +1,7 @@
-The cpufreq-nforce2 driver changes the FSB on nVidia nForce2 plattforms.
+The cpufreq-nforce2 driver changes the FSB on nVidia nForce2 platforms.
-This works better than on other plattforms, because the FSB of the CPU
+This works better than on other platforms, because the FSB of the CPU
can be controlled independently from the PCI/AGP clock.
The module has two options:
diff --git a/Documentation/cpu-hotplug.txt b/Documentation/cpu-hotplug.txt
index 4868c34f7509..cc60d29b954c 100644
--- a/Documentation/cpu-hotplug.txt
+++ b/Documentation/cpu-hotplug.txt
@@ -54,8 +54,8 @@ additional_cpus=n (*) Use this to limit hotpluggable cpus. This option sets
ia64 and x86_64 use the number of disabled local apics in ACPI tables MADT
to determine the number of potentially hot-pluggable cpus. The implementation
-should only rely on this to count the #of cpus, but *MUST* not rely on the
-apicid values in those tables for disabled apics. In the event BIOS doesnt
+should only rely on this to count the # of cpus, but *MUST* not rely on the
+apicid values in those tables for disabled apics. In the event BIOS doesn't
mark such hot-pluggable cpus as disabled entries, one could use this
parameter "additional_cpus=x" to represent those cpus in the cpu_possible_map.
diff --git a/Documentation/devices.txt b/Documentation/devices.txt
index 28c4f79662c2..70690f1a14af 100644
--- a/Documentation/devices.txt
+++ b/Documentation/devices.txt
@@ -92,7 +92,7 @@ Your cooperation is appreciated.
7 = /dev/full Returns ENOSPC on write
8 = /dev/random Nondeterministic random number gen.
9 = /dev/urandom Faster, less secure random number gen.
- 10 = /dev/aio Asyncronous I/O notification interface
+ 10 = /dev/aio Asynchronous I/O notification interface
11 = /dev/kmsg Writes to this come out as printk's
1 block RAM disk
0 = /dev/ram0 First RAM disk
@@ -1093,7 +1093,7 @@ Your cooperation is appreciated.
55 char DSP56001 digital signal processor
0 = /dev/dsp56k First DSP56001
- 55 block Mylex DAC960 PCI RAID controller; eigth controller
+ 55 block Mylex DAC960 PCI RAID controller; eighth controller
0 = /dev/rd/c7d0 First disk, whole disk
8 = /dev/rd/c7d1 Second disk, whole disk
...
@@ -1456,7 +1456,7 @@ Your cooperation is appreciated.
1 = /dev/cum1 Callout device for ttyM1
...
- 79 block Compaq Intelligent Drive Array, eigth controller
+ 79 block Compaq Intelligent Drive Array, eighth controller
0 = /dev/ida/c7d0 First logical drive whole disk
16 = /dev/ida/c7d1 Second logical drive whole disk
...
@@ -1900,7 +1900,7 @@ Your cooperation is appreciated.
1 = /dev/av1 Second A/V card
...
-111 block Compaq Next Generation Drive Array, eigth controller
+111 block Compaq Next Generation Drive Array, eighth controller
0 = /dev/cciss/c7d0 First logical drive, whole disk
16 = /dev/cciss/c7d1 Second logical drive, whole disk
...
diff --git a/Documentation/driver-model/platform.txt b/Documentation/driver-model/platform.txt
index 5eee3e0bfc4c..9f0bc3bfd776 100644
--- a/Documentation/driver-model/platform.txt
+++ b/Documentation/driver-model/platform.txt
@@ -1,99 +1,131 @@
Platform Devices and Drivers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+See <linux/platform_device.h> for the driver model interface to the
+platform bus: platform_device, and platform_driver. This pseudo-bus
+is used to connect devices on busses with minimal infrastructure,
+like those used to integrate peripherals on many system-on-chip
+processors, or some "legacy" PC interconnects; as opposed to large
+formally specified ones like PCI or USB.
+
Platform devices
~~~~~~~~~~~~~~~~
Platform devices are devices that typically appear as autonomous
entities in the system. This includes legacy port-based devices and
-host bridges to peripheral buses.
-
-
-Platform drivers
-~~~~~~~~~~~~~~~~
-Drivers for platform devices are typically very simple and
-unstructured. Either the device was present at a particular I/O port
-and the driver was loaded, or it was not. There was no possibility
-of hotplugging or alternative discovery besides probing at a specific
-I/O address and expecting a specific response.
+host bridges to peripheral buses, and most controllers integrated
+into system-on-chip platforms. What they usually have in common
+is direct addressing from a CPU bus. Rarely, a platform_device will
+be connected through a segment of some other kind of bus; but its
+registers will still be directly addressible.
+Platform devices are given a name, used in driver binding, and a
+list of resources such as addresses and IRQs.
-Other Architectures, Modern Firmware, and new Platforms
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-These devices are not always at the legacy I/O ports. This is true on
-other architectures and on some modern architectures. In most cases,
-the drivers are modified to discover the devices at other well-known
-ports for the given platform. However, the firmware in these systems
-does usually know where exactly these devices reside, and in some
-cases, it's the only way of discovering them.
+struct platform_device {
+ const char *name;
+ u32 id;
+ struct device dev;
+ u32 num_resources;
+ struct resource *resource;
+};
-The Platform Bus
-~~~~~~~~~~~~~~~~
-A platform bus has been created to deal with these issues. First and
-foremost, it groups all the legacy devices under a common bus, and
-gives them a common parent if they don't already have one.
-
-But, besides the organizational benefits, the platform bus can also
-accommodate firmware-based enumeration.
-
-
-Device Discovery
+Platform drivers
~~~~~~~~~~~~~~~~
-The platform bus has no concept of probing for devices. Devices
-discovery is left up to either the legacy drivers or the
-firmware. These entities are expected to notify the platform of
-devices that it discovers via the bus's add() callback:
-
- platform_bus.add(parent,bus_id).
-
-
-Bus IDs
-~~~~~~~
-Bus IDs are the canonical names for the devices. There is no globally
-standard addressing mechanism for legacy devices. In the IA-32 world,
-we have Pnp IDs to use, as well as the legacy I/O ports. However,
-neither tell what the device really is or have any meaning on other
-platforms.
-
-Since both PnP IDs and the legacy I/O ports (and other standard I/O
-ports for specific devices) have a 1:1 mapping, we map the
-platform-specific name or identifier to a generic name (at least
-within the scope of the kernel).
-
-For example, a serial driver might find a device at I/O 0x3f8. The
-ACPI firmware might also discover a device with PnP ID (_HID)
-PNP0501. Both correspond to the same device and should be mapped to the
-canonical name 'serial'.
-
-The bus_id field should be a concatenation of the canonical name and
-the instance of that type of device. For example, the device at I/O
-port 0x3f8 should have a bus_id of "serial0". This places the
-responsibility of enumerating devices of a particular type up to the
-discovery mechanism. But, they are the entity that should know best
-(as opposed to the platform bus driver).
-
-
-Drivers
-~~~~~~~
-Drivers for platform devices should have a name that is the same as
-the canonical name of the devices they support. This allows the
-platform bus driver to do simple matching with the basic data
-structures to determine if a driver supports a certain device.
-
-For example, a legacy serial driver should have a name of 'serial' and
-register itself with the platform bus.
-
-
-Driver Binding
-~~~~~~~~~~~~~~
-Legacy drivers assume they are bound to the device once they start up
-and probe an I/O port. Divorcing them from this will be a difficult
-process. However, that shouldn't prevent us from implementing
-firmware-based enumeration.
-
-The firmware should notify the platform bus about devices before the
-legacy drivers have had a chance to load. Once the drivers are loaded,
-they driver model core will attempt to bind the driver to any
-previously-discovered devices. Once that has happened, it will be free
-to discover any other devices it pleases.
+Platform drivers follow the standard driver model convention, where
+discovery/enumeration is handled outside the drivers, and drivers
+provide probe() and remove() methods. They support power management
+and shutdown notifications using the standard conventions.
+
+struct platform_driver {
+ int (*probe)(struct platform_device *);
+ int (*remove)(struct platform_device *);
+ void (*shutdown)(struct platform_device *);
+ int (*suspend)(struct platform_device *, pm_message_t state);
+ int (*suspend_late)(struct platform_device *, pm_message_t state);
+ int (*resume_early)(struct platform_device *);
+ int (*resume)(struct platform_device *);
+ struct device_driver driver;
+};
+
+Note that probe() should general verify that the specified device hardware
+actually exists; sometimes platform setup code can't be sure. The probing
+can use device resources, including clocks, and device platform_data.
+
+Platform drivers register themselves the normal way:
+
+ int platform_driver_register(struct platform_driver *drv);
+
+Or, in common situations where the device is known not to be hot-pluggable,
+the probe() routine can live in an init section to reduce the driver's
+runtime memory footprint:
+
+ int platform_driver_probe(struct platform_driver *drv,
+ int (*probe)(struct platform_device *))
+
+
+Device Enumeration
+~~~~~~~~~~~~~~~~~~
+As a rule, platform specific (and often board-specific) setup code wil
+register platform devices:
+
+ int platform_device_register(struct platform_device *pdev);
+
+ int platform_add_devices(struct platform_device **pdevs, int ndev);
+
+The general rule is to register only those devices that actually exist,
+but in some cases extra devices might be registered. For example, a kernel
+might be configured to work with an external network adapter that might not
+be populated on all boards, or likewise to work with an integrated controller
+that some boards might not hook up to any peripherals.
+
+In some cases, boot firmware will export tables describing the devices
+that are populated on a given board. Without such tables, often the
+only way for system setup code to set up the correct devices is to build
+a kernel for a specific target board. Such board-specific kernels are
+common with embedded and custom systems development.
+
+In many cases, the memory and IRQ resources associated with the platform
+device are not enough to let the device's driver work. Board setup code
+will often provide additional information using the device's platform_data
+field to hold additional information.
+
+Embedded systems frequently need one or more clocks for platform devices,
+which are normally kept off until they're actively needed (to save power).
+System setup also associates those clocks with the device, so that that
+calls to clk_get(&pdev->dev, clock_name) return them as needed.
+
+
+Device Naming and Driver Binding
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The platform_device.dev.bus_id is the canonical name for the devices.
+It's built from two components:
+
+ * platform_device.name ... which is also used to for driver matching.
+
+ * platform_device.id ... the device instance number, or else "-1"
+ to indicate there's only one.
+
+These are catenated, so name/id "serial"/0 indicates bus_id "serial.0", and
+"serial/3" indicates bus_id "serial.3"; both would use the platform_driver
+named "serial". While "my_rtc"/-1 would be bus_id "my_rtc" (no instance id)
+and use the platform_driver called "my_rtc".
+
+Driver binding is performed automatically by the driver core, invoking
+driver probe() after finding a match between device and driver. If the
+probe() succeeds, the driver and device are bound as usual. There are
+three different ways to find such a match:
+
+ - Whenever a device is registered, the drivers for that bus are
+ checked for matches. Platform devices should be registered very
+ early during system boot.
+
+ - When a driver is registered using platform_driver_register(), all
+ unbound devices on that bus are checked for matches. Drivers
+ usually register later during booting, or by module loading.
+
+ - Registering a driver using platform_driver_probe() works just like
+ using platform_driver_register(), except that the the driver won't
+ be probed later if another device registers. (Which is OK, since
+ this interface is only for use with non-hotpluggable devices.)
diff --git a/Documentation/driver-model/porting.txt b/Documentation/driver-model/porting.txt
index 98b233cb8b36..92d86f7271b4 100644
--- a/Documentation/driver-model/porting.txt
+++ b/Documentation/driver-model/porting.txt
@@ -92,7 +92,7 @@ struct device represents a single device. It mainly contains metadata
describing the relationship the device has to other entities.
-- Embedd a struct device in the bus-specific device type.
+- Embed a struct device in the bus-specific device type.
struct pci_dev {
diff --git a/Documentation/dvb/ci.txt b/Documentation/dvb/ci.txt
index 531239b29082..2ecd834585e6 100644
--- a/Documentation/dvb/ci.txt
+++ b/Documentation/dvb/ci.txt
@@ -71,7 +71,7 @@ eliminating the need for any additional ioctls.
The disadvantage is that the driver/hardware has to manage the rest. For
the application programmer it would be as simple as sending/receiving an
array to/from the CI ioctls as defined in the Linux DVB API. No changes
-have been made in the API to accomodate this feature.
+have been made in the API to accommodate this feature.
* Why the need for another CI interface ?
@@ -102,7 +102,7 @@ This CI interface follows the CI high level interface, which is not
implemented by most applications. Hence this area is revisited.
This CI interface is quite different in the case that it tries to
-accomodate all other CI based devices, that fall into the other categories
+accommodate all other CI based devices, that fall into the other categories.
This means that this CI interface handles the EN50221 style tags in the
Application layer only and no session management is taken care of by the
diff --git a/Documentation/eisa.txt b/Documentation/eisa.txt
index 6a099edadd62..60e361ba08c0 100644
--- a/Documentation/eisa.txt
+++ b/Documentation/eisa.txt
@@ -62,7 +62,7 @@ res : root device I/O resource
bus_base_addr : slot 0 address on this bus
slots : max slot number to probe
force_probe : Probe even when slot 0 is empty (no EISA mainboard)
-dma_mask : Default DMA mask. Usualy the bridge device dma_mask.
+dma_mask : Default DMA mask. Usually the bridge device dma_mask.
bus_nr : unique bus id, set by eisa_root_register
** Driver :
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index d52c4aaaf17f..226ecf2ffd56 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -70,18 +70,6 @@ Who: Dominik Brodowski <linux@brodo.de>
---------------------------
-What: ip_queue and ip6_queue (old ipv4-only and ipv6-only netfilter queue)
-When: December 2005
-Why: This interface has been obsoleted by the new layer3-independent
- "nfnetlink_queue". The Kernel interface is compatible, so the old
- ip[6]tables "QUEUE" targets still work and will transparently handle
- all packets into nfnetlink queue number 0. Userspace users will have
- to link against API-compatible library on top of libnfnetlink_queue
- instead of the current 'libipq'.
-Who: Harald Welte <laforge@netfilter.org>
-
----------------------------
-
What: remove EXPORT_SYMBOL(kernel_thread)
When: August 2006
Files: arch/*/kernel/*_ksyms.c
@@ -227,21 +215,6 @@ Who: Patrick McHardy <kaber@trash.net>
---------------------------
-What: frame diverter
-When: November 2006
-Why: The frame diverter is included in most distribution kernels, but is
- broken. It does not correctly handle many things:
- - IPV6
- - non-linear skb's
- - network device RCU on removal
- - input frames not correctly checked for protocol errors
- It also adds allocation overhead even if not enabled.
- It is not clear if anyone is still using it.
-Who: Stephen Hemminger <shemminger@osdl.org>
-
----------------------------
-
-
What: PHYSDEVPATH, PHYSDEVBUS, PHYSDEVDRIVER in the uevent environment
When: October 2008
Why: The stacking of class devices makes these values misleading and
@@ -261,10 +234,11 @@ Who: Jean Delvare <khali@linux-fr.org>
---------------------------
-What: ftape
-When: 2.6.20
-Why: Orphaned for ages. SMP bugs long unfixed. Few users left
- in the world.
-Who: Jeff Garzik <jeff@garzik.org>
+What: IPv4 only connection tracking/NAT/helpers
+When: 2.6.22
+Why: The new layer 3 independant connection tracking replaces the old
+ IPv4 only version. After some stabilization of the new code the
+ old one will be removed.
+Who: Patrick McHardy <kaber@trash.net>
---------------------------
diff --git a/Documentation/filesystems/adfs.txt b/Documentation/filesystems/adfs.txt
index 060abb0c7004..9e8811f92b84 100644
--- a/Documentation/filesystems/adfs.txt
+++ b/Documentation/filesystems/adfs.txt
@@ -3,7 +3,7 @@ Mount options for ADFS
uid=nnn All files in the partition will be owned by
user id nnn. Default 0 (root).
- gid=nnn All files in the partition willbe in group
+ gid=nnn All files in the partition will be in group
nnn. Default 0 (root).
ownmask=nnn The permission mask for ADFS 'owner' permissions
will be nnn. Default 0700.
diff --git a/Documentation/filesystems/configfs/configfs.txt b/Documentation/filesystems/configfs/configfs.txt
index c3a7afb5eabf..b34cdb50eab4 100644
--- a/Documentation/filesystems/configfs/configfs.txt
+++ b/Documentation/filesystems/configfs/configfs.txt
@@ -209,7 +209,7 @@ will happen for write(2).
[struct config_group]
-A config_item cannot live in a vaccum. The only way one can be created
+A config_item cannot live in a vacuum. The only way one can be created
is via mkdir(2) on a config_group. This will trigger creation of a
child item.
@@ -275,7 +275,7 @@ directory is not empty.
[struct configfs_subsystem]
-A subsystem must register itself, ususally at module_init time. This
+A subsystem must register itself, usually at module_init time. This
tells configfs to make the subsystem appear in the file tree.
struct configfs_subsystem {
diff --git a/Documentation/filesystems/fuse.txt b/Documentation/filesystems/fuse.txt
index a584f05403a4..3d7447738958 100644
--- a/Documentation/filesystems/fuse.txt
+++ b/Documentation/filesystems/fuse.txt
@@ -111,7 +111,7 @@ For each connection the following files exist within this directory:
'waiting'
- The number of requests which are waiting to be transfered to
+ The number of requests which are waiting to be transferred to
userspace or being processed by the filesystem daemon. If there is
no filesystem activity and 'waiting' is non-zero, then the
filesystem is hung or deadlocked.
@@ -136,7 +136,7 @@ following will happen:
2) If the request is not yet sent to userspace AND the signal is not
fatal, then an 'interrupted' flag is set for the request. When
- the request has been successfully transfered to userspace and
+ the request has been successfully transferred to userspace and
this flag is set, an INTERRUPT request is queued.
3) If the request is already sent to userspace, then an INTERRUPT
diff --git a/Documentation/filesystems/hpfs.txt b/Documentation/filesystems/hpfs.txt
index 33dc360c8e89..38aba03efc5e 100644
--- a/Documentation/filesystems/hpfs.txt
+++ b/Documentation/filesystems/hpfs.txt
@@ -274,7 +274,7 @@ History
Fixed race-condition in buffer code - it is in all filesystems in Linux;
when reading device (cat /dev/hda) while creating files on it, files
could be damaged
-2.02 Woraround for bug in breada in Linux. breada could cause accesses beyond
+2.02 Workaround for bug in breada in Linux. breada could cause accesses beyond
end of partition
2.03 Char, block devices and pipes are correctly created
Fixed non-crashing race in unlink (Alexander Viro)
diff --git a/Documentation/filesystems/ntfs.txt b/Documentation/filesystems/ntfs.txt
index 35f105b29e3e..13ba649bda75 100644
--- a/Documentation/filesystems/ntfs.txt
+++ b/Documentation/filesystems/ntfs.txt
@@ -337,7 +337,7 @@ Finally, for a mirrored volume, i.e. raid level 1, the table would look like
this (note all values are in 512-byte sectors):
--- cut here ---
-# Ofs Size Raid Log Number Region Should Number Source Start Taget Start
+# Ofs Size Raid Log Number Region Should Number Source Start Target Start
# in of the type type of log size sync? of Device in Device in
# vol volume params mirrors Device Device
0 2056320 mirror core 2 16 nosync 2 /dev/hda1 0 /dev/hdb1 0
@@ -599,7 +599,7 @@ Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
- Major bug fixes for reading files and volumes in corner cases which
were being hit by Windows 2k/XP users.
2.1.2:
- - Major bug fixes aleviating the hangs in statfs experienced by some
+ - Major bug fixes alleviating the hangs in statfs experienced by some
users.
2.1.1:
- Update handling of compressed files so people no longer get the
diff --git a/Documentation/filesystems/ocfs2.txt b/Documentation/filesystems/ocfs2.txt
index 4389c684a80a..af6defd10cb6 100644
--- a/Documentation/filesystems/ocfs2.txt
+++ b/Documentation/filesystems/ocfs2.txt
@@ -30,7 +30,7 @@ Caveats
Features which OCFS2 does not support yet:
- sparse files
- extended attributes
- - shared writeable mmap
+ - shared writable mmap
- loopback is supported, but data written will not
be cluster coherent.
- quotas
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index 3355e6920105..72af5de1effb 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -1220,9 +1220,9 @@ applications are using mlock(), or if you are running with no swap then
you probably should increase the lower_zone_protection setting.
The units of this tunable are fairly vague. It is approximately equal
-to "megabytes". So setting lower_zone_protection=100 will protect around 100
+to "megabytes," so setting lower_zone_protection=100 will protect around 100
megabytes of the lowmem zone from user allocations. It will also make
-those 100 megabytes unavaliable for use by applications and by
+those 100 megabytes unavailable for use by applications and by
pagecache, so there is a cost.
The effects of this tunable may be observed by monitoring
@@ -1538,10 +1538,10 @@ TCP settings
tcp_ecn
-------
-This file controls the use of the ECN bit in the IPv4 headers, this is a new
+This file controls the use of the ECN bit in the IPv4 headers. This is a new
feature about Explicit Congestion Notification, but some routers and firewalls
-block trafic that has this bit set, so it could be necessary to echo 0 to
-/proc/sys/net/ipv4/tcp_ecn, if you want to talk to this sites. For more info
+block traffic that has this bit set, so it could be necessary to echo 0 to
+/proc/sys/net/ipv4/tcp_ecn if you want to talk to these sites. For more info
you could read RFC2481.
tcp_retrans_collapse
diff --git a/Documentation/filesystems/spufs.txt b/Documentation/filesystems/spufs.txt
index 982645a1981d..1343d118a9b2 100644
--- a/Documentation/filesystems/spufs.txt
+++ b/Documentation/filesystems/spufs.txt
@@ -210,7 +210,7 @@ FILES
/signal2
The two signal notification channels of an SPU. These are read-write
files that operate on a 32 bit word. Writing to one of these files
- triggers an interrupt on the SPU. The value writting to the signal
+ triggers an interrupt on the SPU. The value written to the signal
files can be read from the SPU through a channel read or from host user
space through the file. After the value has been read by the SPU, it
is reset to zero. The possible operations on an open signal1 or sig-
diff --git a/Documentation/ftape.txt b/Documentation/ftape.txt
deleted file mode 100644
index 7d8bb3384031..000000000000
--- a/Documentation/ftape.txt
+++ /dev/null
@@ -1,307 +0,0 @@
-Intro
-=====
-
-This file describes some issues involved when using the "ftape"
-floppy tape device driver that comes with the Linux kernel.
-
-ftape has a home page at
-
-http://ftape.dot-heine.de/
-
-which contains further information about ftape. Please cross check
-this WWW address against the address given (if any) in the MAINTAINERS
-file located in the top level directory of the Linux kernel source
-tree.
-
-NOTE: This is an unmaintained set of drivers, and it is not guaranteed to work.
-If you are interested in taking over maintenance, contact Claus-Justus Heine
-<ch@dot-heine.de>, the former maintainer.
-
-Contents
-========
-
-A minus 1: Ftape documentation
-
-A. Changes
- 1. Goal
- 2. I/O Block Size
- 3. Write Access when not at EOD (End Of Data) or BOT (Begin Of Tape)
- 4. Formatting
- 5. Interchanging cartridges with other operating systems
-
-B. Debugging Output
- 1. Introduction
- 2. Tuning the debugging output
-
-C. Boot and load time configuration
- 1. Setting boot time parameters
- 2. Module load time parameters
- 3. Ftape boot- and load time options
- 4. Example kernel parameter setting
- 5. Example module parameter setting
-
-D. Support and contacts
-
-*******************************************************************************
-
-A minus 1. Ftape documentation
-==============================
-
-Unluckily, the ftape-HOWTO is out of date. This really needs to be
-changed. Up to date documentation as well as recent development
-versions of ftape and useful links to related topics can be found at
-the ftape home page at
-
-http://ftape.dot-heine.de/
-
-*******************************************************************************
-
-A. Changes
-==========
-
-1. Goal
- ~~~~
- The goal of all that incompatibilities was to give ftape an interface
- that resembles the interface provided by SCSI tape drives as close
- as possible. Thus any Unix backup program that is known to work
- with SCSI tape drives should also work.
-
- The concept of a fixed block size for read/write transfers is
- rather unrelated to this SCSI tape compatibility at the file system
- interface level. It developed out of a feature of zftape, a
- block wise user transparent on-the-fly compression. That compression
- support will not be dropped in future releases for compatibility
- reasons with previous releases of zftape.
-
-2. I/O Block Size
- ~~~~~~~~~~~~~~
- The block size defaults to 10k which is the default block size of
- GNU tar.
-
- The block size can be tuned either during kernel configuration or
- at runtime with the MTIOCTOP ioctl using the MTSETBLK operation
- (i.e. do "mt -f /dev/qft0" setblk #BLKSZ). A block size of 0
- switches to variable block size mode i.e. "mt setblk 0" switches
- off the block size restriction. However, this disables zftape's
- built in on-the-fly compression which doesn't work with variable
- block size mode.
-
- The BLKSZ parameter must be given as a byte count and must be a
- multiple of 32k or 0, i.e. use "mt setblk 32768" to switch to a
- block size of 32k.
-
- The typical symptom of a block size mismatch is an "invalid
- argument" error message.
-
-3. Write Access when not at EOD (End Of Data) or BOT (Begin Of Tape)
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- zftape (the file system interface of ftape-3.x) denies write access
- to the tape cartridge when it isn't positioned either at BOT or
- EOD.
-
-4. Formatting
- ~~~~~~~~~~
- ftape DOES support formatting of floppy tape cartridges. You need the
- `ftformat' program that is shipped with the modules version of ftape.
- Please get the latest version of ftape from
-
- ftp://sunsite.unc.edu/pub/Linux/kernel/tapes
-
- or from the ftape home page at
-
- http://ftape.dot-heine.de/
-
- `ftformat' is contained in the `./contrib/' subdirectory of that
- separate ftape package.
-
-5. Interchanging cartridges with other operating systems
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- The internal emulation of Unix tape device file marks has changed
- completely. ftape now uses the volume table segment as specified
- by the QIC-40/80/3010/3020/113 standards to emulate file marks. As
- a consequence there is limited support to interchange cartridges
- with other operating systems.
-
- To be more precise: ftape will detect volumes written by other OS's
- programs and other OS's programs will detect volumes written by
- ftape.
-
- However, it isn't possible to extract the data dumped to the tape
- by some MSDOS program with ftape. This exceeds the scope of a
- kernel device driver. If you need such functionality, then go ahead
- and write a user space utility that is able to do that. ftape already
- provides all kernel level support necessary to do that.
-
-*******************************************************************************
-
-B. Debugging Output
- ================
-
-1. Introduction
- ~~~~~~~~~~~~
- The ftape driver can be very noisy in that is can print lots of
- debugging messages to the kernel log files and the system console.
- While this is useful for debugging it might be annoying during
- normal use and enlarges the size of the driver by several kilobytes.
-
- To reduce the size of the driver you can trim the maximal amount of
- debugging information available during kernel configuration. Please
- refer to the kernel configuration script and its on-line help
- functionality.
-
- The amount of debugging output maps to the "tracing" boot time
- option and the "ft_tracing" modules option as follows:
-
- 0 bugs
- 1 + errors (with call-stack dump)
- 2 + warnings
- 3 + information
- 4 + more information
- 5 + program flow
- 6 + fdc/dma info
- 7 + data flow
- 8 + everything else
-
-2. Tuning the debugging output
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~
- To reduce the amount of debugging output printed to the system
- console you can
-
- i) trim the debugging output at run-time with
-
- mt -f /dev/nqft0 setdensity #DBGLVL
-
- where "#DBGLVL" is a number between 0 and 9
-
- ii) trim the debugging output at module load time with
-
- modprobe ftape ft_tracing=#DBGLVL
-
- Of course, this applies only if you have configured ftape to be
- compiled as a module.
-
- iii) trim the debugging output during system boot time. Add the
- following to the kernel command line:
-
- ftape=#DBGLVL,tracing
-
- Please refer also to the next section if you don't know how to
- set boot time parameters.
-
-*******************************************************************************
-
-C. Boot and load time configuration
- ================================
-
-1. Setting boot time parameters
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Assuming that you use lilo, the LI)nux LO)ader, boot time kernel
- parameters can be set by adding a line
-
- append some_kernel_boot_time_parameter
-
- to `/etc/lilo.conf' or at real boot time by typing in the options
- at the prompt provided by LILO. I can't give you advice on how to
- specify those parameters with other loaders as I don't use them.
-
- For ftape, each "some_kernel_boot_time_parameter" looks like
- "ftape=value,option". As an example, the debugging output can be
- increased with
-
- ftape=4,tracing
-
- NOTE: the value precedes the option name.
-
-2. Module load time parameters
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Module parameters can be specified either directly when invoking
- the program 'modprobe' at the shell prompt:
-
- modprobe ftape ft_tracing=4
-
- or by editing the file `/etc/modprobe.conf' in which case they take
- effect each time when the module is loaded with `modprobe' (please
- refer to the respective manual pages). Thus, you should add a line
-
- options ftape ft_tracing=4
-
- to `/etc/modprobe.conf` if you intend to increase the debugging
- output of the driver.
-
-
-3. Ftape boot- and load time options
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- i. Controlling the amount of debugging output
- DBGLVL has to be replaced by a number between 0 and 8.
-
- module | kernel command line
- -----------------------|----------------------
- ft_tracing=DBGLVL | ftape=DBGLVL,tracing
-
- ii. Hardware setup
- BASE is the base address of your floppy disk controller,
- IRQ and DMA give its interrupt and DMA channel, respectively.
- BOOL is an integer, "0" means "no"; any other value means
- "yes". You don't need to specify anything if connecting your tape
- drive to the standard floppy disk controller. All of these
- values have reasonable defaults. The defaults can be modified
- during kernel configuration, i.e. while running "make config",
- "make menuconfig" or "make xconfig" in the top level directory
- of the Linux kernel source tree. Please refer also to the on
- line documentation provided during that kernel configuration
- process.
-
- ft_probe_fc10 is set to a non-zero value if you wish for ftape to
- probe for a Colorado FC-10 or FC-20 controller.
-
- ft_mach2 is set to a non-zero value if you wish for ftape to probe
- for a Mountain MACH-2 controller.
-
- module | kernel command line
- -----------------------|----------------------
- ft_fdc_base=BASE | ftape=BASE,ioport
- ft_fdc_irq=IRQ | ftape=IRQ,irq
- ft_fdc_dma=DMA | ftape=DMA,dma
- ft_probe_fc10=BOOL | ftape=BOOL,fc10
- ft_mach2=BOOL | ftape=BOOL,mach2
- ft_fdc_threshold=THR | ftape=THR,threshold
- ft_fdc_rate_limit=RATE | ftape=RATE,datarate
-
-4. Example kernel parameter setting
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- To configure ftape to probe for a Colorado FC-10/FC-20 controller
- and to increase the amount of debugging output a little bit, add
- the following line to `/etc/lilo.conf':
-
- append ftape=1,fc10 ftape=4,tracing
-
-5. Example module parameter setting
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- To do the same, but with ftape compiled as a loadable kernel
- module, add the following line to `/etc/modprobe.conf':
-
- options ftape ft_probe_fc10=1 ft_tracing=4
-
-*******************************************************************************
-
-D. Support and contacts
- ====================
-
- Ftape is distributed under the GNU General Public License. There is
- absolutely no warranty for this software. However, you can reach
- the current maintainer of the ftape package under the email address
- given in the MAINTAINERS file which is located in the top level
- directory of the Linux kernel source tree. There you'll find also
- the relevant mailing list to use as a discussion forum and the web
- page to query for the most recent documentation, related work and
- development versions of ftape.
-
- Changelog:
- ==========
-
-~1996: Original Document
-
-10-24-2004: General cleanup and updating, noting additional module options.
- James Nelson <james4765@gmail.com>
diff --git a/Documentation/fujitsu/frv/gdbstub.txt b/Documentation/fujitsu/frv/gdbstub.txt
index 6ce5aa9abbc5..9304fb36ae8a 100644
--- a/Documentation/fujitsu/frv/gdbstub.txt
+++ b/Documentation/fujitsu/frv/gdbstub.txt
@@ -59,7 +59,7 @@ the following things on the "Kernel Hacking" tab:
Then build as usual, download to the board and execute. Note that if
"Immediate activation" was selected, then the kernel will wait for GDB to
attach. If not, then the kernel will boot immediately and GDB will have to
-interupt it or wait for an exception to occur if before doing anything with
+interrupt it or wait for an exception to occur before doing anything with
the kernel.
diff --git a/Documentation/fujitsu/frv/kernel-ABI.txt b/Documentation/fujitsu/frv/kernel-ABI.txt
index 8b0a5fc8bfd9..aaa1cec86f0b 100644
--- a/Documentation/fujitsu/frv/kernel-ABI.txt
+++ b/Documentation/fujitsu/frv/kernel-ABI.txt
@@ -156,7 +156,7 @@ 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
+Furthermore, 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.
diff --git a/Documentation/ide.txt b/Documentation/ide.txt
index 0bf38baa2db9..786c3a766995 100644
--- a/Documentation/ide.txt
+++ b/Documentation/ide.txt
@@ -390,5 +390,5 @@ mlord@pobox.com
Wed Apr 17 22:52:44 CEST 2002 edited by Marcin Dalecki, the current
maintainer.
-Wed Aug 20 22:31:29 CEST 2003 updated ide boot uptions to current ide.c
+Wed Aug 20 22:31:29 CEST 2003 updated ide boot options to current ide.c
comments at 2.6.0-test4 time. Maciej Soltysiak <solt@dns.toxicfilms.tv>
diff --git a/Documentation/input/amijoy.txt b/Documentation/input/amijoy.txt
index 4f0e89df5c51..7dc4f175943c 100644
--- a/Documentation/input/amijoy.txt
+++ b/Documentation/input/amijoy.txt
@@ -91,8 +91,8 @@ JOY1DAT Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 X7 X6 X5 X4 X3 X2 X1 X0
| 1 | M0HQ | JOY0DAT Horizontal Clock (quadrature) |
| 2 | M0V | JOY0DAT Vertical Clock |
| 3 | M0VQ | JOY0DAT Vertical Clock (quadrature) |
- | 4 | M1V | JOY1DAT Horizontall Clock |
- | 5 | M1VQ | JOY1DAT Horizontall Clock (quadrature) |
+ | 4 | M1V | JOY1DAT Horizontal Clock |
+ | 5 | M1VQ | JOY1DAT Horizontal Clock (quadrature) |
| 6 | M1V | JOY1DAT Vertical Clock |
| 7 | M1VQ | JOY1DAT Vertical Clock (quadrature) |
+--------+----------+-----------------------------------------+
diff --git a/Documentation/input/atarikbd.txt b/Documentation/input/atarikbd.txt
index 1e7e5853ba4c..668f4d0d97d6 100644
--- a/Documentation/input/atarikbd.txt
+++ b/Documentation/input/atarikbd.txt
@@ -103,7 +103,7 @@ LEFT=0x74 & RIGHT=0x75).
5.1 Joystick Event Reporting
-In this mode, the ikbd generates a record whever the joystick position is
+In this mode, the ikbd generates a record whenever the joystick position is
changed (i.e. for each opening or closing of a joystick switch or trigger).
The joystick event record is two bytes of the form:
@@ -277,8 +277,8 @@ default to 1 at RESET (or power-up).
9.7 SET MOUSE SCALE
0x0C
- X ; horizontal mouse ticks per internel X
- Y ; vertical mouse ticks per internel Y
+ X ; horizontal mouse ticks per internal X
+ Y ; vertical mouse ticks per internal Y
This command sets the scale factor for the ABSOLUTE MOUSE POSITIONING mode.
In this mode, the specified number of mouse phase changes ('clicks') must
@@ -323,7 +323,7 @@ mouse position.
0x0F
This command makes the origin of the Y axis to be at the bottom of the
-logical coordinate system internel to the ikbd for all relative or absolute
+logical coordinate system internal to the ikbd for all relative or absolute
mouse motion. This causes mouse motion toward the user to be negative in sign
and away from the user to be positive.
@@ -597,8 +597,8 @@ mode or FIRE BUTTON MONITORING mode.
10. SCAN CODES
-The key scan codes return by the ikbd are chosen to simplify the
-implementaion of GSX.
+The key scan codes returned by the ikbd are chosen to simplify the
+implementation of GSX.
GSX Standard Keyboard Mapping.
diff --git a/Documentation/input/yealink.txt b/Documentation/input/yealink.txt
index 0a8c97e87d47..5360e434486c 100644
--- a/Documentation/input/yealink.txt
+++ b/Documentation/input/yealink.txt
@@ -134,7 +134,7 @@ Reading /sys/../lineX will return the format string with its current value:
888888888888
Linux Rocks!
-Writing to /sys/../lineX will set the coresponding LCD line.
+Writing to /sys/../lineX will set the corresponding LCD line.
- Excess characters are ignored.
- If less characters are written than allowed, the remaining digits are
unchanged.
diff --git a/Documentation/ioctl/cdrom.txt b/Documentation/ioctl/cdrom.txt
index 8ec32cc49eb1..62d4af44ec4a 100644
--- a/Documentation/ioctl/cdrom.txt
+++ b/Documentation/ioctl/cdrom.txt
@@ -735,7 +735,7 @@ CDROM_DISC_STATUS Get disc type, etc.
Ok, this is where problems start. The current interface for
the CDROM_DISC_STATUS ioctl is flawed. It makes the false
assumption that CDs are all CDS_DATA_1 or all CDS_AUDIO, etc.
- Unfortunatly, while this is often the case, it is also
+ Unfortunately, while this is often the case, it is also
very common for CDs to have some tracks with data, and some
tracks with audio. Just because I feel like it, I declare
the following to be the best way to cope. If the CD has
diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index 50f4eddf899c..4b3d6710c504 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -227,9 +227,9 @@ more details, with real examples.
be included in a library, lib.a.
All objects listed with lib-y are combined in a single
library for that directory.
- Objects that are listed in obj-y and additionaly listed in
- lib-y will not be included in the library, since they will anyway
- be accessible.
+ Objects that are listed in obj-y and additionally listed in
+ lib-y will not be included in the library, since they will
+ be accessible anyway.
For consistency, objects listed in lib-m will be included in lib.a.
Note that the same kbuild makefile may list files to be built-in
@@ -535,7 +535,7 @@ Both possibilities are described in the following.
Host programs can be made up based on composite objects.
The syntax used to define composite objects for host programs is
similar to the syntax used for kernel objects.
- $(<executeable>-objs) lists all objects used to link the final
+ $(<executable>-objs) lists all objects used to link the final
executable.
Example:
@@ -1022,7 +1022,7 @@ When kbuild executes, the following steps are followed (roughly):
In this example, there are two possible targets, requiring different
options to the linker. The linker options are specified using the
LDFLAGS_$@ syntax - one for each potential target.
- $(targets) are assinged all potential targets, by which kbuild knows
+ $(targets) are assigned all potential targets, by which kbuild knows
the targets and will:
1) check for commandline changes
2) delete target during make clean
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 67473849f20e..15e4fed127f6 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -557,9 +557,6 @@ and is between 256 and 4096 characters. It is defined in the file
floppy= [HW]
See Documentation/floppy.txt.
- ftape= [HW] Floppy Tape subsystem debugging options.
- See Documentation/ftape.txt.
-
gamecon.map[2|3]=
[HW,JOY] Multisystem joystick and NES/SNES/PSX pad
support via parallel port (up to 5 devices per port)
diff --git a/Documentation/keys.txt b/Documentation/keys.txt
index 3da586bc7859..60c665d9cfaa 100644
--- a/Documentation/keys.txt
+++ b/Documentation/keys.txt
@@ -304,7 +304,7 @@ about the status of the key service:
R Revoked
D Dead
Q Contributes to user's quota
- U Under contruction by callback to userspace
+ U Under construction by callback to userspace
N Negative key
This file must be enabled at kernel configuration time as it allows anyone
diff --git a/Documentation/laptop-mode.txt b/Documentation/laptop-mode.txt
index c487186eb2b9..6f639e3473af 100644
--- a/Documentation/laptop-mode.txt
+++ b/Documentation/laptop-mode.txt
@@ -121,7 +121,7 @@ contains the following options:
MAX_AGE:
Maximum time, in seconds, of hard drive spindown time that you are
-confortable with. Worst case, it's possible that you could lose this
+comfortable with. Worst case, it's possible that you could lose this
amount of work if your battery fails while you're in laptop mode.
MINIMUM_BATTERY_MINUTES:
@@ -235,7 +235,7 @@ It should be installed as /etc/default/laptop-mode on Debian, and as
--------------------CONFIG FILE BEGIN-------------------------------------------
# Maximum time, in seconds, of hard drive spindown time that you are
-# confortable with. Worst case, it's possible that you could lose this
+# comfortable with. Worst case, it's possible that you could lose this
# amount of work if your battery fails you while in laptop mode.
#MAX_AGE=600
@@ -350,7 +350,7 @@ fi
# set defaults instead:
# Maximum time, in seconds, of hard drive spindown time that you are
-# confortable with. Worst case, it's possible that you could lose this
+# comfortable with. Worst case, it's possible that you could lose this
# amount of work if your battery fails you while in laptop mode.
MAX_AGE=${MAX_AGE:-'600'}
@@ -699,7 +699,7 @@ ACPI integration
Dax Kelson submitted this so that the ACPI acpid daemon will
kick off the laptop_mode script and run hdparm. The part that
automatically disables laptop mode when the battery is low was
-writen by Jan Topinski.
+written by Jan Topinski.
-----------------/etc/acpi/events/ac_adapter BEGIN------------------------------
event=ac_adapter
diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt
index 7751704b6db1..58408dd023c7 100644
--- a/Documentation/memory-barriers.txt
+++ b/Documentation/memory-barriers.txt
@@ -212,7 +212,7 @@ There are some minimal guarantees that may be expected of a CPU:
STORE *X = c, d = LOAD *X
- (Loads and stores overlap if they are targetted at overlapping pieces of
+ (Loads and stores overlap if they are targeted at overlapping pieces of
memory).
And there are a number of things that _must_ or _must_not_ be assumed:
diff --git a/Documentation/networking/NAPI_HOWTO.txt b/Documentation/networking/NAPI_HOWTO.txt
index 93af3e87c65b..fb8dc6422a52 100644
--- a/Documentation/networking/NAPI_HOWTO.txt
+++ b/Documentation/networking/NAPI_HOWTO.txt
@@ -95,8 +95,8 @@ There are two types of event register ACK mechanisms.
Move all to dev->poll()
C) Ability to detect new work correctly.
-NAPI works by shutting down event interrupts when theres work and
-turning them on when theres none.
+NAPI works by shutting down event interrupts when there's work and
+turning them on when there's none.
New packets might show up in the small window while interrupts were being
re-enabled (refer to appendix 2). A packet might sneak in during the period
we are enabling interrupts. We only get to know about such a packet when the
@@ -114,7 +114,7 @@ Locking rules and environmental guarantees
only one CPU can pick the initial interrupt and hence the initial
netif_rx_schedule(dev);
- The core layer invokes devices to send packets in a round robin format.
-This implies receive is totaly lockless because of the guarantee only that
+This implies receive is totally lockless because of the guarantee that only
one CPU is executing it.
- contention can only be the result of some other CPU accessing the rx
ring. This happens only in close() and suspend() (when these methods
@@ -510,7 +510,7 @@ static int my_poll (struct net_device *dev, int *budget)
an interrupt will be generated */
goto done;
}
- /* done! at least thats what it looks like ;->
+ /* done! at least that's what it looks like ;->
if new packets came in after our last check on status bits
they'll be caught by the while check and we go back and clear them
since we havent exceeded our quota */
@@ -535,11 +535,11 @@ done:
* 1. it can race with disabling irqs in irq handler (which are done to
* schedule polls)
* 2. it can race with dis/enabling irqs in other poll threads
- * 3. if an irq raised after the begining of the outer beginning
- * loop(marked in the code above), it will be immediately
+ * 3. if an irq raised after the beginning of the outer beginning
+ * loop (marked in the code above), it will be immediately
* triggered here.
*
- * Summarizing: the logic may results in some redundant irqs both
+ * Summarizing: the logic may result in some redundant irqs both
* due to races in masking and due to too late acking of already
* processed irqs. The good news: no events are ever lost.
*/
@@ -601,7 +601,7 @@ a)
5) dev->close() and dev->suspend() issues
==========================================
-The driver writter neednt worry about this. The top net layer takes
+The driver writer needn't worry about this; the top net layer takes
care of it.
6) Adding new Stats to /proc
@@ -622,9 +622,9 @@ FC should be programmed to apply in the case when the system cant pull out
packets fast enough i.e send a pause only when you run out of rx buffers.
Note FC in itself is a good solution but we have found it to not be
much of a commodity feature (both in NICs and switches) and hence falls
-under the same category as using NIC based mitigation. Also experiments
-indicate that its much harder to resolve the resource allocation
-issue (aka lazy receiving that NAPI offers) and hence quantify its usefullness
+under the same category as using NIC based mitigation. Also, experiments
+indicate that it's much harder to resolve the resource allocation
+issue (aka lazy receiving that NAPI offers) and hence quantify its usefulness
proved harder. In any case, FC works even better with NAPI but is not
necessary.
@@ -678,10 +678,10 @@ routine:
CSR5 bit of interest is only the rx status.
If you look at the last if statement:
you just finished grabbing all the packets from the rx ring .. you check if
-status bit says theres more packets just in ... it says none; you then
+status bit says there are more packets just in ... it says none; you then
enable rx interrupts again; if a new packet just came in during this check,
we are counting that CSR5 will be set in that small window of opportunity
-and that by re-enabling interrupts, we would actually triger an interrupt
+and that by re-enabling interrupts, we would actually trigger an interrupt
to register the new packet for processing.
[The above description nay be very verbose, if you have better wording
diff --git a/Documentation/networking/cs89x0.txt b/Documentation/networking/cs89x0.txt
index 64896470e279..6387d3decf85 100644
--- a/Documentation/networking/cs89x0.txt
+++ b/Documentation/networking/cs89x0.txt
@@ -248,7 +248,7 @@ c) The driver's hardware probe routine is designed to avoid
with device probing. To avoid this behaviour, add one
to the `io=' module parameter. This doesn't actually change
the I/O address, but it is a flag to tell the driver
- topartially initialise the hardware before trying to
+ to partially initialise the hardware before trying to
identify the card. This could be dangerous if you are
not sure that there is a cs89x0 card at the provided address.
@@ -620,8 +620,8 @@ I/O Address Device IRQ Device
12 Mouse (PS/2)
Memory Address Device 13 Math Coprocessor
-------------- --------------------- 14 Hard Disk controller
-A000-BFFF EGA Graphics Adpater
-A000-C7FF VGA Graphics Adpater
+A000-BFFF EGA Graphics Adapter
+A000-C7FF VGA Graphics Adapter
B000-BFFF Mono Graphics Adapter
B800-BFFF Color Graphics Adapter
E000-FFFF AT BIOS
diff --git a/Documentation/networking/dccp.txt b/Documentation/networking/dccp.txt
index 74563b38ffd9..dda15886bcb5 100644
--- a/Documentation/networking/dccp.txt
+++ b/Documentation/networking/dccp.txt
@@ -19,21 +19,17 @@ for real time and multimedia traffic.
It has a base protocol and pluggable congestion control IDs (CCIDs).
-It is at draft RFC status and the homepage for DCCP as a protocol is at:
- http://www.icir.org/kohler/dcp/
+It is at experimental RFC status and the homepage for DCCP as a protocol is at:
+ http://www.read.cs.ucla.edu/dccp/
Missing features
================
The DCCP implementation does not currently have all the features that are in
-the draft RFC.
+the RFC.
-In particular the following are missing:
-- CCID2 support
-- feature negotiation
-
-When testing against other implementations it appears that elapsed time
-options are not coded compliant to the specification.
+The known bugs are at:
+ http://linux-net.osdl.org/index.php/TODO#DCCP
Socket options
==============
@@ -47,12 +43,70 @@ the socket will fall back to 0 (which means that no meaningful service code
is present). Connecting sockets set at most one service option; for
listening sockets, multiple service codes can be specified.
+DCCP_SOCKOPT_SEND_CSCOV and DCCP_SOCKOPT_RECV_CSCOV are used for setting the
+partial checksum coverage (RFC 4340, sec. 9.2). The default is that checksums
+always cover the entire packet and that only fully covered application data is
+accepted by the receiver. Hence, when using this feature on the sender, it must
+be enabled at the receiver, too with suitable choice of CsCov.
+
+DCCP_SOCKOPT_SEND_CSCOV sets the sender checksum coverage. Values in the
+ range 0..15 are acceptable. The default setting is 0 (full coverage),
+ values between 1..15 indicate partial coverage.
+DCCP_SOCKOPT_SEND_CSCOV is for the receiver and has a different meaning: it
+ sets a threshold, where again values 0..15 are acceptable. The default
+ of 0 means that all packets with a partial coverage will be discarded.
+ Values in the range 1..15 indicate that packets with minimally such a
+ coverage value are also acceptable. The higher the number, the more
+ restrictive this setting (see [RFC 4340, sec. 9.2.1]).
+
+Sysctl variables
+================
+Several DCCP default parameters can be managed by the following sysctls
+(sysctl net.dccp.default or /proc/sys/net/dccp/default):
+
+request_retries
+ The number of active connection initiation retries (the number of
+ Requests minus one) before timing out. In addition, it also governs
+ the behaviour of the other, passive side: this variable also sets
+ the number of times DCCP repeats sending a Response when the initial
+ handshake does not progress from RESPOND to OPEN (i.e. when no Ack
+ is received after the initial Request). This value should be greater
+ than 0, suggested is less than 10. Analogue of tcp_syn_retries.
+
+retries1
+ How often a DCCP Response is retransmitted until the listening DCCP
+ side considers its connecting peer dead. Analogue of tcp_retries1.
+
+retries2
+ The number of times a general DCCP packet is retransmitted. This has
+ importance for retransmitted acknowledgments and feature negotiation,
+ data packets are never retransmitted. Analogue of tcp_retries2.
+
+send_ndp = 1
+ Whether or not to send NDP count options (sec. 7.7.2).
+
+send_ackvec = 1
+ Whether or not to send Ack Vector options (sec. 11.5).
+
+ack_ratio = 2
+ The default Ack Ratio (sec. 11.3) to use.
+
+tx_ccid = 2
+ Default CCID for the sender-receiver half-connection.
+
+rx_ccid = 2
+ Default CCID for the receiver-sender half-connection.
+
+seq_window = 100
+ The initial sequence window (sec. 7.5.2).
+
+tx_qlen = 5
+ The size of the transmit buffer in packets. A value of 0 corresponds
+ to an unbounded transmit buffer.
+
Notes
=====
-SELinux does not yet have support for DCCP. You will need to turn it off or
-else you will get EACCES.
-
-DCCP does not travel through NAT successfully at present. This is because
-the checksum covers the psuedo-header as per TCP and UDP. It should be
-relatively trivial to add Linux NAT support for DCCP.
+DCCP does not travel through NAT successfully at present on many boxes. This is
+because the checksum covers the psuedo-header as per TCP and UDP. Linux NAT
+support for DCCP has been added.
diff --git a/Documentation/networking/e1000.txt b/Documentation/networking/e1000.txt
index 5c0a5cc03998..61b171cf5313 100644
--- a/Documentation/networking/e1000.txt
+++ b/Documentation/networking/e1000.txt
@@ -1,7 +1,7 @@
Linux* Base Driver for the Intel(R) PRO/1000 Family of Adapters
===============================================================
-November 15, 2005
+September 26, 2006
Contents
@@ -9,6 +9,7 @@ Contents
- In This Release
- Identifying Your Adapter
+- Building and Installation
- Command Line Parameters
- Speed and Duplex Configuration
- Additional Configurations
@@ -41,6 +42,9 @@ or later), lspci, and ifconfig to obtain the same information.
Instructions on updating ethtool can be found in the section "Additional
Configurations" later in this document.
+NOTE: The Intel(R) 82562v 10/100 Network Connection only provides 10/100
+support.
+
Identifying Your Adapter
========================
@@ -51,28 +55,27 @@ Driver ID Guide at:
http://support.intel.com/support/network/adapter/pro100/21397.htm
For the latest Intel network drivers for Linux, refer to the following
-website. In the search field, enter your adapter name or type, or use the
+website. In the search field, enter your adapter name or type, or use the
networking link on the left to search for your adapter:
http://downloadfinder.intel.com/scripts-df/support_intel.asp
-Command Line Parameters =======================
+Command Line Parameters
+=======================
If the driver is built as a module, the following optional parameters
-are used by entering them on the command line with the modprobe or insmod
-command using this syntax:
+are used by entering them on the command line with the modprobe command
+using this syntax:
modprobe e1000 [<option>=<VAL1>,<VAL2>,...]
- insmod e1000 [<option>=<VAL1>,<VAL2>,...]
-
For example, with two PRO/1000 PCI adapters, entering:
- insmod e1000 TxDescriptors=80,128
+ modprobe e1000 TxDescriptors=80,128
-loads the e1000 driver with 80 TX descriptors for the first adapter and 128
-TX descriptors for the second adapter.
+loads the e1000 driver with 80 TX descriptors for the first adapter and
+128 TX descriptors for the second adapter.
The default value for each parameter is generally the recommended setting,
unless otherwise noted.
@@ -87,7 +90,7 @@ NOTES: For more information about the AutoNeg, Duplex, and Speed
http://www.intel.com/design/network/applnots/ap450.htm
A descriptor describes a data buffer and attributes related to
- the data buffer. This information is accessed by the hardware.
+ the data buffer. This information is accessed by the hardware.
AutoNeg
@@ -96,9 +99,9 @@ AutoNeg
Valid Range: 0x01-0x0F, 0x20-0x2F
Default Value: 0x2F
-This parameter is a bit mask that specifies which speed and duplex
-settings the board advertises. When this parameter is used, the Speed
-and Duplex parameters must not be specified.
+This parameter is a bit-mask that specifies the speed and duplex settings
+advertised by the adapter. When this parameter is used, the Speed and
+Duplex parameters must not be specified.
NOTE: Refer to the Speed and Duplex section of this readme for more
information on the AutoNeg parameter.
@@ -110,14 +113,15 @@ Duplex
Valid Range: 0-2 (0=auto-negotiate, 1=half, 2=full)
Default Value: 0
-Defines the direction in which data is allowed to flow. Can be either
-one or two-directional. If both Duplex and the link partner are set to
-auto-negotiate, the board auto-detects the correct duplex. If the link
-partner is forced (either full or half), Duplex defaults to half-duplex.
+This defines the direction in which data is allowed to flow. Can be
+either one or two-directional. If both Duplex and the link partner are
+set to auto-negotiate, the board auto-detects the correct duplex. If the
+link partner is forced (either full or half), Duplex defaults to half-
+duplex.
FlowControl
-----------
+-----------
Valid Range: 0-3 (0=none, 1=Rx only, 2=Tx only, 3=Rx&Tx)
Default Value: Reads flow control settings from the EEPROM
@@ -127,57 +131,107 @@ to Ethernet PAUSE frames.
InterruptThrottleRate
---------------------
-(not supported on Intel 82542, 82543 or 82544-based adapters)
-Valid Range: 100-100000 (0=off, 1=dynamic)
-Default Value: 8000
-
-This value represents the maximum number of interrupts per second the
-controller generates. InterruptThrottleRate is another setting used in
-interrupt moderation. Dynamic mode uses a heuristic algorithm to adjust
-InterruptThrottleRate based on the current traffic load.
+(not supported on Intel(R) 82542, 82543 or 82544-based adapters)
+Valid Range: 0,1,3,100-100000 (0=off, 1=dynamic, 3=dynamic conservative)
+Default Value: 3
+
+The driver can limit the amount of interrupts per second that the adapter
+will generate for incoming packets. It does this by writing a value to the
+adapter that is based on the maximum amount of interrupts that the adapter
+will generate per second.
+
+Setting InterruptThrottleRate to a value greater or equal to 100
+will program the adapter to send out a maximum of that many interrupts
+per second, even if more packets have come in. This reduces interrupt
+load on the system and can lower CPU utilization under heavy load,
+but will increase latency as packets are not processed as quickly.
+
+The default behaviour of the driver previously assumed a static
+InterruptThrottleRate value of 8000, providing a good fallback value for
+all traffic types,but lacking in small packet performance and latency.
+The hardware can handle many more small packets per second however, and
+for this reason an adaptive interrupt moderation algorithm was implemented.
+
+Since 7.3.x, the driver has two adaptive modes (setting 1 or 3) in which
+it dynamically adjusts the InterruptThrottleRate value based on the traffic
+that it receives. After determining the type of incoming traffic in the last
+timeframe, it will adjust the InterruptThrottleRate to an appropriate value
+for that traffic.
+
+The algorithm classifies the incoming traffic every interval into
+classes. Once the class is determined, the InterruptThrottleRate value is
+adjusted to suit that traffic type the best. There are three classes defined:
+"Bulk traffic", for large amounts of packets of normal size; "Low latency",
+for small amounts of traffic and/or a significant percentage of small
+packets; and "Lowest latency", for almost completely small packets or
+minimal traffic.
+
+In dynamic conservative mode, the InterruptThrottleRate value is set to 4000
+for traffic that falls in class "Bulk traffic". If traffic falls in the "Low
+latency" or "Lowest latency" class, the InterruptThrottleRate is increased
+stepwise to 20000. This default mode is suitable for most applications.
+
+For situations where low latency is vital such as cluster or
+grid computing, the algorithm can reduce latency even more when
+InterruptThrottleRate is set to mode 1. In this mode, which operates
+the same as mode 3, the InterruptThrottleRate will be increased stepwise to
+70000 for traffic in class "Lowest latency".
+
+Setting InterruptThrottleRate to 0 turns off any interrupt moderation
+and may improve small packet latency, but is generally not suitable
+for bulk throughput traffic.
NOTE: InterruptThrottleRate takes precedence over the TxAbsIntDelay and
- RxAbsIntDelay parameters. In other words, minimizing the receive
+ RxAbsIntDelay parameters. In other words, minimizing the receive
and/or transmit absolute delays does not force the controller to
generate more interrupts than what the Interrupt Throttle Rate
allows.
-CAUTION: If you are using the Intel PRO/1000 CT Network Connection
+CAUTION: If you are using the Intel(R) PRO/1000 CT Network Connection
(controller 82547), setting InterruptThrottleRate to a value
greater than 75,000, may hang (stop transmitting) adapters
- under certain network conditions. If this occurs a NETDEV
- WATCHDOG message is logged in the system event log. In
+ under certain network conditions. If this occurs a NETDEV
+ WATCHDOG message is logged in the system event log. In
addition, the controller is automatically reset, restoring
- the network connection. To eliminate the potential for the
+ the network connection. To eliminate the potential for the
hang, ensure that InterruptThrottleRate is set no greater
than 75,000 and is not set to 0.
NOTE: When e1000 is loaded with default settings and multiple adapters
are in use simultaneously, the CPU utilization may increase non-
- linearly. In order to limit the CPU utilization without impacting
+ linearly. In order to limit the CPU utilization without impacting
the overall throughput, we recommend that you load the driver as
follows:
- insmod e1000.o InterruptThrottleRate=3000,3000,3000
+ modprobe e1000 InterruptThrottleRate=3000,3000,3000
This sets the InterruptThrottleRate to 3000 interrupts/sec for
- the first, second, and third instances of the driver. The range
+ the first, second, and third instances of the driver. The range
of 2000 to 3000 interrupts per second works on a majority of
systems and is a good starting point, but the optimal value will
- be platform-specific. If CPU utilization is not a concern, use
+ be platform-specific. If CPU utilization is not a concern, use
RX_POLLING (NAPI) and default driver settings.
+
RxDescriptors
-------------
Valid Range: 80-256 for 82542 and 82543-based adapters
80-4096 for all other supported adapters
Default Value: 256
-This value specifies the number of receive descriptors allocated by the
-driver. Increasing this value allows the driver to buffer more incoming
-packets. Each descriptor is 16 bytes. A receive buffer is also
-allocated for each descriptor and is 2048.
+This value specifies the number of receive buffer descriptors allocated
+by the driver. Increasing this value allows the driver to buffer more
+incoming packets, at the expense of increased system memory utilization.
+
+Each descriptor is 16 bytes. A receive buffer is also allocated for each
+descriptor and can be either 2048, 4096, 8192, or 16384 bytes, depending
+on the MTU setting. The maximum MTU size is 16110.
+
+NOTE: MTU designates the frame size. It only needs to be set for Jumbo
+ Frames. Depending on the available system resources, the request
+ for a higher number of receive descriptors may be denied. In this
+ case, use a lower number.
RxIntDelay
@@ -187,17 +241,17 @@ Default Value: 0
This value delays the generation of receive interrupts in units of 1.024
microseconds. Receive interrupt reduction can improve CPU efficiency if
-properly tuned for specific network traffic. Increasing this value adds
+properly tuned for specific network traffic. Increasing this value adds
extra latency to frame reception and can end up decreasing the throughput
-of TCP traffic. If the system is reporting dropped receives, this value
+of TCP traffic. If the system is reporting dropped receives, this value
may be set too high, causing the driver to run out of available receive
descriptors.
CAUTION: When setting RxIntDelay to a value other than 0, adapters may
- hang (stop transmitting) under certain network conditions. If
+ hang (stop transmitting) under certain network conditions. If
this occurs a NETDEV WATCHDOG message is logged in the system
- event log. In addition, the controller is automatically reset,
- restoring the network connection. To eliminate the potential
+ event log. In addition, the controller is automatically reset,
+ restoring the network connection. To eliminate the potential
for the hang ensure that RxIntDelay is set to 0.
@@ -208,7 +262,7 @@ Valid Range: 0-65535 (0=off)
Default Value: 128
This value, in units of 1.024 microseconds, limits the delay in which a
-receive interrupt is generated. Useful only if RxIntDelay is non-zero,
+receive interrupt is generated. Useful only if RxIntDelay is non-zero,
this value ensures that an interrupt is generated after the initial
packet is received within the set amount of time. Proper tuning,
along with RxIntDelay, may improve traffic throughput in specific network
@@ -222,9 +276,9 @@ Valid Settings: 0, 10, 100, 1000
Default Value: 0 (auto-negotiate at all supported speeds)
Speed forces the line speed to the specified value in megabits per second
-(Mbps). If this parameter is not specified or is set to 0 and the link
+(Mbps). If this parameter is not specified or is set to 0 and the link
partner is set to auto-negotiate, the board will auto-detect the correct
-speed. Duplex should also be set when Speed is set to either 10 or 100.
+speed. Duplex should also be set when Speed is set to either 10 or 100.
TxDescriptors
@@ -234,7 +288,7 @@ Valid Range: 80-256 for 82542 and 82543-based adapters
Default Value: 256
This value is the number of transmit descriptors allocated by the driver.
-Increasing this value allows the driver to queue more transmits. Each
+Increasing this value allows the driver to queue more transmits. Each
descriptor is 16 bytes.
NOTE: Depending on the available system resources, the request for a
@@ -248,8 +302,8 @@ Valid Range: 0-65535 (0=off)
Default Value: 64
This value delays the generation of transmit interrupts in units of
-1.024 microseconds. Transmit interrupt reduction can improve CPU
-efficiency if properly tuned for specific network traffic. If the
+1.024 microseconds. Transmit interrupt reduction can improve CPU
+efficiency if properly tuned for specific network traffic. If the
system is reporting dropped transmits, this value may be set too high
causing the driver to run out of available transmit descriptors.
@@ -261,7 +315,7 @@ Valid Range: 0-65535 (0=off)
Default Value: 64
This value, in units of 1.024 microseconds, limits the delay in which a
-transmit interrupt is generated. Useful only if TxIntDelay is non-zero,
+transmit interrupt is generated. Useful only if TxIntDelay is non-zero,
this value ensures that an interrupt is generated after the initial
packet is sent on the wire within the set amount of time. Proper tuning,
along with TxIntDelay, may improve traffic throughput in specific
@@ -288,15 +342,15 @@ fiber interface board only links at 1000 Mbps full-duplex.
For copper-based boards, the keywords interact as follows:
- The default operation is auto-negotiate. The board advertises all
+ The default operation is auto-negotiate. The board advertises all
supported speed and duplex combinations, and it links at the highest
common speed and duplex mode IF the link partner is set to auto-negotiate.
If Speed = 1000, limited auto-negotiation is enabled and only 1000 Mbps
is advertised (The 1000BaseT spec requires auto-negotiation.)
- If Speed = 10 or 100, then both Speed and Duplex should be set. Auto-
- negotiation is disabled, and the AutoNeg parameter is ignored. Partner
+ If Speed = 10 or 100, then both Speed and Duplex should be set. Auto-
+ negotiation is disabled, and the AutoNeg parameter is ignored. Partner
SHOULD also be forced.
The AutoNeg parameter is used when more control is required over the
@@ -304,7 +358,7 @@ auto-negotiation process. It should be used when you wish to control which
speed and duplex combinations are advertised during the auto-negotiation
process.
-The parameter may be specified as either a decimal or hexidecimal value as
+The parameter may be specified as either a decimal or hexadecimal value as
determined by the bitmap below.
Bit position 7 6 5 4 3 2 1 0
@@ -337,20 +391,19 @@ Additional Configurations
Configuring the Driver on Different Distributions
-------------------------------------------------
-
Configuring a network driver to load properly when the system is started
- is distribution dependent. Typically, the configuration process involves
+ is distribution dependent. Typically, the configuration process involves
adding an alias line to /etc/modules.conf or /etc/modprobe.conf as well
- as editing other system startup scripts and/or configuration files. Many
+ as editing other system startup scripts and/or configuration files. Many
popular Linux distributions ship with tools to make these changes for you.
To learn the proper way to configure a network device for your system,
- refer to your distribution documentation. If during this process you are
+ refer to your distribution documentation. If during this process you are
asked for the driver or module name, the name for the Linux Base Driver
- for the Intel PRO/1000 Family of Adapters is e1000.
+ for the Intel(R) PRO/1000 Family of Adapters is e1000.
As an example, if you install the e1000 driver for two PRO/1000 adapters
(eth0 and eth1) and set the speed and duplex to 10full and 100half, add
- the following to modules.conf or modprobe.conf:
+ the following to modules.conf or or modprobe.conf:
alias eth0 e1000
alias eth1 e1000
@@ -358,9 +411,8 @@ Additional Configurations
Viewing Link Messages
---------------------
-
Link messages will not be displayed to the console if the distribution is
- restricting system messages. In order to see network driver link messages
+ restricting system messages. In order to see network driver link messages
on your console, set dmesg to eight by entering the following:
dmesg -n 8
@@ -369,11 +421,9 @@ Additional Configurations
Jumbo Frames
------------
-
- The driver supports Jumbo Frames for all adapters except 82542 and
- 82573-based adapters. Jumbo Frames support is enabled by changing the
- MTU to a value larger than the default of 1500. Use the ifconfig command
- to increase the MTU size. For example:
+ Jumbo Frames support is enabled by changing the MTU to a value larger than
+ the default of 1500. Use the ifconfig command to increase the MTU size.
+ For example:
ifconfig eth<x> mtu 9000 up
@@ -390,26 +440,49 @@ Additional Configurations
- To enable Jumbo Frames, increase the MTU size on the interface beyond
1500.
- - The maximum MTU setting for Jumbo Frames is 16110. This value coincides
+
+ - The maximum MTU setting for Jumbo Frames is 16110. This value coincides
with the maximum Jumbo Frames size of 16128.
+
- Using Jumbo Frames at 10 or 100 Mbps may result in poor performance or
loss of link.
+
- Some Intel gigabit adapters that support Jumbo Frames have a frame size
limit of 9238 bytes, with a corresponding MTU size limit of 9216 bytes.
- The adapters with this limitation are based on the Intel 82571EB and
- 82572EI controllers, which correspond to these product names:
- Intel® PRO/1000 PT Dual Port Server Adapter
- Intel® PRO/1000 PF Dual Port Server Adapter
- Intel® PRO/1000 PT Server Adapter
- Intel® PRO/1000 PT Desktop Adapter
- Intel® PRO/1000 PF Server Adapter
-
- - The Intel PRO/1000 PM Network Connection does not support jumbo frames.
+ The adapters with this limitation are based on the Intel(R) 82571EB,
+ 82572EI, 82573L and 80003ES2LAN controller. These correspond to the
+ following product names:
+ Intel(R) PRO/1000 PT Server Adapter
+ Intel(R) PRO/1000 PT Desktop Adapter
+ Intel(R) PRO/1000 PT Network Connection
+ Intel(R) PRO/1000 PT Dual Port Server Adapter
+ Intel(R) PRO/1000 PT Dual Port Network Connection
+ Intel(R) PRO/1000 PF Server Adapter
+ Intel(R) PRO/1000 PF Network Connection
+ Intel(R) PRO/1000 PF Dual Port Server Adapter
+ Intel(R) PRO/1000 PB Server Connection
+ Intel(R) PRO/1000 PL Network Connection
+ Intel(R) PRO/1000 EB Network Connection with I/O Acceleration
+ Intel(R) PRO/1000 EB Backplane Connection with I/O Acceleration
+ Intel(R) PRO/1000 PT Quad Port Server Adapter
+
+ - Adapters based on the Intel(R) 82542 and 82573V/E controller do not
+ support Jumbo Frames. These correspond to the following product names:
+ Intel(R) PRO/1000 Gigabit Server Adapter
+ Intel(R) PRO/1000 PM Network Connection
+
+ - The following adapters do not support Jumbo Frames:
+ Intel(R) 82562V 10/100 Network Connection
+ Intel(R) 82566DM Gigabit Network Connection
+ Intel(R) 82566DC Gigabit Network Connection
+ Intel(R) 82566MM Gigabit Network Connection
+ Intel(R) 82566MC Gigabit Network Connection
+ Intel(R) 82562GT 10/100 Network Connection
+ Intel(R) 82562G 10/100 Network Connection
Ethtool
-------
-
The driver utilizes the ethtool interface for driver configuration and
diagnostics, as well as displaying statistical information. Ethtool
version 1.6 or later is required for this functionality.
@@ -417,15 +490,14 @@ Additional Configurations
The latest release of ethtool can be found from
http://sourceforge.net/projects/gkernel.
- NOTE: Ethtool 1.6 only supports a limited set of ethtool options. Support
+ NOTE: Ethtool 1.6 only supports a limited set of ethtool options. Support
for a more complete ethtool feature set can be enabled by upgrading
ethtool to ethtool-1.8.1.
Enabling Wake on LAN* (WoL)
---------------------------
-
- WoL is configured through the Ethtool* utility. Ethtool is included with
- all versions of Red Hat after Red Hat 7.2. For other Linux distributions,
+ WoL is configured through the Ethtool* utility. Ethtool is included with
+ all versions of Red Hat after Red Hat 7.2. For other Linux distributions,
download and install Ethtool from the following website:
http://sourceforge.net/projects/gkernel.
@@ -436,11 +508,17 @@ Additional Configurations
For this driver version, in order to enable WoL, the e1000 driver must be
loaded when shutting down or rebooting the system.
+ Wake On LAN is only supported on port A for the following devices:
+ Intel(R) PRO/1000 PT Dual Port Network Connection
+ Intel(R) PRO/1000 PT Dual Port Server Connection
+ Intel(R) PRO/1000 PT Dual Port Server Adapter
+ Intel(R) PRO/1000 PF Dual Port Server Adapter
+ Intel(R) PRO/1000 PT Quad Port Server Adapter
+
NAPI
----
-
- NAPI (Rx polling mode) is supported in the e1000 driver. NAPI is enabled
- or disabled based on the configuration of the kernel. To override
+ NAPI (Rx polling mode) is supported in the e1000 driver. NAPI is enabled
+ or disabled based on the configuration of the kernel. To override
the default, use the following compile-time flags.
To enable NAPI, compile the driver module, passing in a configuration option:
@@ -457,88 +535,105 @@ Additional Configurations
Known Issues
============
- Jumbo Frames System Requirement
- -------------------------------
-
- Memory allocation failures have been observed on Linux systems with 64 MB
- of RAM or less that are running Jumbo Frames. If you are using Jumbo
- Frames, your system may require more than the advertised minimum
- requirement of 64 MB of system memory.
-
- Performance Degradation with Jumbo Frames
- -----------------------------------------
-
- Degradation in throughput performance may be observed in some Jumbo frames
- environments. If this is observed, increasing the application's socket
- buffer size and/or increasing the /proc/sys/net/ipv4/tcp_*mem entry values
- may help. See the specific application manual and
- /usr/src/linux*/Documentation/
- networking/ip-sysctl.txt for more details.
-
- Jumbo frames on Foundry BigIron 8000 switch
- -------------------------------------------
- There is a known issue using Jumbo frames when connected to a Foundry
- BigIron 8000 switch. This is a 3rd party limitation. If you experience
- loss of packets, lower the MTU size.
-
- Multiple Interfaces on Same Ethernet Broadcast Network
- ------------------------------------------------------
-
- Due to the default ARP behavior on Linux, it is not possible to have
- one system on two IP networks in the same Ethernet broadcast domain
- (non-partitioned switch) behave as expected. All Ethernet interfaces
- will respond to IP traffic for any IP address assigned to the system.
- This results in unbalanced receive traffic.
-
- If you have multiple interfaces in a server, either turn on ARP
- filtering by entering:
-
- echo 1 > /proc/sys/net/ipv4/conf/all/arp_filter
- (this only works if your kernel's version is higher than 2.4.5),
-
- NOTE: This setting is not saved across reboots. The configuration
- change can be made permanent by adding the line:
- net.ipv4.conf.all.arp_filter = 1
- to the file /etc/sysctl.conf
-
- or,
-
- install the interfaces in separate broadcast domains (either in
- different switches or in a switch partitioned to VLANs).
-
- 82541/82547 can't link or are slow to link with some link partners
- -----------------------------------------------------------------
-
- There is a known compatibility issue with 82541/82547 and some
- low-end switches where the link will not be established, or will
- be slow to establish. In particular, these switches are known to
- be incompatible with 82541/82547:
-
- Planex FXG-08TE
- I-O Data ETG-SH8
-
- To workaround this issue, the driver can be compiled with an override
- of the PHY's master/slave setting. Forcing master or forcing slave
- mode will improve time-to-link.
-
- # make EXTRA_CFLAGS=-DE1000_MASTER_SLAVE=<n>
-
- Where <n> is:
-
- 0 = Hardware default
- 1 = Master mode
- 2 = Slave mode
- 3 = Auto master/slave
-
- Disable rx flow control with ethtool
- ------------------------------------
-
- In order to disable receive flow control using ethtool, you must turn
- off auto-negotiation on the same command line.
-
- For example:
-
- ethtool -A eth? autoneg off rx off
+Dropped Receive Packets on Half-duplex 10/100 Networks
+------------------------------------------------------
+If you have an Intel PCI Express adapter running at 10mbps or 100mbps, half-
+duplex, you may observe occasional dropped receive packets. There are no
+workarounds for this problem in this network configuration. The network must
+be updated to operate in full-duplex, and/or 1000mbps only.
+
+Jumbo Frames System Requirement
+-------------------------------
+Memory allocation failures have been observed on Linux systems with 64 MB
+of RAM or less that are running Jumbo Frames. If you are using Jumbo
+Frames, your system may require more than the advertised minimum
+requirement of 64 MB of system memory.
+
+Performance Degradation with Jumbo Frames
+-----------------------------------------
+Degradation in throughput performance may be observed in some Jumbo frames
+environments. If this is observed, increasing the application's socket
+buffer size and/or increasing the /proc/sys/net/ipv4/tcp_*mem entry values
+may help. See the specific application manual and
+/usr/src/linux*/Documentation/
+networking/ip-sysctl.txt for more details.
+
+Jumbo Frames on Foundry BigIron 8000 switch
+-------------------------------------------
+There is a known issue using Jumbo frames when connected to a Foundry
+BigIron 8000 switch. This is a 3rd party limitation. If you experience
+loss of packets, lower the MTU size.
+
+Allocating Rx Buffers when Using Jumbo Frames
+---------------------------------------------
+Allocating Rx buffers when using Jumbo Frames on 2.6.x kernels may fail if
+the available memory is heavily fragmented. This issue may be seen with PCI-X
+adapters or with packet split disabled. This can be reduced or eliminated
+by changing the amount of available memory for receive buffer allocation, by
+increasing /proc/sys/vm/min_free_kbytes.
+
+Multiple Interfaces on Same Ethernet Broadcast Network
+------------------------------------------------------
+Due to the default ARP behavior on Linux, it is not possible to have
+one system on two IP networks in the same Ethernet broadcast domain
+(non-partitioned switch) behave as expected. All Ethernet interfaces
+will respond to IP traffic for any IP address assigned to the system.
+This results in unbalanced receive traffic.
+
+If you have multiple interfaces in a server, either turn on ARP
+filtering by entering:
+
+ echo 1 > /proc/sys/net/ipv4/conf/all/arp_filter
+(this only works if your kernel's version is higher than 2.4.5),
+
+NOTE: This setting is not saved across reboots. The configuration
+change can be made permanent by adding the line:
+ net.ipv4.conf.all.arp_filter = 1
+to the file /etc/sysctl.conf
+
+ or,
+
+install the interfaces in separate broadcast domains (either in
+different switches or in a switch partitioned to VLANs).
+
+82541/82547 can't link or are slow to link with some link partners
+-----------------------------------------------------------------
+There is a known compatibility issue with 82541/82547 and some
+low-end switches where the link will not be established, or will
+be slow to establish. In particular, these switches are known to
+be incompatible with 82541/82547:
+
+ Planex FXG-08TE
+ I-O Data ETG-SH8
+
+To workaround this issue, the driver can be compiled with an override
+of the PHY's master/slave setting. Forcing master or forcing slave
+mode will improve time-to-link.
+
+ # make CFLAGS_EXTRA=-DE1000_MASTER_SLAVE=<n>
+
+Where <n> is:
+
+ 0 = Hardware default
+ 1 = Master mode
+ 2 = Slave mode
+ 3 = Auto master/slave
+
+Disable rx flow control with ethtool
+------------------------------------
+In order to disable receive flow control using ethtool, you must turn
+off auto-negotiation on the same command line.
+
+For example:
+
+ ethtool -A eth? autoneg off rx off
+
+Unplugging network cable while ethtool -p is running
+----------------------------------------------------
+In kernel versions 2.5.50 and later (including 2.6 kernel), unplugging
+the network cable while ethtool -p is running will cause the system to
+become unresponsive to keyboard commands, except for control-alt-delete.
+Restarting the system appears to be the only remedy.
Support
@@ -548,24 +643,10 @@ For general information, go to the Intel support website at:
http://support.intel.com
- or the Intel Wired Networking project hosted by Sourceforge at:
+or the Intel Wired Networking project hosted by Sourceforge at:
http://sourceforge.net/projects/e1000
If an issue is identified with the released source code on the supported
kernel with a supported adapter, email the specific information related
-to the issue to e1000-devel@lists.sourceforge.net
-
-
-License
-=======
-
-This software program is released under the terms of a license agreement
-between you ('Licensee') and Intel. Do not use or load this software or any
-associated materials (collectively, the 'Software') until you have carefully
-read the full terms and conditions of the file COPYING located in this software
-package. By loading or using the Software, you agree to the terms of this
-Agreement. If you do not agree with the terms of this Agreement, do not
-install or use the Software.
-
-* Other names and brands may be claimed as the property of others.
+to the issue to e1000-devel@lists.sf.net
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index fd3c0c012351..a0f6842368c3 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -101,6 +101,11 @@ inet_peer_gc_maxtime - INTEGER
TCP variables:
+somaxconn - INTEGER
+ Limit of socket listen() backlog, known in userspace as SOMAXCONN.
+ Defaults to 128. See also tcp_max_syn_backlog for additional tuning
+ for TCP sockets.
+
tcp_abc - INTEGER
Controls Appropriate Byte Count (ABC) defined in RFC3465.
ABC is a way of increasing congestion window (cwnd) more slowly
@@ -112,48 +117,51 @@ tcp_abc - INTEGER
of two segments to compensate for delayed acknowledgments.
Default: 0 (off)
-tcp_syn_retries - INTEGER
- Number of times initial SYNs for an active TCP connection attempt
- will be retransmitted. Should not be higher than 255. Default value
- is 5, which corresponds to ~180seconds.
+tcp_abort_on_overflow - BOOLEAN
+ If listening service is too slow to accept new connections,
+ reset them. Default state is FALSE. It means that if overflow
+ occurred due to a burst, connection will recover. Enable this
+ option _only_ if you are really sure that listening daemon
+ cannot be tuned to accept connections faster. Enabling this
+ option can harm clients of your server.
-tcp_synack_retries - INTEGER
- Number of times SYNACKs for a passive TCP connection attempt will
- be retransmitted. Should not be higher than 255. Default value
- is 5, which corresponds to ~180seconds.
+tcp_adv_win_scale - INTEGER
+ Count buffering overhead as bytes/2^tcp_adv_win_scale
+ (if tcp_adv_win_scale > 0) or bytes-bytes/2^(-tcp_adv_win_scale),
+ if it is <= 0.
+ Default: 2
-tcp_keepalive_time - INTEGER
- How often TCP sends out keepalive messages when keepalive is enabled.
- Default: 2hours.
+tcp_allowed_congestion_control - STRING
+ Show/set the congestion control choices available to non-privileged
+ processes. The list is a subset of those listed in
+ tcp_available_congestion_control.
+ Default is "reno" and the default setting (tcp_congestion_control).
-tcp_keepalive_probes - INTEGER
- How many keepalive probes TCP sends out, until it decides that the
- connection is broken. Default value: 9.
+tcp_app_win - INTEGER
+ Reserve max(window/2^tcp_app_win, mss) of window for application
+ buffer. Value 0 is special, it means that nothing is reserved.
+ Default: 31
-tcp_keepalive_intvl - INTEGER
- How frequently the probes are send out. Multiplied by
- tcp_keepalive_probes it is time to kill not responding connection,
- after probes started. Default value: 75sec i.e. connection
- will be aborted after ~11 minutes of retries.
+tcp_available_congestion_control - STRING
+ Shows the available congestion control choices that are registered.
+ More congestion control algorithms may be available as modules,
+ but not loaded.
-tcp_retries1 - INTEGER
- How many times to retry before deciding that something is wrong
- and it is necessary to report this suspicion to network layer.
- Minimal RFC value is 3, it is default, which corresponds
- to ~3sec-8min depending on RTO.
+tcp_congestion_control - STRING
+ Set the congestion control algorithm to be used for new
+ connections. The algorithm "reno" is always available, but
+ additional choices may be available based on kernel configuration.
+ Default is set as part of kernel configuration.
-tcp_retries2 - INTEGER
- How may times to retry before killing alive TCP connection.
- RFC1122 says that the limit should be longer than 100 sec.
- It is too small number. Default value 15 corresponds to ~13-30min
- depending on RTO.
+tcp_dsack - BOOLEAN
+ Allows TCP to send "duplicate" SACKs.
-tcp_orphan_retries - INTEGER
- How may times to retry before killing TCP connection, closed
- by our side. Default value 7 corresponds to ~50sec-16min
- depending on RTO. If you machine is loaded WEB server,
- you should think about lowering this value, such sockets
- may consume significant resources. Cf. tcp_max_orphans.
+tcp_ecn - BOOLEAN
+ Enable Explicit Congestion Notification in TCP.
+
+tcp_fack - BOOLEAN
+ Enable FACK congestion avoidance and fast retransmission.
+ The value is not used, if tcp_sack is not enabled.
tcp_fin_timeout - INTEGER
Time to hold socket in state FIN-WAIT-2, if it was closed
@@ -166,24 +174,33 @@ tcp_fin_timeout - INTEGER
because they eat maximum 1.5K of memory, but they tend
to live longer. Cf. tcp_max_orphans.
-tcp_max_tw_buckets - INTEGER
- Maximal number of timewait sockets held by system simultaneously.
- If this number is exceeded time-wait socket is immediately destroyed
- and warning is printed. This limit exists only to prevent
- simple DoS attacks, you _must_ not lower the limit artificially,
- but rather increase it (probably, after increasing installed memory),
- if network conditions require more than default value.
+tcp_frto - BOOLEAN
+ Enables F-RTO, an enhanced recovery algorithm for TCP retransmission
+ timeouts. It is particularly beneficial in wireless environments
+ where packet loss is typically due to random radio interference
+ rather than intermediate router congestion.
-tcp_tw_recycle - BOOLEAN
- Enable fast recycling TIME-WAIT sockets. Default value is 0.
- It should not be changed without advice/request of technical
- experts.
+tcp_keepalive_time - INTEGER
+ How often TCP sends out keepalive messages when keepalive is enabled.
+ Default: 2hours.
-tcp_tw_reuse - BOOLEAN
- Allow to reuse TIME-WAIT sockets for new connections when it is
- safe from protocol viewpoint. Default value is 0.
- It should not be changed without advice/request of technical
- experts.
+tcp_keepalive_probes - INTEGER
+ How many keepalive probes TCP sends out, until it decides that the
+ connection is broken. Default value: 9.
+
+tcp_keepalive_intvl - INTEGER
+ How frequently the probes are send out. Multiplied by
+ tcp_keepalive_probes it is time to kill not responding connection,
+ after probes started. Default value: 75sec i.e. connection
+ will be aborted after ~11 minutes of retries.
+
+tcp_low_latency - BOOLEAN
+ If set, the TCP stack makes decisions that prefer lower
+ latency as opposed to higher throughput. By default, this
+ option is not set meaning that higher throughput is preferred.
+ An example of an application where this default should be
+ changed would be a Beowulf compute cluster.
+ Default: 0
tcp_max_orphans - INTEGER
Maximal number of TCP sockets not attached to any user file handle,
@@ -197,41 +214,6 @@ tcp_max_orphans - INTEGER
more aggressively. Let me to remind again: each orphan eats
up to ~64K of unswappable memory.
-tcp_abort_on_overflow - BOOLEAN
- If listening service is too slow to accept new connections,
- reset them. Default state is FALSE. It means that if overflow
- occurred due to a burst, connection will recover. Enable this
- option _only_ if you are really sure that listening daemon
- cannot be tuned to accept connections faster. Enabling this
- option can harm clients of your server.
-
-tcp_syncookies - BOOLEAN
- Only valid when the kernel was compiled with CONFIG_SYNCOOKIES
- Send out syncookies when the syn backlog queue of a socket
- overflows. This is to prevent against the common 'syn flood attack'
- Default: FALSE
-
- Note, that syncookies is fallback facility.
- It MUST NOT be used to help highly loaded servers to stand
- against legal connection rate. If you see synflood warnings
- in your logs, but investigation shows that they occur
- because of overload with legal connections, you should tune
- another parameters until this warning disappear.
- See: tcp_max_syn_backlog, tcp_synack_retries, tcp_abort_on_overflow.
-
- syncookies seriously violate TCP protocol, do not allow
- to use TCP extensions, can result in serious degradation
- of some services (f.e. SMTP relaying), visible not by you,
- but your clients and relays, contacting you. While you see
- synflood warnings in logs not being really flooded, your server
- is seriously misconfigured.
-
-tcp_stdurg - BOOLEAN
- Use the Host requirements interpretation of the TCP urg pointer field.
- Most hosts use the older BSD interpretation, so if you turn this on
- Linux might not communicate correctly with them.
- Default: FALSE
-
tcp_max_syn_backlog - INTEGER
Maximal number of remembered connection requests, which are
still did not receive an acknowledgment from connecting client.
@@ -239,24 +221,34 @@ tcp_max_syn_backlog - INTEGER
and 128 for low memory machines. If server suffers of overload,
try to increase this number.
-tcp_window_scaling - BOOLEAN
- Enable window scaling as defined in RFC1323.
+tcp_max_tw_buckets - INTEGER
+ Maximal number of timewait sockets held by system simultaneously.
+ If this number is exceeded time-wait socket is immediately destroyed
+ and warning is printed. This limit exists only to prevent
+ simple DoS attacks, you _must_ not lower the limit artificially,
+ but rather increase it (probably, after increasing installed memory),
+ if network conditions require more than default value.
-tcp_timestamps - BOOLEAN
- Enable timestamps as defined in RFC1323.
+tcp_mem - vector of 3 INTEGERs: min, pressure, max
+ min: below this number of pages TCP is not bothered about its
+ memory appetite.
-tcp_sack - BOOLEAN
- Enable select acknowledgments (SACKS).
+ pressure: when amount of memory allocated by TCP exceeds this number
+ of pages, TCP moderates its memory consumption and enters memory
+ pressure mode, which is exited when memory consumption falls
+ under "min".
-tcp_fack - BOOLEAN
- Enable FACK congestion avoidance and fast retransmission.
- The value is not used, if tcp_sack is not enabled.
+ max: number of pages allowed for queueing by all TCP sockets.
-tcp_dsack - BOOLEAN
- Allows TCP to send "duplicate" SACKs.
+ Defaults are calculated at boot time from amount of available
+ memory.
-tcp_ecn - BOOLEAN
- Enable Explicit Congestion Notification in TCP.
+tcp_orphan_retries - INTEGER
+ How may times to retry before killing TCP connection, closed
+ by our side. Default value 7 corresponds to ~50sec-16min
+ depending on RTO. If you machine is loaded WEB server,
+ you should think about lowering this value, such sockets
+ may consume significant resources. Cf. tcp_max_orphans.
tcp_reordering - INTEGER
Maximal reordering of packets in a TCP stream.
@@ -267,20 +259,23 @@ tcp_retrans_collapse - BOOLEAN
On retransmit try to send bigger packets to work around bugs in
certain TCP stacks.
-tcp_wmem - vector of 3 INTEGERs: min, default, max
- min: Amount of memory reserved for send buffers for TCP socket.
- Each TCP socket has rights to use it due to fact of its birth.
- Default: 4K
+tcp_retries1 - INTEGER
+ How many times to retry before deciding that something is wrong
+ and it is necessary to report this suspicion to network layer.
+ Minimal RFC value is 3, it is default, which corresponds
+ to ~3sec-8min depending on RTO.
- default: Amount of memory allowed for send buffers for TCP socket
- by default. This value overrides net.core.wmem_default used
- by other protocols, it is usually lower than net.core.wmem_default.
- Default: 16K
+tcp_retries2 - INTEGER
+ How may times to retry before killing alive TCP connection.
+ RFC1122 says that the limit should be longer than 100 sec.
+ It is too small number. Default value 15 corresponds to ~13-30min
+ depending on RTO.
- max: Maximal amount of memory allowed for automatically selected
- send buffers for TCP socket. This value does not override
- net.core.wmem_max, "static" selection via SO_SNDBUF does not use this.
- Default: 128K
+tcp_rfc1337 - BOOLEAN
+ If set, the TCP stack behaves conforming to RFC1337. If unset,
+ we are not conforming to RFC, but prevent TCP TIME_WAIT
+ assassination.
+ Default: 0
tcp_rmem - vector of 3 INTEGERs: min, default, max
min: Minimal size of receive buffer used by TCP sockets.
@@ -299,67 +294,91 @@ tcp_rmem - vector of 3 INTEGERs: min, default, max
net.core.rmem_max, "static" selection via SO_RCVBUF does not use this.
Default: 87380*2 bytes.
-tcp_mem - vector of 3 INTEGERs: min, pressure, max
- min: below this number of pages TCP is not bothered about its
- memory appetite.
+tcp_sack - BOOLEAN
+ Enable select acknowledgments (SACKS).
- pressure: when amount of memory allocated by TCP exceeds this number
- of pages, TCP moderates its memory consumption and enters memory
- pressure mode, which is exited when memory consumption falls
- under "min".
+tcp_slow_start_after_idle - BOOLEAN
+ If set, provide RFC2861 behavior and time out the congestion
+ window after an idle period. An idle period is defined at
+ the current RTO. If unset, the congestion window will not
+ be timed out after an idle period.
+ Default: 1
- max: number of pages allowed for queueing by all TCP sockets.
+tcp_stdurg - BOOLEAN
+ Use the Host requirements interpretation of the TCP urg pointer field.
+ Most hosts use the older BSD interpretation, so if you turn this on
+ Linux might not communicate correctly with them.
+ Default: FALSE
- Defaults are calculated at boot time from amount of available
- memory.
+tcp_synack_retries - INTEGER
+ Number of times SYNACKs for a passive TCP connection attempt will
+ be retransmitted. Should not be higher than 255. Default value
+ is 5, which corresponds to ~180seconds.
-tcp_app_win - INTEGER
- Reserve max(window/2^tcp_app_win, mss) of window for application
- buffer. Value 0 is special, it means that nothing is reserved.
- Default: 31
+tcp_syncookies - BOOLEAN
+ Only valid when the kernel was compiled with CONFIG_SYNCOOKIES
+ Send out syncookies when the syn backlog queue of a socket
+ overflows. This is to prevent against the common 'syn flood attack'
+ Default: FALSE
-tcp_adv_win_scale - INTEGER
- Count buffering overhead as bytes/2^tcp_adv_win_scale
- (if tcp_adv_win_scale > 0) or bytes-bytes/2^(-tcp_adv_win_scale),
- if it is <= 0.
- Default: 2
+ Note, that syncookies is fallback facility.
+ It MUST NOT be used to help highly loaded servers to stand
+ against legal connection rate. If you see synflood warnings
+ in your logs, but investigation shows that they occur
+ because of overload with legal connections, you should tune
+ another parameters until this warning disappear.
+ See: tcp_max_syn_backlog, tcp_synack_retries, tcp_abort_on_overflow.
-tcp_rfc1337 - BOOLEAN
- If set, the TCP stack behaves conforming to RFC1337. If unset,
- we are not conforming to RFC, but prevent TCP TIME_WAIT
- assassination.
- Default: 0
+ syncookies seriously violate TCP protocol, do not allow
+ to use TCP extensions, can result in serious degradation
+ of some services (f.e. SMTP relaying), visible not by you,
+ but your clients and relays, contacting you. While you see
+ synflood warnings in logs not being really flooded, your server
+ is seriously misconfigured.
-tcp_low_latency - BOOLEAN
- If set, the TCP stack makes decisions that prefer lower
- latency as opposed to higher throughput. By default, this
- option is not set meaning that higher throughput is preferred.
- An example of an application where this default should be
- changed would be a Beowulf compute cluster.
- Default: 0
+tcp_syn_retries - INTEGER
+ Number of times initial SYNs for an active TCP connection attempt
+ will be retransmitted. Should not be higher than 255. Default value
+ is 5, which corresponds to ~180seconds.
+
+tcp_timestamps - BOOLEAN
+ Enable timestamps as defined in RFC1323.
tcp_tso_win_divisor - INTEGER
- This allows control over what percentage of the congestion window
- can be consumed by a single TSO frame.
- The setting of this parameter is a choice between burstiness and
- building larger TSO frames.
- Default: 3
+ This allows control over what percentage of the congestion window
+ can be consumed by a single TSO frame.
+ The setting of this parameter is a choice between burstiness and
+ building larger TSO frames.
+ Default: 3
-tcp_frto - BOOLEAN
- Enables F-RTO, an enhanced recovery algorithm for TCP retransmission
- timeouts. It is particularly beneficial in wireless environments
- where packet loss is typically due to random radio interference
- rather than intermediate router congestion.
+tcp_tw_recycle - BOOLEAN
+ Enable fast recycling TIME-WAIT sockets. Default value is 0.
+ It should not be changed without advice/request of technical
+ experts.
-tcp_congestion_control - STRING
- Set the congestion control algorithm to be used for new
- connections. The algorithm "reno" is always available, but
- additional choices may be available based on kernel configuration.
+tcp_tw_reuse - BOOLEAN
+ Allow to reuse TIME-WAIT sockets for new connections when it is
+ safe from protocol viewpoint. Default value is 0.
+ It should not be changed without advice/request of technical
+ experts.
-somaxconn - INTEGER
- Limit of socket listen() backlog, known in userspace as SOMAXCONN.
- Defaults to 128. See also tcp_max_syn_backlog for additional tuning
- for TCP sockets.
+tcp_window_scaling - BOOLEAN
+ Enable window scaling as defined in RFC1323.
+
+tcp_wmem - vector of 3 INTEGERs: min, default, max
+ min: Amount of memory reserved for send buffers for TCP socket.
+ Each TCP socket has rights to use it due to fact of its birth.
+ Default: 4K
+
+ default: Amount of memory allowed for send buffers for TCP socket
+ by default. This value overrides net.core.wmem_default used
+ by other protocols, it is usually lower than net.core.wmem_default.
+ Default: 16K
+
+ max: Maximal amount of memory allowed for automatically selected
+ send buffers for TCP socket. This value does not override
+ net.core.wmem_max, "static" selection via SO_SNDBUF does not use this.
+ Default: 128K
tcp_workaround_signed_windows - BOOLEAN
If set, assume no receipt of a window scaling option means the
@@ -368,13 +387,6 @@ tcp_workaround_signed_windows - BOOLEAN
not receive a window scaling option from them.
Default: 0
-tcp_slow_start_after_idle - BOOLEAN
- If set, provide RFC2861 behavior and time out the congestion
- window after an idle period. An idle period is defined at
- the current RTO. If unset, the congestion window will not
- be timed out after an idle period.
- Default: 1
-
CIPSOv4 Variables:
cipso_cache_enable - BOOLEAN
@@ -974,4 +986,3 @@ no_cong_thresh FIXME
slot_timeout FIXME
warn_noreply_time FIXME
-$Id: ip-sysctl.txt,v 1.20 2001/12/13 09:00:18 davem Exp $
diff --git a/Documentation/networking/iphase.txt b/Documentation/networking/iphase.txt
index 493203a080a8..55eac4a784e2 100644
--- a/Documentation/networking/iphase.txt
+++ b/Documentation/networking/iphase.txt
@@ -81,7 +81,7 @@ Installation
1M. The RAM size decides the number of buffers and buffer size. The default
size and number of buffers are set as following:
- Totol Rx RAM Tx RAM Rx Buf Tx Buf Rx buf Tx buf
+ Total Rx RAM Tx RAM Rx Buf Tx Buf Rx buf Tx buf
RAM size size size size size cnt cnt
-------- ------ ------ ------ ------ ------ ------
128K 64K 64K 10K 10K 6 6
diff --git a/Documentation/networking/packet_mmap.txt b/Documentation/networking/packet_mmap.txt
index 12a008a5c221..5a232d946be3 100644
--- a/Documentation/networking/packet_mmap.txt
+++ b/Documentation/networking/packet_mmap.txt
@@ -284,7 +284,7 @@ the necessary memory, so normally limits can be reached.
-------------------
If you check the source code you will see that what I draw here as a frame
-is not only the link level frame. At the begining of each frame there is a
+is not only the link level frame. At the beginning of each frame there is a
header called struct tpacket_hdr used in PACKET_MMAP to hold link level's frame
meta information like timestamp. So what we draw here a frame it's really
the following (from include/linux/if_packet.h):
diff --git a/Documentation/networking/phy.txt b/Documentation/networking/phy.txt
index 29ccae409031..0bc95eab1512 100644
--- a/Documentation/networking/phy.txt
+++ b/Documentation/networking/phy.txt
@@ -1,7 +1,7 @@
-------
PHY Abstraction Layer
-(Updated 2005-07-21)
+(Updated 2006-11-30)
Purpose
@@ -97,11 +97,12 @@ Letting the PHY Abstraction Layer do Everything
Next, you need to know the device name of the PHY connected to this device.
The name will look something like, "phy0:0", where the first number is the
- bus id, and the second is the PHY's address on that bus.
+ bus id, and the second is the PHY's address on that bus. Typically,
+ the bus is responsible for making its ID unique.
Now, to connect, just call this function:
- phydev = phy_connect(dev, phy_name, &adjust_link, flags);
+ phydev = phy_connect(dev, phy_name, &adjust_link, flags, interface);
phydev is a pointer to the phy_device structure which represents the PHY. If
phy_connect is successful, it will return the pointer. dev, here, is the
@@ -115,6 +116,10 @@ Letting the PHY Abstraction Layer do Everything
This is useful if the system has put hardware restrictions on
the PHY/controller, of which the PHY needs to be aware.
+ interface is a u32 which specifies the connection type used
+ between the controller and the PHY. Examples are GMII, MII,
+ RGMII, and SGMII. For a full list, see include/linux/phy.h
+
Now just make sure that phydev->supported and phydev->advertising have any
values pruned from them which don't make sense for your controller (a 10/100
controller may be connected to a gigabit capable PHY, so you would need to
@@ -191,7 +196,7 @@ Doing it all yourself
start, or disables then frees them for stop.
struct phy_device * phy_attach(struct net_device *dev, const char *phy_id,
- u32 flags);
+ u32 flags, phy_interface_t interface);
Attaches a network device to a particular PHY, binding the PHY to a generic
driver if none was found during bus initialization. Passes in
diff --git a/Documentation/networking/pktgen.txt b/Documentation/networking/pktgen.txt
index c8eee23be8c0..c6cf4a3c16e0 100644
--- a/Documentation/networking/pktgen.txt
+++ b/Documentation/networking/pktgen.txt
@@ -63,8 +63,8 @@ Current:
Result: OK: 13101142(c12220741+d880401) usec, 10000000 (60byte,0frags)
763292pps 390Mb/sec (390805504bps) errors: 39664
-Confguring threads and devices
-==============================
+Configuring threads and devices
+================================
This is done via the /proc interface easiest done via pgset in the scripts
Examples:
@@ -116,7 +116,7 @@ Examples:
there must be no spaces between the
arguments. Leading zeros are required.
Do not set the bottom of stack bit,
- thats done automatically. If you do
+ that's done automatically. If you do
set the bottom of stack bit, that
indicates that you want to randomly
generate that address and the flag
diff --git a/Documentation/networking/proc_net_tcp.txt b/Documentation/networking/proc_net_tcp.txt
index 59cb915c3713..5e21f7cb6383 100644
--- a/Documentation/networking/proc_net_tcp.txt
+++ b/Documentation/networking/proc_net_tcp.txt
@@ -25,7 +25,7 @@ up into 3 parts because of the length of the line):
1000 0 54165785 4 cd1e6040 25 4 27 3 -1
| | | | | | | | | |--> slow start size threshold,
- | | | | | | | | | or -1 if the treshold
+ | | | | | | | | | or -1 if the threshold
| | | | | | | | | is >= 0xFFFF
| | | | | | | | |----> sending congestion window
| | | | | | | |-------> (ack.quick<<1)|ack.pingpong
diff --git a/Documentation/networking/sk98lin.txt b/Documentation/networking/sk98lin.txt
index 4e1cc745ec63..8590a954df1d 100644
--- a/Documentation/networking/sk98lin.txt
+++ b/Documentation/networking/sk98lin.txt
@@ -346,7 +346,7 @@ Possible modes:
depending on the load of the system. If the driver detects that the
system load is too high, the driver tries to shield the system against
too much network load by enabling interrupt moderation. If - at a later
- time - the CPU utilizaton decreases again (or if the network load is
+ time - the CPU utilization decreases again (or if the network load is
negligible) the interrupt moderation will automatically be disabled.
Interrupt moderation should be used when the driver has to handle one or more
diff --git a/Documentation/networking/slicecom.txt b/Documentation/networking/slicecom.txt
index 2f04c9267f89..32d3b916afad 100644
--- a/Documentation/networking/slicecom.txt
+++ b/Documentation/networking/slicecom.txt
@@ -126,7 +126,7 @@ comx0/boardnum - board number of the SliceCom in the PC (using the 'natural'
Though the options below are to be set on a single interface, they apply to the
whole board. The restriction, to use them on 'UP' interfaces, is because the
-command sequence below could lead to unpredicable results.
+command sequence below could lead to unpredictable results.
# echo 0 >boardnum
# echo internal >clock_source
diff --git a/Documentation/networking/udplite.txt b/Documentation/networking/udplite.txt
new file mode 100644
index 000000000000..dd6f46b83dab
--- /dev/null
+++ b/Documentation/networking/udplite.txt
@@ -0,0 +1,281 @@
+ ===========================================================================
+ The UDP-Lite protocol (RFC 3828)
+ ===========================================================================
+
+
+ UDP-Lite is a Standards-Track IETF transport protocol whose characteristic
+ is a variable-length checksum. This has advantages for transport of multimedia
+ (video, VoIP) over wireless networks, as partly damaged packets can still be
+ fed into the codec instead of being discarded due to a failed checksum test.
+
+ This file briefly describes the existing kernel support and the socket API.
+ For in-depth information, you can consult:
+
+ o The UDP-Lite Homepage: http://www.erg.abdn.ac.uk/users/gerrit/udp-lite/
+ Fom here you can also download some example application source code.
+
+ o The UDP-Lite HOWTO on
+ http://www.erg.abdn.ac.uk/users/gerrit/udp-lite/files/UDP-Lite-HOWTO.txt
+
+ o The Wireshark UDP-Lite WiKi (with capture files):
+ http://wiki.wireshark.org/Lightweight_User_Datagram_Protocol
+
+ o The Protocol Spec, RFC 3828, http://www.ietf.org/rfc/rfc3828.txt
+
+
+ I) APPLICATIONS
+
+ Several applications have been ported successfully to UDP-Lite. Ethereal
+ (now called wireshark) has UDP-Litev4/v6 support by default. The tarball on
+
+ http://www.erg.abdn.ac.uk/users/gerrit/udp-lite/files/udplite_linux.tar.gz
+
+ has source code for several v4/v6 client-server and network testing examples.
+
+ Porting applications to UDP-Lite is straightforward: only socket level and
+ IPPROTO need to be changed; senders additionally set the checksum coverage
+ length (default = header length = 8). Details are in the next section.
+
+
+ II) PROGRAMMING API
+
+ UDP-Lite provides a connectionless, unreliable datagram service and hence
+ uses the same socket type as UDP. In fact, porting from UDP to UDP-Lite is
+ very easy: simply add `IPPROTO_UDPLITE' as the last argument of the socket(2)
+ call so that the statement looks like:
+
+ s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDPLITE);
+
+ or, respectively,
+
+ s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDPLITE);
+
+ With just the above change you are able to run UDP-Lite services or connect
+ to UDP-Lite servers. The kernel will assume that you are not interested in
+ using partial checksum coverage and so emulate UDP mode (full coverage).
+
+ To make use of the partial checksum coverage facilities requires setting a
+ single socket option, which takes an integer specifying the coverage length:
+
+ * Sender checksum coverage: UDPLITE_SEND_CSCOV
+
+ For example,
+
+ int val = 20;
+ setsockopt(s, SOL_UDPLITE, UDPLITE_SEND_CSCOV, &val, sizeof(int));
+
+ sets the checksum coverage length to 20 bytes (12b data + 8b header).
+ Of each packet only the first 20 bytes (plus the pseudo-header) will be
+ checksummed. This is useful for RTP applications which have a 12-byte
+ base header.
+
+
+ * Receiver checksum coverage: UDPLITE_RECV_CSCOV
+
+ This option is the receiver-side analogue. It is truly optional, i.e. not
+ required to enable traffic with partial checksum coverage. Its function is
+ that of a traffic filter: when enabled, it instructs the kernel to drop
+ all packets which have a coverage _less_ than this value. For example, if
+ RTP and UDP headers are to be protected, a receiver can enforce that only
+ packets with a minimum coverage of 20 are admitted:
+
+ int min = 20;
+ setsockopt(s, SOL_UDPLITE, UDPLITE_RECV_CSCOV, &min, sizeof(int));
+
+ The calls to getsockopt(2) are analogous. Being an extension and not a stand-
+ alone protocol, all socket options known from UDP can be used in exactly the
+ same manner as before, e.g. UDP_CORK or UDP_ENCAP.
+
+ A detailed discussion of UDP-Lite checksum coverage options is in section IV.
+
+
+ III) HEADER FILES
+
+ The socket API requires support through header files in /usr/include:
+
+ * /usr/include/netinet/in.h
+ to define IPPROTO_UDPLITE
+
+ * /usr/include/netinet/udplite.h
+ for UDP-Lite header fields and protocol constants
+
+ For testing purposes, the following can serve as a `mini' header file:
+
+ #define IPPROTO_UDPLITE 136
+ #define SOL_UDPLITE 136
+ #define UDPLITE_SEND_CSCOV 10
+ #define UDPLITE_RECV_CSCOV 11
+
+ Ready-made header files for various distros are in the UDP-Lite tarball.
+
+
+ IV) KERNEL BEHAVIOUR WITH REGARD TO THE VARIOUS SOCKET OPTIONS
+
+ To enable debugging messages, the log level need to be set to 8, as most
+ messages use the KERN_DEBUG level (7).
+
+ 1) Sender Socket Options
+
+ If the sender specifies a value of 0 as coverage length, the module
+ assumes full coverage, transmits a packet with coverage length of 0
+ and according checksum. If the sender specifies a coverage < 8 and
+ different from 0, the kernel assumes 8 as default value. Finally,
+ if the specified coverage length exceeds the packet length, the packet
+ length is used instead as coverage length.
+
+ 2) Receiver Socket Options
+
+ The receiver specifies the minimum value of the coverage length it
+ is willing to accept. A value of 0 here indicates that the receiver
+ always wants the whole of the packet covered. In this case, all
+ partially covered packets are dropped and an error is logged.
+
+ It is not possible to specify illegal values (<0 and <8); in these
+ cases the default of 8 is assumed.
+
+ All packets arriving with a coverage value less than the specified
+ threshold are discarded, these events are also logged.
+
+ 3) Disabling the Checksum Computation
+
+ On both sender and receiver, checksumming will always be performed
+ and can not be disabled using SO_NO_CHECK. Thus
+
+ setsockopt(sockfd, SOL_SOCKET, SO_NO_CHECK, ... );
+
+ will always will be ignored, while the value of
+
+ getsockopt(sockfd, SOL_SOCKET, SO_NO_CHECK, &value, ...);
+
+ is meaningless (as in TCP). Packets with a zero checksum field are
+ illegal (cf. RFC 3828, sec. 3.1) will be silently discarded.
+
+ 4) Fragmentation
+
+ The checksum computation respects both buffersize and MTU. The size
+ of UDP-Lite packets is determined by the size of the send buffer. The
+ minimum size of the send buffer is 2048 (defined as SOCK_MIN_SNDBUF
+ in include/net/sock.h), the default value is configurable as
+ net.core.wmem_default or via setting the SO_SNDBUF socket(7)
+ option. The maximum upper bound for the send buffer is determined
+ by net.core.wmem_max.
+
+ Given a payload size larger than the send buffer size, UDP-Lite will
+ split the payload into several individual packets, filling up the
+ send buffer size in each case.
+
+ The precise value also depends on the interface MTU. The interface MTU,
+ in turn, may trigger IP fragmentation. In this case, the generated
+ UDP-Lite packet is split into several IP packets, of which only the
+ first one contains the L4 header.
+
+ The send buffer size has implications on the checksum coverage length.
+ Consider the following example:
+
+ Payload: 1536 bytes Send Buffer: 1024 bytes
+ MTU: 1500 bytes Coverage Length: 856 bytes
+
+ UDP-Lite will ship the 1536 bytes in two separate packets:
+
+ Packet 1: 1024 payload + 8 byte header + 20 byte IP header = 1052 bytes
+ Packet 2: 512 payload + 8 byte header + 20 byte IP header = 540 bytes
+
+ The coverage packet covers the UDP-Lite header and 848 bytes of the
+ payload in the first packet, the second packet is fully covered. Note
+ that for the second packet, the coverage length exceeds the packet
+ length. The kernel always re-adjusts the coverage length to the packet
+ length in such cases.
+
+ As an example of what happens when one UDP-Lite packet is split into
+ several tiny fragments, consider the following example.
+
+ Payload: 1024 bytes Send buffer size: 1024 bytes
+ MTU: 300 bytes Coverage length: 575 bytes
+
+ +-+-----------+--------------+--------------+--------------+
+ |8| 272 | 280 | 280 | 280 |
+ +-+-----------+--------------+--------------+--------------+
+ 280 560 840 1032
+ ^
+ *****checksum coverage*************
+
+ The UDP-Lite module generates one 1032 byte packet (1024 + 8 byte
+ header). According to the interface MTU, these are split into 4 IP
+ packets (280 byte IP payload + 20 byte IP header). The kernel module
+ sums the contents of the entire first two packets, plus 15 bytes of
+ the last packet before releasing the fragments to the IP module.
+
+ To see the analogous case for IPv6 fragmentation, consider a link
+ MTU of 1280 bytes and a write buffer of 3356 bytes. If the checksum
+ coverage is less than 1232 bytes (MTU minus IPv6/fragment header
+ lengths), only the first fragment needs to be considered. When using
+ larger checksum coverage lengths, each eligible fragment needs to be
+ checksummed. Suppose we have a checksum coverage of 3062. The buffer
+ of 3356 bytes will be split into the following fragments:
+
+ Fragment 1: 1280 bytes carrying 1232 bytes of UDP-Lite data
+ Fragment 2: 1280 bytes carrying 1232 bytes of UDP-Lite data
+ Fragment 3: 948 bytes carrying 900 bytes of UDP-Lite data
+
+ The first two fragments have to be checksummed in full, of the last
+ fragment only 598 (= 3062 - 2*1232) bytes are checksummed.
+
+ While it is important that such cases are dealt with correctly, they
+ are (annoyingly) rare: UDP-Lite is designed for optimising multimedia
+ performance over wireless (or generally noisy) links and thus smaller
+ coverage lenghts are likely to be expected.
+
+
+ V) UDP-LITE RUNTIME STATISTICS AND THEIR MEANING
+
+ Exceptional and error conditions are logged to syslog at the KERN_DEBUG
+ level. Live statistics about UDP-Lite are available in /proc/net/snmp
+ and can (with newer versions of netstat) be viewed using
+
+ netstat -svu
+
+ This displays UDP-Lite statistics variables, whose meaning is as follows.
+
+ InDatagrams: Total number of received datagrams.
+
+ NoPorts: Number of packets received to an unknown port.
+ These cases are counted separately (not as InErrors).
+
+ InErrors: Number of erroneous UDP-Lite packets. Errors include:
+ * internal socket queue receive errors
+ * packet too short (less than 8 bytes or stated
+ coverage length exceeds received length)
+ * xfrm4_policy_check() returned with error
+ * application has specified larger min. coverage
+ length than that of incoming packet
+ * checksum coverage violated
+ * bad checksum
+
+ OutDatagrams: Total number of sent datagrams.
+
+ These statistics derive from the UDP MIB (RFC 2013).
+
+
+ VI) IPTABLES
+
+ There is packet match support for UDP-Lite as well as support for the LOG target.
+ If you copy and paste the following line into /etc/protcols,
+
+ udplite 136 UDP-Lite # UDP-Lite [RFC 3828]
+
+ then
+ iptables -A INPUT -p udplite -j LOG
+
+ will produce logging output to syslog. Dropping and rejecting packets also works.
+
+
+ VII) MAINTAINER ADDRESS
+
+ The UDP-Lite patch was developed at
+ University of Aberdeen
+ Electronics Research Group
+ Department of Engineering
+ Fraser Noble Building
+ Aberdeen AB24 3UE; UK
+ The current maintainer is Gerrit Renker, <gerrit@erg.abdn.ac.uk>. Initial
+ code was developed by William Stanislaus, <william@erg.abdn.ac.uk>.
diff --git a/Documentation/networking/wan-router.txt b/Documentation/networking/wan-router.txt
index 0cf654147634..653978dcea7f 100644
--- a/Documentation/networking/wan-router.txt
+++ b/Documentation/networking/wan-router.txt
@@ -412,7 +412,7 @@ beta-2.1.4 Jul 2000 o Dynamic interface configuration:
beta3-2.1.4 Jul 2000 o X25 M_BIT Problem fix.
o Added the Multi-Port PPP
- Updated utilites for the Multi-Port PPP.
+ Updated utilities for the Multi-Port PPP.
2.1.4 Aut 2000
o In X25API:
@@ -444,13 +444,13 @@ beta1-2.1.5 Nov 15 2000
o Cpipemon
- Added set FT1 commands to the cpipemon. Thus CSU/DSU
- configuraiton can be performed using cpipemon.
+ configuration can be performed using cpipemon.
All systems that cannot run cfgft1 GUI utility should
use cpipemon to configure the on board CSU/DSU.
o Keyboard Led Monitor/Debugger
- - A new utilty /usr/sbin/wpkbdmon uses keyboard leds
+ - A new utility /usr/sbin/wpkbdmon uses keyboard leds
to convey operational statistic information of the
Sangoma WANPIPE cards.
NUM_LOCK = Line State (On=connected, Off=disconnected)
@@ -464,7 +464,7 @@ beta1-2.1.5 Nov 15 2000
- Appropriate number of devices are dynamically loaded
based on the number of Sangoma cards found.
- Note: The kernel configuraiton option
+ Note: The kernel configuration option
CONFIG_WANPIPE_CARDS has been taken out.
o Fixed the Frame Relay and Chdlc network interfaces so they are
diff --git a/Documentation/networking/xfrm_sync.txt b/Documentation/networking/xfrm_sync.txt
index 8be626f7c0b8..d7aac9dedeb4 100644
--- a/Documentation/networking/xfrm_sync.txt
+++ b/Documentation/networking/xfrm_sync.txt
@@ -47,10 +47,13 @@ aevent_id structure looks like:
struct xfrm_aevent_id {
struct xfrm_usersa_id sa_id;
+ xfrm_address_t saddr;
__u32 flags;
+ __u32 reqid;
};
-xfrm_usersa_id in this message layout identifies the SA.
+The unique SA is identified by the combination of xfrm_usersa_id,
+reqid and saddr.
flags are used to indicate different things. The possible
flags are:
diff --git a/Documentation/pnp.txt b/Documentation/pnp.txt
index 9ff966bf76e6..28037aa1846c 100644
--- a/Documentation/pnp.txt
+++ b/Documentation/pnp.txt
@@ -184,7 +184,7 @@ static const struct pnp_id pnp_dev_table[] = {
Please note that the character 'X' can be used as a wild card in the function
portion (last four characters).
ex:
- /* Unkown PnP modems */
+ /* Unknown PnP modems */
{ "PNPCXXX", UNKNOWN_DEV },
Supported PnP card IDs can optionally be defined.
diff --git a/Documentation/power/pci.txt b/Documentation/power/pci.txt
index 24edf25b3bb7..c750f9f2e76e 100644
--- a/Documentation/power/pci.txt
+++ b/Documentation/power/pci.txt
@@ -153,7 +153,7 @@ Description:
events, which is implicit if it doesn't even support it in the first
place).
- Note that the PMC Register in the device's PM Capabilties has a bitmask
+ Note that the PMC Register in the device's PM Capabilities has a bitmask
of the states it supports generating PME# from. D3hot is bit 3 and
D3cold is bit 4. So, while a value of 4 as the state may not seem
semantically correct, it is.
@@ -268,7 +268,7 @@ to wake the system up. (However, it is possible that a device may support
some non-standard way of generating a wake event on sleep.)
Bits 15:11 of the PMC (Power Mgmt Capabilities) Register in a device's
-PM Capabilties describe what power states the device supports generating a
+PM Capabilities describe what power states the device supports generating a
wake event from:
+------------------+
diff --git a/Documentation/power/states.txt b/Documentation/power/states.txt
index 3e5e5d3ff419..0931a330d362 100644
--- a/Documentation/power/states.txt
+++ b/Documentation/power/states.txt
@@ -62,7 +62,7 @@ setup via another operating system for it to use. Despite the
inconvenience, this method requires minimal work by the kernel, since
the firmware will also handle restoring memory contents on resume.
-If the kernel is responsible for persistantly saving state, a mechanism
+If the kernel is responsible for persistently saving state, a mechanism
called 'swsusp' (Swap Suspend) is used to write memory contents to
free swap space. swsusp has some restrictive requirements, but should
work in most cases. Some, albeit outdated, documentation can be found
diff --git a/Documentation/power/swsusp.txt b/Documentation/power/swsusp.txt
index 9ea2208b43b5..e635e6f1e316 100644
--- a/Documentation/power/swsusp.txt
+++ b/Documentation/power/swsusp.txt
@@ -153,7 +153,7 @@ add:
If the thread is needed for writing the image to storage, you should
instead set the PF_NOFREEZE process flag when creating the thread (and
-be very carefull).
+be very careful).
Q: What is the difference between "platform", "shutdown" and
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index 27b457c09729..4ac2d641fcb6 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -33,13 +33,13 @@
- Change version 16 format to always align
property data to 4 bytes. Since tokens are
already aligned, that means no specific
- required alignement between property size
+ required alignment between property size
and property data. The old style variable
alignment would make it impossible to do
"simple" insertion of properties using
memove (thanks Milton for
noticing). Updated kernel patch as well
- - Correct a few more alignement constraints
+ - Correct a few more alignment constraints
- Add a chapter about the device-tree
compiler and the textural representation of
the tree that can be "compiled" by dtc.
@@ -854,7 +854,7 @@ address which can extend beyond that limit.
console device if any. Typically, if you have serial devices on
your board, you may want to put the full path to the one set as
the default console in the firmware here, for the kernel to pick
- it up as it's own default console. If you look at the funciton
+ it up as its own default console. If you look at the function
set_preferred_console() in arch/ppc64/kernel/setup.c, you'll see
that the kernel tries to find out the default console and has
knowledge of various types like 8250 serial ports. You may want
@@ -1124,7 +1124,7 @@ should have the following properties:
- interrupt-parent : contains the phandle of the interrupt
controller which handles interrupts for this device
- interrupts : a list of tuples representing the interrupt
- number and the interrupt sense and level for each interupt
+ number and the interrupt sense and level for each interrupt
for this device.
This information is used by the kernel to build the interrupt table
diff --git a/Documentation/robust-futex-ABI.txt b/Documentation/robust-futex-ABI.txt
index 8529a17ffaa1..535f69fab45f 100644
--- a/Documentation/robust-futex-ABI.txt
+++ b/Documentation/robust-futex-ABI.txt
@@ -170,7 +170,7 @@ any point:
1) the 'head' pointer or an subsequent linked list pointer
is not a valid address of a user space word
2) the calculated location of the 'lock word' (address plus
- 'offset') is not the valud address of a 32 bit user space
+ 'offset') is not the valid address of a 32 bit user space
word
3) if the list contains more than 1 million (subject to
future kernel configuration changes) elements.
diff --git a/Documentation/robust-futexes.txt b/Documentation/robust-futexes.txt
index 76e8064b8c3a..0a9446a53bd1 100644
--- a/Documentation/robust-futexes.txt
+++ b/Documentation/robust-futexes.txt
@@ -181,7 +181,7 @@ for new threads, without the need of another syscall.]
So there is virtually zero overhead for tasks not using robust futexes,
and even for robust futex users, there is only one extra syscall per
thread lifetime, and the cleanup operation, if it happens, is fast and
-straightforward. The kernel doesnt have any internal distinction between
+straightforward. The kernel doesn't have any internal distinction between
robust and normal futexes.
If a futex is found to be held at exit time, the kernel sets the
diff --git a/Documentation/rtc.txt b/Documentation/rtc.txt
index 2a58f985795a..7cf1ec5bcdd3 100644
--- a/Documentation/rtc.txt
+++ b/Documentation/rtc.txt
@@ -1,12 +1,49 @@
- Real Time Clock Driver for Linux
- ================================
+ Real Time Clock (RTC) Drivers for Linux
+ =======================================
+
+When Linux developers talk about a "Real Time Clock", they usually mean
+something that tracks wall clock time and is battery backed so that it
+works even with system power off. Such clocks will normally not track
+the local time zone or daylight savings time -- unless they dual boot
+with MS-Windows -- but will instead be set to Coordinated Universal Time
+(UTC, formerly "Greenwich Mean Time").
+
+The newest non-PC hardware tends to just count seconds, like the time(2)
+system call reports, but RTCs also very commonly represent time using
+the Gregorian calendar and 24 hour time, as reported by gmtime(3).
+
+Linux has two largely-compatible userspace RTC API families you may
+need to know about:
+
+ * /dev/rtc ... is the RTC provided by PC compatible systems,
+ so it's not very portable to non-x86 systems.
+
+ * /dev/rtc0, /dev/rtc1 ... are part of a framework that's
+ supported by a wide variety of RTC chips on all systems.
+
+Programmers need to understand that the PC/AT functionality is not
+always available, and some systems can do much more. That is, the
+RTCs use the same API to make requests in both RTC frameworks (using
+different filenames of course), but the hardware may not offer the
+same functionality. For example, not every RTC is hooked up to an
+IRQ, so they can't all issue alarms; and where standard PC RTCs can
+only issue an alarm up to 24 hours in the future, other hardware may
+be able to schedule one any time in the upcoming century.
+
+
+ Old PC/AT-Compatible driver: /dev/rtc
+ --------------------------------------
All PCs (even Alpha machines) have a Real Time Clock built into them.
Usually they are built into the chipset of the computer, but some may
actually have a Motorola MC146818 (or clone) on the board. This is the
clock that keeps the date and time while your computer is turned off.
+ACPI has standardized that MC146818 functionality, and extended it in
+a few ways (enabling longer alarm periods, and wake-from-hibernate).
+That functionality is NOT exposed in the old driver.
+
However it can also be used to generate signals from a slow 2Hz to a
relatively fast 8192Hz, in increments of powers of two. These signals
are reported by interrupt number 8. (Oh! So *that* is what IRQ 8 is
@@ -63,223 +100,331 @@ Rather than write 50 pages describing the ioctl() and so on, it is
perhaps more useful to include a small test program that demonstrates
how to use them, and demonstrates the features of the driver. This is
probably a lot more useful to people interested in writing applications
-that will be using this driver.
+that will be using this driver. See the code at the end of this document.
+
+(The original /dev/rtc driver was written by Paul Gortmaker.)
+
+
+ New portable "RTC Class" drivers: /dev/rtcN
+ --------------------------------------------
+
+Because Linux supports many non-ACPI and non-PC platforms, some of which
+have more than one RTC style clock, it needed a more portable solution
+than expecting a single battery-backed MC146818 clone on every system.
+Accordingly, a new "RTC Class" framework has been defined. It offers
+three different userspace interfaces:
+
+ * /dev/rtcN ... much the same as the older /dev/rtc interface
+
+ * /sys/class/rtc/rtcN ... sysfs attributes support readonly
+ access to some RTC attributes.
+
+ * /proc/driver/rtc ... the first RTC (rtc0) may expose itself
+ using a procfs interface. More information is (currently) shown
+ here than through sysfs.
+
+The RTC Class framework supports a wide variety of RTCs, ranging from those
+integrated into embeddable system-on-chip (SOC) processors to discrete chips
+using I2C, SPI, or some other bus to communicate with the host CPU. There's
+even support for PC-style RTCs ... including the features exposed on newer PCs
+through ACPI.
+
+The new framework also removes the "one RTC per system" restriction. For
+example, maybe the low-power battery-backed RTC is a discrete I2C chip, but
+a high functionality RTC is integrated into the SOC. That system might read
+the system clock from the discrete RTC, but use the integrated one for all
+other tasks, because of its greater functionality.
+
+The ioctl() calls supported by /dev/rtc are also supported by the RTC class
+framework. However, because the chips and systems are not standardized,
+some PC/AT functionality might not be provided. And in the same way, some
+newer features -- including those enabled by ACPI -- are exposed by the
+RTC class framework, but can't be supported by the older driver.
+
+ * RTC_RD_TIME, RTC_SET_TIME ... every RTC supports at least reading
+ time, returning the result as a Gregorian calendar date and 24 hour
+ wall clock time. To be most useful, this time may also be updated.
+
+ * RTC_AIE_ON, RTC_AIE_OFF, RTC_ALM_SET, RTC_ALM_READ ... when the RTC
+ is connected to an IRQ line, it can often issue an alarm IRQ up to
+ 24 hours in the future.
+
+ * RTC_WKALM_SET, RTC_WKALM_READ ... RTCs that can issue alarms beyond
+ the next 24 hours use a slightly more powerful API, which supports
+ setting the longer alarm time and enabling its IRQ using a single
+ request (using the same model as EFI firmware).
+
+ * RTC_UIE_ON, RTC_UIE_OFF ... if the RTC offers IRQs, it probably
+ also offers update IRQs whenever the "seconds" counter changes.
+ If needed, the RTC framework can emulate this mechanism.
+
+ * RTC_PIE_ON, RTC_PIE_OFF, RTC_IRQP_SET, RTC_IRQP_READ ... another
+ feature often accessible with an IRQ line is a periodic IRQ, issued
+ at settable frequencies (usually 2^N Hz).
+
+In many cases, the RTC alarm can be a system wake event, used to force
+Linux out of a low power sleep state (or hibernation) back to a fully
+operational state. For example, a system could enter a deep power saving
+state until it's time to execute some scheduled tasks.
- Paul Gortmaker
-------------------- 8< ---------------- 8< -----------------------------
/*
- * Real Time Clock Driver Test/Example Program
+ * Real Time Clock Driver Test/Example Program
*
- * Compile with:
- * gcc -s -Wall -Wstrict-prototypes rtctest.c -o rtctest
+ * Compile with:
+ * gcc -s -Wall -Wstrict-prototypes rtctest.c -o rtctest
*
- * Copyright (C) 1996, Paul Gortmaker.
+ * Copyright (C) 1996, Paul Gortmaker.
*
- * Released under the GNU General Public License, version 2,
- * included herein by reference.
+ * Released under the GNU General Public License, version 2,
+ * included herein by reference.
*
*/
#include <stdio.h>
-#include <stdlib.h>
#include <linux/rtc.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
+#include <stdlib.h>
#include <errno.h>
-int main(void) {
-
-int i, fd, retval, irqcount = 0;
-unsigned long tmp, data;
-struct rtc_time rtc_tm;
-fd = open ("/dev/rtc", O_RDONLY);
+/*
+ * This expects the new RTC class driver framework, working with
+ * clocks that will often not be clones of what the PC-AT had.
+ * Use the command line to specify another RTC if you need one.
+ */
+static const char default_rtc[] = "/dev/rtc0";
+
+
+int main(int argc, char **argv)
+{
+ int i, fd, retval, irqcount = 0;
+ unsigned long tmp, data;
+ struct rtc_time rtc_tm;
+ const char *rtc = default_rtc;
+
+ switch (argc) {
+ case 2:
+ rtc = argv[1];
+ /* FALLTHROUGH */
+ case 1:
+ break;
+ default:
+ fprintf(stderr, "usage: rtctest [rtcdev]\n");
+ return 1;
+ }
-if (fd == -1) {
- perror("/dev/rtc");
- exit(errno);
-}
+ fd = open(rtc, O_RDONLY);
-fprintf(stderr, "\n\t\t\tRTC Driver Test Example.\n\n");
+ if (fd == -1) {
+ perror(rtc);
+ exit(errno);
+ }
-/* Turn on update interrupts (one per second) */
-retval = ioctl(fd, RTC_UIE_ON, 0);
-if (retval == -1) {
- perror("ioctl");
- exit(errno);
-}
+ fprintf(stderr, "\n\t\t\tRTC Driver Test Example.\n\n");
-fprintf(stderr, "Counting 5 update (1/sec) interrupts from reading /dev/rtc:");
-fflush(stderr);
-for (i=1; i<6; i++) {
- /* This read will block */
- retval = read(fd, &data, sizeof(unsigned long));
+ /* Turn on update interrupts (one per second) */
+ retval = ioctl(fd, RTC_UIE_ON, 0);
if (retval == -1) {
- perror("read");
+ if (errno == ENOTTY) {
+ fprintf(stderr,
+ "\n...Update IRQs not supported.\n");
+ goto test_READ;
+ }
+ perror("ioctl");
exit(errno);
}
- fprintf(stderr, " %d",i);
+
+ fprintf(stderr, "Counting 5 update (1/sec) interrupts from reading %s:",
+ rtc);
fflush(stderr);
- irqcount++;
-}
+ for (i=1; i<6; i++) {
+ /* This read will block */
+ retval = read(fd, &data, sizeof(unsigned long));
+ if (retval == -1) {
+ perror("read");
+ exit(errno);
+ }
+ fprintf(stderr, " %d",i);
+ fflush(stderr);
+ irqcount++;
+ }
-fprintf(stderr, "\nAgain, from using select(2) on /dev/rtc:");
-fflush(stderr);
-for (i=1; i<6; i++) {
- struct timeval tv = {5, 0}; /* 5 second timeout on select */
- fd_set readfds;
+ fprintf(stderr, "\nAgain, from using select(2) on /dev/rtc:");
+ fflush(stderr);
+ for (i=1; i<6; i++) {
+ struct timeval tv = {5, 0}; /* 5 second timeout on select */
+ fd_set readfds;
+
+ FD_ZERO(&readfds);
+ FD_SET(fd, &readfds);
+ /* The select will wait until an RTC interrupt happens. */
+ retval = select(fd+1, &readfds, NULL, NULL, &tv);
+ if (retval == -1) {
+ perror("select");
+ exit(errno);
+ }
+ /* This read won't block unlike the select-less case above. */
+ retval = read(fd, &data, sizeof(unsigned long));
+ if (retval == -1) {
+ perror("read");
+ exit(errno);
+ }
+ fprintf(stderr, " %d",i);
+ fflush(stderr);
+ irqcount++;
+ }
- FD_ZERO(&readfds);
- FD_SET(fd, &readfds);
- /* The select will wait until an RTC interrupt happens. */
- retval = select(fd+1, &readfds, NULL, NULL, &tv);
+ /* Turn off update interrupts */
+ retval = ioctl(fd, RTC_UIE_OFF, 0);
if (retval == -1) {
- perror("select");
+ perror("ioctl");
exit(errno);
}
- /* This read won't block unlike the select-less case above. */
- retval = read(fd, &data, sizeof(unsigned long));
+
+test_READ:
+ /* Read the RTC time/date */
+ retval = ioctl(fd, RTC_RD_TIME, &rtc_tm);
if (retval == -1) {
- perror("read");
+ perror("ioctl");
exit(errno);
}
- fprintf(stderr, " %d",i);
- fflush(stderr);
- irqcount++;
-}
-
-/* Turn off update interrupts */
-retval = ioctl(fd, RTC_UIE_OFF, 0);
-if (retval == -1) {
- perror("ioctl");
- exit(errno);
-}
-
-/* Read the RTC time/date */
-retval = ioctl(fd, RTC_RD_TIME, &rtc_tm);
-if (retval == -1) {
- perror("ioctl");
- exit(errno);
-}
-
-fprintf(stderr, "\n\nCurrent RTC date/time is %d-%d-%d, %02d:%02d:%02d.\n",
- rtc_tm.tm_mday, rtc_tm.tm_mon + 1, rtc_tm.tm_year + 1900,
- rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec);
-
-/* Set the alarm to 5 sec in the future, and check for rollover */
-rtc_tm.tm_sec += 5;
-if (rtc_tm.tm_sec >= 60) {
- rtc_tm.tm_sec %= 60;
- rtc_tm.tm_min++;
-}
-if (rtc_tm.tm_min == 60) {
- rtc_tm.tm_min = 0;
- rtc_tm.tm_hour++;
-}
-if (rtc_tm.tm_hour == 24)
- rtc_tm.tm_hour = 0;
-
-retval = ioctl(fd, RTC_ALM_SET, &rtc_tm);
-if (retval == -1) {
- perror("ioctl");
- exit(errno);
-}
-
-/* Read the current alarm settings */
-retval = ioctl(fd, RTC_ALM_READ, &rtc_tm);
-if (retval == -1) {
- perror("ioctl");
- exit(errno);
-}
-
-fprintf(stderr, "Alarm time now set to %02d:%02d:%02d.\n",
- rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec);
-/* Enable alarm interrupts */
-retval = ioctl(fd, RTC_AIE_ON, 0);
-if (retval == -1) {
- perror("ioctl");
- exit(errno);
-}
+ fprintf(stderr, "\n\nCurrent RTC date/time is %d-%d-%d, %02d:%02d:%02d.\n",
+ rtc_tm.tm_mday, rtc_tm.tm_mon + 1, rtc_tm.tm_year + 1900,
+ rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec);
-fprintf(stderr, "Waiting 5 seconds for alarm...");
-fflush(stderr);
-/* This blocks until the alarm ring causes an interrupt */
-retval = read(fd, &data, sizeof(unsigned long));
-if (retval == -1) {
- perror("read");
- exit(errno);
-}
-irqcount++;
-fprintf(stderr, " okay. Alarm rang.\n");
-
-/* Disable alarm interrupts */
-retval = ioctl(fd, RTC_AIE_OFF, 0);
-if (retval == -1) {
- perror("ioctl");
- exit(errno);
-}
+ /* Set the alarm to 5 sec in the future, and check for rollover */
+ rtc_tm.tm_sec += 5;
+ if (rtc_tm.tm_sec >= 60) {
+ rtc_tm.tm_sec %= 60;
+ rtc_tm.tm_min++;
+ }
+ if (rtc_tm.tm_min == 60) {
+ rtc_tm.tm_min = 0;
+ rtc_tm.tm_hour++;
+ }
+ if (rtc_tm.tm_hour == 24)
+ rtc_tm.tm_hour = 0;
-/* Read periodic IRQ rate */
-retval = ioctl(fd, RTC_IRQP_READ, &tmp);
-if (retval == -1) {
- perror("ioctl");
- exit(errno);
-}
-fprintf(stderr, "\nPeriodic IRQ rate was %ldHz.\n", tmp);
+ retval = ioctl(fd, RTC_ALM_SET, &rtc_tm);
+ if (retval == -1) {
+ if (errno == ENOTTY) {
+ fprintf(stderr,
+ "\n...Alarm IRQs not supported.\n");
+ goto test_PIE;
+ }
+ perror("ioctl");
+ exit(errno);
+ }
-fprintf(stderr, "Counting 20 interrupts at:");
-fflush(stderr);
+ /* Read the current alarm settings */
+ retval = ioctl(fd, RTC_ALM_READ, &rtc_tm);
+ if (retval == -1) {
+ perror("ioctl");
+ exit(errno);
+ }
-/* The frequencies 128Hz, 256Hz, ... 8192Hz are only allowed for root. */
-for (tmp=2; tmp<=64; tmp*=2) {
+ fprintf(stderr, "Alarm time now set to %02d:%02d:%02d.\n",
+ rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec);
- retval = ioctl(fd, RTC_IRQP_SET, tmp);
+ /* Enable alarm interrupts */
+ retval = ioctl(fd, RTC_AIE_ON, 0);
if (retval == -1) {
perror("ioctl");
exit(errno);
}
- fprintf(stderr, "\n%ldHz:\t", tmp);
+ fprintf(stderr, "Waiting 5 seconds for alarm...");
fflush(stderr);
+ /* This blocks until the alarm ring causes an interrupt */
+ retval = read(fd, &data, sizeof(unsigned long));
+ if (retval == -1) {
+ perror("read");
+ exit(errno);
+ }
+ irqcount++;
+ fprintf(stderr, " okay. Alarm rang.\n");
- /* Enable periodic interrupts */
- retval = ioctl(fd, RTC_PIE_ON, 0);
+ /* Disable alarm interrupts */
+ retval = ioctl(fd, RTC_AIE_OFF, 0);
if (retval == -1) {
perror("ioctl");
exit(errno);
}
- for (i=1; i<21; i++) {
- /* This blocks */
- retval = read(fd, &data, sizeof(unsigned long));
+test_PIE:
+ /* Read periodic IRQ rate */
+ retval = ioctl(fd, RTC_IRQP_READ, &tmp);
+ if (retval == -1) {
+ /* not all RTCs support periodic IRQs */
+ if (errno == ENOTTY) {
+ fprintf(stderr, "\nNo periodic IRQ support\n");
+ return 0;
+ }
+ perror("ioctl");
+ exit(errno);
+ }
+ fprintf(stderr, "\nPeriodic IRQ rate is %ldHz.\n", tmp);
+
+ fprintf(stderr, "Counting 20 interrupts at:");
+ fflush(stderr);
+
+ /* The frequencies 128Hz, 256Hz, ... 8192Hz are only allowed for root. */
+ for (tmp=2; tmp<=64; tmp*=2) {
+
+ retval = ioctl(fd, RTC_IRQP_SET, tmp);
if (retval == -1) {
- perror("read");
- exit(errno);
+ /* not all RTCs can change their periodic IRQ rate */
+ if (errno == ENOTTY) {
+ fprintf(stderr,
+ "\n...Periodic IRQ rate is fixed\n");
+ goto done;
+ }
+ perror("ioctl");
+ exit(errno);
}
- fprintf(stderr, " %d",i);
+
+ fprintf(stderr, "\n%ldHz:\t", tmp);
fflush(stderr);
- irqcount++;
- }
- /* Disable periodic interrupts */
- retval = ioctl(fd, RTC_PIE_OFF, 0);
- if (retval == -1) {
- perror("ioctl");
- exit(errno);
+ /* Enable periodic interrupts */
+ retval = ioctl(fd, RTC_PIE_ON, 0);
+ if (retval == -1) {
+ perror("ioctl");
+ exit(errno);
+ }
+
+ for (i=1; i<21; i++) {
+ /* This blocks */
+ retval = read(fd, &data, sizeof(unsigned long));
+ if (retval == -1) {
+ perror("read");
+ exit(errno);
+ }
+ fprintf(stderr, " %d",i);
+ fflush(stderr);
+ irqcount++;
+ }
+
+ /* Disable periodic interrupts */
+ retval = ioctl(fd, RTC_PIE_OFF, 0);
+ if (retval == -1) {
+ perror("ioctl");
+ exit(errno);
+ }
}
-}
-fprintf(stderr, "\n\n\t\t\t *** Test complete ***\n");
-fprintf(stderr, "\nTyping \"cat /proc/interrupts\" will show %d more events on IRQ 8.\n\n",
- irqcount);
+done:
+ fprintf(stderr, "\n\n\t\t\t *** Test complete ***\n");
-close(fd);
-return 0;
+ close(fd);
-} /* end main */
+ return 0;
+}
diff --git a/Documentation/s390/crypto/crypto-API.txt b/Documentation/s390/crypto/crypto-API.txt
index 29dee792c887..41a8b07da05a 100644
--- a/Documentation/s390/crypto/crypto-API.txt
+++ b/Documentation/s390/crypto/crypto-API.txt
@@ -75,8 +75,8 @@ name of the respective module is given in square brackets.
- SHA1 Digest Algorithm [sha1 -> sha1_z990]
- DES Encrypt/Decrypt Algorithm (64bit key) [des -> des_z990]
-- Tripple DES Encrypt/Decrypt Algorithm (128bit key) [des3_ede128 -> des_z990]
-- Tripple DES Encrypt/Decrypt Algorithm (192bit key) [des3_ede -> des_z990]
+- Triple DES Encrypt/Decrypt Algorithm (128bit key) [des3_ede128 -> des_z990]
+- Triple DES Encrypt/Decrypt Algorithm (192bit key) [des3_ede -> des_z990]
In order to load, for example, the sha1_z990 module when the sha1 algorithm is
requested (see 3.2.) add 'alias sha1 sha1_z990' to /etc/modprobe.conf.
diff --git a/Documentation/scsi/aic79xx.txt b/Documentation/scsi/aic79xx.txt
index 904d49e90ef2..6aa9a891f3d0 100644
--- a/Documentation/scsi/aic79xx.txt
+++ b/Documentation/scsi/aic79xx.txt
@@ -127,7 +127,7 @@ The following information is available in this file:
- Correct a reference to free'ed memory during controller
shutdown.
- Reset the bus on an SE->LVD change. This is required
- to reset our transcievers.
+ to reset our transceivers.
1.3.5 (March 24th, 2003)
- Fix a few register window mode bugs.
@@ -169,7 +169,7 @@ The following information is available in this file:
1.3.0 (January 21st, 2003)
- Full regression testing for all U320 products completed.
- Added abort and target/lun reset error recovery handler and
- interrupt coalessing.
+ interrupt coalescing.
1.2.0 (November 14th, 2002)
- Added support for Domain Validation
diff --git a/Documentation/scsi/aic7xxx_old.txt b/Documentation/scsi/aic7xxx_old.txt
index c92f4473193b..05667e7308d4 100644
--- a/Documentation/scsi/aic7xxx_old.txt
+++ b/Documentation/scsi/aic7xxx_old.txt
@@ -256,7 +256,7 @@ linux-1.1.x and fairly stable since linux-1.2.x, and are also in FreeBSD
En/Disable High Byte LVD Termination
The upper 2 bits that deal with LVD termination only apply to Ultra2
- controllers. Futhermore, due to the current Ultra2 controller
+ controllers. Furthermore, due to the current Ultra2 controller
designs, these bits are tied together such that setting either bit
enables both low and high byte LVD termination. It is not possible
to only set high or low byte LVD termination in this manner. This is
@@ -436,7 +436,7 @@ linux-1.1.x and fairly stable since linux-1.2.x, and are also in FreeBSD
the commas to periods, insmod won't interpret this as more than one
string and write junk into our binary image. I consider it a bug in
the insmod program that even if you wrap your string in quotes (quotes
- that pass the shell mind you and that insmod sees) it still treates
+ that pass the shell mind you and that insmod sees) it still treats
a comma inside of those quotes as starting a new variable, resulting
in memory scribbles if you don't switch the commas to periods.
diff --git a/Documentation/scsi/ibmmca.txt b/Documentation/scsi/ibmmca.txt
index 35f6b8ed2295..9707941704e3 100644
--- a/Documentation/scsi/ibmmca.txt
+++ b/Documentation/scsi/ibmmca.txt
@@ -461,7 +461,7 @@
This needs the RD-Bit to be disabled on IM_OTHER_SCSI_CMD_CMD which
allows data to be written from the system to the device. It is a
necessary step to be allowed to set blocksize of SCSI-tape-drives and
- the tape-speed, whithout confusing the SCSI-Subsystem.
+ the tape-speed, without confusing the SCSI-Subsystem.
2) The recognition of a tape is included in the check_devices routine.
This is done by checking for TYPE_TAPE, that is already defined in
the kernel-scsi-environment. The markup of a tape is done in the
@@ -710,8 +710,8 @@
of troubles with some controllers and after I wanted to apply some
extensions, it jumped out in the same situation, on my w/cache, as like
on D. Weinehalls' Model 56, having integrated SCSI. This gave me the
- descissive hint to move the code-part out and declare it global. Now,
- it seems to work by far much better an more stable. Let us see, what
+ decisive hint to move the code-part out and declare it global. Now
+ it seems to work far better and more stable. Let us see what
the world thinks of it...
3) By the way, only Sony DAT-drives seem to show density code 0x13. A
test with a HP drive gave right results, so the problem is vendor-
@@ -822,10 +822,10 @@
A long period of collecting bugreports from all corners of the world
now lead to the following corrections to the code:
1) SCSI-2 F/W support crashed with a COMMAND ERROR. The reason for this
- was, that it is possible to disbale Fast-SCSI for the external bus.
- The feature-control command, where this crash appeared regularly tried
+ was that it is possible to disable Fast-SCSI for the external bus.
+ The feature-control command, where this crash appeared regularly, tried
to set the maximum speed of 10MHz synchronous transfer speed and that
- reports a COMMAND ERROR, if external bus Fast-SCSI is disabled. Now,
+ reports a COMMAND ERROR if external bus Fast-SCSI is disabled. Now,
the feature-command probes down from maximum speed until the adapter
stops to complain, which is at the same time the maximum possible
speed selected in the reference program. So, F/W external can run at
@@ -920,7 +920,7 @@
completed in such a way, that they are now completely conform to the
demands in the technical description of IBM. Main candidates were the
DEVICE_INQUIRY, REQUEST_SENSE and DEVICE_CAPACITY commands. They must
- be tranferred by bypassing the internal command buffer of the adapter
+ be transferred by bypassing the internal command buffer of the adapter
or else the response can be a random result. GET_POS_INFO would be more
safe in usage, if one could use the SUPRESS_EXCEPTION_SHORT, but this
is not allowed by the technical references of IBM. (Sorry, folks, the
diff --git a/Documentation/scsi/in2000.txt b/Documentation/scsi/in2000.txt
index 80f104042645..c3e2a90475d2 100644
--- a/Documentation/scsi/in2000.txt
+++ b/Documentation/scsi/in2000.txt
@@ -24,7 +24,7 @@ UPDATE NEWS: version 1.32 - 28 Mar 98
UPDATE NEWS: version 1.31 - 6 Jul 97
Fixed a bug that caused incorrect SCSI status bytes to be
- returned from commands sent to LUN's greater than 0. This
+ returned from commands sent to LUNs greater than 0. This
means that CDROM changers work now! Fixed a bug in the
handling of command-line arguments when loaded as a module.
Also put all the header data in in2000.h where it belongs.
diff --git a/Documentation/scsi/libsas.txt b/Documentation/scsi/libsas.txt
index 9e2078b2a615..aa54f54c4a50 100644
--- a/Documentation/scsi/libsas.txt
+++ b/Documentation/scsi/libsas.txt
@@ -393,7 +393,7 @@ struct sas_task {
task_proto -- _one_ of enum sas_proto
scatter -- pointer to scatter gather list array
num_scatter -- number of elements in scatter
- total_xfer_len -- total number of bytes expected to be transfered
+ total_xfer_len -- total number of bytes expected to be transferred
data_dir -- PCI_DMA_...
task_done -- callback when the task has finished execution
};
diff --git a/Documentation/scsi/ncr53c8xx.txt b/Documentation/scsi/ncr53c8xx.txt
index 58ad8db333d9..caf10b155185 100644
--- a/Documentation/scsi/ncr53c8xx.txt
+++ b/Documentation/scsi/ncr53c8xx.txt
@@ -115,7 +115,7 @@ SCSI standard documentations are available at SYMBIOS ftp server:
ftp://ftp.symbios.com/
-Usefull SCSI tools written by Eric Youngdale are available at tsx-11:
+Useful SCSI tools written by Eric Youngdale are available at tsx-11:
ftp://tsx-11.mit.edu/pub/linux/ALPHA/scsi/scsiinfo-X.Y.tar.gz
ftp://tsx-11.mit.edu/pub/linux/ALPHA/scsi/scsidev-X.Y.tar.gz
diff --git a/Documentation/scsi/scsi-changer.txt b/Documentation/scsi/scsi-changer.txt
index d74bbd29eb3a..032399b16a53 100644
--- a/Documentation/scsi/scsi-changer.txt
+++ b/Documentation/scsi/scsi-changer.txt
@@ -88,7 +88,7 @@ If the module finds the changer, it prints some messages about the
device [ try "dmesg" if you don't see anything ] and should show up in
/proc/devices. If not.... some changers use ID ? / LUN 0 for the
device and ID ? / LUN 1 for the robot mechanism. But Linux does *not*
-look for LUN's other than 0 as default, becauce there are to many
+look for LUNs other than 0 as default, because there are too many
broken devices. So you can try:
1) echo "scsi add-single-device 0 0 ID 1" > /proc/scsi/scsi
@@ -107,7 +107,7 @@ because the kernel will translate the error codes into human-readable
strings then.
You can display these messages with the dmesg command (or check the
-logfiles). If you email me some question becauce of a problem with the
+logfiles). If you email me some question because of a problem with the
driver, please include these messages.
diff --git a/Documentation/scsi/scsi_eh.txt b/Documentation/scsi/scsi_eh.txt
index b964eef2f62f..7acbebb17fa6 100644
--- a/Documentation/scsi/scsi_eh.txt
+++ b/Documentation/scsi/scsi_eh.txt
@@ -75,7 +75,7 @@ with the command.
- otherwise
scsi_eh_scmd_add(scmd, 0) is invoked for the command. See
- [1-3] for details of this funciton.
+ [1-3] for details of this function.
[1-2-2] Completing a scmd w/ timeout
diff --git a/Documentation/scsi/st.txt b/Documentation/scsi/st.txt
index 5ff65b184265..3c12422f7f41 100644
--- a/Documentation/scsi/st.txt
+++ b/Documentation/scsi/st.txt
@@ -261,7 +261,7 @@ pairs are separated with a comma (no spaces allowed). A colon can be
used instead of the equal mark. The definition is prepended by the
string st=. Here is an example:
- st=buffer_kbs:64,write_threhold_kbs:60
+ st=buffer_kbs:64,write_threshold_kbs:60
The following syntax used by the old kernel versions is also supported:
diff --git a/Documentation/scsi/sym53c8xx_2.txt b/Documentation/scsi/sym53c8xx_2.txt
index 26c8a08ca3ea..2c1745a9df00 100644
--- a/Documentation/scsi/sym53c8xx_2.txt
+++ b/Documentation/scsi/sym53c8xx_2.txt
@@ -609,7 +609,7 @@ appropriate mailing lists or news-groups. Send me a copy in order to
be sure I will receive it. Obviously, a bug in the driver code is
possible.
- My cyrrent email address: Gerard Roudier <groudier@free.fr>
+ My current email address: Gerard Roudier <groudier@free.fr>
Allowing disconnections is important if you use several devices on
your SCSI bus but often causes problems with buggy devices.
diff --git a/Documentation/sharedsubtree.txt b/Documentation/sharedsubtree.txt
index 2d8f403eb6eb..ccf1cebe744f 100644
--- a/Documentation/sharedsubtree.txt
+++ b/Documentation/sharedsubtree.txt
@@ -942,13 +942,13 @@ replicas continue to be exactly same.
->mnt_slave
->mnt_master
- ->mnt_share links togather all the mount to/from which this vfsmount
+ ->mnt_share links together all the mount to/from which this vfsmount
send/receives propagation events.
->mnt_slave_list links all the mounts to which this vfsmount propagates
to.
- ->mnt_slave links togather all the slaves that its master vfsmount
+ ->mnt_slave links together all the slaves that its master vfsmount
propagates to.
->mnt_master points to the master vfsmount from which this vfsmount
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 3472d9c4ef1b..9fef210ab50a 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -955,7 +955,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
dmx6fire, dsp24, dsp24_value, dsp24_71, ez8,
phase88, mediastation
omni - Omni I/O support for MidiMan M-Audio Delta44/66
- cs8427_timeout - reset timeout for the CS8427 chip (S/PDIF transciever)
+ cs8427_timeout - reset timeout for the CS8427 chip (S/PDIF transceiver)
in msec resolution, default value is 500 (0.5 sec)
This module supports multiple cards and autoprobe. Note: The consumer part
diff --git a/Documentation/sound/alsa/Audigy-mixer.txt b/Documentation/sound/alsa/Audigy-mixer.txt
index 5132fd95e074..7f10dc6ff28c 100644
--- a/Documentation/sound/alsa/Audigy-mixer.txt
+++ b/Documentation/sound/alsa/Audigy-mixer.txt
@@ -6,7 +6,7 @@ This is based on SB-Live-mixer.txt.
The EMU10K2 chips have a DSP part which can be programmed to support
various ways of sample processing, which is described here.
-(This acticle does not deal with the overall functionality of the
+(This article does not deal with the overall functionality of the
EMU10K2 chips. See the manuals section for further details.)
The ALSA driver programs this portion of chip by default code
diff --git a/Documentation/sound/alsa/SB-Live-mixer.txt b/Documentation/sound/alsa/SB-Live-mixer.txt
index 651adaf60473..f5639d40521d 100644
--- a/Documentation/sound/alsa/SB-Live-mixer.txt
+++ b/Documentation/sound/alsa/SB-Live-mixer.txt
@@ -5,7 +5,7 @@
The EMU10K1 chips have a DSP part which can be programmed to support
various ways of sample processing, which is described here.
-(This acticle does not deal with the overall functionality of the
+(This article does not deal with the overall functionality of the
EMU10K1 chips. See the manuals section for further details.)
The ALSA driver programs this portion of chip by default code
diff --git a/Documentation/stable_kernel_rules.txt b/Documentation/stable_kernel_rules.txt
index 02a481225b0d..c815c5206e84 100644
--- a/Documentation/stable_kernel_rules.txt
+++ b/Documentation/stable_kernel_rules.txt
@@ -50,7 +50,7 @@ Review cycle:
Contact the kernel security team for more details on this procedure.
-Review committe:
+Review committee:
- This is made up of a number of kernel developers who have volunteered for
this task, and a few that haven't.
diff --git a/Documentation/sysctl/fs.txt b/Documentation/sysctl/fs.txt
index 5c3a51905969..aa986a35e994 100644
--- a/Documentation/sysctl/fs.txt
+++ b/Documentation/sysctl/fs.txt
@@ -146,7 +146,7 @@ or otherwise protected/tainted binaries. The modes are
readable by root only. This allows the end user to remove
such a dump but not access it directly. For security reasons
core dumps in this mode will not overwrite one another or
- other files. This mode is appropriate when adminstrators are
+ other files. This mode is appropriate when administrators are
attempting to debug problems in a normal environment.
==============================================================
diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt
index 20d0d797f539..e96a341eb7e4 100644
--- a/Documentation/sysctl/vm.txt
+++ b/Documentation/sysctl/vm.txt
@@ -129,7 +129,7 @@ the high water marks for each per cpu page list.
zone_reclaim_mode:
-Zone_reclaim_mode allows to set more or less agressive approaches to
+Zone_reclaim_mode allows someone to set more or less aggressive approaches to
reclaim memory when a zone runs out of memory. If it is set to zero then no
zone reclaim occurs. Allocations will be satisfied from other zones / nodes
in the system.
diff --git a/Documentation/uml/UserModeLinux-HOWTO.txt b/Documentation/uml/UserModeLinux-HOWTO.txt
index b60590eca18f..628013f944c4 100644
--- a/Documentation/uml/UserModeLinux-HOWTO.txt
+++ b/Documentation/uml/UserModeLinux-HOWTO.txt
@@ -1477,7 +1477,7 @@
- Making it world-writeable looks bad, but it seems not to be
+ Making it world-writable looks bad, but it seems not to be
exploitable as a security hole. However, it does allow anyone to cre-
ate useless tap devices (useless because they can't configure them),
which is a DOS attack. A somewhat more secure alternative would to be
diff --git a/Documentation/usb/hiddev.txt b/Documentation/usb/hiddev.txt
index 6a790754e963..6e8c9f1d2f22 100644
--- a/Documentation/usb/hiddev.txt
+++ b/Documentation/usb/hiddev.txt
@@ -8,7 +8,7 @@ interfaces, but have similar sorts of communication needs. The two big
examples for this are power devices (especially uninterruptable power
supplies) and monitor control on higher end monitors.
-To support these disparite requirements, the Linux USB system provides
+To support these disparate requirements, the Linux USB system provides
HID events to two separate interfaces:
* the input subsystem, which converts HID events into normal input
device interfaces (such as keyboard, mouse and joystick) and a
diff --git a/Documentation/usb/rio.txt b/Documentation/usb/rio.txt
index ab21db454694..aee715af7db7 100644
--- a/Documentation/usb/rio.txt
+++ b/Documentation/usb/rio.txt
@@ -24,10 +24,10 @@ are in no way responsible for any damage that may occur, no matter how
inconsequential.
It seems that the Rio has a problem when sending .mp3 with low batteries.
-I suggest when the batteries are low and want to transfer stuff that you
+I suggest when the batteries are low and you want to transfer stuff that you
replace it with a fresh one. In my case, what happened is I lost two 16kb
blocks (they are no longer usable to store information to it). But I don't
-know if thats normal or not. It could simply be a problem with the flash
+know if that's normal or not; it could simply be a problem with the flash
memory.
In an extreme case, I left my Rio playing overnight and the batteries wore
diff --git a/Documentation/usb/usb-serial.txt b/Documentation/usb/usb-serial.txt
index 50436e1663ea..d61f6e7865de 100644
--- a/Documentation/usb/usb-serial.txt
+++ b/Documentation/usb/usb-serial.txt
@@ -175,7 +175,7 @@ Keyspan USA-series Serial Adapters
Current status:
The USA-18X, USA-28X, USA-19, USA-19W and USA-49W are supported and
- have been pretty throughly tested at various baud rates with 8-N-1
+ have been pretty thoroughly tested at various baud rates with 8-N-1
character settings. Other character lengths and parity setups are
presently untested.
@@ -253,7 +253,7 @@ Cypress M8 CY4601 Family Serial Driver
together without hacking the adapter to set the line high.
The driver is smp safe. Performance with the driver is rather low when using
- it for transfering files. This is being worked on, but I would be willing to
+ it for transferring files. This is being worked on, but I would be willing to
accept patches. An urb queue or packet buffer would likely fit the bill here.
If you have any questions, problems, patches, feature requests, etc. you can
@@ -297,7 +297,7 @@ Belkin USB Serial Adapter F5U103
Parity N,E,O,M,S
Handshake None, Software (XON/XOFF), Hardware (CTSRTS,CTSDTR)*
Break Set and clear
- Line contrl Input/Output query and control **
+ Line control Input/Output query and control **
* Hardware input flow control is only enabled for firmware
levels above 2.06. Read source code comments describing Belkin
@@ -309,7 +309,7 @@ Belkin USB Serial Adapter F5U103
automatic hardware flow control.
TO DO List:
- -- Add true modem contol line query capability. Currently tracks the
+ -- Add true modem control line query capability. Currently tracks the
states reported by the interrupt and the states requested.
-- Add error reporting back to application for UART error conditions.
-- Add support for flush ioctls.
diff --git a/Documentation/watchdog/watchdog-api.txt b/Documentation/watchdog/watchdog-api.txt
index 7e8ae83e9847..8d16f6f3c4ec 100644
--- a/Documentation/watchdog/watchdog-api.txt
+++ b/Documentation/watchdog/watchdog-api.txt
@@ -214,7 +214,7 @@ returned value is the temperature in degrees fahrenheit.
Finally the SETOPTIONS ioctl can be used to control some aspects of
the cards operation; right now the pcwd driver is the only one
-supporting thiss ioctl.
+supporting this ioctl.
int options = 0;
ioctl(fd, WDIOC_SETOPTIONS, options);
diff --git a/MAINTAINERS b/MAINTAINERS
index a5508f930ed9..8385a69138a8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -155,16 +155,16 @@ L: netdev@vger.kernel.org
S: Maintained
9P FILE SYSTEM
-P: Eric Van Hensbergen
-M: ericvh@gmail.com
-P: Ron Minnich
-M: rminnich@lanl.gov
-P: Latchesar Ionkov
-M: lucho@ionkov.net
-L: v9fs-developer@lists.sourceforge.net
-W: http://v9fs.sf.net
-T: git kernel.org:/pub/scm/linux/kernel/ericvh/v9fs.git
-S: Maintained
+P: Eric Van Hensbergen
+M: ericvh@gmail.com
+P: Ron Minnich
+M: rminnich@lanl.gov
+P: Latchesar Ionkov
+M: lucho@ionkov.net
+L: v9fs-developer@lists.sourceforge.net
+W: http://v9fs.sf.net
+T: git kernel.org:/pub/scm/linux/kernel/ericvh/v9fs.git
+S: Maintained
A2232 SERIAL BOARD DRIVER
P: Enver Haase
@@ -290,8 +290,8 @@ M: ink@jurassic.park.msu.ru
S: Maintained for 2.4; PCI support for 2.6.
AMD GEODE PROCESSOR/CHIPSET SUPPORT
-P: Jordan Crouse
-M: info-linux@geode.amd.com
+P: Jordan Crouse
+M: info-linux@geode.amd.com
L: info-linux@geode.amd.com
W: http://www.amd.com/us-en/ConnectivitySolutions/TechnicalResources/0,,50_2334_2452_11363,00.html
S: Supported
@@ -353,6 +353,12 @@ P: Richard Purdie
M: rpurdie@rpsys.net
S: Maintained
+ARM/HP JORNADA 7XX MACHINE SUPPORT
+P: Kristoffer Ericson
+M: kristoffer_e1@hotmail.com
+W: www.jlime.com
+S: Maintained
+
ARM/TOSA MACHINE SUPPORT
P: Dirk Opfer
M: dirk@opfer-online.de
@@ -426,6 +432,13 @@ L: linux-atm-general@lists.sourceforge.net (subscribers-only)
W: http://linux-atm.sourceforge.net
S: Maintained
+ATMEL MACB ETHERNET DRIVER
+P: Atmel AVR32 Support Team
+M: avr32@atmel.com
+P: Haavard Skinnemoen
+M: hskinnemoen@atmel.com
+S: Supported
+
ATMEL WIRELESS DRIVER
P: Simon Kelley
M: simon@thekelleys.org.uk
@@ -595,13 +608,13 @@ M: maxk@qualcomm.com
S: Maintained
BONDING DRIVER
-P: Chad Tindel
-M: ctindel@users.sourceforge.net
-P: Jay Vosburgh
-M: fubar@us.ibm.com
-L: bonding-devel@lists.sourceforge.net
-W: http://sourceforge.net/projects/bonding/
-S: Supported
+P: Chad Tindel
+M: ctindel@users.sourceforge.net
+P: Jay Vosburgh
+M: fubar@us.ibm.com
+L: bonding-devel@lists.sourceforge.net
+W: http://sourceforge.net/projects/bonding/
+S: Supported
BROADBAND PROCESSOR ARCHITECTURE
P: Arnd Bergmann
@@ -738,8 +751,8 @@ W: http://www.bullopensource.org/cpuset/
S: Supported
CRAMFS FILESYSTEM
-W: http://sourceforge.net/projects/cramfs/
-S: Orphan
+W: http://sourceforge.net/projects/cramfs/
+S: Orphan
CRIS PORT
P: Mikael Starvik
@@ -1048,11 +1061,11 @@ W: http://sourceforge.net/projects/emu10k1/
S: Maintained
EMULEX LPFC FC SCSI DRIVER
-P: James Smart
-M: james.smart@emulex.com
-L: linux-scsi@vger.kernel.org
-W: http://sourceforge.net/projects/lpfcxxxx
-S: Supported
+P: James Smart
+M: james.smart@emulex.com
+L: linux-scsi@vger.kernel.org
+W: http://sourceforge.net/projects/lpfcxxxx
+S: Supported
EPSON 1355 FRAMEBUFFER DRIVER
P: Christopher Hoover
@@ -1153,11 +1166,6 @@ P: David Howells
M: dhowells@redhat.com
S: Maintained
-FTAPE/QIC-117
-L: linux-tape@vger.kernel.org
-W: http://sourceforge.net/projects/ftape
-S: Orphan
-
FUSE: FILESYSTEM IN USERSPACE
P: Miklos Szeredi
M: miklos@szeredi.hu
@@ -1489,16 +1497,16 @@ L: linux-kernel@vger.kernel.org
S: Maintained
INTEL FRAMEBUFFER DRIVER (excluding 810 and 815)
-P: Sylvain Meyer
-M: sylvain.meyer@worldonline.fr
-L: linux-fbdev-devel@lists.sourceforge.net
-S: Maintained
+P: Sylvain Meyer
+M: sylvain.meyer@worldonline.fr
+L: linux-fbdev-devel@lists.sourceforge.net
+S: Maintained
INTEL 810/815 FRAMEBUFFER DRIVER
-P: Antonino Daplas
-M: adaplas@pol.net
-L: linux-fbdev-devel@lists.sourceforge.net
-S: Maintained
+P: Antonino Daplas
+M: adaplas@pol.net
+L: linux-fbdev-devel@lists.sourceforge.net
+S: Maintained
INTEL APIC/IOAPIC, LOWLEVEL X86 SMP SUPPORT
P: Ingo Molnar
@@ -1824,11 +1832,11 @@ L: linuxppc-embedded@ozlabs.org
S: Maintained
LINUX FOR POWERPC EMBEDDED PPC83XX AND PPC85XX
-P: Kumar Gala
-M: galak@kernel.crashing.org
-W: http://www.penguinppc.org/
-L: linuxppc-embedded@ozlabs.org
-S: Maintained
+P: Kumar Gala
+M: galak@kernel.crashing.org
+W: http://www.penguinppc.org/
+L: linuxppc-embedded@ozlabs.org
+S: Maintained
LINUX FOR POWERPC PA SEMI PWRFICIENT
P: Olof Johansson
@@ -1927,10 +1935,10 @@ W: http://www.syskonnect.com
S: Supported
MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7
-P: Michael Kerrisk
-M: mtk-manpages@gmx.net
-W: ftp://ftp.kernel.org/pub/linux/docs/manpages
-S: Maintained
+P: Michael Kerrisk
+M: mtk-manpages@gmx.net
+W: ftp://ftp.kernel.org/pub/linux/docs/manpages
+S: Maintained
MARVELL MV643XX ETHERNET DRIVER
P: Dale Farnsworth
@@ -1947,11 +1955,11 @@ L: linux-fbdev-devel@lists.sourceforge.net
S: Maintained
MEGARAID SCSI DRIVERS
-P: Neela Syam Kolli
-M: Neela.Kolli@engenio.com
-S: linux-scsi@vger.kernel.org
-W: http://megaraid.lsilogic.com
-S: Maintained
+P: Neela Syam Kolli
+M: Neela.Kolli@engenio.com
+S: linux-scsi@vger.kernel.org
+W: http://megaraid.lsilogic.com
+S: Maintained
MEMORY MANAGEMENT
L: linux-mm@kvack.org
@@ -2126,6 +2134,13 @@ L: netdev@vger.kernel.org
T: git kernel.org:/pub/scm/linux/kernel/git/linville/wireless-2.6.git
S: Maintained
+NETXEN (1/10) GbE SUPPORT
+P: Amit S. Kale
+M: amitkale@netxen.com
+L: netdev@vger.kernel.org
+W: http://www.netxen.com
+S: Supported
+
IPVS
P: Wensong Zhang
M: wensong@linux-vs.org
@@ -2180,10 +2195,10 @@ T: git kernel.org:/pub/scm/linux/kernel/git/aia21/ntfs-2.6.git
S: Maintained
NVIDIA (rivafb and nvidiafb) FRAMEBUFFER DRIVER
-P: Antonino Daplas
-M: adaplas@pol.net
-L: linux-fbdev-devel@lists.sourceforge.net
-S: Maintained
+P: Antonino Daplas
+M: adaplas@pol.net
+L: linux-fbdev-devel@lists.sourceforge.net
+S: Maintained
OPENCORES I2C BUS DRIVER
P: Peter Korsgaard
@@ -2533,10 +2548,10 @@ RISCOM8 DRIVER
S: Orphan
S3 SAVAGE FRAMEBUFFER DRIVER
-P: Antonino Daplas
-M: adaplas@pol.net
-L: linux-fbdev-devel@lists.sourceforge.net
-S: Maintained
+P: Antonino Daplas
+M: adaplas@pol.net
+L: linux-fbdev-devel@lists.sourceforge.net
+S: Maintained
S390
P: Martin Schwidefsky
@@ -2617,10 +2632,10 @@ L: linux-scsi@vger.kernel.org
S: Maintained
SCTP PROTOCOL
-P: Sridhar Samudrala
-M: sri@us.ibm.com
-L: lksctp-developers@lists.sourceforge.net
-S: Supported
+P: Sridhar Samudrala
+M: sri@us.ibm.com
+L: lksctp-developers@lists.sourceforge.net
+S: Supported
SCx200 CPU SUPPORT
P: Jim Cromie
@@ -2788,9 +2803,9 @@ L: tpmdd-devel@lists.sourceforge.net
S: Maintained
Telecom Clock Driver for MCPL0010
-P: Mark Gross
-M: mark.gross@intel.com
-S: Supported
+P: Mark Gross
+M: mark.gross@intel.com
+S: Supported
TENSILICA XTENSA PORT (xtensa):
P: Chris Zankel
@@ -2937,9 +2952,9 @@ L: linux-kernel@vger.kernel.org
S: Maintained
TI PARALLEL LINK CABLE DRIVER
-P: Romain Lievin
-M: roms@lpg.ticalc.org
-S: Maintained
+P: Romain Lievin
+M: roms@lpg.ticalc.org
+S: Maintained
TIPC NETWORK LAYER
P: Per Liden
@@ -2989,12 +3004,12 @@ L: linux-kernel@vger.kernel.org
S: Maintained
TRIVIAL PATCHES
-P: Adrian Bunk
-M: trivial@kernel.org
-L: linux-kernel@vger.kernel.org
-W: http://www.kernel.org/pub/linux/kernel/people/bunk/trivial/
-T: git kernel.org:/pub/scm/linux/kernel/git/bunk/trivial.git
-S: Maintained
+P: Adrian Bunk
+M: trivial@kernel.org
+L: linux-kernel@vger.kernel.org
+W: http://www.kernel.org/pub/linux/kernel/people/bunk/trivial/
+T: git kernel.org:/pub/scm/linux/kernel/git/bunk/trivial.git
+S: Maintained
TMS380 TOKEN-RING NETWORK DRIVER
P: Adam Fritzler
diff --git a/Makefile b/Makefile
index 958fad6739b3..aef96259051f 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 19
-EXTRAVERSION =-rc6
+EXTRAVERSION =
NAME=Avast! A bilge rat!
# *DOCUMENTATION*
diff --git a/arch/alpha/lib/checksum.c b/arch/alpha/lib/checksum.c
index 89044e6385fe..ab3761c437a8 100644
--- a/arch/alpha/lib/checksum.c
+++ b/arch/alpha/lib/checksum.c
@@ -41,28 +41,25 @@ static inline unsigned short from64to16(unsigned long x)
* computes the checksum of the TCP/UDP pseudo-header
* returns a 16-bit checksum, already complemented.
*/
-unsigned short int csum_tcpudp_magic(unsigned long saddr,
- unsigned long daddr,
+__sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
unsigned short len,
unsigned short proto,
- unsigned int sum)
+ __wsum sum)
{
- return ~from64to16(saddr + daddr + sum +
- ((unsigned long) ntohs(len) << 16) +
- ((unsigned long) proto << 8));
+ return (__force __sum16)~from64to16(
+ (__force u64)saddr + (__force u64)daddr +
+ (__force u64)sum + ((len + proto) << 8));
}
-unsigned int csum_tcpudp_nofold(unsigned long saddr,
- unsigned long daddr,
+__wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
unsigned short len,
unsigned short proto,
- unsigned int sum)
+ __wsum sum)
{
unsigned long result;
- result = (saddr + daddr + sum +
- ((unsigned long) ntohs(len) << 16) +
- ((unsigned long) proto << 8));
+ result = (__force u64)saddr + (__force u64)daddr +
+ (__force u64)sum + ((len + proto) << 8);
/* Fold down to 32-bits so we don't lose in the typedef-less
network stack. */
@@ -70,7 +67,7 @@ unsigned int csum_tcpudp_nofold(unsigned long saddr,
result = (result & 0xffffffff) + (result >> 32);
/* 33 to 32 */
result = (result & 0xffffffff) + (result >> 32);
- return result;
+ return (__force __wsum)result;
}
/*
@@ -146,9 +143,9 @@ out:
* This is a version of ip_compute_csum() optimized for IP headers,
* which always checksum on 4 octet boundaries.
*/
-unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl)
+__sum16 ip_fast_csum(const void *iph, unsigned int ihl)
{
- return ~do_csum(iph,ihl*4);
+ return (__force __sum16)~do_csum(iph,ihl*4);
}
/*
@@ -163,15 +160,15 @@ unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl)
*
* it's best to have buff aligned on a 32-bit boundary
*/
-unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
+__wsum csum_partial(const void *buff, int len, __wsum sum)
{
unsigned long result = do_csum(buff, len);
/* add in old sum, and carry.. */
- result += sum;
+ result += (__force u32)sum;
/* 32+c bits -> 32 bits */
result = (result & 0xffffffff) + (result >> 32);
- return result;
+ return (__force __wsum)result;
}
EXPORT_SYMBOL(csum_partial);
@@ -180,7 +177,7 @@ EXPORT_SYMBOL(csum_partial);
* this routine is used for miscellaneous IP-like checksums, mainly
* in icmp.c
*/
-unsigned short ip_compute_csum(unsigned char * buff, int len)
+__sum16 ip_compute_csum(const void *buff, int len)
{
- return ~from64to16(do_csum(buff,len));
+ return (__force __sum16)~from64to16(do_csum(buff,len));
}
diff --git a/arch/alpha/lib/csum_partial_copy.c b/arch/alpha/lib/csum_partial_copy.c
index a37948f3037a..4ca75c74ce90 100644
--- a/arch/alpha/lib/csum_partial_copy.c
+++ b/arch/alpha/lib/csum_partial_copy.c
@@ -329,11 +329,11 @@ csum_partial_cfu_unaligned(const unsigned long __user * src,
return checksum;
}
-static unsigned int
-do_csum_partial_copy_from_user(const char __user *src, char *dst, int len,
- unsigned int sum, int *errp)
+__wsum
+csum_partial_copy_from_user(const void __user *src, void *dst, int len,
+ __wsum sum, int *errp)
{
- unsigned long checksum = (unsigned) sum;
+ unsigned long checksum = (__force u32) sum;
unsigned long soff = 7 & (unsigned long) src;
unsigned long doff = 7 & (unsigned long) dst;
@@ -367,25 +367,12 @@ do_csum_partial_copy_from_user(const char __user *src, char *dst, int len,
}
checksum = from64to16 (checksum);
}
- return checksum;
-}
-
-unsigned int
-csum_partial_copy_from_user(const char __user *src, char *dst, int len,
- unsigned int sum, int *errp)
-{
- if (!access_ok(VERIFY_READ, src, len)) {
- *errp = -EFAULT;
- memset(dst, 0, len);
- return sum;
- }
-
- return do_csum_partial_copy_from_user(src, dst, len, sum, errp);
+ return (__force __wsum)checksum;
}
-unsigned int
-csum_partial_copy_nocheck(const char __user *src, char *dst, int len,
- unsigned int sum)
+__wsum
+csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
{
- return do_csum_partial_copy_from_user(src, dst, len, sum, NULL);
+ return csum_partial_copy_from_user((__force const void __user *)src,
+ dst, len, sum, NULL);
}
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index adb05de40e24..ce00c570459d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -879,6 +879,8 @@ endif
source "drivers/scsi/Kconfig"
+source "drivers/ata/Kconfig"
+
source "drivers/md/Kconfig"
source "drivers/message/fusion/Kconfig"
diff --git a/arch/arm/configs/assabet_defconfig b/arch/arm/configs/assabet_defconfig
index 089c9d598409..b1cd331aaecf 100644
--- a/arch/arm/configs/assabet_defconfig
+++ b/arch/arm/configs/assabet_defconfig
@@ -184,6 +184,7 @@ CONFIG_BINFMT_ELF=y
# Power management options
#
CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
# CONFIG_APM is not set
#
diff --git a/arch/arm/configs/cerfcube_defconfig b/arch/arm/configs/cerfcube_defconfig
index f81a60005cd3..09b7acd7f647 100644
--- a/arch/arm/configs/cerfcube_defconfig
+++ b/arch/arm/configs/cerfcube_defconfig
@@ -194,6 +194,7 @@ CONFIG_BINFMT_ELF=y
# Power management options
#
CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
# CONFIG_APM is not set
#
diff --git a/arch/arm/configs/corgi_defconfig b/arch/arm/configs/corgi_defconfig
index 3c3461e83398..c41c04fa5020 100644
--- a/arch/arm/configs/corgi_defconfig
+++ b/arch/arm/configs/corgi_defconfig
@@ -208,6 +208,7 @@ CONFIG_BINFMT_MISC=m
# Power management options
#
CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
CONFIG_APM=y
#
diff --git a/arch/arm/configs/h3600_defconfig b/arch/arm/configs/h3600_defconfig
index 7a0da0b7facb..8f986e9f1c62 100644
--- a/arch/arm/configs/h3600_defconfig
+++ b/arch/arm/configs/h3600_defconfig
@@ -194,6 +194,7 @@ CONFIG_BINFMT_ELF=y
# Power management options
#
CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
# CONFIG_APM is not set
#
diff --git a/arch/arm/configs/integrator_defconfig b/arch/arm/configs/integrator_defconfig
index d1ba7fdde818..692ab57ba1ca 100644
--- a/arch/arm/configs/integrator_defconfig
+++ b/arch/arm/configs/integrator_defconfig
@@ -190,6 +190,7 @@ CONFIG_BINFMT_ELF=y
# Power management options
#
CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
# CONFIG_APM is not set
#
diff --git a/arch/arm/configs/jornada720_defconfig b/arch/arm/configs/jornada720_defconfig
index ad1048db96fb..80a6fd97eb32 100644
--- a/arch/arm/configs/jornada720_defconfig
+++ b/arch/arm/configs/jornada720_defconfig
@@ -182,6 +182,7 @@ CONFIG_BINFMT_AOUT=m
# Power management options
#
CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
# CONFIG_APM is not set
#
diff --git a/arch/arm/configs/lart_defconfig b/arch/arm/configs/lart_defconfig
index c3a932844160..a1cc34f25602 100644
--- a/arch/arm/configs/lart_defconfig
+++ b/arch/arm/configs/lart_defconfig
@@ -180,6 +180,7 @@ CONFIG_BINFMT_AOUT=y
# Power management options
#
CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
CONFIG_APM=m
#
diff --git a/arch/arm/configs/neponset_defconfig b/arch/arm/configs/neponset_defconfig
index 3d35255c64ed..df8168e57b7c 100644
--- a/arch/arm/configs/neponset_defconfig
+++ b/arch/arm/configs/neponset_defconfig
@@ -190,6 +190,7 @@ CONFIG_BINFMT_AOUT=y
# Power management options
#
CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
CONFIG_APM=y
#
diff --git a/arch/arm/configs/simpad_defconfig b/arch/arm/configs/simpad_defconfig
index 2e5a616cc98d..140056a3507f 100644
--- a/arch/arm/configs/simpad_defconfig
+++ b/arch/arm/configs/simpad_defconfig
@@ -180,6 +180,7 @@ CONFIG_BINFMT_MISC=m
# Power management options
#
CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
CONFIG_APM=y
#
diff --git a/arch/arm/configs/spitz_defconfig b/arch/arm/configs/spitz_defconfig
index d1ace3abfd8a..bd03238968c1 100644
--- a/arch/arm/configs/spitz_defconfig
+++ b/arch/arm/configs/spitz_defconfig
@@ -207,6 +207,7 @@ CONFIG_BINFMT_MISC=m
# Power management options
#
CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
CONFIG_APM=y
#
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index a07d202143c3..070bcb7a6306 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -451,6 +451,7 @@ int smp_call_function(void (*func)(void *info), void *info, int retry,
return smp_call_function_on_cpu(func, info, retry, wait,
cpu_online_map);
}
+EXPORT_SYMBOL_GPL(smp_call_function);
void show_ipi_list(struct seq_file *p)
{
diff --git a/arch/arm/mach-ebsa110/io.c b/arch/arm/mach-ebsa110/io.c
index c648bfb676a1..db38afb2aa88 100644
--- a/arch/arm/mach-ebsa110/io.c
+++ b/arch/arm/mach-ebsa110/io.c
@@ -28,7 +28,7 @@
#include <asm/io.h>
#include <asm/page.h>
-static void __iomem *__isamem_convert_addr(void __iomem *addr)
+static void __iomem *__isamem_convert_addr(const volatile void __iomem *addr)
{
u32 ret, a = (u32 __force) addr;
@@ -63,7 +63,7 @@ static void __iomem *__isamem_convert_addr(void __iomem *addr)
/*
* read[bwl] and write[bwl]
*/
-u8 __readb(void __iomem *addr)
+u8 __readb(const volatile void __iomem *addr)
{
void __iomem *a = __isamem_convert_addr(addr);
u32 ret;
@@ -75,7 +75,7 @@ u8 __readb(void __iomem *addr)
return ret;
}
-u16 __readw(void __iomem *addr)
+u16 __readw(const volatile void __iomem *addr)
{
void __iomem *a = __isamem_convert_addr(addr);
@@ -85,7 +85,7 @@ u16 __readw(void __iomem *addr)
return __raw_readw(a);
}
-u32 __readl(void __iomem *addr)
+u32 __readl(const volatile void __iomem *addr)
{
void __iomem *a = __isamem_convert_addr(addr);
u32 ret;
diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig
index 57f23b465392..e316bd93313f 100644
--- a/arch/arm/mach-ixp4xx/Kconfig
+++ b/arch/arm/mach-ixp4xx/Kconfig
@@ -133,7 +133,7 @@ config IXP4XX_INDIRECT_PCI
into the kernel and we can use the standard read[bwl]/write[bwl]
macros. This is the preferred method due to speed but it
limits the system to just 64MB of PCI memory. This can be
- problamatic if using video cards and other memory-heavy devices.
+ problematic if using video cards and other memory-heavy devices.
2) If > 64MB of memory space is required, the IXP4xx can be
configured to use indirect registers to access PCI This allows
diff --git a/arch/arm/mach-lh7a40x/Kconfig b/arch/arm/mach-lh7a40x/Kconfig
index 147b01928a9b..6f4c6a1798c1 100644
--- a/arch/arm/mach-lh7a40x/Kconfig
+++ b/arch/arm/mach-lh7a40x/Kconfig
@@ -8,7 +8,7 @@ config MACH_KEV7A400
help
Say Y here if you are using the Sharp KEV7A400 development
board. This hardware is discontinued, so I'd be very
- suprised if you wanted this option.
+ surprised if you wanted this option.
config MACH_LPD7A400
bool "LPD7A400 Card Engine"
diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
index 63965c78de8c..9aa26b99045d 100644
--- a/arch/arm/mach-s3c2410/Kconfig
+++ b/arch/arm/mach-s3c2410/Kconfig
@@ -91,7 +91,7 @@ config SMDK2440_CPU2442
config MACH_S3C2413
bool
help
- Internal node for S3C2413 verison of SMDK2413, so that
+ Internal node for S3C2413 version of SMDK2413, so that
machine_is_s3c2413() will work when MACH_SMDK2413 is
selected
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index c0bfb8212b77..b09a19f87d68 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -197,7 +197,7 @@ config CPU_ARM940T
select CPU_CP15_MPU
help
ARM940T is a member of the ARM9TDMI family of general-
- purpose microprocessors with MPU and seperate 4KB
+ purpose microprocessors with MPU and separate 4KB
instruction and 4KB data cases, each with a 4-word line
length.
diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c
index 50e6b6bfb2e2..b797217e82be 100644
--- a/arch/arm/mm/consistent.c
+++ b/arch/arm/mm/consistent.c
@@ -476,6 +476,9 @@ core_initcall(consistent_init);
/*
* Make an area consistent for devices.
+ * Note: Drivers should NOT use this function directly, as it will break
+ * platforms with CONFIG_DMABOUNCE.
+ * Use the driver DMA support - see dma-mapping.h (dma_sync_*)
*/
void consistent_sync(void *vaddr, size_t size, int direction)
{
diff --git a/arch/cris/arch-v10/Kconfig b/arch/cris/arch-v10/Kconfig
index 44eb1b9accb3..c7ea9efd0104 100644
--- a/arch/cris/arch-v10/Kconfig
+++ b/arch/cris/arch-v10/Kconfig
@@ -323,7 +323,7 @@ config ETRAX_DEF_R_WAITSTATES
depends on ETRAX_ARCH_V10
default "95a6"
help
- Waitstates for SRAM, Flash and peripherials (not DRAM). 95f8 is a
+ Waitstates for SRAM, Flash and peripherals (not DRAM). 95f8 is a
good choice for most Axis products...
config ETRAX_DEF_R_BUS_CONFIG
diff --git a/arch/cris/arch-v10/drivers/Kconfig b/arch/cris/arch-v10/drivers/Kconfig
index 734d5f3a5304..e7e724bc0ba6 100644
--- a/arch/cris/arch-v10/drivers/Kconfig
+++ b/arch/cris/arch-v10/drivers/Kconfig
@@ -839,7 +839,7 @@ config ETRAX_DS1302_TRICKLE_CHARGE
default "0"
help
This controls the initial value of the trickle charge register.
- 0 = disabled (use this if you are unsure or have a non rechargable battery)
+ 0 = disabled (use this if you are unsure or have a non rechargeable battery)
Otherwise the following values can be OR:ed together to control the
charge current:
1 = 2kohm, 2 = 4kohm, 3 = 4kohm
diff --git a/arch/cris/arch-v10/drivers/eeprom.c b/arch/cris/arch-v10/drivers/eeprom.c
index 6e1f191a71e3..284ebfda03f0 100644
--- a/arch/cris/arch-v10/drivers/eeprom.c
+++ b/arch/cris/arch-v10/drivers/eeprom.c
@@ -1,7 +1,7 @@
/*!*****************************************************************************
*!
-*! Implements an interface for i2c compatible eeproms to run under linux.
-*! Supports 2k, 8k(?) and 16k. Uses adaptive timing adjustents by
+*! Implements an interface for i2c compatible eeproms to run under Linux.
+*! Supports 2k, 8k(?) and 16k. Uses adaptive timing adjustments by
*! Johan.Adolfsson@axis.com
*!
*! Probing results:
@@ -51,7 +51,7 @@
*! Revision 1.8 2001/06/15 13:24:29 jonashg
*! * Added verification of pointers from userspace in read and write.
*! * Made busy counter volatile.
-*! * Added define for inital write delay.
+*! * Added define for initial write delay.
*! * Removed warnings by using loff_t instead of unsigned long.
*!
*! Revision 1.7 2001/06/14 15:26:54 jonashg
diff --git a/arch/cris/arch-v10/drivers/i2c.c b/arch/cris/arch-v10/drivers/i2c.c
index 6114596c3b33..092c724a645f 100644
--- a/arch/cris/arch-v10/drivers/i2c.c
+++ b/arch/cris/arch-v10/drivers/i2c.c
@@ -47,7 +47,7 @@
*! Update Port B register and shadow even when running with hardware support
*! to avoid glitches when reading bits
*! Never set direction to out in i2c_inbyte
-*! Removed incorrect clock togling at end of i2c_inbyte
+*! Removed incorrect clock toggling at end of i2c_inbyte
*!
*! Revision 1.8 2002/08/13 06:31:53 starvik
*! Made SDA and SCL line configurable
diff --git a/arch/cris/arch-v10/kernel/kgdb.c b/arch/cris/arch-v10/kernel/kgdb.c
index 34528da98817..07628a13c6c4 100644
--- a/arch/cris/arch-v10/kernel/kgdb.c
+++ b/arch/cris/arch-v10/kernel/kgdb.c
@@ -33,7 +33,7 @@
*!
*! Revision 1.2 2002/11/19 14:35:24 starvik
*! Changes from linux 2.4
-*! Changed struct initializer syntax to the currently prefered notation
+*! Changed struct initializer syntax to the currently preferred notation
*!
*! Revision 1.1 2001/12/17 13:59:27 bjornw
*! Initial revision
diff --git a/arch/cris/arch-v10/lib/old_checksum.c b/arch/cris/arch-v10/lib/old_checksum.c
index 22a6f0aa9cef..497634a64829 100644
--- a/arch/cris/arch-v10/lib/old_checksum.c
+++ b/arch/cris/arch-v10/lib/old_checksum.c
@@ -47,39 +47,41 @@
#include <asm/delay.h>
-unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
+__wsum csum_partial(const void *p, int len, __wsum __sum)
{
- /*
- * Experiments with ethernet and slip connections show that buff
- * is aligned on either a 2-byte or 4-byte boundary.
- */
- const unsigned char *endMarker = buff + len;
- const unsigned char *marker = endMarker - (len % 16);
+ u32 sum = (__force u32)__sum;
+ const u16 *buff = p;
+ /*
+ * Experiments with ethernet and slip connections show that buff
+ * is aligned on either a 2-byte or 4-byte boundary.
+ */
+ const void *endMarker = p + len;
+ const void *marker = endMarker - (len % 16);
#if 0
- if((int)buff & 0x3)
- printk("unaligned buff %p\n", buff);
- __delay(900); /* extra delay of 90 us to test performance hit */
+ if((int)buff & 0x3)
+ printk("unaligned buff %p\n", buff);
+ __delay(900); /* extra delay of 90 us to test performance hit */
#endif
- BITON;
- while (buff < marker) {
- sum += *((unsigned short *)buff)++;
- sum += *((unsigned short *)buff)++;
- sum += *((unsigned short *)buff)++;
- sum += *((unsigned short *)buff)++;
- sum += *((unsigned short *)buff)++;
- sum += *((unsigned short *)buff)++;
- sum += *((unsigned short *)buff)++;
- sum += *((unsigned short *)buff)++;
- }
- marker = endMarker - (len % 2);
- while(buff < marker) {
- sum += *((unsigned short *)buff)++;
- }
- if(endMarker - buff > 0) {
- sum += *buff; /* add extra byte seperately */
- }
- BITOFF;
- return(sum);
+ BITON;
+ while (buff < marker) {
+ sum += *buff++;
+ sum += *buff++;
+ sum += *buff++;
+ sum += *buff++;
+ sum += *buff++;
+ sum += *buff++;
+ sum += *buff++;
+ sum += *buff++;
+ }
+ marker = endMarker - (len % 2);
+ while (buff < marker)
+ sum += *buff++;
+
+ if (endMarker > buff)
+ sum += *(const u8 *)buff; /* add extra byte seperately */
+
+ BITOFF;
+ return (__force __wsum)sum;
}
EXPORT_SYMBOL(csum_partial);
diff --git a/arch/cris/arch-v32/drivers/Kconfig b/arch/cris/arch-v32/drivers/Kconfig
index a33097f95362..f64624fc4504 100644
--- a/arch/cris/arch-v32/drivers/Kconfig
+++ b/arch/cris/arch-v32/drivers/Kconfig
@@ -88,7 +88,7 @@ config ETRAX_SERIAL_PORT0_DMA7_IN
help
Enables the DMA7 input channel for ser0 (ttyS0).
If you do not enable DMA, an interrupt for each character will be
- used when receiveing data.
+ used when receiving data.
Normally you want to use DMA, unless you use the DMA channel for
something else.
@@ -157,7 +157,7 @@ config ETRAX_SERIAL_PORT1_DMA5_IN
help
Enables the DMA5 input channel for ser1 (ttyS1).
If you do not enable DMA, an interrupt for each character will be
- used when receiveing data.
+ used when receiving data.
Normally you want this on, unless you use the DMA channel for
something else.
@@ -228,7 +228,7 @@ config ETRAX_SERIAL_PORT2_DMA3_IN
help
Enables the DMA3 input channel for ser2 (ttyS2).
If you do not enable DMA, an interrupt for each character will be
- used when receiveing data.
+ used when receiving data.
Normally you want to use DMA, unless you use the DMA channel for
something else.
@@ -297,7 +297,7 @@ config ETRAX_SERIAL_PORT3_DMA9_IN
help
Enables the DMA9 input channel for ser3 (ttyS3).
If you do not enable DMA, an interrupt for each character will be
- used when receiveing data.
+ used when receiving data.
Normally you want to use DMA, unless you use the DMA channel for
something else.
diff --git a/arch/frv/lib/checksum.c b/arch/frv/lib/checksum.c
index 20e7dfc474ef..44e16d59bc10 100644
--- a/arch/frv/lib/checksum.c
+++ b/arch/frv/lib/checksum.c
@@ -32,7 +32,6 @@
of the assembly has to go. */
#include <net/checksum.h>
-#include <asm/checksum.h>
#include <linux/module.h>
static inline unsigned short from32to16(unsigned long x)
@@ -105,15 +104,15 @@ out:
*
* it's best to have buff aligned on a 32-bit boundary
*/
-unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
+__wsum csum_partial(const void *buff, int len, __wsum sum)
{
unsigned int result = do_csum(buff, len);
/* add in old sum, and carry.. */
- result += sum;
- if (sum > result)
+ result += (__force u32)sum;
+ if ((__force u32)sum > result)
result += 1;
- return result;
+ return (__force __wsum)result;
}
EXPORT_SYMBOL(csum_partial);
@@ -122,9 +121,9 @@ EXPORT_SYMBOL(csum_partial);
* this routine is used for miscellaneous IP-like checksums, mainly
* in icmp.c
*/
-unsigned short ip_compute_csum(const unsigned char * buff, int len)
+__sum16 ip_compute_csum(const void *buff, int len)
{
- return ~do_csum(buff, len);
+ return (__force __sum16)~do_csum(buff, len);
}
EXPORT_SYMBOL(ip_compute_csum);
@@ -132,9 +131,9 @@ EXPORT_SYMBOL(ip_compute_csum);
/*
* copy from fs while checksumming, otherwise like csum_partial
*/
-unsigned int
-csum_partial_copy_from_user(const char __user *src, char *dst,
- int len, int sum, int *csum_err)
+__wsum
+csum_partial_copy_from_user(const void __user *src, void *dst,
+ int len, __wsum sum, int *csum_err)
{
int rem;
@@ -157,11 +156,11 @@ EXPORT_SYMBOL(csum_partial_copy_from_user);
/*
* copy from ds while checksumming, otherwise like csum_partial
*/
-unsigned int
-csum_partial_copy(const char *src, char *dst, int len, int sum)
+__wsum
+csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
{
memcpy(dst, src, len);
return csum_partial(dst, len, sum);
}
-EXPORT_SYMBOL(csum_partial_copy);
+EXPORT_SYMBOL(csum_partial_copy_nocheck);
diff --git a/arch/h8300/kernel/h8300_ksyms.c b/arch/h8300/kernel/h8300_ksyms.c
index 9b4be053de3c..d1b15267ac81 100644
--- a/arch/h8300/kernel/h8300_ksyms.c
+++ b/arch/h8300/kernel/h8300_ksyms.c
@@ -39,7 +39,7 @@ EXPORT_SYMBOL(enable_irq);
EXPORT_SYMBOL(disable_irq);
/* Networking helper routines. */
-EXPORT_SYMBOL(csum_partial_copy);
+EXPORT_SYMBOL(csum_partial_copy_nocheck);
/* The following are special because they're not called
explicitly (the C compiler generates them). Fortunately,
diff --git a/arch/h8300/lib/checksum.c b/arch/h8300/lib/checksum.c
index 5aa688d9242d..bdc5b032acd6 100644
--- a/arch/h8300/lib/checksum.c
+++ b/arch/h8300/lib/checksum.c
@@ -96,9 +96,9 @@ out:
* This is a version of ip_compute_csum() optimized for IP headers,
* which always checksum on 4 octet boundaries.
*/
-unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl)
+__sum16 ip_fast_csum(const void *iph, unsigned int ihl)
{
- return ~do_csum(iph,ihl*4);
+ return (__force __sum16)~do_csum(iph,ihl*4);
}
/*
@@ -113,15 +113,19 @@ unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl)
*
* it's best to have buff aligned on a 32-bit boundary
*/
-unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
+/*
+ * Egads... That thing apparently assumes that *all* checksums it ever sees will
+ * be folded. Very likely a bug.
+ */
+__wsum csum_partial(const void *buff, int len, __wsum sum)
{
unsigned int result = do_csum(buff, len);
/* add in old sum, and carry.. */
- result += sum;
+ result += (__force u32)sum;
/* 16+c bits -> 16 bits */
result = (result & 0xffff) + (result >> 16);
- return result;
+ return (__force __wsum)result;
}
EXPORT_SYMBOL(csum_partial);
@@ -130,20 +134,21 @@ EXPORT_SYMBOL(csum_partial);
* this routine is used for miscellaneous IP-like checksums, mainly
* in icmp.c
*/
-unsigned short ip_compute_csum(const unsigned char * buff, int len)
+__sum16 ip_compute_csum(const void *buff, int len)
{
- return ~do_csum(buff,len);
+ return (__force __sum16)~do_csum(buff,len);
}
/*
* copy from fs while checksumming, otherwise like csum_partial
*/
-unsigned int
-csum_partial_copy_from_user(const char *src, char *dst, int len, int sum, int *csum_err)
+__wsum
+csum_partial_copy_from_user(const void __user *src, void *dst, int len,
+ __wsum sum, int *csum_err)
{
if (csum_err) *csum_err = 0;
- memcpy(dst, src, len);
+ memcpy(dst, (__force const void *)src, len);
return csum_partial(dst, len, sum);
}
@@ -151,8 +156,8 @@ csum_partial_copy_from_user(const char *src, char *dst, int len, int sum, int *c
* copy from ds while checksumming, otherwise like csum_partial
*/
-unsigned int
-csum_partial_copy(const char *src, char *dst, int len, int sum)
+__wsum
+csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
{
memcpy(dst, src, len);
return csum_partial(dst, len, sum);
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
index d12fb97a5337..c8f96cff07c6 100644
--- a/arch/i386/kernel/acpi/boot.c
+++ b/arch/i386/kernel/acpi/boot.c
@@ -333,7 +333,7 @@ acpi_parse_ioapic(acpi_table_entry_header * header, const unsigned long end)
/*
* Parse Interrupt Source Override for the ACPI SCI
*/
-static void acpi_sci_ioapic_setup(u32 bus_irq, u32 gsi, u16 polarity, u16 trigger)
+static void acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
{
if (trigger == 0) /* compatible SCI trigger is level */
trigger = 3;
@@ -353,13 +353,13 @@ static void acpi_sci_ioapic_setup(u32 bus_irq, u32 gsi, u16 polarity, u16 trigge
* If GSI is < 16, this will update its flags,
* else it will create a new mp_irqs[] entry.
*/
- mp_override_legacy_irq(bus_irq, polarity, trigger, gsi);
+ mp_override_legacy_irq(gsi, polarity, trigger, gsi);
/*
* stash over-ride to indicate we've been here
* and for later update of acpi_fadt
*/
- acpi_sci_override_gsi = bus_irq;
+ acpi_sci_override_gsi = gsi;
return;
}
@@ -377,7 +377,7 @@ acpi_parse_int_src_ovr(acpi_table_entry_header * header,
acpi_table_print_madt_entry(header);
if (intsrc->bus_irq == acpi_fadt.sci_int) {
- acpi_sci_ioapic_setup(intsrc->bus_irq, intsrc->global_irq,
+ acpi_sci_ioapic_setup(intsrc->global_irq,
intsrc->flags.polarity,
intsrc->flags.trigger);
return 0;
@@ -880,7 +880,7 @@ static int __init acpi_parse_madt_ioapic_entries(void)
* pretend we got one so we can set the SCI flags.
*/
if (!acpi_sci_override_gsi)
- acpi_sci_ioapic_setup(acpi_fadt.sci_int, acpi_fadt.sci_int, 0, 0);
+ acpi_sci_ioapic_setup(acpi_fadt.sci_int, 0, 0);
/* Fill in identity legacy mapings where no override */
mp_config_acpi_legacy_irqs();
diff --git a/arch/i386/kernel/cpuid.c b/arch/i386/kernel/cpuid.c
index fde8bea85cee..ab0c327e79dc 100644
--- a/arch/i386/kernel/cpuid.c
+++ b/arch/i386/kernel/cpuid.c
@@ -156,14 +156,14 @@ static struct file_operations cpuid_fops = {
.open = cpuid_open,
};
-static int cpuid_class_device_create(int i)
+static int cpuid_device_create(int i)
{
int err = 0;
- struct class_device *class_err;
+ struct device *dev;
- class_err = class_device_create(cpuid_class, NULL, MKDEV(CPUID_MAJOR, i), NULL, "cpu%d",i);
- if (IS_ERR(class_err))
- err = PTR_ERR(class_err);
+ dev = device_create(cpuid_class, NULL, MKDEV(CPUID_MAJOR, i), "cpu%d",i);
+ if (IS_ERR(dev))
+ err = PTR_ERR(dev);
return err;
}
@@ -174,10 +174,10 @@ static int cpuid_class_cpu_callback(struct notifier_block *nfb, unsigned long ac
switch (action) {
case CPU_ONLINE:
- cpuid_class_device_create(cpu);
+ cpuid_device_create(cpu);
break;
case CPU_DEAD:
- class_device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu));
+ device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu));
break;
}
return NOTIFY_OK;
@@ -206,7 +206,7 @@ static int __init cpuid_init(void)
goto out_chrdev;
}
for_each_online_cpu(i) {
- err = cpuid_class_device_create(i);
+ err = cpuid_device_create(i);
if (err != 0)
goto out_class;
}
@@ -218,7 +218,7 @@ static int __init cpuid_init(void)
out_class:
i = 0;
for_each_online_cpu(i) {
- class_device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, i));
+ device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, i));
}
class_destroy(cpuid_class);
out_chrdev:
@@ -232,7 +232,7 @@ static void __exit cpuid_exit(void)
int cpu = 0;
for_each_online_cpu(cpu)
- class_device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu));
+ device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu));
class_destroy(cpuid_class);
unregister_chrdev(CPUID_MAJOR, "cpu/cpuid");
unregister_hotcpu_notifier(&cpuid_class_cpu_notifier);
diff --git a/arch/i386/kernel/msr.c b/arch/i386/kernel/msr.c
index d535cdbbfd25..a773f776c9ea 100644
--- a/arch/i386/kernel/msr.c
+++ b/arch/i386/kernel/msr.c
@@ -239,14 +239,14 @@ static struct file_operations msr_fops = {
.open = msr_open,
};
-static int msr_class_device_create(int i)
+static int msr_device_create(int i)
{
int err = 0;
- struct class_device *class_err;
+ struct device *dev;
- class_err = class_device_create(msr_class, NULL, MKDEV(MSR_MAJOR, i), NULL, "msr%d",i);
- if (IS_ERR(class_err))
- err = PTR_ERR(class_err);
+ dev = device_create(msr_class, NULL, MKDEV(MSR_MAJOR, i), "msr%d",i);
+ if (IS_ERR(dev))
+ err = PTR_ERR(dev);
return err;
}
@@ -258,10 +258,10 @@ static int msr_class_cpu_callback(struct notifier_block *nfb,
switch (action) {
case CPU_ONLINE:
- msr_class_device_create(cpu);
+ msr_device_create(cpu);
break;
case CPU_DEAD:
- class_device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu));
+ device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu));
break;
}
return NOTIFY_OK;
@@ -290,7 +290,7 @@ static int __init msr_init(void)
goto out_chrdev;
}
for_each_online_cpu(i) {
- err = msr_class_device_create(i);
+ err = msr_device_create(i);
if (err != 0)
goto out_class;
}
@@ -302,7 +302,7 @@ static int __init msr_init(void)
out_class:
i = 0;
for_each_online_cpu(i)
- class_device_destroy(msr_class, MKDEV(MSR_MAJOR, i));
+ device_destroy(msr_class, MKDEV(MSR_MAJOR, i));
class_destroy(msr_class);
out_chrdev:
unregister_chrdev(MSR_MAJOR, "cpu/msr");
@@ -314,7 +314,7 @@ static void __exit msr_exit(void)
{
int cpu = 0;
for_each_online_cpu(cpu)
- class_device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu));
+ device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu));
class_destroy(msr_class);
unregister_chrdev(MSR_MAJOR, "cpu/msr");
unregister_hotcpu_notifier(&msr_class_cpu_notifier);
diff --git a/arch/i386/kernel/pci-dma.c b/arch/i386/kernel/pci-dma.c
index 25fe66853934..5c8c6ef1fc5e 100644
--- a/arch/i386/kernel/pci-dma.c
+++ b/arch/i386/kernel/pci-dma.c
@@ -75,7 +75,7 @@ EXPORT_SYMBOL(dma_free_coherent);
int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
dma_addr_t device_addr, size_t size, int flags)
{
- void __iomem *mem_base;
+ void __iomem *mem_base = NULL;
int pages = size >> PAGE_SHIFT;
int bitmap_size = (pages + 31)/32;
@@ -114,6 +114,8 @@ int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
free1_out:
kfree(dev->dma_mem->bitmap);
out:
+ if (mem_base)
+ iounmap(mem_base);
return 0;
}
EXPORT_SYMBOL(dma_declare_coherent_memory);
diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c
index cdfcf971098b..53ca6e897984 100644
--- a/arch/i386/pci/common.c
+++ b/arch/i386/pci/common.c
@@ -20,7 +20,7 @@
unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |
PCI_PROBE_MMCONF;
-int pci_bf_sort;
+static int pci_bf_sort;
int pci_routeirq;
int pcibios_last_bus = -1;
unsigned long pirq_table_addr;
diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c
index c1949ff38d61..cde1170b01a1 100644
--- a/arch/i386/pci/fixup.c
+++ b/arch/i386/pci/fixup.c
@@ -74,52 +74,6 @@ static void __devinit pci_fixup_ncr53c810(struct pci_dev *d)
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, pci_fixup_ncr53c810);
-static void __devinit pci_fixup_ide_bases(struct pci_dev *d)
-{
- int i;
-
- /*
- * PCI IDE controllers use non-standard I/O port decoding, respect it.
- */
- if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
- return;
- DBG("PCI: IDE base address fixup for %s\n", pci_name(d));
- for(i=0; i<4; i++) {
- struct resource *r = &d->resource[i];
- if ((r->start & ~0x80) == 0x374) {
- r->start |= 2;
- r->end = r->start;
- }
- }
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
-
-static void __devinit pci_fixup_ide_trash(struct pci_dev *d)
-{
- int i;
-
- /*
- * Runs the fixup only for the first IDE controller
- * (Shai Fultheim - shai@ftcon.com)
- */
- static int called = 0;
- if (called)
- return;
- called = 1;
-
- /*
- * There exist PCI IDE controllers which have utter garbage
- * in first four base registers. Ignore that.
- */
- DBG("PCI: IDE base address trash cleared for %s\n", pci_name(d));
- for(i=0; i<4; i++)
- d->resource[i].start = d->resource[i].end = d->resource[i].flags = 0;
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, pci_fixup_ide_trash);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10, pci_fixup_ide_trash);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_11, pci_fixup_ide_trash);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_9, pci_fixup_ide_trash);
-
static void __devinit pci_fixup_latency(struct pci_dev *d)
{
/*
diff --git a/arch/i386/pci/i386.c b/arch/i386/pci/i386.c
index 98580292f0d4..43005f044424 100644
--- a/arch/i386/pci/i386.c
+++ b/arch/i386/pci/i386.c
@@ -104,16 +104,24 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
/* Depth-First Search on bus tree */
list_for_each_entry(bus, bus_list, node) {
if ((dev = bus->self)) {
- for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
+ for (idx = PCI_BRIDGE_RESOURCES;
+ idx < PCI_NUM_RESOURCES; idx++) {
r = &dev->resource[idx];
if (!r->flags)
continue;
pr = pci_find_parent_resource(dev, r);
- if (!r->start || !pr || request_resource(pr, r) < 0) {
- printk(KERN_ERR "PCI: Cannot allocate resource region %d of bridge %s\n", idx, pci_name(dev));
- /* Something is wrong with the region.
- Invalidate the resource to prevent child
- resource allocations in this range. */
+ if (!r->start || !pr ||
+ request_resource(pr, r) < 0) {
+ printk(KERN_ERR "PCI: Cannot allocate "
+ "resource region %d "
+ "of bridge %s\n",
+ idx, pci_name(dev));
+ /*
+ * Something is wrong with the region.
+ * Invalidate the resource to prevent
+ * child resource allocations in this
+ * range.
+ */
r->flags = 0;
}
}
@@ -131,7 +139,7 @@ static void __init pcibios_allocate_resources(int pass)
for_each_pci_dev(dev) {
pci_read_config_word(dev, PCI_COMMAND, &command);
- for(idx = 0; idx < 6; idx++) {
+ for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) {
r = &dev->resource[idx];
if (r->parent) /* Already allocated */
continue;
@@ -142,11 +150,15 @@ static void __init pcibios_allocate_resources(int pass)
else
disabled = !(command & PCI_COMMAND_MEMORY);
if (pass == disabled) {
- DBG("PCI: Resource %08lx-%08lx (f=%lx, d=%d, p=%d)\n",
+ DBG("PCI: Resource %08lx-%08lx "
+ "(f=%lx, d=%d, p=%d)\n",
r->start, r->end, r->flags, disabled, pass);
pr = pci_find_parent_resource(dev, r);
if (!pr || request_resource(pr, r) < 0) {
- printk(KERN_ERR "PCI: Cannot allocate resource region %d of device %s\n", idx, pci_name(dev));
+ printk(KERN_ERR "PCI: Cannot allocate "
+ "resource region %d "
+ "of device %s\n",
+ idx, pci_name(dev));
/* We'll assign a new address later */
r->end -= r->start;
r->start = 0;
@@ -156,12 +168,16 @@ static void __init pcibios_allocate_resources(int pass)
if (!pass) {
r = &dev->resource[PCI_ROM_RESOURCE];
if (r->flags & IORESOURCE_ROM_ENABLE) {
- /* Turn the ROM off, leave the resource region, but keep it unregistered. */
+ /* Turn the ROM off, leave the resource region,
+ * but keep it unregistered. */
u32 reg;
- DBG("PCI: Switching off ROM of %s\n", pci_name(dev));
+ DBG("PCI: Switching off ROM of %s\n",
+ pci_name(dev));
r->flags &= ~IORESOURCE_ROM_ENABLE;
- pci_read_config_dword(dev, dev->rom_base_reg, &reg);
- pci_write_config_dword(dev, dev->rom_base_reg, reg & ~PCI_ROM_ADDRESS_ENABLE);
+ pci_read_config_dword(dev,
+ dev->rom_base_reg, &reg);
+ pci_write_config_dword(dev, dev->rom_base_reg,
+ reg & ~PCI_ROM_ADDRESS_ENABLE);
}
}
}
@@ -173,9 +189,11 @@ static int __init pcibios_assign_resources(void)
struct resource *r, *pr;
if (!(pci_probe & PCI_ASSIGN_ROMS)) {
- /* Try to use BIOS settings for ROMs, otherwise let
- pci_assign_unassigned_resources() allocate the new
- addresses. */
+ /*
+ * Try to use BIOS settings for ROMs, otherwise let
+ * pci_assign_unassigned_resources() allocate the new
+ * addresses.
+ */
for_each_pci_dev(dev) {
r = &dev->resource[PCI_ROM_RESOURCE];
if (!r->flags || !r->start)
@@ -215,9 +233,9 @@ int pcibios_enable_resources(struct pci_dev *dev, int mask)
pci_read_config_word(dev, PCI_COMMAND, &cmd);
old_cmd = cmd;
- for(idx = 0; idx < PCI_NUM_RESOURCES; idx++) {
+ for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) {
/* Only set up the requested stuff */
- if (!(mask & (1<<idx)))
+ if (!(mask & (1 << idx)))
continue;
r = &dev->resource[idx];
@@ -227,7 +245,9 @@ int pcibios_enable_resources(struct pci_dev *dev, int mask)
(!(r->flags & IORESOURCE_ROM_ENABLE)))
continue;
if (!r->start && r->end) {
- printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev));
+ printk(KERN_ERR "PCI: Device %s not available "
+ "because of resource collisions\n",
+ pci_name(dev));
return -EINVAL;
}
if (r->flags & IORESOURCE_IO)
@@ -236,7 +256,8 @@ int pcibios_enable_resources(struct pci_dev *dev, int mask)
cmd |= PCI_COMMAND_MEMORY;
}
if (cmd != old_cmd) {
- printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd);
+ printk("PCI: Enabling device %s (%04x -> %04x)\n",
+ pci_name(dev), old_cmd, cmd);
pci_write_config_word(dev, PCI_COMMAND, cmd);
}
return 0;
@@ -258,7 +279,8 @@ void pcibios_set_master(struct pci_dev *dev)
lat = pcibios_max_latency;
else
return;
- printk(KERN_DEBUG "PCI: Setting latency timer of device %s to %d\n", pci_name(dev), lat);
+ printk(KERN_DEBUG "PCI: Setting latency timer of device %s to %d\n",
+ pci_name(dev), lat);
pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
}
diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c
index 69163998adeb..e65551cd8216 100644
--- a/arch/i386/pci/irq.c
+++ b/arch/i386/pci/irq.c
@@ -543,6 +543,12 @@ static __init int intel_router_probe(struct irq_router *r, struct pci_dev *route
case PCI_DEVICE_ID_INTEL_ICH8_2:
case PCI_DEVICE_ID_INTEL_ICH8_3:
case PCI_DEVICE_ID_INTEL_ICH8_4:
+ case PCI_DEVICE_ID_INTEL_ICH9_0:
+ case PCI_DEVICE_ID_INTEL_ICH9_1:
+ case PCI_DEVICE_ID_INTEL_ICH9_2:
+ case PCI_DEVICE_ID_INTEL_ICH9_3:
+ case PCI_DEVICE_ID_INTEL_ICH9_4:
+ case PCI_DEVICE_ID_INTEL_ICH9_5:
r->name = "PIIX/ICH";
r->get = pirq_piix_get;
r->set = pirq_piix_set;
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index db8e1fcfa047..14691cda05c3 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -75,7 +75,7 @@
** If a device prefetches beyond the end of a valid pdir entry, it will cause
** a hard failure, ie. MCA. Version 3.0 and later of the zx1 LBA should
** disconnect on 4k boundaries and prevent such issues. If the device is
-** particularly agressive, this option will keep the entire pdir valid such
+** particularly aggressive, this option will keep the entire pdir valid such
** that prefetching will hit a valid address. This could severely impact
** error containment, and is therefore off by default. The page that is
** used for spill-over is poisoned, so that should help debugging somewhat.
@@ -258,10 +258,10 @@ static u64 prefetch_spill_page;
/*
** DMA_CHUNK_SIZE is used by the SCSI mid-layer to break up
-** (or rather not merge) DMA's into managable chunks.
+** (or rather not merge) DMAs into manageable chunks.
** On parisc, this is more of the software/tuning constraint
-** rather than the HW. I/O MMU allocation alogorithms can be
-** faster with smaller size is (to some degree).
+** rather than the HW. I/O MMU allocation algorithms can be
+** faster with smaller sizes (to some degree).
*/
#define DMA_CHUNK_SIZE (BITS_PER_LONG*iovp_size)
diff --git a/arch/ia64/lib/checksum.c b/arch/ia64/lib/checksum.c
index beb11721d9f5..4411d9baeb21 100644
--- a/arch/ia64/lib/checksum.c
+++ b/arch/ia64/lib/checksum.c
@@ -33,32 +33,32 @@ from64to16 (unsigned long x)
* computes the checksum of the TCP/UDP pseudo-header
* returns a 16-bit checksum, already complemented.
*/
-unsigned short int
-csum_tcpudp_magic (unsigned long saddr, unsigned long daddr, unsigned short len,
- unsigned short proto, unsigned int sum)
+__sum16
+csum_tcpudp_magic (__be32 saddr, __be32 daddr, unsigned short len,
+ unsigned short proto, __wsum sum)
{
- return ~from64to16(saddr + daddr + sum + ((unsigned long) ntohs(len) << 16) +
- ((unsigned long) proto << 8));
+ return (__force __sum16)~from64to16(
+ (__force u64)saddr + (__force u64)daddr +
+ (__force u64)sum + ((len + proto) << 8));
}
EXPORT_SYMBOL(csum_tcpudp_magic);
-unsigned int
-csum_tcpudp_nofold (unsigned long saddr, unsigned long daddr, unsigned short len,
- unsigned short proto, unsigned int sum)
+__wsum
+csum_tcpudp_nofold (__be32 saddr, __be32 daddr, unsigned short len,
+ unsigned short proto, __wsum sum)
{
unsigned long result;
- result = (saddr + daddr + sum +
- ((unsigned long) ntohs(len) << 16) +
- ((unsigned long) proto << 8));
+ result = (__force u64)saddr + (__force u64)daddr +
+ (__force u64)sum + ((len + proto) << 8);
/* Fold down to 32-bits so we don't lose in the typedef-less network stack. */
/* 64 to 33 */
result = (result & 0xffffffff) + (result >> 32);
/* 33 to 32 */
result = (result & 0xffffffff) + (result >> 32);
- return result;
+ return (__force __wsum)result;
}
extern unsigned long do_csum (const unsigned char *, long);
@@ -75,16 +75,15 @@ extern unsigned long do_csum (const unsigned char *, long);
*
* it's best to have buff aligned on a 32-bit boundary
*/
-unsigned int
-csum_partial (const unsigned char * buff, int len, unsigned int sum)
+__wsum csum_partial(const void *buff, int len, __wsum sum)
{
- unsigned long result = do_csum(buff, len);
+ u64 result = do_csum(buff, len);
/* add in old sum, and carry.. */
- result += sum;
+ result += (__force u32)sum;
/* 32+c bits -> 32 bits */
result = (result & 0xffffffff) + (result >> 32);
- return result;
+ return (__force __wsum)result;
}
EXPORT_SYMBOL(csum_partial);
@@ -93,10 +92,9 @@ EXPORT_SYMBOL(csum_partial);
* this routine is used for miscellaneous IP-like checksums, mainly
* in icmp.c
*/
-unsigned short
-ip_compute_csum (unsigned char * buff, int len)
+__sum16 ip_compute_csum (const void *buff, int len)
{
- return ~do_csum(buff,len);
+ return (__force __sum16)~do_csum(buff,len);
}
EXPORT_SYMBOL(ip_compute_csum);
diff --git a/arch/ia64/lib/csum_partial_copy.c b/arch/ia64/lib/csum_partial_copy.c
index 36866e8a5d2b..503dfe6d1450 100644
--- a/arch/ia64/lib/csum_partial_copy.c
+++ b/arch/ia64/lib/csum_partial_copy.c
@@ -104,9 +104,9 @@ out:
*/
extern unsigned long do_csum(const unsigned char *, long);
-static unsigned int
-do_csum_partial_copy_from_user (const unsigned char __user *src, unsigned char *dst,
- int len, unsigned int psum, int *errp)
+__wsum
+csum_partial_copy_from_user(const void __user *src, void *dst,
+ int len, __wsum psum, int *errp)
{
unsigned long result;
@@ -122,30 +122,17 @@ do_csum_partial_copy_from_user (const unsigned char __user *src, unsigned char *
result = do_csum(dst, len);
/* add in old sum, and carry.. */
- result += psum;
+ result += (__force u32)psum;
/* 32+c bits -> 32 bits */
result = (result & 0xffffffff) + (result >> 32);
- return result;
-}
-
-unsigned int
-csum_partial_copy_from_user (const unsigned char __user *src, unsigned char *dst,
- int len, unsigned int sum, int *errp)
-{
- if (!access_ok(VERIFY_READ, src, len)) {
- *errp = -EFAULT;
- memset(dst, 0, len);
- return sum;
- }
-
- return do_csum_partial_copy_from_user(src, dst, len, sum, errp);
+ return (__force __wsum)result;
}
-unsigned int
-csum_partial_copy_nocheck(const unsigned char __user *src, unsigned char *dst,
- int len, unsigned int sum)
+__wsum
+csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
{
- return do_csum_partial_copy_from_user(src, dst, len, sum, NULL);
+ return csum_partial_copy_from_user((__force const void __user *)src,
+ dst, len, sum, NULL);
}
EXPORT_SYMBOL(csum_partial_copy_nocheck);
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index b30be7c48ba8..f4edfbf27134 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -469,10 +469,11 @@ pcibios_fixup_resources(struct pci_dev *dev, int start, int limit)
}
}
-static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
+void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
{
pcibios_fixup_resources(dev, 0, PCI_BRIDGE_RESOURCES);
}
+EXPORT_SYMBOL_GPL(pcibios_fixup_device_resources);
static void __devinit pcibios_fixup_bridge_resources(struct pci_dev *dev)
{
@@ -493,6 +494,7 @@ pcibios_fixup_bus (struct pci_bus *b)
}
list_for_each_entry(dev, &b->devices, bus_list)
pcibios_fixup_device_resources(dev);
+ platform_pci_fixup_bus(b);
return;
}
@@ -738,75 +740,44 @@ int ia64_pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size)
return ret;
}
+/* It's defined in drivers/pci/pci.c */
+extern u8 pci_cache_line_size;
+
/**
- * pci_cacheline_size - determine cacheline size for PCI devices
- * @dev: void
+ * set_pci_cacheline_size - determine cacheline size for PCI devices
*
* We want to use the line-size of the outer-most cache. We assume
* that this line-size is the same for all CPUs.
*
* Code mostly taken from arch/ia64/kernel/palinfo.c:cache_info().
- *
- * RETURNS: An appropriate -ERRNO error value on eror, or zero for success.
*/
-static unsigned long
-pci_cacheline_size (void)
+static void __init set_pci_cacheline_size(void)
{
u64 levels, unique_caches;
s64 status;
pal_cache_config_info_t cci;
- static u8 cacheline_size;
-
- if (cacheline_size)
- return cacheline_size;
status = ia64_pal_cache_summary(&levels, &unique_caches);
if (status != 0) {
- printk(KERN_ERR "%s: ia64_pal_cache_summary() failed (status=%ld)\n",
- __FUNCTION__, status);
- return SMP_CACHE_BYTES;
+ printk(KERN_ERR "%s: ia64_pal_cache_summary() failed "
+ "(status=%ld)\n", __FUNCTION__, status);
+ return;
}
- status = ia64_pal_cache_config_info(levels - 1, /* cache_type (data_or_unified)= */ 2,
- &cci);
+ status = ia64_pal_cache_config_info(levels - 1,
+ /* cache_type (data_or_unified)= */ 2, &cci);
if (status != 0) {
- printk(KERN_ERR "%s: ia64_pal_cache_config_info() failed (status=%ld)\n",
- __FUNCTION__, status);
- return SMP_CACHE_BYTES;
+ printk(KERN_ERR "%s: ia64_pal_cache_config_info() failed "
+ "(status=%ld)\n", __FUNCTION__, status);
+ return;
}
- cacheline_size = 1 << cci.pcci_line_size;
- return cacheline_size;
+ pci_cache_line_size = (1 << cci.pcci_line_size) / 4;
}
-/**
- * pcibios_prep_mwi - helper function for drivers/pci/pci.c:pci_set_mwi()
- * @dev: the PCI device for which MWI is enabled
- *
- * For ia64, we can get the cacheline sizes from PAL.
- *
- * RETURNS: An appropriate -ERRNO error value on eror, or zero for success.
- */
-int
-pcibios_prep_mwi (struct pci_dev *dev)
-{
- unsigned long desired_linesize, current_linesize;
- int rc = 0;
- u8 pci_linesize;
-
- desired_linesize = pci_cacheline_size();
-
- pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &pci_linesize);
- current_linesize = 4 * pci_linesize;
- if (desired_linesize != current_linesize) {
- printk(KERN_WARNING "PCI: slot %s has incorrect PCI cache line size of %lu bytes,",
- pci_name(dev), current_linesize);
- if (current_linesize > desired_linesize) {
- printk(" expected %lu bytes instead\n", desired_linesize);
- rc = -EINVAL;
- } else {
- printk(" correcting to %lu\n", desired_linesize);
- pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, desired_linesize / 4);
- }
- }
- return rc;
+static int __init pcibios_init(void)
+{
+ set_pci_cacheline_size();
+ return 0;
}
+
+subsys_initcall(pcibios_init);
diff --git a/arch/ia64/sn/kernel/Makefile b/arch/ia64/sn/kernel/Makefile
index 2d78f34dd763..0a59371d3475 100644
--- a/arch/ia64/sn/kernel/Makefile
+++ b/arch/ia64/sn/kernel/Makefile
@@ -4,13 +4,14 @@
# License. See the file "COPYING" in the main directory of this archive
# for more details.
#
-# Copyright (C) 1999,2001-2005 Silicon Graphics, Inc. All Rights Reserved.
+# Copyright (C) 1999,2001-2006 Silicon Graphics, Inc. All Rights Reserved.
#
CPPFLAGS += -I$(srctree)/arch/ia64/sn/include
obj-y += setup.o bte.o bte_error.o irq.o mca.o idle.o \
- huberror.o io_init.o iomv.o klconflib.o pio_phys.o \
+ huberror.o io_acpi_init.o io_common.o \
+ io_init.o iomv.o klconflib.o pio_phys.o \
sn2/
obj-$(CONFIG_IA64_GENERIC) += machvec.o
obj-$(CONFIG_SGI_TIOCX) += tiocx.o
diff --git a/arch/ia64/sn/kernel/io_acpi_init.c b/arch/ia64/sn/kernel/io_acpi_init.c
new file mode 100644
index 000000000000..99d7f278612a
--- /dev/null
+++ b/arch/ia64/sn/kernel/io_acpi_init.c
@@ -0,0 +1,231 @@
+/*
+ * 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 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#include <asm/sn/types.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/pcidev.h>
+#include <asm/sn/pcibus_provider_defs.h>
+#include <asm/sn/sn_sal.h>
+#include "xtalk/hubdev.h"
+#include <linux/acpi.h>
+
+
+/*
+ * The code in this file will only be executed when running with
+ * a PROM that has ACPI IO support. (i.e., SN_ACPI_BASE_SUPPORT() == 1)
+ */
+
+
+/*
+ * This value must match the UUID the PROM uses
+ * (io/acpi/defblk.c) when building a vendor descriptor.
+ */
+struct acpi_vendor_uuid sn_uuid = {
+ .subtype = 0,
+ .data = { 0x2c, 0xc6, 0xa6, 0xfe, 0x9c, 0x44, 0xda, 0x11,
+ 0xa2, 0x7c, 0x08, 0x00, 0x69, 0x13, 0xea, 0x51 },
+};
+
+/*
+ * Perform the early IO init in PROM.
+ */
+static s64
+sal_ioif_init(u64 *result)
+{
+ struct ia64_sal_retval isrv = {0,0,0,0};
+
+ SAL_CALL_NOLOCK(isrv,
+ SN_SAL_IOIF_INIT, 0, 0, 0, 0, 0, 0, 0);
+ *result = isrv.v0;
+ return isrv.status;
+}
+
+/*
+ * sn_hubdev_add - The 'add' function of the acpi_sn_hubdev_driver.
+ * Called for every "SGIHUB" or "SGITIO" device defined
+ * in the ACPI namespace.
+ */
+static int __init
+sn_hubdev_add(struct acpi_device *device)
+{
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ u64 addr;
+ struct hubdev_info *hubdev;
+ struct hubdev_info *hubdev_ptr;
+ int i;
+ u64 nasid;
+ struct acpi_resource *resource;
+ int ret = 0;
+ acpi_status status;
+ struct acpi_resource_vendor_typed *vendor;
+ extern void sn_common_hubdev_init(struct hubdev_info *);
+
+ status = acpi_get_vendor_resource(device->handle, METHOD_NAME__CRS,
+ &sn_uuid, &buffer);
+ if (ACPI_FAILURE(status)) {
+ printk(KERN_ERR
+ "sn_hubdev_add: acpi_get_vendor_resource() failed: %d\n",
+ status);
+ return 1;
+ }
+
+ resource = buffer.pointer;
+ vendor = &resource->data.vendor_typed;
+ if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) !=
+ sizeof(struct hubdev_info *)) {
+ printk(KERN_ERR
+ "sn_hubdev_add: Invalid vendor data length: %d\n",
+ vendor->byte_length);
+ ret = 1;
+ goto exit;
+ }
+
+ memcpy(&addr, vendor->byte_data, sizeof(struct hubdev_info *));
+ hubdev_ptr = __va((struct hubdev_info *) addr);
+
+ nasid = hubdev_ptr->hdi_nasid;
+ i = nasid_to_cnodeid(nasid);
+ hubdev = (struct hubdev_info *)(NODEPDA(i)->pdinfo);
+ *hubdev = *hubdev_ptr;
+ sn_common_hubdev_init(hubdev);
+
+exit:
+ kfree(buffer.pointer);
+ return ret;
+}
+
+/*
+ * sn_get_bussoft_ptr() - The pcibus_bussoft pointer is found in
+ * the ACPI Vendor resource for this bus.
+ */
+static struct pcibus_bussoft *
+sn_get_bussoft_ptr(struct pci_bus *bus)
+{
+ u64 addr;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ acpi_handle handle;
+ struct pcibus_bussoft *prom_bussoft_ptr;
+ struct acpi_resource *resource;
+ acpi_status status;
+ struct acpi_resource_vendor_typed *vendor;
+
+
+ handle = PCI_CONTROLLER(bus)->acpi_handle;
+ status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS,
+ &sn_uuid, &buffer);
+ if (ACPI_FAILURE(status)) {
+ printk(KERN_ERR "get_acpi_pcibus_ptr: "
+ "get_acpi_bussoft_info() failed: %d\n",
+ status);
+ return NULL;
+ }
+ resource = buffer.pointer;
+ vendor = &resource->data.vendor_typed;
+
+ if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) !=
+ sizeof(struct pcibus_bussoft *)) {
+ printk(KERN_ERR
+ "get_acpi_bussoft_ptr: Invalid vendor data "
+ "length %d\n", vendor->byte_length);
+ kfree(buffer.pointer);
+ return NULL;
+ }
+ memcpy(&addr, vendor->byte_data, sizeof(struct pcibus_bussoft *));
+ prom_bussoft_ptr = __va((struct pcibus_bussoft *) addr);
+ kfree(buffer.pointer);
+
+ return prom_bussoft_ptr;
+}
+
+/*
+ * sn_acpi_bus_fixup
+ */
+void
+sn_acpi_bus_fixup(struct pci_bus *bus)
+{
+ struct pci_dev *pci_dev = NULL;
+ struct pcibus_bussoft *prom_bussoft_ptr;
+ extern void sn_common_bus_fixup(struct pci_bus *,
+ struct pcibus_bussoft *);
+
+ if (!bus->parent) { /* If root bus */
+ prom_bussoft_ptr = sn_get_bussoft_ptr(bus);
+ if (prom_bussoft_ptr == NULL) {
+ printk(KERN_ERR
+ "sn_pci_fixup_bus: 0x%04x:0x%02x Unable to "
+ "obtain prom_bussoft_ptr\n",
+ pci_domain_nr(bus), bus->number);
+ return;
+ }
+ sn_common_bus_fixup(bus, prom_bussoft_ptr);
+ }
+ list_for_each_entry(pci_dev, &bus->devices, bus_list) {
+ sn_pci_fixup_slot(pci_dev);
+ }
+}
+
+/*
+ * sn_acpi_slot_fixup - Perform any SN specific slot fixup.
+ * At present there does not appear to be
+ * any generic way to handle a ROM image
+ * that has been shadowed by the PROM, so
+ * we pass a pointer to it within the
+ * pcidev_info structure.
+ */
+
+void
+sn_acpi_slot_fixup(struct pci_dev *dev, struct pcidev_info *pcidev_info)
+{
+ void __iomem *addr;
+ size_t size;
+
+ if (pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE]) {
+ /*
+ * A valid ROM image exists and has been shadowed by the
+ * PROM. Setup the pci_dev ROM resource to point to
+ * the shadowed copy.
+ */
+ size = dev->resource[PCI_ROM_RESOURCE].end -
+ dev->resource[PCI_ROM_RESOURCE].start;
+ addr =
+ ioremap(pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE],
+ size);
+ dev->resource[PCI_ROM_RESOURCE].start = (unsigned long) addr;
+ dev->resource[PCI_ROM_RESOURCE].end =
+ (unsigned long) addr + size;
+ dev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_BIOS_COPY;
+ }
+}
+
+static struct acpi_driver acpi_sn_hubdev_driver = {
+ .name = "SGI HUBDEV Driver",
+ .ids = "SGIHUB,SGITIO",
+ .ops = {
+ .add = sn_hubdev_add,
+ },
+};
+
+
+/*
+ * sn_io_acpi_init - PROM has ACPI support for IO, defining at a minimum the
+ * nodes and root buses in the DSDT. As a result, bus scanning
+ * will be initiated by the Linux ACPI code.
+ */
+
+void __init
+sn_io_acpi_init(void)
+{
+ u64 result;
+ s64 status;
+
+ acpi_bus_register_driver(&acpi_sn_hubdev_driver);
+ status = sal_ioif_init(&result);
+ if (status || result)
+ panic("sal_ioif_init failed: [%lx] %s\n",
+ status, ia64_sal_strerror(status));
+}
diff --git a/arch/ia64/sn/kernel/io_common.c b/arch/ia64/sn/kernel/io_common.c
new file mode 100644
index 000000000000..d4dd8f4b6b8d
--- /dev/null
+++ b/arch/ia64/sn/kernel/io_common.c
@@ -0,0 +1,613 @@
+/*
+ * 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 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#include <linux/bootmem.h>
+#include <asm/sn/types.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/sn_feature_sets.h>
+#include <asm/sn/geo.h>
+#include <asm/sn/io.h>
+#include <asm/sn/l1.h>
+#include <asm/sn/module.h>
+#include <asm/sn/pcibr_provider.h>
+#include <asm/sn/pcibus_provider_defs.h>
+#include <asm/sn/pcidev.h>
+#include <asm/sn/simulator.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/sn/tioca_provider.h>
+#include <asm/sn/tioce_provider.h>
+#include "xtalk/hubdev.h"
+#include "xtalk/xwidgetdev.h"
+#include <linux/acpi.h>
+#include <asm/sn/sn2/sn_hwperf.h>
+#include <asm/sn/acpi.h>
+
+extern void sn_init_cpei_timer(void);
+extern void register_sn_procfs(void);
+extern void sn_acpi_bus_fixup(struct pci_bus *);
+extern void sn_bus_fixup(struct pci_bus *);
+extern void sn_acpi_slot_fixup(struct pci_dev *, struct pcidev_info *);
+extern void sn_more_slot_fixup(struct pci_dev *, struct pcidev_info *);
+extern void sn_legacy_pci_window_fixup(struct pci_controller *, u64, u64);
+extern void sn_io_acpi_init(void);
+extern void sn_io_init(void);
+
+
+static struct list_head sn_sysdata_list;
+
+/* sysdata list struct */
+struct sysdata_el {
+ struct list_head entry;
+ void *sysdata;
+};
+
+int sn_ioif_inited; /* SN I/O infrastructure initialized? */
+
+struct sn_pcibus_provider *sn_pci_provider[PCIIO_ASIC_MAX_TYPES]; /* indexed by asic type */
+
+/*
+ * Hooks and struct for unsupported pci providers
+ */
+
+static dma_addr_t
+sn_default_pci_map(struct pci_dev *pdev, unsigned long paddr, size_t size, int type)
+{
+ return 0;
+}
+
+static void
+sn_default_pci_unmap(struct pci_dev *pdev, dma_addr_t addr, int direction)
+{
+ return;
+}
+
+static void *
+sn_default_pci_bus_fixup(struct pcibus_bussoft *soft, struct pci_controller *controller)
+{
+ return NULL;
+}
+
+static struct sn_pcibus_provider sn_pci_default_provider = {
+ .dma_map = sn_default_pci_map,
+ .dma_map_consistent = sn_default_pci_map,
+ .dma_unmap = sn_default_pci_unmap,
+ .bus_fixup = sn_default_pci_bus_fixup,
+};
+
+/*
+ * Retrieve the DMA Flush List given nasid, widget, and device.
+ * This list is needed to implement the WAR - Flush DMA data on PIO Reads.
+ */
+static inline u64
+sal_get_device_dmaflush_list(u64 nasid, u64 widget_num, u64 device_num,
+ u64 address)
+{
+ struct ia64_sal_retval ret_stuff;
+ ret_stuff.status = 0;
+ ret_stuff.v0 = 0;
+
+ SAL_CALL_NOLOCK(ret_stuff,
+ (u64) SN_SAL_IOIF_GET_DEVICE_DMAFLUSH_LIST,
+ (u64) nasid, (u64) widget_num,
+ (u64) device_num, (u64) address, 0, 0, 0);
+ return ret_stuff.status;
+}
+
+/*
+ * Retrieve the pci device information given the bus and device|function number.
+ */
+static inline u64
+sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev,
+ u64 sn_irq_info)
+{
+ struct ia64_sal_retval ret_stuff;
+ ret_stuff.status = 0;
+ ret_stuff.v0 = 0;
+
+ SAL_CALL_NOLOCK(ret_stuff,
+ (u64) SN_SAL_IOIF_GET_PCIDEV_INFO,
+ (u64) segment, (u64) bus_number, (u64) devfn,
+ (u64) pci_dev,
+ sn_irq_info, 0, 0);
+ return ret_stuff.v0;
+}
+
+/*
+ * sn_pcidev_info_get() - Retrieve the pcidev_info struct for the specified
+ * device.
+ */
+inline struct pcidev_info *
+sn_pcidev_info_get(struct pci_dev *dev)
+{
+ struct pcidev_info *pcidev;
+
+ list_for_each_entry(pcidev,
+ &(SN_PLATFORM_DATA(dev)->pcidev_info), pdi_list) {
+ if (pcidev->pdi_linux_pcidev == dev)
+ return pcidev;
+ }
+ return NULL;
+}
+
+/* Older PROM flush WAR
+ *
+ * 01/16/06 -- This war will be in place until a new official PROM is released.
+ * Additionally note that the struct sn_flush_device_war also has to be
+ * removed from arch/ia64/sn/include/xtalk/hubdev.h
+ */
+static u8 war_implemented = 0;
+
+static s64 sn_device_fixup_war(u64 nasid, u64 widget, int device,
+ struct sn_flush_device_common *common)
+{
+ struct sn_flush_device_war *war_list;
+ struct sn_flush_device_war *dev_entry;
+ struct ia64_sal_retval isrv = {0,0,0,0};
+
+ if (!war_implemented) {
+ printk(KERN_WARNING "PROM version < 4.50 -- implementing old "
+ "PROM flush WAR\n");
+ war_implemented = 1;
+ }
+
+ war_list = kzalloc(DEV_PER_WIDGET * sizeof(*war_list), GFP_KERNEL);
+ if (!war_list)
+ BUG();
+
+ SAL_CALL_NOLOCK(isrv, SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST,
+ nasid, widget, __pa(war_list), 0, 0, 0 ,0);
+ if (isrv.status)
+ panic("sn_device_fixup_war failed: %s\n",
+ ia64_sal_strerror(isrv.status));
+
+ dev_entry = war_list + device;
+ memcpy(common,dev_entry, sizeof(*common));
+ kfree(war_list);
+
+ return isrv.status;
+}
+
+/*
+ * sn_common_hubdev_init() - This routine is called to initialize the HUB data
+ * structure for each node in the system.
+ */
+void __init
+sn_common_hubdev_init(struct hubdev_info *hubdev)
+{
+
+ struct sn_flush_device_kernel *sn_flush_device_kernel;
+ struct sn_flush_device_kernel *dev_entry;
+ s64 status;
+ int widget, device, size;
+
+ /* Attach the error interrupt handlers */
+ if (hubdev->hdi_nasid & 1) /* If TIO */
+ ice_error_init(hubdev);
+ else
+ hub_error_init(hubdev);
+
+ for (widget = 0; widget <= HUB_WIDGET_ID_MAX; widget++)
+ hubdev->hdi_xwidget_info[widget].xwi_hubinfo = hubdev;
+
+ if (!hubdev->hdi_flush_nasid_list.widget_p)
+ return;
+
+ size = (HUB_WIDGET_ID_MAX + 1) *
+ sizeof(struct sn_flush_device_kernel *);
+ hubdev->hdi_flush_nasid_list.widget_p =
+ kzalloc(size, GFP_KERNEL);
+ if (!hubdev->hdi_flush_nasid_list.widget_p)
+ BUG();
+
+ for (widget = 0; widget <= HUB_WIDGET_ID_MAX; widget++) {
+ size = DEV_PER_WIDGET *
+ sizeof(struct sn_flush_device_kernel);
+ sn_flush_device_kernel = kzalloc(size, GFP_KERNEL);
+ if (!sn_flush_device_kernel)
+ BUG();
+
+ dev_entry = sn_flush_device_kernel;
+ for (device = 0; device < DEV_PER_WIDGET;
+ device++, dev_entry++) {
+ size = sizeof(struct sn_flush_device_common);
+ dev_entry->common = kzalloc(size, GFP_KERNEL);
+ if (!dev_entry->common)
+ BUG();
+ if (sn_prom_feature_available(PRF_DEVICE_FLUSH_LIST))
+ status = sal_get_device_dmaflush_list(
+ hubdev->hdi_nasid, widget, device,
+ (u64)(dev_entry->common));
+ else
+ status = sn_device_fixup_war(hubdev->hdi_nasid,
+ widget, device,
+ dev_entry->common);
+ if (status != SALRET_OK)
+ panic("SAL call failed: %s\n",
+ ia64_sal_strerror(status));
+
+ spin_lock_init(&dev_entry->sfdl_flush_lock);
+ }
+
+ if (sn_flush_device_kernel)
+ hubdev->hdi_flush_nasid_list.widget_p[widget] =
+ sn_flush_device_kernel;
+ }
+}
+
+void sn_pci_unfixup_slot(struct pci_dev *dev)
+{
+ struct pci_dev *host_pci_dev = SN_PCIDEV_INFO(dev)->host_pci_dev;
+
+ sn_irq_unfixup(dev);
+ pci_dev_put(host_pci_dev);
+ pci_dev_put(dev);
+}
+
+/*
+ * sn_pci_fixup_slot() - This routine sets up a slot's resources consistent
+ * with the Linux PCI abstraction layer. Resources
+ * acquired from our PCI provider include PIO maps
+ * to BAR space and interrupt objects.
+ */
+void sn_pci_fixup_slot(struct pci_dev *dev)
+{
+ int segment = pci_domain_nr(dev->bus);
+ int status = 0;
+ struct pcibus_bussoft *bs;
+ struct pci_bus *host_pci_bus;
+ struct pci_dev *host_pci_dev;
+ struct pcidev_info *pcidev_info;
+ struct sn_irq_info *sn_irq_info;
+ unsigned int bus_no, devfn;
+
+ pci_dev_get(dev); /* for the sysdata pointer */
+ pcidev_info = kzalloc(sizeof(struct pcidev_info), GFP_KERNEL);
+ if (!pcidev_info)
+ BUG(); /* Cannot afford to run out of memory */
+
+ sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
+ if (!sn_irq_info)
+ BUG(); /* Cannot afford to run out of memory */
+
+ /* Call to retrieve pci device information needed by kernel. */
+ status = sal_get_pcidev_info((u64) segment, (u64) dev->bus->number,
+ dev->devfn,
+ (u64) __pa(pcidev_info),
+ (u64) __pa(sn_irq_info));
+ if (status)
+ BUG(); /* Cannot get platform pci device information */
+
+ /* Add pcidev_info to list in pci_controller.platform_data */
+ list_add_tail(&pcidev_info->pdi_list,
+ &(SN_PLATFORM_DATA(dev->bus)->pcidev_info));
+
+ if (SN_ACPI_BASE_SUPPORT())
+ sn_acpi_slot_fixup(dev, pcidev_info);
+ else
+ sn_more_slot_fixup(dev, pcidev_info);
+ /*
+ * Using the PROMs values for the PCI host bus, get the Linux
+ * PCI host_pci_dev struct and set up host bus linkages
+ */
+
+ bus_no = (pcidev_info->pdi_slot_host_handle >> 32) & 0xff;
+ devfn = pcidev_info->pdi_slot_host_handle & 0xffffffff;
+ host_pci_bus = pci_find_bus(segment, bus_no);
+ host_pci_dev = pci_get_slot(host_pci_bus, devfn);
+
+ pcidev_info->host_pci_dev = host_pci_dev;
+ pcidev_info->pdi_linux_pcidev = dev;
+ pcidev_info->pdi_host_pcidev_info = SN_PCIDEV_INFO(host_pci_dev);
+ bs = SN_PCIBUS_BUSSOFT(dev->bus);
+ pcidev_info->pdi_pcibus_info = bs;
+
+ if (bs && bs->bs_asic_type < PCIIO_ASIC_MAX_TYPES) {
+ SN_PCIDEV_BUSPROVIDER(dev) = sn_pci_provider[bs->bs_asic_type];
+ } else {
+ SN_PCIDEV_BUSPROVIDER(dev) = &sn_pci_default_provider;
+ }
+
+ /* Only set up IRQ stuff if this device has a host bus context */
+ if (bs && sn_irq_info->irq_irq) {
+ pcidev_info->pdi_sn_irq_info = sn_irq_info;
+ dev->irq = pcidev_info->pdi_sn_irq_info->irq_irq;
+ sn_irq_fixup(dev, sn_irq_info);
+ } else {
+ pcidev_info->pdi_sn_irq_info = NULL;
+ kfree(sn_irq_info);
+ }
+}
+
+/*
+ * sn_common_bus_fixup - Perform platform specific bus fixup.
+ * Execute the ASIC specific fixup routine
+ * for this bus.
+ */
+void
+sn_common_bus_fixup(struct pci_bus *bus,
+ struct pcibus_bussoft *prom_bussoft_ptr)
+{
+ int cnode;
+ struct pci_controller *controller;
+ struct hubdev_info *hubdev_info;
+ int nasid;
+ void *provider_soft;
+ struct sn_pcibus_provider *provider;
+ struct sn_platform_data *sn_platform_data;
+
+ controller = PCI_CONTROLLER(bus);
+ /*
+ * Per-provider fixup. Copies the bus soft structure from prom
+ * to local area and links SN_PCIBUS_BUSSOFT().
+ */
+
+ if (prom_bussoft_ptr->bs_asic_type >= PCIIO_ASIC_MAX_TYPES) {
+ printk(KERN_WARNING "sn_common_bus_fixup: Unsupported asic type, %d",
+ prom_bussoft_ptr->bs_asic_type);
+ return;
+ }
+
+ if (prom_bussoft_ptr->bs_asic_type == PCIIO_ASIC_TYPE_PPB)
+ return; /* no further fixup necessary */
+
+ provider = sn_pci_provider[prom_bussoft_ptr->bs_asic_type];
+ if (provider == NULL)
+ panic("sn_common_bus_fixup: No provider registered for this asic type, %d",
+ prom_bussoft_ptr->bs_asic_type);
+
+ if (provider->bus_fixup)
+ provider_soft = (*provider->bus_fixup) (prom_bussoft_ptr,
+ controller);
+ else
+ provider_soft = NULL;
+
+ /*
+ * Generic bus fixup goes here. Don't reference prom_bussoft_ptr
+ * after this point.
+ */
+ controller->platform_data = kzalloc(sizeof(struct sn_platform_data),
+ GFP_KERNEL);
+ if (controller->platform_data == NULL)
+ BUG();
+ sn_platform_data =
+ (struct sn_platform_data *) controller->platform_data;
+ sn_platform_data->provider_soft = provider_soft;
+ INIT_LIST_HEAD(&((struct sn_platform_data *)
+ controller->platform_data)->pcidev_info);
+ nasid = NASID_GET(SN_PCIBUS_BUSSOFT(bus)->bs_base);
+ cnode = nasid_to_cnodeid(nasid);
+ hubdev_info = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo);
+ SN_PCIBUS_BUSSOFT(bus)->bs_xwidget_info =
+ &(hubdev_info->hdi_xwidget_info[SN_PCIBUS_BUSSOFT(bus)->bs_xid]);
+
+ /*
+ * If the node information we obtained during the fixup phase is
+ * invalid then set controller->node to -1 (undetermined)
+ */
+ if (controller->node >= num_online_nodes()) {
+ struct pcibus_bussoft *b = SN_PCIBUS_BUSSOFT(bus);
+
+ printk(KERN_WARNING "Device ASIC=%u XID=%u PBUSNUM=%u"
+ "L_IO=%lx L_MEM=%lx BASE=%lx\n",
+ b->bs_asic_type, b->bs_xid, b->bs_persist_busnum,
+ b->bs_legacy_io, b->bs_legacy_mem, b->bs_base);
+ printk(KERN_WARNING "on node %d but only %d nodes online."
+ "Association set to undetermined.\n",
+ controller->node, num_online_nodes());
+ controller->node = -1;
+ }
+}
+
+void sn_bus_store_sysdata(struct pci_dev *dev)
+{
+ struct sysdata_el *element;
+
+ element = kzalloc(sizeof(struct sysdata_el), GFP_KERNEL);
+ if (!element) {
+ dev_dbg(dev, "%s: out of memory!\n", __FUNCTION__);
+ return;
+ }
+ element->sysdata = SN_PCIDEV_INFO(dev);
+ list_add(&element->entry, &sn_sysdata_list);
+}
+
+void sn_bus_free_sysdata(void)
+{
+ struct sysdata_el *element;
+ struct list_head *list, *safe;
+
+ list_for_each_safe(list, safe, &sn_sysdata_list) {
+ element = list_entry(list, struct sysdata_el, entry);
+ list_del(&element->entry);
+ list_del(&(((struct pcidev_info *)
+ (element->sysdata))->pdi_list));
+ kfree(element->sysdata);
+ kfree(element);
+ }
+ return;
+}
+
+/*
+ * hubdev_init_node() - Creates the HUB data structure and link them to it's
+ * own NODE specific data area.
+ */
+void hubdev_init_node(nodepda_t * npda, cnodeid_t node)
+{
+ struct hubdev_info *hubdev_info;
+ int size;
+ pg_data_t *pg;
+
+ size = sizeof(struct hubdev_info);
+
+ if (node >= num_online_nodes()) /* Headless/memless IO nodes */
+ pg = NODE_DATA(0);
+ else
+ pg = NODE_DATA(node);
+
+ hubdev_info = (struct hubdev_info *)alloc_bootmem_node(pg, size);
+
+ npda->pdinfo = (void *)hubdev_info;
+}
+
+geoid_t
+cnodeid_get_geoid(cnodeid_t cnode)
+{
+ struct hubdev_info *hubdev;
+
+ hubdev = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo);
+ return hubdev->hdi_geoid;
+}
+
+void sn_generate_path(struct pci_bus *pci_bus, char *address)
+{
+ nasid_t nasid;
+ cnodeid_t cnode;
+ geoid_t geoid;
+ moduleid_t moduleid;
+ u16 bricktype;
+
+ nasid = NASID_GET(SN_PCIBUS_BUSSOFT(pci_bus)->bs_base);
+ cnode = nasid_to_cnodeid(nasid);
+ geoid = cnodeid_get_geoid(cnode);
+ moduleid = geo_module(geoid);
+
+ sprintf(address, "module_%c%c%c%c%.2d",
+ '0'+RACK_GET_CLASS(MODULE_GET_RACK(moduleid)),
+ '0'+RACK_GET_GROUP(MODULE_GET_RACK(moduleid)),
+ '0'+RACK_GET_NUM(MODULE_GET_RACK(moduleid)),
+ MODULE_GET_BTCHAR(moduleid), MODULE_GET_BPOS(moduleid));
+
+ /* Tollhouse requires slot id to be displayed */
+ bricktype = MODULE_GET_BTYPE(moduleid);
+ if ((bricktype == L1_BRICKTYPE_191010) ||
+ (bricktype == L1_BRICKTYPE_1932))
+ sprintf(address, "%s^%d", address, geo_slot(geoid));
+}
+
+/*
+ * sn_pci_fixup_bus() - Perform SN specific setup of software structs
+ * (pcibus_bussoft, pcidev_info) and hardware
+ * registers, for the specified bus and devices under it.
+ */
+void __devinit
+sn_pci_fixup_bus(struct pci_bus *bus)
+{
+
+ if (SN_ACPI_BASE_SUPPORT())
+ sn_acpi_bus_fixup(bus);
+ else
+ sn_bus_fixup(bus);
+}
+
+/*
+ * sn_io_early_init - Perform early IO (and some non-IO) initialization.
+ * In particular, setup the sn_pci_provider[] array.
+ * This needs to be done prior to any bus scanning
+ * (acpi_scan_init()) in the ACPI case, as the SN
+ * bus fixup code will reference the array.
+ */
+static int __init
+sn_io_early_init(void)
+{
+ int i;
+
+ if (!ia64_platform_is("sn2") || IS_RUNNING_ON_FAKE_PROM())
+ return 0;
+
+ /*
+ * prime sn_pci_provider[]. Individial provider init routines will
+ * override their respective default entries.
+ */
+
+ for (i = 0; i < PCIIO_ASIC_MAX_TYPES; i++)
+ sn_pci_provider[i] = &sn_pci_default_provider;
+
+ pcibr_init_provider();
+ tioca_init_provider();
+ tioce_init_provider();
+
+ /*
+ * This is needed to avoid bounce limit checks in the blk layer
+ */
+ ia64_max_iommu_merge_mask = ~PAGE_MASK;
+
+ sn_irq_lh_init();
+ INIT_LIST_HEAD(&sn_sysdata_list);
+ sn_init_cpei_timer();
+
+#ifdef CONFIG_PROC_FS
+ register_sn_procfs();
+#endif
+
+ printk(KERN_INFO "ACPI DSDT OEM Rev 0x%x\n",
+ acpi_gbl_DSDT->oem_revision);
+ if (SN_ACPI_BASE_SUPPORT())
+ sn_io_acpi_init();
+ else
+ sn_io_init();
+ return 0;
+}
+
+arch_initcall(sn_io_early_init);
+
+/*
+ * sn_io_late_init() - Perform any final platform specific IO initialization.
+ */
+
+int __init
+sn_io_late_init(void)
+{
+ struct pci_bus *bus;
+ struct pcibus_bussoft *bussoft;
+ cnodeid_t cnode;
+ nasid_t nasid;
+ cnodeid_t near_cnode;
+
+ if (!ia64_platform_is("sn2") || IS_RUNNING_ON_FAKE_PROM())
+ return 0;
+
+ /*
+ * Setup closest node in pci_controller->node for
+ * PIC, TIOCP, TIOCE (TIOCA does it during bus fixup using
+ * info from the PROM).
+ */
+ bus = NULL;
+ while ((bus = pci_find_next_bus(bus)) != NULL) {
+ bussoft = SN_PCIBUS_BUSSOFT(bus);
+ nasid = NASID_GET(bussoft->bs_base);
+ cnode = nasid_to_cnodeid(nasid);
+ if ((bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCP) ||
+ (bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCE)) {
+ /* TIO PCI Bridge: find nearest node with CPUs */
+ int e = sn_hwperf_get_nearest_node(cnode, NULL,
+ &near_cnode);
+ if (e < 0) {
+ near_cnode = (cnodeid_t)-1; /* use any node */
+ printk(KERN_WARNING "pcibr_bus_fixup: failed "
+ "to find near node with CPUs to TIO "
+ "node %d, err=%d\n", cnode, e);
+ }
+ PCI_CONTROLLER(bus)->node = near_cnode;
+ } else if (bussoft->bs_asic_type == PCIIO_ASIC_TYPE_PIC) {
+ PCI_CONTROLLER(bus)->node = cnode;
+ }
+ }
+
+ sn_ioif_inited = 1; /* SN I/O infrastructure now initialized */
+
+ return 0;
+}
+
+fs_initcall(sn_io_late_init);
+
+EXPORT_SYMBOL(sn_pci_fixup_slot);
+EXPORT_SYMBOL(sn_pci_unfixup_slot);
+EXPORT_SYMBOL(sn_bus_store_sysdata);
+EXPORT_SYMBOL(sn_bus_free_sysdata);
+EXPORT_SYMBOL(sn_generate_path);
+
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c
index dc09a6a28a37..9ad843e0383b 100644
--- a/arch/ia64/sn/kernel/io_init.c
+++ b/arch/ia64/sn/kernel/io_init.c
@@ -3,103 +3,28 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1992 - 1997, 2000-2005 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 1992 - 1997, 2000-2006 Silicon Graphics, Inc. All rights reserved.
*/
-#include <linux/bootmem.h>
-#include <linux/nodemask.h>
#include <asm/sn/types.h>
#include <asm/sn/addrs.h>
-#include <asm/sn/sn_feature_sets.h>
-#include <asm/sn/geo.h>
#include <asm/sn/io.h>
-#include <asm/sn/l1.h>
#include <asm/sn/module.h>
-#include <asm/sn/pcibr_provider.h>
+#include <asm/sn/intr.h>
#include <asm/sn/pcibus_provider_defs.h>
#include <asm/sn/pcidev.h>
-#include <asm/sn/simulator.h>
#include <asm/sn/sn_sal.h>
-#include <asm/sn/tioca_provider.h>
-#include <asm/sn/tioce_provider.h>
#include "xtalk/hubdev.h"
-#include "xtalk/xwidgetdev.h"
-
-
-extern void sn_init_cpei_timer(void);
-extern void register_sn_procfs(void);
-
-static struct list_head sn_sysdata_list;
-
-/* sysdata list struct */
-struct sysdata_el {
- struct list_head entry;
- void *sysdata;
-};
-
-struct slab_info {
- struct hubdev_info hubdev;
-};
-
-struct brick {
- moduleid_t id; /* Module ID of this module */
- struct slab_info slab_info[MAX_SLABS + 1];
-};
-
-int sn_ioif_inited; /* SN I/O infrastructure initialized? */
-
-struct sn_pcibus_provider *sn_pci_provider[PCIIO_ASIC_MAX_TYPES]; /* indexed by asic type */
-
-static int max_segment_number; /* Default highest segment number */
-static int max_pcibus_number = 255; /* Default highest pci bus number */
/*
- * Hooks and struct for unsupported pci providers
+ * The code in this file will only be executed when running with
+ * a PROM that does _not_ have base ACPI IO support.
+ * (i.e., SN_ACPI_BASE_SUPPORT() == 0)
*/
-static dma_addr_t
-sn_default_pci_map(struct pci_dev *pdev, unsigned long paddr, size_t size, int type)
-{
- return 0;
-}
-
-static void
-sn_default_pci_unmap(struct pci_dev *pdev, dma_addr_t addr, int direction)
-{
- return;
-}
-
-static void *
-sn_default_pci_bus_fixup(struct pcibus_bussoft *soft, struct pci_controller *controller)
-{
- return NULL;
-}
-
-static struct sn_pcibus_provider sn_pci_default_provider = {
- .dma_map = sn_default_pci_map,
- .dma_map_consistent = sn_default_pci_map,
- .dma_unmap = sn_default_pci_unmap,
- .bus_fixup = sn_default_pci_bus_fixup,
-};
-
-/*
- * Retrieve the DMA Flush List given nasid, widget, and device.
- * This list is needed to implement the WAR - Flush DMA data on PIO Reads.
- */
-static inline u64
-sal_get_device_dmaflush_list(u64 nasid, u64 widget_num, u64 device_num,
- u64 address)
-{
- struct ia64_sal_retval ret_stuff;
- ret_stuff.status = 0;
- ret_stuff.v0 = 0;
+static int max_segment_number; /* Default highest segment number */
+static int max_pcibus_number = 255; /* Default highest pci bus number */
- SAL_CALL_NOLOCK(ret_stuff,
- (u64) SN_SAL_IOIF_GET_DEVICE_DMAFLUSH_LIST,
- (u64) nasid, (u64) widget_num,
- (u64) device_num, (u64) address, 0, 0, 0);
- return ret_stuff.status;
-}
/*
* Retrieve the hub device info structure for the given nasid.
@@ -131,93 +56,20 @@ static inline u64 sal_get_pcibus_info(u64 segment, u64 busnum, u64 address)
return ret_stuff.v0;
}
-/*
- * Retrieve the pci device information given the bus and device|function number.
- */
-static inline u64
-sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev,
- u64 sn_irq_info)
-{
- struct ia64_sal_retval ret_stuff;
- ret_stuff.status = 0;
- ret_stuff.v0 = 0;
-
- SAL_CALL_NOLOCK(ret_stuff,
- (u64) SN_SAL_IOIF_GET_PCIDEV_INFO,
- (u64) segment, (u64) bus_number, (u64) devfn,
- (u64) pci_dev,
- sn_irq_info, 0, 0);
- return ret_stuff.v0;
-}
-
-/*
- * sn_pcidev_info_get() - Retrieve the pcidev_info struct for the specified
- * device.
- */
-inline struct pcidev_info *
-sn_pcidev_info_get(struct pci_dev *dev)
-{
- struct pcidev_info *pcidev;
-
- list_for_each_entry(pcidev,
- &(SN_PCI_CONTROLLER(dev)->pcidev_info), pdi_list) {
- if (pcidev->pdi_linux_pcidev == dev) {
- return pcidev;
- }
- }
- return NULL;
-}
-
-/* Older PROM flush WAR
- *
- * 01/16/06 -- This war will be in place until a new official PROM is released.
- * Additionally note that the struct sn_flush_device_war also has to be
- * removed from arch/ia64/sn/include/xtalk/hubdev.h
- */
-static u8 war_implemented = 0;
-
-static s64 sn_device_fixup_war(u64 nasid, u64 widget, int device,
- struct sn_flush_device_common *common)
-{
- struct sn_flush_device_war *war_list;
- struct sn_flush_device_war *dev_entry;
- struct ia64_sal_retval isrv = {0,0,0,0};
-
- if (!war_implemented) {
- printk(KERN_WARNING "PROM version < 4.50 -- implementing old "
- "PROM flush WAR\n");
- war_implemented = 1;
- }
-
- war_list = kzalloc(DEV_PER_WIDGET * sizeof(*war_list), GFP_KERNEL);
- if (!war_list)
- BUG();
-
- SAL_CALL_NOLOCK(isrv, SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST,
- nasid, widget, __pa(war_list), 0, 0, 0 ,0);
- if (isrv.status)
- panic("sn_device_fixup_war failed: %s\n",
- ia64_sal_strerror(isrv.status));
-
- dev_entry = war_list + device;
- memcpy(common,dev_entry, sizeof(*common));
- kfree(war_list);
-
- return isrv.status;
-}
/*
- * sn_fixup_ionodes() - This routine initializes the HUB data strcuture for
- * each node in the system.
+ * sn_fixup_ionodes() - This routine initializes the HUB data structure for
+ * each node in the system. This function is only
+ * executed when running with a non-ACPI capable PROM.
*/
static void __init sn_fixup_ionodes(void)
{
- struct sn_flush_device_kernel *sn_flush_device_kernel;
- struct sn_flush_device_kernel *dev_entry;
+
struct hubdev_info *hubdev;
u64 status;
u64 nasid;
- int i, widget, device, size;
+ int i;
+ extern void sn_common_hubdev_init(struct hubdev_info *);
/*
* Get SGI Specific HUB chipset information.
@@ -240,70 +92,47 @@ static void __init sn_fixup_ionodes(void)
max_segment_number = hubdev->max_segment_number;
max_pcibus_number = hubdev->max_pcibus_number;
}
+ sn_common_hubdev_init(hubdev);
+ }
+}
- /* Attach the error interrupt handlers */
- if (nasid & 1)
- ice_error_init(hubdev);
- else
- hub_error_init(hubdev);
-
- for (widget = 0; widget <= HUB_WIDGET_ID_MAX; widget++)
- hubdev->hdi_xwidget_info[widget].xwi_hubinfo = hubdev;
-
- if (!hubdev->hdi_flush_nasid_list.widget_p)
- continue;
-
- size = (HUB_WIDGET_ID_MAX + 1) *
- sizeof(struct sn_flush_device_kernel *);
- hubdev->hdi_flush_nasid_list.widget_p =
- kzalloc(size, GFP_KERNEL);
- if (!hubdev->hdi_flush_nasid_list.widget_p)
+/*
+ * sn_pci_legacy_window_fixup - Create PCI controller windows for
+ * legacy IO and MEM space. This needs to
+ * be done here, as the PROM does not have
+ * ACPI support defining the root buses
+ * and their resources (_CRS),
+ */
+static void
+sn_legacy_pci_window_fixup(struct pci_controller *controller,
+ u64 legacy_io, u64 legacy_mem)
+{
+ controller->window = kcalloc(2, sizeof(struct pci_window),
+ GFP_KERNEL);
+ if (controller->window == NULL)
BUG();
-
- for (widget = 0; widget <= HUB_WIDGET_ID_MAX; widget++) {
- size = DEV_PER_WIDGET *
- sizeof(struct sn_flush_device_kernel);
- sn_flush_device_kernel = kzalloc(size, GFP_KERNEL);
- if (!sn_flush_device_kernel)
- BUG();
-
- dev_entry = sn_flush_device_kernel;
- for (device = 0; device < DEV_PER_WIDGET;
- device++,dev_entry++) {
- size = sizeof(struct sn_flush_device_common);
- dev_entry->common = kzalloc(size, GFP_KERNEL);
- if (!dev_entry->common)
- BUG();
-
- if (sn_prom_feature_available(
- PRF_DEVICE_FLUSH_LIST))
- status = sal_get_device_dmaflush_list(
- nasid, widget, device,
- (u64)(dev_entry->common));
- else
- status = sn_device_fixup_war(nasid,
- widget, device,
- dev_entry->common);
- if (status != SALRET_OK)
- panic("SAL call failed: %s\n",
- ia64_sal_strerror(status));
-
- spin_lock_init(&dev_entry->sfdl_flush_lock);
- }
-
- if (sn_flush_device_kernel)
- hubdev->hdi_flush_nasid_list.widget_p[widget] =
- sn_flush_device_kernel;
- }
- }
+ controller->window[0].offset = legacy_io;
+ controller->window[0].resource.name = "legacy_io";
+ controller->window[0].resource.flags = IORESOURCE_IO;
+ controller->window[0].resource.start = legacy_io;
+ controller->window[0].resource.end =
+ controller->window[0].resource.start + 0xffff;
+ controller->window[0].resource.parent = &ioport_resource;
+ controller->window[1].offset = legacy_mem;
+ controller->window[1].resource.name = "legacy_mem";
+ controller->window[1].resource.flags = IORESOURCE_MEM;
+ controller->window[1].resource.start = legacy_mem;
+ controller->window[1].resource.end =
+ controller->window[1].resource.start + (1024 * 1024) - 1;
+ controller->window[1].resource.parent = &iomem_resource;
+ controller->windows = 2;
}
/*
* sn_pci_window_fixup() - Create a pci_window for each device resource.
- * Until ACPI support is added, we need this code
- * to setup pci_windows for use by
- * pcibios_bus_to_resource(),
- * pcibios_resource_to_bus(), etc.
+ * It will setup pci_windows for use by
+ * pcibios_bus_to_resource(), pcibios_resource_to_bus(),
+ * etc.
*/
static void
sn_pci_window_fixup(struct pci_dev *dev, unsigned int count,
@@ -342,60 +171,22 @@ sn_pci_window_fixup(struct pci_dev *dev, unsigned int count,
controller->window = new_window;
}
-void sn_pci_unfixup_slot(struct pci_dev *dev)
-{
- struct pci_dev *host_pci_dev = SN_PCIDEV_INFO(dev)->host_pci_dev;
-
- sn_irq_unfixup(dev);
- pci_dev_put(host_pci_dev);
- pci_dev_put(dev);
-}
-
/*
- * sn_pci_fixup_slot() - This routine sets up a slot's resources
- * consistent with the Linux PCI abstraction layer. Resources acquired
- * from our PCI provider include PIO maps to BAR space and interrupt
- * objects.
+ * sn_more_slot_fixup() - We are not running with an ACPI capable PROM,
+ * and need to convert the pci_dev->resource
+ * 'start' and 'end' addresses to mapped addresses,
+ * and setup the pci_controller->window array entries.
*/
-void sn_pci_fixup_slot(struct pci_dev *dev)
+void
+sn_more_slot_fixup(struct pci_dev *dev, struct pcidev_info *pcidev_info)
{
unsigned int count = 0;
int idx;
- int segment = pci_domain_nr(dev->bus);
- int status = 0;
- struct pcibus_bussoft *bs;
- struct pci_bus *host_pci_bus;
- struct pci_dev *host_pci_dev;
- struct pcidev_info *pcidev_info;
s64 pci_addrs[PCI_ROM_RESOURCE + 1];
- struct sn_irq_info *sn_irq_info;
- unsigned long size;
- unsigned int bus_no, devfn;
-
- pci_dev_get(dev); /* for the sysdata pointer */
- pcidev_info = kzalloc(sizeof(struct pcidev_info), GFP_KERNEL);
- if (!pcidev_info)
- BUG(); /* Cannot afford to run out of memory */
-
- sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
- if (!sn_irq_info)
- BUG(); /* Cannot afford to run out of memory */
-
- /* Call to retrieve pci device information needed by kernel. */
- status = sal_get_pcidev_info((u64) segment, (u64) dev->bus->number,
- dev->devfn,
- (u64) __pa(pcidev_info),
- (u64) __pa(sn_irq_info));
- if (status)
- BUG(); /* Cannot get platform pci device information */
-
- /* Add pcidev_info to list in sn_pci_controller struct */
- list_add_tail(&pcidev_info->pdi_list,
- &(SN_PCI_CONTROLLER(dev->bus)->pcidev_info));
+ unsigned long addr, end, size, start;
/* Copy over PIO Mapped Addresses */
for (idx = 0; idx <= PCI_ROM_RESOURCE; idx++) {
- unsigned long start, end, addr;
if (!pcidev_info->pdi_pio_mapped_addr[idx]) {
pci_addrs[idx] = -1;
@@ -419,60 +210,28 @@ void sn_pci_fixup_slot(struct pci_dev *dev)
dev->resource[idx].parent = &ioport_resource;
else
dev->resource[idx].parent = &iomem_resource;
+ /* If ROM, mark as shadowed in PROM */
+ if (idx == PCI_ROM_RESOURCE)
+ dev->resource[idx].flags |= IORESOURCE_ROM_BIOS_COPY;
}
/* Create a pci_window in the pci_controller struct for
* each device resource.
*/
if (count > 0)
sn_pci_window_fixup(dev, count, pci_addrs);
-
- /*
- * Using the PROMs values for the PCI host bus, get the Linux
- * PCI host_pci_dev struct and set up host bus linkages
- */
-
- bus_no = (pcidev_info->pdi_slot_host_handle >> 32) & 0xff;
- devfn = pcidev_info->pdi_slot_host_handle & 0xffffffff;
- host_pci_bus = pci_find_bus(segment, bus_no);
- host_pci_dev = pci_get_slot(host_pci_bus, devfn);
-
- pcidev_info->host_pci_dev = host_pci_dev;
- pcidev_info->pdi_linux_pcidev = dev;
- pcidev_info->pdi_host_pcidev_info = SN_PCIDEV_INFO(host_pci_dev);
- bs = SN_PCIBUS_BUSSOFT(dev->bus);
- pcidev_info->pdi_pcibus_info = bs;
-
- if (bs && bs->bs_asic_type < PCIIO_ASIC_MAX_TYPES) {
- SN_PCIDEV_BUSPROVIDER(dev) = sn_pci_provider[bs->bs_asic_type];
- } else {
- SN_PCIDEV_BUSPROVIDER(dev) = &sn_pci_default_provider;
- }
-
- /* Only set up IRQ stuff if this device has a host bus context */
- if (bs && sn_irq_info->irq_irq) {
- pcidev_info->pdi_sn_irq_info = sn_irq_info;
- dev->irq = pcidev_info->pdi_sn_irq_info->irq_irq;
- sn_irq_fixup(dev, sn_irq_info);
- } else {
- pcidev_info->pdi_sn_irq_info = NULL;
- kfree(sn_irq_info);
- }
}
/*
* sn_pci_controller_fixup() - This routine sets up a bus's resources
- * consistent with the Linux PCI abstraction layer.
+ * consistent with the Linux PCI abstraction layer.
*/
-void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus)
+static void
+sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus)
{
- int status;
- int nasid, cnode;
+ s64 status = 0;
struct pci_controller *controller;
- struct sn_pci_controller *sn_controller;
struct pcibus_bussoft *prom_bussoft_ptr;
- struct hubdev_info *hubdev_info;
- void *provider_soft;
- struct sn_pcibus_provider *provider;
+
status = sal_get_pcibus_info((u64) segment, (u64) busnum,
(u64) ia64_tpa(&prom_bussoft_ptr));
@@ -480,261 +239,77 @@ void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus)
return; /*bus # does not exist */
prom_bussoft_ptr = __va(prom_bussoft_ptr);
- /* Allocate a sn_pci_controller, which has a pci_controller struct
- * as the first member.
- */
- sn_controller = kzalloc(sizeof(struct sn_pci_controller), GFP_KERNEL);
- if (!sn_controller)
+ controller = kzalloc(sizeof(*controller), GFP_KERNEL);
+ if (!controller)
BUG();
- INIT_LIST_HEAD(&sn_controller->pcidev_info);
- controller = &sn_controller->pci_controller;
controller->segment = segment;
- if (bus == NULL) {
- bus = pci_scan_bus(busnum, &pci_root_ops, controller);
- if (bus == NULL)
- goto error_return; /* error, or bus already scanned */
- bus->sysdata = NULL;
- }
-
- if (bus->sysdata)
- goto error_return; /* sysdata already alloc'd */
-
/*
- * Per-provider fixup. Copies the contents from prom to local
- * area and links SN_PCIBUS_BUSSOFT().
+ * Temporarily save the prom_bussoft_ptr for use by sn_bus_fixup().
+ * (platform_data will be overwritten later in sn_common_bus_fixup())
*/
+ controller->platform_data = prom_bussoft_ptr;
- if (prom_bussoft_ptr->bs_asic_type >= PCIIO_ASIC_MAX_TYPES)
- goto error_return; /* unsupported asic type */
-
- if (prom_bussoft_ptr->bs_asic_type == PCIIO_ASIC_TYPE_PPB)
- goto error_return; /* no further fixup necessary */
-
- provider = sn_pci_provider[prom_bussoft_ptr->bs_asic_type];
- if (provider == NULL)
- goto error_return; /* no provider registerd for this asic */
+ bus = pci_scan_bus(busnum, &pci_root_ops, controller);
+ if (bus == NULL)
+ goto error_return; /* error, or bus already scanned */
bus->sysdata = controller;
- if (provider->bus_fixup)
- provider_soft = (*provider->bus_fixup) (prom_bussoft_ptr, controller);
- else
- provider_soft = NULL;
-
- if (provider_soft == NULL) {
- /* fixup failed or not applicable */
- bus->sysdata = NULL;
- goto error_return;
- }
-
- /*
- * Setup pci_windows for legacy IO and MEM space.
- * (Temporary until ACPI support is in place.)
- */
- controller->window = kcalloc(2, sizeof(struct pci_window), GFP_KERNEL);
- if (controller->window == NULL)
- BUG();
- controller->window[0].offset = prom_bussoft_ptr->bs_legacy_io;
- controller->window[0].resource.name = "legacy_io";
- controller->window[0].resource.flags = IORESOURCE_IO;
- controller->window[0].resource.start = prom_bussoft_ptr->bs_legacy_io;
- controller->window[0].resource.end =
- controller->window[0].resource.start + 0xffff;
- controller->window[0].resource.parent = &ioport_resource;
- controller->window[1].offset = prom_bussoft_ptr->bs_legacy_mem;
- controller->window[1].resource.name = "legacy_mem";
- controller->window[1].resource.flags = IORESOURCE_MEM;
- controller->window[1].resource.start = prom_bussoft_ptr->bs_legacy_mem;
- controller->window[1].resource.end =
- controller->window[1].resource.start + (1024 * 1024) - 1;
- controller->window[1].resource.parent = &iomem_resource;
- controller->windows = 2;
-
- /*
- * Generic bus fixup goes here. Don't reference prom_bussoft_ptr
- * after this point.
- */
-
- PCI_CONTROLLER(bus)->platform_data = provider_soft;
- nasid = NASID_GET(SN_PCIBUS_BUSSOFT(bus)->bs_base);
- cnode = nasid_to_cnodeid(nasid);
- hubdev_info = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo);
- SN_PCIBUS_BUSSOFT(bus)->bs_xwidget_info =
- &(hubdev_info->hdi_xwidget_info[SN_PCIBUS_BUSSOFT(bus)->bs_xid]);
- /*
- * If the node information we obtained during the fixup phase is invalid
- * then set controller->node to -1 (undetermined)
- */
- if (controller->node >= num_online_nodes()) {
- struct pcibus_bussoft *b = SN_PCIBUS_BUSSOFT(bus);
-
- printk(KERN_WARNING "Device ASIC=%u XID=%u PBUSNUM=%u"
- "L_IO=%lx L_MEM=%lx BASE=%lx\n",
- b->bs_asic_type, b->bs_xid, b->bs_persist_busnum,
- b->bs_legacy_io, b->bs_legacy_mem, b->bs_base);
- printk(KERN_WARNING "on node %d but only %d nodes online."
- "Association set to undetermined.\n",
- controller->node, num_online_nodes());
- controller->node = -1;
- }
return;
error_return:
- kfree(sn_controller);
+ kfree(controller);
return;
}
-void sn_bus_store_sysdata(struct pci_dev *dev)
+/*
+ * sn_bus_fixup
+ */
+void
+sn_bus_fixup(struct pci_bus *bus)
{
- struct sysdata_el *element;
-
- element = kzalloc(sizeof(struct sysdata_el), GFP_KERNEL);
- if (!element) {
- dev_dbg(dev, "%s: out of memory!\n", __FUNCTION__);
- return;
- }
- element->sysdata = SN_PCIDEV_INFO(dev);
- list_add(&element->entry, &sn_sysdata_list);
-}
+ struct pci_dev *pci_dev = NULL;
+ struct pcibus_bussoft *prom_bussoft_ptr;
+ extern void sn_common_bus_fixup(struct pci_bus *,
+ struct pcibus_bussoft *);
+
+
+ if (!bus->parent) { /* If root bus */
+ prom_bussoft_ptr = PCI_CONTROLLER(bus)->platform_data;
+ if (prom_bussoft_ptr == NULL) {
+ printk(KERN_ERR
+ "sn_bus_fixup: 0x%04x:0x%02x Unable to "
+ "obtain prom_bussoft_ptr\n",
+ pci_domain_nr(bus), bus->number);
+ return;
+ }
+ sn_common_bus_fixup(bus, prom_bussoft_ptr);
+ sn_legacy_pci_window_fixup(PCI_CONTROLLER(bus),
+ prom_bussoft_ptr->bs_legacy_io,
+ prom_bussoft_ptr->bs_legacy_mem);
+ }
+ list_for_each_entry(pci_dev, &bus->devices, bus_list) {
+ sn_pci_fixup_slot(pci_dev);
+ }
-void sn_bus_free_sysdata(void)
-{
- struct sysdata_el *element;
- struct list_head *list, *safe;
-
- list_for_each_safe(list, safe, &sn_sysdata_list) {
- element = list_entry(list, struct sysdata_el, entry);
- list_del(&element->entry);
- list_del(&(((struct pcidev_info *)
- (element->sysdata))->pdi_list));
- kfree(element->sysdata);
- kfree(element);
- }
- return;
}
/*
- * Ugly hack to get PCI setup until we have a proper ACPI namespace.
+ * sn_io_init - PROM does not have ACPI support to define nodes or root buses,
+ * so we need to do things the hard way, including initiating the
+ * bus scanning ourselves.
*/
-#define PCI_BUSES_TO_SCAN 256
-
-static int __init sn_pci_init(void)
+void __init sn_io_init(void)
{
int i, j;
- struct pci_dev *pci_dev = NULL;
-
- if (!ia64_platform_is("sn2") || IS_RUNNING_ON_FAKE_PROM())
- return 0;
-
- /*
- * prime sn_pci_provider[]. Individial provider init routines will
- * override their respective default entries.
- */
-
- for (i = 0; i < PCIIO_ASIC_MAX_TYPES; i++)
- sn_pci_provider[i] = &sn_pci_default_provider;
- pcibr_init_provider();
- tioca_init_provider();
- tioce_init_provider();
-
- /*
- * This is needed to avoid bounce limit checks in the blk layer
- */
- ia64_max_iommu_merge_mask = ~PAGE_MASK;
sn_fixup_ionodes();
- sn_irq_lh_init();
- INIT_LIST_HEAD(&sn_sysdata_list);
- sn_init_cpei_timer();
-
-#ifdef CONFIG_PROC_FS
- register_sn_procfs();
-#endif
/* busses are not known yet ... */
for (i = 0; i <= max_segment_number; i++)
for (j = 0; j <= max_pcibus_number; j++)
sn_pci_controller_fixup(i, j, NULL);
-
- /*
- * Generic Linux PCI Layer has created the pci_bus and pci_dev
- * structures - time for us to add our SN PLatform specific
- * information.
- */
-
- while ((pci_dev =
- pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_dev)) != NULL)
- sn_pci_fixup_slot(pci_dev);
-
- sn_ioif_inited = 1; /* sn I/O infrastructure now initialized */
-
- return 0;
-}
-
-/*
- * hubdev_init_node() - Creates the HUB data structure and link them to it's
- * own NODE specific data area.
- */
-void hubdev_init_node(nodepda_t * npda, cnodeid_t node)
-{
- struct hubdev_info *hubdev_info;
- int size;
- pg_data_t *pg;
-
- size = sizeof(struct hubdev_info);
-
- if (node >= num_online_nodes()) /* Headless/memless IO nodes */
- pg = NODE_DATA(0);
- else
- pg = NODE_DATA(node);
-
- hubdev_info = (struct hubdev_info *)alloc_bootmem_node(pg, size);
-
- npda->pdinfo = (void *)hubdev_info;
}
-
-geoid_t
-cnodeid_get_geoid(cnodeid_t cnode)
-{
- struct hubdev_info *hubdev;
-
- hubdev = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo);
- return hubdev->hdi_geoid;
-}
-
-void sn_generate_path(struct pci_bus *pci_bus, char *address)
-{
- nasid_t nasid;
- cnodeid_t cnode;
- geoid_t geoid;
- moduleid_t moduleid;
- u16 bricktype;
-
- nasid = NASID_GET(SN_PCIBUS_BUSSOFT(pci_bus)->bs_base);
- cnode = nasid_to_cnodeid(nasid);
- geoid = cnodeid_get_geoid(cnode);
- moduleid = geo_module(geoid);
-
- sprintf(address, "module_%c%c%c%c%.2d",
- '0'+RACK_GET_CLASS(MODULE_GET_RACK(moduleid)),
- '0'+RACK_GET_GROUP(MODULE_GET_RACK(moduleid)),
- '0'+RACK_GET_NUM(MODULE_GET_RACK(moduleid)),
- MODULE_GET_BTCHAR(moduleid), MODULE_GET_BPOS(moduleid));
-
- /* Tollhouse requires slot id to be displayed */
- bricktype = MODULE_GET_BTYPE(moduleid);
- if ((bricktype == L1_BRICKTYPE_191010) ||
- (bricktype == L1_BRICKTYPE_1932))
- sprintf(address, "%s^%d", address, geo_slot(geoid));
-}
-
-subsys_initcall(sn_pci_init);
-EXPORT_SYMBOL(sn_pci_fixup_slot);
-EXPORT_SYMBOL(sn_pci_unfixup_slot);
-EXPORT_SYMBOL(sn_pci_controller_fixup);
-EXPORT_SYMBOL(sn_bus_store_sysdata);
-EXPORT_SYMBOL(sn_bus_free_sysdata);
-EXPORT_SYMBOL(sn_generate_path);
diff --git a/arch/ia64/sn/kernel/iomv.c b/arch/ia64/sn/kernel/iomv.c
index 7ce3cdad627b..4aa4f301d56d 100644
--- a/arch/ia64/sn/kernel/iomv.c
+++ b/arch/ia64/sn/kernel/iomv.c
@@ -3,10 +3,11 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2000-2003, 2006 Silicon Graphics, Inc. All rights reserved.
*/
#include <linux/module.h>
+#include <linux/acpi.h>
#include <asm/io.h>
#include <asm/delay.h>
#include <asm/vga.h>
@@ -15,6 +16,7 @@
#include <asm/sn/pda.h>
#include <asm/sn/sn_cpuid.h>
#include <asm/sn/shub_mmr.h>
+#include <asm/sn/acpi.h>
#define IS_LEGACY_VGA_IOPORT(p) \
(((p) >= 0x3b0 && (p) <= 0x3bb) || ((p) >= 0x3c0 && (p) <= 0x3df))
@@ -31,11 +33,14 @@ void *sn_io_addr(unsigned long port)
{
if (!IS_RUNNING_ON_SIMULATOR()) {
if (IS_LEGACY_VGA_IOPORT(port))
- port += vga_console_iobase;
+ return (__ia64_mk_io_addr(port));
/* On sn2, legacy I/O ports don't point at anything */
if (port < (64 * 1024))
return NULL;
- return ((void *)(port | __IA64_UNCACHED_OFFSET));
+ if (SN_ACPI_BASE_SUPPORT())
+ return (__ia64_mk_io_addr(port));
+ else
+ return ((void *)(port | __IA64_UNCACHED_OFFSET));
} else {
/* but the simulator uses them... */
unsigned long addr;
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
index 7a2d824c5ce3..1d009f93244d 100644
--- a/arch/ia64/sn/kernel/setup.c
+++ b/arch/ia64/sn/kernel/setup.c
@@ -388,6 +388,14 @@ void __init sn_setup(char **cmdline_p)
ia64_sn_plat_set_error_handling_features(); // obsolete
ia64_sn_set_os_feature(OSF_MCA_SLV_TO_OS_INIT_SLV);
ia64_sn_set_os_feature(OSF_FEAT_LOG_SBES);
+ /*
+ * Note: The calls to notify the PROM of ACPI and PCI Segment
+ * support must be done prior to acpi_load_tables(), as
+ * an ACPI capable PROM will rebuild the DSDT as result
+ * of the call.
+ */
+ ia64_sn_set_os_feature(OSF_PCISEGMENT_ENABLE);
+ ia64_sn_set_os_feature(OSF_ACPI_ENABLE);
#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE)
@@ -413,6 +421,16 @@ void __init sn_setup(char **cmdline_p)
if (! vga_console_membase)
sn_scan_pcdp();
+ /*
+ * Setup legacy IO space.
+ * vga_console_iobase maps to PCI IO Space address 0 on the
+ * bus containing the VGA console.
+ */
+ if (vga_console_iobase) {
+ io_space[0].mmio_base = vga_console_iobase;
+ io_space[0].sparse = 0;
+ }
+
if (vga_console_membase) {
/* usable vga ... make tty0 the preferred default console */
if (!strstr(*cmdline_p, "console="))
diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c
index feaf1a6e8101..493380b2c05f 100644
--- a/arch/ia64/sn/kernel/tiocx.c
+++ b/arch/ia64/sn/kernel/tiocx.c
@@ -552,7 +552,7 @@ static void __exit tiocx_exit(void)
bus_unregister(&tiocx_bus_type);
}
-subsys_initcall(tiocx_init);
+fs_initcall(tiocx_init);
module_exit(tiocx_exit);
/************************************************************************
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c
index 27dd7df0f446..6846dc9b432d 100644
--- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c
+++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c
@@ -3,7 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 2001-2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2001-2004, 2006 Silicon Graphics, Inc. All rights reserved.
*/
#include <linux/interrupt.h>
@@ -109,7 +109,6 @@ void *
pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller)
{
int nasid, cnode, j;
- cnodeid_t near_cnode;
struct hubdev_info *hubdev_info;
struct pcibus_info *soft;
struct sn_flush_device_kernel *sn_flush_device_kernel;
@@ -186,20 +185,6 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
return NULL;
}
- if (prom_bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCP) {
- /* TIO PCI Bridge: find nearest node with CPUs */
- int e = sn_hwperf_get_nearest_node(cnode, NULL, &near_cnode);
-
- if (e < 0) {
- near_cnode = (cnodeid_t)-1; /* use any node */
- printk(KERN_WARNING "pcibr_bus_fixup: failed to find "
- "near node with CPUs to TIO node %d, err=%d\n",
- cnode, e);
- }
- controller->node = near_cnode;
- }
- else
- controller->node = cnode;
return soft;
}
diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c
index 46e16dcf5971..35f854fb6120 100644
--- a/arch/ia64/sn/pci/tioce_provider.c
+++ b/arch/ia64/sn/pci/tioce_provider.c
@@ -15,7 +15,6 @@
#include <asm/sn/pcidev.h>
#include <asm/sn/pcibus_provider_defs.h>
#include <asm/sn/tioce_provider.h>
-#include <asm/sn/sn2/sn_hwperf.h>
/*
* 1/26/2006
@@ -990,8 +989,6 @@ tioce_target_interrupt(struct sn_irq_info *sn_irq_info)
static void *
tioce_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller)
{
- int my_nasid;
- cnodeid_t my_cnode, mem_cnode;
struct tioce_common *tioce_common;
struct tioce_kernel *tioce_kern;
struct tioce __iomem *tioce_mmr;
@@ -1035,21 +1032,6 @@ tioce_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
tioce_common->ce_pcibus.bs_persist_segment,
tioce_common->ce_pcibus.bs_persist_busnum);
- /*
- * identify closest nasid for memory allocations
- */
-
- my_nasid = NASID_GET(tioce_common->ce_pcibus.bs_base);
- my_cnode = nasid_to_cnodeid(my_nasid);
-
- if (sn_hwperf_get_nearest_node(my_cnode, &mem_cnode, NULL) < 0) {
- printk(KERN_WARNING "tioce_bus_fixup: failed to find "
- "closest node with MEM to TIO node %d\n", my_cnode);
- mem_cnode = (cnodeid_t)-1; /* use any node */
- }
-
- controller->node = mem_cnode;
-
return tioce_common;
}
diff --git a/arch/m32r/lib/csum_partial_copy.c b/arch/m32r/lib/csum_partial_copy.c
index 3d5f06145854..5596f3df833f 100644
--- a/arch/m32r/lib/csum_partial_copy.c
+++ b/arch/m32r/lib/csum_partial_copy.c
@@ -27,9 +27,8 @@
/*
* Copy while checksumming, otherwise like csum_partial
*/
-unsigned int
-csum_partial_copy_nocheck (const unsigned char *src, unsigned char *dst,
- int len, unsigned int sum)
+__wsum
+csum_partial_copy_nocheck (const void *src, void *dst, int len, __wsum sum)
{
sum = csum_partial(src, len, sum);
memcpy(dst, src, len);
@@ -42,10 +41,9 @@ EXPORT_SYMBOL(csum_partial_copy_nocheck);
* Copy from userspace and compute checksum. If we catch an exception
* then zero the rest of the buffer.
*/
-unsigned int
-csum_partial_copy_from_user (const unsigned char __user *src,
- unsigned char *dst,
- int len, unsigned int sum, int *err_ptr)
+__wsum
+csum_partial_copy_from_user (const void __user *src, void *dst,
+ int len, __wsum sum, int *err_ptr)
{
int missing;
diff --git a/arch/m68k/lib/checksum.c b/arch/m68k/lib/checksum.c
index cb13c6e3ccae..aed3be29e06b 100644
--- a/arch/m68k/lib/checksum.c
+++ b/arch/m68k/lib/checksum.c
@@ -39,8 +39,7 @@
* computes a partial checksum, e.g. for TCP/UDP fragments
*/
-unsigned int
-csum_partial (const unsigned char *buff, int len, unsigned int sum)
+__wsum csum_partial(const void *buff, int len, __wsum sum)
{
unsigned long tmp1, tmp2;
/*
@@ -133,9 +132,9 @@ EXPORT_SYMBOL(csum_partial);
* copy from user space while checksumming, with exception handling.
*/
-unsigned int
-csum_partial_copy_from_user(const unsigned char __user *src, unsigned char *dst,
- int len, int sum, int *csum_err)
+__wsum
+csum_partial_copy_from_user(const void __user *src, void *dst,
+ int len, __wsum sum, int *csum_err)
{
/*
* GCC doesn't like more than 10 operands for the asm
@@ -325,8 +324,8 @@ csum_partial_copy_from_user(const unsigned char __user *src, unsigned char *dst,
* copy from kernel space while checksumming, otherwise like csum_partial
*/
-unsigned int
-csum_partial_copy_nocheck(const unsigned char *src, unsigned char *dst, int len, int sum)
+__wsum
+csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
{
unsigned long tmp1, tmp2;
__asm__("movel %2,%4\n\t"
diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig
index 6d920d4bdc3d..c1bc22c6d0d8 100644
--- a/arch/m68knommu/Kconfig
+++ b/arch/m68knommu/Kconfig
@@ -565,7 +565,7 @@ config ROMVEC
depends on ROM
help
This is almost always the same as the base of the ROM. Since on all
- 68000 type varients the vectors are at the base of the boot device
+ 68000 type variants the vectors are at the base of the boot device
on system startup.
config ROMVECSIZE
@@ -574,7 +574,7 @@ config ROMVECSIZE
depends on ROM
help
Define the size of the vector region in ROM. For most 68000
- varients this would be 0x400 bytes in size. Set to 0 if you do
+ variants this would be 0x400 bytes in size. Set to 0 if you do
not want a vector region at the start of the ROM.
config ROMSTART
diff --git a/arch/m68knommu/kernel/m68k_ksyms.c b/arch/m68knommu/kernel/m68k_ksyms.c
index 1e62150f3588..25327c9eadd7 100644
--- a/arch/m68knommu/kernel/m68k_ksyms.c
+++ b/arch/m68knommu/kernel/m68k_ksyms.c
@@ -38,7 +38,7 @@ EXPORT_SYMBOL(ip_fast_csum);
EXPORT_SYMBOL(kernel_thread);
/* Networking helper routines. */
-EXPORT_SYMBOL(csum_partial_copy);
+EXPORT_SYMBOL(csum_partial_copy_nocheck);
/* The following are special because they're not called
explicitly (the C compiler generates them). Fortunately,
diff --git a/arch/m68knommu/lib/checksum.c b/arch/m68knommu/lib/checksum.c
index 7bec6fdee34b..269d83bfbbe1 100644
--- a/arch/m68knommu/lib/checksum.c
+++ b/arch/m68knommu/lib/checksum.c
@@ -96,9 +96,9 @@ out:
* This is a version of ip_compute_csum() optimized for IP headers,
* which always checksum on 4 octet boundaries.
*/
-unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl)
+__sum16 ip_fast_csum(const void *iph, unsigned int ihl)
{
- return ~do_csum(iph,ihl*4);
+ return (__force __sum16)~do_csum(iph,ihl*4);
}
/*
@@ -113,15 +113,15 @@ unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl)
*
* it's best to have buff aligned on a 32-bit boundary
*/
-unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
+__wsum csum_partial(const void *buff, int len, __wsum sum)
{
unsigned int result = do_csum(buff, len);
/* add in old sum, and carry.. */
- result += sum;
- if (sum > result)
+ result += (__force u32)sum;
+ if ((__force u32)sum > result)
result += 1;
- return result;
+ return (__force __wsum)result;
}
EXPORT_SYMBOL(csum_partial);
@@ -130,21 +130,21 @@ EXPORT_SYMBOL(csum_partial);
* this routine is used for miscellaneous IP-like checksums, mainly
* in icmp.c
*/
-unsigned short ip_compute_csum(const unsigned char * buff, int len)
+__sum16 ip_compute_csum(const void *buff, int len)
{
- return ~do_csum(buff,len);
+ return (__force __sum16)~do_csum(buff,len);
}
/*
* copy from fs while checksumming, otherwise like csum_partial
*/
-unsigned int
-csum_partial_copy_from_user(const unsigned char *src, unsigned char *dst,
- int len, int sum, int *csum_err)
+__wsum
+csum_partial_copy_from_user(const void __user *src, void *dst,
+ int len, __wsum sum, int *csum_err)
{
if (csum_err) *csum_err = 0;
- memcpy(dst, src, len);
+ memcpy(dst, (__force const void *)src, len);
return csum_partial(dst, len, sum);
}
@@ -152,8 +152,8 @@ csum_partial_copy_from_user(const unsigned char *src, unsigned char *dst,
* copy from ds while checksumming, otherwise like csum_partial
*/
-unsigned int
-csum_partial_copy(const unsigned char *src, unsigned char *dst, int len, int sum)
+__wsum
+csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
{
memcpy(dst, src, len);
return csum_partial(dst, len, sum);
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 1443024b1c7c..27f83e642968 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -266,8 +266,8 @@ config MIPS_MALTA
select BOOT_ELF32
select HAVE_STD_PC_SERIAL_PORT
select DMA_NONCOHERENT
- select IRQ_CPU
select GENERIC_ISA_DMA
+ select IRQ_CPU
select HW_HAS_PCI
select I8259
select MIPS_BOARDS_GEN
@@ -534,7 +534,7 @@ config SGI_IP22
select HW_HAS_EISA
select IP22_CPU_SCACHE
select IRQ_CPU
- select NO_ISA if ISA
+ select GENERIC_ISA_DMA_SUPPORT_BROKEN
select SWAP_IO_SPACE
select SYS_HAS_CPU_R4X00
select SYS_HAS_CPU_R5000
@@ -766,6 +766,23 @@ config TOSHIBA_RBTX4938
endchoice
+config KEXEC
+ bool "Kexec system call (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ help
+ kexec is a system call that implements the ability to shutdown your
+ current kernel, and to start another kernel. It is like a reboot
+ but it is indepedent of the system firmware. And like a reboot
+ you can start any kernel with it, not just Linux.
+
+ The name comes from the similiarity to the exec system call.
+
+ It is an ongoing process to be certain the hardware in a machine
+ is properly shutdown, so do not be surprised if this code does not
+ initially work for you. It may help to enable device hotplugging
+ support. As of this writing the exact hardware interface is
+ strongly in flux, so no good recommendation can be made.
+
source "arch/mips/ddb5xxx/Kconfig"
source "arch/mips/gt64120/ev64120/Kconfig"
source "arch/mips/jazz/Kconfig"
@@ -864,8 +881,11 @@ config MIPS_NILE4
config MIPS_DISABLE_OBSOLETE_IDE
bool
+config GENERIC_ISA_DMA_SUPPORT_BROKEN
+ bool
+
#
-# Endianess selection. Suffiently obscure so many users don't know what to
+# Endianess selection. Sufficiently obscure so many users don't know what to
# answer,so we try hard to limit the available choices. Also the use of a
# choice statement should be more obvious to the user.
#
@@ -874,7 +894,7 @@ choice
help
Some MIPS machines can be configured for either little or big endian
byte order. These modes require different kernels and a different
- Linux distribution. In general there is one prefered byteorder for a
+ Linux distribution. In general there is one preferred byteorder for a
particular system but some systems are just as commonly used in the
one or the other endianess.
@@ -1835,13 +1855,11 @@ source "drivers/pci/Kconfig"
config ISA
bool
-config NO_ISA
- bool
-
config EISA
bool "EISA support"
depends on HW_HAS_EISA
select ISA
+ select GENERIC_ISA_DMA
---help---
The Extended Industry Standard Architecture (EISA) bus was
developed as an open alternative to the IBM MicroChannel bus.
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index d580d46f967b..641aa30b3638 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -63,9 +63,7 @@ cflags-y += -mabi=64
ifdef CONFIG_BUILD_ELF64
cflags-y += $(call cc-option,-mno-explicit-relocs)
else
-# -msym32 can not be used for modules since they are loaded into XKSEG
-CFLAGS_MODULE += $(call cc-option,-mno-explicit-relocs)
-CFLAGS_KERNEL += $(call cc-option,-msym32)
+cflags-y += $(call cc-option,-msym32)
endif
endif
diff --git a/arch/mips/au1000/common/irq.c b/arch/mips/au1000/common/irq.c
index 2abe132bb07d..9cf7b6715836 100644
--- a/arch/mips/au1000/common/irq.c
+++ b/arch/mips/au1000/common/irq.c
@@ -70,7 +70,6 @@ extern irq_cpustat_t irq_stat [NR_CPUS];
extern void mips_timer_interrupt(void);
static void setup_local_irq(unsigned int irq, int type, int int_req);
-static unsigned int startup_irq(unsigned int irq);
static void end_irq(unsigned int irq_nr);
static inline void mask_and_ack_level_irq(unsigned int irq_nr);
static inline void mask_and_ack_rise_edge_irq(unsigned int irq_nr);
@@ -84,20 +83,6 @@ void (*board_init_irq)(void);
static DEFINE_SPINLOCK(irq_lock);
-static unsigned int startup_irq(unsigned int irq_nr)
-{
- local_enable_irq(irq_nr);
- return 0;
-}
-
-
-static void shutdown_irq(unsigned int irq_nr)
-{
- local_disable_irq(irq_nr);
- return;
-}
-
-
inline void local_enable_irq(unsigned int irq_nr)
{
if (irq_nr > AU1000_LAST_INTC0_INT) {
@@ -249,41 +234,37 @@ void restore_local_and_enable(int controller, unsigned long mask)
static struct irq_chip rise_edge_irq_type = {
.typename = "Au1000 Rise Edge",
- .startup = startup_irq,
- .shutdown = shutdown_irq,
- .enable = local_enable_irq,
- .disable = local_disable_irq,
.ack = mask_and_ack_rise_edge_irq,
+ .mask = local_disable_irq,
+ .mask_ack = mask_and_ack_rise_edge_irq,
+ .unmask = local_enable_irq,
.end = end_irq,
};
static struct irq_chip fall_edge_irq_type = {
.typename = "Au1000 Fall Edge",
- .startup = startup_irq,
- .shutdown = shutdown_irq,
- .enable = local_enable_irq,
- .disable = local_disable_irq,
.ack = mask_and_ack_fall_edge_irq,
+ .mask = local_disable_irq,
+ .mask_ack = mask_and_ack_fall_edge_irq,
+ .unmask = local_enable_irq,
.end = end_irq,
};
static struct irq_chip either_edge_irq_type = {
.typename = "Au1000 Rise or Fall Edge",
- .startup = startup_irq,
- .shutdown = shutdown_irq,
- .enable = local_enable_irq,
- .disable = local_disable_irq,
.ack = mask_and_ack_either_edge_irq,
+ .mask = local_disable_irq,
+ .mask_ack = mask_and_ack_either_edge_irq,
+ .unmask = local_enable_irq,
.end = end_irq,
};
static struct irq_chip level_irq_type = {
.typename = "Au1000 Level",
- .startup = startup_irq,
- .shutdown = shutdown_irq,
- .enable = local_enable_irq,
- .disable = local_disable_irq,
.ack = mask_and_ack_level_irq,
+ .mask = local_disable_irq,
+ .mask_ack = mask_and_ack_level_irq,
+ .unmask = local_enable_irq,
.end = end_irq,
};
@@ -328,31 +309,31 @@ static void setup_local_irq(unsigned int irq_nr, int type, int int_req)
au_writel(1<<(irq_nr-32), IC1_CFG2CLR);
au_writel(1<<(irq_nr-32), IC1_CFG1CLR);
au_writel(1<<(irq_nr-32), IC1_CFG0SET);
- irq_desc[irq_nr].chip = &rise_edge_irq_type;
+ set_irq_chip(irq_nr, &rise_edge_irq_type);
break;
case INTC_INT_FALL_EDGE: /* 0:1:0 */
au_writel(1<<(irq_nr-32), IC1_CFG2CLR);
au_writel(1<<(irq_nr-32), IC1_CFG1SET);
au_writel(1<<(irq_nr-32), IC1_CFG0CLR);
- irq_desc[irq_nr].chip = &fall_edge_irq_type;
+ set_irq_chip(irq_nr, &fall_edge_irq_type);
break;
case INTC_INT_RISE_AND_FALL_EDGE: /* 0:1:1 */
au_writel(1<<(irq_nr-32), IC1_CFG2CLR);
au_writel(1<<(irq_nr-32), IC1_CFG1SET);
au_writel(1<<(irq_nr-32), IC1_CFG0SET);
- irq_desc[irq_nr].chip = &either_edge_irq_type;
+ set_irq_chip(irq_nr, &either_edge_irq_type);
break;
case INTC_INT_HIGH_LEVEL: /* 1:0:1 */
au_writel(1<<(irq_nr-32), IC1_CFG2SET);
au_writel(1<<(irq_nr-32), IC1_CFG1CLR);
au_writel(1<<(irq_nr-32), IC1_CFG0SET);
- irq_desc[irq_nr].chip = &level_irq_type;
+ set_irq_chip(irq_nr, &level_irq_type);
break;
case INTC_INT_LOW_LEVEL: /* 1:1:0 */
au_writel(1<<(irq_nr-32), IC1_CFG2SET);
au_writel(1<<(irq_nr-32), IC1_CFG1SET);
au_writel(1<<(irq_nr-32), IC1_CFG0CLR);
- irq_desc[irq_nr].chip = &level_irq_type;
+ set_irq_chip(irq_nr, &level_irq_type);
break;
case INTC_INT_DISABLED: /* 0:0:0 */
au_writel(1<<(irq_nr-32), IC1_CFG0CLR);
@@ -380,31 +361,31 @@ static void setup_local_irq(unsigned int irq_nr, int type, int int_req)
au_writel(1<<irq_nr, IC0_CFG2CLR);
au_writel(1<<irq_nr, IC0_CFG1CLR);
au_writel(1<<irq_nr, IC0_CFG0SET);
- irq_desc[irq_nr].chip = &rise_edge_irq_type;
+ set_irq_chip(irq_nr, &rise_edge_irq_type);
break;
case INTC_INT_FALL_EDGE: /* 0:1:0 */
au_writel(1<<irq_nr, IC0_CFG2CLR);
au_writel(1<<irq_nr, IC0_CFG1SET);
au_writel(1<<irq_nr, IC0_CFG0CLR);
- irq_desc[irq_nr].chip = &fall_edge_irq_type;
+ set_irq_chip(irq_nr, &fall_edge_irq_type);
break;
case INTC_INT_RISE_AND_FALL_EDGE: /* 0:1:1 */
au_writel(1<<irq_nr, IC0_CFG2CLR);
au_writel(1<<irq_nr, IC0_CFG1SET);
au_writel(1<<irq_nr, IC0_CFG0SET);
- irq_desc[irq_nr].chip = &either_edge_irq_type;
+ set_irq_chip(irq_nr, &either_edge_irq_type);
break;
case INTC_INT_HIGH_LEVEL: /* 1:0:1 */
au_writel(1<<irq_nr, IC0_CFG2SET);
au_writel(1<<irq_nr, IC0_CFG1CLR);
au_writel(1<<irq_nr, IC0_CFG0SET);
- irq_desc[irq_nr].chip = &level_irq_type;
+ set_irq_chip(irq_nr, &level_irq_type);
break;
case INTC_INT_LOW_LEVEL: /* 1:1:0 */
au_writel(1<<irq_nr, IC0_CFG2SET);
au_writel(1<<irq_nr, IC0_CFG1SET);
au_writel(1<<irq_nr, IC0_CFG0CLR);
- irq_desc[irq_nr].chip = &level_irq_type;
+ set_irq_chip(irq_nr, &level_irq_type);
break;
case INTC_INT_DISABLED: /* 0:0:0 */
au_writel(1<<irq_nr, IC0_CFG0CLR);
diff --git a/arch/mips/au1000/pb1200/board_setup.c b/arch/mips/au1000/pb1200/board_setup.c
index 8b953b9fc25c..043302b7fe58 100644
--- a/arch/mips/au1000/pb1200/board_setup.c
+++ b/arch/mips/au1000/pb1200/board_setup.c
@@ -55,7 +55,7 @@
#endif
extern void _board_init_irq(void);
-extern void (*board_init_irq)(void);
+extern void (*board_init_irq)(void);
void board_reset (void)
{
@@ -151,11 +151,7 @@ void __init board_setup(void)
#endif
/* Setup Pb1200 External Interrupt Controller */
- {
- extern void (*board_init_irq)(void);
- extern void _board_init_irq(void);
- board_init_irq = _board_init_irq;
- }
+ board_init_irq = _board_init_irq;
}
int
diff --git a/arch/mips/cobalt/irq.c b/arch/mips/cobalt/irq.c
index 82e569d5b02c..4c46f0e73783 100644
--- a/arch/mips/cobalt/irq.c
+++ b/arch/mips/cobalt/irq.c
@@ -45,25 +45,22 @@ static inline void galileo_irq(void)
{
unsigned int mask, pending, devfn;
- mask = GALILEO_INL(GT_INTRMASK_OFS);
- pending = GALILEO_INL(GT_INTRCAUSE_OFS) & mask;
+ mask = GT_READ(GT_INTRMASK_OFS);
+ pending = GT_READ(GT_INTRCAUSE_OFS) & mask;
- if (pending & GALILEO_INTR_T0EXP) {
-
- GALILEO_OUTL(~GALILEO_INTR_T0EXP, GT_INTRCAUSE_OFS);
+ if (pending & GT_INTR_T0EXP_MSK) {
+ GT_WRITE(GT_INTRCAUSE_OFS, ~GT_INTR_T0EXP_MSK);
do_IRQ(COBALT_GALILEO_IRQ);
-
- } else if (pending & GALILEO_INTR_RETRY_CTR) {
-
- devfn = GALILEO_INL(GT_PCI0_CFGADDR_OFS) >> 8;
- GALILEO_OUTL(~GALILEO_INTR_RETRY_CTR, GT_INTRCAUSE_OFS);
- printk(KERN_WARNING "Galileo: PCI retry count exceeded (%02x.%u)\n",
- PCI_SLOT(devfn), PCI_FUNC(devfn));
-
+ } else if (pending & GT_INTR_RETRYCTR0_MSK) {
+ devfn = GT_READ(GT_PCI0_CFGADDR_OFS) >> 8;
+ GT_WRITE(GT_INTRCAUSE_OFS, ~GT_INTR_RETRYCTR0_MSK);
+ printk(KERN_WARNING
+ "Galileo: PCI retry count exceeded (%02x.%u)\n",
+ PCI_SLOT(devfn), PCI_FUNC(devfn));
} else {
-
- GALILEO_OUTL(mask & ~pending, GT_INTRMASK_OFS);
- printk(KERN_WARNING "Galileo: masking unexpected interrupt %08x\n", pending);
+ GT_WRITE(GT_INTRMASK_OFS, mask & ~pending);
+ printk(KERN_WARNING
+ "Galileo: masking unexpected interrupt %08x\n", pending);
}
}
@@ -104,7 +101,7 @@ void __init arch_init_irq(void)
* Mask all Galileo interrupts. The Galileo
* handler is set in cobalt_timer_setup()
*/
- GALILEO_OUTL(0, GT_INTRMASK_OFS);
+ GT_WRITE(GT_INTRMASK_OFS, 0);
init_i8259_irqs(); /* 0 ... 15 */
mips_cpu_irq_init(COBALT_CPU_IRQ); /* 16 ... 23 */
diff --git a/arch/mips/cobalt/setup.c b/arch/mips/cobalt/setup.c
index bf9dc72b9720..e8f0f20b852d 100644
--- a/arch/mips/cobalt/setup.c
+++ b/arch/mips/cobalt/setup.c
@@ -51,23 +51,23 @@ const char *get_system_type(void)
void __init plat_timer_setup(struct irqaction *irq)
{
/* Load timer value for HZ (TCLK is 50MHz) */
- GALILEO_OUTL(50*1000*1000 / HZ, GT_TC0_OFS);
+ GT_WRITE(GT_TC0_OFS, 50*1000*1000 / HZ);
/* Enable timer */
- GALILEO_OUTL(GALILEO_ENTC0 | GALILEO_SELTC0, GT_TC_CONTROL_OFS);
+ GT_WRITE(GT_TC_CONTROL_OFS, GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK);
/* Register interrupt */
setup_irq(COBALT_GALILEO_IRQ, irq);
/* Enable interrupt */
- GALILEO_OUTL(GALILEO_INTR_T0EXP | GALILEO_INL(GT_INTRMASK_OFS), GT_INTRMASK_OFS);
+ GT_WRITE(GT_INTRMASK_OFS, GT_INTR_T0EXP_MSK | GT_READ(GT_INTRMASK_OFS));
}
extern struct pci_ops gt64111_pci_ops;
static struct resource cobalt_mem_resource = {
- .start = GT64111_MEM_BASE,
- .end = GT64111_MEM_END,
+ .start = GT_DEF_PCI0_MEM0_BASE,
+ .end = GT_DEF_PCI0_MEM0_BASE + GT_DEF_PCI0_MEM0_SIZE - 1,
.name = "PCI memory",
.flags = IORESOURCE_MEM
};
@@ -115,7 +115,7 @@ static struct pci_controller cobalt_pci_controller = {
.mem_resource = &cobalt_mem_resource,
.mem_offset = 0,
.io_resource = &cobalt_io_resource,
- .io_offset = 0 - GT64111_IO_BASE
+ .io_offset = 0 - GT_DEF_PCI0_IO_BASE,
};
void __init plat_mem_setup(void)
@@ -128,7 +128,7 @@ void __init plat_mem_setup(void)
_machine_halt = cobalt_machine_halt;
pm_power_off = cobalt_machine_power_off;
- set_io_port_base(CKSEG1ADDR(GT64111_IO_BASE));
+ set_io_port_base(CKSEG1ADDR(GT_DEF_PCI0_IO_BASE));
/* I/O port resource must include UART and LCD/buttons */
ioport_resource.end = 0x0fffffff;
@@ -139,7 +139,7 @@ void __init plat_mem_setup(void)
/* Read the cobalt id register out of the PCI config space */
PCI_CFG_SET(devfn, (VIA_COBALT_BRD_ID_REG & ~0x3));
- cobalt_board_id = GALILEO_INL(GT_PCI0_CFGDATA_OFS);
+ cobalt_board_id = GT_READ(GT_PCI0_CFGDATA_OFS);
cobalt_board_id >>= ((VIA_COBALT_BRD_ID_REG & 3) * 8);
cobalt_board_id = VIA_COBALT_BRD_REG_to_ID(cobalt_board_id);
diff --git a/arch/mips/ddb5xxx/ddb5477/irq_5477.c b/arch/mips/ddb5xxx/ddb5477/irq_5477.c
index ba52705a2738..96249aa5df5d 100644
--- a/arch/mips/ddb5xxx/ddb5477/irq_5477.c
+++ b/arch/mips/ddb5xxx/ddb5477/irq_5477.c
@@ -53,14 +53,6 @@ vrc5477_irq_disable(unsigned int irq)
ll_vrc5477_irq_disable(irq - vrc5477_irq_base);
}
-static unsigned int vrc5477_irq_startup(unsigned int irq)
-{
- vrc5477_irq_enable(irq);
- return 0;
-}
-
-#define vrc5477_irq_shutdown vrc5477_irq_disable
-
static void
vrc5477_irq_ack(unsigned int irq)
{
@@ -91,11 +83,10 @@ vrc5477_irq_end(unsigned int irq)
struct irq_chip vrc5477_irq_controller = {
.typename = "vrc5477_irq",
- .startup = vrc5477_irq_startup,
- .shutdown = vrc5477_irq_shutdown,
- .enable = vrc5477_irq_enable,
- .disable = vrc5477_irq_disable,
.ack = vrc5477_irq_ack,
+ .mask = vrc5477_irq_disable,
+ .mask_ack = vrc5477_irq_ack,
+ .unmask = vrc5477_irq_enable,
.end = vrc5477_irq_end
};
@@ -103,12 +94,8 @@ void __init vrc5477_irq_init(u32 irq_base)
{
u32 i;
- for (i= irq_base; i< irq_base+ NUM_5477_IRQ; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = NULL;
- irq_desc[i].depth = 1;
- irq_desc[i].chip = &vrc5477_irq_controller;
- }
+ for (i= irq_base; i< irq_base+ NUM_5477_IRQ; i++)
+ set_irq_chip(i, &vrc5477_irq_controller);
vrc5477_irq_base = irq_base;
}
diff --git a/arch/mips/dec/ecc-berr.c b/arch/mips/dec/ecc-berr.c
index 3e374d05978f..c8430c07355e 100644
--- a/arch/mips/dec/ecc-berr.c
+++ b/arch/mips/dec/ecc-berr.c
@@ -18,7 +18,6 @@
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/sched.h>
-#include <linux/spinlock.h>
#include <linux/types.h>
#include <asm/addrspace.h>
@@ -231,13 +230,10 @@ irqreturn_t dec_ecc_be_interrupt(int irq, void *dev_id)
static inline void dec_kn02_be_init(void)
{
volatile u32 *csr = (void *)CKSEG1ADDR(KN02_SLOT_BASE + KN02_CSR);
- unsigned long flags;
kn0x_erraddr = (void *)CKSEG1ADDR(KN02_SLOT_BASE + KN02_ERRADDR);
kn0x_chksyn = (void *)CKSEG1ADDR(KN02_SLOT_BASE + KN02_CHKSYN);
- spin_lock_irqsave(&kn02_lock, flags);
-
/* Preset write-only bits of the Control Register cache. */
cached_kn02_csr = *csr | KN02_CSR_LEDS;
@@ -247,8 +243,6 @@ static inline void dec_kn02_be_init(void)
cached_kn02_csr |= KN02_CSR_CORRECT;
*csr = cached_kn02_csr;
iob();
-
- spin_unlock_irqrestore(&kn02_lock, flags);
}
static inline void dec_kn03_be_init(void)
diff --git a/arch/mips/dec/int-handler.S b/arch/mips/dec/int-handler.S
index 31dd47d1002d..b251ef864c33 100644
--- a/arch/mips/dec/int-handler.S
+++ b/arch/mips/dec/int-handler.S
@@ -267,7 +267,7 @@ handle_it:
LONG_L s0, TI_REGS($28)
LONG_S sp, TI_REGS($28)
PTR_LA ra, ret_from_irq
- j do_IRQ
+ j dec_irq_dispatch
nop
#ifdef CONFIG_32BIT
diff --git a/arch/mips/dec/ioasic-irq.c b/arch/mips/dec/ioasic-irq.c
index 41cd2a96148b..269b22b34313 100644
--- a/arch/mips/dec/ioasic-irq.c
+++ b/arch/mips/dec/ioasic-irq.c
@@ -13,7 +13,6 @@
#include <linux/init.h>
#include <linux/irq.h>
-#include <linux/spinlock.h>
#include <linux/types.h>
#include <asm/dec/ioasic.h>
@@ -21,8 +20,6 @@
#include <asm/dec/ioasic_ints.h>
-static DEFINE_SPINLOCK(ioasic_lock);
-
static int ioasic_irq_base;
@@ -52,65 +49,31 @@ static inline void clear_ioasic_irq(unsigned int irq)
ioasic_write(IO_REG_SIR, sir);
}
-static inline void enable_ioasic_irq(unsigned int irq)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&ioasic_lock, flags);
- unmask_ioasic_irq(irq);
- spin_unlock_irqrestore(&ioasic_lock, flags);
-}
-
-static inline void disable_ioasic_irq(unsigned int irq)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&ioasic_lock, flags);
- mask_ioasic_irq(irq);
- spin_unlock_irqrestore(&ioasic_lock, flags);
-}
-
-
-static inline unsigned int startup_ioasic_irq(unsigned int irq)
-{
- enable_ioasic_irq(irq);
- return 0;
-}
-
-#define shutdown_ioasic_irq disable_ioasic_irq
-
static inline void ack_ioasic_irq(unsigned int irq)
{
- spin_lock(&ioasic_lock);
mask_ioasic_irq(irq);
- spin_unlock(&ioasic_lock);
fast_iob();
}
static inline void end_ioasic_irq(unsigned int irq)
{
if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
- enable_ioasic_irq(irq);
+ unmask_ioasic_irq(irq);
}
static struct irq_chip ioasic_irq_type = {
.typename = "IO-ASIC",
- .startup = startup_ioasic_irq,
- .shutdown = shutdown_ioasic_irq,
- .enable = enable_ioasic_irq,
- .disable = disable_ioasic_irq,
.ack = ack_ioasic_irq,
+ .mask = mask_ioasic_irq,
+ .mask_ack = ack_ioasic_irq,
+ .unmask = unmask_ioasic_irq,
.end = end_ioasic_irq,
};
-#define startup_ioasic_dma_irq startup_ioasic_irq
-
-#define shutdown_ioasic_dma_irq shutdown_ioasic_irq
-
-#define enable_ioasic_dma_irq enable_ioasic_irq
+#define unmask_ioasic_dma_irq unmask_ioasic_irq
-#define disable_ioasic_dma_irq disable_ioasic_irq
+#define mask_ioasic_dma_irq mask_ioasic_irq
#define ack_ioasic_dma_irq ack_ioasic_irq
@@ -123,11 +86,10 @@ static inline void end_ioasic_dma_irq(unsigned int irq)
static struct irq_chip ioasic_dma_irq_type = {
.typename = "IO-ASIC-DMA",
- .startup = startup_ioasic_dma_irq,
- .shutdown = shutdown_ioasic_dma_irq,
- .enable = enable_ioasic_dma_irq,
- .disable = disable_ioasic_dma_irq,
.ack = ack_ioasic_dma_irq,
+ .mask = mask_ioasic_dma_irq,
+ .mask_ack = ack_ioasic_dma_irq,
+ .unmask = unmask_ioasic_dma_irq,
.end = end_ioasic_dma_irq,
};
@@ -140,18 +102,12 @@ void __init init_ioasic_irqs(int base)
ioasic_write(IO_REG_SIMR, 0);
fast_iob();
- for (i = base; i < base + IO_INR_DMA; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = 0;
- irq_desc[i].depth = 1;
- irq_desc[i].chip = &ioasic_irq_type;
- }
- for (; i < base + IO_IRQ_LINES; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = 0;
- irq_desc[i].depth = 1;
- irq_desc[i].chip = &ioasic_dma_irq_type;
- }
+ for (i = base; i < base + IO_INR_DMA; i++)
+ set_irq_chip_and_handler(i, &ioasic_irq_type,
+ handle_level_irq);
+ for (; i < base + IO_IRQ_LINES; i++)
+ set_irq_chip_and_handler(i, &ioasic_dma_irq_type,
+ handle_level_irq);
ioasic_irq_base = base;
}
diff --git a/arch/mips/dec/kn02-irq.c b/arch/mips/dec/kn02-irq.c
index 04a367a60a57..5a9be4c93584 100644
--- a/arch/mips/dec/kn02-irq.c
+++ b/arch/mips/dec/kn02-irq.c
@@ -14,7 +14,6 @@
#include <linux/init.h>
#include <linux/irq.h>
-#include <linux/spinlock.h>
#include <linux/types.h>
#include <asm/dec/kn02.h>
@@ -29,7 +28,6 @@
* There is no default value -- it has to be initialized.
*/
u32 cached_kn02_csr;
-DEFINE_SPINLOCK(kn02_lock);
static int kn02_irq_base;
@@ -53,54 +51,24 @@ static inline void mask_kn02_irq(unsigned int irq)
*csr = cached_kn02_csr;
}
-static inline void enable_kn02_irq(unsigned int irq)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&kn02_lock, flags);
- unmask_kn02_irq(irq);
- spin_unlock_irqrestore(&kn02_lock, flags);
-}
-
-static inline void disable_kn02_irq(unsigned int irq)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&kn02_lock, flags);
- mask_kn02_irq(irq);
- spin_unlock_irqrestore(&kn02_lock, flags);
-}
-
-
-static unsigned int startup_kn02_irq(unsigned int irq)
-{
- enable_kn02_irq(irq);
- return 0;
-}
-
-#define shutdown_kn02_irq disable_kn02_irq
-
static void ack_kn02_irq(unsigned int irq)
{
- spin_lock(&kn02_lock);
mask_kn02_irq(irq);
- spin_unlock(&kn02_lock);
iob();
}
static void end_kn02_irq(unsigned int irq)
{
if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
- enable_kn02_irq(irq);
+ unmask_kn02_irq(irq);
}
static struct irq_chip kn02_irq_type = {
.typename = "KN02-CSR",
- .startup = startup_kn02_irq,
- .shutdown = shutdown_kn02_irq,
- .enable = enable_kn02_irq,
- .disable = disable_kn02_irq,
.ack = ack_kn02_irq,
+ .mask = mask_kn02_irq,
+ .mask_ack = ack_kn02_irq,
+ .unmask = unmask_kn02_irq,
.end = end_kn02_irq,
};
@@ -109,22 +77,15 @@ void __init init_kn02_irqs(int base)
{
volatile u32 *csr = (volatile u32 *)CKSEG1ADDR(KN02_SLOT_BASE +
KN02_CSR);
- unsigned long flags;
int i;
/* Mask interrupts. */
- spin_lock_irqsave(&kn02_lock, flags);
cached_kn02_csr &= ~KN02_CSR_IOINTEN;
*csr = cached_kn02_csr;
iob();
- spin_unlock_irqrestore(&kn02_lock, flags);
-
- for (i = base; i < base + KN02_IRQ_LINES; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = 0;
- irq_desc[i].depth = 1;
- irq_desc[i].chip = &kn02_irq_type;
- }
+
+ for (i = base; i < base + KN02_IRQ_LINES; i++)
+ set_irq_chip_and_handler(i, &kn02_irq_type, handle_level_irq);
kn02_irq_base = base;
}
diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c
index 6b7481e97bec..d34032ac492a 100644
--- a/arch/mips/dec/setup.c
+++ b/arch/mips/dec/setup.c
@@ -761,3 +761,9 @@ void __init arch_init_irq(void)
if (dec_interrupt[DEC_IRQ_HALT] >= 0)
setup_irq(dec_interrupt[DEC_IRQ_HALT], &haltirq);
}
+
+asmlinkage unsigned int dec_irq_dispatch(unsigned int irq)
+{
+ do_IRQ(irq);
+ return 0;
+}
diff --git a/arch/mips/dec/time.c b/arch/mips/dec/time.c
index 69e424e9ab6f..8b7e0c17ac35 100644
--- a/arch/mips/dec/time.c
+++ b/arch/mips/dec/time.c
@@ -151,7 +151,7 @@ static void dec_timer_ack(void)
CMOS_READ(RTC_REG_C); /* Ack the RTC interrupt. */
}
-static unsigned int dec_ioasic_hpt_read(void)
+static cycle_t dec_ioasic_hpt_read(void)
{
/*
* The free-running counter is 32-bit which is good for about
@@ -171,7 +171,7 @@ void __init dec_time_init(void)
if (!cpu_has_counter && IOASIC)
/* For pre-R4k systems we use the I/O ASIC's counter. */
- mips_hpt_read = dec_ioasic_hpt_read;
+ clocksource_mips.read = dec_ioasic_hpt_read;
/* Set up the rate of periodic DS1287 interrupts. */
CMOS_WRITE(RTC_REF_CLCK_32KHZ | (16 - __ffs(HZ)), RTC_REG_A);
diff --git a/arch/mips/emma2rh/common/irq_emma2rh.c b/arch/mips/emma2rh/common/irq_emma2rh.c
index 197ed4c2ba04..59b98299c896 100644
--- a/arch/mips/emma2rh/common/irq_emma2rh.c
+++ b/arch/mips/emma2rh/common/irq_emma2rh.c
@@ -56,22 +56,6 @@ static void emma2rh_irq_disable(unsigned int irq)
ll_emma2rh_irq_disable(irq - emma2rh_irq_base);
}
-static unsigned int emma2rh_irq_startup(unsigned int irq)
-{
- emma2rh_irq_enable(irq);
- return 0;
-}
-
-#define emma2rh_irq_shutdown emma2rh_irq_disable
-
-static void emma2rh_irq_ack(unsigned int irq)
-{
- /* disable interrupt - some handler will re-enable the irq
- * and if the interrupt is leveled, we will have infinite loop
- */
- ll_emma2rh_irq_disable(irq - emma2rh_irq_base);
-}
-
static void emma2rh_irq_end(unsigned int irq)
{
if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
@@ -80,25 +64,20 @@ static void emma2rh_irq_end(unsigned int irq)
struct irq_chip emma2rh_irq_controller = {
.typename = "emma2rh_irq",
- .startup = emma2rh_irq_startup,
- .shutdown = emma2rh_irq_shutdown,
- .enable = emma2rh_irq_enable,
- .disable = emma2rh_irq_disable,
- .ack = emma2rh_irq_ack,
+ .ack = emma2rh_irq_disable,
+ .mask = emma2rh_irq_disable,
+ .mask_ack = emma2rh_irq_disable,
+ .unmask = emma2rh_irq_enable,
.end = emma2rh_irq_end,
- .set_affinity = NULL /* no affinity stuff for UP */
};
void emma2rh_irq_init(u32 irq_base)
{
u32 i;
- for (i = irq_base; i < irq_base + NUM_EMMA2RH_IRQ; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = NULL;
- irq_desc[i].depth = 1;
- irq_desc[i].chip = &emma2rh_irq_controller;
- }
+ for (i = irq_base; i < irq_base + NUM_EMMA2RH_IRQ; i++)
+ set_irq_chip_and_handler(i, &emma2rh_irq_controller,
+ handle_level_irq);
emma2rh_irq_base = irq_base;
}
diff --git a/arch/mips/emma2rh/markeins/irq_markeins.c b/arch/mips/emma2rh/markeins/irq_markeins.c
index 0b36eb001e62..3ac4e405ecdc 100644
--- a/arch/mips/emma2rh/markeins/irq_markeins.c
+++ b/arch/mips/emma2rh/markeins/irq_markeins.c
@@ -48,19 +48,6 @@ static void emma2rh_sw_irq_disable(unsigned int irq)
ll_emma2rh_sw_irq_disable(irq - emma2rh_sw_irq_base);
}
-static unsigned int emma2rh_sw_irq_startup(unsigned int irq)
-{
- emma2rh_sw_irq_enable(irq);
- return 0;
-}
-
-#define emma2rh_sw_irq_shutdown emma2rh_sw_irq_disable
-
-static void emma2rh_sw_irq_ack(unsigned int irq)
-{
- ll_emma2rh_sw_irq_disable(irq - emma2rh_sw_irq_base);
-}
-
static void emma2rh_sw_irq_end(unsigned int irq)
{
if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
@@ -69,25 +56,20 @@ static void emma2rh_sw_irq_end(unsigned int irq)
struct irq_chip emma2rh_sw_irq_controller = {
.typename = "emma2rh_sw_irq",
- .startup = emma2rh_sw_irq_startup,
- .shutdown = emma2rh_sw_irq_shutdown,
- .enable = emma2rh_sw_irq_enable,
- .disable = emma2rh_sw_irq_disable,
- .ack = emma2rh_sw_irq_ack,
+ .ack = emma2rh_sw_irq_disable,
+ .mask = emma2rh_sw_irq_disable,
+ .mask_ack = emma2rh_sw_irq_disable,
+ .unmask = emma2rh_sw_irq_enable,
.end = emma2rh_sw_irq_end,
- .set_affinity = NULL,
};
void emma2rh_sw_irq_init(u32 irq_base)
{
u32 i;
- for (i = irq_base; i < irq_base + NUM_EMMA2RH_IRQ_SW; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = NULL;
- irq_desc[i].depth = 2;
- irq_desc[i].chip = &emma2rh_sw_irq_controller;
- }
+ for (i = irq_base; i < irq_base + NUM_EMMA2RH_IRQ_SW; i++)
+ set_irq_chip_and_handler(i, &emma2rh_sw_irq_controller,
+ handle_level_irq);
emma2rh_sw_irq_base = irq_base;
}
@@ -126,14 +108,6 @@ static void emma2rh_gpio_irq_disable(unsigned int irq)
ll_emma2rh_gpio_irq_disable(irq - emma2rh_gpio_irq_base);
}
-static unsigned int emma2rh_gpio_irq_startup(unsigned int irq)
-{
- emma2rh_gpio_irq_enable(irq);
- return 0;
-}
-
-#define emma2rh_gpio_irq_shutdown emma2rh_gpio_irq_disable
-
static void emma2rh_gpio_irq_ack(unsigned int irq)
{
irq -= emma2rh_gpio_irq_base;
@@ -149,25 +123,19 @@ static void emma2rh_gpio_irq_end(unsigned int irq)
struct irq_chip emma2rh_gpio_irq_controller = {
.typename = "emma2rh_gpio_irq",
- .startup = emma2rh_gpio_irq_startup,
- .shutdown = emma2rh_gpio_irq_shutdown,
- .enable = emma2rh_gpio_irq_enable,
- .disable = emma2rh_gpio_irq_disable,
.ack = emma2rh_gpio_irq_ack,
+ .mask = emma2rh_gpio_irq_disable,
+ .mask_ack = emma2rh_gpio_irq_ack,
+ .unmask = emma2rh_gpio_irq_enable,
.end = emma2rh_gpio_irq_end,
- .set_affinity = NULL,
};
void emma2rh_gpio_irq_init(u32 irq_base)
{
u32 i;
- for (i = irq_base; i < irq_base + NUM_EMMA2RH_IRQ_GPIO; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = NULL;
- irq_desc[i].depth = 2;
- irq_desc[i].chip = &emma2rh_gpio_irq_controller;
- }
+ for (i = irq_base; i < irq_base + NUM_EMMA2RH_IRQ_GPIO; i++)
+ set_irq_chip(i, &emma2rh_gpio_irq_controller);
emma2rh_gpio_irq_base = irq_base;
}
diff --git a/arch/mips/gt64120/ev64120/irq.c b/arch/mips/gt64120/ev64120/irq.c
index ed4d82b9a24a..b3e5796c81d7 100644
--- a/arch/mips/gt64120/ev64120/irq.c
+++ b/arch/mips/gt64120/ev64120/irq.c
@@ -66,38 +66,21 @@ asmlinkage void plat_irq_dispatch(void)
static void disable_ev64120_irq(unsigned int irq_nr)
{
- unsigned long flags;
-
- local_irq_save(flags);
if (irq_nr >= 8) { // All PCI interrupts are on line 5 or 2
clear_c0_status(9 << 10);
} else {
clear_c0_status(1 << (irq_nr + 8));
}
- local_irq_restore(flags);
}
static void enable_ev64120_irq(unsigned int irq_nr)
{
- unsigned long flags;
-
- local_irq_save(flags);
if (irq_nr >= 8) // All PCI interrupts are on line 5 or 2
set_c0_status(9 << 10);
else
set_c0_status(1 << (irq_nr + 8));
- local_irq_restore(flags);
-}
-
-static unsigned int startup_ev64120_irq(unsigned int irq)
-{
- enable_ev64120_irq(irq);
- return 0; /* Never anything pending */
}
-#define shutdown_ev64120_irq disable_ev64120_irq
-#define mask_and_ack_ev64120_irq disable_ev64120_irq
-
static void end_ev64120_irq(unsigned int irq)
{
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
@@ -106,13 +89,11 @@ static void end_ev64120_irq(unsigned int irq)
static struct irq_chip ev64120_irq_type = {
.typename = "EV64120",
- .startup = startup_ev64120_irq,
- .shutdown = shutdown_ev64120_irq,
- .enable = enable_ev64120_irq,
- .disable = disable_ev64120_irq,
- .ack = mask_and_ack_ev64120_irq,
+ .ack = disable_ev64120_irq,
+ .mask = disable_ev64120_irq,
+ .mask_ack = disable_ev64120_irq,
+ .unmask = enable_ev64120_irq,
.end = end_ev64120_irq,
- .set_affinity = NULL
};
void gt64120_irq_setup(void)
@@ -122,8 +103,6 @@ void gt64120_irq_setup(void)
*/
clear_c0_status(ST0_IM);
- local_irq_disable();
-
/*
* Enable timer. Other interrupts will be enabled as they are
* registered.
@@ -133,16 +112,5 @@ void gt64120_irq_setup(void)
void __init arch_init_irq(void)
{
- int i;
-
- /* Let's initialize our IRQ descriptors */
- for (i = 0; i < NR_IRQS; i++) {
- irq_desc[i].status = 0;
- irq_desc[i].chip = &no_irq_chip;
- irq_desc[i].action = NULL;
- irq_desc[i].depth = 0;
- spin_lock_init(&irq_desc[i].lock);
- }
-
gt64120_irq_setup();
}
diff --git a/arch/mips/jazz/irq.c b/arch/mips/jazz/irq.c
index d5bd6b3a0933..5c4f50cdf157 100644
--- a/arch/mips/jazz/irq.c
+++ b/arch/mips/jazz/irq.c
@@ -28,14 +28,6 @@ static void enable_r4030_irq(unsigned int irq)
spin_unlock_irqrestore(&r4030_lock, flags);
}
-static unsigned int startup_r4030_irq(unsigned int irq)
-{
- enable_r4030_irq(irq);
- return 0; /* never anything pending */
-}
-
-#define shutdown_r4030_irq disable_r4030_irq
-
void disable_r4030_irq(unsigned int irq)
{
unsigned int mask = ~(1 << (irq - JAZZ_PARALLEL_IRQ));
@@ -47,8 +39,6 @@ void disable_r4030_irq(unsigned int irq)
spin_unlock_irqrestore(&r4030_lock, flags);
}
-#define mask_and_ack_r4030_irq disable_r4030_irq
-
static void end_r4030_irq(unsigned int irq)
{
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
@@ -57,11 +47,10 @@ static void end_r4030_irq(unsigned int irq)
static struct irq_chip r4030_irq_type = {
.typename = "R4030",
- .startup = startup_r4030_irq,
- .shutdown = shutdown_r4030_irq,
- .enable = enable_r4030_irq,
- .disable = disable_r4030_irq,
- .ack = mask_and_ack_r4030_irq,
+ .ack = disable_r4030_irq,
+ .mask = disable_r4030_irq,
+ .mask_ack = disable_r4030_irq,
+ .unmask = enable_r4030_irq,
.end = end_r4030_irq,
};
@@ -69,12 +58,8 @@ void __init init_r4030_ints(void)
{
int i;
- for (i = JAZZ_PARALLEL_IRQ; i <= JAZZ_TIMER_IRQ; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = 0;
- irq_desc[i].depth = 1;
- irq_desc[i].chip = &r4030_irq_type;
- }
+ for (i = JAZZ_PARALLEL_IRQ; i <= JAZZ_TIMER_IRQ; i++)
+ set_irq_chip_and_handler(i, &r4030_irq_type, handle_level_irq);
r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, 0);
r4030_read_reg16(JAZZ_IO_IRQ_SOURCE); /* clear pending IRQs */
diff --git a/arch/mips/jmr3927/rbhma3100/irq.c b/arch/mips/jmr3927/rbhma3100/irq.c
index de4a238c28be..3da49c5aaf49 100644
--- a/arch/mips/jmr3927/rbhma3100/irq.c
+++ b/arch/mips/jmr3927/rbhma3100/irq.c
@@ -90,17 +90,6 @@ static unsigned char irc_level[TX3927_NUM_IR] = {
static void jmr3927_irq_disable(unsigned int irq_nr);
static void jmr3927_irq_enable(unsigned int irq_nr);
-static DEFINE_SPINLOCK(jmr3927_irq_lock);
-
-static unsigned int jmr3927_irq_startup(unsigned int irq)
-{
- jmr3927_irq_enable(irq);
-
- return 0;
-}
-
-#define jmr3927_irq_shutdown jmr3927_irq_disable
-
static void jmr3927_irq_ack(unsigned int irq)
{
if (irq == JMR3927_IRQ_IRC_TMR0)
@@ -118,9 +107,7 @@ static void jmr3927_irq_end(unsigned int irq)
static void jmr3927_irq_disable(unsigned int irq_nr)
{
struct tb_irq_space* sp;
- unsigned long flags;
- spin_lock_irqsave(&jmr3927_irq_lock, flags);
for (sp = tb_irq_spaces; sp; sp = sp->next) {
if (sp->start_irqno <= irq_nr &&
irq_nr < sp->start_irqno + sp->nr_irqs) {
@@ -130,15 +117,12 @@ static void jmr3927_irq_disable(unsigned int irq_nr)
break;
}
}
- spin_unlock_irqrestore(&jmr3927_irq_lock, flags);
}
static void jmr3927_irq_enable(unsigned int irq_nr)
{
struct tb_irq_space* sp;
- unsigned long flags;
- spin_lock_irqsave(&jmr3927_irq_lock, flags);
for (sp = tb_irq_spaces; sp; sp = sp->next) {
if (sp->start_irqno <= irq_nr &&
irq_nr < sp->start_irqno + sp->nr_irqs) {
@@ -148,7 +132,6 @@ static void jmr3927_irq_enable(unsigned int irq_nr)
break;
}
}
- spin_unlock_irqrestore(&jmr3927_irq_lock, flags);
}
/*
@@ -457,11 +440,10 @@ void __init arch_init_irq(void)
static struct irq_chip jmr3927_irq_controller = {
.typename = "jmr3927_irq",
- .startup = jmr3927_irq_startup,
- .shutdown = jmr3927_irq_shutdown,
- .enable = jmr3927_irq_enable,
- .disable = jmr3927_irq_disable,
.ack = jmr3927_irq_ack,
+ .mask = jmr3927_irq_disable,
+ .mask_ack = jmr3927_irq_ack,
+ .unmask = jmr3927_irq_enable,
.end = jmr3927_irq_end,
};
@@ -469,12 +451,8 @@ void jmr3927_irq_init(u32 irq_base)
{
u32 i;
- for (i= irq_base; i< irq_base + JMR3927_NR_IRQ_IRC + JMR3927_NR_IRQ_IOC; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = NULL;
- irq_desc[i].depth = 1;
- irq_desc[i].chip = &jmr3927_irq_controller;
- }
+ for (i= irq_base; i< irq_base + JMR3927_NR_IRQ_IRC + JMR3927_NR_IRQ_IOC; i++)
+ set_irq_chip(i, &jmr3927_irq_controller);
jmr3927_irq_base = irq_base;
}
diff --git a/arch/mips/jmr3927/rbhma3100/setup.c b/arch/mips/jmr3927/rbhma3100/setup.c
index 16e5dfe7aa8a..138f25efe38a 100644
--- a/arch/mips/jmr3927/rbhma3100/setup.c
+++ b/arch/mips/jmr3927/rbhma3100/setup.c
@@ -170,7 +170,7 @@ static void jmr3927_machine_power_off(void)
while (1);
}
-static unsigned int jmr3927_hpt_read(void)
+static cycle_t jmr3927_hpt_read(void)
{
/* We assume this function is called xtime_lock held. */
return jiffies * (JMR3927_TIMER_CLK / HZ) + jmr3927_tmrptr->trr;
@@ -182,7 +182,7 @@ extern void rtc_ds1742_init(unsigned long base);
#endif
static void __init jmr3927_time_init(void)
{
- mips_hpt_read = jmr3927_hpt_read;
+ clocksource_mips.read = jmr3927_hpt_read;
mips_hpt_frequency = JMR3927_TIMER_CLK;
#ifdef USE_RTC_DS1742
if (jmr3927_have_nvram()) {
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index cd9cec9e39e9..bbbb8d7cb89b 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -6,7 +6,7 @@ extra-y := head.o init_task.o vmlinux.lds
obj-y += cpu-probe.o branch.o entry.o genex.o irq.o process.o \
ptrace.o reset.o semaphore.o setup.o signal.o syscall.o \
- time.o traps.o unaligned.o
+ time.o topology.o traps.o unaligned.o
binfmt_irix-objs := irixelf.o irixinv.o irixioctl.o irixsig.o \
irix5sys.o sysirix.o
@@ -45,7 +45,6 @@ obj-$(CONFIG_MIPS_APSP_KSPD) += kspd.o
obj-$(CONFIG_MIPS_VPE_LOADER) += vpe.o
obj-$(CONFIG_MIPS_VPE_APSP_API) += rtlx.o
-obj-$(CONFIG_NO_ISA) += dma-no-isa.o
obj-$(CONFIG_I8259) += i8259.o
obj-$(CONFIG_IRQ_CPU) += irq_cpu.o
obj-$(CONFIG_IRQ_CPU_RM7K) += irq-rm7000.o
@@ -67,6 +66,8 @@ obj-$(CONFIG_64BIT) += cpu-bugs64.o
obj-$(CONFIG_I8253) += i8253.o
+obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
+
CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 8485af340ee1..442839e9578c 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -110,9 +110,8 @@ static inline void check_wait(void)
{
struct cpuinfo_mips *c = &current_cpu_data;
- printk("Checking for 'wait' instruction... ");
if (nowait) {
- printk (" disabled.\n");
+ printk("Wait instruction disabled.\n");
return;
}
@@ -120,11 +119,9 @@ static inline void check_wait(void)
case CPU_R3081:
case CPU_R3081E:
cpu_wait = r3081_wait;
- printk(" available.\n");
break;
case CPU_TX3927:
cpu_wait = r39xx_wait;
- printk(" available.\n");
break;
case CPU_R4200:
/* case CPU_R4300: */
@@ -146,33 +143,23 @@ static inline void check_wait(void)
case CPU_74K:
case CPU_PR4450:
cpu_wait = r4k_wait;
- printk(" available.\n");
break;
case CPU_TX49XX:
cpu_wait = r4k_wait_irqoff;
- printk(" available.\n");
break;
case CPU_AU1000:
case CPU_AU1100:
case CPU_AU1500:
case CPU_AU1550:
case CPU_AU1200:
- if (allow_au1k_wait) {
+ if (allow_au1k_wait)
cpu_wait = au1k_wait;
- printk(" available.\n");
- } else
- printk(" unavailable.\n");
break;
case CPU_RM9000:
- if ((c->processor_id & 0x00ff) >= 0x40) {
+ if ((c->processor_id & 0x00ff) >= 0x40)
cpu_wait = r4k_wait;
- printk(" available.\n");
- } else {
- printk(" unavailable.\n");
- }
break;
default:
- printk(" unavailable.\n");
break;
}
}
diff --git a/arch/mips/kernel/dma-no-isa.c b/arch/mips/kernel/dma-no-isa.c
deleted file mode 100644
index 6df8b07741e3..000000000000
--- a/arch/mips/kernel/dma-no-isa.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2004 by Ralf Baechle
- *
- * Dummy ISA DMA functions for systems that don't have ISA but share drivers
- * with ISA such as legacy free PCI.
- */
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-
-DEFINE_SPINLOCK(dma_spin_lock);
-
-int request_dma(unsigned int dmanr, const char * device_id)
-{
- return -EINVAL;
-}
-
-void free_dma(unsigned int dmanr)
-{
-}
-
-EXPORT_SYMBOL(dma_spin_lock);
-EXPORT_SYMBOL(request_dma);
-EXPORT_SYMBOL(free_dma);
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index 5baca16993d0..aacd4a005c5f 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -19,6 +19,7 @@
#include <asm/mipsregs.h>
#include <asm/stackframe.h>
#include <asm/war.h>
+#include <asm/page.h>
#define PANIC_PIC(msg) \
.set push; \
@@ -378,6 +379,68 @@ NESTED(nmi_handler, PT_SIZE, sp)
BUILD_HANDLER dsp dsp sti silent /* #26 */
BUILD_HANDLER reserved reserved sti verbose /* others */
+ .align 5
+ LEAF(handle_ri_rdhwr_vivt)
+#ifdef CONFIG_MIPS_MT_SMTC
+ PANIC_PIC("handle_ri_rdhwr_vivt called")
+#else
+ .set push
+ .set noat
+ .set noreorder
+ /* check if TLB contains a entry for EPC */
+ MFC0 k1, CP0_ENTRYHI
+ andi k1, 0xff /* ASID_MASK */
+ MFC0 k0, CP0_EPC
+ PTR_SRL k0, PAGE_SHIFT + 1
+ PTR_SLL k0, PAGE_SHIFT + 1
+ or k1, k0
+ MTC0 k1, CP0_ENTRYHI
+ mtc0_tlbw_hazard
+ tlbp
+ tlb_probe_hazard
+ mfc0 k1, CP0_INDEX
+ .set pop
+ bltz k1, handle_ri /* slow path */
+ /* fall thru */
+#endif
+ END(handle_ri_rdhwr_vivt)
+
+ LEAF(handle_ri_rdhwr)
+ .set push
+ .set noat
+ .set noreorder
+ /* 0x7c03e83b: rdhwr v1,$29 */
+ MFC0 k1, CP0_EPC
+ lui k0, 0x7c03
+ lw k1, (k1)
+ ori k0, 0xe83b
+ .set reorder
+ bne k0, k1, handle_ri /* if not ours */
+ /* The insn is rdhwr. No need to check CAUSE.BD here. */
+ get_saved_sp /* k1 := current_thread_info */
+ .set noreorder
+ MFC0 k0, CP0_EPC
+#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
+ ori k1, _THREAD_MASK
+ xori k1, _THREAD_MASK
+ LONG_L v1, TI_TP_VALUE(k1)
+ LONG_ADDIU k0, 4
+ jr k0
+ rfe
+#else
+ LONG_ADDIU k0, 4 /* stall on $k0 */
+ MTC0 k0, CP0_EPC
+ /* I hope three instructions between MTC0 and ERET are enough... */
+ ori k1, _THREAD_MASK
+ xori k1, _THREAD_MASK
+ LONG_L v1, TI_TP_VALUE(k1)
+ .set mips3
+ eret
+ .set mips0
+#endif
+ .set pop
+ END(handle_ri_rdhwr)
+
#ifdef CONFIG_64BIT
/* A temporary overflow handler used by check_daddi(). */
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index ddc1b71c9378..a2e095adaa3f 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -250,6 +250,9 @@ NESTED(smp_bootstrap, 16, sp)
*/
page swapper_pg_dir, _PGD_ORDER
#ifdef CONFIG_64BIT
+#if defined(CONFIG_MODULES) && !defined(CONFIG_BUILD_ELF64)
+ page module_pg_dir, _PGD_ORDER
+#endif
page invalid_pmd_table, _PMD_ORDER
#endif
page invalid_pte_table, _PTE_ORDER
diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c
index 48e3418c217b..2526c0ca4d81 100644
--- a/arch/mips/kernel/i8259.c
+++ b/arch/mips/kernel/i8259.c
@@ -40,21 +40,10 @@ static void end_8259A_irq (unsigned int irq)
enable_8259A_irq(irq);
}
-#define shutdown_8259A_irq disable_8259A_irq
-
void mask_and_ack_8259A(unsigned int);
-static unsigned int startup_8259A_irq(unsigned int irq)
-{
- enable_8259A_irq(irq);
-
- return 0; /* never anything pending */
-}
-
static struct irq_chip i8259A_irq_type = {
.typename = "XT-PIC",
- .startup = startup_8259A_irq,
- .shutdown = shutdown_8259A_irq,
.enable = enable_8259A_irq,
.disable = disable_8259A_irq,
.ack = mask_and_ack_8259A,
@@ -120,7 +109,7 @@ int i8259A_irq_pending(unsigned int irq)
void make_8259A_irq(unsigned int irq)
{
disable_irq_nosync(irq);
- irq_desc[irq].chip = &i8259A_irq_type;
+ set_irq_chip(irq, &i8259A_irq_type);
enable_irq(irq);
}
@@ -323,12 +312,8 @@ void __init init_i8259_irqs (void)
init_8259A(0);
- for (i = 0; i < 16; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = NULL;
- irq_desc[i].depth = 1;
- irq_desc[i].chip = &i8259A_irq_type;
- }
+ for (i = 0; i < 16; i++)
+ set_irq_chip(i, &i8259A_irq_type);
setup_irq(2, &irq2);
}
diff --git a/arch/mips/kernel/irq-msc01.c b/arch/mips/kernel/irq-msc01.c
index 650a80ca3741..bcaad6696082 100644
--- a/arch/mips/kernel/irq-msc01.c
+++ b/arch/mips/kernel/irq-msc01.c
@@ -45,31 +45,6 @@ static inline void unmask_msc_irq(unsigned int irq)
}
/*
- * Enables the IRQ on SOC-it
- */
-static void enable_msc_irq(unsigned int irq)
-{
- unmask_msc_irq(irq);
-}
-
-/*
- * Initialize the IRQ on SOC-it
- */
-static unsigned int startup_msc_irq(unsigned int irq)
-{
- unmask_msc_irq(irq);
- return 0;
-}
-
-/*
- * Disables the IRQ on SOC-it
- */
-static void disable_msc_irq(unsigned int irq)
-{
- mask_msc_irq(irq);
-}
-
-/*
* Masks and ACKs an IRQ
*/
static void level_mask_and_ack_msc_irq(unsigned int irq)
@@ -136,25 +111,23 @@ msc_bind_eic_interrupt (unsigned int irq, unsigned int set)
(irq<<MSC01_IC_RAMW_ADDR_SHF) | (set<<MSC01_IC_RAMW_DATA_SHF));
}
-#define shutdown_msc_irq disable_msc_irq
-
struct irq_chip msc_levelirq_type = {
.typename = "SOC-it-Level",
- .startup = startup_msc_irq,
- .shutdown = shutdown_msc_irq,
- .enable = enable_msc_irq,
- .disable = disable_msc_irq,
.ack = level_mask_and_ack_msc_irq,
+ .mask = mask_msc_irq,
+ .mask_ack = level_mask_and_ack_msc_irq,
+ .unmask = unmask_msc_irq,
+ .eoi = unmask_msc_irq,
.end = end_msc_irq,
};
struct irq_chip msc_edgeirq_type = {
.typename = "SOC-it-Edge",
- .startup =startup_msc_irq,
- .shutdown = shutdown_msc_irq,
- .enable = enable_msc_irq,
- .disable = disable_msc_irq,
.ack = edge_mask_and_ack_msc_irq,
+ .mask = mask_msc_irq,
+ .mask_ack = edge_mask_and_ack_msc_irq,
+ .unmask = unmask_msc_irq,
+ .eoi = unmask_msc_irq,
.end = end_msc_irq,
};
@@ -175,14 +148,14 @@ void __init init_msc_irqs(unsigned int base, msc_irqmap_t *imp, int nirq)
switch (imp->im_type) {
case MSC01_IRQ_EDGE:
- irq_desc[base+n].chip = &msc_edgeirq_type;
+ set_irq_chip(base+n, &msc_edgeirq_type);
if (cpu_has_veic)
MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT);
else
MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT | imp->im_lvl);
break;
case MSC01_IRQ_LEVEL:
- irq_desc[base+n].chip = &msc_levelirq_type;
+ set_irq_chip(base+n, &msc_levelirq_type);
if (cpu_has_veic)
MSCIC_WRITE(MSC01_IC_SUP+n*8, 0);
else
diff --git a/arch/mips/kernel/irq-mv6434x.c b/arch/mips/kernel/irq-mv6434x.c
index 37d106202b83..6cfb31cafde2 100644
--- a/arch/mips/kernel/irq-mv6434x.c
+++ b/arch/mips/kernel/irq-mv6434x.c
@@ -67,39 +67,6 @@ static inline void unmask_mv64340_irq(unsigned int irq)
}
/*
- * Enables the IRQ on Marvell Chip
- */
-static void enable_mv64340_irq(unsigned int irq)
-{
- unmask_mv64340_irq(irq);
-}
-
-/*
- * Initialize the IRQ on Marvell Chip
- */
-static unsigned int startup_mv64340_irq(unsigned int irq)
-{
- unmask_mv64340_irq(irq);
- return 0;
-}
-
-/*
- * Disables the IRQ on Marvell Chip
- */
-static void disable_mv64340_irq(unsigned int irq)
-{
- mask_mv64340_irq(irq);
-}
-
-/*
- * Masks and ACKs an IRQ
- */
-static void mask_and_ack_mv64340_irq(unsigned int irq)
-{
- mask_mv64340_irq(irq);
-}
-
-/*
* End IRQ processing
*/
static void end_mv64340_irq(unsigned int irq)
@@ -133,15 +100,12 @@ void ll_mv64340_irq(void)
do_IRQ(ls1bit32(irq_src_high) + irq_base + 32);
}
-#define shutdown_mv64340_irq disable_mv64340_irq
-
struct irq_chip mv64340_irq_type = {
.typename = "MV-64340",
- .startup = startup_mv64340_irq,
- .shutdown = shutdown_mv64340_irq,
- .enable = enable_mv64340_irq,
- .disable = disable_mv64340_irq,
- .ack = mask_and_ack_mv64340_irq,
+ .ack = mask_mv64340_irq,
+ .mask = mask_mv64340_irq,
+ .mask_ack = mask_mv64340_irq,
+ .unmask = unmask_mv64340_irq,
.end = end_mv64340_irq,
};
@@ -149,13 +113,9 @@ void __init mv64340_irq_init(unsigned int base)
{
int i;
- /* Reset irq handlers pointers to NULL */
- for (i = base; i < base + 64; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = 0;
- irq_desc[i].depth = 2;
- irq_desc[i].chip = &mv64340_irq_type;
- }
+ for (i = base; i < base + 64; i++)
+ set_irq_chip_and_handler(i, &mv64340_irq_type,
+ handle_level_irq);
irq_base = base;
}
diff --git a/arch/mips/kernel/irq-rm7000.c b/arch/mips/kernel/irq-rm7000.c
index 6b54c7109e2e..ddcc2a5f8a06 100644
--- a/arch/mips/kernel/irq-rm7000.c
+++ b/arch/mips/kernel/irq-rm7000.c
@@ -29,42 +29,6 @@ static inline void mask_rm7k_irq(unsigned int irq)
clear_c0_intcontrol(0x100 << (irq - irq_base));
}
-static inline void rm7k_cpu_irq_enable(unsigned int irq)
-{
- unsigned long flags;
-
- local_irq_save(flags);
- unmask_rm7k_irq(irq);
- local_irq_restore(flags);
-}
-
-static void rm7k_cpu_irq_disable(unsigned int irq)
-{
- unsigned long flags;
-
- local_irq_save(flags);
- mask_rm7k_irq(irq);
- local_irq_restore(flags);
-}
-
-static unsigned int rm7k_cpu_irq_startup(unsigned int irq)
-{
- rm7k_cpu_irq_enable(irq);
-
- return 0;
-}
-
-#define rm7k_cpu_irq_shutdown rm7k_cpu_irq_disable
-
-/*
- * While we ack the interrupt interrupts are disabled and thus we don't need
- * to deal with concurrency issues. Same for rm7k_cpu_irq_end.
- */
-static void rm7k_cpu_irq_ack(unsigned int irq)
-{
- mask_rm7k_irq(irq);
-}
-
static void rm7k_cpu_irq_end(unsigned int irq)
{
if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
@@ -73,11 +37,10 @@ static void rm7k_cpu_irq_end(unsigned int irq)
static struct irq_chip rm7k_irq_controller = {
.typename = "RM7000",
- .startup = rm7k_cpu_irq_startup,
- .shutdown = rm7k_cpu_irq_shutdown,
- .enable = rm7k_cpu_irq_enable,
- .disable = rm7k_cpu_irq_disable,
- .ack = rm7k_cpu_irq_ack,
+ .ack = mask_rm7k_irq,
+ .mask = mask_rm7k_irq,
+ .mask_ack = mask_rm7k_irq,
+ .unmask = unmask_rm7k_irq,
.end = rm7k_cpu_irq_end,
};
@@ -87,12 +50,9 @@ void __init rm7k_cpu_irq_init(int base)
clear_c0_intcontrol(0x00000f00); /* Mask all */
- for (i = base; i < base + 4; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = NULL;
- irq_desc[i].depth = 1;
- irq_desc[i].chip = &rm7k_irq_controller;
- }
+ for (i = base; i < base + 4; i++)
+ set_irq_chip_and_handler(i, &rm7k_irq_controller,
+ handle_level_irq);
irq_base = base;
}
diff --git a/arch/mips/kernel/irq-rm9000.c b/arch/mips/kernel/irq-rm9000.c
index 62f011ba97a2..ba6440c88abd 100644
--- a/arch/mips/kernel/irq-rm9000.c
+++ b/arch/mips/kernel/irq-rm9000.c
@@ -48,15 +48,6 @@ static void rm9k_cpu_irq_disable(unsigned int irq)
local_irq_restore(flags);
}
-static unsigned int rm9k_cpu_irq_startup(unsigned int irq)
-{
- rm9k_cpu_irq_enable(irq);
-
- return 0;
-}
-
-#define rm9k_cpu_irq_shutdown rm9k_cpu_irq_disable
-
/*
* Performance counter interrupts are global on all processors.
*/
@@ -89,16 +80,6 @@ static void rm9k_perfcounter_irq_shutdown(unsigned int irq)
on_each_cpu(local_rm9k_perfcounter_irq_shutdown, (void *) irq, 0, 1);
}
-
-/*
- * While we ack the interrupt interrupts are disabled and thus we don't need
- * to deal with concurrency issues. Same for rm9k_cpu_irq_end.
- */
-static void rm9k_cpu_irq_ack(unsigned int irq)
-{
- mask_rm9k_irq(irq);
-}
-
static void rm9k_cpu_irq_end(unsigned int irq)
{
if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
@@ -107,11 +88,10 @@ static void rm9k_cpu_irq_end(unsigned int irq)
static struct irq_chip rm9k_irq_controller = {
.typename = "RM9000",
- .startup = rm9k_cpu_irq_startup,
- .shutdown = rm9k_cpu_irq_shutdown,
- .enable = rm9k_cpu_irq_enable,
- .disable = rm9k_cpu_irq_disable,
- .ack = rm9k_cpu_irq_ack,
+ .ack = mask_rm9k_irq,
+ .mask = mask_rm9k_irq,
+ .mask_ack = mask_rm9k_irq,
+ .unmask = unmask_rm9k_irq,
.end = rm9k_cpu_irq_end,
};
@@ -119,9 +99,10 @@ static struct irq_chip rm9k_perfcounter_irq = {
.typename = "RM9000",
.startup = rm9k_perfcounter_irq_startup,
.shutdown = rm9k_perfcounter_irq_shutdown,
- .enable = rm9k_cpu_irq_enable,
- .disable = rm9k_cpu_irq_disable,
- .ack = rm9k_cpu_irq_ack,
+ .ack = mask_rm9k_irq,
+ .mask = mask_rm9k_irq,
+ .mask_ack = mask_rm9k_irq,
+ .unmask = unmask_rm9k_irq,
.end = rm9k_cpu_irq_end,
};
@@ -135,15 +116,13 @@ void __init rm9k_cpu_irq_init(int base)
clear_c0_intcontrol(0x0000f000); /* Mask all */
- for (i = base; i < base + 4; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = NULL;
- irq_desc[i].depth = 1;
- irq_desc[i].chip = &rm9k_irq_controller;
- }
+ for (i = base; i < base + 4; i++)
+ set_irq_chip_and_handler(i, &rm9k_irq_controller,
+ handle_level_irq);
rm9000_perfcount_irq = base + 1;
- irq_desc[rm9000_perfcount_irq].chip = &rm9k_perfcounter_irq;
+ set_irq_chip_and_handler(rm9000_perfcount_irq, &rm9k_perfcounter_irq,
+ handle_level_irq);
irq_base = base;
}
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
index 9b0e49d63d7b..b339798b3172 100644
--- a/arch/mips/kernel/irq.c
+++ b/arch/mips/kernel/irq.c
@@ -88,25 +88,6 @@ atomic_t irq_err_count;
unsigned long irq_hwmask[NR_IRQS];
#endif /* CONFIG_MIPS_MT_SMTC */
-#undef do_IRQ
-
-/*
- * do_IRQ handles all normal device IRQ's (the special
- * SMP cross-CPU interrupts have their own specific
- * handlers).
- */
-asmlinkage unsigned int do_IRQ(unsigned int irq)
-{
- irq_enter();
-
- __DO_IRQ_SMTC_HOOK();
- __do_IRQ(irq);
-
- irq_exit();
-
- return 1;
-}
-
/*
* Generic, controller-independent functions:
*/
@@ -172,19 +153,6 @@ __setup("nokgdb", nokgdb);
void __init init_IRQ(void)
{
- int i;
-
- for (i = 0; i < NR_IRQS; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = NULL;
- irq_desc[i].depth = 1;
- irq_desc[i].chip = &no_irq_chip;
- spin_lock_init(&irq_desc[i].lock);
-#ifdef CONFIG_MIPS_MT_SMTC
- irq_hwmask[i] = 0;
-#endif /* CONFIG_MIPS_MT_SMTC */
- }
-
arch_init_irq();
#ifdef CONFIG_KGDB
diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c
index 9bb21c7f2149..be5ac23d3812 100644
--- a/arch/mips/kernel/irq_cpu.c
+++ b/arch/mips/kernel/irq_cpu.c
@@ -50,44 +50,6 @@ static inline void mask_mips_irq(unsigned int irq)
irq_disable_hazard();
}
-static inline void mips_cpu_irq_enable(unsigned int irq)
-{
- unsigned long flags;
-
- local_irq_save(flags);
- unmask_mips_irq(irq);
- back_to_back_c0_hazard();
- local_irq_restore(flags);
-}
-
-static void mips_cpu_irq_disable(unsigned int irq)
-{
- unsigned long flags;
-
- local_irq_save(flags);
- mask_mips_irq(irq);
- back_to_back_c0_hazard();
- local_irq_restore(flags);
-}
-
-static unsigned int mips_cpu_irq_startup(unsigned int irq)
-{
- mips_cpu_irq_enable(irq);
-
- return 0;
-}
-
-#define mips_cpu_irq_shutdown mips_cpu_irq_disable
-
-/*
- * While we ack the interrupt interrupts are disabled and thus we don't need
- * to deal with concurrency issues. Same for mips_cpu_irq_end.
- */
-static void mips_cpu_irq_ack(unsigned int irq)
-{
- mask_mips_irq(irq);
-}
-
static void mips_cpu_irq_end(unsigned int irq)
{
if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
@@ -96,11 +58,11 @@ static void mips_cpu_irq_end(unsigned int irq)
static struct irq_chip mips_cpu_irq_controller = {
.typename = "MIPS",
- .startup = mips_cpu_irq_startup,
- .shutdown = mips_cpu_irq_shutdown,
- .enable = mips_cpu_irq_enable,
- .disable = mips_cpu_irq_disable,
- .ack = mips_cpu_irq_ack,
+ .ack = mask_mips_irq,
+ .mask = mask_mips_irq,
+ .mask_ack = mask_mips_irq,
+ .unmask = unmask_mips_irq,
+ .eoi = unmask_mips_irq,
.end = mips_cpu_irq_end,
};
@@ -110,8 +72,6 @@ static struct irq_chip mips_cpu_irq_controller = {
#define unmask_mips_mt_irq unmask_mips_irq
#define mask_mips_mt_irq mask_mips_irq
-#define mips_mt_cpu_irq_enable mips_cpu_irq_enable
-#define mips_mt_cpu_irq_disable mips_cpu_irq_disable
static unsigned int mips_mt_cpu_irq_startup(unsigned int irq)
{
@@ -119,13 +79,11 @@ static unsigned int mips_mt_cpu_irq_startup(unsigned int irq)
clear_c0_cause(0x100 << (irq - mips_cpu_irq_base));
evpe(vpflags);
- mips_mt_cpu_irq_enable(irq);
+ unmask_mips_mt_irq(irq);
return 0;
}
-#define mips_mt_cpu_irq_shutdown mips_mt_cpu_irq_disable
-
/*
* While we ack the interrupt interrupts are disabled and thus we don't need
* to deal with concurrency issues. Same for mips_cpu_irq_end.
@@ -143,10 +101,11 @@ static void mips_mt_cpu_irq_ack(unsigned int irq)
static struct irq_chip mips_mt_cpu_irq_controller = {
.typename = "MIPS",
.startup = mips_mt_cpu_irq_startup,
- .shutdown = mips_mt_cpu_irq_shutdown,
- .enable = mips_mt_cpu_irq_enable,
- .disable = mips_mt_cpu_irq_disable,
.ack = mips_mt_cpu_irq_ack,
+ .mask = mask_mips_mt_irq,
+ .mask_ack = mips_mt_cpu_irq_ack,
+ .unmask = unmask_mips_mt_irq,
+ .eoi = unmask_mips_mt_irq,
.end = mips_mt_cpu_irq_end,
};
@@ -163,19 +122,12 @@ void __init mips_cpu_irq_init(int irq_base)
* leave them uninitialized for other processors.
*/
if (cpu_has_mipsmt)
- for (i = irq_base; i < irq_base + 2; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = NULL;
- irq_desc[i].depth = 1;
- irq_desc[i].chip = &mips_mt_cpu_irq_controller;
- }
-
- for (i = irq_base + 2; i < irq_base + 8; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = NULL;
- irq_desc[i].depth = 1;
- irq_desc[i].chip = &mips_cpu_irq_controller;
- }
+ for (i = irq_base; i < irq_base + 2; i++)
+ set_irq_chip(i, &mips_mt_cpu_irq_controller);
+
+ for (i = irq_base + 2; i < irq_base + 8; i++)
+ set_irq_chip_and_handler(i, &mips_cpu_irq_controller,
+ handle_level_irq);
mips_cpu_irq_base = irq_base;
}
diff --git a/arch/mips/kernel/machine_kexec.c b/arch/mips/kernel/machine_kexec.c
new file mode 100644
index 000000000000..e0ad754c7edd
--- /dev/null
+++ b/arch/mips/kernel/machine_kexec.c
@@ -0,0 +1,85 @@
+/*
+ * machine_kexec.c for kexec
+ * Created by <nschichan@corp.free.fr> on Thu Oct 12 15:15:06 2006
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <linux/kexec.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+
+#include <asm/cacheflush.h>
+#include <asm/page.h>
+
+const extern unsigned char relocate_new_kernel[];
+const extern unsigned int relocate_new_kernel_size;
+
+extern unsigned long kexec_start_address;
+extern unsigned long kexec_indirection_page;
+
+int
+machine_kexec_prepare(struct kimage *kimage)
+{
+ return 0;
+}
+
+void
+machine_kexec_cleanup(struct kimage *kimage)
+{
+}
+
+void
+machine_shutdown(void)
+{
+}
+
+void
+machine_crash_shutdown(struct pt_regs *regs)
+{
+}
+
+void
+machine_kexec(struct kimage *image)
+{
+ unsigned long reboot_code_buffer;
+ unsigned long entry;
+ unsigned long *ptr;
+
+ reboot_code_buffer =
+ (unsigned long)page_address(image->control_code_page);
+
+ kexec_start_address = image->start;
+ kexec_indirection_page = phys_to_virt(image->head & PAGE_MASK);
+
+ memcpy((void*)reboot_code_buffer, relocate_new_kernel,
+ relocate_new_kernel_size);
+
+ /*
+ * The generic kexec code builds a page list with physical
+ * addresses. they are directly accessible through KSEG0 (or
+ * CKSEG0 or XPHYS if on 64bit system), hence the
+ * pys_to_virt() call.
+ */
+ for (ptr = &image->head; (entry = *ptr) && !(entry &IND_DONE);
+ ptr = (entry & IND_INDIRECTION) ?
+ phys_to_virt(entry & PAGE_MASK) : ptr + 1) {
+ if (*ptr & IND_SOURCE || *ptr & IND_INDIRECTION ||
+ *ptr & IND_DESTINATION)
+ *ptr = phys_to_virt(*ptr);
+ }
+
+ /*
+ * we do not want to be bothered.
+ */
+ local_irq_disable();
+
+ flush_icache_range(reboot_code_buffer,
+ reboot_code_buffer + KEXEC_CONTROL_CODE_SIZE);
+
+ printk("Will call new kernel at %08x\n", image->start);
+ printk("Bye ...\n");
+ flush_cache_all();
+ ((void (*)(void))reboot_code_buffer)();
+}
diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c
index d7bf0215bc1d..cb0801437b66 100644
--- a/arch/mips/kernel/module.c
+++ b/arch/mips/kernel/module.c
@@ -29,6 +29,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/spinlock.h>
+#include <asm/pgtable.h> /* MODULE_START */
struct mips_hi16 {
struct mips_hi16 *next;
@@ -43,9 +44,23 @@ static DEFINE_SPINLOCK(dbe_lock);
void *module_alloc(unsigned long size)
{
+#ifdef MODULE_START
+ struct vm_struct *area;
+
+ size = PAGE_ALIGN(size);
+ if (!size)
+ return NULL;
+
+ area = __get_vm_area(size, VM_ALLOC, MODULE_START, MODULE_END);
+ if (!area)
+ return NULL;
+
+ return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL);
+#else
if (size == 0)
return NULL;
return vmalloc(size);
+#endif
}
/* Free memory returned from module_alloc */
diff --git a/arch/mips/kernel/relocate_kernel.S b/arch/mips/kernel/relocate_kernel.S
new file mode 100644
index 000000000000..a3f0d00c1334
--- /dev/null
+++ b/arch/mips/kernel/relocate_kernel.S
@@ -0,0 +1,80 @@
+/*
+ * relocate_kernel.S for kexec
+ * Created by <nschichan@corp.free.fr> on Thu Oct 12 17:49:57 2006
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <asm/asm.h>
+#include <asm/asmmacro.h>
+#include <asm/regdef.h>
+#include <asm/page.h>
+#include <asm/mipsregs.h>
+#include <asm/stackframe.h>
+#include <asm/addrspace.h>
+
+ .globl relocate_new_kernel
+relocate_new_kernel:
+
+ PTR_L s0, kexec_indirection_page
+ PTR_L s1, kexec_start_address
+
+process_entry:
+ PTR_L s2, (s0)
+ PTR_ADD s0, s0, SZREG
+
+ /* destination page */
+ and s3, s2, 0x1
+ beq s3, zero, 1f
+ and s4, s2, ~0x1 /* store destination addr in s4 */
+ move a0, s4
+ b process_entry
+
+1:
+ /* indirection page, update s0 */
+ and s3, s2, 0x2
+ beq s3, zero, 1f
+ and s0, s2, ~0x2
+ b process_entry
+
+1:
+ /* done page */
+ and s3, s2, 0x4
+ beq s3, zero, 1f
+ b done
+1:
+ /* source page */
+ and s3, s2, 0x8
+ beq s3, zero, process_entry
+ and s2, s2, ~0x8
+ li s6, (1 << PAGE_SHIFT) / SZREG
+
+copy_word:
+ /* copy page word by word */
+ REG_L s5, (s2)
+ REG_S s5, (s4)
+ INT_ADD s4, s4, SZREG
+ INT_ADD s2, s2, SZREG
+ INT_SUB s6, s6, 1
+ beq s6, zero, process_entry
+ b copy_word
+ b process_entry
+
+done:
+ /* jump to kexec_start_address */
+ j s1
+
+ .globl kexec_start_address
+kexec_start_address:
+ .long 0x0
+
+ .globl kexec_indirection_page
+kexec_indirection_page:
+ .long 0x0
+
+relocate_new_kernel_end:
+
+ .globl relocate_new_kernel_size
+relocate_new_kernel_size:
+ .long relocate_new_kernel_end - relocate_new_kernel
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index a95f37de080e..7c0b3936ba44 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -653,7 +653,7 @@ einval: li v0, -EINVAL
sys sys_move_pages 6
sys sys_set_robust_list 2
sys sys_get_robust_list 3 /* 4310 */
- sys sys_ni_syscall 0
+ sys sys_kexec_load 4
sys sys_getcpu 3
sys sys_epoll_pwait 6
.endm
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index 8fb0f60f657b..e569b846e9a3 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -468,6 +468,6 @@ sys_call_table:
PTR sys_move_pages
PTR sys_set_robust_list
PTR sys_get_robust_list
- PTR sys_ni_syscall /* 5270 */
+ PTR sys_kexec_load /* 5270 */
PTR sys_getcpu
PTR sys_epoll_pwait
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 0da5ca2040ff..5b18f265d75b 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -394,6 +394,6 @@ EXPORT(sysn32_call_table)
PTR sys_move_pages
PTR compat_sys_set_robust_list
PTR compat_sys_get_robust_list
- PTR sys_ni_syscall
+ PTR compat_sys_kexec_load
PTR sys_getcpu
PTR sys_epoll_pwait
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index b9d00cae8b5f..e91379c1be1d 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -516,7 +516,7 @@ sys_call_table:
PTR compat_sys_move_pages
PTR compat_sys_set_robust_list
PTR compat_sys_get_robust_list /* 4310 */
- PTR sys_ni_syscall
+ PTR compat_sys_kexec_load
PTR sys_getcpu
PTR sys_epoll_pwait
.size sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 8f6e89697ccf..89440a0d8528 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -145,13 +145,12 @@ static int __init rd_start_early(char *p)
unsigned long start = memparse(p, &p);
#ifdef CONFIG_64BIT
- /* HACK: Guess if the sign extension was forgotten */
- if (start > 0x0000000080000000 && start < 0x00000000ffffffff)
- start |= 0xffffffff00000000UL;
+ /* Guess if the sign extension was forgotten by bootloader */
+ if (start < XKPHYS)
+ start = (int)start;
#endif
initrd_start = start;
initrd_end += start;
-
return 0;
}
early_param("rd_start", rd_start_early);
@@ -159,41 +158,64 @@ early_param("rd_start", rd_start_early);
static int __init rd_size_early(char *p)
{
initrd_end += memparse(p, &p);
-
return 0;
}
early_param("rd_size", rd_size_early);
+/* it returns the next free pfn after initrd */
static unsigned long __init init_initrd(void)
{
- unsigned long tmp, end, size;
+ unsigned long end;
u32 *initrd_header;
- ROOT_DEV = Root_RAM0;
-
/*
* Board specific code or command line parser should have
* already set up initrd_start and initrd_end. In these cases
* perfom sanity checks and use them if all looks good.
*/
- size = initrd_end - initrd_start;
- if (initrd_end == 0 || size == 0) {
- initrd_start = 0;
- initrd_end = 0;
- } else
- return initrd_end;
-
- end = (unsigned long)&_end;
- tmp = PAGE_ALIGN(end) - sizeof(u32) * 2;
- if (tmp < end)
- tmp += PAGE_SIZE;
-
- initrd_header = (u32 *)tmp;
- if (initrd_header[0] == 0x494E5244) {
- initrd_start = (unsigned long)&initrd_header[2];
- initrd_end = initrd_start + initrd_header[1];
+ if (initrd_start && initrd_end > initrd_start)
+ goto sanitize;
+
+ /*
+ * See if initrd has been added to the kernel image by
+ * arch/mips/boot/addinitrd.c. In that case a header is
+ * prepended to initrd and is made up by 8 bytes. The fisrt
+ * word is a magic number and the second one is the size of
+ * initrd. Initrd start must be page aligned in any cases.
+ */
+ initrd_header = __va(PAGE_ALIGN(__pa_symbol(&_end) + 8)) - 8;
+ if (initrd_header[0] != 0x494E5244)
+ goto disable;
+ initrd_start = (unsigned long)(initrd_header + 2);
+ initrd_end = initrd_start + initrd_header[1];
+
+sanitize:
+ if (initrd_start & ~PAGE_MASK) {
+ printk(KERN_ERR "initrd start must be page aligned\n");
+ goto disable;
}
- return initrd_end;
+ if (initrd_start < PAGE_OFFSET) {
+ printk(KERN_ERR "initrd start < PAGE_OFFSET\n");
+ goto disable;
+ }
+
+ /*
+ * Sanitize initrd addresses. For example firmware
+ * can't guess if they need to pass them through
+ * 64-bits values if the kernel has been built in pure
+ * 32-bit. We need also to switch from KSEG0 to XKPHYS
+ * addresses now, so the code can now safely use __pa().
+ */
+ end = __pa(initrd_end);
+ initrd_end = (unsigned long)__va(end);
+ initrd_start = (unsigned long)__va(__pa(initrd_start));
+
+ ROOT_DEV = Root_RAM0;
+ return PFN_UP(end);
+disable:
+ initrd_start = 0;
+ initrd_end = 0;
+ return 0;
}
static void __init finalize_initrd(void)
@@ -204,12 +226,12 @@ static void __init finalize_initrd(void)
printk(KERN_INFO "Initrd not found or empty");
goto disable;
}
- if (CPHYSADDR(initrd_end) > PFN_PHYS(max_low_pfn)) {
+ if (__pa(initrd_end) > PFN_PHYS(max_low_pfn)) {
printk("Initrd extends beyond end of memory");
goto disable;
}
- reserve_bootmem(CPHYSADDR(initrd_start), size);
+ reserve_bootmem(__pa(initrd_start), size);
initrd_below_start_ok = 1;
printk(KERN_INFO "Initial ramdisk at: 0x%lx (%lu bytes)\n",
@@ -259,8 +281,7 @@ static void __init bootmem_init(void)
* not selected. Once that done we can determine the low bound
* of usable memory.
*/
- reserved_end = init_initrd();
- reserved_end = PFN_UP(CPHYSADDR(max(reserved_end, (unsigned long)&_end)));
+ reserved_end = max(init_initrd(), PFN_UP(__pa_symbol(&_end)));
/*
* Find the highest page frame number we have available.
@@ -432,10 +453,10 @@ static void __init resource_init(void)
if (UNCAC_BASE != IO_BASE)
return;
- code_resource.start = virt_to_phys(&_text);
- code_resource.end = virt_to_phys(&_etext) - 1;
- data_resource.start = virt_to_phys(&_etext);
- data_resource.end = virt_to_phys(&_edata) - 1;
+ code_resource.start = __pa_symbol(&_text);
+ code_resource.end = __pa_symbol(&_etext) - 1;
+ data_resource.start = __pa_symbol(&_etext);
+ data_resource.end = __pa_symbol(&_edata) - 1;
/*
* Request address space for all standard RAM.
diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c
index 477c5334ec1b..a67c18555ed3 100644
--- a/arch/mips/kernel/signal_n32.c
+++ b/arch/mips/kernel/signal_n32.c
@@ -17,7 +17,6 @@
*/
#include <linux/cache.h>
#include <linux/sched.h>
-#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c
index 2ac19a6cbf68..1ee689c0e0c9 100644
--- a/arch/mips/kernel/smp-mt.c
+++ b/arch/mips/kernel/smp-mt.c
@@ -278,7 +278,9 @@ void __init plat_prepare_cpus(unsigned int max_cpus)
/* need to mark IPI's as IRQ_PER_CPU */
irq_desc[cpu_ipi_resched_irq].status |= IRQ_PER_CPU;
+ set_irq_handler(cpu_ipi_resched_irq, handle_percpu_irq);
irq_desc[cpu_ipi_call_irq].status |= IRQ_PER_CPU;
+ set_irq_handler(cpu_ipi_call_irq, handle_percpu_irq);
}
/*
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index db80957ada89..49db516789e0 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -463,28 +463,5 @@ void flush_tlb_one(unsigned long vaddr)
smp_on_each_tlb(flush_tlb_one_ipi, (void *) vaddr);
}
-static DEFINE_PER_CPU(struct cpu, cpu_devices);
-
-static int __init topology_init(void)
-{
- int i, ret;
-
-#ifdef CONFIG_NUMA
- for_each_online_node(i)
- register_one_node(i);
-#endif /* CONFIG_NUMA */
-
- for_each_present_cpu(i) {
- ret = register_cpu(&per_cpu(cpu_devices, i), i);
- if (ret)
- printk(KERN_WARNING "topology_init: register_cpu %d "
- "failed (%d)\n", i, ret);
- }
-
- return 0;
-}
-
-subsys_initcall(topology_init);
-
EXPORT_SYMBOL(flush_tlb_page);
EXPORT_SYMBOL(flush_tlb_one);
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
index 3b78caf112f5..802febed7df5 100644
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
@@ -1009,6 +1009,7 @@ void setup_cross_vpe_interrupts(void)
setup_irq_smtc(cpu_ipi_irq, &irq_ipi, (0x100 << MIPS_CPU_IPI_IRQ));
irq_desc[cpu_ipi_irq].status |= IRQ_PER_CPU;
+ set_irq_handler(cpu_ipi_irq, handle_percpu_irq);
}
/*
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index e535f86efa2f..11aab6d6bfe5 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -11,7 +11,6 @@
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
-#include <linux/clocksource.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -83,17 +82,11 @@ static void null_timer_ack(void) { /* nothing */ }
/*
* Null high precision timer functions for systems lacking one.
*/
-static unsigned int null_hpt_read(void)
+static cycle_t null_hpt_read(void)
{
return 0;
}
-static void __init null_hpt_init(void)
-{
- /* nothing */
-}
-
-
/*
* Timer ack for an R4k-compatible timer of a known frequency.
*/
@@ -118,7 +111,7 @@ static void c0_timer_ack(void)
/*
* High precision timer functions for a R4k-compatible timer.
*/
-static unsigned int c0_hpt_read(void)
+static cycle_t c0_hpt_read(void)
{
return read_c0_count();
}
@@ -132,9 +125,6 @@ static void __init c0_hpt_timer_init(void)
int (*mips_timer_state)(void);
void (*mips_timer_ack)(void);
-unsigned int (*mips_hpt_read)(void);
-void (*mips_hpt_init)(void) __initdata = null_hpt_init;
-unsigned int mips_hpt_mask = 0xffffffff;
/* last time when xtime and rtc are sync'ed up */
static long last_rtc_update;
@@ -276,8 +266,7 @@ static struct irqaction timer_irqaction = {
static unsigned int __init calibrate_hpt(void)
{
- u64 frequency;
- u32 hpt_start, hpt_end, hpt_count, hz;
+ cycle_t frequency, hpt_start, hpt_end, hpt_count, hz;
const int loops = HZ / 10;
int log_2_loops = 0;
@@ -303,28 +292,23 @@ static unsigned int __init calibrate_hpt(void)
* during the calculated number of periods between timer
* interrupts.
*/
- hpt_start = mips_hpt_read();
+ hpt_start = clocksource_mips.read();
do {
while (mips_timer_state());
while (!mips_timer_state());
} while (--i);
- hpt_end = mips_hpt_read();
+ hpt_end = clocksource_mips.read();
- hpt_count = (hpt_end - hpt_start) & mips_hpt_mask;
+ hpt_count = (hpt_end - hpt_start) & clocksource_mips.mask;
hz = HZ;
- frequency = (u64)hpt_count * (u64)hz;
+ frequency = hpt_count * hz;
return frequency >> log_2_loops;
}
-static cycle_t read_mips_hpt(void)
-{
- return (cycle_t)mips_hpt_read();
-}
-
-static struct clocksource clocksource_mips = {
+struct clocksource clocksource_mips = {
.name = "MIPS",
- .read = read_mips_hpt,
+ .mask = 0xffffffff,
.is_continuous = 1,
};
@@ -333,7 +317,7 @@ static void __init init_mips_clocksource(void)
u64 temp;
u32 shift;
- if (!mips_hpt_frequency || mips_hpt_read == null_hpt_read)
+ if (!mips_hpt_frequency || clocksource_mips.read == null_hpt_read)
return;
/* Calclate a somewhat reasonable rating value */
@@ -347,7 +331,6 @@ static void __init init_mips_clocksource(void)
}
clocksource_mips.shift = shift;
clocksource_mips.mult = (u32)temp;
- clocksource_mips.mask = mips_hpt_mask;
clocksource_register(&clocksource_mips);
}
@@ -367,32 +350,36 @@ void __init time_init(void)
-xtime.tv_sec, -xtime.tv_nsec);
/* Choose appropriate high precision timer routines. */
- if (!cpu_has_counter && !mips_hpt_read)
+ if (!cpu_has_counter && !clocksource_mips.read)
/* No high precision timer -- sorry. */
- mips_hpt_read = null_hpt_read;
+ clocksource_mips.read = null_hpt_read;
else if (!mips_hpt_frequency && !mips_timer_state) {
/* A high precision timer of unknown frequency. */
- if (!mips_hpt_read)
+ if (!clocksource_mips.read)
/* No external high precision timer -- use R4k. */
- mips_hpt_read = c0_hpt_read;
+ clocksource_mips.read = c0_hpt_read;
} else {
/* We know counter frequency. Or we can get it. */
- if (!mips_hpt_read) {
+ if (!clocksource_mips.read) {
/* No external high precision timer -- use R4k. */
- mips_hpt_read = c0_hpt_read;
+ clocksource_mips.read = c0_hpt_read;
if (!mips_timer_state) {
/* No external timer interrupt -- use R4k. */
- mips_hpt_init = c0_hpt_timer_init;
mips_timer_ack = c0_timer_ack;
+ /* Calculate cache parameters. */
+ cycles_per_jiffy =
+ (mips_hpt_frequency + HZ / 2) / HZ;
+ /*
+ * This sets up the high precision
+ * timer for the first interrupt.
+ */
+ c0_hpt_timer_init();
}
}
if (!mips_hpt_frequency)
mips_hpt_frequency = calibrate_hpt();
- /* Calculate cache parameters. */
- cycles_per_jiffy = (mips_hpt_frequency + HZ / 2) / HZ;
-
/* Report the high precision timer rate for a reference. */
printk("Using %u.%03u MHz high precision timer.\n",
((mips_hpt_frequency + 500) / 1000) / 1000,
@@ -403,9 +390,6 @@ void __init time_init(void)
/* No timer interrupt ack (e.g. i8254). */
mips_timer_ack = null_timer_ack;
- /* This sets up the high precision timer for the first interrupt. */
- mips_hpt_init();
-
/*
* Call board specific timer interrupt setup.
*
diff --git a/arch/mips/kernel/topology.c b/arch/mips/kernel/topology.c
new file mode 100644
index 000000000000..660e44ed44d7
--- /dev/null
+++ b/arch/mips/kernel/topology.c
@@ -0,0 +1,29 @@
+#include <linux/cpu.h>
+#include <linux/cpumask.h>
+#include <linux/init.h>
+#include <linux/node.h>
+#include <linux/nodemask.h>
+#include <linux/percpu.h>
+
+static DEFINE_PER_CPU(struct cpu, cpu_devices);
+
+static int __init topology_init(void)
+{
+ int i, ret;
+
+#ifdef CONFIG_NUMA
+ for_each_online_node(i)
+ register_one_node(i);
+#endif /* CONFIG_NUMA */
+
+ for_each_present_cpu(i) {
+ ret = register_cpu(&per_cpu(cpu_devices, i), i);
+ if (ret)
+ printk(KERN_WARNING "topology_init: register_cpu %d "
+ "failed (%d)\n", i, ret);
+ }
+
+ return 0;
+}
+
+subsys_initcall(topology_init);
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 9fda1b8be3a7..2a932cada244 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -54,6 +54,8 @@ extern asmlinkage void handle_dbe(void);
extern asmlinkage void handle_sys(void);
extern asmlinkage void handle_bp(void);
extern asmlinkage void handle_ri(void);
+extern asmlinkage void handle_ri_rdhwr_vivt(void);
+extern asmlinkage void handle_ri_rdhwr(void);
extern asmlinkage void handle_cpu(void);
extern asmlinkage void handle_ov(void);
extern asmlinkage void handle_tr(void);
@@ -397,19 +399,6 @@ asmlinkage void do_be(struct pt_regs *regs)
force_sig(SIGBUS, current);
}
-static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode)
-{
- unsigned int __user *epc;
-
- epc = (unsigned int __user *) regs->cp0_epc +
- ((regs->cp0_cause & CAUSEF_BD) != 0);
- if (!get_user(*opcode, epc))
- return 0;
-
- force_sig(SIGSEGV, current);
- return 1;
-}
-
/*
* ll/sc emulation
*/
@@ -544,8 +533,8 @@ static inline int simulate_llsc(struct pt_regs *regs)
{
unsigned int opcode;
- if (unlikely(get_insn_opcode(regs, &opcode)))
- return -EFAULT;
+ if (get_user(opcode, (unsigned int __user *) exception_epc(regs)))
+ goto out_sigsegv;
if ((opcode & OPCODE) == LL) {
simulate_ll(regs, opcode);
@@ -557,6 +546,10 @@ static inline int simulate_llsc(struct pt_regs *regs)
}
return -EFAULT; /* Strange things going on ... */
+
+out_sigsegv:
+ force_sig(SIGSEGV, current);
+ return -EFAULT;
}
/*
@@ -569,8 +562,8 @@ static inline int simulate_rdhwr(struct pt_regs *regs)
struct thread_info *ti = task_thread_info(current);
unsigned int opcode;
- if (unlikely(get_insn_opcode(regs, &opcode)))
- return -EFAULT;
+ if (get_user(opcode, (unsigned int __user *) exception_epc(regs)))
+ goto out_sigsegv;
if (unlikely(compute_return_epc(regs)))
return -EFAULT;
@@ -589,6 +582,10 @@ static inline int simulate_rdhwr(struct pt_regs *regs)
/* Not ours. */
return -EFAULT;
+
+out_sigsegv:
+ force_sig(SIGSEGV, current);
+ return -EFAULT;
}
asmlinkage void do_ov(struct pt_regs *regs)
@@ -672,10 +669,8 @@ asmlinkage void do_bp(struct pt_regs *regs)
unsigned int opcode, bcode;
siginfo_t info;
- die_if_kernel("Break instruction in kernel code", regs);
-
- if (get_insn_opcode(regs, &opcode))
- return;
+ if (get_user(opcode, (unsigned int __user *) exception_epc(regs)))
+ goto out_sigsegv;
/*
* There is the ancient bug in the MIPS assemblers that the break
@@ -696,6 +691,7 @@ asmlinkage void do_bp(struct pt_regs *regs)
switch (bcode) {
case BRK_OVERFLOW << 10:
case BRK_DIVZERO << 10:
+ die_if_kernel("Break instruction in kernel code", regs);
if (bcode == (BRK_DIVZERO << 10))
info.si_code = FPE_INTDIV;
else
@@ -705,9 +701,16 @@ asmlinkage void do_bp(struct pt_regs *regs)
info.si_addr = (void __user *) regs->cp0_epc;
force_sig_info(SIGFPE, &info, current);
break;
+ case BRK_BUG:
+ die("Kernel bug detected", regs);
+ break;
default:
+ die_if_kernel("Break instruction in kernel code", regs);
force_sig(SIGTRAP, current);
}
+
+out_sigsegv:
+ force_sig(SIGSEGV, current);
}
asmlinkage void do_tr(struct pt_regs *regs)
@@ -715,10 +718,8 @@ asmlinkage void do_tr(struct pt_regs *regs)
unsigned int opcode, tcode = 0;
siginfo_t info;
- die_if_kernel("Trap instruction in kernel code", regs);
-
- if (get_insn_opcode(regs, &opcode))
- return;
+ if (get_user(opcode, (unsigned int __user *) exception_epc(regs)))
+ goto out_sigsegv;
/* Immediate versions don't provide a code. */
if (!(opcode & OPCODE))
@@ -733,6 +734,7 @@ asmlinkage void do_tr(struct pt_regs *regs)
switch (tcode) {
case BRK_OVERFLOW:
case BRK_DIVZERO:
+ die_if_kernel("Trap instruction in kernel code", regs);
if (tcode == BRK_DIVZERO)
info.si_code = FPE_INTDIV;
else
@@ -742,9 +744,16 @@ asmlinkage void do_tr(struct pt_regs *regs)
info.si_addr = (void __user *) regs->cp0_epc;
force_sig_info(SIGFPE, &info, current);
break;
+ case BRK_BUG:
+ die("Kernel bug detected", regs);
+ break;
default:
+ die_if_kernel("Trap instruction in kernel code", regs);
force_sig(SIGTRAP, current);
}
+
+out_sigsegv:
+ force_sig(SIGSEGV, current);
}
asmlinkage void do_ri(struct pt_regs *regs)
@@ -1423,6 +1432,15 @@ void __init set_uncached_handler (unsigned long offset, void *addr, unsigned lon
memcpy((void *)(uncached_ebase + offset), addr, size);
}
+static int __initdata rdhwr_noopt;
+static int __init set_rdhwr_noopt(char *str)
+{
+ rdhwr_noopt = 1;
+ return 1;
+}
+
+__setup("rdhwr_noopt", set_rdhwr_noopt);
+
void __init trap_init(void)
{
extern char except_vec3_generic, except_vec3_r4000;
@@ -1502,7 +1520,9 @@ void __init trap_init(void)
set_except_vector(8, handle_sys);
set_except_vector(9, handle_bp);
- set_except_vector(10, handle_ri);
+ set_except_vector(10, rdhwr_noopt ? handle_ri :
+ (cpu_has_vtag_icache ?
+ handle_ri_rdhwr_vivt : handle_ri_rdhwr));
set_except_vector(11, handle_cpu);
set_except_vector(12, handle_ov);
set_except_vector(13, handle_tr);
diff --git a/arch/mips/lasat/interrupt.c b/arch/mips/lasat/interrupt.c
index a144a002dcc4..4a84a7beac53 100644
--- a/arch/mips/lasat/interrupt.c
+++ b/arch/mips/lasat/interrupt.c
@@ -36,33 +36,14 @@ static volatile int lasat_int_mask_shift;
void disable_lasat_irq(unsigned int irq_nr)
{
- unsigned long flags;
-
- local_irq_save(flags);
*lasat_int_mask &= ~(1 << irq_nr) << lasat_int_mask_shift;
- local_irq_restore(flags);
}
void enable_lasat_irq(unsigned int irq_nr)
{
- unsigned long flags;
-
- local_irq_save(flags);
*lasat_int_mask |= (1 << irq_nr) << lasat_int_mask_shift;
- local_irq_restore(flags);
}
-static unsigned int startup_lasat_irq(unsigned int irq)
-{
- enable_lasat_irq(irq);
-
- return 0; /* never anything pending */
-}
-
-#define shutdown_lasat_irq disable_lasat_irq
-
-#define mask_and_ack_lasat_irq disable_lasat_irq
-
static void end_lasat_irq(unsigned int irq)
{
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
@@ -71,11 +52,10 @@ static void end_lasat_irq(unsigned int irq)
static struct irq_chip lasat_irq_type = {
.typename = "Lasat",
- .startup = startup_lasat_irq,
- .shutdown = shutdown_lasat_irq,
- .enable = enable_lasat_irq,
- .disable = disable_lasat_irq,
- .ack = mask_and_ack_lasat_irq,
+ .ack = disable_lasat_irq,
+ .mask = disable_lasat_irq,
+ .mask_ack = disable_lasat_irq,
+ .unmask = enable_lasat_irq,
.end = end_lasat_irq,
};
@@ -152,10 +132,6 @@ void __init arch_init_irq(void)
panic("arch_init_irq: mips_machtype incorrect");
}
- for (i = 0; i <= LASATINT_END; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = 0;
- irq_desc[i].depth = 1;
- irq_desc[i].chip = &lasat_irq_type;
- }
+ for (i = 0; i <= LASATINT_END; i++)
+ set_irq_chip_and_handler(i, &lasat_irq_type, handle_level_irq);
}
diff --git a/arch/mips/lib/csum_partial_copy.c b/arch/mips/lib/csum_partial_copy.c
index 6e9f366f961d..1720f2ceeeae 100644
--- a/arch/mips/lib/csum_partial_copy.c
+++ b/arch/mips/lib/csum_partial_copy.c
@@ -16,8 +16,8 @@
/*
* copy while checksumming, otherwise like csum_partial
*/
-unsigned int csum_partial_copy_nocheck(const unsigned char *src,
- unsigned char *dst, int len, unsigned int sum)
+__wsum csum_partial_copy_nocheck(const void *src,
+ void *dst, int len, __wsum sum)
{
/*
* It's 2:30 am and I don't feel like doing it real ...
@@ -33,8 +33,8 @@ unsigned int csum_partial_copy_nocheck(const unsigned char *src,
* Copy from userspace and compute checksum. If we catch an exception
* then zero the rest of the buffer.
*/
-unsigned int csum_partial_copy_from_user (const unsigned char __user *src,
- unsigned char *dst, int len, unsigned int sum, int *err_ptr)
+__wsum csum_partial_copy_from_user (const void __user *src,
+ void *dst, int len, __wsum sum, int *err_ptr)
{
int missing;
diff --git a/arch/mips/mips-boards/atlas/atlas_int.c b/arch/mips/mips-boards/atlas/atlas_int.c
index be624b8c3b0e..43dba6ce6603 100644
--- a/arch/mips/mips-boards/atlas/atlas_int.c
+++ b/arch/mips/mips-boards/atlas/atlas_int.c
@@ -62,16 +62,6 @@ void enable_atlas_irq(unsigned int irq_nr)
iob();
}
-static unsigned int startup_atlas_irq(unsigned int irq)
-{
- enable_atlas_irq(irq);
- return 0; /* never anything pending */
-}
-
-#define shutdown_atlas_irq disable_atlas_irq
-
-#define mask_and_ack_atlas_irq disable_atlas_irq
-
static void end_atlas_irq(unsigned int irq)
{
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
@@ -80,11 +70,11 @@ static void end_atlas_irq(unsigned int irq)
static struct irq_chip atlas_irq_type = {
.typename = "Atlas",
- .startup = startup_atlas_irq,
- .shutdown = shutdown_atlas_irq,
- .enable = enable_atlas_irq,
- .disable = disable_atlas_irq,
- .ack = mask_and_ack_atlas_irq,
+ .ack = disable_atlas_irq,
+ .mask = disable_atlas_irq,
+ .mask_ack = disable_atlas_irq,
+ .unmask = enable_atlas_irq,
+ .eoi = enable_atlas_irq,
.end = end_atlas_irq,
};
@@ -217,13 +207,8 @@ static inline void init_atlas_irqs (int base)
*/
atlas_hw0_icregs->intrsten = 0xffffffff;
- for (i = ATLAS_INT_BASE; i <= ATLAS_INT_END; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = 0;
- irq_desc[i].depth = 1;
- irq_desc[i].chip = &atlas_irq_type;
- spin_lock_init(&irq_desc[i].lock);
- }
+ for (i = ATLAS_INT_BASE; i <= ATLAS_INT_END; i++)
+ set_irq_chip_and_handler(i, &atlas_irq_type, handle_level_irq);
}
static struct irqaction atlasirq = {
diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c
index d817c60c5ca5..e4604c73f02e 100644
--- a/arch/mips/mips-boards/generic/time.c
+++ b/arch/mips/mips-boards/generic/time.c
@@ -288,6 +288,7 @@ void __init plat_timer_setup(struct irqaction *irq)
The effect is that the int remains disabled on the second cpu.
Mark the interrupt with IRQ_PER_CPU to avoid any confusion */
irq_desc[mips_cpu_timer_irq].status |= IRQ_PER_CPU;
+ set_irq_handler(mips_cpu_timer_irq, handle_percpu_irq);
#endif
/* to generate the first timer interrupt */
diff --git a/arch/mips/mips-boards/malta/malta_setup.c b/arch/mips/mips-boards/malta/malta_setup.c
index ab460f805bef..282f3e52eea3 100644
--- a/arch/mips/mips-boards/malta/malta_setup.c
+++ b/arch/mips/mips-boards/malta/malta_setup.c
@@ -159,7 +159,7 @@ void __init plat_mem_setup(void)
BONITO_PCIMEMBASECFG |=
(BONITO_PCIMEMBASECFG_MEMBASE0_CACHED |
BONITO_PCIMEMBASECFG_MEMBASE1_CACHED);
- printk("Disabled Bonito IOBC coherency\n");
+ printk("Enabled Bonito IOBC coherency\n");
}
}
else
diff --git a/arch/mips/mips-boards/sim/sim_time.c b/arch/mips/mips-boards/sim/sim_time.c
index 24a4ed00cc0a..30711d016fed 100644
--- a/arch/mips/mips-boards/sim/sim_time.c
+++ b/arch/mips/mips-boards/sim/sim_time.c
@@ -3,31 +3,24 @@
#include <linux/kernel_stat.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
-
-#include <asm/mipsregs.h>
-#include <asm/ptrace.h>
-#include <asm/hardirq.h>
-#include <asm/div64.h>
-#include <asm/cpu.h>
-#include <asm/time.h>
-
#include <linux/interrupt.h>
#include <linux/mc146818rtc.h>
#include <linux/timex.h>
+
#include <asm/mipsregs.h>
+#include <asm/ptrace.h>
#include <asm/hardirq.h>
-#include <asm/irq.h>
#include <asm/div64.h>
#include <asm/cpu.h>
#include <asm/time.h>
+#include <asm/irq.h>
#include <asm/mc146818-time.h>
#include <asm/msc01_ic.h>
+#include <asm/smp.h>
#include <asm/mips-boards/generic.h>
#include <asm/mips-boards/prom.h>
#include <asm/mips-boards/simint.h>
-#include <asm/mc146818-time.h>
-#include <asm/smp.h>
unsigned long cpu_khz;
@@ -203,7 +196,8 @@ void __init plat_timer_setup(struct irqaction *irq)
on seperate cpu's the first one tries to handle the second interrupt.
The effect is that the int remains disabled on the second cpu.
Mark the interrupt with IRQ_PER_CPU to avoid any confusion */
- irq_desc[mips_cpu_timer_irq].status |= IRQ_PER_CPU;
+ irq_desc[mips_cpu_timer_irq].flags |= IRQ_PER_CPU;
+ set_irq_handler(mips_cpu_timer_irq, handle_percpu_irq);
#endif
/* to generate the first timer interrupt */
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index cc895dad71d2..df04a315d830 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -323,7 +323,6 @@ static void __init r4k_blast_scache_setup(void)
static inline void local_r4k_flush_cache_all(void * args)
{
r4k_blast_dcache();
- r4k_blast_icache();
}
static void r4k_flush_cache_all(void)
@@ -359,21 +358,19 @@ static void r4k___flush_cache_all(void)
static inline void local_r4k_flush_cache_range(void * args)
{
struct vm_area_struct *vma = args;
- int exec;
if (!(cpu_context(smp_processor_id(), vma->vm_mm)))
return;
- exec = vma->vm_flags & VM_EXEC;
- if (cpu_has_dc_aliases || exec)
- r4k_blast_dcache();
- if (exec)
- r4k_blast_icache();
+ r4k_blast_dcache();
}
static void r4k_flush_cache_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end)
{
+ if (!cpu_has_dc_aliases)
+ return;
+
r4k_on_each_cpu(local_r4k_flush_cache_range, vma, 1, 1);
}
@@ -384,18 +381,21 @@ static inline void local_r4k_flush_cache_mm(void * args)
if (!cpu_context(smp_processor_id(), mm))
return;
- r4k_blast_dcache();
- r4k_blast_icache();
-
/*
* Kludge alert. For obscure reasons R4000SC and R4400SC go nuts if we
* only flush the primary caches but R10000 and R12000 behave sane ...
+ * R4000SC and R4400SC indexed S-cache ops also invalidate primary
+ * caches, so we can bail out early.
*/
if (current_cpu_data.cputype == CPU_R4000SC ||
current_cpu_data.cputype == CPU_R4000MC ||
current_cpu_data.cputype == CPU_R4400SC ||
- current_cpu_data.cputype == CPU_R4400MC)
+ current_cpu_data.cputype == CPU_R4400MC) {
r4k_blast_scache();
+ return;
+ }
+
+ r4k_blast_dcache();
}
static void r4k_flush_cache_mm(struct mm_struct *mm)
diff --git a/arch/mips/mm/c-sb1.c b/arch/mips/mm/c-sb1.c
index d0ddb4a768a5..3a8afd47feaa 100644
--- a/arch/mips/mm/c-sb1.c
+++ b/arch/mips/mm/c-sb1.c
@@ -19,6 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/init.h>
+#include <linux/hardirq.h>
#include <asm/asm.h>
#include <asm/bootinfo.h>
@@ -242,6 +243,25 @@ void sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsign
__attribute__((alias("local_sb1_flush_cache_page")));
#endif
+#ifdef CONFIG_SMP
+static void sb1_flush_cache_data_page_ipi(void *info)
+{
+ unsigned long start = (unsigned long)info;
+
+ __sb1_writeback_inv_dcache_range(start, start + PAGE_SIZE);
+}
+
+static void sb1_flush_cache_data_page(unsigned long addr)
+{
+ if (in_atomic())
+ __sb1_writeback_inv_dcache_range(addr, addr + PAGE_SIZE);
+ else
+ on_each_cpu(sb1_flush_cache_data_page_ipi, (void *) addr, 1, 1);
+}
+#else
+void sb1_flush_cache_data_page(unsigned long)
+ __attribute__((alias("local_sb1_flush_cache_data_page")));
+#endif
/*
* Invalidate all caches on this CPU
@@ -481,7 +501,7 @@ void sb1_cache_init(void)
flush_cache_sigtramp = sb1_flush_cache_sigtramp;
local_flush_data_cache_page = (void *) sb1_nop;
- flush_data_cache_page = (void *) sb1_nop;
+ flush_data_cache_page = sb1_flush_cache_data_page;
/* Full flush */
__flush_cache_all = sb1___flush_cache_all;
diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c
index 8423d8590779..6f90e7ef66ac 100644
--- a/arch/mips/mm/fault.c
+++ b/arch/mips/mm/fault.c
@@ -60,6 +60,10 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write,
*/
if (unlikely(address >= VMALLOC_START && address <= VMALLOC_END))
goto vmalloc_fault;
+#ifdef MODULE_START
+ if (unlikely(address >= MODULE_START && address < MODULE_END))
+ goto vmalloc_fault;
+#endif
/*
* If we're in an interrupt or have no user
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index 2de4d3c367a2..9e29ba9205f0 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -90,9 +90,9 @@ unsigned long setup_zero_pages(void)
if (!empty_zero_page)
panic("Oh boy, that early out of memory?");
- page = virt_to_page(empty_zero_page);
+ page = virt_to_page((void *)empty_zero_page);
split_page(page, order);
- while (page < virt_to_page(empty_zero_page + (PAGE_SIZE << order))) {
+ while (page < virt_to_page((void *)(empty_zero_page + (PAGE_SIZE << order)))) {
SetPageReserved(page);
page++;
}
@@ -443,15 +443,18 @@ void __init mem_init(void)
}
#endif /* !CONFIG_NEED_MULTIPLE_NODES */
-void free_init_pages(char *what, unsigned long begin, unsigned long end)
+static void free_init_pages(char *what, unsigned long begin, unsigned long end)
{
- unsigned long addr;
+ unsigned long pfn;
- 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);
+ for (pfn = PFN_UP(begin); pfn < PFN_DOWN(end); pfn++) {
+ struct page *page = pfn_to_page(pfn);
+ void *addr = phys_to_virt(PFN_PHYS(pfn));
+
+ ClearPageReserved(page);
+ init_page_count(page);
+ memset(addr, POISON_FREE_INITMEM, PAGE_SIZE);
+ __free_page(page);
totalram_pages++;
}
printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10);
@@ -460,12 +463,9 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end)
#ifdef CONFIG_BLK_DEV_INITRD
void free_initrd_mem(unsigned long start, unsigned long end)
{
-#ifdef CONFIG_64BIT
- /* Switch from KSEG0 to XKPHYS addresses */
- start = (unsigned long)phys_to_virt(CPHYSADDR(start));
- end = (unsigned long)phys_to_virt(CPHYSADDR(end));
-#endif
- free_init_pages("initrd memory", start, end);
+ free_init_pages("initrd memory",
+ virt_to_phys((void *)start),
+ virt_to_phys((void *)end));
}
#endif
@@ -473,17 +473,13 @@ extern unsigned long prom_free_prom_memory(void);
void free_initmem(void)
{
- unsigned long start, end, freed;
+ unsigned long freed;
freed = prom_free_prom_memory();
if (freed)
printk(KERN_INFO "Freeing firmware memory: %ldk freed\n",freed);
- start = (unsigned long)(&__init_begin);
- end = (unsigned long)(&__init_end);
-#ifdef CONFIG_64BIT
- start = PAGE_OFFSET | CPHYSADDR(start);
- end = PAGE_OFFSET | CPHYSADDR(end);
-#endif
- free_init_pages("unused kernel memory", start, end);
+ free_init_pages("unused kernel memory",
+ __pa_symbol(&__init_begin),
+ __pa_symbol(&__init_end));
}
diff --git a/arch/mips/mm/pgtable-64.c b/arch/mips/mm/pgtable-64.c
index 8d600d307d5d..c46eb651bf09 100644
--- a/arch/mips/mm/pgtable-64.c
+++ b/arch/mips/mm/pgtable-64.c
@@ -58,6 +58,9 @@ void __init pagetable_init(void)
/* Initialize the entire pgd. */
pgd_init((unsigned long)swapper_pg_dir);
+#ifdef MODULE_START
+ pgd_init((unsigned long)module_pg_dir);
+#endif
pmd_init((unsigned long)invalid_pmd_table, (unsigned long)invalid_pte_table);
pgd_base = swapper_pg_dir;
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index fec318a1c8c5..492c518e7ba5 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -423,6 +423,9 @@ enum label_id {
label_invalid,
label_second_part,
label_leave,
+#ifdef MODULE_START
+ label_module_alloc,
+#endif
label_vmalloc,
label_vmalloc_done,
label_tlbw_hazard,
@@ -455,6 +458,9 @@ static __init void build_label(struct label **lab, u32 *addr,
L_LA(_second_part)
L_LA(_leave)
+#ifdef MODULE_START
+L_LA(_module_alloc)
+#endif
L_LA(_vmalloc)
L_LA(_vmalloc_done)
L_LA(_tlbw_hazard)
@@ -686,6 +692,13 @@ static void __init il_bgezl(u32 **p, struct reloc **r, unsigned int reg,
i_bgezl(p, reg, 0);
}
+static void __init __attribute__((unused))
+il_bgez(u32 **p, struct reloc **r, unsigned int reg, enum label_id l)
+{
+ r_mips_pc16(r, *p, l);
+ i_bgez(p, reg, 0);
+}
+
/* The only general purpose registers allowed in TLB handlers. */
#define K0 26
#define K1 27
@@ -970,7 +983,11 @@ build_get_pmde64(u32 **p, struct label **l, struct reloc **r,
* The vmalloc handling is not in the hotpath.
*/
i_dmfc0(p, tmp, C0_BADVADDR);
+#ifdef MODULE_START
+ il_bltz(p, r, tmp, label_module_alloc);
+#else
il_bltz(p, r, tmp, label_vmalloc);
+#endif
/* No i_nop needed here, since the next insn doesn't touch TMP. */
#ifdef CONFIG_SMP
@@ -1023,8 +1040,46 @@ build_get_pgd_vmalloc64(u32 **p, struct label **l, struct reloc **r,
{
long swpd = (long)swapper_pg_dir;
+#ifdef MODULE_START
+ long modd = (long)module_pg_dir;
+
+ l_module_alloc(l, *p);
+ /*
+ * Assumption:
+ * VMALLOC_START >= 0xc000000000000000UL
+ * MODULE_START >= 0xe000000000000000UL
+ */
+ i_SLL(p, ptr, bvaddr, 2);
+ il_bgez(p, r, ptr, label_vmalloc);
+
+ if (in_compat_space_p(MODULE_START) && !rel_lo(MODULE_START)) {
+ i_lui(p, ptr, rel_hi(MODULE_START)); /* delay slot */
+ } else {
+ /* unlikely configuration */
+ i_nop(p); /* delay slot */
+ i_LA(p, ptr, MODULE_START);
+ }
+ i_dsubu(p, bvaddr, bvaddr, ptr);
+
+ if (in_compat_space_p(modd) && !rel_lo(modd)) {
+ il_b(p, r, label_vmalloc_done);
+ i_lui(p, ptr, rel_hi(modd));
+ } else {
+ i_LA_mostly(p, ptr, modd);
+ il_b(p, r, label_vmalloc_done);
+ i_daddiu(p, ptr, ptr, rel_lo(modd));
+ }
+
+ l_vmalloc(l, *p);
+ if (in_compat_space_p(MODULE_START) && !rel_lo(MODULE_START) &&
+ MODULE_START << 32 == VMALLOC_START)
+ i_dsll32(p, ptr, ptr, 0); /* typical case */
+ else
+ i_LA(p, ptr, VMALLOC_START);
+#else
l_vmalloc(l, *p);
i_LA(p, ptr, VMALLOC_START);
+#endif
i_dsubu(p, bvaddr, bvaddr, ptr);
if (in_compat_space_p(swpd) && !rel_lo(swpd)) {
diff --git a/arch/mips/momentum/ocelot_c/cpci-irq.c b/arch/mips/momentum/ocelot_c/cpci-irq.c
index 47e3fa32b075..e5a4a0a8a7f0 100644
--- a/arch/mips/momentum/ocelot_c/cpci-irq.c
+++ b/arch/mips/momentum/ocelot_c/cpci-irq.c
@@ -66,39 +66,6 @@ static inline void unmask_cpci_irq(unsigned int irq)
}
/*
- * Enables the IRQ in the FPGA
- */
-static void enable_cpci_irq(unsigned int irq)
-{
- unmask_cpci_irq(irq);
-}
-
-/*
- * Initialize the IRQ in the FPGA
- */
-static unsigned int startup_cpci_irq(unsigned int irq)
-{
- unmask_cpci_irq(irq);
- return 0;
-}
-
-/*
- * Disables the IRQ in the FPGA
- */
-static void disable_cpci_irq(unsigned int irq)
-{
- mask_cpci_irq(irq);
-}
-
-/*
- * Masks and ACKs an IRQ
- */
-static void mask_and_ack_cpci_irq(unsigned int irq)
-{
- mask_cpci_irq(irq);
-}
-
-/*
* End IRQ processing
*/
static void end_cpci_irq(unsigned int irq)
@@ -125,15 +92,12 @@ void ll_cpci_irq(void)
do_IRQ(ls1bit8(irq_src) + CPCI_IRQ_BASE);
}
-#define shutdown_cpci_irq disable_cpci_irq
-
struct irq_chip cpci_irq_type = {
.typename = "CPCI/FPGA",
- .startup = startup_cpci_irq,
- .shutdown = shutdown_cpci_irq,
- .enable = enable_cpci_irq,
- .disable = disable_cpci_irq,
- .ack = mask_and_ack_cpci_irq,
+ .ack = mask_cpci_irq,
+ .mask = mask_cpci_irq,
+ .mask_ack = mask_cpci_irq,
+ .unmask = unmask_cpci_irq,
.end = end_cpci_irq,
};
@@ -141,11 +105,6 @@ void cpci_irq_init(void)
{
int i;
- /* Reset irq handlers pointers to NULL */
- for (i = CPCI_IRQ_BASE; i < (CPCI_IRQ_BASE + 8); i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = 0;
- irq_desc[i].depth = 2;
- irq_desc[i].chip = &cpci_irq_type;
- }
+ for (i = CPCI_IRQ_BASE; i < (CPCI_IRQ_BASE + 8); i++)
+ set_irq_chip_and_handler(i, &cpci_irq_type, handle_level_irq);
}
diff --git a/arch/mips/momentum/ocelot_c/uart-irq.c b/arch/mips/momentum/ocelot_c/uart-irq.c
index 510257dc205a..0029f0008dea 100644
--- a/arch/mips/momentum/ocelot_c/uart-irq.c
+++ b/arch/mips/momentum/ocelot_c/uart-irq.c
@@ -60,39 +60,6 @@ static inline void unmask_uart_irq(unsigned int irq)
}
/*
- * Enables the IRQ in the FPGA
- */
-static void enable_uart_irq(unsigned int irq)
-{
- unmask_uart_irq(irq);
-}
-
-/*
- * Initialize the IRQ in the FPGA
- */
-static unsigned int startup_uart_irq(unsigned int irq)
-{
- unmask_uart_irq(irq);
- return 0;
-}
-
-/*
- * Disables the IRQ in the FPGA
- */
-static void disable_uart_irq(unsigned int irq)
-{
- mask_uart_irq(irq);
-}
-
-/*
- * Masks and ACKs an IRQ
- */
-static void mask_and_ack_uart_irq(unsigned int irq)
-{
- mask_uart_irq(irq);
-}
-
-/*
* End IRQ processing
*/
static void end_uart_irq(unsigned int irq)
@@ -118,28 +85,17 @@ void ll_uart_irq(void)
do_IRQ(ls1bit8(irq_src) + 74);
}
-#define shutdown_uart_irq disable_uart_irq
-
struct irq_chip uart_irq_type = {
.typename = "UART/FPGA",
- .startup = startup_uart_irq,
- .shutdown = shutdown_uart_irq,
- .enable = enable_uart_irq,
- .disable = disable_uart_irq,
- .ack = mask_and_ack_uart_irq,
+ .ack = mask_uart_irq,
+ .mask = mask_uart_irq,
+ .mask_ack = mask_uart_irq,
+ .unmask = unmask_uart_irq,
.end = end_uart_irq,
};
void uart_irq_init(void)
{
- /* Reset irq handlers pointers to NULL */
- irq_desc[80].status = IRQ_DISABLED;
- irq_desc[80].action = 0;
- irq_desc[80].depth = 2;
- irq_desc[80].chip = &uart_irq_type;
-
- irq_desc[81].status = IRQ_DISABLED;
- irq_desc[81].action = 0;
- irq_desc[81].depth = 2;
- irq_desc[81].chip = &uart_irq_type;
+ set_irq_chip_and_handler(80, &uart_irq_type, handle_level_irq);
+ set_irq_chip_and_handler(81, &uart_irq_type, handle_level_irq);
}
diff --git a/arch/mips/oprofile/Makefile b/arch/mips/oprofile/Makefile
index 0a50aad5bbe4..bf3be6fcf7ff 100644
--- a/arch/mips/oprofile/Makefile
+++ b/arch/mips/oprofile/Makefile
@@ -12,5 +12,6 @@ oprofile-y := $(DRIVER_OBJS) common.o
oprofile-$(CONFIG_CPU_MIPS32) += op_model_mipsxx.o
oprofile-$(CONFIG_CPU_MIPS64) += op_model_mipsxx.o
+oprofile-$(CONFIG_CPU_R10000) += op_model_mipsxx.o
oprofile-$(CONFIG_CPU_SB1) += op_model_mipsxx.o
oprofile-$(CONFIG_CPU_RM9000) += op_model_rm9000.o
diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c
index 65eb55400d77..4e0a90b3916b 100644
--- a/arch/mips/oprofile/common.c
+++ b/arch/mips/oprofile/common.c
@@ -83,6 +83,9 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
case CPU_74K:
case CPU_SB1:
case CPU_SB1A:
+ case CPU_R10000:
+ case CPU_R12000:
+ case CPU_R14000:
lmodel = &op_model_mipsxx_ops;
break;
diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c
index 1fb240c57bac..455d76ad06d8 100644
--- a/arch/mips/oprofile/op_model_mipsxx.c
+++ b/arch/mips/oprofile/op_model_mipsxx.c
@@ -18,7 +18,7 @@
#define M_PERFCTL_SUPERVISOR (1UL << 2)
#define M_PERFCTL_USER (1UL << 3)
#define M_PERFCTL_INTERRUPT_ENABLE (1UL << 4)
-#define M_PERFCTL_EVENT(event) ((event) << 5)
+#define M_PERFCTL_EVENT(event) (((event) & 0x3f) << 5)
#define M_PERFCTL_VPEID(vpe) ((vpe) << 16)
#define M_PERFCTL_MT_EN(filter) ((filter) << 20)
#define M_TC_EN_ALL M_PERFCTL_MT_EN(0)
@@ -218,13 +218,23 @@ static inline int __n_counters(void)
static inline int n_counters(void)
{
- int counters = __n_counters();
+ int counters;
+
+ switch (current_cpu_data.cputype) {
+ case CPU_R10000:
+ counters = 2;
+
+ case CPU_R12000:
+ case CPU_R14000:
+ counters = 4;
+
+ default:
+ counters = __n_counters();
+ }
#ifdef CONFIG_MIPS_MT_SMP
- if (current_cpu_data.cputype == CPU_34K)
- return counters >> 1;
+ counters >> 1;
#endif
-
return counters;
}
@@ -284,6 +294,18 @@ static int __init mipsxx_init(void)
op_model_mipsxx_ops.cpu_type = "mips/5K";
break;
+ case CPU_R10000:
+ if ((current_cpu_data.processor_id & 0xff) == 0x20)
+ op_model_mipsxx_ops.cpu_type = "mips/r10000-v2.x";
+ else
+ op_model_mipsxx_ops.cpu_type = "mips/r10000";
+ break;
+
+ case CPU_R12000:
+ case CPU_R14000:
+ op_model_mipsxx_ops.cpu_type = "mips/r12000";
+ break;
+
case CPU_SB1:
case CPU_SB1A:
op_model_mipsxx_ops.cpu_type = "mips/sb1";
diff --git a/arch/mips/pci/fixup-cobalt.c b/arch/mips/pci/fixup-cobalt.c
index 75a01e764898..7d5f6bbf7a9d 100644
--- a/arch/mips/pci/fixup-cobalt.c
+++ b/arch/mips/pci/fixup-cobalt.c
@@ -94,22 +94,21 @@ static void qube_raq_galileo_fixup(struct pci_dev *dev)
#if 0
if (galileo_id >= 0x10) {
/* New Galileo, assumes PCI stop line to VIA is connected. */
- GALILEO_OUTL(0x4020, GT_PCI0_TOR_OFS);
+ GT_WRITE(GT_PCI0_TOR_OFS, 0x4020);
} else if (galileo_id == 0x1 || galileo_id == 0x2)
#endif
{
signed int timeo;
/* XXX WE MUST DO THIS ELSE GALILEO LOCKS UP! -DaveM */
- timeo = GALILEO_INL(GT_PCI0_TOR_OFS);
+ timeo = GT_READ(GT_PCI0_TOR_OFS);
/* Old Galileo, assumes PCI STOP line to VIA is disconnected. */
- GALILEO_OUTL(
+ GT_WRITE(GT_PCI0_TOR_OFS,
(0xff << 16) | /* retry count */
(0xff << 8) | /* timeout 1 */
- 0xff, /* timeout 0 */
- GT_PCI0_TOR_OFS);
+ 0xff); /* timeout 0 */
/* enable PCI retry exceeded interrupt */
- GALILEO_OUTL(GALILEO_INTR_RETRY_CTR | GALILEO_INL(GT_INTRMASK_OFS), GT_INTRMASK_OFS);
+ GT_WRITE(GT_INTRMASK_OFS, GT_INTR_RETRYCTR0_MSK | GT_READ(GT_INTRMASK_OFS));
}
}
diff --git a/arch/mips/pci/ops-gt64111.c b/arch/mips/pci/ops-gt64111.c
index 13de45940b19..ecd3991bd0e4 100644
--- a/arch/mips/pci/ops-gt64111.c
+++ b/arch/mips/pci/ops-gt64111.c
@@ -38,18 +38,18 @@ static int gt64111_pci_read_config(struct pci_bus *bus, unsigned int devfn,
switch (size) {
case 4:
PCI_CFG_SET(devfn, where);
- *val = GALILEO_INL(GT_PCI0_CFGDATA_OFS);
+ *val = GT_READ(GT_PCI0_CFGDATA_OFS);
return PCIBIOS_SUCCESSFUL;
case 2:
PCI_CFG_SET(devfn, (where & ~0x3));
- *val = GALILEO_INL(GT_PCI0_CFGDATA_OFS)
+ *val = GT_READ(GT_PCI0_CFGDATA_OFS)
>> ((where & 3) * 8);
return PCIBIOS_SUCCESSFUL;
case 1:
PCI_CFG_SET(devfn, (where & ~0x3));
- *val = GALILEO_INL(GT_PCI0_CFGDATA_OFS)
+ *val = GT_READ(GT_PCI0_CFGDATA_OFS)
>> ((where & 3) * 8);
return PCIBIOS_SUCCESSFUL;
}
@@ -68,25 +68,25 @@ static int gt64111_pci_write_config(struct pci_bus *bus, unsigned int devfn,
switch (size) {
case 4:
PCI_CFG_SET(devfn, where);
- GALILEO_OUTL(val, GT_PCI0_CFGDATA_OFS);
+ GT_WRITE(GT_PCI0_CFGDATA_OFS, val);
return PCIBIOS_SUCCESSFUL;
case 2:
PCI_CFG_SET(devfn, (where & ~0x3));
- tmp = GALILEO_INL(GT_PCI0_CFGDATA_OFS);
+ tmp = GT_READ(GT_PCI0_CFGDATA_OFS);
tmp &= ~(0xffff << ((where & 0x3) * 8));
tmp |= (val << ((where & 0x3) * 8));
- GALILEO_OUTL(tmp, GT_PCI0_CFGDATA_OFS);
+ GT_WRITE(GT_PCI0_CFGDATA_OFS, tmp);
return PCIBIOS_SUCCESSFUL;
case 1:
PCI_CFG_SET(devfn, (where & ~0x3));
- tmp = GALILEO_INL(GT_PCI0_CFGDATA_OFS);
+ tmp = GT_READ(GT_PCI0_CFGDATA_OFS);
tmp &= ~(0xff << ((where & 0x3) * 8));
tmp |= (val << ((where & 0x3) * 8));
- GALILEO_OUTL(tmp, GT_PCI0_CFGDATA_OFS);
+ GT_WRITE(GT_PCI0_CFGDATA_OFS, tmp);
return PCIBIOS_SUCCESSFUL;
}
diff --git a/arch/mips/philips/pnx8550/common/int.c b/arch/mips/philips/pnx8550/common/int.c
index 710611615ca2..0dc23930edbd 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>
-static DEFINE_SPINLOCK(irq_lock);
-
/* default prio for interrupts */
/* first one is a no-no so therefore always prio 0 (disabled) */
static char gic_prio[PNX8550_INT_GIC_TOTINT] = {
@@ -149,38 +147,6 @@ static inline void unmask_irq(unsigned int irq_nr)
}
}
-#define pnx8550_disable pnx8550_ack
-static void pnx8550_ack(unsigned int irq)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&irq_lock, flags);
- mask_irq(irq);
- spin_unlock_irqrestore(&irq_lock, flags);
-}
-
-#define pnx8550_enable pnx8550_unmask
-static void pnx8550_unmask(unsigned int irq)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&irq_lock, flags);
- unmask_irq(irq);
- spin_unlock_irqrestore(&irq_lock, flags);
-}
-
-static unsigned int startup_irq(unsigned int irq_nr)
-{
- pnx8550_unmask(irq_nr);
- return 0;
-}
-
-static void shutdown_irq(unsigned int irq_nr)
-{
- pnx8550_ack(irq_nr);
- return;
-}
-
int pnx8550_set_gic_priority(int irq, int priority)
{
int gic_irq = irq-PNX8550_INT_GIC_MIN;
@@ -192,26 +158,19 @@ int pnx8550_set_gic_priority(int irq, int priority)
return prev_priority;
}
-static inline void mask_and_ack_level_irq(unsigned int irq)
-{
- pnx8550_disable(irq);
- return;
-}
-
static void end_irq(unsigned int irq)
{
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
- pnx8550_enable(irq);
+ unmask_irq(irq);
}
}
static struct irq_chip level_irq_type = {
.typename = "PNX Level IRQ",
- .startup = startup_irq,
- .shutdown = shutdown_irq,
- .enable = pnx8550_enable,
- .disable = pnx8550_disable,
- .ack = mask_and_ack_level_irq,
+ .ack = mask_irq,
+ .mask = mask_irq,
+ .mask_ack = mask_irq,
+ .unmask = unmask_irq,
.end = end_irq,
};
@@ -233,8 +192,8 @@ void __init arch_init_irq(void)
int configPR;
for (i = 0; i < PNX8550_INT_CP0_TOTINT; i++) {
- irq_desc[i].chip = &level_irq_type;
- pnx8550_ack(i); /* mask the irq just in case */
+ set_irq_chip_and_handler(i, &level_irq_type, handle_level_irq);
+ mask_irq(i); /* mask the irq just in case */
}
/* init of GIC/IPC interrupts */
@@ -270,7 +229,7 @@ void __init arch_init_irq(void)
/* mask/priority is still 0 so we will not get any
* interrupts until it is unmasked */
- irq_desc[i].chip = &level_irq_type;
+ set_irq_chip_and_handler(i, &level_irq_type, handle_level_irq);
}
/* Priority level 0 */
@@ -279,20 +238,21 @@ void __init arch_init_irq(void)
/* Set int vector table address */
PNX8550_GIC_VECTOR_0 = PNX8550_GIC_VECTOR_1 = 0;
- irq_desc[MIPS_CPU_GIC_IRQ].chip = &level_irq_type;
+ set_irq_chip_and_handler(MIPS_CPU_GIC_IRQ, &level_irq_type,
+ handle_level_irq);
setup_irq(MIPS_CPU_GIC_IRQ, &gic_action);
/* init of Timer interrupts */
- for (i = PNX8550_INT_TIMER_MIN; i <= PNX8550_INT_TIMER_MAX; i++) {
- irq_desc[i].chip = &level_irq_type;
- }
+ for (i = PNX8550_INT_TIMER_MIN; i <= PNX8550_INT_TIMER_MAX; i++)
+ set_irq_chip_and_handler(i, &level_irq_type, handle_level_irq);
/* Stop Timer 1-3 */
configPR = read_c0_config7();
configPR |= 0x00000038;
write_c0_config7(configPR);
- irq_desc[MIPS_CPU_TIMER_IRQ].chip = &level_irq_type;
+ set_irq_chip_and_handler(MIPS_CPU_TIMER_IRQ, &level_irq_type,
+ handle_level_irq);
setup_irq(MIPS_CPU_TIMER_IRQ, &timer_action);
}
diff --git a/arch/mips/pmc-sierra/yosemite/smp.c b/arch/mips/pmc-sierra/yosemite/smp.c
index 3cc0436db6cf..305491e74dbe 100644
--- a/arch/mips/pmc-sierra/yosemite/smp.c
+++ b/arch/mips/pmc-sierra/yosemite/smp.c
@@ -99,8 +99,6 @@ void prom_cpus_done(void)
*/
void prom_init_secondary(void)
{
- mips_hpt_init();
-
set_c0_status(ST0_CO | ST0_IE | ST0_IM);
}
diff --git a/arch/mips/sgi-ip22/ip22-eisa.c b/arch/mips/sgi-ip22/ip22-eisa.c
index 0d18ed47c47a..a1a9af6da7bf 100644
--- a/arch/mips/sgi-ip22/ip22-eisa.c
+++ b/arch/mips/sgi-ip22/ip22-eisa.c
@@ -95,16 +95,11 @@ static irqreturn_t ip22_eisa_intr(int irq, void *dev_id)
static void enable_eisa1_irq(unsigned int irq)
{
- unsigned long flags;
u8 mask;
- local_irq_save(flags);
-
mask = inb(EISA_INT1_MASK);
mask &= ~((u8) (1 << irq));
outb(mask, EISA_INT1_MASK);
-
- local_irq_restore(flags);
}
static unsigned int startup_eisa1_irq(unsigned int irq)
@@ -130,8 +125,6 @@ static void disable_eisa1_irq(unsigned int irq)
outb(mask, EISA_INT1_MASK);
}
-#define shutdown_eisa1_irq disable_eisa1_irq
-
static void mask_and_ack_eisa1_irq(unsigned int irq)
{
disable_eisa1_irq(irq);
@@ -148,25 +141,20 @@ static void end_eisa1_irq(unsigned int irq)
static struct irq_chip ip22_eisa1_irq_type = {
.typename = "IP22 EISA",
.startup = startup_eisa1_irq,
- .shutdown = shutdown_eisa1_irq,
- .enable = enable_eisa1_irq,
- .disable = disable_eisa1_irq,
.ack = mask_and_ack_eisa1_irq,
+ .mask = disable_eisa1_irq,
+ .mask_ack = mask_and_ack_eisa1_irq,
+ .unmask = enable_eisa1_irq,
.end = end_eisa1_irq,
};
static void enable_eisa2_irq(unsigned int irq)
{
- unsigned long flags;
u8 mask;
- local_irq_save(flags);
-
mask = inb(EISA_INT2_MASK);
mask &= ~((u8) (1 << (irq - 8)));
outb(mask, EISA_INT2_MASK);
-
- local_irq_restore(flags);
}
static unsigned int startup_eisa2_irq(unsigned int irq)
@@ -192,8 +180,6 @@ static void disable_eisa2_irq(unsigned int irq)
outb(mask, EISA_INT2_MASK);
}
-#define shutdown_eisa2_irq disable_eisa2_irq
-
static void mask_and_ack_eisa2_irq(unsigned int irq)
{
disable_eisa2_irq(irq);
@@ -210,10 +196,10 @@ static void end_eisa2_irq(unsigned int irq)
static struct irq_chip ip22_eisa2_irq_type = {
.typename = "IP22 EISA",
.startup = startup_eisa2_irq,
- .shutdown = shutdown_eisa2_irq,
- .enable = enable_eisa2_irq,
- .disable = disable_eisa2_irq,
.ack = mask_and_ack_eisa2_irq,
+ .mask = disable_eisa2_irq,
+ .mask_ack = mask_and_ack_eisa2_irq,
+ .unmask = enable_eisa2_irq,
.end = end_eisa2_irq,
};
@@ -275,13 +261,10 @@ int __init ip22_eisa_init(void)
outb(0, EISA_DMA2_WRITE_SINGLE);
for (i = SGINT_EISA; i < (SGINT_EISA + EISA_MAX_IRQ); i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = 0;
- irq_desc[i].depth = 1;
if (i < (SGINT_EISA + 8))
- irq_desc[i].chip = &ip22_eisa1_irq_type;
+ set_irq_chip(i, &ip22_eisa1_irq_type);
else
- irq_desc[i].chip = &ip22_eisa2_irq_type;
+ set_irq_chip(i, &ip22_eisa2_irq_type);
}
/* Cannot use request_irq because of kmalloc not being ready at such
diff --git a/arch/mips/sgi-ip22/ip22-int.c b/arch/mips/sgi-ip22/ip22-int.c
index af518898eaa1..c7b138053159 100644
--- a/arch/mips/sgi-ip22/ip22-int.c
+++ b/arch/mips/sgi-ip22/ip22-int.c
@@ -40,34 +40,17 @@ extern int ip22_eisa_init(void);
static void enable_local0_irq(unsigned int irq)
{
- unsigned long flags;
-
- local_irq_save(flags);
/* don't allow mappable interrupt to be enabled from setup_irq,
* we have our own way to do so */
if (irq != SGI_MAP_0_IRQ)
sgint->imask0 |= (1 << (irq - SGINT_LOCAL0));
- local_irq_restore(flags);
-}
-
-static unsigned int startup_local0_irq(unsigned int irq)
-{
- enable_local0_irq(irq);
- return 0; /* Never anything pending */
}
static void disable_local0_irq(unsigned int irq)
{
- unsigned long flags;
-
- local_irq_save(flags);
sgint->imask0 &= ~(1 << (irq - SGINT_LOCAL0));
- local_irq_restore(flags);
}
-#define shutdown_local0_irq disable_local0_irq
-#define mask_and_ack_local0_irq disable_local0_irq
-
static void end_local0_irq (unsigned int irq)
{
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
@@ -76,44 +59,26 @@ static void end_local0_irq (unsigned int irq)
static struct irq_chip ip22_local0_irq_type = {
.typename = "IP22 local 0",
- .startup = startup_local0_irq,
- .shutdown = shutdown_local0_irq,
- .enable = enable_local0_irq,
- .disable = disable_local0_irq,
- .ack = mask_and_ack_local0_irq,
+ .ack = disable_local0_irq,
+ .mask = disable_local0_irq,
+ .mask_ack = disable_local0_irq,
+ .unmask = enable_local0_irq,
.end = end_local0_irq,
};
static void enable_local1_irq(unsigned int irq)
{
- unsigned long flags;
-
- local_irq_save(flags);
/* don't allow mappable interrupt to be enabled from setup_irq,
* we have our own way to do so */
if (irq != SGI_MAP_1_IRQ)
sgint->imask1 |= (1 << (irq - SGINT_LOCAL1));
- local_irq_restore(flags);
-}
-
-static unsigned int startup_local1_irq(unsigned int irq)
-{
- enable_local1_irq(irq);
- return 0; /* Never anything pending */
}
void disable_local1_irq(unsigned int irq)
{
- unsigned long flags;
-
- local_irq_save(flags);
sgint->imask1 &= ~(1 << (irq - SGINT_LOCAL1));
- local_irq_restore(flags);
}
-#define shutdown_local1_irq disable_local1_irq
-#define mask_and_ack_local1_irq disable_local1_irq
-
static void end_local1_irq (unsigned int irq)
{
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
@@ -122,44 +87,26 @@ static void end_local1_irq (unsigned int irq)
static struct irq_chip ip22_local1_irq_type = {
.typename = "IP22 local 1",
- .startup = startup_local1_irq,
- .shutdown = shutdown_local1_irq,
- .enable = enable_local1_irq,
- .disable = disable_local1_irq,
- .ack = mask_and_ack_local1_irq,
+ .ack = disable_local1_irq,
+ .mask = disable_local1_irq,
+ .mask_ack = disable_local1_irq,
+ .unmask = enable_local1_irq,
.end = end_local1_irq,
};
static void enable_local2_irq(unsigned int irq)
{
- unsigned long flags;
-
- local_irq_save(flags);
sgint->imask0 |= (1 << (SGI_MAP_0_IRQ - SGINT_LOCAL0));
sgint->cmeimask0 |= (1 << (irq - SGINT_LOCAL2));
- local_irq_restore(flags);
-}
-
-static unsigned int startup_local2_irq(unsigned int irq)
-{
- enable_local2_irq(irq);
- return 0; /* Never anything pending */
}
void disable_local2_irq(unsigned int irq)
{
- unsigned long flags;
-
- local_irq_save(flags);
sgint->cmeimask0 &= ~(1 << (irq - SGINT_LOCAL2));
if (!sgint->cmeimask0)
sgint->imask0 &= ~(1 << (SGI_MAP_0_IRQ - SGINT_LOCAL0));
- local_irq_restore(flags);
}
-#define shutdown_local2_irq disable_local2_irq
-#define mask_and_ack_local2_irq disable_local2_irq
-
static void end_local2_irq (unsigned int irq)
{
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
@@ -168,44 +115,26 @@ static void end_local2_irq (unsigned int irq)
static struct irq_chip ip22_local2_irq_type = {
.typename = "IP22 local 2",
- .startup = startup_local2_irq,
- .shutdown = shutdown_local2_irq,
- .enable = enable_local2_irq,
- .disable = disable_local2_irq,
- .ack = mask_and_ack_local2_irq,
+ .ack = disable_local2_irq,
+ .mask = disable_local2_irq,
+ .mask_ack = disable_local2_irq,
+ .unmask = enable_local2_irq,
.end = end_local2_irq,
};
static void enable_local3_irq(unsigned int irq)
{
- unsigned long flags;
-
- local_irq_save(flags);
sgint->imask1 |= (1 << (SGI_MAP_1_IRQ - SGINT_LOCAL1));
sgint->cmeimask1 |= (1 << (irq - SGINT_LOCAL3));
- local_irq_restore(flags);
-}
-
-static unsigned int startup_local3_irq(unsigned int irq)
-{
- enable_local3_irq(irq);
- return 0; /* Never anything pending */
}
void disable_local3_irq(unsigned int irq)
{
- unsigned long flags;
-
- local_irq_save(flags);
sgint->cmeimask1 &= ~(1 << (irq - SGINT_LOCAL3));
if (!sgint->cmeimask1)
sgint->imask1 &= ~(1 << (SGI_MAP_1_IRQ - SGINT_LOCAL1));
- local_irq_restore(flags);
}
-#define shutdown_local3_irq disable_local3_irq
-#define mask_and_ack_local3_irq disable_local3_irq
-
static void end_local3_irq (unsigned int irq)
{
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
@@ -214,11 +143,10 @@ static void end_local3_irq (unsigned int irq)
static struct irq_chip ip22_local3_irq_type = {
.typename = "IP22 local 3",
- .startup = startup_local3_irq,
- .shutdown = shutdown_local3_irq,
- .enable = enable_local3_irq,
- .disable = disable_local3_irq,
- .ack = mask_and_ack_local3_irq,
+ .ack = disable_local3_irq,
+ .mask = disable_local3_irq,
+ .mask_ack = disable_local3_irq,
+ .unmask = enable_local3_irq,
.end = end_local3_irq,
};
@@ -430,10 +358,7 @@ void __init arch_init_irq(void)
else
handler = &ip22_local3_irq_type;
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = 0;
- irq_desc[i].depth = 1;
- irq_desc[i].chip = handler;
+ set_irq_chip_and_handler(i, handler, handle_level_irq);
}
/* vector handler. this register the IRQ as non-sharable */
diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c
index 270ecd3e6b4a..5f8835b4e84a 100644
--- a/arch/mips/sgi-ip27/ip27-irq.c
+++ b/arch/mips/sgi-ip27/ip27-irq.c
@@ -332,11 +332,6 @@ static inline void disable_bridge_irq(unsigned int irq)
intr_disconnect_level(cpu, swlevel);
}
-static void mask_and_ack_bridge_irq(unsigned int irq)
-{
- disable_bridge_irq(irq);
-}
-
static void end_bridge_irq(unsigned int irq)
{
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)) &&
@@ -348,18 +343,16 @@ static struct irq_chip bridge_irq_type = {
.typename = "bridge",
.startup = startup_bridge_irq,
.shutdown = shutdown_bridge_irq,
- .enable = enable_bridge_irq,
- .disable = disable_bridge_irq,
- .ack = mask_and_ack_bridge_irq,
+ .ack = disable_bridge_irq,
+ .mask = disable_bridge_irq,
+ .mask_ack = disable_bridge_irq,
+ .unmask = enable_bridge_irq,
.end = end_bridge_irq,
};
void __devinit register_bridge_irq(unsigned int irq)
{
- irq_desc[irq].status = IRQ_DISABLED;
- irq_desc[irq].action = 0;
- irq_desc[irq].depth = 1;
- irq_desc[irq].chip = &bridge_irq_type;
+ set_irq_chip_and_handler(irq, &bridge_irq_type, handle_level_irq);
}
int __devinit request_bridge_irq(struct bridge_controller *bc)
diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c
index 5e82a268e3c9..7d361726bbfb 100644
--- a/arch/mips/sgi-ip27/ip27-timer.c
+++ b/arch/mips/sgi-ip27/ip27-timer.c
@@ -172,15 +172,6 @@ static __init unsigned long get_m48t35_time(void)
return mktime(year, month, date, hour, min, sec);
}
-static unsigned int startup_rt_irq(unsigned int irq)
-{
- return 0;
-}
-
-static void shutdown_rt_irq(unsigned int irq)
-{
-}
-
static void enable_rt_irq(unsigned int irq)
{
}
@@ -189,21 +180,17 @@ static void disable_rt_irq(unsigned int irq)
{
}
-static void mask_and_ack_rt(unsigned int irq)
-{
-}
-
static void end_rt_irq(unsigned int irq)
{
}
static struct irq_chip rt_irq_type = {
.typename = "SN HUB RT timer",
- .startup = startup_rt_irq,
- .shutdown = shutdown_rt_irq,
- .enable = enable_rt_irq,
- .disable = disable_rt_irq,
- .ack = mask_and_ack_rt,
+ .ack = disable_rt_irq,
+ .mask = disable_rt_irq,
+ .mask_ack = disable_rt_irq,
+ .unmask = enable_rt_irq,
+ .eoi = enable_rt_irq,
.end = end_rt_irq,
};
@@ -221,10 +208,7 @@ void __init plat_timer_setup(struct irqaction *irq)
if (irqno < 0)
panic("Can't allocate interrupt number for timer interrupt");
- irq_desc[irqno].status = IRQ_DISABLED;
- irq_desc[irqno].action = NULL;
- irq_desc[irqno].depth = 1;
- irq_desc[irqno].chip = &rt_irq_type;
+ set_irq_chip_and_handler(irqno, &rt_irq_type, handle_percpu_irq);
/* over-write the handler, we use our own way */
irq->handler = no_action;
@@ -239,14 +223,14 @@ void __init plat_timer_setup(struct irqaction *irq)
setup_irq(irqno, &rt_irqaction);
}
-static unsigned int ip27_hpt_read(void)
+static cycle_t ip27_hpt_read(void)
{
return REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT);
}
void __init ip27_time_init(void)
{
- mips_hpt_read = ip27_hpt_read;
+ clocksource_mips.read = ip27_hpt_read;
mips_hpt_frequency = CYCLES_PER_SEC;
xtime.tv_sec = get_m48t35_time();
xtime.tv_nsec = 0;
diff --git a/arch/mips/sgi-ip32/ip32-irq.c b/arch/mips/sgi-ip32/ip32-irq.c
index c9acadd0846b..ae063864c026 100644
--- a/arch/mips/sgi-ip32/ip32-irq.c
+++ b/arch/mips/sgi-ip32/ip32-irq.c
@@ -113,12 +113,6 @@ static void inline flush_mace_bus(void)
* is quite different anyway.
*/
-/*
- * IRQ spinlock - Ralf says not to disable CPU interrupts,
- * and I think he knows better.
- */
-static DEFINE_SPINLOCK(ip32_irq_lock);
-
/* Some initial interrupts to set up */
extern irqreturn_t crime_memerr_intr(int irq, void *dev_id);
extern irqreturn_t crime_cpuerr_intr(int irq, void *dev_id);
@@ -138,12 +132,6 @@ static void enable_cpu_irq(unsigned int irq)
set_c0_status(STATUSF_IP7);
}
-static unsigned int startup_cpu_irq(unsigned int irq)
-{
- enable_cpu_irq(irq);
- return 0;
-}
-
static void disable_cpu_irq(unsigned int irq)
{
clear_c0_status(STATUSF_IP7);
@@ -155,16 +143,12 @@ static void end_cpu_irq(unsigned int irq)
enable_cpu_irq (irq);
}
-#define shutdown_cpu_irq disable_cpu_irq
-#define mask_and_ack_cpu_irq disable_cpu_irq
-
static struct irq_chip ip32_cpu_interrupt = {
.typename = "IP32 CPU",
- .startup = startup_cpu_irq,
- .shutdown = shutdown_cpu_irq,
- .enable = enable_cpu_irq,
- .disable = disable_cpu_irq,
- .ack = mask_and_ack_cpu_irq,
+ .ack = disable_cpu_irq,
+ .mask = disable_cpu_irq,
+ .mask_ack = disable_cpu_irq,
+ .unmask = enable_cpu_irq,
.end = end_cpu_irq,
};
@@ -177,45 +161,27 @@ static uint64_t crime_mask;
static void enable_crime_irq(unsigned int irq)
{
- unsigned long flags;
-
- spin_lock_irqsave(&ip32_irq_lock, flags);
crime_mask |= 1 << (irq - 1);
crime->imask = crime_mask;
- spin_unlock_irqrestore(&ip32_irq_lock, flags);
-}
-
-static unsigned int startup_crime_irq(unsigned int irq)
-{
- enable_crime_irq(irq);
- return 0; /* This is probably not right; we could have pending irqs */
}
static void disable_crime_irq(unsigned int irq)
{
- unsigned long flags;
-
- spin_lock_irqsave(&ip32_irq_lock, flags);
crime_mask &= ~(1 << (irq - 1));
crime->imask = crime_mask;
flush_crime_bus();
- spin_unlock_irqrestore(&ip32_irq_lock, flags);
}
static void mask_and_ack_crime_irq(unsigned int irq)
{
- unsigned long flags;
-
/* Edge triggered interrupts must be cleared. */
if ((irq >= CRIME_GBE0_IRQ && irq <= CRIME_GBE3_IRQ)
|| (irq >= CRIME_RE_EMPTY_E_IRQ && irq <= CRIME_RE_IDLE_E_IRQ)
|| (irq >= CRIME_SOFT0_IRQ && irq <= CRIME_SOFT2_IRQ)) {
uint64_t crime_int;
- spin_lock_irqsave(&ip32_irq_lock, flags);
crime_int = crime->hard_int;
crime_int &= ~(1 << (irq - 1));
crime->hard_int = crime_int;
- spin_unlock_irqrestore(&ip32_irq_lock, flags);
}
disable_crime_irq(irq);
}
@@ -226,15 +192,12 @@ static void end_crime_irq(unsigned int irq)
enable_crime_irq(irq);
}
-#define shutdown_crime_irq disable_crime_irq
-
static struct irq_chip ip32_crime_interrupt = {
.typename = "IP32 CRIME",
- .startup = startup_crime_irq,
- .shutdown = shutdown_crime_irq,
- .enable = enable_crime_irq,
- .disable = disable_crime_irq,
.ack = mask_and_ack_crime_irq,
+ .mask = disable_crime_irq,
+ .mask_ack = mask_and_ack_crime_irq,
+ .unmask = enable_crime_irq,
.end = end_crime_irq,
};
@@ -248,34 +211,20 @@ static unsigned long macepci_mask;
static void enable_macepci_irq(unsigned int irq)
{
- unsigned long flags;
-
- spin_lock_irqsave(&ip32_irq_lock, flags);
macepci_mask |= MACEPCI_CONTROL_INT(irq - 9);
mace->pci.control = macepci_mask;
crime_mask |= 1 << (irq - 1);
crime->imask = crime_mask;
- spin_unlock_irqrestore(&ip32_irq_lock, flags);
-}
-
-static unsigned int startup_macepci_irq(unsigned int irq)
-{
- enable_macepci_irq (irq);
- return 0;
}
static void disable_macepci_irq(unsigned int irq)
{
- unsigned long flags;
-
- spin_lock_irqsave(&ip32_irq_lock, flags);
crime_mask &= ~(1 << (irq - 1));
crime->imask = crime_mask;
flush_crime_bus();
macepci_mask &= ~MACEPCI_CONTROL_INT(irq - 9);
mace->pci.control = macepci_mask;
flush_mace_bus();
- spin_unlock_irqrestore(&ip32_irq_lock, flags);
}
static void end_macepci_irq(unsigned int irq)
@@ -284,16 +233,12 @@ static void end_macepci_irq(unsigned int irq)
enable_macepci_irq(irq);
}
-#define shutdown_macepci_irq disable_macepci_irq
-#define mask_and_ack_macepci_irq disable_macepci_irq
-
static struct irq_chip ip32_macepci_interrupt = {
.typename = "IP32 MACE PCI",
- .startup = startup_macepci_irq,
- .shutdown = shutdown_macepci_irq,
- .enable = enable_macepci_irq,
- .disable = disable_macepci_irq,
- .ack = mask_and_ack_macepci_irq,
+ .ack = disable_macepci_irq,
+ .mask = disable_macepci_irq,
+ .mask_ack = disable_macepci_irq,
+ .unmask = enable_macepci_irq,
.end = end_macepci_irq,
};
@@ -339,7 +284,6 @@ static unsigned long maceisa_mask;
static void enable_maceisa_irq (unsigned int irq)
{
unsigned int crime_int = 0;
- unsigned long flags;
DBG ("maceisa enable: %u\n", irq);
@@ -355,26 +299,16 @@ static void enable_maceisa_irq (unsigned int irq)
break;
}
DBG ("crime_int %08x enabled\n", crime_int);
- spin_lock_irqsave(&ip32_irq_lock, flags);
crime_mask |= crime_int;
crime->imask = crime_mask;
maceisa_mask |= 1 << (irq - 33);
mace->perif.ctrl.imask = maceisa_mask;
- spin_unlock_irqrestore(&ip32_irq_lock, flags);
-}
-
-static unsigned int startup_maceisa_irq(unsigned int irq)
-{
- enable_maceisa_irq(irq);
- return 0;
}
static void disable_maceisa_irq(unsigned int irq)
{
unsigned int crime_int = 0;
- unsigned long flags;
- spin_lock_irqsave(&ip32_irq_lock, flags);
maceisa_mask &= ~(1 << (irq - 33));
if(!(maceisa_mask & MACEISA_AUDIO_INT))
crime_int |= MACE_AUDIO_INT;
@@ -387,23 +321,20 @@ static void disable_maceisa_irq(unsigned int irq)
flush_crime_bus();
mace->perif.ctrl.imask = maceisa_mask;
flush_mace_bus();
- spin_unlock_irqrestore(&ip32_irq_lock, flags);
}
static void mask_and_ack_maceisa_irq(unsigned int irq)
{
- unsigned long mace_int, flags;
+ unsigned long mace_int;
switch (irq) {
case MACEISA_PARALLEL_IRQ:
case MACEISA_SERIAL1_TDMAPR_IRQ:
case MACEISA_SERIAL2_TDMAPR_IRQ:
/* edge triggered */
- spin_lock_irqsave(&ip32_irq_lock, flags);
mace_int = mace->perif.ctrl.istat;
mace_int &= ~(1 << (irq - 33));
mace->perif.ctrl.istat = mace_int;
- spin_unlock_irqrestore(&ip32_irq_lock, flags);
break;
}
disable_maceisa_irq(irq);
@@ -415,15 +346,12 @@ static void end_maceisa_irq(unsigned irq)
enable_maceisa_irq(irq);
}
-#define shutdown_maceisa_irq disable_maceisa_irq
-
static struct irq_chip ip32_maceisa_interrupt = {
.typename = "IP32 MACE ISA",
- .startup = startup_maceisa_irq,
- .shutdown = shutdown_maceisa_irq,
- .enable = enable_maceisa_irq,
- .disable = disable_maceisa_irq,
.ack = mask_and_ack_maceisa_irq,
+ .mask = disable_maceisa_irq,
+ .mask_ack = mask_and_ack_maceisa_irq,
+ .unmask = enable_maceisa_irq,
.end = end_maceisa_irq,
};
@@ -433,29 +361,15 @@ static struct irq_chip ip32_maceisa_interrupt = {
static void enable_mace_irq(unsigned int irq)
{
- unsigned long flags;
-
- spin_lock_irqsave(&ip32_irq_lock, flags);
crime_mask |= 1 << (irq - 1);
crime->imask = crime_mask;
- spin_unlock_irqrestore(&ip32_irq_lock, flags);
-}
-
-static unsigned int startup_mace_irq(unsigned int irq)
-{
- enable_mace_irq(irq);
- return 0;
}
static void disable_mace_irq(unsigned int irq)
{
- unsigned long flags;
-
- spin_lock_irqsave(&ip32_irq_lock, flags);
crime_mask &= ~(1 << (irq - 1));
crime->imask = crime_mask;
flush_crime_bus();
- spin_unlock_irqrestore(&ip32_irq_lock, flags);
}
static void end_mace_irq(unsigned int irq)
@@ -464,16 +378,12 @@ static void end_mace_irq(unsigned int irq)
enable_mace_irq(irq);
}
-#define shutdown_mace_irq disable_mace_irq
-#define mask_and_ack_mace_irq disable_mace_irq
-
static struct irq_chip ip32_mace_interrupt = {
.typename = "IP32 MACE",
- .startup = startup_mace_irq,
- .shutdown = shutdown_mace_irq,
- .enable = enable_mace_irq,
- .disable = disable_mace_irq,
- .ack = mask_and_ack_mace_irq,
+ .ack = disable_mace_irq,
+ .mask = disable_mace_irq,
+ .mask_ack = disable_mace_irq,
+ .unmask = enable_mace_irq,
.end = end_mace_irq,
};
@@ -586,10 +496,7 @@ void __init arch_init_irq(void)
else
controller = &ip32_maceisa_interrupt;
- irq_desc[irq].status = IRQ_DISABLED;
- irq_desc[irq].action = 0;
- irq_desc[irq].depth = 0;
- irq_desc[irq].chip = controller;
+ set_irq_chip(irq, controller);
}
setup_irq(CRIME_MEMERR_IRQ, &memerr_irq);
setup_irq(CRIME_CPUERR_IRQ, &cpuerr_irq);
diff --git a/arch/mips/sibyte/bcm1480/irq.c b/arch/mips/sibyte/bcm1480/irq.c
index 8b1f41484923..2e8f6b2e2420 100644
--- a/arch/mips/sibyte/bcm1480/irq.c
+++ b/arch/mips/sibyte/bcm1480/irq.c
@@ -45,11 +45,9 @@
*/
-#define shutdown_bcm1480_irq disable_bcm1480_irq
static void end_bcm1480_irq(unsigned int irq);
static void enable_bcm1480_irq(unsigned int irq);
static void disable_bcm1480_irq(unsigned int irq);
-static unsigned int startup_bcm1480_irq(unsigned int irq);
static void ack_bcm1480_irq(unsigned int irq);
#ifdef CONFIG_SMP
static void bcm1480_set_affinity(unsigned int irq, cpumask_t mask);
@@ -85,11 +83,10 @@ extern char sb1250_duart_present[];
static struct irq_chip bcm1480_irq_type = {
.typename = "BCM1480-IMR",
- .startup = startup_bcm1480_irq,
- .shutdown = shutdown_bcm1480_irq,
- .enable = enable_bcm1480_irq,
- .disable = disable_bcm1480_irq,
.ack = ack_bcm1480_irq,
+ .mask = disable_bcm1480_irq,
+ .mask_ack = ack_bcm1480_irq,
+ .unmask = enable_bcm1480_irq,
.end = end_bcm1480_irq,
#ifdef CONFIG_SMP
.set_affinity = bcm1480_set_affinity
@@ -188,14 +185,6 @@ static void bcm1480_set_affinity(unsigned int irq, cpumask_t mask)
/*****************************************************************************/
-static unsigned int startup_bcm1480_irq(unsigned int irq)
-{
- bcm1480_unmask_irq(bcm1480_irq_owner[irq], irq);
-
- return 0; /* never anything pending */
-}
-
-
static void disable_bcm1480_irq(unsigned int irq)
{
bcm1480_mask_irq(bcm1480_irq_owner[irq], irq);
@@ -270,16 +259,9 @@ void __init init_bcm1480_irqs(void)
{
int i;
- for (i = 0; i < NR_IRQS; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = 0;
- irq_desc[i].depth = 1;
- if (i < BCM1480_NR_IRQS) {
- irq_desc[i].chip = &bcm1480_irq_type;
- bcm1480_irq_owner[i] = 0;
- } else {
- irq_desc[i].chip = &no_irq_chip;
- }
+ for (i = 0; i < BCM1480_NR_IRQS; i++) {
+ set_irq_chip(i, &bcm1480_irq_type);
+ bcm1480_irq_owner[i] = 0;
}
}
diff --git a/arch/mips/sibyte/bcm1480/time.c b/arch/mips/sibyte/bcm1480/time.c
index e136bde5248e..6f3f71bf4244 100644
--- a/arch/mips/sibyte/bcm1480/time.c
+++ b/arch/mips/sibyte/bcm1480/time.c
@@ -94,8 +94,6 @@ void bcm1480_time_init(void)
*/
}
-#include <asm/sibyte/sb1250.h>
-
void bcm1480_timer_interrupt(void)
{
int cpu = smp_processor_id();
@@ -119,7 +117,7 @@ void bcm1480_timer_interrupt(void)
}
}
-static unsigned int bcm1480_hpt_read(void)
+static cycle_t bcm1480_hpt_read(void)
{
/* We assume this function is called xtime_lock held. */
unsigned long count =
@@ -129,6 +127,6 @@ static unsigned int bcm1480_hpt_read(void)
void __init bcm1480_hpt_setup(void)
{
- mips_hpt_read = bcm1480_hpt_read;
+ clocksource_mips.read = bcm1480_hpt_read;
mips_hpt_frequency = BCM1480_HPT_VALUE;
}
diff --git a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c
index d5d26770daf6..82ce7533053f 100644
--- a/arch/mips/sibyte/sb1250/irq.c
+++ b/arch/mips/sibyte/sb1250/irq.c
@@ -44,11 +44,9 @@
*/
-#define shutdown_sb1250_irq disable_sb1250_irq
static void end_sb1250_irq(unsigned int irq);
static void enable_sb1250_irq(unsigned int irq);
static void disable_sb1250_irq(unsigned int irq);
-static unsigned int startup_sb1250_irq(unsigned int irq);
static void ack_sb1250_irq(unsigned int irq);
#ifdef CONFIG_SMP
static void sb1250_set_affinity(unsigned int irq, cpumask_t mask);
@@ -70,11 +68,10 @@ extern char sb1250_duart_present[];
static struct irq_chip sb1250_irq_type = {
.typename = "SB1250-IMR",
- .startup = startup_sb1250_irq,
- .shutdown = shutdown_sb1250_irq,
- .enable = enable_sb1250_irq,
- .disable = disable_sb1250_irq,
.ack = ack_sb1250_irq,
+ .mask = disable_sb1250_irq,
+ .mask_ack = ack_sb1250_irq,
+ .unmask = enable_sb1250_irq,
.end = end_sb1250_irq,
#ifdef CONFIG_SMP
.set_affinity = sb1250_set_affinity
@@ -163,14 +160,6 @@ static void sb1250_set_affinity(unsigned int irq, cpumask_t mask)
/*****************************************************************************/
-static unsigned int startup_sb1250_irq(unsigned int irq)
-{
- sb1250_unmask_irq(sb1250_irq_owner[irq], irq);
-
- return 0; /* never anything pending */
-}
-
-
static void disable_sb1250_irq(unsigned int irq)
{
sb1250_mask_irq(sb1250_irq_owner[irq], irq);
@@ -239,16 +228,9 @@ void __init init_sb1250_irqs(void)
{
int i;
- for (i = 0; i < NR_IRQS; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = 0;
- irq_desc[i].depth = 1;
- if (i < SB1250_NR_IRQS) {
- irq_desc[i].chip = &sb1250_irq_type;
- sb1250_irq_owner[i] = 0;
- } else {
- irq_desc[i].chip = &no_irq_chip;
- }
+ for (i = 0; i < SB1250_NR_IRQS; i++) {
+ set_irq_chip(i, &sb1250_irq_type);
+ sb1250_irq_owner[i] = 0;
}
}
diff --git a/arch/mips/sibyte/sb1250/time.c b/arch/mips/sibyte/sb1250/time.c
index bcb74f2c1948..2efffe15ff23 100644
--- a/arch/mips/sibyte/sb1250/time.c
+++ b/arch/mips/sibyte/sb1250/time.c
@@ -51,7 +51,7 @@
extern int sb1250_steal_irq(int irq);
-static unsigned int sb1250_hpt_read(void);
+static cycle_t sb1250_hpt_read(void);
void __init sb1250_hpt_setup(void)
{
@@ -66,8 +66,8 @@ void __init sb1250_hpt_setup(void)
IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CFG)));
mips_hpt_frequency = V_SCD_TIMER_FREQ;
- mips_hpt_read = sb1250_hpt_read;
- mips_hpt_mask = M_SCD_TIMER_INIT;
+ clocksource_mips.read = sb1250_hpt_read;
+ clocksource_mips.mask = M_SCD_TIMER_INIT;
}
}
@@ -143,7 +143,7 @@ void sb1250_timer_interrupt(void)
* The HPT is free running from SB1250_HPT_VALUE down to 0 then starts over
* again.
*/
-static unsigned int sb1250_hpt_read(void)
+static cycle_t sb1250_hpt_read(void)
{
unsigned int count;
diff --git a/arch/mips/sni/irq.c b/arch/mips/sni/irq.c
index 48fb74a7aaec..8511bcc6d99d 100644
--- a/arch/mips/sni/irq.c
+++ b/arch/mips/sni/irq.c
@@ -11,44 +11,25 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/kernel.h>
-#include <linux/spinlock.h>
#include <asm/i8259.h>
#include <asm/io.h>
#include <asm/sni.h>
-DEFINE_SPINLOCK(pciasic_lock);
-
static void enable_pciasic_irq(unsigned int irq)
{
unsigned int mask = 1 << (irq - PCIMT_IRQ_INT2);
- unsigned long flags;
- spin_lock_irqsave(&pciasic_lock, flags);
*(volatile u8 *) PCIMT_IRQSEL |= mask;
- spin_unlock_irqrestore(&pciasic_lock, flags);
-}
-
-static unsigned int startup_pciasic_irq(unsigned int irq)
-{
- enable_pciasic_irq(irq);
- return 0; /* never anything pending */
}
-#define shutdown_pciasic_irq disable_pciasic_irq
-
void disable_pciasic_irq(unsigned int irq)
{
unsigned int mask = ~(1 << (irq - PCIMT_IRQ_INT2));
- unsigned long flags;
- spin_lock_irqsave(&pciasic_lock, flags);
*(volatile u8 *) PCIMT_IRQSEL &= mask;
- spin_unlock_irqrestore(&pciasic_lock, flags);
}
-#define mask_and_ack_pciasic_irq disable_pciasic_irq
-
static void end_pciasic_irq(unsigned int irq)
{
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
@@ -57,11 +38,10 @@ static void end_pciasic_irq(unsigned int irq)
static struct irq_chip pciasic_irq_type = {
.typename = "ASIC-PCI",
- .startup = startup_pciasic_irq,
- .shutdown = shutdown_pciasic_irq,
- .enable = enable_pciasic_irq,
- .disable = disable_pciasic_irq,
- .ack = mask_and_ack_pciasic_irq,
+ .ack = disable_pciasic_irq,
+ .mask = disable_pciasic_irq,
+ .mask_ack = disable_pciasic_irq,
+ .unmask = enable_pciasic_irq,
.end = end_pciasic_irq,
};
@@ -178,12 +158,8 @@ asmlinkage void plat_irq_dispatch(void)
void __init init_pciasic(void)
{
- unsigned long flags;
-
- spin_lock_irqsave(&pciasic_lock, flags);
* (volatile u8 *) PCIMT_IRQSEL =
IT_EISA | IT_INTA | IT_INTB | IT_INTC | IT_INTD;
- spin_unlock_irqrestore(&pciasic_lock, flags);
}
/*
@@ -199,12 +175,8 @@ void __init arch_init_irq(void)
init_pciasic();
/* Actually we've got more interrupts to handle ... */
- for (i = PCIMT_IRQ_INT2; i <= PCIMT_IRQ_ETHERNET; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = 0;
- irq_desc[i].depth = 1;
- irq_desc[i].chip = &pciasic_irq_type;
- }
+ for (i = PCIMT_IRQ_INT2; i <= PCIMT_IRQ_ETHERNET; i++)
+ set_irq_chip(i, &pciasic_irq_type);
change_c0_status(ST0_IM, IE_IRQ1|IE_IRQ2|IE_IRQ3|IE_IRQ4);
}
diff --git a/arch/mips/tx4927/common/tx4927_irq.c b/arch/mips/tx4927/common/tx4927_irq.c
index 8266a88a3f88..21873de49aa8 100644
--- a/arch/mips/tx4927/common/tx4927_irq.c
+++ b/arch/mips/tx4927/common/tx4927_irq.c
@@ -64,19 +64,13 @@
#define TX4927_IRQ_NEST4 ( 1 << 9 )
#define TX4927_IRQ_CP0_INIT ( 1 << 10 )
-#define TX4927_IRQ_CP0_STARTUP ( 1 << 11 )
-#define TX4927_IRQ_CP0_SHUTDOWN ( 1 << 12 )
#define TX4927_IRQ_CP0_ENABLE ( 1 << 13 )
#define TX4927_IRQ_CP0_DISABLE ( 1 << 14 )
-#define TX4927_IRQ_CP0_MASK ( 1 << 15 )
#define TX4927_IRQ_CP0_ENDIRQ ( 1 << 16 )
#define TX4927_IRQ_PIC_INIT ( 1 << 20 )
-#define TX4927_IRQ_PIC_STARTUP ( 1 << 21 )
-#define TX4927_IRQ_PIC_SHUTDOWN ( 1 << 22 )
#define TX4927_IRQ_PIC_ENABLE ( 1 << 23 )
#define TX4927_IRQ_PIC_DISABLE ( 1 << 24 )
-#define TX4927_IRQ_PIC_MASK ( 1 << 25 )
#define TX4927_IRQ_PIC_ENDIRQ ( 1 << 26 )
#define TX4927_IRQ_ALL 0xffffffff
@@ -87,18 +81,12 @@ static const u32 tx4927_irq_debug_flag = (TX4927_IRQ_NONE
| TX4927_IRQ_INFO
| TX4927_IRQ_WARN | TX4927_IRQ_EROR
// | TX4927_IRQ_CP0_INIT
-// | TX4927_IRQ_CP0_STARTUP
-// | TX4927_IRQ_CP0_SHUTDOWN
// | TX4927_IRQ_CP0_ENABLE
// | TX4927_IRQ_CP0_DISABLE
-// | TX4927_IRQ_CP0_MASK
// | TX4927_IRQ_CP0_ENDIRQ
// | TX4927_IRQ_PIC_INIT
-// | TX4927_IRQ_PIC_STARTUP
-// | TX4927_IRQ_PIC_SHUTDOWN
// | TX4927_IRQ_PIC_ENABLE
// | TX4927_IRQ_PIC_DISABLE
-// | TX4927_IRQ_PIC_MASK
// | TX4927_IRQ_PIC_ENDIRQ
// | TX4927_IRQ_INIT
// | TX4927_IRQ_NEST1
@@ -124,49 +112,36 @@ static const u32 tx4927_irq_debug_flag = (TX4927_IRQ_NONE
* Forwad definitions for all pic's
*/
-static unsigned int tx4927_irq_cp0_startup(unsigned int irq);
-static void tx4927_irq_cp0_shutdown(unsigned int irq);
static void tx4927_irq_cp0_enable(unsigned int irq);
static void tx4927_irq_cp0_disable(unsigned int irq);
-static void tx4927_irq_cp0_mask_and_ack(unsigned int irq);
static void tx4927_irq_cp0_end(unsigned int irq);
-static unsigned int tx4927_irq_pic_startup(unsigned int irq);
-static void tx4927_irq_pic_shutdown(unsigned int irq);
static void tx4927_irq_pic_enable(unsigned int irq);
static void tx4927_irq_pic_disable(unsigned int irq);
-static void tx4927_irq_pic_mask_and_ack(unsigned int irq);
static void tx4927_irq_pic_end(unsigned int irq);
/*
* Kernel structs for all pic's
*/
-static DEFINE_SPINLOCK(tx4927_cp0_lock);
-static DEFINE_SPINLOCK(tx4927_pic_lock);
-
#define TX4927_CP0_NAME "TX4927-CP0"
static struct irq_chip tx4927_irq_cp0_type = {
.typename = TX4927_CP0_NAME,
- .startup = tx4927_irq_cp0_startup,
- .shutdown = tx4927_irq_cp0_shutdown,
- .enable = tx4927_irq_cp0_enable,
- .disable = tx4927_irq_cp0_disable,
- .ack = tx4927_irq_cp0_mask_and_ack,
+ .ack = tx4927_irq_cp0_disable,
+ .mask = tx4927_irq_cp0_disable,
+ .mask_ack = tx4927_irq_cp0_disable,
+ .unmask = tx4927_irq_cp0_enable,
.end = tx4927_irq_cp0_end,
- .set_affinity = NULL
};
#define TX4927_PIC_NAME "TX4927-PIC"
static struct irq_chip tx4927_irq_pic_type = {
.typename = TX4927_PIC_NAME,
- .startup = tx4927_irq_pic_startup,
- .shutdown = tx4927_irq_pic_shutdown,
- .enable = tx4927_irq_pic_enable,
- .disable = tx4927_irq_pic_disable,
- .ack = tx4927_irq_pic_mask_and_ack,
+ .ack = tx4927_irq_pic_disable,
+ .mask = tx4927_irq_pic_disable,
+ .mask_ack = tx4927_irq_pic_disable,
+ .unmask = tx4927_irq_pic_enable,
.end = tx4927_irq_pic_end,
- .set_affinity = NULL
};
#define TX4927_PIC_ACTION(s) { no_action, 0, CPU_MASK_NONE, s, NULL, NULL }
@@ -211,8 +186,6 @@ tx4927_irq_cp0_modify(unsigned cp0_reg, unsigned clr_bits, unsigned set_bits)
break;
}
}
-
- return;
}
static void __init tx4927_irq_cp0_init(void)
@@ -222,71 +195,23 @@ static void __init tx4927_irq_cp0_init(void)
TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_INIT, "beg=%d end=%d\n",
TX4927_IRQ_CP0_BEG, TX4927_IRQ_CP0_END);
- for (i = TX4927_IRQ_CP0_BEG; i <= TX4927_IRQ_CP0_END; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = 0;
- irq_desc[i].depth = 1;
- irq_desc[i].chip = &tx4927_irq_cp0_type;
- }
-
- return;
-}
-
-static unsigned int tx4927_irq_cp0_startup(unsigned int irq)
-{
- TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_STARTUP, "irq=%d \n", irq);
-
- tx4927_irq_cp0_enable(irq);
-
- return (0);
-}
-
-static void tx4927_irq_cp0_shutdown(unsigned int irq)
-{
- TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_SHUTDOWN, "irq=%d \n", irq);
-
- tx4927_irq_cp0_disable(irq);
-
- return;
+ for (i = TX4927_IRQ_CP0_BEG; i <= TX4927_IRQ_CP0_END; i++)
+ set_irq_chip_and_handler(i, &tx4927_irq_cp0_type,
+ handle_level_irq);
}
static void tx4927_irq_cp0_enable(unsigned int irq)
{
- unsigned long flags;
-
TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_ENABLE, "irq=%d \n", irq);
- spin_lock_irqsave(&tx4927_cp0_lock, flags);
-
tx4927_irq_cp0_modify(CCP0_STATUS, 0, tx4927_irq_cp0_mask(irq));
-
- spin_unlock_irqrestore(&tx4927_cp0_lock, flags);
-
- return;
}
static void tx4927_irq_cp0_disable(unsigned int irq)
{
- unsigned long flags;
-
TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_DISABLE, "irq=%d \n", irq);
- spin_lock_irqsave(&tx4927_cp0_lock, flags);
-
tx4927_irq_cp0_modify(CCP0_STATUS, tx4927_irq_cp0_mask(irq), 0);
-
- spin_unlock_irqrestore(&tx4927_cp0_lock, flags);
-
- return;
-}
-
-static void tx4927_irq_cp0_mask_and_ack(unsigned int irq)
-{
- TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_MASK, "irq=%d \n", irq);
-
- tx4927_irq_cp0_disable(irq);
-
- return;
}
static void tx4927_irq_cp0_end(unsigned int irq)
@@ -296,8 +221,6 @@ static void tx4927_irq_cp0_end(unsigned int irq)
if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
tx4927_irq_cp0_enable(irq);
}
-
- return;
}
/*
@@ -418,94 +341,39 @@ static void tx4927_irq_pic_modify(unsigned pic_reg, unsigned clr_bits,
val &= (~clr_bits);
val |= (set_bits);
TX4927_WR(pic_reg, val);
-
- return;
}
static void __init tx4927_irq_pic_init(void)
{
- unsigned long flags;
int i;
TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_INIT, "beg=%d end=%d\n",
TX4927_IRQ_PIC_BEG, TX4927_IRQ_PIC_END);
- for (i = TX4927_IRQ_PIC_BEG; i <= TX4927_IRQ_PIC_END; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = 0;
- irq_desc[i].depth = 2;
- irq_desc[i].chip = &tx4927_irq_pic_type;
- }
+ for (i = TX4927_IRQ_PIC_BEG; i <= TX4927_IRQ_PIC_END; i++)
+ set_irq_chip_and_handler(i, &tx4927_irq_pic_type,
+ handle_level_irq);
setup_irq(TX4927_IRQ_NEST_PIC_ON_CP0, &tx4927_irq_pic_action);
- spin_lock_irqsave(&tx4927_pic_lock, flags);
-
TX4927_WR(0xff1ff640, 0x6); /* irq level mask -- only accept hightest */
TX4927_WR(0xff1ff600, TX4927_RD(0xff1ff600) | 0x1); /* irq enable */
-
- spin_unlock_irqrestore(&tx4927_pic_lock, flags);
-
- return;
-}
-
-static unsigned int tx4927_irq_pic_startup(unsigned int irq)
-{
- TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_STARTUP, "irq=%d\n", irq);
-
- tx4927_irq_pic_enable(irq);
-
- return (0);
-}
-
-static void tx4927_irq_pic_shutdown(unsigned int irq)
-{
- TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_SHUTDOWN, "irq=%d\n", irq);
-
- tx4927_irq_pic_disable(irq);
-
- return;
}
static void tx4927_irq_pic_enable(unsigned int irq)
{
- unsigned long flags;
-
TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_ENABLE, "irq=%d\n", irq);
- spin_lock_irqsave(&tx4927_pic_lock, flags);
-
tx4927_irq_pic_modify(tx4927_irq_pic_addr(irq), 0,
tx4927_irq_pic_mask(irq));
-
- spin_unlock_irqrestore(&tx4927_pic_lock, flags);
-
- return;
}
static void tx4927_irq_pic_disable(unsigned int irq)
{
- unsigned long flags;
-
TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_DISABLE, "irq=%d\n", irq);
- spin_lock_irqsave(&tx4927_pic_lock, flags);
-
tx4927_irq_pic_modify(tx4927_irq_pic_addr(irq),
tx4927_irq_pic_mask(irq), 0);
-
- spin_unlock_irqrestore(&tx4927_pic_lock, flags);
-
- return;
-}
-
-static void tx4927_irq_pic_mask_and_ack(unsigned int irq)
-{
- TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_MASK, "irq=%d\n", irq);
-
- tx4927_irq_pic_disable(irq);
-
- return;
}
static void tx4927_irq_pic_end(unsigned int irq)
@@ -515,8 +383,6 @@ static void tx4927_irq_pic_end(unsigned int irq)
if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
tx4927_irq_pic_enable(irq);
}
-
- return;
}
/*
@@ -533,8 +399,6 @@ void __init tx4927_irq_init(void)
tx4927_irq_pic_init();
TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "+\n");
-
- return;
}
static int tx4927_irq_nested(void)
diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c
index 0c3c3f668230..34cdb2a240e9 100644
--- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c
+++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c
@@ -151,16 +151,11 @@ JP7 is not bus master -- do NOT use -- only 4 pci bus master's allowed -- SouthB
#define TOSHIBA_RBTX4927_IRQ_EROR ( 1 << 2 )
#define TOSHIBA_RBTX4927_IRQ_IOC_INIT ( 1 << 10 )
-#define TOSHIBA_RBTX4927_IRQ_IOC_STARTUP ( 1 << 11 )
-#define TOSHIBA_RBTX4927_IRQ_IOC_SHUTDOWN ( 1 << 12 )
#define TOSHIBA_RBTX4927_IRQ_IOC_ENABLE ( 1 << 13 )
#define TOSHIBA_RBTX4927_IRQ_IOC_DISABLE ( 1 << 14 )
-#define TOSHIBA_RBTX4927_IRQ_IOC_MASK ( 1 << 15 )
#define TOSHIBA_RBTX4927_IRQ_IOC_ENDIRQ ( 1 << 16 )
#define TOSHIBA_RBTX4927_IRQ_ISA_INIT ( 1 << 20 )
-#define TOSHIBA_RBTX4927_IRQ_ISA_STARTUP ( 1 << 21 )
-#define TOSHIBA_RBTX4927_IRQ_ISA_SHUTDOWN ( 1 << 22 )
#define TOSHIBA_RBTX4927_IRQ_ISA_ENABLE ( 1 << 23 )
#define TOSHIBA_RBTX4927_IRQ_ISA_DISABLE ( 1 << 24 )
#define TOSHIBA_RBTX4927_IRQ_ISA_MASK ( 1 << 25 )
@@ -175,15 +170,10 @@ static const u32 toshiba_rbtx4927_irq_debug_flag =
(TOSHIBA_RBTX4927_IRQ_NONE | TOSHIBA_RBTX4927_IRQ_INFO |
TOSHIBA_RBTX4927_IRQ_WARN | TOSHIBA_RBTX4927_IRQ_EROR
// | TOSHIBA_RBTX4927_IRQ_IOC_INIT
-// | TOSHIBA_RBTX4927_IRQ_IOC_STARTUP
-// | TOSHIBA_RBTX4927_IRQ_IOC_SHUTDOWN
// | TOSHIBA_RBTX4927_IRQ_IOC_ENABLE
// | TOSHIBA_RBTX4927_IRQ_IOC_DISABLE
-// | TOSHIBA_RBTX4927_IRQ_IOC_MASK
// | TOSHIBA_RBTX4927_IRQ_IOC_ENDIRQ
// | TOSHIBA_RBTX4927_IRQ_ISA_INIT
-// | TOSHIBA_RBTX4927_IRQ_ISA_STARTUP
-// | TOSHIBA_RBTX4927_IRQ_ISA_SHUTDOWN
// | TOSHIBA_RBTX4927_IRQ_ISA_ENABLE
// | TOSHIBA_RBTX4927_IRQ_ISA_DISABLE
// | TOSHIBA_RBTX4927_IRQ_ISA_MASK
@@ -231,35 +221,25 @@ extern void disable_8259A_irq(unsigned int irq);
extern void mask_and_ack_8259A(unsigned int irq);
#endif
-static unsigned int toshiba_rbtx4927_irq_ioc_startup(unsigned int irq);
-static void toshiba_rbtx4927_irq_ioc_shutdown(unsigned int irq);
static void toshiba_rbtx4927_irq_ioc_enable(unsigned int irq);
static void toshiba_rbtx4927_irq_ioc_disable(unsigned int irq);
-static void toshiba_rbtx4927_irq_ioc_mask_and_ack(unsigned int irq);
static void toshiba_rbtx4927_irq_ioc_end(unsigned int irq);
#ifdef CONFIG_TOSHIBA_FPCIB0
-static unsigned int toshiba_rbtx4927_irq_isa_startup(unsigned int irq);
-static void toshiba_rbtx4927_irq_isa_shutdown(unsigned int irq);
static void toshiba_rbtx4927_irq_isa_enable(unsigned int irq);
static void toshiba_rbtx4927_irq_isa_disable(unsigned int irq);
static void toshiba_rbtx4927_irq_isa_mask_and_ack(unsigned int irq);
static void toshiba_rbtx4927_irq_isa_end(unsigned int irq);
#endif
-static DEFINE_SPINLOCK(toshiba_rbtx4927_ioc_lock);
-
-
#define TOSHIBA_RBTX4927_IOC_NAME "RBTX4927-IOC"
static struct irq_chip toshiba_rbtx4927_irq_ioc_type = {
.typename = TOSHIBA_RBTX4927_IOC_NAME,
- .startup = toshiba_rbtx4927_irq_ioc_startup,
- .shutdown = toshiba_rbtx4927_irq_ioc_shutdown,
- .enable = toshiba_rbtx4927_irq_ioc_enable,
- .disable = toshiba_rbtx4927_irq_ioc_disable,
- .ack = toshiba_rbtx4927_irq_ioc_mask_and_ack,
+ .ack = toshiba_rbtx4927_irq_ioc_disable,
+ .mask = toshiba_rbtx4927_irq_ioc_disable,
+ .mask_ack = toshiba_rbtx4927_irq_ioc_disable,
+ .unmask = toshiba_rbtx4927_irq_ioc_enable,
.end = toshiba_rbtx4927_irq_ioc_end,
- .set_affinity = NULL
};
#define TOSHIBA_RBTX4927_IOC_INTR_ENAB 0xbc002000
#define TOSHIBA_RBTX4927_IOC_INTR_STAT 0xbc002006
@@ -269,13 +249,11 @@ static struct irq_chip toshiba_rbtx4927_irq_ioc_type = {
#define TOSHIBA_RBTX4927_ISA_NAME "RBTX4927-ISA"
static struct irq_chip toshiba_rbtx4927_irq_isa_type = {
.typename = TOSHIBA_RBTX4927_ISA_NAME,
- .startup = toshiba_rbtx4927_irq_isa_startup,
- .shutdown = toshiba_rbtx4927_irq_isa_shutdown,
- .enable = toshiba_rbtx4927_irq_isa_enable,
- .disable = toshiba_rbtx4927_irq_isa_disable,
.ack = toshiba_rbtx4927_irq_isa_mask_and_ack,
+ .mask = toshiba_rbtx4927_irq_isa_disable,
+ .mask_ack = toshiba_rbtx4927_irq_isa_mask_and_ack,
+ .unmask = toshiba_rbtx4927_irq_isa_enable,
.end = toshiba_rbtx4927_irq_isa_end,
- .set_affinity = NULL
};
#endif
@@ -363,58 +341,16 @@ static void __init toshiba_rbtx4927_irq_ioc_init(void)
TOSHIBA_RBTX4927_IRQ_IOC_END);
for (i = TOSHIBA_RBTX4927_IRQ_IOC_BEG;
- i <= TOSHIBA_RBTX4927_IRQ_IOC_END; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = 0;
- irq_desc[i].depth = 3;
- irq_desc[i].chip = &toshiba_rbtx4927_irq_ioc_type;
- }
+ i <= TOSHIBA_RBTX4927_IRQ_IOC_END; i++)
+ set_irq_chip_and_handler(i, &toshiba_rbtx4927_irq_ioc_type,
+ handle_level_irq);
setup_irq(TOSHIBA_RBTX4927_IRQ_NEST_IOC_ON_PIC,
&toshiba_rbtx4927_irq_ioc_action);
-
- return;
}
-static unsigned int toshiba_rbtx4927_irq_ioc_startup(unsigned int irq)
-{
- TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_IOC_STARTUP,
- "irq=%d\n", irq);
-
- if (irq < TOSHIBA_RBTX4927_IRQ_IOC_BEG
- || irq > TOSHIBA_RBTX4927_IRQ_IOC_END) {
- TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR,
- "bad irq=%d\n", irq);
- panic("\n");
- }
-
- toshiba_rbtx4927_irq_ioc_enable(irq);
-
- return (0);
-}
-
-
-static void toshiba_rbtx4927_irq_ioc_shutdown(unsigned int irq)
-{
- TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_IOC_SHUTDOWN,
- "irq=%d\n", irq);
-
- if (irq < TOSHIBA_RBTX4927_IRQ_IOC_BEG
- || irq > TOSHIBA_RBTX4927_IRQ_IOC_END) {
- TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR,
- "bad irq=%d\n", irq);
- panic("\n");
- }
-
- toshiba_rbtx4927_irq_ioc_disable(irq);
-
- return;
-}
-
-
static void toshiba_rbtx4927_irq_ioc_enable(unsigned int irq)
{
- unsigned long flags;
volatile unsigned char v;
TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_IOC_ENABLE,
@@ -427,21 +363,14 @@ static void toshiba_rbtx4927_irq_ioc_enable(unsigned int irq)
panic("\n");
}
- spin_lock_irqsave(&toshiba_rbtx4927_ioc_lock, flags);
-
v = TX4927_RD08(TOSHIBA_RBTX4927_IOC_INTR_ENAB);
v |= (1 << (irq - TOSHIBA_RBTX4927_IRQ_IOC_BEG));
TOSHIBA_RBTX4927_WR08(TOSHIBA_RBTX4927_IOC_INTR_ENAB, v);
-
- spin_unlock_irqrestore(&toshiba_rbtx4927_ioc_lock, flags);
-
- return;
}
static void toshiba_rbtx4927_irq_ioc_disable(unsigned int irq)
{
- unsigned long flags;
volatile unsigned char v;
TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_IOC_DISABLE,
@@ -454,36 +383,11 @@ static void toshiba_rbtx4927_irq_ioc_disable(unsigned int irq)
panic("\n");
}
- spin_lock_irqsave(&toshiba_rbtx4927_ioc_lock, flags);
-
v = TX4927_RD08(TOSHIBA_RBTX4927_IOC_INTR_ENAB);
v &= ~(1 << (irq - TOSHIBA_RBTX4927_IRQ_IOC_BEG));
TOSHIBA_RBTX4927_WR08(TOSHIBA_RBTX4927_IOC_INTR_ENAB, v);
-
- spin_unlock_irqrestore(&toshiba_rbtx4927_ioc_lock, flags);
-
- return;
}
-
-static void toshiba_rbtx4927_irq_ioc_mask_and_ack(unsigned int irq)
-{
- TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_IOC_MASK,
- "irq=%d\n", irq);
-
- if (irq < TOSHIBA_RBTX4927_IRQ_IOC_BEG
- || irq > TOSHIBA_RBTX4927_IRQ_IOC_END) {
- TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR,
- "bad irq=%d\n", irq);
- panic("\n");
- }
-
- toshiba_rbtx4927_irq_ioc_disable(irq);
-
- return;
-}
-
-
static void toshiba_rbtx4927_irq_ioc_end(unsigned int irq)
{
TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_IOC_ENDIRQ,
@@ -499,8 +403,6 @@ static void toshiba_rbtx4927_irq_ioc_end(unsigned int irq)
if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
toshiba_rbtx4927_irq_ioc_enable(irq);
}
-
- return;
}
@@ -520,13 +422,8 @@ static void __init toshiba_rbtx4927_irq_isa_init(void)
TOSHIBA_RBTX4927_IRQ_ISA_END);
for (i = TOSHIBA_RBTX4927_IRQ_ISA_BEG;
- i <= TOSHIBA_RBTX4927_IRQ_ISA_END; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = 0;
- irq_desc[i].depth =
- ((i < TOSHIBA_RBTX4927_IRQ_ISA_MID) ? (4) : (5));
- irq_desc[i].chip = &toshiba_rbtx4927_irq_isa_type;
- }
+ i <= TOSHIBA_RBTX4927_IRQ_ISA_END; i++)
+ set_irq_chip(i, &toshiba_rbtx4927_irq_isa_type);
setup_irq(TOSHIBA_RBTX4927_IRQ_NEST_ISA_ON_IOC,
&toshiba_rbtx4927_irq_isa_master);
@@ -536,48 +433,6 @@ static void __init toshiba_rbtx4927_irq_isa_init(void)
/* make sure we are looking at IRR (not ISR) */
outb(0x0A, 0x20);
outb(0x0A, 0xA0);
-
- return;
-}
-#endif
-
-
-#ifdef CONFIG_TOSHIBA_FPCIB0
-static unsigned int toshiba_rbtx4927_irq_isa_startup(unsigned int irq)
-{
- TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_ISA_STARTUP,
- "irq=%d\n", irq);
-
- if (irq < TOSHIBA_RBTX4927_IRQ_ISA_BEG
- || irq > TOSHIBA_RBTX4927_IRQ_ISA_END) {
- TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR,
- "bad irq=%d\n", irq);
- panic("\n");
- }
-
- toshiba_rbtx4927_irq_isa_enable(irq);
-
- return (0);
-}
-#endif
-
-
-#ifdef CONFIG_TOSHIBA_FPCIB0
-static void toshiba_rbtx4927_irq_isa_shutdown(unsigned int irq)
-{
- TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_ISA_SHUTDOWN,
- "irq=%d\n", irq);
-
- if (irq < TOSHIBA_RBTX4927_IRQ_ISA_BEG
- || irq > TOSHIBA_RBTX4927_IRQ_ISA_END) {
- TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR,
- "bad irq=%d\n", irq);
- panic("\n");
- }
-
- toshiba_rbtx4927_irq_isa_disable(irq);
-
- return;
}
#endif
@@ -596,8 +451,6 @@ static void toshiba_rbtx4927_irq_isa_enable(unsigned int irq)
}
enable_8259A_irq(irq);
-
- return;
}
#endif
@@ -616,8 +469,6 @@ static void toshiba_rbtx4927_irq_isa_disable(unsigned int irq)
}
disable_8259A_irq(irq);
-
- return;
}
#endif
@@ -636,8 +487,6 @@ static void toshiba_rbtx4927_irq_isa_mask_and_ack(unsigned int irq)
}
mask_and_ack_8259A(irq);
-
- return;
}
#endif
@@ -658,8 +507,6 @@ static void toshiba_rbtx4927_irq_isa_end(unsigned int irq)
if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
toshiba_rbtx4927_irq_isa_enable(irq);
}
-
- return;
}
#endif
@@ -668,8 +515,6 @@ void __init arch_init_irq(void)
{
extern void tx4927_irq_init(void);
- local_irq_disable();
-
tx4927_irq_init();
toshiba_rbtx4927_irq_ioc_init();
#ifdef CONFIG_TOSHIBA_FPCIB0
@@ -681,8 +526,6 @@ void __init arch_init_irq(void)
#endif
wbflush();
-
- return;
}
void toshiba_rbtx4927_irq_dump(char *key)
@@ -715,7 +558,6 @@ void toshiba_rbtx4927_irq_dump(char *key)
}
}
#endif
- return;
}
void toshiba_rbtx4927_irq_dump_pics(char *s)
@@ -780,6 +622,4 @@ void toshiba_rbtx4927_irq_dump_pics(char *s)
level5_s);
TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_INFO, "[%s]\n",
s);
-
- return;
}
diff --git a/arch/mips/tx4938/common/irq.c b/arch/mips/tx4938/common/irq.c
index 77fe2454f5b9..42e127683ae9 100644
--- a/arch/mips/tx4938/common/irq.c
+++ b/arch/mips/tx4938/common/irq.c
@@ -37,48 +37,36 @@
/* Forwad definitions for all pic's */
/**********************************************************************************/
-static unsigned int tx4938_irq_cp0_startup(unsigned int irq);
-static void tx4938_irq_cp0_shutdown(unsigned int irq);
static void tx4938_irq_cp0_enable(unsigned int irq);
static void tx4938_irq_cp0_disable(unsigned int irq);
-static void tx4938_irq_cp0_mask_and_ack(unsigned int irq);
static void tx4938_irq_cp0_end(unsigned int irq);
-static unsigned int tx4938_irq_pic_startup(unsigned int irq);
-static void tx4938_irq_pic_shutdown(unsigned int irq);
static void tx4938_irq_pic_enable(unsigned int irq);
static void tx4938_irq_pic_disable(unsigned int irq);
-static void tx4938_irq_pic_mask_and_ack(unsigned int irq);
static void tx4938_irq_pic_end(unsigned int irq);
/**********************************************************************************/
/* Kernel structs for all pic's */
/**********************************************************************************/
-DEFINE_SPINLOCK(tx4938_cp0_lock);
-DEFINE_SPINLOCK(tx4938_pic_lock);
#define TX4938_CP0_NAME "TX4938-CP0"
static struct irq_chip tx4938_irq_cp0_type = {
.typename = TX4938_CP0_NAME,
- .startup = tx4938_irq_cp0_startup,
- .shutdown = tx4938_irq_cp0_shutdown,
- .enable = tx4938_irq_cp0_enable,
- .disable = tx4938_irq_cp0_disable,
- .ack = tx4938_irq_cp0_mask_and_ack,
+ .ack = tx4938_irq_cp0_disable,
+ .mask = tx4938_irq_cp0_disable,
+ .mask_ack = tx4938_irq_cp0_disable,
+ .unmask = tx4938_irq_cp0_enable,
.end = tx4938_irq_cp0_end,
- .set_affinity = NULL
};
#define TX4938_PIC_NAME "TX4938-PIC"
static struct irq_chip tx4938_irq_pic_type = {
.typename = TX4938_PIC_NAME,
- .startup = tx4938_irq_pic_startup,
- .shutdown = tx4938_irq_pic_shutdown,
- .enable = tx4938_irq_pic_enable,
- .disable = tx4938_irq_pic_disable,
- .ack = tx4938_irq_pic_mask_and_ack,
+ .ack = tx4938_irq_pic_disable,
+ .mask = tx4938_irq_pic_disable,
+ .mask_ack = tx4938_irq_pic_disable,
+ .unmask = tx4938_irq_pic_enable,
.end = tx4938_irq_pic_end,
- .set_affinity = NULL
};
static struct irqaction tx4938_irq_pic_action = {
@@ -99,56 +87,21 @@ tx4938_irq_cp0_init(void)
{
int i;
- for (i = TX4938_IRQ_CP0_BEG; i <= TX4938_IRQ_CP0_END; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = 0;
- irq_desc[i].depth = 1;
- irq_desc[i].chip = &tx4938_irq_cp0_type;
- }
-}
-
-static unsigned int
-tx4938_irq_cp0_startup(unsigned int irq)
-{
- tx4938_irq_cp0_enable(irq);
-
- return 0;
-}
-
-static void
-tx4938_irq_cp0_shutdown(unsigned int irq)
-{
- tx4938_irq_cp0_disable(irq);
+ for (i = TX4938_IRQ_CP0_BEG; i <= TX4938_IRQ_CP0_END; i++)
+ set_irq_chip_and_handler(i, &tx4938_irq_cp0_type,
+ handle_level_irq);
}
static void
tx4938_irq_cp0_enable(unsigned int irq)
{
- unsigned long flags;
-
- spin_lock_irqsave(&tx4938_cp0_lock, flags);
-
set_c0_status(tx4938_irq_cp0_mask(irq));
-
- spin_unlock_irqrestore(&tx4938_cp0_lock, flags);
}
static void
tx4938_irq_cp0_disable(unsigned int irq)
{
- unsigned long flags;
-
- spin_lock_irqsave(&tx4938_cp0_lock, flags);
-
clear_c0_status(tx4938_irq_cp0_mask(irq));
-
- spin_unlock_irqrestore(&tx4938_cp0_lock, flags);
-}
-
-static void
-tx4938_irq_cp0_mask_and_ack(unsigned int irq)
-{
- tx4938_irq_cp0_disable(irq);
}
static void
@@ -290,70 +243,30 @@ tx4938_irq_pic_modify(unsigned pic_reg, unsigned clr_bits, unsigned set_bits)
static void __init
tx4938_irq_pic_init(void)
{
- unsigned long flags;
int i;
- for (i = TX4938_IRQ_PIC_BEG; i <= TX4938_IRQ_PIC_END; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = 0;
- irq_desc[i].depth = 2;
- irq_desc[i].chip = &tx4938_irq_pic_type;
- }
+ for (i = TX4938_IRQ_PIC_BEG; i <= TX4938_IRQ_PIC_END; i++)
+ set_irq_chip_and_handler(i, &tx4938_irq_pic_type,
+ handle_level_irq);
setup_irq(TX4938_IRQ_NEST_PIC_ON_CP0, &tx4938_irq_pic_action);
- spin_lock_irqsave(&tx4938_pic_lock, flags);
-
TX4938_WR(0xff1ff640, 0x6); /* irq level mask -- only accept hightest */
TX4938_WR(0xff1ff600, TX4938_RD(0xff1ff600) | 0x1); /* irq enable */
-
- spin_unlock_irqrestore(&tx4938_pic_lock, flags);
-}
-
-static unsigned int
-tx4938_irq_pic_startup(unsigned int irq)
-{
- tx4938_irq_pic_enable(irq);
-
- return 0;
-}
-
-static void
-tx4938_irq_pic_shutdown(unsigned int irq)
-{
- tx4938_irq_pic_disable(irq);
}
static void
tx4938_irq_pic_enable(unsigned int irq)
{
- unsigned long flags;
-
- spin_lock_irqsave(&tx4938_pic_lock, flags);
-
tx4938_irq_pic_modify(tx4938_irq_pic_addr(irq), 0,
tx4938_irq_pic_mask(irq));
-
- spin_unlock_irqrestore(&tx4938_pic_lock, flags);
}
static void
tx4938_irq_pic_disable(unsigned int irq)
{
- unsigned long flags;
-
- spin_lock_irqsave(&tx4938_pic_lock, flags);
-
tx4938_irq_pic_modify(tx4938_irq_pic_addr(irq),
tx4938_irq_pic_mask(irq), 0);
-
- spin_unlock_irqrestore(&tx4938_pic_lock, flags);
-}
-
-static void
-tx4938_irq_pic_mask_and_ack(unsigned int irq)
-{
- tx4938_irq_pic_disable(irq);
}
static void
diff --git a/arch/mips/tx4938/common/setup.c b/arch/mips/tx4938/common/setup.c
index f415a1f18fba..dc87d92bb08d 100644
--- a/arch/mips/tx4938/common/setup.c
+++ b/arch/mips/tx4938/common/setup.c
@@ -31,7 +31,6 @@
#include <asm/mipsregs.h>
#include <asm/system.h>
#include <asm/time.h>
-#include <asm/time.h>
#include <asm/tx4938/rbtx4938.h>
extern void toshiba_rbtx4938_setup(void);
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/irq.c b/arch/mips/tx4938/toshiba_rbtx4938/irq.c
index 102e473c10a2..8c87a35f3068 100644
--- a/arch/mips/tx4938/toshiba_rbtx4938/irq.c
+++ b/arch/mips/tx4938/toshiba_rbtx4938/irq.c
@@ -87,25 +87,18 @@ IRQ Device
#include <linux/bootmem.h>
#include <asm/tx4938/rbtx4938.h>
-static unsigned int toshiba_rbtx4938_irq_ioc_startup(unsigned int irq);
-static void toshiba_rbtx4938_irq_ioc_shutdown(unsigned int irq);
static void toshiba_rbtx4938_irq_ioc_enable(unsigned int irq);
static void toshiba_rbtx4938_irq_ioc_disable(unsigned int irq);
-static void toshiba_rbtx4938_irq_ioc_mask_and_ack(unsigned int irq);
static void toshiba_rbtx4938_irq_ioc_end(unsigned int irq);
-DEFINE_SPINLOCK(toshiba_rbtx4938_ioc_lock);
-
#define TOSHIBA_RBTX4938_IOC_NAME "RBTX4938-IOC"
static struct irq_chip toshiba_rbtx4938_irq_ioc_type = {
.typename = TOSHIBA_RBTX4938_IOC_NAME,
- .startup = toshiba_rbtx4938_irq_ioc_startup,
- .shutdown = toshiba_rbtx4938_irq_ioc_shutdown,
- .enable = toshiba_rbtx4938_irq_ioc_enable,
- .disable = toshiba_rbtx4938_irq_ioc_disable,
- .ack = toshiba_rbtx4938_irq_ioc_mask_and_ack,
+ .ack = toshiba_rbtx4938_irq_ioc_disable,
+ .mask = toshiba_rbtx4938_irq_ioc_disable,
+ .mask_ack = toshiba_rbtx4938_irq_ioc_disable,
+ .unmask = toshiba_rbtx4938_irq_ioc_enable,
.end = toshiba_rbtx4938_irq_ioc_end,
- .set_affinity = NULL
};
#define TOSHIBA_RBTX4938_IOC_INTR_ENAB 0xb7f02000
@@ -142,69 +135,36 @@ toshiba_rbtx4938_irq_ioc_init(void)
int i;
for (i = TOSHIBA_RBTX4938_IRQ_IOC_BEG;
- i <= TOSHIBA_RBTX4938_IRQ_IOC_END; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = 0;
- irq_desc[i].depth = 3;
- irq_desc[i].chip = &toshiba_rbtx4938_irq_ioc_type;
- }
+ i <= TOSHIBA_RBTX4938_IRQ_IOC_END; i++)
+ set_irq_chip_and_handler(i, &toshiba_rbtx4938_irq_ioc_type,
+ handle_level_irq);
setup_irq(RBTX4938_IRQ_IOCINT,
&toshiba_rbtx4938_irq_ioc_action);
}
-static unsigned int
-toshiba_rbtx4938_irq_ioc_startup(unsigned int irq)
-{
- toshiba_rbtx4938_irq_ioc_enable(irq);
-
- return 0;
-}
-
-static void
-toshiba_rbtx4938_irq_ioc_shutdown(unsigned int irq)
-{
- toshiba_rbtx4938_irq_ioc_disable(irq);
-}
-
static void
toshiba_rbtx4938_irq_ioc_enable(unsigned int irq)
{
- unsigned long flags;
volatile unsigned char v;
- spin_lock_irqsave(&toshiba_rbtx4938_ioc_lock, flags);
-
v = TX4938_RD08(TOSHIBA_RBTX4938_IOC_INTR_ENAB);
v |= (1 << (irq - TOSHIBA_RBTX4938_IRQ_IOC_BEG));
TX4938_WR08(TOSHIBA_RBTX4938_IOC_INTR_ENAB, v);
mmiowb();
TX4938_RD08(TOSHIBA_RBTX4938_IOC_INTR_ENAB);
-
- spin_unlock_irqrestore(&toshiba_rbtx4938_ioc_lock, flags);
}
static void
toshiba_rbtx4938_irq_ioc_disable(unsigned int irq)
{
- unsigned long flags;
volatile unsigned char v;
- spin_lock_irqsave(&toshiba_rbtx4938_ioc_lock, flags);
-
v = TX4938_RD08(TOSHIBA_RBTX4938_IOC_INTR_ENAB);
v &= ~(1 << (irq - TOSHIBA_RBTX4938_IRQ_IOC_BEG));
TX4938_WR08(TOSHIBA_RBTX4938_IOC_INTR_ENAB, v);
mmiowb();
TX4938_RD08(TOSHIBA_RBTX4938_IOC_INTR_ENAB);
-
- spin_unlock_irqrestore(&toshiba_rbtx4938_ioc_lock, flags);
-}
-
-static void
-toshiba_rbtx4938_irq_ioc_mask_and_ack(unsigned int irq)
-{
- toshiba_rbtx4938_irq_ioc_disable(irq);
}
static void
diff --git a/arch/mips/vr41xx/common/icu.c b/arch/mips/vr41xx/common/icu.c
index c215c0d39fae..54b92a74c7ac 100644
--- a/arch/mips/vr41xx/common/icu.c
+++ b/arch/mips/vr41xx/common/icu.c
@@ -417,14 +417,7 @@ void vr41xx_disable_bcuint(void)
EXPORT_SYMBOL(vr41xx_disable_bcuint);
-static unsigned int startup_sysint1_irq(unsigned int irq)
-{
- icu1_set(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(irq));
-
- return 0; /* never anything pending */
-}
-
-static void shutdown_sysint1_irq(unsigned int irq)
+static void disable_sysint1_irq(unsigned int irq)
{
icu1_clear(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(irq));
}
@@ -434,9 +427,6 @@ static void enable_sysint1_irq(unsigned int irq)
icu1_set(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(irq));
}
-#define disable_sysint1_irq shutdown_sysint1_irq
-#define ack_sysint1_irq shutdown_sysint1_irq
-
static void end_sysint1_irq(unsigned int irq)
{
if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
@@ -445,22 +435,14 @@ static void end_sysint1_irq(unsigned int irq)
static struct irq_chip sysint1_irq_type = {
.typename = "SYSINT1",
- .startup = startup_sysint1_irq,
- .shutdown = shutdown_sysint1_irq,
- .enable = enable_sysint1_irq,
- .disable = disable_sysint1_irq,
- .ack = ack_sysint1_irq,
+ .ack = disable_sysint1_irq,
+ .mask = disable_sysint1_irq,
+ .mask_ack = disable_sysint1_irq,
+ .unmask = enable_sysint1_irq,
.end = end_sysint1_irq,
};
-static unsigned int startup_sysint2_irq(unsigned int irq)
-{
- icu2_set(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(irq));
-
- return 0; /* never anything pending */
-}
-
-static void shutdown_sysint2_irq(unsigned int irq)
+static void disable_sysint2_irq(unsigned int irq)
{
icu2_clear(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(irq));
}
@@ -470,9 +452,6 @@ static void enable_sysint2_irq(unsigned int irq)
icu2_set(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(irq));
}
-#define disable_sysint2_irq shutdown_sysint2_irq
-#define ack_sysint2_irq shutdown_sysint2_irq
-
static void end_sysint2_irq(unsigned int irq)
{
if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
@@ -481,11 +460,10 @@ static void end_sysint2_irq(unsigned int irq)
static struct irq_chip sysint2_irq_type = {
.typename = "SYSINT2",
- .startup = startup_sysint2_irq,
- .shutdown = shutdown_sysint2_irq,
- .enable = enable_sysint2_irq,
- .disable = disable_sysint2_irq,
- .ack = ack_sysint2_irq,
+ .ack = disable_sysint2_irq,
+ .mask = disable_sysint2_irq,
+ .mask_ack = disable_sysint2_irq,
+ .unmask = enable_sysint2_irq,
.end = end_sysint2_irq,
};
@@ -723,10 +701,12 @@ static int __init vr41xx_icu_init(void)
icu2_write(MGIUINTHREG, 0xffff);
for (i = SYSINT1_IRQ_BASE; i <= SYSINT1_IRQ_LAST; i++)
- irq_desc[i].chip = &sysint1_irq_type;
+ set_irq_chip_and_handler(i, &sysint1_irq_type,
+ handle_level_irq);
for (i = SYSINT2_IRQ_BASE; i <= SYSINT2_IRQ_LAST; i++)
- irq_desc[i].chip = &sysint2_irq_type;
+ set_irq_chip_and_handler(i, &sysint2_irq_type,
+ handle_level_irq);
cascade_irq(INT0_IRQ, icu_get_irq);
cascade_irq(INT1_IRQ, icu_get_irq);
diff --git a/arch/mips/vr41xx/nec-cmbvr4133/irq.c b/arch/mips/vr41xx/nec-cmbvr4133/irq.c
index 2483487344c2..a039bb7251ff 100644
--- a/arch/mips/vr41xx/nec-cmbvr4133/irq.c
+++ b/arch/mips/vr41xx/nec-cmbvr4133/irq.c
@@ -30,17 +30,6 @@ extern void init_8259A(int hoge);
extern int vr4133_rockhopper;
-static unsigned int startup_i8259_irq(unsigned int irq)
-{
- enable_8259A_irq(irq - I8259_IRQ_BASE);
- return 0;
-}
-
-static void shutdown_i8259_irq(unsigned int irq)
-{
- disable_8259A_irq(irq - I8259_IRQ_BASE);
-}
-
static void enable_i8259_irq(unsigned int irq)
{
enable_8259A_irq(irq - I8259_IRQ_BASE);
@@ -64,11 +53,10 @@ static void end_i8259_irq(unsigned int irq)
static struct irq_chip i8259_irq_type = {
.typename = "XT-PIC",
- .startup = startup_i8259_irq,
- .shutdown = shutdown_i8259_irq,
- .enable = enable_i8259_irq,
- .disable = disable_i8259_irq,
.ack = ack_i8259_irq,
+ .mask = disable_i8259_irq,
+ .mask_ack = ack_i8259_irq,
+ .unmask = enable_i8259_irq,
.end = end_i8259_irq,
};
@@ -104,7 +92,7 @@ void __init rockhopper_init_irq(void)
}
for (i = I8259_IRQ_BASE; i <= I8259_IRQ_LAST; i++)
- irq_desc[i].chip = &i8259_irq_type;
+ set_irq_chip(i, &i8259_irq_type);
setup_irq(I8259_SLAVE_IRQ, &i8259_slave_cascade);
diff --git a/arch/parisc/lib/checksum.c b/arch/parisc/lib/checksum.c
index 8a1e08068e7d..462696d30d3b 100644
--- a/arch/parisc/lib/checksum.c
+++ b/arch/parisc/lib/checksum.c
@@ -101,11 +101,14 @@ out:
/*
* computes a partial checksum, e.g. for TCP/UDP fragments
*/
-unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum)
+/*
+ * why bother folding?
+ */
+__wsum csum_partial(const void *buff, int len, __wsum sum)
{
unsigned int result = do_csum(buff, len);
addc(result, sum);
- return from32to16(result);
+ return (__force __wsum)from32to16(result);
}
EXPORT_SYMBOL(csum_partial);
@@ -113,8 +116,8 @@ EXPORT_SYMBOL(csum_partial);
/*
* copy while checksumming, otherwise like csum_partial
*/
-unsigned int csum_partial_copy_nocheck(const unsigned char *src, unsigned char *dst,
- int len, unsigned int sum)
+__wsum csum_partial_copy_nocheck(const void *src, void *dst,
+ int len, __wsum sum)
{
/*
* It's 2:30 am and I don't feel like doing it real ...
@@ -131,9 +134,9 @@ EXPORT_SYMBOL(csum_partial_copy_nocheck);
* Copy from userspace and compute checksum. If we catch an exception
* then zero the rest of the buffer.
*/
-unsigned int csum_partial_copy_from_user(const unsigned char __user *src,
- unsigned char *dst, int len,
- unsigned int sum, int *err_ptr)
+__wsum csum_partial_copy_from_user(const void __user *src,
+ void *dst, int len,
+ __wsum sum, int *err_ptr)
{
int missing;
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 0673dbedb241..116d7d3683ed 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -425,7 +425,7 @@ config PPC_MAPLE
default n
help
This option enables support for the Maple 970FX Evaluation Board.
- For more informations, refer to <http://www.970eval.com>
+ For more information, refer to <http://www.970eval.com>
config PPC_PASEMI
depends on PPC_MULTIPLATFORM && PPC64
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig
index 7edb6b461382..edcd5b875b66 100644
--- a/arch/powerpc/platforms/83xx/Kconfig
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -21,7 +21,7 @@ config MPC834x_SYS
Be aware that PCI buses can only function when SYS board is plugged
into the PIB (Platform IO Board) board from Freescale which provide
3 PCI slots. The PIBs PCI initialization is the bootloader's
- responsiblilty.
+ responsibility.
config MPC834x_ITX
bool "Freescale MPC834x ITX"
@@ -30,7 +30,7 @@ config MPC834x_ITX
This option enables support for the MPC 834x ITX evaluation board.
Be aware that PCI initialization is the bootloader's
- responsiblilty.
+ responsibility.
config MPC8360E_PB
bool "Freescale MPC8360E PB"
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c
index 9923adc5248e..257dc9068468 100644
--- a/arch/powerpc/platforms/powermac/pci.c
+++ b/arch/powerpc/platforms/powermac/pci.c
@@ -48,7 +48,6 @@ static struct pci_controller *u3_ht;
static int has_second_ohare;
#endif /* CONFIG_PPC64 */
-extern u8 pci_cache_line_size;
extern int pcibios_assign_bus_offset;
struct device_node *k2_skiplist[2];
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index 077711e63104..ef018e25fb07 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -724,7 +724,7 @@ config MPC834x_SYS
Be aware that PCI buses can only function when SYS board is plugged
into the PIB (Platform IO Board) board from Freescale which provide
3 PCI slots. The PIBs PCI initialization is the bootloader's
- responsiblilty.
+ responsibility.
config EV64360
bool "Marvell-EV64360BP"
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 6a461d4caeff..bffc7e176970 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -217,7 +217,7 @@ config SH_SHMIN
bool "SHMIN"
select CPU_SUBTYPE_SH7706
help
- Select SHMIN if configureing for the SHMIN board
+ Select SHMIN if configuring for the SHMIN board.
config SH_UNKNOWN
bool "BareCPU"
diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c
index 9daad70bc305..8a2fd19dc9eb 100644
--- a/arch/sh/kernel/sh_ksyms.c
+++ b/arch/sh/kernel/sh_ksyms.c
@@ -18,7 +18,6 @@
#include <asm/delay.h>
#include <asm/tlbflush.h>
#include <asm/cacheflush.h>
-#include <asm/checksum.h>
extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
extern struct hw_interrupt_type no_irq_type;
diff --git a/arch/sh64/kernel/sh_ksyms.c b/arch/sh64/kernel/sh_ksyms.c
index 4b2df7247b59..7aa4b4f7bc5e 100644
--- a/arch/sh64/kernel/sh_ksyms.c
+++ b/arch/sh64/kernel/sh_ksyms.c
@@ -38,7 +38,7 @@ EXPORT_SYMBOL(disable_irq);
EXPORT_SYMBOL(kernel_thread);
/* Networking helper routines. */
-EXPORT_SYMBOL(csum_partial_copy);
+EXPORT_SYMBOL(csum_partial_copy_nocheck);
EXPORT_SYMBOL(strstr);
diff --git a/arch/sh64/lib/c-checksum.c b/arch/sh64/lib/c-checksum.c
index 0e8a742abf8c..4b2676380deb 100644
--- a/arch/sh64/lib/c-checksum.c
+++ b/arch/sh64/lib/c-checksum.c
@@ -118,24 +118,24 @@ static unsigned long do_csum(const unsigned char *buff, int len)
/* computes the checksum of a memory block at buff, length len,
and adds in "sum" (32-bit) */
-unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum)
+__wsum csum_partial(const void *buff, int len, __wsum sum)
{
unsigned long long result = do_csum(buff, len);
/* add in old sum, and carry.. */
- result += sum;
+ result += (__force u32)sum;
/* 32+c bits -> 32 bits */
result = (result & 0xffffffff) + (result >> 32);
pr_debug("csum_partial, buff %p len %d sum 0x%x result=0x%016Lx\n",
buff, len, sum, result);
- return result;
+ return (__force __wsum)result;
}
/* Copy while checksumming, otherwise like csum_partial. */
-unsigned int
-csum_partial_copy(const unsigned char *src, unsigned char *dst, int len, unsigned int sum)
+__wsum
+csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
{
sum = csum_partial(src, len, sum);
memcpy(dst, src, len);
@@ -145,9 +145,9 @@ csum_partial_copy(const unsigned char *src, unsigned char *dst, int len, unsigne
/* Copy from userspace and compute checksum. If we catch an exception
then zero the rest of the buffer. */
-unsigned int
-csum_partial_copy_from_user(const unsigned char *src, unsigned char *dst, int len,
- unsigned int sum, int *err_ptr)
+__wsum
+csum_partial_copy_from_user(const void __user *src, void *dst, int len,
+ __wsum sum, int *err_ptr)
{
int missing;
@@ -166,9 +166,9 @@ csum_partial_copy_from_user(const unsigned char *src, unsigned char *dst, int le
}
/* Copy to userspace and compute checksum. */
-unsigned int
+__wsum
csum_partial_copy_to_user(const unsigned char *src, unsigned char *dst, int len,
- unsigned int sum, int *err_ptr)
+ __wsum sum, int *err_ptr)
{
sum = csum_partial(src, len, sum);
@@ -182,28 +182,24 @@ csum_partial_copy_to_user(const unsigned char *src, unsigned char *dst, int len,
* This is a version of ip_compute_csum() optimized for IP headers,
* which always checksum on 4 octet boundaries.
*/
-unsigned short ip_fast_csum(unsigned char *iph, unsigned int ihl)
+__sum16 ip_fast_csum(const void *iph, unsigned int ihl)
{
pr_debug("ip_fast_csum %p,%d\n", iph, ihl);
- return ~do_csum(iph, ihl * 4);
+ return (__force __sum16)~do_csum(iph, ihl * 4);
}
-unsigned int csum_tcpudp_nofold(unsigned long saddr,
- unsigned long daddr,
+__wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
unsigned short len,
- unsigned short proto, unsigned int sum)
+ unsigned short proto, __wsum sum)
{
unsigned long long result;
pr_debug("ntohs(0x%x)=0x%x\n", 0xdead, ntohs(0xdead));
pr_debug("htons(0x%x)=0x%x\n", 0xdead, htons(0xdead));
- result = ((unsigned long long) saddr +
- (unsigned long long) daddr +
- (unsigned long long) sum +
- ((unsigned long long) ntohs(len) << 16) +
- ((unsigned long long) proto << 8));
+ result = (__force u64) saddr + (__force u64) daddr +
+ (__force u64) sum + ((len + proto) << 8);
/* Fold down to 32-bits so we don't loose in the typedef-less
network stack. */
@@ -215,16 +211,5 @@ unsigned int csum_tcpudp_nofold(unsigned long saddr,
pr_debug("%s saddr %x daddr %x len %x proto %x sum %x result %08Lx\n",
__FUNCTION__, saddr, daddr, len, proto, sum, result);
- return result;
-}
-
-// Post SIM:
-unsigned int
-csum_partial_copy_nocheck(const unsigned char *src, unsigned char *dst, int len, unsigned int sum)
-{
- // unsigned dummy;
- pr_debug("csum_partial_copy_nocheck src %p dst %p len %d\n", src, dst,
- len);
-
- return csum_partial_copy(src, dst, len, sum);
+ return (__wsum)result;
}
diff --git a/arch/sh64/lib/dbg.c b/arch/sh64/lib/dbg.c
index 1326f45f31eb..4310fc87444e 100644
--- a/arch/sh64/lib/dbg.c
+++ b/arch/sh64/lib/dbg.c
@@ -383,7 +383,7 @@ void show_excp_regs(char *from, int trapnr, int signr, struct pt_regs *regs)
/* ======================================================================= */
/*
-** Depending on <base> scan the MMU, Data or Instrction side
+** Depending on <base> scan the MMU, Data or Instruction side
** looking for a valid mapping matching Eaddr & asid.
** Return -1 if not found or the TLB id entry otherwise.
** Note: it works only for 4k pages!
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 2f96610a83e9..92a7c8a636d3 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -212,8 +212,8 @@ config SPARC_LED
tristate "Sun4m LED driver"
help
This driver toggles the front-panel LED on sun4m systems
- in a user-specifyable manner. It's state can be probed
- by reading /proc/led and it's blinking mode can be changed
+ in a user-specifiable manner. Its state can be probed
+ by reading /proc/led and its blinking mode can be changed
via writes to /proc/led
source "fs/Kconfig.binfmt"
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
index e02f01b644af..dfc41cd4bb5d 100644
--- a/arch/sparc64/kernel/pci.c
+++ b/arch/sparc64/kernel/pci.c
@@ -646,13 +646,4 @@ int pci_domain_nr(struct pci_bus *pbus)
}
EXPORT_SYMBOL(pci_domain_nr);
-int pcibios_prep_mwi(struct pci_dev *dev)
-{
- /* We set correct PCI_CACHE_LINE_SIZE register values for every
- * device probed on this platform. So there is nothing to check
- * and this always succeeds.
- */
- return 0;
-}
-
#endif /* !(CONFIG_PCI) */
diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c
index 2f880cb167a5..0cad3546cb89 100644
--- a/arch/um/drivers/chan_user.c
+++ b/arch/um/drivers/chan_user.c
@@ -120,7 +120,7 @@ static int winch_thread(void *arg)
/* These are synchronization calls between various UML threads on the
* host - since they are not different kernel threads, we cannot use
* kernel semaphores. We don't use SysV semaphores because they are
- * persistant. */
+ * persistent. */
count = os_read_file(pipe_fd, &c, sizeof(c));
if(count != sizeof(c))
printk("winch_thread : failed to read synchronization byte, "
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 6516f6dca96d..13a86bd383d3 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -233,6 +233,8 @@ extern unsigned long __do_user_copy(void *to, const void *from, int n,
void (*op)(void *to, const void *from,
int n), int *faulted_out);
+/* execvp.c */
+extern int execvp_noalloc(char *buf, const char *file, char *const argv[]);
/* helper.c */
extern int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
unsigned long *stack_out);
diff --git a/arch/um/include/sysdep-i386/checksum.h b/arch/um/include/sysdep-i386/checksum.h
index 052bb061a978..0cb4645cbeb8 100644
--- a/arch/um/include/sysdep-i386/checksum.h
+++ b/arch/um/include/sysdep-i386/checksum.h
@@ -20,8 +20,7 @@
*
* it's best to have buff aligned on a 32-bit boundary
*/
-unsigned int csum_partial(const unsigned char * buff, int len,
- unsigned int sum);
+__wsum csum_partial(const void *buff, int len, __wsum sum);
/*
* Note: when you get a NULL pointer exception here this means someone
@@ -32,8 +31,8 @@ unsigned int csum_partial(const unsigned char * buff, int len,
*/
static __inline__
-unsigned int csum_partial_copy_nocheck(const unsigned char *src, unsigned char *dst,
- int len, int sum)
+__wsum csum_partial_copy_nocheck(const void *src, void *dst,
+ int len, __wsum sum)
{
memcpy(dst, src, len);
return csum_partial(dst, len, sum);
@@ -48,36 +47,25 @@ unsigned int csum_partial_copy_nocheck(const unsigned char *src, unsigned char *
*/
static __inline__
-unsigned int csum_partial_copy_from_user(const unsigned char __user *src,
- unsigned char *dst,
- int len, int sum, int *err_ptr)
+__wsum csum_partial_copy_from_user(const void __user *src, void *dst,
+ int len, __wsum sum, int *err_ptr)
{
- if(copy_from_user(dst, src, len)){
+ if (copy_from_user(dst, src, len)) {
*err_ptr = -EFAULT;
- return(-1);
+ return (__force __wsum)-1;
}
return csum_partial(dst, len, sum);
}
/*
- * These are the old (and unsafe) way of doing checksums, a warning message
- * will be printed if they are used and an exception occurs.
- *
- * these functions should go away after some time.
- */
-
-#define csum_partial_copy_fromuser csum_partial_copy_from_user
-
-/*
* This is a version of ip_compute_csum() optimized for IP headers,
* which always checksum on 4 octet boundaries.
*
* By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
* Arnt Gulbrandsen.
*/
-static inline unsigned short ip_fast_csum(unsigned char * iph,
- unsigned int ihl)
+static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
{
unsigned int sum;
@@ -105,29 +93,29 @@ static inline unsigned short ip_fast_csum(unsigned char * iph,
: "=r" (sum), "=r" (iph), "=r" (ihl)
: "1" (iph), "2" (ihl)
: "memory");
- return sum;
+ return (__force __sum16)sum;
}
/*
* Fold a partial checksum
*/
-static inline unsigned int csum_fold(unsigned int sum)
+static inline __sum16 csum_fold(__wsum sum)
{
__asm__(
"addl %1, %0 ;\n"
"adcl $0xffff, %0 ;\n"
: "=r" (sum)
- : "r" (sum << 16), "0" (sum & 0xffff0000)
+ : "r" ((__force u32)sum << 16),
+ "0" ((__force u32)sum & 0xffff0000)
);
- return (~sum) >> 16;
+ return (__force __sum16)(~(__force u32)sum >> 16);
}
-static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
- unsigned long daddr,
+static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
unsigned short len,
unsigned short proto,
- unsigned int sum)
+ __wsum sum)
{
__asm__(
"addl %1, %0 ;\n"
@@ -135,7 +123,7 @@ static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
"adcl %3, %0 ;\n"
"adcl $0, %0 ;\n"
: "=r" (sum)
- : "g" (daddr), "g"(saddr), "g"((ntohs(len)<<16)+proto*256), "0"(sum));
+ : "g" (daddr), "g"(saddr), "g"((len + proto) << 8), "0"(sum));
return sum;
}
@@ -143,11 +131,10 @@ static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
* computes the checksum of the TCP/UDP pseudo-header
* returns a 16-bit checksum, already complemented
*/
-static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
- unsigned long daddr,
+static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
unsigned short len,
unsigned short proto,
- unsigned int sum)
+ __wsum sum)
{
return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
}
@@ -157,17 +144,16 @@ static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
* in icmp.c
*/
-static inline unsigned short ip_compute_csum(unsigned char * buff, int len)
+static inline __sum16 ip_compute_csum(const void *buff, int len)
{
return csum_fold (csum_partial(buff, len, 0));
}
#define _HAVE_ARCH_IPV6_CSUM
-static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
- struct in6_addr *daddr,
- __u32 len,
- unsigned short proto,
- unsigned int sum)
+static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+ const struct in6_addr *daddr,
+ __u32 len, unsigned short proto,
+ __wsum sum)
{
__asm__(
"addl 0(%1), %0 ;\n"
@@ -192,14 +178,14 @@ static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
* Copy and checksum to user
*/
#define HAVE_CSUM_COPY_USER
-static __inline__ unsigned int csum_and_copy_to_user(const unsigned char *src,
- unsigned char __user *dst,
- int len, int sum, int *err_ptr)
+static __inline__ __wsum csum_and_copy_to_user(const void *src,
+ void __user *dst,
+ int len, __wsum sum, int *err_ptr)
{
- if (access_ok(VERIFY_WRITE, dst, len)){
- if(copy_to_user(dst, src, len)){
+ if (access_ok(VERIFY_WRITE, dst, len)) {
+ if (copy_to_user(dst, src, len)) {
*err_ptr = -EFAULT;
- return(-1);
+ return (__force __wsum)-1;
}
return csum_partial(src, len, sum);
@@ -208,7 +194,7 @@ static __inline__ unsigned int csum_and_copy_to_user(const unsigned char *src,
if (len)
*err_ptr = -EFAULT;
- return -1; /* invalid checksum */
+ return (__force __wsum)-1; /* invalid checksum */
}
#endif
diff --git a/arch/um/include/sysdep-x86_64/checksum.h b/arch/um/include/sysdep-x86_64/checksum.h
index ea97005af694..a5be9031ea85 100644
--- a/arch/um/include/sysdep-x86_64/checksum.h
+++ b/arch/um/include/sysdep-x86_64/checksum.h
@@ -9,8 +9,7 @@
#include "linux/in6.h"
#include "asm/uaccess.h"
-extern unsigned csum_partial(const unsigned char *buff, unsigned len,
- unsigned sum);
+extern __wsum csum_partial(const void *buff, int len, __wsum sum);
/*
* Note: when you get a NULL pointer exception here this means someone
@@ -21,21 +20,21 @@ extern unsigned csum_partial(const unsigned char *buff, unsigned len,
*/
static __inline__
-unsigned int csum_partial_copy_nocheck(const unsigned char *src, unsigned char *dst,
- int len, int sum)
+__wsum csum_partial_copy_nocheck(const void *src, void *dst,
+ int len, __wsum sum)
{
memcpy(dst, src, len);
return(csum_partial(dst, len, sum));
}
static __inline__
-unsigned int csum_partial_copy_from_user(const unsigned char *src,
- unsigned char *dst, int len, int sum,
+__wsum csum_partial_copy_from_user(const void __user *src,
+ void *dst, int len, __wsum sum,
int *err_ptr)
{
- if(copy_from_user(dst, src, len)){
+ if (copy_from_user(dst, src, len)) {
*err_ptr = -EFAULT;
- return(-1);
+ return (__force __wsum)-1;
}
return csum_partial(dst, len, sum);
}
@@ -48,15 +47,16 @@ unsigned int csum_partial_copy_from_user(const unsigned char *src,
* the last step before putting a checksum into a packet.
* Make sure not to mix with 64bit checksums.
*/
-static inline unsigned int csum_fold(unsigned int sum)
+static inline __sum16 csum_fold(__wsum sum)
{
__asm__(
" addl %1,%0\n"
" adcl $0xffff,%0"
: "=r" (sum)
- : "r" (sum << 16), "0" (sum & 0xffff0000)
+ : "r" ((__force u32)sum << 16),
+ "0" ((__force u32)sum & 0xffff0000)
);
- return (~sum) >> 16;
+ return (__force __sum16)(~(__force u32)sum >> 16);
}
/**
@@ -70,28 +70,27 @@ static inline unsigned int csum_fold(unsigned int sum)
* Returns the pseudo header checksum the input data. Result is
* 32bit unfolded.
*/
-static inline unsigned long
-csum_tcpudp_nofold(unsigned saddr, unsigned daddr, unsigned short len,
- unsigned short proto, unsigned int sum)
+static inline __wsum
+csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
+ unsigned short proto, __wsum sum)
{
asm(" addl %1, %0\n"
" adcl %2, %0\n"
" adcl %3, %0\n"
" adcl $0, %0\n"
: "=r" (sum)
- : "g" (daddr), "g" (saddr), "g" ((ntohs(len)<<16)+proto*256), "0" (sum));
- return sum;
+ : "g" (daddr), "g" (saddr), "g" ((len + proto) << 8), "0" (sum));
+ return sum;
}
/*
* computes the checksum of the TCP/UDP pseudo-header
* returns a 16-bit checksum, already complemented
*/
-static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
- unsigned long daddr,
- unsigned short len,
- unsigned short proto,
- unsigned int sum)
+static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
+ unsigned short len,
+ unsigned short proto,
+ __wsum sum)
{
return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
}
@@ -101,7 +100,7 @@ static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
* iph: ipv4 header
* ihl: length of header / 4
*/
-static inline unsigned short ip_fast_csum(unsigned char *iph, unsigned int ihl)
+static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
{
unsigned int sum;
@@ -128,7 +127,7 @@ static inline unsigned short ip_fast_csum(unsigned char *iph, unsigned int ihl)
: "=r" (sum), "=r" (iph), "=r" (ihl)
: "1" (iph), "2" (ihl)
: "memory");
- return(sum);
+ return (__force __sum16)sum;
}
static inline unsigned add32_with_carry(unsigned a, unsigned b)
@@ -140,6 +139,6 @@ static inline unsigned add32_with_carry(unsigned a, unsigned b)
return a;
}
-extern unsigned short ip_compute_csum(unsigned char * buff, int len);
+extern __sum16 ip_compute_csum(const void *buff, int len);
#endif
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index b4183929b32c..2f8c79464015 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -3,8 +3,8 @@
# Licensed under the GPL
#
-obj-y = aio.o elf_aux.o file.o helper.o irq.o main.o mem.o process.o sigio.o \
- signal.o start_up.o time.o trap.o tty.o uaccess.o umid.o tls.o \
+obj-y = aio.o elf_aux.o execvp.o file.o helper.o irq.o main.o mem.o process.o \
+ sigio.o signal.o start_up.o time.o trap.o tty.o uaccess.o umid.o tls.o \
user_syms.o util.o drivers/ sys-$(SUBARCH)/
obj-$(CONFIG_MODE_SKAS) += skas/
@@ -15,9 +15,9 @@ user-objs-$(CONFIG_MODE_TT) += tt.o
obj-$(CONFIG_TTY_LOG) += tty_log.o
user-objs-$(CONFIG_TTY_LOG) += tty_log.o
-USER_OBJS := $(user-objs-y) aio.o elf_aux.o file.o helper.o irq.o main.o mem.o \
- process.o sigio.o signal.o start_up.o time.o trap.o tty.o tls.o \
- uaccess.o umid.o util.o
+USER_OBJS := $(user-objs-y) aio.o elf_aux.o execvp.o file.o helper.o irq.o \
+ main.o mem.o process.o sigio.o signal.o start_up.o time.o trap.o tty.o \
+ tls.o uaccess.o umid.o util.o
CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH)
diff --git a/arch/um/os-Linux/execvp.c b/arch/um/os-Linux/execvp.c
new file mode 100644
index 000000000000..66e583a4031b
--- /dev/null
+++ b/arch/um/os-Linux/execvp.c
@@ -0,0 +1,149 @@
+/* Copyright (C) 2006 by Paolo Giarrusso - modified from glibc' execvp.c.
+ Original copyright notice follows:
+
+ Copyright (C) 1991,92,1995-99,2002,2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+#include <unistd.h>
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+
+#ifndef TEST
+#include "um_malloc.h"
+#else
+#include <stdio.h>
+#define um_kmalloc malloc
+#endif
+#include "os.h"
+
+/* Execute FILE, searching in the `PATH' environment variable if it contains
+ no slashes, with arguments ARGV and environment from `environ'. */
+int execvp_noalloc(char *buf, const char *file, char *const argv[])
+{
+ if (*file == '\0') {
+ return -ENOENT;
+ }
+
+ if (strchr (file, '/') != NULL) {
+ /* Don't search when it contains a slash. */
+ execv(file, argv);
+ } else {
+ int got_eacces;
+ size_t len, pathlen;
+ char *name, *p;
+ char *path = getenv("PATH");
+ if (path == NULL)
+ path = ":/bin:/usr/bin";
+
+ len = strlen(file) + 1;
+ pathlen = strlen(path);
+ /* Copy the file name at the top. */
+ name = memcpy(buf + pathlen + 1, file, len);
+ /* And add the slash. */
+ *--name = '/';
+
+ got_eacces = 0;
+ p = path;
+ do {
+ char *startp;
+
+ path = p;
+ //Let's avoid this GNU extension.
+ //p = strchrnul (path, ':');
+ p = strchr(path, ':');
+ if (!p)
+ p = strchr(path, '\0');
+
+ if (p == path)
+ /* Two adjacent colons, or a colon at the beginning or the end
+ of `PATH' means to search the current directory. */
+ startp = name + 1;
+ else
+ startp = memcpy(name - (p - path), path, p - path);
+
+ /* Try to execute this name. If it works, execv will not return. */
+ execv(startp, argv);
+
+ /*
+ if (errno == ENOEXEC) {
+ }
+ */
+
+ switch (errno) {
+ case EACCES:
+ /* Record the we got a `Permission denied' error. If we end
+ up finding no executable we can use, we want to diagnose
+ that we did find one but were denied access. */
+ got_eacces = 1;
+ case ENOENT:
+ case ESTALE:
+ case ENOTDIR:
+ /* Those errors indicate the file is missing or not executable
+ by us, in which case we want to just try the next path
+ directory. */
+ case ENODEV:
+ case ETIMEDOUT:
+ /* Some strange filesystems like AFS return even
+ stranger error numbers. They cannot reasonably mean
+ anything else so ignore those, too. */
+ case ENOEXEC:
+ /* We won't go searching for the shell
+ * if it is not executable - the Linux
+ * kernel already handles this enough,
+ * for us. */
+ break;
+
+ default:
+ /* Some other error means we found an executable file, but
+ something went wrong executing it; return the error to our
+ caller. */
+ return -errno;
+ }
+ } while (*p++ != '\0');
+
+ /* We tried every element and none of them worked. */
+ if (got_eacces)
+ /* At least one failure was due to permissions, so report that
+ error. */
+ return -EACCES;
+ }
+
+ /* Return the error from the last attempt (probably ENOENT). */
+ return -errno;
+}
+#ifdef TEST
+int main(int argc, char**argv)
+{
+ char buf[PATH_MAX];
+ int ret;
+ argc--;
+ if (!argc) {
+ fprintf(stderr, "Not enough arguments\n");
+ return 1;
+ }
+ argv++;
+ if (ret = execvp_noalloc(buf, argv[0], argv)) {
+ errno = -ret;
+ perror("execvp_noalloc");
+ }
+ return 0;
+}
+#endif
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index d13299cfa318..c7ad6306e22f 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -8,18 +8,21 @@
#include <unistd.h>
#include <errno.h>
#include <sched.h>
+#include <limits.h>
#include <sys/signal.h>
#include <sys/wait.h>
#include "user.h"
#include "kern_util.h"
#include "user_util.h"
#include "os.h"
+#include "um_malloc.h"
struct helper_data {
void (*pre_exec)(void*);
void *pre_data;
char **argv;
int fd;
+ char *buf;
};
/* Debugging aid, changed only from gdb */
@@ -41,9 +44,8 @@ static int helper_child(void *arg)
}
if (data->pre_exec != NULL)
(*data->pre_exec)(data->pre_data);
- execvp(argv[0], argv);
- errval = -errno;
- printk("helper_child - execve of '%s' failed - errno = %d\n", argv[0], errno);
+ errval = execvp_noalloc(data->buf, argv[0], argv);
+ printk("helper_child - execvp of '%s' failed - errno = %d\n", argv[0], -errval);
os_write_file(data->fd, &errval, sizeof(errval));
kill(os_getpid(), SIGKILL);
return 0;
@@ -84,11 +86,13 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
data.pre_data = pre_data;
data.argv = argv;
data.fd = fds[1];
+ data.buf = __cant_sleep() ? um_kmalloc_atomic(PATH_MAX) :
+ um_kmalloc(PATH_MAX);
pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data);
if (pid < 0) {
ret = -errno;
printk("run_helper : clone failed, errno = %d\n", errno);
- goto out_close;
+ goto out_free2;
}
close(fds[1]);
@@ -109,6 +113,8 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
CATCH_EINTR(waitpid(pid, NULL, 0));
}
+out_free2:
+ kfree(data.buf);
out_close:
if (fds[1] != -1)
close(fds[1]);
diff --git a/arch/v850/kernel/v850_ksyms.c b/arch/v850/kernel/v850_ksyms.c
index 67bc48e57c60..93575fdc874d 100644
--- a/arch/v850/kernel/v850_ksyms.c
+++ b/arch/v850/kernel/v850_ksyms.c
@@ -24,7 +24,7 @@ EXPORT_SYMBOL (kernel_thread);
EXPORT_SYMBOL (__bug);
/* Networking helper routines. */
-EXPORT_SYMBOL (csum_partial_copy);
+EXPORT_SYMBOL (csum_partial_copy_nocheck);
EXPORT_SYMBOL (csum_partial_copy_from_user);
EXPORT_SYMBOL (ip_compute_csum);
EXPORT_SYMBOL (ip_fast_csum);
diff --git a/arch/v850/lib/checksum.c b/arch/v850/lib/checksum.c
index fa5872633075..042158dfe17a 100644
--- a/arch/v850/lib/checksum.c
+++ b/arch/v850/lib/checksum.c
@@ -88,32 +88,32 @@ out:
* This is a version of ip_compute_csum() optimized for IP headers,
* which always checksum on 4 octet boundaries.
*/
-unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl)
+__sum16 ip_fast_csum(const void *iph, unsigned int ihl)
{
- return ~do_csum(iph,ihl*4);
+ return (__force __sum16)~do_csum(iph,ihl*4);
}
/*
* this routine is used for miscellaneous IP-like checksums, mainly
* in icmp.c
*/
-unsigned short ip_compute_csum(const unsigned char * buff, int len)
+__sum16 ip_compute_csum(const void *buff, int len)
{
- return ~do_csum(buff,len);
+ return (__force __sum16)~do_csum(buff,len);
}
/*
* computes a partial checksum, e.g. for TCP/UDP fragments
*/
-unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum)
+__wsum csum_partial(const void *buff, int len, __wsum sum)
{
unsigned int result = do_csum(buff, len);
/* add in old sum, and carry.. */
- result += sum;
- if(sum > result)
+ result += (__force u32)sum;
+ if ((__force u32)sum > result)
result += 1;
- return result;
+ return (__force __wsum)result;
}
EXPORT_SYMBOL(csum_partial);
@@ -121,8 +121,8 @@ EXPORT_SYMBOL(csum_partial);
/*
* copy while checksumming, otherwise like csum_partial
*/
-unsigned int csum_partial_copy(const unsigned char *src, unsigned char *dst,
- int len, unsigned int sum)
+__wsum csum_partial_copy_nocheck(const void *src, void *dst,
+ int len, __wsum sum)
{
/*
* It's 2:30 am and I don't feel like doing it real ...
@@ -138,9 +138,9 @@ unsigned int csum_partial_copy(const unsigned char *src, unsigned char *dst,
* Copy from userspace and compute checksum. If we catch an exception
* then zero the rest of the buffer.
*/
-unsigned int csum_partial_copy_from_user (const unsigned char *src,
- unsigned char *dst,
- int len, unsigned int sum,
+__wsum csum_partial_copy_from_user (const void *src,
+ void *dst,
+ int len, __wsum sum,
int *err_ptr)
{
int missing;
diff --git a/arch/x86_64/kernel/early_printk.c b/arch/x86_64/kernel/early_printk.c
index e22ecd54870d..47b6d90349da 100644
--- a/arch/x86_64/kernel/early_printk.c
+++ b/arch/x86_64/kernel/early_printk.c
@@ -224,7 +224,7 @@ static int __init setup_early_printk(char *buf)
return 0;
early_console_initialized = 1;
- if (!strcmp(buf,"keep"))
+ if (strstr(buf, "keep"))
keep_early = 1;
if (!strncmp(buf, "serial", 6)) {
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index 14654e682411..c80081a6ba41 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -754,10 +754,8 @@ void __setup_vector_irq(int cpu)
{
/* Initialize vector_irq on a new cpu */
/* This function must be called with vector_lock held */
- unsigned long flags;
int irq, vector;
-
/* Mark the inuse vectors */
for (irq = 0; irq < NR_IRQ_VECTORS; ++irq) {
if (!cpu_isset(cpu, irq_domain[irq]))
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index a153d0a01b72..0d65b22f229c 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -242,12 +242,19 @@ static int dump_trace_unwind(struct unwind_frame_info *info, void *context)
* severe exception (double fault, nmi, stack fault, debug, mce) hardware stack
*/
+static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
+{
+ void *t = (void *)tinfo;
+ return p > t && p < t + THREAD_SIZE - 3;
+}
+
void dump_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * stack,
struct stacktrace_ops *ops, void *data)
{
const unsigned cpu = smp_processor_id();
unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr;
unsigned used = 0;
+ struct thread_info *tinfo;
if (!tsk)
tsk = current;
@@ -370,7 +377,8 @@ void dump_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s
/*
* This handles the process stack:
*/
- HANDLE_STACK (((long) stack & (THREAD_SIZE-1)) != 0);
+ tinfo = current_thread_info();
+ HANDLE_STACK (valid_stack_ptr(tinfo, stack));
#undef HANDLE_STACK
}
EXPORT_SYMBOL(dump_trace);
diff --git a/arch/x86_64/lib/csum-partial.c b/arch/x86_64/lib/csum-partial.c
index c493735218da..06ae630de82b 100644
--- a/arch/x86_64/lib/csum-partial.c
+++ b/arch/x86_64/lib/csum-partial.c
@@ -132,9 +132,10 @@ static __force_inline unsigned do_csum(const unsigned char *buff, unsigned len)
*
* it's best to have buff aligned on a 64-bit boundary
*/
-unsigned csum_partial(const unsigned char *buff, unsigned len, unsigned sum)
+__wsum csum_partial(const void *buff, int len, __wsum sum)
{
- return add32_with_carry(do_csum(buff, len), sum);
+ return (__force __wsum)add32_with_carry(do_csum(buff, len),
+ (__force u32)sum);
}
EXPORT_SYMBOL(csum_partial);
@@ -143,7 +144,7 @@ EXPORT_SYMBOL(csum_partial);
* this routine is used for miscellaneous IP-like checksums, mainly
* in icmp.c
*/
-unsigned short ip_compute_csum(unsigned char * buff, int len)
+__sum16 ip_compute_csum(const void *buff, int len)
{
return csum_fold(csum_partial(buff,len,0));
}
diff --git a/arch/x86_64/lib/csum-wrappers.c b/arch/x86_64/lib/csum-wrappers.c
index b1320ec58428..fd42a4a095fc 100644
--- a/arch/x86_64/lib/csum-wrappers.c
+++ b/arch/x86_64/lib/csum-wrappers.c
@@ -18,9 +18,9 @@
* Returns an 32bit unfolded checksum of the buffer.
* src and dst are best aligned to 64bits.
*/
-unsigned int
-csum_partial_copy_from_user(const unsigned char __user *src, unsigned char *dst,
- int len, unsigned int isum, int *errp)
+__wsum
+csum_partial_copy_from_user(const void __user *src, void *dst,
+ int len, __wsum isum, int *errp)
{
might_sleep();
*errp = 0;
@@ -34,17 +34,19 @@ csum_partial_copy_from_user(const unsigned char __user *src, unsigned char *dst,
if (unlikely((unsigned long)src & 6)) {
while (((unsigned long)src & 6) && len >= 2) {
__u16 val16;
- *errp = __get_user(val16, (__u16 __user *)src);
+ *errp = __get_user(val16, (const __u16 __user *)src);
if (*errp)
return isum;
*(__u16 *)dst = val16;
- isum = add32_with_carry(isum, val16);
+ isum = (__force __wsum)add32_with_carry(
+ (__force unsigned)isum, val16);
src += 2;
dst += 2;
len -= 2;
}
}
- isum = csum_partial_copy_generic((__force void *)src,dst,len,isum,errp,NULL);
+ isum = csum_partial_copy_generic((__force const void *)src,
+ dst, len, isum, errp, NULL);
if (likely(*errp == 0))
return isum;
}
@@ -66,9 +68,9 @@ EXPORT_SYMBOL(csum_partial_copy_from_user);
* Returns an 32bit unfolded checksum of the buffer.
* src and dst are best aligned to 64bits.
*/
-unsigned int
-csum_partial_copy_to_user(unsigned const char *src, unsigned char __user *dst,
- int len, unsigned int isum, int *errp)
+__wsum
+csum_partial_copy_to_user(const void *src, void __user *dst,
+ int len, __wsum isum, int *errp)
{
might_sleep();
if (unlikely(!access_ok(VERIFY_WRITE, dst, len))) {
@@ -79,7 +81,8 @@ csum_partial_copy_to_user(unsigned const char *src, unsigned char __user *dst,
if (unlikely((unsigned long)dst & 6)) {
while (((unsigned long)dst & 6) && len >= 2) {
__u16 val16 = *(__u16 *)src;
- isum = add32_with_carry(isum, val16);
+ isum = (__force __wsum)add32_with_carry(
+ (__force unsigned)isum, val16);
*errp = __put_user(val16, (__u16 __user *)dst);
if (*errp)
return isum;
@@ -104,19 +107,21 @@ EXPORT_SYMBOL(csum_partial_copy_to_user);
*
* Returns an 32bit unfolded checksum of the buffer.
*/
-unsigned int
-csum_partial_copy_nocheck(const unsigned char *src, unsigned char *dst, int len, unsigned int sum)
+__wsum
+csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
{
return csum_partial_copy_generic(src,dst,len,sum,NULL,NULL);
}
EXPORT_SYMBOL(csum_partial_copy_nocheck);
-unsigned short csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr,
- __u32 len, unsigned short proto, unsigned int sum)
+__sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+ const struct in6_addr *daddr,
+ __u32 len, unsigned short proto, __wsum sum)
{
__u64 rest, sum64;
- rest = (__u64)htonl(len) + (__u64)htons(proto) + (__u64)sum;
+ rest = (__force __u64)htonl(len) + (__force __u64)htons(proto) +
+ (__force __u64)sum;
asm(" addq (%[saddr]),%[sum]\n"
" adcq 8(%[saddr]),%[sum]\n"
" adcq (%[daddr]),%[sum]\n"
@@ -124,7 +129,7 @@ unsigned short csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr,
" adcq $0,%[sum]\n"
: [sum] "=r" (sum64)
: "[sum]" (rest),[saddr] "r" (saddr), [daddr] "r" (daddr));
- return csum_fold(add32_with_carry(sum64 & 0xffffffff, sum64>>32));
+ return csum_fold((__force __wsum)add32_with_carry(sum64 & 0xffffffff, sum64>>32));
}
EXPORT_SYMBOL(csum_ipv6_magic);
diff --git a/block/as-iosched.c b/block/as-iosched.c
index f371c9359999..5934c4bfd52a 100644
--- a/block/as-iosched.c
+++ b/block/as-iosched.c
@@ -1318,7 +1318,7 @@ static void as_exit_queue(elevator_t *e)
/*
* initialize elevator private data (as_data).
*/
-static void *as_init_queue(request_queue_t *q, elevator_t *e)
+static void *as_init_queue(request_queue_t *q)
{
struct as_data *ad;
diff --git a/block/blktrace.c b/block/blktrace.c
index 135593c8e45b..562ca7cbf858 100644
--- a/block/blktrace.c
+++ b/block/blktrace.c
@@ -22,30 +22,61 @@
#include <linux/init.h>
#include <linux/mutex.h>
#include <linux/debugfs.h>
+#include <linux/time.h>
#include <asm/uaccess.h>
static DEFINE_PER_CPU(unsigned long long, blk_trace_cpu_offset) = { 0, };
static unsigned int blktrace_seq __read_mostly = 1;
/*
+ * Send out a notify message.
+ */
+static inline unsigned int trace_note(struct blk_trace *bt,
+ pid_t pid, int action,
+ const void *data, size_t len)
+{
+ struct blk_io_trace *t;
+ int cpu = smp_processor_id();
+
+ t = relay_reserve(bt->rchan, sizeof(*t) + len);
+ if (t == NULL)
+ return 0;
+
+ t->magic = BLK_IO_TRACE_MAGIC | BLK_IO_TRACE_VERSION;
+ t->time = sched_clock() - per_cpu(blk_trace_cpu_offset, cpu);
+ t->device = bt->dev;
+ t->action = action;
+ t->pid = pid;
+ t->cpu = cpu;
+ t->pdu_len = len;
+ memcpy((void *) t + sizeof(*t), data, len);
+ return blktrace_seq;
+}
+
+/*
* Send out a notify for this process, if we haven't done so since a trace
* started
*/
static void trace_note_tsk(struct blk_trace *bt, struct task_struct *tsk)
{
- struct blk_io_trace *t;
+ tsk->btrace_seq = trace_note(bt, tsk->pid,
+ BLK_TN_PROCESS,
+ tsk->comm, sizeof(tsk->comm));
+}
- t = relay_reserve(bt->rchan, sizeof(*t) + sizeof(tsk->comm));
- if (t) {
- t->magic = BLK_IO_TRACE_MAGIC | BLK_IO_TRACE_VERSION;
- t->device = bt->dev;
- t->action = BLK_TC_ACT(BLK_TC_NOTIFY);
- t->pid = tsk->pid;
- t->cpu = smp_processor_id();
- t->pdu_len = sizeof(tsk->comm);
- memcpy((void *) t + sizeof(*t), tsk->comm, t->pdu_len);
- tsk->btrace_seq = blktrace_seq;
- }
+static void trace_note_time(struct blk_trace *bt)
+{
+ struct timespec now;
+ unsigned long flags;
+ u32 words[2];
+
+ getnstimeofday(&now);
+ words[0] = now.tv_sec;
+ words[1] = now.tv_nsec;
+
+ local_irq_save(flags);
+ trace_note(bt, 0, BLK_TN_TIMESTAMP, words, sizeof(words));
+ local_irq_restore(flags);
}
static int act_log_check(struct blk_trace *bt, u32 what, sector_t sector,
@@ -394,6 +425,8 @@ static int blk_trace_startstop(request_queue_t *q, int start)
blktrace_seq++;
smp_mb();
bt->trace_state = Blktrace_running;
+
+ trace_note_time(bt);
ret = 0;
}
} else {
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 6cec3a1dccb8..84e9be073180 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -1464,8 +1464,7 @@ cfq_update_io_thinktime(struct cfq_data *cfqd, struct cfq_io_context *cic)
}
static void
-cfq_update_io_seektime(struct cfq_data *cfqd, struct cfq_io_context *cic,
- struct request *rq)
+cfq_update_io_seektime(struct cfq_io_context *cic, struct request *rq)
{
sector_t sdist;
u64 total;
@@ -1617,7 +1616,7 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
}
cfq_update_io_thinktime(cfqd, cic);
- cfq_update_io_seektime(cfqd, cic, rq);
+ cfq_update_io_seektime(cic, rq);
cfq_update_idle_window(cfqd, cfqq, cic);
cic->last_queue = jiffies;
@@ -1770,7 +1769,7 @@ static int cfq_may_queue(request_queue_t *q, int rw)
/*
* queue lock held here
*/
-static void cfq_put_request(request_queue_t *q, struct request *rq)
+static void cfq_put_request(struct request *rq)
{
struct cfq_queue *cfqq = RQ_CFQQ(rq);
@@ -1953,7 +1952,7 @@ static void cfq_exit_queue(elevator_t *e)
kfree(cfqd);
}
-static void *cfq_init_queue(request_queue_t *q, elevator_t *e)
+static void *cfq_init_queue(request_queue_t *q)
{
struct cfq_data *cfqd;
int i;
diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c
index b7c5b34cb7b4..6d673e938d3e 100644
--- a/block/deadline-iosched.c
+++ b/block/deadline-iosched.c
@@ -356,7 +356,7 @@ static void deadline_exit_queue(elevator_t *e)
/*
* initialize elevator private data (deadline_data).
*/
-static void *deadline_init_queue(request_queue_t *q, elevator_t *e)
+static void *deadline_init_queue(request_queue_t *q)
{
struct deadline_data *dd;
diff --git a/block/elevator.c b/block/elevator.c
index 8ccd163254b8..c0063f345c5d 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -129,7 +129,7 @@ static struct elevator_type *elevator_get(const char *name)
static void *elevator_init_queue(request_queue_t *q, struct elevator_queue *eq)
{
- return eq->ops->elevator_init_fn(q, eq);
+ return eq->ops->elevator_init_fn(q);
}
static void elevator_attach(request_queue_t *q, struct elevator_queue *eq,
@@ -810,7 +810,7 @@ void elv_put_request(request_queue_t *q, struct request *rq)
elevator_t *e = q->elevator;
if (e->ops->elevator_put_req_fn)
- e->ops->elevator_put_req_fn(q, rq);
+ e->ops->elevator_put_req_fn(rq);
}
int elv_may_queue(request_queue_t *q, int rw)
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index eb4cf6df7374..cc6e95f8e5d9 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -2322,6 +2322,84 @@ void blk_insert_request(request_queue_t *q, struct request *rq,
EXPORT_SYMBOL(blk_insert_request);
+static int __blk_rq_unmap_user(struct bio *bio)
+{
+ int ret = 0;
+
+ if (bio) {
+ if (bio_flagged(bio, BIO_USER_MAPPED))
+ bio_unmap_user(bio);
+ else
+ ret = bio_uncopy_user(bio);
+ }
+
+ return ret;
+}
+
+static int __blk_rq_map_user(request_queue_t *q, struct request *rq,
+ void __user *ubuf, unsigned int len)
+{
+ unsigned long uaddr;
+ struct bio *bio, *orig_bio;
+ int reading, ret;
+
+ reading = rq_data_dir(rq) == READ;
+
+ /*
+ * if alignment requirement is satisfied, map in user pages for
+ * direct dma. else, set up kernel bounce buffers
+ */
+ uaddr = (unsigned long) ubuf;
+ if (!(uaddr & queue_dma_alignment(q)) && !(len & queue_dma_alignment(q)))
+ bio = bio_map_user(q, NULL, uaddr, len, reading);
+ else
+ bio = bio_copy_user(q, uaddr, len, reading);
+
+ if (IS_ERR(bio)) {
+ return PTR_ERR(bio);
+ }
+
+ orig_bio = bio;
+ blk_queue_bounce(q, &bio);
+ /*
+ * We link the bounce buffer in and could have to traverse it
+ * later so we have to get a ref to prevent it from being freed
+ */
+ bio_get(bio);
+
+ /*
+ * for most (all? don't know of any) queues we could
+ * skip grabbing the queue lock here. only drivers with
+ * funky private ->back_merge_fn() function could be
+ * problematic.
+ */
+ spin_lock_irq(q->queue_lock);
+ if (!rq->bio)
+ blk_rq_bio_prep(q, rq, bio);
+ else if (!q->back_merge_fn(q, rq, bio)) {
+ ret = -EINVAL;
+ spin_unlock_irq(q->queue_lock);
+ goto unmap_bio;
+ } else {
+ rq->biotail->bi_next = bio;
+ rq->biotail = bio;
+
+ rq->nr_sectors += bio_sectors(bio);
+ rq->hard_nr_sectors = rq->nr_sectors;
+ rq->data_len += bio->bi_size;
+ }
+ spin_unlock_irq(q->queue_lock);
+
+ return bio->bi_size;
+
+unmap_bio:
+ /* if it was boucned we must call the end io function */
+ bio_endio(bio, bio->bi_size, 0);
+ __blk_rq_unmap_user(orig_bio);
+ bio_put(bio);
+ return ret;
+}
+
/**
* blk_rq_map_user - map user data to a request, for REQ_BLOCK_PC usage
* @q: request queue where request should be inserted
@@ -2343,42 +2421,44 @@ EXPORT_SYMBOL(blk_insert_request);
* unmapping.
*/
int blk_rq_map_user(request_queue_t *q, struct request *rq, void __user *ubuf,
- unsigned int len)
+ unsigned long len)
{
- unsigned long uaddr;
- struct bio *bio;
- int reading;
+ unsigned long bytes_read = 0;
+ int ret;
if (len > (q->max_hw_sectors << 9))
return -EINVAL;
if (!len || !ubuf)
return -EINVAL;
- reading = rq_data_dir(rq) == READ;
+ while (bytes_read != len) {
+ unsigned long map_len, end, start;
- /*
- * if alignment requirement is satisfied, map in user pages for
- * direct dma. else, set up kernel bounce buffers
- */
- uaddr = (unsigned long) ubuf;
- if (!(uaddr & queue_dma_alignment(q)) && !(len & queue_dma_alignment(q)))
- bio = bio_map_user(q, NULL, uaddr, len, reading);
- else
- bio = bio_copy_user(q, uaddr, len, reading);
+ map_len = min_t(unsigned long, len - bytes_read, BIO_MAX_SIZE);
+ end = ((unsigned long)ubuf + map_len + PAGE_SIZE - 1)
+ >> PAGE_SHIFT;
+ start = (unsigned long)ubuf >> PAGE_SHIFT;
- if (!IS_ERR(bio)) {
- rq->bio = rq->biotail = bio;
- blk_rq_bio_prep(q, rq, bio);
+ /*
+ * A bad offset could cause us to require BIO_MAX_PAGES + 1
+ * pages. If this happens we just lower the requested
+ * mapping len by a page so that we can fit
+ */
+ if (end - start > BIO_MAX_PAGES)
+ map_len -= PAGE_SIZE;
- rq->buffer = rq->data = NULL;
- rq->data_len = len;
- return 0;
+ ret = __blk_rq_map_user(q, rq, ubuf, map_len);
+ if (ret < 0)
+ goto unmap_rq;
+ bytes_read += ret;
+ ubuf += ret;
}
- /*
- * bio is the err-ptr
- */
- return PTR_ERR(bio);
+ rq->buffer = rq->data = NULL;
+ return 0;
+unmap_rq:
+ blk_rq_unmap_user(rq);
+ return ret;
}
EXPORT_SYMBOL(blk_rq_map_user);
@@ -2404,7 +2484,7 @@ EXPORT_SYMBOL(blk_rq_map_user);
* unmapping.
*/
int blk_rq_map_user_iov(request_queue_t *q, struct request *rq,
- struct sg_iovec *iov, int iov_count)
+ struct sg_iovec *iov, int iov_count, unsigned int len)
{
struct bio *bio;
@@ -2418,10 +2498,15 @@ int blk_rq_map_user_iov(request_queue_t *q, struct request *rq,
if (IS_ERR(bio))
return PTR_ERR(bio);
- rq->bio = rq->biotail = bio;
+ if (bio->bi_size != len) {
+ bio_endio(bio, bio->bi_size, 0);
+ bio_unmap_user(bio);
+ return -EINVAL;
+ }
+
+ bio_get(bio);
blk_rq_bio_prep(q, rq, bio);
rq->buffer = rq->data = NULL;
- rq->data_len = bio->bi_size;
return 0;
}
@@ -2429,23 +2514,26 @@ EXPORT_SYMBOL(blk_rq_map_user_iov);
/**
* blk_rq_unmap_user - unmap a request with user data
- * @bio: bio to be unmapped
- * @ulen: length of user buffer
+ * @rq: rq to be unmapped
*
* Description:
- * Unmap a bio previously mapped by blk_rq_map_user().
+ * Unmap a rq previously mapped by blk_rq_map_user().
+ * rq->bio must be set to the original head of the request.
*/
-int blk_rq_unmap_user(struct bio *bio, unsigned int ulen)
+int blk_rq_unmap_user(struct request *rq)
{
- int ret = 0;
+ struct bio *bio, *mapped_bio;
- if (bio) {
- if (bio_flagged(bio, BIO_USER_MAPPED))
- bio_unmap_user(bio);
+ while ((bio = rq->bio)) {
+ if (bio_flagged(bio, BIO_BOUNCED))
+ mapped_bio = bio->bi_private;
else
- ret = bio_uncopy_user(bio);
- }
+ mapped_bio = bio;
+ __blk_rq_unmap_user(mapped_bio);
+ rq->bio = bio->bi_next;
+ bio_put(bio);
+ }
return 0;
}
@@ -2476,11 +2564,8 @@ int blk_rq_map_kern(request_queue_t *q, struct request *rq, void *kbuf,
if (rq_data_dir(rq) == WRITE)
bio->bi_rw |= (1 << BIO_RW);
- rq->bio = rq->biotail = bio;
blk_rq_bio_prep(q, rq, bio);
-
rq->buffer = rq->data = NULL;
- rq->data_len = len;
return 0;
}
@@ -3495,6 +3580,7 @@ void blk_rq_bio_prep(request_queue_t *q, struct request *rq, struct bio *bio)
rq->hard_cur_sectors = rq->current_nr_sectors;
rq->hard_nr_sectors = rq->nr_sectors = bio_sectors(bio);
rq->buffer = bio_data(bio);
+ rq->data_len = bio->bi_size;
rq->bio = rq->biotail = bio;
}
diff --git a/block/noop-iosched.c b/block/noop-iosched.c
index 79af43179421..1c3de2b9a6b5 100644
--- a/block/noop-iosched.c
+++ b/block/noop-iosched.c
@@ -65,7 +65,7 @@ noop_latter_request(request_queue_t *q, struct request *rq)
return list_entry(rq->queuelist.next, struct request, queuelist);
}
-static void *noop_init_queue(request_queue_t *q, elevator_t *e)
+static void *noop_init_queue(request_queue_t *q)
{
struct noop_data *nd;
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index e55a75621437..5493c2fbbab1 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -226,7 +226,6 @@ static int sg_io(struct file *file, request_queue_t *q,
unsigned long start_time;
int writing = 0, ret = 0;
struct request *rq;
- struct bio *bio;
char sense[SCSI_SENSE_BUFFERSIZE];
unsigned char cmd[BLK_MAX_CDB];
@@ -258,30 +257,6 @@ static int sg_io(struct file *file, request_queue_t *q,
if (!rq)
return -ENOMEM;
- if (hdr->iovec_count) {
- const int size = sizeof(struct sg_iovec) * hdr->iovec_count;
- struct sg_iovec *iov;
-
- iov = kmalloc(size, GFP_KERNEL);
- if (!iov) {
- ret = -ENOMEM;
- goto out;
- }
-
- if (copy_from_user(iov, hdr->dxferp, size)) {
- kfree(iov);
- ret = -EFAULT;
- goto out;
- }
-
- ret = blk_rq_map_user_iov(q, rq, iov, hdr->iovec_count);
- kfree(iov);
- } else if (hdr->dxfer_len)
- ret = blk_rq_map_user(q, rq, hdr->dxferp, hdr->dxfer_len);
-
- if (ret)
- goto out;
-
/*
* fill in request structure
*/
@@ -294,7 +269,6 @@ static int sg_io(struct file *file, request_queue_t *q,
rq->sense_len = 0;
rq->cmd_type = REQ_TYPE_BLOCK_PC;
- bio = rq->bio;
/*
* bounce this after holding a reference to the original bio, it's
@@ -309,6 +283,31 @@ static int sg_io(struct file *file, request_queue_t *q,
if (!rq->timeout)
rq->timeout = BLK_DEFAULT_TIMEOUT;
+ if (hdr->iovec_count) {
+ const int size = sizeof(struct sg_iovec) * hdr->iovec_count;
+ struct sg_iovec *iov;
+
+ iov = kmalloc(size, GFP_KERNEL);
+ if (!iov) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ if (copy_from_user(iov, hdr->dxferp, size)) {
+ kfree(iov);
+ ret = -EFAULT;
+ goto out;
+ }
+
+ ret = blk_rq_map_user_iov(q, rq, iov, hdr->iovec_count,
+ hdr->dxfer_len);
+ kfree(iov);
+ } else if (hdr->dxfer_len)
+ ret = blk_rq_map_user(q, rq, hdr->dxferp, hdr->dxfer_len);
+
+ if (ret)
+ goto out;
+
rq->retries = 0;
start_time = jiffies;
@@ -339,7 +338,7 @@ static int sg_io(struct file *file, request_queue_t *q,
hdr->sb_len_wr = len;
}
- if (blk_rq_unmap_user(bio, hdr->dxfer_len))
+ if (blk_rq_unmap_user(rq))
ret = -EFAULT;
/* may not have succeeded, but output values written to control
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 10f160dc75b1..a2f46d587d55 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -267,9 +267,9 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
{
acpi_status status;
- if (dev->firmware_data) {
+ if (dev->archdata.acpi_handle) {
printk(KERN_WARNING PREFIX
- "Drivers changed 'firmware_data' for %s\n", dev->bus_id);
+ "Drivers changed 'acpi_handle' for %s\n", dev->bus_id);
return -EINVAL;
}
get_device(dev);
@@ -278,25 +278,26 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
put_device(dev);
return -EINVAL;
}
- dev->firmware_data = handle;
+ dev->archdata.acpi_handle = handle;
return 0;
}
static int acpi_unbind_one(struct device *dev)
{
- if (!dev->firmware_data)
+ if (!dev->archdata.acpi_handle)
return 0;
- if (dev == acpi_get_physical_device(dev->firmware_data)) {
+ if (dev == acpi_get_physical_device(dev->archdata.acpi_handle)) {
/* acpi_get_physical_device increase refcnt by one */
put_device(dev);
- acpi_detach_data(dev->firmware_data, acpi_glue_data_handler);
- dev->firmware_data = NULL;
+ acpi_detach_data(dev->archdata.acpi_handle,
+ acpi_glue_data_handler);
+ dev->archdata.acpi_handle = NULL;
/* acpi_bind_one increase refcnt by one */
put_device(dev);
} else {
printk(KERN_ERR PREFIX
- "Oops, 'firmware_data' corrupt for %s\n", dev->bus_id);
+ "Oops, 'acpi_handle' corrupt for %s\n", dev->bus_id);
}
return 0;
}
@@ -328,7 +329,8 @@ static int acpi_platform_notify(struct device *dev)
if (!ret) {
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
- acpi_get_name(dev->firmware_data, ACPI_FULL_PATHNAME, &buffer);
+ acpi_get_name(dev->archdata.acpi_handle,
+ ACPI_FULL_PATHNAME, &buffer);
DBG("Device %s -> %s\n", dev->bus_id, (char *)buffer.pointer);
kfree(buffer.pointer);
} else
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index 7ba5e49ab302..6fd174a37149 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -83,10 +83,8 @@ static int acpi_processor_ppc_notifier(struct notifier_block *nb,
goto out;
ppc = (unsigned int)pr->performance_platform_limit;
- if (!ppc)
- goto out;
- if (ppc > pr->performance->state_count)
+ if (ppc >= pr->performance->state_count)
goto out;
cpufreq_verify_within_limits(policy, 0,
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 234197e57e9e..bddb14e91d3c 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -78,6 +78,7 @@ enum {
board_ahci = 0,
board_ahci_vt8251 = 1,
+ board_ahci_ign_iferr = 2,
/* global controller registers */
HOST_CAP = 0x00, /* host capabilities */
@@ -168,6 +169,7 @@ enum {
/* ap->flags bits */
AHCI_FLAG_RESET_NEEDS_CLO = (1 << 24),
AHCI_FLAG_NO_NCQ = (1 << 25),
+ AHCI_FLAG_IGN_IRQ_IF_ERR = (1 << 26), /* ignore IRQ_IF_ERR */
};
struct ahci_cmd_hdr {
@@ -295,6 +297,17 @@ static const struct ata_port_info ahci_port_info[] = {
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
.port_ops = &ahci_ops,
},
+ /* board_ahci_ign_iferr */
+ {
+ .sht = &ahci_sht,
+ .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
+ ATA_FLAG_SKIP_D2H_BSY |
+ AHCI_FLAG_IGN_IRQ_IF_ERR,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .port_ops = &ahci_ops,
+ },
};
static const struct pci_device_id ahci_pci_tbl[] = {
@@ -314,13 +327,24 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */
{ PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */
{ PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */
+ { PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */
+ { PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */
+ { PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */
+ { PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */
+ { PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */
+ { PCI_VDEVICE(INTEL, 0x2929), board_ahci }, /* ICH9M */
+ { PCI_VDEVICE(INTEL, 0x292a), board_ahci }, /* ICH9M */
+ { PCI_VDEVICE(INTEL, 0x292b), board_ahci }, /* ICH9M */
+ { PCI_VDEVICE(INTEL, 0x292f), board_ahci }, /* ICH9M */
+ { PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */
+ { PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */
/* JMicron */
- { PCI_VDEVICE(JMICRON, 0x2360), board_ahci }, /* JMicron JMB360 */
- { PCI_VDEVICE(JMICRON, 0x2361), board_ahci }, /* JMicron JMB361 */
- { PCI_VDEVICE(JMICRON, 0x2363), board_ahci }, /* JMicron JMB363 */
- { PCI_VDEVICE(JMICRON, 0x2365), board_ahci }, /* JMicron JMB365 */
- { PCI_VDEVICE(JMICRON, 0x2366), board_ahci }, /* JMicron JMB366 */
+ { PCI_VDEVICE(JMICRON, 0x2360), board_ahci_ign_iferr }, /* JMB360 */
+ { PCI_VDEVICE(JMICRON, 0x2361), board_ahci_ign_iferr }, /* JMB361 */
+ { PCI_VDEVICE(JMICRON, 0x2363), board_ahci_ign_iferr }, /* JMB363 */
+ { PCI_VDEVICE(JMICRON, 0x2365), board_ahci_ign_iferr }, /* JMB365 */
+ { PCI_VDEVICE(JMICRON, 0x2366), board_ahci_ign_iferr }, /* JMB366 */
/* ATI */
{ PCI_VDEVICE(ATI, 0x4380), board_ahci }, /* ATI SB600 non-raid */
@@ -969,6 +993,10 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
/* analyze @irq_stat */
ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat);
+ /* some controllers set IRQ_IF_ERR on device errors, ignore it */
+ if (ap->flags & AHCI_FLAG_IGN_IRQ_IF_ERR)
+ irq_stat &= ~PORT_IRQ_IF_ERR;
+
if (irq_stat & PORT_IRQ_TF_ERR)
err_mask |= AC_ERR_DEV;
diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c
index 377425e71391..4a80ff9312b8 100644
--- a/drivers/ata/ata_generic.c
+++ b/drivers/ata/ata_generic.c
@@ -116,6 +116,7 @@ static struct scsi_host_template generic_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index c872b324dbd3..4c32d93d44b1 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -1451,6 +1451,7 @@ nothing_to_do:
static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
{
+ struct ata_port *ap = qc->ap;
struct scsi_cmnd *cmd = qc->scsicmd;
u8 *cdb = cmd->cmnd;
int need_sense = (qc->err_mask != 0);
@@ -1459,11 +1460,12 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
* schedule EH_REVALIDATE operation to update the IDENTIFY DEVICE
* cache
*/
- if (!need_sense && (qc->tf.command == ATA_CMD_SET_FEATURES) &&
+ if (ap->ops->error_handler &&
+ !need_sense && (qc->tf.command == ATA_CMD_SET_FEATURES) &&
((qc->tf.feature == SETFEATURES_WC_ON) ||
(qc->tf.feature == SETFEATURES_WC_OFF))) {
- qc->ap->eh_info.action |= ATA_EH_REVALIDATE;
- ata_port_schedule_eh(qc->ap);
+ ap->eh_info.action |= ATA_EH_REVALIDATE;
+ ata_port_schedule_eh(ap);
}
/* For ATA pass thru (SAT) commands, generate a sense block if
@@ -1490,8 +1492,8 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
}
}
- if (need_sense && !qc->ap->ops->error_handler)
- ata_dump_status(qc->ap->id, &qc->result_tf);
+ if (need_sense && !ap->ops->error_handler)
+ ata_dump_status(ap->id, &qc->result_tf);
qc->scsidone(cmd);
@@ -3347,20 +3349,23 @@ EXPORT_SYMBOL_GPL(ata_sas_slave_configure);
* @ap: ATA port to which the command is being sent
*
* RETURNS:
- * Zero.
+ * Return value from __ata_scsi_queuecmd() if @cmd can be queued,
+ * 0 otherwise.
*/
int ata_sas_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *),
struct ata_port *ap)
{
+ int rc = 0;
+
ata_scsi_dump_cdb(ap, cmd);
if (likely(ata_scsi_dev_enabled(ap->device)))
- __ata_scsi_queuecmd(cmd, done, ap->device);
+ rc = __ata_scsi_queuecmd(cmd, done, ap->device);
else {
cmd->result = (DID_BAD_TARGET << 16);
done(cmd);
}
- return 0;
+ return rc;
}
EXPORT_SYMBOL_GPL(ata_sas_queuecmd);
diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c
index 1d695df5860a..64eed99f6814 100644
--- a/drivers/ata/pata_ali.c
+++ b/drivers/ata/pata_ali.c
@@ -346,6 +346,7 @@ static struct scsi_host_template ali_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c
index 5c47a9e0e0ca..8be46a63af74 100644
--- a/drivers/ata/pata_amd.c
+++ b/drivers/ata/pata_amd.c
@@ -333,6 +333,7 @@ static struct scsi_host_template amd_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c
index 96a098020a8f..2cd30761ca1f 100644
--- a/drivers/ata/pata_artop.c
+++ b/drivers/ata/pata_artop.c
@@ -314,6 +314,7 @@ static struct scsi_host_template artop_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c
index 1ce28d2125f4..4e1d3b59adbb 100644
--- a/drivers/ata/pata_atiixp.c
+++ b/drivers/ata/pata_atiixp.c
@@ -216,6 +216,7 @@ static struct scsi_host_template atiixp_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c
index b9bbd1d454bf..29a60df465da 100644
--- a/drivers/ata/pata_cmd64x.c
+++ b/drivers/ata/pata_cmd64x.c
@@ -275,6 +275,7 @@ static struct scsi_host_template cmd64x_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c
index 2cd3c0ff76df..33d2b88f9c79 100644
--- a/drivers/ata/pata_cs5520.c
+++ b/drivers/ata/pata_cs5520.c
@@ -166,6 +166,7 @@ static struct scsi_host_template cs5520_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_cs5530.c b/drivers/ata/pata_cs5530.c
index a07cc81ef791..981f49223469 100644
--- a/drivers/ata/pata_cs5530.c
+++ b/drivers/ata/pata_cs5530.c
@@ -180,6 +180,7 @@ static struct scsi_host_template cs5530_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_cs5535.c b/drivers/ata/pata_cs5535.c
index f8def3f9c618..8dafa4a49fdc 100644
--- a/drivers/ata/pata_cs5535.c
+++ b/drivers/ata/pata_cs5535.c
@@ -184,6 +184,7 @@ static struct scsi_host_template cs5535_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_cypress.c b/drivers/ata/pata_cypress.c
index 247b43608b14..5a0b811907ee 100644
--- a/drivers/ata/pata_cypress.c
+++ b/drivers/ata/pata_cypress.c
@@ -135,6 +135,7 @@ static struct scsi_host_template cy82c693_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c
index ef18c60fe140..755f79279de3 100644
--- a/drivers/ata/pata_efar.c
+++ b/drivers/ata/pata_efar.c
@@ -233,6 +233,7 @@ static struct scsi_host_template efar_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c
index 6d3e4c0f15fe..c0e150a9586b 100644
--- a/drivers/ata/pata_hpt366.c
+++ b/drivers/ata/pata_hpt366.c
@@ -329,6 +329,7 @@ static struct scsi_host_template hpt36x_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c
index fce3fcdc7e79..1eeb16f0fb02 100644
--- a/drivers/ata/pata_hpt37x.c
+++ b/drivers/ata/pata_hpt37x.c
@@ -775,6 +775,7 @@ static struct scsi_host_template hpt37x_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c
index 58cfb2bc8098..47d7664e9eee 100644
--- a/drivers/ata/pata_hpt3x2n.c
+++ b/drivers/ata/pata_hpt3x2n.c
@@ -341,6 +341,7 @@ static struct scsi_host_template hpt3x2n_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c
index 3334d72e251b..d216cc564b56 100644
--- a/drivers/ata/pata_hpt3x3.c
+++ b/drivers/ata/pata_hpt3x3.c
@@ -118,6 +118,7 @@ static struct scsi_host_template hpt3x3_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c
index 640b8b0954f5..40ca2b82b7fc 100644
--- a/drivers/ata/pata_isapnp.c
+++ b/drivers/ata/pata_isapnp.c
@@ -34,6 +34,7 @@ static struct scsi_host_template isapnp_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c
index 18ff3e59a89b..7f68f14be6fd 100644
--- a/drivers/ata/pata_it821x.c
+++ b/drivers/ata/pata_it821x.c
@@ -675,6 +675,7 @@ static struct scsi_host_template it821x_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c
index 52a2bdf3c38d..0210b10d49cd 100644
--- a/drivers/ata/pata_jmicron.c
+++ b/drivers/ata/pata_jmicron.c
@@ -136,6 +136,7 @@ static struct scsi_host_template jmicron_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
/* Use standard CHS mapping rules */
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c
index 10231ef731d1..b39078b2a47b 100644
--- a/drivers/ata/pata_legacy.c
+++ b/drivers/ata/pata_legacy.c
@@ -135,6 +135,7 @@ static struct scsi_host_template legacy_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_mpiix.c b/drivers/ata/pata_mpiix.c
index 9dfe3e9abea3..e00d406bfdf5 100644
--- a/drivers/ata/pata_mpiix.c
+++ b/drivers/ata/pata_mpiix.c
@@ -166,6 +166,7 @@ static struct scsi_host_template mpiix_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_netcell.c b/drivers/ata/pata_netcell.c
index f5672de99c22..1963a4d35873 100644
--- a/drivers/ata/pata_netcell.c
+++ b/drivers/ata/pata_netcell.c
@@ -62,6 +62,7 @@ static struct scsi_host_template netcell_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
/* Use standard CHS mapping rules */
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_ns87410.c b/drivers/ata/pata_ns87410.c
index 2a3dbeed89b4..7ec800f00ec8 100644
--- a/drivers/ata/pata_ns87410.c
+++ b/drivers/ata/pata_ns87410.c
@@ -156,6 +156,7 @@ static struct scsi_host_template ns87410_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c
index fc947dfecd73..8837256632e9 100644
--- a/drivers/ata/pata_oldpiix.c
+++ b/drivers/ata/pata_oldpiix.c
@@ -231,6 +231,7 @@ static struct scsi_host_template oldpiix_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_opti.c b/drivers/ata/pata_opti.c
index a7320ba15575..c6319cf50de4 100644
--- a/drivers/ata/pata_opti.c
+++ b/drivers/ata/pata_opti.c
@@ -202,6 +202,7 @@ static struct scsi_host_template opti_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_optidma.c b/drivers/ata/pata_optidma.c
index c6906b4215de..2f4770cce04e 100644
--- a/drivers/ata/pata_optidma.c
+++ b/drivers/ata/pata_optidma.c
@@ -359,6 +359,7 @@ static struct scsi_host_template optidma_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c
index e93ea2702c73..999922de476e 100644
--- a/drivers/ata/pata_pcmcia.c
+++ b/drivers/ata/pata_pcmcia.c
@@ -69,6 +69,7 @@ static struct scsi_host_template pcmcia_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c
index d894d9918b1d..beb6d10a234b 100644
--- a/drivers/ata/pata_pdc2027x.c
+++ b/drivers/ata/pata_pdc2027x.c
@@ -141,6 +141,7 @@ static struct scsi_host_template pdc2027x_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c
index 5ba9eb20a6c2..6baf51b2fda1 100644
--- a/drivers/ata/pata_pdc202xx_old.c
+++ b/drivers/ata/pata_pdc202xx_old.c
@@ -269,6 +269,7 @@ static struct scsi_host_template pdc_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_qdi.c b/drivers/ata/pata_qdi.c
index 2c3cc0ccc606..314938dea1fc 100644
--- a/drivers/ata/pata_qdi.c
+++ b/drivers/ata/pata_qdi.c
@@ -164,6 +164,7 @@ static struct scsi_host_template qdi_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_radisys.c b/drivers/ata/pata_radisys.c
index 1af83d7694d5..048c2bb21ef1 100644
--- a/drivers/ata/pata_radisys.c
+++ b/drivers/ata/pata_radisys.c
@@ -227,6 +227,7 @@ static struct scsi_host_template radisys_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_rz1000.c b/drivers/ata/pata_rz1000.c
index 4533b6357d99..e4e5ea423fef 100644
--- a/drivers/ata/pata_rz1000.c
+++ b/drivers/ata/pata_rz1000.c
@@ -90,6 +90,7 @@ static struct scsi_host_template rz1000_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c
index 067d9d223e35..0c75dae74764 100644
--- a/drivers/ata/pata_sc1200.c
+++ b/drivers/ata/pata_sc1200.c
@@ -193,6 +193,7 @@ static struct scsi_host_template sc1200_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c
index 5bbf76ec14a4..be7f60efcb61 100644
--- a/drivers/ata/pata_serverworks.c
+++ b/drivers/ata/pata_serverworks.c
@@ -325,6 +325,7 @@ static struct scsi_host_template serverworks_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c
index 4a2b72b4be8a..11942fd03b55 100644
--- a/drivers/ata/pata_sil680.c
+++ b/drivers/ata/pata_sil680.c
@@ -225,6 +225,7 @@ static struct scsi_host_template sil680_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c
index b9ffafb4198c..91e85f90941d 100644
--- a/drivers/ata/pata_sis.c
+++ b/drivers/ata/pata_sis.c
@@ -545,6 +545,7 @@ static struct scsi_host_template sis_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c
index 08a6dc88676f..dc1cfc6d805b 100644
--- a/drivers/ata/pata_sl82c105.c
+++ b/drivers/ata/pata_sl82c105.c
@@ -237,6 +237,7 @@ static struct scsi_host_template sl82c105_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_triflex.c b/drivers/ata/pata_triflex.c
index 9640f80e8b0d..bfda1f7e760a 100644
--- a/drivers/ata/pata_triflex.c
+++ b/drivers/ata/pata_triflex.c
@@ -192,6 +192,7 @@ static struct scsi_host_template triflex_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c
index 1e7be9eee9c3..c5f1616d224d 100644
--- a/drivers/ata/pata_via.c
+++ b/drivers/ata/pata_via.c
@@ -295,6 +295,7 @@ static struct scsi_host_template via_sht = {
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c
index 9fffa7af6db1..afa7d750a593 100644
--- a/drivers/atm/ambassador.c
+++ b/drivers/atm/ambassador.c
@@ -972,7 +972,7 @@ static int make_rate (unsigned int rate, rounding r,
}
case round_up: {
// check all bits that we are discarding
- if (man & (-1>>9)) {
+ if (man & (~0U>>9)) {
man = (man>>(32-9)) + 1;
if (man == (1<<9)) {
// no need to check for round up outside of range
diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c
index 697ad82f6634..9c67df5ccfa4 100644
--- a/drivers/atm/firestream.c
+++ b/drivers/atm/firestream.c
@@ -512,7 +512,7 @@ static unsigned int make_rate (unsigned int rate, int r,
}
case ROUND_UP: {
/* check all bits that we are discarding */
- if (man & (-1>>9)) {
+ if (man & (~0U>>9)) {
man = (man>>(32-9)) + 1;
if (man == (1<<9)) {
/* no need to check for round up outside of range */
diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c
index 9ed1c60048f0..bb7ef570514c 100644
--- a/drivers/atm/iphase.c
+++ b/drivers/atm/iphase.c
@@ -305,7 +305,7 @@ static void clear_lockup (struct atm_vcc *vcc, IADEV *dev) {
** | R | NZ | 5-bit exponent | 9-bit mantissa |
** +----+----+------------------+-------------------------------+
**
-** R = reserverd (written as 0)
+** R = reserved (written as 0)
** NZ = 0 if 0 cells/sec; 1 otherwise
**
** if NZ = 1, rate = 1.mmmmmmmmm x 2^(eeeee) cells/sec
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 7d8a7ce73fb3..472810f8e6e7 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -355,6 +355,21 @@ static void device_remove_attrs(struct bus_type * bus, struct device * dev)
}
}
+#ifdef CONFIG_SYSFS_DEPRECATED
+static int make_deprecated_bus_links(struct device *dev)
+{
+ return sysfs_create_link(&dev->kobj,
+ &dev->bus->subsys.kset.kobj, "bus");
+}
+
+static void remove_deprecated_bus_links(struct device *dev)
+{
+ sysfs_remove_link(&dev->kobj, "bus");
+}
+#else
+static inline int make_deprecated_bus_links(struct device *dev) { return 0; }
+static inline void remove_deprecated_bus_links(struct device *dev) { }
+#endif
/**
* bus_add_device - add device to bus
@@ -381,8 +396,7 @@ int bus_add_device(struct device * dev)
&dev->bus->subsys.kset.kobj, "subsystem");
if (error)
goto out_subsys;
- error = sysfs_create_link(&dev->kobj,
- &dev->bus->subsys.kset.kobj, "bus");
+ error = make_deprecated_bus_links(dev);
if (error)
goto out_deprecated;
}
@@ -436,7 +450,7 @@ void bus_remove_device(struct device * dev)
{
if (dev->bus) {
sysfs_remove_link(&dev->kobj, "subsystem");
- sysfs_remove_link(&dev->kobj, "bus");
+ remove_deprecated_bus_links(dev);
sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id);
device_remove_attrs(dev->bus, dev);
if (dev->is_registered) {
@@ -724,6 +738,8 @@ int bus_register(struct bus_type * bus)
{
int retval;
+ BLOCKING_INIT_NOTIFIER_HEAD(&bus->bus_notifier);
+
retval = kobject_set_name(&bus->subsys.kset.kobj, "%s", bus->name);
if (retval)
goto out;
@@ -782,6 +798,18 @@ void bus_unregister(struct bus_type * bus)
subsystem_unregister(&bus->subsys);
}
+int bus_register_notifier(struct bus_type *bus, struct notifier_block *nb)
+{
+ return blocking_notifier_chain_register(&bus->bus_notifier, nb);
+}
+EXPORT_SYMBOL_GPL(bus_register_notifier);
+
+int bus_unregister_notifier(struct bus_type *bus, struct notifier_block *nb)
+{
+ return blocking_notifier_chain_unregister(&bus->bus_notifier, nb);
+}
+EXPORT_SYMBOL_GPL(bus_unregister_notifier);
+
int __init buses_init(void)
{
return subsystem_register(&bus_subsys);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 0ff267a248db..f098881f45b2 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -352,6 +352,92 @@ static const char *class_uevent_name(struct kset *kset, struct kobject *kobj)
return class_dev->class->name;
}
+#ifdef CONFIG_SYSFS_DEPRECATED
+char *make_class_name(const char *name, struct kobject *kobj)
+{
+ char *class_name;
+ int size;
+
+ size = strlen(name) + strlen(kobject_name(kobj)) + 2;
+
+ class_name = kmalloc(size, GFP_KERNEL);
+ if (!class_name)
+ return ERR_PTR(-ENOMEM);
+
+ strcpy(class_name, name);
+ strcat(class_name, ":");
+ strcat(class_name, kobject_name(kobj));
+ return class_name;
+}
+
+static int deprecated_class_uevent(char **envp, int num_envp, int *cur_index,
+ char *buffer, int buffer_size,
+ int *cur_len,
+ struct class_device *class_dev)
+{
+ struct device *dev = class_dev->dev;
+ char *path;
+
+ if (!dev)
+ return 0;
+
+ /* add device, backing this class device (deprecated) */
+ path = kobject_get_path(&dev->kobj, GFP_KERNEL);
+
+ add_uevent_var(envp, num_envp, cur_index, buffer, buffer_size,
+ cur_len, "PHYSDEVPATH=%s", path);
+ kfree(path);
+
+ if (dev->bus)
+ add_uevent_var(envp, num_envp, cur_index,
+ buffer, buffer_size, cur_len,
+ "PHYSDEVBUS=%s", dev->bus->name);
+
+ if (dev->driver)
+ add_uevent_var(envp, num_envp, cur_index,
+ buffer, buffer_size, cur_len,
+ "PHYSDEVDRIVER=%s", dev->driver->name);
+ return 0;
+}
+
+static int make_deprecated_class_device_links(struct class_device *class_dev)
+{
+ char *class_name;
+ int error;
+
+ if (!class_dev->dev)
+ return 0;
+
+ class_name = make_class_name(class_dev->class->name, &class_dev->kobj);
+ error = sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj,
+ class_name);
+ kfree(class_name);
+ return error;
+}
+
+static void remove_deprecated_class_device_links(struct class_device *class_dev)
+{
+ char *class_name;
+
+ if (!class_dev->dev)
+ return;
+
+ class_name = make_class_name(class_dev->class->name, &class_dev->kobj);
+ sysfs_remove_link(&class_dev->dev->kobj, class_name);
+ kfree(class_name);
+}
+#else
+static inline int deprecated_class_uevent(char **envp, int num_envp,
+ int *cur_index, char *buffer,
+ int buffer_size, int *cur_len,
+ struct class_device *class_dev)
+{ return 0; }
+static inline int make_deprecated_class_device_links(struct class_device *cd)
+{ return 0; }
+static void remove_deprecated_class_device_links(struct class_device *cd)
+{ }
+#endif
+
static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp,
int num_envp, char *buffer, int buffer_size)
{
@@ -362,25 +448,8 @@ static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp,
pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id);
- if (class_dev->dev) {
- /* add device, backing this class device (deprecated) */
- struct device *dev = class_dev->dev;
- char *path = kobject_get_path(&dev->kobj, GFP_KERNEL);
-
- add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
- &length, "PHYSDEVPATH=%s", path);
- kfree(path);
-
- if (dev->bus)
- add_uevent_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "PHYSDEVBUS=%s", dev->bus->name);
-
- if (dev->driver)
- add_uevent_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "PHYSDEVDRIVER=%s", dev->driver->name);
- }
+ deprecated_class_uevent(envp, num_envp, &i, buffer, buffer_size,
+ &length, class_dev);
if (MAJOR(class_dev->devt)) {
add_uevent_var(envp, num_envp, &i,
@@ -506,29 +575,11 @@ void class_device_initialize(struct class_device *class_dev)
INIT_LIST_HEAD(&class_dev->node);
}
-char *make_class_name(const char *name, struct kobject *kobj)
-{
- char *class_name;
- int size;
-
- size = strlen(name) + strlen(kobject_name(kobj)) + 2;
-
- class_name = kmalloc(size, GFP_KERNEL);
- if (!class_name)
- return ERR_PTR(-ENOMEM);
-
- strcpy(class_name, name);
- strcat(class_name, ":");
- strcat(class_name, kobject_name(kobj));
- return class_name;
-}
-
int class_device_add(struct class_device *class_dev)
{
struct class *parent_class = NULL;
struct class_device *parent_class_dev = NULL;
struct class_interface *class_intf;
- char *class_name = NULL;
int error = -EINVAL;
class_dev = class_device_get(class_dev);
@@ -599,20 +650,18 @@ int class_device_add(struct class_device *class_dev)
goto out5;
if (class_dev->dev) {
- class_name = make_class_name(class_dev->class->name,
- &class_dev->kobj);
error = sysfs_create_link(&class_dev->kobj,
&class_dev->dev->kobj, "device");
if (error)
goto out6;
- error = sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj,
- class_name);
- if (error)
- goto out7;
}
error = class_device_add_groups(class_dev);
if (error)
+ goto out7;
+
+ error = make_deprecated_class_device_links(class_dev);
+ if (error)
goto out8;
kobject_uevent(&class_dev->kobj, KOBJ_ADD);
@@ -629,8 +678,7 @@ int class_device_add(struct class_device *class_dev)
goto out1;
out8:
- if (class_dev->dev)
- sysfs_remove_link(&class_dev->kobj, class_name);
+ class_device_remove_groups(class_dev);
out7:
if (class_dev->dev)
sysfs_remove_link(&class_dev->kobj, "device");
@@ -649,7 +697,6 @@ int class_device_add(struct class_device *class_dev)
class_put(parent_class);
out1:
class_device_put(class_dev);
- kfree(class_name);
return error;
}
@@ -726,7 +773,6 @@ void class_device_del(struct class_device *class_dev)
struct class *parent_class = class_dev->class;
struct class_device *parent_device = class_dev->parent;
struct class_interface *class_intf;
- char *class_name = NULL;
if (parent_class) {
down(&parent_class->sem);
@@ -738,10 +784,8 @@ void class_device_del(struct class_device *class_dev)
}
if (class_dev->dev) {
- class_name = make_class_name(class_dev->class->name,
- &class_dev->kobj);
+ remove_deprecated_class_device_links(class_dev);
sysfs_remove_link(&class_dev->kobj, "device");
- sysfs_remove_link(&class_dev->dev->kobj, class_name);
}
sysfs_remove_link(&class_dev->kobj, "subsystem");
class_device_remove_file(class_dev, &class_dev->uevent_attr);
@@ -755,7 +799,6 @@ void class_device_del(struct class_device *class_dev)
class_device_put(parent_device);
class_put(parent_class);
- kfree(class_name);
}
void class_device_unregister(struct class_device *class_dev)
@@ -804,14 +847,17 @@ int class_device_rename(struct class_device *class_dev, char *new_name)
pr_debug("CLASS: renaming '%s' to '%s'\n", class_dev->class_id,
new_name);
+#ifdef CONFIG_SYSFS_DEPRECATED
if (class_dev->dev)
old_class_name = make_class_name(class_dev->class->name,
&class_dev->kobj);
+#endif
strlcpy(class_dev->class_id, new_name, KOBJ_NAME_LEN);
error = kobject_rename(&class_dev->kobj, new_name);
+#ifdef CONFIG_SYSFS_DEPRECATED
if (class_dev->dev) {
new_class_name = make_class_name(class_dev->class->name,
&class_dev->kobj);
@@ -819,6 +865,7 @@ int class_device_rename(struct class_device *class_dev, char *new_name)
new_class_name);
sysfs_remove_link(&class_dev->dev->kobj, old_class_name);
}
+#endif
class_device_put(class_dev);
kfree(old_class_name);
@@ -893,23 +940,6 @@ void class_interface_unregister(struct class_interface *class_intf)
class_put(parent);
}
-int virtual_device_parent(struct device *dev)
-{
- if (!dev->class)
- return -ENODEV;
-
- if (!dev->class->virtual_dir) {
- static struct kobject *virtual_dir = NULL;
-
- if (!virtual_dir)
- virtual_dir = kobject_add_dir(&devices_subsys.kset.kobj, "virtual");
- dev->class->virtual_dir = kobject_add_dir(virtual_dir, dev->class->name);
- }
-
- dev->kobj.parent = dev->class->virtual_dir;
- return 0;
-}
-
int __init classes_init(void)
{
int retval;
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 68ad11af22b4..e4b530ef757d 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -17,6 +17,7 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/kdev_t.h>
+#include <linux/notifier.h>
#include <asm/semaphore.h>
@@ -153,20 +154,24 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp,
"MINOR=%u", MINOR(dev->devt));
}
+#ifdef CONFIG_SYSFS_DEPRECATED
/* add bus name (same as SUBSYSTEM, deprecated) */
if (dev->bus)
add_uevent_var(envp, num_envp, &i,
buffer, buffer_size, &length,
"PHYSDEVBUS=%s", dev->bus->name);
+#endif
/* add driver name (PHYSDEV* values are deprecated)*/
if (dev->driver) {
add_uevent_var(envp, num_envp, &i,
buffer, buffer_size, &length,
"DRIVER=%s", dev->driver->name);
+#ifdef CONFIG_SYSFS_DEPRECATED
add_uevent_var(envp, num_envp, &i,
buffer, buffer_size, &length,
"PHYSDEVDRIVER=%s", dev->driver->name);
+#endif
}
/* terminate, set to next free slot, shrink available space */
@@ -383,6 +388,52 @@ void device_initialize(struct device *dev)
device_init_wakeup(dev, 0);
}
+#ifdef CONFIG_SYSFS_DEPRECATED
+static int setup_parent(struct device *dev, struct device *parent)
+{
+ /* Set the parent to the class, not the parent device */
+ /* this keeps sysfs from having a symlink to make old udevs happy */
+ if (dev->class)
+ dev->kobj.parent = &dev->class->subsys.kset.kobj;
+ else if (parent)
+ dev->kobj.parent = &parent->kobj;
+
+ return 0;
+}
+#else
+static int virtual_device_parent(struct device *dev)
+{
+ if (!dev->class)
+ return -ENODEV;
+
+ if (!dev->class->virtual_dir) {
+ static struct kobject *virtual_dir = NULL;
+
+ if (!virtual_dir)
+ virtual_dir = kobject_add_dir(&devices_subsys.kset.kobj, "virtual");
+ dev->class->virtual_dir = kobject_add_dir(virtual_dir, dev->class->name);
+ }
+
+ dev->kobj.parent = dev->class->virtual_dir;
+ return 0;
+}
+
+static int setup_parent(struct device *dev, struct device *parent)
+{
+ int error;
+
+ /* if this is a class device, and has no parent, create one */
+ if ((dev->class) && (parent == NULL)) {
+ error = virtual_device_parent(dev);
+ if (error)
+ return error;
+ } else if (parent)
+ dev->kobj.parent = &parent->kobj;
+
+ return 0;
+}
+#endif
+
/**
* device_add - add device to device hierarchy.
* @dev: device.
@@ -405,29 +456,29 @@ int device_add(struct device *dev)
if (!dev || !strlen(dev->bus_id))
goto Error;
- /* if this is a class device, and has no parent, create one */
- if ((dev->class) && (dev->parent == NULL)) {
- error = virtual_device_parent(dev);
- if (error)
- goto Error;
- }
+ pr_debug("DEV: registering device: ID = '%s'\n", dev->bus_id);
parent = get_device(dev->parent);
- pr_debug("DEV: registering device: ID = '%s'\n", dev->bus_id);
+ error = setup_parent(dev, parent);
+ if (error)
+ goto Error;
/* first, register with generic layer. */
kobject_set_name(&dev->kobj, "%s", dev->bus_id);
- if (parent)
- dev->kobj.parent = &parent->kobj;
-
- if ((error = kobject_add(&dev->kobj)))
+ error = kobject_add(&dev->kobj);
+ if (error)
goto Error;
/* notify platform of device entry */
if (platform_notify)
platform_notify(dev);
+ /* notify clients of device entry (new way) */
+ if (dev->bus)
+ blocking_notifier_call_chain(&dev->bus->bus_notifier,
+ BUS_NOTIFY_ADD_DEVICE, dev);
+
dev->uevent_attr.attr.name = "uevent";
dev->uevent_attr.attr.mode = S_IWUSR;
if (dev->driver)
@@ -461,13 +512,18 @@ int device_add(struct device *dev)
if (dev->class) {
sysfs_create_link(&dev->kobj, &dev->class->subsys.kset.kobj,
"subsystem");
- sysfs_create_link(&dev->class->subsys.kset.kobj, &dev->kobj,
- dev->bus_id);
+ /* If this is not a "fake" compatible device, then create the
+ * symlink from the class to the device. */
+ if (dev->kobj.parent != &dev->class->subsys.kset.kobj)
+ sysfs_create_link(&dev->class->subsys.kset.kobj,
+ &dev->kobj, dev->bus_id);
+#ifdef CONFIG_SYSFS_DEPRECATED
if (parent) {
sysfs_create_link(&dev->kobj, &dev->parent->kobj, "device");
class_name = make_class_name(dev->class->name, &dev->kobj);
sysfs_create_link(&dev->parent->kobj, &dev->kobj, class_name);
}
+#endif
}
if ((error = device_add_attrs(dev)))
@@ -504,6 +560,9 @@ int device_add(struct device *dev)
BusError:
device_pm_remove(dev);
PMError:
+ if (dev->bus)
+ blocking_notifier_call_chain(&dev->bus->bus_notifier,
+ BUS_NOTIFY_DEL_DEVICE, dev);
device_remove_groups(dev);
GroupError:
device_remove_attrs(dev);
@@ -586,22 +645,31 @@ void put_device(struct device * dev)
void device_del(struct device * dev)
{
struct device * parent = dev->parent;
- char *class_name = NULL;
struct class_interface *class_intf;
if (parent)
klist_del(&dev->knode_parent);
- if (dev->devt_attr)
+ if (dev->devt_attr) {
device_remove_file(dev, dev->devt_attr);
+ kfree(dev->devt_attr);
+ }
if (dev->class) {
sysfs_remove_link(&dev->kobj, "subsystem");
- sysfs_remove_link(&dev->class->subsys.kset.kobj, dev->bus_id);
- class_name = make_class_name(dev->class->name, &dev->kobj);
+ /* If this is not a "fake" compatible device, remove the
+ * symlink from the class to the device. */
+ if (dev->kobj.parent != &dev->class->subsys.kset.kobj)
+ sysfs_remove_link(&dev->class->subsys.kset.kobj,
+ dev->bus_id);
+#ifdef CONFIG_SYSFS_DEPRECATED
if (parent) {
- sysfs_remove_link(&dev->kobj, "device");
+ char *class_name = make_class_name(dev->class->name,
+ &dev->kobj);
sysfs_remove_link(&dev->parent->kobj, class_name);
+ kfree(class_name);
+ sysfs_remove_link(&dev->kobj, "device");
}
- kfree(class_name);
+#endif
+
down(&dev->class->sem);
/* notify any interfaces that the device is now gone */
list_for_each_entry(class_intf, &dev->class->interfaces, node)
@@ -614,13 +682,16 @@ void device_del(struct device * dev)
device_remove_file(dev, &dev->uevent_attr);
device_remove_groups(dev);
device_remove_attrs(dev);
+ bus_remove_device(dev);
/* Notify the platform of the removal, in case they
* need to do anything...
*/
if (platform_notify_remove)
platform_notify_remove(dev);
- bus_remove_device(dev);
+ if (dev->bus)
+ blocking_notifier_call_chain(&dev->bus->bus_notifier,
+ BUS_NOTIFY_DEL_DEVICE, dev);
device_pm_remove(dev);
kobject_uevent(&dev->kobj, KOBJ_REMOVE);
kobject_del(&dev->kobj);
@@ -679,12 +750,45 @@ int device_for_each_child(struct device * parent, void * data,
return error;
}
+/**
+ * device_find_child - device iterator for locating a particular device.
+ * @parent: parent struct device
+ * @data: Data to pass to match function
+ * @match: Callback function to check device
+ *
+ * This is similar to the device_for_each_child() function above, but it
+ * returns a reference to a device that is 'found' for later use, as
+ * determined by the @match callback.
+ *
+ * The callback should return 0 if the device doesn't match and non-zero
+ * if it does. If the callback returns non-zero and a reference to the
+ * current device can be obtained, this function will return to the caller
+ * and not iterate over any more devices.
+ */
+struct device * device_find_child(struct device *parent, void *data,
+ int (*match)(struct device *, void *))
+{
+ struct klist_iter i;
+ struct device *child;
+
+ if (!parent)
+ return NULL;
+
+ klist_iter_init(&parent->klist_children, &i);
+ while ((child = next_device(&i)))
+ if (match(child, data) && get_device(child))
+ break;
+ klist_iter_exit(&i);
+ return child;
+}
+
int __init devices_init(void)
{
return subsystem_register(&devices_subsys);
}
EXPORT_SYMBOL_GPL(device_for_each_child);
+EXPORT_SYMBOL_GPL(device_find_child);
EXPORT_SYMBOL_GPL(device_initialize);
EXPORT_SYMBOL_GPL(device_add);
@@ -807,8 +911,10 @@ int device_rename(struct device *dev, char *new_name)
pr_debug("DEVICE: renaming '%s' to '%s'\n", dev->bus_id, new_name);
+#ifdef CONFIG_SYSFS_DEPRECATED
if ((dev->class) && (dev->parent))
old_class_name = make_class_name(dev->class->name, &dev->kobj);
+#endif
if (dev->class) {
old_symlink_name = kmalloc(BUS_ID_SIZE, GFP_KERNEL);
@@ -823,6 +929,7 @@ int device_rename(struct device *dev, char *new_name)
error = kobject_rename(&dev->kobj, new_name);
+#ifdef CONFIG_SYSFS_DEPRECATED
if (old_class_name) {
new_class_name = make_class_name(dev->class->name, &dev->kobj);
if (new_class_name) {
@@ -831,6 +938,8 @@ int device_rename(struct device *dev, char *new_name)
sysfs_remove_link(&dev->parent->kobj, old_class_name);
}
}
+#endif
+
if (dev->class) {
sysfs_remove_link(&dev->class->subsys.kset.kobj,
old_symlink_name);
@@ -846,3 +955,95 @@ int device_rename(struct device *dev, char *new_name)
return error;
}
+
+
+static int device_move_class_links(struct device *dev,
+ struct device *old_parent,
+ struct device *new_parent)
+{
+#ifdef CONFIG_SYSFS_DEPRECATED
+ int error;
+ char *class_name;
+
+ class_name = make_class_name(dev->class->name, &dev->kobj);
+ if (!class_name) {
+ error = PTR_ERR(class_name);
+ class_name = NULL;
+ goto out;
+ }
+ if (old_parent) {
+ sysfs_remove_link(&dev->kobj, "device");
+ sysfs_remove_link(&old_parent->kobj, class_name);
+ }
+ error = sysfs_create_link(&dev->kobj, &new_parent->kobj, "device");
+ if (error)
+ goto out;
+ error = sysfs_create_link(&new_parent->kobj, &dev->kobj, class_name);
+ if (error)
+ sysfs_remove_link(&dev->kobj, "device");
+out:
+ kfree(class_name);
+ return error;
+#else
+ return 0;
+#endif
+}
+
+/**
+ * device_move - moves a device to a new parent
+ * @dev: the pointer to the struct device to be moved
+ * @new_parent: the new parent of the device
+ */
+int device_move(struct device *dev, struct device *new_parent)
+{
+ int error;
+ struct device *old_parent;
+
+ dev = get_device(dev);
+ if (!dev)
+ return -EINVAL;
+
+ if (!device_is_registered(dev)) {
+ error = -EINVAL;
+ goto out;
+ }
+ new_parent = get_device(new_parent);
+ if (!new_parent) {
+ error = -EINVAL;
+ goto out;
+ }
+ pr_debug("DEVICE: moving '%s' to '%s'\n", dev->bus_id,
+ new_parent->bus_id);
+ error = kobject_move(&dev->kobj, &new_parent->kobj);
+ if (error) {
+ put_device(new_parent);
+ goto out;
+ }
+ old_parent = dev->parent;
+ dev->parent = new_parent;
+ if (old_parent)
+ klist_remove(&dev->knode_parent);
+ klist_add_tail(&dev->knode_parent, &new_parent->klist_children);
+ if (!dev->class)
+ goto out_put;
+ error = device_move_class_links(dev, old_parent, new_parent);
+ if (error) {
+ /* We ignore errors on cleanup since we're hosed anyway... */
+ device_move_class_links(dev, new_parent, old_parent);
+ if (!kobject_move(&dev->kobj, &old_parent->kobj)) {
+ klist_remove(&dev->knode_parent);
+ if (old_parent)
+ klist_add_tail(&dev->knode_parent,
+ &old_parent->klist_children);
+ }
+ put_device(new_parent);
+ goto out;
+ }
+out_put:
+ put_device(old_parent);
+out:
+ put_device(dev);
+ return error;
+}
+
+EXPORT_SYMBOL_GPL(device_move);
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index c5d6bb4290ad..510e7884975f 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -26,33 +26,28 @@
#define to_drv(node) container_of(node, struct device_driver, kobj.entry)
-/**
- * device_bind_driver - bind a driver to one device.
- * @dev: device.
- *
- * Allow manual attachment of a driver to a device.
- * Caller must have already set @dev->driver.
- *
- * Note that this does not modify the bus reference count
- * nor take the bus's rwsem. Please verify those are accounted
- * for before calling this. (It is ok to call with no other effort
- * from a driver's probe() method.)
- *
- * This function must be called with @dev->sem held.
- */
-int device_bind_driver(struct device *dev)
+static void driver_bound(struct device *dev)
{
- int ret;
-
if (klist_node_attached(&dev->knode_driver)) {
printk(KERN_WARNING "%s: device %s already bound\n",
__FUNCTION__, kobject_name(&dev->kobj));
- return 0;
+ return;
}
pr_debug("bound device '%s' to driver '%s'\n",
dev->bus_id, dev->driver->name);
+
+ if (dev->bus)
+ blocking_notifier_call_chain(&dev->bus->bus_notifier,
+ BUS_NOTIFY_BOUND_DRIVER, dev);
+
klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices);
+}
+
+static int driver_sysfs_add(struct device *dev)
+{
+ int ret;
+
ret = sysfs_create_link(&dev->driver->kobj, &dev->kobj,
kobject_name(&dev->kobj));
if (ret == 0) {
@@ -65,6 +60,36 @@ int device_bind_driver(struct device *dev)
return ret;
}
+static void driver_sysfs_remove(struct device *dev)
+{
+ struct device_driver *drv = dev->driver;
+
+ if (drv) {
+ sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj));
+ sysfs_remove_link(&dev->kobj, "driver");
+ }
+}
+
+/**
+ * device_bind_driver - bind a driver to one device.
+ * @dev: device.
+ *
+ * Allow manual attachment of a driver to a device.
+ * Caller must have already set @dev->driver.
+ *
+ * Note that this does not modify the bus reference count
+ * nor take the bus's rwsem. Please verify those are accounted
+ * for before calling this. (It is ok to call with no other effort
+ * from a driver's probe() method.)
+ *
+ * This function must be called with @dev->sem held.
+ */
+int device_bind_driver(struct device *dev)
+{
+ driver_bound(dev);
+ return driver_sysfs_add(dev);
+}
+
struct stupid_thread_structure {
struct device_driver *drv;
struct device *dev;
@@ -85,30 +110,32 @@ static int really_probe(void *void_data)
drv->bus->name, drv->name, dev->bus_id);
dev->driver = drv;
+ if (driver_sysfs_add(dev)) {
+ printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
+ __FUNCTION__, dev->bus_id);
+ goto probe_failed;
+ }
+
if (dev->bus->probe) {
ret = dev->bus->probe(dev);
- if (ret) {
- dev->driver = NULL;
+ if (ret)
goto probe_failed;
- }
} else if (drv->probe) {
ret = drv->probe(dev);
- if (ret) {
- dev->driver = NULL;
+ if (ret)
goto probe_failed;
- }
- }
- if (device_bind_driver(dev)) {
- printk(KERN_ERR "%s: device_bind_driver(%s) failed\n",
- __FUNCTION__, dev->bus_id);
- /* How does undo a ->probe? We're screwed. */
}
+
+ driver_bound(dev);
ret = 1;
pr_debug("%s: Bound Device %s to Driver %s\n",
drv->bus->name, dev->bus_id, drv->name);
goto done;
probe_failed:
+ driver_sysfs_remove(dev);
+ dev->driver = NULL;
+
if (ret == -ENODEV || ret == -ENXIO) {
/* Driver matched, but didn't support device
* or device not found.
@@ -284,10 +311,15 @@ static void __device_release_driver(struct device * dev)
drv = dev->driver;
if (drv) {
get_driver(drv);
- sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj));
+ driver_sysfs_remove(dev);
sysfs_remove_link(&dev->kobj, "driver");
klist_remove(&dev->knode_driver);
+ if (dev->bus)
+ blocking_notifier_call_chain(&dev->bus->bus_notifier,
+ BUS_NOTIFY_UNBIND_DRIVER,
+ dev);
+
if (dev->bus && dev->bus->remove)
dev->bus->remove(dev);
else if (drv->remove)
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 14615694ae9a..4bad2870c485 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -21,6 +21,8 @@
#include <linux/firmware.h>
#include "base.h"
+#define to_dev(obj) container_of(obj, struct device, kobj)
+
MODULE_AUTHOR("Manuel Estrada Sainz <ranty@debian.org>");
MODULE_DESCRIPTION("Multi purpose firmware loading support");
MODULE_LICENSE("GPL");
@@ -86,12 +88,12 @@ firmware_timeout_store(struct class *class, const char *buf, size_t count)
static CLASS_ATTR(timeout, 0644, firmware_timeout_show, firmware_timeout_store);
-static void fw_class_dev_release(struct class_device *class_dev);
+static void fw_dev_release(struct device *dev);
-static int firmware_class_uevent(struct class_device *class_dev, char **envp,
- int num_envp, char *buffer, int buffer_size)
+static int firmware_uevent(struct device *dev, char **envp, int num_envp,
+ char *buffer, int buffer_size)
{
- struct firmware_priv *fw_priv = class_get_devdata(class_dev);
+ struct firmware_priv *fw_priv = dev_get_drvdata(dev);
int i = 0, len = 0;
if (!test_bit(FW_STATUS_READY, &fw_priv->status))
@@ -110,21 +112,21 @@ static int firmware_class_uevent(struct class_device *class_dev, char **envp,
static struct class firmware_class = {
.name = "firmware",
- .uevent = firmware_class_uevent,
- .release = fw_class_dev_release,
+ .dev_uevent = firmware_uevent,
+ .dev_release = fw_dev_release,
};
-static ssize_t
-firmware_loading_show(struct class_device *class_dev, char *buf)
+static ssize_t firmware_loading_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
- struct firmware_priv *fw_priv = class_get_devdata(class_dev);
+ struct firmware_priv *fw_priv = dev_get_drvdata(dev);
int loading = test_bit(FW_STATUS_LOADING, &fw_priv->status);
return sprintf(buf, "%d\n", loading);
}
/**
* firmware_loading_store - set value in the 'loading' control file
- * @class_dev: class_device pointer
+ * @dev: device pointer
* @buf: buffer to scan for loading control value
* @count: number of bytes in @buf
*
@@ -134,11 +136,11 @@ firmware_loading_show(struct class_device *class_dev, char *buf)
* 0: Conclude the load and hand the data to the driver code.
* -1: Conclude the load with an error and discard any written data.
**/
-static ssize_t
-firmware_loading_store(struct class_device *class_dev,
- const char *buf, size_t count)
+static ssize_t firmware_loading_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
- struct firmware_priv *fw_priv = class_get_devdata(class_dev);
+ struct firmware_priv *fw_priv = dev_get_drvdata(dev);
int loading = simple_strtol(buf, NULL, 10);
switch (loading) {
@@ -174,15 +176,14 @@ firmware_loading_store(struct class_device *class_dev,
return count;
}
-static CLASS_DEVICE_ATTR(loading, 0644,
- firmware_loading_show, firmware_loading_store);
+static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store);
static ssize_t
firmware_data_read(struct kobject *kobj,
char *buffer, loff_t offset, size_t count)
{
- struct class_device *class_dev = to_class_dev(kobj);
- struct firmware_priv *fw_priv = class_get_devdata(class_dev);
+ struct device *dev = to_dev(kobj);
+ struct firmware_priv *fw_priv = dev_get_drvdata(dev);
struct firmware *fw;
ssize_t ret_count = count;
@@ -234,7 +235,7 @@ fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
/**
* firmware_data_write - write method for firmware
- * @kobj: kobject for the class_device
+ * @kobj: kobject for the device
* @buffer: buffer being written
* @offset: buffer offset for write in total data store area
* @count: buffer size
@@ -246,8 +247,8 @@ static ssize_t
firmware_data_write(struct kobject *kobj,
char *buffer, loff_t offset, size_t count)
{
- struct class_device *class_dev = to_class_dev(kobj);
- struct firmware_priv *fw_priv = class_get_devdata(class_dev);
+ struct device *dev = to_dev(kobj);
+ struct firmware_priv *fw_priv = dev_get_drvdata(dev);
struct firmware *fw;
ssize_t retval;
@@ -280,13 +281,12 @@ static struct bin_attribute firmware_attr_data_tmpl = {
.write = firmware_data_write,
};
-static void
-fw_class_dev_release(struct class_device *class_dev)
+static void fw_dev_release(struct device *dev)
{
- struct firmware_priv *fw_priv = class_get_devdata(class_dev);
+ struct firmware_priv *fw_priv = dev_get_drvdata(dev);
kfree(fw_priv);
- kfree(class_dev);
+ kfree(dev);
module_put(THIS_MODULE);
}
@@ -298,26 +298,23 @@ firmware_class_timeout(u_long data)
fw_load_abort(fw_priv);
}
-static inline void
-fw_setup_class_device_id(struct class_device *class_dev, struct device *dev)
+static inline void fw_setup_device_id(struct device *f_dev, struct device *dev)
{
/* XXX warning we should watch out for name collisions */
- strlcpy(class_dev->class_id, dev->bus_id, BUS_ID_SIZE);
+ strlcpy(f_dev->bus_id, dev->bus_id, BUS_ID_SIZE);
}
-static int
-fw_register_class_device(struct class_device **class_dev_p,
- const char *fw_name, struct device *device)
+static int fw_register_device(struct device **dev_p, const char *fw_name,
+ struct device *device)
{
int retval;
struct firmware_priv *fw_priv = kzalloc(sizeof(*fw_priv),
GFP_KERNEL);
- struct class_device *class_dev = kzalloc(sizeof(*class_dev),
- GFP_KERNEL);
+ struct device *f_dev = kzalloc(sizeof(*f_dev), GFP_KERNEL);
- *class_dev_p = NULL;
+ *dev_p = NULL;
- if (!fw_priv || !class_dev) {
+ if (!fw_priv || !f_dev) {
printk(KERN_ERR "%s: kmalloc failed\n", __FUNCTION__);
retval = -ENOMEM;
goto error_kfree;
@@ -331,55 +328,54 @@ fw_register_class_device(struct class_device **class_dev_p,
fw_priv->timeout.data = (u_long) fw_priv;
init_timer(&fw_priv->timeout);
- fw_setup_class_device_id(class_dev, device);
- class_dev->dev = device;
- class_dev->class = &firmware_class;
- class_set_devdata(class_dev, fw_priv);
- retval = class_device_register(class_dev);
+ fw_setup_device_id(f_dev, device);
+ f_dev->parent = device;
+ f_dev->class = &firmware_class;
+ dev_set_drvdata(f_dev, fw_priv);
+ retval = device_register(f_dev);
if (retval) {
- printk(KERN_ERR "%s: class_device_register failed\n",
+ printk(KERN_ERR "%s: device_register failed\n",
__FUNCTION__);
goto error_kfree;
}
- *class_dev_p = class_dev;
+ *dev_p = f_dev;
return 0;
error_kfree:
kfree(fw_priv);
- kfree(class_dev);
+ kfree(f_dev);
return retval;
}
-static int
-fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p,
- const char *fw_name, struct device *device, int uevent)
+static int fw_setup_device(struct firmware *fw, struct device **dev_p,
+ const char *fw_name, struct device *device,
+ int uevent)
{
- struct class_device *class_dev;
+ struct device *f_dev;
struct firmware_priv *fw_priv;
int retval;
- *class_dev_p = NULL;
- retval = fw_register_class_device(&class_dev, fw_name, device);
+ *dev_p = NULL;
+ retval = fw_register_device(&f_dev, fw_name, device);
if (retval)
goto out;
/* Need to pin this module until class device is destroyed */
__module_get(THIS_MODULE);
- fw_priv = class_get_devdata(class_dev);
+ fw_priv = dev_get_drvdata(f_dev);
fw_priv->fw = fw;
- retval = sysfs_create_bin_file(&class_dev->kobj, &fw_priv->attr_data);
+ retval = sysfs_create_bin_file(&f_dev->kobj, &fw_priv->attr_data);
if (retval) {
printk(KERN_ERR "%s: sysfs_create_bin_file failed\n",
__FUNCTION__);
goto error_unreg;
}
- retval = class_device_create_file(class_dev,
- &class_device_attr_loading);
+ retval = device_create_file(f_dev, &dev_attr_loading);
if (retval) {
- printk(KERN_ERR "%s: class_device_create_file failed\n",
+ printk(KERN_ERR "%s: device_create_file failed\n",
__FUNCTION__);
goto error_unreg;
}
@@ -388,11 +384,11 @@ fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p,
set_bit(FW_STATUS_READY, &fw_priv->status);
else
set_bit(FW_STATUS_READY_NOHOTPLUG, &fw_priv->status);
- *class_dev_p = class_dev;
+ *dev_p = f_dev;
goto out;
error_unreg:
- class_device_unregister(class_dev);
+ device_unregister(f_dev);
out:
return retval;
}
@@ -401,7 +397,7 @@ static int
_request_firmware(const struct firmware **firmware_p, const char *name,
struct device *device, int uevent)
{
- struct class_device *class_dev;
+ struct device *f_dev;
struct firmware_priv *fw_priv;
struct firmware *firmware;
int retval;
@@ -417,12 +413,11 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
goto out;
}
- retval = fw_setup_class_device(firmware, &class_dev, name, device,
- uevent);
+ retval = fw_setup_device(firmware, &f_dev, name, device, uevent);
if (retval)
goto error_kfree_fw;
- fw_priv = class_get_devdata(class_dev);
+ fw_priv = dev_get_drvdata(f_dev);
if (uevent) {
if (loading_timeout > 0) {
@@ -430,7 +425,7 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
add_timer(&fw_priv->timeout);
}
- kobject_uevent(&class_dev->kobj, KOBJ_ADD);
+ kobject_uevent(&f_dev->kobj, KOBJ_ADD);
wait_for_completion(&fw_priv->completion);
set_bit(FW_STATUS_DONE, &fw_priv->status);
del_timer_sync(&fw_priv->timeout);
@@ -445,7 +440,7 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
}
fw_priv->fw = NULL;
mutex_unlock(&fw_lock);
- class_device_unregister(class_dev);
+ device_unregister(f_dev);
goto out;
error_kfree_fw:
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 940ce41f1887..d1df4a087924 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -388,6 +388,11 @@ static int platform_drv_probe(struct device *_dev)
return drv->probe(dev);
}
+static int platform_drv_probe_fail(struct device *_dev)
+{
+ return -ENXIO;
+}
+
static int platform_drv_remove(struct device *_dev)
{
struct platform_driver *drv = to_platform_driver(_dev->driver);
@@ -451,6 +456,49 @@ void platform_driver_unregister(struct platform_driver *drv)
}
EXPORT_SYMBOL_GPL(platform_driver_unregister);
+/**
+ * platform_driver_probe - register driver for non-hotpluggable device
+ * @drv: platform driver structure
+ * @probe: the driver probe routine, probably from an __init section
+ *
+ * Use this instead of platform_driver_register() when you know the device
+ * is not hotpluggable and has already been registered, and you want to
+ * remove its run-once probe() infrastructure from memory after the driver
+ * has bound to the device.
+ *
+ * One typical use for this would be with drivers for controllers integrated
+ * into system-on-chip processors, where the controller devices have been
+ * configured as part of board setup.
+ *
+ * Returns zero if the driver registered and bound to a device, else returns
+ * a negative error code and with the driver not registered.
+ */
+int platform_driver_probe(struct platform_driver *drv,
+ int (*probe)(struct platform_device *))
+{
+ int retval, code;
+
+ /* temporary section violation during probe() */
+ drv->probe = probe;
+ retval = code = platform_driver_register(drv);
+
+ /* Fixup that section violation, being paranoid about code scanning
+ * the list of drivers in order to probe new devices. Check to see
+ * if the probe was successful, and make sure any forced probes of
+ * new devices fail.
+ */
+ spin_lock(&platform_bus_type.klist_drivers.k_lock);
+ drv->probe = NULL;
+ if (code == 0 && list_empty(&drv->driver.klist_devices.k_list))
+ retval = -ENODEV;
+ drv->driver.probe = platform_drv_probe_fail;
+ spin_unlock(&platform_bus_type.klist_drivers.k_lock);
+
+ if (code != retval)
+ platform_driver_unregister(drv);
+ return retval;
+}
+EXPORT_SYMBOL_GPL(platform_driver_probe);
/* modalias support enables more hands-off userspace setup:
* (a) environment variable lets new-style hotplug events work once system is
diff --git a/drivers/base/topology.c b/drivers/base/topology.c
index 28dccb730af9..3d12b85b0962 100644
--- a/drivers/base/topology.c
+++ b/drivers/base/topology.c
@@ -94,54 +94,63 @@ static struct attribute_group topology_attr_group = {
.name = "topology"
};
+static cpumask_t topology_dev_map = CPU_MASK_NONE;
+
/* Add/Remove cpu_topology interface for CPU device */
-static int __cpuinit topology_add_dev(struct sys_device * sys_dev)
+static int __cpuinit topology_add_dev(unsigned int cpu)
{
- return sysfs_create_group(&sys_dev->kobj, &topology_attr_group);
+ int rc;
+ struct sys_device *sys_dev = get_cpu_sysdev(cpu);
+
+ rc = sysfs_create_group(&sys_dev->kobj, &topology_attr_group);
+ if (!rc)
+ cpu_set(cpu, topology_dev_map);
+ return rc;
}
-static int __cpuinit topology_remove_dev(struct sys_device * sys_dev)
+#ifdef CONFIG_HOTPLUG_CPU
+static void __cpuinit topology_remove_dev(unsigned int cpu)
{
+ struct sys_device *sys_dev = get_cpu_sysdev(cpu);
+
+ if (!cpu_isset(cpu, topology_dev_map))
+ return;
+ cpu_clear(cpu, topology_dev_map);
sysfs_remove_group(&sys_dev->kobj, &topology_attr_group);
- return 0;
}
static int __cpuinit topology_cpu_callback(struct notifier_block *nfb,
- unsigned long action, void *hcpu)
+ unsigned long action, void *hcpu)
{
unsigned int cpu = (unsigned long)hcpu;
- struct sys_device *sys_dev;
+ int rc = 0;
- sys_dev = get_cpu_sysdev(cpu);
switch (action) {
- case CPU_ONLINE:
- topology_add_dev(sys_dev);
+ case CPU_UP_PREPARE:
+ rc = topology_add_dev(cpu);
break;
+ case CPU_UP_CANCELED:
case CPU_DEAD:
- topology_remove_dev(sys_dev);
+ topology_remove_dev(cpu);
break;
}
- return NOTIFY_OK;
+ return rc ? NOTIFY_BAD : NOTIFY_OK;
}
-
-static struct notifier_block __cpuinitdata topology_cpu_notifier =
-{
- .notifier_call = topology_cpu_callback,
-};
+#endif
static int __cpuinit topology_sysfs_init(void)
{
- int i;
+ int cpu;
+ int rc;
- for_each_online_cpu(i) {
- topology_cpu_callback(&topology_cpu_notifier, CPU_ONLINE,
- (void *)(long)i);
+ for_each_online_cpu(cpu) {
+ rc = topology_add_dev(cpu);
+ if (rc)
+ return rc;
}
-
- register_hotcpu_notifier(&topology_cpu_notifier);
+ hotcpu_notifier(topology_cpu_callback, 0);
return 0;
}
device_initcall(topology_sysfs_init);
-
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 7ea0f48f8fa6..2df5cf4ec743 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -2133,16 +2133,14 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
rq->timeout = 60 * HZ;
bio = rq->bio;
- if (rq->bio)
- blk_queue_bounce(q, &rq->bio);
-
if (blk_execute_rq(q, cdi->disk, rq, 0)) {
struct request_sense *s = rq->sense;
ret = -EIO;
cdi->last_sense = s->sense_key;
}
- if (blk_rq_unmap_user(bio, len))
+ rq->bio = bio;
+ if (blk_rq_unmap_user(rq))
ret = -EFAULT;
if (ret)
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 2af12fc45115..24f922f12783 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -855,39 +855,6 @@ config TANBAC_TB0219
depends TANBAC_TB022X
select GPIO_VR41XX
-menu "Ftape, the floppy tape device driver"
-
-config FTAPE
- tristate "Ftape (QIC-80/Travan) support"
- depends on BROKEN_ON_SMP && (ALPHA || X86)
- ---help---
- If you have a tape drive that is connected to your floppy
- controller, say Y here.
-
- Some tape drives (like the Seagate "Tape Store 3200" or the Iomega
- "Ditto 3200" or the Exabyte "Eagle TR-3") come with a "high speed"
- controller of their own. These drives (and their companion
- controllers) are also supported if you say Y here.
-
- If you have a special controller (such as the CMS FC-10, FC-20,
- Mountain Mach-II, or any controller that is based on the Intel 82078
- FDC like the high speed controllers by Seagate and Exabyte and
- Iomega's "Ditto Dash") you must configure it by selecting the
- appropriate entries from the "Floppy tape controllers" sub-menu
- below and possibly modify the default values for the IRQ and DMA
- channel and the IO base in ftape's configuration menu.
-
- If you want to use your floppy tape drive on a PCI-bus based system,
- please read the file <file:drivers/char/ftape/README.PCI>.
-
- The ftape kernel driver is also available as a runtime loadable
- module. To compile this driver as a module, choose M here: the
- module will be called ftape.
-
-source "drivers/char/ftape/Kconfig"
-
-endmenu
-
source "drivers/char/agp/Kconfig"
source "drivers/char/drm/Kconfig"
@@ -994,7 +961,7 @@ config HPET
help
If you say Y here, you will have a miscdevice named "/dev/hpet/". Each
open selects one of the timers supported by the HPET. The timers are
- non-periodioc and/or periodic.
+ non-periodic and/or periodic.
config HPET_RTC_IRQ
bool "HPET Control RTC IRQ" if !HPET_EMULATE_RTC
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 777cad045094..b1fcdab90947 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -78,7 +78,6 @@ obj-$(CONFIG_TOSHIBA) += toshiba.o
obj-$(CONFIG_I8K) += i8k.o
obj-$(CONFIG_DS1620) += ds1620.o
obj-$(CONFIG_HW_RANDOM) += hw_random/
-obj-$(CONFIG_FTAPE) += ftape/
obj-$(CONFIG_COBALT_LCD) += lcd.o
obj-$(CONFIG_PPDEV) += ppdev.o
obj-$(CONFIG_NWBUTTON) += nwbutton.o
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index c39200161688..5ff457b41efb 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -1054,7 +1054,7 @@ void *agp_generic_alloc_page(struct agp_bridge_data *bridge)
{
struct page * page;
- page = alloc_page(GFP_KERNEL);
+ page = alloc_page(GFP_KERNEL | GFP_DMA32);
if (page == NULL)
return NULL;
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index d1ede7db5a12..555b3a8ab49c 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -169,7 +169,7 @@ static void *i8xx_alloc_pages(void)
{
struct page * page;
- page = alloc_pages(GFP_KERNEL, 2);
+ page = alloc_pages(GFP_KERNEL | GFP_DMA32, 2);
if (page == NULL)
return NULL;
@@ -387,11 +387,7 @@ static void intel_i830_init_gtt_entries(void)
/* We obtain the size of the GTT, which is also stored (for some
* reason) at the top of stolen memory. Then we add 4KB to that
* for the video BIOS popup, which is also stored in there. */
-
- if (IS_I965)
- size = 512 + 4;
- else
- size = agp_bridge->driver->fetch_size() + 4;
+ size = agp_bridge->driver->fetch_size() + 4;
if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82830_HB ||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) {
@@ -805,6 +801,26 @@ static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge)
return 0;
}
+
+/*
+ * The i965 supports 36-bit physical addresses, but to keep
+ * the format of the GTT the same, the bits that don't fit
+ * in a 32-bit word are shifted down to bits 4..7.
+ *
+ * Gcc is smart enough to notice that "(addr >> 28) & 0xf0"
+ * is always zero on 32-bit architectures, so no need to make
+ * this conditional.
+ */
+static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge,
+ unsigned long addr, int type)
+{
+ /* Shift high bits down */
+ addr |= (addr >> 28) & 0xf0;
+
+ /* Type checking must be done elsewhere */
+ return addr | bridge->driver->masks[type].mask;
+}
+
static int intel_i965_fetch_size(void)
{
struct aper_size_info_fixed *values;
@@ -832,7 +848,8 @@ static int intel_i965_fetch_size(void)
agp_bridge->previous_size = agp_bridge->current_size = (void *)(values + offset);
- return values[offset].size;
+ /* The i965 GTT is always sized as if it had a 512kB aperture size */
+ return 512;
}
/* The intel i965 automatically initializes the agp aperture during POST.
@@ -1584,7 +1601,7 @@ static struct agp_bridge_driver intel_i965_driver = {
.fetch_size = intel_i965_fetch_size,
.cleanup = intel_i915_cleanup,
.tlb_flush = intel_i810_tlbflush,
- .mask_memory = intel_i810_mask_memory,
+ .mask_memory = intel_i965_mask_memory,
.masks = intel_i810_masks,
.agp_enable = intel_i810_agp_enable,
.cache_flush = global_cache_flush,
diff --git a/drivers/char/ftape/Kconfig b/drivers/char/ftape/Kconfig
deleted file mode 100644
index 0d65189a7ae8..000000000000
--- a/drivers/char/ftape/Kconfig
+++ /dev/null
@@ -1,330 +0,0 @@
-#
-# Ftape configuration
-#
-config ZFTAPE
- tristate "Zftape, the VFS interface"
- depends on FTAPE
- ---help---
- Normally, you want to say Y or M. DON'T say N here or you
- WON'T BE ABLE TO USE YOUR FLOPPY TAPE DRIVE.
-
- The ftape module itself no longer contains the routines necessary
- to interface with the kernel VFS layer (i.e. to actually write data
- to and read data from the tape drive). Instead the file system
- interface (i.e. the hardware independent part of the driver) has
- been moved to a separate module.
-
- To compile this driver as a module, choose M here: the
- module will be called zftape.
-
- Regardless of whether you say Y or M here, an additional runtime
- loadable module called `zft-compressor' which contains code to
- support user transparent on-the-fly compression based on Ross
- William's lzrw3 algorithm will be produced. If you have enabled the
- kernel module loader (i.e. have said Y to "Kernel module loader
- support", above) then `zft-compressor' will be loaded
- automatically by zftape when needed.
-
- Despite its name, zftape does NOT use compression by default.
-
-config ZFT_DFLT_BLK_SZ
- int "Default block size"
- depends on ZFTAPE
- default "10240"
- ---help---
- If unsure leave this at its default value, i.e. 10240. Note that
- you specify only the default block size here. The block size can be
- changed at run time using the MTSETBLK tape operation with the
- MTIOCTOP ioctl (i.e. with "mt -f /dev/qft0 setblk #BLKSZ" from the
- shell command line).
-
- The probably most striking difference between zftape and previous
- versions of ftape is the fact that all data must be written or read
- in multiples of a fixed block size. The block size defaults to
- 10240 which is what GNU tar uses. The values for the block size
- should be either 1 or multiples of 1024 up to a maximum value of
- 63488 (i.e. 62 K). If you specify `1' then zftape's builtin
- compression will be disabled.
-
- Reasonable values are `10240' (GNU tar's default block size),
- `5120' (afio's default block size), `32768' (default block size some
- backup programs assume for SCSI tape drives) or `1' (no restriction
- on block size, but disables builtin compression).
-
-comment "The compressor will be built as a module only!"
- depends on FTAPE && ZFTAPE
-
-config ZFT_COMPRESSOR
- tristate
- depends on FTAPE!=n && ZFTAPE!=n
- default m
-
-config FT_NR_BUFFERS
- int "Number of ftape buffers (EXPERIMENTAL)"
- depends on FTAPE && EXPERIMENTAL
- default "3"
- help
- Please leave this at `3' unless you REALLY know what you are doing.
- It is not necessary to change this value. Values below 3 make the
- proper use of ftape impossible, values greater than 3 are a waste of
- memory. You can change the amount of DMA memory used by ftape at
- runtime with "mt -f /dev/qft0 setdrvbuffer #NUMBUFFERS". Each buffer
- wastes 32 KB of memory. Please note that this memory cannot be
- swapped out.
-
-config FT_PROC_FS
- bool "Enable procfs status report (+2kb)"
- depends on FTAPE && PROC_FS
- ---help---
- Optional. Saying Y will result in creation of a directory
- `/proc/ftape' under the /proc file system. The files can be viewed
- with your favorite pager (i.e. use "more /proc/ftape/history" or
- "less /proc/ftape/history" or simply "cat /proc/ftape/history"). The
- file will contain some status information about the inserted
- cartridge, the kernel driver, your tape drive, the floppy disk
- controller and the error history for the most recent use of the
- kernel driver. Saying Y will enlarge the size of the ftape driver
- by approximately 2 KB.
-
- WARNING: When compiling ftape as a module (i.e. saying M to "Floppy
- tape drive") it is dangerous to use ftape's /proc file system
- interface. Accessing `/proc/ftape' while the module is unloaded will
- result in a kernel Oops. This cannot be fixed from inside ftape.
-
-choice
- prompt "Debugging output"
- depends on FTAPE
- default FT_NORMAL_DEBUG
-
-config FT_NORMAL_DEBUG
- bool "Normal"
- ---help---
- This option controls the amount of debugging output the ftape driver
- is ABLE to produce; it does not increase or diminish the debugging
- level itself. If unsure, leave this at its default setting,
- i.e. choose "Normal".
-
- Ftape can print lots of debugging messages to the system console
- resp. kernel log files. Reducing the amount of possible debugging
- output reduces the size of the kernel module by some KB, so it might
- be a good idea to use "None" for emergency boot floppies.
-
- If you want to save memory then the following strategy is
- recommended: leave this option at its default setting "Normal" until
- you know that the driver works as expected, afterwards reconfigure
- the kernel, this time specifying "Reduced" or "None" and recompile
- and install the kernel as usual. Note that choosing "Excessive"
- debugging output does not increase the amount of debugging output
- printed to the console but only makes it possible to produce
- "Excessive" debugging output.
-
- Please read <file:Documentation/ftape.txt> for a short description
- how to control the amount of debugging output.
-
-config FT_FULL_DEBUG
- bool "Excessive"
- help
- Extremely verbose output for driver debugging purposes.
-
-config FT_NO_TRACE
- bool "Reduced"
- help
- Reduced tape driver debugging output.
-
-config FT_NO_TRACE_AT_ALL
- bool "None"
- help
- Suppress all debugging output from the tape drive.
-
-endchoice
-
-comment "Hardware configuration"
- depends on FTAPE
-
-choice
- prompt "Floppy tape controllers"
- depends on FTAPE
- default FT_STD_FDC
-
-config FT_STD_FDC
- bool "Standard"
- ---help---
- Only change this setting if you have a special controller. If you
- didn't plug any add-on card into your computer system but just
- plugged the floppy tape cable into the already existing floppy drive
- controller then you don't want to change the default setting,
- i.e. choose "Standard".
-
- Choose "MACH-2" if you have a Mountain Mach-2 controller.
- Choose "FC-10/FC-20" if you have a Colorado FC-10 or FC-20
- controller.
- Choose "Alt/82078" if you have another controller that is located at
- an IO base address different from the standard floppy drive
- controller's base address of `0x3f0', or uses an IRQ (interrupt)
- channel different from `6', or a DMA channel different from
- `2'. This is necessary for any controller card that is based on
- Intel's 82078 FDC such as Seagate's, Exabyte's and Iomega's "high
- speed" controllers.
-
- If you choose something other than "Standard" then please make
- sure that the settings for the IO base address and the IRQ and DMA
- channel in the configuration menus below are correct. Use the manual
- of your tape drive to determine the correct settings!
-
- If you are already successfully using your tape drive with another
- operating system then you definitely should use the same settings
- for the IO base, the IRQ and DMA channel that have proven to work
- with that other OS.
-
- Note that this menu lets you specify only the default setting for
- the hardware setup. The hardware configuration can be changed at
- boot time (when ftape is compiled into the kernel, i.e. if you
- have said Y to "Floppy tape drive") or module load time (i.e. if you
- have said M to "Floppy tape drive").
-
- Please read also the file <file:Documentation/ftape.txt> which
- contains a short description of the parameters that can be set at
- boot or load time. If you want to use your floppy tape drive on a
- PCI-bus based system, please read the file
- <file:drivers/char/ftape/README.PCI>.
-
-config FT_MACH2
- bool "MACH-2"
-
-config FT_PROBE_FC10
- bool "FC-10/FC-20"
-
-config FT_ALT_FDC
- bool "Alt/82078"
-
-endchoice
-
-comment "Consult the manuals of your tape drive for the correct settings!"
- depends on FTAPE && !FT_STD_FDC
-
-config FT_FDC_BASE
- hex "IO base of the floppy disk controller"
- depends on FTAPE && !FT_STD_FDC
- default "0"
- ---help---
- You don't need to specify a value if the following default
- settings for the base IO address are correct:
- <<< MACH-2 : 0x1E0 >>>
- <<< FC-10/FC-20: 0x180 >>>
- <<< Secondary : 0x370 >>>
- Secondary refers to a secondary FDC controller like the "high speed"
- controllers delivered by Seagate or Exabyte or Iomega's Ditto Dash.
- Please make sure that the setting for the IO base address
- specified here is correct. USE THE MANUAL OF YOUR TAPE DRIVE OR
- CONTROLLER CARD TO DETERMINE THE CORRECT SETTING. If you are already
- successfully using the tape drive with another operating system then
- you definitely should use the same settings for the IO base that has
- proven to work with that other OS.
-
- Note that this menu lets you specify only the default setting for
- the IO base. The hardware configuration can be changed at boot time
- (when ftape is compiled into the kernel, i.e. if you specified Y to
- "Floppy tape drive") or module load time (i.e. if you have said M to
- "Floppy tape drive").
-
- Please read also the file <file:Documentation/ftape.txt> which
- contains a short description of the parameters that can be set at
- boot or load time.
-
-config FT_FDC_IRQ
- int "IRQ channel of the floppy disk controller"
- depends on FTAPE && !FT_STD_FDC
- default "0"
- ---help---
- You don't need to specify a value if the following default
- settings for the interrupt channel are correct:
- <<< MACH-2 : 6 >>>
- <<< FC-10/FC-20: 9 >>>
- <<< Secondary : 6 >>>
- Secondary refers to secondary a FDC controller like the "high speed"
- controllers delivered by Seagate or Exabyte or Iomega's Ditto Dash.
- Please make sure that the setting for the IO base address
- specified here is correct. USE THE MANUAL OF YOUR TAPE DRIVE OR
- CONTROLLER CARD TO DETERMINE THE CORRECT SETTING. If you are already
- successfully using the tape drive with another operating system then
- you definitely should use the same settings for the IO base that has
- proven to work with that other OS.
-
- Note that this menu lets you specify only the default setting for
- the IRQ channel. The hardware configuration can be changed at boot
- time (when ftape is compiled into the kernel, i.e. if you said Y to
- "Floppy tape drive") or module load time (i.e. if you said M to
- "Floppy tape drive").
-
- Please read also the file <file:Documentation/ftape.txt> which
- contains a short description of the parameters that can be set at
- boot or load time.
-
-config FT_FDC_DMA
- int "DMA channel of the floppy disk controller"
- depends on FTAPE && !FT_STD_FDC
- default "0"
- ---help---
- You don't need to specify a value if the following default
- settings for the DMA channel are correct:
- <<< MACH-2 : 2 >>>
- <<< FC-10/FC-20: 3 >>>
- <<< Secondary : 2 >>>
- Secondary refers to a secondary FDC controller like the "high speed"
- controllers delivered by Seagate or Exabyte or Iomega's Ditto Dash.
- Please make sure that the setting for the IO base address
- specified here is correct. USE THE MANUAL OF YOUR TAPE DRIVE OR
- CONTROLLER CARD TO DETERMINE THE CORRECT SETTING. If you are already
- successfully using the tape drive with another operating system then
- you definitely should use the same settings for the IO base that has
- proven to work with that other OS.
-
- Note that this menu lets you specify only the default setting for
- the DMA channel. The hardware configuration can be changed at boot
- time (when ftape is compiled into the kernel, i.e. if you said Y to
- "Floppy tape drive") or module load time (i.e. if you said M to
- "Floppy tape drive").
-
- Please read also the file <file:Documentation/ftape.txt> which
- contains a short description of the parameters that can be set at
- boot or load time.
-
-config FT_FDC_THR
- int "Default FIFO threshold (EXPERIMENTAL)"
- depends on FTAPE && EXPERIMENTAL
- default "8"
- help
- Set the FIFO threshold of the FDC. If this is higher the DMA
- controller may serve the FDC after a higher latency time. If this is
- lower, fewer DMA transfers occur leading to less bus contention.
- You may try to tune this if ftape annoys you with "reduced data
- rate because of excessive overrun errors" messages. However, this
- doesn't seem to have too much effect.
-
- If unsure, don't touch the initial value, i.e. leave it at "8".
-
-config FT_FDC_MAX_RATE
- int "Maximal data rate to use (EXPERIMENTAL)"
- depends on FTAPE && EXPERIMENTAL
- default "2000"
- ---help---
- With some motherboard/FDC combinations ftape will not be able to
- run your FDC/tape drive combination at the highest available
- speed. If this is the case you'll encounter "reduced data rate
- because of excessive overrun errors" messages and lots of retries
- before ftape finally decides to reduce the data rate.
-
- In this case it might be desirable to tell ftape beforehand that
- it need not try to run the tape drive at the highest available
- speed. If unsure, leave this disabled, i.e. leave it at 2000
- bits/sec.
-
-config FT_ALPHA_CLOCK
- int "CPU clock frequency of your DEC Alpha" if ALPHA
- depends on FTAPE
- default "0"
- help
- On some DEC Alpha machines the CPU clock frequency cannot be
- determined automatically, so you need to specify it here ONLY if
- running a DEC Alpha, otherwise this setting has no effect.
-
diff --git a/drivers/char/ftape/Makefile b/drivers/char/ftape/Makefile
deleted file mode 100644
index 0e67d2f8b7ec..000000000000
--- a/drivers/char/ftape/Makefile
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# Copyright (C) 1997 Claus Heine.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; see the file COPYING. If not, write to
-# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-# $Source: /homes/cvs/ftape-stacked/ftape/Makefile,v $
-# $Revision: 1.4 $
-# $Date: 1997/10/05 19:17:56 $
-#
-# Makefile for the QIC-40/80/3010/3020 floppy-tape driver for
-# Linux.
-#
-
-obj-$(CONFIG_FTAPE) += lowlevel/
-obj-$(CONFIG_ZFTAPE) += zftape/
-obj-$(CONFIG_ZFT_COMPRESSOR) += compressor/
diff --git a/drivers/char/ftape/README.PCI b/drivers/char/ftape/README.PCI
deleted file mode 100644
index 18de159d36e0..000000000000
--- a/drivers/char/ftape/README.PCI
+++ /dev/null
@@ -1,81 +0,0 @@
-Some notes for ftape users with PCI motherboards:
-=================================================
-
-The problem:
-------------
-
-There have been some problem reports from people using PCI-bus based
-systems getting overrun errors.
-I wasn't able to reproduce these until I ran ftape on a Intel Plato
-(Premiere PCI II) motherboard with bios version 1.00.08AX1.
-It turned out that if GAT (Guaranteed Access Timing) is enabled (?)
-ftape gets a lot of overrun errors.
-The problem disappears when disabling GAT in the bios.
-Note that Intel removed this setting (permanently disabled) from the
-1.00.10AX1 bios !
-
-It looks like that if GAT is enabled there are often large periods
-(greater than 120 us !??) on the ISA bus that the DMA controller cannot
-service the floppy disk controller.
-I cannot imagine this being acceptable in a decent PCI implementation.
-Maybe this is a `feature' of the chipset. I can only speculate why
-Intel choose to remove the option from the latest Bios...
-
-The lesson of this all is that there may be other motherboard
-implementations having the same of similar problems.
-If you experience a lot of overrun errors during a backup to tape,
-see if there is some setting in the Bios that may influence the
-bus timing.
-
-I judge this a hardware problem and not a limitation of ftape ;-)
-My DOS backup software seems to be suffering from the same problems
-and even refuses to run at 1 Mbps !
-Ftape will reduce the data-rate from 1 Mbps to 500 Kbps if the number
-of overrun errors on a track exceeds a threshold.
-
-
-Possible solutions:
--------------------
-
-Some of the problems were solved by upgrading the (flash) bios.
-Other suggest that it has to do with the FDC being on the PCI
-bus, but that is not the case with the Intel Premiere II boards.
-[If upgrading the bios doesn't solve the problem you could try
-a floppy disk controller on the isa-bus].
-
-Here is a list of systems and recommended BIOS settings:
-
-
- Intel Premiere PCI (Revenge):
-
-Bios version 1.00.09.AF2 is reported to work.
-
-
-
- Intel Premiere PCI II (Plato):
-
-Bios version 1.00.10.AX1 and version 11 beta are ok.
-If using version 1.00.08.AX1, GAT must be disabled !
-
-
-
- ASUS PCI/I-SP3G:
-
-Preferred settings: ISA-GAT-mode : disabled
- DMA-linebuffer-mode : standard
- ISA-masterbuffer-mode : standard
-
-
- DELL Dimension XPS P90
-
-Bios version A2 is reported to be broken, while bios version A5 works.
-You can get a flash bios upgrade from http://www.dell.com
-
-
-To see if you're having the GAT problem, try making a backup
-under DOS. If it's very slow and often repositions you're
-probably having this problem.
-
- --//--
- LocalWords: ftape PCI bios GAT ISA DMA chipset Mbps Kbps FDC isa AF ok ASUS
- LocalWords: SP linebuffer masterbuffer XPS http www com
diff --git a/drivers/char/ftape/RELEASE-NOTES b/drivers/char/ftape/RELEASE-NOTES
deleted file mode 100644
index 03799dbc05a4..000000000000
--- a/drivers/char/ftape/RELEASE-NOTES
+++ /dev/null
@@ -1,966 +0,0 @@
-Hey, Emacs, we're -*-Text-*- mode!
-
-===== Release notes for ftape-3.04d 25/11/97 =====
-- The correct pre-processor statement for "else if" is "#elif" not
- "elsif".
-- Need to call zft_reset_position() when overwriting cartridges
- previously written with ftape-2.x, sftape, or ancient
- (pre-ftape-3.x) versions of zftape.
-
-===== Release notes for ftape-3.04c 16/11/97 =====
-- fdc_probe() was calling DUMPREGS with a result length of "1" which
- was just fine. Undo previous change.
-
-===== Release notes for ftape-3.04b 14/11/97 =====
-
-- patches/2.x.x/floppy.c.diff was somewhat broken, releasing i/o
- regions it never had allocated.
-- fdc_probe() was calling DUMPREGS with a result length of "1" instead
- of "10"
-- Writing deleted data marks if the first segents on track zero are
- should work now.
-- ftformat should now be able to handle those cases where the tape
- drive sets the read only status bit (QIC-40/80 cartridges with
- QIC-3010/3020 tape drives) because the header segment is damaged.
-- the MTIOCFTCMD ioctl may now be issued by the superuser ONLY.
-
-===== Release notes for ftape-3.04a 12/11/97 =====
-- Fix an "infinite loop can't be killed by signal" bug in
- ftape_get_drive_status(). Only relevant when trying to access
- buggy/misconfigured hardware
-- Try to compensate a bug in the HP Colorado T3000's firmware: it
- doesn't set the write protect bit for QIC80/QIC40 cartridges.
-
-===== Release notes for ftape-3.04 06/11/97 =====
-- If positioning with fast seeking fails fall back to a slow seek
- before giving up.
-- (nearly) no retries on "no data errors" when verifying after
- formatting. Improved tuning of the bad sector map after formatting.
-- the directory layout has changed again to allow for easier kernel
- integration
-- Module parameter "ftape_tracing" now is called "ft_tracing" because
- the "ftape_tracing" variable has the version checksum attached to it.
-- `/proc/ftape' interface for 2.0.* kernels. `/proc/ftape' no longer
- is a directory but a file that contains all the information formerly
- provided in separate files under the `/proc/ftape/' directory.
-- Most of the configuration options have been prefixed by "CONFIG_FT_"
- in preparation of the kernel inclusion. The Makefiles under
- "./ftape/" should be directly usable by the kernel.
-- The MODVERSIONS stuff is now auto-detected.
-- Broke backslashed multi line options in MCONFIG into separate lines
- using GNU-make's "+=" feature.
-- The html and dvi version of the manual is now installed under
- '/usr/doc/ftape` with 'make install`
-- New SMP define in MCONFIG. ftape works with SMP if this is defined.
-- attempt to cope with "excessive overrun errors" by gradually
- increasing FDC FIFO threshold. But this doesn't seem to have too
- much an effect.
-- New load time configuration parameter "ft_fdc_rate_limit". If you
- encounter too many overrun errors with a 2Mb controller then you
- might want to set this to 1000.
-- overrun errors on the last sector in a segment sometimes result in
- a zero DMA residue. Dunno why, but compensate for it.
-- there were still fdc_read() timeout errors. I think I have fixed it
- now, please FIXME.
-- Sometimes ftape_write() failed to re-start the tape drive when a
- segment without a good sector was reached ("wait for empty segment
- failed"). This is fixed. Especially important for > QIC-3010.
-- sftape (aka ftape-2.x) has vanished. I didn't work on it for
- ages. It is probably still possible to use the old code with
- ftape-3.04, if one really needs it (BUT RECOMPILE IT)
-- zftape no longer alters the contents of already existing volume
- table entries, which makes it possible to fill in missing fields,
- like time stamps using some user space program.
-- ./contrib/vtblc/ contains such a program.
-- new perl script ./contrib/scripts/listtape that list the contents of a
- floppy tape cartridge parsing the output of "mt volinfo" + "mt fsf"
-- the MTWEOF implementation has changed a little bit (after I had a
- look at amanda). Calling MTWEOF while the tape is still held open
- after writing something to the tape now will terminate the current
- volume, and start a new one at the current position.
-- the volume table maintained by zftape now is a doubly linked list
- that grows dynamically as needed.
-
- formatting floppy tape cartridges
- ---------------------------------
- * there is a new user space formatting program that does most of the
- dirty work in user space (auto-detect, computing the sector
- coordinates, adjusting time stamps and statistics). It has a
- simple command line interface.
- * ftape-format.o has vanished, it has been folded into the low level
- ftape.o module, and the ioctl interface into zftape.o. Most of the
- complicated stuff has been moved to user space, so there was no
- need for a separate module anymore.
- * there is a new ioctl MTIOCFTCMD that sends a bare QIC-117 command
- to the tape drive.
- * there is a new mmap() feature to map the dma buffers into user
- space to be used by the user level formatting program.
- * Formatting of yet unformatted or totally degaussed cartridges
- should be possible now. FIXME.
-
-===== Release notes for ftape-3.03b, <forgot the exact date> ====
-
-ftape-3.03b was released as a beta release only. Its main new feature
-was support of the DITTO-2GB drive. This was made possible by reverse
-engineering done by <fill in his name> after Iomega failed to support
-ftape. Although they had promised to do so (this makes me feel a bit
-sad and uncomfortable about Iomega).
-
-===== Release notes for ftape-3.03a, 22/05/97 ====
-
-- Finally fixed auto-un-loading of modules for kernels > 2.1.18
-- Add an "uninstall" target to the Makefile
-- removed the kdtime hack
-- texi2www didn't properly set the back-reference from a footnote back
- to the regular text.
-
- zftape specific
- ---------------
- * hide the old compression map volume. Taper doesn't accept the
- presence of non-Taper volumes and Taper-written volume on the same
- tape.
- * EOD (End Of Data) handling was still broken: the expected behavior
- is to return a zero byte count at the first attempt to read past
- EOD, return a zero byte count at the second attempt to read past
- EOD and THEN return -EIO.
-
- ftape-format specific
- ---------------------
- * Detection of QIC-40 cartridges in select_tape_format() was broken
- and made it impossible to format QIC-3010/3020 cartridges.
- * There are strange "TR-1 Extra" cartridges out there which weren't
- detected properly because the don't strictly conform to the
- QIC-80, Rev. N, spec.
-
-===== Release notes for ftape-3.03, 30/04/97 =====
-
-- Removed kernel integration code from the package. I plan to provide
- a package that can be integrated into the stock kernel separately
- (hopefully soon).
- As a result, a simple `make' command now will build everything.
-- ALL compile time configuration options have been moved to the file
- `MCONFIG'.
-- Quite a few `low level' changes to allow formatting of cartridges.
-- formatting is implemented as a separate module `ftape-format.o'. The
- modified `mt' program contains sample code that shows how to use it.
-- The VFS interface has been moved from the `ftape.o' module to the
- high level modules `zftape.o' resp. `sftape.o'. `ftape.o' contains
- the hardware support only.
-- A bit of /proc support for kernels > 2.1.28
-- Moved documentation to Doc subdir. INSTALL now contains some real
- installation notes.
-- `install' target in Makefile.
-
-zftape specific:
-----------------
-
-- zftape works for large cartridges now ( > 2^31 bytes)
-- MTIOCVOLINFO and MTIOCGETSIZE now return the size in KILOBYTES,
- NO LONGER in bytes.
-
-- permissions for write access to a cartridge have changed:
- * zftape now also takes the file access mode into account
- * zftape no longer allows writing in the middle of the recorded
- media. The tape has to be positioned at BOT or EOD for write
- access.
-
-- MTBSF has changed. It used to position at the beginning of the
- previous file when called with count 1. This was different from the
- expected behavior for other Un*x tape drivers (i.e. SCSI). MTBSF
- with count 1 should merely position at the beginning of the current
- volume. Fixed. As a result, `tar --verify' now produces the desired
- result: it verifies the last written volume, not the pre-last
- written volume.
-
-- The compression map has vanished --> no need for `mt erase' any
- more. Fast seeking in a compressed volume is still be possible, but
- takes slightly longer. As a side effect, you may experience an
- additional volume showing up in front of all others for old
- cartridges. This is the tape volume that holds the compression map.
-
-- The compression support for zftape has been moved to a separate
- module `zft-compressor'. DON'T forget to load it before trying to
- read back compressed volumes. The stock `zftape.o' module probes for
- the module `zft-compressor' using the kerneld message channel; you
- have to install `zft-compressor.o' in a place where modprobe can
- find it if you want to use this.
-
-- New experimental feature that tries to get the broken down GMT time
- from user space via a kernel daemon message channel. You need to
- compile and start the `kdtime' daemon contained in the contrib
- directory to use it. Needed (?) for time stamps in the header
- segments and the volume table.
-
-- variable block size mode via MTSETBLK 0
-
-- keep modules locked in memory after the block size has been changed
-
-sftape specific:
-----------------
-
-- end of tape handling should be fixed, i.e. multi volume archives
- written with `afio' can be read back now.
-
-
-===== Release notes for ftape-3.02a, 09/01/97 =====
-
-No big news:
-- call zft_init() resp. sft_init() when compiling the entire stuff
- into the kernel image.
-- fix bug in ftape-setup.c when NO_TRACE_AT_ALL was defined.
-- fix bug in sftape-eof.c/zftape-eof.c for old kernels (1.2.*)
-- add support for new module interface for recent kernels
-
-===== Release notes for ftape-3.02, 16/12/96 =====
-- Fixed the `FDC unlock command failed' bug in fdc-io.c. When the FIFO
- was already locked when ftape was loaded, ftape failed to unlock it.
-- Fixed compilation of `contrib/gnumt'. It now finds `mtio.h' even if
- ftape is NOT included into the kernel source tree.
-- fc-10.c: include <asm/io.h> for inb() and outb().
-- ftape/sftape/zftape: all global variable now have either a `ftape_',
- a `ft_', `sft_', `zft_' or `qic_' prefix to prevent name clashes
- with other parts of the kernel when including ftape into the kernel
- source tree.
-- Kerneld support has changed. `ftape' now searches for a module
- `ftape-frontend' when none of the frontend (`sftape' or `zftape') is
- loaded. Please refer to the `Installation/Loading ftape' section of
- the TeXinfo manual.
-- Add load resp. boot-time configuration of ftape. There are now
- variables ft_fdc_base, ft_fdc_dma and ft_fdc_irq corresponding to
- the former FDC_BASE etc. compile time definitions. One can also use
- the kernel command line parameters to configure the driver if it is
- compiled into the kernel. Also, the FC-10/FC-20 support is load-time
- configurable now as well as the MACH-II hack (ft_probe_fc10,
- resp. ft_mach2). Please refer to the section `Installation/Configure
- ftape' of the TeXinfo manual.
-- I removed the MODVERSIONS option from `Makefile.module'. Let me alone
- with ftape and MODVERSIONS unless you include the ftape sources into
- the kernel source tree.
-- new vendors in `vendors.h':
- * HP Colorado T3000
- * ComByte DoublePlay (including a bug fix for their broken
- formatting software, thanks to whraven@njackn.com)
- * Iomega DITTO 2GIG. NOTE: this drive cannot work with ftape because
- the logical data layout of the cartridges used by this drive does
- NOT conform to the QIC standards, it is a special Iomega specific
- format. I've sent mail to Iomega but didn't receive an answer
- yet. If you want this drive to be supported by ftape, ask Iomega
- to give me information about it.
-- zftape:
- * re-introduced the MTIOC_ZFTAPE_GETBLKSZ ioctl for compatibility
- with zftape 1.06a and earlier. Please don't use it when writing
- new software, use the MTIOCVOLINFO ioctl instead.
- * Major overhaul of the code that updates the header segments. Never
- change the tape label unless erasing the tape. Thus we almost
- never need to write the header segments, unless we would modify
- the bad sector map which isn't done yet. Updating of volume table
- and compression map more secure now although it takes a bit
- longer.
- * Fixed bug when aborting a write operation with a signal: zftape
- now finishes the current volume (i.e. writes an eof marker) at the
- current position. It didn't before which led to somehow *strange*
- behavior in this cases.
- * Keep module locked in memory when using it with the non-rewinding
- devices and the tape is not logical at BOT. Needed for kerneld
- support.
-- sftape:
- * Keep module locked in memory when using it with the non-rewinding
- devices and the tape is not logical at BOT. Needed for kerneld
- support.
-
-===== Release notes for ftape-3.01, 14/11/96 =====
-
-- Fixed silly bugs in ftape-3.00:
- * MAKEDEV.ftape: major device number must be 27, not 23
- * sftape/sftape-read.c: sftape_read_header_segments() called
- itself recursively instead of calling ftape_read_header_segment()
- * zftape/qic-vtbl.h: conversion of ftape's file marks to zftape's
- internal volume table was broken.
- * patches/2.x.x/linux-2.0.21.dif: my RCS (resp. CVS) system replaced
- the `$Revison:' etc. macros in the `ftape.h' concerning part of the
- patch :-( Fixed.
- * info/ftape.info: Fixed misspellings (`cp' <-> `cp -r' etc.)
- * when ftape/sftape or ftape/zftape was compiled into the kernel the
- variable ftape_status was declared twice. Fixed.
- * removed reference to undeclared variable kernel_version when not
- compiling as module
- * fixed a bug introduced by the use of bit-fields for some flags
- (i.e. write_protected, no_cartridge, formatted)
- * flag `header_read' is now reset correctly to zero when tape is
- removed.
-- fixed a bug in sftape/sftape-eof.c that was already in the original
- ftape code. MTFSF/BSF was not handled correctly when positioned
- right before the file mark (think of tar)
-- Changed TRACE macros (following a suggestion of Marcin Dalecki) to use
- the predefined __FUNCTION__ macro of GCC. Spares about 4k of code.
-- added new vendor id for Iomega DITTO 2GIG
-- fixed a bug already present in zftape-1.06 when aborting a write
- with a signal: we now finish the current volume at that
- position. Header segments remain NOT up to date until an explicit call
- to MTREW or MTOFFL is done.
-
-===== Release notes for ftape-3.00, 14/10/96 =====
-
-- Merged ftape with zftape. There are three modules now:
- ftape for the hardware support, sftape for the implementation of the
- original ftape eof mark stuff and zftape that implements zftape's way
- of handling things (compression, volume table, tape blocks of
- constant length)
-- Documentation in TeXinfo format in the `info' subdirectory.
-- New ioctls for zftape. See zftape/zftape.h
-- Dummy formatting ioctl for ftape. See ftape.h
-- Kernel patch files for the 2.*.* series to include ftape-3.00 in the
- kernel source tree. These includes a kernel compatible Config.in
- script and fairly large online information for the kernel configure
- script.
-- Support for compiling with Linux-1.2.13.
-- Modified GNU mt from their cpio package that can handle the new
- ioctls.
-- ftape/sftape/zftape is kerneld save now!
-
-Notes on sftape:
-- sftape implements the eof handling code of the original ftape. If
- you like to stick with the original ftape stuff, you have to use
- this module, not zftape.
-- sftape is kerneld save, unlike the original ftape.
-- we keep the entire header segment now in memory, so no need to read
- it before updating the header segments. Additional memory
- consumption: 256 bytes.
-
-Notes for zftape:
-- zftape has support for tapes with format code 6 now, which use a
- slightly different volume table format compared with other floppy
- tapes.
-- new ioctls for zftape. Have a look at zftape/zftape.h
-- The internal volume table representation has changed for zftape. Old
- cartridges are converted automatically.
-- zftape no longer uses compression map segments, which have vanished
- from the QIC specs, but creates volume table entry that reserves
- enough space for the compression map.
-- zftape is kerneld save now.
-- we keep the entire header segment now in memory, so no need to read
- it before updating the header segments. Additional memory
- consumption: 256 bytes.
-
-Notes for contrib/gnumt:
-- modified mt from the GNU cpio package that supports all the new
- ioctls of zftape.
-Notes for contrib/swapout:
-- This contains the swapout.c program that was written by Kai
- Harrekilde-Pederson. I simply added a Makefile.
-
-===== Release notes for ftape-2.10, 14/10/96 =====
-
-The ftape maintainer has changed.
-Kai Harrekilde-Petersen <khp@dolphinics.no>
-has resigned from maintaining ftape, and I,
-Claus-Justus Heine <claus@momo.math.rwth-aachen.de>,
-have taken over.
-
-- Added support for tapes with `format code 6', i.e. QIC-3020 tapes
- with more than 2^16 segments.
-- merged changes made by Bas Laarhoven with ftape-2.09. Refer
- to his release notes below. I've included them into this
- file unchanged for your reference.
-- disabled call stack back trace for now. This new feature
- introduced by the interim release 2.0.x still seems to
- be buggy.
-- Tried to minimize differences between the ftape version
- to be included into the kernel source tree and the standalone
- module version.
-- Reintroduced support for Linux-1.2.13. Please refer to the
- Install-guide.
-
-===== Release notes for ftape-2.09, 16/06/96 =====
-
-There aren't any really big news in this release, mostly just that I
-(the maintainer) have changed my email address (due to a new job). My
-new address is <khp@dolphinics.no>
-
-- The CLK_48MHZ and FDC_82078SL options has gone (all 2Mbps cards seem
- to use a 48MHz oscillator anyway and I haven't heard of an 'SL
- chip out there).
-- The S82078B has been `downgraded' to i82077AA compability.
-- TESTING option revived. Right now, it'll enable the (seriously broken)
- 2Mbps code. If you enable it, you'll experience a tape drive that's
- *really* out to lunch!
-- Some (bold) changes in the init code. Please notify me if they
- break things for you.
-
-===== Release notes for ftape-2.08, 14/03/96 =====
-
-If you correct a problem with ftape, please send your patch to
-khp@dolphinics.no too.
-
-- Updated to reflect that NR_MEM_LISTS is gone in 1.3.74
-- Teac 700 added to list of known drives.
-- The registered device name is now "ft" rather than "ftape".
-
-===== Release notes for ftape-2.07a, 14/03/96 =====
-
-Bugfixes by Marcin Dalecki <dalecki@namu03.gwdg.de>:
-- In the last release it just compiled against 1.3.70;
- now the params to request_irq() and free_irq are() are fixed, so it also
- works in 1.3.73 :-)
-- Support for modules is now correct for newer kernels.
-
-===== Release notes for ftape-2.07, 04/03/96 =====
-
-
-- ftape updated to compile against 1.3.70.
-- Iomega 700 and Wangtek 3200 recognised.
-
-
-===== Release notes for ftape-2.06b, 13/02/96 =====
-
-Another simple bugfix version.
-
-- Jumbo 700 recognised.
-- Typo in vendors.h fixed.
-
-
-===== Release notes for ftape-2.06a, 10/02/96 =====
-
-This release is a simple bugfix version.
-
-- Linux/SMP: ftape *should* work.
-- FC-10/20: Only accepts IRQs 3-7, or 9. If IRQ 9, properly tell the card
- to use IRQ 2. Thanks to Greg Crider (gcrider@iclnet.org) for finding and
- locating this bug and testing the patch.
-- Insight drive recognised correctly again.
-- Motor-on wakeup version of the Iomega 250 drive added
-
-
-===== Release notes for ftape-2.06, 28/01/96 =====
-
-Special thanks go to Neal Friedman and Steven Sorbom for their
-help in producing and testing this release.
-
-I have continued to clean up the code, with an eye towards inclusion
-of ftape in Linus' official kernel (In fact, as I type this, I am
-running on a kernel with ftape support statically linked). I have
-test-compiled ftape against my 1.2.13 tree without problems.
-Hopefully, everything should be OK for the v1.2.x people.
-
-WARNING! Alan Cox has mailed me that ftape does *NOT* work with
-Linux/SMP. If you try to run ftape under Linux/SMP, it will cause a
-kernel deadlock (which is worse than a panic).
-
-- QIC-3020/TR-3: 1Mbps support works. Neal is capable of reading and
- writing data to a tape. ftape will automatically detect the type of
- tape (e.g. TR-3 vs QIC-80) and move the fdc in and out of
- "perpendicular mode" as necessary.
-- 2Mbps support is disabled by default, since it is not fully
- debugged. If you are adventurous, remove -DFDC_82078SL in the
- Makefile and see what happens :-)
-- fdc detection: silly bugs removed (Only 2Mbps fdcs were affected)
- and added detection of the National Semiconductors PC8744 fdc chip
- (used in the PC873xx "super-IO" chips).
-- Removed warning about incompatible types when compiling with Linux
- 1.2.x.
-- README.PCI updated with info about the DELL Dimension XPS P90.
-- Connor TST3200R added to detected drives.
-- `swapout' utility added to distribution. It will dirty 5Meg of
- memory, trying to swap out other programs. Just say `make swapout'
- to build it. ftape will do this automatically Real Soon Now (ie:
- when I have found out which kernel memory alloc function to call).
-
-
-===== Release notes for ftape-2.05, 08/01/96 =====
-
-- For v1.2.x Kernels, you must apply the patch linux-1.2/ksyms.patch to
- the kernel and rebuild it (it adds the __get_dma_pages symbol to
- ksyms.c).
-- Included new asm-i386/io.h file from v1.3.x kernel series, to enable
- gcc v.2.7.[12] to compile v1.2.x kernels (linux-1.2/io.h).
-- Module versions: If you wish to compile ftape as a versioned module,
- you must first compile your kernel with CONFIG_MODVERSIONS=y.
- Otherwise, you will get complaints that <linux/modversions.h> does not
- exist (if that happens, a `touch modversions.h' will help you out).
-- CLK_48MHZ: new define in the Makefile (default: non-zero). If you have
- a tape controller card that uses the i82078(-1) chip, but cannot get
- it to work with ftape, try set it to 0 (and please report this).
-- QIC-3010/3020: Complete support is still missing, but will hopefully
- come soon. Steven Sorbom has kindly provided me with hints about
- this. Writing of QIC-3020 tapes definitely does NOT work (do not try
- it! - the drive will not be in "perpendicular mode" and this will ruin
- the formatting info on the tape).
-- ftape_num_buffers is out of fashion: use NR_BUFFERS instead (and
- recompile if you want to change it :-).
-
-
-===== Release notes for ftape-2.04, 01/01/96 =====
-
-This version by Kai Harrekilde-Petersen <khp@dolphinics.no>
-
-- ALERT! Support for Kernels earlier then v1.1.85 is about to go away.
- I intend to clean up some of the code (getting rid of an annoyingly
- large numbers of #ifdef mostly), which means that support for
- pre-1.1.85 kernels must go as well.
-- NR_FTAPE_BUFFERS is gone; You can instead select the number of dma
- buffers by saying `insmod ftape.o ftape_num_buffer=<n>' instead.
-- Configure script gone. ftape will now automagically determine your
- kernel version by /usr/include/linux/version.h instead.
-- CONFIG_MODVERSIONS now work. All combinations of versioned /
- unversioned kernel and ftape module works (at least with my 1.3.52
- kernel).
-- If you have problems with inserting ftape into an old (1.2.x)
- kernel (e.g. insmod says "1.2.8 does not match 1.2.8), recompile
- your modules utilities with your new compiler.
-- Reveal TB1400 drive added to vendors.h
-- Support for the i82078-1 (2Mbps) chip is coming along. The
- biggest problem is that I don't have such a card, which makes
- testing / debugging somewhat problematic. The second biggest
- problem is that I do not have the QIC-3010/3020 standards either.
- Status right now is that the chip is detected, and it should be
- possible to put it into 2Mbps mode. However, I do not know what
- "extras" are needed to complete the support. Although putting the
- i82078 into 1Mbps mode ought to work out of the box, it doesn't
- (right now, ftape complains about id am errors).
-
-
-===== Release notes for ftape-2.04beta5, 29/12/95 =====
-
-Bas offline linux-tape
-----------------------
-For reasons only known to the majordomo mail list processor, Bas was
-kicked off the linux-tape list sometime during the summer. Being
-overworked at his for-pay job, he didn't notice it much. Instead I
-(Kai, khp@dolphinics.no) has worked on ftape to produce the 2.04(beta)
-version.
-
-zftape
-------
-Note that there exists a much improved version of ftape, written by
-Claus-Justus Heine <claus@willi.math.rwth-aachen.de> which is named
-zftape, which conforms to the QIC-80 specs on how to mark backups, and
-is capable of doing automatic compression. However, zftape makes
-substantial changes to ftape, and I (Kai) have therefore declined to
-integrate zftape into ftape. Hopefully, this will happen soon.
-
-CONFIG_QIC117 removed from the kernel
--------------------------------------
-The biggest change of all is that ftape now will allocate its dma
-buffers when it is inserted. The means that the CONFIG_QIC117 option
-has disappeared from the Linux kernel as of v1.3.34. If you have an
-earlier kernel, simply answer 'no' to the question will do the trick
-(if you get complains about __get_free_pages() missing, contact the
-linux-tape mailing list).
-
-Note that ftape-2.04beta will work equally well on kernels with and
-without `ftape support'. The only catch is, that you will waste
-around 96-128Kb of precious DMA'able memory on a box that has ftape
-support compiled in.
-
-Now for the real changes:
-
-- FC-20 can now use DMA channels 1, 2, and 3. Thanks to Daniel
- Cohen, catman@wpi.edu.
-- ftape no longer requires a (gigantic) 96Kb buffer to be statically
- allocated by the kernel.
-- Added new Iomega drive (8882) to vendors.h
-- -fno-strength-reduce added to Makefile, since GCC is broken.
-- i82078-1 (2Mbps) FDC support started.
-
-
-===== Release notes for ftape-2.03b, 27/05/95 =====
-
-- Prevented verify_area to return error if called with zero length.
-- Fixed a bug in flush_buffers that caused too much padding to be
- written when a final segment had bad sectors.
-- Increased maximum fast-seek overshoot value from 5 to 10 segments.
-- Breaking loop after 5 retries when positioning fails.
-- Fixed wrong calculation of tape length for QIC-3010 and QIC-3020
- tapes (densities were swapped).
-- Fixed wrong calculation of overshoot on seek_forward: Wrong sign
- of error.
-- Suppress (false) error message due to new tape loaded.
-- Added two new CMS drives (11c3 and 11c5) to vendors.h.
-
-
-===== Release notes for ftape-2.03a, 09/05/95 =====
-
-- Fixed display of old error (even if already cleared) in ftape_open.
-- Improved tape length detection, ioctls would fail for 425 ft tapes.
- Until the tape length is calculated with data from the header
- segment, we'll use worst-case values.
-- Clear eof_mark after rewinding ioctls.
-- Fixed wrong version message (2.03 had 2.02g id).
-- Fixed bug that caused the fdc to be reset very frequently.
- This shouldn't affect normal operation but the timing of the
- report routines has changed again and that may cause problems.
- We'll just have to find out....
-- Implemented correct write precompensation setting for QIC-3010/3020.
-- Cleaned up fdc_interrupt_wait routine. Hope it still works :-)
-- Finally removed (already disabled) special eof mark handling for
- gnu tar.
-- Changed order of get_dma_residue and disable_dma in fdc-isr.c
- because the current order would fail on at least one system.
- We're back to the original order again, hope (and expect) this
- doesn't break any other system.
-
-
-===== Release notes for ftape-2.03, 07/05/95 =====
-
-(Changes refer to the first ftape-2.02 release)
-
-Support for wide and extended length tapes
-------------------------------------------
-The Conner TSM 420 and 850 drives are reported to be working.
-I haven't received any reports about other brands; the TSM 420
-and 850 seem to be the most widely used wide drives.
-Extended length tapes (425 ft) with normal QIC-80 drives
-are operating too (At least I've had no reports stating otherwise).
-_Not_ yet completely supported (although they may work) are
-QIC-3020 drives and 2 Mbps floppy disk controllers won't work at
-the highest speed.
-If someone is kind enough to send me one of these, I'll include
-support for it too ;-)
-
-Easier configuration
---------------------
-Problems due to wrong settings in the Makefile are prevented
-by using a configuration script that sets the necessary (kernel
-version dependent) compile time options.
-This kernel version is now determined from the sources found
-at /usr/src/linux, or if not found, the old way using
-/proc/version.
-Versioned modules will be used automatically when supported
-by- and configured in- the kernel.
-Note that the current modules code (1.1.87) is still broken
-and _needs_ the fix included in the insmod directory.
-Please don't send me any more Oops reports caused by insmod :-(
-
-Reduced module size
--------------------
-The standard module size is much reduced and some compile time
-options can even reduce it further. (I don't recommend this
-for normal use but it can be handy for rescue diskettes)
-
-Option: Approx. module size:
-
-<standard> 150 Kb
-NO_TRACE 125 Kb
-NO_TRACE_AT_ALL 67 Kb
-
-
-Much improved driver interruption
----------------------------------
-Most possible loops have been broken and signal detection
-has been improved.
-In most cases the driver can be aborted by ^C (SIGINT) and
-SIGKILL (kill -9) will generate be a sure kill.
-(Note that aborting a tape operation may damage the last
-data written to tape)
-
-Improved error recovery
------------------------
-Ftape now returns an error (ENODATA) to the application if
-a segment proves to be unrecoverable and then skips the
-bad segment.
-This causes most applications to continue to work (tar
-and afio) loosing only a small amount (up to 29 Kb) of data.
-Retried read operations will now be done slightly off-track
-to improve the chance of success. Serious head off-track
-errors will be detected.
-
-FC-10 and FC-20 controllers
----------------------------
-Ftape now supports both the old CMS FC-10 and the newer FC-20
-controllers.
-Because the operation of these cards is still undocumented,
-thus far they will only work with the default settings (See
-Makefile). Any feed-back on how to use them with other settings
-will be welcome !
-Compilation will fail if one changes the settings to illegal
-values.
-
-Kernels and compilers
----------------------
-Ftape is currently being developed using the 2.5.8 compiler.
-The older 2.4.5 probably works too (Set option in Makefile!).
-I have no experience with any later compilers nor Elf support.
-Any information on this is welcome.
-The latest kernel I have tested ftape with is 1.2.6.
-
-Compression
------------
-An impressive collection of changes for ftape including
-on-the-fly compression is still lying on my desk.
-If 2.03 proves to be reliable I might start integrating these
-but as usual, I'm short in time :-(
-
-Formatting
-----------
-There is still no way to format tapes under Linux. As far as
-I know all attempts to write such a program have died now.
-Since formatted tapes are rather common now, I think all we
-need is a utility that writes a worst case pattern and verifies
-that with the drive put in verify mode, reducing margins.
-Any takers ?
-
-Furthermore
------------
-Cleaned up messages.
-Prepared to support multiple tape drives on one fdc.
-Thanks to all the people who sent bug reports and helped me
-improve the driver. Without trying to be complete I'll mention
-Gary Anderson (without his accurate reports and unreliable
-hardware there wouldn't be a 2.03), Stefan Kneifel (FC-20),
-Robert Broughton (FC-20, you were almost there ;-), Bjorn
-Ekwall (for the versioned modules and buggy insmod ;-), Peter
-Fox, Christopher Oliver, Ralph Whittaker and not the least
-Linus Torvalds (for Linux and keeping me busy because of
-changes to the kernel ;-)
-Thanks to anyone I forgot, for the bug reports, the ftape
-bashing and the mental support...
-
-
-That's it for now. Have Fun,
-
-Bas.
-
-
-===== Release notes for ftape-2.02g, 06/05/95 =====
-
-- Added extra test to break read-id loop with signal.
-- Changed rewind code to handle negative overshoot for drives
- that take very long to start or stop.
-- Let use of get/set i/o-regions depend on kernel version.
-- Changed code to use a more general test for conditional
- compilations depending on kernel version.
-- Improved micro-step functionality to go off-track only
- while reading (id & data).
-- Added failure on tape-not-referenced bit in ftape_command.
-- Added FOREVER option to read-wait routine.
-- Changed read-id to use shorter timeout causing smaller
- rewinds on timeout.
-- Made kernel-interface functions static.
-
-
-===== Release notes for ftape-2.02f, 03/05/95 =====
-
-- Added support for dual tape drives on my system, extended Configure
- script to detect host 'dodo'.
-- Log media defect in history if ecc failed and no data was returned.
-- Fixed Configure script that was failing for kernel versions with
- double digit version or revision numbers.
-
-
-===== Release notes for ftape-2.02e, 01/05/95 =====
-
-- Fixed reposition loop at logical eot (failing read_id).
-- Fixed 34 segment offset when rewinding.
-- Added fast seek capability for more than 255 segments.
-- Fixed wrong busy result from ftape_command causing reverse
- seek to fail.
-- Added breakout from infinite rewind loop (if something fails).
-
-
-===== Release notes for ftape-2.02d, 30/04/95 =====
-
-- Improved abortion on signals: Interrupt will make a graceful
- exit, Kill will be less nice and should be used if everything
- else fails.
-- Included check for tape-head off track.
-- Implemented exit from tape-start loop.
-- Added kernel io-port registration.
-- Implemented skip of failing segment (ENODATA) on ecc failure.
- This allows afio and tar to continue when the tape is damaged.
-- Made distinction between drive names with different codes.
-
-
-===== Release notes for ftape-2.02c, 22/04/95 =====
-
-- Fixed too tight command queueing after tape stop/pause command
- issued from within interrupt service routine (Showed as timeout
- on Acknowledge errors during retries on some systems)
-- Tried to fix timeouts when using 425 ft tape because the extended
- length doesn't seem to be detected by the hardware.
- We now use the format code from the header segment so adjust the
- timing after reading the header segment.
-- Fixed some messages stating 'unexpected something...' being not
- unexpected anymore.
-- Started preparations for merge of dynamic buffer allocation and
- compression code.
-- Changed some debug messages to include relevant segment information
- at level 4.
-- Included early bail-out when drive offline, preventing a lot of
- false messages.
-- Moved ftape_parameter_xxx() offsets into function instead of in calls.
-- Removed 'weird, drive busy but no data' error when caused by
- an error during a read-id.
-- Improved 'timeout on acknowledge' diagnostics.
-- Moved MODULE option into Configure.
-- Reduced code size when no tracing at all was set (Claus Heine).
-- No longer log error code 0 (no error) as an error.
-
-
-===== Release notes for ftape-2.02b, 09/04/95 =====
-
-- Relaxed timing for status operation and displaying
- abnormal results. Hopefully this shows what's going
- wrong with the Conner TSM850R drives.
-- Created script for configuration, using version number
- of kernel source if available, otherwise /proc/version.
-- Fixed conditionals in kernel-interface.c.
-- Removed unavoidable TRACE output.
-
-
-===== Release notes for ftape-2.02a, 01/04/95 =====
-
-- Implemented `new-style' (versioned) modules support for new
- kernels.
-- Reduced size of module by moving static data to bss.
-- Now using version number of kernel source instead of running
- kernel for kernel versions >= 1.1.82
-- Added feedback on drive speeds to vendor information.
-- Included fixed insmod sources to distribution (Let's hope
- the modules distribution get fixed soon :-/).
-
-Note that I haven't yet implemented any of the code extension I
-received. I hope to find some time to do this soon.
-
-
-===== Release notes for ftape-2.02, 15/01/95 =====
-
-
-- Fixed failing repositioning when overshoot was incremented.
-- Fixed rate selection: Because of a deficiency in the QIC-117
- specification one cannot distinguish between a not implemented
- and a failing command. Therefor we now try to find out if the
- drive does support this command before usage.
-- Fixed error retry using wrong offset in fdc-isr.
-- Improved retry code to retry only once on a single no-data
- error in a segment.
-- Validate sector number extracted from eof mark because an
- invalid file mark (due to ???) could cause kernel panic.
-- Split ftape-io.c into ftape-io.c and ftape-ctl.c files.
-- Corrected too high media error count after writing to
- a bad tape.
-- Added #include <asm/segment.h> again because old kernel versions
- need it.
-- Fixed fdc not being disabled when open failed because no tape
- drive was found.
-- Fixed problem with soft error in sector 32 (shift operator with
- shiftcount 32 is not defined).
-
-
-===== Release notes for ftape-2.01, 08/01/95 =====
-
-
-- Removed TESTING setting from distributed Makefile.
-- Fixed `mt asf' failure: Rewind was deferred to close which
- overruled the fsf ioctl.
-- Prevented non-interruptible commands being interrupted.
-- Added missing timeout.pause setting.
-- Maximum tape speed read from drive type information table.
- If the information is not in the table (0) the drive will
- determine the speed itself and put a message in the logfile.
- This information should then be added to the table in the
- vendors.h file (and reported to me).
-- Added call to ftape_init_drive after soft reset for those
- (antique) drives that don't do an implicit seek_load_point
- after a reset or power up.
-- Don't try to set data rate if reset failed.
-- Prevent update of seek variables when starting from the
- beginning or the end of the tape.
-- Fixed wrong adjustment of overshoot in seek_forward().
-- Added sync to Makefile (again).
-- Added code to diagnose timer problems (calibr.c).
-- Replaced time differences by timediff calls.
-- Removed reference to do_floppy from object for recent kernels.
-- Fixed wrong display of 'failing dma controller' message.
-- Removed various no longer used #include statements.
-- Added max. tape speed value to vendor-struct.
-- Changed ftape-command to check pre-conditions and wait
- if needed.
-- Further updated qic117.h to rev G.
-- Combined command name table and restrictions table to one.
- Extended this table with some new fields.
-- Increased timeout on Ack timer value and included code to
- report out of spec behaviour.
-- Increased rewind timeout margin to calculated + 20%.
-- Improved data rate selection so it won't fail on some
- older (pre standard) drives.
-- Changed initialisation code so drive will be rewound if the
- driver is reloaded and the tape is not at bot.
-- Moved some of the flush operations from close to the ioctls.
-- Added exit code value to failing verify area message.
-- Loop until tape halted in smart-stop.
-- Fast seek handled specially if located at bot or eot.
-- Being more conservative on overshoot value.
-
-
-===== Release notes for ftape-2.00, 31/12/94 =====
-
- The Install-guide is completely rewritten and now also includes
-some information on how to use the driver. If you're either new
-to ftape or new to Unix tape devices make sure to read it !
-
- If you own a pci system and experience problems with the
-ftape driver make sure to read the README.PCI file. It contains
-some hints on how to fix your hardware.
-
- For anybody who hasn't noticed: The version number of the
-driver has been incremented (The latest released version has
-been version 1.14d).
- This has been done for two major reasons:
-
- o A new (better) error recovery scheme is implemented.
- o Support for new drive types has been added.
-
- All these improvements/changes will probably include a couple
-of new (and old?) bugs. If you encounter any problems that you think
-I'm not yet aware of, feel free to send a report to <bas@vimec.nl>.
- I recommend keeping a version of ftape-1.14d available, just
-in case ;-)
-
- This version should work with all kernel versions from 1.0.9 up
-to 1.1.72 (and probably earlier and later versions too).
-
-
-Major new features:
-
-- Better handling of tapes with defects: When a sector repeatedly
- (SOFT_RETRIES in ftape.h) cannot be written to or read from it is
- marked as an hard error and gets skipped.
- The error correction code can handle up to three of these hard
- errors provided there are no other errors in that segment (32 Kb).
-
-- Allows writing to tapes with defects (although the risk of loosing
- data increases !)
- Look for the media-defects entry printed with the statistics when
- the tape is closed. A non-zero value here shows a bad tape.
- [the actual count is wrong (too high), this is a known bug].
-
-- Use of backup header segment if first one is failing.
-
-- Support for extended length tapes with QIC-80: both 425 and 1100 ft.
- 0.25 inch tapes are now recognized and handled.
-
-- Support for new QIC-80 drives with 8 mm `wide' tapes (e.g. Conner
- TSM 420).
-
-- Support for new QIC-3010 and QIC-3020 drives (experimental) with
- both 0.25 inch and 8 mm tapes.
-
-Some minor features were added, a couple of small bugs were fixed and
-probably some new ones introduced ;-).
-
-[lseek() didn't make it into this version]
-
-Have fun,
-
-Bas.
-----
- LocalWords: ftape MCONFIG mt VFS zftape resp sftape proc subdir MTIOCVOLINFO
- LocalWords: MTIOCGETSIZE BOT EOD MTBSF zft kerneld modprobe kdtime contrib TR
- LocalWords: MTSETBLK afio uninstall texi www EIO QIC init sft eof aka dma GB
- LocalWords: SIGKILL MTIOCFTCMD mmap Iomega FDC fdc io gnumt mtio fc asm inb
- LocalWords: outb ft qic frontend TeXinfo irq mach MODVERSIONS CONFIG html dvi
- LocalWords: usr doc SMP Mb Dunno FIXME vtblc perl listtape volinfo fsf MTWEOF
- LocalWords: amanda degaussed ComByte DoublePlay whraven njackn com MTIOC vtbl
- LocalWords: GETBLKSZ MAKEDEV zftape's linux dif CVS Revison cp MTREW MTOFFL
- LocalWords: MTFSF BSF Marcin Dalecki GCC Config cpio swapout Kai Harrekilde
- LocalWords: Pederson khp dolphinics Justus claus momo rwth aachen Laarhoven
diff --git a/drivers/char/ftape/compressor/Makefile b/drivers/char/ftape/compressor/Makefile
deleted file mode 100644
index 1fbd6c4019db..000000000000
--- a/drivers/char/ftape/compressor/Makefile
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# Copyright (C) 1997 Claus-Justus Heine.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; see the file COPYING. If not, write to
-# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-# $Source: /homes/cvs/ftape-stacked/ftape/compressor/Makefile,v $
-# $Revision: 1.1 $
-# $Date: 1997/10/05 19:12:28 $
-#
-# Makefile for the optional compressor for th zftape VFS
-# interface to the QIC-40/80/3010/3020 floppy-tape driver for
-# Linux.
-#
-
-obj-$(CONFIG_ZFT_COMPRESSOR) += zft-compressor.o
-
-zft-compressor-objs := zftape-compress.o lzrw3.o
-
-CFLAGS_lzrw3.o := -O6 -funroll-all-loops
diff --git a/drivers/char/ftape/compressor/lzrw3.c b/drivers/char/ftape/compressor/lzrw3.c
deleted file mode 100644
index a032a0ee2a99..000000000000
--- a/drivers/char/ftape/compressor/lzrw3.c
+++ /dev/null
@@ -1,743 +0,0 @@
-/*
- * $Source: /homes/cvs/ftape-stacked/ftape/compressor/lzrw3.c,v $
- * $Revision: 1.1 $
- * $Date: 1997/10/05 19:12:29 $
- *
- * Implementation of Ross Williams lzrw3 algorithm. Adaption for zftape.
- *
- */
-
-#include "../compressor/lzrw3.h" /* Defines single exported function "compress". */
-
-/******************************************************************************/
-/* */
-/* LZRW3.C */
-/* */
-/******************************************************************************/
-/* */
-/* Author : Ross Williams. */
-/* Date : 30-Jun-1991. */
-/* Release : 1. */
-/* */
-/******************************************************************************/
-/* */
-/* This file contains an implementation of the LZRW3 data compression */
-/* algorithm in C. */
-/* */
-/* The algorithm is a general purpose compression algorithm that runs fast */
-/* and gives reasonable compression. The algorithm is a member of the Lempel */
-/* Ziv family of algorithms and bases its compression on the presence in the */
-/* data of repeated substrings. */
-/* */
-/* This algorithm is unpatented and the code is public domain. As the */
-/* algorithm is based on the LZ77 class of algorithms, it is unlikely to be */
-/* the subject of a patent challenge. */
-/* */
-/* Unlike the LZRW1 and LZRW1-A algorithms, the LZRW3 algorithm is */
-/* deterministic and is guaranteed to yield the same compressed */
-/* representation for a given file each time it is run. */
-/* */
-/* The LZRW3 algorithm was originally designed and implemented */
-/* by Ross Williams on 31-Dec-1990. */
-/* */
-/* Here are the results of applying this code, compiled under THINK C 4.0 */
-/* and running on a Mac-SE (8MHz 68000), to the standard calgary corpus. */
-/* */
-/* +----------------------------------------------------------------+ */
-/* | DATA COMPRESSION TEST | */
-/* | ===================== | */
-/* | Time of run : Sun 30-Jun-1991 09:31PM | */
-/* | Timing accuracy : One part in 100 | */
-/* | Context length : 262144 bytes (= 256.0000K) | */
-/* | Test suite : Calgary Corpus Suite | */
-/* | Files in suite : 14 | */
-/* | Algorithm : LZRW3 | */
-/* | Note: All averages are calculated from the un-rounded values. | */
-/* +----------------------------------------------------------------+ */
-/* | File Name Length CxB ComLen %Remn Bits Com K/s Dec K/s | */
-/* | ---------- ------ --- ------ ----- ---- ------- ------- | */
-/* | rpus:Bib.D 111261 1 55033 49.5 3.96 19.46 32.27 | */
-/* | us:Book1.D 768771 3 467962 60.9 4.87 17.03 31.07 | */
-/* | us:Book2.D 610856 3 317102 51.9 4.15 19.39 34.15 | */
-/* | rpus:Geo.D 102400 1 82424 80.5 6.44 11.65 18.18 | */
-/* | pus:News.D 377109 2 205670 54.5 4.36 17.14 27.47 | */
-/* | pus:Obj1.D 21504 1 13027 60.6 4.85 13.40 18.95 | */
-/* | pus:Obj2.D 246814 1 116286 47.1 3.77 19.31 30.10 | */
-/* | s:Paper1.D 53161 1 27522 51.8 4.14 18.60 31.15 | */
-/* | s:Paper2.D 82199 1 45160 54.9 4.40 18.45 32.84 | */
-/* | rpus:Pic.D 513216 2 122388 23.8 1.91 35.29 51.05 | */
-/* | us:Progc.D 39611 1 19669 49.7 3.97 18.87 30.64 | */
-/* | us:Progl.D 71646 1 28247 39.4 3.15 24.34 40.66 | */
-/* | us:Progp.D 49379 1 19377 39.2 3.14 23.91 39.23 | */
-/* | us:Trans.D 93695 1 33481 35.7 2.86 25.48 40.37 | */
-/* +----------------------------------------------------------------+ */
-/* | Average 224401 1 110953 50.0 4.00 20.17 32.72 | */
-/* +----------------------------------------------------------------+ */
-/* */
-/******************************************************************************/
-
-/******************************************************************************/
-
-/* The following structure is returned by the "compress" function below when */
-/* the user asks the function to return identifying information. */
-/* The most important field in the record is the working memory field which */
-/* tells the calling program how much working memory should be passed to */
-/* "compress" when it is called to perform a compression or decompression. */
-/* LZRW3 uses the same amount of memory during compression and decompression. */
-/* For more information on this structure see "compress.h". */
-
-#define U(X) ((ULONG) X)
-#define SIZE_P_BYTE (U(sizeof(UBYTE *)))
-#define SIZE_WORD (U(sizeof(UWORD )))
-#define ALIGNMENT_FUDGE (U(16))
-#define MEM_REQ ( U(4096)*(SIZE_P_BYTE) + ALIGNMENT_FUDGE )
-
-static struct compress_identity identity =
-{
- U(0x032DDEA8), /* Algorithm identification number. */
- MEM_REQ, /* Working memory (bytes) required. */
- "LZRW3", /* Name of algorithm. */
- "1.0", /* Version number of algorithm. */
- "31-Dec-1990", /* Date of algorithm. */
- "Public Domain", /* Copyright notice. */
- "Ross N. Williams", /* Author of algorithm. */
- "Renaissance Software", /* Affiliation of author. */
- "Public Domain" /* Vendor of algorithm. */
-};
-
-LOCAL void compress_compress (UBYTE *,UBYTE *,ULONG,UBYTE *, LONG *);
-LOCAL void compress_decompress(UBYTE *,UBYTE *,LONG, UBYTE *, ULONG *);
-
-/******************************************************************************/
-
-/* This function is the only function exported by this module. */
-/* Depending on its first parameter, the function can be requested to */
-/* compress a block of memory, decompress a block of memory, or to identify */
-/* itself. For more information, see the specification file "compress.h". */
-
-EXPORT void lzrw3_compress(
- UWORD action, /* Action to be performed. */
- UBYTE *wrk_mem, /* Address of working memory we can use.*/
- UBYTE *src_adr, /* Address of input data. */
- LONG src_len, /* Length of input data. */
- UBYTE *dst_adr, /* Address to put output data. */
- void *p_dst_len /* Address of longword for length of output data.*/
-)
-{
- switch (action)
- {
- case COMPRESS_ACTION_IDENTITY:
- *((struct compress_identity **)p_dst_len)= &identity;
- break;
- case COMPRESS_ACTION_COMPRESS:
- compress_compress(wrk_mem,src_adr,src_len,dst_adr,(LONG *)p_dst_len);
- break;
- case COMPRESS_ACTION_DECOMPRESS:
- compress_decompress(wrk_mem,src_adr,src_len,dst_adr,(LONG *)p_dst_len);
- break;
- }
-}
-
-/******************************************************************************/
-/* */
-/* BRIEF DESCRIPTION OF THE LZRW3 ALGORITHM */
-/* ======================================== */
-/* The LZRW3 algorithm is identical to the LZRW1-A algorithm except that */
-/* instead of transmitting history offsets, it transmits hash table indexes. */
-/* In order to decode the indexes, the decompressor must maintain an */
-/* identical hash table. Copy items are straightforward:when the decompressor */
-/* receives a copy item, it simply looks up the hash table to translate the */
-/* index into a pointer into the data already decompressed. To update the */
-/* hash table, it replaces the same table entry with a pointer to the start */
-/* of the newly decoded phrase. The tricky part is with literal items, for at */
-/* the time that the decompressor receives a literal item the decompressor */
-/* does not have the three bytes in the Ziv (that the compressor has) to */
-/* perform the three-byte hash. To solve this problem, in LZRW3, both the */
-/* compressor and decompressor are wired up so that they "buffer" these */
-/* literals and update their hash tables only when three bytes are available. */
-/* This makes the maximum buffering 2 bytes. */
-/* */
-/* Replacement of offsets by hash table indexes yields a few percent extra */
-/* compression at the cost of some speed. LZRW3 is slower than LZRW1, LZRW1-A */
-/* and LZRW2, but yields better compression. */
-/* */
-/* Extra compression could be obtained by using a hash table of depth two. */
-/* However, increasing the depth above one incurs a significant decrease in */
-/* compression speed which was not considered worthwhile. Another reason for */
-/* keeping the depth down to one was to allow easy comparison with the */
-/* LZRW1-A and LZRW2 algorithms so as to demonstrate the exact effect of the */
-/* use of direct hash indexes. */
-/* */
-/* +---+ */
-/* |___|4095 */
-/* |___| */
-/* +---------------------*_|<---+ /----+---\ */
-/* | |___| +---|Hash | */
-/* | |___| |Function| */
-/* | |___| \--------/ */
-/* | |___|0 ^ */
-/* | +---+ | */
-/* | Hash +-----+ */
-/* | Table | */
-/* | --- */
-/* v ^^^ */
-/* +-------------------------------------|----------------+ */
-/* |||||||||||||||||||||||||||||||||||||||||||||||||||||||| */
-/* +-------------------------------------|----------------+ */
-/* | |1......18| | */
-/* |<------- Lempel=History ------------>|<--Ziv-->| | */
-/* | (=bytes already processed) |<-Still to go-->| */
-/* |<-------------------- INPUT BLOCK ------------------->| */
-/* */
-/* The diagram above for LZRW3 looks almost identical to the diagram for */
-/* LZRW1. The difference is that in LZRW3, the compressor transmits hash */
-/* table indices instead of Lempel offsets. For this to work, the */
-/* decompressor must maintain a hash table as well as the compressor and both */
-/* compressor and decompressor must "buffer" literals, as the decompressor */
-/* cannot hash phrases commencing with a literal until another two bytes have */
-/* arrived. */
-/* */
-/* LZRW3 Algorithm Execution Summary */
-/* --------------------------------- */
-/* 1. Hash the first three bytes of the Ziv to yield a hash table index h. */
-/* 2. Look up the hash table yielding history pointer p. */
-/* 3. Match where p points with the Ziv. If there is a match of three or */
-/* more bytes, code those bytes (in the Ziv) as a copy item, otherwise */
-/* code the next byte in the Ziv as a literal item. */
-/* 4. Update the hash table as possible subject to the constraint that only */
-/* phrases commencing three bytes back from the Ziv can be hashed and */
-/* entered into the hash table. (This enables the decompressor to keep */
-/* pace). See the description and code for more details. */
-/* */
-/******************************************************************************/
-/* */
-/* DEFINITION OF COMPRESSED FILE FORMAT */
-/* ==================================== */
-/* * A compressed file consists of a COPY FLAG followed by a REMAINDER. */
-/* * The copy flag CF uses up four bytes with the first byte being the */
-/* least significant. */
-/* * If CF=1, then the compressed file represents the remainder of the file */
-/* exactly. Otherwise CF=0 and the remainder of the file consists of zero */
-/* or more GROUPS, each of which represents one or more bytes. */
-/* * Each group consists of two bytes of CONTROL information followed by */
-/* sixteen ITEMs except for the last group which can contain from one */
-/* to sixteen items. */
-/* * An item can be either a LITERAL item or a COPY item. */
-/* * Each item corresponds to a bit in the control bytes. */
-/* * The first control byte corresponds to the first 8 items in the group */
-/* with bit 0 corresponding to the first item in the group and bit 7 to */
-/* the eighth item in the group. */
-/* * The second control byte corresponds to the second 8 items in the group */
-/* with bit 0 corresponding to the ninth item in the group and bit 7 to */
-/* the sixteenth item in the group. */
-/* * A zero bit in a control word means that the corresponding item is a */
-/* literal item. A one bit corresponds to a copy item. */
-/* * A literal item consists of a single byte which represents itself. */
-/* * A copy item consists of two bytes that represent from 3 to 18 bytes. */
-/* * The first byte in a copy item will be denoted C1. */
-/* * The second byte in a copy item will be denoted C2. */
-/* * Bits will be selected using square brackets. */
-/* For example: C1[0..3] is the low nibble of the first control byte. */
-/* of copy item C1. */
-/* * The LENGTH of a copy item is defined to be C1[0..3]+3 which is a number */
-/* in the range [3,18]. */
-/* * The INDEX of a copy item is defined to be C1[4..7]*256+C2[0..8] which */
-/* is a number in the range [0,4095]. */
-/* * A copy item represents the sequence of bytes */
-/* text[POS-OFFSET..POS-OFFSET+LENGTH-1] where */
-/* text is the entire text of the uncompressed string. */
-/* POS is the index in the text of the character following the */
-/* string represented by all the items preceeding the item */
-/* being defined. */
-/* OFFSET is obtained from INDEX by looking up the hash table. */
-/* */
-/******************************************************************************/
-
-/* The following #define defines the length of the copy flag that appears at */
-/* the start of the compressed file. The value of four bytes was chosen */
-/* because the fast_copy routine on my Macintosh runs faster if the source */
-/* and destination blocks are relatively longword aligned. */
-/* The actual flag data appears in the first byte. The rest are zeroed so as */
-/* to normalize the compressed representation (i.e. not non-deterministic). */
-#define FLAG_BYTES 4
-
-/* The following #defines define the meaning of the values of the copy */
-/* flag at the start of the compressed file. */
-#define FLAG_COMPRESS 0 /* Signals that output was result of compression. */
-#define FLAG_COPY 1 /* Signals that output was simply copied over. */
-
-/* The 68000 microprocessor (on which this algorithm was originally developed */
-/* is fussy about non-aligned arrays of words. To avoid these problems the */
-/* following macro can be used to "waste" from 0 to 3 bytes so as to align */
-/* the argument pointer. */
-#define ULONG_ALIGN_UP(X) ((((ULONG)X)+sizeof(ULONG)-1)&~(sizeof(ULONG)-1))
-
-
-/* The following constant defines the maximum length of an uncompressed item. */
-/* This definition must not be changed; its value is hardwired into the code. */
-/* The longest number of bytes that can be spanned by a single item is 18 */
-/* for the longest copy item. */
-#define MAX_RAW_ITEM (18)
-
-/* The following constant defines the maximum length of an uncompressed group.*/
-/* This definition must not be changed; its value is hardwired into the code. */
-/* A group contains at most 16 items which explains this definition. */
-#define MAX_RAW_GROUP (16*MAX_RAW_ITEM)
-
-/* The following constant defines the maximum length of a compressed group. */
-/* This definition must not be changed; its value is hardwired into the code. */
-/* A compressed group consists of two control bytes followed by up to 16 */
-/* compressed items each of which can have a maximum length of two bytes. */
-#define MAX_CMP_GROUP (2+16*2)
-
-/* The following constant defines the number of entries in the hash table. */
-/* This definition must not be changed; its value is hardwired into the code. */
-#define HASH_TABLE_LENGTH (4096)
-
-/* LZRW3, unlike LZRW1(-A), must initialize its hash table so as to enable */
-/* the compressor and decompressor to stay in step maintaining identical hash */
-/* tables. In an early version of the algorithm, the tables were simply */
-/* initialized to zero and a check for zero was included just before the */
-/* matching code. However, this test costs time. A better solution is to */
-/* initialize all the entries in the hash table to point to a constant */
-/* string. The decompressor does the same. This solution requires no extra */
-/* test. The contents of the string do not matter so long as the string is */
-/* the same for the compressor and decompressor and contains at least */
-/* MAX_RAW_ITEM bytes. I chose consecutive decimal digits because they do not */
-/* have white space problems (e.g. there is no chance that the compiler will */
-/* replace more than one space by a TAB) and because they make the length of */
-/* the string obvious by inspection. */
-#define START_STRING_18 ((UBYTE *) "123456789012345678")
-
-/* In this algorithm, hash values have to be calculated at more than one */
-/* point. The following macro neatens the code up for this. */
-#define HASH(PTR) \
- (((40543*(((*(PTR))<<8)^((*((PTR)+1))<<4)^(*((PTR)+2))))>>4) & 0xFFF)
-
-/******************************************************************************/
-
-/* Input : Hand over the required amount of working memory in p_wrk_mem. */
-/* Input : Specify input block using p_src_first and src_len. */
-/* Input : Point p_dst_first to the start of the output zone (OZ). */
-/* Input : Point p_dst_len to a ULONG to receive the output length. */
-/* Input : Input block and output zone must not overlap. */
-/* Output : Length of output block written to *p_dst_len. */
-/* Output : Output block in Mem[p_dst_first..p_dst_first+*p_dst_len-1]. May */
-/* Output : write in OZ=Mem[p_dst_first..p_dst_first+src_len+MAX_CMP_GROUP-1].*/
-/* Output : Upon completion guaranteed *p_dst_len<=src_len+FLAG_BYTES. */
-LOCAL void compress_compress(UBYTE *p_wrk_mem,
- UBYTE *p_src_first, ULONG src_len,
- UBYTE *p_dst_first, LONG *p_dst_len)
-{
- /* p_src and p_dst step through the source and destination blocks. */
- register UBYTE *p_src = p_src_first;
- register UBYTE *p_dst = p_dst_first;
-
- /* The following variables are never modified and are used in the */
- /* calculations that determine when the main loop terminates. */
- UBYTE *p_src_post = p_src_first+src_len;
- UBYTE *p_dst_post = p_dst_first+src_len;
- UBYTE *p_src_max1 = p_src_first+src_len-MAX_RAW_ITEM;
- UBYTE *p_src_max16 = p_src_first+src_len-MAX_RAW_ITEM*16;
-
- /* The variables 'p_control' and 'control' are used to buffer control bits. */
- /* Before each group is processed, the next two bytes of the output block */
- /* are set aside for the control word for the group about to be processed. */
- /* 'p_control' is set to point to the first byte of that word. Meanwhile, */
- /* 'control' buffers the control bits being generated during the processing */
- /* of the group. Instead of having a counter to keep track of how many items */
- /* have been processed (=the number of bits in the control word), at the */
- /* start of each group, the top word of 'control' is filled with 1 bits. */
- /* As 'control' is shifted for each item, the 1 bits in the top word are */
- /* absorbed or destroyed. When they all run out (i.e. when the top word is */
- /* all zero bits, we know that we are at the end of a group. */
-# define TOPWORD 0xFFFF0000
- UBYTE *p_control;
- register ULONG control=TOPWORD;
-
- /* THe variable 'hash' always points to the first element of the hash table. */
- UBYTE **hash= (UBYTE **) ULONG_ALIGN_UP(p_wrk_mem);
-
- /* The following two variables represent the literal buffer. p_h1 points to */
- /* the hash table entry corresponding to the youngest literal. p_h2 points */
- /* to the hash table entry corresponding to the second youngest literal. */
- /* Note: p_h1=0=>p_h2=0 because zero values denote absence of a pending */
- /* literal. The variables are initialized to zero meaning an empty "buffer". */
- UBYTE **p_h1=NULL;
- UBYTE **p_h2=NULL;
-
- /* To start, we write the flag bytes. Being optimistic, we set the flag to */
- /* FLAG_COMPRESS. The remaining flag bytes are zeroed so as to keep the */
- /* algorithm deterministic. */
- *p_dst++=FLAG_COMPRESS;
- {UWORD i; for (i=2;i<=FLAG_BYTES;i++) *p_dst++=0;}
-
- /* Reserve the first word of output as the control word for the first group. */
- /* Note: This is undone at the end if the input block is empty. */
- p_control=p_dst; p_dst+=2;
-
- /* Initialize all elements of the hash table to point to a constant string. */
- /* Use of an unrolled loop speeds this up considerably. */
- {UWORD i; UBYTE **p_h=hash;
-# define ZH *p_h++=START_STRING_18
- for (i=0;i<256;i++) /* 256=HASH_TABLE_LENGTH/16. */
- {ZH;ZH;ZH;ZH;
- ZH;ZH;ZH;ZH;
- ZH;ZH;ZH;ZH;
- ZH;ZH;ZH;ZH;}
- }
-
- /* The main loop processes either 1 or 16 items per iteration. As its */
- /* termination logic is complicated, I have opted for an infinite loop */
- /* structure containing 'break' and 'goto' statements. */
- while (TRUE)
- {/* Begin main processing loop. */
-
- /* Note: All the variables here except unroll should be defined within */
- /* the inner loop. Unfortunately the loop hasn't got a block. */
- register UBYTE *p; /* Scans through targ phrase during matching. */
- register UBYTE *p_ziv= NULL ; /* Points to first byte of current Ziv. */
- register UWORD unroll; /* Loop counter for unrolled inner loop. */
- register UWORD index; /* Index of current hash table entry. */
- register UBYTE **p_h0 = NULL ; /* Pointer to current hash table entry. */
-
- /* Test for overrun and jump to overrun code if necessary. */
- if (p_dst>p_dst_post)
- goto overrun;
-
- /* The following cascade of if statements efficiently catches and deals */
- /* with varying degrees of closeness to the end of the input block. */
- /* When we get very close to the end, we stop updating the table and */
- /* code the remaining bytes as literals. This makes the code simpler. */
- unroll=16;
- if (p_src>p_src_max16)
- {
- unroll=1;
- if (p_src>p_src_max1)
- {
- if (p_src==p_src_post)
- break;
- else
- goto literal;
- }
- }
-
- /* This inner unrolled loop processes 'unroll' (whose value is either 1 */
- /* or 16) items. I have chosen to implement this loop with labels and */
- /* gotos to heighten the ease with which the loop may be implemented with */
- /* a single decrement and branch instruction in assembly language and */
- /* also because the labels act as highly readable place markers. */
- /* (Also because we jump into the loop for endgame literals (see above)). */
-
- begin_unrolled_loop:
-
- /* To process the next phrase, we hash the next three bytes and use */
- /* the resultant hash table index to look up the hash table. A pointer */
- /* to the entry is stored in p_h0 so as to avoid an array lookup. The */
- /* hash table entry *p_h0 is looked up yielding a pointer p to a */
- /* potential match of the Ziv in the history. */
- index=HASH(p_src);
- p_h0=&hash[index];
- p=*p_h0;
-
- /* Having looked up the candidate position, we are in a position to */
- /* attempt a match. The match loop has been unrolled using the PS */
- /* macro so that failure within the first three bytes automatically */
- /* results in the literal branch being taken. The coding is simple. */
- /* p_ziv saves p_src so we can let p_src wander. */
-# define PS *p++!=*p_src++
- p_ziv=p_src;
- if (PS || PS || PS)
- {
- /* Literal. */
-
- /* Code the literal byte as itself and a zero control bit. */
- p_src=p_ziv; literal: *p_dst++=*p_src++; control&=0xFFFEFFFF;
-
- /* We have just coded a literal. If we had two pending ones, that */
- /* makes three and we can update the hash table. */
- if (p_h2!=0)
- {*p_h2=p_ziv-2;}
-
- /* In any case, rotate the hash table pointers for next time. */
- p_h2=p_h1; p_h1=p_h0;
-
- }
- else
- {
- /* Copy */
-
- /* Match up to 15 remaining bytes using an unrolled loop and code. */
-#if 0
- PS || PS || PS || PS || PS || PS || PS || PS ||
- PS || PS || PS || PS || PS || PS || PS || p_src++;
-#else
- if (
- !( PS || PS || PS || PS || PS || PS || PS || PS ||
- PS || PS || PS || PS || PS || PS || PS )
- ) p_src++;
-#endif
- *p_dst++=((index&0xF00)>>4)|(--p_src-p_ziv-3);
- *p_dst++=index&0xFF;
-
- /* As we have just coded three bytes, we are now in a position to */
- /* update the hash table with the literal bytes that were pending */
- /* upon the arrival of extra context bytes. */
- if (p_h1!=0)
- {
- if (p_h2)
- {*p_h2=p_ziv-2; p_h2=NULL;}
- *p_h1=p_ziv-1; p_h1=NULL;
- }
-
- /* In any case, we can update the hash table based on the current */
- /* position as we just coded at least three bytes in a copy items. */
- *p_h0=p_ziv;
-
- }
- control>>=1;
-
- /* This loop is all set up for a decrement and jump instruction! */
-#ifndef linux
-` end_unrolled_loop: if (--unroll) goto begin_unrolled_loop;
-#else
- /* end_unrolled_loop: */ if (--unroll) goto begin_unrolled_loop;
-#endif
-
- /* At this point it will nearly always be the end of a group in which */
- /* case, we have to do some control-word processing. However, near the */
- /* end of the input block, the inner unrolled loop is only executed once. */
- /* This necessitates the 'if' test. */
- if ((control&TOPWORD)==0)
- {
- /* Write the control word to the place we saved for it in the output. */
- *p_control++= control &0xFF;
- *p_control = (control>>8) &0xFF;
-
- /* Reserve the next word in the output block for the control word */
- /* for the group about to be processed. */
- p_control=p_dst; p_dst+=2;
-
- /* Reset the control bits buffer. */
- control=TOPWORD;
- }
-
- } /* End main processing loop. */
-
- /* After the main processing loop has executed, all the input bytes have */
- /* been processed. However, the control word has still to be written to the */
- /* word reserved for it in the output at the start of the most recent group. */
- /* Before writing, the control word has to be shifted so that all the bits */
- /* are in the right place. The "empty" bit positions are filled with 1s */
- /* which partially fill the top word. */
- while(control&TOPWORD) control>>=1;
- *p_control++= control &0xFF;
- *p_control++=(control>>8) &0xFF;
-
- /* If the last group contained no items, delete the control word too. */
- if (p_control==p_dst) p_dst-=2;
-
- /* Write the length of the output block to the dst_len parameter and return. */
- *p_dst_len=p_dst-p_dst_first;
- return;
-
- /* Jump here as soon as an overrun is detected. An overrun is defined to */
- /* have occurred if p_dst>p_dst_first+src_len. That is, the moment the */
- /* length of the output written so far exceeds the length of the input block.*/
- /* The algorithm checks for overruns at least at the end of each group */
- /* which means that the maximum overrun is MAX_CMP_GROUP bytes. */
- /* Once an overrun occurs, the only thing to do is to set the copy flag and */
- /* copy the input over. */
- overrun:
-#if 0
- *p_dst_first=FLAG_COPY;
- fast_copy(p_src_first,p_dst_first+FLAG_BYTES,src_len);
- *p_dst_len=src_len+FLAG_BYTES;
-#else
- fast_copy(p_src_first,p_dst_first,src_len);
- *p_dst_len= -src_len; /* return a negative number to indicate uncompressed data */
-#endif
-}
-
-/******************************************************************************/
-
-/* Input : Hand over the required amount of working memory in p_wrk_mem. */
-/* Input : Specify input block using p_src_first and src_len. */
-/* Input : Point p_dst_first to the start of the output zone. */
-/* Input : Point p_dst_len to a ULONG to receive the output length. */
-/* Input : Input block and output zone must not overlap. User knows */
-/* Input : upperbound on output block length from earlier compression. */
-/* Input : In any case, maximum expansion possible is nine times. */
-/* Output : Length of output block written to *p_dst_len. */
-/* Output : Output block in Mem[p_dst_first..p_dst_first+*p_dst_len-1]. */
-/* Output : Writes only in Mem[p_dst_first..p_dst_first+*p_dst_len-1]. */
-LOCAL void compress_decompress( UBYTE *p_wrk_mem,
- UBYTE *p_src_first, LONG src_len,
- UBYTE *p_dst_first, ULONG *p_dst_len)
-{
- /* Byte pointers p_src and p_dst scan through the input and output blocks. */
- register UBYTE *p_src = p_src_first+FLAG_BYTES;
- register UBYTE *p_dst = p_dst_first;
- /* we need to avoid a SEGV when trying to uncompress corrupt data */
- register UBYTE *p_dst_post = p_dst_first + *p_dst_len;
-
- /* The following two variables are never modified and are used to control */
- /* the main loop. */
- UBYTE *p_src_post = p_src_first+src_len;
- UBYTE *p_src_max16 = p_src_first+src_len-(MAX_CMP_GROUP-2);
-
- /* The hash table is the only resident of the working memory. The hash table */
- /* contains HASH_TABLE_LENGTH=4096 pointers to positions in the history. To */
- /* keep Macintoshes happy, it is longword aligned. */
- UBYTE **hash = (UBYTE **) ULONG_ALIGN_UP(p_wrk_mem);
-
- /* The variable 'control' is used to buffer the control bits which appear in */
- /* groups of 16 bits (control words) at the start of each compressed group. */
- /* When each group is read, bit 16 of the register is set to one. Whenever */
- /* a new bit is needed, the register is shifted right. When the value of the */
- /* register becomes 1, we know that we have reached the end of a group. */
- /* Initializing the register to 1 thus instructs the code to follow that it */
- /* should read a new control word immediately. */
- register ULONG control=1;
-
- /* The value of 'literals' is always in the range 0..3. It is the number of */
- /* consecutive literal items just seen. We have to record this number so as */
- /* to know when to update the hash table. When literals gets to 3, there */
- /* have been three consecutive literals and we can update at the position of */
- /* the oldest of the three. */
- register UWORD literals=0;
-
- /* Check the leading copy flag to see if the compressor chose to use a copy */
- /* operation instead of a compression operation. If a copy operation was */
- /* used, then all we need to do is copy the data over, set the output length */
- /* and return. */
-#if 0
- if (*p_src_first==FLAG_COPY)
- {
- fast_copy(p_src_first+FLAG_BYTES,p_dst_first,src_len-FLAG_BYTES);
- *p_dst_len=src_len-FLAG_BYTES;
- return;
- }
-#else
- if ( src_len < 0 )
- {
- fast_copy(p_src_first,p_dst_first,-src_len );
- *p_dst_len = (ULONG)-src_len;
- return;
- }
-#endif
-
- /* Initialize all elements of the hash table to point to a constant string. */
- /* Use of an unrolled loop speeds this up considerably. */
- {UWORD i; UBYTE **p_h=hash;
-# define ZJ *p_h++=START_STRING_18
- for (i=0;i<256;i++) /* 256=HASH_TABLE_LENGTH/16. */
- {ZJ;ZJ;ZJ;ZJ;
- ZJ;ZJ;ZJ;ZJ;
- ZJ;ZJ;ZJ;ZJ;
- ZJ;ZJ;ZJ;ZJ;}
- }
-
- /* The outer loop processes either 1 or 16 items per iteration depending on */
- /* how close p_src is to the end of the input block. */
- while (p_src!=p_src_post)
- {/* Start of outer loop */
-
- register UWORD unroll; /* Counts unrolled loop executions. */
-
- /* When 'control' has the value 1, it means that the 16 buffered control */
- /* bits that were read in at the start of the current group have all been */
- /* shifted out and that all that is left is the 1 bit that was injected */
- /* into bit 16 at the start of the current group. When we reach the end */
- /* of a group, we have to load a new control word and inject a new 1 bit. */
- if (control==1)
- {
- control=0x10000|*p_src++;
- control|=(*p_src++)<<8;
- }
-
- /* If it is possible that we are within 16 groups from the end of the */
- /* input, execute the unrolled loop only once, else process a whole group */
- /* of 16 items by looping 16 times. */
- unroll= p_src<=p_src_max16 ? 16 : 1;
-
- /* This inner loop processes one phrase (item) per iteration. */
- while (unroll--)
- { /* Begin unrolled inner loop. */
-
- /* Process a literal or copy item depending on the next control bit. */
- if (control&1)
- {
- /* Copy item. */
-
- register UBYTE *p; /* Points to place from which to copy. */
- register UWORD lenmt; /* Length of copy item minus three. */
- register UBYTE **p_hte; /* Pointer to current hash table entry.*/
- register UBYTE *p_ziv=p_dst; /* Pointer to start of current Ziv. */
-
- /* Read and dismantle the copy word. Work out from where to copy. */
- lenmt=*p_src++;
- p_hte=&hash[((lenmt&0xF0)<<4)|*p_src++];
- p=*p_hte;
- lenmt&=0xF;
-
- /* Now perform the copy using a half unrolled loop. */
- *p_dst++=*p++;
- *p_dst++=*p++;
- *p_dst++=*p++;
- while (lenmt--)
- *p_dst++=*p++;
-
- /* Because we have just received 3 or more bytes in a copy item */
- /* (whose bytes we have just installed in the output), we are now */
- /* in a position to flush all the pending literal hashings that had */
- /* been postponed for lack of bytes. */
- if (literals>0)
- {
- register UBYTE *r=p_ziv-literals;
- hash[HASH(r)]=r;
- if (literals==2)
- {r++; hash[HASH(r)]=r;}
- literals=0;
- }
-
- /* In any case, we can immediately update the hash table with the */
- /* current position. We don't need to do a HASH(...) to work out */
- /* where to put the pointer, as the compressor just told us!!! */
- *p_hte=p_ziv;
-
- }
- else
- {
- /* Literal item. */
-
- /* Copy over the literal byte. */
- *p_dst++=*p_src++;
-
- /* If we now have three literals waiting to be hashed into the hash */
- /* table, we can do one of them now (because there are three). */
- if (++literals == 3)
- {register UBYTE *p=p_dst-3; hash[HASH(p)]=p; literals=2;}
- }
-
- /* Shift the control buffer so the next control bit is in bit 0. */
- control>>=1;
-#if 1
- if (p_dst > p_dst_post)
- {
- /* Shit: we tried to decompress corrupt data */
- *p_dst_len = 0;
- return;
- }
-#endif
- } /* End unrolled inner loop. */
-
- } /* End of outer loop */
-
- /* Write the length of the decompressed data before returning. */
- *p_dst_len=p_dst-p_dst_first;
-}
-
-/******************************************************************************/
-/* End of LZRW3.C */
-/******************************************************************************/
diff --git a/drivers/char/ftape/compressor/lzrw3.h b/drivers/char/ftape/compressor/lzrw3.h
deleted file mode 100644
index 533feba47526..000000000000
--- a/drivers/char/ftape/compressor/lzrw3.h
+++ /dev/null
@@ -1,253 +0,0 @@
-#ifndef _LZRW3_H
-#define _LZRW3_H
-/*
- * $Source: /homes/cvs/ftape-stacked/ftape/compressor/lzrw3.h,v $
- * $Revision: 1.1 $
- * $Date: 1997/10/05 19:12:30 $
- *
- * include files for lzrw3. Only slighty modified from the original
- * version. Assembles the three include files compress.h, port.h and
- * fastcopy.h from the original lzrw3 package.
- *
- */
-
-#include <linux/types.h>
-#include <linux/string.h>
-
-/******************************************************************************/
-/* */
-/* COMPRESS.H */
-/* */
-/******************************************************************************/
-/* */
-/* Author : Ross Williams. */
-/* Date : December 1989. */
-/* */
-/* This header file defines the interface to a set of functions called */
-/* 'compress', each member of which implements a particular data compression */
-/* algorithm. */
-/* */
-/* Normally in C programming, for each .H file, there is a corresponding .C */
-/* file that implements the functions promised in the .H file. */
-/* Here, there are many .C files corresponding to this header file. */
-/* Each comforming implementation file contains a single function */
-/* called 'compress' that implements a single data compression */
-/* algorithm that conforms with the interface specified in this header file. */
-/* Only one algorithm can be linked in at a time in this organization. */
-/* */
-/******************************************************************************/
-/* */
-/* DEFINITION OF FUNCTION COMPRESS */
-/* =============================== */
-/* */
-/* Summary of Function Compress */
-/* ---------------------------- */
-/* The action that 'compress' takes depends on its first argument called */
-/* 'action'. The function provides three actions: */
-/* */
-/* - Return information about the algorithm. */
-/* - Compress a block of memory. */
-/* - Decompress a block of memory. */
-/* */
-/* Parameters */
-/* ---------- */
-/* See the formal C definition later for a description of the parameters. */
-/* */
-/* Constants */
-/* --------- */
-/* COMPRESS_OVERRUN: The constant COMPRESS_OVERRUN defines by how many bytes */
-/* an algorithm is allowed to expand a block during a compression operation. */
-/* */
-/* Although compression algorithms usually compress data, there will always */
-/* be data that a given compressor will expand (this can be proven). */
-/* Fortunately, the degree of expansion can be limited to a single bit, by */
-/* copying over the input data if the data gets bigger during compression. */
-/* To allow for this possibility, the first bit of a compressed */
-/* representation can be used as a flag indicating whether the */
-/* input data was copied over, or truly compressed. In practice, the first */
-/* byte would be used to store this bit so as to maintain byte alignment. */
-/* */
-/* Unfortunately, in general, the only way to tell if an algorithm will */
-/* expand a particular block of data is to run the algorithm on the data. */
-/* If the algorithm does not continuously monitor how many output bytes it */
-/* has written, it might write an output block far larger than the input */
-/* block before realizing that it has done so. */
-/* On the other hand, continuous checks on output length are inefficient. */
-/* */
-/* To cater for all these problems, this interface definition: */
-/* > Allows a compression algorithm to return an output block that is up to */
-/* COMPRESS_OVERRUN bytes longer than the input block. */
-/* > Allows a compression algorithm to write up to COMPRESS_OVERRUN bytes */
-/* more than the length of the input block to the memory of the output */
-/* block regardless of the length of the output block eventually returned. */
-/* This allows an algorithm to overrun the length of the input block in the */
-/* output block by up to COMPRESS_OVERRUN bytes between expansion checks. */
-/* */
-/* The problem does not arise for decompression. */
-/* */
-/* Identity Action */
-/* --------------- */
-/* > action must be COMPRESS_ACTION_IDENTITY. */
-/* > p_dst_len must point to a longword to receive a longword address. */
-/* > The value of the other parameters does not matter. */
-/* > After execution, the longword that p_dst_len points to will be a pointer */
-/* to a structure of type compress_identity. */
-/* Thus, for example, after the call, (*p_dst_len)->memory will return the */
-/* number of bytes of working memory that the algorithm requires to run. */
-/* > The values of the identity structure returned are fixed constant */
-/* attributes of the algorithm and must not vary from call to call. */
-/* */
-/* Common Requirements for Compression and Decompression Actions */
-/* ------------------------------------------------------------- */
-/* > wrk_mem must point to an unused block of memory of a length specified in */
-/* the algorithm's identity block. The identity block can be obtained by */
-/* making a separate call to compress, specifying the identity action. */
-/* > The INPUT BLOCK is defined to be Memory[src_addr,src_addr+src_len-1]. */
-/* > dst_len will be used to denote *p_dst_len. */
-/* > dst_len is not read by compress, only written. */
-/* > The value of dst_len is defined only upon termination. */
-/* > The OUTPUT BLOCK is defined to be Memory[dst_addr,dst_addr+dst_len-1]. */
-/* */
-/* Compression Action */
-/* ------------------ */
-/* > action must be COMPRESS_ACTION_COMPRESS. */
-/* > src_len must be in the range [0,COMPRESS_MAX_ORG]. */
-/* > The OUTPUT ZONE is defined to be */
-/* Memory[dst_addr,dst_addr+src_len-1+COMPRESS_OVERRUN]. */
-/* > The function can modify any part of the output zone regardless of the */
-/* final length of the output block. */
-/* > The input block and the output zone must not overlap. */
-/* > dst_len will be in the range [0,src_len+COMPRESS_OVERRUN]. */
-/* > dst_len will be in the range [0,COMPRESS_MAX_COM] (from prev fact). */
-/* > The output block will consist of a representation of the input block. */
-/* */
-/* Decompression Action */
-/* -------------------- */
-/* > action must be COMPRESS_ACTION_DECOMPRESS. */
-/* > The input block must be the result of an earlier compression operation. */
-/* > If the previous fact is true, the following facts must also be true: */
-/* > src_len will be in the range [0,COMPRESS_MAX_COM]. */
-/* > dst_len will be in the range [0,COMPRESS_MAX_ORG]. */
-/* > The input and output blocks must not overlap. */
-/* > Only the output block is modified. */
-/* > Upon termination, the output block will consist of the bytes contained */
-/* in the input block passed to the earlier compression operation. */
-/* */
-/******************************************************************************/
-
-/******************************************************************************/
-/* */
-/* PORT.H */
-/* */
-/******************************************************************************/
-/* */
-/* This module contains macro definitions and types that are likely to */
-/* change between computers. */
-/* */
-/******************************************************************************/
-
-#ifndef DONE_PORT /* Only do this if not previously done. */
-
- #ifdef THINK_C
- #define UBYTE unsigned char /* Unsigned byte */
- #define UWORD unsigned int /* Unsigned word (2 bytes) */
- #define ULONG unsigned long /* Unsigned word (4 bytes) */
- #define BOOL unsigned char /* Boolean */
- #define FOPEN_BINARY_READ "rb" /* Mode string for binary reading. */
- #define FOPEN_BINARY_WRITE "wb" /* Mode string for binary writing. */
- #define FOPEN_TEXT_APPEND "a" /* Mode string for text appending. */
- #define REAL double /* USed for floating point stuff. */
- #endif
- #if defined(LINUX) || defined(linux)
- #define UBYTE __u8 /* Unsigned byte */
- #define UWORD __u16 /* Unsigned word (2 bytes) */
- #define ULONG __u32 /* Unsigned word (4 bytes) */
- #define LONG __s32 /* Signed word (4 bytes) */
- #define BOOL is not used here /* Boolean */
- #define FOPEN_BINARY_READ not used /* Mode string for binary reading. */
- #define FOPEN_BINARY_WRITE not used /* Mode string for binary writing. */
- #define FOPEN_TEXT_APPEND not used /* Mode string for text appending. */
- #define REAL not used /* USed for floating point stuff. */
- #ifndef TRUE
- #define TRUE 1
- #endif
- #endif
-
- #define DONE_PORT /* Don't do all this again. */
- #define MALLOC_FAIL NULL /* Failure status from malloc() */
- #define LOCAL static /* For non-exported routines. */
- #define EXPORT /* Signals exported function. */
- #define then /* Useful for aligning ifs. */
-
-#endif
-
-/******************************************************************************/
-/* End of PORT.H */
-/******************************************************************************/
-
-#define COMPRESS_ACTION_IDENTITY 0
-#define COMPRESS_ACTION_COMPRESS 1
-#define COMPRESS_ACTION_DECOMPRESS 2
-
-#define COMPRESS_OVERRUN 1024
-#define COMPRESS_MAX_COM 0x70000000
-#define COMPRESS_MAX_ORG (COMPRESS_MAX_COM-COMPRESS_OVERRUN)
-
-#define COMPRESS_MAX_STRLEN 255
-
-/* The following structure provides information about the algorithm. */
-/* > The top bit of id must be zero. The remaining bits must be chosen by */
-/* the author of the algorithm by tossing a coin 31 times. */
-/* > The amount of memory requested by the algorithm is specified in bytes */
-/* and must be in the range [0,0x70000000]. */
-/* > All strings s must be such that strlen(s)<=COMPRESS_MAX_STRLEN. */
-struct compress_identity
- {
- ULONG id; /* Identifying number of algorithm. */
- ULONG memory; /* Number of bytes of working memory required. */
-
- char *name; /* Name of algorithm. */
- char *version; /* Version number. */
- char *date; /* Date of release of this version. */
- char *copyright; /* Copyright message. */
-
- char *author; /* Author of algorithm. */
- char *affiliation; /* Affiliation of author. */
- char *vendor; /* Where the algorithm can be obtained. */
- };
-
-void lzrw3_compress( /* Single function interface to compression algorithm. */
-UWORD action, /* Action to be performed. */
-UBYTE *wrk_mem, /* Working memory temporarily given to routine to use. */
-UBYTE *src_adr, /* Address of input data. */
-LONG src_len, /* Length of input data. */
-UBYTE *dst_adr, /* Address of output data. */
-void *p_dst_len /* Pointer to a longword where routine will write: */
- /* If action=..IDENTITY => Adr of id structure. */
- /* If action=..COMPRESS => Length of output data. */
- /* If action=..DECOMPRESS => Length of output data. */
-);
-
-/******************************************************************************/
-/* End of COMPRESS.H */
-/******************************************************************************/
-
-
-/******************************************************************************/
-/* fast_copy.h */
-/******************************************************************************/
-
-/* This function copies a block of memory very quickly. */
-/* The exact speed depends on the relative alignment of the blocks of memory. */
-/* PRE : 0<=src_len<=(2^32)-1 . */
-/* PRE : Source and destination blocks must not overlap. */
-/* POST : MEM[dst_adr,dst_adr+src_len-1]=MEM[src_adr,src_adr+src_len-1]. */
-/* POST : MEM[dst_adr,dst_adr+src_len-1] is the only memory changed. */
-
-#define fast_copy(src,dst,len) memcpy(dst,src,len)
-
-/******************************************************************************/
-/* End of fast_copy.h */
-/******************************************************************************/
-
-#endif
diff --git a/drivers/char/ftape/compressor/zftape-compress.c b/drivers/char/ftape/compressor/zftape-compress.c
deleted file mode 100644
index 65ffc0be3df9..000000000000
--- a/drivers/char/ftape/compressor/zftape-compress.c
+++ /dev/null
@@ -1,1203 +0,0 @@
-/*
- * Copyright (C) 1994-1997 Claus-Justus Heine
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
- USA.
-
- *
- * This file implements a "generic" interface between the *
- * zftape-driver and a compression-algorithm. The *
- * compression-algorithm currently used is a LZ77. I use the *
- * implementation lzrw3 by Ross N. Williams (Renaissance *
- * Software). The compression program itself is in the file
- * lzrw3.c * and lzrw3.h. To adopt another compression algorithm
- * the functions * zft_compress() and zft_uncompress() must be
- * changed * appropriately. See below.
- */
-
-#include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-
-#include <linux/zftape.h>
-
-#include <asm/uaccess.h>
-
-#include "../zftape/zftape-init.h"
-#include "../zftape/zftape-eof.h"
-#include "../zftape/zftape-ctl.h"
-#include "../zftape/zftape-write.h"
-#include "../zftape/zftape-read.h"
-#include "../zftape/zftape-rw.h"
-#include "../compressor/zftape-compress.h"
-#include "../zftape/zftape-vtbl.h"
-#include "../compressor/lzrw3.h"
-
-/*
- * global variables
- */
-
-/* I handle the allocation of this buffer as a special case, because
- * it's size varies depending on the tape length inserted.
- */
-
-/* local variables
- */
-static void *zftc_wrk_mem = NULL;
-static __u8 *zftc_buf = NULL;
-static void *zftc_scratch_buf = NULL;
-
-/* compression statistics
- */
-static unsigned int zftc_wr_uncompressed = 0;
-static unsigned int zftc_wr_compressed = 0;
-static unsigned int zftc_rd_uncompressed = 0;
-static unsigned int zftc_rd_compressed = 0;
-
-/* forward */
-static int zftc_write(int *write_cnt,
- __u8 *dst_buf, const int seg_sz,
- const __u8 __user *src_buf, const int req_len,
- const zft_position *pos, const zft_volinfo *volume);
-static int zftc_read(int *read_cnt,
- __u8 __user *dst_buf, const int to_do,
- const __u8 *src_buf, const int seg_sz,
- const zft_position *pos, const zft_volinfo *volume);
-static int zftc_seek(unsigned int new_block_pos,
- zft_position *pos, const zft_volinfo *volume,
- __u8 *buffer);
-static void zftc_lock (void);
-static void zftc_reset (void);
-static void zftc_cleanup(void);
-static void zftc_stats (void);
-
-/* compressed segment. This conforms to QIC-80-MC, Revision K.
- *
- * Rev. K applies to tapes with `fixed length format' which is
- * indicated by format code 2,3 and 5. See below for format code 4 and 6
- *
- * 2 bytes: offset of compression segment structure
- * 29k > offset >= 29k-18: data from previous segment ens in this
- * segment and no compressed block starts
- * in this segment
- * offset == 0: data from previous segment occupies entire
- * segment and continues in next segment
- * n bytes: remainder from previous segment
- *
- * Rev. K:
- * 4 bytes: 4 bytes: files set byte offset
- * Post Rev. K and QIC-3020/3020:
- * 8 bytes: 8 bytes: files set byte offset
- * 2 bytes: byte count N (amount of data following)
- * bit 15 is set if data is compressed, bit 15 is not
- * set if data is uncompressed
- * N bytes: data (as much as specified in the byte count)
- * 2 bytes: byte count N_1 of next cluster
- * N_1 bytes: data of next cluset
- * 2 bytes: byte count N_2 of next cluster
- * N_2 bytes: ...
- *
- * Note that the `N' byte count accounts only for the bytes that in the
- * current segment if the cluster spans to the next segment.
- */
-
-typedef struct
-{
- int cmpr_pos; /* actual position in compression buffer */
- int cmpr_sz; /* what is left in the compression buffer
- * when copying the compressed data to the
- * deblock buffer
- */
- unsigned int first_block; /* location of header information in
- * this segment
- */
- unsigned int count; /* amount of data of current block
- * contained in current segment
- */
- unsigned int offset; /* offset in current segment */
- unsigned int spans:1; /* might continue in next segment */
- unsigned int uncmpr; /* 0x8000 if this block contains
- * uncompressed data
- */
- __s64 foffs; /* file set byte offset, same as in
- * compression map segment
- */
-} cmpr_info;
-
-static cmpr_info cseg; /* static data. Must be kept uptodate and shared by
- * read, write and seek functions
- */
-
-#define DUMP_CMPR_INFO(level, msg, info) \
- TRACE(level, msg "\n" \
- KERN_INFO "cmpr_pos : %d\n" \
- KERN_INFO "cmpr_sz : %d\n" \
- KERN_INFO "first_block: %d\n" \
- KERN_INFO "count : %d\n" \
- KERN_INFO "offset : %d\n" \
- KERN_INFO "spans : %d\n" \
- KERN_INFO "uncmpr : 0x%04x\n" \
- KERN_INFO "foffs : " LL_X, \
- (info)->cmpr_pos, (info)->cmpr_sz, (info)->first_block, \
- (info)->count, (info)->offset, (info)->spans == 1, \
- (info)->uncmpr, LL((info)->foffs))
-
-/* dispatch compression segment info, return error code
- *
- * afterwards, cseg->offset points to start of data of the NEXT
- * compressed block, and cseg->count contains the amount of data
- * left in the actual compressed block. cseg->spans is set to 1 if
- * the block is continued in the following segment. Otherwise it is
- * set to 0.
- */
-static int get_cseg (cmpr_info *cinfo, const __u8 *buff,
- const unsigned int seg_sz,
- const zft_volinfo *volume)
-{
- TRACE_FUN(ft_t_flow);
-
- cinfo->first_block = GET2(buff, 0);
- if (cinfo->first_block == 0) { /* data spans to next segment */
- cinfo->count = seg_sz - sizeof(__u16);
- cinfo->offset = seg_sz;
- cinfo->spans = 1;
- } else { /* cluster definetely ends in this segment */
- if (cinfo->first_block > seg_sz) {
- /* data corrupted */
- TRACE_ABORT(-EIO, ft_t_err, "corrupted data:\n"
- KERN_INFO "segment size: %d\n"
- KERN_INFO "first block : %d",
- seg_sz, cinfo->first_block);
- }
- cinfo->count = cinfo->first_block - sizeof(__u16);
- cinfo->offset = cinfo->first_block;
- cinfo->spans = 0;
- }
- /* now get the offset the first block should have in the
- * uncompressed data stream.
- *
- * For this magic `18' refer to CRF-3 standard or QIC-80MC,
- * Rev. K.
- */
- if ((seg_sz - cinfo->offset) > 18) {
- if (volume->qic113) { /* > revision K */
- TRACE(ft_t_data_flow, "New QIC-113 compliance");
- cinfo->foffs = GET8(buff, cinfo->offset);
- cinfo->offset += sizeof(__s64);
- } else {
- TRACE(/* ft_t_data_flow */ ft_t_noise, "pre QIC-113 version");
- cinfo->foffs = (__s64)GET4(buff, cinfo->offset);
- cinfo->offset += sizeof(__u32);
- }
- }
- if (cinfo->foffs > volume->size) {
- TRACE_ABORT(-EIO, ft_t_err, "Inconsistency:\n"
- KERN_INFO "offset in current volume: %d\n"
- KERN_INFO "size of current volume : %d",
- (int)(cinfo->foffs>>10), (int)(volume->size>>10));
- }
- if (cinfo->cmpr_pos + cinfo->count > volume->blk_sz) {
- TRACE_ABORT(-EIO, ft_t_err, "Inconsistency:\n"
- KERN_INFO "block size : %d\n"
- KERN_INFO "data record: %d",
- volume->blk_sz, cinfo->cmpr_pos + cinfo->count);
- }
- DUMP_CMPR_INFO(ft_t_noise /* ft_t_any */, "", cinfo);
- TRACE_EXIT 0;
-}
-
-/* This one is called, when a new cluster starts in same segment.
- *
- * Note: if this is the first cluster in the current segment, we must
- * not check whether there are more than 18 bytes available because
- * this have already been done in get_cseg() and there may be less
- * than 18 bytes available due to header information.
- *
- */
-static void get_next_cluster(cmpr_info *cluster, const __u8 *buff,
- const int seg_sz, const int finish)
-{
- TRACE_FUN(ft_t_flow);
-
- if (seg_sz - cluster->offset > 18 || cluster->foffs != 0) {
- cluster->count = GET2(buff, cluster->offset);
- cluster->uncmpr = cluster->count & 0x8000;
- cluster->count -= cluster->uncmpr;
- cluster->offset += sizeof(__u16);
- cluster->foffs = 0;
- if ((cluster->offset + cluster->count) < seg_sz) {
- cluster->spans = 0;
- } else if (cluster->offset + cluster->count == seg_sz) {
- cluster->spans = !finish;
- } else {
- /* either an error or a volume written by an
- * old version. If this is a data error, then we'll
- * catch it later.
- */
- TRACE(ft_t_data_flow, "Either error or old volume");
- cluster->spans = 1;
- cluster->count = seg_sz - cluster->offset;
- }
- } else {
- cluster->count = 0;
- cluster->spans = 0;
- cluster->foffs = 0;
- }
- DUMP_CMPR_INFO(ft_t_noise /* ft_t_any */ , "", cluster);
- TRACE_EXIT;
-}
-
-static void zftc_lock(void)
-{
-}
-
-/* this function is needed for zftape_reset_position in zftape-io.c
- */
-static void zftc_reset(void)
-{
- TRACE_FUN(ft_t_flow);
-
- memset((void *)&cseg, '\0', sizeof(cseg));
- zftc_stats();
- TRACE_EXIT;
-}
-
-static int cmpr_mem_initialized = 0;
-static unsigned int alloc_blksz = 0;
-
-static int zft_allocate_cmpr_mem(unsigned int blksz)
-{
- TRACE_FUN(ft_t_flow);
-
- if (cmpr_mem_initialized && blksz == alloc_blksz) {
- TRACE_EXIT 0;
- }
- TRACE_CATCH(zft_vmalloc_once(&zftc_wrk_mem, CMPR_WRK_MEM_SIZE),
- zftc_cleanup());
- TRACE_CATCH(zft_vmalloc_always(&zftc_buf, blksz + CMPR_OVERRUN),
- zftc_cleanup());
- alloc_blksz = blksz;
- TRACE_CATCH(zft_vmalloc_always(&zftc_scratch_buf, blksz+CMPR_OVERRUN),
- zftc_cleanup());
- cmpr_mem_initialized = 1;
- TRACE_EXIT 0;
-}
-
-static void zftc_cleanup(void)
-{
- TRACE_FUN(ft_t_flow);
-
- zft_vfree(&zftc_wrk_mem, CMPR_WRK_MEM_SIZE);
- zft_vfree(&zftc_buf, alloc_blksz + CMPR_OVERRUN);
- zft_vfree(&zftc_scratch_buf, alloc_blksz + CMPR_OVERRUN);
- cmpr_mem_initialized = alloc_blksz = 0;
- TRACE_EXIT;
-}
-
-/*****************************************************************************
- * *
- * The following two functions "ftape_compress()" and *
- * "ftape_uncompress()" are the interface to the actual compression *
- * algorithm (i.e. they are calling the "compress()" function from *
- * the lzrw3 package for now). These routines could quite easily be *
- * changed to adopt another compression algorithm instead of lzrw3, *
- * which currently is used. *
- * *
- *****************************************************************************/
-
-/* called by zft_compress_write() to perform the compression. Must
- * return the size of the compressed data.
- *
- * NOTE: The size of the compressed data should not exceed the size of
- * the uncompressed data. Most compression algorithms have means
- * to store data unchanged if the "compressed" data amount would
- * exceed the original one. Mostly this is done by storing some
- * flag-bytes in front of the compressed data to indicate if it
- * is compressed or not. Thus the worst compression result
- * length is the original length plus those flag-bytes.
- *
- * We don't want that, as the QIC-80 standard provides a means
- * of marking uncompressed blocks by simply setting bit 15 of
- * the compressed block's length. Thus a compessed block can
- * have at most a length of 2^15-1 bytes. The QIC-80 standard
- * restricts the block-length even further, allowing only 29k -
- * 6 bytes.
- *
- * Currently, the maximum blocksize used by zftape is 28k.
- *
- * In short: don't exceed the length of the input-package, set
- * bit 15 of the compressed size to 1 if you have copied data
- * instead of compressing it.
- */
-static int zft_compress(__u8 *in_buffer, unsigned int in_sz, __u8 *out_buffer)
-{
- __s32 compressed_sz;
- TRACE_FUN(ft_t_flow);
-
-
- lzrw3_compress(COMPRESS_ACTION_COMPRESS, zftc_wrk_mem,
- in_buffer, in_sz, out_buffer, &compressed_sz);
- if (TRACE_LEVEL >= ft_t_info) {
- /* the compiler will optimize this away when
- * compiled with NO_TRACE_AT_ALL option
- */
- TRACE(ft_t_data_flow, "\n"
- KERN_INFO "before compression: %d bytes\n"
- KERN_INFO "after compresison : %d bytes",
- in_sz,
- (int)(compressed_sz < 0
- ? -compressed_sz : compressed_sz));
- /* for statistical purposes
- */
- zftc_wr_compressed += (compressed_sz < 0
- ? -compressed_sz : compressed_sz);
- zftc_wr_uncompressed += in_sz;
- }
- TRACE_EXIT (int)compressed_sz;
-}
-
-/* called by zft_compress_read() to decompress the data. Must
- * return the size of the decompressed data for sanity checks
- * (compared with zft_blk_sz)
- *
- * NOTE: Read the note for zft_compress() above! If bit 15 of the
- * parameter in_sz is set, then the data in in_buffer isn't
- * compressed, which must be handled by the un-compression
- * algorithm. (I changed lzrw3 to handle this.)
- *
- * The parameter max_out_sz is needed to prevent buffer overruns when
- * uncompressing corrupt data.
- */
-static unsigned int zft_uncompress(__u8 *in_buffer,
- int in_sz,
- __u8 *out_buffer,
- unsigned int max_out_sz)
-{
- TRACE_FUN(ft_t_flow);
-
- lzrw3_compress(COMPRESS_ACTION_DECOMPRESS, zftc_wrk_mem,
- in_buffer, (__s32)in_sz,
- out_buffer, (__u32 *)&max_out_sz);
-
- if (TRACE_LEVEL >= ft_t_info) {
- TRACE(ft_t_data_flow, "\n"
- KERN_INFO "before decompression: %d bytes\n"
- KERN_INFO "after decompression : %d bytes",
- in_sz < 0 ? -in_sz : in_sz,(int)max_out_sz);
- /* for statistical purposes
- */
- zftc_rd_compressed += in_sz < 0 ? -in_sz : in_sz;
- zftc_rd_uncompressed += max_out_sz;
- }
- TRACE_EXIT (unsigned int)max_out_sz;
-}
-
-/* print some statistics about the efficiency of the compression to
- * the kernel log
- */
-static void zftc_stats(void)
-{
- TRACE_FUN(ft_t_flow);
-
- if (TRACE_LEVEL < ft_t_info) {
- TRACE_EXIT;
- }
- if (zftc_wr_uncompressed != 0) {
- if (zftc_wr_compressed > (1<<14)) {
- TRACE(ft_t_info, "compression statistics (writing):\n"
- KERN_INFO " compr./uncmpr. : %3d %%",
- (((zftc_wr_compressed>>10) * 100)
- / (zftc_wr_uncompressed>>10)));
- } else {
- TRACE(ft_t_info, "compression statistics (writing):\n"
- KERN_INFO " compr./uncmpr. : %3d %%",
- ((zftc_wr_compressed * 100)
- / zftc_wr_uncompressed));
- }
- }
- if (zftc_rd_uncompressed != 0) {
- if (zftc_rd_compressed > (1<<14)) {
- TRACE(ft_t_info, "compression statistics (reading):\n"
- KERN_INFO " compr./uncmpr. : %3d %%",
- (((zftc_rd_compressed>>10) * 100)
- / (zftc_rd_uncompressed>>10)));
- } else {
- TRACE(ft_t_info, "compression statistics (reading):\n"
- KERN_INFO " compr./uncmpr. : %3d %%",
- ((zftc_rd_compressed * 100)
- / zftc_rd_uncompressed));
- }
- }
- /* only print it once: */
- zftc_wr_uncompressed =
- zftc_wr_compressed =
- zftc_rd_uncompressed =
- zftc_rd_compressed = 0;
- TRACE_EXIT;
-}
-
-/* start new compressed block
- */
-static int start_new_cseg(cmpr_info *cluster,
- char *dst_buf,
- const zft_position *pos,
- const unsigned int blk_sz,
- const char *src_buf,
- const int this_segs_sz,
- const int qic113)
-{
- int size_left;
- int cp_cnt;
- int buf_pos;
- TRACE_FUN(ft_t_flow);
-
- size_left = this_segs_sz - sizeof(__u16) - cluster->cmpr_sz;
- TRACE(ft_t_data_flow,"\n"
- KERN_INFO "segment size : %d\n"
- KERN_INFO "compressed_sz: %d\n"
- KERN_INFO "size_left : %d",
- this_segs_sz, cluster->cmpr_sz, size_left);
- if (size_left > 18) { /* start a new cluseter */
- cp_cnt = cluster->cmpr_sz;
- cluster->cmpr_sz = 0;
- buf_pos = cp_cnt + sizeof(__u16);
- PUT2(dst_buf, 0, buf_pos);
-
- if (qic113) {
- __s64 foffs = pos->volume_pos;
- if (cp_cnt) foffs += (__s64)blk_sz;
-
- TRACE(ft_t_data_flow, "new style QIC-113 header");
- PUT8(dst_buf, buf_pos, foffs);
- buf_pos += sizeof(__s64);
- } else {
- __u32 foffs = (__u32)pos->volume_pos;
- if (cp_cnt) foffs += (__u32)blk_sz;
-
- TRACE(ft_t_data_flow, "old style QIC-80MC header");
- PUT4(dst_buf, buf_pos, foffs);
- buf_pos += sizeof(__u32);
- }
- } else if (size_left >= 0) {
- cp_cnt = cluster->cmpr_sz;
- cluster->cmpr_sz = 0;
- buf_pos = cp_cnt + sizeof(__u16);
- PUT2(dst_buf, 0, buf_pos);
- /* zero unused part of segment. */
- memset(dst_buf + buf_pos, '\0', size_left);
- buf_pos = this_segs_sz;
- } else { /* need entire segment and more space */
- PUT2(dst_buf, 0, 0);
- cp_cnt = this_segs_sz - sizeof(__u16);
- cluster->cmpr_sz -= cp_cnt;
- buf_pos = this_segs_sz;
- }
- memcpy(dst_buf + sizeof(__u16), src_buf + cluster->cmpr_pos, cp_cnt);
- cluster->cmpr_pos += cp_cnt;
- TRACE_EXIT buf_pos;
-}
-
-/* return-value: the number of bytes removed from the user-buffer
- * `src_buf' or error code
- *
- * int *write_cnt : how much actually has been moved to the
- * dst_buf. Need not be initialized when
- * function returns with an error code
- * (negativ return value)
- * __u8 *dst_buf : kernel space buffer where the has to be
- * copied to. The contents of this buffers
- * goes to a specific segment.
- * const int seg_sz : the size of the segment dst_buf will be
- * copied to.
- * const zft_position *pos : struct containing the coordinates in
- * the current volume (byte position,
- * segment id of current segment etc)
- * const zft_volinfo *volume: information about the current volume,
- * size etc.
- * const __u8 *src_buf : user space buffer that contains the
- * data the user wants to be written to
- * tape.
- * const int req_len : the amount of data the user wants to be
- * written to tape.
- */
-static int zftc_write(int *write_cnt,
- __u8 *dst_buf, const int seg_sz,
- const __u8 __user *src_buf, const int req_len,
- const zft_position *pos, const zft_volinfo *volume)
-{
- int req_len_left = req_len;
- int result;
- int len_left;
- int buf_pos_write = pos->seg_byte_pos;
- TRACE_FUN(ft_t_flow);
-
- /* Note: we do not unlock the module because
- * there are some values cached in that `cseg' variable. We
- * don't don't want to use this information when being
- * unloaded by kerneld even when the tape is full or when we
- * cannot allocate enough memory.
- */
- if (pos->tape_pos > (volume->size-volume->blk_sz-ZFT_CMPR_OVERHEAD)) {
- TRACE_EXIT -ENOSPC;
- }
- if (zft_allocate_cmpr_mem(volume->blk_sz) < 0) {
- /* should we unlock the module? But it shouldn't
- * be locked anyway ...
- */
- TRACE_EXIT -ENOMEM;
- }
- if (buf_pos_write == 0) { /* fill a new segment */
- *write_cnt = buf_pos_write = start_new_cseg(&cseg,
- dst_buf,
- pos,
- volume->blk_sz,
- zftc_buf,
- seg_sz,
- volume->qic113);
- if (cseg.cmpr_sz == 0 && cseg.cmpr_pos != 0) {
- req_len_left -= result = volume->blk_sz;
- cseg.cmpr_pos = 0;
- } else {
- result = 0;
- }
- } else {
- *write_cnt = result = 0;
- }
-
- len_left = seg_sz - buf_pos_write;
- while ((req_len_left > 0) && (len_left > 18)) {
- /* now we have some size left for a new compressed
- * block. We know, that the compression buffer is
- * empty (else there wouldn't be any space left).
- */
- if (copy_from_user(zftc_scratch_buf, src_buf + result,
- volume->blk_sz) != 0) {
- TRACE_EXIT -EFAULT;
- }
- req_len_left -= volume->blk_sz;
- cseg.cmpr_sz = zft_compress(zftc_scratch_buf, volume->blk_sz,
- zftc_buf);
- if (cseg.cmpr_sz < 0) {
- cseg.uncmpr = 0x8000;
- cseg.cmpr_sz = -cseg.cmpr_sz;
- } else {
- cseg.uncmpr = 0;
- }
- /* increment "result" iff we copied the entire
- * compressed block to the zft_deblock_buf
- */
- len_left -= sizeof(__u16);
- if (len_left >= cseg.cmpr_sz) {
- len_left -= cseg.count = cseg.cmpr_sz;
- cseg.cmpr_pos = cseg.cmpr_sz = 0;
- result += volume->blk_sz;
- } else {
- cseg.cmpr_sz -=
- cseg.cmpr_pos =
- cseg.count = len_left;
- len_left = 0;
- }
- PUT2(dst_buf, buf_pos_write, cseg.uncmpr | cseg.count);
- buf_pos_write += sizeof(__u16);
- memcpy(dst_buf + buf_pos_write, zftc_buf, cseg.count);
- buf_pos_write += cseg.count;
- *write_cnt += cseg.count + sizeof(__u16);
- FT_SIGNAL_EXIT(_DONT_BLOCK);
- }
- /* erase the remainder of the segment if less than 18 bytes
- * left (18 bytes is due to the QIC-80 standard)
- */
- if (len_left <= 18) {
- memset(dst_buf + buf_pos_write, '\0', len_left);
- (*write_cnt) += len_left;
- }
- TRACE(ft_t_data_flow, "returning %d", result);
- TRACE_EXIT result;
-}
-
-/* out:
- *
- * int *read_cnt: the number of bytes we removed from the zft_deblock_buf
- * (result)
- * int *to_do : the remaining size of the read-request.
- *
- * in:
- *
- * char *buff : buff is the address of the upper part of the user
- * buffer, that hasn't been filled with data yet.
-
- * int buf_pos_read : copy of from _ftape_read()
- * int buf_len_read : copy of buf_len_rd from _ftape_read()
- * char *zft_deblock_buf: zft_deblock_buf
- * unsigned short blk_sz: the block size valid for this volume, may differ
- * from zft_blk_sz.
- * int finish: if != 0 means that this is the last segment belonging
- * to this volume
- * returns the amount of data actually copied to the user-buffer
- *
- * to_do MUST NOT SHRINK except to indicate an EOF. In this case *to_do has to
- * be set to 0
- */
-static int zftc_read (int *read_cnt,
- __u8 __user *dst_buf, const int to_do,
- const __u8 *src_buf, const int seg_sz,
- const zft_position *pos, const zft_volinfo *volume)
-{
- int uncompressed_sz;
- int result = 0;
- int remaining = to_do;
- TRACE_FUN(ft_t_flow);
-
- TRACE_CATCH(zft_allocate_cmpr_mem(volume->blk_sz),);
- if (pos->seg_byte_pos == 0) {
- /* new segment just read
- */
- TRACE_CATCH(get_cseg(&cseg, src_buf, seg_sz, volume),
- *read_cnt = 0);
- memcpy(zftc_buf + cseg.cmpr_pos, src_buf + sizeof(__u16),
- cseg.count);
- cseg.cmpr_pos += cseg.count;
- *read_cnt = cseg.offset;
- DUMP_CMPR_INFO(ft_t_noise /* ft_t_any */, "", &cseg);
- } else {
- *read_cnt = 0;
- }
- /* loop and uncompress until user buffer full or
- * deblock-buffer empty
- */
- TRACE(ft_t_data_flow, "compressed_sz: %d, compos : %d, *read_cnt: %d",
- cseg.cmpr_sz, cseg.cmpr_pos, *read_cnt);
- while ((cseg.spans == 0) && (remaining > 0)) {
- if (cseg.cmpr_pos != 0) { /* cmpr buf is not empty */
- uncompressed_sz =
- zft_uncompress(zftc_buf,
- cseg.uncmpr == 0x8000 ?
- -cseg.cmpr_pos : cseg.cmpr_pos,
- zftc_scratch_buf,
- volume->blk_sz);
- if (uncompressed_sz != volume->blk_sz) {
- *read_cnt = 0;
- TRACE_ABORT(-EIO, ft_t_warn,
- "Uncompressed blk (%d) != blk size (%d)",
- uncompressed_sz, volume->blk_sz);
- }
- if (copy_to_user(dst_buf + result,
- zftc_scratch_buf,
- uncompressed_sz) != 0 ) {
- TRACE_EXIT -EFAULT;
- }
- remaining -= uncompressed_sz;
- result += uncompressed_sz;
- cseg.cmpr_pos = 0;
- }
- if (remaining > 0) {
- get_next_cluster(&cseg, src_buf, seg_sz,
- volume->end_seg == pos->seg_pos);
- if (cseg.count != 0) {
- memcpy(zftc_buf, src_buf + cseg.offset,
- cseg.count);
- cseg.cmpr_pos = cseg.count;
- cseg.offset += cseg.count;
- *read_cnt += cseg.count + sizeof(__u16);
- } else {
- remaining = 0;
- }
- }
- TRACE(ft_t_data_flow, "\n"
- KERN_INFO "compressed_sz: %d\n"
- KERN_INFO "compos : %d\n"
- KERN_INFO "*read_cnt : %d",
- cseg.cmpr_sz, cseg.cmpr_pos, *read_cnt);
- }
- if (seg_sz - cseg.offset <= 18) {
- *read_cnt += seg_sz - cseg.offset;
- TRACE(ft_t_data_flow, "expanding read cnt to: %d", *read_cnt);
- }
- TRACE(ft_t_data_flow, "\n"
- KERN_INFO "segment size : %d\n"
- KERN_INFO "read count : %d\n"
- KERN_INFO "buf_pos_read : %d\n"
- KERN_INFO "remaining : %d",
- seg_sz, *read_cnt, pos->seg_byte_pos,
- seg_sz - *read_cnt - pos->seg_byte_pos);
- TRACE(ft_t_data_flow, "returning: %d", result);
- TRACE_EXIT result;
-}
-
-/* seeks to the new data-position. Reads sometimes a segment.
- *
- * start_seg and end_seg give the boundaries of the current volume
- * blk_sz is the blk_sz of the current volume as stored in the
- * volume label
- *
- * We don't allow blocksizes less than 1024 bytes, therefore we don't need
- * a 64 bit argument for new_block_pos.
- */
-
-static int seek_in_segment(const unsigned int to_do, cmpr_info *c_info,
- const char *src_buf, const int seg_sz,
- const int seg_pos, const zft_volinfo *volume);
-static int slow_seek_forward_until_error(const unsigned int distance,
- cmpr_info *c_info, zft_position *pos,
- const zft_volinfo *volume, __u8 *buf);
-static int search_valid_segment(unsigned int segment,
- const unsigned int end_seg,
- const unsigned int max_foffs,
- zft_position *pos, cmpr_info *c_info,
- const zft_volinfo *volume, __u8 *buf);
-static int slow_seek_forward(unsigned int dest, cmpr_info *c_info,
- zft_position *pos, const zft_volinfo *volume,
- __u8 *buf);
-static int compute_seg_pos(unsigned int dest, zft_position *pos,
- const zft_volinfo *volume);
-
-#define ZFT_SLOW_SEEK_THRESHOLD 10 /* segments */
-#define ZFT_FAST_SEEK_MAX_TRIALS 10 /* times */
-#define ZFT_FAST_SEEK_BACKUP 10 /* segments */
-
-static int zftc_seek(unsigned int new_block_pos,
- zft_position *pos, const zft_volinfo *volume, __u8 *buf)
-{
- unsigned int dest;
- int limit;
- int distance;
- int result = 0;
- int seg_dist;
- int new_seg;
- int old_seg = 0;
- int fast_seek_trials = 0;
- TRACE_FUN(ft_t_flow);
-
- if (new_block_pos == 0) {
- pos->seg_pos = volume->start_seg;
- pos->seg_byte_pos = 0;
- pos->volume_pos = 0;
- zftc_reset();
- TRACE_EXIT 0;
- }
- dest = new_block_pos * (volume->blk_sz >> 10);
- distance = dest - (pos->volume_pos >> 10);
- while (distance != 0) {
- seg_dist = compute_seg_pos(dest, pos, volume);
- TRACE(ft_t_noise, "\n"
- KERN_INFO "seg_dist: %d\n"
- KERN_INFO "distance: %d\n"
- KERN_INFO "dest : %d\n"
- KERN_INFO "vpos : %d\n"
- KERN_INFO "seg_pos : %d\n"
- KERN_INFO "trials : %d",
- seg_dist, distance, dest,
- (unsigned int)(pos->volume_pos>>10), pos->seg_pos,
- fast_seek_trials);
- if (distance > 0) {
- if (seg_dist < 0) {
- TRACE(ft_t_bug, "BUG: distance %d > 0, "
- "segment difference %d < 0",
- distance, seg_dist);
- result = -EIO;
- break;
- }
- new_seg = pos->seg_pos + seg_dist;
- if (new_seg > volume->end_seg) {
- new_seg = volume->end_seg;
- }
- if (old_seg == new_seg || /* loop */
- seg_dist <= ZFT_SLOW_SEEK_THRESHOLD ||
- fast_seek_trials >= ZFT_FAST_SEEK_MAX_TRIALS) {
- TRACE(ft_t_noise, "starting slow seek:\n"
- KERN_INFO "fast seek failed too often: %s\n"
- KERN_INFO "near target position : %s\n"
- KERN_INFO "looping between two segs : %s",
- (fast_seek_trials >=
- ZFT_FAST_SEEK_MAX_TRIALS)
- ? "yes" : "no",
- (seg_dist <= ZFT_SLOW_SEEK_THRESHOLD)
- ? "yes" : "no",
- (old_seg == new_seg)
- ? "yes" : "no");
- result = slow_seek_forward(dest, &cseg,
- pos, volume, buf);
- break;
- }
- old_seg = new_seg;
- limit = volume->end_seg;
- fast_seek_trials ++;
- for (;;) {
- result = search_valid_segment(new_seg, limit,
- volume->size,
- pos, &cseg,
- volume, buf);
- if (result == 0 || result == -EINTR) {
- break;
- }
- if (new_seg == volume->start_seg) {
- result = -EIO; /* set errror
- * condition
- */
- break;
- }
- limit = new_seg;
- new_seg -= ZFT_FAST_SEEK_BACKUP;
- if (new_seg < volume->start_seg) {
- new_seg = volume->start_seg;
- }
- }
- if (result < 0) {
- TRACE(ft_t_warn,
- "Couldn't find a readable segment");
- break;
- }
- } else /* if (distance < 0) */ {
- if (seg_dist > 0) {
- TRACE(ft_t_bug, "BUG: distance %d < 0, "
- "segment difference %d >0",
- distance, seg_dist);
- result = -EIO;
- break;
- }
- new_seg = pos->seg_pos + seg_dist;
- if (fast_seek_trials > 0 && seg_dist == 0) {
- /* this avoids sticking to the same
- * segment all the time. On the other hand:
- * if we got here for the first time, and the
- * deblock_buffer still contains a valid
- * segment, then there is no need to skip to
- * the previous segment if the desired position
- * is inside this segment.
- */
- new_seg --;
- }
- if (new_seg < volume->start_seg) {
- new_seg = volume->start_seg;
- }
- limit = pos->seg_pos;
- fast_seek_trials ++;
- for (;;) {
- result = search_valid_segment(new_seg, limit,
- pos->volume_pos,
- pos, &cseg,
- volume, buf);
- if (result == 0 || result == -EINTR) {
- break;
- }
- if (new_seg == volume->start_seg) {
- result = -EIO; /* set errror
- * condition
- */
- break;
- }
- limit = new_seg;
- new_seg -= ZFT_FAST_SEEK_BACKUP;
- if (new_seg < volume->start_seg) {
- new_seg = volume->start_seg;
- }
- }
- if (result < 0) {
- TRACE(ft_t_warn,
- "Couldn't find a readable segment");
- break;
- }
- }
- distance = dest - (pos->volume_pos >> 10);
- }
- TRACE_EXIT result;
-}
-
-
-/* advance inside the given segment at most to_do bytes.
- * of kilobytes moved
- */
-
-static int seek_in_segment(const unsigned int to_do,
- cmpr_info *c_info,
- const char *src_buf,
- const int seg_sz,
- const int seg_pos,
- const zft_volinfo *volume)
-{
- int result = 0;
- int blk_sz = volume->blk_sz >> 10;
- int remaining = to_do;
- TRACE_FUN(ft_t_flow);
-
- if (c_info->offset == 0) {
- /* new segment just read
- */
- TRACE_CATCH(get_cseg(c_info, src_buf, seg_sz, volume),);
- c_info->cmpr_pos += c_info->count;
- DUMP_CMPR_INFO(ft_t_noise, "", c_info);
- }
- /* loop and uncompress until user buffer full or
- * deblock-buffer empty
- */
- TRACE(ft_t_noise, "compressed_sz: %d, compos : %d",
- c_info->cmpr_sz, c_info->cmpr_pos);
- while (c_info->spans == 0 && remaining > 0) {
- if (c_info->cmpr_pos != 0) { /* cmpr buf is not empty */
- result += blk_sz;
- remaining -= blk_sz;
- c_info->cmpr_pos = 0;
- }
- if (remaining > 0) {
- get_next_cluster(c_info, src_buf, seg_sz,
- volume->end_seg == seg_pos);
- if (c_info->count != 0) {
- c_info->cmpr_pos = c_info->count;
- c_info->offset += c_info->count;
- } else {
- break;
- }
- }
- /* Allow escape from this loop on signal!
- */
- FT_SIGNAL_EXIT(_DONT_BLOCK);
- DUMP_CMPR_INFO(ft_t_noise, "", c_info);
- TRACE(ft_t_noise, "to_do: %d", remaining);
- }
- if (seg_sz - c_info->offset <= 18) {
- c_info->offset = seg_sz;
- }
- TRACE(ft_t_noise, "\n"
- KERN_INFO "segment size : %d\n"
- KERN_INFO "buf_pos_read : %d\n"
- KERN_INFO "remaining : %d",
- seg_sz, c_info->offset,
- seg_sz - c_info->offset);
- TRACE_EXIT result;
-}
-
-static int slow_seek_forward_until_error(const unsigned int distance,
- cmpr_info *c_info,
- zft_position *pos,
- const zft_volinfo *volume,
- __u8 *buf)
-{
- unsigned int remaining = distance;
- int seg_sz;
- int seg_pos;
- int result;
- TRACE_FUN(ft_t_flow);
-
- seg_pos = pos->seg_pos;
- do {
- TRACE_CATCH(seg_sz = zft_fetch_segment(seg_pos, buf,
- FT_RD_AHEAD),);
- /* now we have the contents of the actual segment in
- * the deblock buffer
- */
- TRACE_CATCH(result = seek_in_segment(remaining, c_info, buf,
- seg_sz, seg_pos,volume),);
- remaining -= result;
- pos->volume_pos += result<<10;
- pos->seg_pos = seg_pos;
- pos->seg_byte_pos = c_info->offset;
- seg_pos ++;
- if (seg_pos <= volume->end_seg && c_info->offset == seg_sz) {
- pos->seg_pos ++;
- pos->seg_byte_pos = 0;
- c_info->offset = 0;
- }
- /* Allow escape from this loop on signal!
- */
- FT_SIGNAL_EXIT(_DONT_BLOCK);
- TRACE(ft_t_noise, "\n"
- KERN_INFO "remaining: %d\n"
- KERN_INFO "seg_pos: %d\n"
- KERN_INFO "end_seg: %d\n"
- KERN_INFO "result: %d",
- remaining, seg_pos, volume->end_seg, result);
- } while (remaining > 0 && seg_pos <= volume->end_seg);
- TRACE_EXIT 0;
-}
-
-/* return segment id of next segment containing valid data, -EIO otherwise
- */
-static int search_valid_segment(unsigned int segment,
- const unsigned int end_seg,
- const unsigned int max_foffs,
- zft_position *pos,
- cmpr_info *c_info,
- const zft_volinfo *volume,
- __u8 *buf)
-{
- cmpr_info tmp_info;
- int seg_sz;
- TRACE_FUN(ft_t_flow);
-
- memset(&tmp_info, 0, sizeof(cmpr_info));
- while (segment <= end_seg) {
- FT_SIGNAL_EXIT(_DONT_BLOCK);
- TRACE(ft_t_noise,
- "Searching readable segment between %d and %d",
- segment, end_seg);
- seg_sz = zft_fetch_segment(segment, buf, FT_RD_AHEAD);
- if ((seg_sz > 0) &&
- (get_cseg (&tmp_info, buf, seg_sz, volume) >= 0) &&
- (tmp_info.foffs != 0 || segment == volume->start_seg)) {
- if ((tmp_info.foffs>>10) > max_foffs) {
- TRACE_ABORT(-EIO, ft_t_noise, "\n"
- KERN_INFO "cseg.foff: %d\n"
- KERN_INFO "dest : %d",
- (int)(tmp_info.foffs >> 10),
- max_foffs);
- }
- DUMP_CMPR_INFO(ft_t_noise, "", &tmp_info);
- *c_info = tmp_info;
- pos->seg_pos = segment;
- pos->volume_pos = c_info->foffs;
- pos->seg_byte_pos = c_info->offset;
- TRACE(ft_t_noise, "found segment at %d", segment);
- TRACE_EXIT 0;
- }
- segment++;
- }
- TRACE_EXIT -EIO;
-}
-
-static int slow_seek_forward(unsigned int dest,
- cmpr_info *c_info,
- zft_position *pos,
- const zft_volinfo *volume,
- __u8 *buf)
-{
- unsigned int distance;
- int result = 0;
- TRACE_FUN(ft_t_flow);
-
- distance = dest - (pos->volume_pos >> 10);
- while ((distance > 0) &&
- (result = slow_seek_forward_until_error(distance,
- c_info,
- pos,
- volume,
- buf)) < 0) {
- if (result == -EINTR) {
- break;
- }
- TRACE(ft_t_noise, "seg_pos: %d", pos->seg_pos);
- /* the failing segment is either pos->seg_pos or
- * pos->seg_pos + 1. There is no need to further try
- * that segment, because ftape_read_segment() already
- * has tried very much to read it. So we start with
- * following segment, which is pos->seg_pos + 1
- */
- if(search_valid_segment(pos->seg_pos+1, volume->end_seg, dest,
- pos, c_info,
- volume, buf) < 0) {
- TRACE(ft_t_noise, "search_valid_segment() failed");
- result = -EIO;
- break;
- }
- distance = dest - (pos->volume_pos >> 10);
- result = 0;
- TRACE(ft_t_noise, "segment: %d", pos->seg_pos);
- /* found valid segment, retry the seek */
- }
- TRACE_EXIT result;
-}
-
-static int compute_seg_pos(const unsigned int dest,
- zft_position *pos,
- const zft_volinfo *volume)
-{
- int segment;
- int distance = dest - (pos->volume_pos >> 10);
- unsigned int raw_size;
- unsigned int virt_size;
- unsigned int factor;
- TRACE_FUN(ft_t_flow);
-
- if (distance >= 0) {
- raw_size = volume->end_seg - pos->seg_pos + 1;
- virt_size = ((unsigned int)(volume->size>>10)
- - (unsigned int)(pos->volume_pos>>10)
- + FT_SECTORS_PER_SEGMENT - FT_ECC_SECTORS - 1);
- virt_size /= FT_SECTORS_PER_SEGMENT - FT_ECC_SECTORS;
- if (virt_size == 0 || raw_size == 0) {
- TRACE_EXIT 0;
- }
- if (raw_size >= (1<<25)) {
- factor = raw_size/(virt_size>>7);
- } else {
- factor = (raw_size<<7)/virt_size;
- }
- segment = distance/(FT_SECTORS_PER_SEGMENT-FT_ECC_SECTORS);
- segment = (segment * factor)>>7;
- } else {
- raw_size = pos->seg_pos - volume->start_seg + 1;
- virt_size = ((unsigned int)(pos->volume_pos>>10)
- + FT_SECTORS_PER_SEGMENT - FT_ECC_SECTORS - 1);
- virt_size /= FT_SECTORS_PER_SEGMENT - FT_ECC_SECTORS;
- if (virt_size == 0 || raw_size == 0) {
- TRACE_EXIT 0;
- }
- if (raw_size >= (1<<25)) {
- factor = raw_size/(virt_size>>7);
- } else {
- factor = (raw_size<<7)/virt_size;
- }
- segment = distance/(FT_SECTORS_PER_SEGMENT-FT_ECC_SECTORS);
- }
- TRACE(ft_t_noise, "factor: %d/%d", factor, 1<<7);
- TRACE_EXIT segment;
-}
-
-static struct zft_cmpr_ops cmpr_ops = {
- zftc_write,
- zftc_read,
- zftc_seek,
- zftc_lock,
- zftc_reset,
- zftc_cleanup
-};
-
-int zft_compressor_init(void)
-{
- TRACE_FUN(ft_t_flow);
-
-#ifdef MODULE
- printk(KERN_INFO "zftape compressor v1.00a 970514 for " FTAPE_VERSION "\n");
- if (TRACE_LEVEL >= ft_t_info) {
- printk(
-KERN_INFO "(c) 1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de)\n"
-KERN_INFO "Compressor for zftape (lzrw3 algorithm)\n");
- }
-#else /* !MODULE */
- /* print a short no-nonsense boot message */
- printk(KERN_INFO "zftape compressor v1.00a 970514\n");
- printk(KERN_INFO "For use with " FTAPE_VERSION "\n");
-#endif /* MODULE */
- TRACE(ft_t_info, "zft_compressor_init @ 0x%p", zft_compressor_init);
- TRACE(ft_t_info, "installing compressor for zftape ...");
- TRACE_CATCH(zft_cmpr_register(&cmpr_ops),);
- TRACE_EXIT 0;
-}
-
-#ifdef MODULE
-
-MODULE_AUTHOR(
- "(c) 1996, 1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de");
-MODULE_DESCRIPTION(
-"Compression routines for zftape. Uses the lzrw3 algorithm by Ross Williams");
-MODULE_LICENSE("GPL");
-
-/* Called by modules package when installing the driver
- */
-int init_module(void)
-{
- return zft_compressor_init();
-}
-
-#endif /* MODULE */
diff --git a/drivers/char/ftape/compressor/zftape-compress.h b/drivers/char/ftape/compressor/zftape-compress.h
deleted file mode 100644
index f200741e33bf..000000000000
--- a/drivers/char/ftape/compressor/zftape-compress.h
+++ /dev/null
@@ -1,83 +0,0 @@
-#ifndef _ZFTAPE_COMPRESS_H
-#define _ZFTAPE_COMPRESS_H
-/*
- * Copyright (c) 1994-1997 Claus-Justus Heine
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
- USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/compressor/zftape-compress.h,v $
- * $Revision: 1.1 $
- * $Date: 1997/10/05 19:12:32 $
- *
- * This file contains macros and definitions for zftape's
- * builtin compression code.
- *
- */
-
-#include "../zftape/zftape-buffers.h"
-#include "../zftape/zftape-vtbl.h"
-#include "../compressor/lzrw3.h"
-
-/* CMPR_WRK_MEM_SIZE gives the size of the compression wrk_mem */
-/* I got these out of lzrw3.c */
-#define U(X) ((__u32) X)
-#define SIZE_P_BYTE (U(sizeof(__u8 *)))
-#define ALIGNMENT_FUDGE (U(16))
-
-#define CMPR_WRK_MEM_SIZE (U(4096)*(SIZE_P_BYTE) + ALIGNMENT_FUDGE)
-
-/* the maximum number of bytes the size of the "compressed" data can
- * exceed the uncompressed data. As it is quite useless to compress
- * data twice it is sometimes the case that it is more efficient to
- * copy a block of data but to feed it to the "compression"
- * algorithm. In this case there are some flag bytes or the like
- * proceding the "compressed" data. THAT MUST NOT BE THE CASE for the
- * algorithm we use for this driver. Instead, the high bit 15 of
- * compressed_size:
- *
- * compressed_size = ftape_compress()
- *
- * must be set in such a case.
- *
- * Nevertheless, it might also be as for lzrw3 that there is an
- * "intermediate" overrun that exceeds the amount of the compressed
- * data that is actually produced. During the algorithm we need in the
- * worst case MAX_CMP_GROUP bytes more than the input-size.
- */
-#define MAX_CMP_GROUP (2+16*2) /* from lzrw3.c */
-
-#define CMPR_OVERRUN MAX_CMP_GROUP /* during compression */
-
-/****************************************************/
-
-#define CMPR_BUFFER_SIZE (MAX_BLOCK_SIZE + CMPR_OVERRUN)
-
-/* the compression map stores the byte offset compressed blocks within
- * the current volume for catridges with format code 2,3 and 5
- * (and old versions of zftape) and the offset measured in kilobytes for
- * format code 4 and 6. This gives us a possible max. size of a
- * compressed volume of 1024*4GIG which should be enough.
- */
-typedef __u32 CmprMap;
-
-/* globals
- */
-
-/* exported functions
- */
-
-#endif /* _ZFTAPE_COMPRESS_H */
diff --git a/drivers/char/ftape/lowlevel/Makefile b/drivers/char/ftape/lowlevel/Makefile
deleted file mode 100644
index febab07ba427..000000000000
--- a/drivers/char/ftape/lowlevel/Makefile
+++ /dev/null
@@ -1,43 +0,0 @@
-#
-# Copyright (C) 1996, 1997 Clau-Justus Heine.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; see the file COPYING. If not, write to
-# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-# $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/Makefile,v $
-# $Revision: 1.4 $
-# $Date: 1997/10/07 09:26:02 $
-#
-# Makefile for the lowlevel part QIC-40/80/3010/3020 floppy-tape
-# driver for Linux.
-#
-
-obj-$(CONFIG_FTAPE) += ftape.o
-
-ftape-objs := ftape-init.o fdc-io.o fdc-isr.o \
- ftape-bsm.o ftape-ctl.o ftape-read.o ftape-rw.o \
- ftape-write.o ftape-io.o ftape-calibr.o ftape-ecc.o fc-10.o \
- ftape-buffer.o ftape-format.o ftape_syms.o
-
-ifeq ($(CONFIG_FTAPE),y)
-ftape-objs += ftape-setup.o
-endif
-
-ifndef CONFIG_FT_NO_TRACE_AT_ALL
-ftape-objs += ftape-tracing.o
-endif
-
-ifeq ($(CONFIG_FT_PROC_FS),y)
-ftape-objs += ftape-proc.o
-endif
diff --git a/drivers/char/ftape/lowlevel/fc-10.c b/drivers/char/ftape/lowlevel/fc-10.c
deleted file mode 100644
index 9bc1cddade76..000000000000
--- a/drivers/char/ftape/lowlevel/fc-10.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- *
-
- Copyright (C) 1993,1994 Jon Tombs.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- The entire guts of this program was written by dosemu, modified to
- record reads and writes to the ports in the 0x180-0x188 address space,
- while running the CMS program TAPE.EXE V2.0.5 supplied with the drive.
-
- Modified to use an array of addresses and generally cleaned up (made
- much shorter) 4 June 94, dosemu isn't that good at writing short code it
- would seem :-). Made independent of 0x180, but I doubt it will work
- at any other address.
-
- Modified for distribution with ftape source. 21 June 94, SJL.
-
- Modifications on 20 October 95, by Daniel Cohen (catman@wpi.edu):
- Modified to support different DMA, IRQ, and IO Ports. Borland's
- Turbo Debugger in virtual 8086 mode (TD386.EXE with hardware breakpoints
- provided by the TDH386.SYS Device Driver) was used on the CMS program
- TAPE V4.0.5. I set breakpoints on I/O to ports 0x180-0x187. Note that
- CMS's program will not successfully configure the tape drive if you set
- breakpoints on IO Reads, but you can set them on IO Writes without problems.
- Known problems:
- - You can not use DMA Channels 5 or 7.
-
- Modification on 29 January 96, by Daniel Cohen (catman@wpi.edu):
- Modified to only accept IRQs 3 - 7, or 9. Since we can only send a 3 bit
- number representing the IRQ to the card, special handling is required when
- IRQ 9 is selected. IRQ 2 and 9 are the same, and we should request IRQ 9
- from the kernel while telling the card to use IRQ 2. Thanks to Greg
- Crider (gcrider@iclnet.org) for finding and locating this bug, as well as
- testing the patch.
-
- Modification on 11 December 96, by Claus Heine (claus@momo.math.rwth-aachen.de):
- Modified a little to use variahle ft_fdc_base, ft_fdc_irq, ft_fdc_dma
- instead of preprocessor symbols. Thus we can compile this into the module
- or kernel and let the user specify the options as command line arguments.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/fc-10.c,v $
- * $Revision: 1.2 $
- * $Date: 1997/10/05 19:18:04 $
- *
- * This file contains code for the CMS FC-10/FC-20 card.
- */
-
-#include <asm/io.h>
-#include <linux/ftape.h>
-#include "../lowlevel/ftape-tracing.h"
-#include "../lowlevel/fdc-io.h"
-#include "../lowlevel/fc-10.h"
-
-static __u16 inbs_magic[] = {
- 0x3, 0x3, 0x0, 0x4, 0x7, 0x2, 0x5, 0x3, 0x1, 0x4,
- 0x3, 0x5, 0x2, 0x0, 0x3, 0x7, 0x4, 0x2,
- 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7
-};
-
-static __u16 fc10_ports[] = {
- 0x180, 0x210, 0x2A0, 0x300, 0x330, 0x340, 0x370
-};
-
-int fc10_enable(void)
-{
- int i;
- __u8 cardConfig = 0x00;
- __u8 x;
- TRACE_FUN(ft_t_flow);
-
-/* This code will only work if the FC-10 (or FC-20) is set to
- * use DMA channels 1, 2, or 3. DMA channels 5 and 7 seem to be
- * initialized by the same command as channels 1 and 3, respectively.
- */
- if (ft_fdc_dma > 3) {
- TRACE_ABORT(0, ft_t_err,
-"Error: The FC-10/20 must be set to use DMA channels 1, 2, or 3!");
- }
-/* Only allow the FC-10/20 to use IRQ 3-7, or 9. Note that CMS's program
- * only accepts IRQ's 2-7, but in linux, IRQ 2 is the same as IRQ 9.
- */
- if (ft_fdc_irq < 3 || ft_fdc_irq == 8 || ft_fdc_irq > 9) {
- TRACE_ABORT(0, ft_t_err,
-"Error: The FC-10/20 must be set to use IRQ levels 3 - 7, or 9!\n"
-KERN_INFO "Note: IRQ 9 is the same as IRQ 2");
- }
- /* Clear state machine ???
- */
- for (i = 0; i < NR_ITEMS(inbs_magic); i++) {
- inb(ft_fdc_base + inbs_magic[i]);
- }
- outb(0x0, ft_fdc_base);
-
- x = inb(ft_fdc_base);
- if (x == 0x13 || x == 0x93) {
- for (i = 1; i < 8; i++) {
- if (inb(ft_fdc_base + i) != x) {
- TRACE_EXIT 0;
- }
- }
- } else {
- TRACE_EXIT 0;
- }
-
- outb(0x8, ft_fdc_base);
-
- for (i = 0; i < 8; i++) {
- if (inb(ft_fdc_base + i) != 0x0) {
- TRACE_EXIT 0;
- }
- }
- outb(0x10, ft_fdc_base);
-
- for (i = 0; i < 8; i++) {
- if (inb(ft_fdc_base + i) != 0xff) {
- TRACE_EXIT 0;
- }
- }
-
- /* Okay, we found a FC-10 card ! ???
- */
- outb(0x0, fdc.ccr);
-
- /* Clear state machine again ???
- */
- for (i = 0; i < NR_ITEMS(inbs_magic); i++) {
- inb(ft_fdc_base + inbs_magic[i]);
- }
- /* Send io port */
- for (i = 0; i < NR_ITEMS(fc10_ports); i++)
- if (ft_fdc_base == fc10_ports[i])
- cardConfig = i + 1;
- if (cardConfig == 0) {
- TRACE_EXIT 0; /* Invalid I/O Port */
- }
- /* and IRQ - If using IRQ 9, tell the FC card it is actually IRQ 2 */
- if (ft_fdc_irq != 9)
- cardConfig |= ft_fdc_irq << 3;
- else
- cardConfig |= 2 << 3;
-
- /* and finally DMA Channel */
- cardConfig |= ft_fdc_dma << 6;
- outb(cardConfig, ft_fdc_base); /* DMA [2 bits]/IRQ [3 bits]/BASE [3 bits] */
-
- /* Enable FC-10 ???
- */
- outb(0, fdc.ccr);
- outb(0, fdc.dor2);
- outb(FDC_DMA_MODE /* 8 */, fdc.dor);
- outb(FDC_DMA_MODE /* 8 */, fdc.dor);
- outb(1, fdc.dor2);
-
- /*************************************
- *
- * cH: why the hell should this be necessary? This is done
- * by fdc_reset()!!!
- *
- *************************************/
- /* Initialize fdc, select drive B:
- */
- outb(FDC_DMA_MODE, fdc.dor); /* assert reset, dma & irq enabled */
- /* 0x08 */
- outb(FDC_DMA_MODE|FDC_RESET_NOT, fdc.dor); /* release reset */
- /* 0x08 | 0x04 = 0x0c */
- outb(FDC_DMA_MODE|FDC_RESET_NOT|FDC_MOTOR_1|FTAPE_SEL_B, fdc.dor);
- /* 0x08 | 0x04 | 0x20 | 0x01 = 0x2d */
- /* select drive 1 */ /* why not drive 0 ???? */
- TRACE_EXIT (x == 0x93) ? 2 : 1;
-}
diff --git a/drivers/char/ftape/lowlevel/fc-10.h b/drivers/char/ftape/lowlevel/fc-10.h
deleted file mode 100644
index da7b88bca889..000000000000
--- a/drivers/char/ftape/lowlevel/fc-10.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef _FC_10_H
-#define _FC_10_H
-
-/*
- * Copyright (C) 1994-1996 Bas Laarhoven.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/fc-10.h,v $
- * $Revision: 1.1 $
- * $Date: 1997/09/19 09:05:22 $
- *
- * This file contains definitions for the FC-10 code
- * of the QIC-40/80 floppy-tape driver for Linux.
- */
-
-/*
- * fc-10.c defined global vars.
- */
-
-/*
- * fc-10.c defined global functions.
- */
-extern int fc10_enable(void);
-
-#endif
diff --git a/drivers/char/ftape/lowlevel/fdc-io.c b/drivers/char/ftape/lowlevel/fdc-io.c
deleted file mode 100644
index bbcf918f056f..000000000000
--- a/drivers/char/ftape/lowlevel/fdc-io.c
+++ /dev/null
@@ -1,1349 +0,0 @@
-/*
- * Copyright (C) 1993-1996 Bas Laarhoven,
- * (C) 1996-1997 Claus-Justus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/fdc-io.c,v $
- * $Revision: 1.7.4.2 $
- * $Date: 1997/11/16 14:48:17 $
- *
- * This file contains the low-level floppy disk interface code
- * for the QIC-40/80/3010/3020 floppy-tape driver "ftape" for
- * Linux.
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/irq.h>
-
-#include <linux/ftape.h>
-#include <linux/qic117.h>
-#include "../lowlevel/ftape-tracing.h"
-#include "../lowlevel/fdc-io.h"
-#include "../lowlevel/fdc-isr.h"
-#include "../lowlevel/ftape-io.h"
-#include "../lowlevel/ftape-rw.h"
-#include "../lowlevel/ftape-ctl.h"
-#include "../lowlevel/ftape-calibr.h"
-#include "../lowlevel/fc-10.h"
-
-/* Global vars.
- */
-static int ftape_motor;
-volatile int ftape_current_cylinder = -1;
-volatile fdc_mode_enum fdc_mode = fdc_idle;
-fdc_config_info fdc;
-DECLARE_WAIT_QUEUE_HEAD(ftape_wait_intr);
-
-unsigned int ft_fdc_base = CONFIG_FT_FDC_BASE;
-unsigned int ft_fdc_irq = CONFIG_FT_FDC_IRQ;
-unsigned int ft_fdc_dma = CONFIG_FT_FDC_DMA;
-unsigned int ft_fdc_threshold = CONFIG_FT_FDC_THR; /* bytes */
-unsigned int ft_fdc_rate_limit = CONFIG_FT_FDC_MAX_RATE; /* bits/sec */
-int ft_probe_fc10 = CONFIG_FT_PROBE_FC10;
-int ft_mach2 = CONFIG_FT_MACH2;
-
-/* Local vars.
- */
-static spinlock_t fdc_io_lock;
-static unsigned int fdc_calibr_count;
-static unsigned int fdc_calibr_time;
-static int fdc_status;
-volatile __u8 fdc_head; /* FDC head from sector id */
-volatile __u8 fdc_cyl; /* FDC track from sector id */
-volatile __u8 fdc_sect; /* FDC sector from sector id */
-static int fdc_data_rate = 500; /* data rate (Kbps) */
-static int fdc_rate_code; /* data rate code (0 == 500 Kbps) */
-static int fdc_seek_rate = 2; /* step rate (msec) */
-static void (*do_ftape) (void);
-static int fdc_fifo_state; /* original fifo setting - fifo enabled */
-static int fdc_fifo_thr; /* original fifo setting - threshold */
-static int fdc_lock_state; /* original lock setting - locked */
-static int fdc_fifo_locked; /* has fifo && lock set ? */
-static __u8 fdc_precomp; /* default precomp. value (nsec) */
-static __u8 fdc_prec_code; /* fdc precomp. select code */
-
-static char ftape_id[] = "ftape"; /* used by request irq and free irq */
-
-static int fdc_set_seek_rate(int seek_rate);
-
-void fdc_catch_stray_interrupts(int count)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&fdc_io_lock, flags);
- if (count == 0) {
- ft_expected_stray_interrupts = 0;
- } else {
- ft_expected_stray_interrupts += count;
- }
- spin_unlock_irqrestore(&fdc_io_lock, flags);
-}
-
-/* Wait during a timeout period for a given FDC status.
- * If usecs == 0 then just test status, else wait at least for usecs.
- * Returns -ETIME on timeout. Function must be calibrated first !
- */
-static int fdc_wait(unsigned int usecs, __u8 mask, __u8 state)
-{
- int count_1 = (fdc_calibr_count * usecs +
- fdc_calibr_count - 1) / fdc_calibr_time;
-
- do {
- fdc_status = inb_p(fdc.msr);
- if ((fdc_status & mask) == state) {
- return 0;
- }
- } while (count_1-- >= 0);
- return -ETIME;
-}
-
-int fdc_ready_wait(unsigned int usecs)
-{
- return fdc_wait(usecs, FDC_DATA_READY | FDC_BUSY, FDC_DATA_READY);
-}
-
-/* Why can't we just use udelay()?
- */
-static void fdc_usec_wait(unsigned int usecs)
-{
- fdc_wait(usecs, 0, 1); /* will always timeout ! */
-}
-
-static int fdc_ready_out_wait(unsigned int usecs)
-{
- fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */
- return fdc_wait(usecs, FDC_DATA_OUT_READY, FDC_DATA_OUT_READY);
-}
-
-void fdc_wait_calibrate(void)
-{
- ftape_calibrate("fdc_wait",
- fdc_usec_wait, &fdc_calibr_count, &fdc_calibr_time);
-}
-
-/* Wait for a (short) while for the FDC to become ready
- * and transfer the next command byte.
- * Return -ETIME on timeout on getting ready (depends on hardware!).
- */
-static int fdc_write(const __u8 data)
-{
- fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */
- if (fdc_wait(150, FDC_DATA_READY_MASK, FDC_DATA_IN_READY) < 0) {
- return -ETIME;
- } else {
- outb(data, fdc.fifo);
- return 0;
- }
-}
-
-/* Wait for a (short) while for the FDC to become ready
- * and transfer the next result byte.
- * Return -ETIME if timeout on getting ready (depends on hardware!).
- */
-static int fdc_read(__u8 * data)
-{
- fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */
- if (fdc_wait(150, FDC_DATA_READY_MASK, FDC_DATA_OUT_READY) < 0) {
- return -ETIME;
- } else {
- *data = inb(fdc.fifo);
- return 0;
- }
-}
-
-/* Output a cmd_len long command string to the FDC.
- * The FDC should be ready to receive a new command or
- * an error (EBUSY or ETIME) will occur.
- */
-int fdc_command(const __u8 * cmd_data, int cmd_len)
-{
- int result = 0;
- unsigned long flags;
- int count = cmd_len;
- int retry = 0;
-#ifdef TESTING
- static unsigned int last_time;
- unsigned int time;
-#endif
- TRACE_FUN(ft_t_any);
-
- fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */
- spin_lock_irqsave(&fdc_io_lock, flags);
- if (!in_interrupt())
- /* Yes, I know, too much comments inside this function
- * ...
- *
- * Yet another bug in the original driver. All that
- * havoc is caused by the fact that the isr() sends
- * itself a command to the floppy tape driver (pause,
- * micro step pause). Now, the problem is that
- * commands are transmitted via the fdc_seek
- * command. But: the fdc performs seeks in the
- * background i.e. it doesn't signal busy while
- * sending the step pulses to the drive. Therefore the
- * non-interrupt level driver has no chance to tell
- * whether the isr() just has issued a seek. Therefore
- * we HAVE TO have a look at the ft_hide_interrupt
- * flag: it signals the non-interrupt level part of
- * the driver that it has to wait for the fdc until it
- * has completet seeking.
- *
- * THIS WAS PRESUMABLY THE REASON FOR ALL THAT
- * "fdc_read timeout" errors, I HOPE :-)
- */
- if (ft_hide_interrupt) {
- restore_flags(flags);
- TRACE(ft_t_info,
- "Waiting for the isr() completing fdc_seek()");
- if (fdc_interrupt_wait(2 * FT_SECOND) < 0) {
- TRACE(ft_t_warn,
- "Warning: timeout waiting for isr() seek to complete");
- }
- if (ft_hide_interrupt || !ft_seek_completed) {
- /* There cannot be another
- * interrupt. The isr() only stops
- * the tape and the next interrupt
- * won't come until we have send our
- * command to the drive.
- */
- TRACE_ABORT(-EIO, ft_t_bug,
- "BUG? isr() is still seeking?\n"
- KERN_INFO "hide: %d\n"
- KERN_INFO "seek: %d",
- ft_hide_interrupt,
- ft_seek_completed);
-
- }
- fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */
- spin_lock_irqsave(&fdc_io_lock, flags);
- }
- fdc_status = inb(fdc.msr);
- if ((fdc_status & FDC_DATA_READY_MASK) != FDC_DATA_IN_READY) {
- spin_unlock_irqrestore(&fdc_io_lock, flags);
- TRACE_ABORT(-EBUSY, ft_t_err, "fdc not ready");
- }
- fdc_mode = *cmd_data; /* used by isr */
-#ifdef TESTING
- if (fdc_mode == FDC_SEEK) {
- time = ftape_timediff(last_time, ftape_timestamp());
- if (time < 6000) {
- TRACE(ft_t_bug,"Warning: short timeout between seek commands: %d",
- time);
- }
- }
-#endif
- if (!in_interrupt()) {
- /* shouldn't be cleared if called from isr
- */
- ft_interrupt_seen = 0;
- }
- while (count) {
- result = fdc_write(*cmd_data);
- if (result < 0) {
- TRACE(ft_t_fdc_dma,
- "fdc_mode = %02x, status = %02x at index %d",
- (int) fdc_mode, (int) fdc_status,
- cmd_len - count);
- if (++retry <= 3) {
- TRACE(ft_t_warn, "fdc_write timeout, retry");
- } else {
- TRACE(ft_t_err, "fdc_write timeout, fatal");
- /* recover ??? */
- break;
- }
- } else {
- --count;
- ++cmd_data;
- }
- }
-#ifdef TESTING
- if (fdc_mode == FDC_SEEK) {
- last_time = ftape_timestamp();
- }
-#endif
- spin_unlock_irqrestore(&fdc_io_lock, flags);
- TRACE_EXIT result;
-}
-
-/* Input a res_len long result string from the FDC.
- * The FDC should be ready to send the result or an error
- * (EBUSY or ETIME) will occur.
- */
-int fdc_result(__u8 * res_data, int res_len)
-{
- int result = 0;
- unsigned long flags;
- int count = res_len;
- int retry = 0;
- TRACE_FUN(ft_t_any);
-
- spin_lock_irqsave(&fdc_io_lock, flags);
- fdc_status = inb(fdc.msr);
- if ((fdc_status & FDC_DATA_READY_MASK) != FDC_DATA_OUT_READY) {
- TRACE(ft_t_err, "fdc not ready");
- result = -EBUSY;
- } else while (count) {
- if (!(fdc_status & FDC_BUSY)) {
- spin_unlock_irqrestore(&fdc_io_lock, flags);
- TRACE_ABORT(-EIO, ft_t_err, "premature end of result phase");
- }
- result = fdc_read(res_data);
- if (result < 0) {
- TRACE(ft_t_fdc_dma,
- "fdc_mode = %02x, status = %02x at index %d",
- (int) fdc_mode,
- (int) fdc_status,
- res_len - count);
- if (++retry <= 3) {
- TRACE(ft_t_warn, "fdc_read timeout, retry");
- } else {
- TRACE(ft_t_err, "fdc_read timeout, fatal");
- /* recover ??? */
- break;
- ++retry;
- }
- } else {
- --count;
- ++res_data;
- }
- }
- spin_unlock_irqrestore(&fdc_io_lock, flags);
- fdc_usec_wait(FT_RQM_DELAY); /* allow FDC to negate BSY */
- TRACE_EXIT result;
-}
-
-/* Handle command and result phases for
- * commands without data phase.
- */
-static int fdc_issue_command(const __u8 * out_data, int out_count,
- __u8 * in_data, int in_count)
-{
- TRACE_FUN(ft_t_any);
-
- if (out_count > 0) {
- TRACE_CATCH(fdc_command(out_data, out_count),);
- }
- /* will take 24 - 30 usec for fdc_sense_drive_status and
- * fdc_sense_interrupt_status commands.
- * 35 fails sometimes (5/9/93 SJL)
- * On a loaded system it incidentally takes longer than
- * this for the fdc to get ready ! ?????? WHY ??????
- * So until we know what's going on use a very long timeout.
- */
- TRACE_CATCH(fdc_ready_out_wait(500 /* usec */),);
- if (in_count > 0) {
- TRACE_CATCH(fdc_result(in_data, in_count),
- TRACE(ft_t_err, "result phase aborted"));
- }
- TRACE_EXIT 0;
-}
-
-/* Wait for FDC interrupt with timeout (in milliseconds).
- * Signals are blocked so the wait will not be aborted.
- * Note: interrupts must be enabled ! (23/05/93 SJL)
- */
-int fdc_interrupt_wait(unsigned int time)
-{
- DECLARE_WAITQUEUE(wait,current);
- sigset_t old_sigmask;
- static int resetting;
- long timeout;
-
- TRACE_FUN(ft_t_fdc_dma);
-
- if (waitqueue_active(&ftape_wait_intr)) {
- TRACE_ABORT(-EIO, ft_t_err, "error: nested call");
- }
- /* timeout time will be up to USPT microseconds too long ! */
- timeout = (1000 * time + FT_USPT - 1) / FT_USPT;
-
- spin_lock_irq(&current->sighand->siglock);
- old_sigmask = current->blocked;
- sigfillset(&current->blocked);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
-
- set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&ftape_wait_intr, &wait);
- while (!ft_interrupt_seen && timeout)
- timeout = schedule_timeout_interruptible(timeout);
-
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = old_sigmask;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
-
- remove_wait_queue(&ftape_wait_intr, &wait);
- /* the following IS necessary. True: as well
- * wake_up_interruptible() as the schedule() set TASK_RUNNING
- * when they wakeup a task, BUT: it may very well be that
- * ft_interrupt_seen is already set to 1 when we enter here
- * in which case schedule() gets never called, and
- * TASK_RUNNING never set. This has the funny effect that we
- * execute all the code until we leave kernel space, but then
- * the task is stopped (a task CANNOT be preempted while in
- * kernel mode. Sending a pair of SIGSTOP/SIGCONT to the
- * tasks wakes it up again. Funny! :-)
- */
- current->state = TASK_RUNNING;
- if (ft_interrupt_seen) { /* woken up by interrupt */
- ft_interrupt_seen = 0;
- TRACE_EXIT 0;
- }
- /* Original comment:
- * In first instance, next statement seems unnecessary since
- * it will be cleared in fdc_command. However, a small part of
- * the software seems to rely on this being cleared here
- * (ftape_close might fail) so stick to it until things get fixed !
- */
- /* My deeply sought of knowledge:
- * Behold NO! It is obvious. fdc_reset() doesn't call fdc_command()
- * but nevertheless uses fdc_interrupt_wait(). OF COURSE this needs to
- * be reset here.
- */
- ft_interrupt_seen = 0; /* clear for next call */
- if (!resetting) {
- resetting = 1; /* break infinite recursion if reset fails */
- TRACE(ft_t_any, "cleanup reset");
- fdc_reset();
- resetting = 0;
- }
- TRACE_EXIT (signal_pending(current)) ? -EINTR : -ETIME;
-}
-
-/* Start/stop drive motor. Enable DMA mode.
- */
-void fdc_motor(int motor)
-{
- int unit = ft_drive_sel;
- int data = unit | FDC_RESET_NOT | FDC_DMA_MODE;
- TRACE_FUN(ft_t_any);
-
- ftape_motor = motor;
- if (ftape_motor) {
- data |= FDC_MOTOR_0 << unit;
- TRACE(ft_t_noise, "turning motor %d on", unit);
- } else {
- TRACE(ft_t_noise, "turning motor %d off", unit);
- }
- if (ft_mach2) {
- outb_p(data, fdc.dor2);
- } else {
- outb_p(data, fdc.dor);
- }
- ftape_sleep(10 * FT_MILLISECOND);
- TRACE_EXIT;
-}
-
-static void fdc_update_dsr(void)
-{
- TRACE_FUN(ft_t_any);
-
- TRACE(ft_t_flow, "rate = %d Kbps, precomp = %d ns",
- fdc_data_rate, fdc_precomp);
- if (fdc.type >= i82077) {
- outb_p((fdc_rate_code & 0x03) | fdc_prec_code, fdc.dsr);
- } else {
- outb_p(fdc_rate_code & 0x03, fdc.ccr);
- }
- TRACE_EXIT;
-}
-
-void fdc_set_write_precomp(int precomp)
-{
- TRACE_FUN(ft_t_any);
-
- TRACE(ft_t_noise, "New precomp: %d nsec", precomp);
- fdc_precomp = precomp;
- /* write precompensation can be set in multiples of 41.67 nsec.
- * round the parameter to the nearest multiple and convert it
- * into a fdc setting. Note that 0 means default to the fdc,
- * 7 is used instead of that.
- */
- fdc_prec_code = ((fdc_precomp + 21) / 42) << 2;
- if (fdc_prec_code == 0 || fdc_prec_code > (6 << 2)) {
- fdc_prec_code = 7 << 2;
- }
- fdc_update_dsr();
- TRACE_EXIT;
-}
-
-/* Reprogram the 82078 registers to use Data Rate Table 1 on all drives.
- */
-static void fdc_set_drive_specs(void)
-{
- __u8 cmd[] = { FDC_DRIVE_SPEC, 0x00, 0x00, 0x00, 0x00, 0xc0};
- int result;
- TRACE_FUN(ft_t_any);
-
- TRACE(ft_t_flow, "Setting of drive specs called");
- if (fdc.type >= i82078_1) {
- cmd[1] = (0 << 5) | (2 << 2);
- cmd[2] = (1 << 5) | (2 << 2);
- cmd[3] = (2 << 5) | (2 << 2);
- cmd[4] = (3 << 5) | (2 << 2);
- result = fdc_command(cmd, NR_ITEMS(cmd));
- if (result < 0) {
- TRACE(ft_t_err, "Setting of drive specs failed");
- }
- }
- TRACE_EXIT;
-}
-
-/* Select clock for fdc, must correspond with tape drive setting !
- * This also influences the fdc timing so we must adjust some values.
- */
-int fdc_set_data_rate(int rate)
-{
- int bad_rate = 0;
- TRACE_FUN(ft_t_any);
-
- /* Select clock for fdc, must correspond with tape drive setting !
- * This also influences the fdc timing so we must adjust some values.
- */
- TRACE(ft_t_fdc_dma, "new rate = %d", rate);
- switch (rate) {
- case 250:
- fdc_rate_code = fdc_data_rate_250;
- break;
- case 500:
- fdc_rate_code = fdc_data_rate_500;
- break;
- case 1000:
- if (fdc.type < i82077) {
- bad_rate = 1;
- } else {
- fdc_rate_code = fdc_data_rate_1000;
- }
- break;
- case 2000:
- if (fdc.type < i82078_1) {
- bad_rate = 1;
- } else {
- fdc_rate_code = fdc_data_rate_2000;
- }
- break;
- default:
- bad_rate = 1;
- }
- if (bad_rate) {
- TRACE_ABORT(-EIO,
- ft_t_fdc_dma, "%d is not a valid data rate", rate);
- }
- fdc_data_rate = rate;
- fdc_update_dsr();
- fdc_set_seek_rate(fdc_seek_rate); /* clock changed! */
- ftape_udelay(1000);
- TRACE_EXIT 0;
-}
-
-/* keep the unit select if keep_select is != 0,
- */
-static void fdc_dor_reset(int keep_select)
-{
- __u8 fdc_ctl = ft_drive_sel;
-
- if (keep_select != 0) {
- fdc_ctl |= FDC_DMA_MODE;
- if (ftape_motor) {
- fdc_ctl |= FDC_MOTOR_0 << ft_drive_sel;
- }
- }
- ftape_udelay(10); /* ??? but seems to be necessary */
- if (ft_mach2) {
- outb_p(fdc_ctl & 0x0f, fdc.dor);
- outb_p(fdc_ctl, fdc.dor2);
- } else {
- outb_p(fdc_ctl, fdc.dor);
- }
- fdc_usec_wait(10); /* delay >= 14 fdc clocks */
- if (keep_select == 0) {
- fdc_ctl = 0;
- }
- fdc_ctl |= FDC_RESET_NOT;
- if (ft_mach2) {
- outb_p(fdc_ctl & 0x0f, fdc.dor);
- outb_p(fdc_ctl, fdc.dor2);
- } else {
- outb_p(fdc_ctl, fdc.dor);
- }
-}
-
-/* Reset the floppy disk controller. Leave the ftape_unit selected.
- */
-void fdc_reset(void)
-{
- int st0;
- int i;
- int dummy;
- unsigned long flags;
- TRACE_FUN(ft_t_any);
-
- spin_lock_irqsave(&fdc_io_lock, flags);
-
- fdc_dor_reset(1); /* keep unit selected */
-
- fdc_mode = fdc_idle;
-
- /* maybe the spin_lock_irq* pair is not necessary, BUT:
- * the following line MUST be here. Otherwise fdc_interrupt_wait()
- * won't wait. Note that fdc_reset() is called from
- * ftape_dumb_stop() when the fdc is busy transferring data. In this
- * case fdc_isr() MOST PROBABLY sets ft_interrupt_seen, and tries
- * to get the result bytes from the fdc etc. CLASH.
- */
- ft_interrupt_seen = 0;
-
- /* Program data rate
- */
- fdc_update_dsr(); /* restore data rate and precomp */
-
- spin_unlock_irqrestore(&fdc_io_lock, flags);
-
- /*
- * Wait for first polling cycle to complete
- */
- if (fdc_interrupt_wait(1 * FT_SECOND) < 0) {
- TRACE(ft_t_err, "no drive polling interrupt!");
- } else { /* clear all disk-changed statuses */
- for (i = 0; i < 4; ++i) {
- if(fdc_sense_interrupt_status(&st0, &dummy) != 0) {
- TRACE(ft_t_err, "sense failed for %d", i);
- }
- if (i == ft_drive_sel) {
- ftape_current_cylinder = dummy;
- }
- }
- TRACE(ft_t_noise, "drive polling completed");
- }
- /*
- * SPECIFY COMMAND
- */
- fdc_set_seek_rate(fdc_seek_rate);
- /*
- * DRIVE SPECIFICATION COMMAND (if fdc type known)
- */
- if (fdc.type >= i82078_1) {
- fdc_set_drive_specs();
- }
- TRACE_EXIT;
-}
-
-#if !defined(CLK_48MHZ)
-# define CLK_48MHZ 1
-#endif
-
-/* When we're done, put the fdc into reset mode so that the regular
- * floppy disk driver will figure out that something is wrong and
- * initialize the controller the way it wants.
- */
-void fdc_disable(void)
-{
- __u8 cmd1[] = {FDC_CONFIGURE, 0x00, 0x00, 0x00};
- __u8 cmd2[] = {FDC_LOCK};
- __u8 cmd3[] = {FDC_UNLOCK};
- __u8 stat[1];
- TRACE_FUN(ft_t_flow);
-
- if (!fdc_fifo_locked) {
- fdc_reset();
- TRACE_EXIT;
- }
- if (fdc_issue_command(cmd3, 1, stat, 1) < 0 || stat[0] != 0x00) {
- fdc_dor_reset(0);
- TRACE_ABORT(/**/, ft_t_bug,
- "couldn't unlock fifo, configuration remains changed");
- }
- fdc_fifo_locked = 0;
- if (CLK_48MHZ && fdc.type >= i82078) {
- cmd1[0] |= FDC_CLK48_BIT;
- }
- cmd1[2] = ((fdc_fifo_state) ? 0 : 0x20) + (fdc_fifo_thr - 1);
- if (fdc_command(cmd1, NR_ITEMS(cmd1)) < 0) {
- fdc_dor_reset(0);
- TRACE_ABORT(/**/, ft_t_bug,
- "couldn't reconfigure fifo to old state");
- }
- if (fdc_lock_state &&
- fdc_issue_command(cmd2, 1, stat, 1) < 0) {
- fdc_dor_reset(0);
- TRACE_ABORT(/**/, ft_t_bug, "couldn't lock old state again");
- }
- TRACE(ft_t_noise, "fifo restored: %sabled, thr. %d, %slocked",
- fdc_fifo_state ? "en" : "dis",
- fdc_fifo_thr, (fdc_lock_state) ? "" : "not ");
- fdc_dor_reset(0);
- TRACE_EXIT;
-}
-
-/* Specify FDC seek-rate (milliseconds)
- */
-static int fdc_set_seek_rate(int seek_rate)
-{
- /* set step rate, dma mode, and minimal head load and unload times
- */
- __u8 in[3] = { FDC_SPECIFY, 1, (1 << 1)};
-
- fdc_seek_rate = seek_rate;
- in[1] |= (16 - (fdc_data_rate * fdc_seek_rate) / 500) << 4;
-
- return fdc_command(in, 3);
-}
-
-/* Sense drive status: get unit's drive status (ST3)
- */
-int fdc_sense_drive_status(int *st3)
-{
- __u8 out[2];
- __u8 in[1];
- TRACE_FUN(ft_t_any);
-
- out[0] = FDC_SENSED;
- out[1] = ft_drive_sel;
- TRACE_CATCH(fdc_issue_command(out, 2, in, 1),);
- *st3 = in[0];
- TRACE_EXIT 0;
-}
-
-/* Sense Interrupt Status command:
- * should be issued at the end of each seek.
- * get ST0 and current cylinder.
- */
-int fdc_sense_interrupt_status(int *st0, int *current_cylinder)
-{
- __u8 out[1];
- __u8 in[2];
- TRACE_FUN(ft_t_any);
-
- out[0] = FDC_SENSEI;
- TRACE_CATCH(fdc_issue_command(out, 1, in, 2),);
- *st0 = in[0];
- *current_cylinder = in[1];
- TRACE_EXIT 0;
-}
-
-/* step to track
- */
-int fdc_seek(int track)
-{
- __u8 out[3];
- int st0, pcn;
-#ifdef TESTING
- unsigned int time;
-#endif
- TRACE_FUN(ft_t_any);
-
- out[0] = FDC_SEEK;
- out[1] = ft_drive_sel;
- out[2] = track;
-#ifdef TESTING
- time = ftape_timestamp();
-#endif
- /* We really need this command to work !
- */
- ft_seek_completed = 0;
- TRACE_CATCH(fdc_command(out, 3),
- fdc_reset();
- TRACE(ft_t_noise, "destination was: %d, resetting FDC...",
- track));
- /* Handle interrupts until ft_seek_completed or timeout.
- */
- for (;;) {
- TRACE_CATCH(fdc_interrupt_wait(2 * FT_SECOND),);
- if (ft_seek_completed) {
- TRACE_CATCH(fdc_sense_interrupt_status(&st0, &pcn),);
- if ((st0 & ST0_SEEK_END) == 0) {
- TRACE_ABORT(-EIO, ft_t_err,
- "no seek-end after seek completion !??");
- }
- break;
- }
- }
-#ifdef TESTING
- time = ftape_timediff(time, ftape_timestamp()) / abs(track - ftape_current_cylinder);
- if ((time < 900 || time > 3100) && abs(track - ftape_current_cylinder) > 5) {
- TRACE(ft_t_warn, "Wrong FDC STEP interval: %d usecs (%d)",
- time, track - ftape_current_cylinder);
- }
-#endif
- /* Verify whether we issued the right tape command.
- */
- /* Verify that we seek to the proper track. */
- if (pcn != track) {
- TRACE_ABORT(-EIO, ft_t_err, "bad seek..");
- }
- ftape_current_cylinder = track;
- TRACE_EXIT 0;
-}
-
-static int perpend_mode; /* set if fdc is in perpendicular mode */
-
-static int perpend_off(void)
-{
- __u8 perpend[] = {FDC_PERPEND, 0x00};
- TRACE_FUN(ft_t_any);
-
- if (perpend_mode) {
- /* Turn off perpendicular mode */
- perpend[1] = 0x80;
- TRACE_CATCH(fdc_command(perpend, 2),
- TRACE(ft_t_err,"Perpendicular mode exit failed!"));
- perpend_mode = 0;
- }
- TRACE_EXIT 0;
-}
-
-static int handle_perpend(int segment_id)
-{
- __u8 perpend[] = {FDC_PERPEND, 0x00};
- TRACE_FUN(ft_t_any);
-
- /* When writing QIC-3020 tapes, turn on perpendicular mode
- * if tape is moving in forward direction (even tracks).
- */
- if (ft_qic_std == QIC_TAPE_QIC3020 &&
- ((segment_id / ft_segments_per_track) & 1) == 0) {
-/* FIXME: some i82077 seem to support perpendicular mode as
- * well.
- */
-#if 0
- if (fdc.type < i82077AA) {}
-#else
- if (fdc.type < i82077 && ft_data_rate < 1000) {
-#endif
- /* fdc does not support perpendicular mode: complain
- */
- TRACE_ABORT(-EIO, ft_t_err,
- "Your FDC does not support QIC-3020.");
- }
- perpend[1] = 0x03 /* 0x83 + (0x4 << ft_drive_sel) */ ;
- TRACE_CATCH(fdc_command(perpend, 2),
- TRACE(ft_t_err,"Perpendicular mode entry failed!"));
- TRACE(ft_t_flow, "Perpendicular mode set");
- perpend_mode = 1;
- TRACE_EXIT 0;
- }
- TRACE_EXIT perpend_off();
-}
-
-static inline void fdc_setup_dma(char mode,
- volatile void *addr, unsigned int count)
-{
- /* Program the DMA controller.
- */
- disable_dma(fdc.dma);
- clear_dma_ff(fdc.dma);
- set_dma_mode(fdc.dma, mode);
- set_dma_addr(fdc.dma, virt_to_bus((void*)addr));
- set_dma_count(fdc.dma, count);
- enable_dma(fdc.dma);
-}
-
-/* Setup fdc and dma for formatting the next segment
- */
-int fdc_setup_formatting(buffer_struct * buff)
-{
- unsigned long flags;
- __u8 out[6] = {
- FDC_FORMAT, 0x00, 3, 4 * FT_SECTORS_PER_SEGMENT, 0x00, 0x6b
- };
- TRACE_FUN(ft_t_any);
-
- TRACE_CATCH(handle_perpend(buff->segment_id),);
- /* Program the DMA controller.
- */
- TRACE(ft_t_fdc_dma,
- "phys. addr. = %lx", virt_to_bus((void*) buff->ptr));
- spin_lock_irqsave(&fdc_io_lock, flags);
- fdc_setup_dma(DMA_MODE_WRITE, buff->ptr, FT_SECTORS_PER_SEGMENT * 4);
- /* Issue FDC command to start reading/writing.
- */
- out[1] = ft_drive_sel;
- out[4] = buff->gap3;
- TRACE_CATCH(fdc_setup_error = fdc_command(out, sizeof(out)),
- restore_flags(flags); fdc_mode = fdc_idle);
- spin_unlock_irqrestore(&fdc_io_lock, flags);
- TRACE_EXIT 0;
-}
-
-
-/* Setup Floppy Disk Controller and DMA to read or write the next cluster
- * of good sectors from or to the current segment.
- */
-int fdc_setup_read_write(buffer_struct * buff, __u8 operation)
-{
- unsigned long flags;
- __u8 out[9];
- int dma_mode;
- TRACE_FUN(ft_t_any);
-
- switch(operation) {
- case FDC_VERIFY:
- if (fdc.type < i82077) {
- operation = FDC_READ;
- }
- case FDC_READ:
- case FDC_READ_DELETED:
- dma_mode = DMA_MODE_READ;
- TRACE(ft_t_fdc_dma, "xfer %d sectors to 0x%p",
- buff->sector_count, buff->ptr);
- TRACE_CATCH(perpend_off(),);
- break;
- case FDC_WRITE_DELETED:
- TRACE(ft_t_noise, "deleting segment %d", buff->segment_id);
- case FDC_WRITE:
- dma_mode = DMA_MODE_WRITE;
- /* When writing QIC-3020 tapes, turn on perpendicular mode
- * if tape is moving in forward direction (even tracks).
- */
- TRACE_CATCH(handle_perpend(buff->segment_id),);
- TRACE(ft_t_fdc_dma, "xfer %d sectors from 0x%p",
- buff->sector_count, buff->ptr);
- break;
- default:
- TRACE_ABORT(-EIO,
- ft_t_bug, "bug: invalid operation parameter");
- }
- TRACE(ft_t_fdc_dma, "phys. addr. = %lx",virt_to_bus((void*)buff->ptr));
- spin_lock_irqsave(&fdc_io_lock, flags);
- if (operation != FDC_VERIFY) {
- fdc_setup_dma(dma_mode, buff->ptr,
- FT_SECTOR_SIZE * buff->sector_count);
- }
- /* Issue FDC command to start reading/writing.
- */
- out[0] = operation;
- out[1] = ft_drive_sel;
- out[2] = buff->cyl;
- out[3] = buff->head;
- out[4] = buff->sect + buff->sector_offset;
- out[5] = 3; /* Sector size of 1K. */
- out[6] = out[4] + buff->sector_count - 1; /* last sector */
- out[7] = 109; /* Gap length. */
- out[8] = 0xff; /* No limit to transfer size. */
- TRACE(ft_t_fdc_dma, "C: 0x%02x, H: 0x%02x, R: 0x%02x, cnt: 0x%02x",
- out[2], out[3], out[4], out[6] - out[4] + 1);
- spin_unlock_irqrestore(&fdc_io_lock, flags);
- TRACE_CATCH(fdc_setup_error = fdc_command(out, 9),fdc_mode = fdc_idle);
- TRACE_EXIT 0;
-}
-
-int fdc_fifo_threshold(__u8 threshold,
- int *fifo_state, int *lock_state, int *fifo_thr)
-{
- const __u8 cmd0[] = {FDC_DUMPREGS};
- __u8 cmd1[] = {FDC_CONFIGURE, 0, (0x0f & (threshold - 1)), 0};
- const __u8 cmd2[] = {FDC_LOCK};
- const __u8 cmd3[] = {FDC_UNLOCK};
- __u8 reg[10];
- __u8 stat;
- int i;
- int result;
- TRACE_FUN(ft_t_any);
-
- if (CLK_48MHZ && fdc.type >= i82078) {
- cmd1[0] |= FDC_CLK48_BIT;
- }
- /* Dump fdc internal registers for examination
- */
- TRACE_CATCH(fdc_command(cmd0, NR_ITEMS(cmd0)),
- TRACE(ft_t_warn, "dumpreg cmd failed, fifo unchanged"));
- /* Now read fdc internal registers from fifo
- */
- for (i = 0; i < (int)NR_ITEMS(reg); ++i) {
- fdc_read(&reg[i]);
- TRACE(ft_t_fdc_dma, "Register %d = 0x%02x", i, reg[i]);
- }
- if (fifo_state && lock_state && fifo_thr) {
- *fifo_state = (reg[8] & 0x20) == 0;
- *lock_state = reg[7] & 0x80;
- *fifo_thr = 1 + (reg[8] & 0x0f);
- }
- TRACE(ft_t_noise,
- "original fifo state: %sabled, threshold %d, %slocked",
- ((reg[8] & 0x20) == 0) ? "en" : "dis",
- 1 + (reg[8] & 0x0f), (reg[7] & 0x80) ? "" : "not ");
- /* If fdc is already locked, unlock it first ! */
- if (reg[7] & 0x80) {
- fdc_ready_wait(100);
- TRACE_CATCH(fdc_issue_command(cmd3, NR_ITEMS(cmd3), &stat, 1),
- TRACE(ft_t_bug, "FDC unlock command failed, "
- "configuration unchanged"));
- }
- fdc_fifo_locked = 0;
- /* Enable fifo and set threshold at xx bytes to allow a
- * reasonably large latency and reduce number of dma bursts.
- */
- fdc_ready_wait(100);
- if ((result = fdc_command(cmd1, NR_ITEMS(cmd1))) < 0) {
- TRACE(ft_t_bug, "configure cmd failed, fifo unchanged");
- }
- /* Now lock configuration so reset will not change it
- */
- if(fdc_issue_command(cmd2, NR_ITEMS(cmd2), &stat, 1) < 0 ||
- stat != 0x10) {
- TRACE_ABORT(-EIO, ft_t_bug,
- "FDC lock command failed, stat = 0x%02x", stat);
- }
- fdc_fifo_locked = 1;
- TRACE_EXIT result;
-}
-
-static int fdc_fifo_enable(void)
-{
- TRACE_FUN(ft_t_any);
-
- if (fdc_fifo_locked) {
- TRACE_ABORT(0, ft_t_warn, "Fifo not enabled because locked");
- }
- TRACE_CATCH(fdc_fifo_threshold(ft_fdc_threshold /* bytes */,
- &fdc_fifo_state,
- &fdc_lock_state,
- &fdc_fifo_thr),);
- TRACE_CATCH(fdc_fifo_threshold(ft_fdc_threshold /* bytes */,
- NULL, NULL, NULL),);
- TRACE_EXIT 0;
-}
-
-/* Determine fd controller type
- */
-static __u8 fdc_save_state[2];
-
-static int fdc_probe(void)
-{
- __u8 cmd[1];
- __u8 stat[16]; /* must be able to hold dumpregs & save results */
- int i;
- TRACE_FUN(ft_t_any);
-
- /* Try to find out what kind of fd controller we have to deal with
- * Scheme borrowed from floppy driver:
- * first try if FDC_DUMPREGS command works
- * (this indicates that we have a 82072 or better)
- * then try the FDC_VERSION command (82072 doesn't support this)
- * then try the FDC_UNLOCK command (some older 82077's don't support this)
- * then try the FDC_PARTID command (82078's support this)
- */
- cmd[0] = FDC_DUMPREGS;
- if (fdc_issue_command(cmd, 1, stat, 1) != 0) {
- TRACE_ABORT(no_fdc, ft_t_bug, "No FDC found");
- }
- if (stat[0] == 0x80) {
- /* invalid command: must be pre 82072 */
- TRACE_ABORT(i8272,
- ft_t_warn, "Type 8272A/765A compatible FDC found");
- }
- fdc_result(&stat[1], 9);
- fdc_save_state[0] = stat[7];
- fdc_save_state[1] = stat[8];
- cmd[0] = FDC_VERSION;
- if (fdc_issue_command(cmd, 1, stat, 1) < 0 || stat[0] == 0x80) {
- TRACE_ABORT(i8272, ft_t_warn, "Type 82072 FDC found");
- }
- if (*stat != 0x90) {
- TRACE_ABORT(i8272, ft_t_warn, "Unknown FDC found");
- }
- cmd[0] = FDC_UNLOCK;
- if(fdc_issue_command(cmd, 1, stat, 1) < 0 || stat[0] != 0x00) {
- TRACE_ABORT(i8272, ft_t_warn,
- "Type pre-1991 82077 FDC found, "
- "treating it like a 82072");
- }
- if (fdc_save_state[0] & 0x80) { /* was locked */
- cmd[0] = FDC_LOCK; /* restore lock */
- (void)fdc_issue_command(cmd, 1, stat, 1);
- TRACE(ft_t_warn, "FDC is already locked");
- }
- /* Test for a i82078 FDC */
- cmd[0] = FDC_PARTID;
- if (fdc_issue_command(cmd, 1, stat, 1) < 0 || stat[0] == 0x80) {
- /* invalid command: not a i82078xx type FDC */
- for (i = 0; i < 4; ++i) {
- outb_p(i, fdc.tdr);
- if ((inb_p(fdc.tdr) & 0x03) != i) {
- TRACE_ABORT(i82077,
- ft_t_warn, "Type 82077 FDC found");
- }
- }
- TRACE_ABORT(i82077AA, ft_t_warn, "Type 82077AA FDC found");
- }
- /* FDC_PARTID cmd succeeded */
- switch (stat[0] >> 5) {
- case 0x0:
- /* i82078SL or i82078-1. The SL part cannot run at
- * 2Mbps (the SL and -1 dies are identical; they are
- * speed graded after production, according to Intel).
- * Some SL's can be detected by doing a SAVE cmd and
- * look at bit 7 of the first byte (the SEL3V# bit).
- * If it is 0, the part runs off 3Volts, and hence it
- * is a SL.
- */
- cmd[0] = FDC_SAVE;
- if(fdc_issue_command(cmd, 1, stat, 16) < 0) {
- TRACE(ft_t_err, "FDC_SAVE failed. Dunno why");
- /* guess we better claim the fdc to be a i82078 */
- TRACE_ABORT(i82078,
- ft_t_warn,
- "Type i82078 FDC (i suppose) found");
- }
- if ((stat[0] & FDC_SEL3V_BIT)) {
- /* fdc running off 5Volts; Pray that it's a i82078-1
- */
- TRACE_ABORT(i82078_1, ft_t_warn,
- "Type i82078-1 or 5Volt i82078SL FDC found");
- }
- TRACE_ABORT(i82078, ft_t_warn,
- "Type 3Volt i82078SL FDC (1Mbps) found");
- case 0x1:
- case 0x2: /* S82078B */
- /* The '78B isn't '78 compatible. Detect it as a '77AA */
- TRACE_ABORT(i82077AA, ft_t_warn, "Type i82077AA FDC found");
- case 0x3: /* NSC PC8744 core; used in several super-IO chips */
- TRACE_ABORT(i82077AA,
- ft_t_warn, "Type 82077AA compatible FDC found");
- default:
- TRACE(ft_t_warn, "A previously undetected FDC found");
- TRACE_ABORT(i82077AA, ft_t_warn,
- "Treating it as a 82077AA. Please report partid= %d",
- stat[0]);
- } /* switch(stat[ 0] >> 5) */
- TRACE_EXIT no_fdc;
-}
-
-static int fdc_request_regions(void)
-{
- TRACE_FUN(ft_t_flow);
-
- if (ft_mach2 || ft_probe_fc10) {
- if (!request_region(fdc.sra, 8, "fdc (ft)")) {
-#ifndef BROKEN_FLOPPY_DRIVER
- TRACE_EXIT -EBUSY;
-#else
- TRACE(ft_t_warn,
-"address 0x%03x occupied (by floppy driver?), using it anyway", fdc.sra);
-#endif
- }
- } else {
- if (!request_region(fdc.sra, 6, "fdc (ft)")) {
-#ifndef BROKEN_FLOPPY_DRIVER
- TRACE_EXIT -EBUSY;
-#else
- TRACE(ft_t_warn,
-"address 0x%03x occupied (by floppy driver?), using it anyway", fdc.sra);
-#endif
- }
- if (!request_region(fdc.sra + 7, 1, "fdc (ft)")) {
-#ifndef BROKEN_FLOPPY_DRIVER
- release_region(fdc.sra, 6);
- TRACE_EXIT -EBUSY;
-#else
- TRACE(ft_t_warn,
-"address 0x%03x occupied (by floppy driver?), using it anyway", fdc.sra + 7);
-#endif
- }
- }
- TRACE_EXIT 0;
-}
-
-void fdc_release_regions(void)
-{
- TRACE_FUN(ft_t_flow);
-
- if (fdc.sra != 0) {
- if (fdc.dor2 != 0) {
- release_region(fdc.sra, 8);
- } else {
- release_region(fdc.sra, 6);
- release_region(fdc.dir, 1);
- }
- }
- TRACE_EXIT;
-}
-
-static int fdc_config_regs(unsigned int fdc_base,
- unsigned int fdc_irq,
- unsigned int fdc_dma)
-{
- TRACE_FUN(ft_t_flow);
-
- fdc.irq = fdc_irq;
- fdc.dma = fdc_dma;
- fdc.sra = fdc_base;
- fdc.srb = fdc_base + 1;
- fdc.dor = fdc_base + 2;
- fdc.tdr = fdc_base + 3;
- fdc.msr = fdc.dsr = fdc_base + 4;
- fdc.fifo = fdc_base + 5;
- fdc.dir = fdc.ccr = fdc_base + 7;
- fdc.dor2 = (ft_mach2 || ft_probe_fc10) ? fdc_base + 6 : 0;
- TRACE_CATCH(fdc_request_regions(), fdc.sra = 0);
- TRACE_EXIT 0;
-}
-
-static int fdc_config(void)
-{
- static int already_done;
- TRACE_FUN(ft_t_any);
-
- if (already_done) {
- TRACE_CATCH(fdc_request_regions(),);
- *(fdc.hook) = fdc_isr; /* hook our handler in */
- TRACE_EXIT 0;
- }
- if (ft_probe_fc10) {
- int fc_type;
-
- TRACE_CATCH(fdc_config_regs(ft_fdc_base,
- ft_fdc_irq, ft_fdc_dma),);
- fc_type = fc10_enable();
- if (fc_type != 0) {
- TRACE(ft_t_warn, "FC-%c0 controller found", '0' + fc_type);
- fdc.type = fc10;
- fdc.hook = &do_ftape;
- *(fdc.hook) = fdc_isr; /* hook our handler in */
- already_done = 1;
- TRACE_EXIT 0;
- } else {
- TRACE(ft_t_warn, "FC-10/20 controller not found");
- fdc_release_regions();
- fdc.type = no_fdc;
- ft_probe_fc10 = 0;
- ft_fdc_base = 0x3f0;
- ft_fdc_irq = 6;
- ft_fdc_dma = 2;
- }
- }
- TRACE(ft_t_warn, "fdc base: 0x%x, irq: %d, dma: %d",
- ft_fdc_base, ft_fdc_irq, ft_fdc_dma);
- TRACE_CATCH(fdc_config_regs(ft_fdc_base, ft_fdc_irq, ft_fdc_dma),);
- fdc.hook = &do_ftape;
- *(fdc.hook) = fdc_isr; /* hook our handler in */
- already_done = 1;
- TRACE_EXIT 0;
-}
-
-static irqreturn_t ftape_interrupt(int irq, void *dev_id)
-{
- void (*handler) (void) = *fdc.hook;
- int handled = 0;
- TRACE_FUN(ft_t_any);
-
- *fdc.hook = NULL;
- if (handler) {
- handled = 1;
- handler();
- } else {
- TRACE(ft_t_bug, "Unexpected ftape interrupt");
- }
- TRACE_EXIT IRQ_RETVAL(handled);
-}
-
-static int fdc_grab_irq_and_dma(void)
-{
- TRACE_FUN(ft_t_any);
-
- if (fdc.hook == &do_ftape) {
- /* Get fast interrupt handler.
- */
- if (request_irq(fdc.irq, ftape_interrupt,
- IRQF_DISABLED, "ft", ftape_id)) {
- TRACE_ABORT(-EIO, ft_t_bug,
- "Unable to grab IRQ%d for ftape driver",
- fdc.irq);
- }
- if (request_dma(fdc.dma, ftape_id)) {
- free_irq(fdc.irq, ftape_id);
- TRACE_ABORT(-EIO, ft_t_bug,
- "Unable to grab DMA%d for ftape driver",
- fdc.dma);
- }
- }
- if (ft_fdc_base != 0x3f0 && (ft_fdc_dma == 2 || ft_fdc_irq == 6)) {
- /* Using same dma channel or irq as standard fdc, need
- * to disable the dma-gate on the std fdc. This
- * couldn't be done in the floppy driver as some
- * laptops are using the dma-gate to enter a low power
- * or even suspended state :-(
- */
- outb_p(FDC_RESET_NOT, 0x3f2);
- TRACE(ft_t_noise, "DMA-gate on standard fdc disabled");
- }
- TRACE_EXIT 0;
-}
-
-int fdc_release_irq_and_dma(void)
-{
- TRACE_FUN(ft_t_any);
-
- if (fdc.hook == &do_ftape) {
- disable_dma(fdc.dma); /* just in case... */
- free_dma(fdc.dma);
- free_irq(fdc.irq, ftape_id);
- }
- if (ft_fdc_base != 0x3f0 && (ft_fdc_dma == 2 || ft_fdc_irq == 6)) {
- /* Using same dma channel as standard fdc, need to
- * disable the dma-gate on the std fdc. This couldn't
- * be done in the floppy driver as some laptops are
- * using the dma-gate to enter a low power or even
- * suspended state :-(
- */
- outb_p(FDC_RESET_NOT | FDC_DMA_MODE, 0x3f2);
- TRACE(ft_t_noise, "DMA-gate on standard fdc enabled again");
- }
- TRACE_EXIT 0;
-}
-
-int fdc_init(void)
-{
- TRACE_FUN(ft_t_any);
-
- /* find a FDC to use */
- TRACE_CATCH(fdc_config(),);
- TRACE_CATCH(fdc_grab_irq_and_dma(), fdc_release_regions());
- ftape_motor = 0;
- fdc_catch_stray_interrupts(0); /* clear number of awainted
- * stray interrupte
- */
- fdc_catch_stray_interrupts(1); /* one always comes (?) */
- TRACE(ft_t_flow, "resetting fdc");
- fdc_set_seek_rate(2); /* use nominal QIC step rate */
- fdc_reset(); /* init fdc & clear track counters */
- if (fdc.type == no_fdc) { /* no FC-10 or FC-20 found */
- fdc.type = fdc_probe();
- fdc_reset(); /* update with new knowledge */
- }
- if (fdc.type == no_fdc) {
- fdc_release_irq_and_dma();
- fdc_release_regions();
- TRACE_EXIT -ENXIO;
- }
- if (fdc.type >= i82077) {
- if (fdc_fifo_enable() < 0) {
- TRACE(ft_t_warn, "couldn't enable fdc fifo !");
- } else {
- TRACE(ft_t_flow, "fdc fifo enabled and locked");
- }
- }
- TRACE_EXIT 0;
-}
diff --git a/drivers/char/ftape/lowlevel/fdc-io.h b/drivers/char/ftape/lowlevel/fdc-io.h
deleted file mode 100644
index 7ec3c72178bb..000000000000
--- a/drivers/char/ftape/lowlevel/fdc-io.h
+++ /dev/null
@@ -1,252 +0,0 @@
-#ifndef _FDC_IO_H
-#define _FDC_IO_H
-
-/*
- * Copyright (C) 1993-1996 Bas Laarhoven,
- * (C) 1996-1997 Claus-Justus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/fdc-io.h,v $
- * $Revision: 1.3 $
- * $Date: 1997/10/05 19:18:06 $
- *
- * This file contains the declarations for the low level
- * functions that communicate with the floppy disk controller,
- * for the QIC-40/80/3010/3020 floppy-tape driver "ftape" for
- * Linux.
- */
-
-#include <linux/fdreg.h>
-
-#include "../lowlevel/ftape-bsm.h"
-
-#define FDC_SK_BIT (0x20)
-#define FDC_MT_BIT (0x80)
-
-#define FDC_READ (FD_READ & ~(FDC_SK_BIT | FDC_MT_BIT))
-#define FDC_WRITE (FD_WRITE & ~FDC_MT_BIT)
-#define FDC_READ_DELETED (0x4c)
-#define FDC_WRITE_DELETED (0x49)
-#define FDC_VERIFY (0x56)
-#define FDC_READID (0x4a)
-#define FDC_SENSED (0x04)
-#define FDC_SENSEI (FD_SENSEI)
-#define FDC_FORMAT (FD_FORMAT)
-#define FDC_RECAL (FD_RECALIBRATE)
-#define FDC_SEEK (FD_SEEK)
-#define FDC_SPECIFY (FD_SPECIFY)
-#define FDC_RECALIBR (FD_RECALIBRATE)
-#define FDC_VERSION (FD_VERSION)
-#define FDC_PERPEND (FD_PERPENDICULAR)
-#define FDC_DUMPREGS (FD_DUMPREGS)
-#define FDC_LOCK (FD_LOCK)
-#define FDC_UNLOCK (FD_UNLOCK)
-#define FDC_CONFIGURE (FD_CONFIGURE)
-#define FDC_DRIVE_SPEC (0x8e) /* i82078 has this (any others?) */
-#define FDC_PARTID (0x18) /* i82078 has this */
-#define FDC_SAVE (0x2e) /* i82078 has this (any others?) */
-#define FDC_RESTORE (0x4e) /* i82078 has this (any others?) */
-
-#define FDC_STATUS_MASK (STATUS_BUSY | STATUS_DMA | STATUS_DIR | STATUS_READY)
-#define FDC_DATA_READY (STATUS_READY)
-#define FDC_DATA_OUTPUT (STATUS_DIR)
-#define FDC_DATA_READY_MASK (STATUS_READY | STATUS_DIR)
-#define FDC_DATA_OUT_READY (STATUS_READY | STATUS_DIR)
-#define FDC_DATA_IN_READY (STATUS_READY)
-#define FDC_BUSY (STATUS_BUSY)
-#define FDC_CLK48_BIT (0x80)
-#define FDC_SEL3V_BIT (0x40)
-
-#define ST0_INT_MASK (ST0_INTR)
-#define FDC_INT_NORMAL (ST0_INTR & 0x00)
-#define FDC_INT_ABNORMAL (ST0_INTR & 0x40)
-#define FDC_INT_INVALID (ST0_INTR & 0x80)
-#define FDC_INT_READYCH (ST0_INTR & 0xC0)
-#define ST0_SEEK_END (ST0_SE)
-#define ST3_TRACK_0 (ST3_TZ)
-
-#define FDC_RESET_NOT (0x04)
-#define FDC_DMA_MODE (0x08)
-#define FDC_MOTOR_0 (0x10)
-#define FDC_MOTOR_1 (0x20)
-
-typedef struct {
- void (**hook) (void); /* our wedge into the isr */
- enum {
- no_fdc, i8272, i82077, i82077AA, fc10,
- i82078, i82078_1
- } type; /* FDC type */
- unsigned int irq; /* FDC irq nr */
- unsigned int dma; /* FDC dma channel nr */
- __u16 sra; /* Status register A (PS/2 only) */
- __u16 srb; /* Status register B (PS/2 only) */
- __u16 dor; /* Digital output register */
- __u16 tdr; /* Tape Drive Register (82077SL-1 &
- 82078 only) */
- __u16 msr; /* Main Status Register */
- __u16 dsr; /* Datarate Select Register (8207x only) */
- __u16 fifo; /* Data register / Fifo on 8207x */
- __u16 dir; /* Digital Input Register */
- __u16 ccr; /* Configuration Control Register */
- __u16 dor2; /* Alternate dor on MACH-2 controller,
- also used with FC-10, meaning unknown */
-} fdc_config_info;
-
-typedef enum {
- fdc_data_rate_250 = 2,
- fdc_data_rate_300 = 1, /* any fdc in default configuration */
- fdc_data_rate_500 = 0,
- fdc_data_rate_1000 = 3,
- fdc_data_rate_2000 = 1, /* i82078-1: when using Data Rate Table #2 */
-} fdc_data_rate_type;
-
-typedef enum {
- fdc_idle = 0,
- fdc_reading_data = FDC_READ,
- fdc_seeking = FDC_SEEK,
- fdc_writing_data = FDC_WRITE,
- fdc_deleting = FDC_WRITE_DELETED,
- fdc_reading_id = FDC_READID,
- fdc_recalibrating = FDC_RECAL,
- fdc_formatting = FDC_FORMAT,
- fdc_verifying = FDC_VERIFY
-} fdc_mode_enum;
-
-typedef enum {
- waiting = 0,
- reading,
- writing,
- formatting,
- verifying,
- deleting,
- done,
- error,
- mmapped,
-} buffer_state_enum;
-
-typedef struct {
- __u8 *address;
- volatile buffer_state_enum status;
- volatile __u8 *ptr;
- volatile unsigned int bytes;
- volatile unsigned int segment_id;
-
- /* bitmap for remainder of segment not yet handled.
- * one bit set for each bad sector that must be skipped.
- */
- volatile SectorMap bad_sector_map;
-
- /* bitmap with bad data blocks in data buffer.
- * the errors in this map may be retried.
- */
- volatile SectorMap soft_error_map;
-
- /* bitmap with bad data blocks in data buffer
- * the errors in this map may not be retried.
- */
- volatile SectorMap hard_error_map;
-
- /* retry counter for soft errors.
- */
- volatile int retry;
-
- /* sectors to skip on retry ???
- */
- volatile unsigned int skip;
-
- /* nr of data blocks in data buffer
- */
- volatile unsigned int data_offset;
-
- /* offset in segment for first sector to be handled.
- */
- volatile unsigned int sector_offset;
-
- /* size of cluster of good sectors to be handled.
- */
- volatile unsigned int sector_count;
-
- /* size of remaining part of segment to be handled.
- */
- volatile unsigned int remaining;
-
- /* points to next segment (contiguous) to be handled,
- * or is zero if no read-ahead is allowed.
- */
- volatile unsigned int next_segment;
-
- /* flag being set if deleted data was read.
- */
- volatile int deleted;
-
- /* floppy coordinates of first sector in segment */
- volatile __u8 head;
- volatile __u8 cyl;
- volatile __u8 sect;
-
- /* gap to use when formatting */
- __u8 gap3;
- /* flag set when buffer is mmaped */
- int mmapped;
-} buffer_struct;
-
-/*
- * fdc-io.c defined public variables
- */
-extern volatile fdc_mode_enum fdc_mode;
-extern int fdc_setup_error; /* outdated ??? */
-extern wait_queue_head_t ftape_wait_intr;
-extern volatile int ftape_current_cylinder; /* track nr FDC thinks we're on */
-extern volatile __u8 fdc_head; /* FDC head */
-extern volatile __u8 fdc_cyl; /* FDC track */
-extern volatile __u8 fdc_sect; /* FDC sector */
-extern fdc_config_info fdc; /* FDC hardware configuration */
-
-extern unsigned int ft_fdc_base;
-extern unsigned int ft_fdc_irq;
-extern unsigned int ft_fdc_dma;
-extern unsigned int ft_fdc_threshold;
-extern unsigned int ft_fdc_rate_limit;
-extern int ft_probe_fc10;
-extern int ft_mach2;
-/*
- * fdc-io.c defined public functions
- */
-extern void fdc_catch_stray_interrupts(int count);
-extern int fdc_ready_wait(unsigned int timeout);
-extern int fdc_command(const __u8 * cmd_data, int cmd_len);
-extern int fdc_result(__u8 * res_data, int res_len);
-extern int fdc_interrupt_wait(unsigned int time);
-extern int fdc_seek(int track);
-extern int fdc_sense_drive_status(int *st3);
-extern void fdc_motor(int motor);
-extern void fdc_reset(void);
-extern void fdc_disable(void);
-extern int fdc_fifo_threshold(__u8 threshold,
- int *fifo_state, int *lock_state, int *fifo_thr);
-extern void fdc_wait_calibrate(void);
-extern int fdc_sense_interrupt_status(int *st0, int *current_cylinder);
-extern void fdc_save_drive_specs(void);
-extern void fdc_restore_drive_specs(void);
-extern int fdc_set_data_rate(int rate);
-extern void fdc_set_write_precomp(int precomp);
-extern int fdc_release_irq_and_dma(void);
-extern void fdc_release_regions(void);
-extern int fdc_init(void);
-extern int fdc_setup_read_write(buffer_struct * buff, __u8 operation);
-extern int fdc_setup_formatting(buffer_struct * buff);
-#endif
diff --git a/drivers/char/ftape/lowlevel/fdc-isr.c b/drivers/char/ftape/lowlevel/fdc-isr.c
deleted file mode 100644
index ad2bc733ae1b..000000000000
--- a/drivers/char/ftape/lowlevel/fdc-isr.c
+++ /dev/null
@@ -1,1170 +0,0 @@
-/*
- * Copyright (C) 1994-1996 Bas Laarhoven,
- * (C) 1996-1997 Claus-Justus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/fdc-isr.c,v $
- * $Revision: 1.9 $
- * $Date: 1997/10/17 23:01:53 $
- *
- * This file contains the interrupt service routine and
- * associated code for the QIC-40/80/3010/3020 floppy-tape driver
- * "ftape" for Linux.
- */
-
-#include <asm/io.h>
-#include <asm/dma.h>
-
-#define volatile /* */
-
-#include <linux/ftape.h>
-#include <linux/qic117.h>
-#include "../lowlevel/ftape-tracing.h"
-#include "../lowlevel/fdc-isr.h"
-#include "../lowlevel/fdc-io.h"
-#include "../lowlevel/ftape-ctl.h"
-#include "../lowlevel/ftape-rw.h"
-#include "../lowlevel/ftape-io.h"
-#include "../lowlevel/ftape-calibr.h"
-#include "../lowlevel/ftape-bsm.h"
-
-/* Global vars.
- */
-volatile int ft_expected_stray_interrupts;
-volatile int ft_interrupt_seen;
-volatile int ft_seek_completed;
-volatile int ft_hide_interrupt;
-/* Local vars.
- */
-typedef enum {
- no_error = 0, id_am_error = 0x01, id_crc_error = 0x02,
- data_am_error = 0x04, data_crc_error = 0x08,
- no_data_error = 0x10, overrun_error = 0x20,
-} error_cause;
-static int stop_read_ahead;
-
-
-static void print_error_cause(int cause)
-{
- TRACE_FUN(ft_t_any);
-
- switch (cause) {
- case no_data_error:
- TRACE(ft_t_noise, "no data error");
- break;
- case id_am_error:
- TRACE(ft_t_noise, "id am error");
- break;
- case id_crc_error:
- TRACE(ft_t_noise, "id crc error");
- break;
- case data_am_error:
- TRACE(ft_t_noise, "data am error");
- break;
- case data_crc_error:
- TRACE(ft_t_noise, "data crc error");
- break;
- case overrun_error:
- TRACE(ft_t_noise, "overrun error");
- break;
- default:;
- }
- TRACE_EXIT;
-}
-
-static char *fdc_mode_txt(fdc_mode_enum mode)
-{
- switch (mode) {
- case fdc_idle:
- return "fdc_idle";
- case fdc_reading_data:
- return "fdc_reading_data";
- case fdc_seeking:
- return "fdc_seeking";
- case fdc_writing_data:
- return "fdc_writing_data";
- case fdc_reading_id:
- return "fdc_reading_id";
- case fdc_recalibrating:
- return "fdc_recalibrating";
- case fdc_formatting:
- return "fdc_formatting";
- case fdc_verifying:
- return "fdc_verifying";
- default:
- return "unknown";
- }
-}
-
-static inline error_cause decode_irq_cause(fdc_mode_enum mode, __u8 st[])
-{
- error_cause cause = no_error;
- TRACE_FUN(ft_t_any);
-
- /* Valid st[], decode cause of interrupt.
- */
- switch (st[0] & ST0_INT_MASK) {
- case FDC_INT_NORMAL:
- TRACE(ft_t_fdc_dma,"normal completion: %s",fdc_mode_txt(mode));
- break;
- case FDC_INT_ABNORMAL:
- TRACE(ft_t_flow, "abnormal completion %s", fdc_mode_txt(mode));
- TRACE(ft_t_fdc_dma, "ST0: 0x%02x, ST1: 0x%02x, ST2: 0x%02x",
- st[0], st[1], st[2]);
- TRACE(ft_t_fdc_dma,
- "C: 0x%02x, H: 0x%02x, R: 0x%02x, N: 0x%02x",
- st[3], st[4], st[5], st[6]);
- if (st[1] & 0x01) {
- if (st[2] & 0x01) {
- cause = data_am_error;
- } else {
- cause = id_am_error;
- }
- } else if (st[1] & 0x20) {
- if (st[2] & 0x20) {
- cause = data_crc_error;
- } else {
- cause = id_crc_error;
- }
- } else if (st[1] & 0x04) {
- cause = no_data_error;
- } else if (st[1] & 0x10) {
- cause = overrun_error;
- }
- print_error_cause(cause);
- break;
- case FDC_INT_INVALID:
- TRACE(ft_t_flow, "invalid completion %s", fdc_mode_txt(mode));
- break;
- case FDC_INT_READYCH:
- if (st[0] & ST0_SEEK_END) {
- TRACE(ft_t_flow, "drive poll completed");
- } else {
- TRACE(ft_t_flow, "ready change %s",fdc_mode_txt(mode));
- }
- break;
- default:
- break;
- }
- TRACE_EXIT cause;
-}
-
-static void update_history(error_cause cause)
-{
- switch (cause) {
- case id_am_error:
- ft_history.id_am_errors++;
- break;
- case id_crc_error:
- ft_history.id_crc_errors++;
- break;
- case data_am_error:
- ft_history.data_am_errors++;
- break;
- case data_crc_error:
- ft_history.data_crc_errors++;
- break;
- case overrun_error:
- ft_history.overrun_errors++;
- break;
- case no_data_error:
- ft_history.no_data_errors++;
- break;
- default:;
- }
-}
-
-static void skip_bad_sector(buffer_struct * buff)
-{
- TRACE_FUN(ft_t_any);
-
- /* Mark sector as soft error and skip it
- */
- if (buff->remaining > 0) {
- ++buff->sector_offset;
- ++buff->data_offset;
- --buff->remaining;
- buff->ptr += FT_SECTOR_SIZE;
- buff->bad_sector_map >>= 1;
- } else {
- /* Hey, what is this????????????? C code: if we shift
- * more than 31 bits, we get no shift. That's bad!!!!!!
- */
- ++buff->sector_offset; /* hack for error maps */
- TRACE(ft_t_warn, "skipping last sector in segment");
- }
- TRACE_EXIT;
-}
-
-static void update_error_maps(buffer_struct * buff, unsigned int error_offset)
-{
- int hard = 0;
- TRACE_FUN(ft_t_any);
-
- if (buff->retry < FT_SOFT_RETRIES) {
- buff->soft_error_map |= (1 << error_offset);
- } else {
- buff->hard_error_map |= (1 << error_offset);
- buff->soft_error_map &= ~buff->hard_error_map;
- buff->retry = -1; /* will be set to 0 in setup_segment */
- hard = 1;
- }
- TRACE(ft_t_noise, "sector %d : %s error\n"
- KERN_INFO "hard map: 0x%08lx\n"
- KERN_INFO "soft map: 0x%08lx",
- FT_SECTOR(error_offset), hard ? "hard" : "soft",
- (long) buff->hard_error_map, (long) buff->soft_error_map);
- TRACE_EXIT;
-}
-
-static void print_progress(buffer_struct *buff, error_cause cause)
-{
- TRACE_FUN(ft_t_any);
-
- switch (cause) {
- case no_error:
- TRACE(ft_t_flow,"%d Sector(s) transferred", buff->sector_count);
- break;
- case no_data_error:
- TRACE(ft_t_flow, "Sector %d not found",
- FT_SECTOR(buff->sector_offset));
- break;
- case overrun_error:
- /* got an overrun error on the first byte, must be a
- * hardware problem
- */
- TRACE(ft_t_bug,
- "Unexpected error: failing DMA or FDC controller ?");
- break;
- case data_crc_error:
- TRACE(ft_t_flow, "Error in sector %d",
- FT_SECTOR(buff->sector_offset - 1));
- break;
- case id_crc_error:
- case id_am_error:
- case data_am_error:
- TRACE(ft_t_flow, "Error in sector %d",
- FT_SECTOR(buff->sector_offset));
- break;
- default:
- TRACE(ft_t_flow, "Unexpected error at sector %d",
- FT_SECTOR(buff->sector_offset));
- break;
- }
- TRACE_EXIT;
-}
-
-/*
- * Error cause: Amount xferred: Action:
- *
- * id_am_error 0 mark bad and skip
- * id_crc_error 0 mark bad and skip
- * data_am_error 0 mark bad and skip
- * data_crc_error % 1024 mark bad and skip
- * no_data_error 0 retry on write
- * mark bad and skip on read
- * overrun_error [ 0..all-1 ] mark bad and skip
- * no_error all continue
- */
-
-/* the arg `sector' is returned by the fdc and tells us at which sector we
- * are positioned at (relative to starting sector of segment)
- */
-static void determine_verify_progress(buffer_struct *buff,
- error_cause cause,
- __u8 sector)
-{
- TRACE_FUN(ft_t_any);
-
- if (cause == no_error && sector == 1) {
- buff->sector_offset = FT_SECTORS_PER_SEGMENT;
- buff->remaining = 0;
- if (TRACE_LEVEL >= ft_t_flow) {
- print_progress(buff, cause);
- }
- } else {
- buff->sector_offset = sector - buff->sect;
- buff->remaining = FT_SECTORS_PER_SEGMENT - buff->sector_offset;
- TRACE(ft_t_noise, "%ssector offset: 0x%04x",
- (cause == no_error) ? "unexpected " : "",
- buff->sector_offset);
- switch (cause) {
- case overrun_error:
- break;
-#if 0
- case no_data_error:
- buff->retry = FT_SOFT_RETRIES;
- if (buff->hard_error_map &&
- buff->sector_offset > 1 &&
- (buff->hard_error_map &
- (1 << (buff->sector_offset-2)))) {
- buff->retry --;
- }
- break;
-#endif
- default:
- buff->retry = FT_SOFT_RETRIES;
- break;
- }
- if (TRACE_LEVEL >= ft_t_flow) {
- print_progress(buff, cause);
- }
- /* Sector_offset points to the problem area Now adjust
- * sector_offset so it always points one past he failing
- * sector. I.e. skip the bad sector.
- */
- ++buff->sector_offset;
- --buff->remaining;
- update_error_maps(buff, buff->sector_offset - 1);
- }
- TRACE_EXIT;
-}
-
-static void determine_progress(buffer_struct *buff,
- error_cause cause,
- __u8 sector)
-{
- unsigned int dma_residue;
- TRACE_FUN(ft_t_any);
-
- /* Using less preferred order of disable_dma and
- * get_dma_residue because this seems to fail on at least one
- * system if reversed!
- */
- dma_residue = get_dma_residue(fdc.dma);
- disable_dma(fdc.dma);
- if (cause != no_error || dma_residue != 0) {
- TRACE(ft_t_noise, "%sDMA residue: 0x%04x",
- (cause == no_error) ? "unexpected " : "",
- dma_residue);
- /* adjust to actual value: */
- if (dma_residue == 0) {
- /* this happens sometimes with overrun errors.
- * I don't know whether we could ignore the
- * overrun error. Play save.
- */
- buff->sector_count --;
- } else {
- buff->sector_count -= ((dma_residue +
- (FT_SECTOR_SIZE - 1)) /
- FT_SECTOR_SIZE);
- }
- }
- /* Update var's influenced by the DMA operation.
- */
- if (buff->sector_count > 0) {
- buff->sector_offset += buff->sector_count;
- buff->data_offset += buff->sector_count;
- buff->ptr += (buff->sector_count *
- FT_SECTOR_SIZE);
- buff->remaining -= buff->sector_count;
- buff->bad_sector_map >>= buff->sector_count;
- }
- if (TRACE_LEVEL >= ft_t_flow) {
- print_progress(buff, cause);
- }
- if (cause != no_error) {
- if (buff->remaining == 0) {
- TRACE(ft_t_warn, "foo?\n"
- KERN_INFO "count : %d\n"
- KERN_INFO "offset: %d\n"
- KERN_INFO "soft : %08x\n"
- KERN_INFO "hard : %08x",
- buff->sector_count,
- buff->sector_offset,
- buff->soft_error_map,
- buff->hard_error_map);
- }
- /* Sector_offset points to the problem area, except if we got
- * a data_crc_error. In that case it points one past the
- * failing sector.
- *
- * Now adjust sector_offset so it always points one past he
- * failing sector. I.e. skip the bad sector.
- */
- if (cause != data_crc_error) {
- skip_bad_sector(buff);
- }
- update_error_maps(buff, buff->sector_offset - 1);
- }
- TRACE_EXIT;
-}
-
-static int calc_steps(int cmd)
-{
- if (ftape_current_cylinder > cmd) {
- return ftape_current_cylinder - cmd;
- } else {
- return ftape_current_cylinder + cmd;
- }
-}
-
-static void pause_tape(int retry, int mode)
-{
- int result;
- __u8 out[3] = {FDC_SEEK, ft_drive_sel, 0};
- TRACE_FUN(ft_t_any);
-
- /* We'll use a raw seek command to get the tape to rewind and
- * stop for a retry.
- */
- ++ft_history.rewinds;
- if (qic117_cmds[ftape_current_command].non_intr) {
- TRACE(ft_t_warn, "motion command may be issued too soon");
- }
- if (retry && (mode == fdc_reading_data ||
- mode == fdc_reading_id ||
- mode == fdc_verifying)) {
- ftape_current_command = QIC_MICRO_STEP_PAUSE;
- ftape_might_be_off_track = 1;
- } else {
- ftape_current_command = QIC_PAUSE;
- }
- out[2] = calc_steps(ftape_current_command);
- result = fdc_command(out, 3); /* issue QIC_117 command */
- ftape_current_cylinder = out[ 2];
- if (result < 0) {
- TRACE(ft_t_noise, "qic-pause failed, status = %d", result);
- } else {
- ft_location.known = 0;
- ft_runner_status = idle;
- ft_hide_interrupt = 1;
- ftape_tape_running = 0;
- }
- TRACE_EXIT;
-}
-
-static void continue_xfer(buffer_struct *buff,
- fdc_mode_enum mode,
- unsigned int skip)
-{
- int write = 0;
- TRACE_FUN(ft_t_any);
-
- if (mode == fdc_writing_data || mode == fdc_deleting) {
- write = 1;
- }
- /* This part can be removed if it never happens
- */
- if (skip > 0 &&
- (ft_runner_status != running ||
- (write && (buff->status != writing)) ||
- (!write && (buff->status != reading &&
- buff->status != verifying)))) {
- TRACE(ft_t_err, "unexpected runner/buffer state %d/%d",
- ft_runner_status, buff->status);
- buff->status = error;
- /* finish this buffer: */
- (void)ftape_next_buffer(ft_queue_head);
- ft_runner_status = aborting;
- fdc_mode = fdc_idle;
- } else if (buff->remaining > 0 && ftape_calc_next_cluster(buff) > 0) {
- /* still sectors left in current segment, continue
- * with this segment
- */
- if (fdc_setup_read_write(buff, mode) < 0) {
- /* failed, abort operation
- */
- buff->bytes = buff->ptr - buff->address;
- buff->status = error;
- /* finish this buffer: */
- (void)ftape_next_buffer(ft_queue_head);
- ft_runner_status = aborting;
- fdc_mode = fdc_idle;
- }
- } else {
- /* current segment completed
- */
- unsigned int last_segment = buff->segment_id;
- int eot = ((last_segment + 1) % ft_segments_per_track) == 0;
- unsigned int next = buff->next_segment; /* 0 means stop ! */
-
- buff->bytes = buff->ptr - buff->address;
- buff->status = done;
- buff = ftape_next_buffer(ft_queue_head);
- if (eot) {
- /* finished last segment on current track,
- * can't continue
- */
- ft_runner_status = logical_eot;
- fdc_mode = fdc_idle;
- TRACE_EXIT;
- }
- if (next <= 0) {
- /* don't continue with next segment
- */
- TRACE(ft_t_noise, "no %s allowed, stopping tape",
- (write) ? "write next" : "read ahead");
- pause_tape(0, mode);
- ft_runner_status = idle; /* not quite true until
- * next irq
- */
- TRACE_EXIT;
- }
- /* continue with next segment
- */
- if (buff->status != waiting) {
- TRACE(ft_t_noise, "all input buffers %s, pausing tape",
- (write) ? "empty" : "full");
- pause_tape(0, mode);
- ft_runner_status = idle; /* not quite true until
- * next irq
- */
- TRACE_EXIT;
- }
- if (write && next != buff->segment_id) {
- TRACE(ft_t_noise,
- "segments out of order, aborting write");
- ft_runner_status = do_abort;
- fdc_mode = fdc_idle;
- TRACE_EXIT;
- }
- ftape_setup_new_segment(buff, next, 0);
- if (stop_read_ahead) {
- buff->next_segment = 0;
- stop_read_ahead = 0;
- }
- if (ftape_calc_next_cluster(buff) == 0 ||
- fdc_setup_read_write(buff, mode) != 0) {
- TRACE(ft_t_err, "couldn't start %s-ahead",
- write ? "write" : "read");
- ft_runner_status = do_abort;
- fdc_mode = fdc_idle;
- } else {
- /* keep on going */
- switch (ft_driver_state) {
- case reading: buff->status = reading; break;
- case verifying: buff->status = verifying; break;
- case writing: buff->status = writing; break;
- case deleting: buff->status = deleting; break;
- default:
- TRACE(ft_t_err,
- "BUG: ft_driver_state %d should be one out of "
- "{reading, writing, verifying, deleting}",
- ft_driver_state);
- buff->status = write ? writing : reading;
- break;
- }
- }
- }
- TRACE_EXIT;
-}
-
-static void retry_sector(buffer_struct *buff,
- int mode,
- unsigned int skip)
-{
- TRACE_FUN(ft_t_any);
-
- TRACE(ft_t_noise, "%s error, will retry",
- (mode == fdc_writing_data || mode == fdc_deleting) ? "write" : "read");
- pause_tape(1, mode);
- ft_runner_status = aborting;
- buff->status = error;
- buff->skip = skip;
- TRACE_EXIT;
-}
-
-static unsigned int find_resume_point(buffer_struct *buff)
-{
- int i = 0;
- SectorMap mask;
- SectorMap map;
- TRACE_FUN(ft_t_any);
-
- /* This function is to be called after all variables have been
- * updated to point past the failing sector.
- * If there are any soft errors before the failing sector,
- * find the first soft error and return the sector offset.
- * Otherwise find the last hard error.
- * Note: there should always be at least one hard or soft error !
- */
- if (buff->sector_offset < 1 || buff->sector_offset > 32) {
- TRACE(ft_t_bug, "BUG: sector_offset = %d",
- buff->sector_offset);
- TRACE_EXIT 0;
- }
- if (buff->sector_offset >= 32) { /* C-limitation on shift ! */
- mask = 0xffffffff;
- } else {
- mask = (1 << buff->sector_offset) - 1;
- }
- map = buff->soft_error_map & mask;
- if (map) {
- while ((map & (1 << i)) == 0) {
- ++i;
- }
- TRACE(ft_t_noise, "at sector %d", FT_SECTOR(i));
- } else {
- map = buff->hard_error_map & mask;
- i = buff->sector_offset - 1;
- if (map) {
- while ((map & (1 << i)) == 0) {
- --i;
- }
- TRACE(ft_t_noise, "after sector %d", FT_SECTOR(i));
- ++i; /* first sector after last hard error */
- } else {
- TRACE(ft_t_bug, "BUG: no soft or hard errors");
- }
- }
- TRACE_EXIT i;
-}
-
-/* check possible dma residue when formatting, update position record in
- * buffer struct. This is, of course, modelled after determine_progress(), but
- * we don't need to set up for retries because the format process cannot be
- * interrupted (except at the end of the tape track).
- */
-static int determine_fmt_progress(buffer_struct *buff, error_cause cause)
-{
- unsigned int dma_residue;
- TRACE_FUN(ft_t_any);
-
- /* Using less preferred order of disable_dma and
- * get_dma_residue because this seems to fail on at least one
- * system if reversed!
- */
- dma_residue = get_dma_residue(fdc.dma);
- disable_dma(fdc.dma);
- if (cause != no_error || dma_residue != 0) {
- TRACE(ft_t_info, "DMA residue = 0x%04x", dma_residue);
- fdc_mode = fdc_idle;
- switch(cause) {
- case no_error:
- ft_runner_status = aborting;
- buff->status = idle;
- break;
- case overrun_error:
- /* got an overrun error on the first byte, must be a
- * hardware problem
- */
- TRACE(ft_t_bug,
- "Unexpected error: failing DMA controller ?");
- ft_runner_status = do_abort;
- buff->status = error;
- break;
- default:
- TRACE(ft_t_noise, "Unexpected error at segment %d",
- buff->segment_id);
- ft_runner_status = do_abort;
- buff->status = error;
- break;
- }
- TRACE_EXIT -EIO; /* can only retry entire track in format mode
- */
- }
- /* Update var's influenced by the DMA operation.
- */
- buff->ptr += FT_SECTORS_PER_SEGMENT * 4;
- buff->bytes -= FT_SECTORS_PER_SEGMENT * 4;
- buff->remaining -= FT_SECTORS_PER_SEGMENT;
- buff->segment_id ++; /* done with segment */
- TRACE_EXIT 0;
-}
-
-/*
- * Continue formatting, switch buffers if there is no data left in
- * current buffer. This is, of course, modelled after
- * continue_xfer(), but we don't need to set up for retries because
- * the format process cannot be interrupted (except at the end of the
- * tape track).
- */
-static void continue_formatting(buffer_struct *buff)
-{
- TRACE_FUN(ft_t_any);
-
- if (buff->remaining <= 0) { /* no space left in dma buffer */
- unsigned int next = buff->next_segment;
-
- if (next == 0) { /* end of tape track */
- buff->status = done;
- ft_runner_status = logical_eot;
- fdc_mode = fdc_idle;
- TRACE(ft_t_noise, "Done formatting track %d",
- ft_location.track);
- TRACE_EXIT;
- }
- /*
- * switch to next buffer!
- */
- buff->status = done;
- buff = ftape_next_buffer(ft_queue_head);
-
- if (buff->status != waiting || next != buff->segment_id) {
- goto format_setup_error;
- }
- }
- if (fdc_setup_formatting(buff) < 0) {
- goto format_setup_error;
- }
- buff->status = formatting;
- TRACE(ft_t_fdc_dma, "Formatting segment %d on track %d",
- buff->segment_id, ft_location.track);
- TRACE_EXIT;
- format_setup_error:
- ft_runner_status = do_abort;
- fdc_mode = fdc_idle;
- buff->status = error;
- TRACE(ft_t_err, "Error setting up for segment %d on track %d",
- buff->segment_id, ft_location.track);
- TRACE_EXIT;
-
-}
-
-/* this handles writing, read id, reading and formatting
- */
-static void handle_fdc_busy(buffer_struct *buff)
-{
- static int no_data_error_count;
- int retry = 0;
- error_cause cause;
- __u8 in[7];
- int skip;
- fdc_mode_enum fmode = fdc_mode;
- TRACE_FUN(ft_t_any);
-
- if (fdc_result(in, 7) < 0) { /* better get it fast ! */
- TRACE(ft_t_err,
- "Probably fatal error during FDC Result Phase\n"
- KERN_INFO
- "drive may hang until (power on) reset :-(");
- /* what to do next ????
- */
- TRACE_EXIT;
- }
- cause = decode_irq_cause(fdc_mode, in);
-#ifdef TESTING
- { int i;
- for (i = 0; i < (int)ft_nr_buffers; ++i)
- TRACE(ft_t_any, "buffer[%d] status: %d, segment_id: %d",
- i, ft_buffer[i]->status, ft_buffer[i]->segment_id);
- }
-#endif
- if (fmode == fdc_reading_data && ft_driver_state == verifying) {
- fmode = fdc_verifying;
- }
- switch (fmode) {
- case fdc_verifying:
- if (ft_runner_status == aborting ||
- ft_runner_status == do_abort) {
- TRACE(ft_t_noise,"aborting %s",fdc_mode_txt(fdc_mode));
- break;
- }
- if (buff->retry > 0) {
- TRACE(ft_t_flow, "this is retry nr %d", buff->retry);
- }
- switch (cause) {
- case no_error:
- no_data_error_count = 0;
- determine_verify_progress(buff, cause, in[5]);
- if (in[2] & 0x40) {
- /* This should not happen when verifying
- */
- TRACE(ft_t_warn,
- "deleted data in segment %d/%d",
- buff->segment_id,
- FT_SECTOR(buff->sector_offset - 1));
- buff->remaining = 0; /* abort transfer */
- buff->hard_error_map = EMPTY_SEGMENT;
- skip = 1;
- } else {
- skip = 0;
- }
- continue_xfer(buff, fdc_mode, skip);
- break;
- case no_data_error:
- no_data_error_count ++;
- case overrun_error:
- retry ++;
- case id_am_error:
- case id_crc_error:
- case data_am_error:
- case data_crc_error:
- determine_verify_progress(buff, cause, in[5]);
- if (cause == no_data_error) {
- if (no_data_error_count >= 2) {
- TRACE(ft_t_warn,
- "retrying because of successive "
- "no data errors");
- no_data_error_count = 0;
- } else {
- retry --;
- }
- } else {
- no_data_error_count = 0;
- }
- if (retry) {
- skip = find_resume_point(buff);
- } else {
- skip = buff->sector_offset;
- }
- if (retry && skip < 32) {
- retry_sector(buff, fdc_mode, skip);
- } else {
- continue_xfer(buff, fdc_mode, skip);
- }
- update_history(cause);
- break;
- default:
- /* Don't know why this could happen
- * but find out.
- */
- determine_verify_progress(buff, cause, in[5]);
- retry_sector(buff, fdc_mode, 0);
- TRACE(ft_t_err, "Error: unexpected error");
- break;
- }
- break;
- case fdc_reading_data:
-#ifdef TESTING
- /* I'm sorry, but: NOBODY ever used this trace
- * messages for ages. I guess that Bas was the last person
- * that ever really used this (thank you, between the lines)
- */
- if (cause == no_error) {
- TRACE(ft_t_flow,"reading segment %d",buff->segment_id);
- } else {
- TRACE(ft_t_noise, "error reading segment %d",
- buff->segment_id);
- TRACE(ft_t_noise, "\n"
- KERN_INFO
- "IRQ:C: 0x%02x, H: 0x%02x, R: 0x%02x, N: 0x%02x\n"
- KERN_INFO
- "BUF:C: 0x%02x, H: 0x%02x, R: 0x%02x",
- in[3], in[4], in[5], in[6],
- buff->cyl, buff->head, buff->sect);
- }
-#endif
- if (ft_runner_status == aborting ||
- ft_runner_status == do_abort) {
- TRACE(ft_t_noise,"aborting %s",fdc_mode_txt(fdc_mode));
- break;
- }
- if (buff->bad_sector_map == FAKE_SEGMENT) {
- /* This condition occurs when reading a `fake'
- * sector that's not accessible. Doesn't
- * really matter as we would have ignored it
- * anyway !
- *
- * Chance is that we're past the next segment
- * now, so the next operation may fail and
- * result in a retry.
- */
- buff->remaining = 0; /* skip failing sector */
- /* buff->ptr = buff->address; */
- /* fake success: */
- continue_xfer(buff, fdc_mode, 1);
- /* trace calls are expensive: place them AFTER
- * the real stuff has been done.
- *
- */
- TRACE(ft_t_noise, "skipping empty segment %d (read), size? %d",
- buff->segment_id, buff->ptr - buff->address);
- TRACE_EXIT;
- }
- if (buff->retry > 0) {
- TRACE(ft_t_flow, "this is retry nr %d", buff->retry);
- }
- switch (cause) {
- case no_error:
- determine_progress(buff, cause, in[5]);
- if (in[2] & 0x40) {
- /* Handle deleted data in header segments.
- * Skip segment and force read-ahead.
- */
- TRACE(ft_t_warn,
- "deleted data in segment %d/%d",
- buff->segment_id,
- FT_SECTOR(buff->sector_offset - 1));
- buff->deleted = 1;
- buff->remaining = 0;/*abort transfer */
- buff->soft_error_map |=
- (-1L << buff->sector_offset);
- if (buff->segment_id == 0) {
- /* stop on next segment */
- stop_read_ahead = 1;
- }
- /* force read-ahead: */
- buff->next_segment =
- buff->segment_id + 1;
- skip = (FT_SECTORS_PER_SEGMENT -
- buff->sector_offset);
- } else {
- skip = 0;
- }
- continue_xfer(buff, fdc_mode, skip);
- break;
- case no_data_error:
- /* Tape started too far ahead of or behind the
- * right sector. This may also happen in the
- * middle of a segment !
- *
- * Handle no-data as soft error. If next
- * sector fails too, a retry (with needed
- * reposition) will follow.
- */
- retry ++;
- case id_am_error:
- case id_crc_error:
- case data_am_error:
- case data_crc_error:
- case overrun_error:
- retry += (buff->soft_error_map != 0 ||
- buff->hard_error_map != 0);
- determine_progress(buff, cause, in[5]);
-#if 1 || defined(TESTING)
- if (cause == overrun_error) retry ++;
-#endif
- if (retry) {
- skip = find_resume_point(buff);
- } else {
- skip = buff->sector_offset;
- }
- /* Try to resume with next sector on single
- * errors (let ecc correct it), but retry on
- * no_data (we'll be past the target when we
- * get here so we cannot retry) or on
- * multiple errors (reduce chance on ecc
- * failure).
- */
- /* cH: 23/02/97: if the last sector in the
- * segment was a hard error, then there is
- * no sense in a retry. This occasion seldom
- * occurs but ... @:³²¸`@%&§$
- */
- if (retry && skip < 32) {
- retry_sector(buff, fdc_mode, skip);
- } else {
- continue_xfer(buff, fdc_mode, skip);
- }
- update_history(cause);
- break;
- default:
- /* Don't know why this could happen
- * but find out.
- */
- determine_progress(buff, cause, in[5]);
- retry_sector(buff, fdc_mode, 0);
- TRACE(ft_t_err, "Error: unexpected error");
- break;
- }
- break;
- case fdc_reading_id:
- if (cause == no_error) {
- fdc_cyl = in[3];
- fdc_head = in[4];
- fdc_sect = in[5];
- TRACE(ft_t_fdc_dma,
- "id read: C: 0x%02x, H: 0x%02x, R: 0x%02x",
- fdc_cyl, fdc_head, fdc_sect);
- } else { /* no valid information, use invalid sector */
- fdc_cyl = fdc_head = fdc_sect = 0;
- TRACE(ft_t_flow, "Didn't find valid sector Id");
- }
- fdc_mode = fdc_idle;
- break;
- case fdc_deleting:
- case fdc_writing_data:
-#ifdef TESTING
- if (cause == no_error) {
- TRACE(ft_t_flow, "writing segment %d", buff->segment_id);
- } else {
- TRACE(ft_t_noise, "error writing segment %d",
- buff->segment_id);
- }
-#endif
- if (ft_runner_status == aborting ||
- ft_runner_status == do_abort) {
- TRACE(ft_t_flow, "aborting %s",fdc_mode_txt(fdc_mode));
- break;
- }
- if (buff->retry > 0) {
- TRACE(ft_t_flow, "this is retry nr %d", buff->retry);
- }
- if (buff->bad_sector_map == FAKE_SEGMENT) {
- /* This condition occurs when trying to write to a
- * `fake' sector that's not accessible. Doesn't really
- * matter as it isn't used anyway ! Might be located
- * at wrong segment, then we'll fail on the next
- * segment.
- */
- TRACE(ft_t_noise, "skipping empty segment (write)");
- buff->remaining = 0; /* skip failing sector */
- /* fake success: */
- continue_xfer(buff, fdc_mode, 1);
- break;
- }
- switch (cause) {
- case no_error:
- determine_progress(buff, cause, in[5]);
- continue_xfer(buff, fdc_mode, 0);
- break;
- case no_data_error:
- case id_am_error:
- case id_crc_error:
- case data_am_error:
- case overrun_error:
- update_history(cause);
- determine_progress(buff, cause, in[5]);
- skip = find_resume_point(buff);
- retry_sector(buff, fdc_mode, skip);
- break;
- default:
- if (in[1] & 0x02) {
- TRACE(ft_t_err, "media not writable");
- } else {
- TRACE(ft_t_bug, "unforeseen write error");
- }
- fdc_mode = fdc_idle;
- break;
- }
- break; /* fdc_deleting || fdc_writing_data */
- case fdc_formatting:
- /* The interrupt comes after formatting a segment. We then
- * have to set up QUICKLY for the next segment. But
- * afterwards, there is plenty of time.
- */
- switch (cause) {
- case no_error:
- /* would like to keep most of the formatting stuff
- * outside the isr code, but timing is too critical
- */
- if (determine_fmt_progress(buff, cause) >= 0) {
- continue_formatting(buff);
- }
- break;
- case no_data_error:
- case id_am_error:
- case id_crc_error:
- case data_am_error:
- case overrun_error:
- default:
- determine_fmt_progress(buff, cause);
- update_history(cause);
- if (in[1] & 0x02) {
- TRACE(ft_t_err, "media not writable");
- } else {
- TRACE(ft_t_bug, "unforeseen write error");
- }
- break;
- } /* cause */
- break;
- default:
- TRACE(ft_t_warn, "Warning: unexpected irq during: %s",
- fdc_mode_txt(fdc_mode));
- fdc_mode = fdc_idle;
- break;
- }
- TRACE_EXIT;
-}
-
-/* FDC interrupt service routine.
- */
-void fdc_isr(void)
-{
- static int isr_active;
-#ifdef TESTING
- unsigned int t0 = ftape_timestamp();
-#endif
- TRACE_FUN(ft_t_any);
-
- if (isr_active++) {
- --isr_active;
- TRACE(ft_t_bug, "BUG: nested interrupt, not good !");
- *fdc.hook = fdc_isr; /* hook our handler into the fdc
- * code again
- */
- TRACE_EXIT;
- }
- sti();
- if (inb_p(fdc.msr) & FDC_BUSY) { /* Entering Result Phase */
- ft_hide_interrupt = 0;
- handle_fdc_busy(ftape_get_buffer(ft_queue_head));
- if (ft_runner_status == do_abort) {
- /* cease operation, remember tape position
- */
- TRACE(ft_t_flow, "runner aborting");
- ft_runner_status = aborting;
- ++ft_expected_stray_interrupts;
- }
- } else { /* !FDC_BUSY */
- /* clear interrupt, cause should be gotten by issuing
- * a Sense Interrupt Status command.
- */
- if (fdc_mode == fdc_recalibrating || fdc_mode == fdc_seeking) {
- if (ft_hide_interrupt) {
- int st0;
- int pcn;
-
- if (fdc_sense_interrupt_status(&st0, &pcn) < 0)
- TRACE(ft_t_err,
- "sense interrupt status failed");
- ftape_current_cylinder = pcn;
- TRACE(ft_t_flow, "handled hidden interrupt");
- }
- ft_seek_completed = 1;
- fdc_mode = fdc_idle;
- } else if (!waitqueue_active(&ftape_wait_intr)) {
- if (ft_expected_stray_interrupts == 0) {
- TRACE(ft_t_warn, "unexpected stray interrupt");
- } else {
- TRACE(ft_t_flow, "expected stray interrupt");
- --ft_expected_stray_interrupts;
- }
- } else {
- if (fdc_mode == fdc_reading_data ||
- fdc_mode == fdc_verifying ||
- fdc_mode == fdc_writing_data ||
- fdc_mode == fdc_deleting ||
- fdc_mode == fdc_formatting ||
- fdc_mode == fdc_reading_id) {
- if (inb_p(fdc.msr) & FDC_BUSY) {
- TRACE(ft_t_bug,
- "***** FDC failure, busy too late");
- } else {
- TRACE(ft_t_bug,
- "***** FDC failure, no busy");
- }
- } else {
- TRACE(ft_t_fdc_dma, "awaited stray interrupt");
- }
- }
- ft_hide_interrupt = 0;
- }
- /* Handle sleep code.
- */
- if (!ft_hide_interrupt) {
- ft_interrupt_seen ++;
- if (waitqueue_active(&ftape_wait_intr)) {
- wake_up_interruptible(&ftape_wait_intr);
- }
- } else {
- TRACE(ft_t_flow, "hiding interrupt while %s",
- waitqueue_active(&ftape_wait_intr) ? "waiting":"active");
- }
-#ifdef TESTING
- t0 = ftape_timediff(t0, ftape_timestamp());
- if (t0 >= 1000) {
- /* only tell us about long calls */
- TRACE(ft_t_noise, "isr() duration: %5d usec", t0);
- }
-#endif
- *fdc.hook = fdc_isr; /* hook our handler into the fdc code again */
- --isr_active;
- TRACE_EXIT;
-}
diff --git a/drivers/char/ftape/lowlevel/fdc-isr.h b/drivers/char/ftape/lowlevel/fdc-isr.h
deleted file mode 100644
index 065aa978942d..000000000000
--- a/drivers/char/ftape/lowlevel/fdc-isr.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#ifndef _FDC_ISR_H
-#define _FDC_ISR_H
-
-/*
- * Copyright (C) 1993-1996 Bas Laarhoven,
- * (C) 1996-1997 Claus-Justus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/fdc-isr.h,v $
- * $Revision: 1.2 $
- * $Date: 1997/10/05 19:18:07 $
- *
- * This file declares the global variables necessary to
- * synchronize the interrupt service routine (isr) with the
- * remainder of the QIC-40/80/3010/3020 floppy-tape driver
- * "ftape" for Linux.
- */
-
-/*
- * fdc-isr.c defined public variables
- */
-extern volatile int ft_expected_stray_interrupts; /* masks stray interrupts */
-extern volatile int ft_seek_completed; /* flag set by isr */
-extern volatile int ft_interrupt_seen; /* flag set by isr */
-extern volatile int ft_hide_interrupt; /* flag set by isr */
-
-/*
- * fdc-io.c defined public functions
- */
-extern void fdc_isr(void);
-
-/*
- * A kernel hook that steals one interrupt from the floppy
- * driver (Should be fixed when the new fdc driver gets ready)
- * See the linux kernel source files:
- * drivers/block/floppy.c & drivers/block/blk.h
- * for the details.
- */
-extern void (*do_floppy) (void);
-
-#endif
diff --git a/drivers/char/ftape/lowlevel/ftape-bsm.c b/drivers/char/ftape/lowlevel/ftape-bsm.c
deleted file mode 100644
index d1a301cc344f..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-bsm.c
+++ /dev/null
@@ -1,491 +0,0 @@
-/*
- * Copyright (C) 1994-1996 Bas Laarhoven,
- * (C) 1996-1997 Claus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-bsm.c,v $
- * $Revision: 1.3 $
- * $Date: 1997/10/05 19:15:15 $
- *
- * This file contains the bad-sector map handling code for
- * the QIC-117 floppy tape driver for Linux.
- * QIC-40, QIC-80, QIC-3010 and QIC-3020 maps are implemented.
- */
-
-#include <linux/string.h>
-
-#include <linux/ftape.h>
-#include "../lowlevel/ftape-tracing.h"
-#include "../lowlevel/ftape-bsm.h"
-#include "../lowlevel/ftape-ctl.h"
-#include "../lowlevel/ftape-rw.h"
-
-/* Global vars.
- */
-
-/* Local vars.
- */
-static __u8 *bad_sector_map;
-static SectorCount *bsm_hash_ptr;
-
-typedef enum {
- forward, backward
-} mode_type;
-
-#if 0
-static void ftape_put_bad_sector_entry(int segment_id, SectorMap new_map);
-#endif
-
-#if 0
-/* fix_tape converts a normal QIC-80 tape into a 'wide' tape.
- * For testing purposes only !
- */
-void fix_tape(__u8 * buffer, ft_format_type new_code)
-{
- static __u8 list[BAD_SECTOR_MAP_SIZE];
- SectorMap *src_ptr = (SectorMap *) list;
- __u8 *dst_ptr = bad_sector_map;
- SectorMap map;
- unsigned int sector = 1;
- int i;
-
- if (format_code != fmt_var && format_code != fmt_big) {
- memcpy(list, bad_sector_map, sizeof(list));
- memset(bad_sector_map, 0, sizeof(bad_sector_map));
- while ((__u8 *) src_ptr - list < sizeof(list)) {
- map = *src_ptr++;
- if (map == EMPTY_SEGMENT) {
- *(SectorMap *) dst_ptr = 0x800000 + sector;
- dst_ptr += 3;
- sector += SECTORS_PER_SEGMENT;
- } else {
- for (i = 0; i < SECTORS_PER_SEGMENT; ++i) {
- if (map & 1) {
- *(SewctorMap *) dst_ptr = sector;
- dst_ptr += 3;
- }
- map >>= 1;
- ++sector;
- }
- }
- }
- }
- bad_sector_map_changed = 1;
- *(buffer + 4) = new_code; /* put new format code */
- if (format_code != fmt_var && new_code == fmt_big) {
- PUT4(buffer, FT_6_HSEG_1, (__u32)GET2(buffer, 6));
- PUT4(buffer, FT_6_HSEG_2, (__u32)GET2(buffer, 8));
- PUT4(buffer, FT_6_FRST_SEG, (__u32)GET2(buffer, 10));
- PUT4(buffer, FT_6_LAST_SEG, (__u32)GET2(buffer, 12));
- memset(buffer+6, '\0', 8);
- }
- format_code = new_code;
-}
-
-#endif
-
-/* given buffer that contains a header segment, find the end of
- * of the bsm list
- */
-__u8 * ftape_find_end_of_bsm_list(__u8 * address)
-{
- __u8 *ptr = address + FT_HEADER_END; /* start of bsm list */
- __u8 *limit = address + FT_SEGMENT_SIZE;
- while (ptr + 2 < limit) {
- if (ptr[0] || ptr[1] || ptr[2]) {
- ptr += 3;
- } else {
- return ptr;
- }
- }
- return NULL;
-}
-
-static inline void put_sector(SectorCount *ptr, unsigned int sector)
-{
- ptr->bytes[0] = sector & 0xff;
- sector >>= 8;
- ptr->bytes[1] = sector & 0xff;
- sector >>= 8;
- ptr->bytes[2] = sector & 0xff;
-}
-
-static inline unsigned int get_sector(SectorCount *ptr)
-{
-#if 1
- unsigned int sector;
-
- sector = ptr->bytes[0];
- sector += ptr->bytes[1] << 8;
- sector += ptr->bytes[2] << 16;
-
- return sector;
-#else
- /* GET4 gets the next four bytes in Intel little endian order
- * and converts them to host byte order and handles unaligned
- * access.
- */
- return (GET4(ptr, 0) & 0x00ffffff); /* back to host byte order */
-#endif
-}
-
-static void bsm_debug_fake(void)
-{
- /* for testing of bad sector handling at end of tape
- */
-#if 0
- ftape_put_bad_sector_entry(segments_per_track * tracks_per_tape - 3,
- 0x000003e0;
- ftape_put_bad_sector_entry(segments_per_track * tracks_per_tape - 2,
- 0xff3fffff;
- ftape_put_bad_sector_entry(segments_per_track * tracks_per_tape - 1,
- 0xffffe000;
-#endif
- /* Enable to test bad sector handling
- */
-#if 0
- ftape_put_bad_sector_entry(30, 0xfffffffe)
- ftape_put_bad_sector_entry(32, 0x7fffffff);
- ftape_put_bad_sector_entry(34, 0xfffeffff);
- ftape_put_bad_sector_entry(36, 0x55555555);
- ftape_put_bad_sector_entry(38, 0xffffffff);
- ftape_put_bad_sector_entry(50, 0xffff0000);
- ftape_put_bad_sector_entry(51, 0xffffffff);
- ftape_put_bad_sector_entry(52, 0xffffffff);
- ftape_put_bad_sector_entry(53, 0x0000ffff);
-#endif
- /* Enable when testing multiple volume tar dumps.
- */
-#if 0
- {
- int i;
-
- for (i = ft_first_data_segment;
- i <= ft_last_data_segment - 7; ++i) {
- ftape_put_bad_sector_entry(i, EMPTY_SEGMENT);
- }
- }
-#endif
- /* Enable when testing bit positions in *_error_map
- */
-#if 0
- {
- int i;
-
- for (i = first_data_segment; i <= last_data_segment; ++i) {
- ftape_put_bad_sector_entry(i,
- ftape_get_bad_sector_entry(i)
- | 0x00ff00ff);
- }
- }
-#endif
-}
-
-static void print_bad_sector_map(void)
-{
- unsigned int good_sectors;
- unsigned int total_bad = 0;
- int i;
- TRACE_FUN(ft_t_flow);
-
- if (ft_format_code == fmt_big ||
- ft_format_code == fmt_var ||
- ft_format_code == fmt_1100ft) {
- SectorCount *ptr = (SectorCount *)bad_sector_map;
- unsigned int sector;
- __u16 *ptr16;
-
- while((sector = get_sector(ptr++)) != 0) {
- if ((ft_format_code == fmt_big ||
- ft_format_code == fmt_var) &&
- sector & 0x800000) {
- total_bad += FT_SECTORS_PER_SEGMENT - 3;
- TRACE(ft_t_noise, "bad segment at sector: %6d",
- sector & 0x7fffff);
- } else {
- ++total_bad;
- TRACE(ft_t_noise, "bad sector: %6d", sector);
- }
- }
- /* Display old ftape's end-of-file marks
- */
- ptr16 = (__u16*)ptr;
- while ((sector = get_unaligned(ptr16++)) != 0) {
- TRACE(ft_t_noise, "Old ftape eof mark: %4d/%2d",
- sector, get_unaligned(ptr16++));
- }
- } else { /* fixed size format */
- for (i = ft_first_data_segment;
- i < (int)(ft_segments_per_track * ft_tracks_per_tape); ++i) {
- SectorMap map = ((SectorMap *) bad_sector_map)[i];
-
- if (map) {
- TRACE(ft_t_noise,
- "bsm for segment %4d: 0x%08x", i, (unsigned int)map);
- total_bad += ((map == EMPTY_SEGMENT)
- ? FT_SECTORS_PER_SEGMENT - 3
- : count_ones(map));
- }
- }
- }
- good_sectors =
- ((ft_segments_per_track * ft_tracks_per_tape - ft_first_data_segment)
- * (FT_SECTORS_PER_SEGMENT - 3)) - total_bad;
- TRACE(ft_t_info, "%d Kb usable on this tape", good_sectors);
- if (total_bad == 0) {
- TRACE(ft_t_info,
- "WARNING: this tape has no bad blocks registered !");
- } else {
- TRACE(ft_t_info, "%d bad sectors", total_bad);
- }
- TRACE_EXIT;
-}
-
-
-void ftape_extract_bad_sector_map(__u8 * buffer)
-{
- TRACE_FUN(ft_t_any);
-
- /* Fill the bad sector map with the contents of buffer.
- */
- if (ft_format_code == fmt_var || ft_format_code == fmt_big) {
- /* QIC-3010/3020 and wide QIC-80 tapes no longer have a failed
- * sector log but use this area to extend the bad sector map.
- */
- bad_sector_map = &buffer[FT_HEADER_END];
- } else {
- /* non-wide QIC-80 tapes have a failed sector log area that
- * mustn't be included in the bad sector map.
- */
- bad_sector_map = &buffer[FT_FSL + FT_FSL_SIZE];
- }
- if (ft_format_code == fmt_1100ft ||
- ft_format_code == fmt_var ||
- ft_format_code == fmt_big) {
- bsm_hash_ptr = (SectorCount *)bad_sector_map;
- } else {
- bsm_hash_ptr = NULL;
- }
- bsm_debug_fake();
- if (TRACE_LEVEL >= ft_t_info) {
- print_bad_sector_map();
- }
- TRACE_EXIT;
-}
-
-static inline SectorMap cvt2map(unsigned int sector)
-{
- return 1 << (((sector & 0x7fffff) - 1) % FT_SECTORS_PER_SEGMENT);
-}
-
-static inline int cvt2segment(unsigned int sector)
-{
- return ((sector & 0x7fffff) - 1) / FT_SECTORS_PER_SEGMENT;
-}
-
-static int forward_seek_entry(int segment_id,
- SectorCount **ptr,
- SectorMap *map)
-{
- unsigned int sector;
- int segment;
-
- do {
- sector = get_sector((*ptr)++);
- segment = cvt2segment(sector);
- } while (sector != 0 && segment < segment_id);
- (*ptr) --; /* point to first sector >= segment_id */
- /* Get all sectors in segment_id
- */
- if (sector == 0 || segment != segment_id) {
- *map = 0;
- return 0;
- } else if ((sector & 0x800000) &&
- (ft_format_code == fmt_var || ft_format_code == fmt_big)) {
- *map = EMPTY_SEGMENT;
- return FT_SECTORS_PER_SEGMENT;
- } else {
- int count = 1;
- SectorCount *tmp_ptr = (*ptr) + 1;
-
- *map = cvt2map(sector);
- while ((sector = get_sector(tmp_ptr++)) != 0 &&
- (segment = cvt2segment(sector)) == segment_id) {
- *map |= cvt2map(sector);
- ++count;
- }
- return count;
- }
-}
-
-static int backwards_seek_entry(int segment_id,
- SectorCount **ptr,
- SectorMap *map)
-{
- unsigned int sector;
- int segment; /* max unsigned int */
-
- if (*ptr <= (SectorCount *)bad_sector_map) {
- *map = 0;
- return 0;
- }
- do {
- sector = get_sector(--(*ptr));
- segment = cvt2segment(sector);
- } while (*ptr > (SectorCount *)bad_sector_map && segment > segment_id);
- if (segment > segment_id) { /* at start of list, no entry found */
- *map = 0;
- return 0;
- } else if (segment < segment_id) {
- /* before smaller entry, adjust for overshoot */
- (*ptr) ++;
- *map = 0;
- return 0;
- } else if ((sector & 0x800000) &&
- (ft_format_code == fmt_big || ft_format_code == fmt_var)) {
- *map = EMPTY_SEGMENT;
- return FT_SECTORS_PER_SEGMENT;
- } else { /* get all sectors in segment_id */
- int count = 1;
-
- *map = cvt2map(sector);
- while(*ptr > (SectorCount *)bad_sector_map) {
- sector = get_sector(--(*ptr));
- segment = cvt2segment(sector);
- if (segment != segment_id) {
- break;
- }
- *map |= cvt2map(sector);
- ++count;
- }
- if (segment < segment_id) {
- (*ptr) ++;
- }
- return count;
- }
-}
-
-#if 0
-static void ftape_put_bad_sector_entry(int segment_id, SectorMap new_map)
-{
- SectorCount *ptr = (SectorCount *)bad_sector_map;
- int count;
- int new_count;
- SectorMap map;
- TRACE_FUN(ft_t_any);
-
- if (ft_format_code == fmt_1100ft ||
- ft_format_code == fmt_var ||
- ft_format_code == fmt_big) {
- count = forward_seek_entry(segment_id, &ptr, &map);
- new_count = count_ones(new_map);
- /* If format code == 4 put empty segment instead of 32
- * bad sectors.
- */
- if (ft_format_code == fmt_var || ft_format_code == fmt_big) {
- if (new_count == FT_SECTORS_PER_SEGMENT) {
- new_count = 1;
- }
- if (count == FT_SECTORS_PER_SEGMENT) {
- count = 1;
- }
- }
- if (count != new_count) {
- /* insert (or delete if < 0) new_count - count
- * entries. Move trailing part of list
- * including terminating 0.
- */
- SectorCount *hi_ptr = ptr;
-
- do {
- } while (get_sector(hi_ptr++) != 0);
- /* Note: ptr is of type byte *, and each bad sector
- * consumes 3 bytes.
- */
- memmove(ptr + new_count, ptr + count,
- (size_t)(hi_ptr - (ptr + count))*sizeof(SectorCount));
- }
- TRACE(ft_t_noise, "putting map 0x%08x at %p, segment %d",
- (unsigned int)new_map, ptr, segment_id);
- if (new_count == 1 && new_map == EMPTY_SEGMENT) {
- put_sector(ptr++, (0x800001 +
- segment_id *
- FT_SECTORS_PER_SEGMENT));
- } else {
- int i = 0;
-
- while (new_map) {
- if (new_map & 1) {
- put_sector(ptr++,
- 1 + segment_id *
- FT_SECTORS_PER_SEGMENT + i);
- }
- ++i;
- new_map >>= 1;
- }
- }
- } else {
- ((SectorMap *) bad_sector_map)[segment_id] = new_map;
- }
- TRACE_EXIT;
-}
-#endif /* 0 */
-
-SectorMap ftape_get_bad_sector_entry(int segment_id)
-{
- if (ft_used_header_segment == -1) {
- /* When reading header segment we'll need a blank map.
- */
- return 0;
- } else if (bsm_hash_ptr != NULL) {
- /* Invariants:
- * map - mask value returned on last call.
- * bsm_hash_ptr - points to first sector greater or equal to
- * first sector in last_referenced segment.
- * last_referenced - segment id used in the last call,
- * sector and map belong to this id.
- * This code is designed for sequential access and retries.
- * For true random access it may have to be redesigned.
- */
- static int last_reference = -1;
- static SectorMap map;
-
- if (segment_id > last_reference) {
- /* Skip all sectors before segment_id
- */
- forward_seek_entry(segment_id, &bsm_hash_ptr, &map);
- } else if (segment_id < last_reference) {
- /* Skip backwards until begin of buffer or
- * first sector in segment_id
- */
- backwards_seek_entry(segment_id, &bsm_hash_ptr, &map);
- } /* segment_id == last_reference : keep map */
- last_reference = segment_id;
- return map;
- } else {
- return ((SectorMap *) bad_sector_map)[segment_id];
- }
-}
-
-/* This is simply here to prevent us from overwriting other kernel
- * data. Writes will result in NULL Pointer dereference.
- */
-void ftape_init_bsm(void)
-{
- bad_sector_map = NULL;
- bsm_hash_ptr = NULL;
-}
diff --git a/drivers/char/ftape/lowlevel/ftape-bsm.h b/drivers/char/ftape/lowlevel/ftape-bsm.h
deleted file mode 100644
index ed45465af4d4..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-bsm.h
+++ /dev/null
@@ -1,66 +0,0 @@
-#ifndef _FTAPE_BSM_H
-#define _FTAPE_BSM_H
-
-/*
- * Copyright (C) 1994-1996 Bas Laarhoven,
- * (C) 1996-1997 Claus-Justus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-bsm.h,v $
- * $Revision: 1.2 $
- * $Date: 1997/10/05 19:18:07 $
- *
- * This file contains definitions for the bad sector map handling
- * routines for the QIC-117 floppy-tape driver for Linux.
- */
-
-#include <linux/ftape.h>
-#include <linux/ftape-header-segment.h>
-
-#define EMPTY_SEGMENT (0xffffffff)
-#define FAKE_SEGMENT (0xfffffffe)
-
-/* maximum (format code 4) bad sector map size (bytes).
- */
-#define BAD_SECTOR_MAP_SIZE (29 * SECTOR_SIZE - 256)
-
-/* format code 4 bad sector entry, ftape uses this
- * internally for all format codes
- */
-typedef __u32 SectorMap;
-/* variable and 1100 ft bad sector map entry. These three bytes represent
- * a single sector address measured from BOT.
- */
-typedef struct NewSectorMap {
- __u8 bytes[3];
-} SectorCount;
-
-
-/*
- * ftape-bsm.c defined global vars.
- */
-
-/*
- * ftape-bsm.c defined global functions.
- */
-extern void update_bad_sector_map(__u8 * buffer);
-extern void ftape_extract_bad_sector_map(__u8 * buffer);
-extern SectorMap ftape_get_bad_sector_entry(int segment_id);
-extern __u8 *ftape_find_end_of_bsm_list(__u8 * address);
-extern void ftape_init_bsm(void);
-
-#endif
diff --git a/drivers/char/ftape/lowlevel/ftape-buffer.c b/drivers/char/ftape/lowlevel/ftape-buffer.c
deleted file mode 100644
index c706ff162771..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-buffer.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (C) 1997 Claus-Justus Heine
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-buffer.c,v $
- * $Revision: 1.3 $
- * $Date: 1997/10/16 23:33:11 $
- *
- * This file contains the allocator/dealloctor for ftape's dynamic dma
- * buffer.
- */
-
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/mman.h>
-#include <asm/dma.h>
-
-#include <linux/ftape.h>
-#include "../lowlevel/ftape-rw.h"
-#include "../lowlevel/ftape-read.h"
-#include "../lowlevel/ftape-tracing.h"
-#include "../lowlevel/ftape-buffer.h"
-
-/* DMA'able memory allocation stuff.
- */
-
-static inline void *dmaalloc(size_t size)
-{
- unsigned long addr;
-
- if (size == 0) {
- return NULL;
- }
- addr = __get_dma_pages(GFP_KERNEL, get_order(size));
- if (addr) {
- struct page *page;
-
- for (page = virt_to_page(addr); page < virt_to_page(addr+size); page++)
- SetPageReserved(page);
- }
- return (void *)addr;
-}
-
-static inline void dmafree(void *addr, size_t size)
-{
- if (size > 0) {
- struct page *page;
-
- for (page = virt_to_page((unsigned long)addr);
- page < virt_to_page((unsigned long)addr+size); page++)
- ClearPageReserved(page);
- free_pages((unsigned long) addr, get_order(size));
- }
-}
-
-static int add_one_buffer(void)
-{
- TRACE_FUN(ft_t_flow);
-
- if (ft_nr_buffers >= FT_MAX_NR_BUFFERS) {
- TRACE_EXIT -ENOMEM;
- }
- ft_buffer[ft_nr_buffers] = kmalloc(sizeof(buffer_struct), GFP_KERNEL);
- if (ft_buffer[ft_nr_buffers] == NULL) {
- TRACE_EXIT -ENOMEM;
- }
- memset(ft_buffer[ft_nr_buffers], 0, sizeof(buffer_struct));
- ft_buffer[ft_nr_buffers]->address = dmaalloc(FT_BUFF_SIZE);
- if (ft_buffer[ft_nr_buffers]->address == NULL) {
- kfree(ft_buffer[ft_nr_buffers]);
- ft_buffer[ft_nr_buffers] = NULL;
- TRACE_EXIT -ENOMEM;
- }
- ft_nr_buffers ++;
- TRACE(ft_t_info, "buffer nr #%d @ %p, dma area @ %p",
- ft_nr_buffers,
- ft_buffer[ft_nr_buffers-1],
- ft_buffer[ft_nr_buffers-1]->address);
- TRACE_EXIT 0;
-}
-
-static void del_one_buffer(void)
-{
- TRACE_FUN(ft_t_flow);
- if (ft_nr_buffers > 0) {
- TRACE(ft_t_info, "releasing buffer nr #%d @ %p, dma area @ %p",
- ft_nr_buffers,
- ft_buffer[ft_nr_buffers-1],
- ft_buffer[ft_nr_buffers-1]->address);
- ft_nr_buffers --;
- dmafree(ft_buffer[ft_nr_buffers]->address, FT_BUFF_SIZE);
- kfree(ft_buffer[ft_nr_buffers]);
- ft_buffer[ft_nr_buffers] = NULL;
- }
- TRACE_EXIT;
-}
-
-int ftape_set_nr_buffers(int cnt)
-{
- int delta = cnt - ft_nr_buffers;
- TRACE_FUN(ft_t_flow);
-
- if (delta > 0) {
- while (delta--) {
- if (add_one_buffer() < 0) {
- TRACE_EXIT -ENOMEM;
- }
- }
- } else if (delta < 0) {
- while (delta++) {
- del_one_buffer();
- }
- }
- ftape_zap_read_buffers();
- TRACE_EXIT 0;
-}
diff --git a/drivers/char/ftape/lowlevel/ftape-buffer.h b/drivers/char/ftape/lowlevel/ftape-buffer.h
deleted file mode 100644
index eec99cee8f82..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-buffer.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef _FTAPE_BUFFER_H
-#define _FTAPE_BUFFER_H
-
-/*
- * Copyright (C) 1997 Claus-Justus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-buffer.h,v $
- * $Revision: 1.2 $
- * $Date: 1997/10/05 19:18:08 $
- *
- * This file contains the allocator/dealloctor for ftape's dynamic dma
- * buffer.
- */
-
-extern int ftape_set_nr_buffers(int cnt);
-
-#endif
diff --git a/drivers/char/ftape/lowlevel/ftape-calibr.c b/drivers/char/ftape/lowlevel/ftape-calibr.c
deleted file mode 100644
index 8e50bfd35a52..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-calibr.c
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * Copyright (C) 1993-1996 Bas Laarhoven.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-calibr.c,v $
- * $Revision: 1.2 $
- * $Date: 1997/10/05 19:18:08 $
- *
- * GP calibration routine for processor speed dependent
- * functions.
- */
-
-#include <linux/errno.h>
-#include <linux/jiffies.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#if defined(__alpha__)
-# include <asm/hwrpb.h>
-#elif defined(__x86_64__)
-# include <asm/msr.h>
-# include <asm/timex.h>
-#elif defined(__i386__)
-# include <linux/timex.h>
-#endif
-#include <linux/ftape.h>
-#include "../lowlevel/ftape-tracing.h"
-#include "../lowlevel/ftape-calibr.h"
-#include "../lowlevel/fdc-io.h"
-
-#undef DEBUG
-
-#if !defined(__alpha__) && !defined(__i386__) && !defined(__x86_64__)
-# error Ftape is not implemented for this architecture!
-#endif
-
-#if defined(__alpha__) || defined(__x86_64__)
-static unsigned long ps_per_cycle = 0;
-#endif
-
-static spinlock_t calibr_lock;
-
-/*
- * Note: On Intel PCs, the clock ticks at 100 Hz (HZ==100) which is
- * too slow for certain timeouts (and that clock doesn't even tick
- * when interrupts are disabled). For that reason, the 8254 timer is
- * used directly to implement fine-grained timeouts. However, on
- * Alpha PCs, the 8254 is *not* used to implement the clock tick
- * (which is 1024 Hz, normally) and the 8254 timer runs at some
- * "random" frequency (it seems to run at 18Hz, but it's not safe to
- * rely on this value). Instead, we use the Alpha's "rpcc"
- * instruction to read cycle counts. As this is a 32 bit counter,
- * it will overflow only once per 30 seconds (on a 200MHz machine),
- * which is plenty.
- */
-
-unsigned int ftape_timestamp(void)
-{
-#if defined(__alpha__)
- unsigned long r;
-
- asm volatile ("rpcc %0" : "=r" (r));
- return r;
-#elif defined(__x86_64__)
- unsigned long r;
- rdtscl(r);
- return r;
-#elif defined(__i386__)
-
-/*
- * Note that there is some time between counter underflowing and jiffies
- * increasing, so the code below won't always give correct output.
- * -Vojtech
- */
-
- unsigned long flags;
- __u16 lo;
- __u16 hi;
-
- spin_lock_irqsave(&calibr_lock, flags);
- outb_p(0x00, 0x43); /* latch the count ASAP */
- lo = inb_p(0x40); /* read the latched count */
- lo |= inb(0x40) << 8;
- hi = jiffies;
- spin_unlock_irqrestore(&calibr_lock, flags);
- return ((hi + 1) * (unsigned int) LATCH) - lo; /* downcounter ! */
-#endif
-}
-
-static unsigned int short_ftape_timestamp(void)
-{
-#if defined(__alpha__) || defined(__x86_64__)
- return ftape_timestamp();
-#elif defined(__i386__)
- unsigned int count;
- unsigned long flags;
-
- spin_lock_irqsave(&calibr_lock, flags);
- outb_p(0x00, 0x43); /* latch the count ASAP */
- count = inb_p(0x40); /* read the latched count */
- count |= inb(0x40) << 8;
- spin_unlock_irqrestore(&calibr_lock, flags);
- return (LATCH - count); /* normal: downcounter */
-#endif
-}
-
-static unsigned int diff(unsigned int t0, unsigned int t1)
-{
-#if defined(__alpha__) || defined(__x86_64__)
- return (t1 - t0);
-#elif defined(__i386__)
- /*
- * This is tricky: to work for both short and full ftape_timestamps
- * we'll have to discriminate between these.
- * If it _looks_ like short stamps with wrapping around we'll
- * asume it are. This will generate a small error if it really
- * was a (very large) delta from full ftape_timestamps.
- */
- return (t1 <= t0 && t0 <= LATCH) ? t1 + LATCH - t0 : t1 - t0;
-#endif
-}
-
-static unsigned int usecs(unsigned int count)
-{
-#if defined(__alpha__) || defined(__x86_64__)
- return (ps_per_cycle * count) / 1000000UL;
-#elif defined(__i386__)
- return (10000 * count) / ((CLOCK_TICK_RATE + 50) / 100);
-#endif
-}
-
-unsigned int ftape_timediff(unsigned int t0, unsigned int t1)
-{
- /*
- * Calculate difference in usec for ftape_timestamp results t0 & t1.
- * Note that on the i386 platform with short time-stamps, the
- * maximum allowed timespan is 1/HZ or we'll lose ticks!
- */
- return usecs(diff(t0, t1));
-}
-
-/* To get an indication of the I/O performance,
- * measure the duration of the inb() function.
- */
-static void time_inb(void)
-{
- int i;
- int t0, t1;
- unsigned long flags;
- int status;
- TRACE_FUN(ft_t_any);
-
- spin_lock_irqsave(&calibr_lock, flags);
- t0 = short_ftape_timestamp();
- for (i = 0; i < 1000; ++i) {
- status = inb(fdc.msr);
- }
- t1 = short_ftape_timestamp();
- spin_unlock_irqrestore(&calibr_lock, flags);
- TRACE(ft_t_info, "inb() duration: %d nsec", ftape_timediff(t0, t1));
- TRACE_EXIT;
-}
-
-static void init_clock(void)
-{
- TRACE_FUN(ft_t_any);
-
-#if defined(__x86_64__)
- ps_per_cycle = 1000000000UL / cpu_khz;
-#elif defined(__alpha__)
- extern struct hwrpb_struct *hwrpb;
- ps_per_cycle = (1000*1000*1000*1000UL) / hwrpb->cycle_freq;
-#endif
- TRACE_EXIT;
-}
-
-/*
- * Input: function taking int count as parameter.
- * pointers to calculated calibration variables.
- */
-void ftape_calibrate(char *name,
- void (*fun) (unsigned int),
- unsigned int *calibr_count,
- unsigned int *calibr_time)
-{
- static int first_time = 1;
- int i;
- unsigned int tc = 0;
- unsigned int count;
- unsigned int time;
-#if defined(__i386__)
- unsigned int old_tc = 0;
- unsigned int old_count = 1;
- unsigned int old_time = 1;
-#endif
- TRACE_FUN(ft_t_flow);
-
- if (first_time) { /* get idea of I/O performance */
- init_clock();
- time_inb();
- first_time = 0;
- }
- /* value of timeout must be set so that on very slow systems
- * it will give a time less than one jiffy, and on
- * very fast systems it'll give reasonable precision.
- */
-
- count = 40;
- for (i = 0; i < 15; ++i) {
- unsigned int t0;
- unsigned int t1;
- unsigned int once;
- unsigned int multiple;
- unsigned long flags;
-
- *calibr_count =
- *calibr_time = count; /* set TC to 1 */
- spin_lock_irqsave(&calibr_lock, flags);
- fun(0); /* dummy, get code into cache */
- t0 = short_ftape_timestamp();
- fun(0); /* overhead + one test */
- t1 = short_ftape_timestamp();
- once = diff(t0, t1);
- t0 = short_ftape_timestamp();
- fun(count); /* overhead + count tests */
- t1 = short_ftape_timestamp();
- multiple = diff(t0, t1);
- spin_unlock_irqrestore(&calibr_lock, flags);
- time = ftape_timediff(0, multiple - once);
- tc = (1000 * time) / (count - 1);
- TRACE(ft_t_any, "once:%3d us,%6d times:%6d us, TC:%5d ns",
- usecs(once), count - 1, usecs(multiple), tc);
-#if defined(__alpha__) || defined(__x86_64__)
- /*
- * Increase the calibration count exponentially until the
- * calibration time exceeds 100 ms.
- */
- if (time >= 100*1000) {
- break;
- }
-#elif defined(__i386__)
- /*
- * increase the count until the resulting time nears 2/HZ,
- * then the tc will drop sharply because we lose LATCH counts.
- */
- if (tc <= old_tc / 2) {
- time = old_time;
- count = old_count;
- break;
- }
- old_tc = tc;
- old_count = count;
- old_time = time;
-#endif
- count *= 2;
- }
- *calibr_count = count - 1;
- *calibr_time = time;
- TRACE(ft_t_info, "TC for `%s()' = %d nsec (at %d counts)",
- name, (1000 * *calibr_time) / *calibr_count, *calibr_count);
- TRACE_EXIT;
-}
diff --git a/drivers/char/ftape/lowlevel/ftape-calibr.h b/drivers/char/ftape/lowlevel/ftape-calibr.h
deleted file mode 100644
index 0c7e75246c7d..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-calibr.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef _FTAPE_CALIBR_H
-#define _FTAPE_CALIBR_H
-
-/*
- * Copyright (C) 1993-1996 Bas Laarhoven.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-calibr.h,v $
- * $Revision: 1.1 $
- * $Date: 1997/09/19 09:05:26 $
- *
- * This file contains a gp calibration routine for
- * hardware dependent timeout functions.
- */
-
-extern void ftape_calibrate(char *name,
- void (*fun) (unsigned int),
- unsigned int *calibr_count,
- unsigned int *calibr_time);
-extern unsigned int ftape_timestamp(void);
-extern unsigned int ftape_timediff(unsigned int t0, unsigned int t1);
-
-#endif /* _FTAPE_CALIBR_H */
diff --git a/drivers/char/ftape/lowlevel/ftape-ctl.c b/drivers/char/ftape/lowlevel/ftape-ctl.c
deleted file mode 100644
index 5d7c1ce92d59..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-ctl.c
+++ /dev/null
@@ -1,896 +0,0 @@
-/*
- * Copyright (C) 1993-1996 Bas Laarhoven,
- * 1996-1997 Claus-Justus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-ctl.c,v $
- * $Revision: 1.4 $
- * $Date: 1997/11/11 14:37:44 $
- *
- * This file contains the non-read/write ftape functions for the
- * QIC-40/80/3010/3020 floppy-tape driver "ftape" for Linux.
- */
-
-#include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/mman.h>
-
-#include <linux/ftape.h>
-#include <linux/qic117.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-
-/* ease porting between pre-2.4.x and later kernels */
-#define vma_get_pgoff(v) ((v)->vm_pgoff)
-
-#include "../lowlevel/ftape-tracing.h"
-#include "../lowlevel/ftape-io.h"
-#include "../lowlevel/ftape-ctl.h"
-#include "../lowlevel/ftape-write.h"
-#include "../lowlevel/ftape-read.h"
-#include "../lowlevel/ftape-rw.h"
-#include "../lowlevel/ftape-bsm.h"
-
-/* Global vars.
- */
-ftape_info ftape_status = {
-/* vendor information */
- { 0, }, /* drive type */
-/* data rates */
- 500, /* used data rate */
- 500, /* drive max rate */
- 500, /* fdc max rate */
-/* drive selection, either FTAPE_SEL_A/B/C/D */
- -1, /* drive selection */
-/* flags set after decode the drive and tape status */
- 0, /* formatted */
- 1, /* no tape */
- 1, /* write protected */
- 1, /* new tape */
-/* values of last queried drive/tape status and error */
- {{0,}}, /* last error code */
- {{0,}}, /* drive status, configuration, tape status */
-/* cartridge geometry */
- 20, /* tracks_per_tape */
- 102, /* segments_per_track */
-/* location of header segments, etc. */
- -1, /* used_header_segment */
- -1, /* header_segment_1 */
- -1, /* header_segment_2 */
- -1, /* first_data_segment */
- -1, /* last_data_segment */
-/* the format code as stored in the header segment */
- fmt_normal, /* format code */
-/* the default for the qic std: unknown */
- -1,
-/* is tape running? */
- idle, /* runner_state */
-/* is tape reading/writing/verifying/formatting/deleting */
- idle, /* driver state */
-/* flags fatal hardware error */
- 1, /* failure */
-/* history record */
- { 0, } /* history record */
-};
-
-int ftape_segments_per_head = 1020;
-int ftape_segments_per_cylinder = 4;
-int ftape_init_drive_needed = 1; /* need to be global for ftape_reset_drive()
- * in ftape-io.c
- */
-
-/* Local vars.
- */
-static const vendor_struct vendors[] = QIC117_VENDORS;
-static const wakeup_method methods[] = WAKEUP_METHODS;
-
-const ftape_info *ftape_get_status(void)
-{
-#if defined(STATUS_PARANOYA)
- static ftape_info get_status;
-
- get_status = ftape_status;
- return &get_status;
-#else
- return &ftape_status; /* maybe return only a copy of it to assure
- * read only access
- */
-#endif
-}
-
-static int ftape_not_operational(int status)
-{
- /* return true if status indicates tape can not be used.
- */
- return ((status ^ QIC_STATUS_CARTRIDGE_PRESENT) &
- (QIC_STATUS_ERROR |
- QIC_STATUS_CARTRIDGE_PRESENT |
- QIC_STATUS_NEW_CARTRIDGE));
-}
-
-int ftape_seek_to_eot(void)
-{
- int status;
- TRACE_FUN(ft_t_any);
-
- TRACE_CATCH(ftape_ready_wait(ftape_timeout.pause, &status),);
- while ((status & QIC_STATUS_AT_EOT) == 0) {
- if (ftape_not_operational(status)) {
- TRACE_EXIT -EIO;
- }
- TRACE_CATCH(ftape_command_wait(QIC_PHYSICAL_FORWARD,
- ftape_timeout.rewind,&status),);
- }
- TRACE_EXIT 0;
-}
-
-int ftape_seek_to_bot(void)
-{
- int status;
- TRACE_FUN(ft_t_any);
-
- TRACE_CATCH(ftape_ready_wait(ftape_timeout.pause, &status),);
- while ((status & QIC_STATUS_AT_BOT) == 0) {
- if (ftape_not_operational(status)) {
- TRACE_EXIT -EIO;
- }
- TRACE_CATCH(ftape_command_wait(QIC_PHYSICAL_REVERSE,
- ftape_timeout.rewind,&status),);
- }
- TRACE_EXIT 0;
-}
-
-static int ftape_new_cartridge(void)
-{
- ft_location.track = -1; /* force seek on first access */
- ftape_zap_read_buffers();
- ftape_zap_write_buffers();
- return 0;
-}
-
-int ftape_abort_operation(void)
-{
- int result = 0;
- int status;
- TRACE_FUN(ft_t_flow);
-
- if (ft_runner_status == running) {
- TRACE(ft_t_noise, "aborting runner, waiting");
-
- ft_runner_status = do_abort;
- /* set timeout so that the tape will run to logical EOT
- * if we missed the last sector and there are no queue pulses.
- */
- result = ftape_dumb_stop();
- }
- if (ft_runner_status != idle) {
- if (ft_runner_status == do_abort) {
- TRACE(ft_t_noise, "forcing runner abort");
- }
- TRACE(ft_t_noise, "stopping tape");
- result = ftape_stop_tape(&status);
- ft_location.known = 0;
- ft_runner_status = idle;
- }
- ftape_reset_buffer();
- ftape_zap_read_buffers();
- ftape_set_state(idle);
- TRACE_EXIT result;
-}
-
-static int lookup_vendor_id(unsigned int vendor_id)
-{
- int i = 0;
-
- while (vendors[i].vendor_id != vendor_id) {
- if (++i >= NR_ITEMS(vendors)) {
- return -1;
- }
- }
- return i;
-}
-
-static void ftape_detach_drive(void)
-{
- TRACE_FUN(ft_t_any);
-
- TRACE(ft_t_flow, "disabling tape drive and fdc");
- ftape_put_drive_to_sleep(ft_drive_type.wake_up);
- fdc_catch_stray_interrupts(1); /* one always comes */
- fdc_disable();
- fdc_release_irq_and_dma();
- fdc_release_regions();
- TRACE_EXIT;
-}
-
-static void clear_history(void)
-{
- ft_history.used = 0;
- ft_history.id_am_errors =
- ft_history.id_crc_errors =
- ft_history.data_am_errors =
- ft_history.data_crc_errors =
- ft_history.overrun_errors =
- ft_history.no_data_errors =
- ft_history.retries =
- ft_history.crc_errors =
- ft_history.crc_failures =
- ft_history.ecc_failures =
- ft_history.corrected =
- ft_history.defects =
- ft_history.rewinds = 0;
-}
-
-static int ftape_activate_drive(vendor_struct * drive_type)
-{
- int result = 0;
- TRACE_FUN(ft_t_flow);
-
- /* If we already know the drive type, wake it up.
- * Else try to find out what kind of drive is attached.
- */
- if (drive_type->wake_up != unknown_wake_up) {
- TRACE(ft_t_flow, "enabling tape drive and fdc");
- result = ftape_wakeup_drive(drive_type->wake_up);
- if (result < 0) {
- TRACE(ft_t_err, "known wakeup method failed");
- }
- } else {
- wake_up_types method;
- const ft_trace_t old_tracing = TRACE_LEVEL;
- if (TRACE_LEVEL < ft_t_flow) {
- SET_TRACE_LEVEL(ft_t_bug);
- }
-
- /* Try to awaken the drive using all known methods.
- * Lower tracing for a while.
- */
- for (method=no_wake_up; method < NR_ITEMS(methods); ++method) {
- drive_type->wake_up = method;
-#ifdef CONFIG_FT_TWO_DRIVES
- /* Test setup for dual drive configuration.
- * /dev/rft2 uses mountain wakeup
- * /dev/rft3 uses colorado wakeup
- * Other systems will use the normal scheme.
- */
- if ((ft_drive_sel < 2) ||
- (ft_drive_sel == 2 && method == FT_WAKE_UP_1) ||
- (ft_drive_sel == 3 && method == FT_WAKE_UP_2)) {
- result=ftape_wakeup_drive(drive_type->wake_up);
- } else {
- result = -EIO;
- }
-#else
- result = ftape_wakeup_drive(drive_type->wake_up);
-#endif
- if (result >= 0) {
- TRACE(ft_t_warn, "drive wakeup method: %s",
- methods[drive_type->wake_up].name);
- break;
- }
- }
- SET_TRACE_LEVEL(old_tracing);
-
- if (method >= NR_ITEMS(methods)) {
- /* no response at all, cannot open this drive */
- drive_type->wake_up = unknown_wake_up;
- TRACE(ft_t_err, "no tape drive found !");
- result = -ENODEV;
- }
- }
- TRACE_EXIT result;
-}
-
-static int ftape_get_drive_status(void)
-{
- int result;
- int status;
- TRACE_FUN(ft_t_flow);
-
- ft_no_tape = ft_write_protected = 0;
- /* Tape drive is activated now.
- * First clear error status if present.
- */
- do {
- result = ftape_ready_wait(ftape_timeout.reset, &status);
- if (result < 0) {
- if (result == -ETIME) {
- TRACE(ft_t_err, "ftape_ready_wait timeout");
- } else if (result == -EINTR) {
- TRACE(ft_t_err, "ftape_ready_wait aborted");
- } else {
- TRACE(ft_t_err, "ftape_ready_wait failed");
- }
- TRACE_EXIT -EIO;
- }
- /* Clear error condition (drive is ready !)
- */
- if (status & QIC_STATUS_ERROR) {
- unsigned int error;
- qic117_cmd_t command;
-
- TRACE(ft_t_err, "error status set");
- result = ftape_report_error(&error, &command, 1);
- if (result < 0) {
- TRACE(ft_t_err,
- "report_error_code failed: %d", result);
- /* hope it's working next time */
- ftape_reset_drive();
- TRACE_EXIT -EIO;
- } else if (error != 0) {
- TRACE(ft_t_noise, "error code : %d", error);
- TRACE(ft_t_noise, "error command: %d", command);
- }
- }
- if (status & QIC_STATUS_NEW_CARTRIDGE) {
- unsigned int error;
- qic117_cmd_t command;
- const ft_trace_t old_tracing = TRACE_LEVEL;
- SET_TRACE_LEVEL(ft_t_bug);
-
- /* Undocumented feature: Must clear (not present!)
- * error here or we'll fail later.
- */
- ftape_report_error(&error, &command, 1);
-
- SET_TRACE_LEVEL(old_tracing);
- TRACE(ft_t_info, "status: new cartridge");
- ft_new_tape = 1;
- } else {
- ft_new_tape = 0;
- }
- FT_SIGNAL_EXIT(_DONT_BLOCK);
- } while (status & QIC_STATUS_ERROR);
-
- ft_no_tape = !(status & QIC_STATUS_CARTRIDGE_PRESENT);
- ft_write_protected = (status & QIC_STATUS_WRITE_PROTECT) != 0;
- if (ft_no_tape) {
- TRACE(ft_t_warn, "no cartridge present");
- } else {
- if (ft_write_protected) {
- TRACE(ft_t_noise, "Write protected cartridge");
- }
- }
- TRACE_EXIT 0;
-}
-
-static void ftape_log_vendor_id(void)
-{
- int vendor_index;
- TRACE_FUN(ft_t_flow);
-
- ftape_report_vendor_id(&ft_drive_type.vendor_id);
- vendor_index = lookup_vendor_id(ft_drive_type.vendor_id);
- if (ft_drive_type.vendor_id == UNKNOWN_VENDOR &&
- ft_drive_type.wake_up == wake_up_colorado) {
- vendor_index = 0;
- /* hack to get rid of all this mail */
- ft_drive_type.vendor_id = 0;
- }
- if (vendor_index < 0) {
- /* Unknown vendor id, first time opening device. The
- * drive_type remains set to type found at wakeup
- * time, this will probably keep the driver operating
- * for this new vendor.
- */
- TRACE(ft_t_warn, "\n"
- KERN_INFO "============ unknown vendor id ===========\n"
- KERN_INFO "A new, yet unsupported tape drive is found\n"
- KERN_INFO "Please report the following values:\n"
- KERN_INFO " Vendor id : 0x%04x\n"
- KERN_INFO " Wakeup method : %s\n"
- KERN_INFO "And a description of your tape drive\n"
- KERN_INFO "to "THE_FTAPE_MAINTAINER"\n"
- KERN_INFO "==========================================",
- ft_drive_type.vendor_id,
- methods[ft_drive_type.wake_up].name);
- ft_drive_type.speed = 0; /* unknown */
- } else {
- ft_drive_type.name = vendors[vendor_index].name;
- ft_drive_type.speed = vendors[vendor_index].speed;
- TRACE(ft_t_info, "tape drive type: %s", ft_drive_type.name);
- /* scan all methods for this vendor_id in table */
- while(ft_drive_type.wake_up != vendors[vendor_index].wake_up) {
- if (vendor_index < NR_ITEMS(vendors) - 1 &&
- vendors[vendor_index + 1].vendor_id
- ==
- ft_drive_type.vendor_id) {
- ++vendor_index;
- } else {
- break;
- }
- }
- if (ft_drive_type.wake_up != vendors[vendor_index].wake_up) {
- TRACE(ft_t_warn, "\n"
- KERN_INFO "==========================================\n"
- KERN_INFO "wakeup type mismatch:\n"
- KERN_INFO "found: %s, expected: %s\n"
- KERN_INFO "please report this to "THE_FTAPE_MAINTAINER"\n"
- KERN_INFO "==========================================",
- methods[ft_drive_type.wake_up].name,
- methods[vendors[vendor_index].wake_up].name);
- }
- }
- TRACE_EXIT;
-}
-
-void ftape_calc_timeouts(unsigned int qic_std,
- unsigned int data_rate,
- unsigned int tape_len)
-{
- int speed; /* deci-ips ! */
- int ff_speed;
- int length;
- TRACE_FUN(ft_t_any);
-
- /* tape transport speed
- * data rate: QIC-40 QIC-80 QIC-3010 QIC-3020
- *
- * 250 Kbps 25 ips n/a n/a n/a
- * 500 Kbps 50 ips 34 ips 22.6 ips n/a
- * 1 Mbps n/a 68 ips 45.2 ips 22.6 ips
- * 2 Mbps n/a n/a n/a 45.2 ips
- *
- * fast tape transport speed is at least 68 ips.
- */
- switch (qic_std) {
- case QIC_TAPE_QIC40:
- speed = (data_rate == 250) ? 250 : 500;
- break;
- case QIC_TAPE_QIC80:
- speed = (data_rate == 500) ? 340 : 680;
- break;
- case QIC_TAPE_QIC3010:
- speed = (data_rate == 500) ? 226 : 452;
- break;
- case QIC_TAPE_QIC3020:
- speed = (data_rate == 1000) ? 226 : 452;
- break;
- default:
- TRACE(ft_t_bug, "Unknown qic_std (bug) ?");
- speed = 500;
- break;
- }
- if (ft_drive_type.speed == 0) {
- unsigned long t0;
- static int dt = 0; /* keep gcc from complaining */
- static int first_time = 1;
-
- /* Measure the time it takes to wind to EOT and back to BOT.
- * If the tape length is known, calculate the rewind speed.
- * Else keep the time value for calculation of the rewind
- * speed later on, when the length _is_ known.
- * Ask for a report only when length and speed are both known.
- */
- if (first_time) {
- ftape_seek_to_bot();
- t0 = jiffies;
- ftape_seek_to_eot();
- ftape_seek_to_bot();
- dt = (int) (((jiffies - t0) * FT_USPT) / 1000);
- if (dt < 1) {
- dt = 1; /* prevent div by zero on failures */
- }
- first_time = 0;
- TRACE(ft_t_info,
- "trying to determine seek timeout, got %d msec",
- dt);
- }
- if (tape_len != 0) {
- ft_drive_type.speed =
- (2 * 12 * tape_len * 1000) / dt;
- TRACE(ft_t_warn, "\n"
- KERN_INFO "==========================================\n"
- KERN_INFO "drive type: %s\n"
- KERN_INFO "delta time = %d ms, length = %d ft\n"
- KERN_INFO "has a maximum tape speed of %d ips\n"
- KERN_INFO "please report this to "THE_FTAPE_MAINTAINER"\n"
- KERN_INFO "==========================================",
- ft_drive_type.name, dt, tape_len,
- ft_drive_type.speed);
- }
- }
- /* Handle unknown length tapes as very long ones. We'll
- * determine the actual length from a header segment later.
- * This is normal for all modern (Wide,TR1/2/3) formats.
- */
- if (tape_len <= 0) {
- TRACE(ft_t_noise,
- "Unknown tape length, using maximal timeouts");
- length = QIC_TOP_TAPE_LEN; /* use worst case values */
- } else {
- length = tape_len; /* use actual values */
- }
- if (ft_drive_type.speed == 0) {
- ff_speed = speed;
- } else {
- ff_speed = ft_drive_type.speed;
- }
- /* time to go from bot to eot at normal speed (data rate):
- * time = (1+delta) * length (ft) * 12 (inch/ft) / speed (ips)
- * delta = 10 % for seek speed, 20 % for rewind speed.
- */
- ftape_timeout.seek = (length * 132 * FT_SECOND) / speed;
- ftape_timeout.rewind = (length * 144 * FT_SECOND) / (10 * ff_speed);
- ftape_timeout.reset = 20 * FT_SECOND + ftape_timeout.rewind;
- TRACE(ft_t_noise, "timeouts for speed = %d, length = %d\n"
- KERN_INFO "seek timeout : %d sec\n"
- KERN_INFO "rewind timeout: %d sec\n"
- KERN_INFO "reset timeout : %d sec",
- speed, length,
- (ftape_timeout.seek + 500) / 1000,
- (ftape_timeout.rewind + 500) / 1000,
- (ftape_timeout.reset + 500) / 1000);
- TRACE_EXIT;
-}
-
-/* This function calibrates the datarate (i.e. determines the maximal
- * usable data rate) and sets the global variable ft_qic_std to qic_std
- *
- */
-int ftape_calibrate_data_rate(unsigned int qic_std)
-{
- int rate = ft_fdc_rate_limit;
- int result;
- TRACE_FUN(ft_t_flow);
-
- ft_qic_std = qic_std;
-
- if (ft_qic_std == -1) {
- TRACE_ABORT(-EIO, ft_t_err,
- "Unable to determine data rate if QIC standard is unknown");
- }
-
- /* Select highest rate supported by both fdc and drive.
- * Start with highest rate supported by the fdc.
- */
- while (fdc_set_data_rate(rate) < 0 && rate > 250) {
- rate /= 2;
- }
- TRACE(ft_t_info,
- "Highest FDC supported data rate: %d Kbps", rate);
- ft_fdc_max_rate = rate;
- do {
- result = ftape_set_data_rate(rate, ft_qic_std);
- } while (result == -EINVAL && (rate /= 2) > 250);
- if (result < 0) {
- TRACE_ABORT(-EIO, ft_t_err, "set datarate failed");
- }
- ft_data_rate = rate;
- TRACE_EXIT 0;
-}
-
-static int ftape_init_drive(void)
-{
- int status;
- qic_model model;
- unsigned int qic_std;
- unsigned int data_rate;
- TRACE_FUN(ft_t_flow);
-
- ftape_init_drive_needed = 0; /* don't retry if this fails ? */
- TRACE_CATCH(ftape_report_raw_drive_status(&status),);
- if (status & QIC_STATUS_CARTRIDGE_PRESENT) {
- if (!(status & QIC_STATUS_AT_BOT)) {
- /* Antique drives will get here after a soft reset,
- * modern ones only if the driver is loaded when the
- * tape wasn't rewound properly.
- */
- /* Tape should be at bot if new cartridge ! */
- ftape_seek_to_bot();
- }
- if (!(status & QIC_STATUS_REFERENCED)) {
- TRACE(ft_t_flow, "starting seek_load_point");
- TRACE_CATCH(ftape_command_wait(QIC_SEEK_LOAD_POINT,
- ftape_timeout.reset,
- &status),);
- }
- }
- ft_formatted = (status & QIC_STATUS_REFERENCED) != 0;
- if (!ft_formatted) {
- TRACE(ft_t_warn, "Warning: tape is not formatted !");
- }
-
- /* report configuration aborts when ftape_tape_len == -1
- * unknown qic_std is okay if not formatted.
- */
- TRACE_CATCH(ftape_report_configuration(&model,
- &data_rate,
- &qic_std,
- &ftape_tape_len),);
-
- /* Maybe add the following to the /proc entry
- */
- TRACE(ft_t_info, "%s drive @ %d Kbps",
- (model == prehistoric) ? "prehistoric" :
- ((model == pre_qic117c) ? "pre QIC-117C" :
- ((model == post_qic117b) ? "post QIC-117B" :
- "post QIC-117D")), data_rate);
-
- if (ft_formatted) {
- /* initialize ft_used_data_rate to maximum value
- * and set ft_qic_std
- */
- TRACE_CATCH(ftape_calibrate_data_rate(qic_std),);
- if (ftape_tape_len == 0) {
- TRACE(ft_t_info, "unknown length QIC-%s tape",
- (ft_qic_std == QIC_TAPE_QIC40) ? "40" :
- ((ft_qic_std == QIC_TAPE_QIC80) ? "80" :
- ((ft_qic_std == QIC_TAPE_QIC3010)
- ? "3010" : "3020")));
- } else {
- TRACE(ft_t_info, "%d ft. QIC-%s tape", ftape_tape_len,
- (ft_qic_std == QIC_TAPE_QIC40) ? "40" :
- ((ft_qic_std == QIC_TAPE_QIC80) ? "80" :
- ((ft_qic_std == QIC_TAPE_QIC3010)
- ? "3010" : "3020")));
- }
- ftape_calc_timeouts(ft_qic_std, ft_data_rate, ftape_tape_len);
- /* soft write-protect QIC-40/QIC-80 cartridges used with a
- * Colorado T3000 drive. Buggy hardware!
- */
- if ((ft_drive_type.vendor_id == 0x011c6) &&
- ((ft_qic_std == QIC_TAPE_QIC40 ||
- ft_qic_std == QIC_TAPE_QIC80) &&
- !ft_write_protected)) {
- TRACE(ft_t_warn, "\n"
- KERN_INFO "The famous Colorado T3000 bug:\n"
- KERN_INFO "%s drives can't write QIC40 and QIC80\n"
- KERN_INFO "cartridges but don't set the write-protect flag!",
- ft_drive_type.name);
- ft_write_protected = 1;
- }
- } else {
- /* Doesn't make too much sense to set the data rate
- * because we don't know what to use for the write
- * precompensation.
- * Need to do this again when formatting the cartridge.
- */
- ft_data_rate = data_rate;
- ftape_calc_timeouts(QIC_TAPE_QIC40,
- data_rate,
- ftape_tape_len);
- }
- ftape_new_cartridge();
- TRACE_EXIT 0;
-}
-
-static void ftape_munmap(void)
-{
- int i;
- TRACE_FUN(ft_t_flow);
-
- for (i = 0; i < ft_nr_buffers; i++) {
- ft_buffer[i]->mmapped = 0;
- }
- TRACE_EXIT;
-}
-
-/* Map the dma buffers into the virtual address range given by vma.
- * We only check the caller doesn't map non-existent buffers. We
- * don't check for multiple mappings.
- */
-int ftape_mmap(struct vm_area_struct *vma)
-{
- int num_buffers;
- int i;
- TRACE_FUN(ft_t_flow);
-
- if (ft_failure) {
- TRACE_EXIT -ENODEV;
- }
- if (!(vma->vm_flags & (VM_READ|VM_WRITE))) {
- TRACE_ABORT(-EINVAL, ft_t_err, "Undefined mmap() access");
- }
- if (vma_get_pgoff(vma) != 0) {
- TRACE_ABORT(-EINVAL, ft_t_err, "page offset must be 0");
- }
- if ((vma->vm_end - vma->vm_start) % FT_BUFF_SIZE != 0) {
- TRACE_ABORT(-EINVAL, ft_t_err,
- "size = %ld, should be a multiple of %d",
- vma->vm_end - vma->vm_start,
- FT_BUFF_SIZE);
- }
- num_buffers = (vma->vm_end - vma->vm_start) / FT_BUFF_SIZE;
- if (num_buffers > ft_nr_buffers) {
- TRACE_ABORT(-EINVAL,
- ft_t_err, "size = %ld, should be less than %d",
- vma->vm_end - vma->vm_start,
- ft_nr_buffers * FT_BUFF_SIZE);
- }
- if (ft_driver_state != idle) {
- /* this also clears the buffer states
- */
- ftape_abort_operation();
- } else {
- ftape_reset_buffer();
- }
- for (i = 0; i < num_buffers; i++) {
- unsigned long pfn;
-
- pfn = virt_to_phys(ft_buffer[i]->address) >> PAGE_SHIFT;
- TRACE_CATCH(remap_pfn_range(vma, vma->vm_start +
- i * FT_BUFF_SIZE,
- pfn,
- FT_BUFF_SIZE,
- vma->vm_page_prot),
- _res = -EAGAIN);
- TRACE(ft_t_noise, "remapped dma buffer @ %p to location @ %p",
- ft_buffer[i]->address,
- (void *)(vma->vm_start + i * FT_BUFF_SIZE));
- }
- for (i = 0; i < num_buffers; i++) {
- memset(ft_buffer[i]->address, 0xAA, FT_BUFF_SIZE);
- ft_buffer[i]->mmapped++;
- }
- TRACE_EXIT 0;
-}
-
-static void ftape_init_driver(void); /* forward declaration */
-
-/* OPEN routine called by kernel-interface code
- */
-int ftape_enable(int drive_selection)
-{
- TRACE_FUN(ft_t_any);
-
- if (ft_drive_sel == -1 || ft_drive_sel != drive_selection) {
- /* Other selection than last time
- */
- ftape_init_driver();
- }
- ft_drive_sel = FTAPE_SEL(drive_selection);
- ft_failure = 0;
- TRACE_CATCH(fdc_init(),); /* init & detect fdc */
- TRACE_CATCH(ftape_activate_drive(&ft_drive_type),
- fdc_disable();
- fdc_release_irq_and_dma();
- fdc_release_regions());
- TRACE_CATCH(ftape_get_drive_status(), ftape_detach_drive());
- if (ft_drive_type.vendor_id == UNKNOWN_VENDOR) {
- ftape_log_vendor_id();
- }
- if (ft_new_tape) {
- ftape_init_drive_needed = 1;
- }
- if (!ft_no_tape && ftape_init_drive_needed) {
- TRACE_CATCH(ftape_init_drive(), ftape_detach_drive());
- }
- ftape_munmap(); /* clear the mmap flag */
- clear_history();
- TRACE_EXIT 0;
-}
-
-/* release routine called by the high level interface modules
- * zftape or sftape.
- */
-void ftape_disable(void)
-{
- int i;
- TRACE_FUN(ft_t_any);
-
- for (i = 0; i < ft_nr_buffers; i++) {
- if (ft_buffer[i]->mmapped) {
- TRACE(ft_t_noise, "first byte of buffer %d: 0x%02x",
- i, *ft_buffer[i]->address);
- }
- }
- if (sigtestsetmask(&current->pending.signal, _DONT_BLOCK) &&
- !(sigtestsetmask(&current->pending.signal, _NEVER_BLOCK)) &&
- ftape_tape_running) {
- TRACE(ft_t_warn,
- "Interrupted by fatal signal and tape still running");
- ftape_dumb_stop();
- ftape_abort_operation(); /* it's annoying */
- } else {
- ftape_set_state(idle);
- }
- ftape_detach_drive();
- if (ft_history.used) {
- TRACE(ft_t_info, "== Non-fatal errors this run: ==");
- TRACE(ft_t_info, "fdc isr statistics:\n"
- KERN_INFO " id_am_errors : %3d\n"
- KERN_INFO " id_crc_errors : %3d\n"
- KERN_INFO " data_am_errors : %3d\n"
- KERN_INFO " data_crc_errors : %3d\n"
- KERN_INFO " overrun_errors : %3d\n"
- KERN_INFO " no_data_errors : %3d\n"
- KERN_INFO " retries : %3d",
- ft_history.id_am_errors, ft_history.id_crc_errors,
- ft_history.data_am_errors, ft_history.data_crc_errors,
- ft_history.overrun_errors, ft_history.no_data_errors,
- ft_history.retries);
- if (ft_history.used & 1) {
- TRACE(ft_t_info, "ecc statistics:\n"
- KERN_INFO " crc_errors : %3d\n"
- KERN_INFO " crc_failures : %3d\n"
- KERN_INFO " ecc_failures : %3d\n"
- KERN_INFO " sectors corrected: %3d",
- ft_history.crc_errors, ft_history.crc_failures,
- ft_history.ecc_failures, ft_history.corrected);
- }
- if (ft_history.defects > 0) {
- TRACE(ft_t_warn, "Warning: %d media defects!",
- ft_history.defects);
- }
- if (ft_history.rewinds > 0) {
- TRACE(ft_t_info, "tape motion statistics:\n"
- KERN_INFO "repositions : %3d",
- ft_history.rewinds);
- }
- }
- ft_failure = 1;
- TRACE_EXIT;
-}
-
-static void ftape_init_driver(void)
-{
- TRACE_FUN(ft_t_flow);
-
- ft_drive_type.vendor_id = UNKNOWN_VENDOR;
- ft_drive_type.speed = 0;
- ft_drive_type.wake_up = unknown_wake_up;
- ft_drive_type.name = "Unknown";
-
- ftape_timeout.seek = 650 * FT_SECOND;
- ftape_timeout.reset = 670 * FT_SECOND;
- ftape_timeout.rewind = 650 * FT_SECOND;
- ftape_timeout.head_seek = 15 * FT_SECOND;
- ftape_timeout.stop = 5 * FT_SECOND;
- ftape_timeout.pause = 16 * FT_SECOND;
-
- ft_qic_std = -1;
- ftape_tape_len = 0; /* unknown */
- ftape_current_command = 0;
- ftape_current_cylinder = -1;
-
- ft_segments_per_track = 102;
- ftape_segments_per_head = 1020;
- ftape_segments_per_cylinder = 4;
- ft_tracks_per_tape = 20;
-
- ft_failure = 1;
-
- ft_formatted = 0;
- ft_no_tape = 1;
- ft_write_protected = 1;
- ft_new_tape = 1;
-
- ft_driver_state = idle;
-
- ft_data_rate =
- ft_fdc_max_rate = 500;
- ft_drive_max_rate = 0; /* triggers set_rate_test() */
-
- ftape_init_drive_needed = 1;
-
- ft_header_segment_1 = -1;
- ft_header_segment_2 = -1;
- ft_used_header_segment = -1;
- ft_first_data_segment = -1;
- ft_last_data_segment = -1;
-
- ft_location.track = -1;
- ft_location.known = 0;
-
- ftape_tape_running = 0;
- ftape_might_be_off_track = 1;
-
- ftape_new_cartridge(); /* init some tape related variables */
- ftape_init_bsm();
- TRACE_EXIT;
-}
diff --git a/drivers/char/ftape/lowlevel/ftape-ctl.h b/drivers/char/ftape/lowlevel/ftape-ctl.h
deleted file mode 100644
index 5f5e30bc3615..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-ctl.h
+++ /dev/null
@@ -1,162 +0,0 @@
-#ifndef _FTAPE_CTL_H
-#define _FTAPE_CTL_H
-
-/*
- * Copyright (C) 1993-1996 Bas Laarhoven,
- * (C) 1996-1997 Claus-Justus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-ctl.h,v $
- * $Revision: 1.2 $
- * $Date: 1997/10/05 19:18:09 $
- *
- * This file contains the non-standard IOCTL related definitions
- * for the QIC-40/80/3010/3020 floppy-tape driver "ftape" for
- * Linux.
- */
-
-#include <linux/ioctl.h>
-#include <linux/mtio.h>
-#include <linux/ftape-vendors.h>
-
-#include "../lowlevel/ftape-rw.h"
-#include <linux/ftape-header-segment.h>
-
-typedef struct {
- int used; /* any reading or writing done */
- /* isr statistics */
- unsigned int id_am_errors; /* id address mark not found */
- unsigned int id_crc_errors; /* crc error in id address mark */
- unsigned int data_am_errors; /* data address mark not found */
- unsigned int data_crc_errors; /* crc error in data field */
- unsigned int overrun_errors; /* fdc access timing problem */
- unsigned int no_data_errors; /* sector not found */
- unsigned int retries; /* number of tape retries */
- /* ecc statistics */
- unsigned int crc_errors; /* crc error in data */
- unsigned int crc_failures; /* bad data without crc error */
- unsigned int ecc_failures; /* failed to correct */
- unsigned int corrected; /* total sectors corrected */
- /* general statistics */
- unsigned int rewinds; /* number of tape rewinds */
- unsigned int defects; /* bad sectors due to media defects */
-} history_record;
-
-/* this structure contains * ALL * information that we want
- * our child modules to know about, but don't want them to
- * modify.
- */
-typedef struct {
- /* vendor information */
- vendor_struct fti_drive_type;
- /* data rates */
- unsigned int fti_used_data_rate;
- unsigned int fti_drive_max_rate;
- unsigned int fti_fdc_max_rate;
- /* drive selection, either FTAPE_SEL_A/B/C/D */
- int fti_drive_sel;
- /* flags set after decode the drive and tape status */
- unsigned int fti_formatted :1;
- unsigned int fti_no_tape :1;
- unsigned int fti_write_protected:1;
- unsigned int fti_new_tape :1;
- /* values of last queried drive/tape status and error */
- ft_drive_error fti_last_error;
- ft_drive_status fti_last_status;
- /* cartridge geometry */
- unsigned int fti_tracks_per_tape;
- unsigned int fti_segments_per_track;
- /* location of header segments, etc. */
- int fti_used_header_segment;
- int fti_header_segment_1;
- int fti_header_segment_2;
- int fti_first_data_segment;
- int fti_last_data_segment;
- /* the format code as stored in the header segment */
- ft_format_type fti_format_code;
- /* the following is the sole reason for the ftape_set_status() call */
- unsigned int fti_qic_std;
- /* is tape running? */
- volatile enum runner_status_enum fti_runner_status;
- /* is tape reading/writing/verifying/formatting/deleting */
- buffer_state_enum fti_state;
- /* flags fatal hardware error */
- unsigned int fti_failure:1;
- /* history record */
- history_record fti_history;
-} ftape_info;
-
-/* vendor information */
-#define ft_drive_type ftape_status.fti_drive_type
-/* data rates */
-#define ft_data_rate ftape_status.fti_used_data_rate
-#define ft_drive_max_rate ftape_status.fti_drive_max_rate
-#define ft_fdc_max_rate ftape_status.fti_fdc_max_rate
-/* drive selection, either FTAPE_SEL_A/B/C/D */
-#define ft_drive_sel ftape_status.fti_drive_sel
-/* flags set after decode the drive and tape status */
-#define ft_formatted ftape_status.fti_formatted
-#define ft_no_tape ftape_status.fti_no_tape
-#define ft_write_protected ftape_status.fti_write_protected
-#define ft_new_tape ftape_status.fti_new_tape
-/* values of last queried drive/tape status and error */
-#define ft_last_error ftape_status.fti_last_error
-#define ft_last_status ftape_status.fti_last_status
-/* cartridge geometry */
-#define ft_tracks_per_tape ftape_status.fti_tracks_per_tape
-#define ft_segments_per_track ftape_status.fti_segments_per_track
-/* the format code as stored in the header segment */
-#define ft_format_code ftape_status.fti_format_code
-/* the qic status as returned by report drive configuration */
-#define ft_qic_std ftape_status.fti_qic_std
-#define ft_used_header_segment ftape_status.fti_used_header_segment
-#define ft_header_segment_1 ftape_status.fti_header_segment_1
-#define ft_header_segment_2 ftape_status.fti_header_segment_2
-#define ft_first_data_segment ftape_status.fti_first_data_segment
-#define ft_last_data_segment ftape_status.fti_last_data_segment
-/* is tape running? */
-#define ft_runner_status ftape_status.fti_runner_status
-/* is tape reading/writing/verifying/formatting/deleting */
-#define ft_driver_state ftape_status.fti_state
-/* flags fatal hardware error */
-#define ft_failure ftape_status.fti_failure
-/* history record */
-#define ft_history ftape_status.fti_history
-
-/*
- * ftape-ctl.c defined global vars.
- */
-extern ftape_info ftape_status;
-extern int ftape_segments_per_head;
-extern int ftape_segments_per_cylinder;
-extern int ftape_init_drive_needed;
-
-/*
- * ftape-ctl.c defined global functions.
- */
-extern int ftape_mmap(struct vm_area_struct *vma);
-extern int ftape_enable(int drive_selection);
-extern void ftape_disable(void);
-extern int ftape_seek_to_bot(void);
-extern int ftape_seek_to_eot(void);
-extern int ftape_abort_operation(void);
-extern void ftape_calc_timeouts(unsigned int qic_std,
- unsigned int data_rate,
- unsigned int tape_len);
-extern int ftape_calibrate_data_rate(unsigned int qic_std);
-extern const ftape_info *ftape_get_status(void);
-#endif
diff --git a/drivers/char/ftape/lowlevel/ftape-ecc.c b/drivers/char/ftape/lowlevel/ftape-ecc.c
deleted file mode 100644
index e5632f674bc8..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-ecc.c
+++ /dev/null
@@ -1,853 +0,0 @@
-/*
- *
- * Copyright (c) 1993 Ning and David Mosberger.
-
- This is based on code originally written by Bas Laarhoven (bas@vimec.nl)
- and David L. Brown, Jr., and incorporates improvements suggested by
- Kai Harrekilde-Petersen.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
- USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-ecc.c,v $
- * $Revision: 1.3 $
- * $Date: 1997/10/05 19:18:10 $
- *
- * This file contains the Reed-Solomon error correction code
- * for the QIC-40/80 floppy-tape driver for Linux.
- */
-
-#include <linux/ftape.h>
-
-#include "../lowlevel/ftape-tracing.h"
-#include "../lowlevel/ftape-ecc.h"
-
-/* Machines that are big-endian should define macro BIG_ENDIAN.
- * Unfortunately, there doesn't appear to be a standard include file
- * that works for all OSs.
- */
-
-#if defined(__sparc__) || defined(__hppa)
-#define BIG_ENDIAN
-#endif /* __sparc__ || __hppa */
-
-#if defined(__mips__)
-#error Find a smart way to determine the Endianness of the MIPS CPU
-#endif
-
-/* Notice: to minimize the potential for confusion, we use r to
- * denote the independent variable of the polynomials in the
- * Galois Field GF(2^8). We reserve x for polynomials that
- * that have coefficients in GF(2^8).
- *
- * The Galois Field in which coefficient arithmetic is performed are
- * the polynomials over Z_2 (i.e., 0 and 1) modulo the irreducible
- * polynomial f(r), where f(r)=r^8 + r^7 + r^2 + r + 1. A polynomial
- * is represented as a byte with the MSB as the coefficient of r^7 and
- * the LSB as the coefficient of r^0. For example, the binary
- * representation of f(x) is 0x187 (of course, this doesn't fit into 8
- * bits). In this field, the polynomial r is a primitive element.
- * That is, r^i with i in 0,...,255 enumerates all elements in the
- * field.
- *
- * The generator polynomial for the QIC-80 ECC is
- *
- * g(x) = x^3 + r^105*x^2 + r^105*x + 1
- *
- * which can be factored into:
- *
- * g(x) = (x-r^-1)(x-r^0)(x-r^1)
- *
- * the byte representation of the coefficients are:
- *
- * r^105 = 0xc0
- * r^-1 = 0xc3
- * r^0 = 0x01
- * r^1 = 0x02
- *
- * Notice that r^-1 = r^254 as exponent arithmetic is performed
- * modulo 2^8-1 = 255.
- *
- * For more information on Galois Fields and Reed-Solomon codes, refer
- * to any good book. I found _An Introduction to Error Correcting
- * Codes with Applications_ by S. A. Vanstone and P. C. van Oorschot
- * to be a good introduction into the former. _CODING THEORY: The
- * Essentials_ I found very useful for its concise description of
- * Reed-Solomon encoding/decoding.
- *
- */
-
-typedef __u8 Matrix[3][3];
-
-/*
- * gfpow[] is defined such that gfpow[i] returns r^i if
- * i is in the range [0..255].
- */
-static const __u8 gfpow[] =
-{
- 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
- 0x87, 0x89, 0x95, 0xad, 0xdd, 0x3d, 0x7a, 0xf4,
- 0x6f, 0xde, 0x3b, 0x76, 0xec, 0x5f, 0xbe, 0xfb,
- 0x71, 0xe2, 0x43, 0x86, 0x8b, 0x91, 0xa5, 0xcd,
- 0x1d, 0x3a, 0x74, 0xe8, 0x57, 0xae, 0xdb, 0x31,
- 0x62, 0xc4, 0x0f, 0x1e, 0x3c, 0x78, 0xf0, 0x67,
- 0xce, 0x1b, 0x36, 0x6c, 0xd8, 0x37, 0x6e, 0xdc,
- 0x3f, 0x7e, 0xfc, 0x7f, 0xfe, 0x7b, 0xf6, 0x6b,
- 0xd6, 0x2b, 0x56, 0xac, 0xdf, 0x39, 0x72, 0xe4,
- 0x4f, 0x9e, 0xbb, 0xf1, 0x65, 0xca, 0x13, 0x26,
- 0x4c, 0x98, 0xb7, 0xe9, 0x55, 0xaa, 0xd3, 0x21,
- 0x42, 0x84, 0x8f, 0x99, 0xb5, 0xed, 0x5d, 0xba,
- 0xf3, 0x61, 0xc2, 0x03, 0x06, 0x0c, 0x18, 0x30,
- 0x60, 0xc0, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0,
- 0x47, 0x8e, 0x9b, 0xb1, 0xe5, 0x4d, 0x9a, 0xb3,
- 0xe1, 0x45, 0x8a, 0x93, 0xa1, 0xc5, 0x0d, 0x1a,
- 0x34, 0x68, 0xd0, 0x27, 0x4e, 0x9c, 0xbf, 0xf9,
- 0x75, 0xea, 0x53, 0xa6, 0xcb, 0x11, 0x22, 0x44,
- 0x88, 0x97, 0xa9, 0xd5, 0x2d, 0x5a, 0xb4, 0xef,
- 0x59, 0xb2, 0xe3, 0x41, 0x82, 0x83, 0x81, 0x85,
- 0x8d, 0x9d, 0xbd, 0xfd, 0x7d, 0xfa, 0x73, 0xe6,
- 0x4b, 0x96, 0xab, 0xd1, 0x25, 0x4a, 0x94, 0xaf,
- 0xd9, 0x35, 0x6a, 0xd4, 0x2f, 0x5e, 0xbc, 0xff,
- 0x79, 0xf2, 0x63, 0xc6, 0x0b, 0x16, 0x2c, 0x58,
- 0xb0, 0xe7, 0x49, 0x92, 0xa3, 0xc1, 0x05, 0x0a,
- 0x14, 0x28, 0x50, 0xa0, 0xc7, 0x09, 0x12, 0x24,
- 0x48, 0x90, 0xa7, 0xc9, 0x15, 0x2a, 0x54, 0xa8,
- 0xd7, 0x29, 0x52, 0xa4, 0xcf, 0x19, 0x32, 0x64,
- 0xc8, 0x17, 0x2e, 0x5c, 0xb8, 0xf7, 0x69, 0xd2,
- 0x23, 0x46, 0x8c, 0x9f, 0xb9, 0xf5, 0x6d, 0xda,
- 0x33, 0x66, 0xcc, 0x1f, 0x3e, 0x7c, 0xf8, 0x77,
- 0xee, 0x5b, 0xb6, 0xeb, 0x51, 0xa2, 0xc3, 0x01
-};
-
-/*
- * This is a log table. That is, gflog[r^i] returns i (modulo f(r)).
- * gflog[0] is undefined and the first element is therefore not valid.
- */
-static const __u8 gflog[256] =
-{
- 0xff, 0x00, 0x01, 0x63, 0x02, 0xc6, 0x64, 0x6a,
- 0x03, 0xcd, 0xc7, 0xbc, 0x65, 0x7e, 0x6b, 0x2a,
- 0x04, 0x8d, 0xce, 0x4e, 0xc8, 0xd4, 0xbd, 0xe1,
- 0x66, 0xdd, 0x7f, 0x31, 0x6c, 0x20, 0x2b, 0xf3,
- 0x05, 0x57, 0x8e, 0xe8, 0xcf, 0xac, 0x4f, 0x83,
- 0xc9, 0xd9, 0xd5, 0x41, 0xbe, 0x94, 0xe2, 0xb4,
- 0x67, 0x27, 0xde, 0xf0, 0x80, 0xb1, 0x32, 0x35,
- 0x6d, 0x45, 0x21, 0x12, 0x2c, 0x0d, 0xf4, 0x38,
- 0x06, 0x9b, 0x58, 0x1a, 0x8f, 0x79, 0xe9, 0x70,
- 0xd0, 0xc2, 0xad, 0xa8, 0x50, 0x75, 0x84, 0x48,
- 0xca, 0xfc, 0xda, 0x8a, 0xd6, 0x54, 0x42, 0x24,
- 0xbf, 0x98, 0x95, 0xf9, 0xe3, 0x5e, 0xb5, 0x15,
- 0x68, 0x61, 0x28, 0xba, 0xdf, 0x4c, 0xf1, 0x2f,
- 0x81, 0xe6, 0xb2, 0x3f, 0x33, 0xee, 0x36, 0x10,
- 0x6e, 0x18, 0x46, 0xa6, 0x22, 0x88, 0x13, 0xf7,
- 0x2d, 0xb8, 0x0e, 0x3d, 0xf5, 0xa4, 0x39, 0x3b,
- 0x07, 0x9e, 0x9c, 0x9d, 0x59, 0x9f, 0x1b, 0x08,
- 0x90, 0x09, 0x7a, 0x1c, 0xea, 0xa0, 0x71, 0x5a,
- 0xd1, 0x1d, 0xc3, 0x7b, 0xae, 0x0a, 0xa9, 0x91,
- 0x51, 0x5b, 0x76, 0x72, 0x85, 0xa1, 0x49, 0xeb,
- 0xcb, 0x7c, 0xfd, 0xc4, 0xdb, 0x1e, 0x8b, 0xd2,
- 0xd7, 0x92, 0x55, 0xaa, 0x43, 0x0b, 0x25, 0xaf,
- 0xc0, 0x73, 0x99, 0x77, 0x96, 0x5c, 0xfa, 0x52,
- 0xe4, 0xec, 0x5f, 0x4a, 0xb6, 0xa2, 0x16, 0x86,
- 0x69, 0xc5, 0x62, 0xfe, 0x29, 0x7d, 0xbb, 0xcc,
- 0xe0, 0xd3, 0x4d, 0x8c, 0xf2, 0x1f, 0x30, 0xdc,
- 0x82, 0xab, 0xe7, 0x56, 0xb3, 0x93, 0x40, 0xd8,
- 0x34, 0xb0, 0xef, 0x26, 0x37, 0x0c, 0x11, 0x44,
- 0x6f, 0x78, 0x19, 0x9a, 0x47, 0x74, 0xa7, 0xc1,
- 0x23, 0x53, 0x89, 0xfb, 0x14, 0x5d, 0xf8, 0x97,
- 0x2e, 0x4b, 0xb9, 0x60, 0x0f, 0xed, 0x3e, 0xe5,
- 0xf6, 0x87, 0xa5, 0x17, 0x3a, 0xa3, 0x3c, 0xb7
-};
-
-/* This is a multiplication table for the factor 0xc0 (i.e., r^105 (mod f(r)).
- * gfmul_c0[f] returns r^105 * f(r) (modulo f(r)).
- */
-static const __u8 gfmul_c0[256] =
-{
- 0x00, 0xc0, 0x07, 0xc7, 0x0e, 0xce, 0x09, 0xc9,
- 0x1c, 0xdc, 0x1b, 0xdb, 0x12, 0xd2, 0x15, 0xd5,
- 0x38, 0xf8, 0x3f, 0xff, 0x36, 0xf6, 0x31, 0xf1,
- 0x24, 0xe4, 0x23, 0xe3, 0x2a, 0xea, 0x2d, 0xed,
- 0x70, 0xb0, 0x77, 0xb7, 0x7e, 0xbe, 0x79, 0xb9,
- 0x6c, 0xac, 0x6b, 0xab, 0x62, 0xa2, 0x65, 0xa5,
- 0x48, 0x88, 0x4f, 0x8f, 0x46, 0x86, 0x41, 0x81,
- 0x54, 0x94, 0x53, 0x93, 0x5a, 0x9a, 0x5d, 0x9d,
- 0xe0, 0x20, 0xe7, 0x27, 0xee, 0x2e, 0xe9, 0x29,
- 0xfc, 0x3c, 0xfb, 0x3b, 0xf2, 0x32, 0xf5, 0x35,
- 0xd8, 0x18, 0xdf, 0x1f, 0xd6, 0x16, 0xd1, 0x11,
- 0xc4, 0x04, 0xc3, 0x03, 0xca, 0x0a, 0xcd, 0x0d,
- 0x90, 0x50, 0x97, 0x57, 0x9e, 0x5e, 0x99, 0x59,
- 0x8c, 0x4c, 0x8b, 0x4b, 0x82, 0x42, 0x85, 0x45,
- 0xa8, 0x68, 0xaf, 0x6f, 0xa6, 0x66, 0xa1, 0x61,
- 0xb4, 0x74, 0xb3, 0x73, 0xba, 0x7a, 0xbd, 0x7d,
- 0x47, 0x87, 0x40, 0x80, 0x49, 0x89, 0x4e, 0x8e,
- 0x5b, 0x9b, 0x5c, 0x9c, 0x55, 0x95, 0x52, 0x92,
- 0x7f, 0xbf, 0x78, 0xb8, 0x71, 0xb1, 0x76, 0xb6,
- 0x63, 0xa3, 0x64, 0xa4, 0x6d, 0xad, 0x6a, 0xaa,
- 0x37, 0xf7, 0x30, 0xf0, 0x39, 0xf9, 0x3e, 0xfe,
- 0x2b, 0xeb, 0x2c, 0xec, 0x25, 0xe5, 0x22, 0xe2,
- 0x0f, 0xcf, 0x08, 0xc8, 0x01, 0xc1, 0x06, 0xc6,
- 0x13, 0xd3, 0x14, 0xd4, 0x1d, 0xdd, 0x1a, 0xda,
- 0xa7, 0x67, 0xa0, 0x60, 0xa9, 0x69, 0xae, 0x6e,
- 0xbb, 0x7b, 0xbc, 0x7c, 0xb5, 0x75, 0xb2, 0x72,
- 0x9f, 0x5f, 0x98, 0x58, 0x91, 0x51, 0x96, 0x56,
- 0x83, 0x43, 0x84, 0x44, 0x8d, 0x4d, 0x8a, 0x4a,
- 0xd7, 0x17, 0xd0, 0x10, 0xd9, 0x19, 0xde, 0x1e,
- 0xcb, 0x0b, 0xcc, 0x0c, 0xc5, 0x05, 0xc2, 0x02,
- 0xef, 0x2f, 0xe8, 0x28, 0xe1, 0x21, 0xe6, 0x26,
- 0xf3, 0x33, 0xf4, 0x34, 0xfd, 0x3d, 0xfa, 0x3a
-};
-
-
-/* Returns V modulo 255 provided V is in the range -255,-254,...,509.
- */
-static inline __u8 mod255(int v)
-{
- if (v > 0) {
- if (v < 255) {
- return v;
- } else {
- return v - 255;
- }
- } else {
- return v + 255;
- }
-}
-
-
-/* Add two numbers in the field. Addition in this field is equivalent
- * to a bit-wise exclusive OR operation---subtraction is therefore
- * identical to addition.
- */
-static inline __u8 gfadd(__u8 a, __u8 b)
-{
- return a ^ b;
-}
-
-
-/* Add two vectors of numbers in the field. Each byte in A and B gets
- * added individually.
- */
-static inline unsigned long gfadd_long(unsigned long a, unsigned long b)
-{
- return a ^ b;
-}
-
-
-/* Multiply two numbers in the field:
- */
-static inline __u8 gfmul(__u8 a, __u8 b)
-{
- if (a && b) {
- return gfpow[mod255(gflog[a] + gflog[b])];
- } else {
- return 0;
- }
-}
-
-
-/* Just like gfmul, except we have already looked up the log of the
- * second number.
- */
-static inline __u8 gfmul_exp(__u8 a, int b)
-{
- if (a) {
- return gfpow[mod255(gflog[a] + b)];
- } else {
- return 0;
- }
-}
-
-
-/* Just like gfmul_exp, except that A is a vector of numbers. That
- * is, each byte in A gets multiplied by gfpow[mod255(B)].
- */
-static inline unsigned long gfmul_exp_long(unsigned long a, int b)
-{
- __u8 t;
-
- if (sizeof(long) == 4) {
- return (
- ((t = (__u32)a >> 24 & 0xff) ?
- (((__u32) gfpow[mod255(gflog[t] + b)]) << 24) : 0) |
- ((t = (__u32)a >> 16 & 0xff) ?
- (((__u32) gfpow[mod255(gflog[t] + b)]) << 16) : 0) |
- ((t = (__u32)a >> 8 & 0xff) ?
- (((__u32) gfpow[mod255(gflog[t] + b)]) << 8) : 0) |
- ((t = (__u32)a >> 0 & 0xff) ?
- (((__u32) gfpow[mod255(gflog[t] + b)]) << 0) : 0));
- } else if (sizeof(long) == 8) {
- return (
- ((t = (__u64)a >> 56 & 0xff) ?
- (((__u64) gfpow[mod255(gflog[t] + b)]) << 56) : 0) |
- ((t = (__u64)a >> 48 & 0xff) ?
- (((__u64) gfpow[mod255(gflog[t] + b)]) << 48) : 0) |
- ((t = (__u64)a >> 40 & 0xff) ?
- (((__u64) gfpow[mod255(gflog[t] + b)]) << 40) : 0) |
- ((t = (__u64)a >> 32 & 0xff) ?
- (((__u64) gfpow[mod255(gflog[t] + b)]) << 32) : 0) |
- ((t = (__u64)a >> 24 & 0xff) ?
- (((__u64) gfpow[mod255(gflog[t] + b)]) << 24) : 0) |
- ((t = (__u64)a >> 16 & 0xff) ?
- (((__u64) gfpow[mod255(gflog[t] + b)]) << 16) : 0) |
- ((t = (__u64)a >> 8 & 0xff) ?
- (((__u64) gfpow[mod255(gflog[t] + b)]) << 8) : 0) |
- ((t = (__u64)a >> 0 & 0xff) ?
- (((__u64) gfpow[mod255(gflog[t] + b)]) << 0) : 0));
- } else {
- TRACE_FUN(ft_t_any);
- TRACE_ABORT(-1, ft_t_err, "Error: size of long is %d bytes",
- (int)sizeof(long));
- }
-}
-
-
-/* Divide two numbers in the field. Returns a/b (modulo f(x)).
- */
-static inline __u8 gfdiv(__u8 a, __u8 b)
-{
- if (!b) {
- TRACE_FUN(ft_t_any);
- TRACE_ABORT(0xff, ft_t_bug, "Error: division by zero");
- } else if (a == 0) {
- return 0;
- } else {
- return gfpow[mod255(gflog[a] - gflog[b])];
- }
-}
-
-
-/* The following functions return the inverse of the matrix of the
- * linear system that needs to be solved to determine the error
- * magnitudes. The first deals with matrices of rank 3, while the
- * second deals with matrices of rank 2. The error indices are passed
- * in arguments L0,..,L2 (0=first sector, 31=last sector). The error
- * indices must be sorted in ascending order, i.e., L0<L1<L2.
- *
- * The linear system that needs to be solved for the error magnitudes
- * is A * b = s, where s is the known vector of syndromes, b is the
- * vector of error magnitudes and A in the ORDER=3 case:
- *
- * A_3 = {{1/r^L[0], 1/r^L[1], 1/r^L[2]},
- * { 1, 1, 1},
- * { r^L[0], r^L[1], r^L[2]}}
- */
-static inline int gfinv3(__u8 l0,
- __u8 l1,
- __u8 l2,
- Matrix Ainv)
-{
- __u8 det;
- __u8 t20, t10, t21, t12, t01, t02;
- int log_det;
-
- /* compute some intermediate results: */
- t20 = gfpow[l2 - l0]; /* t20 = r^l2/r^l0 */
- t10 = gfpow[l1 - l0]; /* t10 = r^l1/r^l0 */
- t21 = gfpow[l2 - l1]; /* t21 = r^l2/r^l1 */
- t12 = gfpow[l1 - l2 + 255]; /* t12 = r^l1/r^l2 */
- t01 = gfpow[l0 - l1 + 255]; /* t01 = r^l0/r^l1 */
- t02 = gfpow[l0 - l2 + 255]; /* t02 = r^l0/r^l2 */
- /* Calculate the determinant of matrix A_3^-1 (sometimes
- * called the Vandermonde determinant):
- */
- det = gfadd(t20, gfadd(t10, gfadd(t21, gfadd(t12, gfadd(t01, t02)))));
- if (!det) {
- TRACE_FUN(ft_t_any);
- TRACE_ABORT(0, ft_t_err,
- "Inversion failed (3 CRC errors, >0 CRC failures)");
- }
- log_det = 255 - gflog[det];
-
- /* Now, calculate all of the coefficients:
- */
- Ainv[0][0]= gfmul_exp(gfadd(gfpow[l1], gfpow[l2]), log_det);
- Ainv[0][1]= gfmul_exp(gfadd(t21, t12), log_det);
- Ainv[0][2]= gfmul_exp(gfadd(gfpow[255 - l1], gfpow[255 - l2]),log_det);
-
- Ainv[1][0]= gfmul_exp(gfadd(gfpow[l0], gfpow[l2]), log_det);
- Ainv[1][1]= gfmul_exp(gfadd(t20, t02), log_det);
- Ainv[1][2]= gfmul_exp(gfadd(gfpow[255 - l0], gfpow[255 - l2]),log_det);
-
- Ainv[2][0]= gfmul_exp(gfadd(gfpow[l0], gfpow[l1]), log_det);
- Ainv[2][1]= gfmul_exp(gfadd(t10, t01), log_det);
- Ainv[2][2]= gfmul_exp(gfadd(gfpow[255 - l0], gfpow[255 - l1]),log_det);
-
- return 1;
-}
-
-
-static inline int gfinv2(__u8 l0, __u8 l1, Matrix Ainv)
-{
- __u8 det;
- __u8 t1, t2;
- int log_det;
-
- t1 = gfpow[255 - l0];
- t2 = gfpow[255 - l1];
- det = gfadd(t1, t2);
- if (!det) {
- TRACE_FUN(ft_t_any);
- TRACE_ABORT(0, ft_t_err,
- "Inversion failed (2 CRC errors, >0 CRC failures)");
- }
- log_det = 255 - gflog[det];
-
- /* Now, calculate all of the coefficients:
- */
- Ainv[0][0] = Ainv[1][0] = gfpow[log_det];
-
- Ainv[0][1] = gfmul_exp(t2, log_det);
- Ainv[1][1] = gfmul_exp(t1, log_det);
-
- return 1;
-}
-
-
-/* Multiply matrix A by vector S and return result in vector B. M is
- * assumed to be of order NxN, S and B of order Nx1.
- */
-static inline void gfmat_mul(int n, Matrix A,
- __u8 *s, __u8 *b)
-{
- int i, j;
- __u8 dot_prod;
-
- for (i = 0; i < n; ++i) {
- dot_prod = 0;
- for (j = 0; j < n; ++j) {
- dot_prod = gfadd(dot_prod, gfmul(A[i][j], s[j]));
- }
- b[i] = dot_prod;
- }
-}
-
-
-
-/* The Reed Solomon ECC codes are computed over the N-th byte of each
- * block, where N=SECTOR_SIZE. There are up to 29 blocks of data, and
- * 3 blocks of ECC. The blocks are stored contiguously in memory. A
- * segment, consequently, is assumed to have at least 4 blocks: one or
- * more data blocks plus three ECC blocks.
- *
- * Notice: In QIC-80 speak, a CRC error is a sector with an incorrect
- * CRC. A CRC failure is a sector with incorrect data, but
- * a valid CRC. In the error control literature, the former
- * is usually called "erasure", the latter "error."
- */
-/* Compute the parity bytes for C columns of data, where C is the
- * number of bytes that fit into a long integer. We use a linear
- * feed-back register to do this. The parity bytes P[0], P[STRIDE],
- * P[2*STRIDE] are computed such that:
- *
- * x^k * p(x) + m(x) = 0 (modulo g(x))
- *
- * where k = NBLOCKS,
- * p(x) = P[0] + P[STRIDE]*x + P[2*STRIDE]*x^2, and
- * m(x) = sum_{i=0}^k m_i*x^i.
- * m_i = DATA[i*SECTOR_SIZE]
- */
-static inline void set_parity(unsigned long *data,
- int nblocks,
- unsigned long *p,
- int stride)
-{
- unsigned long p0, p1, p2, t1, t2, *end;
-
- end = data + nblocks * (FT_SECTOR_SIZE / sizeof(long));
- p0 = p1 = p2 = 0;
- while (data < end) {
- /* The new parity bytes p0_i, p1_i, p2_i are computed
- * from the old values p0_{i-1}, p1_{i-1}, p2_{i-1}
- * recursively as:
- *
- * p0_i = p1_{i-1} + r^105 * (m_{i-1} - p0_{i-1})
- * p1_i = p2_{i-1} + r^105 * (m_{i-1} - p0_{i-1})
- * p2_i = (m_{i-1} - p0_{i-1})
- *
- * With the initial condition: p0_0 = p1_0 = p2_0 = 0.
- */
- t1 = gfadd_long(*data, p0);
- /*
- * Multiply each byte in t1 by 0xc0:
- */
- if (sizeof(long) == 4) {
- t2= (((__u32) gfmul_c0[(__u32)t1 >> 24 & 0xff]) << 24 |
- ((__u32) gfmul_c0[(__u32)t1 >> 16 & 0xff]) << 16 |
- ((__u32) gfmul_c0[(__u32)t1 >> 8 & 0xff]) << 8 |
- ((__u32) gfmul_c0[(__u32)t1 >> 0 & 0xff]) << 0);
- } else if (sizeof(long) == 8) {
- t2= (((__u64) gfmul_c0[(__u64)t1 >> 56 & 0xff]) << 56 |
- ((__u64) gfmul_c0[(__u64)t1 >> 48 & 0xff]) << 48 |
- ((__u64) gfmul_c0[(__u64)t1 >> 40 & 0xff]) << 40 |
- ((__u64) gfmul_c0[(__u64)t1 >> 32 & 0xff]) << 32 |
- ((__u64) gfmul_c0[(__u64)t1 >> 24 & 0xff]) << 24 |
- ((__u64) gfmul_c0[(__u64)t1 >> 16 & 0xff]) << 16 |
- ((__u64) gfmul_c0[(__u64)t1 >> 8 & 0xff]) << 8 |
- ((__u64) gfmul_c0[(__u64)t1 >> 0 & 0xff]) << 0);
- } else {
- TRACE_FUN(ft_t_any);
- TRACE(ft_t_err, "Error: long is of size %d",
- (int) sizeof(long));
- TRACE_EXIT;
- }
- p0 = gfadd_long(t2, p1);
- p1 = gfadd_long(t2, p2);
- p2 = t1;
- data += FT_SECTOR_SIZE / sizeof(long);
- }
- *p = p0;
- p += stride;
- *p = p1;
- p += stride;
- *p = p2;
- return;
-}
-
-
-/* Compute the 3 syndrome values. DATA should point to the first byte
- * of the column for which the syndromes are desired. The syndromes
- * are computed over the first NBLOCKS of rows. The three bytes will
- * be placed in S[0], S[1], and S[2].
- *
- * S[i] is the value of the "message" polynomial m(x) evaluated at the
- * i-th root of the generator polynomial g(x).
- *
- * As g(x)=(x-r^-1)(x-1)(x-r^1) we evaluate the message polynomial at
- * x=r^-1 to get S[0], at x=r^0=1 to get S[1], and at x=r to get S[2].
- * This could be done directly and efficiently via the Horner scheme.
- * However, it would require multiplication tables for the factors
- * r^-1 (0xc3) and r (0x02). The following scheme does not require
- * any multiplication tables beyond what's needed for set_parity()
- * anyway and is slightly faster if there are no errors and slightly
- * slower if there are errors. The latter is hopefully the infrequent
- * case.
- *
- * To understand the alternative algorithm, notice that set_parity(m,
- * k, p) computes parity bytes such that:
- *
- * x^k * p(x) = m(x) (modulo g(x)).
- *
- * That is, to evaluate m(r^m), where r^m is a root of g(x), we can
- * simply evaluate (r^m)^k*p(r^m). Also, notice that p is 0 if and
- * only if s is zero. That is, if all parity bytes are 0, we know
- * there is no error in the data and consequently there is no need to
- * compute s(x) at all! In all other cases, we compute s(x) from p(x)
- * by evaluating (r^m)^k*p(r^m) for m=-1, m=0, and m=1. The p(x)
- * polynomial is evaluated via the Horner scheme.
- */
-static int compute_syndromes(unsigned long *data, int nblocks, unsigned long *s)
-{
- unsigned long p[3];
-
- set_parity(data, nblocks, p, 1);
- if (p[0] | p[1] | p[2]) {
- /* Some of the checked columns do not have a zero
- * syndrome. For simplicity, we compute the syndromes
- * for all columns that we have computed the
- * remainders for.
- */
- s[0] = gfmul_exp_long(
- gfadd_long(p[0],
- gfmul_exp_long(
- gfadd_long(p[1],
- gfmul_exp_long(p[2], -1)),
- -1)),
- -nblocks);
- s[1] = gfadd_long(gfadd_long(p[2], p[1]), p[0]);
- s[2] = gfmul_exp_long(
- gfadd_long(p[0],
- gfmul_exp_long(
- gfadd_long(p[1],
- gfmul_exp_long(p[2], 1)),
- 1)),
- nblocks);
- return 0;
- } else {
- return 1;
- }
-}
-
-
-/* Correct the block in the column pointed to by DATA. There are NBAD
- * CRC errors and their indices are in BAD_LOC[0], up to
- * BAD_LOC[NBAD-1]. If NBAD>1, Ainv holds the inverse of the matrix
- * of the linear system that needs to be solved to determine the error
- * magnitudes. S[0], S[1], and S[2] are the syndrome values. If row
- * j gets corrected, then bit j will be set in CORRECTION_MAP.
- */
-static inline int correct_block(__u8 *data, int nblocks,
- int nbad, int *bad_loc, Matrix Ainv,
- __u8 *s,
- SectorMap * correction_map)
-{
- int ncorrected = 0;
- int i;
- __u8 t1, t2;
- __u8 c0, c1, c2; /* check bytes */
- __u8 error_mag[3], log_error_mag;
- __u8 *dp, l, e;
- TRACE_FUN(ft_t_any);
-
- switch (nbad) {
- case 0:
- /* might have a CRC failure: */
- if (s[0] == 0) {
- /* more than one error */
- TRACE_ABORT(-1, ft_t_err,
- "ECC failed (0 CRC errors, >1 CRC failures)");
- }
- t1 = gfdiv(s[1], s[0]);
- if ((bad_loc[nbad++] = gflog[t1]) >= nblocks) {
- TRACE(ft_t_err,
- "ECC failed (0 CRC errors, >1 CRC failures)");
- TRACE_ABORT(-1, ft_t_err,
- "attempt to correct data at %d", bad_loc[0]);
- }
- error_mag[0] = s[1];
- break;
- case 1:
- t1 = gfadd(gfmul_exp(s[1], bad_loc[0]), s[2]);
- t2 = gfadd(gfmul_exp(s[0], bad_loc[0]), s[1]);
- if (t1 == 0 && t2 == 0) {
- /* one erasure, no error: */
- Ainv[0][0] = gfpow[bad_loc[0]];
- } else if (t1 == 0 || t2 == 0) {
- /* one erasure and more than one error: */
- TRACE_ABORT(-1, ft_t_err,
- "ECC failed (1 erasure, >1 error)");
- } else {
- /* one erasure, one error: */
- if ((bad_loc[nbad++] = gflog[gfdiv(t1, t2)])
- >= nblocks) {
- TRACE(ft_t_err, "ECC failed "
- "(1 CRC errors, >1 CRC failures)");
- TRACE_ABORT(-1, ft_t_err,
- "attempt to correct data at %d",
- bad_loc[1]);
- }
- if (!gfinv2(bad_loc[0], bad_loc[1], Ainv)) {
- /* inversion failed---must have more
- * than one error
- */
- TRACE_EXIT -1;
- }
- }
- /* FALL THROUGH TO ERROR MAGNITUDE COMPUTATION:
- */
- case 2:
- case 3:
- /* compute error magnitudes: */
- gfmat_mul(nbad, Ainv, s, error_mag);
- break;
-
- default:
- TRACE_ABORT(-1, ft_t_err,
- "Internal Error: number of CRC errors > 3");
- }
-
- /* Perform correction by adding ERROR_MAG[i] to the byte at
- * offset BAD_LOC[i]. Also add the value of the computed
- * error polynomial to the syndrome values. If the correction
- * was successful, the resulting check bytes should be zero
- * (i.e., the corrected data is a valid code word).
- */
- c0 = s[0];
- c1 = s[1];
- c2 = s[2];
- for (i = 0; i < nbad; ++i) {
- e = error_mag[i];
- if (e) {
- /* correct the byte at offset L by magnitude E: */
- l = bad_loc[i];
- dp = &data[l * FT_SECTOR_SIZE];
- *dp = gfadd(*dp, e);
- *correction_map |= 1 << l;
- ++ncorrected;
-
- log_error_mag = gflog[e];
- c0 = gfadd(c0, gfpow[mod255(log_error_mag - l)]);
- c1 = gfadd(c1, e);
- c2 = gfadd(c2, gfpow[mod255(log_error_mag + l)]);
- }
- }
- if (c0 || c1 || c2) {
- TRACE_ABORT(-1, ft_t_err,
- "ECC self-check failed, too many errors");
- }
- TRACE_EXIT ncorrected;
-}
-
-
-#if defined(ECC_SANITY_CHECK) || defined(ECC_PARANOID)
-
-/* Perform a sanity check on the computed parity bytes:
- */
-static int sanity_check(unsigned long *data, int nblocks)
-{
- TRACE_FUN(ft_t_any);
- unsigned long s[3];
-
- if (!compute_syndromes(data, nblocks, s)) {
- TRACE_ABORT(0, ft_bug,
- "Internal Error: syndrome self-check failed");
- }
- TRACE_EXIT 1;
-}
-
-#endif /* defined(ECC_SANITY_CHECK) || defined(ECC_PARANOID) */
-
-/* Compute the parity for an entire segment of data.
- */
-int ftape_ecc_set_segment_parity(struct memory_segment *mseg)
-{
- int i;
- __u8 *parity_bytes;
-
- parity_bytes = &mseg->data[(mseg->blocks - 3) * FT_SECTOR_SIZE];
- for (i = 0; i < FT_SECTOR_SIZE; i += sizeof(long)) {
- set_parity((unsigned long *) &mseg->data[i], mseg->blocks - 3,
- (unsigned long *) &parity_bytes[i],
- FT_SECTOR_SIZE / sizeof(long));
-#ifdef ECC_PARANOID
- if (!sanity_check((unsigned long *) &mseg->data[i],
- mseg->blocks)) {
- return -1;
- }
-#endif /* ECC_PARANOID */
- }
- return 0;
-}
-
-
-/* Checks and corrects (if possible) the segment MSEG. Returns one of
- * ECC_OK, ECC_CORRECTED, and ECC_FAILED.
- */
-int ftape_ecc_correct_data(struct memory_segment *mseg)
-{
- int col, i, result;
- int ncorrected = 0;
- int nerasures = 0; /* # of erasures (CRC errors) */
- int erasure_loc[3]; /* erasure locations */
- unsigned long ss[3];
- __u8 s[3];
- Matrix Ainv;
- TRACE_FUN(ft_t_flow);
-
- mseg->corrected = 0;
-
- /* find first column that has non-zero syndromes: */
- for (col = 0; col < FT_SECTOR_SIZE; col += sizeof(long)) {
- if (!compute_syndromes((unsigned long *) &mseg->data[col],
- mseg->blocks, ss)) {
- /* something is wrong---have to fix things */
- break;
- }
- }
- if (col >= FT_SECTOR_SIZE) {
- /* all syndromes are ok, therefore nothing to correct */
- TRACE_EXIT ECC_OK;
- }
- /* count the number of CRC errors if there were any: */
- if (mseg->read_bad) {
- for (i = 0; i < mseg->blocks; i++) {
- if (BAD_CHECK(mseg->read_bad, i)) {
- if (nerasures >= 3) {
- /* this is too much for ECC */
- TRACE_ABORT(ECC_FAILED, ft_t_err,
- "ECC failed (>3 CRC errors)");
- } /* if */
- erasure_loc[nerasures++] = i;
- }
- }
- }
- /*
- * If there are at least 2 CRC errors, determine inverse of matrix
- * of linear system to be solved:
- */
- switch (nerasures) {
- case 2:
- if (!gfinv2(erasure_loc[0], erasure_loc[1], Ainv)) {
- TRACE_EXIT ECC_FAILED;
- }
- break;
- case 3:
- if (!gfinv3(erasure_loc[0], erasure_loc[1],
- erasure_loc[2], Ainv)) {
- TRACE_EXIT ECC_FAILED;
- }
- break;
- default:
- /* this is not an error condition... */
- break;
- }
-
- do {
- for (i = 0; i < sizeof(long); ++i) {
- s[0] = ss[0];
- s[1] = ss[1];
- s[2] = ss[2];
- if (s[0] | s[1] | s[2]) {
-#ifdef BIG_ENDIAN
- result = correct_block(
- &mseg->data[col + sizeof(long) - 1 - i],
- mseg->blocks,
- nerasures,
- erasure_loc,
- Ainv,
- s,
- &mseg->corrected);
-#else
- result = correct_block(&mseg->data[col + i],
- mseg->blocks,
- nerasures,
- erasure_loc,
- Ainv,
- s,
- &mseg->corrected);
-#endif
- if (result < 0) {
- TRACE_EXIT ECC_FAILED;
- }
- ncorrected += result;
- }
- ss[0] >>= 8;
- ss[1] >>= 8;
- ss[2] >>= 8;
- }
-
-#ifdef ECC_SANITY_CHECK
- if (!sanity_check((unsigned long *) &mseg->data[col],
- mseg->blocks)) {
- TRACE_EXIT ECC_FAILED;
- }
-#endif /* ECC_SANITY_CHECK */
-
- /* find next column with non-zero syndromes: */
- while ((col += sizeof(long)) < FT_SECTOR_SIZE) {
- if (!compute_syndromes((unsigned long *)
- &mseg->data[col], mseg->blocks, ss)) {
- /* something is wrong---have to fix things */
- break;
- }
- }
- } while (col < FT_SECTOR_SIZE);
- if (ncorrected && nerasures == 0) {
- TRACE(ft_t_warn, "block contained error not caught by CRC");
- }
- TRACE((ncorrected > 0) ? ft_t_noise : ft_t_any, "number of corrections: %d", ncorrected);
- TRACE_EXIT ncorrected ? ECC_CORRECTED : ECC_OK;
-}
diff --git a/drivers/char/ftape/lowlevel/ftape-ecc.h b/drivers/char/ftape/lowlevel/ftape-ecc.h
deleted file mode 100644
index 4829146fe9a0..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-ecc.h
+++ /dev/null
@@ -1,84 +0,0 @@
-#ifndef _FTAPE_ECC_H_
-#define _FTAPE_ECC_H_
-
-/*
- * Copyright (C) 1993 Ning and David Mosberger.
- * Original:
- * Copyright (C) 1993 Bas Laarhoven.
- * Copyright (C) 1992 David L. Brown, Jr.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
- USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-ecc.h,v $
- * $Revision: 1.2 $
- * $Date: 1997/10/05 19:18:11 $
- *
- * This file contains the definitions for the
- * Reed-Solomon error correction code
- * for the QIC-40/80 tape streamer device driver.
- */
-
-#include "../lowlevel/ftape-bsm.h"
-
-#define BAD_CLEAR(entry) ((entry)=0)
-#define BAD_SET(entry,sector) ((entry)|=(1<<(sector)))
-#define BAD_CHECK(entry,sector) ((entry)&(1<<(sector)))
-
-/*
- * Return values for ecc_correct_data:
- */
-enum {
- ECC_OK, /* Data was correct. */
- ECC_CORRECTED, /* Correctable error in data. */
- ECC_FAILED, /* Could not correct data. */
-};
-
-/*
- * Representation of an in memory segment. MARKED_BAD lists the
- * sectors that were marked bad during formatting. If the N-th sector
- * in a segment is marked bad, bit 1<<N will be set in MARKED_BAD.
- * The sectors should be read in from the disk and packed, as if the
- * bad sectors were not there, and the segment just contained fewer
- * sectors. READ_SECTORS is a bitmap of errors encountered while
- * reading the data. These offsets are relative to the packed data.
- * BLOCKS is a count of the sectors not marked bad. This is just to
- * prevent having to count the zero bits in MARKED_BAD each time this
- * is needed. DATA is the actual sector packed data from (or to) the
- * tape.
- */
- struct memory_segment {
- SectorMap marked_bad;
- SectorMap read_bad;
- int blocks;
- __u8 *data;
- SectorMap corrected;
- };
-
-/*
- * ecc.c defined global variables:
- */
-#ifdef TEST
-extern int ftape_ecc_tracing;
-#endif
-
-/*
- * ecc.c defined global functions:
- */
-extern int ftape_ecc_correct_data(struct memory_segment *data);
-extern int ftape_ecc_set_segment_parity(struct memory_segment *data);
-
-#endif /* _FTAPE_ECC_H_ */
diff --git a/drivers/char/ftape/lowlevel/ftape-format.c b/drivers/char/ftape/lowlevel/ftape-format.c
deleted file mode 100644
index 5dd4c59a3f34..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-format.c
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- * Copyright (C) 1997 Claus-Justus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-format.c,v $
- * $Revision: 1.2.4.1 $
- * $Date: 1997/11/14 16:05:39 $
- *
- * This file contains the code to support formatting of floppy
- * tape cartridges with the QIC-40/80/3010/3020 floppy-tape
- * driver "ftape" for Linux.
- */
-
-#include <linux/string.h>
-#include <linux/errno.h>
-
-#include <linux/ftape.h>
-#include <linux/qic117.h>
-#include "../lowlevel/ftape-tracing.h"
-#include "../lowlevel/ftape-io.h"
-#include "../lowlevel/ftape-ctl.h"
-#include "../lowlevel/ftape-rw.h"
-#include "../lowlevel/ftape-ecc.h"
-#include "../lowlevel/ftape-bsm.h"
-#include "../lowlevel/ftape-format.h"
-
-#if defined(TESTING)
-#define FT_FMT_SEGS_PER_BUF 50
-#else
-#define FT_FMT_SEGS_PER_BUF (FT_BUFF_SIZE/(4*FT_SECTORS_PER_SEGMENT))
-#endif
-
-static spinlock_t ftape_format_lock;
-
-/*
- * first segment of the new buffer
- */
-static int switch_segment;
-
-/*
- * at most 256 segments fit into one 32 kb buffer. Even TR-1 cartridges have
- * more than this many segments per track, so better be careful.
- *
- * buffer_struct *buff: buffer to store the formatting coordinates in
- * int start: starting segment for this buffer.
- * int spt: segments per track
- *
- * Note: segment ids are relative to the start of the track here.
- */
-static void setup_format_buffer(buffer_struct *buff, int start, int spt,
- __u8 gap3)
-{
- int to_do = spt - start;
- TRACE_FUN(ft_t_flow);
-
- if (to_do > FT_FMT_SEGS_PER_BUF) {
- to_do = FT_FMT_SEGS_PER_BUF;
- }
- buff->ptr = buff->address;
- buff->remaining = to_do * FT_SECTORS_PER_SEGMENT; /* # sectors */
- buff->bytes = buff->remaining * 4; /* need 4 bytes per sector */
- buff->gap3 = gap3;
- buff->segment_id = start;
- buff->next_segment = start + to_do;
- if (buff->next_segment >= spt) {
- buff->next_segment = 0; /* 0 means: stop runner */
- }
- buff->status = waiting; /* tells the isr that it can use
- * this buffer
- */
- TRACE_EXIT;
-}
-
-
-/*
- * start formatting a new track.
- */
-int ftape_format_track(const unsigned int track, const __u8 gap3)
-{
- unsigned long flags;
- buffer_struct *tail, *head;
- int status;
- TRACE_FUN(ft_t_flow);
-
- TRACE_CATCH(ftape_ready_wait(ftape_timeout.pause, &status),);
- if (track & 1) {
- if (!(status & QIC_STATUS_AT_EOT)) {
- TRACE_CATCH(ftape_seek_to_eot(),);
- }
- } else {
- if (!(status & QIC_STATUS_AT_BOT)) {
- TRACE_CATCH(ftape_seek_to_bot(),);
- }
- }
- ftape_abort_operation(); /* this sets ft_head = ft_tail = 0 */
- ftape_set_state(formatting);
-
- TRACE(ft_t_noise,
- "Formatting track %d, logical: from segment %d to %d",
- track, track * ft_segments_per_track,
- (track + 1) * ft_segments_per_track - 1);
-
- /*
- * initialize the buffer switching protocol for this track
- */
- head = ftape_get_buffer(ft_queue_head); /* tape isn't running yet */
- tail = ftape_get_buffer(ft_queue_tail); /* tape isn't running yet */
- switch_segment = 0;
- do {
- FT_SIGNAL_EXIT(_DONT_BLOCK);
- setup_format_buffer(tail, switch_segment,
- ft_segments_per_track, gap3);
- switch_segment = tail->next_segment;
- } while ((switch_segment != 0) &&
- ((tail = ftape_next_buffer(ft_queue_tail)) != head));
- /* go */
- head->status = formatting;
- TRACE_CATCH(ftape_seek_head_to_track(track),);
- TRACE_CATCH(ftape_command(QIC_LOGICAL_FORWARD),);
- spin_lock_irqsave(&ftape_format_lock, flags);
- TRACE_CATCH(fdc_setup_formatting(head), restore_flags(flags));
- spin_unlock_irqrestore(&ftape_format_lock, flags);
- TRACE_EXIT 0;
-}
-
-/* return segment id of segment currently being formatted and do the
- * buffer switching stuff.
- */
-int ftape_format_status(unsigned int *segment_id)
-{
- buffer_struct *tail = ftape_get_buffer(ft_queue_tail);
- int result;
- TRACE_FUN(ft_t_flow);
-
- while (switch_segment != 0 &&
- ftape_get_buffer(ft_queue_head) != tail) {
- FT_SIGNAL_EXIT(_DONT_BLOCK);
- /* need more buffers, first wait for empty buffer
- */
- TRACE_CATCH(ftape_wait_segment(formatting),);
- /* don't worry for gap3. If we ever hit this piece of code,
- * then all buffer already have the correct gap3 set!
- */
- setup_format_buffer(tail, switch_segment,
- ft_segments_per_track, tail->gap3);
- switch_segment = tail->next_segment;
- if (switch_segment != 0) {
- tail = ftape_next_buffer(ft_queue_tail);
- }
- }
- /* should runner stop ?
- */
- if (ft_runner_status == aborting || ft_runner_status == do_abort) {
- buffer_struct *head = ftape_get_buffer(ft_queue_head);
- TRACE(ft_t_warn, "Error formatting segment %d",
- ftape_get_buffer(ft_queue_head)->segment_id);
- (void)ftape_abort_operation();
- TRACE_EXIT (head->status != error) ? -EAGAIN : -EIO;
- }
- /*
- * don't care if the timer expires, this is just kind of a
- * "select" operation that lets the calling process sleep
- * until something has happened
- */
- if (fdc_interrupt_wait(5 * FT_SECOND) < 0) {
- TRACE(ft_t_noise, "End of track %d at segment %d",
- ft_location.track,
- ftape_get_buffer(ft_queue_head)->segment_id);
- result = 1; /* end of track, unlock module */
- } else {
- result = 0;
- }
- /*
- * the calling process should use the seg id to determine
- * which parts of the dma buffers can be safely overwritten
- * with new data.
- */
- *segment_id = ftape_get_buffer(ft_queue_head)->segment_id;
- /*
- * Internally we start counting segment ids from the start of
- * each track when formatting, but externally we keep them
- * relative to the start of the tape:
- */
- *segment_id += ft_location.track * ft_segments_per_track;
- TRACE_EXIT result;
-}
-
-/*
- * The segment id is relative to the start of the tape
- */
-int ftape_verify_segment(const unsigned int segment_id, SectorMap *bsm)
-{
- int result;
- int verify_done = 0;
- TRACE_FUN(ft_t_flow);
-
- TRACE(ft_t_noise, "Verifying segment %d", segment_id);
-
- if (ft_driver_state != verifying) {
- TRACE(ft_t_noise, "calling ftape_abort_operation");
- if (ftape_abort_operation() < 0) {
- TRACE(ft_t_err, "ftape_abort_operation failed");
- TRACE_EXIT -EIO;
- }
- }
- *bsm = 0x00000000;
- ftape_set_state(verifying);
- for (;;) {
- buffer_struct *tail;
- /*
- * Allow escape from this loop on signal
- */
- FT_SIGNAL_EXIT(_DONT_BLOCK);
- /*
- * Search all full buffers for the first matching the
- * wanted segment. Clear other buffers on the fly.
- */
- tail = ftape_get_buffer(ft_queue_tail);
- while (!verify_done && tail->status == done) {
- /*
- * Allow escape from this loop on signal !
- */
- FT_SIGNAL_EXIT(_DONT_BLOCK);
- if (tail->segment_id == segment_id) {
- /* If out buffer is already full,
- * return its contents.
- */
- TRACE(ft_t_flow, "found segment in cache: %d",
- segment_id);
- if ((tail->soft_error_map |
- tail->hard_error_map) != 0) {
- TRACE(ft_t_info,"bsm[%d] = 0x%08lx",
- segment_id,
- (unsigned long)
- (tail->soft_error_map |
- tail->hard_error_map));
- *bsm = (tail->soft_error_map |
- tail->hard_error_map);
- }
- verify_done = 1;
- } else {
- TRACE(ft_t_flow,"zapping segment in cache: %d",
- tail->segment_id);
- }
- tail->status = waiting;
- tail = ftape_next_buffer(ft_queue_tail);
- }
- if (!verify_done && tail->status == verifying) {
- if (tail->segment_id == segment_id) {
- switch(ftape_wait_segment(verifying)) {
- case 0:
- break;
- case -EINTR:
- TRACE_ABORT(-EINTR, ft_t_warn,
- "interrupted by "
- "non-blockable signal");
- break;
- default:
- ftape_abort_operation();
- ftape_set_state(verifying);
- /* be picky */
- TRACE_ABORT(-EIO, ft_t_warn,
- "wait_segment failed");
- }
- } else {
- /* We're reading the wrong segment,
- * stop runner.
- */
- TRACE(ft_t_noise, "verifying wrong segment");
- ftape_abort_operation();
- ftape_set_state(verifying);
- }
- }
- /* should runner stop ?
- */
- if (ft_runner_status == aborting) {
- buffer_struct *head = ftape_get_buffer(ft_queue_head);
- if (head->status == error ||
- head->status == verifying) {
- /* no data or overrun error */
- head->status = waiting;
- }
- TRACE_CATCH(ftape_dumb_stop(),);
- } else {
- /* If just passed last segment on tape: wait
- * for BOT or EOT mark. Sets ft_runner_status to
- * idle if at lEOT and successful
- */
- TRACE_CATCH(ftape_handle_logical_eot(),);
- }
- if (verify_done) {
- TRACE_EXIT 0;
- }
- /* Now at least one buffer is idle!
- * Restart runner & tape if needed.
- */
- /* We could optimize the following a little bit. We know that
- * the bad sector map is empty.
- */
- tail = ftape_get_buffer(ft_queue_tail);
- if (tail->status == waiting) {
- buffer_struct *head = ftape_get_buffer(ft_queue_head);
-
- ftape_setup_new_segment(head, segment_id, -1);
- ftape_calc_next_cluster(head);
- if (ft_runner_status == idle) {
- result = ftape_start_tape(segment_id,
- head->sector_offset);
- switch(result) {
- case 0:
- break;
- case -ETIME:
- case -EINTR:
- TRACE_ABORT(result, ft_t_err, "Error: "
- "segment %d unreachable",
- segment_id);
- break;
- default:
- *bsm = EMPTY_SEGMENT;
- TRACE_EXIT 0;
- break;
- }
- }
- head->status = verifying;
- fdc_setup_read_write(head, FDC_VERIFY);
- }
- }
- /* not reached */
- TRACE_EXIT -EIO;
-}
diff --git a/drivers/char/ftape/lowlevel/ftape-format.h b/drivers/char/ftape/lowlevel/ftape-format.h
deleted file mode 100644
index f15161566643..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-format.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef _FTAPE_FORMAT_H
-#define _FTAPE_FORMAT_H
-
-/*
- * Copyright (C) 1996-1997 Claus-Justus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-format.h,v $
- * $Revision: 1.2 $
- * $Date: 1997/10/05 19:18:13 $
- *
- * This file contains the low level definitions for the
- * formatting support for the QIC-40/80/3010/3020 floppy-tape
- * driver "ftape" for Linux.
- */
-
-#ifdef __KERNEL__
-extern int ftape_format_track(const unsigned int track, const __u8 gap3);
-extern int ftape_format_status(unsigned int *segment_id);
-extern int ftape_verify_segment(const unsigned int segment_id, SectorMap *bsm);
-#endif /* __KERNEL__ */
-
-#endif
diff --git a/drivers/char/ftape/lowlevel/ftape-init.c b/drivers/char/ftape/lowlevel/ftape-init.c
deleted file mode 100644
index 4998132a81d1..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-init.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (C) 1993-1996 Bas Laarhoven,
- * (C) 1996-1997 Claus-Justus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * This file contains the code that interfaces the kernel
- * for the QIC-40/80/3010/3020 floppy-tape driver for Linux.
- */
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/signal.h>
-#include <linux/major.h>
-
-#include <linux/ftape.h>
-#include <linux/init.h>
-#include <linux/qic117.h>
-#ifdef CONFIG_ZFTAPE
-#include <linux/zftape.h>
-#endif
-
-#include "../lowlevel/ftape-init.h"
-#include "../lowlevel/ftape-io.h"
-#include "../lowlevel/ftape-read.h"
-#include "../lowlevel/ftape-write.h"
-#include "../lowlevel/ftape-ctl.h"
-#include "../lowlevel/ftape-rw.h"
-#include "../lowlevel/fdc-io.h"
-#include "../lowlevel/ftape-buffer.h"
-#include "../lowlevel/ftape-proc.h"
-#include "../lowlevel/ftape-tracing.h"
-
-
-#if defined(MODULE) && !defined(CONFIG_FT_NO_TRACE_AT_ALL)
-static int ft_tracing = -1;
-#endif
-
-
-/* Called by modules package when installing the driver
- * or by kernel during the initialization phase
- */
-static int __init ftape_init(void)
-{
- TRACE_FUN(ft_t_flow);
-
-#ifdef MODULE
-#ifndef CONFIG_FT_NO_TRACE_AT_ALL
- if (ft_tracing != -1) {
- ftape_tracing = ft_tracing;
- }
-#endif
- printk(KERN_INFO FTAPE_VERSION "\n");
- if (TRACE_LEVEL >= ft_t_info) {
- printk(
-KERN_INFO "(c) 1993-1996 Bas Laarhoven (bas@vimec.nl)\n"
-KERN_INFO "(c) 1995-1996 Kai Harrekilde-Petersen (khp@dolphinics.no)\n"
-KERN_INFO "(c) 1996-1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de)\n"
-KERN_INFO "QIC-117 driver for QIC-40/80/3010/3020 floppy tape drives\n");
- }
-#else /* !MODULE */
- /* print a short no-nonsense boot message */
- printk(KERN_INFO FTAPE_VERSION "\n");
-#endif /* MODULE */
- TRACE(ft_t_info, "installing QIC-117 floppy tape hardware drive ... ");
- TRACE(ft_t_info, "ftape_init @ 0x%p", ftape_init);
- /* Allocate the DMA buffers. They are deallocated at cleanup() time.
- */
-#ifdef TESTING
-#ifdef MODULE
- while (ftape_set_nr_buffers(CONFIG_FT_NR_BUFFERS) < 0) {
- ftape_sleep(FT_SECOND/20);
- if (signal_pending(current)) {
- (void)ftape_set_nr_buffers(0);
- TRACE(ft_t_bug,
- "Killed by signal while allocating buffers.");
- TRACE_ABORT(-EINTR,
- ft_t_bug, "Free up memory and retry");
- }
- }
-#else
- TRACE_CATCH(ftape_set_nr_buffers(CONFIG_FT_NR_BUFFERS),
- (void)ftape_set_nr_buffers(0));
-#endif
-#else
- TRACE_CATCH(ftape_set_nr_buffers(CONFIG_FT_NR_BUFFERS),
- (void)ftape_set_nr_buffers(0));
-#endif
- ft_drive_sel = -1;
- ft_failure = 1; /* inhibit any operation but open */
- ftape_udelay_calibrate(); /* must be before fdc_wait_calibrate ! */
- fdc_wait_calibrate();
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_FT_PROC_FS)
- (void)ftape_proc_init();
-#endif
-#ifdef CONFIG_ZFTAPE
- (void)zft_init();
-#endif
- TRACE_EXIT 0;
-}
-
-module_param(ft_fdc_base, uint, 0);
-MODULE_PARM_DESC(ft_fdc_base, "Base address of FDC controller.");
-module_param(ft_fdc_irq, uint, 0);
-MODULE_PARM_DESC(ft_fdc_irq, "IRQ (interrupt channel) to use.");
-module_param(ft_fdc_dma, uint, 0);
-MODULE_PARM_DESC(ft_fdc_dma, "DMA channel to use.");
-module_param(ft_fdc_threshold, uint, 0);
-MODULE_PARM_DESC(ft_fdc_threshold, "Threshold of the FDC Fifo.");
-module_param(ft_fdc_rate_limit, uint, 0);
-MODULE_PARM_DESC(ft_fdc_rate_limit, "Maximal data rate for FDC.");
-module_param(ft_probe_fc10, bool, 0);
-MODULE_PARM_DESC(ft_probe_fc10,
- "If non-zero, probe for a Colorado FC-10/FC-20 controller.");
-module_param(ft_mach2, bool, 0);
-MODULE_PARM_DESC(ft_mach2,
- "If non-zero, probe for a Mountain MACH-2 controller.");
-#if defined(MODULE) && !defined(CONFIG_FT_NO_TRACE_AT_ALL)
-module_param(ft_tracing, int, 0644);
-MODULE_PARM_DESC(ft_tracing,
- "Amount of debugging output, 0 <= tracing <= 8, default 3.");
-#endif
-
-MODULE_AUTHOR(
- "(c) 1993-1996 Bas Laarhoven (bas@vimec.nl), "
- "(c) 1995-1996 Kai Harrekilde-Petersen (khp@dolphinics.no), "
- "(c) 1996, 1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de)");
-MODULE_DESCRIPTION(
- "QIC-117 driver for QIC-40/80/3010/3020 floppy tape drives.");
-MODULE_LICENSE("GPL");
-
-static void __exit ftape_exit(void)
-{
- TRACE_FUN(ft_t_flow);
-
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_FT_PROC_FS)
- ftape_proc_destroy();
-#endif
- (void)ftape_set_nr_buffers(0);
- printk(KERN_INFO "ftape: unloaded.\n");
- TRACE_EXIT;
-}
-
-module_init(ftape_init);
-module_exit(ftape_exit);
diff --git a/drivers/char/ftape/lowlevel/ftape-init.h b/drivers/char/ftape/lowlevel/ftape-init.h
deleted file mode 100644
index 99a7b8ab086f..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-init.h
+++ /dev/null
@@ -1,43 +0,0 @@
-#ifndef _FTAPE_INIT_H
-#define _FTAPE_INIT_H
-
-/*
- * Copyright (C) 1993-1996 Bas Laarhoven,
- * (C) 1996-1997 Claus-Justus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-init.h,v $
- * $Revision: 1.2 $
- * $Date: 1997/10/05 19:18:16 $
- *
- * This file contains the definitions for the interface to
- * the Linux kernel for floppy tape driver ftape.
- *
- */
-
-#include <linux/linkage.h>
-#include <linux/signal.h>
-
-#define _NEVER_BLOCK (sigmask(SIGKILL) | sigmask(SIGSTOP))
-#define _DONT_BLOCK (_NEVER_BLOCK | sigmask(SIGINT))
-#define _DO_BLOCK (sigmask(SIGPIPE))
-
-#ifndef QIC117_TAPE_MAJOR
-#define QIC117_TAPE_MAJOR 27
-#endif
-
-#endif
diff --git a/drivers/char/ftape/lowlevel/ftape-io.c b/drivers/char/ftape/lowlevel/ftape-io.c
deleted file mode 100644
index 259015aeff55..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-io.c
+++ /dev/null
@@ -1,992 +0,0 @@
-/*
- * Copyright (C) 1993-1996 Bas Laarhoven,
- * (C) 1996 Kai Harrekilde-Petersen,
- * (C) 1997 Claus-Justus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-io.c,v $
- * $Revision: 1.4 $
- * $Date: 1997/11/11 14:02:36 $
- *
- * This file contains the general control functions for the
- * QIC-40/80/3010/3020 floppy-tape driver "ftape" for Linux.
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <asm/system.h>
-#include <linux/ioctl.h>
-#include <linux/mtio.h>
-#include <linux/delay.h>
-
-#include <linux/ftape.h>
-#include <linux/qic117.h>
-#include "../lowlevel/ftape-tracing.h"
-#include "../lowlevel/fdc-io.h"
-#include "../lowlevel/ftape-io.h"
-#include "../lowlevel/ftape-ctl.h"
-#include "../lowlevel/ftape-rw.h"
-#include "../lowlevel/ftape-write.h"
-#include "../lowlevel/ftape-read.h"
-#include "../lowlevel/ftape-init.h"
-#include "../lowlevel/ftape-calibr.h"
-
-/* Global vars.
- */
-/* NOTE: sectors start numbering at 1, all others at 0 ! */
-ft_timeout_table ftape_timeout;
-unsigned int ftape_tape_len;
-volatile qic117_cmd_t ftape_current_command;
-const struct qic117_command_table qic117_cmds[] = QIC117_COMMANDS;
-int ftape_might_be_off_track;
-
-/* Local vars.
- */
-static int diagnostic_mode;
-static unsigned int ftape_udelay_count;
-static unsigned int ftape_udelay_time;
-
-void ftape_udelay(unsigned int usecs)
-{
- volatile int count = (ftape_udelay_count * usecs +
- ftape_udelay_count - 1) / ftape_udelay_time;
- volatile int i;
-
- while (count-- > 0) {
- for (i = 0; i < 20; ++i);
- }
-}
-
-void ftape_udelay_calibrate(void)
-{
- ftape_calibrate("ftape_udelay",
- ftape_udelay, &ftape_udelay_count, &ftape_udelay_time);
-}
-
-/* Delay (msec) routine.
- */
-void ftape_sleep(unsigned int time)
-{
- TRACE_FUN(ft_t_any);
-
- time *= 1000; /* msecs -> usecs */
- if (time < FT_USPT) {
- /* Time too small for scheduler, do a busy wait ! */
- ftape_udelay(time);
- } else {
- long timeout;
- unsigned long flags;
- unsigned int ticks = (time + FT_USPT - 1) / FT_USPT;
-
- TRACE(ft_t_any, "%d msec, %d ticks", time/1000, ticks);
- timeout = ticks;
- save_flags(flags);
- sti();
- msleep_interruptible(jiffies_to_msecs(timeout));
- /* Mmm. Isn't current->blocked == 0xffffffff ?
- */
- if (signal_pending(current)) {
- TRACE(ft_t_err, "awoken by non-blocked signal :-(");
- }
- restore_flags(flags);
- }
- TRACE_EXIT;
-}
-
-/* send a command or parameter to the drive
- * Generates # of step pulses.
- */
-static inline int ft_send_to_drive(int arg)
-{
- /* Always wait for a command_timeout period to separate
- * individuals commands and/or parameters.
- */
- ftape_sleep(3 * FT_MILLISECOND);
- /* Keep cylinder nr within range, step towards home if possible.
- */
- if (ftape_current_cylinder >= arg) {
- return fdc_seek(ftape_current_cylinder - arg);
- } else {
- return fdc_seek(ftape_current_cylinder + arg);
- }
-}
-
-/* forward */ int ftape_report_raw_drive_status(int *status);
-
-static int ft_check_cmd_restrictions(qic117_cmd_t command)
-{
- int status = -1;
- TRACE_FUN(ft_t_any);
-
- TRACE(ft_t_flow, "%s", qic117_cmds[command].name);
- /* A new motion command during an uninterruptible (motion)
- * command requires a ready status before the new command can
- * be issued. Otherwise a new motion command needs to be
- * checked against required status.
- */
- if (qic117_cmds[command].cmd_type == motion &&
- qic117_cmds[ftape_current_command].non_intr) {
- ftape_report_raw_drive_status(&status);
- if ((status & QIC_STATUS_READY) == 0) {
- TRACE(ft_t_noise,
- "motion cmd (%d) during non-intr cmd (%d)",
- command, ftape_current_command);
- TRACE(ft_t_noise, "waiting until drive gets ready");
- ftape_ready_wait(ftape_timeout.seek,
- &status);
- }
- }
- if (qic117_cmds[command].mask != 0) {
- __u8 difference;
- /* Some commands do require a certain status:
- */
- if (status == -1) { /* not yet set */
- ftape_report_raw_drive_status(&status);
- }
- difference = ((status ^ qic117_cmds[command].state) &
- qic117_cmds[command].mask);
- /* Wait until the drive gets
- * ready. This may last forever if
- * the drive never gets ready...
- */
- while ((difference & QIC_STATUS_READY) != 0) {
- TRACE(ft_t_noise, "command %d issued while not ready",
- command);
- TRACE(ft_t_noise, "waiting until drive gets ready");
- if (ftape_ready_wait(ftape_timeout.seek,
- &status) == -EINTR) {
- /* Bail out on signal !
- */
- TRACE_ABORT(-EINTR, ft_t_warn,
- "interrupted by non-blockable signal");
- }
- difference = ((status ^ qic117_cmds[command].state) &
- qic117_cmds[command].mask);
- }
- while ((difference & QIC_STATUS_ERROR) != 0) {
- int err;
- qic117_cmd_t cmd;
-
- TRACE(ft_t_noise,
- "command %d issued while error pending",
- command);
- TRACE(ft_t_noise, "clearing error status");
- ftape_report_error(&err, &cmd, 1);
- ftape_report_raw_drive_status(&status);
- difference = ((status ^ qic117_cmds[command].state) &
- qic117_cmds[command].mask);
- if ((difference & QIC_STATUS_ERROR) != 0) {
- /* Bail out on fatal signal !
- */
- FT_SIGNAL_EXIT(_NEVER_BLOCK);
- }
- }
- if (difference) {
- /* Any remaining difference can't be solved
- * here.
- */
- if (difference & (QIC_STATUS_CARTRIDGE_PRESENT |
- QIC_STATUS_NEW_CARTRIDGE |
- QIC_STATUS_REFERENCED)) {
- TRACE(ft_t_warn,
- "Fatal: tape removed or reinserted !");
- ft_failure = 1;
- } else {
- TRACE(ft_t_err, "wrong state: 0x%02x should be: 0x%02x",
- status & qic117_cmds[command].mask,
- qic117_cmds[command].state);
- }
- TRACE_EXIT -EIO;
- }
- if (~status & QIC_STATUS_READY & qic117_cmds[command].mask) {
- TRACE_ABORT(-EBUSY, ft_t_err, "Bad: still busy!");
- }
- }
- TRACE_EXIT 0;
-}
-
-/* Issue a tape command:
- */
-int ftape_command(qic117_cmd_t command)
-{
- int result = 0;
- static int level;
- TRACE_FUN(ft_t_any);
-
- if ((unsigned int)command > NR_ITEMS(qic117_cmds)) {
- /* This is a bug we'll want to know about too.
- */
- TRACE_ABORT(-EIO, ft_t_bug, "bug - bad command: %d", command);
- }
- if (++level > 5) { /* This is a bug we'll want to know about. */
- --level;
- TRACE_ABORT(-EIO, ft_t_bug, "bug - recursion for command: %d",
- command);
- }
- /* disable logging and restriction check for some commands,
- * check all other commands that have a prescribed starting
- * status.
- */
- if (diagnostic_mode) {
- TRACE(ft_t_flow, "diagnostic command %d", command);
- } else if (command == QIC_REPORT_DRIVE_STATUS ||
- command == QIC_REPORT_NEXT_BIT) {
- TRACE(ft_t_any, "%s", qic117_cmds[command].name);
- } else {
- TRACE_CATCH(ft_check_cmd_restrictions(command), --level);
- }
- /* Now all conditions are met or result was < 0.
- */
- result = ft_send_to_drive((unsigned int)command);
- if (qic117_cmds[command].cmd_type == motion &&
- command != QIC_LOGICAL_FORWARD && command != QIC_STOP_TAPE) {
- ft_location.known = 0;
- }
- ftape_current_command = command;
- --level;
- TRACE_EXIT result;
-}
-
-/* Send a tape command parameter:
- * Generates command # of step pulses.
- * Skips tape-status call !
- */
-int ftape_parameter(unsigned int parameter)
-{
- TRACE_FUN(ft_t_any);
-
- TRACE(ft_t_flow, "called with parameter = %d", parameter);
- TRACE_EXIT ft_send_to_drive(parameter + 2);
-}
-
-/* Wait for the drive to get ready.
- * timeout time in milli-seconds
- * Returned status is valid if result != -EIO
- *
- * Should we allow to be killed by SIGINT? (^C)
- * Would be nice at least for large timeouts.
- */
-int ftape_ready_wait(unsigned int timeout, int *status)
-{
- unsigned long t0;
- unsigned int poll_delay;
- int signal_retries;
- TRACE_FUN(ft_t_any);
-
- /* the following ** REALLY ** reduces the system load when
- * e.g. one simply rewinds or retensions. The tape is slow
- * anyway. It is really not necessary to detect error
- * conditions with 1/10 seconds granularity
- *
- * On my AMD 133MHZ 486: 100 ms: 23% system load
- * 1 sec: 5%
- * 5 sec: 0.6%, yeah
- */
- if (timeout <= FT_SECOND) {
- poll_delay = 100 * FT_MILLISECOND;
- signal_retries = 20; /* two seconds */
- } else if (timeout < 20 * FT_SECOND) {
- TRACE(ft_t_flow, "setting poll delay to 1 second");
- poll_delay = FT_SECOND;
- signal_retries = 2; /* two seconds */
- } else {
- TRACE(ft_t_flow, "setting poll delay to 5 seconds");
- poll_delay = 5 * FT_SECOND;
- signal_retries = 1; /* five seconds */
- }
- for (;;) {
- t0 = jiffies;
- TRACE_CATCH(ftape_report_raw_drive_status(status),);
- if (*status & QIC_STATUS_READY) {
- TRACE_EXIT 0;
- }
- if (!signal_retries--) {
- FT_SIGNAL_EXIT(_NEVER_BLOCK);
- }
- if ((int)timeout >= 0) {
- /* this will fail when jiffies wraps around about
- * once every year :-)
- */
- timeout -= ((jiffies - t0) * FT_SECOND) / HZ;
- if (timeout <= 0) {
- TRACE_ABORT(-ETIME, ft_t_err, "timeout");
- }
- ftape_sleep(poll_delay);
- timeout -= poll_delay;
- } else {
- ftape_sleep(poll_delay);
- }
- }
- TRACE_EXIT -ETIME;
-}
-
-/* Issue command and wait up to timeout milli seconds for drive ready
- */
-int ftape_command_wait(qic117_cmd_t command, unsigned int timeout, int *status)
-{
- int result;
-
- /* Drive should be ready, issue command
- */
- result = ftape_command(command);
- if (result >= 0) {
- result = ftape_ready_wait(timeout, status);
- }
- return result;
-}
-
-static int ftape_parameter_wait(unsigned int parm, unsigned int timeout, int *status)
-{
- int result;
-
- /* Drive should be ready, issue command
- */
- result = ftape_parameter(parm);
- if (result >= 0) {
- result = ftape_ready_wait(timeout, status);
- }
- return result;
-}
-
-/*--------------------------------------------------------------------------
- * Report operations
- */
-
-/* Query the drive about its status. The command is sent and
- result_length bits of status are returned (2 extra bits are read
- for start and stop). */
-
-int ftape_report_operation(int *status,
- qic117_cmd_t command,
- int result_length)
-{
- int i, st3;
- unsigned int t0;
- unsigned int dt;
- TRACE_FUN(ft_t_any);
-
- TRACE_CATCH(ftape_command(command),);
- t0 = ftape_timestamp();
- i = 0;
- do {
- ++i;
- ftape_sleep(3 * FT_MILLISECOND); /* see remark below */
- TRACE_CATCH(fdc_sense_drive_status(&st3),);
- dt = ftape_timediff(t0, ftape_timestamp());
- /* Ack should be asserted within Ttimout + Tack = 6 msec.
- * Looks like some drives fail to do this so extend this
- * period to 300 msec.
- */
- } while (!(st3 & ST3_TRACK_0) && dt < 300000);
- if (!(st3 & ST3_TRACK_0)) {
- TRACE(ft_t_err,
- "No acknowledge after %u msec. (%i iter)", dt / 1000, i);
- TRACE_ABORT(-EIO, ft_t_err, "timeout on Acknowledge");
- }
- /* dt may be larger than expected because of other tasks
- * scheduled while we were sleeping.
- */
- if (i > 1 && dt > 6000) {
- TRACE(ft_t_err, "Acknowledge after %u msec. (%i iter)",
- dt / 1000, i);
- }
- *status = 0;
- for (i = 0; i < result_length + 1; i++) {
- TRACE_CATCH(ftape_command(QIC_REPORT_NEXT_BIT),);
- TRACE_CATCH(fdc_sense_drive_status(&st3),);
- if (i < result_length) {
- *status |= ((st3 & ST3_TRACK_0) ? 1 : 0) << i;
- } else if ((st3 & ST3_TRACK_0) == 0) {
- TRACE_ABORT(-EIO, ft_t_err, "missing status stop bit");
- }
- }
- /* this command will put track zero and index back into normal state */
- (void)ftape_command(QIC_REPORT_NEXT_BIT);
- TRACE_EXIT 0;
-}
-
-/* Report the current drive status. */
-
-int ftape_report_raw_drive_status(int *status)
-{
- int result;
- int count = 0;
- TRACE_FUN(ft_t_any);
-
- do {
- result = ftape_report_operation(status,
- QIC_REPORT_DRIVE_STATUS, 8);
- } while (result < 0 && ++count <= 3);
- if (result < 0) {
- TRACE_ABORT(-EIO, ft_t_err,
- "report_operation failed after %d trials", count);
- }
- if ((*status & 0xff) == 0xff) {
- TRACE_ABORT(-EIO, ft_t_err,
- "impossible drive status 0xff");
- }
- if (*status & QIC_STATUS_READY) {
- ftape_current_command = QIC_NO_COMMAND; /* completed */
- }
- ft_last_status.status.drive_status = (__u8)(*status & 0xff);
- TRACE_EXIT 0;
-}
-
-int ftape_report_drive_status(int *status)
-{
- TRACE_FUN(ft_t_any);
-
- TRACE_CATCH(ftape_report_raw_drive_status(status),);
- if (*status & QIC_STATUS_NEW_CARTRIDGE ||
- !(*status & QIC_STATUS_CARTRIDGE_PRESENT)) {
- ft_failure = 1; /* will inhibit further operations */
- TRACE_EXIT -EIO;
- }
- if (*status & QIC_STATUS_READY && *status & QIC_STATUS_ERROR) {
- /* Let caller handle all errors */
- TRACE_ABORT(1, ft_t_warn, "warning: error status set!");
- }
- TRACE_EXIT 0;
-}
-
-int ftape_report_error(unsigned int *error,
- qic117_cmd_t *command, int report)
-{
- static const ftape_error ftape_errors[] = QIC117_ERRORS;
- int code;
- TRACE_FUN(ft_t_any);
-
- TRACE_CATCH(ftape_report_operation(&code, QIC_REPORT_ERROR_CODE, 16),);
- *error = (unsigned int)(code & 0xff);
- *command = (qic117_cmd_t)((code>>8)&0xff);
- /* remember hardware status, maybe useful for status ioctls
- */
- ft_last_error.error.command = (__u8)*command;
- ft_last_error.error.error = (__u8)*error;
- if (!report) {
- TRACE_EXIT 0;
- }
- if (*error == 0) {
- TRACE_ABORT(0, ft_t_info, "No error");
- }
- TRACE(ft_t_info, "errorcode: %d", *error);
- if (*error < NR_ITEMS(ftape_errors)) {
- TRACE(ft_t_noise, "%sFatal ERROR:",
- (ftape_errors[*error].fatal ? "" : "Non-"));
- TRACE(ft_t_noise, "%s ...", ftape_errors[*error].message);
- } else {
- TRACE(ft_t_noise, "Unknown ERROR !");
- }
- if ((unsigned int)*command < NR_ITEMS(qic117_cmds) &&
- qic117_cmds[*command].name != NULL) {
- TRACE(ft_t_noise, "... caused by command \'%s\'",
- qic117_cmds[*command].name);
- } else {
- TRACE(ft_t_noise, "... caused by unknown command %d",
- *command);
- }
- TRACE_EXIT 0;
-}
-
-int ftape_report_configuration(qic_model *model,
- unsigned int *rate,
- int *qic_std,
- int *tape_len)
-{
- int result;
- int config;
- int status;
- static const unsigned int qic_rates[ 4] = { 250, 2000, 500, 1000 };
- TRACE_FUN(ft_t_any);
-
- result = ftape_report_operation(&config,
- QIC_REPORT_DRIVE_CONFIGURATION, 8);
- if (result < 0) {
- ft_last_status.status.drive_config = (__u8)0x00;
- *model = prehistoric;
- *rate = 500;
- *qic_std = QIC_TAPE_QIC40;
- *tape_len = 205;
- TRACE_EXIT 0;
- } else {
- ft_last_status.status.drive_config = (__u8)(config & 0xff);
- }
- *rate = qic_rates[(config & QIC_CONFIG_RATE_MASK) >> QIC_CONFIG_RATE_SHIFT];
- result = ftape_report_operation(&status, QIC_REPORT_TAPE_STATUS, 8);
- if (result < 0) {
- ft_last_status.status.tape_status = (__u8)0x00;
- /* pre- QIC117 rev C spec. drive, QIC_CONFIG_80 bit is valid.
- */
- *qic_std = (config & QIC_CONFIG_80) ?
- QIC_TAPE_QIC80 : QIC_TAPE_QIC40;
- /* ?? how's about 425ft tapes? */
- *tape_len = (config & QIC_CONFIG_LONG) ? 307 : 0;
- *model = pre_qic117c;
- result = 0;
- } else {
- ft_last_status.status.tape_status = (__u8)(status & 0xff);
- *model = post_qic117b;
- TRACE(ft_t_any, "report tape status result = %02x", status);
- /* post- QIC117 rev C spec. drive, QIC_CONFIG_80 bit is
- * invalid.
- */
- switch (status & QIC_TAPE_STD_MASK) {
- case QIC_TAPE_QIC40:
- case QIC_TAPE_QIC80:
- case QIC_TAPE_QIC3020:
- case QIC_TAPE_QIC3010:
- *qic_std = status & QIC_TAPE_STD_MASK;
- break;
- default:
- *qic_std = -1;
- break;
- }
- switch (status & QIC_TAPE_LEN_MASK) {
- case QIC_TAPE_205FT:
- /* 205 or 425+ ft 550 Oe tape */
- *tape_len = 0;
- break;
- case QIC_TAPE_307FT:
- /* 307.5 ft 550 Oe Extended Length (XL) tape */
- *tape_len = 307;
- break;
- case QIC_TAPE_VARIABLE:
- /* Variable length 550 Oe tape */
- *tape_len = 0;
- break;
- case QIC_TAPE_1100FT:
- /* 1100 ft 550 Oe tape */
- *tape_len = 1100;
- break;
- case QIC_TAPE_FLEX:
- /* Variable length 900 Oe tape */
- *tape_len = 0;
- break;
- default:
- *tape_len = -1;
- break;
- }
- if (*qic_std == -1 || *tape_len == -1) {
- TRACE(ft_t_any,
- "post qic-117b spec drive with unknown tape");
- }
- result = *tape_len == -1 ? -EIO : 0;
- if (status & QIC_TAPE_WIDE) {
- switch (*qic_std) {
- case QIC_TAPE_QIC80:
- TRACE(ft_t_info, "TR-1 tape detected");
- break;
- case QIC_TAPE_QIC3010:
- TRACE(ft_t_info, "TR-2 tape detected");
- break;
- case QIC_TAPE_QIC3020:
- TRACE(ft_t_info, "TR-3 tape detected");
- break;
- default:
- TRACE(ft_t_warn,
- "Unknown Travan tape type detected");
- break;
- }
- }
- }
- TRACE_EXIT (result < 0) ? -EIO : 0;
-}
-
-static int ftape_report_rom_version(int *version)
-{
-
- if (ftape_report_operation(version, QIC_REPORT_ROM_VERSION, 8) < 0) {
- return -EIO;
- } else {
- return 0;
- }
-}
-
-void ftape_report_vendor_id(unsigned int *id)
-{
- int result;
- TRACE_FUN(ft_t_any);
-
- /* We'll try to get a vendor id from the drive. First
- * according to the QIC-117 spec, a 16-bit id is requested.
- * If that fails we'll try an 8-bit version, otherwise we'll
- * try an undocumented query.
- */
- result = ftape_report_operation((int *) id, QIC_REPORT_VENDOR_ID, 16);
- if (result < 0) {
- result = ftape_report_operation((int *) id,
- QIC_REPORT_VENDOR_ID, 8);
- if (result < 0) {
- /* The following is an undocumented call found
- * in the CMS code.
- */
- result = ftape_report_operation((int *) id, 24, 8);
- if (result < 0) {
- *id = UNKNOWN_VENDOR;
- } else {
- TRACE(ft_t_noise, "got old 8 bit id: %04x",
- *id);
- *id |= 0x20000;
- }
- } else {
- TRACE(ft_t_noise, "got 8 bit id: %04x", *id);
- *id |= 0x10000;
- }
- } else {
- TRACE(ft_t_noise, "got 16 bit id: %04x", *id);
- }
- if (*id == 0x0047) {
- int version;
- int sign;
-
- if (ftape_report_rom_version(&version) < 0) {
- TRACE(ft_t_bug, "report rom version failed");
- TRACE_EXIT;
- }
- TRACE(ft_t_noise, "CMS rom version: %d", version);
- ftape_command(QIC_ENTER_DIAGNOSTIC_1);
- ftape_command(QIC_ENTER_DIAGNOSTIC_1);
- diagnostic_mode = 1;
- if (ftape_report_operation(&sign, 9, 8) < 0) {
- unsigned int error;
- qic117_cmd_t command;
-
- ftape_report_error(&error, &command, 1);
- ftape_command(QIC_ENTER_PRIMARY_MODE);
- diagnostic_mode = 0;
- TRACE_EXIT; /* failure ! */
- } else {
- TRACE(ft_t_noise, "CMS signature: %02x", sign);
- }
- if (sign == 0xa5) {
- result = ftape_report_operation(&sign, 37, 8);
- if (result < 0) {
- if (version >= 63) {
- *id = 0x8880;
- TRACE(ft_t_noise,
- "This is an Iomega drive !");
- } else {
- *id = 0x0047;
- TRACE(ft_t_noise,
- "This is a real CMS drive !");
- }
- } else {
- *id = 0x0047;
- TRACE(ft_t_noise, "CMS status: %d", sign);
- }
- } else {
- *id = UNKNOWN_VENDOR;
- }
- ftape_command(QIC_ENTER_PRIMARY_MODE);
- diagnostic_mode = 0;
- }
- TRACE_EXIT;
-}
-
-static int qic_rate_code(unsigned int rate)
-{
- switch (rate) {
- case 250:
- return QIC_CONFIG_RATE_250;
- case 500:
- return QIC_CONFIG_RATE_500;
- case 1000:
- return QIC_CONFIG_RATE_1000;
- case 2000:
- return QIC_CONFIG_RATE_2000;
- default:
- return QIC_CONFIG_RATE_500;
- }
-}
-
-static int ftape_set_rate_test(unsigned int *max_rate)
-{
- unsigned int error;
- qic117_cmd_t command;
- int status;
- int supported = 0;
- TRACE_FUN(ft_t_any);
-
- /* Check if the drive does support the select rate command
- * by testing all different settings. If any one is accepted
- * we assume the command is supported, else not.
- */
- for (*max_rate = 2000; *max_rate >= 250; *max_rate /= 2) {
- if (ftape_command(QIC_SELECT_RATE) < 0) {
- continue;
- }
- if (ftape_parameter_wait(qic_rate_code(*max_rate),
- 1 * FT_SECOND, &status) < 0) {
- continue;
- }
- if (status & QIC_STATUS_ERROR) {
- ftape_report_error(&error, &command, 0);
- continue;
- }
- supported = 1; /* did accept a request */
- break;
- }
- TRACE(ft_t_noise, "Select Rate command is%s supported",
- supported ? "" : " not");
- TRACE_EXIT supported;
-}
-
-int ftape_set_data_rate(unsigned int new_rate /* Kbps */, unsigned int qic_std)
-{
- int status;
- int result = 0;
- unsigned int data_rate = new_rate;
- static int supported;
- int rate_changed = 0;
- qic_model dummy_model;
- unsigned int dummy_qic_std, dummy_tape_len;
- TRACE_FUN(ft_t_any);
-
- if (ft_drive_max_rate == 0) { /* first time */
- supported = ftape_set_rate_test(&ft_drive_max_rate);
- }
- if (supported) {
- ftape_command(QIC_SELECT_RATE);
- result = ftape_parameter_wait(qic_rate_code(new_rate),
- 1 * FT_SECOND, &status);
- if (result >= 0 && !(status & QIC_STATUS_ERROR)) {
- rate_changed = 1;
- }
- }
- TRACE_CATCH(result = ftape_report_configuration(&dummy_model,
- &data_rate,
- &dummy_qic_std,
- &dummy_tape_len),);
- if (data_rate != new_rate) {
- if (!supported) {
- TRACE(ft_t_warn, "Rate change not supported!");
- } else if (rate_changed) {
- TRACE(ft_t_warn, "Requested: %d, got %d",
- new_rate, data_rate);
- } else {
- TRACE(ft_t_warn, "Rate change failed!");
- }
- result = -EINVAL;
- }
- /*
- * Set data rate and write precompensation as specified:
- *
- * | QIC-40/80 | QIC-3010/3020
- * rate | precomp | precomp
- * ----------+-------------+--------------
- * 250 Kbps. | 250 ns. | 0 ns.
- * 500 Kbps. | 125 ns. | 0 ns.
- * 1 Mbps. | 42 ns. | 0 ns.
- * 2 Mbps | N/A | 0 ns.
- */
- if ((qic_std == QIC_TAPE_QIC40 && data_rate > 500) ||
- (qic_std == QIC_TAPE_QIC80 && data_rate > 1000)) {
- TRACE_ABORT(-EINVAL,
- ft_t_warn, "Datarate too high for QIC-mode");
- }
- TRACE_CATCH(fdc_set_data_rate(data_rate),_res = -EINVAL);
- ft_data_rate = data_rate;
- if (qic_std == QIC_TAPE_QIC40 || qic_std == QIC_TAPE_QIC80) {
- switch (data_rate) {
- case 250:
- fdc_set_write_precomp(250);
- break;
- default:
- case 500:
- fdc_set_write_precomp(125);
- break;
- case 1000:
- fdc_set_write_precomp(42);
- break;
- }
- } else {
- fdc_set_write_precomp(0);
- }
- TRACE_EXIT result;
-}
-
-/* The next two functions are used to cope with excessive overrun errors
- */
-int ftape_increase_threshold(void)
-{
- TRACE_FUN(ft_t_flow);
-
- if (fdc.type < i82077 || ft_fdc_threshold >= 12) {
- TRACE_ABORT(-EIO, ft_t_err, "cannot increase fifo threshold");
- }
- if (fdc_fifo_threshold(++ft_fdc_threshold, NULL, NULL, NULL) < 0) {
- TRACE(ft_t_err, "cannot increase fifo threshold");
- ft_fdc_threshold --;
- fdc_reset();
- }
- TRACE(ft_t_info, "New FIFO threshold: %d", ft_fdc_threshold);
- TRACE_EXIT 0;
-}
-
-int ftape_half_data_rate(void)
-{
- if (ft_data_rate < 500) {
- return -1;
- }
- if (ftape_set_data_rate(ft_data_rate / 2, ft_qic_std) < 0) {
- return -EIO;
- }
- ftape_calc_timeouts(ft_qic_std, ft_data_rate, ftape_tape_len);
- return 0;
-}
-
-/* Seek the head to the specified track.
- */
-int ftape_seek_head_to_track(unsigned int track)
-{
- int status;
- TRACE_FUN(ft_t_any);
-
- ft_location.track = -1; /* remains set in case of error */
- if (track >= ft_tracks_per_tape) {
- TRACE_ABORT(-EINVAL, ft_t_bug, "track out of bounds");
- }
- TRACE(ft_t_flow, "seeking track %d", track);
- TRACE_CATCH(ftape_command(QIC_SEEK_HEAD_TO_TRACK),);
- TRACE_CATCH(ftape_parameter_wait(track, ftape_timeout.head_seek,
- &status),);
- ft_location.track = track;
- ftape_might_be_off_track = 0;
- TRACE_EXIT 0;
-}
-
-int ftape_wakeup_drive(wake_up_types method)
-{
- int status;
- int motor_on = 0;
- TRACE_FUN(ft_t_any);
-
- switch (method) {
- case wake_up_colorado:
- TRACE_CATCH(ftape_command(QIC_PHANTOM_SELECT),);
- TRACE_CATCH(ftape_parameter(0 /* ft_drive_sel ?? */),);
- break;
- case wake_up_mountain:
- TRACE_CATCH(ftape_command(QIC_SOFT_SELECT),);
- ftape_sleep(FT_MILLISECOND); /* NEEDED */
- TRACE_CATCH(ftape_parameter(18),);
- break;
- case wake_up_insight:
- ftape_sleep(100 * FT_MILLISECOND);
- motor_on = 1;
- fdc_motor(motor_on); /* enable is done by motor-on */
- case no_wake_up:
- break;
- default:
- TRACE_EXIT -ENODEV; /* unknown wakeup method */
- break;
- }
- /* If wakeup succeeded we shouldn't get an error here..
- */
- TRACE_CATCH(ftape_report_raw_drive_status(&status),
- if (motor_on) {
- fdc_motor(0);
- });
- TRACE_EXIT 0;
-}
-
-int ftape_put_drive_to_sleep(wake_up_types method)
-{
- TRACE_FUN(ft_t_any);
-
- switch (method) {
- case wake_up_colorado:
- TRACE_CATCH(ftape_command(QIC_PHANTOM_DESELECT),);
- break;
- case wake_up_mountain:
- TRACE_CATCH(ftape_command(QIC_SOFT_DESELECT),);
- break;
- case wake_up_insight:
- fdc_motor(0); /* enable is done by motor-on */
- case no_wake_up: /* no wakeup / no sleep ! */
- break;
- default:
- TRACE_EXIT -ENODEV; /* unknown wakeup method */
- }
- TRACE_EXIT 0;
-}
-
-int ftape_reset_drive(void)
-{
- int result = 0;
- int status;
- unsigned int err_code;
- qic117_cmd_t err_command;
- int i;
- TRACE_FUN(ft_t_any);
-
- /* We want to re-establish contact with our drive. Fire a
- * number of reset commands (single step pulses) and pray for
- * success.
- */
- for (i = 0; i < 2; ++i) {
- TRACE(ft_t_flow, "Resetting fdc");
- fdc_reset();
- ftape_sleep(10 * FT_MILLISECOND);
- TRACE(ft_t_flow, "Reset command to drive");
- result = ftape_command(QIC_RESET);
- if (result == 0) {
- ftape_sleep(1 * FT_SECOND); /* drive not
- * accessible
- * during 1 second
- */
- TRACE(ft_t_flow, "Re-selecting drive");
-
- /* Strange, the QIC-117 specs don't mention
- * this but the drive gets deselected after a
- * soft reset ! So we need to enable it
- * again.
- */
- if (ftape_wakeup_drive(ft_drive_type.wake_up) < 0) {
- TRACE(ft_t_err, "Wakeup failed !");
- }
- TRACE(ft_t_flow, "Waiting until drive gets ready");
- result= ftape_ready_wait(ftape_timeout.reset, &status);
- if (result == 0 && (status & QIC_STATUS_ERROR)) {
- result = ftape_report_error(&err_code,
- &err_command, 1);
- if (result == 0 && err_code == 27) {
- /* Okay, drive saw reset
- * command and responded as it
- * should
- */
- break;
- } else {
- result = -EIO;
- }
- } else {
- result = -EIO;
- }
- }
- FT_SIGNAL_EXIT(_DONT_BLOCK);
- }
- if (result != 0) {
- TRACE(ft_t_err, "General failure to reset tape drive");
- } else {
- /* Restore correct settings: keep original rate
- */
- ftape_set_data_rate(ft_data_rate, ft_qic_std);
- }
- ftape_init_drive_needed = 1;
- TRACE_EXIT result;
-}
diff --git a/drivers/char/ftape/lowlevel/ftape-io.h b/drivers/char/ftape/lowlevel/ftape-io.h
deleted file mode 100644
index 26a7baad8717..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-io.h
+++ /dev/null
@@ -1,90 +0,0 @@
-#ifndef _FTAPE_IO_H
-#define _FTAPE_IO_H
-
-/*
- * Copyright (C) 1993-1996 Bas Laarhoven,
- * (C) 1997 Claus-Justus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-io.h,v $
- * $Revision: 1.2 $
- * $Date: 1997/10/05 19:18:18 $
- *
- * This file contains definitions for the glue part of the
- * QIC-40/80/3010/3020 floppy-tape driver "ftape" for Linux.
- */
-
-#include <linux/qic117.h>
-#include <linux/ftape-vendors.h>
-
-typedef struct {
- unsigned int seek;
- unsigned int reset;
- unsigned int rewind;
- unsigned int head_seek;
- unsigned int stop;
- unsigned int pause;
-} ft_timeout_table;
-
-typedef enum {
- prehistoric, pre_qic117c, post_qic117b, post_qic117d
-} qic_model;
-
-/*
- * ftape-io.c defined global vars.
- */
-extern ft_timeout_table ftape_timeout;
-extern unsigned int ftape_tape_len;
-extern volatile qic117_cmd_t ftape_current_command;
-extern const struct qic117_command_table qic117_cmds[];
-extern int ftape_might_be_off_track;
-
-/*
- * ftape-io.c defined global functions.
- */
-extern void ftape_udelay(unsigned int usecs);
-extern void ftape_udelay_calibrate(void);
-extern void ftape_sleep(unsigned int time);
-extern void ftape_report_vendor_id(unsigned int *id);
-extern int ftape_command(qic117_cmd_t command);
-extern int ftape_command_wait(qic117_cmd_t command,
- unsigned int timeout,
- int *status);
-extern int ftape_parameter(unsigned int parameter);
-extern int ftape_report_operation(int *status,
- qic117_cmd_t command,
- int result_length);
-extern int ftape_report_configuration(qic_model *model,
- unsigned int *rate,
- int *qic_std,
- int *tape_len);
-extern int ftape_report_drive_status(int *status);
-extern int ftape_report_raw_drive_status(int *status);
-extern int ftape_report_status(int *status);
-extern int ftape_ready_wait(unsigned int timeout, int *status);
-extern int ftape_seek_head_to_track(unsigned int track);
-extern int ftape_set_data_rate(unsigned int new_rate, unsigned int qic_std);
-extern int ftape_report_error(unsigned int *error,
- qic117_cmd_t *command,
- int report);
-extern int ftape_reset_drive(void);
-extern int ftape_put_drive_to_sleep(wake_up_types method);
-extern int ftape_wakeup_drive(wake_up_types method);
-extern int ftape_increase_threshold(void);
-extern int ftape_half_data_rate(void);
-
-#endif
diff --git a/drivers/char/ftape/lowlevel/ftape-proc.c b/drivers/char/ftape/lowlevel/ftape-proc.c
deleted file mode 100644
index e805b15e0a12..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-proc.c
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Copyright (C) 1997 Claus-Justus Heine
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-proc.c,v $
- * $Revision: 1.11 $
- * $Date: 1997/10/24 14:47:37 $
- *
- * This file contains the procfs interface for the
- * QIC-40/80/3010/3020 floppy-tape driver "ftape" for Linux.
-
- * Old code removed, switched to dynamic proc entry.
- */
-
-
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_FT_PROC_FS)
-
-#include <linux/proc_fs.h>
-
-#include <linux/ftape.h>
-#include <linux/init.h>
-#include <linux/qic117.h>
-
-#include "../lowlevel/ftape-io.h"
-#include "../lowlevel/ftape-ctl.h"
-#include "../lowlevel/ftape-proc.h"
-#include "../lowlevel/ftape-tracing.h"
-
-static size_t get_driver_info(char *buf)
-{
- const char *debug_level[] = { "bugs" ,
- "errors",
- "warnings",
- "informational",
- "noisy",
- "program flow",
- "fdc and dma",
- "data flow",
- "anything" };
-
- return sprintf(buf,
- "version : %s\n"
- "used data rate: %d kbit/sec\n"
- "dma memory : %d kb\n"
- "debug messages: %s\n",
- FTAPE_VERSION,
- ft_data_rate,
- FT_BUFF_SIZE * ft_nr_buffers >> 10,
- debug_level[TRACE_LEVEL]);
-}
-
-static size_t get_tapedrive_info(char *buf)
-{
- return sprintf(buf,
- "vendor id : 0x%04x\n"
- "drive name: %s\n"
- "wind speed: %d ips\n"
- "wakeup : %s\n"
- "max. rate : %d kbit/sec\n",
- ft_drive_type.vendor_id,
- ft_drive_type.name,
- ft_drive_type.speed,
- ((ft_drive_type.wake_up == no_wake_up)
- ? "No wakeup needed" :
- ((ft_drive_type.wake_up == wake_up_colorado)
- ? "Colorado" :
- ((ft_drive_type.wake_up == wake_up_mountain)
- ? "Mountain" :
- ((ft_drive_type.wake_up == wake_up_insight)
- ? "Motor on" :
- "Unknown")))),
- ft_drive_max_rate);
-}
-
-static size_t get_cartridge_info(char *buf)
-{
- if (ftape_init_drive_needed) {
- return sprintf(buf, "uninitialized\n");
- }
- if (ft_no_tape) {
- return sprintf(buf, "no cartridge inserted\n");
- }
- return sprintf(buf,
- "segments : %5d\n"
- "tracks : %5d\n"
- "length : %5dft\n"
- "formatted : %3s\n"
- "writable : %3s\n"
- "QIC spec. : QIC-%s\n"
- "fmt-code : %1d\n",
- ft_segments_per_track,
- ft_tracks_per_tape,
- ftape_tape_len,
- (ft_formatted == 1) ? "yes" : "no",
- (ft_write_protected == 1) ? "no" : "yes",
- ((ft_qic_std == QIC_TAPE_QIC40) ? "40" :
- ((ft_qic_std == QIC_TAPE_QIC80) ? "80" :
- ((ft_qic_std == QIC_TAPE_QIC3010) ? "3010" :
- ((ft_qic_std == QIC_TAPE_QIC3020) ? "3020" :
- "???")))),
- ft_format_code);
-}
-
-static size_t get_controller_info(char *buf)
-{
- const char *fdc_name[] = { "no fdc",
- "i8272",
- "i82077",
- "i82077AA",
- "Colorado FC-10 or FC-20",
- "i82078",
- "i82078_1" };
-
- return sprintf(buf,
- "FDC type : %s\n"
- "FDC base : 0x%03x\n"
- "FDC irq : %d\n"
- "FDC dma : %d\n"
- "FDC thr. : %d\n"
- "max. rate : %d kbit/sec\n",
- ft_mach2 ? "Mountain MACH-2" : fdc_name[fdc.type],
- fdc.sra, fdc.irq, fdc.dma,
- ft_fdc_threshold, ft_fdc_max_rate);
-}
-
-static size_t get_history_info(char *buf)
-{
- size_t len;
-
- len = sprintf(buf,
- "\nFDC isr statistics\n"
- " id_am_errors : %3d\n"
- " id_crc_errors : %3d\n"
- " data_am_errors : %3d\n"
- " data_crc_errors : %3d\n"
- " overrun_errors : %3d\n"
- " no_data_errors : %3d\n"
- " retries : %3d\n",
- ft_history.id_am_errors, ft_history.id_crc_errors,
- ft_history.data_am_errors, ft_history.data_crc_errors,
- ft_history.overrun_errors, ft_history.no_data_errors,
- ft_history.retries);
- len += sprintf(buf + len,
- "\nECC statistics\n"
- " crc_errors : %3d\n"
- " crc_failures : %3d\n"
- " ecc_failures : %3d\n"
- " sectors corrected: %3d\n",
- ft_history.crc_errors, ft_history.crc_failures,
- ft_history.ecc_failures, ft_history.corrected);
- len += sprintf(buf + len,
- "\ntape quality statistics\n"
- " media defects : %3d\n",
- ft_history.defects);
- len += sprintf(buf + len,
- "\ntape motion statistics\n"
- " repositions : %3d\n",
- ft_history.rewinds);
- return len;
-}
-
-static int ftape_read_proc(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- char *ptr = page;
- size_t len;
-
- ptr += sprintf(ptr, "Kernel Driver\n\n");
- ptr += get_driver_info(ptr);
- ptr += sprintf(ptr, "\nTape Drive\n\n");
- ptr += get_tapedrive_info(ptr);
- ptr += sprintf(ptr, "\nFDC Controller\n\n");
- ptr += get_controller_info(ptr);
- ptr += sprintf(ptr, "\nTape Cartridge\n\n");
- ptr += get_cartridge_info(ptr);
- ptr += sprintf(ptr, "\nHistory Record\n\n");
- ptr += get_history_info(ptr);
-
- len = strlen(page);
- *start = NULL;
- if (off+count >= len) {
- *eof = 1;
- } else {
- *eof = 0;
- }
- return len;
-}
-
-int __init ftape_proc_init(void)
-{
- return create_proc_read_entry("ftape", 0, &proc_root,
- ftape_read_proc, NULL) != NULL;
-}
-
-void ftape_proc_destroy(void)
-{
- remove_proc_entry("ftape", &proc_root);
-}
-
-#endif /* defined(CONFIG_PROC_FS) && defined(CONFIG_FT_PROC_FS) */
diff --git a/drivers/char/ftape/lowlevel/ftape-proc.h b/drivers/char/ftape/lowlevel/ftape-proc.h
deleted file mode 100644
index 264dfcc1d22d..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-proc.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef _FTAPE_PROC_H
-#define _FTAPE_PROC_H
-
-/*
- * Copyright (C) 1997 Claus-Justus Heine
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-proc.h,v $
- * $Revision: 1.2 $
- * $Date: 1997/10/05 19:18:20 $
- *
- * This file contains definitions for the procfs interface of the
- * QIC-40/80/3010/3020 floppy-tape driver "ftape" for Linux.
- */
-
-#include <linux/proc_fs.h>
-
-extern int ftape_proc_init(void);
-extern void ftape_proc_destroy(void);
-
-#endif
diff --git a/drivers/char/ftape/lowlevel/ftape-read.c b/drivers/char/ftape/lowlevel/ftape-read.c
deleted file mode 100644
index d967d8cd86dc..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-read.c
+++ /dev/null
@@ -1,621 +0,0 @@
-/*
- * Copyright (C) 1993-1996 Bas Laarhoven,
- * (C) 1996-1997 Claus-Justus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-read.c,v $
- * $Revision: 1.6 $
- * $Date: 1997/10/21 14:39:22 $
- *
- * This file contains the reading code
- * for the QIC-117 floppy-tape driver for Linux.
- *
- */
-
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/mm.h>
-
-#include <linux/ftape.h>
-#include <linux/qic117.h>
-#include "../lowlevel/ftape-tracing.h"
-#include "../lowlevel/ftape-read.h"
-#include "../lowlevel/ftape-io.h"
-#include "../lowlevel/ftape-ctl.h"
-#include "../lowlevel/ftape-rw.h"
-#include "../lowlevel/ftape-write.h"
-#include "../lowlevel/ftape-ecc.h"
-#include "../lowlevel/ftape-bsm.h"
-
-/* Global vars.
- */
-
-/* Local vars.
- */
-
-void ftape_zap_read_buffers(void)
-{
- int i;
-
- for (i = 0; i < ft_nr_buffers; ++i) {
-/* changed to "fit" with dynamic allocation of tape_buffer. --khp */
- ft_buffer[i]->status = waiting;
- ft_buffer[i]->bytes = 0;
- ft_buffer[i]->skip = 0;
- ft_buffer[i]->retry = 0;
- }
-/* ftape_reset_buffer(); */
-}
-
-static SectorMap convert_sector_map(buffer_struct * buff)
-{
- int i = 0;
- SectorMap bad_map = ftape_get_bad_sector_entry(buff->segment_id);
- SectorMap src_map = buff->soft_error_map | buff->hard_error_map;
- SectorMap dst_map = 0;
- TRACE_FUN(ft_t_any);
-
- if (bad_map || src_map) {
- TRACE(ft_t_flow, "bad_map = 0x%08lx", (long) bad_map);
- TRACE(ft_t_flow, "src_map = 0x%08lx", (long) src_map);
- }
- while (bad_map) {
- while ((bad_map & 1) == 0) {
- if (src_map & 1) {
- dst_map |= (1 << i);
- }
- src_map >>= 1;
- bad_map >>= 1;
- ++i;
- }
- /* (bad_map & 1) == 1 */
- src_map >>= 1;
- bad_map >>= 1;
- }
- if (src_map) {
- dst_map |= (src_map << i);
- }
- if (dst_map) {
- TRACE(ft_t_flow, "dst_map = 0x%08lx", (long) dst_map);
- }
- TRACE_EXIT dst_map;
-}
-
-static int correct_and_copy_fraction(buffer_struct *buff, __u8 * destination,
- int start, int size)
-{
- struct memory_segment mseg;
- int result;
- SectorMap read_bad;
- TRACE_FUN(ft_t_any);
-
- mseg.read_bad = convert_sector_map(buff);
- mseg.marked_bad = 0; /* not used... */
- mseg.blocks = buff->bytes / FT_SECTOR_SIZE;
- mseg.data = buff->address;
- /* If there are no data sectors we can skip this segment.
- */
- if (mseg.blocks <= 3) {
- TRACE_ABORT(0, ft_t_noise, "empty segment");
- }
- read_bad = mseg.read_bad;
- ft_history.crc_errors += count_ones(read_bad);
- result = ftape_ecc_correct_data(&mseg);
- if (read_bad != 0 || mseg.corrected != 0) {
- TRACE(ft_t_noise, "crc error map: 0x%08lx", (unsigned long)read_bad);
- TRACE(ft_t_noise, "corrected map: 0x%08lx", (unsigned long)mseg.corrected);
- ft_history.corrected += count_ones(mseg.corrected);
- }
- if (result == ECC_CORRECTED || result == ECC_OK) {
- if (result == ECC_CORRECTED) {
- TRACE(ft_t_info, "ecc corrected segment: %d", buff->segment_id);
- }
- if(start < 0) {
- start= 0;
- }
- if((start+size) > ((mseg.blocks - 3) * FT_SECTOR_SIZE)) {
- size = (mseg.blocks - 3) * FT_SECTOR_SIZE - start;
- }
- if (size < 0) {
- size= 0;
- }
- if(size > 0) {
- memcpy(destination + start, mseg.data + start, size);
- }
- if ((read_bad ^ mseg.corrected) & mseg.corrected) {
- /* sectors corrected without crc errors set */
- ft_history.crc_failures++;
- }
- TRACE_EXIT size; /* (mseg.blocks - 3) * FT_SECTOR_SIZE; */
- } else {
- ft_history.ecc_failures++;
- TRACE_ABORT(-EAGAIN,
- ft_t_err, "ecc failure on segment %d",
- buff->segment_id);
- }
- TRACE_EXIT 0;
-}
-
-/* Read given segment into buffer at address.
- */
-int ftape_read_segment_fraction(const int segment_id,
- void *address,
- const ft_read_mode_t read_mode,
- const int start,
- const int size)
-{
- int result = 0;
- int retry = 0;
- int bytes_read = 0;
- int read_done = 0;
- TRACE_FUN(ft_t_flow);
-
- ft_history.used |= 1;
- TRACE(ft_t_data_flow, "segment_id = %d", segment_id);
- if (ft_driver_state != reading) {
- TRACE(ft_t_noise, "calling ftape_abort_operation");
- TRACE_CATCH(ftape_abort_operation(),);
- ftape_set_state(reading);
- }
- for(;;) {
- buffer_struct *tail;
- /* Allow escape from this loop on signal !
- */
- FT_SIGNAL_EXIT(_DONT_BLOCK);
- /* Search all full buffers for the first matching the
- * wanted segment. Clear other buffers on the fly.
- */
- tail = ftape_get_buffer(ft_queue_tail);
- while (!read_done && tail->status == done) {
- /* Allow escape from this loop on signal !
- */
- FT_SIGNAL_EXIT(_DONT_BLOCK);
- if (tail->segment_id == segment_id) {
- /* If out buffer is already full,
- * return its contents.
- */
- TRACE(ft_t_flow, "found segment in cache: %d",
- segment_id);
- if (tail->deleted) {
- /* Return a value that
- * read_header_segment
- * understands. As this
- * should only occur when
- * searching for the header
- * segments it shouldn't be
- * misinterpreted elsewhere.
- */
- TRACE_EXIT 0;
- }
- result = correct_and_copy_fraction(
- tail,
- address,
- start,
- size);
- TRACE(ft_t_flow, "segment contains (bytes): %d",
- result);
- if (result < 0) {
- if (result != -EAGAIN) {
- TRACE_EXIT result;
- }
- /* keep read_done == 0, will
- * trigger
- * ftape_abort_operation
- * because reading wrong
- * segment.
- */
- TRACE(ft_t_err, "ecc failed, retry");
- ++retry;
- } else {
- read_done = 1;
- bytes_read = result;
- }
- } else {
- TRACE(ft_t_flow,"zapping segment in cache: %d",
- tail->segment_id);
- }
- tail->status = waiting;
- tail = ftape_next_buffer(ft_queue_tail);
- }
- if (!read_done && tail->status == reading) {
- if (tail->segment_id == segment_id) {
- switch(ftape_wait_segment(reading)) {
- case 0:
- break;
- case -EINTR:
- TRACE_ABORT(-EINTR, ft_t_warn,
- "interrupted by "
- "non-blockable signal");
- break;
- default:
- TRACE(ft_t_noise,
- "wait_segment failed");
- ftape_abort_operation();
- ftape_set_state(reading);
- break;
- }
- } else {
- /* We're reading the wrong segment,
- * stop runner.
- */
- TRACE(ft_t_noise, "reading wrong segment");
- ftape_abort_operation();
- ftape_set_state(reading);
- }
- }
- /* should runner stop ?
- */
- if (ft_runner_status == aborting) {
- buffer_struct *head = ftape_get_buffer(ft_queue_head);
- switch(head->status) {
- case error:
- ft_history.defects +=
- count_ones(head->hard_error_map);
- case reading:
- head->status = waiting;
- break;
- default:
- break;
- }
- TRACE_CATCH(ftape_dumb_stop(),);
- } else {
- /* If just passed last segment on tape: wait
- * for BOT or EOT mark. Sets ft_runner_status to
- * idle if at lEOT and successful
- */
- TRACE_CATCH(ftape_handle_logical_eot(),);
- }
- /* If we got a segment: quit, or else retry up to limit.
- *
- * If segment to read is empty, do not start runner for it,
- * but wait for next read call.
- */
- if (read_done ||
- ftape_get_bad_sector_entry(segment_id) == EMPTY_SEGMENT ) {
- /* bytes_read = 0; should still be zero */
- TRACE_EXIT bytes_read;
-
- }
- if (retry > FT_RETRIES_ON_ECC_ERROR) {
- ft_history.defects++;
- TRACE_ABORT(-ENODATA, ft_t_err,
- "too many retries on ecc failure");
- }
- /* Now at least one buffer is empty !
- * Restart runner & tape if needed.
- */
- TRACE(ft_t_any, "head: %d, tail: %d, ft_runner_status: %d",
- ftape_buffer_id(ft_queue_head),
- ftape_buffer_id(ft_queue_tail),
- ft_runner_status);
- TRACE(ft_t_any, "buffer[].status, [head]: %d, [tail]: %d",
- ftape_get_buffer(ft_queue_head)->status,
- ftape_get_buffer(ft_queue_tail)->status);
- tail = ftape_get_buffer(ft_queue_tail);
- if (tail->status == waiting) {
- buffer_struct *head = ftape_get_buffer(ft_queue_head);
-
- ftape_setup_new_segment(head, segment_id, -1);
- if (read_mode == FT_RD_SINGLE) {
- /* disable read-ahead */
- head->next_segment = 0;
- }
- ftape_calc_next_cluster(head);
- if (ft_runner_status == idle) {
- result = ftape_start_tape(segment_id,
- head->sector_offset);
- if (result < 0) {
- TRACE_ABORT(result, ft_t_err, "Error: "
- "segment %d unreachable",
- segment_id);
- }
- }
- head->status = reading;
- fdc_setup_read_write(head, FDC_READ);
- }
- }
- /* not reached */
- TRACE_EXIT -EIO;
-}
-
-int ftape_read_header_segment(__u8 *address)
-{
- int result;
- int header_segment;
- int first_failed = 0;
- int status;
- TRACE_FUN(ft_t_flow);
-
- ft_used_header_segment = -1;
- TRACE_CATCH(ftape_report_drive_status(&status),);
- TRACE(ft_t_flow, "reading...");
- /* We're looking for the first header segment.
- * A header segment cannot contain bad sectors, therefor at the
- * tape start, segments with bad sectors are (according to QIC-40/80)
- * written with deleted data marks and must be skipped.
- */
- memset(address, '\0', (FT_SECTORS_PER_SEGMENT - 3) * FT_SECTOR_SIZE);
- result = 0;
-#define HEADER_SEGMENT_BOUNDARY 68 /* why not 42? */
- for (header_segment = 0;
- header_segment < HEADER_SEGMENT_BOUNDARY && result == 0;
- ++header_segment) {
- /* Set no read-ahead, the isr will force read-ahead whenever
- * it encounters deleted data !
- */
- result = ftape_read_segment(header_segment,
- address,
- FT_RD_SINGLE);
- if (result < 0 && !first_failed) {
- TRACE(ft_t_err, "header segment damaged, trying backup");
- first_failed = 1;
- result = 0; /* force read of next (backup) segment */
- }
- }
- if (result < 0 || header_segment >= HEADER_SEGMENT_BOUNDARY) {
- TRACE_ABORT(-EIO, ft_t_err,
- "no readable header segment found");
- }
- TRACE_CATCH(ftape_abort_operation(),);
- ft_used_header_segment = header_segment;
- result = ftape_decode_header_segment(address);
- TRACE_EXIT result;
-}
-
-int ftape_decode_header_segment(__u8 *address)
-{
- unsigned int max_floppy_side;
- unsigned int max_floppy_track;
- unsigned int max_floppy_sector;
- unsigned int new_tape_len;
- TRACE_FUN(ft_t_flow);
-
- if (GET4(address, FT_SIGNATURE) == FT_D2G_MAGIC) {
- /* Ditto 2GB header segment. They encrypt the bad sector map.
- * We decrypt it and store them in normal format.
- * I hope this is correct.
- */
- int i;
- TRACE(ft_t_warn,
- "Found Ditto 2GB tape, "
- "trying to decrypt bad sector map");
- for (i=256; i < 29 * FT_SECTOR_SIZE; i++) {
- address[i] = ~(address[i] - (i&0xff));
- }
- PUT4(address, 0,FT_HSEG_MAGIC);
- } else if (GET4(address, FT_SIGNATURE) != FT_HSEG_MAGIC) {
- TRACE_ABORT(-EIO, ft_t_err,
- "wrong signature in header segment");
- }
- ft_format_code = (ft_format_type) address[FT_FMT_CODE];
- if (ft_format_code != fmt_big) {
- ft_header_segment_1 = GET2(address, FT_HSEG_1);
- ft_header_segment_2 = GET2(address, FT_HSEG_2);
- ft_first_data_segment = GET2(address, FT_FRST_SEG);
- ft_last_data_segment = GET2(address, FT_LAST_SEG);
- } else {
- ft_header_segment_1 = GET4(address, FT_6_HSEG_1);
- ft_header_segment_2 = GET4(address, FT_6_HSEG_2);
- ft_first_data_segment = GET4(address, FT_6_FRST_SEG);
- ft_last_data_segment = GET4(address, FT_6_LAST_SEG);
- }
- TRACE(ft_t_noise, "first data segment: %d", ft_first_data_segment);
- TRACE(ft_t_noise, "last data segment: %d", ft_last_data_segment);
- TRACE(ft_t_noise, "header segments are %d and %d",
- ft_header_segment_1, ft_header_segment_2);
-
- /* Verify tape parameters...
- * QIC-40/80 spec: tape_parameters:
- *
- * segments-per-track segments_per_track
- * tracks-per-cartridge tracks_per_tape
- * max-floppy-side (segments_per_track *
- * tracks_per_tape - 1) /
- * ftape_segments_per_head
- * max-floppy-track ftape_segments_per_head /
- * ftape_segments_per_cylinder - 1
- * max-floppy-sector ftape_segments_per_cylinder *
- * FT_SECTORS_PER_SEGMENT
- */
- ft_segments_per_track = GET2(address, FT_SPT);
- ft_tracks_per_tape = address[FT_TPC];
- max_floppy_side = address[FT_FHM];
- max_floppy_track = address[FT_FTM];
- max_floppy_sector = address[FT_FSM];
- TRACE(ft_t_noise, "(fmt/spt/tpc/fhm/ftm/fsm) = %d/%d/%d/%d/%d/%d",
- ft_format_code, ft_segments_per_track, ft_tracks_per_tape,
- max_floppy_side, max_floppy_track, max_floppy_sector);
- new_tape_len = ftape_tape_len;
- switch (ft_format_code) {
- case fmt_425ft:
- new_tape_len = 425;
- break;
- case fmt_normal:
- if (ftape_tape_len == 0) { /* otherwise 307 ft */
- new_tape_len = 205;
- }
- break;
- case fmt_1100ft:
- new_tape_len = 1100;
- break;
- case fmt_var:{
- int segments_per_1000_inch = 1; /* non-zero default for switch */
- switch (ft_qic_std) {
- case QIC_TAPE_QIC40:
- segments_per_1000_inch = 332;
- break;
- case QIC_TAPE_QIC80:
- segments_per_1000_inch = 488;
- break;
- case QIC_TAPE_QIC3010:
- segments_per_1000_inch = 730;
- break;
- case QIC_TAPE_QIC3020:
- segments_per_1000_inch = 1430;
- break;
- }
- new_tape_len = (1000 * ft_segments_per_track +
- (segments_per_1000_inch - 1)) / segments_per_1000_inch;
- break;
- }
- case fmt_big:{
- int segments_per_1000_inch = 1; /* non-zero default for switch */
- switch (ft_qic_std) {
- case QIC_TAPE_QIC40:
- segments_per_1000_inch = 332;
- break;
- case QIC_TAPE_QIC80:
- segments_per_1000_inch = 488;
- break;
- case QIC_TAPE_QIC3010:
- segments_per_1000_inch = 730;
- break;
- case QIC_TAPE_QIC3020:
- segments_per_1000_inch = 1430;
- break;
- default:
- TRACE_ABORT(-EIO, ft_t_bug,
- "%x QIC-standard with fmt-code %d, please report",
- ft_qic_std, ft_format_code);
- }
- new_tape_len = ((1000 * ft_segments_per_track +
- (segments_per_1000_inch - 1)) /
- segments_per_1000_inch);
- break;
- }
- default:
- TRACE_ABORT(-EIO, ft_t_err,
- "unknown tape format, please report !");
- }
- if (new_tape_len != ftape_tape_len) {
- ftape_tape_len = new_tape_len;
- TRACE(ft_t_info, "calculated tape length is %d ft",
- ftape_tape_len);
- ftape_calc_timeouts(ft_qic_std, ft_data_rate, ftape_tape_len);
- }
- if (ft_segments_per_track == 0 && ft_tracks_per_tape == 0 &&
- max_floppy_side == 0 && max_floppy_track == 0 &&
- max_floppy_sector == 0) {
- /* QIC-40 Rev E and earlier has no values in the header.
- */
- ft_segments_per_track = 68;
- ft_tracks_per_tape = 20;
- max_floppy_side = 1;
- max_floppy_track = 169;
- max_floppy_sector = 128;
- }
- /* This test will compensate for the wrong parameter on tapes
- * formatted by Conner software.
- */
- if (ft_segments_per_track == 150 &&
- ft_tracks_per_tape == 28 &&
- max_floppy_side == 7 &&
- max_floppy_track == 149 &&
- max_floppy_sector == 128) {
-TRACE(ft_t_info, "the famous CONNER bug: max_floppy_side off by one !");
- max_floppy_side = 6;
- }
- /* These tests will compensate for the wrong parameter on tapes
- * formatted by ComByte Windows software.
- *
- * First, for 205 foot tapes
- */
- if (ft_segments_per_track == 100 &&
- ft_tracks_per_tape == 28 &&
- max_floppy_side == 9 &&
- max_floppy_track == 149 &&
- max_floppy_sector == 128) {
-TRACE(ft_t_info, "the ComByte bug: max_floppy_side incorrect!");
- max_floppy_side = 4;
- }
- /* Next, for 307 foot tapes. */
- if (ft_segments_per_track == 150 &&
- ft_tracks_per_tape == 28 &&
- max_floppy_side == 9 &&
- max_floppy_track == 149 &&
- max_floppy_sector == 128) {
-TRACE(ft_t_info, "the ComByte bug: max_floppy_side incorrect!");
- max_floppy_side = 6;
- }
- /* This test will compensate for the wrong parameter on tapes
- * formatted by Colorado Windows software.
- */
- if (ft_segments_per_track == 150 &&
- ft_tracks_per_tape == 28 &&
- max_floppy_side == 6 &&
- max_floppy_track == 150 &&
- max_floppy_sector == 128) {
-TRACE(ft_t_info, "the famous Colorado bug: max_floppy_track off by one !");
- max_floppy_track = 149;
- }
- ftape_segments_per_head = ((max_floppy_sector/FT_SECTORS_PER_SEGMENT) *
- (max_floppy_track + 1));
- /* This test will compensate for some bug reported by Dima
- * Brodsky. Seems to be a Colorado bug, either. (freebee
- * Imation tape shipped together with Colorado T3000
- */
- if ((ft_format_code == fmt_var || ft_format_code == fmt_big) &&
- ft_tracks_per_tape == 50 &&
- max_floppy_side == 54 &&
- max_floppy_track == 255 &&
- max_floppy_sector == 128) {
-TRACE(ft_t_info, "the famous ??? bug: max_floppy_track off by one !");
- max_floppy_track = 254;
- }
- /*
- * Verify drive_configuration with tape parameters
- */
- if (ftape_segments_per_head == 0 || ftape_segments_per_cylinder == 0 ||
- ((ft_segments_per_track * ft_tracks_per_tape - 1) / ftape_segments_per_head
- != max_floppy_side) ||
- (ftape_segments_per_head / ftape_segments_per_cylinder - 1 != max_floppy_track) ||
- (ftape_segments_per_cylinder * FT_SECTORS_PER_SEGMENT != max_floppy_sector)
-#ifdef TESTING
- || ((ft_format_code == fmt_var || ft_format_code == fmt_big) &&
- (max_floppy_track != 254 || max_floppy_sector != 128))
-#endif
- ) {
- char segperheadz = ftape_segments_per_head ? ' ' : '?';
- char segpercylz = ftape_segments_per_cylinder ? ' ' : '?';
- TRACE(ft_t_err,"Tape parameters inconsistency, please report");
- TRACE(ft_t_err, "reported = %d/%d/%d/%d/%d/%d",
- ft_format_code,
- ft_segments_per_track,
- ft_tracks_per_tape,
- max_floppy_side,
- max_floppy_track,
- max_floppy_sector);
- TRACE(ft_t_err, "required = %d/%d/%d/%d%c/%d%c/%d",
- ft_format_code,
- ft_segments_per_track,
- ft_tracks_per_tape,
- ftape_segments_per_head ?
- ((ft_segments_per_track * ft_tracks_per_tape -1) /
- ftape_segments_per_head ) :
- (ft_segments_per_track * ft_tracks_per_tape -1),
- segperheadz,
- ftape_segments_per_cylinder ?
- (ftape_segments_per_head /
- ftape_segments_per_cylinder - 1 ) :
- ftape_segments_per_head - 1,
- segpercylz,
- (ftape_segments_per_cylinder * FT_SECTORS_PER_SEGMENT));
- TRACE_EXIT -EIO;
- }
- ftape_extract_bad_sector_map(address);
- TRACE_EXIT 0;
-}
diff --git a/drivers/char/ftape/lowlevel/ftape-read.h b/drivers/char/ftape/lowlevel/ftape-read.h
deleted file mode 100644
index 069f99f2a984..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-read.h
+++ /dev/null
@@ -1,51 +0,0 @@
-#ifndef _FTAPE_READ_H
-#define _FTAPE_READ_H
-
-/*
- * Copyright (C) 1994-1996 Bas Laarhoven,
- * (C) 1996-1997 Claus-Justus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-read.h,v $
- * $Revision: 1.2 $
- * $Date: 1997/10/05 19:18:22 $
- *
- * This file contains the definitions for the read functions
- * for the QIC-117 floppy-tape driver for Linux.
- *
- */
-
-/* ftape-read.c defined global functions.
- */
-typedef enum {
- FT_RD_SINGLE = 0,
- FT_RD_AHEAD = 1,
-} ft_read_mode_t;
-
-extern int ftape_read_header_segment(__u8 *address);
-extern int ftape_decode_header_segment(__u8 *address);
-extern int ftape_read_segment_fraction(const int segment,
- void *address,
- const ft_read_mode_t read_mode,
- const int start,
- const int size);
-#define ftape_read_segment(segment, address, read_mode) \
- ftape_read_segment_fraction(segment, address, read_mode, \
- 0, FT_SEGMENT_SIZE)
-extern void ftape_zap_read_buffers(void);
-
-#endif /* _FTAPE_READ_H */
diff --git a/drivers/char/ftape/lowlevel/ftape-rw.c b/drivers/char/ftape/lowlevel/ftape-rw.c
deleted file mode 100644
index c0d6dc2cbfd3..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-rw.c
+++ /dev/null
@@ -1,1092 +0,0 @@
-/*
- * Copyright (C) 1993-1996 Bas Laarhoven,
- * (C) 1996-1997 Claus-Justus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-rw.c,v $
- * $Revision: 1.7 $
- * $Date: 1997/10/28 14:26:49 $
- *
- * This file contains some common code for the segment read and
- * segment write routines for the QIC-117 floppy-tape driver for
- * Linux.
- */
-
-#include <linux/string.h>
-#include <linux/errno.h>
-
-#include <linux/ftape.h>
-#include <linux/qic117.h>
-#include "../lowlevel/ftape-tracing.h"
-#include "../lowlevel/ftape-rw.h"
-#include "../lowlevel/fdc-io.h"
-#include "../lowlevel/ftape-init.h"
-#include "../lowlevel/ftape-io.h"
-#include "../lowlevel/ftape-ctl.h"
-#include "../lowlevel/ftape-read.h"
-#include "../lowlevel/ftape-ecc.h"
-#include "../lowlevel/ftape-bsm.h"
-
-/* Global vars.
- */
-int ft_nr_buffers;
-buffer_struct *ft_buffer[FT_MAX_NR_BUFFERS];
-static volatile int ft_head;
-static volatile int ft_tail; /* not volatile but need same type as head */
-int fdc_setup_error;
-location_record ft_location = {-1, 0};
-volatile int ftape_tape_running;
-
-/* Local vars.
- */
-static int overrun_count_offset;
-static int inhibit_correction;
-
-/* maxmimal allowed overshoot when fast seeking
- */
-#define OVERSHOOT_LIMIT 10
-
-/* Increment cyclic buffer nr.
- */
-buffer_struct *ftape_next_buffer(ft_buffer_queue_t pos)
-{
- switch (pos) {
- case ft_queue_head:
- if (++ft_head >= ft_nr_buffers) {
- ft_head = 0;
- }
- return ft_buffer[ft_head];
- case ft_queue_tail:
- if (++ft_tail >= ft_nr_buffers) {
- ft_tail = 0;
- }
- return ft_buffer[ft_tail];
- default:
- return NULL;
- }
-}
-int ftape_buffer_id(ft_buffer_queue_t pos)
-{
- switch(pos) {
- case ft_queue_head: return ft_head;
- case ft_queue_tail: return ft_tail;
- default: return -1;
- }
-}
-buffer_struct *ftape_get_buffer(ft_buffer_queue_t pos)
-{
- switch(pos) {
- case ft_queue_head: return ft_buffer[ft_head];
- case ft_queue_tail: return ft_buffer[ft_tail];
- default: return NULL;
- }
-}
-void ftape_reset_buffer(void)
-{
- ft_head = ft_tail = 0;
-}
-
-buffer_state_enum ftape_set_state(buffer_state_enum new_state)
-{
- buffer_state_enum old_state = ft_driver_state;
-
- ft_driver_state = new_state;
- return old_state;
-}
-/* Calculate Floppy Disk Controller and DMA parameters for a segment.
- * head: selects buffer struct in array.
- * offset: number of physical sectors to skip (including bad ones).
- * count: number of physical sectors to handle (including bad ones).
- */
-static int setup_segment(buffer_struct * buff,
- int segment_id,
- unsigned int sector_offset,
- unsigned int sector_count,
- int retry)
-{
- SectorMap offset_mask;
- SectorMap mask;
- TRACE_FUN(ft_t_any);
-
- buff->segment_id = segment_id;
- buff->sector_offset = sector_offset;
- buff->remaining = sector_count;
- buff->head = segment_id / ftape_segments_per_head;
- buff->cyl = (segment_id % ftape_segments_per_head) / ftape_segments_per_cylinder;
- buff->sect = (segment_id % ftape_segments_per_cylinder) * FT_SECTORS_PER_SEGMENT + 1;
- buff->deleted = 0;
- offset_mask = (1 << buff->sector_offset) - 1;
- mask = ftape_get_bad_sector_entry(segment_id) & offset_mask;
- while (mask) {
- if (mask & 1) {
- offset_mask >>= 1; /* don't count bad sector */
- }
- mask >>= 1;
- }
- buff->data_offset = count_ones(offset_mask); /* good sectors to skip */
- buff->ptr = buff->address + buff->data_offset * FT_SECTOR_SIZE;
- TRACE(ft_t_flow, "data offset = %d sectors", buff->data_offset);
- if (retry) {
- buff->soft_error_map &= offset_mask; /* keep skipped part */
- } else {
- buff->hard_error_map = buff->soft_error_map = 0;
- }
- buff->bad_sector_map = ftape_get_bad_sector_entry(buff->segment_id);
- if (buff->bad_sector_map != 0) {
- TRACE(ft_t_noise, "segment: %d, bad sector map: %08lx",
- buff->segment_id, (long)buff->bad_sector_map);
- } else {
- TRACE(ft_t_flow, "segment: %d", buff->segment_id);
- }
- if (buff->sector_offset > 0) {
- buff->bad_sector_map >>= buff->sector_offset;
- }
- if (buff->sector_offset != 0 || buff->remaining != FT_SECTORS_PER_SEGMENT) {
- TRACE(ft_t_flow, "sector offset = %d, count = %d",
- buff->sector_offset, buff->remaining);
- }
- /* Segments with 3 or less sectors are not written with valid
- * data because there is no space left for the ecc. The
- * data written is whatever happens to be in the buffer.
- * Reading such a segment will return a zero byte-count.
- * To allow us to read/write segments with all bad sectors
- * we fake one readable sector in the segment. This
- * prevents having to handle these segments in a very
- * special way. It is not important if the reading of this
- * bad sector fails or not (the data is ignored). It is
- * only read to keep the driver running.
- *
- * The QIC-40/80 spec. has no information on how to handle
- * this case, so this is my interpretation.
- */
- if (buff->bad_sector_map == EMPTY_SEGMENT) {
- TRACE(ft_t_flow, "empty segment %d, fake first sector good",
- buff->segment_id);
- if (buff->ptr != buff->address) {
- TRACE(ft_t_bug, "This is a bug: %p/%p",
- buff->ptr, buff->address);
- }
- buff->bad_sector_map = FAKE_SEGMENT;
- }
- fdc_setup_error = 0;
- buff->next_segment = segment_id + 1;
- TRACE_EXIT 0;
-}
-
-/* Calculate Floppy Disk Controller and DMA parameters for a new segment.
- */
-int ftape_setup_new_segment(buffer_struct * buff, int segment_id, int skip)
-{
- int result = 0;
- static int old_segment_id = -1;
- static buffer_state_enum old_ft_driver_state = idle;
- int retry = 0;
- unsigned offset = 0;
- int count = FT_SECTORS_PER_SEGMENT;
- TRACE_FUN(ft_t_flow);
-
- TRACE(ft_t_flow, "%s segment %d (old = %d)",
- (ft_driver_state == reading || ft_driver_state == verifying)
- ? "reading" : "writing",
- segment_id, old_segment_id);
- if (ft_driver_state != old_ft_driver_state) { /* when verifying */
- old_segment_id = -1;
- old_ft_driver_state = ft_driver_state;
- }
- if (segment_id == old_segment_id) {
- ++buff->retry;
- ++ft_history.retries;
- TRACE(ft_t_flow, "setting up for retry nr %d", buff->retry);
- retry = 1;
- if (skip && buff->skip > 0) { /* allow skip on retry */
- offset = buff->skip;
- count -= offset;
- TRACE(ft_t_flow, "skipping %d sectors", offset);
- }
- } else {
- buff->retry = 0;
- buff->skip = 0;
- old_segment_id = segment_id;
- }
- result = setup_segment(buff, segment_id, offset, count, retry);
- TRACE_EXIT result;
-}
-
-/* Determine size of next cluster of good sectors.
- */
-int ftape_calc_next_cluster(buffer_struct * buff)
-{
- /* Skip bad sectors.
- */
- while (buff->remaining > 0 && (buff->bad_sector_map & 1) != 0) {
- buff->bad_sector_map >>= 1;
- ++buff->sector_offset;
- --buff->remaining;
- }
- /* Find next cluster of good sectors
- */
- if (buff->bad_sector_map == 0) { /* speed up */
- buff->sector_count = buff->remaining;
- } else {
- SectorMap map = buff->bad_sector_map;
-
- buff->sector_count = 0;
- while (buff->sector_count < buff->remaining && (map & 1) == 0) {
- ++buff->sector_count;
- map >>= 1;
- }
- }
- return buff->sector_count;
-}
-
-/* if just passed the last segment on a track, wait for BOT
- * or EOT mark.
- */
-int ftape_handle_logical_eot(void)
-{
- TRACE_FUN(ft_t_flow);
-
- if (ft_runner_status == logical_eot) {
- int status;
-
- TRACE(ft_t_noise, "tape at logical EOT");
- TRACE_CATCH(ftape_ready_wait(ftape_timeout.seek, &status),);
- if ((status & (QIC_STATUS_AT_BOT | QIC_STATUS_AT_EOT)) == 0) {
- TRACE_ABORT(-EIO, ft_t_err, "eot/bot not reached");
- }
- ft_runner_status = end_of_tape;
- }
- if (ft_runner_status == end_of_tape) {
- TRACE(ft_t_noise, "runner stopped because of logical EOT");
- ft_runner_status = idle;
- }
- TRACE_EXIT 0;
-}
-
-static int check_bot_eot(int status)
-{
- TRACE_FUN(ft_t_flow);
-
- if (status & (QIC_STATUS_AT_BOT | QIC_STATUS_AT_EOT)) {
- ft_location.bot = ((ft_location.track & 1) == 0 ?
- (status & QIC_STATUS_AT_BOT) != 0:
- (status & QIC_STATUS_AT_EOT) != 0);
- ft_location.eot = !ft_location.bot;
- ft_location.segment = (ft_location.track +
- (ft_location.bot ? 0 : 1)) * ft_segments_per_track - 1;
- ft_location.sector = -1;
- ft_location.known = 1;
- TRACE(ft_t_flow, "tape at logical %s",
- ft_location.bot ? "bot" : "eot");
- TRACE(ft_t_flow, "segment = %d", ft_location.segment);
- } else {
- ft_location.known = 0;
- }
- TRACE_EXIT ft_location.known;
-}
-
-/* Read Id of first sector passing tape head.
- */
-static int ftape_read_id(void)
-{
- int status;
- __u8 out[2];
- TRACE_FUN(ft_t_any);
-
- /* Assume tape is running on entry, be able to handle
- * situation where it stopped or is stopping.
- */
- ft_location.known = 0; /* default is location not known */
- out[0] = FDC_READID;
- out[1] = ft_drive_sel;
- TRACE_CATCH(fdc_command(out, 2),);
- switch (fdc_interrupt_wait(20 * FT_SECOND)) {
- case 0:
- if (fdc_sect == 0) {
- if (ftape_report_drive_status(&status) >= 0 &&
- (status & QIC_STATUS_READY)) {
- ftape_tape_running = 0;
- TRACE(ft_t_flow, "tape has stopped");
- check_bot_eot(status);
- }
- } else {
- ft_location.known = 1;
- ft_location.segment = (ftape_segments_per_head
- * fdc_head
- + ftape_segments_per_cylinder
- * fdc_cyl
- + (fdc_sect - 1)
- / FT_SECTORS_PER_SEGMENT);
- ft_location.sector = ((fdc_sect - 1)
- % FT_SECTORS_PER_SEGMENT);
- ft_location.eot = ft_location.bot = 0;
- }
- break;
- case -ETIME:
- /* Didn't find id on tape, must be near end: Wait
- * until stopped.
- */
- if (ftape_ready_wait(FT_FOREVER, &status) >= 0) {
- ftape_tape_running = 0;
- TRACE(ft_t_flow, "tape has stopped");
- check_bot_eot(status);
- }
- break;
- default:
- /* Interrupted or otherwise failing
- * fdc_interrupt_wait()
- */
- TRACE(ft_t_err, "fdc_interrupt_wait failed");
- break;
- }
- if (!ft_location.known) {
- TRACE_ABORT(-EIO, ft_t_flow, "no id found");
- }
- if (ft_location.sector == 0) {
- TRACE(ft_t_flow, "passing segment %d/%d",
- ft_location.segment, ft_location.sector);
- } else {
- TRACE(ft_t_fdc_dma, "passing segment %d/%d",
- ft_location.segment, ft_location.sector);
- }
- TRACE_EXIT 0;
-}
-
-static int logical_forward(void)
-{
- ftape_tape_running = 1;
- return ftape_command(QIC_LOGICAL_FORWARD);
-}
-
-int ftape_stop_tape(int *pstatus)
-{
- int retry = 0;
- int result;
- TRACE_FUN(ft_t_flow);
-
- do {
- result = ftape_command_wait(QIC_STOP_TAPE,
- ftape_timeout.stop, pstatus);
- if (result == 0) {
- if ((*pstatus & QIC_STATUS_READY) == 0) {
- result = -EIO;
- } else {
- ftape_tape_running = 0;
- }
- }
- } while (result < 0 && ++retry <= 3);
- if (result < 0) {
- TRACE(ft_t_err, "failed ! (fatal)");
- }
- TRACE_EXIT result;
-}
-
-int ftape_dumb_stop(void)
-{
- int result;
- int status;
- TRACE_FUN(ft_t_flow);
-
- /* Abort current fdc operation if it's busy (probably read
- * or write operation pending) with a reset.
- */
- if (fdc_ready_wait(100 /* usec */) < 0) {
- TRACE(ft_t_noise, "aborting fdc operation");
- fdc_reset();
- }
- /* Reading id's after the last segment on a track may fail
- * but eventually the drive will become ready (logical eot).
- */
- result = ftape_report_drive_status(&status);
- ft_location.known = 0;
- do {
- if (result == 0 && status & QIC_STATUS_READY) {
- /* Tape is not running any more.
- */
- TRACE(ft_t_noise, "tape already halted");
- check_bot_eot(status);
- ftape_tape_running = 0;
- } else if (ftape_tape_running) {
- /* Tape is (was) still moving.
- */
-#ifdef TESTING
- ftape_read_id();
-#endif
- result = ftape_stop_tape(&status);
- } else {
- /* Tape not yet ready but stopped.
- */
- result = ftape_ready_wait(ftape_timeout.pause,&status);
- }
- } while (ftape_tape_running
- && !(sigtestsetmask(&current->pending.signal, _NEVER_BLOCK)));
-#ifndef TESTING
- ft_location.known = 0;
-#endif
- if (ft_runner_status == aborting || ft_runner_status == do_abort) {
- ft_runner_status = idle;
- }
- TRACE_EXIT result;
-}
-
-/* Wait until runner has finished tail buffer.
- *
- */
-int ftape_wait_segment(buffer_state_enum state)
-{
- int status;
- int result = 0;
- TRACE_FUN(ft_t_flow);
-
- while (ft_buffer[ft_tail]->status == state) {
- TRACE(ft_t_flow, "state: %d", ft_buffer[ft_tail]->status);
- /* First buffer still being worked on, wait up to timeout.
- *
- * Note: we check two times for being killed. 50
- * seconds are quite long. Note that
- * fdc_interrupt_wait() is not killable by any
- * means. ftape_read_segment() wants us to return
- * -EINTR in case of a signal.
- */
- FT_SIGNAL_EXIT(_DONT_BLOCK);
- result = fdc_interrupt_wait(50 * FT_SECOND);
- FT_SIGNAL_EXIT(_DONT_BLOCK);
- if (result < 0) {
- TRACE_ABORT(result,
- ft_t_err, "fdc_interrupt_wait failed");
- }
- if (fdc_setup_error) {
- /* recover... FIXME */
- TRACE_ABORT(-EIO, ft_t_err, "setup error");
- }
- }
- if (ft_buffer[ft_tail]->status != error) {
- TRACE_EXIT 0;
- }
- TRACE_CATCH(ftape_report_drive_status(&status),);
- TRACE(ft_t_noise, "ftape_report_drive_status: 0x%02x", status);
- if ((status & QIC_STATUS_READY) &&
- (status & QIC_STATUS_ERROR)) {
- unsigned int error;
- qic117_cmd_t command;
-
- /* Report and clear error state.
- * In case the drive can't operate at the selected
- * rate, select the next lower data rate.
- */
- ftape_report_error(&error, &command, 1);
- if (error == 31 && command == QIC_LOGICAL_FORWARD) {
- /* drive does not accept this data rate */
- if (ft_data_rate > 250) {
- TRACE(ft_t_info,
- "Probable data rate conflict");
- TRACE(ft_t_info,
- "Lowering data rate to %d Kbps",
- ft_data_rate / 2);
- ftape_half_data_rate();
- if (ft_buffer[ft_tail]->retry > 0) {
- /* give it a chance */
- --ft_buffer[ft_tail]->retry;
- }
- } else {
- /* no rate is accepted... */
- TRACE(ft_t_err, "We're dead :(");
- }
- } else {
- TRACE(ft_t_err, "Unknown error");
- }
- TRACE_EXIT -EIO; /* g.p. error */
- }
- TRACE_EXIT 0;
-}
-
-/* forward */ static int seek_forward(int segment_id, int fast);
-
-static int fast_seek(int count, int reverse)
-{
- int result = 0;
- int status;
- TRACE_FUN(ft_t_flow);
-
- if (count > 0) {
- /* If positioned at begin or end of tape, fast seeking needs
- * special treatment.
- * Starting from logical bot needs a (slow) seek to the first
- * segment before the high speed seek. Most drives do this
- * automatically but some older don't, so we treat them
- * all the same.
- * Starting from logical eot is even more difficult because
- * we cannot (slow) reverse seek to the last segment.
- * TO BE IMPLEMENTED.
- */
- inhibit_correction = 0;
- if (ft_location.known &&
- ((ft_location.bot && !reverse) ||
- (ft_location.eot && reverse))) {
- if (!reverse) {
- /* (slow) skip to first segment on a track
- */
- seek_forward(ft_location.track * ft_segments_per_track, 0);
- --count;
- } else {
- /* When seeking backwards from
- * end-of-tape the number of erased
- * gaps found seems to be higher than
- * expected. Therefor the drive must
- * skip some more segments than
- * calculated, but we don't know how
- * many. Thus we will prevent the
- * re-calculation of offset and
- * overshoot when seeking backwards.
- */
- inhibit_correction = 1;
- count += 3; /* best guess */
- }
- }
- } else {
- TRACE(ft_t_flow, "warning: zero or negative count: %d", count);
- }
- if (count > 0) {
- int i;
- int nibbles = count > 255 ? 3 : 2;
-
- if (count > 4095) {
- TRACE(ft_t_noise, "skipping clipped at 4095 segment");
- count = 4095;
- }
- /* Issue this tape command first. */
- if (!reverse) {
- TRACE(ft_t_noise, "skipping %d segment(s)", count);
- result = ftape_command(nibbles == 3 ?
- QIC_SKIP_EXTENDED_FORWARD : QIC_SKIP_FORWARD);
- } else {
- TRACE(ft_t_noise, "backing up %d segment(s)", count);
- result = ftape_command(nibbles == 3 ?
- QIC_SKIP_EXTENDED_REVERSE : QIC_SKIP_REVERSE);
- }
- if (result < 0) {
- TRACE(ft_t_noise, "Skip command failed");
- } else {
- --count; /* 0 means one gap etc. */
- for (i = 0; i < nibbles; ++i) {
- if (result >= 0) {
- result = ftape_parameter(count & 15);
- count /= 16;
- }
- }
- result = ftape_ready_wait(ftape_timeout.rewind, &status);
- if (result >= 0) {
- ftape_tape_running = 0;
- }
- }
- }
- TRACE_EXIT result;
-}
-
-static int validate(int id)
-{
- /* Check to see if position found is off-track as reported
- * once. Because all tracks in one direction lie next to
- * each other, if off-track the error will be approximately
- * 2 * ft_segments_per_track.
- */
- if (ft_location.track == -1) {
- return 1; /* unforseen situation, don't generate error */
- } else {
- /* Use margin of ft_segments_per_track on both sides
- * because ftape needs some margin and the error we're
- * looking for is much larger !
- */
- int lo = (ft_location.track - 1) * ft_segments_per_track;
- int hi = (ft_location.track + 2) * ft_segments_per_track;
-
- return (id >= lo && id < hi);
- }
-}
-
-static int seek_forward(int segment_id, int fast)
-{
- int failures = 0;
- int count;
- static int margin = 1; /* fixed: stop this before target */
- static int overshoot = 1;
- static int min_count = 8;
- int expected = -1;
- int target = segment_id - margin;
- int fast_seeking;
- int prev_segment = ft_location.segment;
- TRACE_FUN(ft_t_flow);
-
- if (!ft_location.known) {
- TRACE_ABORT(-EIO, ft_t_err,
- "fatal: cannot seek from unknown location");
- }
- if (!validate(segment_id)) {
- ftape_sleep(1 * FT_SECOND);
- ft_failure = 1;
- TRACE_ABORT(-EIO, ft_t_err,
- "fatal: head off track (bad hardware?)");
- }
- TRACE(ft_t_noise, "from %d/%d to %d/0 - %d",
- ft_location.segment, ft_location.sector,segment_id,margin);
- count = target - ft_location.segment - overshoot;
- fast_seeking = (fast &&
- count > (min_count + (ft_location.bot ? 1 : 0)));
- if (fast_seeking) {
- TRACE(ft_t_noise, "fast skipping %d segments", count);
- expected = segment_id - margin;
- fast_seek(count, 0);
- }
- if (!ftape_tape_running) {
- logical_forward();
- }
- while (ft_location.segment < segment_id) {
- /* This requires at least one sector in a (bad) segment to
- * have a valid and readable sector id !
- * It looks like this is not guaranteed, so we must try
- * to find a way to skip an EMPTY_SEGMENT. !!! FIXME !!!
- */
- if (ftape_read_id() < 0 || !ft_location.known ||
- sigtestsetmask(&current->pending.signal, _DONT_BLOCK)) {
- ft_location.known = 0;
- if (!ftape_tape_running ||
- ++failures > FT_SECTORS_PER_SEGMENT) {
- TRACE_ABORT(-EIO, ft_t_err,
- "read_id failed completely");
- }
- FT_SIGNAL_EXIT(_DONT_BLOCK);
- TRACE(ft_t_flow, "read_id failed, retry (%d)",
- failures);
- continue;
- }
- if (fast_seeking) {
- TRACE(ft_t_noise, "ended at %d/%d (%d,%d)",
- ft_location.segment, ft_location.sector,
- overshoot, inhibit_correction);
- if (!inhibit_correction &&
- (ft_location.segment < expected ||
- ft_location.segment > expected + margin)) {
- int error = ft_location.segment - expected;
- TRACE(ft_t_noise,
- "adjusting overshoot from %d to %d",
- overshoot, overshoot + error);
- overshoot += error;
- /* All overshoots have the same
- * direction, so it should never
- * become negative, but who knows.
- */
- if (overshoot < -5 ||
- overshoot > OVERSHOOT_LIMIT) {
- if (overshoot < 0) {
- /* keep sane value */
- overshoot = -5;
- } else {
- /* keep sane value */
- overshoot = OVERSHOOT_LIMIT;
- }
- TRACE(ft_t_noise,
- "clipped overshoot to %d",
- overshoot);
- }
- }
- fast_seeking = 0;
- }
- if (ft_location.known) {
- if (ft_location.segment > prev_segment + 1) {
- TRACE(ft_t_noise,
- "missed segment %d while skipping",
- prev_segment + 1);
- }
- prev_segment = ft_location.segment;
- }
- }
- if (ft_location.segment > segment_id) {
- TRACE_ABORT(-EIO,
- ft_t_noise, "failed: skip ended at segment %d/%d",
- ft_location.segment, ft_location.sector);
- }
- TRACE_EXIT 0;
-}
-
-static int skip_reverse(int segment_id, int *pstatus)
-{
- int failures = 0;
- static int overshoot = 1;
- static int min_rewind = 2; /* 1 + overshoot */
- static const int margin = 1; /* stop this before target */
- int expected = 0;
- int count = 1;
- int short_seek;
- int target = segment_id - margin;
- TRACE_FUN(ft_t_flow);
-
- if (ft_location.known && !validate(segment_id)) {
- ftape_sleep(1 * FT_SECOND);
- ft_failure = 1;
- TRACE_ABORT(-EIO, ft_t_err,
- "fatal: head off track (bad hardware?)");
- }
- do {
- if (!ft_location.known) {
- TRACE(ft_t_warn, "warning: location not known");
- }
- TRACE(ft_t_noise, "from %d/%d to %d/0 - %d",
- ft_location.segment, ft_location.sector,
- segment_id, margin);
- /* min_rewind == 1 + overshoot_when_doing_minimum_rewind
- * overshoot == overshoot_when_doing_larger_rewind
- * Initially min_rewind == 1 + overshoot, optimization
- * of both values will be done separately.
- * overshoot and min_rewind can be negative as both are
- * sums of three components:
- * any_overshoot == rewind_overshoot -
- * stop_overshoot -
- * start_overshoot
- */
- if (ft_location.segment - target - (min_rewind - 1) < 1) {
- short_seek = 1;
- } else {
- count = ft_location.segment - target - overshoot;
- short_seek = (count < 1);
- }
- if (short_seek) {
- count = 1; /* do shortest rewind */
- expected = ft_location.segment - min_rewind;
- if (expected/ft_segments_per_track != ft_location.track) {
- expected = (ft_location.track *
- ft_segments_per_track);
- }
- } else {
- expected = target;
- }
- fast_seek(count, 1);
- logical_forward();
- if (ftape_read_id() < 0 || !ft_location.known ||
- (sigtestsetmask(&current->pending.signal, _DONT_BLOCK))) {
- if ((!ftape_tape_running && !ft_location.known) ||
- ++failures > FT_SECTORS_PER_SEGMENT) {
- TRACE_ABORT(-EIO, ft_t_err,
- "read_id failed completely");
- }
- FT_SIGNAL_EXIT(_DONT_BLOCK);
- TRACE_CATCH(ftape_report_drive_status(pstatus),);
- TRACE(ft_t_noise, "ftape_read_id failed, retry (%d)",
- failures);
- continue;
- }
- TRACE(ft_t_noise, "ended at %d/%d (%d,%d,%d)",
- ft_location.segment, ft_location.sector,
- min_rewind, overshoot, inhibit_correction);
- if (!inhibit_correction &&
- (ft_location.segment < expected ||
- ft_location.segment > expected + margin)) {
- int error = expected - ft_location.segment;
- if (short_seek) {
- TRACE(ft_t_noise,
- "adjusting min_rewind from %d to %d",
- min_rewind, min_rewind + error);
- min_rewind += error;
- if (min_rewind < -5) {
- /* is this right ? FIXME ! */
- /* keep sane value */
- min_rewind = -5;
- TRACE(ft_t_noise,
- "clipped min_rewind to %d",
- min_rewind);
- }
- } else {
- TRACE(ft_t_noise,
- "adjusting overshoot from %d to %d",
- overshoot, overshoot + error);
- overshoot += error;
- if (overshoot < -5 ||
- overshoot > OVERSHOOT_LIMIT) {
- if (overshoot < 0) {
- /* keep sane value */
- overshoot = -5;
- } else {
- /* keep sane value */
- overshoot = OVERSHOOT_LIMIT;
- }
- TRACE(ft_t_noise,
- "clipped overshoot to %d",
- overshoot);
- }
- }
- }
- } while (ft_location.segment > segment_id);
- if (ft_location.known) {
- TRACE(ft_t_noise, "current location: %d/%d",
- ft_location.segment, ft_location.sector);
- }
- TRACE_EXIT 0;
-}
-
-static int determine_position(void)
-{
- int retry = 0;
- int status;
- int result;
- TRACE_FUN(ft_t_flow);
-
- if (!ftape_tape_running) {
- /* This should only happen if tape is stopped by isr.
- */
- TRACE(ft_t_flow, "waiting for tape stop");
- if (ftape_ready_wait(ftape_timeout.pause, &status) < 0) {
- TRACE(ft_t_flow, "drive still running (fatal)");
- ftape_tape_running = 1; /* ? */
- }
- } else {
- ftape_report_drive_status(&status);
- }
- if (status & QIC_STATUS_READY) {
- /* Drive must be ready to check error state !
- */
- TRACE(ft_t_flow, "drive is ready");
- if (status & QIC_STATUS_ERROR) {
- unsigned int error;
- qic117_cmd_t command;
-
- /* Report and clear error state, try to continue.
- */
- TRACE(ft_t_flow, "error status set");
- ftape_report_error(&error, &command, 1);
- ftape_ready_wait(ftape_timeout.reset, &status);
- ftape_tape_running = 0; /* ? */
- }
- if (check_bot_eot(status)) {
- if (ft_location.bot) {
- if ((status & QIC_STATUS_READY) == 0) {
- /* tape moving away from
- * bot/eot, let's see if we
- * can catch up with the first
- * segment on this track.
- */
- } else {
- TRACE(ft_t_flow,
- "start tape from logical bot");
- logical_forward(); /* start moving */
- }
- } else {
- if ((status & QIC_STATUS_READY) == 0) {
- TRACE(ft_t_noise, "waiting for logical end of track");
- result = ftape_ready_wait(ftape_timeout.reset, &status);
- /* error handling needed ? */
- } else {
- TRACE(ft_t_noise,
- "tape at logical end of track");
- }
- }
- } else {
- TRACE(ft_t_flow, "start tape");
- logical_forward(); /* start moving */
- ft_location.known = 0; /* not cleared by logical forward ! */
- }
- }
- /* tape should be moving now, start reading id's
- */
- while (!ft_location.known &&
- retry++ < FT_SECTORS_PER_SEGMENT &&
- (result = ftape_read_id()) < 0) {
-
- TRACE(ft_t_flow, "location unknown");
-
- /* exit on signal
- */
- FT_SIGNAL_EXIT(_DONT_BLOCK);
-
- /* read-id somehow failed, tape may
- * have reached end or some other
- * error happened.
- */
- TRACE(ft_t_flow, "read-id failed");
- TRACE_CATCH(ftape_report_drive_status(&status),);
- TRACE(ft_t_err, "ftape_report_drive_status: 0x%02x", status);
- if (status & QIC_STATUS_READY) {
- ftape_tape_running = 0;
- TRACE(ft_t_noise, "tape stopped for unknown reason! "
- "status = 0x%02x", status);
- if (status & QIC_STATUS_ERROR ||
- !check_bot_eot(status)) {
- /* oops, tape stopped but not at end!
- */
- TRACE_EXIT -EIO;
- }
- }
- }
- TRACE(ft_t_flow,
- "tape is positioned at segment %d", ft_location.segment);
- TRACE_EXIT ft_location.known ? 0 : -EIO;
-}
-
-/* Get the tape running and position it just before the
- * requested segment.
- * Seek tape-track and reposition as needed.
- */
-int ftape_start_tape(int segment_id, int sector_offset)
-{
- int track = segment_id / ft_segments_per_track;
- int result = -EIO;
- int status;
- static int last_segment = -1;
- static int bad_bus_timing = 0;
- /* number of segments passing the head between starting the tape
- * and being able to access the first sector.
- */
- static int start_offset = 1;
- int retry;
- TRACE_FUN(ft_t_flow);
-
- /* If sector_offset > 0, seek into wanted segment instead of
- * into previous.
- * This allows error recovery if a part of the segment is bad
- * (erased) causing the tape drive to generate an index pulse
- * thus causing a no-data error before the requested sector
- * is reached.
- */
- ftape_tape_running = 0;
- TRACE(ft_t_noise, "target segment: %d/%d%s", segment_id, sector_offset,
- ft_buffer[ft_head]->retry > 0 ? " retry" : "");
- if (ft_buffer[ft_head]->retry > 0) { /* this is a retry */
- int dist = segment_id - last_segment;
-
- if ((int)ft_history.overrun_errors < overrun_count_offset) {
- overrun_count_offset = ft_history.overrun_errors;
- } else if (dist < 0 || dist > 50) {
- overrun_count_offset = ft_history.overrun_errors;
- } else if ((ft_history.overrun_errors -
- overrun_count_offset) >= 8) {
- if (ftape_increase_threshold() >= 0) {
- --ft_buffer[ft_head]->retry;
- overrun_count_offset =
- ft_history.overrun_errors;
- TRACE(ft_t_warn, "increased threshold because "
- "of excessive overrun errors");
- } else if (!bad_bus_timing && ft_data_rate >= 1000) {
- ftape_half_data_rate();
- --ft_buffer[ft_head]->retry;
- bad_bus_timing = 1;
- overrun_count_offset =
- ft_history.overrun_errors;
- TRACE(ft_t_warn, "reduced datarate because "
- "of excessive overrun errors");
- }
- }
- }
- last_segment = segment_id;
- if (ft_location.track != track ||
- (ftape_might_be_off_track && ft_buffer[ft_head]->retry== 0)) {
- /* current track unknown or not equal to destination
- */
- ftape_ready_wait(ftape_timeout.seek, &status);
- ftape_seek_head_to_track(track);
- /* overrun_count_offset = ft_history.overrun_errors; */
- }
- result = -EIO;
- retry = 0;
- while (result < 0 &&
- retry++ <= 5 &&
- !ft_failure &&
- !(sigtestsetmask(&current->pending.signal, _DONT_BLOCK))) {
-
- if (retry && start_offset < 5) {
- start_offset ++;
- }
- /* Check if we are able to catch the requested
- * segment in time.
- */
- if ((ft_location.known || (determine_position() == 0)) &&
- ft_location.segment >=
- (segment_id -
- ((ftape_tape_running || ft_location.bot)
- ? 0 : start_offset))) {
- /* Too far ahead (in or past target segment).
- */
- if (ftape_tape_running) {
- if ((result = ftape_stop_tape(&status)) < 0) {
- TRACE(ft_t_err,
- "stop tape failed with code %d",
- result);
- break;
- }
- TRACE(ft_t_noise, "tape stopped");
- ftape_tape_running = 0;
- }
- TRACE(ft_t_noise, "repositioning");
- ++ft_history.rewinds;
- if (segment_id % ft_segments_per_track < start_offset){
- TRACE(ft_t_noise, "end of track condition\n"
- KERN_INFO "segment_id : %d\n"
- KERN_INFO "ft_segments_per_track: %d\n"
- KERN_INFO "start_offset : %d",
- segment_id, ft_segments_per_track,
- start_offset);
-
- /* If seeking to first segments on
- * track better do a complete rewind
- * to logical begin of track to get a
- * more steady tape motion.
- */
- result = ftape_command_wait(
- (ft_location.track & 1)
- ? QIC_PHYSICAL_FORWARD
- : QIC_PHYSICAL_REVERSE,
- ftape_timeout.rewind, &status);
- check_bot_eot(status); /* update location */
- } else {
- result= skip_reverse(segment_id - start_offset,
- &status);
- }
- }
- if (!ft_location.known) {
- TRACE(ft_t_bug, "panic: location not known");
- result = -EIO;
- continue; /* while() will check for failure */
- }
- TRACE(ft_t_noise, "current segment: %d/%d",
- ft_location.segment, ft_location.sector);
- /* We're on the right track somewhere before the
- * wanted segment. Start tape movement if needed and
- * skip to just before or inside the requested
- * segment. Keep tape running.
- */
- result = 0;
- if (ft_location.segment <
- (segment_id - ((ftape_tape_running || ft_location.bot)
- ? 0 : start_offset))) {
- if (sector_offset > 0) {
- result = seek_forward(segment_id,
- retry <= 3);
- } else {
- result = seek_forward(segment_id - 1,
- retry <= 3);
- }
- }
- if (result == 0 &&
- ft_location.segment !=
- (segment_id - (sector_offset > 0 ? 0 : 1))) {
- result = -EIO;
- }
- }
- if (result < 0) {
- TRACE(ft_t_err, "failed to reposition");
- } else {
- ft_runner_status = running;
- }
- TRACE_EXIT result;
-}
diff --git a/drivers/char/ftape/lowlevel/ftape-rw.h b/drivers/char/ftape/lowlevel/ftape-rw.h
deleted file mode 100644
index 32f4feeb887c..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-rw.h
+++ /dev/null
@@ -1,111 +0,0 @@
-#ifndef _FTAPE_RW_H
-#define _FTAPE_RW_H
-
-/*
- * Copyright (C) 1993-1996 Bas Laarhoven,
- * (C) 1996-1997 Claus-Justus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-rw.h,v $
- * $Revision: 1.2 $
- * $Date: 1997/10/05 19:18:25 $
- *
- * This file contains the definitions for the read and write
- * functions for the QIC-117 floppy-tape driver for Linux.
- *
- * Claus-Justus Heine (1996/09/20): Add definition of format code 6
- * Claus-Justus Heine (1996/10/04): Changed GET/PUT macros to cast to (__u8 *)
- *
- */
-
-#include "../lowlevel/fdc-io.h"
-#include "../lowlevel/ftape-init.h"
-#include "../lowlevel/ftape-bsm.h"
-
-#include <asm/unaligned.h>
-
-#define GET2(address, offset) get_unaligned((__u16*)((__u8 *)address + offset))
-#define GET4(address, offset) get_unaligned((__u32*)((__u8 *)address + offset))
-#define GET8(address, offset) get_unaligned((__u64*)((__u8 *)address + offset))
-#define PUT2(address, offset , value) put_unaligned((value), (__u16*)((__u8 *)address + offset))
-#define PUT4(address, offset , value) put_unaligned((value), (__u32*)((__u8 *)address + offset))
-#define PUT8(address, offset , value) put_unaligned((value), (__u64*)((__u8 *)address + offset))
-
-enum runner_status_enum {
- idle = 0,
- running,
- do_abort,
- aborting,
- logical_eot,
- end_of_tape,
-};
-
-typedef enum ft_buffer_queue {
- ft_queue_head = 0,
- ft_queue_tail = 1
-} ft_buffer_queue_t;
-
-
-typedef struct {
- int track; /* tape head position */
- volatile int segment; /* current segment */
- volatile int sector; /* sector offset within current segment */
- volatile unsigned int bot; /* logical begin of track */
- volatile unsigned int eot; /* logical end of track */
- volatile unsigned int known; /* validates bot, segment, sector */
-} location_record;
-
-/* Count nr of 1's in pattern.
- */
-static inline int count_ones(unsigned long mask)
-{
- int bits;
-
- for (bits = 0; mask != 0; mask >>= 1) {
- if (mask & 1) {
- ++bits;
- }
- }
- return bits;
-}
-
-#define FT_MAX_NR_BUFFERS 16 /* arbitrary value */
-/* ftape-rw.c defined global vars.
- */
-extern buffer_struct *ft_buffer[FT_MAX_NR_BUFFERS];
-extern int ft_nr_buffers;
-extern location_record ft_location;
-extern volatile int ftape_tape_running;
-
-/* ftape-rw.c defined global functions.
- */
-extern int ftape_setup_new_segment(buffer_struct * buff,
- int segment_id,
- int offset);
-extern int ftape_calc_next_cluster(buffer_struct * buff);
-extern buffer_struct *ftape_next_buffer (ft_buffer_queue_t pos);
-extern buffer_struct *ftape_get_buffer (ft_buffer_queue_t pos);
-extern int ftape_buffer_id (ft_buffer_queue_t pos);
-extern void ftape_reset_buffer(void);
-extern void ftape_tape_parameters(__u8 drive_configuration);
-extern int ftape_wait_segment(buffer_state_enum state);
-extern int ftape_dumb_stop(void);
-extern int ftape_start_tape(int segment_id, int offset);
-extern int ftape_stop_tape(int *pstatus);
-extern int ftape_handle_logical_eot(void);
-extern buffer_state_enum ftape_set_state(buffer_state_enum new_state);
-#endif /* _FTAPE_RW_H */
diff --git a/drivers/char/ftape/lowlevel/ftape-setup.c b/drivers/char/ftape/lowlevel/ftape-setup.c
deleted file mode 100644
index 678340acd0b7..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-setup.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 1996, 1997 Claus-Justus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-setup.c,v $
- * $Revision: 1.7 $
- * $Date: 1997/10/10 09:57:06 $
- *
- * This file contains the code for processing the kernel command
- * line options for the QIC-40/80/3010/3020 floppy-tape driver
- * "ftape" for Linux.
- */
-
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/mm.h>
-
-#include <linux/ftape.h>
-#include <linux/init.h>
-#include "../lowlevel/ftape-tracing.h"
-#include "../lowlevel/fdc-io.h"
-
-static struct param_table {
- const char *name;
- int *var;
- int def_param;
- int min;
- int max;
-} config_params[] __initdata = {
-#ifndef CONFIG_FT_NO_TRACE_AT_ALL
- { "tracing", &ftape_tracing, 3, ft_t_bug, ft_t_any},
-#endif
- { "ioport", &ft_fdc_base, CONFIG_FT_FDC_BASE, 0x0, 0xfff},
- { "irq", &ft_fdc_irq, CONFIG_FT_FDC_IRQ, 2, 15},
- { "dma", &ft_fdc_dma, CONFIG_FT_FDC_DMA, 0, 3},
- { "threshold", &ft_fdc_threshold, CONFIG_FT_FDC_THR, 1, 16},
- { "datarate", &ft_fdc_rate_limit, CONFIG_FT_FDC_MAX_RATE, 500, 2000},
- { "fc10", &ft_probe_fc10, CONFIG_FT_PROBE_FC10, 0, 1},
- { "mach2", &ft_mach2, CONFIG_FT_MACH2, 0, 1}
-};
-
-static int __init ftape_setup(char *str)
-{
- int i;
- int param;
- int ints[2];
-
- TRACE_FUN(ft_t_flow);
-
- str = get_options(str, ARRAY_SIZE(ints), ints);
- if (str) {
- for (i=0; i < NR_ITEMS(config_params); i++) {
- if (strcmp(str,config_params[i].name) == 0){
- if (ints[0]) {
- param = ints[1];
- } else {
- param = config_params[i].def_param;
- }
- if (param < config_params[i].min ||
- param > config_params[i].max) {
- TRACE(ft_t_err,
- "parameter %s out of range %d ... %d",
- config_params[i].name,
- config_params[i].min,
- config_params[i].max);
- goto out;
- }
- if(config_params[i].var) {
- TRACE(ft_t_info, "%s=%d", str, param);
- *config_params[i].var = param;
- }
- goto out;
- }
- }
- }
- if (str) {
- TRACE(ft_t_err, "unknown ftape option [%s]", str);
-
- TRACE(ft_t_err, "allowed options are:");
- for (i=0; i < NR_ITEMS(config_params); i++) {
- TRACE(ft_t_err, " %s",config_params[i].name);
- }
- } else {
- TRACE(ft_t_err, "botched ftape option");
- }
- out:
- TRACE_EXIT 1;
-}
-
-__setup("ftape=", ftape_setup);
diff --git a/drivers/char/ftape/lowlevel/ftape-tracing.c b/drivers/char/ftape/lowlevel/ftape-tracing.c
deleted file mode 100644
index 7fdc6567440b..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-tracing.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 1993-1996 Bas Laarhoven,
- * (C) 1996-1997 Claus-Justus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-tracing.c,v $
- * $Revision: 1.2 $
- * $Date: 1997/10/05 19:18:27 $
- *
- * This file contains the reading code
- * for the QIC-117 floppy-tape driver for Linux.
- */
-
-#include <linux/ftape.h>
-#include "../lowlevel/ftape-tracing.h"
-
-/* Global vars.
- */
-/* tracing
- * set it to: to log :
- * 0 bugs
- * 1 + errors
- * 2 + warnings
- * 3 + information
- * 4 + more information
- * 5 + program flow
- * 6 + fdc/dma info
- * 7 + data flow
- * 8 + everything else
- */
-ft_trace_t ftape_tracing = ft_t_info; /* Default level: information and up */
-int ftape_function_nest_level;
-
-/* Local vars.
- */
-static __u8 trace_id;
-static char spacing[] = "* ";
-
-void ftape_trace_call(const char *file, const char *name)
-{
- char *indent;
-
- /* Since printk seems not to work with "%*s" format
- * we'll use this work-around.
- */
- if (ftape_function_nest_level < 0) {
- printk(KERN_INFO "function nest level (%d) < 0\n",
- ftape_function_nest_level);
- ftape_function_nest_level = 0;
- }
- if (ftape_function_nest_level < sizeof(spacing)) {
- indent = (spacing +
- sizeof(spacing) - 1 -
- ftape_function_nest_level);
- } else {
- indent = spacing;
- }
- printk(KERN_INFO "[%03d]%s+%s (%s)\n",
- (int) trace_id++, indent, file, name);
-}
-
-void ftape_trace_exit(const char *file, const char *name)
-{
- char *indent;
-
- /* Since printk seems not to work with "%*s" format
- * we'll use this work-around.
- */
- if (ftape_function_nest_level < 0) {
- printk(KERN_INFO "function nest level (%d) < 0\n", ftape_function_nest_level);
- ftape_function_nest_level = 0;
- }
- if (ftape_function_nest_level < sizeof(spacing)) {
- indent = (spacing +
- sizeof(spacing) - 1 -
- ftape_function_nest_level);
- } else {
- indent = spacing;
- }
- printk(KERN_INFO "[%03d]%s-%s (%s)\n",
- (int) trace_id++, indent, file, name);
-}
-
-void ftape_trace_log(const char *file, const char *function)
-{
- char *indent;
-
- /* Since printk seems not to work with "%*s" format
- * we'll use this work-around.
- */
- if (ftape_function_nest_level < 0) {
- printk(KERN_INFO "function nest level (%d) < 0\n", ftape_function_nest_level);
- ftape_function_nest_level = 0;
- }
- if (ftape_function_nest_level < sizeof(spacing)) {
- indent = (spacing +
- sizeof(spacing) - 1 -
- ftape_function_nest_level);
- } else {
- indent = spacing;
- }
- printk(KERN_INFO "[%03d]%s%s (%s) - ",
- (int) trace_id++, indent, file, function);
-}
diff --git a/drivers/char/ftape/lowlevel/ftape-tracing.h b/drivers/char/ftape/lowlevel/ftape-tracing.h
deleted file mode 100644
index 2950810c7085..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-tracing.h
+++ /dev/null
@@ -1,179 +0,0 @@
-#ifndef _FTAPE_TRACING_H
-#define _FTAPE_TRACING_H
-
-/*
- * Copyright (C) 1994-1996 Bas Laarhoven,
- * (C) 1996-1997 Claus-Justus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-tracing.h,v $
- * $Revision: 1.2 $
- * $Date: 1997/10/05 19:18:28 $
- *
- * This file contains definitions that eases the debugging of the
- * QIC-40/80/3010/3020 floppy-tape driver "ftape" for Linux.
- */
-
-#include <linux/kernel.h>
-
-/*
- * Be very careful with TRACE_EXIT and TRACE_ABORT.
- *
- * if (something) TRACE_EXIT error;
- *
- * will NOT work. Use
- *
- * if (something) {
- * TRACE_EXIT error;
- * }
- *
- * instead. Maybe a bit dangerous, but save lots of lines of code.
- */
-
-#define LL_X "%d/%d KB"
-#define LL(x) (unsigned int)((__u64)(x)>>10), (unsigned int)((x)&1023)
-
-typedef enum {
- ft_t_nil = -1,
- ft_t_bug,
- ft_t_err,
- ft_t_warn,
- ft_t_info,
- ft_t_noise,
- ft_t_flow,
- ft_t_fdc_dma,
- ft_t_data_flow,
- ft_t_any
-} ft_trace_t;
-
-#ifdef CONFIG_FT_NO_TRACE_AT_ALL
-/* the compiler will optimize away most TRACE() macros
- */
-#define FT_TRACE_TOP_LEVEL ft_t_bug
-#define TRACE_FUN(level) do {} while(0)
-#define TRACE_EXIT return
-#define TRACE(l, m, i...) \
-{ \
- if ((ft_trace_t)(l) == FT_TRACE_TOP_LEVEL) { \
- printk(KERN_INFO"ftape%s(%s):\n" \
- KERN_INFO m".\n" ,__FILE__, __FUNCTION__ , ##i); \
- } \
-}
-#define SET_TRACE_LEVEL(l) if ((l) == (l)) do {} while(0)
-#define TRACE_LEVEL FT_TRACE_TOP_LEVEL
-
-#else
-
-#ifdef CONFIG_FT_NO_TRACE
-/* the compiler will optimize away many TRACE() macros
- * the ftape_simple_trace_call() function simply increments
- * the function nest level.
- */
-#define FT_TRACE_TOP_LEVEL ft_t_warn
-#define TRACE_FUN(level) ftape_function_nest_level++
-#define TRACE_EXIT ftape_function_nest_level--; return
-
-#else
-#ifdef CONFIG_FT_FULL_DEBUG
-#define FT_TRACE_TOP_LEVEL ft_t_any
-#else
-#define FT_TRACE_TOP_LEVEL ft_t_flow
-#endif
-#define TRACE_FUN(level) \
- const ft_trace_t _tracing = level; \
- if (ftape_tracing >= (ft_trace_t)(level) && \
- (ft_trace_t)(level) <= FT_TRACE_TOP_LEVEL) \
- ftape_trace_call(__FILE__, __FUNCTION__); \
- ftape_function_nest_level ++;
-
-#define TRACE_EXIT \
- --ftape_function_nest_level; \
- if (ftape_tracing >= (ft_trace_t)(_tracing) && \
- (ft_trace_t)(_tracing) <= FT_TRACE_TOP_LEVEL) \
- ftape_trace_exit(__FILE__, __FUNCTION__); \
- return
-
-#endif
-
-#define TRACE(l, m, i...) \
-{ \
- if (ftape_tracing >= (ft_trace_t)(l) && \
- (ft_trace_t)(l) <= FT_TRACE_TOP_LEVEL) { \
- ftape_trace_log(__FILE__, __FUNCTION__); \
- printk(m".\n" ,##i); \
- } \
-}
-
-#define SET_TRACE_LEVEL(l) \
-{ \
- if ((ft_trace_t)(l) <= FT_TRACE_TOP_LEVEL) { \
- ftape_tracing = (ft_trace_t)(l); \
- } else { \
- ftape_tracing = FT_TRACE_TOP_LEVEL; \
- } \
-}
-#define TRACE_LEVEL \
-((ftape_tracing <= FT_TRACE_TOP_LEVEL) ? ftape_tracing : FT_TRACE_TOP_LEVEL)
-
-
-/* Global variables declared in tracing.c
- */
-extern ft_trace_t ftape_tracing; /* sets default level */
-extern int ftape_function_nest_level;
-
-/* Global functions declared in tracing.c
- */
-extern void ftape_trace_call(const char *file, const char *name);
-extern void ftape_trace_exit(const char *file, const char *name);
-extern void ftape_trace_log (const char *file, const char *name);
-
-#endif /* !defined(CONFIG_FT_NO_TRACE_AT_ALL) */
-
-/*
- * Abort with a message.
- */
-#define TRACE_ABORT(res, i...) \
-{ \
- TRACE(i); \
- TRACE_EXIT res; \
-}
-
-/* The following transforms the common "if(result < 0) ... " into a
- * one-liner.
- */
-#define _TRACE_CATCH(level, fun, action) \
-{ \
- int _res = (fun); \
- if (_res < 0) { \
- do { action /* */ ; } while(0); \
- TRACE_ABORT(_res, level, "%s failed: %d", #fun, _res); \
- } \
-}
-
-#define TRACE_CATCH(fun, fail) _TRACE_CATCH(ft_t_err, fun, fail)
-
-/* Abort the current function when signalled. This doesn't belong here,
- * but rather into ftape-rw.h (maybe)
- */
-#define FT_SIGNAL_EXIT(sig_mask) \
- if (sigtestsetmask(&current->pending.signal, sig_mask)) { \
- TRACE_ABORT(-EINTR, \
- ft_t_warn, \
- "interrupted by non-blockable signal"); \
- }
-
-#endif /* _FTAPE_TRACING_H */
diff --git a/drivers/char/ftape/lowlevel/ftape-write.c b/drivers/char/ftape/lowlevel/ftape-write.c
deleted file mode 100644
index 45601ec801ee..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-write.c
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- * Copyright (C) 1993-1995 Bas Laarhoven,
- * (C) 1996-1997 Claus-Justus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-write.c,v $
- * $Revision: 1.3.4.1 $
- * $Date: 1997/11/14 18:07:04 $
- *
- * This file contains the writing code
- * for the QIC-117 floppy-tape driver for Linux.
- */
-
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/mm.h>
-
-#include <linux/ftape.h>
-#include <linux/qic117.h>
-#include "../lowlevel/ftape-tracing.h"
-#include "../lowlevel/ftape-write.h"
-#include "../lowlevel/ftape-read.h"
-#include "../lowlevel/ftape-io.h"
-#include "../lowlevel/ftape-ctl.h"
-#include "../lowlevel/ftape-rw.h"
-#include "../lowlevel/ftape-ecc.h"
-#include "../lowlevel/ftape-bsm.h"
-#include "../lowlevel/fdc-isr.h"
-
-/* Global vars.
- */
-
-/* Local vars.
- */
-static int last_write_failed;
-
-void ftape_zap_write_buffers(void)
-{
- int i;
-
- for (i = 0; i < ft_nr_buffers; ++i) {
- ft_buffer[i]->status = done;
- }
- ftape_reset_buffer();
-}
-
-static int copy_and_gen_ecc(void *destination,
- const void *source,
- const SectorMap bad_sector_map)
-{
- int result;
- struct memory_segment mseg;
- int bads = count_ones(bad_sector_map);
- TRACE_FUN(ft_t_any);
-
- if (bads > 0) {
- TRACE(ft_t_noise, "bad sectors in map: %d", bads);
- }
- if (bads + 3 >= FT_SECTORS_PER_SEGMENT) {
- TRACE(ft_t_noise, "empty segment");
- mseg.blocks = 0; /* skip entire segment */
- result = 0; /* nothing written */
- } else {
- mseg.blocks = FT_SECTORS_PER_SEGMENT - bads;
- mseg.data = destination;
- memcpy(mseg.data, source, (mseg.blocks - 3) * FT_SECTOR_SIZE);
- result = ftape_ecc_set_segment_parity(&mseg);
- if (result < 0) {
- TRACE(ft_t_err, "ecc_set_segment_parity failed");
- } else {
- result = (mseg.blocks - 3) * FT_SECTOR_SIZE;
- }
- }
- TRACE_EXIT result;
-}
-
-
-int ftape_start_writing(const ft_write_mode_t mode)
-{
- buffer_struct *head = ftape_get_buffer(ft_queue_head);
- int segment_id = head->segment_id;
- int result;
- buffer_state_enum wanted_state = (mode == FT_WR_DELETE
- ? deleting
- : writing);
- TRACE_FUN(ft_t_flow);
-
- if ((ft_driver_state != wanted_state) || head->status != waiting) {
- TRACE_EXIT 0;
- }
- ftape_setup_new_segment(head, segment_id, 1);
- if (mode == FT_WR_SINGLE) {
- /* stop tape instead of pause */
- head->next_segment = 0;
- }
- ftape_calc_next_cluster(head); /* prepare */
- head->status = ft_driver_state; /* either writing or deleting */
- if (ft_runner_status == idle) {
- TRACE(ft_t_noise,
- "starting runner for segment %d", segment_id);
- TRACE_CATCH(ftape_start_tape(segment_id,head->sector_offset),);
- } else {
- TRACE(ft_t_noise, "runner not idle, not starting tape");
- }
- /* go */
- result = fdc_setup_read_write(head, (mode == FT_WR_DELETE
- ? FDC_WRITE_DELETED : FDC_WRITE));
- ftape_set_state(wanted_state); /* should not be necessary */
- TRACE_EXIT result;
-}
-
-/* Wait until all data is actually written to tape.
- *
- * There is a problem: when the tape runs into logical EOT, then this
- * failes. We need to restart the runner in this case.
- */
-int ftape_loop_until_writes_done(void)
-{
- buffer_struct *head;
- TRACE_FUN(ft_t_flow);
-
- while ((ft_driver_state == writing || ft_driver_state == deleting) &&
- ftape_get_buffer(ft_queue_head)->status != done) {
- /* set the runner status to idle if at lEOT */
- TRACE_CATCH(ftape_handle_logical_eot(), last_write_failed = 1);
- /* restart the tape if necessary */
- if (ft_runner_status == idle) {
- TRACE(ft_t_noise, "runner is idle, restarting");
- if (ft_driver_state == deleting) {
- TRACE_CATCH(ftape_start_writing(FT_WR_DELETE),
- last_write_failed = 1);
- } else {
- TRACE_CATCH(ftape_start_writing(FT_WR_MULTI),
- last_write_failed = 1);
- }
- }
- TRACE(ft_t_noise, "tail: %d, head: %d",
- ftape_buffer_id(ft_queue_tail),
- ftape_buffer_id(ft_queue_head));
- TRACE_CATCH(fdc_interrupt_wait(5 * FT_SECOND),
- last_write_failed = 1);
- head = ftape_get_buffer(ft_queue_head);
- if (head->status == error) {
- /* Allow escape from loop when signaled !
- */
- FT_SIGNAL_EXIT(_DONT_BLOCK);
- if (head->hard_error_map != 0) {
- /* Implement hard write error recovery here
- */
- }
- /* retry this one */
- head->status = waiting;
- if (ft_runner_status == aborting) {
- ftape_dumb_stop();
- }
- if (ft_runner_status != idle) {
- TRACE_ABORT(-EIO, ft_t_err,
- "unexpected state: "
- "ft_runner_status != idle");
- }
- ftape_start_writing(ft_driver_state == deleting
- ? FT_WR_MULTI : FT_WR_DELETE);
- }
- TRACE(ft_t_noise, "looping until writes done");
- }
- ftape_set_state(idle);
- TRACE_EXIT 0;
-}
-
-/* Write given segment from buffer at address to tape.
- */
-static int write_segment(const int segment_id,
- const void *address,
- const ft_write_mode_t write_mode)
-{
- int bytes_written = 0;
- buffer_struct *tail;
- buffer_state_enum wanted_state = (write_mode == FT_WR_DELETE
- ? deleting : writing);
- TRACE_FUN(ft_t_flow);
-
- TRACE(ft_t_noise, "segment_id = %d", segment_id);
- if (ft_driver_state != wanted_state) {
- if (ft_driver_state == deleting ||
- wanted_state == deleting) {
- TRACE_CATCH(ftape_loop_until_writes_done(),);
- }
- TRACE(ft_t_noise, "calling ftape_abort_operation");
- TRACE_CATCH(ftape_abort_operation(),);
- ftape_zap_write_buffers();
- ftape_set_state(wanted_state);
- }
- /* if all buffers full we'll have to wait...
- */
- ftape_wait_segment(wanted_state);
- tail = ftape_get_buffer(ft_queue_tail);
- switch(tail->status) {
- case done:
- ft_history.defects += count_ones(tail->hard_error_map);
- break;
- case waiting:
- /* this could happen with multiple EMPTY_SEGMENTs, but
- * shouldn't happen any more as we re-start the runner even
- * with an empty segment.
- */
- bytes_written = -EAGAIN;
- break;
- case error:
- /* setup for a retry
- */
- tail->status = waiting;
- bytes_written = -EAGAIN; /* force retry */
- if (tail->hard_error_map != 0) {
- TRACE(ft_t_warn,
- "warning: %d hard error(s) in written segment",
- count_ones(tail->hard_error_map));
- TRACE(ft_t_noise, "hard_error_map = 0x%08lx",
- (long)tail->hard_error_map);
- /* Implement hard write error recovery here
- */
- }
- break;
- default:
- TRACE_ABORT(-EIO, ft_t_err,
- "wait for empty segment failed, tail status: %d",
- tail->status);
- }
- /* should runner stop ?
- */
- if (ft_runner_status == aborting) {
- buffer_struct *head = ftape_get_buffer(ft_queue_head);
- if (head->status == wanted_state) {
- head->status = done; /* ???? */
- }
- /* don't call abort_operation(), we don't want to zap
- * the dma buffers
- */
- TRACE_CATCH(ftape_dumb_stop(),);
- } else {
- /* If just passed last segment on tape: wait for BOT
- * or EOT mark. Sets ft_runner_status to idle if at lEOT
- * and successful
- */
- TRACE_CATCH(ftape_handle_logical_eot(),);
- }
- if (tail->status == done) {
- /* now at least one buffer is empty, fill it with our
- * data. skip bad sectors and generate ecc.
- * copy_and_gen_ecc return nr of bytes written, range
- * 0..29 Kb inclusive!
- *
- * Empty segments are handled inside coyp_and_gen_ecc()
- */
- if (write_mode != FT_WR_DELETE) {
- TRACE_CATCH(bytes_written = copy_and_gen_ecc(
- tail->address, address,
- ftape_get_bad_sector_entry(segment_id)),);
- }
- tail->segment_id = segment_id;
- tail->status = waiting;
- tail = ftape_next_buffer(ft_queue_tail);
- }
- /* Start tape only if all buffers full or flush mode.
- * This will give higher probability of streaming.
- */
- if (ft_runner_status != running &&
- ((tail->status == waiting &&
- ftape_get_buffer(ft_queue_head) == tail) ||
- write_mode != FT_WR_ASYNC)) {
- TRACE_CATCH(ftape_start_writing(write_mode),);
- }
- TRACE_EXIT bytes_written;
-}
-
-/* Write as much as fits from buffer to the given segment on tape
- * and handle retries.
- * Return the number of bytes written (>= 0), or:
- * -EIO write failed
- * -EINTR interrupted by signal
- * -ENOSPC device full
- */
-int ftape_write_segment(const int segment_id,
- const void *buffer,
- const ft_write_mode_t flush)
-{
- int retry = 0;
- int result;
- TRACE_FUN(ft_t_flow);
-
- ft_history.used |= 2;
- if (segment_id >= ft_tracks_per_tape*ft_segments_per_track) {
- /* tape full */
- TRACE_ABORT(-ENOSPC, ft_t_err,
- "invalid segment id: %d (max %d)",
- segment_id,
- ft_tracks_per_tape * ft_segments_per_track -1);
- }
- for (;;) {
- if ((result = write_segment(segment_id, buffer, flush)) >= 0) {
- if (result == 0) { /* empty segment */
- TRACE(ft_t_noise,
- "empty segment, nothing written");
- }
- TRACE_EXIT result;
- }
- if (result == -EAGAIN) {
- if (++retry > 100) { /* give up */
- TRACE_ABORT(-EIO, ft_t_err,
- "write failed, >100 retries in segment");
- }
- TRACE(ft_t_warn, "write error, retry %d (%d)",
- retry,
- ftape_get_buffer(ft_queue_tail)->segment_id);
- } else {
- TRACE_ABORT(result, ft_t_err,
- "write_segment failed, error: %d", result);
- }
- /* Allow escape from loop when signaled !
- */
- FT_SIGNAL_EXIT(_DONT_BLOCK);
- }
-}
diff --git a/drivers/char/ftape/lowlevel/ftape-write.h b/drivers/char/ftape/lowlevel/ftape-write.h
deleted file mode 100644
index 0e7f898b7af9..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-write.h
+++ /dev/null
@@ -1,53 +0,0 @@
-#ifndef _FTAPE_WRITE_H
-#define _FTAPE_WRITE_H
-
-/*
- * Copyright (C) 1994-1995 Bas Laarhoven,
- * (C) 1996-1997 Claus-Justus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-write.h,v $
- $Author: claus $
- *
- $Revision: 1.2 $
- $Date: 1997/10/05 19:18:30 $
- $State: Exp $
- *
- * This file contains the definitions for the write functions
- * for the QIC-117 floppy-tape driver for Linux.
- *
- */
-
-
-/* ftape-write.c defined global functions.
- */
-typedef enum {
- FT_WR_ASYNC = 0, /* start tape only when all buffers are full */
- FT_WR_MULTI = 1, /* start tape, but don't necessarily stop */
- FT_WR_SINGLE = 2, /* write a single segment and stop afterwards */
- FT_WR_DELETE = 3 /* write deleted data marks */
-} ft_write_mode_t;
-
-extern int ftape_start_writing(const ft_write_mode_t mode);
-extern int ftape_write_segment(const int segment,
- const void *address,
- const ft_write_mode_t flushing);
-extern void ftape_zap_write_buffers(void);
-extern int ftape_loop_until_writes_done(void);
-
-#endif /* _FTAPE_WRITE_H */
-
diff --git a/drivers/char/ftape/lowlevel/ftape_syms.c b/drivers/char/ftape/lowlevel/ftape_syms.c
deleted file mode 100644
index 8e0dc4a07ca6..000000000000
--- a/drivers/char/ftape/lowlevel/ftape_syms.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 1996-1997 Claus-Justus Heine
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape_syms.c,v $
- * $Revision: 1.4 $
- * $Date: 1997/10/17 00:03:51 $
- *
- * This file contains the symbols that the ftape low level
- * part of the QIC-40/80/3010/3020 floppy-tape driver "ftape"
- * exports to its high level clients
- */
-
-#include <linux/module.h>
-
-#include <linux/ftape.h>
-#include "../lowlevel/ftape-tracing.h"
-#include "../lowlevel/ftape-init.h"
-#include "../lowlevel/fdc-io.h"
-#include "../lowlevel/ftape-read.h"
-#include "../lowlevel/ftape-write.h"
-#include "../lowlevel/ftape-io.h"
-#include "../lowlevel/ftape-ctl.h"
-#include "../lowlevel/ftape-rw.h"
-#include "../lowlevel/ftape-bsm.h"
-#include "../lowlevel/ftape-buffer.h"
-#include "../lowlevel/ftape-format.h"
-
-/* bad sector handling from ftape-bsm.c */
-EXPORT_SYMBOL(ftape_get_bad_sector_entry);
-EXPORT_SYMBOL(ftape_find_end_of_bsm_list);
-/* from ftape-rw.c */
-EXPORT_SYMBOL(ftape_set_state);
-/* from ftape-ctl.c */
-EXPORT_SYMBOL(ftape_seek_to_bot);
-EXPORT_SYMBOL(ftape_seek_to_eot);
-EXPORT_SYMBOL(ftape_abort_operation);
-EXPORT_SYMBOL(ftape_get_status);
-EXPORT_SYMBOL(ftape_enable);
-EXPORT_SYMBOL(ftape_disable);
-EXPORT_SYMBOL(ftape_mmap);
-EXPORT_SYMBOL(ftape_calibrate_data_rate);
-/* from ftape-io.c */
-EXPORT_SYMBOL(ftape_reset_drive);
-EXPORT_SYMBOL(ftape_command);
-EXPORT_SYMBOL(ftape_parameter);
-EXPORT_SYMBOL(ftape_ready_wait);
-EXPORT_SYMBOL(ftape_report_operation);
-EXPORT_SYMBOL(ftape_report_error);
-/* from ftape-read.c */
-EXPORT_SYMBOL(ftape_read_segment_fraction);
-EXPORT_SYMBOL(ftape_zap_read_buffers);
-EXPORT_SYMBOL(ftape_read_header_segment);
-EXPORT_SYMBOL(ftape_decode_header_segment);
-/* from ftape-write.c */
-EXPORT_SYMBOL(ftape_write_segment);
-EXPORT_SYMBOL(ftape_start_writing);
-EXPORT_SYMBOL(ftape_loop_until_writes_done);
-/* from ftape-buffer.h */
-EXPORT_SYMBOL(ftape_set_nr_buffers);
-/* from ftape-format.h */
-EXPORT_SYMBOL(ftape_format_track);
-EXPORT_SYMBOL(ftape_format_status);
-EXPORT_SYMBOL(ftape_verify_segment);
-/* from tracing.c */
-#ifndef CONFIG_FT_NO_TRACE_AT_ALL
-EXPORT_SYMBOL(ftape_tracing);
-EXPORT_SYMBOL(ftape_function_nest_level);
-EXPORT_SYMBOL(ftape_trace_call);
-EXPORT_SYMBOL(ftape_trace_exit);
-EXPORT_SYMBOL(ftape_trace_log);
-#endif
-
diff --git a/drivers/char/ftape/zftape/Makefile b/drivers/char/ftape/zftape/Makefile
deleted file mode 100644
index 6d91c1f77c05..000000000000
--- a/drivers/char/ftape/zftape/Makefile
+++ /dev/null
@@ -1,36 +0,0 @@
-#
-# Copyright (C) 1996, 1997 Claus-Justus Heine.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; see the file COPYING. If not, write to
-# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-# $Source: /homes/cvs/ftape-stacked/ftape/zftape/Makefile,v $
-# $Revision: 1.4 $
-# $Date: 1997/10/05 19:18:58 $
-#
-# Makefile for the QIC-40/80/3010/3020 zftape interface VFS to
-# ftape
-#
-
-
-# ZFT_OBSOLETE - enable the MTIOC_ZFTAPE_GETBLKSZ ioctl. You should
-# leave this enabled for compatibility with taper.
-
-obj-$(CONFIG_ZFTAPE) += zftape.o
-
-zftape-objs := zftape-rw.o zftape-ctl.o zftape-read.o \
- zftape-write.o zftape-vtbl.o zftape-eof.o \
- zftape-init.o zftape-buffers.o zftape_syms.o
-
-EXTRA_CFLAGS := -DZFT_OBSOLETE
diff --git a/drivers/char/ftape/zftape/zftape-buffers.c b/drivers/char/ftape/zftape/zftape-buffers.c
deleted file mode 100644
index 7ebce2ec7897..000000000000
--- a/drivers/char/ftape/zftape/zftape-buffers.c
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright (C) 1995-1997 Claus-Justus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-buffers.c,v $
- * $Revision: 1.2 $
- * $Date: 1997/10/05 19:18:59 $
- *
- * This file contains the dynamic buffer allocation routines
- * of zftape
- */
-
-#include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-
-#include <linux/zftape.h>
-
-#include <linux/vmalloc.h>
-
-#include "../zftape/zftape-init.h"
-#include "../zftape/zftape-eof.h"
-#include "../zftape/zftape-ctl.h"
-#include "../zftape/zftape-write.h"
-#include "../zftape/zftape-read.h"
-#include "../zftape/zftape-rw.h"
-#include "../zftape/zftape-vtbl.h"
-
-/* global variables
- */
-
-/* local varibales
- */
-static unsigned int used_memory;
-static unsigned int peak_memory;
-
-void zft_memory_stats(void)
-{
- TRACE_FUN(ft_t_flow);
-
- TRACE(ft_t_noise, "Memory usage (vmalloc allocations):\n"
- KERN_INFO "total allocated: %d\n"
- KERN_INFO "peak allocation: %d",
- used_memory, peak_memory);
- peak_memory = used_memory;
- TRACE_EXIT;
-}
-
-int zft_vcalloc_once(void *new, size_t size)
-{
- TRACE_FUN(ft_t_flow);
- if (zft_vmalloc_once(new, size) < 0) {
- TRACE_EXIT -ENOMEM;
- }
- memset(*(void **)new, '\0', size);
- TRACE_EXIT 0;
-}
-int zft_vmalloc_once(void *new, size_t size)
-{
- TRACE_FUN(ft_t_flow);
-
- if (*(void **)new != NULL || size == 0) {
- TRACE_EXIT 0;
- }
- if ((*(void **)new = vmalloc(size)) == NULL) {
- TRACE_EXIT -ENOMEM;
- }
- used_memory += size;
- if (peak_memory < used_memory) {
- peak_memory = used_memory;
- }
- TRACE_ABORT(0, ft_t_noise,
- "allocated buffer @ %p, %zd bytes", *(void **)new, size);
-}
-int zft_vmalloc_always(void *new, size_t size)
-{
- TRACE_FUN(ft_t_flow);
-
- zft_vfree(new, size);
- TRACE_EXIT zft_vmalloc_once(new, size);
-}
-void zft_vfree(void *old, size_t size)
-{
- TRACE_FUN(ft_t_flow);
-
- if (*(void **)old) {
- vfree(*(void **)old);
- used_memory -= size;
- TRACE(ft_t_noise, "released buffer @ %p, %zd bytes",
- *(void **)old, size);
- *(void **)old = NULL;
- }
- TRACE_EXIT;
-}
-
-void *zft_kmalloc(size_t size)
-{
- void *new;
-
- while ((new = kmalloc(size, GFP_KERNEL)) == NULL) {
- msleep_interruptible(100);
- }
- memset(new, 0, size);
- used_memory += size;
- if (peak_memory < used_memory) {
- peak_memory = used_memory;
- }
- return new;
-}
-
-void zft_kfree(void *old, size_t size)
-{
- kfree(old);
- used_memory -= size;
-}
-
-/* there are some more buffers that are allocated on demand.
- * cleanup_module() calles this function to be sure to have released
- * them
- */
-void zft_uninit_mem(void)
-{
- TRACE_FUN(ft_t_flow);
-
- zft_vfree(&zft_hseg_buf, FT_SEGMENT_SIZE);
- zft_vfree(&zft_deblock_buf, FT_SEGMENT_SIZE); zft_deblock_segment = -1;
- zft_free_vtbl();
- if (zft_cmpr_lock(0 /* don't load */) == 0) {
- (*zft_cmpr_ops->cleanup)();
- (*zft_cmpr_ops->reset)(); /* unlock it again */
- }
- zft_memory_stats();
- TRACE_EXIT;
-}
diff --git a/drivers/char/ftape/zftape/zftape-buffers.h b/drivers/char/ftape/zftape/zftape-buffers.h
deleted file mode 100644
index 798e3128c682..000000000000
--- a/drivers/char/ftape/zftape/zftape-buffers.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#ifndef _FTAPE_DYNMEM_H
-#define _FTAPE_DYNMEM_H
-
-/*
- * Copyright (C) 1995-1997 Claus-Justus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-buffers.h,v $
- * $Revision: 1.2 $
- * $Date: 1997/10/05 19:18:59 $
- *
- * memory allocation routines.
- *
- */
-
-/* we do not allocate all of the really large buffer memory before
- * someone tries to open the drive. ftape_open() may fail with
- * -ENOMEM, but that's better having 200k of vmalloced memory which
- * cannot be swapped out.
- */
-
-extern void zft_memory_stats(void);
-extern int zft_vmalloc_once(void *new, size_t size);
-extern int zft_vcalloc_once(void *new, size_t size);
-extern int zft_vmalloc_always(void *new, size_t size);
-extern void zft_vfree(void *old, size_t size);
-extern void *zft_kmalloc(size_t size);
-extern void zft_kfree(void *old, size_t size);
-
-/* called by cleanup_module()
- */
-extern void zft_uninit_mem(void);
-
-#endif
-
-
-
-
-
-
-
diff --git a/drivers/char/ftape/zftape/zftape-ctl.c b/drivers/char/ftape/zftape/zftape-ctl.c
deleted file mode 100644
index 22ba0f5d00cf..000000000000
--- a/drivers/char/ftape/zftape/zftape-ctl.c
+++ /dev/null
@@ -1,1417 +0,0 @@
-/*
- * Copyright (C) 1996, 1997 Claus-Justus Heine
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-ctl.c,v $
- * $Revision: 1.2.6.2 $
- * $Date: 1997/11/14 18:07:33 $
- *
- * This file contains the non-read/write zftape functions
- * for the QIC-40/80/3010/3020 floppy-tape driver for Linux.
- */
-
-#include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/fcntl.h>
-
-#include <linux/zftape.h>
-
-#include <asm/uaccess.h>
-
-#include "../zftape/zftape-init.h"
-#include "../zftape/zftape-eof.h"
-#include "../zftape/zftape-ctl.h"
-#include "../zftape/zftape-write.h"
-#include "../zftape/zftape-read.h"
-#include "../zftape/zftape-rw.h"
-#include "../zftape/zftape-vtbl.h"
-
-/* Global vars.
- */
-int zft_write_protected; /* this is when cartridge rdonly or O_RDONLY */
-int zft_header_read;
-int zft_offline;
-unsigned int zft_unit;
-int zft_resid;
-int zft_mt_compression;
-
-/* Local vars.
- */
-static int going_offline;
-
-typedef int (mt_fun)(int *argptr);
-typedef int (*mt_funp)(int *argptr);
-typedef struct
-{
- mt_funp function;
- unsigned offline : 1; /* op permitted if offline or no_tape */
- unsigned write_protected : 1; /* op permitted if write-protected */
- unsigned not_formatted : 1; /* op permitted if tape not formatted */
- unsigned raw_mode : 1; /* op permitted if zft_mode == 0 */
- unsigned need_idle_state : 1; /* need to call def_idle_state */
- char *name;
-} fun_entry;
-
-static mt_fun mt_dummy, mt_reset, mt_fsr, mt_bsr, mt_rew, mt_offl, mt_nop,
- mt_weof, mt_erase, mt_ras2, mt_setblk, mt_setdensity,
- mt_seek, mt_tell, mt_reten, mt_eom, mt_fsf, mt_bsf,
- mt_fsfm, mt_bsfm, mt_setdrvbuffer, mt_compression;
-
-static fun_entry mt_funs[]=
-{
- {mt_reset , 1, 1, 1, 1, 0, "MT_RESET" }, /* 0 */
- {mt_fsf , 0, 1, 0, 0, 1, "MT_FSF" },
- {mt_bsf , 0, 1, 0, 0, 1, "MT_BSF" },
- {mt_fsr , 0, 1, 0, 1, 1, "MT_FSR" },
- {mt_bsr , 0, 1, 0, 1, 1, "MT_BSR" },
- {mt_weof , 0, 0, 0, 0, 0, "MT_WEOF" }, /* 5 */
- {mt_rew , 0, 1, 1, 1, 0, "MT_REW" },
- {mt_offl , 0, 1, 1, 1, 0, "MT_OFFL" },
- {mt_nop , 1, 1, 1, 1, 0, "MT_NOP" },
- {mt_reten , 0, 1, 1, 1, 0, "MT_RETEN" },
- {mt_bsfm , 0, 1, 0, 0, 1, "MT_BSFM" }, /* 10 */
- {mt_fsfm , 0, 1, 0, 0, 1, "MT_FSFM" },
- {mt_eom , 0, 1, 0, 0, 1, "MT_EOM" },
- {mt_erase , 0, 0, 0, 1, 0, "MT_ERASE" },
- {mt_dummy , 1, 1, 1, 1, 0, "MT_RAS1" },
- {mt_ras2 , 0, 0, 0, 1, 0, "MT_RAS2" },
- {mt_dummy , 1, 1, 1, 1, 0, "MT_RAS3" },
- {mt_dummy , 1, 1, 1, 1, 0, "UNKNOWN" },
- {mt_dummy , 1, 1, 1, 1, 0, "UNKNOWN" },
- {mt_dummy , 1, 1, 1, 1, 0, "UNKNOWN" },
- {mt_setblk , 1, 1, 1, 1, 1, "MT_SETBLK"}, /* 20 */
- {mt_setdensity , 1, 1, 1, 1, 0, "MT_SETDENSITY"},
- {mt_seek , 0, 1, 0, 1, 1, "MT_SEEK" },
- {mt_dummy , 0, 1, 0, 1, 1, "MT_TELL" }, /* wr-only ?! */
- {mt_setdrvbuffer, 1, 1, 1, 1, 0, "MT_SETDRVBUFFER" },
- {mt_dummy , 1, 1, 1, 1, 0, "MT_FSS" }, /* 25 */
- {mt_dummy , 1, 1, 1, 1, 0, "MT_BSS" },
- {mt_dummy , 1, 1, 1, 1, 0, "MT_WSM" },
- {mt_dummy , 1, 1, 1, 1, 0, "MT_LOCK" },
- {mt_dummy , 1, 1, 1, 1, 0, "MT_UNLOCK"},
- {mt_dummy , 1, 1, 1, 1, 0, "MT_LOAD" }, /* 30 */
- {mt_dummy , 1, 1, 1, 1, 0, "MT_UNLOAD"},
- {mt_compression , 1, 1, 1, 0, 1, "MT_COMPRESSION"},
- {mt_dummy , 1, 1, 1, 1, 0, "MT_SETPART"},
- {mt_dummy , 1, 1, 1, 1, 0, "MT_MKPART"}
-};
-
-#define NR_MT_CMDS NR_ITEMS(mt_funs)
-
-void zft_reset_position(zft_position *pos)
-{
- TRACE_FUN(ft_t_flow);
-
- pos->seg_byte_pos =
- pos->volume_pos = 0;
- if (zft_header_read) {
- /* need to keep track of the volume table and
- * compression map. We therefor simply
- * position at the beginning of the first
- * volume. This covers old ftape archives as
- * well has various flavours of the
- * compression map segments. The worst case is
- * that the compression map shows up as a
- * additional volume in front of all others.
- */
- pos->seg_pos = zft_find_volume(0)->start_seg;
- pos->tape_pos = zft_calc_tape_pos(pos->seg_pos);
- } else {
- pos->tape_pos = 0;
- pos->seg_pos = -1;
- }
- zft_just_before_eof = 0;
- zft_deblock_segment = -1;
- zft_io_state = zft_idle;
- zft_zap_read_buffers();
- zft_prevent_flush();
- /* unlock the compresison module if it is loaded.
- * The zero arg means not to try to load the module.
- */
- if (zft_cmpr_lock(0) == 0) {
- (*zft_cmpr_ops->reset)(); /* unlock */
- }
- TRACE_EXIT;
-}
-
-static void zft_init_driver(void)
-{
- TRACE_FUN(ft_t_flow);
-
- zft_resid =
- zft_header_read =
- zft_old_ftape =
- zft_offline =
- zft_write_protected =
- going_offline =
- zft_mt_compression =
- zft_header_changed =
- zft_volume_table_changed =
- zft_written_segments = 0;
- zft_blk_sz = CONFIG_ZFT_DFLT_BLK_SZ;
- zft_reset_position(&zft_pos); /* does most of the stuff */
- ftape_zap_read_buffers();
- ftape_set_state(idle);
- TRACE_EXIT;
-}
-
-int zft_def_idle_state(void)
-{
- int result = 0;
- TRACE_FUN(ft_t_flow);
-
- if (!zft_header_read) {
- result = zft_read_header_segments();
- } else if ((result = zft_flush_buffers()) >= 0 && zft_qic_mode) {
- /* don't move past eof
- */
- (void)zft_close_volume(&zft_pos);
- }
- if (ftape_abort_operation() < 0) {
- TRACE(ft_t_warn, "ftape_abort_operation() failed");
- result = -EIO;
- }
- /* clear remaining read buffers */
- zft_zap_read_buffers();
- zft_io_state = zft_idle;
- TRACE_EXIT result;
-}
-
-/*****************************************************************************
- * *
- * functions for the MTIOCTOP commands *
- * *
- *****************************************************************************/
-
-static int mt_dummy(int *dummy)
-{
- TRACE_FUN(ft_t_flow);
-
- TRACE_EXIT -ENOSYS;
-}
-
-static int mt_reset(int *dummy)
-{
- TRACE_FUN(ft_t_flow);
-
- (void)ftape_seek_to_bot();
- TRACE_CATCH(ftape_reset_drive(),
- zft_init_driver(); zft_uninit_mem(); zft_offline = 1);
- /* fake a re-open of the device. This will set all flage and
- * allocate buffers as appropriate. The new tape condition will
- * force the open routine to do anything we need.
- */
- TRACE_CATCH(_zft_open(-1 /* fake reopen */, 0 /* dummy */),);
- TRACE_EXIT 0;
-}
-
-static int mt_fsf(int *arg)
-{
- int result;
- TRACE_FUN(ft_t_flow);
-
- result = zft_skip_volumes(*arg, &zft_pos);
- zft_just_before_eof = 0;
- TRACE_EXIT result;
-}
-
-static int mt_bsf(int *arg)
-{
- int result = 0;
- TRACE_FUN(ft_t_flow);
-
- if (*arg != 0) {
- result = zft_skip_volumes(-*arg + 1, &zft_pos);
- }
- TRACE_EXIT result;
-}
-
-static int seek_block(__s64 data_offset,
- __s64 block_increment,
- zft_position *pos)
-{
- int result = 0;
- __s64 new_block_pos;
- __s64 vol_block_count;
- const zft_volinfo *volume;
- int exceed;
- TRACE_FUN(ft_t_flow);
-
- volume = zft_find_volume(pos->seg_pos);
- if (volume->start_seg == 0 || volume->end_seg == 0) {
- TRACE_EXIT -EIO;
- }
- new_block_pos = (zft_div_blksz(data_offset, volume->blk_sz)
- + block_increment);
- vol_block_count = zft_div_blksz(volume->size, volume->blk_sz);
- if (new_block_pos < 0) {
- TRACE(ft_t_noise,
- "new_block_pos " LL_X " < 0", LL(new_block_pos));
- zft_resid = (int)new_block_pos;
- new_block_pos = 0;
- exceed = 1;
- } else if (new_block_pos > vol_block_count) {
- TRACE(ft_t_noise,
- "new_block_pos " LL_X " exceeds size of volume " LL_X,
- LL(new_block_pos), LL(vol_block_count));
- zft_resid = (int)(vol_block_count - new_block_pos);
- new_block_pos = vol_block_count;
- exceed = 1;
- } else {
- exceed = 0;
- }
- if (zft_use_compression && volume->use_compression) {
- TRACE_CATCH(zft_cmpr_lock(1 /* try to load */),);
- result = (*zft_cmpr_ops->seek)(new_block_pos, pos, volume,
- zft_deblock_buf);
- pos->tape_pos = zft_calc_tape_pos(pos->seg_pos);
- pos->tape_pos += pos->seg_byte_pos;
- } else {
- pos->volume_pos = zft_mul_blksz(new_block_pos, volume->blk_sz);
- pos->tape_pos = zft_calc_tape_pos(volume->start_seg);
- pos->tape_pos += pos->volume_pos;
- pos->seg_pos = zft_calc_seg_byte_coord(&pos->seg_byte_pos,
- pos->tape_pos);
- }
- zft_just_before_eof = volume->size == pos->volume_pos;
- if (zft_just_before_eof) {
- /* why this? because zft_file_no checks agains start
- * and end segment of a volume. We do not want to
- * advance to the next volume with this function.
- */
- TRACE(ft_t_noise, "set zft_just_before_eof");
- zft_position_before_eof(pos, volume);
- }
- TRACE(ft_t_noise, "\n"
- KERN_INFO "new_seg_pos : %d\n"
- KERN_INFO "new_tape_pos: " LL_X "\n"
- KERN_INFO "vol_size : " LL_X "\n"
- KERN_INFO "seg_byte_pos: %d\n"
- KERN_INFO "blk_sz : %d",
- pos->seg_pos, LL(pos->tape_pos),
- LL(volume->size), pos->seg_byte_pos,
- volume->blk_sz);
- if (!exceed) {
- zft_resid = new_block_pos - zft_div_blksz(pos->volume_pos,
- volume->blk_sz);
- }
- if (zft_resid < 0) {
- zft_resid = -zft_resid;
- }
- TRACE_EXIT ((exceed || zft_resid != 0) && result >= 0) ? -EINVAL : result;
-}
-
-static int mt_fsr(int *arg)
-{
- int result;
- TRACE_FUN(ft_t_flow);
-
- result = seek_block(zft_pos.volume_pos, *arg, &zft_pos);
- TRACE_EXIT result;
-}
-
-static int mt_bsr(int *arg)
-{
- int result;
- TRACE_FUN(ft_t_flow);
-
- result = seek_block(zft_pos.volume_pos, -*arg, &zft_pos);
- TRACE_EXIT result;
-}
-
-static int mt_weof(int *arg)
-{
- int result;
- TRACE_FUN(ft_t_flow);
-
- TRACE_CATCH(zft_flush_buffers(),);
- result = zft_weof(*arg, &zft_pos);
- TRACE_EXIT result;
-}
-
-static int mt_rew(int *dummy)
-{
- int result;
- TRACE_FUN(ft_t_flow);
-
- if(zft_header_read) {
- (void)zft_def_idle_state();
- }
- result = ftape_seek_to_bot();
- zft_reset_position(&zft_pos);
- TRACE_EXIT result;
-}
-
-static int mt_offl(int *dummy)
-{
- int result;
- TRACE_FUN(ft_t_flow);
-
- going_offline= 1;
- result = mt_rew(NULL);
- TRACE_EXIT result;
-}
-
-static int mt_nop(int *dummy)
-{
- TRACE_FUN(ft_t_flow);
- /* should we set tape status?
- */
- if (!zft_offline) { /* offline includes no_tape */
- (void)zft_def_idle_state();
- }
- TRACE_EXIT 0;
-}
-
-static int mt_reten(int *dummy)
-{
- int result;
- TRACE_FUN(ft_t_flow);
-
- if(zft_header_read) {
- (void)zft_def_idle_state();
- }
- result = ftape_seek_to_eot();
- if (result >= 0) {
- result = ftape_seek_to_bot();
- }
- TRACE_EXIT(result);
-}
-
-static int fsfbsfm(int arg, zft_position *pos)
-{
- const zft_volinfo *vtbl;
- __s64 block_pos;
- TRACE_FUN(ft_t_flow);
-
- /* What to do? This should seek to the next file-mark and
- * position BEFORE. That is, a next write would just extend
- * the current file. Well. Let's just seek to the end of the
- * current file, if count == 1. If count > 1, then do a
- * "mt_fsf(count - 1)", and then seek to the end of that file.
- * If count == 0, do nothing
- */
- if (arg == 0) {
- TRACE_EXIT 0;
- }
- zft_just_before_eof = 0;
- TRACE_CATCH(zft_skip_volumes(arg < 0 ? arg : arg-1, pos),
- if (arg > 0) {
- zft_resid ++;
- });
- vtbl = zft_find_volume(pos->seg_pos);
- block_pos = zft_div_blksz(vtbl->size, vtbl->blk_sz);
- (void)seek_block(0, block_pos, pos);
- if (pos->volume_pos != vtbl->size) {
- zft_just_before_eof = 0;
- zft_resid = 1;
- /* we didn't managed to go there */
- TRACE_ABORT(-EIO, ft_t_err,
- "wanted file position " LL_X ", arrived at " LL_X,
- LL(vtbl->size), LL(pos->volume_pos));
- }
- zft_just_before_eof = 1;
- TRACE_EXIT 0;
-}
-
-static int mt_bsfm(int *arg)
-{
- int result;
- TRACE_FUN(ft_t_flow);
-
- result = fsfbsfm(-*arg, &zft_pos);
- TRACE_EXIT result;
-}
-
-static int mt_fsfm(int *arg)
-{
- int result;
- TRACE_FUN(ft_t_flow);
-
- result = fsfbsfm(*arg, &zft_pos);
- TRACE_EXIT result;
-}
-
-static int mt_eom(int *dummy)
-{
- TRACE_FUN(ft_t_flow);
-
- zft_skip_to_eom(&zft_pos);
- TRACE_EXIT 0;
-}
-
-static int mt_erase(int *dummy)
-{
- int result;
- TRACE_FUN(ft_t_flow);
-
- result = zft_erase();
- TRACE_EXIT result;
-}
-
-static int mt_ras2(int *dummy)
-{
- int result;
- TRACE_FUN(ft_t_flow);
-
- result = -ENOSYS;
- TRACE_EXIT result;
-}
-
-/* Sets the new blocksize in BYTES
- *
- */
-static int mt_setblk(int *new_size)
-{
- TRACE_FUN(ft_t_flow);
-
- if((unsigned int)(*new_size) > ZFT_MAX_BLK_SZ) {
- TRACE_ABORT(-EINVAL, ft_t_info,
- "desired blk_sz (%d) should be <= %d bytes",
- *new_size, ZFT_MAX_BLK_SZ);
- }
- if ((*new_size & (FT_SECTOR_SIZE-1)) != 0) {
- TRACE_ABORT(-EINVAL, ft_t_info,
- "desired blk_sz (%d) must be a multiple of %d bytes",
- *new_size, FT_SECTOR_SIZE);
- }
- if (*new_size == 0) {
- if (zft_use_compression) {
- TRACE_ABORT(-EINVAL, ft_t_info,
- "Variable block size not yet "
- "supported with compression");
- }
- *new_size = 1;
- }
- zft_blk_sz = *new_size;
- TRACE_EXIT 0;
-}
-
-static int mt_setdensity(int *arg)
-{
- TRACE_FUN(ft_t_flow);
-
- SET_TRACE_LEVEL(*arg);
- TRACE(TRACE_LEVEL, "tracing set to %d", TRACE_LEVEL);
- if ((int)TRACE_LEVEL != *arg) {
- TRACE_EXIT -EINVAL;
- }
- TRACE_EXIT 0;
-}
-
-static int mt_seek(int *new_block_pos)
-{
- int result= 0;
- TRACE_FUN(ft_t_any);
-
- result = seek_block(0, (__s64)*new_block_pos, &zft_pos);
- TRACE_EXIT result;
-}
-
-/* OK, this is totally different from SCSI, but the worst thing that can
- * happen is that there is not enough defragmentated memory that can be
- * allocated. Also, there is a hardwired limit of 16 dma buffers in the
- * stock ftape module. This shouldn't bring the system down.
- *
- * NOTE: the argument specifies the total number of dma buffers to use.
- * The driver needs at least 3 buffers to function at all.
- *
- */
-static int mt_setdrvbuffer(int *cnt)
-{
- TRACE_FUN(ft_t_flow);
-
- if (*cnt < 3) {
- TRACE_EXIT -EINVAL;
- }
- TRACE_CATCH(ftape_set_nr_buffers(*cnt),);
- TRACE_EXIT 0;
-}
-/* return the block position from start of volume
- */
-static int mt_tell(int *arg)
-{
- TRACE_FUN(ft_t_flow);
-
- *arg = zft_div_blksz(zft_pos.volume_pos,
- zft_find_volume(zft_pos.seg_pos)->blk_sz);
- TRACE_EXIT 0;
-}
-
-static int mt_compression(int *arg)
-{
- TRACE_FUN(ft_t_flow);
-
- /* Ok. We could also check whether compression is available at
- * all by trying to load the compression module. We could
- * also check for a block size of 1 byte which is illegal
- * with compression. Instead of doing it here we rely on
- * zftape_write() to do the proper checks.
- */
- if ((unsigned int)*arg > 1) {
- TRACE_EXIT -EINVAL;
- }
- if (*arg != 0 && zft_blk_sz == 1) { /* variable block size */
- TRACE_ABORT(-EINVAL, ft_t_info,
- "Compression not yet supported "
- "with variable block size");
- }
- zft_mt_compression = *arg;
- if ((zft_unit & ZFT_ZIP_MODE) == 0) {
- zft_use_compression = zft_mt_compression;
- }
- TRACE_EXIT 0;
-}
-
-/* check whether write access is allowed. Write access is denied when
- * + zft_write_protected == 1 -- this accounts for either hard write
- * protection of the cartridge or for
- * O_RDONLY access mode of the tape device
- * + zft_offline == 1 -- this meany that there is either no tape
- * or that the MTOFFLINE ioctl has been
- * previously issued (`soft eject')
- * + ft_formatted == 0 -- this means that the cartridge is not
- * formatted
- * Then we distinuguish two cases. When zft_qic_mode is TRUE, then we try
- * to emulate a `traditional' (aka SCSI like) UN*X tape device. Therefore we
- * deny writes when
- * + zft_qic_mode ==1 &&
- * (!zft_tape_at_lbot() && -- tape no at logical BOT
- * !(zft_tape_at_eom() || -- tape not at logical EOM (or EOD)
- * (zft_tape_at_eom() &&
- * zft_old_ftape()))) -- we can't add new volume to tapes
- * written by old ftape because ftape
- * don't use the volume table
- *
- * when the drive is in true raw mode (aka /dev/rawft0) then we don't
- * care about LBOT and EOM conditions. This device is intended for a
- * user level program that wants to truly implement the QIC-80 compliance
- * at the logical data layout level of the cartridge, i.e. implement all
- * that volume table and volume directory stuff etc.<
- */
-int zft_check_write_access(zft_position *pos)
-{
- TRACE_FUN(ft_t_flow);
-
- if (zft_offline) { /* offline includes no_tape */
- TRACE_ABORT(-ENXIO,
- ft_t_info, "tape is offline or no cartridge");
- }
- if (!ft_formatted) {
- TRACE_ABORT(-EACCES, ft_t_info, "tape is not formatted");
- }
- if (zft_write_protected) {
- TRACE_ABORT(-EACCES, ft_t_info, "cartridge write protected");
- }
- if (zft_qic_mode) {
- /* check BOT condition */
- if (!zft_tape_at_lbot(pos)) {
- /* protect cartridges written by old ftape if
- * not at BOT because they use the vtbl
- * segment for storing data
- */
- if (zft_old_ftape) {
- TRACE_ABORT(-EACCES, ft_t_warn,
- "Cannot write to cartridges written by old ftape when not at BOT");
- }
- /* not at BOT, but allow writes at EOD, of course
- */
- if (!zft_tape_at_eod(pos)) {
- TRACE_ABORT(-EACCES, ft_t_info,
- "tape not at BOT and not at EOD");
- }
- }
- /* fine. Now the tape is either at BOT or at EOD. */
- }
- /* or in raw mode in which case we don't care about BOT and EOD */
- TRACE_EXIT 0;
-}
-
-/* OPEN routine called by kernel-interface code
- *
- * NOTE: this is also called by mt_reset() with dev_minor == -1
- * to fake a reopen after a reset.
- */
-int _zft_open(unsigned int dev_minor, unsigned int access_mode)
-{
- static unsigned int tape_unit;
- static unsigned int file_access_mode;
- int result;
- TRACE_FUN(ft_t_flow);
-
- if ((int)dev_minor == -1) {
- /* fake reopen */
- zft_unit = tape_unit;
- access_mode = file_access_mode;
- zft_init_driver(); /* reset all static data to defaults */
- } else {
- tape_unit = dev_minor;
- file_access_mode = access_mode;
- if ((result = ftape_enable(FTAPE_SEL(dev_minor))) < 0) {
- TRACE_ABORT(-ENXIO, ft_t_err,
- "ftape_enable failed: %d", result);
- }
- if (ft_new_tape || ft_no_tape || !ft_formatted ||
- (FTAPE_SEL(zft_unit) != FTAPE_SEL(dev_minor)) ||
- (zft_unit & ZFT_RAW_MODE) != (dev_minor & ZFT_RAW_MODE)) {
- /* reset all static data to defaults,
- */
- zft_init_driver();
- }
- zft_unit = dev_minor;
- }
- zft_set_flags(zft_unit); /* decode the minor bits */
- if (zft_blk_sz == 1 && zft_use_compression) {
- ftape_disable(); /* resets ft_no_tape */
- TRACE_ABORT(-ENODEV, ft_t_warn, "Variable block size not yet "
- "supported with compression");
- }
- /* no need for most of the buffers when no tape or not
- * formatted. for the read/write operations, it is the
- * regardless whether there is no tape, a not-formatted tape
- * or the whether the driver is soft offline.
- * Nevertheless we allow some ioctls with non-formatted tapes,
- * like rewind and reset.
- */
- if (ft_no_tape || !ft_formatted) {
- zft_uninit_mem();
- }
- if (ft_no_tape) {
- zft_offline = 1; /* so we need not test two variables */
- }
- if ((access_mode == O_WRONLY || access_mode == O_RDWR) &&
- (ft_write_protected || ft_no_tape)) {
- ftape_disable(); /* resets ft_no_tape */
- TRACE_ABORT(ft_no_tape ? -ENXIO : -EROFS,
- ft_t_warn, "wrong access mode %s cartridge",
- ft_no_tape ? "without a" : "with write protected");
- }
- zft_write_protected = (access_mode == O_RDONLY ||
- ft_write_protected != 0);
- if (zft_write_protected) {
- TRACE(ft_t_noise,
- "read only access mode: %d, "
- "drive write protected: %d",
- access_mode == O_RDONLY,
- ft_write_protected != 0);
- }
- if (!zft_offline) {
- TRACE_CATCH(zft_vmalloc_once(&zft_deblock_buf,FT_SEGMENT_SIZE),
- ftape_disable());
- }
- /* zft_seg_pos should be greater than the vtbl segpos but not
- * if in compatibility mode and only after we read in the
- * header segments
- *
- * might also be a problem if the user makes a backup with a
- * *qft* device and rewinds it with a raw device.
- */
- if (zft_qic_mode &&
- !zft_old_ftape &&
- zft_pos.seg_pos >= 0 &&
- zft_header_read &&
- zft_pos.seg_pos <= ft_first_data_segment) {
- TRACE(ft_t_noise, "you probably mixed up the zftape devices!");
- zft_reset_position(&zft_pos);
- }
- TRACE_EXIT 0;
-}
-
-/* RELEASE routine called by kernel-interface code
- */
-int _zft_close(void)
-{
- int result = 0;
- TRACE_FUN(ft_t_flow);
-
- if (zft_offline) {
- /* call the hardware release routine. Puts the drive offline */
- ftape_disable();
- TRACE_EXIT 0;
- }
- if (!(ft_write_protected || zft_old_ftape)) {
- result = zft_flush_buffers();
- TRACE(ft_t_noise, "writing file mark at current position");
- if (zft_qic_mode && zft_close_volume(&zft_pos) == 0) {
- zft_move_past_eof(&zft_pos);
- }
- if ((zft_tape_at_lbot(&zft_pos) ||
- !(zft_unit & FTAPE_NO_REWIND))) {
- if (result >= 0) {
- result = zft_update_header_segments();
- } else {
- TRACE(ft_t_err,
- "Error: unable to update header segments");
- }
- }
- }
- ftape_abort_operation();
- if (!(zft_unit & FTAPE_NO_REWIND)) {
- TRACE(ft_t_noise, "rewinding tape");
- if (ftape_seek_to_bot() < 0 && result >= 0) {
- result = -EIO; /* keep old value */
- }
- zft_reset_position(&zft_pos);
- }
- zft_zap_read_buffers();
- /* now free up memory as much as possible. We don't destroy
- * the deblock buffer if it containes a valid segment.
- */
- if (zft_deblock_segment == -1) {
- zft_vfree(&zft_deblock_buf, FT_SEGMENT_SIZE);
- }
- /* high level driver status, forces creation of a new volume
- * when calling ftape_write again and not zft_just_before_eof
- */
- zft_io_state = zft_idle;
- if (going_offline) {
- zft_init_driver();
- zft_uninit_mem();
- going_offline = 0;
- zft_offline = 1;
- } else if (zft_cmpr_lock(0 /* don't load */) == 0) {
- (*zft_cmpr_ops->reset)(); /* unlock it again */
- }
- zft_memory_stats();
- /* call the hardware release routine. Puts the drive offline */
- ftape_disable();
- TRACE_EXIT result;
-}
-
-/*
- * the wrapper function around the wrapper MTIOCTOP ioctl
- */
-static int mtioctop(struct mtop *mtop, int arg_size)
-{
- int result = 0;
- fun_entry *mt_fun_entry;
- TRACE_FUN(ft_t_flow);
-
- if (arg_size != sizeof(struct mtop) || mtop->mt_op >= NR_MT_CMDS) {
- TRACE_EXIT -EINVAL;
- }
- TRACE(ft_t_noise, "calling MTIOCTOP command: %s",
- mt_funs[mtop->mt_op].name);
- mt_fun_entry= &mt_funs[mtop->mt_op];
- zft_resid = mtop->mt_count;
- if (!mt_fun_entry->offline && zft_offline) {
- if (ft_no_tape) {
- TRACE_ABORT(-ENXIO, ft_t_info, "no tape present");
- } else {
- TRACE_ABORT(-ENXIO, ft_t_info, "drive is offline");
- }
- }
- if (!mt_fun_entry->not_formatted && !ft_formatted) {
- TRACE_ABORT(-EACCES, ft_t_info, "tape is not formatted");
- }
- if (!mt_fun_entry->write_protected) {
- TRACE_CATCH(zft_check_write_access(&zft_pos),);
- }
- if (mt_fun_entry->need_idle_state && !(zft_offline || !ft_formatted)) {
- TRACE_CATCH(zft_def_idle_state(),);
- }
- if (!zft_qic_mode && !mt_fun_entry->raw_mode) {
- TRACE_ABORT(-EACCES, ft_t_info,
-"Drive needs to be in QIC-80 compatibility mode for this command");
- }
- result = (mt_fun_entry->function)(&mtop->mt_count);
- if (zft_tape_at_lbot(&zft_pos)) {
- TRACE_CATCH(zft_update_header_segments(),);
- }
- if (result >= 0) {
- zft_resid = 0;
- }
- TRACE_EXIT result;
-}
-
-/*
- * standard MTIOCGET ioctl
- */
-static int mtiocget(struct mtget *mtget, int arg_size)
-{
- const zft_volinfo *volume;
- __s64 max_tape_pos;
- TRACE_FUN(ft_t_flow);
-
- if (arg_size != sizeof(struct mtget)) {
- TRACE_ABORT(-EINVAL, ft_t_info, "bad argument size: %d",
- arg_size);
- }
- mtget->mt_type = ft_drive_type.vendor_id + 0x800000;
- mtget->mt_dsreg = ft_last_status.space;
- mtget->mt_erreg = ft_last_error.space; /* error register */
- mtget->mt_resid = zft_resid; /* residuum of writes, reads and
- * MTIOCTOP commands
- */
- if (!zft_offline) { /* neither no_tape nor soft offline */
- mtget->mt_gstat = GMT_ONLINE(~0UL);
- /* should rather return the status of the cartridge
- * than the access mode of the file, therefor use
- * ft_write_protected, not zft_write_protected
- */
- if (ft_write_protected) {
- mtget->mt_gstat |= GMT_WR_PROT(~0UL);
- }
- if(zft_header_read) { /* this catches non-formatted */
- volume = zft_find_volume(zft_pos.seg_pos);
- mtget->mt_fileno = volume->count;
- max_tape_pos = zft_capacity - zft_blk_sz;
- if (zft_use_compression) {
- max_tape_pos -= ZFT_CMPR_OVERHEAD;
- }
- if (zft_tape_at_eod(&zft_pos)) {
- mtget->mt_gstat |= GMT_EOD(~0UL);
- }
- if (zft_pos.tape_pos > max_tape_pos) {
- mtget->mt_gstat |= GMT_EOT(~0UL);
- }
- mtget->mt_blkno = zft_div_blksz(zft_pos.volume_pos,
- volume->blk_sz);
- if (zft_just_before_eof) {
- mtget->mt_gstat |= GMT_EOF(~0UL);
- }
- if (zft_tape_at_lbot(&zft_pos)) {
- mtget->mt_gstat |= GMT_BOT(~0UL);
- }
- } else {
- mtget->mt_fileno = mtget->mt_blkno = -1;
- if (mtget->mt_dsreg & QIC_STATUS_AT_BOT) {
- mtget->mt_gstat |= GMT_BOT(~0UL);
- }
- }
- } else {
- if (ft_no_tape) {
- mtget->mt_gstat = GMT_DR_OPEN(~0UL);
- } else {
- mtget->mt_gstat = 0UL;
- }
- mtget->mt_fileno = mtget->mt_blkno = -1;
- }
- TRACE_EXIT 0;
-}
-
-#ifdef MTIOCRDFTSEG
-/*
- * Read a floppy tape segment. This is useful for manipulating the
- * volume table, and read the old header segment before re-formatting
- * the cartridge.
- */
-static int mtiocrdftseg(struct mtftseg * mtftseg, int arg_size)
-{
- TRACE_FUN(ft_t_flow);
-
- TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCRDFTSEG");
- if (zft_qic_mode) {
- TRACE_ABORT(-EACCES, ft_t_info,
- "driver needs to be in raw mode for this ioctl");
- }
- if (arg_size != sizeof(struct mtftseg)) {
- TRACE_ABORT(-EINVAL, ft_t_info, "bad argument size: %d",
- arg_size);
- }
- if (zft_offline) {
- TRACE_EXIT -ENXIO;
- }
- if (mtftseg->mt_mode != FT_RD_SINGLE &&
- mtftseg->mt_mode != FT_RD_AHEAD) {
- TRACE_ABORT(-EINVAL, ft_t_info, "invalid read mode");
- }
- if (!ft_formatted) {
- TRACE_EXIT -EACCES; /* -ENXIO ? */
-
- }
- if (!zft_header_read) {
- TRACE_CATCH(zft_def_idle_state(),);
- }
- if (mtftseg->mt_segno > ft_last_data_segment) {
- TRACE_ABORT(-EINVAL, ft_t_info, "segment number is too large");
- }
- mtftseg->mt_result = ftape_read_segment(mtftseg->mt_segno,
- zft_deblock_buf,
- mtftseg->mt_mode);
- if (mtftseg->mt_result < 0) {
- /* a negativ result is not an ioctl error. if
- * the user wants to read damaged tapes,
- * it's up to her/him
- */
- TRACE_EXIT 0;
- }
- if (copy_to_user(mtftseg->mt_data,
- zft_deblock_buf,
- mtftseg->mt_result) != 0) {
- TRACE_EXIT -EFAULT;
- }
- TRACE_EXIT 0;
-}
-#endif
-
-#ifdef MTIOCWRFTSEG
-/*
- * write a floppy tape segment. This version features writing of
- * deleted address marks, and gracefully ignores the (software)
- * ft_formatted flag to support writing of header segments after
- * formatting.
- */
-static int mtiocwrftseg(struct mtftseg * mtftseg, int arg_size)
-{
- int result;
- TRACE_FUN(ft_t_flow);
-
- TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCWRFTSEG");
- if (zft_write_protected || zft_qic_mode) {
- TRACE_EXIT -EACCES;
- }
- if (arg_size != sizeof(struct mtftseg)) {
- TRACE_ABORT(-EINVAL, ft_t_info, "bad argument size: %d",
- arg_size);
- }
- if (zft_offline) {
- TRACE_EXIT -ENXIO;
- }
- if (mtftseg->mt_mode != FT_WR_ASYNC &&
- mtftseg->mt_mode != FT_WR_MULTI &&
- mtftseg->mt_mode != FT_WR_SINGLE &&
- mtftseg->mt_mode != FT_WR_DELETE) {
- TRACE_ABORT(-EINVAL, ft_t_info, "invalid write mode");
- }
- /*
- * We don't check for ft_formatted, because this gives
- * only the software status of the driver.
- *
- * We assume that the user knows what it is
- * doing. And rely on the low level stuff to fail
- * when the tape isn't formatted. We only make sure
- * that The header segment buffer is allocated,
- * because it holds the bad sector map.
- */
- if (zft_hseg_buf == NULL) {
- TRACE_EXIT -ENXIO;
- }
- if (mtftseg->mt_mode != FT_WR_DELETE) {
- if (copy_from_user(zft_deblock_buf,
- mtftseg->mt_data,
- FT_SEGMENT_SIZE) != 0) {
- TRACE_EXIT -EFAULT;
- }
- }
- mtftseg->mt_result = ftape_write_segment(mtftseg->mt_segno,
- zft_deblock_buf,
- mtftseg->mt_mode);
- if (mtftseg->mt_result >= 0 && mtftseg->mt_mode == FT_WR_SINGLE) {
- /*
- * a negativ result is not an ioctl error. if
- * the user wants to write damaged tapes,
- * it's up to her/him
- */
- if ((result = ftape_loop_until_writes_done()) < 0) {
- mtftseg->mt_result = result;
- }
- }
- TRACE_EXIT 0;
-}
-#endif
-
-#ifdef MTIOCVOLINFO
-/*
- * get information about volume positioned at.
- */
-static int mtiocvolinfo(struct mtvolinfo *volinfo, int arg_size)
-{
- const zft_volinfo *volume;
- TRACE_FUN(ft_t_flow);
-
- TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCVOLINFO");
- if (arg_size != sizeof(struct mtvolinfo)) {
- TRACE_ABORT(-EINVAL,
- ft_t_info, "bad argument size: %d", arg_size);
- }
- if (zft_offline) {
- TRACE_EXIT -ENXIO;
- }
- if (!ft_formatted) {
- TRACE_EXIT -EACCES;
- }
- TRACE_CATCH(zft_def_idle_state(),);
- volume = zft_find_volume(zft_pos.seg_pos);
- volinfo->mt_volno = volume->count;
- volinfo->mt_blksz = volume->blk_sz == 1 ? 0 : volume->blk_sz;
- volinfo->mt_size = volume->size >> 10;
- volinfo->mt_rawsize = ((zft_calc_tape_pos(volume->end_seg + 1) >> 10) -
- (zft_calc_tape_pos(volume->start_seg) >> 10));
- volinfo->mt_cmpr = volume->use_compression;
- TRACE_EXIT 0;
-}
-#endif
-
-#ifdef ZFT_OBSOLETE
-static int mtioc_zftape_getblksz(struct mtblksz *blksz, int arg_size)
-{
- TRACE_FUN(ft_t_flow);
-
- TRACE(ft_t_noise, "\n"
- KERN_INFO "Mag tape ioctl command: MTIOC_ZTAPE_GETBLKSZ\n"
- KERN_INFO "This ioctl is here merely for compatibility.\n"
- KERN_INFO "Please use MTIOCVOLINFO instead");
- if (arg_size != sizeof(struct mtblksz)) {
- TRACE_ABORT(-EINVAL,
- ft_t_info, "bad argument size: %d", arg_size);
- }
- if (zft_offline) {
- TRACE_EXIT -ENXIO;
- }
- if (!ft_formatted) {
- TRACE_EXIT -EACCES;
- }
- TRACE_CATCH(zft_def_idle_state(),);
- blksz->mt_blksz = zft_find_volume(zft_pos.seg_pos)->blk_sz;
- TRACE_EXIT 0;
-}
-#endif
-
-#ifdef MTIOCGETSIZE
-/*
- * get the capacity of the tape cartridge.
- */
-static int mtiocgetsize(struct mttapesize *size, int arg_size)
-{
- TRACE_FUN(ft_t_flow);
-
- TRACE(ft_t_noise, "Mag tape ioctl command: MTIOC_ZFTAPE_GETSIZE");
- if (arg_size != sizeof(struct mttapesize)) {
- TRACE_ABORT(-EINVAL,
- ft_t_info, "bad argument size: %d", arg_size);
- }
- if (zft_offline) {
- TRACE_EXIT -ENXIO;
- }
- if (!ft_formatted) {
- TRACE_EXIT -EACCES;
- }
- TRACE_CATCH(zft_def_idle_state(),);
- size->mt_capacity = (unsigned int)(zft_capacity>>10);
- size->mt_used = (unsigned int)(zft_get_eom_pos()>>10);
- TRACE_EXIT 0;
-}
-#endif
-
-static int mtiocpos(struct mtpos *mtpos, int arg_size)
-{
- int result;
- TRACE_FUN(ft_t_flow);
-
- TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCPOS");
- if (arg_size != sizeof(struct mtpos)) {
- TRACE_ABORT(-EINVAL,
- ft_t_info, "bad argument size: %d", arg_size);
- }
- result = mt_tell((int *)&mtpos->mt_blkno);
- TRACE_EXIT result;
-}
-
-#ifdef MTIOCFTFORMAT
-/*
- * formatting of floppy tape cartridges. This is intended to be used
- * together with the MTIOCFTCMD ioctl and the new mmap feature
- */
-
-/*
- * This function uses ftape_decode_header_segment() to inform the low
- * level ftape module about the new parameters.
- *
- * It erases the hseg_buf. The calling process must specify all
- * parameters to assure proper operation.
- *
- * return values: -EINVAL - wrong argument size
- * -EINVAL - if ftape_decode_header_segment() failed.
- */
-static int set_format_parms(struct ftfmtparms *p, __u8 *hseg_buf)
-{
- ft_trace_t old_level = TRACE_LEVEL;
- TRACE_FUN(ft_t_flow);
-
- TRACE(ft_t_noise, "MTIOCFTFORMAT operation FTFMT_SETPARMS");
- memset(hseg_buf, 0, FT_SEGMENT_SIZE);
- PUT4(hseg_buf, FT_SIGNATURE, FT_HSEG_MAGIC);
-
- /* fill in user specified parameters
- */
- hseg_buf[FT_FMT_CODE] = (__u8)p->ft_fmtcode;
- PUT2(hseg_buf, FT_SPT, p->ft_spt);
- hseg_buf[FT_TPC] = (__u8)p->ft_tpc;
- hseg_buf[FT_FHM] = (__u8)p->ft_fhm;
- hseg_buf[FT_FTM] = (__u8)p->ft_ftm;
-
- /* fill in sane defaults to make ftape happy.
- */
- hseg_buf[FT_FSM] = (__u8)128; /* 128 is hard wired all over ftape */
- if (p->ft_fmtcode == fmt_big) {
- PUT4(hseg_buf, FT_6_HSEG_1, 0);
- PUT4(hseg_buf, FT_6_HSEG_2, 1);
- PUT4(hseg_buf, FT_6_FRST_SEG, 2);
- PUT4(hseg_buf, FT_6_LAST_SEG, p->ft_spt * p->ft_tpc - 1);
- } else {
- PUT2(hseg_buf, FT_HSEG_1, 0);
- PUT2(hseg_buf, FT_HSEG_2, 1);
- PUT2(hseg_buf, FT_FRST_SEG, 2);
- PUT2(hseg_buf, FT_LAST_SEG, p->ft_spt * p->ft_tpc - 1);
- }
-
- /* Synchronize with the low level module. This is particularly
- * needed for unformatted cartridges as the QIC std was previously
- * unknown BUT is needed to set data rate and to calculate timeouts.
- */
- TRACE_CATCH(ftape_calibrate_data_rate(p->ft_qicstd&QIC_TAPE_STD_MASK),
- _res = -EINVAL);
-
- /* The following will also recalcualte the timeouts for the tape
- * length and QIC std we want to format to.
- * abort with -EINVAL rather than -EIO
- */
- SET_TRACE_LEVEL(ft_t_warn);
- TRACE_CATCH(ftape_decode_header_segment(hseg_buf),
- SET_TRACE_LEVEL(old_level); _res = -EINVAL);
- SET_TRACE_LEVEL(old_level);
- TRACE_EXIT 0;
-}
-
-/*
- * Return the internal SOFTWARE status of the kernel driver. This does
- * NOT query the tape drive about its status.
- */
-static int get_format_parms(struct ftfmtparms *p, __u8 *hseg_buffer)
-{
- TRACE_FUN(ft_t_flow);
-
- TRACE(ft_t_noise, "MTIOCFTFORMAT operation FTFMT_GETPARMS");
- p->ft_qicstd = ft_qic_std;
- p->ft_fmtcode = ft_format_code;
- p->ft_fhm = hseg_buffer[FT_FHM];
- p->ft_ftm = hseg_buffer[FT_FTM];
- p->ft_spt = ft_segments_per_track;
- p->ft_tpc = ft_tracks_per_tape;
- TRACE_EXIT 0;
-}
-
-static int mtiocftformat(struct mtftformat *mtftformat, int arg_size)
-{
- int result;
- union fmt_arg *arg = &mtftformat->fmt_arg;
- TRACE_FUN(ft_t_flow);
-
- TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCFTFORMAT");
- if (zft_offline) {
- if (ft_no_tape) {
- TRACE_ABORT(-ENXIO, ft_t_info, "no tape present");
- } else {
- TRACE_ABORT(-ENXIO, ft_t_info, "drive is offline");
- }
- }
- if (zft_qic_mode) {
- TRACE_ABORT(-EACCES, ft_t_info,
- "driver needs to be in raw mode for this ioctl");
- }
- if (zft_hseg_buf == NULL) {
- TRACE_CATCH(zft_vcalloc_once(&zft_hseg_buf, FT_SEGMENT_SIZE),);
- }
- zft_header_read = 0;
- switch(mtftformat->fmt_op) {
- case FTFMT_SET_PARMS:
- TRACE_CATCH(set_format_parms(&arg->fmt_parms, zft_hseg_buf),);
- TRACE_EXIT 0;
- case FTFMT_GET_PARMS:
- TRACE_CATCH(get_format_parms(&arg->fmt_parms, zft_hseg_buf),);
- TRACE_EXIT 0;
- case FTFMT_FORMAT_TRACK:
- if ((ft_formatted && zft_check_write_access(&zft_pos) < 0) ||
- (!ft_formatted && zft_write_protected)) {
- TRACE_ABORT(-EACCES, ft_t_info, "Write access denied");
- }
- TRACE_CATCH(ftape_format_track(arg->fmt_track.ft_track,
- arg->fmt_track.ft_gap3),);
- TRACE_EXIT 0;
- case FTFMT_STATUS:
- TRACE_CATCH(ftape_format_status(&arg->fmt_status.ft_segment),);
- TRACE_EXIT 0;
- case FTFMT_VERIFY:
- TRACE_CATCH(ftape_verify_segment(arg->fmt_verify.ft_segment,
- (SectorMap *)&arg->fmt_verify.ft_bsm),);
- TRACE_EXIT 0;
- default:
- TRACE_ABORT(-EINVAL, ft_t_err, "Invalid format operation");
- }
- TRACE_EXIT result;
-}
-#endif
-
-#ifdef MTIOCFTCMD
-/*
- * send a QIC-117 command to the drive, with optional timeouts,
- * parameter and result bits. This is intended to be used together
- * with the formatting ioctl.
- */
-static int mtiocftcmd(struct mtftcmd *ftcmd, int arg_size)
-{
- int i;
- TRACE_FUN(ft_t_flow);
-
- TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCFTCMD");
- if (!capable(CAP_SYS_ADMIN)) {
- TRACE_ABORT(-EPERM, ft_t_info,
- "need CAP_SYS_ADMIN capability to send raw qic-117 commands");
- }
- if (zft_qic_mode) {
- TRACE_ABORT(-EACCES, ft_t_info,
- "driver needs to be in raw mode for this ioctl");
- }
- if (arg_size != sizeof(struct mtftcmd)) {
- TRACE_ABORT(-EINVAL,
- ft_t_info, "bad argument size: %d", arg_size);
- }
- if (ftcmd->ft_wait_before) {
- TRACE_CATCH(ftape_ready_wait(ftcmd->ft_wait_before,
- &ftcmd->ft_status),);
- }
- if (ftcmd->ft_status & QIC_STATUS_ERROR)
- goto ftmtcmd_error;
- if (ftcmd->ft_result_bits != 0) {
- TRACE_CATCH(ftape_report_operation(&ftcmd->ft_result,
- ftcmd->ft_cmd,
- ftcmd->ft_result_bits),);
- } else {
- TRACE_CATCH(ftape_command(ftcmd->ft_cmd),);
- if (ftcmd->ft_status & QIC_STATUS_ERROR)
- goto ftmtcmd_error;
- for (i = 0; i < ftcmd->ft_parm_cnt; i++) {
- TRACE_CATCH(ftape_parameter(ftcmd->ft_parms[i]&0x0f),);
- if (ftcmd->ft_status & QIC_STATUS_ERROR)
- goto ftmtcmd_error;
- }
- }
- if (ftcmd->ft_wait_after != 0) {
- TRACE_CATCH(ftape_ready_wait(ftcmd->ft_wait_after,
- &ftcmd->ft_status),);
- }
-ftmtcmd_error:
- if (ftcmd->ft_status & QIC_STATUS_ERROR) {
- TRACE(ft_t_noise, "error status set");
- TRACE_CATCH(ftape_report_error(&ftcmd->ft_error,
- &ftcmd->ft_cmd, 1),);
- }
- TRACE_EXIT 0; /* this is not an i/o error */
-}
-#endif
-
-/* IOCTL routine called by kernel-interface code
- */
-int _zft_ioctl(unsigned int command, void __user * arg)
-{
- int result;
- union { struct mtop mtop;
- struct mtget mtget;
- struct mtpos mtpos;
-#ifdef MTIOCRDFTSEG
- struct mtftseg mtftseg;
-#endif
-#ifdef MTIOCVOLINFO
- struct mtvolinfo mtvolinfo;
-#endif
-#ifdef MTIOCGETSIZE
- struct mttapesize mttapesize;
-#endif
-#ifdef MTIOCFTFORMAT
- struct mtftformat mtftformat;
-#endif
-#ifdef ZFT_OBSOLETE
- struct mtblksz mtblksz;
-#endif
-#ifdef MTIOCFTCMD
- struct mtftcmd mtftcmd;
-#endif
- } krnl_arg;
- int arg_size = _IOC_SIZE(command);
- int dir = _IOC_DIR(command);
- TRACE_FUN(ft_t_flow);
-
- /* This check will only catch arguments that are too large !
- */
- if (dir & (_IOC_READ | _IOC_WRITE) && arg_size > sizeof(krnl_arg)) {
- TRACE_ABORT(-EINVAL,
- ft_t_info, "bad argument size: %d", arg_size);
- }
- if (dir & _IOC_WRITE) {
- if (copy_from_user(&krnl_arg, arg, arg_size) != 0) {
- TRACE_EXIT -EFAULT;
- }
- }
- TRACE(ft_t_flow, "called with ioctl command: 0x%08x", command);
- switch (command) {
- case MTIOCTOP:
- result = mtioctop(&krnl_arg.mtop, arg_size);
- break;
- case MTIOCGET:
- result = mtiocget(&krnl_arg.mtget, arg_size);
- break;
- case MTIOCPOS:
- result = mtiocpos(&krnl_arg.mtpos, arg_size);
- break;
-#ifdef MTIOCVOLINFO
- case MTIOCVOLINFO:
- result = mtiocvolinfo(&krnl_arg.mtvolinfo, arg_size);
- break;
-#endif
-#ifdef ZFT_OBSOLETE
- case MTIOC_ZFTAPE_GETBLKSZ:
- result = mtioc_zftape_getblksz(&krnl_arg.mtblksz, arg_size);
- break;
-#endif
-#ifdef MTIOCRDFTSEG
- case MTIOCRDFTSEG: /* read a segment via ioctl */
- result = mtiocrdftseg(&krnl_arg.mtftseg, arg_size);
- break;
-#endif
-#ifdef MTIOCWRFTSEG
- case MTIOCWRFTSEG: /* write a segment via ioctl */
- result = mtiocwrftseg(&krnl_arg.mtftseg, arg_size);
- break;
-#endif
-#ifdef MTIOCGETSIZE
- case MTIOCGETSIZE:
- result = mtiocgetsize(&krnl_arg.mttapesize, arg_size);
- break;
-#endif
-#ifdef MTIOCFTFORMAT
- case MTIOCFTFORMAT:
- result = mtiocftformat(&krnl_arg.mtftformat, arg_size);
- break;
-#endif
-#ifdef MTIOCFTCMD
- case MTIOCFTCMD:
- result = mtiocftcmd(&krnl_arg.mtftcmd, arg_size);
- break;
-#endif
- default:
- result = -EINVAL;
- break;
- }
- if ((result >= 0) && (dir & _IOC_READ)) {
- if (copy_to_user(arg, &krnl_arg, arg_size) != 0) {
- TRACE_EXIT -EFAULT;
- }
- }
- TRACE_EXIT result;
-}
diff --git a/drivers/char/ftape/zftape/zftape-ctl.h b/drivers/char/ftape/zftape/zftape-ctl.h
deleted file mode 100644
index 8e6f2d7ac74e..000000000000
--- a/drivers/char/ftape/zftape/zftape-ctl.h
+++ /dev/null
@@ -1,58 +0,0 @@
-#ifndef _ZFTAPE_CTL_H
-#define _ZFTAPE_CTL_H
-
-/*
- * Copyright (C) 1996, 1997 Claus-Justus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-ctl.h,v $
- * $Revision: 1.2 $
- * $Date: 1997/10/05 19:19:02 $
- *
- * This file contains the non-standard IOCTL related definitions
- * for the QIC-40/80 floppy-tape driver for Linux.
- */
-
-#include <linux/ioctl.h>
-#include <linux/mtio.h>
-
-#include "../zftape/zftape-rw.h"
-
-#ifdef CONFIG_ZFTAPE_MODULE
-#define ftape_status (*zft_status)
-#endif
-
-extern int zft_offline;
-extern int zft_mt_compression;
-extern int zft_write_protected;
-extern int zft_header_read;
-extern unsigned int zft_unit;
-extern int zft_resid;
-
-extern void zft_reset_position(zft_position *pos);
-extern int zft_check_write_access(zft_position *pos);
-extern int zft_def_idle_state(void);
-
-/* hooks for the VFS interface
- */
-extern int _zft_open(unsigned int dev_minor, unsigned int access_mode);
-extern int _zft_close(void);
-extern int _zft_ioctl(unsigned int command, void __user *arg);
-#endif
-
-
-
diff --git a/drivers/char/ftape/zftape/zftape-eof.c b/drivers/char/ftape/zftape/zftape-eof.c
deleted file mode 100644
index dcadcaee9ac1..000000000000
--- a/drivers/char/ftape/zftape/zftape-eof.c
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * I use these routines just to decide when I have to fake a
- * volume-table to preserve compatibility to original ftape.
- */
-/*
- * Copyright (C) 1994-1995 Bas Laarhoven.
- *
- * Modified for zftape 1996, 1997 Claus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-eof.c,v $
- * $Revision: 1.2 $
- * $Date: 1997/10/05 19:19:02 $
- *
- * This file contains the eof mark handling code
- * for the QIC-40/80 floppy-tape driver for Linux.
- */
-
-#include <linux/string.h>
-#include <linux/errno.h>
-
-#include <linux/zftape.h>
-
-#include "../zftape/zftape-init.h"
-#include "../zftape/zftape-rw.h"
-#include "../zftape/zftape-eof.h"
-
-/* Global vars.
- */
-
-/* a copy of the failed sector log from the header segment.
- */
-eof_mark_union *zft_eof_map;
-
-/* number of eof marks (entries in bad sector log) on tape.
- */
-int zft_nr_eof_marks = -1;
-
-
-/* Local vars.
- */
-
-static char linux_tape_label[] = "Linux raw format V";
-enum {
- min_fmt_version = 1, max_fmt_version = 2
-};
-static unsigned ftape_fmt_version = 0;
-
-
-/* Ftape (mis)uses the bad sector log to record end-of-file marks.
- * Initially (when the tape is erased) all entries in the bad sector
- * log are added to the tape's bad sector map. The bad sector log then
- * is cleared.
- *
- * The bad sector log normally contains entries of the form:
- * even 16-bit word: segment number of bad sector
- * odd 16-bit word: encoded date
- * There can be a total of 448 entries (1792 bytes).
- *
- * My guess is that no program is using this bad sector log (the *
- * format seems useless as there is no indication of the bad sector
- * itself, only the segment) However, if any program does use the bad
- * sector log, the format used by ftape will let the program think
- * there are some bad sectors and no harm is done.
- *
- * The eof mark entries that ftape stores in the bad sector log: even
- * 16-bit word: segment number of eof mark odd 16-bit word: sector
- * number of eof mark [1..32]
- *
- * The zft_eof_map as maintained is a sorted list of eof mark entries.
- *
- *
- * The tape name field in the header segments is used to store a linux
- * tape identification string and a version number. This way the tape
- * can be recognized as a Linux raw format tape when using tools under
- * other OS's.
- *
- * 'Wide' QIC tapes (format code 4) don't have a failed sector list
- * anymore. That space is used for the (longer) bad sector map that
- * now is a variable length list too. We now store our end-of-file
- * marker list after the bad-sector-map on tape. The list is delimited
- * by a (__u32) 0 entry.
- */
-
-int zft_ftape_validate_label(char *label)
-{
- static char tmp_label[45];
- int result = 0;
- TRACE_FUN(ft_t_any);
-
- memcpy(tmp_label, label, FT_LABEL_SZ);
- tmp_label[FT_LABEL_SZ] = '\0';
- TRACE(ft_t_noise, "tape label = `%s'", tmp_label);
- ftape_fmt_version = 0;
- if (memcmp(label, linux_tape_label, strlen(linux_tape_label)) == 0) {
- int pos = strlen(linux_tape_label);
- while (label[pos] >= '0' && label[pos] <= '9') {
- ftape_fmt_version *= 10;
- ftape_fmt_version = label[ pos++] - '0';
- }
- result = (ftape_fmt_version >= min_fmt_version &&
- ftape_fmt_version <= max_fmt_version);
- }
- TRACE(ft_t_noise, "format version = %d", ftape_fmt_version);
- TRACE_EXIT result;
-}
-
-static __u8 * find_end_of_eof_list(__u8 * ptr, __u8 * limit)
-{
- while (ptr + 3 < limit) {
-
- if (get_unaligned((__u32*)ptr)) {
- ptr += sizeof(__u32);
- } else {
- return ptr;
- }
- }
- return NULL;
-}
-
-void zft_ftape_extract_file_marks(__u8* address)
-{
- int i;
- TRACE_FUN(ft_t_any);
-
- zft_eof_map = NULL;
- if (ft_format_code == fmt_var || ft_format_code == fmt_big) {
- __u8* end;
- __u8* start = ftape_find_end_of_bsm_list(address);
-
- zft_nr_eof_marks = 0;
- if (start) {
- start += 3; /* skip end of list mark */
- end = find_end_of_eof_list(start,
- address + FT_SEGMENT_SIZE);
- if (end && end - start <= FT_FSL_SIZE) {
- zft_nr_eof_marks = ((end - start) /
- sizeof(eof_mark_union));
- zft_eof_map = (eof_mark_union *)start;
- } else {
- TRACE(ft_t_err,
- "EOF Mark List is too long or damaged!");
- }
- } else {
- TRACE(ft_t_err,
- "Bad Sector List is too long or damaged !");
- }
- } else {
- zft_eof_map = (eof_mark_union *)&address[FT_FSL];
- zft_nr_eof_marks = GET2(address, FT_FSL_CNT);
- }
- TRACE(ft_t_noise, "number of file marks: %d", zft_nr_eof_marks);
- if (ftape_fmt_version == 1) {
- TRACE(ft_t_info, "swapping version 1 fields");
- /* version 1 format uses swapped sector and segment
- * fields, correct that !
- */
- for (i = 0; i < zft_nr_eof_marks; ++i) {
- __u16 tmp = GET2(&zft_eof_map[i].mark.segment,0);
- PUT2(&zft_eof_map[i].mark.segment, 0,
- GET2(&zft_eof_map[i].mark.date,0));
- PUT2(&zft_eof_map[i].mark.date, 0, tmp);
- }
- }
- for (i = 0; i < zft_nr_eof_marks; ++i) {
- TRACE(ft_t_noise, "eof mark: %5d/%2d",
- GET2(&zft_eof_map[i].mark.segment, 0),
- GET2(&zft_eof_map[i].mark.date,0));
- }
- TRACE_EXIT;
-}
-
-void zft_clear_ftape_file_marks(void)
-{
- TRACE_FUN(ft_t_flow);
- /* Clear failed sector log: remove all tape marks. We
- * don't use old ftape-style EOF-marks.
- */
- TRACE(ft_t_info, "Clearing old ftape's eof map");
- memset(zft_eof_map, 0, zft_nr_eof_marks * sizeof(__u32));
- zft_nr_eof_marks = 0;
- PUT2(zft_hseg_buf, FT_FSL_CNT, 0); /* nr of eof-marks */
- zft_header_changed = 1;
- zft_update_label(zft_hseg_buf);
- TRACE_EXIT;
-}
diff --git a/drivers/char/ftape/zftape/zftape-eof.h b/drivers/char/ftape/zftape/zftape-eof.h
deleted file mode 100644
index 26568c26c518..000000000000
--- a/drivers/char/ftape/zftape/zftape-eof.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#ifndef _ZFTAPE_EOF_H
-#define _ZFTAPE_EOF_H
-
-/*
- * Copyright (C) 1994-1995 Bas Laarhoven.
- * adaptaed for zftape 1996, 1997 by Claus Heine
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-eof.h,v $
- * $Revision: 1.2 $
- * $Date: 1997/10/05 19:19:03 $
- *
- * Definitions and declarations for the end of file markers
- * for the QIC-40/80 floppy-tape driver for Linux.
- */
-
-#include <linux/ftape-header-segment.h>
-#include "../zftape/zftape-buffers.h"
-/* failed sector log size (only used if format code != 4).
- */
-
-typedef union {
- ft_fsl_entry mark;
- __u32 entry;
-} eof_mark_union;
-
-/* ftape-eof.c defined global vars.
- */
-extern int zft_nr_eof_marks;
-extern eof_mark_union *zft_eof_map;
-
-/* ftape-eof.c defined global functions.
- */
-extern void zft_ftape_extract_file_marks(__u8* address);
-extern int zft_ftape_validate_label(char* label);
-extern void zft_clear_ftape_file_marks(void);
-
-#endif
diff --git a/drivers/char/ftape/zftape/zftape-init.c b/drivers/char/ftape/zftape/zftape-init.c
deleted file mode 100644
index 164a1aa77a2f..000000000000
--- a/drivers/char/ftape/zftape/zftape-init.c
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * Copyright (C) 1996, 1997 Claus-Justus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * This file contains the code that registers the zftape frontend
- * to the ftape floppy tape driver for Linux
- */
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/signal.h>
-#include <linux/major.h>
-#include <linux/slab.h>
-#ifdef CONFIG_KMOD
-#include <linux/kmod.h>
-#endif
-#include <linux/fcntl.h>
-#include <linux/smp_lock.h>
-
-#include <linux/zftape.h>
-#include <linux/init.h>
-#include <linux/device.h>
-
-#include "../zftape/zftape-init.h"
-#include "../zftape/zftape-read.h"
-#include "../zftape/zftape-write.h"
-#include "../zftape/zftape-ctl.h"
-#include "../zftape/zftape-buffers.h"
-
-MODULE_AUTHOR("(c) 1996, 1997 Claus-Justus Heine "
- "(claus@momo.math.rwth-aachen.de)");
-MODULE_DESCRIPTION(ZFTAPE_VERSION " - "
- "VFS interface for the Linux floppy tape driver. "
- "Support for QIC-113 compatible volume table "
- "and builtin compression (lzrw3 algorithm)");
-MODULE_SUPPORTED_DEVICE("char-major-27");
-MODULE_LICENSE("GPL");
-
-/* Global vars.
- */
-struct zft_cmpr_ops *zft_cmpr_ops = NULL;
-const ftape_info *zft_status;
-
-/* Local vars.
- */
-static unsigned long busy_flag;
-
-static sigset_t orig_sigmask;
-
-/* the interface to the kernel vfs layer
- */
-
-/* Note about llseek():
- *
- * st.c and tpqic.c update fp->f_pos but don't implment llseek() and
- * initialize the llseek component of the file_ops struct with NULL.
- * This means that the user will get the default seek, but the tape
- * device will not respect the new position, but happily read from the
- * old position. Think a zftape specific llseek() function would be
- * better, returning -ESPIPE. TODO.
- */
-
-static int zft_open (struct inode *ino, struct file *filep);
-static int zft_close(struct inode *ino, struct file *filep);
-static int zft_ioctl(struct inode *ino, struct file *filep,
- unsigned int command, unsigned long arg);
-static int zft_mmap(struct file *filep, struct vm_area_struct *vma);
-static ssize_t zft_read (struct file *fp, char __user *buff,
- size_t req_len, loff_t *ppos);
-static ssize_t zft_write(struct file *fp, const char __user *buff,
- size_t req_len, loff_t *ppos);
-
-static const struct file_operations zft_cdev =
-{
- .owner = THIS_MODULE,
- .read = zft_read,
- .write = zft_write,
- .ioctl = zft_ioctl,
- .mmap = zft_mmap,
- .open = zft_open,
- .release = zft_close,
-};
-
-static struct class *zft_class;
-
-/* Open floppy tape device
- */
-static int zft_open(struct inode *ino, struct file *filep)
-{
- int result;
- TRACE_FUN(ft_t_flow);
-
- nonseekable_open(ino, filep);
- TRACE(ft_t_flow, "called for minor %d", iminor(ino));
- if ( test_and_set_bit(0,&busy_flag) ) {
- TRACE_ABORT(-EBUSY, ft_t_warn, "failed: already busy");
- }
- if ((iminor(ino) & ~(ZFT_MINOR_OP_MASK | FTAPE_NO_REWIND))
- >
- FTAPE_SEL_D) {
- clear_bit(0,&busy_flag);
- TRACE_ABORT(-ENXIO, ft_t_err, "failed: invalid unit nr");
- }
- orig_sigmask = current->blocked;
- sigfillset(&current->blocked);
- result = _zft_open(iminor(ino), filep->f_flags & O_ACCMODE);
- if (result < 0) {
- current->blocked = orig_sigmask; /* restore mask */
- clear_bit(0,&busy_flag);
- TRACE_ABORT(result, ft_t_err, "_ftape_open failed");
- } else {
- /* Mask signals that will disturb proper operation of the
- * program that is calling.
- */
- current->blocked = orig_sigmask;
- sigaddsetmask (&current->blocked, _DO_BLOCK);
- TRACE_EXIT 0;
- }
-}
-
-/* Close floppy tape device
- */
-static int zft_close(struct inode *ino, struct file *filep)
-{
- int result;
- TRACE_FUN(ft_t_flow);
-
- if ( !test_bit(0,&busy_flag) || iminor(ino) != zft_unit) {
- TRACE(ft_t_err, "failed: not busy or wrong unit");
- TRACE_EXIT 0;
- }
- sigfillset(&current->blocked);
- result = _zft_close();
- if (result < 0) {
- TRACE(ft_t_err, "_zft_close failed");
- }
- current->blocked = orig_sigmask; /* restore before open state */
- clear_bit(0,&busy_flag);
- TRACE_EXIT 0;
-}
-
-/* Ioctl for floppy tape device
- */
-static int zft_ioctl(struct inode *ino, struct file *filep,
- unsigned int command, unsigned long arg)
-{
- int result = -EIO;
- sigset_t old_sigmask;
- TRACE_FUN(ft_t_flow);
-
- if ( !test_bit(0,&busy_flag) || iminor(ino) != zft_unit || ft_failure) {
- TRACE_ABORT(-EIO, ft_t_err,
- "failed: not busy, failure or wrong unit");
- }
- old_sigmask = current->blocked; /* save mask */
- sigfillset(&current->blocked);
- /* This will work as long as sizeof(void *) == sizeof(long) */
- result = _zft_ioctl(command, (void __user *) arg);
- current->blocked = old_sigmask; /* restore mask */
- TRACE_EXIT result;
-}
-
-/* Ioctl for floppy tape device
- */
-static int zft_mmap(struct file *filep, struct vm_area_struct *vma)
-{
- int result = -EIO;
- sigset_t old_sigmask;
- TRACE_FUN(ft_t_flow);
-
- if ( !test_bit(0,&busy_flag) ||
- iminor(filep->f_dentry->d_inode) != zft_unit ||
- ft_failure)
- {
- TRACE_ABORT(-EIO, ft_t_err,
- "failed: not busy, failure or wrong unit");
- }
- old_sigmask = current->blocked; /* save mask */
- sigfillset(&current->blocked);
- if ((result = ftape_mmap(vma)) >= 0) {
-#ifndef MSYNC_BUG_WAS_FIXED
- static struct vm_operations_struct dummy = { NULL, };
- vma->vm_ops = &dummy;
-#endif
- }
- current->blocked = old_sigmask; /* restore mask */
- TRACE_EXIT result;
-}
-
-/* Read from floppy tape device
- */
-static ssize_t zft_read(struct file *fp, char __user *buff,
- size_t req_len, loff_t *ppos)
-{
- int result = -EIO;
- sigset_t old_sigmask;
- struct inode *ino = fp->f_dentry->d_inode;
- TRACE_FUN(ft_t_flow);
-
- TRACE(ft_t_data_flow, "called with count: %ld", (unsigned long)req_len);
- if (!test_bit(0,&busy_flag) || iminor(ino) != zft_unit || ft_failure) {
- TRACE_ABORT(-EIO, ft_t_err,
- "failed: not busy, failure or wrong unit");
- }
- old_sigmask = current->blocked; /* save mask */
- sigfillset(&current->blocked);
- result = _zft_read(buff, req_len);
- current->blocked = old_sigmask; /* restore mask */
- TRACE(ft_t_data_flow, "return with count: %d", result);
- TRACE_EXIT result;
-}
-
-/* Write to tape device
- */
-static ssize_t zft_write(struct file *fp, const char __user *buff,
- size_t req_len, loff_t *ppos)
-{
- int result = -EIO;
- sigset_t old_sigmask;
- struct inode *ino = fp->f_dentry->d_inode;
- TRACE_FUN(ft_t_flow);
-
- TRACE(ft_t_flow, "called with count: %ld", (unsigned long)req_len);
- if (!test_bit(0,&busy_flag) || iminor(ino) != zft_unit || ft_failure) {
- TRACE_ABORT(-EIO, ft_t_err,
- "failed: not busy, failure or wrong unit");
- }
- old_sigmask = current->blocked; /* save mask */
- sigfillset(&current->blocked);
- result = _zft_write(buff, req_len);
- current->blocked = old_sigmask; /* restore mask */
- TRACE(ft_t_data_flow, "return with count: %d", result);
- TRACE_EXIT result;
-}
-
-/* END OF VFS INTERFACE
- *
- *****************************************************************************/
-
-/* driver/module initialization
- */
-
-/* the compression module has to call this function to hook into the zftape
- * code
- */
-int zft_cmpr_register(struct zft_cmpr_ops *new_ops)
-{
- TRACE_FUN(ft_t_flow);
-
- if (zft_cmpr_ops != NULL) {
- TRACE_EXIT -EBUSY;
- } else {
- zft_cmpr_ops = new_ops;
- TRACE_EXIT 0;
- }
-}
-
-/* lock the zft-compressor() module.
- */
-int zft_cmpr_lock(int try_to_load)
-{
- if (zft_cmpr_ops == NULL) {
-#ifdef CONFIG_KMOD
- if (try_to_load) {
- request_module("zft-compressor");
- if (zft_cmpr_ops == NULL) {
- return -ENOSYS;
- }
- } else {
- return -ENOSYS;
- }
-#else
- return -ENOSYS;
-#endif
- }
- (*zft_cmpr_ops->lock)();
- return 0;
-}
-
-#ifdef CONFIG_ZFT_COMPRESSOR
-extern int zft_compressor_init(void);
-#endif
-
-/* Called by modules package when installing the driver or by kernel
- * during the initialization phase
- */
-int __init zft_init(void)
-{
- int i;
- TRACE_FUN(ft_t_flow);
-
-#ifdef MODULE
- printk(KERN_INFO ZFTAPE_VERSION "\n");
- if (TRACE_LEVEL >= ft_t_info) {
- printk(
-KERN_INFO
-"(c) 1996, 1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de)\n"
-KERN_INFO
-"vfs interface for ftape floppy tape driver.\n"
-KERN_INFO
-"Support for QIC-113 compatible volume table, dynamic memory allocation\n"
-KERN_INFO
-"and builtin compression (lzrw3 algorithm).\n");
- }
-#else /* !MODULE */
- /* print a short no-nonsense boot message */
- printk(KERN_INFO ZFTAPE_VERSION "\n");
-#endif /* MODULE */
- TRACE(ft_t_info, "zft_init @ 0x%p", zft_init);
- TRACE(ft_t_info,
- "installing zftape VFS interface for ftape driver ...");
- TRACE_CATCH(register_chrdev(QIC117_TAPE_MAJOR, "zft", &zft_cdev),);
-
- zft_class = class_create(THIS_MODULE, "zft");
- for (i = 0; i < 4; i++) {
- class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i), NULL, "qft%i", i);
- class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 4), NULL, "nqft%i", i);
- class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 16), NULL, "zqft%i", i);
- class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 20), NULL, "nzqft%i", i);
- class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 32), NULL, "rawqft%i", i);
- class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 36), NULL, "nrawrawqft%i", i);
- }
-
-#ifdef CONFIG_ZFT_COMPRESSOR
- (void)zft_compressor_init();
-#endif
- zft_status = ftape_get_status(); /* fetch global data of ftape
- * hardware driver
- */
- TRACE_EXIT 0;
-}
-
-
-/* Called by modules package when removing the driver
- */
-static void zft_exit(void)
-{
- int i;
- TRACE_FUN(ft_t_flow);
-
- if (unregister_chrdev(QIC117_TAPE_MAJOR, "zft") != 0) {
- TRACE(ft_t_warn, "failed");
- } else {
- TRACE(ft_t_info, "successful");
- }
- for (i = 0; i < 4; i++) {
- class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i));
- class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 4));
- class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 16));
- class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 20));
- class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 32));
- class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 36));
- }
- class_destroy(zft_class);
- zft_uninit_mem(); /* release remaining memory, if any */
- printk(KERN_INFO "zftape successfully unloaded.\n");
- TRACE_EXIT;
-}
-
-module_init(zft_init);
-module_exit(zft_exit);
diff --git a/drivers/char/ftape/zftape/zftape-init.h b/drivers/char/ftape/zftape/zftape-init.h
deleted file mode 100644
index 937e5d48c20e..000000000000
--- a/drivers/char/ftape/zftape/zftape-init.h
+++ /dev/null
@@ -1,77 +0,0 @@
-#ifndef _ZFTAPE_INIT_H
-#define _ZFTAPE_INIT_H
-
-/*
- * Copyright (C) 1996, 1997 Claus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-init.h,v $
- * $Revision: 1.2 $
- * $Date: 1997/10/05 19:19:05 $
- *
- * This file contains definitions and macro for the vfs
- * interface defined by zftape
- *
- */
-
-#include <linux/ftape-header-segment.h>
-
-#include "../lowlevel/ftape-tracing.h"
-#include "../lowlevel/ftape-ctl.h"
-#include "../lowlevel/ftape-read.h"
-#include "../lowlevel/ftape-write.h"
-#include "../lowlevel/ftape-bsm.h"
-#include "../lowlevel/ftape-io.h"
-#include "../lowlevel/ftape-buffer.h"
-#include "../lowlevel/ftape-format.h"
-
-#include "../zftape/zftape-rw.h"
-
-#ifdef MODULE
-#define ftape_status (*zft_status)
-#endif
-
-extern const ftape_info *zft_status; /* needed for zftape-vtbl.h */
-
-#include "../zftape/zftape-vtbl.h"
-
-struct zft_cmpr_ops {
- int (*write)(int *write_cnt,
- __u8 *dst_buf, const int seg_sz,
- const __u8 __user *src_buf, const int req_len,
- const zft_position *pos, const zft_volinfo *volume);
- int (*read)(int *read_cnt,
- __u8 __user *dst_buf, const int req_len,
- const __u8 *src_buf, const int seg_sz,
- const zft_position *pos, const zft_volinfo *volume);
- int (*seek)(unsigned int new_block_pos,
- zft_position *pos, const zft_volinfo *volume,
- __u8 *buffer);
- void (*lock) (void);
- void (*reset) (void);
- void (*cleanup)(void);
-};
-
-extern struct zft_cmpr_ops *zft_cmpr_ops;
-/* zftape-init.c defined global functions.
- */
-extern int zft_cmpr_register(struct zft_cmpr_ops *new_ops);
-extern int zft_cmpr_lock(int try_to_load);
-
-#endif
-
-
diff --git a/drivers/char/ftape/zftape/zftape-read.c b/drivers/char/ftape/zftape/zftape-read.c
deleted file mode 100644
index 214bf03dce68..000000000000
--- a/drivers/char/ftape/zftape/zftape-read.c
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * Copyright (C) 1996, 1997 Claus-Justus Heine
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-read.c,v $
- * $Revision: 1.2 $
- * $Date: 1997/10/05 19:19:06 $
- *
- * This file contains the high level reading code
- * for the QIC-117 floppy-tape driver for Linux.
- */
-
-#include <linux/errno.h>
-#include <linux/mm.h>
-
-#include <linux/zftape.h>
-
-#include <asm/uaccess.h>
-
-#include "../zftape/zftape-init.h"
-#include "../zftape/zftape-eof.h"
-#include "../zftape/zftape-ctl.h"
-#include "../zftape/zftape-write.h"
-#include "../zftape/zftape-read.h"
-#include "../zftape/zftape-rw.h"
-#include "../zftape/zftape-vtbl.h"
-
-/* Global vars.
- */
-int zft_just_before_eof;
-
-/* Local vars.
- */
-static int buf_len_rd;
-
-void zft_zap_read_buffers(void)
-{
- buf_len_rd = 0;
-}
-
-int zft_read_header_segments(void)
-{
- TRACE_FUN(ft_t_flow);
-
- zft_header_read = 0;
- TRACE_CATCH(zft_vmalloc_once(&zft_hseg_buf, FT_SEGMENT_SIZE),);
- TRACE_CATCH(ftape_read_header_segment(zft_hseg_buf),);
- TRACE(ft_t_info, "Segments written since first format: %d",
- (int)GET4(zft_hseg_buf, FT_SEG_CNT));
- zft_qic113 = (ft_format_code != fmt_normal &&
- ft_format_code != fmt_1100ft &&
- ft_format_code != fmt_425ft);
- TRACE(ft_t_info, "ft_first_data_segment: %d, ft_last_data_segment: %d",
- ft_first_data_segment, ft_last_data_segment);
- zft_capacity = zft_get_capacity();
- zft_old_ftape = zft_ftape_validate_label(&zft_hseg_buf[FT_LABEL]);
- if (zft_old_ftape) {
- TRACE(ft_t_info,
-"Found old ftaped tape, emulating eof marks, entering read-only mode");
- zft_ftape_extract_file_marks(zft_hseg_buf);
- TRACE_CATCH(zft_fake_volume_headers(zft_eof_map,
- zft_nr_eof_marks),);
- } else {
- /* the specs say that the volume table must be
- * initialized with zeroes during formatting, so it
- * MUST be readable, i.e. contain vaid ECC
- * information.
- */
- TRACE_CATCH(ftape_read_segment(ft_first_data_segment,
- zft_deblock_buf,
- FT_RD_SINGLE),);
- TRACE_CATCH(zft_extract_volume_headers(zft_deblock_buf),);
- }
- zft_header_read = 1;
- zft_set_flags(zft_unit);
- zft_reset_position(&zft_pos);
- TRACE_EXIT 0;
-}
-
-int zft_fetch_segment_fraction(const unsigned int segment, void *buffer,
- const ft_read_mode_t read_mode,
- const unsigned int start,
- const unsigned int size)
-{
- int seg_sz;
- TRACE_FUN(ft_t_flow);
-
- if (segment == zft_deblock_segment) {
- TRACE(ft_t_data_flow,
- "re-using segment %d already in deblock buffer",
- segment);
- seg_sz = zft_get_seg_sz(segment);
- if (start > seg_sz) {
- TRACE_ABORT(-EINVAL, ft_t_bug,
- "trying to read beyond end of segment:\n"
- KERN_INFO "seg_sz : %d\n"
- KERN_INFO "start : %d\n"
- KERN_INFO "segment: %d",
- seg_sz, start, segment);
- }
- if ((start + size) > seg_sz) {
- TRACE_EXIT seg_sz - start;
- }
- TRACE_EXIT size;
- }
- seg_sz = ftape_read_segment_fraction(segment, buffer, read_mode,
- start, size);
- TRACE(ft_t_data_flow, "segment %d, result %d", segment, seg_sz);
- if ((int)seg_sz >= 0 && start == 0 && size == FT_SEGMENT_SIZE) {
- /* this implicitly assumes that we are always called with
- * buffer == zft_deblock_buf
- */
- zft_deblock_segment = segment;
- } else {
- zft_deblock_segment = -1;
- }
- TRACE_EXIT seg_sz;
-}
-
-/*
- * out:
- *
- * int *read_cnt: the number of bytes we removed from the
- * zft_deblock_buf (result)
- *
- * int *to_do : the remaining size of the read-request. Is changed.
- *
- * in:
- *
- * char *buff : buff is the address of the upper part of the user
- * buffer, that hasn't been filled with data yet.
- * int buf_pos_read: copy of buf_pos_rd
- * int buf_len_read: copy of buf_len_rd
- * char *zft_deblock_buf: ftape_zft_deblock_buf
- *
- * returns the amount of data actually copied to the user-buffer
- *
- * to_do MUST NOT SHRINK except to indicate an EOT. In this case to_do
- * has to be set to 0. We cannot return -ENOSPC, because we return the
- * amount of data actually * copied to the user-buffer
- */
-static int zft_simple_read (int *read_cnt,
- __u8 __user *dst_buf,
- const int to_do,
- const __u8 *src_buf,
- const int seg_sz,
- const zft_position *pos,
- const zft_volinfo *volume)
-{
- TRACE_FUN(ft_t_flow);
-
- if (seg_sz - pos->seg_byte_pos < to_do) {
- *read_cnt = seg_sz - pos->seg_byte_pos;
- } else {
- *read_cnt = to_do;
- }
- if (copy_to_user(dst_buf,
- src_buf + pos->seg_byte_pos, *read_cnt) != 0) {
- TRACE_EXIT -EFAULT;
- }
- TRACE(ft_t_noise, "nr bytes just read: %d", *read_cnt);
- TRACE_EXIT *read_cnt;
-}
-
-/* req_len: gets clipped due to EOT of EOF.
- * req_clipped: is a flag indicating whether req_len was clipped or not
- * volume: contains information on current volume (blk_sz etc.)
- */
-static int check_read_access(int *req_len,
- const zft_volinfo **volume,
- int *req_clipped,
- const zft_position *pos)
-{
- static __s64 remaining;
- static int eod;
- TRACE_FUN(ft_t_flow);
-
- if (zft_io_state != zft_reading) {
- if (zft_offline) { /* offline includes no_tape */
- TRACE_ABORT(-ENXIO, ft_t_warn,
- "tape is offline or no cartridge");
- }
- if (!ft_formatted) {
- TRACE_ABORT(-EACCES,
- ft_t_warn, "tape is not formatted");
- }
- /* now enter defined state, read header segment if not
- * already done and flush write buffers
- */
- TRACE_CATCH(zft_def_idle_state(),);
- zft_io_state = zft_reading;
- if (zft_tape_at_eod(pos)) {
- eod = 1;
- TRACE_EXIT 1;
- }
- eod = 0;
- *volume = zft_find_volume(pos->seg_pos);
- /* get the space left until EOF */
- remaining = zft_check_for_eof(*volume, pos);
- buf_len_rd = 0;
- TRACE(ft_t_noise, "remaining: " LL_X ", vol_no: %d",
- LL(remaining), (*volume)->count);
- } else if (zft_tape_at_eod(pos)) {
- if (++eod > 2) {
- TRACE_EXIT -EIO; /* st.c also returns -EIO */
- } else {
- TRACE_EXIT 1;
- }
- }
- if ((*req_len % (*volume)->blk_sz) != 0) {
- /* this message is informational only. The user gets the
- * proper return value
- */
- TRACE_ABORT(-EINVAL, ft_t_info,
- "req_len %d not a multiple of block size %d",
- *req_len, (*volume)->blk_sz);
- }
- /* As GNU tar doesn't accept partial read counts when the
- * multiple volume flag is set, we make sure to return the
- * requested amount of data. Except, of course, at the end of
- * the tape or file mark.
- */
- remaining -= *req_len;
- if (remaining <= 0) {
- TRACE(ft_t_noise,
- "clipped request from %d to %d.",
- *req_len, (int)(*req_len + remaining));
- *req_len += remaining;
- *req_clipped = 1;
- } else {
- *req_clipped = 0;
- }
- TRACE_EXIT 0;
-}
-
-/* this_segs_size: the current segment's size.
- * buff: the USER-SPACE buffer provided by the calling function.
- * req_len: how much data should be read at most.
- * volume: contains information on current volume (blk_sz etc.)
- */
-static int empty_deblock_buf(__u8 __user *usr_buf, const int req_len,
- const __u8 *src_buf, const int seg_sz,
- zft_position *pos,
- const zft_volinfo *volume)
-{
- int cnt;
- int result = 0;
- TRACE_FUN(ft_t_flow);
-
- TRACE(ft_t_data_flow, "this_segs_size: %d", seg_sz);
- if (zft_use_compression && volume->use_compression) {
- TRACE_CATCH(zft_cmpr_lock(1 /* try to load */),);
- TRACE_CATCH(result= (*zft_cmpr_ops->read)(&cnt,
- usr_buf, req_len,
- src_buf, seg_sz,
- pos, volume),);
- } else {
- TRACE_CATCH(result= zft_simple_read (&cnt,
- usr_buf, req_len,
- src_buf, seg_sz,
- pos, volume),);
- }
- pos->volume_pos += result;
- pos->tape_pos += cnt;
- pos->seg_byte_pos += cnt;
- buf_len_rd -= cnt; /* remaining bytes in buffer */
- TRACE(ft_t_data_flow, "buf_len_rd: %d, cnt: %d", buf_len_rd, cnt);
- if(pos->seg_byte_pos >= seg_sz) {
- pos->seg_pos++;
- pos->seg_byte_pos = 0;
- }
- TRACE(ft_t_data_flow, "bytes moved out of deblock-buffer: %d", cnt);
- TRACE_EXIT result;
-}
-
-
-/* note: we store the segment id of the segment that is inside the
- * deblock buffer. This spares a lot of ftape_read_segment()s when we
- * use small block-sizes. The block-size may be 1kb (SECTOR_SIZE). In
- * this case a MTFSR 28 maybe still inside the same segment.
- */
-int _zft_read(char __user *buff, int req_len)
-{
- int req_clipped;
- int result = 0;
- int bytes_read = 0;
- static unsigned int seg_sz = 0;
- static const zft_volinfo *volume = NULL;
- TRACE_FUN(ft_t_flow);
-
- zft_resid = req_len;
- result = check_read_access(&req_len, &volume,
- &req_clipped, &zft_pos);
- switch(result) {
- case 0:
- break; /* nothing special */
- case 1:
- TRACE(ft_t_noise, "EOD reached");
- TRACE_EXIT 0; /* EOD */
- default:
- TRACE_ABORT(result, ft_t_noise,
- "check_read_access() failed with result %d",
- result);
- TRACE_EXIT result;
- }
- while (req_len > 0) {
- /* Allow escape from this loop on signal !
- */
- FT_SIGNAL_EXIT(_DONT_BLOCK);
- /* buf_len_rd == 0 means that we need to read a new
- * segment.
- */
- if (buf_len_rd == 0) {
- while((result = zft_fetch_segment(zft_pos.seg_pos,
- zft_deblock_buf,
- FT_RD_AHEAD)) == 0) {
- zft_pos.seg_pos ++;
- zft_pos.seg_byte_pos = 0;
- }
- if (result < 0) {
- zft_resid -= bytes_read;
- TRACE_ABORT(result, ft_t_noise,
- "zft_fetch_segment(): %d",
- result);
- }
- seg_sz = result;
- buf_len_rd = seg_sz - zft_pos.seg_byte_pos;
- }
- TRACE_CATCH(result = empty_deblock_buf(buff,
- req_len,
- zft_deblock_buf,
- seg_sz,
- &zft_pos,
- volume),
- zft_resid -= bytes_read);
- TRACE(ft_t_data_flow, "bytes just read: %d", result);
- bytes_read += result; /* what we got so far */
- buff += result; /* index in user-buffer */
- req_len -= result; /* what's left from req_len */
- } /* while (req_len > 0) */
- if (req_clipped) {
- TRACE(ft_t_data_flow,
- "maybe partial count because of eof mark");
- if (zft_just_before_eof && bytes_read == 0) {
- /* req_len was > 0, but user didn't get
- * anything the user has read in the eof-mark
- */
- zft_move_past_eof(&zft_pos);
- ftape_abort_operation();
- } else {
- /* don't skip to the next file before the user
- * tried to read a second time past EOF Just
- * mark that we are at EOF and maybe decrement
- * zft_seg_pos to stay in the same volume;
- */
- zft_just_before_eof = 1;
- zft_position_before_eof(&zft_pos, volume);
- TRACE(ft_t_noise, "just before eof");
- }
- }
- zft_resid -= result; /* for MTSTATUS */
- TRACE_EXIT bytes_read;
-}
diff --git a/drivers/char/ftape/zftape/zftape-read.h b/drivers/char/ftape/zftape/zftape-read.h
deleted file mode 100644
index 42941de0c23a..000000000000
--- a/drivers/char/ftape/zftape/zftape-read.h
+++ /dev/null
@@ -1,53 +0,0 @@
-#ifndef _ZFTAPE_READ_H
-#define _ZFTAPE_READ_H
-
-/*
- * Copyright (C) 1996, 1997 Claus-Justus Heine
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-read.h,v $
- * $Revision: 1.2 $
- * $Date: 1997/10/05 19:19:07 $
- *
- * This file contains the definitions for the read functions
- * for the zftape driver for Linux.
- *
- */
-
-#include "../lowlevel/ftape-read.h"
-
-/* ftape-read.c defined global vars.
- */
-extern int zft_just_before_eof;
-
-/* ftape-read.c defined global functions.
- */
-extern void zft_zap_read_buffers(void);
-extern int zft_read_header_segments(void);
-extern int zft_fetch_segment_fraction(const unsigned int segment,
- void *buffer,
- const ft_read_mode_t read_mode,
- const unsigned int start,
- const unsigned int size);
-#define zft_fetch_segment(segment, address, read_mode) \
- zft_fetch_segment_fraction(segment, address, read_mode, \
- 0, FT_SEGMENT_SIZE)
-/* hook for the VFS interface
- */
-extern int _zft_read(char __user *buff, int req_len);
-
-#endif /* _ZFTAPE_READ_H */
diff --git a/drivers/char/ftape/zftape/zftape-rw.c b/drivers/char/ftape/zftape/zftape-rw.c
deleted file mode 100644
index dab634686885..000000000000
--- a/drivers/char/ftape/zftape/zftape-rw.c
+++ /dev/null
@@ -1,375 +0,0 @@
-/*
- * Copyright (C) 1996, 1997 Claus-Justus Heine
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-rw.c,v $
- * $Revision: 1.2 $
- * $Date: 1997/10/05 19:19:08 $
- *
- * This file contains some common code for the r/w code for
- * zftape.
- */
-
-#include <linux/errno.h>
-#include <linux/mm.h>
-
-#include <linux/zftape.h>
-#include "../zftape/zftape-init.h"
-#include "../zftape/zftape-eof.h"
-#include "../zftape/zftape-ctl.h"
-#include "../zftape/zftape-write.h"
-#include "../zftape/zftape-read.h"
-#include "../zftape/zftape-rw.h"
-#include "../zftape/zftape-vtbl.h"
-
-/* Global vars.
- */
-
-__u8 *zft_deblock_buf;
-__u8 *zft_hseg_buf;
-int zft_deblock_segment = -1;
-zft_status_enum zft_io_state = zft_idle;
-int zft_header_changed;
-int zft_qic113; /* conform to old specs. and old zftape */
-int zft_use_compression;
-zft_position zft_pos = {
- -1, /* seg_pos */
- 0, /* seg_byte_pos */
- 0, /* tape_pos */
- 0 /* volume_pos */
-};
-unsigned int zft_blk_sz = CONFIG_ZFT_DFLT_BLK_SZ;
-__s64 zft_capacity;
-
-unsigned int zft_written_segments;
-int zft_label_changed;
-
-/* Local vars.
- */
-
-unsigned int zft_get_seg_sz(unsigned int segment)
-{
- int size;
- TRACE_FUN(ft_t_any);
-
- size = FT_SEGMENT_SIZE -
- count_ones(ftape_get_bad_sector_entry(segment))*FT_SECTOR_SIZE;
- if (size > 0) {
- TRACE_EXIT (unsigned)size;
- } else {
- TRACE_EXIT 0;
- }
-}
-
-/* ftape_set_flags(). Claus-Justus Heine, 1994/1995
- */
-void zft_set_flags(unsigned minor_unit)
-{
- TRACE_FUN(ft_t_flow);
-
- zft_use_compression = zft_qic_mode = 0;
- switch (minor_unit & ZFT_MINOR_OP_MASK) {
- case (ZFT_Q80_MODE | ZFT_ZIP_MODE):
- case ZFT_ZIP_MODE:
- zft_use_compression = 1;
- case 0:
- case ZFT_Q80_MODE:
- zft_qic_mode = 1;
- if (zft_mt_compression) { /* override the default */
- zft_use_compression = 1;
- }
- break;
- case ZFT_RAW_MODE:
- TRACE(ft_t_noise, "switching to raw mode");
- break;
- default:
- TRACE(ft_t_warn, "Warning:\n"
- KERN_INFO "Wrong combination of minor device bits.\n"
- KERN_INFO "Switching to raw read-only mode.");
- zft_write_protected = 1;
- break;
- }
- TRACE_EXIT;
-}
-
-/* computes the segment and byte offset inside the segment
- * corresponding to tape_pos.
- *
- * tape_pos gives the offset in bytes from the beginning of the
- * ft_first_data_segment *seg_byte_pos is the offset in the current
- * segment in bytes
- *
- * Of, if this routine was called often one should cache the last data
- * pos it was called with, but actually this is only needed in
- * ftape_seek_block(), that is, almost never.
- */
-int zft_calc_seg_byte_coord(int *seg_byte_pos, __s64 tape_pos)
-{
- int segment;
- int seg_sz;
- TRACE_FUN(ft_t_flow);
-
- if (tape_pos == 0) {
- *seg_byte_pos = 0;
- segment = ft_first_data_segment;
- } else {
- seg_sz = 0;
-
- for (segment = ft_first_data_segment;
- ((tape_pos > 0) && (segment <= ft_last_data_segment));
- segment++) {
- seg_sz = zft_get_seg_sz(segment);
- tape_pos -= seg_sz;
- }
- if(tape_pos >= 0) {
- /* the case tape_pos > != 0 means that the
- * argument tape_pos lies beyond the EOT.
- */
- *seg_byte_pos= 0;
- } else { /* tape_pos < 0 */
- segment--;
- *seg_byte_pos= tape_pos + seg_sz;
- }
- }
- TRACE_EXIT(segment);
-}
-
-/* ftape_calc_tape_pos().
- *
- * computes the offset in bytes from the beginning of the
- * ft_first_data_segment inverse to ftape_calc_seg_byte_coord
- *
- * We should do some caching. But how:
- *
- * Each time the header segments are read in, this routine is called
- * with ft_tracks_per_tape*segments_per_track argumnet. So this should be
- * the time to reset the cache.
- *
- * Also, it might be in the future that the bad sector map gets
- * changed. -> reset the cache
- */
-static int seg_pos;
-static __s64 tape_pos;
-
-__s64 zft_get_capacity(void)
-{
- seg_pos = ft_first_data_segment;
- tape_pos = 0;
-
- while (seg_pos <= ft_last_data_segment) {
- tape_pos += zft_get_seg_sz(seg_pos ++);
- }
- return tape_pos;
-}
-
-__s64 zft_calc_tape_pos(int segment)
-{
- int d1, d2, d3;
- TRACE_FUN(ft_t_any);
-
- if (segment > ft_last_data_segment) {
- TRACE_EXIT zft_capacity;
- }
- if (segment < ft_first_data_segment) {
- TRACE_EXIT 0;
- }
- d2 = segment - seg_pos;
- if (-d2 > 10) {
- d1 = segment - ft_first_data_segment;
- if (-d2 > d1) {
- tape_pos = 0;
- seg_pos = ft_first_data_segment;
- d2 = d1;
- }
- }
- if (d2 > 10) {
- d3 = ft_last_data_segment - segment;
- if (d2 > d3) {
- tape_pos = zft_capacity;
- seg_pos = ft_last_data_segment + 1;
- d2 = -d3;
- }
- }
- if (d2 > 0) {
- while (seg_pos < segment) {
- tape_pos += zft_get_seg_sz(seg_pos++);
- }
- } else {
- while (seg_pos > segment) {
- tape_pos -= zft_get_seg_sz(--seg_pos);
- }
- }
- TRACE(ft_t_noise, "new cached pos: %d", seg_pos);
-
- TRACE_EXIT tape_pos;
-}
-
-/* copy Z-label string to buffer, keeps track of the correct offset in
- * `buffer'
- */
-void zft_update_label(__u8 *buffer)
-{
- TRACE_FUN(ft_t_flow);
-
- if (strncmp(&buffer[FT_LABEL], ZFTAPE_LABEL,
- sizeof(ZFTAPE_LABEL)-1) != 0) {
- TRACE(ft_t_info, "updating label from \"%s\" to \"%s\"",
- &buffer[FT_LABEL], ZFTAPE_LABEL);
- strcpy(&buffer[FT_LABEL], ZFTAPE_LABEL);
- memset(&buffer[FT_LABEL] + sizeof(ZFTAPE_LABEL) - 1, ' ',
- FT_LABEL_SZ - sizeof(ZFTAPE_LABEL + 1));
- PUT4(buffer, FT_LABEL_DATE, 0);
- zft_label_changed = zft_header_changed = 1; /* changed */
- }
- TRACE_EXIT;
-}
-
-int zft_verify_write_segments(unsigned int segment,
- __u8 *data, size_t size,
- __u8 *buffer)
-{
- int result;
- __u8 *write_buf;
- __u8 *src_buf;
- int single;
- int seg_pos;
- int seg_sz;
- int remaining;
- ft_write_mode_t write_mode;
- TRACE_FUN(ft_t_flow);
-
- seg_pos = segment;
- seg_sz = zft_get_seg_sz(seg_pos);
- src_buf = data;
- single = size <= seg_sz;
- remaining = size;
- do {
- TRACE(ft_t_noise, "\n"
- KERN_INFO "remaining: %d\n"
- KERN_INFO "seg_sz : %d\n"
- KERN_INFO "segment : %d",
- remaining, seg_sz, seg_pos);
- if (remaining == seg_sz) {
- write_buf = src_buf;
- write_mode = single ? FT_WR_SINGLE : FT_WR_MULTI;
- remaining = 0;
- } else if (remaining > seg_sz) {
- write_buf = src_buf;
- write_mode = FT_WR_ASYNC; /* don't start tape */
- remaining -= seg_sz;
- } else { /* remaining < seg_sz */
- write_buf = buffer;
- memcpy(write_buf, src_buf, remaining);
- memset(&write_buf[remaining],'\0',seg_sz-remaining);
- write_mode = single ? FT_WR_SINGLE : FT_WR_MULTI;
- remaining = 0;
- }
- if ((result = ftape_write_segment(seg_pos,
- write_buf,
- write_mode)) != seg_sz) {
- TRACE(ft_t_err, "Error: "
- "Couldn't write segment %d", seg_pos);
- TRACE_EXIT result < 0 ? result : -EIO; /* bail out */
- }
- zft_written_segments ++;
- seg_sz = zft_get_seg_sz(++seg_pos);
- src_buf += result;
- } while (remaining > 0);
- if (ftape_get_status()->fti_state == writing) {
- TRACE_CATCH(ftape_loop_until_writes_done(),);
- TRACE_CATCH(ftape_abort_operation(),);
- zft_prevent_flush();
- }
- seg_pos = segment;
- src_buf = data;
- remaining = size;
- do {
- TRACE_CATCH(result = ftape_read_segment(seg_pos, buffer,
- single ? FT_RD_SINGLE
- : FT_RD_AHEAD),);
- if (memcmp(src_buf, buffer,
- remaining > result ? result : remaining) != 0) {
- TRACE_ABORT(-EIO, ft_t_err,
- "Failed to verify written segment %d",
- seg_pos);
- }
- remaining -= result;
- TRACE(ft_t_noise, "verify successful:\n"
- KERN_INFO "segment : %d\n"
- KERN_INFO "segsize : %d\n"
- KERN_INFO "remaining: %d",
- seg_pos, result, remaining);
- src_buf += seg_sz;
- seg_pos++;
- } while (remaining > 0);
- TRACE_EXIT size;
-}
-
-
-/* zft_erase(). implemented compression-handling
- *
- * calculate the first data-segment when using/not using compression.
- *
- * update header-segment and compression-map-segment.
- */
-int zft_erase(void)
-{
- int result = 0;
- TRACE_FUN(ft_t_flow);
-
- if (!zft_header_read) {
- TRACE_CATCH(zft_vmalloc_once((void **)&zft_hseg_buf,
- FT_SEGMENT_SIZE),);
- /* no need to read the vtbl and compression map */
- TRACE_CATCH(ftape_read_header_segment(zft_hseg_buf),);
- if ((zft_old_ftape =
- zft_ftape_validate_label(&zft_hseg_buf[FT_LABEL]))) {
- zft_ftape_extract_file_marks(zft_hseg_buf);
- }
- TRACE(ft_t_noise,
- "ft_first_data_segment: %d, ft_last_data_segment: %d",
- ft_first_data_segment, ft_last_data_segment);
- zft_qic113 = (ft_format_code != fmt_normal &&
- ft_format_code != fmt_1100ft &&
- ft_format_code != fmt_425ft);
- }
- if (zft_old_ftape) {
- zft_clear_ftape_file_marks();
- zft_old_ftape = 0; /* no longer old ftape */
- }
- PUT2(zft_hseg_buf, FT_CMAP_START, 0);
- zft_volume_table_changed = 1;
- zft_capacity = zft_get_capacity();
- zft_init_vtbl();
- /* the rest must be done in ftape_update_header_segments
- */
- zft_header_read = 1;
- zft_header_changed = 1; /* force update of timestamp */
- result = zft_update_header_segments();
-
- ftape_abort_operation();
-
- zft_reset_position(&zft_pos);
- zft_set_flags (zft_unit);
- TRACE_EXIT result;
-}
-
-unsigned int zft_get_time(void)
-{
- unsigned int date = FT_TIME_STAMP(2097, 11, 30, 23, 59, 59); /* fun */
- return date;
-}
diff --git a/drivers/char/ftape/zftape/zftape-rw.h b/drivers/char/ftape/zftape/zftape-rw.h
deleted file mode 100644
index 1ceec22b60bd..000000000000
--- a/drivers/char/ftape/zftape/zftape-rw.h
+++ /dev/null
@@ -1,101 +0,0 @@
-#ifndef _ZFTAPE_RW_H
-#define _ZFTAPE_RW_H
-
-/*
- * Copyright (C) 1996, 1997 Claus-Justus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-rw.h,v $
- * $Revision: 1.2 $
- * $Date: 1997/10/05 19:19:09 $
- *
- * This file contains the definitions for the read and write
- * functions for the QIC-117 floppy-tape driver for Linux.
- *
- */
-
-#include "../zftape/zftape-buffers.h"
-
-#define SEGMENTS_PER_TAPE (ft_segments_per_track * ft_tracks_per_tape)
-
-/* QIC-113 Rev. G says that `a maximum of 63488 raw bytes may be
- * compressed into a single frame'.
- * Maybe we should stick to 32kb to make it more `beautiful'
- */
-#define ZFT_MAX_BLK_SZ (62*1024) /* bytes */
-#if !defined(CONFIG_ZFT_DFLT_BLK_SZ)
-# define CONFIG_ZFT_DFLT_BLK_SZ (10*1024) /* bytes, default of gnu tar */
-#elif CONFIG_ZFT_DFLT_BLK_SZ == 0
-# undef CONFIG_ZFT_DFLT_BLK_SZ
-# define CONFIG_ZFT_DFLT_BLK_SZ 1
-#elif (CONFIG_ZFT_DFLT_BLK_SZ % 1024) != 0
-# error CONFIG_ZFT_DFLT_BLK_SZ must be 1 or a multiple of 1024
-#endif
-/* The *optional* compression routines need some overhead per tape
- * block for their purposes. Instead of asking the actual compression
- * implementation how much it needs, we restrict this overhead to be
- * maximal of ZFT_CMPT_OVERHEAD size. We need this for EOT
- * conditions. The tape is assumed to be logical at EOT when the
- * distance from the physical EOT is less than
- * one tape block + ZFT_CMPR_OVERHEAD
- */
-#define ZFT_CMPR_OVERHEAD 16 /* bytes */
-
-typedef enum
-{
- zft_idle = 0,
- zft_reading,
- zft_writing,
-} zft_status_enum;
-
-typedef struct /* all values measured in bytes */
-{
- int seg_pos; /* segment currently positioned at */
- int seg_byte_pos; /* offset in current segment */
- __s64 tape_pos; /* real offset from BOT */
- __s64 volume_pos; /* pos. in uncompressed data stream in
- * current volume
- */
-} zft_position;
-
-extern zft_position zft_pos;
-extern __u8 *zft_deblock_buf;
-extern __u8 *zft_hseg_buf;
-extern int zft_deblock_segment;
-extern zft_status_enum zft_io_state;
-extern int zft_header_changed;
-extern int zft_qic113; /* conform to old specs. and old zftape */
-extern int zft_use_compression;
-extern unsigned int zft_blk_sz;
-extern __s64 zft_capacity;
-extern unsigned int zft_written_segments;
-extern int zft_label_changed;
-
-/* zftape-rw.c exported functions
- */
-extern unsigned int zft_get_seg_sz(unsigned int segment);
-extern void zft_set_flags(unsigned int minor_unit);
-extern int zft_calc_seg_byte_coord(int *seg_byte_pos, __s64 tape_pos);
-extern __s64 zft_calc_tape_pos(int segment);
-extern __s64 zft_get_capacity(void);
-extern void zft_update_label(__u8 *buffer);
-extern int zft_erase(void);
-extern int zft_verify_write_segments(unsigned int segment,
- __u8 *data, size_t size, __u8 *buffer);
-extern unsigned int zft_get_time(void);
-#endif /* _ZFTAPE_RW_H */
-
diff --git a/drivers/char/ftape/zftape/zftape-vtbl.c b/drivers/char/ftape/zftape/zftape-vtbl.c
deleted file mode 100644
index ad7f8be6340b..000000000000
--- a/drivers/char/ftape/zftape/zftape-vtbl.c
+++ /dev/null
@@ -1,757 +0,0 @@
-/*
- * Copyright (c) 1995-1997 Claus-Justus Heine
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
- USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-vtbl.c,v $
- * $Revision: 1.7.6.1 $
- * $Date: 1997/11/24 13:48:31 $
- *
- * This file defines a volume table as defined in various QIC
- * standards.
- *
- * This is a minimal implementation, just allowing ordinary DOS
- * :( prgrams to identify the cartridge as used.
- */
-
-#include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-
-#include <linux/zftape.h>
-#include "../zftape/zftape-init.h"
-#include "../zftape/zftape-eof.h"
-#include "../zftape/zftape-ctl.h"
-#include "../zftape/zftape-write.h"
-#include "../zftape/zftape-read.h"
-#include "../zftape/zftape-rw.h"
-#include "../zftape/zftape-vtbl.h"
-
-#define ZFT_CMAP_HACK /* leave this defined to hide the compression map */
-
-/*
- * global variables
- */
-int zft_qic_mode = 1; /* use the vtbl */
-int zft_old_ftape; /* prevents old ftaped tapes to be overwritten */
-int zft_volume_table_changed; /* for write_header_segments() */
-
-/*
- * private variables (only exported for inline functions)
- */
-LIST_HEAD(zft_vtbl);
-
-/* We could also allocate these dynamically when extracting the volume table
- * sizeof(zft_volinfo) is about 32 or something close to that
- */
-static zft_volinfo tape_vtbl;
-static zft_volinfo eot_vtbl;
-static zft_volinfo *cur_vtbl;
-
-static inline void zft_new_vtbl_entry(void)
-{
- struct list_head *tmp = &zft_last_vtbl->node;
- zft_volinfo *new = zft_kmalloc(sizeof(zft_volinfo));
-
- list_add(&new->node, tmp);
- new->count = zft_eom_vtbl->count ++;
-}
-
-void zft_free_vtbl(void)
-{
- for (;;) {
- struct list_head *tmp = zft_vtbl.prev;
- zft_volinfo *vtbl;
-
- if (tmp == &zft_vtbl)
- break;
- list_del(tmp);
- vtbl = list_entry(tmp, zft_volinfo, node);
- zft_kfree(vtbl, sizeof(zft_volinfo));
- }
- INIT_LIST_HEAD(&zft_vtbl);
- cur_vtbl = NULL;
-}
-
-/* initialize vtbl, called by ftape_new_cartridge()
- */
-void zft_init_vtbl(void)
-{
- zft_volinfo *new;
-
- zft_free_vtbl();
-
- /* Create the two dummy vtbl entries
- */
- new = zft_kmalloc(sizeof(zft_volinfo));
- list_add(&new->node, &zft_vtbl);
- new = zft_kmalloc(sizeof(zft_volinfo));
- list_add(&new->node, &zft_vtbl);
- zft_head_vtbl->end_seg = ft_first_data_segment;
- zft_head_vtbl->blk_sz = zft_blk_sz;
- zft_head_vtbl->count = -1;
- zft_eom_vtbl->start_seg = ft_first_data_segment + 1;
- zft_eom_vtbl->end_seg = ft_last_data_segment + 1;
- zft_eom_vtbl->blk_sz = zft_blk_sz;
- zft_eom_vtbl->count = 0;
-
- /* Reset the pointer for zft_find_volume()
- */
- cur_vtbl = zft_eom_vtbl;
-
- /* initialize the dummy vtbl entries for zft_qic_mode == 0
- */
- eot_vtbl.start_seg = ft_last_data_segment + 1;
- eot_vtbl.end_seg = ft_last_data_segment + 1;
- eot_vtbl.blk_sz = zft_blk_sz;
- eot_vtbl.count = -1;
- tape_vtbl.start_seg = ft_first_data_segment;
- tape_vtbl.end_seg = ft_last_data_segment;
- tape_vtbl.blk_sz = zft_blk_sz;
- tape_vtbl.size = zft_capacity;
- tape_vtbl.count = 0;
-}
-
-/* check for a valid VTBL signature.
- */
-static int vtbl_signature_valid(__u8 signature[4])
-{
- const char *vtbl_ids[] = VTBL_IDS; /* valid signatures */
- int j;
-
- for (j = 0;
- (j < NR_ITEMS(vtbl_ids)) && (memcmp(signature, vtbl_ids[j], 4) != 0);
- j++);
- return j < NR_ITEMS(vtbl_ids);
-}
-
-/* We used to store the block-size of the volume in the volume-label,
- * using the keyword "blocksize". The blocksize written to the
- * volume-label is in bytes.
- *
- * We use this now only for compatibility with old zftape version. We
- * store the blocksize directly as binary number in the vendor
- * extension part of the volume entry.
- */
-static int check_volume_label(const char *label, int *blk_sz)
-{
- int valid_format;
- char *blocksize;
- TRACE_FUN(ft_t_flow);
-
- TRACE(ft_t_noise, "called with \"%s\" / \"%s\"", label, ZFT_VOL_NAME);
- if (strncmp(label, ZFT_VOL_NAME, strlen(ZFT_VOL_NAME)) != 0) {
- *blk_sz = 1; /* smallest block size that we allow */
- valid_format = 0;
- } else {
- TRACE(ft_t_noise, "got old style zftape vtbl entry");
- /* get the default blocksize */
- /* use the kernel strstr() */
- blocksize= strstr(label, " blocksize ");
- if (blocksize) {
- blocksize += strlen(" blocksize ");
- for(*blk_sz= 0;
- *blocksize >= '0' && *blocksize <= '9';
- blocksize++) {
- *blk_sz *= 10;
- *blk_sz += *blocksize - '0';
- }
- if (*blk_sz > ZFT_MAX_BLK_SZ) {
- *blk_sz= 1;
- valid_format= 0;
- } else {
- valid_format = 1;
- }
- } else {
- *blk_sz= 1;
- valid_format= 0;
- }
- }
- TRACE_EXIT valid_format;
-}
-
-/* check for a zftape volume
- */
-static int check_volume(__u8 *entry, zft_volinfo *volume)
-{
- TRACE_FUN(ft_t_flow);
-
- if(strncmp(&entry[VTBL_EXT+EXT_ZFTAPE_SIG], ZFTAPE_SIG,
- strlen(ZFTAPE_SIG)) == 0) {
- TRACE(ft_t_noise, "got new style zftape vtbl entry");
- volume->blk_sz = GET2(entry, VTBL_EXT+EXT_ZFTAPE_BLKSZ);
- volume->qic113 = entry[VTBL_EXT+EXT_ZFTAPE_QIC113];
- TRACE_EXIT 1;
- } else {
- TRACE_EXIT check_volume_label(&entry[VTBL_DESC], &volume->blk_sz);
- }
-}
-
-
-/* create zftape specific vtbl entry, the volume bounds are inserted
- * in the calling function, zft_create_volume_headers()
- */
-static void create_zft_volume(__u8 *entry, zft_volinfo *vtbl)
-{
- TRACE_FUN(ft_t_flow);
-
- memset(entry, 0, VTBL_SIZE);
- memcpy(&entry[VTBL_SIG], VTBL_ID, 4);
- sprintf(&entry[VTBL_DESC], ZFT_VOL_NAME" %03d", vtbl->count);
- entry[VTBL_FLAGS] = (VTBL_FL_NOT_VERIFIED | VTBL_FL_SEG_SPANNING);
- entry[VTBL_M_NO] = 1; /* multi_cartridge_count */
- strcpy(&entry[VTBL_EXT+EXT_ZFTAPE_SIG], ZFTAPE_SIG);
- PUT2(entry, VTBL_EXT+EXT_ZFTAPE_BLKSZ, vtbl->blk_sz);
- if (zft_qic113) {
- PUT8(entry, VTBL_DATA_SIZE, vtbl->size);
- entry[VTBL_CMPR] = VTBL_CMPR_UNREG;
- if (vtbl->use_compression) { /* use compression: */
- entry[VTBL_CMPR] |= VTBL_CMPR_USED;
- }
- entry[VTBL_EXT+EXT_ZFTAPE_QIC113] = 1;
- } else {
- PUT4(entry, VTBL_DATA_SIZE, vtbl->size);
- entry[VTBL_K_CMPR] = VTBL_CMPR_UNREG;
- if (vtbl->use_compression) { /* use compression: */
- entry[VTBL_K_CMPR] |= VTBL_CMPR_USED;
- }
- }
- if (ft_format_code == fmt_big) {
- /* SCSI like vtbl, store the number of used
- * segments as 4 byte value
- */
- PUT4(entry, VTBL_SCSI_SEGS, vtbl->end_seg-vtbl->start_seg + 1);
- } else {
- /* normal, QIC-80MC like vtbl
- */
- PUT2(entry, VTBL_START, vtbl->start_seg);
- PUT2(entry, VTBL_END, vtbl->end_seg);
- }
- TRACE_EXIT;
-}
-
-/* this one creates the volume headers for each volume. It is assumed
- * that buffer already contains the old volume-table, so that vtbl
- * entries without the zft_volume flag set can savely be ignored.
- */
-static void zft_create_volume_headers(__u8 *buffer)
-{
- __u8 *entry;
- struct list_head *tmp;
- zft_volinfo *vtbl;
- TRACE_FUN(ft_t_flow);
-
-#ifdef ZFT_CMAP_HACK
- if((strncmp(&buffer[VTBL_EXT+EXT_ZFTAPE_SIG], ZFTAPE_SIG,
- strlen(ZFTAPE_SIG)) == 0) &&
- buffer[VTBL_EXT+EXT_ZFTAPE_CMAP] != 0) {
- TRACE(ft_t_noise, "deleting cmap volume");
- memmove(buffer, buffer + VTBL_SIZE,
- FT_SEGMENT_SIZE - VTBL_SIZE);
- }
-#endif
- entry = buffer;
- for (tmp = zft_head_vtbl->node.next;
- tmp != &zft_eom_vtbl->node;
- tmp = tmp->next) {
- vtbl = list_entry(tmp, zft_volinfo, node);
- /* we now fill in the values only for newly created volumes.
- */
- if (vtbl->new_volume) {
- create_zft_volume(entry, vtbl);
- vtbl->new_volume = 0; /* clear the flag */
- }
-
- DUMP_VOLINFO(ft_t_noise, &entry[VTBL_DESC], vtbl);
- entry += VTBL_SIZE;
- }
- memset(entry, 0, FT_SEGMENT_SIZE - zft_eom_vtbl->count * VTBL_SIZE);
- TRACE_EXIT;
-}
-
-/* write volume table to tape. Calls zft_create_volume_headers()
- */
-int zft_update_volume_table(unsigned int segment)
-{
- int result = 0;
- __u8 *verify_buf = NULL;
- TRACE_FUN(ft_t_flow);
-
- TRACE_CATCH(result = ftape_read_segment(ft_first_data_segment,
- zft_deblock_buf,
- FT_RD_SINGLE),);
- zft_create_volume_headers(zft_deblock_buf);
- TRACE(ft_t_noise, "writing volume table segment %d", segment);
- if (zft_vmalloc_once(&verify_buf, FT_SEGMENT_SIZE) == 0) {
- TRACE_CATCH(zft_verify_write_segments(segment,
- zft_deblock_buf, result,
- verify_buf),
- zft_vfree(&verify_buf, FT_SEGMENT_SIZE));
- zft_vfree(&verify_buf, FT_SEGMENT_SIZE);
- } else {
- TRACE_CATCH(ftape_write_segment(segment, zft_deblock_buf,
- FT_WR_SINGLE),);
- }
- TRACE_EXIT 0;
-}
-
-/* non zftape volumes are handled in raw mode. Thus we need to
- * calculate the raw amount of data contained in those segments.
- */
-static void extract_alien_volume(__u8 *entry, zft_volinfo *vtbl)
-{
- TRACE_FUN(ft_t_flow);
-
- vtbl->size = (zft_calc_tape_pos(zft_last_vtbl->end_seg+1) -
- zft_calc_tape_pos(zft_last_vtbl->start_seg));
- vtbl->use_compression = 0;
- vtbl->qic113 = zft_qic113;
- if (vtbl->qic113) {
- TRACE(ft_t_noise,
- "Fake alien volume's size from " LL_X " to " LL_X,
- LL(GET8(entry, VTBL_DATA_SIZE)), LL(vtbl->size));
- } else {
- TRACE(ft_t_noise,
- "Fake alien volume's size from %d to " LL_X,
- (int)GET4(entry, VTBL_DATA_SIZE), LL(vtbl->size));
- }
- TRACE_EXIT;
-}
-
-
-/* extract an zftape specific volume
- */
-static void extract_zft_volume(__u8 *entry, zft_volinfo *vtbl)
-{
- TRACE_FUN(ft_t_flow);
-
- if (vtbl->qic113) {
- vtbl->size = GET8(entry, VTBL_DATA_SIZE);
- vtbl->use_compression =
- (entry[VTBL_CMPR] & VTBL_CMPR_USED) != 0;
- } else {
- vtbl->size = GET4(entry, VTBL_DATA_SIZE);
- if (entry[VTBL_K_CMPR] & VTBL_CMPR_UNREG) {
- vtbl->use_compression =
- (entry[VTBL_K_CMPR] & VTBL_CMPR_USED) != 0;
- } else if (entry[VTBL_CMPR] & VTBL_CMPR_UNREG) {
- vtbl->use_compression =
- (entry[VTBL_CMPR] & VTBL_CMPR_USED) != 0;
- } else {
- TRACE(ft_t_warn, "Geeh! There is something wrong:\n"
- KERN_INFO "QIC compression (Rev = K): %x\n"
- KERN_INFO "QIC compression (Rev > K): %x",
- entry[VTBL_K_CMPR], entry[VTBL_CMPR]);
- }
- }
- TRACE_EXIT;
-}
-
-/* extract the volume table from buffer. "buffer" must already contain
- * the vtbl-segment
- */
-int zft_extract_volume_headers(__u8 *buffer)
-{
- __u8 *entry;
- TRACE_FUN(ft_t_flow);
-
- zft_init_vtbl();
- entry = buffer;
-#ifdef ZFT_CMAP_HACK
- if ((strncmp(&entry[VTBL_EXT+EXT_ZFTAPE_SIG], ZFTAPE_SIG,
- strlen(ZFTAPE_SIG)) == 0) &&
- entry[VTBL_EXT+EXT_ZFTAPE_CMAP] != 0) {
- TRACE(ft_t_noise, "ignoring cmap volume");
- entry += VTBL_SIZE;
- }
-#endif
- /* the end of the vtbl is indicated by an invalid signature
- */
- while (vtbl_signature_valid(&entry[VTBL_SIG]) &&
- (entry - buffer) < FT_SEGMENT_SIZE) {
- zft_new_vtbl_entry();
- if (ft_format_code == fmt_big) {
- /* SCSI like vtbl, stores only the number of
- * segments used
- */
- unsigned int num_segments= GET4(entry, VTBL_SCSI_SEGS);
- zft_last_vtbl->start_seg = zft_eom_vtbl->start_seg;
- zft_last_vtbl->end_seg =
- zft_last_vtbl->start_seg + num_segments - 1;
- } else {
- /* `normal', QIC-80 like vtbl
- */
- zft_last_vtbl->start_seg = GET2(entry, VTBL_START);
- zft_last_vtbl->end_seg = GET2(entry, VTBL_END);
- }
- zft_eom_vtbl->start_seg = zft_last_vtbl->end_seg + 1;
- /* check if we created this volume and get the
- * blk_sz
- */
- zft_last_vtbl->zft_volume = check_volume(entry, zft_last_vtbl);
- if (zft_last_vtbl->zft_volume == 0) {
- extract_alien_volume(entry, zft_last_vtbl);
- } else {
- extract_zft_volume(entry, zft_last_vtbl);
- }
- DUMP_VOLINFO(ft_t_noise, &entry[VTBL_DESC], zft_last_vtbl);
- entry +=VTBL_SIZE;
- }
-#if 0
-/*
- * undefine to test end of tape handling
- */
- zft_new_vtbl_entry();
- zft_last_vtbl->start_seg = zft_eom_vtbl->start_seg;
- zft_last_vtbl->end_seg = ft_last_data_segment - 10;
- zft_last_vtbl->blk_sz = zft_blk_sz;
- zft_last_vtbl->zft_volume = 1;
- zft_last_vtbl->qic113 = zft_qic113;
- zft_last_vtbl->size = (zft_calc_tape_pos(zft_last_vtbl->end_seg+1)
- - zft_calc_tape_pos(zft_last_vtbl->start_seg));
-#endif
- TRACE_EXIT 0;
-}
-
-/* this functions translates the failed_sector_log, misused as
- * EOF-marker list, into a virtual volume table. The table mustn't be
- * written to tape, because this would occupy the first data segment,
- * which should be the volume table, but is actually the first segment
- * that is filled with data (when using standard ftape). We assume,
- * that we get a non-empty failed_sector_log.
- */
-int zft_fake_volume_headers (eof_mark_union *eof_map, int num_failed_sectors)
-{
- unsigned int segment, sector;
- int have_eom = 0;
- int vol_no;
- TRACE_FUN(ft_t_flow);
-
- if ((num_failed_sectors >= 2) &&
- (GET2(&eof_map[num_failed_sectors - 1].mark.segment, 0)
- ==
- GET2(&eof_map[num_failed_sectors - 2].mark.segment, 0) + 1) &&
- (GET2(&eof_map[num_failed_sectors - 1].mark.date, 0) == 1)) {
- /* this should be eom. We keep the remainder of the
- * tape as another volume.
- */
- have_eom = 1;
- }
- zft_init_vtbl();
- zft_eom_vtbl->start_seg = ft_first_data_segment;
- for(vol_no = 0; vol_no < num_failed_sectors - have_eom; vol_no ++) {
- zft_new_vtbl_entry();
-
- segment = GET2(&eof_map[vol_no].mark.segment, 0);
- sector = GET2(&eof_map[vol_no].mark.date, 0);
-
- zft_last_vtbl->start_seg = zft_eom_vtbl->start_seg;
- zft_last_vtbl->end_seg = segment;
- zft_eom_vtbl->start_seg = segment + 1;
- zft_last_vtbl->blk_sz = 1;
- zft_last_vtbl->size =
- (zft_calc_tape_pos(zft_last_vtbl->end_seg)
- - zft_calc_tape_pos(zft_last_vtbl->start_seg)
- + (sector-1) * FT_SECTOR_SIZE);
- TRACE(ft_t_noise,
- "failed sector log: segment: %d, sector: %d",
- segment, sector);
- DUMP_VOLINFO(ft_t_noise, "Faked volume", zft_last_vtbl);
- }
- if (!have_eom) {
- zft_new_vtbl_entry();
- zft_last_vtbl->start_seg = zft_eom_vtbl->start_seg;
- zft_last_vtbl->end_seg = ft_last_data_segment;
- zft_eom_vtbl->start_seg = ft_last_data_segment + 1;
- zft_last_vtbl->size = zft_capacity;
- zft_last_vtbl->size -= zft_calc_tape_pos(zft_last_vtbl->start_seg);
- zft_last_vtbl->blk_sz = 1;
- DUMP_VOLINFO(ft_t_noise, "Faked volume",zft_last_vtbl);
- }
- TRACE_EXIT 0;
-}
-
-/* update the internal volume table
- *
- * if before start of last volume: erase all following volumes if
- * inside a volume: set end of volume to infinity
- *
- * this function is intended to be called every time _ftape_write() is
- * called
- *
- * return: 0 if no new volume was created, 1 if a new volume was
- * created
- *
- * NOTE: we don't need to check for zft_mode as ftape_write() does
- * that already. This function gets never called without accessing
- * zftape via the *qft* devices
- */
-
-int zft_open_volume(zft_position *pos, int blk_sz, int use_compression)
-{
- TRACE_FUN(ft_t_flow);
-
- if (!zft_qic_mode) {
- TRACE_EXIT 0;
- }
- if (zft_tape_at_lbot(pos)) {
- zft_init_vtbl();
- if(zft_old_ftape) {
- /* clear old ftape's eof marks */
- zft_clear_ftape_file_marks();
- zft_old_ftape = 0; /* no longer old ftape */
- }
- zft_reset_position(pos);
- }
- if (pos->seg_pos != zft_last_vtbl->end_seg + 1) {
- TRACE_ABORT(-EIO, ft_t_bug,
- "BUG: seg_pos: %d, zft_last_vtbl->end_seg: %d",
- pos->seg_pos, zft_last_vtbl->end_seg);
- }
- TRACE(ft_t_noise, "create new volume");
- if (zft_eom_vtbl->count >= ZFT_MAX_VOLUMES) {
- TRACE_ABORT(-ENOSPC, ft_t_err,
- "Error: maxmimal number of volumes exhausted "
- "(maxmimum is %d)", ZFT_MAX_VOLUMES);
- }
- zft_new_vtbl_entry();
- pos->volume_pos = pos->seg_byte_pos = 0;
- zft_last_vtbl->start_seg = pos->seg_pos;
- zft_last_vtbl->end_seg = ft_last_data_segment; /* infinity */
- zft_last_vtbl->blk_sz = blk_sz;
- zft_last_vtbl->size = zft_capacity;
- zft_last_vtbl->zft_volume = 1;
- zft_last_vtbl->use_compression = use_compression;
- zft_last_vtbl->qic113 = zft_qic113;
- zft_last_vtbl->new_volume = 1;
- zft_last_vtbl->open = 1;
- zft_volume_table_changed = 1;
- zft_eom_vtbl->start_seg = ft_last_data_segment + 1;
- TRACE_EXIT 0;
-}
-
-/* perform mtfsf, mtbsf, not allowed without zft_qic_mode
- */
-int zft_skip_volumes(int count, zft_position *pos)
-{
- const zft_volinfo *vtbl;
- TRACE_FUN(ft_t_flow);
-
- TRACE(ft_t_noise, "count: %d", count);
-
- vtbl= zft_find_volume(pos->seg_pos);
- while (count > 0 && vtbl != zft_eom_vtbl) {
- vtbl = list_entry(vtbl->node.next, zft_volinfo, node);
- count --;
- }
- while (count < 0 && vtbl != zft_first_vtbl) {
- vtbl = list_entry(vtbl->node.prev, zft_volinfo, node);
- count ++;
- }
- pos->seg_pos = vtbl->start_seg;
- pos->seg_byte_pos = 0;
- pos->volume_pos = 0;
- pos->tape_pos = zft_calc_tape_pos(pos->seg_pos);
- zft_just_before_eof = vtbl->size == 0;
- if (zft_cmpr_ops) {
- (*zft_cmpr_ops->reset)();
- }
- zft_deblock_segment = -1; /* no need to keep cache */
- TRACE(ft_t_noise, "repositioning to:\n"
- KERN_INFO "zft_seg_pos : %d\n"
- KERN_INFO "zft_seg_byte_pos : %d\n"
- KERN_INFO "zft_tape_pos : " LL_X "\n"
- KERN_INFO "zft_volume_pos : " LL_X "\n"
- KERN_INFO "file number : %d",
- pos->seg_pos, pos->seg_byte_pos,
- LL(pos->tape_pos), LL(pos->volume_pos), vtbl->count);
- zft_resid = count < 0 ? -count : count;
- TRACE_EXIT zft_resid ? -EINVAL : 0;
-}
-
-/* the following simply returns the raw data position of the EOM
- * marker, MTIOCSIZE ioctl
- */
-__s64 zft_get_eom_pos(void)
-{
- if (zft_qic_mode) {
- return zft_calc_tape_pos(zft_eom_vtbl->start_seg);
- } else {
- /* there is only one volume in raw mode */
- return zft_capacity;
- }
-}
-
-/* skip to eom, used for MTEOM
- */
-void zft_skip_to_eom(zft_position *pos)
-{
- TRACE_FUN(ft_t_flow);
- pos->seg_pos = zft_eom_vtbl->start_seg;
- pos->seg_byte_pos =
- pos->volume_pos =
- zft_just_before_eof = 0;
- pos->tape_pos = zft_calc_tape_pos(pos->seg_pos);
- TRACE(ft_t_noise, "ftape positioned to segment %d, data pos " LL_X,
- pos->seg_pos, LL(pos->tape_pos));
- TRACE_EXIT;
-}
-
-/* write an EOF-marker by setting zft_last_vtbl->end_seg to seg_pos.
- * NOTE: this function assumes that zft_last_vtbl points to a valid
- * vtbl entry
- *
- * NOTE: this routine always positions before the EOF marker
- */
-int zft_close_volume(zft_position *pos)
-{
- TRACE_FUN(ft_t_any);
-
- if (zft_vtbl_empty || !zft_last_vtbl->open) { /* should not happen */
- TRACE(ft_t_noise, "There are no volumes to finish");
- TRACE_EXIT -EIO;
- }
- if (pos->seg_byte_pos == 0 &&
- pos->seg_pos != zft_last_vtbl->start_seg) {
- pos->seg_pos --;
- pos->seg_byte_pos = zft_get_seg_sz(pos->seg_pos);
- }
- zft_last_vtbl->end_seg = pos->seg_pos;
- zft_last_vtbl->size = pos->volume_pos;
- zft_volume_table_changed = 1;
- zft_just_before_eof = 1;
- zft_eom_vtbl->start_seg = zft_last_vtbl->end_seg + 1;
- zft_last_vtbl->open = 0; /* closed */
- TRACE_EXIT 0;
-}
-
-/* write count file-marks at current position.
- *
- * The tape is positioned after the eof-marker, that is at byte 0 of
- * the segment following the eof-marker
- *
- * this function is only allowed in zft_qic_mode
- *
- * Only allowed when tape is at BOT or EOD.
- */
-int zft_weof(unsigned int count, zft_position *pos)
-{
-
- TRACE_FUN(ft_t_flow);
-
- if (!count) { /* write zero EOF marks should be a real no-op */
- TRACE_EXIT 0;
- }
- zft_volume_table_changed = 1;
- if (zft_tape_at_lbot(pos)) {
- zft_init_vtbl();
- if(zft_old_ftape) {
- /* clear old ftape's eof marks */
- zft_clear_ftape_file_marks();
- zft_old_ftape = 0; /* no longer old ftape */
- }
- }
- if (zft_last_vtbl->open) {
- zft_close_volume(pos);
- zft_move_past_eof(pos);
- count --;
- }
- /* now it's easy, just append eof-marks, that is empty
- * volumes, to the end of the already recorded media.
- */
- while (count > 0 &&
- pos->seg_pos <= ft_last_data_segment &&
- zft_eom_vtbl->count < ZFT_MAX_VOLUMES) {
- TRACE(ft_t_noise,
- "Writing zero sized file at segment %d", pos->seg_pos);
- zft_new_vtbl_entry();
- zft_last_vtbl->start_seg = pos->seg_pos;
- zft_last_vtbl->end_seg = pos->seg_pos;
- zft_last_vtbl->size = 0;
- zft_last_vtbl->blk_sz = zft_blk_sz;
- zft_last_vtbl->zft_volume = 1;
- zft_last_vtbl->use_compression = 0;
- pos->tape_pos += zft_get_seg_sz(pos->seg_pos);
- zft_eom_vtbl->start_seg = ++ pos->seg_pos;
- count --;
- }
- if (count > 0) {
- /* there are two possibilities: end of tape, or the
- * maximum number of files is exhausted.
- */
- zft_resid = count;
- TRACE(ft_t_noise,"Number of marks NOT written: %d", zft_resid);
- if (zft_eom_vtbl->count == ZFT_MAX_VOLUMES) {
- TRACE_ABORT(-EINVAL, ft_t_warn,
- "maximum allowed number of files "
- "exhausted: %d", ZFT_MAX_VOLUMES);
- } else {
- TRACE_ABORT(-ENOSPC,
- ft_t_noise, "reached end of tape");
- }
- }
- TRACE_EXIT 0;
-}
-
-const zft_volinfo *zft_find_volume(unsigned int seg_pos)
-{
- TRACE_FUN(ft_t_flow);
-
- TRACE(ft_t_any, "called with seg_pos %d",seg_pos);
- if (!zft_qic_mode) {
- if (seg_pos > ft_last_data_segment) {
- TRACE_EXIT &eot_vtbl;
- }
- tape_vtbl.blk_sz = zft_blk_sz;
- TRACE_EXIT &tape_vtbl;
- }
- if (seg_pos < zft_first_vtbl->start_seg) {
- TRACE_EXIT (cur_vtbl = zft_first_vtbl);
- }
- while (seg_pos > cur_vtbl->end_seg) {
- cur_vtbl = list_entry(cur_vtbl->node.next, zft_volinfo, node);
- TRACE(ft_t_noise, "%d - %d", cur_vtbl->start_seg, cur_vtbl->end_seg);
- }
- while (seg_pos < cur_vtbl->start_seg) {
- cur_vtbl = list_entry(cur_vtbl->node.prev, zft_volinfo, node);
- TRACE(ft_t_noise, "%d - %d", cur_vtbl->start_seg, cur_vtbl->end_seg);
- }
- if (seg_pos > cur_vtbl->end_seg || seg_pos < cur_vtbl->start_seg) {
- TRACE(ft_t_bug, "This cannot happen");
- }
- DUMP_VOLINFO(ft_t_noise, "", cur_vtbl);
- TRACE_EXIT cur_vtbl;
-}
-
-/* this function really assumes that we are just before eof
- */
-void zft_move_past_eof(zft_position *pos)
-{
- TRACE_FUN(ft_t_flow);
-
- TRACE(ft_t_noise, "old seg. pos: %d", pos->seg_pos);
- pos->tape_pos += zft_get_seg_sz(pos->seg_pos++) - pos->seg_byte_pos;
- pos->seg_byte_pos = 0;
- pos->volume_pos = 0;
- if (zft_cmpr_ops) {
- (*zft_cmpr_ops->reset)();
- }
- zft_just_before_eof = 0;
- zft_deblock_segment = -1; /* no need to cache it anymore */
- TRACE(ft_t_noise, "new seg. pos: %d", pos->seg_pos);
- TRACE_EXIT;
-}
diff --git a/drivers/char/ftape/zftape/zftape-vtbl.h b/drivers/char/ftape/zftape/zftape-vtbl.h
deleted file mode 100644
index f31d196d1759..000000000000
--- a/drivers/char/ftape/zftape/zftape-vtbl.h
+++ /dev/null
@@ -1,227 +0,0 @@
-#ifndef _ZFTAPE_VTBL_H
-#define _ZFTAPE_VTBL_H
-
-/*
- * Copyright (c) 1995-1997 Claus-Justus Heine
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
- USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-vtbl.h,v $
- * $Revision: 1.3 $
- * $Date: 1997/10/28 14:30:09 $
- *
- * This file defines a volume table as defined in the QIC-80
- * development standards.
- */
-
-#include <linux/list.h>
-
-#include "../lowlevel/ftape-tracing.h"
-
-#include "../zftape/zftape-eof.h"
-#include "../zftape/zftape-ctl.h"
-#include "../zftape/zftape-rw.h"
-
-#define VTBL_SIZE 128 /* bytes */
-
-/* The following are offsets in the vtbl. */
-#define VTBL_SIG 0
-#define VTBL_START 4
-#define VTBL_END 6
-#define VTBL_DESC 8
-#define VTBL_DATE 52
-#define VTBL_FLAGS 56
-#define VTBL_FL_VENDOR_SPECIFIC (1<<0)
-#define VTBL_FL_MUTLI_CARTRIDGE (1<<1)
-#define VTBL_FL_NOT_VERIFIED (1<<2)
-#define VTBL_FL_REDIR_INHIBIT (1<<3)
-#define VTBL_FL_SEG_SPANNING (1<<4)
-#define VTBL_FL_DIRECTORY_LAST (1<<5)
-#define VTBL_FL_RESERVED_6 (1<<6)
-#define VTBL_FL_RESERVED_7 (1<<7)
-#define VTBL_M_NO 57
-#define VTBL_EXT 58
-#define EXT_ZFTAPE_SIG 0
-#define EXT_ZFTAPE_BLKSZ 10
-#define EXT_ZFTAPE_CMAP 12
-#define EXT_ZFTAPE_QIC113 13
-#define VTBL_PWD 84
-#define VTBL_DIR_SIZE 92
-#define VTBL_DATA_SIZE 96
-#define VTBL_OS_VERSION 104
-#define VTBL_SRC_DRIVE 106
-#define VTBL_DEV 122
-#define VTBL_RESERVED_1 123
-#define VTBL_CMPR 124
-#define VTBL_CMPR_UNREG 0x3f
-#define VTBL_CMPR_USED 0x80
-#define VTBL_FMT 125
-#define VTBL_RESERVED_2 126
-#define VTBL_RESERVED_3 127
-/* compatibility with pre revision K */
-#define VTBL_K_CMPR 120
-
-/* the next is used by QIC-3020 tapes with format code 6 (>2^16
- * segments) It is specified in QIC-113, Rev. G, Section 5 (SCSI
- * volume table). The difference is simply, that we only store the
- * number of segments used, not the starting segment.
- */
-#define VTBL_SCSI_SEGS 4 /* is a 4 byte value */
-
-/* one vtbl is 128 bytes, that results in a maximum number of
- * 29*1024/128 = 232 volumes.
- */
-#define ZFT_MAX_VOLUMES (FT_SEGMENT_SIZE/VTBL_SIZE)
-#define VTBL_ID "VTBL"
-#define VTBL_IDS { VTBL_ID, "XTBL", "UTID", "EXVT" } /* other valid ids */
-#define ZFT_VOL_NAME "zftape volume" /* volume label used by me */
-#define ZFTAPE_SIG "LINUX ZFT"
-
-/* global variables
- */
-typedef struct zft_internal_vtbl
-{
- struct list_head node;
- int count;
- unsigned int start_seg; /* 32 bits are enough for now */
- unsigned int end_seg; /* 32 bits are enough for now */
- __s64 size; /* uncompressed size */
- unsigned int blk_sz; /* block size for this volume */
- unsigned int zft_volume :1; /* zftape created this volume */
- unsigned int use_compression:1; /* compressed volume */
- unsigned int qic113 :1; /* layout of compressed block
- * info and vtbl conforms to
- * QIC-113, Rev. G
- */
- unsigned int new_volume :1; /* it was created by us, this
- * run. this allows the
- * fields that aren't really
- * used by zftape to be filled
- * in by some user level
- * program.
- */
- unsigned int open :1; /* just in progress of being
- * written
- */
-} zft_volinfo;
-
-extern struct list_head zft_vtbl;
-#define zft_head_vtbl list_entry(zft_vtbl.next, zft_volinfo, node)
-#define zft_eom_vtbl list_entry(zft_vtbl.prev, zft_volinfo, node)
-#define zft_last_vtbl list_entry(zft_eom_vtbl->node.prev, zft_volinfo, node)
-#define zft_first_vtbl list_entry(zft_head_vtbl->node.next, zft_volinfo, node)
-#define zft_vtbl_empty (zft_eom_vtbl->node.prev == &zft_head_vtbl->node)
-
-#define DUMP_VOLINFO(level, desc, info) \
-{ \
- char tmp[21]; \
- strlcpy(tmp, desc, sizeof(tmp)); \
- TRACE(level, "Volume %d:\n" \
- KERN_INFO "description : %s\n" \
- KERN_INFO "first segment: %d\n" \
- KERN_INFO "last segment: %d\n" \
- KERN_INFO "size : " LL_X "\n" \
- KERN_INFO "block size : %d\n" \
- KERN_INFO "compression : %d\n" \
- KERN_INFO "zftape volume: %d\n" \
- KERN_INFO "QIC-113 conf.: %d", \
- (info)->count, tmp, (info)->start_seg, (info)->end_seg, \
- LL((info)->size), (info)->blk_sz, \
- (info)->use_compression != 0, (info)->zft_volume != 0, \
- (info)->qic113 != 0); \
-}
-
-extern int zft_qic_mode;
-extern int zft_old_ftape;
-extern int zft_volume_table_changed;
-
-/* exported functions */
-extern void zft_init_vtbl (void);
-extern void zft_free_vtbl (void);
-extern int zft_extract_volume_headers(__u8 *buffer);
-extern int zft_update_volume_table (unsigned int segment);
-extern int zft_open_volume (zft_position *pos,
- int blk_sz, int use_compression);
-extern int zft_close_volume (zft_position *pos);
-extern const zft_volinfo *zft_find_volume(unsigned int seg_pos);
-extern int zft_skip_volumes (int count, zft_position *pos);
-extern __s64 zft_get_eom_pos (void);
-extern void zft_skip_to_eom (zft_position *pos);
-extern int zft_fake_volume_headers (eof_mark_union *eof_map,
- int num_failed_sectors);
-extern int zft_weof (unsigned int count, zft_position *pos);
-extern void zft_move_past_eof (zft_position *pos);
-
-static inline int zft_tape_at_eod (const zft_position *pos);
-static inline int zft_tape_at_lbot (const zft_position *pos);
-static inline void zft_position_before_eof (zft_position *pos,
- const zft_volinfo *volume);
-static inline __s64 zft_check_for_eof(const zft_volinfo *vtbl,
- const zft_position *pos);
-
-/* this function decrements the zft_seg_pos counter if we are right
- * at the beginning of a segment. This is to handle fsfm/bsfm -- we
- * need to position before the eof mark. NOTE: zft_tape_pos is not
- * changed
- */
-static inline void zft_position_before_eof(zft_position *pos,
- const zft_volinfo *volume)
-{
- TRACE_FUN(ft_t_flow);
-
- if (pos->seg_pos == volume->end_seg + 1 && pos->seg_byte_pos == 0) {
- pos->seg_pos --;
- pos->seg_byte_pos = zft_get_seg_sz(pos->seg_pos);
- }
- TRACE_EXIT;
-}
-
-/* Mmmh. Is the position at the end of the last volume, that is right
- * before the last EOF mark also logical an EOD condition?
- */
-static inline int zft_tape_at_eod(const zft_position *pos)
-{
- TRACE_FUN(ft_t_any);
-
- if (zft_qic_mode) {
- TRACE_EXIT (pos->seg_pos >= zft_eom_vtbl->start_seg ||
- zft_last_vtbl->open);
- } else {
- TRACE_EXIT pos->seg_pos > ft_last_data_segment;
- }
-}
-
-static inline int zft_tape_at_lbot(const zft_position *pos)
-{
- if (zft_qic_mode) {
- return (pos->seg_pos <= zft_first_vtbl->start_seg &&
- pos->volume_pos == 0);
- } else {
- return (pos->seg_pos <= ft_first_data_segment &&
- pos->volume_pos == 0);
- }
-}
-
-/* This one checks for EOF. return remaing space (may be negative)
- */
-static inline __s64 zft_check_for_eof(const zft_volinfo *vtbl,
- const zft_position *pos)
-{
- return (__s64)(vtbl->size - pos->volume_pos);
-}
-
-#endif /* _ZFTAPE_VTBL_H */
diff --git a/drivers/char/ftape/zftape/zftape-write.c b/drivers/char/ftape/zftape/zftape-write.c
deleted file mode 100644
index 94327b8c97b9..000000000000
--- a/drivers/char/ftape/zftape/zftape-write.c
+++ /dev/null
@@ -1,483 +0,0 @@
-/*
- * Copyright (C) 1996, 1997 Claus Heine
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-write.c,v $
- * $Revision: 1.3 $
- * $Date: 1997/11/06 00:50:29 $
- *
- * This file contains the writing code
- * for the QIC-117 floppy-tape driver for Linux.
- */
-
-#include <linux/errno.h>
-#include <linux/mm.h>
-
-#include <linux/zftape.h>
-
-#include <asm/uaccess.h>
-
-#include "../zftape/zftape-init.h"
-#include "../zftape/zftape-eof.h"
-#include "../zftape/zftape-ctl.h"
-#include "../zftape/zftape-write.h"
-#include "../zftape/zftape-read.h"
-#include "../zftape/zftape-rw.h"
-#include "../zftape/zftape-vtbl.h"
-
-/* Global vars.
- */
-
-/* Local vars.
- */
-static int last_write_failed;
-static int need_flush;
-
-void zft_prevent_flush(void)
-{
- need_flush = 0;
-}
-
-static int zft_write_header_segments(__u8* buffer)
-{
- int header_1_ok = 0;
- int header_2_ok = 0;
- unsigned int time_stamp;
- TRACE_FUN(ft_t_noise);
-
- TRACE_CATCH(ftape_abort_operation(),);
- ftape_seek_to_bot(); /* prevents extra rewind */
- if (GET4(buffer, 0) != FT_HSEG_MAGIC) {
- TRACE_ABORT(-EIO, ft_t_err,
- "wrong header signature found, aborting");
- }
- /* Be optimistic: */
- PUT4(buffer, FT_SEG_CNT,
- zft_written_segments + GET4(buffer, FT_SEG_CNT) + 2);
- if ((time_stamp = zft_get_time()) != 0) {
- PUT4(buffer, FT_WR_DATE, time_stamp);
- if (zft_label_changed) {
- PUT4(buffer, FT_LABEL_DATE, time_stamp);
- }
- }
- TRACE(ft_t_noise,
- "writing first header segment %d", ft_header_segment_1);
- header_1_ok = zft_verify_write_segments(ft_header_segment_1,
- buffer, FT_SEGMENT_SIZE,
- zft_deblock_buf) >= 0;
- TRACE(ft_t_noise,
- "writing second header segment %d", ft_header_segment_2);
- header_2_ok = zft_verify_write_segments(ft_header_segment_2,
- buffer, FT_SEGMENT_SIZE,
- zft_deblock_buf) >= 0;
- if (!header_1_ok) {
- TRACE(ft_t_warn, "Warning: "
- "update of first header segment failed");
- }
- if (!header_2_ok) {
- TRACE(ft_t_warn, "Warning: "
- "update of second header segment failed");
- }
- if (!header_1_ok && !header_2_ok) {
- TRACE_ABORT(-EIO, ft_t_err, "Error: "
- "update of both header segments failed.");
- }
- TRACE_EXIT 0;
-}
-
-int zft_update_header_segments(void)
-{
- TRACE_FUN(ft_t_noise);
-
- /* must NOT use zft_write_protected, as it also includes the
- * file access mode. But we also want to update when soft
- * write protection is enabled (O_RDONLY)
- */
- if (ft_write_protected || zft_old_ftape) {
- TRACE_ABORT(0, ft_t_noise, "Tape set read-only: no update");
- }
- if (!zft_header_read) {
- TRACE_ABORT(0, ft_t_noise, "Nothing to update");
- }
- if (!zft_header_changed) {
- zft_header_changed = zft_written_segments > 0;
- }
- if (!zft_header_changed && !zft_volume_table_changed) {
- TRACE_ABORT(0, ft_t_noise, "Nothing to update");
- }
- TRACE(ft_t_noise, "Updating header segments");
- if (ftape_get_status()->fti_state == writing) {
- TRACE_CATCH(ftape_loop_until_writes_done(),);
- }
- TRACE_CATCH(ftape_abort_operation(),);
-
- zft_deblock_segment = -1; /* invalidate the cache */
- if (zft_header_changed) {
- TRACE_CATCH(zft_write_header_segments(zft_hseg_buf),);
- }
- if (zft_volume_table_changed) {
- TRACE_CATCH(zft_update_volume_table(ft_first_data_segment),);
- }
- zft_header_changed =
- zft_volume_table_changed =
- zft_label_changed =
- zft_written_segments = 0;
- TRACE_CATCH(ftape_abort_operation(),);
- ftape_seek_to_bot();
- TRACE_EXIT 0;
-}
-
-static int read_merge_buffer(int seg_pos, __u8 *buffer, int offset, int seg_sz)
-{
- int result = 0;
- const ft_trace_t old_tracing = TRACE_LEVEL;
- TRACE_FUN(ft_t_flow);
-
- if (zft_qic_mode) {
- /* writing in the middle of a volume is NOT allowed
- *
- */
- TRACE(ft_t_noise, "No need to read a segment");
- memset(buffer + offset, 0, seg_sz - offset);
- TRACE_EXIT 0;
- }
- TRACE(ft_t_any, "waiting");
- ftape_start_writing(FT_WR_MULTI);
- TRACE_CATCH(ftape_loop_until_writes_done(),);
-
- TRACE(ft_t_noise, "trying to read segment %d from offset %d",
- seg_pos, offset);
- SET_TRACE_LEVEL(ft_t_bug);
- result = zft_fetch_segment_fraction(seg_pos, buffer,
- FT_RD_SINGLE,
- offset, seg_sz - offset);
- SET_TRACE_LEVEL(old_tracing);
- if (result != (seg_sz - offset)) {
- TRACE(ft_t_noise, "Ignore error: read_segment() result: %d",
- result);
- memset(buffer + offset, 0, seg_sz - offset);
- }
- TRACE_EXIT 0;
-}
-
-/* flush the write buffer to tape and write an eof-marker at the
- * current position if not in raw mode. This function always
- * positions the tape before the eof-marker. _ftape_close() should
- * then advance to the next segment.
- *
- * the parameter "finish_volume" describes whether to position before
- * or after the possibly created file-mark. We always position after
- * the file-mark when called from ftape_close() and a flush was needed
- * (that is ftape_write() was the last tape operation before calling
- * ftape_flush) But we always position before the file-mark when this
- * function get's called from outside ftape_close()
- */
-int zft_flush_buffers(void)
-{
- int result;
- int data_remaining;
- int this_segs_size;
- TRACE_FUN(ft_t_flow);
-
- TRACE(ft_t_data_flow,
- "entered, ftape_state = %d", ftape_get_status()->fti_state);
- if (ftape_get_status()->fti_state != writing && !need_flush) {
- TRACE_ABORT(0, ft_t_noise, "no need for flush");
- }
- zft_io_state = zft_idle; /* triggers some initializations for the
- * read and write routines
- */
- if (last_write_failed) {
- ftape_abort_operation();
- TRACE_EXIT -EIO;
- }
- TRACE(ft_t_noise, "flushing write buffers");
- this_segs_size = zft_get_seg_sz(zft_pos.seg_pos);
- if (this_segs_size == zft_pos.seg_byte_pos) {
- zft_pos.seg_pos ++;
- data_remaining = zft_pos.seg_byte_pos = 0;
- } else {
- data_remaining = zft_pos.seg_byte_pos;
- }
- /* If there is any data not written to tape yet, append zero's
- * up to the end of the sector (if using compression) or merge
- * it with the data existing on the tape Then write the
- * segment(s) to tape.
- */
- TRACE(ft_t_noise, "Position:\n"
- KERN_INFO "seg_pos : %d\n"
- KERN_INFO "byte pos : %d\n"
- KERN_INFO "remaining: %d",
- zft_pos.seg_pos, zft_pos.seg_byte_pos, data_remaining);
- if (data_remaining > 0) {
- do {
- this_segs_size = zft_get_seg_sz(zft_pos.seg_pos);
- if (this_segs_size > data_remaining) {
- TRACE_CATCH(read_merge_buffer(zft_pos.seg_pos,
- zft_deblock_buf,
- data_remaining,
- this_segs_size),
- last_write_failed = 1);
- }
- result = ftape_write_segment(zft_pos.seg_pos,
- zft_deblock_buf,
- FT_WR_MULTI);
- if (result != this_segs_size) {
- TRACE(ft_t_err, "flush buffers failed");
- zft_pos.tape_pos -= zft_pos.seg_byte_pos;
- zft_pos.seg_byte_pos = 0;
-
- last_write_failed = 1;
- TRACE_EXIT result;
- }
- zft_written_segments ++;
- TRACE(ft_t_data_flow,
- "flush, moved out buffer: %d", result);
- /* need next segment for more data (empty segments?)
- */
- if (result < data_remaining) {
- if (result > 0) {
- /* move remainder to buffer beginning
- */
- memmove(zft_deblock_buf,
- zft_deblock_buf + result,
- FT_SEGMENT_SIZE - result);
- }
- }
- data_remaining -= result;
- zft_pos.seg_pos ++;
- } while (data_remaining > 0);
- TRACE(ft_t_any, "result: %d", result);
- zft_deblock_segment = --zft_pos.seg_pos;
- if (data_remaining == 0) { /* first byte next segment */
- zft_pos.seg_byte_pos = this_segs_size;
- } else { /* after data previous segment, data_remaining < 0 */
- zft_pos.seg_byte_pos = data_remaining + result;
- }
- } else {
- TRACE(ft_t_noise, "zft_deblock_buf empty");
- zft_pos.seg_pos --;
- zft_pos.seg_byte_pos = zft_get_seg_sz (zft_pos.seg_pos);
- ftape_start_writing(FT_WR_MULTI);
- }
- TRACE(ft_t_any, "waiting");
- if ((result = ftape_loop_until_writes_done()) < 0) {
- /* that's really bad. What to to with zft_tape_pos?
- */
- TRACE(ft_t_err, "flush buffers failed");
- }
- TRACE(ft_t_any, "zft_seg_pos: %d, zft_seg_byte_pos: %d",
- zft_pos.seg_pos, zft_pos.seg_byte_pos);
- last_write_failed =
- need_flush = 0;
- TRACE_EXIT result;
-}
-
-/* return-value: the number of bytes removed from the user-buffer
- *
- * out:
- * int *write_cnt: how much actually has been moved to the
- * zft_deblock_buf
- * int req_len : MUST NOT BE CHANGED, except at EOT, in
- * which case it may be adjusted
- * in :
- * char *buff : the user buffer
- * int buf_pos_write : copy of buf_len_wr int
- * this_segs_size : the size in bytes of the actual segment
- * char
- * *zft_deblock_buf : zft_deblock_buf
- */
-static int zft_simple_write(int *cnt,
- __u8 *dst_buf, const int seg_sz,
- const __u8 __user *src_buf, const int req_len,
- const zft_position *pos,const zft_volinfo *volume)
-{
- int space_left;
- TRACE_FUN(ft_t_flow);
-
- /* volume->size holds the tape capacity while volume is open */
- if (pos->tape_pos + volume->blk_sz > volume->size) {
- TRACE_EXIT -ENOSPC;
- }
- /* remaining space in this segment, NOT zft_deblock_buf
- */
- space_left = seg_sz - pos->seg_byte_pos;
- *cnt = req_len < space_left ? req_len : space_left;
- if (copy_from_user(dst_buf + pos->seg_byte_pos, src_buf, *cnt) != 0) {
- TRACE_EXIT -EFAULT;
- }
- TRACE_EXIT *cnt;
-}
-
-static int check_write_access(int req_len,
- const zft_volinfo **volume,
- zft_position *pos,
- const unsigned int blk_sz)
-{
- int result;
- TRACE_FUN(ft_t_flow);
-
- if ((req_len % zft_blk_sz) != 0) {
- TRACE_ABORT(-EINVAL, ft_t_info,
- "write-count %d must be multiple of block-size %d",
- req_len, blk_sz);
- }
- if (zft_io_state == zft_writing) {
- /* all other error conditions have been checked earlier
- */
- TRACE_EXIT 0;
- }
- zft_io_state = zft_idle;
- TRACE_CATCH(zft_check_write_access(pos),);
- /* If we haven't read the header segment yet, do it now.
- * This will verify the configuration, get the bad sector
- * table and read the volume table segment
- */
- if (!zft_header_read) {
- TRACE_CATCH(zft_read_header_segments(),);
- }
- /* fine. Now the tape is either at BOT or at EOD,
- * Write start of volume now
- */
- TRACE_CATCH(zft_open_volume(pos, blk_sz, zft_use_compression),);
- *volume = zft_find_volume(pos->seg_pos);
- DUMP_VOLINFO(ft_t_noise, "", *volume);
- zft_just_before_eof = 0;
- /* now merge with old data if necessary */
- if (!zft_qic_mode && pos->seg_byte_pos != 0){
- result = zft_fetch_segment(pos->seg_pos,
- zft_deblock_buf,
- FT_RD_SINGLE);
- if (result < 0) {
- if (result == -EINTR || result == -ENOSPC) {
- TRACE_EXIT result;
- }
- TRACE(ft_t_noise,
- "ftape_read_segment() result: %d. "
- "This might be normal when using "
- "a newly\nformatted tape", result);
- memset(zft_deblock_buf, '\0', pos->seg_byte_pos);
- }
- }
- zft_io_state = zft_writing;
- TRACE_EXIT 0;
-}
-
-static int fill_deblock_buf(__u8 *dst_buf, const int seg_sz,
- zft_position *pos, const zft_volinfo *volume,
- const char __user *usr_buf, const int req_len)
-{
- int cnt = 0;
- int result = 0;
- TRACE_FUN(ft_t_flow);
-
- if (seg_sz == 0) {
- TRACE_ABORT(0, ft_t_data_flow, "empty segment");
- }
- TRACE(ft_t_data_flow, "\n"
- KERN_INFO "remaining req_len: %d\n"
- KERN_INFO " buf_pos: %d",
- req_len, pos->seg_byte_pos);
- /* zft_deblock_buf will not contain a valid segment any longer */
- zft_deblock_segment = -1;
- if (zft_use_compression) {
- TRACE_CATCH(zft_cmpr_lock(1 /* try to load */),);
- TRACE_CATCH(result= (*zft_cmpr_ops->write)(&cnt,
- dst_buf, seg_sz,
- usr_buf, req_len,
- pos, volume),);
- } else {
- TRACE_CATCH(result= zft_simple_write(&cnt,
- dst_buf, seg_sz,
- usr_buf, req_len,
- pos, volume),);
- }
- pos->volume_pos += result;
- pos->seg_byte_pos += cnt;
- pos->tape_pos += cnt;
- TRACE(ft_t_data_flow, "\n"
- KERN_INFO "removed from user-buffer : %d bytes.\n"
- KERN_INFO "copied to zft_deblock_buf: %d bytes.\n"
- KERN_INFO "zft_tape_pos : " LL_X " bytes.",
- result, cnt, LL(pos->tape_pos));
- TRACE_EXIT result;
-}
-
-
-/* called by the kernel-interface routine "zft_write()"
- */
-int _zft_write(const char __user *buff, int req_len)
-{
- int result = 0;
- int written = 0;
- int write_cnt;
- int seg_sz;
- static const zft_volinfo *volume = NULL;
- TRACE_FUN(ft_t_flow);
-
- zft_resid = req_len;
- last_write_failed = 1; /* reset to 0 when successful */
- /* check if write is allowed
- */
- TRACE_CATCH(check_write_access(req_len, &volume,&zft_pos,zft_blk_sz),);
- while (req_len > 0) {
- /* Allow us to escape from this loop with a signal !
- */
- FT_SIGNAL_EXIT(_DONT_BLOCK);
- seg_sz = zft_get_seg_sz(zft_pos.seg_pos);
- if ((write_cnt = fill_deblock_buf(zft_deblock_buf,
- seg_sz,
- &zft_pos,
- volume,
- buff,
- req_len)) < 0) {
- zft_resid -= written;
- if (write_cnt == -ENOSPC) {
- /* leave the remainder to flush_buffers()
- */
- TRACE(ft_t_info, "No space left on device");
- last_write_failed = 0;
- if (!need_flush) {
- need_flush = written > 0;
- }
- TRACE_EXIT written > 0 ? written : -ENOSPC;
- } else {
- TRACE_EXIT result;
- }
- }
- if (zft_pos.seg_byte_pos == seg_sz) {
- TRACE_CATCH(ftape_write_segment(zft_pos.seg_pos,
- zft_deblock_buf,
- FT_WR_ASYNC),
- zft_resid -= written);
- zft_written_segments ++;
- zft_pos.seg_byte_pos = 0;
- zft_deblock_segment = zft_pos.seg_pos;
- ++zft_pos.seg_pos;
- }
- written += write_cnt;
- buff += write_cnt;
- req_len -= write_cnt;
- } /* while (req_len > 0) */
- TRACE(ft_t_data_flow, "remaining in blocking buffer: %d",
- zft_pos.seg_byte_pos);
- TRACE(ft_t_data_flow, "just written bytes: %d", written);
- last_write_failed = 0;
- zft_resid -= written;
- need_flush = need_flush || written > 0;
- TRACE_EXIT written; /* bytes written */
-}
diff --git a/drivers/char/ftape/zftape/zftape-write.h b/drivers/char/ftape/zftape/zftape-write.h
deleted file mode 100644
index ea887015b493..000000000000
--- a/drivers/char/ftape/zftape/zftape-write.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef _ZFTAPE_WRITE_H
-#define _ZFTAPE_WRITE_H
-
-/*
- * Copyright (C) 1996, 1997 Claus-Justus Heine
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-write.h,v $
- * $Revision: 1.2 $
- * $Date: 1997/10/05 19:19:13 $
- *
- * This file contains the definitions for the write functions
- * for the zftape driver for Linux.
- *
- */
-
-extern int zft_flush_buffers(void);
-extern int zft_update_header_segments(void);
-extern void zft_prevent_flush(void);
-
-/* hook for the VFS interface
- */
-extern int _zft_write(const char __user *buff, int req_len);
-#endif /* _ZFTAPE_WRITE_H */
diff --git a/drivers/char/ftape/zftape/zftape_syms.c b/drivers/char/ftape/zftape/zftape_syms.c
deleted file mode 100644
index 2db1401682df..000000000000
--- a/drivers/char/ftape/zftape/zftape_syms.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 1997 Claus-Justus Heine
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape_syms.c,v $
- * $Revision: 1.3 $
- * $Date: 1997/10/05 19:19:14 $
- *
- * This file contains the symbols that the zftape frontend to
- * the ftape floppy tape driver exports
- */
-
-#include <linux/module.h>
-
-#include <linux/zftape.h>
-
-#include "../zftape/zftape-init.h"
-#include "../zftape/zftape-read.h"
-#include "../zftape/zftape-buffers.h"
-#include "../zftape/zftape-ctl.h"
-
-/* zftape-init.c */
-EXPORT_SYMBOL(zft_cmpr_register);
-/* zftape-read.c */
-EXPORT_SYMBOL(zft_fetch_segment_fraction);
-/* zftape-buffers.c */
-EXPORT_SYMBOL(zft_vmalloc_once);
-EXPORT_SYMBOL(zft_vmalloc_always);
-EXPORT_SYMBOL(zft_vfree);
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
index 154a81d328c1..ebace201bec6 100644
--- a/drivers/char/hw_random/core.c
+++ b/drivers/char/hw_random/core.c
@@ -162,7 +162,8 @@ static struct miscdevice rng_miscdev = {
};
-static ssize_t hwrng_attr_current_store(struct class_device *class,
+static ssize_t hwrng_attr_current_store(struct device *dev,
+ struct device_attribute *attr,
const char *buf, size_t len)
{
int err;
@@ -192,7 +193,8 @@ static ssize_t hwrng_attr_current_store(struct class_device *class,
return err ? : len;
}
-static ssize_t hwrng_attr_current_show(struct class_device *class,
+static ssize_t hwrng_attr_current_show(struct device *dev,
+ struct device_attribute *attr,
char *buf)
{
int err;
@@ -210,7 +212,8 @@ static ssize_t hwrng_attr_current_show(struct class_device *class,
return ret;
}
-static ssize_t hwrng_attr_available_show(struct class_device *class,
+static ssize_t hwrng_attr_available_show(struct device *dev,
+ struct device_attribute *attr,
char *buf)
{
int err;
@@ -234,20 +237,18 @@ static ssize_t hwrng_attr_available_show(struct class_device *class,
return ret;
}
-static CLASS_DEVICE_ATTR(rng_current, S_IRUGO | S_IWUSR,
- hwrng_attr_current_show,
- hwrng_attr_current_store);
-static CLASS_DEVICE_ATTR(rng_available, S_IRUGO,
- hwrng_attr_available_show,
- NULL);
+static DEVICE_ATTR(rng_current, S_IRUGO | S_IWUSR,
+ hwrng_attr_current_show,
+ hwrng_attr_current_store);
+static DEVICE_ATTR(rng_available, S_IRUGO,
+ hwrng_attr_available_show,
+ NULL);
static void unregister_miscdev(void)
{
- class_device_remove_file(rng_miscdev.class,
- &class_device_attr_rng_available);
- class_device_remove_file(rng_miscdev.class,
- &class_device_attr_rng_current);
+ device_remove_file(rng_miscdev.this_device, &dev_attr_rng_available);
+ device_remove_file(rng_miscdev.this_device, &dev_attr_rng_current);
misc_deregister(&rng_miscdev);
}
@@ -258,20 +259,19 @@ static int register_miscdev(void)
err = misc_register(&rng_miscdev);
if (err)
goto out;
- err = class_device_create_file(rng_miscdev.class,
- &class_device_attr_rng_current);
+ err = device_create_file(rng_miscdev.this_device,
+ &dev_attr_rng_current);
if (err)
goto err_misc_dereg;
- err = class_device_create_file(rng_miscdev.class,
- &class_device_attr_rng_available);
+ err = device_create_file(rng_miscdev.this_device,
+ &dev_attr_rng_available);
if (err)
goto err_remove_current;
out:
return err;
err_remove_current:
- class_device_remove_file(rng_miscdev.class,
- &class_device_attr_rng_current);
+ device_remove_file(rng_miscdev.this_device, &dev_attr_rng_current);
err_misc_dereg:
misc_deregister(&rng_miscdev);
goto out;
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 55473371b7c6..e67eef4867ba 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -980,10 +980,10 @@ static int __init chr_dev_init(void)
mem_class = class_create(THIS_MODULE, "mem");
for (i = 0; i < ARRAY_SIZE(devlist); i++)
- class_device_create(mem_class, NULL,
- MKDEV(MEM_MAJOR, devlist[i].minor),
- NULL, devlist[i].name);
-
+ device_create(mem_class, NULL,
+ MKDEV(MEM_MAJOR, devlist[i].minor),
+ devlist[i].name);
+
return 0;
}
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index 62ebe09656e3..7a484fc7cb9e 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -169,11 +169,6 @@ fail:
return err;
}
-/*
- * TODO for 2.7:
- * - add a struct kref to struct miscdevice and make all usages of
- * them dynamic.
- */
static struct class *misc_class;
static const struct file_operations misc_fops = {
@@ -228,10 +223,10 @@ int misc_register(struct miscdevice * misc)
misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7);
dev = MKDEV(MISC_MAJOR, misc->minor);
- misc->class = class_device_create(misc_class, NULL, dev, misc->dev,
+ misc->this_device = device_create(misc_class, misc->parent, dev,
"%s", misc->name);
- if (IS_ERR(misc->class)) {
- err = PTR_ERR(misc->class);
+ if (IS_ERR(misc->this_device)) {
+ err = PTR_ERR(misc->this_device);
goto out;
}
@@ -264,7 +259,7 @@ int misc_deregister(struct miscdevice * misc)
down(&misc_sem);
list_del(&misc->list);
- class_device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor));
+ device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor));
if (i < DYNAMIC_MINORS && i>0) {
misc_minors[i>>3] &= ~(1 << (misc->minor & 7));
}
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index efc485edad1c..c1e3dd837fc8 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -752,13 +752,13 @@ static const struct file_operations pp_fops = {
static void pp_attach(struct parport *port)
{
- class_device_create(ppdev_class, NULL, MKDEV(PP_MAJOR, port->number),
- NULL, "parport%d", port->number);
+ device_create(ppdev_class, NULL, MKDEV(PP_MAJOR, port->number),
+ "parport%d", port->number);
}
static void pp_detach(struct parport *port)
{
- class_device_destroy(ppdev_class, MKDEV(PP_MAJOR, port->number));
+ device_destroy(ppdev_class, MKDEV(PP_MAJOR, port->number));
}
static struct parport_driver pp_driver = {
diff --git a/drivers/char/random.c b/drivers/char/random.c
index fa764688cad1..4c6782a1ecdb 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1466,8 +1466,8 @@ static __init int seqgen_init(void)
late_initcall(seqgen_init);
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-__u32 secure_tcpv6_sequence_number(__u32 *saddr, __u32 *daddr,
- __u16 sport, __u16 dport)
+__u32 secure_tcpv6_sequence_number(__be32 *saddr, __be32 *daddr,
+ __be16 sport, __be16 dport)
{
struct timeval tv;
__u32 seq;
@@ -1479,10 +1479,10 @@ __u32 secure_tcpv6_sequence_number(__u32 *saddr, __u32 *daddr,
*/
memcpy(hash, saddr, 16);
- hash[4]=(sport << 16) + dport;
+ hash[4]=((__force u16)sport << 16) + (__force u16)dport;
memcpy(&hash[5],keyptr->secret,sizeof(__u32) * 7);
- seq = twothirdsMD4Transform(daddr, hash) & HASH_MASK;
+ seq = twothirdsMD4Transform((const __u32 *)daddr, hash) & HASH_MASK;
seq += keyptr->count;
do_gettimeofday(&tv);
@@ -1496,7 +1496,7 @@ EXPORT_SYMBOL(secure_tcpv6_sequence_number);
/* The code below is shamelessly stolen from secure_tcp_sequence_number().
* All blames to Andrey V. Savochkin <saw@msu.ru>.
*/
-__u32 secure_ip_id(__u32 daddr)
+__u32 secure_ip_id(__be32 daddr)
{
struct keydata *keyptr;
__u32 hash[4];
@@ -1508,7 +1508,7 @@ __u32 secure_ip_id(__u32 daddr)
* The dest ip address is placed in the starting vector,
* which is then hashed with random data.
*/
- hash[0] = daddr;
+ hash[0] = (__force __u32)daddr;
hash[1] = keyptr->secret[9];
hash[2] = keyptr->secret[10];
hash[3] = keyptr->secret[11];
@@ -1518,8 +1518,8 @@ __u32 secure_ip_id(__u32 daddr)
#ifdef CONFIG_INET
-__u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
- __u16 sport, __u16 dport)
+__u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
+ __be16 sport, __be16 dport)
{
struct timeval tv;
__u32 seq;
@@ -1532,9 +1532,9 @@ __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
* Note that the words are placed into the starting vector, which is
* then mixed with a partial MD4 over random data.
*/
- hash[0]=saddr;
- hash[1]=daddr;
- hash[2]=(sport << 16) + dport;
+ hash[0]=(__force u32)saddr;
+ hash[1]=(__force u32)daddr;
+ hash[2]=((__force u16)sport << 16) + (__force u16)dport;
hash[3]=keyptr->secret[11];
seq = half_md4_transform(hash, keyptr->secret) & HASH_MASK;
@@ -1559,7 +1559,7 @@ __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
EXPORT_SYMBOL(secure_tcp_sequence_number);
/* Generate secure starting point for ephemeral IPV4 transport port search */
-u32 secure_ipv4_port_ephemeral(__u32 saddr, __u32 daddr, __u16 dport)
+u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport)
{
struct keydata *keyptr = get_keyptr();
u32 hash[4];
@@ -1568,25 +1568,25 @@ u32 secure_ipv4_port_ephemeral(__u32 saddr, __u32 daddr, __u16 dport)
* Pick a unique starting offset for each ephemeral port search
* (saddr, daddr, dport) and 48bits of random data.
*/
- hash[0] = saddr;
- hash[1] = daddr;
- hash[2] = dport ^ keyptr->secret[10];
+ hash[0] = (__force u32)saddr;
+ hash[1] = (__force u32)daddr;
+ hash[2] = (__force u32)dport ^ keyptr->secret[10];
hash[3] = keyptr->secret[11];
return half_md4_transform(hash, keyptr->secret);
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-u32 secure_ipv6_port_ephemeral(const __u32 *saddr, const __u32 *daddr, __u16 dport)
+u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr, __be16 dport)
{
struct keydata *keyptr = get_keyptr();
u32 hash[12];
memcpy(hash, saddr, 16);
- hash[4] = dport;
+ hash[4] = (__force u32)dport;
memcpy(&hash[5],keyptr->secret,sizeof(__u32) * 7);
- return twothirdsMD4Transform(daddr, hash);
+ return twothirdsMD4Transform((const __u32 *)daddr, hash);
}
#endif
@@ -1595,17 +1595,17 @@ u32 secure_ipv6_port_ephemeral(const __u32 *saddr, const __u32 *daddr, __u16 dpo
* bit's 32-47 increase every key exchange
* 0-31 hash(source, dest)
*/
-u64 secure_dccp_sequence_number(__u32 saddr, __u32 daddr,
- __u16 sport, __u16 dport)
+u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
+ __be16 sport, __be16 dport)
{
struct timeval tv;
u64 seq;
__u32 hash[4];
struct keydata *keyptr = get_keyptr();
- hash[0] = saddr;
- hash[1] = daddr;
- hash[2] = (sport << 16) + dport;
+ hash[0] = (__force u32)saddr;
+ hash[1] = (__force u32)daddr;
+ hash[2] = ((__force u16)sport << 16) + (__force u16)dport;
hash[3] = keyptr->secret[11];
seq = half_md4_transform(hash, keyptr->secret);
@@ -1641,7 +1641,7 @@ unsigned int get_random_int(void)
* drain on it), and uses halfMD4Transform within the second. We
* also mix it with jiffies and the PID:
*/
- return secure_ip_id(current->pid + jiffies);
+ return secure_ip_id((__force __be32)(current->pid + jiffies));
}
/*
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index 89b718e326e5..3b32313f6eb4 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -127,9 +127,9 @@ raw_ioctl(struct inode *inode, struct file *filp,
static void bind_device(struct raw_config_request *rq)
{
- class_device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor));
- class_device_create(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor),
- NULL, "raw%d", rq->raw_minor);
+ device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor));
+ device_create(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor),
+ "raw%d", rq->raw_minor);
}
/*
@@ -200,7 +200,7 @@ static int raw_ctl_ioctl(struct inode *inode, struct file *filp,
if (rq.block_major == 0 && rq.block_minor == 0) {
/* unbind */
rawdev->binding = NULL;
- class_device_destroy(raw_class,
+ device_destroy(raw_class,
MKDEV(RAW_MAJOR, rq.raw_minor));
} else {
rawdev->binding = bdget(dev);
@@ -283,7 +283,7 @@ static int __init raw_init(void)
ret = PTR_ERR(raw_class);
goto error_region;
}
- class_device_create(raw_class, NULL, MKDEV(RAW_MAJOR, 0), NULL, "rawctl");
+ device_create(raw_class, NULL, MKDEV(RAW_MAJOR, 0), "rawctl");
return 0;
@@ -295,7 +295,7 @@ error:
static void __exit raw_exit(void)
{
- class_device_destroy(raw_class, MKDEV(RAW_MAJOR, 0));
+ device_destroy(raw_class, MKDEV(RAW_MAJOR, 0));
class_destroy(raw_class);
cdev_del(&raw_cdev);
unregister_chrdev_region(MKDEV(RAW_MAJOR, 0), MAX_RAW_MINORS);
diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c
index 4df6ab2206a1..167ebc84e8d7 100644
--- a/drivers/char/rio/riocmd.c
+++ b/drivers/char/rio/riocmd.c
@@ -922,7 +922,7 @@ int RIOUnUse(unsigned long iPortP, struct CmdBlk *CmdBlkP)
**
** Packet is an actual packet structure to be filled in with the packet
** information associated with the command. You need to fill in everything,
-** as the command processore doesn't process the command packet in any way.
+** as the command processor doesn't process the command packet in any way.
**
** The PreFuncP is called before the packet is enqueued on the host rup.
** PreFuncP is called as (*PreFuncP)(PreArg, CmdBlkP);. PreFuncP must
diff --git a/drivers/char/rio/rioinit.c b/drivers/char/rio/rioinit.c
index 99f3df02b61c..0794844369d6 100644
--- a/drivers/char/rio/rioinit.c
+++ b/drivers/char/rio/rioinit.c
@@ -222,7 +222,7 @@ int RIOBoardTest(unsigned long paddr, void __iomem *caddr, unsigned char type, i
** which value will be written into memory.
** Call with op set to zero means that the RAM will not be read and checked
** before it is written.
-** Call with op not zero, and the RAM will be read and compated with val[op-1]
+** Call with op not zero and the RAM will be read and compared with val[op-1]
** to check that the data from the previous phase was retained.
*/
diff --git a/drivers/char/rio/rioparam.c b/drivers/char/rio/rioparam.c
index 1066d9760704..bb498d24adcc 100644
--- a/drivers/char/rio/rioparam.c
+++ b/drivers/char/rio/rioparam.c
@@ -87,8 +87,8 @@ static char *_rioparam_c_sccs_ = "@(#)rioparam.c 1.3";
** command bit set onto the port. The command bit is in the len field,
** and gets ORed in with the actual byte count.
**
-** When you send a packet with the command bit set, then the first
-** data byte ( data[0] ) is interpretted as the command to execute.
+** When you send a packet with the command bit set the first
+** data byte (data[0]) is interpreted as the command to execute.
** It also governs what data structure overlay should accompany the packet.
** Commands are defined in cirrus/cirrus.h
**
@@ -103,7 +103,7 @@ static char *_rioparam_c_sccs_ = "@(#)rioparam.c 1.3";
**
** Most commands do not use the remaining bytes in the data array. The
** exceptions are OPEN MOPEN and CONFIG. (NB. As with the SI CONFIG and
-** OPEN are currently analagous). With these three commands the following
+** OPEN are currently analogous). With these three commands the following
** 11 data bytes are all used to pass config information such as baud rate etc.
** The fields are also defined in cirrus.h. Some contain straightforward
** information such as the transmit XON character. Two contain the transmit and
diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c
index 2444a0e24b31..244d30a03fef 100644
--- a/drivers/char/tlclk.c
+++ b/drivers/char/tlclk.c
@@ -792,15 +792,14 @@ static int __init tlclk_init(void)
ret = misc_register(&tlclk_miscdev);
if (ret < 0) {
printk(KERN_ERR "tlclk: misc_register returns %d.\n", ret);
- ret = -EBUSY;
goto out3;
}
tlclk_device = platform_device_register_simple("telco_clock",
-1, NULL, 0);
- if (!tlclk_device) {
+ if (IS_ERR(tlclk_device)) {
printk(KERN_ERR "tlclk: platform_device_register failed.\n");
- ret = -EBUSY;
+ ret = PTR_ERR(tlclk_device);
goto out4;
}
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 36f91a655275..774fa861169a 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -1130,7 +1130,7 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend
scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num);
chip->vendor.miscdev.name = devname;
- chip->vendor.miscdev.dev = dev;
+ chip->vendor.miscdev.parent = dev;
chip->dev = get_device(dev);
if (misc_register(&chip->vendor.miscdev)) {
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 83e9e7d9b58c..b3cfc8bc613c 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -3615,7 +3615,8 @@ static struct class *tty_class;
* This field is optional, if there is no known struct device
* for this tty device it can be set to NULL safely.
*
- * Returns a pointer to the class device (or ERR_PTR(-EFOO) on error).
+ * Returns a pointer to the struct device for this tty device
+ * (or ERR_PTR(-EFOO) on error).
*
* This call is required to be made to register an individual tty device
* if the tty driver's flags have the TTY_DRIVER_DYNAMIC_DEV bit set. If
@@ -3625,8 +3626,8 @@ static struct class *tty_class;
* Locking: ??
*/
-struct class_device *tty_register_device(struct tty_driver *driver,
- unsigned index, struct device *device)
+struct device *tty_register_device(struct tty_driver *driver, unsigned index,
+ struct device *device)
{
char name[64];
dev_t dev = MKDEV(driver->major, driver->minor_start) + index;
@@ -3642,7 +3643,7 @@ struct class_device *tty_register_device(struct tty_driver *driver,
else
tty_line_name(driver, index, name);
- return class_device_create(tty_class, NULL, dev, device, "%s", name);
+ return device_create(tty_class, device, dev, name);
}
/**
@@ -3658,7 +3659,7 @@ struct class_device *tty_register_device(struct tty_driver *driver,
void tty_unregister_device(struct tty_driver *driver, unsigned index)
{
- class_device_destroy(tty_class, MKDEV(driver->major, driver->minor_start) + index);
+ device_destroy(tty_class, MKDEV(driver->major, driver->minor_start) + index);
}
EXPORT_SYMBOL(tty_register_device);
@@ -3898,20 +3899,20 @@ static int __init tty_init(void)
if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) ||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0)
panic("Couldn't register /dev/tty driver\n");
- class_device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty");
+ device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), "tty");
cdev_init(&console_cdev, &console_fops);
if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) ||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0)
panic("Couldn't register /dev/console driver\n");
- class_device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL, "console");
+ device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), "console");
#ifdef CONFIG_UNIX98_PTYS
cdev_init(&ptmx_cdev, &ptmx_fops);
if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) ||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
panic("Couldn't register /dev/ptmx driver\n");
- class_device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
+ device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), "ptmx");
#endif
#ifdef CONFIG_VT
@@ -3919,7 +3920,7 @@ static int __init tty_init(void)
if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) ||
register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
panic("Couldn't register /dev/tty0 driver\n");
- class_device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
+ device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), "tty0");
vty_init();
#endif
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
index bd7a98c6ea7a..f442b574b44a 100644
--- a/drivers/char/vc_screen.c
+++ b/drivers/char/vc_screen.c
@@ -476,16 +476,16 @@ static struct class *vc_class;
void vcs_make_sysfs(struct tty_struct *tty)
{
- class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1),
- NULL, "vcs%u", tty->index + 1);
- class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129),
- NULL, "vcsa%u", tty->index + 1);
+ device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1),
+ "vcs%u", tty->index + 1);
+ device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129),
+ "vcsa%u", tty->index + 1);
}
void vcs_remove_sysfs(struct tty_struct *tty)
{
- class_device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 1));
- class_device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 129));
+ device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 1));
+ device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 129));
}
int __init vcs_init(void)
@@ -494,7 +494,7 @@ int __init vcs_init(void)
panic("unable to get major %d for vcs device", VCS_MAJOR);
vc_class = class_create(THIS_MODULE, "vc");
- class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
- class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
+ device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 0), "vcs");
+ device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 128), "vcsa");
return 0;
}
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 8ee04adc37f0..75ff0286e1ad 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -112,7 +112,7 @@
struct con_driver {
const struct consw *con;
const char *desc;
- struct class_device *class_dev;
+ struct device *dev;
int node;
int first;
int last;
@@ -3023,10 +3023,10 @@ static inline int vt_unbind(struct con_driver *con)
}
#endif /* CONFIG_VT_HW_CONSOLE_BINDING */
-static ssize_t store_bind(struct class_device *class_device,
+static ssize_t store_bind(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct con_driver *con = class_get_devdata(class_device);
+ struct con_driver *con = dev_get_drvdata(dev);
int bind = simple_strtoul(buf, NULL, 0);
if (bind)
@@ -3037,17 +3037,19 @@ static ssize_t store_bind(struct class_device *class_device,
return count;
}
-static ssize_t show_bind(struct class_device *class_device, char *buf)
+static ssize_t show_bind(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
- struct con_driver *con = class_get_devdata(class_device);
+ struct con_driver *con = dev_get_drvdata(dev);
int bind = con_is_bound(con->con);
return snprintf(buf, PAGE_SIZE, "%i\n", bind);
}
-static ssize_t show_name(struct class_device *class_device, char *buf)
+static ssize_t show_name(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
- struct con_driver *con = class_get_devdata(class_device);
+ struct con_driver *con = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%s %s\n",
(con->flag & CON_DRIVER_FLAG_MODULE) ? "(M)" : "(S)",
@@ -3055,43 +3057,40 @@ static ssize_t show_name(struct class_device *class_device, char *buf)
}
-static struct class_device_attribute class_device_attrs[] = {
+static struct device_attribute device_attrs[] = {
__ATTR(bind, S_IRUGO|S_IWUSR, show_bind, store_bind),
__ATTR(name, S_IRUGO, show_name, NULL),
};
-static int vtconsole_init_class_device(struct con_driver *con)
+static int vtconsole_init_device(struct con_driver *con)
{
int i;
int error = 0;
con->flag |= CON_DRIVER_FLAG_ATTR;
- class_set_devdata(con->class_dev, con);
- for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) {
- error = class_device_create_file(con->class_dev,
- &class_device_attrs[i]);
+ dev_set_drvdata(con->dev, con);
+ for (i = 0; i < ARRAY_SIZE(device_attrs); i++) {
+ error = device_create_file(con->dev, &device_attrs[i]);
if (error)
break;
}
if (error) {
while (--i >= 0)
- class_device_remove_file(con->class_dev,
- &class_device_attrs[i]);
+ device_remove_file(con->dev, &device_attrs[i]);
con->flag &= ~CON_DRIVER_FLAG_ATTR;
}
return error;
}
-static void vtconsole_deinit_class_device(struct con_driver *con)
+static void vtconsole_deinit_device(struct con_driver *con)
{
int i;
if (con->flag & CON_DRIVER_FLAG_ATTR) {
- for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
- class_device_remove_file(con->class_dev,
- &class_device_attrs[i]);
+ for (i = 0; i < ARRAY_SIZE(device_attrs); i++)
+ device_remove_file(con->dev, &device_attrs[i]);
con->flag &= ~CON_DRIVER_FLAG_ATTR;
}
}
@@ -3179,18 +3178,17 @@ int register_con_driver(const struct consw *csw, int first, int last)
if (retval)
goto err;
- con_driver->class_dev = class_device_create(vtconsole_class, NULL,
- MKDEV(0, con_driver->node),
- NULL, "vtcon%i",
- con_driver->node);
+ con_driver->dev = device_create(vtconsole_class, NULL,
+ MKDEV(0, con_driver->node),
+ "vtcon%i", con_driver->node);
- if (IS_ERR(con_driver->class_dev)) {
- printk(KERN_WARNING "Unable to create class_device for %s; "
+ if (IS_ERR(con_driver->dev)) {
+ printk(KERN_WARNING "Unable to create device for %s; "
"errno = %ld\n", con_driver->desc,
- PTR_ERR(con_driver->class_dev));
- con_driver->class_dev = NULL;
+ PTR_ERR(con_driver->dev));
+ con_driver->dev = NULL;
} else {
- vtconsole_init_class_device(con_driver);
+ vtconsole_init_device(con_driver);
}
err:
@@ -3226,12 +3224,12 @@ int unregister_con_driver(const struct consw *csw)
if (con_driver->con == csw &&
con_driver->flag & CON_DRIVER_FLAG_MODULE) {
- vtconsole_deinit_class_device(con_driver);
- class_device_destroy(vtconsole_class,
- MKDEV(0, con_driver->node));
+ vtconsole_deinit_device(con_driver);
+ device_destroy(vtconsole_class,
+ MKDEV(0, con_driver->node));
con_driver->con = NULL;
con_driver->desc = NULL;
- con_driver->class_dev = NULL;
+ con_driver->dev = NULL;
con_driver->node = 0;
con_driver->flag = 0;
con_driver->first = 0;
@@ -3289,19 +3287,18 @@ static int __init vtconsole_class_init(void)
for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
struct con_driver *con = &registered_con_driver[i];
- if (con->con && !con->class_dev) {
- con->class_dev =
- class_device_create(vtconsole_class, NULL,
- MKDEV(0, con->node), NULL,
- "vtcon%i", con->node);
+ if (con->con && !con->dev) {
+ con->dev = device_create(vtconsole_class, NULL,
+ MKDEV(0, con->node),
+ "vtcon%i", con->node);
- if (IS_ERR(con->class_dev)) {
+ if (IS_ERR(con->dev)) {
printk(KERN_WARNING "Unable to create "
- "class_device for %s; errno = %ld\n",
- con->desc, PTR_ERR(con->class_dev));
- con->class_dev = NULL;
+ "device for %s; errno = %ld\n",
+ con->desc, PTR_ERR(con->dev));
+ con->dev = NULL;
} else {
- vtconsole_init_class_device(con);
+ vtconsole_init_device(con);
}
}
}
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index 0187b1185323..ea09d0c974ea 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -340,6 +340,14 @@ config ITCO_WDT
To compile this driver as a module, choose M here: the
module will be called iTCO_wdt.
+config ITCO_VENDOR_SUPPORT
+ bool "Intel TCO Timer/Watchdog Specific Vendor Support"
+ depends on ITCO_WDT
+ ---help---
+ Add vendor specific support to the intel TCO timer based watchdog
+ devices. At this moment we only have additional support for some
+ SuperMicro Inc. motherboards.
+
config SC1200_WDT
tristate "National Semiconductor PC87307/PC97307 (ala SC1200) Watchdog"
depends on WATCHDOG && X86
@@ -363,6 +371,20 @@ config SCx200_WDT
If compiled as a module, it will be called scx200_wdt.
+config PC87413_WDT
+ tristate "NS PC87413 watchdog"
+ depends on WATCHDOG && X86
+ ---help---
+ This is the driver for the hardware watchdog on the PC87413 chipset
+ This watchdog simply watches your kernel to make sure it doesn't
+ freeze, and if it does, it reboots your computer after a certain
+ amount of time.
+
+ To compile this driver as a module, choose M here: the
+ module will be called pc87413_wdt.
+
+ Most people will say N.
+
config 60XX_WDT
tristate "SBC-60XX Watchdog Timer"
depends on WATCHDOG && X86
@@ -553,6 +575,16 @@ config INDYDOG
timer expired and no process has written to /dev/watchdog during
that time.
+config WDT_RM9K_GPI
+ tristate "RM9000/GPI hardware watchdog"
+ depends on WATCHDOG && CPU_RM9000
+ help
+ Watchdog implementation using the GPI hardware found on
+ PMC-Sierra RM9xxx CPUs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called rm9k_wdt.
+
# S390 Architecture
config ZVM_WATCHDOG
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
index 36440497047c..2cd8ff8d10ac 100644
--- a/drivers/char/watchdog/Makefile
+++ b/drivers/char/watchdog/Makefile
@@ -47,9 +47,10 @@ obj-$(CONFIG_IBMASR) += ibmasr.o
obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o
obj-$(CONFIG_I6300ESB_WDT) += i6300esb.o
obj-$(CONFIG_I8XX_TCO) += i8xx_tco.o
-obj-$(CONFIG_ITCO_WDT) += iTCO_wdt.o
+obj-$(CONFIG_ITCO_WDT) += iTCO_wdt.o iTCO_vendor_support.o
obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o
obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o
+obj-$(CONFIG_PC87413_WDT) += pc87413_wdt.o
obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o
obj-$(CONFIG_SBC8360_WDT) += sbc8360.o
obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o
@@ -72,6 +73,7 @@ obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o
# MIPS Architecture
obj-$(CONFIG_INDYDOG) += indydog.o
+obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o
# S390 Architecture
diff --git a/drivers/char/watchdog/iTCO_vendor_support.c b/drivers/char/watchdog/iTCO_vendor_support.c
new file mode 100644
index 000000000000..415083990097
--- /dev/null
+++ b/drivers/char/watchdog/iTCO_vendor_support.c
@@ -0,0 +1,307 @@
+/*
+ * intel TCO vendor specific watchdog driver support
+ *
+ * (c) Copyright 2006 Wim Van Sebroeck <wim@iguana.be>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Neither Wim Van Sebroeck nor Iguana vzw. admit liability nor
+ * provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charge.
+ */
+
+/*
+ * Includes, defines, variables, module parameters, ...
+ */
+
+/* Module and version information */
+#define DRV_NAME "iTCO_vendor_support"
+#define DRV_VERSION "1.01"
+#define DRV_RELDATE "11-Nov-2006"
+#define PFX DRV_NAME ": "
+
+/* Includes */
+#include <linux/module.h> /* For module specific items */
+#include <linux/moduleparam.h> /* For new moduleparam's */
+#include <linux/types.h> /* For standard types (like size_t) */
+#include <linux/errno.h> /* For the -ENODEV/... values */
+#include <linux/kernel.h> /* For printk/panic/... */
+#include <linux/init.h> /* For __init/__exit/... */
+#include <linux/ioport.h> /* For io-port access */
+
+#include <asm/io.h> /* For inb/outb/... */
+
+/* iTCO defines */
+#define SMI_EN acpibase + 0x30 /* SMI Control and Enable Register */
+#define TCOBASE acpibase + 0x60 /* TCO base address */
+#define TCO1_STS TCOBASE + 0x04 /* TCO1 Status Register */
+
+/* List of vendor support modes */
+#define SUPERMICRO_OLD_BOARD 1 /* SuperMicro Pentium 3 Era 370SSE+-OEM1/P3TSSE */
+#define SUPERMICRO_NEW_BOARD 2 /* SuperMicro Pentium 4 / Xeon 4 / EMT64T Era Systems */
+
+static int vendorsupport = 0;
+module_param(vendorsupport, int, 0);
+MODULE_PARM_DESC(vendorsupport, "iTCO vendor specific support mode, default=0 (none), 1=SuperMicro Pent3, 2=SuperMicro Pent4+");
+
+/*
+ * Vendor Specific Support
+ */
+
+/*
+ * Vendor Support: 1
+ * Board: Super Micro Computer Inc. 370SSE+-OEM1/P3TSSE
+ * iTCO chipset: ICH2
+ *
+ * Code contributed by: R. Seretny <lkpatches@paypc.com>
+ * Documentation obtained by R. Seretny from SuperMicro Technical Support
+ *
+ * To enable Watchdog function:
+ * BIOS setup -> Power -> TCO Logic SMI Enable -> Within5Minutes
+ * This setting enables SMI to clear the watchdog expired flag.
+ * If BIOS or CPU fail which may cause SMI hang, then system will
+ * reboot. When application starts to use watchdog function,
+ * application has to take over the control from SMI.
+ *
+ * For P3TSSE, J36 jumper needs to be removed to enable the Watchdog
+ * function.
+ *
+ * Note: The system will reboot when Expire Flag is set TWICE.
+ * So, if the watchdog timer is 20 seconds, then the maximum hang
+ * time is about 40 seconds, and the minimum hang time is about
+ * 20.6 seconds.
+ */
+
+static void supermicro_old_pre_start(unsigned long acpibase)
+{
+ unsigned long val32;
+
+ val32 = inl(SMI_EN);
+ val32 &= 0xffffdfff; /* Turn off SMI clearing watchdog */
+ outl(val32, SMI_EN); /* Needed to activate watchdog */
+}
+
+static void supermicro_old_pre_stop(unsigned long acpibase)
+{
+ unsigned long val32;
+
+ val32 = inl(SMI_EN);
+ val32 &= 0x00002000; /* Turn on SMI clearing watchdog */
+ outl(val32, SMI_EN); /* Needed to deactivate watchdog */
+}
+
+static void supermicro_old_pre_keepalive(unsigned long acpibase)
+{
+ /* Reload TCO Timer (done in iTCO_wdt_keepalive) + */
+ /* Clear "Expire Flag" (Bit 3 of TC01_STS register) */
+ outb(0x08, TCO1_STS);
+}
+
+/*
+ * Vendor Support: 2
+ * Board: Super Micro Computer Inc. P4SBx, P4DPx
+ * iTCO chipset: ICH4
+ *
+ * Code contributed by: R. Seretny <lkpatches@paypc.com>
+ * Documentation obtained by R. Seretny from SuperMicro Technical Support
+ *
+ * To enable Watchdog function:
+ * 1. BIOS
+ * For P4SBx:
+ * BIOS setup -> Advanced -> Integrated Peripherals -> Watch Dog Feature
+ * For P4DPx:
+ * BIOS setup -> Advanced -> I/O Device Configuration -> Watch Dog
+ * This setting enables or disables Watchdog function. When enabled, the
+ * default watchdog timer is set to be 5 minutes (about 4’35â€). It is
+ * enough to load and run the OS. The application (service or driver) has
+ * to take over the control once OS is running up and before watchdog
+ * expires.
+ *
+ * 2. JUMPER
+ * For P4SBx: JP39
+ * For P4DPx: JP37
+ * This jumper is used for safety. Closed is enabled. This jumper
+ * prevents user enables watchdog in BIOS by accident.
+ *
+ * To enable Watch Dog function, both BIOS and JUMPER must be enabled.
+ *
+ * The documentation lists motherboards P4SBx and P4DPx series as of
+ * 20-March-2002. However, this code works flawlessly with much newer
+ * motherboards, such as my X6DHR-8G2 (SuperServer 6014H-82).
+ *
+ * The original iTCO driver as written does not actually reset the
+ * watchdog timer on these machines, as a result they reboot after five
+ * minutes.
+ *
+ * NOTE: You may leave the Watchdog function disabled in the SuperMicro
+ * BIOS to avoid a "boot-race"... This driver will enable watchdog
+ * functionality even if it's disabled in the BIOS once the /dev/watchdog
+ * file is opened.
+ */
+
+/* I/O Port's */
+#define SM_REGINDEX 0x2e /* SuperMicro ICH4+ Register Index */
+#define SM_DATAIO 0x2f /* SuperMicro ICH4+ Register Data I/O */
+
+/* Control Register's */
+#define SM_CTLPAGESW 0x07 /* SuperMicro ICH4+ Control Page Switch */
+#define SM_CTLPAGE 0x08 /* SuperMicro ICH4+ Control Page Num */
+
+#define SM_WATCHENABLE 0x30 /* Watchdog enable: Bit 0: 0=off, 1=on */
+
+#define SM_WATCHPAGE 0x87 /* Watchdog unlock control page */
+
+#define SM_ENDWATCH 0xAA /* Watchdog lock control page */
+
+#define SM_COUNTMODE 0xf5 /* Watchdog count mode select */
+ /* (Bit 3: 0 = seconds, 1 = minutes */
+
+#define SM_WATCHTIMER 0xf6 /* 8-bits, Watchdog timer counter (RW) */
+
+#define SM_RESETCONTROL 0xf7 /* Watchdog reset control */
+ /* Bit 6: timer is reset by kbd interrupt */
+ /* Bit 7: timer is reset by mouse interrupt */
+
+static void supermicro_new_unlock_watchdog(void)
+{
+ outb(SM_WATCHPAGE, SM_REGINDEX); /* Write 0x87 to port 0x2e twice */
+ outb(SM_WATCHPAGE, SM_REGINDEX);
+
+ outb(SM_CTLPAGESW, SM_REGINDEX); /* Switch to watchdog control page */
+ outb(SM_CTLPAGE, SM_DATAIO);
+}
+
+static void supermicro_new_lock_watchdog(void)
+{
+ outb(SM_ENDWATCH, SM_REGINDEX);
+}
+
+static void supermicro_new_pre_start(unsigned int heartbeat)
+{
+ unsigned int val;
+
+ supermicro_new_unlock_watchdog();
+
+ /* Watchdog timer setting needs to be in seconds*/
+ outb(SM_COUNTMODE, SM_REGINDEX);
+ val = inb(SM_DATAIO);
+ val &= 0xF7;
+ outb(val, SM_DATAIO);
+
+ /* Write heartbeat interval to WDOG */
+ outb (SM_WATCHTIMER, SM_REGINDEX);
+ outb((heartbeat & 255), SM_DATAIO);
+
+ /* Make sure keyboard/mouse interrupts don't interfere */
+ outb(SM_RESETCONTROL, SM_REGINDEX);
+ val = inb(SM_DATAIO);
+ val &= 0x3f;
+ outb(val, SM_DATAIO);
+
+ /* enable watchdog by setting bit 0 of Watchdog Enable to 1 */
+ outb(SM_WATCHENABLE, SM_REGINDEX);
+ val = inb(SM_DATAIO);
+ val |= 0x01;
+ outb(val, SM_DATAIO);
+
+ supermicro_new_lock_watchdog();
+}
+
+static void supermicro_new_pre_stop(void)
+{
+ unsigned int val;
+
+ supermicro_new_unlock_watchdog();
+
+ /* disable watchdog by setting bit 0 of Watchdog Enable to 0 */
+ outb(SM_WATCHENABLE, SM_REGINDEX);
+ val = inb(SM_DATAIO);
+ val &= 0xFE;
+ outb(val, SM_DATAIO);
+
+ supermicro_new_lock_watchdog();
+}
+
+static void supermicro_new_pre_set_heartbeat(unsigned int heartbeat)
+{
+ supermicro_new_unlock_watchdog();
+
+ /* reset watchdog timeout to heartveat value */
+ outb(SM_WATCHTIMER, SM_REGINDEX);
+ outb((heartbeat & 255), SM_DATAIO);
+
+ supermicro_new_lock_watchdog();
+}
+
+/*
+ * Generic Support Functions
+ */
+
+void iTCO_vendor_pre_start(unsigned long acpibase,
+ unsigned int heartbeat)
+{
+ if (vendorsupport == SUPERMICRO_OLD_BOARD)
+ supermicro_old_pre_start(acpibase);
+ else if (vendorsupport == SUPERMICRO_NEW_BOARD)
+ supermicro_new_pre_start(heartbeat);
+}
+EXPORT_SYMBOL(iTCO_vendor_pre_start);
+
+void iTCO_vendor_pre_stop(unsigned long acpibase)
+{
+ if (vendorsupport == SUPERMICRO_OLD_BOARD)
+ supermicro_old_pre_stop(acpibase);
+ else if (vendorsupport == SUPERMICRO_NEW_BOARD)
+ supermicro_new_pre_stop();
+}
+EXPORT_SYMBOL(iTCO_vendor_pre_stop);
+
+void iTCO_vendor_pre_keepalive(unsigned long acpibase, unsigned int heartbeat)
+{
+ if (vendorsupport == SUPERMICRO_OLD_BOARD)
+ supermicro_old_pre_keepalive(acpibase);
+ else if (vendorsupport == SUPERMICRO_NEW_BOARD)
+ supermicro_new_pre_set_heartbeat(heartbeat);
+}
+EXPORT_SYMBOL(iTCO_vendor_pre_keepalive);
+
+void iTCO_vendor_pre_set_heartbeat(unsigned int heartbeat)
+{
+ if (vendorsupport == SUPERMICRO_NEW_BOARD)
+ supermicro_new_pre_set_heartbeat(heartbeat);
+}
+EXPORT_SYMBOL(iTCO_vendor_pre_set_heartbeat);
+
+int iTCO_vendor_check_noreboot_on(void)
+{
+ switch(vendorsupport) {
+ case SUPERMICRO_OLD_BOARD:
+ return 0;
+ default:
+ return 1;
+ }
+}
+EXPORT_SYMBOL(iTCO_vendor_check_noreboot_on);
+
+static int __init iTCO_vendor_init_module(void)
+{
+ printk (KERN_INFO PFX "vendor-support=%d\n", vendorsupport);
+ return 0;
+}
+
+static void __exit iTCO_vendor_exit_module(void)
+{
+ printk (KERN_INFO PFX "Module Unloaded\n");
+}
+
+module_init(iTCO_vendor_init_module);
+module_exit(iTCO_vendor_exit_module);
+
+MODULE_AUTHOR("Wim Van Sebroeck <wim@iguana.be>, R. Seretny <lkpatches@paypc.com>");
+MODULE_DESCRIPTION("Intel TCO Vendor Specific WatchDog Timer Driver Support");
+MODULE_VERSION(DRV_VERSION);
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/char/watchdog/iTCO_wdt.c b/drivers/char/watchdog/iTCO_wdt.c
index b6f29cb8bd39..7eac922df867 100644
--- a/drivers/char/watchdog/iTCO_wdt.c
+++ b/drivers/char/watchdog/iTCO_wdt.c
@@ -48,8 +48,8 @@
/* Module and version information */
#define DRV_NAME "iTCO_wdt"
-#define DRV_VERSION "1.00"
-#define DRV_RELDATE "08-Oct-2006"
+#define DRV_VERSION "1.01"
+#define DRV_RELDATE "11-Nov-2006"
#define PFX DRV_NAME ": "
/* Includes */
@@ -189,6 +189,21 @@ static int nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, int, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+/* iTCO Vendor Specific Support hooks */
+#ifdef CONFIG_ITCO_VENDOR_SUPPORT
+extern void iTCO_vendor_pre_start(unsigned long, unsigned int);
+extern void iTCO_vendor_pre_stop(unsigned long);
+extern void iTCO_vendor_pre_keepalive(unsigned long, unsigned int);
+extern void iTCO_vendor_pre_set_heartbeat(unsigned int);
+extern int iTCO_vendor_check_noreboot_on(void);
+#else
+#define iTCO_vendor_pre_start(acpibase, heartbeat) {}
+#define iTCO_vendor_pre_stop(acpibase) {}
+#define iTCO_vendor_pre_keepalive(acpibase,heartbeat) {}
+#define iTCO_vendor_pre_set_heartbeat(heartbeat) {}
+#define iTCO_vendor_check_noreboot_on() 1 /* 1=check noreboot; 0=don't check */
+#endif
+
/*
* Some TCO specific functions
*/
@@ -249,6 +264,8 @@ static int iTCO_wdt_start(void)
spin_lock(&iTCO_wdt_private.io_lock);
+ iTCO_vendor_pre_start(iTCO_wdt_private.ACPIBASE, heartbeat);
+
/* disable chipset's NO_REBOOT bit */
if (iTCO_wdt_unset_NO_REBOOT_bit()) {
printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot disabled by hardware\n");
@@ -273,6 +290,8 @@ static int iTCO_wdt_stop(void)
spin_lock(&iTCO_wdt_private.io_lock);
+ iTCO_vendor_pre_stop(iTCO_wdt_private.ACPIBASE);
+
/* Bit 11: TCO Timer Halt -> 1 = The TCO timer is disabled */
val = inw(TCO1_CNT);
val |= 0x0800;
@@ -293,6 +312,8 @@ static int iTCO_wdt_keepalive(void)
{
spin_lock(&iTCO_wdt_private.io_lock);
+ iTCO_vendor_pre_keepalive(iTCO_wdt_private.ACPIBASE, heartbeat);
+
/* Reload the timer by writing to the TCO Timer Counter register */
if (iTCO_wdt_private.iTCO_version == 2) {
outw(0x01, TCO_RLD);
@@ -319,6 +340,8 @@ static int iTCO_wdt_set_heartbeat(int t)
((iTCO_wdt_private.iTCO_version == 1) && (tmrval > 0x03f)))
return -EINVAL;
+ iTCO_vendor_pre_set_heartbeat(tmrval);
+
/* Write new heartbeat to watchdog */
if (iTCO_wdt_private.iTCO_version == 2) {
spin_lock(&iTCO_wdt_private.io_lock);
@@ -569,7 +592,7 @@ static int iTCO_wdt_init(struct pci_dev *pdev, const struct pci_device_id *ent,
}
/* Check chipset's NO_REBOOT bit */
- if (iTCO_wdt_unset_NO_REBOOT_bit()) {
+ if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) {
printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot disabled by hardware\n");
ret = -ENODEV; /* Cannot reset NO_REBOOT bit */
goto out;
diff --git a/drivers/char/watchdog/pc87413_wdt.c b/drivers/char/watchdog/pc87413_wdt.c
new file mode 100644
index 000000000000..1d447e32af41
--- /dev/null
+++ b/drivers/char/watchdog/pc87413_wdt.c
@@ -0,0 +1,635 @@
+/*
+ * NS pc87413-wdt Watchdog Timer driver for Linux 2.6.x.x
+ *
+ * This code is based on wdt.c with original copyright.
+ *
+ * (C) Copyright 2006 Sven Anders, <anders@anduras.de>
+ * and Marcus Junker, <junker@anduras.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Neither Sven Anders, Marcus Junker nor ANDURAS AG
+ * admit liability nor provide warranty for any of this software.
+ * This material is provided "AS-IS" and at no charge.
+ *
+ * Release 1.1
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/notifier.h>
+#include <linux/fs.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/moduleparam.h>
+#include <linux/version.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+/* #define DEBUG 1 */
+
+#define DEFAULT_TIMEOUT 1 /* 1 minute */
+#define MAX_TIMEOUT 255
+
+#define VERSION "1.1"
+#define MODNAME "pc87413 WDT"
+#define PFX MODNAME ": "
+#define DPFX MODNAME " - DEBUG: "
+
+#define WDT_INDEX_IO_PORT (io+0) /* I/O port base (index register) */
+#define WDT_DATA_IO_PORT (WDT_INDEX_IO_PORT+1)
+#define SWC_LDN 0x04
+#define SIOCFG2 0x22 /* Serial IO register */
+#define WDCTL 0x10 /* Watchdog-Timer-Controll-Register */
+#define WDTO 0x11 /* Watchdog timeout register */
+#define WDCFG 0x12 /* Watchdog config register */
+
+static int io = 0x2E; /* Address used on Portwell Boards */
+
+static int timeout = DEFAULT_TIMEOUT; /* timeout value */
+static unsigned long timer_enabled = 0; /* is the timer enabled? */
+
+static char expect_close; /* is the close expected? */
+
+static spinlock_t io_lock; /* to guard the watchdog from io races */
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+
+/* -- Low level function ----------------------------------------*/
+
+/* Select pins for Watchdog output */
+
+static inline void pc87413_select_wdt_out (void)
+{
+ unsigned int cr_data = 0;
+
+ /* Step 1: Select multiple pin,pin55,as WDT output */
+
+ outb_p(SIOCFG2, WDT_INDEX_IO_PORT);
+
+ cr_data = inb (WDT_DATA_IO_PORT);
+
+ cr_data |= 0x80; /* Set Bit7 to 1*/
+ outb_p(SIOCFG2, WDT_INDEX_IO_PORT);
+
+ outb_p(cr_data, WDT_DATA_IO_PORT);
+
+#ifdef DEBUG
+ printk(KERN_INFO DPFX "Select multiple pin,pin55,as WDT output:"
+ " Bit7 to 1: %d\n", cr_data);
+#endif
+}
+
+/* Enable SWC functions */
+
+static inline void pc87413_enable_swc(void)
+{
+ unsigned int cr_data=0;
+
+ /* Step 2: Enable SWC functions */
+
+ outb_p(0x07, WDT_INDEX_IO_PORT); /* Point SWC_LDN (LDN=4) */
+ outb_p(SWC_LDN, WDT_DATA_IO_PORT);
+
+ outb_p(0x30, WDT_INDEX_IO_PORT); /* Read Index 0x30 First */
+ cr_data = inb(WDT_DATA_IO_PORT);
+ cr_data |= 0x01; /* Set Bit0 to 1 */
+ outb_p(0x30, WDT_INDEX_IO_PORT);
+ outb_p(cr_data, WDT_DATA_IO_PORT); /* Index0x30_bit0P1 */
+
+#ifdef DEBUG
+ printk(KERN_INFO DPFX "pc87413 - Enable SWC functions\n");
+#endif
+}
+
+/* Read SWC I/O base address */
+
+static inline unsigned int pc87413_get_swc_base(void)
+{
+ unsigned int swc_base_addr = 0;
+ unsigned char addr_l, addr_h = 0;
+
+ /* Step 3: Read SWC I/O Base Address */
+
+ outb_p(0x60, WDT_INDEX_IO_PORT); /* Read Index 0x60 */
+ addr_h = inb(WDT_DATA_IO_PORT);
+
+ outb_p(0x61, WDT_INDEX_IO_PORT); /* Read Index 0x61 */
+
+ addr_l = inb(WDT_DATA_IO_PORT);
+
+ swc_base_addr = (addr_h << 8) + addr_l;
+
+#ifdef DEBUG
+ printk(KERN_INFO DPFX "Read SWC I/O Base Address: low %d, high %d,"
+ " res %d\n", addr_l, addr_h, swc_base_addr);
+#endif
+
+ return swc_base_addr;
+}
+
+/* Select Bank 3 of SWC */
+
+static inline void pc87413_swc_bank3(unsigned int swc_base_addr)
+{
+ /* Step 4: Select Bank3 of SWC */
+
+ outb_p(inb(swc_base_addr + 0x0f) | 0x03, swc_base_addr + 0x0f);
+
+#ifdef DEBUG
+ printk(KERN_INFO DPFX "Select Bank3 of SWC\n");
+#endif
+}
+
+/* Set watchdog timeout to x minutes */
+
+static inline void pc87413_programm_wdto(unsigned int swc_base_addr,
+ char pc87413_time)
+{
+ /* Step 5: Programm WDTO, Twd. */
+
+ outb_p(pc87413_time, swc_base_addr + WDTO);
+
+#ifdef DEBUG
+ printk(KERN_INFO DPFX "Set WDTO to %d minutes\n", pc87413_time);
+#endif
+}
+
+/* Enable WDEN */
+
+static inline void pc87413_enable_wden(unsigned int swc_base_addr)
+{
+ /* Step 6: Enable WDEN */
+
+ outb_p(inb (swc_base_addr + WDCTL) | 0x01, swc_base_addr + WDCTL);
+
+#ifdef DEBUG
+ printk(KERN_INFO DPFX "Enable WDEN\n");
+#endif
+}
+
+/* Enable SW_WD_TREN */
+static inline void pc87413_enable_sw_wd_tren(unsigned int swc_base_addr)
+{
+ /* Enable SW_WD_TREN */
+
+ outb_p(inb (swc_base_addr + WDCFG) | 0x80, swc_base_addr + WDCFG);
+
+#ifdef DEBUG
+ printk(KERN_INFO DPFX "Enable SW_WD_TREN\n");
+#endif
+}
+
+/* Disable SW_WD_TREN */
+
+static inline void pc87413_disable_sw_wd_tren(unsigned int swc_base_addr)
+{
+ /* Disable SW_WD_TREN */
+
+ outb_p(inb (swc_base_addr + WDCFG) & 0x7f, swc_base_addr + WDCFG);
+
+#ifdef DEBUG
+ printk(KERN_INFO DPFX "pc87413 - Disable SW_WD_TREN\n");
+#endif
+}
+
+/* Enable SW_WD_TRG */
+
+static inline void pc87413_enable_sw_wd_trg(unsigned int swc_base_addr)
+{
+ /* Enable SW_WD_TRG */
+
+ outb_p(inb (swc_base_addr + WDCTL) | 0x80, swc_base_addr + WDCTL);
+
+#ifdef DEBUG
+ printk(KERN_INFO DPFX "pc87413 - Enable SW_WD_TRG\n");
+#endif
+}
+
+/* Disable SW_WD_TRG */
+
+static inline void pc87413_disable_sw_wd_trg(unsigned int swc_base_addr)
+{
+ /* Disable SW_WD_TRG */
+
+ outb_p(inb (swc_base_addr + WDCTL) & 0x7f, swc_base_addr + WDCTL);
+
+#ifdef DEBUG
+ printk(KERN_INFO DPFX "Disable SW_WD_TRG\n");
+#endif
+}
+
+/* -- Higher level functions ------------------------------------*/
+
+/* Enable the watchdog */
+
+static void pc87413_enable(void)
+{
+ unsigned int swc_base_addr;
+
+ spin_lock(&io_lock);
+
+ pc87413_select_wdt_out();
+ pc87413_enable_swc();
+ swc_base_addr = pc87413_get_swc_base();
+ pc87413_swc_bank3(swc_base_addr);
+ pc87413_programm_wdto(swc_base_addr, timeout);
+ pc87413_enable_wden(swc_base_addr);
+ pc87413_enable_sw_wd_tren(swc_base_addr);
+ pc87413_enable_sw_wd_trg(swc_base_addr);
+
+ spin_unlock(&io_lock);
+}
+
+/* Disable the watchdog */
+
+static void pc87413_disable(void)
+{
+ unsigned int swc_base_addr;
+
+ spin_lock(&io_lock);
+
+ pc87413_select_wdt_out();
+ pc87413_enable_swc();
+ swc_base_addr = pc87413_get_swc_base();
+ pc87413_swc_bank3(swc_base_addr);
+ pc87413_disable_sw_wd_tren(swc_base_addr);
+ pc87413_disable_sw_wd_trg(swc_base_addr);
+ pc87413_programm_wdto(swc_base_addr, 0);
+
+ spin_unlock(&io_lock);
+}
+
+/* Refresh the watchdog */
+
+static void pc87413_refresh(void)
+{
+ unsigned int swc_base_addr;
+
+ spin_lock(&io_lock);
+
+ pc87413_select_wdt_out();
+ pc87413_enable_swc();
+ swc_base_addr = pc87413_get_swc_base();
+ pc87413_swc_bank3(swc_base_addr);
+ pc87413_disable_sw_wd_tren(swc_base_addr);
+ pc87413_disable_sw_wd_trg(swc_base_addr);
+ pc87413_programm_wdto(swc_base_addr, timeout);
+ pc87413_enable_wden(swc_base_addr);
+ pc87413_enable_sw_wd_tren(swc_base_addr);
+ pc87413_enable_sw_wd_trg(swc_base_addr);
+
+ spin_unlock(&io_lock);
+}
+
+/* -- File operations -------------------------------------------*/
+
+/**
+ * pc87413_open:
+ * @inode: inode of device
+ * @file: file handle to device
+ *
+ */
+
+static int pc87413_open(struct inode *inode, struct file *file)
+{
+ /* /dev/watchdog can only be opened once */
+
+ if (test_and_set_bit(0, &timer_enabled))
+ return -EBUSY;
+
+ if (nowayout)
+ __module_get(THIS_MODULE);
+
+ /* Reload and activate timer */
+ pc87413_refresh();
+
+ printk(KERN_INFO MODNAME "Watchdog enabled. Timeout set to"
+ " %d minute(s).\n", timeout);
+
+ return nonseekable_open(inode, file);
+}
+
+/**
+ * pc87413_release:
+ * @inode: inode to board
+ * @file: file handle to board
+ *
+ * The watchdog has a configurable API. There is a religious dispute
+ * between people who want their watchdog to be able to shut down and
+ * those who want to be sure if the watchdog manager dies the machine
+ * reboots. In the former case we disable the counters, in the latter
+ * case you have to open it again very soon.
+ */
+
+static int pc87413_release(struct inode *inode, struct file *file)
+{
+ /* Shut off the timer. */
+
+ if (expect_close == 42) {
+ pc87413_disable();
+ printk(KERN_INFO MODNAME "Watchdog disabled,"
+ " sleeping again...\n");
+ } else {
+ printk(KERN_CRIT MODNAME "Unexpected close, not stopping"
+ " watchdog!\n");
+ pc87413_refresh();
+ }
+
+ clear_bit(0, &timer_enabled);
+ expect_close = 0;
+
+ return 0;
+}
+
+/**
+ * pc87413_status:
+ *
+ * return, if the watchdog is enabled (timeout is set...)
+ */
+
+
+static int pc87413_status(void)
+{
+ return 0; /* currently not supported */
+}
+
+/**
+ * pc87413_write:
+ * @file: file handle to the watchdog
+ * @data: data buffer to write
+ * @len: length in bytes
+ * @ppos: pointer to the position to write. No seeks allowed
+ *
+ * A write to a watchdog device is defined as a keepalive signal. Any
+ * write of data will do, as we we don't define content meaning.
+ */
+
+static ssize_t pc87413_write(struct file *file, const char __user *data,
+ size_t len, loff_t *ppos)
+{
+ /* See if we got the magic character 'V' and reload the timer */
+ if (len) {
+ if (!nowayout) {
+ size_t i;
+
+ /* reset expect flag */
+ expect_close = 0;
+
+ /* scan to see whether or not we got the magic character */
+ for (i = 0; i != len; i++) {
+ char c;
+ if (get_user(c, data+i))
+ return -EFAULT;
+ if (c == 'V')
+ expect_close = 42;
+ }
+ }
+
+ /* someone wrote to us, we should reload the timer */
+ pc87413_refresh();
+ }
+ return len;
+}
+
+/**
+ * pc87413_ioctl:
+ * @inode: inode of the device
+ * @file: file handle to the device
+ * @cmd: watchdog command
+ * @arg: argument pointer
+ *
+ * The watchdog API defines a common set of functions for all watchdogs
+ * according to their available features. We only actually usefully support
+ * querying capabilities and current status.
+ */
+
+static int pc87413_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int new_timeout;
+
+ union {
+ struct watchdog_info __user *ident;
+ int __user *i;
+ } uarg;
+
+ static struct watchdog_info ident = {
+ .options = WDIOF_KEEPALIVEPING |
+ WDIOF_SETTIMEOUT |
+ WDIOF_MAGICCLOSE,
+ .firmware_version = 1,
+ .identity = "PC87413(HF/F) watchdog"
+ };
+
+ uarg.i = (int __user *)arg;
+
+ switch(cmd) {
+ default:
+ return -ENOTTY;
+
+ case WDIOC_GETSUPPORT:
+ return copy_to_user(uarg.ident, &ident,
+ sizeof(ident)) ? -EFAULT : 0;
+
+ case WDIOC_GETSTATUS:
+ return put_user(pc87413_status(), uarg.i);
+
+ case WDIOC_GETBOOTSTATUS:
+ return put_user(0, uarg.i);
+
+ case WDIOC_KEEPALIVE:
+ pc87413_refresh();
+#ifdef DEBUG
+ printk(KERN_INFO DPFX "keepalive\n");
+#endif
+ return 0;
+
+ case WDIOC_SETTIMEOUT:
+ if (get_user(new_timeout, uarg.i))
+ return -EFAULT;
+
+ // the API states this is given in secs
+ new_timeout /= 60;
+
+ if (new_timeout < 0 || new_timeout > MAX_TIMEOUT)
+ return -EINVAL;
+
+ timeout = new_timeout;
+ pc87413_refresh();
+
+ // fall through and return the new timeout...
+
+ case WDIOC_GETTIMEOUT:
+
+ new_timeout = timeout * 60;
+
+ return put_user(new_timeout, uarg.i);
+
+ case WDIOC_SETOPTIONS:
+ {
+ int options, retval = -EINVAL;
+
+ if (get_user(options, uarg.i))
+ return -EFAULT;
+
+ if (options & WDIOS_DISABLECARD) {
+ pc87413_disable();
+ retval = 0;
+ }
+
+ if (options & WDIOS_ENABLECARD) {
+ pc87413_enable();
+ retval = 0;
+ }
+
+ return retval;
+ }
+ }
+}
+
+/* -- Notifier funtions -----------------------------------------*/
+
+/**
+ * notify_sys:
+ * @this: our notifier block
+ * @code: the event being reported
+ * @unused: unused
+ *
+ * Our notifier is called on system shutdowns. We want to turn the card
+ * off at reboot otherwise the machine will reboot again during memory
+ * test or worse yet during the following fsck. This would suck, in fact
+ * trust me - if it happens it does suck.
+ */
+
+static int pc87413_notify_sys(struct notifier_block *this,
+ unsigned long code,
+ void *unused)
+{
+ if (code == SYS_DOWN || code == SYS_HALT)
+ {
+ /* Turn the card off */
+ pc87413_disable();
+ }
+ return NOTIFY_DONE;
+}
+
+/* -- Module's structures ---------------------------------------*/
+
+static struct file_operations pc87413_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = pc87413_write,
+ .ioctl = pc87413_ioctl,
+ .open = pc87413_open,
+ .release = pc87413_release,
+};
+
+static struct notifier_block pc87413_notifier =
+{
+ .notifier_call = pc87413_notify_sys,
+};
+
+static struct miscdevice pc87413_miscdev=
+{
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &pc87413_fops
+};
+
+/* -- Module init functions -------------------------------------*/
+
+/**
+ * pc87413_init: module's "constructor"
+ *
+ * Set up the WDT watchdog board. All we have to do is grab the
+ * resources we require and bitch if anyone beat us to them.
+ * The open() function will actually kick the board off.
+ */
+
+static int __init pc87413_init(void)
+{
+ int ret;
+
+ spin_lock_init(&io_lock);
+
+ printk(KERN_INFO PFX "Version " VERSION " at io 0x%X\n", WDT_INDEX_IO_PORT);
+
+ /* request_region(io, 2, "pc87413"); */
+
+ ret = register_reboot_notifier(&pc87413_notifier);
+ if (ret != 0) {
+ printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
+ ret);
+ }
+
+ ret = misc_register(&pc87413_miscdev);
+
+ if (ret != 0) {
+ printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+ WATCHDOG_MINOR, ret);
+ unregister_reboot_notifier(&pc87413_notifier);
+ return ret;
+ }
+
+ printk(KERN_INFO PFX "initialized. timeout=%d min \n", timeout);
+
+ pc87413_enable();
+
+ return 0;
+}
+
+/**
+ * pc87413_exit: module's "destructor"
+ *
+ * Unload the watchdog. You cannot do this with any file handles open.
+ * If your watchdog is set to continue ticking on close and you unload
+ * it, well it keeps ticking. We won't get the interrupt but the board
+ * will not touch PC memory so all is fine. You just have to load a new
+ * module in 60 seconds or reboot.
+ */
+
+static void __exit pc87413_exit(void)
+{
+ /* Stop the timer before we leave */
+ if (!nowayout)
+ {
+ pc87413_disable();
+ printk(KERN_INFO MODNAME "Watchdog disabled.\n");
+ }
+
+ misc_deregister(&pc87413_miscdev);
+ unregister_reboot_notifier(&pc87413_notifier);
+ /* release_region(io,2); */
+
+ printk(MODNAME " watchdog component driver removed.\n");
+}
+
+module_init(pc87413_init);
+module_exit(pc87413_exit);
+
+MODULE_AUTHOR("Sven Anders <anders@anduras.de>, Marcus Junker <junker@anduras.de>,");
+MODULE_DESCRIPTION("PC87413 WDT driver");
+MODULE_LICENSE("GPL");
+
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+
+module_param(io, int, 0);
+MODULE_PARM_DESC(io, MODNAME " I/O port (default: " __MODULE_STRING(io) ").");
+
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in minutes (default=" __MODULE_STRING(timeout) ").");
+
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
diff --git a/drivers/char/watchdog/pcwd_usb.c b/drivers/char/watchdog/pcwd_usb.c
index bda45334d802..e275dd4a705d 100644
--- a/drivers/char/watchdog/pcwd_usb.c
+++ b/drivers/char/watchdog/pcwd_usb.c
@@ -561,8 +561,7 @@ static struct notifier_block usb_pcwd_notifier = {
*/
static inline void usb_pcwd_delete (struct usb_pcwd_private *usb_pcwd)
{
- if (usb_pcwd->intr_urb != NULL)
- usb_free_urb (usb_pcwd->intr_urb);
+ usb_free_urb(usb_pcwd->intr_urb);
if (usb_pcwd->intr_buffer != NULL)
usb_buffer_free(usb_pcwd->udev, usb_pcwd->intr_size,
usb_pcwd->intr_buffer, usb_pcwd->intr_dma);
diff --git a/drivers/char/watchdog/rm9k_wdt.c b/drivers/char/watchdog/rm9k_wdt.c
new file mode 100644
index 000000000000..ec3909371c21
--- /dev/null
+++ b/drivers/char/watchdog/rm9k_wdt.c
@@ -0,0 +1,420 @@
+/*
+ * Watchdog implementation for GPI h/w found on PMC-Sierra RM9xxx
+ * chips.
+ *
+ * Copyright (C) 2004 by Basler Vision Technologies AG
+ * Author: Thomas Koeller <thomas.koeller@baslerweb.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/platform_device.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/interrupt.h>
+#include <linux/fs.h>
+#include <linux/reboot.h>
+#include <linux/notifier.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <asm/io.h>
+#include <asm/atomic.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/rm9k-ocd.h>
+
+#include <rm9k_wdt.h>
+
+
+#define CLOCK 125000000
+#define MAX_TIMEOUT_SECONDS 32
+#define CPCCR 0x0080
+#define CPGIG1SR 0x0044
+#define CPGIG1ER 0x0054
+
+
+/* Function prototypes */
+static irqreturn_t wdt_gpi_irqhdl(int, void *, struct pt_regs *);
+static void wdt_gpi_start(void);
+static void wdt_gpi_stop(void);
+static void wdt_gpi_set_timeout(unsigned int);
+static int wdt_gpi_open(struct inode *, struct file *);
+static int wdt_gpi_release(struct inode *, struct file *);
+static ssize_t wdt_gpi_write(struct file *, const char __user *, size_t, loff_t *);
+static long wdt_gpi_ioctl(struct file *, unsigned int, unsigned long);
+static int wdt_gpi_notify(struct notifier_block *, unsigned long, void *);
+static const struct resource *wdt_gpi_get_resource(struct platform_device *, const char *, unsigned int);
+static int __init wdt_gpi_probe(struct device *);
+static int __exit wdt_gpi_remove(struct device *);
+
+
+static const char wdt_gpi_name[] = "wdt_gpi";
+static atomic_t opencnt;
+static int expect_close;
+static int locked;
+
+
+/* These are set from device resources */
+static void __iomem * wd_regs;
+static unsigned int wd_irq, wd_ctr;
+
+
+/* Module arguments */
+static int timeout = MAX_TIMEOUT_SECONDS;
+module_param(timeout, int, 0444);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds");
+
+static unsigned long resetaddr = 0xbffdc200;
+module_param(resetaddr, ulong, 0444);
+MODULE_PARM_DESC(resetaddr, "Address to write to to force a reset");
+
+static unsigned long flagaddr = 0xbffdc104;
+module_param(flagaddr, ulong, 0444);
+MODULE_PARM_DESC(flagaddr, "Address to write to boot flags to");
+
+static int powercycle;
+module_param(powercycle, bool, 0444);
+MODULE_PARM_DESC(powercycle, "Cycle power if watchdog expires");
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0444);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be disabled once started");
+
+
+/* Interrupt handler */
+static irqreturn_t wdt_gpi_irqhdl(int irq, void *ctxt, struct pt_regs *regs)
+{
+ if (!unlikely(__raw_readl(wd_regs + 0x0008) & 0x1))
+ return IRQ_NONE;
+ __raw_writel(0x1, wd_regs + 0x0008);
+
+
+ printk(KERN_CRIT "%s: watchdog expired - resetting system\n",
+ wdt_gpi_name);
+
+ *(volatile char *) flagaddr |= 0x01;
+ *(volatile char *) resetaddr = powercycle ? 0x01 : 0x2;
+ iob();
+ while (1)
+ cpu_relax();
+}
+
+
+/* Watchdog functions */
+static void wdt_gpi_start(void)
+{
+ u32 reg;
+
+ lock_titan_regs();
+ reg = titan_readl(CPGIG1ER);
+ titan_writel(reg | (0x100 << wd_ctr), CPGIG1ER);
+ iob();
+ unlock_titan_regs();
+}
+
+static void wdt_gpi_stop(void)
+{
+ u32 reg;
+
+ lock_titan_regs();
+ reg = titan_readl(CPCCR) & ~(0xf << (wd_ctr * 4));
+ titan_writel(reg, CPCCR);
+ reg = titan_readl(CPGIG1ER);
+ titan_writel(reg & ~(0x100 << wd_ctr), CPGIG1ER);
+ iob();
+ unlock_titan_regs();
+}
+
+static void wdt_gpi_set_timeout(unsigned int to)
+{
+ u32 reg;
+ const u32 wdval = (to * CLOCK) & ~0x0000000f;
+
+ lock_titan_regs();
+ reg = titan_readl(CPCCR) & ~(0xf << (wd_ctr * 4));
+ titan_writel(reg, CPCCR);
+ wmb();
+ __raw_writel(wdval, wd_regs + 0x0000);
+ wmb();
+ titan_writel(reg | (0x2 << (wd_ctr * 4)), CPCCR);
+ wmb();
+ titan_writel(reg | (0x5 << (wd_ctr * 4)), CPCCR);
+ iob();
+ unlock_titan_regs();
+}
+
+
+/* /dev/watchdog operations */
+static int wdt_gpi_open(struct inode *inode, struct file *file)
+{
+ int res;
+
+ if (unlikely(atomic_dec_if_positive(&opencnt) < 0))
+ return -EBUSY;
+
+ expect_close = 0;
+ if (locked) {
+ module_put(THIS_MODULE);
+ free_irq(wd_irq, &miscdev);
+ locked = 0;
+ }
+
+ res = request_irq(wd_irq, wdt_gpi_irqhdl, SA_SHIRQ | SA_INTERRUPT,
+ wdt_gpi_name, &miscdev);
+ if (unlikely(res))
+ return res;
+
+ wdt_gpi_set_timeout(timeout);
+ wdt_gpi_start();
+
+ printk(KERN_INFO "%s: watchdog started, timeout = %u seconds\n",
+ wdt_gpi_name, timeout);
+ return nonseekable_open(inode, file);
+}
+
+static int wdt_gpi_release(struct inode *inode, struct file *file)
+{
+ if (nowayout) {
+ printk(KERN_INFO "%s: no way out - watchdog left running\n",
+ wdt_gpi_name);
+ __module_get(THIS_MODULE);
+ locked = 1;
+ } else {
+ if (expect_close) {
+ wdt_gpi_stop();
+ free_irq(wd_irq, &miscdev);
+ printk(KERN_INFO "%s: watchdog stopped\n", wdt_gpi_name);
+ } else {
+ printk(KERN_CRIT "%s: unexpected close() -"
+ " watchdog left running\n",
+ wdt_gpi_name);
+ wdt_gpi_set_timeout(timeout);
+ __module_get(THIS_MODULE);
+ locked = 1;
+ }
+ }
+
+ atomic_inc(&opencnt);
+ return 0;
+}
+
+static ssize_t
+wdt_gpi_write(struct file *f, const char __user *d, size_t s, loff_t *o)
+{
+ char val;
+
+ wdt_gpi_set_timeout(timeout);
+ expect_close = (s > 0) && !get_user(val, d) && (val == 'V');
+ return s ? 1 : 0;
+}
+
+static long
+wdt_gpi_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+{
+ long res = -ENOTTY;
+ const long size = _IOC_SIZE(cmd);
+ int stat;
+ void __user *argp = (void __user *)arg;
+ static struct watchdog_info wdinfo = {
+ .identity = "RM9xxx/GPI watchdog",
+ .firmware_version = 0,
+ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING
+ };
+
+ if (unlikely(_IOC_TYPE(cmd) != WATCHDOG_IOCTL_BASE))
+ return -ENOTTY;
+
+ if ((_IOC_DIR(cmd) & _IOC_READ)
+ && !access_ok(VERIFY_WRITE, arg, size))
+ return -EFAULT;
+
+ if ((_IOC_DIR(cmd) & _IOC_WRITE)
+ && !access_ok(VERIFY_READ, arg, size))
+ return -EFAULT;
+
+ expect_close = 0;
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ wdinfo.options = nowayout ?
+ WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING :
+ WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE;
+ res = __copy_to_user(argp, &wdinfo, size) ? -EFAULT : size;
+ break;
+
+ case WDIOC_GETSTATUS:
+ break;
+
+ case WDIOC_GETBOOTSTATUS:
+ stat = (*(volatile char *) flagaddr & 0x01)
+ ? WDIOF_CARDRESET : 0;
+ res = __copy_to_user(argp, &stat, size) ?
+ -EFAULT : size;
+ break;
+
+ case WDIOC_SETOPTIONS:
+ break;
+
+ case WDIOC_KEEPALIVE:
+ wdt_gpi_set_timeout(timeout);
+ res = size;
+ break;
+
+ case WDIOC_SETTIMEOUT:
+ {
+ int val;
+ if (unlikely(__copy_from_user(&val, argp, size))) {
+ res = -EFAULT;
+ break;
+ }
+
+ if (val > MAX_TIMEOUT_SECONDS)
+ val = MAX_TIMEOUT_SECONDS;
+ timeout = val;
+ wdt_gpi_set_timeout(val);
+ res = size;
+ printk(KERN_INFO "%s: timeout set to %u seconds\n",
+ wdt_gpi_name, timeout);
+ }
+ break;
+
+ case WDIOC_GETTIMEOUT:
+ res = __copy_to_user(argp, &timeout, size) ?
+ -EFAULT : size;
+ break;
+ }
+
+ return res;
+}
+
+
+/* Shutdown notifier */
+static int
+wdt_gpi_notify(struct notifier_block *this, unsigned long code, void *unused)
+{
+ if (code == SYS_DOWN || code == SYS_HALT)
+ wdt_gpi_stop();
+
+ return NOTIFY_DONE;
+}
+
+
+/* Kernel interfaces */
+static struct file_operations fops = {
+ .owner = THIS_MODULE,
+ .open = wdt_gpi_open,
+ .release = wdt_gpi_release,
+ .write = wdt_gpi_write,
+ .unlocked_ioctl = wdt_gpi_ioctl,
+};
+
+static struct miscdevice miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = wdt_gpi_name,
+ .fops = &fops,
+};
+
+static struct notifier_block wdt_gpi_shutdown = {
+ .notifier_call = wdt_gpi_notify,
+};
+
+
+/* Init & exit procedures */
+static const struct resource *
+wdt_gpi_get_resource(struct platform_device *pdv, const char *name,
+ unsigned int type)
+{
+ char buf[80];
+ if (snprintf(buf, sizeof buf, "%s_0", name) >= sizeof buf)
+ return NULL;
+ return platform_get_resource_byname(pdv, type, buf);
+}
+
+/* No hotplugging on the platform bus - use __init */
+static int __init wdt_gpi_probe(struct device *dev)
+{
+ int res;
+ struct platform_device * const pdv = to_platform_device(dev);
+ const struct resource
+ * const rr = wdt_gpi_get_resource(pdv, WDT_RESOURCE_REGS,
+ IORESOURCE_MEM),
+ * const ri = wdt_gpi_get_resource(pdv, WDT_RESOURCE_IRQ,
+ IORESOURCE_IRQ),
+ * const rc = wdt_gpi_get_resource(pdv, WDT_RESOURCE_COUNTER,
+ 0);
+
+ if (unlikely(!rr || !ri || !rc))
+ return -ENXIO;
+
+ wd_regs = ioremap_nocache(rr->start, rr->end + 1 - rr->start);
+ if (unlikely(!wd_regs))
+ return -ENOMEM;
+ wd_irq = ri->start;
+ wd_ctr = rc->start;
+ res = misc_register(&miscdev);
+ if (res)
+ iounmap(wd_regs);
+ else
+ register_reboot_notifier(&wdt_gpi_shutdown);
+ return res;
+}
+
+static int __exit wdt_gpi_remove(struct device *dev)
+{
+ int res;
+
+ unregister_reboot_notifier(&wdt_gpi_shutdown);
+ res = misc_deregister(&miscdev);
+ iounmap(wd_regs);
+ wd_regs = NULL;
+ return res;
+}
+
+
+/* Device driver init & exit */
+static struct device_driver wdt_gpi_driver = {
+ .name = (char *) wdt_gpi_name,
+ .bus = &platform_bus_type,
+ .owner = THIS_MODULE,
+ .probe = wdt_gpi_probe,
+ .remove = __exit_p(wdt_gpi_remove),
+ .shutdown = NULL,
+ .suspend = NULL,
+ .resume = NULL,
+};
+
+static int __init wdt_gpi_init_module(void)
+{
+ atomic_set(&opencnt, 1);
+ if (timeout > MAX_TIMEOUT_SECONDS)
+ timeout = MAX_TIMEOUT_SECONDS;
+ return driver_register(&wdt_gpi_driver);
+}
+
+static void __exit wdt_gpi_cleanup_module(void)
+{
+ driver_unregister(&wdt_gpi_driver);
+}
+
+module_init(wdt_gpi_init_module);
+module_exit(wdt_gpi_cleanup_module);
+
+MODULE_AUTHOR("Thomas Koeller <thomas.koeller@baslerweb.com>");
+MODULE_DESCRIPTION("Basler eXcite watchdog driver for gpi devices");
+MODULE_VERSION("0.1");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 510816c16da3..04bee524e31a 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -125,6 +125,7 @@ config I2C_I801
ICH7
ESB2
ICH8
+ ICH9
This driver can also be built as a module. If so, the module
will be called i2c-i801.
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index bbb2fbee836f..c7be2fdbd86b 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -33,6 +33,7 @@
ICH7 27DA
ESB2 269B
ICH8 283E
+ ICH9 2930
This driver supports several versions of Intel's I/O Controller Hubs (ICH).
For SMBus support, they are similar to the PIIX4 and are part
of Intel's '810' and other chipsets.
@@ -457,6 +458,7 @@ static struct pci_device_id i801_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_17) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_17) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_5) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_6) },
{ 0, }
};
diff --git a/drivers/i2c/busses/i2c-ixp4xx.c b/drivers/i2c/busses/i2c-ixp4xx.c
index 05fffb9415a2..68fe863f9d54 100644
--- a/drivers/i2c/busses/i2c-ixp4xx.c
+++ b/drivers/i2c/busses/i2c-ixp4xx.c
@@ -138,7 +138,7 @@ static int ixp4xx_i2c_probe(struct platform_device *plat_dev)
gpio_line_set(gpio->sda_pin, 0);
err = i2c_bit_add_bus(&drv_data->adapter);
- if (err != 0)
+ if (err) {
printk(KERN_ERR "ERROR: Could not install %s\n", plat_dev->dev.bus_id);
kfree(drv_data);
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 3f869033ed70..94a4e9a3013c 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -42,7 +42,7 @@ static struct i2c_driver i2cdev_driver;
struct i2c_dev {
struct list_head list;
struct i2c_adapter *adap;
- struct class_device *class_dev;
+ struct device *dev;
};
#define I2C_MINORS 256
@@ -92,15 +92,16 @@ static void return_i2c_dev(struct i2c_dev *i2c_dev)
spin_unlock(&i2c_dev_list_lock);
}
-static ssize_t show_adapter_name(struct class_device *class_dev, char *buf)
+static ssize_t show_adapter_name(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
- struct i2c_dev *i2c_dev = i2c_dev_get_by_minor(MINOR(class_dev->devt));
+ struct i2c_dev *i2c_dev = i2c_dev_get_by_minor(MINOR(dev->devt));
if (!i2c_dev)
return -ENODEV;
return sprintf(buf, "%s\n", i2c_dev->adap->name);
}
-static CLASS_DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL);
+static DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL);
static ssize_t i2cdev_read (struct file *file, char __user *buf, size_t count,
loff_t *offset)
@@ -413,15 +414,14 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap)
return PTR_ERR(i2c_dev);
/* register this i2c device with the driver core */
- i2c_dev->class_dev = class_device_create(i2c_dev_class, NULL,
- MKDEV(I2C_MAJOR, adap->nr),
- &adap->dev, "i2c-%d",
- adap->nr);
- if (!i2c_dev->class_dev) {
+ i2c_dev->dev = device_create(i2c_dev_class, &adap->dev,
+ MKDEV(I2C_MAJOR, adap->nr),
+ "i2c-%d", adap->nr);
+ if (!i2c_dev->dev) {
res = -ENODEV;
goto error;
}
- res = class_device_create_file(i2c_dev->class_dev, &class_device_attr_name);
+ res = device_create_file(i2c_dev->dev, &dev_attr_name);
if (res)
goto error_destroy;
@@ -429,7 +429,7 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap)
adap->name, adap->nr);
return 0;
error_destroy:
- class_device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
+ device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
error:
return_i2c_dev(i2c_dev);
kfree(i2c_dev);
@@ -444,9 +444,9 @@ static int i2cdev_detach_adapter(struct i2c_adapter *adap)
if (!i2c_dev) /* attach_adapter must have failed */
return 0;
- class_device_remove_file(i2c_dev->class_dev, &class_device_attr_name);
+ device_remove_file(i2c_dev->dev, &dev_attr_name);
return_i2c_dev(i2c_dev);
- class_device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
+ device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
kfree(i2c_dev);
pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name);
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index 8ccee9c769f8..e3a267622bb6 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -1635,7 +1635,7 @@ static int idefloppy_begin_format(ide_drive_t *drive, int __user *arg)
/*
** Get ATAPI_FORMAT_UNIT progress indication.
**
-** Userland gives a pointer to an int. The int is set to a progresss
+** Userland gives a pointer to an int. The int is set to a progress
** indicator 0-65536, with 65536=100%.
**
** If the drive does not support format progress indication, we just check
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
index 244f7eb7006d..cfad09accf52 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/pci/sgiioc4.c
@@ -768,14 +768,7 @@ ioc4_ide_init(void)
return ioc4_register_submodule(&ioc4_ide_submodule);
}
-static void __devexit
-ioc4_ide_exit(void)
-{
- ioc4_unregister_submodule(&ioc4_ide_submodule);
-}
-
late_initcall(ioc4_ide_init); /* Call only after IDE init is done */
-module_exit(ioc4_ide_exit);
MODULE_AUTHOR("Aniket Malatpure/Jeremy Higdon");
MODULE_DESCRIPTION("IDE PCI driver module for SGI IOC4 Base-IO Card");
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index 84b2f5cb3722..af939796750d 100644
--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -139,7 +139,7 @@ static void queue_req(struct addr_req *req)
mutex_lock(&lock);
list_for_each_entry_reverse(temp_req, &req_list, list) {
- if (time_after(req->timeout, temp_req->timeout))
+ if (time_after_eq(req->timeout, temp_req->timeout))
break;
}
@@ -225,19 +225,17 @@ static void process_req(struct work_struct *work)
mutex_lock(&lock);
list_for_each_entry_safe(req, temp_req, &req_list, list) {
- if (req->status) {
+ if (req->status == -ENODATA) {
src_in = (struct sockaddr_in *) &req->src_addr;
dst_in = (struct sockaddr_in *) &req->dst_addr;
req->status = addr_resolve_remote(src_in, dst_in,
req->addr);
+ if (req->status && time_after_eq(jiffies, req->timeout))
+ req->status = -ETIMEDOUT;
+ else if (req->status == -ENODATA)
+ continue;
}
- if (req->status && time_after(jiffies, req->timeout))
- req->status = -ETIMEDOUT;
- else if (req->status == -ENODATA)
- continue;
-
- list_del(&req->list);
- list_add_tail(&req->list, &done_list);
+ list_move_tail(&req->list, &done_list);
}
if (!list_empty(&req_list)) {
@@ -347,8 +345,7 @@ void rdma_addr_cancel(struct rdma_dev_addr *addr)
if (req->addr == addr) {
req->status = -ECANCELED;
req->timeout = jiffies;
- list_del(&req->list);
- list_add(&req->list, &req_list);
+ list_move(&req->list, &req_list);
set_timeout(req->timeout);
break;
}
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index e1990f531d0a..79c937bf6962 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -147,12 +147,12 @@ struct cm_id_private {
__be32 rq_psn;
int timeout_ms;
enum ib_mtu path_mtu;
+ __be16 pkey;
u8 private_data_len;
u8 max_cm_retries;
u8 peer_to_peer;
u8 responder_resources;
u8 initiator_depth;
- u8 local_ack_timeout;
u8 retry_count;
u8 rnr_retry_count;
u8 service_timeout;
@@ -240,11 +240,10 @@ static void * cm_copy_private_data(const void *private_data,
if (!private_data || !private_data_len)
return NULL;
- data = kmalloc(private_data_len, GFP_KERNEL);
+ data = kmemdup(private_data, private_data_len, GFP_KERNEL);
if (!data)
return ERR_PTR(-ENOMEM);
- memcpy(data, private_data, private_data_len);
return data;
}
@@ -690,7 +689,7 @@ static void cm_enter_timewait(struct cm_id_private *cm_id_priv)
* timewait before notifying the user that we've exited timewait.
*/
cm_id_priv->id.state = IB_CM_TIMEWAIT;
- wait_time = cm_convert_to_ms(cm_id_priv->local_ack_timeout);
+ wait_time = cm_convert_to_ms(cm_id_priv->av.packet_life_time + 1);
queue_delayed_work(cm.wq, &cm_id_priv->timewait_info->work.work,
msecs_to_jiffies(wait_time));
cm_id_priv->timewait_info = NULL;
@@ -1009,6 +1008,7 @@ int ib_send_cm_req(struct ib_cm_id *cm_id,
cm_id_priv->responder_resources = param->responder_resources;
cm_id_priv->retry_count = param->retry_count;
cm_id_priv->path_mtu = param->primary_path->mtu;
+ cm_id_priv->pkey = param->primary_path->pkey;
cm_id_priv->qp_type = param->qp_type;
ret = cm_alloc_msg(cm_id_priv, &cm_id_priv->msg);
@@ -1023,8 +1023,6 @@ int ib_send_cm_req(struct ib_cm_id *cm_id,
cm_id_priv->local_qpn = cm_req_get_local_qpn(req_msg);
cm_id_priv->rq_psn = cm_req_get_starting_psn(req_msg);
- cm_id_priv->local_ack_timeout =
- cm_req_get_primary_local_ack_timeout(req_msg);
spin_lock_irqsave(&cm_id_priv->lock, flags);
ret = ib_post_send_mad(cm_id_priv->msg, NULL);
@@ -1409,9 +1407,8 @@ static int cm_req_handler(struct cm_work *work)
cm_id_priv->initiator_depth = cm_req_get_resp_res(req_msg);
cm_id_priv->responder_resources = cm_req_get_init_depth(req_msg);
cm_id_priv->path_mtu = cm_req_get_path_mtu(req_msg);
+ cm_id_priv->pkey = req_msg->pkey;
cm_id_priv->sq_psn = cm_req_get_starting_psn(req_msg);
- cm_id_priv->local_ack_timeout =
- cm_req_get_primary_local_ack_timeout(req_msg);
cm_id_priv->retry_count = cm_req_get_retry_count(req_msg);
cm_id_priv->rnr_retry_count = cm_req_get_rnr_retry_count(req_msg);
cm_id_priv->qp_type = cm_req_get_qp_type(req_msg);
@@ -1715,7 +1712,7 @@ static int cm_establish_handler(struct cm_work *work)
unsigned long flags;
int ret;
- /* See comment in ib_cm_establish about lookup. */
+ /* See comment in cm_establish about lookup. */
cm_id_priv = cm_acquire_id(work->local_id, work->remote_id);
if (!cm_id_priv)
return -EINVAL;
@@ -2401,11 +2398,16 @@ int ib_send_cm_lap(struct ib_cm_id *cm_id,
cm_id_priv = container_of(cm_id, struct cm_id_private, id);
spin_lock_irqsave(&cm_id_priv->lock, flags);
if (cm_id->state != IB_CM_ESTABLISHED ||
- cm_id->lap_state != IB_CM_LAP_IDLE) {
+ (cm_id->lap_state != IB_CM_LAP_UNINIT &&
+ cm_id->lap_state != IB_CM_LAP_IDLE)) {
ret = -EINVAL;
goto out;
}
+ ret = cm_init_av_by_path(alternate_path, &cm_id_priv->alt_av);
+ if (ret)
+ goto out;
+
ret = cm_alloc_msg(cm_id_priv, &msg);
if (ret)
goto out;
@@ -2430,7 +2432,8 @@ out: spin_unlock_irqrestore(&cm_id_priv->lock, flags);
}
EXPORT_SYMBOL(ib_send_cm_lap);
-static void cm_format_path_from_lap(struct ib_sa_path_rec *path,
+static void cm_format_path_from_lap(struct cm_id_private *cm_id_priv,
+ struct ib_sa_path_rec *path,
struct cm_lap_msg *lap_msg)
{
memset(path, 0, sizeof *path);
@@ -2442,10 +2445,10 @@ static void cm_format_path_from_lap(struct ib_sa_path_rec *path,
path->hop_limit = lap_msg->alt_hop_limit;
path->traffic_class = cm_lap_get_traffic_class(lap_msg);
path->reversible = 1;
- /* pkey is same as in REQ */
+ path->pkey = cm_id_priv->pkey;
path->sl = cm_lap_get_sl(lap_msg);
path->mtu_selector = IB_SA_EQ;
- /* mtu is same as in REQ */
+ path->mtu = cm_id_priv->path_mtu;
path->rate_selector = IB_SA_EQ;
path->rate = cm_lap_get_packet_rate(lap_msg);
path->packet_life_time_selector = IB_SA_EQ;
@@ -2471,7 +2474,7 @@ static int cm_lap_handler(struct cm_work *work)
param = &work->cm_event.param.lap_rcvd;
param->alternate_path = &work->path[0];
- cm_format_path_from_lap(param->alternate_path, lap_msg);
+ cm_format_path_from_lap(cm_id_priv, param->alternate_path, lap_msg);
work->cm_event.private_data = &lap_msg->private_data;
spin_lock_irqsave(&cm_id_priv->lock, flags);
@@ -2479,6 +2482,7 @@ static int cm_lap_handler(struct cm_work *work)
goto unlock;
switch (cm_id_priv->id.lap_state) {
+ case IB_CM_LAP_UNINIT:
case IB_CM_LAP_IDLE:
break;
case IB_CM_MRA_LAP_SENT:
@@ -2501,6 +2505,10 @@ static int cm_lap_handler(struct cm_work *work)
cm_id_priv->id.lap_state = IB_CM_LAP_RCVD;
cm_id_priv->tid = lap_msg->hdr.tid;
+ cm_init_av_for_response(work->port, work->mad_recv_wc->wc,
+ work->mad_recv_wc->recv_buf.grh,
+ &cm_id_priv->av);
+ cm_init_av_by_path(param->alternate_path, &cm_id_priv->alt_av);
ret = atomic_inc_and_test(&cm_id_priv->work_count);
if (!ret)
list_add_tail(&work->list, &cm_id_priv->work_list);
@@ -3039,7 +3047,7 @@ static void cm_work_handler(struct work_struct *_work)
cm_free_work(work);
}
-int ib_cm_establish(struct ib_cm_id *cm_id)
+static int cm_establish(struct ib_cm_id *cm_id)
{
struct cm_id_private *cm_id_priv;
struct cm_work *work;
@@ -3087,7 +3095,44 @@ int ib_cm_establish(struct ib_cm_id *cm_id)
out:
return ret;
}
-EXPORT_SYMBOL(ib_cm_establish);
+
+static int cm_migrate(struct ib_cm_id *cm_id)
+{
+ struct cm_id_private *cm_id_priv;
+ unsigned long flags;
+ int ret = 0;
+
+ cm_id_priv = container_of(cm_id, struct cm_id_private, id);
+ spin_lock_irqsave(&cm_id_priv->lock, flags);
+ if (cm_id->state == IB_CM_ESTABLISHED &&
+ (cm_id->lap_state == IB_CM_LAP_UNINIT ||
+ cm_id->lap_state == IB_CM_LAP_IDLE)) {
+ cm_id->lap_state = IB_CM_LAP_IDLE;
+ cm_id_priv->av = cm_id_priv->alt_av;
+ } else
+ ret = -EINVAL;
+ spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+
+ return ret;
+}
+
+int ib_cm_notify(struct ib_cm_id *cm_id, enum ib_event_type event)
+{
+ int ret;
+
+ switch (event) {
+ case IB_EVENT_COMM_EST:
+ ret = cm_establish(cm_id);
+ break;
+ case IB_EVENT_PATH_MIG:
+ ret = cm_migrate(cm_id);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ return ret;
+}
+EXPORT_SYMBOL(ib_cm_notify);
static void cm_recv_handler(struct ib_mad_agent *mad_agent,
struct ib_mad_recv_wc *mad_recv_wc)
@@ -3172,8 +3217,7 @@ static int cm_init_qp_init_attr(struct cm_id_private *cm_id_priv,
case IB_CM_ESTABLISHED:
*qp_attr_mask = IB_QP_STATE | IB_QP_ACCESS_FLAGS |
IB_QP_PKEY_INDEX | IB_QP_PORT;
- qp_attr->qp_access_flags = IB_ACCESS_LOCAL_WRITE |
- IB_ACCESS_REMOTE_WRITE;
+ qp_attr->qp_access_flags = IB_ACCESS_REMOTE_WRITE;
if (cm_id_priv->responder_resources)
qp_attr->qp_access_flags |= IB_ACCESS_REMOTE_READ |
IB_ACCESS_REMOTE_ATOMIC;
@@ -3221,6 +3265,9 @@ static int cm_init_qp_rtr_attr(struct cm_id_private *cm_id_priv,
if (cm_id_priv->alt_av.ah_attr.dlid) {
*qp_attr_mask |= IB_QP_ALT_PATH;
qp_attr->alt_port_num = cm_id_priv->alt_av.port->port_num;
+ qp_attr->alt_pkey_index = cm_id_priv->alt_av.pkey_index;
+ qp_attr->alt_timeout =
+ cm_id_priv->alt_av.packet_life_time + 1;
qp_attr->alt_ah_attr = cm_id_priv->alt_av.ah_attr;
}
ret = 0;
@@ -3247,19 +3294,31 @@ static int cm_init_qp_rts_attr(struct cm_id_private *cm_id_priv,
case IB_CM_REP_SENT:
case IB_CM_MRA_REP_RCVD:
case IB_CM_ESTABLISHED:
- *qp_attr_mask = IB_QP_STATE | IB_QP_SQ_PSN;
- qp_attr->sq_psn = be32_to_cpu(cm_id_priv->sq_psn);
- if (cm_id_priv->qp_type == IB_QPT_RC) {
- *qp_attr_mask |= IB_QP_TIMEOUT | IB_QP_RETRY_CNT |
- IB_QP_RNR_RETRY |
- IB_QP_MAX_QP_RD_ATOMIC;
- qp_attr->timeout = cm_id_priv->local_ack_timeout;
- qp_attr->retry_cnt = cm_id_priv->retry_count;
- qp_attr->rnr_retry = cm_id_priv->rnr_retry_count;
- qp_attr->max_rd_atomic = cm_id_priv->initiator_depth;
- }
- if (cm_id_priv->alt_av.ah_attr.dlid) {
- *qp_attr_mask |= IB_QP_PATH_MIG_STATE;
+ if (cm_id_priv->id.lap_state == IB_CM_LAP_UNINIT) {
+ *qp_attr_mask = IB_QP_STATE | IB_QP_SQ_PSN;
+ qp_attr->sq_psn = be32_to_cpu(cm_id_priv->sq_psn);
+ if (cm_id_priv->qp_type == IB_QPT_RC) {
+ *qp_attr_mask |= IB_QP_TIMEOUT | IB_QP_RETRY_CNT |
+ IB_QP_RNR_RETRY |
+ IB_QP_MAX_QP_RD_ATOMIC;
+ qp_attr->timeout =
+ cm_id_priv->av.packet_life_time + 1;
+ qp_attr->retry_cnt = cm_id_priv->retry_count;
+ qp_attr->rnr_retry = cm_id_priv->rnr_retry_count;
+ qp_attr->max_rd_atomic =
+ cm_id_priv->initiator_depth;
+ }
+ if (cm_id_priv->alt_av.ah_attr.dlid) {
+ *qp_attr_mask |= IB_QP_PATH_MIG_STATE;
+ qp_attr->path_mig_state = IB_MIG_REARM;
+ }
+ } else {
+ *qp_attr_mask = IB_QP_ALT_PATH | IB_QP_PATH_MIG_STATE;
+ qp_attr->alt_port_num = cm_id_priv->alt_av.port->port_num;
+ qp_attr->alt_pkey_index = cm_id_priv->alt_av.pkey_index;
+ qp_attr->alt_timeout =
+ cm_id_priv->alt_av.packet_life_time + 1;
+ qp_attr->alt_ah_attr = cm_id_priv->alt_av.ah_attr;
qp_attr->path_mig_state = IB_MIG_REARM;
}
ret = 0;
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 189f73f3f721..985a6b564d8f 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -344,7 +344,7 @@ static int cma_init_ib_qp(struct rdma_id_private *id_priv, struct ib_qp *qp)
return ret;
qp_attr.qp_state = IB_QPS_INIT;
- qp_attr.qp_access_flags = IB_ACCESS_LOCAL_WRITE;
+ qp_attr.qp_access_flags = 0;
qp_attr.port_num = id_priv->id.port_num;
return ib_modify_qp(qp, &qp_attr, IB_QP_STATE | IB_QP_ACCESS_FLAGS |
IB_QP_PKEY_INDEX | IB_QP_PORT);
@@ -935,13 +935,8 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
mutex_lock(&lock);
ret = cma_acquire_dev(conn_id);
mutex_unlock(&lock);
- if (ret) {
- ret = -ENODEV;
- cma_exch(conn_id, CMA_DESTROYING);
- cma_release_remove(conn_id);
- rdma_destroy_id(&conn_id->id);
- goto out;
- }
+ if (ret)
+ goto release_conn_id;
conn_id->cm_id.ib = cm_id;
cm_id->context = conn_id;
@@ -951,13 +946,17 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
ret = cma_notify_user(conn_id, RDMA_CM_EVENT_CONNECT_REQUEST, 0,
ib_event->private_data + offset,
IB_CM_REQ_PRIVATE_DATA_SIZE - offset);
- if (ret) {
- /* Destroy the CM ID by returning a non-zero value. */
- conn_id->cm_id.ib = NULL;
- cma_exch(conn_id, CMA_DESTROYING);
- cma_release_remove(conn_id);
- rdma_destroy_id(&conn_id->id);
- }
+ if (!ret)
+ goto out;
+
+ /* Destroy the CM ID by returning a non-zero value. */
+ conn_id->cm_id.ib = NULL;
+
+release_conn_id:
+ cma_exch(conn_id, CMA_DESTROYING);
+ cma_release_remove(conn_id);
+ rdma_destroy_id(&conn_id->id);
+
out:
cma_release_remove(listen_id);
return ret;
@@ -1481,19 +1480,18 @@ static int cma_bind_loopback(struct rdma_id_private *id_priv)
u8 p;
mutex_lock(&lock);
+ if (list_empty(&dev_list)) {
+ ret = -ENODEV;
+ goto out;
+ }
list_for_each_entry(cma_dev, &dev_list, list)
for (p = 1; p <= cma_dev->device->phys_port_cnt; ++p)
- if (!ib_query_port (cma_dev->device, p, &port_attr) &&
+ if (!ib_query_port(cma_dev->device, p, &port_attr) &&
port_attr.state == IB_PORT_ACTIVE)
goto port_found;
- if (!list_empty(&dev_list)) {
- p = 1;
- cma_dev = list_entry(dev_list.next, struct cma_device, list);
- } else {
- ret = -ENODEV;
- goto out;
- }
+ p = 1;
+ cma_dev = list_entry(dev_list.next, struct cma_device, list);
port_found:
ret = ib_get_cached_gid(cma_dev->device, p, 0, &gid);
@@ -2123,8 +2121,6 @@ static void cma_add_one(struct ib_device *device)
cma_dev->device = device;
cma_dev->node_guid = device->node_guid;
- if (!cma_dev->node_guid)
- goto err;
init_completion(&cma_dev->comp);
atomic_set(&cma_dev->refcount, 1);
@@ -2136,9 +2132,6 @@ static void cma_add_one(struct ib_device *device)
list_for_each_entry(id_priv, &listen_any_list, list)
cma_listen_on_dev(id_priv, cma_dev);
mutex_unlock(&lock);
- return;
-err:
- kfree(cma_dev);
}
static int cma_remove_id_dev(struct rdma_id_private *id_priv)
diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c
index 9bfa785252dc..1039ad57d53b 100644
--- a/drivers/infiniband/core/iwcm.c
+++ b/drivers/infiniband/core/iwcm.c
@@ -80,7 +80,7 @@ struct iwcm_work {
* 1) in the event upcall, cm_event_handler(), for a listening cm_id. If
* the backlog is exceeded, then no more connection request events will
* be processed. cm_event_handler() returns -ENOMEM in this case. Its up
- * to the provider to reject the connectino request.
+ * to the provider to reject the connection request.
* 2) in the connection request workqueue handler, cm_conn_req_handler().
* If work elements cannot be allocated for the new connect request cm_id,
* then IWCM will call the provider reject method. This is ok since
@@ -131,26 +131,25 @@ static int alloc_work_entries(struct iwcm_id_private *cm_id_priv, int count)
}
/*
- * Save private data from incoming connection requests in the
- * cm_id_priv so the low level driver doesn't have to. Adjust
+ * Save private data from incoming connection requests to
+ * iw_cm_event, so the low level driver doesn't have to. Adjust
* the event ptr to point to the local copy.
*/
-static int copy_private_data(struct iwcm_id_private *cm_id_priv,
- struct iw_cm_event *event)
+static int copy_private_data(struct iw_cm_event *event)
{
void *p;
- p = kmalloc(event->private_data_len, GFP_ATOMIC);
+ p = kmemdup(event->private_data, event->private_data_len, GFP_ATOMIC);
if (!p)
return -ENOMEM;
- memcpy(p, event->private_data, event->private_data_len);
event->private_data = p;
return 0;
}
/*
- * Release a reference on cm_id. If the last reference is being removed
- * and iw_destroy_cm_id is waiting, wake up the waiting thread.
+ * Release a reference on cm_id. If the last reference is being
+ * released, enable the waiting thread (in iw_destroy_cm_id) to
+ * get woken up, and return 1 if a thread is already waiting.
*/
static int iwcm_deref_id(struct iwcm_id_private *cm_id_priv)
{
@@ -243,7 +242,7 @@ static int iwcm_modify_qp_sqd(struct ib_qp *qp)
/*
* CM_ID <-- CLOSING
*
- * Block if a passive or active connection is currenlty being processed. Then
+ * Block if a passive or active connection is currently being processed. Then
* process the event as follows:
* - If we are ESTABLISHED, move to CLOSING and modify the QP state
* based on the abrupt flag
@@ -408,7 +407,7 @@ int iw_cm_listen(struct iw_cm_id *cm_id, int backlog)
{
struct iwcm_id_private *cm_id_priv;
unsigned long flags;
- int ret = 0;
+ int ret;
cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
@@ -535,7 +534,7 @@ EXPORT_SYMBOL(iw_cm_accept);
int iw_cm_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param)
{
struct iwcm_id_private *cm_id_priv;
- int ret = 0;
+ int ret;
unsigned long flags;
struct ib_qp *qp;
@@ -620,7 +619,7 @@ static void cm_conn_req_handler(struct iwcm_id_private *listen_id_priv,
spin_lock_irqsave(&listen_id_priv->lock, flags);
if (listen_id_priv->state != IW_CM_STATE_LISTEN) {
spin_unlock_irqrestore(&listen_id_priv->lock, flags);
- return;
+ goto out;
}
spin_unlock_irqrestore(&listen_id_priv->lock, flags);
@@ -629,7 +628,7 @@ static void cm_conn_req_handler(struct iwcm_id_private *listen_id_priv,
listen_id_priv->id.context);
/* If the cm_id could not be created, ignore the request */
if (IS_ERR(cm_id))
- return;
+ goto out;
cm_id->provider_data = iw_event->provider_data;
cm_id->local_addr = iw_event->local_addr;
@@ -642,7 +641,7 @@ static void cm_conn_req_handler(struct iwcm_id_private *listen_id_priv,
if (ret) {
iw_cm_reject(cm_id, NULL, 0);
iw_destroy_cm_id(cm_id);
- return;
+ goto out;
}
/* Call the client CM handler */
@@ -654,6 +653,7 @@ static void cm_conn_req_handler(struct iwcm_id_private *listen_id_priv,
kfree(cm_id);
}
+out:
if (iw_event->private_data_len)
kfree(iw_event->private_data);
}
@@ -674,7 +674,7 @@ static int cm_conn_est_handler(struct iwcm_id_private *cm_id_priv,
struct iw_cm_event *iw_event)
{
unsigned long flags;
- int ret = 0;
+ int ret;
spin_lock_irqsave(&cm_id_priv->lock, flags);
@@ -704,7 +704,7 @@ static int cm_conn_rep_handler(struct iwcm_id_private *cm_id_priv,
struct iw_cm_event *iw_event)
{
unsigned long flags;
- int ret = 0;
+ int ret;
spin_lock_irqsave(&cm_id_priv->lock, flags);
/*
@@ -830,8 +830,8 @@ static int process_event(struct iwcm_id_private *cm_id_priv,
*/
static void cm_work_handler(struct work_struct *_work)
{
- struct iwcm_work lwork, *work =
- container_of(_work, struct iwcm_work, work);
+ struct iwcm_work *work = container_of(_work, struct iwcm_work, work);
+ struct iw_cm_event levent;
struct iwcm_id_private *cm_id_priv = work->cm_id;
unsigned long flags;
int empty;
@@ -844,11 +844,11 @@ static void cm_work_handler(struct work_struct *_work)
struct iwcm_work, list);
list_del_init(&work->list);
empty = list_empty(&cm_id_priv->work_list);
- lwork = *work;
+ levent = work->event;
put_work(work);
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
- ret = process_event(cm_id_priv, &work->event);
+ ret = process_event(cm_id_priv, &levent);
if (ret) {
set_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags);
destroy_cm_id(&cm_id_priv->id);
@@ -907,7 +907,7 @@ static int cm_event_handler(struct iw_cm_id *cm_id,
if ((work->event.event == IW_CM_EVENT_CONNECT_REQUEST ||
work->event.event == IW_CM_EVENT_CONNECT_REPLY) &&
work->event.private_data_len) {
- ret = copy_private_data(cm_id_priv, &work->event);
+ ret = copy_private_data(&work->event);
if (ret) {
put_work(work);
goto out;
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index 5a54ac35e961..15f38d94b3a8 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -46,7 +46,7 @@ MODULE_DESCRIPTION("kernel IB MAD API");
MODULE_AUTHOR("Hal Rosenstock");
MODULE_AUTHOR("Sean Hefty");
-static kmem_cache_t *ib_mad_cache;
+static struct kmem_cache *ib_mad_cache;
static struct list_head ib_mad_port_list;
static u32 ib_mad_client_id = 0;
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
index ad4f4d5c2924..f15220a0ee75 100644
--- a/drivers/infiniband/core/ucm.c
+++ b/drivers/infiniband/core/ucm.c
@@ -161,12 +161,14 @@ static void ib_ucm_cleanup_events(struct ib_ucm_context *ctx)
struct ib_ucm_event, ctx_list);
list_del(&uevent->file_list);
list_del(&uevent->ctx_list);
+ mutex_unlock(&ctx->file->file_mutex);
/* clear incoming connections. */
if (ib_ucm_new_cm_id(uevent->resp.event))
ib_destroy_cm_id(uevent->cm_id);
kfree(uevent);
+ mutex_lock(&ctx->file->file_mutex);
}
mutex_unlock(&ctx->file->file_mutex);
}
@@ -328,20 +330,18 @@ static int ib_ucm_event_process(struct ib_cm_event *evt,
}
if (uvt->data_len) {
- uvt->data = kmalloc(uvt->data_len, GFP_KERNEL);
+ uvt->data = kmemdup(evt->private_data, uvt->data_len, GFP_KERNEL);
if (!uvt->data)
goto err1;
- memcpy(uvt->data, evt->private_data, uvt->data_len);
uvt->resp.present |= IB_UCM_PRES_DATA;
}
if (uvt->info_len) {
- uvt->info = kmalloc(uvt->info_len, GFP_KERNEL);
+ uvt->info = kmemdup(info, uvt->info_len, GFP_KERNEL);
if (!uvt->info)
goto err2;
- memcpy(uvt->info, info, uvt->info_len);
uvt->resp.present |= IB_UCM_PRES_INFO;
}
return 0;
@@ -685,11 +685,11 @@ out:
return result;
}
-static ssize_t ib_ucm_establish(struct ib_ucm_file *file,
- const char __user *inbuf,
- int in_len, int out_len)
+static ssize_t ib_ucm_notify(struct ib_ucm_file *file,
+ const char __user *inbuf,
+ int in_len, int out_len)
{
- struct ib_ucm_establish cmd;
+ struct ib_ucm_notify cmd;
struct ib_ucm_context *ctx;
int result;
@@ -700,7 +700,7 @@ static ssize_t ib_ucm_establish(struct ib_ucm_file *file,
if (IS_ERR(ctx))
return PTR_ERR(ctx);
- result = ib_cm_establish(ctx->cm_id);
+ result = ib_cm_notify(ctx->cm_id, (enum ib_event_type) cmd.event);
ib_ucm_ctx_put(ctx);
return result;
}
@@ -1107,7 +1107,7 @@ static ssize_t (*ucm_cmd_table[])(struct ib_ucm_file *file,
[IB_USER_CM_CMD_DESTROY_ID] = ib_ucm_destroy_id,
[IB_USER_CM_CMD_ATTR_ID] = ib_ucm_attr_id,
[IB_USER_CM_CMD_LISTEN] = ib_ucm_listen,
- [IB_USER_CM_CMD_ESTABLISH] = ib_ucm_establish,
+ [IB_USER_CM_CMD_NOTIFY] = ib_ucm_notify,
[IB_USER_CM_CMD_SEND_REQ] = ib_ucm_send_req,
[IB_USER_CM_CMD_SEND_REP] = ib_ucm_send_rep,
[IB_USER_CM_CMD_SEND_RTU] = ib_ucm_send_rtu,
diff --git a/drivers/infiniband/hw/amso1100/c2.h b/drivers/infiniband/hw/amso1100/c2.h
index 1b17dcdd0505..04a9db5de881 100644
--- a/drivers/infiniband/hw/amso1100/c2.h
+++ b/drivers/infiniband/hw/amso1100/c2.h
@@ -302,7 +302,7 @@ struct c2_dev {
unsigned long pa; /* PA device memory */
void **qptr_array;
- kmem_cache_t *host_msg_cache;
+ struct kmem_cache *host_msg_cache;
struct list_head cca_link; /* adapter list */
struct list_head eh_wakeup_list; /* event wakeup list */
diff --git a/drivers/infiniband/hw/amso1100/c2_qp.c b/drivers/infiniband/hw/amso1100/c2_qp.c
index 5bcf697aa335..179d005ed4a5 100644
--- a/drivers/infiniband/hw/amso1100/c2_qp.c
+++ b/drivers/infiniband/hw/amso1100/c2_qp.c
@@ -564,6 +564,32 @@ int c2_alloc_qp(struct c2_dev *c2dev,
return err;
}
+static inline void c2_lock_cqs(struct c2_cq *send_cq, struct c2_cq *recv_cq)
+{
+ if (send_cq == recv_cq)
+ spin_lock_irq(&send_cq->lock);
+ else if (send_cq > recv_cq) {
+ spin_lock_irq(&send_cq->lock);
+ spin_lock_nested(&recv_cq->lock, SINGLE_DEPTH_NESTING);
+ } else {
+ spin_lock_irq(&recv_cq->lock);
+ spin_lock_nested(&send_cq->lock, SINGLE_DEPTH_NESTING);
+ }
+}
+
+static inline void c2_unlock_cqs(struct c2_cq *send_cq, struct c2_cq *recv_cq)
+{
+ if (send_cq == recv_cq)
+ spin_unlock_irq(&send_cq->lock);
+ else if (send_cq > recv_cq) {
+ spin_unlock(&recv_cq->lock);
+ spin_unlock_irq(&send_cq->lock);
+ } else {
+ spin_unlock(&send_cq->lock);
+ spin_unlock_irq(&recv_cq->lock);
+ }
+}
+
void c2_free_qp(struct c2_dev *c2dev, struct c2_qp *qp)
{
struct c2_cq *send_cq;
@@ -576,15 +602,9 @@ void c2_free_qp(struct c2_dev *c2dev, struct c2_qp *qp)
* Lock CQs here, so that CQ polling code can do QP lookup
* without taking a lock.
*/
- spin_lock_irq(&send_cq->lock);
- if (send_cq != recv_cq)
- spin_lock(&recv_cq->lock);
-
+ c2_lock_cqs(send_cq, recv_cq);
c2_free_qpn(c2dev, qp->qpn);
-
- if (send_cq != recv_cq)
- spin_unlock(&recv_cq->lock);
- spin_unlock_irq(&send_cq->lock);
+ c2_unlock_cqs(send_cq, recv_cq);
/*
* Destory qp in the rnic...
diff --git a/drivers/infiniband/hw/amso1100/c2_rnic.c b/drivers/infiniband/hw/amso1100/c2_rnic.c
index 623dc95f91df..1687c511cb2f 100644
--- a/drivers/infiniband/hw/amso1100/c2_rnic.c
+++ b/drivers/infiniband/hw/amso1100/c2_rnic.c
@@ -441,7 +441,7 @@ static int c2_rnic_close(struct c2_dev *c2dev)
* involves initalizing the various limits and resouce pools that
* comprise the RNIC instance.
*/
-int c2_rnic_init(struct c2_dev *c2dev)
+int __devinit c2_rnic_init(struct c2_dev *c2dev)
{
int err;
u32 qsize, msgsize;
@@ -611,7 +611,7 @@ int c2_rnic_init(struct c2_dev *c2dev)
/*
* Called by c2_remove to cleanup the RNIC resources.
*/
-void c2_rnic_term(struct c2_dev *c2dev)
+void __devexit c2_rnic_term(struct c2_dev *c2dev)
{
/* Close the open adapter instance */
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
index 01f5aa9cb56d..3d1c1c535038 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -52,7 +52,7 @@
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>");
MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver");
-MODULE_VERSION("SVNEHCA_0018");
+MODULE_VERSION("SVNEHCA_0019");
int ehca_open_aqp1 = 0;
int ehca_debug_level = 0;
@@ -790,7 +790,7 @@ int __init ehca_module_init(void)
int ret;
printk(KERN_INFO "eHCA Infiniband Device Driver "
- "(Rel.: SVNEHCA_0018)\n");
+ "(Rel.: SVNEHCA_0019)\n");
idr_init(&ehca_qp_idr);
idr_init(&ehca_cq_idr);
spin_lock_init(&ehca_qp_idr_lock);
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
index cf3e50ee2d06..8682aa50c707 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -732,8 +732,7 @@ static int prepare_sqe_rts(struct ehca_qp *my_qp, struct ehca_shca *shca,
u64 h_ret;
struct ipz_queue *squeue;
void *bad_send_wqe_p, *bad_send_wqe_v;
- void *squeue_start_p, *squeue_end_p;
- void *squeue_start_v, *squeue_end_v;
+ u64 q_ofs;
struct ehca_wqe *wqe;
int qp_num = my_qp->ib_qp.qp_num;
@@ -755,26 +754,23 @@ static int prepare_sqe_rts(struct ehca_qp *my_qp, struct ehca_shca *shca,
if (ehca_debug_level)
ehca_dmp(bad_send_wqe_v, 32, "qp_num=%x bad_wqe", qp_num);
squeue = &my_qp->ipz_squeue;
- squeue_start_p = (void*)virt_to_abs(ipz_qeit_calc(squeue, 0L));
- squeue_end_p = squeue_start_p+squeue->queue_length;
- squeue_start_v = abs_to_virt((u64)squeue_start_p);
- squeue_end_v = abs_to_virt((u64)squeue_end_p);
- ehca_dbg(&shca->ib_device, "qp_num=%x squeue_start_v=%p squeue_end_v=%p",
- qp_num, squeue_start_v, squeue_end_v);
+ if (ipz_queue_abs_to_offset(squeue, (u64)bad_send_wqe_p, &q_ofs)) {
+ ehca_err(&shca->ib_device, "failed to get wqe offset qp_num=%x"
+ " bad_send_wqe_p=%p", qp_num, bad_send_wqe_p);
+ return -EFAULT;
+ }
/* loop sets wqe's purge bit */
- wqe = (struct ehca_wqe*)bad_send_wqe_v;
+ wqe = (struct ehca_wqe*)ipz_qeit_calc(squeue, q_ofs);
*bad_wqe_cnt = 0;
while (wqe->optype != 0xff && wqe->wqef != 0xff) {
if (ehca_debug_level)
ehca_dmp(wqe, 32, "qp_num=%x wqe", qp_num);
wqe->nr_of_data_seg = 0; /* suppress data access */
wqe->wqef = WQEF_PURGE; /* WQE to be purged */
- wqe = (struct ehca_wqe*)((u8*)wqe+squeue->qe_size);
+ q_ofs = ipz_queue_advance_offset(squeue, q_ofs);
+ wqe = (struct ehca_wqe*)ipz_qeit_calc(squeue, q_ofs);
*bad_wqe_cnt = (*bad_wqe_cnt)+1;
- if ((void*)wqe >= squeue_end_v) {
- wqe = squeue_start_v;
- }
}
/*
* bad wqe will be reprocessed and ignored when pol_cq() is called,
diff --git a/drivers/infiniband/hw/ehca/ipz_pt_fn.c b/drivers/infiniband/hw/ehca/ipz_pt_fn.c
index e028ff1588cc..bf7a40088f61 100644
--- a/drivers/infiniband/hw/ehca/ipz_pt_fn.c
+++ b/drivers/infiniband/hw/ehca/ipz_pt_fn.c
@@ -70,6 +70,19 @@ void *ipz_qeit_eq_get_inc(struct ipz_queue *queue)
return ret;
}
+int ipz_queue_abs_to_offset(struct ipz_queue *queue, u64 addr, u64 *q_offset)
+{
+ int i;
+ for (i = 0; i < queue->queue_length / queue->pagesize; i++) {
+ u64 page = (u64)virt_to_abs(queue->queue_pages[i]);
+ if (addr >= page && addr < page + queue->pagesize) {
+ *q_offset = addr - page + i * queue->pagesize;
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+
int ipz_queue_ctor(struct ipz_queue *queue,
const u32 nr_of_pages,
const u32 pagesize, const u32 qe_size, const u32 nr_of_sg)
diff --git a/drivers/infiniband/hw/ehca/ipz_pt_fn.h b/drivers/infiniband/hw/ehca/ipz_pt_fn.h
index 2f13509d5257..dc3bda2634b7 100644
--- a/drivers/infiniband/hw/ehca/ipz_pt_fn.h
+++ b/drivers/infiniband/hw/ehca/ipz_pt_fn.h
@@ -150,6 +150,21 @@ static inline void *ipz_qeit_reset(struct ipz_queue *queue)
return ipz_qeit_get(queue);
}
+/*
+ * return the q_offset corresponding to an absolute address
+ */
+int ipz_queue_abs_to_offset(struct ipz_queue *queue, u64 addr, u64 *q_offset);
+
+/*
+ * return the next queue offset. don't modify the queue.
+ */
+static inline u64 ipz_queue_advance_offset(struct ipz_queue *queue, u64 offset)
+{
+ offset += queue->qe_size;
+ if (offset >= queue->queue_length) offset = 0;
+ return offset;
+}
+
/* struct generic page table */
struct ipz_pt {
u64 entries[EHCA_PT_ENTRIES];
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c
index a5456108dbad..acdee33ee1f8 100644
--- a/drivers/infiniband/hw/ipath/ipath_verbs.c
+++ b/drivers/infiniband/hw/ipath/ipath_verbs.c
@@ -1487,7 +1487,7 @@ int ipath_register_ib_device(struct ipath_devdata *dd)
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->pma_counter_select[4] = IB_PMA_PORT_XMIT_WAIT;
idev->link_width_enabled = 3; /* 1x or 4x */
/* Snapshot current HW counters to "clear" them. */
diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c
index 69599455aca2..57cdc1bc5f50 100644
--- a/drivers/infiniband/hw/mthca/mthca_av.c
+++ b/drivers/infiniband/hw/mthca/mthca_av.c
@@ -33,7 +33,6 @@
* $Id: mthca_av.c 1349 2004-12-16 21:09:43Z roland $
*/
-#include <linux/init.h>
#include <linux/string.h>
#include <linux/slab.h>
@@ -323,7 +322,7 @@ int mthca_ah_query(struct ib_ah *ibah, struct ib_ah_attr *attr)
return 0;
}
-int __devinit mthca_init_av_table(struct mthca_dev *dev)
+int mthca_init_av_table(struct mthca_dev *dev)
{
int err;
diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c
index 149b36901239..283d50b76c3d 100644
--- a/drivers/infiniband/hw/mthca/mthca_cq.c
+++ b/drivers/infiniband/hw/mthca/mthca_cq.c
@@ -36,7 +36,6 @@
* $Id: mthca_cq.c 1369 2004-12-20 16:17:07Z roland $
*/
-#include <linux/init.h>
#include <linux/hardirq.h>
#include <asm/io.h>
@@ -970,7 +969,7 @@ void mthca_free_cq(struct mthca_dev *dev,
mthca_free_mailbox(dev, mailbox);
}
-int __devinit mthca_init_cq_table(struct mthca_dev *dev)
+int mthca_init_cq_table(struct mthca_dev *dev)
{
int err;
diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c
index e284e0613a94..8ec9fa1ff9ea 100644
--- a/drivers/infiniband/hw/mthca/mthca_eq.c
+++ b/drivers/infiniband/hw/mthca/mthca_eq.c
@@ -33,7 +33,6 @@
* $Id: mthca_eq.c 1382 2004-12-24 02:21:02Z roland $
*/
-#include <linux/init.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
@@ -479,10 +478,10 @@ static irqreturn_t mthca_arbel_msi_x_interrupt(int irq, void *eq_ptr)
return IRQ_HANDLED;
}
-static int __devinit mthca_create_eq(struct mthca_dev *dev,
- int nent,
- u8 intr,
- struct mthca_eq *eq)
+static int mthca_create_eq(struct mthca_dev *dev,
+ int nent,
+ u8 intr,
+ struct mthca_eq *eq)
{
int npages;
u64 *dma_list = NULL;
@@ -664,9 +663,9 @@ static void mthca_free_irqs(struct mthca_dev *dev)
dev->eq_table.eq + i);
}
-static int __devinit mthca_map_reg(struct mthca_dev *dev,
- unsigned long offset, unsigned long size,
- void __iomem **map)
+static int mthca_map_reg(struct mthca_dev *dev,
+ unsigned long offset, unsigned long size,
+ void __iomem **map)
{
unsigned long base = pci_resource_start(dev->pdev, 0);
@@ -691,7 +690,7 @@ static void mthca_unmap_reg(struct mthca_dev *dev, unsigned long offset,
iounmap(map);
}
-static int __devinit mthca_map_eq_regs(struct mthca_dev *dev)
+static int mthca_map_eq_regs(struct mthca_dev *dev)
{
if (mthca_is_memfree(dev)) {
/*
@@ -781,7 +780,7 @@ static void mthca_unmap_eq_regs(struct mthca_dev *dev)
}
}
-int __devinit mthca_map_eq_icm(struct mthca_dev *dev, u64 icm_virt)
+int mthca_map_eq_icm(struct mthca_dev *dev, u64 icm_virt)
{
int ret;
u8 status;
@@ -825,7 +824,7 @@ void mthca_unmap_eq_icm(struct mthca_dev *dev)
__free_page(dev->eq_table.icm_page);
}
-int __devinit mthca_init_eq_table(struct mthca_dev *dev)
+int mthca_init_eq_table(struct mthca_dev *dev)
{
int err;
u8 status;
diff --git a/drivers/infiniband/hw/mthca/mthca_mad.c b/drivers/infiniband/hw/mthca/mthca_mad.c
index 45e106f14807..acfa41d968ee 100644
--- a/drivers/infiniband/hw/mthca/mthca_mad.c
+++ b/drivers/infiniband/hw/mthca/mthca_mad.c
@@ -317,7 +317,7 @@ err:
return ret;
}
-void __devexit mthca_free_agents(struct mthca_dev *dev)
+void mthca_free_agents(struct mthca_dev *dev)
{
struct ib_mad_agent *agent;
int p, q;
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
index 47ea02148368..0491ec7a7c0a 100644
--- a/drivers/infiniband/hw/mthca/mthca_main.c
+++ b/drivers/infiniband/hw/mthca/mthca_main.c
@@ -98,7 +98,7 @@ static struct mthca_profile default_profile = {
.uarc_size = 1 << 18, /* Arbel only */
};
-static int __devinit mthca_tune_pci(struct mthca_dev *mdev)
+static int mthca_tune_pci(struct mthca_dev *mdev)
{
int cap;
u16 val;
@@ -143,7 +143,7 @@ static int __devinit mthca_tune_pci(struct mthca_dev *mdev)
return 0;
}
-static int __devinit mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim *dev_lim)
+static int mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim *dev_lim)
{
int err;
u8 status;
@@ -255,7 +255,7 @@ static int __devinit mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim
return 0;
}
-static int __devinit mthca_init_tavor(struct mthca_dev *mdev)
+static int mthca_init_tavor(struct mthca_dev *mdev)
{
u8 status;
int err;
@@ -333,7 +333,7 @@ err_disable:
return err;
}
-static int __devinit mthca_load_fw(struct mthca_dev *mdev)
+static int mthca_load_fw(struct mthca_dev *mdev)
{
u8 status;
int err;
@@ -379,10 +379,10 @@ err_free:
return err;
}
-static int __devinit mthca_init_icm(struct mthca_dev *mdev,
- struct mthca_dev_lim *dev_lim,
- struct mthca_init_hca_param *init_hca,
- u64 icm_size)
+static int mthca_init_icm(struct mthca_dev *mdev,
+ struct mthca_dev_lim *dev_lim,
+ struct mthca_init_hca_param *init_hca,
+ u64 icm_size)
{
u64 aux_pages;
u8 status;
@@ -575,7 +575,7 @@ static void mthca_free_icms(struct mthca_dev *mdev)
mthca_free_icm(mdev, mdev->fw.arbel.aux_icm);
}
-static int __devinit mthca_init_arbel(struct mthca_dev *mdev)
+static int mthca_init_arbel(struct mthca_dev *mdev)
{
struct mthca_dev_lim dev_lim;
struct mthca_profile profile;
@@ -683,7 +683,7 @@ static void mthca_close_hca(struct mthca_dev *mdev)
mthca_SYS_DIS(mdev, &status);
}
-static int __devinit mthca_init_hca(struct mthca_dev *mdev)
+static int mthca_init_hca(struct mthca_dev *mdev)
{
u8 status;
int err;
@@ -720,7 +720,7 @@ err_close:
return err;
}
-static int __devinit mthca_setup_hca(struct mthca_dev *dev)
+static int mthca_setup_hca(struct mthca_dev *dev)
{
int err;
u8 status;
@@ -875,8 +875,7 @@ err_uar_table_free:
return err;
}
-static int __devinit mthca_request_regions(struct pci_dev *pdev,
- int ddr_hidden)
+static int mthca_request_regions(struct pci_dev *pdev, int ddr_hidden)
{
int err;
@@ -928,7 +927,7 @@ static void mthca_release_regions(struct pci_dev *pdev,
MTHCA_HCR_SIZE);
}
-static int __devinit mthca_enable_msi_x(struct mthca_dev *mdev)
+static int mthca_enable_msi_x(struct mthca_dev *mdev)
{
struct msix_entry entries[3];
int err;
@@ -1213,7 +1212,7 @@ int __mthca_restart_one(struct pci_dev *pdev)
}
static int __devinit mthca_init_one(struct pci_dev *pdev,
- const struct pci_device_id *id)
+ const struct pci_device_id *id)
{
static int mthca_version_printed = 0;
int ret;
diff --git a/drivers/infiniband/hw/mthca/mthca_mcg.c b/drivers/infiniband/hw/mthca/mthca_mcg.c
index 47ca8a9b7247..a8ad072be074 100644
--- a/drivers/infiniband/hw/mthca/mthca_mcg.c
+++ b/drivers/infiniband/hw/mthca/mthca_mcg.c
@@ -32,7 +32,6 @@
* $Id: mthca_mcg.c 1349 2004-12-16 21:09:43Z roland $
*/
-#include <linux/init.h>
#include <linux/string.h>
#include <linux/slab.h>
@@ -371,7 +370,7 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
return err;
}
-int __devinit mthca_init_mcg_table(struct mthca_dev *dev)
+int mthca_init_mcg_table(struct mthca_dev *dev)
{
int err;
int table_size = dev->limits.num_mgms + dev->limits.num_amgms;
diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c
index a486dec1707e..f71ffa88db3a 100644
--- a/drivers/infiniband/hw/mthca/mthca_mr.c
+++ b/drivers/infiniband/hw/mthca/mthca_mr.c
@@ -34,7 +34,6 @@
*/
#include <linux/slab.h>
-#include <linux/init.h>
#include <linux/errno.h>
#include "mthca_dev.h"
@@ -135,7 +134,7 @@ static void mthca_buddy_free(struct mthca_buddy *buddy, u32 seg, int order)
spin_unlock(&buddy->lock);
}
-static int __devinit mthca_buddy_init(struct mthca_buddy *buddy, int max_order)
+static int mthca_buddy_init(struct mthca_buddy *buddy, int max_order)
{
int i, s;
@@ -759,7 +758,7 @@ void mthca_arbel_fmr_unmap(struct mthca_dev *dev, struct mthca_fmr *fmr)
*(u8 *) fmr->mem.arbel.mpt = MTHCA_MPT_STATUS_SW;
}
-int __devinit mthca_init_mr_table(struct mthca_dev *dev)
+int mthca_init_mr_table(struct mthca_dev *dev)
{
unsigned long addr;
int err, i;
diff --git a/drivers/infiniband/hw/mthca/mthca_pd.c b/drivers/infiniband/hw/mthca/mthca_pd.c
index 59df51614c85..c1e950764bd8 100644
--- a/drivers/infiniband/hw/mthca/mthca_pd.c
+++ b/drivers/infiniband/hw/mthca/mthca_pd.c
@@ -34,7 +34,6 @@
* $Id: mthca_pd.c 1349 2004-12-16 21:09:43Z roland $
*/
-#include <linux/init.h>
#include <linux/errno.h>
#include "mthca_dev.h"
@@ -69,7 +68,7 @@ void mthca_pd_free(struct mthca_dev *dev, struct mthca_pd *pd)
mthca_free(&dev->pd_table.alloc, pd->pd_num);
}
-int __devinit mthca_init_pd_table(struct mthca_dev *dev)
+int mthca_init_pd_table(struct mthca_dev *dev)
{
return mthca_alloc_init(&dev->pd_table.alloc,
dev->limits.num_pds,
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index fc67f780581b..21422a3336ad 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -1100,11 +1100,10 @@ static struct ib_fmr *mthca_alloc_fmr(struct ib_pd *pd, int mr_access_flags,
struct mthca_fmr *fmr;
int err;
- fmr = kmalloc(sizeof *fmr, GFP_KERNEL);
+ fmr = kmemdup(fmr_attr, sizeof *fmr, GFP_KERNEL);
if (!fmr)
return ERR_PTR(-ENOMEM);
- memcpy(&fmr->attr, fmr_attr, sizeof *fmr_attr);
err = mthca_fmr_alloc(to_mdev(pd->device), to_mpd(pd)->pd_num,
convert_access(mr_access_flags), fmr);
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index 6a7822e0fc19..33e3ba7937f1 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -35,7 +35,6 @@
* $Id: mthca_qp.c 1355 2004-12-17 15:23:43Z roland $
*/
-#include <linux/init.h>
#include <linux/string.h>
#include <linux/slab.h>
@@ -2241,7 +2240,7 @@ void mthca_free_err_wqe(struct mthca_dev *dev, struct mthca_qp *qp, int is_send,
*new_wqe = 0;
}
-int __devinit mthca_init_qp_table(struct mthca_dev *dev)
+int mthca_init_qp_table(struct mthca_dev *dev)
{
int err;
u8 status;
diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c
index f5d7677d1079..34d2c4768962 100644
--- a/drivers/infiniband/hw/mthca/mthca_srq.c
+++ b/drivers/infiniband/hw/mthca/mthca_srq.c
@@ -120,7 +120,7 @@ static void mthca_arbel_init_srq_context(struct mthca_dev *dev,
memset(context, 0, sizeof *context);
- logsize = long_log2(srq->max) + srq->wqe_shift;
+ logsize = long_log2(srq->max);
context->state_logsize_srqn = cpu_to_be32(logsize << 24 | srq->srqn);
context->lkey = cpu_to_be32(srq->mr.ibmr.lkey);
context->db_index = cpu_to_be32(srq->db_index);
@@ -715,7 +715,7 @@ int mthca_max_srq_sge(struct mthca_dev *dev)
sizeof (struct mthca_data_seg));
}
-int __devinit mthca_init_srq_table(struct mthca_dev *dev)
+int mthca_init_srq_table(struct mthca_dev *dev)
{
int err;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 3b2ee0eba05e..99547996aba2 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -233,7 +233,7 @@ static inline struct ipoib_neigh **to_ipoib_neigh(struct neighbour *neigh)
}
struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neigh);
-void ipoib_neigh_free(struct ipoib_neigh *neigh);
+void ipoib_neigh_free(struct net_device *dev, struct ipoib_neigh *neigh);
extern struct workqueue_struct *ipoib_workqueue;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 71114a8c12b9..c09280243726 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -264,7 +264,7 @@ static void path_free(struct net_device *dev, struct ipoib_path *path)
if (neigh->ah)
ipoib_put_ah(neigh->ah);
- ipoib_neigh_free(neigh);
+ ipoib_neigh_free(dev, neigh);
}
spin_unlock_irqrestore(&priv->lock, flags);
@@ -525,10 +525,11 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
ipoib_send(dev, skb, path->ah, IPOIB_QPN(skb->dst->neighbour->ha));
} else {
neigh->ah = NULL;
- __skb_queue_tail(&neigh->queue, skb);
if (!path->query && path_rec_start(dev, path))
goto err_list;
+
+ __skb_queue_tail(&neigh->queue, skb);
}
spin_unlock(&priv->lock);
@@ -538,7 +539,7 @@ err_list:
list_del(&neigh->list);
err_path:
- ipoib_neigh_free(neigh);
+ ipoib_neigh_free(dev, neigh);
++priv->stats.tx_dropped;
dev_kfree_skb_any(skb);
@@ -655,7 +656,7 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
*/
ipoib_put_ah(neigh->ah);
list_del(&neigh->list);
- ipoib_neigh_free(neigh);
+ ipoib_neigh_free(dev, neigh);
spin_unlock(&priv->lock);
ipoib_path_lookup(skb, dev);
goto out;
@@ -786,7 +787,7 @@ static void ipoib_neigh_destructor(struct neighbour *n)
if (neigh->ah)
ah = neigh->ah;
list_del(&neigh->list);
- ipoib_neigh_free(neigh);
+ ipoib_neigh_free(n->dev, neigh);
}
spin_unlock_irqrestore(&priv->lock, flags);
@@ -809,9 +810,15 @@ struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neighbour)
return neigh;
}
-void ipoib_neigh_free(struct ipoib_neigh *neigh)
+void ipoib_neigh_free(struct net_device *dev, struct ipoib_neigh *neigh)
{
+ struct ipoib_dev_priv *priv = netdev_priv(dev);
+ struct sk_buff *skb;
*to_ipoib_neigh(neigh->neighbour) = NULL;
+ while ((skb = __skb_dequeue(&neigh->queue))) {
+ ++priv->stats.tx_dropped;
+ dev_kfree_skb_any(skb);
+ }
kfree(neigh);
}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index f0a4fac1a215..b04b72ca32ed 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -114,7 +114,7 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast)
*/
if (neigh->ah)
ipoib_put_ah(neigh->ah);
- ipoib_neigh_free(neigh);
+ ipoib_neigh_free(dev, neigh);
}
spin_unlock_irqrestore(&priv->lock, flags);
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h
index 9c53916f28c2..234e5b061a75 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
@@ -283,7 +283,7 @@ struct iser_global {
struct mutex connlist_mutex;
struct list_head connlist; /* all iSER IB connections */
- kmem_cache_t *desc_cache;
+ struct kmem_cache *desc_cache;
};
extern struct iser_global ig;
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 214f66195af2..a6289595557b 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -1177,9 +1177,11 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
break;
}
- target->status = srp_alloc_iu_bufs(target);
- if (target->status)
- break;
+ if (!target->rx_ring[0]) {
+ target->status = srp_alloc_iu_bufs(target);
+ if (target->status)
+ break;
+ }
qp_attr = kmalloc(sizeof *qp_attr, GFP_KERNEL);
if (!qp_attr) {
@@ -1717,7 +1719,8 @@ static ssize_t srp_create_target(struct class_device *class_dev,
if (!target_host)
return -ENOMEM;
- target_host->max_lun = SRP_MAX_LUN;
+ target_host->max_lun = SRP_MAX_LUN;
+ target_host->max_cmd_len = sizeof ((struct srp_cmd *) (void *) 0L)->cdb;
target = host_to_target(target_host);
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
index 105112fb7b57..80cdebcbcb99 100644
--- a/drivers/input/joystick/iforce/iforce-usb.c
+++ b/drivers/input/joystick/iforce/iforce-usb.c
@@ -178,9 +178,9 @@ static int iforce_usb_probe(struct usb_interface *intf,
fail:
if (iforce) {
- if (iforce->irq) usb_free_urb(iforce->irq);
- if (iforce->out) usb_free_urb(iforce->out);
- if (iforce->ctrl) usb_free_urb(iforce->ctrl);
+ usb_free_urb(iforce->irq);
+ usb_free_urb(iforce->out);
+ usb_free_urb(iforce->ctrl);
kfree(iforce);
}
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c
index ba2a2035d648..7c8d0399ae82 100644
--- a/drivers/input/serio/serio_raw.c
+++ b/drivers/input/serio/serio_raw.c
@@ -297,7 +297,7 @@ static int serio_raw_connect(struct serio *serio, struct serio_driver *drv)
serio_raw->dev.minor = PSMOUSE_MINOR;
serio_raw->dev.name = serio_raw->name;
- serio_raw->dev.dev = &serio->dev;
+ serio_raw->dev.parent = &serio->dev;
serio_raw->dev.fops = &serio_raw_fops;
err = misc_register(&serio_raw->dev);
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c
index 5800beeebb85..defd5743dba6 100644
--- a/drivers/isdn/gigaset/common.c
+++ b/drivers/isdn/gigaset/common.c
@@ -702,7 +702,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
cs->open_count = 0;
cs->dev = NULL;
cs->tty = NULL;
- cs->class = NULL;
+ cs->tty_dev = NULL;
cs->cidmode = cidmode != 0;
//if(onechannel) { //FIXME
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h
index 884bd72c1bf4..06298cc52bf5 100644
--- a/drivers/isdn/gigaset/gigaset.h
+++ b/drivers/isdn/gigaset/gigaset.h
@@ -444,7 +444,7 @@ struct cardstate {
struct gigaset_driver *driver;
unsigned minor_index;
struct device *dev;
- struct class_device *class;
+ struct device *tty_dev;
const struct gigaset_ops *ops;
diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c
index 596f3aebe2f7..7edea015867e 100644
--- a/drivers/isdn/gigaset/interface.c
+++ b/drivers/isdn/gigaset/interface.c
@@ -625,13 +625,13 @@ void gigaset_if_init(struct cardstate *cs)
return;
tasklet_init(&cs->if_wake_tasklet, &if_wake, (unsigned long) cs);
- cs->class = tty_register_device(drv->tty, cs->minor_index, NULL);
+ cs->tty_dev = tty_register_device(drv->tty, cs->minor_index, NULL);
- if (!IS_ERR(cs->class))
- class_set_devdata(cs->class, cs);
+ if (!IS_ERR(cs->tty_dev))
+ dev_set_drvdata(cs->tty_dev, cs);
else {
warn("could not register device to the tty subsystem");
- cs->class = NULL;
+ cs->tty_dev = NULL;
}
}
@@ -645,7 +645,7 @@ void gigaset_if_free(struct cardstate *cs)
tasklet_disable(&cs->if_wake_tasklet);
tasklet_kill(&cs->if_wake_tasklet);
- cs->class = NULL;
+ cs->tty_dev = NULL;
tty_unregister_device(drv->tty, cs->minor_index);
}
diff --git a/drivers/isdn/gigaset/proc.c b/drivers/isdn/gigaset/proc.c
index 9ad840e95dbe..e767afa55abf 100644
--- a/drivers/isdn/gigaset/proc.c
+++ b/drivers/isdn/gigaset/proc.c
@@ -16,11 +16,12 @@
#include "gigaset.h"
#include <linux/ctype.h>
-static ssize_t show_cidmode(struct class_device *class, char *buf)
+static ssize_t show_cidmode(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
int ret;
unsigned long flags;
- struct cardstate *cs = class_get_devdata(class);
+ struct cardstate *cs = dev_get_drvdata(dev);
spin_lock_irqsave(&cs->lock, flags);
ret = sprintf(buf, "%u\n", cs->cidmode);
@@ -29,10 +30,10 @@ static ssize_t show_cidmode(struct class_device *class, char *buf)
return ret;
}
-static ssize_t set_cidmode(struct class_device *class,
+static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct cardstate *cs = class_get_devdata(class);
+ struct cardstate *cs = dev_get_drvdata(dev);
long int value;
char *end;
@@ -64,25 +65,25 @@ static ssize_t set_cidmode(struct class_device *class,
return count;
}
-static CLASS_DEVICE_ATTR(cidmode, S_IRUGO|S_IWUSR, show_cidmode, set_cidmode);
+static DEVICE_ATTR(cidmode, S_IRUGO|S_IWUSR, show_cidmode, set_cidmode);
/* free sysfs for device */
void gigaset_free_dev_sysfs(struct cardstate *cs)
{
- if (!cs->class)
+ if (!cs->tty_dev)
return;
gig_dbg(DEBUG_INIT, "removing sysfs entries");
- class_device_remove_file(cs->class, &class_device_attr_cidmode);
+ device_remove_file(cs->tty_dev, &dev_attr_cidmode);
}
/* initialize sysfs for device */
void gigaset_init_dev_sysfs(struct cardstate *cs)
{
- if (!cs->class)
+ if (!cs->tty_dev)
return;
gig_dbg(DEBUG_INIT, "setting up sysfs");
- if (class_device_create_file(cs->class, &class_device_attr_cidmode))
+ if (device_create_file(cs->tty_dev, &dev_attr_cidmode))
dev_err(cs->dev, "could not create sysfs attribute\n");
}
diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c
index 4ffa9eb1c28e..5ebf49ac9b23 100644
--- a/drivers/isdn/gigaset/usb-gigaset.c
+++ b/drivers/isdn/gigaset/usb-gigaset.c
@@ -815,14 +815,11 @@ static int gigaset_probe(struct usb_interface *interface,
return 0;
error:
- if (ucs->read_urb)
- usb_kill_urb(ucs->read_urb);
+ usb_kill_urb(ucs->read_urb);
kfree(ucs->bulk_out_buffer);
- if (ucs->bulk_out_urb != NULL)
- usb_free_urb(ucs->bulk_out_urb);
+ usb_free_urb(ucs->bulk_out_urb);
kfree(cs->inbuf[0].rcvbuf);
- if (ucs->read_urb != NULL)
- usb_free_urb(ucs->read_urb);
+ 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;
@@ -850,11 +847,9 @@ static void gigaset_disconnect(struct usb_interface *interface)
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);
+ usb_free_urb(ucs->bulk_out_urb);
kfree(cs->inbuf[0].rcvbuf);
- if (ucs->read_urb != NULL)
- usb_free_urb(ucs->read_urb);
+ usb_free_urb(ucs->read_urb);
ucs->read_urb = ucs->bulk_out_urb = NULL;
cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL;
diff --git a/drivers/isdn/hardware/eicon/os_4bri.c b/drivers/isdn/hardware/eicon/os_4bri.c
index 11e6f937c1e4..7b4ec3f60dbf 100644
--- a/drivers/isdn/hardware/eicon/os_4bri.c
+++ b/drivers/isdn/hardware/eicon/os_4bri.c
@@ -464,7 +464,7 @@ int diva_4bri_init_card(diva_os_xdi_adapter_t * a)
/*
** Cleanup function will be called for master adapter only
-** this is garanteed by design: cleanup callback is set
+** this is guaranteed by design: cleanup callback is set
** by master adapter only
*/
static int diva_4bri_cleanup_adapter(diva_os_xdi_adapter_t * a)
diff --git a/drivers/isdn/hisax/hfc4s8s_l1.h b/drivers/isdn/hisax/hfc4s8s_l1.h
index e8f9c077fa85..9d5d2a56b4e9 100644
--- a/drivers/isdn/hisax/hfc4s8s_l1.h
+++ b/drivers/isdn/hisax/hfc4s8s_l1.h
@@ -16,7 +16,7 @@
/*
* include Genero generated HFC-4S/8S header file hfc48scu.h
-* for comlete register description. This will define _HFC48SCU_H_
+* for complete register description. This will define _HFC48SCU_H_
* to prevent redefinitions
*/
diff --git a/drivers/isdn/hisax/isdnl2.c b/drivers/isdn/hisax/isdnl2.c
index 6d0431725555..cd3b5ad53491 100644
--- a/drivers/isdn/hisax/isdnl2.c
+++ b/drivers/isdn/hisax/isdnl2.c
@@ -1442,7 +1442,7 @@ l2_tei_remove(struct FsmInst *fi, int event, void *arg)
}
static void
-l2_st14_persistant_da(struct FsmInst *fi, int event, void *arg)
+l2_st14_persistent_da(struct FsmInst *fi, int event, void *arg)
{
struct PStack *st = fi->userdata;
@@ -1453,7 +1453,7 @@ l2_st14_persistant_da(struct FsmInst *fi, int event, void *arg)
}
static void
-l2_st5_persistant_da(struct FsmInst *fi, int event, void *arg)
+l2_st5_persistent_da(struct FsmInst *fi, int event, void *arg)
{
struct PStack *st = fi->userdata;
@@ -1466,7 +1466,7 @@ l2_st5_persistant_da(struct FsmInst *fi, int event, void *arg)
}
static void
-l2_st6_persistant_da(struct FsmInst *fi, int event, void *arg)
+l2_st6_persistent_da(struct FsmInst *fi, int event, void *arg)
{
struct PStack *st = fi->userdata;
@@ -1477,7 +1477,7 @@ l2_st6_persistant_da(struct FsmInst *fi, int event, void *arg)
}
static void
-l2_persistant_da(struct FsmInst *fi, int event, void *arg)
+l2_persistent_da(struct FsmInst *fi, int event, void *arg)
{
struct PStack *st = fi->userdata;
@@ -1612,14 +1612,14 @@ static struct FsmNode L2FnList[] __initdata =
{ST_L2_6, EV_L2_FRAME_ERROR, l2_frame_error},
{ST_L2_7, EV_L2_FRAME_ERROR, l2_frame_error_reest},
{ST_L2_8, EV_L2_FRAME_ERROR, l2_frame_error_reest},
- {ST_L2_1, EV_L1_DEACTIVATE, l2_st14_persistant_da},
+ {ST_L2_1, EV_L1_DEACTIVATE, l2_st14_persistent_da},
{ST_L2_2, EV_L1_DEACTIVATE, l2_st24_tei_remove},
{ST_L2_3, EV_L1_DEACTIVATE, l2_st3_tei_remove},
- {ST_L2_4, EV_L1_DEACTIVATE, l2_st14_persistant_da},
- {ST_L2_5, EV_L1_DEACTIVATE, l2_st5_persistant_da},
- {ST_L2_6, EV_L1_DEACTIVATE, l2_st6_persistant_da},
- {ST_L2_7, EV_L1_DEACTIVATE, l2_persistant_da},
- {ST_L2_8, EV_L1_DEACTIVATE, l2_persistant_da},
+ {ST_L2_4, EV_L1_DEACTIVATE, l2_st14_persistent_da},
+ {ST_L2_5, EV_L1_DEACTIVATE, l2_st5_persistent_da},
+ {ST_L2_6, EV_L1_DEACTIVATE, l2_st6_persistent_da},
+ {ST_L2_7, EV_L1_DEACTIVATE, l2_persistent_da},
+ {ST_L2_8, EV_L1_DEACTIVATE, l2_persistent_da},
};
#define L2_FN_COUNT (sizeof(L2FnList)/sizeof(struct FsmNode))
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c
index dd0bcbe140bd..8458ff3f351e 100644
--- a/drivers/media/dvb/cinergyT2/cinergyT2.c
+++ b/drivers/media/dvb/cinergyT2/cinergyT2.c
@@ -275,8 +275,7 @@ static void cinergyt2_free_stream_urbs (struct cinergyt2 *cinergyt2)
int i;
for (i=0; i<STREAM_URB_COUNT; i++)
- if (cinergyt2->stream_urb[i])
- usb_free_urb(cinergyt2->stream_urb[i]);
+ usb_free_urb(cinergyt2->stream_urb[i]);
usb_buffer_free(cinergyt2->udev, STREAM_URB_COUNT*STREAM_BUF_SIZE,
cinergyt2->streambuf, cinergyt2->streambuf_dmahandle);
@@ -320,8 +319,7 @@ static void cinergyt2_stop_stream_xfer (struct cinergyt2 *cinergyt2)
cinergyt2_control_stream_transfer(cinergyt2, 0);
for (i=0; i<STREAM_URB_COUNT; i++)
- if (cinergyt2->stream_urb[i])
- usb_kill_urb(cinergyt2->stream_urb[i]);
+ usb_kill_urb(cinergyt2->stream_urb[i]);
}
static int cinergyt2_start_stream_xfer (struct cinergyt2 *cinergyt2)
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index 53304e6991ac..a2ab2eebfc68 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -348,7 +348,7 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
{
- fe_status_t s;
+ fe_status_t s = 0;
struct dvb_frontend_private *fepriv = fe->frontend_priv;
/* if we've got no parameters, just keep idling */
diff --git a/drivers/media/dvb/frontends/tda10086.c b/drivers/media/dvb/frontends/tda10086.c
index 7456b0b9976b..4c27a2d90a38 100644
--- a/drivers/media/dvb/frontends/tda10086.c
+++ b/drivers/media/dvb/frontends/tda10086.c
@@ -441,6 +441,10 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
dprintk ("%s\n", __FUNCTION__);
+ // check for invalid symbol rate
+ if (fe_params->u.qpsk.symbol_rate < 500000)
+ return -EINVAL;
+
// calculate the updated frequency (note: we convert from Hz->kHz)
tmp64 = tda10086_read_byte(state, 0x52);
tmp64 |= (tda10086_read_byte(state, 0x51) << 8);
diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c
index fc1267b8c892..9a155396d6ac 100644
--- a/drivers/media/dvb/ttpci/budget-patch.c
+++ b/drivers/media/dvb/ttpci/budget-patch.c
@@ -500,14 +500,14 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte
/* New design (By Emard)
** this rps1 code will copy internal HS event to GPIO3 pin.
-** GPIO3 is in budget-patch hardware connectd to port B VSYNC
+** GPIO3 is in budget-patch hardware connected to port B VSYNC
** HS is an internal event of 7146, accessible with RPS
** and temporarily raised high every n lines
** (n in defined in the RPS_THRESH1 counter threshold)
** I think HS is raised high on the beginning of the n-th line
** and remains high until this n-th line that triggered
-** it is completely received. When the receiption of n-th line
+** it is completely received. When the reception of n-th line
** ends, HS is lowered.
** To transmit data over DMA, 7146 needs changing state at
@@ -541,7 +541,7 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte
** hardware debug note: a working budget card (including budget patch)
** with vpeirq() interrupt setup in mode "0x90" (every 64K) will
** generate 3 interrupts per 25-Hz DMA frame of 2*188*512 bytes
-** and that means 3*25=75 Hz of interrupt freqency, as seen by
+** and that means 3*25=75 Hz of interrupt frequency, as seen by
** watch cat /proc/interrupts
**
** If this frequency is 3x lower (and data received in the DMA
@@ -550,7 +550,7 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte
** this means VSYNC line is not connected in the hardware.
** (check soldering pcb and pins)
** The same behaviour of missing VSYNC can be duplicated on budget
-** cards, by seting DD1_INIT trigger mode 7 in 3rd nibble.
+** cards, by setting DD1_INIT trigger mode 7 in 3rd nibble.
*/
// Setup RPS1 "program" (p35)
diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c
index e58f0391e9d1..56f1c80defc6 100644
--- a/drivers/media/dvb/ttpci/budget.c
+++ b/drivers/media/dvb/ttpci/budget.c
@@ -46,6 +46,10 @@
#include "lnbp21.h"
#include "bsru6.h"
+static int diseqc_method;
+module_param(diseqc_method, int, 0444);
+MODULE_PARM_DESC(diseqc_method, "Select DiSEqC method for subsystem id 13c2:1003, 0: default, 1: more reliable (for newer revisions only)");
+
static void Set22K (struct budget *budget, int state)
{
struct saa7146_dev *dev=budget->dev;
@@ -382,6 +386,11 @@ static void frontend_init(struct budget *budget)
if (budget->dvb_frontend) {
budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
+ if (budget->dev->pci->subsystem_device == 0x1003 && diseqc_method == 0) {
+ budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
+ budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst;
+ budget->dvb_frontend->ops.set_tone = budget_set_tone;
+ }
break;
}
break;
diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
index a1c9fa9919ea..8135f3e76aeb 100644
--- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
@@ -1135,8 +1135,7 @@ static void ttusb_dec_free_iso_urbs(struct ttusb_dec *dec)
dprintk("%s\n", __FUNCTION__);
for (i = 0; i < ISO_BUF_COUNT; i++)
- if (dec->iso_urb[i])
- usb_free_urb(dec->iso_urb[i]);
+ usb_free_urb(dec->iso_urb[i]);
pci_free_consistent(NULL,
ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF *
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index bf267552941f..b8fde5cf4735 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -24,7 +24,7 @@ config VIDEO_HELPER_CHIPS_AUTO
decode audio/video standards. This option will autoselect
all pertinent modules to each selected video module.
- Unselect this only if you know exaclty what you are doing, since
+ Unselect this only if you know exactly what you are doing, since
it may break support on some boards.
In doubt, say Y.
diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c
index f786ab11d2cd..86e353b26b53 100644
--- a/drivers/media/video/et61x251/et61x251_core.c
+++ b/drivers/media/video/et61x251/et61x251_core.c
@@ -1182,8 +1182,6 @@ static void et61x251_release_resources(struct et61x251_device* cam)
video_set_drvdata(cam->v4ldev, NULL);
video_unregister_device(cam->v4ldev);
- usb_put_dev(cam->usbdev);
-
mutex_unlock(&et61x251_sysfs_lock);
kfree(cam->control_buffer);
@@ -1275,6 +1273,7 @@ static int et61x251_release(struct inode* inode, struct file* filp)
if (cam->state & DEV_DISCONNECTED) {
et61x251_release_resources(cam);
+ usb_put_dev(cam->usbdev);
mutex_unlock(&cam->dev_mutex);
kfree(cam);
return 0;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index f920e0ccacd3..1f787333d18c 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -1953,8 +1953,8 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
return hdw;
fail:
if (hdw) {
- if (hdw->ctl_read_urb) usb_free_urb(hdw->ctl_read_urb);
- if (hdw->ctl_write_urb) usb_free_urb(hdw->ctl_write_urb);
+ usb_free_urb(hdw->ctl_read_urb);
+ usb_free_urb(hdw->ctl_write_urb);
if (hdw->ctl_read_buffer) kfree(hdw->ctl_read_buffer);
if (hdw->ctl_write_buffer) kfree(hdw->ctl_write_buffer);
if (hdw->controls) kfree(hdw->controls);
@@ -2575,12 +2575,10 @@ static void pvr2_ctl_timeout(unsigned long data)
struct pvr2_hdw *hdw = (struct pvr2_hdw *)data;
if (hdw->ctl_write_pend_flag || hdw->ctl_read_pend_flag) {
hdw->ctl_timeout_flag = !0;
- if (hdw->ctl_write_pend_flag && hdw->ctl_write_urb) {
+ if (hdw->ctl_write_pend_flag)
usb_unlink_urb(hdw->ctl_write_urb);
- }
- if (hdw->ctl_read_pend_flag && hdw->ctl_read_urb) {
+ if (hdw->ctl_read_pend_flag)
usb_unlink_urb(hdw->ctl_read_urb);
- }
}
}
diff --git a/drivers/media/video/pvrusb2/pvrusb2-io.c b/drivers/media/video/pvrusb2/pvrusb2-io.c
index 70aa63eba0cb..57fb32033543 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-io.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-io.c
@@ -289,7 +289,7 @@ static void pvr2_buffer_done(struct pvr2_buffer *bp)
pvr2_buffer_set_none(bp);
bp->signature = 0;
bp->stream = NULL;
- if (bp->purb) usb_free_urb(bp->purb);
+ usb_free_urb(bp->purb);
pvr2_trace(PVR2_TRACE_BUF_POOL,"/*---TRACE_FLOW---*/"
" bufferDone %p",bp);
}
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
index 46c114830884..a996aad79276 100644
--- a/drivers/media/video/pwc/pwc-if.c
+++ b/drivers/media/video/pwc/pwc-if.c
@@ -866,11 +866,9 @@ int pwc_isoc_init(struct pwc_device *pdev)
}
if (ret) {
/* De-allocate in reverse order */
- while (i >= 0) {
- if (pdev->sbuf[i].urb != NULL)
- usb_free_urb(pdev->sbuf[i].urb);
+ while (i--) {
+ usb_free_urb(pdev->sbuf[i].urb);
pdev->sbuf[i].urb = NULL;
- i--;
}
return ret;
}
@@ -1095,8 +1093,7 @@ static int pwc_video_open(struct inode *inode, struct file *file)
PWC_DEBUG_OPEN(">> video_open called(vdev = 0x%p).\n", vdev);
pdev = (struct pwc_device *)vdev->priv;
- if (pdev == NULL)
- BUG();
+ BUG_ON(!pdev);
if (pdev->vopen) {
PWC_DEBUG_OPEN("I'm busy, someone is using the device.\n");
return -EBUSY;
diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c
index 8ba05c214ca7..92eabf88a09b 100644
--- a/drivers/media/video/saa6588.c
+++ b/drivers/media/video/saa6588.c
@@ -212,8 +212,10 @@ static void read_from_buf(struct saa6588 *s, struct rds_command *a)
if (rd_blocks > s->block_count)
rd_blocks = s->block_count;
- if (!rd_blocks)
+ if (!rd_blocks) {
+ spin_unlock_irqrestore(&s->lock, flags);
return;
+ }
for (i = 0; i < rd_blocks; i++) {
if (block_to_user_buf(s, buf_ptr)) {
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c
index c5719f7bd1ac..f28398dd9d93 100644
--- a/drivers/media/video/saa7115.c
+++ b/drivers/media/video/saa7115.c
@@ -1464,8 +1464,6 @@ static int saa711x_attach(struct i2c_adapter *adapter, int address, int kind)
client->driver = &i2c_driver_saa711x;
snprintf(client->name, sizeof(client->name) - 1, "saa7115");
- v4l_dbg(1, debug, client, "detecting saa7115 client on address 0x%x\n", address << 1);
-
for (i=0;i<0x0f;i++) {
saa711x_write(client, 0, i);
name[i] = (saa711x_read(client, 0) &0x0f) +'0';
@@ -1477,6 +1475,13 @@ static int saa711x_attach(struct i2c_adapter *adapter, int address, int kind)
saa711x_write(client, 0, 5);
chip_id = saa711x_read(client, 0) & 0x0f;
+ /* Check whether this chip is part of the saa711x series */
+ if (memcmp(name, "1f711", 5)) {
+ v4l_dbg(1, debug, client, "chip found @ 0x%x (ID %s) does not match a known saa711x chip.\n",
+ address << 1, name);
+ return 0;
+ }
+
snprintf(client->name, sizeof(client->name) - 1, "saa711%d",chip_id);
v4l_info(client, "saa711%d found (%s) @ 0x%x (%s)\n", chip_id, name, address << 1, adapter->name);
diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c
index a4702d3c2aca..18458d46c0ff 100644
--- a/drivers/media/video/sn9c102/sn9c102_core.c
+++ b/drivers/media/video/sn9c102/sn9c102_core.c
@@ -775,7 +775,7 @@ static int sn9c102_start_transfer(struct sn9c102_device* cam)
return 0;
free_urbs:
- for (i = 0; (i < SN9C102_URBS) && cam->urb[i]; i++)
+ for (i = 0; i < SN9C102_URBS; i++)
usb_free_urb(cam->urb[i]);
free_buffers:
@@ -1462,8 +1462,6 @@ static void sn9c102_release_resources(struct sn9c102_device* cam)
video_set_drvdata(cam->v4ldev, NULL);
video_unregister_device(cam->v4ldev);
- usb_put_dev(cam->usbdev);
-
mutex_unlock(&sn9c102_sysfs_lock);
kfree(cam->control_buffer);
@@ -1555,6 +1553,7 @@ static int sn9c102_release(struct inode* inode, struct file* filp)
if (cam->state & DEV_DISCONNECTED) {
sn9c102_release_resources(cam);
+ usb_put_dev(cam->usbdev);
mutex_unlock(&cam->dev_mutex);
kfree(cam);
return 0;
diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c
index 9a26b9484aae..bbf2beeeb449 100644
--- a/drivers/media/video/usbvideo/quickcam_messenger.c
+++ b/drivers/media/video/usbvideo/quickcam_messenger.c
@@ -190,8 +190,7 @@ static int qcm_alloc_int_urb(struct qcm *cam)
static void qcm_free_int(struct qcm *cam)
{
- if (cam->button_urb)
- usb_free_urb(cam->button_urb);
+ usb_free_urb(cam->button_urb);
}
#endif /* CONFIG_INPUT */
diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c
index 5b5563424422..52d0f759ee00 100644
--- a/drivers/media/video/zc0301/zc0301_core.c
+++ b/drivers/media/video/zc0301/zc0301_core.c
@@ -489,7 +489,7 @@ static int zc0301_start_transfer(struct zc0301_device* cam)
return 0;
free_urbs:
- for (i = 0; (i < ZC0301_URBS) && cam->urb[i]; i++)
+ for (i = 0; i < ZC0301_URBS; i++)
usb_free_urb(cam->urb[i]);
free_buffers:
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index e5c72719debc..051b7c5b8f03 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -6185,7 +6185,7 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
"Abort", /* 12h */
"IO Not Yet Executed", /* 13h */
"IO Executed", /* 14h */
- "Persistant Reservation Out Not Affiliation Owner", /* 15h */
+ "Persistent Reservation Out Not Affiliation Owner", /* 15h */
"Open Transmit DMA Abort", /* 16h */
"IO Device Missing Delay Retry", /* 17h */
NULL, /* 18h */
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c
index 62f1ac08332c..8287f95c8c42 100644
--- a/drivers/message/i2o/pci.c
+++ b/drivers/message/i2o/pci.c
@@ -320,7 +320,6 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
struct i2o_controller *c;
int rc;
struct pci_dev *i960 = NULL;
- int enabled = pdev->is_enabled;
printk(KERN_INFO "i2o: Checking for PCI I2O controllers...\n");
@@ -330,12 +329,11 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
return -ENODEV;
}
- if (!enabled)
- if ((rc = pci_enable_device(pdev))) {
- printk(KERN_WARNING "i2o: couldn't enable device %s\n",
- pci_name(pdev));
- return rc;
- }
+ if ((rc = pci_enable_device(pdev))) {
+ printk(KERN_WARNING "i2o: couldn't enable device %s\n",
+ pci_name(pdev));
+ return rc;
+ }
if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
printk(KERN_WARNING "i2o: no suitable DMA found for %s\n",
@@ -442,8 +440,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
i2o_iop_free(c);
disable:
- if (!enabled)
- pci_disable_device(pdev);
+ pci_disable_device(pdev);
return rc;
}
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index ea41852ec8cd..f4f8ccaf5455 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -40,7 +40,7 @@ config MMC_ARMMMCI
If unsure, say N.
config MMC_PXA
- tristate "Intel PXA255 Multimedia Card Interface support"
+ tristate "Intel PXA25x/26x/27x Multimedia Card Interface support"
depends on ARCH_PXA && MMC
help
This selects the Intel(R) PXA(R) Multimedia card Interface.
diff --git a/drivers/mmc/at91_mci.c b/drivers/mmc/at91_mci.c
index 494b23fb0a01..6495cd8a9306 100644
--- a/drivers/mmc/at91_mci.c
+++ b/drivers/mmc/at91_mci.c
@@ -793,7 +793,7 @@ int at91_mci_get_ro(struct mmc_host *mmc)
return read_only;
}
-static struct mmc_host_ops at91_mci_ops = {
+static const struct mmc_host_ops at91_mci_ops = {
.request = at91_mci_request,
.set_ios = at91_mci_set_ios,
.get_ro = at91_mci_get_ro,
diff --git a/drivers/mmc/au1xmmc.c b/drivers/mmc/au1xmmc.c
index 53ffcbb14a97..447fba5825fd 100644
--- a/drivers/mmc/au1xmmc.c
+++ b/drivers/mmc/au1xmmc.c
@@ -875,7 +875,7 @@ static void au1xmmc_init_dma(struct au1xmmc_host *host)
host->rx_chan = rxchan;
}
-struct mmc_host_ops au1xmmc_ops = {
+struct const mmc_host_ops au1xmmc_ops = {
.request = au1xmmc_request,
.set_ios = au1xmmc_set_ios,
};
diff --git a/drivers/mmc/imxmmc.c b/drivers/mmc/imxmmc.c
index 659d4a822cc5..06e7fcd19221 100644
--- a/drivers/mmc/imxmmc.c
+++ b/drivers/mmc/imxmmc.c
@@ -877,7 +877,7 @@ static void imxmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
}
}
-static struct mmc_host_ops imxmci_ops = {
+static const struct mmc_host_ops imxmci_ops = {
.request = imxmci_request,
.set_ios = imxmci_set_ios,
};
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 21fd39e4a20f..6f2a282e2b97 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -4,6 +4,7 @@
* Copyright (C) 2003-2004 Russell King, All Rights Reserved.
* SD support Copyright (C) 2004 Ian Molton, All Rights Reserved.
* SD support Copyright (C) 2005 Pierre Ossman, All Rights Reserved.
+ * MMCv4 support Copyright (C) 2006 Philip Langdale, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -396,23 +397,23 @@ static int mmc_select_card(struct mmc_host *host, struct mmc_card *card)
return err;
/*
- * Default bus width is 1 bit.
- */
- host->ios.bus_width = MMC_BUS_WIDTH_1;
-
- /*
- * We can only change the bus width of the selected
- * card so therefore we have to put the handling
+ * We can only change the bus width of SD cards when
+ * they are selected so we have to put the handling
* here.
+ *
+ * The card is in 1 bit mode by default so
+ * we only need to change if it supports the
+ * wider version.
*/
- if (host->caps & MMC_CAP_4_BIT_DATA) {
+ if (mmc_card_sd(card) &&
+ (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {
+
/*
- * The card is in 1 bit mode by default so
- * we only need to change if it supports the
- * wider version.
- */
- if (mmc_card_sd(card) &&
- (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {
+ * Default bus width is 1 bit.
+ */
+ host->ios.bus_width = MMC_BUS_WIDTH_1;
+
+ if (host->caps & MMC_CAP_4_BIT_DATA) {
struct mmc_command cmd;
cmd.opcode = SD_APP_SET_BUS_WIDTH;
cmd.arg = SD_BUS_WIDTH_4;
@@ -453,11 +454,11 @@ static void mmc_deselect_cards(struct mmc_host *host)
static inline void mmc_delay(unsigned int ms)
{
- if (ms < HZ / 1000) {
- yield();
+ if (ms < 1000 / HZ) {
+ cond_resched();
mdelay(ms);
} else {
- msleep_interruptible (ms);
+ msleep(ms);
}
}
@@ -953,6 +954,137 @@ static void mmc_read_csds(struct mmc_host *host)
}
}
+static void mmc_process_ext_csds(struct mmc_host *host)
+{
+ int err;
+ struct mmc_card *card;
+
+ struct mmc_request mrq;
+ struct mmc_command cmd;
+ struct mmc_data data;
+
+ struct scatterlist sg;
+
+ /*
+ * As the ext_csd is so large and mostly unused, we don't store the
+ * raw block in mmc_card.
+ */
+ u8 *ext_csd;
+ ext_csd = kmalloc(512, GFP_KERNEL);
+ if (!ext_csd) {
+ printk("%s: could not allocate a buffer to receive the ext_csd."
+ "mmc v4 cards will be treated as v3.\n",
+ mmc_hostname(host));
+ return;
+ }
+
+ list_for_each_entry(card, &host->cards, node) {
+ if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT))
+ continue;
+ if (mmc_card_sd(card))
+ continue;
+ if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
+ continue;
+
+ err = mmc_select_card(host, card);
+ if (err != MMC_ERR_NONE) {
+ mmc_card_set_dead(card);
+ continue;
+ }
+
+ memset(&cmd, 0, sizeof(struct mmc_command));
+
+ cmd.opcode = MMC_SEND_EXT_CSD;
+ cmd.arg = 0;
+ cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+ memset(&data, 0, sizeof(struct mmc_data));
+
+ mmc_set_data_timeout(&data, card, 0);
+
+ data.blksz = 512;
+ data.blocks = 1;
+ data.flags = MMC_DATA_READ;
+ data.sg = &sg;
+ data.sg_len = 1;
+
+ memset(&mrq, 0, sizeof(struct mmc_request));
+
+ mrq.cmd = &cmd;
+ mrq.data = &data;
+
+ sg_init_one(&sg, ext_csd, 512);
+
+ mmc_wait_for_req(host, &mrq);
+
+ if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
+ mmc_card_set_dead(card);
+ continue;
+ }
+
+ switch (ext_csd[EXT_CSD_CARD_TYPE]) {
+ case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26:
+ card->ext_csd.hs_max_dtr = 52000000;
+ break;
+ case EXT_CSD_CARD_TYPE_26:
+ card->ext_csd.hs_max_dtr = 26000000;
+ break;
+ default:
+ /* MMC v4 spec says this cannot happen */
+ printk("%s: card is mmc v4 but doesn't support "
+ "any high-speed modes.\n",
+ mmc_hostname(card->host));
+ mmc_card_set_bad(card);
+ continue;
+ }
+
+ /* Activate highspeed support. */
+ cmd.opcode = MMC_SWITCH;
+ cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
+ (EXT_CSD_HS_TIMING << 16) |
+ (1 << 8) |
+ EXT_CSD_CMD_SET_NORMAL;
+ cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
+
+ err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+ if (err != MMC_ERR_NONE) {
+ printk("%s: failed to switch card to mmc v4 "
+ "high-speed mode.\n",
+ mmc_hostname(card->host));
+ continue;
+ }
+
+ mmc_card_set_highspeed(card);
+
+ /* Check for host support for wide-bus modes. */
+ if (!(host->caps & MMC_CAP_4_BIT_DATA)) {
+ continue;
+ }
+
+ /* Activate 4-bit support. */
+ cmd.opcode = MMC_SWITCH;
+ cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
+ (EXT_CSD_BUS_WIDTH << 16) |
+ (EXT_CSD_BUS_WIDTH_4 << 8) |
+ EXT_CSD_CMD_SET_NORMAL;
+ cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
+
+ err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+ if (err != MMC_ERR_NONE) {
+ printk("%s: failed to switch card to "
+ "mmc v4 4-bit bus mode.\n",
+ mmc_hostname(card->host));
+ continue;
+ }
+
+ host->ios.bus_width = MMC_BUS_WIDTH_4;
+ }
+
+ kfree(ext_csd);
+
+ mmc_deselect_cards(host);
+}
+
static void mmc_read_scrs(struct mmc_host *host)
{
int err;
@@ -1025,14 +1157,133 @@ static void mmc_read_scrs(struct mmc_host *host)
mmc_deselect_cards(host);
}
+static void mmc_read_switch_caps(struct mmc_host *host)
+{
+ int err;
+ struct mmc_card *card;
+ struct mmc_request mrq;
+ struct mmc_command cmd;
+ struct mmc_data data;
+ unsigned char *status;
+ struct scatterlist sg;
+
+ status = kmalloc(64, GFP_KERNEL);
+ if (!status) {
+ printk(KERN_WARNING "%s: Unable to allocate buffer for "
+ "reading switch capabilities.\n",
+ mmc_hostname(host));
+ return;
+ }
+
+ list_for_each_entry(card, &host->cards, node) {
+ if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT))
+ continue;
+ if (!mmc_card_sd(card))
+ continue;
+ if (card->scr.sda_vsn < SCR_SPEC_VER_1)
+ continue;
+
+ err = mmc_select_card(host, card);
+ if (err != MMC_ERR_NONE) {
+ mmc_card_set_dead(card);
+ continue;
+ }
+
+ memset(&cmd, 0, sizeof(struct mmc_command));
+
+ cmd.opcode = SD_SWITCH;
+ cmd.arg = 0x00FFFFF1;
+ cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+ memset(&data, 0, sizeof(struct mmc_data));
+
+ mmc_set_data_timeout(&data, card, 0);
+
+ data.blksz = 64;
+ data.blocks = 1;
+ data.flags = MMC_DATA_READ;
+ data.sg = &sg;
+ data.sg_len = 1;
+
+ memset(&mrq, 0, sizeof(struct mmc_request));
+
+ mrq.cmd = &cmd;
+ mrq.data = &data;
+
+ sg_init_one(&sg, status, 64);
+
+ mmc_wait_for_req(host, &mrq);
+
+ if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
+ mmc_card_set_dead(card);
+ continue;
+ }
+
+ if (status[13] & 0x02)
+ card->sw_caps.hs_max_dtr = 50000000;
+
+ memset(&cmd, 0, sizeof(struct mmc_command));
+
+ cmd.opcode = SD_SWITCH;
+ cmd.arg = 0x80FFFFF1;
+ cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+ memset(&data, 0, sizeof(struct mmc_data));
+
+ mmc_set_data_timeout(&data, card, 0);
+
+ data.blksz = 64;
+ data.blocks = 1;
+ data.flags = MMC_DATA_READ;
+ data.sg = &sg;
+ data.sg_len = 1;
+
+ memset(&mrq, 0, sizeof(struct mmc_request));
+
+ mrq.cmd = &cmd;
+ mrq.data = &data;
+
+ sg_init_one(&sg, status, 64);
+
+ mmc_wait_for_req(host, &mrq);
+
+ if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
+ mmc_card_set_dead(card);
+ continue;
+ }
+
+ if ((status[16] & 0xF) != 1) {
+ printk(KERN_WARNING "%s: Problem switching card "
+ "into high-speed mode!\n",
+ mmc_hostname(host));
+ continue;
+ }
+
+ mmc_card_set_highspeed(card);
+ }
+
+ kfree(status);
+
+ mmc_deselect_cards(host);
+}
+
static unsigned int mmc_calculate_clock(struct mmc_host *host)
{
struct mmc_card *card;
unsigned int max_dtr = host->f_max;
list_for_each_entry(card, &host->cards, node)
- if (!mmc_card_dead(card) && max_dtr > card->csd.max_dtr)
- max_dtr = card->csd.max_dtr;
+ if (!mmc_card_dead(card)) {
+ if (mmc_card_highspeed(card) && mmc_card_sd(card)) {
+ if (max_dtr > card->sw_caps.hs_max_dtr)
+ max_dtr = card->sw_caps.hs_max_dtr;
+ } else if (mmc_card_highspeed(card) && !mmc_card_sd(card)) {
+ if (max_dtr > card->ext_csd.hs_max_dtr)
+ max_dtr = card->ext_csd.hs_max_dtr;
+ } else if (max_dtr > card->csd.max_dtr) {
+ max_dtr = card->csd.max_dtr;
+ }
+ }
pr_debug("%s: selected %d.%03dMHz transfer rate\n",
mmc_hostname(host),
@@ -1150,8 +1401,11 @@ static void mmc_setup(struct mmc_host *host)
mmc_read_csds(host);
- if (host->mode == MMC_MODE_SD)
+ if (host->mode == MMC_MODE_SD) {
mmc_read_scrs(host);
+ mmc_read_switch_caps(host);
+ } else
+ mmc_process_ext_csds(host);
}
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
index f9027c8db792..87713572293f 100644
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/mmc_block.c
@@ -83,7 +83,6 @@ static void mmc_blk_put(struct mmc_blk_data *md)
md->usage--;
if (md->usage == 0) {
put_disk(md->disk);
- mmc_cleanup_queue(&md->queue);
kfree(md);
}
mutex_unlock(&open_lock);
@@ -225,10 +224,10 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
struct mmc_blk_data *md = mq->data;
struct mmc_card *card = md->queue.card;
struct mmc_blk_request brq;
- int ret;
+ int ret = 1;
if (mmc_card_claim_host(card))
- goto cmd_err;
+ goto flush_queue;
do {
struct mmc_command cmd;
@@ -345,8 +344,6 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
return 1;
cmd_err:
- ret = 1;
-
/*
* If this is an SD card and we're writing, we can first
* mark the known good sectors as ok.
@@ -380,6 +377,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
mmc_card_release_host(card);
+flush_queue:
spin_lock_irq(&md->lock);
while (ret) {
ret = end_that_request_chunk(req, 0,
@@ -553,12 +551,11 @@ static void mmc_blk_remove(struct mmc_card *card)
if (md) {
int devidx;
+ /* Stop new requests from getting into the queue */
del_gendisk(md->disk);
- /*
- * I think this is needed.
- */
- md->disk->queue = NULL;
+ /* Then flush out any already in there */
+ mmc_cleanup_queue(&md->queue);
devidx = md->disk->first_minor >> MMC_SHIFT;
__clear_bit(devidx, dev_use);
diff --git a/drivers/mmc/mmc_queue.c b/drivers/mmc/mmc_queue.c
index 4ccdd82b680f..a17423a4ed8f 100644
--- a/drivers/mmc/mmc_queue.c
+++ b/drivers/mmc/mmc_queue.c
@@ -10,13 +10,13 @@
*/
#include <linux/module.h>
#include <linux/blkdev.h>
+#include <linux/kthread.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
#include "mmc_queue.h"
-#define MMC_QUEUE_EXIT (1 << 0)
-#define MMC_QUEUE_SUSPENDED (1 << 1)
+#define MMC_QUEUE_SUSPENDED (1 << 0)
/*
* Prepare a MMC request. Essentially, this means passing the
@@ -59,7 +59,6 @@ static int mmc_queue_thread(void *d)
{
struct mmc_queue *mq = d;
struct request_queue *q = mq->queue;
- DECLARE_WAITQUEUE(wait, current);
/*
* Set iothread to ensure that we aren't put to sleep by
@@ -67,12 +66,7 @@ static int mmc_queue_thread(void *d)
*/
current->flags |= PF_MEMALLOC|PF_NOFREEZE;
- daemonize("mmcqd");
-
- complete(&mq->thread_complete);
-
down(&mq->thread_sem);
- add_wait_queue(&mq->thread_wq, &wait);
do {
struct request *req = NULL;
@@ -84,7 +78,7 @@ static int mmc_queue_thread(void *d)
spin_unlock_irq(q->queue_lock);
if (!req) {
- if (mq->flags & MMC_QUEUE_EXIT)
+ if (kthread_should_stop())
break;
up(&mq->thread_sem);
schedule();
@@ -95,10 +89,8 @@ static int mmc_queue_thread(void *d)
mq->issue_fn(mq, req);
} while (1);
- remove_wait_queue(&mq->thread_wq, &wait);
up(&mq->thread_sem);
- complete_and_exit(&mq->thread_complete, 0);
return 0;
}
@@ -111,9 +103,22 @@ static int mmc_queue_thread(void *d)
static void mmc_request(request_queue_t *q)
{
struct mmc_queue *mq = q->queuedata;
+ struct request *req;
+ int ret;
+
+ if (!mq) {
+ printk(KERN_ERR "MMC: killing requests for dead queue\n");
+ while ((req = elv_next_request(q)) != NULL) {
+ do {
+ ret = end_that_request_chunk(req, 0,
+ req->current_nr_sectors << 9);
+ } while (ret);
+ }
+ return;
+ }
if (!mq->req)
- wake_up(&mq->thread_wq);
+ wake_up_process(mq->thread);
}
/**
@@ -130,8 +135,8 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
u64 limit = BLK_BOUNCE_HIGH;
int ret;
- if (host->dev->dma_mask && *host->dev->dma_mask)
- limit = *host->dev->dma_mask;
+ if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask)
+ limit = *mmc_dev(host)->dma_mask;
mq->card = card;
mq->queue = blk_init_queue(mmc_request, lock);
@@ -152,36 +157,40 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
GFP_KERNEL);
if (!mq->sg) {
ret = -ENOMEM;
- goto cleanup;
+ goto cleanup_queue;
}
- init_completion(&mq->thread_complete);
- init_waitqueue_head(&mq->thread_wq);
init_MUTEX(&mq->thread_sem);
- ret = kernel_thread(mmc_queue_thread, mq, CLONE_KERNEL);
- if (ret >= 0) {
- wait_for_completion(&mq->thread_complete);
- init_completion(&mq->thread_complete);
- ret = 0;
- goto out;
+ mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd");
+ if (IS_ERR(mq->thread)) {
+ ret = PTR_ERR(mq->thread);
+ goto free_sg;
}
- cleanup:
+ return 0;
+
+ free_sg:
kfree(mq->sg);
mq->sg = NULL;
-
+ cleanup_queue:
blk_cleanup_queue(mq->queue);
- out:
return ret;
}
EXPORT_SYMBOL(mmc_init_queue);
void mmc_cleanup_queue(struct mmc_queue *mq)
{
- mq->flags |= MMC_QUEUE_EXIT;
- wake_up(&mq->thread_wq);
- wait_for_completion(&mq->thread_complete);
+ request_queue_t *q = mq->queue;
+ unsigned long flags;
+
+ /* Mark that we should start throwing out stragglers */
+ spin_lock_irqsave(q->queue_lock, flags);
+ q->queuedata = NULL;
+ spin_unlock_irqrestore(q->queue_lock, flags);
+
+ /* Then terminate our worker thread */
+ kthread_stop(mq->thread);
kfree(mq->sg);
mq->sg = NULL;
diff --git a/drivers/mmc/mmc_queue.h b/drivers/mmc/mmc_queue.h
index 7182d2f69b4e..c9f139e764f6 100644
--- a/drivers/mmc/mmc_queue.h
+++ b/drivers/mmc/mmc_queue.h
@@ -6,8 +6,7 @@ struct task_struct;
struct mmc_queue {
struct mmc_card *card;
- struct completion thread_complete;
- wait_queue_head_t thread_wq;
+ struct task_struct *thread;
struct semaphore thread_sem;
unsigned int flags;
struct request *req;
diff --git a/drivers/mmc/mmc_sysfs.c b/drivers/mmc/mmc_sysfs.c
index fd9a5fc6db7b..e334acd045bc 100644
--- a/drivers/mmc/mmc_sysfs.c
+++ b/drivers/mmc/mmc_sysfs.c
@@ -199,7 +199,7 @@ void mmc_init_card(struct mmc_card *card, struct mmc_host *host)
memset(card, 0, sizeof(struct mmc_card));
card->host = host;
device_initialize(&card->dev);
- card->dev.parent = card->host->dev;
+ card->dev.parent = mmc_dev(host);
card->dev.bus = &mmc_bus_type;
card->dev.release = mmc_release_card;
}
@@ -242,7 +242,7 @@ void mmc_remove_card(struct mmc_card *card)
}
-static void mmc_host_classdev_release(struct class_device *dev)
+static void mmc_host_classdev_release(struct device *dev)
{
struct mmc_host *host = cls_dev_to_mmc_host(dev);
kfree(host);
@@ -250,7 +250,7 @@ static void mmc_host_classdev_release(struct class_device *dev)
static struct class mmc_host_class = {
.name = "mmc_host",
- .release = mmc_host_classdev_release,
+ .dev_release = mmc_host_classdev_release,
};
static DEFINE_IDR(mmc_host_idr);
@@ -267,10 +267,10 @@ struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev)
if (host) {
memset(host, 0, sizeof(struct mmc_host) + extra);
- host->dev = dev;
- host->class_dev.dev = host->dev;
+ host->parent = dev;
+ host->class_dev.parent = dev;
host->class_dev.class = &mmc_host_class;
- class_device_initialize(&host->class_dev);
+ device_initialize(&host->class_dev);
}
return host;
@@ -292,10 +292,10 @@ int mmc_add_host_sysfs(struct mmc_host *host)
if (err)
return err;
- snprintf(host->class_dev.class_id, BUS_ID_SIZE,
+ snprintf(host->class_dev.bus_id, BUS_ID_SIZE,
"mmc%d", host->index);
- return class_device_add(&host->class_dev);
+ return device_add(&host->class_dev);
}
/*
@@ -303,7 +303,7 @@ int mmc_add_host_sysfs(struct mmc_host *host)
*/
void mmc_remove_host_sysfs(struct mmc_host *host)
{
- class_device_del(&host->class_dev);
+ device_del(&host->class_dev);
spin_lock(&mmc_host_lock);
idr_remove(&mmc_host_idr, host->index);
@@ -315,7 +315,7 @@ void mmc_remove_host_sysfs(struct mmc_host *host)
*/
void mmc_free_host_sysfs(struct mmc_host *host)
{
- class_device_put(&host->class_dev);
+ put_device(&host->class_dev);
}
static struct workqueue_struct *workqueue;
diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c
index 828503c4ee62..e9b80e920266 100644
--- a/drivers/mmc/mmci.c
+++ b/drivers/mmc/mmci.c
@@ -443,7 +443,7 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
}
}
-static struct mmc_host_ops mmci_ops = {
+static const struct mmc_host_ops mmci_ops = {
.request = mmci_request,
.set_ios = mmci_set_ios,
};
diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c
index 762fa2895891..435d331e772a 100644
--- a/drivers/mmc/omap.c
+++ b/drivers/mmc/omap.c
@@ -38,7 +38,57 @@
#include <asm/arch/fpga.h>
#include <asm/arch/tps65010.h>
-#include "omap.h"
+#define OMAP_MMC_REG_CMD 0x00
+#define OMAP_MMC_REG_ARGL 0x04
+#define OMAP_MMC_REG_ARGH 0x08
+#define OMAP_MMC_REG_CON 0x0c
+#define OMAP_MMC_REG_STAT 0x10
+#define OMAP_MMC_REG_IE 0x14
+#define OMAP_MMC_REG_CTO 0x18
+#define OMAP_MMC_REG_DTO 0x1c
+#define OMAP_MMC_REG_DATA 0x20
+#define OMAP_MMC_REG_BLEN 0x24
+#define OMAP_MMC_REG_NBLK 0x28
+#define OMAP_MMC_REG_BUF 0x2c
+#define OMAP_MMC_REG_SDIO 0x34
+#define OMAP_MMC_REG_REV 0x3c
+#define OMAP_MMC_REG_RSP0 0x40
+#define OMAP_MMC_REG_RSP1 0x44
+#define OMAP_MMC_REG_RSP2 0x48
+#define OMAP_MMC_REG_RSP3 0x4c
+#define OMAP_MMC_REG_RSP4 0x50
+#define OMAP_MMC_REG_RSP5 0x54
+#define OMAP_MMC_REG_RSP6 0x58
+#define OMAP_MMC_REG_RSP7 0x5c
+#define OMAP_MMC_REG_IOSR 0x60
+#define OMAP_MMC_REG_SYSC 0x64
+#define OMAP_MMC_REG_SYSS 0x68
+
+#define OMAP_MMC_STAT_CARD_ERR (1 << 14)
+#define OMAP_MMC_STAT_CARD_IRQ (1 << 13)
+#define OMAP_MMC_STAT_OCR_BUSY (1 << 12)
+#define OMAP_MMC_STAT_A_EMPTY (1 << 11)
+#define OMAP_MMC_STAT_A_FULL (1 << 10)
+#define OMAP_MMC_STAT_CMD_CRC (1 << 8)
+#define OMAP_MMC_STAT_CMD_TOUT (1 << 7)
+#define OMAP_MMC_STAT_DATA_CRC (1 << 6)
+#define OMAP_MMC_STAT_DATA_TOUT (1 << 5)
+#define OMAP_MMC_STAT_END_BUSY (1 << 4)
+#define OMAP_MMC_STAT_END_OF_DATA (1 << 3)
+#define OMAP_MMC_STAT_CARD_BUSY (1 << 2)
+#define OMAP_MMC_STAT_END_OF_CMD (1 << 0)
+
+#define OMAP_MMC_READ(host, reg) __raw_readw((host)->virt_base + OMAP_MMC_REG_##reg)
+#define OMAP_MMC_WRITE(host, reg, val) __raw_writew((val), (host)->virt_base + OMAP_MMC_REG_##reg)
+
+/*
+ * Command types
+ */
+#define OMAP_MMC_CMDTYPE_BC 0
+#define OMAP_MMC_CMDTYPE_BCR 1
+#define OMAP_MMC_CMDTYPE_AC 2
+#define OMAP_MMC_CMDTYPE_ADTC 3
+
#define DRIVER_NAME "mmci-omap"
#define RSP_TYPE(x) ((x) & ~(MMC_RSP_BUSY|MMC_RSP_OPCODE))
@@ -60,8 +110,9 @@ struct mmc_omap_host {
unsigned char id; /* 16xx chips have 2 MMC blocks */
struct clk * iclk;
struct clk * fclk;
- struct resource *res;
- void __iomem *base;
+ struct resource *mem_res;
+ void __iomem *virt_base;
+ unsigned int phys_base;
int irq;
unsigned char bus_mode;
unsigned char hw_bus_mode;
@@ -191,16 +242,16 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd)
clk_enable(host->fclk);
- OMAP_MMC_WRITE(host->base, CTO, 200);
- OMAP_MMC_WRITE(host->base, ARGL, cmd->arg & 0xffff);
- OMAP_MMC_WRITE(host->base, ARGH, cmd->arg >> 16);
- OMAP_MMC_WRITE(host->base, IE,
+ OMAP_MMC_WRITE(host, CTO, 200);
+ OMAP_MMC_WRITE(host, ARGL, cmd->arg & 0xffff);
+ OMAP_MMC_WRITE(host, ARGH, cmd->arg >> 16);
+ OMAP_MMC_WRITE(host, IE,
OMAP_MMC_STAT_A_EMPTY | OMAP_MMC_STAT_A_FULL |
OMAP_MMC_STAT_CMD_CRC | OMAP_MMC_STAT_CMD_TOUT |
OMAP_MMC_STAT_DATA_CRC | OMAP_MMC_STAT_DATA_TOUT |
OMAP_MMC_STAT_END_OF_CMD | OMAP_MMC_STAT_CARD_ERR |
OMAP_MMC_STAT_END_OF_DATA);
- OMAP_MMC_WRITE(host->base, CMD, cmdreg);
+ OMAP_MMC_WRITE(host, CMD, cmdreg);
}
static void
@@ -296,22 +347,22 @@ mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd)
if (cmd->flags & MMC_RSP_136) {
/* response type 2 */
cmd->resp[3] =
- OMAP_MMC_READ(host->base, RSP0) |
- (OMAP_MMC_READ(host->base, RSP1) << 16);
+ OMAP_MMC_READ(host, RSP0) |
+ (OMAP_MMC_READ(host, RSP1) << 16);
cmd->resp[2] =
- OMAP_MMC_READ(host->base, RSP2) |
- (OMAP_MMC_READ(host->base, RSP3) << 16);
+ OMAP_MMC_READ(host, RSP2) |
+ (OMAP_MMC_READ(host, RSP3) << 16);
cmd->resp[1] =
- OMAP_MMC_READ(host->base, RSP4) |
- (OMAP_MMC_READ(host->base, RSP5) << 16);
+ OMAP_MMC_READ(host, RSP4) |
+ (OMAP_MMC_READ(host, RSP5) << 16);
cmd->resp[0] =
- OMAP_MMC_READ(host->base, RSP6) |
- (OMAP_MMC_READ(host->base, RSP7) << 16);
+ OMAP_MMC_READ(host, RSP6) |
+ (OMAP_MMC_READ(host, RSP7) << 16);
} else {
/* response types 1, 1b, 3, 4, 5, 6 */
cmd->resp[0] =
- OMAP_MMC_READ(host->base, RSP6) |
- (OMAP_MMC_READ(host->base, RSP7) << 16);
+ OMAP_MMC_READ(host, RSP6) |
+ (OMAP_MMC_READ(host, RSP7) << 16);
}
}
@@ -354,9 +405,9 @@ mmc_omap_xfer_data(struct mmc_omap_host *host, int write)
host->data->bytes_xfered += n;
if (write) {
- __raw_writesw(host->base + OMAP_MMC_REG_DATA, host->buffer, n);
+ __raw_writesw(host->virt_base + OMAP_MMC_REG_DATA, host->buffer, n);
} else {
- __raw_readsw(host->base + OMAP_MMC_REG_DATA, host->buffer, n);
+ __raw_readsw(host->virt_base + OMAP_MMC_REG_DATA, host->buffer, n);
}
}
@@ -386,11 +437,11 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
int transfer_error;
if (host->cmd == NULL && host->data == NULL) {
- status = OMAP_MMC_READ(host->base, STAT);
+ status = OMAP_MMC_READ(host, STAT);
dev_info(mmc_dev(host->mmc),"spurious irq 0x%04x\n", status);
if (status != 0) {
- OMAP_MMC_WRITE(host->base, STAT, status);
- OMAP_MMC_WRITE(host->base, IE, 0);
+ OMAP_MMC_WRITE(host, STAT, status);
+ OMAP_MMC_WRITE(host, IE, 0);
}
return IRQ_HANDLED;
}
@@ -399,8 +450,8 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
end_transfer = 0;
transfer_error = 0;
- while ((status = OMAP_MMC_READ(host->base, STAT)) != 0) {
- OMAP_MMC_WRITE(host->base, STAT, status);
+ while ((status = OMAP_MMC_READ(host, STAT)) != 0) {
+ OMAP_MMC_WRITE(host, STAT, status);
#ifdef CONFIG_MMC_DEBUG
dev_dbg(mmc_dev(host->mmc), "MMC IRQ %04x (CMD %d): ",
status, host->cmd != NULL ? host->cmd->opcode : -1);
@@ -470,8 +521,8 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
if (status & OMAP_MMC_STAT_CARD_ERR) {
if (host->cmd && host->cmd->opcode == MMC_STOP_TRANSMISSION) {
- u32 response = OMAP_MMC_READ(host->base, RSP6)
- | (OMAP_MMC_READ(host->base, RSP7) << 16);
+ u32 response = OMAP_MMC_READ(host, RSP6)
+ | (OMAP_MMC_READ(host, RSP7) << 16);
/* STOP sometimes sets must-ignore bits */
if (!(response & (R1_CC_ERROR
| R1_ILLEGAL_COMMAND
@@ -530,12 +581,6 @@ static void mmc_omap_switch_timer(unsigned long arg)
schedule_work(&host->switch_work);
}
-/* FIXME: Handle card insertion and removal properly. Maybe use a mask
- * for MMC state? */
-static void mmc_omap_switch_callback(unsigned long data, u8 mmc_mask)
-{
-}
-
static void mmc_omap_switch_handler(void *data)
{
struct mmc_omap_host *host = (struct mmc_omap_host *) data;
@@ -581,7 +626,7 @@ mmc_omap_prepare_dma(struct mmc_omap_host *host, struct mmc_data *data)
int dst_port = 0;
int sync_dev = 0;
- data_addr = io_v2p((u32) host->base) + OMAP_MMC_REG_DATA;
+ data_addr = host->phys_base + OMAP_MMC_REG_DATA;
frame = data->blksz;
count = sg_dma_len(sg);
@@ -640,10 +685,9 @@ mmc_omap_prepare_dma(struct mmc_omap_host *host, struct mmc_data *data)
}
/* Max limit for DMA frame count is 0xffff */
- if (unlikely(count > 0xffff))
- BUG();
+ BUG_ON(count > 0xffff);
- OMAP_MMC_WRITE(host->base, BUF, buf);
+ OMAP_MMC_WRITE(host, BUF, buf);
omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S16,
frame, count, OMAP_DMA_SYNC_FRAME,
sync_dev, 0);
@@ -728,11 +772,11 @@ static inline void set_cmd_timeout(struct mmc_omap_host *host, struct mmc_reques
{
u16 reg;
- reg = OMAP_MMC_READ(host->base, SDIO);
+ reg = OMAP_MMC_READ(host, SDIO);
reg &= ~(1 << 5);
- OMAP_MMC_WRITE(host->base, SDIO, reg);
+ OMAP_MMC_WRITE(host, SDIO, reg);
/* Set maximum timeout */
- OMAP_MMC_WRITE(host->base, CTO, 0xff);
+ OMAP_MMC_WRITE(host, CTO, 0xff);
}
static inline void set_data_timeout(struct mmc_omap_host *host, struct mmc_request *req)
@@ -746,14 +790,14 @@ static inline void set_data_timeout(struct mmc_omap_host *host, struct mmc_reque
timeout = req->data->timeout_clks + req->data->timeout_ns / 500;
/* Check if we need to use timeout multiplier register */
- reg = OMAP_MMC_READ(host->base, SDIO);
+ reg = OMAP_MMC_READ(host, SDIO);
if (timeout > 0xffff) {
reg |= (1 << 5);
timeout /= 1024;
} else
reg &= ~(1 << 5);
- OMAP_MMC_WRITE(host->base, SDIO, reg);
- OMAP_MMC_WRITE(host->base, DTO, timeout);
+ OMAP_MMC_WRITE(host, SDIO, reg);
+ OMAP_MMC_WRITE(host, DTO, timeout);
}
static void
@@ -765,19 +809,18 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req)
host->data = data;
if (data == NULL) {
- OMAP_MMC_WRITE(host->base, BLEN, 0);
- OMAP_MMC_WRITE(host->base, NBLK, 0);
- OMAP_MMC_WRITE(host->base, BUF, 0);
+ OMAP_MMC_WRITE(host, BLEN, 0);
+ OMAP_MMC_WRITE(host, NBLK, 0);
+ OMAP_MMC_WRITE(host, BUF, 0);
host->dma_in_use = 0;
set_cmd_timeout(host, req);
return;
}
-
block_size = data->blksz;
- OMAP_MMC_WRITE(host->base, NBLK, data->blocks - 1);
- OMAP_MMC_WRITE(host->base, BLEN, block_size - 1);
+ OMAP_MMC_WRITE(host, NBLK, data->blocks - 1);
+ OMAP_MMC_WRITE(host, BLEN, block_size - 1);
set_data_timeout(host, req);
/* cope with calling layer confusion; it issues "single
@@ -819,7 +862,7 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req)
/* Revert to PIO? */
if (!use_dma) {
- OMAP_MMC_WRITE(host->base, BUF, 0x1f1f);
+ OMAP_MMC_WRITE(host, BUF, 0x1f1f);
host->total_bytes_left = data->blocks * block_size;
host->sg_len = sg_len;
mmc_omap_sg_to_buf(host);
@@ -845,7 +888,6 @@ static void mmc_omap_request(struct mmc_host *mmc, struct mmc_request *req)
static void innovator_fpga_socket_power(int on)
{
#if defined(CONFIG_MACH_OMAP_INNOVATOR) && defined(CONFIG_ARCH_OMAP15XX)
-
if (on) {
fpga_write(fpga_read(OMAP1510_FPGA_POWER) | (1 << 3),
OMAP1510_FPGA_POWER);
@@ -871,8 +913,8 @@ static void mmc_omap_power(struct mmc_omap_host *host, int on)
/* GPIO 4 of TPS65010 sends SD_EN signal */
tps65010_set_gpio_out_value(GPIO4, HIGH);
else if (cpu_is_omap24xx()) {
- u16 reg = OMAP_MMC_READ(host->base, CON);
- OMAP_MMC_WRITE(host->base, CON, reg | (1 << 11));
+ u16 reg = OMAP_MMC_READ(host, CON);
+ OMAP_MMC_WRITE(host, CON, reg | (1 << 11));
} else
if (host->power_pin >= 0)
omap_set_gpio_dataout(host->power_pin, 1);
@@ -884,8 +926,8 @@ static void mmc_omap_power(struct mmc_omap_host *host, int on)
else if (machine_is_omap_h3())
tps65010_set_gpio_out_value(GPIO4, LOW);
else if (cpu_is_omap24xx()) {
- u16 reg = OMAP_MMC_READ(host->base, CON);
- OMAP_MMC_WRITE(host->base, CON, reg & ~(1 << 11));
+ u16 reg = OMAP_MMC_READ(host, CON);
+ OMAP_MMC_WRITE(host, CON, reg & ~(1 << 11));
} else
if (host->power_pin >= 0)
omap_set_gpio_dataout(host->power_pin, 0);
@@ -927,7 +969,7 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
case MMC_POWER_UP:
case MMC_POWER_ON:
mmc_omap_power(host, 1);
- dsor |= 1<<11;
+ dsor |= 1 << 11;
break;
}
@@ -941,14 +983,14 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
* which results in the while loop below getting stuck.
* Writing to the CON register twice seems to do the trick. */
for (i = 0; i < 2; i++)
- OMAP_MMC_WRITE(host->base, CON, dsor);
+ OMAP_MMC_WRITE(host, CON, dsor);
if (ios->power_mode == MMC_POWER_UP) {
/* Send clock cycles, poll completion */
- OMAP_MMC_WRITE(host->base, IE, 0);
- OMAP_MMC_WRITE(host->base, STAT, 0xffff);
- OMAP_MMC_WRITE(host->base, CMD, 1<<7);
- while (0 == (OMAP_MMC_READ(host->base, STAT) & 1));
- OMAP_MMC_WRITE(host->base, STAT, 1);
+ OMAP_MMC_WRITE(host, IE, 0);
+ OMAP_MMC_WRITE(host, STAT, 0xffff);
+ OMAP_MMC_WRITE(host, CMD, 1 << 7);
+ while ((OMAP_MMC_READ(host, STAT) & 1) == 0);
+ OMAP_MMC_WRITE(host, STAT, 1);
}
clk_disable(host->fclk);
}
@@ -960,7 +1002,7 @@ static int mmc_omap_get_ro(struct mmc_host *mmc)
return host->wp_pin && omap_get_gpio_datain(host->wp_pin);
}
-static struct mmc_host_ops mmc_omap_ops = {
+static const struct mmc_host_ops mmc_omap_ops = {
.request = mmc_omap_request,
.set_ios = mmc_omap_set_ios,
.get_ro = mmc_omap_get_ro,
@@ -971,25 +1013,29 @@ static int __init mmc_omap_probe(struct platform_device *pdev)
struct omap_mmc_conf *minfo = pdev->dev.platform_data;
struct mmc_host *mmc;
struct mmc_omap_host *host = NULL;
- struct resource *r;
+ struct resource *res;
int ret = 0;
int irq;
-
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ if (minfo == NULL) {
+ dev_err(&pdev->dev, "platform data missing\n");
+ return -ENXIO;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
irq = platform_get_irq(pdev, 0);
- if (!r || irq < 0)
+ if (res == NULL || irq < 0)
return -ENXIO;
- r = request_mem_region(pdev->resource[0].start,
- pdev->resource[0].end - pdev->resource[0].start + 1,
- pdev->name);
- if (!r)
+ res = request_mem_region(res->start, res->end - res->start + 1,
+ pdev->name);
+ if (res == NULL)
return -EBUSY;
mmc = mmc_alloc_host(sizeof(struct mmc_omap_host), &pdev->dev);
- if (!mmc) {
+ if (mmc == NULL) {
ret = -ENOMEM;
- goto out;
+ goto err_free_mem_region;
}
host = mmc_priv(mmc);
@@ -1001,13 +1047,13 @@ static int __init mmc_omap_probe(struct platform_device *pdev)
host->dma_timer.data = (unsigned long) host;
host->id = pdev->id;
- host->res = r;
+ host->mem_res = res;
host->irq = irq;
if (cpu_is_omap24xx()) {
host->iclk = clk_get(&pdev->dev, "mmc_ick");
if (IS_ERR(host->iclk))
- goto out;
+ goto err_free_mmc_host;
clk_enable(host->iclk);
}
@@ -1018,7 +1064,7 @@ static int __init mmc_omap_probe(struct platform_device *pdev)
if (IS_ERR(host->fclk)) {
ret = PTR_ERR(host->fclk);
- goto out;
+ goto err_free_iclk;
}
/* REVISIT:
@@ -1031,14 +1077,15 @@ static int __init mmc_omap_probe(struct platform_device *pdev)
host->use_dma = 1;
host->dma_ch = -1;
- host->irq = pdev->resource[1].start;
- host->base = (void __iomem*)IO_ADDRESS(r->start);
+ host->irq = irq;
+ host->phys_base = host->mem_res->start;
+ host->virt_base = (void __iomem *) IO_ADDRESS(host->phys_base);
mmc->ops = &mmc_omap_ops;
mmc->f_min = 400000;
mmc->f_max = 24000000;
- mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34;
- mmc->caps = MMC_CAP_BYTEBLOCK;
+ mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+ mmc->caps = MMC_CAP_MULTIWRITE | MMC_CAP_BYTEBLOCK;
if (minfo->wire4)
mmc->caps |= MMC_CAP_4_BIT_DATA;
@@ -1056,20 +1103,18 @@ static int __init mmc_omap_probe(struct platform_device *pdev)
if ((ret = omap_request_gpio(host->power_pin)) != 0) {
dev_err(mmc_dev(host->mmc),
"Unable to get GPIO pin for MMC power\n");
- goto out;
+ goto err_free_fclk;
}
omap_set_gpio_direction(host->power_pin, 0);
}
ret = request_irq(host->irq, mmc_omap_irq, 0, DRIVER_NAME, host);
if (ret)
- goto out;
+ goto err_free_power_gpio;
host->dev = &pdev->dev;
platform_set_drvdata(pdev, host);
- mmc_add_host(mmc);
-
if (host->switch_pin >= 0) {
INIT_WORK(&host->switch_work, mmc_omap_switch_handler, host);
init_timer(&host->switch_timer);
@@ -1107,10 +1152,11 @@ static int __init mmc_omap_probe(struct platform_device *pdev)
schedule_work(&host->switch_work);
}
-no_switch:
+ mmc_add_host(mmc);
+
return 0;
-out:
+no_switch:
/* FIXME: Free other resources too. */
if (host) {
if (host->iclk && !IS_ERR(host->iclk))
@@ -1119,6 +1165,20 @@ out:
clk_put(host->fclk);
mmc_free_host(host->mmc);
}
+err_free_power_gpio:
+ if (host->power_pin >= 0)
+ omap_free_gpio(host->power_pin);
+err_free_fclk:
+ clk_put(host->fclk);
+err_free_iclk:
+ if (host->iclk != NULL) {
+ clk_disable(host->iclk);
+ clk_put(host->iclk);
+ }
+err_free_mmc_host:
+ mmc_free_host(host->mmc);
+err_free_mem_region:
+ release_mem_region(res->start, res->end - res->start + 1);
return ret;
}
@@ -1128,30 +1188,31 @@ static int mmc_omap_remove(struct platform_device *pdev)
platform_set_drvdata(pdev, NULL);
- if (host) {
- mmc_remove_host(host->mmc);
- free_irq(host->irq, host);
-
- if (host->power_pin >= 0)
- omap_free_gpio(host->power_pin);
- if (host->switch_pin >= 0) {
- device_remove_file(&pdev->dev, &dev_attr_enable_poll);
- device_remove_file(&pdev->dev, &dev_attr_cover_switch);
- free_irq(OMAP_GPIO_IRQ(host->switch_pin), host);
- omap_free_gpio(host->switch_pin);
- host->switch_pin = -1;
- del_timer_sync(&host->switch_timer);
- flush_scheduled_work();
- }
- if (host->iclk && !IS_ERR(host->iclk))
- clk_put(host->iclk);
- if (host->fclk && !IS_ERR(host->fclk))
- clk_put(host->fclk);
- mmc_free_host(host->mmc);
+ BUG_ON(host == NULL);
+
+ mmc_remove_host(host->mmc);
+ free_irq(host->irq, host);
+
+ if (host->power_pin >= 0)
+ omap_free_gpio(host->power_pin);
+ if (host->switch_pin >= 0) {
+ device_remove_file(&pdev->dev, &dev_attr_enable_poll);
+ device_remove_file(&pdev->dev, &dev_attr_cover_switch);
+ free_irq(OMAP_GPIO_IRQ(host->switch_pin), host);
+ omap_free_gpio(host->switch_pin);
+ host->switch_pin = -1;
+ del_timer_sync(&host->switch_timer);
+ flush_scheduled_work();
}
+ if (host->iclk && !IS_ERR(host->iclk))
+ clk_put(host->iclk);
+ if (host->fclk && !IS_ERR(host->fclk))
+ clk_put(host->fclk);
release_mem_region(pdev->resource[0].start,
- pdev->resource[0].end - pdev->resource[0].start + 1);
+ pdev->resource[0].end - pdev->resource[0].start + 1);
+
+ mmc_free_host(host->mmc);
return 0;
}
diff --git a/drivers/mmc/omap.h b/drivers/mmc/omap.h
deleted file mode 100644
index c954d355a5e3..000000000000
--- a/drivers/mmc/omap.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#ifndef DRIVERS_MEDIA_MMC_OMAP_H
-#define DRIVERS_MEDIA_MMC_OMAP_H
-
-#define OMAP_MMC_REG_CMD 0x00
-#define OMAP_MMC_REG_ARGL 0x04
-#define OMAP_MMC_REG_ARGH 0x08
-#define OMAP_MMC_REG_CON 0x0c
-#define OMAP_MMC_REG_STAT 0x10
-#define OMAP_MMC_REG_IE 0x14
-#define OMAP_MMC_REG_CTO 0x18
-#define OMAP_MMC_REG_DTO 0x1c
-#define OMAP_MMC_REG_DATA 0x20
-#define OMAP_MMC_REG_BLEN 0x24
-#define OMAP_MMC_REG_NBLK 0x28
-#define OMAP_MMC_REG_BUF 0x2c
-#define OMAP_MMC_REG_SDIO 0x34
-#define OMAP_MMC_REG_REV 0x3c
-#define OMAP_MMC_REG_RSP0 0x40
-#define OMAP_MMC_REG_RSP1 0x44
-#define OMAP_MMC_REG_RSP2 0x48
-#define OMAP_MMC_REG_RSP3 0x4c
-#define OMAP_MMC_REG_RSP4 0x50
-#define OMAP_MMC_REG_RSP5 0x54
-#define OMAP_MMC_REG_RSP6 0x58
-#define OMAP_MMC_REG_RSP7 0x5c
-#define OMAP_MMC_REG_IOSR 0x60
-#define OMAP_MMC_REG_SYSC 0x64
-#define OMAP_MMC_REG_SYSS 0x68
-
-#define OMAP_MMC_STAT_CARD_ERR (1 << 14)
-#define OMAP_MMC_STAT_CARD_IRQ (1 << 13)
-#define OMAP_MMC_STAT_OCR_BUSY (1 << 12)
-#define OMAP_MMC_STAT_A_EMPTY (1 << 11)
-#define OMAP_MMC_STAT_A_FULL (1 << 10)
-#define OMAP_MMC_STAT_CMD_CRC (1 << 8)
-#define OMAP_MMC_STAT_CMD_TOUT (1 << 7)
-#define OMAP_MMC_STAT_DATA_CRC (1 << 6)
-#define OMAP_MMC_STAT_DATA_TOUT (1 << 5)
-#define OMAP_MMC_STAT_END_BUSY (1 << 4)
-#define OMAP_MMC_STAT_END_OF_DATA (1 << 3)
-#define OMAP_MMC_STAT_CARD_BUSY (1 << 2)
-#define OMAP_MMC_STAT_END_OF_CMD (1 << 0)
-
-#define OMAP_MMC_READ(base, reg) __raw_readw((base) + OMAP_MMC_REG_##reg)
-#define OMAP_MMC_WRITE(base, reg, val) __raw_writew((val), (base) + OMAP_MMC_REG_##reg)
-
-/*
- * Command types
- */
-#define OMAP_MMC_CMDTYPE_BC 0
-#define OMAP_MMC_CMDTYPE_BCR 1
-#define OMAP_MMC_CMDTYPE_AC 2
-#define OMAP_MMC_CMDTYPE_ADTC 3
-
-#endif
diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c
index a526698b8c91..471e9f4e0530 100644
--- a/drivers/mmc/pxamci.c
+++ b/drivers/mmc/pxamci.c
@@ -393,7 +393,7 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
host->clkrt, host->cmdat);
}
-static struct mmc_host_ops pxamci_ops = {
+static const struct mmc_host_ops pxamci_ops = {
.request = pxamci_request,
.get_ro = pxamci_get_ro,
.set_ios = pxamci_set_ios,
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 9a7d39b7cdbf..cd98117632d3 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -616,6 +616,7 @@ static void sdhci_finish_command(struct sdhci_host *host)
static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
{
int div;
+ u8 ctrl;
u16 clk;
unsigned long timeout;
@@ -624,6 +625,13 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL);
+ ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
+ if (clock > 25000000)
+ ctrl |= SDHCI_CTRL_HISPD;
+ else
+ ctrl &= ~SDHCI_CTRL_HISPD;
+ writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
+
if (clock == 0)
goto out;
@@ -784,7 +792,7 @@ static int sdhci_get_ro(struct mmc_host *mmc)
return !(present & SDHCI_WRITE_PROTECT);
}
-static struct mmc_host_ops sdhci_ops = {
+static const struct mmc_host_ops sdhci_ops = {
.request = sdhci_request,
.set_ios = sdhci_set_ios,
.get_ro = sdhci_get_ro,
@@ -1291,6 +1299,13 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
else if (caps & SDHCI_CAN_VDD_180)
mmc->ocr_avail |= MMC_VDD_17_18|MMC_VDD_18_19;
+ if ((host->max_clk > 25000000) && !(caps & SDHCI_CAN_DO_HISPD)) {
+ printk(KERN_ERR "%s: Controller reports > 25 MHz base clock,"
+ " but no high speed support.\n",
+ host->slot_descr);
+ mmc->f_max = 25000000;
+ }
+
if (mmc->ocr_avail == 0) {
printk(KERN_ERR "%s: Hardware doesn't report any "
"support voltages.\n", host->slot_descr);
diff --git a/drivers/mmc/sdhci.h b/drivers/mmc/sdhci.h
index 72a67937afe0..f9d1a0a6f03a 100644
--- a/drivers/mmc/sdhci.h
+++ b/drivers/mmc/sdhci.h
@@ -71,6 +71,7 @@
#define SDHCI_HOST_CONTROL 0x28
#define SDHCI_CTRL_LED 0x01
#define SDHCI_CTRL_4BITBUS 0x02
+#define SDHCI_CTRL_HISPD 0x04
#define SDHCI_POWER_CONTROL 0x29
#define SDHCI_POWER_ON 0x01
@@ -138,6 +139,7 @@
#define SDHCI_CLOCK_BASE_SHIFT 8
#define SDHCI_MAX_BLOCK_MASK 0x00030000
#define SDHCI_MAX_BLOCK_SHIFT 16
+#define SDHCI_CAN_DO_HISPD 0x00200000
#define SDHCI_CAN_DO_DMA 0x00400000
#define SDHCI_CAN_VDD_330 0x01000000
#define SDHCI_CAN_VDD_300 0x02000000
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c
index ced309b37a8f..7a282672f8e9 100644
--- a/drivers/mmc/wbsd.c
+++ b/drivers/mmc/wbsd.c
@@ -1021,7 +1021,7 @@ static int wbsd_get_ro(struct mmc_host *mmc)
return csr & WBSD_WRPT;
}
-static struct mmc_host_ops wbsd_ops = {
+static const struct mmc_host_ops wbsd_ops = {
.request = wbsd_request,
.set_ios = wbsd_set_ios,
.get_ro = wbsd_get_ro,
@@ -1488,7 +1488,7 @@ static void __devinit wbsd_request_dma(struct wbsd_host *host, int dma)
/*
* Translate the address to a physical address.
*/
- host->dma_addr = dma_map_single(host->mmc->dev, host->dma_buffer,
+ host->dma_addr = dma_map_single(mmc_dev(host->mmc), host->dma_buffer,
WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
/*
@@ -1512,7 +1512,7 @@ kfree:
*/
BUG_ON(1);
- dma_unmap_single(host->mmc->dev, host->dma_addr,
+ dma_unmap_single(mmc_dev(host->mmc), host->dma_addr,
WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
host->dma_addr = (dma_addr_t)NULL;
@@ -1530,7 +1530,7 @@ err:
static void __devexit wbsd_release_dma(struct wbsd_host *host)
{
if (host->dma_addr) {
- dma_unmap_single(host->mmc->dev, host->dma_addr,
+ dma_unmap_single(mmc_dev(host->mmc), host->dma_addr,
WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
}
kfree(host->dma_buffer);
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
index 7ea49a0d5ec3..296159ec5189 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -1087,7 +1087,7 @@ static int inval_cache_and_wait_for_operation(
}
spin_lock(chip->mutex);
- if (chip->state != chip_state) {
+ while (chip->state != chip_state) {
/* Someone's suspended the operation: sleep */
DECLARE_WAITQUEUE(wait, current);
set_current_state(TASK_UNINTERRUPTIBLE);
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 24747bdc3e19..d132ed571f13 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -607,7 +607,7 @@ config MTD_BAST_MAXSIZE
default "4"
config MTD_SHARP_SL
- bool "ROM maped on Sharp SL Series"
+ bool "ROM mapped on Sharp SL Series"
depends on MTD && ARCH_PXA
help
This enables access to the flash chip on the Sharp SL Series of PDAs.
diff --git a/drivers/mtd/maps/cfi_flagadm.c b/drivers/mtd/maps/cfi_flagadm.c
index 92b5d883d7b0..65e5ee552010 100644
--- a/drivers/mtd/maps/cfi_flagadm.c
+++ b/drivers/mtd/maps/cfi_flagadm.c
@@ -80,7 +80,7 @@ struct mtd_partition flagadm_parts[] = {
.size = FLASH_PARTITION2_SIZE
},
{
- .name = "Persistant storage",
+ .name = "Persistent storage",
.offset = FLASH_PARTITION3_ADDR,
.size = FLASH_PARTITION3_SIZE
}
diff --git a/drivers/net/8390.c b/drivers/net/8390.c
index 3d1c599ac3cb..a82807641dcf 100644
--- a/drivers/net/8390.c
+++ b/drivers/net/8390.c
@@ -1,1104 +1,40 @@
-/* 8390.c: A general NS8390 ethernet driver core for linux. */
-/*
- Written 1992-94 by Donald Becker.
-
- Copyright 1993 United States Government as represented by the
- Director, National Security Agency.
-
- This software may be used and distributed according to the terms
- of the GNU General Public License, incorporated herein by reference.
-
- The author may be reached as becker@scyld.com, or C/O
- Scyld Computing Corporation
- 410 Severn Ave., Suite 210
- Annapolis MD 21403
-
-
- This is the chip-specific code for many 8390-based ethernet adaptors.
- This is not a complete driver, it must be combined with board-specific
- code such as ne.c, wd.c, 3c503.c, etc.
-
- Seeing how at least eight drivers use this code, (not counting the
- PCMCIA ones either) it is easy to break some card by what seems like
- a simple innocent change. Please contact me or Donald if you think
- you have found something that needs changing. -- PG
-
-
- Changelog:
-
- Paul Gortmaker : remove set_bit lock, other cleanups.
- Paul Gortmaker : add ei_get_8390_hdr() so we can pass skb's to
- ei_block_input() for eth_io_copy_and_sum().
- Paul Gortmaker : exchange static int ei_pingpong for a #define,
- also add better Tx error handling.
- Paul Gortmaker : rewrite Rx overrun handling as per NS specs.
- Alexey Kuznetsov : use the 8390's six bit hash multicast filter.
- Paul Gortmaker : tweak ANK's above multicast changes a bit.
- Paul Gortmaker : update packet statistics for v2.1.x
- Alan Cox : support arbitary stupid port mappings on the
- 68K Macintosh. Support >16bit I/O spaces
- Paul Gortmaker : add kmod support for auto-loading of the 8390
- module by all drivers that require it.
- Alan Cox : Spinlocking work, added 'BUG_83C690'
- Paul Gortmaker : Separate out Tx timeout code from Tx path.
- Paul Gortmaker : Remove old unused single Tx buffer code.
- Hayato Fujiwara : Add m32r support.
- Paul Gortmaker : use skb_padto() instead of stack scratch area
-
- Sources:
- The National Semiconductor LAN Databook, and the 3Com 3c503 databook.
-
- */
+/* 8390 core for usual drivers */
static const char version[] =
"8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/jiffies.h>
-#include <linux/fs.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/bitops.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fcntl.h>
-#include <linux/in.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/crc32.h>
-
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-
-#define NS8390_CORE
-#include "8390.h"
-
-#define BUG_83C690
-
-/* These are the operational function interfaces to board-specific
- routines.
- void reset_8390(struct net_device *dev)
- Resets the board associated with DEV, including a hardware reset of
- the 8390. This is only called when there is a transmit timeout, and
- it is always followed by 8390_init().
- void block_output(struct net_device *dev, int count, const unsigned char *buf,
- int start_page)
- Write the COUNT bytes of BUF to the packet buffer at START_PAGE. The
- "page" value uses the 8390's 256-byte pages.
- void get_8390_hdr(struct net_device *dev, struct e8390_hdr *hdr, int ring_page)
- Read the 4 byte, page aligned 8390 header. *If* there is a
- subsequent read, it will be of the rest of the packet.
- void block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
- Read COUNT bytes from the packet buffer into the skb data area. Start
- reading from RING_OFFSET, the address as the 8390 sees it. This will always
- follow the read of the 8390 header.
-*/
-#define ei_reset_8390 (ei_local->reset_8390)
-#define ei_block_output (ei_local->block_output)
-#define ei_block_input (ei_local->block_input)
-#define ei_get_8390_hdr (ei_local->get_8390_hdr)
-
-/* use 0 for production, 1 for verification, >2 for debug */
-#ifndef ei_debug
-int ei_debug = 1;
-#endif
-
-/* Index to functions. */
-static void ei_tx_intr(struct net_device *dev);
-static void ei_tx_err(struct net_device *dev);
-static void ei_tx_timeout(struct net_device *dev);
-static void ei_receive(struct net_device *dev);
-static void ei_rx_overrun(struct net_device *dev);
-
-/* Routines generic to NS8390-based boards. */
-static void NS8390_trigger_send(struct net_device *dev, unsigned int length,
- int start_page);
-static void set_multicast_list(struct net_device *dev);
-static void do_set_multicast_list(struct net_device *dev);
-
-/*
- * SMP and the 8390 setup.
- *
- * The 8390 isnt exactly designed to be multithreaded on RX/TX. There is
- * a page register that controls bank and packet buffer access. We guard
- * this with ei_local->page_lock. Nobody should assume or set the page other
- * than zero when the lock is not held. Lock holders must restore page 0
- * before unlocking. Even pure readers must take the lock to protect in
- * page 0.
- *
- * To make life difficult the chip can also be very slow. We therefore can't
- * just use spinlocks. For the longer lockups we disable the irq the device
- * sits on and hold the lock. We must hold the lock because there is a dual
- * processor case other than interrupts (get stats/set multicast list in
- * parallel with each other and transmit).
- *
- * Note: in theory we can just disable the irq on the card _but_ there is
- * a latency on SMP irq delivery. So we can easily go "disable irq" "sync irqs"
- * enter lock, take the queued irq. So we waddle instead of flying.
- *
- * Finally by special arrangement for the purpose of being generally
- * annoying the transmit function is called bh atomic. That places
- * restrictions on the user context callers as disable_irq won't save
- * them.
- */
-
-
+#include "lib8390.c"
-/**
- * ei_open - Open/initialize the board.
- * @dev: network device to initialize
- *
- * This routine goes all-out, setting everything
- * up anew at each open, even though many of these registers should only
- * need to be set once at boot.
- */
int ei_open(struct net_device *dev)
{
- unsigned long flags;
- struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
-
- /* The card I/O part of the driver (e.g. 3c503) can hook a Tx timeout
- wrapper that does e.g. media check & then calls ei_tx_timeout. */
- if (dev->tx_timeout == NULL)
- dev->tx_timeout = ei_tx_timeout;
- if (dev->watchdog_timeo <= 0)
- dev->watchdog_timeo = TX_TIMEOUT;
-
- /*
- * Grab the page lock so we own the register set, then call
- * the init function.
- */
-
- spin_lock_irqsave(&ei_local->page_lock, flags);
- NS8390_init(dev, 1);
- /* Set the flag before we drop the lock, That way the IRQ arrives
- after its set and we get no silly warnings */
- netif_start_queue(dev);
- spin_unlock_irqrestore(&ei_local->page_lock, flags);
- ei_local->irqlock = 0;
- return 0;
+ return __ei_open(dev);
}
-/**
- * ei_close - shut down network device
- * @dev: network device to close
- *
- * Opposite of ei_open(). Only used when "ifconfig <devname> down" is done.
- */
int ei_close(struct net_device *dev)
{
- struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
- unsigned long flags;
-
- /*
- * Hold the page lock during close
- */
-
- spin_lock_irqsave(&ei_local->page_lock, flags);
- NS8390_init(dev, 0);
- spin_unlock_irqrestore(&ei_local->page_lock, flags);
- netif_stop_queue(dev);
- return 0;
-}
-
-/**
- * ei_tx_timeout - handle transmit time out condition
- * @dev: network device which has apparently fallen asleep
- *
- * Called by kernel when device never acknowledges a transmit has
- * completed (or failed) - i.e. never posted a Tx related interrupt.
- */
-
-void ei_tx_timeout(struct net_device *dev)
-{
- long e8390_base = dev->base_addr;
- struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
- int txsr, isr, tickssofar = jiffies - dev->trans_start;
- unsigned long flags;
-
-#if defined(CONFIG_M32R) && defined(CONFIG_SMP)
- unsigned long icucr;
-
- local_irq_save(flags);
- icucr = inl(M32R_ICU_CR1_PORTL);
- icucr |= M32R_ICUCR_ISMOD11;
- outl(icucr, M32R_ICU_CR1_PORTL);
- local_irq_restore(flags);
-#endif
- ei_local->stat.tx_errors++;
-
- spin_lock_irqsave(&ei_local->page_lock, flags);
- txsr = inb(e8390_base+EN0_TSR);
- isr = inb(e8390_base+EN0_ISR);
- spin_unlock_irqrestore(&ei_local->page_lock, flags);
-
- printk(KERN_DEBUG "%s: Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n",
- dev->name, (txsr & ENTSR_ABT) ? "excess collisions." :
- (isr) ? "lost interrupt?" : "cable problem?", txsr, isr, tickssofar);
-
- if (!isr && !ei_local->stat.tx_packets)
- {
- /* The 8390 probably hasn't gotten on the cable yet. */
- ei_local->interface_num ^= 1; /* Try a different xcvr. */
- }
-
- /* Ugly but a reset can be slow, yet must be protected */
-
- disable_irq_nosync_lockdep(dev->irq);
- spin_lock(&ei_local->page_lock);
-
- /* Try to restart the card. Perhaps the user has fixed something. */
- ei_reset_8390(dev);
- NS8390_init(dev, 1);
-
- spin_unlock(&ei_local->page_lock);
- enable_irq_lockdep(dev->irq);
- netif_wake_queue(dev);
-}
-
-/**
- * ei_start_xmit - begin packet transmission
- * @skb: packet to be sent
- * @dev: network device to which packet is sent
- *
- * Sends a packet to an 8390 network device.
- */
-
-static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- long e8390_base = dev->base_addr;
- struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
- int send_length = skb->len, output_page;
- unsigned long flags;
- char buf[ETH_ZLEN];
- char *data = skb->data;
-
- if (skb->len < ETH_ZLEN) {
- memset(buf, 0, ETH_ZLEN); /* more efficient than doing just the needed bits */
- memcpy(buf, data, skb->len);
- send_length = ETH_ZLEN;
- data = buf;
- }
-
- /* Mask interrupts from the ethercard.
- SMP: We have to grab the lock here otherwise the IRQ handler
- on another CPU can flip window and race the IRQ mask set. We end
- up trashing the mcast filter not disabling irqs if we don't lock */
-
- spin_lock_irqsave(&ei_local->page_lock, flags);
- outb_p(0x00, e8390_base + EN0_IMR);
- spin_unlock_irqrestore(&ei_local->page_lock, flags);
-
-
- /*
- * Slow phase with lock held.
- */
-
- disable_irq_nosync_lockdep_irqsave(dev->irq, &flags);
-
- spin_lock(&ei_local->page_lock);
-
- ei_local->irqlock = 1;
-
- /*
- * We have two Tx slots available for use. Find the first free
- * slot, and then perform some sanity checks. With two Tx bufs,
- * you get very close to transmitting back-to-back packets. With
- * only one Tx buf, the transmitter sits idle while you reload the
- * card, leaving a substantial gap between each transmitted packet.
- */
-
- if (ei_local->tx1 == 0)
- {
- output_page = ei_local->tx_start_page;
- ei_local->tx1 = send_length;
- if (ei_debug && ei_local->tx2 > 0)
- printk(KERN_DEBUG "%s: idle transmitter tx2=%d, lasttx=%d, txing=%d.\n",
- dev->name, ei_local->tx2, ei_local->lasttx, ei_local->txing);
- }
- else if (ei_local->tx2 == 0)
- {
- output_page = ei_local->tx_start_page + TX_PAGES/2;
- ei_local->tx2 = send_length;
- if (ei_debug && ei_local->tx1 > 0)
- printk(KERN_DEBUG "%s: idle transmitter, tx1=%d, lasttx=%d, txing=%d.\n",
- dev->name, ei_local->tx1, ei_local->lasttx, ei_local->txing);
- }
- else
- { /* We should never get here. */
- if (ei_debug)
- printk(KERN_DEBUG "%s: No Tx buffers free! tx1=%d tx2=%d last=%d\n",
- dev->name, ei_local->tx1, ei_local->tx2, ei_local->lasttx);
- ei_local->irqlock = 0;
- netif_stop_queue(dev);
- outb_p(ENISR_ALL, e8390_base + EN0_IMR);
- spin_unlock(&ei_local->page_lock);
- enable_irq_lockdep_irqrestore(dev->irq, &flags);
- ei_local->stat.tx_errors++;
- return 1;
- }
-
- /*
- * Okay, now upload the packet and trigger a send if the transmitter
- * isn't already sending. If it is busy, the interrupt handler will
- * trigger the send later, upon receiving a Tx done interrupt.
- */
-
- ei_block_output(dev, send_length, data, output_page);
-
- if (! ei_local->txing)
- {
- ei_local->txing = 1;
- NS8390_trigger_send(dev, send_length, output_page);
- dev->trans_start = jiffies;
- if (output_page == ei_local->tx_start_page)
- {
- ei_local->tx1 = -1;
- ei_local->lasttx = -1;
- }
- else
- {
- ei_local->tx2 = -1;
- ei_local->lasttx = -2;
- }
- }
- else ei_local->txqueue++;
-
- if (ei_local->tx1 && ei_local->tx2)
- netif_stop_queue(dev);
- else
- netif_start_queue(dev);
-
- /* Turn 8390 interrupts back on. */
- ei_local->irqlock = 0;
- outb_p(ENISR_ALL, e8390_base + EN0_IMR);
-
- spin_unlock(&ei_local->page_lock);
- enable_irq_lockdep_irqrestore(dev->irq, &flags);
-
- dev_kfree_skb (skb);
- ei_local->stat.tx_bytes += send_length;
-
- return 0;
+ return __ei_close(dev);
}
-/**
- * ei_interrupt - handle the interrupts from an 8390
- * @irq: interrupt number
- * @dev_id: a pointer to the net_device
- *
- * Handle the ether interface interrupts. We pull packets from
- * the 8390 via the card specific functions and fire them at the networking
- * stack. We also handle transmit completions and wake the transmit path if
- * necessary. We also update the counters and do other housekeeping as
- * needed.
- */
-
irqreturn_t ei_interrupt(int irq, void *dev_id)
{
- struct net_device *dev = dev_id;
- long e8390_base;
- int interrupts, nr_serviced = 0;
- struct ei_device *ei_local;
-
- e8390_base = dev->base_addr;
- ei_local = netdev_priv(dev);
-
- /*
- * Protect the irq test too.
- */
-
- spin_lock(&ei_local->page_lock);
-
- if (ei_local->irqlock)
- {
-#if 1 /* This might just be an interrupt for a PCI device sharing this line */
- /* The "irqlock" check is only for testing. */
- printk(ei_local->irqlock
- ? "%s: Interrupted while interrupts are masked! isr=%#2x imr=%#2x.\n"
- : "%s: Reentering the interrupt handler! isr=%#2x imr=%#2x.\n",
- dev->name, inb_p(e8390_base + EN0_ISR),
- inb_p(e8390_base + EN0_IMR));
-#endif
- spin_unlock(&ei_local->page_lock);
- return IRQ_NONE;
- }
-
- /* Change to page 0 and read the intr status reg. */
- outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD);
- if (ei_debug > 3)
- printk(KERN_DEBUG "%s: interrupt(isr=%#2.2x).\n", dev->name,
- inb_p(e8390_base + EN0_ISR));
-
- /* !!Assumption!! -- we stay in page 0. Don't break this. */
- while ((interrupts = inb_p(e8390_base + EN0_ISR)) != 0
- && ++nr_serviced < MAX_SERVICE)
- {
- if (!netif_running(dev)) {
- printk(KERN_WARNING "%s: interrupt from stopped card\n", dev->name);
- /* rmk - acknowledge the interrupts */
- outb_p(interrupts, e8390_base + EN0_ISR);
- interrupts = 0;
- break;
- }
- if (interrupts & ENISR_OVER)
- ei_rx_overrun(dev);
- else if (interrupts & (ENISR_RX+ENISR_RX_ERR))
- {
- /* Got a good (?) packet. */
- ei_receive(dev);
- }
- /* Push the next to-transmit packet through. */
- if (interrupts & ENISR_TX)
- ei_tx_intr(dev);
- else if (interrupts & ENISR_TX_ERR)
- ei_tx_err(dev);
-
- if (interrupts & ENISR_COUNTERS)
- {
- ei_local->stat.rx_frame_errors += inb_p(e8390_base + EN0_COUNTER0);
- ei_local->stat.rx_crc_errors += inb_p(e8390_base + EN0_COUNTER1);
- ei_local->stat.rx_missed_errors+= inb_p(e8390_base + EN0_COUNTER2);
- outb_p(ENISR_COUNTERS, e8390_base + EN0_ISR); /* Ack intr. */
- }
-
- /* Ignore any RDC interrupts that make it back to here. */
- if (interrupts & ENISR_RDC)
- {
- outb_p(ENISR_RDC, e8390_base + EN0_ISR);
- }
-
- outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD);
- }
-
- if (interrupts && ei_debug)
- {
- outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD);
- if (nr_serviced >= MAX_SERVICE)
- {
- /* 0xFF is valid for a card removal */
- if(interrupts!=0xFF)
- printk(KERN_WARNING "%s: Too much work at interrupt, status %#2.2x\n",
- dev->name, interrupts);
- outb_p(ENISR_ALL, e8390_base + EN0_ISR); /* Ack. most intrs. */
- } else {
- printk(KERN_WARNING "%s: unknown interrupt %#2x\n", dev->name, interrupts);
- outb_p(0xff, e8390_base + EN0_ISR); /* Ack. all intrs. */
- }
- }
- spin_unlock(&ei_local->page_lock);
- return IRQ_RETVAL(nr_serviced > 0);
+ return __ei_interrupt(irq, dev_id);
}
#ifdef CONFIG_NET_POLL_CONTROLLER
void ei_poll(struct net_device *dev)
{
- disable_irq_lockdep(dev->irq);
- ei_interrupt(dev->irq, dev);
- enable_irq_lockdep(dev->irq);
+ __ei_poll(dev);
}
#endif
-/**
- * ei_tx_err - handle transmitter error
- * @dev: network device which threw the exception
- *
- * A transmitter error has happened. Most likely excess collisions (which
- * is a fairly normal condition). If the error is one where the Tx will
- * have been aborted, we try and send another one right away, instead of
- * letting the failed packet sit and collect dust in the Tx buffer. This
- * is a much better solution as it avoids kernel based Tx timeouts, and
- * an unnecessary card reset.
- *
- * Called with lock held.
- */
-
-static void ei_tx_err(struct net_device *dev)
-{
- long e8390_base = dev->base_addr;
- struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
- unsigned char txsr = inb_p(e8390_base+EN0_TSR);
- unsigned char tx_was_aborted = txsr & (ENTSR_ABT+ENTSR_FU);
-
-#ifdef VERBOSE_ERROR_DUMP
- printk(KERN_DEBUG "%s: transmitter error (%#2x): ", dev->name, txsr);
- if (txsr & ENTSR_ABT)
- printk("excess-collisions ");
- if (txsr & ENTSR_ND)
- printk("non-deferral ");
- if (txsr & ENTSR_CRS)
- printk("lost-carrier ");
- if (txsr & ENTSR_FU)
- printk("FIFO-underrun ");
- if (txsr & ENTSR_CDH)
- printk("lost-heartbeat ");
- printk("\n");
-#endif
-
- outb_p(ENISR_TX_ERR, e8390_base + EN0_ISR); /* Ack intr. */
-
- if (tx_was_aborted)
- ei_tx_intr(dev);
- else
- {
- ei_local->stat.tx_errors++;
- if (txsr & ENTSR_CRS) ei_local->stat.tx_carrier_errors++;
- if (txsr & ENTSR_CDH) ei_local->stat.tx_heartbeat_errors++;
- if (txsr & ENTSR_OWC) ei_local->stat.tx_window_errors++;
- }
-}
-
-/**
- * ei_tx_intr - transmit interrupt handler
- * @dev: network device for which tx intr is handled
- *
- * We have finished a transmit: check for errors and then trigger the next
- * packet to be sent. Called with lock held.
- */
-
-static void ei_tx_intr(struct net_device *dev)
-{
- long e8390_base = dev->base_addr;
- struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
- int status = inb(e8390_base + EN0_TSR);
-
- outb_p(ENISR_TX, e8390_base + EN0_ISR); /* Ack intr. */
-
- /*
- * There are two Tx buffers, see which one finished, and trigger
- * the send of another one if it exists.
- */
- ei_local->txqueue--;
-
- if (ei_local->tx1 < 0)
- {
- if (ei_local->lasttx != 1 && ei_local->lasttx != -1)
- printk(KERN_ERR "%s: bogus last_tx_buffer %d, tx1=%d.\n",
- ei_local->name, ei_local->lasttx, ei_local->tx1);
- ei_local->tx1 = 0;
- if (ei_local->tx2 > 0)
- {
- ei_local->txing = 1;
- NS8390_trigger_send(dev, ei_local->tx2, ei_local->tx_start_page + 6);
- dev->trans_start = jiffies;
- ei_local->tx2 = -1,
- ei_local->lasttx = 2;
- }
- else ei_local->lasttx = 20, ei_local->txing = 0;
- }
- else if (ei_local->tx2 < 0)
- {
- if (ei_local->lasttx != 2 && ei_local->lasttx != -2)
- printk("%s: bogus last_tx_buffer %d, tx2=%d.\n",
- ei_local->name, ei_local->lasttx, ei_local->tx2);
- ei_local->tx2 = 0;
- if (ei_local->tx1 > 0)
- {
- ei_local->txing = 1;
- NS8390_trigger_send(dev, ei_local->tx1, ei_local->tx_start_page);
- dev->trans_start = jiffies;
- ei_local->tx1 = -1;
- ei_local->lasttx = 1;
- }
- else
- ei_local->lasttx = 10, ei_local->txing = 0;
- }
-// else printk(KERN_WARNING "%s: unexpected TX-done interrupt, lasttx=%d.\n",
-// dev->name, ei_local->lasttx);
-
- /* Minimize Tx latency: update the statistics after we restart TXing. */
- if (status & ENTSR_COL)
- ei_local->stat.collisions++;
- if (status & ENTSR_PTX)
- ei_local->stat.tx_packets++;
- else
- {
- ei_local->stat.tx_errors++;
- if (status & ENTSR_ABT)
- {
- ei_local->stat.tx_aborted_errors++;
- ei_local->stat.collisions += 16;
- }
- if (status & ENTSR_CRS)
- ei_local->stat.tx_carrier_errors++;
- if (status & ENTSR_FU)
- ei_local->stat.tx_fifo_errors++;
- if (status & ENTSR_CDH)
- ei_local->stat.tx_heartbeat_errors++;
- if (status & ENTSR_OWC)
- ei_local->stat.tx_window_errors++;
- }
- netif_wake_queue(dev);
-}
-
-/**
- * ei_receive - receive some packets
- * @dev: network device with which receive will be run
- *
- * We have a good packet(s), get it/them out of the buffers.
- * Called with lock held.
- */
-
-static void ei_receive(struct net_device *dev)
-{
- long e8390_base = dev->base_addr;
- struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
- unsigned char rxing_page, this_frame, next_frame;
- unsigned short current_offset;
- int rx_pkt_count = 0;
- struct e8390_pkt_hdr rx_frame;
- int num_rx_pages = ei_local->stop_page-ei_local->rx_start_page;
-
- while (++rx_pkt_count < 10)
- {
- int pkt_len, pkt_stat;
-
- /* Get the rx page (incoming packet pointer). */
- outb_p(E8390_NODMA+E8390_PAGE1, e8390_base + E8390_CMD);
- rxing_page = inb_p(e8390_base + EN1_CURPAG);
- outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD);
-
- /* Remove one frame from the ring. Boundary is always a page behind. */
- this_frame = inb_p(e8390_base + EN0_BOUNDARY) + 1;
- if (this_frame >= ei_local->stop_page)
- this_frame = ei_local->rx_start_page;
-
- /* Someday we'll omit the previous, iff we never get this message.
- (There is at least one clone claimed to have a problem.)
-
- Keep quiet if it looks like a card removal. One problem here
- is that some clones crash in roughly the same way.
- */
- if (ei_debug > 0 && this_frame != ei_local->current_page && (this_frame!=0x0 || rxing_page!=0xFF))
- printk(KERN_ERR "%s: mismatched read page pointers %2x vs %2x.\n",
- dev->name, this_frame, ei_local->current_page);
-
- if (this_frame == rxing_page) /* Read all the frames? */
- break; /* Done for now */
-
- current_offset = this_frame << 8;
- ei_get_8390_hdr(dev, &rx_frame, this_frame);
-
- pkt_len = rx_frame.count - sizeof(struct e8390_pkt_hdr);
- pkt_stat = rx_frame.status;
-
- next_frame = this_frame + 1 + ((pkt_len+4)>>8);
-
- /* Check for bogosity warned by 3c503 book: the status byte is never
- written. This happened a lot during testing! This code should be
- cleaned up someday. */
- if (rx_frame.next != next_frame
- && rx_frame.next != next_frame + 1
- && rx_frame.next != next_frame - num_rx_pages
- && rx_frame.next != next_frame + 1 - num_rx_pages) {
- ei_local->current_page = rxing_page;
- outb(ei_local->current_page-1, e8390_base+EN0_BOUNDARY);
- ei_local->stat.rx_errors++;
- continue;
- }
-
- if (pkt_len < 60 || pkt_len > 1518)
- {
- if (ei_debug)
- printk(KERN_DEBUG "%s: bogus packet size: %d, status=%#2x nxpg=%#2x.\n",
- dev->name, rx_frame.count, rx_frame.status,
- rx_frame.next);
- ei_local->stat.rx_errors++;
- ei_local->stat.rx_length_errors++;
- }
- else if ((pkt_stat & 0x0F) == ENRSR_RXOK)
- {
- struct sk_buff *skb;
-
- skb = dev_alloc_skb(pkt_len+2);
- if (skb == NULL)
- {
- if (ei_debug > 1)
- printk(KERN_DEBUG "%s: Couldn't allocate a sk_buff of size %d.\n",
- dev->name, pkt_len);
- ei_local->stat.rx_dropped++;
- break;
- }
- else
- {
- skb_reserve(skb,2); /* IP headers on 16 byte boundaries */
- skb->dev = dev;
- skb_put(skb, pkt_len); /* Make room */
- ei_block_input(dev, pkt_len, skb, current_offset + sizeof(rx_frame));
- skb->protocol=eth_type_trans(skb,dev);
- netif_rx(skb);
- dev->last_rx = jiffies;
- ei_local->stat.rx_packets++;
- ei_local->stat.rx_bytes += pkt_len;
- if (pkt_stat & ENRSR_PHY)
- ei_local->stat.multicast++;
- }
- }
- else
- {
- if (ei_debug)
- printk(KERN_DEBUG "%s: bogus packet: status=%#2x nxpg=%#2x size=%d\n",
- dev->name, rx_frame.status, rx_frame.next,
- rx_frame.count);
- ei_local->stat.rx_errors++;
- /* NB: The NIC counts CRC, frame and missed errors. */
- if (pkt_stat & ENRSR_FO)
- ei_local->stat.rx_fifo_errors++;
- }
- next_frame = rx_frame.next;
-
- /* This _should_ never happen: it's here for avoiding bad clones. */
- if (next_frame >= ei_local->stop_page) {
- printk("%s: next frame inconsistency, %#2x\n", dev->name,
- next_frame);
- next_frame = ei_local->rx_start_page;
- }
- ei_local->current_page = next_frame;
- outb_p(next_frame-1, e8390_base+EN0_BOUNDARY);
- }
-
- /* We used to also ack ENISR_OVER here, but that would sometimes mask
- a real overrun, leaving the 8390 in a stopped state with rec'vr off. */
- outb_p(ENISR_RX+ENISR_RX_ERR, e8390_base+EN0_ISR);
- return;
-}
-
-/**
- * ei_rx_overrun - handle receiver overrun
- * @dev: network device which threw exception
- *
- * We have a receiver overrun: we have to kick the 8390 to get it started
- * again. Problem is that you have to kick it exactly as NS prescribes in
- * the updated datasheets, or "the NIC may act in an unpredictable manner."
- * This includes causing "the NIC to defer indefinitely when it is stopped
- * on a busy network." Ugh.
- * Called with lock held. Don't call this with the interrupts off or your
- * computer will hate you - it takes 10ms or so.
- */
-
-static void ei_rx_overrun(struct net_device *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);
-
- /*
- * Record whether a Tx was in progress and then issue the
- * stop command.
- */
- was_txing = inb_p(e8390_base+E8390_CMD) & E8390_TRANS;
- outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
-
- if (ei_debug > 1)
- printk(KERN_DEBUG "%s: Receiver overrun.\n", dev->name);
- ei_local->stat.rx_over_errors++;
-
- /*
- * Wait a full Tx time (1.2ms) + some guard time, NS says 1.6ms total.
- * Early datasheets said to poll the reset bit, but now they say that
- * it "is not a reliable indicator and subsequently should be ignored."
- * We wait at least 10ms.
- */
-
- mdelay(10);
-
- /*
- * Reset RBCR[01] back to zero as per magic incantation.
- */
- outb_p(0x00, e8390_base+EN0_RCNTLO);
- outb_p(0x00, e8390_base+EN0_RCNTHI);
-
- /*
- * See if any Tx was interrupted or not. According to NS, this
- * step is vital, and skipping it will cause no end of havoc.
- */
-
- if (was_txing)
- {
- unsigned char tx_completed = inb_p(e8390_base+EN0_ISR) & (ENISR_TX+ENISR_TX_ERR);
- if (!tx_completed)
- must_resend = 1;
- }
-
- /*
- * Have to enter loopback mode and then restart the NIC before
- * you are allowed to slurp packets up off the ring.
- */
- outb_p(E8390_TXOFF, e8390_base + EN0_TXCR);
- outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, e8390_base + E8390_CMD);
-
- /*
- * Clear the Rx ring of all the debris, and ack the interrupt.
- */
- ei_receive(dev);
- outb_p(ENISR_OVER, e8390_base+EN0_ISR);
-
- /*
- * Leave loopback mode, and resend any packet that got stopped.
- */
- outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR);
- if (must_resend)
- outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START + E8390_TRANS, e8390_base + E8390_CMD);
-}
-
-/*
- * Collect the stats. This is called unlocked and from several contexts.
- */
-
-static struct net_device_stats *get_stats(struct net_device *dev)
-{
- long ioaddr = dev->base_addr;
- struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
- unsigned long flags;
-
- /* If the card is stopped, just return the present stats. */
- if (!netif_running(dev))
- return &ei_local->stat;
-
- spin_lock_irqsave(&ei_local->page_lock,flags);
- /* Read the counter registers, assuming we are in page 0. */
- ei_local->stat.rx_frame_errors += inb_p(ioaddr + EN0_COUNTER0);
- ei_local->stat.rx_crc_errors += inb_p(ioaddr + EN0_COUNTER1);
- ei_local->stat.rx_missed_errors+= inb_p(ioaddr + EN0_COUNTER2);
- spin_unlock_irqrestore(&ei_local->page_lock, flags);
-
- return &ei_local->stat;
-}
-
-/*
- * Form the 64 bit 8390 multicast table from the linked list of addresses
- * associated with this dev structure.
- */
-
-static inline void make_mc_bits(u8 *bits, struct net_device *dev)
-{
- struct dev_mc_list *dmi;
-
- for (dmi=dev->mc_list; dmi; dmi=dmi->next)
- {
- u32 crc;
- if (dmi->dmi_addrlen != ETH_ALEN)
- {
- printk(KERN_INFO "%s: invalid multicast address length given.\n", dev->name);
- continue;
- }
- crc = ether_crc(ETH_ALEN, dmi->dmi_addr);
- /*
- * The 8390 uses the 6 most significant bits of the
- * CRC to index the multicast table.
- */
- bits[crc>>29] |= (1<<((crc>>26)&7));
- }
-}
-
-/**
- * do_set_multicast_list - set/clear multicast filter
- * @dev: net device for which multicast filter is adjusted
- *
- * Set or clear the multicast filter for this adaptor. May be called
- * from a BH in 2.1.x. Must be called with lock held.
- */
-
-static void do_set_multicast_list(struct net_device *dev)
-{
- long e8390_base = dev->base_addr;
- int i;
- struct ei_device *ei_local = (struct ei_device*)netdev_priv(dev);
-
- if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI)))
- {
- memset(ei_local->mcfilter, 0, 8);
- if (dev->mc_list)
- make_mc_bits(ei_local->mcfilter, dev);
- }
- else
- memset(ei_local->mcfilter, 0xFF, 8); /* mcast set to accept-all */
-
- /*
- * DP8390 manuals don't specify any magic sequence for altering
- * the multicast regs on an already running card. To be safe, we
- * ensure multicast mode is off prior to loading up the new hash
- * table. If this proves to be not enough, we can always resort
- * to stopping the NIC, loading the table and then restarting.
- *
- * Bug Alert! The MC regs on the SMC 83C690 (SMC Elite and SMC
- * Elite16) appear to be write-only. The NS 8390 data sheet lists
- * them as r/w so this is a bug. The SMC 83C790 (SMC Ultra and
- * Ultra32 EISA) appears to have this bug fixed.
- */
-
- if (netif_running(dev))
- outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR);
- outb_p(E8390_NODMA + E8390_PAGE1, e8390_base + E8390_CMD);
- for(i = 0; i < 8; i++)
- {
- outb_p(ei_local->mcfilter[i], e8390_base + EN1_MULT_SHIFT(i));
-#ifndef BUG_83C690
- if(inb_p(e8390_base + EN1_MULT_SHIFT(i))!=ei_local->mcfilter[i])
- printk(KERN_ERR "Multicast filter read/write mismap %d\n",i);
-#endif
- }
- outb_p(E8390_NODMA + E8390_PAGE0, e8390_base + E8390_CMD);
-
- if(dev->flags&IFF_PROMISC)
- outb_p(E8390_RXCONFIG | 0x18, e8390_base + EN0_RXCR);
- else if(dev->flags&IFF_ALLMULTI || dev->mc_list)
- outb_p(E8390_RXCONFIG | 0x08, e8390_base + EN0_RXCR);
- else
- outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR);
- }
-
-/*
- * Called without lock held. This is invoked from user context and may
- * be parallel to just about everything else. Its also fairly quick and
- * not called too often. Must protect against both bh and irq users
- */
-
-static void set_multicast_list(struct net_device *dev)
-{
- unsigned long flags;
- struct ei_device *ei_local = (struct ei_device*)netdev_priv(dev);
-
- spin_lock_irqsave(&ei_local->page_lock, flags);
- do_set_multicast_list(dev);
- spin_unlock_irqrestore(&ei_local->page_lock, flags);
-}
-
-/**
- * ethdev_setup - init rest of 8390 device struct
- * @dev: network device structure to init
- *
- * Initialize the rest of the 8390 device structure. Do NOT __init
- * this, as it is used by 8390 based modular drivers too.
- */
-
-static void ethdev_setup(struct net_device *dev)
-{
- struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
- if (ei_debug > 1)
- printk(version);
-
- dev->hard_start_xmit = &ei_start_xmit;
- dev->get_stats = get_stats;
- dev->set_multicast_list = &set_multicast_list;
-
- ether_setup(dev);
-
- spin_lock_init(&ei_local->page_lock);
-}
-
-/**
- * alloc_ei_netdev - alloc_etherdev counterpart for 8390
- * @size: extra bytes to allocate
- *
- * Allocate 8390-specific net_device.
- */
struct net_device *__alloc_ei_netdev(int size)
{
- return alloc_netdev(sizeof(struct ei_device) + size, "eth%d",
- ethdev_setup);
+ return ____alloc_ei_netdev(size);
}
-
-
-
-/* This page of functions should be 8390 generic */
-/* Follow National Semi's recommendations for initializing the "NIC". */
-
-/**
- * NS8390_init - initialize 8390 hardware
- * @dev: network device to initialize
- * @startp: boolean. non-zero value to initiate chip processing
- *
- * Must be called with lock held.
- */
-
void NS8390_init(struct net_device *dev, int startp)
{
- long e8390_base = dev->base_addr;
- struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
- int i;
- int endcfg = ei_local->word16
- ? (0x48 | ENDCFG_WTS | (ei_local->bigendian ? ENDCFG_BOS : 0))
- : 0x48;
-
- if(sizeof(struct e8390_pkt_hdr)!=4)
- panic("8390.c: header struct mispacked\n");
- /* Follow National Semi's recommendations for initing the DP83902. */
- outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); /* 0x21 */
- outb_p(endcfg, e8390_base + EN0_DCFG); /* 0x48 or 0x49 */
- /* Clear the remote byte count registers. */
- outb_p(0x00, e8390_base + EN0_RCNTLO);
- outb_p(0x00, e8390_base + EN0_RCNTHI);
- /* Set to monitor and loopback mode -- this is vital!. */
- outb_p(E8390_RXOFF, e8390_base + EN0_RXCR); /* 0x20 */
- outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); /* 0x02 */
- /* Set the transmit page and receive ring. */
- outb_p(ei_local->tx_start_page, e8390_base + EN0_TPSR);
- ei_local->tx1 = ei_local->tx2 = 0;
- outb_p(ei_local->rx_start_page, e8390_base + EN0_STARTPG);
- outb_p(ei_local->stop_page-1, e8390_base + EN0_BOUNDARY); /* 3c503 says 0x3f,NS0x26*/
- ei_local->current_page = ei_local->rx_start_page; /* assert boundary+1 */
- outb_p(ei_local->stop_page, e8390_base + EN0_STOPPG);
- /* Clear the pending interrupts and mask. */
- outb_p(0xFF, e8390_base + EN0_ISR);
- outb_p(0x00, e8390_base + EN0_IMR);
-
- /* Copy the station address into the DS8390 registers. */
-
- outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, e8390_base+E8390_CMD); /* 0x61 */
- for(i = 0; i < 6; i++)
- {
- outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS_SHIFT(i));
- if (ei_debug > 1 && inb_p(e8390_base + EN1_PHYS_SHIFT(i))!=dev->dev_addr[i])
- printk(KERN_ERR "Hw. address read/write mismap %d\n",i);
- }
-
- outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG);
- outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
-
- netif_start_queue(dev);
- ei_local->tx1 = ei_local->tx2 = 0;
- ei_local->txing = 0;
-
- if (startp)
- {
- outb_p(0xff, e8390_base + EN0_ISR);
- outb_p(ENISR_ALL, e8390_base + EN0_IMR);
- outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+E8390_CMD);
- outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR); /* xmit on. */
- /* 3c503 TechMan says rxconfig only after the NIC is started. */
- outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR); /* rx on, */
- do_set_multicast_list(dev); /* (re)load the mcast table */
- }
-}
-
-/* Trigger a transmit start, assuming the length is valid.
- Always called with the page lock held */
-
-static void NS8390_trigger_send(struct net_device *dev, unsigned int length,
- int start_page)
-{
- long e8390_base = dev->base_addr;
- struct ei_device *ei_local __attribute((unused)) = (struct ei_device *) netdev_priv(dev);
-
- outb_p(E8390_NODMA+E8390_PAGE0, e8390_base+E8390_CMD);
-
- if (inb_p(e8390_base + E8390_CMD) & E8390_TRANS)
- {
- printk(KERN_WARNING "%s: trigger_send() called with the transmitter busy.\n",
- dev->name);
- return;
- }
- outb_p(length & 0xff, e8390_base + EN0_TCNTLO);
- outb_p(length >> 8, e8390_base + EN0_TCNTHI);
- outb_p(start_page, e8390_base + EN0_TPSR);
- outb_p(E8390_NODMA+E8390_TRANS+E8390_START, e8390_base+E8390_CMD);
+ return __NS8390_init(dev, startp);
}
EXPORT_SYMBOL(ei_open);
diff --git a/drivers/net/8390.h b/drivers/net/8390.h
index f44f1220b3a5..414de5bd228f 100644
--- a/drivers/net/8390.h
+++ b/drivers/net/8390.h
@@ -107,35 +107,14 @@ struct ei_device {
* - removed AMIGA_PCMCIA from this list, handled as ISA io now
*/
-#if defined(CONFIG_MAC) || \
- defined(CONFIG_ZORRO8390) || defined(CONFIG_ZORRO8390_MODULE) || \
- defined(CONFIG_HYDRA) || defined(CONFIG_HYDRA_MODULE)
-#define EI_SHIFT(x) (ei_local->reg_offset[x])
-#undef inb
-#undef inb_p
-#undef outb
-#undef outb_p
-
-#define inb(port) in_8(port)
-#define outb(val,port) out_8(port,val)
-#define inb_p(port) in_8(port)
-#define outb_p(val,port) out_8(port,val)
-
-#elif defined(CONFIG_ARM_ETHERH) || defined(CONFIG_ARM_ETHERH_MODULE)
-#define EI_SHIFT(x) (ei_local->reg_offset[x])
-#undef inb
-#undef inb_p
-#undef outb
-#undef outb_p
-
-#define inb(_p) readb(_p)
-#define outb(_v,_p) writeb(_v,_p)
-#define inb_p(_p) inb(_p)
-#define outb_p(_v,_p) outb(_v,_p)
-
-#elif defined(CONFIG_NE_H8300) || defined(CONFIG_NE_H8300_MODULE)
-#define EI_SHIFT(x) (ei_local->reg_offset[x])
-#else
+#ifndef ei_inb
+#define ei_inb(_p) inb(_p)
+#define ei_outb(_v,_p) outb(_v,_p)
+#define ei_inb_p(_p) inb_p(_p)
+#define ei_outb_p(_v,_p) outb_p(_v,_p)
+#endif
+
+#ifndef EI_SHIFT
#define EI_SHIFT(x) (x)
#endif
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 6e863aa9894c..9de0eed6755b 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -32,7 +32,7 @@ config IFB
tristate "Intermediate Functional Block support"
depends on NET_CLS_ACT
---help---
- This is an intermidiate driver that allows sharing of
+ This is an intermediate driver that allows sharing of
resources.
To compile this driver as a module, choose M here: the module
will be called ifb. If you want to use more than one ifb
@@ -188,6 +188,17 @@ config MII
or internal device. It is safe to say Y or M here even if your
ethernet card lack MII.
+config MACB
+ tristate "Atmel MACB support"
+ depends on NET_ETHERNET && AVR32
+ select MII
+ help
+ The Atmel MACB ethernet interface is found on many AT32 and AT91
+ parts. Say Y to include support for the MACB chip.
+
+ To compile this driver as a module, choose M here: the module
+ will be called macb.
+
source "drivers/net/arm/Kconfig"
config MACE
@@ -1769,8 +1780,8 @@ config VIA_RHINE_NAPI
information.
config LAN_SAA9730
- bool "Philips SAA9730 Ethernet support (EXPERIMENTAL)"
- depends on NET_PCI && EXPERIMENTAL && MIPS
+ bool "Philips SAA9730 Ethernet support"
+ depends on NET_PCI && PCI && MIPS_ATLAS
help
The SAA9730 is a combined multimedia and peripheral controller used
in thin clients, Internet access terminals, and diskless
@@ -2136,7 +2147,7 @@ config SK98LIN
This driver supports the original Yukon chipset. A cleaner driver is
also available (skge) which seems to work better than this one.
- This driver does not support the newer Yukon2 chipset. A seperate
+ This driver does not support the newer Yukon2 chipset. A separate
driver, sky2, is provided to support Yukon2-based adapters.
The following adapters are supported by this driver:
@@ -2251,6 +2262,14 @@ config SPIDER_NET
This driver supports the Gigabit Ethernet chips present on the
Cell Processor-Based Blades from IBM.
+config TSI108_ETH
+ tristate "Tundra TSI108 gigabit Ethernet support"
+ depends on TSI108_BRIDGE
+ help
+ This driver supports Tundra TSI108 gigabit Ethernet ports.
+ To compile this driver as a module, choose M here: the module
+ will be called tsi108_eth.
+
config GIANFAR
tristate "Gianfar Ethernet"
depends on 85xx || 83xx || PPC_86xx
@@ -2341,10 +2360,11 @@ menu "Ethernet (10000 Mbit)"
config CHELSIO_T1
tristate "Chelsio 10Gb Ethernet support"
depends on PCI
+ select CRC32
help
- This driver supports Chelsio N110 and N210 models 10Gb Ethernet
- cards. More information about adapter features and performance
- tuning is in <file:Documentation/networking/cxgb.txt>.
+ This driver supports Chelsio gigabit and 10-gigabit
+ Ethernet cards. More information about adapter features and
+ performance tuning is in <file:Documentation/networking/cxgb.txt>.
For general information about Chelsio and our products, visit
our website at <http://www.chelsio.com>.
@@ -2357,6 +2377,13 @@ config CHELSIO_T1
To compile this driver as a module, choose M here: the module
will be called cxgb.
+config CHELSIO_T1_1G
+ bool "Chelsio gigabit Ethernet support"
+ depends on CHELSIO_T1
+ help
+ Enables support for Chelsio's gigabit Ethernet PCI cards. If you
+ are using only 10G cards say 'N' here.
+
config EHEA
tristate "eHEA Ethernet support"
depends on IBMEBUS
@@ -2447,6 +2474,12 @@ config MYRI10GE
<file:Documentation/networking/net-modules.txt>. The module
will be called myri10ge.
+config NETXEN_NIC
+ tristate "NetXen Multi port (1/10) Gigabit Ethernet NIC"
+ depends on PCI
+ help
+ This enables the support for NetXen's Gigabit Ethernet card.
+
endmenu
source "drivers/net/tokenring/Kconfig"
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index f270bc49e571..4c0d4e5ce42b 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -82,7 +82,7 @@ obj-$(CONFIG_HAMACHI) += hamachi.o
obj-$(CONFIG_NET) += Space.o loopback.o
obj-$(CONFIG_SEEQ8005) += seeq8005.o
obj-$(CONFIG_NET_SB1000) += sb1000.o
-obj-$(CONFIG_MAC8390) += mac8390.o 8390.o
+obj-$(CONFIG_MAC8390) += mac8390.o
obj-$(CONFIG_APNE) += apne.o 8390.o
obj-$(CONFIG_PCMCIA_PCNET) += 8390.o
obj-$(CONFIG_SHAPER) += shaper.o
@@ -90,7 +90,6 @@ obj-$(CONFIG_HP100) += hp100.o
obj-$(CONFIG_SMC9194) += smc9194.o
obj-$(CONFIG_FEC) += fec.o
obj-$(CONFIG_68360_ENET) += 68360enet.o
-obj-$(CONFIG_ARM_ETHERH) += 8390.o
obj-$(CONFIG_WD80x3) += wd.o 8390.o
obj-$(CONFIG_EL2) += 3c503.o 8390.o
obj-$(CONFIG_NE2000) += ne.o 8390.o
@@ -107,8 +106,9 @@ obj-$(CONFIG_NE3210) += ne3210.o 8390.o
obj-$(CONFIG_NET_SB1250_MAC) += sb1250-mac.o
obj-$(CONFIG_B44) += b44.o
obj-$(CONFIG_FORCEDETH) += forcedeth.o
-obj-$(CONFIG_NE_H8300) += ne-h8300.o 8390.o
+obj-$(CONFIG_NE_H8300) += ne-h8300.o
+obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o
obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
obj-$(CONFIG_QLA3XXX) += qla3xxx.o
@@ -165,7 +165,7 @@ obj-$(CONFIG_BVME6000_NET) += 82596.o
obj-$(CONFIG_LP486E) += lp486e.o
obj-$(CONFIG_ETH16I) += eth16i.o
-obj-$(CONFIG_ZORRO8390) += zorro8390.o 8390.o
+obj-$(CONFIG_ZORRO8390) += zorro8390.o
obj-$(CONFIG_HPLANCE) += hplance.o 7990.o
obj-$(CONFIG_MVME147_NET) += mvme147.o 7990.o
obj-$(CONFIG_EQUALIZER) += eql.o
@@ -178,7 +178,7 @@ obj-$(CONFIG_ATARILANCE) += atarilance.o
obj-$(CONFIG_ATARI_BIONET) += atari_bionet.o
obj-$(CONFIG_ATARI_PAMSNET) += atari_pamsnet.o
obj-$(CONFIG_A2065) += a2065.o
-obj-$(CONFIG_HYDRA) += hydra.o 8390.o
+obj-$(CONFIG_HYDRA) += hydra.o
obj-$(CONFIG_ARIADNE) += ariadne.o
obj-$(CONFIG_CS89x0) += cs89x0.o
obj-$(CONFIG_MACSONIC) += macsonic.o
@@ -197,6 +197,8 @@ obj-$(CONFIG_SMC911X) += smc911x.o
obj-$(CONFIG_DM9000) += dm9000.o
obj-$(CONFIG_FEC_8XX) += fec_8xx/
+obj-$(CONFIG_MACB) += macb.o
+
obj-$(CONFIG_ARM) += arm/
obj-$(CONFIG_DEV_APPLETALK) += appletalk/
obj-$(CONFIG_TR) += tokenring/
@@ -214,3 +216,4 @@ obj-$(CONFIG_NETCONSOLE) += netconsole.o
obj-$(CONFIG_FS_ENET) += fs_enet/
+obj-$(CONFIG_NETXEN_NIC) += netxen/
diff --git a/drivers/net/Space.c b/drivers/net/Space.c
index a67f5efc983f..602ed31a5dd9 100644
--- a/drivers/net/Space.c
+++ b/drivers/net/Space.c
@@ -33,7 +33,6 @@
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/netlink.h>
-#include <linux/divert.h>
/* A unified ethernet device probe. This is the easiest way to have every
ethernet adaptor have the name "eth[0123...]".
diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c
index ef65e5917c8f..18896f24d407 100644
--- a/drivers/net/amd8111e.c
+++ b/drivers/net/amd8111e.c
@@ -1490,32 +1490,7 @@ static void amd8111e_read_regs(struct amd8111e_priv *lp, u32 *buf)
buf[12] = readl(mmio + STAT0);
}
-/*
-amd8111e crc generator implementation is different from the kernel
-ether_crc() function.
-*/
-static int amd8111e_ether_crc(int len, char* mac_addr)
-{
- int i,byte;
- unsigned char octet;
- u32 crc= INITCRC;
-
- for(byte=0; byte < len; byte++){
- octet = mac_addr[byte];
- for( i=0;i < 8; i++){
- /*If the next bit form the input stream is 1,subtract the divisor (CRC32) from the dividend(crc).*/
- if( (octet & 0x1) ^ (crc & 0x1) ){
- crc >>= 1;
- crc ^= CRC32;
- }
- else
- crc >>= 1;
- octet >>= 1;
- }
- }
- return crc;
-}
/*
This function sets promiscuos mode, all-multi mode or the multicast address
list to the device.
@@ -1556,7 +1531,7 @@ static void amd8111e_set_multicast_list(struct net_device *dev)
mc_filter[1] = mc_filter[0] = 0;
for (i = 0, mc_ptr = dev->mc_list; mc_ptr && i < dev->mc_count;
i++, mc_ptr = mc_ptr->next) {
- bit_num = ( amd8111e_ether_crc(ETH_ALEN,mc_ptr->dmi_addr) >> 26 ) & 0x3f;
+ bit_num = (ether_crc_le(ETH_ALEN, mc_ptr->dmi_addr) >> 26) & 0x3f;
mc_filter[bit_num >> 5] |= 1 << (bit_num & 31);
}
amd8111e_writeq(*(u64*)mc_filter,lp->mmio+ LADRF);
diff --git a/drivers/net/amd8111e.h b/drivers/net/amd8111e.h
index 7727d328f65e..2007510c4eb6 100644
--- a/drivers/net/amd8111e.h
+++ b/drivers/net/amd8111e.h
@@ -651,10 +651,6 @@ typedef enum {
/* driver ioctl parameters */
#define AMD8111E_REG_DUMP_LEN 13*sizeof(u32)
-/* crc generator constants */
-#define CRC32 0xedb88320
-#define INITCRC 0xFFFFFFFF
-
/* amd8111e desriptor format */
struct amd8111e_tx_dr{
diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c
index 4ae98970b282..f3faa4fe58e7 100644
--- a/drivers/net/arm/etherh.c
+++ b/drivers/net/arm/etherh.c
@@ -52,7 +52,12 @@
#include <asm/ecard.h>
#include <asm/io.h>
-#include "../8390.h"
+#define EI_SHIFT(x) (ei_local->reg_offset[x])
+
+#define ei_inb(_p) readb((void __iomem *)_p)
+#define ei_outb(_v,_p) writeb(_v,(void __iomem *)_p)
+#define ei_inb_p(_p) readb((void __iomem *)_p)
+#define ei_outb_p(_v,_p) writeb(_v,(void __iomem *)_p)
#define NET_DEBUG 0
#define DEBUG_INIT 2
@@ -60,6 +65,11 @@
#define DRV_NAME "etherh"
#define DRV_VERSION "1.11"
+static char version[] __initdata =
+ "EtherH/EtherM Driver (c) 2002-2004 Russell King " DRV_VERSION "\n";
+
+#include "../lib8390.c"
+
static unsigned int net_debug = NET_DEBUG;
struct etherh_priv {
@@ -87,9 +97,6 @@ MODULE_AUTHOR("Russell King");
MODULE_DESCRIPTION("EtherH/EtherM driver");
MODULE_LICENSE("GPL");
-static char version[] __initdata =
- "EtherH/EtherM Driver (c) 2002-2004 Russell King " DRV_VERSION "\n";
-
#define ETHERH500_DATAPORT 0x800 /* MEMC */
#define ETHERH500_NS8390 0x000 /* MEMC */
#define ETHERH500_CTRLPORT 0x800 /* IOC */
@@ -177,7 +184,7 @@ etherh_setif(struct net_device *dev)
switch (etherh_priv(dev)->id) {
case PROD_I3_ETHERLAN600:
case PROD_I3_ETHERLAN600A:
- addr = (void *)dev->base_addr + EN0_RCNTHI;
+ addr = (void __iomem *)dev->base_addr + EN0_RCNTHI;
switch (dev->if_port) {
case IF_PORT_10BASE2:
@@ -218,7 +225,7 @@ etherh_getifstat(struct net_device *dev)
switch (etherh_priv(dev)->id) {
case PROD_I3_ETHERLAN600:
case PROD_I3_ETHERLAN600A:
- addr = (void *)dev->base_addr + EN0_RCNTHI;
+ addr = (void __iomem *)dev->base_addr + EN0_RCNTHI;
switch (dev->if_port) {
case IF_PORT_10BASE2:
stat = 1;
@@ -281,7 +288,7 @@ static void
etherh_reset(struct net_device *dev)
{
struct ei_device *ei_local = netdev_priv(dev);
- void __iomem *addr = (void *)dev->base_addr;
+ void __iomem *addr = (void __iomem *)dev->base_addr;
writeb(E8390_NODMA+E8390_PAGE0+E8390_STOP, addr);
@@ -327,7 +334,7 @@ etherh_block_output (struct net_device *dev, int count, const unsigned char *buf
ei_local->dmaing = 1;
- addr = (void *)dev->base_addr;
+ addr = (void __iomem *)dev->base_addr;
dma_base = etherh_priv(dev)->dma_base;
count = (count + 1) & ~1;
@@ -360,7 +367,7 @@ etherh_block_output (struct net_device *dev, int count, const unsigned char *buf
printk(KERN_ERR "%s: timeout waiting for TX RDC\n",
dev->name);
etherh_reset (dev);
- NS8390_init (dev, 1);
+ __NS8390_init (dev, 1);
break;
}
@@ -387,7 +394,7 @@ etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int
ei_local->dmaing = 1;
- addr = (void *)dev->base_addr;
+ addr = (void __iomem *)dev->base_addr;
dma_base = etherh_priv(dev)->dma_base;
buf = skb->data;
@@ -427,7 +434,7 @@ etherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_p
ei_local->dmaing = 1;
- addr = (void *)dev->base_addr;
+ addr = (void __iomem *)dev->base_addr;
dma_base = etherh_priv(dev)->dma_base;
writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
@@ -465,7 +472,7 @@ etherh_open(struct net_device *dev)
return -EINVAL;
}
- if (request_irq(dev->irq, ei_interrupt, 0, dev->name, dev))
+ if (request_irq(dev->irq, __ei_interrupt, 0, dev->name, dev))
return -EAGAIN;
/*
@@ -491,7 +498,7 @@ etherh_open(struct net_device *dev)
etherh_setif(dev);
etherh_reset(dev);
- ei_open(dev);
+ __ei_open(dev);
return 0;
}
@@ -502,7 +509,7 @@ etherh_open(struct net_device *dev)
static int
etherh_close(struct net_device *dev)
{
- ei_close (dev);
+ __ei_close (dev);
free_irq (dev->irq, dev);
return 0;
}
@@ -650,7 +657,7 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
if (ret)
goto out;
- dev = __alloc_ei_netdev(sizeof(struct etherh_priv));
+ dev = ____alloc_ei_netdev(sizeof(struct etherh_priv));
if (!dev) {
ret = -ENOMEM;
goto release;
@@ -736,7 +743,7 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
ei_local->interface_num = 0;
etherh_reset(dev);
- NS8390_init(dev, 0);
+ __NS8390_init(dev, 0);
ret = register_netdev(dev);
if (ret)
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index 7db3c8af0894..f0b6879a1c7d 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -360,7 +360,8 @@ static int mii_probe (struct net_device *dev)
BUG_ON(!phydev);
BUG_ON(phydev->attached_dev);
- phydev = phy_connect(dev, phydev->dev.bus_id, &au1000_adjust_link, 0);
+ phydev = phy_connect(dev, phydev->dev.bus_id, &au1000_adjust_link, 0,
+ PHY_INTERFACE_MODE_MII);
if (IS_ERR(phydev)) {
printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index b12cc4596b8d..5bacb7587df4 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -53,11 +53,12 @@
#include "bnx2.h"
#include "bnx2_fw.h"
+#include "bnx2_fw2.h"
#define DRV_MODULE_NAME "bnx2"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "1.4.45"
-#define DRV_MODULE_RELDATE "September 29, 2006"
+#define DRV_MODULE_VERSION "1.5.1"
+#define DRV_MODULE_RELDATE "November 15, 2006"
#define RUN_AT(x) (jiffies + (x))
@@ -85,6 +86,7 @@ typedef enum {
NC370F,
BCM5708,
BCM5708S,
+ BCM5709,
} board_t;
/* indexed by board_t, above */
@@ -98,6 +100,7 @@ static const struct {
{ "HP NC370F Multifunction Gigabit Server Adapter" },
{ "Broadcom NetXtreme II BCM5708 1000Base-T" },
{ "Broadcom NetXtreme II BCM5708 1000Base-SX" },
+ { "Broadcom NetXtreme II BCM5709 1000Base-T" },
};
static struct pci_device_id bnx2_pci_tbl[] = {
@@ -115,6 +118,8 @@ static struct pci_device_id bnx2_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5706S },
{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5708S,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5708S },
+ { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5709,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5709 },
{ 0, }
};
@@ -236,8 +241,23 @@ static void
bnx2_ctx_wr(struct bnx2 *bp, u32 cid_addr, u32 offset, u32 val)
{
offset += cid_addr;
- REG_WR(bp, BNX2_CTX_DATA_ADR, offset);
- REG_WR(bp, BNX2_CTX_DATA, val);
+ if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+ int i;
+
+ REG_WR(bp, BNX2_CTX_CTX_DATA, val);
+ REG_WR(bp, BNX2_CTX_CTX_CTRL,
+ offset | BNX2_CTX_CTX_CTRL_WRITE_REQ);
+ for (i = 0; i < 5; i++) {
+ u32 val;
+ val = REG_RD(bp, BNX2_CTX_CTX_CTRL);
+ if ((val & BNX2_CTX_CTX_CTRL_WRITE_REQ) == 0)
+ break;
+ udelay(5);
+ }
+ } else {
+ REG_WR(bp, BNX2_CTX_DATA_ADR, offset);
+ REG_WR(bp, BNX2_CTX_DATA, val);
+ }
}
static int
@@ -403,6 +423,14 @@ bnx2_free_mem(struct bnx2 *bp)
{
int i;
+ for (i = 0; i < bp->ctx_pages; i++) {
+ if (bp->ctx_blk[i]) {
+ pci_free_consistent(bp->pdev, BCM_PAGE_SIZE,
+ bp->ctx_blk[i],
+ bp->ctx_blk_mapping[i]);
+ bp->ctx_blk[i] = NULL;
+ }
+ }
if (bp->status_blk) {
pci_free_consistent(bp->pdev, bp->status_stats_size,
bp->status_blk, bp->status_blk_mapping);
@@ -481,6 +509,18 @@ bnx2_alloc_mem(struct bnx2 *bp)
bp->stats_blk_mapping = bp->status_blk_mapping + status_blk_size;
+ if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+ bp->ctx_pages = 0x2000 / BCM_PAGE_SIZE;
+ if (bp->ctx_pages == 0)
+ bp->ctx_pages = 1;
+ for (i = 0; i < bp->ctx_pages; i++) {
+ bp->ctx_blk[i] = pci_alloc_consistent(bp->pdev,
+ BCM_PAGE_SIZE,
+ &bp->ctx_blk_mapping[i]);
+ if (bp->ctx_blk[i] == NULL)
+ goto alloc_mem_err;
+ }
+ }
return 0;
alloc_mem_err:
@@ -803,13 +843,13 @@ bnx2_set_mac_link(struct bnx2 *bp)
val &= ~(BNX2_EMAC_MODE_PORT | BNX2_EMAC_MODE_HALF_DUPLEX |
BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK |
- BNX2_EMAC_MODE_25G);
+ BNX2_EMAC_MODE_25G_MODE);
if (bp->link_up) {
switch (bp->line_speed) {
case SPEED_10:
- if (CHIP_NUM(bp) == CHIP_NUM_5708) {
- val |= BNX2_EMAC_MODE_PORT_MII_10;
+ if (CHIP_NUM(bp) != CHIP_NUM_5706) {
+ val |= BNX2_EMAC_MODE_PORT_MII_10M;
break;
}
/* fall through */
@@ -817,7 +857,7 @@ bnx2_set_mac_link(struct bnx2 *bp)
val |= BNX2_EMAC_MODE_PORT_MII;
break;
case SPEED_2500:
- val |= BNX2_EMAC_MODE_25G;
+ val |= BNX2_EMAC_MODE_25G_MODE;
/* fall through */
case SPEED_1000:
val |= BNX2_EMAC_MODE_PORT_GMII;
@@ -860,7 +900,7 @@ bnx2_set_link(struct bnx2 *bp)
u32 bmsr;
u8 link_up;
- if (bp->loopback == MAC_LOOPBACK) {
+ if (bp->loopback == MAC_LOOPBACK || bp->loopback == PHY_LOOPBACK) {
bp->link_up = 1;
return 0;
}
@@ -902,6 +942,7 @@ bnx2_set_link(struct bnx2 *bp)
u32 bmcr;
bnx2_read_phy(bp, MII_BMCR, &bmcr);
+ bmcr &= ~BCM5708S_BMCR_FORCE_2500;
if (!(bmcr & BMCR_ANENABLE)) {
bnx2_write_phy(bp, MII_BMCR, bmcr |
BMCR_ANENABLE);
@@ -988,7 +1029,21 @@ bnx2_setup_serdes_phy(struct bnx2 *bp)
u32 new_bmcr;
int force_link_down = 0;
- if (CHIP_NUM(bp) == CHIP_NUM_5708) {
+ bnx2_read_phy(bp, MII_ADVERTISE, &adv);
+ adv &= ~(ADVERTISE_1000XFULL | ADVERTISE_1000XHALF);
+
+ bnx2_read_phy(bp, MII_BMCR, &bmcr);
+ new_bmcr = bmcr & ~(BMCR_ANENABLE | BCM5708S_BMCR_FORCE_2500);
+ new_bmcr |= BMCR_SPEED1000;
+ if (bp->req_line_speed == SPEED_2500) {
+ new_bmcr |= BCM5708S_BMCR_FORCE_2500;
+ bnx2_read_phy(bp, BCM5708S_UP1, &up1);
+ if (!(up1 & BCM5708S_UP1_2G5)) {
+ up1 |= BCM5708S_UP1_2G5;
+ bnx2_write_phy(bp, BCM5708S_UP1, up1);
+ force_link_down = 1;
+ }
+ } else if (CHIP_NUM(bp) == CHIP_NUM_5708) {
bnx2_read_phy(bp, BCM5708S_UP1, &up1);
if (up1 & BCM5708S_UP1_2G5) {
up1 &= ~BCM5708S_UP1_2G5;
@@ -997,12 +1052,6 @@ bnx2_setup_serdes_phy(struct bnx2 *bp)
}
}
- bnx2_read_phy(bp, MII_ADVERTISE, &adv);
- adv &= ~(ADVERTISE_1000XFULL | ADVERTISE_1000XHALF);
-
- bnx2_read_phy(bp, MII_BMCR, &bmcr);
- new_bmcr = bmcr & ~BMCR_ANENABLE;
- new_bmcr |= BMCR_SPEED1000;
if (bp->req_duplex == DUPLEX_FULL) {
adv |= ADVERTISE_1000XFULL;
new_bmcr |= BMCR_FULLDPLX;
@@ -1023,6 +1072,7 @@ bnx2_setup_serdes_phy(struct bnx2 *bp)
bp->link_up = 0;
netif_carrier_off(bp->dev);
bnx2_write_phy(bp, MII_BMCR, new_bmcr);
+ bnx2_report_link(bp);
}
bnx2_write_phy(bp, MII_ADVERTISE, adv);
bnx2_write_phy(bp, MII_BMCR, new_bmcr);
@@ -1048,30 +1098,26 @@ bnx2_setup_serdes_phy(struct bnx2 *bp)
if ((adv != new_adv) || ((bmcr & BMCR_ANENABLE) == 0)) {
/* Force a link down visible on the other side */
if (bp->link_up) {
- int i;
-
bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK);
- for (i = 0; i < 110; i++) {
- udelay(100);
- }
+ spin_unlock_bh(&bp->phy_lock);
+ msleep(20);
+ spin_lock_bh(&bp->phy_lock);
}
bnx2_write_phy(bp, MII_ADVERTISE, new_adv);
bnx2_write_phy(bp, MII_BMCR, bmcr | BMCR_ANRESTART |
BMCR_ANENABLE);
- if (CHIP_NUM(bp) == CHIP_NUM_5706) {
- /* Speed up link-up time when the link partner
- * does not autonegotiate which is very common
- * in blade servers. Some blade servers use
- * IPMI for kerboard input and it's important
- * to minimize link disruptions. Autoneg. involves
- * exchanging base pages plus 3 next pages and
- * normally completes in about 120 msec.
- */
- bp->current_interval = SERDES_AN_TIMEOUT;
- bp->serdes_an_pending = 1;
- mod_timer(&bp->timer, jiffies + bp->current_interval);
- }
+ /* Speed up link-up time when the link partner
+ * does not autonegotiate which is very common
+ * in blade servers. Some blade servers use
+ * IPMI for kerboard input and it's important
+ * to minimize link disruptions. Autoneg. involves
+ * exchanging base pages plus 3 next pages and
+ * normally completes in about 120 msec.
+ */
+ bp->current_interval = SERDES_AN_TIMEOUT;
+ bp->serdes_an_pending = 1;
+ mod_timer(&bp->timer, jiffies + bp->current_interval);
}
return 0;
@@ -1153,7 +1199,6 @@ bnx2_setup_copper_phy(struct bnx2 *bp)
}
if (new_bmcr != bmcr) {
u32 bmsr;
- int i = 0;
bnx2_read_phy(bp, MII_BMSR, &bmsr);
bnx2_read_phy(bp, MII_BMSR, &bmsr);
@@ -1161,12 +1206,12 @@ bnx2_setup_copper_phy(struct bnx2 *bp)
if (bmsr & BMSR_LSTATUS) {
/* Force link down */
bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK);
- do {
- udelay(100);
- bnx2_read_phy(bp, MII_BMSR, &bmsr);
- bnx2_read_phy(bp, MII_BMSR, &bmsr);
- i++;
- } while ((bmsr & BMSR_LSTATUS) && (i < 620));
+ spin_unlock_bh(&bp->phy_lock);
+ msleep(50);
+ spin_lock_bh(&bp->phy_lock);
+
+ bnx2_read_phy(bp, MII_BMSR, &bmsr);
+ bnx2_read_phy(bp, MII_BMSR, &bmsr);
}
bnx2_write_phy(bp, MII_BMCR, new_bmcr);
@@ -1258,9 +1303,8 @@ bnx2_init_5706s_phy(struct bnx2 *bp)
{
bp->phy_flags &= ~PHY_PARALLEL_DETECT_FLAG;
- if (CHIP_NUM(bp) == CHIP_NUM_5706) {
- REG_WR(bp, BNX2_MISC_UNUSED0, 0x300);
- }
+ if (CHIP_NUM(bp) == CHIP_NUM_5706)
+ REG_WR(bp, BNX2_MISC_GP_HW_CTL0, 0x300);
if (bp->dev->mtu > 1500) {
u32 val;
@@ -1397,13 +1441,13 @@ bnx2_set_phy_loopback(struct bnx2 *bp)
for (i = 0; i < 10; i++) {
if (bnx2_test_link(bp) == 0)
break;
- udelay(10);
+ msleep(100);
}
mac_mode = REG_RD(bp, BNX2_EMAC_MODE);
mac_mode &= ~(BNX2_EMAC_MODE_PORT | BNX2_EMAC_MODE_HALF_DUPLEX |
BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK |
- BNX2_EMAC_MODE_25G);
+ BNX2_EMAC_MODE_25G_MODE);
mac_mode |= BNX2_EMAC_MODE_PORT_GMII;
REG_WR(bp, BNX2_EMAC_MODE, mac_mode);
@@ -1454,6 +1498,40 @@ bnx2_fw_sync(struct bnx2 *bp, u32 msg_data, int silent)
return 0;
}
+static int
+bnx2_init_5709_context(struct bnx2 *bp)
+{
+ int i, ret = 0;
+ u32 val;
+
+ val = BNX2_CTX_COMMAND_ENABLED | BNX2_CTX_COMMAND_MEM_INIT | (1 << 12);
+ val |= (BCM_PAGE_BITS - 8) << 16;
+ REG_WR(bp, BNX2_CTX_COMMAND, val);
+ for (i = 0; i < bp->ctx_pages; i++) {
+ int j;
+
+ REG_WR(bp, BNX2_CTX_HOST_PAGE_TBL_DATA0,
+ (bp->ctx_blk_mapping[i] & 0xffffffff) |
+ BNX2_CTX_HOST_PAGE_TBL_DATA0_VALID);
+ REG_WR(bp, BNX2_CTX_HOST_PAGE_TBL_DATA1,
+ (u64) bp->ctx_blk_mapping[i] >> 32);
+ REG_WR(bp, BNX2_CTX_HOST_PAGE_TBL_CTRL, i |
+ BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ);
+ for (j = 0; j < 10; j++) {
+
+ val = REG_RD(bp, BNX2_CTX_HOST_PAGE_TBL_CTRL);
+ if (!(val & BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ))
+ break;
+ udelay(5);
+ }
+ if (val & BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ) {
+ ret = -EBUSY;
+ break;
+ }
+ }
+ return ret;
+}
+
static void
bnx2_init_context(struct bnx2 *bp)
{
@@ -1576,9 +1654,8 @@ bnx2_alloc_rx_skb(struct bnx2 *bp, u16 index)
return -ENOMEM;
}
- if (unlikely((align = (unsigned long) skb->data & 0x7))) {
- skb_reserve(skb, 8 - align);
- }
+ if (unlikely((align = (unsigned long) skb->data & (BNX2_RX_ALIGN - 1))))
+ skb_reserve(skb, BNX2_RX_ALIGN - align);
mapping = pci_map_single(bp->pdev, skb->data, bp->rx_buf_use_size,
PCI_DMA_FROMDEVICE);
@@ -2040,7 +2117,8 @@ bnx2_set_rx_mode(struct net_device *dev)
if (dev->flags & IFF_PROMISC) {
/* Promiscuous mode. */
rx_mode |= BNX2_EMAC_RX_MODE_PROMISCUOUS;
- sort_mode |= BNX2_RPM_SORT_USER0_PROM_EN;
+ sort_mode |= BNX2_RPM_SORT_USER0_PROM_EN |
+ BNX2_RPM_SORT_USER0_PROM_VLAN;
}
else if (dev->flags & IFF_ALLMULTI) {
for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) {
@@ -2208,11 +2286,12 @@ load_rv2p_fw(struct bnx2 *bp, u32 *rv2p_code, u32 rv2p_code_len,
}
}
-static void
+static int
load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, struct fw_info *fw)
{
u32 offset;
u32 val;
+ int rc;
/* Halt the CPU. */
val = REG_RD_IND(bp, cpu_reg->mode);
@@ -2222,7 +2301,18 @@ load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, struct fw_info *fw)
/* Load the Text area. */
offset = cpu_reg->spad_base + (fw->text_addr - cpu_reg->mips_view_base);
- if (fw->text) {
+ if (fw->gz_text) {
+ u32 text_len;
+ void *text;
+
+ rc = bnx2_gunzip(bp, fw->gz_text, fw->gz_text_len, &text,
+ &text_len);
+ if (rc)
+ return rc;
+
+ fw->text = text;
+ }
+ if (fw->gz_text) {
int j;
for (j = 0; j < (fw->text_len / 4); j++, offset += 4) {
@@ -2280,13 +2370,15 @@ load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, struct fw_info *fw)
val &= ~cpu_reg->mode_value_halt;
REG_WR_IND(bp, cpu_reg->state, cpu_reg->state_value_clear);
REG_WR_IND(bp, cpu_reg->mode, val);
+
+ return 0;
}
static int
bnx2_init_cpus(struct bnx2 *bp)
{
struct cpu_reg cpu_reg;
- struct fw_info fw;
+ struct fw_info *fw;
int rc = 0;
void *text;
u32 text_len;
@@ -2323,44 +2415,15 @@ bnx2_init_cpus(struct bnx2 *bp)
cpu_reg.spad_base = BNX2_RXP_SCRATCH;
cpu_reg.mips_view_base = 0x8000000;
- fw.ver_major = bnx2_RXP_b06FwReleaseMajor;
- fw.ver_minor = bnx2_RXP_b06FwReleaseMinor;
- fw.ver_fix = bnx2_RXP_b06FwReleaseFix;
- fw.start_addr = bnx2_RXP_b06FwStartAddr;
-
- fw.text_addr = bnx2_RXP_b06FwTextAddr;
- fw.text_len = bnx2_RXP_b06FwTextLen;
- fw.text_index = 0;
+ if (CHIP_NUM(bp) == CHIP_NUM_5709)
+ fw = &bnx2_rxp_fw_09;
+ else
+ fw = &bnx2_rxp_fw_06;
- rc = bnx2_gunzip(bp, bnx2_RXP_b06FwText, sizeof(bnx2_RXP_b06FwText),
- &text, &text_len);
+ rc = load_cpu_fw(bp, &cpu_reg, fw);
if (rc)
goto init_cpu_err;
- fw.text = text;
-
- fw.data_addr = bnx2_RXP_b06FwDataAddr;
- fw.data_len = bnx2_RXP_b06FwDataLen;
- fw.data_index = 0;
- fw.data = bnx2_RXP_b06FwData;
-
- fw.sbss_addr = bnx2_RXP_b06FwSbssAddr;
- fw.sbss_len = bnx2_RXP_b06FwSbssLen;
- fw.sbss_index = 0;
- fw.sbss = bnx2_RXP_b06FwSbss;
-
- fw.bss_addr = bnx2_RXP_b06FwBssAddr;
- fw.bss_len = bnx2_RXP_b06FwBssLen;
- fw.bss_index = 0;
- fw.bss = bnx2_RXP_b06FwBss;
-
- fw.rodata_addr = bnx2_RXP_b06FwRodataAddr;
- fw.rodata_len = bnx2_RXP_b06FwRodataLen;
- fw.rodata_index = 0;
- fw.rodata = bnx2_RXP_b06FwRodata;
-
- load_cpu_fw(bp, &cpu_reg, &fw);
-
/* Initialize the TX Processor. */
cpu_reg.mode = BNX2_TXP_CPU_MODE;
cpu_reg.mode_value_halt = BNX2_TXP_CPU_MODE_SOFT_HALT;
@@ -2375,44 +2438,15 @@ bnx2_init_cpus(struct bnx2 *bp)
cpu_reg.spad_base = BNX2_TXP_SCRATCH;
cpu_reg.mips_view_base = 0x8000000;
- fw.ver_major = bnx2_TXP_b06FwReleaseMajor;
- fw.ver_minor = bnx2_TXP_b06FwReleaseMinor;
- fw.ver_fix = bnx2_TXP_b06FwReleaseFix;
- fw.start_addr = bnx2_TXP_b06FwStartAddr;
-
- fw.text_addr = bnx2_TXP_b06FwTextAddr;
- fw.text_len = bnx2_TXP_b06FwTextLen;
- fw.text_index = 0;
+ if (CHIP_NUM(bp) == CHIP_NUM_5709)
+ fw = &bnx2_txp_fw_09;
+ else
+ fw = &bnx2_txp_fw_06;
- rc = bnx2_gunzip(bp, bnx2_TXP_b06FwText, sizeof(bnx2_TXP_b06FwText),
- &text, &text_len);
+ rc = load_cpu_fw(bp, &cpu_reg, fw);
if (rc)
goto init_cpu_err;
- fw.text = text;
-
- fw.data_addr = bnx2_TXP_b06FwDataAddr;
- fw.data_len = bnx2_TXP_b06FwDataLen;
- fw.data_index = 0;
- fw.data = bnx2_TXP_b06FwData;
-
- fw.sbss_addr = bnx2_TXP_b06FwSbssAddr;
- fw.sbss_len = bnx2_TXP_b06FwSbssLen;
- fw.sbss_index = 0;
- fw.sbss = bnx2_TXP_b06FwSbss;
-
- fw.bss_addr = bnx2_TXP_b06FwBssAddr;
- fw.bss_len = bnx2_TXP_b06FwBssLen;
- fw.bss_index = 0;
- fw.bss = bnx2_TXP_b06FwBss;
-
- fw.rodata_addr = bnx2_TXP_b06FwRodataAddr;
- fw.rodata_len = bnx2_TXP_b06FwRodataLen;
- fw.rodata_index = 0;
- fw.rodata = bnx2_TXP_b06FwRodata;
-
- load_cpu_fw(bp, &cpu_reg, &fw);
-
/* Initialize the TX Patch-up Processor. */
cpu_reg.mode = BNX2_TPAT_CPU_MODE;
cpu_reg.mode_value_halt = BNX2_TPAT_CPU_MODE_SOFT_HALT;
@@ -2427,44 +2461,15 @@ bnx2_init_cpus(struct bnx2 *bp)
cpu_reg.spad_base = BNX2_TPAT_SCRATCH;
cpu_reg.mips_view_base = 0x8000000;
- fw.ver_major = bnx2_TPAT_b06FwReleaseMajor;
- fw.ver_minor = bnx2_TPAT_b06FwReleaseMinor;
- fw.ver_fix = bnx2_TPAT_b06FwReleaseFix;
- fw.start_addr = bnx2_TPAT_b06FwStartAddr;
-
- fw.text_addr = bnx2_TPAT_b06FwTextAddr;
- fw.text_len = bnx2_TPAT_b06FwTextLen;
- fw.text_index = 0;
+ if (CHIP_NUM(bp) == CHIP_NUM_5709)
+ fw = &bnx2_tpat_fw_09;
+ else
+ fw = &bnx2_tpat_fw_06;
- rc = bnx2_gunzip(bp, bnx2_TPAT_b06FwText, sizeof(bnx2_TPAT_b06FwText),
- &text, &text_len);
+ rc = load_cpu_fw(bp, &cpu_reg, fw);
if (rc)
goto init_cpu_err;
- fw.text = text;
-
- fw.data_addr = bnx2_TPAT_b06FwDataAddr;
- fw.data_len = bnx2_TPAT_b06FwDataLen;
- fw.data_index = 0;
- fw.data = bnx2_TPAT_b06FwData;
-
- fw.sbss_addr = bnx2_TPAT_b06FwSbssAddr;
- fw.sbss_len = bnx2_TPAT_b06FwSbssLen;
- fw.sbss_index = 0;
- fw.sbss = bnx2_TPAT_b06FwSbss;
-
- fw.bss_addr = bnx2_TPAT_b06FwBssAddr;
- fw.bss_len = bnx2_TPAT_b06FwBssLen;
- fw.bss_index = 0;
- fw.bss = bnx2_TPAT_b06FwBss;
-
- fw.rodata_addr = bnx2_TPAT_b06FwRodataAddr;
- fw.rodata_len = bnx2_TPAT_b06FwRodataLen;
- fw.rodata_index = 0;
- fw.rodata = bnx2_TPAT_b06FwRodata;
-
- load_cpu_fw(bp, &cpu_reg, &fw);
-
/* Initialize the Completion Processor. */
cpu_reg.mode = BNX2_COM_CPU_MODE;
cpu_reg.mode_value_halt = BNX2_COM_CPU_MODE_SOFT_HALT;
@@ -2479,44 +2484,36 @@ bnx2_init_cpus(struct bnx2 *bp)
cpu_reg.spad_base = BNX2_COM_SCRATCH;
cpu_reg.mips_view_base = 0x8000000;
- fw.ver_major = bnx2_COM_b06FwReleaseMajor;
- fw.ver_minor = bnx2_COM_b06FwReleaseMinor;
- fw.ver_fix = bnx2_COM_b06FwReleaseFix;
- fw.start_addr = bnx2_COM_b06FwStartAddr;
-
- fw.text_addr = bnx2_COM_b06FwTextAddr;
- fw.text_len = bnx2_COM_b06FwTextLen;
- fw.text_index = 0;
+ if (CHIP_NUM(bp) == CHIP_NUM_5709)
+ fw = &bnx2_com_fw_09;
+ else
+ fw = &bnx2_com_fw_06;
- rc = bnx2_gunzip(bp, bnx2_COM_b06FwText, sizeof(bnx2_COM_b06FwText),
- &text, &text_len);
+ rc = load_cpu_fw(bp, &cpu_reg, fw);
if (rc)
goto init_cpu_err;
- fw.text = text;
-
- fw.data_addr = bnx2_COM_b06FwDataAddr;
- fw.data_len = bnx2_COM_b06FwDataLen;
- fw.data_index = 0;
- fw.data = bnx2_COM_b06FwData;
-
- fw.sbss_addr = bnx2_COM_b06FwSbssAddr;
- fw.sbss_len = bnx2_COM_b06FwSbssLen;
- fw.sbss_index = 0;
- fw.sbss = bnx2_COM_b06FwSbss;
-
- fw.bss_addr = bnx2_COM_b06FwBssAddr;
- fw.bss_len = bnx2_COM_b06FwBssLen;
- fw.bss_index = 0;
- fw.bss = bnx2_COM_b06FwBss;
-
- fw.rodata_addr = bnx2_COM_b06FwRodataAddr;
- fw.rodata_len = bnx2_COM_b06FwRodataLen;
- fw.rodata_index = 0;
- fw.rodata = bnx2_COM_b06FwRodata;
+ /* Initialize the Command Processor. */
+ cpu_reg.mode = BNX2_CP_CPU_MODE;
+ cpu_reg.mode_value_halt = BNX2_CP_CPU_MODE_SOFT_HALT;
+ cpu_reg.mode_value_sstep = BNX2_CP_CPU_MODE_STEP_ENA;
+ cpu_reg.state = BNX2_CP_CPU_STATE;
+ cpu_reg.state_value_clear = 0xffffff;
+ cpu_reg.gpr0 = BNX2_CP_CPU_REG_FILE;
+ cpu_reg.evmask = BNX2_CP_CPU_EVENT_MASK;
+ cpu_reg.pc = BNX2_CP_CPU_PROGRAM_COUNTER;
+ cpu_reg.inst = BNX2_CP_CPU_INSTRUCTION;
+ cpu_reg.bp = BNX2_CP_CPU_HW_BREAKPOINT;
+ cpu_reg.spad_base = BNX2_CP_SCRATCH;
+ cpu_reg.mips_view_base = 0x8000000;
- load_cpu_fw(bp, &cpu_reg, &fw);
+ if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+ fw = &bnx2_cp_fw_09;
+ load_cpu_fw(bp, &cpu_reg, fw);
+ if (rc)
+ goto init_cpu_err;
+ }
init_cpu_err:
bnx2_gunzip_end(bp);
return rc;
@@ -3288,31 +3285,44 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code)
* before we issue a reset. */
val = REG_RD(bp, BNX2_MISC_ID);
- val = BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ |
- BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
- BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP;
+ if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+ REG_WR(bp, BNX2_MISC_COMMAND, BNX2_MISC_COMMAND_SW_RESET);
+ REG_RD(bp, BNX2_MISC_COMMAND);
+ udelay(5);
- /* Chip reset. */
- REG_WR(bp, BNX2_PCICFG_MISC_CONFIG, val);
+ val = BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
+ BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP;
- if ((CHIP_ID(bp) == CHIP_ID_5706_A0) ||
- (CHIP_ID(bp) == CHIP_ID_5706_A1))
- msleep(15);
+ pci_write_config_dword(bp->pdev, BNX2_PCICFG_MISC_CONFIG, val);
- /* Reset takes approximate 30 usec */
- for (i = 0; i < 10; i++) {
- val = REG_RD(bp, BNX2_PCICFG_MISC_CONFIG);
- if ((val & (BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ |
- BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY)) == 0) {
- break;
+ } else {
+ val = BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ |
+ BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
+ BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP;
+
+ /* Chip reset. */
+ REG_WR(bp, BNX2_PCICFG_MISC_CONFIG, val);
+
+ if ((CHIP_ID(bp) == CHIP_ID_5706_A0) ||
+ (CHIP_ID(bp) == CHIP_ID_5706_A1)) {
+ current->state = TASK_UNINTERRUPTIBLE;
+ schedule_timeout(HZ / 50);
}
- udelay(10);
- }
- if (val & (BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ |
- BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY)) {
- printk(KERN_ERR PFX "Chip reset did not complete\n");
- return -EBUSY;
+ /* Reset takes approximate 30 usec */
+ for (i = 0; i < 10; i++) {
+ val = REG_RD(bp, BNX2_PCICFG_MISC_CONFIG);
+ if ((val & (BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ |
+ BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY)) == 0)
+ break;
+ udelay(10);
+ }
+
+ if (val & (BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ |
+ BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY)) {
+ printk(KERN_ERR PFX "Chip reset did not complete\n");
+ return -EBUSY;
+ }
}
/* Make sure byte swapping is properly configured. */
@@ -3390,7 +3400,10 @@ bnx2_init_chip(struct bnx2 *bp)
/* Initialize context mapping and zero out the quick contexts. The
* context block must have already been enabled. */
- bnx2_init_context(bp);
+ if (CHIP_NUM(bp) == CHIP_NUM_5709)
+ bnx2_init_5709_context(bp);
+ else
+ bnx2_init_context(bp);
if ((rc = bnx2_init_cpus(bp)) != 0)
return rc;
@@ -3501,12 +3514,40 @@ bnx2_init_chip(struct bnx2 *bp)
return rc;
}
+static void
+bnx2_init_tx_context(struct bnx2 *bp, u32 cid)
+{
+ u32 val, offset0, offset1, offset2, offset3;
+
+ if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+ offset0 = BNX2_L2CTX_TYPE_XI;
+ offset1 = BNX2_L2CTX_CMD_TYPE_XI;
+ offset2 = BNX2_L2CTX_TBDR_BHADDR_HI_XI;
+ offset3 = BNX2_L2CTX_TBDR_BHADDR_LO_XI;
+ } else {
+ offset0 = BNX2_L2CTX_TYPE;
+ offset1 = BNX2_L2CTX_CMD_TYPE;
+ offset2 = BNX2_L2CTX_TBDR_BHADDR_HI;
+ offset3 = BNX2_L2CTX_TBDR_BHADDR_LO;
+ }
+ val = BNX2_L2CTX_TYPE_TYPE_L2 | BNX2_L2CTX_TYPE_SIZE_L2;
+ CTX_WR(bp, GET_CID_ADDR(cid), offset0, val);
+
+ val = BNX2_L2CTX_CMD_TYPE_TYPE_L2 | (8 << 16);
+ CTX_WR(bp, GET_CID_ADDR(cid), offset1, val);
+
+ val = (u64) bp->tx_desc_mapping >> 32;
+ CTX_WR(bp, GET_CID_ADDR(cid), offset2, val);
+
+ val = (u64) bp->tx_desc_mapping & 0xffffffff;
+ CTX_WR(bp, GET_CID_ADDR(cid), offset3, val);
+}
static void
bnx2_init_tx_ring(struct bnx2 *bp)
{
struct tx_bd *txbd;
- u32 val;
+ u32 cid;
bp->tx_wake_thresh = bp->tx_ring_size / 2;
@@ -3520,19 +3561,11 @@ bnx2_init_tx_ring(struct bnx2 *bp)
bp->hw_tx_cons = 0;
bp->tx_prod_bseq = 0;
- val = BNX2_L2CTX_TYPE_TYPE_L2;
- val |= BNX2_L2CTX_TYPE_SIZE_L2;
- CTX_WR(bp, GET_CID_ADDR(TX_CID), BNX2_L2CTX_TYPE, val);
+ cid = TX_CID;
+ bp->tx_bidx_addr = MB_GET_CID_ADDR(cid) + BNX2_L2CTX_TX_HOST_BIDX;
+ bp->tx_bseq_addr = MB_GET_CID_ADDR(cid) + BNX2_L2CTX_TX_HOST_BSEQ;
- val = BNX2_L2CTX_CMD_TYPE_TYPE_L2;
- val |= 8 << 16;
- CTX_WR(bp, GET_CID_ADDR(TX_CID), BNX2_L2CTX_CMD_TYPE, val);
-
- val = (u64) bp->tx_desc_mapping >> 32;
- CTX_WR(bp, GET_CID_ADDR(TX_CID), BNX2_L2CTX_TBDR_BHADDR_HI, val);
-
- val = (u64) bp->tx_desc_mapping & 0xffffffff;
- CTX_WR(bp, GET_CID_ADDR(TX_CID), BNX2_L2CTX_TBDR_BHADDR_LO, val);
+ bnx2_init_tx_context(bp, cid);
}
static void
@@ -3545,8 +3578,8 @@ bnx2_init_rx_ring(struct bnx2 *bp)
/* 8 for CRC and VLAN */
bp->rx_buf_use_size = bp->dev->mtu + ETH_HLEN + bp->rx_offset + 8;
- /* 8 for alignment */
- bp->rx_buf_size = bp->rx_buf_use_size + 8;
+ /* hw alignment */
+ bp->rx_buf_size = bp->rx_buf_use_size + BNX2_RX_ALIGN;
ring_prod = prod = bp->rx_prod = 0;
bp->rx_cons = 0;
@@ -3712,7 +3745,9 @@ bnx2_init_nic(struct bnx2 *bp)
if ((rc = bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_RESET)) != 0)
return rc;
+ spin_lock_bh(&bp->phy_lock);
bnx2_init_phy(bp);
+ spin_unlock_bh(&bp->phy_lock);
bnx2_set_link(bp);
return 0;
}
@@ -3952,7 +3987,7 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
bnx2_set_mac_loopback(bp);
}
else if (loopback_mode == BNX2_PHY_LOOPBACK) {
- bp->loopback = 0;
+ bp->loopback = PHY_LOOPBACK;
bnx2_set_phy_loopback(bp);
}
else
@@ -3992,8 +4027,8 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
bp->tx_prod = NEXT_TX_BD(bp->tx_prod);
bp->tx_prod_bseq += pkt_size;
- REG_WR16(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BIDX, bp->tx_prod);
- REG_WR(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BSEQ, bp->tx_prod_bseq);
+ REG_WR16(bp, bp->tx_bidx_addr, bp->tx_prod);
+ REG_WR(bp, bp->tx_bseq_addr, bp->tx_prod_bseq);
udelay(100);
@@ -4162,80 +4197,117 @@ bnx2_test_intr(struct bnx2 *bp)
}
static void
-bnx2_timer(unsigned long data)
+bnx2_5706_serdes_timer(struct bnx2 *bp)
{
- struct bnx2 *bp = (struct bnx2 *) data;
- u32 msg;
+ spin_lock(&bp->phy_lock);
+ if (bp->serdes_an_pending)
+ bp->serdes_an_pending--;
+ else if ((bp->link_up == 0) && (bp->autoneg & AUTONEG_SPEED)) {
+ u32 bmcr;
- if (!netif_running(bp->dev))
- return;
+ bp->current_interval = bp->timer_interval;
- if (atomic_read(&bp->intr_sem) != 0)
- goto bnx2_restart_timer;
+ bnx2_read_phy(bp, MII_BMCR, &bmcr);
- msg = (u32) ++bp->fw_drv_pulse_wr_seq;
- REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_PULSE_MB, msg);
+ if (bmcr & BMCR_ANENABLE) {
+ u32 phy1, phy2;
- bp->stats_blk->stat_FwRxDrop = REG_RD_IND(bp, BNX2_FW_RX_DROP_COUNT);
+ bnx2_write_phy(bp, 0x1c, 0x7c00);
+ bnx2_read_phy(bp, 0x1c, &phy1);
- if ((bp->phy_flags & PHY_SERDES_FLAG) &&
- (CHIP_NUM(bp) == CHIP_NUM_5706)) {
+ bnx2_write_phy(bp, 0x17, 0x0f01);
+ bnx2_read_phy(bp, 0x15, &phy2);
+ bnx2_write_phy(bp, 0x17, 0x0f01);
+ bnx2_read_phy(bp, 0x15, &phy2);
- spin_lock(&bp->phy_lock);
- if (bp->serdes_an_pending) {
- bp->serdes_an_pending--;
+ if ((phy1 & 0x10) && /* SIGNAL DETECT */
+ !(phy2 & 0x20)) { /* no CONFIG */
+
+ bmcr &= ~BMCR_ANENABLE;
+ bmcr |= BMCR_SPEED1000 | BMCR_FULLDPLX;
+ bnx2_write_phy(bp, MII_BMCR, bmcr);
+ bp->phy_flags |= PHY_PARALLEL_DETECT_FLAG;
+ }
}
- else if ((bp->link_up == 0) && (bp->autoneg & AUTONEG_SPEED)) {
- u32 bmcr;
+ }
+ else if ((bp->link_up) && (bp->autoneg & AUTONEG_SPEED) &&
+ (bp->phy_flags & PHY_PARALLEL_DETECT_FLAG)) {
+ u32 phy2;
- bp->current_interval = bp->timer_interval;
+ bnx2_write_phy(bp, 0x17, 0x0f01);
+ bnx2_read_phy(bp, 0x15, &phy2);
+ if (phy2 & 0x20) {
+ u32 bmcr;
bnx2_read_phy(bp, MII_BMCR, &bmcr);
+ bmcr |= BMCR_ANENABLE;
+ bnx2_write_phy(bp, MII_BMCR, bmcr);
- if (bmcr & BMCR_ANENABLE) {
- u32 phy1, phy2;
+ bp->phy_flags &= ~PHY_PARALLEL_DETECT_FLAG;
+ }
+ } else
+ bp->current_interval = bp->timer_interval;
- bnx2_write_phy(bp, 0x1c, 0x7c00);
- bnx2_read_phy(bp, 0x1c, &phy1);
+ spin_unlock(&bp->phy_lock);
+}
- bnx2_write_phy(bp, 0x17, 0x0f01);
- bnx2_read_phy(bp, 0x15, &phy2);
- bnx2_write_phy(bp, 0x17, 0x0f01);
- bnx2_read_phy(bp, 0x15, &phy2);
+static void
+bnx2_5708_serdes_timer(struct bnx2 *bp)
+{
+ if ((bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) == 0) {
+ bp->serdes_an_pending = 0;
+ return;
+ }
- if ((phy1 & 0x10) && /* SIGNAL DETECT */
- !(phy2 & 0x20)) { /* no CONFIG */
+ spin_lock(&bp->phy_lock);
+ if (bp->serdes_an_pending)
+ bp->serdes_an_pending--;
+ else if ((bp->link_up == 0) && (bp->autoneg & AUTONEG_SPEED)) {
+ u32 bmcr;
- bmcr &= ~BMCR_ANENABLE;
- bmcr |= BMCR_SPEED1000 |
- BMCR_FULLDPLX;
- bnx2_write_phy(bp, MII_BMCR, bmcr);
- bp->phy_flags |=
- PHY_PARALLEL_DETECT_FLAG;
- }
- }
+ bnx2_read_phy(bp, MII_BMCR, &bmcr);
+
+ if (bmcr & BMCR_ANENABLE) {
+ bmcr &= ~BMCR_ANENABLE;
+ bmcr |= BMCR_FULLDPLX | BCM5708S_BMCR_FORCE_2500;
+ bnx2_write_phy(bp, MII_BMCR, bmcr);
+ bp->current_interval = SERDES_FORCED_TIMEOUT;
+ } else {
+ bmcr &= ~(BMCR_FULLDPLX | BCM5708S_BMCR_FORCE_2500);
+ bmcr |= BMCR_ANENABLE;
+ bnx2_write_phy(bp, MII_BMCR, bmcr);
+ bp->serdes_an_pending = 2;
+ bp->current_interval = bp->timer_interval;
}
- else if ((bp->link_up) && (bp->autoneg & AUTONEG_SPEED) &&
- (bp->phy_flags & PHY_PARALLEL_DETECT_FLAG)) {
- u32 phy2;
- bnx2_write_phy(bp, 0x17, 0x0f01);
- bnx2_read_phy(bp, 0x15, &phy2);
- if (phy2 & 0x20) {
- u32 bmcr;
+ } else
+ bp->current_interval = bp->timer_interval;
- bnx2_read_phy(bp, MII_BMCR, &bmcr);
- bmcr |= BMCR_ANENABLE;
- bnx2_write_phy(bp, MII_BMCR, bmcr);
+ spin_unlock(&bp->phy_lock);
+}
+
+static void
+bnx2_timer(unsigned long data)
+{
+ struct bnx2 *bp = (struct bnx2 *) data;
+ u32 msg;
- bp->phy_flags &= ~PHY_PARALLEL_DETECT_FLAG;
+ if (!netif_running(bp->dev))
+ return;
- }
- }
- else
- bp->current_interval = bp->timer_interval;
+ if (atomic_read(&bp->intr_sem) != 0)
+ goto bnx2_restart_timer;
- spin_unlock(&bp->phy_lock);
+ msg = (u32) ++bp->fw_drv_pulse_wr_seq;
+ REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_PULSE_MB, msg);
+
+ bp->stats_blk->stat_FwRxDrop = REG_RD_IND(bp, BNX2_FW_RX_DROP_COUNT);
+
+ if (bp->phy_flags & PHY_SERDES_FLAG) {
+ if (CHIP_NUM(bp) == CHIP_NUM_5706)
+ bnx2_5706_serdes_timer(bp);
+ else if (CHIP_NUM(bp) == CHIP_NUM_5708)
+ bnx2_5708_serdes_timer(bp);
}
bnx2_restart_timer:
@@ -4508,8 +4580,8 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
prod = NEXT_TX_BD(prod);
bp->tx_prod_bseq += skb->len;
- REG_WR16(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BIDX, prod);
- REG_WR(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BSEQ, bp->tx_prod_bseq);
+ REG_WR16(bp, bp->tx_bidx_addr, prod);
+ REG_WR(bp, bp->tx_bseq_addr, bp->tx_prod_bseq);
mmiowb();
@@ -4743,10 +4815,14 @@ bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
}
else {
if (bp->phy_flags & PHY_SERDES_FLAG) {
- if ((cmd->speed != SPEED_1000) ||
- (cmd->duplex != DUPLEX_FULL)) {
+ if ((cmd->speed != SPEED_1000 &&
+ cmd->speed != SPEED_2500) ||
+ (cmd->duplex != DUPLEX_FULL))
+ return -EINVAL;
+
+ if (cmd->speed == SPEED_2500 &&
+ !(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG))
return -EINVAL;
- }
}
else if (cmd->speed == SPEED_1000) {
return -EINVAL;
@@ -4903,11 +4979,10 @@ bnx2_nway_reset(struct net_device *dev)
msleep(20);
spin_lock_bh(&bp->phy_lock);
- if (CHIP_NUM(bp) == CHIP_NUM_5706) {
- bp->current_interval = SERDES_AN_TIMEOUT;
- bp->serdes_an_pending = 1;
- mod_timer(&bp->timer, jiffies + bp->current_interval);
- }
+
+ bp->current_interval = SERDES_AN_TIMEOUT;
+ bp->serdes_an_pending = 1;
+ mod_timer(&bp->timer, jiffies + bp->current_interval);
}
bnx2_read_phy(bp, MII_BMCR, &bmcr);
@@ -5288,6 +5363,8 @@ bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf)
memset(buf, 0, sizeof(u64) * BNX2_NUM_TESTS);
if (etest->flags & ETH_TEST_FL_OFFLINE) {
+ int i;
+
bnx2_netif_stop(bp);
bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_DIAG);
bnx2_free_skbs(bp);
@@ -5312,9 +5389,11 @@ bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf)
}
/* wait for link up */
- msleep_interruptible(3000);
- if ((!bp->link_up) && !(bp->phy_flags & PHY_SERDES_FLAG))
- msleep_interruptible(4000);
+ for (i = 0; i < 7; i++) {
+ if (bp->link_up)
+ break;
+ msleep_interruptible(1000);
+ }
}
if (bnx2_test_nvram(bp) != 0) {
@@ -5604,13 +5683,6 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
goto err_out_release;
}
- bp->pcix_cap = pci_find_capability(pdev, PCI_CAP_ID_PCIX);
- if (bp->pcix_cap == 0) {
- dev_err(&pdev->dev, "Cannot find PCIX capability, aborting.\n");
- rc = -EIO;
- goto err_out_release;
- }
-
if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) {
bp->flags |= USING_DAC_FLAG;
if (pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK) != 0) {
@@ -5633,7 +5705,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
INIT_WORK(&bp->reset_task, bnx2_reset_task);
dev->base_addr = dev->mem_start = pci_resource_start(pdev, 0);
- mem_len = MB_GET_CID_ADDR(17);
+ mem_len = MB_GET_CID_ADDR(TX_TSS_CID + 1);
dev->mem_end = dev->mem_start + mem_len;
dev->irq = pdev->irq;
@@ -5657,6 +5729,16 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
bp->chip_id = REG_RD(bp, BNX2_MISC_ID);
+ if (CHIP_NUM(bp) != CHIP_NUM_5709) {
+ bp->pcix_cap = pci_find_capability(pdev, PCI_CAP_ID_PCIX);
+ if (bp->pcix_cap == 0) {
+ dev_err(&pdev->dev,
+ "Cannot find PCIX capability, aborting.\n");
+ rc = -EIO;
+ goto err_out_unmap;
+ }
+ }
+
/* Get bus information. */
reg = REG_RD(bp, BNX2_PCICFG_MISC_STATUS);
if (reg & BNX2_PCICFG_MISC_STATUS_PCIX_DET) {
@@ -5776,10 +5858,15 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
bp->phy_addr = 1;
/* Disable WOL support if we are running on a SERDES chip. */
- if (CHIP_BOND_ID(bp) & CHIP_BOND_ID_SERDES_BIT) {
+ if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+ if (CHIP_BOND_ID(bp) != BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID_C)
+ bp->phy_flags |= PHY_SERDES_FLAG;
+ } else if (CHIP_BOND_ID(bp) & CHIP_BOND_ID_SERDES_BIT)
bp->phy_flags |= PHY_SERDES_FLAG;
+
+ if (bp->phy_flags & PHY_SERDES_FLAG) {
bp->flags |= NO_WOL_FLAG;
- if (CHIP_NUM(bp) == CHIP_NUM_5708) {
+ if (CHIP_NUM(bp) != CHIP_NUM_5706) {
bp->phy_addr = 2;
reg = REG_RD_IND(bp, bp->shmem_base +
BNX2_SHARED_HW_CFG_CONFIG);
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index ca31904893ea..13b6f9b11e01 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -56,6 +56,7 @@ struct rx_bd {
};
+#define BNX2_RX_ALIGN 16
/*
* status_block definition
@@ -90,6 +91,7 @@ struct status_block {
#define STATUS_ATTN_BITS_DMAE_ABORT (1L<<25)
#define STATUS_ATTN_BITS_FLSH_ABORT (1L<<26)
#define STATUS_ATTN_BITS_GRC_ABORT (1L<<27)
+ #define STATUS_ATTN_BITS_EPB_ERROR (1L<<30)
#define STATUS_ATTN_BITS_PARITY_ERROR (1L<<31)
u32 status_attn_bits_ack;
@@ -117,7 +119,8 @@ struct status_block {
u16 status_completion_producer_index;
u16 status_cmd_consumer_index;
u16 status_idx;
- u16 status_unused;
+ u8 status_unused;
+ u8 status_blk_num;
#elif defined(__LITTLE_ENDIAN)
u16 status_tx_quick_consumer_index1;
u16 status_tx_quick_consumer_index0;
@@ -141,7 +144,8 @@ struct status_block {
u16 status_rx_quick_consumer_index14;
u16 status_cmd_consumer_index;
u16 status_completion_producer_index;
- u16 status_unused;
+ u8 status_blk_num;
+ u8 status_unused;
u16 status_idx;
#endif
};
@@ -301,6 +305,10 @@ struct l2_fhdr {
#define BNX2_L2CTX_TXP_BIDX 0x000000a8
#define BNX2_L2CTX_TXP_BSEQ 0x000000ac
+#define BNX2_L2CTX_TYPE_XI 0x00000080
+#define BNX2_L2CTX_CMD_TYPE_XI 0x00000240
+#define BNX2_L2CTX_TBDR_BHADDR_HI_XI 0x00000258
+#define BNX2_L2CTX_TBDR_BHADDR_LO_XI 0x0000025c
/*
* l2_bd_chain_context definition
@@ -328,11 +336,15 @@ struct l2_fhdr {
#define BNX2_PCICFG_MISC_CONFIG 0x00000068
#define BNX2_PCICFG_MISC_CONFIG_TARGET_BYTE_SWAP (1L<<2)
#define BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP (1L<<3)
+#define BNX2_PCICFG_MISC_CONFIG_RESERVED1 (1L<<4)
#define BNX2_PCICFG_MISC_CONFIG_CLOCK_CTL_ENA (1L<<5)
#define BNX2_PCICFG_MISC_CONFIG_TARGET_GRC_WORD_SWAP (1L<<6)
#define BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA (1L<<7)
#define BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ (1L<<8)
#define BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY (1L<<9)
+#define BNX2_PCICFG_MISC_CONFIG_GRC_WIN1_SWAP_EN (1L<<10)
+#define BNX2_PCICFG_MISC_CONFIG_GRC_WIN2_SWAP_EN (1L<<11)
+#define BNX2_PCICFG_MISC_CONFIG_GRC_WIN3_SWAP_EN (1L<<12)
#define BNX2_PCICFG_MISC_CONFIG_ASIC_METAL_REV (0xffL<<16)
#define BNX2_PCICFG_MISC_CONFIG_ASIC_BASE_REV (0xfL<<24)
#define BNX2_PCICFG_MISC_CONFIG_ASIC_ID (0xfL<<28)
@@ -347,6 +359,7 @@ struct l2_fhdr {
#define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED_100 (1L<<4)
#define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED_133 (2L<<4)
#define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED_PCI_MODE (3L<<4)
+#define BNX2_PCICFG_MISC_STATUS_BAD_MEM_WRITE_BE (1L<<8)
#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS 0x00000070
#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET (0xfL<<0)
@@ -366,7 +379,7 @@ struct l2_fhdr {
#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_12 (1L<<8)
#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_6 (2L<<8)
#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_62 (4L<<8)
-#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PLAY_DEAD (1L<<11)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_MIN_POWER (1L<<11)
#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED (0xfL<<12)
#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_100 (0L<<12)
#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_80 (1L<<12)
@@ -374,18 +387,21 @@ struct l2_fhdr {
#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_40 (4L<<12)
#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_25 (8L<<12)
#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_STOP (1L<<16)
-#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_PLL_STOP (1L<<17)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_RESERVED_17 (1L<<17)
#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_RESERVED_18 (1L<<18)
-#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_USE_SPD_DET (1L<<19)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_RESERVED_19 (1L<<19)
#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_RESERVED (0xfffL<<20)
#define BNX2_PCICFG_REG_WINDOW_ADDRESS 0x00000078
+#define BNX2_PCICFG_REG_WINDOW_ADDRESS_VAL (0xfffffL<<2)
+
#define BNX2_PCICFG_REG_WINDOW 0x00000080
#define BNX2_PCICFG_INT_ACK_CMD 0x00000084
#define BNX2_PCICFG_INT_ACK_CMD_INDEX (0xffffL<<0)
#define BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID (1L<<16)
#define BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM (1L<<17)
#define BNX2_PCICFG_INT_ACK_CMD_MASK_INT (1L<<18)
+#define BNX2_PCICFG_INT_ACK_CMD_INTERRUPT_NUM (0xfL<<24)
#define BNX2_PCICFG_STATUS_BIT_SET_CMD 0x00000088
#define BNX2_PCICFG_STATUS_BIT_CLEAR_CMD 0x0000008c
@@ -398,9 +414,11 @@ struct l2_fhdr {
* offset: 0x400
*/
#define BNX2_PCI_GRC_WINDOW_ADDR 0x00000400
-#define BNX2_PCI_GRC_WINDOW_ADDR_PCI_GRC_WINDOW_ADDR_VALUE (0x3ffffL<<8)
+#define BNX2_PCI_GRC_WINDOW_ADDR_VALUE (0x1ffL<<13)
+#define BNX2_PCI_GRC_WINDOW_ADDR_SEP_WIN (1L<<31)
#define BNX2_PCI_CONFIG_1 0x00000404
+#define BNX2_PCI_CONFIG_1_RESERVED0 (0xffL<<0)
#define BNX2_PCI_CONFIG_1_READ_BOUNDARY (0x7L<<8)
#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_OFF (0L<<8)
#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_16 (1L<<8)
@@ -419,6 +437,7 @@ struct l2_fhdr {
#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_256 (5L<<11)
#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_512 (6L<<11)
#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_1024 (7L<<11)
+#define BNX2_PCI_CONFIG_1_RESERVED1 (0x3ffffL<<14)
#define BNX2_PCI_CONFIG_2 0x00000408
#define BNX2_PCI_CONFIG_2_BAR1_SIZE (0xfL<<0)
@@ -468,9 +487,13 @@ struct l2_fhdr {
#define BNX2_PCI_CONFIG_2_FORCE_32_BIT_MSTR (1L<<23)
#define BNX2_PCI_CONFIG_2_FORCE_32_BIT_TGT (1L<<24)
#define BNX2_PCI_CONFIG_2_KEEP_REQ_ASSERT (1L<<25)
+#define BNX2_PCI_CONFIG_2_RESERVED0 (0x3fL<<26)
+#define BNX2_PCI_CONFIG_2_BAR_PREFETCH_XI (1L<<16)
+#define BNX2_PCI_CONFIG_2_RESERVED0_XI (0x7fffL<<17)
#define BNX2_PCI_CONFIG_3 0x0000040c
#define BNX2_PCI_CONFIG_3_STICKY_BYTE (0xffL<<0)
+#define BNX2_PCI_CONFIG_3_REG_STICKY_BYTE (0xffL<<8)
#define BNX2_PCI_CONFIG_3_FORCE_PME (1L<<24)
#define BNX2_PCI_CONFIG_3_PME_STATUS (1L<<25)
#define BNX2_PCI_CONFIG_3_PME_ENABLE (1L<<26)
@@ -501,8 +524,10 @@ struct l2_fhdr {
#define BNX2_PCI_VPD_INTF_INTF_REQ (1L<<0)
#define BNX2_PCI_VPD_ADDR_FLAG 0x0000042c
-#define BNX2_PCI_VPD_ADDR_FLAG_ADDRESS (0x1fff<<2)
-#define BNX2_PCI_VPD_ADDR_FLAG_WR (1<<15)
+#define BNX2_PCI_VPD_ADDR_FLAG_MSK 0x0000ffff
+#define BNX2_PCI_VPD_ADDR_FLAG_SL 0L
+#define BNX2_PCI_VPD_ADDR_FLAG_ADDRESS (0x1fffL<<2)
+#define BNX2_PCI_VPD_ADDR_FLAG_WR (1L<<15)
#define BNX2_PCI_VPD_DATA 0x00000430
#define BNX2_PCI_ID_VAL1 0x00000434
@@ -535,19 +560,26 @@ struct l2_fhdr {
#define BNX2_PCI_ID_VAL4_CAP_ENA_13 (13L<<0)
#define BNX2_PCI_ID_VAL4_CAP_ENA_14 (14L<<0)
#define BNX2_PCI_ID_VAL4_CAP_ENA_15 (15L<<0)
+#define BNX2_PCI_ID_VAL4_RESERVED0 (0x3L<<4)
#define BNX2_PCI_ID_VAL4_PM_SCALE_PRG (0x3L<<6)
#define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_0 (0L<<6)
#define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_1 (1L<<6)
#define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_2 (2L<<6)
#define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_3 (3L<<6)
+#define BNX2_PCI_ID_VAL4_MSI_PV_MASK_CAP (1L<<8)
#define BNX2_PCI_ID_VAL4_MSI_LIMIT (0x7L<<9)
-#define BNX2_PCI_ID_VAL4_MSI_ADVERTIZE (0x7L<<12)
+#define BNX2_PCI_ID_VAL4_MULTI_MSG_CAP (0x7L<<12)
#define BNX2_PCI_ID_VAL4_MSI_ENABLE (1L<<15)
#define BNX2_PCI_ID_VAL4_MAX_64_ADVERTIZE (1L<<16)
#define BNX2_PCI_ID_VAL4_MAX_133_ADVERTIZE (1L<<17)
-#define BNX2_PCI_ID_VAL4_MAX_MEM_READ_SIZE (0x3L<<21)
-#define BNX2_PCI_ID_VAL4_MAX_SPLIT_SIZE (0x7L<<23)
-#define BNX2_PCI_ID_VAL4_MAX_CUMULATIVE_SIZE (0x7L<<26)
+#define BNX2_PCI_ID_VAL4_RESERVED2 (0x7L<<18)
+#define BNX2_PCI_ID_VAL4_MAX_CUMULATIVE_SIZE_B21 (0x3L<<21)
+#define BNX2_PCI_ID_VAL4_MAX_SPLIT_SIZE_B21 (0x3L<<23)
+#define BNX2_PCI_ID_VAL4_MAX_CUMULATIVE_SIZE_B0 (1L<<25)
+#define BNX2_PCI_ID_VAL4_MAX_MEM_READ_SIZE_B10 (0x3L<<26)
+#define BNX2_PCI_ID_VAL4_MAX_SPLIT_SIZE_B0 (1L<<28)
+#define BNX2_PCI_ID_VAL4_RESERVED3 (0x7L<<29)
+#define BNX2_PCI_ID_VAL4_RESERVED3_XI (0xffffL<<16)
#define BNX2_PCI_ID_VAL5 0x00000444
#define BNX2_PCI_ID_VAL5_D1_SUPPORT (1L<<0)
@@ -556,6 +588,10 @@ struct l2_fhdr {
#define BNX2_PCI_ID_VAL5_PME_IN_D1 (1L<<3)
#define BNX2_PCI_ID_VAL5_PME_IN_D2 (1L<<4)
#define BNX2_PCI_ID_VAL5_PME_IN_D3_HOT (1L<<5)
+#define BNX2_PCI_ID_VAL5_RESERVED0_TE (0x3ffffffL<<6)
+#define BNX2_PCI_ID_VAL5_PM_VERSION_XI (0x7L<<6)
+#define BNX2_PCI_ID_VAL5_NO_SOFT_RESET_XI (1L<<9)
+#define BNX2_PCI_ID_VAL5_RESERVED0_XI (0x3fffffL<<10)
#define BNX2_PCI_PCIX_EXTENDED_STATUS 0x00000448
#define BNX2_PCI_PCIX_EXTENDED_STATUS_NO_SNOOP (1L<<8)
@@ -567,12 +603,91 @@ struct l2_fhdr {
#define BNX2_PCI_ID_VAL6_MAX_LAT (0xffL<<0)
#define BNX2_PCI_ID_VAL6_MIN_GNT (0xffL<<8)
#define BNX2_PCI_ID_VAL6_BIST (0xffL<<16)
+#define BNX2_PCI_ID_VAL6_RESERVED0 (0xffL<<24)
#define BNX2_PCI_MSI_DATA 0x00000450
-#define BNX2_PCI_MSI_DATA_PCI_MSI_DATA (0xffffL<<0)
+#define BNX2_PCI_MSI_DATA_MSI_DATA (0xffffL<<0)
#define BNX2_PCI_MSI_ADDR_H 0x00000454
#define BNX2_PCI_MSI_ADDR_L 0x00000458
+#define BNX2_PCI_MSI_ADDR_L_VAL (0x3fffffffL<<2)
+
+#define BNX2_PCI_CFG_ACCESS_CMD 0x0000045c
+#define BNX2_PCI_CFG_ACCESS_CMD_ADR (0x3fL<<2)
+#define BNX2_PCI_CFG_ACCESS_CMD_RD_REQ (1L<<27)
+#define BNX2_PCI_CFG_ACCESS_CMD_WR_REQ (0xfL<<28)
+
+#define BNX2_PCI_CFG_ACCESS_DATA 0x00000460
+#define BNX2_PCI_MSI_MASK 0x00000464
+#define BNX2_PCI_MSI_MASK_MSI_MASK (0xffffffffL<<0)
+
+#define BNX2_PCI_MSI_PEND 0x00000468
+#define BNX2_PCI_MSI_PEND_MSI_PEND (0xffffffffL<<0)
+
+#define BNX2_PCI_PM_DATA_C 0x0000046c
+#define BNX2_PCI_PM_DATA_C_PM_DATA_8_PRG (0xffL<<0)
+#define BNX2_PCI_PM_DATA_C_RESERVED0 (0xffffffL<<8)
+
+#define BNX2_PCI_MSIX_CONTROL 0x000004c0
+#define BNX2_PCI_MSIX_CONTROL_MSIX_TBL_SIZ (0x7ffL<<0)
+#define BNX2_PCI_MSIX_CONTROL_RESERVED0 (0x1fffffL<<11)
+
+#define BNX2_PCI_MSIX_TBL_OFF_BIR 0x000004c4
+#define BNX2_PCI_MSIX_TBL_OFF_BIR_MSIX_TBL_BIR (0x7L<<0)
+#define BNX2_PCI_MSIX_TBL_OFF_BIR_MSIX_TBL_OFF (0x1fffffffL<<3)
+
+#define BNX2_PCI_MSIX_PBA_OFF_BIT 0x000004c8
+#define BNX2_PCI_MSIX_PBA_OFF_BIT_MSIX_PBA_BIR (0x7L<<0)
+#define BNX2_PCI_MSIX_PBA_OFF_BIT_MSIX_PBA_OFF (0x1fffffffL<<3)
+
+#define BNX2_PCI_PCIE_CAPABILITY 0x000004d0
+#define BNX2_PCI_PCIE_CAPABILITY_INTERRUPT_MSG_NUM (0x1fL<<0)
+#define BNX2_PCI_PCIE_CAPABILITY_COMPLY_PCIE_1_1 (1L<<5)
+
+#define BNX2_PCI_DEVICE_CAPABILITY 0x000004d4
+#define BNX2_PCI_DEVICE_CAPABILITY_MAX_PL_SIZ_SUPPORTED (0x7L<<0)
+#define BNX2_PCI_DEVICE_CAPABILITY_EXTENDED_TAG_SUPPORT (1L<<5)
+#define BNX2_PCI_DEVICE_CAPABILITY_L0S_ACCEPTABLE_LATENCY (0x7L<<6)
+#define BNX2_PCI_DEVICE_CAPABILITY_L1_ACCEPTABLE_LATENCY (0x7L<<9)
+#define BNX2_PCI_DEVICE_CAPABILITY_ROLE_BASED_ERR_RPT (1L<<15)
+
+#define BNX2_PCI_LINK_CAPABILITY 0x000004dc
+#define BNX2_PCI_LINK_CAPABILITY_MAX_LINK_SPEED (0xfL<<0)
+#define BNX2_PCI_LINK_CAPABILITY_MAX_LINK_SPEED_0001 (1L<<0)
+#define BNX2_PCI_LINK_CAPABILITY_MAX_LINK_SPEED_0010 (1L<<0)
+#define BNX2_PCI_LINK_CAPABILITY_MAX_LINK_WIDTH (0x1fL<<4)
+#define BNX2_PCI_LINK_CAPABILITY_CLK_POWER_MGMT (1L<<9)
+#define BNX2_PCI_LINK_CAPABILITY_ASPM_SUPPORT (0x3L<<10)
+#define BNX2_PCI_LINK_CAPABILITY_L0S_EXIT_LAT (0x7L<<12)
+#define BNX2_PCI_LINK_CAPABILITY_L0S_EXIT_LAT_101 (5L<<12)
+#define BNX2_PCI_LINK_CAPABILITY_L0S_EXIT_LAT_110 (6L<<12)
+#define BNX2_PCI_LINK_CAPABILITY_L1_EXIT_LAT (0x7L<<15)
+#define BNX2_PCI_LINK_CAPABILITY_L1_EXIT_LAT_001 (1L<<15)
+#define BNX2_PCI_LINK_CAPABILITY_L1_EXIT_LAT_010 (2L<<15)
+#define BNX2_PCI_LINK_CAPABILITY_L0S_EXIT_COMM_LAT (0x7L<<18)
+#define BNX2_PCI_LINK_CAPABILITY_L0S_EXIT_COMM_LAT_101 (5L<<18)
+#define BNX2_PCI_LINK_CAPABILITY_L0S_EXIT_COMM_LAT_110 (6L<<18)
+#define BNX2_PCI_LINK_CAPABILITY_L1_EXIT_COMM_LAT (0x7L<<21)
+#define BNX2_PCI_LINK_CAPABILITY_L1_EXIT_COMM_LAT_001 (1L<<21)
+#define BNX2_PCI_LINK_CAPABILITY_L1_EXIT_COMM_LAT_010 (2L<<21)
+#define BNX2_PCI_LINK_CAPABILITY_PORT_NUM (0xffL<<24)
+
+#define BNX2_PCI_PCIE_DEVICE_CAPABILITY_2 0x000004e4
+#define BNX2_PCI_PCIE_DEVICE_CAPABILITY_2_CMPL_TO_RANGE_SUPP (0xfL<<0)
+#define BNX2_PCI_PCIE_DEVICE_CAPABILITY_2_CMPL_TO_DISABL_SUPP (1L<<4)
+#define BNX2_PCI_PCIE_DEVICE_CAPABILITY_2_RESERVED (0x7ffffffL<<5)
+
+#define BNX2_PCI_PCIE_LINK_CAPABILITY_2 0x000004e8
+#define BNX2_PCI_PCIE_LINK_CAPABILITY_2_RESERVED (0xffffffffL<<0)
+
+#define BNX2_PCI_GRC_WINDOW1_ADDR 0x00000610
+#define BNX2_PCI_GRC_WINDOW1_ADDR_VALUE (0x1ffL<<13)
+
+#define BNX2_PCI_GRC_WINDOW2_ADDR 0x00000614
+#define BNX2_PCI_GRC_WINDOW2_ADDR_VALUE (0x1ffL<<13)
+
+#define BNX2_PCI_GRC_WINDOW3_ADDR 0x00000618
+#define BNX2_PCI_GRC_WINDOW3_ADDR_VALUE (0x1ffL<<13)
/*
@@ -582,13 +697,23 @@ struct l2_fhdr {
#define BNX2_MISC_COMMAND 0x00000800
#define BNX2_MISC_COMMAND_ENABLE_ALL (1L<<0)
#define BNX2_MISC_COMMAND_DISABLE_ALL (1L<<1)
-#define BNX2_MISC_COMMAND_CORE_RESET (1L<<4)
-#define BNX2_MISC_COMMAND_HARD_RESET (1L<<5)
+#define BNX2_MISC_COMMAND_SW_RESET (1L<<4)
+#define BNX2_MISC_COMMAND_POR_RESET (1L<<5)
+#define BNX2_MISC_COMMAND_HD_RESET (1L<<6)
+#define BNX2_MISC_COMMAND_CMN_SW_RESET (1L<<7)
#define BNX2_MISC_COMMAND_PAR_ERROR (1L<<8)
+#define BNX2_MISC_COMMAND_CS16_ERR (1L<<9)
+#define BNX2_MISC_COMMAND_CS16_ERR_LOC (0xfL<<12)
#define BNX2_MISC_COMMAND_PAR_ERR_RAM (0x7fL<<16)
+#define BNX2_MISC_COMMAND_POWERDOWN_EVENT (1L<<23)
+#define BNX2_MISC_COMMAND_SW_SHUTDOWN (1L<<24)
+#define BNX2_MISC_COMMAND_SHUTDOWN_EN (1L<<25)
+#define BNX2_MISC_COMMAND_DINTEG_ATTN_EN (1L<<26)
+#define BNX2_MISC_COMMAND_PCIE_LINK_IN_L23 (1L<<27)
+#define BNX2_MISC_COMMAND_PCIE_DIS (1L<<28)
#define BNX2_MISC_CFG 0x00000804
-#define BNX2_MISC_CFG_PCI_GRC_TMOUT (1L<<0)
+#define BNX2_MISC_CFG_GRC_TMOUT (1L<<0)
#define BNX2_MISC_CFG_NVM_WR_EN (0x3L<<1)
#define BNX2_MISC_CFG_NVM_WR_EN_PROTECT (0L<<1)
#define BNX2_MISC_CFG_NVM_WR_EN_PCI (1L<<1)
@@ -596,16 +721,45 @@ struct l2_fhdr {
#define BNX2_MISC_CFG_NVM_WR_EN_ALLOW2 (3L<<1)
#define BNX2_MISC_CFG_BIST_EN (1L<<3)
#define BNX2_MISC_CFG_CK25_OUT_ALT_SRC (1L<<4)
-#define BNX2_MISC_CFG_BYPASS_BSCAN (1L<<5)
-#define BNX2_MISC_CFG_BYPASS_EJTAG (1L<<6)
+#define BNX2_MISC_CFG_RESERVED5_TE (1L<<5)
+#define BNX2_MISC_CFG_RESERVED6_TE (1L<<6)
#define BNX2_MISC_CFG_CLK_CTL_OVERRIDE (1L<<7)
-#define BNX2_MISC_CFG_LEDMODE (0x3L<<8)
+#define BNX2_MISC_CFG_LEDMODE (0x7L<<8)
#define BNX2_MISC_CFG_LEDMODE_MAC (0L<<8)
-#define BNX2_MISC_CFG_LEDMODE_GPHY1 (1L<<8)
-#define BNX2_MISC_CFG_LEDMODE_GPHY2 (2L<<8)
+#define BNX2_MISC_CFG_LEDMODE_PHY1_TE (1L<<8)
+#define BNX2_MISC_CFG_LEDMODE_PHY2_TE (2L<<8)
+#define BNX2_MISC_CFG_LEDMODE_PHY3_TE (3L<<8)
+#define BNX2_MISC_CFG_LEDMODE_PHY4_TE (4L<<8)
+#define BNX2_MISC_CFG_LEDMODE_PHY5_TE (5L<<8)
+#define BNX2_MISC_CFG_LEDMODE_PHY6_TE (6L<<8)
+#define BNX2_MISC_CFG_LEDMODE_PHY7_TE (7L<<8)
+#define BNX2_MISC_CFG_MCP_GRC_TMOUT_TE (1L<<11)
+#define BNX2_MISC_CFG_DBU_GRC_TMOUT_TE (1L<<12)
+#define BNX2_MISC_CFG_LEDMODE_XI (0xfL<<8)
+#define BNX2_MISC_CFG_LEDMODE_MAC_XI (0L<<8)
+#define BNX2_MISC_CFG_LEDMODE_PHY1_XI (1L<<8)
+#define BNX2_MISC_CFG_LEDMODE_PHY2_XI (2L<<8)
+#define BNX2_MISC_CFG_LEDMODE_PHY3_XI (3L<<8)
+#define BNX2_MISC_CFG_LEDMODE_MAC2_XI (4L<<8)
+#define BNX2_MISC_CFG_LEDMODE_PHY4_XI (5L<<8)
+#define BNX2_MISC_CFG_LEDMODE_PHY5_XI (6L<<8)
+#define BNX2_MISC_CFG_LEDMODE_PHY6_XI (7L<<8)
+#define BNX2_MISC_CFG_LEDMODE_MAC3_XI (8L<<8)
+#define BNX2_MISC_CFG_LEDMODE_PHY7_XI (9L<<8)
+#define BNX2_MISC_CFG_LEDMODE_PHY8_XI (10L<<8)
+#define BNX2_MISC_CFG_LEDMODE_PHY9_XI (11L<<8)
+#define BNX2_MISC_CFG_LEDMODE_MAC4_XI (12L<<8)
+#define BNX2_MISC_CFG_LEDMODE_PHY10_XI (13L<<8)
+#define BNX2_MISC_CFG_LEDMODE_PHY11_XI (14L<<8)
+#define BNX2_MISC_CFG_LEDMODE_UNUSED_XI (15L<<8)
+#define BNX2_MISC_CFG_PORT_SELECT_XI (1L<<13)
+#define BNX2_MISC_CFG_PARITY_MODE_XI (1L<<14)
#define BNX2_MISC_ID 0x00000808
#define BNX2_MISC_ID_BOND_ID (0xfL<<0)
+#define BNX2_MISC_ID_BOND_ID_X (0L<<0)
+#define BNX2_MISC_ID_BOND_ID_C (3L<<0)
+#define BNX2_MISC_ID_BOND_ID_S (12L<<0)
#define BNX2_MISC_ID_CHIP_METAL (0xffL<<4)
#define BNX2_MISC_ID_CHIP_REV (0xfL<<12)
#define BNX2_MISC_ID_CHIP_NUM (0xffffL<<16)
@@ -639,6 +793,8 @@ struct l2_fhdr {
#define BNX2_MISC_ENABLE_STATUS_BITS_TIMER_ENABLE (1L<<25)
#define BNX2_MISC_ENABLE_STATUS_BITS_DMA_ENGINE_ENABLE (1L<<26)
#define BNX2_MISC_ENABLE_STATUS_BITS_UMP_ENABLE (1L<<27)
+#define BNX2_MISC_ENABLE_STATUS_BITS_RV2P_CMD_SCHEDULER_ENABLE (1L<<28)
+#define BNX2_MISC_ENABLE_STATUS_BITS_RSVD_FUTURE_ENABLE (0x7L<<29)
#define BNX2_MISC_ENABLE_SET_BITS 0x00000810
#define BNX2_MISC_ENABLE_SET_BITS_TX_SCHEDULER_ENABLE (1L<<0)
@@ -669,6 +825,8 @@ struct l2_fhdr {
#define BNX2_MISC_ENABLE_SET_BITS_TIMER_ENABLE (1L<<25)
#define BNX2_MISC_ENABLE_SET_BITS_DMA_ENGINE_ENABLE (1L<<26)
#define BNX2_MISC_ENABLE_SET_BITS_UMP_ENABLE (1L<<27)
+#define BNX2_MISC_ENABLE_SET_BITS_RV2P_CMD_SCHEDULER_ENABLE (1L<<28)
+#define BNX2_MISC_ENABLE_SET_BITS_RSVD_FUTURE_ENABLE (0x7L<<29)
#define BNX2_MISC_ENABLE_CLR_BITS 0x00000814
#define BNX2_MISC_ENABLE_CLR_BITS_TX_SCHEDULER_ENABLE (1L<<0)
@@ -699,6 +857,8 @@ struct l2_fhdr {
#define BNX2_MISC_ENABLE_CLR_BITS_TIMER_ENABLE (1L<<25)
#define BNX2_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE (1L<<26)
#define BNX2_MISC_ENABLE_CLR_BITS_UMP_ENABLE (1L<<27)
+#define BNX2_MISC_ENABLE_CLR_BITS_RV2P_CMD_SCHEDULER_ENABLE (1L<<28)
+#define BNX2_MISC_ENABLE_CLR_BITS_RSVD_FUTURE_ENABLE (0x7L<<29)
#define BNX2_MISC_CLOCK_CONTROL_BITS 0x00000818
#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET (0xfL<<0)
@@ -718,30 +878,41 @@ struct l2_fhdr {
#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_12 (1L<<8)
#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_6 (2L<<8)
#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_62 (4L<<8)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_PLAY_DEAD (1L<<11)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED0_XI (0x7L<<8)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_MIN_POWER (1L<<11)
#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED (0xfL<<12)
#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_100 (0L<<12)
#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_80 (1L<<12)
#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_50 (2L<<12)
#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_40 (4L<<12)
#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_25 (8L<<12)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED1_XI (0xfL<<12)
#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_STOP (1L<<16)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_PLL_STOP (1L<<17)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED_18 (1L<<18)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_USE_SPD_DET (1L<<19)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED (0xfffL<<20)
-
-#define BNX2_MISC_GPIO 0x0000081c
-#define BNX2_MISC_GPIO_VALUE (0xffL<<0)
-#define BNX2_MISC_GPIO_SET (0xffL<<8)
-#define BNX2_MISC_GPIO_CLR (0xffL<<16)
-#define BNX2_MISC_GPIO_FLOAT (0xffL<<24)
-
-#define BNX2_MISC_GPIO_INT 0x00000820
-#define BNX2_MISC_GPIO_INT_INT_STATE (0xfL<<0)
-#define BNX2_MISC_GPIO_INT_OLD_VALUE (0xfL<<8)
-#define BNX2_MISC_GPIO_INT_OLD_SET (0xfL<<16)
-#define BNX2_MISC_GPIO_INT_OLD_CLR (0xfL<<24)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED_17_TE (1L<<17)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED_18_TE (1L<<18)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED_19_TE (1L<<19)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED_TE (0xfffL<<20)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_MGMT_XI (1L<<17)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED2_XI (0x3fL<<18)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_VCO_XI (0x7L<<24)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED3_XI (1L<<27)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_XI (0xfL<<28)
+
+#define BNX2_MISC_SPIO 0x0000081c
+#define BNX2_MISC_SPIO_VALUE (0xffL<<0)
+#define BNX2_MISC_SPIO_SET (0xffL<<8)
+#define BNX2_MISC_SPIO_CLR (0xffL<<16)
+#define BNX2_MISC_SPIO_FLOAT (0xffL<<24)
+
+#define BNX2_MISC_SPIO_INT 0x00000820
+#define BNX2_MISC_SPIO_INT_INT_STATE_TE (0xfL<<0)
+#define BNX2_MISC_SPIO_INT_OLD_VALUE_TE (0xfL<<8)
+#define BNX2_MISC_SPIO_INT_OLD_SET_TE (0xfL<<16)
+#define BNX2_MISC_SPIO_INT_OLD_CLR_TE (0xfL<<24)
+#define BNX2_MISC_SPIO_INT_INT_STATE_XI (0xffL<<0)
+#define BNX2_MISC_SPIO_INT_OLD_VALUE_XI (0xffL<<8)
+#define BNX2_MISC_SPIO_INT_OLD_SET_XI (0xffL<<16)
+#define BNX2_MISC_SPIO_INT_OLD_CLR_XI (0xffL<<24)
#define BNX2_MISC_CONFIG_LFSR 0x00000824
#define BNX2_MISC_CONFIG_LFSR_DIV (0xffffL<<0)
@@ -775,6 +946,8 @@ struct l2_fhdr {
#define BNX2_MISC_LFSR_MASK_BITS_TIMER_ENABLE (1L<<25)
#define BNX2_MISC_LFSR_MASK_BITS_DMA_ENGINE_ENABLE (1L<<26)
#define BNX2_MISC_LFSR_MASK_BITS_UMP_ENABLE (1L<<27)
+#define BNX2_MISC_LFSR_MASK_BITS_RV2P_CMD_SCHEDULER_ENABLE (1L<<28)
+#define BNX2_MISC_LFSR_MASK_BITS_RSVD_FUTURE_ENABLE (0x7L<<29)
#define BNX2_MISC_ARB_REQ0 0x0000082c
#define BNX2_MISC_ARB_REQ1 0x00000830
@@ -831,22 +1004,12 @@ struct l2_fhdr {
#define BNX2_MISC_ARB_GNT3_30 (0x7L<<24)
#define BNX2_MISC_ARB_GNT3_31 (0x7L<<28)
-#define BNX2_MISC_PRBS_CONTROL 0x00000878
-#define BNX2_MISC_PRBS_CONTROL_EN (1L<<0)
-#define BNX2_MISC_PRBS_CONTROL_RSTB (1L<<1)
-#define BNX2_MISC_PRBS_CONTROL_INV (1L<<2)
-#define BNX2_MISC_PRBS_CONTROL_ERR_CLR (1L<<3)
-#define BNX2_MISC_PRBS_CONTROL_ORDER (0x3L<<4)
-#define BNX2_MISC_PRBS_CONTROL_ORDER_7TH (0L<<4)
-#define BNX2_MISC_PRBS_CONTROL_ORDER_15TH (1L<<4)
-#define BNX2_MISC_PRBS_CONTROL_ORDER_23RD (2L<<4)
-#define BNX2_MISC_PRBS_CONTROL_ORDER_31ST (3L<<4)
-
-#define BNX2_MISC_PRBS_STATUS 0x0000087c
-#define BNX2_MISC_PRBS_STATUS_LOCK (1L<<0)
-#define BNX2_MISC_PRBS_STATUS_STKY (1L<<1)
-#define BNX2_MISC_PRBS_STATUS_ERRORS (0x3fffL<<2)
-#define BNX2_MISC_PRBS_STATUS_STATE (0xfL<<16)
+#define BNX2_MISC_RESERVED1 0x00000878
+#define BNX2_MISC_RESERVED1_MISC_RESERVED1_VALUE (0x3fL<<0)
+
+#define BNX2_MISC_RESERVED2 0x0000087c
+#define BNX2_MISC_RESERVED2_PCIE_DIS (1L<<0)
+#define BNX2_MISC_RESERVED2_LINK_IN_L23 (1L<<1)
#define BNX2_MISC_SM_ASF_CONTROL 0x00000880
#define BNX2_MISC_SM_ASF_CONTROL_ASF_RST (1L<<0)
@@ -857,13 +1020,15 @@ struct l2_fhdr {
#define BNX2_MISC_SM_ASF_CONTROL_PL_TO (1L<<5)
#define BNX2_MISC_SM_ASF_CONTROL_RT_TO (1L<<6)
#define BNX2_MISC_SM_ASF_CONTROL_SMB_EVENT (1L<<7)
-#define BNX2_MISC_SM_ASF_CONTROL_RES (0xfL<<8)
+#define BNX2_MISC_SM_ASF_CONTROL_STRETCH_EN (1L<<8)
+#define BNX2_MISC_SM_ASF_CONTROL_STRETCH_PULSE (1L<<9)
+#define BNX2_MISC_SM_ASF_CONTROL_RES (0x3L<<10)
#define BNX2_MISC_SM_ASF_CONTROL_SMB_EN (1L<<12)
#define BNX2_MISC_SM_ASF_CONTROL_SMB_BB_EN (1L<<13)
#define BNX2_MISC_SM_ASF_CONTROL_SMB_NO_ADDR_FILT (1L<<14)
#define BNX2_MISC_SM_ASF_CONTROL_SMB_AUTOREAD (1L<<15)
-#define BNX2_MISC_SM_ASF_CONTROL_NIC_SMB_ADDR1 (0x3fL<<16)
-#define BNX2_MISC_SM_ASF_CONTROL_NIC_SMB_ADDR2 (0x3fL<<24)
+#define BNX2_MISC_SM_ASF_CONTROL_NIC_SMB_ADDR1 (0x7fL<<16)
+#define BNX2_MISC_SM_ASF_CONTROL_NIC_SMB_ADDR2 (0x7fL<<23)
#define BNX2_MISC_SM_ASF_CONTROL_EN_NIC_SMB_ADDR_0 (1L<<30)
#define BNX2_MISC_SM_ASF_CONTROL_SMB_EARLY_ATTN (1L<<31)
@@ -891,13 +1056,13 @@ struct l2_fhdr {
#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS (0xfL<<20)
#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_OK (0L<<20)
#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_FIRST_NACK (1L<<20)
-#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_SUB_NACK (9L<<20)
#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_UFLOW (2L<<20)
#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_STOP (3L<<20)
#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_TIMEOUT (4L<<20)
#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_FIRST_LOST (5L<<20)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_BADACK (6L<<20)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_SUB_NACK (9L<<20)
#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_SUB_LOST (0xdL<<20)
-#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_BADACK (0x6L<<20)
#define BNX2_MISC_SMB_OUT_SMB_OUT_SLAVEMODE (1L<<24)
#define BNX2_MISC_SMB_OUT_SMB_OUT_DAT_EN (1L<<25)
#define BNX2_MISC_SMB_OUT_SMB_OUT_DAT_IN (1L<<26)
@@ -955,6 +1120,38 @@ struct l2_fhdr {
#define BNX2_MISC_PERR_ENA0_RDE_MISC_RPC (1L<<29)
#define BNX2_MISC_PERR_ENA0_RDE_MISC_RPM (1L<<30)
#define BNX2_MISC_PERR_ENA0_RV2P_MISC_CB0REGS (1L<<31)
+#define BNX2_MISC_PERR_ENA0_COM_DMAE_PERR_EN_XI (1L<<0)
+#define BNX2_MISC_PERR_ENA0_CP_DMAE_PERR_EN_XI (1L<<1)
+#define BNX2_MISC_PERR_ENA0_RPM_ACPIBEMEM_PERR_EN_XI (1L<<2)
+#define BNX2_MISC_PERR_ENA0_CTX_USAGE_CNT_PERR_EN_XI (1L<<3)
+#define BNX2_MISC_PERR_ENA0_CTX_PGTBL_PERR_EN_XI (1L<<4)
+#define BNX2_MISC_PERR_ENA0_CTX_CACHE_PERR_EN_XI (1L<<5)
+#define BNX2_MISC_PERR_ENA0_CTX_MIRROR_PERR_EN_XI (1L<<6)
+#define BNX2_MISC_PERR_ENA0_COM_CTXC_PERR_EN_XI (1L<<7)
+#define BNX2_MISC_PERR_ENA0_COM_SCPAD_PERR_EN_XI (1L<<8)
+#define BNX2_MISC_PERR_ENA0_CP_CTXC_PERR_EN_XI (1L<<9)
+#define BNX2_MISC_PERR_ENA0_CP_SCPAD_PERR_EN_XI (1L<<10)
+#define BNX2_MISC_PERR_ENA0_RXP_RBUFC_PERR_EN_XI (1L<<11)
+#define BNX2_MISC_PERR_ENA0_RXP_CTXC_PERR_EN_XI (1L<<12)
+#define BNX2_MISC_PERR_ENA0_RXP_SCPAD_PERR_EN_XI (1L<<13)
+#define BNX2_MISC_PERR_ENA0_TPAT_SCPAD_PERR_EN_XI (1L<<14)
+#define BNX2_MISC_PERR_ENA0_TXP_CTXC_PERR_EN_XI (1L<<15)
+#define BNX2_MISC_PERR_ENA0_TXP_SCPAD_PERR_EN_XI (1L<<16)
+#define BNX2_MISC_PERR_ENA0_CS_TMEM_PERR_EN_XI (1L<<17)
+#define BNX2_MISC_PERR_ENA0_MQ_CTX_PERR_EN_XI (1L<<18)
+#define BNX2_MISC_PERR_ENA0_RPM_DFIFOMEM_PERR_EN_XI (1L<<19)
+#define BNX2_MISC_PERR_ENA0_RPC_DFIFOMEM_PERR_EN_XI (1L<<20)
+#define BNX2_MISC_PERR_ENA0_RBUF_PTRMEM_PERR_EN_XI (1L<<21)
+#define BNX2_MISC_PERR_ENA0_RBUF_DATAMEM_PERR_EN_XI (1L<<22)
+#define BNX2_MISC_PERR_ENA0_RV2P_P2IRAM_PERR_EN_XI (1L<<23)
+#define BNX2_MISC_PERR_ENA0_RV2P_P1IRAM_PERR_EN_XI (1L<<24)
+#define BNX2_MISC_PERR_ENA0_RV2P_CB1REGS_PERR_EN_XI (1L<<25)
+#define BNX2_MISC_PERR_ENA0_RV2P_CB0REGS_PERR_EN_XI (1L<<26)
+#define BNX2_MISC_PERR_ENA0_TPBUF_PERR_EN_XI (1L<<27)
+#define BNX2_MISC_PERR_ENA0_THBUF_PERR_EN_XI (1L<<28)
+#define BNX2_MISC_PERR_ENA0_TDMA_PERR_EN_XI (1L<<29)
+#define BNX2_MISC_PERR_ENA0_TBDC_PERR_EN_XI (1L<<30)
+#define BNX2_MISC_PERR_ENA0_TSCH_LR_PERR_EN_XI (1L<<31)
#define BNX2_MISC_PERR_ENA1 0x000008a8
#define BNX2_MISC_PERR_ENA1_RV2P_MISC_CB1REGS (1L<<0)
@@ -989,6 +1186,35 @@ struct l2_fhdr {
#define BNX2_MISC_PERR_ENA1_RXPQ_MISC (1L<<29)
#define BNX2_MISC_PERR_ENA1_RXPCQ_MISC (1L<<30)
#define BNX2_MISC_PERR_ENA1_RLUPQ_MISC (1L<<31)
+#define BNX2_MISC_PERR_ENA1_RBDC_PERR_EN_XI (1L<<0)
+#define BNX2_MISC_PERR_ENA1_RDMA_DFIFO_PERR_EN_XI (1L<<2)
+#define BNX2_MISC_PERR_ENA1_HC_STATS_PERR_EN_XI (1L<<3)
+#define BNX2_MISC_PERR_ENA1_HC_MSIX_PERR_EN_XI (1L<<4)
+#define BNX2_MISC_PERR_ENA1_HC_PRODUCSTB_PERR_EN_XI (1L<<5)
+#define BNX2_MISC_PERR_ENA1_HC_CONSUMSTB_PERR_EN_XI (1L<<6)
+#define BNX2_MISC_PERR_ENA1_TPATQ_PERR_EN_XI (1L<<7)
+#define BNX2_MISC_PERR_ENA1_MCPQ_PERR_EN_XI (1L<<8)
+#define BNX2_MISC_PERR_ENA1_TDMAQ_PERR_EN_XI (1L<<9)
+#define BNX2_MISC_PERR_ENA1_TXPQ_PERR_EN_XI (1L<<10)
+#define BNX2_MISC_PERR_ENA1_COMTQ_PERR_EN_XI (1L<<11)
+#define BNX2_MISC_PERR_ENA1_COMQ_PERR_EN_XI (1L<<12)
+#define BNX2_MISC_PERR_ENA1_RLUPQ_PERR_EN_XI (1L<<13)
+#define BNX2_MISC_PERR_ENA1_RXPQ_PERR_EN_XI (1L<<14)
+#define BNX2_MISC_PERR_ENA1_RV2PPQ_PERR_EN_XI (1L<<15)
+#define BNX2_MISC_PERR_ENA1_RDMAQ_PERR_EN_XI (1L<<16)
+#define BNX2_MISC_PERR_ENA1_TASQ_PERR_EN_XI (1L<<17)
+#define BNX2_MISC_PERR_ENA1_TBDRQ_PERR_EN_XI (1L<<18)
+#define BNX2_MISC_PERR_ENA1_TSCHQ_PERR_EN_XI (1L<<19)
+#define BNX2_MISC_PERR_ENA1_COMXQ_PERR_EN_XI (1L<<20)
+#define BNX2_MISC_PERR_ENA1_RXPCQ_PERR_EN_XI (1L<<21)
+#define BNX2_MISC_PERR_ENA1_RV2PTQ_PERR_EN_XI (1L<<22)
+#define BNX2_MISC_PERR_ENA1_RV2PMQ_PERR_EN_XI (1L<<23)
+#define BNX2_MISC_PERR_ENA1_CPQ_PERR_EN_XI (1L<<24)
+#define BNX2_MISC_PERR_ENA1_CSQ_PERR_EN_XI (1L<<25)
+#define BNX2_MISC_PERR_ENA1_RLUP_CID_PERR_EN_XI (1L<<26)
+#define BNX2_MISC_PERR_ENA1_RV2PCS_TMEM_PERR_EN_XI (1L<<27)
+#define BNX2_MISC_PERR_ENA1_RV2PCSQ_PERR_EN_XI (1L<<28)
+#define BNX2_MISC_PERR_ENA1_MQ_IDX_PERR_EN_XI (1L<<29)
#define BNX2_MISC_PERR_ENA2 0x000008ac
#define BNX2_MISC_PERR_ENA2_COMQ_MISC (1L<<0)
@@ -1000,19 +1226,498 @@ struct l2_fhdr {
#define BNX2_MISC_PERR_ENA2_TDMAQ_MISC (1L<<6)
#define BNX2_MISC_PERR_ENA2_TPATQ_MISC (1L<<7)
#define BNX2_MISC_PERR_ENA2_TASQ_MISC (1L<<8)
+#define BNX2_MISC_PERR_ENA2_TGT_FIFO_PERR_EN_XI (1L<<0)
+#define BNX2_MISC_PERR_ENA2_UMP_TX_PERR_EN_XI (1L<<1)
+#define BNX2_MISC_PERR_ENA2_UMP_RX_PERR_EN_XI (1L<<2)
+#define BNX2_MISC_PERR_ENA2_MCP_ROM_PERR_EN_XI (1L<<3)
+#define BNX2_MISC_PERR_ENA2_MCP_SCPAD_PERR_EN_XI (1L<<4)
+#define BNX2_MISC_PERR_ENA2_HB_MEM_PERR_EN_XI (1L<<5)
+#define BNX2_MISC_PERR_ENA2_PCIE_REPLAY_PERR_EN_XI (1L<<6)
#define BNX2_MISC_DEBUG_VECTOR_SEL 0x000008b0
#define BNX2_MISC_DEBUG_VECTOR_SEL_0 (0xfffL<<0)
#define BNX2_MISC_DEBUG_VECTOR_SEL_1 (0xfffL<<12)
+#define BNX2_MISC_DEBUG_VECTOR_SEL_1_XI (0xfffL<<15)
#define BNX2_MISC_VREG_CONTROL 0x000008b4
#define BNX2_MISC_VREG_CONTROL_1_2 (0xfL<<0)
+#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_XI (0xfL<<0)
+#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS14_XI (0L<<0)
+#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS12_XI (1L<<0)
+#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS10_XI (2L<<0)
+#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS8_XI (3L<<0)
+#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS6_XI (4L<<0)
+#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS4_XI (5L<<0)
+#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS2_XI (6L<<0)
+#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_NOM_XI (7L<<0)
+#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS2_XI (8L<<0)
+#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS4_XI (9L<<0)
+#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS6_XI (10L<<0)
+#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS8_XI (11L<<0)
+#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS10_XI (12L<<0)
+#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS12_XI (13L<<0)
+#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS14_XI (14L<<0)
+#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS16_XI (15L<<0)
#define BNX2_MISC_VREG_CONTROL_2_5 (0xfL<<4)
+#define BNX2_MISC_VREG_CONTROL_2_5_PLUS14 (0L<<4)
+#define BNX2_MISC_VREG_CONTROL_2_5_PLUS12 (1L<<4)
+#define BNX2_MISC_VREG_CONTROL_2_5_PLUS10 (2L<<4)
+#define BNX2_MISC_VREG_CONTROL_2_5_PLUS8 (3L<<4)
+#define BNX2_MISC_VREG_CONTROL_2_5_PLUS6 (4L<<4)
+#define BNX2_MISC_VREG_CONTROL_2_5_PLUS4 (5L<<4)
+#define BNX2_MISC_VREG_CONTROL_2_5_PLUS2 (6L<<4)
+#define BNX2_MISC_VREG_CONTROL_2_5_NOM (7L<<4)
+#define BNX2_MISC_VREG_CONTROL_2_5_MINUS2 (8L<<4)
+#define BNX2_MISC_VREG_CONTROL_2_5_MINUS4 (9L<<4)
+#define BNX2_MISC_VREG_CONTROL_2_5_MINUS6 (10L<<4)
+#define BNX2_MISC_VREG_CONTROL_2_5_MINUS8 (11L<<4)
+#define BNX2_MISC_VREG_CONTROL_2_5_MINUS10 (12L<<4)
+#define BNX2_MISC_VREG_CONTROL_2_5_MINUS12 (13L<<4)
+#define BNX2_MISC_VREG_CONTROL_2_5_MINUS14 (14L<<4)
+#define BNX2_MISC_VREG_CONTROL_2_5_MINUS16 (15L<<4)
+#define BNX2_MISC_VREG_CONTROL_1_0_MGMT (0xfL<<8)
+#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS14 (0L<<8)
+#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS12 (1L<<8)
+#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS10 (2L<<8)
+#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS8 (3L<<8)
+#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS6 (4L<<8)
+#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS4 (5L<<8)
+#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS2 (6L<<8)
+#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_NOM (7L<<8)
+#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS2 (8L<<8)
+#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS4 (9L<<8)
+#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS6 (10L<<8)
+#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS8 (11L<<8)
+#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS10 (12L<<8)
+#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS12 (13L<<8)
+#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS14 (14L<<8)
+#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS16 (15L<<8)
#define BNX2_MISC_FINAL_CLK_CTL_VAL 0x000008b8
#define BNX2_MISC_FINAL_CLK_CTL_VAL_MISC_FINAL_CLK_CTL_VAL (0x3ffffffL<<6)
-#define BNX2_MISC_UNUSED0 0x000008bc
+#define BNX2_MISC_GP_HW_CTL0 0x000008bc
+#define BNX2_MISC_GP_HW_CTL0_TX_DRIVE (1L<<0)
+#define BNX2_MISC_GP_HW_CTL0_RMII_MODE (1L<<1)
+#define BNX2_MISC_GP_HW_CTL0_RMII_CRSDV_SEL (1L<<2)
+#define BNX2_MISC_GP_HW_CTL0_RVMII_MODE (1L<<3)
+#define BNX2_MISC_GP_HW_CTL0_FLASH_SAMP_SCLK_NEGEDGE_TE (1L<<4)
+#define BNX2_MISC_GP_HW_CTL0_HIDDEN_REVISION_ID_TE (1L<<5)
+#define BNX2_MISC_GP_HW_CTL0_HC_CNTL_TMOUT_CTR_RST_TE (1L<<6)
+#define BNX2_MISC_GP_HW_CTL0_RESERVED1_XI (0x7L<<4)
+#define BNX2_MISC_GP_HW_CTL0_ENA_CORE_RST_ON_MAIN_PWR_GOING_AWAY (1L<<7)
+#define BNX2_MISC_GP_HW_CTL0_ENA_SEL_VAUX_B_IN_L2_TE (1L<<8)
+#define BNX2_MISC_GP_HW_CTL0_GRC_BNK_FREE_FIX_TE (1L<<9)
+#define BNX2_MISC_GP_HW_CTL0_LED_ACT_SEL_TE (1L<<10)
+#define BNX2_MISC_GP_HW_CTL0_RESERVED2_XI (0x7L<<8)
+#define BNX2_MISC_GP_HW_CTL0_UP1_DEF0 (1L<<11)
+#define BNX2_MISC_GP_HW_CTL0_FIBER_MODE_DIS_DEF (1L<<12)
+#define BNX2_MISC_GP_HW_CTL0_FORCE2500_DEF (1L<<13)
+#define BNX2_MISC_GP_HW_CTL0_AUTODETECT_DIS_DEF (1L<<14)
+#define BNX2_MISC_GP_HW_CTL0_PARALLEL_DETECT_DEF (1L<<15)
+#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI (0xfL<<16)
+#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI_3MA (0L<<16)
+#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI_2P5MA (1L<<16)
+#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI_2P0MA (3L<<16)
+#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI_1P5MA (5L<<16)
+#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI_1P0MA (7L<<16)
+#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI_PWRDN (15L<<16)
+#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PRE2DIS (1L<<20)
+#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PRE1DIS (1L<<21)
+#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_CTAT (0x3L<<22)
+#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_CTAT_M6P (0L<<22)
+#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_CTAT_M0P (1L<<22)
+#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_CTAT_P0P (2L<<22)
+#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_CTAT_P6P (3L<<22)
+#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PTAT (0x3L<<24)
+#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PTAT_M6P (0L<<24)
+#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PTAT_M0P (1L<<24)
+#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PTAT_P0P (2L<<24)
+#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PTAT_P6P (3L<<24)
+#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_IAMP_ADJ (0x3L<<26)
+#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_IAMP_ADJ_240UA (0L<<26)
+#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_IAMP_ADJ_160UA (1L<<26)
+#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_IAMP_ADJ_400UA (2L<<26)
+#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_IAMP_ADJ_320UA (3L<<26)
+#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_ICBUF_ADJ (0x3L<<28)
+#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_ICBUF_ADJ_240UA (0L<<28)
+#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_ICBUF_ADJ_160UA (1L<<28)
+#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_ICBUF_ADJ_400UA (2L<<28)
+#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_ICBUF_ADJ_320UA (3L<<28)
+#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_XTAL_ADJ (0x3L<<30)
+#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_XTAL_ADJ_1P57 (0L<<30)
+#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_XTAL_ADJ_1P45 (1L<<30)
+#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_XTAL_ADJ_1P62 (2L<<30)
+#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_XTAL_ADJ_1P66 (3L<<30)
+
+#define BNX2_MISC_GP_HW_CTL1 0x000008c0
+#define BNX2_MISC_GP_HW_CTL1_1_ATTN_BTN_PRSNT_TE (1L<<0)
+#define BNX2_MISC_GP_HW_CTL1_1_ATTN_IND_PRSNT_TE (1L<<1)
+#define BNX2_MISC_GP_HW_CTL1_1_PWR_IND_PRSNT_TE (1L<<2)
+#define BNX2_MISC_GP_HW_CTL1_0_PCIE_LOOPBACK_TE (1L<<3)
+#define BNX2_MISC_GP_HW_CTL1_RESERVED_SOFT_XI (0xffffL<<0)
+#define BNX2_MISC_GP_HW_CTL1_RESERVED_HARD_XI (0xffffL<<16)
+
+#define BNX2_MISC_NEW_HW_CTL 0x000008c4
+#define BNX2_MISC_NEW_HW_CTL_MAIN_POR_BYPASS (1L<<0)
+#define BNX2_MISC_NEW_HW_CTL_RINGOSC_ENABLE (1L<<1)
+#define BNX2_MISC_NEW_HW_CTL_RINGOSC_SEL0 (1L<<2)
+#define BNX2_MISC_NEW_HW_CTL_RINGOSC_SEL1 (1L<<3)
+#define BNX2_MISC_NEW_HW_CTL_RESERVED_SHARED (0xfffL<<4)
+#define BNX2_MISC_NEW_HW_CTL_RESERVED_SPLIT (0xffffL<<16)
+
+#define BNX2_MISC_NEW_CORE_CTL 0x000008c8
+#define BNX2_MISC_NEW_CORE_CTL_LINK_HOLDOFF_SUCCESS (1L<<0)
+#define BNX2_MISC_NEW_CORE_CTL_LINK_HOLDOFF_REQ (1L<<1)
+#define BNX2_MISC_NEW_CORE_CTL_RESERVED_CMN (0x3fffL<<2)
+#define BNX2_MISC_NEW_CORE_CTL_RESERVED_TC (0xffffL<<16)
+
+#define BNX2_MISC_ECO_HW_CTL 0x000008cc
+#define BNX2_MISC_ECO_HW_CTL_LARGE_GRC_TMOUT_EN (1L<<0)
+#define BNX2_MISC_ECO_HW_CTL_RESERVED_SOFT (0x7fffL<<1)
+#define BNX2_MISC_ECO_HW_CTL_RESERVED_HARD (0xffffL<<16)
+
+#define BNX2_MISC_ECO_CORE_CTL 0x000008d0
+#define BNX2_MISC_ECO_CORE_CTL_RESERVED_SOFT (0xffffL<<0)
+#define BNX2_MISC_ECO_CORE_CTL_RESERVED_HARD (0xffffL<<16)
+
+#define BNX2_MISC_PPIO 0x000008d4
+#define BNX2_MISC_PPIO_VALUE (0xfL<<0)
+#define BNX2_MISC_PPIO_SET (0xfL<<8)
+#define BNX2_MISC_PPIO_CLR (0xfL<<16)
+#define BNX2_MISC_PPIO_FLOAT (0xfL<<24)
+
+#define BNX2_MISC_PPIO_INT 0x000008d8
+#define BNX2_MISC_PPIO_INT_INT_STATE (0xfL<<0)
+#define BNX2_MISC_PPIO_INT_OLD_VALUE (0xfL<<8)
+#define BNX2_MISC_PPIO_INT_OLD_SET (0xfL<<16)
+#define BNX2_MISC_PPIO_INT_OLD_CLR (0xfL<<24)
+
+#define BNX2_MISC_RESET_NUMS 0x000008dc
+#define BNX2_MISC_RESET_NUMS_NUM_HARD_RESETS (0x7L<<0)
+#define BNX2_MISC_RESET_NUMS_NUM_PCIE_RESETS (0x7L<<4)
+#define BNX2_MISC_RESET_NUMS_NUM_PERSTB_RESETS (0x7L<<8)
+#define BNX2_MISC_RESET_NUMS_NUM_CMN_RESETS (0x7L<<12)
+#define BNX2_MISC_RESET_NUMS_NUM_PORT_RESETS (0x7L<<16)
+
+#define BNX2_MISC_CS16_ERR 0x000008e0
+#define BNX2_MISC_CS16_ERR_ENA_PCI (1L<<0)
+#define BNX2_MISC_CS16_ERR_ENA_RDMA (1L<<1)
+#define BNX2_MISC_CS16_ERR_ENA_TDMA (1L<<2)
+#define BNX2_MISC_CS16_ERR_ENA_EMAC (1L<<3)
+#define BNX2_MISC_CS16_ERR_ENA_CTX (1L<<4)
+#define BNX2_MISC_CS16_ERR_ENA_TBDR (1L<<5)
+#define BNX2_MISC_CS16_ERR_ENA_RBDC (1L<<6)
+#define BNX2_MISC_CS16_ERR_ENA_COM (1L<<7)
+#define BNX2_MISC_CS16_ERR_ENA_CP (1L<<8)
+#define BNX2_MISC_CS16_ERR_STA_PCI (1L<<16)
+#define BNX2_MISC_CS16_ERR_STA_RDMA (1L<<17)
+#define BNX2_MISC_CS16_ERR_STA_TDMA (1L<<18)
+#define BNX2_MISC_CS16_ERR_STA_EMAC (1L<<19)
+#define BNX2_MISC_CS16_ERR_STA_CTX (1L<<20)
+#define BNX2_MISC_CS16_ERR_STA_TBDR (1L<<21)
+#define BNX2_MISC_CS16_ERR_STA_RBDC (1L<<22)
+#define BNX2_MISC_CS16_ERR_STA_COM (1L<<23)
+#define BNX2_MISC_CS16_ERR_STA_CP (1L<<24)
+
+#define BNX2_MISC_SPIO_EVENT 0x000008e4
+#define BNX2_MISC_SPIO_EVENT_ENABLE (0xffL<<0)
+
+#define BNX2_MISC_PPIO_EVENT 0x000008e8
+#define BNX2_MISC_PPIO_EVENT_ENABLE (0xfL<<0)
+
+#define BNX2_MISC_DUAL_MEDIA_CTRL 0x000008ec
+#define BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID (0xffL<<0)
+#define BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID_X (0L<<0)
+#define BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID_C (3L<<0)
+#define BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID_S (12L<<0)
+#define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_CTRL_STRAP (0x7L<<8)
+#define BNX2_MISC_DUAL_MEDIA_CTRL_PORT_SWAP_PIN (1L<<11)
+#define BNX2_MISC_DUAL_MEDIA_CTRL_SERDES1_SIGDET (1L<<12)
+#define BNX2_MISC_DUAL_MEDIA_CTRL_SERDES0_SIGDET (1L<<13)
+#define BNX2_MISC_DUAL_MEDIA_CTRL_PHY1_SIGDET (1L<<14)
+#define BNX2_MISC_DUAL_MEDIA_CTRL_PHY0_SIGDET (1L<<15)
+#define BNX2_MISC_DUAL_MEDIA_CTRL_LCPLL_RST (1L<<16)
+#define BNX2_MISC_DUAL_MEDIA_CTRL_SERDES1_RST (1L<<17)
+#define BNX2_MISC_DUAL_MEDIA_CTRL_SERDES0_RST (1L<<18)
+#define BNX2_MISC_DUAL_MEDIA_CTRL_PHY1_RST (1L<<19)
+#define BNX2_MISC_DUAL_MEDIA_CTRL_PHY0_RST (1L<<20)
+#define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_CTRL (0x7L<<21)
+#define BNX2_MISC_DUAL_MEDIA_CTRL_PORT_SWAP (1L<<24)
+#define BNX2_MISC_DUAL_MEDIA_CTRL_STRAP_OVERRIDE (1L<<25)
+#define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_SERDES_IDDQ (0xfL<<26)
+#define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_SERDES_IDDQ_SER1_IDDQ (1L<<26)
+#define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_SERDES_IDDQ_SER0_IDDQ (2L<<26)
+#define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_SERDES_IDDQ_PHY1_IDDQ (4L<<26)
+#define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_SERDES_IDDQ_PHY0_IDDQ (8L<<26)
+
+#define BNX2_MISC_OTP_CMD1 0x000008f0
+#define BNX2_MISC_OTP_CMD1_FMODE (0x7L<<0)
+#define BNX2_MISC_OTP_CMD1_FMODE_IDLE (0L<<0)
+#define BNX2_MISC_OTP_CMD1_FMODE_WRITE (1L<<0)
+#define BNX2_MISC_OTP_CMD1_FMODE_INIT (2L<<0)
+#define BNX2_MISC_OTP_CMD1_FMODE_SET (3L<<0)
+#define BNX2_MISC_OTP_CMD1_FMODE_RST (4L<<0)
+#define BNX2_MISC_OTP_CMD1_FMODE_VERIFY (5L<<0)
+#define BNX2_MISC_OTP_CMD1_FMODE_RESERVED0 (6L<<0)
+#define BNX2_MISC_OTP_CMD1_FMODE_RESERVED1 (7L<<0)
+#define BNX2_MISC_OTP_CMD1_USEPINS (1L<<8)
+#define BNX2_MISC_OTP_CMD1_PROGSEL (1L<<9)
+#define BNX2_MISC_OTP_CMD1_PROGSTART (1L<<10)
+#define BNX2_MISC_OTP_CMD1_PCOUNT (0x7L<<16)
+#define BNX2_MISC_OTP_CMD1_PBYP (1L<<19)
+#define BNX2_MISC_OTP_CMD1_VSEL (0xfL<<20)
+#define BNX2_MISC_OTP_CMD1_TM (0x7L<<27)
+#define BNX2_MISC_OTP_CMD1_SADBYP (1L<<30)
+#define BNX2_MISC_OTP_CMD1_DEBUG (1L<<31)
+
+#define BNX2_MISC_OTP_CMD2 0x000008f4
+#define BNX2_MISC_OTP_CMD2_OTP_ROM_ADDR (0x3ffL<<0)
+#define BNX2_MISC_OTP_CMD2_DOSEL (0x7fL<<16)
+#define BNX2_MISC_OTP_CMD2_DOSEL_0 (0L<<16)
+#define BNX2_MISC_OTP_CMD2_DOSEL_1 (1L<<16)
+#define BNX2_MISC_OTP_CMD2_DOSEL_127 (127L<<16)
+
+#define BNX2_MISC_OTP_STATUS 0x000008f8
+#define BNX2_MISC_OTP_STATUS_DATA (0xffL<<0)
+#define BNX2_MISC_OTP_STATUS_VALID (1L<<8)
+#define BNX2_MISC_OTP_STATUS_BUSY (1L<<9)
+#define BNX2_MISC_OTP_STATUS_BUSYSM (1L<<10)
+#define BNX2_MISC_OTP_STATUS_DONE (1L<<11)
+
+#define BNX2_MISC_OTP_SHIFT1_CMD 0x000008fc
+#define BNX2_MISC_OTP_SHIFT1_CMD_RESET_MODE_N (1L<<0)
+#define BNX2_MISC_OTP_SHIFT1_CMD_SHIFT_DONE (1L<<1)
+#define BNX2_MISC_OTP_SHIFT1_CMD_SHIFT_START (1L<<2)
+#define BNX2_MISC_OTP_SHIFT1_CMD_LOAD_DATA (1L<<3)
+#define BNX2_MISC_OTP_SHIFT1_CMD_SHIFT_SELECT (0x1fL<<8)
+
+#define BNX2_MISC_OTP_SHIFT1_DATA 0x00000900
+#define BNX2_MISC_OTP_SHIFT2_CMD 0x00000904
+#define BNX2_MISC_OTP_SHIFT2_CMD_RESET_MODE_N (1L<<0)
+#define BNX2_MISC_OTP_SHIFT2_CMD_SHIFT_DONE (1L<<1)
+#define BNX2_MISC_OTP_SHIFT2_CMD_SHIFT_START (1L<<2)
+#define BNX2_MISC_OTP_SHIFT2_CMD_LOAD_DATA (1L<<3)
+#define BNX2_MISC_OTP_SHIFT2_CMD_SHIFT_SELECT (0x1fL<<8)
+
+#define BNX2_MISC_OTP_SHIFT2_DATA 0x00000908
+#define BNX2_MISC_BIST_CS0 0x0000090c
+#define BNX2_MISC_BIST_CS0_MBIST_EN (1L<<0)
+#define BNX2_MISC_BIST_CS0_BIST_SETUP (0x3L<<1)
+#define BNX2_MISC_BIST_CS0_MBIST_ASYNC_RESET (1L<<3)
+#define BNX2_MISC_BIST_CS0_MBIST_DONE (1L<<8)
+#define BNX2_MISC_BIST_CS0_MBIST_GO (1L<<9)
+#define BNX2_MISC_BIST_CS0_BIST_OVERRIDE (1L<<31)
+
+#define BNX2_MISC_BIST_MEMSTATUS0 0x00000910
+#define BNX2_MISC_BIST_CS1 0x00000914
+#define BNX2_MISC_BIST_CS1_MBIST_EN (1L<<0)
+#define BNX2_MISC_BIST_CS1_BIST_SETUP (0x3L<<1)
+#define BNX2_MISC_BIST_CS1_MBIST_ASYNC_RESET (1L<<3)
+#define BNX2_MISC_BIST_CS1_MBIST_DONE (1L<<8)
+#define BNX2_MISC_BIST_CS1_MBIST_GO (1L<<9)
+
+#define BNX2_MISC_BIST_MEMSTATUS1 0x00000918
+#define BNX2_MISC_BIST_CS2 0x0000091c
+#define BNX2_MISC_BIST_CS2_MBIST_EN (1L<<0)
+#define BNX2_MISC_BIST_CS2_BIST_SETUP (0x3L<<1)
+#define BNX2_MISC_BIST_CS2_MBIST_ASYNC_RESET (1L<<3)
+#define BNX2_MISC_BIST_CS2_MBIST_DONE (1L<<8)
+#define BNX2_MISC_BIST_CS2_MBIST_GO (1L<<9)
+
+#define BNX2_MISC_BIST_MEMSTATUS2 0x00000920
+#define BNX2_MISC_BIST_CS3 0x00000924
+#define BNX2_MISC_BIST_CS3_MBIST_EN (1L<<0)
+#define BNX2_MISC_BIST_CS3_BIST_SETUP (0x3L<<1)
+#define BNX2_MISC_BIST_CS3_MBIST_ASYNC_RESET (1L<<3)
+#define BNX2_MISC_BIST_CS3_MBIST_DONE (1L<<8)
+#define BNX2_MISC_BIST_CS3_MBIST_GO (1L<<9)
+
+#define BNX2_MISC_BIST_MEMSTATUS3 0x00000928
+#define BNX2_MISC_BIST_CS4 0x0000092c
+#define BNX2_MISC_BIST_CS4_MBIST_EN (1L<<0)
+#define BNX2_MISC_BIST_CS4_BIST_SETUP (0x3L<<1)
+#define BNX2_MISC_BIST_CS4_MBIST_ASYNC_RESET (1L<<3)
+#define BNX2_MISC_BIST_CS4_MBIST_DONE (1L<<8)
+#define BNX2_MISC_BIST_CS4_MBIST_GO (1L<<9)
+
+#define BNX2_MISC_BIST_MEMSTATUS4 0x00000930
+#define BNX2_MISC_BIST_CS5 0x00000934
+#define BNX2_MISC_BIST_CS5_MBIST_EN (1L<<0)
+#define BNX2_MISC_BIST_CS5_BIST_SETUP (0x3L<<1)
+#define BNX2_MISC_BIST_CS5_MBIST_ASYNC_RESET (1L<<3)
+#define BNX2_MISC_BIST_CS5_MBIST_DONE (1L<<8)
+#define BNX2_MISC_BIST_CS5_MBIST_GO (1L<<9)
+
+#define BNX2_MISC_BIST_MEMSTATUS5 0x00000938
+#define BNX2_MISC_MEM_TM0 0x0000093c
+#define BNX2_MISC_MEM_TM0_PCIE_REPLAY_TM (0xfL<<0)
+#define BNX2_MISC_MEM_TM0_MCP_SCPAD (0xfL<<8)
+#define BNX2_MISC_MEM_TM0_UMP_TM (0xffL<<16)
+#define BNX2_MISC_MEM_TM0_HB_MEM_TM (0xfL<<24)
+
+#define BNX2_MISC_USPLL_CTRL 0x00000940
+#define BNX2_MISC_USPLL_CTRL_PH_DET_DIS (1L<<0)
+#define BNX2_MISC_USPLL_CTRL_FREQ_DET_DIS (1L<<1)
+#define BNX2_MISC_USPLL_CTRL_LCPX (0x3fL<<2)
+#define BNX2_MISC_USPLL_CTRL_RX (0x3L<<8)
+#define BNX2_MISC_USPLL_CTRL_VC_EN (1L<<10)
+#define BNX2_MISC_USPLL_CTRL_VCO_MG (0x3L<<11)
+#define BNX2_MISC_USPLL_CTRL_KVCO_XF (0x7L<<13)
+#define BNX2_MISC_USPLL_CTRL_KVCO_XS (0x7L<<16)
+#define BNX2_MISC_USPLL_CTRL_TESTD_EN (1L<<19)
+#define BNX2_MISC_USPLL_CTRL_TESTD_SEL (0x7L<<20)
+#define BNX2_MISC_USPLL_CTRL_TESTA_EN (1L<<23)
+#define BNX2_MISC_USPLL_CTRL_TESTA_SEL (0x3L<<24)
+#define BNX2_MISC_USPLL_CTRL_ATTEN_FREF (1L<<26)
+#define BNX2_MISC_USPLL_CTRL_DIGITAL_RST (1L<<27)
+#define BNX2_MISC_USPLL_CTRL_ANALOG_RST (1L<<28)
+#define BNX2_MISC_USPLL_CTRL_LOCK (1L<<29)
+
+#define BNX2_MISC_PERR_STATUS0 0x00000944
+#define BNX2_MISC_PERR_STATUS0_COM_DMAE_PERR (1L<<0)
+#define BNX2_MISC_PERR_STATUS0_CP_DMAE_PERR (1L<<1)
+#define BNX2_MISC_PERR_STATUS0_RPM_ACPIBEMEM_PERR (1L<<2)
+#define BNX2_MISC_PERR_STATUS0_CTX_USAGE_CNT_PERR (1L<<3)
+#define BNX2_MISC_PERR_STATUS0_CTX_PGTBL_PERR (1L<<4)
+#define BNX2_MISC_PERR_STATUS0_CTX_CACHE_PERR (1L<<5)
+#define BNX2_MISC_PERR_STATUS0_CTX_MIRROR_PERR (1L<<6)
+#define BNX2_MISC_PERR_STATUS0_COM_CTXC_PERR (1L<<7)
+#define BNX2_MISC_PERR_STATUS0_COM_SCPAD_PERR (1L<<8)
+#define BNX2_MISC_PERR_STATUS0_CP_CTXC_PERR (1L<<9)
+#define BNX2_MISC_PERR_STATUS0_CP_SCPAD_PERR (1L<<10)
+#define BNX2_MISC_PERR_STATUS0_RXP_RBUFC_PERR (1L<<11)
+#define BNX2_MISC_PERR_STATUS0_RXP_CTXC_PERR (1L<<12)
+#define BNX2_MISC_PERR_STATUS0_RXP_SCPAD_PERR (1L<<13)
+#define BNX2_MISC_PERR_STATUS0_TPAT_SCPAD_PERR (1L<<14)
+#define BNX2_MISC_PERR_STATUS0_TXP_CTXC_PERR (1L<<15)
+#define BNX2_MISC_PERR_STATUS0_TXP_SCPAD_PERR (1L<<16)
+#define BNX2_MISC_PERR_STATUS0_CS_TMEM_PERR (1L<<17)
+#define BNX2_MISC_PERR_STATUS0_MQ_CTX_PERR (1L<<18)
+#define BNX2_MISC_PERR_STATUS0_RPM_DFIFOMEM_PERR (1L<<19)
+#define BNX2_MISC_PERR_STATUS0_RPC_DFIFOMEM_PERR (1L<<20)
+#define BNX2_MISC_PERR_STATUS0_RBUF_PTRMEM_PERR (1L<<21)
+#define BNX2_MISC_PERR_STATUS0_RBUF_DATAMEM_PERR (1L<<22)
+#define BNX2_MISC_PERR_STATUS0_RV2P_P2IRAM_PERR (1L<<23)
+#define BNX2_MISC_PERR_STATUS0_RV2P_P1IRAM_PERR (1L<<24)
+#define BNX2_MISC_PERR_STATUS0_RV2P_CB1REGS_PERR (1L<<25)
+#define BNX2_MISC_PERR_STATUS0_RV2P_CB0REGS_PERR (1L<<26)
+#define BNX2_MISC_PERR_STATUS0_TPBUF_PERR (1L<<27)
+#define BNX2_MISC_PERR_STATUS0_THBUF_PERR (1L<<28)
+#define BNX2_MISC_PERR_STATUS0_TDMA_PERR (1L<<29)
+#define BNX2_MISC_PERR_STATUS0_TBDC_PERR (1L<<30)
+#define BNX2_MISC_PERR_STATUS0_TSCH_LR_PERR (1L<<31)
+
+#define BNX2_MISC_PERR_STATUS1 0x00000948
+#define BNX2_MISC_PERR_STATUS1_RBDC_PERR (1L<<0)
+#define BNX2_MISC_PERR_STATUS1_RDMA_DFIFO_PERR (1L<<2)
+#define BNX2_MISC_PERR_STATUS1_HC_STATS_PERR (1L<<3)
+#define BNX2_MISC_PERR_STATUS1_HC_MSIX_PERR (1L<<4)
+#define BNX2_MISC_PERR_STATUS1_HC_PRODUCSTB_PERR (1L<<5)
+#define BNX2_MISC_PERR_STATUS1_HC_CONSUMSTB_PERR (1L<<6)
+#define BNX2_MISC_PERR_STATUS1_TPATQ_PERR (1L<<7)
+#define BNX2_MISC_PERR_STATUS1_MCPQ_PERR (1L<<8)
+#define BNX2_MISC_PERR_STATUS1_TDMAQ_PERR (1L<<9)
+#define BNX2_MISC_PERR_STATUS1_TXPQ_PERR (1L<<10)
+#define BNX2_MISC_PERR_STATUS1_COMTQ_PERR (1L<<11)
+#define BNX2_MISC_PERR_STATUS1_COMQ_PERR (1L<<12)
+#define BNX2_MISC_PERR_STATUS1_RLUPQ_PERR (1L<<13)
+#define BNX2_MISC_PERR_STATUS1_RXPQ_PERR (1L<<14)
+#define BNX2_MISC_PERR_STATUS1_RV2PPQ_PERR (1L<<15)
+#define BNX2_MISC_PERR_STATUS1_RDMAQ_PERR (1L<<16)
+#define BNX2_MISC_PERR_STATUS1_TASQ_PERR (1L<<17)
+#define BNX2_MISC_PERR_STATUS1_TBDRQ_PERR (1L<<18)
+#define BNX2_MISC_PERR_STATUS1_TSCHQ_PERR (1L<<19)
+#define BNX2_MISC_PERR_STATUS1_COMXQ_PERR (1L<<20)
+#define BNX2_MISC_PERR_STATUS1_RXPCQ_PERR (1L<<21)
+#define BNX2_MISC_PERR_STATUS1_RV2PTQ_PERR (1L<<22)
+#define BNX2_MISC_PERR_STATUS1_RV2PMQ_PERR (1L<<23)
+#define BNX2_MISC_PERR_STATUS1_CPQ_PERR (1L<<24)
+#define BNX2_MISC_PERR_STATUS1_CSQ_PERR (1L<<25)
+#define BNX2_MISC_PERR_STATUS1_RLUP_CID_PERR (1L<<26)
+#define BNX2_MISC_PERR_STATUS1_RV2PCS_TMEM_PERR (1L<<27)
+#define BNX2_MISC_PERR_STATUS1_RV2PCSQ_PERR (1L<<28)
+#define BNX2_MISC_PERR_STATUS1_MQ_IDX_PERR (1L<<29)
+
+#define BNX2_MISC_PERR_STATUS2 0x0000094c
+#define BNX2_MISC_PERR_STATUS2_TGT_FIFO_PERR (1L<<0)
+#define BNX2_MISC_PERR_STATUS2_UMP_TX_PERR (1L<<1)
+#define BNX2_MISC_PERR_STATUS2_UMP_RX_PERR (1L<<2)
+#define BNX2_MISC_PERR_STATUS2_MCP_ROM_PERR (1L<<3)
+#define BNX2_MISC_PERR_STATUS2_MCP_SCPAD_PERR (1L<<4)
+#define BNX2_MISC_PERR_STATUS2_HB_MEM_PERR (1L<<5)
+#define BNX2_MISC_PERR_STATUS2_PCIE_REPLAY_PERR (1L<<6)
+
+#define BNX2_MISC_LCPLL_CTRL0 0x00000950
+#define BNX2_MISC_LCPLL_CTRL0_OAC (0x7L<<0)
+#define BNX2_MISC_LCPLL_CTRL0_OAC_NEGTWENTY (0L<<0)
+#define BNX2_MISC_LCPLL_CTRL0_OAC_ZERO (1L<<0)
+#define BNX2_MISC_LCPLL_CTRL0_OAC_TWENTY (3L<<0)
+#define BNX2_MISC_LCPLL_CTRL0_OAC_FORTY (7L<<0)
+#define BNX2_MISC_LCPLL_CTRL0_ICP_CTRL (0x7L<<3)
+#define BNX2_MISC_LCPLL_CTRL0_ICP_CTRL_360 (0L<<3)
+#define BNX2_MISC_LCPLL_CTRL0_ICP_CTRL_480 (1L<<3)
+#define BNX2_MISC_LCPLL_CTRL0_ICP_CTRL_600 (3L<<3)
+#define BNX2_MISC_LCPLL_CTRL0_ICP_CTRL_720 (7L<<3)
+#define BNX2_MISC_LCPLL_CTRL0_BIAS_CTRL (0x3L<<6)
+#define BNX2_MISC_LCPLL_CTRL0_PLL_OBSERVE (0x7L<<8)
+#define BNX2_MISC_LCPLL_CTRL0_VTH_CTRL (0x3L<<11)
+#define BNX2_MISC_LCPLL_CTRL0_VTH_CTRL_0 (0L<<11)
+#define BNX2_MISC_LCPLL_CTRL0_VTH_CTRL_1 (1L<<11)
+#define BNX2_MISC_LCPLL_CTRL0_VTH_CTRL_2 (2L<<11)
+#define BNX2_MISC_LCPLL_CTRL0_PLLSEQSTART (1L<<13)
+#define BNX2_MISC_LCPLL_CTRL0_RESERVED (1L<<14)
+#define BNX2_MISC_LCPLL_CTRL0_CAPRETRY_EN (1L<<15)
+#define BNX2_MISC_LCPLL_CTRL0_FREQMONITOR_EN (1L<<16)
+#define BNX2_MISC_LCPLL_CTRL0_FREQDETRESTART_EN (1L<<17)
+#define BNX2_MISC_LCPLL_CTRL0_FREQDETRETRY_EN (1L<<18)
+#define BNX2_MISC_LCPLL_CTRL0_PLLFORCEFDONE_EN (1L<<19)
+#define BNX2_MISC_LCPLL_CTRL0_PLLFORCEFDONE (1L<<20)
+#define BNX2_MISC_LCPLL_CTRL0_PLLFORCEFPASS (1L<<21)
+#define BNX2_MISC_LCPLL_CTRL0_PLLFORCECAPDONE_EN (1L<<22)
+#define BNX2_MISC_LCPLL_CTRL0_PLLFORCECAPDONE (1L<<23)
+#define BNX2_MISC_LCPLL_CTRL0_PLLFORCECAPPASS_EN (1L<<24)
+#define BNX2_MISC_LCPLL_CTRL0_PLLFORCECAPPASS (1L<<25)
+#define BNX2_MISC_LCPLL_CTRL0_CAPRESTART (1L<<26)
+#define BNX2_MISC_LCPLL_CTRL0_CAPSELECTM_EN (1L<<27)
+
+#define BNX2_MISC_LCPLL_CTRL1 0x00000954
+#define BNX2_MISC_LCPLL_CTRL1_CAPSELECTM (0x1fL<<0)
+#define BNX2_MISC_LCPLL_CTRL1_CAPFORCESLOWDOWN_EN (1L<<5)
+#define BNX2_MISC_LCPLL_CTRL1_CAPFORCESLOWDOWN (1L<<6)
+#define BNX2_MISC_LCPLL_CTRL1_SLOWDN_XOR (1L<<7)
+
+#define BNX2_MISC_LCPLL_STATUS 0x00000958
+#define BNX2_MISC_LCPLL_STATUS_FREQDONE_SM (1L<<0)
+#define BNX2_MISC_LCPLL_STATUS_FREQPASS_SM (1L<<1)
+#define BNX2_MISC_LCPLL_STATUS_PLLSEQDONE (1L<<2)
+#define BNX2_MISC_LCPLL_STATUS_PLLSEQPASS (1L<<3)
+#define BNX2_MISC_LCPLL_STATUS_PLLSTATE (0x7L<<4)
+#define BNX2_MISC_LCPLL_STATUS_CAPSTATE (0x7L<<7)
+#define BNX2_MISC_LCPLL_STATUS_CAPSELECT (0x1fL<<10)
+#define BNX2_MISC_LCPLL_STATUS_SLOWDN_INDICATOR (1L<<15)
+#define BNX2_MISC_LCPLL_STATUS_SLOWDN_INDICATOR_0 (0L<<15)
+#define BNX2_MISC_LCPLL_STATUS_SLOWDN_INDICATOR_1 (1L<<15)
+
+#define BNX2_MISC_OSCFUNDS_CTRL 0x0000095c
+#define BNX2_MISC_OSCFUNDS_CTRL_FREQ_MON (1L<<5)
+#define BNX2_MISC_OSCFUNDS_CTRL_FREQ_MON_OFF (0L<<5)
+#define BNX2_MISC_OSCFUNDS_CTRL_FREQ_MON_ON (1L<<5)
+#define BNX2_MISC_OSCFUNDS_CTRL_XTAL_ADJCM (0x3L<<6)
+#define BNX2_MISC_OSCFUNDS_CTRL_XTAL_ADJCM_0 (0L<<6)
+#define BNX2_MISC_OSCFUNDS_CTRL_XTAL_ADJCM_1 (1L<<6)
+#define BNX2_MISC_OSCFUNDS_CTRL_XTAL_ADJCM_2 (2L<<6)
+#define BNX2_MISC_OSCFUNDS_CTRL_XTAL_ADJCM_3 (3L<<6)
+#define BNX2_MISC_OSCFUNDS_CTRL_ICBUF_ADJ (0x3L<<8)
+#define BNX2_MISC_OSCFUNDS_CTRL_ICBUF_ADJ_0 (0L<<8)
+#define BNX2_MISC_OSCFUNDS_CTRL_ICBUF_ADJ_1 (1L<<8)
+#define BNX2_MISC_OSCFUNDS_CTRL_ICBUF_ADJ_2 (2L<<8)
+#define BNX2_MISC_OSCFUNDS_CTRL_ICBUF_ADJ_3 (3L<<8)
+#define BNX2_MISC_OSCFUNDS_CTRL_IAMP_ADJ (0x3L<<10)
+#define BNX2_MISC_OSCFUNDS_CTRL_IAMP_ADJ_0 (0L<<10)
+#define BNX2_MISC_OSCFUNDS_CTRL_IAMP_ADJ_1 (1L<<10)
+#define BNX2_MISC_OSCFUNDS_CTRL_IAMP_ADJ_2 (2L<<10)
+#define BNX2_MISC_OSCFUNDS_CTRL_IAMP_ADJ_3 (3L<<10)
/*
@@ -1031,11 +1736,35 @@ struct l2_fhdr {
#define BNX2_NVM_COMMAND_WRDI (1L<<17)
#define BNX2_NVM_COMMAND_EWSR (1L<<18)
#define BNX2_NVM_COMMAND_WRSR (1L<<19)
+#define BNX2_NVM_COMMAND_RD_ID (1L<<20)
+#define BNX2_NVM_COMMAND_RD_STATUS (1L<<21)
+#define BNX2_NVM_COMMAND_MODE_256 (1L<<22)
#define BNX2_NVM_STATUS 0x00006404
#define BNX2_NVM_STATUS_PI_FSM_STATE (0xfL<<0)
#define BNX2_NVM_STATUS_EE_FSM_STATE (0xfL<<4)
#define BNX2_NVM_STATUS_EQ_FSM_STATE (0xfL<<8)
+#define BNX2_NVM_STATUS_SPI_FSM_STATE_XI (0x1fL<<0)
+#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_IDLE_XI (0L<<0)
+#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_CMD0_XI (1L<<0)
+#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_CMD1_XI (2L<<0)
+#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_CMD_FINISH0_XI (3L<<0)
+#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_CMD_FINISH1_XI (4L<<0)
+#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_ADDR0_XI (5L<<0)
+#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_WRITE_DATA0_XI (6L<<0)
+#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_WRITE_DATA1_XI (7L<<0)
+#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_WRITE_DATA2_XI (8L<<0)
+#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_DATA0_XI (9L<<0)
+#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_DATA1_XI (10L<<0)
+#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_DATA2_XI (11L<<0)
+#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_STATUS_RDID0_XI (12L<<0)
+#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_STATUS_RDID1_XI (13L<<0)
+#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_STATUS_RDID2_XI (14L<<0)
+#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_STATUS_RDID3_XI (15L<<0)
+#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_STATUS_RDID4_XI (16L<<0)
+#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_CHECK_BUSY0_XI (17L<<0)
+#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_ST_WREN_XI (18L<<0)
+#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_WAIT_XI (19L<<0)
#define BNX2_NVM_WRITE 0x00006408
#define BNX2_NVM_WRITE_NVM_WRITE_VALUE (0xffffffffL<<0)
@@ -1046,6 +1775,10 @@ struct l2_fhdr {
#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_CS_B (8L<<0)
#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SO (16L<<0)
#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SI (32L<<0)
+#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SI_XI (1L<<0)
+#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SO_XI (2L<<0)
+#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_CS_B_XI (4L<<0)
+#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SCLK_XI (8L<<0)
#define BNX2_NVM_ADDR 0x0000640c
#define BNX2_NVM_ADDR_NVM_ADDR_VALUE (0xffffffL<<0)
@@ -1056,6 +1789,10 @@ struct l2_fhdr {
#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_CS_B (8L<<0)
#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SO (16L<<0)
#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SI (32L<<0)
+#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SI_XI (1L<<0)
+#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SO_XI (2L<<0)
+#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_CS_B_XI (4L<<0)
+#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SCLK_XI (8L<<0)
#define BNX2_NVM_READ 0x00006410
#define BNX2_NVM_READ_NVM_READ_VALUE (0xffffffffL<<0)
@@ -1066,6 +1803,10 @@ struct l2_fhdr {
#define BNX2_NVM_READ_NVM_READ_VALUE_CS_B (8L<<0)
#define BNX2_NVM_READ_NVM_READ_VALUE_SO (16L<<0)
#define BNX2_NVM_READ_NVM_READ_VALUE_SI (32L<<0)
+#define BNX2_NVM_READ_NVM_READ_VALUE_SI_XI (1L<<0)
+#define BNX2_NVM_READ_NVM_READ_VALUE_SO_XI (2L<<0)
+#define BNX2_NVM_READ_NVM_READ_VALUE_CS_B_XI (4L<<0)
+#define BNX2_NVM_READ_NVM_READ_VALUE_SCLK_XI (8L<<0)
#define BNX2_NVM_CFG1 0x00006414
#define BNX2_NVM_CFG1_FLASH_MODE (1L<<0)
@@ -1077,14 +1818,21 @@ struct l2_fhdr {
#define BNX2_NVM_CFG1_STATUS_BIT_BUFFER_RDY (7L<<4)
#define BNX2_NVM_CFG1_SPI_CLK_DIV (0xfL<<7)
#define BNX2_NVM_CFG1_SEE_CLK_DIV (0x7ffL<<11)
+#define BNX2_NVM_CFG1_STRAP_CONTROL_0 (1L<<23)
#define BNX2_NVM_CFG1_PROTECT_MODE (1L<<24)
#define BNX2_NVM_CFG1_FLASH_SIZE (1L<<25)
+#define BNX2_NVM_CFG1_FW_USTRAP_1 (1L<<26)
+#define BNX2_NVM_CFG1_FW_USTRAP_0 (1L<<27)
+#define BNX2_NVM_CFG1_FW_USTRAP_2 (1L<<28)
+#define BNX2_NVM_CFG1_FW_USTRAP_3 (1L<<29)
+#define BNX2_NVM_CFG1_FW_FLASH_TYPE_EN (1L<<30)
#define BNX2_NVM_CFG1_COMPAT_BYPASSS (1L<<31)
#define BNX2_NVM_CFG2 0x00006418
#define BNX2_NVM_CFG2_ERASE_CMD (0xffL<<0)
#define BNX2_NVM_CFG2_DUMMY (0xffL<<8)
#define BNX2_NVM_CFG2_STATUS_CMD (0xffL<<16)
+#define BNX2_NVM_CFG2_READ_ID (0xffL<<24)
#define BNX2_NVM_CFG3 0x0000641c
#define BNX2_NVM_CFG3_BUFFER_RD_CMD (0xffL<<0)
@@ -1119,6 +1867,35 @@ struct l2_fhdr {
#define BNX2_NVM_WRITE1_WRDI_CMD (0xffL<<8)
#define BNX2_NVM_WRITE1_SR_DATA (0xffL<<16)
+#define BNX2_NVM_CFG4 0x0000642c
+#define BNX2_NVM_CFG4_FLASH_SIZE (0x7L<<0)
+#define BNX2_NVM_CFG4_FLASH_SIZE_1MBIT (0L<<0)
+#define BNX2_NVM_CFG4_FLASH_SIZE_2MBIT (1L<<0)
+#define BNX2_NVM_CFG4_FLASH_SIZE_4MBIT (2L<<0)
+#define BNX2_NVM_CFG4_FLASH_SIZE_8MBIT (3L<<0)
+#define BNX2_NVM_CFG4_FLASH_SIZE_16MBIT (4L<<0)
+#define BNX2_NVM_CFG4_FLASH_SIZE_32MBIT (5L<<0)
+#define BNX2_NVM_CFG4_FLASH_SIZE_64MBIT (6L<<0)
+#define BNX2_NVM_CFG4_FLASH_SIZE_128MBIT (7L<<0)
+#define BNX2_NVM_CFG4_FLASH_VENDOR (1L<<3)
+#define BNX2_NVM_CFG4_FLASH_VENDOR_ST (0L<<3)
+#define BNX2_NVM_CFG4_FLASH_VENDOR_ATMEL (1L<<3)
+#define BNX2_NVM_CFG4_MODE_256_EMPTY_BIT_LOC (0x3L<<4)
+#define BNX2_NVM_CFG4_MODE_256_EMPTY_BIT_LOC_BIT8 (0L<<4)
+#define BNX2_NVM_CFG4_MODE_256_EMPTY_BIT_LOC_BIT9 (1L<<4)
+#define BNX2_NVM_CFG4_MODE_256_EMPTY_BIT_LOC_BIT10 (2L<<4)
+#define BNX2_NVM_CFG4_MODE_256_EMPTY_BIT_LOC_BIT11 (3L<<4)
+#define BNX2_NVM_CFG4_STATUS_BIT_POLARITY (1L<<6)
+#define BNX2_NVM_CFG4_RESERVED (0x1ffffffL<<7)
+
+#define BNX2_NVM_RECONFIG 0x00006430
+#define BNX2_NVM_RECONFIG_ORIG_STRAP_VALUE (0xfL<<0)
+#define BNX2_NVM_RECONFIG_ORIG_STRAP_VALUE_ST (0L<<0)
+#define BNX2_NVM_RECONFIG_ORIG_STRAP_VALUE_ATMEL (1L<<0)
+#define BNX2_NVM_RECONFIG_RECONFIG_STRAP_VALUE (0xfL<<4)
+#define BNX2_NVM_RECONFIG_RESERVED (0x7fffffL<<8)
+#define BNX2_NVM_RECONFIG_RECONFIG_DONE (1L<<31)
+
/*
@@ -1140,6 +1917,8 @@ struct l2_fhdr {
#define BNX2_DMA_STATUS_BIG_WRITE_TRANSFERS_STAT (1L<<23)
#define BNX2_DMA_STATUS_BIG_WRITE_DELAY_PCI_CLKS_STAT (1L<<24)
#define BNX2_DMA_STATUS_BIG_WRITE_RETRY_AFTER_DATA_STAT (1L<<25)
+#define BNX2_DMA_STATUS_GLOBAL_ERR_XI (1L<<0)
+#define BNX2_DMA_STATUS_BME_XI (1L<<4)
#define BNX2_DMA_CONFIG 0x00000c08
#define BNX2_DMA_CONFIG_DATA_BYTE_SWAP (1L<<0)
@@ -1161,85 +1940,315 @@ struct l2_fhdr {
#define BNX2_DMA_CONFIG_BIG_SIZE_128 (0x2L<<24)
#define BNX2_DMA_CONFIG_BIG_SIZE_256 (0x4L<<24)
#define BNX2_DMA_CONFIG_BIG_SIZE_512 (0x8L<<24)
+#define BNX2_DMA_CONFIG_DAT_WBSWAP_MODE_XI (0x3L<<0)
+#define BNX2_DMA_CONFIG_CTL_WBSWAP_MODE_XI (0x3L<<4)
+#define BNX2_DMA_CONFIG_MAX_PL_XI (0x7L<<12)
+#define BNX2_DMA_CONFIG_MAX_PL_128B_XI (0L<<12)
+#define BNX2_DMA_CONFIG_MAX_PL_256B_XI (1L<<12)
+#define BNX2_DMA_CONFIG_MAX_PL_512B_XI (2L<<12)
+#define BNX2_DMA_CONFIG_MAX_PL_EN_XI (1L<<15)
+#define BNX2_DMA_CONFIG_MAX_RRS_XI (0x7L<<16)
+#define BNX2_DMA_CONFIG_MAX_RRS_128B_XI (0L<<16)
+#define BNX2_DMA_CONFIG_MAX_RRS_256B_XI (1L<<16)
+#define BNX2_DMA_CONFIG_MAX_RRS_512B_XI (2L<<16)
+#define BNX2_DMA_CONFIG_MAX_RRS_1024B_XI (3L<<16)
+#define BNX2_DMA_CONFIG_MAX_RRS_2048B_XI (4L<<16)
+#define BNX2_DMA_CONFIG_MAX_RRS_4096B_XI (5L<<16)
+#define BNX2_DMA_CONFIG_MAX_RRS_EN_XI (1L<<19)
+#define BNX2_DMA_CONFIG_NO_64SWAP_EN_XI (1L<<31)
#define BNX2_DMA_BLACKOUT 0x00000c0c
#define BNX2_DMA_BLACKOUT_RD_RETRY_BLACKOUT (0xffL<<0)
#define BNX2_DMA_BLACKOUT_2ND_RD_RETRY_BLACKOUT (0xffL<<8)
#define BNX2_DMA_BLACKOUT_WR_RETRY_BLACKOUT (0xffL<<16)
-#define BNX2_DMA_RCHAN_STAT 0x00000c30
-#define BNX2_DMA_RCHAN_STAT_COMP_CODE_0 (0x7L<<0)
-#define BNX2_DMA_RCHAN_STAT_PAR_ERR_0 (1L<<3)
-#define BNX2_DMA_RCHAN_STAT_COMP_CODE_1 (0x7L<<4)
-#define BNX2_DMA_RCHAN_STAT_PAR_ERR_1 (1L<<7)
-#define BNX2_DMA_RCHAN_STAT_COMP_CODE_2 (0x7L<<8)
-#define BNX2_DMA_RCHAN_STAT_PAR_ERR_2 (1L<<11)
-#define BNX2_DMA_RCHAN_STAT_COMP_CODE_3 (0x7L<<12)
-#define BNX2_DMA_RCHAN_STAT_PAR_ERR_3 (1L<<15)
-#define BNX2_DMA_RCHAN_STAT_COMP_CODE_4 (0x7L<<16)
-#define BNX2_DMA_RCHAN_STAT_PAR_ERR_4 (1L<<19)
-#define BNX2_DMA_RCHAN_STAT_COMP_CODE_5 (0x7L<<20)
-#define BNX2_DMA_RCHAN_STAT_PAR_ERR_5 (1L<<23)
-#define BNX2_DMA_RCHAN_STAT_COMP_CODE_6 (0x7L<<24)
-#define BNX2_DMA_RCHAN_STAT_PAR_ERR_6 (1L<<27)
-#define BNX2_DMA_RCHAN_STAT_COMP_CODE_7 (0x7L<<28)
-#define BNX2_DMA_RCHAN_STAT_PAR_ERR_7 (1L<<31)
-
-#define BNX2_DMA_WCHAN_STAT 0x00000c34
-#define BNX2_DMA_WCHAN_STAT_COMP_CODE_0 (0x7L<<0)
-#define BNX2_DMA_WCHAN_STAT_PAR_ERR_0 (1L<<3)
-#define BNX2_DMA_WCHAN_STAT_COMP_CODE_1 (0x7L<<4)
-#define BNX2_DMA_WCHAN_STAT_PAR_ERR_1 (1L<<7)
-#define BNX2_DMA_WCHAN_STAT_COMP_CODE_2 (0x7L<<8)
-#define BNX2_DMA_WCHAN_STAT_PAR_ERR_2 (1L<<11)
-#define BNX2_DMA_WCHAN_STAT_COMP_CODE_3 (0x7L<<12)
-#define BNX2_DMA_WCHAN_STAT_PAR_ERR_3 (1L<<15)
-#define BNX2_DMA_WCHAN_STAT_COMP_CODE_4 (0x7L<<16)
-#define BNX2_DMA_WCHAN_STAT_PAR_ERR_4 (1L<<19)
-#define BNX2_DMA_WCHAN_STAT_COMP_CODE_5 (0x7L<<20)
-#define BNX2_DMA_WCHAN_STAT_PAR_ERR_5 (1L<<23)
-#define BNX2_DMA_WCHAN_STAT_COMP_CODE_6 (0x7L<<24)
-#define BNX2_DMA_WCHAN_STAT_PAR_ERR_6 (1L<<27)
-#define BNX2_DMA_WCHAN_STAT_COMP_CODE_7 (0x7L<<28)
-#define BNX2_DMA_WCHAN_STAT_PAR_ERR_7 (1L<<31)
-
-#define BNX2_DMA_RCHAN_ASSIGNMENT 0x00000c38
-#define BNX2_DMA_RCHAN_ASSIGNMENT_0 (0xfL<<0)
-#define BNX2_DMA_RCHAN_ASSIGNMENT_1 (0xfL<<4)
-#define BNX2_DMA_RCHAN_ASSIGNMENT_2 (0xfL<<8)
-#define BNX2_DMA_RCHAN_ASSIGNMENT_3 (0xfL<<12)
-#define BNX2_DMA_RCHAN_ASSIGNMENT_4 (0xfL<<16)
-#define BNX2_DMA_RCHAN_ASSIGNMENT_5 (0xfL<<20)
-#define BNX2_DMA_RCHAN_ASSIGNMENT_6 (0xfL<<24)
-#define BNX2_DMA_RCHAN_ASSIGNMENT_7 (0xfL<<28)
-
-#define BNX2_DMA_WCHAN_ASSIGNMENT 0x00000c3c
-#define BNX2_DMA_WCHAN_ASSIGNMENT_0 (0xfL<<0)
-#define BNX2_DMA_WCHAN_ASSIGNMENT_1 (0xfL<<4)
-#define BNX2_DMA_WCHAN_ASSIGNMENT_2 (0xfL<<8)
-#define BNX2_DMA_WCHAN_ASSIGNMENT_3 (0xfL<<12)
-#define BNX2_DMA_WCHAN_ASSIGNMENT_4 (0xfL<<16)
-#define BNX2_DMA_WCHAN_ASSIGNMENT_5 (0xfL<<20)
-#define BNX2_DMA_WCHAN_ASSIGNMENT_6 (0xfL<<24)
-#define BNX2_DMA_WCHAN_ASSIGNMENT_7 (0xfL<<28)
-
-#define BNX2_DMA_RCHAN_STAT_00 0x00000c40
-#define BNX2_DMA_RCHAN_STAT_00_RCHAN_STA_HOST_ADDR_LOW (0xffffffffL<<0)
-
-#define BNX2_DMA_RCHAN_STAT_01 0x00000c44
-#define BNX2_DMA_RCHAN_STAT_01_RCHAN_STA_HOST_ADDR_HIGH (0xffffffffL<<0)
-
-#define BNX2_DMA_RCHAN_STAT_02 0x00000c48
-#define BNX2_DMA_RCHAN_STAT_02_LENGTH (0xffffL<<0)
-#define BNX2_DMA_RCHAN_STAT_02_WORD_SWAP (1L<<16)
-#define BNX2_DMA_RCHAN_STAT_02_BYTE_SWAP (1L<<17)
-#define BNX2_DMA_RCHAN_STAT_02_PRIORITY_LVL (1L<<18)
-
-#define BNX2_DMA_RCHAN_STAT_10 0x00000c4c
-#define BNX2_DMA_RCHAN_STAT_11 0x00000c50
-#define BNX2_DMA_RCHAN_STAT_12 0x00000c54
-#define BNX2_DMA_RCHAN_STAT_20 0x00000c58
-#define BNX2_DMA_RCHAN_STAT_21 0x00000c5c
+#define BNX2_DMA_READ_MASTER_SETTING_0 0x00000c10
+#define BNX2_DMA_READ_MASTER_SETTING_0_TBDC_NO_SNOOP (1L<<0)
+#define BNX2_DMA_READ_MASTER_SETTING_0_TBDC_RELAX_ORDER (1L<<1)
+#define BNX2_DMA_READ_MASTER_SETTING_0_TBDC_PRIORITY (1L<<2)
+#define BNX2_DMA_READ_MASTER_SETTING_0_TBDC_TRAFFIC_CLASS (0x7L<<4)
+#define BNX2_DMA_READ_MASTER_SETTING_0_TBDC_PARAM_EN (1L<<7)
+#define BNX2_DMA_READ_MASTER_SETTING_0_RBDC_NO_SNOOP (1L<<8)
+#define BNX2_DMA_READ_MASTER_SETTING_0_RBDC_RELAX_ORDER (1L<<9)
+#define BNX2_DMA_READ_MASTER_SETTING_0_RBDC_PRIORITY (1L<<10)
+#define BNX2_DMA_READ_MASTER_SETTING_0_RBDC_TRAFFIC_CLASS (0x7L<<12)
+#define BNX2_DMA_READ_MASTER_SETTING_0_RBDC_PARAM_EN (1L<<15)
+#define BNX2_DMA_READ_MASTER_SETTING_0_TDMA_NO_SNOOP (1L<<16)
+#define BNX2_DMA_READ_MASTER_SETTING_0_TDMA_RELAX_ORDER (1L<<17)
+#define BNX2_DMA_READ_MASTER_SETTING_0_TDMA_PRIORITY (1L<<18)
+#define BNX2_DMA_READ_MASTER_SETTING_0_TDMA_TRAFFIC_CLASS (0x7L<<20)
+#define BNX2_DMA_READ_MASTER_SETTING_0_TDMA_PARAM_EN (1L<<23)
+#define BNX2_DMA_READ_MASTER_SETTING_0_CTX_NO_SNOOP (1L<<24)
+#define BNX2_DMA_READ_MASTER_SETTING_0_CTX_RELAX_ORDER (1L<<25)
+#define BNX2_DMA_READ_MASTER_SETTING_0_CTX_PRIORITY (1L<<26)
+#define BNX2_DMA_READ_MASTER_SETTING_0_CTX_TRAFFIC_CLASS (0x7L<<28)
+#define BNX2_DMA_READ_MASTER_SETTING_0_CTX_PARAM_EN (1L<<31)
+
+#define BNX2_DMA_READ_MASTER_SETTING_1 0x00000c14
+#define BNX2_DMA_READ_MASTER_SETTING_1_COM_NO_SNOOP (1L<<0)
+#define BNX2_DMA_READ_MASTER_SETTING_1_COM_RELAX_ORDER (1L<<1)
+#define BNX2_DMA_READ_MASTER_SETTING_1_COM_PRIORITY (1L<<2)
+#define BNX2_DMA_READ_MASTER_SETTING_1_COM_TRAFFIC_CLASS (0x7L<<4)
+#define BNX2_DMA_READ_MASTER_SETTING_1_COM_PARAM_EN (1L<<7)
+#define BNX2_DMA_READ_MASTER_SETTING_1_CP_NO_SNOOP (1L<<8)
+#define BNX2_DMA_READ_MASTER_SETTING_1_CP_RELAX_ORDER (1L<<9)
+#define BNX2_DMA_READ_MASTER_SETTING_1_CP_PRIORITY (1L<<10)
+#define BNX2_DMA_READ_MASTER_SETTING_1_CP_TRAFFIC_CLASS (0x7L<<12)
+#define BNX2_DMA_READ_MASTER_SETTING_1_CP_PARAM_EN (1L<<15)
+
+#define BNX2_DMA_WRITE_MASTER_SETTING_0 0x00000c18
+#define BNX2_DMA_WRITE_MASTER_SETTING_0_HC_NO_SNOOP (1L<<0)
+#define BNX2_DMA_WRITE_MASTER_SETTING_0_HC_RELAX_ORDER (1L<<1)
+#define BNX2_DMA_WRITE_MASTER_SETTING_0_HC_PRIORITY (1L<<2)
+#define BNX2_DMA_WRITE_MASTER_SETTING_0_HC_CS_VLD (1L<<3)
+#define BNX2_DMA_WRITE_MASTER_SETTING_0_HC_TRAFFIC_CLASS (0x7L<<4)
+#define BNX2_DMA_WRITE_MASTER_SETTING_0_HC_PARAM_EN (1L<<7)
+#define BNX2_DMA_WRITE_MASTER_SETTING_0_RDMA_NO_SNOOP (1L<<8)
+#define BNX2_DMA_WRITE_MASTER_SETTING_0_RDMA_RELAX_ORDER (1L<<9)
+#define BNX2_DMA_WRITE_MASTER_SETTING_0_RDMA_PRIORITY (1L<<10)
+#define BNX2_DMA_WRITE_MASTER_SETTING_0_RDMA_CS_VLD (1L<<11)
+#define BNX2_DMA_WRITE_MASTER_SETTING_0_RDMA_TRAFFIC_CLASS (0x7L<<12)
+#define BNX2_DMA_WRITE_MASTER_SETTING_0_RDMA_PARAM_EN (1L<<15)
+#define BNX2_DMA_WRITE_MASTER_SETTING_0_CTX_NO_SNOOP (1L<<24)
+#define BNX2_DMA_WRITE_MASTER_SETTING_0_CTX_RELAX_ORDER (1L<<25)
+#define BNX2_DMA_WRITE_MASTER_SETTING_0_CTX_PRIORITY (1L<<26)
+#define BNX2_DMA_WRITE_MASTER_SETTING_0_CTX_CS_VLD (1L<<27)
+#define BNX2_DMA_WRITE_MASTER_SETTING_0_CTX_TRAFFIC_CLASS (0x7L<<28)
+#define BNX2_DMA_WRITE_MASTER_SETTING_0_CTX_PARAM_EN (1L<<31)
+
+#define BNX2_DMA_WRITE_MASTER_SETTING_1 0x00000c1c
+#define BNX2_DMA_WRITE_MASTER_SETTING_1_COM_NO_SNOOP (1L<<0)
+#define BNX2_DMA_WRITE_MASTER_SETTING_1_COM_RELAX_ORDER (1L<<1)
+#define BNX2_DMA_WRITE_MASTER_SETTING_1_COM_PRIORITY (1L<<2)
+#define BNX2_DMA_WRITE_MASTER_SETTING_1_COM_CS_VLD (1L<<3)
+#define BNX2_DMA_WRITE_MASTER_SETTING_1_COM_TRAFFIC_CLASS (0x7L<<4)
+#define BNX2_DMA_WRITE_MASTER_SETTING_1_COM_PARAM_EN (1L<<7)
+#define BNX2_DMA_WRITE_MASTER_SETTING_1_CP_NO_SNOOP (1L<<8)
+#define BNX2_DMA_WRITE_MASTER_SETTING_1_CP_RELAX_ORDER (1L<<9)
+#define BNX2_DMA_WRITE_MASTER_SETTING_1_CP_PRIORITY (1L<<10)
+#define BNX2_DMA_WRITE_MASTER_SETTING_1_CP_CS_VLD (1L<<11)
+#define BNX2_DMA_WRITE_MASTER_SETTING_1_CP_TRAFFIC_CLASS (0x7L<<12)
+#define BNX2_DMA_WRITE_MASTER_SETTING_1_CP_PARAM_EN (1L<<15)
+
+#define BNX2_DMA_ARBITER 0x00000c20
+#define BNX2_DMA_ARBITER_NUM_READS (0x7L<<0)
+#define BNX2_DMA_ARBITER_WR_ARB_MODE (1L<<4)
+#define BNX2_DMA_ARBITER_WR_ARB_MODE_STRICT (0L<<4)
+#define BNX2_DMA_ARBITER_WR_ARB_MODE_RND_RBN (1L<<4)
+#define BNX2_DMA_ARBITER_RD_ARB_MODE (0x3L<<5)
+#define BNX2_DMA_ARBITER_RD_ARB_MODE_STRICT (0L<<5)
+#define BNX2_DMA_ARBITER_RD_ARB_MODE_RND_RBN (1L<<5)
+#define BNX2_DMA_ARBITER_RD_ARB_MODE_WGT_RND_RBN (2L<<5)
+#define BNX2_DMA_ARBITER_ALT_MODE_EN (1L<<8)
+#define BNX2_DMA_ARBITER_RR_MODE (1L<<9)
+#define BNX2_DMA_ARBITER_TIMER_MODE (1L<<10)
+#define BNX2_DMA_ARBITER_OUSTD_READ_REQ (0xfL<<12)
+
+#define BNX2_DMA_ARB_TIMERS 0x00000c24
+#define BNX2_DMA_ARB_TIMERS_RD_DRR_WAIT_TIME (0xffL<<0)
+#define BNX2_DMA_ARB_TIMERS_TM_MIN_TIMEOUT (0xffL<<12)
+#define BNX2_DMA_ARB_TIMERS_TM_MAX_TIMEOUT (0xfffL<<20)
+
+#define BNX2_DMA_DEBUG_VECT_PEEK 0x00000c2c
+#define BNX2_DMA_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+#define BNX2_DMA_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+#define BNX2_DMA_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+#define BNX2_DMA_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+#define BNX2_DMA_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+#define BNX2_DMA_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+#define BNX2_DMA_TAG_RAM_00 0x00000c30
+#define BNX2_DMA_TAG_RAM_00_CHANNEL (0xfL<<0)
+#define BNX2_DMA_TAG_RAM_00_MASTER (0x7L<<4)
+#define BNX2_DMA_TAG_RAM_00_MASTER_CTX (0L<<4)
+#define BNX2_DMA_TAG_RAM_00_MASTER_RBDC (1L<<4)
+#define BNX2_DMA_TAG_RAM_00_MASTER_TBDC (2L<<4)
+#define BNX2_DMA_TAG_RAM_00_MASTER_COM (3L<<4)
+#define BNX2_DMA_TAG_RAM_00_MASTER_CP (4L<<4)
+#define BNX2_DMA_TAG_RAM_00_MASTER_TDMA (5L<<4)
+#define BNX2_DMA_TAG_RAM_00_SWAP (0x3L<<7)
+#define BNX2_DMA_TAG_RAM_00_SWAP_CONFIG (0L<<7)
+#define BNX2_DMA_TAG_RAM_00_SWAP_DATA (1L<<7)
+#define BNX2_DMA_TAG_RAM_00_SWAP_CONTROL (2L<<7)
+#define BNX2_DMA_TAG_RAM_00_FUNCTION (1L<<9)
+#define BNX2_DMA_TAG_RAM_00_VALID (1L<<10)
+
+#define BNX2_DMA_TAG_RAM_01 0x00000c34
+#define BNX2_DMA_TAG_RAM_01_CHANNEL (0xfL<<0)
+#define BNX2_DMA_TAG_RAM_01_MASTER (0x7L<<4)
+#define BNX2_DMA_TAG_RAM_01_MASTER_CTX (0L<<4)
+#define BNX2_DMA_TAG_RAM_01_MASTER_RBDC (1L<<4)
+#define BNX2_DMA_TAG_RAM_01_MASTER_TBDC (2L<<4)
+#define BNX2_DMA_TAG_RAM_01_MASTER_COM (3L<<4)
+#define BNX2_DMA_TAG_RAM_01_MASTER_CP (4L<<4)
+#define BNX2_DMA_TAG_RAM_01_MASTER_TDMA (5L<<4)
+#define BNX2_DMA_TAG_RAM_01_SWAP (0x3L<<7)
+#define BNX2_DMA_TAG_RAM_01_SWAP_CONFIG (0L<<7)
+#define BNX2_DMA_TAG_RAM_01_SWAP_DATA (1L<<7)
+#define BNX2_DMA_TAG_RAM_01_SWAP_CONTROL (2L<<7)
+#define BNX2_DMA_TAG_RAM_01_FUNCTION (1L<<9)
+#define BNX2_DMA_TAG_RAM_01_VALID (1L<<10)
+
+#define BNX2_DMA_TAG_RAM_02 0x00000c38
+#define BNX2_DMA_TAG_RAM_02_CHANNEL (0xfL<<0)
+#define BNX2_DMA_TAG_RAM_02_MASTER (0x7L<<4)
+#define BNX2_DMA_TAG_RAM_02_MASTER_CTX (0L<<4)
+#define BNX2_DMA_TAG_RAM_02_MASTER_RBDC (1L<<4)
+#define BNX2_DMA_TAG_RAM_02_MASTER_TBDC (2L<<4)
+#define BNX2_DMA_TAG_RAM_02_MASTER_COM (3L<<4)
+#define BNX2_DMA_TAG_RAM_02_MASTER_CP (4L<<4)
+#define BNX2_DMA_TAG_RAM_02_MASTER_TDMA (5L<<4)
+#define BNX2_DMA_TAG_RAM_02_SWAP (0x3L<<7)
+#define BNX2_DMA_TAG_RAM_02_SWAP_CONFIG (0L<<7)
+#define BNX2_DMA_TAG_RAM_02_SWAP_DATA (1L<<7)
+#define BNX2_DMA_TAG_RAM_02_SWAP_CONTROL (2L<<7)
+#define BNX2_DMA_TAG_RAM_02_FUNCTION (1L<<9)
+#define BNX2_DMA_TAG_RAM_02_VALID (1L<<10)
+
+#define BNX2_DMA_TAG_RAM_03 0x00000c3c
+#define BNX2_DMA_TAG_RAM_03_CHANNEL (0xfL<<0)
+#define BNX2_DMA_TAG_RAM_03_MASTER (0x7L<<4)
+#define BNX2_DMA_TAG_RAM_03_MASTER_CTX (0L<<4)
+#define BNX2_DMA_TAG_RAM_03_MASTER_RBDC (1L<<4)
+#define BNX2_DMA_TAG_RAM_03_MASTER_TBDC (2L<<4)
+#define BNX2_DMA_TAG_RAM_03_MASTER_COM (3L<<4)
+#define BNX2_DMA_TAG_RAM_03_MASTER_CP (4L<<4)
+#define BNX2_DMA_TAG_RAM_03_MASTER_TDMA (5L<<4)
+#define BNX2_DMA_TAG_RAM_03_SWAP (0x3L<<7)
+#define BNX2_DMA_TAG_RAM_03_SWAP_CONFIG (0L<<7)
+#define BNX2_DMA_TAG_RAM_03_SWAP_DATA (1L<<7)
+#define BNX2_DMA_TAG_RAM_03_SWAP_CONTROL (2L<<7)
+#define BNX2_DMA_TAG_RAM_03_FUNCTION (1L<<9)
+#define BNX2_DMA_TAG_RAM_03_VALID (1L<<10)
+
+#define BNX2_DMA_TAG_RAM_04 0x00000c40
+#define BNX2_DMA_TAG_RAM_04_CHANNEL (0xfL<<0)
+#define BNX2_DMA_TAG_RAM_04_MASTER (0x7L<<4)
+#define BNX2_DMA_TAG_RAM_04_MASTER_CTX (0L<<4)
+#define BNX2_DMA_TAG_RAM_04_MASTER_RBDC (1L<<4)
+#define BNX2_DMA_TAG_RAM_04_MASTER_TBDC (2L<<4)
+#define BNX2_DMA_TAG_RAM_04_MASTER_COM (3L<<4)
+#define BNX2_DMA_TAG_RAM_04_MASTER_CP (4L<<4)
+#define BNX2_DMA_TAG_RAM_04_MASTER_TDMA (5L<<4)
+#define BNX2_DMA_TAG_RAM_04_SWAP (0x3L<<7)
+#define BNX2_DMA_TAG_RAM_04_SWAP_CONFIG (0L<<7)
+#define BNX2_DMA_TAG_RAM_04_SWAP_DATA (1L<<7)
+#define BNX2_DMA_TAG_RAM_04_SWAP_CONTROL (2L<<7)
+#define BNX2_DMA_TAG_RAM_04_FUNCTION (1L<<9)
+#define BNX2_DMA_TAG_RAM_04_VALID (1L<<10)
+
+#define BNX2_DMA_TAG_RAM_05 0x00000c44
+#define BNX2_DMA_TAG_RAM_05_CHANNEL (0xfL<<0)
+#define BNX2_DMA_TAG_RAM_05_MASTER (0x7L<<4)
+#define BNX2_DMA_TAG_RAM_05_MASTER_CTX (0L<<4)
+#define BNX2_DMA_TAG_RAM_05_MASTER_RBDC (1L<<4)
+#define BNX2_DMA_TAG_RAM_05_MASTER_TBDC (2L<<4)
+#define BNX2_DMA_TAG_RAM_05_MASTER_COM (3L<<4)
+#define BNX2_DMA_TAG_RAM_05_MASTER_CP (4L<<4)
+#define BNX2_DMA_TAG_RAM_05_MASTER_TDMA (5L<<4)
+#define BNX2_DMA_TAG_RAM_05_SWAP (0x3L<<7)
+#define BNX2_DMA_TAG_RAM_05_SWAP_CONFIG (0L<<7)
+#define BNX2_DMA_TAG_RAM_05_SWAP_DATA (1L<<7)
+#define BNX2_DMA_TAG_RAM_05_SWAP_CONTROL (2L<<7)
+#define BNX2_DMA_TAG_RAM_05_FUNCTION (1L<<9)
+#define BNX2_DMA_TAG_RAM_05_VALID (1L<<10)
+
+#define BNX2_DMA_TAG_RAM_06 0x00000c48
+#define BNX2_DMA_TAG_RAM_06_CHANNEL (0xfL<<0)
+#define BNX2_DMA_TAG_RAM_06_MASTER (0x7L<<4)
+#define BNX2_DMA_TAG_RAM_06_MASTER_CTX (0L<<4)
+#define BNX2_DMA_TAG_RAM_06_MASTER_RBDC (1L<<4)
+#define BNX2_DMA_TAG_RAM_06_MASTER_TBDC (2L<<4)
+#define BNX2_DMA_TAG_RAM_06_MASTER_COM (3L<<4)
+#define BNX2_DMA_TAG_RAM_06_MASTER_CP (4L<<4)
+#define BNX2_DMA_TAG_RAM_06_MASTER_TDMA (5L<<4)
+#define BNX2_DMA_TAG_RAM_06_SWAP (0x3L<<7)
+#define BNX2_DMA_TAG_RAM_06_SWAP_CONFIG (0L<<7)
+#define BNX2_DMA_TAG_RAM_06_SWAP_DATA (1L<<7)
+#define BNX2_DMA_TAG_RAM_06_SWAP_CONTROL (2L<<7)
+#define BNX2_DMA_TAG_RAM_06_FUNCTION (1L<<9)
+#define BNX2_DMA_TAG_RAM_06_VALID (1L<<10)
+
+#define BNX2_DMA_TAG_RAM_07 0x00000c4c
+#define BNX2_DMA_TAG_RAM_07_CHANNEL (0xfL<<0)
+#define BNX2_DMA_TAG_RAM_07_MASTER (0x7L<<4)
+#define BNX2_DMA_TAG_RAM_07_MASTER_CTX (0L<<4)
+#define BNX2_DMA_TAG_RAM_07_MASTER_RBDC (1L<<4)
+#define BNX2_DMA_TAG_RAM_07_MASTER_TBDC (2L<<4)
+#define BNX2_DMA_TAG_RAM_07_MASTER_COM (3L<<4)
+#define BNX2_DMA_TAG_RAM_07_MASTER_CP (4L<<4)
+#define BNX2_DMA_TAG_RAM_07_MASTER_TDMA (5L<<4)
+#define BNX2_DMA_TAG_RAM_07_SWAP (0x3L<<7)
+#define BNX2_DMA_TAG_RAM_07_SWAP_CONFIG (0L<<7)
+#define BNX2_DMA_TAG_RAM_07_SWAP_DATA (1L<<7)
+#define BNX2_DMA_TAG_RAM_07_SWAP_CONTROL (2L<<7)
+#define BNX2_DMA_TAG_RAM_07_FUNCTION (1L<<9)
+#define BNX2_DMA_TAG_RAM_07_VALID (1L<<10)
+
+#define BNX2_DMA_TAG_RAM_08 0x00000c50
+#define BNX2_DMA_TAG_RAM_08_CHANNEL (0xfL<<0)
+#define BNX2_DMA_TAG_RAM_08_MASTER (0x7L<<4)
+#define BNX2_DMA_TAG_RAM_08_MASTER_CTX (0L<<4)
+#define BNX2_DMA_TAG_RAM_08_MASTER_RBDC (1L<<4)
+#define BNX2_DMA_TAG_RAM_08_MASTER_TBDC (2L<<4)
+#define BNX2_DMA_TAG_RAM_08_MASTER_COM (3L<<4)
+#define BNX2_DMA_TAG_RAM_08_MASTER_CP (4L<<4)
+#define BNX2_DMA_TAG_RAM_08_MASTER_TDMA (5L<<4)
+#define BNX2_DMA_TAG_RAM_08_SWAP (0x3L<<7)
+#define BNX2_DMA_TAG_RAM_08_SWAP_CONFIG (0L<<7)
+#define BNX2_DMA_TAG_RAM_08_SWAP_DATA (1L<<7)
+#define BNX2_DMA_TAG_RAM_08_SWAP_CONTROL (2L<<7)
+#define BNX2_DMA_TAG_RAM_08_FUNCTION (1L<<9)
+#define BNX2_DMA_TAG_RAM_08_VALID (1L<<10)
+
+#define BNX2_DMA_TAG_RAM_09 0x00000c54
+#define BNX2_DMA_TAG_RAM_09_CHANNEL (0xfL<<0)
+#define BNX2_DMA_TAG_RAM_09_MASTER (0x7L<<4)
+#define BNX2_DMA_TAG_RAM_09_MASTER_CTX (0L<<4)
+#define BNX2_DMA_TAG_RAM_09_MASTER_RBDC (1L<<4)
+#define BNX2_DMA_TAG_RAM_09_MASTER_TBDC (2L<<4)
+#define BNX2_DMA_TAG_RAM_09_MASTER_COM (3L<<4)
+#define BNX2_DMA_TAG_RAM_09_MASTER_CP (4L<<4)
+#define BNX2_DMA_TAG_RAM_09_MASTER_TDMA (5L<<4)
+#define BNX2_DMA_TAG_RAM_09_SWAP (0x3L<<7)
+#define BNX2_DMA_TAG_RAM_09_SWAP_CONFIG (0L<<7)
+#define BNX2_DMA_TAG_RAM_09_SWAP_DATA (1L<<7)
+#define BNX2_DMA_TAG_RAM_09_SWAP_CONTROL (2L<<7)
+#define BNX2_DMA_TAG_RAM_09_FUNCTION (1L<<9)
+#define BNX2_DMA_TAG_RAM_09_VALID (1L<<10)
+
+#define BNX2_DMA_TAG_RAM_10 0x00000c58
+#define BNX2_DMA_TAG_RAM_10_CHANNEL (0xfL<<0)
+#define BNX2_DMA_TAG_RAM_10_MASTER (0x7L<<4)
+#define BNX2_DMA_TAG_RAM_10_MASTER_CTX (0L<<4)
+#define BNX2_DMA_TAG_RAM_10_MASTER_RBDC (1L<<4)
+#define BNX2_DMA_TAG_RAM_10_MASTER_TBDC (2L<<4)
+#define BNX2_DMA_TAG_RAM_10_MASTER_COM (3L<<4)
+#define BNX2_DMA_TAG_RAM_10_MASTER_CP (4L<<4)
+#define BNX2_DMA_TAG_RAM_10_MASTER_TDMA (5L<<4)
+#define BNX2_DMA_TAG_RAM_10_SWAP (0x3L<<7)
+#define BNX2_DMA_TAG_RAM_10_SWAP_CONFIG (0L<<7)
+#define BNX2_DMA_TAG_RAM_10_SWAP_DATA (1L<<7)
+#define BNX2_DMA_TAG_RAM_10_SWAP_CONTROL (2L<<7)
+#define BNX2_DMA_TAG_RAM_10_FUNCTION (1L<<9)
+#define BNX2_DMA_TAG_RAM_10_VALID (1L<<10)
+
+#define BNX2_DMA_TAG_RAM_11 0x00000c5c
+#define BNX2_DMA_TAG_RAM_11_CHANNEL (0xfL<<0)
+#define BNX2_DMA_TAG_RAM_11_MASTER (0x7L<<4)
+#define BNX2_DMA_TAG_RAM_11_MASTER_CTX (0L<<4)
+#define BNX2_DMA_TAG_RAM_11_MASTER_RBDC (1L<<4)
+#define BNX2_DMA_TAG_RAM_11_MASTER_TBDC (2L<<4)
+#define BNX2_DMA_TAG_RAM_11_MASTER_COM (3L<<4)
+#define BNX2_DMA_TAG_RAM_11_MASTER_CP (4L<<4)
+#define BNX2_DMA_TAG_RAM_11_MASTER_TDMA (5L<<4)
+#define BNX2_DMA_TAG_RAM_11_SWAP (0x3L<<7)
+#define BNX2_DMA_TAG_RAM_11_SWAP_CONFIG (0L<<7)
+#define BNX2_DMA_TAG_RAM_11_SWAP_DATA (1L<<7)
+#define BNX2_DMA_TAG_RAM_11_SWAP_CONTROL (2L<<7)
+#define BNX2_DMA_TAG_RAM_11_FUNCTION (1L<<9)
+#define BNX2_DMA_TAG_RAM_11_VALID (1L<<10)
+
#define BNX2_DMA_RCHAN_STAT_22 0x00000c60
#define BNX2_DMA_RCHAN_STAT_30 0x00000c64
#define BNX2_DMA_RCHAN_STAT_31 0x00000c68
@@ -1336,6 +2345,25 @@ struct l2_fhdr {
*/
#define BNX2_CTX_COMMAND 0x00001000
#define BNX2_CTX_COMMAND_ENABLED (1L<<0)
+#define BNX2_CTX_COMMAND_DISABLE_USAGE_CNT (1L<<1)
+#define BNX2_CTX_COMMAND_DISABLE_PLRU (1L<<2)
+#define BNX2_CTX_COMMAND_DISABLE_COMBINE_READ (1L<<3)
+#define BNX2_CTX_COMMAND_FLUSH_AHEAD (0x1fL<<8)
+#define BNX2_CTX_COMMAND_MEM_INIT (1L<<13)
+#define BNX2_CTX_COMMAND_PAGE_SIZE (0xfL<<16)
+#define BNX2_CTX_COMMAND_PAGE_SIZE_256 (0L<<16)
+#define BNX2_CTX_COMMAND_PAGE_SIZE_512 (1L<<16)
+#define BNX2_CTX_COMMAND_PAGE_SIZE_1K (2L<<16)
+#define BNX2_CTX_COMMAND_PAGE_SIZE_2K (3L<<16)
+#define BNX2_CTX_COMMAND_PAGE_SIZE_4K (4L<<16)
+#define BNX2_CTX_COMMAND_PAGE_SIZE_8K (5L<<16)
+#define BNX2_CTX_COMMAND_PAGE_SIZE_16K (6L<<16)
+#define BNX2_CTX_COMMAND_PAGE_SIZE_32K (7L<<16)
+#define BNX2_CTX_COMMAND_PAGE_SIZE_64K (8L<<16)
+#define BNX2_CTX_COMMAND_PAGE_SIZE_128K (9L<<16)
+#define BNX2_CTX_COMMAND_PAGE_SIZE_256K (10L<<16)
+#define BNX2_CTX_COMMAND_PAGE_SIZE_512K (11L<<16)
+#define BNX2_CTX_COMMAND_PAGE_SIZE_1M (12L<<16)
#define BNX2_CTX_STATUS 0x00001004
#define BNX2_CTX_STATUS_LOCK_WAIT (1L<<0)
@@ -1343,6 +2371,13 @@ struct l2_fhdr {
#define BNX2_CTX_STATUS_WRITE_STAT (1L<<17)
#define BNX2_CTX_STATUS_ACC_STALL_STAT (1L<<18)
#define BNX2_CTX_STATUS_LOCK_STALL_STAT (1L<<19)
+#define BNX2_CTX_STATUS_EXT_READ_STAT (1L<<20)
+#define BNX2_CTX_STATUS_EXT_WRITE_STAT (1L<<21)
+#define BNX2_CTX_STATUS_MISS_STAT (1L<<22)
+#define BNX2_CTX_STATUS_HIT_STAT (1L<<23)
+#define BNX2_CTX_STATUS_DEAD_LOCK (1L<<24)
+#define BNX2_CTX_STATUS_USAGE_CNT_ERR (1L<<25)
+#define BNX2_CTX_STATUS_INVALID_PAGE (1L<<26)
#define BNX2_CTX_VIRT_ADDR 0x00001008
#define BNX2_CTX_VIRT_ADDR_VIRT_ADDR (0x7fffL<<6)
@@ -1357,10 +2392,15 @@ struct l2_fhdr {
#define BNX2_CTX_LOCK 0x00001018
#define BNX2_CTX_LOCK_TYPE (0x7L<<0)
#define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_VOID (0x0L<<0)
-#define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_COMPLETE (0x7L<<0)
#define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_PROTOCOL (0x1L<<0)
#define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_TX (0x2L<<0)
#define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_TIMER (0x4L<<0)
+#define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_COMPLETE (0x7L<<0)
+#define BNX2_CTX_LOCK_TYPE_VOID_XI (0L<<0)
+#define BNX2_CTX_LOCK_TYPE_PROTOCOL_XI (1L<<0)
+#define BNX2_CTX_LOCK_TYPE_TX_XI (2L<<0)
+#define BNX2_CTX_LOCK_TYPE_TIMER_XI (4L<<0)
+#define BNX2_CTX_LOCK_TYPE_COMPLETE_XI (7L<<0)
#define BNX2_CTX_LOCK_CID_VALUE (0x3fffL<<7)
#define BNX2_CTX_LOCK_GRANTED (1L<<26)
#define BNX2_CTX_LOCK_MODE (0x7L<<27)
@@ -1370,21 +2410,89 @@ struct l2_fhdr {
#define BNX2_CTX_LOCK_STATUS (1L<<30)
#define BNX2_CTX_LOCK_REQ (1L<<31)
+#define BNX2_CTX_CTX_CTRL 0x0000101c
+#define BNX2_CTX_CTX_CTRL_CTX_ADDR (0x7ffffL<<2)
+#define BNX2_CTX_CTX_CTRL_MOD_USAGE_CNT (0x3L<<21)
+#define BNX2_CTX_CTX_CTRL_NO_RAM_ACC (1L<<23)
+#define BNX2_CTX_CTX_CTRL_PREFETCH_SIZE (0x3L<<24)
+#define BNX2_CTX_CTX_CTRL_ATTR (1L<<26)
+#define BNX2_CTX_CTX_CTRL_WRITE_REQ (1L<<30)
+#define BNX2_CTX_CTX_CTRL_READ_REQ (1L<<31)
+
+#define BNX2_CTX_CTX_DATA 0x00001020
#define BNX2_CTX_ACCESS_STATUS 0x00001040
#define BNX2_CTX_ACCESS_STATUS_MASTERENCODED (0xfL<<0)
#define BNX2_CTX_ACCESS_STATUS_ACCESSMEMORYSM (0x3L<<10)
#define BNX2_CTX_ACCESS_STATUS_PAGETABLEINITSM (0x3L<<12)
#define BNX2_CTX_ACCESS_STATUS_ACCESSMEMORYINITSM (0x3L<<14)
#define BNX2_CTX_ACCESS_STATUS_QUALIFIED_REQUEST (0x7ffL<<17)
+#define BNX2_CTX_ACCESS_STATUS_CAMMASTERENCODED_XI (0x1fL<<0)
+#define BNX2_CTX_ACCESS_STATUS_CACHEMASTERENCODED_XI (0x1fL<<5)
+#define BNX2_CTX_ACCESS_STATUS_REQUEST_XI (0x3fffffL<<10)
#define BNX2_CTX_DBG_LOCK_STATUS 0x00001044
#define BNX2_CTX_DBG_LOCK_STATUS_SM (0x3ffL<<0)
#define BNX2_CTX_DBG_LOCK_STATUS_MATCH (0x3ffL<<22)
+#define BNX2_CTX_CACHE_CTRL_STATUS 0x00001048
+#define BNX2_CTX_CACHE_CTRL_STATUS_RFIFO_OVERFLOW (1L<<0)
+#define BNX2_CTX_CACHE_CTRL_STATUS_INVALID_READ_COMP (1L<<1)
+#define BNX2_CTX_CACHE_CTRL_STATUS_FLUSH_START (1L<<6)
+#define BNX2_CTX_CACHE_CTRL_STATUS_FREE_ENTRY_CNT (0x3fL<<7)
+#define BNX2_CTX_CACHE_CTRL_STATUS_CACHE_ENTRY_NEEDED (0x3fL<<13)
+#define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN0_ACTIVE (1L<<19)
+#define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN1_ACTIVE (1L<<20)
+#define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN2_ACTIVE (1L<<21)
+#define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN3_ACTIVE (1L<<22)
+#define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN4_ACTIVE (1L<<23)
+#define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN5_ACTIVE (1L<<24)
+#define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN6_ACTIVE (1L<<25)
+#define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN7_ACTIVE (1L<<26)
+#define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN8_ACTIVE (1L<<27)
+#define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN9_ACTIVE (1L<<28)
+#define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN10_ACTIVE (1L<<29)
+
+#define BNX2_CTX_CACHE_CTRL_SM_STATUS 0x0000104c
+#define BNX2_CTX_CACHE_CTRL_SM_STATUS_CS_DWC (0x7L<<0)
+#define BNX2_CTX_CACHE_CTRL_SM_STATUS_CS_WFIFOC (0x7L<<3)
+#define BNX2_CTX_CACHE_CTRL_SM_STATUS_CS_RTAGC (0x7L<<6)
+#define BNX2_CTX_CACHE_CTRL_SM_STATUS_CS_RFIFOC (0x7L<<9)
+#define BNX2_CTX_CACHE_CTRL_SM_STATUS_INVALID_BLK_ADDR (0x7fffL<<16)
+
+#define BNX2_CTX_CACHE_STATUS 0x00001050
+#define BNX2_CTX_CACHE_STATUS_HELD_ENTRIES (0x3ffL<<0)
+#define BNX2_CTX_CACHE_STATUS_MAX_HELD_ENTRIES (0x3ffL<<16)
+
+#define BNX2_CTX_DMA_STATUS 0x00001054
+#define BNX2_CTX_DMA_STATUS_RD_CHAN0_STATUS (0x3L<<0)
+#define BNX2_CTX_DMA_STATUS_RD_CHAN1_STATUS (0x3L<<2)
+#define BNX2_CTX_DMA_STATUS_RD_CHAN2_STATUS (0x3L<<4)
+#define BNX2_CTX_DMA_STATUS_RD_CHAN3_STATUS (0x3L<<6)
+#define BNX2_CTX_DMA_STATUS_RD_CHAN4_STATUS (0x3L<<8)
+#define BNX2_CTX_DMA_STATUS_RD_CHAN5_STATUS (0x3L<<10)
+#define BNX2_CTX_DMA_STATUS_RD_CHAN6_STATUS (0x3L<<12)
+#define BNX2_CTX_DMA_STATUS_RD_CHAN7_STATUS (0x3L<<14)
+#define BNX2_CTX_DMA_STATUS_RD_CHAN8_STATUS (0x3L<<16)
+#define BNX2_CTX_DMA_STATUS_RD_CHAN9_STATUS (0x3L<<18)
+#define BNX2_CTX_DMA_STATUS_RD_CHAN10_STATUS (0x3L<<20)
+
+#define BNX2_CTX_REP_STATUS 0x00001058
+#define BNX2_CTX_REP_STATUS_ERROR_ENTRY (0x3ffL<<0)
+#define BNX2_CTX_REP_STATUS_ERROR_CLIENT_ID (0x1fL<<10)
+#define BNX2_CTX_REP_STATUS_USAGE_CNT_MAX_ERR (1L<<16)
+#define BNX2_CTX_REP_STATUS_USAGE_CNT_MIN_ERR (1L<<17)
+#define BNX2_CTX_REP_STATUS_USAGE_CNT_MISS_ERR (1L<<18)
+
+#define BNX2_CTX_CKSUM_ERROR_STATUS 0x0000105c
+#define BNX2_CTX_CKSUM_ERROR_STATUS_CALCULATED (0xffffL<<0)
+#define BNX2_CTX_CKSUM_ERROR_STATUS_EXPECTED (0xffffL<<16)
+
#define BNX2_CTX_CHNL_LOCK_STATUS_0 0x00001080
#define BNX2_CTX_CHNL_LOCK_STATUS_0_CID (0x3fffL<<0)
#define BNX2_CTX_CHNL_LOCK_STATUS_0_TYPE (0x3L<<14)
#define BNX2_CTX_CHNL_LOCK_STATUS_0_MODE (1L<<16)
+#define BNX2_CTX_CHNL_LOCK_STATUS_0_MODE_XI (1L<<14)
+#define BNX2_CTX_CHNL_LOCK_STATUS_0_TYPE_XI (0x7L<<15)
#define BNX2_CTX_CHNL_LOCK_STATUS_1 0x00001084
#define BNX2_CTX_CHNL_LOCK_STATUS_2 0x00001088
@@ -1394,6 +2502,26 @@ struct l2_fhdr {
#define BNX2_CTX_CHNL_LOCK_STATUS_6 0x00001098
#define BNX2_CTX_CHNL_LOCK_STATUS_7 0x0000109c
#define BNX2_CTX_CHNL_LOCK_STATUS_8 0x000010a0
+#define BNX2_CTX_CHNL_LOCK_STATUS_9 0x000010a4
+
+#define BNX2_CTX_CACHE_DATA 0x000010c4
+#define BNX2_CTX_HOST_PAGE_TBL_CTRL 0x000010c8
+#define BNX2_CTX_HOST_PAGE_TBL_CTRL_PAGE_TBL_ADDR (0x1ffL<<0)
+#define BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ (1L<<30)
+#define BNX2_CTX_HOST_PAGE_TBL_CTRL_READ_REQ (1L<<31)
+
+#define BNX2_CTX_HOST_PAGE_TBL_DATA0 0x000010cc
+#define BNX2_CTX_HOST_PAGE_TBL_DATA0_VALID (1L<<0)
+#define BNX2_CTX_HOST_PAGE_TBL_DATA0_VALUE (0xffffffL<<8)
+
+#define BNX2_CTX_HOST_PAGE_TBL_DATA1 0x000010d0
+#define BNX2_CTX_CAM_CTRL 0x000010d4
+#define BNX2_CTX_CAM_CTRL_CAM_ADDR (0x3ffL<<0)
+#define BNX2_CTX_CAM_CTRL_RESET (1L<<27)
+#define BNX2_CTX_CAM_CTRL_INVALIDATE (1L<<28)
+#define BNX2_CTX_CAM_CTRL_SEARCH (1L<<29)
+#define BNX2_CTX_CAM_CTRL_WRITE_REQ (1L<<30)
+#define BNX2_CTX_CAM_CTRL_READ_REQ (1L<<31)
/*
@@ -1407,14 +2535,16 @@ struct l2_fhdr {
#define BNX2_EMAC_MODE_PORT_NONE (0L<<2)
#define BNX2_EMAC_MODE_PORT_MII (1L<<2)
#define BNX2_EMAC_MODE_PORT_GMII (2L<<2)
-#define BNX2_EMAC_MODE_PORT_MII_10 (3L<<2)
+#define BNX2_EMAC_MODE_PORT_MII_10M (3L<<2)
#define BNX2_EMAC_MODE_MAC_LOOP (1L<<4)
-#define BNX2_EMAC_MODE_25G (1L<<5)
+#define BNX2_EMAC_MODE_25G_MODE (1L<<5)
#define BNX2_EMAC_MODE_TAGGED_MAC_CTL (1L<<7)
#define BNX2_EMAC_MODE_TX_BURST (1L<<8)
#define BNX2_EMAC_MODE_MAX_DEFER_DROP_ENA (1L<<9)
#define BNX2_EMAC_MODE_EXT_LINK_POL (1L<<10)
#define BNX2_EMAC_MODE_FORCE_LINK (1L<<11)
+#define BNX2_EMAC_MODE_SERDES_MODE (1L<<12)
+#define BNX2_EMAC_MODE_BOND_OVRD (1L<<13)
#define BNX2_EMAC_MODE_MPKT (1L<<18)
#define BNX2_EMAC_MODE_MPKT_RCVD (1L<<19)
#define BNX2_EMAC_MODE_ACPI_RCVD (1L<<20)
@@ -1422,6 +2552,11 @@ struct l2_fhdr {
#define BNX2_EMAC_STATUS 0x00001404
#define BNX2_EMAC_STATUS_LINK (1L<<11)
#define BNX2_EMAC_STATUS_LINK_CHANGE (1L<<12)
+#define BNX2_EMAC_STATUS_SERDES_AUTONEG_COMPLETE (1L<<13)
+#define BNX2_EMAC_STATUS_SERDES_AUTONEG_CHANGE (1L<<14)
+#define BNX2_EMAC_STATUS_SERDES_NXT_PG_CHANGE (1L<<16)
+#define BNX2_EMAC_STATUS_SERDES_RX_CONFIG_IS_0 (1L<<17)
+#define BNX2_EMAC_STATUS_SERDES_RX_CONFIG_IS_0_CHANGE (1L<<18)
#define BNX2_EMAC_STATUS_MI_COMPLETE (1L<<22)
#define BNX2_EMAC_STATUS_MI_INT (1L<<23)
#define BNX2_EMAC_STATUS_AP_ERROR (1L<<24)
@@ -1429,6 +2564,9 @@ struct l2_fhdr {
#define BNX2_EMAC_ATTENTION_ENA 0x00001408
#define BNX2_EMAC_ATTENTION_ENA_LINK (1L<<11)
+#define BNX2_EMAC_ATTENTION_ENA_AUTONEG_CHANGE (1L<<14)
+#define BNX2_EMAC_ATTENTION_ENA_NXT_PG_CHANGE (1L<<16)
+#define BNX2_EMAC_ATTENTION_ENA_SERDES_RX_CONFIG_IS_0_CHANGE (1L<<18)
#define BNX2_EMAC_ATTENTION_ENA_MI_COMPLETE (1L<<22)
#define BNX2_EMAC_ATTENTION_ENA_MI_INT (1L<<23)
#define BNX2_EMAC_ATTENTION_ENA_AP_ERROR (1L<<24)
@@ -1445,6 +2583,13 @@ struct l2_fhdr {
#define BNX2_EMAC_LED_100MB (1L<<8)
#define BNX2_EMAC_LED_10MB (1L<<9)
#define BNX2_EMAC_LED_TRAFFIC_STAT (1L<<10)
+#define BNX2_EMAC_LED_2500MB (1L<<11)
+#define BNX2_EMAC_LED_2500MB_OVERRIDE (1L<<12)
+#define BNX2_EMAC_LED_ACTIVITY_SEL (0x3L<<17)
+#define BNX2_EMAC_LED_ACTIVITY_SEL_0 (0L<<17)
+#define BNX2_EMAC_LED_ACTIVITY_SEL_1 (1L<<17)
+#define BNX2_EMAC_LED_ACTIVITY_SEL_2 (2L<<17)
+#define BNX2_EMAC_LED_ACTIVITY_SEL_3 (3L<<17)
#define BNX2_EMAC_LED_BLNK_RATE (0xfffL<<19)
#define BNX2_EMAC_LED_BLNK_RATE_ENA (1L<<31)
@@ -1515,9 +2660,15 @@ struct l2_fhdr {
#define BNX2_EMAC_MDIO_COMM_PHY_ADDR (0x1fL<<21)
#define BNX2_EMAC_MDIO_COMM_COMMAND (0x3L<<26)
#define BNX2_EMAC_MDIO_COMM_COMMAND_UNDEFINED_0 (0L<<26)
+#define BNX2_EMAC_MDIO_COMM_COMMAND_ADDRESS (0L<<26)
#define BNX2_EMAC_MDIO_COMM_COMMAND_WRITE (1L<<26)
#define BNX2_EMAC_MDIO_COMM_COMMAND_READ (2L<<26)
+#define BNX2_EMAC_MDIO_COMM_COMMAND_WRITE_22_XI (1L<<26)
+#define BNX2_EMAC_MDIO_COMM_COMMAND_WRITE_45_XI (1L<<26)
+#define BNX2_EMAC_MDIO_COMM_COMMAND_READ_22_XI (2L<<26)
+#define BNX2_EMAC_MDIO_COMM_COMMAND_READ_INC_45_XI (2L<<26)
#define BNX2_EMAC_MDIO_COMM_COMMAND_UNDEFINED_3 (3L<<26)
+#define BNX2_EMAC_MDIO_COMM_COMMAND_READ_45 (3L<<26)
#define BNX2_EMAC_MDIO_COMM_FAIL (1L<<28)
#define BNX2_EMAC_MDIO_COMM_START_BUSY (1L<<29)
#define BNX2_EMAC_MDIO_COMM_DISEXT (1L<<30)
@@ -1534,13 +2685,17 @@ struct l2_fhdr {
#define BNX2_EMAC_MDIO_MODE_MDIO_OE (1L<<10)
#define BNX2_EMAC_MDIO_MODE_MDC (1L<<11)
#define BNX2_EMAC_MDIO_MODE_MDINT (1L<<12)
+#define BNX2_EMAC_MDIO_MODE_EXT_MDINT (1L<<13)
#define BNX2_EMAC_MDIO_MODE_CLOCK_CNT (0x1fL<<16)
+#define BNX2_EMAC_MDIO_MODE_CLOCK_CNT_XI (0x3fL<<16)
+#define BNX2_EMAC_MDIO_MODE_CLAUSE_45_XI (1L<<31)
#define BNX2_EMAC_MDIO_AUTO_STATUS 0x000014b8
#define BNX2_EMAC_MDIO_AUTO_STATUS_AUTO_ERR (1L<<0)
#define BNX2_EMAC_TX_MODE 0x000014bc
#define BNX2_EMAC_TX_MODE_RESET (1L<<0)
+#define BNX2_EMAC_TX_MODE_CS16_TEST (1L<<2)
#define BNX2_EMAC_TX_MODE_EXT_PAUSE_EN (1L<<3)
#define BNX2_EMAC_TX_MODE_FLOW_EN (1L<<4)
#define BNX2_EMAC_TX_MODE_BIG_BACKOFF (1L<<5)
@@ -1553,6 +2708,7 @@ struct l2_fhdr {
#define BNX2_EMAC_TX_STATUS_XON_SENT (1L<<2)
#define BNX2_EMAC_TX_STATUS_LINK_UP (1L<<3)
#define BNX2_EMAC_TX_STATUS_UNDERRUN (1L<<4)
+#define BNX2_EMAC_TX_STATUS_CS16_ERROR (1L<<5)
#define BNX2_EMAC_TX_LENGTHS 0x000014c4
#define BNX2_EMAC_TX_LENGTHS_SLOT (0xffL<<0)
@@ -1586,6 +2742,10 @@ struct l2_fhdr {
#define BNX2_EMAC_MULTICAST_HASH5 0x000014e4
#define BNX2_EMAC_MULTICAST_HASH6 0x000014e8
#define BNX2_EMAC_MULTICAST_HASH7 0x000014ec
+#define BNX2_EMAC_CKSUM_ERROR_STATUS 0x000014f0
+#define BNX2_EMAC_CKSUM_ERROR_STATUS_CALCULATED (0xffffL<<0)
+#define BNX2_EMAC_CKSUM_ERROR_STATUS_EXPECTED (0xffffL<<16)
+
#define BNX2_EMAC_RX_STAT_IFHCINOCTETS 0x00001500
#define BNX2_EMAC_RX_STAT_IFHCINBADOCTETS 0x00001504
#define BNX2_EMAC_RX_STAT_ETHERSTATSFRAGMENTS 0x00001508
@@ -1608,7 +2768,7 @@ struct l2_fhdr {
#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS256OCTETSTO511OCTETS 0x0000154c
#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS512OCTETSTO1023OCTETS 0x00001550
#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS1024OCTETSTO1522OCTETS 0x00001554
-#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS1523OCTETSTO9022OCTETS 0x00001558
+#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTSOVER1522OCTETS 0x00001558
#define BNX2_EMAC_RXMAC_DEBUG0 0x0000155c
#define BNX2_EMAC_RXMAC_DEBUG1 0x00001560
#define BNX2_EMAC_RXMAC_DEBUG1_LENGTH_NE_BYTE_COUNT (1L<<0)
@@ -1661,9 +2821,9 @@ struct l2_fhdr {
#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UMAC2 (0x1L<<16)
#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UMAC3 (0x2L<<16)
#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UNI (0x3L<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MMAC2 (0x7L<<16)
#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MMAC3 (0x5L<<16)
#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PSA1 (0x6L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MMAC2 (0x7L<<16)
#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PSA2 (0x7L<<16)
#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PSA3 (0x8L<<16)
#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MC2 (0x9L<<16)
@@ -1701,7 +2861,7 @@ struct l2_fhdr {
#define BNX2_EMAC_RXMAC_DEBUG4_SLOT_FILLED (1L<<23)
#define BNX2_EMAC_RXMAC_DEBUG4_FALSE_CARRIER (1L<<24)
#define BNX2_EMAC_RXMAC_DEBUG4_LAST_DATA (1L<<25)
-#define BNX2_EMAC_RXMAC_DEBUG4_sfd_FOUND (1L<<26)
+#define BNX2_EMAC_RXMAC_DEBUG4_SFD_FOUND (1L<<26)
#define BNX2_EMAC_RXMAC_DEBUG4_ADVANCE (1L<<27)
#define BNX2_EMAC_RXMAC_DEBUG4_START (1L<<28)
@@ -1733,6 +2893,7 @@ struct l2_fhdr {
#define BNX2_EMAC_RXMAC_DEBUG5_IDI_RPM_ACCEPT (1L<<19)
#define BNX2_EMAC_RXMAC_DEBUG5_FMLEN (0xfffL<<20)
+#define BNX2_EMAC_RX_STAT_FALSECARRIERERRORS 0x00001574
#define BNX2_EMAC_RX_STAT_AC0 0x00001580
#define BNX2_EMAC_RX_STAT_AC1 0x00001584
#define BNX2_EMAC_RX_STAT_AC2 0x00001588
@@ -1757,6 +2918,7 @@ struct l2_fhdr {
#define BNX2_EMAC_RX_STAT_AC21 0x000015d4
#define BNX2_EMAC_RX_STAT_AC22 0x000015d8
#define BNX2_EMAC_RXMAC_SUC_DBG_OVERRUNVEC 0x000015dc
+#define BNX2_EMAC_RX_STAT_AC_28 0x000015f4
#define BNX2_EMAC_TX_STAT_IFHCOUTOCTETS 0x00001600
#define BNX2_EMAC_TX_STAT_IFHCOUTBADOCTETS 0x00001604
#define BNX2_EMAC_TX_STAT_ETHERSTATSCOLLISIONS 0x00001608
@@ -1777,7 +2939,7 @@ struct l2_fhdr {
#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS256OCTETSTO511OCTETS 0x00001644
#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS512OCTETSTO1023OCTETS 0x00001648
#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS1024OCTETSTO1522OCTETS 0x0000164c
-#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS1523OCTETSTO9022OCTETS 0x00001650
+#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTSOVER1522OCTETS 0x00001650
#define BNX2_EMAC_TX_STAT_DOT3STATSINTERNALMACTRANSMITERRORS 0x00001654
#define BNX2_EMAC_TXMAC_DEBUG0 0x00001658
#define BNX2_EMAC_TXMAC_DEBUG1 0x0000165c
@@ -1843,16 +3005,16 @@ struct l2_fhdr {
#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_IDLE (0x0L<<16)
#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_MCA1 (0x2L<<16)
#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_MCA2 (0x3L<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_SRC3 (0x4L<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_SRC2 (0x5L<<16)
#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_MCA3 (0x6L<<16)
#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_SRC1 (0x7L<<16)
-#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_SRC2 (0x5L<<16)
-#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_SRC3 (0x4L<<16)
-#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_TYPE (0xcL<<16)
-#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_CMD (0xeL<<16)
-#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_TIME (0xaL<<16)
#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_CRC1 (0x8L<<16)
#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_CRC2 (0x9L<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_TIME (0xaL<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_TYPE (0xcL<<16)
#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_WAIT (0xdL<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_CMD (0xeL<<16)
#define BNX2_EMAC_TXMAC_DEBUG4_STATS0_VALID (1L<<20)
#define BNX2_EMAC_TXMAC_DEBUG4_APPEND_CRC (1L<<21)
#define BNX2_EMAC_TXMAC_DEBUG4_SLOT_FILLED (1L<<22)
@@ -1887,8 +3049,11 @@ struct l2_fhdr {
#define BNX2_EMAC_TX_STAT_AC18 0x000016c8
#define BNX2_EMAC_TX_STAT_AC19 0x000016cc
#define BNX2_EMAC_TX_STAT_AC20 0x000016d0
-#define BNX2_EMAC_TX_STAT_AC21 0x000016d4
#define BNX2_EMAC_TXMAC_SUC_DBG_OVERRUNVEC 0x000016d8
+#define BNX2_EMAC_TX_RATE_LIMIT_CTRL 0x000016fc
+#define BNX2_EMAC_TX_RATE_LIMIT_CTRL_TX_THROTTLE_INC (0x7fL<<0)
+#define BNX2_EMAC_TX_RATE_LIMIT_CTRL_TX_THROTTLE_NUM (0x7fL<<16)
+#define BNX2_EMAC_TX_RATE_LIMIT_CTRL_RATE_LIMITER_EN (1L<<31)
/*
@@ -1909,8 +3074,15 @@ struct l2_fhdr {
#define BNX2_RPM_CONFIG_ACPI_KEEP (1L<<2)
#define BNX2_RPM_CONFIG_MP_KEEP (1L<<3)
#define BNX2_RPM_CONFIG_SORT_VECT_VAL (0xfL<<4)
+#define BNX2_RPM_CONFIG_DISABLE_WOL_ASSERT (1L<<30)
#define BNX2_RPM_CONFIG_IGNORE_VLAN (1L<<31)
+#define BNX2_RPM_MGMT_PKT_CTRL 0x0000180c
+#define BNX2_RPM_MGMT_PKT_CTRL_MGMT_SORT (0xfL<<0)
+#define BNX2_RPM_MGMT_PKT_CTRL_MGMT_RULE (0xfL<<4)
+#define BNX2_RPM_MGMT_PKT_CTRL_MGMT_DISCARD_EN (1L<<30)
+#define BNX2_RPM_MGMT_PKT_CTRL_MGMT_EN (1L<<31)
+
#define BNX2_RPM_VLAN_MATCH0 0x00001810
#define BNX2_RPM_VLAN_MATCH0_RPM_VLAN_MTCH0_VALUE (0xfffL<<0)
@@ -1931,6 +3103,7 @@ struct l2_fhdr {
#define BNX2_RPM_SORT_USER0_PROM_EN (1L<<19)
#define BNX2_RPM_SORT_USER0_VLAN_EN (0xfL<<20)
#define BNX2_RPM_SORT_USER0_PROM_VLAN (1L<<24)
+#define BNX2_RPM_SORT_USER0_VLAN_NOTMATCH (1L<<25)
#define BNX2_RPM_SORT_USER0_ENA (1L<<31)
#define BNX2_RPM_SORT_USER1 0x00001824
@@ -1968,11 +3141,187 @@ struct l2_fhdr {
#define BNX2_RPM_STAT_IFINFTQDISCARDS 0x00001848
#define BNX2_RPM_STAT_IFINMBUFDISCARD 0x0000184c
#define BNX2_RPM_STAT_RULE_CHECKER_P4_HIT 0x00001850
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION0 0x00001854
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION0_NEXT_HEADER_LEN (0xffL<<0)
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION0_NEXT_HEADER (0xffL<<16)
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION0_NEXT_HEADER_LEN_TYPE (1L<<30)
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION0_NEXT_HEADER_EN (1L<<31)
+
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION1 0x00001858
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION1_NEXT_HEADER_LEN (0xffL<<0)
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION1_NEXT_HEADER (0xffL<<16)
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION1_NEXT_HEADER_LEN_TYPE (1L<<30)
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION1_NEXT_HEADER_EN (1L<<31)
+
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION2 0x0000185c
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION2_NEXT_HEADER_LEN (0xffL<<0)
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION2_NEXT_HEADER (0xffL<<16)
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION2_NEXT_HEADER_LEN_TYPE (1L<<30)
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION2_NEXT_HEADER_EN (1L<<31)
+
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION3 0x00001860
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION3_NEXT_HEADER_LEN (0xffL<<0)
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION3_NEXT_HEADER (0xffL<<16)
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION3_NEXT_HEADER_LEN_TYPE (1L<<30)
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION3_NEXT_HEADER_EN (1L<<31)
+
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION4 0x00001864
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION4_NEXT_HEADER_LEN (0xffL<<0)
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION4_NEXT_HEADER (0xffL<<16)
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION4_NEXT_HEADER_LEN_TYPE (1L<<30)
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION4_NEXT_HEADER_EN (1L<<31)
+
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION5 0x00001868
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION5_NEXT_HEADER_LEN (0xffL<<0)
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION5_NEXT_HEADER (0xffL<<16)
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION5_NEXT_HEADER_LEN_TYPE (1L<<30)
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION5_NEXT_HEADER_EN (1L<<31)
+
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION6 0x0000186c
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION6_NEXT_HEADER_LEN (0xffL<<0)
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION6_NEXT_HEADER (0xffL<<16)
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION6_NEXT_HEADER_LEN_TYPE (1L<<30)
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION6_NEXT_HEADER_EN (1L<<31)
+
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION7 0x00001870
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION7_NEXT_HEADER_LEN (0xffL<<0)
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION7_NEXT_HEADER (0xffL<<16)
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION7_NEXT_HEADER_LEN_TYPE (1L<<30)
+#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION7_NEXT_HEADER_EN (1L<<31)
+
#define BNX2_RPM_STAT_AC0 0x00001880
#define BNX2_RPM_STAT_AC1 0x00001884
#define BNX2_RPM_STAT_AC2 0x00001888
#define BNX2_RPM_STAT_AC3 0x0000188c
#define BNX2_RPM_STAT_AC4 0x00001890
+#define BNX2_RPM_RC_CNTL_16 0x000018e0
+#define BNX2_RPM_RC_CNTL_16_OFFSET (0xffL<<0)
+#define BNX2_RPM_RC_CNTL_16_CLASS (0x7L<<8)
+#define BNX2_RPM_RC_CNTL_16_PRIORITY (1L<<11)
+#define BNX2_RPM_RC_CNTL_16_P4 (1L<<12)
+#define BNX2_RPM_RC_CNTL_16_HDR_TYPE (0x7L<<13)
+#define BNX2_RPM_RC_CNTL_16_HDR_TYPE_START (0L<<13)
+#define BNX2_RPM_RC_CNTL_16_HDR_TYPE_IP (1L<<13)
+#define BNX2_RPM_RC_CNTL_16_HDR_TYPE_TCP (2L<<13)
+#define BNX2_RPM_RC_CNTL_16_HDR_TYPE_UDP (3L<<13)
+#define BNX2_RPM_RC_CNTL_16_HDR_TYPE_DATA (4L<<13)
+#define BNX2_RPM_RC_CNTL_16_HDR_TYPE_TCP_UDP (5L<<13)
+#define BNX2_RPM_RC_CNTL_16_HDR_TYPE_ICMPV6 (6L<<13)
+#define BNX2_RPM_RC_CNTL_16_COMP (0x3L<<16)
+#define BNX2_RPM_RC_CNTL_16_COMP_EQUAL (0L<<16)
+#define BNX2_RPM_RC_CNTL_16_COMP_NEQUAL (1L<<16)
+#define BNX2_RPM_RC_CNTL_16_COMP_GREATER (2L<<16)
+#define BNX2_RPM_RC_CNTL_16_COMP_LESS (3L<<16)
+#define BNX2_RPM_RC_CNTL_16_MAP (1L<<18)
+#define BNX2_RPM_RC_CNTL_16_SBIT (1L<<19)
+#define BNX2_RPM_RC_CNTL_16_CMDSEL (0x1fL<<20)
+#define BNX2_RPM_RC_CNTL_16_DISCARD (1L<<25)
+#define BNX2_RPM_RC_CNTL_16_MASK (1L<<26)
+#define BNX2_RPM_RC_CNTL_16_P1 (1L<<27)
+#define BNX2_RPM_RC_CNTL_16_P2 (1L<<28)
+#define BNX2_RPM_RC_CNTL_16_P3 (1L<<29)
+#define BNX2_RPM_RC_CNTL_16_NBIT (1L<<30)
+
+#define BNX2_RPM_RC_VALUE_MASK_16 0x000018e4
+#define BNX2_RPM_RC_VALUE_MASK_16_VALUE (0xffffL<<0)
+#define BNX2_RPM_RC_VALUE_MASK_16_MASK (0xffffL<<16)
+
+#define BNX2_RPM_RC_CNTL_17 0x000018e8
+#define BNX2_RPM_RC_CNTL_17_OFFSET (0xffL<<0)
+#define BNX2_RPM_RC_CNTL_17_CLASS (0x7L<<8)
+#define BNX2_RPM_RC_CNTL_17_PRIORITY (1L<<11)
+#define BNX2_RPM_RC_CNTL_17_P4 (1L<<12)
+#define BNX2_RPM_RC_CNTL_17_HDR_TYPE (0x7L<<13)
+#define BNX2_RPM_RC_CNTL_17_HDR_TYPE_START (0L<<13)
+#define BNX2_RPM_RC_CNTL_17_HDR_TYPE_IP (1L<<13)
+#define BNX2_RPM_RC_CNTL_17_HDR_TYPE_TCP (2L<<13)
+#define BNX2_RPM_RC_CNTL_17_HDR_TYPE_UDP (3L<<13)
+#define BNX2_RPM_RC_CNTL_17_HDR_TYPE_DATA (4L<<13)
+#define BNX2_RPM_RC_CNTL_17_HDR_TYPE_TCP_UDP (5L<<13)
+#define BNX2_RPM_RC_CNTL_17_HDR_TYPE_ICMPV6 (6L<<13)
+#define BNX2_RPM_RC_CNTL_17_COMP (0x3L<<16)
+#define BNX2_RPM_RC_CNTL_17_COMP_EQUAL (0L<<16)
+#define BNX2_RPM_RC_CNTL_17_COMP_NEQUAL (1L<<16)
+#define BNX2_RPM_RC_CNTL_17_COMP_GREATER (2L<<16)
+#define BNX2_RPM_RC_CNTL_17_COMP_LESS (3L<<16)
+#define BNX2_RPM_RC_CNTL_17_MAP (1L<<18)
+#define BNX2_RPM_RC_CNTL_17_SBIT (1L<<19)
+#define BNX2_RPM_RC_CNTL_17_CMDSEL (0x1fL<<20)
+#define BNX2_RPM_RC_CNTL_17_DISCARD (1L<<25)
+#define BNX2_RPM_RC_CNTL_17_MASK (1L<<26)
+#define BNX2_RPM_RC_CNTL_17_P1 (1L<<27)
+#define BNX2_RPM_RC_CNTL_17_P2 (1L<<28)
+#define BNX2_RPM_RC_CNTL_17_P3 (1L<<29)
+#define BNX2_RPM_RC_CNTL_17_NBIT (1L<<30)
+
+#define BNX2_RPM_RC_VALUE_MASK_17 0x000018ec
+#define BNX2_RPM_RC_VALUE_MASK_17_VALUE (0xffffL<<0)
+#define BNX2_RPM_RC_VALUE_MASK_17_MASK (0xffffL<<16)
+
+#define BNX2_RPM_RC_CNTL_18 0x000018f0
+#define BNX2_RPM_RC_CNTL_18_OFFSET (0xffL<<0)
+#define BNX2_RPM_RC_CNTL_18_CLASS (0x7L<<8)
+#define BNX2_RPM_RC_CNTL_18_PRIORITY (1L<<11)
+#define BNX2_RPM_RC_CNTL_18_P4 (1L<<12)
+#define BNX2_RPM_RC_CNTL_18_HDR_TYPE (0x7L<<13)
+#define BNX2_RPM_RC_CNTL_18_HDR_TYPE_START (0L<<13)
+#define BNX2_RPM_RC_CNTL_18_HDR_TYPE_IP (1L<<13)
+#define BNX2_RPM_RC_CNTL_18_HDR_TYPE_TCP (2L<<13)
+#define BNX2_RPM_RC_CNTL_18_HDR_TYPE_UDP (3L<<13)
+#define BNX2_RPM_RC_CNTL_18_HDR_TYPE_DATA (4L<<13)
+#define BNX2_RPM_RC_CNTL_18_HDR_TYPE_TCP_UDP (5L<<13)
+#define BNX2_RPM_RC_CNTL_18_HDR_TYPE_ICMPV6 (6L<<13)
+#define BNX2_RPM_RC_CNTL_18_COMP (0x3L<<16)
+#define BNX2_RPM_RC_CNTL_18_COMP_EQUAL (0L<<16)
+#define BNX2_RPM_RC_CNTL_18_COMP_NEQUAL (1L<<16)
+#define BNX2_RPM_RC_CNTL_18_COMP_GREATER (2L<<16)
+#define BNX2_RPM_RC_CNTL_18_COMP_LESS (3L<<16)
+#define BNX2_RPM_RC_CNTL_18_MAP (1L<<18)
+#define BNX2_RPM_RC_CNTL_18_SBIT (1L<<19)
+#define BNX2_RPM_RC_CNTL_18_CMDSEL (0x1fL<<20)
+#define BNX2_RPM_RC_CNTL_18_DISCARD (1L<<25)
+#define BNX2_RPM_RC_CNTL_18_MASK (1L<<26)
+#define BNX2_RPM_RC_CNTL_18_P1 (1L<<27)
+#define BNX2_RPM_RC_CNTL_18_P2 (1L<<28)
+#define BNX2_RPM_RC_CNTL_18_P3 (1L<<29)
+#define BNX2_RPM_RC_CNTL_18_NBIT (1L<<30)
+
+#define BNX2_RPM_RC_VALUE_MASK_18 0x000018f4
+#define BNX2_RPM_RC_VALUE_MASK_18_VALUE (0xffffL<<0)
+#define BNX2_RPM_RC_VALUE_MASK_18_MASK (0xffffL<<16)
+
+#define BNX2_RPM_RC_CNTL_19 0x000018f8
+#define BNX2_RPM_RC_CNTL_19_OFFSET (0xffL<<0)
+#define BNX2_RPM_RC_CNTL_19_CLASS (0x7L<<8)
+#define BNX2_RPM_RC_CNTL_19_PRIORITY (1L<<11)
+#define BNX2_RPM_RC_CNTL_19_P4 (1L<<12)
+#define BNX2_RPM_RC_CNTL_19_HDR_TYPE (0x7L<<13)
+#define BNX2_RPM_RC_CNTL_19_HDR_TYPE_START (0L<<13)
+#define BNX2_RPM_RC_CNTL_19_HDR_TYPE_IP (1L<<13)
+#define BNX2_RPM_RC_CNTL_19_HDR_TYPE_TCP (2L<<13)
+#define BNX2_RPM_RC_CNTL_19_HDR_TYPE_UDP (3L<<13)
+#define BNX2_RPM_RC_CNTL_19_HDR_TYPE_DATA (4L<<13)
+#define BNX2_RPM_RC_CNTL_19_HDR_TYPE_TCP_UDP (5L<<13)
+#define BNX2_RPM_RC_CNTL_19_HDR_TYPE_ICMPV6 (6L<<13)
+#define BNX2_RPM_RC_CNTL_19_COMP (0x3L<<16)
+#define BNX2_RPM_RC_CNTL_19_COMP_EQUAL (0L<<16)
+#define BNX2_RPM_RC_CNTL_19_COMP_NEQUAL (1L<<16)
+#define BNX2_RPM_RC_CNTL_19_COMP_GREATER (2L<<16)
+#define BNX2_RPM_RC_CNTL_19_COMP_LESS (3L<<16)
+#define BNX2_RPM_RC_CNTL_19_MAP (1L<<18)
+#define BNX2_RPM_RC_CNTL_19_SBIT (1L<<19)
+#define BNX2_RPM_RC_CNTL_19_CMDSEL (0x1fL<<20)
+#define BNX2_RPM_RC_CNTL_19_DISCARD (1L<<25)
+#define BNX2_RPM_RC_CNTL_19_MASK (1L<<26)
+#define BNX2_RPM_RC_CNTL_19_P1 (1L<<27)
+#define BNX2_RPM_RC_CNTL_19_P2 (1L<<28)
+#define BNX2_RPM_RC_CNTL_19_P3 (1L<<29)
+#define BNX2_RPM_RC_CNTL_19_NBIT (1L<<30)
+
+#define BNX2_RPM_RC_VALUE_MASK_19 0x000018fc
+#define BNX2_RPM_RC_VALUE_MASK_19_VALUE (0xffffL<<0)
+#define BNX2_RPM_RC_VALUE_MASK_19_MASK (0xffffL<<16)
+
#define BNX2_RPM_RC_CNTL_0 0x00001900
#define BNX2_RPM_RC_CNTL_0_OFFSET (0xffL<<0)
#define BNX2_RPM_RC_CNTL_0_CLASS (0x7L<<8)
@@ -1984,14 +3333,18 @@ struct l2_fhdr {
#define BNX2_RPM_RC_CNTL_0_HDR_TYPE_TCP (2L<<13)
#define BNX2_RPM_RC_CNTL_0_HDR_TYPE_UDP (3L<<13)
#define BNX2_RPM_RC_CNTL_0_HDR_TYPE_DATA (4L<<13)
+#define BNX2_RPM_RC_CNTL_0_HDR_TYPE_TCP_UDP (5L<<13)
+#define BNX2_RPM_RC_CNTL_0_HDR_TYPE_ICMPV6 (6L<<13)
#define BNX2_RPM_RC_CNTL_0_COMP (0x3L<<16)
#define BNX2_RPM_RC_CNTL_0_COMP_EQUAL (0L<<16)
#define BNX2_RPM_RC_CNTL_0_COMP_NEQUAL (1L<<16)
#define BNX2_RPM_RC_CNTL_0_COMP_GREATER (2L<<16)
#define BNX2_RPM_RC_CNTL_0_COMP_LESS (3L<<16)
+#define BNX2_RPM_RC_CNTL_0_MAP_XI (1L<<18)
#define BNX2_RPM_RC_CNTL_0_SBIT (1L<<19)
#define BNX2_RPM_RC_CNTL_0_CMDSEL (0xfL<<20)
#define BNX2_RPM_RC_CNTL_0_MAP (1L<<24)
+#define BNX2_RPM_RC_CNTL_0_CMDSEL_XI (0x1fL<<20)
#define BNX2_RPM_RC_CNTL_0_DISCARD (1L<<25)
#define BNX2_RPM_RC_CNTL_0_MASK (1L<<26)
#define BNX2_RPM_RC_CNTL_0_P1 (1L<<27)
@@ -2006,81 +3359,518 @@ struct l2_fhdr {
#define BNX2_RPM_RC_CNTL_1 0x00001908
#define BNX2_RPM_RC_CNTL_1_A (0x3ffffL<<0)
#define BNX2_RPM_RC_CNTL_1_B (0xfffL<<19)
+#define BNX2_RPM_RC_CNTL_1_OFFSET_XI (0xffL<<0)
+#define BNX2_RPM_RC_CNTL_1_CLASS_XI (0x7L<<8)
+#define BNX2_RPM_RC_CNTL_1_PRIORITY_XI (1L<<11)
+#define BNX2_RPM_RC_CNTL_1_P4_XI (1L<<12)
+#define BNX2_RPM_RC_CNTL_1_HDR_TYPE_XI (0x7L<<13)
+#define BNX2_RPM_RC_CNTL_1_HDR_TYPE_START_XI (0L<<13)
+#define BNX2_RPM_RC_CNTL_1_HDR_TYPE_IP_XI (1L<<13)
+#define BNX2_RPM_RC_CNTL_1_HDR_TYPE_TCP_XI (2L<<13)
+#define BNX2_RPM_RC_CNTL_1_HDR_TYPE_UDP_XI (3L<<13)
+#define BNX2_RPM_RC_CNTL_1_HDR_TYPE_DATA_XI (4L<<13)
+#define BNX2_RPM_RC_CNTL_1_HDR_TYPE_TCP_UDP_XI (5L<<13)
+#define BNX2_RPM_RC_CNTL_1_HDR_TYPE_ICMPV6_XI (6L<<13)
+#define BNX2_RPM_RC_CNTL_1_COMP_XI (0x3L<<16)
+#define BNX2_RPM_RC_CNTL_1_COMP_EQUAL_XI (0L<<16)
+#define BNX2_RPM_RC_CNTL_1_COMP_NEQUAL_XI (1L<<16)
+#define BNX2_RPM_RC_CNTL_1_COMP_GREATER_XI (2L<<16)
+#define BNX2_RPM_RC_CNTL_1_COMP_LESS_XI (3L<<16)
+#define BNX2_RPM_RC_CNTL_1_MAP_XI (1L<<18)
+#define BNX2_RPM_RC_CNTL_1_SBIT_XI (1L<<19)
+#define BNX2_RPM_RC_CNTL_1_CMDSEL_XI (0x1fL<<20)
+#define BNX2_RPM_RC_CNTL_1_DISCARD_XI (1L<<25)
+#define BNX2_RPM_RC_CNTL_1_MASK_XI (1L<<26)
+#define BNX2_RPM_RC_CNTL_1_P1_XI (1L<<27)
+#define BNX2_RPM_RC_CNTL_1_P2_XI (1L<<28)
+#define BNX2_RPM_RC_CNTL_1_P3_XI (1L<<29)
+#define BNX2_RPM_RC_CNTL_1_NBIT_XI (1L<<30)
#define BNX2_RPM_RC_VALUE_MASK_1 0x0000190c
+#define BNX2_RPM_RC_VALUE_MASK_1_VALUE (0xffffL<<0)
+#define BNX2_RPM_RC_VALUE_MASK_1_MASK (0xffffL<<16)
+
#define BNX2_RPM_RC_CNTL_2 0x00001910
#define BNX2_RPM_RC_CNTL_2_A (0x3ffffL<<0)
#define BNX2_RPM_RC_CNTL_2_B (0xfffL<<19)
+#define BNX2_RPM_RC_CNTL_2_OFFSET_XI (0xffL<<0)
+#define BNX2_RPM_RC_CNTL_2_CLASS_XI (0x7L<<8)
+#define BNX2_RPM_RC_CNTL_2_PRIORITY_XI (1L<<11)
+#define BNX2_RPM_RC_CNTL_2_P4_XI (1L<<12)
+#define BNX2_RPM_RC_CNTL_2_HDR_TYPE_XI (0x7L<<13)
+#define BNX2_RPM_RC_CNTL_2_HDR_TYPE_START_XI (0L<<13)
+#define BNX2_RPM_RC_CNTL_2_HDR_TYPE_IP_XI (1L<<13)
+#define BNX2_RPM_RC_CNTL_2_HDR_TYPE_TCP_XI (2L<<13)
+#define BNX2_RPM_RC_CNTL_2_HDR_TYPE_UDP_XI (3L<<13)
+#define BNX2_RPM_RC_CNTL_2_HDR_TYPE_DATA_XI (4L<<13)
+#define BNX2_RPM_RC_CNTL_2_HDR_TYPE_TCP_UDP_XI (5L<<13)
+#define BNX2_RPM_RC_CNTL_2_HDR_TYPE_ICMPV6_XI (6L<<13)
+#define BNX2_RPM_RC_CNTL_2_COMP_XI (0x3L<<16)
+#define BNX2_RPM_RC_CNTL_2_COMP_EQUAL_XI (0L<<16)
+#define BNX2_RPM_RC_CNTL_2_COMP_NEQUAL_XI (1L<<16)
+#define BNX2_RPM_RC_CNTL_2_COMP_GREATER_XI (2L<<16)
+#define BNX2_RPM_RC_CNTL_2_COMP_LESS_XI (3L<<16)
+#define BNX2_RPM_RC_CNTL_2_MAP_XI (1L<<18)
+#define BNX2_RPM_RC_CNTL_2_SBIT_XI (1L<<19)
+#define BNX2_RPM_RC_CNTL_2_CMDSEL_XI (0x1fL<<20)
+#define BNX2_RPM_RC_CNTL_2_DISCARD_XI (1L<<25)
+#define BNX2_RPM_RC_CNTL_2_MASK_XI (1L<<26)
+#define BNX2_RPM_RC_CNTL_2_P1_XI (1L<<27)
+#define BNX2_RPM_RC_CNTL_2_P2_XI (1L<<28)
+#define BNX2_RPM_RC_CNTL_2_P3_XI (1L<<29)
+#define BNX2_RPM_RC_CNTL_2_NBIT_XI (1L<<30)
#define BNX2_RPM_RC_VALUE_MASK_2 0x00001914
+#define BNX2_RPM_RC_VALUE_MASK_2_VALUE (0xffffL<<0)
+#define BNX2_RPM_RC_VALUE_MASK_2_MASK (0xffffL<<16)
+
#define BNX2_RPM_RC_CNTL_3 0x00001918
#define BNX2_RPM_RC_CNTL_3_A (0x3ffffL<<0)
#define BNX2_RPM_RC_CNTL_3_B (0xfffL<<19)
+#define BNX2_RPM_RC_CNTL_3_OFFSET_XI (0xffL<<0)
+#define BNX2_RPM_RC_CNTL_3_CLASS_XI (0x7L<<8)
+#define BNX2_RPM_RC_CNTL_3_PRIORITY_XI (1L<<11)
+#define BNX2_RPM_RC_CNTL_3_P4_XI (1L<<12)
+#define BNX2_RPM_RC_CNTL_3_HDR_TYPE_XI (0x7L<<13)
+#define BNX2_RPM_RC_CNTL_3_HDR_TYPE_START_XI (0L<<13)
+#define BNX2_RPM_RC_CNTL_3_HDR_TYPE_IP_XI (1L<<13)
+#define BNX2_RPM_RC_CNTL_3_HDR_TYPE_TCP_XI (2L<<13)
+#define BNX2_RPM_RC_CNTL_3_HDR_TYPE_UDP_XI (3L<<13)
+#define BNX2_RPM_RC_CNTL_3_HDR_TYPE_DATA_XI (4L<<13)
+#define BNX2_RPM_RC_CNTL_3_HDR_TYPE_TCP_UDP_XI (5L<<13)
+#define BNX2_RPM_RC_CNTL_3_HDR_TYPE_ICMPV6_XI (6L<<13)
+#define BNX2_RPM_RC_CNTL_3_COMP_XI (0x3L<<16)
+#define BNX2_RPM_RC_CNTL_3_COMP_EQUAL_XI (0L<<16)
+#define BNX2_RPM_RC_CNTL_3_COMP_NEQUAL_XI (1L<<16)
+#define BNX2_RPM_RC_CNTL_3_COMP_GREATER_XI (2L<<16)
+#define BNX2_RPM_RC_CNTL_3_COMP_LESS_XI (3L<<16)
+#define BNX2_RPM_RC_CNTL_3_MAP_XI (1L<<18)
+#define BNX2_RPM_RC_CNTL_3_SBIT_XI (1L<<19)
+#define BNX2_RPM_RC_CNTL_3_CMDSEL_XI (0x1fL<<20)
+#define BNX2_RPM_RC_CNTL_3_DISCARD_XI (1L<<25)
+#define BNX2_RPM_RC_CNTL_3_MASK_XI (1L<<26)
+#define BNX2_RPM_RC_CNTL_3_P1_XI (1L<<27)
+#define BNX2_RPM_RC_CNTL_3_P2_XI (1L<<28)
+#define BNX2_RPM_RC_CNTL_3_P3_XI (1L<<29)
+#define BNX2_RPM_RC_CNTL_3_NBIT_XI (1L<<30)
#define BNX2_RPM_RC_VALUE_MASK_3 0x0000191c
+#define BNX2_RPM_RC_VALUE_MASK_3_VALUE (0xffffL<<0)
+#define BNX2_RPM_RC_VALUE_MASK_3_MASK (0xffffL<<16)
+
#define BNX2_RPM_RC_CNTL_4 0x00001920
#define BNX2_RPM_RC_CNTL_4_A (0x3ffffL<<0)
#define BNX2_RPM_RC_CNTL_4_B (0xfffL<<19)
+#define BNX2_RPM_RC_CNTL_4_OFFSET_XI (0xffL<<0)
+#define BNX2_RPM_RC_CNTL_4_CLASS_XI (0x7L<<8)
+#define BNX2_RPM_RC_CNTL_4_PRIORITY_XI (1L<<11)
+#define BNX2_RPM_RC_CNTL_4_P4_XI (1L<<12)
+#define BNX2_RPM_RC_CNTL_4_HDR_TYPE_XI (0x7L<<13)
+#define BNX2_RPM_RC_CNTL_4_HDR_TYPE_START_XI (0L<<13)
+#define BNX2_RPM_RC_CNTL_4_HDR_TYPE_IP_XI (1L<<13)
+#define BNX2_RPM_RC_CNTL_4_HDR_TYPE_TCP_XI (2L<<13)
+#define BNX2_RPM_RC_CNTL_4_HDR_TYPE_UDP_XI (3L<<13)
+#define BNX2_RPM_RC_CNTL_4_HDR_TYPE_DATA_XI (4L<<13)
+#define BNX2_RPM_RC_CNTL_4_HDR_TYPE_TCP_UDP_XI (5L<<13)
+#define BNX2_RPM_RC_CNTL_4_HDR_TYPE_ICMPV6_XI (6L<<13)
+#define BNX2_RPM_RC_CNTL_4_COMP_XI (0x3L<<16)
+#define BNX2_RPM_RC_CNTL_4_COMP_EQUAL_XI (0L<<16)
+#define BNX2_RPM_RC_CNTL_4_COMP_NEQUAL_XI (1L<<16)
+#define BNX2_RPM_RC_CNTL_4_COMP_GREATER_XI (2L<<16)
+#define BNX2_RPM_RC_CNTL_4_COMP_LESS_XI (3L<<16)
+#define BNX2_RPM_RC_CNTL_4_MAP_XI (1L<<18)
+#define BNX2_RPM_RC_CNTL_4_SBIT_XI (1L<<19)
+#define BNX2_RPM_RC_CNTL_4_CMDSEL_XI (0x1fL<<20)
+#define BNX2_RPM_RC_CNTL_4_DISCARD_XI (1L<<25)
+#define BNX2_RPM_RC_CNTL_4_MASK_XI (1L<<26)
+#define BNX2_RPM_RC_CNTL_4_P1_XI (1L<<27)
+#define BNX2_RPM_RC_CNTL_4_P2_XI (1L<<28)
+#define BNX2_RPM_RC_CNTL_4_P3_XI (1L<<29)
+#define BNX2_RPM_RC_CNTL_4_NBIT_XI (1L<<30)
#define BNX2_RPM_RC_VALUE_MASK_4 0x00001924
+#define BNX2_RPM_RC_VALUE_MASK_4_VALUE (0xffffL<<0)
+#define BNX2_RPM_RC_VALUE_MASK_4_MASK (0xffffL<<16)
+
#define BNX2_RPM_RC_CNTL_5 0x00001928
#define BNX2_RPM_RC_CNTL_5_A (0x3ffffL<<0)
#define BNX2_RPM_RC_CNTL_5_B (0xfffL<<19)
+#define BNX2_RPM_RC_CNTL_5_OFFSET_XI (0xffL<<0)
+#define BNX2_RPM_RC_CNTL_5_CLASS_XI (0x7L<<8)
+#define BNX2_RPM_RC_CNTL_5_PRIORITY_XI (1L<<11)
+#define BNX2_RPM_RC_CNTL_5_P4_XI (1L<<12)
+#define BNX2_RPM_RC_CNTL_5_HDR_TYPE_XI (0x7L<<13)
+#define BNX2_RPM_RC_CNTL_5_HDR_TYPE_START_XI (0L<<13)
+#define BNX2_RPM_RC_CNTL_5_HDR_TYPE_IP_XI (1L<<13)
+#define BNX2_RPM_RC_CNTL_5_HDR_TYPE_TCP_XI (2L<<13)
+#define BNX2_RPM_RC_CNTL_5_HDR_TYPE_UDP_XI (3L<<13)
+#define BNX2_RPM_RC_CNTL_5_HDR_TYPE_DATA_XI (4L<<13)
+#define BNX2_RPM_RC_CNTL_5_HDR_TYPE_TCP_UDP_XI (5L<<13)
+#define BNX2_RPM_RC_CNTL_5_HDR_TYPE_ICMPV6_XI (6L<<13)
+#define BNX2_RPM_RC_CNTL_5_COMP_XI (0x3L<<16)
+#define BNX2_RPM_RC_CNTL_5_COMP_EQUAL_XI (0L<<16)
+#define BNX2_RPM_RC_CNTL_5_COMP_NEQUAL_XI (1L<<16)
+#define BNX2_RPM_RC_CNTL_5_COMP_GREATER_XI (2L<<16)
+#define BNX2_RPM_RC_CNTL_5_COMP_LESS_XI (3L<<16)
+#define BNX2_RPM_RC_CNTL_5_MAP_XI (1L<<18)
+#define BNX2_RPM_RC_CNTL_5_SBIT_XI (1L<<19)
+#define BNX2_RPM_RC_CNTL_5_CMDSEL_XI (0x1fL<<20)
+#define BNX2_RPM_RC_CNTL_5_DISCARD_XI (1L<<25)
+#define BNX2_RPM_RC_CNTL_5_MASK_XI (1L<<26)
+#define BNX2_RPM_RC_CNTL_5_P1_XI (1L<<27)
+#define BNX2_RPM_RC_CNTL_5_P2_XI (1L<<28)
+#define BNX2_RPM_RC_CNTL_5_P3_XI (1L<<29)
+#define BNX2_RPM_RC_CNTL_5_NBIT_XI (1L<<30)
#define BNX2_RPM_RC_VALUE_MASK_5 0x0000192c
+#define BNX2_RPM_RC_VALUE_MASK_5_VALUE (0xffffL<<0)
+#define BNX2_RPM_RC_VALUE_MASK_5_MASK (0xffffL<<16)
+
#define BNX2_RPM_RC_CNTL_6 0x00001930
#define BNX2_RPM_RC_CNTL_6_A (0x3ffffL<<0)
#define BNX2_RPM_RC_CNTL_6_B (0xfffL<<19)
+#define BNX2_RPM_RC_CNTL_6_OFFSET_XI (0xffL<<0)
+#define BNX2_RPM_RC_CNTL_6_CLASS_XI (0x7L<<8)
+#define BNX2_RPM_RC_CNTL_6_PRIORITY_XI (1L<<11)
+#define BNX2_RPM_RC_CNTL_6_P4_XI (1L<<12)
+#define BNX2_RPM_RC_CNTL_6_HDR_TYPE_XI (0x7L<<13)
+#define BNX2_RPM_RC_CNTL_6_HDR_TYPE_START_XI (0L<<13)
+#define BNX2_RPM_RC_CNTL_6_HDR_TYPE_IP_XI (1L<<13)
+#define BNX2_RPM_RC_CNTL_6_HDR_TYPE_TCP_XI (2L<<13)
+#define BNX2_RPM_RC_CNTL_6_HDR_TYPE_UDP_XI (3L<<13)
+#define BNX2_RPM_RC_CNTL_6_HDR_TYPE_DATA_XI (4L<<13)
+#define BNX2_RPM_RC_CNTL_6_HDR_TYPE_TCP_UDP_XI (5L<<13)
+#define BNX2_RPM_RC_CNTL_6_HDR_TYPE_ICMPV6_XI (6L<<13)
+#define BNX2_RPM_RC_CNTL_6_COMP_XI (0x3L<<16)
+#define BNX2_RPM_RC_CNTL_6_COMP_EQUAL_XI (0L<<16)
+#define BNX2_RPM_RC_CNTL_6_COMP_NEQUAL_XI (1L<<16)
+#define BNX2_RPM_RC_CNTL_6_COMP_GREATER_XI (2L<<16)
+#define BNX2_RPM_RC_CNTL_6_COMP_LESS_XI (3L<<16)
+#define BNX2_RPM_RC_CNTL_6_MAP_XI (1L<<18)
+#define BNX2_RPM_RC_CNTL_6_SBIT_XI (1L<<19)
+#define BNX2_RPM_RC_CNTL_6_CMDSEL_XI (0x1fL<<20)
+#define BNX2_RPM_RC_CNTL_6_DISCARD_XI (1L<<25)
+#define BNX2_RPM_RC_CNTL_6_MASK_XI (1L<<26)
+#define BNX2_RPM_RC_CNTL_6_P1_XI (1L<<27)
+#define BNX2_RPM_RC_CNTL_6_P2_XI (1L<<28)
+#define BNX2_RPM_RC_CNTL_6_P3_XI (1L<<29)
+#define BNX2_RPM_RC_CNTL_6_NBIT_XI (1L<<30)
#define BNX2_RPM_RC_VALUE_MASK_6 0x00001934
+#define BNX2_RPM_RC_VALUE_MASK_6_VALUE (0xffffL<<0)
+#define BNX2_RPM_RC_VALUE_MASK_6_MASK (0xffffL<<16)
+
#define BNX2_RPM_RC_CNTL_7 0x00001938
#define BNX2_RPM_RC_CNTL_7_A (0x3ffffL<<0)
#define BNX2_RPM_RC_CNTL_7_B (0xfffL<<19)
+#define BNX2_RPM_RC_CNTL_7_OFFSET_XI (0xffL<<0)
+#define BNX2_RPM_RC_CNTL_7_CLASS_XI (0x7L<<8)
+#define BNX2_RPM_RC_CNTL_7_PRIORITY_XI (1L<<11)
+#define BNX2_RPM_RC_CNTL_7_P4_XI (1L<<12)
+#define BNX2_RPM_RC_CNTL_7_HDR_TYPE_XI (0x7L<<13)
+#define BNX2_RPM_RC_CNTL_7_HDR_TYPE_START_XI (0L<<13)
+#define BNX2_RPM_RC_CNTL_7_HDR_TYPE_IP_XI (1L<<13)
+#define BNX2_RPM_RC_CNTL_7_HDR_TYPE_TCP_XI (2L<<13)
+#define BNX2_RPM_RC_CNTL_7_HDR_TYPE_UDP_XI (3L<<13)
+#define BNX2_RPM_RC_CNTL_7_HDR_TYPE_DATA_XI (4L<<13)
+#define BNX2_RPM_RC_CNTL_7_HDR_TYPE_TCP_UDP_XI (5L<<13)
+#define BNX2_RPM_RC_CNTL_7_HDR_TYPE_ICMPV6_XI (6L<<13)
+#define BNX2_RPM_RC_CNTL_7_COMP_XI (0x3L<<16)
+#define BNX2_RPM_RC_CNTL_7_COMP_EQUAL_XI (0L<<16)
+#define BNX2_RPM_RC_CNTL_7_COMP_NEQUAL_XI (1L<<16)
+#define BNX2_RPM_RC_CNTL_7_COMP_GREATER_XI (2L<<16)
+#define BNX2_RPM_RC_CNTL_7_COMP_LESS_XI (3L<<16)
+#define BNX2_RPM_RC_CNTL_7_MAP_XI (1L<<18)
+#define BNX2_RPM_RC_CNTL_7_SBIT_XI (1L<<19)
+#define BNX2_RPM_RC_CNTL_7_CMDSEL_XI (0x1fL<<20)
+#define BNX2_RPM_RC_CNTL_7_DISCARD_XI (1L<<25)
+#define BNX2_RPM_RC_CNTL_7_MASK_XI (1L<<26)
+#define BNX2_RPM_RC_CNTL_7_P1_XI (1L<<27)
+#define BNX2_RPM_RC_CNTL_7_P2_XI (1L<<28)
+#define BNX2_RPM_RC_CNTL_7_P3_XI (1L<<29)
+#define BNX2_RPM_RC_CNTL_7_NBIT_XI (1L<<30)
#define BNX2_RPM_RC_VALUE_MASK_7 0x0000193c
+#define BNX2_RPM_RC_VALUE_MASK_7_VALUE (0xffffL<<0)
+#define BNX2_RPM_RC_VALUE_MASK_7_MASK (0xffffL<<16)
+
#define BNX2_RPM_RC_CNTL_8 0x00001940
#define BNX2_RPM_RC_CNTL_8_A (0x3ffffL<<0)
#define BNX2_RPM_RC_CNTL_8_B (0xfffL<<19)
+#define BNX2_RPM_RC_CNTL_8_OFFSET_XI (0xffL<<0)
+#define BNX2_RPM_RC_CNTL_8_CLASS_XI (0x7L<<8)
+#define BNX2_RPM_RC_CNTL_8_PRIORITY_XI (1L<<11)
+#define BNX2_RPM_RC_CNTL_8_P4_XI (1L<<12)
+#define BNX2_RPM_RC_CNTL_8_HDR_TYPE_XI (0x7L<<13)
+#define BNX2_RPM_RC_CNTL_8_HDR_TYPE_START_XI (0L<<13)
+#define BNX2_RPM_RC_CNTL_8_HDR_TYPE_IP_XI (1L<<13)
+#define BNX2_RPM_RC_CNTL_8_HDR_TYPE_TCP_XI (2L<<13)
+#define BNX2_RPM_RC_CNTL_8_HDR_TYPE_UDP_XI (3L<<13)
+#define BNX2_RPM_RC_CNTL_8_HDR_TYPE_DATA_XI (4L<<13)
+#define BNX2_RPM_RC_CNTL_8_HDR_TYPE_TCP_UDP_XI (5L<<13)
+#define BNX2_RPM_RC_CNTL_8_HDR_TYPE_ICMPV6_XI (6L<<13)
+#define BNX2_RPM_RC_CNTL_8_COMP_XI (0x3L<<16)
+#define BNX2_RPM_RC_CNTL_8_COMP_EQUAL_XI (0L<<16)
+#define BNX2_RPM_RC_CNTL_8_COMP_NEQUAL_XI (1L<<16)
+#define BNX2_RPM_RC_CNTL_8_COMP_GREATER_XI (2L<<16)
+#define BNX2_RPM_RC_CNTL_8_COMP_LESS_XI (3L<<16)
+#define BNX2_RPM_RC_CNTL_8_MAP_XI (1L<<18)
+#define BNX2_RPM_RC_CNTL_8_SBIT_XI (1L<<19)
+#define BNX2_RPM_RC_CNTL_8_CMDSEL_XI (0x1fL<<20)
+#define BNX2_RPM_RC_CNTL_8_DISCARD_XI (1L<<25)
+#define BNX2_RPM_RC_CNTL_8_MASK_XI (1L<<26)
+#define BNX2_RPM_RC_CNTL_8_P1_XI (1L<<27)
+#define BNX2_RPM_RC_CNTL_8_P2_XI (1L<<28)
+#define BNX2_RPM_RC_CNTL_8_P3_XI (1L<<29)
+#define BNX2_RPM_RC_CNTL_8_NBIT_XI (1L<<30)
#define BNX2_RPM_RC_VALUE_MASK_8 0x00001944
+#define BNX2_RPM_RC_VALUE_MASK_8_VALUE (0xffffL<<0)
+#define BNX2_RPM_RC_VALUE_MASK_8_MASK (0xffffL<<16)
+
#define BNX2_RPM_RC_CNTL_9 0x00001948
#define BNX2_RPM_RC_CNTL_9_A (0x3ffffL<<0)
#define BNX2_RPM_RC_CNTL_9_B (0xfffL<<19)
+#define BNX2_RPM_RC_CNTL_9_OFFSET_XI (0xffL<<0)
+#define BNX2_RPM_RC_CNTL_9_CLASS_XI (0x7L<<8)
+#define BNX2_RPM_RC_CNTL_9_PRIORITY_XI (1L<<11)
+#define BNX2_RPM_RC_CNTL_9_P4_XI (1L<<12)
+#define BNX2_RPM_RC_CNTL_9_HDR_TYPE_XI (0x7L<<13)
+#define BNX2_RPM_RC_CNTL_9_HDR_TYPE_START_XI (0L<<13)
+#define BNX2_RPM_RC_CNTL_9_HDR_TYPE_IP_XI (1L<<13)
+#define BNX2_RPM_RC_CNTL_9_HDR_TYPE_TCP_XI (2L<<13)
+#define BNX2_RPM_RC_CNTL_9_HDR_TYPE_UDP_XI (3L<<13)
+#define BNX2_RPM_RC_CNTL_9_HDR_TYPE_DATA_XI (4L<<13)
+#define BNX2_RPM_RC_CNTL_9_HDR_TYPE_TCP_UDP_XI (5L<<13)
+#define BNX2_RPM_RC_CNTL_9_HDR_TYPE_ICMPV6_XI (6L<<13)
+#define BNX2_RPM_RC_CNTL_9_COMP_XI (0x3L<<16)
+#define BNX2_RPM_RC_CNTL_9_COMP_EQUAL_XI (0L<<16)
+#define BNX2_RPM_RC_CNTL_9_COMP_NEQUAL_XI (1L<<16)
+#define BNX2_RPM_RC_CNTL_9_COMP_GREATER_XI (2L<<16)
+#define BNX2_RPM_RC_CNTL_9_COMP_LESS_XI (3L<<16)
+#define BNX2_RPM_RC_CNTL_9_MAP_XI (1L<<18)
+#define BNX2_RPM_RC_CNTL_9_SBIT_XI (1L<<19)
+#define BNX2_RPM_RC_CNTL_9_CMDSEL_XI (0x1fL<<20)
+#define BNX2_RPM_RC_CNTL_9_DISCARD_XI (1L<<25)
+#define BNX2_RPM_RC_CNTL_9_MASK_XI (1L<<26)
+#define BNX2_RPM_RC_CNTL_9_P1_XI (1L<<27)
+#define BNX2_RPM_RC_CNTL_9_P2_XI (1L<<28)
+#define BNX2_RPM_RC_CNTL_9_P3_XI (1L<<29)
+#define BNX2_RPM_RC_CNTL_9_NBIT_XI (1L<<30)
#define BNX2_RPM_RC_VALUE_MASK_9 0x0000194c
+#define BNX2_RPM_RC_VALUE_MASK_9_VALUE (0xffffL<<0)
+#define BNX2_RPM_RC_VALUE_MASK_9_MASK (0xffffL<<16)
+
#define BNX2_RPM_RC_CNTL_10 0x00001950
#define BNX2_RPM_RC_CNTL_10_A (0x3ffffL<<0)
#define BNX2_RPM_RC_CNTL_10_B (0xfffL<<19)
+#define BNX2_RPM_RC_CNTL_10_OFFSET_XI (0xffL<<0)
+#define BNX2_RPM_RC_CNTL_10_CLASS_XI (0x7L<<8)
+#define BNX2_RPM_RC_CNTL_10_PRIORITY_XI (1L<<11)
+#define BNX2_RPM_RC_CNTL_10_P4_XI (1L<<12)
+#define BNX2_RPM_RC_CNTL_10_HDR_TYPE_XI (0x7L<<13)
+#define BNX2_RPM_RC_CNTL_10_HDR_TYPE_START_XI (0L<<13)
+#define BNX2_RPM_RC_CNTL_10_HDR_TYPE_IP_XI (1L<<13)
+#define BNX2_RPM_RC_CNTL_10_HDR_TYPE_TCP_XI (2L<<13)
+#define BNX2_RPM_RC_CNTL_10_HDR_TYPE_UDP_XI (3L<<13)
+#define BNX2_RPM_RC_CNTL_10_HDR_TYPE_DATA_XI (4L<<13)
+#define BNX2_RPM_RC_CNTL_10_HDR_TYPE_TCP_UDP_XI (5L<<13)
+#define BNX2_RPM_RC_CNTL_10_HDR_TYPE_ICMPV6_XI (6L<<13)
+#define BNX2_RPM_RC_CNTL_10_COMP_XI (0x3L<<16)
+#define BNX2_RPM_RC_CNTL_10_COMP_EQUAL_XI (0L<<16)
+#define BNX2_RPM_RC_CNTL_10_COMP_NEQUAL_XI (1L<<16)
+#define BNX2_RPM_RC_CNTL_10_COMP_GREATER_XI (2L<<16)
+#define BNX2_RPM_RC_CNTL_10_COMP_LESS_XI (3L<<16)
+#define BNX2_RPM_RC_CNTL_10_MAP_XI (1L<<18)
+#define BNX2_RPM_RC_CNTL_10_SBIT_XI (1L<<19)
+#define BNX2_RPM_RC_CNTL_10_CMDSEL_XI (0x1fL<<20)
+#define BNX2_RPM_RC_CNTL_10_DISCARD_XI (1L<<25)
+#define BNX2_RPM_RC_CNTL_10_MASK_XI (1L<<26)
+#define BNX2_RPM_RC_CNTL_10_P1_XI (1L<<27)
+#define BNX2_RPM_RC_CNTL_10_P2_XI (1L<<28)
+#define BNX2_RPM_RC_CNTL_10_P3_XI (1L<<29)
+#define BNX2_RPM_RC_CNTL_10_NBIT_XI (1L<<30)
#define BNX2_RPM_RC_VALUE_MASK_10 0x00001954
+#define BNX2_RPM_RC_VALUE_MASK_10_VALUE (0xffffL<<0)
+#define BNX2_RPM_RC_VALUE_MASK_10_MASK (0xffffL<<16)
+
#define BNX2_RPM_RC_CNTL_11 0x00001958
#define BNX2_RPM_RC_CNTL_11_A (0x3ffffL<<0)
#define BNX2_RPM_RC_CNTL_11_B (0xfffL<<19)
+#define BNX2_RPM_RC_CNTL_11_OFFSET_XI (0xffL<<0)
+#define BNX2_RPM_RC_CNTL_11_CLASS_XI (0x7L<<8)
+#define BNX2_RPM_RC_CNTL_11_PRIORITY_XI (1L<<11)
+#define BNX2_RPM_RC_CNTL_11_P4_XI (1L<<12)
+#define BNX2_RPM_RC_CNTL_11_HDR_TYPE_XI (0x7L<<13)
+#define BNX2_RPM_RC_CNTL_11_HDR_TYPE_START_XI (0L<<13)
+#define BNX2_RPM_RC_CNTL_11_HDR_TYPE_IP_XI (1L<<13)
+#define BNX2_RPM_RC_CNTL_11_HDR_TYPE_TCP_XI (2L<<13)
+#define BNX2_RPM_RC_CNTL_11_HDR_TYPE_UDP_XI (3L<<13)
+#define BNX2_RPM_RC_CNTL_11_HDR_TYPE_DATA_XI (4L<<13)
+#define BNX2_RPM_RC_CNTL_11_HDR_TYPE_TCP_UDP_XI (5L<<13)
+#define BNX2_RPM_RC_CNTL_11_HDR_TYPE_ICMPV6_XI (6L<<13)
+#define BNX2_RPM_RC_CNTL_11_COMP_XI (0x3L<<16)
+#define BNX2_RPM_RC_CNTL_11_COMP_EQUAL_XI (0L<<16)
+#define BNX2_RPM_RC_CNTL_11_COMP_NEQUAL_XI (1L<<16)
+#define BNX2_RPM_RC_CNTL_11_COMP_GREATER_XI (2L<<16)
+#define BNX2_RPM_RC_CNTL_11_COMP_LESS_XI (3L<<16)
+#define BNX2_RPM_RC_CNTL_11_MAP_XI (1L<<18)
+#define BNX2_RPM_RC_CNTL_11_SBIT_XI (1L<<19)
+#define BNX2_RPM_RC_CNTL_11_CMDSEL_XI (0x1fL<<20)
+#define BNX2_RPM_RC_CNTL_11_DISCARD_XI (1L<<25)
+#define BNX2_RPM_RC_CNTL_11_MASK_XI (1L<<26)
+#define BNX2_RPM_RC_CNTL_11_P1_XI (1L<<27)
+#define BNX2_RPM_RC_CNTL_11_P2_XI (1L<<28)
+#define BNX2_RPM_RC_CNTL_11_P3_XI (1L<<29)
+#define BNX2_RPM_RC_CNTL_11_NBIT_XI (1L<<30)
#define BNX2_RPM_RC_VALUE_MASK_11 0x0000195c
+#define BNX2_RPM_RC_VALUE_MASK_11_VALUE (0xffffL<<0)
+#define BNX2_RPM_RC_VALUE_MASK_11_MASK (0xffffL<<16)
+
#define BNX2_RPM_RC_CNTL_12 0x00001960
#define BNX2_RPM_RC_CNTL_12_A (0x3ffffL<<0)
#define BNX2_RPM_RC_CNTL_12_B (0xfffL<<19)
+#define BNX2_RPM_RC_CNTL_12_OFFSET_XI (0xffL<<0)
+#define BNX2_RPM_RC_CNTL_12_CLASS_XI (0x7L<<8)
+#define BNX2_RPM_RC_CNTL_12_PRIORITY_XI (1L<<11)
+#define BNX2_RPM_RC_CNTL_12_P4_XI (1L<<12)
+#define BNX2_RPM_RC_CNTL_12_HDR_TYPE_XI (0x7L<<13)
+#define BNX2_RPM_RC_CNTL_12_HDR_TYPE_START_XI (0L<<13)
+#define BNX2_RPM_RC_CNTL_12_HDR_TYPE_IP_XI (1L<<13)
+#define BNX2_RPM_RC_CNTL_12_HDR_TYPE_TCP_XI (2L<<13)
+#define BNX2_RPM_RC_CNTL_12_HDR_TYPE_UDP_XI (3L<<13)
+#define BNX2_RPM_RC_CNTL_12_HDR_TYPE_DATA_XI (4L<<13)
+#define BNX2_RPM_RC_CNTL_12_HDR_TYPE_TCP_UDP_XI (5L<<13)
+#define BNX2_RPM_RC_CNTL_12_HDR_TYPE_ICMPV6_XI (6L<<13)
+#define BNX2_RPM_RC_CNTL_12_COMP_XI (0x3L<<16)
+#define BNX2_RPM_RC_CNTL_12_COMP_EQUAL_XI (0L<<16)
+#define BNX2_RPM_RC_CNTL_12_COMP_NEQUAL_XI (1L<<16)
+#define BNX2_RPM_RC_CNTL_12_COMP_GREATER_XI (2L<<16)
+#define BNX2_RPM_RC_CNTL_12_COMP_LESS_XI (3L<<16)
+#define BNX2_RPM_RC_CNTL_12_MAP_XI (1L<<18)
+#define BNX2_RPM_RC_CNTL_12_SBIT_XI (1L<<19)
+#define BNX2_RPM_RC_CNTL_12_CMDSEL_XI (0x1fL<<20)
+#define BNX2_RPM_RC_CNTL_12_DISCARD_XI (1L<<25)
+#define BNX2_RPM_RC_CNTL_12_MASK_XI (1L<<26)
+#define BNX2_RPM_RC_CNTL_12_P1_XI (1L<<27)
+#define BNX2_RPM_RC_CNTL_12_P2_XI (1L<<28)
+#define BNX2_RPM_RC_CNTL_12_P3_XI (1L<<29)
+#define BNX2_RPM_RC_CNTL_12_NBIT_XI (1L<<30)
#define BNX2_RPM_RC_VALUE_MASK_12 0x00001964
+#define BNX2_RPM_RC_VALUE_MASK_12_VALUE (0xffffL<<0)
+#define BNX2_RPM_RC_VALUE_MASK_12_MASK (0xffffL<<16)
+
#define BNX2_RPM_RC_CNTL_13 0x00001968
#define BNX2_RPM_RC_CNTL_13_A (0x3ffffL<<0)
#define BNX2_RPM_RC_CNTL_13_B (0xfffL<<19)
+#define BNX2_RPM_RC_CNTL_13_OFFSET_XI (0xffL<<0)
+#define BNX2_RPM_RC_CNTL_13_CLASS_XI (0x7L<<8)
+#define BNX2_RPM_RC_CNTL_13_PRIORITY_XI (1L<<11)
+#define BNX2_RPM_RC_CNTL_13_P4_XI (1L<<12)
+#define BNX2_RPM_RC_CNTL_13_HDR_TYPE_XI (0x7L<<13)
+#define BNX2_RPM_RC_CNTL_13_HDR_TYPE_START_XI (0L<<13)
+#define BNX2_RPM_RC_CNTL_13_HDR_TYPE_IP_XI (1L<<13)
+#define BNX2_RPM_RC_CNTL_13_HDR_TYPE_TCP_XI (2L<<13)
+#define BNX2_RPM_RC_CNTL_13_HDR_TYPE_UDP_XI (3L<<13)
+#define BNX2_RPM_RC_CNTL_13_HDR_TYPE_DATA_XI (4L<<13)
+#define BNX2_RPM_RC_CNTL_13_HDR_TYPE_TCP_UDP_XI (5L<<13)
+#define BNX2_RPM_RC_CNTL_13_HDR_TYPE_ICMPV6_XI (6L<<13)
+#define BNX2_RPM_RC_CNTL_13_COMP_XI (0x3L<<16)
+#define BNX2_RPM_RC_CNTL_13_COMP_EQUAL_XI (0L<<16)
+#define BNX2_RPM_RC_CNTL_13_COMP_NEQUAL_XI (1L<<16)
+#define BNX2_RPM_RC_CNTL_13_COMP_GREATER_XI (2L<<16)
+#define BNX2_RPM_RC_CNTL_13_COMP_LESS_XI (3L<<16)
+#define BNX2_RPM_RC_CNTL_13_MAP_XI (1L<<18)
+#define BNX2_RPM_RC_CNTL_13_SBIT_XI (1L<<19)
+#define BNX2_RPM_RC_CNTL_13_CMDSEL_XI (0x1fL<<20)
+#define BNX2_RPM_RC_CNTL_13_DISCARD_XI (1L<<25)
+#define BNX2_RPM_RC_CNTL_13_MASK_XI (1L<<26)
+#define BNX2_RPM_RC_CNTL_13_P1_XI (1L<<27)
+#define BNX2_RPM_RC_CNTL_13_P2_XI (1L<<28)
+#define BNX2_RPM_RC_CNTL_13_P3_XI (1L<<29)
+#define BNX2_RPM_RC_CNTL_13_NBIT_XI (1L<<30)
#define BNX2_RPM_RC_VALUE_MASK_13 0x0000196c
+#define BNX2_RPM_RC_VALUE_MASK_13_VALUE (0xffffL<<0)
+#define BNX2_RPM_RC_VALUE_MASK_13_MASK (0xffffL<<16)
+
#define BNX2_RPM_RC_CNTL_14 0x00001970
#define BNX2_RPM_RC_CNTL_14_A (0x3ffffL<<0)
#define BNX2_RPM_RC_CNTL_14_B (0xfffL<<19)
+#define BNX2_RPM_RC_CNTL_14_OFFSET_XI (0xffL<<0)
+#define BNX2_RPM_RC_CNTL_14_CLASS_XI (0x7L<<8)
+#define BNX2_RPM_RC_CNTL_14_PRIORITY_XI (1L<<11)
+#define BNX2_RPM_RC_CNTL_14_P4_XI (1L<<12)
+#define BNX2_RPM_RC_CNTL_14_HDR_TYPE_XI (0x7L<<13)
+#define BNX2_RPM_RC_CNTL_14_HDR_TYPE_START_XI (0L<<13)
+#define BNX2_RPM_RC_CNTL_14_HDR_TYPE_IP_XI (1L<<13)
+#define BNX2_RPM_RC_CNTL_14_HDR_TYPE_TCP_XI (2L<<13)
+#define BNX2_RPM_RC_CNTL_14_HDR_TYPE_UDP_XI (3L<<13)
+#define BNX2_RPM_RC_CNTL_14_HDR_TYPE_DATA_XI (4L<<13)
+#define BNX2_RPM_RC_CNTL_14_HDR_TYPE_TCP_UDP_XI (5L<<13)
+#define BNX2_RPM_RC_CNTL_14_HDR_TYPE_ICMPV6_XI (6L<<13)
+#define BNX2_RPM_RC_CNTL_14_COMP_XI (0x3L<<16)
+#define BNX2_RPM_RC_CNTL_14_COMP_EQUAL_XI (0L<<16)
+#define BNX2_RPM_RC_CNTL_14_COMP_NEQUAL_XI (1L<<16)
+#define BNX2_RPM_RC_CNTL_14_COMP_GREATER_XI (2L<<16)
+#define BNX2_RPM_RC_CNTL_14_COMP_LESS_XI (3L<<16)
+#define BNX2_RPM_RC_CNTL_14_MAP_XI (1L<<18)
+#define BNX2_RPM_RC_CNTL_14_SBIT_XI (1L<<19)
+#define BNX2_RPM_RC_CNTL_14_CMDSEL_XI (0x1fL<<20)
+#define BNX2_RPM_RC_CNTL_14_DISCARD_XI (1L<<25)
+#define BNX2_RPM_RC_CNTL_14_MASK_XI (1L<<26)
+#define BNX2_RPM_RC_CNTL_14_P1_XI (1L<<27)
+#define BNX2_RPM_RC_CNTL_14_P2_XI (1L<<28)
+#define BNX2_RPM_RC_CNTL_14_P3_XI (1L<<29)
+#define BNX2_RPM_RC_CNTL_14_NBIT_XI (1L<<30)
#define BNX2_RPM_RC_VALUE_MASK_14 0x00001974
+#define BNX2_RPM_RC_VALUE_MASK_14_VALUE (0xffffL<<0)
+#define BNX2_RPM_RC_VALUE_MASK_14_MASK (0xffffL<<16)
+
#define BNX2_RPM_RC_CNTL_15 0x00001978
#define BNX2_RPM_RC_CNTL_15_A (0x3ffffL<<0)
#define BNX2_RPM_RC_CNTL_15_B (0xfffL<<19)
+#define BNX2_RPM_RC_CNTL_15_OFFSET_XI (0xffL<<0)
+#define BNX2_RPM_RC_CNTL_15_CLASS_XI (0x7L<<8)
+#define BNX2_RPM_RC_CNTL_15_PRIORITY_XI (1L<<11)
+#define BNX2_RPM_RC_CNTL_15_P4_XI (1L<<12)
+#define BNX2_RPM_RC_CNTL_15_HDR_TYPE_XI (0x7L<<13)
+#define BNX2_RPM_RC_CNTL_15_HDR_TYPE_START_XI (0L<<13)
+#define BNX2_RPM_RC_CNTL_15_HDR_TYPE_IP_XI (1L<<13)
+#define BNX2_RPM_RC_CNTL_15_HDR_TYPE_TCP_XI (2L<<13)
+#define BNX2_RPM_RC_CNTL_15_HDR_TYPE_UDP_XI (3L<<13)
+#define BNX2_RPM_RC_CNTL_15_HDR_TYPE_DATA_XI (4L<<13)
+#define BNX2_RPM_RC_CNTL_15_HDR_TYPE_TCP_UDP_XI (5L<<13)
+#define BNX2_RPM_RC_CNTL_15_HDR_TYPE_ICMPV6_XI (6L<<13)
+#define BNX2_RPM_RC_CNTL_15_COMP_XI (0x3L<<16)
+#define BNX2_RPM_RC_CNTL_15_COMP_EQUAL_XI (0L<<16)
+#define BNX2_RPM_RC_CNTL_15_COMP_NEQUAL_XI (1L<<16)
+#define BNX2_RPM_RC_CNTL_15_COMP_GREATER_XI (2L<<16)
+#define BNX2_RPM_RC_CNTL_15_COMP_LESS_XI (3L<<16)
+#define BNX2_RPM_RC_CNTL_15_MAP_XI (1L<<18)
+#define BNX2_RPM_RC_CNTL_15_SBIT_XI (1L<<19)
+#define BNX2_RPM_RC_CNTL_15_CMDSEL_XI (0x1fL<<20)
+#define BNX2_RPM_RC_CNTL_15_DISCARD_XI (1L<<25)
+#define BNX2_RPM_RC_CNTL_15_MASK_XI (1L<<26)
+#define BNX2_RPM_RC_CNTL_15_P1_XI (1L<<27)
+#define BNX2_RPM_RC_CNTL_15_P2_XI (1L<<28)
+#define BNX2_RPM_RC_CNTL_15_P3_XI (1L<<29)
+#define BNX2_RPM_RC_CNTL_15_NBIT_XI (1L<<30)
#define BNX2_RPM_RC_VALUE_MASK_15 0x0000197c
+#define BNX2_RPM_RC_VALUE_MASK_15_VALUE (0xffffL<<0)
+#define BNX2_RPM_RC_VALUE_MASK_15_MASK (0xffffL<<16)
+
#define BNX2_RPM_RC_CONFIG 0x00001980
#define BNX2_RPM_RC_CONFIG_RULE_ENABLE (0xffffL<<0)
+#define BNX2_RPM_RC_CONFIG_RULE_ENABLE_XI (0xfffffL<<0)
#define BNX2_RPM_RC_CONFIG_DEF_CLASS (0x7L<<24)
+#define BNX2_RPM_RC_CONFIG_KNUM_OVERWRITE (1L<<31)
#define BNX2_RPM_DEBUG0 0x00001984
#define BNX2_RPM_DEBUG0_FM_BCNT (0xffffL<<0)
@@ -2236,6 +4026,16 @@ struct l2_fhdr {
#define BNX2_RPM_DEBUG9_INFIFO_OVERRUN_OCCURRED (1L<<29)
#define BNX2_RPM_DEBUG9_ACPI_MATCH_INT (1L<<30)
#define BNX2_RPM_DEBUG9_ACPI_ENABLE_SYN (1L<<31)
+#define BNX2_RPM_DEBUG9_BEMEM_R_XI (0x1fL<<0)
+#define BNX2_RPM_DEBUG9_EO_XI (1L<<5)
+#define BNX2_RPM_DEBUG9_AEOF_DE_XI (1L<<6)
+#define BNX2_RPM_DEBUG9_SO_XI (1L<<7)
+#define BNX2_RPM_DEBUG9_WD64_CT_XI (0x1fL<<8)
+#define BNX2_RPM_DEBUG9_EOF_VLDBYTE_XI (0x7L<<13)
+#define BNX2_RPM_DEBUG9_ACPI_RDE_PAT_ID_XI (0xfL<<16)
+#define BNX2_RPM_DEBUG9_CALCRC_RESULT_XI (0x3ffL<<20)
+#define BNX2_RPM_DEBUG9_DATA_IN_VL_XI (1L<<30)
+#define BNX2_RPM_DEBUG9_CALCRC_BUFFER_VLD_XI (1L<<31)
#define BNX2_RPM_ACPI_DBG_BUF_W00 0x000019c0
#define BNX2_RPM_ACPI_DBG_BUF_W01 0x000019c4
@@ -2253,6 +4053,56 @@ struct l2_fhdr {
#define BNX2_RPM_ACPI_DBG_BUF_W31 0x000019f4
#define BNX2_RPM_ACPI_DBG_BUF_W32 0x000019f8
#define BNX2_RPM_ACPI_DBG_BUF_W33 0x000019fc
+#define BNX2_RPM_ACPI_BYTE_ENABLE_CTRL 0x00001a00
+#define BNX2_RPM_ACPI_BYTE_ENABLE_CTRL_BYTE_ADDRESS (0xffffL<<0)
+#define BNX2_RPM_ACPI_BYTE_ENABLE_CTRL_DEBUGRD (1L<<28)
+#define BNX2_RPM_ACPI_BYTE_ENABLE_CTRL_MODE (1L<<29)
+#define BNX2_RPM_ACPI_BYTE_ENABLE_CTRL_INIT (1L<<30)
+#define BNX2_RPM_ACPI_BYTE_ENABLE_CTRL_WR (1L<<31)
+
+#define BNX2_RPM_ACPI_PATTERN_CTRL 0x00001a04
+#define BNX2_RPM_ACPI_PATTERN_CTRL_PATTERN_ID (0xfL<<0)
+#define BNX2_RPM_ACPI_PATTERN_CTRL_CRC_SM_CLR (1L<<30)
+#define BNX2_RPM_ACPI_PATTERN_CTRL_WR (1L<<31)
+
+#define BNX2_RPM_ACPI_DATA 0x00001a08
+#define BNX2_RPM_ACPI_DATA_PATTERN_BE (0xffffffffL<<0)
+
+#define BNX2_RPM_ACPI_PATTERN_LEN0 0x00001a0c
+#define BNX2_RPM_ACPI_PATTERN_LEN0_PATTERN_LEN3 (0xffL<<0)
+#define BNX2_RPM_ACPI_PATTERN_LEN0_PATTERN_LEN2 (0xffL<<8)
+#define BNX2_RPM_ACPI_PATTERN_LEN0_PATTERN_LEN1 (0xffL<<16)
+#define BNX2_RPM_ACPI_PATTERN_LEN0_PATTERN_LEN0 (0xffL<<24)
+
+#define BNX2_RPM_ACPI_PATTERN_LEN1 0x00001a10
+#define BNX2_RPM_ACPI_PATTERN_LEN1_PATTERN_LEN7 (0xffL<<0)
+#define BNX2_RPM_ACPI_PATTERN_LEN1_PATTERN_LEN6 (0xffL<<8)
+#define BNX2_RPM_ACPI_PATTERN_LEN1_PATTERN_LEN5 (0xffL<<16)
+#define BNX2_RPM_ACPI_PATTERN_LEN1_PATTERN_LEN4 (0xffL<<24)
+
+#define BNX2_RPM_ACPI_PATTERN_CRC0 0x00001a18
+#define BNX2_RPM_ACPI_PATTERN_CRC0_PATTERN_CRC0 (0xffffffffL<<0)
+
+#define BNX2_RPM_ACPI_PATTERN_CRC1 0x00001a1c
+#define BNX2_RPM_ACPI_PATTERN_CRC1_PATTERN_CRC1 (0xffffffffL<<0)
+
+#define BNX2_RPM_ACPI_PATTERN_CRC2 0x00001a20
+#define BNX2_RPM_ACPI_PATTERN_CRC2_PATTERN_CRC2 (0xffffffffL<<0)
+
+#define BNX2_RPM_ACPI_PATTERN_CRC3 0x00001a24
+#define BNX2_RPM_ACPI_PATTERN_CRC3_PATTERN_CRC3 (0xffffffffL<<0)
+
+#define BNX2_RPM_ACPI_PATTERN_CRC4 0x00001a28
+#define BNX2_RPM_ACPI_PATTERN_CRC4_PATTERN_CRC4 (0xffffffffL<<0)
+
+#define BNX2_RPM_ACPI_PATTERN_CRC5 0x00001a2c
+#define BNX2_RPM_ACPI_PATTERN_CRC5_PATTERN_CRC5 (0xffffffffL<<0)
+
+#define BNX2_RPM_ACPI_PATTERN_CRC6 0x00001a30
+#define BNX2_RPM_ACPI_PATTERN_CRC6_PATTERN_CRC6 (0xffffffffL<<0)
+
+#define BNX2_RPM_ACPI_PATTERN_CRC7 0x00001a34
+#define BNX2_RPM_ACPI_PATTERN_CRC7_PATTERN_CRC7 (0xffffffffL<<0)
/*
@@ -2263,15 +4113,20 @@ struct l2_fhdr {
#define BNX2_RBUF_COMMAND_ENABLED (1L<<0)
#define BNX2_RBUF_COMMAND_FREE_INIT (1L<<1)
#define BNX2_RBUF_COMMAND_RAM_INIT (1L<<2)
+#define BNX2_RBUF_COMMAND_PKT_OFFSET_OVFL (1L<<3)
#define BNX2_RBUF_COMMAND_OVER_FREE (1L<<4)
#define BNX2_RBUF_COMMAND_ALLOC_REQ (1L<<5)
+#define BNX2_RBUF_COMMAND_EN_PRI_CHNGE_TE (1L<<6)
+#define BNX2_RBUF_COMMAND_CU_ISOLATE_XI (1L<<5)
+#define BNX2_RBUF_COMMAND_EN_PRI_CHANGE_XI (1L<<6)
+#define BNX2_RBUF_COMMAND_GRC_ENDIAN_CONV_DIS_XI (1L<<7)
#define BNX2_RBUF_STATUS1 0x00200004
#define BNX2_RBUF_STATUS1_FREE_COUNT (0x3ffL<<0)
#define BNX2_RBUF_STATUS2 0x00200008
-#define BNX2_RBUF_STATUS2_FREE_TAIL (0x3ffL<<0)
-#define BNX2_RBUF_STATUS2_FREE_HEAD (0x3ffL<<16)
+#define BNX2_RBUF_STATUS2_FREE_TAIL (0x1ffL<<0)
+#define BNX2_RBUF_STATUS2_FREE_HEAD (0x1ffL<<16)
#define BNX2_RBUF_CONFIG 0x0020000c
#define BNX2_RBUF_CONFIG_XOFF_TRIP (0x3ffL<<0)
@@ -2279,16 +4134,21 @@ struct l2_fhdr {
#define BNX2_RBUF_FW_BUF_ALLOC 0x00200010
#define BNX2_RBUF_FW_BUF_ALLOC_VALUE (0x1ffL<<7)
+#define BNX2_RBUF_FW_BUF_ALLOC_TYPE (1L<<16)
+#define BNX2_RBUF_FW_BUF_ALLOC_ALLOC_REQ (1L<<31)
#define BNX2_RBUF_FW_BUF_FREE 0x00200014
#define BNX2_RBUF_FW_BUF_FREE_COUNT (0x7fL<<0)
#define BNX2_RBUF_FW_BUF_FREE_TAIL (0x1ffL<<7)
#define BNX2_RBUF_FW_BUF_FREE_HEAD (0x1ffL<<16)
+#define BNX2_RBUF_FW_BUF_FREE_TYPE (1L<<25)
+#define BNX2_RBUF_FW_BUF_FREE_FREE_REQ (1L<<31)
#define BNX2_RBUF_FW_BUF_SEL 0x00200018
#define BNX2_RBUF_FW_BUF_SEL_COUNT (0x7fL<<0)
#define BNX2_RBUF_FW_BUF_SEL_TAIL (0x1ffL<<7)
#define BNX2_RBUF_FW_BUF_SEL_HEAD (0x1ffL<<16)
+#define BNX2_RBUF_FW_BUF_SEL_SEL_REQ (1L<<31)
#define BNX2_RBUF_CONFIG2 0x0020001c
#define BNX2_RBUF_CONFIG2_MAC_DROP_TRIP (0x3ffL<<0)
@@ -2376,6 +4236,8 @@ struct l2_fhdr {
#define BNX2_RV2P_INSTR_HIGH_HIGH (0x1fL<<0)
#define BNX2_RV2P_INSTR_LOW 0x00002834
+#define BNX2_RV2P_INSTR_LOW_LOW (0xffffffffL<<0)
+
#define BNX2_RV2P_PROC1_ADDR_CMD 0x00002838
#define BNX2_RV2P_PROC1_ADDR_CMD_ADD (0x3ffL<<0)
#define BNX2_RV2P_PROC1_ADDR_CMD_RDWR (1L<<31)
@@ -2395,7 +4257,29 @@ struct l2_fhdr {
#define BNX2_RV2P_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
#define BNX2_RV2P_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
-#define BNX2_RV2P_PFTQ_DATA 0x00002b40
+#define BNX2_RV2P_MPFE_PFE_CTL 0x00002afc
+#define BNX2_RV2P_MPFE_PFE_CTL_INC_USAGE_CNT (1L<<0)
+#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE (0xfL<<4)
+#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_0 (0L<<4)
+#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_1 (1L<<4)
+#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_2 (2L<<4)
+#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_3 (3L<<4)
+#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_4 (4L<<4)
+#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_5 (5L<<4)
+#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_6 (6L<<4)
+#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_7 (7L<<4)
+#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_8 (8L<<4)
+#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_9 (9L<<4)
+#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_10 (10L<<4)
+#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_11 (11L<<4)
+#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_12 (12L<<4)
+#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_13 (13L<<4)
+#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_14 (14L<<4)
+#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_15 (15L<<4)
+#define BNX2_RV2P_MPFE_PFE_CTL_PFE_COUNT (0xfL<<12)
+#define BNX2_RV2P_MPFE_PFE_CTL_OFFSET (0x1ffL<<16)
+
+#define BNX2_RV2P_RV2PPQ 0x00002b40
#define BNX2_RV2P_PFTQ_CMD 0x00002b78
#define BNX2_RV2P_PFTQ_CMD_OFFSET (0x3ffL<<0)
#define BNX2_RV2P_PFTQ_CMD_WR_TOP (1L<<10)
@@ -2416,7 +4300,7 @@ struct l2_fhdr {
#define BNX2_RV2P_PFTQ_CTL_MAX_DEPTH (0x3ffL<<12)
#define BNX2_RV2P_PFTQ_CTL_CUR_DEPTH (0x3ffL<<22)
-#define BNX2_RV2P_TFTQ_DATA 0x00002b80
+#define BNX2_RV2P_RV2PTQ 0x00002b80
#define BNX2_RV2P_TFTQ_CMD 0x00002bb8
#define BNX2_RV2P_TFTQ_CMD_OFFSET (0x3ffL<<0)
#define BNX2_RV2P_TFTQ_CMD_WR_TOP (1L<<10)
@@ -2437,7 +4321,7 @@ struct l2_fhdr {
#define BNX2_RV2P_TFTQ_CTL_MAX_DEPTH (0x3ffL<<12)
#define BNX2_RV2P_TFTQ_CTL_CUR_DEPTH (0x3ffL<<22)
-#define BNX2_RV2P_MFTQ_DATA 0x00002bc0
+#define BNX2_RV2P_RV2PMQ 0x00002bc0
#define BNX2_RV2P_MFTQ_CMD 0x00002bf8
#define BNX2_RV2P_MFTQ_CMD_OFFSET (0x3ffL<<0)
#define BNX2_RV2P_MFTQ_CMD_WR_TOP (1L<<10)
@@ -2466,18 +4350,26 @@ struct l2_fhdr {
*/
#define BNX2_MQ_COMMAND 0x00003c00
#define BNX2_MQ_COMMAND_ENABLED (1L<<0)
+#define BNX2_MQ_COMMAND_INIT (1L<<1)
#define BNX2_MQ_COMMAND_OVERFLOW (1L<<4)
#define BNX2_MQ_COMMAND_WR_ERROR (1L<<5)
#define BNX2_MQ_COMMAND_RD_ERROR (1L<<6)
+#define BNX2_MQ_COMMAND_IDB_CFG_ERROR (1L<<7)
+#define BNX2_MQ_COMMAND_IDB_OVERFLOW (1L<<10)
+#define BNX2_MQ_COMMAND_NO_BIN_ERROR (1L<<11)
+#define BNX2_MQ_COMMAND_NO_MAP_ERROR (1L<<12)
#define BNX2_MQ_STATUS 0x00003c04
#define BNX2_MQ_STATUS_CTX_ACCESS_STAT (1L<<16)
#define BNX2_MQ_STATUS_CTX_ACCESS64_STAT (1L<<17)
#define BNX2_MQ_STATUS_PCI_STALL_STAT (1L<<18)
+#define BNX2_MQ_STATUS_IDB_OFLOW_STAT (1L<<19)
#define BNX2_MQ_CONFIG 0x00003c08
#define BNX2_MQ_CONFIG_TX_HIGH_PRI (1L<<0)
#define BNX2_MQ_CONFIG_HALT_DIS (1L<<1)
+#define BNX2_MQ_CONFIG_BIN_MQ_MODE (1L<<2)
+#define BNX2_MQ_CONFIG_DIS_IDB_DROP (1L<<3)
#define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE (0x7L<<4)
#define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_256 (0L<<4)
#define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_512 (1L<<4)
@@ -2533,6 +4425,7 @@ struct l2_fhdr {
#define BNX2_MQ_MEM_WR_DATA2 0x00003c80
#define BNX2_MQ_MEM_WR_DATA2_VALUE (0x3fffffffL<<0)
+#define BNX2_MQ_MEM_WR_DATA2_VALUE_XI (0x7fffffffL<<0)
#define BNX2_MQ_MEM_RD_ADDR 0x00003c84
#define BNX2_MQ_MEM_RD_ADDR_VALUE (0x3fL<<0)
@@ -2545,6 +4438,16 @@ struct l2_fhdr {
#define BNX2_MQ_MEM_RD_DATA2 0x00003c90
#define BNX2_MQ_MEM_RD_DATA2_VALUE (0x3fffffffL<<0)
+#define BNX2_MQ_MEM_RD_DATA2_VALUE_XI (0x7fffffffL<<0)
+
+
+/*
+ * tsch_reg definition
+ * offset: 0x4c00
+ */
+#define BNX2_TSCH_TSS_CFG 0x00004c1c
+#define BNX2_TSCH_TSS_CFG_TSS_START_CID (0x7ffL<<8)
+#define BNX2_TSCH_TSS_CFG_NUM_OF_TSS_CON (0xfL<<24)
@@ -2594,7 +4497,11 @@ struct l2_fhdr {
#define BNX2_TBDR_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
#define BNX2_TBDR_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
-#define BNX2_TBDR_FTQ_DATA 0x000053c0
+#define BNX2_TBDR_CKSUM_ERROR_STATUS 0x00005010
+#define BNX2_TBDR_CKSUM_ERROR_STATUS_CALCULATED (0xffffL<<0)
+#define BNX2_TBDR_CKSUM_ERROR_STATUS_EXPECTED (0xffffL<<16)
+
+#define BNX2_TBDR_TBDRQ 0x000053c0
#define BNX2_TBDR_FTQ_CMD 0x000053f8
#define BNX2_TBDR_FTQ_CMD_OFFSET (0x3ffL<<0)
#define BNX2_TBDR_FTQ_CMD_WR_TOP (1L<<10)
@@ -2624,7 +4531,15 @@ struct l2_fhdr {
#define BNX2_TDMA_COMMAND 0x00005c00
#define BNX2_TDMA_COMMAND_ENABLED (1L<<0)
#define BNX2_TDMA_COMMAND_MASTER_ABORT (1L<<4)
+#define BNX2_TDMA_COMMAND_CS16_ERR (1L<<5)
#define BNX2_TDMA_COMMAND_BAD_L2_LENGTH_ABORT (1L<<7)
+#define BNX2_TDMA_COMMAND_MASK_CS1 (1L<<20)
+#define BNX2_TDMA_COMMAND_MASK_CS2 (1L<<21)
+#define BNX2_TDMA_COMMAND_MASK_CS3 (1L<<22)
+#define BNX2_TDMA_COMMAND_MASK_CS4 (1L<<23)
+#define BNX2_TDMA_COMMAND_FORCE_ILOCK_CKERR (1L<<24)
+#define BNX2_TDMA_COMMAND_OFIFO_CLR (1L<<30)
+#define BNX2_TDMA_COMMAND_IFIFO_CLR (1L<<31)
#define BNX2_TDMA_STATUS 0x00005c04
#define BNX2_TDMA_STATUS_DMA_WAIT (1L<<0)
@@ -2633,10 +4548,18 @@ struct l2_fhdr {
#define BNX2_TDMA_STATUS_LOCK_WAIT (1L<<3)
#define BNX2_TDMA_STATUS_FTQ_ENTRY_CNT (1L<<16)
#define BNX2_TDMA_STATUS_BURST_CNT (1L<<17)
+#define BNX2_TDMA_STATUS_MAX_IFIFO_DEPTH (0x3fL<<20)
+#define BNX2_TDMA_STATUS_OFIFO_OVERFLOW (1L<<30)
+#define BNX2_TDMA_STATUS_IFIFO_OVERFLOW (1L<<31)
#define BNX2_TDMA_CONFIG 0x00005c08
#define BNX2_TDMA_CONFIG_ONE_DMA (1L<<0)
#define BNX2_TDMA_CONFIG_ONE_RECORD (1L<<1)
+#define BNX2_TDMA_CONFIG_NUM_DMA_CHAN (0x3L<<2)
+#define BNX2_TDMA_CONFIG_NUM_DMA_CHAN_0 (0L<<2)
+#define BNX2_TDMA_CONFIG_NUM_DMA_CHAN_1 (1L<<2)
+#define BNX2_TDMA_CONFIG_NUM_DMA_CHAN_2 (2L<<2)
+#define BNX2_TDMA_CONFIG_NUM_DMA_CHAN_3 (3L<<2)
#define BNX2_TDMA_CONFIG_LIMIT_SZ (0xfL<<4)
#define BNX2_TDMA_CONFIG_LIMIT_SZ_64 (0L<<4)
#define BNX2_TDMA_CONFIG_LIMIT_SZ_128 (0x4L<<4)
@@ -2649,7 +4572,35 @@ struct l2_fhdr {
#define BNX2_TDMA_CONFIG_LINE_SZ_512 (8L<<8)
#define BNX2_TDMA_CONFIG_ALIGN_ENA (1L<<15)
#define BNX2_TDMA_CONFIG_CHK_L2_BD (1L<<16)
+#define BNX2_TDMA_CONFIG_CMPL_ENTRY (1L<<17)
+#define BNX2_TDMA_CONFIG_OFIFO_CMP (1L<<19)
+#define BNX2_TDMA_CONFIG_OFIFO_CMP_3 (0L<<19)
+#define BNX2_TDMA_CONFIG_OFIFO_CMP_2 (1L<<19)
#define BNX2_TDMA_CONFIG_FIFO_CMP (0xfL<<20)
+#define BNX2_TDMA_CONFIG_IFIFO_DEPTH_XI (0x7L<<20)
+#define BNX2_TDMA_CONFIG_IFIFO_DEPTH_0_XI (0L<<20)
+#define BNX2_TDMA_CONFIG_IFIFO_DEPTH_4_XI (1L<<20)
+#define BNX2_TDMA_CONFIG_IFIFO_DEPTH_8_XI (2L<<20)
+#define BNX2_TDMA_CONFIG_IFIFO_DEPTH_16_XI (3L<<20)
+#define BNX2_TDMA_CONFIG_IFIFO_DEPTH_32_XI (4L<<20)
+#define BNX2_TDMA_CONFIG_IFIFO_DEPTH_64_XI (5L<<20)
+#define BNX2_TDMA_CONFIG_FIFO_CMP_EN_XI (1L<<23)
+#define BNX2_TDMA_CONFIG_BYTES_OST_XI (0x7L<<24)
+#define BNX2_TDMA_CONFIG_BYTES_OST_512_XI (0L<<24)
+#define BNX2_TDMA_CONFIG_BYTES_OST_1024_XI (1L<<24)
+#define BNX2_TDMA_CONFIG_BYTES_OST_2048_XI (2L<<24)
+#define BNX2_TDMA_CONFIG_BYTES_OST_4096_XI (3L<<24)
+#define BNX2_TDMA_CONFIG_BYTES_OST_8192_XI (4L<<24)
+#define BNX2_TDMA_CONFIG_BYTES_OST_16384_XI (5L<<24)
+#define BNX2_TDMA_CONFIG_HC_BYPASS_XI (1L<<27)
+#define BNX2_TDMA_CONFIG_LCL_MRRS_XI (0x7L<<28)
+#define BNX2_TDMA_CONFIG_LCL_MRRS_128_XI (0L<<28)
+#define BNX2_TDMA_CONFIG_LCL_MRRS_256_XI (1L<<28)
+#define BNX2_TDMA_CONFIG_LCL_MRRS_512_XI (2L<<28)
+#define BNX2_TDMA_CONFIG_LCL_MRRS_1024_XI (3L<<28)
+#define BNX2_TDMA_CONFIG_LCL_MRRS_2048_XI (4L<<28)
+#define BNX2_TDMA_CONFIG_LCL_MRRS_4096_XI (5L<<28)
+#define BNX2_TDMA_CONFIG_LCL_MRRS_EN_XI (1L<<31)
#define BNX2_TDMA_PAYLOAD_PROD 0x00005c0c
#define BNX2_TDMA_PAYLOAD_PROD_VALUE (0x1fffL<<3)
@@ -2685,7 +4636,22 @@ struct l2_fhdr {
#define BNX2_TDMA_DR_INTF_STATUS_NXT_PNTR (0xfL<<12)
#define BNX2_TDMA_DR_INTF_STATUS_BYTE_COUNT (0x7L<<16)
-#define BNX2_TDMA_FTQ_DATA 0x00005fc0
+#define BNX2_TDMA_PUSH_FSM 0x00005c90
+#define BNX2_TDMA_BD_IF_DEBUG 0x00005c94
+#define BNX2_TDMA_DMAD_IF_DEBUG 0x00005c98
+#define BNX2_TDMA_CTX_IF_DEBUG 0x00005c9c
+#define BNX2_TDMA_TPBUF_IF_DEBUG 0x00005ca0
+#define BNX2_TDMA_DR_IF_DEBUG 0x00005ca4
+#define BNX2_TDMA_TPATQ_IF_DEBUG 0x00005ca8
+#define BNX2_TDMA_TDMA_ILOCK_CKSUM 0x00005cac
+#define BNX2_TDMA_TDMA_ILOCK_CKSUM_CALCULATED (0xffffL<<0)
+#define BNX2_TDMA_TDMA_ILOCK_CKSUM_EXPECTED (0xffffL<<16)
+
+#define BNX2_TDMA_TDMA_PCIE_CKSUM 0x00005cb0
+#define BNX2_TDMA_TDMA_PCIE_CKSUM_CALCULATED (0xffffL<<0)
+#define BNX2_TDMA_TDMA_PCIE_CKSUM_EXPECTED (0xffffL<<16)
+
+#define BNX2_TDMA_TDMAQ 0x00005fc0
#define BNX2_TDMA_FTQ_CMD 0x00005ff8
#define BNX2_TDMA_FTQ_CMD_OFFSET (0x3ffL<<0)
#define BNX2_TDMA_FTQ_CMD_WR_TOP (1L<<10)
@@ -2724,6 +4690,8 @@ struct l2_fhdr {
#define BNX2_HC_COMMAND_FORCE_INT_LOW (2L<<19)
#define BNX2_HC_COMMAND_FORCE_INT_FREE (3L<<19)
#define BNX2_HC_COMMAND_CLR_STAT_NOW (1L<<21)
+#define BNX2_HC_COMMAND_MAIN_PWR_INT (1L<<22)
+#define BNX2_HC_COMMAND_COAL_ON_NEXT_EVENT (1L<<27)
#define BNX2_HC_STATUS 0x00006804
#define BNX2_HC_STATUS_MASTER_ABORT (1L<<0)
@@ -2746,6 +4714,23 @@ struct l2_fhdr {
#define BNX2_HC_CONFIG_STATISTIC_PRIORITY (1L<<5)
#define BNX2_HC_CONFIG_STATUS_PRIORITY (1L<<6)
#define BNX2_HC_CONFIG_STAT_MEM_ADDR (0xffL<<8)
+#define BNX2_HC_CONFIG_PER_MODE (1L<<16)
+#define BNX2_HC_CONFIG_ONE_SHOT (1L<<17)
+#define BNX2_HC_CONFIG_USE_INT_PARAM (1L<<18)
+#define BNX2_HC_CONFIG_SET_MASK_AT_RD (1L<<19)
+#define BNX2_HC_CONFIG_PER_COLLECT_LIMIT (0xfL<<20)
+#define BNX2_HC_CONFIG_SB_ADDR_INC (0x7L<<24)
+#define BNX2_HC_CONFIG_SB_ADDR_INC_64B (0L<<24)
+#define BNX2_HC_CONFIG_SB_ADDR_INC_128B (1L<<24)
+#define BNX2_HC_CONFIG_SB_ADDR_INC_256B (2L<<24)
+#define BNX2_HC_CONFIG_SB_ADDR_INC_512B (3L<<24)
+#define BNX2_HC_CONFIG_SB_ADDR_INC_1024B (4L<<24)
+#define BNX2_HC_CONFIG_SB_ADDR_INC_2048B (5L<<24)
+#define BNX2_HC_CONFIG_SB_ADDR_INC_4096B (6L<<24)
+#define BNX2_HC_CONFIG_SB_ADDR_INC_8192B (7L<<24)
+#define BNX2_HC_CONFIG_GEN_STAT_AVG_INTR (1L<<29)
+#define BNX2_HC_CONFIG_UNMASK_ALL (1L<<30)
+#define BNX2_HC_CONFIG_TX_SEL (1L<<31)
#define BNX2_HC_ATTN_BITS_ENABLE 0x0000680c
#define BNX2_HC_STATUS_ADDR_L 0x00006810
@@ -2782,6 +4767,7 @@ struct l2_fhdr {
#define BNX2_HC_PERIODIC_TICKS 0x0000683c
#define BNX2_HC_PERIODIC_TICKS_HC_PERIODIC_TICKS (0xffffL<<0)
+#define BNX2_HC_PERIODIC_TICKS_HC_INT_PERIODIC_TICKS (0xffffL<<16)
#define BNX2_HC_STAT_COLLECT_TICKS 0x00006840
#define BNX2_HC_STAT_COLLECT_TICKS_HC_STAT_COLL_TICKS (0xffL<<4)
@@ -2789,6 +4775,10 @@ struct l2_fhdr {
#define BNX2_HC_STATS_TICKS 0x00006844
#define BNX2_HC_STATS_TICKS_HC_STAT_TICKS (0xffffL<<8)
+#define BNX2_HC_STATS_INTERRUPT_STATUS 0x00006848
+#define BNX2_HC_STATS_INTERRUPT_STATUS_SB_STATUS (0x1ffL<<0)
+#define BNX2_HC_STATS_INTERRUPT_STATUS_INT_STATUS (0x1ffL<<16)
+
#define BNX2_HC_STAT_MEM_DATA 0x0000684c
#define BNX2_HC_STAT_GEN_SEL_0 0x00006850
#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0 (0x7fL<<0)
@@ -2917,24 +4907,108 @@ struct l2_fhdr {
#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_1 (0x7fL<<8)
#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_2 (0x7fL<<16)
#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_3 (0x7fL<<24)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_XI (0xffL<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UMP_RX_FRAME_DROP_XI (52L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S0_XI (57L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S1_XI (58L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S2_XI (85L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S3_XI (86L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S4_XI (87L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S5_XI (88L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S6_XI (89L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S7_XI (90L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S8_XI (91L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S9_XI (92L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S10_XI (93L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MQ_IDB_OFLOW_XI (94L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_BLK_RD_CNT_XI (123L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_BLK_WR_CNT_XI (124L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_HITS_XI (125L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_MISSES_XI (126L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC1_XI (128L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC1_XI (129L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC1_XI (130L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC1_XI (131L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC1_XI (132L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC1_XI (133L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC2_XI (134L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC2_XI (135L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC2_XI (136L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC2_XI (137L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC2_XI (138L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC2_XI (139L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC3_XI (140L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC3_XI (141L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC3_XI (142L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC3_XI (143L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC3_XI (144L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC3_XI (145L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC4_XI (146L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC4_XI (147L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC4_XI (148L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC4_XI (149L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC4_XI (150L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC4_XI (151L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC5_XI (152L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC5_XI (153L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC5_XI (154L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC5_XI (155L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC5_XI (156L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC5_XI (157L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC6_XI (158L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC6_XI (159L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC6_XI (160L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC6_XI (161L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC6_XI (162L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC6_XI (163L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC7_XI (164L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC7_XI (165L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC7_XI (166L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC7_XI (167L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC7_XI (168L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC7_XI (169L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC8_XI (170L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC8_XI (171L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC8_XI (172L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC8_XI (173L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC8_XI (174L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC8_XI (175L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PCS_CMD_CNT_XI (176L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PCS_SLOT_CNT_XI (177L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PCSQ_VALID_CNT_XI (178L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_1_XI (0xffL<<8)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_2_XI (0xffL<<16)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_3_XI (0xffL<<24)
#define BNX2_HC_STAT_GEN_SEL_1 0x00006854
#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_4 (0x7fL<<0)
#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_5 (0x7fL<<8)
#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_6 (0x7fL<<16)
#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_7 (0x7fL<<24)
+#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_4_XI (0xffL<<0)
+#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_5_XI (0xffL<<8)
+#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_6_XI (0xffL<<16)
+#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_7_XI (0xffL<<24)
#define BNX2_HC_STAT_GEN_SEL_2 0x00006858
#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_8 (0x7fL<<0)
#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_9 (0x7fL<<8)
#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_10 (0x7fL<<16)
#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_11 (0x7fL<<24)
+#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_8_XI (0xffL<<0)
+#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_9_XI (0xffL<<8)
+#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_10_XI (0xffL<<16)
+#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_11_XI (0xffL<<24)
#define BNX2_HC_STAT_GEN_SEL_3 0x0000685c
#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_12 (0x7fL<<0)
#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_13 (0x7fL<<8)
#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_14 (0x7fL<<16)
#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_15 (0x7fL<<24)
+#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_12_XI (0xffL<<0)
+#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_13_XI (0xffL<<8)
+#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_14_XI (0xffL<<16)
+#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_15_XI (0xffL<<24)
#define BNX2_HC_STAT_GEN_STAT0 0x00006888
#define BNX2_HC_STAT_GEN_STAT1 0x0000688c
@@ -2968,6 +5042,7 @@ struct l2_fhdr {
#define BNX2_HC_STAT_GEN_STAT_AC13 0x000068fc
#define BNX2_HC_STAT_GEN_STAT_AC14 0x00006900
#define BNX2_HC_STAT_GEN_STAT_AC15 0x00006904
+#define BNX2_HC_STAT_GEN_STAT_AC 0x000068c8
#define BNX2_HC_VIS 0x00006908
#define BNX2_HC_VIS_STAT_BUILD_STATE (0xfL<<0)
#define BNX2_HC_VIS_STAT_BUILD_STATE_IDLE (0L<<0)
@@ -3038,6 +5113,349 @@ struct l2_fhdr {
#define BNX2_HC_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
#define BNX2_HC_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+#define BNX2_HC_COALESCE_NOW 0x00006914
+#define BNX2_HC_COALESCE_NOW_COAL_NOW (0x1ffL<<1)
+#define BNX2_HC_COALESCE_NOW_COAL_NOW_WO_INT (0x1ffL<<11)
+#define BNX2_HC_COALESCE_NOW_COAL_ON_NXT_EVENT (0x1ffL<<21)
+
+#define BNX2_HC_MSIX_BIT_VECTOR 0x00006918
+#define BNX2_HC_MSIX_BIT_VECTOR_VAL (0x1ffL<<0)
+
+#define BNX2_HC_SB_CONFIG_1 0x00006a00
+#define BNX2_HC_SB_CONFIG_1_RX_TMR_MODE (1L<<1)
+#define BNX2_HC_SB_CONFIG_1_TX_TMR_MODE (1L<<2)
+#define BNX2_HC_SB_CONFIG_1_COM_TMR_MODE (1L<<3)
+#define BNX2_HC_SB_CONFIG_1_CMD_TMR_MODE (1L<<4)
+#define BNX2_HC_SB_CONFIG_1_PER_MODE (1L<<16)
+#define BNX2_HC_SB_CONFIG_1_ONE_SHOT (1L<<17)
+#define BNX2_HC_SB_CONFIG_1_USE_INT_PARAM (1L<<18)
+#define BNX2_HC_SB_CONFIG_1_PER_COLLECT_LIMIT (0xfL<<20)
+
+#define BNX2_HC_TX_QUICK_CONS_TRIP_1 0x00006a04
+#define BNX2_HC_TX_QUICK_CONS_TRIP_1_VALUE (0xffL<<0)
+#define BNX2_HC_TX_QUICK_CONS_TRIP_1_INT (0xffL<<16)
+
+#define BNX2_HC_COMP_PROD_TRIP_1 0x00006a08
+#define BNX2_HC_COMP_PROD_TRIP_1_VALUE (0xffL<<0)
+#define BNX2_HC_COMP_PROD_TRIP_1_INT (0xffL<<16)
+
+#define BNX2_HC_RX_QUICK_CONS_TRIP_1 0x00006a0c
+#define BNX2_HC_RX_QUICK_CONS_TRIP_1_VALUE (0xffL<<0)
+#define BNX2_HC_RX_QUICK_CONS_TRIP_1_INT (0xffL<<16)
+
+#define BNX2_HC_RX_TICKS_1 0x00006a10
+#define BNX2_HC_RX_TICKS_1_VALUE (0x3ffL<<0)
+#define BNX2_HC_RX_TICKS_1_INT (0x3ffL<<16)
+
+#define BNX2_HC_TX_TICKS_1 0x00006a14
+#define BNX2_HC_TX_TICKS_1_VALUE (0x3ffL<<0)
+#define BNX2_HC_TX_TICKS_1_INT (0x3ffL<<16)
+
+#define BNX2_HC_COM_TICKS_1 0x00006a18
+#define BNX2_HC_COM_TICKS_1_VALUE (0x3ffL<<0)
+#define BNX2_HC_COM_TICKS_1_INT (0x3ffL<<16)
+
+#define BNX2_HC_CMD_TICKS_1 0x00006a1c
+#define BNX2_HC_CMD_TICKS_1_VALUE (0x3ffL<<0)
+#define BNX2_HC_CMD_TICKS_1_INT (0x3ffL<<16)
+
+#define BNX2_HC_PERIODIC_TICKS_1 0x00006a20
+#define BNX2_HC_PERIODIC_TICKS_1_HC_PERIODIC_TICKS (0xffffL<<0)
+#define BNX2_HC_PERIODIC_TICKS_1_HC_INT_PERIODIC_TICKS (0xffffL<<16)
+
+#define BNX2_HC_SB_CONFIG_2 0x00006a24
+#define BNX2_HC_SB_CONFIG_2_RX_TMR_MODE (1L<<1)
+#define BNX2_HC_SB_CONFIG_2_TX_TMR_MODE (1L<<2)
+#define BNX2_HC_SB_CONFIG_2_COM_TMR_MODE (1L<<3)
+#define BNX2_HC_SB_CONFIG_2_CMD_TMR_MODE (1L<<4)
+#define BNX2_HC_SB_CONFIG_2_PER_MODE (1L<<16)
+#define BNX2_HC_SB_CONFIG_2_ONE_SHOT (1L<<17)
+#define BNX2_HC_SB_CONFIG_2_USE_INT_PARAM (1L<<18)
+#define BNX2_HC_SB_CONFIG_2_PER_COLLECT_LIMIT (0xfL<<20)
+
+#define BNX2_HC_TX_QUICK_CONS_TRIP_2 0x00006a28
+#define BNX2_HC_TX_QUICK_CONS_TRIP_2_VALUE (0xffL<<0)
+#define BNX2_HC_TX_QUICK_CONS_TRIP_2_INT (0xffL<<16)
+
+#define BNX2_HC_COMP_PROD_TRIP_2 0x00006a2c
+#define BNX2_HC_COMP_PROD_TRIP_2_VALUE (0xffL<<0)
+#define BNX2_HC_COMP_PROD_TRIP_2_INT (0xffL<<16)
+
+#define BNX2_HC_RX_QUICK_CONS_TRIP_2 0x00006a30
+#define BNX2_HC_RX_QUICK_CONS_TRIP_2_VALUE (0xffL<<0)
+#define BNX2_HC_RX_QUICK_CONS_TRIP_2_INT (0xffL<<16)
+
+#define BNX2_HC_RX_TICKS_2 0x00006a34
+#define BNX2_HC_RX_TICKS_2_VALUE (0x3ffL<<0)
+#define BNX2_HC_RX_TICKS_2_INT (0x3ffL<<16)
+
+#define BNX2_HC_TX_TICKS_2 0x00006a38
+#define BNX2_HC_TX_TICKS_2_VALUE (0x3ffL<<0)
+#define BNX2_HC_TX_TICKS_2_INT (0x3ffL<<16)
+
+#define BNX2_HC_COM_TICKS_2 0x00006a3c
+#define BNX2_HC_COM_TICKS_2_VALUE (0x3ffL<<0)
+#define BNX2_HC_COM_TICKS_2_INT (0x3ffL<<16)
+
+#define BNX2_HC_CMD_TICKS_2 0x00006a40
+#define BNX2_HC_CMD_TICKS_2_VALUE (0x3ffL<<0)
+#define BNX2_HC_CMD_TICKS_2_INT (0x3ffL<<16)
+
+#define BNX2_HC_PERIODIC_TICKS_2 0x00006a44
+#define BNX2_HC_PERIODIC_TICKS_2_HC_PERIODIC_TICKS (0xffffL<<0)
+#define BNX2_HC_PERIODIC_TICKS_2_HC_INT_PERIODIC_TICKS (0xffffL<<16)
+
+#define BNX2_HC_SB_CONFIG_3 0x00006a48
+#define BNX2_HC_SB_CONFIG_3_RX_TMR_MODE (1L<<1)
+#define BNX2_HC_SB_CONFIG_3_TX_TMR_MODE (1L<<2)
+#define BNX2_HC_SB_CONFIG_3_COM_TMR_MODE (1L<<3)
+#define BNX2_HC_SB_CONFIG_3_CMD_TMR_MODE (1L<<4)
+#define BNX2_HC_SB_CONFIG_3_PER_MODE (1L<<16)
+#define BNX2_HC_SB_CONFIG_3_ONE_SHOT (1L<<17)
+#define BNX2_HC_SB_CONFIG_3_USE_INT_PARAM (1L<<18)
+#define BNX2_HC_SB_CONFIG_3_PER_COLLECT_LIMIT (0xfL<<20)
+
+#define BNX2_HC_TX_QUICK_CONS_TRIP_3 0x00006a4c
+#define BNX2_HC_TX_QUICK_CONS_TRIP_3_VALUE (0xffL<<0)
+#define BNX2_HC_TX_QUICK_CONS_TRIP_3_INT (0xffL<<16)
+
+#define BNX2_HC_COMP_PROD_TRIP_3 0x00006a50
+#define BNX2_HC_COMP_PROD_TRIP_3_VALUE (0xffL<<0)
+#define BNX2_HC_COMP_PROD_TRIP_3_INT (0xffL<<16)
+
+#define BNX2_HC_RX_QUICK_CONS_TRIP_3 0x00006a54
+#define BNX2_HC_RX_QUICK_CONS_TRIP_3_VALUE (0xffL<<0)
+#define BNX2_HC_RX_QUICK_CONS_TRIP_3_INT (0xffL<<16)
+
+#define BNX2_HC_RX_TICKS_3 0x00006a58
+#define BNX2_HC_RX_TICKS_3_VALUE (0x3ffL<<0)
+#define BNX2_HC_RX_TICKS_3_INT (0x3ffL<<16)
+
+#define BNX2_HC_TX_TICKS_3 0x00006a5c
+#define BNX2_HC_TX_TICKS_3_VALUE (0x3ffL<<0)
+#define BNX2_HC_TX_TICKS_3_INT (0x3ffL<<16)
+
+#define BNX2_HC_COM_TICKS_3 0x00006a60
+#define BNX2_HC_COM_TICKS_3_VALUE (0x3ffL<<0)
+#define BNX2_HC_COM_TICKS_3_INT (0x3ffL<<16)
+
+#define BNX2_HC_CMD_TICKS_3 0x00006a64
+#define BNX2_HC_CMD_TICKS_3_VALUE (0x3ffL<<0)
+#define BNX2_HC_CMD_TICKS_3_INT (0x3ffL<<16)
+
+#define BNX2_HC_PERIODIC_TICKS_3 0x00006a68
+#define BNX2_HC_PERIODIC_TICKS_3_HC_PERIODIC_TICKS (0xffffL<<0)
+#define BNX2_HC_PERIODIC_TICKS_3_HC_INT_PERIODIC_TICKS (0xffffL<<16)
+
+#define BNX2_HC_SB_CONFIG_4 0x00006a6c
+#define BNX2_HC_SB_CONFIG_4_RX_TMR_MODE (1L<<1)
+#define BNX2_HC_SB_CONFIG_4_TX_TMR_MODE (1L<<2)
+#define BNX2_HC_SB_CONFIG_4_COM_TMR_MODE (1L<<3)
+#define BNX2_HC_SB_CONFIG_4_CMD_TMR_MODE (1L<<4)
+#define BNX2_HC_SB_CONFIG_4_PER_MODE (1L<<16)
+#define BNX2_HC_SB_CONFIG_4_ONE_SHOT (1L<<17)
+#define BNX2_HC_SB_CONFIG_4_USE_INT_PARAM (1L<<18)
+#define BNX2_HC_SB_CONFIG_4_PER_COLLECT_LIMIT (0xfL<<20)
+
+#define BNX2_HC_TX_QUICK_CONS_TRIP_4 0x00006a70
+#define BNX2_HC_TX_QUICK_CONS_TRIP_4_VALUE (0xffL<<0)
+#define BNX2_HC_TX_QUICK_CONS_TRIP_4_INT (0xffL<<16)
+
+#define BNX2_HC_COMP_PROD_TRIP_4 0x00006a74
+#define BNX2_HC_COMP_PROD_TRIP_4_VALUE (0xffL<<0)
+#define BNX2_HC_COMP_PROD_TRIP_4_INT (0xffL<<16)
+
+#define BNX2_HC_RX_QUICK_CONS_TRIP_4 0x00006a78
+#define BNX2_HC_RX_QUICK_CONS_TRIP_4_VALUE (0xffL<<0)
+#define BNX2_HC_RX_QUICK_CONS_TRIP_4_INT (0xffL<<16)
+
+#define BNX2_HC_RX_TICKS_4 0x00006a7c
+#define BNX2_HC_RX_TICKS_4_VALUE (0x3ffL<<0)
+#define BNX2_HC_RX_TICKS_4_INT (0x3ffL<<16)
+
+#define BNX2_HC_TX_TICKS_4 0x00006a80
+#define BNX2_HC_TX_TICKS_4_VALUE (0x3ffL<<0)
+#define BNX2_HC_TX_TICKS_4_INT (0x3ffL<<16)
+
+#define BNX2_HC_COM_TICKS_4 0x00006a84
+#define BNX2_HC_COM_TICKS_4_VALUE (0x3ffL<<0)
+#define BNX2_HC_COM_TICKS_4_INT (0x3ffL<<16)
+
+#define BNX2_HC_CMD_TICKS_4 0x00006a88
+#define BNX2_HC_CMD_TICKS_4_VALUE (0x3ffL<<0)
+#define BNX2_HC_CMD_TICKS_4_INT (0x3ffL<<16)
+
+#define BNX2_HC_PERIODIC_TICKS_4 0x00006a8c
+#define BNX2_HC_PERIODIC_TICKS_4_HC_PERIODIC_TICKS (0xffffL<<0)
+#define BNX2_HC_PERIODIC_TICKS_4_HC_INT_PERIODIC_TICKS (0xffffL<<16)
+
+#define BNX2_HC_SB_CONFIG_5 0x00006a90
+#define BNX2_HC_SB_CONFIG_5_RX_TMR_MODE (1L<<1)
+#define BNX2_HC_SB_CONFIG_5_TX_TMR_MODE (1L<<2)
+#define BNX2_HC_SB_CONFIG_5_COM_TMR_MODE (1L<<3)
+#define BNX2_HC_SB_CONFIG_5_CMD_TMR_MODE (1L<<4)
+#define BNX2_HC_SB_CONFIG_5_PER_MODE (1L<<16)
+#define BNX2_HC_SB_CONFIG_5_ONE_SHOT (1L<<17)
+#define BNX2_HC_SB_CONFIG_5_USE_INT_PARAM (1L<<18)
+#define BNX2_HC_SB_CONFIG_5_PER_COLLECT_LIMIT (0xfL<<20)
+
+#define BNX2_HC_TX_QUICK_CONS_TRIP_5 0x00006a94
+#define BNX2_HC_TX_QUICK_CONS_TRIP_5_VALUE (0xffL<<0)
+#define BNX2_HC_TX_QUICK_CONS_TRIP_5_INT (0xffL<<16)
+
+#define BNX2_HC_COMP_PROD_TRIP_5 0x00006a98
+#define BNX2_HC_COMP_PROD_TRIP_5_VALUE (0xffL<<0)
+#define BNX2_HC_COMP_PROD_TRIP_5_INT (0xffL<<16)
+
+#define BNX2_HC_RX_QUICK_CONS_TRIP_5 0x00006a9c
+#define BNX2_HC_RX_QUICK_CONS_TRIP_5_VALUE (0xffL<<0)
+#define BNX2_HC_RX_QUICK_CONS_TRIP_5_INT (0xffL<<16)
+
+#define BNX2_HC_RX_TICKS_5 0x00006aa0
+#define BNX2_HC_RX_TICKS_5_VALUE (0x3ffL<<0)
+#define BNX2_HC_RX_TICKS_5_INT (0x3ffL<<16)
+
+#define BNX2_HC_TX_TICKS_5 0x00006aa4
+#define BNX2_HC_TX_TICKS_5_VALUE (0x3ffL<<0)
+#define BNX2_HC_TX_TICKS_5_INT (0x3ffL<<16)
+
+#define BNX2_HC_COM_TICKS_5 0x00006aa8
+#define BNX2_HC_COM_TICKS_5_VALUE (0x3ffL<<0)
+#define BNX2_HC_COM_TICKS_5_INT (0x3ffL<<16)
+
+#define BNX2_HC_CMD_TICKS_5 0x00006aac
+#define BNX2_HC_CMD_TICKS_5_VALUE (0x3ffL<<0)
+#define BNX2_HC_CMD_TICKS_5_INT (0x3ffL<<16)
+
+#define BNX2_HC_PERIODIC_TICKS_5 0x00006ab0
+#define BNX2_HC_PERIODIC_TICKS_5_HC_PERIODIC_TICKS (0xffffL<<0)
+#define BNX2_HC_PERIODIC_TICKS_5_HC_INT_PERIODIC_TICKS (0xffffL<<16)
+
+#define BNX2_HC_SB_CONFIG_6 0x00006ab4
+#define BNX2_HC_SB_CONFIG_6_RX_TMR_MODE (1L<<1)
+#define BNX2_HC_SB_CONFIG_6_TX_TMR_MODE (1L<<2)
+#define BNX2_HC_SB_CONFIG_6_COM_TMR_MODE (1L<<3)
+#define BNX2_HC_SB_CONFIG_6_CMD_TMR_MODE (1L<<4)
+#define BNX2_HC_SB_CONFIG_6_PER_MODE (1L<<16)
+#define BNX2_HC_SB_CONFIG_6_ONE_SHOT (1L<<17)
+#define BNX2_HC_SB_CONFIG_6_USE_INT_PARAM (1L<<18)
+#define BNX2_HC_SB_CONFIG_6_PER_COLLECT_LIMIT (0xfL<<20)
+
+#define BNX2_HC_TX_QUICK_CONS_TRIP_6 0x00006ab8
+#define BNX2_HC_TX_QUICK_CONS_TRIP_6_VALUE (0xffL<<0)
+#define BNX2_HC_TX_QUICK_CONS_TRIP_6_INT (0xffL<<16)
+
+#define BNX2_HC_COMP_PROD_TRIP_6 0x00006abc
+#define BNX2_HC_COMP_PROD_TRIP_6_VALUE (0xffL<<0)
+#define BNX2_HC_COMP_PROD_TRIP_6_INT (0xffL<<16)
+
+#define BNX2_HC_RX_QUICK_CONS_TRIP_6 0x00006ac0
+#define BNX2_HC_RX_QUICK_CONS_TRIP_6_VALUE (0xffL<<0)
+#define BNX2_HC_RX_QUICK_CONS_TRIP_6_INT (0xffL<<16)
+
+#define BNX2_HC_RX_TICKS_6 0x00006ac4
+#define BNX2_HC_RX_TICKS_6_VALUE (0x3ffL<<0)
+#define BNX2_HC_RX_TICKS_6_INT (0x3ffL<<16)
+
+#define BNX2_HC_TX_TICKS_6 0x00006ac8
+#define BNX2_HC_TX_TICKS_6_VALUE (0x3ffL<<0)
+#define BNX2_HC_TX_TICKS_6_INT (0x3ffL<<16)
+
+#define BNX2_HC_COM_TICKS_6 0x00006acc
+#define BNX2_HC_COM_TICKS_6_VALUE (0x3ffL<<0)
+#define BNX2_HC_COM_TICKS_6_INT (0x3ffL<<16)
+
+#define BNX2_HC_CMD_TICKS_6 0x00006ad0
+#define BNX2_HC_CMD_TICKS_6_VALUE (0x3ffL<<0)
+#define BNX2_HC_CMD_TICKS_6_INT (0x3ffL<<16)
+
+#define BNX2_HC_PERIODIC_TICKS_6 0x00006ad4
+#define BNX2_HC_PERIODIC_TICKS_6_HC_PERIODIC_TICKS (0xffffL<<0)
+#define BNX2_HC_PERIODIC_TICKS_6_HC_INT_PERIODIC_TICKS (0xffffL<<16)
+
+#define BNX2_HC_SB_CONFIG_7 0x00006ad8
+#define BNX2_HC_SB_CONFIG_7_RX_TMR_MODE (1L<<1)
+#define BNX2_HC_SB_CONFIG_7_TX_TMR_MODE (1L<<2)
+#define BNX2_HC_SB_CONFIG_7_COM_TMR_MODE (1L<<3)
+#define BNX2_HC_SB_CONFIG_7_CMD_TMR_MODE (1L<<4)
+#define BNX2_HC_SB_CONFIG_7_PER_MODE (1L<<16)
+#define BNX2_HC_SB_CONFIG_7_ONE_SHOT (1L<<17)
+#define BNX2_HC_SB_CONFIG_7_USE_INT_PARAM (1L<<18)
+#define BNX2_HC_SB_CONFIG_7_PER_COLLECT_LIMIT (0xfL<<20)
+
+#define BNX2_HC_TX_QUICK_CONS_TRIP_7 0x00006adc
+#define BNX2_HC_TX_QUICK_CONS_TRIP_7_VALUE (0xffL<<0)
+#define BNX2_HC_TX_QUICK_CONS_TRIP_7_INT (0xffL<<16)
+
+#define BNX2_HC_COMP_PROD_TRIP_7 0x00006ae0
+#define BNX2_HC_COMP_PROD_TRIP_7_VALUE (0xffL<<0)
+#define BNX2_HC_COMP_PROD_TRIP_7_INT (0xffL<<16)
+
+#define BNX2_HC_RX_QUICK_CONS_TRIP_7 0x00006ae4
+#define BNX2_HC_RX_QUICK_CONS_TRIP_7_VALUE (0xffL<<0)
+#define BNX2_HC_RX_QUICK_CONS_TRIP_7_INT (0xffL<<16)
+
+#define BNX2_HC_RX_TICKS_7 0x00006ae8
+#define BNX2_HC_RX_TICKS_7_VALUE (0x3ffL<<0)
+#define BNX2_HC_RX_TICKS_7_INT (0x3ffL<<16)
+
+#define BNX2_HC_TX_TICKS_7 0x00006aec
+#define BNX2_HC_TX_TICKS_7_VALUE (0x3ffL<<0)
+#define BNX2_HC_TX_TICKS_7_INT (0x3ffL<<16)
+
+#define BNX2_HC_COM_TICKS_7 0x00006af0
+#define BNX2_HC_COM_TICKS_7_VALUE (0x3ffL<<0)
+#define BNX2_HC_COM_TICKS_7_INT (0x3ffL<<16)
+
+#define BNX2_HC_CMD_TICKS_7 0x00006af4
+#define BNX2_HC_CMD_TICKS_7_VALUE (0x3ffL<<0)
+#define BNX2_HC_CMD_TICKS_7_INT (0x3ffL<<16)
+
+#define BNX2_HC_PERIODIC_TICKS_7 0x00006af8
+#define BNX2_HC_PERIODIC_TICKS_7_HC_PERIODIC_TICKS (0xffffL<<0)
+#define BNX2_HC_PERIODIC_TICKS_7_HC_INT_PERIODIC_TICKS (0xffffL<<16)
+
+#define BNX2_HC_SB_CONFIG_8 0x00006afc
+#define BNX2_HC_SB_CONFIG_8_RX_TMR_MODE (1L<<1)
+#define BNX2_HC_SB_CONFIG_8_TX_TMR_MODE (1L<<2)
+#define BNX2_HC_SB_CONFIG_8_COM_TMR_MODE (1L<<3)
+#define BNX2_HC_SB_CONFIG_8_CMD_TMR_MODE (1L<<4)
+#define BNX2_HC_SB_CONFIG_8_PER_MODE (1L<<16)
+#define BNX2_HC_SB_CONFIG_8_ONE_SHOT (1L<<17)
+#define BNX2_HC_SB_CONFIG_8_USE_INT_PARAM (1L<<18)
+#define BNX2_HC_SB_CONFIG_8_PER_COLLECT_LIMIT (0xfL<<20)
+
+#define BNX2_HC_TX_QUICK_CONS_TRIP_8 0x00006b00
+#define BNX2_HC_TX_QUICK_CONS_TRIP_8_VALUE (0xffL<<0)
+#define BNX2_HC_TX_QUICK_CONS_TRIP_8_INT (0xffL<<16)
+
+#define BNX2_HC_COMP_PROD_TRIP_8 0x00006b04
+#define BNX2_HC_COMP_PROD_TRIP_8_VALUE (0xffL<<0)
+#define BNX2_HC_COMP_PROD_TRIP_8_INT (0xffL<<16)
+
+#define BNX2_HC_RX_QUICK_CONS_TRIP_8 0x00006b08
+#define BNX2_HC_RX_QUICK_CONS_TRIP_8_VALUE (0xffL<<0)
+#define BNX2_HC_RX_QUICK_CONS_TRIP_8_INT (0xffL<<16)
+
+#define BNX2_HC_RX_TICKS_8 0x00006b0c
+#define BNX2_HC_RX_TICKS_8_VALUE (0x3ffL<<0)
+#define BNX2_HC_RX_TICKS_8_INT (0x3ffL<<16)
+
+#define BNX2_HC_TX_TICKS_8 0x00006b10
+#define BNX2_HC_TX_TICKS_8_VALUE (0x3ffL<<0)
+#define BNX2_HC_TX_TICKS_8_INT (0x3ffL<<16)
+
+#define BNX2_HC_COM_TICKS_8 0x00006b14
+#define BNX2_HC_COM_TICKS_8_VALUE (0x3ffL<<0)
+#define BNX2_HC_COM_TICKS_8_INT (0x3ffL<<16)
+
+#define BNX2_HC_CMD_TICKS_8 0x00006b18
+#define BNX2_HC_CMD_TICKS_8_VALUE (0x3ffL<<0)
+#define BNX2_HC_CMD_TICKS_8_INT (0x3ffL<<16)
+
+#define BNX2_HC_PERIODIC_TICKS_8 0x00006b1c
+#define BNX2_HC_PERIODIC_TICKS_8_HC_PERIODIC_TICKS (0xffffL<<0)
+#define BNX2_HC_PERIODIC_TICKS_8_HC_INT_PERIODIC_TICKS (0xffffL<<16)
/*
@@ -3063,7 +5481,7 @@ struct l2_fhdr {
#define BNX2_TXP_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3)
#define BNX2_TXP_CPU_STATE_PAGE_0_INST_HALTED (1L<<4)
#define BNX2_TXP_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5)
-#define BNX2_TXP_CPU_STATE_BAD_pc_HALTED (1L<<6)
+#define BNX2_TXP_CPU_STATE_BAD_PC_HALTED (1L<<6)
#define BNX2_TXP_CPU_STATE_ALIGN_HALTED (1L<<7)
#define BNX2_TXP_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
#define BNX2_TXP_CPU_STATE_SOFT_HALTED (1L<<10)
@@ -3111,7 +5529,7 @@ struct l2_fhdr {
#define BNX2_TXP_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2)
#define BNX2_TXP_CPU_REG_FILE 0x00045200
-#define BNX2_TXP_FTQ_DATA 0x000453c0
+#define BNX2_TXP_TXPQ 0x000453c0
#define BNX2_TXP_FTQ_CMD 0x000453f8
#define BNX2_TXP_FTQ_CMD_OFFSET (0x3ffL<<0)
#define BNX2_TXP_FTQ_CMD_WR_TOP (1L<<10)
@@ -3158,7 +5576,7 @@ struct l2_fhdr {
#define BNX2_TPAT_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3)
#define BNX2_TPAT_CPU_STATE_PAGE_0_INST_HALTED (1L<<4)
#define BNX2_TPAT_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5)
-#define BNX2_TPAT_CPU_STATE_BAD_pc_HALTED (1L<<6)
+#define BNX2_TPAT_CPU_STATE_BAD_PC_HALTED (1L<<6)
#define BNX2_TPAT_CPU_STATE_ALIGN_HALTED (1L<<7)
#define BNX2_TPAT_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
#define BNX2_TPAT_CPU_STATE_SOFT_HALTED (1L<<10)
@@ -3206,7 +5624,7 @@ struct l2_fhdr {
#define BNX2_TPAT_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2)
#define BNX2_TPAT_CPU_REG_FILE 0x00085200
-#define BNX2_TPAT_FTQ_DATA 0x000853c0
+#define BNX2_TPAT_TPATQ 0x000853c0
#define BNX2_TPAT_FTQ_CMD 0x000853f8
#define BNX2_TPAT_FTQ_CMD_OFFSET (0x3ffL<<0)
#define BNX2_TPAT_FTQ_CMD_WR_TOP (1L<<10)
@@ -3253,7 +5671,7 @@ struct l2_fhdr {
#define BNX2_RXP_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3)
#define BNX2_RXP_CPU_STATE_PAGE_0_INST_HALTED (1L<<4)
#define BNX2_RXP_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5)
-#define BNX2_RXP_CPU_STATE_BAD_pc_HALTED (1L<<6)
+#define BNX2_RXP_CPU_STATE_BAD_PC_HALTED (1L<<6)
#define BNX2_RXP_CPU_STATE_ALIGN_HALTED (1L<<7)
#define BNX2_RXP_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
#define BNX2_RXP_CPU_STATE_SOFT_HALTED (1L<<10)
@@ -3301,7 +5719,29 @@ struct l2_fhdr {
#define BNX2_RXP_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2)
#define BNX2_RXP_CPU_REG_FILE 0x000c5200
-#define BNX2_RXP_CFTQ_DATA 0x000c5380
+#define BNX2_RXP_PFE_PFE_CTL 0x000c537c
+#define BNX2_RXP_PFE_PFE_CTL_INC_USAGE_CNT (1L<<0)
+#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE (0xfL<<4)
+#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_0 (0L<<4)
+#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_1 (1L<<4)
+#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_2 (2L<<4)
+#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_3 (3L<<4)
+#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_4 (4L<<4)
+#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_5 (5L<<4)
+#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_6 (6L<<4)
+#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_7 (7L<<4)
+#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_8 (8L<<4)
+#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_9 (9L<<4)
+#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_10 (10L<<4)
+#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_11 (11L<<4)
+#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_12 (12L<<4)
+#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_13 (13L<<4)
+#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_14 (14L<<4)
+#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_15 (15L<<4)
+#define BNX2_RXP_PFE_PFE_CTL_PFE_COUNT (0xfL<<12)
+#define BNX2_RXP_PFE_PFE_CTL_OFFSET (0x1ffL<<16)
+
+#define BNX2_RXP_RXPCQ 0x000c5380
#define BNX2_RXP_CFTQ_CMD 0x000c53b8
#define BNX2_RXP_CFTQ_CMD_OFFSET (0x3ffL<<0)
#define BNX2_RXP_CFTQ_CMD_WR_TOP (1L<<10)
@@ -3322,7 +5762,7 @@ struct l2_fhdr {
#define BNX2_RXP_CFTQ_CTL_MAX_DEPTH (0x3ffL<<12)
#define BNX2_RXP_CFTQ_CTL_CUR_DEPTH (0x3ffL<<22)
-#define BNX2_RXP_FTQ_DATA 0x000c53c0
+#define BNX2_RXP_RXPQ 0x000c53c0
#define BNX2_RXP_FTQ_CMD 0x000c53f8
#define BNX2_RXP_FTQ_CMD_OFFSET (0x3ffL<<0)
#define BNX2_RXP_FTQ_CMD_WR_TOP (1L<<10)
@@ -3350,6 +5790,10 @@ struct l2_fhdr {
* com_reg definition
* offset: 0x100000
*/
+#define BNX2_COM_CKSUM_ERROR_STATUS 0x00100000
+#define BNX2_COM_CKSUM_ERROR_STATUS_CALCULATED (0xffffL<<0)
+#define BNX2_COM_CKSUM_ERROR_STATUS_EXPECTED (0xffffL<<16)
+
#define BNX2_COM_CPU_MODE 0x00105000
#define BNX2_COM_CPU_MODE_LOCAL_RST (1L<<0)
#define BNX2_COM_CPU_MODE_STEP_ENA (1L<<1)
@@ -3369,7 +5813,7 @@ struct l2_fhdr {
#define BNX2_COM_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3)
#define BNX2_COM_CPU_STATE_PAGE_0_INST_HALTED (1L<<4)
#define BNX2_COM_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5)
-#define BNX2_COM_CPU_STATE_BAD_pc_HALTED (1L<<6)
+#define BNX2_COM_CPU_STATE_BAD_PC_HALTED (1L<<6)
#define BNX2_COM_CPU_STATE_ALIGN_HALTED (1L<<7)
#define BNX2_COM_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
#define BNX2_COM_CPU_STATE_SOFT_HALTED (1L<<10)
@@ -3417,7 +5861,29 @@ struct l2_fhdr {
#define BNX2_COM_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2)
#define BNX2_COM_CPU_REG_FILE 0x00105200
-#define BNX2_COM_COMXQ_FTQ_DATA 0x00105340
+#define BNX2_COM_COMTQ_PFE_PFE_CTL 0x001052bc
+#define BNX2_COM_COMTQ_PFE_PFE_CTL_INC_USAGE_CNT (1L<<0)
+#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE (0xfL<<4)
+#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_0 (0L<<4)
+#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_1 (1L<<4)
+#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_2 (2L<<4)
+#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_3 (3L<<4)
+#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_4 (4L<<4)
+#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_5 (5L<<4)
+#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_6 (6L<<4)
+#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_7 (7L<<4)
+#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_8 (8L<<4)
+#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_9 (9L<<4)
+#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_10 (10L<<4)
+#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_11 (11L<<4)
+#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_12 (12L<<4)
+#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_13 (13L<<4)
+#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_14 (14L<<4)
+#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_15 (15L<<4)
+#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_COUNT (0xfL<<12)
+#define BNX2_COM_COMTQ_PFE_PFE_CTL_OFFSET (0x1ffL<<16)
+
+#define BNX2_COM_COMXQ 0x00105340
#define BNX2_COM_COMXQ_FTQ_CMD 0x00105378
#define BNX2_COM_COMXQ_FTQ_CMD_OFFSET (0x3ffL<<0)
#define BNX2_COM_COMXQ_FTQ_CMD_WR_TOP (1L<<10)
@@ -3438,7 +5904,7 @@ struct l2_fhdr {
#define BNX2_COM_COMXQ_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
#define BNX2_COM_COMXQ_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
-#define BNX2_COM_COMTQ_FTQ_DATA 0x00105380
+#define BNX2_COM_COMTQ 0x00105380
#define BNX2_COM_COMTQ_FTQ_CMD 0x001053b8
#define BNX2_COM_COMTQ_FTQ_CMD_OFFSET (0x3ffL<<0)
#define BNX2_COM_COMTQ_FTQ_CMD_WR_TOP (1L<<10)
@@ -3459,7 +5925,7 @@ struct l2_fhdr {
#define BNX2_COM_COMTQ_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
#define BNX2_COM_COMTQ_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
-#define BNX2_COM_COMQ_FTQ_DATA 0x001053c0
+#define BNX2_COM_COMQ 0x001053c0
#define BNX2_COM_COMQ_FTQ_CMD 0x001053f8
#define BNX2_COM_COMQ_FTQ_CMD_OFFSET (0x3ffL<<0)
#define BNX2_COM_COMQ_FTQ_CMD_WR_TOP (1L<<10)
@@ -3489,6 +5955,10 @@ struct l2_fhdr {
* cp_reg definition
* offset: 0x180000
*/
+#define BNX2_CP_CKSUM_ERROR_STATUS 0x00180000
+#define BNX2_CP_CKSUM_ERROR_STATUS_CALCULATED (0xffffL<<0)
+#define BNX2_CP_CKSUM_ERROR_STATUS_EXPECTED (0xffffL<<16)
+
#define BNX2_CP_CPU_MODE 0x00185000
#define BNX2_CP_CPU_MODE_LOCAL_RST (1L<<0)
#define BNX2_CP_CPU_MODE_STEP_ENA (1L<<1)
@@ -3508,7 +5978,7 @@ struct l2_fhdr {
#define BNX2_CP_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3)
#define BNX2_CP_CPU_STATE_PAGE_0_INST_HALTED (1L<<4)
#define BNX2_CP_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5)
-#define BNX2_CP_CPU_STATE_BAD_pc_HALTED (1L<<6)
+#define BNX2_CP_CPU_STATE_BAD_PC_HALTED (1L<<6)
#define BNX2_CP_CPU_STATE_ALIGN_HALTED (1L<<7)
#define BNX2_CP_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
#define BNX2_CP_CPU_STATE_SOFT_HALTED (1L<<10)
@@ -3556,7 +6026,29 @@ struct l2_fhdr {
#define BNX2_CP_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2)
#define BNX2_CP_CPU_REG_FILE 0x00185200
-#define BNX2_CP_CPQ_FTQ_DATA 0x001853c0
+#define BNX2_CP_CPQ_PFE_PFE_CTL 0x001853bc
+#define BNX2_CP_CPQ_PFE_PFE_CTL_INC_USAGE_CNT (1L<<0)
+#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE (0xfL<<4)
+#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_0 (0L<<4)
+#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_1 (1L<<4)
+#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_2 (2L<<4)
+#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_3 (3L<<4)
+#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_4 (4L<<4)
+#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_5 (5L<<4)
+#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_6 (6L<<4)
+#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_7 (7L<<4)
+#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_8 (8L<<4)
+#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_9 (9L<<4)
+#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_10 (10L<<4)
+#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_11 (11L<<4)
+#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_12 (12L<<4)
+#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_13 (13L<<4)
+#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_14 (14L<<4)
+#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_15 (15L<<4)
+#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_COUNT (0xfL<<12)
+#define BNX2_CP_CPQ_PFE_PFE_CTL_OFFSET (0x1ffL<<16)
+
+#define BNX2_CP_CPQ 0x001853c0
#define BNX2_CP_CPQ_FTQ_CMD 0x001853f8
#define BNX2_CP_CPQ_FTQ_CMD_OFFSET (0x3ffL<<0)
#define BNX2_CP_CPQ_FTQ_CMD_WR_TOP (1L<<10)
@@ -3584,6 +6076,59 @@ struct l2_fhdr {
* mcp_reg definition
* offset: 0x140000
*/
+#define BNX2_MCP_MCP_CONTROL 0x00140080
+#define BNX2_MCP_MCP_CONTROL_SMBUS_SEL (1L<<30)
+#define BNX2_MCP_MCP_CONTROL_MCP_ISOLATE (1L<<31)
+
+#define BNX2_MCP_MCP_ATTENTION_STATUS 0x00140084
+#define BNX2_MCP_MCP_ATTENTION_STATUS_DRV_DOORBELL (1L<<29)
+#define BNX2_MCP_MCP_ATTENTION_STATUS_WATCHDOG_TIMEOUT (1L<<30)
+#define BNX2_MCP_MCP_ATTENTION_STATUS_CPU_EVENT (1L<<31)
+
+#define BNX2_MCP_MCP_HEARTBEAT_CONTROL 0x00140088
+#define BNX2_MCP_MCP_HEARTBEAT_CONTROL_MCP_HEARTBEAT_ENABLE (1L<<31)
+
+#define BNX2_MCP_MCP_HEARTBEAT_STATUS 0x0014008c
+#define BNX2_MCP_MCP_HEARTBEAT_STATUS_MCP_HEARTBEAT_PERIOD (0x7ffL<<0)
+#define BNX2_MCP_MCP_HEARTBEAT_STATUS_VALID (1L<<31)
+
+#define BNX2_MCP_MCP_HEARTBEAT 0x00140090
+#define BNX2_MCP_MCP_HEARTBEAT_MCP_HEARTBEAT_COUNT (0x3fffffffL<<0)
+#define BNX2_MCP_MCP_HEARTBEAT_MCP_HEARTBEAT_INC (1L<<30)
+#define BNX2_MCP_MCP_HEARTBEAT_MCP_HEARTBEAT_RESET (1L<<31)
+
+#define BNX2_MCP_WATCHDOG_RESET 0x00140094
+#define BNX2_MCP_WATCHDOG_RESET_WATCHDOG_RESET (1L<<31)
+
+#define BNX2_MCP_WATCHDOG_CONTROL 0x00140098
+#define BNX2_MCP_WATCHDOG_CONTROL_WATCHDOG_TIMEOUT (0xfffffffL<<0)
+#define BNX2_MCP_WATCHDOG_CONTROL_WATCHDOG_ATTN (1L<<29)
+#define BNX2_MCP_WATCHDOG_CONTROL_MCP_RST_ENABLE (1L<<30)
+#define BNX2_MCP_WATCHDOG_CONTROL_WATCHDOG_ENABLE (1L<<31)
+
+#define BNX2_MCP_ACCESS_LOCK 0x0014009c
+#define BNX2_MCP_ACCESS_LOCK_LOCK (1L<<31)
+
+#define BNX2_MCP_TOE_ID 0x001400a0
+#define BNX2_MCP_TOE_ID_FUNCTION_ID (1L<<31)
+
+#define BNX2_MCP_MAILBOX_CFG 0x001400a4
+#define BNX2_MCP_MAILBOX_CFG_MAILBOX_OFFSET (0x3fffL<<0)
+#define BNX2_MCP_MAILBOX_CFG_MAILBOX_SIZE (0xfffL<<20)
+
+#define BNX2_MCP_MAILBOX_CFG_OTHER_FUNC 0x001400a8
+#define BNX2_MCP_MAILBOX_CFG_OTHER_FUNC_MAILBOX_OFFSET (0x3fffL<<0)
+#define BNX2_MCP_MAILBOX_CFG_OTHER_FUNC_MAILBOX_SIZE (0xfffL<<20)
+
+#define BNX2_MCP_MCP_DOORBELL 0x001400ac
+#define BNX2_MCP_MCP_DOORBELL_MCP_DOORBELL (1L<<31)
+
+#define BNX2_MCP_DRIVER_DOORBELL 0x001400b0
+#define BNX2_MCP_DRIVER_DOORBELL_DRIVER_DOORBELL (1L<<31)
+
+#define BNX2_MCP_DRIVER_DOORBELL_OTHER_FUNC 0x001400b4
+#define BNX2_MCP_DRIVER_DOORBELL_OTHER_FUNC_DRIVER_DOORBELL (1L<<31)
+
#define BNX2_MCP_CPU_MODE 0x00145000
#define BNX2_MCP_CPU_MODE_LOCAL_RST (1L<<0)
#define BNX2_MCP_CPU_MODE_STEP_ENA (1L<<1)
@@ -3603,7 +6148,7 @@ struct l2_fhdr {
#define BNX2_MCP_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3)
#define BNX2_MCP_CPU_STATE_PAGE_0_INST_HALTED (1L<<4)
#define BNX2_MCP_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5)
-#define BNX2_MCP_CPU_STATE_BAD_pc_HALTED (1L<<6)
+#define BNX2_MCP_CPU_STATE_BAD_PC_HALTED (1L<<6)
#define BNX2_MCP_CPU_STATE_ALIGN_HALTED (1L<<7)
#define BNX2_MCP_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
#define BNX2_MCP_CPU_STATE_SOFT_HALTED (1L<<10)
@@ -3651,7 +6196,7 @@ struct l2_fhdr {
#define BNX2_MCP_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2)
#define BNX2_MCP_CPU_REG_FILE 0x00145200
-#define BNX2_MCP_MCPQ_FTQ_DATA 0x001453c0
+#define BNX2_MCP_MCPQ 0x001453c0
#define BNX2_MCP_MCPQ_FTQ_CMD 0x001453f8
#define BNX2_MCP_MCPQ_FTQ_CMD_OFFSET (0x3ffL<<0)
#define BNX2_MCP_MCPQ_FTQ_CMD_WR_TOP (1L<<10)
@@ -3696,6 +6241,8 @@ struct l2_fhdr {
/* 5708 Serdes PHY registers */
+#define BCM5708S_BMCR_FORCE_2500 0x20
+
#define BCM5708S_UP1 0xb
#define BCM5708S_UP1_2G5 0x1
@@ -3804,6 +6351,7 @@ struct l2_fhdr {
#define INVALID_CID_ADDR 0xffffffff
#define TX_CID 16
+#define TX_TSS_CID 32
#define RX_CID 0
#define MB_TX_CID_ADDR MB_GET_CID_ADDR(TX_CID)
@@ -3889,6 +6437,8 @@ struct bnx2 {
u32 tx_prod_bseq __attribute__((aligned(L1_CACHE_BYTES)));
u16 tx_prod;
+ u32 tx_bidx_addr;
+ u32 tx_bseq_addr;
u16 tx_cons __attribute__((aligned(L1_CACHE_BYTES)));
u16 hw_tx_cons;
@@ -3945,6 +6495,7 @@ struct bnx2 {
#define CHIP_NUM(bp) (((bp)->chip_id) & 0xffff0000)
#define CHIP_NUM_5706 0x57060000
#define CHIP_NUM_5708 0x57080000
+#define CHIP_NUM_5709 0x57090000
#define CHIP_REV(bp) (((bp)->chip_id) & 0x0000f000)
#define CHIP_REV_Ax 0x00000000
@@ -4007,6 +6558,10 @@ struct bnx2 {
struct statistics_block *stats_blk;
dma_addr_t stats_blk_mapping;
+ int ctx_pages;
+ void *ctx_blk[4];
+ dma_addr_t ctx_blk_mapping[4];
+
u32 hc_cmd;
u32 rx_mode;
@@ -4038,6 +6593,7 @@ struct bnx2 {
u8 serdes_an_pending;
#define SERDES_AN_TIMEOUT (HZ / 3)
+#define SERDES_FORCED_TIMEOUT (HZ / 10)
u8 mac_addr[8];
@@ -4104,41 +6660,43 @@ struct cpu_reg {
};
struct fw_info {
- u32 ver_major;
- u32 ver_minor;
- u32 ver_fix;
+ const u32 ver_major;
+ const u32 ver_minor;
+ const u32 ver_fix;
- u32 start_addr;
+ const u32 start_addr;
/* Text section. */
- u32 text_addr;
- u32 text_len;
- u32 text_index;
+ const u32 text_addr;
+ const u32 text_len;
+ const u32 text_index;
u32 *text;
+ u8 *gz_text;
+ const u32 gz_text_len;
/* Data section. */
- u32 data_addr;
- u32 data_len;
- u32 data_index;
- u32 *data;
+ const u32 data_addr;
+ const u32 data_len;
+ const u32 data_index;
+ const u32 *data;
/* SBSS section. */
- u32 sbss_addr;
- u32 sbss_len;
- u32 sbss_index;
- u32 *sbss;
+ const u32 sbss_addr;
+ const u32 sbss_len;
+ const u32 sbss_index;
+ const u32 *sbss;
/* BSS section. */
- u32 bss_addr;
- u32 bss_len;
- u32 bss_index;
- u32 *bss;
+ const u32 bss_addr;
+ const u32 bss_len;
+ const u32 bss_index;
+ const u32 *bss;
/* Read-only section. */
- u32 rodata_addr;
- u32 rodata_len;
- u32 rodata_index;
- u32 *rodata;
+ const u32 rodata_addr;
+ const u32 rodata_len;
+ const u32 rodata_index;
+ const u32 *rodata;
};
#define RV2P_PROC1 0
diff --git a/drivers/net/bnx2_fw.h b/drivers/net/bnx2_fw.h
index 2d753dca0d75..21d368ff424d 100644
--- a/drivers/net/bnx2_fw.h
+++ b/drivers/net/bnx2_fw.h
@@ -14,20 +14,6 @@
* accompanying it.
*/
-static const int bnx2_COM_b06FwReleaseMajor = 0x1;
-static const int bnx2_COM_b06FwReleaseMinor = 0x0;
-static const int bnx2_COM_b06FwReleaseFix = 0x0;
-static const u32 bnx2_COM_b06FwStartAddr = 0x080008b4;
-static const u32 bnx2_COM_b06FwTextAddr = 0x08000000;
-static const int bnx2_COM_b06FwTextLen = 0x57bc;
-static const u32 bnx2_COM_b06FwDataAddr = 0x08005840;
-static const int bnx2_COM_b06FwDataLen = 0x0;
-static const u32 bnx2_COM_b06FwRodataAddr = 0x080057c0;
-static const int bnx2_COM_b06FwRodataLen = 0x58;
-static const u32 bnx2_COM_b06FwBssAddr = 0x08005860;
-static const int bnx2_COM_b06FwBssLen = 0x88;
-static const u32 bnx2_COM_b06FwSbssAddr = 0x08005840;
-static const int bnx2_COM_b06FwSbssLen = 0x1c;
static u8 bnx2_COM_b06FwText[] = {
0x1f, 0x8b, 0x08, 0x08, 0x09, 0x83, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xec, 0x5b, 0x7d, 0x6c,
@@ -673,389 +659,752 @@ static u32 bnx2_COM_b06FwRodata[(0x58/4) + 1] = {
static u32 bnx2_COM_b06FwBss[(0x88/4) + 1] = { 0x0 };
static u32 bnx2_COM_b06FwSbss[(0x1c/4) + 1] = { 0x0 };
-static int bnx2_RXP_b06FwReleaseMajor = 0x1;
-static int bnx2_RXP_b06FwReleaseMinor = 0x0;
-static int bnx2_RXP_b06FwReleaseFix = 0x0;
-static u32 bnx2_RXP_b06FwStartAddr = 0x08003184;
-static u32 bnx2_RXP_b06FwTextAddr = 0x08000000;
-static int bnx2_RXP_b06FwTextLen = 0x588c;
-static u32 bnx2_RXP_b06FwDataAddr = 0x080058e0;
-static int bnx2_RXP_b06FwDataLen = 0x0;
-static u32 bnx2_RXP_b06FwRodataAddr = 0x08005890;
-static int bnx2_RXP_b06FwRodataLen = 0x28;
-static u32 bnx2_RXP_b06FwBssAddr = 0x08005900;
-static int bnx2_RXP_b06FwBssLen = 0x13a4;
-static u32 bnx2_RXP_b06FwSbssAddr = 0x080058e0;
-static int bnx2_RXP_b06FwSbssLen = 0x1c;
+static struct fw_info bnx2_com_fw_06 = {
+ .ver_major = 0x1,
+ .ver_minor = 0x0,
+ .ver_fix = 0x0,
+
+ .start_addr = 0x080008b4,
+
+ .text_addr = 0x08000000,
+ .text_len = 0x57bc,
+ .text_index = 0x0,
+ .gz_text = bnx2_COM_b06FwText,
+ .gz_text_len = sizeof(bnx2_COM_b06FwText),
+
+ .data_addr = 0x08005840,
+ .data_len = 0x0,
+ .data_index = 0x0,
+ .data = bnx2_COM_b06FwData,
+
+ .sbss_addr = 0x08005840,
+ .sbss_len = 0x1c,
+ .sbss_index = 0x0,
+ .sbss = bnx2_COM_b06FwSbss,
+
+ .bss_addr = 0x08005860,
+ .bss_len = 0x88,
+ .bss_index = 0x0,
+ .bss = bnx2_COM_b06FwBss,
+
+ .rodata_addr = 0x080057c0,
+ .rodata_len = 0x58,
+ .rodata_index = 0x0,
+ .rodata = bnx2_COM_b06FwRodata,
+};
+
static u8 bnx2_RXP_b06FwText[] = {
- 0x1f, 0x8b, 0x08, 0x08, 0x07, 0x87, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
- 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xed, 0x5c, 0x5d, 0x6c,
- 0x1c, 0xd7, 0x75, 0x3e, 0xf3, 0x43, 0x71, 0x49, 0x91, 0xd4, 0x70, 0xb9,
- 0x62, 0x57, 0x12, 0x65, 0xed, 0x8a, 0x43, 0x71, 0x6d, 0x31, 0xce, 0x50,
- 0x58, 0xdb, 0x82, 0xb1, 0x48, 0xc7, 0xb3, 0xa4, 0xc8, 0x24, 0x02, 0x42,
- 0x1b, 0x42, 0xab, 0xa4, 0xa9, 0xc1, 0x90, 0x72, 0x91, 0x22, 0x2c, 0xa0,
- 0x1a, 0x79, 0xf0, 0x43, 0x10, 0x2f, 0x56, 0x3f, 0xa6, 0xd1, 0x8d, 0x96,
- 0xb6, 0x1c, 0x53, 0x08, 0x82, 0x82, 0xe5, 0x52, 0x52, 0x0b, 0x2c, 0xb4,
- 0x96, 0xed, 0x36, 0x7e, 0xa8, 0x23, 0x9a, 0x92, 0x8d, 0xa6, 0x68, 0x81,
- 0x22, 0xad, 0xd1, 0xf4, 0x4d, 0x95, 0x9a, 0x4a, 0x75, 0x5f, 0xd4, 0xa2,
- 0x48, 0xda, 0x46, 0xcd, 0xf4, 0xfb, 0xee, 0xcc, 0x88, 0xd4, 0x9a, 0xb2,
- 0x2c, 0x3b, 0x0d, 0x62, 0x74, 0x0e, 0x30, 0xd8, 0xb9, 0x7f, 0xe7, 0xef,
- 0x9e, 0x73, 0xee, 0x39, 0x77, 0x28, 0x7d, 0xa5, 0x43, 0xda, 0x25, 0x84,
- 0x4e, 0x3c, 0x99, 0xc3, 0xcf, 0x3c, 0xfd, 0xe0, 0xc3, 0x0f, 0xee, 0xc1,
- 0xeb, 0xb0, 0xa1, 0x6d, 0xd0, 0xa3, 0xfe, 0x18, 0x62, 0x88, 0x21, 0x86,
- 0x18, 0x62, 0x88, 0x21, 0x86, 0x18, 0x62, 0x88, 0x21, 0x86, 0x18, 0x62,
- 0x88, 0x21, 0x86, 0x18, 0x62, 0x88, 0x21, 0x86, 0x18, 0x62, 0x88, 0x21,
- 0x86, 0x18, 0x62, 0x88, 0x21, 0x86, 0x18, 0x62, 0x88, 0x21, 0x86, 0x18,
- 0x62, 0x88, 0x21, 0x86, 0x18, 0x62, 0x88, 0x21, 0x86, 0x18, 0x62, 0x88,
- 0x21, 0x86, 0x18, 0x62, 0x88, 0x21, 0x86, 0xff, 0xef, 0x60, 0x88, 0x58,
- 0xfc, 0xed, 0x0c, 0x1f, 0x49, 0xe8, 0x85, 0xcb, 0x07, 0x3d, 0x5b, 0x12,
- 0x46, 0x61, 0x69, 0x66, 0xda, 0x16, 0x71, 0xeb, 0xbb, 0x33, 0x45, 0xf9,
- 0x1f, 0xbf, 0x94, 0x32, 0x85, 0xfd, 0xdb, 0x0b, 0x37, 0x9f, 0x7d, 0xf3,
- 0x91, 0xec, 0x8d, 0x05, 0x43, 0x12, 0x56, 0xe1, 0xe8, 0xb0, 0xb5, 0x4b,
- 0x12, 0x7d, 0x58, 0xf3, 0xdd, 0xc1, 0xcf, 0x59, 0xd2, 0x15, 0xe1, 0xba,
- 0xee, 0xbf, 0x39, 0x68, 0xc9, 0x2b, 0x8d, 0x94, 0x5c, 0x68, 0x6c, 0xdf,
- 0x24, 0x5d, 0xd9, 0x52, 0x09, 0xfd, 0x6e, 0x8a, 0xe3, 0x96, 0x94, 0xab,
- 0x2d, 0xe2, 0x2a, 0xba, 0x7d, 0x5a, 0x71, 0xfe, 0x3e, 0xcd, 0x9b, 0x7f,
- 0x9e, 0xff, 0x1e, 0x24, 0xa5, 0xcb, 0x7d, 0x68, 0xf7, 0xa1, 0xcd, 0xf7,
- 0x81, 0xf4, 0x94, 0x98, 0x72, 0xa4, 0x91, 0x90, 0xa3, 0xd5, 0x8c, 0xe8,
- 0x05, 0x71, 0xbd, 0xbc, 0x9d, 0x2e, 0xa3, 0x6f, 0xea, 0x00, 0xdb, 0x29,
- 0xe0, 0xf9, 0x0e, 0xd7, 0x59, 0x5e, 0x5e, 0x4a, 0xb7, 0xc6, 0x14, 0x0d,
- 0x8e, 0xb1, 0x0f, 0xbf, 0x58, 0x5f, 0xae, 0x76, 0x00, 0x6f, 0xd6, 0x71,
- 0x41, 0xdc, 0x73, 0x2c, 0xd0, 0xf6, 0xfd, 0xdf, 0x75, 0x32, 0xb2, 0xe2,
- 0x74, 0x81, 0xa7, 0x16, 0x69, 0xb5, 0xc5, 0xd2, 0x0b, 0xb6, 0xb5, 0x22,
- 0x6d, 0x1c, 0xeb, 0x34, 0x0a, 0xbe, 0x3f, 0x9d, 0x97, 0xae, 0xa0, 0x6f,
- 0xb7, 0xe2, 0x63, 0x72, 0x42, 0xc3, 0xbc, 0x57, 0x49, 0x0f, 0x3a, 0xe2,
- 0x3b, 0x7f, 0xf3, 0x52, 0xac, 0x6c, 0x97, 0xc9, 0x54, 0xf6, 0xa0, 0x1b,
- 0xd0, 0x74, 0x3d, 0x67, 0x2b, 0x70, 0x6a, 0xe0, 0x4f, 0xdb, 0x81, 0xf5,
- 0xee, 0x0a, 0x68, 0x1a, 0x85, 0xcd, 0x62, 0x6c, 0x66, 0x9f, 0xe8, 0x3b,
- 0x87, 0x93, 0xe1, 0x78, 0x97, 0x36, 0x32, 0x6f, 0x88, 0x6e, 0xff, 0x81,
- 0xe6, 0xd5, 0x7a, 0xe5, 0xd8, 0xbc, 0x8e, 0x77, 0x5d, 0xae, 0xe6, 0x4b,
- 0x9a, 0xdb, 0xa8, 0x68, 0xde, 0xd9, 0x59, 0xad, 0x78, 0xd6, 0x94, 0xa3,
- 0xb6, 0x7f, 0xe1, 0xb4, 0x73, 0x42, 0x1b, 0x39, 0x7b, 0x46, 0x1b, 0x3d,
- 0xfb, 0x86, 0x36, 0xde, 0xd8, 0xb2, 0x49, 0xda, 0xb3, 0xd0, 0x1e, 0x71,
- 0x90, 0xbf, 0x4f, 0x87, 0xba, 0xec, 0xa2, 0xde, 0x4a, 0xe4, 0x7d, 0x9f,
- 0xf3, 0x86, 0xe6, 0x55, 0x6d, 0x8b, 0xfb, 0xe6, 0xa6, 0x22, 0x1a, 0xed,
- 0x72, 0x74, 0xde, 0x94, 0x63, 0xd5, 0x94, 0x3c, 0x57, 0x2d, 0x29, 0x5a,
- 0x86, 0x5d, 0xd2, 0xbc, 0x06, 0xc7, 0x2b, 0xa0, 0x75, 0x42, 0xdb, 0x07,
- 0x9a, 0xde, 0x59, 0x29, 0x5d, 0x71, 0xe6, 0x40, 0xaf, 0x03, 0x78, 0xff,
- 0x58, 0x1b, 0x6d, 0xf4, 0x6a, 0xde, 0xc9, 0x9b, 0xe2, 0x39, 0x59, 0xeb,
- 0x4b, 0x62, 0xba, 0xb0, 0x01, 0xc8, 0x0c, 0xfd, 0x38, 0xd0, 0x49, 0xca,
- 0xf7, 0xf5, 0x82, 0xff, 0x2c, 0x74, 0x6f, 0x5d, 0xa1, 0xfc, 0x8d, 0x5e,
- 0x29, 0xcf, 0x53, 0xd7, 0xa6, 0x36, 0x52, 0xf5, 0x2f, 0x78, 0x8e, 0xf4,
- 0x19, 0xe2, 0xfb, 0x47, 0x9d, 0x81, 0xf4, 0x21, 0x39, 0x03, 0xdc, 0x75,
- 0xad, 0xd8, 0xa0, 0xae, 0xc1, 0xdf, 0x2d, 0x39, 0x02, 0xbd, 0x15, 0x9d,
- 0x5e, 0x99, 0xb4, 0xb2, 0x2e, 0xf6, 0x68, 0x53, 0x20, 0x57, 0x32, 0xb4,
- 0x17, 0xd2, 0xe7, 0xde, 0x67, 0xd3, 0x9e, 0xa1, 0xcb, 0x53, 0x2f, 0x3d,
- 0xdf, 0xb3, 0x38, 0xb4, 0x91, 0x32, 0x43, 0xff, 0xf2, 0x45, 0xcf, 0xf6,
- 0xb6, 0xb4, 0x48, 0x29, 0x6d, 0x48, 0x16, 0xfb, 0xb4, 0x43, 0x4e, 0x3b,
- 0x22, 0x87, 0x2a, 0xd0, 0x8d, 0x6d, 0x5a, 0x8b, 0x62, 0x67, 0xca, 0x32,
- 0x50, 0x32, 0x75, 0x74, 0x26, 0x49, 0x97, 0x3a, 0xd2, 0xe5, 0x7a, 0x9e,
- 0x7a, 0xa2, 0x3d, 0x7f, 0x28, 0x5d, 0x69, 0xab, 0xba, 0x5a, 0xd5, 0xd3,
- 0xf8, 0x2f, 0x5d, 0x4f, 0xd4, 0xc9, 0x72, 0x28, 0xb7, 0x03, 0xdc, 0x8f,
- 0x40, 0x5f, 0xe2, 0xea, 0xc3, 0x0f, 0xb1, 0x6f, 0x93, 0x51, 0xb0, 0xd3,
- 0x17, 0x61, 0x14, 0x7a, 0x61, 0x37, 0x64, 0x19, 0xa6, 0xee, 0xe0, 0xc3,
- 0x1f, 0x49, 0x5e, 0xf9, 0xd5, 0x90, 0x97, 0xfc, 0xdb, 0x32, 0x55, 0x49,
- 0x80, 0x06, 0x65, 0xd4, 0xe5, 0xbd, 0x7c, 0x64, 0x1b, 0x7b, 0x20, 0x5f,
- 0x5e, 0xa6, 0xbe, 0x45, 0x7f, 0xa2, 0xfd, 0xf3, 0x9d, 0xb2, 0xfe, 0xcc,
- 0xbf, 0xee, 0x7c, 0x92, 0xf6, 0x96, 0x7c, 0x27, 0xe4, 0x78, 0x35, 0xc9,
- 0x3d, 0xd4, 0x56, 0x54, 0x6c, 0x8a, 0x64, 0x14, 0xdd, 0x28, 0x74, 0x48,
- 0x51, 0xed, 0xf7, 0x5e, 0xd0, 0x43, 0x2c, 0xa8, 0xf2, 0xbd, 0xa0, 0x64,
- 0x9b, 0xb6, 0xed, 0xcc, 0x11, 0xc9, 0xc2, 0xbe, 0x45, 0x8e, 0xcc, 0x99,
- 0x32, 0x6d, 0xff, 0x63, 0xa7, 0xb4, 0x2f, 0xdf, 0x6f, 0xa8, 0xb8, 0xae,
- 0xf7, 0x6e, 0x90, 0x4d, 0xe0, 0x77, 0xf9, 0x7e, 0x5d, 0xe4, 0xa6, 0x59,
- 0xc8, 0x5a, 0x23, 0x08, 0xf6, 0x46, 0x81, 0xb1, 0x4c, 0x43, 0x2c, 0x93,
- 0x44, 0x8b, 0x4d, 0x7d, 0xf9, 0xfe, 0xf8, 0xf0, 0xdd, 0xf5, 0x75, 0x64,
- 0x9e, 0xb4, 0xa9, 0x2f, 0xc6, 0xa8, 0x12, 0xf4, 0xc1, 0xf8, 0x74, 0xbb,
- 0xae, 0x8a, 0xa1, 0xae, 0x46, 0xfe, 0xef, 0xed, 0xc2, 0xf5, 0xaa, 0xa2,
- 0x79, 0xce, 0xbb, 0xa1, 0x2f, 0xd8, 0x32, 0x02, 0x7f, 0x37, 0xec, 0x4f,
- 0xcb, 0x91, 0x54, 0x76, 0xc2, 0x95, 0xc0, 0xe6, 0xaf, 0xad, 0xb1, 0xf9,
- 0xd1, 0xbb, 0xc8, 0x75, 0x3c, 0x94, 0xcb, 0x0d, 0xe5, 0x1a, 0x85, 0x5c,
- 0x63, 0x90, 0x6b, 0xe5, 0x23, 0xc8, 0xb5, 0xf2, 0x91, 0xe5, 0xd2, 0xa4,
- 0xec, 0x3c, 0x08, 0x5a, 0xa6, 0xfc, 0xab, 0x13, 0xd8, 0xf2, 0xbf, 0x38,
- 0x9f, 0x14, 0x19, 0x7c, 0x7f, 0x70, 0xd8, 0x16, 0xef, 0x5b, 0xe0, 0xd5,
- 0x71, 0x40, 0x8b, 0xef, 0xef, 0x97, 0xe1, 0x6e, 0xfe, 0x38, 0x8b, 0x7d,
- 0x5d, 0xcf, 0x1f, 0x29, 0x87, 0x3e, 0x7c, 0xef, 0xfe, 0xa8, 0x6b, 0x1f,
- 0x55, 0x0e, 0xc6, 0x9c, 0x4f, 0x35, 0x9d, 0xab, 0x1f, 0x56, 0x86, 0xf5,
- 0x63, 0xca, 0x2f, 0x4f, 0x86, 0xc7, 0x64, 0x72, 0x33, 0xed, 0xa9, 0xa4,
- 0x8d, 0x0c, 0x92, 0xef, 0xb5, 0xfc, 0x4a, 0x26, 0xe0, 0x0d, 0x39, 0xd1,
- 0xd2, 0x46, 0x39, 0xb2, 0x60, 0x49, 0x69, 0xe9, 0x4e, 0x71, 0x57, 0x03,
- 0x6f, 0xb4, 0x47, 0xf6, 0x7d, 0xd2, 0x7c, 0x2a, 0xc8, 0x2b, 0x2e, 0x54,
- 0x91, 0x83, 0x56, 0x13, 0x72, 0xd9, 0x48, 0xcb, 0x9b, 0x83, 0x87, 0xe5,
- 0xf3, 0xd5, 0x24, 0xe8, 0x31, 0x9f, 0x2c, 0xe7, 0x10, 0x17, 0xb5, 0xb2,
- 0x63, 0x08, 0x79, 0xaf, 0xd9, 0x9c, 0x13, 0xc4, 0x96, 0x72, 0x10, 0x83,
- 0x5d, 0x6f, 0x50, 0xe5, 0x14, 0x90, 0x4f, 0x64, 0x0c, 0xb1, 0xb7, 0x66,
- 0xb3, 0xcd, 0xfe, 0xa0, 0xef, 0xb3, 0x95, 0x5e, 0xad, 0xc8, 0xbc, 0x64,
- 0xf0, 0xa6, 0x4c, 0x3b, 0x41, 0xdf, 0xe7, 0x2a, 0xa3, 0x9b, 0x98, 0x1f,
- 0x1a, 0x05, 0xc9, 0x94, 0x9d, 0xf7, 0x7c, 0xd7, 0xba, 0x7d, 0xcd, 0xfa,
- 0x78, 0xb2, 0x13, 0x81, 0xce, 0x45, 0xfb, 0xaa, 0xad, 0xf7, 0xb6, 0x4a,
- 0x09, 0x27, 0x5d, 0xd6, 0x1a, 0x47, 0xe7, 0xbe, 0x4a, 0x79, 0x5b, 0xab,
- 0xdc, 0x34, 0x80, 0x3f, 0x6d, 0x68, 0x62, 0x1e, 0xaa, 0x94, 0xbb, 0xd9,
- 0xa6, 0xbe, 0x74, 0x4d, 0x12, 0xa3, 0x15, 0x5f, 0xae, 0x3a, 0x41, 0xee,
- 0x63, 0x68, 0x7a, 0x6f, 0x5b, 0xb8, 0x56, 0xd7, 0x76, 0x39, 0x97, 0x44,
- 0x3a, 0x0e, 0x55, 0xc4, 0x2a, 0x56, 0x76, 0x39, 0x6f, 0x4b, 0xb9, 0xa7,
- 0x6d, 0x75, 0x5d, 0x8a, 0xeb, 0x76, 0x0e, 0xaf, 0x9d, 0xbb, 0xcb, 0xb9,
- 0x28, 0xe5, 0x2d, 0x6d, 0xab, 0xb4, 0xd2, 0x58, 0xdb, 0x17, 0xac, 0xe5,
- 0xf8, 0x66, 0x71, 0xbb, 0x39, 0x47, 0xef, 0x6d, 0xbf, 0x45, 0x43, 0x32,
- 0xc5, 0x4a, 0xb9, 0xa7, 0x7d, 0x15, 0xaf, 0x4d, 0xbc, 0xde, 0x1a, 0xbc,
- 0xc4, 0xd9, 0xbe, 0x8a, 0x33, 0x07, 0x9c, 0x43, 0xab, 0x38, 0x39, 0x7e,
- 0x58, 0x8a, 0x38, 0xd3, 0x5a, 0x0a, 0x32, 0xbc, 0x54, 0xc9, 0x48, 0x79,
- 0x28, 0x01, 0xdd, 0xf7, 0x1f, 0xfc, 0x9a, 0xaa, 0x43, 0xcc, 0x61, 0x0f,
- 0xba, 0x32, 0x55, 0x5e, 0x87, 0xd8, 0x08, 0xdb, 0xf8, 0x5a, 0x5d, 0x86,
- 0x17, 0xeb, 0xa6, 0x1c, 0x6f, 0x70, 0xbf, 0x98, 0xe3, 0x05, 0x75, 0xc6,
- 0x85, 0x46, 0x4e, 0xdb, 0x87, 0xbd, 0x66, 0x9d, 0xb0, 0xaf, 0x61, 0x6a,
- 0xa3, 0x3c, 0x1f, 0x80, 0x97, 0x76, 0x7e, 0xac, 0x41, 0xdb, 0x79, 0x03,
- 0xb6, 0x41, 0xce, 0xa3, 0x9c, 0xbd, 0x95, 0xb9, 0x53, 0x66, 0xd1, 0x51,
- 0x75, 0x88, 0x56, 0xcb, 0x77, 0x20, 0x07, 0x4d, 0xa0, 0xd6, 0x80, 0xcd,
- 0xdb, 0x78, 0x6f, 0x70, 0xde, 0x32, 0xe6, 0x6d, 0xe0, 0x3c, 0xec, 0xcd,
- 0x25, 0xe5, 0x0f, 0xa6, 0xcd, 0xf1, 0x77, 0xb1, 0xc7, 0x68, 0xd7, 0x59,
- 0x57, 0x58, 0x02, 0x5f, 0xc1, 0x3e, 0xa2, 0x6e, 0x48, 0xed, 0x60, 0x7e,
- 0x8f, 0xb9, 0x19, 0xcc, 0xcd, 0x66, 0x18, 0xcf, 0x3d, 0xfb, 0x99, 0x0e,
- 0xe9, 0x42, 0xbb, 0xce, 0x35, 0xd9, 0x0c, 0x72, 0x5b, 0xdf, 0xcb, 0xb7,
- 0xc9, 0x4a, 0xca, 0xbf, 0x60, 0xd8, 0xd1, 0xdc, 0x08, 0x6f, 0xf3, 0x5c,
- 0xe6, 0xc5, 0xc4, 0xbd, 0x21, 0xcc, 0x83, 0xc7, 0xc5, 0x6d, 0xfc, 0x49,
- 0xb7, 0x74, 0xb9, 0xf8, 0x8d, 0xe6, 0x4c, 0x6f, 0x0e, 0x6a, 0x2e, 0xbe,
- 0xb7, 0x50, 0x3e, 0x17, 0xe7, 0xa1, 0x56, 0xac, 0x66, 0x26, 0x59, 0x1f,
- 0x15, 0xeb, 0x6c, 0xef, 0x85, 0x3f, 0x04, 0x75, 0xd7, 0x85, 0x5b, 0xbe,
- 0x70, 0x19, 0x7a, 0x4b, 0x43, 0x6f, 0x29, 0x39, 0xdf, 0x60, 0x9d, 0xe6,
- 0x42, 0x5f, 0x19, 0xf1, 0x1a, 0xe3, 0x58, 0x2b, 0x87, 0x81, 0x03, 0x3a,
- 0x17, 0x47, 0x2f, 0x64, 0x65, 0xca, 0xda, 0x1d, 0xf1, 0x00, 0x5c, 0x88,
- 0x1f, 0x85, 0x36, 0xf4, 0xf1, 0x1d, 0x9a, 0x53, 0xff, 0x86, 0x7f, 0x94,
- 0xed, 0x09, 0xbd, 0x30, 0xd6, 0xd4, 0xbf, 0x6e, 0xfc, 0xa1, 0x1c, 0x68,
- 0x33, 0x06, 0x31, 0xfe, 0xe8, 0xa8, 0xf3, 0x18, 0x8b, 0x48, 0xd7, 0x92,
- 0x23, 0x4b, 0x23, 0xdc, 0x37, 0x8b, 0xf1, 0xa7, 0x5c, 0xe7, 0x9e, 0x29,
- 0x5c, 0xc0, 0x19, 0xad, 0xf1, 0xfd, 0x11, 0x87, 0x6b, 0x7c, 0x99, 0x70,
- 0x3a, 0xc4, 0x48, 0x96, 0xb4, 0xc7, 0x07, 0x11, 0x7b, 0x1e, 0xe0, 0x3e,
- 0x32, 0x06, 0x6d, 0x17, 0xb0, 0xea, 0xb4, 0x3c, 0x3c, 0xc8, 0x75, 0xa0,
- 0xdd, 0x2a, 0x7a, 0x92, 0x34, 0xf3, 0x21, 0x4f, 0x43, 0xdd, 0x81, 0xbe,
- 0x06, 0xac, 0x40, 0x7f, 0x9f, 0xe9, 0x5e, 0xd5, 0x1f, 0xd7, 0x35, 0xf3,
- 0xcb, 0x18, 0x96, 0x90, 0x81, 0x33, 0x1b, 0x65, 0xe7, 0xa2, 0x25, 0xf6,
- 0x99, 0x55, 0xfe, 0x76, 0x9e, 0x5b, 0xcb, 0x5f, 0xf4, 0x7f, 0x15, 0x5c,
- 0xd0, 0xc5, 0x8e, 0xfa, 0x1e, 0x4b, 0x05, 0xb8, 0xa3, 0xf6, 0x7b, 0xe1,
- 0x5e, 0xf1, 0xfd, 0x99, 0x70, 0x4f, 0xb0, 0x07, 0x88, 0x95, 0xe7, 0x6f,
- 0xc5, 0xa9, 0x0c, 0xf6, 0x06, 0xb6, 0xa7, 0xe2, 0x11, 0xe3, 0x18, 0xed,
- 0xbb, 0x63, 0xd2, 0x2c, 0xb0, 0x8e, 0xe6, 0x3e, 0xc9, 0x44, 0xb9, 0x22,
- 0xa5, 0xad, 0x85, 0x67, 0x7d, 0xd8, 0xcf, 0xa4, 0xa5, 0x6c, 0xaf, 0x63,
- 0xaf, 0x97, 0x37, 0xa0, 0x1b, 0x8c, 0xc1, 0x26, 0xf5, 0x42, 0x42, 0x8a,
- 0x8d, 0x44, 0xc2, 0x3c, 0x31, 0xf0, 0x23, 0xcf, 0x48, 0x24, 0xf4, 0x13,
- 0x81, 0x9d, 0x4d, 0xd6, 0x6f, 0x20, 0x56, 0x6a, 0x72, 0x74, 0xe8, 0x86,
- 0xcf, 0x1a, 0xd8, 0xdb, 0x0b, 0x9b, 0x1b, 0x82, 0xcf, 0x80, 0x8f, 0x72,
- 0xa3, 0xa3, 0x37, 0xe0, 0xed, 0x2b, 0x11, 0x8f, 0xa6, 0x8e, 0xdc, 0xd3,
- 0xcb, 0xfb, 0xbe, 0x51, 0xd8, 0x90, 0x98, 0xce, 0x8f, 0x6f, 0xd1, 0xcf,
- 0xed, 0xdf, 0x62, 0x9c, 0x2b, 0x6d, 0x01, 0x3e, 0xdd, 0xcb, 0xe3, 0xf7,
- 0x9c, 0xc8, 0x44, 0x15, 0x3a, 0xdf, 0x03, 0x3d, 0x59, 0xf0, 0xc5, 0x3d,
- 0xa6, 0xca, 0xd1, 0xf5, 0x3d, 0x2f, 0x6e, 0x0a, 0x70, 0xf0, 0xfd, 0x27,
- 0x7e, 0x70, 0x86, 0x5e, 0x0e, 0xfb, 0x7e, 0x3f, 0xdc, 0x87, 0x5f, 0x45,
- 0xb9, 0x78, 0x5e, 0x44, 0xb2, 0xad, 0x3d, 0x37, 0xb2, 0xe3, 0x25, 0x9c,
- 0x33, 0xa7, 0x1d, 0xdf, 0x7f, 0x07, 0xcf, 0x35, 0xa7, 0xd9, 0x46, 0xde,
- 0x7f, 0xf6, 0x31, 0x07, 0xf8, 0x2c, 0xce, 0xbd, 0xd1, 0xa6, 0xb3, 0xff,
- 0x5e, 0xcf, 0xbd, 0x7b, 0x3f, 0xfb, 0xc9, 0xf3, 0x1d, 0x7d, 0xef, 0x03,
- 0xce, 0xfe, 0x0f, 0x5c, 0x77, 0x0f, 0x3e, 0x1b, 0xd8, 0x6d, 0xb1, 0xd1,
- 0x1c, 0x5f, 0xee, 0xd5, 0x7f, 0x7f, 0xad, 0xfb, 0x76, 0xff, 0xb5, 0xbb,
- 0x6f, 0xf7, 0xdf, 0xcd, 0xdd, 0xbf, 0x18, 0xff, 0xcd, 0x01, 0x0f, 0x7d,
- 0x70, 0xad, 0xff, 0xae, 0xe7, 0x93, 0xd4, 0xf7, 0xf3, 0x3d, 0xe5, 0xa1,
- 0xce, 0x30, 0x1f, 0x52, 0xe7, 0xf5, 0x17, 0xa7, 0x6d, 0xef, 0x7e, 0x53,
- 0x4a, 0xb9, 0x16, 0xc9, 0xe6, 0x6a, 0xb2, 0x43, 0x8e, 0x3b, 0x22, 0x4b,
- 0xaa, 0x16, 0x31, 0x51, 0x8b, 0x0f, 0xa0, 0x3e, 0x0b, 0xf4, 0xba, 0xa4,
- 0xf4, 0xf2, 0x02, 0x78, 0x89, 0xf0, 0x74, 0xdd, 0x05, 0x0f, 0x71, 0x10,
- 0x17, 0xf1, 0x0c, 0xe2, 0x7c, 0xb7, 0xd7, 0xc1, 0x85, 0x73, 0xea, 0x25,
- 0xd4, 0x64, 0xb6, 0xde, 0xa3, 0x07, 0x67, 0xb2, 0x5b, 0x96, 0xdd, 0xe9,
- 0xeb, 0xf2, 0x05, 0x9e, 0x59, 0x0a, 0xae, 0xce, 0x21, 0x56, 0x0f, 0x8d,
- 0x85, 0x75, 0xd2, 0xdc, 0x41, 0xcf, 0x8e, 0xee, 0x49, 0x78, 0x47, 0x92,
- 0x90, 0x92, 0x9a, 0xb5, 0x04, 0x1d, 0x68, 0x72, 0x0d, 0x67, 0xd0, 0xd5,
- 0xb9, 0x76, 0xe0, 0x45, 0xee, 0x77, 0x20, 0xbb, 0x57, 0xb4, 0x7e, 0xab,
- 0x55, 0x6b, 0x87, 0x2f, 0x65, 0xc4, 0x55, 0x6d, 0x9e, 0xd3, 0xa7, 0x66,
- 0x16, 0x2b, 0xc8, 0x03, 0x6d, 0x9c, 0xaf, 0x79, 0xbc, 0xd7, 0x49, 0x43,
- 0x93, 0x2b, 0x73, 0xba, 0xfc, 0xd3, 0x9c, 0x21, 0xff, 0x8c, 0x3a, 0xf4,
- 0x9a, 0x7d, 0x6a, 0xe6, 0xb4, 0x2d, 0xf7, 0x81, 0xd5, 0xf0, 0x0e, 0x4f,
- 0x76, 0x9a, 0x42, 0x5b, 0x1d, 0x48, 0xff, 0x8e, 0x20, 0xff, 0xc1, 0x9a,
- 0x2b, 0x73, 0xa4, 0xb5, 0x76, 0x8d, 0xf4, 0x22, 0x1f, 0x83, 0x5d, 0x0f,
- 0x30, 0x27, 0xe2, 0x7c, 0xd4, 0xab, 0x03, 0xd6, 0x3e, 0xc5, 0x5b, 0x42,
- 0x16, 0xeb, 0x9c, 0x6f, 0x82, 0xb7, 0x2e, 0x9c, 0x31, 0x59, 0x6b, 0x52,
- 0xfe, 0xb0, 0x5b, 0xe5, 0xaa, 0x1a, 0xfb, 0x0d, 0xb5, 0xc7, 0xef, 0xef,
- 0xe7, 0xde, 0x1b, 0x32, 0x95, 0x62, 0x9b, 0x63, 0x59, 0xd4, 0x9c, 0xc4,
- 0x97, 0xdd, 0xeb, 0x0a, 0x79, 0x0e, 0xde, 0xaf, 0x08, 0x65, 0xdb, 0x6d,
- 0x5d, 0x97, 0xd7, 0x7d, 0xf7, 0x00, 0xe5, 0x89, 0x72, 0x8b, 0x39, 0x9f,
- 0xb1, 0xd8, 0x28, 0xcc, 0xc0, 0x8e, 0xbf, 0x2a, 0xdf, 0x6f, 0x1c, 0x92,
- 0xef, 0x35, 0x26, 0xe5, 0xcf, 0x1a, 0x5f, 0x96, 0x3f, 0x6d, 0x1c, 0x94,
- 0xd7, 0x1b, 0x07, 0xe4, 0xb5, 0xc6, 0x84, 0xbc, 0xda, 0xd8, 0x0f, 0x1b,
- 0x1f, 0x87, 0x8d, 0x9f, 0x9a, 0x99, 0xac, 0xf7, 0xcb, 0xd4, 0x49, 0xc4,
- 0x20, 0xe7, 0x1b, 0xba, 0xba, 0xe3, 0xb3, 0xe9, 0xe7, 0x2d, 0x32, 0xad,
- 0xee, 0xaf, 0x34, 0xe4, 0x89, 0x2d, 0xbc, 0x2b, 0x7c, 0xc5, 0x33, 0x2e,
- 0x87, 0xf1, 0xe8, 0xe1, 0x94, 0xb4, 0x03, 0xbf, 0xca, 0x4b, 0x4d, 0x9e,
- 0xdb, 0x62, 0x86, 0xf7, 0x9c, 0x87, 0x24, 0xc9, 0xfb, 0xb0, 0x9c, 0x67,
- 0xa0, 0xde, 0x5e, 0xd7, 0x27, 0x73, 0xb4, 0x65, 0xe8, 0xc6, 0x95, 0x43,
- 0xb0, 0x53, 0xc3, 0x7e, 0xcb, 0xa5, 0x1e, 0x16, 0x97, 0x28, 0xf7, 0x46,
- 0x59, 0x5c, 0xa0, 0x6f, 0xff, 0x1b, 0x64, 0x6c, 0x97, 0xda, 0x82, 0x89,
- 0xb9, 0x6e, 0x98, 0xab, 0x6c, 0xa7, 0x3d, 0x00, 0x1f, 0xf1, 0x7e, 0x10,
- 0x4e, 0xab, 0x09, 0x27, 0xf1, 0x24, 0x54, 0x0c, 0x08, 0x70, 0x5b, 0x52,
- 0x5b, 0x4a, 0xca, 0xc2, 0x42, 0x0f, 0x9e, 0x94, 0x2c, 0xd4, 0x6d, 0x3c,
- 0x39, 0x3c, 0x43, 0x78, 0xd2, 0xb0, 0x53, 0xca, 0xc8, 0xd8, 0x12, 0xc9,
- 0x88, 0x78, 0x5c, 0xed, 0x0d, 0x6b, 0x2a, 0xf2, 0xa3, 0x85, 0xfc, 0x74,
- 0x87, 0x7d, 0x1d, 0x52, 0xab, 0x38, 0x32, 0x55, 0xfd, 0x94, 0x3e, 0xa5,
- 0x74, 0x07, 0xfc, 0x95, 0x21, 0xb4, 0xef, 0x0f, 0xdb, 0x8f, 0xca, 0xf4,
- 0xbc, 0xc8, 0xca, 0xcb, 0x03, 0x7a, 0x51, 0xb5, 0xf7, 0xa2, 0xad, 0xa3,
- 0x9d, 0x0d, 0xdb, 0xcc, 0x8f, 0x0e, 0xe0, 0x71, 0xd5, 0xf3, 0xf5, 0xea,
- 0xb8, 0x3c, 0x55, 0xed, 0x77, 0x5e, 0x87, 0xcd, 0xbd, 0x65, 0x46, 0xf7,
- 0xd2, 0x04, 0x24, 0x79, 0xf6, 0x56, 0x75, 0xf7, 0xf1, 0x04, 0xe2, 0xad,
- 0x9b, 0x34, 0xe5, 0x6f, 0x4f, 0x64, 0xad, 0xa7, 0xf5, 0x5c, 0x52, 0xda,
- 0x7d, 0xff, 0x71, 0x3b, 0x3b, 0x3b, 0xa9, 0x77, 0xca, 0xdf, 0xbf, 0x98,
- 0x91, 0x85, 0xb3, 0x5b, 0x65, 0xa1, 0x06, 0x99, 0x1a, 0xbf, 0x8e, 0x7d,
- 0x35, 0xe5, 0xea, 0x9e, 0x47, 0xb1, 0x27, 0x8c, 0x5d, 0x49, 0xe4, 0x6c,
- 0x1b, 0xc4, 0xec, 0x25, 0x5d, 0x49, 0x98, 0x85, 0x9c, 0x1c, 0x81, 0xdf,
- 0x4f, 0xdb, 0xb9, 0x1e, 0x69, 0xc7, 0x7b, 0x7d, 0x04, 0x7c, 0x5b, 0x32,
- 0xd5, 0x6b, 0xc9, 0x99, 0xc1, 0x68, 0xff, 0xb6, 0x62, 0x6e, 0x46, 0x16,
- 0xcf, 0x66, 0xf0, 0x9b, 0x83, 0xfd, 0xec, 0x94, 0x57, 0x6a, 0xfd, 0xb2,
- 0x54, 0xdb, 0x2a, 0x8b, 0xb5, 0xe6, 0x7d, 0xe8, 0xec, 0x09, 0xe2, 0x1d,
- 0xf1, 0xf4, 0x5b, 0x53, 0xfa, 0x56, 0x71, 0xcd, 0x7e, 0xeb, 0x29, 0xfd,
- 0x1f, 0xe4, 0x31, 0x33, 0xa0, 0xa9, 0x17, 0x7e, 0xa4, 0xee, 0x84, 0x26,
- 0x79, 0xf6, 0x2a, 0xbc, 0x4f, 0x26, 0x49, 0xfb, 0xf5, 0xc6, 0x07, 0xd1,
- 0x59, 0xcb, 0xcf, 0x9d, 0x68, 0x52, 0x06, 0xe2, 0xec, 0xbf, 0x71, 0x52,
- 0xef, 0x95, 0xe5, 0x6d, 0x0f, 0x58, 0x4f, 0xea, 0xad, 0x88, 0x01, 0x3f,
- 0x97, 0x9f, 0xee, 0xd9, 0x24, 0x3f, 0xfc, 0xcd, 0xec, 0xa9, 0x6f, 0x22,
- 0xd9, 0xbf, 0xb2, 0xa7, 0x83, 0x71, 0x01, 0xef, 0xec, 0xcf, 0xde, 0x70,
- 0x75, 0xea, 0xe1, 0x2f, 0xa0, 0x87, 0xec, 0x9c, 0xba, 0x9b, 0x56, 0x3c,
- 0x90, 0x3e, 0xf5, 0x52, 0x06, 0x6f, 0x18, 0xab, 0xf7, 0x03, 0x57, 0x59,
- 0xe9, 0xf9, 0x09, 0x27, 0x7b, 0x03, 0xe9, 0xb0, 0xbf, 0x68, 0xf7, 0xa7,
- 0x77, 0xea, 0x3b, 0x64, 0x32, 0xfd, 0x80, 0xf5, 0xb4, 0x6c, 0x21, 0xce,
- 0xd9, 0x05, 0xc1, 0xda, 0x79, 0xe2, 0xfb, 0x2b, 0xe0, 0x0b, 0x70, 0x28,
- 0xff, 0x51, 0x38, 0x77, 0x59, 0x5f, 0xd7, 0x79, 0xc6, 0x63, 0x0c, 0x71,
- 0xe1, 0xe2, 0x10, 0x65, 0x40, 0x82, 0x95, 0xca, 0xa6, 0x5d, 0xfd, 0xc3,
- 0xc8, 0x47, 0xfc, 0xfd, 0x56, 0x51, 0x27, 0x0f, 0xe7, 0xc0, 0xcb, 0x4f,
- 0xc0, 0x7f, 0x3f, 0x70, 0xa2, 0xf6, 0x48, 0x47, 0x74, 0xff, 0x4e, 0xd1,
- 0x7d, 0xad, 0x21, 0xe6, 0x2a, 0x5d, 0xf4, 0xd5, 0x75, 0xc8, 0xdd, 0x07,
- 0x7b, 0xb5, 0xf0, 0xcb, 0xbd, 0xe9, 0x0c, 0xf7, 0x98, 0xeb, 0x22, 0xba,
- 0x11, 0xbf, 0x5c, 0x73, 0x27, 0x1e, 0xee, 0x75, 0x3e, 0xea, 0xd4, 0x03,
- 0x09, 0x79, 0xf7, 0x44, 0xb4, 0x37, 0x07, 0x64, 0xba, 0x0a, 0xdd, 0xed,
- 0xea, 0x0f, 0xfc, 0x27, 0x1d, 0xf1, 0x40, 0xde, 0xff, 0x06, 0xbc, 0x07,
- 0xb8, 0x5b, 0x0b, 0xcd, 0xba, 0xc3, 0x58, 0x3d, 0xa0, 0x31, 0xb6, 0x0e,
- 0x4f, 0x57, 0xf6, 0x44, 0xbe, 0x98, 0x84, 0x5f, 0xed, 0xb6, 0x9e, 0x10,
- 0xd6, 0x63, 0xc4, 0x9b, 0x94, 0x1f, 0xbe, 0x0c, 0x1e, 0x92, 0xf4, 0x93,
- 0x7f, 0x5f, 0xe3, 0x27, 0x1c, 0xdb, 0x2a, 0x35, 0xd4, 0xd4, 0x5e, 0xde,
- 0x94, 0x69, 0x25, 0x03, 0xda, 0x35, 0xfa, 0x77, 0x29, 0xf4, 0xef, 0x47,
- 0x80, 0xa3, 0x5d, 0x8c, 0x47, 0x1f, 0xc7, 0x59, 0x9d, 0xcd, 0x2c, 0xeb,
- 0xcc, 0x03, 0x76, 0x4b, 0x51, 0xdd, 0x4f, 0xdf, 0x8b, 0xee, 0xa2, 0xd8,
- 0x94, 0x96, 0x8b, 0x95, 0x28, 0x2e, 0xa5, 0x71, 0x9e, 0xb4, 0xcb, 0xa5,
- 0xb9, 0x28, 0xe6, 0xb5, 0xcb, 0x12, 0xf2, 0x9a, 0x95, 0x97, 0x2c, 0x8c,
- 0x25, 0xe5, 0xe2, 0x5c, 0x12, 0x31, 0xab, 0x47, 0x56, 0xe6, 0x7a, 0x30,
- 0x96, 0xc2, 0xba, 0x14, 0xe6, 0xdb, 0xb2, 0x52, 0xb1, 0x81, 0x27, 0x87,
- 0x76, 0x0e, 0xed, 0x21, 0xb9, 0xa4, 0xbe, 0x17, 0x30, 0x2f, 0x18, 0x42,
- 0xdc, 0x62, 0x5e, 0x30, 0x82, 0x18, 0x32, 0x81, 0x27, 0x8a, 0x5d, 0xa7,
- 0x66, 0xa6, 0x2a, 0xbc, 0x73, 0x84, 0x0e, 0xac, 0x53, 0x33, 0xd3, 0xb6,
- 0x89, 0xba, 0xed, 0x1b, 0xda, 0x54, 0x83, 0x72, 0x41, 0xb7, 0x43, 0x1d,
- 0xa2, 0x3f, 0x4a, 0x9b, 0xe4, 0x79, 0x67, 0x20, 0xc6, 0x77, 0x01, 0x9f,
- 0x23, 0xfa, 0x6f, 0xd0, 0x17, 0xa0, 0xc3, 0x27, 0xba, 0xe4, 0xd2, 0xcb,
- 0x8c, 0x35, 0xae, 0xbc, 0x7a, 0x96, 0x3a, 0x2c, 0xf6, 0xac, 0xea, 0x90,
- 0x63, 0x0f, 0xe1, 0x8c, 0xd8, 0x0f, 0x7b, 0x32, 0x33, 0x87, 0x90, 0xcb,
- 0x7c, 0x1b, 0xf6, 0x59, 0x66, 0xcd, 0x9d, 0x0e, 0x6a, 0x84, 0x20, 0x06,
- 0xa0, 0xdd, 0x47, 0x5d, 0xb1, 0xdd, 0x07, 0xbb, 0xe3, 0x58, 0x9f, 0x1a,
- 0x5b, 0x04, 0x8e, 0x60, 0x8c, 0xed, 0xcd, 0xb2, 0xa8, 0xc6, 0x0e, 0xaa,
- 0xb1, 0xb2, 0xb2, 0x0f, 0x8e, 0x1d, 0x52, 0xb1, 0xe9, 0x7c, 0x23, 0xea,
- 0xdf, 0x88, 0x58, 0xc2, 0x7e, 0xf6, 0xe5, 0x61, 0xeb, 0x7b, 0x71, 0xae,
- 0x15, 0x64, 0xa9, 0x81, 0x3a, 0x30, 0xff, 0x7b, 0x98, 0xcb, 0x3d, 0xc8,
- 0x9e, 0x2a, 0xe9, 0xe4, 0xf1, 0x20, 0xce, 0x83, 0xfd, 0x21, 0xad, 0xb6,
- 0x90, 0xaf, 0x03, 0x61, 0xbb, 0x25, 0xa4, 0x4d, 0x3c, 0x36, 0x70, 0x1c,
- 0xc3, 0x5a, 0x17, 0x38, 0x18, 0x63, 0x11, 0x23, 0x52, 0x29, 0xe8, 0x82,
- 0x34, 0xdb, 0xa4, 0xac, 0xde, 0xf7, 0xc3, 0x76, 0xb9, 0x16, 0x3a, 0xb4,
- 0xa2, 0x75, 0xa5, 0x70, 0xcf, 0x53, 0xea, 0x9c, 0xd1, 0x93, 0x9b, 0xc3,
- 0x9c, 0x10, 0x7a, 0x45, 0x9c, 0xd5, 0x93, 0x8c, 0x37, 0xef, 0x84, 0x76,
- 0xda, 0x8b, 0xbe, 0x87, 0x44, 0xef, 0x65, 0xdf, 0x51, 0xe0, 0x61, 0xed,
- 0x3c, 0x0c, 0x99, 0xd9, 0xe6, 0xfa, 0x6c, 0xd3, 0xfa, 0xc4, 0x3a, 0xeb,
- 0x3b, 0x9a, 0xfa, 0x32, 0x52, 0x9b, 0xef, 0x52, 0xf1, 0xf2, 0x7c, 0x18,
- 0x2f, 0x17, 0x6b, 0x94, 0x05, 0x7e, 0x96, 0x7f, 0x5b, 0xe9, 0xa2, 0x76,
- 0x36, 0xb0, 0xf5, 0xa5, 0x93, 0x3c, 0x17, 0x57, 0xe7, 0xd5, 0xd4, 0xbc,
- 0xdf, 0x06, 0xff, 0xba, 0x1c, 0x55, 0x32, 0x70, 0x3e, 0xe6, 0xd5, 0x02,
- 0xbf, 0x31, 0x6c, 0xce, 0xa1, 0x8f, 0x44, 0x6b, 0x38, 0xff, 0xe7, 0xa8,
- 0x55, 0xbe, 0xac, 0xd6, 0xac, 0xfa, 0x0c, 0xf9, 0x71, 0x42, 0x9e, 0x7b,
- 0xc0, 0x5f, 0x67, 0x28, 0x43, 0x7b, 0x28, 0x03, 0xf1, 0xfd, 0x27, 0x70,
- 0xb7, 0x61, 0x1e, 0x79, 0xdd, 0x86, 0x3e, 0xbe, 0xff, 0x17, 0xfa, 0x76,
- 0x23, 0xff, 0x23, 0x6f, 0x89, 0x26, 0xde, 0xfe, 0x03, 0x63, 0x3d, 0x4a,
- 0xb7, 0x35, 0xd4, 0x26, 0x53, 0xbc, 0xef, 0x48, 0xe1, 0x1c, 0x38, 0xb9,
- 0x4d, 0xd1, 0xad, 0x9d, 0xbd, 0x86, 0xf1, 0x5e, 0xac, 0x89, 0xda, 0xcd,
- 0xb2, 0xe9, 0x58, 0xfb, 0x53, 0x25, 0xcf, 0x62, 0xed, 0x4e, 0xf2, 0x6f,
- 0x5b, 0x23, 0x3b, 0xe5, 0x26, 0x4f, 0xe4, 0xa7, 0x1f, 0x4f, 0x2b, 0x72,
- 0x21, 0xd8, 0x6d, 0xd2, 0x90, 0xd1, 0x7c, 0x9a, 0xdf, 0xf9, 0x12, 0xbc,
- 0x17, 0x1d, 0x19, 0xe4, 0x9e, 0xa1, 0xdd, 0x60, 0x4e, 0x47, 0x7f, 0x4b,
- 0xc8, 0x31, 0xd4, 0x24, 0xe5, 0x85, 0x8c, 0x56, 0x3c, 0x99, 0x45, 0x16,
- 0xad, 0xbe, 0xd5, 0xc9, 0x8b, 0x4b, 0xb6, 0x7c, 0x1b, 0x7e, 0x7a, 0xb2,
- 0x9e, 0x4d, 0x7f, 0x13, 0xf9, 0xc1, 0x91, 0x25, 0xe6, 0x13, 0x3d, 0x29,
- 0x65, 0x9b, 0xf3, 0x9a, 0x6c, 0x60, 0x4c, 0x9b, 0x47, 0x7e, 0x6a, 0xdd,
- 0x2d, 0x47, 0x82, 0x9f, 0x57, 0xd7, 0xc6, 0x0c, 0xca, 0xb1, 0x36, 0x66,
- 0x10, 0x0f, 0x63, 0xc6, 0x4e, 0xec, 0x13, 0x63, 0x06, 0xf6, 0xff, 0x24,
- 0x63, 0x86, 0x8d, 0x75, 0x8c, 0x19, 0x79, 0x59, 0xac, 0x32, 0x66, 0xec,
- 0x45, 0x9b, 0x31, 0xa3, 0x80, 0x76, 0x10, 0x2f, 0x16, 0x55, 0xbc, 0xc8,
- 0x5a, 0xcb, 0xc2, 0x38, 0x81, 0x3c, 0xb1, 0x8a, 0x3c, 0xb1, 0x8a, 0x3c,
- 0xb1, 0x8a, 0x3c, 0xb1, 0x8a, 0x3c, 0x11, 0xb6, 0xfe, 0x5a, 0x15, 0x79,
- 0x22, 0xfc, 0xe7, 0x3c, 0x72, 0x92, 0xa0, 0xa6, 0x38, 0x8c, 0x9a, 0xc2,
- 0xd5, 0xc6, 0xaa, 0xe3, 0xda, 0xbe, 0x2a, 0x6a, 0x43, 0xf5, 0x9d, 0x58,
- 0x1f, 0xda, 0x80, 0xba, 0xa8, 0xe6, 0x6c, 0x01, 0x5f, 0xd7, 0xe0, 0x1b,
- 0xd4, 0xd3, 0x56, 0x99, 0xca, 0xed, 0x80, 0x7c, 0xd8, 0x7f, 0xfb, 0xfb,
- 0xe8, 0x43, 0x3e, 0x9f, 0x63, 0x0d, 0xc2, 0x78, 0xb5, 0x0f, 0x6d, 0x1d,
- 0x6d, 0xec, 0xe9, 0x04, 0x7c, 0xc4, 0x7e, 0x90, 0xf9, 0x62, 0x7a, 0x41,
- 0x9e, 0xdc, 0x1c, 0xd8, 0xf4, 0x6f, 0x31, 0x27, 0x5e, 0xd3, 0xde, 0x88,
- 0x39, 0xf0, 0x17, 0xd8, 0x97, 0x5a, 0x03, 0x5c, 0xba, 0xfd, 0xe7, 0xc4,
- 0xd1, 0xb7, 0xe1, 0xd6, 0x1c, 0xda, 0xd5, 0xf7, 0x9a, 0xfa, 0xb2, 0x98,
- 0xcf, 0xef, 0xe2, 0x3b, 0xf0, 0xfb, 0x16, 0x7e, 0x61, 0x77, 0xf6, 0x05,
- 0xcc, 0xe9, 0xc3, 0xef, 0x77, 0x9a, 0xe6, 0x42, 0x0a, 0xfb, 0x2f, 0xd1,
- 0x77, 0x31, 0xa4, 0xc1, 0x6f, 0x89, 0x5f, 0x6a, 0xe2, 0xe3, 0x07, 0xe8,
- 0xfb, 0x6b, 0xf4, 0xf9, 0xfe, 0xdb, 0x4e, 0xd4, 0x27, 0xa5, 0x96, 0x70,
- 0xef, 0x46, 0xd5, 0xde, 0x69, 0xca, 0xe6, 0x8f, 0x2c, 0xe9, 0xaa, 0x0e,
- 0x7a, 0xae, 0x8e, 0xea, 0x08, 0x71, 0xbe, 0xbc, 0x10, 0xd4, 0xad, 0xc7,
- 0x51, 0x73, 0x16, 0xab, 0xb4, 0x91, 0x1c, 0xfa, 0x6d, 0x9c, 0x69, 0x32,
- 0x69, 0xdc, 0xaa, 0x63, 0x13, 0x89, 0xc9, 0x7a, 0x9b, 0x48, 0x37, 0x69,
- 0x32, 0x4f, 0x22, 0x8e, 0xd9, 0x99, 0xe2, 0xc2, 0xec, 0x8c, 0x07, 0x9c,
- 0x63, 0x75, 0xae, 0xe5, 0x3c, 0x93, 0xf7, 0x63, 0x4d, 0x74, 0x69, 0x13,
- 0x60, 0x06, 0xf4, 0x9e, 0xab, 0x93, 0x7e, 0x40, 0xb3, 0xac, 0x68, 0xda,
- 0xe8, 0x8f, 0xea, 0xc7, 0x1c, 0x6a, 0x5d, 0x99, 0x64, 0xed, 0x5c, 0x0c,
- 0x69, 0xba, 0x75, 0x49, 0x24, 0x0a, 0xcd, 0xf8, 0x82, 0x8c, 0xf3, 0xb9,
- 0xfa, 0xec, 0x8c, 0xfe, 0x42, 0x36, 0xc7, 0x3b, 0x11, 0xd7, 0x9a, 0x9d,
- 0x69, 0x1d, 0x48, 0xc8, 0x8f, 0x91, 0xbb, 0x1d, 0x53, 0x34, 0x66, 0x67,
- 0x8c, 0x17, 0x02, 0x5b, 0x0c, 0xe8, 0xe0, 0x3c, 0xc9, 0xb7, 0x43, 0x4e,
- 0xd2, 0x62, 0x4d, 0x1d, 0x8c, 0x4f, 0xaa, 0x7a, 0xd1, 0x94, 0x2b, 0x15,
- 0x45, 0x3b, 0xac, 0xdb, 0xc9, 0xc3, 0xec, 0x8c, 0xfc, 0xd1, 0x2d, 0x1e,
- 0xd6, 0x91, 0x87, 0x78, 0x49, 0x27, 0xd0, 0x5b, 0xc0, 0x7f, 0x12, 0xf5,
- 0x7b, 0x54, 0xab, 0xfb, 0xfe, 0x8a, 0x93, 0x43, 0x5c, 0xe0, 0x3e, 0xb6,
- 0xa8, 0x3c, 0xd7, 0x73, 0x32, 0xbc, 0xef, 0x9b, 0xe3, 0xdf, 0x39, 0x78,
- 0xf9, 0x01, 0xd4, 0x4d, 0xbc, 0x1b, 0xa4, 0x7f, 0xe1, 0xf7, 0x36, 0xff,
- 0xe2, 0x7c, 0xf6, 0x93, 0xe7, 0x81, 0xf4, 0x55, 0xf0, 0xe7, 0xe5, 0xd1,
- 0x87, 0x58, 0x51, 0x6c, 0x44, 0xb8, 0x78, 0xc7, 0xce, 0x39, 0x2a, 0xff,
- 0x6e, 0xf2, 0xd1, 0x96, 0xf0, 0xdc, 0xa5, 0x8e, 0xc8, 0x27, 0xf9, 0xe9,
- 0x84, 0x4d, 0x90, 0x17, 0xce, 0x8f, 0xee, 0x25, 0xd8, 0xfe, 0xb8, 0x36,
- 0x12, 0xdd, 0xa9, 0x7d, 0x9c, 0x3d, 0x8f, 0x74, 0x76, 0x37, 0x7e, 0x88,
- 0x83, 0xb4, 0x23, 0xbe, 0x22, 0x9e, 0x88, 0x8f, 0xfc, 0x44, 0xbc, 0x28,
- 0x1b, 0x5d, 0x97, 0x9f, 0x60, 0x5d, 0xc0, 0x4f, 0x69, 0x21, 0x0d, 0x9d,
- 0x90, 0xa7, 0x11, 0x6d, 0xa4, 0xba, 0xde, 0x1d, 0xc7, 0x0f, 0x5c, 0xc6,
- 0xd5, 0xb1, 0x06, 0xef, 0xa1, 0x48, 0x97, 0x7f, 0x3b, 0xb2, 0xa4, 0x8d,
- 0x34, 0xf8, 0x9d, 0xa9, 0xae, 0xb9, 0x8d, 0x88, 0xde, 0x5a, 0x9d, 0x46,
- 0xbf, 0xbc, 0x2b, 0xff, 0x0c, 0xf6, 0xa9, 0x3b, 0xf8, 0xbb, 0x14, 0x55,
- 0x47, 0xb1, 0x6f, 0xb9, 0xd5, 0x73, 0xa2, 0xbf, 0xd3, 0xd9, 0x1f, 0xe6,
- 0x43, 0x51, 0x6d, 0x1c, 0xd5, 0x59, 0xea, 0x9e, 0x7d, 0xaf, 0xe7, 0x68,
- 0xc8, 0x4f, 0x99, 0x33, 0x05, 0x3a, 0x08, 0xf1, 0xde, 0x91, 0xcf, 0x91,
- 0x26, 0x3e, 0x47, 0xc1, 0xe7, 0x3e, 0xf0, 0x39, 0x76, 0x8b, 0xcf, 0x5b,
- 0xb6, 0x97, 0x29, 0xc3, 0xf6, 0x46, 0xd6, 0xb5, 0xbd, 0x55, 0x3a, 0xab,
- 0x73, 0x83, 0xfb, 0x9a, 0x91, 0x86, 0x2f, 0xc7, 0x9d, 0x8f, 0x53, 0x37,
- 0xb7, 0xcb, 0x99, 0x85, 0xbb, 0xd5, 0xb7, 0x11, 0xaf, 0x2a, 0x77, 0x94,
- 0x4b, 0xf5, 0x80, 0x9f, 0x1f, 0x2f, 0xb1, 0x3d, 0x12, 0xea, 0x8a, 0x3a,
- 0xcb, 0x3a, 0x25, 0xb9, 0x1b, 0x2f, 0xbf, 0xf8, 0x9c, 0x76, 0xa5, 0x12,
- 0x9d, 0x4f, 0x5a, 0x78, 0xc6, 0xae, 0xe5, 0x29, 0xfa, 0x6e, 0x32, 0x66,
- 0x45, 0xf7, 0x67, 0x22, 0xfc, 0xfe, 0xc0, 0xef, 0x75, 0x6b, 0xbf, 0x13,
- 0xf0, 0x7c, 0x8a, 0x78, 0xd7, 0x53, 0x3c, 0x9f, 0xc6, 0x9c, 0x66, 0x19,
- 0x5c, 0xd8, 0xa4, 0x9e, 0xe4, 0x98, 0xe7, 0xd0, 0x2f, 0x4c, 0xd0, 0x0c,
- 0xee, 0xdd, 0x6a, 0x4b, 0xbe, 0x5c, 0x74, 0x36, 0x06, 0xe7, 0x28, 0x64,
- 0xba, 0x6c, 0xf1, 0xfe, 0x0a, 0x31, 0x8c, 0x67, 0x83, 0xb2, 0xb5, 0x16,
- 0xf5, 0x5c, 0x39, 0xd0, 0x0e, 0x1d, 0xb3, 0xdd, 0xd6, 0xcb, 0xfb, 0x0a,
- 0xca, 0xbc, 0xa0, 0xf6, 0x21, 0xd2, 0x71, 0xf4, 0x7d, 0xae, 0x55, 0x96,
- 0xc3, 0xbb, 0xad, 0xc5, 0x8a, 0xef, 0xbf, 0x83, 0x3c, 0xfc, 0x34, 0x74,
- 0x5f, 0xae, 0xff, 0xcc, 0x5f, 0x4e, 0xf1, 0x6f, 0xa5, 0x22, 0x9b, 0xd8,
- 0xd1, 0xcb, 0x7b, 0x20, 0xf8, 0x96, 0x1c, 0xaf, 0x87, 0x65, 0xbf, 0x70,
- 0x9c, 0x7d, 0xff, 0x0d, 0xbe, 0x7d, 0xff, 0xf4, 0xaa, 0x9d, 0x02, 0xfe,
- 0x17, 0x33, 0xe1, 0x9b, 0xdd, 0x90, 0x58, 0x00, 0x00, 0x00 };
+ 0x1f, 0x8b, 0x08, 0x08, 0xcb, 0xa3, 0x46, 0x45, 0x00, 0x03, 0x74, 0x65,
+ 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xec, 0x5c, 0x6f, 0x6c,
+ 0x1c, 0xc7, 0x75, 0x7f, 0x3b, 0xbb, 0xa4, 0x4e, 0xd4, 0x91, 0x5c, 0x1e,
+ 0x4f, 0xf4, 0x49, 0x66, 0x94, 0x5d, 0x71, 0x25, 0x5e, 0x2d, 0xc6, 0x5d,
+ 0x31, 0x57, 0x9b, 0x08, 0xce, 0xf1, 0x79, 0xef, 0x64, 0xb1, 0x86, 0x0a,
+ 0x51, 0x0d, 0x1d, 0x1b, 0x85, 0x6b, 0xb0, 0x47, 0x39, 0xae, 0xdb, 0x7e,
+ 0x90, 0x65, 0x1b, 0x30, 0xda, 0x10, 0xbe, 0x1c, 0xe9, 0x46, 0x75, 0x2f,
+ 0xdc, 0x8b, 0xc4, 0x98, 0x06, 0xfa, 0x07, 0x57, 0x92, 0xfa, 0x83, 0xe0,
+ 0xa0, 0x93, 0xe2, 0x26, 0xf5, 0x17, 0x57, 0x84, 0x2a, 0xc7, 0xf9, 0xe0,
+ 0x02, 0x4e, 0x63, 0x20, 0x06, 0xea, 0x16, 0xaa, 0xec, 0xd8, 0x46, 0x81,
+ 0xa2, 0x42, 0x1c, 0xd8, 0x46, 0xfc, 0x67, 0xfb, 0x7b, 0x33, 0xbb, 0xd4,
+ 0x91, 0x96, 0x6d, 0xa0, 0x1f, 0xfa, 0xa5, 0x3b, 0xc0, 0x61, 0x67, 0x66,
+ 0xe7, 0xbd, 0x79, 0xf3, 0xfe, 0xbf, 0x59, 0x4a, 0x7f, 0x90, 0xa4, 0x2e,
+ 0x0a, 0x5b, 0x37, 0x7e, 0xd6, 0x91, 0xc7, 0x8f, 0xde, 0x3c, 0x76, 0xf3,
+ 0x28, 0xd1, 0x97, 0x47, 0xf5, 0x1b, 0x12, 0x22, 0x9a, 0x8f, 0x5b, 0xdc,
+ 0xe2, 0x16, 0xb7, 0xb8, 0xc5, 0x2d, 0x6e, 0x71, 0x8b, 0x5b, 0xdc, 0xe2,
+ 0x16, 0xb7, 0xb8, 0xc5, 0x2d, 0x6e, 0x71, 0x8b, 0x5b, 0xdc, 0xe2, 0x16,
+ 0xb7, 0xb8, 0xc5, 0x2d, 0x6e, 0x71, 0x8b, 0x5b, 0xdc, 0xe2, 0x16, 0xb7,
+ 0xb8, 0xc5, 0x2d, 0x6e, 0x71, 0x8b, 0x5b, 0xdc, 0xe2, 0x16, 0xb7, 0xb8,
+ 0xc5, 0x2d, 0x6e, 0x71, 0x8b, 0x5b, 0xdc, 0xe2, 0x16, 0xb7, 0xb8, 0xc5,
+ 0x2d, 0x6e, 0x71, 0xfb, 0xff, 0xde, 0x74, 0x22, 0x93, 0x9f, 0xdd, 0xe1,
+ 0x8f, 0x12, 0x22, 0xbf, 0xfa, 0x90, 0xe7, 0x50, 0x42, 0xcf, 0xbf, 0x34,
+ 0x33, 0xed, 0x10, 0x15, 0x9a, 0x7b, 0xac, 0x22, 0x7d, 0x14, 0x54, 0xd2,
+ 0x06, 0xf1, 0xfc, 0x17, 0xf2, 0x1f, 0x3e, 0xf1, 0xfc, 0xad, 0xf6, 0xd5,
+ 0x86, 0x4e, 0x09, 0x33, 0x3f, 0xb7, 0xd7, 0xdc, 0x4d, 0x89, 0x41, 0xc0,
+ 0xfc, 0xf5, 0xf0, 0x7f, 0xf4, 0x50, 0x0f, 0x5d, 0xc3, 0xe3, 0x24, 0xe8,
+ 0xb2, 0xfe, 0x9c, 0xe6, 0xb5, 0x82, 0xe0, 0xa4, 0x1b, 0x04, 0x3f, 0xc6,
+ 0xef, 0x2d, 0x17, 0x63, 0xff, 0xe3, 0xa0, 0x60, 0xe8, 0x24, 0x9c, 0xbf,
+ 0xd4, 0xbc, 0xe5, 0x2e, 0xaa, 0x2e, 0x1a, 0x34, 0xeb, 0xa7, 0xe9, 0x98,
+ 0x5f, 0xd1, 0x4a, 0xad, 0x9a, 0xb6, 0xef, 0xf4, 0xbc, 0x76, 0xe7, 0xe9,
+ 0x63, 0xda, 0xfe, 0xd3, 0x75, 0xcd, 0x3b, 0x4d, 0x15, 0xb1, 0x37, 0x49,
+ 0x05, 0xf3, 0x8c, 0x56, 0x6c, 0x0d, 0x68, 0xde, 0x89, 0x0f, 0xc9, 0x73,
+ 0x6d, 0xf3, 0xf7, 0xc8, 0x28, 0x80, 0x16, 0xf2, 0x6a, 0x41, 0xe0, 0xb9,
+ 0x06, 0x15, 0xd2, 0x41, 0x20, 0xf2, 0xc1, 0x13, 0x5e, 0xce, 0x31, 0x85,
+ 0x96, 0xa6, 0x6a, 0x6b, 0x00, 0x78, 0x93, 0x5a, 0x71, 0xd1, 0xd0, 0x4a,
+ 0x7e, 0x70, 0xc1, 0x73, 0x69, 0x50, 0xa7, 0x20, 0x98, 0x73, 0x77, 0x65,
+ 0x0e, 0xd3, 0x29, 0xe0, 0x6d, 0x02, 0x1f, 0x99, 0x22, 0xcf, 0xf4, 0x31,
+ 0x9d, 0x4c, 0x72, 0x45, 0x2b, 0x0e, 0x47, 0xf4, 0x91, 0xc5, 0xf4, 0x97,
+ 0x57, 0x04, 0xe8, 0xdc, 0x42, 0xe5, 0x86, 0x49, 0x53, 0x2b, 0x1b, 0xd7,
+ 0x5f, 0x0e, 0x9e, 0x1f, 0x36, 0xe9, 0x5c, 0xcb, 0xae, 0x54, 0x28, 0x41,
+ 0x73, 0xbe, 0x45, 0x22, 0x4f, 0x05, 0x2f, 0x37, 0x48, 0x17, 0x5a, 0x19,
+ 0xfa, 0x41, 0xcb, 0xc9, 0x54, 0x69, 0x13, 0x95, 0xd3, 0x69, 0x3a, 0xdf,
+ 0x4a, 0xe3, 0x8c, 0xc1, 0x05, 0xe1, 0x38, 0x66, 0x15, 0x6b, 0xab, 0xad,
+ 0x97, 0xf8, 0xdf, 0xbf, 0x98, 0xd3, 0x39, 0x09, 0x53, 0x01, 0xdd, 0xe1,
+ 0x5a, 0x3e, 0x87, 0x5c, 0x2b, 0xcf, 0xa2, 0xd6, 0x52, 0x65, 0x3a, 0x87,
+ 0xb9, 0xd6, 0x1d, 0x6b, 0xfc, 0x2d, 0xa4, 0xf9, 0x69, 0x52, 0xd5, 0xef,
+ 0x00, 0x6f, 0xb8, 0x3f, 0x88, 0xb3, 0xee, 0xd0, 0xbc, 0xc5, 0x7f, 0x65,
+ 0xbc, 0x69, 0x41, 0x3b, 0x30, 0x1e, 0xc4, 0x98, 0xfb, 0xbb, 0x32, 0x65,
+ 0x02, 0x8f, 0x5b, 0x49, 0x8c, 0x99, 0xce, 0x20, 0xd8, 0xef, 0x92, 0x59,
+ 0x75, 0x7b, 0x01, 0x6b, 0x51, 0xd5, 0xed, 0x01, 0xbe, 0x0e, 0xea, 0x73,
+ 0xf8, 0x7c, 0xbc, 0xe7, 0x66, 0xcc, 0x07, 0xdd, 0x7a, 0x3e, 0x08, 0xa6,
+ 0x73, 0xd4, 0xa3, 0xe6, 0xf6, 0x48, 0x1c, 0x53, 0x13, 0x1a, 0xd6, 0xbd,
+ 0xc3, 0x7b, 0x24, 0x52, 0x79, 0xee, 0xf3, 0x33, 0x47, 0xde, 0xfc, 0x8e,
+ 0x90, 0xa6, 0x0c, 0x68, 0xba, 0x31, 0xec, 0x43, 0x0e, 0x3e, 0xf8, 0xe1,
+ 0xde, 0x80, 0xb1, 0xf6, 0x45, 0xe0, 0xc9, 0x56, 0x89, 0xf7, 0xe8, 0xa7,
+ 0xa5, 0x34, 0x89, 0x2b, 0x6e, 0x5f, 0xb8, 0xae, 0x07, 0xb4, 0x46, 0xfa,
+ 0x30, 0x40, 0x73, 0x8b, 0xcc, 0xf3, 0x1a, 0x64, 0x24, 0x68, 0xe7, 0x2d,
+ 0x15, 0xad, 0xd0, 0x3a, 0x86, 0xbe, 0x41, 0xd3, 0x4e, 0x70, 0x61, 0xce,
+ 0x9d, 0xd7, 0x8a, 0xa7, 0x4f, 0x69, 0xa5, 0xd3, 0xcf, 0x69, 0xfb, 0x5a,
+ 0x2f, 0x76, 0x53, 0x97, 0x8d, 0xd3, 0x27, 0xe8, 0x49, 0x5f, 0x23, 0xa6,
+ 0x73, 0x09, 0x3c, 0x2c, 0x98, 0x15, 0x32, 0x9c, 0x1e, 0xed, 0x4e, 0xe0,
+ 0xe9, 0x70, 0xfe, 0x2c, 0x49, 0x3d, 0x3a, 0x6d, 0x72, 0xa2, 0xb5, 0x69,
+ 0xfa, 0x73, 0xd0, 0x74, 0xd1, 0xdd, 0xca, 0x7c, 0xeb, 0x55, 0x30, 0xa9,
+ 0x90, 0x0e, 0xd6, 0x2f, 0x96, 0x9f, 0x6d, 0x7a, 0xba, 0xa0, 0xd2, 0xc2,
+ 0x5f, 0xf4, 0x57, 0x47, 0xb6, 0xf0, 0x3a, 0xd8, 0xc2, 0xd5, 0x87, 0xa6,
+ 0x1d, 0xaf, 0xcf, 0xa0, 0x8a, 0x29, 0xc8, 0x36, 0x8b, 0xf4, 0x45, 0x9a,
+ 0x73, 0x89, 0x8a, 0x35, 0xec, 0xeb, 0x18, 0xe0, 0x8f, 0x03, 0xfe, 0xec,
+ 0xaa, 0xe8, 0xe2, 0x1e, 0xa0, 0xa9, 0x68, 0x46, 0xc8, 0xcb, 0x25, 0xba,
+ 0x4b, 0xc2, 0x8b, 0xbc, 0x0b, 0x5d, 0xed, 0xe2, 0x3e, 0xf6, 0x4e, 0xc8,
+ 0xbd, 0xf5, 0xbc, 0x93, 0x59, 0x26, 0xd2, 0x44, 0x7e, 0x0f, 0xf0, 0xb1,
+ 0x0e, 0xf3, 0xba, 0x79, 0xd0, 0xc9, 0xf4, 0x73, 0xdf, 0x01, 0x4c, 0x02,
+ 0xfa, 0xde, 0xdd, 0x46, 0x2b, 0xe8, 0x49, 0x33, 0xbf, 0x99, 0x7f, 0xf2,
+ 0xac, 0xda, 0xb5, 0xb3, 0x7e, 0x10, 0x0c, 0x8f, 0x1a, 0xf4, 0x63, 0x79,
+ 0x66, 0xb6, 0x37, 0x5e, 0x97, 0x0e, 0xf5, 0x23, 0x01, 0x9d, 0x22, 0xad,
+ 0xec, 0x9a, 0x6b, 0xb8, 0xca, 0x44, 0x42, 0xcf, 0x27, 0xa9, 0x28, 0xe9,
+ 0x1b, 0xc3, 0x5e, 0x6c, 0x87, 0xb0, 0x27, 0x87, 0xcf, 0xc2, 0x73, 0x79,
+ 0xd8, 0xbb, 0xcd, 0x7d, 0x2a, 0xd7, 0xd9, 0xf6, 0x99, 0xb6, 0x55, 0x5b,
+ 0xfe, 0xd3, 0x2c, 0x89, 0x4f, 0x0c, 0xe8, 0xd4, 0x4b, 0x13, 0xee, 0x87,
+ 0x81, 0xd8, 0x8d, 0xf7, 0x23, 0x19, 0xd0, 0x66, 0x5b, 0xb0, 0xca, 0x94,
+ 0x4e, 0x1a, 0xe8, 0xde, 0x93, 0x31, 0xc9, 0xc1, 0xd9, 0xc0, 0xdf, 0x89,
+ 0x55, 0x30, 0xff, 0xd3, 0xe8, 0x54, 0x78, 0x41, 0x66, 0xc1, 0x03, 0x8d,
+ 0x9e, 0xfb, 0x65, 0xc9, 0x33, 0x13, 0xe7, 0xd7, 0xe7, 0x99, 0xbf, 0x5d,
+ 0xb0, 0x0b, 0x8d, 0xca, 0x2e, 0xe3, 0x8e, 0x70, 0x08, 0x1a, 0xbe, 0xa5,
+ 0x1d, 0x47, 0x24, 0x5f, 0xd6, 0x5d, 0x83, 0x46, 0x47, 0x79, 0x2d, 0xaf,
+ 0xe3, 0xf5, 0xf6, 0x98, 0x25, 0x3e, 0x08, 0xf6, 0xae, 0xdb, 0xd3, 0x21,
+ 0x31, 0x0f, 0x9a, 0x95, 0x2c, 0xc0, 0xc3, 0xcf, 0x5b, 0xcb, 0x72, 0xd8,
+ 0xc8, 0x6f, 0x5e, 0xdb, 0xbe, 0x0e, 0xfa, 0x3c, 0xc0, 0x34, 0x9c, 0x4c,
+ 0x2a, 0x3b, 0x8d, 0x68, 0x8a, 0x64, 0xa9, 0x85, 0x38, 0x3e, 0xeb, 0x1c,
+ 0xbc, 0x1e, 0xfe, 0xc3, 0x87, 0xff, 0x80, 0x4f, 0x3c, 0xef, 0xc3, 0xbf,
+ 0xf8, 0xec, 0x6f, 0x2c, 0x7a, 0x7e, 0x18, 0xfe, 0xf1, 0x9a, 0x7f, 0x42,
+ 0x1b, 0x47, 0x5f, 0x90, 0x0e, 0xff, 0x34, 0xdb, 0x10, 0xb0, 0x73, 0xf8,
+ 0x8a, 0x15, 0x9e, 0x83, 0x5f, 0x58, 0x29, 0xe1, 0xe9, 0x50, 0xb5, 0xc9,
+ 0x7a, 0x18, 0xf9, 0x61, 0xf6, 0x57, 0x19, 0xf8, 0x26, 0xf6, 0x47, 0xec,
+ 0xb7, 0x78, 0x6d, 0x10, 0x94, 0x5c, 0x86, 0x0d, 0x20, 0x47, 0xb6, 0xbb,
+ 0x24, 0x89, 0x54, 0x45, 0x3b, 0x34, 0x0c, 0x7b, 0xbc, 0x89, 0x7d, 0x0b,
+ 0xdb, 0xe5, 0x8d, 0x44, 0x9d, 0xbc, 0xdf, 0xaf, 0xbb, 0xd5, 0xbf, 0xd9,
+ 0xdb, 0x84, 0x35, 0xf2, 0xd9, 0xa3, 0xc6, 0x66, 0xe8, 0x97, 0xf8, 0xbd,
+ 0x6d, 0x15, 0x68, 0x57, 0x38, 0xe6, 0xfe, 0x1a, 0xbd, 0xae, 0xb8, 0x25,
+ 0x41, 0x3b, 0x4f, 0x29, 0x7f, 0xba, 0x73, 0x09, 0x9a, 0x71, 0x4a, 0xd1,
+ 0xb8, 0xf3, 0x6c, 0xe4, 0x57, 0x93, 0xc0, 0x07, 0xfa, 0xfc, 0xb5, 0x18,
+ 0x82, 0xf6, 0x9e, 0x06, 0xd3, 0xc2, 0xdc, 0x46, 0x5e, 0xb0, 0x2f, 0x67,
+ 0xfb, 0x34, 0xdb, 0xed, 0x73, 0x2f, 0xec, 0xd3, 0xed, 0x24, 0xdb, 0xfd,
+ 0x27, 0xd8, 0xe7, 0xb7, 0x5d, 0x0d, 0xbc, 0x21, 0xba, 0x54, 0xcb, 0xc0,
+ 0x3f, 0x18, 0x99, 0xd7, 0x69, 0x97, 0x35, 0x0b, 0xbd, 0x3c, 0xc9, 0x73,
+ 0x4d, 0xcc, 0x49, 0x3f, 0xae, 0xfc, 0xc7, 0x65, 0xfd, 0xbb, 0xa0, 0x2b,
+ 0x08, 0x66, 0x81, 0xb3, 0x3c, 0xa2, 0x87, 0xb6, 0x18, 0xcd, 0x5f, 0x45,
+ 0x3c, 0xf4, 0x7e, 0x43, 0xa7, 0x4a, 0xb6, 0x83, 0xec, 0xec, 0x12, 0x70,
+ 0x4f, 0xbb, 0xca, 0xee, 0xd9, 0x36, 0x96, 0x81, 0x7f, 0xce, 0x1f, 0x86,
+ 0x5f, 0x60, 0xbb, 0x01, 0x5d, 0xc0, 0xbf, 0x0c, 0xfc, 0x73, 0xad, 0x0e,
+ 0xfa, 0x96, 0x11, 0xc5, 0xd9, 0xe8, 0x3c, 0xdb, 0xb0, 0x2c, 0xda, 0xf7,
+ 0x08, 0xdd, 0xe5, 0xa7, 0xe0, 0x73, 0xd8, 0x27, 0x57, 0xb3, 0xb0, 0x2b,
+ 0xad, 0xea, 0xf2, 0xde, 0x3a, 0x2d, 0xaf, 0xad, 0xa1, 0x42, 0x55, 0xd9,
+ 0x6c, 0xc1, 0x1b, 0xae, 0x64, 0x74, 0xe9, 0x7b, 0x88, 0xee, 0x84, 0xad,
+ 0x2e, 0x3b, 0x3c, 0xe6, 0x79, 0x35, 0x37, 0x5e, 0x1b, 0xd0, 0x8a, 0xec,
+ 0xbf, 0x86, 0x3f, 0x04, 0x7d, 0x6a, 0xee, 0xb7, 0x6b, 0x0f, 0xb1, 0x8c,
+ 0x70, 0x16, 0xb2, 0xaa, 0xee, 0x7f, 0x06, 0xd0, 0xdf, 0x75, 0x30, 0xd7,
+ 0xc7, 0x63, 0x8f, 0x2b, 0x9d, 0x25, 0x6d, 0xbf, 0x23, 0x06, 0x3a, 0x43,
+ 0x9f, 0xb7, 0x1f, 0x93, 0xfb, 0x6a, 0xd5, 0xfe, 0x4e, 0xfa, 0x50, 0xe7,
+ 0x18, 0x7c, 0x85, 0xc8, 0xf0, 0x6a, 0xbb, 0xc1, 0x8f, 0x6a, 0x5f, 0xdb,
+ 0x5c, 0xa2, 0x54, 0x0b, 0xe8, 0xa2, 0xab, 0x60, 0x30, 0x4e, 0x16, 0x6b,
+ 0x62, 0x20, 0x41, 0x6b, 0x63, 0x93, 0x61, 0x56, 0x68, 0x77, 0x76, 0x99,
+ 0x24, 0x6c, 0x7f, 0xe2, 0x1a, 0x6c, 0xba, 0x54, 0xab, 0xf6, 0xb5, 0x8d,
+ 0x33, 0x45, 0xe0, 0x12, 0x7b, 0xd7, 0x60, 0x07, 0xaf, 0xc1, 0x6e, 0x25,
+ 0xab, 0x8f, 0xe1, 0xc5, 0xc0, 0xe6, 0x6b, 0xb8, 0xad, 0x90, 0x9e, 0xfe,
+ 0xcd, 0xd7, 0x70, 0x38, 0x8c, 0xb3, 0x6d, 0x9c, 0x65, 0x9c, 0x3b, 0xaf,
+ 0xe1, 0x1c, 0x59, 0x4f, 0xcf, 0x11, 0x82, 0x0f, 0x4a, 0x74, 0xe6, 0x69,
+ 0xef, 0xa5, 0xda, 0xd0, 0xc4, 0x5d, 0x84, 0xf8, 0x38, 0xb2, 0x29, 0xf4,
+ 0xe1, 0xc6, 0x5e, 0x0f, 0xbc, 0x32, 0x88, 0x7d, 0xa2, 0x46, 0x55, 0xc8,
+ 0xf9, 0x8f, 0x9a, 0xb4, 0xf7, 0x62, 0xd3, 0x08, 0x75, 0x89, 0x75, 0xe2,
+ 0x6d, 0xd8, 0x58, 0x72, 0xca, 0x40, 0x0c, 0xbf, 0x20, 0x6d, 0x8c, 0x26,
+ 0xaa, 0x35, 0xaa, 0x6c, 0xcf, 0x3f, 0x11, 0x40, 0x17, 0xa7, 0xe0, 0xd3,
+ 0xc0, 0xe3, 0xe4, 0x98, 0x97, 0xc3, 0x7c, 0x93, 0x6d, 0x0b, 0x7e, 0x05,
+ 0xb0, 0xd0, 0xb5, 0x84, 0x3e, 0xbf, 0xeb, 0x55, 0x4f, 0xe7, 0x7d, 0x2c,
+ 0xe4, 0x5c, 0x89, 0x84, 0x98, 0xbf, 0x1a, 0xb0, 0x9e, 0x4d, 0x8f, 0x5c,
+ 0x45, 0x8e, 0x63, 0x92, 0x37, 0x06, 0xff, 0x01, 0x7d, 0x9f, 0x6d, 0x11,
+ 0x72, 0x82, 0x3f, 0xed, 0x55, 0x36, 0xf6, 0x9d, 0xad, 0xea, 0x49, 0x06,
+ 0xfb, 0xf2, 0xe9, 0x1c, 0xe7, 0x0f, 0x9d, 0x09, 0x2f, 0x37, 0xbe, 0x4d,
+ 0x3f, 0x7b, 0x60, 0x9b, 0x38, 0x5b, 0xd9, 0x26, 0x10, 0x03, 0x60, 0x53,
+ 0xc2, 0xcb, 0xa1, 0x7f, 0x36, 0xb2, 0xa1, 0x0c, 0x6c, 0x88, 0x69, 0x65,
+ 0x3a, 0x7f, 0x04, 0x7b, 0x95, 0xb4, 0xd2, 0x84, 0x0f, 0x9a, 0x46, 0x3f,
+ 0x82, 0x9e, 0xe0, 0x2c, 0xf0, 0x81, 0x05, 0x70, 0x49, 0x8c, 0xfe, 0x2a,
+ 0xb4, 0x67, 0xee, 0xbf, 0x1b, 0xa8, 0x78, 0x72, 0x30, 0xdc, 0xff, 0x17,
+ 0xa1, 0x0f, 0x88, 0x70, 0x31, 0x9e, 0xac, 0x36, 0x81, 0x5c, 0x68, 0xa2,
+ 0x65, 0x68, 0xec, 0xcf, 0x8b, 0x3e, 0xe7, 0x30, 0x9c, 0xbf, 0x3c, 0x1e,
+ 0xfa, 0x45, 0xce, 0x5b, 0x92, 0x21, 0x4f, 0x73, 0x51, 0x5c, 0x94, 0xf6,
+ 0x86, 0x18, 0x65, 0x95, 0x5d, 0x99, 0xd3, 0x68, 0xd3, 0xb9, 0x24, 0xd6,
+ 0x61, 0xae, 0x85, 0x73, 0xc3, 0x2f, 0x21, 0x0f, 0xe2, 0xdc, 0x14, 0xeb,
+ 0x3b, 0x43, 0x9b, 0xbf, 0x44, 0x65, 0xf8, 0x54, 0xc3, 0xe1, 0xf7, 0x5e,
+ 0x2f, 0x75, 0x61, 0xdc, 0xc4, 0x5e, 0xf0, 0x13, 0xba, 0xe4, 0x33, 0x62,
+ 0x41, 0xfa, 0x06, 0xce, 0xaf, 0xb0, 0xd6, 0xc2, 0x5a, 0xf6, 0xbb, 0xbc,
+ 0xf6, 0x3c, 0xe8, 0xc0, 0xb8, 0xc9, 0x30, 0xec, 0xa3, 0x82, 0xf7, 0xbc,
+ 0xdc, 0x1e, 0x73, 0x82, 0x12, 0x21, 0x5e, 0xab, 0x0d, 0xef, 0xc6, 0xb5,
+ 0x9c, 0xd3, 0x04, 0x17, 0x74, 0x87, 0xf1, 0x47, 0x79, 0x18, 0xd1, 0xf4,
+ 0x09, 0xe4, 0x71, 0x4e, 0x07, 0xe2, 0x14, 0x8f, 0x86, 0x4c, 0x75, 0xce,
+ 0x08, 0xe6, 0x81, 0xfe, 0xf5, 0xe3, 0xbb, 0x53, 0xd7, 0xfc, 0x23, 0x5b,
+ 0x17, 0x15, 0x10, 0x1f, 0xc0, 0x27, 0x6b, 0x8a, 0x73, 0xbf, 0x62, 0x53,
+ 0xa2, 0xc4, 0xdc, 0x18, 0x7c, 0xa2, 0xca, 0xa3, 0x2e, 0xf8, 0x1b, 0xe5,
+ 0x66, 0x82, 0xd7, 0x05, 0xf0, 0xd7, 0x82, 0xfe, 0x8c, 0x03, 0x96, 0x8e,
+ 0x00, 0x07, 0xc7, 0x6a, 0x57, 0xe4, 0x53, 0x54, 0x36, 0x39, 0xa7, 0xe8,
+ 0x64, 0xfa, 0x0a, 0x6c, 0xfb, 0x22, 0xbf, 0x19, 0x73, 0xdc, 0x7f, 0xac,
+ 0x57, 0xc9, 0xab, 0x9b, 0xc7, 0x13, 0x22, 0xdf, 0xbb, 0x61, 0xfe, 0x9f,
+ 0xbb, 0x15, 0x6d, 0x72, 0x8c, 0xf9, 0x7f, 0xdb, 0x30, 0xfe, 0xe3, 0xd4,
+ 0xfa, 0xf1, 0xdd, 0xdb, 0x42, 0xfd, 0x43, 0xff, 0xf1, 0x90, 0x5e, 0xd0,
+ 0xb6, 0x46, 0x6b, 0x94, 0x2b, 0x53, 0x5d, 0x20, 0x5f, 0xf4, 0x72, 0xbb,
+ 0xac, 0x2a, 0x6c, 0xaa, 0xd4, 0x02, 0xdd, 0x6b, 0x71, 0x6c, 0x6d, 0x4d,
+ 0xe5, 0xda, 0x1a, 0xe5, 0xe7, 0x4b, 0xad, 0x00, 0x79, 0x56, 0x7b, 0xcc,
+ 0xcb, 0xa2, 0x5f, 0xc1, 0x3e, 0x05, 0x9a, 0xf6, 0x2f, 0x16, 0x84, 0x73,
+ 0x4c, 0xe6, 0x89, 0xc2, 0x79, 0x4a, 0x2b, 0x2d, 0x73, 0xfe, 0x08, 0x5b,
+ 0x72, 0x64, 0xdd, 0x80, 0x98, 0x72, 0x5c, 0x2b, 0x9c, 0x5e, 0x40, 0xfe,
+ 0xb8, 0x82, 0xdf, 0x19, 0xfc, 0x9a, 0xf8, 0x45, 0xf9, 0xfb, 0x33, 0xc8,
+ 0xff, 0xa5, 0x7f, 0x45, 0x2c, 0x50, 0xfb, 0xff, 0x62, 0x05, 0x3a, 0xb6,
+ 0x90, 0xa6, 0x6f, 0x3b, 0xa2, 0x5f, 0x28, 0x9f, 0x52, 0x40, 0xde, 0x6b,
+ 0xbe, 0x4d, 0xbf, 0x13, 0xe6, 0x50, 0x44, 0xaf, 0xd7, 0xc1, 0xc7, 0x91,
+ 0xfd, 0xa1, 0xbe, 0x66, 0x1f, 0xf4, 0xa4, 0xef, 0x0c, 0x73, 0x24, 0xe4,
+ 0x6a, 0x05, 0xb9, 0xea, 0xfb, 0xe0, 0x8d, 0x46, 0x6f, 0x41, 0x7f, 0x5e,
+ 0xaf, 0x77, 0x81, 0x1e, 0x87, 0xca, 0x93, 0xf6, 0x18, 0x69, 0x43, 0xe6,
+ 0x26, 0xad, 0x0b, 0x36, 0x0c, 0xfb, 0x96, 0x63, 0x4a, 0x74, 0xe4, 0xcf,
+ 0xcd, 0x2c, 0xd5, 0x04, 0xd6, 0x22, 0xef, 0xc9, 0xa1, 0x0f, 0xd9, 0x5f,
+ 0xa9, 0x33, 0x9c, 0xa0, 0x37, 0xea, 0x3a, 0xbd, 0x89, 0xbc, 0xeb, 0x2d,
+ 0xe7, 0xdc, 0x0c, 0x62, 0xd6, 0x00, 0xe2, 0x03, 0x6a, 0x98, 0x5d, 0xec,
+ 0xa3, 0x77, 0x1a, 0x78, 0x96, 0xf0, 0xbb, 0x13, 0x79, 0xe3, 0xf5, 0x61,
+ 0x3e, 0x6d, 0x3d, 0xd3, 0x96, 0x00, 0x0c, 0xaf, 0x37, 0x40, 0x5b, 0x0f,
+ 0xe4, 0x6f, 0x9b, 0x53, 0xf4, 0xcb, 0x5e, 0x99, 0xab, 0x68, 0x3c, 0xaf,
+ 0xfc, 0xd2, 0x27, 0xe7, 0x99, 0xcf, 0x3a, 0x74, 0x9c, 0xc7, 0xfc, 0x8e,
+ 0xfd, 0x27, 0xe3, 0xb3, 0xc7, 0x0a, 0x38, 0xcc, 0x95, 0xba, 0xea, 0x47,
+ 0x73, 0xa4, 0x45, 0x31, 0x8c, 0xfd, 0x62, 0x89, 0x0a, 0x92, 0xef, 0x13,
+ 0x24, 0x65, 0xb0, 0x4e, 0x9e, 0x94, 0x30, 0xf2, 0xf5, 0x99, 0x39, 0x87,
+ 0xe5, 0x0a, 0xff, 0x56, 0x8b, 0xe4, 0xca, 0x32, 0xea, 0xa4, 0x6a, 0xfd,
+ 0x29, 0xc8, 0x55, 0x84, 0xf5, 0x01, 0xec, 0x7b, 0x81, 0xe5, 0x8b, 0xba,
+ 0xb1, 0x8e, 0xbc, 0xa7, 0x4e, 0x29, 0x55, 0xdf, 0x1c, 0x47, 0x5d, 0x00,
+ 0xf9, 0xd5, 0x16, 0x80, 0x03, 0x36, 0x5a, 0x5b, 0xc1, 0x13, 0xb5, 0x48,
+ 0xed, 0x0c, 0x9e, 0x83, 0x78, 0x36, 0x59, 0x37, 0xc3, 0x3c, 0xe3, 0x13,
+ 0xf4, 0xc0, 0x9e, 0x4a, 0x6c, 0x4f, 0xf4, 0x8f, 0xad, 0x3c, 0xfd, 0x43,
+ 0x6b, 0x8c, 0x7e, 0xd4, 0xca, 0xd1, 0x0f, 0x5b, 0x2e, 0xfd, 0x7d, 0x6b,
+ 0x84, 0x9e, 0x6d, 0x65, 0xb9, 0x96, 0x43, 0xce, 0x64, 0x71, 0xce, 0x44,
+ 0x0f, 0xfa, 0xb7, 0xc3, 0xde, 0x59, 0xfe, 0xe7, 0x66, 0x0a, 0xcd, 0x21,
+ 0x2a, 0x9f, 0x80, 0x6f, 0x76, 0x6f, 0xe3, 0x1a, 0x94, 0x1e, 0x73, 0xb9,
+ 0x86, 0xe8, 0xe0, 0xf7, 0xa8, 0x23, 0xe0, 0xbb, 0xe1, 0xcb, 0xa6, 0xd2,
+ 0xf6, 0x39, 0x4f, 0x1f, 0x08, 0x7d, 0xc0, 0x5d, 0x29, 0xea, 0xc2, 0x5e,
+ 0xf0, 0x7f, 0x17, 0x9f, 0x86, 0x0d, 0xc8, 0x1a, 0x28, 0x01, 0x5f, 0xc3,
+ 0x79, 0x80, 0xc1, 0x76, 0xcc, 0xf5, 0x87, 0xe5, 0xe9, 0x5c, 0x17, 0xb2,
+ 0x3d, 0xeb, 0x08, 0x1a, 0x0c, 0x37, 0x69, 0xb2, 0xdc, 0x0c, 0x87, 0x7d,
+ 0x6a, 0x21, 0xf4, 0x6f, 0x89, 0x50, 0x2f, 0x4d, 0xcc, 0x3f, 0x15, 0xfa,
+ 0xe3, 0x8d, 0xfb, 0x20, 0x56, 0x20, 0x97, 0x54, 0xeb, 0x18, 0x56, 0x0b,
+ 0x61, 0xfb, 0xc3, 0xb9, 0x24, 0xf8, 0xed, 0x52, 0xd9, 0x7f, 0x43, 0xe3,
+ 0x1c, 0x5b, 0x38, 0xcc, 0xff, 0x11, 0x8c, 0x2f, 0x87, 0xe3, 0xaf, 0xd0,
+ 0xf4, 0x22, 0x81, 0xd6, 0xd7, 0xb4, 0xa2, 0x1c, 0x8f, 0x61, 0x2c, 0x30,
+ 0xd6, 0xb9, 0x6e, 0xe0, 0x0c, 0x23, 0xc5, 0xba, 0x2e, 0x9c, 0x71, 0xf0,
+ 0x71, 0x12, 0xbf, 0x82, 0xfc, 0x3d, 0xe2, 0x0f, 0x15, 0xde, 0x41, 0xbc,
+ 0xd0, 0x3a, 0xa2, 0xdc, 0x67, 0x3b, 0x6a, 0xcf, 0x20, 0x38, 0x84, 0x5a,
+ 0xdd, 0x4a, 0x19, 0xf4, 0x2f, 0xf3, 0xb6, 0x79, 0x48, 0xcc, 0xe1, 0x4c,
+ 0x41, 0x30, 0xe1, 0xd8, 0x95, 0x82, 0xe8, 0xa6, 0x9f, 0x1f, 0xe7, 0xb8,
+ 0x5b, 0x9f, 0x79, 0x01, 0xba, 0xd7, 0x58, 0xe9, 0xa4, 0x46, 0xc3, 0xa0,
+ 0x2b, 0xa3, 0x43, 0xa0, 0xd3, 0xa4, 0x46, 0x33, 0x85, 0x5c, 0x6e, 0x33,
+ 0xa1, 0x3c, 0x94, 0x0e, 0x43, 0xcf, 0x67, 0xa5, 0x8f, 0xf6, 0x1c, 0x3c,
+ 0x9b, 0x1f, 0xf4, 0xae, 0x3f, 0x73, 0x09, 0xf4, 0xf7, 0xa0, 0x0a, 0xd9,
+ 0x2e, 0xe5, 0x5c, 0xf6, 0x87, 0x4c, 0x4f, 0x20, 0x6e, 0x19, 0x43, 0xe6,
+ 0x7e, 0xf1, 0xab, 0xe0, 0x0e, 0x83, 0x65, 0xf7, 0xaa, 0xac, 0x77, 0x64,
+ 0x9c, 0xc3, 0x7e, 0x4b, 0x2b, 0xaf, 0x81, 0x16, 0x93, 0x9e, 0x6d, 0x6e,
+ 0x0f, 0xc7, 0x96, 0xe4, 0xc5, 0xb3, 0xcd, 0x2e, 0xfa, 0x61, 0x63, 0x0b,
+ 0x2d, 0x37, 0xf8, 0x7d, 0x27, 0x2d, 0x35, 0x86, 0xae, 0x1e, 0x15, 0x03,
+ 0xb4, 0x7a, 0xe3, 0x4d, 0xe6, 0x57, 0x05, 0xf2, 0x82, 0xc9, 0x8f, 0xe9,
+ 0xbd, 0xd1, 0x5e, 0xfa, 0xe9, 0x3d, 0x76, 0xfd, 0x7e, 0x01, 0x1b, 0x18,
+ 0x4d, 0xb2, 0x6d, 0xa3, 0xcf, 0xf3, 0xf6, 0x55, 0x4b, 0xb0, 0x6e, 0xff,
+ 0x04, 0x3c, 0xb5, 0x8f, 0x29, 0x3b, 0x60, 0xdc, 0x8c, 0x17, 0xba, 0xe1,
+ 0xbc, 0x08, 0x9c, 0x78, 0xd7, 0x1c, 0x02, 0xae, 0x17, 0x25, 0x2f, 0x0e,
+ 0xb9, 0xf6, 0x55, 0x42, 0x0e, 0x79, 0xc5, 0x19, 0xca, 0x0a, 0xb1, 0x9d,
+ 0x1a, 0x99, 0x9b, 0xcc, 0xf3, 0xf0, 0xff, 0xa8, 0xab, 0x2a, 0x97, 0xa9,
+ 0x3e, 0x73, 0xc9, 0x61, 0xfd, 0x67, 0xbf, 0xf1, 0x12, 0xf2, 0x4e, 0x93,
+ 0x4e, 0x34, 0xd9, 0x5f, 0x32, 0x2e, 0xce, 0xfd, 0x77, 0x9b, 0x5f, 0x13,
+ 0x9c, 0x23, 0xe0, 0x1d, 0xe6, 0xf5, 0x2f, 0xb1, 0x9c, 0x3b, 0x18, 0x36,
+ 0x6b, 0x89, 0x60, 0x03, 0x8f, 0x86, 0xcc, 0x5d, 0x82, 0xf7, 0xfb, 0x6f,
+ 0xec, 0xfb, 0x2e, 0x68, 0x1d, 0x02, 0x2c, 0xe2, 0x65, 0xa6, 0x7d, 0x8f,
+ 0x57, 0xe4, 0x1e, 0xc7, 0x9b, 0xc8, 0xf3, 0xd6, 0xf6, 0xc0, 0x5c, 0x53,
+ 0xe0, 0x9c, 0x86, 0x94, 0xcb, 0x95, 0x51, 0xe6, 0xef, 0x6d, 0x7d, 0x9c,
+ 0x63, 0xea, 0xf9, 0xbf, 0x09, 0xa2, 0x5a, 0xf3, 0x95, 0xf9, 0x49, 0xf8,
+ 0xe7, 0x20, 0xa8, 0xee, 0x1e, 0x52, 0x71, 0x68, 0x90, 0xdf, 0x1f, 0x90,
+ 0xb2, 0xa8, 0x8a, 0x4e, 0xba, 0xc3, 0xb0, 0x00, 0xcb, 0x73, 0x2f, 0x87,
+ 0x72, 0x84, 0x11, 0x75, 0xa1, 0xdf, 0x8c, 0xf4, 0x32, 0x05, 0x1d, 0xdb,
+ 0x63, 0x1e, 0x0a, 0x63, 0x32, 0xc7, 0xb4, 0x9f, 0x42, 0xe7, 0xac, 0x14,
+ 0xeb, 0x4d, 0xaa, 0xef, 0x9a, 0xde, 0xf0, 0xbb, 0xfa, 0x8c, 0x07, 0xda,
+ 0x8a, 0x0b, 0x9d, 0x54, 0xaa, 0x27, 0x90, 0x03, 0x19, 0x34, 0x97, 0xc3,
+ 0x18, 0x3a, 0x54, 0x6a, 0xb0, 0xce, 0x57, 0x42, 0x9d, 0x4f, 0x86, 0xb8,
+ 0x4f, 0x82, 0x17, 0xb6, 0xb5, 0x2a, 0xb8, 0x76, 0xda, 0x26, 0xeb, 0x5f,
+ 0x1d, 0xb6, 0x5c, 0xae, 0x71, 0xed, 0x89, 0xfc, 0xdb, 0x3c, 0x37, 0x33,
+ 0xed, 0x18, 0xa0, 0x6b, 0x44, 0x2b, 0xb7, 0x1c, 0xad, 0xec, 0x33, 0x7d,
+ 0xbb, 0x41, 0xb7, 0x26, 0x6b, 0xdc, 0xa5, 0xd6, 0x7b, 0xc1, 0xd2, 0xee,
+ 0x4d, 0xe8, 0x43, 0xe7, 0x27, 0x58, 0xae, 0x5f, 0x60, 0xba, 0xac, 0x82,
+ 0x60, 0x3e, 0xa7, 0xe9, 0xd4, 0xf0, 0xdf, 0xf5, 0x72, 0x3e, 0x75, 0x7a,
+ 0x98, 0xf1, 0x83, 0x8e, 0x74, 0x9a, 0x96, 0x7d, 0xde, 0xa3, 0x3e, 0xc3,
+ 0x3c, 0x2c, 0x2f, 0x98, 0xf4, 0x88, 0x94, 0xdb, 0x6b, 0xd2, 0xa6, 0xcb,
+ 0x2b, 0xb0, 0xa5, 0xd4, 0x90, 0x79, 0x94, 0xec, 0xab, 0x17, 0x75, 0xbb,
+ 0x3e, 0x05, 0x7b, 0x5e, 0x5a, 0xd4, 0x69, 0xa7, 0xac, 0xb1, 0x58, 0x36,
+ 0xf6, 0x31, 0x58, 0x7c, 0x78, 0xf6, 0x43, 0x6d, 0x67, 0xef, 0xa1, 0x4b,
+ 0x4f, 0xff, 0x16, 0x7c, 0x0d, 0xf3, 0xd5, 0xb0, 0x0e, 0x23, 0x9f, 0x58,
+ 0x40, 0xee, 0x51, 0x45, 0x6e, 0x5c, 0xc8, 0x30, 0x6c, 0xc4, 0xef, 0xad,
+ 0x92, 0xff, 0x42, 0xf2, 0x7f, 0x07, 0x55, 0xa5, 0x0d, 0x65, 0xe4, 0x3b,
+ 0x01, 0x1c, 0xea, 0x1d, 0x8f, 0x91, 0x2b, 0xc9, 0x77, 0xf7, 0x2a, 0x38,
+ 0xf6, 0x11, 0x19, 0x7e, 0x77, 0x14, 0x7b, 0x32, 0x8f, 0xa3, 0xf9, 0x6e,
+ 0x52, 0x36, 0x14, 0xf1, 0x1d, 0x89, 0x44, 0x33, 0x4d, 0xbf, 0x8b, 0x9a,
+ 0x67, 0xb2, 0x39, 0x48, 0xa5, 0xa6, 0x05, 0x19, 0xcc, 0xf4, 0xf1, 0xd9,
+ 0x8a, 0x2b, 0x38, 0x8f, 0x60, 0x5a, 0xef, 0xa5, 0xc3, 0x7e, 0x44, 0x4f,
+ 0x32, 0xa4, 0x6f, 0x32, 0x1c, 0x27, 0x42, 0x1a, 0xda, 0xf1, 0x25, 0x81,
+ 0x0b, 0x31, 0x3e, 0xf7, 0x57, 0x21, 0x1e, 0xf6, 0x1f, 0xa0, 0x75, 0x32,
+ 0x43, 0x2b, 0x3e, 0xd3, 0xb1, 0x85, 0xaa, 0x69, 0xee, 0x1f, 0x80, 0x9e,
+ 0x31, 0x9e, 0x4d, 0x9c, 0xc7, 0xac, 0xe3, 0xf1, 0x91, 0x66, 0x05, 0x3c,
+ 0x66, 0xfe, 0xf2, 0xba, 0x24, 0x2d, 0x7d, 0x85, 0xe5, 0xb7, 0x07, 0xf9,
+ 0x3b, 0xeb, 0xc2, 0x96, 0x50, 0xaf, 0xd4, 0x9e, 0xa5, 0x85, 0x1e, 0xc8,
+ 0x8a, 0xf7, 0xed, 0xa2, 0xbb, 0x61, 0xef, 0xc5, 0x06, 0xef, 0x3f, 0x09,
+ 0x3d, 0x7a, 0x59, 0xee, 0x5f, 0x5a, 0x19, 0x08, 0xe1, 0x19, 0xb6, 0x67,
+ 0x03, 0x6c, 0x27, 0xed, 0xab, 0x9b, 0xd7, 0x81, 0xff, 0x7d, 0xc0, 0x0b,
+ 0x3a, 0x99, 0x63, 0x78, 0xc6, 0x83, 0x75, 0x8d, 0xf4, 0x67, 0xe0, 0x49,
+ 0xc9, 0x5a, 0xbe, 0xd8, 0xe8, 0xa4, 0x62, 0x3d, 0xc2, 0xc5, 0x78, 0x3e,
+ 0x46, 0xad, 0x7b, 0x9f, 0xc4, 0x35, 0x2d, 0x71, 0xe1, 0x7d, 0x83, 0x7d,
+ 0xcd, 0xad, 0x80, 0x47, 0xbd, 0xee, 0x80, 0xb6, 0x54, 0x37, 0x2d, 0xc9,
+ 0x7a, 0xbd, 0x4b, 0xf9, 0x98, 0xd4, 0x66, 0xbc, 0xdf, 0x02, 0x5b, 0xdf,
+ 0x83, 0x3c, 0xa6, 0x07, 0x73, 0xd6, 0x86, 0xb9, 0x8d, 0xf4, 0x27, 0x36,
+ 0xd0, 0xdf, 0x89, 0x75, 0xfd, 0xd8, 0x53, 0xad, 0x2b, 0x61, 0xdd, 0xec,
+ 0x02, 0x6c, 0x82, 0x73, 0xf3, 0x34, 0xc7, 0xe4, 0x1b, 0x25, 0x2d, 0xb3,
+ 0x2b, 0xef, 0xe1, 0x5c, 0x03, 0x80, 0x8d, 0xc6, 0x8a, 0x0f, 0x75, 0xe0,
+ 0xf9, 0x5e, 0x43, 0xde, 0x4b, 0x40, 0x06, 0x9b, 0x53, 0x7c, 0xf6, 0x6a,
+ 0xe3, 0xf3, 0x78, 0x76, 0x63, 0x1b, 0xbf, 0x98, 0x57, 0x4c, 0x2f, 0xd3,
+ 0x0a, 0x3d, 0x25, 0xd8, 0x9b, 0x8b, 0x9a, 0x2f, 0xa5, 0x53, 0x29, 0x87,
+ 0x78, 0xee, 0xf3, 0x5d, 0x2d, 0xdb, 0xe5, 0xa0, 0xaa, 0x0b, 0x1c, 0x8e,
+ 0xeb, 0x86, 0x3c, 0xfb, 0xe1, 0x15, 0xbe, 0xaf, 0xb5, 0x10, 0x4f, 0xed,
+ 0x2c, 0xe1, 0xec, 0x0f, 0xaf, 0x38, 0xf4, 0x68, 0x33, 0x4b, 0x47, 0x9b,
+ 0xb6, 0x79, 0x3f, 0x7c, 0x40, 0x79, 0xed, 0x1e, 0x77, 0x57, 0x8a, 0xfd,
+ 0x96, 0x81, 0x9c, 0xb3, 0xc3, 0x51, 0x39, 0x48, 0x95, 0xeb, 0xb1, 0x05,
+ 0x9b, 0xef, 0x68, 0xcc, 0x06, 0x6d, 0xcc, 0x53, 0xfe, 0x2f, 0x73, 0x14,
+ 0xde, 0x9f, 0xfd, 0x34, 0x72, 0x12, 0x1f, 0x39, 0x89, 0x8f, 0x9c, 0xc4,
+ 0x47, 0x4e, 0xe2, 0x23, 0x27, 0xf1, 0x91, 0x93, 0xf8, 0xc8, 0x49, 0x7c,
+ 0xe4, 0x24, 0xc8, 0xff, 0x55, 0x5d, 0x30, 0x8e, 0x5c, 0x1b, 0xfe, 0xcb,
+ 0xff, 0x6a, 0x98, 0x53, 0x44, 0x31, 0x99, 0xe7, 0x56, 0x37, 0x79, 0x6e,
+ 0x74, 0x4f, 0x7c, 0x00, 0x73, 0x13, 0x61, 0xee, 0xc3, 0x6b, 0xa2, 0x98,
+ 0xcd, 0xeb, 0x68, 0xcc, 0x43, 0xbd, 0x59, 0x98, 0xe4, 0xdc, 0x48, 0xc5,
+ 0x2a, 0x95, 0x97, 0xbf, 0x8a, 0xfc, 0xc8, 0x42, 0x7e, 0x34, 0x88, 0x5c,
+ 0x88, 0xef, 0xb5, 0xa3, 0xfb, 0xa3, 0x82, 0x76, 0xc8, 0x1f, 0xd7, 0xbe,
+ 0xe6, 0x73, 0xde, 0xee, 0x58, 0x65, 0x21, 0x16, 0xfa, 0x29, 0xa0, 0xe2,
+ 0xe8, 0xb7, 0x90, 0x23, 0x7f, 0x4f, 0xde, 0x95, 0x4d, 0x0c, 0xb3, 0xcc,
+ 0x27, 0x3e, 0x25, 0x4f, 0x8e, 0xf8, 0xab, 0xee, 0xf8, 0xc4, 0x12, 0xf3,
+ 0x8f, 0xa8, 0xef, 0x2c, 0x18, 0x7e, 0x36, 0x41, 0xa9, 0x53, 0x5b, 0x30,
+ 0x67, 0x52, 0xbf, 0xbc, 0x27, 0x82, 0x28, 0xcf, 0xfe, 0x1a, 0xf2, 0x72,
+ 0x48, 0x9c, 0xe5, 0xdb, 0x04, 0xc6, 0xcb, 0xfe, 0xb5, 0x32, 0x53, 0x6c,
+ 0x54, 0xa4, 0x4e, 0x1d, 0x6a, 0x96, 0x90, 0x3f, 0xf5, 0xf6, 0x53, 0x97,
+ 0x81, 0x1a, 0x2a, 0xc2, 0xcd, 0x38, 0x7f, 0x99, 0x92, 0xb5, 0xcd, 0xd9,
+ 0x35, 0x79, 0x42, 0xd6, 0xbc, 0x4f, 0x65, 0xa6, 0x5a, 0xb7, 0x33, 0x5c,
+ 0xd7, 0x82, 0xd6, 0x99, 0x27, 0x81, 0x63, 0x19, 0x39, 0x81, 0x2e, 0xf7,
+ 0xae, 0xcc, 0xcc, 0xd6, 0xd5, 0x5d, 0x95, 0xa2, 0x01, 0xf1, 0x2f, 0xd7,
+ 0x45, 0xfa, 0x92, 0xba, 0xb3, 0x12, 0x12, 0x96, 0xe1, 0x18, 0xde, 0x00,
+ 0x1c, 0xcb, 0x2d, 0x0b, 0x58, 0x96, 0x1d, 0xd3, 0x50, 0x99, 0xa9, 0x34,
+ 0xda, 0x69, 0x60, 0x3c, 0x8c, 0x37, 0x3a, 0x0f, 0x9f, 0x25, 0x45, 0xe2,
+ 0x54, 0x10, 0x94, 0x47, 0x07, 0xc3, 0x3a, 0x12, 0xf5, 0xe3, 0x09, 0x43,
+ 0xea, 0xb9, 0x1a, 0x7f, 0x53, 0xc6, 0x29, 0x4b, 0xf0, 0x3c, 0x3f, 0xf1,
+ 0x2e, 0xf7, 0x24, 0xe6, 0x30, 0x5e, 0x8e, 0xd6, 0x8a, 0x70, 0x6d, 0x77,
+ 0x1b, 0x3f, 0x3b, 0xc2, 0xfd, 0x98, 0x26, 0x3e, 0xe7, 0x65, 0xec, 0xc5,
+ 0x74, 0xf1, 0x1a, 0x13, 0xb4, 0x41, 0x96, 0xfe, 0xff, 0x96, 0xf7, 0xed,
+ 0x67, 0x62, 0x9e, 0x1a, 0x80, 0xe1, 0xf5, 0x8c, 0x23, 0x82, 0xc1, 0x8b,
+ 0xb3, 0x0a, 0x4e, 0xac, 0xdd, 0xed, 0x7d, 0xd6, 0xbe, 0xed, 0xb4, 0x46,
+ 0xfb, 0x47, 0x78, 0xb2, 0x4a, 0x6e, 0x6b, 0xf0, 0xf2, 0xff, 0x0a, 0xc3,
+ 0x13, 0xba, 0xf8, 0x89, 0x3b, 0xd2, 0x6c, 0x5b, 0x6d, 0x1c, 0xdd, 0x35,
+ 0x70, 0xcd, 0xcf, 0x35, 0x3c, 0x7f, 0x47, 0x68, 0xaf, 0x4b, 0x4b, 0x61,
+ 0x2c, 0x83, 0x2e, 0xaa, 0xbb, 0xd4, 0x70, 0x6c, 0x70, 0x6c, 0x43, 0xe3,
+ 0x1c, 0x3f, 0xb2, 0x91, 0xf6, 0x7b, 0x42, 0x95, 0x9b, 0x9c, 0x59, 0x8c,
+ 0x7c, 0x0e, 0xfc, 0xc1, 0xb0, 0x11, 0xfa, 0xed, 0x24, 0xfc, 0x56, 0x0f,
+ 0xed, 0x83, 0xbf, 0xb9, 0x13, 0xfe, 0x66, 0x3f, 0xea, 0xca, 0xf1, 0x95,
+ 0xf6, 0xfb, 0x57, 0xae, 0x65, 0xab, 0x74, 0x58, 0xca, 0xae, 0x12, 0xe8,
+ 0xce, 0xc7, 0x90, 0xdf, 0x2e, 0x99, 0xa3, 0x29, 0x79, 0xc2, 0x57, 0xba,
+ 0xfc, 0x2d, 0x62, 0xe3, 0x3d, 0x6f, 0x16, 0x7a, 0xdd, 0x55, 0x10, 0x32,
+ 0xff, 0x52, 0x7c, 0xab, 0x36, 0x14, 0xdf, 0xe0, 0x53, 0x81, 0xdf, 0xa0,
+ 0x4a, 0xd3, 0xa4, 0x0a, 0xf6, 0xad, 0x60, 0xdf, 0x0a, 0xea, 0xc1, 0xd9,
+ 0x66, 0xfb, 0x77, 0xaa, 0xee, 0xb0, 0xc6, 0x66, 0xd8, 0xa8, 0x6f, 0x86,
+ 0xe7, 0xd2, 0xda, 0x9e, 0xc7, 0xc0, 0xbb, 0x47, 0xc1, 0xbb, 0x23, 0xa8,
+ 0x83, 0xfe, 0x04, 0x75, 0xd0, 0x1f, 0xa2, 0x0e, 0x3a, 0x8c, 0x3a, 0x68,
+ 0x0a, 0x75, 0xd0, 0x7d, 0xb0, 0xfd, 0x7b, 0x61, 0xfb, 0x93, 0xb0, 0xfd,
+ 0x09, 0x79, 0xc7, 0x73, 0xc8, 0xdf, 0x78, 0xef, 0x11, 0xed, 0xc5, 0xed,
+ 0x4d, 0x22, 0x88, 0xaf, 0x7c, 0x62, 0x9c, 0x1a, 0x2d, 0xae, 0x87, 0x5c,
+ 0x79, 0x7f, 0x35, 0xed, 0x4e, 0x6a, 0x53, 0xc8, 0xb9, 0xef, 0x1f, 0xe1,
+ 0x3a, 0x29, 0xa5, 0xee, 0x2b, 0x73, 0xf6, 0x73, 0x1e, 0xd2, 0x2e, 0xe4,
+ 0x6d, 0x38, 0xb3, 0x7d, 0xa6, 0xa8, 0x47, 0x35, 0x4a, 0xdf, 0x5a, 0x8d,
+ 0xb2, 0x3c, 0xcf, 0x35, 0xca, 0xab, 0x6b, 0x35, 0xca, 0xf2, 0x3c, 0xd7,
+ 0x28, 0xaf, 0xac, 0xab, 0x51, 0xae, 0x3c, 0xfd, 0xf2, 0xba, 0x1a, 0xe5,
+ 0xca, 0xd3, 0x2f, 0x85, 0x63, 0xa6, 0x03, 0x7e, 0xc9, 0x0d, 0x69, 0x35,
+ 0x5d, 0x3c, 0x7b, 0xc3, 0x7c, 0xe1, 0xfb, 0xfd, 0xeb, 0xff, 0x1f, 0x3a,
+ 0x6e, 0x9d, 0x1a, 0x39, 0xdf, 0xd8, 0xaa, 0xea, 0x9a, 0xf6, 0xf9, 0xde,
+ 0xb6, 0xf9, 0x55, 0xf9, 0x6d, 0xb4, 0x5c, 0xdb, 0xfc, 0x3e, 0xbc, 0x27,
+ 0xad, 0x0c, 0xdb, 0xf5, 0x02, 0x7d, 0x1c, 0xf0, 0xf7, 0x3d, 0x4f, 0x74,
+ 0xc9, 0xef, 0x6a, 0x9e, 0xcc, 0x91, 0x61, 0xa3, 0xa3, 0x47, 0xb7, 0x2a,
+ 0x3b, 0xe6, 0x7e, 0x5a, 0x53, 0xbe, 0xf9, 0x41, 0xe0, 0x01, 0xaf, 0x7d,
+ 0x43, 0xde, 0xe1, 0xa8, 0xf3, 0xaa, 0xbb, 0x6c, 0x23, 0xbf, 0x8a, 0x38,
+ 0x03, 0x59, 0x4b, 0xdc, 0x5c, 0xf3, 0x71, 0x9d, 0x18, 0xf9, 0xef, 0x08,
+ 0xd7, 0xcf, 0xd2, 0x8a, 0xee, 0xdb, 0x50, 0xef, 0xf1, 0x9a, 0x68, 0xdc,
+ 0x5e, 0x1f, 0x26, 0xc3, 0xfb, 0xac, 0x55, 0x95, 0x13, 0x49, 0x7c, 0x46,
+ 0x88, 0xef, 0xbf, 0x02, 0xe5, 0x37, 0x18, 0xde, 0x6c, 0x83, 0x1f, 0x47,
+ 0x9e, 0xc6, 0x77, 0x2b, 0x9c, 0x6f, 0x19, 0xf4, 0xee, 0x7c, 0x37, 0xbd,
+ 0x73, 0x1c, 0xf9, 0xa6, 0x6b, 0x67, 0x5f, 0x46, 0xbd, 0x70, 0x8a, 0xf3,
+ 0xe2, 0x51, 0xa6, 0x73, 0xc8, 0x9a, 0x25, 0xab, 0x5f, 0xe5, 0xd1, 0x47,
+ 0xb4, 0x4f, 0xd2, 0x2d, 0xc2, 0x7d, 0x7e, 0xd6, 0xb6, 0x8f, 0xd5, 0xb6,
+ 0x4f, 0x81, 0xed, 0xad, 0xf1, 0x75, 0x9c, 0xb9, 0xb2, 0xfd, 0x26, 0x33,
+ 0x1d, 0xd6, 0x52, 0x8f, 0x8c, 0x6e, 0xa6, 0xfa, 0x80, 0x7d, 0xee, 0x15,
+ 0xe4, 0xda, 0xe5, 0x51, 0xcc, 0xa5, 0x87, 0xf0, 0x8e, 0xe7, 0xed, 0x06,
+ 0x09, 0xfb, 0x5c, 0x83, 0x90, 0x4c, 0x77, 0xd9, 0x15, 0xbe, 0x63, 0x4b,
+ 0x0b, 0xee, 0x4b, 0xda, 0x1a, 0xa1, 0xfd, 0x66, 0x2e, 0xe2, 0xcc, 0x53,
+ 0xa8, 0x99, 0x8e, 0xa8, 0xbb, 0xaf, 0x70, 0x9f, 0x5b, 0xb4, 0x8b, 0x32,
+ 0xaf, 0xcd, 0x69, 0x95, 0xb4, 0x3a, 0xe3, 0x37, 0x60, 0xeb, 0xba, 0x60,
+ 0xd8, 0x77, 0x81, 0x5b, 0xa3, 0xa5, 0xe3, 0xba, 0xbc, 0xeb, 0x2c, 0x8f,
+ 0xb2, 0xac, 0xf9, 0x79, 0x3d, 0xde, 0x45, 0x67, 0xfa, 0xdb, 0xf0, 0x4c,
+ 0x5f, 0x0a, 0x6b, 0xed, 0xe8, 0x4c, 0x09, 0x7a, 0x63, 0xde, 0x04, 0xec,
+ 0x08, 0xf8, 0x51, 0xa2, 0x95, 0x96, 0xf5, 0x39, 0x78, 0x6a, 0x6d, 0xbc,
+ 0x31, 0x36, 0xc8, 0x30, 0xaa, 0x59, 0xc0, 0x83, 0x89, 0x0c, 0xec, 0x70,
+ 0xba, 0x3f, 0xba, 0x83, 0xd5, 0x1d, 0xa1, 0xa9, 0xda, 0x9b, 0xe7, 0x07,
+ 0x61, 0x8b, 0x16, 0xec, 0x93, 0xf3, 0x9d, 0x12, 0xd7, 0x19, 0xe1, 0xf7,
+ 0x4b, 0xdb, 0x9c, 0xa4, 0x2c, 0x6a, 0x15, 0x3e, 0x7f, 0x9e, 0x96, 0x5b,
+ 0x11, 0x0d, 0x39, 0xd8, 0xe3, 0x18, 0x7e, 0x23, 0x78, 0xe7, 0xe2, 0xc7,
+ 0x75, 0x4e, 0x81, 0x1e, 0x93, 0x79, 0x34, 0xf2, 0xe4, 0x61, 0xa6, 0xef,
+ 0x00, 0xd6, 0xb3, 0x3e, 0xb3, 0x9e, 0x1e, 0x20, 0x6f, 0x80, 0x7d, 0x45,
+ 0x06, 0xb8, 0x01, 0xe3, 0xbf, 0x0e, 0x5b, 0x1f, 0xc4, 0xd3, 0x36, 0xcb,
+ 0xcc, 0x5b, 0x89, 0x3f, 0x08, 0xf4, 0x1c, 0x7f, 0x3b, 0x18, 0x0f, 0xc7,
+ 0x43, 0xe6, 0xdd, 0xac, 0x7b, 0x99, 0x1d, 0x74, 0x6e, 0x31, 0x8a, 0x61,
+ 0x33, 0xb0, 0x41, 0xbe, 0x53, 0x1d, 0x07, 0x5f, 0x78, 0xac, 0x85, 0xb1,
+ 0x0c, 0xf3, 0xcb, 0x0b, 0x38, 0x77, 0x9e, 0x4e, 0xa1, 0x66, 0xa7, 0x01,
+ 0x7e, 0x22, 0x57, 0xf5, 0xb7, 0x84, 0xfa, 0xbe, 0x1e, 0x5e, 0x77, 0xb8,
+ 0x3f, 0x0e, 0xfa, 0x8c, 0x36, 0x78, 0x86, 0x51, 0xb5, 0xc5, 0x45, 0x42,
+ 0x2c, 0xcd, 0x04, 0xb7, 0x8b, 0xfc, 0x7d, 0xf4, 0x80, 0x3c, 0x53, 0x9e,
+ 0x0e, 0x2f, 0x06, 0x81, 0x97, 0x1b, 0xca, 0x2e, 0x93, 0x9d, 0x7d, 0x92,
+ 0xf6, 0x98, 0xfb, 0x48, 0x97, 0xdf, 0xe0, 0x50, 0x13, 0xdf, 0xde, 0x91,
+ 0x0f, 0x82, 0x93, 0xa0, 0xfd, 0x05, 0xb9, 0xcf, 0x7d, 0xa0, 0x1f, 0xbc,
+ 0x92, 0xf5, 0x04, 0xd3, 0x0a, 0xde, 0xa4, 0x99, 0xde, 0x24, 0x1d, 0x6e,
+ 0x9d, 0x0f, 0x65, 0xf3, 0x28, 0x79, 0xfe, 0xdb, 0x3a, 0xdf, 0x47, 0x97,
+ 0x5b, 0x4f, 0x86, 0xb4, 0xe5, 0x41, 0x2f, 0xf6, 0x6f, 0xbd, 0x90, 0x66,
+ 0xdf, 0xc0, 0x32, 0xf7, 0x90, 0xf1, 0x79, 0xa3, 0xcf, 0x40, 0x07, 0x3f,
+ 0xcd, 0x0f, 0xa4, 0x68, 0xbd, 0x1f, 0x60, 0xb8, 0xd4, 0x75, 0x74, 0x85,
+ 0xe9, 0x20, 0xe9, 0x3f, 0x85, 0xb3, 0x19, 0xf4, 0x30, 0x3e, 0x7d, 0x83,
+ 0x2f, 0xa8, 0xc8, 0xe7, 0xaa, 0xce, 0xbe, 0x89, 0xe3, 0x14, 0xeb, 0x70,
+ 0x0f, 0xfc, 0x1f, 0x74, 0x10, 0x76, 0x5c, 0x5c, 0xe4, 0x3b, 0x85, 0x61,
+ 0xbe, 0x87, 0x3a, 0x53, 0x82, 0x6c, 0x97, 0xf8, 0xbb, 0x60, 0x5a, 0xe5,
+ 0x82, 0xaa, 0x76, 0xb2, 0xd8, 0x17, 0x32, 0xaf, 0xa5, 0x9f, 0x2c, 0xc9,
+ 0xef, 0x80, 0x29, 0xac, 0x09, 0xf0, 0x6c, 0xff, 0x9b, 0x88, 0x9f, 0x14,
+ 0xd4, 0xdf, 0x44, 0x84, 0xdf, 0x64, 0x1b, 0x2a, 0x07, 0x78, 0xb8, 0x69,
+ 0xd0, 0x54, 0x33, 0xfa, 0x1b, 0x09, 0x96, 0x83, 0x83, 0x3a, 0x3e, 0x8a,
+ 0xfb, 0x81, 0x8c, 0x2f, 0xd5, 0x75, 0xb2, 0xfc, 0x66, 0x98, 0xcf, 0x70,
+ 0xfe, 0xce, 0x3c, 0xc4, 0x78, 0x59, 0xc9, 0x6f, 0x49, 0xec, 0x84, 0xfc,
+ 0xc0, 0x73, 0xdf, 0x80, 0x2d, 0x65, 0xc2, 0x98, 0x6c, 0x72, 0x7d, 0x18,
+ 0xd6, 0xac, 0xdb, 0xa9, 0x3a, 0xc9, 0xef, 0x13, 0xf4, 0xfa, 0xfc, 0xa0,
+ 0x7c, 0x5f, 0xa6, 0x44, 0xf8, 0x9e, 0xc7, 0x29, 0x2a, 0xcb, 0xf7, 0xf7,
+ 0x86, 0xf8, 0x50, 0x63, 0xdd, 0x1b, 0x8d, 0x33, 0x90, 0xa3, 0x82, 0x9b,
+ 0x46, 0x2c, 0x7b, 0x0c, 0x71, 0x6c, 0x1a, 0x7c, 0x2f, 0x4e, 0x54, 0x68,
+ 0x87, 0xc3, 0x3a, 0x0e, 0x99, 0xa5, 0x58, 0xc7, 0x58, 0xbf, 0x18, 0xa6,
+ 0x17, 0x79, 0x26, 0xce, 0x3b, 0x4a, 0x53, 0x7a, 0xfe, 0xfd, 0x83, 0xe5,
+ 0x9a, 0x6d, 0x16, 0xe8, 0xa3, 0xc0, 0x33, 0x78, 0xbc, 0x7a, 0xf0, 0x61,
+ 0x75, 0x4f, 0x2f, 0x44, 0xfe, 0xd2, 0xc1, 0xb2, 0xea, 0xe3, 0xcc, 0xef,
+ 0x87, 0x7d, 0x86, 0xd3, 0xe5, 0xf7, 0xd3, 0x7f, 0xbf, 0xd5, 0xa0, 0x8b,
+ 0xb7, 0x06, 0xc1, 0xfd, 0xfc, 0x0d, 0x27, 0xac, 0x41, 0xd5, 0x77, 0x71,
+ 0x8e, 0x13, 0xa8, 0x37, 0x46, 0x2d, 0xad, 0x04, 0xdb, 0x3d, 0xe5, 0xa3,
+ 0x5e, 0x11, 0xf6, 0xd8, 0xaa, 0x30, 0x11, 0x7f, 0xb9, 0x96, 0xff, 0xcd,
+ 0x7e, 0xfe, 0x26, 0x3c, 0xe7, 0xf2, 0x9a, 0x6d, 0xea, 0xae, 0xea, 0xe6,
+ 0xdb, 0xa4, 0xcf, 0x25, 0x0a, 0xe3, 0xd0, 0xcd, 0xed, 0xf6, 0xd1, 0x9e,
+ 0x23, 0xb2, 0x5d, 0xd0, 0x94, 0x01, 0x7a, 0xaa, 0xb5, 0x28, 0xdf, 0xe2,
+ 0xef, 0xfd, 0xab, 0x07, 0xbf, 0xdb, 0xbc, 0x74, 0x70, 0x16, 0xf2, 0xe1,
+ 0x33, 0xcd, 0x36, 0x23, 0xfd, 0x8b, 0x72, 0x7e, 0xee, 0x23, 0xfe, 0xfb,
+ 0x88, 0xff, 0x3e, 0xe2, 0xbf, 0x8f, 0xf8, 0xef, 0x23, 0xfe, 0xfb, 0x88,
+ 0xff, 0xe0, 0xe1, 0x0f, 0xa0, 0x2f, 0xe7, 0xfd, 0x89, 0x30, 0xdf, 0x7a,
+ 0x7c, 0x2d, 0xdf, 0x3a, 0xd7, 0xe2, 0x6f, 0x3f, 0x92, 0x96, 0x4a, 0x85,
+ 0x54, 0xbe, 0x4a, 0x82, 0xf3, 0x9b, 0x28, 0x5f, 0xbd, 0xfe, 0x37, 0x0c,
+ 0x05, 0xc7, 0xb9, 0x1a, 0xc3, 0x55, 0x34, 0xe1, 0x30, 0x9c, 0xca, 0xd7,
+ 0xb8, 0x46, 0x5a, 0x0f, 0xc3, 0xdf, 0xc9, 0xd8, 0xb7, 0xa9, 0x6f, 0x34,
+ 0xea, 0x7b, 0xd0, 0xe3, 0x5f, 0xf7, 0x10, 0x8b, 0xcb, 0x4d, 0x19, 0x8f,
+ 0x31, 0x7e, 0x06, 0x63, 0x83, 0xf5, 0x8f, 0xdf, 0xdd, 0xc3, 0x75, 0x41,
+ 0xb9, 0x89, 0xbc, 0x68, 0x39, 0xca, 0x85, 0x00, 0xe7, 0xbf, 0xa9, 0x95,
+ 0xea, 0x2c, 0x67, 0x41, 0xb3, 0x69, 0x30, 0xc5, 0x69, 0xaf, 0x75, 0x5e,
+ 0x96, 0xb5, 0x8e, 0xfa, 0x9b, 0x9e, 0x11, 0xd0, 0x16, 0xdd, 0xfd, 0x12,
+ 0xe9, 0xf3, 0x69, 0xf9, 0x77, 0x00, 0x29, 0x67, 0x58, 0xfe, 0x3d, 0x42,
+ 0x1f, 0xf6, 0x11, 0xf3, 0x3b, 0xdb, 0xee, 0x56, 0xa9, 0xa0, 0x7c, 0x76,
+ 0xa7, 0xfa, 0x3b, 0x08, 0x91, 0x86, 0xed, 0xde, 0xb6, 0x0d, 0x67, 0x83,
+ 0x5c, 0x5f, 0xdd, 0x2a, 0xf3, 0x67, 0xf8, 0xd1, 0x93, 0xc3, 0x7d, 0x03,
+ 0xd4, 0xb3, 0x9d, 0x4e, 0x0d, 0x73, 0xad, 0xb5, 0x19, 0xf8, 0x78, 0xad,
+ 0x9d, 0x2d, 0x88, 0xed, 0x74, 0x7a, 0x11, 0x7e, 0x76, 0xd1, 0x76, 0x59,
+ 0x97, 0x97, 0x86, 0xd3, 0xf0, 0xcf, 0x63, 0x03, 0x1c, 0x9f, 0x97, 0x5b,
+ 0xac, 0x2b, 0x7d, 0x80, 0x1f, 0x84, 0x5e, 0x6e, 0x82, 0x3d, 0x09, 0xec,
+ 0x1f, 0xe1, 0xfe, 0xb9, 0xc4, 0xdd, 0xe7, 0xec, 0xd9, 0x26, 0x75, 0x43,
+ 0xd8, 0xa6, 0x25, 0x40, 0xfb, 0x27, 0x6a, 0x44, 0x97, 0xf8, 0x6c, 0xb3,
+ 0x7e, 0xfb, 0xb7, 0xba, 0x37, 0xb5, 0x72, 0x9d, 0xff, 0x0e, 0x61, 0x98,
+ 0xf6, 0x41, 0xbf, 0x4c, 0xe7, 0x4d, 0xed, 0x81, 0xc6, 0xff, 0x14, 0x6e,
+ 0x75, 0xb1, 0x71, 0x5c, 0x55, 0xf8, 0xdc, 0x59, 0xaf, 0xed, 0x38, 0x6b,
+ 0x67, 0xe2, 0x6c, 0xec, 0xb5, 0x15, 0xc4, 0xce, 0x7a, 0x12, 0x4f, 0xb5,
+ 0x8e, 0x3a, 0xb6, 0x12, 0xb4, 0x42, 0x96, 0x58, 0xed, 0x7a, 0x5d, 0x87,
+ 0x92, 0xb2, 0x85, 0x50, 0x05, 0x09, 0x55, 0x96, 0x9d, 0xd2, 0x54, 0x80,
+ 0x90, 0xfa, 0x80, 0x78, 0xcb, 0x6a, 0x6d, 0x87, 0xa4, 0xec, 0x76, 0x6d,
+ 0x62, 0xd7, 0x2f, 0x3c, 0x2c, 0xeb, 0x75, 0x6a, 0xbb, 0x9b, 0xac, 0x42,
+ 0xfb, 0x50, 0x9e, 0x62, 0x99, 0x92, 0xc2, 0x4b, 0x85, 0xc4, 0x03, 0x02,
+ 0x54, 0xa9, 0x4a, 0xda, 0x34, 0x0f, 0x25, 0x11, 0xbc, 0x50, 0x0a, 0xd2,
+ 0xf0, 0x7d, 0x77, 0x66, 0x1d, 0x27, 0x50, 0x61, 0x69, 0x35, 0x77, 0xee,
+ 0xdc, 0x3b, 0x73, 0x7f, 0xce, 0xf9, 0xce, 0x77, 0xce, 0x3d, 0x66, 0x1b,
+ 0x1b, 0x65, 0xfa, 0xd3, 0xab, 0x6a, 0xa6, 0xda, 0x2b, 0x0b, 0x90, 0xe3,
+ 0xe2, 0x48, 0x38, 0x88, 0x97, 0x76, 0x05, 0xfa, 0x0c, 0xc7, 0xdf, 0xb7,
+ 0x57, 0x9a, 0x57, 0x16, 0xcd, 0x4e, 0xcd, 0xab, 0x1e, 0x7d, 0x76, 0x0a,
+ 0x63, 0x8a, 0x61, 0x1d, 0xba, 0xfb, 0x34, 0x36, 0x19, 0xbc, 0xef, 0x7f,
+ 0xec, 0xbe, 0xef, 0xb1, 0xfb, 0xc3, 0xff, 0xa3, 0x3d, 0xcb, 0x8f, 0xcb,
+ 0x03, 0xc7, 0x69, 0xa5, 0xf8, 0x95, 0x62, 0xc9, 0x36, 0x66, 0x4b, 0x56,
+ 0x9a, 0xbc, 0x20, 0x2b, 0x9e, 0xca, 0xba, 0xed, 0xc0, 0xbb, 0x76, 0x99,
+ 0x5f, 0x86, 0xcc, 0x63, 0x1e, 0x1d, 0x36, 0xcf, 0xb4, 0x13, 0x7d, 0xd4,
+ 0x99, 0x4e, 0x6c, 0x83, 0x61, 0x0f, 0xc5, 0xd0, 0xce, 0x7b, 0xc9, 0x4d,
+ 0x9a, 0xe7, 0x74, 0x1c, 0x86, 0x7c, 0xc6, 0x53, 0x45, 0x9d, 0x9f, 0xc1,
+ 0x36, 0x6d, 0x72, 0xc7, 0xce, 0xf4, 0x06, 0xf9, 0x3e, 0xf0, 0x5b, 0xc7,
+ 0xfa, 0xc8, 0x35, 0x5e, 0x74, 0x77, 0xeb, 0xcc, 0xdb, 0xc2, 0x3c, 0x2a,
+ 0x08, 0xcd, 0xb3, 0x22, 0xd5, 0xba, 0xc8, 0xeb, 0xf8, 0xfd, 0xae, 0x1e,
+ 0xf8, 0x0a, 0x8a, 0x3e, 0xf3, 0xb8, 0x6c, 0x55, 0xbe, 0x2c, 0x0d, 0xd8,
+ 0x9f, 0x4d, 0xd7, 0xf3, 0xee, 0xb9, 0x71, 0xbd, 0xe6, 0x3f, 0x29, 0x29,
+ 0x49, 0x8c, 0xd2, 0xbe, 0xb5, 0xcb, 0x4f, 0x97, 0xdb, 0x64, 0xdb, 0xb4,
+ 0xcc, 0x7b, 0xc2, 0x5c, 0xb6, 0x98, 0x4c, 0x45, 0x43, 0x9a, 0xa3, 0xca,
+ 0xb7, 0xc0, 0xa0, 0xf1, 0xec, 0xee, 0xf2, 0x33, 0x7d, 0x8c, 0x9d, 0x7c,
+ 0xb4, 0xcc, 0x7b, 0x03, 0x57, 0x43, 0x76, 0xec, 0x10, 0xb8, 0x2c, 0x40,
+ 0xc8, 0xe4, 0xba, 0x73, 0xbe, 0xcf, 0x71, 0x6c, 0xa8, 0xa3, 0x2f, 0xda,
+ 0x2e, 0xc5, 0xa3, 0xc0, 0x44, 0x35, 0xa4, 0x73, 0x8a, 0x76, 0xa2, 0x1a,
+ 0xa3, 0x43, 0x35, 0xe6, 0xc8, 0x99, 0xfb, 0x35, 0x5e, 0x67, 0xae, 0x7d,
+ 0x5f, 0xcf, 0x05, 0xe5, 0x42, 0xcd, 0xa5, 0xac, 0x9a, 0xb2, 0x09, 0x5d,
+ 0xdb, 0x68, 0x2e, 0xf5, 0x73, 0xaf, 0xb6, 0x9a, 0x3f, 0xe8, 0xf3, 0x7d,
+ 0x2d, 0xd6, 0xfd, 0xb0, 0xcf, 0xaf, 0x8b, 0x07, 0xbe, 0x13, 0x7d, 0xac,
+ 0x2a, 0xe6, 0xf6, 0xb2, 0x34, 0x57, 0x7f, 0x2c, 0x6f, 0x57, 0x7e, 0x24,
+ 0xbf, 0x5a, 0x3d, 0x0b, 0xfe, 0x61, 0x55, 0x0b, 0xb0, 0x27, 0x37, 0x9a,
+ 0x9e, 0x77, 0xc3, 0x3d, 0x03, 0x5f, 0xc1, 0xf3, 0xfe, 0xe0, 0x6e, 0x4b,
+ 0x62, 0xec, 0x3b, 0x98, 0x73, 0x1e, 0x3a, 0x44, 0x2c, 0x9c, 0x82, 0xbc,
+ 0x25, 0xfb, 0xa5, 0x2b, 0xa2, 0xe5, 0x64, 0x68, 0x2c, 0x8c, 0x39, 0x18,
+ 0x01, 0x27, 0xe7, 0x5c, 0x46, 0xfa, 0x29, 0x33, 0x46, 0xf3, 0x15, 0x7c,
+ 0x3f, 0x0c, 0xbd, 0xd8, 0x8f, 0x9f, 0x92, 0x7b, 0xa3, 0x18, 0xeb, 0x28,
+ 0x65, 0x2f, 0x2c, 0x89, 0x27, 0x31, 0x8f, 0x7c, 0x9b, 0xdc, 0x2f, 0x5d,
+ 0xe9, 0x63, 0x5c, 0xee, 0x7e, 0x89, 0x65, 0xe3, 0x4b, 0x3d, 0xe2, 0x49,
+ 0x1b, 0x6c, 0xf9, 0xfc, 0x09, 0x9f, 0x37, 0xfd, 0x5a, 0x0d, 0xa3, 0xbd,
+ 0x5d, 0x78, 0x47, 0x91, 0xe7, 0x15, 0xbc, 0x30, 0x78, 0x79, 0x0e, 0x7c,
+ 0x28, 0xd3, 0xbc, 0x20, 0x3b, 0xa3, 0x11, 0xb4, 0x21, 0x5f, 0xd1, 0x58,
+ 0x22, 0xd9, 0x12, 0x73, 0xb0, 0x98, 0x0f, 0x85, 0x31, 0x9e, 0x21, 0x6e,
+ 0x70, 0x8c, 0xed, 0x3c, 0xb7, 0x0b, 0xea, 0x6c, 0xc8, 0x08, 0xeb, 0x28,
+ 0xdf, 0x69, 0xcd, 0xa9, 0x60, 0x43, 0xf1, 0xbe, 0x11, 0xc9, 0xe8, 0x72,
+ 0x0f, 0xde, 0x77, 0x41, 0xe7, 0x25, 0xfa, 0xef, 0x4c, 0xa1, 0x0d, 0x71,
+ 0x26, 0x05, 0x2e, 0xf1, 0xa1, 0x9a, 0x00, 0xbd, 0x99, 0x29, 0xf5, 0xc9,
+ 0x84, 0xb9, 0x6f, 0xcf, 0x1c, 0x0b, 0xda, 0x57, 0x30, 0x8c, 0x91, 0x60,
+ 0x4c, 0x3d, 0x7b, 0xc6, 0xc4, 0xfe, 0xf8, 0xc1, 0xc7, 0xcd, 0x2c, 0x2f,
+ 0x02, 0xa7, 0x16, 0x7f, 0x9b, 0x71, 0x9f, 0x97, 0x6c, 0xb4, 0x5d, 0xfb,
+ 0x36, 0x35, 0xec, 0x4b, 0xb6, 0xc4, 0x78, 0xd4, 0xb7, 0x81, 0x43, 0xfb,
+ 0x82, 0x3a, 0xb6, 0x15, 0x23, 0x83, 0xb5, 0x4f, 0x6b, 0x3d, 0x64, 0xdd,
+ 0x17, 0x25, 0xb3, 0x98, 0x97, 0x49, 0xdd, 0x8f, 0x6b, 0x38, 0xa8, 0x79,
+ 0x08, 0x75, 0x35, 0x71, 0x08, 0x6b, 0x99, 0x0c, 0x07, 0x6d, 0xf7, 0x91,
+ 0xc9, 0xe3, 0xef, 0xd3, 0x40, 0x67, 0xf1, 0xec, 0x10, 0xf7, 0xa8, 0x5d,
+ 0x12, 0xdf, 0x84, 0xbd, 0x2c, 0xb5, 0xea, 0x23, 0xf2, 0x49, 0xe9, 0xb3,
+ 0x3e, 0x9e, 0x93, 0xfc, 0xb5, 0x64, 0xca, 0x47, 0x25, 0x7d, 0x7e, 0x3a,
+ 0x1d, 0x12, 0xeb, 0xbc, 0xef, 0x67, 0x1f, 0x9d, 0x9e, 0x57, 0x7c, 0x7e,
+ 0xf4, 0xfc, 0xba, 0xea, 0x44, 0xdb, 0x08, 0xda, 0x71, 0x1c, 0xa6, 0xe4,
+ 0x4a, 0x7f, 0xf7, 0x66, 0x8e, 0x79, 0xde, 0xa4, 0xce, 0xe1, 0x4a, 0x9a,
+ 0xf3, 0xaa, 0xc5, 0xcf, 0x1d, 0x29, 0x45, 0x3b, 0xf0, 0xad, 0xa4, 0xb9,
+ 0xae, 0x8e, 0x62, 0x3c, 0x2c, 0x1f, 0xa2, 0x4e, 0xc4, 0xb6, 0x85, 0xef,
+ 0xb7, 0xa6, 0xd6, 0x54, 0x32, 0x3e, 0xa4, 0xac, 0x74, 0x11, 0xbf, 0x36,
+ 0xa5, 0xcf, 0x1e, 0x63, 0x71, 0x05, 0xdd, 0xc5, 0x9c, 0xec, 0xe3, 0x9e,
+ 0x37, 0x65, 0xb3, 0x3e, 0x69, 0x46, 0x14, 0xe3, 0x26, 0x5d, 0xfa, 0x8c,
+ 0xf2, 0xd2, 0xe1, 0xa4, 0x79, 0x5c, 0x1d, 0x0c, 0xee, 0x53, 0xc0, 0xcc,
+ 0xdd, 0xf7, 0x9d, 0x5d, 0x53, 0xa6, 0x5c, 0x2e, 0x25, 0xe3, 0xb3, 0xca,
+ 0xca, 0xe3, 0x9d, 0xf9, 0x09, 0x45, 0xdc, 0x48, 0x9a, 0x5d, 0x8a, 0xb1,
+ 0xcd, 0x0e, 0x3d, 0xef, 0x29, 0xf4, 0x4f, 0xaa, 0xb6, 0x60, 0x3c, 0xdc,
+ 0xaf, 0xcb, 0xfd, 0xbe, 0xce, 0x10, 0x73, 0x06, 0x8c, 0x99, 0x45, 0xe6,
+ 0x83, 0xe9, 0x3c, 0x84, 0x74, 0x62, 0x8c, 0xf7, 0x86, 0x3c, 0x38, 0xf9,
+ 0x0f, 0xd4, 0xa1, 0x5c, 0x65, 0x9d, 0x13, 0xe8, 0xdb, 0x31, 0xcd, 0x9f,
+ 0x1f, 0x9c, 0x2c, 0xe8, 0xfc, 0xc4, 0x1d, 0x95, 0x08, 0xe6, 0xbd, 0xbb,
+ 0x67, 0xf1, 0x8c, 0xfb, 0x05, 0xbe, 0x67, 0x31, 0x34, 0xde, 0x21, 0xcc,
+ 0x07, 0xcd, 0x55, 0x5a, 0xb2, 0xc1, 0xd8, 0x00, 0xcf, 0xf7, 0x5b, 0x67,
+ 0xe5, 0x17, 0xc4, 0x18, 0xeb, 0xdc, 0x23, 0x27, 0xe0, 0x9d, 0xe0, 0xab,
+ 0x75, 0xbc, 0xa7, 0xb8, 0x2c, 0x05, 0xbf, 0xbf, 0x74, 0x32, 0xff, 0xb4,
+ 0x58, 0xff, 0xbc, 0x77, 0xf8, 0x36, 0x30, 0x87, 0xfb, 0x07, 0x27, 0x29,
+ 0x9f, 0x5c, 0x9b, 0xb8, 0x9a, 0xbc, 0xc2, 0xf1, 0x0c, 0x4a, 0x6e, 0x19,
+ 0xdc, 0x08, 0xbf, 0xf9, 0x65, 0x7f, 0xdf, 0xd6, 0xc1, 0xb3, 0x73, 0x25,
+ 0x53, 0xeb, 0xeb, 0xac, 0xcb, 0xb3, 0x0f, 0xe8, 0x8a, 0xce, 0x7b, 0x62,
+ 0x5f, 0xe6, 0x0a, 0x1e, 0xa1, 0x7d, 0x74, 0x6a, 0x12, 0x45, 0x5b, 0x72,
+ 0x56, 0xd6, 0x83, 0xbf, 0xc3, 0x66, 0x16, 0x5f, 0x8d, 0x08, 0x30, 0x39,
+ 0x15, 0x0f, 0x1d, 0x90, 0x79, 0xd7, 0x95, 0x46, 0xf3, 0x84, 0x5c, 0x6b,
+ 0x3a, 0xfa, 0x19, 0xed, 0xd9, 0xc2, 0x6b, 0xfa, 0x5c, 0x3a, 0xfe, 0xa1,
+ 0xb2, 0x9c, 0xab, 0xf0, 0x6b, 0xbe, 0x7b, 0x8c, 0x79, 0xc2, 0xe1, 0x81,
+ 0x87, 0x79, 0x70, 0xc0, 0x0e, 0x70, 0x8e, 0xb7, 0xc0, 0x39, 0xde, 0x04,
+ 0xe7, 0xf8, 0x25, 0x38, 0xf6, 0x8d, 0xca, 0x54, 0x80, 0xff, 0xd3, 0xc0,
+ 0x21, 0xda, 0x6a, 0xeb, 0x2c, 0xf6, 0x74, 0xba, 0x00, 0x19, 0xfc, 0x00,
+ 0xfe, 0xc7, 0x56, 0x25, 0x23, 0x1b, 0xab, 0x93, 0xb2, 0xb9, 0xea, 0xe7,
+ 0x1c, 0xbf, 0xcb, 0x3c, 0xad, 0x51, 0xee, 0x93, 0x03, 0x1c, 0xda, 0x27,
+ 0x89, 0xe3, 0xc4, 0x8f, 0x4e, 0x59, 0x2b, 0xaf, 0x69, 0x1c, 0x5a, 0x2b,
+ 0xb3, 0x1c, 0x12, 0x9d, 0xf3, 0x75, 0x66, 0x5b, 0x6a, 0xee, 0x16, 0xea,
+ 0xbb, 0x99, 0xdb, 0x15, 0xc4, 0xd6, 0x89, 0x97, 0x7f, 0x0e, 0xf6, 0x5e,
+ 0xe9, 0x5c, 0xb8, 0x19, 0xf3, 0x00, 0xda, 0xb5, 0xb0, 0x6b, 0xc8, 0x3f,
+ 0x27, 0x57, 0x7f, 0x41, 0x1b, 0x7c, 0x03, 0x9c, 0xf1, 0x2a, 0x6c, 0xc8,
+ 0x8e, 0x73, 0x40, 0x73, 0xbf, 0x1d, 0xe7, 0x88, 0xce, 0xad, 0xe5, 0x7b,
+ 0x8a, 0x65, 0x5b, 0xe6, 0xca, 0x56, 0xbc, 0x00, 0xf9, 0xbb, 0x06, 0xbf,
+ 0x6d, 0x03, 0x7b, 0xb0, 0x89, 0xb5, 0xd8, 0x6a, 0xd2, 0xce, 0xbf, 0xaf,
+ 0xb1, 0x77, 0xad, 0xf9, 0x27, 0xbc, 0xc7, 0x3a, 0x9b, 0x96, 0x3f, 0xf6,
+ 0x13, 0x03, 0x99, 0x8f, 0x97, 0xd5, 0xfd, 0xfd, 0x7e, 0x1b, 0x68, 0xbb,
+ 0xd9, 0x24, 0x1e, 0x8b, 0x5c, 0x2c, 0xd9, 0xb0, 0x25, 0x17, 0x63, 0xe4,
+ 0x00, 0x55, 0xd5, 0xea, 0xe7, 0x05, 0x63, 0xf6, 0xbc, 0xfd, 0x36, 0xc7,
+ 0xe5, 0x04, 0xb8, 0x4d, 0xdb, 0xbf, 0xad, 0xb9, 0x4d, 0xa9, 0xf2, 0xbc,
+ 0x5c, 0x5f, 0x4d, 0x05, 0x1c, 0x27, 0x2f, 0x6f, 0x80, 0xe3, 0x35, 0x2b,
+ 0xad, 0x1c, 0xed, 0x71, 0xac, 0x53, 0x45, 0xcd, 0x2d, 0x75, 0xc9, 0xa5,
+ 0x95, 0xa2, 0xba, 0xbc, 0x52, 0x52, 0xaf, 0x2c, 0x95, 0x55, 0x71, 0xc9,
+ 0xf3, 0xfe, 0xe9, 0xce, 0xc8, 0xdb, 0xab, 0x9e, 0x9c, 0x76, 0x8d, 0x81,
+ 0x90, 0xb4, 0xf2, 0xdf, 0x3c, 0xaf, 0x13, 0xd8, 0xbc, 0x75, 0xd8, 0xf3,
+ 0x9e, 0x18, 0x1d, 0x15, 0xe7, 0x30, 0x39, 0xca, 0x70, 0x8c, 0x39, 0xac,
+ 0xc4, 0x9c, 0x8c, 0x6d, 0x9f, 0xaf, 0x29, 0x05, 0x7c, 0x3b, 0xe0, 0xf3,
+ 0x97, 0x27, 0xbb, 0x83, 0x33, 0x8f, 0xb3, 0x2f, 0x31, 0x26, 0x1c, 0xfb,
+ 0xaf, 0x98, 0xb0, 0x29, 0xe7, 0xca, 0x58, 0x88, 0xae, 0xa8, 0x7c, 0xaf,
+ 0x1c, 0x79, 0xac, 0x6c, 0xe2, 0xea, 0x18, 0xc5, 0xf2, 0x7d, 0x6f, 0x48,
+ 0xc7, 0xfe, 0xc1, 0x49, 0x4c, 0xcf, 0x9b, 0x75, 0xf9, 0xbd, 0x03, 0x8c,
+ 0xc9, 0x98, 0xdd, 0xb0, 0xff, 0xa7, 0xb5, 0x7d, 0xae, 0xaa, 0x8c, 0x4d,
+ 0xfd, 0x8e, 0xca, 0x44, 0x19, 0x36, 0x5e, 0x31, 0x2f, 0x94, 0x5c, 0xc1,
+ 0x8a, 0xcd, 0x02, 0x3b, 0x66, 0x80, 0x37, 0x4f, 0xeb, 0xb3, 0xd1, 0x43,
+ 0x1a, 0x7b, 0xe6, 0x58, 0xce, 0x4b, 0xba, 0xe6, 0xf6, 0xea, 0xf5, 0xbb,
+ 0x7d, 0xad, 0x18, 0xf3, 0xf7, 0x1c, 0x7a, 0x9c, 0xe7, 0xf9, 0x40, 0xaf,
+ 0x64, 0xd7, 0xcf, 0x40, 0x27, 0x62, 0x58, 0xdb, 0xb0, 0xd6, 0x87, 0x1d,
+ 0xd8, 0xef, 0x1d, 0x27, 0x1c, 0x60, 0x6a, 0x27, 0xee, 0xd9, 0x6e, 0x12,
+ 0xfd, 0x3a, 0x24, 0xb3, 0xd4, 0xae, 0x71, 0xf5, 0xd1, 0xba, 0x34, 0x78,
+ 0x48, 0x0e, 0xe5, 0x10, 0xea, 0xe2, 0x41, 0x99, 0xdc, 0x6b, 0x1a, 0xe5,
+ 0x36, 0x5c, 0xd9, 0xe6, 0x28, 0x78, 0x05, 0xae, 0xbf, 0xc0, 0xfb, 0x46,
+ 0x31, 0xe6, 0xbc, 0x29, 0xef, 0x9d, 0xa4, 0x2d, 0x71, 0x0c, 0xe6, 0x1a,
+ 0xcf, 0xda, 0xb8, 0x36, 0xca, 0x2a, 0xbb, 0xc8, 0x32, 0xae, 0x55, 0xff,
+ 0xf9, 0x23, 0x98, 0x84, 0x3e, 0x99, 0x15, 0x1f, 0x93, 0xde, 0xdb, 0xc5,
+ 0x24, 0xd6, 0x75, 0xc8, 0xc4, 0x52, 0x5c, 0x9d, 0xba, 0x62, 0x42, 0xde,
+ 0xba, 0x24, 0xbb, 0x12, 0xd5, 0x7c, 0xb4, 0x06, 0x59, 0x5c, 0x87, 0x5c,
+ 0xad, 0x41, 0xa6, 0x32, 0x65, 0x2b, 0x35, 0xad, 0xe2, 0x3a, 0x2e, 0x30,
+ 0x05, 0x79, 0x0d, 0xbf, 0x4a, 0x2e, 0x4a, 0xfd, 0x75, 0xd0, 0x46, 0x68,
+ 0x47, 0xd3, 0x61, 0x65, 0x43, 0x0e, 0x21, 0x97, 0x65, 0x5f, 0x7f, 0xdf,
+ 0x51, 0x1a, 0x57, 0x53, 0x77, 0x24, 0xe9, 0xdc, 0x11, 0xcb, 0xdd, 0xc1,
+ 0xef, 0x37, 0xe2, 0xca, 0x55, 0xe8, 0xfb, 0xeb, 0xf8, 0x4e, 0xf8, 0x35,
+ 0x43, 0x8e, 0x0d, 0x6b, 0x9d, 0x4e, 0x49, 0xc8, 0x72, 0x36, 0xc5, 0xd7,
+ 0xf1, 0x75, 0xad, 0xe3, 0x90, 0x37, 0x60, 0x90, 0xaf, 0xd3, 0xe9, 0x40,
+ 0x46, 0xbf, 0x01, 0xfd, 0xb5, 0xe0, 0x95, 0xc5, 0x65, 0x1e, 0xfa, 0x7f,
+ 0x15, 0xcf, 0x6f, 0x36, 0x3f, 0x56, 0x73, 0x8b, 0x2a, 0xc8, 0x3f, 0x79,
+ 0x0e, 0x3c, 0xf9, 0xf7, 0x58, 0xbb, 0x1e, 0xcd, 0xdd, 0x13, 0xa3, 0x3c,
+ 0x07, 0xfb, 0xb7, 0xba, 0x64, 0x1f, 0x97, 0xdb, 0x23, 0x27, 0x50, 0xee,
+ 0xc6, 0xd5, 0xc0, 0x3a, 0x44, 0xf4, 0xf9, 0xf5, 0x5a, 0x69, 0xc4, 0x28,
+ 0xea, 0x33, 0xe6, 0x31, 0xf4, 0x25, 0x96, 0x1d, 0xc6, 0x73, 0xc6, 0x65,
+ 0x38, 0x37, 0x70, 0x26, 0x15, 0xd3, 0x39, 0xa1, 0x35, 0x70, 0x89, 0x75,
+ 0xbc, 0xef, 0x16, 0xe3, 0x7a, 0x0d, 0xe8, 0xf0, 0xc8, 0x67, 0x5e, 0x3a,
+ 0xca, 0xbc, 0xf3, 0xf7, 0x63, 0xbe, 0xfd, 0xfb, 0xc4, 0xbb, 0x6d, 0xcf,
+ 0xa5, 0x0c, 0xdc, 0x7c, 0x60, 0x02, 0xef, 0xc8, 0xdb, 0x61, 0x8b, 0xaa,
+ 0x5a, 0x7e, 0xd9, 0xce, 0xef, 0x5b, 0x6c, 0x24, 0xcd, 0x77, 0xc5, 0xef,
+ 0x3b, 0x6f, 0xd3, 0xee, 0x74, 0x00, 0x5f, 0xe2, 0x9a, 0x57, 0xde, 0xb2,
+ 0x0b, 0x40, 0x05, 0x2b, 0x3e, 0x05, 0x19, 0x6d, 0x17, 0xcb, 0xc9, 0xc9,
+ 0xc3, 0xef, 0xce, 0xea, 0xbe, 0x6c, 0xdb, 0xea, 0xdb, 0xfa, 0x2e, 0xc7,
+ 0xcf, 0xb9, 0x70, 0x0e, 0xf0, 0x6d, 0x4c, 0x53, 0xcb, 0xe8, 0x4e, 0xc3,
+ 0x18, 0xf0, 0x65, 0xb4, 0x35, 0x8f, 0xe8, 0xff, 0x99, 0x07, 0xe5, 0x64,
+ 0xc4, 0xf0, 0xcf, 0xdb, 0x71, 0x6d, 0x70, 0x3d, 0x3f, 0x06, 0xbf, 0xdf,
+ 0x2b, 0x3f, 0xad, 0x38, 0xa3, 0x2f, 0x3f, 0x4f, 0xec, 0xca, 0x0f, 0x7d,
+ 0xd4, 0x2e, 0xc9, 0xad, 0xd8, 0x32, 0x59, 0xd6, 0xfb, 0x0d, 0xae, 0xc9,
+ 0xf8, 0xd1, 0x09, 0xc8, 0x0d, 0x65, 0x9d, 0xba, 0x65, 0x4a, 0x15, 0x72,
+ 0x54, 0x05, 0x3e, 0x55, 0x21, 0x53, 0xe4, 0x40, 0x55, 0xe0, 0x5b, 0xb5,
+ 0x69, 0x39, 0x75, 0xcc, 0x99, 0x36, 0x7b, 0x1d, 0x72, 0x74, 0xb5, 0xc9,
+ 0xfd, 0xd7, 0x63, 0x36, 0x69, 0x07, 0x6f, 0xee, 0xee, 0xfd, 0xa7, 0xd8,
+ 0xfb, 0x23, 0x72, 0x0d, 0x7e, 0xcb, 0xf5, 0xca, 0x08, 0x30, 0x49, 0x80,
+ 0x51, 0x2e, 0x64, 0x23, 0x25, 0x1b, 0x95, 0x71, 0xd9, 0x84, 0x7d, 0xda,
+ 0x5a, 0x4d, 0x80, 0x4f, 0x03, 0x47, 0xaf, 0x1c, 0x93, 0x37, 0x56, 0x95,
+ 0xcc, 0xd8, 0xb0, 0x33, 0x6b, 0x8c, 0xc1, 0x43, 0x9e, 0xab, 0x5d, 0xfa,
+ 0xbc, 0x7d, 0xa2, 0xee, 0xc7, 0xe2, 0x73, 0xf5, 0x1e, 0x99, 0xac, 0x9b,
+ 0xf2, 0x54, 0xbd, 0x57, 0xbe, 0x5a, 0x8f, 0xca, 0xe9, 0x46, 0x4c, 0xbe,
+ 0x56, 0x1f, 0x94, 0xa7, 0xeb, 0x47, 0xe4, 0x99, 0x46, 0x5c, 0xbe, 0x0e,
+ 0xbf, 0x30, 0xdf, 0x70, 0x64, 0xaa, 0x31, 0x22, 0xa7, 0x1a, 0x8c, 0xb1,
+ 0xe3, 0x7b, 0xf8, 0x65, 0x77, 0x63, 0x17, 0x1c, 0x57, 0x27, 0xc6, 0xe5,
+ 0xa8, 0x9c, 0x3e, 0x6f, 0x94, 0xbc, 0x1f, 0xff, 0x10, 0x79, 0x01, 0x7d,
+ 0x17, 0xae, 0x28, 0xa9, 0xe9, 0xef, 0xb7, 0xfe, 0x47, 0x24, 0xa2, 0x7d,
+ 0xa3, 0x17, 0xaa, 0x83, 0x68, 0x63, 0xd3, 0x27, 0x09, 0xe2, 0x20, 0xad,
+ 0xf8, 0x7f, 0xcb, 0xf7, 0x32, 0x74, 0x0c, 0xfb, 0x26, 0x7d, 0x2f, 0xbd,
+ 0xf6, 0xc4, 0x0f, 0xfa, 0x39, 0xf4, 0xb5, 0xf6, 0x9e, 0x51, 0xb4, 0xbe,
+ 0xbb, 0x90, 0x7f, 0xf4, 0x7f, 0x51, 0xfc, 0xb3, 0xa6, 0x73, 0x8d, 0x41,
+ 0xfe, 0x4f, 0x0a, 0xc6, 0xf2, 0xf9, 0xf9, 0xdd, 0x93, 0x95, 0x09, 0xf5,
+ 0x54, 0x85, 0x8c, 0xc6, 0x93, 0x85, 0xdd, 0x3c, 0xba, 0xaf, 0xc8, 0x9a,
+ 0x1b, 0xd1, 0x63, 0xf0, 0xe3, 0xf6, 0x69, 0x9d, 0x53, 0x37, 0x31, 0x4c,
+ 0xf9, 0xe3, 0x19, 0x5a, 0x4f, 0x70, 0xb6, 0x00, 0x6e, 0xeb, 0x9a, 0x72,
+ 0xb1, 0xee, 0xc7, 0xaf, 0xe6, 0xb4, 0xbc, 0x5c, 0x87, 0xcc, 0xf1, 0xfc,
+ 0xc1, 0xbf, 0x16, 0xaa, 0x7e, 0xdf, 0xec, 0xb0, 0x43, 0x7f, 0x1c, 0xf3,
+ 0x35, 0x7a, 0xf9, 0x2d, 0xfe, 0x4f, 0x0e, 0xca, 0xc1, 0x78, 0x99, 0x0f,
+ 0x6c, 0x6b, 0x59, 0xf4, 0xcf, 0x67, 0x1d, 0x79, 0x11, 0x7b, 0x51, 0x33,
+ 0x39, 0xfe, 0x4e, 0xa9, 0x39, 0xf4, 0x6d, 0x89, 0xdf, 0xc3, 0x52, 0xc5,
+ 0x77, 0x6a, 0x4e, 0x2b, 0x36, 0xe6, 0xe3, 0x6c, 0xcd, 0x7c, 0xf8, 0xdd,
+ 0xe9, 0xea, 0x41, 0xdc, 0xa3, 0xce, 0x01, 0x67, 0x3a, 0xc3, 0xfb, 0x05,
+ 0x94, 0x19, 0x1b, 0x99, 0xc3, 0x35, 0x16, 0xd4, 0xfd, 0x7c, 0x40, 0x73,
+ 0xf5, 0xf1, 0x87, 0xfd, 0x66, 0xaa, 0x56, 0x21, 0x13, 0xba, 0xab, 0x8c,
+ 0x9f, 0xad, 0x0f, 0x10, 0x73, 0x0f, 0xda, 0xfc, 0x45, 0xe4, 0x6f, 0xa6,
+ 0x8e, 0x29, 0x04, 0xcf, 0xf6, 0xc9, 0xb3, 0x26, 0x73, 0xcd, 0xd3, 0x6a,
+ 0xa2, 0xf2, 0x72, 0x90, 0x57, 0x7b, 0x57, 0x1d, 0xac, 0x35, 0x07, 0xfc,
+ 0xbc, 0x74, 0xbe, 0x7b, 0x6f, 0x2e, 0xfa, 0x5e, 0x39, 0x61, 0x4e, 0x7a,
+ 0x07, 0x78, 0xab, 0x36, 0x62, 0xd0, 0x41, 0xe0, 0x9d, 0xdd, 0xa6, 0xf5,
+ 0xb1, 0xd8, 0xf8, 0x97, 0xb7, 0xad, 0xf5, 0xb9, 0x15, 0x63, 0xb8, 0x35,
+ 0x40, 0xdf, 0x96, 0xb8, 0x71, 0xd1, 0x8f, 0x1b, 0x69, 0x1f, 0x1a, 0x58,
+ 0x81, 0x3a, 0xea, 0x2a, 0xf4, 0x64, 0xb7, 0x2d, 0xff, 0xfe, 0x03, 0x7d,
+ 0xe7, 0x95, 0xf0, 0x2c, 0x67, 0x00, 0x00, 0x00 };
static u32 bnx2_RXP_b06FwData[(0x0/4) + 1] = { 0x0 };
-static u32 bnx2_RXP_b06FwRodata[(0x28/4) + 1] = {
- 0x0800468c, 0x0800458c, 0x08004630, 0x08004648, 0x08004660, 0x08004680,
- 0x0800468c, 0x0800468c, 0x08004594, 0x00000000, 0x00000000 };
-static u32 bnx2_RXP_b06FwBss[(0x13a4/4) + 1] = { 0x0 };
-static u32 bnx2_RXP_b06FwSbss[(0x1c/4) + 1] = { 0x0 };
+static u32 bnx2_RXP_b06FwRodata[(0x278/4) + 1] = {
+ 0x08003fdc, 0x08003edc, 0x08003f80, 0x08003f98, 0x08003fb0, 0x08003fd0,
+ 0x08003fdc, 0x08003fdc, 0x08003ee4, 0x00000000, 0x08004a04, 0x08004a3c,
+ 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004a74, 0x08004c38,
+ 0x08004b80, 0x08004bb8, 0x08004c38, 0x08004b08, 0x08004c38, 0x08004c38,
+ 0x08004bb8, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38,
+ 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004bf8,
+ 0x08004c38, 0x08004bf8, 0x08004b80, 0x08004c38, 0x08004c38, 0x08004bf8,
+ 0x08004bf8, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38,
+ 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38,
+ 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38,
+ 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38,
+ 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38,
+ 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38,
+ 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38,
+ 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38,
+ 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38,
+ 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38,
+ 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38,
+ 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38,
+ 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38,
+ 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38,
+ 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38,
+ 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38,
+ 0x08004ae4, 0x00000000, 0x08006018, 0x08006030, 0x08006030, 0x08006030,
+ 0x08006018, 0x08006030, 0x08006030, 0x08006030, 0x08006018, 0x08006030,
+ 0x08006030, 0x08006030, 0x08006018, 0x08006030, 0x08006030, 0x08006030,
+ 0x08006024, 0x00000000, 0x00000000 };
+
+static u32 bnx2_RXP_b06FwBss[(0x13dc/4) + 1] = { 0x0 };
+static u32 bnx2_RXP_b06FwSbss[(0x2c/4) + 1] = { 0x0 };
+
+static struct fw_info bnx2_rxp_fw_06 = {
+ .ver_major = 0x2,
+ .ver_minor = 0x8,
+ .ver_fix = 0x17,
+
+ .start_addr = 0x08003184,
+
+ .text_addr = 0x08000000,
+ .text_len = 0x6728,
+ .text_index = 0x0,
+ .gz_text = bnx2_RXP_b06FwText,
+ .gz_text_len = sizeof(bnx2_RXP_b06FwText),
+
+ .data_addr = 0x080069c0,
+ .data_len = 0x0,
+ .data_index = 0x0,
+ .data = bnx2_RXP_b06FwData,
+
+ .sbss_addr = 0x080069c0,
+ .sbss_len = 0x2c,
+ .sbss_index = 0x0,
+ .sbss = bnx2_RXP_b06FwSbss,
+
+ .bss_addr = 0x080069f0,
+ .bss_len = 0x13dc,
+ .bss_index = 0x0,
+ .bss = bnx2_RXP_b06FwBss,
+
+ .rodata_addr = 0x08006728,
+ .rodata_len = 0x278,
+ .rodata_index = 0x0,
+ .rodata = bnx2_RXP_b06FwRodata,
+};
static u8 bnx2_rv2p_proc1[] = {
0x1f, 0x8b, 0x08, 0x08, 0x5e, 0xd0, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
@@ -1316,20 +1665,6 @@ static u8 bnx2_rv2p_proc2[] = {
0x63, 0xd6, 0x11, 0x8f, 0x47, 0xd5, 0x5f, 0x3f, 0x97, 0x8f, 0x31, 0xd8,
0x17, 0x00, 0x00, 0x00 };
-static const int bnx2_TPAT_b06FwReleaseMajor = 0x1;
-static const int bnx2_TPAT_b06FwReleaseMinor = 0x0;
-static const int bnx2_TPAT_b06FwReleaseFix = 0x0;
-static const u32 bnx2_TPAT_b06FwStartAddr = 0x08000860;
-static const u32 bnx2_TPAT_b06FwTextAddr = 0x08000800;
-static const int bnx2_TPAT_b06FwTextLen = 0x122c;
-static const u32 bnx2_TPAT_b06FwDataAddr = 0x08001a60;
-static const int bnx2_TPAT_b06FwDataLen = 0x0;
-static const u32 bnx2_TPAT_b06FwRodataAddr = 0x00000000;
-static const int bnx2_TPAT_b06FwRodataLen = 0x0;
-static const u32 bnx2_TPAT_b06FwBssAddr = 0x08001aa0;
-static const int bnx2_TPAT_b06FwBssLen = 0x250;
-static const u32 bnx2_TPAT_b06FwSbssAddr = 0x08001a60;
-static const int bnx2_TPAT_b06FwSbssLen = 0x34;
static u8 bnx2_TPAT_b06FwText[] = {
0x1f, 0x8b, 0x08, 0x08, 0x47, 0xd2, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xc5, 0x57, 0x4d, 0x68,
@@ -1529,20 +1864,40 @@ static u32 bnx2_TPAT_b06FwRodata[(0x0/4) + 1] = { 0x0 };
static u32 bnx2_TPAT_b06FwBss[(0x250/4) + 1] = { 0x0 };
static u32 bnx2_TPAT_b06FwSbss[(0x34/4) + 1] = { 0x0 };
-static const int bnx2_TXP_b06FwReleaseMajor = 0x1;
-static const int bnx2_TXP_b06FwReleaseMinor = 0x0;
-static const int bnx2_TXP_b06FwReleaseFix = 0x0;
-static const u32 bnx2_TXP_b06FwStartAddr = 0x080034b0;
-static const u32 bnx2_TXP_b06FwTextAddr = 0x08000000;
-static const int bnx2_TXP_b06FwTextLen = 0x5748;
-static const u32 bnx2_TXP_b06FwDataAddr = 0x08005760;
-static const int bnx2_TXP_b06FwDataLen = 0x0;
-static const u32 bnx2_TXP_b06FwRodataAddr = 0x00000000;
-static const int bnx2_TXP_b06FwRodataLen = 0x0;
-static const u32 bnx2_TXP_b06FwBssAddr = 0x080057a0;
-static const int bnx2_TXP_b06FwBssLen = 0x1c4;
-static const u32 bnx2_TXP_b06FwSbssAddr = 0x08005760;
-static const int bnx2_TXP_b06FwSbssLen = 0x38;
+static struct fw_info bnx2_tpat_fw_06 = {
+ .ver_major = 0x1,
+ .ver_minor = 0x0,
+ .ver_fix = 0x0,
+
+ .start_addr = 0x08000860,
+
+ .text_addr = 0x08000800,
+ .text_len = 0x122c,
+ .text_index = 0x0,
+ .gz_text = bnx2_TPAT_b06FwText,
+ .gz_text_len = sizeof(bnx2_TPAT_b06FwText),
+
+ .data_addr = 0x08001a60,
+ .data_len = 0x0,
+ .data_index = 0x0,
+ .data = bnx2_TPAT_b06FwData,
+
+ .sbss_addr = 0x08001a60,
+ .sbss_len = 0x34,
+ .sbss_index = 0x0,
+ .sbss = bnx2_TPAT_b06FwSbss,
+
+ .bss_addr = 0x08001aa0,
+ .bss_len = 0x250,
+ .bss_index = 0x0,
+ .bss = bnx2_TPAT_b06FwBss,
+
+ .rodata_addr = 0x00000000,
+ .rodata_len = 0x0,
+ .rodata_index = 0x0,
+ .rodata = bnx2_TPAT_b06FwRodata,
+};
+
static u8 bnx2_TXP_b06FwText[] = {
0x1f, 0x8b, 0x08, 0x08, 0x21, 0xd3, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xed, 0x5c, 0x6d, 0x6c,
@@ -1964,3 +2319,38 @@ static u32 bnx2_TXP_b06FwData[(0x0/4) + 1] = { 0x0 };
static u32 bnx2_TXP_b06FwRodata[(0x0/4) + 1] = { 0x0 };
static u32 bnx2_TXP_b06FwBss[(0x1c4/4) + 1] = { 0x0 };
static u32 bnx2_TXP_b06FwSbss[(0x38/4) + 1] = { 0x0 };
+
+static struct fw_info bnx2_txp_fw_06 = {
+ .ver_major = 0x1,
+ .ver_minor = 0x0,
+ .ver_fix = 0x0,
+
+ .start_addr = 0x080034b0,
+
+ .text_addr = 0x08000000,
+ .text_len = 0x5748,
+ .text_index = 0x0,
+ .gz_text = bnx2_TXP_b06FwText,
+ .gz_text_len = sizeof(bnx2_TXP_b06FwText),
+
+ .data_addr = 0x08005760,
+ .data_len = 0x0,
+ .data_index = 0x0,
+ .data = bnx2_TXP_b06FwData,
+
+ .sbss_addr = 0x08005760,
+ .sbss_len = 0x38,
+ .sbss_index = 0x0,
+ .sbss = bnx2_TXP_b06FwSbss,
+
+ .bss_addr = 0x080057a0,
+ .bss_len = 0x1c4,
+ .bss_index = 0x0,
+ .bss = bnx2_TXP_b06FwBss,
+
+ .rodata_addr = 0x00000000,
+ .rodata_len = 0x0,
+ .rodata_index = 0x0,
+ .rodata = bnx2_TXP_b06FwRodata,
+};
+
diff --git a/drivers/net/bnx2_fw2.h b/drivers/net/bnx2_fw2.h
new file mode 100644
index 000000000000..680c769a3fc0
--- /dev/null
+++ b/drivers/net/bnx2_fw2.h
@@ -0,0 +1,4086 @@
+/* bnx2_fw2.h: Broadcom NX2 network driver.
+ *
+ * Copyright (c) 2006 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, except as noted below.
+ *
+ * This file contains firmware data derived from proprietary unpublished
+ * source code, Copyright (c) 2006 Broadcom Corporation.
+ *
+ * Permission is hereby granted for the distribution of this firmware data
+ * in hexadecimal or equivalent format, provided this copyright notice is
+ * accompanying it.
+ */
+
+static u8 bnx2_COM_b09FwText[] = {
+ 0x1f, 0x8b, 0x08, 0x08, 0xac, 0xfb, 0x2f, 0x45, 0x00, 0x03, 0x74, 0x65,
+ 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xdc, 0x5b, 0x6b, 0x70,
+ 0x1b, 0xd7, 0x75, 0x3e, 0xfb, 0x00, 0x09, 0x91, 0x10, 0xb5, 0xa4, 0x60,
+ 0x1a, 0x96, 0x68, 0x07, 0x20, 0x57, 0x22, 0x6a, 0xb1, 0x29, 0x4c, 0x33,
+ 0x16, 0x9b, 0xc2, 0x12, 0x02, 0x50, 0xae, 0x26, 0xc3, 0x3a, 0x94, 0xcd,
+ 0xd8, 0x4a, 0xaa, 0xc9, 0x30, 0x00, 0xa5, 0xf4, 0x61, 0xb7, 0x92, 0xab,
+ 0xa9, 0x5d, 0xd7, 0xaa, 0x21, 0x92, 0x6a, 0xf5, 0x83, 0xe5, 0x2a, 0x16,
+ 0x43, 0xa9, 0xd3, 0x74, 0xc2, 0x12, 0x56, 0xac, 0x4e, 0x31, 0x85, 0xfc,
+ 0xd6, 0x38, 0xb1, 0xc9, 0x4a, 0x76, 0xeb, 0xf4, 0xe1, 0xa6, 0x33, 0xcd,
+ 0xa3, 0x9d, 0x36, 0xf6, 0xa8, 0x3f, 0xea, 0xe9, 0xd3, 0x33, 0x6e, 0xa7,
+ 0xea, 0xd8, 0x0e, 0xfa, 0x7d, 0x77, 0x77, 0x81, 0x25, 0x48, 0xbd, 0xfc,
+ 0xc8, 0x8f, 0x70, 0x06, 0xb3, 0x7b, 0xef, 0xde, 0xbd, 0xf7, 0xdc, 0xf3,
+ 0xf8, 0xce, 0x63, 0x2f, 0xfb, 0x44, 0x5a, 0xc4, 0xfb, 0x5b, 0x8b, 0x5f,
+ 0xfc, 0xfe, 0x5f, 0x2d, 0x7c, 0x7c, 0xf0, 0xe3, 0xfd, 0x22, 0xb7, 0xdc,
+ 0xa2, 0xb7, 0x86, 0x75, 0xf6, 0x1b, 0xf8, 0x45, 0xf1, 0xeb, 0xf7, 0xee,
+ 0x57, 0xfb, 0xb3, 0xf0, 0x7b, 0x13, 0x0f, 0xc7, 0xfe, 0x55, 0x44, 0xbb,
+ 0xc4, 0x98, 0xe0, 0x5f, 0xb5, 0x7a, 0xf9, 0xe7, 0x5c, 0x38, 0x7e, 0x89,
+ 0x67, 0x86, 0xbb, 0x9c, 0xa2, 0x97, 0x3f, 0x09, 0xeb, 0x69, 0x39, 0x94,
+ 0xb5, 0x25, 0x6c, 0xa4, 0xdf, 0x3c, 0x54, 0xb0, 0x45, 0x32, 0xe5, 0x2d,
+ 0xf1, 0x9c, 0xbc, 0x57, 0x2d, 0x46, 0x4d, 0x61, 0xff, 0x8d, 0xe9, 0x77,
+ 0xbf, 0xf6, 0xe2, 0xd6, 0xc4, 0x5b, 0xf3, 0x86, 0x84, 0xad, 0xf4, 0x19,
+ 0xb1, 0x36, 0x4b, 0xb8, 0x0b, 0xef, 0x7c, 0xb5, 0xf7, 0x3d, 0x91, 0x36,
+ 0x7f, 0xae, 0x37, 0xab, 0x2f, 0xf6, 0x4a, 0x71, 0x43, 0x3a, 0x2c, 0x7a,
+ 0x7a, 0xd3, 0xf7, 0xb3, 0x86, 0x35, 0x66, 0xa4, 0x2d, 0x59, 0xac, 0xc8,
+ 0xc8, 0xde, 0x69, 0x09, 0x87, 0xd3, 0x47, 0x9b, 0x9b, 0x37, 0x49, 0xd8,
+ 0x4c, 0x8f, 0x1d, 0xfa, 0x6d, 0xfb, 0xd1, 0xaa, 0x6e, 0xdb, 0xc9, 0x05,
+ 0x89, 0x0c, 0x9e, 0x1a, 0xc0, 0xf3, 0x72, 0x22, 0x29, 0xb2, 0x55, 0x74,
+ 0xbb, 0x18, 0x31, 0xec, 0xb0, 0x64, 0x2b, 0xb6, 0xe4, 0x2a, 0x22, 0x7f,
+ 0x5e, 0xd6, 0xe4, 0x94, 0xdd, 0x29, 0x0b, 0x7d, 0xef, 0x56, 0x33, 0xa0,
+ 0xe5, 0xcf, 0xec, 0xb1, 0x43, 0x53, 0x36, 0xe9, 0x9d, 0x6d, 0x76, 0xe9,
+ 0x9d, 0x6a, 0x2a, 0xd8, 0xa6, 0x4c, 0x94, 0xd9, 0x37, 0xa2, 0xb3, 0x2f,
+ 0x94, 0x7e, 0x68, 0xcd, 0x29, 0x3b, 0xe2, 0xf5, 0xed, 0xdc, 0x9e, 0xc5,
+ 0x7c, 0x93, 0x65, 0x8e, 0x3d, 0x93, 0x2a, 0xd8, 0x51, 0xaf, 0x3f, 0x79,
+ 0x5b, 0xd6, 0x8e, 0xa1, 0xbf, 0xcb, 0x7b, 0x76, 0xf2, 0xbe, 0x82, 0x6d,
+ 0x7b, 0xcf, 0xbe, 0x8a, 0xb9, 0x93, 0x5e, 0xff, 0x7d, 0xdb, 0x0a, 0x76,
+ 0x9f, 0xd7, 0x3f, 0xbd, 0x2d, 0x6b, 0xa7, 0xbc, 0xfe, 0xe4, 0xee, 0x82,
+ 0x3d, 0xe0, 0xf5, 0x9f, 0xbd, 0x3d, 0x6b, 0x0f, 0x7a, 0xfd, 0x0f, 0x6d,
+ 0x2d, 0xd8, 0x69, 0xf4, 0x1f, 0x6d, 0xd6, 0x37, 0x59, 0x72, 0xa4, 0x1c,
+ 0xc7, 0x2f, 0x83, 0x67, 0x43, 0xe8, 0xdb, 0x89, 0xdf, 0x30, 0x7e, 0xbf,
+ 0xb8, 0x4e, 0xda, 0x46, 0x70, 0xfd, 0xc6, 0x46, 0x97, 0x77, 0xe0, 0x91,
+ 0x13, 0x96, 0x37, 0x8c, 0x98, 0xbc, 0xd8, 0xfb, 0x06, 0x78, 0x68, 0xc9,
+ 0x99, 0x8a, 0x68, 0x23, 0xbd, 0x31, 0xf0, 0x2e, 0x2a, 0x4f, 0x56, 0x5a,
+ 0xc5, 0x78, 0xcc, 0x00, 0x6f, 0x3e, 0x2f, 0xf9, 0x68, 0x58, 0xda, 0xe7,
+ 0x34, 0xe9, 0xee, 0x0f, 0x4b, 0xc6, 0x52, 0x72, 0x13, 0x7d, 0x26, 0x2a,
+ 0xc6, 0x5c, 0x66, 0xbd, 0x2e, 0x9b, 0xac, 0x9c, 0x14, 0xc1, 0xbb, 0xef,
+ 0x51, 0x27, 0xf1, 0x2c, 0x2e, 0xb9, 0xe9, 0x9b, 0x65, 0xcc, 0x22, 0x5d,
+ 0x3b, 0x6f, 0x74, 0xd7, 0x0a, 0x6b, 0xd9, 0x13, 0x23, 0x72, 0xc4, 0x89,
+ 0x68, 0xb9, 0x13, 0xdb, 0x24, 0x9b, 0x92, 0x28, 0xde, 0x8b, 0xe5, 0xf1,
+ 0xa4, 0x54, 0x1e, 0x91, 0x29, 0x47, 0xb4, 0xac, 0x43, 0x7e, 0x76, 0xe2,
+ 0x79, 0x9b, 0x1a, 0x8b, 0xbe, 0x2e, 0x43, 0xcd, 0x1d, 0x46, 0xbf, 0x85,
+ 0xfe, 0x0e, 0x6d, 0x48, 0xcd, 0xa1, 0xfa, 0xe3, 0x93, 0x12, 0x91, 0xc7,
+ 0xcb, 0x51, 0x6f, 0x6c, 0xb5, 0x9a, 0x4d, 0x59, 0x18, 0x37, 0x22, 0x93,
+ 0x4e, 0x54, 0xc6, 0x70, 0x9d, 0x70, 0xb8, 0x7e, 0x0c, 0x3a, 0xf5, 0xda,
+ 0xa1, 0xfc, 0xac, 0x9a, 0x2f, 0x6e, 0xa4, 0x39, 0x5f, 0x17, 0xc6, 0x4d,
+ 0x80, 0x2e, 0x4d, 0x4c, 0x25, 0xcb, 0x8c, 0xe4, 0xa7, 0x35, 0xe8, 0x1b,
+ 0xae, 0x8a, 0xaf, 0x43, 0xa0, 0xdf, 0x14, 0xbb, 0x5f, 0x93, 0x02, 0x64,
+ 0x55, 0xb4, 0xd0, 0x2e, 0x9f, 0xd5, 0xb3, 0x4e, 0xb3, 0xe4, 0xcc, 0xb8,
+ 0x18, 0x33, 0x4a, 0x97, 0x64, 0x12, 0xef, 0xe8, 0x36, 0xc7, 0x5c, 0xc4,
+ 0xbe, 0xc7, 0x94, 0x1c, 0x9a, 0xd2, 0x45, 0x3d, 0x57, 0xe9, 0x14, 0x7d,
+ 0x6e, 0x8f, 0xbc, 0x3c, 0x2d, 0x96, 0x91, 0x7e, 0xb7, 0x9a, 0xb5, 0xa7,
+ 0xf4, 0xec, 0x13, 0xa6, 0x84, 0x66, 0x34, 0x99, 0xb2, 0x13, 0xb0, 0x80,
+ 0xa3, 0xfa, 0x8e, 0xca, 0x59, 0x8c, 0xe3, 0x7b, 0x18, 0x57, 0xd6, 0xc1,
+ 0x57, 0xde, 0x6f, 0xb1, 0x74, 0xa5, 0xcf, 0x1c, 0x03, 0x19, 0x60, 0x1f,
+ 0x4f, 0x3a, 0x90, 0x89, 0x92, 0x51, 0x1c, 0x32, 0x7a, 0x15, 0x32, 0x1a,
+ 0x80, 0x6c, 0x52, 0xf2, 0x52, 0xa5, 0x4f, 0x9e, 0xaf, 0x24, 0xe5, 0x39,
+ 0xe8, 0xeb, 0xb3, 0x95, 0xb8, 0x3c, 0x53, 0xe9, 0x92, 0xa7, 0x2b, 0x31,
+ 0x79, 0x4a, 0xc9, 0x2d, 0x07, 0xdb, 0x50, 0xb2, 0x0c, 0x5f, 0x9f, 0x96,
+ 0x70, 0x27, 0xe4, 0xd1, 0x01, 0xfd, 0x69, 0x87, 0x6e, 0x7e, 0xa5, 0x37,
+ 0x2c, 0xb3, 0xbd, 0x92, 0x59, 0x8f, 0xfe, 0x9b, 0xd2, 0xa6, 0xe2, 0x91,
+ 0x89, 0xe7, 0x93, 0xd3, 0x21, 0xc9, 0x59, 0x8f, 0xcb, 0x85, 0x19, 0x53,
+ 0x26, 0x2b, 0xdb, 0x6f, 0x72, 0x65, 0xc6, 0xf6, 0xbc, 0x9c, 0x9f, 0x69,
+ 0xc2, 0xb3, 0x79, 0x79, 0x79, 0xb3, 0x2e, 0x13, 0xb3, 0x6f, 0x89, 0x09,
+ 0x1e, 0x0e, 0x29, 0x79, 0x3f, 0x2e, 0xff, 0xfc, 0x27, 0x22, 0x23, 0xe0,
+ 0x8b, 0xde, 0xff, 0xef, 0xd5, 0x8c, 0x05, 0x7e, 0xf4, 0xf7, 0x41, 0x3f,
+ 0x74, 0x5c, 0x29, 0xcf, 0x38, 0xc6, 0x98, 0x5a, 0xce, 0x39, 0x0d, 0x9b,
+ 0x6a, 0xd5, 0xb2, 0xc7, 0x45, 0x0a, 0xc7, 0xab, 0x52, 0x48, 0x85, 0xe4,
+ 0x01, 0xab, 0x2a, 0x43, 0xa9, 0x26, 0x39, 0x60, 0x75, 0xca, 0x44, 0xdf,
+ 0xcf, 0x68, 0x3e, 0x96, 0x7d, 0xa5, 0x92, 0xc6, 0x3d, 0xfb, 0x44, 0x66,
+ 0xd5, 0xbd, 0xdb, 0x5f, 0xac, 0x84, 0x24, 0x13, 0x2d, 0xc6, 0x4c, 0xb9,
+ 0xa0, 0xb9, 0xb4, 0xed, 0xf4, 0x9f, 0x41, 0x5e, 0x63, 0xc0, 0x90, 0x84,
+ 0xd2, 0xa5, 0xfc, 0xf4, 0x9a, 0x8b, 0x19, 0xd5, 0x1d, 0x52, 0x7a, 0x6a,
+ 0xa4, 0x4d, 0xd2, 0x31, 0xa6, 0xa5, 0xa3, 0xd2, 0xad, 0xec, 0x64, 0x00,
+ 0x63, 0x06, 0xb5, 0xbb, 0x2b, 0x94, 0x37, 0xee, 0xcb, 0xa4, 0x75, 0x03,
+ 0xc6, 0x9a, 0xb8, 0x66, 0x3c, 0x9a, 0x83, 0x74, 0x72, 0x2e, 0xd2, 0xc9,
+ 0xeb, 0xde, 0x00, 0x9d, 0xfb, 0x6a, 0xf7, 0xb3, 0x81, 0xfb, 0x62, 0xe5,
+ 0xd7, 0x5b, 0x5c, 0xfa, 0xc8, 0xd7, 0x41, 0x99, 0x98, 0x7e, 0xc8, 0x5b,
+ 0x0b, 0xf7, 0x65, 0xae, 0xb1, 0x00, 0x3e, 0xa9, 0x91, 0x57, 0x58, 0xab,
+ 0x18, 0x58, 0xeb, 0x70, 0x60, 0xad, 0xc3, 0x81, 0xb5, 0x8a, 0xe0, 0xad,
+ 0xac, 0xd3, 0x81, 0x33, 0x79, 0xc2, 0xbc, 0x1c, 0xc5, 0x9c, 0x6f, 0x88,
+ 0x91, 0xa6, 0x2d, 0xf8, 0x36, 0xf9, 0x07, 0x18, 0x9f, 0x96, 0x73, 0x0e,
+ 0x78, 0x73, 0x3c, 0x24, 0x77, 0xa9, 0x71, 0xff, 0xb1, 0xc6, 0xa5, 0x31,
+ 0xf8, 0x2c, 0x2c, 0xbb, 0xa2, 0xbc, 0xf7, 0x9f, 0x99, 0xe0, 0x37, 0xdb,
+ 0x93, 0x37, 0xb8, 0x6d, 0xde, 0x9f, 0xf5, 0xf6, 0xd2, 0xee, 0xbe, 0x57,
+ 0x79, 0x53, 0x61, 0xc6, 0x62, 0x85, 0xb6, 0x2d, 0x29, 0xc3, 0x96, 0xfd,
+ 0x43, 0xa9, 0x4e, 0x99, 0xb4, 0xb4, 0xd4, 0x44, 0xb2, 0x99, 0xfc, 0xcf,
+ 0xe8, 0x76, 0x2b, 0xec, 0x47, 0xe2, 0x3a, 0x71, 0x51, 0xed, 0xeb, 0x5b,
+ 0x1e, 0xfd, 0x16, 0xdb, 0x23, 0xba, 0xdd, 0xd1, 0xd0, 0x4f, 0xfd, 0xff,
+ 0x4b, 0xdc, 0xd3, 0x06, 0xfa, 0x75, 0x77, 0xed, 0xbf, 0x42, 0x9b, 0x58,
+ 0x15, 0xf1, 0xda, 0xfe, 0xf3, 0xff, 0x32, 0x96, 0xb7, 0x8f, 0x6d, 0x5c,
+ 0xde, 0xf6, 0x6d, 0x29, 0x88, 0x73, 0xdc, 0x2b, 0x6c, 0xd8, 0xa6, 0xfe,
+ 0x85, 0x40, 0x6b, 0x0a, 0x36, 0xdc, 0xec, 0xd1, 0xf0, 0xba, 0x47, 0x03,
+ 0x68, 0xc5, 0xb8, 0x89, 0x0a, 0xdf, 0x51, 0xa2, 0x6c, 0x68, 0x93, 0xf7,
+ 0xfe, 0xfd, 0x5a, 0xf5, 0xfc, 0x0d, 0x83, 0xeb, 0xf8, 0x57, 0xd1, 0x86,
+ 0x60, 0x67, 0x93, 0xb3, 0xa6, 0xe4, 0x53, 0x31, 0x65, 0x0f, 0xf9, 0x54,
+ 0x1d, 0x3f, 0x26, 0xa7, 0x1b, 0xf1, 0x83, 0xef, 0x11, 0x3f, 0x5c, 0xec,
+ 0x98, 0x98, 0x25, 0x8e, 0xd4, 0x71, 0xe3, 0xc8, 0xb4, 0x8f, 0x25, 0x9c,
+ 0x9b, 0x18, 0xe2, 0xe3, 0x07, 0xdf, 0x23, 0x7e, 0x18, 0x90, 0x15, 0xe7,
+ 0xf4, 0xd7, 0x9f, 0x6a, 0x98, 0x7b, 0x4a, 0x61, 0x93, 0x8b, 0xcb, 0x6f,
+ 0x06, 0x70, 0xbe, 0x0b, 0x18, 0x1d, 0x85, 0xfc, 0x7c, 0x8c, 0x26, 0x76,
+ 0xc6, 0x80, 0xeb, 0xe0, 0x91, 0xc2, 0xe4, 0x08, 0x70, 0xcc, 0xf4, 0x30,
+ 0x35, 0xec, 0x61, 0x6a, 0x04, 0x78, 0xca, 0xb6, 0xe5, 0xb5, 0xa3, 0x5e,
+ 0x3b, 0x86, 0x36, 0xfc, 0xef, 0x1c, 0x6d, 0xec, 0xb5, 0x43, 0xe3, 0xb3,
+ 0x0a, 0xa7, 0x89, 0xf1, 0xc0, 0x0a, 0xe2, 0x2c, 0xf1, 0xb6, 0x4b, 0x16,
+ 0xca, 0x58, 0xaf, 0x86, 0x69, 0x94, 0x47, 0x90, 0x1e, 0xd2, 0xb2, 0x46,
+ 0xf4, 0xc7, 0xdc, 0xfd, 0xe8, 0xe9, 0xcf, 0xeb, 0xd2, 0xc2, 0x7d, 0x90,
+ 0xee, 0x1b, 0x41, 0x2b, 0xf7, 0xf6, 0xa3, 0xa4, 0x95, 0xeb, 0x35, 0xd2,
+ 0x7b, 0x1a, 0xf4, 0x66, 0x80, 0xb7, 0xa2, 0x8d, 0xf6, 0x8e, 0x82, 0xde,
+ 0x11, 0x60, 0xf1, 0x30, 0xb0, 0x78, 0x27, 0xb0, 0x78, 0x08, 0x58, 0x9c,
+ 0x06, 0x0e, 0x0f, 0x02, 0x87, 0x07, 0x80, 0xc3, 0x29, 0xec, 0x2b, 0x2a,
+ 0xf3, 0xc0, 0xe5, 0x79, 0xe0, 0xf3, 0x3c, 0xe4, 0x35, 0x31, 0x27, 0xda,
+ 0x17, 0xb0, 0xfe, 0x63, 0x33, 0x89, 0xd3, 0xd0, 0xcd, 0x58, 0x51, 0x87,
+ 0x3d, 0xa5, 0x06, 0xa1, 0x23, 0x49, 0x29, 0x55, 0x46, 0xa5, 0x40, 0x3f,
+ 0xb6, 0xb9, 0x07, 0xb6, 0x0b, 0xfb, 0x89, 0xf9, 0x71, 0xd3, 0x5a, 0xef,
+ 0xfa, 0xf7, 0x22, 0xf6, 0x1f, 0x83, 0x27, 0x89, 0xb8, 0xc8, 0xb0, 0xe4,
+ 0x9d, 0x1e, 0x2b, 0xab, 0x27, 0x31, 0x8e, 0xed, 0xb8, 0xb6, 0xf7, 0x78,
+ 0x42, 0x1b, 0x3f, 0xce, 0x3d, 0x4d, 0x03, 0xe3, 0xaa, 0x32, 0x95, 0xa2,
+ 0xad, 0x56, 0xe5, 0x54, 0x2a, 0x31, 0x58, 0x94, 0x56, 0x39, 0x12, 0x9d,
+ 0x56, 0xfe, 0xcd, 0x4c, 0x1f, 0x53, 0xfa, 0x51, 0xb0, 0x71, 0x2d, 0x77,
+ 0x6b, 0xf9, 0xe3, 0xf4, 0x3b, 0x3d, 0xf8, 0x85, 0x40, 0x0b, 0xe7, 0x37,
+ 0x65, 0x68, 0x40, 0xb4, 0x7d, 0xbd, 0x45, 0xa0, 0x62, 0xc2, 0x3a, 0x87,
+ 0x95, 0x73, 0xd3, 0x3d, 0xb1, 0x9c, 0x6e, 0xca, 0x98, 0xa9, 0xc9, 0x04,
+ 0xec, 0x65, 0x28, 0xf5, 0x7f, 0xd5, 0x23, 0x51, 0x3e, 0x6f, 0x96, 0xdf,
+ 0x51, 0x38, 0x8b, 0xb5, 0x4b, 0xb3, 0x58, 0x37, 0x04, 0xfe, 0x71, 0x5d,
+ 0xce, 0x83, 0x36, 0x30, 0xcf, 0xb4, 0x13, 0xa7, 0x8b, 0xb2, 0x1d, 0x76,
+ 0xb7, 0x4e, 0xb2, 0x7d, 0x4d, 0x92, 0x19, 0x89, 0xcb, 0xc4, 0xcc, 0x76,
+ 0xe0, 0x1e, 0x64, 0x60, 0xb7, 0x48, 0x7e, 0x34, 0x2e, 0x5f, 0x9e, 0x61,
+ 0x5f, 0x06, 0xfb, 0x4f, 0x1c, 0xcd, 0x08, 0xf7, 0x1f, 0x52, 0xfb, 0x8a,
+ 0xeb, 0x19, 0x39, 0xe0, 0xbc, 0xa4, 0xbb, 0x76, 0xe9, 0xb6, 0xf7, 0x42,
+ 0x1e, 0xa7, 0xc0, 0xef, 0xbc, 0x63, 0xcb, 0x02, 0xfc, 0x4a, 0xee, 0x38,
+ 0x70, 0xd5, 0x6e, 0x03, 0x06, 0x26, 0xce, 0xd2, 0x3e, 0x0c, 0xc4, 0x5a,
+ 0x25, 0xc5, 0xeb, 0x2e, 0x39, 0x3e, 0xa3, 0xcb, 0xb3, 0xb7, 0xc5, 0xd1,
+ 0x06, 0xd6, 0xa6, 0x12, 0x67, 0xc6, 0xf4, 0x2e, 0xb9, 0xb5, 0x23, 0x86,
+ 0xf7, 0x52, 0x5a, 0xde, 0xf9, 0x37, 0xf2, 0xf2, 0x64, 0x5c, 0xe7, 0x58,
+ 0x5d, 0x72, 0x29, 0x03, 0x3a, 0x56, 0xc4, 0xf8, 0x7f, 0x40, 0x7f, 0x97,
+ 0xcc, 0x21, 0xbe, 0x99, 0x03, 0x4d, 0xd9, 0x14, 0xb1, 0x30, 0x71, 0x72,
+ 0x49, 0x07, 0x66, 0xcd, 0x41, 0x37, 0x47, 0x11, 0x3f, 0xcc, 0xfc, 0x37,
+ 0xc6, 0xc4, 0x21, 0xd3, 0x1e, 0x6b, 0x02, 0xf8, 0x92, 0xe9, 0xe2, 0x3d,
+ 0xe7, 0xb4, 0xe5, 0x94, 0x43, 0x1d, 0x8a, 0xcb, 0xe3, 0x15, 0xbe, 0xd7,
+ 0x73, 0xf6, 0x69, 0xb1, 0xe5, 0x41, 0xe7, 0x7f, 0x30, 0xfe, 0x1d, 0xc4,
+ 0x9e, 0x96, 0x94, 0x20, 0xb7, 0x02, 0x78, 0x99, 0x89, 0xb9, 0xed, 0x89,
+ 0xb9, 0xc4, 0xd9, 0x0b, 0x3a, 0xef, 0xed, 0xe2, 0x82, 0x7e, 0xb3, 0x48,
+ 0x07, 0xf9, 0x99, 0x02, 0x2f, 0x6d, 0x4b, 0xd7, 0x37, 0x7b, 0xf1, 0x16,
+ 0x6d, 0xc0, 0x06, 0x7d, 0xa6, 0x2c, 0xf4, 0x07, 0x6d, 0x80, 0x7e, 0xd6,
+ 0xb7, 0x81, 0x44, 0x6c, 0x49, 0xd7, 0xf1, 0xdc, 0x94, 0x63, 0xaa, 0xad,
+ 0x81, 0xd6, 0x44, 0x8c, 0xfb, 0x9b, 0x2c, 0x27, 0xe5, 0x71, 0x87, 0xe3,
+ 0xc1, 0xe7, 0xe9, 0x88, 0x37, 0x1e, 0xf1, 0x8e, 0xc3, 0x98, 0x29, 0x09,
+ 0x9a, 0x5d, 0xbb, 0x58, 0x98, 0x8e, 0xaa, 0x67, 0x47, 0x1c, 0x37, 0x36,
+ 0xd2, 0x11, 0x3f, 0xcd, 0x23, 0x7e, 0xca, 0x29, 0x1b, 0xb1, 0x32, 0x88,
+ 0xaf, 0xe1, 0x67, 0x5d, 0xfb, 0x28, 0x95, 0x49, 0xcb, 0x3d, 0xa0, 0x2f,
+ 0x51, 0x04, 0x31, 0xc7, 0x74, 0xb8, 0xeb, 0xec, 0x80, 0x14, 0x19, 0x63,
+ 0x9d, 0x33, 0x1e, 0x91, 0xb1, 0x12, 0xfd, 0x1b, 0x7e, 0x8e, 0x6d, 0x31,
+ 0xa6, 0xcf, 0x28, 0xdf, 0xd3, 0x03, 0x3d, 0x80, 0x5f, 0x4a, 0xb5, 0x8b,
+ 0xeb, 0x07, 0xf7, 0x40, 0x9e, 0xc3, 0x90, 0x7b, 0x5a, 0xc6, 0x4f, 0x8c,
+ 0x53, 0xa7, 0x93, 0x25, 0x49, 0x24, 0x8f, 0xc8, 0x16, 0x6b, 0x01, 0xbe,
+ 0x30, 0x33, 0x5a, 0xdd, 0xae, 0xa7, 0xf9, 0xce, 0xa3, 0x78, 0x07, 0xd7,
+ 0xd2, 0xb8, 0x3c, 0x50, 0x61, 0xdf, 0x9d, 0x86, 0xb4, 0xc0, 0x56, 0x06,
+ 0xf6, 0x78, 0x76, 0x80, 0xf9, 0x4c, 0x7f, 0xbe, 0x71, 0x6f, 0x3e, 0x8e,
+ 0xe3, 0x18, 0xbe, 0x53, 0x9f, 0x77, 0x07, 0x7d, 0x1b, 0xb0, 0x64, 0x87,
+ 0x5e, 0xdd, 0x1e, 0xc2, 0xf3, 0x53, 0x03, 0xbc, 0xc7, 0x3c, 0xf0, 0x6d,
+ 0x96, 0x3d, 0x8c, 0xb1, 0xa3, 0x98, 0x73, 0x8d, 0x64, 0x3b, 0x7d, 0x7a,
+ 0xa9, 0x03, 0x8c, 0x3f, 0xd8, 0x8e, 0xae, 0x77, 0x79, 0xff, 0x25, 0xc3,
+ 0xd5, 0xc9, 0x11, 0xb4, 0x69, 0x7f, 0x07, 0x25, 0xe7, 0x24, 0xb0, 0x4f,
+ 0xf0, 0xb6, 0x32, 0xe1, 0xed, 0x11, 0xfc, 0x1f, 0x39, 0x0c, 0x3e, 0x48,
+ 0xd1, 0xe5, 0x0d, 0xf9, 0x42, 0x9e, 0xfc, 0x16, 0x74, 0xff, 0x61, 0x8c,
+ 0x81, 0x7f, 0x50, 0x3c, 0x58, 0xea, 0x70, 0x63, 0xd1, 0x44, 0x31, 0xc3,
+ 0xfc, 0xa9, 0x83, 0x98, 0x07, 0xfc, 0xa9, 0x40, 0xb1, 0x30, 0xf7, 0x92,
+ 0xbe, 0x86, 0xf4, 0xc6, 0x97, 0x0c, 0x83, 0xed, 0xe4, 0x12, 0x74, 0xb8,
+ 0x04, 0xf9, 0x64, 0xfb, 0x68, 0xb3, 0x36, 0xe4, 0x31, 0x63, 0x50, 0x5f,
+ 0x4b, 0x88, 0x05, 0xf3, 0xce, 0x16, 0xeb, 0x5e, 0xf2, 0xcd, 0xb2, 0xe4,
+ 0x69, 0x27, 0x88, 0x1d, 0x3b, 0x30, 0x94, 0x7a, 0x18, 0x85, 0x1e, 0x98,
+ 0xf0, 0xc9, 0x31, 0xc8, 0xfc, 0xc5, 0x0e, 0x77, 0x2f, 0xbc, 0x37, 0x65,
+ 0xde, 0xc2, 0x9a, 0xce, 0xef, 0xaf, 0x73, 0xfb, 0x78, 0xcf, 0xb8, 0xc8,
+ 0x97, 0xab, 0x4f, 0x3b, 0xe5, 0xdb, 0x28, 0xd3, 0x43, 0xd8, 0x0b, 0xfb,
+ 0x71, 0x2d, 0x1d, 0x94, 0x71, 0xd0, 0x56, 0x18, 0xd8, 0x14, 0x3b, 0x8f,
+ 0xf1, 0x39, 0xe0, 0x79, 0xd1, 0xe4, 0xb3, 0x8b, 0x5a, 0xfd, 0x1d, 0xc4,
+ 0x5c, 0x36, 0xfd, 0xd9, 0x92, 0xf6, 0x85, 0xca, 0xcb, 0x5a, 0xb6, 0x74,
+ 0x51, 0xcb, 0x41, 0x4f, 0x4a, 0x0e, 0x73, 0x06, 0xda, 0x8f, 0x85, 0xb5,
+ 0x13, 0xb1, 0xb7, 0xf5, 0x9e, 0xf8, 0x02, 0xb0, 0x60, 0x2f, 0x6c, 0x3a,
+ 0x67, 0xee, 0x94, 0x02, 0xb0, 0x35, 0x7f, 0x62, 0x0b, 0xec, 0x2d, 0x1e,
+ 0xa0, 0x8b, 0x78, 0x56, 0xa4, 0x4f, 0xd5, 0x76, 0x38, 0x52, 0x6c, 0x4a,
+ 0x13, 0xd7, 0x36, 0x41, 0x77, 0xd0, 0x57, 0xae, 0xeb, 0xdf, 0x1d, 0x2b,
+ 0x68, 0x45, 0x7e, 0x39, 0xb0, 0x9c, 0xde, 0x92, 0x5c, 0x99, 0xde, 0x1d,
+ 0x35, 0x7a, 0x89, 0x19, 0xc0, 0x7f, 0xd8, 0xcd, 0x4b, 0xd0, 0xdf, 0xe7,
+ 0x1d, 0xe0, 0xbf, 0x03, 0xfc, 0x87, 0x4d, 0x3d, 0x03, 0xdd, 0x7b, 0xda,
+ 0x81, 0x0f, 0x70, 0xe0, 0x03, 0x1c, 0xf8, 0x00, 0x27, 0x0b, 0x39, 0x11,
+ 0xe7, 0xe9, 0x43, 0x76, 0xd7, 0x7c, 0x9e, 0x1b, 0x37, 0xdd, 0xe0, 0xc5,
+ 0x22, 0xa3, 0x88, 0x45, 0x36, 0xc8, 0x44, 0xf2, 0x7a, 0xec, 0xad, 0x05,
+ 0xd7, 0x56, 0x5c, 0xb1, 0x46, 0xf2, 0x76, 0xcf, 0x4e, 0x1e, 0x06, 0x5d,
+ 0x88, 0xbf, 0x93, 0x3f, 0x0d, 0x3d, 0x6c, 0x02, 0x3d, 0x3f, 0xe5, 0xc5,
+ 0x2c, 0x0f, 0x9a, 0xae, 0x1e, 0xb6, 0xa2, 0xef, 0x93, 0xe8, 0x6b, 0xc5,
+ 0x98, 0x03, 0x18, 0xc3, 0x98, 0xa7, 0xcd, 0xeb, 0x0b, 0x8e, 0x63, 0xec,
+ 0xf3, 0x19, 0xac, 0x95, 0xc0, 0xb8, 0x36, 0xcc, 0xdd, 0x85, 0x31, 0xdb,
+ 0x30, 0xe6, 0x46, 0xb4, 0x19, 0x33, 0x6f, 0x44, 0xfb, 0x13, 0x0d, 0xef,
+ 0x7c, 0x0c, 0x7d, 0xb7, 0x37, 0xf4, 0x9d, 0x43, 0x1f, 0xf2, 0x50, 0xeb,
+ 0xbc, 0xf7, 0x5e, 0x11, 0xed, 0xce, 0x86, 0x31, 0xaf, 0xa2, 0x0f, 0x71,
+ 0xaf, 0xf5, 0x2d, 0x5c, 0x91, 0x7f, 0x5a, 0xa4, 0xc9, 0x7f, 0xc6, 0xb8,
+ 0x37, 0x8e, 0xfe, 0x90, 0x17, 0xbb, 0xfe, 0xa6, 0x09, 0xbd, 0xd3, 0x86,
+ 0x9c, 0xdf, 0x30, 0xdd, 0x58, 0xef, 0x4e, 0xcb, 0xd5, 0x43, 0xbf, 0xfd,
+ 0x70, 0x43, 0x9b, 0x63, 0x17, 0x1a, 0xfa, 0xfe, 0xa5, 0xa1, 0xfd, 0xdd,
+ 0xd0, 0xca, 0x77, 0x06, 0xdb, 0x97, 0xf7, 0x15, 0x3a, 0x96, 0xb7, 0xed,
+ 0xa6, 0x95, 0xef, 0xe8, 0xeb, 0x96, 0xf7, 0xdd, 0xb8, 0xbe, 0x61, 0x0c,
+ 0x74, 0x2a, 0x8a, 0x1c, 0xc9, 0x1f, 0x1f, 0xbe, 0xce, 0x7d, 0x4e, 0xfe,
+ 0x36, 0xea, 0x92, 0xda, 0x3a, 0xda, 0x3a, 0xe4, 0xb0, 0xa4, 0xc1, 0x9e,
+ 0x2c, 0x3d, 0xfd, 0xb2, 0x96, 0x83, 0x4e, 0x65, 0x2b, 0xfe, 0x7c, 0xb4,
+ 0xd9, 0xc6, 0xdc, 0xdc, 0xcf, 0xc9, 0x19, 0x2b, 0x45, 0xa0, 0x37, 0xf7,
+ 0xd0, 0x27, 0x1d, 0x2d, 0x4a, 0xdd, 0x3e, 0xbb, 0xf5, 0x4b, 0xd9, 0xe7,
+ 0xed, 0x1e, 0x46, 0x1d, 0x06, 0x9d, 0x55, 0x19, 0x49, 0x35, 0xd3, 0xc7,
+ 0x78, 0xd8, 0x45, 0xdc, 0xa9, 0x56, 0x8d, 0xcd, 0x55, 0xd9, 0x9f, 0x7a,
+ 0xa7, 0x2a, 0x0a, 0xf3, 0x06, 0x15, 0xee, 0xc4, 0xf5, 0x1e, 0xc8, 0xc8,
+ 0x42, 0x6e, 0x82, 0x7c, 0x3a, 0x4a, 0x9f, 0x74, 0x90, 0xf1, 0xc9, 0xa3,
+ 0x2e, 0xa6, 0x12, 0x77, 0xd0, 0x46, 0x5e, 0x96, 0x3f, 0xce, 0xf5, 0x71,
+ 0x2d, 0x11, 0xc7, 0x47, 0x95, 0x4f, 0xc9, 0x5b, 0x9c, 0x77, 0x35, 0x6c,
+ 0x3c, 0x6b, 0x32, 0xa6, 0x33, 0xed, 0xd3, 0xf0, 0x6f, 0x7c, 0xc6, 0x58,
+ 0xe1, 0x34, 0xe3, 0x92, 0x00, 0x56, 0x6d, 0x35, 0xe0, 0x32, 0x8b, 0xcb,
+ 0xf7, 0xb5, 0x81, 0x79, 0xc4, 0x55, 0xec, 0x75, 0x75, 0x2c, 0xea, 0xd1,
+ 0xaf, 0x6c, 0xdb, 0xbb, 0x6a, 0xb6, 0xed, 0xeb, 0xde, 0x6a, 0x39, 0xf8,
+ 0xf7, 0x95, 0x2c, 0x9e, 0xaa, 0x24, 0x8e, 0x15, 0x61, 0x4b, 0x8b, 0x2a,
+ 0xef, 0xf6, 0xe5, 0xc2, 0x18, 0x27, 0x71, 0x72, 0x1e, 0x6f, 0x8e, 0xab,
+ 0x1c, 0x83, 0xf9, 0x45, 0x55, 0x76, 0xa4, 0x5a, 0xa3, 0xe4, 0x43, 0x46,
+ 0xff, 0x76, 0x88, 0x31, 0xc3, 0xa2, 0x43, 0x9e, 0xa5, 0xf0, 0x3c, 0x05,
+ 0x4c, 0xf8, 0x27, 0xc9, 0x45, 0xd9, 0xf7, 0x76, 0x75, 0x01, 0x71, 0x95,
+ 0x8a, 0x8f, 0x94, 0xbf, 0x67, 0x7c, 0xb7, 0x1f, 0xfc, 0x22, 0x4f, 0x47,
+ 0xc0, 0x67, 0x3f, 0x06, 0x78, 0x8d, 0x75, 0x15, 0x59, 0x1e, 0x07, 0x8b,
+ 0x3c, 0x50, 0x7e, 0x19, 0x73, 0xea, 0x6e, 0xac, 0xc2, 0x3c, 0xdc, 0x66,
+ 0x7f, 0x47, 0x88, 0xb1, 0x9c, 0xeb, 0xeb, 0x0d, 0xac, 0x87, 0xdc, 0xbe,
+ 0xfc, 0x8f, 0x2a, 0x6e, 0x2a, 0x28, 0x79, 0x20, 0x86, 0xaa, 0xf0, 0x19,
+ 0xfb, 0xc2, 0x5e, 0xec, 0x1c, 0xf1, 0x62, 0x65, 0xcb, 0x8b, 0x95, 0x49,
+ 0x07, 0x6b, 0x6f, 0x7e, 0x5c, 0x40, 0x99, 0x2d, 0x1d, 0xd2, 0x37, 0x33,
+ 0x2e, 0x68, 0x93, 0xd5, 0xe3, 0x02, 0x9f, 0xa6, 0x6d, 0xa0, 0x89, 0x71,
+ 0x9e, 0xaa, 0xbd, 0x74, 0xb8, 0xf5, 0x1e, 0xd2, 0xe0, 0xfb, 0x47, 0xe5,
+ 0x87, 0x8f, 0xc2, 0xe5, 0x61, 0x6f, 0x69, 0xd0, 0xba, 0x53, 0xb2, 0xd3,
+ 0xdb, 0x3c, 0x7f, 0xcb, 0x1c, 0x80, 0xf1, 0xb7, 0xab, 0xb3, 0xd9, 0xd4,
+ 0x84, 0x3f, 0x4f, 0x27, 0x3c, 0x64, 0xa0, 0x2e, 0xc4, 0xb5, 0x18, 0xc7,
+ 0xf8, 0x31, 0xcd, 0x4e, 0x2f, 0xa6, 0x19, 0x96, 0xfd, 0x8e, 0x1b, 0xf3,
+ 0x8f, 0xa0, 0x3f, 0xef, 0x28, 0xda, 0x63, 0x8c, 0x2d, 0x75, 0xc4, 0xdc,
+ 0x99, 0x3d, 0x09, 0x24, 0x0f, 0xee, 0x5e, 0xba, 0xb1, 0x97, 0x52, 0x6d,
+ 0x2f, 0xad, 0x4b, 0xcb, 0xf7, 0x32, 0xaa, 0xde, 0x9d, 0x5a, 0xf1, 0xae,
+ 0x60, 0x1f, 0xbb, 0x2f, 0xf1, 0x8c, 0x7b, 0x64, 0xdc, 0x60, 0x79, 0x7b,
+ 0xf4, 0xe5, 0x74, 0x00, 0x7b, 0x4c, 0x6a, 0x79, 0x15, 0x6b, 0xed, 0x51,
+ 0x3c, 0xcf, 0x97, 0xc7, 0x70, 0xa5, 0x7d, 0xa8, 0x79, 0x94, 0x8d, 0x4c,
+ 0x28, 0x3e, 0x8f, 0xab, 0x7d, 0x2c, 0x94, 0x7f, 0x41, 0x0a, 0x27, 0x7e,
+ 0x09, 0x7e, 0x2f, 0x58, 0x0f, 0x63, 0x2d, 0x91, 0xfc, 0x28, 0x06, 0xf0,
+ 0x93, 0x7b, 0x65, 0xad, 0xeb, 0x0f, 0x43, 0x6e, 0x7e, 0x10, 0x81, 0x8c,
+ 0x35, 0xf7, 0xb9, 0x5a, 0xdf, 0xe7, 0x6b, 0x53, 0x80, 0x9e, 0x2a, 0x62,
+ 0xce, 0x18, 0x68, 0x08, 0xbe, 0x73, 0x50, 0x86, 0x1c, 0xca, 0xa3, 0x27,
+ 0x36, 0x2e, 0xb6, 0x95, 0x17, 0x3f, 0xce, 0xe0, 0xfa, 0xb4, 0xf9, 0x5c,
+ 0xcc, 0x10, 0xd6, 0x2f, 0x7d, 0xde, 0xf9, 0x7c, 0x8b, 0x2c, 0x35, 0xea,
+ 0xc0, 0x14, 0xe8, 0x29, 0x38, 0xe4, 0x93, 0xaf, 0x9b, 0xfe, 0xda, 0xaf,
+ 0xaa, 0xfd, 0x4c, 0xaa, 0x9a, 0xdd, 0x73, 0x35, 0x1d, 0x9d, 0x40, 0x0c,
+ 0xe2, 0xea, 0xdc, 0x7d, 0x1e, 0x6f, 0x7c, 0xdd, 0x8c, 0x78, 0x72, 0x66,
+ 0x1e, 0x47, 0xdb, 0xf1, 0xf5, 0x60, 0x93, 0x75, 0xb7, 0xe2, 0x05, 0x9f,
+ 0x11, 0x53, 0x5c, 0x59, 0x8e, 0xd5, 0x64, 0xb9, 0xb6, 0x41, 0x2f, 0xbf,
+ 0xb7, 0xce, 0xb5, 0x43, 0xda, 0x1b, 0xec, 0x16, 0xf4, 0x3d, 0xb5, 0xcc,
+ 0xbe, 0x93, 0x97, 0xa8, 0x83, 0x46, 0xc4, 0x98, 0xfb, 0x53, 0xf0, 0xf2,
+ 0x63, 0xc8, 0x55, 0x44, 0xcc, 0x19, 0xe2, 0x10, 0xe3, 0x8d, 0x7a, 0xbc,
+ 0xbb, 0x20, 0xab, 0xc5, 0xba, 0x57, 0x8a, 0x35, 0x7e, 0xf2, 0x2a, 0x63,
+ 0x8d, 0x78, 0x93, 0xb4, 0x10, 0x8b, 0x86, 0x11, 0xdb, 0x6a, 0xd2, 0x64,
+ 0x3f, 0x08, 0x1f, 0x76, 0xc6, 0x6c, 0xb6, 0x7d, 0x4c, 0x88, 0x48, 0xfb,
+ 0xdc, 0x06, 0x85, 0x0b, 0xd6, 0x4c, 0x1d, 0x17, 0x26, 0xc0, 0xfb, 0x11,
+ 0xb7, 0xb6, 0x1a, 0x6d, 0x97, 0xab, 0xcd, 0x8d, 0xeb, 0x71, 0xff, 0x58,
+ 0x2d, 0xee, 0xbf, 0xa1, 0x81, 0x8f, 0xab, 0xe1, 0xe2, 0x19, 0xf0, 0x2d,
+ 0x8d, 0xfc, 0x97, 0x79, 0xed, 0x10, 0xf2, 0x61, 0xe6, 0x62, 0x19, 0xe4,
+ 0xc4, 0x89, 0x33, 0xc0, 0x2a, 0xe4, 0xc8, 0x89, 0xb7, 0xe0, 0x57, 0x90,
+ 0x37, 0x27, 0xe6, 0x99, 0xbb, 0x2e, 0x22, 0x3f, 0x7e, 0x1a, 0xf9, 0xf1,
+ 0x53, 0x95, 0x3e, 0xf0, 0x37, 0xa9, 0xb0, 0x73, 0xef, 0x71, 0xd1, 0xee,
+ 0x52, 0xf5, 0x61, 0xda, 0x73, 0x14, 0x7e, 0xb4, 0x5a, 0x3d, 0x90, 0xea,
+ 0x41, 0x4e, 0x1e, 0x97, 0x4f, 0x99, 0xcc, 0x63, 0x35, 0xb3, 0xbb, 0x7f,
+ 0xc1, 0x08, 0xc6, 0xa4, 0xd9, 0x2b, 0xfa, 0x81, 0x95, 0xbc, 0xcf, 0x29,
+ 0x5f, 0x70, 0xcc, 0xb8, 0x1c, 0xef, 0xef, 0xaa, 0xf1, 0xfe, 0xc2, 0x1a,
+ 0x69, 0x19, 0x56, 0x35, 0x80, 0xee, 0xfe, 0x03, 0xc4, 0xab, 0x14, 0xfc,
+ 0x3a, 0xfc, 0x6f, 0x55, 0xee, 0x48, 0x5d, 0xac, 0x9e, 0xb7, 0xd7, 0x49,
+ 0xbe, 0xef, 0x8b, 0x1e, 0x66, 0x8f, 0x3d, 0x92, 0xb5, 0x8b, 0xb0, 0x0f,
+ 0xb7, 0x16, 0x39, 0x3e, 0x1d, 0x46, 0x14, 0xca, 0xbf, 0x0e, 0x59, 0x18,
+ 0xfc, 0x1b, 0xc8, 0x70, 0xcb, 0x69, 0x16, 0xb0, 0x74, 0xe0, 0xf0, 0x42,
+ 0x34, 0xa2, 0xea, 0x33, 0xd7, 0xd9, 0xec, 0xb7, 0x20, 0xd3, 0x51, 0x59,
+ 0x40, 0xfc, 0x50, 0x1a, 0x04, 0x8d, 0x7d, 0x9d, 0x18, 0x4f, 0xbb, 0x23,
+ 0xcf, 0x47, 0xe1, 0x7b, 0xc9, 0xd3, 0x28, 0xc6, 0xef, 0xc2, 0x98, 0x0e,
+ 0x5c, 0xbf, 0x68, 0x2c, 0x58, 0xcc, 0x9d, 0x7f, 0x0e, 0x6d, 0xce, 0x11,
+ 0xf4, 0x9d, 0x9f, 0x0e, 0x89, 0x9a, 0x93, 0xef, 0x74, 0x2a, 0xfb, 0xaf,
+ 0xaf, 0xc5, 0x75, 0xf8, 0xec, 0xbd, 0xea, 0x2d, 0xfd, 0x83, 0x81, 0xf5,
+ 0xda, 0x02, 0xeb, 0x0d, 0x06, 0xd6, 0x23, 0x9d, 0x1d, 0x01, 0x3a, 0x3b,
+ 0xf0, 0x7e, 0x0e, 0x6b, 0x0f, 0xab, 0x98, 0xa7, 0xbe, 0xe6, 0xfd, 0x81,
+ 0x35, 0xfd, 0xfd, 0x75, 0x06, 0xde, 0x7b, 0x07, 0xeb, 0xb1, 0x2f, 0x1a,
+ 0xe8, 0x23, 0x0d, 0xeb, 0xd1, 0xc7, 0x76, 0x47, 0x80, 0x2e, 0xd2, 0xba,
+ 0x16, 0xfd, 0x2a, 0x7e, 0x02, 0x9f, 0x5b, 0xe0, 0xb7, 0x74, 0xf8, 0x0e,
+ 0xd6, 0xa0, 0x1b, 0xf7, 0xfa, 0x65, 0xac, 0xeb, 0xcf, 0x17, 0xc5, 0x1c,
+ 0x1c, 0xcf, 0xb1, 0x86, 0xf7, 0x3e, 0xfb, 0xf9, 0xfc, 0x1b, 0xd5, 0xaf,
+ 0x2b, 0xbe, 0xad, 0x07, 0xed, 0xaa, 0xee, 0x22, 0xf3, 0x1d, 0x26, 0xe4,
+ 0xc9, 0xfc, 0x58, 0x93, 0x9b, 0x6c, 0x5d, 0xeb, 0xe9, 0xa7, 0xec, 0xd7,
+ 0x79, 0x58, 0xda, 0xa2, 0x65, 0x8f, 0xb3, 0x5e, 0xd0, 0xea, 0xe5, 0x7c,
+ 0xc8, 0x3d, 0x94, 0x8f, 0x31, 0xbd, 0xe7, 0xf4, 0x31, 0x8c, 0x5b, 0xe8,
+ 0x3f, 0x33, 0xde, 0x3d, 0xae, 0xd0, 0xe1, 0x7d, 0xa5, 0x0e, 0x39, 0xaf,
+ 0x78, 0x6a, 0xc9, 0xb9, 0x1a, 0x4f, 0x43, 0xde, 0xb7, 0x90, 0x83, 0xde,
+ 0x77, 0x06, 0x03, 0x71, 0x11, 0xee, 0xcb, 0x19, 0xd0, 0x10, 0x97, 0x9e,
+ 0x7e, 0xe6, 0x6e, 0x45, 0x5c, 0x59, 0xa7, 0xd0, 0x70, 0x75, 0xeb, 0x17,
+ 0x3d, 0xfd, 0xf0, 0x4b, 0xc0, 0xa1, 0x9e, 0xfe, 0xef, 0xa8, 0x7c, 0xae,
+ 0x54, 0xb1, 0xb4, 0x3b, 0x1c, 0xb7, 0x46, 0x74, 0xce, 0xbe, 0x5c, 0x8d,
+ 0x68, 0xa0, 0x99, 0x75, 0x0d, 0xbf, 0x46, 0x74, 0x4e, 0x54, 0x8d, 0xe8,
+ 0xe4, 0x15, 0x6a, 0x44, 0x99, 0xab, 0xaf, 0x11, 0x71, 0x7e, 0x53, 0xee,
+ 0x1e, 0x10, 0xed, 0x4b, 0x5e, 0x8d, 0xe8, 0x82, 0xb8, 0x35, 0xa2, 0xf3,
+ 0xb2, 0x7a, 0x8d, 0xe8, 0x68, 0x43, 0x8d, 0x68, 0xbd, 0xaa, 0x11, 0x71,
+ 0x1e, 0xb7, 0x46, 0xc4, 0x76, 0xbe, 0x7f, 0x30, 0x50, 0xeb, 0x00, 0xfe,
+ 0x3a, 0xb7, 0x82, 0x6f, 0x96, 0x36, 0xea, 0xf8, 0x98, 0x46, 0xec, 0xbf,
+ 0xbe, 0xe6, 0xbf, 0xea, 0xf8, 0xa6, 0x29, 0x9d, 0xbb, 0x12, 0xbe, 0x8d,
+ 0xba, 0x71, 0xc9, 0x32, 0x6c, 0x9b, 0xaa, 0xc5, 0x2e, 0xbf, 0xdc, 0xcc,
+ 0x1c, 0x7a, 0xb2, 0x5c, 0x9f, 0x77, 0x12, 0xf2, 0x1e, 0xab, 0xd5, 0x49,
+ 0x2e, 0x15, 0x1f, 0x45, 0xe5, 0xe0, 0xaa, 0xdf, 0x9a, 0x62, 0x99, 0x95,
+ 0xdf, 0x9a, 0x34, 0x89, 0x82, 0xce, 0x7c, 0x7f, 0x5e, 0xe5, 0x5d, 0x0b,
+ 0xce, 0xcf, 0xcb, 0xd2, 0xbd, 0x16, 0xf0, 0xc7, 0xaf, 0x9f, 0x50, 0xbe,
+ 0x75, 0x9f, 0x92, 0xd5, 0x3f, 0xba, 0x1a, 0xca, 0x3e, 0x55, 0x43, 0xf9,
+ 0x5a, 0x73, 0xb0, 0x86, 0x72, 0x4e, 0x2e, 0x5f, 0x43, 0xd9, 0xb7, 0x4a,
+ 0x0d, 0xe5, 0x15, 0xa9, 0xd7, 0x50, 0x5e, 0x11, 0xbf, 0x86, 0x62, 0xc8,
+ 0xd2, 0x7a, 0xce, 0xb3, 0x1f, 0xef, 0x8c, 0xe0, 0x37, 0x8c, 0x9f, 0x5b,
+ 0x53, 0x39, 0x57, 0xa3, 0x7f, 0xb5, 0x9a, 0xca, 0x37, 0x9b, 0xdf, 0x4f,
+ 0x4d, 0xc5, 0xf5, 0x01, 0x7e, 0x4d, 0xa5, 0x05, 0xf1, 0x0e, 0x7c, 0x8e,
+ 0x1e, 0xac, 0xa9, 0xfc, 0x2d, 0xed, 0x01, 0x7d, 0x2a, 0x46, 0x40, 0x3f,
+ 0xec, 0x02, 0x7e, 0x29, 0xa3, 0x6a, 0x1c, 0x9f, 0xf6, 0x78, 0xb8, 0x1b,
+ 0x7b, 0x8e, 0x43, 0x16, 0xe4, 0x63, 0x8f, 0x8a, 0x2d, 0x33, 0x66, 0x4c,
+ 0xcb, 0xf6, 0xc2, 0x9b, 0x4d, 0xf3, 0x5b, 0x74, 0x4c, 0xc6, 0x2b, 0xd4,
+ 0xf1, 0x2e, 0xc4, 0xe2, 0x26, 0xfa, 0x76, 0xa3, 0xed, 0xc7, 0x54, 0xfd,
+ 0xb5, 0x39, 0x68, 0x9b, 0x0b, 0xc0, 0x59, 0xe0, 0xc4, 0x55, 0xf8, 0xa8,
+ 0x6d, 0xa0, 0x39, 0xb8, 0x8f, 0x22, 0xfc, 0x13, 0xfa, 0x94, 0xcc, 0x19,
+ 0x5b, 0xfa, 0xb4, 0xc4, 0x69, 0xe7, 0x57, 0x31, 0x1f, 0xfb, 0xb6, 0xa9,
+ 0x7c, 0xac, 0x30, 0xc0, 0xbd, 0xd2, 0xd7, 0x2d, 0x82, 0x3e, 0xf4, 0x95,
+ 0x98, 0x03, 0xd2, 0xef, 0xf9, 0x39, 0x5a, 0x44, 0xe5, 0x68, 0x9d, 0x8a,
+ 0x1f, 0xe4, 0xf5, 0x8d, 0x61, 0x62, 0x65, 0xa7, 0xcd, 0x3d, 0x0c, 0x7b,
+ 0x58, 0xc7, 0xb6, 0x9b, 0x0b, 0x66, 0x74, 0xde, 0x3f, 0x02, 0xb9, 0xb2,
+ 0x4e, 0xe3, 0xcb, 0xef, 0x21, 0x6f, 0xdf, 0x83, 0x52, 0xec, 0x94, 0xf0,
+ 0x7a, 0xd0, 0x93, 0x9f, 0x61, 0xdc, 0xfd, 0x09, 0x95, 0x83, 0x44, 0xed,
+ 0x4b, 0xdb, 0xed, 0x5d, 0xd7, 0x60, 0xb7, 0x23, 0x97, 0xb5, 0xdb, 0xcf,
+ 0x85, 0x83, 0x76, 0x7b, 0xd7, 0x35, 0xd8, 0xed, 0xfe, 0x6b, 0xb2, 0x5b,
+ 0xee, 0x8d, 0x98, 0xe4, 0xd7, 0xc4, 0x56, 0xc6, 0x59, 0xfe, 0xba, 0x13,
+ 0x58, 0x33, 0x73, 0x89, 0x35, 0xc7, 0x2e, 0x59, 0x5b, 0x6d, 0x8c, 0xb1,
+ 0xae, 0x46, 0xde, 0xcc, 0xad, 0xe8, 0x6f, 0x23, 0x9e, 0x5f, 0xba, 0xdd,
+ 0xcb, 0xe7, 0xfd, 0xbc, 0x3e, 0x68, 0x3f, 0xd4, 0x0b, 0xea, 0xc2, 0x63,
+ 0xe0, 0x17, 0xf5, 0xc1, 0xb7, 0xb9, 0x9e, 0x06, 0x1d, 0x5c, 0x44, 0xbe,
+ 0xdf, 0xe3, 0xe9, 0x20, 0x65, 0xdd, 0xab, 0xbe, 0x11, 0x95, 0x9c, 0x47,
+ 0xdc, 0x3c, 0x1f, 0x3a, 0x90, 0x2f, 0xf9, 0xb6, 0x06, 0x9e, 0x44, 0xfd,
+ 0x67, 0xe4, 0xa3, 0x8d, 0x98, 0x67, 0x0b, 0xe2, 0x35, 0xf0, 0x48, 0xf5,
+ 0x2f, 0xaf, 0x09, 0x5f, 0x1e, 0xcf, 0xa4, 0x18, 0xc2, 0xd8, 0x53, 0x03,
+ 0xb0, 0xf1, 0x01, 0x62, 0x54, 0x1a, 0x79, 0x0f, 0xf5, 0x90, 0xba, 0xb9,
+ 0x29, 0xb9, 0x43, 0x67, 0x4c, 0xb5, 0x07, 0xb6, 0x47, 0x7d, 0x8d, 0xcb,
+ 0x8e, 0xca, 0xa6, 0x33, 0xe7, 0x74, 0xae, 0x51, 0xad, 0xe6, 0x99, 0x2b,
+ 0x5a, 0xa2, 0x77, 0xf7, 0xff, 0x45, 0x98, 0x7e, 0xe9, 0x7a, 0xdb, 0xf0,
+ 0x74, 0x2d, 0x83, 0x7b, 0xea, 0xed, 0xeb, 0xf0, 0xf7, 0xfc, 0xc6, 0xfe,
+ 0x03, 0xf4, 0xc7, 0x60, 0xf3, 0xf4, 0xef, 0xcc, 0x47, 0xb6, 0x7a, 0xe3,
+ 0x7a, 0xd4, 0xf7, 0xcf, 0x6c, 0xea, 0x56, 0xef, 0xbb, 0x13, 0xfd, 0x4f,
+ 0x82, 0x3e, 0x7b, 0x99, 0x9c, 0x79, 0x46, 0x21, 0xa7, 0xf2, 0x19, 0xbe,
+ 0xaf, 0x74, 0x12, 0x39, 0x88, 0x19, 0xa8, 0xa5, 0x87, 0xbd, 0xdc, 0x8d,
+ 0x36, 0x16, 0x81, 0x0c, 0xb7, 0x7b, 0xb9, 0x0a, 0xf3, 0xd7, 0xe5, 0x67,
+ 0x13, 0x56, 0xd7, 0x81, 0x0d, 0xef, 0x43, 0x07, 0x1a, 0xe5, 0x17, 0x86,
+ 0xed, 0xfb, 0xf2, 0xf3, 0xe3, 0x98, 0x79, 0x6f, 0xdf, 0x3d, 0xae, 0x0c,
+ 0x7f, 0x2c, 0xf6, 0xa9, 0x05, 0xf6, 0xe9, 0xe3, 0xd1, 0x3e, 0x6f, 0x9f,
+ 0x5b, 0x1b, 0xf0, 0x68, 0xa4, 0xc1, 0x66, 0x3f, 0x4a, 0x3c, 0x3a, 0xb4,
+ 0xe6, 0xa3, 0xc7, 0x23, 0xee, 0x6b, 0xe3, 0xaa, 0x38, 0xe4, 0xee, 0xe3,
+ 0x77, 0x45, 0x4f, 0x7f, 0x98, 0xf9, 0xde, 0xfb, 0x91, 0x4f, 0x10, 0x47,
+ 0x28, 0x93, 0x36, 0x15, 0xc3, 0xba, 0xb6, 0x07, 0x5f, 0x5e, 0x0a, 0xc9,
+ 0x1b, 0xf7, 0x84, 0xe5, 0x7f, 0x6f, 0xe3, 0xf7, 0x30, 0xd3, 0xab, 0x69,
+ 0xb1, 0xfd, 0xc2, 0x1a, 0xd7, 0x0f, 0xbd, 0xd0, 0xee, 0xfa, 0x1d, 0xbe,
+ 0xe3, 0xdb, 0xb3, 0x85, 0xe7, 0x7c, 0xb6, 0x91, 0x5f, 0x4c, 0xae, 0x21,
+ 0x07, 0xdc, 0x64, 0x5d, 0xd0, 0x57, 0xcb, 0x01, 0x2f, 0x5f, 0x0f, 0xac,
+ 0xe7, 0x80, 0xc4, 0xd9, 0x0e, 0xa5, 0x1b, 0xf9, 0x28, 0x73, 0x1f, 0xc3,
+ 0xc3, 0x4e, 0xde, 0x23, 0xb7, 0x75, 0x90, 0xef, 0x42, 0xb6, 0xcf, 0x21,
+ 0x5e, 0x7a, 0xd6, 0x41, 0x8e, 0xeb, 0x20, 0xb7, 0x75, 0x90, 0xdb, 0x3a,
+ 0xc8, 0x6d, 0x9d, 0xa4, 0x97, 0x23, 0x8f, 0x78, 0x75, 0x7f, 0x7e, 0xe3,
+ 0x66, 0x7d, 0xa1, 0x08, 0x5f, 0x32, 0xc5, 0x73, 0x13, 0x7a, 0x36, 0xb5,
+ 0xc6, 0xdb, 0x9f, 0x5f, 0x13, 0xef, 0xf2, 0x6a, 0x36, 0xdf, 0x54, 0x75,
+ 0x43, 0xd1, 0x1f, 0x68, 0x71, 0xbf, 0x83, 0xf3, 0x7c, 0xc7, 0xaf, 0x21,
+ 0x2e, 0x51, 0x67, 0x88, 0x68, 0xa3, 0x55, 0x3d, 0xcd, 0x9a, 0x8c, 0xe8,
+ 0x7a, 0xfa, 0x16, 0xbc, 0xb3, 0xc5, 0xcd, 0x09, 0xa2, 0x62, 0xe8, 0xe9,
+ 0x56, 0xf2, 0x54, 0xd3, 0xd3, 0x6b, 0xbd, 0xb9, 0xf6, 0xb7, 0xb8, 0xb1,
+ 0x55, 0x2f, 0xdb, 0xa6, 0xce, 0x38, 0x41, 0xc5, 0xda, 0x7e, 0xff, 0xc5,
+ 0xf6, 0xe5, 0x6b, 0x85, 0x14, 0xbe, 0x67, 0x53, 0xf7, 0x62, 0x3e, 0xb6,
+ 0xeb, 0xfc, 0xd6, 0x2f, 0xc9, 0xef, 0x90, 0xc7, 0x6f, 0x97, 0xc7, 0x06,
+ 0xc7, 0xa9, 0xba, 0x30, 0x79, 0xed, 0xcf, 0xa7, 0xea, 0x7a, 0x58, 0x47,
+ 0x9d, 0xcd, 0xc0, 0xf5, 0x07, 0xa6, 0xb4, 0x8d, 0xee, 0x0e, 0xd9, 0xc1,
+ 0x75, 0xfd, 0x6f, 0xe2, 0x57, 0xb3, 0x66, 0x8f, 0xfa, 0x8e, 0xe6, 0xfa,
+ 0x8c, 0x90, 0xd2, 0x41, 0x33, 0xcd, 0x7d, 0xfd, 0x50, 0x9d, 0xa9, 0xa1,
+ 0xfe, 0xe5, 0x90, 0xc7, 0x4c, 0x0d, 0x6c, 0x8a, 0x9b, 0xfa, 0x48, 0x0b,
+ 0xeb, 0xaf, 0x43, 0x15, 0x1f, 0xf7, 0xb8, 0x5e, 0xa3, 0x1f, 0x67, 0x5d,
+ 0xcd, 0xc7, 0x33, 0xd9, 0xe0, 0xd6, 0xdb, 0x3e, 0x88, 0x2d, 0xb5, 0x34,
+ 0xd8, 0x92, 0xbf, 0x4f, 0xee, 0x9f, 0xd7, 0xd5, 0xcf, 0x43, 0x2c, 0x56,
+ 0x02, 0xdf, 0x47, 0x6a, 0xba, 0xc1, 0xb3, 0x2a, 0x9f, 0x85, 0x0e, 0xf2,
+ 0xdb, 0xc0, 0x4e, 0xd8, 0x51, 0xb5, 0x3a, 0xc4, 0x1a, 0x73, 0xdf, 0x67,
+ 0x54, 0x7e, 0xa9, 0xa7, 0xe7, 0x55, 0xfd, 0xc1, 0x5c, 0x51, 0x7f, 0x18,
+ 0x82, 0xae, 0x20, 0x06, 0x70, 0xda, 0x54, 0x4c, 0xa7, 0xe2, 0x85, 0x4a,
+ 0xe3, 0xf7, 0x97, 0xfb, 0x5b, 0x5d, 0x3e, 0xfc, 0x5d, 0x8b, 0xfb, 0x0d,
+ 0xe2, 0x8f, 0xa2, 0xcb, 0xdb, 0x7c, 0xff, 0xaf, 0x5b, 0xfc, 0xb3, 0x3b,
+ 0x85, 0x13, 0x43, 0xd0, 0x45, 0xe4, 0xe4, 0x6a, 0x3e, 0xc4, 0xbb, 0x4f,
+ 0xcc, 0x76, 0x2c, 0x1f, 0x8f, 0xbe, 0x13, 0xfe, 0xf8, 0x8e, 0x86, 0xf1,
+ 0x1d, 0x18, 0xff, 0x7b, 0x0d, 0xe3, 0x3b, 0x02, 0xe3, 0xa3, 0x0d, 0xe3,
+ 0xa3, 0x18, 0xff, 0x7c, 0xc3, 0xf8, 0x68, 0x60, 0x7c, 0x67, 0xc3, 0xf8,
+ 0x4e, 0x8c, 0x7f, 0xa1, 0x61, 0x3c, 0xfa, 0x4e, 0x34, 0x79, 0xdf, 0xc5,
+ 0x88, 0xb1, 0xfb, 0xbd, 0x5c, 0x1c, 0xd7, 0x72, 0xe3, 0xb7, 0x16, 0xea,
+ 0x5d, 0x17, 0x64, 0xe0, 0x9f, 0xa7, 0xa3, 0xbd, 0x66, 0x60, 0xaf, 0xf5,
+ 0x58, 0xc6, 0xd5, 0xc7, 0xa0, 0x2e, 0x12, 0x1f, 0x8a, 0x62, 0xd8, 0xd0,
+ 0x9d, 0x12, 0x74, 0xa8, 0xe4, 0xfb, 0x24, 0x9e, 0x83, 0xe2, 0x19, 0x53,
+ 0xd7, 0xf7, 0x86, 0xec, 0x45, 0x2f, 0x07, 0x7b, 0x9b, 0xb4, 0x03, 0x2f,
+ 0x7d, 0xcc, 0x94, 0x63, 0xae, 0xdd, 0x50, 0x7f, 0x39, 0xbf, 0x67, 0x3f,
+ 0xd4, 0x55, 0x6f, 0x9d, 0xa1, 0x15, 0xb8, 0x16, 0x5f, 0x51, 0xdb, 0x32,
+ 0xae, 0x02, 0xd7, 0x46, 0x6a, 0xb8, 0xf6, 0x59, 0x99, 0xaf, 0xe5, 0xdb,
+ 0xc3, 0x72, 0xc0, 0xd9, 0xc5, 0x33, 0x36, 0xc7, 0x32, 0xf2, 0xe1, 0xe4,
+ 0xdb, 0xbb, 0x6a, 0x7e, 0x92, 0x67, 0x3a, 0x96, 0x0e, 0x31, 0x87, 0xf2,
+ 0x6b, 0xb3, 0x53, 0xce, 0xcf, 0xb6, 0x42, 0x2e, 0xb0, 0x8d, 0x6b, 0xcd,
+ 0xb7, 0x39, 0x5f, 0x54, 0x0e, 0xb8, 0xe7, 0x1d, 0x6a, 0xf3, 0x16, 0x6b,
+ 0xf3, 0xc6, 0x3c, 0x7b, 0xa3, 0x0f, 0xae, 0xfb, 0xcb, 0x1c, 0xfc, 0xe5,
+ 0x18, 0x72, 0xee, 0x45, 0x67, 0xb5, 0xfa, 0xe8, 0xb5, 0xfa, 0xcb, 0xc6,
+ 0x3a, 0x73, 0xa3, 0xbf, 0xe4, 0x3a, 0x8d, 0xb5, 0xe5, 0x78, 0x03, 0xfe,
+ 0x53, 0x9f, 0x0e, 0x7b, 0x31, 0x35, 0xae, 0xa5, 0xc3, 0xb0, 0x47, 0x5d,
+ 0xc6, 0x94, 0xfe, 0xb2, 0xed, 0xe7, 0x96, 0xbb, 0x6b, 0xb9, 0x65, 0x3d,
+ 0x1f, 0x44, 0xec, 0x9a, 0xfc, 0xa4, 0x87, 0x8f, 0x8c, 0x91, 0xa7, 0xd0,
+ 0x7f, 0x0c, 0x3a, 0xc0, 0x67, 0xac, 0x97, 0xde, 0x2c, 0x9f, 0x32, 0x5d,
+ 0xff, 0xe4, 0xd6, 0xa6, 0x76, 0xab, 0xf8, 0x9f, 0xdf, 0x0b, 0x0a, 0xa9,
+ 0x76, 0x2f, 0xde, 0xbb, 0x12, 0xae, 0x2e, 0xcf, 0x4d, 0x75, 0xfd, 0x51,
+ 0xbc, 0xcb, 0xdc, 0xd4, 0x8c, 0x10, 0x43, 0xb3, 0x95, 0xcb, 0xbe, 0x5f,
+ 0xa4, 0x7f, 0x29, 0xa8, 0xef, 0x82, 0x2a, 0x0f, 0xc5, 0xb8, 0x45, 0xef,
+ 0x7d, 0x37, 0x0f, 0xcd, 0x56, 0xbe, 0xdd, 0xea, 0xe2, 0xe0, 0xe5, 0x72,
+ 0x96, 0x9f, 0x88, 0xb0, 0xae, 0xb7, 0xe8, 0x5c, 0x89, 0xd6, 0x95, 0x79,
+ 0xaf, 0xb1, 0x22, 0xef, 0x1d, 0xf5, 0xf2, 0xda, 0xcf, 0xa9, 0xbc, 0xd7,
+ 0xe5, 0x31, 0xf7, 0x12, 0xcc, 0xa3, 0x6c, 0x60, 0x21, 0xbf, 0xa9, 0x10,
+ 0x1f, 0x26, 0x94, 0xdf, 0xca, 0x4f, 0xdf, 0x09, 0x3e, 0x47, 0x57, 0xd1,
+ 0x9b, 0x8f, 0xda, 0x4f, 0xf8, 0x7b, 0x3f, 0x2c, 0x6e, 0xbd, 0x6e, 0x27,
+ 0x68, 0x61, 0x6e, 0x15, 0xf2, 0xf4, 0xe1, 0xbb, 0xde, 0x39, 0x53, 0x7f,
+ 0x9c, 0x9f, 0xc7, 0xd7, 0xbe, 0xbb, 0x16, 0x33, 0xcb, 0xea, 0x27, 0x1b,
+ 0x09, 0xc3, 0x90, 0x7b, 0xe6, 0x1a, 0xbe, 0x5b, 0x7c, 0x90, 0xf3, 0x11,
+ 0x8d, 0x7e, 0x8d, 0xdf, 0x4d, 0xf9, 0xad, 0x54, 0xb4, 0xbb, 0x7b, 0x6d,
+ 0xd8, 0x00, 0xcf, 0x2c, 0x07, 0xf1, 0x35, 0x2c, 0xf9, 0x39, 0x09, 0x47,
+ 0xd3, 0xfc, 0x06, 0x40, 0xff, 0xff, 0xba, 0xb7, 0xcf, 0x98, 0xec, 0x9f,
+ 0x71, 0x6b, 0x9e, 0xfa, 0x65, 0xcf, 0xc5, 0x1d, 0x00, 0x1f, 0x12, 0x47,
+ 0xfd, 0x9a, 0xa7, 0xee, 0x9e, 0x8b, 0x3b, 0xfa, 0xe1, 0x9d, 0x8b, 0xe3,
+ 0xfc, 0xa6, 0xec, 0x5a, 0xe5, 0x5c, 0x9c, 0x71, 0x95, 0xe7, 0xe2, 0xda,
+ 0x55, 0xcd, 0x93, 0xf3, 0xb8, 0x35, 0x4f, 0xb6, 0xbb, 0xfb, 0x59, 0x2b,
+ 0xe1, 0xd9, 0xb7, 0x01, 0x75, 0x06, 0xb9, 0xbb, 0xff, 0x47, 0x91, 0xa3,
+ 0x7c, 0x3d, 0xf2, 0xd1, 0xe7, 0x28, 0xdc, 0xcb, 0xaf, 0xb8, 0xdf, 0x77,
+ 0xe5, 0x5a, 0xea, 0x00, 0x1f, 0xac, 0xae, 0xb9, 0x5f, 0xd5, 0x35, 0xbf,
+ 0x13, 0x09, 0xd6, 0x35, 0xf5, 0x2b, 0x9c, 0x0d, 0xdb, 0xbf, 0x4a, 0x5d,
+ 0x33, 0x14, 0x38, 0x1b, 0x16, 0xf2, 0xce, 0x86, 0xb5, 0xdb, 0xc8, 0x25,
+ 0xbd, 0x3a, 0xa6, 0x7e, 0xd9, 0xb3, 0x61, 0xff, 0x19, 0xf9, 0xe0, 0x75,
+ 0xcc, 0x15, 0x67, 0xc3, 0xe0, 0xeb, 0x36, 0x48, 0xfc, 0x9a, 0xf2, 0x9e,
+ 0x0f, 0x92, 0xf3, 0xf0, 0xbc, 0x7e, 0x13, 0xf6, 0x1c, 0x92, 0x5d, 0x51,
+ 0xea, 0x27, 0xcf, 0x36, 0xf6, 0xc2, 0x16, 0x70, 0xad, 0xb0, 0x9d, 0xa4,
+ 0x8c, 0xb4, 0x91, 0xde, 0xe5, 0xe7, 0x10, 0xea, 0xe7, 0x71, 0xc3, 0xb5,
+ 0xf3, 0xb8, 0x47, 0xa0, 0x37, 0xfa, 0x4c, 0x58, 0x16, 0x02, 0x3a, 0x35,
+ 0x85, 0x78, 0x4f, 0x9f, 0xb3, 0xbc, 0xe7, 0xfc, 0x9f, 0x8a, 0x28, 0x30,
+ 0x8f, 0x67, 0x78, 0xdb, 0xc4, 0x98, 0x73, 0xbf, 0x59, 0xba, 0xff, 0x57,
+ 0x12, 0xc3, 0x18, 0x9e, 0xf1, 0x0c, 0xc9, 0x01, 0x55, 0xb3, 0xf0, 0x75,
+ 0x79, 0xc7, 0x5a, 0x69, 0x59, 0x9f, 0xa9, 0xb7, 0xa3, 0xab, 0xf8, 0x7d,
+ 0xc4, 0x91, 0x33, 0xd4, 0xe7, 0x5b, 0x25, 0xe7, 0xd5, 0x83, 0x0a, 0x95,
+ 0x6d, 0x5e, 0x7e, 0xa1, 0xbe, 0xed, 0x80, 0x97, 0xdd, 0x9e, 0x0f, 0xc6,
+ 0xb5, 0xd4, 0x4d, 0x9f, 0x87, 0x35, 0x4e, 0xca, 0xd0, 0xf4, 0x96, 0xd8,
+ 0x38, 0xf0, 0x6e, 0x4c, 0xad, 0x79, 0x2d, 0x3c, 0xd7, 0x2e, 0xf1, 0xbd,
+ 0xf1, 0x6a, 0xf9, 0xee, 0xc7, 0xc7, 0x8f, 0x62, 0x7f, 0xdd, 0xd0, 0x8f,
+ 0x87, 0x25, 0x77, 0xe2, 0x66, 0x19, 0x9a, 0x4d, 0x80, 0x9e, 0x1f, 0x56,
+ 0x0b, 0x29, 0xc4, 0xd2, 0x4f, 0xf0, 0xdc, 0x18, 0x30, 0x14, 0x7c, 0x7b,
+ 0x66, 0xc5, 0x77, 0xec, 0xe0, 0x59, 0xb3, 0x64, 0xed, 0xec, 0xd0, 0x53,
+ 0x15, 0x09, 0x77, 0x90, 0xe6, 0x99, 0xfa, 0xd9, 0xef, 0xc5, 0xca, 0x0e,
+ 0xe5, 0xdb, 0x9e, 0xac, 0x2c, 0xab, 0xfd, 0x28, 0x19, 0x4e, 0x94, 0x9f,
+ 0x04, 0x2f, 0x5e, 0x51, 0xfe, 0xed, 0x88, 0x23, 0x37, 0x19, 0x42, 0x79,
+ 0x88, 0x06, 0x1e, 0xa8, 0x33, 0x1c, 0xee, 0xf7, 0xfd, 0x2e, 0x25, 0x57,
+ 0x17, 0x2b, 0x76, 0x06, 0xce, 0x60, 0xd4, 0x65, 0xeb, 0x9e, 0xcd, 0x70,
+ 0x65, 0xe1, 0x9e, 0x1f, 0x21, 0x3f, 0x97, 0x0e, 0xed, 0xb2, 0xdd, 0xf3,
+ 0x23, 0x3d, 0x73, 0xec, 0xeb, 0x6c, 0xf0, 0x7d, 0x61, 0xe8, 0x00, 0xcf,
+ 0x1d, 0xf1, 0xcc, 0x37, 0x69, 0x56, 0xb5, 0x8e, 0x55, 0xbf, 0x6d, 0x5f,
+ 0x5b, 0xcd, 0xd5, 0x5d, 0xb3, 0x5b, 0xad, 0x79, 0x9d, 0x87, 0x59, 0xfe,
+ 0x59, 0xef, 0x94, 0xf6, 0xff, 0xd4, 0x5d, 0x7b, 0x6c, 0x1b, 0xf7, 0x7d,
+ 0xff, 0xf2, 0x48, 0x3d, 0xac, 0xe7, 0x49, 0xa6, 0x64, 0x5a, 0x52, 0x94,
+ 0x3b, 0xe9, 0x64, 0x29, 0xb1, 0x12, 0x70, 0x9e, 0xba, 0x0a, 0x88, 0x9a,
+ 0xb0, 0x24, 0xfd, 0x58, 0x10, 0x0c, 0xb4, 0xad, 0x64, 0xee, 0x92, 0xad,
+ 0x0e, 0x25, 0xa7, 0x1d, 0x30, 0x60, 0x6e, 0xd6, 0x02, 0x69, 0x07, 0xc7,
+ 0x0c, 0x65, 0x27, 0xc6, 0xaa, 0x88, 0x4c, 0xcc, 0x6a, 0x1d, 0xb0, 0x62,
+ 0x1c, 0xa5, 0x38, 0x69, 0xa7, 0x80, 0x69, 0xda, 0x04, 0xc5, 0xfe, 0xb1,
+ 0x26, 0x3b, 0x7b, 0x61, 0x7f, 0x04, 0xdb, 0x80, 0x1a, 0x5b, 0x81, 0xba,
+ 0x76, 0x8a, 0x65, 0x1b, 0xe0, 0x34, 0xdb, 0xb0, 0x75, 0x58, 0x0b, 0xee,
+ 0xfb, 0xf9, 0x3d, 0xc8, 0x23, 0x79, 0xd4, 0xc3, 0x71, 0x06, 0x4c, 0x80,
+ 0x40, 0xde, 0xf1, 0x77, 0x77, 0xbf, 0xdf, 0xf7, 0xf7, 0x7d, 0xbf, 0x6e,
+ 0x2e, 0x33, 0x1e, 0xf2, 0x33, 0x7e, 0xcf, 0x15, 0x61, 0x5f, 0x37, 0xd2,
+ 0xe1, 0x36, 0x83, 0x67, 0xa4, 0x0e, 0x9e, 0xd5, 0x34, 0xc1, 0xf6, 0x78,
+ 0x99, 0x77, 0x4b, 0xd8, 0xc9, 0xf3, 0xc8, 0x63, 0xd7, 0x39, 0x0e, 0x12,
+ 0x76, 0x65, 0x1a, 0x5a, 0x72, 0xe7, 0x37, 0x54, 0x60, 0x77, 0xb2, 0x0c,
+ 0xbb, 0x3d, 0xff, 0x8f, 0x60, 0x77, 0x4d, 0xe8, 0xbf, 0xdf, 0x2e, 0x22,
+ 0x6f, 0x4d, 0xeb, 0x00, 0xba, 0x6e, 0x09, 0x70, 0x04, 0x3f, 0xb5, 0xf3,
+ 0xeb, 0x04, 0x9e, 0x8a, 0xbc, 0xe2, 0x52, 0xe9, 0x3b, 0xe1, 0xb2, 0x9f,
+ 0x92, 0xed, 0x12, 0xd8, 0x27, 0xf0, 0xe7, 0x35, 0x96, 0x91, 0x47, 0x6f,
+ 0x4b, 0x46, 0x42, 0x57, 0xaa, 0xb5, 0x4f, 0x7e, 0xbb, 0xcb, 0x6d, 0x9f,
+ 0x1c, 0xdd, 0xa1, 0x7d, 0x72, 0x5a, 0xda, 0x27, 0xa9, 0xed, 0xdb, 0x27,
+ 0x03, 0x75, 0x79, 0x5d, 0x95, 0xf5, 0xec, 0xdc, 0x3e, 0x31, 0x36, 0xb5,
+ 0x4f, 0x46, 0x5d, 0xbe, 0x18, 0xcc, 0xf7, 0x57, 0x29, 0x75, 0x0c, 0x3c,
+ 0x4e, 0xc3, 0x19, 0x30, 0x3e, 0x56, 0xe3, 0x17, 0xfe, 0x38, 0x61, 0xfd,
+ 0xd7, 0xff, 0xc7, 0xb0, 0x1e, 0xac, 0xf3, 0x79, 0x57, 0xd6, 0x03, 0x21,
+ 0xfe, 0x51, 0x60, 0x3d, 0xd8, 0xd0, 0x77, 0xda, 0x38, 0x67, 0xb1, 0xda,
+ 0x77, 0x3a, 0x62, 0x34, 0xe2, 0xed, 0x7f, 0xe4, 0xf2, 0xa9, 0xba, 0xf9,
+ 0x3b, 0x68, 0x8a, 0x7c, 0x47, 0xc7, 0xf5, 0xb3, 0x40, 0x4b, 0x76, 0x2a,
+ 0x45, 0xb0, 0x99, 0xf0, 0xbc, 0x90, 0xa0, 0xb5, 0x1a, 0x7d, 0x8b, 0x9f,
+ 0xc7, 0xeb, 0x7b, 0xf5, 0x09, 0x21, 0xa7, 0xa4, 0xff, 0x01, 0xe3, 0x27,
+ 0x7c, 0xf3, 0x62, 0xac, 0xcc, 0x6f, 0x52, 0xfe, 0x08, 0xa5, 0xfb, 0x37,
+ 0xf2, 0x43, 0xd4, 0xcb, 0xbc, 0x9d, 0xd9, 0x0a, 0x9a, 0xc6, 0xef, 0xe6,
+ 0x7d, 0x09, 0x55, 0xd9, 0x5a, 0xe0, 0x9f, 0xa7, 0x59, 0x2f, 0x18, 0x29,
+ 0xeb, 0x04, 0xd5, 0x7b, 0x73, 0x4e, 0xd8, 0x74, 0x9a, 0x77, 0x26, 0x64,
+ 0xee, 0xa9, 0x38, 0x0f, 0x3d, 0x4d, 0xf3, 0xce, 0x5a, 0x3d, 0xf8, 0x6e,
+ 0x0f, 0xbc, 0xf0, 0xca, 0x69, 0x2a, 0xef, 0x9d, 0x85, 0x9c, 0xf3, 0xb8,
+ 0xe7, 0xde, 0x95, 0x6b, 0xc2, 0x52, 0x95, 0xb1, 0xf2, 0xfa, 0xb8, 0x58,
+ 0xd7, 0x0f, 0x8e, 0x44, 0x51, 0xfb, 0x56, 0xae, 0x17, 0xab, 0xad, 0x77,
+ 0x82, 0x1c, 0xd0, 0x74, 0xa8, 0x6b, 0xa2, 0x01, 0x8b, 0x61, 0x8f, 0x7a,
+ 0x27, 0xb7, 0x2c, 0xc1, 0x75, 0xb5, 0xb0, 0xa8, 0xc8, 0x91, 0xf3, 0x4a,
+ 0x8e, 0x14, 0x5c, 0x7c, 0xbc, 0x5e, 0x6f, 0xef, 0xf5, 0xd0, 0xdb, 0xbd,
+ 0x6a, 0x9e, 0x30, 0xa7, 0x67, 0x58, 0x0f, 0xb9, 0x1f, 0x7a, 0x88, 0x89,
+ 0xba, 0x25, 0xa9, 0x8b, 0xe0, 0x77, 0x96, 0x35, 0xaf, 0x86, 0x18, 0x57,
+ 0x8e, 0xd0, 0x53, 0xac, 0x6b, 0x5f, 0xa2, 0x7b, 0x94, 0x7d, 0x16, 0x71,
+ 0xe5, 0x99, 0x22, 0x8f, 0xdf, 0x47, 0xa9, 0x27, 0xec, 0x89, 0x08, 0x1d,
+ 0xa1, 0x53, 0x22, 0x67, 0x06, 0xf1, 0x3d, 0xe4, 0x1c, 0xdc, 0x2b, 0x9e,
+ 0x2f, 0x7d, 0x19, 0x77, 0x22, 0xa7, 0x6e, 0xfb, 0xf9, 0xfb, 0xba, 0x56,
+ 0x2f, 0x2a, 0x9e, 0xb9, 0xaa, 0x68, 0x4a, 0x9c, 0xe3, 0xeb, 0x9f, 0x31,
+ 0xea, 0xaf, 0x8f, 0x18, 0xf1, 0x62, 0xdc, 0x88, 0xae, 0x60, 0xdc, 0x33,
+ 0x46, 0xac, 0x08, 0x1b, 0x52, 0xe3, 0x88, 0x1d, 0x06, 0xbd, 0x6d, 0xd0,
+ 0xd6, 0xb1, 0x88, 0x02, 0xd5, 0xd4, 0x49, 0x6c, 0x63, 0xde, 0x87, 0xaa,
+ 0xe6, 0xad, 0xe1, 0x8b, 0xef, 0xf0, 0xf7, 0x44, 0x18, 0xa6, 0x5a, 0xaf,
+ 0x6d, 0x83, 0x7f, 0x7d, 0x22, 0x45, 0x9b, 0xe9, 0xb5, 0x76, 0x9d, 0x5e,
+ 0x5b, 0xd8, 0x72, 0xde, 0x1f, 0x95, 0xc6, 0x65, 0x3d, 0xa2, 0xdf, 0x11,
+ 0xfa, 0x2b, 0xcf, 0xbb, 0x4a, 0xb7, 0xad, 0xc1, 0x29, 0x8c, 0xd1, 0x7e,
+ 0x70, 0xed, 0x07, 0xeb, 0x52, 0xf9, 0xc0, 0x3a, 0x3f, 0xa1, 0x0d, 0xf5,
+ 0x5e, 0xa6, 0xcc, 0x6b, 0x85, 0x8d, 0xb5, 0xce, 0xf3, 0x83, 0xbd, 0xf5,
+ 0xa0, 0x98, 0x23, 0xdb, 0x5b, 0x56, 0x8c, 0xa4, 0xaf, 0x7b, 0xbe, 0x58,
+ 0x55, 0xff, 0xe9, 0x51, 0x07, 0x39, 0xe2, 0x51, 0x07, 0xe9, 0xa6, 0xb5,
+ 0x80, 0x8b, 0xd6, 0x42, 0x2e, 0xbd, 0x6d, 0x88, 0xed, 0x96, 0x0e, 0xe6,
+ 0x21, 0xb0, 0x5b, 0xda, 0xc8, 0xff, 0xb2, 0xdb, 0x6e, 0xa9, 0xad, 0x45,
+ 0x07, 0xdd, 0x41, 0x37, 0x93, 0x36, 0x4c, 0x3c, 0x57, 0xae, 0x63, 0xe7,
+ 0x75, 0x57, 0x6a, 0x0e, 0x57, 0xea, 0xea, 0x23, 0xbd, 0xe6, 0x3b, 0x5c,
+ 0x37, 0x5f, 0xc8, 0xaf, 0x48, 0x43, 0x9d, 0xce, 0xcb, 0xae, 0xba, 0x53,
+ 0xf3, 0xab, 0xe5, 0x67, 0x78, 0xd6, 0x88, 0xf0, 0x79, 0xa7, 0xca, 0xbc,
+ 0x6c, 0x5a, 0xce, 0x37, 0x53, 0x6d, 0x67, 0xf8, 0x97, 0x48, 0xc1, 0xce,
+ 0x9b, 0xb7, 0xef, 0xcc, 0x7f, 0xd6, 0x5e, 0x23, 0x77, 0xdf, 0x33, 0xa5,
+ 0x5f, 0xac, 0x49, 0xe5, 0x61, 0xf7, 0x29, 0x7b, 0x6f, 0x2b, 0x7c, 0xc7,
+ 0xb9, 0x26, 0xe5, 0x4b, 0xb4, 0xad, 0x3c, 0x01, 0xcf, 0x8f, 0x9d, 0x68,
+ 0x72, 0x4c, 0x15, 0xcb, 0x42, 0xbc, 0x0a, 0x78, 0xaf, 0xef, 0x0f, 0x9e,
+ 0xbd, 0x9d, 0x3d, 0xb3, 0xea, 0xf6, 0x4c, 0xe2, 0x15, 0x6c, 0x2d, 0xe4,
+ 0x17, 0x4f, 0xd6, 0xe4, 0x78, 0x7f, 0x14, 0x58, 0x74, 0x79, 0xe4, 0x3d,
+ 0x23, 0x6f, 0xb9, 0xd1, 0x3c, 0xaf, 0xbb, 0xf4, 0x72, 0xcc, 0xb7, 0x54,
+ 0x7a, 0x23, 0x3c, 0x20, 0x65, 0x71, 0xd1, 0x5b, 0x47, 0x32, 0xb7, 0x3d,
+ 0xbf, 0x5a, 0xd9, 0xbb, 0x77, 0x9b, 0xb2, 0x57, 0xf4, 0xf4, 0xf0, 0x1d,
+ 0x14, 0x3c, 0xa0, 0x83, 0x56, 0x72, 0xc8, 0xbf, 0xfe, 0x05, 0xd0, 0x3c,
+ 0xf3, 0x59, 0x57, 0x4d, 0x9a, 0xf7, 0x3e, 0x96, 0x63, 0x2a, 0x81, 0x19,
+ 0xc4, 0xfe, 0x90, 0x5b, 0xd2, 0xcb, 0xbc, 0x07, 0xe3, 0xc7, 0xac, 0xab,
+ 0xf0, 0xf7, 0x2a, 0xff, 0x53, 0x5c, 0xc9, 0x97, 0x83, 0xdb, 0x88, 0xad,
+ 0xec, 0x8c, 0x4f, 0xdb, 0xd6, 0x3a, 0x21, 0xee, 0x83, 0x7c, 0xe1, 0xfb,
+ 0xba, 0xa8, 0xeb, 0x33, 0x2d, 0x2d, 0xce, 0x97, 0x7a, 0x64, 0x2c, 0x0a,
+ 0xbf, 0x75, 0xd0, 0x2b, 0x39, 0xe4, 0x72, 0xe3, 0xb7, 0xdf, 0xe0, 0xdf,
+ 0xbc, 0x78, 0x94, 0xce, 0x45, 0x87, 0x2e, 0x27, 0xf7, 0x27, 0x4f, 0xb0,
+ 0x95, 0x4a, 0xf4, 0xb7, 0xe1, 0x5f, 0x94, 0xf1, 0x8c, 0xe2, 0x9d, 0x8e,
+ 0xd5, 0x78, 0xf9, 0x0b, 0xdf, 0xec, 0xb9, 0xdd, 0xdc, 0xc8, 0x2f, 0x6c,
+ 0xcb, 0x5f, 0x88, 0x38, 0xff, 0x76, 0x62, 0x26, 0x3a, 0x36, 0x3c, 0x25,
+ 0x6a, 0x4e, 0xdd, 0x78, 0x70, 0x67, 0xe2, 0xc3, 0xc0, 0x87, 0xe1, 0x3a,
+ 0x5e, 0xf5, 0xd1, 0xfd, 0xfd, 0xb5, 0x70, 0x6d, 0xf3, 0xf4, 0x55, 0x79,
+ 0xc7, 0x81, 0x11, 0xf3, 0x87, 0x9f, 0xfa, 0x21, 0x9a, 0xbf, 0x08, 0x1c,
+ 0x36, 0x18, 0xdb, 0x46, 0x69, 0x21, 0x88, 0xba, 0x22, 0x51, 0x9b, 0xa3,
+ 0xe2, 0x86, 0xb2, 0x56, 0x68, 0x5e, 0xd4, 0x40, 0x8e, 0x85, 0x6e, 0xf2,
+ 0xbc, 0xe7, 0x8b, 0x29, 0x3a, 0xc5, 0x32, 0xf6, 0xd4, 0x4a, 0x45, 0x77,
+ 0xaf, 0xaf, 0x83, 0xac, 0xc6, 0xf1, 0x9b, 0x02, 0xc7, 0x87, 0x36, 0xc5,
+ 0xf1, 0xc3, 0x65, 0x1c, 0xff, 0x44, 0xaf, 0xc4, 0xe7, 0x67, 0xf9, 0x5e,
+ 0x5d, 0x74, 0x50, 0xdc, 0x37, 0xc5, 0xdf, 0xdb, 0xe9, 0xa0, 0xec, 0x61,
+ 0xc1, 0xcf, 0x66, 0x1e, 0x9f, 0x49, 0xd1, 0x53, 0x17, 0x53, 0xbe, 0xb8,
+ 0xa8, 0x5f, 0x70, 0xf7, 0xe8, 0xd0, 0xd7, 0x63, 0x5c, 0x23, 0xfc, 0xd7,
+ 0x7c, 0x49, 0xd6, 0x5c, 0xe5, 0x25, 0x7f, 0xa2, 0x77, 0xc3, 0x83, 0x35,
+ 0xf8, 0x5f, 0x6d, 0x3b, 0x9e, 0x56, 0x32, 0xf0, 0xd8, 0x26, 0x7e, 0x8d,
+ 0x7a, 0xbc, 0xec, 0xf1, 0xd0, 0x87, 0x7f, 0xbd, 0x57, 0xc6, 0xa9, 0x36,
+ 0xf3, 0x6b, 0xb8, 0x71, 0xb4, 0x2a, 0x6e, 0xcf, 0x7c, 0xff, 0xbf, 0x55,
+ 0x1c, 0xfd, 0xa5, 0x5e, 0x29, 0x2f, 0x50, 0x1f, 0x98, 0x60, 0x38, 0x9c,
+ 0x64, 0x5d, 0x65, 0x90, 0x9a, 0x5f, 0xd6, 0x6b, 0x1d, 0x14, 0xfc, 0xd6,
+ 0xed, 0xa7, 0x39, 0xa7, 0x6a, 0xbb, 0xd3, 0xae, 0x35, 0x9d, 0x13, 0x36,
+ 0x4e, 0x63, 0x7a, 0x6b, 0x9c, 0x73, 0x35, 0x54, 0x23, 0x13, 0x6a, 0xf1,
+ 0x0d, 0xbd, 0x4f, 0xb0, 0xbf, 0x64, 0x48, 0x3d, 0x78, 0x9a, 0xf5, 0xdb,
+ 0x9d, 0xc6, 0x8b, 0x3e, 0xaa, 0x8e, 0x58, 0xdb, 0x53, 0xa3, 0xf6, 0x3b,
+ 0xf6, 0x41, 0xda, 0x1c, 0xc9, 0x57, 0x1f, 0x12, 0xbc, 0xe0, 0xdc, 0x64,
+ 0x89, 0x62, 0xe1, 0x4e, 0x4a, 0x4e, 0xf2, 0xb3, 0xa7, 0x1d, 0xb6, 0xbd,
+ 0xfc, 0x94, 0x62, 0xfa, 0x4d, 0x4e, 0xee, 0x52, 0xfa, 0xa2, 0xf6, 0xa7,
+ 0xb7, 0xa8, 0x3c, 0x87, 0x67, 0x45, 0x5c, 0x52, 0xf6, 0xc6, 0xe0, 0xef,
+ 0x2b, 0xfa, 0xde, 0xcf, 0x8a, 0xf8, 0x68, 0xf2, 0x62, 0xb3, 0x1a, 0xd7,
+ 0xee, 0x1a, 0x87, 0x31, 0xed, 0x6a, 0x2c, 0xee, 0xa9, 0x75, 0x8a, 0x56,
+ 0xc5, 0x6f, 0x1f, 0x11, 0x75, 0x60, 0xb2, 0x56, 0x0f, 0xbf, 0x9f, 0xa6,
+ 0xb9, 0xf2, 0x5a, 0xda, 0x79, 0xec, 0xcf, 0x4a, 0x11, 0x61, 0xcb, 0xb5,
+ 0xb3, 0xce, 0x8b, 0x79, 0xd7, 0xcf, 0x09, 0x6b, 0xf1, 0x8b, 0xf8, 0x10,
+ 0x7f, 0x57, 0xcf, 0x39, 0x59, 0x9e, 0x13, 0x72, 0x34, 0xec, 0x90, 0xbc,
+ 0x97, 0x1e, 0xd7, 0xee, 0x1a, 0xa7, 0x79, 0x85, 0x8e, 0x3f, 0xfc, 0x80,
+ 0xe7, 0xf1, 0x37, 0x2a, 0x87, 0xd7, 0x14, 0xf1, 0x53, 0x99, 0xa3, 0xa1,
+ 0xbf, 0xc3, 0xbf, 0x8c, 0x9c, 0x0a, 0xe4, 0x49, 0xb8, 0xf9, 0x8d, 0x5c,
+ 0x6f, 0x00, 0xb2, 0xa8, 0x88, 0xb8, 0x29, 0xe2, 0x15, 0x8d, 0x74, 0xe7,
+ 0xbd, 0xc8, 0xcd, 0xdf, 0x81, 0x0e, 0xba, 0x1d, 0xfa, 0xb3, 0x3c, 0xe8,
+ 0xcf, 0xfd, 0x7c, 0xd4, 0xc1, 0xa1, 0x1e, 0x2e, 0x35, 0x61, 0x50, 0x89,
+ 0x6d, 0x05, 0x83, 0xf2, 0xa6, 0x8f, 0x9e, 0x72, 0xec, 0xf0, 0x0a, 0xc9,
+ 0x9a, 0xc9, 0xd8, 0xa2, 0x3d, 0xb1, 0x4e, 0xfb, 0x45, 0xcd, 0x38, 0x7a,
+ 0x1f, 0xe4, 0x59, 0x06, 0x9f, 0xa4, 0x09, 0xb6, 0x8f, 0xd8, 0xfe, 0x9c,
+ 0x45, 0xbc, 0x45, 0xef, 0x0b, 0x6a, 0xe0, 0xf1, 0x39, 0xc1, 0x70, 0x7a,
+ 0x6c, 0x37, 0xb5, 0x45, 0xf8, 0x9e, 0x13, 0xe0, 0x4f, 0xe8, 0xe7, 0x45,
+ 0x51, 0xb6, 0x93, 0x60, 0xb3, 0x9e, 0x9c, 0xb5, 0xcd, 0x3c, 0x19, 0x3c,
+ 0x16, 0xb6, 0x2b, 0xee, 0x83, 0xeb, 0x23, 0x66, 0x13, 0xd5, 0xd6, 0xe4,
+ 0x3e, 0x2b, 0xea, 0x14, 0xdf, 0x0d, 0xdf, 0x47, 0x46, 0x3f, 0xf8, 0x15,
+ 0xf6, 0xed, 0x5e, 0x15, 0x27, 0x3a, 0xcb, 0xdf, 0xc7, 0xd5, 0xf7, 0xaf,
+ 0x88, 0xfd, 0x94, 0xdf, 0x35, 0x7e, 0xe3, 0xef, 0x5f, 0x5a, 0xc8, 0xf9,
+ 0xa1, 0xca, 0x59, 0xa9, 0xca, 0x05, 0x09, 0x8d, 0x1a, 0x5f, 0xa1, 0xd3,
+ 0x2b, 0x9b, 0xf9, 0x5f, 0xbc, 0x6a, 0x5d, 0xbb, 0xb7, 0x59, 0xeb, 0xfa,
+ 0x07, 0xbb, 0x65, 0x6d, 0x99, 0x7b, 0x2e, 0xff, 0xc9, 0x73, 0xf1, 0xd2,
+ 0xc9, 0xea, 0xf4, 0x44, 0x5e, 0x6f, 0x89, 0xfe, 0x29, 0xfc, 0x49, 0xba,
+ 0x1e, 0x0c, 0xa9, 0x9c, 0x25, 0xe4, 0x28, 0xdd, 0xa7, 0xf0, 0x5a, 0xf3,
+ 0x7e, 0xf2, 0xe0, 0xfd, 0x8f, 0x89, 0x5c, 0x4d, 0x29, 0x3b, 0x06, 0x15,
+ 0x3c, 0x00, 0xb3, 0x90, 0x0b, 0x66, 0x7d, 0x2e, 0x98, 0x19, 0xea, 0x7b,
+ 0xa7, 0x38, 0x3e, 0xbd, 0xf2, 0x99, 0x6e, 0x59, 0x2f, 0x8e, 0x58, 0xe2,
+ 0xbc, 0xfa, 0xbe, 0xd5, 0x7a, 0x7f, 0xce, 0x6b, 0x15, 0xfe, 0x26, 0xd7,
+ 0x5a, 0x5f, 0x27, 0x72, 0x5a, 0x82, 0xf5, 0x30, 0xf8, 0x8e, 0xeb, 0x3c,
+ 0xe6, 0x38, 0xe6, 0x9a, 0xe3, 0x88, 0x6b, 0x8e, 0x77, 0x37, 0x98, 0x23,
+ 0xf3, 0xf8, 0xe2, 0x69, 0xfe, 0xbf, 0xdd, 0xb9, 0xca, 0x79, 0xce, 0x0b,
+ 0x78, 0xb6, 0x53, 0x3a, 0x18, 0x52, 0xb2, 0xe3, 0xfb, 0xaa, 0x16, 0xdd,
+ 0x6b, 0xce, 0xff, 0x40, 0x8d, 0xf7, 0xcd, 0x8d, 0xab, 0xee, 0xfa, 0xe3,
+ 0x97, 0x28, 0x26, 0xeb, 0xc8, 0x15, 0x6d, 0x7f, 0xb5, 0x81, 0x1f, 0xfa,
+ 0x41, 0xa1, 0xff, 0xcc, 0xcb, 0x78, 0xd0, 0x80, 0xec, 0xbf, 0x16, 0xa0,
+ 0xd5, 0x72, 0x2d, 0xaf, 0x5f, 0xd5, 0xee, 0xdc, 0x1f, 0xbc, 0xb3, 0x75,
+ 0xbc, 0x38, 0xff, 0x88, 0xf0, 0xe5, 0xc9, 0xf8, 0x51, 0x42, 0xd5, 0x23,
+ 0xdb, 0x16, 0x72, 0x03, 0x0a, 0x6b, 0xf0, 0xbf, 0x36, 0xaa, 0xdd, 0xc5,
+ 0xb5, 0xf0, 0x03, 0x6a, 0x3b, 0xfe, 0x84, 0xe0, 0x89, 0xd2, 0x3f, 0x26,
+ 0xeb, 0x6f, 0x0b, 0x6b, 0x27, 0x45, 0xcd, 0x6b, 0x54, 0xd5, 0xf1, 0x26,
+ 0xa9, 0x43, 0xe8, 0xb9, 0xb7, 0x5f, 0x7f, 0xfb, 0x5c, 0x70, 0xe7, 0xf5,
+ 0xb7, 0xee, 0x6b, 0x76, 0x56, 0x7f, 0x6b, 0xf2, 0xda, 0x8d, 0x65, 0x59,
+ 0x7f, 0x5b, 0x1d, 0x93, 0x91, 0xfe, 0xc0, 0xa4, 0x4b, 0x7f, 0x90, 0xfa,
+ 0xfa, 0x6f, 0xb9, 0xf2, 0xb7, 0x65, 0x6d, 0x6d, 0xa1, 0xac, 0xb3, 0xca,
+ 0xda, 0x5a, 0x99, 0xef, 0xed, 0xee, 0x03, 0x23, 0x63, 0x3f, 0xf2, 0x39,
+ 0x9d, 0x35, 0xb1, 0x1f, 0x59, 0x53, 0x6b, 0x19, 0x8d, 0x6c, 0x38, 0xd1,
+ 0xe7, 0xa2, 0x8f, 0xba, 0x22, 0x8c, 0xbb, 0xed, 0x0d, 0xfa, 0x21, 0x44,
+ 0x1a, 0xf4, 0x43, 0x70, 0xf3, 0x7e, 0xb7, 0x8e, 0x05, 0x9d, 0x18, 0xb2,
+ 0x11, 0xba, 0x30, 0xfa, 0x19, 0x84, 0xe9, 0x74, 0x59, 0xf7, 0xbc, 0x8f,
+ 0x12, 0x4a, 0xf7, 0x3c, 0xbd, 0xa2, 0xf9, 0xd1, 0x48, 0x0d, 0x3f, 0xf2,
+ 0xd2, 0x45, 0x6d, 0x95, 0xe7, 0xa3, 0xe9, 0x35, 0xe5, 0xa2, 0xd7, 0x94,
+ 0x07, 0xbd, 0x8a, 0x67, 0x34, 0x98, 0xf7, 0xf7, 0xd5, 0x35, 0xf8, 0x4f,
+ 0x84, 0xd0, 0xb3, 0x85, 0x79, 0x6a, 0x50, 0xe9, 0x7f, 0x2e, 0x7a, 0x3d,
+ 0xc5, 0xf4, 0xaa, 0xcf, 0x63, 0xbe, 0x0d, 0x73, 0x41, 0x95, 0xce, 0x38,
+ 0xe8, 0x3b, 0x74, 0xf1, 0x1b, 0x22, 0x4f, 0xaa, 0xda, 0x5e, 0xd4, 0xfa,
+ 0xc4, 0x3e, 0x41, 0x4b, 0xd7, 0xfd, 0xc8, 0x5b, 0xd1, 0xe7, 0x4c, 0xe5,
+ 0x27, 0xd3, 0xb0, 0x68, 0xae, 0xd2, 0x39, 0x2a, 0xfa, 0x86, 0xc8, 0xf1,
+ 0x75, 0xcd, 0xed, 0x43, 0x9e, 0x9b, 0x3e, 0xaf, 0x65, 0xe6, 0xb5, 0x2a,
+ 0x7f, 0xc6, 0xe5, 0xaa, 0x9e, 0x83, 0xf0, 0x1d, 0x75, 0x26, 0x0c, 0x27,
+ 0x2e, 0x72, 0x4c, 0x7b, 0x1c, 0xf8, 0xc9, 0xa2, 0x4c, 0xfb, 0x3d, 0x09,
+ 0xe4, 0x33, 0xf7, 0x2c, 0x59, 0x74, 0x3c, 0x73, 0xff, 0x5d, 0x12, 0x57,
+ 0xce, 0x8a, 0x3e, 0x92, 0xe8, 0x67, 0x16, 0x63, 0xf9, 0x1c, 0xf5, 0x4f,
+ 0xd3, 0xf9, 0x62, 0x0b, 0x15, 0x58, 0xbb, 0xf7, 0x3b, 0x79, 0xe1, 0xeb,
+ 0x63, 0x9e, 0x94, 0x45, 0x2f, 0x51, 0x63, 0xb9, 0x99, 0xef, 0xdb, 0x4f,
+ 0xab, 0xb9, 0x31, 0xd1, 0x13, 0x4a, 0xf6, 0x17, 0xc1, 0x58, 0x1f, 0xf5,
+ 0x3a, 0x07, 0xfb, 0xa8, 0xed, 0xb3, 0x22, 0xc7, 0xb2, 0x90, 0x3d, 0x2b,
+ 0x3f, 0xf3, 0x0f, 0xa8, 0x67, 0xf0, 0xf3, 0x8a, 0x7f, 0x4a, 0x91, 0x5e,
+ 0xcb, 0x65, 0xcb, 0xb9, 0xff, 0xbc, 0xf5, 0x95, 0xa3, 0x3b, 0xd2, 0x57,
+ 0x52, 0x89, 0x8a, 0xbe, 0xe2, 0xbe, 0x77, 0x39, 0x07, 0xa6, 0x5f, 0xf6,
+ 0x7b, 0x00, 0x0c, 0xda, 0xa1, 0x8b, 0x25, 0x00, 0x4b, 0x63, 0xc6, 0x0e,
+ 0x45, 0xfd, 0x53, 0xb4, 0x50, 0x1c, 0x32, 0x92, 0x59, 0xe8, 0xcc, 0xfc,
+ 0x99, 0x8f, 0xee, 0x91, 0x3e, 0x1a, 0x7d, 0x0d, 0xf8, 0xca, 0x6e, 0x1e,
+ 0xff, 0x7a, 0xbf, 0xcc, 0xcb, 0x76, 0x9f, 0xef, 0xe2, 0xf3, 0x7b, 0x42,
+ 0xd5, 0xe7, 0x77, 0xf1, 0xf9, 0xde, 0x04, 0xf6, 0xd0, 0x58, 0x82, 0x5f,
+ 0xd2, 0xa1, 0x34, 0xef, 0xcd, 0x42, 0x91, 0x65, 0xeb, 0xcb, 0xcc, 0x47,
+ 0x57, 0xf4, 0xb8, 0x3e, 0xd4, 0xec, 0x88, 0x3d, 0x31, 0x78, 0xcc, 0xb9,
+ 0xcc, 0x04, 0x8f, 0x1b, 0x24, 0xff, 0xcb, 0x6c, 0x8b, 0xae, 0x68, 0x5c,
+ 0xd5, 0xf9, 0xf6, 0xdf, 0xe8, 0x93, 0x39, 0x55, 0xdf, 0xdd, 0x23, 0xe1,
+ 0xe7, 0x08, 0x9e, 0x72, 0x9e, 0xe1, 0xf2, 0xbc, 0xc0, 0x43, 0x7b, 0xda,
+ 0x2a, 0x3f, 0xbf, 0x13, 0x78, 0xd5, 0x8a, 0xbc, 0xd9, 0xc0, 0x12, 0xf3,
+ 0xc5, 0x19, 0xc7, 0x4c, 0x97, 0x73, 0xd5, 0x1e, 0x1f, 0x90, 0xd7, 0xbf,
+ 0xd9, 0x27, 0xfb, 0x83, 0x7e, 0x6b, 0x40, 0xf7, 0x48, 0x94, 0x32, 0x07,
+ 0xf9, 0xcb, 0x3e, 0x01, 0x1b, 0xff, 0x32, 0xf8, 0xa5, 0xc1, 0xdf, 0x79,
+ 0x3d, 0x09, 0xcc, 0xf1, 0x4a, 0x9f, 0xee, 0x17, 0x23, 0xd7, 0x15, 0xe7,
+ 0xf9, 0x46, 0x78, 0x5d, 0xfa, 0xfc, 0x0c, 0x1f, 0x7b, 0xed, 0x2f, 0xee,
+ 0xd5, 0x96, 0x90, 0xfd, 0xc5, 0xda, 0x12, 0xc9, 0x09, 0xb9, 0xcf, 0x15,
+ 0x9f, 0x6e, 0xa8, 0xec, 0xd3, 0x3d, 0x9f, 0xb9, 0xd5, 0x07, 0xff, 0x86,
+ 0xb1, 0xc4, 0xfb, 0x1d, 0x7c, 0x9e, 0xc7, 0xa2, 0x56, 0x21, 0xcd, 0x9f,
+ 0x1d, 0x2a, 0xaf, 0xa7, 0x1e, 0x57, 0x64, 0x9e, 0x84, 0x96, 0x5b, 0xb8,
+ 0xf6, 0x43, 0xbe, 0x87, 0x94, 0x5d, 0x8d, 0x9f, 0x43, 0x75, 0x79, 0x30,
+ 0xf5, 0x38, 0xb6, 0x99, 0x1f, 0x56, 0xc4, 0x13, 0x3d, 0xf0, 0x6c, 0xb3,
+ 0x7e, 0x06, 0xd7, 0x84, 0x1f, 0x2d, 0x56, 0x47, 0xaf, 0xa0, 0xe3, 0x00,
+ 0xfd, 0xce, 0x62, 0x8a, 0x76, 0xf1, 0x5e, 0xfd, 0xa6, 0xf1, 0x00, 0xe2,
+ 0xed, 0x24, 0x73, 0x9e, 0x18, 0xc6, 0x19, 0x67, 0xe2, 0x94, 0x11, 0x01,
+ 0xbf, 0x2c, 0x05, 0x9c, 0x0e, 0x6a, 0x66, 0x5a, 0xfd, 0x65, 0x1a, 0x65,
+ 0xfb, 0x0f, 0x34, 0xeb, 0x84, 0xe2, 0x04, 0x7a, 0xb3, 0xcd, 0x43, 0xac,
+ 0x13, 0xc7, 0x8a, 0xc0, 0x67, 0x83, 0x3e, 0x9f, 0x23, 0xfa, 0x5c, 0x6e,
+ 0xd4, 0xfc, 0x26, 0x39, 0x56, 0xe5, 0x77, 0xdb, 0x8c, 0xf2, 0x3c, 0xe2,
+ 0xc5, 0x2f, 0xd3, 0xfb, 0xa2, 0xcf, 0x09, 0xe0, 0xa8, 0xf7, 0xfd, 0x4b,
+ 0x74, 0x32, 0x81, 0x79, 0x6f, 0x9f, 0x3e, 0x8f, 0xef, 0x88, 0x3e, 0xdb,
+ 0x3c, 0xe8, 0xf3, 0xc5, 0x7e, 0x89, 0x37, 0x25, 0xc6, 0xd1, 0x36, 0x9a,
+ 0xcb, 0x22, 0x07, 0xec, 0xd3, 0xe8, 0x3b, 0x95, 0x4d, 0x32, 0x5f, 0x4a,
+ 0x56, 0xf8, 0xd2, 0x85, 0x28, 0x1b, 0xc3, 0x4c, 0xe3, 0xe8, 0xcb, 0xa6,
+ 0xf2, 0x7e, 0xb0, 0x8e, 0x01, 0x1a, 0x5d, 0x6e, 0xe7, 0x6b, 0x69, 0x3d,
+ 0x3a, 0x15, 0x51, 0xb5, 0xfe, 0xb6, 0x15, 0x63, 0xfe, 0x78, 0x9e, 0x69,
+ 0x39, 0x9d, 0xbd, 0x97, 0x0a, 0xc1, 0x21, 0x1a, 0x59, 0xd6, 0xfd, 0x4d,
+ 0x44, 0xce, 0xc6, 0xa0, 0xe4, 0x49, 0x7a, 0xdd, 0x9f, 0x10, 0xbe, 0x0b,
+ 0xeb, 0xd2, 0xc7, 0xb5, 0xee, 0xf6, 0x2d, 0xf8, 0xd2, 0x25, 0x45, 0xb3,
+ 0xa5, 0xcb, 0xd1, 0x30, 0xa5, 0xa2, 0x53, 0xaf, 0xf4, 0x03, 0xff, 0x47,
+ 0x2e, 0xc1, 0x0f, 0x07, 0x1e, 0x6d, 0x51, 0x22, 0x53, 0x0b, 0x8b, 0x21,
+ 0x5e, 0x37, 0x7e, 0x2f, 0x7d, 0x30, 0x17, 0x7e, 0x40, 0xc8, 0xfe, 0xd1,
+ 0x4b, 0x3c, 0x4e, 0xca, 0x26, 0xc5, 0x37, 0xbc, 0xf0, 0x50, 0xf7, 0xc5,
+ 0xd4, 0xb8, 0x28, 0x73, 0x3d, 0x59, 0x7f, 0x33, 0x13, 0xfe, 0x5a, 0x9c,
+ 0xbc, 0xe6, 0x3b, 0xba, 0x68, 0xd1, 0xb1, 0x8c, 0xfd, 0xf5, 0x14, 0x4d,
+ 0x31, 0x5d, 0xbb, 0xe5, 0x05, 0x8f, 0x27, 0xe0, 0xd9, 0x34, 0xd3, 0x3e,
+ 0xdb, 0xcd, 0x59, 0x4b, 0xe6, 0xdd, 0x89, 0xde, 0x73, 0x38, 0x46, 0xdd,
+ 0xf1, 0x5f, 0xf5, 0x6b, 0x79, 0x90, 0xcc, 0xa2, 0x8e, 0x90, 0x3f, 0xf3,
+ 0x3c, 0x1e, 0xb9, 0xff, 0x39, 0xdc, 0x07, 0xf2, 0x0e, 0x73, 0xe7, 0xe3,
+ 0x55, 0xb9, 0xaf, 0x23, 0x7c, 0x6f, 0xd4, 0xdd, 0x1f, 0x2b, 0x4e, 0xf2,
+ 0xfe, 0x76, 0x09, 0xde, 0x2c, 0xf7, 0x73, 0x9a, 0xce, 0x79, 0xf2, 0x15,
+ 0xb9, 0x2f, 0x49, 0x17, 0x7d, 0x27, 0x05, 0x7d, 0x4f, 0x8b, 0xfd, 0x48,
+ 0xe6, 0x0c, 0xd6, 0xd7, 0xb4, 0xef, 0x81, 0xed, 0xec, 0x5c, 0x40, 0xe7,
+ 0x06, 0xf2, 0xf7, 0x0f, 0xfb, 0x45, 0x5e, 0x22, 0xec, 0xef, 0x1c, 0x3e,
+ 0xa7, 0xe9, 0x79, 0x96, 0xeb, 0x2f, 0x64, 0x5a, 0xe8, 0x6a, 0xb6, 0x85,
+ 0xde, 0xc9, 0x0e, 0xd1, 0x95, 0xc5, 0x6e, 0x3a, 0xc7, 0x3a, 0xf3, 0x39,
+ 0x27, 0x60, 0xa5, 0xa9, 0x1b, 0xf1, 0x45, 0xe4, 0x0c, 0x31, 0xdd, 0x61,
+ 0x3c, 0xf4, 0xbf, 0xe8, 0x5e, 0xc6, 0x39, 0xd6, 0xbd, 0x5b, 0xe9, 0x3d,
+ 0x7e, 0x66, 0x3a, 0xa3, 0x73, 0x1d, 0xe0, 0x93, 0x1f, 0x2b, 0xeb, 0xaf,
+ 0x5b, 0xe3, 0x88, 0xb9, 0x05, 0x8e, 0x4c, 0x8b, 0xf8, 0xd6, 0xc2, 0x22,
+ 0xff, 0xbe, 0x08, 0xff, 0x39, 0xc3, 0x9b, 0xf9, 0xf3, 0x93, 0x01, 0x8c,
+ 0xc7, 0x39, 0x47, 0xe6, 0x4a, 0x8a, 0xb5, 0x85, 0xf8, 0xd8, 0x27, 0x6a,
+ 0xa4, 0x25, 0x1c, 0x5a, 0x79, 0x7d, 0x3e, 0x31, 0x3e, 0xb9, 0xda, 0x4a,
+ 0xf3, 0x39, 0xd6, 0x41, 0x72, 0x7e, 0xb6, 0x61, 0x30, 0xf6, 0xef, 0x54,
+ 0x6f, 0x61, 0xdc, 0xbf, 0x8b, 0xd2, 0x62, 0x1c, 0x7f, 0xae, 0x76, 0xd1,
+ 0x42, 0xae, 0x43, 0x1d, 0xdf, 0x2b, 0x72, 0xdc, 0x65, 0x1f, 0x23, 0xfc,
+ 0xb6, 0x19, 0x7f, 0x7b, 0x97, 0x71, 0x0a, 0x32, 0x55, 0xda, 0xa5, 0xe0,
+ 0x35, 0x97, 0xeb, 0x7a, 0x22, 0x03, 0xe7, 0xa6, 0xe8, 0x25, 0x96, 0xb7,
+ 0x23, 0x2f, 0xc3, 0x7f, 0xfc, 0x38, 0xf0, 0x26, 0x9f, 0xa2, 0x41, 0x3e,
+ 0x46, 0x5f, 0x24, 0xbf, 0xa8, 0x73, 0x8a, 0x05, 0x27, 0x44, 0x6d, 0x88,
+ 0xa4, 0xd1, 0x59, 0xd1, 0x8b, 0xee, 0x2d, 0xc1, 0x9b, 0xec, 0x94, 0x65,
+ 0x40, 0x1f, 0x81, 0x0f, 0x46, 0xe6, 0x60, 0x1d, 0x77, 0x7a, 0xde, 0xed,
+ 0x9b, 0x19, 0xa7, 0x48, 0x3f, 0xf0, 0x5e, 0xd2, 0xac, 0xea, 0x2f, 0x20,
+ 0xf8, 0xbd, 0xb9, 0x4f, 0xd7, 0x4b, 0xea, 0x63, 0x2d, 0x2b, 0xf4, 0x71,
+ 0x47, 0xcd, 0xef, 0x66, 0xcd, 0xef, 0xe5, 0x7c, 0x39, 0x96, 0x79, 0x2c,
+ 0xe7, 0x49, 0xf6, 0x28, 0x4a, 0x2e, 0x4b, 0xfc, 0x33, 0xf7, 0x8d, 0x99,
+ 0x8f, 0x2a, 0x1d, 0x3c, 0xb9, 0x36, 0x1a, 0xea, 0x31, 0x26, 0x8c, 0xe4,
+ 0xe4, 0x3f, 0x96, 0x22, 0x09, 0xe8, 0x45, 0x4f, 0xee, 0x51, 0xf9, 0xa7,
+ 0x3c, 0xaf, 0x54, 0x18, 0xaa, 0xdb, 0xec, 0x5a, 0x07, 0xad, 0x8b, 0x9e,
+ 0x5c, 0x42, 0xc7, 0xe0, 0xeb, 0x71, 0x9f, 0x94, 0xd9, 0x44, 0xe8, 0x73,
+ 0x0e, 0x1a, 0xdf, 0x1f, 0xba, 0xc4, 0xfb, 0x19, 0x5f, 0xfb, 0x69, 0xe9,
+ 0xa4, 0xe8, 0x71, 0x83, 0xb1, 0x5d, 0x34, 0x27, 0x74, 0x7e, 0xd6, 0x5f,
+ 0xaa, 0xec, 0xaa, 0x29, 0xcc, 0x33, 0x85, 0xd8, 0x8a, 0xe1, 0xfc, 0xbe,
+ 0x2f, 0x99, 0x97, 0xb1, 0xf2, 0x78, 0x4d, 0xac, 0x7c, 0x56, 0xc4, 0xca,
+ 0x11, 0x27, 0x07, 0x5c, 0x01, 0x4b, 0xaf, 0x9c, 0x16, 0xec, 0x63, 0x98,
+ 0x90, 0x1b, 0x7e, 0xee, 0xa2, 0xe0, 0x37, 0xe1, 0x98, 0x5f, 0xe6, 0x57,
+ 0xc7, 0x79, 0xc6, 0x06, 0x5d, 0x60, 0x7c, 0xb0, 0x27, 0x36, 0x58, 0x97,
+ 0x58, 0xc9, 0x7e, 0x99, 0xae, 0xe4, 0x9b, 0x58, 0xd7, 0x5b, 0xa0, 0x8d,
+ 0x3c, 0xb1, 0x4e, 0xd8, 0x4d, 0x0b, 0x61, 0xc6, 0xb1, 0x89, 0x36, 0xde,
+ 0x4f, 0xd6, 0x6b, 0x27, 0x98, 0xee, 0x78, 0xee, 0x2b, 0xb9, 0xd2, 0x8f,
+ 0xd2, 0xe1, 0x88, 0x15, 0x9d, 0xea, 0x60, 0xbb, 0xc5, 0xe4, 0x7f, 0x87,
+ 0xff, 0x77, 0x85, 0x00, 0x93, 0xc2, 0x2a, 0x7e, 0x67, 0x9d, 0x27, 0x53,
+ 0xfa, 0xd1, 0x1c, 0x8f, 0x99, 0x9b, 0x82, 0xfd, 0x03, 0x3b, 0xcf, 0xe1,
+ 0x7f, 0x39, 0x66, 0x65, 0x95, 0xf1, 0xfb, 0x62, 0x2a, 0x64, 0x08, 0xde,
+ 0xbe, 0xce, 0x3c, 0xfe, 0x02, 0xcd, 0xf1, 0x1c, 0xae, 0x10, 0xae, 0xb5,
+ 0x28, 0x19, 0xde, 0xc7, 0x78, 0xdf, 0xcd, 0x9f, 0xa8, 0xbf, 0x6a, 0xa7,
+ 0x85, 0xc9, 0x31, 0x55, 0x7f, 0xf5, 0xbd, 0x06, 0xf5, 0x57, 0xb8, 0x8e,
+ 0xe5, 0xfe, 0x62, 0xe9, 0xe6, 0x5c, 0xd8, 0xfd, 0x3c, 0x32, 0x92, 0xe1,
+ 0x4e, 0xa1, 0x23, 0xad, 0xac, 0xfa, 0xf8, 0xd9, 0x11, 0x2b, 0x39, 0xc5,
+ 0x73, 0xcc, 0xb9, 0xe7, 0x5d, 0xba, 0x19, 0x0b, 0x63, 0x9c, 0xbf, 0x66,
+ 0x1c, 0xdb, 0xca, 0x53, 0x72, 0x3d, 0x85, 0x5c, 0xe9, 0xe7, 0xd1, 0xb0,
+ 0x5e, 0x9f, 0xfb, 0x5a, 0xac, 0x03, 0xf4, 0xc4, 0x9f, 0x2b, 0x5d, 0xbe,
+ 0x2b, 0x59, 0xd8, 0xdf, 0x06, 0xe3, 0x39, 0x66, 0x34, 0x44, 0xa9, 0x15,
+ 0xa6, 0xef, 0x8b, 0x1d, 0xbe, 0x8d, 0xec, 0x95, 0x52, 0xb2, 0x2a, 0x97,
+ 0xa5, 0xda, 0xef, 0x2e, 0x6d, 0xae, 0x21, 0x72, 0x96, 0x20, 0x33, 0x21,
+ 0x2f, 0x53, 0x25, 0xbf, 0x03, 0xfd, 0x0e, 0xb6, 0xd0, 0x59, 0xe6, 0x57,
+ 0x32, 0x1f, 0x89, 0x79, 0x27, 0xf3, 0x2c, 0x49, 0x2f, 0xf1, 0xaa, 0xd7,
+ 0x0d, 0x48, 0x9c, 0x1d, 0xa9, 0xe4, 0x41, 0xba, 0xe2, 0xe9, 0x01, 0x57,
+ 0x3c, 0xdd, 0x74, 0xe5, 0x41, 0x06, 0x85, 0x3e, 0x56, 0xd1, 0xa1, 0x82,
+ 0x4a, 0x87, 0x82, 0xae, 0x25, 0x79, 0x59, 0xa1, 0xcc, 0xcb, 0x76, 0x6f,
+ 0xc1, 0xcb, 0xbc, 0x6c, 0xd3, 0x75, 0xc5, 0x37, 0xec, 0x30, 0xe4, 0xfc,
+ 0xe5, 0xe2, 0x34, 0xbd, 0xcd, 0x3c, 0xe2, 0xad, 0x62, 0x98, 0xf9, 0xc6,
+ 0x24, 0xf3, 0x8d, 0x09, 0xe6, 0x1b, 0x0e, 0xc3, 0xc0, 0xe2, 0xb5, 0x5f,
+ 0xf3, 0x5d, 0x59, 0x84, 0xbc, 0x98, 0xa2, 0xe7, 0x8b, 0xe0, 0xc1, 0x93,
+ 0xac, 0xf3, 0x5c, 0xf3, 0x6d, 0x2c, 0x76, 0x31, 0xbe, 0x4a, 0x3d, 0xa7,
+ 0xda, 0x8e, 0x41, 0xaf, 0x15, 0xf8, 0x87, 0xaf, 0x82, 0xcf, 0xbc, 0x91,
+ 0xa2, 0x4e, 0x86, 0x3d, 0xe0, 0xbc, 0x8e, 0xde, 0x14, 0xaf, 0x81, 0x96,
+ 0xd1, 0x13, 0xf8, 0xbb, 0xe3, 0x53, 0x3c, 0xf7, 0x4e, 0xdf, 0x02, 0xef,
+ 0xcb, 0xd3, 0xe1, 0x94, 0xd9, 0xcb, 0x38, 0x7f, 0xac, 0x82, 0xf3, 0xa9,
+ 0x34, 0xaf, 0xa0, 0x67, 0xb9, 0x9b, 0xc6, 0x0e, 0x44, 0xf7, 0xf6, 0x30,
+ 0x9d, 0x22, 0x37, 0xa2, 0xd2, 0xa7, 0xc7, 0x4f, 0x27, 0x83, 0x6d, 0xaa,
+ 0xbf, 0x8f, 0xc5, 0xf2, 0xf1, 0x03, 0xbe, 0xcf, 0x2d, 0x5f, 0x3a, 0xfb,
+ 0x2a, 0x3f, 0x03, 0xc7, 0x5f, 0x85, 0xff, 0x93, 0xed, 0x83, 0x56, 0xe1,
+ 0x3f, 0x2a, 0x88, 0xb1, 0x38, 0xb6, 0x27, 0x98, 0x97, 0x85, 0xd7, 0x0d,
+ 0x7b, 0x3a, 0x62, 0x30, 0xd1, 0x75, 0x99, 0xbc, 0xde, 0xd2, 0xa0, 0x8c,
+ 0xc1, 0xed, 0xdd, 0x2b, 0xf9, 0x06, 0xe3, 0x66, 0x30, 0x22, 0x6c, 0xb4,
+ 0xa6, 0x25, 0x29, 0x27, 0x0b, 0xbc, 0xcf, 0x2b, 0xe1, 0x09, 0xde, 0xe7,
+ 0x0e, 0x25, 0x23, 0x53, 0xfc, 0xbb, 0x90, 0xbf, 0x2c, 0x2b, 0x87, 0xd0,
+ 0xb3, 0xda, 0x14, 0xfd, 0x20, 0x66, 0xd1, 0x6f, 0xa7, 0x83, 0xef, 0x6b,
+ 0x33, 0xd6, 0x82, 0x4f, 0x7c, 0xe0, 0x4b, 0x66, 0xf1, 0x5c, 0xe0, 0x21,
+ 0x7f, 0xcf, 0x4f, 0xd1, 0x85, 0x8c, 0x9e, 0xc3, 0x80, 0x61, 0xbc, 0x84,
+ 0x79, 0xf8, 0x68, 0xb7, 0xf3, 0x43, 0x86, 0x17, 0x1f, 0xff, 0x71, 0xed,
+ 0x9c, 0x86, 0xd5, 0x9c, 0xd0, 0xd3, 0xb2, 0x05, 0x3d, 0x7c, 0x08, 0xbd,
+ 0x8f, 0x0a, 0xa2, 0xe7, 0x64, 0xb3, 0xb0, 0x4d, 0x0b, 0xc2, 0xc6, 0x28,
+ 0x85, 0x2a, 0x7d, 0x30, 0xef, 0xa9, 0x39, 0xf7, 0x13, 0x5f, 0x7a, 0xf1,
+ 0xa0, 0xd0, 0xc5, 0x46, 0x0e, 0xec, 0x55, 0xf5, 0xa7, 0x5d, 0xe2, 0xbe,
+ 0xc6, 0x32, 0x7e, 0x7b, 0x50, 0xfd, 0xf6, 0x49, 0xa1, 0x03, 0x23, 0x2f,
+ 0x2e, 0xb0, 0x24, 0xf0, 0x9c, 0xf7, 0xd7, 0x99, 0x60, 0x3c, 0x0f, 0xad,
+ 0xc0, 0x77, 0x2f, 0xe0, 0xa9, 0xe1, 0x01, 0x58, 0x00, 0xf7, 0x3b, 0x14,
+ 0xde, 0xdb, 0x56, 0xdc, 0xaf, 0xd7, 0xdd, 0x08, 0xce, 0xac, 0xd3, 0x64,
+ 0xb0, 0x56, 0xac, 0x69, 0x8f, 0x2f, 0x92, 0xb7, 0x8c, 0xf4, 0x22, 0x6c,
+ 0x1a, 0xd4, 0xb5, 0xdc, 0x85, 0xbc, 0x29, 0x9e, 0xc3, 0x1e, 0x8a, 0x24,
+ 0x30, 0x2f, 0x8c, 0xd3, 0x30, 0xf8, 0xb7, 0x1a, 0x58, 0xb8, 0xaf, 0xeb,
+ 0x56, 0xd7, 0xb5, 0x8a, 0xbd, 0x20, 0x03, 0xcf, 0xd1, 0xcf, 0xc6, 0x73,
+ 0xf1, 0x7c, 0x5c, 0x87, 0xfb, 0xc9, 0xfb, 0xf6, 0x31, 0x7f, 0x8e, 0x4e,
+ 0xc9, 0x7b, 0x19, 0x97, 0xe4, 0x6f, 0x7d, 0x8e, 0xf7, 0x7c, 0xe5, 0xfe,
+ 0xf9, 0x54, 0xbf, 0x1e, 0xec, 0x5f, 0x37, 0xe5, 0x85, 0x8f, 0x13, 0xbf,
+ 0x75, 0x8a, 0xdf, 0xa2, 0x4e, 0xa7, 0xd8, 0xd7, 0xf3, 0x7c, 0x3c, 0x9f,
+ 0xed, 0xf2, 0xc1, 0x36, 0x4f, 0x27, 0x3a, 0x7d, 0xf9, 0x3c, 0xd6, 0xdb,
+ 0xe9, 0x8b, 0x33, 0xee, 0xc7, 0xb2, 0xf1, 0xd2, 0x82, 0xe0, 0x31, 0xac,
+ 0xd3, 0xf6, 0xda, 0xe6, 0x49, 0xe3, 0x4f, 0x86, 0x64, 0x6f, 0x5b, 0x7c,
+ 0x67, 0xfa, 0xcb, 0x30, 0xfd, 0x65, 0x98, 0xfe, 0x32, 0x4c, 0x7f, 0x19,
+ 0xa6, 0x3f, 0xb6, 0x4b, 0xdf, 0x64, 0x99, 0xf1, 0x6d, 0x96, 0x19, 0x92,
+ 0x66, 0x23, 0xca, 0x8f, 0xa9, 0x69, 0xb6, 0xb6, 0x3e, 0x53, 0xd3, 0x28,
+ 0xe4, 0x34, 0xf9, 0x0e, 0x8f, 0x57, 0xd3, 0xea, 0x55, 0xa6, 0xd5, 0xa6,
+ 0x99, 0x7e, 0xba, 0x91, 0xc3, 0x9e, 0xd9, 0xd6, 0x79, 0xe6, 0xd1, 0x71,
+ 0x3f, 0x74, 0xaa, 0x00, 0xd3, 0x13, 0x74, 0x4a, 0x9b, 0xe1, 0xde, 0x4f,
+ 0x37, 0x99, 0x4f, 0xdf, 0xc8, 0x81, 0x76, 0xef, 0x52, 0xc7, 0x19, 0xa6,
+ 0x5d, 0xc8, 0xb9, 0x25, 0xdf, 0xd5, 0xac, 0xc1, 0xba, 0x57, 0xc0, 0x4c,
+ 0x12, 0xf8, 0xa8, 0xd0, 0xc7, 0x78, 0xdf, 0xd7, 0x99, 0xdf, 0xc3, 0x57,
+ 0x87, 0xbe, 0x5f, 0x79, 0x1f, 0xcb, 0x89, 0xd0, 0x15, 0xe6, 0xa3, 0xa7,
+ 0x73, 0x4b, 0x4c, 0xef, 0xbd, 0xf4, 0x85, 0x1c, 0xe4, 0x31, 0x60, 0xc4,
+ 0xc7, 0x79, 0x12, 0x3e, 0x30, 0x63, 0x06, 0x6b, 0x1f, 0x4b, 0x19, 0x02,
+ 0x4f, 0x9e, 0x01, 0x1c, 0x18, 0xf6, 0x67, 0xf6, 0xa2, 0x67, 0x7d, 0xc4,
+ 0x68, 0x56, 0x3e, 0x45, 0x7c, 0xc7, 0x78, 0x8c, 0x05, 0xdc, 0x70, 0xdc,
+ 0x28, 0xfe, 0x88, 0xf7, 0x42, 0x84, 0x19, 0x1e, 0xb5, 0x7c, 0xeb, 0x02,
+ 0x7a, 0x91, 0x02, 0x5e, 0xd3, 0x51, 0x3f, 0x6a, 0xc5, 0xe9, 0x39, 0xbc,
+ 0xff, 0xe0, 0x85, 0x22, 0xe6, 0xbd, 0x48, 0x0b, 0x41, 0xf0, 0x21, 0x3b,
+ 0x7c, 0x9d, 0x24, 0xec, 0x5a, 0x59, 0xbf, 0xfc, 0xbc, 0x37, 0x6f, 0xb3,
+ 0xa2, 0x42, 0x1f, 0x6e, 0x61, 0xfb, 0x06, 0xb0, 0x79, 0x8b, 0x71, 0x2d,
+ 0x0c, 0x9b, 0x5f, 0xf1, 0xb5, 0x37, 0x99, 0xe7, 0x60, 0xcf, 0x3a, 0x85,
+ 0x8c, 0xf1, 0xe2, 0x65, 0x1b, 0x8a, 0x97, 0x39, 0x2e, 0x5e, 0x96, 0x2e,
+ 0xf3, 0x32, 0xc6, 0x09, 0xc1, 0xc3, 0xc0, 0xa3, 0x66, 0x59, 0x4f, 0x94,
+ 0xdf, 0xa1, 0xff, 0xed, 0x16, 0x3c, 0x8b, 0x79, 0x3d, 0xdb, 0x0d, 0x85,
+ 0x62, 0xca, 0x77, 0x48, 0xf0, 0x0e, 0x8d, 0xd7, 0xff, 0xa3, 0xe8, 0xa1,
+ 0x55, 0xf0, 0x81, 0xf4, 0x2c, 0xf8, 0x95, 0xd7, 0xf8, 0xff, 0x02, 0x6c,
+ 0x79, 0xbc, 0x13, 0x7a, 0x8d, 0xf9, 0x58, 0x21, 0x0c, 0x9b, 0xb5, 0x43,
+ 0xd9, 0x36, 0xe8, 0xbb, 0xb5, 0x07, 0xb9, 0x96, 0x56, 0xb4, 0xcc, 0xc7,
+ 0x76, 0x2b, 0xbf, 0x05, 0xfc, 0x8c, 0xd8, 0xeb, 0x3a, 0x5d, 0xc0, 0x82,
+ 0x2e, 0xc0, 0x63, 0x03, 0x0c, 0x1f, 0xd1, 0x1b, 0x9c, 0xe8, 0x16, 0xc3,
+ 0x01, 0xfb, 0x7c, 0x0b, 0xfb, 0xcc, 0xba, 0x2c, 0x05, 0xe6, 0xa6, 0x02,
+ 0x03, 0x98, 0xdf, 0xc2, 0x6a, 0x85, 0x1f, 0x9e, 0xcf, 0x0c, 0x18, 0x85,
+ 0xac, 0x9c, 0xe3, 0xca, 0xb8, 0xe4, 0x79, 0x85, 0x3c, 0x7a, 0x7b, 0x89,
+ 0xb9, 0xf2, 0x1c, 0xf5, 0xfa, 0x04, 0xff, 0x52, 0x74, 0xbf, 0x1d, 0x5a,
+ 0x4b, 0x30, 0x5d, 0x61, 0x4f, 0x52, 0x2e, 0x9c, 0x79, 0x94, 0x9f, 0x8f,
+ 0x73, 0x8d, 0xd7, 0x71, 0xb3, 0xbc, 0x8e, 0x08, 0xaf, 0x03, 0x63, 0x6f,
+ 0xf9, 0x6e, 0xa8, 0x75, 0xdc, 0x28, 0xaf, 0x63, 0x56, 0xad, 0x83, 0xd2,
+ 0xc6, 0xcc, 0x6e, 0xa5, 0xc7, 0x6f, 0x79, 0xcf, 0xd6, 0x28, 0xeb, 0x27,
+ 0xe9, 0x55, 0xc0, 0xf3, 0x1e, 0x85, 0x2f, 0x6e, 0x7f, 0xa8, 0x7b, 0x6e,
+ 0xf6, 0xc4, 0x75, 0xfa, 0x5d, 0xba, 0x29, 0xf4, 0x93, 0x61, 0xd6, 0x4f,
+ 0x70, 0x9e, 0x16, 0xc0, 0x87, 0xd3, 0x41, 0xf4, 0x9b, 0x1d, 0x64, 0x98,
+ 0xb1, 0x5d, 0x35, 0xc5, 0x9f, 0xc2, 0x4f, 0x86, 0xfb, 0xe8, 0xeb, 0xbf,
+ 0x48, 0x37, 0x17, 0xc1, 0xab, 0xa1, 0x8f, 0xca, 0x9e, 0xb4, 0x37, 0xd7,
+ 0xa4, 0x9f, 0x36, 0xee, 0xe9, 0xa7, 0x85, 0x8f, 0x36, 0x0c, 0x7d, 0xdd,
+ 0x84, 0x3f, 0x37, 0x26, 0xde, 0x67, 0xc1, 0xc7, 0x45, 0xdc, 0xcb, 0x8b,
+ 0xef, 0x4c, 0xbb, 0x72, 0xdc, 0x90, 0x73, 0x92, 0x62, 0x3e, 0xe2, 0x98,
+ 0x4d, 0x86, 0xac, 0x9d, 0xb9, 0x5c, 0xd4, 0x3a, 0x51, 0x9c, 0xf7, 0xc8,
+ 0x09, 0x1b, 0x46, 0x44, 0xf8, 0x0c, 0x5a, 0x9d, 0x0e, 0x6a, 0x61, 0x39,
+ 0x79, 0x8a, 0xd0, 0x13, 0xcd, 0xb6, 0xe0, 0xcb, 0xbf, 0xc0, 0xb8, 0xb7,
+ 0x10, 0xb6, 0x43, 0x9f, 0x13, 0xf6, 0x25, 0xe4, 0x07, 0xde, 0xa7, 0x02,
+ 0x18, 0x63, 0x0e, 0xfc, 0x7d, 0x15, 0xfd, 0x30, 0xc3, 0xbc, 0x7e, 0xf8,
+ 0x81, 0x47, 0xad, 0x77, 0x58, 0xee, 0x5c, 0x10, 0xfe, 0x95, 0xb3, 0x94,
+ 0x66, 0x3a, 0x3c, 0x2c, 0xe8, 0xd0, 0x18, 0x66, 0x6a, 0x61, 0xfa, 0x41,
+ 0x8e, 0xc1, 0x98, 0xe8, 0xbf, 0x23, 0x6d, 0x16, 0x5e, 0xe5, 0x9a, 0xea,
+ 0x6b, 0x90, 0x00, 0x6f, 0xd8, 0xbe, 0x6f, 0x21, 0xf1, 0x91, 0x7d, 0x2a,
+ 0x6e, 0x5d, 0xab, 0xd6, 0x87, 0x0d, 0xfb, 0xcc, 0x12, 0x7d, 0x1f, 0x01,
+ 0x3b, 0xe1, 0x17, 0x34, 0x26, 0x19, 0x6e, 0xfa, 0xdd, 0x35, 0x6e, 0xfb,
+ 0xff, 0x29, 0x51, 0x9f, 0xff, 0x46, 0x51, 0xca, 0xd8, 0x34, 0xdb, 0xe6,
+ 0x0b, 0x07, 0xdc, 0x3a, 0x87, 0x9d, 0x8d, 0x09, 0x9f, 0xcc, 0x00, 0x45,
+ 0x97, 0x27, 0xe9, 0xb1, 0x0c, 0x78, 0x14, 0x5d, 0x8f, 0x3a, 0x78, 0xc3,
+ 0x06, 0x68, 0x79, 0x92, 0xe2, 0x45, 0xc0, 0xc8, 0x47, 0x0b, 0x2c, 0x05,
+ 0xd2, 0x59, 0xc4, 0xee, 0xf9, 0x7b, 0x1e, 0xef, 0x57, 0xf9, 0x15, 0xe5,
+ 0xf7, 0x1e, 0xa2, 0xd8, 0x32, 0xa5, 0x92, 0xe1, 0x87, 0x45, 0xcf, 0xea,
+ 0x64, 0x78, 0x5c, 0xf9, 0x68, 0x42, 0x7c, 0x1e, 0x7e, 0x2f, 0x8b, 0x1e,
+ 0xcd, 0xd8, 0xa9, 0x24, 0x49, 0xdf, 0x03, 0xf1, 0x1c, 0x0c, 0x96, 0xad,
+ 0xbb, 0x99, 0x57, 0x1c, 0x17, 0xfe, 0x07, 0xd6, 0x44, 0x16, 0x31, 0x1e,
+ 0xbe, 0x83, 0x5e, 0x82, 0xbd, 0x95, 0xcc, 0x3e, 0xa0, 0xc6, 0x96, 0xc8,
+ 0x64, 0x5c, 0x30, 0x7f, 0xc9, 0x49, 0x85, 0x8d, 0xca, 0xf5, 0xf0, 0x5d,
+ 0x1c, 0x17, 0xfa, 0xe1, 0x30, 0xdb, 0x30, 0x62, 0x5c, 0x69, 0x4e, 0xf8,
+ 0x21, 0xf8, 0x38, 0xff, 0xd3, 0x01, 0xfd, 0x6e, 0x03, 0x9c, 0x97, 0xfe,
+ 0x09, 0xbe, 0x67, 0x9e, 0xe7, 0x51, 0x95, 0x17, 0x3f, 0x44, 0x91, 0x1d,
+ 0xf8, 0x8b, 0x66, 0xef, 0xa8, 0xbf, 0x88, 0x61, 0xcd, 0xb2, 0xe5, 0x32,
+ 0xd3, 0xc6, 0xdb, 0x5b, 0xda, 0x71, 0xef, 0x6b, 0x19, 0xcd, 0xb0, 0x32,
+ 0xc5, 0xfb, 0x2f, 0xd0, 0xeb, 0x73, 0xa1, 0xf8, 0x29, 0xbc, 0x47, 0xc6,
+ 0x97, 0x10, 0x3a, 0x6f, 0x88, 0x75, 0x17, 0xe8, 0x30, 0xa3, 0x22, 0xbe,
+ 0x15, 0x79, 0xc2, 0x32, 0x16, 0xd6, 0xfa, 0xc9, 0x0f, 0xbf, 0x9a, 0xa3,
+ 0x73, 0x22, 0x5a, 0x45, 0xfe, 0xba, 0x8c, 0x2b, 0x42, 0xfe, 0x82, 0x07,
+ 0xfe, 0xc4, 0x97, 0x5c, 0xf3, 0xf7, 0xe9, 0x7c, 0xb7, 0x48, 0xb0, 0x9c,
+ 0x4f, 0xa3, 0x78, 0x8a, 0xc6, 0x3d, 0x1d, 0xb3, 0x70, 0xbf, 0xd7, 0x0a,
+ 0xb4, 0xeb, 0xd6, 0x19, 0xe0, 0x67, 0x12, 0x7b, 0x74, 0x01, 0x71, 0x5c,
+ 0xa3, 0x2a, 0x1e, 0xd1, 0xc2, 0xfb, 0x04, 0x3b, 0x0f, 0xfe, 0xbb, 0xcf,
+ 0xf2, 0x27, 0xe2, 0x0a, 0x27, 0x07, 0xa1, 0x27, 0xf5, 0x38, 0x8c, 0x33,
+ 0x53, 0x38, 0xee, 0x67, 0xbb, 0x4b, 0xeb, 0xb5, 0xd2, 0xa7, 0xc4, 0xb6,
+ 0x98, 0xda, 0x2f, 0xf8, 0x93, 0x46, 0x54, 0xbf, 0x01, 0x9b, 0xac, 0x5e,
+ 0xc0, 0xe9, 0xe3, 0xa2, 0xc7, 0xad, 0x62, 0x10, 0xdb, 0xc9, 0x59, 0xc2,
+ 0x3b, 0xb7, 0xd0, 0x77, 0xf3, 0x6e, 0xc0, 0x9e, 0xf7, 0xc8, 0x1d, 0xa3,
+ 0xf8, 0x94, 0x7a, 0xff, 0xcf, 0x9d, 0xda, 0xb7, 0x5d, 0x1e, 0xfb, 0xf6,
+ 0xbd, 0x41, 0x19, 0x03, 0xbb, 0x4b, 0x8d, 0xf1, 0xca, 0x53, 0xfd, 0xfb,
+ 0xa7, 0xe1, 0x4f, 0xaa, 0xd4, 0x51, 0x5c, 0x13, 0x7c, 0xa5, 0xde, 0xa7,
+ 0x1d, 0x62, 0x7e, 0x2a, 0xe9, 0xf8, 0xb8, 0x07, 0x1d, 0xf7, 0xce, 0x40,
+ 0x2f, 0xb9, 0x7d, 0x3a, 0x3e, 0xd6, 0x90, 0x8e, 0xff, 0x75, 0x50, 0xfa,
+ 0x54, 0xeb, 0xe9, 0x18, 0xb5, 0x3c, 0xc7, 0x8b, 0x8d, 0xfc, 0x57, 0xd8,
+ 0x07, 0xd4, 0xa4, 0xc3, 0xe7, 0x01, 0x58, 0x69, 0xbf, 0x07, 0xe2, 0x7e,
+ 0xc0, 0x47, 0xc4, 0x4e, 0xfe, 0x90, 0xe2, 0x8b, 0xb5, 0xb1, 0xd0, 0xcd,
+ 0xae, 0xf9, 0x96, 0xc7, 0x35, 0xd0, 0xc5, 0x41, 0x0b, 0x76, 0x48, 0xda,
+ 0xf4, 0x1a, 0x5e, 0xef, 0xf9, 0x0e, 0xe5, 0xec, 0x54, 0x9e, 0xe0, 0xa3,
+ 0x0e, 0xd2, 0x53, 0x88, 0x2b, 0x2b, 0x1f, 0xf0, 0xd1, 0x8c, 0x5c, 0xb7,
+ 0x79, 0x40, 0xe0, 0x03, 0xf4, 0xd5, 0x50, 0xc2, 0x9f, 0xe0, 0x3d, 0x95,
+ 0xfe, 0xdf, 0xe4, 0x6a, 0x48, 0xed, 0x13, 0x8f, 0xc5, 0xfd, 0x3c, 0xeb,
+ 0xfc, 0xb0, 0x3f, 0xf6, 0xd7, 0xd7, 0xcb, 0x79, 0xc5, 0x90, 0x05, 0x25,
+ 0xfa, 0x0f, 0x96, 0x73, 0xfe, 0x03, 0xa6, 0xe8, 0xb9, 0x70, 0xb9, 0x78,
+ 0x80, 0xf5, 0x47, 0xec, 0x21, 0x7c, 0x87, 0xda, 0xb7, 0xfb, 0xf6, 0x30,
+ 0x75, 0xed, 0x67, 0xa9, 0x6f, 0x90, 0xc3, 0x7a, 0xa3, 0x71, 0x00, 0xf9,
+ 0xe1, 0x16, 0x5f, 0x83, 0x5e, 0x51, 0x63, 0x56, 0x9c, 0x3a, 0xe0, 0x4f,
+ 0x40, 0x0f, 0x68, 0x2b, 0x5d, 0x45, 0x53, 0xb3, 0x82, 0xa6, 0xe2, 0x6b,
+ 0xb3, 0x8a, 0xa6, 0x66, 0x95, 0xff, 0x7c, 0x56, 0xd1, 0xd4, 0xac, 0xa2,
+ 0xa9, 0x59, 0x45, 0x53, 0xb3, 0x8c, 0xd7, 0xa3, 0xac, 0xaf, 0x42, 0xf7,
+ 0xd0, 0xfe, 0xcb, 0x2e, 0x4a, 0xe6, 0x70, 0x1e, 0xf2, 0xb8, 0x96, 0xae,
+ 0x7e, 0x6d, 0x58, 0xfb, 0x47, 0x0b, 0x32, 0xcf, 0x8e, 0x9f, 0x85, 0x3d,
+ 0x78, 0x98, 0xe1, 0x77, 0xcd, 0x37, 0xbf, 0x88, 0xb9, 0xfa, 0x28, 0x26,
+ 0x7a, 0xc0, 0x36, 0x51, 0xd4, 0xad, 0xe3, 0x9a, 0xa8, 0xeb, 0x92, 0xb6,
+ 0x5c, 0xaa, 0x61, 0x8d, 0x97, 0xc6, 0x8b, 0x69, 0xb5, 0x5f, 0xb5, 0x76,
+ 0x4e, 0x0b, 0x25, 0xb2, 0x80, 0x2b, 0x72, 0x21, 0x2d, 0xde, 0x1b, 0x01,
+ 0xa7, 0x94, 0xe9, 0x01, 0x83, 0xa3, 0x0a, 0x06, 0x4f, 0x8b, 0x35, 0x22,
+ 0x97, 0x10, 0x3e, 0xc8, 0xc6, 0x70, 0x48, 0x67, 0x46, 0xf9, 0x3e, 0x8c,
+ 0xfb, 0x07, 0x42, 0xcc, 0x83, 0xb6, 0x0b, 0x07, 0xf7, 0xda, 0x1b, 0xf1,
+ 0x9a, 0xed, 0xd6, 0xd3, 0x5c, 0x77, 0xc9, 0x8e, 0x90, 0x92, 0x1b, 0x52,
+ 0xef, 0xdd, 0xe5, 0xd8, 0x89, 0x14, 0xcf, 0xed, 0x2f, 0xc2, 0x7f, 0x39,
+ 0x44, 0x6d, 0x25, 0x3a, 0x12, 0x06, 0x3e, 0x77, 0xb1, 0x5d, 0xc9, 0x73,
+ 0x18, 0x2b, 0xd1, 0x85, 0xf0, 0x3e, 0xb6, 0x5d, 0xf6, 0xb3, 0x0e, 0x3a,
+ 0xca, 0xff, 0x4e, 0xc4, 0xef, 0xc3, 0xbc, 0x3a, 0xf8, 0xda, 0x7e, 0x32,
+ 0x7a, 0x52, 0x66, 0x2b, 0xeb, 0x07, 0x47, 0x2a, 0xf6, 0x88, 0x05, 0xff,
+ 0x1c, 0xeb, 0xb6, 0xc6, 0x5c, 0xb8, 0x5b, 0xd5, 0x9c, 0xc1, 0x87, 0x8d,
+ 0xf8, 0xd6, 0x3f, 0x97, 0x64, 0xaf, 0x80, 0x21, 0x75, 0xfc, 0xe3, 0x52,
+ 0x64, 0x08, 0xc7, 0x78, 0xe7, 0x90, 0x3d, 0x11, 0xf1, 0xfd, 0x58, 0xea,
+ 0xf2, 0x3e, 0xfb, 0x88, 0x7c, 0x3f, 0x80, 0x6d, 0x5a, 0x3e, 0x2f, 0xbc,
+ 0x97, 0x3a, 0x4f, 0x25, 0x5f, 0x15, 0x74, 0x50, 0xa2, 0x7f, 0x67, 0x9a,
+ 0x35, 0x09, 0xb1, 0x8c, 0x29, 0x51, 0x0b, 0x8d, 0x7c, 0xe5, 0xf9, 0x45,
+ 0x3d, 0x2f, 0x47, 0xed, 0xf5, 0xfd, 0xc8, 0x37, 0xcb, 0x16, 0x68, 0x73,
+ 0x99, 0x01, 0x3f, 0xda, 0xe8, 0xf2, 0x46, 0x4f, 0x50, 0xd4, 0x66, 0x77,
+ 0xb3, 0x8e, 0xa3, 0xf3, 0x92, 0xc7, 0xf8, 0xfe, 0x01, 0xf1, 0xbe, 0xb9,
+ 0xd8, 0x12, 0xc6, 0x35, 0xd3, 0xc8, 0x72, 0xe9, 0x21, 0xfe, 0x5d, 0xc4,
+ 0x11, 0x93, 0xd4, 0xaa, 0x62, 0x04, 0x1d, 0x2a, 0xae, 0x14, 0x62, 0x5a,
+ 0xaa, 0xd4, 0x1c, 0x8f, 0x94, 0x7d, 0x6d, 0xc0, 0xf1, 0x5a, 0x5f, 0xdb,
+ 0x73, 0x5b, 0xc8, 0x9b, 0xad, 0xf0, 0x1a, 0x39, 0xa5, 0x2d, 0xa4, 0x7c,
+ 0x88, 0xd6, 0x02, 0x6d, 0xb7, 0xb6, 0x6e, 0xc7, 0xd7, 0xb4, 0x36, 0xcf,
+ 0xac, 0x9f, 0x79, 0xc7, 0x69, 0x53, 0xf8, 0xd4, 0x4c, 0xf3, 0xb9, 0x36,
+ 0x96, 0xd9, 0xa8, 0x97, 0x02, 0xbc, 0xfc, 0x43, 0xa8, 0x37, 0x79, 0x32,
+ 0xd0, 0x4c, 0xab, 0xab, 0xc8, 0x79, 0x78, 0xfc, 0x2e, 0x99, 0xe7, 0xfb,
+ 0x08, 0xc3, 0x65, 0x3f, 0xcb, 0x37, 0x43, 0xc5, 0x70, 0x70, 0x0e, 0xbc,
+ 0x41, 0xf4, 0xfd, 0x0c, 0x3c, 0x3c, 0xde, 0xc6, 0x7a, 0xbd, 0x8c, 0x01,
+ 0x1c, 0xe4, 0x7b, 0x7f, 0x33, 0xf7, 0x08, 0xfc, 0x59, 0xe6, 0x61, 0xbe,
+ 0x7f, 0x8c, 0xf5, 0x81, 0x08, 0x35, 0xd3, 0xca, 0x6a, 0x33, 0xeb, 0xf5,
+ 0xcd, 0xac, 0x0f, 0x8c, 0x9a, 0x23, 0x3e, 0xf1, 0x2c, 0x51, 0xdb, 0xf2,
+ 0xe9, 0xc0, 0x7e, 0xc6, 0x41, 0x3c, 0xeb, 0x8b, 0xea, 0x59, 0xb5, 0xcf,
+ 0xb8, 0x55, 0xc2, 0xf1, 0x61, 0xff, 0xfa, 0x99, 0xab, 0x78, 0x2f, 0xd4,
+ 0xe2, 0x34, 0xeb, 0xbe, 0x41, 0xf1, 0x6e, 0x46, 0x63, 0x66, 0x86, 0xed,
+ 0x80, 0x30, 0x1f, 0x1f, 0xa1, 0x54, 0x31, 0x41, 0xbf, 0x57, 0x74, 0xfb,
+ 0x6a, 0x8f, 0xf0, 0x9c, 0x65, 0x6d, 0x7d, 0x0b, 0xcf, 0xeb, 0x7d, 0xa7,
+ 0x96, 0x67, 0xb4, 0x91, 0xff, 0x6b, 0x41, 0x6a, 0x7e, 0x11, 0xbe, 0x91,
+ 0x12, 0x65, 0xc3, 0xf6, 0x85, 0xeb, 0xe2, 0xbd, 0x1b, 0x16, 0xbd, 0x22,
+ 0xf2, 0x5b, 0xf9, 0x7a, 0xbe, 0xe7, 0x79, 0x8c, 0x7b, 0xc5, 0xa2, 0x2b,
+ 0x8e, 0x84, 0xf7, 0x9f, 0x05, 0x82, 0xe4, 0x7f, 0x1d, 0x39, 0x48, 0xd0,
+ 0xb5, 0xd6, 0xcf, 0x38, 0xfb, 0x98, 0x5f, 0xbf, 0x88, 0xeb, 0xf8, 0xf3,
+ 0x75, 0x1c, 0xb7, 0xf1, 0x3a, 0x21, 0x6f, 0x91, 0x77, 0x02, 0x3e, 0xb7,
+ 0x3f, 0x64, 0x0a, 0xfc, 0x3b, 0xc2, 0x38, 0xd5, 0x24, 0x7c, 0x81, 0xbd,
+ 0x18, 0xeb, 0x0c, 0xb2, 0x6e, 0xb0, 0x7e, 0x66, 0x7c, 0x1f, 0x8e, 0x23,
+ 0x3d, 0x7e, 0x86, 0x91, 0xc4, 0xa1, 0xb0, 0x78, 0xff, 0xa1, 0xeb, 0x2f,
+ 0x70, 0x70, 0x9c, 0x78, 0x3f, 0xa1, 0x3f, 0xf0, 0x7e, 0x9a, 0xe8, 0xb3,
+ 0xd4, 0x46, 0x71, 0x7e, 0x46, 0x2c, 0x27, 0xd7, 0x7d, 0xbe, 0xe8, 0x27,
+ 0xe9, 0x47, 0x6a, 0x1e, 0xd6, 0xef, 0x29, 0xa4, 0x7e, 0xdc, 0x5b, 0xd3,
+ 0x0a, 0xbe, 0x77, 0xd1, 0x8d, 0x5c, 0x07, 0xdd, 0x54, 0xb1, 0xa5, 0x1b,
+ 0xc2, 0xae, 0x62, 0x9e, 0x9c, 0xe8, 0xa2, 0xeb, 0xab, 0x4d, 0x44, 0xbd,
+ 0x6d, 0x22, 0xf6, 0x7b, 0x23, 0x97, 0xc7, 0xf3, 0x87, 0xa5, 0xdf, 0xa5,
+ 0x82, 0x23, 0x37, 0x3c, 0x70, 0xe4, 0x3d, 0x81, 0x23, 0xef, 0x6d, 0x81,
+ 0x23, 0x7b, 0x95, 0x2d, 0xd1, 0x46, 0xcd, 0x0a, 0x3f, 0x5e, 0x63, 0xfc,
+ 0x78, 0x81, 0xf1, 0xe3, 0x50, 0x03, 0xfc, 0x30, 0x6a, 0xf0, 0xe3, 0xb0,
+ 0xc0, 0x8f, 0x9f, 0x6d, 0x8a, 0x1f, 0x87, 0xfc, 0x9b, 0xf9, 0x82, 0x34,
+ 0x6e, 0x0e, 0xd0, 0x4a, 0xce, 0xa1, 0xd5, 0x45, 0x9b, 0x2d, 0x7b, 0xd8,
+ 0xe6, 0x88, 0x19, 0xce, 0x88, 0x7a, 0x97, 0x82, 0xc0, 0x2b, 0x96, 0xe3,
+ 0x33, 0xa8, 0x69, 0xaa, 0xdb, 0x03, 0x12, 0xef, 0xa5, 0x14, 0xf0, 0x97,
+ 0x7b, 0x12, 0xcb, 0xac, 0x9f, 0xf9, 0x73, 0xde, 0xc7, 0x2b, 0x6b, 0x81,
+ 0x00, 0x7e, 0xf3, 0xcf, 0x04, 0x69, 0x63, 0x8d, 0xed, 0x54, 0xc6, 0xb1,
+ 0xab, 0xb9, 0x21, 0xba, 0x92, 0x1b, 0xa0, 0x8d, 0xdc, 0x30, 0xbd, 0x93,
+ 0xc3, 0x33, 0x00, 0x73, 0x3e, 0x16, 0x30, 0x37, 0xe8, 0x60, 0x90, 0xc7,
+ 0xac, 0x0e, 0xd0, 0xfa, 0xaa, 0xc6, 0x57, 0xe0, 0x2a, 0xf6, 0x3f, 0xd2,
+ 0x23, 0xeb, 0xd0, 0xea, 0x71, 0x20, 0x56, 0x85, 0x03, 0xf2, 0x1a, 0xec,
+ 0xfd, 0x42, 0x7d, 0x0d, 0x6d, 0xab, 0x39, 0x83, 0x1c, 0xb8, 0x36, 0xb6,
+ 0xc9, 0x6d, 0xe1, 0x73, 0x3d, 0xe8, 0x87, 0x4e, 0x6b, 0xdc, 0x4d, 0x5d,
+ 0xbc, 0x07, 0x0e, 0xf2, 0x87, 0x86, 0x59, 0x3f, 0xed, 0x16, 0xfa, 0x68,
+ 0xd4, 0x09, 0x84, 0x62, 0x54, 0x3a, 0x6b, 0x38, 0xe8, 0x93, 0xf8, 0x08,
+ 0xdf, 0xcf, 0x50, 0x7e, 0x9e, 0x4e, 0x17, 0x3e, 0xd5, 0xea, 0x9e, 0x88,
+ 0xd1, 0x9e, 0xe0, 0x39, 0x43, 0x4e, 0x56, 0xe2, 0x22, 0x54, 0x8e, 0x8b,
+ 0xb4, 0xf2, 0xba, 0x25, 0x2d, 0xcd, 0x39, 0x3c, 0xae, 0xc8, 0xe3, 0x8a,
+ 0x88, 0xa9, 0xf1, 0xf9, 0x55, 0xc4, 0x73, 0x87, 0x68, 0x63, 0x11, 0x34,
+ 0x07, 0xff, 0x44, 0x25, 0x86, 0xba, 0xb1, 0x86, 0xf3, 0xf0, 0x51, 0x54,
+ 0x62, 0xa8, 0x1b, 0x2a, 0x86, 0xba, 0xb1, 0x36, 0x2d, 0xf8, 0xf0, 0x42,
+ 0x8e, 0x79, 0x40, 0xce, 0xaf, 0xf2, 0x07, 0xf7, 0xa9, 0x77, 0xf6, 0x9c,
+ 0x10, 0x3e, 0xe4, 0x1e, 0x67, 0x73, 0x18, 0x1e, 0xac, 0x83, 0xe1, 0xb4,
+ 0xd0, 0x83, 0xe2, 0x7c, 0xcf, 0x58, 0xee, 0x04, 0xc3, 0x73, 0x96, 0x69,
+ 0x69, 0xb7, 0xa2, 0x25, 0x1d, 0x93, 0xed, 0x26, 0xf5, 0xfe, 0x1f, 0xa1,
+ 0xeb, 0x4b, 0xfe, 0x33, 0x54, 0xc3, 0x7f, 0x28, 0x10, 0x1d, 0x97, 0xd7,
+ 0xa7, 0x8b, 0xaf, 0x0c, 0x6b, 0xff, 0x5b, 0x9a, 0xef, 0xbb, 0x90, 0xdb,
+ 0x49, 0x4c, 0x97, 0xe5, 0xa6, 0x67, 0xce, 0xe0, 0x76, 0x9f, 0xad, 0x71,
+ 0xe1, 0xc4, 0x6d, 0xe0, 0x93, 0xbc, 0x47, 0x05, 0x9f, 0xfe, 0x77, 0x16,
+ 0xc0, 0xb2, 0x93, 0x05, 0x98, 0x57, 0x84, 0x80, 0xf5, 0x03, 0x03, 0xb4,
+ 0x8e, 0x39, 0x00, 0x1e, 0x53, 0x68, 0x02, 0xe6, 0x19, 0xa7, 0xf5, 0x40,
+ 0xfb, 0xfb, 0x95, 0xc1, 0xeb, 0x5d, 0x1b, 0xa0, 0x67, 0x4f, 0x2d, 0xea,
+ 0x79, 0x2c, 0x07, 0xca, 0xa3, 0x4e, 0x2a, 0x0c, 0x24, 0xe6, 0x27, 0x90,
+ 0xff, 0x80, 0xfe, 0x00, 0xf9, 0x11, 0x98, 0x9f, 0x9c, 0x81, 0x72, 0xa0,
+ 0x35, 0x53, 0xcd, 0x6b, 0x40, 0xfa, 0x40, 0x61, 0x08, 0x2a, 0x53, 0x41,
+ 0x63, 0x1d, 0x40, 0xf6, 0x12, 0x21, 0x68, 0xd8, 0x01, 0x69, 0x20, 0xbb,
+ 0x79, 0x8a, 0x08, 0x98, 0x9f, 0x14, 0x20, 0xc4, 0xd0, 0x00, 0xcf, 0x4f,
+ 0xec, 0x40, 0x97, 0xc2, 0xdc, 0xf4, 0xff, 0xff, 0x31, 0x15, 0x16, 0x60,
+ 0xda, 0x03, 0xad, 0xf9, 0xfc, 0xfd, 0xff, 0x80, 0x08, 0x0b, 0x43, 0x0b,
+ 0x7c, 0xed, 0x9e, 0xb0, 0x3c, 0xa8, 0x9c, 0x5b, 0x00, 0x64, 0xb5, 0xc1,
+ 0xeb, 0x6d, 0x16, 0xf0, 0x7d, 0xc4, 0x0b, 0x18, 0x7e, 0x01, 0xcb, 0x95,
+ 0xff, 0xff, 0x97, 0xc2, 0xd5, 0x82, 0x00, 0x00, 0xd4, 0xc2, 0xcb, 0x42,
+ 0x60, 0x7c, 0x00, 0x00, 0x00 };
+static u32 bnx2_COM_b09FwData[(0x0/4) + 1] = { 0x0 };
+static u32 bnx2_COM_b09FwRodata[(0x88/4) + 1] = {
+ 0x08001ad8, 0x08001b14, 0x08001b14, 0x08001b14, 0x08001b14, 0x08001b14,
+ 0x08001a24, 0x08001b14, 0x08001a98, 0x08001b14, 0x080019ac, 0x08001b14,
+ 0x08001b14, 0x08001b14, 0x080019b8, 0x0, 0x08002a2c, 0x08002a7c,
+ 0x08002aac, 0x08002adc, 0x08002b0c, 0x0, 0x08005fac, 0x08005fac,
+ 0x08005fac, 0x08005fac, 0x08005fac, 0x08005fd8, 0x08005fd8, 0x08006018,
+ 0x08006024, 0x08006024, 0x08005fac, 0x0, 0x0 };
+static u32 bnx2_COM_b09FwBss[(0x88/4) + 1] = { 0x0 };
+static u32 bnx2_COM_b09FwSbss[(0x5c/4) + 1] = { 0x0 };
+
+static struct fw_info bnx2_com_fw_09 = {
+ .ver_major = 0x1,
+ .ver_minor = 0x0,
+ .ver_fix = 0x0,
+
+ .start_addr = 0x080000b0,
+
+ .text_addr = 0x08000000,
+ .text_len = 0x7c5c,
+ .text_index = 0x0,
+ .gz_text = bnx2_COM_b09FwText,
+ .gz_text_len = sizeof(bnx2_COM_b09FwText),
+
+ .data_addr = 0x08007d00,
+ .data_len = 0x0,
+ .data_index = 0x0,
+ .data = bnx2_COM_b09FwData,
+
+ .sbss_addr = 0x08007d00,
+ .sbss_len = 0x5c,
+ .sbss_index = 0x0,
+ .sbss = bnx2_COM_b09FwSbss,
+
+ .bss_addr = 0x08007d60,
+ .bss_len = 0x88,
+ .bss_index = 0x0,
+ .bss = bnx2_COM_b09FwBss,
+
+ .rodata_addr = 0x08007c60,
+ .rodata_len = 0x88,
+ .rodata_index = 0x0,
+ .rodata = bnx2_COM_b09FwRodata,
+};
+
+static u8 bnx2_CP_b09FwText[] = {
+ 0x1f, 0x8b, 0x08, 0x08, 0x8e, 0xfc, 0x2f, 0x45, 0x00, 0x03, 0x74, 0x65,
+ 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xbd, 0x7d, 0x0d, 0x74,
+ 0x5c, 0x57, 0x7d, 0xe7, 0xff, 0xdd, 0x79, 0x92, 0xc6, 0xb2, 0x2c, 0x3f,
+ 0xcb, 0x63, 0x65, 0x22, 0x0b, 0x7b, 0x46, 0x7a, 0xb2, 0x95, 0x58, 0x64,
+ 0xc7, 0xae, 0x00, 0x6d, 0x3b, 0x85, 0xe9, 0x48, 0xb2, 0x9d, 0x0f, 0x8a,
+ 0x4c, 0x44, 0x4f, 0x5a, 0xe8, 0x22, 0xc6, 0x76, 0x48, 0x80, 0xb2, 0x4e,
+ 0x09, 0x69, 0x80, 0x04, 0x0f, 0x23, 0xf9, 0x83, 0x74, 0xec, 0x51, 0x12,
+ 0xc5, 0x76, 0x4f, 0x73, 0x58, 0x55, 0x92, 0x1d, 0x43, 0xa7, 0x1e, 0x27,
+ 0x71, 0x68, 0xf6, 0x6c, 0x68, 0xb4, 0x4a, 0xe2, 0xa6, 0x3d, 0xd9, 0xd6,
+ 0xf4, 0x84, 0x6e, 0xda, 0x43, 0x77, 0x85, 0x71, 0x88, 0x4b, 0xb3, 0x4b,
+ 0xf8, 0x68, 0x61, 0xa1, 0xe5, 0xed, 0xef, 0x77, 0xef, 0x7d, 0xd2, 0xe8,
+ 0xc3, 0x09, 0xa1, 0xbb, 0xf5, 0x39, 0xcf, 0x6f, 0xde, 0xfd, 0xfc, 0xdf,
+ 0xff, 0xfd, 0x7f, 0xdf, 0x0f, 0xad, 0x17, 0xa9, 0x17, 0xfb, 0x6f, 0x15,
+ 0x9e, 0x6d, 0x89, 0x7d, 0xbb, 0xb7, 0x5e, 0xd7, 0x73, 0x1d, 0x7e, 0x6e,
+ 0x75, 0x57, 0x46, 0x95, 0xbc, 0x89, 0x7f, 0x89, 0x9f, 0xa1, 0x4c, 0x44,
+ 0xc4, 0x0b, 0xfb, 0xe2, 0x23, 0x51, 0x95, 0x1e, 0xfc, 0x64, 0xd6, 0x97,
+ 0x68, 0x24, 0x7d, 0xf6, 0xb3, 0xbb, 0x7d, 0x91, 0x4c, 0x79, 0x4b, 0xa2,
+ 0x57, 0xfe, 0x25, 0xc8, 0xc7, 0x5c, 0x61, 0xfa, 0x5b, 0xd2, 0xff, 0xfc,
+ 0x9f, 0xbe, 0xf2, 0x8e, 0xe4, 0x6b, 0xe3, 0x11, 0x89, 0x7a, 0xe9, 0x8f,
+ 0x89, 0xb7, 0x49, 0xa2, 0xad, 0xe9, 0x81, 0x4f, 0x3e, 0xbc, 0xf9, 0x6f,
+ 0x44, 0x1a, 0xc3, 0xb6, 0x2e, 0x07, 0x5f, 0xd9, 0x2c, 0xf9, 0x96, 0x74,
+ 0x7c, 0xc8, 0x4d, 0x7b, 0xf2, 0x74, 0x45, 0x06, 0x0a, 0xc5, 0xa8, 0x44,
+ 0xd2, 0x1d, 0x2f, 0xf5, 0x46, 0xf6, 0x07, 0x11, 0xdf, 0xf7, 0x7a, 0xa5,
+ 0xa1, 0x27, 0xdb, 0x8d, 0xf4, 0xf2, 0x56, 0x51, 0x7e, 0x54, 0xb2, 0x15,
+ 0x69, 0x50, 0xbe, 0x8f, 0x77, 0xbd, 0xa8, 0x74, 0xd2, 0xcb, 0x46, 0x5c,
+ 0x29, 0x54, 0x2e, 0xac, 0x30, 0x6d, 0x96, 0xec, 0xfb, 0x6f, 0xa2, 0xe6,
+ 0x8d, 0x36, 0x4b, 0x51, 0x99, 0x8d, 0xc4, 0x05, 0xfd, 0x00, 0xe6, 0x06,
+ 0x19, 0x2e, 0x25, 0x24, 0x5b, 0x64, 0xbf, 0xae, 0xe4, 0x3c, 0xf6, 0xd9,
+ 0x80, 0xfa, 0x2b, 0x9d, 0xe5, 0xcb, 0xb3, 0xec, 0x4b, 0x28, 0x9b, 0x40,
+ 0xb9, 0x56, 0x79, 0xbc, 0x12, 0x97, 0xc7, 0x2a, 0x31, 0x79, 0xb4, 0x72,
+ 0x87, 0x64, 0x50, 0xf7, 0x6c, 0x05, 0x7d, 0x97, 0x6a, 0xa5, 0x77, 0xac,
+ 0x5e, 0xb2, 0x63, 0xed, 0xf1, 0x9c, 0x04, 0xc1, 0x27, 0x52, 0x1f, 0x95,
+ 0xa1, 0x26, 0x94, 0x2f, 0x31, 0x2f, 0xbe, 0x20, 0x2f, 0x97, 0xda, 0xe2,
+ 0xe5, 0x94, 0x23, 0x99, 0xc1, 0x64, 0x7c, 0x48, 0xf1, 0xbb, 0x46, 0xb2,
+ 0x5d, 0xf8, 0x1e, 0x70, 0x25, 0xe2, 0x07, 0xc1, 0x1d, 0xa9, 0x26, 0xc0,
+ 0x91, 0x4c, 0x24, 0x14, 0xeb, 0xb2, 0x5e, 0x32, 0x9f, 0x50, 0x51, 0xc9,
+ 0x57, 0xae, 0x93, 0x44, 0x53, 0x10, 0xbc, 0x37, 0xe5, 0x21, 0x5d, 0xa4,
+ 0xb7, 0x28, 0xfb, 0x54, 0xda, 0x47, 0x9b, 0x92, 0x52, 0xe9, 0xb5, 0x18,
+ 0xc7, 0x16, 0xe0, 0xa9, 0x56, 0x32, 0x31, 0xc9, 0xa8, 0xb4, 0x24, 0x54,
+ 0x7a, 0x05, 0xd2, 0x1c, 0xa9, 0xf1, 0xa7, 0x2c, 0x9d, 0xac, 0xc6, 0xb7,
+ 0x0c, 0xa8, 0x74, 0xd3, 0xa2, 0xf4, 0x64, 0x42, 0xd4, 0x8f, 0xea, 0xd0,
+ 0x67, 0x67, 0x46, 0x31, 0x0d, 0x6f, 0x9d, 0x76, 0xfd, 0x32, 0x69, 0x1f,
+ 0x74, 0x16, 0xa6, 0x3d, 0xb5, 0x8a, 0xb0, 0x8a, 0xe2, 0xef, 0x28, 0xe0,
+ 0x6a, 0x41, 0xff, 0xed, 0x5e, 0x0d, 0xc6, 0x35, 0x90, 0x4a, 0x7a, 0xfd,
+ 0xea, 0xc5, 0x40, 0x9a, 0x09, 0x33, 0xf3, 0x14, 0xf2, 0x50, 0x34, 0x9d,
+ 0xc2, 0xbc, 0xb9, 0x72, 0x08, 0x63, 0xbb, 0x38, 0x96, 0xf4, 0xda, 0x14,
+ 0xde, 0x53, 0xfc, 0xdd, 0x34, 0x14, 0x49, 0x07, 0x41, 0x36, 0x35, 0x2e,
+ 0xb9, 0x72, 0xd2, 0x9b, 0x05, 0x70, 0xbd, 0x63, 0x71, 0x8c, 0x1f, 0xe3,
+ 0x88, 0x65, 0x92, 0x6b, 0xa4, 0xcb, 0xce, 0xcf, 0x5f, 0xa2, 0xef, 0x76,
+ 0xef, 0x0e, 0xd5, 0xee, 0xa5, 0x54, 0xd2, 0x9b, 0x90, 0x3f, 0xc4, 0x77,
+ 0x10, 0xec, 0x4a, 0x25, 0xe3, 0x79, 0xcc, 0xdd, 0xa5, 0x62, 0x4c, 0x5e,
+ 0x2e, 0x26, 0x41, 0xa9, 0xc9, 0xce, 0x49, 0xd9, 0x92, 0x9a, 0x04, 0xdc,
+ 0x05, 0x3c, 0x07, 0x99, 0x57, 0x46, 0x5e, 0x99, 0x75, 0x83, 0xe0, 0xe6,
+ 0xd4, 0x89, 0x60, 0xa8, 0xd9, 0xd0, 0xfe, 0xd3, 0x25, 0xcc, 0x2b, 0xe6,
+ 0xe9, 0xb1, 0x12, 0xe6, 0xb5, 0x84, 0x39, 0xd5, 0xf3, 0xdf, 0x89, 0xf9,
+ 0x27, 0x8d, 0x90, 0x3e, 0xb6, 0x59, 0x7a, 0x7d, 0xb7, 0x7d, 0x8b, 0x64,
+ 0x4b, 0x8e, 0x64, 0x53, 0x3f, 0x09, 0x32, 0x9a, 0x27, 0xc4, 0xe9, 0x2d,
+ 0x91, 0x26, 0x6b, 0x00, 0x2b, 0x3f, 0x7f, 0xdd, 0x96, 0x8b, 0x3a, 0x18,
+ 0x06, 0xe7, 0x83, 0xf9, 0x51, 0xe5, 0xd7, 0xd9, 0xfc, 0x90, 0xf6, 0xf9,
+ 0x0f, 0x74, 0xe7, 0xcf, 0x97, 0xcb, 0x92, 0x36, 0x2b, 0x22, 0xb9, 0x07,
+ 0x03, 0xe9, 0x4d, 0x01, 0x5f, 0x6c, 0xd3, 0x4b, 0x89, 0xae, 0xeb, 0xb1,
+ 0x8c, 0x2e, 0x8b, 0x7f, 0x3f, 0xae, 0x41, 0x1f, 0x4e, 0x5f, 0x69, 0xbe,
+ 0x6e, 0x5f, 0xe9, 0x85, 0x98, 0x85, 0x0f, 0xdf, 0x3d, 0x4e, 0xb6, 0xf2,
+ 0x77, 0x76, 0x8e, 0xc3, 0x71, 0x74, 0x2d, 0x43, 0xe3, 0x2e, 0xf8, 0xc1,
+ 0x93, 0x5c, 0xb1, 0x07, 0xfd, 0xc6, 0xf0, 0x0e, 0x82, 0x91, 0x54, 0x26,
+ 0xe9, 0x4a, 0x1a, 0xdf, 0x03, 0x98, 0xaf, 0x0e, 0xe0, 0x4f, 0xdc, 0xec,
+ 0xe6, 0x94, 0xf4, 0x55, 0x40, 0x7b, 0x95, 0x37, 0x96, 0x14, 0x7a, 0x0c,
+ 0xa9, 0x7f, 0xb1, 0xb8, 0x61, 0x3f, 0x7c, 0xbb, 0x32, 0x02, 0xfa, 0x28,
+ 0x8c, 0xf9, 0x32, 0x5c, 0x9c, 0xf6, 0x94, 0x24, 0x41, 0xbb, 0x69, 0xe9,
+ 0xad, 0xf8, 0x52, 0x28, 0xe2, 0x5d, 0x6a, 0x07, 0xfd, 0xba, 0x92, 0x89,
+ 0x9b, 0x39, 0x29, 0x14, 0x7f, 0x09, 0xe3, 0x02, 0x8e, 0x7d, 0xfe, 0xee,
+ 0xb1, 0xb0, 0x80, 0xf7, 0xbb, 0x53, 0x1a, 0x3f, 0x6f, 0x0e, 0x06, 0xf6,
+ 0x8d, 0x31, 0x60, 0x9c, 0x85, 0xb2, 0x8b, 0x77, 0x0c, 0xef, 0x90, 0x16,
+ 0xe3, 0x80, 0xa9, 0x55, 0x86, 0x41, 0x8b, 0xbd, 0x82, 0xdf, 0x53, 0x84,
+ 0x91, 0xfd, 0xb6, 0xe8, 0xdf, 0xc3, 0x63, 0x1b, 0xf4, 0x77, 0x6e, 0xa0,
+ 0x45, 0xf2, 0x53, 0xe1, 0x58, 0x28, 0x0f, 0x28, 0x03, 0x92, 0x87, 0x45,
+ 0x28, 0x13, 0x82, 0xe0, 0xc1, 0x14, 0xe5, 0x42, 0x10, 0x3c, 0x96, 0xa2,
+ 0x9c, 0x38, 0x07, 0xfe, 0xa7, 0x6c, 0x20, 0xaf, 0xae, 0x55, 0x9c, 0x83,
+ 0x6c, 0x11, 0x7d, 0x40, 0x4e, 0xe4, 0xba, 0x4e, 0x40, 0x6e, 0x50, 0xae,
+ 0x5c, 0xf8, 0x44, 0xd6, 0xcf, 0xc7, 0x23, 0x1a, 0x0f, 0x98, 0x6f, 0xc8,
+ 0xbc, 0x8c, 0x86, 0xbc, 0x4d, 0x0a, 0x5d, 0xa3, 0xb6, 0xcc, 0x65, 0x5d,
+ 0xc6, 0x5d, 0x52, 0xe6, 0x76, 0x65, 0xf8, 0xae, 0x15, 0xf3, 0xb1, 0x42,
+ 0x11, 0x4f, 0x6d, 0x9b, 0xf8, 0x2d, 0xd1, 0x9a, 0xf4, 0x97, 0x90, 0x37,
+ 0x7d, 0xd7, 0x49, 0x7f, 0xb9, 0xbc, 0x59, 0x77, 0x69, 0xde, 0x88, 0xb8,
+ 0x7e, 0xb2, 0x73, 0x97, 0x9a, 0x01, 0x3d, 0x05, 0xc1, 0xc9, 0x54, 0x98,
+ 0xfe, 0x8f, 0xee, 0xd2, 0x3e, 0x12, 0x35, 0x4b, 0xd3, 0xee, 0x5d, 0x26,
+ 0xed, 0xc4, 0x32, 0x69, 0x1b, 0x6a, 0x97, 0xa6, 0xbd, 0x7f, 0x99, 0xb4,
+ 0xfb, 0x97, 0x49, 0xfb, 0x5f, 0xcb, 0xa4, 0x7d, 0x67, 0x99, 0xb4, 0xef,
+ 0x2d, 0x93, 0xd6, 0x52, 0xb7, 0x34, 0xcd, 0x05, 0x3f, 0x6d, 0x92, 0x42,
+ 0xec, 0x73, 0x1c, 0xbb, 0xc5, 0xcd, 0xfe, 0xc8, 0x52, 0xdc, 0xd4, 0xa0,
+ 0x5c, 0xeb, 0xa2, 0x72, 0x53, 0xcb, 0x94, 0xab, 0x45, 0xb9, 0xa6, 0x45,
+ 0xe5, 0x92, 0xcb, 0xe0, 0xba, 0x4e, 0xeb, 0xaf, 0x85, 0xe5, 0x0a, 0xcb,
+ 0x94, 0x63, 0xfa, 0x1e, 0xdb, 0xcf, 0x16, 0x68, 0x99, 0xd7, 0x9b, 0xaf,
+ 0x5a, 0x91, 0x66, 0xa6, 0xb7, 0x42, 0x47, 0xac, 0x50, 0x86, 0xdf, 0x29,
+ 0x5b, 0x98, 0xe6, 0x81, 0xee, 0xa3, 0xa0, 0x3b, 0xca, 0x47, 0xf0, 0x91,
+ 0x4f, 0xfe, 0x5d, 0x25, 0x43, 0xb1, 0x2d, 0xde, 0x2f, 0xa8, 0x06, 0xd0,
+ 0x58, 0xd2, 0x4b, 0x28, 0xf2, 0x97, 0xe4, 0x23, 0x69, 0x3f, 0xdf, 0x2b,
+ 0x2a, 0xa6, 0x24, 0x90, 0xbe, 0x94, 0x6a, 0x52, 0xb2, 0x1f, 0xfc, 0x93,
+ 0x81, 0x4e, 0xda, 0x15, 0xf4, 0x6a, 0x1e, 0x32, 0x65, 0xaf, 0x2c, 0x2b,
+ 0x7d, 0x39, 0x48, 0x19, 0x97, 0xce, 0xdc, 0x95, 0xf5, 0xa7, 0x7b, 0x6a,
+ 0x41, 0xb3, 0x17, 0x51, 0x67, 0x07, 0x6a, 0xee, 0x2d, 0xbb, 0xd2, 0x57,
+ 0xee, 0x04, 0x2f, 0x38, 0x72, 0xde, 0x5f, 0x2d, 0xe7, 0x53, 0x28, 0x5b,
+ 0x89, 0xc8, 0x4c, 0xcc, 0x91, 0x19, 0x7c, 0x67, 0x53, 0xc8, 0xab, 0x84,
+ 0xbc, 0xd5, 0x29, 0x07, 0x4a, 0xbe, 0x1c, 0x2e, 0xfd, 0x92, 0x0a, 0xf5,
+ 0x56, 0x7f, 0x6a, 0xa5, 0x9c, 0xf6, 0x4c, 0xdb, 0x3b, 0xfc, 0x69, 0x68,
+ 0x4c, 0x57, 0x2e, 0xfa, 0xc9, 0xf8, 0x8c, 0xe6, 0x89, 0x1f, 0x06, 0x7d,
+ 0x68, 0x67, 0xc2, 0x4f, 0x7a, 0x7f, 0x8a, 0xef, 0xa1, 0x32, 0xed, 0x90,
+ 0xf9, 0xb6, 0x86, 0xd1, 0xd6, 0xa1, 0xd2, 0x2a, 0xf9, 0xb0, 0xad, 0xbf,
+ 0xdd, 0x9f, 0xee, 0x04, 0xcf, 0x79, 0xa7, 0x28, 0x23, 0x8a, 0x80, 0x6b,
+ 0x10, 0xbc, 0x8d, 0xba, 0xcf, 0x69, 0x39, 0x05, 0xbb, 0xa5, 0xb8, 0x1a,
+ 0x72, 0xf7, 0x1f, 0x83, 0x0f, 0xc7, 0x58, 0x9e, 0x69, 0xd4, 0x25, 0x32,
+ 0xaa, 0xd2, 0x90, 0x09, 0xdd, 0x94, 0x85, 0x09, 0xc8, 0x41, 0xc8, 0x96,
+ 0xd2, 0x4f, 0x83, 0x8c, 0x5b, 0x2d, 0xdf, 0x24, 0x3f, 0x5f, 0x86, 0x69,
+ 0x09, 0x23, 0x2f, 0x4b, 0xb3, 0x73, 0xb2, 0x22, 0x0f, 0xf9, 0xf2, 0x74,
+ 0x85, 0x72, 0xe1, 0x7a, 0xf0, 0x68, 0xab, 0xf4, 0x15, 0x93, 0xf9, 0x8c,
+ 0x6c, 0xc2, 0xfc, 0x7d, 0x1e, 0x73, 0xea, 0xe2, 0xb9, 0xaf, 0x5e, 0x1a,
+ 0x53, 0xd0, 0xcd, 0x4c, 0x47, 0xa3, 0xcd, 0x51, 0xc8, 0xa8, 0xdf, 0x03,
+ 0x1e, 0x86, 0x39, 0xe7, 0xf1, 0x6c, 0xc4, 0x19, 0xa0, 0x3d, 0x32, 0x40,
+ 0xfd, 0x50, 0x66, 0xdb, 0x84, 0x37, 0x6e, 0x7f, 0x47, 0xb5, 0x8c, 0x31,
+ 0xbf, 0x1b, 0xf0, 0x3b, 0x61, 0x7f, 0x7b, 0xf8, 0xed, 0xdb, 0xdf, 0x31,
+ 0xfc, 0xee, 0xb4, 0xbf, 0xa1, 0x5b, 0x8b, 0x5d, 0xfa, 0xf7, 0x48, 0x69,
+ 0xfb, 0x76, 0xe5, 0x5f, 0x27, 0xb9, 0xa9, 0x56, 0x39, 0x50, 0xf4, 0xad,
+ 0x6c, 0xc1, 0x23, 0x4f, 0x3a, 0x66, 0x9c, 0x80, 0x9b, 0xb2, 0xb3, 0x94,
+ 0x77, 0x06, 0x08, 0x3f, 0x68, 0xa0, 0xb7, 0xb8, 0xc5, 0x5b, 0x23, 0xa4,
+ 0x81, 0x11, 0xa7, 0xb7, 0xe2, 0x64, 0x60, 0xaf, 0xc5, 0x87, 0xe5, 0x30,
+ 0x7e, 0x8b, 0x17, 0x49, 0x3f, 0x89, 0xb7, 0xc1, 0x01, 0xf5, 0xce, 0x70,
+ 0x89, 0xf2, 0xd2, 0xc7, 0xd8, 0x13, 0x72, 0x6e, 0x81, 0x0d, 0x45, 0x5c,
+ 0x28, 0xc9, 0x8d, 0x25, 0x4f, 0xe4, 0x25, 0x99, 0x1f, 0x07, 0x43, 0xec,
+ 0x4a, 0xb9, 0xf2, 0xde, 0x14, 0x68, 0xf7, 0x3a, 0x47, 0xb6, 0x5f, 0xe7,
+ 0xc2, 0xe6, 0xf1, 0xc7, 0xb7, 0x83, 0xfe, 0x31, 0xcf, 0x9a, 0x1e, 0xd4,
+ 0x19, 0x81, 0x9d, 0x08, 0x6c, 0x9f, 0xe9, 0xea, 0x1b, 0x2e, 0xe6, 0x3e,
+ 0xa6, 0xd2, 0xfb, 0x3e, 0x95, 0xed, 0xbe, 0x46, 0x72, 0x83, 0x0a, 0x38,
+ 0x6a, 0x1e, 0x82, 0x1e, 0xc4, 0xb8, 0x82, 0x00, 0xf4, 0x0c, 0x79, 0x7e,
+ 0xf3, 0xcd, 0x91, 0x74, 0x8d, 0xf4, 0x0e, 0x36, 0xa3, 0x0e, 0xf3, 0x88,
+ 0xaf, 0xaf, 0xa2, 0x9d, 0x64, 0xa2, 0x4f, 0xe4, 0x9e, 0x91, 0xee, 0x59,
+ 0x67, 0x78, 0xf4, 0x37, 0xc0, 0x93, 0x5b, 0x51, 0xff, 0x01, 0xd4, 0x7f,
+ 0xcd, 0x29, 0x8c, 0xfd, 0xc8, 0x19, 0x1e, 0xfb, 0x9e, 0x33, 0x32, 0xb6,
+ 0x61, 0x43, 0x7f, 0xcf, 0x86, 0x0d, 0xbb, 0x7b, 0x5c, 0x99, 0x00, 0x8f,
+ 0x65, 0xbc, 0x0d, 0x1b, 0x46, 0x7a, 0xba, 0x80, 0x83, 0x2d, 0x5e, 0x9f,
+ 0xf8, 0xde, 0x76, 0x01, 0xff, 0xc4, 0xd8, 0x67, 0x14, 0xf9, 0x49, 0xe4,
+ 0xb3, 0x7e, 0x5c, 0xe7, 0xf7, 0xca, 0x96, 0x78, 0x93, 0xb0, 0xff, 0x88,
+ 0x2d, 0x53, 0x13, 0x91, 0xfa, 0x07, 0xec, 0xfc, 0x66, 0x9c, 0x1a, 0x9f,
+ 0xe9, 0x1c, 0x0b, 0xd3, 0x39, 0xb7, 0x7f, 0x67, 0x6d, 0xd5, 0xd5, 0x48,
+ 0xe7, 0x37, 0x71, 0x46, 0xbc, 0xd0, 0xc6, 0xa8, 0xd1, 0xb6, 0x61, 0xae,
+ 0x48, 0x9a, 0x71, 0x65, 0x4f, 0xd1, 0x41, 0x1d, 0xd0, 0xc5, 0x19, 0xfb,
+ 0x1c, 0x05, 0x6c, 0x83, 0x68, 0xeb, 0xe8, 0x21, 0xd4, 0xa3, 0xcc, 0x48,
+ 0x76, 0x8a, 0xfa, 0x00, 0xca, 0x6c, 0xf1, 0xd6, 0x0a, 0x6d, 0x89, 0x3b,
+ 0x25, 0x57, 0x22, 0x7f, 0x77, 0x00, 0x9e, 0xa8, 0x24, 0x9a, 0xf1, 0x5d,
+ 0x81, 0x4d, 0xf1, 0x60, 0x8d, 0x58, 0xdb, 0x45, 0xe6, 0x6d, 0x91, 0x3b,
+ 0x94, 0xc0, 0xde, 0x18, 0x9a, 0x5c, 0x8f, 0x72, 0x0e, 0xf0, 0x42, 0xfb,
+ 0x03, 0xb4, 0x36, 0x99, 0x91, 0xec, 0x26, 0xf0, 0xc9, 0xa4, 0x87, 0x6f,
+ 0xc0, 0x35, 0xf9, 0x16, 0xbc, 0x23, 0xfa, 0xdb, 0xc0, 0x09, 0xbc, 0xa6,
+ 0x22, 0x56, 0x67, 0x75, 0xa1, 0xef, 0xf7, 0x48, 0x76, 0x34, 0x4e, 0x5b,
+ 0x62, 0x75, 0xd6, 0xcf, 0x40, 0xd7, 0x2b, 0x28, 0x41, 0x8c, 0x61, 0xd2,
+ 0x81, 0x3c, 0xa9, 0x95, 0xdd, 0x8f, 0xe0, 0xf7, 0x83, 0xc6, 0xe6, 0xdd,
+ 0x3d, 0xc9, 0x7e, 0x1a, 0x00, 0x13, 0x6c, 0x90, 0x47, 0x60, 0x9b, 0x3e,
+ 0x02, 0x1b, 0xe4, 0x91, 0x66, 0x3c, 0x1c, 0x1b, 0xdb, 0x9f, 0x59, 0x03,
+ 0x31, 0xa9, 0xbf, 0x73, 0xa4, 0x57, 0xd8, 0xea, 0xb9, 0x62, 0xca, 0x94,
+ 0x2f, 0x76, 0xeb, 0xb7, 0xa1, 0xeb, 0x1e, 0xfb, 0x3b, 0xae, 0xf9, 0x3a,
+ 0xdf, 0x04, 0x9a, 0xaf, 0x74, 0x69, 0x99, 0x93, 0xf5, 0xf1, 0x86, 0xcd,
+ 0x99, 0x69, 0xe2, 0x18, 0xe3, 0x36, 0x2d, 0xae, 0xd3, 0x12, 0x4d, 0xd6,
+ 0xde, 0x28, 0x59, 0x5b, 0x03, 0xb8, 0x19, 0x6a, 0x06, 0xc4, 0x94, 0xcf,
+ 0x12, 0xe2, 0x93, 0x32, 0x00, 0xf4, 0x0b, 0x9b, 0xe2, 0xdc, 0x15, 0xe5,
+ 0xdf, 0xac, 0xb6, 0xb1, 0xce, 0x56, 0x48, 0xc7, 0xa4, 0xed, 0x20, 0xb8,
+ 0x3f, 0x55, 0x87, 0xf6, 0xc9, 0xf3, 0xb0, 0x40, 0x8e, 0x02, 0x26, 0x60,
+ 0xa2, 0xc6, 0x3f, 0xab, 0x69, 0xa0, 0xd6, 0x27, 0x0d, 0x57, 0xf3, 0x97,
+ 0xe8, 0xf1, 0x9e, 0x05, 0x8f, 0xc1, 0xbe, 0x81, 0xfd, 0xd6, 0x01, 0xdb,
+ 0x98, 0x7d, 0x1c, 0xe6, 0xb7, 0xa7, 0xc0, 0x53, 0xd9, 0x39, 0x9e, 0x12,
+ 0x99, 0x28, 0x12, 0x37, 0xa1, 0x5d, 0xc7, 0x79, 0x26, 0x7e, 0x32, 0x18,
+ 0x33, 0xdf, 0x7d, 0x16, 0x4f, 0x3b, 0x2d, 0x9e, 0x6e, 0xb2, 0xef, 0x11,
+ 0xbc, 0x69, 0xe3, 0x0d, 0xe0, 0xcd, 0xf9, 0x19, 0xc4, 0x9b, 0xbc, 0x75,
+ 0x0b, 0xde, 0x28, 0x5b, 0xca, 0xc8, 0x6e, 0x6d, 0x87, 0x45, 0xe4, 0x57,
+ 0xb4, 0x6c, 0xfb, 0x02, 0xe6, 0xb2, 0x48, 0xfa, 0x95, 0x7c, 0x2c, 0x02,
+ 0x9c, 0x14, 0xf0, 0xfb, 0x4e, 0xd7, 0xd0, 0x2a, 0x71, 0xb2, 0xc0, 0x57,
+ 0xaa, 0x82, 0x29, 0x66, 0xe5, 0x5c, 0x42, 0xdb, 0xfa, 0xb9, 0xe2, 0x07,
+ 0x34, 0x5c, 0xb7, 0x42, 0xde, 0xe5, 0x45, 0x35, 0x43, 0x37, 0x80, 0x16,
+ 0x54, 0x0c, 0x9a, 0x2b, 0x78, 0x06, 0x7a, 0x29, 0x37, 0x49, 0xdb, 0xb8,
+ 0x8d, 0x7e, 0x49, 0x34, 0xd7, 0xd5, 0x48, 0x3a, 0x52, 0x0a, 0xf6, 0x17,
+ 0xbe, 0x55, 0xae, 0x4b, 0xd3, 0xa9, 0xa3, 0xfc, 0x98, 0xb6, 0x7f, 0x5d,
+ 0x1f, 0xd2, 0xd6, 0xf8, 0xbd, 0xae, 0xf2, 0xd7, 0x2e, 0x4e, 0x4b, 0x50,
+ 0x0f, 0xa3, 0x5e, 0x22, 0xd7, 0xd5, 0x4c, 0x1e, 0xf3, 0x40, 0xbf, 0x19,
+ 0xe5, 0x6b, 0xdf, 0x27, 0xaf, 0xba, 0x57, 0x2f, 0x2a, 0xaf, 0xdf, 0x8e,
+ 0xfd, 0x76, 0xed, 0xdb, 0xb3, 0xef, 0x84, 0x7d, 0xe7, 0xdd, 0x6e, 0xbe,
+ 0x1d, 0x71, 0xd3, 0x7c, 0x83, 0x92, 0xd3, 0x6c, 0x43, 0xf3, 0x95, 0x95,
+ 0x33, 0x1d, 0x5e, 0x41, 0xc8, 0x57, 0x9f, 0x93, 0x5b, 0x27, 0x8d, 0xfc,
+ 0xdd, 0x0e, 0x19, 0x04, 0xff, 0xcc, 0x9b, 0x11, 0xc0, 0x3f, 0x98, 0x96,
+ 0x5b, 0x2b, 0xc4, 0xdb, 0xef, 0x02, 0x7f, 0x60, 0xe2, 0x7a, 0xea, 0x74,
+ 0xca, 0xdd, 0x3b, 0x61, 0xf7, 0xa2, 0x7c, 0x91, 0x38, 0x1f, 0xd2, 0x73,
+ 0x53, 0x28, 0xee, 0xd1, 0x73, 0x73, 0xb0, 0x38, 0x03, 0xfc, 0xdc, 0x06,
+ 0xba, 0x0f, 0x82, 0x99, 0x54, 0x01, 0x94, 0xf3, 0x11, 0xfc, 0x86, 0x1d,
+ 0x50, 0xfc, 0x18, 0xf2, 0x1b, 0xa5, 0x30, 0x4a, 0x9e, 0x73, 0x2d, 0x0f,
+ 0xbf, 0x13, 0xfc, 0x14, 0x45, 0xbb, 0x48, 0xeb, 0xe6, 0xef, 0x9f, 0x20,
+ 0x0f, 0xef, 0x49, 0x4c, 0x62, 0x33, 0x6d, 0x1d, 0xf6, 0xcd, 0xb9, 0xe3,
+ 0x9c, 0xc5, 0xb4, 0x2c, 0x3f, 0x3b, 0x37, 0x6f, 0x97, 0xe7, 0xe8, 0x36,
+ 0x4f, 0x1f, 0x8f, 0xf9, 0x1a, 0x56, 0xd2, 0xfd, 0xb7, 0xb4, 0x5c, 0x72,
+ 0x8f, 0xce, 0xac, 0x30, 0xef, 0xc5, 0x75, 0x39, 0xe7, 0xd5, 0x34, 0x48,
+ 0xbf, 0x25, 0xd9, 0x93, 0x07, 0x3f, 0x61, 0x9c, 0xd2, 0xa7, 0x7d, 0x1d,
+ 0xd2, 0x04, 0x69, 0x60, 0xdc, 0xd2, 0xe6, 0x94, 0xa5, 0xcd, 0x27, 0xf1,
+ 0xc6, 0x53, 0xba, 0x60, 0x69, 0xf3, 0x29, 0xbc, 0xf1, 0x94, 0x5e, 0x9c,
+ 0xe3, 0xe3, 0x5e, 0xf8, 0x72, 0xdb, 0xa1, 0xdf, 0x76, 0x57, 0x40, 0xbf,
+ 0xe0, 0xbb, 0x1c, 0x7c, 0x80, 0x5c, 0x69, 0x1f, 0xde, 0xec, 0x67, 0xa3,
+ 0x6d, 0x3f, 0x23, 0x7b, 0x4a, 0x01, 0xc6, 0x78, 0x37, 0xc6, 0xfb, 0x39,
+ 0xbc, 0x3f, 0xa3, 0xe5, 0x8c, 0xf2, 0x0f, 0x5b, 0x79, 0xf5, 0x79, 0xbc,
+ 0xdb, 0xe3, 0x07, 0xa5, 0xdd, 0x8b, 0xc8, 0x34, 0xda, 0xfa, 0xba, 0xec,
+ 0xa9, 0xcc, 0xe2, 0xb9, 0x84, 0xe7, 0x55, 0x3c, 0x97, 0xd1, 0xde, 0x0b,
+ 0x48, 0x5f, 0x29, 0xd3, 0x5e, 0x3d, 0xca, 0xbf, 0x86, 0xdf, 0xcf, 0xcb,
+ 0xd0, 0x23, 0x2f, 0xe1, 0xf9, 0x01, 0xf2, 0x9f, 0x45, 0xfd, 0x60, 0xf5,
+ 0x8c, 0x4f, 0x19, 0xf6, 0x9c, 0x6d, 0x3b, 0xe5, 0xe4, 0x2a, 0xa0, 0xe9,
+ 0xd2, 0x00, 0xfa, 0xde, 0xa3, 0x79, 0xa6, 0x0f, 0x32, 0x3f, 0x07, 0x19,
+ 0x37, 0xa4, 0x61, 0x6a, 0x07, 0x7c, 0x79, 0xcc, 0x05, 0xde, 0x93, 0xb5,
+ 0x32, 0x1b, 0xa3, 0x1d, 0x79, 0x93, 0x2e, 0x9f, 0x2b, 0x35, 0x69, 0xbb,
+ 0x7a, 0x7c, 0x09, 0xff, 0xd0, 0xef, 0x0a, 0xe5, 0x81, 0x91, 0xc6, 0x13,
+ 0x45, 0xca, 0x02, 0xe8, 0x9f, 0xe2, 0x08, 0xde, 0xb5, 0x5a, 0x26, 0x14,
+ 0x24, 0x94, 0x07, 0xac, 0x47, 0x99, 0x50, 0x2d, 0x77, 0x28, 0x6b, 0x28,
+ 0x7b, 0x28, 0x4b, 0xcc, 0x7c, 0xec, 0x7e, 0x90, 0x32, 0x1c, 0xb4, 0x10,
+ 0xa3, 0xfd, 0xe1, 0x19, 0x1f, 0x64, 0xec, 0x3e, 0x2b, 0x4f, 0x47, 0xf5,
+ 0x5c, 0xec, 0x29, 0xaa, 0x98, 0x2b, 0xa7, 0x91, 0x86, 0xe7, 0xf8, 0xc3,
+ 0x78, 0x7f, 0x49, 0xf6, 0xe0, 0xc9, 0x1d, 0xff, 0x02, 0x7e, 0x73, 0x6e,
+ 0xca, 0x28, 0x87, 0xa7, 0x74, 0x02, 0x6f, 0x3c, 0xa5, 0x31, 0x2b, 0x47,
+ 0xc6, 0xad, 0x1c, 0xe1, 0x9c, 0xde, 0x04, 0x3c, 0x70, 0x7c, 0x4a, 0xc7,
+ 0x17, 0xc0, 0xcf, 0x4e, 0x6e, 0xf2, 0x5d, 0xd6, 0x8f, 0x6d, 0x14, 0xc3,
+ 0x83, 0x78, 0x3a, 0xc9, 0xcf, 0x0d, 0xda, 0x0e, 0xce, 0x69, 0xda, 0xfd,
+ 0x2b, 0xd7, 0xf0, 0x62, 0xcc, 0xe8, 0x14, 0xaf, 0x59, 0x34, 0xef, 0xcf,
+ 0xe1, 0x31, 0x63, 0xf1, 0xc8, 0xdf, 0xca, 0xfe, 0x86, 0xdc, 0x82, 0x4d,
+ 0x9b, 0xf5, 0x7d, 0xcc, 0x03, 0xc6, 0x72, 0x7c, 0x14, 0x7d, 0x3b, 0xb2,
+ 0xdb, 0xa7, 0x0c, 0x67, 0x0c, 0x81, 0xe3, 0x63, 0xbb, 0x48, 0xd7, 0x38,
+ 0x48, 0xc9, 0xbc, 0x6f, 0x7e, 0x13, 0xe6, 0x2c, 0x23, 0x7b, 0x4b, 0xf7,
+ 0x6a, 0x5f, 0xb9, 0xf6, 0x68, 0x93, 0xf5, 0x73, 0xc2, 0x72, 0xa0, 0xd5,
+ 0x18, 0x6d, 0x9b, 0x2f, 0xc5, 0x0c, 0xcd, 0xf3, 0x37, 0xe5, 0x73, 0xb5,
+ 0xbc, 0x37, 0x76, 0x4d, 0x61, 0x81, 0xac, 0xa3, 0x6d, 0x81, 0x39, 0x2b,
+ 0x57, 0xe3, 0x9d, 0xbe, 0x3b, 0xf9, 0x8a, 0xfc, 0x74, 0x10, 0x3c, 0xf1,
+ 0x5d, 0xcb, 0xfb, 0xf4, 0x35, 0xd8, 0xe7, 0x62, 0x7e, 0xf2, 0x60, 0xfb,
+ 0xba, 0x72, 0x0a, 0xb6, 0xdb, 0xf6, 0xb9, 0x36, 0xae, 0x06, 0x3c, 0x51,
+ 0x79, 0xa4, 0xd8, 0x20, 0x93, 0x45, 0xd5, 0x1c, 0xb1, 0xb2, 0x33, 0x22,
+ 0x09, 0x4d, 0xdf, 0xb4, 0xef, 0x7a, 0xc7, 0x22, 0x96, 0xee, 0xd6, 0xd5,
+ 0x48, 0xfd, 0xef, 0x42, 0xc7, 0xa6, 0xa1, 0x63, 0x1b, 0xa1, 0x83, 0x17,
+ 0xcb, 0x88, 0x35, 0x35, 0x4b, 0x65, 0x04, 0xeb, 0x24, 0xe1, 0x75, 0x1f,
+ 0x44, 0xbd, 0x90, 0xfe, 0xa2, 0x9a, 0xd6, 0x72, 0x92, 0x77, 0xb6, 0x57,
+ 0x46, 0x9c, 0x1d, 0x95, 0xc5, 0x3a, 0x68, 0x8b, 0xe7, 0x8a, 0x81, 0xf5,
+ 0x91, 0x22, 0x6d, 0xd4, 0x64, 0x2a, 0x0b, 0x9c, 0xec, 0x00, 0xcc, 0xcf,
+ 0x8c, 0xc2, 0x4f, 0xa7, 0x5c, 0x06, 0xcc, 0xa7, 0x01, 0xf3, 0xc4, 0xa8,
+ 0x13, 0xda, 0x06, 0xc2, 0xa0, 0xc8, 0xc4, 0x58, 0x97, 0xcc, 0x4c, 0x91,
+ 0x0e, 0x21, 0x03, 0x46, 0x31, 0x9f, 0xa9, 0x15, 0xb0, 0x03, 0xd8, 0x3f,
+ 0xe4, 0xf6, 0x58, 0x8b, 0xce, 0x33, 0xfa, 0xbc, 0x55, 0x66, 0xca, 0x69,
+ 0x0b, 0xdb, 0xe1, 0x2a, 0xd8, 0x56, 0xcc, 0xc1, 0xb6, 0x03, 0xb0, 0xed,
+ 0x5c, 0x16, 0xb6, 0xe5, 0x74, 0x71, 0x1b, 0x6c, 0x1a, 0xa3, 0x8b, 0x0d,
+ 0x5e, 0x9b, 0x2d, 0x3d, 0xbc, 0xdf, 0xda, 0xbb, 0xb4, 0x89, 0x7e, 0x0a,
+ 0x78, 0x48, 0x63, 0xf8, 0x3d, 0x79, 0x2f, 0x65, 0x19, 0xd2, 0xf9, 0xbd,
+ 0x07, 0x65, 0xf0, 0x3d, 0xf9, 0x67, 0x2b, 0x4c, 0xd9, 0xbb, 0x2d, 0x2c,
+ 0xb4, 0x13, 0x32, 0xb0, 0x89, 0xfb, 0x9c, 0xec, 0x24, 0x61, 0xf8, 0x8f,
+ 0x80, 0x17, 0x79, 0x95, 0xea, 0x36, 0xf9, 0x66, 0xbb, 0xd7, 0xda, 0x76,
+ 0xd8, 0x76, 0x38, 0x96, 0x95, 0x56, 0xcf, 0x87, 0xf4, 0x15, 0xda, 0xd7,
+ 0x23, 0x4e, 0x66, 0xc9, 0xb8, 0xaa, 0x69, 0x8e, 0xf2, 0xd6, 0x95, 0x7e,
+ 0xd0, 0x49, 0xff, 0x02, 0x5a, 0x33, 0x72, 0xc3, 0xd0, 0xf1, 0x0a, 0x3b,
+ 0xbe, 0x1a, 0xc3, 0x37, 0xa9, 0x28, 0xf4, 0x21, 0xe5, 0xcd, 0x0e, 0xe3,
+ 0x9b, 0xcb, 0x43, 0x80, 0x35, 0xfc, 0x3e, 0xa8, 0x6d, 0xce, 0xa7, 0x4b,
+ 0x94, 0x49, 0xf3, 0xb4, 0x68, 0x7c, 0x97, 0x56, 0xf4, 0x55, 0x6d, 0xaf,
+ 0xbb, 0x32, 0x60, 0xe6, 0xfc, 0x30, 0xe7, 0x9c, 0xbe, 0x48, 0xfb, 0x03,
+ 0x03, 0x96, 0xbf, 0x92, 0xa3, 0x79, 0x79, 0xbb, 0x1d, 0xfb, 0x1f, 0x2e,
+ 0x33, 0x77, 0x8d, 0x73, 0x73, 0x37, 0x50, 0x59, 0x3c, 0x46, 0x91, 0xb6,
+ 0x07, 0x58, 0xcf, 0x85, 0x8d, 0x94, 0x92, 0x5a, 0x9f, 0xf2, 0x93, 0xb6,
+ 0x12, 0xd2, 0x27, 0xb6, 0x78, 0x4d, 0xf0, 0x01, 0x9e, 0x5e, 0x62, 0x77,
+ 0x25, 0xac, 0xdc, 0xa4, 0x1f, 0x1c, 0xf6, 0x91, 0xb7, 0x72, 0x32, 0x8f,
+ 0xf6, 0x47, 0x9c, 0xfe, 0xca, 0x72, 0xf2, 0x32, 0x94, 0x93, 0x1c, 0x8f,
+ 0x23, 0x77, 0x3c, 0x48, 0x1e, 0x7d, 0xbf, 0xb6, 0xaf, 0xb7, 0x6e, 0xab,
+ 0x01, 0xfe, 0x08, 0xc7, 0xcc, 0x1a, 0xa2, 0x33, 0xf7, 0x08, 0x6c, 0x22,
+ 0x3b, 0x6f, 0xbb, 0xe7, 0xe6, 0x5f, 0xd3, 0x05, 0x7e, 0x33, 0x8e, 0x6a,
+ 0x68, 0xa4, 0xc6, 0x77, 0x34, 0x2d, 0xd4, 0x2e, 0xb1, 0x65, 0x39, 0x06,
+ 0xda, 0xb3, 0xb5, 0xc6, 0x16, 0x2c, 0xd1, 0xfe, 0xa4, 0xec, 0xa2, 0xfd,
+ 0xf9, 0x43, 0xe0, 0x88, 0xe3, 0xe9, 0xb2, 0x69, 0xb4, 0x53, 0x17, 0x8f,
+ 0x6f, 0xb1, 0xff, 0x48, 0x38, 0x09, 0xb7, 0xa1, 0xad, 0x84, 0x22, 0x6c,
+ 0x81, 0x0c, 0x80, 0x97, 0x39, 0x07, 0x8a, 0xb6, 0xeb, 0xb6, 0xbf, 0xa8,
+ 0x31, 0x31, 0xe4, 0xd5, 0xb5, 0x52, 0xcf, 0x3e, 0xc9, 0x7f, 0x7c, 0xaf,
+ 0xd2, 0xf6, 0xef, 0x52, 0x59, 0x56, 0xad, 0x7b, 0xae, 0x9e, 0xc3, 0x5f,
+ 0xff, 0x82, 0x39, 0x0a, 0xf1, 0x17, 0xd2, 0x45, 0x35, 0x0e, 0x49, 0x13,
+ 0x86, 0x16, 0x0c, 0x2d, 0x6e, 0xb4, 0xfa, 0x26, 0xa4, 0xbd, 0xab, 0x40,
+ 0x7b, 0xf7, 0x81, 0xc6, 0x28, 0xc3, 0x19, 0x97, 0x5b, 0x8b, 0xef, 0x23,
+ 0xf8, 0x0e, 0xf9, 0xe4, 0x4a, 0x32, 0x9c, 0xf2, 0x9b, 0x75, 0xb2, 0x56,
+ 0xee, 0x87, 0x7e, 0x2e, 0xeb, 0x70, 0xdc, 0x94, 0xff, 0xff, 0x15, 0xed,
+ 0xac, 0xad, 0x35, 0xf6, 0xca, 0x8d, 0xb5, 0x94, 0xaf, 0x6b, 0xe4, 0x60,
+ 0x55, 0xda, 0x95, 0xe4, 0x77, 0xf5, 0x98, 0xd7, 0xff, 0x3f, 0x18, 0x73,
+ 0x7c, 0xd1, 0x98, 0x3d, 0x3b, 0xe6, 0x77, 0x21, 0xbf, 0xc9, 0xf8, 0x38,
+ 0x1e, 0xf9, 0x2e, 0x1c, 0xb3, 0xc5, 0x85, 0x1e, 0x57, 0xb5, 0x9c, 0x08,
+ 0x65, 0x04, 0xc7, 0x35, 0x60, 0xc7, 0xf0, 0xb9, 0xaa, 0x71, 0x0d, 0xbc,
+ 0x89, 0x71, 0xb5, 0x2e, 0x18, 0xd7, 0xf6, 0x2b, 0x8e, 0x6b, 0x39, 0x1e,
+ 0x27, 0x2f, 0x87, 0xe3, 0x8b, 0xca, 0xae, 0x22, 0xc7, 0xd8, 0x8f, 0x31,
+ 0x1e, 0xd4, 0xfe, 0x80, 0x19, 0x63, 0xda, 0x8e, 0x51, 0x54, 0xdb, 0xb6,
+ 0x7f, 0x8f, 0xdf, 0xd5, 0xe3, 0xa3, 0xee, 0xff, 0x3e, 0x68, 0xba, 0x4e,
+ 0xb2, 0x5d, 0x75, 0x56, 0xfe, 0xdf, 0x24, 0x1f, 0x2e, 0x71, 0xae, 0x93,
+ 0x19, 0x91, 0x51, 0xe8, 0xe0, 0xff, 0x5c, 0xcb, 0xd8, 0xfd, 0xf6, 0x94,
+ 0xd5, 0x63, 0xd0, 0x17, 0x3b, 0x60, 0xf3, 0xf5, 0x17, 0x55, 0x77, 0x44,
+ 0x82, 0xe0, 0xb6, 0xd4, 0xa7, 0xd1, 0xf7, 0x7e, 0xed, 0xab, 0x2e, 0x8d,
+ 0x9b, 0x3f, 0x57, 0x2b, 0x3e, 0xed, 0x0d, 0xea, 0x73, 0xe8, 0xbb, 0xe3,
+ 0xb4, 0xc1, 0xb2, 0xb0, 0x93, 0x33, 0xf1, 0x88, 0xb6, 0xc5, 0xa8, 0x13,
+ 0x93, 0xf1, 0x8c, 0xa4, 0xd1, 0x5f, 0x26, 0xae, 0x84, 0x7d, 0xc0, 0x56,
+ 0x83, 0x0d, 0xf9, 0xe1, 0xca, 0x3e, 0x3c, 0x0f, 0xcb, 0xad, 0xb0, 0x77,
+ 0x6e, 0x7d, 0xe4, 0x0b, 0x72, 0x1b, 0x6c, 0x9d, 0xdb, 0x1e, 0x19, 0x93,
+ 0xbd, 0xb0, 0x6d, 0xf6, 0xc2, 0xce, 0xd9, 0x5b, 0xa1, 0xed, 0x39, 0x8e,
+ 0xb2, 0xad, 0x55, 0xb4, 0x46, 0x1b, 0x87, 0xe3, 0x23, 0xee, 0x0f, 0x72,
+ 0x0e, 0x52, 0x09, 0xf5, 0x8a, 0x9e, 0x97, 0xa6, 0x05, 0x69, 0xaf, 0x27,
+ 0xab, 0x42, 0xfd, 0xb4, 0xca, 0xc6, 0x8d, 0x8c, 0x0d, 0x78, 0x65, 0xda,
+ 0x22, 0x8d, 0x78, 0xc0, 0x33, 0xf1, 0x47, 0xda, 0xaa, 0x1e, 0x7f, 0x63,
+ 0x9d, 0xf8, 0x2b, 0xeb, 0xa4, 0xfe, 0x73, 0x90, 0xaf, 0xd5, 0x34, 0xc5,
+ 0xb7, 0x67, 0x75, 0x0d, 0x69, 0x8b, 0x32, 0x38, 0xa4, 0x87, 0x8d, 0xaf,
+ 0x23, 0x7f, 0xaf, 0x48, 0x4f, 0xfb, 0xb9, 0x2e, 0xb3, 0xbb, 0x5b, 0x56,
+ 0x33, 0x1e, 0x90, 0xad, 0xcc, 0xc7, 0x04, 0x94, 0x5f, 0x1d, 0x13, 0xa0,
+ 0x9f, 0xf5, 0x01, 0xe0, 0xec, 0x16, 0x3c, 0xfb, 0x64, 0x88, 0x71, 0x87,
+ 0x4a, 0x68, 0x97, 0x7f, 0xd5, 0xda, 0xe5, 0x21, 0x1c, 0x09, 0xc0, 0x61,
+ 0xe4, 0xf3, 0x52, 0x3d, 0xb7, 0x50, 0x7f, 0xe7, 0xe7, 0x6c, 0xda, 0x84,
+ 0xec, 0x2a, 0x71, 0xdc, 0x94, 0xc1, 0xc4, 0x4d, 0xb5, 0x0c, 0x8e, 0x5b,
+ 0x3b, 0x0a, 0x65, 0xb4, 0xfc, 0x5c, 0x2a, 0x3b, 0x29, 0xf7, 0x18, 0x9f,
+ 0x7f, 0x20, 0x45, 0x5a, 0x7f, 0xb7, 0x64, 0xe6, 0xe2, 0xf3, 0x02, 0x7a,
+ 0x93, 0x54, 0x24, 0xad, 0xd7, 0xd3, 0xbc, 0x09, 0xd9, 0x21, 0xbd, 0x31,
+ 0xc6, 0x3a, 0x19, 0xcf, 0xf3, 0xf3, 0x13, 0xb0, 0x1f, 0x86, 0x4b, 0x0a,
+ 0x16, 0x7c, 0xad, 0x0c, 0x79, 0x81, 0x6c, 0x4f, 0x39, 0x3a, 0x76, 0x6c,
+ 0x74, 0x6d, 0xa9, 0xce, 0xd8, 0xae, 0x8e, 0x8e, 0xff, 0xce, 0x80, 0xfa,
+ 0x66, 0xb4, 0x7d, 0xab, 0xb4, 0xfe, 0x9d, 0xd6, 0x65, 0x46, 0xeb, 0xc2,
+ 0x38, 0xe6, 0x8c, 0x17, 0xb1, 0xe5, 0xaa, 0xd3, 0xa7, 0xea, 0x42, 0x5b,
+ 0xb0, 0x50, 0x09, 0xd3, 0x9e, 0x5c, 0x26, 0xed, 0x85, 0x65, 0xd2, 0xfe,
+ 0x76, 0x99, 0x34, 0x13, 0x17, 0xec, 0x2f, 0x5e, 0x46, 0xde, 0x88, 0xe6,
+ 0x55, 0x69, 0x36, 0xf6, 0x75, 0x7e, 0xae, 0xcc, 0x2a, 0xeb, 0x97, 0x31,
+ 0x46, 0x6c, 0x62, 0xc3, 0x39, 0x1d, 0x1b, 0xde, 0xe2, 0x6d, 0x53, 0x8c,
+ 0x75, 0x11, 0x17, 0x09, 0xd9, 0xab, 0xf1, 0x42, 0x9c, 0x7c, 0x85, 0x31,
+ 0xe0, 0x3c, 0xd7, 0x5a, 0x13, 0xea, 0x4a, 0xb4, 0x3d, 0x6f, 0x9b, 0x98,
+ 0x79, 0x8b, 0xe9, 0x75, 0xd5, 0x3e, 0xd8, 0x0a, 0xfd, 0xc5, 0x26, 0xd9,
+ 0x3e, 0x96, 0x58, 0x41, 0xbd, 0xb5, 0x63, 0xcc, 0xf8, 0x83, 0x7b, 0xc1,
+ 0x57, 0x19, 0x21, 0x8c, 0xc9, 0x94, 0x08, 0x6d, 0xe2, 0xa5, 0xb6, 0xf0,
+ 0xeb, 0xb7, 0xd7, 0x7b, 0x85, 0xf6, 0x1c, 0xd8, 0x0e, 0x3f, 0x6b, 0x7b,
+ 0xf5, 0xd2, 0x37, 0x16, 0xe2, 0x4a, 0xfd, 0x9c, 0xf5, 0x22, 0x57, 0xa8,
+ 0xa7, 0xed, 0x12, 0x79, 0x66, 0x4e, 0x16, 0x6f, 0x84, 0xcd, 0x24, 0x41,
+ 0xb6, 0x5b, 0x5a, 0x23, 0xa2, 0x63, 0x3c, 0x29, 0x23, 0x9b, 0x3b, 0xb8,
+ 0xb6, 0x03, 0xfa, 0x37, 0xb6, 0x8a, 0x89, 0x9b, 0x86, 0x76, 0xca, 0x72,
+ 0xb4, 0x7b, 0xbd, 0xa5, 0x5d, 0xae, 0xa9, 0xee, 0xa0, 0xcc, 0xc5, 0x9c,
+ 0x18, 0x3a, 0xde, 0x5e, 0x94, 0x44, 0x48, 0xc7, 0x33, 0xf0, 0x8b, 0xab,
+ 0xe9, 0x78, 0x46, 0x52, 0x9a, 0x8e, 0x6b, 0x17, 0xd0, 0x71, 0xab, 0xa5,
+ 0xe3, 0x77, 0x44, 0x0d, 0x5d, 0x28, 0xad, 0xa7, 0x48, 0xa7, 0x86, 0x8e,
+ 0x1d, 0x4d, 0xc7, 0x33, 0x78, 0xbb, 0x7e, 0x8f, 0x2d, 0x13, 0xb1, 0x69,
+ 0xfc, 0x1d, 0xa6, 0x51, 0x2e, 0xfe, 0x66, 0xd4, 0xe8, 0xa5, 0x14, 0xe8,
+ 0x28, 0x4c, 0xff, 0x60, 0xd4, 0xd0, 0x67, 0x75, 0x9a, 0x89, 0x8f, 0xf4,
+ 0x17, 0xdf, 0x13, 0x5d, 0x48, 0x9f, 0x29, 0xd0, 0x67, 0x58, 0xe6, 0xf5,
+ 0xe8, 0xb3, 0xde, 0xae, 0x5b, 0x44, 0xf5, 0xba, 0x7b, 0x26, 0x66, 0x68,
+ 0xf5, 0x56, 0x3d, 0x76, 0x8e, 0xfb, 0xd9, 0x9f, 0x81, 0x56, 0xcd, 0xdc,
+ 0x9c, 0x9f, 0xf7, 0xb7, 0x19, 0x8b, 0x4a, 0x98, 0x18, 0x36, 0xe3, 0xa4,
+ 0x57, 0xb2, 0x1d, 0x8d, 0x7c, 0xaa, 0xd1, 0xf2, 0xa9, 0x71, 0x48, 0xa5,
+ 0xab, 0x65, 0x76, 0x37, 0x74, 0x05, 0x6d, 0x6c, 0x2d, 0xa7, 0x91, 0xd7,
+ 0x9a, 0xc8, 0x16, 0xff, 0xd9, 0xee, 0x5f, 0xe0, 0xba, 0x80, 0x0c, 0x39,
+ 0x48, 0x6b, 0x2b, 0x9b, 0x71, 0x29, 0xbf, 0x11, 0xdf, 0xdd, 0xd2, 0x56,
+ 0x56, 0x72, 0xfb, 0x58, 0x83, 0xec, 0x2b, 0xba, 0xf2, 0x51, 0xd4, 0xff,
+ 0x48, 0xd1, 0x83, 0x3f, 0x3e, 0x1e, 0xa5, 0x5d, 0xb8, 0xb7, 0xc8, 0xf5,
+ 0x49, 0xc7, 0xac, 0x19, 0x2d, 0x58, 0xf3, 0x8c, 0x48, 0x5b, 0x47, 0x01,
+ 0x9e, 0x8a, 0xb8, 0x3b, 0x01, 0x47, 0x5d, 0x3a, 0x2d, 0xaf, 0x74, 0x0f,
+ 0x38, 0xda, 0x97, 0x70, 0x7a, 0xe4, 0xc6, 0x4a, 0x5a, 0x6e, 0xa8, 0x98,
+ 0x75, 0xd2, 0xf9, 0x75, 0xd0, 0xa4, 0x37, 0x0d, 0x9d, 0x93, 0xf1, 0x82,
+ 0xe0, 0x3c, 0xe4, 0xb7, 0x3a, 0xe2, 0x4a, 0xb4, 0x23, 0x19, 0x9f, 0x16,
+ 0xf3, 0x7d, 0xb1, 0xfc, 0xe3, 0x60, 0x28, 0xe6, 0xca, 0x2b, 0x3e, 0xc7,
+ 0xd5, 0x23, 0xd7, 0x97, 0xab, 0xfb, 0xe3, 0x5a, 0xe9, 0x13, 0x51, 0xae,
+ 0x4d, 0x64, 0x2b, 0xe5, 0x28, 0xe3, 0xe7, 0x22, 0x79, 0x69, 0x7b, 0x2b,
+ 0x7c, 0x37, 0x48, 0xeb, 0xb6, 0xb7, 0x82, 0x56, 0x62, 0xd0, 0xf3, 0x5b,
+ 0x01, 0xd7, 0x56, 0xc6, 0xbb, 0x18, 0xe7, 0xe2, 0xf7, 0x5f, 0xa2, 0x5f,
+ 0xd6, 0xfd, 0x5d, 0xbd, 0x66, 0x25, 0x8a, 0x73, 0x6e, 0xf8, 0x65, 0x79,
+ 0x5d, 0xd3, 0x38, 0x14, 0x4d, 0x8b, 0x13, 0x7d, 0x5b, 0x5c, 0x56, 0xf8,
+ 0xd5, 0xfd, 0x73, 0xed, 0x57, 0x14, 0x70, 0xe8, 0xee, 0xd8, 0xdc, 0x23,
+ 0x7d, 0x18, 0x5f, 0xff, 0x92, 0xf1, 0xed, 0x17, 0xc6, 0x54, 0x2f, 0x16,
+ 0x39, 0x86, 0xf9, 0x71, 0xa9, 0x3f, 0x32, 0xe3, 0x8a, 0x76, 0x2c, 0x1e,
+ 0x8f, 0xae, 0xaf, 0x4e, 0x01, 0x96, 0xe7, 0xf4, 0x1e, 0x81, 0x20, 0xb8,
+ 0xa6, 0xe3, 0x62, 0x90, 0x58, 0x97, 0xec, 0x9c, 0x9e, 0x5f, 0xd3, 0x19,
+ 0x8a, 0xa4, 0x33, 0x1a, 0xff, 0xf8, 0x4e, 0xe4, 0xca, 0xdd, 0x98, 0x3b,
+ 0x71, 0x73, 0x5d, 0xae, 0xe6, 0x8d, 0x9c, 0xdf, 0x6d, 0xd7, 0xad, 0x42,
+ 0xbf, 0x29, 0x08, 0x94, 0xbf, 0x58, 0x56, 0x50, 0x47, 0x61, 0xec, 0xb2,
+ 0xdb, 0xee, 0x4b, 0x49, 0x31, 0x6e, 0x38, 0xe4, 0xa6, 0xa3, 0x89, 0x42,
+ 0xb9, 0x0b, 0xbf, 0x1b, 0xf0, 0xfe, 0x45, 0xd8, 0x28, 0x3d, 0xb0, 0x61,
+ 0x24, 0xa6, 0x8c, 0x3c, 0x00, 0xfd, 0x76, 0xe4, 0x95, 0x22, 0x3f, 0x7a,
+ 0x89, 0xe1, 0x72, 0x2c, 0x31, 0x5a, 0xde, 0xcb, 0xfa, 0x28, 0x7b, 0xa5,
+ 0xf8, 0x1d, 0xfb, 0x62, 0x1f, 0xf4, 0x79, 0x7f, 0x96, 0x3e, 0x5c, 0xdb,
+ 0x36, 0xdb, 0x0c, 0xf1, 0xe2, 0xd2, 0x0d, 0xc7, 0xbf, 0x6e, 0xeb, 0x8f,
+ 0x70, 0x7c, 0x7b, 0x2d, 0xdc, 0x8b, 0xfb, 0x7d, 0x49, 0xdb, 0x2c, 0x8f,
+ 0x55, 0x68, 0x27, 0x72, 0x4d, 0x27, 0x79, 0x62, 0x5c, 0x08, 0x47, 0x10,
+ 0x5c, 0x48, 0x19, 0x7d, 0xfd, 0x74, 0x85, 0xeb, 0x1a, 0x41, 0xf0, 0x5d,
+ 0xda, 0xc2, 0x83, 0x25, 0xf4, 0x17, 0xe2, 0x60, 0x63, 0xde, 0x85, 0x2c,
+ 0x1c, 0xe9, 0x26, 0x7e, 0x05, 0x5e, 0x69, 0x87, 0xb7, 0x4b, 0xa2, 0x89,
+ 0xdf, 0x2e, 0x37, 0x24, 0x3e, 0x51, 0xf6, 0x80, 0x67, 0x8e, 0x3b, 0x96,
+ 0xd8, 0x63, 0xc7, 0xcc, 0xfd, 0x20, 0xaf, 0xbf, 0x4f, 0xe3, 0xa5, 0x05,
+ 0x3e, 0x12, 0x61, 0x9a, 0x87, 0x85, 0xb0, 0x25, 0x2c, 0x6e, 0x82, 0xe0,
+ 0xfb, 0x29, 0xf6, 0xd9, 0xcd, 0xfd, 0x00, 0x23, 0xe8, 0x37, 0xbf, 0x56,
+ 0x11, 0x0f, 0xd1, 0xc4, 0x1d, 0xe8, 0xfb, 0xb7, 0xd1, 0xf7, 0xbe, 0x32,
+ 0xfb, 0x83, 0x7c, 0xc0, 0xd8, 0x47, 0x2a, 0x21, 0xbc, 0xcb, 0xf5, 0x1d,
+ 0xce, 0x79, 0xa7, 0xb5, 0xeb, 0xc2, 0x6f, 0x8d, 0x48, 0x4f, 0xc1, 0x97,
+ 0xcb, 0x56, 0x66, 0xd6, 0xb8, 0xf2, 0x2e, 0xc8, 0xda, 0x40, 0x4e, 0x42,
+ 0x86, 0xcd, 0x68, 0xba, 0xc9, 0xae, 0xe7, 0xff, 0x11, 0xf9, 0xe4, 0x0a,
+ 0xc6, 0x94, 0x7b, 0x7d, 0xda, 0xab, 0xb3, 0xc1, 0x8c, 0x4f, 0x99, 0xbc,
+ 0x4a, 0xc6, 0xbd, 0x7c, 0x27, 0xf4, 0x03, 0xd2, 0x1a, 0xe9, 0x63, 0x27,
+ 0xb2, 0x91, 0x64, 0x62, 0x58, 0xb8, 0xc7, 0x89, 0xfb, 0x13, 0xb8, 0xef,
+ 0x87, 0xf2, 0xc0, 0x85, 0x9c, 0xe3, 0x1c, 0x9a, 0xfe, 0x86, 0xcb, 0xf3,
+ 0x65, 0x0f, 0x08, 0xd7, 0x09, 0x93, 0xf1, 0xbd, 0xda, 0x26, 0x01, 0xd5,
+ 0x15, 0x59, 0x76, 0x33, 0x2c, 0x12, 0xbf, 0xaa, 0xbc, 0xde, 0x73, 0x05,
+ 0x3e, 0x67, 0x1c, 0x21, 0x1a, 0xcd, 0x16, 0xe5, 0xb5, 0x48, 0xb7, 0xbc,
+ 0x96, 0x4d, 0xd5, 0x4b, 0xaf, 0x96, 0xf9, 0xcc, 0xd3, 0xe9, 0xb3, 0x26,
+ 0xdd, 0x85, 0x2e, 0xe1, 0x9c, 0xf4, 0x40, 0x46, 0x4f, 0x00, 0x6e, 0xe2,
+ 0xb0, 0x87, 0x32, 0x89, 0xf3, 0xa7, 0x54, 0x3a, 0x16, 0xcd, 0x95, 0xa5,
+ 0x2f, 0x57, 0xb4, 0xb1, 0x9e, 0x01, 0x8e, 0x7f, 0x95, 0xc5, 0x43, 0xa3,
+ 0xb8, 0x80, 0xad, 0x2f, 0x92, 0x70, 0xe0, 0x2b, 0x43, 0xd7, 0x3f, 0xba,
+ 0x4a, 0x1a, 0x89, 0x9b, 0x1e, 0xf0, 0x52, 0x0d, 0x74, 0xd1, 0xfd, 0xcd,
+ 0x5c, 0x37, 0xd5, 0x36, 0x64, 0xec, 0x63, 0xbf, 0xac, 0xd2, 0x7f, 0x1b,
+ 0x57, 0xe9, 0x51, 0x2b, 0x2f, 0xa3, 0x7d, 0x94, 0x97, 0x4f, 0x97, 0x08,
+ 0x8f, 0x78, 0x11, 0x3f, 0xd1, 0xd7, 0x5b, 0x16, 0x15, 0x49, 0x7b, 0xd1,
+ 0xde, 0xf2, 0x42, 0xfa, 0x7f, 0xba, 0xf2, 0x61, 0x6b, 0x0b, 0x56, 0xc7,
+ 0x54, 0xab, 0xf3, 0xc8, 0x83, 0xcb, 0xe5, 0x11, 0x26, 0x89, 0xae, 0x48,
+ 0x5f, 0xf8, 0x54, 0x7b, 0x47, 0xde, 0xab, 0x15, 0xe2, 0x39, 0x80, 0xdc,
+ 0x06, 0xae, 0xcb, 0x5c, 0xaf, 0xde, 0x8f, 0x79, 0xfb, 0x3f, 0x41, 0x26,
+ 0xc6, 0x7c, 0x4f, 0xea, 0xe0, 0xdb, 0xbe, 0x0c, 0xdd, 0xf9, 0x8a, 0x7f,
+ 0xe1, 0x53, 0x9d, 0x1d, 0x41, 0xf0, 0xac, 0x9f, 0x4f, 0xb8, 0x90, 0x1f,
+ 0x87, 0x2d, 0xbe, 0x87, 0x81, 0xef, 0x89, 0x39, 0x7c, 0x27, 0xe4, 0x62,
+ 0xd7, 0xf7, 0x03, 0xae, 0xf5, 0x0d, 0x97, 0x6f, 0xbd, 0x55, 0xa5, 0x3f,
+ 0xfe, 0xa1, 0x6c, 0x37, 0xfb, 0x1b, 0x91, 0xc3, 0x95, 0x9b, 0x88, 0xbf,
+ 0x28, 0xc6, 0x7a, 0x4f, 0x9f, 0x6f, 0xfa, 0xed, 0x5b, 0xd0, 0x2f, 0xe9,
+ 0xe5, 0x47, 0xac, 0x8b, 0x32, 0xd5, 0x75, 0x33, 0xa0, 0xcb, 0xbc, 0xad,
+ 0x3b, 0x70, 0x85, 0xba, 0xde, 0x15, 0xea, 0x1e, 0x46, 0xdd, 0x3d, 0xb6,
+ 0xee, 0x85, 0xcf, 0xbc, 0xb9, 0x7e, 0x07, 0xb8, 0xc7, 0x0e, 0x3e, 0x80,
+ 0xb8, 0x11, 0xff, 0x36, 0xfc, 0xbe, 0x85, 0xed, 0x28, 0xda, 0xf7, 0x23,
+ 0x95, 0x21, 0x19, 0xae, 0xec, 0xc4, 0x33, 0x88, 0xb4, 0x3e, 0x3c, 0xfb,
+ 0xf0, 0x3b, 0x8d, 0x47, 0xa2, 0x6e, 0xfa, 0xc2, 0x5d, 0xc3, 0x7e, 0x88,
+ 0x57, 0xae, 0xcd, 0xb3, 0x0f, 0xd8, 0x17, 0x5d, 0x3f, 0x41, 0x1f, 0x61,
+ 0xfa, 0x07, 0x50, 0x67, 0x1a, 0x69, 0x2b, 0x69, 0x7b, 0x62, 0xae, 0xab,
+ 0xeb, 0x54, 0xc3, 0x36, 0x1d, 0xce, 0x05, 0xf2, 0x0d, 0x8d, 0xf6, 0x16,
+ 0x43, 0x18, 0xef, 0x44, 0x1b, 0xe3, 0x57, 0x29, 0xff, 0x1e, 0xc2, 0x15,
+ 0x57, 0xfe, 0xc7, 0xf0, 0x7e, 0x2d, 0xd8, 0x9d, 0x62, 0x4c, 0x9e, 0xf3,
+ 0x7e, 0xdd, 0xaa, 0xa5, 0x7b, 0x9f, 0x42, 0x1a, 0xe8, 0x84, 0x4e, 0x69,
+ 0xb0, 0x74, 0x5a, 0x80, 0xe5, 0x43, 0x1a, 0xe5, 0x98, 0x17, 0x97, 0x4d,
+ 0x76, 0xe6, 0xa5, 0x07, 0xba, 0x8c, 0xb2, 0xf6, 0xd3, 0xf5, 0x26, 0x0e,
+ 0x03, 0xcb, 0xd1, 0xef, 0x04, 0x3d, 0x37, 0x88, 0x87, 0xfa, 0x03, 0x11,
+ 0x0f, 0x34, 0x18, 0xd6, 0x4f, 0x7a, 0x03, 0x11, 0x8e, 0x19, 0x1c, 0x5f,
+ 0xe6, 0xba, 0x34, 0x6d, 0x6b, 0xd6, 0x0f, 0x6d, 0x1c, 0xfe, 0x7b, 0x59,
+ 0xc4, 0x67, 0x1a, 0xdb, 0x0b, 0xde, 0x55, 0xe3, 0x2f, 0x59, 0x63, 0xc1,
+ 0x38, 0xf3, 0x49, 0x68, 0x30, 0xaf, 0x4f, 0xcb, 0xe9, 0xfc, 0x35, 0x35,
+ 0xd2, 0xe0, 0xf5, 0xeb, 0xdf, 0x2c, 0xd3, 0xe0, 0x81, 0x4f, 0x17, 0x95,
+ 0x61, 0x1a, 0xf3, 0x0a, 0x6b, 0x94, 0xde, 0xab, 0xa4, 0xf7, 0x28, 0xc9,
+ 0x83, 0xa9, 0x64, 0x62, 0x48, 0x25, 0xbd, 0x71, 0xd9, 0x0f, 0xb9, 0x43,
+ 0x39, 0x39, 0x73, 0x7f, 0x44, 0xb8, 0x9f, 0xef, 0x5d, 0x92, 0xf5, 0x29,
+ 0x3f, 0x0b, 0x9f, 0x57, 0x94, 0x75, 0x95, 0x97, 0x1a, 0xcc, 0xd8, 0xb8,
+ 0x0f, 0x01, 0x70, 0x36, 0xd1, 0x86, 0xbb, 0xb5, 0x81, 0x3c, 0x94, 0x50,
+ 0x11, 0xd9, 0x45, 0x3f, 0x5f, 0x7d, 0xb1, 0x5e, 0xea, 0xa7, 0xd7, 0x78,
+ 0x52, 0xd1, 0xe9, 0x66, 0x7f, 0x60, 0xb2, 0x73, 0x48, 0x89, 0x1e, 0x7b,
+ 0x46, 0xbd, 0x91, 0xcc, 0x9e, 0xb5, 0xfa, 0x23, 0x90, 0xc7, 0xb4, 0xbe,
+ 0x98, 0xf9, 0xbc, 0x2b, 0x17, 0x82, 0xb6, 0x4d, 0x17, 0xda, 0xb3, 0x5d,
+ 0xb4, 0x73, 0x57, 0xd9, 0xfd, 0x95, 0x8c, 0x63, 0xbd, 0x4b, 0x9e, 0xf3,
+ 0x0b, 0x18, 0xf7, 0x7e, 0xb9, 0xe0, 0xb3, 0xbf, 0x99, 0xcf, 0x79, 0xc2,
+ 0x74, 0xc2, 0x6e, 0xfa, 0x13, 0xf5, 0xa7, 0x80, 0x87, 0x7d, 0x52, 0x07,
+ 0x5f, 0xc9, 0xee, 0x4b, 0x0e, 0xe4, 0x45, 0xcf, 0x4b, 0x8f, 0xa0, 0xad,
+ 0x15, 0x3e, 0xf8, 0x10, 0x76, 0x73, 0xcd, 0x91, 0xab, 0x21, 0x77, 0x1d,
+ 0xbd, 0xc7, 0x02, 0x93, 0xe1, 0x4d, 0x61, 0xde, 0x33, 0x03, 0x2c, 0x57,
+ 0x2f, 0xd3, 0x31, 0xf2, 0xba, 0xe6, 0x97, 0x4f, 0x65, 0xfd, 0x76, 0x4f,
+ 0x39, 0xc3, 0x8c, 0x31, 0x00, 0xaf, 0xa4, 0xcd, 0x54, 0x6c, 0xbb, 0xcf,
+ 0xb6, 0x58, 0xe6, 0x2a, 0xf9, 0xf6, 0xc0, 0x85, 0x7f, 0x78, 0xd6, 0xff,
+ 0x7b, 0xc0, 0x91, 0x81, 0x4c, 0xe0, 0xf3, 0x6a, 0x90, 0x8f, 0x31, 0xa6,
+ 0xf5, 0xbf, 0xeb, 0xad, 0x9d, 0xac, 0x79, 0x7f, 0x58, 0xef, 0x93, 0x79,
+ 0xfe, 0x33, 0x59, 0xae, 0x77, 0xc0, 0x36, 0xc9, 0x69, 0xb9, 0x18, 0xfd,
+ 0x69, 0x0e, 0xf0, 0x14, 0x2a, 0xb4, 0x43, 0xfe, 0x06, 0x76, 0x88, 0xd6,
+ 0x93, 0xf2, 0xed, 0x41, 0xe6, 0xb1, 0xdd, 0xec, 0xd5, 0xae, 0xd6, 0x0b,
+ 0x21, 0x2c, 0xc9, 0xce, 0x1c, 0xf2, 0x47, 0xb4, 0x1d, 0xef, 0xc9, 0xac,
+ 0xe7, 0xea, 0x7d, 0x27, 0xf9, 0xc1, 0x20, 0x78, 0xc5, 0x77, 0xe5, 0xa4,
+ 0x86, 0xf9, 0x05, 0xf4, 0xe1, 0xc8, 0xc4, 0x80, 0xfb, 0xd3, 0x93, 0x3e,
+ 0xc7, 0xc7, 0x3c, 0xae, 0x2b, 0x6d, 0x8e, 0x1b, 0xf8, 0x68, 0x9b, 0x7e,
+ 0x2f, 0x98, 0x8d, 0x71, 0xdd, 0x02, 0x3c, 0x5d, 0x6a, 0xf7, 0x6e, 0x90,
+ 0xdb, 0xe6, 0x6c, 0x9a, 0x69, 0x31, 0x36, 0xa3, 0xd1, 0x69, 0x17, 0xfe,
+ 0x61, 0xc4, 0xbf, 0xb0, 0xba, 0x80, 0xb9, 0x81, 0x0e, 0x5b, 0x0c, 0x4b,
+ 0x8a, 0xb0, 0x0c, 0x6b, 0x58, 0x62, 0xc0, 0xa5, 0x0b, 0xd9, 0x77, 0x9b,
+ 0x1c, 0x02, 0xde, 0x87, 0x06, 0x45, 0x9e, 0x85, 0x4d, 0x76, 0xbe, 0x0a,
+ 0x9e, 0x19, 0xc0, 0x73, 0xde, 0xe7, 0x5e, 0x00, 0xe6, 0xf9, 0xde, 0xb0,
+ 0x70, 0x2f, 0x00, 0x71, 0xd8, 0x81, 0xdf, 0x22, 0x33, 0xd0, 0xbf, 0x27,
+ 0xfd, 0xd7, 0x82, 0xf1, 0x18, 0x75, 0x23, 0xda, 0x99, 0xdb, 0x1b, 0x14,
+ 0xc8, 0xe7, 0x53, 0xd4, 0x43, 0xb5, 0xd2, 0xb6, 0x8e, 0x7e, 0x88, 0x91,
+ 0x9f, 0x37, 0xf8, 0x19, 0xf4, 0xf5, 0x5b, 0x2b, 0xa5, 0x3e, 0x2f, 0xfd,
+ 0x1d, 0x75, 0xc8, 0x73, 0x6d, 0xde, 0x80, 0xce, 0xeb, 0xef, 0x38, 0x8c,
+ 0xfc, 0x8f, 0xaf, 0x64, 0xbc, 0xdb, 0xf5, 0xd7, 0x4b, 0xdb, 0x1a, 0xe6,
+ 0x55, 0xf3, 0xe0, 0xab, 0xdc, 0x83, 0x69, 0x75, 0x38, 0x64, 0x59, 0x29,
+ 0xef, 0x71, 0xa7, 0xdd, 0x21, 0xcc, 0xc5, 0x6e, 0x9f, 0xb2, 0xed, 0xbf,
+ 0xa3, 0x6e, 0x4a, 0x6e, 0xf4, 0x07, 0x91, 0x37, 0x8d, 0xbc, 0xc3, 0x36,
+ 0x6f, 0xd0, 0xe6, 0x6d, 0x43, 0xde, 0x3e, 0xe0, 0xef, 0x6e, 0x9d, 0x9e,
+ 0xe5, 0x6f, 0x53, 0xc7, 0x5b, 0xd9, 0x71, 0xe1, 0x33, 0x37, 0xf8, 0x84,
+ 0x0b, 0x79, 0x25, 0xae, 0x8b, 0xde, 0x26, 0x79, 0x2f, 0x79, 0x0b, 0x7b,
+ 0xfd, 0x66, 0xb1, 0x0e, 0xb2, 0x89, 0x7b, 0x80, 0x69, 0xb3, 0x6e, 0xf1,
+ 0x5e, 0x96, 0xff, 0x40, 0xba, 0xeb, 0xc9, 0x38, 0x5f, 0x5b, 0xc9, 0xb8,
+ 0xd8, 0x88, 0x4f, 0xfb, 0x3a, 0x90, 0x9c, 0x5e, 0x3f, 0xa1, 0x7f, 0x5b,
+ 0x44, 0x3a, 0xe9, 0x41, 0x35, 0x45, 0xf4, 0x3e, 0x2d, 0x7e, 0x47, 0x61,
+ 0xf7, 0x06, 0x42, 0x9f, 0x8f, 0x36, 0x5d, 0xc6, 0xe3, 0xda, 0x50, 0x98,
+ 0xe7, 0x21, 0x4f, 0x6d, 0x8a, 0xc0, 0x26, 0xaa, 0xf5, 0x1d, 0x1d, 0xa3,
+ 0x2e, 0xe8, 0x75, 0x00, 0xc6, 0xdf, 0x32, 0xf0, 0x63, 0x02, 0xe9, 0x47,
+ 0xdf, 0xa4, 0xfd, 0x68, 0x87, 0xef, 0x1d, 0x10, 0xee, 0x67, 0x65, 0x7a,
+ 0xbb, 0xf7, 0x6d, 0x99, 0xa7, 0xf3, 0x19, 0x49, 0x66, 0x94, 0x03, 0xff,
+ 0x75, 0xab, 0x23, 0xf5, 0xb0, 0x3d, 0x6e, 0x30, 0xfa, 0xcd, 0xe3, 0x9e,
+ 0xc4, 0x8b, 0xda, 0x56, 0x6b, 0xb4, 0xf3, 0x91, 0x05, 0x6e, 0xb8, 0x1f,
+ 0x7c, 0xe0, 0x9e, 0xdd, 0x7e, 0x21, 0x09, 0x6a, 0xd4, 0xba, 0x71, 0x18,
+ 0xb4, 0x91, 0x4d, 0x19, 0xdd, 0x78, 0xc3, 0x9c, 0x6e, 0xfc, 0xf3, 0x95,
+ 0xe4, 0x89, 0xe1, 0x72, 0x1c, 0x75, 0xf5, 0x3a, 0x4a, 0x82, 0x75, 0x6b,
+ 0x31, 0x9f, 0xe7, 0xfd, 0xec, 0x35, 0xa0, 0x2f, 0xc8, 0xe1, 0x64, 0xe7,
+ 0x29, 0xd4, 0x2d, 0xa0, 0xee, 0xe4, 0x5c, 0x5d, 0x47, 0x46, 0x7c, 0xbd,
+ 0xef, 0x59, 0x26, 0xcb, 0x21, 0x1d, 0x26, 0xe3, 0xb7, 0x6a, 0x5e, 0xe0,
+ 0x7e, 0x30, 0x37, 0x71, 0x9f, 0x6c, 0xd6, 0xb4, 0xdd, 0x27, 0xdc, 0x27,
+ 0xc5, 0xb6, 0xef, 0x0b, 0xda, 0xd6, 0x10, 0xbe, 0x12, 0xde, 0xa4, 0x8d,
+ 0x31, 0xbc, 0xc3, 0xf9, 0x37, 0xf3, 0x3e, 0xe4, 0x10, 0xdf, 0xbf, 0x1f,
+ 0xe4, 0x07, 0x39, 0x2f, 0xfc, 0x9e, 0xa7, 0xb9, 0x11, 0xd0, 0x5c, 0xc4,
+ 0x7f, 0xbb, 0x0c, 0xeb, 0x3d, 0x10, 0x29, 0x99, 0xd0, 0xf1, 0xcc, 0x0b,
+ 0xc1, 0x23, 0x0b, 0xe4, 0xf8, 0x47, 0x94, 0xa1, 0x21, 0xfe, 0x2e, 0x24,
+ 0xea, 0x64, 0x66, 0x4d, 0x9d, 0xde, 0xf1, 0x41, 0x7c, 0x8c, 0xde, 0x73,
+ 0x3b, 0xf8, 0xf5, 0xfa, 0xb9, 0xb1, 0x00, 0xdf, 0xc0, 0xe3, 0x4e, 0x63,
+ 0xeb, 0x63, 0x1c, 0x19, 0xed, 0xbf, 0x67, 0x8b, 0x4a, 0xef, 0x0b, 0xa2,
+ 0x8e, 0x3f, 0x00, 0x9d, 0x6a, 0xf6, 0xa4, 0xe0, 0x5d, 0xe1, 0xbc, 0x29,
+ 0xed, 0x73, 0x1c, 0x04, 0x0f, 0x1f, 0xf4, 0xb3, 0x6b, 0x6a, 0x75, 0xdb,
+ 0x49, 0xef, 0x7a, 0x6d, 0x13, 0x6e, 0x94, 0x99, 0x14, 0xdb, 0x23, 0x5e,
+ 0xfe, 0x47, 0x30, 0xe4, 0xcd, 0xa0, 0x7f, 0x43, 0xff, 0x59, 0x5f, 0xb5,
+ 0xd4, 0x49, 0xf5, 0x3e, 0x53, 0xe2, 0xc9, 0x85, 0xbd, 0xd2, 0x01, 0xfc,
+ 0x18, 0x78, 0x73, 0xe5, 0xb7, 0x49, 0x21, 0xe6, 0xda, 0xb1, 0x45, 0xb4,
+ 0x2f, 0x37, 0x91, 0xaa, 0x83, 0x2d, 0xf8, 0x17, 0xc1, 0xe4, 0x82, 0x31,
+ 0x1e, 0xac, 0x1a, 0xe3, 0x4c, 0x02, 0xd8, 0x68, 0x89, 0xcc, 0xc9, 0x01,
+ 0xf6, 0x65, 0x64, 0x52, 0x38, 0xc6, 0x3a, 0x8c, 0x71, 0xc7, 0xdc, 0x18,
+ 0x0f, 0x2f, 0x1a, 0xe3, 0x61, 0x8c, 0x11, 0xf6, 0x42, 0x29, 0xd3, 0xe9,
+ 0xce, 0xcf, 0xfb, 0xd5, 0x35, 0x73, 0xf3, 0x29, 0xdc, 0xeb, 0x84, 0xf1,
+ 0xd3, 0xa6, 0xd8, 0x08, 0x78, 0x74, 0x5b, 0x90, 0x71, 0x0e, 0x64, 0x5b,
+ 0x76, 0x4d, 0x8d, 0x1d, 0xff, 0x76, 0x96, 0x2b, 0x1b, 0x1c, 0x9c, 0x4c,
+ 0xb9, 0x9d, 0x8f, 0xa0, 0xbf, 0xbd, 0x76, 0x5c, 0xbd, 0xe5, 0xab, 0x31,
+ 0xae, 0x0b, 0xdf, 0xc1, 0x18, 0xe0, 0xb3, 0x9d, 0xa0, 0x0f, 0x9c, 0x18,
+ 0x92, 0x05, 0xb2, 0xeb, 0x33, 0xf3, 0x72, 0xd4, 0xc0, 0x4c, 0xdb, 0xba,
+ 0x30, 0x07, 0xf3, 0xdd, 0x8b, 0x60, 0xbe, 0x1b, 0x30, 0xef, 0xb3, 0xf3,
+ 0xb2, 0xaf, 0x6a, 0xcf, 0x62, 0x48, 0x47, 0xfc, 0xfd, 0xbc, 0xf5, 0x45,
+ 0x3e, 0x20, 0xf7, 0x97, 0x3a, 0xe5, 0xcb, 0x95, 0xe4, 0x59, 0xc6, 0xd1,
+ 0xcf, 0x55, 0x92, 0xe3, 0x22, 0x5d, 0xf2, 0xc7, 0xb0, 0x73, 0xae, 0x82,
+ 0x6f, 0xf1, 0x34, 0xfc, 0xd7, 0x3f, 0xa9, 0xf8, 0xf2, 0xc4, 0xdc, 0x7e,
+ 0x38, 0xea, 0xba, 0xb4, 0x9c, 0x84, 0x4f, 0xbb, 0xed, 0x68, 0x1b, 0xf7,
+ 0x2a, 0x11, 0xbe, 0xbb, 0xa8, 0x73, 0xda, 0x94, 0xe6, 0xc5, 0xef, 0x62,
+ 0xbc, 0xa7, 0xa9, 0x6b, 0xd6, 0xfa, 0xbe, 0x77, 0xb3, 0x5a, 0x47, 0x99,
+ 0x90, 0xff, 0x5a, 0xe4, 0x03, 0xf5, 0x26, 0xc6, 0x92, 0xf1, 0x9a, 0xc9,
+ 0x1b, 0xdb, 0x3a, 0x12, 0x7d, 0x42, 0x5b, 0x82, 0xfe, 0x36, 0x6c, 0xa1,
+ 0xd2, 0xe6, 0xf8, 0x5a, 0xa1, 0x4c, 0xa2, 0x5d, 0x94, 0x96, 0x09, 0xc0,
+ 0x3e, 0x06, 0x89, 0x50, 0x68, 0xf6, 0x47, 0x7b, 0xd5, 0x44, 0x03, 0x79,
+ 0x70, 0xdb, 0x19, 0xd0, 0xd7, 0x36, 0x8c, 0xa9, 0x2b, 0x79, 0x76, 0x46,
+ 0x65, 0x4e, 0xac, 0x95, 0x57, 0x82, 0xa1, 0x66, 0x47, 0x9e, 0xd8, 0xc4,
+ 0x3c, 0x2d, 0xb7, 0x3f, 0xd5, 0x0b, 0xf9, 0xd4, 0xce, 0x73, 0x0b, 0x03,
+ 0xf2, 0x2f, 0x77, 0x80, 0x06, 0x7f, 0xb8, 0xe9, 0x6b, 0xc1, 0x6c, 0xb3,
+ 0x2b, 0x5b, 0x37, 0x25, 0xbd, 0xbc, 0xc2, 0x78, 0x4a, 0x18, 0x4f, 0x09,
+ 0xe3, 0xe3, 0x98, 0x4b, 0x18, 0xd7, 0x15, 0xf7, 0x4a, 0xf5, 0x2c, 0x88,
+ 0xcb, 0x1a, 0x3f, 0x2d, 0x93, 0x77, 0x65, 0x83, 0xdd, 0x2b, 0x35, 0x5c,
+ 0x1f, 0xae, 0xb1, 0x65, 0x64, 0x3c, 0x28, 0xf8, 0x7f, 0x70, 0x55, 0xb6,
+ 0x2b, 0xb6, 0x58, 0xe7, 0xdc, 0x35, 0xaf, 0x73, 0x44, 0x9e, 0x33, 0xf3,
+ 0x86, 0x39, 0xf3, 0xbd, 0x49, 0x6e, 0x86, 0x87, 0x0e, 0xdc, 0xaa, 0xf7,
+ 0x3c, 0x77, 0xe0, 0x9b, 0x36, 0xd5, 0xa7, 0xf5, 0x3a, 0xe2, 0x4c, 0xf9,
+ 0x1e, 0x3b, 0x77, 0xf7, 0x68, 0x3d, 0xbb, 0x75, 0xd3, 0xa5, 0x80, 0xfb,
+ 0xdc, 0xbc, 0x4d, 0xcb, 0xc5, 0x22, 0x68, 0xef, 0xd5, 0x69, 0xde, 0xe7,
+ 0x7a, 0x76, 0x41, 0x9f, 0x13, 0x01, 0xde, 0xe6, 0xe2, 0x62, 0xf5, 0x48,
+ 0xa3, 0xbe, 0xf8, 0x69, 0x83, 0x59, 0x47, 0xa5, 0x6c, 0x58, 0x83, 0x34,
+ 0xd7, 0xec, 0x05, 0x5e, 0x90, 0xf7, 0xdf, 0xea, 0xcd, 0x9e, 0x8f, 0xea,
+ 0xb2, 0xe0, 0x31, 0xbd, 0x2f, 0x84, 0xfb, 0x03, 0x7f, 0x79, 0xa5, 0xb1,
+ 0x4d, 0xc3, 0x7c, 0xa6, 0xff, 0x38, 0x98, 0xd0, 0x31, 0x36, 0xf6, 0xf5,
+ 0x43, 0xfc, 0x5e, 0xbc, 0x5f, 0x24, 0xb4, 0x5d, 0xeb, 0x40, 0xf7, 0xda,
+ 0x5f, 0x16, 0x94, 0x89, 0xe7, 0x25, 0x22, 0x13, 0x55, 0x30, 0x4e, 0x10,
+ 0xee, 0x52, 0xd7, 0xaa, 0xf9, 0xd8, 0xdd, 0x6a, 0xa4, 0x11, 0xc6, 0x75,
+ 0x8b, 0xf2, 0xc8, 0x1b, 0xad, 0x2b, 0x49, 0x37, 0xd3, 0xc2, 0xb4, 0xf9,
+ 0x31, 0xcd, 0x68, 0xfb, 0xb9, 0x6d, 0x95, 0xde, 0xfb, 0xc4, 0x35, 0x46,
+ 0xc6, 0x08, 0x63, 0x26, 0xdf, 0xf5, 0xff, 0x56, 0xd7, 0x19, 0x9a, 0xab,
+ 0xa3, 0xe7, 0x02, 0xf9, 0x6e, 0x55, 0x5e, 0x35, 0xdc, 0xd4, 0x5f, 0x43,
+ 0x9d, 0x75, 0xd0, 0x89, 0x17, 0x53, 0xab, 0xc3, 0xbd, 0xf0, 0xb0, 0x21,
+ 0xb2, 0xd7, 0xd4, 0x5a, 0x99, 0x3f, 0x81, 0x79, 0x7d, 0x26, 0x65, 0x78,
+ 0x51, 0xf3, 0x61, 0xf1, 0x36, 0xf8, 0xeb, 0xa1, 0xde, 0xa0, 0x9c, 0x26,
+ 0x6f, 0x22, 0xad, 0x42, 0x9f, 0xe0, 0xc2, 0xea, 0x99, 0xae, 0x57, 0x03,
+ 0xee, 0xb3, 0x7c, 0x45, 0xdb, 0x51, 0x43, 0xb2, 0xb0, 0xed, 0xd1, 0x7b,
+ 0x5e, 0xbf, 0xed, 0xa1, 0x65, 0xda, 0x1e, 0xb2, 0x6d, 0x8b, 0x6b, 0xda,
+ 0x8e, 0x5e, 0xa1, 0xed, 0x81, 0x37, 0x68, 0x7b, 0x70, 0x99, 0xb6, 0x07,
+ 0xc3, 0xb6, 0x95, 0x69, 0xdb, 0x0b, 0xdb, 0x4e, 0x2c, 0xc2, 0xc9, 0x67,
+ 0x5e, 0xbf, 0xed, 0x7d, 0xcb, 0xb4, 0xbd, 0x6f, 0x11, 0xdc, 0xc4, 0x49,
+ 0x2d, 0x74, 0xff, 0x3d, 0xda, 0xe6, 0xac, 0x03, 0xdf, 0x5c, 0x84, 0xfc,
+ 0x36, 0xfe, 0xc8, 0x85, 0xbb, 0x66, 0xcb, 0xe0, 0x2b, 0xf8, 0xd7, 0x99,
+ 0x72, 0x03, 0x9e, 0x71, 0xd8, 0x33, 0x28, 0x07, 0x7b, 0xbc, 0x26, 0x1d,
+ 0xc8, 0xc9, 0x6e, 0x96, 0xcd, 0xc7, 0x6b, 0xe7, 0xf4, 0xc6, 0x3d, 0xe8,
+ 0x8f, 0x6d, 0xfb, 0x5e, 0xbf, 0xbc, 0xa6, 0xfb, 0xcb, 0x95, 0xe9, 0x8f,
+ 0x21, 0xbd, 0x42, 0x1f, 0x97, 0xf5, 0x42, 0x19, 0x58, 0x67, 0xd7, 0x3e,
+ 0x68, 0x6b, 0x32, 0x0e, 0xa7, 0xed, 0x51, 0x29, 0x94, 0x7f, 0x12, 0x4c,
+ 0x83, 0x2e, 0x46, 0xe6, 0x74, 0xc8, 0x93, 0xab, 0x68, 0xb3, 0x8f, 0x53,
+ 0xb3, 0x54, 0xc5, 0xa0, 0x46, 0x7c, 0xa6, 0xfd, 0x98, 0x6d, 0xc2, 0x0e,
+ 0x0c, 0xcb, 0x32, 0x6e, 0x6c, 0x62, 0x4e, 0x67, 0x21, 0x33, 0xcd, 0x9e,
+ 0x0e, 0xfa, 0x2a, 0x4f, 0x81, 0x97, 0xf7, 0x43, 0x76, 0x24, 0xf3, 0x22,
+ 0x3d, 0x8d, 0xe6, 0xac, 0x45, 0x4c, 0x72, 0x5d, 0xbf, 0x69, 0xf1, 0xb8,
+ 0xef, 0xce, 0xe5, 0xcf, 0x59, 0x40, 0x3e, 0x38, 0x94, 0x91, 0xd7, 0x37,
+ 0x9a, 0x75, 0xbb, 0xb7, 0x36, 0x32, 0x1e, 0xa3, 0x36, 0x75, 0xaf, 0xd6,
+ 0xf2, 0xc7, 0x09, 0xbf, 0xbf, 0xb2, 0xe8, 0x3b, 0xac, 0xf7, 0x93, 0xd5,
+ 0x0b, 0xeb, 0x85, 0xe9, 0x70, 0x4d, 0x16, 0xa4, 0x1f, 0x58, 0xb3, 0xb0,
+ 0x7e, 0xac, 0x69, 0xe1, 0xf7, 0xe0, 0xa2, 0xef, 0xcf, 0x2c, 0xfa, 0x7e,
+ 0x61, 0xd1, 0xf7, 0x75, 0x6b, 0x17, 0x95, 0x5f, 0xf4, 0xfd, 0xe5, 0xb5,
+ 0xcb, 0xc3, 0xfb, 0x57, 0x6b, 0x17, 0xc2, 0xf5, 0x94, 0x5e, 0x73, 0x1d,
+ 0xaf, 0xb8, 0xb2, 0xbd, 0x88, 0x7c, 0xe7, 0xd6, 0x18, 0xf2, 0xe1, 0xcb,
+ 0x54, 0xe7, 0x73, 0x8d, 0xe3, 0x1d, 0xb1, 0x85, 0xed, 0xcd, 0xd7, 0xdb,
+ 0x31, 0x5f, 0x2f, 0x35, 0x5f, 0xcf, 0xf8, 0x23, 0x13, 0x15, 0xe6, 0x31,
+ 0x3d, 0x6c, 0xd7, 0xd4, 0x1d, 0x29, 0x79, 0xfa, 0x3c, 0xc2, 0x80, 0x3e,
+ 0x8f, 0x90, 0x80, 0x6f, 0xf4, 0x94, 0x8e, 0xeb, 0xaf, 0x51, 0x48, 0xaf,
+ 0x34, 0xea, 0xd8, 0xbe, 0xe8, 0x33, 0x09, 0x03, 0xb0, 0xb9, 0x78, 0x0e,
+ 0x21, 0x90, 0x9d, 0x29, 0xf3, 0x36, 0xe7, 0x12, 0x0e, 0x07, 0xbd, 0x5e,
+ 0x10, 0x0c, 0xfb, 0x67, 0xad, 0x2c, 0xc7, 0xbb, 0x62, 0xea, 0xd0, 0xd7,
+ 0x7c, 0x14, 0xfa, 0x66, 0xde, 0xc7, 0x7c, 0x8a, 0xf6, 0x3a, 0x68, 0xa6,
+ 0x1b, 0x7a, 0x37, 0xf9, 0xa4, 0x68, 0xdd, 0xd1, 0x05, 0x9d, 0xeb, 0xdd,
+ 0xfb, 0x3e, 0xd8, 0x3a, 0x5f, 0x06, 0xad, 0x1f, 0x4b, 0xf5, 0x68, 0xff,
+ 0xff, 0x1c, 0x74, 0x31, 0xe3, 0x84, 0x8f, 0x69, 0xda, 0x22, 0x8d, 0x35,
+ 0xe8, 0xb3, 0x50, 0x27, 0x53, 0x4e, 0x34, 0xdb, 0x75, 0xde, 0xc4, 0xcd,
+ 0x53, 0xed, 0xde, 0x73, 0xe0, 0xb5, 0x7e, 0x7f, 0x03, 0x6c, 0x66, 0xd1,
+ 0x3a, 0xbf, 0x50, 0x5a, 0x6f, 0x6d, 0x83, 0x66, 0x19, 0x77, 0xb9, 0x56,
+ 0x93, 0xec, 0x19, 0x32, 0x3e, 0x66, 0x3c, 0xa1, 0x18, 0x23, 0xe6, 0xfa,
+ 0x05, 0xcf, 0x39, 0x70, 0x9d, 0x9b, 0xf1, 0x90, 0xf1, 0x7b, 0x47, 0xfc,
+ 0xbc, 0x17, 0xb1, 0x67, 0x23, 0xb2, 0x45, 0x43, 0x9b, 0x7b, 0xb4, 0xad,
+ 0x1a, 0x05, 0x3f, 0x7d, 0x0f, 0x74, 0xcf, 0xba, 0xa4, 0xfd, 0xef, 0x04,
+ 0x93, 0xae, 0x89, 0x4f, 0x29, 0xd4, 0xcb, 0x6a, 0x5c, 0x3d, 0x25, 0x07,
+ 0x4a, 0xe4, 0xff, 0xa8, 0x96, 0xe5, 0xbb, 0x53, 0x94, 0x07, 0x51, 0xe0,
+ 0x71, 0x0a, 0xf8, 0x6b, 0x90, 0xdd, 0x5d, 0x45, 0x94, 0x89, 0xc8, 0xd0,
+ 0x40, 0x03, 0x78, 0x8f, 0x76, 0x09, 0xdf, 0x2e, 0xca, 0x7b, 0x32, 0x55,
+ 0x1c, 0xd7, 0x7b, 0x9e, 0x1f, 0x43, 0xdd, 0xc7, 0xf1, 0x4c, 0x14, 0xcb,
+ 0xa8, 0xf3, 0xb0, 0x2e, 0x3f, 0x31, 0xca, 0x73, 0x22, 0x02, 0x7b, 0xff,
+ 0x49, 0x29, 0x4c, 0xb6, 0xc1, 0x2f, 0x99, 0x1e, 0x77, 0xe7, 0xe2, 0xe4,
+ 0xff, 0xa5, 0x91, 0xeb, 0xcc, 0x85, 0xeb, 0xb8, 0x27, 0x47, 0xdc, 0x81,
+ 0xcd, 0xaa, 0xb3, 0x49, 0xaf, 0xf9, 0xf4, 0x48, 0x3f, 0x6c, 0x8a, 0x9b,
+ 0x2b, 0xcf, 0xc4, 0xcc, 0xda, 0xc0, 0x82, 0xf5, 0x86, 0xc3, 0xc4, 0x8a,
+ 0x3a, 0xea, 0xf2, 0xdc, 0xa7, 0x4c, 0x9c, 0x81, 0xf6, 0x39, 0x1a, 0xae,
+ 0xe7, 0x30, 0xcd, 0x93, 0xb6, 0xeb, 0x00, 0xd7, 0x99, 0x7f, 0xd2, 0xf2,
+ 0xf5, 0x89, 0x4d, 0x61, 0x5f, 0xf9, 0x60, 0x6c, 0x53, 0x5e, 0x3e, 0x81,
+ 0x27, 0x77, 0x5d, 0x72, 0x34, 0xab, 0xd8, 0xef, 0x37, 0x02, 0xc6, 0x02,
+ 0x54, 0xba, 0x55, 0xf2, 0x4d, 0xd5, 0xfd, 0x33, 0xad, 0xc3, 0x2b, 0xa8,
+ 0xd7, 0x83, 0x63, 0x26, 0x11, 0x03, 0x0e, 0xf2, 0x6f, 0x08, 0xcf, 0x16,
+ 0xcf, 0x57, 0xcb, 0xc1, 0x73, 0xc2, 0xae, 0xd7, 0x70, 0x0d, 0x66, 0x05,
+ 0xf0, 0xd2, 0x80, 0xf4, 0x09, 0x19, 0x39, 0xfe, 0x3b, 0x31, 0xee, 0x17,
+ 0xaa, 0xd1, 0x7e, 0xf5, 0x7d, 0xf5, 0x26, 0x06, 0xf2, 0x2c, 0xca, 0x30,
+ 0x7f, 0x1c, 0x75, 0x92, 0xf9, 0x6c, 0x64, 0xad, 0x0c, 0xe9, 0x7e, 0x83,
+ 0x48, 0xdb, 0xb6, 0x7a, 0xbd, 0x4f, 0x5f, 0xce, 0x30, 0x6e, 0x11, 0xd6,
+ 0x7d, 0x56, 0xef, 0x83, 0x73, 0xd3, 0xc9, 0x7c, 0x5f, 0x84, 0xf2, 0xa9,
+ 0x53, 0x7a, 0xb9, 0xce, 0x73, 0x66, 0x5c, 0xd3, 0x76, 0xfb, 0x26, 0x9e,
+ 0x07, 0xdd, 0x02, 0xfb, 0xef, 0x3b, 0x80, 0x89, 0x30, 0x9e, 0x40, 0x3a,
+ 0x7c, 0xc2, 0xd7, 0x85, 0x61, 0xfa, 0x4d, 0xc2, 0x30, 0xfd, 0x26, 0x61,
+ 0x20, 0x2e, 0x00, 0x47, 0xa5, 0x7d, 0x75, 0x68, 0x53, 0x5c, 0x85, 0x71,
+ 0x1c, 0x2c, 0x4d, 0xc3, 0xbf, 0xd5, 0x31, 0x94, 0xce, 0x69, 0x45, 0x9e,
+ 0xf7, 0xc0, 0x73, 0xe0, 0xad, 0x12, 0x78, 0x0f, 0xb6, 0xe1, 0x97, 0x61,
+ 0x1b, 0x3e, 0x01, 0xdb, 0xf0, 0x1c, 0x6c, 0xc3, 0xc7, 0x31, 0x37, 0x8f,
+ 0x2d, 0xe0, 0xd5, 0x8c, 0xe6, 0xd5, 0x42, 0xe9, 0x02, 0x78, 0xb5, 0xeb,
+ 0x0a, 0xfc, 0xe8, 0xc2, 0xc6, 0xa7, 0x0d, 0xed, 0xc0, 0x96, 0xff, 0xb8,
+ 0xf6, 0x8b, 0x1f, 0x4c, 0x8d, 0xb1, 0x0e, 0x68, 0x38, 0x49, 0x9f, 0x16,
+ 0xf2, 0x3f, 0x99, 0x07, 0xef, 0x61, 0xac, 0x8e, 0xa3, 0xae, 0x5b, 0x23,
+ 0xd4, 0x1f, 0xee, 0x36, 0xee, 0xef, 0xe6, 0x58, 0x13, 0x8b, 0xf0, 0x64,
+ 0xf8, 0x73, 0x8f, 0x4f, 0x3d, 0x42, 0xbe, 0x4c, 0x7c, 0x76, 0xc4, 0xaf,
+ 0xe6, 0xc5, 0x1d, 0x1c, 0x5f, 0xe0, 0x6d, 0x5a, 0xae, 0xee, 0x7c, 0xf9,
+ 0x35, 0x73, 0xe5, 0x75, 0xff, 0xa3, 0xe4, 0x37, 0xe8, 0x6e, 0xe2, 0x3e,
+ 0x91, 0x8d, 0x6c, 0xb0, 0xb8, 0xdf, 0x2f, 0x6d, 0xdb, 0x60, 0xaf, 0x0f,
+ 0x82, 0x7e, 0xa7, 0x02, 0xf1, 0xb7, 0x85, 0x6d, 0xce, 0xb7, 0xe3, 0xd9,
+ 0x76, 0x76, 0xc3, 0x96, 0xed, 0xdb, 0xc4, 0xb5, 0x5e, 0xd8, 0xf2, 0xa9,
+ 0x70, 0x3e, 0x60, 0xf9, 0xea, 0x39, 0xa7, 0x0c, 0xa5, 0xec, 0x6c, 0xb0,
+ 0xf1, 0x7e, 0xb6, 0x77, 0x61, 0xd1, 0x3c, 0x5d, 0x0a, 0x78, 0xce, 0x76,
+ 0xc4, 0x1f, 0xab, 0xa2, 0x95, 0xbf, 0xb2, 0xb4, 0xa2, 0x16, 0x8d, 0xe3,
+ 0x9c, 0xa5, 0x95, 0x10, 0xde, 0x58, 0x48, 0x2b, 0x75, 0x21, 0xad, 0xe4,
+ 0xc7, 0x43, 0x5a, 0x61, 0xdd, 0x73, 0x21, 0xad, 0x24, 0xaa, 0x69, 0x25,
+ 0x3f, 0xee, 0xe0, 0x59, 0x0c, 0x07, 0xe9, 0x85, 0xed, 0x90, 0x5e, 0x00,
+ 0x4b, 0xa5, 0x32, 0x47, 0x2f, 0x31, 0xb4, 0x73, 0xa8, 0xa4, 0x34, 0xad,
+ 0x0c, 0xa9, 0x50, 0x47, 0x78, 0x98, 0x73, 0xcc, 0xfd, 0x15, 0x69, 0x24,
+ 0x65, 0x69, 0x64, 0xfe, 0x2c, 0xd1, 0x22, 0xda, 0x00, 0xee, 0x79, 0x5e,
+ 0x60, 0xb3, 0xa6, 0x8d, 0xfb, 0x53, 0x2f, 0xa0, 0xec, 0x28, 0x68, 0x23,
+ 0xc4, 0xc1, 0x03, 0x16, 0x07, 0x8b, 0xe7, 0xf2, 0xb4, 0xc5, 0xc1, 0xa8,
+ 0xc5, 0x81, 0xe6, 0x97, 0x3c, 0xe7, 0x4c, 0x69, 0x1c, 0xd4, 0x69, 0x1c,
+ 0x88, 0x0a, 0xeb, 0x9e, 0x5e, 0x06, 0x07, 0x2c, 0x33, 0xaa, 0xc7, 0x1f,
+ 0xc1, 0xf8, 0xf7, 0x61, 0xfc, 0x4a, 0x8f, 0x9f, 0xf3, 0xc0, 0xf1, 0x03,
+ 0x96, 0xca, 0x77, 0xe6, 0xc6, 0xdf, 0x84, 0x36, 0x0e, 0x6a, 0xdb, 0x99,
+ 0xf1, 0x54, 0xea, 0x46, 0x33, 0xfe, 0xc7, 0x2a, 0xe6, 0x8c, 0xc9, 0x63,
+ 0x4b, 0xf4, 0xd8, 0x0b, 0x96, 0x37, 0x7c, 0xbd, 0xce, 0xc6, 0x73, 0x6d,
+ 0xe7, 0xa0, 0xbb, 0xc6, 0x52, 0x09, 0x7b, 0xe6, 0xd4, 0xd8, 0x43, 0x5f,
+ 0x4d, 0x91, 0x77, 0x3e, 0xaa, 0xf7, 0xfa, 0x9d, 0xa5, 0x5d, 0x54, 0x6a,
+ 0x92, 0xbe, 0xb1, 0x6a, 0xb8, 0x09, 0x6f, 0x3e, 0x50, 0x3e, 0x63, 0x37,
+ 0xfb, 0xa1, 0x3b, 0x4c, 0xdc, 0x1a, 0xb4, 0x84, 0xf4, 0x64, 0xbe, 0x37,
+ 0x52, 0x27, 0xea, 0x81, 0x0f, 0x60, 0xcc, 0x2e, 0x7c, 0xcc, 0x76, 0x6f,
+ 0x9b, 0xa2, 0xae, 0xbb, 0xba, 0x4a, 0xd7, 0x35, 0x5b, 0x5d, 0xb7, 0x86,
+ 0xba, 0x0e, 0x70, 0x3f, 0x25, 0x87, 0x4b, 0x9c, 0xbf, 0x7c, 0xa2, 0x4e,
+ 0xc7, 0x40, 0x1d, 0x1b, 0xe7, 0x4b, 0xc6, 0x0f, 0x6b, 0x5a, 0xa6, 0xce,
+ 0x4a, 0xea, 0xb8, 0xe4, 0x4c, 0xd7, 0x3f, 0xd9, 0x75, 0x10, 0xea, 0xb5,
+ 0xef, 0x07, 0x7f, 0xb0, 0x8c, 0x5e, 0x83, 0xfe, 0xd1, 0xf6, 0x59, 0x0d,
+ 0x64, 0xad, 0x9c, 0x6a, 0xc6, 0xb3, 0x9a, 0xe7, 0xc1, 0x3a, 0x3b, 0x54,
+ 0xbd, 0xd4, 0x9c, 0x6a, 0x94, 0x3d, 0x63, 0x7a, 0xdd, 0x5c, 0xd4, 0x29,
+ 0xe0, 0xff, 0x14, 0xcf, 0x14, 0x88, 0x3e, 0x03, 0x95, 0x1b, 0x85, 0x3f,
+ 0x33, 0xf1, 0x94, 0xd9, 0x1b, 0x38, 0x56, 0xa3, 0x7f, 0xd3, 0xc6, 0x28,
+ 0xa4, 0x32, 0xfa, 0xec, 0xd0, 0x1e, 0xb4, 0xd9, 0xbe, 0xa9, 0x16, 0x63,
+ 0x8e, 0xa1, 0x2e, 0xf7, 0x16, 0xaa, 0x36, 0x57, 0x6a, 0xc5, 0x9d, 0x88,
+ 0xea, 0xf3, 0x4b, 0x3c, 0x7f, 0x9f, 0xed, 0x69, 0x42, 0x5e, 0x44, 0xaf,
+ 0x15, 0xd4, 0x9c, 0x9a, 0x3f, 0xa7, 0xae, 0x8e, 0x8a, 0x5d, 0xc3, 0x4f,
+ 0x6b, 0xbd, 0x12, 0x39, 0x4a, 0x9d, 0xc3, 0xfd, 0x55, 0x3d, 0x98, 0xf7,
+ 0xe5, 0xf4, 0x8d, 0x31, 0x62, 0xb3, 0x98, 0x3f, 0x75, 0x86, 0x67, 0x8d,
+ 0x5b, 0xf1, 0x0e, 0xdb, 0x0b, 0xf5, 0x08, 0x74, 0xdf, 0xdb, 0x3f, 0xe1,
+ 0x49, 0x3d, 0xf0, 0x3d, 0xa1, 0x80, 0x6b, 0x57, 0xd3, 0x42, 0x5e, 0x85,
+ 0xb1, 0x69, 0x43, 0x0f, 0x8f, 0xbf, 0x21, 0x3f, 0x90, 0x26, 0x3a, 0x6d,
+ 0x6c, 0xc1, 0xb7, 0x31, 0x7e, 0xd2, 0xb6, 0xa1, 0x87, 0x47, 0x53, 0x19,
+ 0xc5, 0xbd, 0x51, 0x66, 0x1d, 0x94, 0xb4, 0x41, 0x9a, 0x4f, 0xe8, 0xf5,
+ 0xd1, 0x8c, 0xbc, 0x2c, 0x99, 0xa6, 0x76, 0xd8, 0x5d, 0xff, 0xb6, 0x73,
+ 0x6c, 0xee, 0x2e, 0xd0, 0x34, 0x07, 0xdd, 0xc4, 0x7d, 0xca, 0x9d, 0xf2,
+ 0x5e, 0x9e, 0x57, 0x98, 0x70, 0xa0, 0x94, 0x9f, 0xd2, 0x7b, 0xbf, 0x77,
+ 0x14, 0x57, 0xcb, 0xad, 0xa9, 0xa8, 0x5d, 0xe7, 0xac, 0x05, 0x1d, 0x40,
+ 0x50, 0x9f, 0xaa, 0xc5, 0x13, 0x75, 0x38, 0x7f, 0x17, 0x53, 0x99, 0xa4,
+ 0x22, 0xb3, 0xc3, 0xe7, 0x9f, 0x91, 0x2d, 0xde, 0x1e, 0x7d, 0xce, 0x4e,
+ 0x9c, 0xba, 0x53, 0x7f, 0xe9, 0xd1, 0x06, 0x25, 0xfd, 0xcc, 0xf8, 0xb5,
+ 0x7a, 0x5d, 0xab, 0x3f, 0x15, 0x04, 0x39, 0xcc, 0x5f, 0x41, 0x4c, 0xfc,
+ 0x6c, 0xc2, 0x67, 0x1a, 0xfd, 0xda, 0x06, 0xa7, 0xf6, 0x4c, 0xa3, 0x63,
+ 0x68, 0x45, 0x22, 0x2a, 0x5d, 0xef, 0xd4, 0x9c, 0xba, 0x93, 0x73, 0x06,
+ 0xba, 0xf2, 0x1c, 0x43, 0x57, 0x31, 0x67, 0x9e, 0xae, 0xd6, 0xd9, 0xdf,
+ 0x2a, 0x5d, 0x27, 0x99, 0x64, 0x1d, 0xc6, 0xdb, 0x5b, 0x0c, 0x61, 0x3c,
+ 0x0c, 0xb8, 0x08, 0xcf, 0xdd, 0x18, 0xc3, 0x30, 0x9e, 0x3c, 0x60, 0x01,
+ 0xb3, 0x9f, 0x2a, 0x00, 0xe6, 0x83, 0x78, 0x18, 0x27, 0x6b, 0x76, 0x22,
+ 0x13, 0xd5, 0xf0, 0x12, 0xc6, 0x1f, 0x5b, 0x78, 0x5f, 0x0f, 0x56, 0x4f,
+ 0x66, 0xba, 0x8b, 0x80, 0x87, 0x70, 0xde, 0x07, 0x18, 0x69, 0x97, 0x8e,
+ 0xe2, 0xdb, 0x03, 0x7c, 0x63, 0x16, 0x26, 0xd0, 0xe3, 0xd8, 0x43, 0xf3,
+ 0xbf, 0x8b, 0xb4, 0x93, 0x8f, 0xd9, 0xef, 0xd6, 0x45, 0x32, 0xe0, 0x15,
+ 0x87, 0x78, 0x1e, 0x29, 0xbd, 0xe6, 0xc0, 0x0e, 0x00, 0xdf, 0xbf, 0xe4,
+ 0x44, 0xce, 0xc4, 0xe5, 0x50, 0x91, 0x31, 0x84, 0xe3, 0x0e, 0xe7, 0x41,
+ 0xf9, 0x57, 0xa1, 0x4c, 0x5c, 0xc9, 0xc4, 0xd5, 0x78, 0xde, 0x82, 0x67,
+ 0x03, 0x9e, 0x8d, 0x78, 0xd6, 0xe3, 0x69, 0xc5, 0xf3, 0x2d, 0x94, 0x53,
+ 0xb1, 0x3a, 0xe1, 0x7e, 0xd5, 0x16, 0xa5, 0x34, 0x1f, 0x71, 0xcf, 0xc2,
+ 0x65, 0xc0, 0xe5, 0x2b, 0xd0, 0x3b, 0x1e, 0x9e, 0xf1, 0xf8, 0x3a, 0xfa,
+ 0x98, 0xc5, 0xd3, 0xa9, 0xe4, 0x4c, 0x17, 0x9e, 0x14, 0x9e, 0x6e, 0x3c,
+ 0x3d, 0x78, 0xd2, 0x78, 0x5e, 0x75, 0x0c, 0xcf, 0x5d, 0x02, 0xbe, 0x42,
+ 0x1e, 0x01, 0xce, 0x17, 0xf0, 0x9c, 0xe7, 0xbc, 0x09, 0x9e, 0x73, 0x2c,
+ 0xcf, 0x39, 0xf3, 0x3c, 0x57, 0xeb, 0xa8, 0x63, 0xf5, 0x4e, 0xe4, 0x18,
+ 0x7d, 0x85, 0x5a, 0xc7, 0xf0, 0x7f, 0x44, 0x7a, 0x07, 0x41, 0x4b, 0xc7,
+ 0x30, 0x67, 0xc7, 0x48, 0x57, 0x2e, 0xd2, 0xc7, 0x16, 0xf5, 0x3b, 0xfa,
+ 0x26, 0xfa, 0x3d, 0x61, 0xfb, 0x7d, 0xb8, 0xaa, 0xdf, 0x83, 0x68, 0xfb,
+ 0x3e, 0xdb, 0xef, 0xc1, 0xaa, 0x7e, 0x41, 0x2b, 0xc7, 0xf2, 0x78, 0x48,
+ 0x17, 0x23, 0x48, 0x0f, 0x65, 0xc2, 0xdd, 0x6b, 0xa4, 0xbe, 0x46, 0x9f,
+ 0x27, 0x8d, 0xf9, 0x35, 0x73, 0xba, 0x31, 0x53, 0xa5, 0x1f, 0x7e, 0x16,
+ 0xfd, 0x38, 0x5c, 0xa2, 0x8d, 0x38, 0x5d, 0x25, 0x17, 0xe8, 0xfb, 0x04,
+ 0x72, 0x5c, 0xfb, 0x39, 0xf4, 0x79, 0xe8, 0xff, 0x2c, 0xb6, 0xad, 0x3e,
+ 0xae, 0xf7, 0xe7, 0xde, 0x55, 0x6c, 0x95, 0x4f, 0x14, 0x69, 0x13, 0x92,
+ 0x5e, 0x82, 0x60, 0xcf, 0x36, 0xda, 0xa7, 0xf9, 0x60, 0x9d, 0x9f, 0xd4,
+ 0xb1, 0xb5, 0x4f, 0x2e, 0xd5, 0x19, 0xa3, 0xbd, 0xf0, 0xcd, 0xb3, 0x47,
+ 0x3f, 0x08, 0x9d, 0x51, 0x03, 0xb8, 0x9f, 0xd2, 0x77, 0x80, 0xec, 0x1a,
+ 0x55, 0x23, 0x6b, 0x25, 0x2e, 0x37, 0x17, 0x6b, 0x61, 0xf7, 0x30, 0x56,
+ 0x5e, 0x2f, 0xed, 0xdb, 0xa2, 0xe6, 0x6c, 0x8d, 0x17, 0xc3, 0x6f, 0xcf,
+ 0x9c, 0xf5, 0x89, 0xc5, 0x91, 0x1f, 0x69, 0xa2, 0x1c, 0x8c, 0xf9, 0xef,
+ 0xd4, 0xfb, 0x26, 0xdb, 0xb6, 0xd1, 0x6e, 0xb9, 0x41, 0xeb, 0x70, 0x77,
+ 0x89, 0x9d, 0xa4, 0x5a, 0x3c, 0x99, 0xb7, 0xd1, 0x76, 0x17, 0x93, 0x09,
+ 0xc2, 0xf5, 0x90, 0x70, 0x3f, 0xc1, 0x7e, 0x29, 0xa4, 0x1a, 0x25, 0x92,
+ 0xe6, 0xba, 0x5c, 0xb2, 0x93, 0xb6, 0xd1, 0xc4, 0x98, 0x67, 0xcf, 0x9e,
+ 0xac, 0x96, 0x0b, 0xba, 0x9f, 0x5a, 0x0d, 0xa3, 0x39, 0x8f, 0xc6, 0x35,
+ 0x2f, 0x9e, 0x81, 0x72, 0xf1, 0x6e, 0xd0, 0x7a, 0x67, 0xa2, 0xcc, 0xb3,
+ 0x4e, 0xf0, 0x97, 0xca, 0x31, 0x7d, 0xc6, 0xd4, 0x7b, 0x3b, 0xfc, 0xd8,
+ 0xf2, 0x06, 0xd9, 0x3d, 0xb6, 0x82, 0xeb, 0x28, 0xb1, 0xb5, 0xd0, 0x1f,
+ 0xac, 0xd3, 0xb6, 0x0d, 0xfe, 0xdf, 0xf8, 0x46, 0x79, 0x7c, 0x9c, 0x6d,
+ 0xb7, 0xc8, 0xe4, 0x94, 0x38, 0xde, 0xdb, 0x57, 0xa2, 0x8c, 0xc7, 0xf1,
+ 0x08, 0xf7, 0x3c, 0xb5, 0x6d, 0x13, 0xe5, 0xbd, 0xdd, 0x95, 0xf3, 0xdd,
+ 0x11, 0xbd, 0x26, 0xe3, 0x82, 0x4e, 0xd8, 0xde, 0xf9, 0xee, 0x56, 0x39,
+ 0x3b, 0x05, 0x9a, 0x80, 0xdc, 0xef, 0x3b, 0x45, 0x98, 0x44, 0xb6, 0x4f,
+ 0xc0, 0x5e, 0x90, 0x76, 0x3c, 0xa0, 0x0f, 0xc8, 0xef, 0x5b, 0xbb, 0xd9,
+ 0x17, 0xf4, 0x12, 0x74, 0x5c, 0xdb, 0x36, 0x23, 0x0b, 0x32, 0x13, 0x35,
+ 0x48, 0x67, 0xbb, 0xf0, 0x0f, 0x07, 0xd9, 0x4e, 0x58, 0x57, 0x61, 0x4c,
+ 0xb5, 0x9a, 0x5e, 0x66, 0x17, 0xe9, 0x8f, 0x73, 0x3f, 0x97, 0xfd, 0xcd,
+ 0x36, 0x3a, 0x41, 0x2b, 0xbe, 0xde, 0xc3, 0x63, 0x6c, 0x2b, 0xce, 0x09,
+ 0x6d, 0x22, 0xda, 0x55, 0xd7, 0x6a, 0xfb, 0x62, 0xb2, 0xc2, 0x19, 0xe4,
+ 0xda, 0x48, 0x38, 0x47, 0x71, 0x39, 0x59, 0x9a, 0x9b, 0xa7, 0x0d, 0x35,
+ 0x0b, 0xe7, 0x89, 0xb4, 0x92, 0x1a, 0xb2, 0xb6, 0xc7, 0x8c, 0x3c, 0x0f,
+ 0xbb, 0xac, 0x53, 0xcf, 0xd9, 0x0c, 0x6c, 0x59, 0x3b, 0x67, 0xda, 0x9e,
+ 0x2d, 0x84, 0x73, 0x36, 0x00, 0x8d, 0x53, 0xbe, 0x41, 0xcf, 0x99, 0x07,
+ 0xba, 0xc9, 0x03, 0xef, 0x79, 0xcc, 0x53, 0x1e, 0x73, 0x94, 0x2f, 0xb7,
+ 0xc8, 0xc4, 0x71, 0xd5, 0x5a, 0x23, 0x92, 0xd8, 0xed, 0xb7, 0xc8, 0xf0,
+ 0x14, 0x63, 0x05, 0x1b, 0x60, 0x83, 0x6d, 0xc4, 0xd3, 0x8a, 0x6f, 0xd6,
+ 0xe3, 0x1d, 0x1f, 0x0a, 0x75, 0xeb, 0x96, 0xd8, 0x59, 0x67, 0xd1, 0xf7,
+ 0xd3, 0xc0, 0xc3, 0xa3, 0xc0, 0xc3, 0x3c, 0xef, 0xbc, 0x50, 0x15, 0x5f,
+ 0xe2, 0x58, 0xb5, 0x0e, 0xc5, 0x78, 0x63, 0x7a, 0x3e, 0x75, 0x9c, 0xa9,
+ 0x54, 0xfb, 0x66, 0xec, 0xa9, 0x38, 0xed, 0xa9, 0xdc, 0xa8, 0x67, 0xce,
+ 0x60, 0x0d, 0xc0, 0x77, 0xf2, 0xf7, 0x69, 0x5a, 0x1f, 0x1a, 0x27, 0x5c,
+ 0xd1, 0x10, 0xae, 0x05, 0x73, 0xc6, 0x33, 0xb3, 0x4b, 0xe3, 0x18, 0x2f,
+ 0xcc, 0xed, 0x11, 0x87, 0x2e, 0x97, 0xd1, 0x14, 0xe3, 0x24, 0xad, 0xcb,
+ 0xc0, 0xf4, 0x94, 0xb6, 0x61, 0x45, 0x9d, 0x96, 0x03, 0x25, 0x9e, 0xb7,
+ 0xe5, 0x1a, 0xcc, 0xef, 0x31, 0x7e, 0xd4, 0x39, 0x21, 0xc7, 0xd0, 0x37,
+ 0xd7, 0xc5, 0x95, 0x8d, 0xcf, 0xac, 0xb2, 0x7b, 0xf2, 0xaa, 0x63, 0x34,
+ 0x66, 0xdd, 0x7c, 0xe1, 0xd9, 0x93, 0xe4, 0xc0, 0xac, 0x5e, 0x77, 0xe5,
+ 0x9a, 0xa1, 0x8c, 0x46, 0xa0, 0xfd, 0x76, 0x77, 0x27, 0x7b, 0xcc, 0x59,
+ 0xc3, 0x84, 0xf4, 0x97, 0xcc, 0xf8, 0x2f, 0xea, 0x7d, 0x93, 0x66, 0x7f,
+ 0xb8, 0xd9, 0x53, 0xb9, 0x5f, 0x2e, 0xa6, 0xa2, 0x55, 0x73, 0x5b, 0x27,
+ 0xc3, 0xc0, 0x85, 0x5e, 0xcb, 0x84, 0x5d, 0x9c, 0xeb, 0x7e, 0xbc, 0x89,
+ 0x67, 0xd1, 0xa2, 0x98, 0x9f, 0xc2, 0x38, 0xcf, 0xa7, 0xb3, 0xdd, 0x2b,
+ 0xb5, 0x45, 0x31, 0xcb, 0xb3, 0x4e, 0x90, 0x95, 0x6f, 0xdd, 0x12, 0xaf,
+ 0xd7, 0xf9, 0x2b, 0xec, 0x99, 0x16, 0xd8, 0x0d, 0xbb, 0x02, 0xf9, 0x33,
+ 0xe8, 0xc9, 0xd3, 0x76, 0x4c, 0x09, 0x1d, 0x93, 0x92, 0xe0, 0x7c, 0x2a,
+ 0x6e, 0xe3, 0xce, 0x1c, 0xcb, 0x98, 0xa5, 0x6f, 0x63, 0xff, 0xcc, 0xdb,
+ 0xd0, 0x5d, 0x9a, 0xd6, 0x1f, 0xd7, 0xb2, 0xb0, 0xcb, 0xda, 0xce, 0x3a,
+ 0x8e, 0x73, 0x42, 0xf4, 0x1e, 0xac, 0xd0, 0x37, 0xea, 0xa8, 0xf2, 0x0b,
+ 0x8c, 0x2f, 0x57, 0x18, 0x5b, 0x4e, 0x46, 0xcd, 0xfb, 0x84, 0xf4, 0xe5,
+ 0xf6, 0x6c, 0xe2, 0xdd, 0x30, 0xa1, 0x2f, 0xd7, 0x65, 0x7d, 0xb9, 0x46,
+ 0xed, 0xcb, 0x99, 0xd8, 0x43, 0xe3, 0x9c, 0x2f, 0x57, 0x18, 0xcb, 0x83,
+ 0x56, 0x6a, 0xed, 0x59, 0x09, 0x63, 0x0b, 0x0d, 0x17, 0x5d, 0xbd, 0x6f,
+ 0x24, 0x37, 0xa0, 0xe0, 0x37, 0x18, 0x1f, 0x8b, 0xb1, 0x0a, 0xa5, 0xfe,
+ 0xce, 0xfa, 0x17, 0x1b, 0x24, 0xd3, 0xbc, 0x02, 0xe3, 0x7e, 0x4a, 0xcf,
+ 0xb9, 0x59, 0xc3, 0x82, 0x5c, 0x1b, 0x64, 0xcc, 0x87, 0x67, 0x47, 0x35,
+ 0x7f, 0x25, 0x7a, 0x23, 0x9d, 0xc6, 0x9e, 0xf5, 0x13, 0x6b, 0xa5, 0xfe,
+ 0xb8, 0x53, 0x18, 0x8f, 0xda, 0x7e, 0x13, 0x80, 0xa9, 0x06, 0x73, 0xf3,
+ 0x4e, 0x2b, 0x93, 0xd9, 0xf7, 0x3b, 0xea, 0x18, 0x1b, 0x98, 0x2a, 0x9a,
+ 0x18, 0x60, 0x5f, 0x31, 0x12, 0x9e, 0x5b, 0x57, 0x5c, 0x47, 0xce, 0x0c,
+ 0xae, 0x00, 0x2c, 0x2b, 0x96, 0xb5, 0x59, 0x1f, 0x7b, 0x43, 0x1d, 0x45,
+ 0x9a, 0x7a, 0x4a, 0xef, 0x2f, 0x5c, 0xd9, 0x9d, 0xdc, 0xa9, 0xcf, 0x23,
+ 0xe9, 0x58, 0x62, 0x5e, 0xb8, 0x7f, 0xf7, 0x9b, 0xf2, 0x36, 0x2d, 0xfb,
+ 0x0f, 0xa4, 0xa8, 0xc7, 0xb6, 0xe9, 0xdf, 0xb5, 0xe9, 0x20, 0x38, 0xdf,
+ 0xfd, 0x2c, 0x6c, 0x16, 0xdf, 0xfb, 0x96, 0xb4, 0xc7, 0x7b, 0xb5, 0x0d,
+ 0x85, 0xb9, 0x1a, 0xac, 0x97, 0x15, 0xfe, 0xb8, 0xdd, 0xab, 0x68, 0xd6,
+ 0x03, 0x0b, 0xc2, 0xfb, 0x17, 0x3a, 0x6c, 0x5e, 0x3e, 0xa8, 0x07, 0x3d,
+ 0x7d, 0x44, 0x8c, 0xac, 0xc9, 0xcd, 0xcb, 0x1a, 0xee, 0xa7, 0xcb, 0x90,
+ 0xa0, 0xdd, 0x23, 0x92, 0xe4, 0xdd, 0x49, 0xec, 0xbb, 0x20, 0x57, 0x41,
+ 0x3f, 0xb3, 0x1e, 0x6d, 0x56, 0x7e, 0x73, 0x0f, 0x8a, 0xef, 0x1d, 0x84,
+ 0x8e, 0xb9, 0x61, 0xa9, 0x8e, 0x89, 0xd3, 0xbf, 0xcf, 0x8d, 0xd2, 0x47,
+ 0x5c, 0x89, 0x3a, 0x2d, 0xf2, 0xd1, 0xb1, 0xdf, 0x5a, 0x4b, 0x1e, 0x1b,
+ 0x82, 0x7c, 0x57, 0xf7, 0x87, 0xe7, 0x2e, 0x99, 0xc6, 0x7c, 0xb6, 0x5b,
+ 0x27, 0x89, 0xf7, 0x79, 0xf2, 0xc5, 0x4a, 0x32, 0x31, 0x0b, 0x1d, 0x35,
+ 0xe4, 0x0c, 0xb7, 0x9a, 0xd8, 0xe9, 0xa7, 0xd6, 0x9a, 0x73, 0x5a, 0xf5,
+ 0xc0, 0x69, 0x18, 0x4f, 0xad, 0xa6, 0xdd, 0x59, 0x2b, 0x97, 0x83, 0xa0,
+ 0xbe, 0x5b, 0xcb, 0xe2, 0x9d, 0x94, 0xc5, 0x07, 0x52, 0x1d, 0x86, 0x07,
+ 0xb4, 0xef, 0xc4, 0x3d, 0x00, 0xc0, 0x43, 0xb7, 0xcb, 0xbd, 0xd0, 0x96,
+ 0x4f, 0xfd, 0xcc, 0x8c, 0x95, 0x4f, 0xca, 0x59, 0xca, 0x9f, 0x6a, 0x6b,
+ 0x74, 0x81, 0xec, 0x3d, 0x34, 0x46, 0xbd, 0x9c, 0x9a, 0xfe, 0x26, 0xe4,
+ 0x55, 0x4e, 0xe3, 0xa1, 0x45, 0xee, 0x1b, 0x93, 0xcc, 0x45, 0xe8, 0xac,
+ 0xc2, 0xd4, 0x42, 0x1e, 0x5d, 0xda, 0x1e, 0xc7, 0x7a, 0x7a, 0xad, 0xf1,
+ 0x71, 0x17, 0x8e, 0x75, 0x9a, 0x7b, 0x8c, 0xf4, 0x58, 0xb9, 0x37, 0xff,
+ 0x9c, 0x1d, 0xeb, 0xca, 0x70, 0xac, 0x3d, 0x0b, 0xc7, 0x1a, 0xfa, 0xf8,
+ 0xa1, 0xfc, 0x4d, 0xe8, 0xb3, 0x49, 0xfa, 0x4c, 0xcc, 0xd8, 0x4a, 0xe9,
+ 0x1d, 0x6d, 0xb4, 0x72, 0xd3, 0x83, 0x0e, 0xe2, 0x79, 0xa1, 0xe9, 0xcf,
+ 0x79, 0x62, 0x71, 0xa6, 0x88, 0x07, 0xca, 0xdc, 0x26, 0x7d, 0x9e, 0x71,
+ 0x02, 0x7e, 0xd6, 0x87, 0x8b, 0x2c, 0x1b, 0xe6, 0x5f, 0x29, 0x46, 0x1c,
+ 0xfa, 0xd6, 0xf4, 0x9f, 0x3a, 0x97, 0xc4, 0x16, 0x4c, 0x1c, 0x98, 0xf1,
+ 0x5f, 0x73, 0xcf, 0x02, 0xf7, 0x7d, 0xdf, 0x01, 0xde, 0xfa, 0xed, 0x62,
+ 0xb2, 0x27, 0x1b, 0xa1, 0x3c, 0x9d, 0x95, 0x43, 0x95, 0x3e, 0x69, 0xd3,
+ 0x67, 0xed, 0xdf, 0x30, 0x46, 0x9c, 0xa9, 0x8e, 0x11, 0x8b, 0x63, 0x62,
+ 0xc4, 0x3b, 0x7f, 0x8e, 0x18, 0xb1, 0x38, 0x26, 0x46, 0xbc, 0x9c, 0x9f,
+ 0x35, 0x52, 0x9a, 0xc5, 0xb8, 0xea, 0x21, 0x53, 0x94, 0x93, 0x9b, 0x6a,
+ 0xc0, 0xbb, 0x16, 0x6f, 0xc0, 0x32, 0x56, 0xc0, 0xdb, 0xc3, 0xfb, 0x20,
+ 0xde, 0x31, 0x19, 0x99, 0xd3, 0x1d, 0xb3, 0x90, 0x1f, 0xd4, 0x69, 0xac,
+ 0x6b, 0xfc, 0x82, 0xc9, 0x72, 0x33, 0xca, 0x5d, 0x72, 0x26, 0x58, 0xaf,
+ 0xd4, 0x28, 0xc3, 0x63, 0x94, 0xdd, 0x4d, 0x32, 0x3a, 0x16, 0xda, 0xb8,
+ 0x9f, 0x5d, 0xcf, 0xb5, 0x81, 0x21, 0x09, 0x6d, 0xd8, 0x67, 0xd6, 0x9b,
+ 0xb5, 0xdb, 0x2d, 0x31, 0xa9, 0x5f, 0x8d, 0x39, 0x38, 0xee, 0x5c, 0x1c,
+ 0x5f, 0xbd, 0xc0, 0x96, 0x4d, 0xd8, 0xd8, 0xe0, 0xb8, 0xd5, 0xc1, 0xcb,
+ 0xcb, 0x88, 0xea, 0xf9, 0x8f, 0xdb, 0x73, 0xbc, 0x51, 0x7b, 0xd7, 0x5f,
+ 0x42, 0xcf, 0xcf, 0x40, 0x65, 0x16, 0xfd, 0xad, 0x57, 0x99, 0x71, 0x8e,
+ 0x73, 0xee, 0x7e, 0x1e, 0xc8, 0xc5, 0x56, 0x35, 0x34, 0xbe, 0x80, 0x2e,
+ 0x41, 0xb7, 0x1c, 0x9b, 0x03, 0xda, 0xbd, 0x57, 0x26, 0x46, 0x09, 0x5f,
+ 0x47, 0x3c, 0xa2, 0xcf, 0xf5, 0xe2, 0x7b, 0xdc, 0x9c, 0x27, 0xea, 0xad,
+ 0x84, 0x67, 0x7a, 0xd7, 0x00, 0xde, 0xc5, 0xe7, 0x7a, 0xad, 0x9e, 0xd6,
+ 0x36, 0x04, 0xcf, 0xf7, 0x86, 0x63, 0x58, 0x8e, 0x9e, 0x02, 0x19, 0xd6,
+ 0xfb, 0x7d, 0xd7, 0xca, 0xe9, 0x07, 0xe7, 0xce, 0x17, 0x34, 0xc1, 0x56,
+ 0x69, 0x85, 0xa9, 0x3c, 0xe0, 0xa6, 0xb9, 0xef, 0x82, 0xfb, 0x0b, 0x3a,
+ 0xe2, 0xb7, 0xe9, 0x73, 0x1f, 0xf3, 0x67, 0xac, 0xe7, 0xcf, 0x7e, 0x84,
+ 0x67, 0x5a, 0xe3, 0xd2, 0x07, 0x3a, 0xec, 0xd7, 0xe9, 0x31, 0x8c, 0x87,
+ 0x6b, 0xbe, 0x1a, 0x0f, 0x90, 0x3d, 0x5c, 0xfb, 0xc5, 0xd8, 0x2b, 0x2d,
+ 0x2a, 0xa7, 0xcf, 0x58, 0x47, 0x2d, 0x8d, 0x5d, 0x76, 0xf6, 0x94, 0x13,
+ 0x6a, 0x4f, 0xd9, 0x57, 0x7b, 0xcb, 0x36, 0xaf, 0xfb, 0x01, 0xcc, 0x07,
+ 0x7e, 0x8f, 0x17, 0x9d, 0x21, 0xe0, 0xab, 0x50, 0x3a, 0xe2, 0x64, 0xf4,
+ 0xfb, 0xa8, 0x7d, 0x43, 0x0e, 0x60, 0xae, 0x7a, 0xc7, 0xa3, 0x5a, 0xde,
+ 0xcf, 0xdf, 0xd3, 0x17, 0xce, 0xeb, 0x0b, 0x7a, 0x0d, 0x68, 0x5a, 0x88,
+ 0x6b, 0xcf, 0xda, 0x10, 0xc7, 0x9d, 0x9c, 0xc6, 0x3d, 0xcb, 0x7c, 0x4b,
+ 0xff, 0x06, 0x9d, 0x2b, 0xd3, 0x5e, 0x2b, 0xde, 0x8b, 0xf7, 0x4d, 0x86,
+ 0xfa, 0x86, 0x70, 0xdf, 0x09, 0xbd, 0x16, 0xec, 0x37, 0xf2, 0x6a, 0x56,
+ 0x46, 0x2a, 0x5c, 0xc3, 0x64, 0x3b, 0x48, 0x2f, 0xd7, 0xc0, 0x1e, 0x58,
+ 0x78, 0xbe, 0xba, 0x7f, 0x7e, 0x1e, 0x12, 0xe3, 0x42, 0x58, 0xee, 0xd6,
+ 0x67, 0x17, 0xab, 0xef, 0x1e, 0xb9, 0xf2, 0xbf, 0x70, 0xfd, 0xd0, 0xc8,
+ 0x50, 0x0b, 0x47, 0x86, 0xf2, 0xce, 0xc8, 0x95, 0xaf, 0xcb, 0x41, 0xe0,
+ 0xf1, 0x30, 0x60, 0x52, 0xf7, 0xf3, 0xce, 0xab, 0x57, 0xa5, 0x30, 0x59,
+ 0x2f, 0xea, 0xa1, 0x82, 0xe3, 0x3e, 0x54, 0x2b, 0x91, 0x87, 0x94, 0x53,
+ 0xf3, 0x50, 0xbb, 0xf6, 0xcf, 0x77, 0xa4, 0xda, 0xe3, 0x7b, 0xe5, 0xb8,
+ 0xe3, 0xde, 0xaf, 0xf4, 0x59, 0xdb, 0x82, 0xc7, 0x58, 0xdf, 0x71, 0x27,
+ 0x72, 0x7f, 0xd4, 0x9e, 0xd3, 0x37, 0xf1, 0xbd, 0x59, 0xcd, 0xf7, 0xdf,
+ 0x58, 0x47, 0x9c, 0xcd, 0x0a, 0xf1, 0xf1, 0x59, 0xc8, 0xad, 0x4f, 0x4b,
+ 0x76, 0x34, 0x31, 0x57, 0xc6, 0xec, 0xb3, 0xdf, 0xb0, 0xce, 0xf0, 0x0b,
+ 0xcb, 0xbc, 0xe2, 0xf0, 0xce, 0x1c, 0xa3, 0x33, 0x3e, 0xdf, 0x12, 0xee,
+ 0xb9, 0x37, 0x73, 0xca, 0xfc, 0xc6, 0x75, 0x52, 0xff, 0x0a, 0xe6, 0x8b,
+ 0xfd, 0x11, 0x57, 0xab, 0xf4, 0x3d, 0x05, 0x9e, 0x6c, 0x89, 0xd7, 0xcd,
+ 0xd9, 0x43, 0x46, 0xf6, 0xd6, 0x01, 0x6e, 0xc0, 0x6f, 0xec, 0x3b, 0x21,
+ 0x9d, 0x0a, 0x24, 0x37, 0x69, 0xb6, 0xa3, 0x67, 0x87, 0x98, 0x39, 0x33,
+ 0x34, 0xb3, 0xc2, 0xd8, 0x91, 0xf8, 0x36, 0x74, 0xa1, 0x64, 0xfb, 0xd8,
+ 0x4b, 0x4e, 0x3f, 0xcf, 0x3c, 0x8a, 0xb6, 0x1b, 0x97, 0xb3, 0x09, 0xc1,
+ 0x4b, 0xcf, 0x5b, 0xff, 0x32, 0x08, 0xc6, 0x52, 0x29, 0xde, 0x2b, 0xb8,
+ 0x8c, 0x4f, 0xb9, 0xca, 0x99, 0x1c, 0x6d, 0x70, 0x26, 0x46, 0x03, 0xd9,
+ 0x93, 0xe2, 0x9d, 0x49, 0xdc, 0x93, 0xa0, 0xe3, 0xe3, 0x48, 0x6b, 0x87,
+ 0x6e, 0x7d, 0xc7, 0x3a, 0xee, 0x71, 0xbb, 0xd9, 0x6f, 0xb4, 0xe5, 0x88,
+ 0x63, 0xfa, 0xca, 0xed, 0x27, 0x72, 0xc2, 0xbb, 0x8b, 0xb6, 0xc4, 0x63,
+ 0x7a, 0x7f, 0xe2, 0x17, 0x50, 0x0f, 0x7d, 0x94, 0xd8, 0xaf, 0xeb, 0x4c,
+ 0x40, 0x9e, 0x4d, 0x8e, 0xf1, 0xbe, 0x14, 0x9e, 0x63, 0x88, 0xb4, 0x2a,
+ 0xb9, 0xd6, 0x1b, 0xb6, 0xf7, 0x69, 0xe6, 0xe1, 0x0a, 0x45, 0x74, 0xda,
+ 0x16, 0x6f, 0xf7, 0xdc, 0x1d, 0x9b, 0x61, 0x5a, 0x78, 0xd7, 0xa6, 0xd2,
+ 0x67, 0x56, 0xe0, 0xd3, 0x9e, 0x1e, 0x92, 0xb8, 0x33, 0x55, 0x6c, 0x75,
+ 0x4e, 0x16, 0x33, 0x5b, 0xd7, 0x81, 0x3e, 0xce, 0xa7, 0x3e, 0x46, 0xf9,
+ 0x05, 0xdb, 0xef, 0x45, 0xc9, 0x57, 0x3e, 0x24, 0xe3, 0x2d, 0xed, 0xde,
+ 0xfd, 0x7a, 0x6e, 0x2e, 0x03, 0x67, 0x2d, 0x2a, 0x3b, 0xfa, 0xc4, 0x3a,
+ 0xea, 0xb7, 0xdd, 0x45, 0x05, 0x5e, 0x56, 0xbf, 0x88, 0x07, 0x36, 0x6e,
+ 0xad, 0xb6, 0x51, 0xf6, 0xa6, 0x58, 0xae, 0xc1, 0xe9, 0x1d, 0x5d, 0x85,
+ 0x79, 0xdc, 0x05, 0xfd, 0xe9, 0xc0, 0x46, 0x22, 0xae, 0x1b, 0x9c, 0x3d,
+ 0xa3, 0x79, 0xf4, 0xc8, 0x7d, 0xd6, 0xbc, 0xf7, 0xf0, 0x30, 0xc6, 0xa8,
+ 0xe5, 0x2b, 0x78, 0xf7, 0x12, 0xd7, 0xdb, 0x83, 0x49, 0xd8, 0x06, 0xb9,
+ 0xae, 0x7f, 0x67, 0xd7, 0xab, 0xa7, 0xaf, 0xb0, 0x5e, 0xed, 0xc9, 0x23,
+ 0x15, 0x7d, 0x6f, 0x48, 0xe7, 0xb8, 0xe2, 0x3a, 0x6e, 0xf3, 0x55, 0x7a,
+ 0x7e, 0x54, 0x87, 0xdd, 0x1b, 0x78, 0x72, 0x9d, 0xbd, 0xd3, 0x06, 0x70,
+ 0x5c, 0x05, 0x18, 0x36, 0x62, 0xfc, 0x84, 0xc1, 0xd4, 0x11, 0x75, 0x4b,
+ 0x9c, 0x3a, 0x70, 0x56, 0x4e, 0xaf, 0x0b, 0xf7, 0x7b, 0xa0, 0x1d, 0xc8,
+ 0xb5, 0x47, 0xe3, 0x46, 0x37, 0xae, 0x5d, 0xa6, 0x9d, 0x70, 0x3c, 0x8e,
+ 0x1d, 0x0f, 0x69, 0x75, 0x43, 0x0b, 0xfd, 0x89, 0x59, 0xa9, 0x5b, 0x54,
+ 0x9e, 0xf1, 0xfc, 0x5d, 0xad, 0x66, 0xdf, 0x11, 0xcb, 0x7a, 0xb0, 0x4b,
+ 0x69, 0xe3, 0x12, 0x77, 0x7a, 0xae, 0x8a, 0xdc, 0x5b, 0x9c, 0xf3, 0x2f,
+ 0x43, 0x9e, 0x5c, 0xeb, 0xbd, 0x4d, 0x91, 0xf6, 0x42, 0xfc, 0x12, 0xb7,
+ 0x09, 0xe0, 0x95, 0x71, 0x95, 0xd3, 0x41, 0x66, 0x80, 0x7c, 0xc5, 0x36,
+ 0x98, 0xff, 0xa2, 0x8e, 0xe5, 0x0e, 0xa6, 0x18, 0x27, 0x6a, 0x3f, 0x71,
+ 0x87, 0x0a, 0x65, 0xd3, 0x2c, 0xd7, 0x10, 0x1c, 0xde, 0x21, 0xba, 0x0b,
+ 0x1d, 0x5e, 0x9c, 0x52, 0xce, 0x37, 0xc7, 0x5c, 0x7c, 0xd7, 0xd8, 0xfb,
+ 0x42, 0x8d, 0x6e, 0x12, 0xf9, 0xeb, 0x70, 0xbc, 0xf1, 0x3c, 0xe6, 0xfb,
+ 0x12, 0xe6, 0x7b, 0xf9, 0xfb, 0x41, 0x91, 0x57, 0x46, 0x5e, 0xf9, 0x43,
+ 0x41, 0xa6, 0x89, 0xf4, 0x47, 0x9a, 0x7b, 0x3d, 0x9f, 0x59, 0xef, 0x63,
+ 0x02, 0x6c, 0x67, 0xc1, 0x0b, 0x19, 0xae, 0x25, 0x07, 0xc7, 0x52, 0x37,
+ 0x81, 0x17, 0x76, 0xca, 0x9f, 0xc0, 0x16, 0xf8, 0xe3, 0x4a, 0x1a, 0x3c,
+ 0xd1, 0x03, 0x1e, 0xe9, 0x06, 0x5f, 0xa4, 0xb4, 0x5d, 0xfc, 0x28, 0x74,
+ 0xde, 0xd9, 0x4a, 0xc9, 0xd9, 0x3b, 0x5a, 0x74, 0x72, 0xa3, 0x47, 0x41,
+ 0x17, 0xdc, 0x03, 0xab, 0xae, 0xa9, 0x11, 0x37, 0x3e, 0x29, 0xa4, 0xff,
+ 0x76, 0xee, 0xed, 0x68, 0x06, 0xae, 0xce, 0x10, 0x57, 0x93, 0x95, 0x2d,
+ 0xde, 0x3a, 0xf0, 0x41, 0xb3, 0xe6, 0x83, 0x46, 0x27, 0xe3, 0xdd, 0x64,
+ 0xf9, 0x60, 0x04, 0x7c, 0x50, 0x58, 0xc2, 0x07, 0xcf, 0x58, 0x9a, 0x9f,
+ 0xae, 0xe2, 0x83, 0x49, 0x9b, 0x36, 0x7e, 0x05, 0x3e, 0xb8, 0xca, 0x4f,
+ 0x3e, 0x39, 0x24, 0x27, 0xc0, 0x07, 0x0f, 0x6b, 0x3e, 0xb8, 0x4a, 0xf3,
+ 0x01, 0xe3, 0x46, 0xe4, 0x85, 0x56, 0xc8, 0x0e, 0xf2, 0xc2, 0xb3, 0x32,
+ 0x0b, 0x5e, 0x78, 0x51, 0xb1, 0xef, 0xcb, 0xb4, 0x0f, 0x46, 0xe9, 0x8f,
+ 0x9d, 0x2a, 0x15, 0xc1, 0xbb, 0x4a, 0xbe, 0x30, 0x16, 0x04, 0x33, 0xf0,
+ 0xd1, 0x1f, 0x84, 0x0d, 0xef, 0xea, 0x3b, 0x69, 0xa7, 0x61, 0xbb, 0x10,
+ 0x36, 0xda, 0xe4, 0xe3, 0x0e, 0xe8, 0xfd, 0xf0, 0x04, 0xc6, 0xb0, 0x47,
+ 0xfd, 0x3e, 0xfc, 0x60, 0x0f, 0xf3, 0x4a, 0xdb, 0xfe, 0xb8, 0xe6, 0x9b,
+ 0x1a, 0xe8, 0x80, 0x93, 0xdd, 0x8c, 0x33, 0xf9, 0xde, 0x5e, 0xd5, 0x9e,
+ 0xef, 0x03, 0xcc, 0x11, 0x75, 0xbf, 0x30, 0xc6, 0xd1, 0xb4, 0xc8, 0xb6,
+ 0xa7, 0x5c, 0x18, 0x90, 0xfb, 0x6c, 0x5e, 0x3e, 0xa8, 0x83, 0x1d, 0x5a,
+ 0xa7, 0x8c, 0x5d, 0xae, 0xb6, 0x25, 0xbd, 0xdf, 0x80, 0xd0, 0xac, 0x4d,
+ 0x9b, 0x3d, 0x81, 0x7d, 0xc5, 0x6a, 0xbb, 0xfe, 0x5e, 0xd8, 0xf5, 0xac,
+ 0x23, 0xae, 0xb1, 0xeb, 0xef, 0xb2, 0xbc, 0xc6, 0xdf, 0x9e, 0xb6, 0xf1,
+ 0x0f, 0x00, 0xbe, 0x1d, 0x73, 0x36, 0x3e, 0xdb, 0xa0, 0xad, 0x21, 0x72,
+ 0x03, 0xec, 0xbc, 0x1b, 0xc1, 0x83, 0x37, 0xc1, 0x8f, 0x7a, 0x77, 0xd1,
+ 0x93, 0x9d, 0xc5, 0x66, 0xf8, 0xdb, 0xad, 0xf2, 0xab, 0x63, 0x1b, 0xa5,
+ 0x7f, 0xf4, 0x77, 0x9a, 0xa1, 0x57, 0x61, 0x97, 0xbe, 0x08, 0x38, 0x23,
+ 0x56, 0x56, 0x47, 0xc1, 0x03, 0xed, 0x89, 0x1f, 0xa8, 0x44, 0xab, 0x91,
+ 0xed, 0x3c, 0x4b, 0xbe, 0x5c, 0x3b, 0x31, 0xd4, 0x67, 0x1c, 0xa5, 0x45,
+ 0xce, 0x1c, 0xa7, 0xe7, 0x95, 0x80, 0x2d, 0x9e, 0x82, 0x1d, 0xb2, 0x01,
+ 0xed, 0x31, 0x96, 0xbc, 0x5a, 0x9e, 0xd9, 0xea, 0xde, 0x9d, 0xd3, 0x7c,
+ 0x78, 0xc9, 0xc9, 0x8e, 0xdd, 0x24, 0x85, 0xc1, 0x28, 0xc6, 0xa0, 0x9a,
+ 0xd7, 0xca, 0xf5, 0xd2, 0xaf, 0xc7, 0x73, 0x59, 0x0e, 0x42, 0x1f, 0xff,
+ 0x69, 0xb1, 0x5f, 0x66, 0x07, 0x9a, 0xf0, 0x1d, 0x95, 0x67, 0x8a, 0x5b,
+ 0xe0, 0xef, 0xfc, 0x0a, 0x70, 0x54, 0x8b, 0xef, 0x5a, 0xe9, 0x5d, 0x47,
+ 0x5e, 0x6d, 0x90, 0x19, 0xa4, 0xdf, 0x28, 0xbf, 0x64, 0xd3, 0x99, 0x46,
+ 0xde, 0x68, 0x40, 0xdd, 0xa8, 0x9c, 0x2f, 0xd2, 0x96, 0xd4, 0x3c, 0xd1,
+ 0xf3, 0xb2, 0x6c, 0xc9, 0xbc, 0x0c, 0xdb, 0xf4, 0x59, 0x3c, 0xcf, 0x4b,
+ 0x72, 0xe7, 0x6e, 0x67, 0x4b, 0xa2, 0xdd, 0x81, 0xbe, 0xc4, 0xe3, 0x3a,
+ 0x5b, 0xbc, 0x5a, 0xe7, 0x5a, 0xdb, 0x46, 0x8d, 0x3c, 0x3f, 0xa8, 0xe2,
+ 0x0d, 0x98, 0x93, 0xcd, 0x4e, 0x87, 0x4d, 0xe3, 0xb7, 0xbe, 0x2f, 0x51,
+ 0xda, 0xcf, 0xa8, 0x0d, 0xab, 0x44, 0xda, 0x1a, 0x60, 0xe7, 0xec, 0x11,
+ 0xd5, 0xdc, 0x20, 0xae, 0xb4, 0x4f, 0xa8, 0x56, 0xa4, 0xf9, 0x36, 0x2d,
+ 0xd6, 0x00, 0x9d, 0x80, 0xb4, 0x16, 0xa4, 0x6d, 0xb2, 0x69, 0x4d, 0x0d,
+ 0x52, 0x8b, 0xb4, 0xcb, 0x9a, 0xe7, 0x2f, 0x76, 0xf8, 0x5e, 0xce, 0xa9,
+ 0x97, 0xb6, 0x53, 0x0d, 0x90, 0x0d, 0xab, 0x65, 0x66, 0x6b, 0x9d, 0xb4,
+ 0x21, 0x8f, 0x31, 0xee, 0xd4, 0xa9, 0xa8, 0xbc, 0xf3, 0x54, 0x7b, 0xfc,
+ 0xa3, 0x18, 0x43, 0xfb, 0x19, 0xc6, 0xbc, 0xff, 0xac, 0x99, 0x31, 0x9f,
+ 0xb6, 0x33, 0x7c, 0xd7, 0x69, 0xf9, 0x43, 0x7c, 0x98, 0x3b, 0xdf, 0x60,
+ 0x63, 0x94, 0x8e, 0x3b, 0xc3, 0xa3, 0xd4, 0xdb, 0xed, 0xf6, 0x7e, 0xa2,
+ 0xff, 0xd9, 0x4c, 0x5f, 0x6d, 0x82, 0x36, 0x54, 0x89, 0xfc, 0x48, 0xdd,
+ 0x83, 0xf7, 0xb8, 0x23, 0x85, 0x79, 0x99, 0x35, 0x45, 0xbe, 0x3a, 0xae,
+ 0xb8, 0x4f, 0x05, 0x69, 0x95, 0x77, 0x05, 0x66, 0x8e, 0xc9, 0x0b, 0x46,
+ 0x2e, 0xfd, 0x9a, 0x91, 0x4b, 0xa7, 0xcf, 0x2d, 0x90, 0x4b, 0x05, 0x2d,
+ 0x97, 0x06, 0x05, 0xef, 0xa9, 0x02, 0xe4, 0xd2, 0x08, 0xbe, 0x3d, 0x2d,
+ 0x97, 0x62, 0x62, 0x6d, 0x64, 0x89, 0x5e, 0xc5, 0xfe, 0x27, 0x4b, 0xae,
+ 0xb6, 0xa5, 0x0a, 0xe3, 0xb0, 0x43, 0x4a, 0x23, 0x56, 0x67, 0x4b, 0xba,
+ 0x49, 0x3a, 0x7a, 0x7e, 0x2a, 0xa1, 0x9d, 0x39, 0xdb, 0xcc, 0x3b, 0x8f,
+ 0x5f, 0x54, 0x94, 0x61, 0x27, 0x20, 0xc3, 0x1e, 0xbe, 0x82, 0x0c, 0x43,
+ 0x5e, 0x19, 0x79, 0x65, 0xb6, 0xfb, 0xdd, 0x9f, 0x0e, 0x79, 0x94, 0x1f,
+ 0x94, 0x19, 0x90, 0x49, 0x25, 0xc8, 0xa4, 0x12, 0xe4, 0x54, 0x09, 0x72,
+ 0xa9, 0x04, 0xb9, 0x54, 0x82, 0x5c, 0x2a, 0x41, 0x2e, 0x41, 0xc6, 0x3d,
+ 0x0a, 0x19, 0x67, 0x64, 0xda, 0x00, 0xed, 0x35, 0xb9, 0xcf, 0xea, 0x77,
+ 0x13, 0x27, 0xe9, 0xb2, 0x7e, 0x91, 0xd9, 0xb3, 0x7a, 0xae, 0x2a, 0x2e,
+ 0xb8, 0xeb, 0x88, 0xe6, 0x77, 0xcf, 0x57, 0xd7, 0x3a, 0xdc, 0x1f, 0xf3,
+ 0x03, 0xed, 0xb3, 0x6f, 0xe6, 0x6f, 0xa9, 0x03, 0x5f, 0xbf, 0x62, 0xf9,
+ 0x7a, 0xf3, 0x1c, 0x5f, 0x27, 0x1d, 0xc6, 0x89, 0x97, 0xe7, 0xeb, 0x16,
+ 0x9b, 0x97, 0x0f, 0x56, 0x80, 0xaf, 0x57, 0x2c, 0xe2, 0xeb, 0x28, 0xf8,
+ 0x7a, 0xe7, 0x12, 0xbe, 0x5e, 0xe5, 0xf4, 0xea, 0x3a, 0x3c, 0x83, 0xc6,
+ 0xef, 0x5a, 0x67, 0x9e, 0xaf, 0xf7, 0x6b, 0xbe, 0x3e, 0x04, 0xbe, 0xbe,
+ 0xbe, 0x8a, 0xaf, 0x77, 0x4a, 0xf2, 0x96, 0x6c, 0x64, 0xa3, 0xec, 0xbe,
+ 0x5f, 0x35, 0xaf, 0x91, 0x7f, 0x11, 0x53, 0xdf, 0xf0, 0x58, 0xef, 0x58,
+ 0xb3, 0xe4, 0x1e, 0xfa, 0x11, 0xd7, 0x06, 0xc8, 0x23, 0x43, 0x19, 0xc7,
+ 0x93, 0x83, 0x47, 0x7e, 0x20, 0xd3, 0x9a, 0xb7, 0x44, 0xf6, 0x1c, 0x89,
+ 0xca, 0xf0, 0x11, 0xc6, 0x1e, 0xbe, 0x63, 0xe9, 0xbd, 0x4e, 0x86, 0x07,
+ 0xb9, 0x5f, 0xd2, 0x95, 0xdd, 0x47, 0xe0, 0x63, 0x1d, 0x61, 0xec, 0xe1,
+ 0xf2, 0x1c, 0x8f, 0x4d, 0x43, 0xb6, 0xec, 0x3e, 0xa2, 0xe7, 0x1a, 0xed,
+ 0x34, 0xc8, 0xa1, 0x23, 0x22, 0xb7, 0x1d, 0x71, 0xe5, 0xf6, 0x23, 0x73,
+ 0xbc, 0x36, 0x10, 0xf2, 0xda, 0x9f, 0x83, 0xd7, 0xda, 0x2d, 0xaf, 0xa9,
+ 0x39, 0x5e, 0xfb, 0x5a, 0x15, 0xaf, 0xb1, 0x3e, 0x79, 0xed, 0x82, 0x4d,
+ 0xe3, 0xb7, 0x2b, 0x7b, 0x8f, 0xb4, 0xca, 0xee, 0x87, 0xde, 0x22, 0x7b,
+ 0xee, 0x27, 0xac, 0xe6, 0x9e, 0x3c, 0xda, 0x5f, 0xe3, 0x95, 0x76, 0xb4,
+ 0x1f, 0xee, 0x0f, 0xd2, 0x77, 0x65, 0x75, 0x4e, 0x48, 0x32, 0xcf, 0xfe,
+ 0x6a, 0xe1, 0x3b, 0x9f, 0x82, 0x4f, 0xb1, 0x17, 0x30, 0xdd, 0x7a, 0x44,
+ 0x92, 0xae, 0xbc, 0x26, 0x23, 0xa9, 0x47, 0x5b, 0x8d, 0x3d, 0x71, 0x09,
+ 0xbc, 0x42, 0xfa, 0xcf, 0x48, 0xee, 0xed, 0x81, 0xf6, 0x2b, 0x46, 0xcb,
+ 0x42, 0xff, 0x9f, 0x31, 0x73, 0xc7, 0xdc, 0x77, 0xc7, 0xf3, 0xbe, 0x35,
+ 0xfa, 0xbc, 0x9b, 0x8e, 0xd7, 0x76, 0x33, 0xbf, 0x46, 0xef, 0x37, 0xcd,
+ 0xe9, 0xb3, 0xdc, 0xac, 0xcf, 0x76, 0x62, 0x3a, 0x9e, 0x5e, 0x28, 0xf3,
+ 0x8e, 0x30, 0xde, 0xbd, 0xcc, 0xbb, 0x06, 0xff, 0xf8, 0x2a, 0x13, 0x9b,
+ 0x25, 0xdf, 0x7d, 0xdd, 0xc9, 0x15, 0x2f, 0xe9, 0x7d, 0x85, 0x59, 0x1f,
+ 0xbf, 0xcb, 0xfc, 0x66, 0xf9, 0x4b, 0x8c, 0x71, 0x24, 0x12, 0xea, 0x81,
+ 0x56, 0xee, 0x3b, 0x18, 0x9c, 0x32, 0x76, 0x94, 0xe1, 0xd1, 0x06, 0xed,
+ 0x6b, 0x8c, 0xe0, 0x7b, 0xf7, 0x68, 0xa3, 0x53, 0xa0, 0x6d, 0x32, 0xd0,
+ 0xe0, 0xe4, 0xc7, 0xf7, 0xb4, 0x1a, 0x9b, 0x79, 0x20, 0xce, 0x3d, 0x85,
+ 0x19, 0xb5, 0x54, 0x26, 0x9f, 0x92, 0x50, 0x26, 0x27, 0x6f, 0xc9, 0xc0,
+ 0xb6, 0xce, 0x1d, 0xd1, 0xf7, 0xf7, 0x25, 0xda, 0x15, 0xc7, 0xf4, 0x09,
+ 0xc8, 0xd7, 0x90, 0x16, 0xe2, 0xf2, 0xf1, 0x23, 0xa4, 0x07, 0x15, 0x6b,
+ 0x94, 0xdf, 0xb2, 0xf4, 0x70, 0x59, 0x8a, 0x90, 0x3b, 0x47, 0x8e, 0xdc,
+ 0x2e, 0xe3, 0xbb, 0x16, 0xd3, 0xc3, 0x9e, 0x79, 0x7a, 0x88, 0xc1, 0x3e,
+ 0x73, 0xaa, 0xe9, 0xe1, 0x37, 0xe7, 0xe8, 0x61, 0xdc, 0xf9, 0xd7, 0xd2,
+ 0xc3, 0x0d, 0x0b, 0xe8, 0x61, 0x44, 0xd3, 0x43, 0xff, 0x1c, 0x3d, 0x8c,
+ 0x1c, 0x61, 0xbf, 0x7a, 0x5d, 0xd4, 0x9b, 0x71, 0x38, 0xe7, 0x73, 0xb4,
+ 0x90, 0x18, 0xd6, 0xfb, 0x44, 0x93, 0x79, 0x9e, 0x25, 0x5d, 0xa5, 0x18,
+ 0x1b, 0x99, 0x9f, 0xff, 0xc6, 0x7f, 0xd3, 0xf9, 0x7f, 0x47, 0xfc, 0xff,
+ 0xef, 0xfc, 0x5f, 0x8f, 0xf6, 0x29, 0x8b, 0x43, 0x79, 0x1c, 0xd2, 0xc3,
+ 0x7b, 0xe2, 0x46, 0x2f, 0x70, 0x8e, 0xf9, 0x6d, 0xf6, 0xac, 0x9f, 0x83,
+ 0xfc, 0x7b, 0x1c, 0xf2, 0xef, 0xb1, 0x05, 0xeb, 0x01, 0x3d, 0x36, 0x06,
+ 0x11, 0xc8, 0xc1, 0xd4, 0x3c, 0x3e, 0x66, 0xba, 0x89, 0x0f, 0xb3, 0xf7,
+ 0xe4, 0x6c, 0x65, 0x31, 0x4e, 0x5c, 0xbd, 0xdf, 0xe8, 0x64, 0xaa, 0x1a,
+ 0x27, 0x84, 0x7b, 0xb6, 0x6a, 0x8c, 0xf8, 0x5d, 0xe6, 0xf7, 0x65, 0xbd,
+ 0x87, 0xa4, 0xa0, 0xd7, 0x9f, 0x88, 0x17, 0xae, 0x3f, 0x11, 0x27, 0xae,
+ 0xb6, 0xf7, 0x0b, 0xe5, 0x3a, 0xbd, 0x2f, 0xfc, 0xc0, 0x54, 0x4c, 0x66,
+ 0x62, 0x8c, 0xeb, 0xf1, 0xde, 0x57, 0xfa, 0xca, 0x7e, 0xbc, 0x20, 0x79,
+ 0x7b, 0xd6, 0x67, 0x95, 0xa5, 0x6d, 0xc6, 0x03, 0x79, 0x27, 0x42, 0xb8,
+ 0x0e, 0xd1, 0x69, 0x65, 0x5d, 0x43, 0x55, 0x9c, 0x12, 0x78, 0x1f, 0x93,
+ 0x44, 0xb6, 0x1b, 0xef, 0x29, 0xf6, 0xfd, 0xa4, 0x8c, 0x3c, 0x58, 0x86,
+ 0x2d, 0xf7, 0x30, 0x74, 0x8e, 0x23, 0x10, 0x93, 0xfa, 0x2e, 0x14, 0xc2,
+ 0x30, 0xa1, 0xef, 0xf5, 0xa3, 0xdf, 0x47, 0x7a, 0x88, 0xe3, 0xfb, 0xb2,
+ 0x8d, 0x25, 0xc5, 0xa5, 0x50, 0xfc, 0x01, 0xe0, 0xe7, 0x1d, 0x94, 0x3f,
+ 0xc2, 0xfb, 0x8d, 0xe6, 0xc3, 0xf8, 0x21, 0x03, 0xfa, 0xcd, 0xb9, 0x79,
+ 0xcd, 0xc9, 0x94, 0xcd, 0xfe, 0x96, 0xaa, 0xfb, 0xf5, 0xe5, 0xb0, 0xb6,
+ 0x9f, 0xd3, 0x76, 0x5f, 0x0b, 0xcf, 0xe7, 0x19, 0x1b, 0xfa, 0xcb, 0xb0,
+ 0xa1, 0x9f, 0xa8, 0x64, 0xf4, 0x1a, 0xd6, 0x63, 0xb0, 0xa1, 0x1f, 0x85,
+ 0xee, 0xa1, 0xce, 0x89, 0x59, 0x9d, 0x33, 0xa2, 0x76, 0x69, 0x9d, 0xf3,
+ 0xd7, 0x5a, 0xe7, 0xfc, 0xea, 0x12, 0x9d, 0x73, 0x48, 0xb5, 0x8f, 0x52,
+ 0xe7, 0xf4, 0xaa, 0x9d, 0x0e, 0xed, 0xc5, 0xb5, 0xcb, 0xe8, 0x9c, 0xf7,
+ 0xca, 0xaf, 0xd8, 0xbc, 0xfd, 0xf2, 0xbe, 0x6d, 0x7a, 0xdd, 0xc6, 0x9b,
+ 0x50, 0xbc, 0xcb, 0xce, 0xe8, 0xa0, 0xeb, 0x55, 0xa7, 0x5e, 0xef, 0xfd,
+ 0x6a, 0x95, 0xce, 0x69, 0x53, 0xdd, 0x4e, 0xaf, 0xae, 0xc3, 0x78, 0x04,
+ 0xbf, 0x53, 0x4e, 0x66, 0xa0, 0x0e, 0xdf, 0x71, 0x89, 0x1c, 0xc1, 0xd8,
+ 0xcd, 0x7d, 0x7b, 0xca, 0xe4, 0x5d, 0x63, 0xf3, 0x54, 0x98, 0xee, 0x9a,
+ 0xf4, 0x76, 0x9b, 0x6e, 0x74, 0x55, 0x9b, 0x6a, 0xd5, 0xba, 0x6a, 0x33,
+ 0x18, 0x6a, 0x02, 0xfa, 0x75, 0xa2, 0x14, 0xea, 0x2c, 0xfe, 0x66, 0xbc,
+ 0x99, 0x71, 0x89, 0x30, 0x6e, 0x9d, 0x40, 0x19, 0x3c, 0xa5, 0xd0, 0xa6,
+ 0xe4, 0x6f, 0xf8, 0x0a, 0x78, 0xa6, 0x80, 0xd7, 0x5b, 0xc0, 0x3f, 0xbf,
+ 0x5e, 0x64, 0xdc, 0xb3, 0x59, 0x8e, 0x8e, 0x55, 0xe7, 0xb5, 0xca, 0xbb,
+ 0xc7, 0x36, 0xc8, 0xbe, 0x51, 0xff, 0x6a, 0xa9, 0xdf, 0x28, 0x23, 0xa3,
+ 0x2f, 0xea, 0xfb, 0x40, 0xd6, 0xe8, 0x7b, 0x92, 0x78, 0x7f, 0x98, 0x91,
+ 0x91, 0xfd, 0x8e, 0x91, 0x91, 0x19, 0x35, 0x6f, 0xb3, 0x86, 0x6d, 0xf2,
+ 0x6e, 0xa6, 0xbe, 0xd1, 0xb8, 0xbe, 0x43, 0x7a, 0xa2, 0x72, 0xad, 0xfc,
+ 0xd1, 0x71, 0x75, 0xa7, 0x9a, 0xbf, 0x4b, 0x41, 0xdb, 0xac, 0x93, 0x0b,
+ 0x6c, 0xd6, 0xbf, 0x97, 0x99, 0xf7, 0x45, 0x31, 0x4e, 0xd0, 0xf0, 0x75,
+ 0x2f, 0x73, 0x1d, 0xb4, 0x39, 0x26, 0x97, 0xa4, 0x4f, 0xe3, 0x8f, 0xf2,
+ 0xb4, 0x01, 0x72, 0x70, 0x56, 0xeb, 0xd7, 0xb5, 0xbc, 0xf3, 0xf8, 0x08,
+ 0x6d, 0xd7, 0xaf, 0x6b, 0x79, 0xb6, 0xd6, 0xda, 0xae, 0xd3, 0x90, 0xd3,
+ 0x94, 0xa3, 0x37, 0xca, 0x5f, 0xdb, 0x74, 0xa6, 0x25, 0xe3, 0xb3, 0x42,
+ 0x7d, 0x17, 0x83, 0x0c, 0xa5, 0x3c, 0xfd, 0x59, 0x6d, 0xd7, 0xe7, 0x6c,
+ 0x1b, 0x94, 0x9f, 0x46, 0x76, 0x6f, 0x76, 0xa6, 0x6d, 0x1a, 0xbf, 0xc3,
+ 0x18, 0xba, 0x9f, 0xc9, 0x59, 0x3e, 0x53, 0xce, 0x93, 0xc8, 0x5f, 0x83,
+ 0x7c, 0xf2, 0xd9, 0x63, 0x9a, 0xcf, 0xb4, 0x7d, 0xe2, 0x74, 0xd9, 0x35,
+ 0x85, 0xb9, 0xf5, 0x80, 0x3c, 0xf9, 0x4c, 0x1d, 0xf5, 0xa6, 0x8d, 0x3c,
+ 0xf0, 0x90, 0xfe, 0x45, 0xe8, 0x0e, 0xd6, 0x45, 0xfa, 0xb1, 0x0c, 0xe6,
+ 0xf0, 0x24, 0xfc, 0x9f, 0x46, 0x7c, 0x37, 0xe3, 0x7b, 0x42, 0x7e, 0x75,
+ 0x30, 0xaa, 0xc7, 0x3d, 0x82, 0x71, 0x1c, 0x38, 0x82, 0x31, 0x39, 0xc6,
+ 0x76, 0x76, 0xcf, 0xb8, 0x52, 0x73, 0x86, 0x7c, 0xc7, 0x33, 0x86, 0x41,
+ 0xb0, 0xb7, 0x8b, 0x74, 0x9b, 0xf4, 0xfa, 0xf5, 0xf9, 0xb7, 0xcd, 0xf1,
+ 0x08, 0x70, 0x72, 0x00, 0xf3, 0x31, 0x52, 0xf4, 0xbd, 0xac, 0xe3, 0xc7,
+ 0x31, 0x4e, 0xd8, 0x80, 0xed, 0xb0, 0x05, 0xdb, 0x61, 0x07, 0xb6, 0xc3,
+ 0x0e, 0x5c, 0x2d, 0xa7, 0xb6, 0x72, 0x7f, 0x49, 0xfe, 0x9d, 0xbc, 0x77,
+ 0xf9, 0x1b, 0x3a, 0x36, 0x5f, 0x7b, 0x4b, 0x1f, 0x7c, 0x76, 0xf1, 0x92,
+ 0x03, 0xdc, 0x63, 0x3f, 0xeb, 0xd5, 0xde, 0xd2, 0x2f, 0xed, 0x3d, 0xc8,
+ 0xef, 0xb9, 0x24, 0x1d, 0xb7, 0x7c, 0xd8, 0xa9, 0x1d, 0xe8, 0x03, 0x1e,
+ 0x33, 0x4e, 0x32, 0x3e, 0xe4, 0x30, 0x4e, 0x91, 0xdd, 0x1c, 0xd1, 0x67,
+ 0xc4, 0xa6, 0x19, 0x8b, 0xb8, 0xa5, 0x3d, 0xb2, 0x25, 0xb1, 0xdb, 0x49,
+ 0x0e, 0xa8, 0x48, 0x72, 0xa0, 0xcf, 0x09, 0xcb, 0xf1, 0x0e, 0x6a, 0xc8,
+ 0x19, 0xc0, 0x7a, 0xa0, 0xf4, 0x75, 0xd0, 0xd3, 0x79, 0x29, 0x1c, 0x6f,
+ 0x90, 0xa9, 0x62, 0xbb, 0x97, 0x55, 0x31, 0xe1, 0xbe, 0x12, 0x75, 0x0a,
+ 0x44, 0x7f, 0x26, 0x2a, 0x13, 0xa3, 0x1b, 0x45, 0x69, 0xdb, 0xbd, 0x45,
+ 0xb2, 0x63, 0xa3, 0x72, 0xbe, 0x5b, 0x9a, 0x14, 0xda, 0xe7, 0xdd, 0xde,
+ 0xea, 0x14, 0xd7, 0x11, 0x43, 0x5e, 0x58, 0x4f, 0x3e, 0x19, 0x05, 0x0e,
+ 0x41, 0xb7, 0x8c, 0xeb, 0xd6, 0x09, 0xe5, 0xde, 0xed, 0x3a, 0x66, 0xca,
+ 0x38, 0x6d, 0xf5, 0x7a, 0x03, 0xf9, 0x23, 0xba, 0x2c, 0x7f, 0x4c, 0x96,
+ 0xb8, 0x36, 0x23, 0x79, 0x97, 0x71, 0x61, 0x1f, 0xbf, 0xc7, 0x59, 0xb6,
+ 0x4e, 0x46, 0xba, 0xf3, 0x76, 0x8f, 0xc7, 0x37, 0xc1, 0x07, 0x1c, 0x9f,
+ 0x5e, 0x27, 0x01, 0xaf, 0x2f, 0x5e, 0xcf, 0x88, 0x56, 0xc9, 0x03, 0x47,
+ 0x66, 0x46, 0xc3, 0xf5, 0x0f, 0xb6, 0x87, 0xef, 0x71, 0x23, 0x6f, 0xb3,
+ 0x4b, 0xea, 0x11, 0x2e, 0xae, 0x55, 0x2e, 0x94, 0xb1, 0x4a, 0x9f, 0x13,
+ 0xf6, 0xb4, 0x7c, 0x3d, 0x5d, 0x31, 0xb2, 0x75, 0xbc, 0x12, 0xea, 0x96,
+ 0xa8, 0xd1, 0xa5, 0x4b, 0xf4, 0x89, 0x89, 0x60, 0xce, 0xeb, 0x93, 0x4b,
+ 0x3a, 0x46, 0xf7, 0x6b, 0x53, 0x2d, 0xe2, 0x1e, 0x93, 0xd9, 0x11, 0xff,
+ 0x54, 0x2b, 0xf7, 0x69, 0x8c, 0xa4, 0xde, 0x8c, 0x7e, 0x8c, 0xb5, 0x50,
+ 0x1f, 0x0e, 0xa9, 0xb5, 0x78, 0xaf, 0xd1, 0xf4, 0x07, 0x9e, 0xc2, 0xb7,
+ 0xf1, 0x13, 0xbe, 0x0c, 0x3f, 0xe1, 0x09, 0xe8, 0xba, 0x73, 0xf0, 0x13,
+ 0x1e, 0x87, 0x9f, 0xf0, 0x18, 0xfc, 0x84, 0x47, 0xa1, 0x27, 0xab, 0xfd,
+ 0x83, 0xe1, 0x05, 0xfe, 0x41, 0xa0, 0xf9, 0x9f, 0x31, 0xc0, 0xc7, 0xab,
+ 0x7c, 0x83, 0xbd, 0x46, 0x5f, 0xc1, 0xef, 0x37, 0x7c, 0xd4, 0xa6, 0x6e,
+ 0xd6, 0xfa, 0xd1, 0xec, 0xd9, 0x1d, 0x98, 0xd3, 0x57, 0x6d, 0xca, 0xe8,
+ 0xab, 0x89, 0x79, 0x7d, 0x65, 0xf8, 0xe8, 0xd8, 0xa8, 0x44, 0xfc, 0xd1,
+ 0xe9, 0x6c, 0x6a, 0xbb, 0xe6, 0xa1, 0x26, 0x7f, 0xa3, 0x44, 0x1e, 0x50,
+ 0xcd, 0x35, 0x92, 0xb5, 0xdf, 0xa0, 0xaf, 0xa3, 0x5f, 0x47, 0x5b, 0xef,
+ 0x94, 0x9c, 0xb6, 0xcf, 0xae, 0x8c, 0xef, 0x47, 0x17, 0xe1, 0xbb, 0x50,
+ 0x7a, 0x56, 0xe3, 0xfc, 0x7e, 0x7d, 0x26, 0xbf, 0x41, 0x86, 0xcb, 0x21,
+ 0xce, 0x79, 0x06, 0x8e, 0xfb, 0x30, 0x5a, 0x25, 0x72, 0xac, 0x45, 0xfa,
+ 0x53, 0xa2, 0x72, 0xa9, 0x95, 0x7a, 0xff, 0xca, 0xa9, 0x6e, 0x89, 0xe7,
+ 0xba, 0x49, 0xab, 0xf7, 0xc9, 0x84, 0x9e, 0x8b, 0x16, 0xa9, 0x39, 0x46,
+ 0x1b, 0x25, 0x5c, 0xc3, 0xbb, 0xbd, 0xc5, 0xde, 0x41, 0x1d, 0x35, 0xe5,
+ 0x44, 0x0e, 0xea, 0xf9, 0x9a, 0xd5, 0x7b, 0x0c, 0x6f, 0x9e, 0x62, 0x2c,
+ 0x9e, 0xf7, 0xfd, 0x31, 0x0e, 0xff, 0xaf, 0x99, 0xbf, 0x42, 0x8b, 0xb1,
+ 0x67, 0xd6, 0x58, 0x3b, 0xc6, 0xc4, 0xa9, 0x96, 0xb7, 0x61, 0xd8, 0x4e,
+ 0xf5, 0x1d, 0xb5, 0xab, 0xe0, 0x03, 0x37, 0xa0, 0x4d, 0xae, 0x63, 0xdb,
+ 0xbf, 0x17, 0xe4, 0xfd, 0xb3, 0x73, 0xc0, 0x5f, 0x85, 0xb4, 0x06, 0xe4,
+ 0x31, 0x66, 0xf3, 0x85, 0x16, 0xc6, 0x65, 0xb3, 0x7e, 0xa3, 0x4d, 0x5b,
+ 0xe5, 0x8c, 0x8c, 0xb6, 0xc3, 0x37, 0xe7, 0x39, 0x76, 0xe6, 0xf7, 0x73,
+ 0xee, 0x84, 0x7f, 0xab, 0x69, 0x12, 0xf2, 0x67, 0x8f, 0x5c, 0x6b, 0xe3,
+ 0xce, 0xd4, 0xc3, 0xbf, 0xb8, 0x60, 0xbd, 0xf6, 0x10, 0xf4, 0xd8, 0xad,
+ 0x90, 0x47, 0xd4, 0xc3, 0x87, 0xe4, 0x17, 0x2c, 0x3d, 0x2f, 0xd4, 0xc3,
+ 0x17, 0x85, 0xb1, 0xe1, 0x2e, 0xe4, 0xe5, 0x83, 0x28, 0xe8, 0xe1, 0x70,
+ 0x95, 0xaf, 0x46, 0xbf, 0xaf, 0x2e, 0x6d, 0xd6, 0xc0, 0x16, 0xfa, 0x7d,
+ 0x90, 0x03, 0xb1, 0xd0, 0xcf, 0xab, 0x9d, 0x5b, 0xa3, 0xdd, 0x69, 0xeb,
+ 0x8e, 0xa4, 0x5e, 0x22, 0x8e, 0x12, 0x87, 0xe4, 0xf6, 0xf5, 0xbc, 0x26,
+ 0xcf, 0xf5, 0xbf, 0xa5, 0x71, 0x26, 0x8a, 0xb4, 0xb7, 0x46, 0xc3, 0x68,
+ 0xe5, 0x7c, 0x22, 0xdc, 0xbf, 0x51, 0xb0, 0x75, 0xf7, 0xd8, 0xf5, 0xf8,
+ 0x82, 0x7c, 0x9b, 0x71, 0xce, 0x44, 0x5f, 0x64, 0x25, 0xcf, 0x64, 0xa3,
+ 0xee, 0xed, 0xda, 0x6f, 0xcf, 0x48, 0xd8, 0x16, 0xbf, 0x6b, 0xaa, 0xda,
+ 0xa6, 0x1d, 0xc5, 0xf7, 0xe2, 0xfb, 0x1b, 0x9e, 0xd7, 0x6b, 0x8b, 0xe6,
+ 0x6e, 0x9a, 0x90, 0x4f, 0xc8, 0x3b, 0x09, 0x7d, 0x8e, 0xc9, 0x3f, 0x46,
+ 0xbb, 0x87, 0xeb, 0xae, 0xde, 0xf4, 0x70, 0xea, 0x23, 0xfa, 0x0e, 0xd5,
+ 0x71, 0x11, 0xa7, 0x90, 0xda, 0xab, 0xf7, 0x9d, 0x14, 0x74, 0x7c, 0x39,
+ 0x8f, 0xf7, 0xbc, 0x8f, 0xda, 0x76, 0x8c, 0x7f, 0x0b, 0x88, 0x69, 0x1f,
+ 0x04, 0x6c, 0xd4, 0x21, 0x94, 0xbd, 0x31, 0x69, 0x3b, 0xfa, 0x7e, 0xcd,
+ 0x0b, 0x6b, 0xe1, 0x0b, 0xf4, 0x1e, 0x85, 0xae, 0x3e, 0x1a, 0x97, 0xfe,
+ 0xa3, 0x5a, 0x37, 0x66, 0x96, 0xc6, 0x0a, 0xb6, 0x78, 0x2e, 0xfd, 0x89,
+ 0x98, 0x27, 0xd7, 0x1c, 0x8d, 0xc8, 0xe1, 0xd8, 0x16, 0xaf, 0xc3, 0xb9,
+ 0xd1, 0xea, 0x42, 0x43, 0x7f, 0xa0, 0x15, 0xd4, 0x37, 0xeb, 0x90, 0xbd,
+ 0xf3, 0xb1, 0x6b, 0xd4, 0x7f, 0x49, 0x46, 0xc8, 0x4b, 0x95, 0x88, 0x8c,
+ 0x0f, 0xb6, 0x02, 0x9e, 0xb7, 0xae, 0x07, 0x0e, 0x40, 0x53, 0x98, 0x1f,
+ 0xfd, 0xf7, 0x3c, 0xdc, 0x38, 0xe5, 0x57, 0x1b, 0xfa, 0xef, 0x3b, 0x4a,
+ 0x1d, 0xe6, 0x6b, 0xbe, 0x46, 0xbf, 0x5e, 0x8d, 0xf6, 0x3d, 0xc8, 0x8b,
+ 0x6f, 0x11, 0xff, 0x01, 0xc8, 0xb5, 0xa3, 0x51, 0xe9, 0x38, 0xda, 0x20,
+ 0x9b, 0x8e, 0xd2, 0xf7, 0xa8, 0xf6, 0x45, 0x69, 0x8b, 0x5e, 0xc2, 0xb8,
+ 0x6e, 0x34, 0xf7, 0x0d, 0x4e, 0x45, 0x65, 0x1f, 0xf9, 0x15, 0x65, 0x73,
+ 0xb0, 0x93, 0xb3, 0x47, 0x3d, 0xbd, 0x16, 0x9a, 0xc5, 0x38, 0xf9, 0x37,
+ 0x2c, 0xfa, 0x8e, 0x1a, 0x39, 0x53, 0xa0, 0x6f, 0x32, 0xd0, 0x02, 0xbc,
+ 0x3e, 0x60, 0xf9, 0xe5, 0x3d, 0xeb, 0x2d, 0x5f, 0xfe, 0x9c, 0xfc, 0x96,
+ 0x5b, 0x6f, 0xe4, 0xe5, 0x87, 0xd6, 0x73, 0x2f, 0xd2, 0x5a, 0x9f, 0xef,
+ 0x3a, 0x6d, 0x43, 0x18, 0xb9, 0xf9, 0x7a, 0xfc, 0x27, 0xc0, 0x51, 0xb8,
+ 0xfe, 0x44, 0x3e, 0xe4, 0x1a, 0xb2, 0x3e, 0xb3, 0x92, 0x9a, 0xd1, 0x7f,
+ 0x53, 0x89, 0x6b, 0x61, 0xf3, 0xf7, 0x59, 0x6d, 0xaf, 0x30, 0x36, 0xfe,
+ 0x4c, 0xf8, 0x37, 0x9c, 0xaa, 0xf6, 0x19, 0x56, 0xaf, 0x75, 0x31, 0xbe,
+ 0x34, 0xb7, 0x17, 0x28, 0x18, 0xd5, 0x77, 0xc2, 0xc5, 0x9c, 0x8b, 0xc5,
+ 0x5a, 0xe7, 0x9b, 0x63, 0x12, 0xb8, 0x7e, 0xdc, 0xf9, 0x96, 0xcf, 0xb5,
+ 0x71, 0xcf, 0x79, 0xb9, 0xe8, 0x83, 0xf7, 0xfe, 0x02, 0xe3, 0x68, 0x75,
+ 0x5e, 0xc1, 0x9c, 0x1e, 0x2c, 0x65, 0x92, 0x9e, 0x8d, 0x83, 0x3f, 0x5b,
+ 0x6c, 0x75, 0x9e, 0x9b, 0x8f, 0x21, 0xf5, 0x84, 0x74, 0x71, 0x88, 0x79,
+ 0x65, 0xe4, 0x95, 0x19, 0xeb, 0xad, 0x77, 0x26, 0xc7, 0xec, 0x7e, 0x12,
+ 0xa3, 0x8b, 0xe6, 0xd6, 0x5f, 0x06, 0xf4, 0xfa, 0x84, 0xeb, 0x4c, 0x4e,
+ 0x4d, 0xaf, 0x37, 0xfb, 0x8a, 0x6a, 0x91, 0x67, 0xf6, 0x58, 0x4e, 0x4c,
+ 0xd5, 0xa2, 0x4c, 0xbd, 0x33, 0xa1, 0x63, 0x5e, 0xda, 0xf6, 0x70, 0xc6,
+ 0xa7, 0xea, 0x9d, 0x29, 0xbd, 0xd6, 0x1c, 0x75, 0x4e, 0x8e, 0xb1, 0xed,
+ 0x28, 0xca, 0x88, 0x73, 0x0a, 0xed, 0x4d, 0x8d, 0xb5, 0xc7, 0xf7, 0x49,
+ 0x3b, 0x6c, 0x01, 0xfe, 0x8d, 0x34, 0xde, 0x17, 0xe0, 0x3a, 0x53, 0x73,
+ 0xed, 0x2a, 0xb4, 0xc3, 0xb2, 0xa4, 0x41, 0xf6, 0xeb, 0xa2, 0xfd, 0xa5,
+ 0x6b, 0x52, 0x4b, 0x71, 0x32, 0x06, 0x9c, 0x1c, 0xb4, 0x38, 0x39, 0x61,
+ 0x71, 0x32, 0x5a, 0x85, 0x93, 0x87, 0x17, 0xe1, 0xe4, 0x04, 0x70, 0xf2,
+ 0xf0, 0x15, 0x70, 0x82, 0xbc, 0xf2, 0xc3, 0x16, 0x27, 0xf7, 0x2d, 0xc2,
+ 0x49, 0x7e, 0x2e, 0x16, 0x6f, 0x70, 0x32, 0x02, 0x9c, 0xd4, 0xb4, 0x1a,
+ 0xd8, 0x0f, 0x5a, 0x9c, 0xe0, 0x3d, 0x75, 0x10, 0x65, 0xee, 0xab, 0xc2,
+ 0xc9, 0x41, 0xe0, 0xe4, 0x3e, 0x8b, 0x93, 0xc3, 0x16, 0x27, 0x87, 0x51,
+ 0x26, 0x0f, 0x9c, 0x14, 0x96, 0xc1, 0xc9, 0x08, 0x70, 0x12, 0xb6, 0x5b,
+ 0x40, 0x3b, 0x87, 0xab, 0x70, 0x32, 0xb2, 0x0c, 0x4e, 0xb8, 0xe6, 0x1a,
+ 0xee, 0xe1, 0xbe, 0xfc, 0x06, 0x7b, 0xb8, 0x53, 0x9f, 0x7d, 0xe3, 0x3d,
+ 0xdc, 0x2c, 0x73, 0xb9, 0xea, 0xcc, 0xfb, 0xb3, 0x76, 0x4f, 0x9a, 0xd9,
+ 0xfb, 0x37, 0x7f, 0x0f, 0x5e, 0x3b, 0xf8, 0xbc, 0x90, 0xf7, 0xc4, 0xec,
+ 0x21, 0x75, 0xb7, 0x4d, 0x81, 0xd7, 0x8e, 0xca, 0x81, 0xe3, 0xb5, 0x87,
+ 0x73, 0x36, 0xcd, 0xdf, 0xd6, 0x9e, 0x57, 0x8a, 0x79, 0xe1, 0xde, 0x83,
+ 0x17, 0xcd, 0x5d, 0x50, 0x31, 0x9e, 0xc7, 0xa8, 0x5e, 0x7b, 0x7e, 0xd1,
+ 0xde, 0x55, 0xe4, 0xdd, 0x9b, 0xf5, 0xa7, 0x13, 0xdc, 0x57, 0x55, 0xd0,
+ 0xf0, 0x72, 0x2d, 0xad, 0x47, 0xef, 0xa5, 0xca, 0x16, 0x69, 0x67, 0x27,
+ 0xb8, 0x27, 0x0d, 0xf6, 0x31, 0xf7, 0xed, 0x9a, 0x7d, 0xba, 0xbd, 0x0b,
+ 0xf6, 0xe9, 0x56, 0x9f, 0xef, 0x26, 0xdf, 0xcd, 0xd3, 0xcd, 0xc1, 0xb9,
+ 0xbb, 0x57, 0x8f, 0x3b, 0xcf, 0xe8, 0xf8, 0x70, 0x3d, 0xe6, 0x27, 0x08,
+ 0x4e, 0xa7, 0x4c, 0x5c, 0x76, 0x46, 0xc7, 0x65, 0x05, 0x1e, 0xf8, 0xb0,
+ 0x8d, 0xcd, 0x76, 0xf4, 0x5c, 0x9e, 0x8b, 0xcb, 0x2e, 0xd8, 0xa3, 0xa3,
+ 0xef, 0xff, 0xc8, 0x8e, 0x5e, 0xd2, 0x7b, 0x71, 0xfa, 0x52, 0x8e, 0x14,
+ 0x20, 0x23, 0xf6, 0x8c, 0xbf, 0x2a, 0xc3, 0x0f, 0xf2, 0x9b, 0x3a, 0x2d,
+ 0x02, 0xbd, 0x45, 0xb9, 0x9d, 0x97, 0x6c, 0x0f, 0xd3, 0x4c, 0x9d, 0x3e,
+ 0xed, 0x23, 0x1f, 0x77, 0x7a, 0xe7, 0xfa, 0x27, 0x7e, 0xc3, 0x35, 0x70,
+ 0xfe, 0xa6, 0x9d, 0x93, 0x71, 0xb2, 0x15, 0xe6, 0x87, 0x6b, 0xe1, 0x77,
+ 0xdb, 0xfb, 0x08, 0x99, 0x5f, 0x7d, 0xff, 0xb5, 0xe1, 0xd3, 0xac, 0xfe,
+ 0x3b, 0x22, 0x23, 0x4e, 0x1f, 0xea, 0x4c, 0x7b, 0x0d, 0x03, 0x2a, 0x7d,
+ 0xd3, 0x00, 0xcf, 0xca, 0x4d, 0x2c, 0xf9, 0xfb, 0x01, 0xf3, 0xba, 0xb0,
+ 0xa0, 0xe7, 0x94, 0xfb, 0xb0, 0xa6, 0x41, 0x8b, 0x9a, 0xb6, 0x34, 0xfd,
+ 0x1f, 0x98, 0xd3, 0x91, 0xd4, 0xad, 0xd4, 0x93, 0xa1, 0x8e, 0x4c, 0xc6,
+ 0xfb, 0x78, 0x7f, 0x84, 0xa6, 0x71, 0x7b, 0x97, 0xc4, 0xd4, 0x39, 0xad,
+ 0xdf, 0x47, 0x52, 0xbc, 0x5f, 0x66, 0x99, 0xb2, 0xa3, 0x55, 0x65, 0xf5,
+ 0xb8, 0x3d, 0xf9, 0x43, 0xcc, 0xcd, 0x17, 0x61, 0x6f, 0xf6, 0x8e, 0xbd,
+ 0x0a, 0x9f, 0x31, 0x2e, 0x5f, 0x2a, 0xbd, 0x04, 0x7a, 0xcd, 0xaf, 0xb5,
+ 0x77, 0xe1, 0x65, 0x01, 0x37, 0xcf, 0x38, 0xeb, 0xfd, 0xc3, 0x91, 0x3f,
+ 0x02, 0x5d, 0xfc, 0xc1, 0x4b, 0xec, 0x03, 0xb0, 0x44, 0x60, 0xcf, 0xc3,
+ 0x36, 0x18, 0x7f, 0x49, 0xef, 0x95, 0xbb, 0xbe, 0xfc, 0x92, 0x8e, 0x53,
+ 0xf4, 0x97, 0x5b, 0x65, 0x7b, 0xb9, 0x41, 0x76, 0x40, 0x2f, 0xec, 0x28,
+ 0xfb, 0x78, 0xa2, 0x72, 0x63, 0xd9, 0xcc, 0xd3, 0x47, 0xca, 0x9c, 0xef,
+ 0x6d, 0x32, 0x71, 0xbc, 0x9a, 0x66, 0xa7, 0xed, 0xde, 0x31, 0xd2, 0x0f,
+ 0x9e, 0x52, 0x32, 0x3f, 0xad, 0xc7, 0xce, 0x5d, 0xac, 0xc9, 0xc3, 0xb3,
+ 0xc2, 0xbd, 0xf8, 0xfc, 0x1b, 0x74, 0xdf, 0x68, 0xe5, 0x19, 0x77, 0xde,
+ 0x8f, 0xd8, 0x5f, 0x09, 0xf7, 0x86, 0xbf, 0xfe, 0x19, 0x10, 0xfd, 0x77,
+ 0x5d, 0xf4, 0xde, 0x70, 0x4d, 0x7b, 0xd2, 0x76, 0x26, 0xa6, 0x75, 0x84,
+ 0xa1, 0xf1, 0xf9, 0xbf, 0xe7, 0x22, 0xf2, 0x7f, 0x01, 0x95, 0xf6, 0x2d,
+ 0x58, 0xd0, 0x73, 0x00, 0x00, 0x00 };
+static u32 bnx2_CP_b09FwData[(0x50/4) + 1] = {
+ 0x00010030, 0x00000030, 0x00000000, 0x00000001, 0x00010fd0, 0x00000fd0,
+ 0x00001430, 0x0000007f, 0x00030400, 0x00001000, 0x00000030, 0x00000020,
+ 0x00050200, 0x00001000, 0x00000030, 0x00000010, 0x00010400, 0x00000400,
+ 0x00001030, 0x00000020, 0x00000000 };
+static u32 bnx2_CP_b09FwRodata[(0x118/4) + 1] = {
+ 0x080005d8, 0x080007f8, 0x0800073c, 0x08000764, 0x0800078c, 0x080007b4,
+ 0x08000610, 0x080005fc, 0x08000820, 0x08000820, 0x0800062c, 0x08000648,
+ 0x08000648, 0x08000820, 0x08000660, 0x08000674, 0x08000820, 0x08000688,
+ 0x08000820, 0x08000820, 0x0800069c, 0x08000820, 0x08000820, 0x08000820,
+ 0x08000820, 0x08000820, 0x08000820, 0x08000820, 0x08000820, 0x08000820,
+ 0x08000820, 0x080006b0, 0x08000820, 0x080006c4, 0x080006d8, 0x080006ec,
+ 0x08000820, 0x08000700, 0x08000714, 0x08000728, 0x08003740, 0x08003758,
+ 0x08003768, 0x08003778, 0x08003790, 0x080037a8, 0x080037b8, 0x080037c8,
+ 0x080037e8, 0x080037f8, 0x08003808, 0x08003898, 0x080037d8, 0x08003818,
+ 0x08003828, 0x08003840, 0x08003860, 0x08003898, 0x08003878, 0x08003878,
+ 0x080055f0, 0x080055f0, 0x080055f0, 0x080055f0, 0x080055f0, 0x08005618,
+ 0x08005618, 0x08005640, 0x08005690, 0x08005660, 0x00000000 };
+static u32 bnx2_CP_b09FwBss[(0x870/4) + 1] = { 0x0 };
+static u32 bnx2_CP_b09FwSbss[(0xe9/4) + 1] = { 0x0 };
+
+static struct fw_info bnx2_cp_fw_09 = {
+ .ver_major = 0x1,
+ .ver_minor = 0x0,
+ .ver_fix = 0x0,
+
+ .start_addr = 0x0800006c,
+
+ .text_addr = 0x08000000,
+ .text_len = 0x73cc,
+ .text_index = 0x0,
+ .gz_text = bnx2_CP_b09FwText,
+ .gz_text_len = sizeof(bnx2_CP_b09FwText),
+
+ .data_addr = 0x08007500,
+ .data_len = 0x50,
+ .data_index = 0x0,
+ .data = bnx2_CP_b09FwData,
+
+ .sbss_addr = 0x08007554,
+ .sbss_len = 0xe9,
+ .sbss_index = 0x0,
+ .sbss = bnx2_CP_b09FwSbss,
+
+ .bss_addr = 0x08007640,
+ .bss_len = 0x870,
+ .bss_index = 0x0,
+ .bss = bnx2_CP_b09FwBss,
+
+ .rodata_addr = 0x080073d0,
+ .rodata_len = 0x118,
+ .rodata_index = 0x0,
+ .rodata = bnx2_CP_b09FwRodata,
+};
+
+static u8 bnx2_RXP_b09FwText[] = {
+ 0x1f, 0x8b, 0x08, 0x08, 0x19, 0xfd, 0x2f, 0x45, 0x00, 0x03, 0x74, 0x65,
+ 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xec, 0x5c, 0x6b, 0x6c,
+ 0x1c, 0xd7, 0x75, 0x3e, 0xf3, 0x20, 0xb5, 0xa2, 0xf8, 0x18, 0x2e, 0x57,
+ 0xcc, 0x4a, 0x66, 0xec, 0x5d, 0x71, 0x24, 0xb2, 0x16, 0x6b, 0x8c, 0xd8,
+ 0xad, 0x4d, 0x04, 0x6b, 0x7b, 0x33, 0xbb, 0x92, 0x98, 0x54, 0x85, 0x29,
+ 0x87, 0x75, 0x0c, 0xc3, 0x75, 0xd9, 0xa5, 0x1a, 0xbb, 0xae, 0x51, 0xc8,
+ 0x8f, 0xc4, 0x06, 0x6a, 0xd6, 0x9b, 0x25, 0xdd, 0xa8, 0xe9, 0x82, 0x43,
+ 0x4b, 0xaa, 0xe9, 0x02, 0x69, 0xbb, 0x20, 0xa9, 0xc7, 0x8f, 0x85, 0x56,
+ 0x76, 0x52, 0xc7, 0xf9, 0xe1, 0x48, 0x50, 0x95, 0x20, 0x28, 0x0c, 0x43,
+ 0x48, 0x8d, 0xd6, 0x3f, 0xda, 0x40, 0x95, 0x9f, 0x68, 0x92, 0x42, 0x41,
+ 0x0b, 0xc7, 0x68, 0x6c, 0x4f, 0xbf, 0xef, 0xce, 0x0c, 0xb9, 0xa4, 0x5f,
+ 0x40, 0x7f, 0xf4, 0x4f, 0xe7, 0x02, 0x8b, 0xb9, 0xf7, 0xce, 0x3d, 0xe7,
+ 0x9e, 0x7b, 0xde, 0xe7, 0x0e, 0xa5, 0xdf, 0xef, 0x94, 0x0e, 0x09, 0x5b,
+ 0x17, 0x7e, 0x99, 0xc3, 0x8f, 0x3d, 0x74, 0xc3, 0xd8, 0x0d, 0xa3, 0x22,
+ 0x7b, 0xf6, 0x18, 0x5b, 0x12, 0x7a, 0x34, 0x1f, 0xb7, 0xb8, 0xc5, 0x2d,
+ 0x6e, 0x71, 0x8b, 0x5b, 0xdc, 0xe2, 0x16, 0xb7, 0xb8, 0xc5, 0x2d, 0x6e,
+ 0x71, 0x8b, 0x5b, 0xdc, 0xe2, 0x16, 0xb7, 0xb8, 0xc5, 0x2d, 0x6e, 0x71,
+ 0x8b, 0x5b, 0xdc, 0xe2, 0x16, 0xb7, 0xb8, 0xc5, 0x2d, 0x6e, 0x71, 0x8b,
+ 0x5b, 0xdc, 0xe2, 0x16, 0xb7, 0xb8, 0xc5, 0x2d, 0x6e, 0x71, 0x8b, 0x5b,
+ 0xdc, 0xe2, 0x16, 0xb7, 0xb8, 0xc5, 0x2d, 0x6e, 0x71, 0x8b, 0x5b, 0xdc,
+ 0xe2, 0xf6, 0xff, 0xbd, 0x19, 0x22, 0x16, 0x9f, 0x5d, 0xe1, 0x4f, 0x12,
+ 0x7a, 0xfe, 0xf2, 0x1f, 0xba, 0xb6, 0x24, 0x8c, 0xfc, 0xcf, 0x66, 0xa6,
+ 0x6d, 0x91, 0x42, 0x63, 0x77, 0xa6, 0x28, 0xef, 0xfb, 0x95, 0x94, 0x29,
+ 0x9c, 0xff, 0x6c, 0xfe, 0xbd, 0xbf, 0x7d, 0xf1, 0xa6, 0xec, 0xd5, 0xba,
+ 0x21, 0x09, 0x2b, 0x3f, 0xb7, 0xc7, 0xda, 0x25, 0x89, 0x01, 0xc0, 0x7c,
+ 0x6b, 0xe8, 0xc7, 0xdd, 0xd2, 0x2d, 0x6b, 0x78, 0xec, 0x84, 0x5c, 0x36,
+ 0x5e, 0xd0, 0xdc, 0xa6, 0xef, 0x9f, 0x70, 0x7c, 0xff, 0x87, 0xf8, 0xbd,
+ 0xe5, 0x60, 0xec, 0x7d, 0xe0, 0x17, 0x4c, 0x43, 0x74, 0xfb, 0x2f, 0x34,
+ 0x77, 0xb9, 0x43, 0xaa, 0x8b, 0xa6, 0xcc, 0x7a, 0x29, 0x39, 0xe2, 0x55,
+ 0xb4, 0x52, 0xb3, 0xa6, 0xed, 0x3d, 0x35, 0xaf, 0xed, 0x3b, 0x75, 0x44,
+ 0xdb, 0x7f, 0x6a, 0x41, 0x73, 0x4f, 0x49, 0x45, 0xdf, 0xd3, 0x29, 0x05,
+ 0xeb, 0xb4, 0x56, 0x6c, 0xf6, 0x6b, 0xee, 0xe2, 0x7b, 0xbe, 0xeb, 0x64,
+ 0xad, 0xbb, 0xc4, 0x2c, 0x80, 0x16, 0x71, 0x6b, 0x3e, 0xc6, 0xa6, 0x14,
+ 0x52, 0xbe, 0xaf, 0xe7, 0xfd, 0x27, 0xdc, 0x9c, 0x6d, 0xe9, 0x5a, 0x4a,
+ 0xaa, 0xcd, 0x7e, 0xe0, 0xed, 0xd4, 0x8a, 0x8b, 0xa6, 0x56, 0xf2, 0xfc,
+ 0x73, 0xae, 0x23, 0x03, 0x86, 0xf8, 0xfe, 0x9c, 0xb3, 0x33, 0x7d, 0x48,
+ 0x4e, 0x02, 0x6f, 0x03, 0xf8, 0xc4, 0xd2, 0xf3, 0xa4, 0x8f, 0x74, 0x92,
+ 0xe4, 0x8a, 0x56, 0x1c, 0x8a, 0xe8, 0x93, 0x0c, 0xe9, 0x2f, 0xaf, 0xe8,
+ 0xa0, 0x73, 0x8b, 0x94, 0xeb, 0x96, 0x4c, 0xad, 0x6c, 0x5c, 0x7f, 0xd9,
+ 0x7f, 0x71, 0x28, 0x25, 0xcf, 0x36, 0xb3, 0x47, 0x2a, 0x92, 0x90, 0x39,
+ 0x2f, 0x23, 0x7a, 0x5e, 0x0a, 0x6e, 0x6e, 0x40, 0xce, 0x35, 0xd3, 0xf2,
+ 0x5c, 0xd3, 0x4e, 0x57, 0x65, 0x93, 0x94, 0x53, 0x96, 0x9c, 0x6d, 0xa6,
+ 0x70, 0x46, 0xff, 0x9c, 0x6e, 0xdb, 0x56, 0x15, 0x6b, 0xab, 0xcd, 0x97,
+ 0xf8, 0xef, 0x5f, 0xac, 0xe9, 0x9c, 0x82, 0xa9, 0x80, 0xee, 0x70, 0x2d,
+ 0xcf, 0xa1, 0xd6, 0xaa, 0xb3, 0x04, 0x6b, 0xa5, 0x32, 0x9d, 0xc3, 0x5c,
+ 0x73, 0x34, 0xe4, 0xef, 0x16, 0x9c, 0x97, 0x4f, 0x4b, 0xaa, 0x9e, 0x01,
+ 0xde, 0xb0, 0xff, 0xcf, 0xc0, 0x37, 0x80, 0xf3, 0x5e, 0xab, 0x7e, 0xee,
+ 0xa2, 0xa4, 0x74, 0xd9, 0x99, 0x2e, 0x0b, 0x78, 0xdb, 0xec, 0xc4, 0x98,
+ 0xf4, 0xf9, 0xfe, 0x7e, 0x47, 0xac, 0xaa, 0xd3, 0x03, 0x98, 0x8c, 0x54,
+ 0x9d, 0x6e, 0xe0, 0x69, 0x13, 0xcb, 0xe6, 0xb9, 0xb8, 0xd7, 0x66, 0xcc,
+ 0xfb, 0x5d, 0x46, 0xde, 0xf7, 0xa7, 0x73, 0xd2, 0x1d, 0xcc, 0xed, 0x56,
+ 0x38, 0xa6, 0x26, 0x34, 0xac, 0xfb, 0x05, 0x69, 0x4e, 0x24, 0xf3, 0xec,
+ 0xf3, 0x99, 0x13, 0x77, 0xfe, 0xda, 0x90, 0x96, 0x34, 0x68, 0xb9, 0x26,
+ 0xec, 0x83, 0xff, 0x1e, 0xf8, 0xe0, 0x7c, 0x06, 0x63, 0xed, 0x3a, 0xe0,
+ 0x19, 0xae, 0x0a, 0xf7, 0xe8, 0x93, 0xa5, 0x94, 0xe8, 0x57, 0x9c, 0xde,
+ 0x70, 0x5d, 0x37, 0x68, 0x8d, 0xf4, 0xa0, 0x5f, 0xe6, 0x16, 0xc9, 0xeb,
+ 0x1a, 0x64, 0x83, 0xe7, 0x8d, 0x15, 0xad, 0xd0, 0x3c, 0x82, 0xbe, 0x29,
+ 0xd3, 0xb6, 0x7f, 0x6e, 0xce, 0x99, 0xd7, 0x8a, 0xa7, 0x4e, 0x6a, 0xa5,
+ 0x53, 0x2f, 0x68, 0x7b, 0x9b, 0x2f, 0x74, 0x49, 0x47, 0x16, 0xa7, 0x4e,
+ 0xc8, 0x93, 0x9e, 0x26, 0xa4, 0x73, 0x09, 0xbc, 0x2b, 0x58, 0x15, 0x31,
+ 0xed, 0x6e, 0x6d, 0x1f, 0xf0, 0xb4, 0xd9, 0x7f, 0xd2, 0x29, 0xdd, 0x86,
+ 0x6c, 0xb2, 0xa3, 0xb5, 0x29, 0xf9, 0x33, 0xd0, 0x74, 0xc1, 0x49, 0x91,
+ 0x5f, 0x3d, 0x01, 0x4c, 0x44, 0x07, 0xf5, 0x8a, 0x3a, 0xa5, 0x17, 0x4a,
+ 0xc7, 0xff, 0xbc, 0xaf, 0x3a, 0xb2, 0x85, 0x6b, 0xa0, 0xff, 0xd6, 0xfd,
+ 0xd3, 0xb6, 0xdb, 0x6b, 0x4a, 0xc5, 0xd2, 0x25, 0x6b, 0x15, 0xe5, 0x3a,
+ 0x99, 0x73, 0x44, 0x8a, 0x35, 0xec, 0x69, 0x9b, 0xe0, 0x8d, 0x0d, 0xde,
+ 0xec, 0x3c, 0x32, 0xa8, 0xff, 0x96, 0x64, 0xfa, 0x2b, 0x9a, 0x19, 0xf2,
+ 0x71, 0x49, 0x6e, 0x51, 0xf0, 0x7a, 0xde, 0x81, 0x7e, 0x76, 0xb0, 0x8f,
+ 0x7d, 0x13, 0x6a, 0x5f, 0x23, 0x6f, 0xa7, 0x97, 0x45, 0x34, 0x3d, 0xbf,
+ 0x1b, 0xf8, 0xa8, 0xb7, 0x5c, 0xf7, 0x04, 0x68, 0x24, 0xed, 0xec, 0xdb,
+ 0x80, 0x49, 0x88, 0xeb, 0x74, 0xb5, 0xd0, 0x49, 0x79, 0x93, 0xd7, 0xe4,
+ 0x9d, 0x3a, 0xa7, 0xb6, 0x76, 0xce, 0x5f, 0xf9, 0x9b, 0x46, 0x4d, 0xf9,
+ 0xa1, 0x3a, 0x2f, 0x6d, 0x8c, 0xeb, 0x52, 0xa1, 0x4e, 0x24, 0xa0, 0x47,
+ 0xa2, 0x95, 0x1d, 0x6b, 0x15, 0x57, 0x59, 0x44, 0x37, 0xf2, 0x9d, 0x52,
+ 0x54, 0xf4, 0x8d, 0x61, 0x2f, 0xda, 0x1e, 0x6c, 0xc8, 0xe6, 0x59, 0x38,
+ 0x97, 0x87, 0x8d, 0x67, 0xd9, 0x97, 0xf2, 0x02, 0xed, 0x9d, 0xb4, 0x9d,
+ 0xcf, 0xaa, 0x7f, 0x8e, 0x45, 0x5d, 0x3c, 0xd6, 0x03, 0xda, 0x38, 0x86,
+ 0x1d, 0xda, 0x78, 0x3f, 0xa2, 0x89, 0x3b, 0x36, 0x08, 0xfe, 0x70, 0x9d,
+ 0x9d, 0x81, 0x9c, 0x0b, 0x2e, 0xf6, 0x74, 0x9d, 0xdf, 0x50, 0x3c, 0xe8,
+ 0xc5, 0x79, 0x06, 0xe7, 0xc9, 0xaf, 0x0e, 0xe8, 0xb6, 0x26, 0x65, 0x27,
+ 0x9b, 0xa1, 0xdc, 0x03, 0xda, 0x75, 0xd9, 0x74, 0x63, 0x2b, 0xed, 0x91,
+ 0xac, 0xa8, 0x87, 0xa6, 0x24, 0x47, 0xb9, 0x96, 0xeb, 0xb8, 0x3e, 0x3b,
+ 0x26, 0xfa, 0xaf, 0x7c, 0x6b, 0xdd, 0x59, 0x6d, 0xd9, 0x31, 0x0f, 0x1a,
+ 0x02, 0xde, 0x82, 0x27, 0x9f, 0xb6, 0x96, 0x7c, 0xdd, 0xc8, 0x3f, 0xae,
+ 0x6d, 0x5d, 0x07, 0x9d, 0xe8, 0x27, 0x0d, 0x27, 0x3a, 0x03, 0x5b, 0x8b,
+ 0x68, 0x8a, 0x64, 0xa3, 0x85, 0x38, 0x3e, 0xe9, 0x1c, 0x5c, 0x0f, 0x1f,
+ 0xe0, 0xc1, 0x07, 0xc0, 0xaf, 0x3d, 0xeb, 0xc1, 0xfe, 0x3d, 0xfa, 0x8c,
+ 0x8c, 0xbc, 0x38, 0x04, 0x1f, 0xb7, 0xe6, 0x63, 0xd0, 0xc6, 0xd1, 0xd7,
+ 0xc5, 0x80, 0x8f, 0x99, 0xad, 0xeb, 0xb0, 0x59, 0xf0, 0x78, 0x85, 0x73,
+ 0xb0, 0xed, 0x95, 0x12, 0x9e, 0xb6, 0x54, 0x1b, 0xd4, 0xab, 0xc8, 0x97,
+ 0xd2, 0xe7, 0xa4, 0xe1, 0x5f, 0xe8, 0x77, 0xe8, 0x57, 0xb8, 0xd6, 0xf7,
+ 0x4b, 0x0e, 0x61, 0x7d, 0x99, 0x70, 0x68, 0x43, 0x9d, 0xa2, 0x27, 0x2b,
+ 0xda, 0xc1, 0x21, 0xd8, 0xd6, 0xf5, 0x6d, 0xa0, 0x95, 0x36, 0x76, 0x8d,
+ 0x48, 0x3b, 0xf7, 0xfb, 0x69, 0x57, 0xf0, 0xef, 0xee, 0x36, 0x61, 0x0d,
+ 0x9f, 0xef, 0x86, 0x63, 0x2d, 0xf4, 0x2d, 0x7c, 0x9f, 0xcd, 0x14, 0xa4,
+ 0x3f, 0x1c, 0xb3, 0xbf, 0x4a, 0xaf, 0xa3, 0xdf, 0x98, 0x90, 0x1d, 0x27,
+ 0x03, 0x9f, 0xb8, 0x63, 0xc9, 0x12, 0xfb, 0x64, 0x40, 0xe3, 0x8e, 0x33,
+ 0x91, 0x6f, 0x7c, 0x1f, 0xf0, 0xa0, 0xcf, 0x5b, 0x8d, 0x03, 0x68, 0x3f,
+ 0xd3, 0x60, 0x2a, 0x98, 0xdb, 0xc8, 0x0b, 0xfa, 0x63, 0xda, 0x9b, 0xd5,
+ 0x6a, 0x6f, 0x7b, 0x60, 0x6f, 0x4e, 0xbb, 0x64, 0x9d, 0xbf, 0x87, 0xbd,
+ 0x7d, 0xc3, 0xd1, 0xc0, 0x1b, 0x91, 0x8b, 0xb5, 0x34, 0x6c, 0xdd, 0x4c,
+ 0xbf, 0x26, 0x3b, 0x33, 0xb3, 0xa2, 0xc9, 0x09, 0xce, 0x35, 0x30, 0xa7,
+ 0x7c, 0x71, 0xe0, 0x0b, 0x2e, 0x1b, 0x4f, 0x81, 0x2e, 0xdf, 0x9f, 0x05,
+ 0xce, 0xf2, 0x88, 0x11, 0xda, 0x56, 0x34, 0x6f, 0xdd, 0xef, 0xda, 0xee,
+ 0xaf, 0x19, 0x52, 0x19, 0x6e, 0x93, 0xec, 0xf0, 0x12, 0x70, 0x4f, 0x3b,
+ 0x81, 0x1d, 0x53, 0xd7, 0x97, 0x81, 0x7f, 0xce, 0x1b, 0x82, 0x1e, 0xd3,
+ 0x0e, 0x40, 0x17, 0xf0, 0x2f, 0x03, 0xff, 0x5c, 0xb3, 0x4d, 0xbe, 0x6e,
+ 0x46, 0xb1, 0x32, 0x3a, 0x4f, 0x37, 0x96, 0x45, 0xfb, 0x1e, 0x96, 0x2f,
+ 0x7a, 0x49, 0xcd, 0x3d, 0x46, 0xff, 0x5a, 0x1d, 0x86, 0x9d, 0x68, 0x55,
+ 0x87, 0x7b, 0x1b, 0xb2, 0xbc, 0xba, 0x46, 0x0a, 0xd5, 0xc0, 0x06, 0x0b,
+ 0xee, 0x50, 0x25, 0x6d, 0x28, 0x5f, 0x22, 0xb2, 0x0f, 0xb6, 0xb7, 0x6c,
+ 0x73, 0xcc, 0xf9, 0x60, 0x6e, 0xbc, 0xd6, 0x0f, 0x9f, 0xc8, 0xf1, 0x7b,
+ 0xfe, 0xb4, 0x13, 0xcc, 0x7d, 0xa1, 0x76, 0x57, 0x37, 0xfd, 0x2e, 0xe2,
+ 0x44, 0xa6, 0xea, 0xfc, 0xbb, 0x0f, 0xfd, 0x5d, 0x07, 0xf3, 0xd1, 0x78,
+ 0xb2, 0xe3, 0x81, 0xce, 0x8a, 0xb6, 0xdf, 0xd6, 0xfb, 0xdb, 0x43, 0x1f,
+ 0xb6, 0x1f, 0x93, 0x7b, 0x6b, 0xd5, 0xbe, 0x76, 0x79, 0xcf, 0x60, 0x1c,
+ 0xbd, 0x22, 0x62, 0xba, 0xb5, 0x5d, 0xe0, 0x47, 0xb5, 0xb7, 0x65, 0x2e,
+ 0x51, 0xaa, 0xf9, 0x72, 0xc1, 0x09, 0x60, 0x30, 0xee, 0x2c, 0xd6, 0xf4,
+ 0xfe, 0x84, 0xac, 0x8e, 0x2d, 0xc2, 0xac, 0xc8, 0xae, 0xe1, 0x65, 0x51,
+ 0xb0, 0x7d, 0x89, 0x35, 0xd8, 0x54, 0xa9, 0x56, 0xed, 0x6d, 0x19, 0xa7,
+ 0x8b, 0xc0, 0xa5, 0xef, 0x59, 0x85, 0x1d, 0x58, 0x83, 0xdd, 0x2a, 0x99,
+ 0x5e, 0xc2, 0xeb, 0xfd, 0x9b, 0xd7, 0x70, 0x67, 0x42, 0x7a, 0xfa, 0x36,
+ 0xaf, 0xe1, 0xb0, 0x89, 0xb3, 0x65, 0x3c, 0x4c, 0x9c, 0x3b, 0xd6, 0x70,
+ 0x8e, 0xac, 0xa7, 0xe7, 0xb0, 0xc0, 0x07, 0x25, 0xda, 0xf3, 0xb2, 0xe7,
+ 0x62, 0x6d, 0x70, 0xe2, 0x8b, 0x82, 0x58, 0x37, 0xb2, 0x29, 0xf4, 0xc9,
+ 0xe6, 0x1e, 0x17, 0xbc, 0x32, 0x85, 0x3e, 0x4e, 0x93, 0x2a, 0xe4, 0x7c,
+ 0x7f, 0x43, 0xf6, 0x5c, 0x68, 0x98, 0xa1, 0x2e, 0x51, 0x27, 0xde, 0x86,
+ 0x8d, 0x75, 0x4e, 0x99, 0x88, 0xc3, 0xe7, 0x94, 0x8d, 0xc9, 0x44, 0xb5,
+ 0x26, 0x95, 0xed, 0xf9, 0x27, 0x7c, 0xe8, 0xe2, 0x94, 0x05, 0x3f, 0x5a,
+ 0x94, 0xce, 0x31, 0x37, 0x87, 0xf9, 0x06, 0x6d, 0x0b, 0x7e, 0x05, 0xb0,
+ 0xd0, 0xb5, 0x84, 0x31, 0xbf, 0xf3, 0x55, 0xd7, 0xe0, 0x3e, 0x19, 0xe4,
+ 0x4d, 0x89, 0x84, 0x3e, 0x7f, 0xd5, 0xa7, 0x9e, 0x4d, 0x8f, 0x5c, 0x45,
+ 0x9e, 0x62, 0xc1, 0x57, 0xc2, 0x7f, 0x40, 0xdf, 0x67, 0x9b, 0x82, 0xb8,
+ 0xfe, 0x40, 0x4f, 0x60, 0x63, 0x47, 0xb7, 0x06, 0x4f, 0x31, 0xe9, 0x9b,
+ 0xa7, 0x73, 0xcc, 0x01, 0xda, 0x13, 0x6e, 0x6e, 0x7c, 0x9b, 0x71, 0xe6,
+ 0xc0, 0x36, 0xfd, 0x4c, 0x65, 0x9b, 0x0e, 0x9f, 0x0e, 0x9b, 0xd2, 0xdd,
+ 0x1c, 0xfa, 0x67, 0x22, 0x1b, 0x4a, 0xc3, 0x86, 0xde, 0x56, 0x39, 0xc8,
+ 0xb9, 0xe6, 0x29, 0xd8, 0xab, 0xa2, 0x55, 0x26, 0x90, 0x13, 0xe8, 0xa3,
+ 0xef, 0x43, 0x4f, 0x70, 0x16, 0xf8, 0xc0, 0x02, 0xb8, 0xa4, 0x8f, 0xbe,
+ 0x11, 0xda, 0x33, 0xfb, 0xef, 0xf8, 0x41, 0x7c, 0xf8, 0x7c, 0xb8, 0xff,
+ 0x3f, 0x75, 0x07, 0x3e, 0x20, 0xc2, 0x45, 0x3c, 0xc3, 0xda, 0x04, 0xf2,
+ 0x99, 0x89, 0xa6, 0xa9, 0xd1, 0x9f, 0x17, 0x3d, 0xe6, 0x21, 0xcc, 0x41,
+ 0x1e, 0x0b, 0xfd, 0x22, 0x73, 0x8f, 0xce, 0x90, 0xa7, 0xb9, 0x28, 0xce,
+ 0x29, 0x7b, 0x43, 0xcc, 0xc9, 0x94, 0x9d, 0x36, 0xe5, 0x93, 0xa7, 0x73,
+ 0x9d, 0x58, 0x87, 0xb9, 0x26, 0xce, 0x0d, 0xbf, 0x84, 0x5c, 0x06, 0x6b,
+ 0xce, 0x63, 0x7d, 0x7b, 0x68, 0xf3, 0x17, 0xa5, 0x0c, 0x9f, 0x6a, 0xda,
+ 0x7c, 0x9f, 0xeb, 0x91, 0x0e, 0x8c, 0x1b, 0xd8, 0x0b, 0x7e, 0xc2, 0x50,
+ 0x7c, 0x46, 0x2c, 0x48, 0x5d, 0xc7, 0x1c, 0x09, 0x6b, 0x33, 0x58, 0x4b,
+ 0xbf, 0xcb, 0xb5, 0xcf, 0x82, 0x0e, 0x8c, 0x1b, 0x84, 0xa1, 0x8f, 0x12,
+ 0xdf, 0xcd, 0x6d, 0x86, 0x26, 0xf9, 0xe7, 0x0c, 0x3b, 0x5a, 0x1b, 0xe1,
+ 0xdd, 0xb8, 0x96, 0xf9, 0x09, 0x71, 0xf7, 0x84, 0xf1, 0x7f, 0x5c, 0x0a,
+ 0xcd, 0x02, 0x7e, 0x22, 0xd3, 0xc7, 0x90, 0x8f, 0xd9, 0x6d, 0x88, 0x55,
+ 0x9c, 0xdf, 0x6a, 0x05, 0x67, 0x8d, 0xe0, 0xee, 0xef, 0x5b, 0x3f, 0xfe,
+ 0x42, 0x72, 0xcd, 0x47, 0xd2, 0xc2, 0xa4, 0x80, 0x18, 0x01, 0x5e, 0x65,
+ 0xa6, 0x98, 0xc3, 0x15, 0x1b, 0x4a, 0xa6, 0x98, 0x1b, 0x83, 0x5f, 0x0c,
+ 0xf2, 0xa2, 0x73, 0xde, 0x46, 0xd9, 0x59, 0xe0, 0x77, 0x01, 0x3c, 0xce,
+ 0x40, 0x87, 0xc6, 0x01, 0x2b, 0x87, 0x81, 0x83, 0xf1, 0xd7, 0xd1, 0xf3,
+ 0x49, 0x29, 0x5b, 0xcc, 0x13, 0xda, 0x49, 0x67, 0x81, 0xf6, 0xaf, 0xe7,
+ 0x37, 0x63, 0x8e, 0xfd, 0x7b, 0x7b, 0x02, 0x99, 0x75, 0x71, 0x3c, 0xa1,
+ 0xe7, 0x7b, 0x36, 0xcc, 0x7f, 0xbf, 0x2b, 0xa0, 0x4d, 0x8d, 0x31, 0xff,
+ 0xf2, 0x86, 0xf1, 0xef, 0x25, 0xd7, 0x8f, 0xef, 0xda, 0x16, 0xea, 0x20,
+ 0xfa, 0x8f, 0x85, 0xf4, 0x82, 0xb6, 0x55, 0x5a, 0xa3, 0x9c, 0x57, 0x16,
+ 0x74, 0xe4, 0x7f, 0x6e, 0x6e, 0x27, 0x62, 0x7d, 0x46, 0x4a, 0x4d, 0xd0,
+ 0xbd, 0x1a, 0xcb, 0x56, 0xd7, 0x54, 0xd6, 0xd6, 0x04, 0xbe, 0xbe, 0xd4,
+ 0xf4, 0x91, 0x3b, 0xb5, 0xc6, 0xbd, 0x61, 0xf4, 0x2b, 0xd8, 0xa7, 0x20,
+ 0xd3, 0xde, 0x85, 0x82, 0x6e, 0x1f, 0x09, 0xf2, 0x3e, 0xfb, 0x9b, 0x5a,
+ 0x69, 0x99, 0xf9, 0x20, 0xec, 0xc9, 0x56, 0xf9, 0x3f, 0xe2, 0xca, 0x51,
+ 0xad, 0x70, 0xea, 0x38, 0xf2, 0xc1, 0x15, 0xfc, 0x4e, 0xe3, 0xd7, 0xc0,
+ 0x2f, 0xca, 0xc3, 0x9f, 0x41, 0x1e, 0xaf, 0x7c, 0x2c, 0xe2, 0x41, 0xb0,
+ 0xff, 0x1b, 0x2b, 0xd0, 0xb3, 0xe3, 0x29, 0xf9, 0x86, 0xad, 0xf7, 0xe9,
+ 0x81, 0x5f, 0x29, 0x20, 0x8f, 0xb5, 0xde, 0x96, 0xdf, 0x0e, 0xf3, 0x22,
+ 0x91, 0xd7, 0x16, 0xc0, 0xc7, 0x91, 0xfd, 0xa1, 0xce, 0x16, 0xee, 0x75,
+ 0x95, 0xff, 0x0c, 0xf3, 0x1e, 0xe4, 0x5f, 0x05, 0xb5, 0xea, 0x5b, 0xe0,
+ 0x8d, 0x26, 0x6f, 0x41, 0x87, 0x5e, 0x5b, 0xe8, 0x00, 0x3d, 0xb6, 0x94,
+ 0x27, 0x91, 0x2f, 0x68, 0x83, 0xd6, 0x26, 0xad, 0x03, 0x76, 0x0c, 0x1b,
+ 0x57, 0x63, 0x49, 0xb4, 0xe5, 0x2f, 0xcd, 0x2c, 0xd5, 0x74, 0xac, 0x45,
+ 0xee, 0x93, 0x43, 0x1f, 0xb2, 0xbf, 0xb2, 0x40, 0x38, 0x5d, 0x5e, 0x5f,
+ 0x30, 0xe4, 0x4d, 0xe4, 0x52, 0x6f, 0xd9, 0x97, 0x66, 0x10, 0xb7, 0xfa,
+ 0x11, 0x23, 0x50, 0x8b, 0xec, 0xa4, 0x9f, 0xde, 0x61, 0xe2, 0x59, 0xc2,
+ 0x6f, 0x1f, 0x72, 0xc1, 0x8f, 0x86, 0xf9, 0xb8, 0xf5, 0xa4, 0x2d, 0x01,
+ 0x18, 0xae, 0x37, 0x41, 0x5b, 0x37, 0xe4, 0x9f, 0xb5, 0xa6, 0xe4, 0xf5,
+ 0x1e, 0x95, 0xaf, 0x68, 0x9c, 0x0f, 0x7c, 0xd3, 0x87, 0xe7, 0xc9, 0x67,
+ 0x03, 0x3a, 0xce, 0x31, 0xdf, 0xd1, 0x87, 0x12, 0x5f, 0x76, 0xac, 0x80,
+ 0xc3, 0x5c, 0x59, 0x08, 0xfa, 0xd1, 0x9c, 0x68, 0x51, 0x1c, 0xa3, 0x6f,
+ 0x2c, 0xc1, 0x4e, 0x38, 0x9e, 0x10, 0x25, 0x83, 0x75, 0xf2, 0x94, 0x84,
+ 0x99, 0x3f, 0x3b, 0x33, 0x67, 0x53, 0xae, 0xf0, 0x71, 0xb5, 0x48, 0xae,
+ 0x94, 0x51, 0xbb, 0x54, 0x17, 0xbe, 0x09, 0xb9, 0xea, 0x61, 0xbe, 0x0f,
+ 0x1b, 0x3f, 0x4e, 0xf9, 0xa2, 0xfe, 0x5b, 0x40, 0xee, 0xb3, 0x20, 0xc9,
+ 0xa0, 0x5e, 0x39, 0x8a, 0x3c, 0x1f, 0xf2, 0xab, 0x1d, 0x07, 0x0e, 0xd8,
+ 0x69, 0x6d, 0x05, 0x4f, 0xd4, 0x16, 0xb5, 0xd3, 0x78, 0x0e, 0xe0, 0xd9,
+ 0xa0, 0x6e, 0x86, 0xb9, 0xc6, 0x87, 0xe8, 0x81, 0x3d, 0x95, 0x68, 0x4f,
+ 0xf2, 0xfd, 0x66, 0x5e, 0xbe, 0xdb, 0x1c, 0x93, 0xe7, 0x9b, 0x39, 0xf9,
+ 0xbb, 0xa6, 0x23, 0xdf, 0x69, 0x8e, 0xc8, 0xb7, 0x9b, 0xc3, 0xac, 0xc9,
+ 0x90, 0x37, 0x65, 0x98, 0x37, 0xc9, 0xbd, 0xde, 0xad, 0xb0, 0x77, 0xca,
+ 0xff, 0xd2, 0x4c, 0xa1, 0x31, 0x28, 0xe5, 0x63, 0xf0, 0xcf, 0xce, 0xcd,
+ 0xac, 0x25, 0xe5, 0x11, 0x87, 0x35, 0x41, 0x1b, 0xdf, 0xa3, 0xce, 0x84,
+ 0xff, 0x86, 0x3f, 0x9b, 0x4a, 0x65, 0x4f, 0xbb, 0x46, 0x47, 0xe8, 0x03,
+ 0x6e, 0x49, 0x4a, 0x07, 0xf6, 0x82, 0x0f, 0x5c, 0x7a, 0x1a, 0x36, 0xa0,
+ 0x6a, 0x9a, 0x04, 0xfc, 0x0d, 0x73, 0x01, 0x93, 0x76, 0x8c, 0x3a, 0x30,
+ 0x9b, 0x71, 0x0d, 0xd6, 0x77, 0xb4, 0x67, 0x03, 0x81, 0x83, 0x70, 0xfb,
+ 0x2c, 0xca, 0xcd, 0xb4, 0xe9, 0x57, 0x0b, 0xa1, 0x8f, 0x4b, 0x84, 0x7a,
+ 0x69, 0x61, 0xfe, 0xf1, 0xd0, 0x27, 0x6f, 0xdc, 0x07, 0xf1, 0x02, 0xf9,
+ 0x64, 0xb0, 0x8e, 0xb0, 0x5a, 0x08, 0xdb, 0x17, 0xce, 0x75, 0x82, 0xdf,
+ 0x8e, 0x94, 0xbd, 0x37, 0x35, 0xe6, 0xd9, 0xc8, 0x77, 0x30, 0x1e, 0xc1,
+ 0xf8, 0x4a, 0x38, 0xfe, 0x9c, 0x4c, 0x2f, 0x0a, 0x68, 0xfd, 0x89, 0x56,
+ 0x54, 0xe3, 0x31, 0x8c, 0x75, 0x8c, 0x0d, 0xd6, 0x02, 0x68, 0x37, 0x27,
+ 0xa9, 0xeb, 0xba, 0x4d, 0x5f, 0x38, 0x19, 0xfa, 0xc3, 0x82, 0x1c, 0xf6,
+ 0x06, 0x0b, 0x57, 0x11, 0x33, 0xb4, 0xb6, 0x28, 0xff, 0xd9, 0x0e, 0xbe,
+ 0xf8, 0xfe, 0xed, 0xac, 0xb9, 0x93, 0xa6, 0x7c, 0x7b, 0x3e, 0x6b, 0x3d,
+ 0xa4, 0x7f, 0x0d, 0x67, 0xf2, 0xfd, 0x83, 0x76, 0xf6, 0xc8, 0x94, 0xde,
+ 0x25, 0xdf, 0x3d, 0xca, 0xd8, 0x7b, 0x76, 0xe6, 0x07, 0xd0, 0xbd, 0xfa,
+ 0x4a, 0xbb, 0xd4, 0xeb, 0xa6, 0x5c, 0x19, 0x1d, 0x04, 0x9d, 0x96, 0xd4,
+ 0x1b, 0x49, 0xe4, 0x73, 0x9b, 0x65, 0xb6, 0x5f, 0x19, 0x18, 0xfc, 0xf4,
+ 0xb0, 0xf2, 0xd3, 0xae, 0x8d, 0x67, 0xe3, 0xe7, 0x3d, 0xeb, 0xcf, 0x5c,
+ 0x02, 0xfd, 0xd0, 0xeb, 0xe4, 0x76, 0x25, 0xe7, 0xb2, 0x37, 0x68, 0x95,
+ 0x75, 0xc4, 0x2e, 0x73, 0xd0, 0xba, 0x57, 0xff, 0x2f, 0xff, 0xf3, 0x26,
+ 0x65, 0xf7, 0xaa, 0xaa, 0x61, 0x54, 0xac, 0xc3, 0x7e, 0x4b, 0x2b, 0x2f,
+ 0x83, 0x16, 0xf8, 0xd8, 0xc6, 0xf6, 0x70, 0x9c, 0x51, 0xbc, 0x38, 0xdb,
+ 0xe8, 0x90, 0xef, 0xd4, 0xb7, 0xc8, 0x72, 0x9d, 0xef, 0xdb, 0x65, 0xa9,
+ 0x3e, 0x78, 0xb5, 0x4f, 0xef, 0x97, 0xf3, 0xd7, 0x5c, 0x6f, 0xdd, 0xa3,
+ 0x23, 0x37, 0x98, 0xfc, 0x40, 0x7e, 0x39, 0xda, 0x23, 0x3f, 0xfe, 0x72,
+ 0xf6, 0x99, 0x3f, 0xd5, 0x61, 0x03, 0xa3, 0x9d, 0xb4, 0x6d, 0xf4, 0x39,
+ 0x9f, 0xbd, 0x5a, 0xd0, 0xa9, 0xdb, 0x3f, 0x02, 0x4f, 0xb3, 0x0b, 0x81,
+ 0x1d, 0x10, 0x37, 0xf1, 0x42, 0x37, 0xec, 0xef, 0x01, 0x27, 0xde, 0x35,
+ 0x06, 0x81, 0xeb, 0x7b, 0x8a, 0x17, 0xb7, 0x3b, 0xd9, 0xab, 0x08, 0x49,
+ 0xfe, 0x15, 0x7b, 0x70, 0x78, 0x87, 0xbe, 0x5d, 0xea, 0xe9, 0xeb, 0xad,
+ 0xe7, 0xe0, 0xff, 0x0b, 0xa9, 0xec, 0x91, 0xcb, 0x72, 0x76, 0xe6, 0xa2,
+ 0x4d, 0xfd, 0xa7, 0xdf, 0x78, 0x09, 0xb9, 0xa7, 0x25, 0x0b, 0x0d, 0xfa,
+ 0x4b, 0xe2, 0x62, 0xfe, 0xbf, 0xcb, 0x3a, 0xac, 0x33, 0x4f, 0xc0, 0x3b,
+ 0xcc, 0x1b, 0xbf, 0x4e, 0x39, 0xb7, 0x11, 0x76, 0xb8, 0xa0, 0xff, 0x62,
+ 0x03, 0x8f, 0x06, 0xad, 0xbd, 0x3a, 0xf7, 0xfb, 0x37, 0xec, 0xfb, 0x0e,
+ 0x68, 0x1d, 0x04, 0x2c, 0x62, 0x66, 0xba, 0x75, 0x8f, 0x57, 0xd4, 0x1e,
+ 0xc7, 0x1a, 0xc8, 0xf5, 0x56, 0xf7, 0xc0, 0x5c, 0x43, 0xc7, 0x39, 0x4d,
+ 0x25, 0x97, 0x2b, 0xa3, 0xe4, 0xef, 0x9e, 0x5e, 0xe6, 0x99, 0x46, 0xfe,
+ 0xaf, 0xfd, 0xa8, 0x7e, 0x7c, 0x7e, 0x7e, 0x12, 0xfe, 0xd9, 0xf7, 0x2f,
+ 0xec, 0x1a, 0x04, 0x0d, 0xa8, 0x43, 0xd3, 0xe4, 0xf9, 0xd9, 0x19, 0x17,
+ 0x38, 0x8a, 0x0a, 0xf7, 0x25, 0x59, 0x01, 0xee, 0x09, 0xf2, 0x01, 0xb8,
+ 0xe7, 0x38, 0xaf, 0x64, 0x80, 0xf9, 0x46, 0x06, 0x78, 0x23, 0xfd, 0x4c,
+ 0x42, 0xd7, 0x76, 0x5b, 0xb7, 0x07, 0xba, 0x9e, 0x60, 0x6c, 0x7b, 0x0e,
+ 0xba, 0x57, 0x48, 0x52, 0x7f, 0xda, 0x7b, 0xd7, 0xf4, 0xa7, 0x15, 0x7f,
+ 0xbb, 0x94, 0x16, 0x12, 0xc0, 0x6b, 0xca, 0x5c, 0x8e, 0x78, 0x31, 0xae,
+ 0x53, 0xf7, 0x2b, 0xa1, 0xee, 0x77, 0x86, 0xb8, 0x17, 0xc1, 0x93, 0x6c,
+ 0xa6, 0xae, 0xb3, 0x8e, 0xda, 0xa6, 0x6a, 0x5b, 0x03, 0x36, 0x5d, 0xae,
+ 0xb1, 0x0e, 0xe5, 0xfd, 0xc8, 0xa5, 0x99, 0x69, 0xd4, 0xaa, 0xe5, 0xda,
+ 0x88, 0x56, 0x6e, 0xda, 0x5a, 0xd9, 0xa3, 0xbe, 0xed, 0xb2, 0x2e, 0x28,
+ 0x1e, 0xa7, 0x65, 0xa9, 0xf9, 0x4b, 0xbf, 0xba, 0x6b, 0x13, 0xfa, 0xd0,
+ 0xfd, 0x09, 0xca, 0xf7, 0xb3, 0xa4, 0x0b, 0x41, 0x9c, 0xfc, 0x4e, 0xc9,
+ 0xc9, 0x21, 0x14, 0xbd, 0xc8, 0xad, 0x4e, 0x0d, 0x11, 0x3f, 0xe8, 0x48,
+ 0xa5, 0x64, 0xd9, 0xe3, 0x1e, 0x67, 0x67, 0xc8, 0xcb, 0xf2, 0x71, 0x4b,
+ 0x0e, 0x2b, 0xf9, 0xbd, 0xac, 0x6c, 0xbb, 0xbc, 0x62, 0xc8, 0x74, 0x72,
+ 0xd0, 0x7a, 0x58, 0xb2, 0x57, 0x2f, 0x18, 0xd9, 0x67, 0xa6, 0x60, 0xd7,
+ 0x4b, 0x8b, 0x86, 0xb8, 0xaa, 0xde, 0xa2, 0x8c, 0xb2, 0x0b, 0xb0, 0xfc,
+ 0xf0, 0xec, 0x7b, 0x5b, 0xce, 0xde, 0x2d, 0x2b, 0x4f, 0xff, 0x26, 0x7c,
+ 0xce, 0x01, 0xc8, 0xc2, 0xcc, 0x1c, 0x42, 0x5e, 0xf1, 0xb4, 0x0c, 0x5a,
+ 0x55, 0xe4, 0xc9, 0xe0, 0x3b, 0xda, 0x01, 0x65, 0x03, 0x17, 0x74, 0x8c,
+ 0x07, 0xc8, 0x27, 0x8e, 0xaf, 0x95, 0x0b, 0xca, 0x96, 0xd2, 0xea, 0xdd,
+ 0x0e, 0xe0, 0x08, 0xde, 0x71, 0xfc, 0x19, 0xd9, 0xa1, 0xde, 0xdd, 0xa9,
+ 0xde, 0x55, 0xe9, 0x2b, 0x94, 0xfc, 0xbe, 0x82, 0x3d, 0xc9, 0xe3, 0x68,
+ 0xbe, 0x4b, 0x02, 0x5b, 0x8a, 0xf8, 0x6e, 0xc9, 0xc1, 0x46, 0x4a, 0xbe,
+ 0x84, 0xfa, 0xe7, 0x8e, 0xc6, 0x80, 0x94, 0x20, 0xc7, 0xe9, 0xdc, 0x83,
+ 0xbd, 0x3c, 0x5b, 0x71, 0x25, 0xfb, 0x8c, 0xe8, 0xa4, 0xf5, 0x4e, 0x39,
+ 0xe4, 0x45, 0xf4, 0x74, 0x86, 0xf4, 0x4d, 0x86, 0xe3, 0x44, 0x48, 0x43,
+ 0x2b, 0xbe, 0x4e, 0xe0, 0x42, 0xac, 0xcf, 0x79, 0x21, 0x1e, 0xfa, 0x11,
+ 0xd0, 0x3a, 0x99, 0x96, 0x15, 0x8f, 0x74, 0x6c, 0x91, 0x6a, 0x8a, 0xfd,
+ 0x03, 0xd0, 0x37, 0xe2, 0xd9, 0xc4, 0x7c, 0x66, 0x1d, 0x8f, 0x1f, 0x6c,
+ 0x54, 0xc0, 0x63, 0xf2, 0x97, 0xeb, 0x10, 0x23, 0x3e, 0x47, 0xf9, 0xed,
+ 0x46, 0x2e, 0x6f, 0x07, 0xba, 0x69, 0xad, 0xed, 0x59, 0x3a, 0xde, 0x0d,
+ 0x59, 0x71, 0xdf, 0x0e, 0x99, 0x84, 0xdd, 0x17, 0xeb, 0xdc, 0x7f, 0x12,
+ 0x7a, 0x74, 0x51, 0xed, 0x5f, 0x5a, 0xe9, 0x0f, 0xe1, 0x09, 0xdb, 0xbd,
+ 0x01, 0xb6, 0x5d, 0xf6, 0x2e, 0x58, 0x1f, 0x01, 0xff, 0xbb, 0x80, 0xd7,
+ 0xe5, 0x44, 0x8e, 0xf0, 0xc4, 0x83, 0x75, 0xf5, 0xd4, 0x27, 0xe0, 0x49,
+ 0xaa, 0xba, 0xbe, 0x58, 0x6f, 0x97, 0xe2, 0x42, 0x84, 0x8b, 0x78, 0x3e,
+ 0x40, 0xdd, 0x7b, 0xb7, 0xc2, 0x35, 0xad, 0x70, 0xe1, 0x7d, 0x9d, 0x3e,
+ 0xe7, 0x26, 0xc0, 0xa3, 0x76, 0xb7, 0x41, 0x5b, 0xb2, 0x4b, 0xaa, 0xaa,
+ 0x76, 0xef, 0x50, 0xbe, 0xa6, 0x9a, 0xdc, 0x8c, 0xf7, 0x3e, 0xf6, 0xdc,
+ 0x8d, 0x7c, 0xa6, 0x1b, 0x73, 0x99, 0x0d, 0x73, 0x1b, 0xe9, 0x4f, 0x6c,
+ 0xa0, 0xff, 0xbf, 0x7b, 0x19, 0x52, 0xe6, 0x72, 0xc1, 0xba, 0x12, 0xd6,
+ 0xcd, 0x1e, 0x87, 0x4d, 0x30, 0x4f, 0x4f, 0x31, 0x36, 0x5f, 0xa3, 0x68,
+ 0x99, 0x5d, 0xf9, 0x29, 0xd6, 0xf5, 0x03, 0x36, 0x1a, 0x07, 0x7c, 0x78,
+ 0x0a, 0x78, 0x8e, 0xd7, 0xd5, 0x1d, 0x05, 0x64, 0xf0, 0xbe, 0x3a, 0x7b,
+ 0xb5, 0xfe, 0x69, 0x3c, 0xbb, 0xa6, 0x85, 0x5f, 0xe4, 0x15, 0xe9, 0x25,
+ 0xad, 0xbc, 0x2f, 0x82, 0xbd, 0x39, 0xd0, 0xe3, 0xa4, 0x21, 0xa5, 0x1c,
+ 0xe2, 0xba, 0xc7, 0xbb, 0x57, 0xda, 0xe5, 0x40, 0x50, 0x23, 0xd8, 0x8c,
+ 0xef, 0xa6, 0x3a, 0xfb, 0xa1, 0x15, 0xde, 0xbf, 0x66, 0x78, 0x47, 0x37,
+ 0x8c, 0xda, 0x5b, 0x1e, 0x5a, 0xb1, 0xe5, 0x6b, 0x8d, 0x61, 0x79, 0xb8,
+ 0x91, 0xb5, 0xee, 0x81, 0x0f, 0x28, 0xaf, 0xde, 0xcb, 0x6e, 0x4b, 0xd2,
+ 0x7f, 0x99, 0xc8, 0x3d, 0xdb, 0xec, 0x20, 0x17, 0xa9, 0xb2, 0x36, 0x3b,
+ 0x9e, 0xe5, 0x7d, 0x8d, 0x55, 0x97, 0x8d, 0xf9, 0xca, 0xff, 0x65, 0xae,
+ 0xc2, 0xfd, 0xe9, 0xaf, 0x91, 0x9b, 0x78, 0xc8, 0x4d, 0x3c, 0xe4, 0x26,
+ 0x1e, 0x72, 0x13, 0x0f, 0xb9, 0x89, 0x87, 0xdc, 0xc4, 0x43, 0x6e, 0xe2,
+ 0x21, 0x37, 0x41, 0x1d, 0x10, 0xd4, 0x07, 0xe3, 0xc8, 0xb9, 0xe1, 0xbf,
+ 0xbc, 0x5b, 0xc2, 0xdc, 0x22, 0x8a, 0xcd, 0x9c, 0x3b, 0xbf, 0xc9, 0x0d,
+ 0xea, 0x2b, 0xe5, 0x13, 0x0a, 0xcd, 0x89, 0x30, 0x07, 0xe2, 0x9a, 0x28,
+ 0x76, 0x73, 0x9d, 0x8c, 0xb9, 0xa8, 0x3d, 0x0b, 0x93, 0xcc, 0x91, 0x82,
+ 0x98, 0x15, 0xe4, 0xe7, 0xaf, 0x22, 0x4f, 0xca, 0x20, 0x4f, 0x1a, 0x40,
+ 0x4e, 0xc4, 0x7b, 0xea, 0xe8, 0x2e, 0xa9, 0xa0, 0x1d, 0xf4, 0xc6, 0xb5,
+ 0x2f, 0x79, 0xcc, 0xdf, 0xed, 0x4c, 0x59, 0xd7, 0x8f, 0xf7, 0x89, 0x2f,
+ 0xc5, 0xd1, 0xaf, 0x23, 0x57, 0xfe, 0x4b, 0x75, 0x6f, 0x36, 0x31, 0x44,
+ 0x99, 0xdf, 0xf7, 0x31, 0xf9, 0x72, 0xc4, 0xdf, 0xe0, 0xbe, 0x4f, 0x5f,
+ 0x22, 0xff, 0x44, 0x7a, 0xcf, 0x80, 0xe1, 0x67, 0x12, 0x92, 0x3c, 0xb9,
+ 0x05, 0x73, 0x96, 0xf4, 0xa9, 0x3b, 0x23, 0x88, 0xf2, 0xcc, 0x7f, 0x40,
+ 0x5e, 0xb6, 0xe8, 0x67, 0x78, 0xb3, 0x40, 0xbc, 0xf4, 0xaf, 0xf5, 0x99,
+ 0x62, 0xbd, 0xae, 0x74, 0xea, 0x60, 0xa3, 0x84, 0x3c, 0xca, 0xe8, 0x93,
+ 0x0e, 0x13, 0xb5, 0x54, 0x84, 0x9b, 0x38, 0xdf, 0x4c, 0xaa, 0x1a, 0xe7,
+ 0xcc, 0xaa, 0x3c, 0x21, 0x6b, 0xee, 0x53, 0x9f, 0xa9, 0x2e, 0x64, 0xd3,
+ 0xac, 0x71, 0x0b, 0x56, 0x7d, 0xe6, 0x49, 0xe0, 0x58, 0x46, 0x6e, 0x60,
+ 0xa8, 0xbd, 0xeb, 0x33, 0xb3, 0x0b, 0xc1, 0xbd, 0x55, 0x40, 0x03, 0xe3,
+ 0x55, 0x87, 0x18, 0x4b, 0xc1, 0xfd, 0x95, 0xae, 0x60, 0x09, 0x47, 0x78,
+ 0x13, 0x70, 0x94, 0xdb, 0x30, 0x60, 0x29, 0x3b, 0xd2, 0x50, 0x9f, 0xa9,
+ 0xd4, 0x5b, 0x69, 0x20, 0x1e, 0xe2, 0x8d, 0xce, 0xc3, 0xb3, 0x24, 0x45,
+ 0x3f, 0xe9, 0xfb, 0xe5, 0xd1, 0x81, 0xb0, 0xae, 0x44, 0x1d, 0x79, 0xcc,
+ 0x0c, 0xf4, 0x5c, 0x8d, 0xff, 0x58, 0xc5, 0xa9, 0x8c, 0xce, 0x79, 0x3e,
+ 0xf1, 0x2e, 0xf7, 0x28, 0xe6, 0x30, 0x5e, 0x8e, 0xd6, 0xea, 0xe1, 0xda,
+ 0xae, 0x16, 0x7e, 0xb6, 0x85, 0xfb, 0x91, 0x26, 0x9e, 0xf3, 0x15, 0xec,
+ 0x45, 0xba, 0xb8, 0xc6, 0x04, 0x6d, 0x90, 0xa5, 0xf7, 0xbf, 0xe5, 0x7d,
+ 0xeb, 0x99, 0xc8, 0x53, 0x13, 0x30, 0x5c, 0x4f, 0x1c, 0x11, 0x0c, 0x5e,
+ 0x9c, 0x09, 0xe0, 0xf4, 0xd5, 0x7b, 0xbe, 0x4f, 0xda, 0xb7, 0x95, 0xd6,
+ 0x68, 0xff, 0x08, 0xcf, 0x70, 0x20, 0xb7, 0x55, 0x78, 0xf5, 0x7f, 0x7f,
+ 0xe1, 0x09, 0x5d, 0xfc, 0xd0, 0x7d, 0xe9, 0x70, 0x4b, 0x8d, 0x1c, 0xdd,
+ 0x3b, 0xb0, 0xfe, 0x67, 0x3d, 0xcf, 0xef, 0x03, 0xad, 0xf5, 0x69, 0x29,
+ 0x8c, 0x65, 0xdb, 0xa4, 0x60, 0xb2, 0x56, 0x19, 0x0f, 0xc7, 0x5b, 0x11,
+ 0xdb, 0x38, 0xbe, 0x15, 0xfc, 0x85, 0x2e, 0x3b, 0x1d, 0x61, 0xad, 0x94,
+ 0x0c, 0xbe, 0xeb, 0x0c, 0xd3, 0x8e, 0x58, 0x6b, 0x6e, 0x0e, 0xe7, 0x22,
+ 0x3b, 0xa2, 0x1f, 0x36, 0xc3, 0x39, 0xfa, 0x5b, 0x1d, 0xf5, 0x12, 0xfb,
+ 0xc0, 0xb3, 0xdc, 0x6a, 0x4b, 0xd1, 0x33, 0x29, 0xa7, 0x17, 0x23, 0xbf,
+ 0x05, 0x9f, 0x32, 0x64, 0x86, 0xbe, 0xbf, 0x13, 0xbe, 0xaf, 0x5b, 0xf6,
+ 0xc2, 0x67, 0xed, 0x83, 0xcf, 0xda, 0x8f, 0x1a, 0x75, 0x7c, 0xa5, 0xf5,
+ 0x3e, 0x97, 0x75, 0x71, 0x55, 0x0e, 0x29, 0xf9, 0x57, 0x7c, 0xc3, 0xfe,
+ 0x00, 0x3a, 0xb0, 0x53, 0xe5, 0x7b, 0x81, 0x4e, 0xc0, 0xdf, 0x3a, 0x49,
+ 0xe8, 0xc4, 0xc6, 0x7b, 0xe3, 0x61, 0xd8, 0x46, 0x47, 0x41, 0xc5, 0x86,
+ 0x95, 0x80, 0xf7, 0xd5, 0x7a, 0xc0, 0x7b, 0xf8, 0x65, 0xe0, 0x37, 0xa5,
+ 0xd2, 0xb0, 0xa4, 0x82, 0x7d, 0x2b, 0xd8, 0xb7, 0x82, 0xda, 0x72, 0xb6,
+ 0xd1, 0xfa, 0xed, 0xaa, 0x2b, 0xa4, 0x9d, 0xb0, 0x51, 0xdf, 0x6a, 0x39,
+ 0x7f, 0xf4, 0x3c, 0x02, 0xfe, 0x3f, 0x02, 0xfe, 0x1f, 0x46, 0x4d, 0xf5,
+ 0x00, 0x6a, 0xaa, 0xfb, 0x50, 0x53, 0x1d, 0x42, 0x4d, 0x35, 0x85, 0x9a,
+ 0xea, 0x6e, 0xf8, 0x8f, 0x3b, 0xe1, 0x3f, 0x26, 0xe1, 0x3f, 0x26, 0xd4,
+ 0x9d, 0xd1, 0x41, 0x6f, 0xe3, 0x1d, 0x4a, 0xb4, 0x17, 0xdb, 0x1b, 0x22,
+ 0x50, 0x81, 0xf2, 0xb1, 0x71, 0xa9, 0x37, 0x59, 0x5b, 0x39, 0xea, 0x3e,
+ 0x6c, 0xda, 0x99, 0xd4, 0xa6, 0x90, 0xbf, 0xdf, 0x33, 0xc2, 0x9a, 0x2b,
+ 0xa9, 0x15, 0x55, 0xcd, 0x95, 0x7d, 0xc1, 0x45, 0x8a, 0x84, 0xdc, 0x0f,
+ 0x67, 0xce, 0x9e, 0x2e, 0x1a, 0x51, 0xbd, 0xd3, 0xbb, 0x5a, 0xef, 0x2c,
+ 0xcf, 0xb3, 0xde, 0x79, 0x75, 0xb5, 0xde, 0x59, 0x9e, 0x67, 0xbd, 0xf3,
+ 0xca, 0xba, 0x7a, 0xe7, 0xca, 0xd3, 0x97, 0xd6, 0xd5, 0x3b, 0x57, 0x9e,
+ 0x7e, 0x29, 0x1c, 0x4b, 0xa8, 0x0f, 0x21, 0xad, 0x96, 0x83, 0x67, 0x4f,
+ 0x98, 0x73, 0x34, 0xfb, 0xd6, 0xff, 0xdf, 0x74, 0xca, 0x96, 0x35, 0xb1,
+ 0xff, 0x68, 0x6b, 0x50, 0x23, 0xb5, 0xce, 0x77, 0xb7, 0xcc, 0x5f, 0x56,
+ 0xdf, 0x4b, 0xcb, 0xb5, 0xcd, 0xef, 0xc2, 0x03, 0xcb, 0xca, 0x10, 0xf3,
+ 0xbc, 0x0f, 0x7c, 0x7e, 0xf3, 0x73, 0xf5, 0x0e, 0xf5, 0xcd, 0xcd, 0x55,
+ 0xf9, 0x36, 0xec, 0x7c, 0xf4, 0xd1, 0xad, 0x81, 0x2f, 0x60, 0x3f, 0xa5,
+ 0x05, 0xfe, 0xfd, 0x01, 0xe0, 0x01, 0xaf, 0x3d, 0x53, 0xdd, 0x07, 0x05,
+ 0xe7, 0x0d, 0xee, 0xc6, 0xcd, 0xfc, 0xe5, 0x19, 0xe6, 0xd6, 0x55, 0x85,
+ 0x9b, 0xf5, 0x23, 0x6b, 0xce, 0x28, 0x06, 0x44, 0xb8, 0x5e, 0x4d, 0x05,
+ 0x74, 0xbb, 0xa8, 0x1d, 0xb9, 0x26, 0x1a, 0xb7, 0xd6, 0x9a, 0x9d, 0xe1,
+ 0xbd, 0xdb, 0xe5, 0x20, 0xaf, 0x52, 0xf8, 0xcc, 0x10, 0xdf, 0xcf, 0xfd,
+ 0xc0, 0xf7, 0x10, 0xde, 0x6a, 0x81, 0x1f, 0x47, 0xae, 0xc7, 0x7b, 0x1a,
+ 0xe6, 0x6c, 0xa6, 0xbc, 0x33, 0xdf, 0x25, 0xff, 0x79, 0xd4, 0xf7, 0x27,
+ 0x9c, 0xec, 0xf0, 0x25, 0xd4, 0x1e, 0x27, 0x69, 0x27, 0xa3, 0xa4, 0x73,
+ 0x30, 0x33, 0x2b, 0xa9, 0x3e, 0xd2, 0x72, 0x5e, 0x3f, 0xac, 0x7d, 0x98,
+ 0x6e, 0x3d, 0xdc, 0xe7, 0x1f, 0x5b, 0xf6, 0xc9, 0xb4, 0xec, 0x53, 0xa0,
+ 0xcd, 0xd6, 0xef, 0xc0, 0x99, 0x2b, 0xdb, 0xaf, 0xb7, 0x52, 0x61, 0x5d,
+ 0xf6, 0xf0, 0xe8, 0x66, 0x59, 0xe8, 0xcf, 0x9e, 0x7d, 0x05, 0xf9, 0x7a,
+ 0x79, 0x14, 0x73, 0xa9, 0x41, 0xbc, 0xe3, 0x7c, 0xb6, 0x8e, 0x5c, 0xf4,
+ 0x6c, 0x5d, 0xb6, 0x01, 0x3e, 0x5b, 0x11, 0xe1, 0x3c, 0xfb, 0x8a, 0xb6,
+ 0x7a, 0xe8, 0x03, 0xd2, 0x17, 0x70, 0xe6, 0x29, 0xd4, 0x5f, 0x87, 0x83,
+ 0x7b, 0xb4, 0x70, 0x9f, 0x1b, 0xb5, 0x20, 0x6f, 0xce, 0x69, 0x95, 0xf0,
+ 0x0e, 0xf0, 0x2b, 0xf0, 0x17, 0x86, 0x4e, 0xd8, 0x77, 0x80, 0x5b, 0x93,
+ 0xa5, 0xa3, 0x86, 0xba, 0x3b, 0x2d, 0x8f, 0x52, 0xd6, 0x7c, 0x7e, 0x14,
+ 0xef, 0xa2, 0x33, 0xfd, 0x4d, 0x78, 0xa6, 0xd1, 0xb0, 0x6e, 0x8f, 0xce,
+ 0x94, 0x90, 0xd7, 0xe7, 0x2d, 0xc0, 0x8e, 0x80, 0x1f, 0x25, 0x59, 0x69,
+ 0x66, 0x3e, 0x05, 0x4f, 0xad, 0x85, 0x37, 0xe6, 0x06, 0x19, 0x46, 0x75,
+ 0x0f, 0x78, 0x30, 0x91, 0x86, 0x1d, 0xde, 0xd7, 0x17, 0xdd, 0xe9, 0x1a,
+ 0xb6, 0xae, 0x05, 0x75, 0x3c, 0xe7, 0x07, 0x60, 0x8b, 0x19, 0xd8, 0x27,
+ 0x73, 0xa6, 0x12, 0x6b, 0x15, 0xda, 0x93, 0xe5, 0x1a, 0x59, 0x6b, 0x52,
+ 0x86, 0x51, 0xef, 0xf0, 0xfc, 0x79, 0x59, 0x6e, 0x46, 0x34, 0xe4, 0x60,
+ 0x8f, 0x63, 0xf8, 0x8d, 0xe0, 0x9d, 0x83, 0x1f, 0x6b, 0xa5, 0x82, 0x7c,
+ 0x55, 0xe5, 0xe2, 0xc8, 0xb5, 0x87, 0x48, 0xdf, 0x01, 0xac, 0xa7, 0x3e,
+ 0x53, 0x4f, 0x0f, 0x88, 0xdb, 0x4f, 0x5f, 0x91, 0x06, 0x6e, 0xc0, 0x78,
+ 0xaf, 0xc1, 0xd6, 0x07, 0xf0, 0xcc, 0x5a, 0x65, 0xf2, 0x56, 0xe1, 0xf7,
+ 0x7d, 0x23, 0xc7, 0x6f, 0x11, 0xe3, 0xe1, 0x78, 0xd0, 0xfa, 0x1d, 0xea,
+ 0x5e, 0xfa, 0x5a, 0x39, 0xbb, 0x18, 0xc5, 0xc1, 0x19, 0xd8, 0x20, 0xef,
+ 0x68, 0xc7, 0xc1, 0x17, 0x8e, 0xb5, 0x30, 0x1e, 0x62, 0x7e, 0xf9, 0xaf,
+ 0x70, 0xee, 0xbc, 0x9c, 0x44, 0xfd, 0x2f, 0xfd, 0x7c, 0x66, 0x80, 0x7f,
+ 0x4b, 0xa8, 0xef, 0xeb, 0xe1, 0x0d, 0x9b, 0xfd, 0x71, 0xd0, 0x67, 0xb6,
+ 0xc0, 0x13, 0x26, 0xac, 0x4f, 0x04, 0xf1, 0x38, 0xed, 0xdf, 0xaa, 0xe7,
+ 0xef, 0x96, 0x3f, 0x50, 0x67, 0xca, 0xcb, 0xa1, 0x45, 0xdf, 0x77, 0x73,
+ 0x83, 0xc3, 0xcb, 0x92, 0x1d, 0x7e, 0x52, 0x76, 0x5b, 0x7b, 0x59, 0x8f,
+ 0x59, 0xc4, 0xe3, 0xdf, 0xda, 0x96, 0xf7, 0xfd, 0x13, 0xa0, 0xfd, 0x07,
+ 0x6a, 0x9f, 0xbb, 0x41, 0x3f, 0x78, 0xa5, 0x6a, 0x12, 0xd2, 0x0a, 0xde,
+ 0xa4, 0x48, 0x6f, 0xa7, 0x1c, 0x6a, 0x3e, 0x1f, 0xca, 0xe6, 0x11, 0x71,
+ 0xbd, 0xb7, 0x0d, 0xde, 0x6f, 0x97, 0x9b, 0x8f, 0x86, 0xb4, 0xe5, 0x41,
+ 0x2f, 0xf6, 0x6f, 0xfe, 0x43, 0x8a, 0xbe, 0x81, 0x32, 0x77, 0x91, 0x35,
+ 0xba, 0xa3, 0xcf, 0x40, 0x07, 0x3f, 0xce, 0x0f, 0x24, 0x65, 0xbd, 0x1f,
+ 0x20, 0x5c, 0xf2, 0x23, 0x74, 0x85, 0x74, 0x88, 0xf2, 0x9f, 0x2a, 0x6e,
+ 0x29, 0x7c, 0xc6, 0x06, 0x5f, 0xf0, 0xa4, 0x7a, 0x9e, 0x37, 0xe8, 0x9b,
+ 0x18, 0xff, 0xa8, 0xc3, 0xdd, 0xf0, 0x7f, 0xd0, 0x41, 0xd8, 0x71, 0x71,
+ 0x91, 0xf7, 0x13, 0x43, 0xea, 0x4e, 0xab, 0x04, 0xd9, 0x2e, 0xf1, 0x3b,
+ 0x63, 0x2a, 0xc8, 0x27, 0x83, 0xfa, 0x2b, 0x43, 0x5f, 0x88, 0xf6, 0xb8,
+ 0xf2, 0x93, 0x25, 0xf5, 0x5d, 0x31, 0x89, 0x35, 0x3e, 0x9e, 0xad, 0x7f,
+ 0x27, 0xf1, 0xa3, 0x42, 0xf0, 0x77, 0x12, 0xe1, 0x37, 0xde, 0x7a, 0x90,
+ 0x47, 0x3c, 0xd8, 0x30, 0x65, 0xaa, 0x11, 0xfd, 0xdd, 0x04, 0xe5, 0x60,
+ 0x4b, 0xb9, 0x11, 0xe5, 0x0e, 0x7e, 0x50, 0xd3, 0xac, 0x93, 0xe5, 0xe3,
+ 0x61, 0x4e, 0xc4, 0x1a, 0x80, 0x3c, 0xc4, 0x78, 0x39, 0x90, 0xdf, 0x92,
+ 0xbe, 0x03, 0xf2, 0x03, 0xcf, 0x3d, 0x13, 0xb6, 0x94, 0x0e, 0xe3, 0xba,
+ 0xc5, 0x1a, 0x33, 0xac, 0x7b, 0xb7, 0x4b, 0x75, 0x92, 0xef, 0x13, 0xf2,
+ 0xda, 0xfc, 0x40, 0x70, 0x4f, 0x24, 0x89, 0xf0, 0x3d, 0xc7, 0x49, 0x29,
+ 0xab, 0xf7, 0x77, 0x86, 0xf8, 0x50, 0xa7, 0xdd, 0x19, 0x8d, 0xd3, 0x90,
+ 0x63, 0x00, 0x37, 0x8d, 0x58, 0xf6, 0x55, 0xc4, 0xb1, 0x69, 0xf0, 0xbd,
+ 0x38, 0x51, 0x91, 0x6b, 0x6d, 0x4b, 0xc5, 0x7d, 0x37, 0x49, 0x1d, 0xa3,
+ 0x7e, 0x11, 0xa6, 0x07, 0xb9, 0x2a, 0xce, 0x3b, 0x2a, 0x53, 0x46, 0xfe,
+ 0xdd, 0xdb, 0xca, 0xb5, 0xac, 0x55, 0x90, 0xf7, 0x7d, 0xd7, 0xe4, 0xf8,
+ 0xfc, 0x6d, 0x0f, 0x06, 0x77, 0xfe, 0xba, 0x9e, 0xbf, 0x78, 0x5b, 0x39,
+ 0xe8, 0xe3, 0xcc, 0xef, 0x86, 0x7d, 0xc2, 0x19, 0xea, 0x7b, 0xec, 0x4f,
+ 0x6e, 0x32, 0xe5, 0xc2, 0x4d, 0xbe, 0x7f, 0x0f, 0xbf, 0x09, 0x85, 0x75,
+ 0xac, 0xa5, 0xea, 0xd8, 0x0e, 0x95, 0x8f, 0xb8, 0xa3, 0x19, 0xad, 0x04,
+ 0xdb, 0x3d, 0xe9, 0xa1, 0xe6, 0xd1, 0xb3, 0x63, 0xe7, 0x75, 0x0b, 0xf1,
+ 0x37, 0x9b, 0x39, 0x2e, 0xb9, 0x3e, 0x7e, 0x63, 0x9e, 0x73, 0xb8, 0x66,
+ 0x5b, 0x70, 0xef, 0x75, 0x83, 0xab, 0x7c, 0xae, 0x48, 0x18, 0x87, 0x6e,
+ 0x68, 0xb5, 0x8f, 0xd6, 0x3c, 0x93, 0x76, 0x21, 0x53, 0x26, 0xe8, 0xa9,
+ 0xd6, 0xa2, 0x9c, 0x8d, 0x7f, 0x0f, 0x70, 0xfe, 0xb6, 0xa7, 0x1a, 0x17,
+ 0x6f, 0x9b, 0x85, 0x7c, 0x78, 0xa6, 0xd9, 0x46, 0xa4, 0x7f, 0x51, 0xdd,
+ 0xc0, 0x3e, 0xe2, 0xbf, 0x87, 0xf8, 0xef, 0x21, 0xfe, 0x7b, 0x88, 0xff,
+ 0x1e, 0xe2, 0xbf, 0x87, 0xf8, 0x0f, 0x1e, 0x3e, 0x07, 0x7d, 0x79, 0xd6,
+ 0x9b, 0x08, 0x73, 0xb6, 0xc7, 0x56, 0x73, 0x36, 0xfe, 0xcd, 0xcb, 0xb9,
+ 0xa6, 0xa2, 0xa5, 0x52, 0x91, 0x20, 0xe7, 0x15, 0x9d, 0xf9, 0x4d, 0x94,
+ 0xf3, 0x7e, 0xf4, 0xf7, 0x90, 0x00, 0x8e, 0xf9, 0x1e, 0xe1, 0x2a, 0x9a,
+ 0x6e, 0x13, 0x2e, 0xc8, 0xf9, 0x58, 0x67, 0xad, 0x87, 0xe1, 0x77, 0x37,
+ 0xfa, 0xb6, 0xe0, 0x9b, 0x4f, 0xf0, 0x7d, 0xa9, 0x76, 0x87, 0x8b, 0x58,
+ 0x5c, 0x6e, 0xa8, 0x78, 0x8c, 0x71, 0xe3, 0x0e, 0xfe, 0xad, 0x02, 0x64,
+ 0xc0, 0x77, 0x5f, 0x66, 0x6d, 0x51, 0x6e, 0x20, 0x2f, 0x5a, 0x8e, 0x72,
+ 0x21, 0xc0, 0x79, 0x6f, 0x6a, 0xa5, 0x05, 0xca, 0x59, 0x97, 0xd9, 0x14,
+ 0x98, 0x62, 0xb7, 0xe6, 0x78, 0x97, 0x54, 0xbd, 0x74, 0xb6, 0x49, 0x7a,
+ 0x46, 0x40, 0x5b, 0x74, 0x8f, 0x2c, 0x62, 0xcc, 0xa7, 0x44, 0x9f, 0x47,
+ 0x7e, 0x6b, 0x0f, 0xa9, 0xbf, 0x6f, 0xe8, 0xc5, 0x3e, 0xfa, 0xfc, 0x8e,
+ 0x96, 0x7b, 0x5a, 0x29, 0x04, 0x3e, 0x9b, 0xb1, 0x87, 0xe7, 0x48, 0xc1,
+ 0x76, 0xdd, 0x6d, 0x38, 0x1b, 0xe4, 0xfa, 0xaf, 0x5b, 0x55, 0x0e, 0x0e,
+ 0x3f, 0x7a, 0x62, 0xa8, 0xbf, 0x5f, 0xba, 0xb7, 0xcb, 0xc9, 0x21, 0xd6,
+ 0x6b, 0x9b, 0x81, 0x8f, 0x6b, 0x79, 0xff, 0xb4, 0x5d, 0x4e, 0x2d, 0xc2,
+ 0xcf, 0x2e, 0x66, 0x1d, 0xea, 0xf2, 0xd2, 0x50, 0x0a, 0xfe, 0xf9, 0xe6,
+ 0x7e, 0xc6, 0xe7, 0xe5, 0x26, 0x75, 0xa5, 0x17, 0xf0, 0x03, 0xd0, 0xcb,
+ 0x4d, 0xb0, 0x27, 0x1d, 0xfb, 0x47, 0xb8, 0xff, 0x45, 0xe1, 0xee, 0xb5,
+ 0x9d, 0x6d, 0x4a, 0x37, 0xf4, 0xac, 0x95, 0xd1, 0x41, 0xfb, 0xff, 0x14,
+ 0x6e, 0x6d, 0x31, 0x71, 0x5c, 0x67, 0xf8, 0x3f, 0xb3, 0xdc, 0x8c, 0xd7,
+ 0x30, 0x86, 0xf5, 0xb2, 0x58, 0xae, 0xba, 0x03, 0x63, 0x33, 0xd1, 0x62,
+ 0x65, 0xb0, 0xec, 0x16, 0x55, 0x96, 0xba, 0xda, 0x05, 0x42, 0xe2, 0x3a,
+ 0xdd, 0x24, 0xb4, 0x72, 0xd5, 0x2a, 0x42, 0x60, 0x37, 0x8e, 0xfa, 0xd2,
+ 0x46, 0x55, 0xdb, 0x37, 0xaf, 0x16, 0xec, 0x38, 0xcd, 0xac, 0x17, 0x37,
+ 0x38, 0xf4, 0x71, 0xb3, 0x2c, 0x0e, 0x90, 0x75, 0x56, 0x6e, 0xf2, 0x90,
+ 0x3e, 0x19, 0x6d, 0xa2, 0x24, 0x55, 0xa5, 0xbc, 0x54, 0x7d, 0xab, 0x5a,
+ 0x0b, 0x27, 0xc4, 0x0f, 0xa9, 0xad, 0xf6, 0xa5, 0x77, 0x4d, 0xbf, 0xef,
+ 0xcc, 0x2c, 0xc6, 0xa4, 0x51, 0x91, 0x56, 0x73, 0xe6, 0xcc, 0xb9, 0x9f,
+ 0xff, 0xf2, 0xfd, 0x17, 0x3e, 0x67, 0x67, 0xba, 0xc2, 0xbd, 0xcd, 0x95,
+ 0x76, 0xc6, 0xfe, 0xb6, 0xd4, 0xcc, 0x02, 0xf3, 0x1a, 0x86, 0x64, 0xdc,
+ 0x64, 0xae, 0xcf, 0x96, 0x3a, 0x57, 0x66, 0x1b, 0x1b, 0x65, 0xda, 0xe4,
+ 0x4b, 0x6a, 0xa6, 0xdc, 0x23, 0x17, 0x41, 0xc7, 0x85, 0xe1, 0xd6, 0xd0,
+ 0xf7, 0xda, 0x19, 0xf2, 0x73, 0x77, 0x3c, 0xd4, 0x57, 0x1a, 0x57, 0x16,
+ 0x34, 0xb6, 0xee, 0xde, 0xf5, 0xed, 0x49, 0xac, 0x29, 0x41, 0x5f, 0x79,
+ 0x5c, 0xcb, 0x26, 0x83, 0xef, 0x7d, 0xbb, 0xde, 0xe3, 0xbb, 0xde, 0x0f,
+ 0xfc, 0x8f, 0xf6, 0x2c, 0xef, 0xa6, 0x07, 0xae, 0xd3, 0x1a, 0xe5, 0x2c,
+ 0x05, 0xcf, 0x36, 0x66, 0x3d, 0x2b, 0x4d, 0x5c, 0x90, 0x15, 0x5f, 0x65,
+ 0xdd, 0x36, 0xc8, 0xbb, 0x36, 0x99, 0x5f, 0x04, 0xcd, 0x63, 0x1f, 0xed,
+ 0x36, 0x63, 0xe4, 0x43, 0x71, 0xf2, 0x4c, 0x07, 0xae, 0xc1, 0xb0, 0x07,
+ 0x13, 0x68, 0xe7, 0x3f, 0xef, 0xa6, 0xcc, 0xb3, 0xda, 0x97, 0x43, 0x3c,
+ 0xe3, 0xab, 0x82, 0xce, 0xf7, 0x60, 0x9b, 0x16, 0xb9, 0x63, 0x67, 0x7a,
+ 0xc2, 0x7c, 0x20, 0xd8, 0xbe, 0x5f, 0x8d, 0x13, 0x6b, 0x3c, 0xe7, 0x6e,
+ 0xd7, 0x99, 0x9b, 0xc2, 0x1c, 0x2b, 0x10, 0xcd, 0x53, 0x22, 0xe5, 0xaa,
+ 0xc8, 0xeb, 0xf8, 0xfd, 0xa6, 0x1a, 0xc6, 0x4f, 0x14, 0xed, 0xee, 0x93,
+ 0xb2, 0x5e, 0xfa, 0x9a, 0xd4, 0xa0, 0x7f, 0xd6, 0x5c, 0xdf, 0xbf, 0xeb,
+ 0x26, 0xf5, 0x99, 0xbf, 0xe8, 0x29, 0x19, 0x18, 0xa1, 0x7e, 0x6b, 0x93,
+ 0x97, 0x17, 0x5b, 0x64, 0xc3, 0xb4, 0xcc, 0xbb, 0x44, 0x01, 0x5e, 0x42,
+ 0x26, 0x63, 0x11, 0x8d, 0x51, 0xe5, 0x5b, 0x22, 0x5b, 0xf8, 0xb6, 0xb5,
+ 0xf8, 0x4c, 0x9c, 0xfe, 0x97, 0x4f, 0x16, 0xf9, 0x6e, 0xe0, 0x69, 0x48,
+ 0xc3, 0x8e, 0x00, 0xcb, 0x42, 0x08, 0x99, 0x3c, 0x77, 0xee, 0xf7, 0xbb,
+ 0x5c, 0x1b, 0xea, 0x68, 0xcf, 0xb6, 0x49, 0xe1, 0x30, 0x64, 0xa2, 0x1a,
+ 0xd4, 0x39, 0x47, 0x8d, 0x98, 0x96, 0xd1, 0x91, 0x0a, 0x7d, 0xf8, 0xe6,
+ 0x5e, 0x2d, 0xaf, 0x33, 0x37, 0x7e, 0xa4, 0xf7, 0x82, 0x72, 0xbe, 0xe2,
+ 0x92, 0x56, 0x4d, 0x59, 0x03, 0xaf, 0xad, 0xd6, 0x5f, 0xed, 0xe3, 0x5d,
+ 0xad, 0xd7, 0x5f, 0x88, 0x07, 0xf6, 0x1a, 0xeb, 0x7e, 0x1c, 0x0f, 0xea,
+ 0x92, 0xa1, 0xfd, 0x45, 0x3b, 0xad, 0x8c, 0xbd, 0xbd, 0x20, 0xf5, 0xa5,
+ 0x9f, 0xc9, 0x3b, 0xa5, 0x9f, 0xc8, 0xaf, 0x97, 0xce, 0x00, 0x7f, 0x58,
+ 0xe5, 0x3c, 0xf4, 0xc9, 0xcd, 0xba, 0xef, 0xdf, 0x74, 0xa7, 0x60, 0x2b,
+ 0xf8, 0xfe, 0xef, 0xdc, 0x0d, 0x19, 0x38, 0xf6, 0x3d, 0xec, 0x39, 0x07,
+ 0x1e, 0xa2, 0x2c, 0x9c, 0x04, 0xbd, 0xb9, 0x7d, 0xd2, 0x19, 0xd5, 0x74,
+ 0x32, 0x78, 0xac, 0x15, 0x7b, 0x30, 0x42, 0x4c, 0xce, 0xbd, 0x8c, 0xf4,
+ 0x91, 0x66, 0x8c, 0x7a, 0x09, 0xf3, 0xb7, 0x82, 0x2f, 0xf6, 0xe2, 0xa7,
+ 0xe4, 0xee, 0x08, 0xd6, 0x3a, 0x42, 0xda, 0x6b, 0x95, 0x81, 0x47, 0xb1,
+ 0x8f, 0x5c, 0x8b, 0xdc, 0xf3, 0x7e, 0x19, 0xa7, 0x6f, 0xef, 0x9e, 0xc7,
+ 0xb2, 0xf1, 0x95, 0x2e, 0xf1, 0xa5, 0x05, 0xba, 0x7c, 0xfe, 0x78, 0x80,
+ 0x9b, 0xde, 0x55, 0x43, 0x68, 0x6f, 0xe7, 0xdf, 0x53, 0xc4, 0x79, 0x79,
+ 0xbf, 0x15, 0xb8, 0x7c, 0x1c, 0x78, 0x28, 0x53, 0xbf, 0x20, 0x8d, 0x91,
+ 0x28, 0xda, 0x10, 0xaf, 0x68, 0x59, 0x22, 0x59, 0x8f, 0x39, 0x5a, 0xcc,
+ 0x97, 0xc2, 0x1a, 0xa7, 0x74, 0x2e, 0x57, 0x1f, 0xcf, 0x9c, 0x58, 0x3e,
+ 0xa8, 0xb3, 0x41, 0x23, 0xac, 0x23, 0x7d, 0xa7, 0x35, 0xa6, 0x82, 0x0e,
+ 0xc5, 0x78, 0xc3, 0x92, 0xd1, 0xe5, 0x2e, 0x8c, 0x77, 0x41, 0x32, 0x6e,
+ 0x73, 0xcc, 0x51, 0xb4, 0xa1, 0x9c, 0x19, 0x05, 0x96, 0xf8, 0x58, 0x8d,
+ 0x2d, 0xc6, 0xa0, 0xcb, 0xe3, 0x32, 0x66, 0xee, 0xd9, 0xb1, 0xc7, 0xbc,
+ 0xb6, 0x15, 0x0c, 0x63, 0x38, 0x5c, 0x53, 0xd7, 0x8e, 0x35, 0xb1, 0x3f,
+ 0x7e, 0xb0, 0x93, 0x33, 0x8b, 0x0b, 0x90, 0x53, 0x0b, 0x1f, 0x66, 0xdc,
+ 0x67, 0x25, 0x1b, 0x6b, 0xd3, 0xb6, 0x4d, 0x05, 0xf7, 0x92, 0xf5, 0xe8,
+ 0xd3, 0xfa, 0x0e, 0xe4, 0xd0, 0x9e, 0xb0, 0x8e, 0x6d, 0xc5, 0xc8, 0xe0,
+ 0xec, 0x03, 0x1b, 0x97, 0x75, 0x5f, 0x96, 0xcc, 0x42, 0x4e, 0x26, 0x74,
+ 0x3f, 0x9e, 0xe1, 0x41, 0x8d, 0x43, 0xc8, 0xab, 0x03, 0xbd, 0x38, 0xcb,
+ 0xd4, 0x03, 0x7b, 0x38, 0xd9, 0x4b, 0x2e, 0xfa, 0x4f, 0xc8, 0xb3, 0xf8,
+ 0xd6, 0xcb, 0x3b, 0x6a, 0x93, 0x81, 0x67, 0xa0, 0x2f, 0xbd, 0x66, 0x7d,
+ 0x54, 0x3e, 0xf3, 0xfc, 0x38, 0x63, 0x2e, 0x7f, 0xf6, 0x4c, 0xf9, 0xc4,
+ 0xd3, 0xb1, 0xd8, 0xe9, 0x88, 0x58, 0xe7, 0x03, 0x5b, 0xfd, 0xf0, 0xf4,
+ 0xbc, 0xe2, 0xf7, 0xc3, 0xe7, 0x57, 0x54, 0x07, 0xda, 0x46, 0xd1, 0x8e,
+ 0xeb, 0x30, 0x65, 0xdc, 0xfb, 0xab, 0x3f, 0x73, 0xc4, 0xf7, 0x27, 0x74,
+ 0x4e, 0x58, 0xca, 0x9c, 0x57, 0x4d, 0x7c, 0xee, 0x88, 0x17, 0x6b, 0xc7,
+ 0x5c, 0x29, 0x73, 0x45, 0x1d, 0xc6, 0x7a, 0x58, 0xee, 0x25, 0x4f, 0x24,
+ 0x36, 0x84, 0xe3, 0x5b, 0x93, 0xcb, 0x2a, 0x95, 0x1c, 0x54, 0x56, 0xba,
+ 0x80, 0x5f, 0x8b, 0xd2, 0x71, 0xcc, 0x44, 0x52, 0x81, 0x77, 0xb1, 0x27,
+ 0xfb, 0xa8, 0xef, 0x4f, 0xda, 0xac, 0x4f, 0x99, 0x51, 0x45, 0xdf, 0x4b,
+ 0xa7, 0x8e, 0x77, 0x5e, 0x3e, 0x90, 0x32, 0x8f, 0xaa, 0xfd, 0xe1, 0xfb,
+ 0x28, 0x64, 0xe6, 0xf6, 0x78, 0x67, 0x96, 0x95, 0x29, 0x2f, 0x79, 0xa9,
+ 0xe4, 0xac, 0xb2, 0x72, 0x18, 0x33, 0x37, 0xa6, 0x28, 0x37, 0x52, 0x66,
+ 0xa7, 0xa2, 0x7f, 0xb4, 0x5d, 0xef, 0x7b, 0x12, 0xfd, 0x53, 0xaa, 0x25,
+ 0x5c, 0x0f, 0xef, 0xeb, 0x4a, 0x5f, 0xc0, 0x33, 0x94, 0x39, 0xfd, 0xc6,
+ 0xcc, 0x02, 0xf3, 0xcb, 0x74, 0x5e, 0x43, 0x7a, 0xe0, 0x18, 0xdf, 0x0d,
+ 0xb9, 0x7f, 0xe2, 0x6f, 0xa8, 0x43, 0xb9, 0xcc, 0x3a, 0x27, 0xe4, 0xb7,
+ 0x23, 0x1a, 0x3f, 0xdf, 0x3f, 0x91, 0xd7, 0xb9, 0x8b, 0x0d, 0x35, 0x10,
+ 0xee, 0x7b, 0xfb, 0xce, 0x92, 0x19, 0xf7, 0x4b, 0x1c, 0x67, 0x21, 0x72,
+ 0xb2, 0x5d, 0x98, 0x23, 0x3a, 0x5e, 0x6a, 0xd2, 0x06, 0x7d, 0x03, 0xcc,
+ 0x15, 0x68, 0xc6, 0xdd, 0x2f, 0x88, 0x71, 0xac, 0x63, 0x07, 0x9d, 0x00,
+ 0x77, 0x02, 0xaf, 0x56, 0x31, 0x4e, 0x61, 0x51, 0xf2, 0x41, 0x7f, 0xe9,
+ 0x60, 0x4e, 0x6a, 0xa1, 0xfa, 0x45, 0x63, 0x04, 0x3a, 0x70, 0x1c, 0xef,
+ 0xf7, 0x4f, 0x90, 0x3e, 0x79, 0x36, 0x49, 0x35, 0xbe, 0xc4, 0xf5, 0x1c,
+ 0x94, 0x89, 0x45, 0x60, 0x23, 0xfc, 0xe6, 0x17, 0x83, 0x7b, 0xbb, 0x0e,
+ 0x9c, 0x3d, 0xe1, 0x99, 0x9a, 0x5f, 0x67, 0x5d, 0xc6, 0x4f, 0xc0, 0x2b,
+ 0x3a, 0x8f, 0x8a, 0x7d, 0x99, 0x4b, 0x78, 0x88, 0xfa, 0xd1, 0x6d, 0x48,
+ 0x0c, 0x6d, 0x89, 0x59, 0x59, 0x6f, 0x8d, 0x26, 0x23, 0xdd, 0x32, 0x0f,
+ 0x79, 0x57, 0x81, 0xee, 0x2c, 0x5c, 0x89, 0xca, 0xac, 0xa7, 0xe3, 0xd9,
+ 0xc9, 0x8f, 0x95, 0x2b, 0xb5, 0xfa, 0x71, 0xb9, 0x51, 0x77, 0xf4, 0x37,
+ 0xea, 0xb5, 0xc2, 0xab, 0x86, 0x7c, 0xff, 0x88, 0xce, 0xa5, 0x73, 0x2a,
+ 0xd2, 0xd9, 0x4f, 0xcc, 0xb3, 0xa2, 0xf3, 0xea, 0x20, 0x3b, 0x80, 0x39,
+ 0xde, 0x06, 0xe6, 0x78, 0x0b, 0x98, 0xe3, 0x57, 0xc0, 0xd8, 0x37, 0x4b,
+ 0x93, 0xa1, 0xfc, 0x9f, 0x86, 0x1c, 0xa2, 0xae, 0xb6, 0xce, 0xe0, 0x4e,
+ 0xa7, 0xf3, 0xa0, 0xc1, 0xdb, 0xb0, 0x3f, 0xd6, 0x4b, 0x19, 0x59, 0x5d,
+ 0x9a, 0x90, 0xb5, 0xa5, 0x20, 0x0f, 0xf9, 0x03, 0xe6, 0x7d, 0x8d, 0xf0,
+ 0x9e, 0x1c, 0xc8, 0xa1, 0x3d, 0x32, 0x70, 0x94, 0xf2, 0xa3, 0x43, 0x96,
+ 0x8b, 0xab, 0x5a, 0x0e, 0x2d, 0x17, 0x59, 0x8e, 0x88, 0xce, 0x21, 0x9b,
+ 0xda, 0x90, 0x8a, 0x5b, 0x47, 0xfd, 0x3e, 0xed, 0x0f, 0x0a, 0xfc, 0xf3,
+ 0x94, 0x97, 0x7f, 0x0a, 0xef, 0x5e, 0xe9, 0xdc, 0xba, 0x19, 0xb3, 0x1b,
+ 0xed, 0x9a, 0xb2, 0x6b, 0x30, 0x88, 0xb9, 0xab, 0xdb, 0x68, 0x83, 0x39,
+ 0x80, 0x19, 0xaf, 0x43, 0x87, 0x34, 0x9c, 0x6e, 0x8d, 0xfd, 0x1a, 0xce,
+ 0x21, 0x9d, 0x77, 0xcb, 0x71, 0x0a, 0x45, 0x5b, 0xe6, 0x8a, 0x56, 0x32,
+ 0x0f, 0xfa, 0xbb, 0x01, 0xbb, 0x6d, 0x15, 0x77, 0xb0, 0x86, 0x33, 0x58,
+ 0xaf, 0x53, 0xcf, 0x6f, 0x6a, 0xd9, 0xbb, 0x5c, 0xff, 0x23, 0xc6, 0xb1,
+ 0xce, 0xa4, 0xe5, 0x0f, 0x7d, 0x94, 0x81, 0xf4, 0x4d, 0x65, 0x75, 0xff,
+ 0xa0, 0xdf, 0x2a, 0xda, 0xae, 0xd5, 0x29, 0x8f, 0x45, 0x2e, 0x79, 0x36,
+ 0x74, 0xc9, 0xcb, 0x09, 0x62, 0x80, 0xb2, 0x6a, 0xf6, 0xf3, 0xc3, 0x35,
+ 0xfb, 0xfe, 0x5e, 0x9b, 0xeb, 0x72, 0x42, 0xb9, 0x4d, 0xdd, 0xbf, 0xa1,
+ 0xb1, 0x8d, 0x57, 0x7a, 0x56, 0xde, 0xc4, 0x7d, 0x07, 0x18, 0x27, 0x27,
+ 0x6f, 0x00, 0xe3, 0xd5, 0x4b, 0xcd, 0xbc, 0xed, 0x93, 0x38, 0xa7, 0x92,
+ 0x9a, 0xbb, 0xda, 0x29, 0x97, 0xaf, 0x15, 0xd4, 0x4b, 0xd7, 0x3c, 0xf5,
+ 0xf3, 0xab, 0x45, 0x55, 0xb8, 0xea, 0xfb, 0xff, 0x70, 0x67, 0xe4, 0x9d,
+ 0x25, 0x5f, 0x4e, 0xbb, 0x46, 0x7f, 0x44, 0x9a, 0xf9, 0x74, 0xbe, 0xdf,
+ 0x01, 0xd9, 0xbc, 0x7e, 0xc0, 0xf7, 0x1f, 0x19, 0x19, 0x11, 0xe7, 0x00,
+ 0x31, 0xca, 0x70, 0x82, 0x39, 0xae, 0x94, 0x39, 0x19, 0xdb, 0x3e, 0x5f,
+ 0x51, 0x0a, 0xf2, 0xad, 0x3b, 0xc0, 0x2f, 0x8f, 0xee, 0x0b, 0xe3, 0x26,
+ 0x3f, 0x7c, 0x9e, 0x7e, 0xe5, 0xc4, 0xe7, 0xfc, 0xca, 0xa6, 0x9c, 0x2d,
+ 0xf6, 0xa2, 0x7f, 0x4c, 0x7e, 0x50, 0x8c, 0xee, 0x2a, 0x9b, 0x78, 0x3a,
+ 0x46, 0xa1, 0x78, 0xcf, 0x1f, 0xd4, 0xf1, 0x03, 0x60, 0x12, 0xd3, 0xf7,
+ 0x67, 0x5d, 0xce, 0xd7, 0x8d, 0xf9, 0x36, 0xcc, 0x7d, 0xd0, 0xff, 0xa7,
+ 0xb5, 0x7e, 0x2e, 0x2b, 0xd8, 0xc1, 0xe0, 0xef, 0x98, 0x8c, 0x15, 0xa1,
+ 0xe3, 0x15, 0xf3, 0x4c, 0x89, 0x15, 0xac, 0xc4, 0x2c, 0x64, 0xc7, 0x0c,
+ 0xe4, 0xcd, 0x29, 0x1d, 0x67, 0xed, 0xd5, 0xb2, 0x67, 0x8e, 0xe5, 0x9c,
+ 0xa4, 0x2b, 0x6e, 0x8f, 0x3e, 0xbf, 0xcd, 0x1b, 0x2f, 0x26, 0x82, 0x3b,
+ 0x07, 0x1f, 0xe7, 0x94, 0xb4, 0xc1, 0x1e, 0xca, 0xae, 0x4c, 0x81, 0x27,
+ 0x12, 0x38, 0xdb, 0x56, 0xcd, 0x0f, 0x0d, 0xe8, 0xef, 0x86, 0xf6, 0x29,
+ 0x06, 0xb1, 0x8b, 0x86, 0xc9, 0x76, 0xa7, 0xd0, 0xaf, 0x5d, 0x32, 0x57,
+ 0xdb, 0xb4, 0x5c, 0x7d, 0xb8, 0x2e, 0x0d, 0x1c, 0xf2, 0x04, 0xca, 0x11,
+ 0xd4, 0x25, 0xc3, 0xb2, 0x81, 0xf2, 0x34, 0xca, 0x2d, 0x78, 0xb2, 0xcd,
+ 0x61, 0xe0, 0x0a, 0x3c, 0x5f, 0xc3, 0x78, 0x23, 0x58, 0x73, 0xce, 0x94,
+ 0x8f, 0x4e, 0x50, 0x97, 0x38, 0x06, 0x73, 0x91, 0x67, 0x6d, 0x3c, 0x6b,
+ 0x45, 0x95, 0x5d, 0x60, 0x19, 0xcf, 0x72, 0xf0, 0xfd, 0x21, 0x99, 0x84,
+ 0x3e, 0x99, 0x6b, 0x81, 0x4c, 0xfa, 0x68, 0x5b, 0x26, 0xb1, 0xae, 0x5d,
+ 0xc6, 0xae, 0x92, 0xd7, 0x4d, 0xd0, 0x5b, 0xa7, 0x64, 0xaf, 0xc5, 0x34,
+ 0x1e, 0xad, 0x80, 0x16, 0xaf, 0x83, 0xae, 0x96, 0x41, 0x53, 0x99, 0xa2,
+ 0x35, 0x3a, 0xad, 0x92, 0xda, 0x2f, 0xf0, 0x38, 0xe8, 0xb5, 0xe3, 0x0a,
+ 0xb1, 0x28, 0x79, 0xd9, 0x01, 0xed, 0x89, 0xdf, 0x61, 0xdb, 0x93, 0x8e,
+ 0xb2, 0x41, 0x83, 0xa0, 0xcb, 0x62, 0xc0, 0xd3, 0xef, 0x29, 0x2d, 0x57,
+ 0x47, 0xef, 0x48, 0x2a, 0x7d, 0x47, 0x2c, 0xc8, 0x02, 0xcb, 0xfd, 0x50,
+ 0x5c, 0x8c, 0x79, 0x5c, 0x5e, 0xc7, 0x3c, 0x06, 0xf8, 0xfb, 0xc8, 0x90,
+ 0xe6, 0xef, 0x51, 0x89, 0xec, 0xe6, 0x71, 0xd0, 0x1b, 0x64, 0x50, 0xc0,
+ 0xd3, 0xe9, 0x90, 0x46, 0x9f, 0x06, 0xff, 0x5a, 0xb0, 0xca, 0x92, 0x32,
+ 0x0f, 0xfe, 0xbf, 0x8e, 0xef, 0xb7, 0xea, 0x9f, 0xaa, 0xb9, 0x05, 0x15,
+ 0xe6, 0xb2, 0x7c, 0x1b, 0x38, 0xf9, 0xf7, 0x38, 0xbb, 0x2e, 0x8d, 0xdd,
+ 0x07, 0x46, 0x18, 0x4b, 0xfb, 0xb7, 0xba, 0x6c, 0x1f, 0x95, 0xcd, 0xe1,
+ 0xe3, 0x28, 0xef, 0xc3, 0xd3, 0xc0, 0x39, 0x44, 0x75, 0x2c, 0x7c, 0xd9,
+ 0x1b, 0x36, 0x0a, 0x3a, 0xef, 0xe0, 0x98, 0xce, 0xcf, 0x37, 0xec, 0x03,
+ 0xf8, 0x4e, 0xbf, 0x0c, 0xf7, 0x06, 0xcc, 0xa4, 0x12, 0x3a, 0xc7, 0xb4,
+ 0x02, 0x2c, 0xb1, 0x82, 0xf1, 0xde, 0xa7, 0x5f, 0xaf, 0x06, 0x1e, 0x1e,
+ 0xfe, 0xa7, 0x9f, 0x8e, 0x31, 0x27, 0x7d, 0x33, 0x11, 0xe8, 0xbf, 0xcf,
+ 0xfc, 0x4d, 0x7b, 0x6e, 0xd4, 0xc0, 0xcb, 0x6d, 0x33, 0x86, 0xb6, 0xd0,
+ 0x65, 0xd0, 0x45, 0x65, 0x4d, 0xbf, 0x6c, 0x17, 0xf4, 0x2d, 0xd4, 0x52,
+ 0xe6, 0x07, 0x12, 0xf4, 0x9d, 0xb7, 0xa9, 0x77, 0xda, 0x21, 0x5f, 0x92,
+ 0x1a, 0x57, 0xbe, 0x6f, 0xe7, 0x21, 0x15, 0xac, 0xe4, 0x24, 0x68, 0xb4,
+ 0x4d, 0x2c, 0x67, 0x5c, 0x1e, 0xcc, 0x3b, 0xab, 0xfb, 0xb2, 0x6d, 0xb3,
+ 0x6f, 0x73, 0x5e, 0xae, 0x9f, 0x7b, 0xe1, 0x1e, 0xe8, 0xa7, 0x36, 0x35,
+ 0x8d, 0x36, 0x6a, 0xed, 0xfd, 0x01, 0x8d, 0x36, 0xf7, 0x11, 0xfb, 0x3f,
+ 0xfb, 0x20, 0x9d, 0x0c, 0x1b, 0x41, 0x0e, 0x06, 0x9e, 0x35, 0x9e, 0xe7,
+ 0xa7, 0xc0, 0xf7, 0x3b, 0xe9, 0xa7, 0xe9, 0x67, 0x0c, 0xe8, 0xe7, 0x91,
+ 0x6d, 0xfa, 0x21, 0xdd, 0x74, 0xca, 0xd8, 0x35, 0x5b, 0x26, 0x8a, 0xfa,
+ 0xbe, 0x81, 0x35, 0xe9, 0x3f, 0x3a, 0x0e, 0xba, 0x21, 0xad, 0x93, 0xb7,
+ 0x4c, 0x29, 0x83, 0x8e, 0xca, 0x90, 0x4f, 0x65, 0xd0, 0x14, 0x31, 0x50,
+ 0x19, 0xf2, 0xad, 0x5c, 0xb7, 0x9c, 0x2a, 0xf6, 0x4c, 0x9d, 0xbd, 0x02,
+ 0x3a, 0xba, 0x5e, 0xe7, 0xfd, 0xeb, 0x35, 0x9b, 0xd4, 0x83, 0xb7, 0xb6,
+ 0xef, 0xfe, 0xef, 0xb8, 0xfb, 0x43, 0x72, 0x03, 0x76, 0xcb, 0x9b, 0xa5,
+ 0x61, 0xc8, 0x24, 0x21, 0x5e, 0x04, 0x6d, 0x8c, 0xca, 0x6a, 0xe9, 0xa4,
+ 0xac, 0x41, 0x3f, 0xad, 0x2f, 0x0d, 0x00, 0x4f, 0x43, 0x8e, 0xbe, 0x72,
+ 0x44, 0xde, 0x58, 0x52, 0x32, 0x63, 0x43, 0xbf, 0x2c, 0xd3, 0x07, 0x0f,
+ 0x7a, 0x2e, 0x77, 0xea, 0x98, 0xfd, 0x58, 0x35, 0xf0, 0xc5, 0x8f, 0x57,
+ 0xbb, 0x64, 0xa2, 0x6a, 0xca, 0x63, 0xd5, 0x1e, 0x79, 0xa2, 0x1a, 0x93,
+ 0xd3, 0xb5, 0x84, 0x7c, 0xa3, 0x7a, 0x50, 0x4e, 0x55, 0x0f, 0xc9, 0x93,
+ 0xb5, 0xa4, 0x7c, 0x13, 0x76, 0x61, 0xae, 0xe6, 0xc8, 0x64, 0x6d, 0x58,
+ 0x1e, 0xaf, 0xd1, 0xc7, 0x8e, 0xf9, 0xf0, 0xcb, 0x6e, 0xfb, 0x2e, 0xb8,
+ 0xae, 0x0e, 0xac, 0xcb, 0x51, 0xe3, 0x3a, 0x66, 0x29, 0xb9, 0xc0, 0xff,
+ 0x21, 0x72, 0x0e, 0x7d, 0x2f, 0xbe, 0xa2, 0xa4, 0xa2, 0xe7, 0x6f, 0xfe,
+ 0xdf, 0x48, 0x54, 0xdb, 0x46, 0xe7, 0xca, 0x07, 0xd1, 0xc6, 0xa6, 0x4d,
+ 0x12, 0xfa, 0x41, 0x9a, 0xfe, 0xff, 0xa6, 0xed, 0x65, 0x68, 0x1f, 0xf6,
+ 0x2d, 0xda, 0x5e, 0xfa, 0xec, 0x29, 0x3f, 0x68, 0xe7, 0xd0, 0xd6, 0xda,
+ 0x19, 0xe7, 0x68, 0xce, 0x7b, 0x31, 0xf7, 0xf0, 0xff, 0xa7, 0x04, 0xf1,
+ 0xaa, 0xb3, 0xb5, 0x83, 0xfc, 0x3f, 0x15, 0xac, 0xe5, 0x8b, 0xf3, 0xc5,
+ 0x27, 0x4a, 0x63, 0xea, 0xb1, 0x12, 0x11, 0x8d, 0x2f, 0x17, 0xb7, 0x73,
+ 0xf2, 0xbe, 0x2e, 0xcb, 0x6e, 0x54, 0xaf, 0x21, 0xf0, 0xdb, 0xa7, 0x75,
+ 0x7e, 0xde, 0xd8, 0x10, 0xe9, 0x8f, 0x71, 0xb8, 0xae, 0x30, 0xb6, 0x00,
+ 0x6c, 0xeb, 0x9a, 0x72, 0xa9, 0x1a, 0xf8, 0xaf, 0xe6, 0x34, 0xbd, 0xbc,
+ 0x05, 0x9a, 0x63, 0xfc, 0x21, 0x78, 0xe6, 0xcb, 0x41, 0xdf, 0xec, 0x90,
+ 0x43, 0x7b, 0x1c, 0xfb, 0x35, 0x7a, 0x38, 0x17, 0xff, 0x4f, 0x07, 0xe5,
+ 0x70, 0xbd, 0xcc, 0x2f, 0xb6, 0x35, 0x2d, 0x06, 0x31, 0x5e, 0x47, 0x9e,
+ 0xc3, 0x5d, 0x54, 0x4c, 0xae, 0xbf, 0x43, 0x2a, 0x0e, 0x6d, 0x5b, 0xca,
+ 0xef, 0x21, 0x29, 0x63, 0x9e, 0x8a, 0xd3, 0xf4, 0x8d, 0x05, 0x72, 0xb6,
+ 0x62, 0x3e, 0x98, 0x77, 0xba, 0xbc, 0x1f, 0xef, 0xa8, 0x73, 0x80, 0x99,
+ 0xa6, 0xf8, 0x7e, 0x11, 0x65, 0xfa, 0x46, 0xe6, 0xf0, 0x4c, 0x84, 0x75,
+ 0xaf, 0xf5, 0x6b, 0xac, 0x7e, 0xf2, 0x41, 0xbf, 0x99, 0xb2, 0x95, 0xcf,
+ 0x44, 0xb6, 0x94, 0xf1, 0x8b, 0xf5, 0x7e, 0xca, 0xdc, 0xfd, 0x36, 0x7f,
+ 0x51, 0xf9, 0x8b, 0xa9, 0x7d, 0x0a, 0xe1, 0xb7, 0x3d, 0xf2, 0x94, 0xc9,
+ 0xdc, 0xf5, 0xb4, 0x1a, 0x2b, 0xfd, 0x34, 0xcc, 0xd3, 0xdd, 0x52, 0xfb,
+ 0x2b, 0x6f, 0xf7, 0x07, 0x79, 0xee, 0x1c, 0x7b, 0x67, 0x6e, 0xfb, 0x4e,
+ 0x3a, 0x61, 0x8e, 0x7b, 0x3b, 0x70, 0xab, 0x56, 0x62, 0xe0, 0x41, 0xc8,
+ 0x3b, 0xbb, 0x45, 0xf3, 0x63, 0xa1, 0xf6, 0x2f, 0x7f, 0x43, 0xf3, 0x73,
+ 0xd3, 0xc7, 0xf0, 0xdb, 0x7e, 0xda, 0xb6, 0x94, 0x1b, 0x97, 0x02, 0xbf,
+ 0x91, 0xb6, 0xa1, 0x21, 0x2b, 0x50, 0x47, 0x5e, 0x05, 0x9f, 0x6c, 0xb7,
+ 0xe5, 0xdf, 0x7f, 0x01, 0x99, 0xe7, 0xd3, 0x46, 0x40, 0x67, 0x00, 0x00,
+ 0x00 };
+static u32 bnx2_RXP_b09FwData[(0x0/4) + 1] = { 0x0 };
+static u32 bnx2_RXP_b09FwRodata[(0x278/4) + 1] = {
+ 0x08003fa4, 0x08003ea4, 0x08003f48, 0x08003f60, 0x08003f78, 0x08003f98,
+ 0x08003fa4, 0x08003fa4, 0x08003eac, 0x00000000, 0x080049d4, 0x08004a0c,
+ 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004a44, 0x08004c08,
+ 0x08004b50, 0x08004b88, 0x08004c08, 0x08004ad8, 0x08004c08, 0x08004c08,
+ 0x08004b88, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
+ 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004bc8,
+ 0x08004c08, 0x08004bc8, 0x08004b50, 0x08004c08, 0x08004c08, 0x08004bc8,
+ 0x08004bc8, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
+ 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
+ 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
+ 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
+ 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
+ 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
+ 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
+ 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
+ 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
+ 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
+ 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
+ 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
+ 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
+ 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
+ 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
+ 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
+ 0x08004ab4, 0x00000000, 0x0800602c, 0x08006044, 0x08006044, 0x08006044,
+ 0x0800602c, 0x08006044, 0x08006044, 0x08006044, 0x0800602c, 0x08006044,
+ 0x08006044, 0x08006044, 0x0800602c, 0x08006044, 0x08006044, 0x08006044,
+ 0x08006038, 0x00000000, 0x00000000 };
+static u32 bnx2_RXP_b09FwBss[(0x13dc/4) + 1] = { 0x0 };
+static u32 bnx2_RXP_b09FwSbss[(0x2c/4) + 1] = { 0x0 };
+
+static struct fw_info bnx2_rxp_fw_09 = {
+ .ver_major = 0x1,
+ .ver_minor = 0x0,
+ .ver_fix = 0x0,
+
+ .start_addr = 0x08003184,
+
+ .text_addr = 0x08000000,
+ .text_len = 0x673c,
+ .text_index = 0x0,
+ .gz_text = bnx2_RXP_b09FwText,
+ .gz_text_len = sizeof(bnx2_RXP_b09FwText),
+
+ .data_addr = 0x080069e0,
+ .data_len = 0x0,
+ .data_index = 0x0,
+ .data = bnx2_RXP_b09FwData,
+
+ .sbss_addr = 0x080069e0,
+ .sbss_len = 0x2c,
+ .sbss_index = 0x0,
+ .sbss = bnx2_RXP_b09FwSbss,
+
+ .bss_addr = 0x08006a10,
+ .bss_len = 0x13dc,
+ .bss_index = 0x0,
+ .bss = bnx2_RXP_b09FwBss,
+
+ .rodata_addr = 0x08006740,
+ .rodata_len = 0x278,
+ .rodata_index = 0x0,
+ .rodata = bnx2_RXP_b09FwRodata,
+};
+
+static u8 bnx2_TPAT_b09FwText[] = {
+ 0x1f, 0x8b, 0x08, 0x08, 0xdb, 0xfd, 0x2f, 0x45, 0x00, 0x03, 0x74, 0x65,
+ 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xc5, 0x58, 0x5d, 0x6c,
+ 0x1c, 0x57, 0x15, 0x3e, 0xf3, 0xbb, 0x13, 0x77, 0xed, 0xbd, 0x49, 0x97,
+ 0x6a, 0x13, 0xb9, 0x74, 0xc6, 0x1e, 0x3b, 0x8b, 0x1c, 0x35, 0x93, 0xb0,
+ 0x24, 0x16, 0x5a, 0xd1, 0xc9, 0xcc, 0xae, 0x6b, 0xe5, 0x29, 0x86, 0xbc,
+ 0xf1, 0xb2, 0xac, 0xed, 0x46, 0x54, 0x48, 0x4d, 0x51, 0x84, 0x22, 0x81,
+ 0x94, 0x65, 0x76, 0x53, 0x40, 0x5a, 0x65, 0xc1, 0xa0, 0x04, 0x21, 0x84,
+ 0x22, 0x9b, 0x66, 0x91, 0x58, 0x3c, 0x4d, 0xe9, 0x6b, 0x94, 0xbc, 0x90,
+ 0x96, 0x17, 0x9e, 0x4b, 0x9e, 0xac, 0x02, 0x12, 0x0f, 0xa8, 0x8a, 0x78,
+ 0x40, 0x15, 0x0d, 0x1e, 0xbe, 0x33, 0x3f, 0x9b, 0x5d, 0xd7, 0x29, 0x79,
+ 0xa8, 0x84, 0xa5, 0xf1, 0xcc, 0xfd, 0x39, 0xf7, 0xe7, 0x7c, 0xdf, 0x77,
+ 0xee, 0xb9, 0x5b, 0x92, 0x69, 0x82, 0xd2, 0xbf, 0x49, 0x3c, 0x97, 0xbe,
+ 0x71, 0xf1, 0xd2, 0xe2, 0x8b, 0x27, 0x4d, 0x3a, 0x71, 0xe2, 0x45, 0xe9,
+ 0x19, 0x43, 0xa6, 0xcf, 0xe0, 0x4f, 0x21, 0x12, 0xd9, 0xf8, 0xfc, 0x90,
+ 0x21, 0x57, 0x6f, 0x4e, 0x7b, 0x36, 0x19, 0x4a, 0xd5, 0x79, 0x61, 0xd5,
+ 0x26, 0x72, 0x07, 0x0b, 0xa6, 0x4f, 0xff, 0x89, 0x5a, 0x45, 0x95, 0xb8,
+ 0xfe, 0xf9, 0xea, 0xa3, 0xe3, 0x77, 0x4e, 0x5b, 0x0f, 0x6f, 0x2a, 0x64,
+ 0x88, 0x6a, 0xc3, 0x10, 0xf3, 0x64, 0x4c, 0xc3, 0xe6, 0x97, 0x47, 0x57,
+ 0x34, 0x9a, 0xca, 0xc6, 0x12, 0x14, 0xf4, 0x0c, 0xaa, 0x77, 0x31, 0x8e,
+ 0x7d, 0x59, 0xf2, 0x43, 0x55, 0xf2, 0x6f, 0x18, 0x24, 0x57, 0x5d, 0xc9,
+ 0x0b, 0x6d, 0xb4, 0x49, 0xe4, 0x39, 0x39, 0x72, 0x45, 0x14, 0x7d, 0xd3,
+ 0x91, 0x49, 0xb6, 0x77, 0xa3, 0xd9, 0xb9, 0x25, 0xc9, 0xeb, 0x2f, 0x4b,
+ 0x7e, 0xdf, 0xe3, 0x7d, 0x63, 0x1d, 0x4b, 0x92, 0xdb, 0xe7, 0x77, 0xd5,
+ 0xf0, 0xbb, 0x53, 0xd4, 0x28, 0x52, 0x41, 0xb6, 0xd9, 0xd6, 0x24, 0xdf,
+ 0x59, 0x28, 0x29, 0x34, 0x8b, 0xe7, 0x00, 0xad, 0x3b, 0x94, 0xf7, 0x1c,
+ 0x52, 0x15, 0x5b, 0x26, 0xbf, 0x28, 0xd1, 0xaf, 0x2b, 0x1a, 0x9e, 0xb3,
+ 0x52, 0xad, 0xbf, 0x96, 0x8e, 0x53, 0xa4, 0x36, 0xd6, 0xd2, 0x2c, 0xf2,
+ 0xda, 0x12, 0x7b, 0xcf, 0x59, 0x10, 0x32, 0xcd, 0xe2, 0x99, 0xc4, 0x77,
+ 0x13, 0xfd, 0x34, 0xf2, 0x2a, 0x7b, 0xdb, 0x0e, 0xe0, 0x1b, 0xeb, 0xc4,
+ 0x58, 0x5e, 0xbc, 0x0e, 0x13, 0xeb, 0xb0, 0xa9, 0xd3, 0x5b, 0xc6, 0x3e,
+ 0xe6, 0x4a, 0x4d, 0xd2, 0xa9, 0x13, 0xaf, 0x7d, 0x92, 0x02, 0xa1, 0x50,
+ 0x70, 0x4c, 0x23, 0xf7, 0x9c, 0x8a, 0xf2, 0x21, 0x6a, 0x09, 0x09, 0x7d,
+ 0x3a, 0x29, 0x7e, 0x39, 0xb4, 0xeb, 0xa8, 0x2f, 0x50, 0x50, 0x3c, 0x28,
+ 0xc9, 0xd5, 0xef, 0xa1, 0x7e, 0x4e, 0x34, 0xe9, 0xbb, 0x78, 0x4b, 0x28,
+ 0x1f, 0xe4, 0xf1, 0x50, 0x96, 0x48, 0xb1, 0x49, 0x78, 0xa1, 0x49, 0xed,
+ 0x30, 0xb3, 0xe5, 0xfa, 0xa4, 0xae, 0x15, 0xee, 0xc5, 0x0e, 0xfd, 0x7a,
+ 0x75, 0x6a, 0x08, 0x6a, 0xa9, 0x55, 0xf4, 0xe9, 0xd9, 0xa2, 0x06, 0x9c,
+ 0xdc, 0x18, 0xcf, 0x97, 0xb8, 0x9e, 0xff, 0x50, 0x6f, 0x92, 0x52, 0xb5,
+ 0x85, 0x4f, 0x5f, 0xa6, 0xa4, 0x8d, 0xf7, 0x29, 0x63, 0x6f, 0xa7, 0xd2,
+ 0x72, 0x51, 0x78, 0x37, 0xbe, 0x48, 0x6e, 0xec, 0x1f, 0x03, 0xdf, 0x02,
+ 0x7b, 0xd4, 0x81, 0x75, 0xe0, 0xca, 0xd4, 0x2a, 0x19, 0x64, 0x2d, 0xae,
+ 0xa1, 0xe5, 0x6f, 0x5d, 0x05, 0x7e, 0x67, 0xdc, 0xd4, 0xd4, 0x8e, 0x71,
+ 0xfe, 0x23, 0xd6, 0xd9, 0x12, 0x06, 0xf0, 0x6e, 0x9c, 0x8f, 0xa2, 0x37,
+ 0x9d, 0x28, 0xd2, 0xab, 0x76, 0xf9, 0x16, 0x2d, 0x94, 0x34, 0x9a, 0x17,
+ 0x78, 0xc3, 0x8f, 0x36, 0x7c, 0xa5, 0x65, 0xeb, 0xc9, 0x78, 0x86, 0xbf,
+ 0xcb, 0x12, 0x96, 0x42, 0x1f, 0x74, 0xdf, 0x63, 0x7f, 0x94, 0x97, 0x62,
+ 0x9b, 0x28, 0xda, 0x5c, 0xfc, 0x34, 0x9b, 0xef, 0xa7, 0x36, 0x51, 0x54,
+ 0xaf, 0xf0, 0xbc, 0x16, 0xf6, 0xcc, 0x5c, 0x25, 0xaa, 0x0f, 0x1c, 0xa3,
+ 0xd9, 0xc5, 0xfa, 0x6c, 0xbc, 0x07, 0x25, 0xec, 0xc1, 0x2a, 0x9b, 0x92,
+ 0x41, 0x81, 0x1d, 0xbd, 0x00, 0x7e, 0xb8, 0xbe, 0x6d, 0xbd, 0xef, 0x2b,
+ 0x05, 0xda, 0x72, 0xf2, 0xd4, 0x09, 0x4b, 0x14, 0x84, 0x1d, 0xf2, 0x42,
+ 0x19, 0x73, 0x14, 0x68, 0xd3, 0x7e, 0x18, 0xd5, 0x1d, 0x07, 0x7e, 0x21,
+ 0xb6, 0x2b, 0xd5, 0x69, 0x1a, 0xed, 0x0b, 0x62, 0x8d, 0x1c, 0x60, 0x21,
+ 0xc3, 0x37, 0xb3, 0xf1, 0x77, 0x10, 0x3a, 0x68, 0xa7, 0x96, 0x5c, 0xb1,
+ 0x44, 0x40, 0x56, 0xc9, 0x53, 0x48, 0xc8, 0x55, 0x81, 0x3e, 0x2d, 0xaa,
+ 0x85, 0x06, 0xed, 0x28, 0x97, 0x63, 0x7e, 0xb7, 0x7b, 0x3b, 0xd1, 0x9d,
+ 0xa3, 0x25, 0xba, 0x1b, 0x16, 0xe9, 0x76, 0x48, 0x72, 0xd3, 0x01, 0x37,
+ 0x8a, 0x82, 0xde, 0x0a, 0x47, 0xf7, 0xf2, 0x1b, 0xec, 0x25, 0x38, 0xa2,
+ 0x40, 0x83, 0xab, 0xce, 0x3d, 0x30, 0xc8, 0x02, 0x46, 0x2d, 0xec, 0x3d,
+ 0x7b, 0xf3, 0xbe, 0x76, 0xa6, 0x57, 0x6d, 0xeb, 0x87, 0x3e, 0xa3, 0x76,
+ 0x4d, 0x43, 0xed, 0x5e, 0x7f, 0x0c, 0x30, 0x86, 0xa0, 0xab, 0xd0, 0x93,
+ 0x0c, 0xbf, 0xcc, 0x6c, 0x1b, 0xd4, 0xef, 0xe6, 0xc8, 0xdc, 0x54, 0xa9,
+ 0xd9, 0x2b, 0x92, 0x33, 0x6f, 0x99, 0x24, 0xcb, 0x45, 0x99, 0x54, 0x9a,
+ 0xd9, 0x8c, 0x68, 0x09, 0xeb, 0xb8, 0x6f, 0xff, 0x48, 0xa7, 0xa9, 0xc0,
+ 0xd1, 0x89, 0xfb, 0x18, 0x34, 0x73, 0xcb, 0x90, 0xfc, 0x1e, 0xef, 0x83,
+ 0x7d, 0x6e, 0xa4, 0x3e, 0x57, 0x25, 0xef, 0x46, 0x8e, 0x66, 0x37, 0xfe,
+ 0x11, 0x79, 0x36, 0x7c, 0x0d, 0x9e, 0xaf, 0x56, 0xbe, 0xa0, 0xd0, 0x04,
+ 0xea, 0x36, 0xb9, 0xed, 0x61, 0x5a, 0xcf, 0x63, 0x44, 0x91, 0xe7, 0x3c,
+ 0x4b, 0x1e, 0xf3, 0xff, 0x3c, 0xdb, 0xe4, 0x68, 0x66, 0x83, 0x75, 0x83,
+ 0xf7, 0x26, 0x97, 0x79, 0x6d, 0x07, 0xa8, 0x89, 0x1d, 0x35, 0xcb, 0x45,
+ 0xf8, 0x41, 0x8e, 0x35, 0xd2, 0xc4, 0x8e, 0x65, 0x7b, 0x02, 0x6f, 0x9e,
+ 0xef, 0xac, 0x92, 0xf0, 0x9d, 0xe3, 0x46, 0x9e, 0x7c, 0xe0, 0xab, 0x62,
+ 0x3d, 0x6b, 0x34, 0x57, 0x5a, 0x8f, 0xdb, 0x50, 0x37, 0xe0, 0x36, 0xb1,
+ 0xa7, 0x0d, 0xe5, 0x41, 0xb6, 0x06, 0x70, 0xda, 0x6e, 0x63, 0x16, 0x2d,
+ 0xde, 0x6b, 0xdd, 0xe1, 0xfe, 0xdc, 0xb7, 0x55, 0xd6, 0xc8, 0x2a, 0x6f,
+ 0x62, 0xf4, 0x7e, 0x17, 0xfb, 0xbd, 0xce, 0xb1, 0xc8, 0x36, 0xff, 0x4a,
+ 0xdc, 0x7f, 0x16, 0x7b, 0x9e, 0x5b, 0x6c, 0x73, 0xdb, 0x40, 0x23, 0x7b,
+ 0xa3, 0x25, 0x54, 0xf8, 0x5f, 0x86, 0xf3, 0xfd, 0x1f, 0xff, 0x2b, 0xd2,
+ 0xaa, 0xe0, 0x74, 0xa5, 0x00, 0x7c, 0x2c, 0xb3, 0x0d, 0xbd, 0xdb, 0x18,
+ 0x37, 0x70, 0x14, 0xd8, 0x25, 0x38, 0x71, 0xbf, 0xa5, 0x6e, 0x44, 0xed,
+ 0x78, 0xae, 0x2b, 0x3c, 0x17, 0x62, 0x92, 0xbd, 0xf8, 0x07, 0x70, 0xa3,
+ 0x49, 0x79, 0x9a, 0xdf, 0xce, 0xd3, 0x85, 0x41, 0x9e, 0x66, 0xae, 0xe9,
+ 0xf0, 0x43, 0x14, 0x75, 0x2a, 0xac, 0x51, 0xe0, 0x6d, 0x73, 0x3f, 0xab,
+ 0xa4, 0xc8, 0xbc, 0x0e, 0xb4, 0x6f, 0x13, 0xad, 0x0d, 0x74, 0xf8, 0x4d,
+ 0x1d, 0x19, 0x5b, 0xa6, 0x97, 0x7f, 0x46, 0xf4, 0xf2, 0x80, 0x6d, 0x79,
+ 0xfc, 0xc4, 0xa6, 0x89, 0x3d, 0xcb, 0xc0, 0xfc, 0xc2, 0x40, 0x46, 0xbc,
+ 0x40, 0x3c, 0xed, 0x7b, 0x88, 0x93, 0x35, 0x3c, 0x4b, 0x88, 0x9d, 0x8c,
+ 0x0d, 0xc7, 0x91, 0x5d, 0xe0, 0xb3, 0x8c, 0xb6, 0xb3, 0xa8, 0x4b, 0xf4,
+ 0xae, 0xd8, 0x3a, 0xd5, 0x9c, 0x49, 0x6a, 0x67, 0xb1, 0x4a, 0x70, 0xac,
+ 0x3a, 0x08, 0x4e, 0x1d, 0x40, 0xfc, 0xf9, 0x9d, 0x32, 0x1e, 0xab, 0x10,
+ 0xd3, 0x8a, 0x87, 0x11, 0x9b, 0xfa, 0xa8, 0xe7, 0xf1, 0x6e, 0xe1, 0x7d,
+ 0x00, 0xe5, 0xc3, 0xe8, 0x3b, 0x1a, 0xa7, 0x32, 0xbb, 0x27, 0xc5, 0x28,
+ 0xf0, 0x6e, 0xc3, 0x40, 0x7f, 0x13, 0xba, 0x61, 0x7f, 0xe7, 0x10, 0x3f,
+ 0xd8, 0xe7, 0x39, 0xf8, 0x54, 0xc7, 0xdc, 0x82, 0x66, 0xb7, 0xa9, 0xa5,
+ 0xa4, 0xf1, 0xcb, 0x1f, 0xc6, 0xaf, 0x52, 0xcc, 0x83, 0x20, 0x14, 0xb0,
+ 0x61, 0xfd, 0x66, 0x7a, 0x65, 0xec, 0xc8, 0xf5, 0xa0, 0x65, 0x4f, 0x89,
+ 0xa2, 0x55, 0xa7, 0x40, 0x4d, 0xe0, 0xee, 0x42, 0xc3, 0x4d, 0x68, 0xd8,
+ 0x1f, 0xd1, 0xb0, 0xff, 0x3f, 0x35, 0x0c, 0x7d, 0x42, 0x23, 0xb7, 0xc1,
+ 0xa9, 0xb7, 0x7a, 0xfb, 0xe9, 0x99, 0xb5, 0xcc, 0x9a, 0x36, 0xe9, 0xce,
+ 0xd1, 0xa7, 0xd5, 0x74, 0x49, 0x7e, 0x4a, 0x4d, 0xb7, 0x58, 0xd3, 0x2a,
+ 0x6b, 0xba, 0xb8, 0x57, 0xd3, 0xd3, 0x18, 0x23, 0xd1, 0xe6, 0x19, 0xb5,
+ 0x48, 0xda, 0x3c, 0xf0, 0xd8, 0xc8, 0x93, 0x72, 0xed, 0x31, 0xef, 0x98,
+ 0xcb, 0xfe, 0x00, 0xff, 0xb6, 0x35, 0xb4, 0x49, 0xe3, 0xf5, 0x88, 0x81,
+ 0x6a, 0xd5, 0x2a, 0xad, 0xc5, 0x7d, 0x54, 0xd2, 0xe1, 0xff, 0xd7, 0x8f,
+ 0x5a, 0xa6, 0x29, 0x8f, 0x6a, 0x1f, 0xea, 0xdf, 0x88, 0xae, 0x68, 0x55,
+ 0x9e, 0xa7, 0x65, 0x82, 0xf3, 0xe6, 0x4f, 0x80, 0x55, 0xbb, 0xcb, 0x7c,
+ 0xb7, 0x45, 0x3d, 0xe6, 0x19, 0xca, 0xd0, 0x84, 0x06, 0xde, 0xe6, 0xd0,
+ 0x4f, 0xdd, 0x48, 0x74, 0x74, 0x1b, 0xe3, 0x6e, 0x75, 0x99, 0x67, 0x06,
+ 0xe9, 0xd7, 0xed, 0xd2, 0x85, 0x38, 0x06, 0xcf, 0x8a, 0x25, 0x62, 0x0d,
+ 0xf2, 0xb9, 0x88, 0xf6, 0x41, 0x8e, 0x94, 0x58, 0xf7, 0x13, 0xa9, 0xee,
+ 0x9f, 0x87, 0xaf, 0x26, 0x50, 0x66, 0xed, 0x1f, 0x4e, 0xb5, 0x3f, 0x85,
+ 0x37, 0xd7, 0xad, 0xa8, 0x09, 0x87, 0xc0, 0xc7, 0x0d, 0xc6, 0x37, 0x8f,
+ 0x58, 0xc7, 0xf3, 0xff, 0x33, 0x5a, 0xb5, 0x19, 0x63, 0xdb, 0xfc, 0x01,
+ 0xcd, 0x41, 0x7f, 0xa8, 0xdf, 0xe6, 0xbe, 0x6c, 0x93, 0xf5, 0x15, 0x69,
+ 0xdf, 0x0f, 0xf7, 0xf4, 0x45, 0xfd, 0x36, 0xf7, 0x63, 0x7d, 0x1c, 0x22,
+ 0xe5, 0x3a, 0x9f, 0xdb, 0x1e, 0xeb, 0x03, 0x76, 0x35, 0xd4, 0x71, 0x6e,
+ 0xc1, 0xf6, 0x7c, 0x86, 0xf3, 0x3a, 0x39, 0xef, 0xe0, 0x73, 0x7e, 0xcf,
+ 0x79, 0x3e, 0xd4, 0xc8, 0x19, 0xf0, 0xfe, 0x3b, 0xea, 0x27, 0x35, 0xb2,
+ 0x02, 0x4d, 0x5c, 0x54, 0x13, 0x8d, 0xbc, 0x86, 0xf7, 0x19, 0x94, 0x57,
+ 0xf6, 0x68, 0x24, 0xb3, 0x7b, 0xf2, 0x39, 0x1e, 0xf4, 0x4a, 0xf1, 0x99,
+ 0xcb, 0xf3, 0x29, 0x1b, 0xd4, 0xd2, 0x52, 0x3d, 0xd4, 0x87, 0x7a, 0x98,
+ 0x40, 0xcc, 0xc8, 0xa5, 0x5c, 0xc7, 0xdb, 0xfe, 0x48, 0xf1, 0x1d, 0x4b,
+ 0xb4, 0x89, 0xb5, 0x31, 0x7a, 0x9e, 0xfd, 0xbf, 0xf4, 0x41, 0xe0, 0x51,
+ 0x3c, 0x37, 0x72, 0x11, 0x3e, 0x17, 0xa2, 0xe8, 0x15, 0x07, 0xed, 0x59,
+ 0x4e, 0x12, 0x63, 0x9f, 0xc3, 0xd9, 0xcb, 0x78, 0x20, 0x0f, 0xb4, 0x67,
+ 0xa1, 0x07, 0x8e, 0x05, 0xbb, 0xd1, 0x96, 0xed, 0xa1, 0xae, 0x06, 0xff,
+ 0x33, 0x26, 0xcb, 0xd2, 0x52, 0xdf, 0x60, 0x3b, 0xe8, 0x6d, 0xbf, 0x5c,
+ 0x4c, 0x87, 0xae, 0x1e, 0xe3, 0xc4, 0x3c, 0x6a, 0x8e, 0xe0, 0xd4, 0x88,
+ 0x71, 0xda, 0x19, 0xe2, 0xd4, 0x4c, 0x71, 0x6a, 0xc6, 0x38, 0x3d, 0x48,
+ 0x71, 0xfa, 0xf3, 0x13, 0x70, 0xda, 0x79, 0x0a, 0x9c, 0x0c, 0xda, 0xb2,
+ 0x4b, 0x38, 0x6f, 0xf5, 0x38, 0x77, 0xbd, 0xef, 0xec, 0x97, 0x7b, 0xb1,
+ 0xdf, 0xc7, 0xb0, 0x8a, 0x18, 0xab, 0x2d, 0x1a, 0xcd, 0x43, 0x2c, 0xf3,
+ 0x1e, 0x15, 0x70, 0x6e, 0xe4, 0xe9, 0xea, 0x9e, 0x5c, 0x24, 0x00, 0x4e,
+ 0xb5, 0x14, 0xa7, 0xab, 0xc0, 0xa9, 0x96, 0xe2, 0xb4, 0x3e, 0x82, 0xd3,
+ 0xfa, 0x18, 0x4e, 0x1c, 0x53, 0x2a, 0xc6, 0x7a, 0x37, 0xc3, 0x28, 0xc3,
+ 0x47, 0xa7, 0x9b, 0x62, 0x0a, 0xfb, 0x3f, 0x4e, 0xed, 0x9f, 0xaa, 0x9c,
+ 0xff, 0x02, 0xbb, 0x97, 0x54, 0x39, 0x3e, 0x17, 0xf8, 0xfb, 0x71, 0xbe,
+ 0x82, 0xb9, 0x5c, 0xcf, 0xe1, 0x3d, 0x21, 0xcf, 0xb5, 0x47, 0x63, 0xd1,
+ 0x07, 0x88, 0x45, 0x5c, 0xc7, 0xfd, 0x54, 0xa9, 0x06, 0xcd, 0x2b, 0xc8,
+ 0xe1, 0xfd, 0x61, 0x0e, 0x9f, 0xf8, 0xe1, 0x6a, 0x9a, 0xc3, 0x6f, 0xd9,
+ 0x9c, 0xc3, 0x9f, 0xd0, 0x68, 0x62, 0x39, 0xc5, 0x93, 0x79, 0x3d, 0x89,
+ 0xb6, 0xb3, 0x31, 0xee, 0x6d, 0xc4, 0xf2, 0x55, 0xf8, 0xa0, 0x19, 0xf3,
+ 0x13, 0x79, 0x57, 0xca, 0x5d, 0xe4, 0xbb, 0xe4, 0x87, 0x09, 0x4f, 0x3f,
+ 0xdb, 0x5c, 0xec, 0xef, 0x88, 0xd9, 0x46, 0x43, 0xc5, 0x1d, 0xe0, 0x6e,
+ 0x18, 0xc7, 0xea, 0x73, 0x41, 0x97, 0x5a, 0x47, 0xaa, 0x57, 0x22, 0xe0,
+ 0xee, 0x7e, 0xfd, 0x34, 0x9f, 0x39, 0xf9, 0x45, 0xaf, 0x82, 0xfa, 0x81,
+ 0x41, 0xc8, 0x83, 0x70, 0xa7, 0xa1, 0x96, 0x77, 0x5a, 0x42, 0xbe, 0x83,
+ 0x32, 0x6c, 0x82, 0x70, 0xba, 0x21, 0x57, 0x4b, 0xe0, 0x43, 0x8b, 0x5c,
+ 0xac, 0xd3, 0x0d, 0xe3, 0x7b, 0x4d, 0x43, 0xa9, 0x1a, 0xc8, 0x37, 0xc9,
+ 0xc0, 0x99, 0x0f, 0x9f, 0x98, 0x46, 0x7b, 0x80, 0x9c, 0x08, 0x79, 0x80,
+ 0xb7, 0x08, 0xbf, 0x1c, 0x03, 0x76, 0xa1, 0x0a, 0xdb, 0x6f, 0xe9, 0xc9,
+ 0x9d, 0x88, 0xc8, 0x8b, 0xfd, 0xf5, 0x71, 0xca, 0x91, 0x38, 0xe7, 0x92,
+ 0x6a, 0x3d, 0x32, 0x9b, 0x0e, 0xb8, 0x8e, 0x33, 0xa5, 0x13, 0x72, 0x5e,
+ 0x7d, 0xcc, 0x90, 0xaf, 0x71, 0x3c, 0x7f, 0x00, 0x1f, 0xe2, 0x7b, 0x9b,
+ 0xcf, 0x19, 0x85, 0x73, 0x73, 0xdc, 0x7d, 0xca, 0x88, 0x37, 0x34, 0x89,
+ 0xd8, 0x87, 0xd8, 0x3b, 0xcd, 0x58, 0xb9, 0xc9, 0x19, 0xc4, 0xe3, 0x1d,
+ 0x97, 0x93, 0x79, 0xfe, 0xa4, 0x25, 0x1c, 0xc6, 0x7d, 0x07, 0xfe, 0x5b,
+ 0xed, 0x39, 0x1c, 0x73, 0x3f, 0xaf, 0xd0, 0x43, 0x8a, 0x39, 0x29, 0x4e,
+ 0x20, 0x16, 0x9f, 0x86, 0x8d, 0x1b, 0xeb, 0x31, 0xc9, 0xbd, 0x32, 0x9b,
+ 0x0f, 0xf7, 0x8c, 0xf1, 0x17, 0x65, 0xbc, 0xec, 0x82, 0xd3, 0x95, 0x74,
+ 0xbe, 0x51, 0x8e, 0x2c, 0x20, 0xe5, 0x79, 0xa0, 0x0d, 0xf3, 0xb7, 0xa2,
+ 0x8e, 0x7e, 0xbc, 0x46, 0xd6, 0x25, 0xdb, 0x1c, 0xd1, 0xc6, 0xc7, 0x99,
+ 0xdd, 0x67, 0x8c, 0xea, 0xc8, 0x18, 0x45, 0xde, 0x9b, 0x68, 0x3a, 0xcf,
+ 0xa4, 0xf7, 0x0c, 0x8e, 0x2d, 0x02, 0x3a, 0x95, 0x9f, 0x93, 0xb1, 0x0f,
+ 0x0f, 0x7b, 0xf6, 0xe3, 0xfa, 0x5f, 0xe9, 0xe3, 0xe3, 0xfe, 0x56, 0x4d,
+ 0xca, 0xc7, 0x12, 0x6e, 0xda, 0x78, 0x87, 0x0f, 0x46, 0xd6, 0xae, 0xed,
+ 0x33, 0xef, 0xd7, 0x38, 0x5d, 0x43, 0xbc, 0x21, 0x57, 0xc1, 0x1d, 0xcc,
+ 0x27, 0x7c, 0x87, 0xaf, 0x67, 0x3e, 0x04, 0x6f, 0xe8, 0x5c, 0x3b, 0xe5,
+ 0x8b, 0x9c, 0xf0, 0x85, 0xf3, 0xba, 0xc5, 0x55, 0xf0, 0xa5, 0x0d, 0xbe,
+ 0xc0, 0xae, 0xa1, 0x55, 0xa7, 0xc1, 0x05, 0x8e, 0x4d, 0x28, 0x87, 0xcc,
+ 0x1d, 0xe6, 0x0a, 0xf3, 0xe6, 0x31, 0x5f, 0x5e, 0xe9, 0x1a, 0xc6, 0xe6,
+ 0xa7, 0x70, 0xe5, 0x8d, 0x98, 0x2b, 0xcc, 0xd9, 0x24, 0x7e, 0x74, 0x80,
+ 0x55, 0x90, 0xc6, 0x8f, 0x00, 0xf1, 0xa3, 0xc6, 0xf9, 0x4f, 0x1c, 0x0b,
+ 0x12, 0xfd, 0xac, 0x41, 0x3f, 0x35, 0x85, 0xf3, 0x23, 0xd6, 0x0e, 0xdb,
+ 0xb1, 0x7e, 0xd8, 0xae, 0x90, 0xda, 0x8d, 0xc7, 0x91, 0x76, 0xcf, 0x32,
+ 0xb3, 0x38, 0xd2, 0x86, 0x76, 0x3a, 0xa9, 0x8e, 0xda, 0xa9, 0x8e, 0xd0,
+ 0xa7, 0xa5, 0x54, 0xf8, 0x4c, 0xb0, 0x4c, 0x1f, 0xf1, 0xa3, 0x13, 0x8f,
+ 0xd9, 0xa2, 0xe4, 0x2e, 0xc3, 0xda, 0xe6, 0xb8, 0x3b, 0x12, 0x6f, 0xd3,
+ 0x7b, 0x6e, 0x23, 0xbe, 0xe7, 0x7e, 0x45, 0x1f, 0x8f, 0xb7, 0x38, 0x6b,
+ 0xe2, 0x7b, 0xee, 0x29, 0x9d, 0xef, 0xb9, 0x01, 0x7d, 0x49, 0x1f, 0xbd,
+ 0xe7, 0x06, 0x63, 0xf7, 0xdc, 0xcc, 0x96, 0xeb, 0xf7, 0x8b, 0xbb, 0x99,
+ 0x4f, 0x38, 0xf6, 0x32, 0x9f, 0xf6, 0xcb, 0x15, 0xb3, 0x3e, 0x1c, 0x93,
+ 0x58, 0xef, 0x1c, 0xcb, 0x92, 0xdc, 0xec, 0x6e, 0x98, 0xe9, 0xe2, 0x55,
+ 0xcc, 0x83, 0x72, 0x6f, 0x3f, 0x5d, 0x18, 0xa9, 0x2e, 0x26, 0x13, 0x9b,
+ 0xde, 0xa8, 0x36, 0x5e, 0xd5, 0xc7, 0xb5, 0x91, 0x8d, 0x93, 0x69, 0x23,
+ 0x19, 0x73, 0x47, 0x29, 0xe1, 0x0c, 0x2c, 0x23, 0x1e, 0x09, 0xbe, 0xa3,
+ 0x21, 0x5e, 0x54, 0xf3, 0xb8, 0xa7, 0x14, 0x78, 0xec, 0x76, 0xf8, 0x2c,
+ 0x35, 0x8a, 0x8c, 0x0b, 0xaf, 0xff, 0x61, 0x7c, 0x7f, 0xc0, 0xba, 0x0b,
+ 0x01, 0xff, 0xfe, 0xf1, 0x09, 0x3e, 0xbe, 0x06, 0x3e, 0x66, 0xfb, 0x19,
+ 0xad, 0xbf, 0x34, 0x52, 0x5f, 0x4e, 0x31, 0x4f, 0x7c, 0x7e, 0x2f, 0xd5,
+ 0xc8, 0x26, 0x72, 0xb7, 0xfb, 0xc8, 0x8b, 0xde, 0x44, 0xfc, 0x0e, 0x06,
+ 0x1f, 0x47, 0xf7, 0x8a, 0x2a, 0x75, 0x86, 0x36, 0xbf, 0xc0, 0xba, 0x2d,
+ 0x71, 0x13, 0x5f, 0x6f, 0x0c, 0xb2, 0xb1, 0xb9, 0x9d, 0xeb, 0xfe, 0x8d,
+ 0xf3, 0x19, 0x79, 0xdf, 0xb0, 0xef, 0xfb, 0x11, 0xe7, 0xbb, 0x77, 0x81,
+ 0xc5, 0x3b, 0xe1, 0x34, 0xfd, 0x1e, 0x1c, 0x7b, 0x3b, 0xce, 0x79, 0x93,
+ 0x5c, 0x17, 0xfe, 0xc3, 0x99, 0xc7, 0x67, 0xbd, 0xf7, 0x39, 0x99, 0x2e,
+ 0xd3, 0x57, 0x1d, 0xae, 0x93, 0xa9, 0x7e, 0x2a, 0x8a, 0x2e, 0xe2, 0xdc,
+ 0x5f, 0x19, 0x3b, 0xf7, 0x71, 0x07, 0x3c, 0xc9, 0xf9, 0x7f, 0x96, 0xf3,
+ 0xef, 0x46, 0x33, 0xf3, 0xd6, 0x4d, 0x97, 0x5c, 0xa9, 0xde, 0xe7, 0x7c,
+ 0x6c, 0x98, 0x8b, 0x11, 0x1d, 0x7a, 0x14, 0xc9, 0xf3, 0x7c, 0x36, 0xbd,
+ 0x9b, 0xfa, 0x1c, 0x6d, 0x37, 0x1e, 0xe1, 0x1e, 0x53, 0x8b, 0x7f, 0x17,
+ 0x72, 0xfb, 0x3c, 0x0f, 0x97, 0xf1, 0x0e, 0x39, 0x47, 0x78, 0xd2, 0x6f,
+ 0x35, 0x2a, 0xf0, 0xb5, 0xcc, 0x75, 0x85, 0xe2, 0x7b, 0x21, 0xee, 0x6e,
+ 0x3f, 0x6f, 0x53, 0x12, 0x3b, 0x6a, 0xce, 0x39, 0xac, 0x05, 0x98, 0x88,
+ 0x06, 0x30, 0x9e, 0x47, 0xac, 0xb2, 0xcc, 0x93, 0x72, 0xf2, 0x5b, 0xd5,
+ 0x1a, 0xc6, 0x56, 0x4e, 0x72, 0x2e, 0xf9, 0x51, 0xb4, 0x36, 0x88, 0xcf,
+ 0x44, 0x87, 0xb9, 0xe6, 0x87, 0x07, 0x65, 0x7e, 0xbb, 0x21, 0x7f, 0xeb,
+ 0x98, 0xc7, 0x7c, 0x02, 0x0f, 0x8b, 0xa2, 0x76, 0xc3, 0x14, 0xf5, 0x9e,
+ 0x29, 0x96, 0x7a, 0x32, 0x54, 0x52, 0xc8, 0xd1, 0x14, 0xe7, 0x08, 0x3a,
+ 0xd1, 0x73, 0x58, 0xcb, 0x2d, 0x53, 0xf8, 0xc8, 0xa3, 0xbe, 0xad, 0x58,
+ 0x62, 0x85, 0x76, 0xb1, 0xc7, 0x47, 0x51, 0x72, 0xa7, 0x35, 0x45, 0x6d,
+ 0x38, 0xf7, 0x23, 0xcc, 0xcd, 0x6b, 0x62, 0x2d, 0xf3, 0x79, 0xb6, 0x2c,
+ 0x9d, 0x83, 0x8f, 0xce, 0xf7, 0x77, 0x11, 0x43, 0xf9, 0x3c, 0xcb, 0x23,
+ 0xe6, 0x59, 0x26, 0x5f, 0xf6, 0xef, 0x62, 0xff, 0xef, 0xf4, 0x80, 0x0f,
+ 0x72, 0xc7, 0xb7, 0x87, 0x79, 0x1a, 0x63, 0x58, 0x06, 0x17, 0xd9, 0x3e,
+ 0x8a, 0x82, 0xc5, 0x38, 0x47, 0xc1, 0x5a, 0xe6, 0xca, 0xb7, 0x90, 0xa7,
+ 0xd7, 0x69, 0xa1, 0x5c, 0x8f, 0xdf, 0x11, 0x72, 0x12, 0xfe, 0x5d, 0xc0,
+ 0x12, 0x4d, 0x7c, 0xd7, 0xd2, 0xef, 0x80, 0x73, 0xf8, 0x45, 0x1e, 0x83,
+ 0x73, 0x79, 0xd6, 0xe1, 0x7f, 0x01, 0x17, 0xc6, 0xf1, 0xb2, 0x84, 0x14,
+ 0x00, 0x00, 0x00 };
+static u32 bnx2_TPAT_b09FwData[(0x0/4) + 1] = { 0x0 };
+static u32 bnx2_TPAT_b09FwRodata[(0x0/4) + 1] = { 0x0 };
+static u32 bnx2_TPAT_b09FwBss[(0x250/4) + 1] = { 0x0 };
+static u32 bnx2_TPAT_b09FwSbss[(0x34/4) + 1] = { 0x0 };
+
+static struct fw_info bnx2_tpat_fw_09 = {
+ .ver_major = 0x1,
+ .ver_minor = 0x0,
+ .ver_fix = 0x0,
+
+ .start_addr = 0x08000860,
+
+ .text_addr = 0x08000800,
+ .text_len = 0x1480,
+ .text_index = 0x0,
+ .gz_text = bnx2_TPAT_b09FwText,
+ .gz_text_len = sizeof(bnx2_TPAT_b09FwText),
+
+ .data_addr = 0x08001ca0,
+ .data_len = 0x0,
+ .data_index = 0x0,
+ .data = bnx2_TPAT_b09FwData,
+
+ .sbss_addr = 0x08001ca0,
+ .sbss_len = 0x34,
+ .sbss_index = 0x0,
+ .sbss = bnx2_TPAT_b09FwSbss,
+
+ .bss_addr = 0x08001ce0,
+ .bss_len = 0x250,
+ .bss_index = 0x0,
+ .bss = bnx2_TPAT_b09FwBss,
+
+ .rodata_addr = 0x00000000,
+ .rodata_len = 0x0,
+ .rodata_index = 0x0,
+ .rodata = bnx2_TPAT_b09FwRodata,
+};
+
+static u8 bnx2_TXP_b09FwText[] = {
+ 0x1f, 0x8b, 0x08, 0x08, 0x51, 0xfe, 0x2f, 0x45, 0x00, 0x03, 0x74, 0x65,
+ 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xcd, 0x7b, 0x7f, 0x70,
+ 0x1b, 0xe7, 0x99, 0xde, 0xbb, 0x0b, 0x80, 0x04, 0x29, 0x8a, 0x5a, 0x31,
+ 0x30, 0x83, 0x38, 0xb4, 0x8d, 0x15, 0x17, 0x34, 0x6d, 0xf2, 0x1c, 0x58,
+ 0xe5, 0xf9, 0xd8, 0x06, 0xb5, 0xd7, 0xc0, 0x92, 0xa2, 0x63, 0x26, 0x47,
+ 0xbb, 0xcc, 0x9d, 0x92, 0x51, 0x7d, 0x28, 0x48, 0x29, 0x6e, 0xe3, 0xb4,
+ 0xaa, 0xe3, 0x3f, 0x34, 0x4d, 0x5b, 0xc3, 0x00, 0x25, 0xcb, 0x2e, 0x44,
+ 0xd0, 0x16, 0x63, 0xa5, 0x33, 0x37, 0x53, 0x18, 0x80, 0x28, 0xe7, 0xba,
+ 0x24, 0xdc, 0xe4, 0x2e, 0xe9, 0x1f, 0xc9, 0x99, 0xa5, 0x6c, 0xc5, 0x6d,
+ 0xae, 0x33, 0xbe, 0x3f, 0xda, 0xa6, 0x37, 0xd7, 0x19, 0x8d, 0xfc, 0x23,
+ 0xce, 0x8f, 0xb9, 0xb8, 0x69, 0x7a, 0x56, 0x5b, 0xd9, 0xe8, 0xf3, 0x7c,
+ 0xbb, 0x4b, 0x82, 0x32, 0x15, 0x5b, 0xd7, 0x76, 0xa6, 0x9c, 0xc1, 0x10,
+ 0xfb, 0xed, 0xb7, 0xdf, 0xf7, 0xfe, 0x7e, 0xdf, 0xe7, 0xfd, 0x16, 0x71,
+ 0x91, 0x6e, 0xf1, 0xff, 0x76, 0xe3, 0x93, 0x38, 0x7a, 0xec, 0xb1, 0x3b,
+ 0xc6, 0xef, 0xd8, 0x2f, 0x72, 0xe7, 0x9d, 0xb2, 0x2b, 0xaa, 0xf3, 0xe6,
+ 0xdb, 0x21, 0x91, 0xdc, 0x4f, 0xe5, 0xaf, 0xfc, 0x87, 0xc7, 0x8d, 0x60,
+ 0x7d, 0x7e, 0x24, 0xaa, 0xa7, 0x5f, 0xcc, 0x64, 0x2c, 0x89, 0x86, 0xd2,
+ 0x33, 0x9f, 0x9d, 0xb3, 0x44, 0x6c, 0x77, 0x24, 0x91, 0x95, 0xf7, 0x5a,
+ 0x85, 0x58, 0x58, 0x38, 0x7e, 0x53, 0xfa, 0xca, 0xe3, 0xdf, 0xff, 0x2d,
+ 0xf3, 0x9d, 0x6a, 0x48, 0xa2, 0x46, 0x3a, 0x27, 0xc6, 0x90, 0x44, 0x07,
+ 0xf0, 0xcc, 0xef, 0xdf, 0x3a, 0xa5, 0x4b, 0x6f, 0xb0, 0x56, 0x5c, 0x16,
+ 0x2a, 0x6f, 0xb7, 0xbe, 0x7f, 0x6b, 0x4c, 0xfe, 0x55, 0xd3, 0x90, 0x17,
+ 0x9b, 0x61, 0x6d, 0xb2, 0xd2, 0x23, 0xa5, 0x8a, 0x2b, 0xc7, 0xcb, 0x05,
+ 0xc9, 0x36, 0x5f, 0x90, 0xe2, 0xb2, 0xd1, 0x9b, 0x39, 0xf7, 0x07, 0x52,
+ 0x5a, 0xee, 0xeb, 0xcd, 0x9e, 0x73, 0xa5, 0x58, 0x8e, 0xf7, 0x66, 0x9a,
+ 0x46, 0x6f, 0xf6, 0x4c, 0x0c, 0xd7, 0x7d, 0xbd, 0x99, 0x33, 0x66, 0x41,
+ 0xa4, 0x1f, 0x73, 0xe2, 0xbd, 0xd9, 0x8a, 0x99, 0x13, 0x19, 0x4c, 0xbd,
+ 0x22, 0x03, 0xbd, 0xd9, 0x66, 0x4d, 0x5b, 0x37, 0x34, 0x29, 0xfe, 0x86,
+ 0x18, 0xbd, 0xe9, 0xcb, 0xad, 0x4f, 0x58, 0x86, 0xec, 0xb5, 0x64, 0xcf,
+ 0x1e, 0x4b, 0x9e, 0x88, 0xa7, 0xa3, 0x92, 0x3f, 0xdd, 0x25, 0xb6, 0xe2,
+ 0xc9, 0x90, 0xfc, 0x99, 0x11, 0x63, 0x43, 0x22, 0x62, 0xc7, 0x82, 0xeb,
+ 0x56, 0x2b, 0x93, 0xfa, 0x02, 0xe5, 0x8a, 0xbd, 0xa4, 0x77, 0xb2, 0x29,
+ 0x92, 0xa9, 0x44, 0x25, 0x93, 0x7a, 0xaf, 0xe5, 0x3d, 0x13, 0xc5, 0xbe,
+ 0xe1, 0xde, 0x89, 0x4a, 0xab, 0xe5, 0xa4, 0xb0, 0x47, 0x2a, 0x78, 0x36,
+ 0x22, 0xd5, 0x98, 0x5d, 0x2d, 0xa5, 0x4c, 0xdd, 0xd3, 0x09, 0x79, 0xe4,
+ 0xb5, 0x2d, 0xba, 0xf5, 0xdb, 0x92, 0x8f, 0x49, 0xb5, 0x98, 0xba, 0x4b,
+ 0x9e, 0x4e, 0x19, 0x72, 0x12, 0xeb, 0x3d, 0x95, 0x82, 0x1c, 0xad, 0x63,
+ 0x5a, 0xa6, 0x69, 0xc6, 0x45, 0x7b, 0x5a, 0x32, 0x67, 0x06, 0x8d, 0xac,
+ 0x60, 0x6f, 0xab, 0x75, 0x4b, 0x26, 0x85, 0xfd, 0x46, 0xff, 0x67, 0xcb,
+ 0x8e, 0x99, 0xb9, 0xaa, 0x0c, 0x48, 0xb1, 0x32, 0x98, 0xfa, 0x13, 0xd1,
+ 0xa4, 0xd3, 0xa2, 0x7c, 0x5a, 0x72, 0x3f, 0xf6, 0xcd, 0x58, 0x18, 0x6f,
+ 0x8a, 0xad, 0x27, 0x23, 0xf2, 0x0f, 0x0c, 0x33, 0x91, 0x09, 0xf5, 0x4b,
+ 0xf1, 0x74, 0x27, 0xe8, 0xb4, 0xfb, 0x74, 0xcc, 0x3d, 0x30, 0x26, 0xb1,
+ 0x5d, 0x22, 0x5a, 0x28, 0x9d, 0xc4, 0xba, 0x22, 0x45, 0x77, 0x00, 0xcf,
+ 0x26, 0xc7, 0x7f, 0x2a, 0x7b, 0x24, 0xb1, 0x37, 0x2c, 0x25, 0xb7, 0x1b,
+ 0x72, 0x34, 0xa0, 0x83, 0xe4, 0xf8, 0x5f, 0x40, 0x29, 0xba, 0x95, 0x8c,
+ 0x1f, 0x93, 0x9c, 0x96, 0x6d, 0x76, 0x48, 0x29, 0x19, 0x95, 0x05, 0xd0,
+ 0xb1, 0x90, 0xfa, 0xa2, 0x96, 0x39, 0x77, 0x50, 0xcb, 0x9e, 0xc3, 0xbc,
+ 0x66, 0xdd, 0xb7, 0x35, 0x03, 0xeb, 0xe8, 0x52, 0x4c, 0x1e, 0xc4, 0xbd,
+ 0xa8, 0xcc, 0x61, 0xde, 0x1c, 0x78, 0x2a, 0x35, 0xf7, 0xc8, 0xfa, 0x6c,
+ 0xac, 0x37, 0x03, 0x1d, 0x16, 0x71, 0xff, 0xb7, 0x67, 0x34, 0x31, 0x2c,
+ 0x5b, 0x7e, 0x3c, 0x06, 0x1d, 0x9e, 0x81, 0xfe, 0xce, 0xc4, 0xe5, 0x78,
+ 0x45, 0x62, 0xba, 0x24, 0xe3, 0x79, 0x79, 0x41, 0xea, 0x2e, 0xf5, 0x0f,
+ 0x7d, 0x42, 0xdf, 0x45, 0x97, 0xcf, 0x41, 0x6f, 0x15, 0x07, 0xf2, 0x98,
+ 0x02, 0x0d, 0x0f, 0x6a, 0xf7, 0xd7, 0x67, 0xb5, 0x03, 0xcd, 0x1f, 0x6b,
+ 0xd2, 0x7d, 0x4c, 0xfb, 0x5c, 0xf3, 0x88, 0xe6, 0xcb, 0x1e, 0xba, 0x8b,
+ 0x8a, 0x3d, 0x13, 0x95, 0x95, 0xa6, 0xa7, 0xbb, 0x1a, 0xec, 0xd3, 0x36,
+ 0x6c, 0xe8, 0xe1, 0x6f, 0x6f, 0xce, 0x59, 0x69, 0xc6, 0x64, 0x01, 0xb4,
+ 0x1d, 0x6f, 0x72, 0xfe, 0xef, 0x41, 0x3f, 0x51, 0x71, 0x6f, 0xed, 0x91,
+ 0x1c, 0xc6, 0x8b, 0x67, 0xc4, 0xce, 0xa4, 0x74, 0x3c, 0xd3, 0x2b, 0x21,
+ 0xab, 0x1f, 0x9f, 0x6e, 0x99, 0xab, 0x77, 0xda, 0x21, 0x2b, 0x26, 0x73,
+ 0x4d, 0xca, 0x10, 0xff, 0x2b, 0x81, 0x1c, 0x49, 0x2b, 0xc7, 0xf9, 0x1c,
+ 0xc7, 0x0d, 0x8c, 0xb7, 0x8f, 0xd1, 0x2e, 0x7a, 0x41, 0x8f, 0x39, 0x2c,
+ 0x18, 0xcb, 0x57, 0x92, 0xc6, 0xe7, 0xf8, 0xbf, 0x49, 0xd9, 0x06, 0x32,
+ 0x0d, 0x63, 0xae, 0x2e, 0xf9, 0x3a, 0xf6, 0x39, 0x7d, 0xa5, 0x15, 0x19,
+ 0xc3, 0xb5, 0xf5, 0x4b, 0xc8, 0x92, 0xfb, 0x86, 0x41, 0x93, 0x2e, 0xb9,
+ 0x3a, 0xd7, 0xe2, 0x7d, 0x81, 0xee, 0x8b, 0x7b, 0x75, 0x19, 0x86, 0x7e,
+ 0x4d, 0xec, 0xd3, 0x85, 0x39, 0x3d, 0x90, 0x1f, 0x78, 0x3d, 0x87, 0xef,
+ 0xe0, 0x5d, 0xb7, 0x74, 0x3c, 0xdf, 0x29, 0x73, 0x29, 0xda, 0x0b, 0xe9,
+ 0xdc, 0x85, 0xb5, 0xbb, 0x64, 0xfe, 0x34, 0xe5, 0x01, 0xbb, 0xaa, 0xc4,
+ 0xa4, 0x74, 0xc6, 0x34, 0x1c, 0x31, 0x21, 0x1b, 0x1b, 0xf3, 0x3a, 0x25,
+ 0x67, 0xb4, 0x5a, 0x13, 0xa9, 0x11, 0xe3, 0x9b, 0xca, 0xce, 0x47, 0x8c,
+ 0xa4, 0x26, 0x85, 0x8e, 0xf4, 0x10, 0x64, 0x6b, 0x1e, 0x14, 0xe1, 0xf5,
+ 0x0f, 0xc4, 0x9e, 0xa5, 0xff, 0xc4, 0xb8, 0x17, 0xfc, 0xa9, 0x1f, 0xf4,
+ 0xd3, 0xe7, 0x06, 0xa0, 0x97, 0xb8, 0xf2, 0x83, 0x89, 0x1d, 0xfd, 0xc0,
+ 0x9c, 0xaa, 0x82, 0xdf, 0xe2, 0xb9, 0x30, 0xfd, 0x2f, 0x05, 0x73, 0x93,
+ 0x5d, 0x56, 0x14, 0xb6, 0x40, 0x5a, 0xc6, 0xb1, 0x7e, 0xab, 0xf5, 0xd9,
+ 0x94, 0x47, 0x53, 0xf1, 0x8c, 0x8d, 0x67, 0xc3, 0x90, 0xbb, 0xf9, 0x70,
+ 0x42, 0xed, 0x3f, 0xee, 0xef, 0x6f, 0xc8, 0x1c, 0xe8, 0x2e, 0x56, 0x42,
+ 0x92, 0x35, 0xb8, 0xc6, 0x9f, 0x71, 0x3c, 0xe7, 0xad, 0x05, 0xbb, 0x3d,
+ 0x35, 0x68, 0xdc, 0x07, 0x5f, 0xa2, 0x8f, 0x15, 0x57, 0x29, 0x63, 0xac,
+ 0x33, 0x46, 0x19, 0x1b, 0x8a, 0xc6, 0xcc, 0x19, 0xda, 0x91, 0x0c, 0x84,
+ 0x84, 0x76, 0x8e, 0x98, 0x01, 0xbb, 0x2a, 0xf9, 0x76, 0x95, 0x77, 0xa9,
+ 0xff, 0xbb, 0x7d, 0xff, 0xd4, 0x65, 0x28, 0x49, 0x7b, 0x7f, 0x5a, 0xb2,
+ 0xf0, 0xf1, 0x39, 0xec, 0x54, 0x07, 0x4f, 0xb5, 0xca, 0x20, 0x64, 0x15,
+ 0xf8, 0x1d, 0xf4, 0x3b, 0xfa, 0x6e, 0x2b, 0x88, 0x05, 0xc5, 0x0a, 0x7d,
+ 0xa6, 0x68, 0xe8, 0x52, 0xc0, 0x07, 0x76, 0x63, 0x99, 0xc3, 0x99, 0x90,
+ 0x39, 0x93, 0x03, 0x6d, 0xb0, 0x7b, 0xc9, 0xdc, 0x49, 0x7b, 0xc6, 0x9c,
+ 0xa6, 0xec, 0x0f, 0xfc, 0xac, 0xe6, 0x52, 0x4f, 0xdd, 0xd8, 0x37, 0xa0,
+ 0x29, 0x8c, 0x31, 0xae, 0x13, 0x85, 0xcd, 0x07, 0x36, 0x43, 0xfb, 0x33,
+ 0xed, 0x75, 0xe9, 0x90, 0xe1, 0x24, 0x62, 0xd9, 0x19, 0x1d, 0xfa, 0x1b,
+ 0x40, 0x4c, 0x09, 0xcb, 0x11, 0xc8, 0xea, 0x4b, 0x15, 0xd2, 0xe7, 0xc0,
+ 0xef, 0x10, 0xdb, 0xce, 0x4c, 0xc2, 0xcf, 0xa6, 0xb4, 0x09, 0xf8, 0xc4,
+ 0x67, 0xea, 0xa4, 0xa9, 0x25, 0xf4, 0x4b, 0xe7, 0x5c, 0x4e, 0x9b, 0x6c,
+ 0x1e, 0xd4, 0xa6, 0xce, 0xd1, 0x4f, 0xe8, 0x23, 0xa6, 0xf1, 0x80, 0x78,
+ 0x3c, 0x14, 0x9b, 0xaf, 0x68, 0xf4, 0xd5, 0xe2, 0xa9, 0x2e, 0xd0, 0xb1,
+ 0x0b, 0xf4, 0x18, 0xf0, 0x3d, 0xd8, 0x97, 0x65, 0xce, 0xd0, 0x66, 0x9c,
+ 0xa4, 0x95, 0xf8, 0xe7, 0xf2, 0x41, 0x39, 0x4c, 0x6c, 0xca, 0x61, 0x04,
+ 0x32, 0xd9, 0x2e, 0x87, 0x85, 0x0f, 0xca, 0xc1, 0x2e, 0x40, 0x0e, 0x0b,
+ 0x88, 0x43, 0x0b, 0x4d, 0xf2, 0xdc, 0x12, 0xfd, 0x4e, 0x81, 0x75, 0xca,
+ 0xbd, 0x7a, 0x9a, 0x36, 0x4a, 0x3f, 0x49, 0x26, 0x4a, 0x58, 0xa1, 0xe1,
+ 0xf6, 0x28, 0xdf, 0x98, 0x54, 0xb2, 0xf8, 0x30, 0x7e, 0xc9, 0xdf, 0x16,
+ 0xcf, 0x53, 0x75, 0xc6, 0x1b, 0xd8, 0x79, 0xd2, 0x32, 0xbe, 0x20, 0x5b,
+ 0x7c, 0xdf, 0xb7, 0xc5, 0x37, 0xf6, 0x09, 0x62, 0x10, 0x79, 0x0e, 0xe2,
+ 0x31, 0x6d, 0xe5, 0xa5, 0x56, 0xc8, 0xb2, 0xa0, 0x03, 0xda, 0x0b, 0x69,
+ 0x30, 0x8d, 0xcf, 0x0a, 0xfe, 0x23, 0x2e, 0xd0, 0x97, 0x72, 0x6a, 0x5e,
+ 0x87, 0xe4, 0xf6, 0x7a, 0xf3, 0xe7, 0x2a, 0xad, 0x5f, 0xe8, 0xe9, 0xf7,
+ 0x5b, 0x99, 0x31, 0xcb, 0xf7, 0xf1, 0xa8, 0x7c, 0xb9, 0x6e, 0xe6, 0x12,
+ 0x5a, 0x8f, 0x14, 0x6e, 0x40, 0x5c, 0xa9, 0xd0, 0x3f, 0xfa, 0xaf, 0x11,
+ 0xcb, 0x06, 0xfc, 0x58, 0xf6, 0x13, 0xc8, 0x9e, 0xb9, 0xe7, 0xf0, 0xfb,
+ 0xeb, 0x31, 0xfe, 0x4f, 0x1a, 0x33, 0xf2, 0x05, 0xe6, 0x9b, 0x3d, 0xba,
+ 0x8a, 0xdf, 0x16, 0x73, 0x41, 0x21, 0x9c, 0xee, 0x96, 0xc2, 0x5e, 0x29,
+ 0x84, 0xd2, 0xf4, 0x23, 0xfa, 0x46, 0x87, 0x4f, 0x77, 0x90, 0x3b, 0xf8,
+ 0x77, 0x4c, 0x17, 0x8b, 0x73, 0x90, 0x27, 0x2a, 0xe4, 0xe3, 0xbd, 0x40,
+ 0x27, 0x78, 0x46, 0x22, 0x9e, 0xcd, 0x4d, 0x23, 0x66, 0x52, 0xa6, 0xed,
+ 0xf6, 0xc2, 0x58, 0x2a, 0x09, 0xdd, 0x62, 0x2c, 0x15, 0x23, 0x94, 0x7e,
+ 0x50, 0xb3, 0xeb, 0x5f, 0xd4, 0x6c, 0xc8, 0xce, 0x86, 0xec, 0x6c, 0xc8,
+ 0x2e, 0x03, 0xd9, 0x65, 0x9b, 0xa4, 0x87, 0xb4, 0x78, 0xeb, 0x3b, 0xde,
+ 0xfa, 0xa0, 0xb3, 0x5f, 0xf2, 0xca, 0xc7, 0xc9, 0x2f, 0x62, 0xb2, 0x8a,
+ 0x07, 0x93, 0x9a, 0x17, 0x0f, 0xb8, 0xde, 0x14, 0x9e, 0xbf, 0x1b, 0x79,
+ 0xce, 0xd6, 0x75, 0x6b, 0x4b, 0x26, 0x0b, 0x6d, 0x32, 0x29, 0xb9, 0x94,
+ 0x11, 0xe7, 0xd3, 0x97, 0x5d, 0xe8, 0x3d, 0x90, 0xcb, 0x34, 0x68, 0xe8,
+ 0x24, 0xef, 0x3e, 0x1f, 0x5c, 0xbf, 0xcf, 0x5f, 0xff, 0xd3, 0x58, 0x93,
+ 0xbe, 0xbb, 0xd3, 0xbe, 0xdc, 0x93, 0xb9, 0xf4, 0xd7, 0xf1, 0x83, 0x5a,
+ 0x02, 0x31, 0xfa, 0x45, 0xf8, 0xda, 0xc5, 0x50, 0x5c, 0xbe, 0x7f, 0xeb,
+ 0x6b, 0xa8, 0x2f, 0xa4, 0x70, 0x63, 0xba, 0x95, 0x08, 0xa7, 0xdf, 0x6b,
+ 0x2d, 0x8c, 0x21, 0x7e, 0xa6, 0xcd, 0x78, 0x26, 0x34, 0x2a, 0x2f, 0x35,
+ 0x87, 0xe5, 0x3b, 0x4d, 0x4b, 0xfe, 0xa8, 0x99, 0x90, 0x3f, 0x6c, 0x0e,
+ 0xc8, 0xb7, 0x9b, 0x71, 0xf9, 0x56, 0x33, 0xa8, 0x45, 0xe2, 0xb4, 0xa5,
+ 0x5e, 0xa7, 0xb9, 0x53, 0x3d, 0x04, 0x3b, 0xc7, 0x5a, 0x99, 0xb1, 0x70,
+ 0x2e, 0x94, 0x56, 0x35, 0xc2, 0xcc, 0xd1, 0xf2, 0xe3, 0x2d, 0xdd, 0xb2,
+ 0x0a, 0xba, 0xde, 0x33, 0x6e, 0xdc, 0x25, 0x39, 0x3d, 0x8d, 0x31, 0x77,
+ 0x3c, 0xec, 0x94, 0xbb, 0x90, 0x5f, 0xa2, 0xa8, 0x65, 0x06, 0xa4, 0x80,
+ 0x75, 0x0b, 0xcd, 0x56, 0x6b, 0x29, 0xf5, 0x0f, 0x3f, 0x65, 0xfc, 0x8d,
+ 0x7f, 0xd9, 0x29, 0xbd, 0xdf, 0x5e, 0x37, 0x86, 0xfe, 0xbb, 0x5f, 0x0f,
+ 0xa1, 0xc6, 0xea, 0x57, 0x8b, 0xe7, 0xb4, 0xf4, 0xa8, 0x93, 0x70, 0x37,
+ 0x70, 0x5f, 0xa2, 0xfd, 0xd6, 0xcf, 0x51, 0x85, 0xc8, 0xee, 0x98, 0xc5,
+ 0x9a, 0x6b, 0x26, 0xfb, 0x79, 0xfc, 0xff, 0x58, 0x5a, 0xf6, 0xf4, 0xe1,
+ 0xff, 0xde, 0x34, 0x4c, 0x2a, 0xcd, 0x98, 0xac, 0xb5, 0xc5, 0x64, 0xd1,
+ 0x1c, 0xe4, 0xdf, 0x05, 0xf0, 0xe4, 0x40, 0x1e, 0xbf, 0xd3, 0x8c, 0x6a,
+ 0xd9, 0xd3, 0xfd, 0x52, 0xaa, 0x33, 0xaf, 0x71, 0x5e, 0xd4, 0xaf, 0x7b,
+ 0x78, 0xdd, 0x81, 0x6b, 0x41, 0xae, 0xf9, 0x94, 0x48, 0xaf, 0xf9, 0xa3,
+ 0xcf, 0x4b, 0xdd, 0xaf, 0x5b, 0x22, 0xb2, 0xac, 0x6c, 0x8c, 0xe3, 0xaf,
+ 0x65, 0xbf, 0x36, 0xb4, 0x35, 0xfe, 0xec, 0xe6, 0xf8, 0x3b, 0xd9, 0x4f,
+ 0x6f, 0x8e, 0x77, 0x87, 0x3d, 0x1e, 0xc6, 0xb5, 0x99, 0x66, 0xc1, 0x1f,
+ 0xbb, 0x0c, 0xb9, 0xb7, 0x5a, 0x0b, 0xc8, 0x3d, 0x45, 0xeb, 0x32, 0xea,
+ 0x24, 0xc6, 0x9f, 0xeb, 0x89, 0x37, 0xdb, 0x62, 0x8d, 0x91, 0x09, 0x51,
+ 0x9f, 0x51, 0xf1, 0xd6, 0xe4, 0xfd, 0x4e, 0xc4, 0x9d, 0xcb, 0xf8, 0xce,
+ 0x3c, 0x17, 0xc4, 0x3c, 0xce, 0xe1, 0xf3, 0x6f, 0x5f, 0x43, 0xe7, 0x31,
+ 0xe8, 0xfc, 0xff, 0x1b, 0xdd, 0xe2, 0x4f, 0xe9, 0x56, 0xc5, 0x9d, 0x97,
+ 0xb6, 0xd9, 0x2c, 0xe9, 0xef, 0xf6, 0x69, 0x96, 0x68, 0x38, 0x6d, 0x38,
+ 0x0b, 0xd6, 0x8d, 0x12, 0x41, 0x0d, 0x4b, 0x9b, 0x2d, 0x35, 0xbf, 0x8b,
+ 0xe7, 0x99, 0x27, 0x25, 0x1a, 0x49, 0xd3, 0x2e, 0xd6, 0x07, 0x32, 0xd6,
+ 0x31, 0xa7, 0xe6, 0x1e, 0x73, 0xce, 0x2a, 0x3b, 0x59, 0xbf, 0xc9, 0xab,
+ 0xcd, 0x7f, 0x74, 0x13, 0x6a, 0x73, 0x3c, 0xcf, 0x98, 0xcb, 0xf1, 0x46,
+ 0x4f, 0xc6, 0x62, 0x0e, 0x5a, 0x72, 0x8a, 0xf8, 0x2c, 0xa8, 0xb9, 0xaf,
+ 0x0e, 0x70, 0x6e, 0x67, 0x3a, 0x76, 0xd3, 0x8f, 0xf1, 0xbf, 0x23, 0xfd,
+ 0xce, 0x4d, 0x17, 0x2c, 0xae, 0x3b, 0x75, 0xd3, 0x59, 0xb5, 0x46, 0x18,
+ 0xf1, 0x8c, 0xf3, 0x2e, 0xdf, 0xc4, 0x67, 0x9f, 0x44, 0x1c, 0x3f, 0xe1,
+ 0x42, 0x97, 0xee, 0x8b, 0x4e, 0x1e, 0x9f, 0x39, 0xd2, 0x54, 0xe1, 0x7d,
+ 0xe3, 0xe6, 0x8c, 0x15, 0x56, 0xf9, 0xf6, 0x4b, 0x98, 0x73, 0x04, 0x73,
+ 0x0e, 0xbb, 0x01, 0x3f, 0xea, 0xbe, 0x93, 0xc5, 0xfd, 0xc3, 0x65, 0xc3,
+ 0x71, 0xca, 0xe6, 0x38, 0x6a, 0x8e, 0xf8, 0x71, 0xe4, 0xe3, 0x1c, 0x72,
+ 0xa0, 0x2d, 0xe6, 0x70, 0x41, 0xd2, 0x5d, 0x93, 0xa8, 0xe5, 0x56, 0x90,
+ 0x4f, 0x50, 0x87, 0xa4, 0xaa, 0x32, 0xd8, 0x95, 0x39, 0xad, 0xc3, 0x3e,
+ 0xef, 0x80, 0xbd, 0x1a, 0x8e, 0x9e, 0x44, 0x5c, 0x47, 0xdc, 0x5c, 0xa8,
+ 0x58, 0x5a, 0xb6, 0x3c, 0x68, 0x94, 0xe4, 0x56, 0x59, 0x37, 0xcc, 0xf8,
+ 0xa4, 0xec, 0x92, 0x6c, 0x18, 0xf3, 0x86, 0x3f, 0x2e, 0xb9, 0xb8, 0x86,
+ 0xd8, 0x70, 0x03, 0xe2, 0x16, 0xeb, 0xe4, 0xf6, 0x18, 0xfa, 0x0b, 0x11,
+ 0xeb, 0x8b, 0x21, 0xc6, 0x9e, 0x4e, 0x8b, 0x75, 0x3f, 0xe7, 0xed, 0x92,
+ 0x8d, 0x0f, 0xcc, 0x7b, 0xb7, 0x6d, 0x5e, 0xfb, 0xf8, 0x7b, 0x18, 0xdf,
+ 0x25, 0x17, 0x41, 0x47, 0x38, 0x39, 0x26, 0x25, 0xf0, 0x10, 0x39, 0xd5,
+ 0x6a, 0x5d, 0x00, 0x3f, 0x3a, 0xf8, 0x2f, 0x56, 0x59, 0x0b, 0x84, 0xa4,
+ 0x6a, 0xe0, 0x9e, 0xdb, 0x6a, 0xd5, 0x10, 0x46, 0xf5, 0x55, 0xd2, 0x1c,
+ 0x95, 0x49, 0x77, 0x48, 0xec, 0x06, 0xe5, 0x60, 0xc2, 0xeb, 0xfe, 0xac,
+ 0x2b, 0x7b, 0x86, 0x39, 0x13, 0x16, 0xb1, 0xfa, 0xe7, 0x5d, 0x19, 0xe4,
+ 0x3e, 0x7d, 0xf5, 0x62, 0x57, 0x16, 0x7a, 0x0f, 0xad, 0xfe, 0xe7, 0x2e,
+ 0xe7, 0x34, 0xe9, 0x0a, 0x21, 0xf7, 0xdd, 0x22, 0x45, 0xa3, 0x25, 0xdf,
+ 0x44, 0x8d, 0x50, 0x1c, 0x46, 0x2e, 0x83, 0x17, 0xe8, 0xa0, 0xbb, 0x60,
+ 0x48, 0xb4, 0x3b, 0xfd, 0x7d, 0xd0, 0x37, 0x06, 0xd9, 0xec, 0xc2, 0x9c,
+ 0x10, 0xc6, 0x87, 0xf0, 0xbf, 0x7d, 0xfc, 0x8d, 0x2e, 0xe4, 0x05, 0xc4,
+ 0x60, 0x89, 0x66, 0xc6, 0x7a, 0xb0, 0xfe, 0xf7, 0x30, 0x8e, 0x09, 0xc9,
+ 0xcd, 0xf1, 0x27, 0xbc, 0xf1, 0xb7, 0x41, 0x0b, 0x9f, 0x63, 0x8d, 0x22,
+ 0xd1, 0xb9, 0x31, 0x03, 0x34, 0x70, 0x6e, 0x4c, 0xcd, 0x75, 0xce, 0xd0,
+ 0x06, 0x0c, 0xa7, 0x66, 0xdd, 0x2c, 0xd9, 0xe5, 0x7e, 0x99, 0x5c, 0xee,
+ 0x93, 0x03, 0xcb, 0xe6, 0x4c, 0x95, 0xd8, 0x0f, 0x3c, 0x0b, 0xea, 0x30,
+ 0x7d, 0x55, 0x20, 0x01, 0x33, 0x7e, 0x44, 0x06, 0xe3, 0x5f, 0x92, 0x5f,
+ 0xb6, 0x90, 0xef, 0x91, 0xeb, 0x7b, 0x24, 0xac, 0xd6, 0x89, 0x07, 0x7b,
+ 0xd2, 0x46, 0xb7, 0xed, 0xeb, 0x9c, 0xb9, 0xd6, 0xba, 0x70, 0xfe, 0xd5,
+ 0xf8, 0x55, 0xeb, 0xfe, 0x85, 0xbf, 0xae, 0x81, 0x75, 0x07, 0xb0, 0x26,
+ 0x79, 0x34, 0xbb, 0x26, 0x4e, 0x8b, 0xdd, 0x09, 0xfa, 0x9c, 0xe4, 0x8d,
+ 0xc0, 0x86, 0xfd, 0x72, 0x62, 0x99, 0xf1, 0x42, 0xfa, 0xf1, 0x19, 0x8d,
+ 0x48, 0x72, 0xf8, 0x1c, 0xea, 0xae, 0x09, 0xb5, 0x86, 0x57, 0x93, 0xe9,
+ 0xab, 0x29, 0xd4, 0xc4, 0x3f, 0x05, 0x3d, 0xac, 0x15, 0xc8, 0x73, 0x18,
+ 0xfc, 0xa6, 0x50, 0x8b, 0x11, 0x47, 0xb5, 0x1e, 0xcf, 0xa4, 0xf0, 0xfd,
+ 0x5c, 0xa2, 0x2b, 0x8b, 0x98, 0x08, 0xff, 0xbe, 0x39, 0xa4, 0x72, 0x18,
+ 0xf5, 0x32, 0xda, 0x45, 0x3c, 0x83, 0xe7, 0xa1, 0x27, 0xca, 0x68, 0xbc,
+ 0xcb, 0xa9, 0x50, 0x46, 0x02, 0x7a, 0x2c, 0xd8, 0x64, 0x58, 0x61, 0x29,
+ 0x7d, 0xd5, 0xc6, 0xbc, 0xb7, 0x42, 0xac, 0x77, 0x33, 0x16, 0xbf, 0x23,
+ 0xe6, 0xac, 0x4e, 0x61, 0x2e, 0xbf, 0xdf, 0x85, 0x75, 0x07, 0x87, 0x8b,
+ 0xd2, 0x31, 0x7c, 0x18, 0xf1, 0x4e, 0x1f, 0x1b, 0x01, 0x6d, 0xb4, 0xf3,
+ 0x16, 0xb0, 0xc0, 0x6f, 0x81, 0x1f, 0xf8, 0x46, 0xd2, 0x92, 0xf9, 0x25,
+ 0xca, 0x55, 0x3e, 0x0e, 0x1e, 0xc0, 0x7f, 0x12, 0x71, 0x8d, 0x3c, 0x70,
+ 0x6f, 0x41, 0x8e, 0xbe, 0x5b, 0xf2, 0x4b, 0x51, 0x55, 0xeb, 0xdb, 0x06,
+ 0xf7, 0xd7, 0x34, 0x3d, 0xdd, 0x0d, 0x1d, 0x93, 0xb7, 0x1c, 0x68, 0x7b,
+ 0x0c, 0x79, 0x80, 0xbc, 0x91, 0x2f, 0xfa, 0xca, 0x28, 0xfc, 0x84, 0xf4,
+ 0xfb, 0xb6, 0xa7, 0xad, 0x23, 0xa6, 0xa8, 0x38, 0x98, 0xca, 0x20, 0xb0,
+ 0xbd, 0xd4, 0x1c, 0x97, 0x3f, 0x6e, 0x8e, 0xc9, 0x77, 0x9b, 0x29, 0xe4,
+ 0xc0, 0x51, 0xe4, 0xc0, 0x61, 0xe4, 0x40, 0x0b, 0x39, 0x30, 0x81, 0x1c,
+ 0x38, 0x80, 0x1c, 0x18, 0x47, 0x9c, 0x14, 0x39, 0xa1, 0xf2, 0x6d, 0x2c,
+ 0x0a, 0xcc, 0x1d, 0xb5, 0x9b, 0x0e, 0x78, 0x99, 0xc1, 0x5e, 0xb3, 0xe0,
+ 0xeb, 0x50, 0xd7, 0x44, 0x65, 0x1c, 0x31, 0xd7, 0x42, 0x3c, 0x4a, 0x20,
+ 0xdf, 0x8c, 0x01, 0x6b, 0x89, 0x6c, 0x2c, 0x25, 0x10, 0x13, 0x5b, 0xe2,
+ 0x00, 0x13, 0x97, 0x8c, 0x14, 0x9e, 0xdd, 0xab, 0xec, 0x33, 0x94, 0xbe,
+ 0x3b, 0x2c, 0xdd, 0xa3, 0x92, 0x2f, 0x9f, 0xc4, 0x58, 0x1c, 0xeb, 0x75,
+ 0x21, 0x2f, 0x31, 0x2e, 0x30, 0x06, 0x2c, 0x39, 0xbf, 0x6b, 0xd1, 0xd7,
+ 0xba, 0xb5, 0xcc, 0xe9, 0x82, 0x30, 0x96, 0x23, 0x0f, 0xc0, 0x1e, 0x38,
+ 0x36, 0x89, 0xe7, 0xf8, 0xfd, 0x2f, 0xfd, 0x98, 0xf9, 0xb1, 0x4e, 0x81,
+ 0xd1, 0xbe, 0xc4, 0x9c, 0x67, 0x61, 0x3d, 0xb7, 0xdd, 0x4f, 0x9f, 0x47,
+ 0xad, 0x14, 0xdc, 0x27, 0xae, 0x66, 0x3f, 0xe1, 0x24, 0x68, 0x1e, 0x04,
+ 0xbe, 0x47, 0x6d, 0x75, 0xb0, 0x8a, 0xef, 0xed, 0xf3, 0x5d, 0xcc, 0x57,
+ 0x63, 0x51, 0x23, 0x6d, 0xb1, 0x9e, 0x43, 0xac, 0x3c, 0x86, 0xb8, 0x68,
+ 0x3b, 0xfa, 0x5a, 0x03, 0x7c, 0x42, 0x8e, 0x65, 0xdb, 0x09, 0x0f, 0xbd,
+ 0xd6, 0x7a, 0xd6, 0x1a, 0x96, 0x89, 0xb5, 0x31, 0xc9, 0xae, 0x0d, 0xc6,
+ 0xcf, 0x4b, 0xd7, 0x65, 0x5b, 0x5e, 0x6b, 0x95, 0x5c, 0xf3, 0xa4, 0x0d,
+ 0xbb, 0xdc, 0xb7, 0xdf, 0x90, 0x1a, 0x30, 0xdc, 0xbe, 0xfd, 0x9d, 0xac,
+ 0xe9, 0x5f, 0x14, 0x3d, 0x21, 0x99, 0x45, 0x5b, 0xc6, 0xf6, 0x07, 0xb5,
+ 0xe7, 0x2f, 0x3b, 0xa4, 0x1b, 0x63, 0x6b, 0x09, 0xcc, 0x61, 0xdd, 0xaf,
+ 0xfa, 0x27, 0xe0, 0x59, 0xf3, 0x9e, 0x51, 0x39, 0x8f, 0x98, 0x19, 0xbc,
+ 0x37, 0x6d, 0xe7, 0xfc, 0x22, 0x70, 0x0d, 0xe4, 0x99, 0x59, 0x24, 0xee,
+ 0xda, 0x05, 0x39, 0x45, 0x60, 0x23, 0xd4, 0xfd, 0x20, 0x9e, 0x6d, 0xc9,
+ 0x57, 0x53, 0xb4, 0x87, 0xc7, 0x20, 0x4b, 0xac, 0x15, 0x0e, 0xf8, 0xf9,
+ 0x9a, 0xcc, 0x2d, 0x51, 0x7e, 0x71, 0xd4, 0x96, 0xdc, 0x5b, 0xa2, 0x5d,
+ 0xe9, 0xab, 0xeb, 0x46, 0xdb, 0xd9, 0x58, 0xc4, 0xfa, 0x43, 0xc4, 0xd8,
+ 0x88, 0xd5, 0x65, 0xf6, 0x06, 0x58, 0x53, 0x1d, 0x80, 0x4e, 0xa6, 0x15,
+ 0xe6, 0xce, 0xd4, 0x53, 0x62, 0x9d, 0x62, 0xac, 0x92, 0x44, 0xc8, 0x22,
+ 0xbe, 0x17, 0x43, 0x4f, 0xcf, 0xe2, 0x1e, 0xe5, 0xc9, 0x5a, 0x1f, 0xf7,
+ 0x57, 0xff, 0xa3, 0xd2, 0x49, 0x08, 0xba, 0xcb, 0xef, 0x67, 0x11, 0x22,
+ 0x4b, 0xa1, 0x34, 0x62, 0xe0, 0x18, 0x79, 0x50, 0x7b, 0xa3, 0x9e, 0xa4,
+ 0xdf, 0x81, 0x67, 0xd8, 0x46, 0x5b, 0x5d, 0xa9, 0xfe, 0x4a, 0x95, 0x08,
+ 0x6c, 0x59, 0x0a, 0x91, 0x34, 0x78, 0x1a, 0xc3, 0x77, 0x38, 0xff, 0x09,
+ 0xe8, 0xf3, 0x2c, 0x9e, 0x5f, 0x00, 0x5f, 0x1b, 0x65, 0xd2, 0x9d, 0x4c,
+ 0x1c, 0x57, 0xbe, 0x8b, 0x6b, 0x97, 0xb5, 0xcc, 0xd7, 0xe4, 0xbc, 0xe2,
+ 0xef, 0x13, 0xac, 0x9d, 0xa1, 0xa7, 0xeb, 0xe1, 0x6f, 0xf2, 0x3a, 0xf9,
+ 0xf3, 0xd6, 0x67, 0xce, 0xca, 0x58, 0x09, 0xc9, 0x96, 0x5f, 0x6a, 0x85,
+ 0x2d, 0x2b, 0x3e, 0xef, 0xeb, 0x31, 0xeb, 0x46, 0x41, 0x07, 0xfb, 0x00,
+ 0xfb, 0x95, 0x2e, 0x41, 0x07, 0x6d, 0xa7, 0x10, 0x4d, 0x3f, 0x2e, 0x2b,
+ 0x4b, 0xff, 0x54, 0x6a, 0x4b, 0x05, 0xa9, 0x2f, 0xfd, 0x23, 0x39, 0xb7,
+ 0xd4, 0x92, 0x0b, 0x29, 0x15, 0x93, 0xac, 0x0e, 0xe5, 0xcf, 0x72, 0xa3,
+ 0x87, 0x07, 0x93, 0xe3, 0x97, 0x20, 0xc0, 0x95, 0xaa, 0x47, 0xfb, 0x54,
+ 0x1b, 0xed, 0x17, 0x60, 0x6b, 0xaf, 0x58, 0xa4, 0x7f, 0x4c, 0x6a, 0x65,
+ 0xd2, 0xfe, 0xa0, 0xa2, 0xfd, 0xc0, 0x26, 0xed, 0x92, 0x0b, 0x59, 0xa4,
+ 0x7f, 0x27, 0xda, 0x81, 0xf3, 0xfb, 0x49, 0x7f, 0x02, 0xcf, 0x7e, 0xd0,
+ 0xfe, 0x6a, 0xee, 0x6b, 0xad, 0x8d, 0x72, 0x44, 0xd1, 0x1c, 0x4a, 0x8f,
+ 0x41, 0x3e, 0xaf, 0xb5, 0xd6, 0x5d, 0xfa, 0x11, 0xbe, 0xbb, 0xf7, 0x20,
+ 0x46, 0xf5, 0x61, 0xaf, 0x5e, 0xc9, 0xcf, 0x46, 0x11, 0x27, 0xc7, 0xa1,
+ 0xdb, 0x2e, 0xe5, 0x87, 0x08, 0x17, 0xd0, 0xd9, 0x34, 0xe6, 0x1f, 0xa2,
+ 0xbf, 0x29, 0xb9, 0x38, 0x90, 0x4b, 0xb1, 0x9c, 0x8e, 0xa0, 0xfe, 0xc7,
+ 0x3e, 0x86, 0x93, 0x73, 0xf9, 0xcc, 0x00, 0x62, 0x1a, 0xff, 0x7f, 0x64,
+ 0x7b, 0x28, 0x20, 0xd6, 0x42, 0xe7, 0x3d, 0x90, 0x1f, 0xe8, 0x18, 0x9b,
+ 0x41, 0x6e, 0x4d, 0x0e, 0xd7, 0x54, 0x7f, 0x91, 0x71, 0xe5, 0x28, 0xf2,
+ 0xe9, 0x21, 0x7c, 0xbc, 0xfd, 0x26, 0x9a, 0xdc, 0x73, 0x3b, 0x4f, 0x45,
+ 0x77, 0x7d, 0x2f, 0x01, 0x52, 0xa6, 0xc9, 0x7d, 0x0b, 0x12, 0x4a, 0x87,
+ 0xb0, 0x2f, 0xc7, 0x7a, 0x10, 0x63, 0x06, 0xa2, 0xd9, 0xe6, 0xcf, 0x31,
+ 0x4e, 0x5f, 0x66, 0x7c, 0x0f, 0x68, 0x1f, 0xc5, 0x9a, 0x8c, 0xbb, 0x63,
+ 0xe0, 0x99, 0x35, 0x26, 0xe3, 0x26, 0xf2, 0x48, 0xe3, 0x47, 0xcc, 0x2d,
+ 0xf8, 0x3e, 0xe0, 0x7f, 0xe7, 0x7d, 0x89, 0xde, 0x9c, 0x36, 0xab, 0x05,
+ 0x31, 0xb1, 0x27, 0x74, 0x6e, 0xc5, 0xa5, 0xd8, 0x30, 0x5f, 0x20, 0x66,
+ 0xd4, 0x29, 0x83, 0x35, 0xca, 0x89, 0xfd, 0x27, 0xd4, 0x7f, 0xb5, 0xe7,
+ 0x21, 0x8f, 0xa8, 0xec, 0xb5, 0x0e, 0x22, 0xa6, 0x80, 0xfe, 0xca, 0x18,
+ 0x78, 0x63, 0x8f, 0x66, 0x10, 0xf9, 0x2b, 0x04, 0x21, 0xa0, 0x96, 0x5a,
+ 0x0b, 0xc9, 0xbd, 0xe1, 0x11, 0xa3, 0x28, 0x8f, 0x46, 0x58, 0x36, 0x17,
+ 0xd6, 0x98, 0x07, 0xc2, 0xb2, 0xb0, 0x26, 0x72, 0x69, 0x91, 0x71, 0x45,
+ 0xfd, 0x41, 0xe6, 0x86, 0x33, 0x8f, 0x3c, 0x5b, 0x5a, 0x62, 0x8c, 0x61,
+ 0x9c, 0xb8, 0x01, 0xba, 0x48, 0x7e, 0xe3, 0xab, 0xc8, 0x49, 0xa5, 0xf2,
+ 0x20, 0x62, 0xa6, 0xac, 0xeb, 0x90, 0x29, 0x72, 0x19, 0x6b, 0xd4, 0x1d,
+ 0xfa, 0x32, 0x41, 0x4f, 0x26, 0x2a, 0xc5, 0x45, 0xf6, 0x63, 0xa2, 0xa0,
+ 0x85, 0x35, 0x76, 0x48, 0xd5, 0x3f, 0x37, 0xa8, 0xd8, 0xca, 0xff, 0xe1,
+ 0xb6, 0x7d, 0x93, 0x27, 0xf7, 0xe9, 0x8c, 0x63, 0x37, 0x8b, 0x3d, 0x63,
+ 0x77, 0x1d, 0xa8, 0x74, 0x48, 0xb5, 0x8f, 0x76, 0x49, 0xfd, 0xbf, 0xa0,
+ 0x62, 0xed, 0x02, 0x78, 0x2a, 0x2e, 0x12, 0xe3, 0x86, 0x31, 0x2f, 0xe6,
+ 0xcf, 0xa3, 0x5c, 0xff, 0x89, 0xcc, 0xed, 0x7f, 0x17, 0x74, 0x79, 0x71,
+ 0x2d, 0xbf, 0x1f, 0xf1, 0x76, 0x46, 0x97, 0x3b, 0xef, 0x1a, 0xc7, 0xb3,
+ 0xcc, 0x81, 0xef, 0xf8, 0x78, 0x92, 0x63, 0xec, 0x61, 0x81, 0xbe, 0x15,
+ 0x03, 0xff, 0xfb, 0xa4, 0xb0, 0x12, 0x85, 0x1c, 0x90, 0x4b, 0x6b, 0xde,
+ 0x5a, 0xac, 0x77, 0x4f, 0x42, 0x47, 0xfa, 0xa9, 0xa8, 0x44, 0x4e, 0xf5,
+ 0x49, 0xf8, 0xeb, 0xdd, 0xd2, 0xf1, 0xf5, 0x21, 0x09, 0x7d, 0xdd, 0x64,
+ 0x4e, 0x4f, 0x9c, 0x80, 0xbe, 0xe6, 0x65, 0x5c, 0x9e, 0x44, 0xde, 0x62,
+ 0x5e, 0x57, 0x76, 0x6a, 0xf4, 0x4b, 0x08, 0x05, 0xab, 0xfe, 0x8c, 0x2d,
+ 0x8f, 0xee, 0xff, 0x85, 0xea, 0x33, 0x01, 0xc3, 0x8b, 0xfe, 0xfc, 0x94,
+ 0xd8, 0xcd, 0x77, 0x21, 0x6b, 0xc3, 0x79, 0xed, 0xd6, 0xa0, 0xa6, 0x1c,
+ 0x56, 0xfd, 0xc2, 0x47, 0xf7, 0x7b, 0x35, 0x25, 0xf0, 0xb8, 0xe6, 0xa8,
+ 0x9a, 0x12, 0xf1, 0x35, 0xcc, 0x79, 0xfd, 0xa2, 0x63, 0xaf, 0xbc, 0x0c,
+ 0x42, 0x4f, 0xb7, 0x88, 0x7d, 0x08, 0x7e, 0xf1, 0x9c, 0x2c, 0xe9, 0x69,
+ 0x4d, 0xad, 0x19, 0x7a, 0x86, 0x71, 0x8a, 0xf1, 0x8b, 0x36, 0x9e, 0x4c,
+ 0x14, 0x61, 0x7f, 0xa1, 0xe7, 0x19, 0xa3, 0x3c, 0xdb, 0x9e, 0x68, 0x8b,
+ 0x75, 0x0b, 0x95, 0x7b, 0xa0, 0x43, 0xd4, 0xf2, 0x16, 0xe2, 0x9c, 0x81,
+ 0x5c, 0x6e, 0xf1, 0xda, 0xeb, 0xe1, 0xe5, 0x63, 0x31, 0x75, 0x5d, 0xac,
+ 0x7a, 0x18, 0xdc, 0x5b, 0x9f, 0x75, 0x07, 0x62, 0x4c, 0x93, 0x74, 0x70,
+ 0xdf, 0x01, 0x09, 0x3d, 0x17, 0x93, 0xf0, 0x73, 0xb4, 0x3f, 0x33, 0xe1,
+ 0x40, 0x7e, 0x0b, 0x16, 0x31, 0xd0, 0x0a, 0xb0, 0xc5, 0xcd, 0xa2, 0xaf,
+ 0x0c, 0xc0, 0x77, 0xcc, 0x78, 0x55, 0x92, 0x12, 0xaa, 0x45, 0xe5, 0xad,
+ 0x45, 0x33, 0x41, 0x7b, 0x39, 0x6b, 0x61, 0xbc, 0xd9, 0x75, 0x79, 0x5d,
+ 0x51, 0xc1, 0xb1, 0x2f, 0x87, 0x80, 0x19, 0x86, 0x6d, 0xbd, 0x47, 0x5e,
+ 0x87, 0xbe, 0x73, 0x6a, 0xec, 0x66, 0xac, 0x0b, 0x1a, 0x9e, 0x33, 0xc1,
+ 0x03, 0xd7, 0xfd, 0x1e, 0xd6, 0x54, 0xf8, 0xca, 0xd9, 0x60, 0x4d, 0xba,
+ 0x48, 0xdb, 0xed, 0x83, 0xdd, 0xe1, 0xba, 0xd9, 0x21, 0xb9, 0xd9, 0x84,
+ 0xe8, 0x8b, 0x9f, 0x91, 0xc1, 0xfd, 0xba, 0xc7, 0x8f, 0xe2, 0x91, 0x63,
+ 0xec, 0xc7, 0xdd, 0xae, 0xfc, 0x51, 0x5f, 0x83, 0xcd, 0x3c, 0x48, 0x1d,
+ 0x23, 0xf7, 0x23, 0x8f, 0x31, 0x8e, 0x85, 0x90, 0xc7, 0xb2, 0x4d, 0x4f,
+ 0xef, 0xd5, 0x07, 0xfb, 0xe5, 0xc9, 0xe7, 0x68, 0x4f, 0xb8, 0xb7, 0x69,
+ 0x53, 0x41, 0x0f, 0x98, 0xf7, 0x2c, 0x39, 0xf9, 0x6c, 0x50, 0x73, 0xb0,
+ 0xbe, 0x32, 0xe3, 0x07, 0xc0, 0x8f, 0x7e, 0x27, 0xe3, 0x81, 0xae, 0x6c,
+ 0x37, 0x6f, 0x59, 0x5e, 0xdd, 0x51, 0x49, 0xb0, 0x2f, 0x6e, 0xb0, 0x4e,
+ 0xb3, 0xe3, 0x9e, 0xbc, 0x8b, 0x18, 0x2b, 0x35, 0x67, 0x11, 0xa3, 0x23,
+ 0x72, 0x71, 0xd6, 0x86, 0xee, 0x3f, 0x0b, 0xba, 0x0e, 0x75, 0x11, 0x23,
+ 0x5f, 0x9c, 0x75, 0x70, 0x7d, 0x48, 0xd5, 0x66, 0xa1, 0x3b, 0x61, 0xc7,
+ 0xcd, 0x7e, 0xfa, 0x91, 0xaf, 0xa7, 0x84, 0x56, 0x5c, 0x32, 0xb5, 0x12,
+ 0x62, 0xf6, 0x64, 0x8a, 0x39, 0xbe, 0x53, 0xf5, 0x4d, 0xd9, 0xaf, 0xc9,
+ 0x2b, 0xbc, 0xb0, 0x4f, 0x2b, 0x56, 0x19, 0xe7, 0x0b, 0xf1, 0x0e, 0x21,
+ 0x0e, 0x11, 0xad, 0x66, 0x51, 0x27, 0x9a, 0x9c, 0x57, 0xbd, 0x58, 0x11,
+ 0xc7, 0x3d, 0x42, 0x19, 0x68, 0xf5, 0xea, 0x3e, 0xad, 0x50, 0x0d, 0xc9,
+ 0xc5, 0x18, 0xe9, 0x4e, 0xa8, 0xfa, 0x7d, 0xbf, 0xb2, 0xb5, 0x1e, 0xe4,
+ 0x12, 0xd8, 0x4c, 0xea, 0x93, 0xd8, 0x57, 0x8d, 0xc1, 0xa6, 0xa8, 0x7b,
+ 0xea, 0x5d, 0xc5, 0x48, 0x5f, 0xf7, 0x3b, 0xe5, 0x4c, 0xd0, 0x51, 0x26,
+ 0x7e, 0xef, 0xf4, 0xf1, 0xfb, 0xa2, 0x5f, 0x0f, 0x3d, 0x26, 0xac, 0x53,
+ 0x16, 0x2a, 0xa4, 0x05, 0xf1, 0xd6, 0xdd, 0xc9, 0x96, 0x28, 0x47, 0x2f,
+ 0xa6, 0x1c, 0x45, 0x1d, 0xa3, 0xaf, 0x19, 0xbe, 0x0d, 0xf0, 0x6f, 0x14,
+ 0xf7, 0xbc, 0x5a, 0xaa, 0xd8, 0x8c, 0xc0, 0xdf, 0xa7, 0x21, 0x23, 0xea,
+ 0x06, 0xfa, 0x5b, 0xe3, 0x99, 0x0a, 0xf4, 0xb7, 0xf6, 0xf2, 0xfb, 0x76,
+ 0x1f, 0x63, 0xde, 0xb0, 0x3c, 0x89, 0xf1, 0x13, 0x67, 0x48, 0xcf, 0xb8,
+ 0x8f, 0xc7, 0x12, 0x90, 0x09, 0x63, 0xfc, 0xa8, 0xbc, 0xd5, 0x70, 0x14,
+ 0xfe, 0xdb, 0xb7, 0x7f, 0x46, 0xe6, 0xdd, 0x59, 0xe0, 0x3f, 0xc8, 0xdf,
+ 0x48, 0xc0, 0x3f, 0xe3, 0x2a, 0x3e, 0x1e, 0xfe, 0x68, 0x35, 0x49, 0xd8,
+ 0xcb, 0xd9, 0xf7, 0x5e, 0x67, 0xce, 0xde, 0x0d, 0xfc, 0xf5, 0x91, 0xd6,
+ 0x0f, 0x79, 0xeb, 0xff, 0x17, 0xe8, 0xea, 0x73, 0xd8, 0x23, 0x0a, 0xfa,
+ 0xfa, 0x29, 0xd3, 0x0f, 0x7b, 0x4e, 0xf7, 0x9e, 0xbb, 0xff, 0x3a, 0xe9,
+ 0x32, 0xa4, 0x01, 0x8c, 0x50, 0x50, 0x79, 0x94, 0xb5, 0x62, 0xc4, 0xd7,
+ 0xdf, 0x31, 0x60, 0x67, 0xae, 0x1b, 0xc4, 0xde, 0x4e, 0x29, 0xf4, 0x05,
+ 0xf5, 0x27, 0x62, 0xf6, 0xe6, 0x78, 0x50, 0xcf, 0xf2, 0xf9, 0x94, 0x93,
+ 0x2f, 0xb3, 0x4f, 0xc8, 0x5c, 0xc0, 0x31, 0x65, 0x87, 0x1f, 0x42, 0xb7,
+ 0x09, 0xcf, 0x20, 0xdd, 0xf7, 0x29, 0xba, 0x1d, 0x45, 0x37, 0xfd, 0x8b,
+ 0x67, 0x3a, 0xec, 0xa3, 0x05, 0x7d, 0x33, 0xae, 0x07, 0x4c, 0x00, 0x7d,
+ 0x7f, 0x17, 0x3a, 0xfe, 0x4e, 0x05, 0x98, 0xa0, 0x02, 0x4c, 0x80, 0x3d,
+ 0xbe, 0x0d, 0x1d, 0x7f, 0xab, 0x02, 0x4c, 0x50, 0x89, 0xfb, 0x3d, 0x0a,
+ 0x9b, 0x98, 0xfe, 0x23, 0xda, 0x6e, 0xd0, 0x93, 0xb9, 0xda, 0x2e, 0x39,
+ 0xce, 0xf9, 0x01, 0x36, 0x8e, 0xc2, 0x8e, 0x78, 0x6e, 0x11, 0xf4, 0x3b,
+ 0xfc, 0x1c, 0xd1, 0xe0, 0xb9, 0x00, 0x72, 0x44, 0x83, 0xe7, 0x18, 0x23,
+ 0xf1, 0x10, 0x30, 0x61, 0x48, 0xe2, 0xc2, 0x5e, 0xef, 0xdc, 0x18, 0xd6,
+ 0x1a, 0x1d, 0x84, 0x27, 0x75, 0xa8, 0xbe, 0xd6, 0x71, 0xd5, 0x6f, 0x40,
+ 0x5c, 0xa8, 0x06, 0xb5, 0x5b, 0x52, 0x26, 0x96, 0x88, 0x33, 0x65, 0xaf,
+ 0x9e, 0x86, 0x0e, 0x5c, 0x62, 0xc3, 0xcd, 0xbe, 0xf4, 0x70, 0x1d, 0x7b,
+ 0x16, 0x2d, 0x8f, 0xbe, 0xe3, 0xee, 0xd6, 0x33, 0x07, 0x10, 0x9f, 0xa7,
+ 0xca, 0x09, 0x99, 0x2c, 0x7b, 0x98, 0x00, 0xf5, 0xcf, 0x55, 0xfd, 0x51,
+ 0x9b, 0x7a, 0x80, 0xfe, 0x36, 0x6d, 0x23, 0x71, 0x3e, 0x45, 0x19, 0x53,
+ 0xff, 0xd3, 0xaa, 0x67, 0x7d, 0xa0, 0xee, 0xf5, 0xe5, 0x27, 0x95, 0x2d,
+ 0x84, 0x19, 0x67, 0xa8, 0x3f, 0xcf, 0x87, 0x61, 0x17, 0x79, 0x37, 0x90,
+ 0x4b, 0x3b, 0x1e, 0xf9, 0xbc, 0x26, 0xd6, 0x4e, 0xe3, 0xb9, 0xb6, 0xf1,
+ 0xcd, 0xfb, 0x3e, 0xbd, 0x88, 0x7d, 0x9b, 0x3d, 0x06, 0xc6, 0xa9, 0xad,
+ 0xf1, 0x10, 0xea, 0x87, 0xb0, 0xba, 0x8f, 0x18, 0xde, 0x88, 0x49, 0xb6,
+ 0x61, 0x89, 0x53, 0xe5, 0x3c, 0xf6, 0x2d, 0x18, 0x8f, 0x9e, 0x90, 0xec,
+ 0x52, 0xaf, 0xe4, 0x62, 0x66, 0xca, 0x96, 0xbf, 0x27, 0x1b, 0xcb, 0x85,
+ 0x04, 0xcf, 0x0d, 0x0b, 0x33, 0x1a, 0x9e, 0x7b, 0x18, 0xd7, 0xa4, 0xd9,
+ 0x92, 0xc3, 0x65, 0xe6, 0x9d, 0x91, 0x78, 0x03, 0xf7, 0x72, 0xb3, 0xec,
+ 0xd5, 0x54, 0x61, 0x93, 0x66, 0xa2, 0x8a, 0x78, 0xf0, 0x72, 0x99, 0xfb,
+ 0x01, 0x1b, 0x95, 0xd9, 0xcf, 0x09, 0xee, 0x3f, 0x01, 0x1c, 0x88, 0x58,
+ 0x1d, 0xf3, 0xe7, 0x28, 0x5e, 0x6d, 0x23, 0x2c, 0x81, 0xae, 0x3b, 0x65,
+ 0xdd, 0x8f, 0xbb, 0xb5, 0xb2, 0xd7, 0x47, 0x39, 0x4b, 0x7a, 0xdc, 0xff,
+ 0xd5, 0x5a, 0x8f, 0xa1, 0x16, 0xda, 0xe4, 0xf5, 0x8f, 0xb9, 0x8f, 0x81,
+ 0xb0, 0x2b, 0x27, 0xdc, 0x40, 0x26, 0xbc, 0xcf, 0x31, 0x9e, 0x8d, 0xb6,
+ 0x5a, 0x67, 0xad, 0xf6, 0x9e, 0xdf, 0xf5, 0xf4, 0xcc, 0xde, 0xb8, 0x2d,
+ 0x63, 0xbd, 0xe6, 0xa0, 0x26, 0xf6, 0x7b, 0x66, 0x87, 0x46, 0xbc, 0x9e,
+ 0xd9, 0xfc, 0xc8, 0xf6, 0x9e, 0xd9, 0xcf, 0x6f, 0xf3, 0x7a, 0x66, 0x17,
+ 0x9d, 0x22, 0x3e, 0x5e, 0xcf, 0x6c, 0xf8, 0x76, 0xaf, 0x67, 0xf6, 0xf0,
+ 0xed, 0x5e, 0xcf, 0xec, 0x91, 0x11, 0xaf, 0x67, 0xf6, 0xfb, 0xb7, 0x6f,
+ 0xef, 0x99, 0x3d, 0x36, 0xb2, 0xbd, 0x67, 0x26, 0x13, 0xc8, 0x77, 0x13,
+ 0x5b, 0x3d, 0xb3, 0xf2, 0xc8, 0xb5, 0x7b, 0x66, 0xaf, 0x06, 0x78, 0x1d,
+ 0xfc, 0x8c, 0x81, 0x87, 0x14, 0xf0, 0xfa, 0x28, 0xf0, 0xfa, 0xaf, 0xeb,
+ 0x59, 0x87, 0xc1, 0xe7, 0xcd, 0x7e, 0x5e, 0xb8, 0x1e, 0xdc, 0x7e, 0xbb,
+ 0xff, 0x8c, 0xa0, 0xde, 0x4d, 0xf8, 0xb5, 0x0a, 0xb1, 0xfb, 0x1e, 0xbf,
+ 0x66, 0xfb, 0x6b, 0xd1, 0xad, 0xf3, 0xec, 0xf6, 0xff, 0x37, 0xa0, 0xf4,
+ 0x0e, 0xf0, 0x3c, 0xf9, 0x79, 0x0d, 0xb5, 0x1f, 0xf9, 0x47, 0xa2, 0xef,
+ 0xbe, 0xe8, 0x7c, 0xd5, 0x22, 0xc6, 0x7f, 0x1c, 0xbe, 0x6a, 0xef, 0x0d,
+ 0xc9, 0x3a, 0xfc, 0x96, 0x39, 0xea, 0xa4, 0x64, 0x31, 0x3f, 0xab, 0xe6,
+ 0x27, 0x26, 0xb6, 0xe6, 0xa7, 0x26, 0xbe, 0xaa, 0x6a, 0x52, 0xf3, 0x5f,
+ 0xe3, 0xf3, 0x0d, 0x65, 0xdf, 0x96, 0x87, 0xe1, 0x9d, 0x4a, 0x80, 0xb7,
+ 0xc2, 0x3e, 0x76, 0x36, 0x1c, 0xdb, 0x9d, 0xc0, 0x33, 0xe6, 0x8b, 0xb6,
+ 0x34, 0x14, 0x7e, 0x0f, 0xa5, 0xcd, 0x17, 0x73, 0xaa, 0x5e, 0x33, 0x9c,
+ 0xbc, 0x1b, 0xd4, 0xdf, 0xa8, 0xa1, 0x86, 0x06, 0xd5, 0xf9, 0x9b, 0xbe,
+ 0x36, 0x8c, 0x3c, 0xd6, 0x5e, 0x63, 0xb3, 0xae, 0xd6, 0xfd, 0xba, 0xda,
+ 0x90, 0xbb, 0xf7, 0xb7, 0x63, 0x73, 0x99, 0xf8, 0x5b, 0x0a, 0x9b, 0xef,
+ 0x42, 0x6d, 0x4e, 0xec, 0x4d, 0x1c, 0x43, 0x0c, 0x41, 0x7c, 0xce, 0x7e,
+ 0x01, 0xeb, 0x19, 0xe6, 0x46, 0xd6, 0x37, 0x31, 0x7c, 0xf8, 0xbe, 0x41,
+ 0x80, 0xd1, 0x3b, 0xfc, 0xf8, 0xce, 0xba, 0x28, 0xc0, 0x2a, 0x77, 0x75,
+ 0x7b, 0xb5, 0xd1, 0x2e, 0xcd, 0xab, 0x3f, 0x13, 0xfe, 0x9c, 0xf0, 0x26,
+ 0x16, 0x0e, 0x6f, 0x62, 0xe1, 0x6d, 0xe7, 0x30, 0xa2, 0xde, 0x6d, 0x50,
+ 0xe7, 0x39, 0x3c, 0xdf, 0x11, 0x4d, 0x4f, 0xf3, 0x8c, 0x07, 0x38, 0xc7,
+ 0xe2, 0x99, 0x0f, 0x7d, 0xe9, 0x41, 0x2d, 0x5b, 0x37, 0x10, 0xef, 0x99,
+ 0x7f, 0x90, 0x6b, 0xcb, 0xc1, 0xd9, 0x62, 0xa0, 0x27, 0xca, 0x8e, 0x63,
+ 0x7f, 0xaa, 0xa1, 0xe6, 0x4d, 0x45, 0xac, 0x43, 0xa0, 0x65, 0x0a, 0xff,
+ 0x03, 0x99, 0xde, 0xa3, 0x72, 0x5f, 0x27, 0x6c, 0xf6, 0x78, 0x85, 0xd8,
+ 0xf5, 0x71, 0x69, 0xf8, 0xf8, 0x75, 0x65, 0xc9, 0xc3, 0xae, 0xe1, 0xed,
+ 0xd8, 0x35, 0xb5, 0x21, 0x1e, 0x8d, 0x07, 0x76, 0xa4, 0xd1, 0x70, 0x5e,
+ 0x19, 0x22, 0x66, 0x25, 0x9d, 0xcc, 0x3d, 0xd3, 0x88, 0x81, 0xcc, 0x39,
+ 0xcc, 0x37, 0xc4, 0xa5, 0xd7, 0xa2, 0x4f, 0x8d, 0x1d, 0xed, 0xb0, 0xa2,
+ 0xf8, 0xcc, 0x83, 0x8e, 0x19, 0x3c, 0x93, 0x96, 0x85, 0xd3, 0x5f, 0xd1,
+ 0x9c, 0xfa, 0x3c, 0xe8, 0x99, 0x42, 0xae, 0xa3, 0x2d, 0x15, 0x0c, 0xcf,
+ 0x8e, 0xd6, 0x11, 0xf7, 0x5d, 0xc6, 0x02, 0xd4, 0xae, 0xa8, 0x47, 0xca,
+ 0x8c, 0xbd, 0x3c, 0xeb, 0x0a, 0x62, 0x2e, 0xfb, 0x26, 0xa8, 0x59, 0x59,
+ 0xbb, 0x2e, 0x72, 0xdf, 0xed, 0xba, 0xa8, 0xb9, 0xc4, 0x5d, 0x86, 0xb3,
+ 0xbe, 0x46, 0xdc, 0xf8, 0x51, 0x31, 0xa4, 0xe1, 0xbc, 0x3c, 0x44, 0x1c,
+ 0x79, 0x3d, 0xf8, 0xd1, 0x84, 0x34, 0xcd, 0x17, 0xd6, 0xf5, 0x76, 0xfc,
+ 0xe8, 0x61, 0xc7, 0xcc, 0xda, 0x41, 0xac, 0xc9, 0xda, 0x8c, 0x38, 0xd1,
+ 0x44, 0x98, 0x1b, 0xc4, 0xb3, 0x83, 0xe0, 0xc7, 0xc3, 0x8a, 0x59, 0x60,
+ 0xc5, 0xbf, 0x03, 0xac, 0x58, 0x92, 0xf7, 0xa2, 0xc4, 0x8a, 0xb6, 0x8f,
+ 0x15, 0x1d, 0xd8, 0x71, 0x7e, 0x9b, 0x1d, 0x6b, 0xaa, 0x07, 0xc5, 0x7b,
+ 0x79, 0x60, 0xbd, 0xec, 0xa2, 0x79, 0x1d, 0xf8, 0x50, 0x93, 0x98, 0x3a,
+ 0xaf, 0x0f, 0xb7, 0xad, 0x19, 0xe0, 0xc0, 0x7d, 0x0a, 0xdf, 0xdd, 0x57,
+ 0xd9, 0x85, 0xda, 0x44, 0xe1, 0x3d, 0xff, 0x9c, 0x2f, 0x7c, 0xd5, 0xd9,
+ 0x67, 0xb8, 0xed, 0xec, 0x73, 0x0b, 0x17, 0xe2, 0x39, 0xbf, 0xc7, 0x17,
+ 0x81, 0xde, 0xfe, 0x07, 0x69, 0x82, 0x5f, 0xd1, 0x07, 0x34, 0xcf, 0x4f,
+ 0xb6, 0xe1, 0xc3, 0xff, 0x7a, 0x15, 0x3e, 0x44, 0xce, 0x5a, 0x89, 0x49,
+ 0x06, 0xd8, 0xd0, 0x5e, 0xe3, 0x5a, 0xf4, 0xe5, 0x51, 0xe9, 0x00, 0x7f,
+ 0x9d, 0x8b, 0x7d, 0xc0, 0x44, 0xdd, 0x12, 0x05, 0x36, 0x8a, 0x28, 0x6c,
+ 0x34, 0x44, 0x0c, 0x33, 0x7c, 0x18, 0x98, 0xa6, 0xb1, 0x89, 0x8f, 0xcc,
+ 0xd4, 0x0f, 0xa0, 0x97, 0x87, 0x95, 0xad, 0x8c, 0xcb, 0x53, 0x88, 0x9d,
+ 0x1d, 0x6b, 0xc0, 0x75, 0x2b, 0x1e, 0x6e, 0x8a, 0x5c, 0x85, 0x9b, 0x8e,
+ 0xec, 0x88, 0x9b, 0x54, 0xbf, 0x7e, 0x9c, 0x32, 0x79, 0xdd, 0xf5, 0xfa,
+ 0xf5, 0x97, 0x5c, 0xaf, 0x5f, 0xff, 0xba, 0xdb, 0xde, 0xaf, 0xbf, 0x49,
+ 0x8a, 0x86, 0x69, 0x5f, 0x94, 0xab, 0xfa, 0xf5, 0x33, 0xec, 0x7f, 0x57,
+ 0xbb, 0xbc, 0xbe, 0x7c, 0xb7, 0xdf, 0xaf, 0x37, 0xa5, 0xb8, 0x6d, 0xdc,
+ 0x90, 0xb7, 0xad, 0xa0, 0x5f, 0xff, 0x2f, 0x30, 0xd6, 0x83, 0x3d, 0xb6,
+ 0xf7, 0xea, 0x2f, 0xb9, 0xec, 0xd5, 0xc7, 0x38, 0xcf, 0xef, 0xd5, 0x73,
+ 0x1e, 0x6a, 0x78, 0x97, 0x7d, 0xfa, 0x9b, 0x21, 0x8b, 0x7e, 0xc8, 0xa1,
+ 0x4f, 0x3a, 0x9e, 0x8b, 0x73, 0x8e, 0xea, 0xcf, 0x5f, 0x74, 0x63, 0x78,
+ 0xce, 0xeb, 0xa3, 0x1f, 0x86, 0x5d, 0x1d, 0xd9, 0xec, 0xcf, 0x7b, 0x7b,
+ 0xbc, 0xe1, 0x6e, 0x5f, 0x7f, 0xfb, 0x3a, 0x03, 0xfe, 0x3a, 0x31, 0xac,
+ 0x13, 0xbf, 0x6a, 0x9d, 0xad, 0x7e, 0xfc, 0x1b, 0xae, 0xd7, 0x8b, 0x77,
+ 0x4e, 0x8b, 0xdd, 0x81, 0x98, 0xfc, 0xe2, 0xd0, 0x8d, 0xfe, 0x1a, 0x9b,
+ 0xbd, 0x78, 0xc6, 0x0e, 0xe0, 0x75, 0xc6, 0x0f, 0x3e, 0xff, 0xff, 0xbe,
+ 0x17, 0xcf, 0x3e, 0xbc, 0x77, 0x9e, 0x42, 0xff, 0x04, 0x2e, 0x7f, 0xd6,
+ 0xeb, 0xc1, 0x4f, 0x54, 0x82, 0xde, 0x3a, 0xeb, 0xc6, 0xe0, 0xbd, 0x8c,
+ 0xc1, 0xc4, 0x71, 0xa1, 0xad, 0x90, 0x3e, 0xae, 0xdb, 0x23, 0x73, 0x0a,
+ 0x17, 0xc1, 0xa6, 0x92, 0xd7, 0xc6, 0xc6, 0xb5, 0xc5, 0x00, 0x1b, 0xc7,
+ 0x14, 0x36, 0xae, 0xad, 0x05, 0xd8, 0x38, 0x73, 0x0d, 0x6c, 0xfc, 0xdf,
+ 0xba, 0xbc, 0xf8, 0x1f, 0x95, 0x82, 0xc2, 0xc6, 0xd7, 0x7a, 0xc7, 0x86,
+ 0xf7, 0xba, 0x89, 0x03, 0xc4, 0x3b, 0x17, 0xef, 0xbb, 0x86, 0xaf, 0x05,
+ 0x78, 0x99, 0xb9, 0xbe, 0x5f, 0x66, 0x9e, 0xdb, 0xc2, 0xcb, 0x1e, 0x26,
+ 0x36, 0x13, 0x47, 0x55, 0x2e, 0x04, 0x3e, 0x68, 0xb2, 0xef, 0x7d, 0x48,
+ 0xd9, 0x6e, 0xa9, 0x32, 0xab, 0x70, 0x59, 0x1e, 0xb5, 0x6d, 0x51, 0xe1,
+ 0x60, 0x62, 0xe0, 0x2e, 0x91, 0xbe, 0x20, 0x17, 0x05, 0x18, 0x33, 0xec,
+ 0xc7, 0x67, 0x9e, 0x29, 0xbc, 0x1d, 0xca, 0x10, 0x03, 0xbb, 0x41, 0x8d,
+ 0x40, 0x39, 0x0f, 0x23, 0x76, 0x19, 0xbe, 0xac, 0x3c, 0x9f, 0xdd, 0xb7,
+ 0xff, 0x87, 0xef, 0xdb, 0x06, 0xe3, 0x5a, 0x80, 0x11, 0x51, 0x03, 0x55,
+ 0xc6, 0xd5, 0xbb, 0x0e, 0x1e, 0x46, 0xf4, 0xf0, 0x61, 0xd6, 0x9d, 0x01,
+ 0x4e, 0x9e, 0x95, 0x09, 0xe0, 0xf3, 0xf5, 0xdf, 0x65, 0xef, 0x29, 0xc0,
+ 0x44, 0x36, 0xfe, 0xb7, 0xf7, 0xa2, 0x78, 0xdd, 0xa1, 0xce, 0xfe, 0xce,
+ 0x0f, 0x45, 0xdb, 0xc6, 0xff, 0x3e, 0xe2, 0x37, 0xea, 0xa1, 0x0a, 0x73,
+ 0x1d, 0xb1, 0xd0, 0x6f, 0x40, 0x07, 0x63, 0xd7, 0xc0, 0x42, 0x57, 0xe7,
+ 0x26, 0xe6, 0xcb, 0xad, 0xbc, 0xe4, 0x6c, 0xe6, 0x25, 0xee, 0xf1, 0xeb,
+ 0x72, 0x27, 0xc7, 0x6c, 0x23, 0x62, 0x4d, 0xe1, 0x33, 0x8f, 0x7c, 0xbd,
+ 0x3d, 0x37, 0xcd, 0x5d, 0x47, 0x6e, 0x9a, 0x50, 0xb9, 0x89, 0xf4, 0xa2,
+ 0x9e, 0x83, 0x4c, 0xbe, 0x0b, 0x59, 0x7e, 0x07, 0xb4, 0xff, 0x11, 0xf8,
+ 0xf9, 0x43, 0x60, 0xac, 0x6f, 0x03, 0x63, 0x7d, 0xab, 0xd2, 0xfe, 0x0e,
+ 0xc3, 0xb8, 0xb0, 0x0e, 0xf4, 0xea, 0x66, 0x0f, 0xc3, 0x1f, 0x86, 0x57,
+ 0x35, 0xca, 0x86, 0x33, 0x57, 0x1e, 0x31, 0xe6, 0xbd, 0xf3, 0xd2, 0x44,
+ 0x4e, 0xd2, 0x88, 0x11, 0xcc, 0x15, 0xea, 0x3a, 0xce, 0x7e, 0x25, 0xb1,
+ 0x42, 0x5d, 0xd5, 0x93, 0x43, 0x52, 0x6d, 0x78, 0xf8, 0x6a, 0xe1, 0x8c,
+ 0xb7, 0xc6, 0x9c, 0x8f, 0xaf, 0xf2, 0x3e, 0xbe, 0xca, 0x35, 0x36, 0x12,
+ 0xac, 0xcf, 0x17, 0x52, 0xdb, 0x31, 0xd5, 0x61, 0x1f, 0x53, 0xcd, 0xff,
+ 0x15, 0x31, 0x15, 0xf7, 0xca, 0xe3, 0x99, 0xc9, 0xa5, 0x84, 0x1c, 0x80,
+ 0x7c, 0x27, 0xca, 0xd4, 0x93, 0x69, 0xc3, 0x6e, 0x3e, 0x44, 0x57, 0x8e,
+ 0xd2, 0x4b, 0x28, 0xe9, 0xe9, 0x69, 0x12, 0x7a, 0x9a, 0xf8, 0xb5, 0xf5,
+ 0x8d, 0x1a, 0x33, 0xde, 0x1c, 0x8b, 0xe2, 0xf3, 0x7f, 0xaa, 0x23, 0xd2,
+ 0x4f, 0x3d, 0x5d, 0x8d, 0xb9, 0xae, 0x07, 0x7b, 0x6d, 0xc7, 0x5d, 0xb6,
+ 0xc2, 0x5d, 0x1d, 0xfe, 0x9c, 0x99, 0x89, 0x49, 0xe8, 0xf0, 0xdf, 0x63,
+ 0xce, 0x9f, 0xc0, 0xb7, 0x7e, 0x88, 0x78, 0xfd, 0xef, 0xa0, 0x8b, 0x7f,
+ 0x8b, 0xda, 0xe0, 0x55, 0xe4, 0x9f, 0x1f, 0x60, 0x6c, 0x0b, 0xc7, 0xa8,
+ 0x33, 0xfa, 0xd1, 0x8c, 0x95, 0x98, 0x28, 0xba, 0x89, 0x09, 0x0f, 0x7f,
+ 0xfc, 0xea, 0x6f, 0x66, 0xac, 0x29, 0xbe, 0xc3, 0x00, 0xf9, 0xfe, 0xf9,
+ 0xdd, 0x73, 0x0a, 0x7b, 0x04, 0x98, 0x23, 0x67, 0x73, 0xff, 0x92, 0x9b,
+ 0x9a, 0xa8, 0xe1, 0xe3, 0x61, 0x9b, 0xef, 0xd9, 0x1e, 0xb6, 0x59, 0xfa,
+ 0xeb, 0xd4, 0xbb, 0x87, 0x6b, 0x1e, 0x4e, 0xd3, 0xaf, 0xeb, 0xc0, 0x1c,
+ 0x35, 0xf8, 0x64, 0xa1, 0x69, 0xab, 0xcf, 0xf1, 0x8a, 0x6d, 0x46, 0x20,
+ 0x1f, 0xf6, 0x58, 0x4f, 0xd1, 0x0b, 0x5d, 0xd3, 0x28, 0x13, 0x81, 0xba,
+ 0x66, 0xfc, 0x9f, 0xf9, 0xd7, 0x4f, 0xfb, 0xd7, 0x4f, 0xf9, 0xd7, 0x27,
+ 0x91, 0x77, 0x9f, 0x54, 0xb9, 0x93, 0xe3, 0x1c, 0x83, 0x72, 0x5d, 0xac,
+ 0x85, 0xf5, 0xce, 0x8e, 0xfe, 0xb4, 0x55, 0x8d, 0x79, 0xfe, 0x5c, 0x68,
+ 0x3a, 0xf8, 0xfc, 0x63, 0x7c, 0x0e, 0xe2, 0x33, 0x8d, 0xcf, 0x63, 0xf8,
+ 0x6c, 0xca, 0x54, 0xcb, 0x56, 0xa8, 0xa3, 0x61, 0xc9, 0x62, 0xbc, 0x88,
+ 0x3a, 0x34, 0x93, 0x7a, 0x44, 0x8a, 0xf5, 0x92, 0x94, 0x96, 0x34, 0xe9,
+ 0xb6, 0xd2, 0x52, 0xaa, 0x1f, 0x93, 0xe3, 0x4b, 0xde, 0xb9, 0x61, 0x57,
+ 0xda, 0xc6, 0xdc, 0x96, 0x3c, 0x9c, 0x7a, 0x5c, 0xf4, 0x3b, 0x8f, 0x61,
+ 0x9e, 0xe8, 0xc5, 0xd1, 0xdb, 0xd4, 0xf9, 0x58, 0x3d, 0xe5, 0xc9, 0xf8,
+ 0x80, 0x65, 0x9b, 0xc8, 0x5b, 0xc3, 0x4f, 0x62, 0xed, 0x8c, 0x7a, 0x3f,
+ 0x30, 0x2d, 0x27, 0x4e, 0x6f, 0xec, 0xf5, 0x62, 0xa9, 0x69, 0xbc, 0x81,
+ 0x4d, 0xeb, 0xe0, 0xc3, 0x46, 0xec, 0x9b, 0x82, 0x9d, 0x1f, 0x71, 0xc3,
+ 0xda, 0x04, 0x62, 0xe0, 0x84, 0xab, 0x6a, 0x3d, 0xc4, 0x2a, 0xc3, 0x49,
+ 0x9e, 0x8a, 0xe1, 0x9a, 0xef, 0xd0, 0x20, 0x0f, 0x2a, 0x5b, 0xd9, 0x00,
+ 0x8e, 0xd1, 0x54, 0xbf, 0xaf, 0xb4, 0x79, 0x0e, 0xa4, 0xfa, 0xff, 0x4e,
+ 0x32, 0xa9, 0x4b, 0x7e, 0x8c, 0x38, 0xd6, 0x56, 0xb9, 0xa8, 0x51, 0xb6,
+ 0x3f, 0xc1, 0xda, 0xf0, 0x75, 0x61, 0x5e, 0xbb, 0x07, 0xf3, 0x06, 0x10,
+ 0x7f, 0x71, 0xaf, 0x09, 0x5e, 0x4e, 0x93, 0x57, 0x3e, 0x83, 0xda, 0xb6,
+ 0xfa, 0x49, 0xbd, 0xb8, 0xe4, 0xd7, 0x44, 0xaa, 0x76, 0x48, 0x48, 0x7d,
+ 0xf3, 0xcc, 0xc9, 0xeb, 0x93, 0xd4, 0xdd, 0x00, 0x3b, 0xf4, 0x60, 0x0e,
+ 0xeb, 0x08, 0xc8, 0xc8, 0x3b, 0x27, 0x53, 0x67, 0x64, 0x45, 0xf7, 0x93,
+ 0x7a, 0x69, 0x29, 0x83, 0x71, 0xf6, 0xa4, 0xf1, 0xbd, 0xaa, 0x2b, 0xec,
+ 0x7f, 0x31, 0x74, 0x58, 0x1a, 0xd5, 0x16, 0xe8, 0x45, 0x8e, 0xdd, 0x7b,
+ 0x58, 0x6a, 0xd5, 0x79, 0x79, 0xa1, 0xba, 0xb1, 0x0b, 0xd8, 0x09, 0x32,
+ 0x25, 0xfd, 0x3d, 0x3e, 0xfd, 0x54, 0x41, 0x30, 0x0e, 0x79, 0x9e, 0x2e,
+ 0xc4, 0xbd, 0xba, 0x96, 0xb8, 0xed, 0x24, 0xdf, 0x1b, 0x8c, 0xf3, 0x3d,
+ 0xbe, 0x23, 0xcb, 0xb4, 0xc9, 0x8b, 0xf7, 0x2e, 0x58, 0x9f, 0x92, 0x0b,
+ 0xa9, 0x3d, 0xb2, 0x91, 0x52, 0xf5, 0x2f, 0xf1, 0x01, 0x7c, 0xdb, 0x34,
+ 0xd6, 0xe5, 0x6e, 0x39, 0x01, 0x3f, 0xbd, 0x90, 0xca, 0xa9, 0xf3, 0x9b,
+ 0xe3, 0x4d, 0x62, 0xfb, 0x79, 0xd6, 0x54, 0xb2, 0xae, 0x7a, 0x60, 0xad,
+ 0xd6, 0x64, 0x8a, 0xb1, 0xa7, 0x43, 0x36, 0x14, 0xd6, 0xf2, 0x7a, 0xe3,
+ 0x1b, 0xb3, 0x9e, 0x6f, 0x84, 0x94, 0xbd, 0xff, 0x1b, 0xd0, 0x71, 0x0c,
+ 0x36, 0x1b, 0x51, 0x73, 0x42, 0xe9, 0x4e, 0x7f, 0x8e, 0xc2, 0x66, 0x6d,
+ 0x73, 0xc6, 0xc7, 0x33, 0x96, 0xf1, 0xa9, 0x8c, 0x35, 0x36, 0xe1, 0xf5,
+ 0x53, 0x4c, 0xc3, 0xd6, 0x2e, 0xb6, 0x82, 0xf7, 0x4d, 0xa6, 0xe0, 0x4f,
+ 0x2f, 0x6d, 0x62, 0x63, 0x18, 0xe7, 0xf3, 0x0b, 0xd0, 0x6b, 0x58, 0x3a,
+ 0x4e, 0xb5, 0xee, 0x99, 0x4b, 0x8d, 0x24, 0x8e, 0x08, 0xdf, 0x30, 0x62,
+ 0xfd, 0x6c, 0x82, 0xda, 0x05, 0xe4, 0xc3, 0x2b, 0xc4, 0x08, 0xc3, 0xe7,
+ 0xe5, 0xca, 0x3d, 0x99, 0xd4, 0x7e, 0xad, 0x36, 0x8b, 0xea, 0xe4, 0xf9,
+ 0x29, 0xe6, 0xd3, 0xa3, 0xec, 0x7d, 0x86, 0x4e, 0xbd, 0xad, 0x39, 0x65,
+ 0xf5, 0x8e, 0x39, 0xf4, 0xd2, 0xd2, 0xe6, 0x21, 0x37, 0x3c, 0x3f, 0xc3,
+ 0x04, 0xa8, 0x5b, 0x83, 0x09, 0x47, 0x72, 0xec, 0x71, 0x49, 0x7e, 0x59,
+ 0xf6, 0x65, 0x10, 0x47, 0xed, 0x99, 0x0e, 0x99, 0x6f, 0x18, 0xce, 0xe0,
+ 0xe2, 0x51, 0xac, 0x31, 0x87, 0xb5, 0xa6, 0x51, 0x83, 0xcc, 0x22, 0x27,
+ 0x53, 0xae, 0x8c, 0xd5, 0x0f, 0x43, 0x46, 0x37, 0xf1, 0xcc, 0x78, 0x3c,
+ 0x27, 0xe6, 0x4c, 0x41, 0xad, 0xfb, 0x9e, 0x96, 0x1f, 0xfd, 0x18, 0x72,
+ 0x5a, 0x58, 0x0e, 0x24, 0x45, 0x9f, 0x4e, 0x86, 0xdf, 0x9f, 0xb3, 0x38,
+ 0x16, 0xe5, 0x98, 0x8e, 0xb1, 0xf0, 0xe7, 0x92, 0x51, 0x3d, 0x93, 0x34,
+ 0xc7, 0xd9, 0xef, 0x0d, 0x59, 0x73, 0x12, 0x7a, 0xbe, 0xb7, 0x47, 0xba,
+ 0xa7, 0xa5, 0x77, 0xd5, 0x1c, 0x7f, 0x1d, 0xb4, 0x84, 0x55, 0x6c, 0x9f,
+ 0x13, 0xdd, 0x1f, 0xef, 0xd9, 0x1c, 0x0f, 0xfb, 0xe3, 0xd3, 0xd2, 0xbd,
+ 0x3a, 0x62, 0xbc, 0x29, 0x87, 0xb1, 0x66, 0x48, 0x2e, 0xa1, 0xa6, 0xb1,
+ 0x86, 0xe6, 0xe0, 0x73, 0x0f, 0x91, 0x96, 0x83, 0xc0, 0x14, 0xf0, 0x09,
+ 0xd4, 0xd9, 0xd6, 0x27, 0xe5, 0x4b, 0x46, 0x97, 0xe4, 0x55, 0x4d, 0x1b,
+ 0xf6, 0x7a, 0xa5, 0xb0, 0xf3, 0x5b, 0x87, 0xa6, 0x77, 0x7b, 0xfd, 0x00,
+ 0x9e, 0x67, 0x8c, 0x62, 0xec, 0x4a, 0x6b, 0xc5, 0xe2, 0x18, 0xef, 0x5d,
+ 0x69, 0xd5, 0xad, 0x11, 0x23, 0xab, 0x45, 0xfd, 0x73, 0xed, 0x79, 0xc5,
+ 0x7b, 0xa1, 0x3a, 0x68, 0xd4, 0xe4, 0x16, 0x2d, 0x7b, 0x03, 0xf2, 0x83,
+ 0xfb, 0x19, 0xcc, 0xbd, 0xd2, 0xca, 0x58, 0xf3, 0xaa, 0x7f, 0x5f, 0x93,
+ 0xe0, 0x9a, 0xeb, 0x8c, 0x18, 0x93, 0xea, 0xd9, 0x11, 0xe3, 0x84, 0xd6,
+ 0xfe, 0xac, 0xa1, 0x4d, 0x6e, 0x7b, 0xb6, 0x5b, 0xc9, 0x28, 0x64, 0x79,
+ 0x73, 0x4a, 0xd5, 0x69, 0x79, 0xda, 0xe5, 0xbc, 0x2b, 0xad, 0xac, 0x15,
+ 0xd1, 0x4e, 0xdc, 0xc0, 0x18, 0xc8, 0xb9, 0x97, 0xaf, 0xda, 0x87, 0xd7,
+ 0xd7, 0xda, 0xe3, 0x5d, 0xd9, 0xbe, 0xc7, 0x2e, 0x35, 0xe7, 0x82, 0x9a,
+ 0x13, 0x56, 0xb2, 0xde, 0xbe, 0xcf, 0xcf, 0x64, 0xfb, 0x3e, 0xdd, 0x9b,
+ 0x3c, 0x97, 0xb0, 0xe6, 0x93, 0x98, 0x5b, 0x76, 0x07, 0xe3, 0x75, 0xb9,
+ 0xdc, 0xca, 0x5b, 0x17, 0xe5, 0xc2, 0xe6, 0xda, 0xbf, 0xc2, 0x75, 0x3b,
+ 0x4d, 0xbf, 0xf2, 0x69, 0xe4, 0x77, 0x8e, 0x3d, 0xaa, 0xe4, 0xbd, 0xdb,
+ 0x1a, 0x3c, 0x58, 0xd3, 0xcc, 0xf1, 0x9f, 0x09, 0x75, 0x75, 0x44, 0xc5,
+ 0x98, 0xdb, 0xa0, 0xa7, 0x7d, 0xcf, 0xc0, 0x67, 0x47, 0x6d, 0x35, 0xe7,
+ 0x92, 0x35, 0x2d, 0xfb, 0x4e, 0x0d, 0x1a, 0x97, 0x10, 0xdb, 0x9c, 0x18,
+ 0xaf, 0x51, 0x2b, 0x59, 0x7c, 0x27, 0xfe, 0x4e, 0xd6, 0x01, 0xd0, 0xe5,
+ 0xe0, 0xf0, 0xcf, 0xe4, 0xa8, 0x9c, 0xa8, 0x1c, 0x43, 0x2e, 0x9c, 0x93,
+ 0xe1, 0x67, 0x90, 0x37, 0x2a, 0x05, 0x3c, 0x49, 0x9f, 0xf5, 0x72, 0xe0,
+ 0x9c, 0x7a, 0xcf, 0xfc, 0x24, 0xea, 0x64, 0xd8, 0x6e, 0x79, 0x70, 0x78,
+ 0x05, 0xcf, 0xbc, 0xa0, 0x70, 0xa8, 0x2b, 0x0d, 0xf8, 0x40, 0xe2, 0xf9,
+ 0x3d, 0xb2, 0xfb, 0x01, 0xda, 0x22, 0x32, 0xfd, 0x6d, 0x11, 0xf5, 0xee,
+ 0xbd, 0x6e, 0x75, 0x8a, 0xec, 0xa5, 0xdd, 0x34, 0x61, 0x63, 0x73, 0xde,
+ 0x99, 0xd6, 0xb6, 0x6b, 0x73, 0xe6, 0xa2, 0xac, 0x2a, 0xfb, 0xbb, 0x7d,
+ 0xd5, 0xfb, 0x3f, 0xba, 0x8a, 0x72, 0x38, 0x39, 0x2d, 0x77, 0xac, 0x7a,
+ 0xf6, 0x56, 0x5a, 0x3a, 0xaa, 0xe4, 0x3a, 0xa7, 0xe4, 0xda, 0x92, 0xc3,
+ 0x29, 0xca, 0x9c, 0xbc, 0xf0, 0xbd, 0x40, 0x4f, 0x16, 0xf7, 0xfb, 0xf6,
+ 0x33, 0xf8, 0x0c, 0x7f, 0x57, 0x42, 0xd9, 0xb0, 0xee, 0xbe, 0x7f, 0x37,
+ 0xcf, 0x59, 0xf7, 0xad, 0x92, 0xcf, 0x1b, 0xb7, 0xf1, 0xf9, 0x14, 0x62,
+ 0xea, 0xd0, 0x90, 0xc7, 0xeb, 0xab, 0x4b, 0x1f, 0xce, 0xeb, 0x37, 0x37,
+ 0x79, 0x0d, 0x49, 0x43, 0xd5, 0xaf, 0x5d, 0xbd, 0xd2, 0x8d, 0xa8, 0x07,
+ 0x7b, 0xf8, 0x09, 0xf6, 0x9a, 0x12, 0xd2, 0xe0, 0xed, 0xb7, 0xe1, 0x92,
+ 0x96, 0x80, 0x76, 0xd2, 0x73, 0x9f, 0xaf, 0x2f, 0xee, 0x7f, 0x74, 0xc7,
+ 0x7b, 0x97, 0xc4, 0x70, 0x86, 0x31, 0xa6, 0x2b, 0x9d, 0x65, 0x7d, 0xff,
+ 0x9a, 0x16, 0x5d, 0xe9, 0xcc, 0xde, 0xd4, 0xd9, 0xeb, 0xd0, 0x59, 0x5d,
+ 0x7e, 0x13, 0xbc, 0xc0, 0x9f, 0x9f, 0x19, 0x31, 0x0e, 0x13, 0x5b, 0x18,
+ 0x5c, 0x0f, 0x31, 0xd4, 0xd7, 0x5d, 0xc7, 0x47, 0xd0, 0xdd, 0x9b, 0xa2,
+ 0xf4, 0x07, 0x7e, 0x90, 0x7f, 0xd4, 0xf3, 0x8c, 0x61, 0xe4, 0xa9, 0x43,
+ 0xf9, 0x3e, 0x69, 0x53, 0x67, 0xfc, 0x33, 0x9e, 0x3e, 0x95, 0x6f, 0xfb,
+ 0xfa, 0xcc, 0xcd, 0x50, 0x67, 0xe6, 0x6e, 0x4f, 0x7f, 0x9d, 0x6a, 0xce,
+ 0x62, 0x32, 0xa1, 0xfc, 0xda, 0x1a, 0xba, 0x65, 0x37, 0x75, 0xf8, 0xb4,
+ 0xeb, 0xfd, 0x2f, 0xbb, 0xd3, 0xb2, 0xe8, 0x7e, 0x98, 0x1e, 0x3d, 0x1d,
+ 0x4e, 0x88, 0xe7, 0x3f, 0x57, 0xeb, 0x4f, 0x5f, 0x0d, 0x2b, 0x5b, 0x9d,
+ 0x80, 0xec, 0x4e, 0x56, 0x3e, 0xe6, 0xdb, 0xb7, 0xc7, 0xeb, 0xd0, 0x87,
+ 0xf0, 0x7a, 0xb8, 0x3c, 0x68, 0xbc, 0x8d, 0xb5, 0x26, 0x15, 0x86, 0x8b,
+ 0x88, 0xe3, 0xf3, 0x9a, 0xd8, 0xe4, 0x35, 0xa0, 0xcd, 0x9b, 0x97, 0x65,
+ 0x5d, 0xea, 0x32, 0x3e, 0x3d, 0xaa, 0xde, 0xbf, 0x7f, 0xa3, 0xcc, 0xb8,
+ 0x0c, 0xcc, 0x13, 0xeb, 0x93, 0x4b, 0x8d, 0x84, 0x5c, 0x22, 0x96, 0x18,
+ 0xc3, 0x7f, 0xf7, 0x98, 0x9f, 0x9b, 0xa3, 0xf2, 0x66, 0xb9, 0xbd, 0x56,
+ 0x1c, 0x95, 0xd7, 0xcb, 0x41, 0xbd, 0x48, 0x2c, 0xcb, 0xfc, 0x3f, 0x27,
+ 0x6f, 0x2d, 0x0d, 0xca, 0xfa, 0x0c, 0xf2, 0xf8, 0x10, 0x65, 0x30, 0x62,
+ 0x7c, 0x46, 0xfd, 0xbe, 0xe2, 0x4a, 0xeb, 0xbc, 0x85, 0x75, 0x97, 0x5b,
+ 0x72, 0x84, 0xe7, 0xd0, 0xfc, 0xde, 0xf8, 0x04, 0x56, 0xe1, 0xbc, 0x3e,
+ 0xa9, 0x2d, 0xa3, 0x2e, 0x2f, 0x73, 0x5d, 0xca, 0x69, 0x5a, 0x7d, 0x9f,
+ 0xc4, 0x3e, 0xf7, 0xf3, 0xbd, 0xf4, 0x18, 0x75, 0x71, 0xa5, 0xb5, 0x61,
+ 0xf1, 0x1c, 0x72, 0x4e, 0x1a, 0xd0, 0xd7, 0x97, 0x93, 0x3c, 0x27, 0xcf,
+ 0x0b, 0x7f, 0x9f, 0x52, 0x6b, 0xcc, 0xa0, 0x16, 0xb8, 0xd2, 0x5a, 0xb0,
+ 0x9e, 0x52, 0x7a, 0x6a, 0x54, 0x1f, 0xf0, 0xc7, 0x79, 0xcd, 0x7b, 0x86,
+ 0xb3, 0x6f, 0x88, 0xf5, 0xe7, 0x03, 0xc8, 0xff, 0xac, 0x3d, 0x89, 0xb7,
+ 0x28, 0x8b, 0x04, 0x6a, 0x5c, 0xae, 0xc5, 0xdf, 0x04, 0x25, 0x87, 0xf3,
+ 0x32, 0x09, 0x7a, 0x80, 0xcb, 0x5c, 0xc6, 0xfd, 0x5b, 0x65, 0x23, 0xe6,
+ 0xc5, 0x77, 0xbe, 0xaf, 0xb5, 0x81, 0x98, 0xbf, 0xb1, 0x19, 0xf3, 0xfb,
+ 0x71, 0x6d, 0x38, 0xa9, 0xa1, 0xff, 0x84, 0xf5, 0xd9, 0x77, 0x61, 0xcc,
+ 0x1f, 0xc7, 0x7c, 0x8e, 0xf5, 0x49, 0x69, 0x59, 0x6c, 0xf6, 0x99, 0x6a,
+ 0xc2, 0x77, 0x31, 0x72, 0xb2, 0xd8, 0x18, 0x8c, 0x9f, 0xd7, 0x1c, 0xf5,
+ 0xce, 0x46, 0x72, 0x88, 0x7d, 0xb7, 0x3e, 0x69, 0x2c, 0x4b, 0x22, 0x94,
+ 0x7e, 0x48, 0xdc, 0x86, 0x87, 0xb9, 0x17, 0x34, 0xf6, 0xdf, 0x6c, 0x69,
+ 0x6c, 0x9f, 0x63, 0x84, 0xd2, 0x87, 0xe4, 0x0f, 0xfc, 0x39, 0x8e, 0x9a,
+ 0xf3, 0x1f, 0x76, 0xf3, 0xec, 0xab, 0xe1, 0xf6, 0x82, 0x06, 0xd2, 0x76,
+ 0x63, 0xfb, 0xbe, 0x89, 0xad, 0x7d, 0xb9, 0x27, 0x6a, 0x98, 0xbd, 0x36,
+ 0xf6, 0x7d, 0x15, 0xcf, 0x3c, 0x04, 0x3a, 0xae, 0x84, 0x74, 0xeb, 0x21,
+ 0x29, 0x36, 0xae, 0xde, 0xa3, 0x9d, 0x06, 0x3e, 0xc3, 0xf5, 0xb9, 0xcf,
+ 0x21, 0xd0, 0x77, 0x45, 0xd3, 0xad, 0x43, 0x90, 0xa5, 0xb7, 0x47, 0xe8,
+ 0x39, 0xd3, 0xf8, 0xa1, 0x0c, 0x89, 0xbe, 0xa2, 0x29, 0xf9, 0xeb, 0xb5,
+ 0x51, 0x38, 0xc4, 0x94, 0x74, 0xaf, 0xcd, 0x4a, 0x68, 0x8d, 0x3d, 0x00,
+ 0xda, 0x22, 0xf5, 0xb8, 0x0b, 0x7e, 0x2c, 0x76, 0xd8, 0x22, 0xde, 0x67,
+ 0x1f, 0x77, 0xb5, 0x57, 0x7a, 0x89, 0xf7, 0x59, 0x0f, 0x1c, 0xc4, 0x7f,
+ 0xd6, 0x04, 0x2f, 0xb5, 0x32, 0xa9, 0x77, 0x54, 0xde, 0xcc, 0x37, 0x78,
+ 0xdf, 0x4c, 0x88, 0xf0, 0x1e, 0xe3, 0x43, 0x9f, 0x44, 0xbe, 0x3e, 0x8c,
+ 0x98, 0x90, 0x03, 0x76, 0xc6, 0xba, 0xa7, 0x86, 0x24, 0xec, 0xbd, 0xeb,
+ 0xa0, 0xfa, 0x25, 0x6f, 0x2d, 0x9b, 0xfe, 0xef, 0x53, 0x64, 0xdf, 0xf9,
+ 0x14, 0x7b, 0x9a, 0x03, 0xb0, 0x53, 0xd6, 0x23, 0xa2, 0x6f, 0xa0, 0xde,
+ 0xbc, 0xd4, 0x88, 0xf6, 0xf2, 0x7d, 0xcb, 0xd7, 0x5d, 0x5c, 0x13, 0xbb,
+ 0xc7, 0x14, 0x56, 0xf4, 0xef, 0xf1, 0x3b, 0xea, 0xa0, 0x6d, 0x98, 0x32,
+ 0x01, 0x4c, 0xc9, 0x3a, 0x69, 0xca, 0x7f, 0xe7, 0xcd, 0x70, 0x4e, 0x6c,
+ 0xab, 0x95, 0x86, 0x65, 0x03, 0x38, 0x6b, 0xdd, 0xb5, 0x10, 0x07, 0xdf,
+ 0xd6, 0xea, 0x65, 0xf5, 0xbb, 0x34, 0xed, 0x01, 0x60, 0xac, 0x44, 0x9f,
+ 0xaa, 0x75, 0x4e, 0x3e, 0x20, 0x9e, 0xbd, 0xc3, 0xca, 0x54, 0xcc, 0x5a,
+ 0xaf, 0x7a, 0xb5, 0xc5, 0x46, 0x75, 0x4a, 0xfe, 0xd4, 0x5d, 0x50, 0xbd,
+ 0xd2, 0x25, 0xd4, 0x1b, 0xe1, 0x45, 0x55, 0x6b, 0xb5, 0xe1, 0x54, 0xc4,
+ 0xb7, 0x67, 0x8f, 0xc0, 0x07, 0x4d, 0xf5, 0x6e, 0x81, 0xbe, 0xd2, 0x6a,
+ 0x65, 0x11, 0x2f, 0x74, 0xcb, 0x32, 0x8a, 0xc8, 0x73, 0x59, 0xf5, 0x7e,
+ 0x0a, 0xfd, 0xf7, 0xf7, 0x54, 0x1c, 0x96, 0x1a, 0x64, 0xf3, 0x5c, 0x02,
+ 0xeb, 0x68, 0xca, 0x3e, 0x43, 0x4a, 0x0f, 0x0f, 0x28, 0xec, 0x1a, 0x5a,
+ 0x41, 0x80, 0x5a, 0x1b, 0x12, 0x59, 0x81, 0xbf, 0xc2, 0x77, 0xc3, 0x6b,
+ 0xd4, 0x01, 0x65, 0x3b, 0x2b, 0x11, 0xc8, 0x9e, 0x58, 0x22, 0xb4, 0x48,
+ 0x19, 0xc7, 0x61, 0x17, 0x5c, 0x07, 0x32, 0xe6, 0xbb, 0x2c, 0xcb, 0x1d,
+ 0xf2, 0x4c, 0xc3, 0xf4, 0xdf, 0x3d, 0x7f, 0x89, 0xef, 0xa3, 0xeb, 0x73,
+ 0x63, 0x03, 0xc4, 0x4f, 0x52, 0x6a, 0x00, 0x63, 0x9c, 0x66, 0x0d, 0xce,
+ 0x18, 0x50, 0x88, 0x47, 0x94, 0xaf, 0xb3, 0x06, 0xf6, 0x7c, 0x9f, 0xf8,
+ 0x3a, 0x62, 0x11, 0xdb, 0x8e, 0x62, 0x8f, 0x9d, 0xe4, 0xea, 0xd5, 0x9e,
+ 0x93, 0xa0, 0xf3, 0xfc, 0x92, 0x39, 0x55, 0x90, 0x14, 0xdf, 0x71, 0x9e,
+ 0xb1, 0xc1, 0xf7, 0x06, 0xe2, 0xe4, 0x42, 0x85, 0xef, 0x33, 0x17, 0xe1,
+ 0x59, 0x53, 0x72, 0xbe, 0xcc, 0x1a, 0xf0, 0x76, 0xe8, 0x8b, 0xd7, 0xc5,
+ 0xf1, 0x10, 0xfc, 0xff, 0xa2, 0xc1, 0xdf, 0x91, 0xf1, 0x77, 0x41, 0x66,
+ 0x2a, 0xa1, 0x1d, 0x84, 0x8e, 0x0b, 0x46, 0xc4, 0xb7, 0x03, 0xa7, 0x4c,
+ 0x8c, 0x35, 0x62, 0x9c, 0xc3, 0xf7, 0x97, 0xdd, 0xcb, 0x2d, 0xd6, 0x3f,
+ 0x17, 0x10, 0xe7, 0xa6, 0x92, 0x53, 0xb0, 0x9d, 0x42, 0xbc, 0x13, 0xb4,
+ 0xfe, 0x5d, 0xdc, 0xcb, 0xbb, 0xdc, 0xc7, 0x4c, 0x5d, 0x94, 0x22, 0x30,
+ 0xfd, 0x48, 0xe2, 0x65, 0xd9, 0x83, 0x3a, 0x55, 0x93, 0x37, 0x2d, 0x73,
+ 0x5c, 0x34, 0xb5, 0xde, 0xf0, 0x7d, 0xb0, 0xbd, 0x37, 0x10, 0xdf, 0x3a,
+ 0xfc, 0xda, 0x3d, 0x5b, 0x26, 0x16, 0x3a, 0xaa, 0xde, 0x05, 0xb8, 0x60,
+ 0xb1, 0x7f, 0xc7, 0xdf, 0x44, 0xfe, 0xa5, 0xda, 0x63, 0xeb, 0x8c, 0x8d,
+ 0xfd, 0x63, 0xd2, 0xe7, 0xf1, 0x78, 0xc0, 0xf2, 0x68, 0xe4, 0x3a, 0x91,
+ 0xb6, 0x75, 0xce, 0xfb, 0xeb, 0x9c, 0xf5, 0xd7, 0xa9, 0xf9, 0xeb, 0x5c,
+ 0xd8, 0x5c, 0xe7, 0x6e, 0xe8, 0xbf, 0xd5, 0x7a, 0x0a, 0xf8, 0x21, 0x93,
+ 0x6a, 0xb5, 0x1c, 0xd4, 0x59, 0xa5, 0xd1, 0x79, 0x75, 0x46, 0xaa, 0xa7,
+ 0xbf, 0x71, 0x6f, 0xc6, 0x2a, 0xc4, 0xc3, 0x0a, 0x7b, 0xa0, 0x92, 0x82,
+ 0x1d, 0x16, 0xc4, 0xc3, 0xdc, 0x3c, 0xb7, 0xf3, 0xce, 0xf5, 0xba, 0xa1,
+ 0xc3, 0x1c, 0x72, 0x86, 0x91, 0x39, 0x67, 0x49, 0x61, 0xdf, 0x6f, 0xea,
+ 0xb0, 0xf3, 0x5e, 0xe4, 0x87, 0x9f, 0xc0, 0x66, 0x8c, 0x4c, 0xbd, 0x91,
+ 0x43, 0xbd, 0xc3, 0xf9, 0x77, 0x40, 0x8f, 0x85, 0x4c, 0xad, 0x51, 0xc8,
+ 0x9c, 0xe5, 0x79, 0x0e, 0xe6, 0xd5, 0x1a, 0x3d, 0x90, 0x7b, 0x8f, 0xea,
+ 0x8b, 0xbc, 0x5c, 0x8e, 0x31, 0x06, 0xc1, 0xd6, 0x63, 0x18, 0x8b, 0xab,
+ 0xdf, 0x68, 0xd5, 0xdd, 0x65, 0xf8, 0x74, 0x02, 0xe3, 0xd5, 0xae, 0x49,
+ 0x85, 0x47, 0x2d, 0x59, 0x71, 0x7f, 0xa5, 0x15, 0xcb, 0x97, 0xb5, 0x52,
+ 0x79, 0x18, 0x73, 0x46, 0xf9, 0x5b, 0x9f, 0x3d, 0xc0, 0x49, 0x53, 0xd5,
+ 0x1d, 0x69, 0x4a, 0x80, 0x26, 0xbd, 0x8d, 0xa6, 0x04, 0xe8, 0x41, 0xcc,
+ 0x3c, 0xc5, 0xde, 0xf1, 0xa8, 0x9c, 0x28, 0xf3, 0x9d, 0x26, 0xfe, 0x46,
+ 0xd5, 0x90, 0x30, 0xb0, 0x65, 0xe4, 0x94, 0x19, 0x5f, 0x57, 0xbd, 0x1a,
+ 0x73, 0xb8, 0x2e, 0x23, 0xa9, 0xba, 0xa8, 0xfc, 0x92, 0x38, 0x81, 0x7c,
+ 0xf5, 0x86, 0xdb, 0x23, 0x6f, 0xfa, 0x7b, 0x5d, 0x14, 0x9e, 0x33, 0x6e,
+ 0xdf, 0xeb, 0xc9, 0x4a, 0x2a, 0xf3, 0x8a, 0x15, 0xf2, 0xf9, 0xea, 0xc3,
+ 0x5e, 0x7b, 0x30, 0x37, 0x95, 0x39, 0xdf, 0xd8, 0x69, 0xae, 0x83, 0xb9,
+ 0x91, 0xb6, 0xb9, 0x0e, 0xe6, 0xf5, 0x20, 0xef, 0xf5, 0x28, 0x9e, 0x4a,
+ 0xa0, 0xeb, 0x52, 0x99, 0x3c, 0xf1, 0x0c, 0x82, 0x7b, 0x1a, 0xc4, 0xc6,
+ 0x53, 0xe2, 0x9f, 0xd9, 0xf2, 0xf7, 0x7a, 0x57, 0xf5, 0x6b, 0x94, 0x0d,
+ 0x4c, 0x58, 0x3c, 0x9b, 0x99, 0xd1, 0xb2, 0xf5, 0x3c, 0x72, 0xd5, 0x8d,
+ 0xc4, 0x43, 0x29, 0x1b, 0xb9, 0x92, 0xe7, 0x3c, 0x8d, 0x72, 0x81, 0xef,
+ 0x3d, 0xc3, 0x2e, 0xde, 0x21, 0x5e, 0xbe, 0x31, 0xa4, 0xde, 0x43, 0x70,
+ 0xfc, 0x73, 0x20, 0x31, 0x32, 0x63, 0x7c, 0xf7, 0xe0, 0x6e, 0xa9, 0x2f,
+ 0x7f, 0x11, 0x63, 0x19, 0xe4, 0xc5, 0x43, 0x5a, 0xe6, 0xdc, 0x24, 0xae,
+ 0x1f, 0xc2, 0x35, 0xe2, 0xf0, 0x72, 0x0e, 0xf7, 0x1f, 0xc2, 0xf5, 0xbc,
+ 0x96, 0x6d, 0xe6, 0x70, 0xfd, 0x30, 0xae, 0x27, 0x48, 0x9b, 0xf3, 0x8a,
+ 0x35, 0xa5, 0xd9, 0x58, 0xcb, 0x3e, 0x37, 0x89, 0x4f, 0xfb, 0x7a, 0xbc,
+ 0x07, 0x3d, 0x95, 0x79, 0x3e, 0x96, 0x04, 0x4d, 0x0f, 0x6a, 0x4e, 0xbd,
+ 0x1b, 0x6b, 0x0c, 0xe1, 0x79, 0xda, 0x54, 0xfb, 0x39, 0xd4, 0x6d, 0xaa,
+ 0x67, 0x14, 0x4a, 0xa7, 0x81, 0x77, 0x1f, 0x41, 0xde, 0xd7, 0xc4, 0xb1,
+ 0x1e, 0x97, 0x62, 0x2a, 0x2d, 0x0b, 0xf5, 0x90, 0x64, 0x63, 0x05, 0x7c,
+ 0x2f, 0x48, 0x66, 0x1c, 0xf7, 0xeb, 0xb4, 0x05, 0xce, 0x2b, 0x49, 0xb1,
+ 0x4a, 0xfc, 0xce, 0x7e, 0xd1, 0x57, 0xc0, 0x37, 0xfb, 0x44, 0x79, 0xc8,
+ 0x20, 0x46, 0xfb, 0xdd, 0xa1, 0xa7, 0xe5, 0xbd, 0xd3, 0x8c, 0x7c, 0xac,
+ 0x65, 0xea, 0xfe, 0x59, 0x9d, 0xc5, 0xdf, 0x2b, 0xb1, 0x47, 0x25, 0xc5,
+ 0x50, 0x9a, 0x7d, 0x0e, 0xd5, 0x17, 0x4f, 0x79, 0x67, 0x7a, 0xed, 0xef,
+ 0x90, 0x04, 0xfe, 0xc2, 0x7d, 0xbf, 0x82, 0xe7, 0xbd, 0xbe, 0x54, 0xb6,
+ 0xf9, 0x41, 0x5d, 0xf0, 0x5d, 0xfd, 0x15, 0xe8, 0xe2, 0xfc, 0x87, 0xf6,
+ 0xb9, 0xd8, 0xe3, 0x9a, 0x47, 0x2c, 0x62, 0x7f, 0x2c, 0x90, 0xdf, 0xd5,
+ 0x34, 0x92, 0xbe, 0xc3, 0x58, 0x4b, 0x52, 0x8c, 0xb3, 0xb9, 0x58, 0x42,
+ 0xd5, 0xbe, 0x1b, 0x4b, 0xf2, 0xc4, 0x16, 0xbd, 0xa4, 0x95, 0x72, 0x78,
+ 0x04, 0xf5, 0x1a, 0x7f, 0xff, 0xf0, 0xb8, 0xe4, 0x53, 0xec, 0xd1, 0x84,
+ 0x90, 0x0b, 0x0b, 0xf8, 0xbe, 0x25, 0xb7, 0x92, 0x2f, 0xb7, 0x7c, 0xf5,
+ 0x5b, 0x4a, 0x77, 0x35, 0x8b, 0xfb, 0x05, 0xbd, 0x8b, 0x69, 0xa5, 0xb3,
+ 0x9a, 0x7a, 0xcf, 0x36, 0xe0, 0x3d, 0xe8, 0xbf, 0xed, 0x6c, 0x73, 0x93,
+ 0x16, 0x69, 0xfb, 0x38, 0xdf, 0x5b, 0x18, 0xb6, 0x85, 0xf4, 0x93, 0x0f,
+ 0xe6, 0xac, 0xe0, 0x5c, 0x34, 0xe0, 0x21, 0xe0, 0xf3, 0xa3, 0xca, 0x85,
+ 0x74, 0xee, 0x31, 0xa4, 0x7b, 0xca, 0x08, 0x59, 0xcc, 0x01, 0x9f, 0xf6,
+ 0xfb, 0xf8, 0xff, 0x37, 0xe5, 0xea, 0xf1, 0x1e, 0x86, 0xa8, 0xfc, 0xdf,
+ 0x8b, 0xee, 0xa0, 0xf7, 0xab, 0xcf, 0x80, 0x0d, 0xe7, 0xac, 0xb5, 0xc5,
+ 0x67, 0x6d, 0x07, 0x3e, 0x6b, 0x3e, 0x9f, 0x1f, 0x7e, 0x4e, 0xea, 0xd1,
+ 0x59, 0x5b, 0xb2, 0xc1, 0x23, 0x6d, 0x6a, 0x27, 0x7b, 0xe3, 0x6f, 0x9c,
+ 0xd4, 0xef, 0xad, 0xa2, 0xb6, 0x7b, 0xad, 0x5e, 0x27, 0xeb, 0x64, 0xcf,
+ 0xee, 0xce, 0x22, 0xd7, 0x55, 0xab, 0x5e, 0xcd, 0x5c, 0x75, 0xd9, 0x6b,
+ 0xde, 0x69, 0x6f, 0x0d, 0x34, 0xff, 0x8e, 0x7a, 0xef, 0xa4, 0xe4, 0x7a,
+ 0x7d, 0xa9, 0x6a, 0xb5, 0x3d, 0x57, 0xde, 0xc0, 0x3c, 0x39, 0x5c, 0x90,
+ 0x19, 0xe8, 0x31, 0x89, 0xeb, 0x9b, 0xe5, 0xe5, 0x65, 0x75, 0x86, 0xe4,
+ 0x9f, 0xd5, 0xf0, 0x0c, 0x46, 0x9d, 0x43, 0x23, 0x5e, 0xcd, 0xaa, 0x78,
+ 0xbd, 0xb1, 0xac, 0xee, 0xa9, 0xdf, 0x3c, 0xd4, 0xdd, 0x19, 0xc4, 0x73,
+ 0xd4, 0x06, 0xd6, 0x6e, 0x29, 0xa2, 0x86, 0x3e, 0x6b, 0xcd, 0x18, 0xc4,
+ 0x29, 0x5c, 0x6b, 0x03, 0x6b, 0x9d, 0x5f, 0x96, 0xbd, 0x7c, 0xa7, 0xa3,
+ 0xaa, 0xce, 0xbd, 0xbc, 0x7e, 0xf5, 0xbc, 0x04, 0xbf, 0xd7, 0x8d, 0xfa,
+ 0x39, 0x8e, 0xef, 0x95, 0xf0, 0xb7, 0xa7, 0x8c, 0x01, 0xa8, 0x6b, 0x66,
+ 0x0a, 0x58, 0xaf, 0xd5, 0xf2, 0xfa, 0xd9, 0x2d, 0xd8, 0x7d, 0x84, 0xbf,
+ 0x65, 0xc0, 0xdf, 0x23, 0xb0, 0x13, 0xf8, 0xc1, 0xe6, 0x38, 0xaf, 0x59,
+ 0x4b, 0x04, 0xd7, 0x4c, 0x58, 0xff, 0x1b, 0xed, 0xcc, 0xfa, 0xa1, 0x98,
+ 0x41, 0x00, 0x00, 0x00 };
+static u32 bnx2_TXP_b09FwData[(0xd0/4) + 1] = {
+ 0x00000000, 0x00000014, 0x00000014, 0x00000014, 0x00000014, 0x00000010,
+ 0x00000030, 0x00000030, 0x00000000, 0x00000000, 0x00000000, 0x00000010,
+ 0x00008000, 0x00000000, 0x00000000, 0x00000000, 0x00008002, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000005, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000004, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000006,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000,
+ 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 };
+static u32 bnx2_TXP_b09FwRodata[(0x30/4) + 1] = {
+ 0x08003be8, 0x08003c14, 0x08003c5c, 0x08003c5c, 0x08003ae8, 0x08003b14,
+ 0x08003b14, 0x08003c5c, 0x08003c5c, 0x08003c5c, 0x08003b7c, 0x00000000,
+ 0x00000000 };
+static u32 bnx2_TXP_b09FwBss[(0xa20/4) + 1] = { 0x0 };
+static u32 bnx2_TXP_b09FwSbss[(0x80/4) + 1] = { 0x0 };
+
+static struct fw_info bnx2_txp_fw_09 = {
+ .ver_major = 0x1,
+ .ver_minor = 0x0,
+ .ver_fix = 0x0,
+
+ .start_addr = 0x08000060,
+
+ .text_addr = 0x08000000,
+ .text_len = 0x4194,
+ .text_index = 0x0,
+ .gz_text = bnx2_TXP_b09FwText,
+ .gz_text_len = sizeof(bnx2_TXP_b09FwText),
+
+ .data_addr = 0x080041e0,
+ .data_len = 0xd0,
+ .data_index = 0x0,
+ .data = bnx2_TXP_b09FwData,
+
+ .sbss_addr = 0x080042b0,
+ .sbss_len = 0x80,
+ .sbss_index = 0x0,
+ .sbss = bnx2_TXP_b09FwSbss,
+
+ .bss_addr = 0x08004330,
+ .bss_len = 0xa20,
+ .bss_index = 0x0,
+ .bss = bnx2_TXP_b09FwBss,
+
+ .rodata_addr = 0x08004198,
+ .rodata_len = 0x30,
+ .rodata_index = 0x0,
+ .rodata = bnx2_TXP_b09FwRodata,
+};
+
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 17a461152d39..488d8ed9e740 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1336,6 +1336,13 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
goto err_undo_flags;
}
+ if (slave_dev->get_stats == NULL) {
+ printk(KERN_NOTICE DRV_NAME
+ ": %s: the driver for slave device %s does not provide "
+ "get_stats function, network statistics will be "
+ "inaccurate.\n", bond_dev->name, slave_dev->name);
+ }
+
new_slave = kmalloc(sizeof(struct slave), GFP_KERNEL);
if (!new_slave) {
res = -ENOMEM;
@@ -3605,33 +3612,35 @@ static struct net_device_stats *bond_get_stats(struct net_device *bond_dev)
read_lock_bh(&bond->lock);
bond_for_each_slave(bond, slave, i) {
- sstats = slave->dev->get_stats(slave->dev);
-
- stats->rx_packets += sstats->rx_packets;
- stats->rx_bytes += sstats->rx_bytes;
- stats->rx_errors += sstats->rx_errors;
- stats->rx_dropped += sstats->rx_dropped;
-
- stats->tx_packets += sstats->tx_packets;
- stats->tx_bytes += sstats->tx_bytes;
- stats->tx_errors += sstats->tx_errors;
- stats->tx_dropped += sstats->tx_dropped;
-
- stats->multicast += sstats->multicast;
- stats->collisions += sstats->collisions;
-
- stats->rx_length_errors += sstats->rx_length_errors;
- stats->rx_over_errors += sstats->rx_over_errors;
- stats->rx_crc_errors += sstats->rx_crc_errors;
- stats->rx_frame_errors += sstats->rx_frame_errors;
- stats->rx_fifo_errors += sstats->rx_fifo_errors;
- stats->rx_missed_errors += sstats->rx_missed_errors;
-
- stats->tx_aborted_errors += sstats->tx_aborted_errors;
- stats->tx_carrier_errors += sstats->tx_carrier_errors;
- stats->tx_fifo_errors += sstats->tx_fifo_errors;
- stats->tx_heartbeat_errors += sstats->tx_heartbeat_errors;
- stats->tx_window_errors += sstats->tx_window_errors;
+ if (slave->dev->get_stats) {
+ sstats = slave->dev->get_stats(slave->dev);
+
+ stats->rx_packets += sstats->rx_packets;
+ stats->rx_bytes += sstats->rx_bytes;
+ stats->rx_errors += sstats->rx_errors;
+ stats->rx_dropped += sstats->rx_dropped;
+
+ stats->tx_packets += sstats->tx_packets;
+ stats->tx_bytes += sstats->tx_bytes;
+ stats->tx_errors += sstats->tx_errors;
+ stats->tx_dropped += sstats->tx_dropped;
+
+ stats->multicast += sstats->multicast;
+ stats->collisions += sstats->collisions;
+
+ stats->rx_length_errors += sstats->rx_length_errors;
+ stats->rx_over_errors += sstats->rx_over_errors;
+ stats->rx_crc_errors += sstats->rx_crc_errors;
+ stats->rx_frame_errors += sstats->rx_frame_errors;
+ stats->rx_fifo_errors += sstats->rx_fifo_errors;
+ stats->rx_missed_errors += sstats->rx_missed_errors;
+
+ stats->tx_aborted_errors += sstats->tx_aborted_errors;
+ stats->tx_carrier_errors += sstats->tx_carrier_errors;
+ stats->tx_fifo_errors += sstats->tx_fifo_errors;
+ stats->tx_heartbeat_errors += sstats->tx_heartbeat_errors;
+ stats->tx_window_errors += sstats->tx_window_errors;
+ }
}
read_unlock_bh(&bond->lock);
diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
index fe08f3845491..c8126484c2be 100644
--- a/drivers/net/cassini.c
+++ b/drivers/net/cassini.c
@@ -2825,7 +2825,7 @@ static inline int cas_xmit_tx_ringN(struct cas *cp, int ring,
u64 csum_start_off, csum_stuff_off;
csum_start_off = (u64) (skb->h.raw - skb->data);
- csum_stuff_off = (u64) ((skb->h.raw + skb->csum) - skb->data);
+ csum_stuff_off = csum_start_off + skb->csum_offset;
ctrl = TX_DESC_CSUM_EN |
CAS_BASE(TX_DESC_CSUM_START, csum_start_off) |
diff --git a/drivers/net/chelsio/Makefile b/drivers/net/chelsio/Makefile
index 54c78d94f48b..382d23f810ab 100644
--- a/drivers/net/chelsio/Makefile
+++ b/drivers/net/chelsio/Makefile
@@ -1,11 +1,11 @@
#
-# Chelsio 10Gb NIC driver for Linux.
+# Chelsio T1 driver
#
obj-$(CONFIG_CHELSIO_T1) += cxgb.o
-EXTRA_CFLAGS += -Idrivers/net/chelsio $(DEBUG_FLAGS)
+cxgb-$(CONFIG_CHELSIO_T1_1G) += ixf1010.o mac.o mv88e1xxx.o vsc7326.o vsc8244.o
+cxgb-objs := cxgb2.o espi.o tp.o pm3393.o sge.o subr.o \
+ mv88x201x.o my3126.o $(cxgb-y)
-cxgb-objs := cxgb2.o espi.o pm3393.o sge.o subr.o mv88x201x.o
-
diff --git a/drivers/net/chelsio/common.h b/drivers/net/chelsio/common.h
index 8b1bedbce0d5..74758d2c7af8 100644
--- a/drivers/net/chelsio/common.h
+++ b/drivers/net/chelsio/common.h
@@ -45,6 +45,7 @@
#include <linux/delay.h>
#include <linux/pci.h>
#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
#include <linux/mii.h>
#include <linux/crc32.h>
#include <linux/init.h>
@@ -53,13 +54,30 @@
#define DRV_DESCRIPTION "Chelsio 10Gb Ethernet Driver"
#define DRV_NAME "cxgb"
-#define DRV_VERSION "2.1.1"
+#define DRV_VERSION "2.2"
#define PFX DRV_NAME ": "
#define CH_ERR(fmt, ...) printk(KERN_ERR PFX fmt, ## __VA_ARGS__)
#define CH_WARN(fmt, ...) printk(KERN_WARNING PFX fmt, ## __VA_ARGS__)
#define CH_ALERT(fmt, ...) printk(KERN_ALERT PFX fmt, ## __VA_ARGS__)
+/*
+ * More powerful macro that selectively prints messages based on msg_enable.
+ * For info and debugging messages.
+ */
+#define CH_MSG(adapter, level, category, fmt, ...) do { \
+ if ((adapter)->msg_enable & NETIF_MSG_##category) \
+ printk(KERN_##level PFX "%s: " fmt, (adapter)->name, \
+ ## __VA_ARGS__); \
+} while (0)
+
+#ifdef DEBUG
+# define CH_DBG(adapter, category, fmt, ...) \
+ CH_MSG(adapter, DEBUG, category, fmt, ## __VA_ARGS__)
+#else
+# define CH_DBG(fmt, ...)
+#endif
+
#define CH_DEVICE(devid, ssid, idx) \
{ PCI_VENDOR_ID_CHELSIO, devid, PCI_ANY_ID, ssid, 0, 0, idx }
@@ -71,10 +89,6 @@
typedef struct adapter adapter_t;
-void t1_elmer0_ext_intr(adapter_t *adapter);
-void t1_link_changed(adapter_t *adapter, int port_id, int link_status,
- int speed, int duplex, int fc);
-
struct t1_rx_mode {
struct net_device *dev;
u32 idx;
@@ -97,26 +111,53 @@ static inline u8 *t1_get_next_mcaddr(struct t1_rx_mode *rm)
}
#define MAX_NPORTS 4
+#define PORT_MASK ((1 << MAX_NPORTS) - 1)
+#define NMTUS 8
+#define TCB_SIZE 128
#define SPEED_INVALID 0xffff
#define DUPLEX_INVALID 0xff
enum {
CHBT_BOARD_N110,
- CHBT_BOARD_N210
+ CHBT_BOARD_N210,
+ CHBT_BOARD_7500,
+ CHBT_BOARD_8000,
+ CHBT_BOARD_CHT101,
+ CHBT_BOARD_CHT110,
+ CHBT_BOARD_CHT210,
+ CHBT_BOARD_CHT204,
+ CHBT_BOARD_CHT204V,
+ CHBT_BOARD_CHT204E,
+ CHBT_BOARD_CHN204,
+ CHBT_BOARD_COUGAR,
+ CHBT_BOARD_6800,
+ CHBT_BOARD_SIMUL,
};
enum {
+ CHBT_TERM_FPGA,
CHBT_TERM_T1,
- CHBT_TERM_T2
+ CHBT_TERM_T2,
+ CHBT_TERM_T3
};
enum {
+ CHBT_MAC_CHELSIO_A,
+ CHBT_MAC_IXF1010,
CHBT_MAC_PM3393,
+ CHBT_MAC_VSC7321,
+ CHBT_MAC_DUMMY
};
enum {
+ CHBT_PHY_88E1041,
+ CHBT_PHY_88E1111,
CHBT_PHY_88X2010,
+ CHBT_PHY_XPAK,
+ CHBT_PHY_MY3126,
+ CHBT_PHY_8244,
+ CHBT_PHY_DUMMY
};
enum {
@@ -150,16 +191,44 @@ struct chelsio_pci_params {
unsigned char is_pcix;
};
+struct tp_params {
+ unsigned int pm_size;
+ unsigned int cm_size;
+ unsigned int pm_rx_base;
+ unsigned int pm_tx_base;
+ unsigned int pm_rx_pg_size;
+ unsigned int pm_tx_pg_size;
+ unsigned int pm_rx_num_pgs;
+ unsigned int pm_tx_num_pgs;
+ unsigned int rx_coalescing_size;
+ unsigned int use_5tuple_mode;
+};
+
+struct mc5_params {
+ unsigned int mode; /* selects MC5 width */
+ unsigned int nservers; /* size of server region */
+ unsigned int nroutes; /* size of routing region */
+};
+
+/* Default MC5 region sizes */
+#define DEFAULT_SERVER_REGION_LEN 256
+#define DEFAULT_RT_REGION_LEN 1024
+
struct adapter_params {
struct sge_params sge;
+ struct mc5_params mc5;
+ struct tp_params tp;
struct chelsio_pci_params pci;
const struct board_info *brd_info;
+ unsigned short mtus[NMTUS];
unsigned int nports; /* # of ethernet ports */
unsigned int stats_update_period;
unsigned short chip_revision;
unsigned char chip_version;
+ unsigned char is_asic;
+ unsigned char has_msi;
};
struct link_config {
@@ -207,17 +276,20 @@ struct adapter {
/* Terminator modules. */
struct sge *sge;
struct peespi *espi;
+ struct petp *tp;
struct port_info port[MAX_NPORTS];
struct delayed_work stats_update_task;
struct timer_list stats_update_timer;
- struct semaphore mib_mutex;
spinlock_t tpi_lock;
spinlock_t work_lock;
+ spinlock_t mac_lock;
+
/* guards async operations */
spinlock_t async_lock ____cacheline_aligned;
u32 slow_intr_mask;
+ int t1powersave;
};
enum { /* adapter flags */
@@ -256,6 +328,11 @@ struct board_info {
const char *desc;
};
+static inline int t1_is_asic(const adapter_t *adapter)
+{
+ return adapter->params.is_asic;
+}
+
extern struct pci_device_id t1_pci_tbl[];
static inline int adapter_matches_type(const adapter_t *adapter,
@@ -285,13 +362,15 @@ static inline unsigned int core_ticks_per_usec(const adapter_t *adap)
return board_info(adap)->clock_core / 1000000;
}
+extern int __t1_tpi_read(adapter_t *adapter, u32 addr, u32 *valp);
+extern int __t1_tpi_write(adapter_t *adapter, u32 addr, u32 value);
extern int t1_tpi_write(adapter_t *adapter, u32 addr, u32 value);
extern int t1_tpi_read(adapter_t *adapter, u32 addr, u32 *value);
extern void t1_interrupts_enable(adapter_t *adapter);
extern void t1_interrupts_disable(adapter_t *adapter);
extern void t1_interrupts_clear(adapter_t *adapter);
-extern int elmer0_ext_intr_handler(adapter_t *adapter);
+extern int t1_elmer0_ext_intr_handler(adapter_t *adapter);
extern int t1_slow_intr_handler(adapter_t *adapter);
extern int t1_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc);
@@ -305,9 +384,7 @@ extern int t1_init_hw_modules(adapter_t *adapter);
extern int t1_init_sw_modules(adapter_t *adapter, const struct board_info *bi);
extern void t1_free_sw_modules(adapter_t *adapter);
extern void t1_fatal_err(adapter_t *adapter);
-
-extern void t1_tp_set_udp_checksum_offload(adapter_t *adapter, int enable);
-extern void t1_tp_set_tcp_checksum_offload(adapter_t *adapter, int enable);
-extern void t1_tp_set_ip_checksum_offload(adapter_t *adapter, int enable);
-
+extern void t1_link_changed(adapter_t *adapter, int port_id);
+extern void t1_link_negotiated(adapter_t *adapter, int port_id, int link_stat,
+ int speed, int duplex, int pause);
#endif /* _CXGB_COMMON_H_ */
diff --git a/drivers/net/chelsio/cphy.h b/drivers/net/chelsio/cphy.h
index 3412342f7345..60901f25014e 100644
--- a/drivers/net/chelsio/cphy.h
+++ b/drivers/net/chelsio/cphy.h
@@ -52,7 +52,14 @@ struct mdio_ops {
/* PHY interrupt types */
enum {
cphy_cause_link_change = 0x1,
- cphy_cause_error = 0x2
+ cphy_cause_error = 0x2,
+ cphy_cause_fifo_error = 0x3
+};
+
+enum {
+ PHY_LINK_UP = 0x1,
+ PHY_AUTONEG_RDY = 0x2,
+ PHY_AUTONEG_EN = 0x4
};
struct cphy;
@@ -81,7 +88,18 @@ struct cphy_ops {
/* A PHY instance */
struct cphy {
int addr; /* PHY address */
+ int state; /* Link status state machine */
adapter_t *adapter; /* associated adapter */
+
+ struct work_struct phy_update;
+
+ u16 bmsr;
+ int count;
+ int act_count;
+ int act_on;
+
+ u32 elmer_gpo;
+
struct cphy_ops *ops; /* PHY operations */
int (*mdio_read)(adapter_t *adapter, int phy_addr, int mmd_addr,
int reg_addr, unsigned int *val);
@@ -142,6 +160,10 @@ struct gphy {
int (*reset)(adapter_t *adapter);
};
+extern struct gphy t1_my3126_ops;
+extern struct gphy t1_mv88e1xxx_ops;
+extern struct gphy t1_vsc8244_ops;
+extern struct gphy t1_xpak_ops;
extern struct gphy t1_mv88x201x_ops;
extern struct gphy t1_dummy_phy_ops;
diff --git a/drivers/net/chelsio/cpl5_cmd.h b/drivers/net/chelsio/cpl5_cmd.h
index 5b357d9e88d6..35f565be4fd3 100644
--- a/drivers/net/chelsio/cpl5_cmd.h
+++ b/drivers/net/chelsio/cpl5_cmd.h
@@ -46,24 +46,385 @@
#endif
enum CPL_opcode {
+ CPL_PASS_OPEN_REQ = 0x1,
+ CPL_PASS_OPEN_RPL = 0x2,
+ CPL_PASS_ESTABLISH = 0x3,
+ CPL_PASS_ACCEPT_REQ = 0xE,
+ CPL_PASS_ACCEPT_RPL = 0x4,
+ CPL_ACT_OPEN_REQ = 0x5,
+ CPL_ACT_OPEN_RPL = 0x6,
+ CPL_CLOSE_CON_REQ = 0x7,
+ CPL_CLOSE_CON_RPL = 0x8,
+ CPL_CLOSE_LISTSRV_REQ = 0x9,
+ CPL_CLOSE_LISTSRV_RPL = 0xA,
+ CPL_ABORT_REQ = 0xB,
+ CPL_ABORT_RPL = 0xC,
+ CPL_PEER_CLOSE = 0xD,
+ CPL_ACT_ESTABLISH = 0x17,
+
+ CPL_GET_TCB = 0x24,
+ CPL_GET_TCB_RPL = 0x25,
+ CPL_SET_TCB = 0x26,
+ CPL_SET_TCB_FIELD = 0x27,
+ CPL_SET_TCB_RPL = 0x28,
+ CPL_PCMD = 0x29,
+
+ CPL_PCMD_READ = 0x31,
+ CPL_PCMD_READ_RPL = 0x32,
+
+
+ CPL_RX_DATA = 0xA0,
+ CPL_RX_DATA_DDP = 0xA1,
+ CPL_RX_DATA_ACK = 0xA3,
CPL_RX_PKT = 0xAD,
+ CPL_RX_ISCSI_HDR = 0xAF,
+ CPL_TX_DATA_ACK = 0xB0,
+ CPL_TX_DATA = 0xB1,
CPL_TX_PKT = 0xB2,
CPL_TX_PKT_LSO = 0xB6,
+
+ CPL_RTE_DELETE_REQ = 0xC0,
+ CPL_RTE_DELETE_RPL = 0xC1,
+ CPL_RTE_WRITE_REQ = 0xC2,
+ CPL_RTE_WRITE_RPL = 0xD3,
+ CPL_RTE_READ_REQ = 0xC3,
+ CPL_RTE_READ_RPL = 0xC4,
+ CPL_L2T_WRITE_REQ = 0xC5,
+ CPL_L2T_WRITE_RPL = 0xD4,
+ CPL_L2T_READ_REQ = 0xC6,
+ CPL_L2T_READ_RPL = 0xC7,
+ CPL_SMT_WRITE_REQ = 0xC8,
+ CPL_SMT_WRITE_RPL = 0xD5,
+ CPL_SMT_READ_REQ = 0xC9,
+ CPL_SMT_READ_RPL = 0xCA,
+ CPL_ARP_MISS_REQ = 0xCD,
+ CPL_ARP_MISS_RPL = 0xCE,
+ CPL_MIGRATE_C2T_REQ = 0xDC,
+ CPL_MIGRATE_C2T_RPL = 0xDD,
+ CPL_ERROR = 0xD7,
+
+ /* internal: driver -> TOM */
+ CPL_MSS_CHANGE = 0xE1
};
-enum { /* TX_PKT_LSO ethernet types */
+#define NUM_CPL_CMDS 256
+
+enum CPL_error {
+ CPL_ERR_NONE = 0,
+ CPL_ERR_TCAM_PARITY = 1,
+ CPL_ERR_TCAM_FULL = 3,
+ CPL_ERR_CONN_RESET = 20,
+ CPL_ERR_CONN_EXIST = 22,
+ CPL_ERR_ARP_MISS = 23,
+ CPL_ERR_BAD_SYN = 24,
+ CPL_ERR_CONN_TIMEDOUT = 30,
+ CPL_ERR_XMIT_TIMEDOUT = 31,
+ CPL_ERR_PERSIST_TIMEDOUT = 32,
+ CPL_ERR_FINWAIT2_TIMEDOUT = 33,
+ CPL_ERR_KEEPALIVE_TIMEDOUT = 34,
+ CPL_ERR_ABORT_FAILED = 42,
+ CPL_ERR_GENERAL = 99
+};
+
+enum {
+ CPL_CONN_POLICY_AUTO = 0,
+ CPL_CONN_POLICY_ASK = 1,
+ CPL_CONN_POLICY_DENY = 3
+};
+
+enum {
+ ULP_MODE_NONE = 0,
+ ULP_MODE_TCPDDP = 1,
+ ULP_MODE_ISCSI = 2,
+ ULP_MODE_IWARP = 3,
+ ULP_MODE_SSL = 4
+};
+
+enum {
+ CPL_PASS_OPEN_ACCEPT,
+ CPL_PASS_OPEN_REJECT
+};
+
+enum {
+ CPL_ABORT_SEND_RST = 0,
+ CPL_ABORT_NO_RST,
+ CPL_ABORT_POST_CLOSE_REQ = 2
+};
+
+enum { // TX_PKT_LSO ethernet types
CPL_ETH_II,
CPL_ETH_II_VLAN,
CPL_ETH_802_3,
CPL_ETH_802_3_VLAN
};
-struct cpl_rx_data {
+union opcode_tid {
+ u32 opcode_tid;
+ u8 opcode;
+};
+
+#define S_OPCODE 24
+#define V_OPCODE(x) ((x) << S_OPCODE)
+#define G_OPCODE(x) (((x) >> S_OPCODE) & 0xFF)
+#define G_TID(x) ((x) & 0xFFFFFF)
+
+/* tid is assumed to be 24-bits */
+#define MK_OPCODE_TID(opcode, tid) (V_OPCODE(opcode) | (tid))
+
+#define OPCODE_TID(cmd) ((cmd)->ot.opcode_tid)
+
+/* extract the TID from a CPL command */
+#define GET_TID(cmd) (G_TID(ntohl(OPCODE_TID(cmd))))
+
+struct tcp_options {
+ u16 mss;
+ u8 wsf;
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ u8 rsvd:4;
+ u8 ecn:1;
+ u8 sack:1;
+ u8 tstamp:1;
+#else
+ u8 tstamp:1;
+ u8 sack:1;
+ u8 ecn:1;
+ u8 rsvd:4;
+#endif
+};
+
+struct cpl_pass_open_req {
+ union opcode_tid ot;
+ u16 local_port;
+ u16 peer_port;
+ u32 local_ip;
+ u32 peer_ip;
+ u32 opt0h;
+ u32 opt0l;
+ u32 peer_netmask;
+ u32 opt1;
+};
+
+struct cpl_pass_open_rpl {
+ union opcode_tid ot;
+ u16 local_port;
+ u16 peer_port;
+ u32 local_ip;
+ u32 peer_ip;
+ u8 resvd[7];
+ u8 status;
+};
+
+struct cpl_pass_establish {
+ union opcode_tid ot;
+ u16 local_port;
+ u16 peer_port;
+ u32 local_ip;
+ u32 peer_ip;
+ u32 tos_tid;
+ u8 l2t_idx;
+ u8 rsvd[3];
+ u32 snd_isn;
+ u32 rcv_isn;
+};
+
+struct cpl_pass_accept_req {
+ union opcode_tid ot;
+ u16 local_port;
+ u16 peer_port;
+ u32 local_ip;
+ u32 peer_ip;
+ u32 tos_tid;
+ struct tcp_options tcp_options;
+ u8 dst_mac[6];
+ u16 vlan_tag;
+ u8 src_mac[6];
+ u8 rsvd[2];
+ u32 rcv_isn;
+ u32 unknown_tcp_options;
+};
+
+struct cpl_pass_accept_rpl {
+ union opcode_tid ot;
+ u32 rsvd0;
+ u32 rsvd1;
+ u32 peer_ip;
+ u32 opt0h;
+ union {
+ u32 opt0l;
+ struct {
+ u8 rsvd[3];
+ u8 status;
+ };
+ };
+};
+
+struct cpl_act_open_req {
+ union opcode_tid ot;
+ u16 local_port;
+ u16 peer_port;
+ u32 local_ip;
+ u32 peer_ip;
+ u32 opt0h;
+ u32 opt0l;
+ u32 iff_vlantag;
+ u32 rsvd;
+};
+
+struct cpl_act_open_rpl {
+ union opcode_tid ot;
+ u16 local_port;
+ u16 peer_port;
+ u32 local_ip;
+ u32 peer_ip;
+ u32 new_tid;
+ u8 rsvd[3];
+ u8 status;
+};
+
+struct cpl_act_establish {
+ union opcode_tid ot;
+ u16 local_port;
+ u16 peer_port;
+ u32 local_ip;
+ u32 peer_ip;
+ u32 tos_tid;
+ u32 rsvd;
+ u32 snd_isn;
+ u32 rcv_isn;
+};
+
+struct cpl_get_tcb {
+ union opcode_tid ot;
+ u32 rsvd;
+};
+
+struct cpl_get_tcb_rpl {
+ union opcode_tid ot;
+ u16 len;
+ u8 rsvd;
+ u8 status;
+};
+
+struct cpl_set_tcb {
+ union opcode_tid ot;
+ u16 len;
+ u16 rsvd;
+};
+
+struct cpl_set_tcb_field {
+ union opcode_tid ot;
+ u8 rsvd[3];
+ u8 offset;
+ u32 mask;
+ u32 val;
+};
+
+struct cpl_set_tcb_rpl {
+ union opcode_tid ot;
+ u8 rsvd[3];
+ u8 status;
+};
+
+struct cpl_pcmd {
+ union opcode_tid ot;
+ u16 dlen_in;
+ u16 dlen_out;
+ u32 pcmd_parm[2];
+};
+
+struct cpl_pcmd_read {
+ union opcode_tid ot;
+ u32 rsvd1;
+ u16 rsvd2;
+ u32 addr;
+ u16 len;
+};
+
+struct cpl_pcmd_read_rpl {
+ union opcode_tid ot;
+ u16 len;
+};
+
+struct cpl_close_con_req {
+ union opcode_tid ot;
+ u32 rsvd;
+};
+
+struct cpl_close_con_rpl {
+ union opcode_tid ot;
+ u8 rsvd[3];
+ u8 status;
+ u32 snd_nxt;
+ u32 rcv_nxt;
+};
+
+struct cpl_close_listserv_req {
+ union opcode_tid ot;
+ u32 rsvd;
+};
+
+struct cpl_close_listserv_rpl {
+ union opcode_tid ot;
+ u8 rsvd[3];
+ u8 status;
+};
+
+struct cpl_abort_req {
+ union opcode_tid ot;
u32 rsvd0;
+ u8 rsvd1;
+ u8 cmd;
+ u8 rsvd2[6];
+};
+
+struct cpl_abort_rpl {
+ union opcode_tid ot;
+ u32 rsvd0;
+ u8 rsvd1;
+ u8 status;
+ u8 rsvd2[6];
+};
+
+struct cpl_peer_close {
+ union opcode_tid ot;
+ u32 rsvd;
+};
+
+struct cpl_tx_data {
+ union opcode_tid ot;
+ u32 len;
+ u32 rsvd0;
+ u16 urg;
+ u16 flags;
+};
+
+struct cpl_tx_data_ack {
+ union opcode_tid ot;
+ u32 ack_seq;
+};
+
+struct cpl_rx_data {
+ union opcode_tid ot;
u32 len;
u32 seq;
u16 urg;
- u8 rsvd1;
+ u8 rsvd;
+ u8 status;
+};
+
+struct cpl_rx_data_ack {
+ union opcode_tid ot;
+ u32 credit;
+};
+
+struct cpl_rx_data_ddp {
+ union opcode_tid ot;
+ u32 len;
+ u32 seq;
+ u32 nxt_seq;
+ u32 ulp_crc;
+ u16 ddp_status;
+ u8 rsvd;
u8 status;
};
@@ -99,9 +460,9 @@ struct cpl_tx_pkt_lso {
u8 ip_csum_dis:1;
u8 l4_csum_dis:1;
u8 vlan_valid:1;
- u8 rsvd:1;
+ u8 :1;
#else
- u8 rsvd:1;
+ u8 :1;
u8 vlan_valid:1;
u8 l4_csum_dis:1;
u8 ip_csum_dis:1;
@@ -110,8 +471,7 @@ struct cpl_tx_pkt_lso {
u16 vlan;
__be32 len;
- u32 rsvd2;
- u8 rsvd3;
+ u8 rsvd[5];
#if defined(__LITTLE_ENDIAN_BITFIELD)
u8 tcp_hdr_words:4;
u8 ip_hdr_words:4;
@@ -138,8 +498,142 @@ struct cpl_rx_pkt {
u8 iff:4;
#endif
u16 csum;
- __be16 vlan;
+ u16 vlan;
u16 len;
};
+struct cpl_l2t_write_req {
+ union opcode_tid ot;
+ u32 params;
+ u8 rsvd1[2];
+ u8 dst_mac[6];
+};
+
+struct cpl_l2t_write_rpl {
+ union opcode_tid ot;
+ u8 status;
+ u8 rsvd[3];
+};
+
+struct cpl_l2t_read_req {
+ union opcode_tid ot;
+ u8 rsvd[3];
+ u8 l2t_idx;
+};
+
+struct cpl_l2t_read_rpl {
+ union opcode_tid ot;
+ u32 params;
+ u8 rsvd1[2];
+ u8 dst_mac[6];
+};
+
+struct cpl_smt_write_req {
+ union opcode_tid ot;
+ u8 rsvd0;
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ u8 rsvd1:1;
+ u8 mtu_idx:3;
+ u8 iff:4;
+#else
+ u8 iff:4;
+ u8 mtu_idx:3;
+ u8 rsvd1:1;
+#endif
+ u16 rsvd2;
+ u16 rsvd3;
+ u8 src_mac1[6];
+ u16 rsvd4;
+ u8 src_mac0[6];
+};
+
+struct cpl_smt_write_rpl {
+ union opcode_tid ot;
+ u8 status;
+ u8 rsvd[3];
+};
+
+struct cpl_smt_read_req {
+ union opcode_tid ot;
+ u8 rsvd0;
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ u8 rsvd1:4;
+ u8 iff:4;
+#else
+ u8 iff:4;
+ u8 rsvd1:4;
+#endif
+ u16 rsvd2;
+};
+
+struct cpl_smt_read_rpl {
+ union opcode_tid ot;
+ u8 status;
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ u8 rsvd1:1;
+ u8 mtu_idx:3;
+ u8 rsvd0:4;
+#else
+ u8 rsvd0:4;
+ u8 mtu_idx:3;
+ u8 rsvd1:1;
+#endif
+ u16 rsvd2;
+ u16 rsvd3;
+ u8 src_mac1[6];
+ u16 rsvd4;
+ u8 src_mac0[6];
+};
+
+struct cpl_rte_delete_req {
+ union opcode_tid ot;
+ u32 params;
+};
+
+struct cpl_rte_delete_rpl {
+ union opcode_tid ot;
+ u8 status;
+ u8 rsvd[3];
+};
+
+struct cpl_rte_write_req {
+ union opcode_tid ot;
+ u32 params;
+ u32 netmask;
+ u32 faddr;
+};
+
+struct cpl_rte_write_rpl {
+ union opcode_tid ot;
+ u8 status;
+ u8 rsvd[3];
+};
+
+struct cpl_rte_read_req {
+ union opcode_tid ot;
+ u32 params;
+};
+
+struct cpl_rte_read_rpl {
+ union opcode_tid ot;
+ u8 status;
+ u8 rsvd0[2];
+ u8 l2t_idx;
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ u8 rsvd1:7;
+ u8 select:1;
+#else
+ u8 select:1;
+ u8 rsvd1:7;
+#endif
+ u8 rsvd2[3];
+ u32 addr;
+};
+
+struct cpl_mss_change {
+ union opcode_tid ot;
+ u32 mss;
+};
+
#endif /* _CXGB_CPL5_CMD_H_ */
+
diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c
index f607cc6a276b..de48eadddbc4 100644
--- a/drivers/net/chelsio/cxgb2.c
+++ b/drivers/net/chelsio/cxgb2.c
@@ -45,7 +45,6 @@
#include <linux/if_vlan.h>
#include <linux/mii.h>
#include <linux/sockios.h>
-#include <linux/proc_fs.h>
#include <linux/dma-mapping.h>
#include <asm/uaccess.h>
@@ -54,36 +53,10 @@
#include "gmac.h"
#include "cphy.h"
#include "sge.h"
+#include "tp.h"
#include "espi.h"
+#include "elmer0.h"
-#ifdef work_struct
-#include <linux/tqueue.h>
-#define INIT_WORK INIT_TQUEUE
-#define schedule_work schedule_task
-#define flush_scheduled_work flush_scheduled_tasks
-
-static inline void schedule_mac_stats_update(struct adapter *ap, int secs)
-{
- mod_timer(&ap->stats_update_timer, jiffies + secs * HZ);
-}
-
-static inline void cancel_mac_stats_update(struct adapter *ap)
-{
- del_timer_sync(&ap->stats_update_timer);
- flush_scheduled_tasks();
-}
-
-/*
- * Stats update timer for 2.4. It schedules a task to do the actual update as
- * we need to access MAC statistics in process context.
- */
-static void mac_stats_timer(unsigned long data)
-{
- struct adapter *ap = (struct adapter *)data;
-
- schedule_task(&ap->stats_update_task);
-}
-#else
#include <linux/workqueue.h>
static inline void schedule_mac_stats_update(struct adapter *ap, int secs)
@@ -95,7 +68,6 @@ static inline void cancel_mac_stats_update(struct adapter *ap)
{
cancel_delayed_work(&ap->stats_update_task);
}
-#endif
#define MAX_CMDQ_ENTRIES 16384
#define MAX_CMDQ1_ENTRIES 1024
@@ -103,10 +75,9 @@ static inline void cancel_mac_stats_update(struct adapter *ap)
#define MAX_RX_JUMBO_BUFFERS 16384
#define MAX_TX_BUFFERS_HIGH 16384U
#define MAX_TX_BUFFERS_LOW 1536U
+#define MAX_TX_BUFFERS 1460U
#define MIN_FL_ENTRIES 32
-#define PORT_MASK ((1 << MAX_NPORTS) - 1)
-
#define DFLT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | \
NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP |\
NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
@@ -124,8 +95,21 @@ MODULE_LICENSE("GPL");
static int dflt_msg_enable = DFLT_MSG_ENABLE;
module_param(dflt_msg_enable, int, 0);
-MODULE_PARM_DESC(dflt_msg_enable, "Chelsio T1 message enable bitmap");
+MODULE_PARM_DESC(dflt_msg_enable, "Chelsio T1 default message enable bitmap");
+
+#define HCLOCK 0x0
+#define LCLOCK 0x1
+
+/* T1 cards powersave mode */
+static int t1_clock(struct adapter *adapter, int mode);
+static int t1powersave = 1; /* HW default is powersave mode. */
+module_param(t1powersave, int, 0);
+MODULE_PARM_DESC(t1powersave, "Enable/Disable T1 powersaving mode");
+
+static int disable_msi = 0;
+module_param(disable_msi, int, 0);
+MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
static const char pci_speed[][4] = {
"33", "66", "100", "133"
@@ -149,7 +133,7 @@ static void t1_set_rxmode(struct net_device *dev)
static void link_report(struct port_info *p)
{
if (!netif_carrier_ok(p->dev))
- printk(KERN_INFO "%s: link down\n", p->dev->name);
+ printk(KERN_INFO "%s: link down\n", p->dev->name);
else {
const char *s = "10Mbps";
@@ -159,13 +143,13 @@ static void link_report(struct port_info *p)
case SPEED_100: s = "100Mbps"; break;
}
- printk(KERN_INFO "%s: link up, %s, %s-duplex\n",
+ printk(KERN_INFO "%s: link up, %s, %s-duplex\n",
p->dev->name, s,
p->link_config.duplex == DUPLEX_FULL ? "full" : "half");
}
}
-void t1_link_changed(struct adapter *adapter, int port_id, int link_stat,
+void t1_link_negotiated(struct adapter *adapter, int port_id, int link_stat,
int speed, int duplex, int pause)
{
struct port_info *p = &adapter->port[port_id];
@@ -177,6 +161,22 @@ void t1_link_changed(struct adapter *adapter, int port_id, int link_stat,
netif_carrier_off(p->dev);
link_report(p);
+ /* multi-ports: inform toe */
+ if ((speed > 0) && (adapter->params.nports > 1)) {
+ unsigned int sched_speed = 10;
+ switch (speed) {
+ case SPEED_1000:
+ sched_speed = 1000;
+ break;
+ case SPEED_100:
+ sched_speed = 100;
+ break;
+ case SPEED_10:
+ sched_speed = 10;
+ break;
+ }
+ t1_sched_update_parms(adapter->sge, port_id, 0, sched_speed);
+ }
}
}
@@ -195,8 +195,10 @@ static void link_start(struct port_info *p)
static void enable_hw_csum(struct adapter *adapter)
{
if (adapter->flags & TSO_CAPABLE)
- t1_tp_set_ip_checksum_offload(adapter, 1); /* for TSO only */
- t1_tp_set_tcp_checksum_offload(adapter, 1);
+ t1_tp_set_ip_checksum_offload(adapter->tp, 1); /* for TSO only */
+ if (adapter->flags & UDP_CSUM_CAPABLE)
+ t1_tp_set_udp_checksum_offload(adapter->tp, 1);
+ t1_tp_set_tcp_checksum_offload(adapter->tp, 1);
}
/*
@@ -217,11 +219,19 @@ static int cxgb_up(struct adapter *adapter)
}
t1_interrupts_clear(adapter);
- if ((err = request_irq(adapter->pdev->irq,
- t1_select_intr_handler(adapter), IRQF_SHARED,
- adapter->name, adapter))) {
+
+ adapter->params.has_msi = !disable_msi && pci_enable_msi(adapter->pdev) == 0;
+ err = request_irq(adapter->pdev->irq,
+ t1_select_intr_handler(adapter),
+ adapter->params.has_msi ? 0 : IRQF_SHARED,
+ adapter->name, adapter);
+ if (err) {
+ if (adapter->params.has_msi)
+ pci_disable_msi(adapter->pdev);
+
goto out_err;
}
+
t1_sge_start(adapter->sge);
t1_interrupts_enable(adapter);
out_err:
@@ -236,6 +246,8 @@ static void cxgb_down(struct adapter *adapter)
t1_sge_stop(adapter->sge);
t1_interrupts_disable(adapter);
free_irq(adapter->pdev->irq, adapter);
+ if (adapter->params.has_msi)
+ pci_disable_msi(adapter->pdev);
}
static int cxgb_open(struct net_device *dev)
@@ -290,7 +302,7 @@ static struct net_device_stats *t1_get_stats(struct net_device *dev)
/* Do a full update of the MAC stats */
pstats = p->mac->ops->statistics_update(p->mac,
- MAC_STATS_UPDATE_FULL);
+ MAC_STATS_UPDATE_FULL);
ns->tx_packets = pstats->TxUnicastFramesOK +
pstats->TxMulticastFramesOK + pstats->TxBroadcastFramesOK;
@@ -344,47 +356,53 @@ static void set_msglevel(struct net_device *dev, u32 val)
}
static char stats_strings[][ETH_GSTRING_LEN] = {
- "TxOctetsOK",
- "TxOctetsBad",
- "TxUnicastFramesOK",
- "TxMulticastFramesOK",
- "TxBroadcastFramesOK",
- "TxPauseFrames",
- "TxFramesWithDeferredXmissions",
- "TxLateCollisions",
- "TxTotalCollisions",
- "TxFramesAbortedDueToXSCollisions",
- "TxUnderrun",
- "TxLengthErrors",
- "TxInternalMACXmitError",
- "TxFramesWithExcessiveDeferral",
- "TxFCSErrors",
-
- "RxOctetsOK",
- "RxOctetsBad",
- "RxUnicastFramesOK",
- "RxMulticastFramesOK",
- "RxBroadcastFramesOK",
- "RxPauseFrames",
- "RxFCSErrors",
- "RxAlignErrors",
- "RxSymbolErrors",
- "RxDataErrors",
- "RxSequenceErrors",
- "RxRuntErrors",
- "RxJabberErrors",
- "RxInternalMACRcvError",
- "RxInRangeLengthErrors",
- "RxOutOfRangeLengthField",
- "RxFrameTooLongErrors",
-
- "TSO",
- "VLANextractions",
- "VLANinsertions",
+ "TxOctetsOK",
+ "TxOctetsBad",
+ "TxUnicastFramesOK",
+ "TxMulticastFramesOK",
+ "TxBroadcastFramesOK",
+ "TxPauseFrames",
+ "TxFramesWithDeferredXmissions",
+ "TxLateCollisions",
+ "TxTotalCollisions",
+ "TxFramesAbortedDueToXSCollisions",
+ "TxUnderrun",
+ "TxLengthErrors",
+ "TxInternalMACXmitError",
+ "TxFramesWithExcessiveDeferral",
+ "TxFCSErrors",
+
+ "RxOctetsOK",
+ "RxOctetsBad",
+ "RxUnicastFramesOK",
+ "RxMulticastFramesOK",
+ "RxBroadcastFramesOK",
+ "RxPauseFrames",
+ "RxFCSErrors",
+ "RxAlignErrors",
+ "RxSymbolErrors",
+ "RxDataErrors",
+ "RxSequenceErrors",
+ "RxRuntErrors",
+ "RxJabberErrors",
+ "RxInternalMACRcvError",
+ "RxInRangeLengthErrors",
+ "RxOutOfRangeLengthField",
+ "RxFrameTooLongErrors",
+
+ /* Port stats */
+ "RxPackets",
"RxCsumGood",
+ "TxPackets",
"TxCsumOffload",
- "RxDrops"
-
+ "TxTso",
+ "RxVlan",
+ "TxVlan",
+
+ /* Interrupt stats */
+ "rx drops",
+ "pure_rsps",
+ "unhandled irqs",
"respQ_empty",
"respQ_overflow",
"freelistQ_empty",
@@ -392,11 +410,7 @@ static char stats_strings[][ETH_GSTRING_LEN] = {
"pkt_mismatch",
"cmdQ_full0",
"cmdQ_full1",
- "tx_ipfrags",
- "tx_reg_pkts",
- "tx_lso_pkts",
- "tx_do_cksum",
-
+
"espi_DIP2ParityErr",
"espi_DIP4Err",
"espi_RxDrops",
@@ -404,7 +418,7 @@ static char stats_strings[][ETH_GSTRING_LEN] = {
"espi_RxOvfl",
"espi_ParityErr"
};
-
+
#define T2_REGMAP_SIZE (3 * 1024)
static int get_regs_len(struct net_device *dev)
@@ -439,65 +453,77 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats,
struct adapter *adapter = dev->priv;
struct cmac *mac = adapter->port[dev->if_port].mac;
const struct cmac_statistics *s;
- const struct sge_port_stats *ss;
const struct sge_intr_counts *t;
+ struct sge_port_stats ss;
s = mac->ops->statistics_update(mac, MAC_STATS_UPDATE_FULL);
- ss = t1_sge_get_port_stats(adapter->sge, dev->if_port);
- t = t1_sge_get_intr_counts(adapter->sge);
- *data++ = s->TxOctetsOK;
- *data++ = s->TxOctetsBad;
- *data++ = s->TxUnicastFramesOK;
- *data++ = s->TxMulticastFramesOK;
- *data++ = s->TxBroadcastFramesOK;
- *data++ = s->TxPauseFrames;
- *data++ = s->TxFramesWithDeferredXmissions;
- *data++ = s->TxLateCollisions;
- *data++ = s->TxTotalCollisions;
- *data++ = s->TxFramesAbortedDueToXSCollisions;
- *data++ = s->TxUnderrun;
- *data++ = s->TxLengthErrors;
- *data++ = s->TxInternalMACXmitError;
- *data++ = s->TxFramesWithExcessiveDeferral;
- *data++ = s->TxFCSErrors;
-
- *data++ = s->RxOctetsOK;
- *data++ = s->RxOctetsBad;
- *data++ = s->RxUnicastFramesOK;
- *data++ = s->RxMulticastFramesOK;
- *data++ = s->RxBroadcastFramesOK;
- *data++ = s->RxPauseFrames;
- *data++ = s->RxFCSErrors;
- *data++ = s->RxAlignErrors;
- *data++ = s->RxSymbolErrors;
- *data++ = s->RxDataErrors;
- *data++ = s->RxSequenceErrors;
- *data++ = s->RxRuntErrors;
- *data++ = s->RxJabberErrors;
- *data++ = s->RxInternalMACRcvError;
- *data++ = s->RxInRangeLengthErrors;
- *data++ = s->RxOutOfRangeLengthField;
- *data++ = s->RxFrameTooLongErrors;
-
- *data++ = ss->tso;
- *data++ = ss->vlan_xtract;
- *data++ = ss->vlan_insert;
- *data++ = ss->rx_cso_good;
- *data++ = ss->tx_cso;
- *data++ = ss->rx_drops;
-
- *data++ = (u64)t->respQ_empty;
- *data++ = (u64)t->respQ_overflow;
- *data++ = (u64)t->freelistQ_empty;
- *data++ = (u64)t->pkt_too_big;
- *data++ = (u64)t->pkt_mismatch;
- *data++ = (u64)t->cmdQ_full[0];
- *data++ = (u64)t->cmdQ_full[1];
- *data++ = (u64)t->tx_ipfrags;
- *data++ = (u64)t->tx_reg_pkts;
- *data++ = (u64)t->tx_lso_pkts;
- *data++ = (u64)t->tx_do_cksum;
+ *data++ = s->TxOctetsOK;
+ *data++ = s->TxOctetsBad;
+ *data++ = s->TxUnicastFramesOK;
+ *data++ = s->TxMulticastFramesOK;
+ *data++ = s->TxBroadcastFramesOK;
+ *data++ = s->TxPauseFrames;
+ *data++ = s->TxFramesWithDeferredXmissions;
+ *data++ = s->TxLateCollisions;
+ *data++ = s->TxTotalCollisions;
+ *data++ = s->TxFramesAbortedDueToXSCollisions;
+ *data++ = s->TxUnderrun;
+ *data++ = s->TxLengthErrors;
+ *data++ = s->TxInternalMACXmitError;
+ *data++ = s->TxFramesWithExcessiveDeferral;
+ *data++ = s->TxFCSErrors;
+
+ *data++ = s->RxOctetsOK;
+ *data++ = s->RxOctetsBad;
+ *data++ = s->RxUnicastFramesOK;
+ *data++ = s->RxMulticastFramesOK;
+ *data++ = s->RxBroadcastFramesOK;
+ *data++ = s->RxPauseFrames;
+ *data++ = s->RxFCSErrors;
+ *data++ = s->RxAlignErrors;
+ *data++ = s->RxSymbolErrors;
+ *data++ = s->RxDataErrors;
+ *data++ = s->RxSequenceErrors;
+ *data++ = s->RxRuntErrors;
+ *data++ = s->RxJabberErrors;
+ *data++ = s->RxInternalMACRcvError;
+ *data++ = s->RxInRangeLengthErrors;
+ *data++ = s->RxOutOfRangeLengthField;
+ *data++ = s->RxFrameTooLongErrors;
+
+ t1_sge_get_port_stats(adapter->sge, dev->if_port, &ss);
+ *data++ = ss.rx_packets;
+ *data++ = ss.rx_cso_good;
+ *data++ = ss.tx_packets;
+ *data++ = ss.tx_cso;
+ *data++ = ss.tx_tso;
+ *data++ = ss.vlan_xtract;
+ *data++ = ss.vlan_insert;
+
+ t = t1_sge_get_intr_counts(adapter->sge);
+ *data++ = t->rx_drops;
+ *data++ = t->pure_rsps;
+ *data++ = t->unhandled_irqs;
+ *data++ = t->respQ_empty;
+ *data++ = t->respQ_overflow;
+ *data++ = t->freelistQ_empty;
+ *data++ = t->pkt_too_big;
+ *data++ = t->pkt_mismatch;
+ *data++ = t->cmdQ_full[0];
+ *data++ = t->cmdQ_full[1];
+
+ if (adapter->espi) {
+ const struct espi_intr_counts *e;
+
+ e = t1_espi_get_intr_counts(adapter->espi);
+ *data++ = e->DIP2_parity_err;
+ *data++ = e->DIP4_err;
+ *data++ = e->rx_drops;
+ *data++ = e->tx_drops;
+ *data++ = e->rx_ovflw;
+ *data++ = e->parity_err;
+ }
}
static inline void reg_block_dump(struct adapter *ap, void *buf,
@@ -521,6 +547,15 @@ static void get_regs(struct net_device *dev, struct ethtool_regs *regs,
memset(buf, 0, T2_REGMAP_SIZE);
reg_block_dump(ap, buf, 0, A_SG_RESPACCUTIMER);
+ reg_block_dump(ap, buf, A_MC3_CFG, A_MC4_INT_CAUSE);
+ reg_block_dump(ap, buf, A_TPI_ADDR, A_TPI_PAR);
+ reg_block_dump(ap, buf, A_TP_IN_CONFIG, A_TP_TX_DROP_COUNT);
+ reg_block_dump(ap, buf, A_RAT_ROUTE_CONTROL, A_RAT_INTR_CAUSE);
+ reg_block_dump(ap, buf, A_CSPI_RX_AE_WM, A_CSPI_INTR_ENABLE);
+ reg_block_dump(ap, buf, A_ESPI_SCH_TOKEN0, A_ESPI_GOSTAT);
+ reg_block_dump(ap, buf, A_ULP_ULIMIT, A_ULP_PIO_CTRL);
+ reg_block_dump(ap, buf, A_PL_ENABLE, A_PL_CAUSE);
+ reg_block_dump(ap, buf, A_MC5_CONFIG, A_MC5_MASK_WRITE_CMD);
}
static int get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
@@ -539,12 +574,12 @@ static int get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
cmd->duplex = -1;
}
- cmd->port = (cmd->supported & SUPPORTED_TP) ? PORT_TP : PORT_FIBRE;
- cmd->phy_address = p->phy->addr;
- cmd->transceiver = XCVR_EXTERNAL;
- cmd->autoneg = p->link_config.autoneg;
- cmd->maxtxpkt = 0;
- cmd->maxrxpkt = 0;
+ cmd->port = (cmd->supported & SUPPORTED_TP) ? PORT_TP : PORT_FIBRE;
+ cmd->phy_address = p->phy->addr;
+ cmd->transceiver = XCVR_EXTERNAL;
+ cmd->autoneg = p->link_config.autoneg;
+ cmd->maxtxpkt = 0;
+ cmd->maxrxpkt = 0;
return 0;
}
@@ -715,7 +750,7 @@ static int set_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
return -EINVAL;
if (adapter->flags & FULL_INIT_DONE)
- return -EBUSY;
+ return -EBUSY;
adapter->params.sge.freelQ_size[!jumbo_fl] = e->rx_pending;
adapter->params.sge.freelQ_size[jumbo_fl] = e->rx_jumbo_pending;
@@ -759,7 +794,9 @@ static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
static int get_eeprom_len(struct net_device *dev)
{
- return EEPROM_SIZE;
+ struct adapter *adapter = dev->priv;
+
+ return t1_is_asic(adapter) ? EEPROM_SIZE : 0;
}
#define EEPROM_MAGIC(ap) \
@@ -809,47 +846,36 @@ static const struct ethtool_ops t1_ethtool_ops = {
.set_tso = set_tso,
};
-static void cxgb_proc_cleanup(struct adapter *adapter,
- struct proc_dir_entry *dir)
-{
- const char *name;
- name = adapter->name;
- remove_proc_entry(name, dir);
-}
-//#define chtoe_setup_toedev(adapter) NULL
-#define update_mtu_tab(adapter)
-#define write_smt_entry(adapter, idx)
-
static int t1_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
{
- struct adapter *adapter = dev->priv;
- struct mii_ioctl_data *data = if_mii(req);
+ struct adapter *adapter = dev->priv;
+ struct mii_ioctl_data *data = if_mii(req);
switch (cmd) {
- case SIOCGMIIPHY:
- data->phy_id = adapter->port[dev->if_port].phy->addr;
- /* FALLTHRU */
- case SIOCGMIIREG: {
+ case SIOCGMIIPHY:
+ data->phy_id = adapter->port[dev->if_port].phy->addr;
+ /* FALLTHRU */
+ case SIOCGMIIREG: {
struct cphy *phy = adapter->port[dev->if_port].phy;
u32 val;
if (!phy->mdio_read)
- return -EOPNOTSUPP;
+ return -EOPNOTSUPP;
phy->mdio_read(adapter, data->phy_id, 0, data->reg_num & 0x1f,
&val);
- data->val_out = val;
- break;
+ data->val_out = val;
+ break;
}
- case SIOCSMIIREG: {
+ case SIOCSMIIREG: {
struct cphy *phy = adapter->port[dev->if_port].phy;
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
if (!phy->mdio_write)
- return -EOPNOTSUPP;
+ return -EOPNOTSUPP;
phy->mdio_write(adapter, data->phy_id, 0, data->reg_num & 0x1f,
data->val_in);
- break;
+ break;
}
default:
@@ -865,9 +891,9 @@ static int t1_change_mtu(struct net_device *dev, int new_mtu)
struct cmac *mac = adapter->port[dev->if_port].mac;
if (!mac->ops->set_mtu)
- return -EOPNOTSUPP;
+ return -EOPNOTSUPP;
if (new_mtu < 68)
- return -EINVAL;
+ return -EINVAL;
if ((ret = mac->ops->set_mtu(mac, new_mtu)))
return ret;
dev->mtu = new_mtu;
@@ -918,7 +944,7 @@ static void t1_netpoll(struct net_device *dev)
struct adapter *adapter = dev->priv;
local_irq_save(flags);
- t1_select_intr_handler(adapter)(adapter->pdev->irq, adapter);
+ t1_select_intr_handler(adapter)(adapter->pdev->irq, adapter);
local_irq_restore(flags);
}
#endif
@@ -957,14 +983,14 @@ static void ext_intr_task(struct work_struct *work)
struct adapter *adapter =
container_of(work, struct adapter, ext_intr_handler_task);
- elmer0_ext_intr_handler(adapter);
+ t1_elmer0_ext_intr_handler(adapter);
/* Now reenable external interrupts */
spin_lock_irq(&adapter->async_lock);
adapter->slow_intr_mask |= F_PL_INTR_EXT;
writel(F_PL_INTR_EXT, adapter->regs + A_PL_CAUSE);
writel(adapter->slow_intr_mask | F_PL_INTR_SGE_DATA,
- adapter->regs + A_PL_ENABLE);
+ adapter->regs + A_PL_ENABLE);
spin_unlock_irq(&adapter->async_lock);
}
@@ -980,7 +1006,7 @@ void t1_elmer0_ext_intr(struct adapter *adapter)
*/
adapter->slow_intr_mask &= ~F_PL_INTR_EXT;
writel(adapter->slow_intr_mask | F_PL_INTR_SGE_DATA,
- adapter->regs + A_PL_ENABLE);
+ adapter->regs + A_PL_ENABLE);
schedule_work(&adapter->ext_intr_handler_task);
}
@@ -1013,7 +1039,7 @@ static int __devinit init_one(struct pci_dev *pdev,
err = pci_enable_device(pdev);
if (err)
- return err;
+ return err;
if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
CH_ERR("%s: cannot find PCI device memory base address\n",
@@ -1045,7 +1071,7 @@ static int __devinit init_one(struct pci_dev *pdev,
pci_set_master(pdev);
- mmio_start = pci_resource_start(pdev, 0);
+ mmio_start = pci_resource_start(pdev, 0);
mmio_len = pci_resource_len(pdev, 0);
bi = t1_get_board_info(ent->driver_data);
@@ -1083,21 +1109,15 @@ static int __devinit init_one(struct pci_dev *pdev,
adapter->msg_enable = dflt_msg_enable;
adapter->mmio_len = mmio_len;
- init_MUTEX(&adapter->mib_mutex);
spin_lock_init(&adapter->tpi_lock);
spin_lock_init(&adapter->work_lock);
spin_lock_init(&adapter->async_lock);
+ spin_lock_init(&adapter->mac_lock);
INIT_WORK(&adapter->ext_intr_handler_task,
ext_intr_task);
INIT_DELAYED_WORK(&adapter->stats_update_task,
mac_stats_task);
-#ifdef work_struct
- init_timer(&adapter->stats_update_timer);
- adapter->stats_update_timer.function = mac_stats_timer;
- adapter->stats_update_timer.data =
- (unsigned long)adapter;
-#endif
pci_set_drvdata(pdev, netdev);
}
@@ -1124,16 +1144,19 @@ static int __devinit init_one(struct pci_dev *pdev,
netdev->vlan_rx_register = vlan_rx_register;
netdev->vlan_rx_kill_vid = vlan_rx_kill_vid;
#endif
- adapter->flags |= TSO_CAPABLE;
- netdev->features |= NETIF_F_TSO;
+
+ /* T204: disable TSO */
+ if (!(is_T2(adapter)) || bi->port_number != 4) {
+ adapter->flags |= TSO_CAPABLE;
+ netdev->features |= NETIF_F_TSO;
+ }
}
netdev->open = cxgb_open;
netdev->stop = cxgb_close;
netdev->hard_start_xmit = t1_start_xmit;
netdev->hard_header_len += (adapter->flags & TSO_CAPABLE) ?
- sizeof(struct cpl_tx_pkt_lso) :
- sizeof(struct cpl_tx_pkt);
+ sizeof(struct cpl_tx_pkt_lso) : sizeof(struct cpl_tx_pkt);
netdev->get_stats = t1_get_stats;
netdev->set_multicast_list = t1_set_rxmode;
netdev->do_ioctl = t1_ioctl;
@@ -1144,7 +1167,7 @@ static int __devinit init_one(struct pci_dev *pdev,
#endif
netdev->weight = 64;
- SET_ETHTOOL_OPS(netdev, &t1_ethtool_ops);
+ SET_ETHTOOL_OPS(netdev, &t1_ethtool_ops);
}
if (t1_init_sw_modules(adapter, bi) < 0) {
@@ -1171,7 +1194,7 @@ static int __devinit init_one(struct pci_dev *pdev,
if (!adapter->registered_device_map)
adapter->name = adapter->port[i].dev->name;
- __set_bit(i, &adapter->registered_device_map);
+ __set_bit(i, &adapter->registered_device_map);
}
}
if (!adapter->registered_device_map) {
@@ -1184,18 +1207,28 @@ static int __devinit init_one(struct pci_dev *pdev,
bi->desc, adapter->params.chip_revision,
adapter->params.pci.is_pcix ? "PCIX" : "PCI",
adapter->params.pci.speed, adapter->params.pci.width);
+
+ /*
+ * Set the T1B ASIC and memory clocks.
+ */
+ if (t1powersave)
+ adapter->t1powersave = LCLOCK; /* HW default is powersave mode. */
+ else
+ adapter->t1powersave = HCLOCK;
+ if (t1_is_T1B(adapter))
+ t1_clock(adapter, t1powersave);
+
return 0;
out_release_adapter_res:
t1_free_sw_modules(adapter);
out_free_dev:
if (adapter) {
- if (adapter->regs) iounmap(adapter->regs);
+ if (adapter->regs)
+ iounmap(adapter->regs);
for (i = bi->port_number - 1; i >= 0; --i)
- if (adapter->port[i].dev) {
- cxgb_proc_cleanup(adapter, proc_root_driver);
- kfree(adapter->port[i].dev);
- }
+ if (adapter->port[i].dev)
+ free_netdev(adapter->port[i].dev);
}
pci_release_regions(pdev);
out_disable_pdev:
@@ -1204,6 +1237,155 @@ static int __devinit init_one(struct pci_dev *pdev,
return err;
}
+static void bit_bang(struct adapter *adapter, int bitdata, int nbits)
+{
+ int data;
+ int i;
+ u32 val;
+
+ enum {
+ S_CLOCK = 1 << 3,
+ S_DATA = 1 << 4
+ };
+
+ for (i = (nbits - 1); i > -1; i--) {
+
+ udelay(50);
+
+ data = ((bitdata >> i) & 0x1);
+ __t1_tpi_read(adapter, A_ELMER0_GPO, &val);
+
+ if (data)
+ val |= S_DATA;
+ else
+ val &= ~S_DATA;
+
+ udelay(50);
+
+ /* Set SCLOCK low */
+ val &= ~S_CLOCK;
+ __t1_tpi_write(adapter, A_ELMER0_GPO, val);
+
+ udelay(50);
+
+ /* Write SCLOCK high */
+ val |= S_CLOCK;
+ __t1_tpi_write(adapter, A_ELMER0_GPO, val);
+
+ }
+}
+
+static int t1_clock(struct adapter *adapter, int mode)
+{
+ u32 val;
+ int M_CORE_VAL;
+ int M_MEM_VAL;
+
+ enum {
+ M_CORE_BITS = 9,
+ T_CORE_VAL = 0,
+ T_CORE_BITS = 2,
+ N_CORE_VAL = 0,
+ N_CORE_BITS = 2,
+ M_MEM_BITS = 9,
+ T_MEM_VAL = 0,
+ T_MEM_BITS = 2,
+ N_MEM_VAL = 0,
+ N_MEM_BITS = 2,
+ NP_LOAD = 1 << 17,
+ S_LOAD_MEM = 1 << 5,
+ S_LOAD_CORE = 1 << 6,
+ S_CLOCK = 1 << 3
+ };
+
+ if (!t1_is_T1B(adapter))
+ return -ENODEV; /* Can't re-clock this chip. */
+
+ if (mode & 2) {
+ return 0; /* show current mode. */
+ }
+
+ if ((adapter->t1powersave & 1) == (mode & 1))
+ return -EALREADY; /* ASIC already running in mode. */
+
+ if ((mode & 1) == HCLOCK) {
+ M_CORE_VAL = 0x14;
+ M_MEM_VAL = 0x18;
+ adapter->t1powersave = HCLOCK; /* overclock */
+ } else {
+ M_CORE_VAL = 0xe;
+ M_MEM_VAL = 0x10;
+ adapter->t1powersave = LCLOCK; /* underclock */
+ }
+
+ /* Don't interrupt this serial stream! */
+ spin_lock(&adapter->tpi_lock);
+
+ /* Initialize for ASIC core */
+ __t1_tpi_read(adapter, A_ELMER0_GPO, &val);
+ val |= NP_LOAD;
+ udelay(50);
+ __t1_tpi_write(adapter, A_ELMER0_GPO, val);
+ udelay(50);
+ __t1_tpi_read(adapter, A_ELMER0_GPO, &val);
+ val &= ~S_LOAD_CORE;
+ val &= ~S_CLOCK;
+ __t1_tpi_write(adapter, A_ELMER0_GPO, val);
+ udelay(50);
+
+ /* Serial program the ASIC clock synthesizer */
+ bit_bang(adapter, T_CORE_VAL, T_CORE_BITS);
+ bit_bang(adapter, N_CORE_VAL, N_CORE_BITS);
+ bit_bang(adapter, M_CORE_VAL, M_CORE_BITS);
+ udelay(50);
+
+ /* Finish ASIC core */
+ __t1_tpi_read(adapter, A_ELMER0_GPO, &val);
+ val |= S_LOAD_CORE;
+ udelay(50);
+ __t1_tpi_write(adapter, A_ELMER0_GPO, val);
+ udelay(50);
+ __t1_tpi_read(adapter, A_ELMER0_GPO, &val);
+ val &= ~S_LOAD_CORE;
+ udelay(50);
+ __t1_tpi_write(adapter, A_ELMER0_GPO, val);
+ udelay(50);
+
+ /* Initialize for memory */
+ __t1_tpi_read(adapter, A_ELMER0_GPO, &val);
+ val |= NP_LOAD;
+ udelay(50);
+ __t1_tpi_write(adapter, A_ELMER0_GPO, val);
+ udelay(50);
+ __t1_tpi_read(adapter, A_ELMER0_GPO, &val);
+ val &= ~S_LOAD_MEM;
+ val &= ~S_CLOCK;
+ udelay(50);
+ __t1_tpi_write(adapter, A_ELMER0_GPO, val);
+ udelay(50);
+
+ /* Serial program the memory clock synthesizer */
+ bit_bang(adapter, T_MEM_VAL, T_MEM_BITS);
+ bit_bang(adapter, N_MEM_VAL, N_MEM_BITS);
+ bit_bang(adapter, M_MEM_VAL, M_MEM_BITS);
+ udelay(50);
+
+ /* Finish memory */
+ __t1_tpi_read(adapter, A_ELMER0_GPO, &val);
+ val |= S_LOAD_MEM;
+ udelay(50);
+ __t1_tpi_write(adapter, A_ELMER0_GPO, val);
+ udelay(50);
+ __t1_tpi_read(adapter, A_ELMER0_GPO, &val);
+ val &= ~S_LOAD_MEM;
+ udelay(50);
+ __t1_tpi_write(adapter, A_ELMER0_GPO, val);
+
+ spin_unlock(&adapter->tpi_lock);
+
+ return 0;
+}
+
static inline void t1_sw_reset(struct pci_dev *pdev)
{
pci_write_config_dword(pdev, A_PCICFG_PM_CSR, 3);
@@ -1225,10 +1407,9 @@ static void __devexit remove_one(struct pci_dev *pdev)
t1_free_sw_modules(adapter);
iounmap(adapter->regs);
while (--i >= 0)
- if (adapter->port[i].dev) {
- cxgb_proc_cleanup(adapter, proc_root_driver);
- kfree(adapter->port[i].dev);
- }
+ if (adapter->port[i].dev)
+ free_netdev(adapter->port[i].dev);
+
pci_release_regions(pdev);
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
diff --git a/drivers/net/chelsio/elmer0.h b/drivers/net/chelsio/elmer0.h
index 5590cb2dac19..9ebecaa97d31 100644
--- a/drivers/net/chelsio/elmer0.h
+++ b/drivers/net/chelsio/elmer0.h
@@ -39,6 +39,12 @@
#ifndef _CXGB_ELMER0_H_
#define _CXGB_ELMER0_H_
+/* ELMER0 flavors */
+enum {
+ ELMER0_XC2S300E_6FT256_C,
+ ELMER0_XC2S100E_6TQ144_C
+};
+
/* ELMER0 registers */
#define A_ELMER0_VERSION 0x100000
#define A_ELMER0_PHY_CFG 0x100004
@@ -149,3 +155,4 @@
#define MI1_OP_INDIRECT_READ 3
#endif /* _CXGB_ELMER0_H_ */
+
diff --git a/drivers/net/chelsio/espi.c b/drivers/net/chelsio/espi.c
index 542e5e065c6f..4192f0f5b3ee 100644
--- a/drivers/net/chelsio/espi.c
+++ b/drivers/net/chelsio/espi.c
@@ -81,46 +81,36 @@ static int tricn_write(adapter_t *adapter, int bundle_addr, int module_addr,
return busy;
}
-/* 1. Deassert rx_reset_core. */
-/* 2. Program TRICN_CNFG registers. */
-/* 3. Deassert rx_reset_link */
static int tricn_init(adapter_t *adapter)
{
- int i = 0;
- int stat = 0;
- int timeout = 0;
- int is_ready = 0;
+ int i, sme = 1;
- /* 1 */
- timeout=1000;
- do {
- stat = readl(adapter->regs + A_ESPI_RX_RESET);
- is_ready = (stat & 0x4);
- timeout--;
- udelay(5);
- } while (!is_ready || (timeout==0));
- writel(0x2, adapter->regs + A_ESPI_RX_RESET);
- if (timeout==0)
- {
- CH_ERR("ESPI : ERROR : Timeout tricn_init() \n");
- t1_fatal_err(adapter);
+ if (!(readl(adapter->regs + A_ESPI_RX_RESET) & F_RX_CLK_STATUS)) {
+ CH_ERR("%s: ESPI clock not ready\n", adapter->name);
+ return -1;
}
- /* 2 */
- tricn_write(adapter, 0, 0, 0, TRICN_CNFG, 0x81);
- tricn_write(adapter, 0, 1, 0, TRICN_CNFG, 0x81);
- tricn_write(adapter, 0, 2, 0, TRICN_CNFG, 0x81);
- for (i=1; i<= 8; i++) tricn_write(adapter, 0, 0, i, TRICN_CNFG, 0xf1);
- for (i=1; i<= 2; i++) tricn_write(adapter, 0, 1, i, TRICN_CNFG, 0xf1);
- for (i=1; i<= 3; i++) tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0xe1);
- for (i=4; i<= 4; i++) tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0xf1);
- for (i=5; i<= 5; i++) tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0xe1);
- for (i=6; i<= 6; i++) tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0xf1);
- for (i=7; i<= 7; i++) tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0x80);
- for (i=8; i<= 8; i++) tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0xf1);
-
- /* 3 */
- writel(0x3, adapter->regs + A_ESPI_RX_RESET);
+ writel(F_ESPI_RX_CORE_RST, adapter->regs + A_ESPI_RX_RESET);
+
+ if (sme) {
+ tricn_write(adapter, 0, 0, 0, TRICN_CNFG, 0x81);
+ tricn_write(adapter, 0, 1, 0, TRICN_CNFG, 0x81);
+ tricn_write(adapter, 0, 2, 0, TRICN_CNFG, 0x81);
+ }
+ for (i = 1; i <= 8; i++)
+ tricn_write(adapter, 0, 0, i, TRICN_CNFG, 0xf1);
+ for (i = 1; i <= 2; i++)
+ tricn_write(adapter, 0, 1, i, TRICN_CNFG, 0xf1);
+ for (i = 1; i <= 3; i++)
+ tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0xe1);
+ tricn_write(adapter, 0, 2, 4, TRICN_CNFG, 0xf1);
+ tricn_write(adapter, 0, 2, 5, TRICN_CNFG, 0xe1);
+ tricn_write(adapter, 0, 2, 6, TRICN_CNFG, 0xf1);
+ tricn_write(adapter, 0, 2, 7, TRICN_CNFG, 0x80);
+ tricn_write(adapter, 0, 2, 8, TRICN_CNFG, 0xf1);
+
+ writel(F_ESPI_RX_CORE_RST | F_ESPI_RX_LNK_RST,
+ adapter->regs + A_ESPI_RX_RESET);
return 0;
}
@@ -143,6 +133,7 @@ void t1_espi_intr_enable(struct peespi *espi)
void t1_espi_intr_clear(struct peespi *espi)
{
+ readl(espi->adapter->regs + A_ESPI_DIP2_ERR_COUNT);
writel(0xffffffff, espi->adapter->regs + A_ESPI_INTR_STATUS);
writel(F_PL_INTR_ESPI, espi->adapter->regs + A_PL_CAUSE);
}
@@ -157,7 +148,6 @@ void t1_espi_intr_disable(struct peespi *espi)
int t1_espi_intr_handler(struct peespi *espi)
{
- u32 cnt;
u32 status = readl(espi->adapter->regs + A_ESPI_INTR_STATUS);
if (status & F_DIP4ERR)
@@ -177,7 +167,7 @@ int t1_espi_intr_handler(struct peespi *espi)
* Must read the error count to clear the interrupt
* that it causes.
*/
- cnt = readl(espi->adapter->regs + A_ESPI_DIP2_ERR_COUNT);
+ readl(espi->adapter->regs + A_ESPI_DIP2_ERR_COUNT);
}
/*
@@ -192,7 +182,7 @@ int t1_espi_intr_handler(struct peespi *espi)
const struct espi_intr_counts *t1_espi_get_intr_counts(struct peespi *espi)
{
- return &espi->intr_cnt;
+ return &espi->intr_cnt;
}
static void espi_setup_for_pm3393(adapter_t *adapter)
@@ -210,17 +200,45 @@ static void espi_setup_for_pm3393(adapter_t *adapter)
writel(V_RX_NPORTS(1) | V_TX_NPORTS(1), adapter->regs + A_PORT_CONFIG);
}
-/* T2 Init part -- */
-/* 1. Set T_ESPI_MISCCTRL_ADDR */
-/* 2. Init ESPI registers. */
-/* 3. Init TriCN Hard Macro */
-int t1_espi_init(struct peespi *espi, int mac_type, int nports)
+static void espi_setup_for_vsc7321(adapter_t *adapter)
+{
+ writel(0x1f4, adapter->regs + A_ESPI_SCH_TOKEN0);
+ writel(0x1f401f4, adapter->regs + A_ESPI_SCH_TOKEN1);
+ writel(0x1f4, adapter->regs + A_ESPI_SCH_TOKEN2);
+ writel(0xa00, adapter->regs + A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK);
+ writel(0x1ff, adapter->regs + A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK);
+ writel(1, adapter->regs + A_ESPI_CALENDAR_LENGTH);
+ writel(V_RX_NPORTS(4) | V_TX_NPORTS(4), adapter->regs + A_PORT_CONFIG);
+
+ writel(0x08000008, adapter->regs + A_ESPI_TRAIN);
+}
+
+/*
+ * Note that T1B requires at least 2 ports for IXF1010 due to a HW bug.
+ */
+static void espi_setup_for_ixf1010(adapter_t *adapter, int nports)
{
- u32 cnt;
+ writel(1, adapter->regs + A_ESPI_CALENDAR_LENGTH);
+ if (nports == 4) {
+ if (is_T2(adapter)) {
+ writel(0xf00, adapter->regs + A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK);
+ writel(0x3c0, adapter->regs + A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK);
+ } else {
+ writel(0x7ff, adapter->regs + A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK);
+ writel(0x1ff, adapter->regs + A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK);
+ }
+ } else {
+ writel(0x1fff, adapter->regs + A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK);
+ writel(0x7ff, adapter->regs + A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK);
+ }
+ writel(V_RX_NPORTS(nports) | V_TX_NPORTS(nports), adapter->regs + A_PORT_CONFIG);
+}
+
+int t1_espi_init(struct peespi *espi, int mac_type, int nports)
+{
u32 status_enable_extra = 0;
adapter_t *adapter = espi->adapter;
- u32 status, burstval = 0x800100;
/* Disable ESPI training. MACs that can handle it enable it below. */
writel(0, adapter->regs + A_ESPI_TRAIN);
@@ -229,38 +247,20 @@ int t1_espi_init(struct peespi *espi, int mac_type, int nports)
writel(V_OUT_OF_SYNC_COUNT(4) |
V_DIP2_PARITY_ERR_THRES(3) |
V_DIP4_THRES(1), adapter->regs + A_ESPI_MISC_CONTROL);
- if (nports == 4) {
- /* T204: maxburst1 = 0x40, maxburst2 = 0x20 */
- burstval = 0x200040;
- }
- }
- writel(burstval, adapter->regs + A_ESPI_MAXBURST1_MAXBURST2);
+ writel(nports == 4 ? 0x200040 : 0x1000080,
+ adapter->regs + A_ESPI_MAXBURST1_MAXBURST2);
+ } else
+ writel(0x800100, adapter->regs + A_ESPI_MAXBURST1_MAXBURST2);
- switch (mac_type) {
- case CHBT_MAC_PM3393:
+ if (mac_type == CHBT_MAC_PM3393)
espi_setup_for_pm3393(adapter);
- break;
- default:
+ else if (mac_type == CHBT_MAC_VSC7321)
+ espi_setup_for_vsc7321(adapter);
+ else if (mac_type == CHBT_MAC_IXF1010) {
+ status_enable_extra = F_INTEL1010MODE;
+ espi_setup_for_ixf1010(adapter, nports);
+ } else
return -1;
- }
-
- /*
- * Make sure any pending interrupts from the SPI are
- * Cleared before enabling the interrupt.
- */
- writel(ESPI_INTR_MASK, espi->adapter->regs + A_ESPI_INTR_ENABLE);
- status = readl(espi->adapter->regs + A_ESPI_INTR_STATUS);
- if (status & F_DIP2PARITYERR) {
- cnt = readl(espi->adapter->regs + A_ESPI_DIP2_ERR_COUNT);
- }
-
- /*
- * For T1B we need to write 1 to clear ESPI interrupts. For T2+ we
- * write the status as is.
- */
- if (status && t1_is_T1B(espi->adapter))
- status = 1;
- writel(status, espi->adapter->regs + A_ESPI_INTR_STATUS);
writel(status_enable_extra | F_RXSTATUSENABLE,
adapter->regs + A_ESPI_FIFO_STATUS_ENABLE);
@@ -271,9 +271,11 @@ int t1_espi_init(struct peespi *espi, int mac_type, int nports)
* Always position the control at the 1st port egress IN
* (sop,eop) counter to reduce PIOs for T/N210 workaround.
*/
- espi->misc_ctrl = (readl(adapter->regs + A_ESPI_MISC_CONTROL)
- & ~MON_MASK) | (F_MONITORED_DIRECTION
- | F_MONITORED_INTERFACE);
+ espi->misc_ctrl = readl(adapter->regs + A_ESPI_MISC_CONTROL);
+ espi->misc_ctrl &= ~MON_MASK;
+ espi->misc_ctrl |= F_MONITORED_DIRECTION;
+ if (adapter->params.nports == 1)
+ espi->misc_ctrl |= F_MONITORED_INTERFACE;
writel(espi->misc_ctrl, adapter->regs + A_ESPI_MISC_CONTROL);
spin_lock_init(&espi->lock);
}
@@ -299,8 +301,7 @@ void t1_espi_set_misc_ctrl(adapter_t *adapter, u32 val)
{
struct peespi *espi = adapter->espi;
- if (!is_T2(adapter))
- return;
+ if (!is_T2(adapter)) return;
spin_lock(&espi->lock);
espi->misc_ctrl = (val & ~MON_MASK) |
(espi->misc_ctrl & MON_MASK);
@@ -310,27 +311,61 @@ void t1_espi_set_misc_ctrl(adapter_t *adapter, u32 val)
u32 t1_espi_get_mon(adapter_t *adapter, u32 addr, u8 wait)
{
- u32 sel;
-
struct peespi *espi = adapter->espi;
+ u32 sel;
if (!is_T2(adapter))
return 0;
+
sel = V_MONITORED_PORT_NUM((addr & 0x3c) >> 2);
if (!wait) {
if (!spin_trylock(&espi->lock))
return 0;
- }
- else
+ } else
spin_lock(&espi->lock);
+
if ((sel != (espi->misc_ctrl & MON_MASK))) {
writel(((espi->misc_ctrl & ~MON_MASK) | sel),
adapter->regs + A_ESPI_MISC_CONTROL);
sel = readl(adapter->regs + A_ESPI_SCH_TOKEN3);
writel(espi->misc_ctrl, adapter->regs + A_ESPI_MISC_CONTROL);
- }
- else
+ } else
sel = readl(adapter->regs + A_ESPI_SCH_TOKEN3);
spin_unlock(&espi->lock);
return sel;
}
+
+/*
+ * This function is for T204 only.
+ * compare with t1_espi_get_mon(), it reads espiInTxSop[0 ~ 3] in
+ * one shot, since there is no per port counter on the out side.
+ */
+int
+t1_espi_get_mon_t204(adapter_t *adapter, u32 *valp, u8 wait)
+{
+ struct peespi *espi = adapter->espi;
+ u8 i, nport = (u8)adapter->params.nports;
+
+ if (!wait) {
+ if (!spin_trylock(&espi->lock))
+ return -1;
+ } else
+ spin_lock(&espi->lock);
+
+ if ( (espi->misc_ctrl & MON_MASK) != F_MONITORED_DIRECTION ) {
+ espi->misc_ctrl = (espi->misc_ctrl & ~MON_MASK) |
+ F_MONITORED_DIRECTION;
+ writel(espi->misc_ctrl, adapter->regs + A_ESPI_MISC_CONTROL);
+ }
+ for (i = 0 ; i < nport; i++, valp++) {
+ if (i) {
+ writel(espi->misc_ctrl | V_MONITORED_PORT_NUM(i),
+ adapter->regs + A_ESPI_MISC_CONTROL);
+ }
+ *valp = readl(adapter->regs + A_ESPI_SCH_TOKEN3);
+ }
+
+ writel(espi->misc_ctrl, adapter->regs + A_ESPI_MISC_CONTROL);
+ spin_unlock(&espi->lock);
+ return 0;
+}
diff --git a/drivers/net/chelsio/espi.h b/drivers/net/chelsio/espi.h
index c90e37f8457c..84f2c98bc4cc 100644
--- a/drivers/net/chelsio/espi.h
+++ b/drivers/net/chelsio/espi.h
@@ -64,5 +64,6 @@ const struct espi_intr_counts *t1_espi_get_intr_counts(struct peespi *espi);
void t1_espi_set_misc_ctrl(adapter_t *adapter, u32 val);
u32 t1_espi_get_mon(adapter_t *adapter, u32 addr, u8 wait);
+int t1_espi_get_mon_t204(adapter_t *, u32 *, u8);
#endif /* _CXGB_ESPI_H_ */
diff --git a/drivers/net/chelsio/fpga_defs.h b/drivers/net/chelsio/fpga_defs.h
new file mode 100644
index 000000000000..17a3c2ba36a3
--- /dev/null
+++ b/drivers/net/chelsio/fpga_defs.h
@@ -0,0 +1,232 @@
+/* $Date: 2005/03/07 23:59:05 $ $RCSfile: fpga_defs.h,v $ $Revision: 1.4 $ */
+
+/*
+ * FPGA specific definitions
+ */
+
+#ifndef __CHELSIO_FPGA_DEFS_H__
+#define __CHELSIO_FPGA_DEFS_H__
+
+#define FPGA_PCIX_ADDR_VERSION 0xA08
+#define FPGA_PCIX_ADDR_STAT 0xA0C
+
+/* FPGA master interrupt Cause/Enable bits */
+#define FPGA_PCIX_INTERRUPT_SGE_ERROR 0x1
+#define FPGA_PCIX_INTERRUPT_SGE_DATA 0x2
+#define FPGA_PCIX_INTERRUPT_TP 0x4
+#define FPGA_PCIX_INTERRUPT_MC3 0x8
+#define FPGA_PCIX_INTERRUPT_GMAC 0x10
+#define FPGA_PCIX_INTERRUPT_PCIX 0x20
+
+/* TP interrupt register addresses */
+#define FPGA_TP_ADDR_INTERRUPT_ENABLE 0xA10
+#define FPGA_TP_ADDR_INTERRUPT_CAUSE 0xA14
+#define FPGA_TP_ADDR_VERSION 0xA18
+
+/* TP interrupt Cause/Enable bits */
+#define FPGA_TP_INTERRUPT_MC4 0x1
+#define FPGA_TP_INTERRUPT_MC5 0x2
+
+/*
+ * PM interrupt register addresses
+ */
+#define FPGA_MC3_REG_INTRENABLE 0xA20
+#define FPGA_MC3_REG_INTRCAUSE 0xA24
+#define FPGA_MC3_REG_VERSION 0xA28
+
+/*
+ * GMAC interrupt register addresses
+ */
+#define FPGA_GMAC_ADDR_INTERRUPT_ENABLE 0xA30
+#define FPGA_GMAC_ADDR_INTERRUPT_CAUSE 0xA34
+#define FPGA_GMAC_ADDR_VERSION 0xA38
+
+/* GMAC Cause/Enable bits */
+#define FPGA_GMAC_INTERRUPT_PORT0 0x1
+#define FPGA_GMAC_INTERRUPT_PORT1 0x2
+#define FPGA_GMAC_INTERRUPT_PORT2 0x4
+#define FPGA_GMAC_INTERRUPT_PORT3 0x8
+
+/* MI0 registers */
+#define A_MI0_CLK 0xb00
+
+#define S_MI0_CLK_DIV 0
+#define M_MI0_CLK_DIV 0xff
+#define V_MI0_CLK_DIV(x) ((x) << S_MI0_CLK_DIV)
+#define G_MI0_CLK_DIV(x) (((x) >> S_MI0_CLK_DIV) & M_MI0_CLK_DIV)
+
+#define S_MI0_CLK_CNT 8
+#define M_MI0_CLK_CNT 0xff
+#define V_MI0_CLK_CNT(x) ((x) << S_MI0_CLK_CNT)
+#define G_MI0_CLK_CNT(x) (((x) >> S_MI0_CLK_CNT) & M_MI0_CLK_CNT)
+
+#define A_MI0_CSR 0xb04
+
+#define S_MI0_CSR_POLL 0
+#define V_MI0_CSR_POLL(x) ((x) << S_MI0_CSR_POLL)
+#define F_MI0_CSR_POLL V_MI0_CSR_POLL(1U)
+
+#define S_MI0_PREAMBLE 1
+#define V_MI0_PREAMBLE(x) ((x) << S_MI0_PREAMBLE)
+#define F_MI0_PREAMBLE V_MI0_PREAMBLE(1U)
+
+#define S_MI0_INTR_ENABLE 2
+#define V_MI0_INTR_ENABLE(x) ((x) << S_MI0_INTR_ENABLE)
+#define F_MI0_INTR_ENABLE V_MI0_INTR_ENABLE(1U)
+
+#define S_MI0_BUSY 3
+#define V_MI0_BUSY(x) ((x) << S_MI0_BUSY)
+#define F_MI0_BUSY V_MI0_BUSY(1U)
+
+#define S_MI0_MDIO 4
+#define V_MI0_MDIO(x) ((x) << S_MI0_MDIO)
+#define F_MI0_MDIO V_MI0_MDIO(1U)
+
+#define A_MI0_ADDR 0xb08
+
+#define S_MI0_PHY_REG_ADDR 0
+#define M_MI0_PHY_REG_ADDR 0x1f
+#define V_MI0_PHY_REG_ADDR(x) ((x) << S_MI0_PHY_REG_ADDR)
+#define G_MI0_PHY_REG_ADDR(x) (((x) >> S_MI0_PHY_REG_ADDR) & M_MI0_PHY_REG_ADDR)
+
+#define S_MI0_PHY_ADDR 5
+#define M_MI0_PHY_ADDR 0x1f
+#define V_MI0_PHY_ADDR(x) ((x) << S_MI0_PHY_ADDR)
+#define G_MI0_PHY_ADDR(x) (((x) >> S_MI0_PHY_ADDR) & M_MI0_PHY_ADDR)
+
+#define A_MI0_DATA_EXT 0xb0c
+#define A_MI0_DATA_INT 0xb10
+
+/* GMAC registers */
+#define A_GMAC_MACID_LO 0x28
+#define A_GMAC_MACID_HI 0x2c
+#define A_GMAC_CSR 0x30
+
+#define S_INTERFACE 0
+#define M_INTERFACE 0x3
+#define V_INTERFACE(x) ((x) << S_INTERFACE)
+#define G_INTERFACE(x) (((x) >> S_INTERFACE) & M_INTERFACE)
+
+#define S_MAC_TX_ENABLE 2
+#define V_MAC_TX_ENABLE(x) ((x) << S_MAC_TX_ENABLE)
+#define F_MAC_TX_ENABLE V_MAC_TX_ENABLE(1U)
+
+#define S_MAC_RX_ENABLE 3
+#define V_MAC_RX_ENABLE(x) ((x) << S_MAC_RX_ENABLE)
+#define F_MAC_RX_ENABLE V_MAC_RX_ENABLE(1U)
+
+#define S_MAC_LB_ENABLE 4
+#define V_MAC_LB_ENABLE(x) ((x) << S_MAC_LB_ENABLE)
+#define F_MAC_LB_ENABLE V_MAC_LB_ENABLE(1U)
+
+#define S_MAC_SPEED 5
+#define M_MAC_SPEED 0x3
+#define V_MAC_SPEED(x) ((x) << S_MAC_SPEED)
+#define G_MAC_SPEED(x) (((x) >> S_MAC_SPEED) & M_MAC_SPEED)
+
+#define S_MAC_HD_FC_ENABLE 7
+#define V_MAC_HD_FC_ENABLE(x) ((x) << S_MAC_HD_FC_ENABLE)
+#define F_MAC_HD_FC_ENABLE V_MAC_HD_FC_ENABLE(1U)
+
+#define S_MAC_HALF_DUPLEX 8
+#define V_MAC_HALF_DUPLEX(x) ((x) << S_MAC_HALF_DUPLEX)
+#define F_MAC_HALF_DUPLEX V_MAC_HALF_DUPLEX(1U)
+
+#define S_MAC_PROMISC 9
+#define V_MAC_PROMISC(x) ((x) << S_MAC_PROMISC)
+#define F_MAC_PROMISC V_MAC_PROMISC(1U)
+
+#define S_MAC_MC_ENABLE 10
+#define V_MAC_MC_ENABLE(x) ((x) << S_MAC_MC_ENABLE)
+#define F_MAC_MC_ENABLE V_MAC_MC_ENABLE(1U)
+
+#define S_MAC_RESET 11
+#define V_MAC_RESET(x) ((x) << S_MAC_RESET)
+#define F_MAC_RESET V_MAC_RESET(1U)
+
+#define S_MAC_RX_PAUSE_ENABLE 12
+#define V_MAC_RX_PAUSE_ENABLE(x) ((x) << S_MAC_RX_PAUSE_ENABLE)
+#define F_MAC_RX_PAUSE_ENABLE V_MAC_RX_PAUSE_ENABLE(1U)
+
+#define S_MAC_TX_PAUSE_ENABLE 13
+#define V_MAC_TX_PAUSE_ENABLE(x) ((x) << S_MAC_TX_PAUSE_ENABLE)
+#define F_MAC_TX_PAUSE_ENABLE V_MAC_TX_PAUSE_ENABLE(1U)
+
+#define S_MAC_LWM_ENABLE 14
+#define V_MAC_LWM_ENABLE(x) ((x) << S_MAC_LWM_ENABLE)
+#define F_MAC_LWM_ENABLE V_MAC_LWM_ENABLE(1U)
+
+#define S_MAC_MAGIC_PKT_ENABLE 15
+#define V_MAC_MAGIC_PKT_ENABLE(x) ((x) << S_MAC_MAGIC_PKT_ENABLE)
+#define F_MAC_MAGIC_PKT_ENABLE V_MAC_MAGIC_PKT_ENABLE(1U)
+
+#define S_MAC_ISL_ENABLE 16
+#define V_MAC_ISL_ENABLE(x) ((x) << S_MAC_ISL_ENABLE)
+#define F_MAC_ISL_ENABLE V_MAC_ISL_ENABLE(1U)
+
+#define S_MAC_JUMBO_ENABLE 17
+#define V_MAC_JUMBO_ENABLE(x) ((x) << S_MAC_JUMBO_ENABLE)
+#define F_MAC_JUMBO_ENABLE V_MAC_JUMBO_ENABLE(1U)
+
+#define S_MAC_RX_PAD_ENABLE 18
+#define V_MAC_RX_PAD_ENABLE(x) ((x) << S_MAC_RX_PAD_ENABLE)
+#define F_MAC_RX_PAD_ENABLE V_MAC_RX_PAD_ENABLE(1U)
+
+#define S_MAC_RX_CRC_ENABLE 19
+#define V_MAC_RX_CRC_ENABLE(x) ((x) << S_MAC_RX_CRC_ENABLE)
+#define F_MAC_RX_CRC_ENABLE V_MAC_RX_CRC_ENABLE(1U)
+
+#define A_GMAC_IFS 0x34
+
+#define S_MAC_IFS2 0
+#define M_MAC_IFS2 0x3f
+#define V_MAC_IFS2(x) ((x) << S_MAC_IFS2)
+#define G_MAC_IFS2(x) (((x) >> S_MAC_IFS2) & M_MAC_IFS2)
+
+#define S_MAC_IFS1 8
+#define M_MAC_IFS1 0x7f
+#define V_MAC_IFS1(x) ((x) << S_MAC_IFS1)
+#define G_MAC_IFS1(x) (((x) >> S_MAC_IFS1) & M_MAC_IFS1)
+
+#define A_GMAC_JUMBO_FRAME_LEN 0x38
+#define A_GMAC_LNK_DLY 0x3c
+#define A_GMAC_PAUSETIME 0x40
+#define A_GMAC_MCAST_LO 0x44
+#define A_GMAC_MCAST_HI 0x48
+#define A_GMAC_MCAST_MASK_LO 0x4c
+#define A_GMAC_MCAST_MASK_HI 0x50
+#define A_GMAC_RMT_CNT 0x54
+#define A_GMAC_RMT_DATA 0x58
+#define A_GMAC_BACKOFF_SEED 0x5c
+#define A_GMAC_TXF_THRES 0x60
+
+#define S_TXF_READ_THRESHOLD 0
+#define M_TXF_READ_THRESHOLD 0xff
+#define V_TXF_READ_THRESHOLD(x) ((x) << S_TXF_READ_THRESHOLD)
+#define G_TXF_READ_THRESHOLD(x) (((x) >> S_TXF_READ_THRESHOLD) & M_TXF_READ_THRESHOLD)
+
+#define S_TXF_WRITE_THRESHOLD 16
+#define M_TXF_WRITE_THRESHOLD 0xff
+#define V_TXF_WRITE_THRESHOLD(x) ((x) << S_TXF_WRITE_THRESHOLD)
+#define G_TXF_WRITE_THRESHOLD(x) (((x) >> S_TXF_WRITE_THRESHOLD) & M_TXF_WRITE_THRESHOLD)
+
+#define MAC_REG_BASE 0x600
+#define MAC_REG_ADDR(idx, reg) (MAC_REG_BASE + (idx) * 128 + (reg))
+
+#define MAC_REG_IDLO(idx) MAC_REG_ADDR(idx, A_GMAC_MACID_LO)
+#define MAC_REG_IDHI(idx) MAC_REG_ADDR(idx, A_GMAC_MACID_HI)
+#define MAC_REG_CSR(idx) MAC_REG_ADDR(idx, A_GMAC_CSR)
+#define MAC_REG_IFS(idx) MAC_REG_ADDR(idx, A_GMAC_IFS)
+#define MAC_REG_LARGEFRAMELENGTH(idx) MAC_REG_ADDR(idx, A_GMAC_JUMBO_FRAME_LEN)
+#define MAC_REG_LINKDLY(idx) MAC_REG_ADDR(idx, A_GMAC_LNK_DLY)
+#define MAC_REG_PAUSETIME(idx) MAC_REG_ADDR(idx, A_GMAC_PAUSETIME)
+#define MAC_REG_CASTLO(idx) MAC_REG_ADDR(idx, A_GMAC_MCAST_LO)
+#define MAC_REG_MCASTHI(idx) MAC_REG_ADDR(idx, A_GMAC_MCAST_HI)
+#define MAC_REG_CASTMASKLO(idx) MAC_REG_ADDR(idx, A_GMAC_MCAST_MASK_LO)
+#define MAC_REG_MCASTMASKHI(idx) MAC_REG_ADDR(idx, A_GMAC_MCAST_MASK_HI)
+#define MAC_REG_RMCNT(idx) MAC_REG_ADDR(idx, A_GMAC_RMT_CNT)
+#define MAC_REG_RMDATA(idx) MAC_REG_ADDR(idx, A_GMAC_RMT_DATA)
+#define MAC_REG_GMRANDBACKOFFSEED(idx) MAC_REG_ADDR(idx, A_GMAC_BACKOFF_SEED)
+#define MAC_REG_TXFTHRESHOLDS(idx) MAC_REG_ADDR(idx, A_GMAC_TXF_THRES)
+
+#endif
diff --git a/drivers/net/chelsio/gmac.h b/drivers/net/chelsio/gmac.h
index 746b0eeea964..a2b8ad9b5535 100644
--- a/drivers/net/chelsio/gmac.h
+++ b/drivers/net/chelsio/gmac.h
@@ -62,6 +62,8 @@ struct cmac_statistics {
u64 TxInternalMACXmitError;
u64 TxFramesWithExcessiveDeferral;
u64 TxFCSErrors;
+ u64 TxJumboFramesOK;
+ u64 TxJumboOctetsOK;
/* Receive */
u64 RxOctetsOK;
@@ -81,6 +83,8 @@ struct cmac_statistics {
u64 RxInRangeLengthErrors;
u64 RxOutOfRangeLengthField;
u64 RxFrameTooLongErrors;
+ u64 RxJumboFramesOK;
+ u64 RxJumboOctetsOK;
};
struct cmac_ops {
@@ -128,6 +132,7 @@ struct gmac {
extern struct gmac t1_pm3393_ops;
extern struct gmac t1_chelsio_mac_ops;
extern struct gmac t1_vsc7321_ops;
+extern struct gmac t1_vsc7326_ops;
extern struct gmac t1_ixf1010_ops;
extern struct gmac t1_dummy_mac_ops;
diff --git a/drivers/net/chelsio/ixf1010.c b/drivers/net/chelsio/ixf1010.c
new file mode 100644
index 000000000000..5b8f144e83d4
--- /dev/null
+++ b/drivers/net/chelsio/ixf1010.c
@@ -0,0 +1,485 @@
+/* $Date: 2005/11/12 02:13:49 $ $RCSfile: ixf1010.c,v $ $Revision: 1.36 $ */
+#include "gmac.h"
+#include "elmer0.h"
+
+/* Update fast changing statistics every 15 seconds */
+#define STATS_TICK_SECS 15
+/* 30 minutes for full statistics update */
+#define MAJOR_UPDATE_TICKS (1800 / STATS_TICK_SECS)
+
+/*
+ * The IXF1010 can handle frames up to 16383 bytes but it's optimized for
+ * frames up to 9831 (0x2667) bytes, so we limit jumbo frame size to this.
+ * This length includes ethernet header and FCS.
+ */
+#define MAX_FRAME_SIZE 0x2667
+
+/* MAC registers */
+enum {
+ /* Per-port registers */
+ REG_MACADDR_LOW = 0,
+ REG_MACADDR_HIGH = 0x4,
+ REG_FDFC_TYPE = 0xC,
+ REG_FC_TX_TIMER_VALUE = 0x1c,
+ REG_IPG_RX_TIME1 = 0x28,
+ REG_IPG_RX_TIME2 = 0x2c,
+ REG_IPG_TX_TIME = 0x30,
+ REG_PAUSE_THRES = 0x38,
+ REG_MAX_FRAME_SIZE = 0x3c,
+ REG_RGMII_SPEED = 0x40,
+ REG_FC_ENABLE = 0x48,
+ REG_DISCARD_CTRL_FRAMES = 0x54,
+ REG_DIVERSE_CONFIG = 0x60,
+ REG_RX_FILTER = 0x64,
+ REG_MC_ADDR_LOW = 0x68,
+ REG_MC_ADDR_HIGH = 0x6c,
+
+ REG_RX_OCTETS_OK = 0x80,
+ REG_RX_OCTETS_BAD = 0x84,
+ REG_RX_UC_PKTS = 0x88,
+ REG_RX_MC_PKTS = 0x8c,
+ REG_RX_BC_PKTS = 0x90,
+ REG_RX_FCS_ERR = 0xb0,
+ REG_RX_TAGGED = 0xb4,
+ REG_RX_DATA_ERR = 0xb8,
+ REG_RX_ALIGN_ERR = 0xbc,
+ REG_RX_LONG_ERR = 0xc0,
+ REG_RX_JABBER_ERR = 0xc4,
+ REG_RX_PAUSE_FRAMES = 0xc8,
+ REG_RX_UNKNOWN_CTRL_FRAMES = 0xcc,
+ REG_RX_VERY_LONG_ERR = 0xd0,
+ REG_RX_RUNT_ERR = 0xd4,
+ REG_RX_SHORT_ERR = 0xd8,
+ REG_RX_SYMBOL_ERR = 0xe4,
+
+ REG_TX_OCTETS_OK = 0x100,
+ REG_TX_OCTETS_BAD = 0x104,
+ REG_TX_UC_PKTS = 0x108,
+ REG_TX_MC_PKTS = 0x10c,
+ REG_TX_BC_PKTS = 0x110,
+ REG_TX_EXCESSIVE_LEN_DROP = 0x14c,
+ REG_TX_UNDERRUN = 0x150,
+ REG_TX_TAGGED = 0x154,
+ REG_TX_PAUSE_FRAMES = 0x15C,
+
+ /* Global registers */
+ REG_PORT_ENABLE = 0x1400,
+
+ REG_JTAG_ID = 0x1430,
+
+ RX_FIFO_HIGH_WATERMARK_BASE = 0x1600,
+ RX_FIFO_LOW_WATERMARK_BASE = 0x1628,
+ RX_FIFO_FRAMES_REMOVED_BASE = 0x1650,
+
+ REG_RX_ERR_DROP = 0x167c,
+ REG_RX_FIFO_OVERFLOW_EVENT = 0x1680,
+
+ TX_FIFO_HIGH_WATERMARK_BASE = 0x1800,
+ TX_FIFO_LOW_WATERMARK_BASE = 0x1828,
+ TX_FIFO_XFER_THRES_BASE = 0x1850,
+
+ REG_TX_FIFO_OVERFLOW_EVENT = 0x1878,
+ REG_TX_FIFO_OOS_EVENT = 0x1884,
+
+ TX_FIFO_FRAMES_REMOVED_BASE = 0x1888,
+
+ REG_SPI_RX_BURST = 0x1c00,
+ REG_SPI_RX_TRAINING = 0x1c04,
+ REG_SPI_RX_CALENDAR = 0x1c08,
+ REG_SPI_TX_SYNC = 0x1c0c
+};
+
+enum { /* RMON registers */
+ REG_RxOctetsTotalOK = 0x80,
+ REG_RxOctetsBad = 0x84,
+ REG_RxUCPkts = 0x88,
+ REG_RxMCPkts = 0x8c,
+ REG_RxBCPkts = 0x90,
+ REG_RxJumboPkts = 0xac,
+ REG_RxFCSErrors = 0xb0,
+ REG_RxDataErrors = 0xb8,
+ REG_RxAlignErrors = 0xbc,
+ REG_RxLongErrors = 0xc0,
+ REG_RxJabberErrors = 0xc4,
+ REG_RxPauseMacControlCounter = 0xc8,
+ REG_RxVeryLongErrors = 0xd0,
+ REG_RxRuntErrors = 0xd4,
+ REG_RxShortErrors = 0xd8,
+ REG_RxSequenceErrors = 0xe0,
+ REG_RxSymbolErrors = 0xe4,
+
+ REG_TxOctetsTotalOK = 0x100,
+ REG_TxOctetsBad = 0x104,
+ REG_TxUCPkts = 0x108,
+ REG_TxMCPkts = 0x10c,
+ REG_TxBCPkts = 0x110,
+ REG_TxJumboPkts = 0x12C,
+ REG_TxTotalCollisions = 0x134,
+ REG_TxExcessiveLengthDrop = 0x14c,
+ REG_TxUnderrun = 0x150,
+ REG_TxCRCErrors = 0x158,
+ REG_TxPauseFrames = 0x15c
+};
+
+enum {
+ DIVERSE_CONFIG_PAD_ENABLE = 0x80,
+ DIVERSE_CONFIG_CRC_ADD = 0x40
+};
+
+#define MACREG_BASE 0
+#define MACREG(mac, mac_reg) ((mac)->instance->mac_base + (mac_reg))
+
+struct _cmac_instance {
+ u32 mac_base;
+ u32 index;
+ u32 version;
+ u32 ticks;
+};
+
+static void disable_port(struct cmac *mac)
+{
+ u32 val;
+
+ t1_tpi_read(mac->adapter, REG_PORT_ENABLE, &val);
+ val &= ~(1 << mac->instance->index);
+ t1_tpi_write(mac->adapter, REG_PORT_ENABLE, val);
+}
+
+#define RMON_UPDATE(mac, name, stat_name) \
+ t1_tpi_read((mac)->adapter, MACREG(mac, REG_##name), &val); \
+ (mac)->stats.stat_name += val;
+
+/*
+ * Read the current values of the RMON counters and add them to the cumulative
+ * port statistics. The HW RMON counters are cleared by this operation.
+ */
+static void port_stats_update(struct cmac *mac)
+{
+ u32 val;
+
+ /* Rx stats */
+ RMON_UPDATE(mac, RxOctetsTotalOK, RxOctetsOK);
+ RMON_UPDATE(mac, RxOctetsBad, RxOctetsBad);
+ RMON_UPDATE(mac, RxUCPkts, RxUnicastFramesOK);
+ RMON_UPDATE(mac, RxMCPkts, RxMulticastFramesOK);
+ RMON_UPDATE(mac, RxBCPkts, RxBroadcastFramesOK);
+ RMON_UPDATE(mac, RxJumboPkts, RxJumboFramesOK);
+ RMON_UPDATE(mac, RxFCSErrors, RxFCSErrors);
+ RMON_UPDATE(mac, RxAlignErrors, RxAlignErrors);
+ RMON_UPDATE(mac, RxLongErrors, RxFrameTooLongErrors);
+ RMON_UPDATE(mac, RxVeryLongErrors, RxFrameTooLongErrors);
+ RMON_UPDATE(mac, RxPauseMacControlCounter, RxPauseFrames);
+ RMON_UPDATE(mac, RxDataErrors, RxDataErrors);
+ RMON_UPDATE(mac, RxJabberErrors, RxJabberErrors);
+ RMON_UPDATE(mac, RxRuntErrors, RxRuntErrors);
+ RMON_UPDATE(mac, RxShortErrors, RxRuntErrors);
+ RMON_UPDATE(mac, RxSequenceErrors, RxSequenceErrors);
+ RMON_UPDATE(mac, RxSymbolErrors, RxSymbolErrors);
+
+ /* Tx stats (skip collision stats as we are full-duplex only) */
+ RMON_UPDATE(mac, TxOctetsTotalOK, TxOctetsOK);
+ RMON_UPDATE(mac, TxOctetsBad, TxOctetsBad);
+ RMON_UPDATE(mac, TxUCPkts, TxUnicastFramesOK);
+ RMON_UPDATE(mac, TxMCPkts, TxMulticastFramesOK);
+ RMON_UPDATE(mac, TxBCPkts, TxBroadcastFramesOK);
+ RMON_UPDATE(mac, TxJumboPkts, TxJumboFramesOK);
+ RMON_UPDATE(mac, TxPauseFrames, TxPauseFrames);
+ RMON_UPDATE(mac, TxExcessiveLengthDrop, TxLengthErrors);
+ RMON_UPDATE(mac, TxUnderrun, TxUnderrun);
+ RMON_UPDATE(mac, TxCRCErrors, TxFCSErrors);
+}
+
+/* No-op interrupt operation as this MAC does not support interrupts */
+static int mac_intr_op(struct cmac *mac)
+{
+ return 0;
+}
+
+/* Expect MAC address to be in network byte order. */
+static int mac_set_address(struct cmac *mac, u8 addr[6])
+{
+ u32 addr_lo, addr_hi;
+
+ addr_lo = addr[2];
+ addr_lo = (addr_lo << 8) | addr[3];
+ addr_lo = (addr_lo << 8) | addr[4];
+ addr_lo = (addr_lo << 8) | addr[5];
+
+ addr_hi = addr[0];
+ addr_hi = (addr_hi << 8) | addr[1];
+
+ t1_tpi_write(mac->adapter, MACREG(mac, REG_MACADDR_LOW), addr_lo);
+ t1_tpi_write(mac->adapter, MACREG(mac, REG_MACADDR_HIGH), addr_hi);
+ return 0;
+}
+
+static int mac_get_address(struct cmac *mac, u8 addr[6])
+{
+ u32 addr_lo, addr_hi;
+
+ t1_tpi_read(mac->adapter, MACREG(mac, REG_MACADDR_LOW), &addr_lo);
+ t1_tpi_read(mac->adapter, MACREG(mac, REG_MACADDR_HIGH), &addr_hi);
+
+ addr[0] = (u8) (addr_hi >> 8);
+ addr[1] = (u8) addr_hi;
+ addr[2] = (u8) (addr_lo >> 24);
+ addr[3] = (u8) (addr_lo >> 16);
+ addr[4] = (u8) (addr_lo >> 8);
+ addr[5] = (u8) addr_lo;
+ return 0;
+}
+
+/* This is intended to reset a port, not the whole MAC */
+static int mac_reset(struct cmac *mac)
+{
+ return 0;
+}
+
+static int mac_set_rx_mode(struct cmac *mac, struct t1_rx_mode *rm)
+{
+ u32 val, new_mode;
+ adapter_t *adapter = mac->adapter;
+ u32 addr_lo, addr_hi;
+ u8 *addr;
+
+ t1_tpi_read(adapter, MACREG(mac, REG_RX_FILTER), &val);
+ new_mode = val & ~7;
+ if (!t1_rx_mode_promisc(rm) && mac->instance->version > 0)
+ new_mode |= 1; /* only set if version > 0 due to erratum */
+ if (!t1_rx_mode_promisc(rm) && !t1_rx_mode_allmulti(rm)
+ && t1_rx_mode_mc_cnt(rm) <= 1)
+ new_mode |= 2;
+ if (new_mode != val)
+ t1_tpi_write(adapter, MACREG(mac, REG_RX_FILTER), new_mode);
+ switch (t1_rx_mode_mc_cnt(rm)) {
+ case 0:
+ t1_tpi_write(adapter, MACREG(mac, REG_MC_ADDR_LOW), 0);
+ t1_tpi_write(adapter, MACREG(mac, REG_MC_ADDR_HIGH), 0);
+ break;
+ case 1:
+ addr = t1_get_next_mcaddr(rm);
+ addr_lo = (addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) |
+ addr[5];
+ addr_hi = (addr[0] << 8) | addr[1];
+ t1_tpi_write(adapter, MACREG(mac, REG_MC_ADDR_LOW), addr_lo);
+ t1_tpi_write(adapter, MACREG(mac, REG_MC_ADDR_HIGH), addr_hi);
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static int mac_set_mtu(struct cmac *mac, int mtu)
+{
+ /* MAX_FRAME_SIZE inludes header + FCS, mtu doesn't */
+ if (mtu > (MAX_FRAME_SIZE - 14 - 4)) return -EINVAL;
+ t1_tpi_write(mac->adapter, MACREG(mac, REG_MAX_FRAME_SIZE),
+ mtu + 14 + 4);
+ return 0;
+}
+
+static int mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex,
+ int fc)
+{
+ u32 val;
+
+ if (speed >= 0 && speed != SPEED_100 && speed != SPEED_1000)
+ return -1;
+ if (duplex >= 0 && duplex != DUPLEX_FULL)
+ return -1;
+
+ if (speed >= 0) {
+ val = speed == SPEED_100 ? 1 : 2;
+ t1_tpi_write(mac->adapter, MACREG(mac, REG_RGMII_SPEED), val);
+ }
+
+ t1_tpi_read(mac->adapter, MACREG(mac, REG_FC_ENABLE), &val);
+ val &= ~3;
+ if (fc & PAUSE_RX)
+ val |= 1;
+ if (fc & PAUSE_TX)
+ val |= 2;
+ t1_tpi_write(mac->adapter, MACREG(mac, REG_FC_ENABLE), val);
+ return 0;
+}
+
+static int mac_get_speed_duplex_fc(struct cmac *mac, int *speed, int *duplex,
+ int *fc)
+{
+ u32 val;
+
+ if (duplex)
+ *duplex = DUPLEX_FULL;
+ if (speed) {
+ t1_tpi_read(mac->adapter, MACREG(mac, REG_RGMII_SPEED),
+ &val);
+ *speed = (val & 2) ? SPEED_1000 : SPEED_100;
+ }
+ if (fc) {
+ t1_tpi_read(mac->adapter, MACREG(mac, REG_FC_ENABLE), &val);
+ *fc = 0;
+ if (val & 1)
+ *fc |= PAUSE_RX;
+ if (val & 2)
+ *fc |= PAUSE_TX;
+ }
+ return 0;
+}
+
+static void enable_port(struct cmac *mac)
+{
+ u32 val;
+ u32 index = mac->instance->index;
+ adapter_t *adapter = mac->adapter;
+
+ t1_tpi_read(adapter, MACREG(mac, REG_DIVERSE_CONFIG), &val);
+ val |= DIVERSE_CONFIG_CRC_ADD | DIVERSE_CONFIG_PAD_ENABLE;
+ t1_tpi_write(adapter, MACREG(mac, REG_DIVERSE_CONFIG), val);
+ if (mac->instance->version > 0)
+ t1_tpi_write(adapter, MACREG(mac, REG_RX_FILTER), 3);
+ else /* Don't enable unicast address filtering due to IXF1010 bug */
+ t1_tpi_write(adapter, MACREG(mac, REG_RX_FILTER), 2);
+
+ t1_tpi_read(adapter, REG_RX_ERR_DROP, &val);
+ val |= (1 << index);
+ t1_tpi_write(adapter, REG_RX_ERR_DROP, val);
+
+ /*
+ * Clear the port RMON registers by adding their current values to the
+ * cumulatice port stats and then clearing the stats. Really.
+ */
+ port_stats_update(mac);
+ memset(&mac->stats, 0, sizeof(struct cmac_statistics));
+ mac->instance->ticks = 0;
+
+ t1_tpi_read(adapter, REG_PORT_ENABLE, &val);
+ val |= (1 << index);
+ t1_tpi_write(adapter, REG_PORT_ENABLE, val);
+
+ index <<= 2;
+ if (is_T2(adapter)) {
+ /* T204: set the Fifo water level & threshold */
+ t1_tpi_write(adapter, RX_FIFO_HIGH_WATERMARK_BASE + index, 0x740);
+ t1_tpi_write(adapter, RX_FIFO_LOW_WATERMARK_BASE + index, 0x730);
+ t1_tpi_write(adapter, TX_FIFO_HIGH_WATERMARK_BASE + index, 0x600);
+ t1_tpi_write(adapter, TX_FIFO_LOW_WATERMARK_BASE + index, 0x1d0);
+ t1_tpi_write(adapter, TX_FIFO_XFER_THRES_BASE + index, 0x1100);
+ } else {
+ /*
+ * Set the TX Fifo Threshold to 0x400 instead of 0x100 to work around
+ * Underrun problem. Intel has blessed this solution.
+ */
+ t1_tpi_write(adapter, TX_FIFO_XFER_THRES_BASE + index, 0x400);
+ }
+}
+
+/* IXF1010 ports do not have separate enables for TX and RX */
+static int mac_enable(struct cmac *mac, int which)
+{
+ if (which & (MAC_DIRECTION_RX | MAC_DIRECTION_TX))
+ enable_port(mac);
+ return 0;
+}
+
+static int mac_disable(struct cmac *mac, int which)
+{
+ if (which & (MAC_DIRECTION_RX | MAC_DIRECTION_TX))
+ disable_port(mac);
+ return 0;
+}
+
+/*
+ * This function is called periodically to accumulate the current values of the
+ * RMON counters into the port statistics. Since the counters are only 32 bits
+ * some of them can overflow in less than a minute at GigE speeds, so this
+ * function should be called every 30 seconds or so.
+ *
+ * To cut down on reading costs we update only the octet counters at each tick
+ * and do a full update at major ticks, which can be every 30 minutes or more.
+ */
+static const struct cmac_statistics *mac_update_statistics(struct cmac *mac,
+ int flag)
+{
+ if (flag == MAC_STATS_UPDATE_FULL ||
+ MAJOR_UPDATE_TICKS <= mac->instance->ticks) {
+ port_stats_update(mac);
+ mac->instance->ticks = 0;
+ } else {
+ u32 val;
+
+ RMON_UPDATE(mac, RxOctetsTotalOK, RxOctetsOK);
+ RMON_UPDATE(mac, TxOctetsTotalOK, TxOctetsOK);
+ mac->instance->ticks++;
+ }
+ return &mac->stats;
+}
+
+static void mac_destroy(struct cmac *mac)
+{
+ kfree(mac);
+}
+
+static struct cmac_ops ixf1010_ops = {
+ .destroy = mac_destroy,
+ .reset = mac_reset,
+ .interrupt_enable = mac_intr_op,
+ .interrupt_disable = mac_intr_op,
+ .interrupt_clear = mac_intr_op,
+ .enable = mac_enable,
+ .disable = mac_disable,
+ .set_mtu = mac_set_mtu,
+ .set_rx_mode = mac_set_rx_mode,
+ .set_speed_duplex_fc = mac_set_speed_duplex_fc,
+ .get_speed_duplex_fc = mac_get_speed_duplex_fc,
+ .statistics_update = mac_update_statistics,
+ .macaddress_get = mac_get_address,
+ .macaddress_set = mac_set_address,
+};
+
+static int ixf1010_mac_reset(adapter_t *adapter)
+{
+ u32 val;
+
+ t1_tpi_read(adapter, A_ELMER0_GPO, &val);
+ if ((val & 1) != 0) {
+ val &= ~1;
+ t1_tpi_write(adapter, A_ELMER0_GPO, val);
+ udelay(2);
+ }
+ val |= 1;
+ t1_tpi_write(adapter, A_ELMER0_GPO, val);
+ udelay(2);
+
+ t1_tpi_write(adapter, REG_PORT_ENABLE, 0);
+ return 0;
+}
+
+static struct cmac *ixf1010_mac_create(adapter_t *adapter, int index)
+{
+ struct cmac *mac;
+ u32 val;
+
+ if (index > 9) return NULL;
+
+ mac = kzalloc(sizeof(*mac) + sizeof(cmac_instance), GFP_KERNEL);
+ if (!mac) return NULL;
+
+ mac->ops = &ixf1010_ops;
+ mac->instance = (cmac_instance *)(mac + 1);
+
+ mac->instance->mac_base = MACREG_BASE + (index * 0x200);
+ mac->instance->index = index;
+ mac->adapter = adapter;
+ mac->instance->ticks = 0;
+
+ t1_tpi_read(adapter, REG_JTAG_ID, &val);
+ mac->instance->version = val >> 28;
+ return mac;
+}
+
+struct gmac t1_ixf1010_ops = {
+ STATS_TICK_SECS,
+ ixf1010_mac_create,
+ ixf1010_mac_reset
+};
diff --git a/drivers/net/chelsio/mac.c b/drivers/net/chelsio/mac.c
new file mode 100644
index 000000000000..6af39dc70459
--- /dev/null
+++ b/drivers/net/chelsio/mac.c
@@ -0,0 +1,368 @@
+/* $Date: 2005/10/22 00:42:59 $ $RCSfile: mac.c,v $ $Revision: 1.32 $ */
+#include "gmac.h"
+#include "regs.h"
+#include "fpga_defs.h"
+
+#define MAC_CSR_INTERFACE_GMII 0x0
+#define MAC_CSR_INTERFACE_TBI 0x1
+#define MAC_CSR_INTERFACE_MII 0x2
+#define MAC_CSR_INTERFACE_RMII 0x3
+
+/* Chelsio's MAC statistics. */
+struct mac_statistics {
+
+ /* Transmit */
+ u32 TxFramesTransmittedOK;
+ u32 TxReserved1;
+ u32 TxReserved2;
+ u32 TxOctetsTransmittedOK;
+ u32 TxFramesWithDeferredXmissions;
+ u32 TxLateCollisions;
+ u32 TxFramesAbortedDueToXSCollisions;
+ u32 TxFramesLostDueToIntMACXmitError;
+ u32 TxReserved3;
+ u32 TxMulticastFrameXmittedOK;
+ u32 TxBroadcastFramesXmittedOK;
+ u32 TxFramesWithExcessiveDeferral;
+ u32 TxPAUSEMACCtrlFramesTransmitted;
+
+ /* Receive */
+ u32 RxFramesReceivedOK;
+ u32 RxFrameCheckSequenceErrors;
+ u32 RxAlignmentErrors;
+ u32 RxOctetsReceivedOK;
+ u32 RxFramesLostDueToIntMACRcvError;
+ u32 RxMulticastFramesReceivedOK;
+ u32 RxBroadcastFramesReceivedOK;
+ u32 RxInRangeLengthErrors;
+ u32 RxTxOutOfRangeLengthField;
+ u32 RxFrameTooLongErrors;
+ u32 RxPAUSEMACCtrlFramesReceived;
+};
+
+static int static_aPorts[] = {
+ FPGA_GMAC_INTERRUPT_PORT0,
+ FPGA_GMAC_INTERRUPT_PORT1,
+ FPGA_GMAC_INTERRUPT_PORT2,
+ FPGA_GMAC_INTERRUPT_PORT3
+};
+
+struct _cmac_instance {
+ u32 index;
+};
+
+static int mac_intr_enable(struct cmac *mac)
+{
+ u32 mac_intr;
+
+ if (t1_is_asic(mac->adapter)) {
+ /* ASIC */
+
+ /* We don't use the on chip MAC for ASIC products. */
+ } else {
+ /* FPGA */
+
+ /* Set parent gmac interrupt. */
+ mac_intr = readl(mac->adapter->regs + A_PL_ENABLE);
+ mac_intr |= FPGA_PCIX_INTERRUPT_GMAC;
+ writel(mac_intr, mac->adapter->regs + A_PL_ENABLE);
+
+ mac_intr = readl(mac->adapter->regs + FPGA_GMAC_ADDR_INTERRUPT_ENABLE);
+ mac_intr |= static_aPorts[mac->instance->index];
+ writel(mac_intr,
+ mac->adapter->regs + FPGA_GMAC_ADDR_INTERRUPT_ENABLE);
+ }
+
+ return 0;
+}
+
+static int mac_intr_disable(struct cmac *mac)
+{
+ u32 mac_intr;
+
+ if (t1_is_asic(mac->adapter)) {
+ /* ASIC */
+
+ /* We don't use the on chip MAC for ASIC products. */
+ } else {
+ /* FPGA */
+
+ /* Set parent gmac interrupt. */
+ mac_intr = readl(mac->adapter->regs + A_PL_ENABLE);
+ mac_intr &= ~FPGA_PCIX_INTERRUPT_GMAC;
+ writel(mac_intr, mac->adapter->regs + A_PL_ENABLE);
+
+ mac_intr = readl(mac->adapter->regs + FPGA_GMAC_ADDR_INTERRUPT_ENABLE);
+ mac_intr &= ~(static_aPorts[mac->instance->index]);
+ writel(mac_intr,
+ mac->adapter->regs + FPGA_GMAC_ADDR_INTERRUPT_ENABLE);
+ }
+
+ return 0;
+}
+
+static int mac_intr_clear(struct cmac *mac)
+{
+ u32 mac_intr;
+
+ if (t1_is_asic(mac->adapter)) {
+ /* ASIC */
+
+ /* We don't use the on chip MAC for ASIC products. */
+ } else {
+ /* FPGA */
+
+ /* Set parent gmac interrupt. */
+ writel(FPGA_PCIX_INTERRUPT_GMAC,
+ mac->adapter->regs + A_PL_CAUSE);
+ mac_intr = readl(mac->adapter->regs + FPGA_GMAC_ADDR_INTERRUPT_CAUSE);
+ mac_intr |= (static_aPorts[mac->instance->index]);
+ writel(mac_intr,
+ mac->adapter->regs + FPGA_GMAC_ADDR_INTERRUPT_CAUSE);
+ }
+
+ return 0;
+}
+
+static int mac_get_address(struct cmac *mac, u8 addr[6])
+{
+ u32 data32_lo, data32_hi;
+
+ data32_lo = readl(mac->adapter->regs
+ + MAC_REG_IDLO(mac->instance->index));
+ data32_hi = readl(mac->adapter->regs
+ + MAC_REG_IDHI(mac->instance->index));
+
+ addr[0] = (u8) ((data32_hi >> 8) & 0xFF);
+ addr[1] = (u8) ((data32_hi) & 0xFF);
+ addr[2] = (u8) ((data32_lo >> 24) & 0xFF);
+ addr[3] = (u8) ((data32_lo >> 16) & 0xFF);
+ addr[4] = (u8) ((data32_lo >> 8) & 0xFF);
+ addr[5] = (u8) ((data32_lo) & 0xFF);
+ return 0;
+}
+
+static int mac_reset(struct cmac *mac)
+{
+ u32 data32;
+ int mac_in_reset, time_out = 100;
+ int idx = mac->instance->index;
+
+ data32 = readl(mac->adapter->regs + MAC_REG_CSR(idx));
+ writel(data32 | F_MAC_RESET,
+ mac->adapter->regs + MAC_REG_CSR(idx));
+
+ do {
+ data32 = readl(mac->adapter->regs + MAC_REG_CSR(idx));
+
+ mac_in_reset = data32 & F_MAC_RESET;
+ if (mac_in_reset)
+ udelay(1);
+ } while (mac_in_reset && --time_out);
+
+ if (mac_in_reset) {
+ CH_ERR("%s: MAC %d reset timed out\n",
+ mac->adapter->name, idx);
+ return 2;
+ }
+
+ return 0;
+}
+
+static int mac_set_rx_mode(struct cmac *mac, struct t1_rx_mode *rm)
+{
+ u32 val;
+
+ val = readl(mac->adapter->regs
+ + MAC_REG_CSR(mac->instance->index));
+ val &= ~(F_MAC_PROMISC | F_MAC_MC_ENABLE);
+ val |= V_MAC_PROMISC(t1_rx_mode_promisc(rm) != 0);
+ val |= V_MAC_MC_ENABLE(t1_rx_mode_allmulti(rm) != 0);
+ writel(val,
+ mac->adapter->regs + MAC_REG_CSR(mac->instance->index));
+
+ return 0;
+}
+
+static int mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex,
+ int fc)
+{
+ u32 data32;
+
+ data32 = readl(mac->adapter->regs
+ + MAC_REG_CSR(mac->instance->index));
+ data32 &= ~(F_MAC_HALF_DUPLEX | V_MAC_SPEED(M_MAC_SPEED) |
+ V_INTERFACE(M_INTERFACE) | F_MAC_TX_PAUSE_ENABLE |
+ F_MAC_RX_PAUSE_ENABLE);
+
+ switch (speed) {
+ case SPEED_10:
+ case SPEED_100:
+ data32 |= V_INTERFACE(MAC_CSR_INTERFACE_MII);
+ data32 |= V_MAC_SPEED(speed == SPEED_10 ? 0 : 1);
+ break;
+ case SPEED_1000:
+ data32 |= V_INTERFACE(MAC_CSR_INTERFACE_GMII);
+ data32 |= V_MAC_SPEED(2);
+ break;
+ }
+
+ if (duplex >= 0)
+ data32 |= V_MAC_HALF_DUPLEX(duplex == DUPLEX_HALF);
+
+ if (fc >= 0) {
+ data32 |= V_MAC_RX_PAUSE_ENABLE((fc & PAUSE_RX) != 0);
+ data32 |= V_MAC_TX_PAUSE_ENABLE((fc & PAUSE_TX) != 0);
+ }
+
+ writel(data32,
+ mac->adapter->regs + MAC_REG_CSR(mac->instance->index));
+ return 0;
+}
+
+static int mac_enable(struct cmac *mac, int which)
+{
+ u32 val;
+
+ val = readl(mac->adapter->regs
+ + MAC_REG_CSR(mac->instance->index));
+ if (which & MAC_DIRECTION_RX)
+ val |= F_MAC_RX_ENABLE;
+ if (which & MAC_DIRECTION_TX)
+ val |= F_MAC_TX_ENABLE;
+ writel(val,
+ mac->adapter->regs + MAC_REG_CSR(mac->instance->index));
+ return 0;
+}
+
+static int mac_disable(struct cmac *mac, int which)
+{
+ u32 val;
+
+ val = readl(mac->adapter->regs
+ + MAC_REG_CSR(mac->instance->index));
+ if (which & MAC_DIRECTION_RX)
+ val &= ~F_MAC_RX_ENABLE;
+ if (which & MAC_DIRECTION_TX)
+ val &= ~F_MAC_TX_ENABLE;
+ writel(val,
+ mac->adapter->regs + MAC_REG_CSR(mac->instance->index));
+ return 0;
+}
+
+#if 0
+static int mac_set_ifs(struct cmac *mac, u32 mode)
+{
+ t1_write_reg_4(mac->adapter,
+ MAC_REG_IFS(mac->instance->index),
+ mode);
+ return 0;
+}
+
+static int mac_enable_isl(struct cmac *mac)
+{
+ u32 data32 = readl(mac->adapter->regs
+ + MAC_REG_CSR(mac->instance->index));
+ data32 |= F_MAC_RX_ENABLE | F_MAC_TX_ENABLE;
+ t1_write_reg_4(mac->adapter,
+ MAC_REG_CSR(mac->instance->index),
+ data32);
+ return 0;
+}
+#endif
+
+static int mac_set_mtu(struct cmac *mac, int mtu)
+{
+ if (mtu > 9600)
+ return -EINVAL;
+ writel(mtu + ETH_HLEN + VLAN_HLEN,
+ mac->adapter->regs + MAC_REG_LARGEFRAMELENGTH(mac->instance->index));
+
+ return 0;
+}
+
+static const struct cmac_statistics *mac_update_statistics(struct cmac *mac,
+ int flag)
+{
+ struct mac_statistics st;
+ u32 *p = (u32 *) & st, i;
+
+ writel(0,
+ mac->adapter->regs + MAC_REG_RMCNT(mac->instance->index));
+
+ for (i = 0; i < sizeof(st) / sizeof(u32); i++)
+ *p++ = readl(mac->adapter->regs
+ + MAC_REG_RMDATA(mac->instance->index));
+
+ /* XXX convert stats */
+ return &mac->stats;
+}
+
+static void mac_destroy(struct cmac *mac)
+{
+ kfree(mac);
+}
+
+static struct cmac_ops chelsio_mac_ops = {
+ .destroy = mac_destroy,
+ .reset = mac_reset,
+ .interrupt_enable = mac_intr_enable,
+ .interrupt_disable = mac_intr_disable,
+ .interrupt_clear = mac_intr_clear,
+ .enable = mac_enable,
+ .disable = mac_disable,
+ .set_mtu = mac_set_mtu,
+ .set_rx_mode = mac_set_rx_mode,
+ .set_speed_duplex_fc = mac_set_speed_duplex_fc,
+ .macaddress_get = mac_get_address,
+ .statistics_update = mac_update_statistics,
+};
+
+static struct cmac *mac_create(adapter_t *adapter, int index)
+{
+ struct cmac *mac;
+ u32 data32;
+
+ if (index >= 4)
+ return NULL;
+
+ mac = kzalloc(sizeof(*mac) + sizeof(cmac_instance), GFP_KERNEL);
+ if (!mac)
+ return NULL;
+
+ mac->ops = &chelsio_mac_ops;
+ mac->instance = (cmac_instance *) (mac + 1);
+
+ mac->instance->index = index;
+ mac->adapter = adapter;
+
+ data32 = readl(adapter->regs + MAC_REG_CSR(mac->instance->index));
+ data32 &= ~(F_MAC_RESET | F_MAC_PROMISC | F_MAC_PROMISC |
+ F_MAC_LB_ENABLE | F_MAC_RX_ENABLE | F_MAC_TX_ENABLE);
+ data32 |= F_MAC_JUMBO_ENABLE;
+ writel(data32, adapter->regs + MAC_REG_CSR(mac->instance->index));
+
+ /* Initialize the random backoff seed. */
+ data32 = 0x55aa + (3 * index);
+ writel(data32,
+ adapter->regs + MAC_REG_GMRANDBACKOFFSEED(mac->instance->index));
+
+ /* Check to see if the mac address needs to be set manually. */
+ data32 = readl(adapter->regs + MAC_REG_IDLO(mac->instance->index));
+ if (data32 == 0 || data32 == 0xffffffff) {
+ /*
+ * Add a default MAC address if we can't read one.
+ */
+ writel(0x43FFFFFF - index,
+ adapter->regs + MAC_REG_IDLO(mac->instance->index));
+ writel(0x0007,
+ adapter->regs + MAC_REG_IDHI(mac->instance->index));
+ }
+
+ (void) mac_set_mtu(mac, 1500);
+ return mac;
+}
+
+struct gmac t1_chelsio_mac_ops = {
+ .create = mac_create
+};
diff --git a/drivers/net/chelsio/mv88e1xxx.c b/drivers/net/chelsio/mv88e1xxx.c
new file mode 100644
index 000000000000..28ac93ff7c4f
--- /dev/null
+++ b/drivers/net/chelsio/mv88e1xxx.c
@@ -0,0 +1,397 @@
+/* $Date: 2005/10/24 23:18:13 $ $RCSfile: mv88e1xxx.c,v $ $Revision: 1.49 $ */
+#include "common.h"
+#include "mv88e1xxx.h"
+#include "cphy.h"
+#include "elmer0.h"
+
+/* MV88E1XXX MDI crossover register values */
+#define CROSSOVER_MDI 0
+#define CROSSOVER_MDIX 1
+#define CROSSOVER_AUTO 3
+
+#define INTR_ENABLE_MASK 0x6CA0
+
+/*
+ * Set the bits given by 'bitval' in PHY register 'reg'.
+ */
+static void mdio_set_bit(struct cphy *cphy, int reg, u32 bitval)
+{
+ u32 val;
+
+ (void) simple_mdio_read(cphy, reg, &val);
+ (void) simple_mdio_write(cphy, reg, val | bitval);
+}
+
+/*
+ * Clear the bits given by 'bitval' in PHY register 'reg'.
+ */
+static void mdio_clear_bit(struct cphy *cphy, int reg, u32 bitval)
+{
+ u32 val;
+
+ (void) simple_mdio_read(cphy, reg, &val);
+ (void) simple_mdio_write(cphy, reg, val & ~bitval);
+}
+
+/*
+ * NAME: phy_reset
+ *
+ * DESC: Reset the given PHY's port. NOTE: This is not a global
+ * chip reset.
+ *
+ * PARAMS: cphy - Pointer to PHY instance data.
+ *
+ * RETURN: 0 - Successfull reset.
+ * -1 - Timeout.
+ */
+static int mv88e1xxx_reset(struct cphy *cphy, int wait)
+{
+ u32 ctl;
+ int time_out = 1000;
+
+ mdio_set_bit(cphy, MII_BMCR, BMCR_RESET);
+
+ do {
+ (void) simple_mdio_read(cphy, MII_BMCR, &ctl);
+ ctl &= BMCR_RESET;
+ if (ctl)
+ udelay(1);
+ } while (ctl && --time_out);
+
+ return ctl ? -1 : 0;
+}
+
+static int mv88e1xxx_interrupt_enable(struct cphy *cphy)
+{
+ /* Enable PHY interrupts. */
+ (void) simple_mdio_write(cphy, MV88E1XXX_INTERRUPT_ENABLE_REGISTER,
+ INTR_ENABLE_MASK);
+
+ /* Enable Marvell interrupts through Elmer0. */
+ if (t1_is_asic(cphy->adapter)) {
+ u32 elmer;
+
+ t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer);
+ elmer |= ELMER0_GP_BIT1;
+ if (is_T2(cphy->adapter)) {
+ elmer |= ELMER0_GP_BIT2|ELMER0_GP_BIT3|ELMER0_GP_BIT4;
+ }
+ t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer);
+ }
+ return 0;
+}
+
+static int mv88e1xxx_interrupt_disable(struct cphy *cphy)
+{
+ /* Disable all phy interrupts. */
+ (void) simple_mdio_write(cphy, MV88E1XXX_INTERRUPT_ENABLE_REGISTER, 0);
+
+ /* Disable Marvell interrupts through Elmer0. */
+ if (t1_is_asic(cphy->adapter)) {
+ u32 elmer;
+
+ t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer);
+ elmer &= ~ELMER0_GP_BIT1;
+ if (is_T2(cphy->adapter)) {
+ elmer &= ~(ELMER0_GP_BIT2|ELMER0_GP_BIT3|ELMER0_GP_BIT4);
+ }
+ t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer);
+ }
+ return 0;
+}
+
+static int mv88e1xxx_interrupt_clear(struct cphy *cphy)
+{
+ u32 elmer;
+
+ /* Clear PHY interrupts by reading the register. */
+ (void) simple_mdio_read(cphy,
+ MV88E1XXX_INTERRUPT_STATUS_REGISTER, &elmer);
+
+ /* Clear Marvell interrupts through Elmer0. */
+ if (t1_is_asic(cphy->adapter)) {
+ t1_tpi_read(cphy->adapter, A_ELMER0_INT_CAUSE, &elmer);
+ elmer |= ELMER0_GP_BIT1;
+ if (is_T2(cphy->adapter)) {
+ elmer |= ELMER0_GP_BIT2|ELMER0_GP_BIT3|ELMER0_GP_BIT4;
+ }
+ t1_tpi_write(cphy->adapter, A_ELMER0_INT_CAUSE, elmer);
+ }
+ return 0;
+}
+
+/*
+ * Set the PHY speed and duplex. This also disables auto-negotiation, except
+ * for 1Gb/s, where auto-negotiation is mandatory.
+ */
+static int mv88e1xxx_set_speed_duplex(struct cphy *phy, int speed, int duplex)
+{
+ u32 ctl;
+
+ (void) simple_mdio_read(phy, MII_BMCR, &ctl);
+ if (speed >= 0) {
+ ctl &= ~(BMCR_SPEED100 | BMCR_SPEED1000 | BMCR_ANENABLE);
+ if (speed == SPEED_100)
+ ctl |= BMCR_SPEED100;
+ else if (speed == SPEED_1000)
+ ctl |= BMCR_SPEED1000;
+ }
+ if (duplex >= 0) {
+ ctl &= ~(BMCR_FULLDPLX | BMCR_ANENABLE);
+ if (duplex == DUPLEX_FULL)
+ ctl |= BMCR_FULLDPLX;
+ }
+ if (ctl & BMCR_SPEED1000) /* auto-negotiation required for 1Gb/s */
+ ctl |= BMCR_ANENABLE;
+ (void) simple_mdio_write(phy, MII_BMCR, ctl);
+ return 0;
+}
+
+static int mv88e1xxx_crossover_set(struct cphy *cphy, int crossover)
+{
+ u32 data32;
+
+ (void) simple_mdio_read(cphy,
+ MV88E1XXX_SPECIFIC_CNTRL_REGISTER, &data32);
+ data32 &= ~V_PSCR_MDI_XOVER_MODE(M_PSCR_MDI_XOVER_MODE);
+ data32 |= V_PSCR_MDI_XOVER_MODE(crossover);
+ (void) simple_mdio_write(cphy,
+ MV88E1XXX_SPECIFIC_CNTRL_REGISTER, data32);
+ return 0;
+}
+
+static int mv88e1xxx_autoneg_enable(struct cphy *cphy)
+{
+ u32 ctl;
+
+ (void) mv88e1xxx_crossover_set(cphy, CROSSOVER_AUTO);
+
+ (void) simple_mdio_read(cphy, MII_BMCR, &ctl);
+ /* restart autoneg for change to take effect */
+ ctl |= BMCR_ANENABLE | BMCR_ANRESTART;
+ (void) simple_mdio_write(cphy, MII_BMCR, ctl);
+ return 0;
+}
+
+static int mv88e1xxx_autoneg_disable(struct cphy *cphy)
+{
+ u32 ctl;
+
+ /*
+ * Crossover *must* be set to manual in order to disable auto-neg.
+ * The Alaska FAQs document highlights this point.
+ */
+ (void) mv88e1xxx_crossover_set(cphy, CROSSOVER_MDI);
+
+ /*
+ * Must include autoneg reset when disabling auto-neg. This
+ * is described in the Alaska FAQ document.
+ */
+ (void) simple_mdio_read(cphy, MII_BMCR, &ctl);
+ ctl &= ~BMCR_ANENABLE;
+ (void) simple_mdio_write(cphy, MII_BMCR, ctl | BMCR_ANRESTART);
+ return 0;
+}
+
+static int mv88e1xxx_autoneg_restart(struct cphy *cphy)
+{
+ mdio_set_bit(cphy, MII_BMCR, BMCR_ANRESTART);
+ return 0;
+}
+
+static int mv88e1xxx_advertise(struct cphy *phy, unsigned int advertise_map)
+{
+ u32 val = 0;
+
+ if (advertise_map &
+ (ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full)) {
+ (void) simple_mdio_read(phy, MII_GBCR, &val);
+ val &= ~(GBCR_ADV_1000HALF | GBCR_ADV_1000FULL);
+ if (advertise_map & ADVERTISED_1000baseT_Half)
+ val |= GBCR_ADV_1000HALF;
+ if (advertise_map & ADVERTISED_1000baseT_Full)
+ val |= GBCR_ADV_1000FULL;
+ }
+ (void) simple_mdio_write(phy, MII_GBCR, val);
+
+ val = 1;
+ if (advertise_map & ADVERTISED_10baseT_Half)
+ val |= ADVERTISE_10HALF;
+ if (advertise_map & ADVERTISED_10baseT_Full)
+ val |= ADVERTISE_10FULL;
+ if (advertise_map & ADVERTISED_100baseT_Half)
+ val |= ADVERTISE_100HALF;
+ if (advertise_map & ADVERTISED_100baseT_Full)
+ val |= ADVERTISE_100FULL;
+ if (advertise_map & ADVERTISED_PAUSE)
+ val |= ADVERTISE_PAUSE;
+ if (advertise_map & ADVERTISED_ASYM_PAUSE)
+ val |= ADVERTISE_PAUSE_ASYM;
+ (void) simple_mdio_write(phy, MII_ADVERTISE, val);
+ return 0;
+}
+
+static int mv88e1xxx_set_loopback(struct cphy *cphy, int on)
+{
+ if (on)
+ mdio_set_bit(cphy, MII_BMCR, BMCR_LOOPBACK);
+ else
+ mdio_clear_bit(cphy, MII_BMCR, BMCR_LOOPBACK);
+ return 0;
+}
+
+static int mv88e1xxx_get_link_status(struct cphy *cphy, int *link_ok,
+ int *speed, int *duplex, int *fc)
+{
+ u32 status;
+ int sp = -1, dplx = -1, pause = 0;
+
+ (void) simple_mdio_read(cphy,
+ MV88E1XXX_SPECIFIC_STATUS_REGISTER, &status);
+ if ((status & V_PSSR_STATUS_RESOLVED) != 0) {
+ if (status & V_PSSR_RX_PAUSE)
+ pause |= PAUSE_RX;
+ if (status & V_PSSR_TX_PAUSE)
+ pause |= PAUSE_TX;
+ dplx = (status & V_PSSR_DUPLEX) ? DUPLEX_FULL : DUPLEX_HALF;
+ sp = G_PSSR_SPEED(status);
+ if (sp == 0)
+ sp = SPEED_10;
+ else if (sp == 1)
+ sp = SPEED_100;
+ else
+ sp = SPEED_1000;
+ }
+ if (link_ok)
+ *link_ok = (status & V_PSSR_LINK) != 0;
+ if (speed)
+ *speed = sp;
+ if (duplex)
+ *duplex = dplx;
+ if (fc)
+ *fc = pause;
+ return 0;
+}
+
+static int mv88e1xxx_downshift_set(struct cphy *cphy, int downshift_enable)
+{
+ u32 val;
+
+ (void) simple_mdio_read(cphy,
+ MV88E1XXX_EXT_PHY_SPECIFIC_CNTRL_REGISTER, &val);
+
+ /*
+ * Set the downshift counter to 2 so we try to establish Gb link
+ * twice before downshifting.
+ */
+ val &= ~(V_DOWNSHIFT_ENABLE | V_DOWNSHIFT_CNT(M_DOWNSHIFT_CNT));
+
+ if (downshift_enable)
+ val |= V_DOWNSHIFT_ENABLE | V_DOWNSHIFT_CNT(2);
+ (void) simple_mdio_write(cphy,
+ MV88E1XXX_EXT_PHY_SPECIFIC_CNTRL_REGISTER, val);
+ return 0;
+}
+
+static int mv88e1xxx_interrupt_handler(struct cphy *cphy)
+{
+ int cphy_cause = 0;
+ u32 status;
+
+ /*
+ * Loop until cause reads zero. Need to handle bouncing interrupts.
+ */
+ while (1) {
+ u32 cause;
+
+ (void) simple_mdio_read(cphy,
+ MV88E1XXX_INTERRUPT_STATUS_REGISTER,
+ &cause);
+ cause &= INTR_ENABLE_MASK;
+ if (!cause) break;
+
+ if (cause & MV88E1XXX_INTR_LINK_CHNG) {
+ (void) simple_mdio_read(cphy,
+ MV88E1XXX_SPECIFIC_STATUS_REGISTER, &status);
+
+ if (status & MV88E1XXX_INTR_LINK_CHNG) {
+ cphy->state |= PHY_LINK_UP;
+ } else {
+ cphy->state &= ~PHY_LINK_UP;
+ if (cphy->state & PHY_AUTONEG_EN)
+ cphy->state &= ~PHY_AUTONEG_RDY;
+ cphy_cause |= cphy_cause_link_change;
+ }
+ }
+
+ if (cause & MV88E1XXX_INTR_AUTONEG_DONE)
+ cphy->state |= PHY_AUTONEG_RDY;
+
+ if ((cphy->state & (PHY_LINK_UP | PHY_AUTONEG_RDY)) ==
+ (PHY_LINK_UP | PHY_AUTONEG_RDY))
+ cphy_cause |= cphy_cause_link_change;
+ }
+ return cphy_cause;
+}
+
+static void mv88e1xxx_destroy(struct cphy *cphy)
+{
+ kfree(cphy);
+}
+
+static struct cphy_ops mv88e1xxx_ops = {
+ .destroy = mv88e1xxx_destroy,
+ .reset = mv88e1xxx_reset,
+ .interrupt_enable = mv88e1xxx_interrupt_enable,
+ .interrupt_disable = mv88e1xxx_interrupt_disable,
+ .interrupt_clear = mv88e1xxx_interrupt_clear,
+ .interrupt_handler = mv88e1xxx_interrupt_handler,
+ .autoneg_enable = mv88e1xxx_autoneg_enable,
+ .autoneg_disable = mv88e1xxx_autoneg_disable,
+ .autoneg_restart = mv88e1xxx_autoneg_restart,
+ .advertise = mv88e1xxx_advertise,
+ .set_loopback = mv88e1xxx_set_loopback,
+ .set_speed_duplex = mv88e1xxx_set_speed_duplex,
+ .get_link_status = mv88e1xxx_get_link_status,
+};
+
+static struct cphy *mv88e1xxx_phy_create(adapter_t *adapter, int phy_addr,
+ struct mdio_ops *mdio_ops)
+{
+ struct cphy *cphy = kzalloc(sizeof(*cphy), GFP_KERNEL);
+
+ if (!cphy) return NULL;
+
+ cphy_init(cphy, adapter, phy_addr, &mv88e1xxx_ops, mdio_ops);
+
+ /* Configure particular PHY's to run in a different mode. */
+ if ((board_info(adapter)->caps & SUPPORTED_TP) &&
+ board_info(adapter)->chip_phy == CHBT_PHY_88E1111) {
+ /*
+ * Configure the PHY transmitter as class A to reduce EMI.
+ */
+ (void) simple_mdio_write(cphy,
+ MV88E1XXX_EXTENDED_ADDR_REGISTER, 0xB);
+ (void) simple_mdio_write(cphy,
+ MV88E1XXX_EXTENDED_REGISTER, 0x8004);
+ }
+ (void) mv88e1xxx_downshift_set(cphy, 1); /* Enable downshift */
+
+ /* LED */
+ if (is_T2(adapter)) {
+ (void) simple_mdio_write(cphy,
+ MV88E1XXX_LED_CONTROL_REGISTER, 0x1);
+ }
+
+ return cphy;
+}
+
+static int mv88e1xxx_phy_reset(adapter_t* adapter)
+{
+ return 0;
+}
+
+struct gphy t1_mv88e1xxx_ops = {
+ mv88e1xxx_phy_create,
+ mv88e1xxx_phy_reset
+};
diff --git a/drivers/net/chelsio/mv88e1xxx.h b/drivers/net/chelsio/mv88e1xxx.h
new file mode 100644
index 000000000000..967cc4286359
--- /dev/null
+++ b/drivers/net/chelsio/mv88e1xxx.h
@@ -0,0 +1,127 @@
+/* $Date: 2005/03/07 23:59:05 $ $RCSfile: mv88e1xxx.h,v $ $Revision: 1.13 $ */
+#ifndef CHELSIO_MV8E1XXX_H
+#define CHELSIO_MV8E1XXX_H
+
+#ifndef BMCR_SPEED1000
+# define BMCR_SPEED1000 0x40
+#endif
+
+#ifndef ADVERTISE_PAUSE
+# define ADVERTISE_PAUSE 0x400
+#endif
+#ifndef ADVERTISE_PAUSE_ASYM
+# define ADVERTISE_PAUSE_ASYM 0x800
+#endif
+
+/* Gigabit MII registers */
+#define MII_GBCR 9 /* 1000Base-T control register */
+#define MII_GBSR 10 /* 1000Base-T status register */
+
+/* 1000Base-T control register fields */
+#define GBCR_ADV_1000HALF 0x100
+#define GBCR_ADV_1000FULL 0x200
+#define GBCR_PREFER_MASTER 0x400
+#define GBCR_MANUAL_AS_MASTER 0x800
+#define GBCR_MANUAL_CONFIG_ENABLE 0x1000
+
+/* 1000Base-T status register fields */
+#define GBSR_LP_1000HALF 0x400
+#define GBSR_LP_1000FULL 0x800
+#define GBSR_REMOTE_OK 0x1000
+#define GBSR_LOCAL_OK 0x2000
+#define GBSR_LOCAL_MASTER 0x4000
+#define GBSR_MASTER_FAULT 0x8000
+
+/* Marvell PHY interrupt status bits. */
+#define MV88E1XXX_INTR_JABBER 0x0001
+#define MV88E1XXX_INTR_POLARITY_CHNG 0x0002
+#define MV88E1XXX_INTR_ENG_DETECT_CHNG 0x0010
+#define MV88E1XXX_INTR_DOWNSHIFT 0x0020
+#define MV88E1XXX_INTR_MDI_XOVER_CHNG 0x0040
+#define MV88E1XXX_INTR_FIFO_OVER_UNDER 0x0080
+#define MV88E1XXX_INTR_FALSE_CARRIER 0x0100
+#define MV88E1XXX_INTR_SYMBOL_ERROR 0x0200
+#define MV88E1XXX_INTR_LINK_CHNG 0x0400
+#define MV88E1XXX_INTR_AUTONEG_DONE 0x0800
+#define MV88E1XXX_INTR_PAGE_RECV 0x1000
+#define MV88E1XXX_INTR_DUPLEX_CHNG 0x2000
+#define MV88E1XXX_INTR_SPEED_CHNG 0x4000
+#define MV88E1XXX_INTR_AUTONEG_ERR 0x8000
+
+/* Marvell PHY specific registers. */
+#define MV88E1XXX_SPECIFIC_CNTRL_REGISTER 16
+#define MV88E1XXX_SPECIFIC_STATUS_REGISTER 17
+#define MV88E1XXX_INTERRUPT_ENABLE_REGISTER 18
+#define MV88E1XXX_INTERRUPT_STATUS_REGISTER 19
+#define MV88E1XXX_EXT_PHY_SPECIFIC_CNTRL_REGISTER 20
+#define MV88E1XXX_RECV_ERR_CNTR_REGISTER 21
+#define MV88E1XXX_RES_REGISTER 22
+#define MV88E1XXX_GLOBAL_STATUS_REGISTER 23
+#define MV88E1XXX_LED_CONTROL_REGISTER 24
+#define MV88E1XXX_MANUAL_LED_OVERRIDE_REGISTER 25
+#define MV88E1XXX_EXT_PHY_SPECIFIC_CNTRL_2_REGISTER 26
+#define MV88E1XXX_EXT_PHY_SPECIFIC_STATUS_REGISTER 27
+#define MV88E1XXX_VIRTUAL_CABLE_TESTER_REGISTER 28
+#define MV88E1XXX_EXTENDED_ADDR_REGISTER 29
+#define MV88E1XXX_EXTENDED_REGISTER 30
+
+/* PHY specific control register fields */
+#define S_PSCR_MDI_XOVER_MODE 5
+#define M_PSCR_MDI_XOVER_MODE 0x3
+#define V_PSCR_MDI_XOVER_MODE(x) ((x) << S_PSCR_MDI_XOVER_MODE)
+#define G_PSCR_MDI_XOVER_MODE(x) (((x) >> S_PSCR_MDI_XOVER_MODE) & M_PSCR_MDI_XOVER_MODE)
+
+/* Extended PHY specific control register fields */
+#define S_DOWNSHIFT_ENABLE 8
+#define V_DOWNSHIFT_ENABLE (1 << S_DOWNSHIFT_ENABLE)
+
+#define S_DOWNSHIFT_CNT 9
+#define M_DOWNSHIFT_CNT 0x7
+#define V_DOWNSHIFT_CNT(x) ((x) << S_DOWNSHIFT_CNT)
+#define G_DOWNSHIFT_CNT(x) (((x) >> S_DOWNSHIFT_CNT) & M_DOWNSHIFT_CNT)
+
+/* PHY specific status register fields */
+#define S_PSSR_JABBER 0
+#define V_PSSR_JABBER (1 << S_PSSR_JABBER)
+
+#define S_PSSR_POLARITY 1
+#define V_PSSR_POLARITY (1 << S_PSSR_POLARITY)
+
+#define S_PSSR_RX_PAUSE 2
+#define V_PSSR_RX_PAUSE (1 << S_PSSR_RX_PAUSE)
+
+#define S_PSSR_TX_PAUSE 3
+#define V_PSSR_TX_PAUSE (1 << S_PSSR_TX_PAUSE)
+
+#define S_PSSR_ENERGY_DETECT 4
+#define V_PSSR_ENERGY_DETECT (1 << S_PSSR_ENERGY_DETECT)
+
+#define S_PSSR_DOWNSHIFT_STATUS 5
+#define V_PSSR_DOWNSHIFT_STATUS (1 << S_PSSR_DOWNSHIFT_STATUS)
+
+#define S_PSSR_MDI 6
+#define V_PSSR_MDI (1 << S_PSSR_MDI)
+
+#define S_PSSR_CABLE_LEN 7
+#define M_PSSR_CABLE_LEN 0x7
+#define V_PSSR_CABLE_LEN(x) ((x) << S_PSSR_CABLE_LEN)
+#define G_PSSR_CABLE_LEN(x) (((x) >> S_PSSR_CABLE_LEN) & M_PSSR_CABLE_LEN)
+
+#define S_PSSR_LINK 10
+#define V_PSSR_LINK (1 << S_PSSR_LINK)
+
+#define S_PSSR_STATUS_RESOLVED 11
+#define V_PSSR_STATUS_RESOLVED (1 << S_PSSR_STATUS_RESOLVED)
+
+#define S_PSSR_PAGE_RECEIVED 12
+#define V_PSSR_PAGE_RECEIVED (1 << S_PSSR_PAGE_RECEIVED)
+
+#define S_PSSR_DUPLEX 13
+#define V_PSSR_DUPLEX (1 << S_PSSR_DUPLEX)
+
+#define S_PSSR_SPEED 14
+#define M_PSSR_SPEED 0x3
+#define V_PSSR_SPEED(x) ((x) << S_PSSR_SPEED)
+#define G_PSSR_SPEED(x) (((x) >> S_PSSR_SPEED) & M_PSSR_SPEED)
+
+#endif
diff --git a/drivers/net/chelsio/mv88x201x.c b/drivers/net/chelsio/mv88x201x.c
index db5034282782..c8e89480d906 100644
--- a/drivers/net/chelsio/mv88x201x.c
+++ b/drivers/net/chelsio/mv88x201x.c
@@ -85,29 +85,33 @@ static int mv88x201x_reset(struct cphy *cphy, int wait)
static int mv88x201x_interrupt_enable(struct cphy *cphy)
{
- u32 elmer;
-
/* Enable PHY LASI interrupts. */
mdio_write(cphy, 0x1, 0x9002, 0x1);
/* Enable Marvell interrupts through Elmer0. */
- t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer);
- elmer |= ELMER0_GP_BIT6;
- t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer);
+ if (t1_is_asic(cphy->adapter)) {
+ u32 elmer;
+
+ t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer);
+ elmer |= ELMER0_GP_BIT6;
+ t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer);
+ }
return 0;
}
static int mv88x201x_interrupt_disable(struct cphy *cphy)
{
- u32 elmer;
-
/* Disable PHY LASI interrupts. */
mdio_write(cphy, 0x1, 0x9002, 0x0);
/* Disable Marvell interrupts through Elmer0. */
- t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer);
- elmer &= ~ELMER0_GP_BIT6;
- t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer);
+ if (t1_is_asic(cphy->adapter)) {
+ u32 elmer;
+
+ t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer);
+ elmer &= ~ELMER0_GP_BIT6;
+ t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer);
+ }
return 0;
}
@@ -140,9 +144,11 @@ static int mv88x201x_interrupt_clear(struct cphy *cphy)
#endif
/* Clear Marvell interrupts through Elmer0. */
- t1_tpi_read(cphy->adapter, A_ELMER0_INT_CAUSE, &elmer);
- elmer |= ELMER0_GP_BIT6;
- t1_tpi_write(cphy->adapter, A_ELMER0_INT_CAUSE, elmer);
+ if (t1_is_asic(cphy->adapter)) {
+ t1_tpi_read(cphy->adapter, A_ELMER0_INT_CAUSE, &elmer);
+ elmer |= ELMER0_GP_BIT6;
+ t1_tpi_write(cphy->adapter, A_ELMER0_INT_CAUSE, elmer);
+ }
return 0;
}
@@ -205,11 +211,11 @@ static struct cphy *mv88x201x_phy_create(adapter_t *adapter, int phy_addr,
struct mdio_ops *mdio_ops)
{
u32 val;
- struct cphy *cphy = kmalloc(sizeof(*cphy), GFP_KERNEL);
+ struct cphy *cphy = kzalloc(sizeof(*cphy), GFP_KERNEL);
if (!cphy)
return NULL;
- memset(cphy, 0, sizeof(*cphy));
+
cphy_init(cphy, adapter, phy_addr, &mv88x201x_ops, mdio_ops);
/* Commands the PHY to enable XFP's clock. */
diff --git a/drivers/net/chelsio/my3126.c b/drivers/net/chelsio/my3126.c
new file mode 100644
index 000000000000..0b90014d5b3e
--- /dev/null
+++ b/drivers/net/chelsio/my3126.c
@@ -0,0 +1,204 @@
+/* $Date: 2005/11/12 02:13:49 $ $RCSfile: my3126.c,v $ $Revision: 1.15 $ */
+#include "cphy.h"
+#include "elmer0.h"
+#include "suni1x10gexp_regs.h"
+
+/* Port Reset */
+static int my3126_reset(struct cphy *cphy, int wait)
+{
+ /*
+ * This can be done through registers. It is not required since
+ * a full chip reset is used.
+ */
+ return (0);
+}
+
+static int my3126_interrupt_enable(struct cphy *cphy)
+{
+ schedule_delayed_work(&cphy->phy_update, HZ/30);
+ t1_tpi_read(cphy->adapter, A_ELMER0_GPO, &cphy->elmer_gpo);
+ return (0);
+}
+
+static int my3126_interrupt_disable(struct cphy *cphy)
+{
+ cancel_rearming_delayed_work(&cphy->phy_update);
+ return (0);
+}
+
+static int my3126_interrupt_clear(struct cphy *cphy)
+{
+ return (0);
+}
+
+#define OFFSET(REG_ADDR) (REG_ADDR << 2)
+
+static int my3126_interrupt_handler(struct cphy *cphy)
+{
+ u32 val;
+ u16 val16;
+ u16 status;
+ u32 act_count;
+ adapter_t *adapter;
+ adapter = cphy->adapter;
+
+ if (cphy->count == 50) {
+ mdio_read(cphy, 0x1, 0x1, &val);
+ val16 = (u16) val;
+ status = cphy->bmsr ^ val16;
+
+ if (status & BMSR_LSTATUS)
+ t1_link_changed(adapter, 0);
+ cphy->bmsr = val16;
+
+ /* We have only enabled link change interrupts so it
+ must be that
+ */
+ cphy->count = 0;
+ }
+
+ t1_tpi_write(adapter, OFFSET(SUNI1x10GEXP_REG_MSTAT_CONTROL),
+ SUNI1x10GEXP_BITMSK_MSTAT_SNAP);
+ t1_tpi_read(adapter,
+ OFFSET(SUNI1x10GEXP_REG_MSTAT_COUNTER_1_LOW), &act_count);
+ t1_tpi_read(adapter,
+ OFFSET(SUNI1x10GEXP_REG_MSTAT_COUNTER_33_LOW), &val);
+ act_count += val;
+
+ /* Populate elmer_gpo with the register value */
+ t1_tpi_read(adapter, A_ELMER0_GPO, &val);
+ cphy->elmer_gpo = val;
+
+ if ( (val & (1 << 8)) || (val & (1 << 19)) ||
+ (cphy->act_count == act_count) || cphy->act_on ) {
+ if (is_T2(adapter))
+ val |= (1 << 9);
+ else if (t1_is_T1B(adapter))
+ val |= (1 << 20);
+ cphy->act_on = 0;
+ } else {
+ if (is_T2(adapter))
+ val &= ~(1 << 9);
+ else if (t1_is_T1B(adapter))
+ val &= ~(1 << 20);
+ cphy->act_on = 1;
+ }
+
+ t1_tpi_write(adapter, A_ELMER0_GPO, val);
+
+ cphy->elmer_gpo = val;
+ cphy->act_count = act_count;
+ cphy->count++;
+
+ return cphy_cause_link_change;
+}
+
+static void my3216_poll(void *arg)
+{
+ my3126_interrupt_handler(arg);
+}
+
+static int my3126_set_loopback(struct cphy *cphy, int on)
+{
+ return (0);
+}
+
+/* To check the activity LED */
+static int my3126_get_link_status(struct cphy *cphy,
+ int *link_ok, int *speed, int *duplex, int *fc)
+{
+ u32 val;
+ u16 val16;
+ adapter_t *adapter;
+
+ adapter = cphy->adapter;
+ mdio_read(cphy, 0x1, 0x1, &val);
+ val16 = (u16) val;
+
+ /* Populate elmer_gpo with the register value */
+ t1_tpi_read(adapter, A_ELMER0_GPO, &val);
+ cphy->elmer_gpo = val;
+
+ *link_ok = (val16 & BMSR_LSTATUS);
+
+ if (*link_ok) {
+ /* Turn on the LED. */
+ if (is_T2(adapter))
+ val &= ~(1 << 8);
+ else if (t1_is_T1B(adapter))
+ val &= ~(1 << 19);
+ } else {
+ /* Turn off the LED. */
+ if (is_T2(adapter))
+ val |= (1 << 8);
+ else if (t1_is_T1B(adapter))
+ val |= (1 << 19);
+ }
+
+ t1_tpi_write(adapter, A_ELMER0_GPO, val);
+ cphy->elmer_gpo = val;
+ *speed = SPEED_10000;
+ *duplex = DUPLEX_FULL;
+
+ /* need to add flow control */
+ if (fc)
+ *fc = PAUSE_RX | PAUSE_TX;
+
+ return (0);
+}
+
+static void my3126_destroy(struct cphy *cphy)
+{
+ kfree(cphy);
+}
+
+static struct cphy_ops my3126_ops = {
+ .destroy = my3126_destroy,
+ .reset = my3126_reset,
+ .interrupt_enable = my3126_interrupt_enable,
+ .interrupt_disable = my3126_interrupt_disable,
+ .interrupt_clear = my3126_interrupt_clear,
+ .interrupt_handler = my3126_interrupt_handler,
+ .get_link_status = my3126_get_link_status,
+ .set_loopback = my3126_set_loopback,
+};
+
+static struct cphy *my3126_phy_create(adapter_t *adapter,
+ int phy_addr, struct mdio_ops *mdio_ops)
+{
+ struct cphy *cphy = kzalloc(sizeof (*cphy), GFP_KERNEL);
+
+ if (cphy)
+ cphy_init(cphy, adapter, phy_addr, &my3126_ops, mdio_ops);
+
+ INIT_WORK(&cphy->phy_update, my3216_poll, cphy);
+ cphy->bmsr = 0;
+
+ return (cphy);
+}
+
+/* Chip Reset */
+static int my3126_phy_reset(adapter_t * adapter)
+{
+ u32 val;
+
+ t1_tpi_read(adapter, A_ELMER0_GPO, &val);
+ val &= ~4;
+ t1_tpi_write(adapter, A_ELMER0_GPO, val);
+ msleep(100);
+
+ t1_tpi_write(adapter, A_ELMER0_GPO, val | 4);
+ msleep(1000);
+
+ /* Now lets enable the Laser. Delay 100us */
+ t1_tpi_read(adapter, A_ELMER0_GPO, &val);
+ val |= 0x8000;
+ t1_tpi_write(adapter, A_ELMER0_GPO, val);
+ udelay(100);
+ return (0);
+}
+
+struct gphy t1_my3126_ops = {
+ my3126_phy_create,
+ my3126_phy_reset
+};
diff --git a/drivers/net/chelsio/pm3393.c b/drivers/net/chelsio/pm3393.c
index 04a1404fc65e..63cabeb98afe 100644
--- a/drivers/net/chelsio/pm3393.c
+++ b/drivers/net/chelsio/pm3393.c
@@ -43,21 +43,7 @@
#include "elmer0.h"
#include "suni1x10gexp_regs.h"
-/* 802.3ae 10Gb/s MDIO Manageable Device(MMD)
- */
-enum {
- MMD_RESERVED,
- MMD_PMAPMD,
- MMD_WIS,
- MMD_PCS,
- MMD_PHY_XGXS, /* XGMII Extender Sublayer */
- MMD_DTE_XGXS,
-};
-
-enum {
- PHY_XGXS_CTRL_1,
- PHY_XGXS_STATUS_1
-};
+#include <linux/crc32.h>
#define OFFSET(REG_ADDR) (REG_ADDR << 2)
@@ -88,6 +74,8 @@ enum { /* RMON registers */
RxJabbers = SUNI1x10GEXP_REG_MSTAT_COUNTER_16_LOW,
RxFragments = SUNI1x10GEXP_REG_MSTAT_COUNTER_17_LOW,
RxUndersizedFrames = SUNI1x10GEXP_REG_MSTAT_COUNTER_18_LOW,
+ RxJumboFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_25_LOW,
+ RxJumboOctetsReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_26_LOW,
TxOctetsTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_33_LOW,
TxFramesLostDueToInternalMACTransmissionError = SUNI1x10GEXP_REG_MSTAT_COUNTER_35_LOW,
@@ -95,7 +83,9 @@ enum { /* RMON registers */
TxUnicastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_38_LOW,
TxMulticastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_40_LOW,
TxBroadcastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_42_LOW,
- TxPAUSEMACCtrlFramesTransmitted = SUNI1x10GEXP_REG_MSTAT_COUNTER_43_LOW
+ TxPAUSEMACCtrlFramesTransmitted = SUNI1x10GEXP_REG_MSTAT_COUNTER_43_LOW,
+ TxJumboFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_51_LOW,
+ TxJumboOctetsReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_52_LOW
};
struct _cmac_instance {
@@ -124,12 +114,12 @@ static int pm3393_reset(struct cmac *cmac)
/*
* Enable interrupts for the PM3393
-
- 1. Enable PM3393 BLOCK interrupts.
- 2. Enable PM3393 Master Interrupt bit(INTE)
- 3. Enable ELMER's PM3393 bit.
- 4. Enable Terminator external interrupt.
-*/
+ *
+ * 1. Enable PM3393 BLOCK interrupts.
+ * 2. Enable PM3393 Master Interrupt bit(INTE)
+ * 3. Enable ELMER's PM3393 bit.
+ * 4. Enable Terminator external interrupt.
+ */
static int pm3393_interrupt_enable(struct cmac *cmac)
{
u32 pl_intr;
@@ -257,14 +247,12 @@ static int pm3393_interrupt_clear(struct cmac *cmac)
static int pm3393_interrupt_handler(struct cmac *cmac)
{
u32 master_intr_status;
-/*
- 1. Read master interrupt register.
- 2. Read BLOCK's interrupt status registers.
- 3. Handle BLOCK interrupts.
-*/
+
/* Read the master interrupt status register. */
pmread(cmac, SUNI1x10GEXP_REG_MASTER_INTERRUPT_STATUS,
&master_intr_status);
+ CH_DBG(cmac->adapter, INTR, "PM3393 intr cause 0x%x\n",
+ master_intr_status);
/* TBD XXX Lets just clear everything for now */
pm3393_interrupt_clear(cmac);
@@ -307,11 +295,7 @@ static int pm3393_enable_port(struct cmac *cmac, int which)
* The PHY doesn't give us link status indication on its own so have
* the link management code query it instead.
*/
- {
- extern void link_changed(adapter_t *adapter, int port_id);
-
- link_changed(cmac->adapter, 0);
- }
+ t1_link_changed(cmac->adapter, 0);
return 0;
}
@@ -363,33 +347,6 @@ static int pm3393_set_mtu(struct cmac *cmac, int mtu)
return 0;
}
-static u32 calc_crc(u8 *b, int len)
-{
- int i;
- u32 crc = (u32)~0;
-
- /* calculate crc one bit at a time */
- while (len--) {
- crc ^= *b++;
- for (i = 0; i < 8; i++) {
- if (crc & 0x1)
- crc = (crc >> 1) ^ 0xedb88320;
- else
- crc = (crc >> 1);
- }
- }
-
- /* reverse bits */
- crc = ((crc >> 4) & 0x0f0f0f0f) | ((crc << 4) & 0xf0f0f0f0);
- crc = ((crc >> 2) & 0x33333333) | ((crc << 2) & 0xcccccccc);
- crc = ((crc >> 1) & 0x55555555) | ((crc << 1) & 0xaaaaaaaa);
- /* swap bytes */
- crc = (crc >> 16) | (crc << 16);
- crc = (crc >> 8 & 0x00ff00ff) | (crc << 8 & 0xff00ff00);
-
- return crc;
-}
-
static int pm3393_set_rx_mode(struct cmac *cmac, struct t1_rx_mode *rm)
{
int enabled = cmac->instance->enabled & MAC_DIRECTION_RX;
@@ -423,7 +380,7 @@ static int pm3393_set_rx_mode(struct cmac *cmac, struct t1_rx_mode *rm)
u16 mc_filter[4] = { 0, };
while ((addr = t1_get_next_mcaddr(rm))) {
- bit = (calc_crc(addr, ETH_ALEN) >> 23) & 0x3f; /* bit[23:28] */
+ bit = (ether_crc(ETH_ALEN, addr) >> 23) & 0x3f; /* bit[23:28] */
mc_filter[bit >> 4] |= 1 << (bit & 0xf);
}
pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_LOW, mc_filter[0]);
@@ -471,20 +428,29 @@ static int pm3393_set_speed_duplex_fc(struct cmac *cmac, int speed, int duplex,
return 0;
}
+static void pm3393_rmon_update(struct adapter *adapter, u32 offs, u64 *val,
+ int over)
+{
+ u32 val0, val1, val2;
+
+ t1_tpi_read(adapter, offs, &val0);
+ t1_tpi_read(adapter, offs + 4, &val1);
+ t1_tpi_read(adapter, offs + 8, &val2);
+
+ *val &= ~0ull << 40;
+ *val |= val0 & 0xffff;
+ *val |= (val1 & 0xffff) << 16;
+ *val |= (u64)(val2 & 0xff) << 32;
+
+ if (over)
+ *val += 1ull << 40;
+}
+
#define RMON_UPDATE(mac, name, stat_name) \
- { \
- t1_tpi_read((mac)->adapter, OFFSET(name), &val0); \
- t1_tpi_read((mac)->adapter, OFFSET(((name)+1)), &val1); \
- t1_tpi_read((mac)->adapter, OFFSET(((name)+2)), &val2); \
- (mac)->stats.stat_name = ((u64)val0 & 0xffff) | \
- (((u64)val1 & 0xffff) << 16) | \
- (((u64)val2 & 0xff) << 32) | \
- ((mac)->stats.stat_name & \
- (~(u64)0 << 40)); \
- if (ro & \
- ((name - SUNI1x10GEXP_REG_MSTAT_COUNTER_0_LOW) >> 2)) \
- (mac)->stats.stat_name += ((u64)1 << 40); \
- }
+ pm3393_rmon_update((mac)->adapter, OFFSET(name), \
+ &(mac)->stats.stat_name, \
+ (ro &((name - SUNI1x10GEXP_REG_MSTAT_COUNTER_0_LOW) >> 2)))
+
static const struct cmac_statistics *pm3393_update_statistics(struct cmac *mac,
int flag)
@@ -519,6 +485,8 @@ static const struct cmac_statistics *pm3393_update_statistics(struct cmac *mac,
RMON_UPDATE(mac, RxJabbers, RxJabberErrors);
RMON_UPDATE(mac, RxFragments, RxRuntErrors);
RMON_UPDATE(mac, RxUndersizedFrames, RxRuntErrors);
+ RMON_UPDATE(mac, RxJumboFramesReceivedOK, RxJumboFramesOK);
+ RMON_UPDATE(mac, RxJumboOctetsReceivedOK, RxJumboOctetsOK);
/* Tx stats */
RMON_UPDATE(mac, TxOctetsTransmittedOK, TxOctetsOK);
@@ -529,6 +497,8 @@ static const struct cmac_statistics *pm3393_update_statistics(struct cmac *mac,
RMON_UPDATE(mac, TxMulticastFramesTransmittedOK, TxMulticastFramesOK);
RMON_UPDATE(mac, TxBroadcastFramesTransmittedOK, TxBroadcastFramesOK);
RMON_UPDATE(mac, TxPAUSEMACCtrlFramesTransmitted, TxPauseFrames);
+ RMON_UPDATE(mac, TxJumboFramesReceivedOK, TxJumboFramesOK);
+ RMON_UPDATE(mac, TxJumboOctetsReceivedOK, TxJumboOctetsOK);
return &mac->stats;
}
@@ -631,10 +601,9 @@ static struct cmac *pm3393_mac_create(adapter_t *adapter, int index)
{
struct cmac *cmac;
- cmac = kmalloc(sizeof(*cmac) + sizeof(cmac_instance), GFP_KERNEL);
+ cmac = kzalloc(sizeof(*cmac) + sizeof(cmac_instance), GFP_KERNEL);
if (!cmac)
return NULL;
- memset(cmac, 0, sizeof(*cmac));
cmac->ops = &pm3393_ops;
cmac->instance = (cmac_instance *) (cmac + 1);
@@ -815,6 +784,12 @@ static int pm3393_mac_reset(adapter_t * adapter)
successful_reset = (is_pl4_reset_finished && !is_pl4_outof_lock
&& is_xaui_mabc_pll_locked);
+
+ CH_DBG(adapter, HW,
+ "PM3393 HW reset %d: pl4_reset 0x%x, val 0x%x, "
+ "is_pl4_outof_lock 0x%x, xaui_locked 0x%x\n",
+ i, is_pl4_reset_finished, val, is_pl4_outof_lock,
+ is_xaui_mabc_pll_locked);
}
return successful_reset ? 0 : 1;
}
diff --git a/drivers/net/chelsio/regs.h b/drivers/net/chelsio/regs.h
index b90e11f40d1f..c80bf4d6d0a6 100644
--- a/drivers/net/chelsio/regs.h
+++ b/drivers/net/chelsio/regs.h
@@ -71,6 +71,10 @@
#define V_CMDQ_PRIORITY(x) ((x) << S_CMDQ_PRIORITY)
#define G_CMDQ_PRIORITY(x) (((x) >> S_CMDQ_PRIORITY) & M_CMDQ_PRIORITY)
+#define S_DISABLE_CMDQ0_GTS 8
+#define V_DISABLE_CMDQ0_GTS(x) ((x) << S_DISABLE_CMDQ0_GTS)
+#define F_DISABLE_CMDQ0_GTS V_DISABLE_CMDQ0_GTS(1U)
+
#define S_DISABLE_CMDQ1_GTS 9
#define V_DISABLE_CMDQ1_GTS(x) ((x) << S_DISABLE_CMDQ1_GTS)
#define F_DISABLE_CMDQ1_GTS V_DISABLE_CMDQ1_GTS(1U)
@@ -87,12 +91,18 @@
#define V_ENABLE_BIG_ENDIAN(x) ((x) << S_ENABLE_BIG_ENDIAN)
#define F_ENABLE_BIG_ENDIAN V_ENABLE_BIG_ENDIAN(1U)
+#define S_FL_SELECTION_CRITERIA 13
+#define V_FL_SELECTION_CRITERIA(x) ((x) << S_FL_SELECTION_CRITERIA)
+#define F_FL_SELECTION_CRITERIA V_FL_SELECTION_CRITERIA(1U)
+
#define S_ISCSI_COALESCE 14
#define V_ISCSI_COALESCE(x) ((x) << S_ISCSI_COALESCE)
#define F_ISCSI_COALESCE V_ISCSI_COALESCE(1U)
#define S_RX_PKT_OFFSET 15
+#define M_RX_PKT_OFFSET 0x7
#define V_RX_PKT_OFFSET(x) ((x) << S_RX_PKT_OFFSET)
+#define G_RX_PKT_OFFSET(x) (((x) >> S_RX_PKT_OFFSET) & M_RX_PKT_OFFSET)
#define S_VLAN_XTRACT 18
#define V_VLAN_XTRACT(x) ((x) << S_VLAN_XTRACT)
@@ -108,16 +118,114 @@
#define A_SG_FL1BASELWR 0x20
#define A_SG_FL1BASEUPR 0x24
#define A_SG_CMD0SIZE 0x28
+
+#define S_CMDQ0_SIZE 0
+#define M_CMDQ0_SIZE 0x1ffff
+#define V_CMDQ0_SIZE(x) ((x) << S_CMDQ0_SIZE)
+#define G_CMDQ0_SIZE(x) (((x) >> S_CMDQ0_SIZE) & M_CMDQ0_SIZE)
+
#define A_SG_FL0SIZE 0x2c
+
+#define S_FL0_SIZE 0
+#define M_FL0_SIZE 0x1ffff
+#define V_FL0_SIZE(x) ((x) << S_FL0_SIZE)
+#define G_FL0_SIZE(x) (((x) >> S_FL0_SIZE) & M_FL0_SIZE)
+
#define A_SG_RSPSIZE 0x30
+
+#define S_RESPQ_SIZE 0
+#define M_RESPQ_SIZE 0x1ffff
+#define V_RESPQ_SIZE(x) ((x) << S_RESPQ_SIZE)
+#define G_RESPQ_SIZE(x) (((x) >> S_RESPQ_SIZE) & M_RESPQ_SIZE)
+
#define A_SG_RSPBASELWR 0x34
#define A_SG_RSPBASEUPR 0x38
#define A_SG_FLTHRESHOLD 0x3c
+
+#define S_FL_THRESHOLD 0
+#define M_FL_THRESHOLD 0xffff
+#define V_FL_THRESHOLD(x) ((x) << S_FL_THRESHOLD)
+#define G_FL_THRESHOLD(x) (((x) >> S_FL_THRESHOLD) & M_FL_THRESHOLD)
+
#define A_SG_RSPQUEUECREDIT 0x40
+
+#define S_RESPQ_CREDIT 0
+#define M_RESPQ_CREDIT 0x1ffff
+#define V_RESPQ_CREDIT(x) ((x) << S_RESPQ_CREDIT)
+#define G_RESPQ_CREDIT(x) (((x) >> S_RESPQ_CREDIT) & M_RESPQ_CREDIT)
+
#define A_SG_SLEEPING 0x48
+
+#define S_SLEEPING 0
+#define M_SLEEPING 0xffff
+#define V_SLEEPING(x) ((x) << S_SLEEPING)
+#define G_SLEEPING(x) (((x) >> S_SLEEPING) & M_SLEEPING)
+
#define A_SG_INTRTIMER 0x4c
+
+#define S_INTERRUPT_TIMER_COUNT 0
+#define M_INTERRUPT_TIMER_COUNT 0xffffff
+#define V_INTERRUPT_TIMER_COUNT(x) ((x) << S_INTERRUPT_TIMER_COUNT)
+#define G_INTERRUPT_TIMER_COUNT(x) (((x) >> S_INTERRUPT_TIMER_COUNT) & M_INTERRUPT_TIMER_COUNT)
+
+#define A_SG_CMD0PTR 0x50
+
+#define S_CMDQ0_POINTER 0
+#define M_CMDQ0_POINTER 0xffff
+#define V_CMDQ0_POINTER(x) ((x) << S_CMDQ0_POINTER)
+#define G_CMDQ0_POINTER(x) (((x) >> S_CMDQ0_POINTER) & M_CMDQ0_POINTER)
+
+#define S_CURRENT_GENERATION_BIT 16
+#define V_CURRENT_GENERATION_BIT(x) ((x) << S_CURRENT_GENERATION_BIT)
+#define F_CURRENT_GENERATION_BIT V_CURRENT_GENERATION_BIT(1U)
+
+#define A_SG_CMD1PTR 0x54
+
+#define S_CMDQ1_POINTER 0
+#define M_CMDQ1_POINTER 0xffff
+#define V_CMDQ1_POINTER(x) ((x) << S_CMDQ1_POINTER)
+#define G_CMDQ1_POINTER(x) (((x) >> S_CMDQ1_POINTER) & M_CMDQ1_POINTER)
+
+#define A_SG_FL0PTR 0x58
+
+#define S_FL0_POINTER 0
+#define M_FL0_POINTER 0xffff
+#define V_FL0_POINTER(x) ((x) << S_FL0_POINTER)
+#define G_FL0_POINTER(x) (((x) >> S_FL0_POINTER) & M_FL0_POINTER)
+
+#define A_SG_FL1PTR 0x5c
+
+#define S_FL1_POINTER 0
+#define M_FL1_POINTER 0xffff
+#define V_FL1_POINTER(x) ((x) << S_FL1_POINTER)
+#define G_FL1_POINTER(x) (((x) >> S_FL1_POINTER) & M_FL1_POINTER)
+
+#define A_SG_VERSION 0x6c
+
+#define S_DAY 0
+#define M_DAY 0x1f
+#define V_DAY(x) ((x) << S_DAY)
+#define G_DAY(x) (((x) >> S_DAY) & M_DAY)
+
+#define S_MONTH 5
+#define M_MONTH 0xf
+#define V_MONTH(x) ((x) << S_MONTH)
+#define G_MONTH(x) (((x) >> S_MONTH) & M_MONTH)
+
#define A_SG_CMD1SIZE 0xb0
+
+#define S_CMDQ1_SIZE 0
+#define M_CMDQ1_SIZE 0x1ffff
+#define V_CMDQ1_SIZE(x) ((x) << S_CMDQ1_SIZE)
+#define G_CMDQ1_SIZE(x) (((x) >> S_CMDQ1_SIZE) & M_CMDQ1_SIZE)
+
#define A_SG_FL1SIZE 0xb4
+
+#define S_FL1_SIZE 0
+#define M_FL1_SIZE 0x1ffff
+#define V_FL1_SIZE(x) ((x) << S_FL1_SIZE)
+#define G_FL1_SIZE(x) (((x) >> S_FL1_SIZE) & M_FL1_SIZE)
+
#define A_SG_INT_ENABLE 0xb8
#define S_RESPQ_EXHAUSTED 0
@@ -144,21 +252,369 @@
#define A_SG_RESPACCUTIMER 0xc0
/* MC3 registers */
+#define A_MC3_CFG 0x100
+
+#define S_CLK_ENABLE 0
+#define V_CLK_ENABLE(x) ((x) << S_CLK_ENABLE)
+#define F_CLK_ENABLE V_CLK_ENABLE(1U)
#define S_READY 1
#define V_READY(x) ((x) << S_READY)
#define F_READY V_READY(1U)
-/* MC4 registers */
+#define S_READ_TO_WRITE_DELAY 2
+#define M_READ_TO_WRITE_DELAY 0x7
+#define V_READ_TO_WRITE_DELAY(x) ((x) << S_READ_TO_WRITE_DELAY)
+#define G_READ_TO_WRITE_DELAY(x) (((x) >> S_READ_TO_WRITE_DELAY) & M_READ_TO_WRITE_DELAY)
+
+#define S_WRITE_TO_READ_DELAY 5
+#define M_WRITE_TO_READ_DELAY 0x7
+#define V_WRITE_TO_READ_DELAY(x) ((x) << S_WRITE_TO_READ_DELAY)
+#define G_WRITE_TO_READ_DELAY(x) (((x) >> S_WRITE_TO_READ_DELAY) & M_WRITE_TO_READ_DELAY)
+#define S_MC3_BANK_CYCLE 8
+#define M_MC3_BANK_CYCLE 0xf
+#define V_MC3_BANK_CYCLE(x) ((x) << S_MC3_BANK_CYCLE)
+#define G_MC3_BANK_CYCLE(x) (((x) >> S_MC3_BANK_CYCLE) & M_MC3_BANK_CYCLE)
+
+#define S_REFRESH_CYCLE 12
+#define M_REFRESH_CYCLE 0xf
+#define V_REFRESH_CYCLE(x) ((x) << S_REFRESH_CYCLE)
+#define G_REFRESH_CYCLE(x) (((x) >> S_REFRESH_CYCLE) & M_REFRESH_CYCLE)
+
+#define S_PRECHARGE_CYCLE 16
+#define M_PRECHARGE_CYCLE 0x3
+#define V_PRECHARGE_CYCLE(x) ((x) << S_PRECHARGE_CYCLE)
+#define G_PRECHARGE_CYCLE(x) (((x) >> S_PRECHARGE_CYCLE) & M_PRECHARGE_CYCLE)
+
+#define S_ACTIVE_TO_READ_WRITE_DELAY 18
+#define V_ACTIVE_TO_READ_WRITE_DELAY(x) ((x) << S_ACTIVE_TO_READ_WRITE_DELAY)
+#define F_ACTIVE_TO_READ_WRITE_DELAY V_ACTIVE_TO_READ_WRITE_DELAY(1U)
+
+#define S_ACTIVE_TO_PRECHARGE_DELAY 19
+#define M_ACTIVE_TO_PRECHARGE_DELAY 0x7
+#define V_ACTIVE_TO_PRECHARGE_DELAY(x) ((x) << S_ACTIVE_TO_PRECHARGE_DELAY)
+#define G_ACTIVE_TO_PRECHARGE_DELAY(x) (((x) >> S_ACTIVE_TO_PRECHARGE_DELAY) & M_ACTIVE_TO_PRECHARGE_DELAY)
+
+#define S_WRITE_RECOVERY_DELAY 22
+#define M_WRITE_RECOVERY_DELAY 0x3
+#define V_WRITE_RECOVERY_DELAY(x) ((x) << S_WRITE_RECOVERY_DELAY)
+#define G_WRITE_RECOVERY_DELAY(x) (((x) >> S_WRITE_RECOVERY_DELAY) & M_WRITE_RECOVERY_DELAY)
+
+#define S_DENSITY 24
+#define M_DENSITY 0x3
+#define V_DENSITY(x) ((x) << S_DENSITY)
+#define G_DENSITY(x) (((x) >> S_DENSITY) & M_DENSITY)
+
+#define S_ORGANIZATION 26
+#define V_ORGANIZATION(x) ((x) << S_ORGANIZATION)
+#define F_ORGANIZATION V_ORGANIZATION(1U)
+
+#define S_BANKS 27
+#define V_BANKS(x) ((x) << S_BANKS)
+#define F_BANKS V_BANKS(1U)
+
+#define S_UNREGISTERED 28
+#define V_UNREGISTERED(x) ((x) << S_UNREGISTERED)
+#define F_UNREGISTERED V_UNREGISTERED(1U)
+
+#define S_MC3_WIDTH 29
+#define M_MC3_WIDTH 0x3
+#define V_MC3_WIDTH(x) ((x) << S_MC3_WIDTH)
+#define G_MC3_WIDTH(x) (((x) >> S_MC3_WIDTH) & M_MC3_WIDTH)
+
+#define S_MC3_SLOW 31
+#define V_MC3_SLOW(x) ((x) << S_MC3_SLOW)
+#define F_MC3_SLOW V_MC3_SLOW(1U)
+
+#define A_MC3_MODE 0x104
+
+#define S_MC3_MODE 0
+#define M_MC3_MODE 0x3fff
+#define V_MC3_MODE(x) ((x) << S_MC3_MODE)
+#define G_MC3_MODE(x) (((x) >> S_MC3_MODE) & M_MC3_MODE)
+
+#define S_BUSY 31
+#define V_BUSY(x) ((x) << S_BUSY)
+#define F_BUSY V_BUSY(1U)
+
+#define A_MC3_EXT_MODE 0x108
+
+#define S_MC3_EXTENDED_MODE 0
+#define M_MC3_EXTENDED_MODE 0x3fff
+#define V_MC3_EXTENDED_MODE(x) ((x) << S_MC3_EXTENDED_MODE)
+#define G_MC3_EXTENDED_MODE(x) (((x) >> S_MC3_EXTENDED_MODE) & M_MC3_EXTENDED_MODE)
+
+#define A_MC3_PRECHARG 0x10c
+#define A_MC3_REFRESH 0x110
+
+#define S_REFRESH_ENABLE 0
+#define V_REFRESH_ENABLE(x) ((x) << S_REFRESH_ENABLE)
+#define F_REFRESH_ENABLE V_REFRESH_ENABLE(1U)
+
+#define S_REFRESH_DIVISOR 1
+#define M_REFRESH_DIVISOR 0x3fff
+#define V_REFRESH_DIVISOR(x) ((x) << S_REFRESH_DIVISOR)
+#define G_REFRESH_DIVISOR(x) (((x) >> S_REFRESH_DIVISOR) & M_REFRESH_DIVISOR)
+
+#define A_MC3_STROBE 0x114
+
+#define S_MASTER_DLL_RESET 0
+#define V_MASTER_DLL_RESET(x) ((x) << S_MASTER_DLL_RESET)
+#define F_MASTER_DLL_RESET V_MASTER_DLL_RESET(1U)
+
+#define S_MASTER_DLL_TAP_COUNT 1
+#define M_MASTER_DLL_TAP_COUNT 0xff
+#define V_MASTER_DLL_TAP_COUNT(x) ((x) << S_MASTER_DLL_TAP_COUNT)
+#define G_MASTER_DLL_TAP_COUNT(x) (((x) >> S_MASTER_DLL_TAP_COUNT) & M_MASTER_DLL_TAP_COUNT)
+
+#define S_MASTER_DLL_LOCKED 9
+#define V_MASTER_DLL_LOCKED(x) ((x) << S_MASTER_DLL_LOCKED)
+#define F_MASTER_DLL_LOCKED V_MASTER_DLL_LOCKED(1U)
+
+#define S_MASTER_DLL_MAX_TAP_COUNT 10
+#define V_MASTER_DLL_MAX_TAP_COUNT(x) ((x) << S_MASTER_DLL_MAX_TAP_COUNT)
+#define F_MASTER_DLL_MAX_TAP_COUNT V_MASTER_DLL_MAX_TAP_COUNT(1U)
+
+#define S_MASTER_DLL_TAP_COUNT_OFFSET 11
+#define M_MASTER_DLL_TAP_COUNT_OFFSET 0x3f
+#define V_MASTER_DLL_TAP_COUNT_OFFSET(x) ((x) << S_MASTER_DLL_TAP_COUNT_OFFSET)
+#define G_MASTER_DLL_TAP_COUNT_OFFSET(x) (((x) >> S_MASTER_DLL_TAP_COUNT_OFFSET) & M_MASTER_DLL_TAP_COUNT_OFFSET)
+
+#define S_SLAVE_DLL_RESET 11
+#define V_SLAVE_DLL_RESET(x) ((x) << S_SLAVE_DLL_RESET)
+#define F_SLAVE_DLL_RESET V_SLAVE_DLL_RESET(1U)
+
+#define S_SLAVE_DLL_DELTA 12
+#define M_SLAVE_DLL_DELTA 0xf
+#define V_SLAVE_DLL_DELTA(x) ((x) << S_SLAVE_DLL_DELTA)
+#define G_SLAVE_DLL_DELTA(x) (((x) >> S_SLAVE_DLL_DELTA) & M_SLAVE_DLL_DELTA)
+
+#define S_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT 17
+#define M_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT 0x3f
+#define V_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT(x) ((x) << S_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT)
+#define G_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT(x) (((x) >> S_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT) & M_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT)
+
+#define S_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT_ENABLE 23
+#define V_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT_ENABLE(x) ((x) << S_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT_ENABLE)
+#define F_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT_ENABLE V_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT_ENABLE(1U)
+
+#define S_SLAVE_DELAY_LINE_TAP_COUNT 24
+#define M_SLAVE_DELAY_LINE_TAP_COUNT 0x3f
+#define V_SLAVE_DELAY_LINE_TAP_COUNT(x) ((x) << S_SLAVE_DELAY_LINE_TAP_COUNT)
+#define G_SLAVE_DELAY_LINE_TAP_COUNT(x) (((x) >> S_SLAVE_DELAY_LINE_TAP_COUNT) & M_SLAVE_DELAY_LINE_TAP_COUNT)
+
+#define A_MC3_ECC_CNTL 0x118
+
+#define S_ECC_GENERATION_ENABLE 0
+#define V_ECC_GENERATION_ENABLE(x) ((x) << S_ECC_GENERATION_ENABLE)
+#define F_ECC_GENERATION_ENABLE V_ECC_GENERATION_ENABLE(1U)
+
+#define S_ECC_CHECK_ENABLE 1
+#define V_ECC_CHECK_ENABLE(x) ((x) << S_ECC_CHECK_ENABLE)
+#define F_ECC_CHECK_ENABLE V_ECC_CHECK_ENABLE(1U)
+
+#define S_CORRECTABLE_ERROR_COUNT 2
+#define M_CORRECTABLE_ERROR_COUNT 0xff
+#define V_CORRECTABLE_ERROR_COUNT(x) ((x) << S_CORRECTABLE_ERROR_COUNT)
+#define G_CORRECTABLE_ERROR_COUNT(x) (((x) >> S_CORRECTABLE_ERROR_COUNT) & M_CORRECTABLE_ERROR_COUNT)
+
+#define S_UNCORRECTABLE_ERROR_COUNT 10
+#define M_UNCORRECTABLE_ERROR_COUNT 0xff
+#define V_UNCORRECTABLE_ERROR_COUNT(x) ((x) << S_UNCORRECTABLE_ERROR_COUNT)
+#define G_UNCORRECTABLE_ERROR_COUNT(x) (((x) >> S_UNCORRECTABLE_ERROR_COUNT) & M_UNCORRECTABLE_ERROR_COUNT)
+
+#define A_MC3_CE_ADDR 0x11c
+
+#define S_MC3_CE_ADDR 4
+#define M_MC3_CE_ADDR 0xfffffff
+#define V_MC3_CE_ADDR(x) ((x) << S_MC3_CE_ADDR)
+#define G_MC3_CE_ADDR(x) (((x) >> S_MC3_CE_ADDR) & M_MC3_CE_ADDR)
+
+#define A_MC3_CE_DATA0 0x120
+#define A_MC3_CE_DATA1 0x124
+#define A_MC3_CE_DATA2 0x128
+#define A_MC3_CE_DATA3 0x12c
+#define A_MC3_CE_DATA4 0x130
+#define A_MC3_UE_ADDR 0x134
+
+#define S_MC3_UE_ADDR 4
+#define M_MC3_UE_ADDR 0xfffffff
+#define V_MC3_UE_ADDR(x) ((x) << S_MC3_UE_ADDR)
+#define G_MC3_UE_ADDR(x) (((x) >> S_MC3_UE_ADDR) & M_MC3_UE_ADDR)
+
+#define A_MC3_UE_DATA0 0x138
+#define A_MC3_UE_DATA1 0x13c
+#define A_MC3_UE_DATA2 0x140
+#define A_MC3_UE_DATA3 0x144
+#define A_MC3_UE_DATA4 0x148
+#define A_MC3_BD_ADDR 0x14c
+#define A_MC3_BD_DATA0 0x150
+#define A_MC3_BD_DATA1 0x154
+#define A_MC3_BD_DATA2 0x158
+#define A_MC3_BD_DATA3 0x15c
+#define A_MC3_BD_DATA4 0x160
+#define A_MC3_BD_OP 0x164
+
+#define S_BACK_DOOR_OPERATION 0
+#define V_BACK_DOOR_OPERATION(x) ((x) << S_BACK_DOOR_OPERATION)
+#define F_BACK_DOOR_OPERATION V_BACK_DOOR_OPERATION(1U)
+
+#define A_MC3_BIST_ADDR_BEG 0x168
+#define A_MC3_BIST_ADDR_END 0x16c
+#define A_MC3_BIST_DATA 0x170
+#define A_MC3_BIST_OP 0x174
+
+#define S_OP 0
+#define V_OP(x) ((x) << S_OP)
+#define F_OP V_OP(1U)
+
+#define S_DATA_PATTERN 1
+#define M_DATA_PATTERN 0x3
+#define V_DATA_PATTERN(x) ((x) << S_DATA_PATTERN)
+#define G_DATA_PATTERN(x) (((x) >> S_DATA_PATTERN) & M_DATA_PATTERN)
+
+#define S_CONTINUOUS 3
+#define V_CONTINUOUS(x) ((x) << S_CONTINUOUS)
+#define F_CONTINUOUS V_CONTINUOUS(1U)
+
+#define A_MC3_INT_ENABLE 0x178
+
+#define S_MC3_CORR_ERR 0
+#define V_MC3_CORR_ERR(x) ((x) << S_MC3_CORR_ERR)
+#define F_MC3_CORR_ERR V_MC3_CORR_ERR(1U)
+
+#define S_MC3_UNCORR_ERR 1
+#define V_MC3_UNCORR_ERR(x) ((x) << S_MC3_UNCORR_ERR)
+#define F_MC3_UNCORR_ERR V_MC3_UNCORR_ERR(1U)
+
+#define S_MC3_PARITY_ERR 2
+#define M_MC3_PARITY_ERR 0xff
+#define V_MC3_PARITY_ERR(x) ((x) << S_MC3_PARITY_ERR)
+#define G_MC3_PARITY_ERR(x) (((x) >> S_MC3_PARITY_ERR) & M_MC3_PARITY_ERR)
+
+#define S_MC3_ADDR_ERR 10
+#define V_MC3_ADDR_ERR(x) ((x) << S_MC3_ADDR_ERR)
+#define F_MC3_ADDR_ERR V_MC3_ADDR_ERR(1U)
+
+#define A_MC3_INT_CAUSE 0x17c
+
+/* MC4 registers */
#define A_MC4_CFG 0x180
+
+#define S_POWER_UP 0
+#define V_POWER_UP(x) ((x) << S_POWER_UP)
+#define F_POWER_UP V_POWER_UP(1U)
+
+#define S_MC4_BANK_CYCLE 8
+#define M_MC4_BANK_CYCLE 0x7
+#define V_MC4_BANK_CYCLE(x) ((x) << S_MC4_BANK_CYCLE)
+#define G_MC4_BANK_CYCLE(x) (((x) >> S_MC4_BANK_CYCLE) & M_MC4_BANK_CYCLE)
+
+#define S_MC4_NARROW 24
+#define V_MC4_NARROW(x) ((x) << S_MC4_NARROW)
+#define F_MC4_NARROW V_MC4_NARROW(1U)
+
#define S_MC4_SLOW 25
#define V_MC4_SLOW(x) ((x) << S_MC4_SLOW)
#define F_MC4_SLOW V_MC4_SLOW(1U)
-/* TPI registers */
+#define S_MC4A_WIDTH 24
+#define M_MC4A_WIDTH 0x3
+#define V_MC4A_WIDTH(x) ((x) << S_MC4A_WIDTH)
+#define G_MC4A_WIDTH(x) (((x) >> S_MC4A_WIDTH) & M_MC4A_WIDTH)
+
+#define S_MC4A_SLOW 26
+#define V_MC4A_SLOW(x) ((x) << S_MC4A_SLOW)
+#define F_MC4A_SLOW V_MC4A_SLOW(1U)
+
+#define A_MC4_MODE 0x184
+
+#define S_MC4_MODE 0
+#define M_MC4_MODE 0x7fff
+#define V_MC4_MODE(x) ((x) << S_MC4_MODE)
+#define G_MC4_MODE(x) (((x) >> S_MC4_MODE) & M_MC4_MODE)
+
+#define A_MC4_EXT_MODE 0x188
+
+#define S_MC4_EXTENDED_MODE 0
+#define M_MC4_EXTENDED_MODE 0x7fff
+#define V_MC4_EXTENDED_MODE(x) ((x) << S_MC4_EXTENDED_MODE)
+#define G_MC4_EXTENDED_MODE(x) (((x) >> S_MC4_EXTENDED_MODE) & M_MC4_EXTENDED_MODE)
+
+#define A_MC4_REFRESH 0x190
+#define A_MC4_STROBE 0x194
+#define A_MC4_ECC_CNTL 0x198
+#define A_MC4_CE_ADDR 0x19c
+
+#define S_MC4_CE_ADDR 4
+#define M_MC4_CE_ADDR 0xffffff
+#define V_MC4_CE_ADDR(x) ((x) << S_MC4_CE_ADDR)
+#define G_MC4_CE_ADDR(x) (((x) >> S_MC4_CE_ADDR) & M_MC4_CE_ADDR)
+
+#define A_MC4_CE_DATA0 0x1a0
+#define A_MC4_CE_DATA1 0x1a4
+#define A_MC4_CE_DATA2 0x1a8
+#define A_MC4_CE_DATA3 0x1ac
+#define A_MC4_CE_DATA4 0x1b0
+#define A_MC4_UE_ADDR 0x1b4
+
+#define S_MC4_UE_ADDR 4
+#define M_MC4_UE_ADDR 0xffffff
+#define V_MC4_UE_ADDR(x) ((x) << S_MC4_UE_ADDR)
+#define G_MC4_UE_ADDR(x) (((x) >> S_MC4_UE_ADDR) & M_MC4_UE_ADDR)
+
+#define A_MC4_UE_DATA0 0x1b8
+#define A_MC4_UE_DATA1 0x1bc
+#define A_MC4_UE_DATA2 0x1c0
+#define A_MC4_UE_DATA3 0x1c4
+#define A_MC4_UE_DATA4 0x1c8
+#define A_MC4_BD_ADDR 0x1cc
+
+#define S_MC4_BACK_DOOR_ADDR 0
+#define M_MC4_BACK_DOOR_ADDR 0xfffffff
+#define V_MC4_BACK_DOOR_ADDR(x) ((x) << S_MC4_BACK_DOOR_ADDR)
+#define G_MC4_BACK_DOOR_ADDR(x) (((x) >> S_MC4_BACK_DOOR_ADDR) & M_MC4_BACK_DOOR_ADDR)
+
+#define A_MC4_BD_DATA0 0x1d0
+#define A_MC4_BD_DATA1 0x1d4
+#define A_MC4_BD_DATA2 0x1d8
+#define A_MC4_BD_DATA3 0x1dc
+#define A_MC4_BD_DATA4 0x1e0
+#define A_MC4_BD_OP 0x1e4
+
+#define S_OPERATION 0
+#define V_OPERATION(x) ((x) << S_OPERATION)
+#define F_OPERATION V_OPERATION(1U)
+
+#define A_MC4_BIST_ADDR_BEG 0x1e8
+#define A_MC4_BIST_ADDR_END 0x1ec
+#define A_MC4_BIST_DATA 0x1f0
+#define A_MC4_BIST_OP 0x1f4
+#define A_MC4_INT_ENABLE 0x1f8
+
+#define S_MC4_CORR_ERR 0
+#define V_MC4_CORR_ERR(x) ((x) << S_MC4_CORR_ERR)
+#define F_MC4_CORR_ERR V_MC4_CORR_ERR(1U)
+
+#define S_MC4_UNCORR_ERR 1
+#define V_MC4_UNCORR_ERR(x) ((x) << S_MC4_UNCORR_ERR)
+#define F_MC4_UNCORR_ERR V_MC4_UNCORR_ERR(1U)
+
+#define S_MC4_ADDR_ERR 2
+#define V_MC4_ADDR_ERR(x) ((x) << S_MC4_ADDR_ERR)
+#define F_MC4_ADDR_ERR V_MC4_ADDR_ERR(1U)
+
+#define A_MC4_INT_CAUSE 0x1fc
+/* TPI registers */
#define A_TPI_ADDR 0x280
+
+#define S_TPI_ADDRESS 0
+#define M_TPI_ADDRESS 0xffffff
+#define V_TPI_ADDRESS(x) ((x) << S_TPI_ADDRESS)
+#define G_TPI_ADDRESS(x) (((x) >> S_TPI_ADDRESS) & M_TPI_ADDRESS)
+
#define A_TPI_WR_DATA 0x284
#define A_TPI_RD_DATA 0x288
#define A_TPI_CSR 0x28c
@@ -171,6 +627,10 @@
#define V_TPIRDY(x) ((x) << S_TPIRDY)
#define F_TPIRDY V_TPIRDY(1U)
+#define S_INT_DIR 31
+#define V_INT_DIR(x) ((x) << S_INT_DIR)
+#define F_INT_DIR V_INT_DIR(1U)
+
#define A_TPI_PAR 0x29c
#define S_TPIPAR 0
@@ -178,14 +638,26 @@
#define V_TPIPAR(x) ((x) << S_TPIPAR)
#define G_TPIPAR(x) (((x) >> S_TPIPAR) & M_TPIPAR)
-/* TP registers */
+/* TP registers */
#define A_TP_IN_CONFIG 0x300
+#define S_TP_IN_CSPI_TUNNEL 0
+#define V_TP_IN_CSPI_TUNNEL(x) ((x) << S_TP_IN_CSPI_TUNNEL)
+#define F_TP_IN_CSPI_TUNNEL V_TP_IN_CSPI_TUNNEL(1U)
+
+#define S_TP_IN_CSPI_ETHERNET 1
+#define V_TP_IN_CSPI_ETHERNET(x) ((x) << S_TP_IN_CSPI_ETHERNET)
+#define F_TP_IN_CSPI_ETHERNET V_TP_IN_CSPI_ETHERNET(1U)
+
#define S_TP_IN_CSPI_CPL 3
#define V_TP_IN_CSPI_CPL(x) ((x) << S_TP_IN_CSPI_CPL)
#define F_TP_IN_CSPI_CPL V_TP_IN_CSPI_CPL(1U)
+#define S_TP_IN_CSPI_POS 4
+#define V_TP_IN_CSPI_POS(x) ((x) << S_TP_IN_CSPI_POS)
+#define F_TP_IN_CSPI_POS V_TP_IN_CSPI_POS(1U)
+
#define S_TP_IN_CSPI_CHECK_IP_CSUM 5
#define V_TP_IN_CSPI_CHECK_IP_CSUM(x) ((x) << S_TP_IN_CSPI_CHECK_IP_CSUM)
#define F_TP_IN_CSPI_CHECK_IP_CSUM V_TP_IN_CSPI_CHECK_IP_CSUM(1U)
@@ -194,10 +666,22 @@
#define V_TP_IN_CSPI_CHECK_TCP_CSUM(x) ((x) << S_TP_IN_CSPI_CHECK_TCP_CSUM)
#define F_TP_IN_CSPI_CHECK_TCP_CSUM V_TP_IN_CSPI_CHECK_TCP_CSUM(1U)
+#define S_TP_IN_ESPI_TUNNEL 7
+#define V_TP_IN_ESPI_TUNNEL(x) ((x) << S_TP_IN_ESPI_TUNNEL)
+#define F_TP_IN_ESPI_TUNNEL V_TP_IN_ESPI_TUNNEL(1U)
+
#define S_TP_IN_ESPI_ETHERNET 8
#define V_TP_IN_ESPI_ETHERNET(x) ((x) << S_TP_IN_ESPI_ETHERNET)
#define F_TP_IN_ESPI_ETHERNET V_TP_IN_ESPI_ETHERNET(1U)
+#define S_TP_IN_ESPI_CPL 10
+#define V_TP_IN_ESPI_CPL(x) ((x) << S_TP_IN_ESPI_CPL)
+#define F_TP_IN_ESPI_CPL V_TP_IN_ESPI_CPL(1U)
+
+#define S_TP_IN_ESPI_POS 11
+#define V_TP_IN_ESPI_POS(x) ((x) << S_TP_IN_ESPI_POS)
+#define F_TP_IN_ESPI_POS V_TP_IN_ESPI_POS(1U)
+
#define S_TP_IN_ESPI_CHECK_IP_CSUM 12
#define V_TP_IN_ESPI_CHECK_IP_CSUM(x) ((x) << S_TP_IN_ESPI_CHECK_IP_CSUM)
#define F_TP_IN_ESPI_CHECK_IP_CSUM V_TP_IN_ESPI_CHECK_IP_CSUM(1U)
@@ -212,14 +696,42 @@
#define A_TP_OUT_CONFIG 0x304
+#define S_TP_OUT_C_ETH 0
+#define V_TP_OUT_C_ETH(x) ((x) << S_TP_OUT_C_ETH)
+#define F_TP_OUT_C_ETH V_TP_OUT_C_ETH(1U)
+
#define S_TP_OUT_CSPI_CPL 2
#define V_TP_OUT_CSPI_CPL(x) ((x) << S_TP_OUT_CSPI_CPL)
#define F_TP_OUT_CSPI_CPL V_TP_OUT_CSPI_CPL(1U)
+#define S_TP_OUT_CSPI_POS 3
+#define V_TP_OUT_CSPI_POS(x) ((x) << S_TP_OUT_CSPI_POS)
+#define F_TP_OUT_CSPI_POS V_TP_OUT_CSPI_POS(1U)
+
+#define S_TP_OUT_CSPI_GENERATE_IP_CSUM 4
+#define V_TP_OUT_CSPI_GENERATE_IP_CSUM(x) ((x) << S_TP_OUT_CSPI_GENERATE_IP_CSUM)
+#define F_TP_OUT_CSPI_GENERATE_IP_CSUM V_TP_OUT_CSPI_GENERATE_IP_CSUM(1U)
+
+#define S_TP_OUT_CSPI_GENERATE_TCP_CSUM 5
+#define V_TP_OUT_CSPI_GENERATE_TCP_CSUM(x) ((x) << S_TP_OUT_CSPI_GENERATE_TCP_CSUM)
+#define F_TP_OUT_CSPI_GENERATE_TCP_CSUM V_TP_OUT_CSPI_GENERATE_TCP_CSUM(1U)
+
#define S_TP_OUT_ESPI_ETHERNET 6
#define V_TP_OUT_ESPI_ETHERNET(x) ((x) << S_TP_OUT_ESPI_ETHERNET)
#define F_TP_OUT_ESPI_ETHERNET V_TP_OUT_ESPI_ETHERNET(1U)
+#define S_TP_OUT_ESPI_TAG_ETHERNET 7
+#define V_TP_OUT_ESPI_TAG_ETHERNET(x) ((x) << S_TP_OUT_ESPI_TAG_ETHERNET)
+#define F_TP_OUT_ESPI_TAG_ETHERNET V_TP_OUT_ESPI_TAG_ETHERNET(1U)
+
+#define S_TP_OUT_ESPI_CPL 8
+#define V_TP_OUT_ESPI_CPL(x) ((x) << S_TP_OUT_ESPI_CPL)
+#define F_TP_OUT_ESPI_CPL V_TP_OUT_ESPI_CPL(1U)
+
+#define S_TP_OUT_ESPI_POS 9
+#define V_TP_OUT_ESPI_POS(x) ((x) << S_TP_OUT_ESPI_POS)
+#define F_TP_OUT_ESPI_POS V_TP_OUT_ESPI_POS(1U)
+
#define S_TP_OUT_ESPI_GENERATE_IP_CSUM 10
#define V_TP_OUT_ESPI_GENERATE_IP_CSUM(x) ((x) << S_TP_OUT_ESPI_GENERATE_IP_CSUM)
#define F_TP_OUT_ESPI_GENERATE_IP_CSUM V_TP_OUT_ESPI_GENERATE_IP_CSUM(1U)
@@ -233,6 +745,16 @@
#define S_IP_TTL 0
#define M_IP_TTL 0xff
#define V_IP_TTL(x) ((x) << S_IP_TTL)
+#define G_IP_TTL(x) (((x) >> S_IP_TTL) & M_IP_TTL)
+
+#define S_TCAM_SERVER_REGION_USAGE 8
+#define M_TCAM_SERVER_REGION_USAGE 0x3
+#define V_TCAM_SERVER_REGION_USAGE(x) ((x) << S_TCAM_SERVER_REGION_USAGE)
+#define G_TCAM_SERVER_REGION_USAGE(x) (((x) >> S_TCAM_SERVER_REGION_USAGE) & M_TCAM_SERVER_REGION_USAGE)
+
+#define S_QOS_MAPPING 10
+#define V_QOS_MAPPING(x) ((x) << S_QOS_MAPPING)
+#define F_QOS_MAPPING V_QOS_MAPPING(1U)
#define S_TCP_CSUM 11
#define V_TCP_CSUM(x) ((x) << S_TCP_CSUM)
@@ -246,31 +768,476 @@
#define V_IP_CSUM(x) ((x) << S_IP_CSUM)
#define F_IP_CSUM V_IP_CSUM(1U)
+#define S_IP_ID_SPLIT 14
+#define V_IP_ID_SPLIT(x) ((x) << S_IP_ID_SPLIT)
+#define F_IP_ID_SPLIT V_IP_ID_SPLIT(1U)
+
#define S_PATH_MTU 15
#define V_PATH_MTU(x) ((x) << S_PATH_MTU)
#define F_PATH_MTU V_PATH_MTU(1U)
#define S_5TUPLE_LOOKUP 17
+#define M_5TUPLE_LOOKUP 0x3
#define V_5TUPLE_LOOKUP(x) ((x) << S_5TUPLE_LOOKUP)
+#define G_5TUPLE_LOOKUP(x) (((x) >> S_5TUPLE_LOOKUP) & M_5TUPLE_LOOKUP)
+
+#define S_IP_FRAGMENT_DROP 19
+#define V_IP_FRAGMENT_DROP(x) ((x) << S_IP_FRAGMENT_DROP)
+#define F_IP_FRAGMENT_DROP V_IP_FRAGMENT_DROP(1U)
+
+#define S_PING_DROP 20
+#define V_PING_DROP(x) ((x) << S_PING_DROP)
+#define F_PING_DROP V_PING_DROP(1U)
+
+#define S_PROTECT_MODE 21
+#define V_PROTECT_MODE(x) ((x) << S_PROTECT_MODE)
+#define F_PROTECT_MODE V_PROTECT_MODE(1U)
+
+#define S_SYN_COOKIE_ALGORITHM 22
+#define V_SYN_COOKIE_ALGORITHM(x) ((x) << S_SYN_COOKIE_ALGORITHM)
+#define F_SYN_COOKIE_ALGORITHM V_SYN_COOKIE_ALGORITHM(1U)
+
+#define S_ATTACK_FILTER 23
+#define V_ATTACK_FILTER(x) ((x) << S_ATTACK_FILTER)
+#define F_ATTACK_FILTER V_ATTACK_FILTER(1U)
+
+#define S_INTERFACE_TYPE 24
+#define V_INTERFACE_TYPE(x) ((x) << S_INTERFACE_TYPE)
+#define F_INTERFACE_TYPE V_INTERFACE_TYPE(1U)
+
+#define S_DISABLE_RX_FLOW_CONTROL 25
+#define V_DISABLE_RX_FLOW_CONTROL(x) ((x) << S_DISABLE_RX_FLOW_CONTROL)
+#define F_DISABLE_RX_FLOW_CONTROL V_DISABLE_RX_FLOW_CONTROL(1U)
#define S_SYN_COOKIE_PARAMETER 26
+#define M_SYN_COOKIE_PARAMETER 0x3f
#define V_SYN_COOKIE_PARAMETER(x) ((x) << S_SYN_COOKIE_PARAMETER)
+#define G_SYN_COOKIE_PARAMETER(x) (((x) >> S_SYN_COOKIE_PARAMETER) & M_SYN_COOKIE_PARAMETER)
+
+#define A_TP_GLOBAL_RX_CREDITS 0x30c
+#define A_TP_CM_SIZE 0x310
+#define A_TP_CM_MM_BASE 0x314
+
+#define S_CM_MEMMGR_BASE 0
+#define M_CM_MEMMGR_BASE 0xfffffff
+#define V_CM_MEMMGR_BASE(x) ((x) << S_CM_MEMMGR_BASE)
+#define G_CM_MEMMGR_BASE(x) (((x) >> S_CM_MEMMGR_BASE) & M_CM_MEMMGR_BASE)
+
+#define A_TP_CM_TIMER_BASE 0x318
+
+#define S_CM_TIMER_BASE 0
+#define M_CM_TIMER_BASE 0xfffffff
+#define V_CM_TIMER_BASE(x) ((x) << S_CM_TIMER_BASE)
+#define G_CM_TIMER_BASE(x) (((x) >> S_CM_TIMER_BASE) & M_CM_TIMER_BASE)
+
+#define A_TP_PM_SIZE 0x31c
+#define A_TP_PM_TX_BASE 0x320
+#define A_TP_PM_DEFRAG_BASE 0x324
+#define A_TP_PM_RX_BASE 0x328
+#define A_TP_PM_RX_PG_SIZE 0x32c
+#define A_TP_PM_RX_MAX_PGS 0x330
+#define A_TP_PM_TX_PG_SIZE 0x334
+#define A_TP_PM_TX_MAX_PGS 0x338
+#define A_TP_TCP_OPTIONS 0x340
+
+#define S_TIMESTAMP 0
+#define M_TIMESTAMP 0x3
+#define V_TIMESTAMP(x) ((x) << S_TIMESTAMP)
+#define G_TIMESTAMP(x) (((x) >> S_TIMESTAMP) & M_TIMESTAMP)
+
+#define S_WINDOW_SCALE 2
+#define M_WINDOW_SCALE 0x3
+#define V_WINDOW_SCALE(x) ((x) << S_WINDOW_SCALE)
+#define G_WINDOW_SCALE(x) (((x) >> S_WINDOW_SCALE) & M_WINDOW_SCALE)
+
+#define S_SACK 4
+#define M_SACK 0x3
+#define V_SACK(x) ((x) << S_SACK)
+#define G_SACK(x) (((x) >> S_SACK) & M_SACK)
+
+#define S_ECN 6
+#define M_ECN 0x3
+#define V_ECN(x) ((x) << S_ECN)
+#define G_ECN(x) (((x) >> S_ECN) & M_ECN)
+
+#define S_SACK_ALGORITHM 8
+#define M_SACK_ALGORITHM 0x3
+#define V_SACK_ALGORITHM(x) ((x) << S_SACK_ALGORITHM)
+#define G_SACK_ALGORITHM(x) (((x) >> S_SACK_ALGORITHM) & M_SACK_ALGORITHM)
+
+#define S_MSS 10
+#define V_MSS(x) ((x) << S_MSS)
+#define F_MSS V_MSS(1U)
+
+#define S_DEFAULT_PEER_MSS 16
+#define M_DEFAULT_PEER_MSS 0xffff
+#define V_DEFAULT_PEER_MSS(x) ((x) << S_DEFAULT_PEER_MSS)
+#define G_DEFAULT_PEER_MSS(x) (((x) >> S_DEFAULT_PEER_MSS) & M_DEFAULT_PEER_MSS)
+
+#define A_TP_DACK_CONFIG 0x344
+
+#define S_DACK_MODE 0
+#define V_DACK_MODE(x) ((x) << S_DACK_MODE)
+#define F_DACK_MODE V_DACK_MODE(1U)
+
+#define S_DACK_AUTO_MGMT 1
+#define V_DACK_AUTO_MGMT(x) ((x) << S_DACK_AUTO_MGMT)
+#define F_DACK_AUTO_MGMT V_DACK_AUTO_MGMT(1U)
+
+#define S_DACK_AUTO_CAREFUL 2
+#define V_DACK_AUTO_CAREFUL(x) ((x) << S_DACK_AUTO_CAREFUL)
+#define F_DACK_AUTO_CAREFUL V_DACK_AUTO_CAREFUL(1U)
+
+#define S_DACK_MSS_SELECTOR 3
+#define M_DACK_MSS_SELECTOR 0x3
+#define V_DACK_MSS_SELECTOR(x) ((x) << S_DACK_MSS_SELECTOR)
+#define G_DACK_MSS_SELECTOR(x) (((x) >> S_DACK_MSS_SELECTOR) & M_DACK_MSS_SELECTOR)
+
+#define S_DACK_BYTE_THRESHOLD 5
+#define M_DACK_BYTE_THRESHOLD 0xfffff
+#define V_DACK_BYTE_THRESHOLD(x) ((x) << S_DACK_BYTE_THRESHOLD)
+#define G_DACK_BYTE_THRESHOLD(x) (((x) >> S_DACK_BYTE_THRESHOLD) & M_DACK_BYTE_THRESHOLD)
#define A_TP_PC_CONFIG 0x348
+
+#define S_TP_ACCESS_LATENCY 0
+#define M_TP_ACCESS_LATENCY 0xf
+#define V_TP_ACCESS_LATENCY(x) ((x) << S_TP_ACCESS_LATENCY)
+#define G_TP_ACCESS_LATENCY(x) (((x) >> S_TP_ACCESS_LATENCY) & M_TP_ACCESS_LATENCY)
+
+#define S_HELD_FIN_DISABLE 4
+#define V_HELD_FIN_DISABLE(x) ((x) << S_HELD_FIN_DISABLE)
+#define F_HELD_FIN_DISABLE V_HELD_FIN_DISABLE(1U)
+
+#define S_DDP_FC_ENABLE 5
+#define V_DDP_FC_ENABLE(x) ((x) << S_DDP_FC_ENABLE)
+#define F_DDP_FC_ENABLE V_DDP_FC_ENABLE(1U)
+
+#define S_RDMA_ERR_ENABLE 6
+#define V_RDMA_ERR_ENABLE(x) ((x) << S_RDMA_ERR_ENABLE)
+#define F_RDMA_ERR_ENABLE V_RDMA_ERR_ENABLE(1U)
+
+#define S_FAST_PDU_DELIVERY 7
+#define V_FAST_PDU_DELIVERY(x) ((x) << S_FAST_PDU_DELIVERY)
+#define F_FAST_PDU_DELIVERY V_FAST_PDU_DELIVERY(1U)
+
+#define S_CLEAR_FIN 8
+#define V_CLEAR_FIN(x) ((x) << S_CLEAR_FIN)
+#define F_CLEAR_FIN V_CLEAR_FIN(1U)
+
#define S_DIS_TX_FILL_WIN_PUSH 12
#define V_DIS_TX_FILL_WIN_PUSH(x) ((x) << S_DIS_TX_FILL_WIN_PUSH)
#define F_DIS_TX_FILL_WIN_PUSH V_DIS_TX_FILL_WIN_PUSH(1U)
#define S_TP_PC_REV 30
#define M_TP_PC_REV 0x3
+#define V_TP_PC_REV(x) ((x) << S_TP_PC_REV)
#define G_TP_PC_REV(x) (((x) >> S_TP_PC_REV) & M_TP_PC_REV)
+
+#define A_TP_BACKOFF0 0x350
+
+#define S_ELEMENT0 0
+#define M_ELEMENT0 0xff
+#define V_ELEMENT0(x) ((x) << S_ELEMENT0)
+#define G_ELEMENT0(x) (((x) >> S_ELEMENT0) & M_ELEMENT0)
+
+#define S_ELEMENT1 8
+#define M_ELEMENT1 0xff
+#define V_ELEMENT1(x) ((x) << S_ELEMENT1)
+#define G_ELEMENT1(x) (((x) >> S_ELEMENT1) & M_ELEMENT1)
+
+#define S_ELEMENT2 16
+#define M_ELEMENT2 0xff
+#define V_ELEMENT2(x) ((x) << S_ELEMENT2)
+#define G_ELEMENT2(x) (((x) >> S_ELEMENT2) & M_ELEMENT2)
+
+#define S_ELEMENT3 24
+#define M_ELEMENT3 0xff
+#define V_ELEMENT3(x) ((x) << S_ELEMENT3)
+#define G_ELEMENT3(x) (((x) >> S_ELEMENT3) & M_ELEMENT3)
+
+#define A_TP_BACKOFF1 0x354
+#define A_TP_BACKOFF2 0x358
+#define A_TP_BACKOFF3 0x35c
+#define A_TP_PARA_REG0 0x360
+
+#define S_VAR_MULT 0
+#define M_VAR_MULT 0xf
+#define V_VAR_MULT(x) ((x) << S_VAR_MULT)
+#define G_VAR_MULT(x) (((x) >> S_VAR_MULT) & M_VAR_MULT)
+
+#define S_VAR_GAIN 4
+#define M_VAR_GAIN 0xf
+#define V_VAR_GAIN(x) ((x) << S_VAR_GAIN)
+#define G_VAR_GAIN(x) (((x) >> S_VAR_GAIN) & M_VAR_GAIN)
+
+#define S_SRTT_GAIN 8
+#define M_SRTT_GAIN 0xf
+#define V_SRTT_GAIN(x) ((x) << S_SRTT_GAIN)
+#define G_SRTT_GAIN(x) (((x) >> S_SRTT_GAIN) & M_SRTT_GAIN)
+
+#define S_RTTVAR_INIT 12
+#define M_RTTVAR_INIT 0xf
+#define V_RTTVAR_INIT(x) ((x) << S_RTTVAR_INIT)
+#define G_RTTVAR_INIT(x) (((x) >> S_RTTVAR_INIT) & M_RTTVAR_INIT)
+
+#define S_DUP_THRESH 20
+#define M_DUP_THRESH 0xf
+#define V_DUP_THRESH(x) ((x) << S_DUP_THRESH)
+#define G_DUP_THRESH(x) (((x) >> S_DUP_THRESH) & M_DUP_THRESH)
+
+#define S_INIT_CONG_WIN 24
+#define M_INIT_CONG_WIN 0x7
+#define V_INIT_CONG_WIN(x) ((x) << S_INIT_CONG_WIN)
+#define G_INIT_CONG_WIN(x) (((x) >> S_INIT_CONG_WIN) & M_INIT_CONG_WIN)
+
+#define A_TP_PARA_REG1 0x364
+
+#define S_INITIAL_SLOW_START_THRESHOLD 0
+#define M_INITIAL_SLOW_START_THRESHOLD 0xffff
+#define V_INITIAL_SLOW_START_THRESHOLD(x) ((x) << S_INITIAL_SLOW_START_THRESHOLD)
+#define G_INITIAL_SLOW_START_THRESHOLD(x) (((x) >> S_INITIAL_SLOW_START_THRESHOLD) & M_INITIAL_SLOW_START_THRESHOLD)
+
+#define S_RECEIVE_BUFFER_SIZE 16
+#define M_RECEIVE_BUFFER_SIZE 0xffff
+#define V_RECEIVE_BUFFER_SIZE(x) ((x) << S_RECEIVE_BUFFER_SIZE)
+#define G_RECEIVE_BUFFER_SIZE(x) (((x) >> S_RECEIVE_BUFFER_SIZE) & M_RECEIVE_BUFFER_SIZE)
+
+#define A_TP_PARA_REG2 0x368
+
+#define S_RX_COALESCE_SIZE 0
+#define M_RX_COALESCE_SIZE 0xffff
+#define V_RX_COALESCE_SIZE(x) ((x) << S_RX_COALESCE_SIZE)
+#define G_RX_COALESCE_SIZE(x) (((x) >> S_RX_COALESCE_SIZE) & M_RX_COALESCE_SIZE)
+
+#define S_MAX_RX_SIZE 16
+#define M_MAX_RX_SIZE 0xffff
+#define V_MAX_RX_SIZE(x) ((x) << S_MAX_RX_SIZE)
+#define G_MAX_RX_SIZE(x) (((x) >> S_MAX_RX_SIZE) & M_MAX_RX_SIZE)
+
+#define A_TP_PARA_REG3 0x36c
+
+#define S_RX_COALESCING_PSH_DELIVER 0
+#define V_RX_COALESCING_PSH_DELIVER(x) ((x) << S_RX_COALESCING_PSH_DELIVER)
+#define F_RX_COALESCING_PSH_DELIVER V_RX_COALESCING_PSH_DELIVER(1U)
+
+#define S_RX_COALESCING_ENABLE 1
+#define V_RX_COALESCING_ENABLE(x) ((x) << S_RX_COALESCING_ENABLE)
+#define F_RX_COALESCING_ENABLE V_RX_COALESCING_ENABLE(1U)
+
+#define S_TAHOE_ENABLE 2
+#define V_TAHOE_ENABLE(x) ((x) << S_TAHOE_ENABLE)
+#define F_TAHOE_ENABLE V_TAHOE_ENABLE(1U)
+
+#define S_MAX_REORDER_FRAGMENTS 12
+#define M_MAX_REORDER_FRAGMENTS 0x7
+#define V_MAX_REORDER_FRAGMENTS(x) ((x) << S_MAX_REORDER_FRAGMENTS)
+#define G_MAX_REORDER_FRAGMENTS(x) (((x) >> S_MAX_REORDER_FRAGMENTS) & M_MAX_REORDER_FRAGMENTS)
+
+#define A_TP_TIMER_RESOLUTION 0x390
+
+#define S_DELAYED_ACK_TIMER_RESOLUTION 0
+#define M_DELAYED_ACK_TIMER_RESOLUTION 0x3f
+#define V_DELAYED_ACK_TIMER_RESOLUTION(x) ((x) << S_DELAYED_ACK_TIMER_RESOLUTION)
+#define G_DELAYED_ACK_TIMER_RESOLUTION(x) (((x) >> S_DELAYED_ACK_TIMER_RESOLUTION) & M_DELAYED_ACK_TIMER_RESOLUTION)
+
+#define S_GENERIC_TIMER_RESOLUTION 16
+#define M_GENERIC_TIMER_RESOLUTION 0x3f
+#define V_GENERIC_TIMER_RESOLUTION(x) ((x) << S_GENERIC_TIMER_RESOLUTION)
+#define G_GENERIC_TIMER_RESOLUTION(x) (((x) >> S_GENERIC_TIMER_RESOLUTION) & M_GENERIC_TIMER_RESOLUTION)
+
+#define A_TP_2MSL 0x394
+
+#define S_2MSL 0
+#define M_2MSL 0x3fffffff
+#define V_2MSL(x) ((x) << S_2MSL)
+#define G_2MSL(x) (((x) >> S_2MSL) & M_2MSL)
+
+#define A_TP_RXT_MIN 0x398
+
+#define S_RETRANSMIT_TIMER_MIN 0
+#define M_RETRANSMIT_TIMER_MIN 0xffff
+#define V_RETRANSMIT_TIMER_MIN(x) ((x) << S_RETRANSMIT_TIMER_MIN)
+#define G_RETRANSMIT_TIMER_MIN(x) (((x) >> S_RETRANSMIT_TIMER_MIN) & M_RETRANSMIT_TIMER_MIN)
+
+#define A_TP_RXT_MAX 0x39c
+
+#define S_RETRANSMIT_TIMER_MAX 0
+#define M_RETRANSMIT_TIMER_MAX 0x3fffffff
+#define V_RETRANSMIT_TIMER_MAX(x) ((x) << S_RETRANSMIT_TIMER_MAX)
+#define G_RETRANSMIT_TIMER_MAX(x) (((x) >> S_RETRANSMIT_TIMER_MAX) & M_RETRANSMIT_TIMER_MAX)
+
+#define A_TP_PERS_MIN 0x3a0
+
+#define S_PERSIST_TIMER_MIN 0
+#define M_PERSIST_TIMER_MIN 0xffff
+#define V_PERSIST_TIMER_MIN(x) ((x) << S_PERSIST_TIMER_MIN)
+#define G_PERSIST_TIMER_MIN(x) (((x) >> S_PERSIST_TIMER_MIN) & M_PERSIST_TIMER_MIN)
+
+#define A_TP_PERS_MAX 0x3a4
+
+#define S_PERSIST_TIMER_MAX 0
+#define M_PERSIST_TIMER_MAX 0x3fffffff
+#define V_PERSIST_TIMER_MAX(x) ((x) << S_PERSIST_TIMER_MAX)
+#define G_PERSIST_TIMER_MAX(x) (((x) >> S_PERSIST_TIMER_MAX) & M_PERSIST_TIMER_MAX)
+
+#define A_TP_KEEP_IDLE 0x3ac
+
+#define S_KEEP_ALIVE_IDLE_TIME 0
+#define M_KEEP_ALIVE_IDLE_TIME 0x3fffffff
+#define V_KEEP_ALIVE_IDLE_TIME(x) ((x) << S_KEEP_ALIVE_IDLE_TIME)
+#define G_KEEP_ALIVE_IDLE_TIME(x) (((x) >> S_KEEP_ALIVE_IDLE_TIME) & M_KEEP_ALIVE_IDLE_TIME)
+
+#define A_TP_KEEP_INTVL 0x3b0
+
+#define S_KEEP_ALIVE_INTERVAL_TIME 0
+#define M_KEEP_ALIVE_INTERVAL_TIME 0x3fffffff
+#define V_KEEP_ALIVE_INTERVAL_TIME(x) ((x) << S_KEEP_ALIVE_INTERVAL_TIME)
+#define G_KEEP_ALIVE_INTERVAL_TIME(x) (((x) >> S_KEEP_ALIVE_INTERVAL_TIME) & M_KEEP_ALIVE_INTERVAL_TIME)
+
+#define A_TP_INIT_SRTT 0x3b4
+
+#define S_INITIAL_SRTT 0
+#define M_INITIAL_SRTT 0xffff
+#define V_INITIAL_SRTT(x) ((x) << S_INITIAL_SRTT)
+#define G_INITIAL_SRTT(x) (((x) >> S_INITIAL_SRTT) & M_INITIAL_SRTT)
+
+#define A_TP_DACK_TIME 0x3b8
+
+#define S_DELAYED_ACK_TIME 0
+#define M_DELAYED_ACK_TIME 0x7ff
+#define V_DELAYED_ACK_TIME(x) ((x) << S_DELAYED_ACK_TIME)
+#define G_DELAYED_ACK_TIME(x) (((x) >> S_DELAYED_ACK_TIME) & M_DELAYED_ACK_TIME)
+
+#define A_TP_FINWAIT2_TIME 0x3bc
+
+#define S_FINWAIT2_TIME 0
+#define M_FINWAIT2_TIME 0x3fffffff
+#define V_FINWAIT2_TIME(x) ((x) << S_FINWAIT2_TIME)
+#define G_FINWAIT2_TIME(x) (((x) >> S_FINWAIT2_TIME) & M_FINWAIT2_TIME)
+
+#define A_TP_FAST_FINWAIT2_TIME 0x3c0
+
+#define S_FAST_FINWAIT2_TIME 0
+#define M_FAST_FINWAIT2_TIME 0x3fffffff
+#define V_FAST_FINWAIT2_TIME(x) ((x) << S_FAST_FINWAIT2_TIME)
+#define G_FAST_FINWAIT2_TIME(x) (((x) >> S_FAST_FINWAIT2_TIME) & M_FAST_FINWAIT2_TIME)
+
+#define A_TP_SHIFT_CNT 0x3c4
+
+#define S_KEEPALIVE_MAX 0
+#define M_KEEPALIVE_MAX 0xff
+#define V_KEEPALIVE_MAX(x) ((x) << S_KEEPALIVE_MAX)
+#define G_KEEPALIVE_MAX(x) (((x) >> S_KEEPALIVE_MAX) & M_KEEPALIVE_MAX)
+
+#define S_WINDOWPROBE_MAX 8
+#define M_WINDOWPROBE_MAX 0xff
+#define V_WINDOWPROBE_MAX(x) ((x) << S_WINDOWPROBE_MAX)
+#define G_WINDOWPROBE_MAX(x) (((x) >> S_WINDOWPROBE_MAX) & M_WINDOWPROBE_MAX)
+
+#define S_RETRANSMISSION_MAX 16
+#define M_RETRANSMISSION_MAX 0xff
+#define V_RETRANSMISSION_MAX(x) ((x) << S_RETRANSMISSION_MAX)
+#define G_RETRANSMISSION_MAX(x) (((x) >> S_RETRANSMISSION_MAX) & M_RETRANSMISSION_MAX)
+
+#define S_SYN_MAX 24
+#define M_SYN_MAX 0xff
+#define V_SYN_MAX(x) ((x) << S_SYN_MAX)
+#define G_SYN_MAX(x) (((x) >> S_SYN_MAX) & M_SYN_MAX)
+
+#define A_TP_QOS_REG0 0x3e0
+
+#define S_L3_VALUE 0
+#define M_L3_VALUE 0x3f
+#define V_L3_VALUE(x) ((x) << S_L3_VALUE)
+#define G_L3_VALUE(x) (((x) >> S_L3_VALUE) & M_L3_VALUE)
+
+#define A_TP_QOS_REG1 0x3e4
+#define A_TP_QOS_REG2 0x3e8
+#define A_TP_QOS_REG3 0x3ec
+#define A_TP_QOS_REG4 0x3f0
+#define A_TP_QOS_REG5 0x3f4
+#define A_TP_QOS_REG6 0x3f8
+#define A_TP_QOS_REG7 0x3fc
+#define A_TP_MTU_REG0 0x404
+#define A_TP_MTU_REG1 0x408
+#define A_TP_MTU_REG2 0x40c
+#define A_TP_MTU_REG3 0x410
+#define A_TP_MTU_REG4 0x414
+#define A_TP_MTU_REG5 0x418
+#define A_TP_MTU_REG6 0x41c
+#define A_TP_MTU_REG7 0x420
#define A_TP_RESET 0x44c
+
#define S_TP_RESET 0
#define V_TP_RESET(x) ((x) << S_TP_RESET)
#define F_TP_RESET V_TP_RESET(1U)
+#define S_CM_MEMMGR_INIT 1
+#define V_CM_MEMMGR_INIT(x) ((x) << S_CM_MEMMGR_INIT)
+#define F_CM_MEMMGR_INIT V_CM_MEMMGR_INIT(1U)
+
+#define A_TP_MIB_INDEX 0x450
+#define A_TP_MIB_DATA 0x454
+#define A_TP_SYNC_TIME_HI 0x458
+#define A_TP_SYNC_TIME_LO 0x45c
+#define A_TP_CM_MM_RX_FLST_BASE 0x460
+
+#define S_CM_MEMMGR_RX_FREE_LIST_BASE 0
+#define M_CM_MEMMGR_RX_FREE_LIST_BASE 0xfffffff
+#define V_CM_MEMMGR_RX_FREE_LIST_BASE(x) ((x) << S_CM_MEMMGR_RX_FREE_LIST_BASE)
+#define G_CM_MEMMGR_RX_FREE_LIST_BASE(x) (((x) >> S_CM_MEMMGR_RX_FREE_LIST_BASE) & M_CM_MEMMGR_RX_FREE_LIST_BASE)
+
+#define A_TP_CM_MM_TX_FLST_BASE 0x464
+
+#define S_CM_MEMMGR_TX_FREE_LIST_BASE 0
+#define M_CM_MEMMGR_TX_FREE_LIST_BASE 0xfffffff
+#define V_CM_MEMMGR_TX_FREE_LIST_BASE(x) ((x) << S_CM_MEMMGR_TX_FREE_LIST_BASE)
+#define G_CM_MEMMGR_TX_FREE_LIST_BASE(x) (((x) >> S_CM_MEMMGR_TX_FREE_LIST_BASE) & M_CM_MEMMGR_TX_FREE_LIST_BASE)
+
+#define A_TP_CM_MM_P_FLST_BASE 0x468
+
+#define S_CM_MEMMGR_PSTRUCT_FREE_LIST_BASE 0
+#define M_CM_MEMMGR_PSTRUCT_FREE_LIST_BASE 0xfffffff
+#define V_CM_MEMMGR_PSTRUCT_FREE_LIST_BASE(x) ((x) << S_CM_MEMMGR_PSTRUCT_FREE_LIST_BASE)
+#define G_CM_MEMMGR_PSTRUCT_FREE_LIST_BASE(x) (((x) >> S_CM_MEMMGR_PSTRUCT_FREE_LIST_BASE) & M_CM_MEMMGR_PSTRUCT_FREE_LIST_BASE)
+
+#define A_TP_CM_MM_MAX_P 0x46c
+
+#define S_CM_MEMMGR_MAX_PSTRUCT 0
+#define M_CM_MEMMGR_MAX_PSTRUCT 0xfffffff
+#define V_CM_MEMMGR_MAX_PSTRUCT(x) ((x) << S_CM_MEMMGR_MAX_PSTRUCT)
+#define G_CM_MEMMGR_MAX_PSTRUCT(x) (((x) >> S_CM_MEMMGR_MAX_PSTRUCT) & M_CM_MEMMGR_MAX_PSTRUCT)
+
#define A_TP_INT_ENABLE 0x470
+
+#define S_TX_FREE_LIST_EMPTY 0
+#define V_TX_FREE_LIST_EMPTY(x) ((x) << S_TX_FREE_LIST_EMPTY)
+#define F_TX_FREE_LIST_EMPTY V_TX_FREE_LIST_EMPTY(1U)
+
+#define S_RX_FREE_LIST_EMPTY 1
+#define V_RX_FREE_LIST_EMPTY(x) ((x) << S_RX_FREE_LIST_EMPTY)
+#define F_RX_FREE_LIST_EMPTY V_RX_FREE_LIST_EMPTY(1U)
+
#define A_TP_INT_CAUSE 0x474
+#define A_TP_TIMER_SEPARATOR 0x4a4
+
+#define S_DISABLE_PAST_TIMER_INSERTION 0
+#define V_DISABLE_PAST_TIMER_INSERTION(x) ((x) << S_DISABLE_PAST_TIMER_INSERTION)
+#define F_DISABLE_PAST_TIMER_INSERTION V_DISABLE_PAST_TIMER_INSERTION(1U)
+
+#define S_MODULATION_TIMER_SEPARATOR 1
+#define M_MODULATION_TIMER_SEPARATOR 0x7fff
+#define V_MODULATION_TIMER_SEPARATOR(x) ((x) << S_MODULATION_TIMER_SEPARATOR)
+#define G_MODULATION_TIMER_SEPARATOR(x) (((x) >> S_MODULATION_TIMER_SEPARATOR) & M_MODULATION_TIMER_SEPARATOR)
+
+#define S_GLOBAL_TIMER_SEPARATOR 16
+#define M_GLOBAL_TIMER_SEPARATOR 0xffff
+#define V_GLOBAL_TIMER_SEPARATOR(x) ((x) << S_GLOBAL_TIMER_SEPARATOR)
+#define G_GLOBAL_TIMER_SEPARATOR(x) (((x) >> S_GLOBAL_TIMER_SEPARATOR) & M_GLOBAL_TIMER_SEPARATOR)
+
+#define A_TP_CM_FC_MODE 0x4b0
+#define A_TP_PC_CONGESTION_CNTL 0x4b4
#define A_TP_TX_DROP_CONFIG 0x4b8
#define S_ENABLE_TX_DROP 31
@@ -282,12 +1249,108 @@
#define F_ENABLE_TX_ERROR V_ENABLE_TX_ERROR(1U)
#define S_DROP_TICKS_CNT 4
+#define M_DROP_TICKS_CNT 0x3ffffff
#define V_DROP_TICKS_CNT(x) ((x) << S_DROP_TICKS_CNT)
+#define G_DROP_TICKS_CNT(x) (((x) >> S_DROP_TICKS_CNT) & M_DROP_TICKS_CNT)
#define S_NUM_PKTS_DROPPED 0
+#define M_NUM_PKTS_DROPPED 0xf
#define V_NUM_PKTS_DROPPED(x) ((x) << S_NUM_PKTS_DROPPED)
+#define G_NUM_PKTS_DROPPED(x) (((x) >> S_NUM_PKTS_DROPPED) & M_NUM_PKTS_DROPPED)
+
+#define A_TP_TX_DROP_COUNT 0x4bc
+
+/* RAT registers */
+#define A_RAT_ROUTE_CONTROL 0x580
+
+#define S_USE_ROUTE_TABLE 0
+#define V_USE_ROUTE_TABLE(x) ((x) << S_USE_ROUTE_TABLE)
+#define F_USE_ROUTE_TABLE V_USE_ROUTE_TABLE(1U)
+
+#define S_ENABLE_CSPI 1
+#define V_ENABLE_CSPI(x) ((x) << S_ENABLE_CSPI)
+#define F_ENABLE_CSPI V_ENABLE_CSPI(1U)
+
+#define S_ENABLE_PCIX 2
+#define V_ENABLE_PCIX(x) ((x) << S_ENABLE_PCIX)
+#define F_ENABLE_PCIX V_ENABLE_PCIX(1U)
+
+#define A_RAT_ROUTE_TABLE_INDEX 0x584
+
+#define S_ROUTE_TABLE_INDEX 0
+#define M_ROUTE_TABLE_INDEX 0xf
+#define V_ROUTE_TABLE_INDEX(x) ((x) << S_ROUTE_TABLE_INDEX)
+#define G_ROUTE_TABLE_INDEX(x) (((x) >> S_ROUTE_TABLE_INDEX) & M_ROUTE_TABLE_INDEX)
+
+#define A_RAT_ROUTE_TABLE_DATA 0x588
+#define A_RAT_NO_ROUTE 0x58c
+
+#define S_CPL_OPCODE 0
+#define M_CPL_OPCODE 0xff
+#define V_CPL_OPCODE(x) ((x) << S_CPL_OPCODE)
+#define G_CPL_OPCODE(x) (((x) >> S_CPL_OPCODE) & M_CPL_OPCODE)
+
+#define A_RAT_INTR_ENABLE 0x590
+
+#define S_ZEROROUTEERROR 0
+#define V_ZEROROUTEERROR(x) ((x) << S_ZEROROUTEERROR)
+#define F_ZEROROUTEERROR V_ZEROROUTEERROR(1U)
+
+#define S_CSPIFRAMINGERROR 1
+#define V_CSPIFRAMINGERROR(x) ((x) << S_CSPIFRAMINGERROR)
+#define F_CSPIFRAMINGERROR V_CSPIFRAMINGERROR(1U)
+
+#define S_SGEFRAMINGERROR 2
+#define V_SGEFRAMINGERROR(x) ((x) << S_SGEFRAMINGERROR)
+#define F_SGEFRAMINGERROR V_SGEFRAMINGERROR(1U)
+
+#define S_TPFRAMINGERROR 3
+#define V_TPFRAMINGERROR(x) ((x) << S_TPFRAMINGERROR)
+#define F_TPFRAMINGERROR V_TPFRAMINGERROR(1U)
+
+#define A_RAT_INTR_CAUSE 0x594
/* CSPI registers */
+#define A_CSPI_RX_AE_WM 0x810
+#define A_CSPI_RX_AF_WM 0x814
+#define A_CSPI_CALENDAR_LEN 0x818
+
+#define S_CALENDARLENGTH 0
+#define M_CALENDARLENGTH 0xffff
+#define V_CALENDARLENGTH(x) ((x) << S_CALENDARLENGTH)
+#define G_CALENDARLENGTH(x) (((x) >> S_CALENDARLENGTH) & M_CALENDARLENGTH)
+
+#define A_CSPI_FIFO_STATUS_ENABLE 0x820
+
+#define S_FIFOSTATUSENABLE 0
+#define V_FIFOSTATUSENABLE(x) ((x) << S_FIFOSTATUSENABLE)
+#define F_FIFOSTATUSENABLE V_FIFOSTATUSENABLE(1U)
+
+#define A_CSPI_MAXBURST1_MAXBURST2 0x828
+
+#define S_MAXBURST1 0
+#define M_MAXBURST1 0xffff
+#define V_MAXBURST1(x) ((x) << S_MAXBURST1)
+#define G_MAXBURST1(x) (((x) >> S_MAXBURST1) & M_MAXBURST1)
+
+#define S_MAXBURST2 16
+#define M_MAXBURST2 0xffff
+#define V_MAXBURST2(x) ((x) << S_MAXBURST2)
+#define G_MAXBURST2(x) (((x) >> S_MAXBURST2) & M_MAXBURST2)
+
+#define A_CSPI_TRAIN 0x82c
+
+#define S_CSPI_TRAIN_ALPHA 0
+#define M_CSPI_TRAIN_ALPHA 0xffff
+#define V_CSPI_TRAIN_ALPHA(x) ((x) << S_CSPI_TRAIN_ALPHA)
+#define G_CSPI_TRAIN_ALPHA(x) (((x) >> S_CSPI_TRAIN_ALPHA) & M_CSPI_TRAIN_ALPHA)
+
+#define S_CSPI_TRAIN_DATA_MAXT 16
+#define M_CSPI_TRAIN_DATA_MAXT 0xffff
+#define V_CSPI_TRAIN_DATA_MAXT(x) ((x) << S_CSPI_TRAIN_DATA_MAXT)
+#define G_CSPI_TRAIN_DATA_MAXT(x) (((x) >> S_CSPI_TRAIN_DATA_MAXT) & M_CSPI_TRAIN_DATA_MAXT)
+
+#define A_CSPI_INTR_STATUS 0x848
#define S_DIP4ERR 0
#define V_DIP4ERR(x) ((x) << S_DIP4ERR)
@@ -309,22 +1372,63 @@
#define V_RAMPARITYERR(x) ((x) << S_RAMPARITYERR)
#define F_RAMPARITYERR V_RAMPARITYERR(1U)
-/* ESPI registers */
+#define A_CSPI_INTR_ENABLE 0x84c
+/* ESPI registers */
#define A_ESPI_SCH_TOKEN0 0x880
+
+#define S_SCHTOKEN0 0
+#define M_SCHTOKEN0 0xffff
+#define V_SCHTOKEN0(x) ((x) << S_SCHTOKEN0)
+#define G_SCHTOKEN0(x) (((x) >> S_SCHTOKEN0) & M_SCHTOKEN0)
+
#define A_ESPI_SCH_TOKEN1 0x884
+
+#define S_SCHTOKEN1 0
+#define M_SCHTOKEN1 0xffff
+#define V_SCHTOKEN1(x) ((x) << S_SCHTOKEN1)
+#define G_SCHTOKEN1(x) (((x) >> S_SCHTOKEN1) & M_SCHTOKEN1)
+
#define A_ESPI_SCH_TOKEN2 0x888
+
+#define S_SCHTOKEN2 0
+#define M_SCHTOKEN2 0xffff
+#define V_SCHTOKEN2(x) ((x) << S_SCHTOKEN2)
+#define G_SCHTOKEN2(x) (((x) >> S_SCHTOKEN2) & M_SCHTOKEN2)
+
#define A_ESPI_SCH_TOKEN3 0x88c
+
+#define S_SCHTOKEN3 0
+#define M_SCHTOKEN3 0xffff
+#define V_SCHTOKEN3(x) ((x) << S_SCHTOKEN3)
+#define G_SCHTOKEN3(x) (((x) >> S_SCHTOKEN3) & M_SCHTOKEN3)
+
#define A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK 0x890
+
+#define S_ALMOSTEMPTY 0
+#define M_ALMOSTEMPTY 0xffff
+#define V_ALMOSTEMPTY(x) ((x) << S_ALMOSTEMPTY)
+#define G_ALMOSTEMPTY(x) (((x) >> S_ALMOSTEMPTY) & M_ALMOSTEMPTY)
+
#define A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK 0x894
+
+#define S_ALMOSTFULL 0
+#define M_ALMOSTFULL 0xffff
+#define V_ALMOSTFULL(x) ((x) << S_ALMOSTFULL)
+#define G_ALMOSTFULL(x) (((x) >> S_ALMOSTFULL) & M_ALMOSTFULL)
+
#define A_ESPI_CALENDAR_LENGTH 0x898
#define A_PORT_CONFIG 0x89c
#define S_RX_NPORTS 0
+#define M_RX_NPORTS 0xff
#define V_RX_NPORTS(x) ((x) << S_RX_NPORTS)
+#define G_RX_NPORTS(x) (((x) >> S_RX_NPORTS) & M_RX_NPORTS)
#define S_TX_NPORTS 8
+#define M_TX_NPORTS 0xff
#define V_TX_NPORTS(x) ((x) << S_TX_NPORTS)
+#define G_TX_NPORTS(x) (((x) >> S_TX_NPORTS) & M_TX_NPORTS)
#define A_ESPI_FIFO_STATUS_ENABLE 0x8a0
@@ -332,12 +1436,124 @@
#define V_RXSTATUSENABLE(x) ((x) << S_RXSTATUSENABLE)
#define F_RXSTATUSENABLE V_RXSTATUSENABLE(1U)
+#define S_TXDROPENABLE 1
+#define V_TXDROPENABLE(x) ((x) << S_TXDROPENABLE)
+#define F_TXDROPENABLE V_TXDROPENABLE(1U)
+
+#define S_RXENDIANMODE 2
+#define V_RXENDIANMODE(x) ((x) << S_RXENDIANMODE)
+#define F_RXENDIANMODE V_RXENDIANMODE(1U)
+
+#define S_TXENDIANMODE 3
+#define V_TXENDIANMODE(x) ((x) << S_TXENDIANMODE)
+#define F_TXENDIANMODE V_TXENDIANMODE(1U)
+
#define S_INTEL1010MODE 4
#define V_INTEL1010MODE(x) ((x) << S_INTEL1010MODE)
#define F_INTEL1010MODE V_INTEL1010MODE(1U)
#define A_ESPI_MAXBURST1_MAXBURST2 0x8a8
#define A_ESPI_TRAIN 0x8ac
+
+#define S_MAXTRAINALPHA 0
+#define M_MAXTRAINALPHA 0xffff
+#define V_MAXTRAINALPHA(x) ((x) << S_MAXTRAINALPHA)
+#define G_MAXTRAINALPHA(x) (((x) >> S_MAXTRAINALPHA) & M_MAXTRAINALPHA)
+
+#define S_MAXTRAINDATA 16
+#define M_MAXTRAINDATA 0xffff
+#define V_MAXTRAINDATA(x) ((x) << S_MAXTRAINDATA)
+#define G_MAXTRAINDATA(x) (((x) >> S_MAXTRAINDATA) & M_MAXTRAINDATA)
+
+#define A_RAM_STATUS 0x8b0
+
+#define S_RXFIFOPARITYERROR 0
+#define M_RXFIFOPARITYERROR 0x3ff
+#define V_RXFIFOPARITYERROR(x) ((x) << S_RXFIFOPARITYERROR)
+#define G_RXFIFOPARITYERROR(x) (((x) >> S_RXFIFOPARITYERROR) & M_RXFIFOPARITYERROR)
+
+#define S_TXFIFOPARITYERROR 10
+#define M_TXFIFOPARITYERROR 0x3ff
+#define V_TXFIFOPARITYERROR(x) ((x) << S_TXFIFOPARITYERROR)
+#define G_TXFIFOPARITYERROR(x) (((x) >> S_TXFIFOPARITYERROR) & M_TXFIFOPARITYERROR)
+
+#define S_RXFIFOOVERFLOW 20
+#define M_RXFIFOOVERFLOW 0x3ff
+#define V_RXFIFOOVERFLOW(x) ((x) << S_RXFIFOOVERFLOW)
+#define G_RXFIFOOVERFLOW(x) (((x) >> S_RXFIFOOVERFLOW) & M_RXFIFOOVERFLOW)
+
+#define A_TX_DROP_COUNT0 0x8b4
+
+#define S_TXPORT0DROPCNT 0
+#define M_TXPORT0DROPCNT 0xffff
+#define V_TXPORT0DROPCNT(x) ((x) << S_TXPORT0DROPCNT)
+#define G_TXPORT0DROPCNT(x) (((x) >> S_TXPORT0DROPCNT) & M_TXPORT0DROPCNT)
+
+#define S_TXPORT1DROPCNT 16
+#define M_TXPORT1DROPCNT 0xffff
+#define V_TXPORT1DROPCNT(x) ((x) << S_TXPORT1DROPCNT)
+#define G_TXPORT1DROPCNT(x) (((x) >> S_TXPORT1DROPCNT) & M_TXPORT1DROPCNT)
+
+#define A_TX_DROP_COUNT1 0x8b8
+
+#define S_TXPORT2DROPCNT 0
+#define M_TXPORT2DROPCNT 0xffff
+#define V_TXPORT2DROPCNT(x) ((x) << S_TXPORT2DROPCNT)
+#define G_TXPORT2DROPCNT(x) (((x) >> S_TXPORT2DROPCNT) & M_TXPORT2DROPCNT)
+
+#define S_TXPORT3DROPCNT 16
+#define M_TXPORT3DROPCNT 0xffff
+#define V_TXPORT3DROPCNT(x) ((x) << S_TXPORT3DROPCNT)
+#define G_TXPORT3DROPCNT(x) (((x) >> S_TXPORT3DROPCNT) & M_TXPORT3DROPCNT)
+
+#define A_RX_DROP_COUNT0 0x8bc
+
+#define S_RXPORT0DROPCNT 0
+#define M_RXPORT0DROPCNT 0xffff
+#define V_RXPORT0DROPCNT(x) ((x) << S_RXPORT0DROPCNT)
+#define G_RXPORT0DROPCNT(x) (((x) >> S_RXPORT0DROPCNT) & M_RXPORT0DROPCNT)
+
+#define S_RXPORT1DROPCNT 16
+#define M_RXPORT1DROPCNT 0xffff
+#define V_RXPORT1DROPCNT(x) ((x) << S_RXPORT1DROPCNT)
+#define G_RXPORT1DROPCNT(x) (((x) >> S_RXPORT1DROPCNT) & M_RXPORT1DROPCNT)
+
+#define A_RX_DROP_COUNT1 0x8c0
+
+#define S_RXPORT2DROPCNT 0
+#define M_RXPORT2DROPCNT 0xffff
+#define V_RXPORT2DROPCNT(x) ((x) << S_RXPORT2DROPCNT)
+#define G_RXPORT2DROPCNT(x) (((x) >> S_RXPORT2DROPCNT) & M_RXPORT2DROPCNT)
+
+#define S_RXPORT3DROPCNT 16
+#define M_RXPORT3DROPCNT 0xffff
+#define V_RXPORT3DROPCNT(x) ((x) << S_RXPORT3DROPCNT)
+#define G_RXPORT3DROPCNT(x) (((x) >> S_RXPORT3DROPCNT) & M_RXPORT3DROPCNT)
+
+#define A_DIP4_ERROR_COUNT 0x8c4
+
+#define S_DIP4ERRORCNT 0
+#define M_DIP4ERRORCNT 0xfff
+#define V_DIP4ERRORCNT(x) ((x) << S_DIP4ERRORCNT)
+#define G_DIP4ERRORCNT(x) (((x) >> S_DIP4ERRORCNT) & M_DIP4ERRORCNT)
+
+#define S_DIP4ERRORCNTSHADOW 12
+#define M_DIP4ERRORCNTSHADOW 0xfff
+#define V_DIP4ERRORCNTSHADOW(x) ((x) << S_DIP4ERRORCNTSHADOW)
+#define G_DIP4ERRORCNTSHADOW(x) (((x) >> S_DIP4ERRORCNTSHADOW) & M_DIP4ERRORCNTSHADOW)
+
+#define S_TRICN_RX_TRAIN_ERR 24
+#define V_TRICN_RX_TRAIN_ERR(x) ((x) << S_TRICN_RX_TRAIN_ERR)
+#define F_TRICN_RX_TRAIN_ERR V_TRICN_RX_TRAIN_ERR(1U)
+
+#define S_TRICN_RX_TRAINING 25
+#define V_TRICN_RX_TRAINING(x) ((x) << S_TRICN_RX_TRAINING)
+#define F_TRICN_RX_TRAINING V_TRICN_RX_TRAINING(1U)
+
+#define S_TRICN_RX_TRAIN_OK 26
+#define V_TRICN_RX_TRAIN_OK(x) ((x) << S_TRICN_RX_TRAIN_OK)
+#define F_TRICN_RX_TRAIN_OK V_TRICN_RX_TRAIN_OK(1U)
+
#define A_ESPI_INTR_STATUS 0x8c8
#define S_DIP2PARITYERR 5
@@ -347,19 +1563,56 @@
#define A_ESPI_INTR_ENABLE 0x8cc
#define A_RX_DROP_THRESHOLD 0x8d0
#define A_ESPI_RX_RESET 0x8ec
+
+#define S_ESPI_RX_LNK_RST 0
+#define V_ESPI_RX_LNK_RST(x) ((x) << S_ESPI_RX_LNK_RST)
+#define F_ESPI_RX_LNK_RST V_ESPI_RX_LNK_RST(1U)
+
+#define S_ESPI_RX_CORE_RST 1
+#define V_ESPI_RX_CORE_RST(x) ((x) << S_ESPI_RX_CORE_RST)
+#define F_ESPI_RX_CORE_RST V_ESPI_RX_CORE_RST(1U)
+
+#define S_RX_CLK_STATUS 2
+#define V_RX_CLK_STATUS(x) ((x) << S_RX_CLK_STATUS)
+#define F_RX_CLK_STATUS V_RX_CLK_STATUS(1U)
+
#define A_ESPI_MISC_CONTROL 0x8f0
#define S_OUT_OF_SYNC_COUNT 0
+#define M_OUT_OF_SYNC_COUNT 0xf
#define V_OUT_OF_SYNC_COUNT(x) ((x) << S_OUT_OF_SYNC_COUNT)
+#define G_OUT_OF_SYNC_COUNT(x) (((x) >> S_OUT_OF_SYNC_COUNT) & M_OUT_OF_SYNC_COUNT)
+
+#define S_DIP2_COUNT_MODE_ENABLE 4
+#define V_DIP2_COUNT_MODE_ENABLE(x) ((x) << S_DIP2_COUNT_MODE_ENABLE)
+#define F_DIP2_COUNT_MODE_ENABLE V_DIP2_COUNT_MODE_ENABLE(1U)
#define S_DIP2_PARITY_ERR_THRES 5
+#define M_DIP2_PARITY_ERR_THRES 0xf
#define V_DIP2_PARITY_ERR_THRES(x) ((x) << S_DIP2_PARITY_ERR_THRES)
+#define G_DIP2_PARITY_ERR_THRES(x) (((x) >> S_DIP2_PARITY_ERR_THRES) & M_DIP2_PARITY_ERR_THRES)
#define S_DIP4_THRES 9
+#define M_DIP4_THRES 0xfff
#define V_DIP4_THRES(x) ((x) << S_DIP4_THRES)
+#define G_DIP4_THRES(x) (((x) >> S_DIP4_THRES) & M_DIP4_THRES)
+
+#define S_DIP4_THRES_ENABLE 21
+#define V_DIP4_THRES_ENABLE(x) ((x) << S_DIP4_THRES_ENABLE)
+#define F_DIP4_THRES_ENABLE V_DIP4_THRES_ENABLE(1U)
+
+#define S_FORCE_DISABLE_STATUS 22
+#define V_FORCE_DISABLE_STATUS(x) ((x) << S_FORCE_DISABLE_STATUS)
+#define F_FORCE_DISABLE_STATUS V_FORCE_DISABLE_STATUS(1U)
+
+#define S_DYNAMIC_DESKEW 23
+#define V_DYNAMIC_DESKEW(x) ((x) << S_DYNAMIC_DESKEW)
+#define F_DYNAMIC_DESKEW V_DYNAMIC_DESKEW(1U)
#define S_MONITORED_PORT_NUM 25
+#define M_MONITORED_PORT_NUM 0x3
#define V_MONITORED_PORT_NUM(x) ((x) << S_MONITORED_PORT_NUM)
+#define G_MONITORED_PORT_NUM(x) (((x) >> S_MONITORED_PORT_NUM) & M_MONITORED_PORT_NUM)
#define S_MONITORED_DIRECTION 27
#define V_MONITORED_DIRECTION(x) ((x) << S_MONITORED_DIRECTION)
@@ -370,33 +1623,125 @@
#define F_MONITORED_INTERFACE V_MONITORED_INTERFACE(1U)
#define A_ESPI_DIP2_ERR_COUNT 0x8f4
+
+#define S_DIP2_ERR_CNT 0
+#define M_DIP2_ERR_CNT 0xf
+#define V_DIP2_ERR_CNT(x) ((x) << S_DIP2_ERR_CNT)
+#define G_DIP2_ERR_CNT(x) (((x) >> S_DIP2_ERR_CNT) & M_DIP2_ERR_CNT)
+
#define A_ESPI_CMD_ADDR 0x8f8
#define S_WRITE_DATA 0
+#define M_WRITE_DATA 0xff
#define V_WRITE_DATA(x) ((x) << S_WRITE_DATA)
+#define G_WRITE_DATA(x) (((x) >> S_WRITE_DATA) & M_WRITE_DATA)
#define S_REGISTER_OFFSET 8
+#define M_REGISTER_OFFSET 0xf
#define V_REGISTER_OFFSET(x) ((x) << S_REGISTER_OFFSET)
+#define G_REGISTER_OFFSET(x) (((x) >> S_REGISTER_OFFSET) & M_REGISTER_OFFSET)
#define S_CHANNEL_ADDR 12
+#define M_CHANNEL_ADDR 0xf
#define V_CHANNEL_ADDR(x) ((x) << S_CHANNEL_ADDR)
+#define G_CHANNEL_ADDR(x) (((x) >> S_CHANNEL_ADDR) & M_CHANNEL_ADDR)
#define S_MODULE_ADDR 16
+#define M_MODULE_ADDR 0x3
#define V_MODULE_ADDR(x) ((x) << S_MODULE_ADDR)
+#define G_MODULE_ADDR(x) (((x) >> S_MODULE_ADDR) & M_MODULE_ADDR)
#define S_BUNDLE_ADDR 20
+#define M_BUNDLE_ADDR 0x3
#define V_BUNDLE_ADDR(x) ((x) << S_BUNDLE_ADDR)
+#define G_BUNDLE_ADDR(x) (((x) >> S_BUNDLE_ADDR) & M_BUNDLE_ADDR)
#define S_SPI4_COMMAND 24
+#define M_SPI4_COMMAND 0xff
#define V_SPI4_COMMAND(x) ((x) << S_SPI4_COMMAND)
+#define G_SPI4_COMMAND(x) (((x) >> S_SPI4_COMMAND) & M_SPI4_COMMAND)
#define A_ESPI_GOSTAT 0x8fc
+
+#define S_READ_DATA 0
+#define M_READ_DATA 0xff
+#define V_READ_DATA(x) ((x) << S_READ_DATA)
+#define G_READ_DATA(x) (((x) >> S_READ_DATA) & M_READ_DATA)
+
#define S_ESPI_CMD_BUSY 8
#define V_ESPI_CMD_BUSY(x) ((x) << S_ESPI_CMD_BUSY)
#define F_ESPI_CMD_BUSY V_ESPI_CMD_BUSY(1U)
-/* PL registers */
+#define S_ERROR_ACK 9
+#define V_ERROR_ACK(x) ((x) << S_ERROR_ACK)
+#define F_ERROR_ACK V_ERROR_ACK(1U)
+
+#define S_UNMAPPED_ERR 10
+#define V_UNMAPPED_ERR(x) ((x) << S_UNMAPPED_ERR)
+#define F_UNMAPPED_ERR V_UNMAPPED_ERR(1U)
+
+#define S_TRANSACTION_TIMER 16
+#define M_TRANSACTION_TIMER 0xff
+#define V_TRANSACTION_TIMER(x) ((x) << S_TRANSACTION_TIMER)
+#define G_TRANSACTION_TIMER(x) (((x) >> S_TRANSACTION_TIMER) & M_TRANSACTION_TIMER)
+
+
+/* ULP registers */
+#define A_ULP_ULIMIT 0x980
+#define A_ULP_TAGMASK 0x984
+#define A_ULP_HREG_INDEX 0x988
+#define A_ULP_HREG_DATA 0x98c
+#define A_ULP_INT_ENABLE 0x990
+#define A_ULP_INT_CAUSE 0x994
+#define S_HREG_PAR_ERR 0
+#define V_HREG_PAR_ERR(x) ((x) << S_HREG_PAR_ERR)
+#define F_HREG_PAR_ERR V_HREG_PAR_ERR(1U)
+
+#define S_EGRS_DATA_PAR_ERR 1
+#define V_EGRS_DATA_PAR_ERR(x) ((x) << S_EGRS_DATA_PAR_ERR)
+#define F_EGRS_DATA_PAR_ERR V_EGRS_DATA_PAR_ERR(1U)
+
+#define S_INGRS_DATA_PAR_ERR 2
+#define V_INGRS_DATA_PAR_ERR(x) ((x) << S_INGRS_DATA_PAR_ERR)
+#define F_INGRS_DATA_PAR_ERR V_INGRS_DATA_PAR_ERR(1U)
+
+#define S_PM_INTR 3
+#define V_PM_INTR(x) ((x) << S_PM_INTR)
+#define F_PM_INTR V_PM_INTR(1U)
+
+#define S_PM_E2C_SYNC_ERR 4
+#define V_PM_E2C_SYNC_ERR(x) ((x) << S_PM_E2C_SYNC_ERR)
+#define F_PM_E2C_SYNC_ERR V_PM_E2C_SYNC_ERR(1U)
+
+#define S_PM_C2E_SYNC_ERR 5
+#define V_PM_C2E_SYNC_ERR(x) ((x) << S_PM_C2E_SYNC_ERR)
+#define F_PM_C2E_SYNC_ERR V_PM_C2E_SYNC_ERR(1U)
+
+#define S_PM_E2C_EMPTY_ERR 6
+#define V_PM_E2C_EMPTY_ERR(x) ((x) << S_PM_E2C_EMPTY_ERR)
+#define F_PM_E2C_EMPTY_ERR V_PM_E2C_EMPTY_ERR(1U)
+
+#define S_PM_C2E_EMPTY_ERR 7
+#define V_PM_C2E_EMPTY_ERR(x) ((x) << S_PM_C2E_EMPTY_ERR)
+#define F_PM_C2E_EMPTY_ERR V_PM_C2E_EMPTY_ERR(1U)
+
+#define S_PM_PAR_ERR 8
+#define M_PM_PAR_ERR 0xffff
+#define V_PM_PAR_ERR(x) ((x) << S_PM_PAR_ERR)
+#define G_PM_PAR_ERR(x) (((x) >> S_PM_PAR_ERR) & M_PM_PAR_ERR)
+
+#define S_PM_E2C_WRT_FULL 24
+#define V_PM_E2C_WRT_FULL(x) ((x) << S_PM_E2C_WRT_FULL)
+#define F_PM_E2C_WRT_FULL V_PM_E2C_WRT_FULL(1U)
+
+#define S_PM_C2E_WRT_FULL 25
+#define V_PM_C2E_WRT_FULL(x) ((x) << S_PM_C2E_WRT_FULL)
+#define F_PM_C2E_WRT_FULL V_PM_C2E_WRT_FULL(1U)
+
+#define A_ULP_PIO_CTRL 0x998
+
+/* PL registers */
#define A_PL_ENABLE 0xa00
#define S_PL_INTR_SGE_ERR 0
@@ -407,14 +1752,38 @@
#define V_PL_INTR_SGE_DATA(x) ((x) << S_PL_INTR_SGE_DATA)
#define F_PL_INTR_SGE_DATA V_PL_INTR_SGE_DATA(1U)
+#define S_PL_INTR_MC3 2
+#define V_PL_INTR_MC3(x) ((x) << S_PL_INTR_MC3)
+#define F_PL_INTR_MC3 V_PL_INTR_MC3(1U)
+
+#define S_PL_INTR_MC4 3
+#define V_PL_INTR_MC4(x) ((x) << S_PL_INTR_MC4)
+#define F_PL_INTR_MC4 V_PL_INTR_MC4(1U)
+
+#define S_PL_INTR_MC5 4
+#define V_PL_INTR_MC5(x) ((x) << S_PL_INTR_MC5)
+#define F_PL_INTR_MC5 V_PL_INTR_MC5(1U)
+
+#define S_PL_INTR_RAT 5
+#define V_PL_INTR_RAT(x) ((x) << S_PL_INTR_RAT)
+#define F_PL_INTR_RAT V_PL_INTR_RAT(1U)
+
#define S_PL_INTR_TP 6
#define V_PL_INTR_TP(x) ((x) << S_PL_INTR_TP)
#define F_PL_INTR_TP V_PL_INTR_TP(1U)
+#define S_PL_INTR_ULP 7
+#define V_PL_INTR_ULP(x) ((x) << S_PL_INTR_ULP)
+#define F_PL_INTR_ULP V_PL_INTR_ULP(1U)
+
#define S_PL_INTR_ESPI 8
#define V_PL_INTR_ESPI(x) ((x) << S_PL_INTR_ESPI)
#define F_PL_INTR_ESPI V_PL_INTR_ESPI(1U)
+#define S_PL_INTR_CSPI 9
+#define V_PL_INTR_CSPI(x) ((x) << S_PL_INTR_CSPI)
+#define F_PL_INTR_CSPI V_PL_INTR_CSPI(1U)
+
#define S_PL_INTR_PCIX 10
#define V_PL_INTR_PCIX(x) ((x) << S_PL_INTR_PCIX)
#define F_PL_INTR_PCIX V_PL_INTR_PCIX(1U)
@@ -426,43 +1795,374 @@
#define A_PL_CAUSE 0xa04
/* MC5 registers */
-
#define A_MC5_CONFIG 0xc04
+#define S_MODE 0
+#define V_MODE(x) ((x) << S_MODE)
+#define F_MODE V_MODE(1U)
+
#define S_TCAM_RESET 1
#define V_TCAM_RESET(x) ((x) << S_TCAM_RESET)
#define F_TCAM_RESET V_TCAM_RESET(1U)
+#define S_TCAM_READY 2
+#define V_TCAM_READY(x) ((x) << S_TCAM_READY)
+#define F_TCAM_READY V_TCAM_READY(1U)
+
+#define S_DBGI_ENABLE 4
+#define V_DBGI_ENABLE(x) ((x) << S_DBGI_ENABLE)
+#define F_DBGI_ENABLE V_DBGI_ENABLE(1U)
+
#define S_M_BUS_ENABLE 5
#define V_M_BUS_ENABLE(x) ((x) << S_M_BUS_ENABLE)
#define F_M_BUS_ENABLE V_M_BUS_ENABLE(1U)
-/* PCICFG registers */
+#define S_PARITY_ENABLE 6
+#define V_PARITY_ENABLE(x) ((x) << S_PARITY_ENABLE)
+#define F_PARITY_ENABLE V_PARITY_ENABLE(1U)
+
+#define S_SYN_ISSUE_MODE 7
+#define M_SYN_ISSUE_MODE 0x3
+#define V_SYN_ISSUE_MODE(x) ((x) << S_SYN_ISSUE_MODE)
+#define G_SYN_ISSUE_MODE(x) (((x) >> S_SYN_ISSUE_MODE) & M_SYN_ISSUE_MODE)
+
+#define S_BUILD 16
+#define V_BUILD(x) ((x) << S_BUILD)
+#define F_BUILD V_BUILD(1U)
+
+#define S_COMPRESSION_ENABLE 17
+#define V_COMPRESSION_ENABLE(x) ((x) << S_COMPRESSION_ENABLE)
+#define F_COMPRESSION_ENABLE V_COMPRESSION_ENABLE(1U)
+
+#define S_NUM_LIP 18
+#define M_NUM_LIP 0x3f
+#define V_NUM_LIP(x) ((x) << S_NUM_LIP)
+#define G_NUM_LIP(x) (((x) >> S_NUM_LIP) & M_NUM_LIP)
+
+#define S_TCAM_PART_CNT 24
+#define M_TCAM_PART_CNT 0x3
+#define V_TCAM_PART_CNT(x) ((x) << S_TCAM_PART_CNT)
+#define G_TCAM_PART_CNT(x) (((x) >> S_TCAM_PART_CNT) & M_TCAM_PART_CNT)
+
+#define S_TCAM_PART_TYPE 26
+#define M_TCAM_PART_TYPE 0x3
+#define V_TCAM_PART_TYPE(x) ((x) << S_TCAM_PART_TYPE)
+#define G_TCAM_PART_TYPE(x) (((x) >> S_TCAM_PART_TYPE) & M_TCAM_PART_TYPE)
+
+#define S_TCAM_PART_SIZE 28
+#define M_TCAM_PART_SIZE 0x3
+#define V_TCAM_PART_SIZE(x) ((x) << S_TCAM_PART_SIZE)
+#define G_TCAM_PART_SIZE(x) (((x) >> S_TCAM_PART_SIZE) & M_TCAM_PART_SIZE)
+
+#define S_TCAM_PART_TYPE_HI 30
+#define V_TCAM_PART_TYPE_HI(x) ((x) << S_TCAM_PART_TYPE_HI)
+#define F_TCAM_PART_TYPE_HI V_TCAM_PART_TYPE_HI(1U)
+
+#define A_MC5_SIZE 0xc08
+
+#define S_SIZE 0
+#define M_SIZE 0x3fffff
+#define V_SIZE(x) ((x) << S_SIZE)
+#define G_SIZE(x) (((x) >> S_SIZE) & M_SIZE)
+
+#define A_MC5_ROUTING_TABLE_INDEX 0xc0c
+#define S_START_OF_ROUTING_TABLE 0
+#define M_START_OF_ROUTING_TABLE 0x3fffff
+#define V_START_OF_ROUTING_TABLE(x) ((x) << S_START_OF_ROUTING_TABLE)
+#define G_START_OF_ROUTING_TABLE(x) (((x) >> S_START_OF_ROUTING_TABLE) & M_START_OF_ROUTING_TABLE)
+
+#define A_MC5_SERVER_INDEX 0xc14
+
+#define S_START_OF_SERVER_INDEX 0
+#define M_START_OF_SERVER_INDEX 0x3fffff
+#define V_START_OF_SERVER_INDEX(x) ((x) << S_START_OF_SERVER_INDEX)
+#define G_START_OF_SERVER_INDEX(x) (((x) >> S_START_OF_SERVER_INDEX) & M_START_OF_SERVER_INDEX)
+
+#define A_MC5_LIP_RAM_ADDR 0xc18
+
+#define S_LOCAL_IP_RAM_ADDR 0
+#define M_LOCAL_IP_RAM_ADDR 0x3f
+#define V_LOCAL_IP_RAM_ADDR(x) ((x) << S_LOCAL_IP_RAM_ADDR)
+#define G_LOCAL_IP_RAM_ADDR(x) (((x) >> S_LOCAL_IP_RAM_ADDR) & M_LOCAL_IP_RAM_ADDR)
+
+#define S_RAM_WRITE_ENABLE 8
+#define V_RAM_WRITE_ENABLE(x) ((x) << S_RAM_WRITE_ENABLE)
+#define F_RAM_WRITE_ENABLE V_RAM_WRITE_ENABLE(1U)
+
+#define A_MC5_LIP_RAM_DATA 0xc1c
+#define A_MC5_RSP_LATENCY 0xc20
+
+#define S_SEARCH_RESPONSE_LATENCY 0
+#define M_SEARCH_RESPONSE_LATENCY 0x1f
+#define V_SEARCH_RESPONSE_LATENCY(x) ((x) << S_SEARCH_RESPONSE_LATENCY)
+#define G_SEARCH_RESPONSE_LATENCY(x) (((x) >> S_SEARCH_RESPONSE_LATENCY) & M_SEARCH_RESPONSE_LATENCY)
+
+#define S_LEARN_RESPONSE_LATENCY 8
+#define M_LEARN_RESPONSE_LATENCY 0x1f
+#define V_LEARN_RESPONSE_LATENCY(x) ((x) << S_LEARN_RESPONSE_LATENCY)
+#define G_LEARN_RESPONSE_LATENCY(x) (((x) >> S_LEARN_RESPONSE_LATENCY) & M_LEARN_RESPONSE_LATENCY)
+
+#define A_MC5_PARITY_LATENCY 0xc24
+
+#define S_SRCHLAT 0
+#define M_SRCHLAT 0x1f
+#define V_SRCHLAT(x) ((x) << S_SRCHLAT)
+#define G_SRCHLAT(x) (((x) >> S_SRCHLAT) & M_SRCHLAT)
+
+#define S_PARLAT 8
+#define M_PARLAT 0x1f
+#define V_PARLAT(x) ((x) << S_PARLAT)
+#define G_PARLAT(x) (((x) >> S_PARLAT) & M_PARLAT)
+
+#define A_MC5_WR_LRN_VERIFY 0xc28
+
+#define S_POVEREN 0
+#define V_POVEREN(x) ((x) << S_POVEREN)
+#define F_POVEREN V_POVEREN(1U)
+
+#define S_LRNVEREN 1
+#define V_LRNVEREN(x) ((x) << S_LRNVEREN)
+#define F_LRNVEREN V_LRNVEREN(1U)
+
+#define S_VWVEREN 2
+#define V_VWVEREN(x) ((x) << S_VWVEREN)
+#define F_VWVEREN V_VWVEREN(1U)
+
+#define A_MC5_PART_ID_INDEX 0xc2c
+
+#define S_IDINDEX 0
+#define M_IDINDEX 0xf
+#define V_IDINDEX(x) ((x) << S_IDINDEX)
+#define G_IDINDEX(x) (((x) >> S_IDINDEX) & M_IDINDEX)
+
+#define A_MC5_RESET_MAX 0xc30
+
+#define S_RSTMAX 0
+#define M_RSTMAX 0x1ff
+#define V_RSTMAX(x) ((x) << S_RSTMAX)
+#define G_RSTMAX(x) (((x) >> S_RSTMAX) & M_RSTMAX)
+
+#define A_MC5_INT_ENABLE 0xc40
+
+#define S_MC5_INT_HIT_OUT_ACTIVE_REGION_ERR 0
+#define V_MC5_INT_HIT_OUT_ACTIVE_REGION_ERR(x) ((x) << S_MC5_INT_HIT_OUT_ACTIVE_REGION_ERR)
+#define F_MC5_INT_HIT_OUT_ACTIVE_REGION_ERR V_MC5_INT_HIT_OUT_ACTIVE_REGION_ERR(1U)
+
+#define S_MC5_INT_HIT_IN_ACTIVE_REGION_ERR 1
+#define V_MC5_INT_HIT_IN_ACTIVE_REGION_ERR(x) ((x) << S_MC5_INT_HIT_IN_ACTIVE_REGION_ERR)
+#define F_MC5_INT_HIT_IN_ACTIVE_REGION_ERR V_MC5_INT_HIT_IN_ACTIVE_REGION_ERR(1U)
+
+#define S_MC5_INT_HIT_IN_RT_REGION_ERR 2
+#define V_MC5_INT_HIT_IN_RT_REGION_ERR(x) ((x) << S_MC5_INT_HIT_IN_RT_REGION_ERR)
+#define F_MC5_INT_HIT_IN_RT_REGION_ERR V_MC5_INT_HIT_IN_RT_REGION_ERR(1U)
+
+#define S_MC5_INT_MISS_ERR 3
+#define V_MC5_INT_MISS_ERR(x) ((x) << S_MC5_INT_MISS_ERR)
+#define F_MC5_INT_MISS_ERR V_MC5_INT_MISS_ERR(1U)
+
+#define S_MC5_INT_LIP0_ERR 4
+#define V_MC5_INT_LIP0_ERR(x) ((x) << S_MC5_INT_LIP0_ERR)
+#define F_MC5_INT_LIP0_ERR V_MC5_INT_LIP0_ERR(1U)
+
+#define S_MC5_INT_LIP_MISS_ERR 5
+#define V_MC5_INT_LIP_MISS_ERR(x) ((x) << S_MC5_INT_LIP_MISS_ERR)
+#define F_MC5_INT_LIP_MISS_ERR V_MC5_INT_LIP_MISS_ERR(1U)
+
+#define S_MC5_INT_PARITY_ERR 6
+#define V_MC5_INT_PARITY_ERR(x) ((x) << S_MC5_INT_PARITY_ERR)
+#define F_MC5_INT_PARITY_ERR V_MC5_INT_PARITY_ERR(1U)
+
+#define S_MC5_INT_ACTIVE_REGION_FULL 7
+#define V_MC5_INT_ACTIVE_REGION_FULL(x) ((x) << S_MC5_INT_ACTIVE_REGION_FULL)
+#define F_MC5_INT_ACTIVE_REGION_FULL V_MC5_INT_ACTIVE_REGION_FULL(1U)
+
+#define S_MC5_INT_NFA_SRCH_ERR 8
+#define V_MC5_INT_NFA_SRCH_ERR(x) ((x) << S_MC5_INT_NFA_SRCH_ERR)
+#define F_MC5_INT_NFA_SRCH_ERR V_MC5_INT_NFA_SRCH_ERR(1U)
+
+#define S_MC5_INT_SYN_COOKIE 9
+#define V_MC5_INT_SYN_COOKIE(x) ((x) << S_MC5_INT_SYN_COOKIE)
+#define F_MC5_INT_SYN_COOKIE V_MC5_INT_SYN_COOKIE(1U)
+
+#define S_MC5_INT_SYN_COOKIE_BAD 10
+#define V_MC5_INT_SYN_COOKIE_BAD(x) ((x) << S_MC5_INT_SYN_COOKIE_BAD)
+#define F_MC5_INT_SYN_COOKIE_BAD V_MC5_INT_SYN_COOKIE_BAD(1U)
+
+#define S_MC5_INT_SYN_COOKIE_OFF 11
+#define V_MC5_INT_SYN_COOKIE_OFF(x) ((x) << S_MC5_INT_SYN_COOKIE_OFF)
+#define F_MC5_INT_SYN_COOKIE_OFF V_MC5_INT_SYN_COOKIE_OFF(1U)
+
+#define S_MC5_INT_UNKNOWN_CMD 15
+#define V_MC5_INT_UNKNOWN_CMD(x) ((x) << S_MC5_INT_UNKNOWN_CMD)
+#define F_MC5_INT_UNKNOWN_CMD V_MC5_INT_UNKNOWN_CMD(1U)
+
+#define S_MC5_INT_REQUESTQ_PARITY_ERR 16
+#define V_MC5_INT_REQUESTQ_PARITY_ERR(x) ((x) << S_MC5_INT_REQUESTQ_PARITY_ERR)
+#define F_MC5_INT_REQUESTQ_PARITY_ERR V_MC5_INT_REQUESTQ_PARITY_ERR(1U)
+
+#define S_MC5_INT_DISPATCHQ_PARITY_ERR 17
+#define V_MC5_INT_DISPATCHQ_PARITY_ERR(x) ((x) << S_MC5_INT_DISPATCHQ_PARITY_ERR)
+#define F_MC5_INT_DISPATCHQ_PARITY_ERR V_MC5_INT_DISPATCHQ_PARITY_ERR(1U)
+
+#define S_MC5_INT_DEL_ACT_EMPTY 18
+#define V_MC5_INT_DEL_ACT_EMPTY(x) ((x) << S_MC5_INT_DEL_ACT_EMPTY)
+#define F_MC5_INT_DEL_ACT_EMPTY V_MC5_INT_DEL_ACT_EMPTY(1U)
+
+#define A_MC5_INT_CAUSE 0xc44
+#define A_MC5_INT_TID 0xc48
+#define A_MC5_INT_PTID 0xc4c
+#define A_MC5_DBGI_CONFIG 0xc74
+#define A_MC5_DBGI_REQ_CMD 0xc78
+
+#define S_CMDMODE 0
+#define M_CMDMODE 0x7
+#define V_CMDMODE(x) ((x) << S_CMDMODE)
+#define G_CMDMODE(x) (((x) >> S_CMDMODE) & M_CMDMODE)
+
+#define S_SADRSEL 4
+#define V_SADRSEL(x) ((x) << S_SADRSEL)
+#define F_SADRSEL V_SADRSEL(1U)
+
+#define S_WRITE_BURST_SIZE 22
+#define M_WRITE_BURST_SIZE 0x3ff
+#define V_WRITE_BURST_SIZE(x) ((x) << S_WRITE_BURST_SIZE)
+#define G_WRITE_BURST_SIZE(x) (((x) >> S_WRITE_BURST_SIZE) & M_WRITE_BURST_SIZE)
+
+#define A_MC5_DBGI_REQ_ADDR0 0xc7c
+#define A_MC5_DBGI_REQ_ADDR1 0xc80
+#define A_MC5_DBGI_REQ_ADDR2 0xc84
+#define A_MC5_DBGI_REQ_DATA0 0xc88
+#define A_MC5_DBGI_REQ_DATA1 0xc8c
+#define A_MC5_DBGI_REQ_DATA2 0xc90
+#define A_MC5_DBGI_REQ_DATA3 0xc94
+#define A_MC5_DBGI_REQ_DATA4 0xc98
+#define A_MC5_DBGI_REQ_MASK0 0xc9c
+#define A_MC5_DBGI_REQ_MASK1 0xca0
+#define A_MC5_DBGI_REQ_MASK2 0xca4
+#define A_MC5_DBGI_REQ_MASK3 0xca8
+#define A_MC5_DBGI_REQ_MASK4 0xcac
+#define A_MC5_DBGI_RSP_STATUS 0xcb0
+
+#define S_DBGI_RSP_VALID 0
+#define V_DBGI_RSP_VALID(x) ((x) << S_DBGI_RSP_VALID)
+#define F_DBGI_RSP_VALID V_DBGI_RSP_VALID(1U)
+
+#define S_DBGI_RSP_HIT 1
+#define V_DBGI_RSP_HIT(x) ((x) << S_DBGI_RSP_HIT)
+#define F_DBGI_RSP_HIT V_DBGI_RSP_HIT(1U)
+
+#define S_DBGI_RSP_ERR 2
+#define V_DBGI_RSP_ERR(x) ((x) << S_DBGI_RSP_ERR)
+#define F_DBGI_RSP_ERR V_DBGI_RSP_ERR(1U)
+
+#define S_DBGI_RSP_ERR_REASON 8
+#define M_DBGI_RSP_ERR_REASON 0x7
+#define V_DBGI_RSP_ERR_REASON(x) ((x) << S_DBGI_RSP_ERR_REASON)
+#define G_DBGI_RSP_ERR_REASON(x) (((x) >> S_DBGI_RSP_ERR_REASON) & M_DBGI_RSP_ERR_REASON)
+
+#define A_MC5_DBGI_RSP_DATA0 0xcb4
+#define A_MC5_DBGI_RSP_DATA1 0xcb8
+#define A_MC5_DBGI_RSP_DATA2 0xcbc
+#define A_MC5_DBGI_RSP_DATA3 0xcc0
+#define A_MC5_DBGI_RSP_DATA4 0xcc4
+#define A_MC5_DBGI_RSP_LAST_CMD 0xcc8
+#define A_MC5_POPEN_DATA_WR_CMD 0xccc
+#define A_MC5_POPEN_MASK_WR_CMD 0xcd0
+#define A_MC5_AOPEN_SRCH_CMD 0xcd4
+#define A_MC5_AOPEN_LRN_CMD 0xcd8
+#define A_MC5_SYN_SRCH_CMD 0xcdc
+#define A_MC5_SYN_LRN_CMD 0xce0
+#define A_MC5_ACK_SRCH_CMD 0xce4
+#define A_MC5_ACK_LRN_CMD 0xce8
+#define A_MC5_ILOOKUP_CMD 0xcec
+#define A_MC5_ELOOKUP_CMD 0xcf0
+#define A_MC5_DATA_WRITE_CMD 0xcf4
+#define A_MC5_DATA_READ_CMD 0xcf8
+#define A_MC5_MASK_WRITE_CMD 0xcfc
+
+/* PCICFG registers */
#define A_PCICFG_PM_CSR 0x44
#define A_PCICFG_VPD_ADDR 0x4a
+#define S_VPD_ADDR 0
+#define M_VPD_ADDR 0x7fff
+#define V_VPD_ADDR(x) ((x) << S_VPD_ADDR)
+#define G_VPD_ADDR(x) (((x) >> S_VPD_ADDR) & M_VPD_ADDR)
+
#define S_VPD_OP_FLAG 15
#define V_VPD_OP_FLAG(x) ((x) << S_VPD_OP_FLAG)
#define F_VPD_OP_FLAG V_VPD_OP_FLAG(1U)
#define A_PCICFG_VPD_DATA 0x4c
-
+#define A_PCICFG_PCIX_CMD 0x60
#define A_PCICFG_INTR_ENABLE 0xf4
-#define A_PCICFG_INTR_CAUSE 0xf8
+#define S_MASTER_PARITY_ERR 0
+#define V_MASTER_PARITY_ERR(x) ((x) << S_MASTER_PARITY_ERR)
+#define F_MASTER_PARITY_ERR V_MASTER_PARITY_ERR(1U)
+
+#define S_SIG_TARGET_ABORT 1
+#define V_SIG_TARGET_ABORT(x) ((x) << S_SIG_TARGET_ABORT)
+#define F_SIG_TARGET_ABORT V_SIG_TARGET_ABORT(1U)
+
+#define S_RCV_TARGET_ABORT 2
+#define V_RCV_TARGET_ABORT(x) ((x) << S_RCV_TARGET_ABORT)
+#define F_RCV_TARGET_ABORT V_RCV_TARGET_ABORT(1U)
+
+#define S_RCV_MASTER_ABORT 3
+#define V_RCV_MASTER_ABORT(x) ((x) << S_RCV_MASTER_ABORT)
+#define F_RCV_MASTER_ABORT V_RCV_MASTER_ABORT(1U)
+
+#define S_SIG_SYS_ERR 4
+#define V_SIG_SYS_ERR(x) ((x) << S_SIG_SYS_ERR)
+#define F_SIG_SYS_ERR V_SIG_SYS_ERR(1U)
+
+#define S_DET_PARITY_ERR 5
+#define V_DET_PARITY_ERR(x) ((x) << S_DET_PARITY_ERR)
+#define F_DET_PARITY_ERR V_DET_PARITY_ERR(1U)
+
+#define S_PIO_PARITY_ERR 6
+#define V_PIO_PARITY_ERR(x) ((x) << S_PIO_PARITY_ERR)
+#define F_PIO_PARITY_ERR V_PIO_PARITY_ERR(1U)
+
+#define S_WF_PARITY_ERR 7
+#define V_WF_PARITY_ERR(x) ((x) << S_WF_PARITY_ERR)
+#define F_WF_PARITY_ERR V_WF_PARITY_ERR(1U)
+
+#define S_RF_PARITY_ERR 8
+#define M_RF_PARITY_ERR 0x3
+#define V_RF_PARITY_ERR(x) ((x) << S_RF_PARITY_ERR)
+#define G_RF_PARITY_ERR(x) (((x) >> S_RF_PARITY_ERR) & M_RF_PARITY_ERR)
+
+#define S_CF_PARITY_ERR 10
+#define M_CF_PARITY_ERR 0x3
+#define V_CF_PARITY_ERR(x) ((x) << S_CF_PARITY_ERR)
+#define G_CF_PARITY_ERR(x) (((x) >> S_CF_PARITY_ERR) & M_CF_PARITY_ERR)
+
+#define A_PCICFG_INTR_CAUSE 0xf8
#define A_PCICFG_MODE 0xfc
#define S_PCI_MODE_64BIT 0
#define V_PCI_MODE_64BIT(x) ((x) << S_PCI_MODE_64BIT)
#define F_PCI_MODE_64BIT V_PCI_MODE_64BIT(1U)
+#define S_PCI_MODE_66MHZ 1
+#define V_PCI_MODE_66MHZ(x) ((x) << S_PCI_MODE_66MHZ)
+#define F_PCI_MODE_66MHZ V_PCI_MODE_66MHZ(1U)
+
+#define S_PCI_MODE_PCIX_INITPAT 2
+#define M_PCI_MODE_PCIX_INITPAT 0x7
+#define V_PCI_MODE_PCIX_INITPAT(x) ((x) << S_PCI_MODE_PCIX_INITPAT)
+#define G_PCI_MODE_PCIX_INITPAT(x) (((x) >> S_PCI_MODE_PCIX_INITPAT) & M_PCI_MODE_PCIX_INITPAT)
+
#define S_PCI_MODE_PCIX 5
#define V_PCI_MODE_PCIX(x) ((x) << S_PCI_MODE_PCIX)
#define F_PCI_MODE_PCIX V_PCI_MODE_PCIX(1U)
#define S_PCI_MODE_CLK 6
#define M_PCI_MODE_CLK 0x3
+#define V_PCI_MODE_CLK(x) ((x) << S_PCI_MODE_CLK)
#define G_PCI_MODE_CLK(x) (((x) >> S_PCI_MODE_CLK) & M_PCI_MODE_CLK)
#endif /* _CXGB_REGS_H_ */
diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c
index 9799c12380fc..0ca8d876e16f 100644
--- a/drivers/net/chelsio/sge.c
+++ b/drivers/net/chelsio/sge.c
@@ -42,12 +42,14 @@
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/pci.h>
+#include <linux/ktime.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/if_vlan.h>
#include <linux/skbuff.h>
#include <linux/init.h>
#include <linux/mm.h>
+#include <linux/tcp.h>
#include <linux/ip.h>
#include <linux/in.h>
#include <linux/if_arp.h>
@@ -57,10 +59,8 @@
#include "regs.h"
#include "espi.h"
-
-#ifdef NETIF_F_TSO
-#include <linux/tcp.h>
-#endif
+/* This belongs in if_ether.h */
+#define ETH_P_CPL5 0xf
#define SGE_CMDQ_N 2
#define SGE_FREELQ_N 2
@@ -73,6 +73,7 @@
#define SGE_INTRTIMER_NRES 1000
#define SGE_RX_COPY_THRES 256
#define SGE_RX_SM_BUF_SIZE 1536
+#define SGE_TX_DESC_MAX_PLEN 16384
# define SGE_RX_DROP_THRES 2
@@ -184,17 +185,17 @@ struct cmdQ {
unsigned long status; /* HW DMA fetch status */
unsigned int in_use; /* # of in-use command descriptors */
unsigned int size; /* # of descriptors */
- unsigned int processed; /* total # of descs HW has processed */
- unsigned int cleaned; /* total # of descs SW has reclaimed */
- unsigned int stop_thres; /* SW TX queue suspend threshold */
+ unsigned int processed; /* total # of descs HW has processed */
+ unsigned int cleaned; /* total # of descs SW has reclaimed */
+ unsigned int stop_thres; /* SW TX queue suspend threshold */
u16 pidx; /* producer index (SW) */
u16 cidx; /* consumer index (HW) */
u8 genbit; /* current generation (=valid) bit */
- u8 sop; /* is next entry start of packet? */
+ u8 sop; /* is next entry start of packet? */
struct cmdQ_e *entries; /* HW command descriptor Q */
struct cmdQ_ce *centries; /* SW command context descriptor Q */
- spinlock_t lock; /* Lock to protect cmdQ enqueuing */
dma_addr_t dma_addr; /* DMA addr HW command descriptor Q */
+ spinlock_t lock; /* Lock to protect cmdQ enqueuing */
};
struct freelQ {
@@ -203,8 +204,8 @@ struct freelQ {
u16 pidx; /* producer index (SW) */
u16 cidx; /* consumer index (HW) */
u16 rx_buffer_size; /* Buffer size on this free list */
- u16 dma_offset; /* DMA offset to align IP headers */
- u16 recycleq_idx; /* skb recycle q to use */
+ u16 dma_offset; /* DMA offset to align IP headers */
+ u16 recycleq_idx; /* skb recycle q to use */
u8 genbit; /* current generation (=valid) bit */
struct freelQ_e *entries; /* HW freelist descriptor Q */
struct freelQ_ce *centries; /* SW freelist context descriptor Q */
@@ -226,6 +227,29 @@ enum {
CMDQ_STAT_LAST_PKT_DB = 2 /* last packet rung the doorbell */
};
+/* T204 TX SW scheduler */
+
+/* Per T204 TX port */
+struct sched_port {
+ unsigned int avail; /* available bits - quota */
+ unsigned int drain_bits_per_1024ns; /* drain rate */
+ unsigned int speed; /* drain rate, mbps */
+ unsigned int mtu; /* mtu size */
+ struct sk_buff_head skbq; /* pending skbs */
+};
+
+/* Per T204 device */
+struct sched {
+ ktime_t last_updated; /* last time quotas were computed */
+ unsigned int max_avail; /* max bits to be sent to any port */
+ unsigned int port; /* port index (round robin ports) */
+ unsigned int num; /* num skbs in per port queues */
+ struct sched_port p[MAX_NPORTS];
+ struct tasklet_struct sched_tsk;/* tasklet used to run scheduler */
+};
+static void restart_sched(unsigned long);
+
+
/*
* Main SGE data structure
*
@@ -243,18 +267,240 @@ struct sge {
unsigned int rx_pkt_pad; /* RX padding for L2 packets */
unsigned int jumbo_fl; /* jumbo freelist Q index */
unsigned int intrtimer_nres; /* no-resource interrupt timer */
- unsigned int fixed_intrtimer;/* non-adaptive interrupt timer */
+ unsigned int fixed_intrtimer;/* non-adaptive interrupt timer */
struct timer_list tx_reclaim_timer; /* reclaims TX buffers */
struct timer_list espibug_timer;
- unsigned int espibug_timeout;
- struct sk_buff *espibug_skb;
+ unsigned long espibug_timeout;
+ struct sk_buff *espibug_skb[MAX_NPORTS];
u32 sge_control; /* shadow value of sge control reg */
struct sge_intr_counts stats;
- struct sge_port_stats port_stats[MAX_NPORTS];
+ struct sge_port_stats *port_stats[MAX_NPORTS];
+ struct sched *tx_sched;
struct cmdQ cmdQ[SGE_CMDQ_N] ____cacheline_aligned_in_smp;
};
/*
+ * stop tasklet and free all pending skb's
+ */
+static void tx_sched_stop(struct sge *sge)
+{
+ struct sched *s = sge->tx_sched;
+ int i;
+
+ tasklet_kill(&s->sched_tsk);
+
+ for (i = 0; i < MAX_NPORTS; i++)
+ __skb_queue_purge(&s->p[s->port].skbq);
+}
+
+/*
+ * t1_sched_update_parms() is called when the MTU or link speed changes. It
+ * re-computes scheduler parameters to scope with the change.
+ */
+unsigned int t1_sched_update_parms(struct sge *sge, unsigned int port,
+ unsigned int mtu, unsigned int speed)
+{
+ struct sched *s = sge->tx_sched;
+ struct sched_port *p = &s->p[port];
+ unsigned int max_avail_segs;
+
+ pr_debug("t1_sched_update_params mtu=%d speed=%d\n", mtu, speed);
+ if (speed)
+ p->speed = speed;
+ if (mtu)
+ p->mtu = mtu;
+
+ if (speed || mtu) {
+ unsigned long long drain = 1024ULL * p->speed * (p->mtu - 40);
+ do_div(drain, (p->mtu + 50) * 1000);
+ p->drain_bits_per_1024ns = (unsigned int) drain;
+
+ if (p->speed < 1000)
+ p->drain_bits_per_1024ns =
+ 90 * p->drain_bits_per_1024ns / 100;
+ }
+
+ if (board_info(sge->adapter)->board == CHBT_BOARD_CHT204) {
+ p->drain_bits_per_1024ns -= 16;
+ s->max_avail = max(4096U, p->mtu + 16 + 14 + 4);
+ max_avail_segs = max(1U, 4096 / (p->mtu - 40));
+ } else {
+ s->max_avail = 16384;
+ max_avail_segs = max(1U, 9000 / (p->mtu - 40));
+ }
+
+ pr_debug("t1_sched_update_parms: mtu %u speed %u max_avail %u "
+ "max_avail_segs %u drain_bits_per_1024ns %u\n", p->mtu,
+ p->speed, s->max_avail, max_avail_segs,
+ p->drain_bits_per_1024ns);
+
+ return max_avail_segs * (p->mtu - 40);
+}
+
+/*
+ * t1_sched_max_avail_bytes() tells the scheduler the maximum amount of
+ * data that can be pushed per port.
+ */
+void t1_sched_set_max_avail_bytes(struct sge *sge, unsigned int val)
+{
+ struct sched *s = sge->tx_sched;
+ unsigned int i;
+
+ s->max_avail = val;
+ for (i = 0; i < MAX_NPORTS; i++)
+ t1_sched_update_parms(sge, i, 0, 0);
+}
+
+/*
+ * t1_sched_set_drain_bits_per_us() tells the scheduler at which rate a port
+ * is draining.
+ */
+void t1_sched_set_drain_bits_per_us(struct sge *sge, unsigned int port,
+ unsigned int val)
+{
+ struct sched *s = sge->tx_sched;
+ struct sched_port *p = &s->p[port];
+ p->drain_bits_per_1024ns = val * 1024 / 1000;
+ t1_sched_update_parms(sge, port, 0, 0);
+}
+
+
+/*
+ * get_clock() implements a ns clock (see ktime_get)
+ */
+static inline ktime_t get_clock(void)
+{
+ struct timespec ts;
+
+ ktime_get_ts(&ts);
+ return timespec_to_ktime(ts);
+}
+
+/*
+ * tx_sched_init() allocates resources and does basic initialization.
+ */
+static int tx_sched_init(struct sge *sge)
+{
+ struct sched *s;
+ int i;
+
+ s = kzalloc(sizeof (struct sched), GFP_KERNEL);
+ if (!s)
+ return -ENOMEM;
+
+ pr_debug("tx_sched_init\n");
+ tasklet_init(&s->sched_tsk, restart_sched, (unsigned long) sge);
+ sge->tx_sched = s;
+
+ for (i = 0; i < MAX_NPORTS; i++) {
+ skb_queue_head_init(&s->p[i].skbq);
+ t1_sched_update_parms(sge, i, 1500, 1000);
+ }
+
+ return 0;
+}
+
+/*
+ * sched_update_avail() computes the delta since the last time it was called
+ * and updates the per port quota (number of bits that can be sent to the any
+ * port).
+ */
+static inline int sched_update_avail(struct sge *sge)
+{
+ struct sched *s = sge->tx_sched;
+ ktime_t now = get_clock();
+ unsigned int i;
+ long long delta_time_ns;
+
+ delta_time_ns = ktime_to_ns(ktime_sub(now, s->last_updated));
+
+ pr_debug("sched_update_avail delta=%lld\n", delta_time_ns);
+ if (delta_time_ns < 15000)
+ return 0;
+
+ for (i = 0; i < MAX_NPORTS; i++) {
+ struct sched_port *p = &s->p[i];
+ unsigned int delta_avail;
+
+ delta_avail = (p->drain_bits_per_1024ns * delta_time_ns) >> 13;
+ p->avail = min(p->avail + delta_avail, s->max_avail);
+ }
+
+ s->last_updated = now;
+
+ return 1;
+}
+
+/*
+ * sched_skb() is called from two different places. In the tx path, any
+ * packet generating load on an output port will call sched_skb()
+ * (skb != NULL). In addition, sched_skb() is called from the irq/soft irq
+ * context (skb == NULL).
+ * The scheduler only returns a skb (which will then be sent) if the
+ * length of the skb is <= the current quota of the output port.
+ */
+static struct sk_buff *sched_skb(struct sge *sge, struct sk_buff *skb,
+ unsigned int credits)
+{
+ struct sched *s = sge->tx_sched;
+ struct sk_buff_head *skbq;
+ unsigned int i, len, update = 1;
+
+ pr_debug("sched_skb %p\n", skb);
+ if (!skb) {
+ if (!s->num)
+ return NULL;
+ } else {
+ skbq = &s->p[skb->dev->if_port].skbq;
+ __skb_queue_tail(skbq, skb);
+ s->num++;
+ skb = NULL;
+ }
+
+ if (credits < MAX_SKB_FRAGS + 1)
+ goto out;
+
+ again:
+ for (i = 0; i < MAX_NPORTS; i++) {
+ s->port = ++s->port & (MAX_NPORTS - 1);
+ skbq = &s->p[s->port].skbq;
+
+ skb = skb_peek(skbq);
+
+ if (!skb)
+ continue;
+
+ len = skb->len;
+ if (len <= s->p[s->port].avail) {
+ s->p[s->port].avail -= len;
+ s->num--;
+ __skb_unlink(skb, skbq);
+ goto out;
+ }
+ skb = NULL;
+ }
+
+ if (update-- && sched_update_avail(sge))
+ goto again;
+
+ out:
+ /* If there are more pending skbs, we use the hardware to schedule us
+ * again.
+ */
+ if (s->num && !skb) {
+ struct cmdQ *q = &sge->cmdQ[0];
+ clear_bit(CMDQ_STAT_LAST_PKT_DB, &q->status);
+ if (test_and_set_bit(CMDQ_STAT_RUNNING, &q->status) == 0) {
+ set_bit(CMDQ_STAT_LAST_PKT_DB, &q->status);
+ writel(F_CMDQ0_ENABLE, sge->adapter->regs + A_SG_DOORBELL);
+ }
+ }
+ pr_debug("sched_skb ret %p\n", skb);
+
+ return skb;
+}
+
+/*
* PIO to indicate that memory mapped Q contains valid descriptor(s).
*/
static inline void doorbell_pio(struct adapter *adapter, u32 val)
@@ -335,10 +581,9 @@ static int alloc_rx_resources(struct sge *sge, struct sge_params *p)
goto err_no_mem;
memset(q->entries, 0, size);
size = sizeof(struct freelQ_ce) * q->size;
- q->centries = kmalloc(size, GFP_KERNEL);
+ q->centries = kzalloc(size, GFP_KERNEL);
if (!q->centries)
goto err_no_mem;
- memset(q->centries, 0, size);
}
/*
@@ -351,8 +596,11 @@ static int alloc_rx_resources(struct sge *sge, struct sge_params *p)
sge->freelQ[!sge->jumbo_fl].rx_buffer_size = SGE_RX_SM_BUF_SIZE +
sizeof(struct cpl_rx_data) +
sge->freelQ[!sge->jumbo_fl].dma_offset;
- sge->freelQ[sge->jumbo_fl].rx_buffer_size = (16 * 1024) -
- SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+
+ size = (16 * 1024) -
+ SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+
+ sge->freelQ[sge->jumbo_fl].rx_buffer_size = size;
/*
* Setup which skb recycle Q should be used when recycling buffers from
@@ -389,17 +637,23 @@ static void free_cmdQ_buffers(struct sge *sge, struct cmdQ *q, unsigned int n)
q->in_use -= n;
ce = &q->centries[cidx];
while (n--) {
- if (q->sop)
- pci_unmap_single(pdev, pci_unmap_addr(ce, dma_addr),
- pci_unmap_len(ce, dma_len),
- PCI_DMA_TODEVICE);
- else
- pci_unmap_page(pdev, pci_unmap_addr(ce, dma_addr),
- pci_unmap_len(ce, dma_len),
- PCI_DMA_TODEVICE);
- q->sop = 0;
+ if (q->sop) {
+ if (likely(pci_unmap_len(ce, dma_len))) {
+ pci_unmap_single(pdev,
+ pci_unmap_addr(ce, dma_addr),
+ pci_unmap_len(ce, dma_len),
+ PCI_DMA_TODEVICE);
+ q->sop = 0;
+ }
+ } else {
+ if (likely(pci_unmap_len(ce, dma_len))) {
+ pci_unmap_page(pdev, pci_unmap_addr(ce, dma_addr),
+ pci_unmap_len(ce, dma_len),
+ PCI_DMA_TODEVICE);
+ }
+ }
if (ce->skb) {
- dev_kfree_skb(ce->skb);
+ dev_kfree_skb_any(ce->skb);
q->sop = 1;
}
ce++;
@@ -463,10 +717,9 @@ static int alloc_tx_resources(struct sge *sge, struct sge_params *p)
goto err_no_mem;
memset(q->entries, 0, size);
size = sizeof(struct cmdQ_ce) * q->size;
- q->centries = kmalloc(size, GFP_KERNEL);
+ q->centries = kzalloc(size, GFP_KERNEL);
if (!q->centries)
goto err_no_mem;
- memset(q->centries, 0, size);
}
/*
@@ -506,7 +759,7 @@ void t1_set_vlan_accel(struct adapter *adapter, int on_off)
sge->sge_control |= F_VLAN_XTRACT;
if (adapter->open_device_map) {
writel(sge->sge_control, adapter->regs + A_SG_CONTROL);
- readl(adapter->regs + A_SG_CONTROL); /* flush */
+ readl(adapter->regs + A_SG_CONTROL); /* flush */
}
}
@@ -540,7 +793,6 @@ static void configure_sge(struct sge *sge, struct sge_params *p)
sge->sge_control = F_CMDQ0_ENABLE | F_CMDQ1_ENABLE | F_FL0_ENABLE |
F_FL1_ENABLE | F_CPL_ENABLE | F_RESPONSE_QUEUE_ENABLE |
V_CMDQ_PRIORITY(2) | F_DISABLE_CMDQ1_GTS | F_ISCSI_COALESCE |
- F_DISABLE_FL0_GTS | F_DISABLE_FL1_GTS |
V_RX_PKT_OFFSET(sge->rx_pkt_pad);
#if defined(__BIG_ENDIAN_BITFIELD)
@@ -568,9 +820,12 @@ static inline unsigned int jumbo_payload_capacity(const struct sge *sge)
*/
void t1_sge_destroy(struct sge *sge)
{
- if (sge->espibug_skb)
- kfree_skb(sge->espibug_skb);
+ int i;
+ for_each_port(sge->adapter, i)
+ free_percpu(sge->port_stats[i]);
+
+ kfree(sge->tx_sched);
free_tx_resources(sge);
free_rx_resources(sge);
kfree(sge);
@@ -735,14 +990,28 @@ int t1_sge_intr_error_handler(struct sge *sge)
return 0;
}
-const struct sge_intr_counts *t1_sge_get_intr_counts(struct sge *sge)
+const struct sge_intr_counts *t1_sge_get_intr_counts(const struct sge *sge)
{
return &sge->stats;
}
-const struct sge_port_stats *t1_sge_get_port_stats(struct sge *sge, int port)
+void t1_sge_get_port_stats(const struct sge *sge, int port,
+ struct sge_port_stats *ss)
{
- return &sge->port_stats[port];
+ int cpu;
+
+ memset(ss, 0, sizeof(*ss));
+ for_each_possible_cpu(cpu) {
+ struct sge_port_stats *st = per_cpu_ptr(sge->port_stats[port], cpu);
+
+ ss->rx_packets += st->rx_packets;
+ ss->rx_cso_good += st->rx_cso_good;
+ ss->tx_packets += st->tx_packets;
+ ss->tx_cso += st->tx_cso;
+ ss->tx_tso += st->tx_tso;
+ ss->vlan_xtract += st->vlan_xtract;
+ ss->vlan_insert += st->vlan_insert;
+ }
}
/**
@@ -856,6 +1125,99 @@ static void unexpected_offload(struct adapter *adapter, struct freelQ *fl)
}
/*
+ * T1/T2 SGE limits the maximum DMA size per TX descriptor to
+ * SGE_TX_DESC_MAX_PLEN (16KB). If the PAGE_SIZE is larger than 16KB, the
+ * stack might send more than SGE_TX_DESC_MAX_PLEN in a contiguous manner.
+ * Note that the *_large_page_tx_descs stuff will be optimized out when
+ * PAGE_SIZE <= SGE_TX_DESC_MAX_PLEN.
+ *
+ * compute_large_page_descs() computes how many additional descriptors are
+ * required to break down the stack's request.
+ */
+static inline unsigned int compute_large_page_tx_descs(struct sk_buff *skb)
+{
+ unsigned int count = 0;
+ if (PAGE_SIZE > SGE_TX_DESC_MAX_PLEN) {
+ unsigned int nfrags = skb_shinfo(skb)->nr_frags;
+ unsigned int i, len = skb->len - skb->data_len;
+ while (len > SGE_TX_DESC_MAX_PLEN) {
+ count++;
+ len -= SGE_TX_DESC_MAX_PLEN;
+ }
+ for (i = 0; nfrags--; i++) {
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ len = frag->size;
+ while (len > SGE_TX_DESC_MAX_PLEN) {
+ count++;
+ len -= SGE_TX_DESC_MAX_PLEN;
+ }
+ }
+ }
+ return count;
+}
+
+/*
+ * Write a cmdQ entry.
+ *
+ * Since this function writes the 'flags' field, it must not be used to
+ * write the first cmdQ entry.
+ */
+static inline void write_tx_desc(struct cmdQ_e *e, dma_addr_t mapping,
+ unsigned int len, unsigned int gen,
+ unsigned int eop)
+{
+ if (unlikely(len > SGE_TX_DESC_MAX_PLEN))
+ BUG();
+ e->addr_lo = (u32)mapping;
+ e->addr_hi = (u64)mapping >> 32;
+ e->len_gen = V_CMD_LEN(len) | V_CMD_GEN1(gen);
+ e->flags = F_CMD_DATAVALID | V_CMD_EOP(eop) | V_CMD_GEN2(gen);
+}
+
+/*
+ * See comment for previous function.
+ *
+ * write_tx_descs_large_page() writes additional SGE tx descriptors if
+ * *desc_len exceeds HW's capability.
+ */
+static inline unsigned int write_large_page_tx_descs(unsigned int pidx,
+ struct cmdQ_e **e,
+ struct cmdQ_ce **ce,
+ unsigned int *gen,
+ dma_addr_t *desc_mapping,
+ unsigned int *desc_len,
+ unsigned int nfrags,
+ struct cmdQ *q)
+{
+ if (PAGE_SIZE > SGE_TX_DESC_MAX_PLEN) {
+ struct cmdQ_e *e1 = *e;
+ struct cmdQ_ce *ce1 = *ce;
+
+ while (*desc_len > SGE_TX_DESC_MAX_PLEN) {
+ *desc_len -= SGE_TX_DESC_MAX_PLEN;
+ write_tx_desc(e1, *desc_mapping, SGE_TX_DESC_MAX_PLEN,
+ *gen, nfrags == 0 && *desc_len == 0);
+ ce1->skb = NULL;
+ pci_unmap_len_set(ce1, dma_len, 0);
+ *desc_mapping += SGE_TX_DESC_MAX_PLEN;
+ if (*desc_len) {
+ ce1++;
+ e1++;
+ if (++pidx == q->size) {
+ pidx = 0;
+ *gen ^= 1;
+ ce1 = q->centries;
+ e1 = q->entries;
+ }
+ }
+ }
+ *e = e1;
+ *ce = ce1;
+ }
+ return pidx;
+}
+
+/*
* Write the command descriptors to transmit the given skb starting at
* descriptor pidx with the given generation.
*/
@@ -863,50 +1225,84 @@ static inline void write_tx_descs(struct adapter *adapter, struct sk_buff *skb,
unsigned int pidx, unsigned int gen,
struct cmdQ *q)
{
- dma_addr_t mapping;
+ dma_addr_t mapping, desc_mapping;
struct cmdQ_e *e, *e1;
struct cmdQ_ce *ce;
- unsigned int i, flags, nfrags = skb_shinfo(skb)->nr_frags;
+ unsigned int i, flags, first_desc_len, desc_len,
+ nfrags = skb_shinfo(skb)->nr_frags;
- mapping = pci_map_single(adapter->pdev, skb->data,
- skb->len - skb->data_len, PCI_DMA_TODEVICE);
+ e = e1 = &q->entries[pidx];
ce = &q->centries[pidx];
+
+ mapping = pci_map_single(adapter->pdev, skb->data,
+ skb->len - skb->data_len, PCI_DMA_TODEVICE);
+
+ desc_mapping = mapping;
+ desc_len = skb->len - skb->data_len;
+
+ flags = F_CMD_DATAVALID | F_CMD_SOP |
+ V_CMD_EOP(nfrags == 0 && desc_len <= SGE_TX_DESC_MAX_PLEN) |
+ V_CMD_GEN2(gen);
+ first_desc_len = (desc_len <= SGE_TX_DESC_MAX_PLEN) ?
+ desc_len : SGE_TX_DESC_MAX_PLEN;
+ e->addr_lo = (u32)desc_mapping;
+ e->addr_hi = (u64)desc_mapping >> 32;
+ e->len_gen = V_CMD_LEN(first_desc_len) | V_CMD_GEN1(gen);
+ ce->skb = NULL;
+ pci_unmap_len_set(ce, dma_len, 0);
+
+ if (PAGE_SIZE > SGE_TX_DESC_MAX_PLEN &&
+ desc_len > SGE_TX_DESC_MAX_PLEN) {
+ desc_mapping += first_desc_len;
+ desc_len -= first_desc_len;
+ e1++;
+ ce++;
+ if (++pidx == q->size) {
+ pidx = 0;
+ gen ^= 1;
+ e1 = q->entries;
+ ce = q->centries;
+ }
+ pidx = write_large_page_tx_descs(pidx, &e1, &ce, &gen,
+ &desc_mapping, &desc_len,
+ nfrags, q);
+
+ if (likely(desc_len))
+ write_tx_desc(e1, desc_mapping, desc_len, gen,
+ nfrags == 0);
+ }
+
ce->skb = NULL;
pci_unmap_addr_set(ce, dma_addr, mapping);
pci_unmap_len_set(ce, dma_len, skb->len - skb->data_len);
- flags = F_CMD_DATAVALID | F_CMD_SOP | V_CMD_EOP(nfrags == 0) |
- V_CMD_GEN2(gen);
- e = &q->entries[pidx];
- e->addr_lo = (u32)mapping;
- e->addr_hi = (u64)mapping >> 32;
- e->len_gen = V_CMD_LEN(skb->len - skb->data_len) | V_CMD_GEN1(gen);
- for (e1 = e, i = 0; nfrags--; i++) {
+ for (i = 0; nfrags--; i++) {
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-
- ce++;
e1++;
+ ce++;
if (++pidx == q->size) {
pidx = 0;
gen ^= 1;
- ce = q->centries;
e1 = q->entries;
+ ce = q->centries;
}
mapping = pci_map_page(adapter->pdev, frag->page,
frag->page_offset, frag->size,
PCI_DMA_TODEVICE);
+ desc_mapping = mapping;
+ desc_len = frag->size;
+
+ pidx = write_large_page_tx_descs(pidx, &e1, &ce, &gen,
+ &desc_mapping, &desc_len,
+ nfrags, q);
+ if (likely(desc_len))
+ write_tx_desc(e1, desc_mapping, desc_len, gen,
+ nfrags == 0);
ce->skb = NULL;
pci_unmap_addr_set(ce, dma_addr, mapping);
pci_unmap_len_set(ce, dma_len, frag->size);
-
- e1->addr_lo = (u32)mapping;
- e1->addr_hi = (u64)mapping >> 32;
- e1->len_gen = V_CMD_LEN(frag->size) | V_CMD_GEN1(gen);
- e1->flags = F_CMD_DATAVALID | V_CMD_EOP(nfrags == 0) |
- V_CMD_GEN2(gen);
}
-
ce->skb = skb;
wmb();
e->flags = flags;
@@ -920,26 +1316,56 @@ static inline void reclaim_completed_tx(struct sge *sge, struct cmdQ *q)
unsigned int reclaim = q->processed - q->cleaned;
if (reclaim) {
+ pr_debug("reclaim_completed_tx processed:%d cleaned:%d\n",
+ q->processed, q->cleaned);
free_cmdQ_buffers(sge, q, reclaim);
q->cleaned += reclaim;
}
}
-#ifndef SET_ETHTOOL_OPS
-# define __netif_rx_complete(dev) netif_rx_complete(dev)
-#endif
-
/*
- * We cannot use the standard netif_rx_schedule_prep() because we have multiple
- * ports plus the TOE all multiplexing onto a single response queue, therefore
- * accepting new responses cannot depend on the state of any particular port.
- * So define our own equivalent that omits the netif_running() test.
+ * Called from tasklet. Checks the scheduler for any
+ * pending skbs that can be sent.
*/
-static inline int napi_schedule_prep(struct net_device *dev)
+static void restart_sched(unsigned long arg)
{
- return !test_and_set_bit(__LINK_STATE_RX_SCHED, &dev->state);
-}
+ struct sge *sge = (struct sge *) arg;
+ struct adapter *adapter = sge->adapter;
+ struct cmdQ *q = &sge->cmdQ[0];
+ struct sk_buff *skb;
+ unsigned int credits, queued_skb = 0;
+ spin_lock(&q->lock);
+ reclaim_completed_tx(sge, q);
+
+ credits = q->size - q->in_use;
+ pr_debug("restart_sched credits=%d\n", credits);
+ while ((skb = sched_skb(sge, NULL, credits)) != NULL) {
+ unsigned int genbit, pidx, count;
+ count = 1 + skb_shinfo(skb)->nr_frags;
+ count += compute_large_page_tx_descs(skb);
+ q->in_use += count;
+ genbit = q->genbit;
+ pidx = q->pidx;
+ q->pidx += count;
+ if (q->pidx >= q->size) {
+ q->pidx -= q->size;
+ q->genbit ^= 1;
+ }
+ write_tx_descs(adapter, skb, pidx, genbit, q);
+ credits = q->size - q->in_use;
+ queued_skb = 1;
+ }
+
+ if (queued_skb) {
+ clear_bit(CMDQ_STAT_LAST_PKT_DB, &q->status);
+ if (test_and_set_bit(CMDQ_STAT_RUNNING, &q->status) == 0) {
+ set_bit(CMDQ_STAT_LAST_PKT_DB, &q->status);
+ writel(F_CMDQ0_ENABLE, adapter->regs + A_SG_DOORBELL);
+ }
+ }
+ spin_unlock(&q->lock);
+}
/**
* sge_rx - process an ingress ethernet packet
@@ -954,31 +1380,39 @@ static int sge_rx(struct sge *sge, struct freelQ *fl, unsigned int len)
struct sk_buff *skb;
struct cpl_rx_pkt *p;
struct adapter *adapter = sge->adapter;
+ struct sge_port_stats *st;
- sge->stats.ethernet_pkts++;
skb = get_packet(adapter->pdev, fl, len - sge->rx_pkt_pad,
sge->rx_pkt_pad, 2, SGE_RX_COPY_THRES,
SGE_RX_DROP_THRES);
- if (!skb) {
- sge->port_stats[0].rx_drops++; /* charge only port 0 for now */
+ if (unlikely(!skb)) {
+ sge->stats.rx_drops++;
return 0;
}
p = (struct cpl_rx_pkt *)skb->data;
skb_pull(skb, sizeof(*p));
+ if (p->iff >= adapter->params.nports) {
+ kfree_skb(skb);
+ return 0;
+ }
+
skb->dev = adapter->port[p->iff].dev;
skb->dev->last_rx = jiffies;
+ st = per_cpu_ptr(sge->port_stats[p->iff], smp_processor_id());
+ st->rx_packets++;
+
skb->protocol = eth_type_trans(skb, skb->dev);
if ((adapter->flags & RX_CSUM_ENABLED) && p->csum == 0xffff &&
skb->protocol == htons(ETH_P_IP) &&
(skb->data[9] == IPPROTO_TCP || skb->data[9] == IPPROTO_UDP)) {
- sge->port_stats[p->iff].rx_cso_good++;
+ ++st->rx_cso_good;
skb->ip_summed = CHECKSUM_UNNECESSARY;
} else
skb->ip_summed = CHECKSUM_NONE;
if (unlikely(adapter->vlan_grp && p->vlan_valid)) {
- sge->port_stats[p->iff].vlan_xtract++;
+ st->vlan_xtract++;
if (adapter->params.sge.polling)
vlan_hwaccel_receive_skb(skb, adapter->vlan_grp,
ntohs(p->vlan));
@@ -1039,18 +1473,24 @@ static unsigned int update_tx_info(struct adapter *adapter,
struct cmdQ *cmdq = &sge->cmdQ[0];
cmdq->processed += pr0;
-
+ if (flags & (F_FL0_ENABLE | F_FL1_ENABLE)) {
+ freelQs_empty(sge);
+ flags &= ~(F_FL0_ENABLE | F_FL1_ENABLE);
+ }
if (flags & F_CMDQ0_ENABLE) {
clear_bit(CMDQ_STAT_RUNNING, &cmdq->status);
-
+
if (cmdq->cleaned + cmdq->in_use != cmdq->processed &&
!test_and_set_bit(CMDQ_STAT_LAST_PKT_DB, &cmdq->status)) {
set_bit(CMDQ_STAT_RUNNING, &cmdq->status);
writel(F_CMDQ0_ENABLE, adapter->regs + A_SG_DOORBELL);
}
- flags &= ~F_CMDQ0_ENABLE;
+ if (sge->tx_sched)
+ tasklet_hi_schedule(&sge->tx_sched->sched_tsk);
+
+ flags &= ~F_CMDQ0_ENABLE;
}
-
+
if (unlikely(sge->stopped_tx_queues != 0))
restart_tx_queues(sge);
@@ -1241,20 +1681,21 @@ static irqreturn_t t1_interrupt_napi(int irq, void *data)
if (e->GenerationBit == q->genbit) {
if (e->DataValid ||
process_pure_responses(adapter, e)) {
- if (likely(napi_schedule_prep(sge->netdev)))
+ if (likely(__netif_rx_schedule_prep(sge->netdev)))
__netif_rx_schedule(sge->netdev);
- else
- printk(KERN_CRIT
+ else if (net_ratelimit())
+ printk(KERN_INFO
"NAPI schedule failure!\n");
} else
- writel(q->cidx, adapter->regs + A_SG_SLEEPING);
+ writel(q->cidx, adapter->regs + A_SG_SLEEPING);
+
handled = 1;
goto unlock;
} else
- writel(q->cidx, adapter->regs + A_SG_SLEEPING);
- } else
- if (readl(adapter->regs + A_PL_CAUSE) & F_PL_INTR_SGE_DATA)
- printk(KERN_ERR "data interrupt while NAPI running\n");
+ writel(q->cidx, adapter->regs + A_SG_SLEEPING);
+ } else if (readl(adapter->regs + A_PL_CAUSE) & F_PL_INTR_SGE_DATA) {
+ printk(KERN_ERR "data interrupt while NAPI running\n");
+ }
handled = t1_slow_intr_handler(adapter);
if (!handled)
@@ -1335,34 +1776,59 @@ static int t1_sge_tx(struct sk_buff *skb, struct adapter *adapter,
{
struct sge *sge = adapter->sge;
struct cmdQ *q = &sge->cmdQ[qid];
- unsigned int credits, pidx, genbit, count;
+ unsigned int credits, pidx, genbit, count, use_sched_skb = 0;
+
+ if (!spin_trylock(&q->lock))
+ return NETDEV_TX_LOCKED;
- spin_lock(&q->lock);
reclaim_completed_tx(sge, q);
pidx = q->pidx;
credits = q->size - q->in_use;
count = 1 + skb_shinfo(skb)->nr_frags;
+ count += compute_large_page_tx_descs(skb);
- { /* Ethernet packet */
- if (unlikely(credits < count)) {
+ /* Ethernet packet */
+ if (unlikely(credits < count)) {
+ if (!netif_queue_stopped(dev)) {
netif_stop_queue(dev);
set_bit(dev->if_port, &sge->stopped_tx_queues);
sge->stats.cmdQ_full[2]++;
- spin_unlock(&q->lock);
- if (!netif_queue_stopped(dev))
- CH_ERR("%s: Tx ring full while queue awake!\n",
- adapter->name);
- return NETDEV_TX_BUSY;
+ CH_ERR("%s: Tx ring full while queue awake!\n",
+ adapter->name);
}
- if (unlikely(credits - count < q->stop_thres)) {
- sge->stats.cmdQ_full[2]++;
- netif_stop_queue(dev);
- set_bit(dev->if_port, &sge->stopped_tx_queues);
+ spin_unlock(&q->lock);
+ return NETDEV_TX_BUSY;
+ }
+
+ if (unlikely(credits - count < q->stop_thres)) {
+ netif_stop_queue(dev);
+ set_bit(dev->if_port, &sge->stopped_tx_queues);
+ sge->stats.cmdQ_full[2]++;
+ }
+
+ /* T204 cmdQ0 skbs that are destined for a certain port have to go
+ * through the scheduler.
+ */
+ if (sge->tx_sched && !qid && skb->dev) {
+ use_sched:
+ use_sched_skb = 1;
+ /* Note that the scheduler might return a different skb than
+ * the one passed in.
+ */
+ skb = sched_skb(sge, skb, credits);
+ if (!skb) {
+ spin_unlock(&q->lock);
+ return NETDEV_TX_OK;
}
+ pidx = q->pidx;
+ count = 1 + skb_shinfo(skb)->nr_frags;
+ count += compute_large_page_tx_descs(skb);
}
+
q->in_use += count;
genbit = q->genbit;
+ pidx = q->pidx;
q->pidx += count;
if (q->pidx >= q->size) {
q->pidx -= q->size;
@@ -1388,6 +1854,14 @@ static int t1_sge_tx(struct sk_buff *skb, struct adapter *adapter,
writel(F_CMDQ0_ENABLE, adapter->regs + A_SG_DOORBELL);
}
}
+
+ if (use_sched_skb) {
+ if (spin_trylock(&q->lock)) {
+ credits = q->size - q->in_use;
+ skb = NULL;
+ goto use_sched;
+ }
+ }
return NETDEV_TX_OK;
}
@@ -1412,16 +1886,20 @@ static inline int eth_hdr_len(const void *data)
int t1_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct adapter *adapter = dev->priv;
- struct sge_port_stats *st = &adapter->sge->port_stats[dev->if_port];
struct sge *sge = adapter->sge;
+ struct sge_port_stats *st = per_cpu_ptr(sge->port_stats[dev->if_port], smp_processor_id());
struct cpl_tx_pkt *cpl;
+ struct sk_buff *orig_skb = skb;
+ int ret;
+
+ if (skb->protocol == htons(ETH_P_CPL5))
+ goto send;
-#ifdef NETIF_F_TSO
- if (skb_is_gso(skb)) {
+ if (skb_shinfo(skb)->gso_size) {
int eth_type;
struct cpl_tx_pkt_lso *hdr;
- st->tso++;
+ ++st->tx_tso;
eth_type = skb->nh.raw - skb->data == ETH_HLEN ?
CPL_ETH_II : CPL_ETH_II_VLAN;
@@ -1432,13 +1910,10 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev)
hdr->ip_hdr_words = skb->nh.iph->ihl;
hdr->tcp_hdr_words = skb->h.th->doff;
hdr->eth_type_mss = htons(MK_ETH_TYPE_MSS(eth_type,
- skb_shinfo(skb)->gso_size));
+ skb_shinfo(skb)->gso_size));
hdr->len = htonl(skb->len - sizeof(*hdr));
cpl = (struct cpl_tx_pkt *)hdr;
- sge->stats.tx_lso_pkts++;
- } else
-#endif
- {
+ } else {
/*
* Packets shorter than ETH_HLEN can break the MAC, drop them
* early. Also, we may get oversized packets because some
@@ -1447,6 +1922,8 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev)
*/
if (unlikely(skb->len < ETH_HLEN ||
skb->len > dev->mtu + eth_hdr_len(skb->data))) {
+ pr_debug("%s: packet size %d hdr %d mtu%d\n", dev->name,
+ skb->len, eth_hdr_len(skb->data), dev->mtu);
dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
}
@@ -1456,9 +1933,9 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev)
* components, such as pktgen, do not handle it right.
* Complain when this happens but try to fix things up.
*/
- if (unlikely(skb_headroom(skb) <
- dev->hard_header_len - ETH_HLEN)) {
- struct sk_buff *orig_skb = skb;
+ if (unlikely(skb_headroom(skb) < dev->hard_header_len - ETH_HLEN)) {
+ pr_debug("%s: headroom %d header_len %d\n", dev->name,
+ skb_headroom(skb), dev->hard_header_len);
if (net_ratelimit())
printk(KERN_ERR "%s: inadequate headroom in "
@@ -1471,19 +1948,21 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (!(adapter->flags & UDP_CSUM_CAPABLE) &&
skb->ip_summed == CHECKSUM_PARTIAL &&
- skb->nh.iph->protocol == IPPROTO_UDP)
+ skb->nh.iph->protocol == IPPROTO_UDP) {
if (unlikely(skb_checksum_help(skb))) {
+ pr_debug("%s: unable to do udp checksum\n", dev->name);
dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
}
+ }
/* Hmmm, assuming to catch the gratious arp... and we'll use
* it to flush out stuck espi packets...
- */
- if (unlikely(!adapter->sge->espibug_skb)) {
+ */
+ if ((unlikely(!adapter->sge->espibug_skb[dev->if_port]))) {
if (skb->protocol == htons(ETH_P_ARP) &&
skb->nh.arph->ar_op == htons(ARPOP_REQUEST)) {
- adapter->sge->espibug_skb = skb;
+ adapter->sge->espibug_skb[dev->if_port] = skb;
/* We want to re-use this skb later. We
* simply bump the reference count and it
* will not be freed...
@@ -1499,8 +1978,6 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* the length field isn't used so don't bother setting it */
st->tx_cso += (skb->ip_summed == CHECKSUM_PARTIAL);
- sge->stats.tx_do_cksum += (skb->ip_summed == CHECKSUM_PARTIAL);
- sge->stats.tx_reg_pkts++;
}
cpl->iff = dev->if_port;
@@ -1513,8 +1990,19 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev)
#endif
cpl->vlan_valid = 0;
+send:
+ st->tx_packets++;
dev->trans_start = jiffies;
- return t1_sge_tx(skb, adapter, 0, dev);
+ ret = t1_sge_tx(skb, adapter, 0, dev);
+
+ /* If transmit busy, and we reallocated skb's due to headroom limit,
+ * then silently discard to avoid leak.
+ */
+ if (unlikely(ret != NETDEV_TX_OK && skb != orig_skb)) {
+ dev_kfree_skb_any(skb);
+ ret = NETDEV_TX_OK;
+ }
+ return ret;
}
/*
@@ -1532,10 +2020,9 @@ static void sge_tx_reclaim_cb(unsigned long data)
continue;
reclaim_completed_tx(sge, q);
- if (i == 0 && q->in_use) /* flush pending credits */
- writel(F_CMDQ0_ENABLE,
- sge->adapter->regs + A_SG_DOORBELL);
-
+ if (i == 0 && q->in_use) { /* flush pending credits */
+ writel(F_CMDQ0_ENABLE, sge->adapter->regs + A_SG_DOORBELL);
+ }
spin_unlock(&q->lock);
}
mod_timer(&sge->tx_reclaim_timer, jiffies + TX_RECLAIM_PERIOD);
@@ -1582,11 +2069,20 @@ int t1_sge_configure(struct sge *sge, struct sge_params *p)
*/
void t1_sge_stop(struct sge *sge)
{
+ int i;
writel(0, sge->adapter->regs + A_SG_CONTROL);
- (void) readl(sge->adapter->regs + A_SG_CONTROL); /* flush */
+ readl(sge->adapter->regs + A_SG_CONTROL); /* flush */
+
if (is_T2(sge->adapter))
del_timer_sync(&sge->espibug_timer);
+
del_timer_sync(&sge->tx_reclaim_timer);
+ if (sge->tx_sched)
+ tx_sched_stop(sge);
+
+ for (i = 0; i < MAX_NPORTS; i++)
+ if (sge->espibug_skb[i])
+ kfree_skb(sge->espibug_skb[i]);
}
/*
@@ -1599,74 +2095,128 @@ void t1_sge_start(struct sge *sge)
writel(sge->sge_control, sge->adapter->regs + A_SG_CONTROL);
doorbell_pio(sge->adapter, F_FL0_ENABLE | F_FL1_ENABLE);
- (void) readl(sge->adapter->regs + A_SG_CONTROL); /* flush */
+ readl(sge->adapter->regs + A_SG_CONTROL); /* flush */
mod_timer(&sge->tx_reclaim_timer, jiffies + TX_RECLAIM_PERIOD);
- if (is_T2(sge->adapter))
+ if (is_T2(sge->adapter))
mod_timer(&sge->espibug_timer, jiffies + sge->espibug_timeout);
}
/*
* Callback for the T2 ESPI 'stuck packet feature' workaorund
*/
-static void espibug_workaround(void *data)
+static void espibug_workaround_t204(unsigned long data)
{
struct adapter *adapter = (struct adapter *)data;
struct sge *sge = adapter->sge;
+ unsigned int nports = adapter->params.nports;
+ u32 seop[MAX_NPORTS];
- if (netif_running(adapter->port[0].dev)) {
- struct sk_buff *skb = sge->espibug_skb;
-
- u32 seop = t1_espi_get_mon(adapter, 0x930, 0);
-
- if ((seop & 0xfff0fff) == 0xfff && skb) {
- if (!skb->cb[0]) {
- u8 ch_mac_addr[ETH_ALEN] =
- {0x0, 0x7, 0x43, 0x0, 0x0, 0x0};
- memcpy(skb->data + sizeof(struct cpl_tx_pkt),
- ch_mac_addr, ETH_ALEN);
- memcpy(skb->data + skb->len - 10, ch_mac_addr,
- ETH_ALEN);
- skb->cb[0] = 0xff;
+ if (adapter->open_device_map & PORT_MASK) {
+ int i;
+ if (t1_espi_get_mon_t204(adapter, &(seop[0]), 0) < 0) {
+ return;
+ }
+ for (i = 0; i < nports; i++) {
+ struct sk_buff *skb = sge->espibug_skb[i];
+ if ( (netif_running(adapter->port[i].dev)) &&
+ !(netif_queue_stopped(adapter->port[i].dev)) &&
+ (seop[i] && ((seop[i] & 0xfff) == 0)) &&
+ skb ) {
+ if (!skb->cb[0]) {
+ u8 ch_mac_addr[ETH_ALEN] =
+ {0x0, 0x7, 0x43, 0x0, 0x0, 0x0};
+ memcpy(skb->data + sizeof(struct cpl_tx_pkt),
+ ch_mac_addr, ETH_ALEN);
+ memcpy(skb->data + skb->len - 10,
+ ch_mac_addr, ETH_ALEN);
+ skb->cb[0] = 0xff;
+ }
+
+ /* bump the reference count to avoid freeing of
+ * the skb once the DMA has completed.
+ */
+ skb = skb_get(skb);
+ t1_sge_tx(skb, adapter, 0, adapter->port[i].dev);
}
-
- /* bump the reference count to avoid freeing of the
- * skb once the DMA has completed.
- */
- skb = skb_get(skb);
- t1_sge_tx(skb, adapter, 0, adapter->port[0].dev);
}
}
mod_timer(&sge->espibug_timer, jiffies + sge->espibug_timeout);
}
+static void espibug_workaround(unsigned long data)
+{
+ struct adapter *adapter = (struct adapter *)data;
+ struct sge *sge = adapter->sge;
+
+ if (netif_running(adapter->port[0].dev)) {
+ struct sk_buff *skb = sge->espibug_skb[0];
+ u32 seop = t1_espi_get_mon(adapter, 0x930, 0);
+
+ if ((seop & 0xfff0fff) == 0xfff && skb) {
+ if (!skb->cb[0]) {
+ u8 ch_mac_addr[ETH_ALEN] =
+ {0x0, 0x7, 0x43, 0x0, 0x0, 0x0};
+ memcpy(skb->data + sizeof(struct cpl_tx_pkt),
+ ch_mac_addr, ETH_ALEN);
+ memcpy(skb->data + skb->len - 10, ch_mac_addr,
+ ETH_ALEN);
+ skb->cb[0] = 0xff;
+ }
+
+ /* bump the reference count to avoid freeing of the
+ * skb once the DMA has completed.
+ */
+ skb = skb_get(skb);
+ t1_sge_tx(skb, adapter, 0, adapter->port[0].dev);
+ }
+ }
+ mod_timer(&sge->espibug_timer, jiffies + sge->espibug_timeout);
+}
+
/*
* Creates a t1_sge structure and returns suggested resource parameters.
*/
struct sge * __devinit t1_sge_create(struct adapter *adapter,
struct sge_params *p)
{
- struct sge *sge = kmalloc(sizeof(*sge), GFP_KERNEL);
+ struct sge *sge = kzalloc(sizeof(*sge), GFP_KERNEL);
+ int i;
if (!sge)
return NULL;
- memset(sge, 0, sizeof(*sge));
sge->adapter = adapter;
sge->netdev = adapter->port[0].dev;
sge->rx_pkt_pad = t1_is_T1B(adapter) ? 0 : 2;
sge->jumbo_fl = t1_is_T1B(adapter) ? 1 : 0;
+ for_each_port(adapter, i) {
+ sge->port_stats[i] = alloc_percpu(struct sge_port_stats);
+ if (!sge->port_stats[i])
+ goto nomem_port;
+ }
+
init_timer(&sge->tx_reclaim_timer);
sge->tx_reclaim_timer.data = (unsigned long)sge;
sge->tx_reclaim_timer.function = sge_tx_reclaim_cb;
if (is_T2(sge->adapter)) {
init_timer(&sge->espibug_timer);
- sge->espibug_timer.function = (void *)&espibug_workaround;
+
+ if (adapter->params.nports > 1) {
+ tx_sched_init(sge);
+ sge->espibug_timer.function = espibug_workaround_t204;
+ } else {
+ sge->espibug_timer.function = espibug_workaround;
+ }
sge->espibug_timer.data = (unsigned long)sge->adapter;
+
sge->espibug_timeout = 1;
+ /* for T204, every 10ms */
+ if (adapter->params.nports > 1)
+ sge->espibug_timeout = HZ/100;
}
@@ -1674,10 +2224,25 @@ struct sge * __devinit t1_sge_create(struct adapter *adapter,
p->cmdQ_size[1] = SGE_CMDQ1_E_N;
p->freelQ_size[!sge->jumbo_fl] = SGE_FREEL_SIZE;
p->freelQ_size[sge->jumbo_fl] = SGE_JUMBO_FREEL_SIZE;
- p->rx_coalesce_usecs = 50;
+ if (sge->tx_sched) {
+ if (board_info(sge->adapter)->board == CHBT_BOARD_CHT204)
+ p->rx_coalesce_usecs = 15;
+ else
+ p->rx_coalesce_usecs = 50;
+ } else
+ p->rx_coalesce_usecs = 50;
+
p->coalesce_enable = 0;
p->sample_interval_usecs = 0;
p->polling = 0;
return sge;
+nomem_port:
+ while (i >= 0) {
+ free_percpu(sge->port_stats[i]);
+ --i;
+ }
+ kfree(sge);
+ return NULL;
+
}
diff --git a/drivers/net/chelsio/sge.h b/drivers/net/chelsio/sge.h
index 91af47bab7be..7ceb0117d039 100644
--- a/drivers/net/chelsio/sge.h
+++ b/drivers/net/chelsio/sge.h
@@ -44,6 +44,9 @@
#include <asm/byteorder.h>
struct sge_intr_counts {
+ unsigned int rx_drops; /* # of packets dropped due to no mem */
+ unsigned int pure_rsps; /* # of non-payload responses */
+ unsigned int unhandled_irqs; /* # of unhandled interrupts */
unsigned int respQ_empty; /* # times respQ empty */
unsigned int respQ_overflow; /* # respQ overflow (fatal) */
unsigned int freelistQ_empty; /* # times freelist empty */
@@ -51,24 +54,16 @@ struct sge_intr_counts {
unsigned int pkt_mismatch;
unsigned int cmdQ_full[3]; /* not HW IRQ, host cmdQ[] full */
unsigned int cmdQ_restarted[3];/* # of times cmdQ X was restarted */
- unsigned int ethernet_pkts; /* # of Ethernet packets received */
- unsigned int offload_pkts; /* # of offload packets received */
- unsigned int offload_bundles; /* # of offload pkt bundles delivered */
- unsigned int pure_rsps; /* # of non-payload responses */
- unsigned int unhandled_irqs; /* # of unhandled interrupts */
- unsigned int tx_ipfrags;
- unsigned int tx_reg_pkts;
- unsigned int tx_lso_pkts;
- unsigned int tx_do_cksum;
};
struct sge_port_stats {
- unsigned long rx_cso_good; /* # of successful RX csum offloads */
- unsigned long tx_cso; /* # of TX checksum offloads */
- unsigned long vlan_xtract; /* # of VLAN tag extractions */
- unsigned long vlan_insert; /* # of VLAN tag extractions */
- unsigned long tso; /* # of TSO requests */
- unsigned long rx_drops; /* # of packets dropped due to no mem */
+ u64 rx_packets; /* # of Ethernet packets received */
+ u64 rx_cso_good; /* # of successful RX csum offloads */
+ u64 tx_packets; /* # of TX packets */
+ u64 tx_cso; /* # of TX checksum offloads */
+ u64 tx_tso; /* # of TSO requests */
+ u64 vlan_xtract; /* # of VLAN tag extractions */
+ u64 vlan_insert; /* # of VLAN tag insertions */
};
struct sk_buff;
@@ -90,7 +85,11 @@ int t1_sge_intr_error_handler(struct sge *);
void t1_sge_intr_enable(struct sge *);
void t1_sge_intr_disable(struct sge *);
void t1_sge_intr_clear(struct sge *);
-const struct sge_intr_counts *t1_sge_get_intr_counts(struct sge *sge);
-const struct sge_port_stats *t1_sge_get_port_stats(struct sge *sge, int port);
+const struct sge_intr_counts *t1_sge_get_intr_counts(const struct sge *sge);
+void t1_sge_get_port_stats(const struct sge *sge, int port, struct sge_port_stats *);
+void t1_sched_set_max_avail_bytes(struct sge *, unsigned int);
+void t1_sched_set_drain_bits_per_us(struct sge *, unsigned int, unsigned int);
+unsigned int t1_sched_update_parms(struct sge *, unsigned int, unsigned int,
+ unsigned int);
#endif /* _CXGB_SGE_H_ */
diff --git a/drivers/net/chelsio/subr.c b/drivers/net/chelsio/subr.c
index 12e4e96dba2d..22ed9a383c08 100644
--- a/drivers/net/chelsio/subr.c
+++ b/drivers/net/chelsio/subr.c
@@ -43,6 +43,7 @@
#include "gmac.h"
#include "cphy.h"
#include "sge.h"
+#include "tp.h"
#include "espi.h"
/**
@@ -59,7 +60,7 @@
* otherwise.
*/
static int t1_wait_op_done(adapter_t *adapter, int reg, u32 mask, int polarity,
- int attempts, int delay)
+ int attempts, int delay)
{
while (1) {
u32 val = readl(adapter->regs + reg) & mask;
@@ -78,7 +79,7 @@ static int t1_wait_op_done(adapter_t *adapter, int reg, u32 mask, int polarity,
/*
* Write a register over the TPI interface (unlocked and locked versions).
*/
-static int __t1_tpi_write(adapter_t *adapter, u32 addr, u32 value)
+int __t1_tpi_write(adapter_t *adapter, u32 addr, u32 value)
{
int tpi_busy;
@@ -98,16 +99,16 @@ int t1_tpi_write(adapter_t *adapter, u32 addr, u32 value)
{
int ret;
- spin_lock(&(adapter)->tpi_lock);
+ spin_lock(&adapter->tpi_lock);
ret = __t1_tpi_write(adapter, addr, value);
- spin_unlock(&(adapter)->tpi_lock);
+ spin_unlock(&adapter->tpi_lock);
return ret;
}
/*
* Read a register over the TPI interface (unlocked and locked versions).
*/
-static int __t1_tpi_read(adapter_t *adapter, u32 addr, u32 *valp)
+int __t1_tpi_read(adapter_t *adapter, u32 addr, u32 *valp)
{
int tpi_busy;
@@ -128,18 +129,26 @@ int t1_tpi_read(adapter_t *adapter, u32 addr, u32 *valp)
{
int ret;
- spin_lock(&(adapter)->tpi_lock);
+ spin_lock(&adapter->tpi_lock);
ret = __t1_tpi_read(adapter, addr, valp);
- spin_unlock(&(adapter)->tpi_lock);
+ spin_unlock(&adapter->tpi_lock);
return ret;
}
/*
+ * Set a TPI parameter.
+ */
+static void t1_tpi_par(adapter_t *adapter, u32 value)
+{
+ writel(V_TPIPAR(value), adapter->regs + A_TPI_PAR);
+}
+
+/*
* Called when a port's link settings change to propagate the new values to the
* associated PHY and MAC. After performing the common tasks it invokes an
* OS-specific handler.
*/
-/* static */ void link_changed(adapter_t *adapter, int port_id)
+void t1_link_changed(adapter_t *adapter, int port_id)
{
int link_ok, speed, duplex, fc;
struct cphy *phy = adapter->port[port_id].phy;
@@ -159,23 +168,83 @@ int t1_tpi_read(adapter_t *adapter, u32 addr, u32 *valp)
mac->ops->set_speed_duplex_fc(mac, speed, duplex, fc);
lc->fc = (unsigned char)fc;
}
- t1_link_changed(adapter, port_id, link_ok, speed, duplex, fc);
+ t1_link_negotiated(adapter, port_id, link_ok, speed, duplex, fc);
}
static int t1_pci_intr_handler(adapter_t *adapter)
{
u32 pcix_cause;
- pci_read_config_dword(adapter->pdev, A_PCICFG_INTR_CAUSE, &pcix_cause);
+ pci_read_config_dword(adapter->pdev, A_PCICFG_INTR_CAUSE, &pcix_cause);
if (pcix_cause) {
pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_CAUSE,
- pcix_cause);
+ pcix_cause);
t1_fatal_err(adapter); /* PCI errors are fatal */
}
return 0;
}
+#ifdef CONFIG_CHELSIO_T1_COUGAR
+#include "cspi.h"
+#endif
+#ifdef CONFIG_CHELSIO_T1_1G
+#include "fpga_defs.h"
+
+/*
+ * PHY interrupt handler for FPGA boards.
+ */
+static int fpga_phy_intr_handler(adapter_t *adapter)
+{
+ int p;
+ u32 cause = readl(adapter->regs + FPGA_GMAC_ADDR_INTERRUPT_CAUSE);
+
+ for_each_port(adapter, p)
+ if (cause & (1 << p)) {
+ struct cphy *phy = adapter->port[p].phy;
+ int phy_cause = phy->ops->interrupt_handler(phy);
+
+ if (phy_cause & cphy_cause_link_change)
+ t1_link_changed(adapter, p);
+ }
+ writel(cause, adapter->regs + FPGA_GMAC_ADDR_INTERRUPT_CAUSE);
+ return 0;
+}
+
+/*
+ * Slow path interrupt handler for FPGAs.
+ */
+static int fpga_slow_intr(adapter_t *adapter)
+{
+ u32 cause = readl(adapter->regs + A_PL_CAUSE);
+
+ cause &= ~F_PL_INTR_SGE_DATA;
+ if (cause & F_PL_INTR_SGE_ERR)
+ t1_sge_intr_error_handler(adapter->sge);
+
+ if (cause & FPGA_PCIX_INTERRUPT_GMAC)
+ fpga_phy_intr_handler(adapter);
+
+ if (cause & FPGA_PCIX_INTERRUPT_TP) {
+ /*
+ * FPGA doesn't support MC4 interrupts and it requires
+ * this odd layer of indirection for MC5.
+ */
+ u32 tp_cause = readl(adapter->regs + FPGA_TP_ADDR_INTERRUPT_CAUSE);
+
+ /* Clear TP interrupt */
+ writel(tp_cause, adapter->regs + FPGA_TP_ADDR_INTERRUPT_CAUSE);
+ }
+ if (cause & FPGA_PCIX_INTERRUPT_PCIX)
+ t1_pci_intr_handler(adapter);
+
+ /* Clear the interrupts just processed. */
+ if (cause)
+ writel(cause, adapter->regs + A_PL_CAUSE);
+
+ return cause != 0;
+}
+#endif
/*
* Wait until Elmer's MI1 interface is ready for new operations.
@@ -212,12 +281,62 @@ static void mi1_mdio_init(adapter_t *adapter, const struct board_info *bi)
t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_CFG, val);
}
+#if defined(CONFIG_CHELSIO_T1_1G) || defined(CONFIG_CHELSIO_T1_COUGAR)
+/*
+ * Elmer MI1 MDIO read/write operations.
+ */
+static int mi1_mdio_read(adapter_t *adapter, int phy_addr, int mmd_addr,
+ int reg_addr, unsigned int *valp)
+{
+ u32 addr = V_MI1_REG_ADDR(reg_addr) | V_MI1_PHY_ADDR(phy_addr);
+
+ if (mmd_addr)
+ return -EINVAL;
+
+ spin_lock(&adapter->tpi_lock);
+ __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr);
+ __t1_tpi_write(adapter,
+ A_ELMER0_PORT0_MI1_OP, MI1_OP_DIRECT_READ);
+ mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
+ __t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, valp);
+ spin_unlock(&adapter->tpi_lock);
+ return 0;
+}
+
+static int mi1_mdio_write(adapter_t *adapter, int phy_addr, int mmd_addr,
+ int reg_addr, unsigned int val)
+{
+ u32 addr = V_MI1_REG_ADDR(reg_addr) | V_MI1_PHY_ADDR(phy_addr);
+
+ if (mmd_addr)
+ return -EINVAL;
+
+ spin_lock(&adapter->tpi_lock);
+ __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr);
+ __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, val);
+ __t1_tpi_write(adapter,
+ A_ELMER0_PORT0_MI1_OP, MI1_OP_DIRECT_WRITE);
+ mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
+ spin_unlock(&adapter->tpi_lock);
+ return 0;
+}
+
+#if defined(CONFIG_CHELSIO_T1_1G) || defined(CONFIG_CHELSIO_T1_COUGAR)
+static struct mdio_ops mi1_mdio_ops = {
+ mi1_mdio_init,
+ mi1_mdio_read,
+ mi1_mdio_write
+};
+#endif
+
+#endif
+
static int mi1_mdio_ext_read(adapter_t *adapter, int phy_addr, int mmd_addr,
int reg_addr, unsigned int *valp)
{
u32 addr = V_MI1_REG_ADDR(mmd_addr) | V_MI1_PHY_ADDR(phy_addr);
- spin_lock(&(adapter)->tpi_lock);
+ spin_lock(&adapter->tpi_lock);
/* Write the address we want. */
__t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr);
@@ -227,12 +346,13 @@ static int mi1_mdio_ext_read(adapter_t *adapter, int phy_addr, int mmd_addr,
mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
/* Write the operation we want. */
- __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP, MI1_OP_INDIRECT_READ);
+ __t1_tpi_write(adapter,
+ A_ELMER0_PORT0_MI1_OP, MI1_OP_INDIRECT_READ);
mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
/* Read the data. */
__t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, valp);
- spin_unlock(&(adapter)->tpi_lock);
+ spin_unlock(&adapter->tpi_lock);
return 0;
}
@@ -241,7 +361,7 @@ static int mi1_mdio_ext_write(adapter_t *adapter, int phy_addr, int mmd_addr,
{
u32 addr = V_MI1_REG_ADDR(mmd_addr) | V_MI1_PHY_ADDR(phy_addr);
- spin_lock(&(adapter)->tpi_lock);
+ spin_lock(&adapter->tpi_lock);
/* Write the address we want. */
__t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr);
@@ -254,7 +374,7 @@ static int mi1_mdio_ext_write(adapter_t *adapter, int phy_addr, int mmd_addr,
__t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, val);
__t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP, MI1_OP_INDIRECT_WRITE);
mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
- spin_unlock(&(adapter)->tpi_lock);
+ spin_unlock(&adapter->tpi_lock);
return 0;
}
@@ -265,12 +385,25 @@ static struct mdio_ops mi1_mdio_ext_ops = {
};
enum {
+ CH_BRD_T110_1CU,
CH_BRD_N110_1F,
CH_BRD_N210_1F,
+ CH_BRD_T210_1F,
+ CH_BRD_T210_1CU,
+ CH_BRD_N204_4CU,
};
static struct board_info t1_board[] = {
+{ CHBT_BOARD_CHT110, 1/*ports#*/,
+ SUPPORTED_10000baseT_Full /*caps*/, CHBT_TERM_T1,
+ CHBT_MAC_PM3393, CHBT_PHY_MY3126,
+ 125000000/*clk-core*/, 150000000/*clk-mc3*/, 125000000/*clk-mc4*/,
+ 1/*espi-ports*/, 0/*clk-cspi*/, 44/*clk-elmer0*/, 1/*mdien*/,
+ 1/*mdiinv*/, 1/*mdc*/, 1/*phybaseaddr*/, &t1_pm3393_ops,
+ &t1_my3126_ops, &mi1_mdio_ext_ops,
+ "Chelsio T110 1x10GBase-CX4 TOE" },
+
{ CHBT_BOARD_N110, 1/*ports#*/,
SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE /*caps*/, CHBT_TERM_T1,
CHBT_MAC_PM3393, CHBT_PHY_88X2010,
@@ -289,12 +422,47 @@ static struct board_info t1_board[] = {
&t1_mv88x201x_ops, &mi1_mdio_ext_ops,
"Chelsio N210 1x10GBaseX NIC" },
+{ CHBT_BOARD_CHT210, 1/*ports#*/,
+ SUPPORTED_10000baseT_Full /*caps*/, CHBT_TERM_T2,
+ CHBT_MAC_PM3393, CHBT_PHY_88X2010,
+ 125000000/*clk-core*/, 133000000/*clk-mc3*/, 125000000/*clk-mc4*/,
+ 1/*espi-ports*/, 0/*clk-cspi*/, 44/*clk-elmer0*/, 0/*mdien*/,
+ 0/*mdiinv*/, 1/*mdc*/, 0/*phybaseaddr*/, &t1_pm3393_ops,
+ &t1_mv88x201x_ops, &mi1_mdio_ext_ops,
+ "Chelsio T210 1x10GBaseX TOE" },
+
+{ CHBT_BOARD_CHT210, 1/*ports#*/,
+ SUPPORTED_10000baseT_Full /*caps*/, CHBT_TERM_T2,
+ CHBT_MAC_PM3393, CHBT_PHY_MY3126,
+ 125000000/*clk-core*/, 133000000/*clk-mc3*/, 125000000/*clk-mc4*/,
+ 1/*espi-ports*/, 0/*clk-cspi*/, 44/*clk-elmer0*/, 1/*mdien*/,
+ 1/*mdiinv*/, 1/*mdc*/, 1/*phybaseaddr*/, &t1_pm3393_ops,
+ &t1_my3126_ops, &mi1_mdio_ext_ops,
+ "Chelsio T210 1x10GBase-CX4 TOE" },
+
+#ifdef CONFIG_CHELSIO_T1_1G
+{ CHBT_BOARD_CHN204, 4/*ports#*/,
+ SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg |
+ SUPPORTED_PAUSE | SUPPORTED_TP /*caps*/, CHBT_TERM_T2, CHBT_MAC_VSC7321, CHBT_PHY_88E1111,
+ 100000000/*clk-core*/, 0/*clk-mc3*/, 0/*clk-mc4*/,
+ 4/*espi-ports*/, 0/*clk-cspi*/, 44/*clk-elmer0*/, 0/*mdien*/,
+ 0/*mdiinv*/, 1/*mdc*/, 4/*phybaseaddr*/, &t1_vsc7326_ops,
+ &t1_mv88e1xxx_ops, &mi1_mdio_ops,
+ "Chelsio N204 4x100/1000BaseT NIC" },
+#endif
+
};
struct pci_device_id t1_pci_tbl[] = {
+ CH_DEVICE(8, 0, CH_BRD_T110_1CU),
+ CH_DEVICE(8, 1, CH_BRD_T110_1CU),
CH_DEVICE(7, 0, CH_BRD_N110_1F),
CH_DEVICE(10, 1, CH_BRD_N210_1F),
- { 0, }
+ CH_DEVICE(11, 1, CH_BRD_T210_1F),
+ CH_DEVICE(14, 1, CH_BRD_T210_1CU),
+ CH_DEVICE(16, 1, CH_BRD_N204_4CU),
+ { 0 }
};
MODULE_DEVICE_TABLE(pci, t1_pci_tbl);
@@ -390,9 +558,14 @@ int t1_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc)
if (lc->supported & SUPPORTED_Autoneg) {
lc->advertising &= ~(ADVERTISED_ASYM_PAUSE | ADVERTISED_PAUSE);
if (fc) {
- lc->advertising |= ADVERTISED_ASYM_PAUSE;
- if (fc == (PAUSE_RX | PAUSE_TX))
+ if (fc == ((PAUSE_RX | PAUSE_TX) &
+ (mac->adapter->params.nports < 2)))
lc->advertising |= ADVERTISED_PAUSE;
+ else {
+ lc->advertising |= ADVERTISED_ASYM_PAUSE;
+ if (fc == PAUSE_RX)
+ lc->advertising |= ADVERTISED_PAUSE;
+ }
}
phy->ops->advertise(phy, lc->advertising);
@@ -403,11 +576,15 @@ int t1_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc)
mac->ops->set_speed_duplex_fc(mac, lc->speed,
lc->duplex, fc);
/* Also disables autoneg */
+ phy->state = PHY_AUTONEG_RDY;
phy->ops->set_speed_duplex(phy, lc->speed, lc->duplex);
phy->ops->reset(phy, 0);
- } else
+ } else {
+ phy->state = PHY_AUTONEG_EN;
phy->ops->autoneg_enable(phy); /* also resets PHY */
+ }
} else {
+ phy->state = PHY_AUTONEG_RDY;
mac->ops->set_speed_duplex_fc(mac, -1, -1, fc);
lc->fc = (unsigned char)fc;
phy->ops->reset(phy, 0);
@@ -418,24 +595,109 @@ int t1_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc)
/*
* External interrupt handler for boards using elmer0.
*/
-int elmer0_ext_intr_handler(adapter_t *adapter)
+int t1_elmer0_ext_intr_handler(adapter_t *adapter)
{
- struct cphy *phy;
+ struct cphy *phy;
int phy_cause;
- u32 cause;
+ u32 cause;
t1_tpi_read(adapter, A_ELMER0_INT_CAUSE, &cause);
switch (board_info(adapter)->board) {
+#ifdef CONFIG_CHELSIO_T1_1G
+ case CHBT_BOARD_CHT204:
+ case CHBT_BOARD_CHT204E:
+ case CHBT_BOARD_CHN204:
+ case CHBT_BOARD_CHT204V: {
+ int i, port_bit;
+ for_each_port(adapter, i) {
+ port_bit = i + 1;
+ if (!(cause & (1 << port_bit))) continue;
+
+ phy = adapter->port[i].phy;
+ phy_cause = phy->ops->interrupt_handler(phy);
+ if (phy_cause & cphy_cause_link_change)
+ t1_link_changed(adapter, i);
+ }
+ break;
+ }
+ case CHBT_BOARD_CHT101:
+ if (cause & ELMER0_GP_BIT1) { /* Marvell 88E1111 interrupt */
+ phy = adapter->port[0].phy;
+ phy_cause = phy->ops->interrupt_handler(phy);
+ if (phy_cause & cphy_cause_link_change)
+ t1_link_changed(adapter, 0);
+ }
+ break;
+ case CHBT_BOARD_7500: {
+ int p;
+ /*
+ * Elmer0's interrupt cause isn't useful here because there is
+ * only one bit that can be set for all 4 ports. This means
+ * we are forced to check every PHY's interrupt status
+ * register to see who initiated the interrupt.
+ */
+ for_each_port(adapter, p) {
+ phy = adapter->port[p].phy;
+ phy_cause = phy->ops->interrupt_handler(phy);
+ if (phy_cause & cphy_cause_link_change)
+ t1_link_changed(adapter, p);
+ }
+ break;
+ }
+#endif
+ case CHBT_BOARD_CHT210:
case CHBT_BOARD_N210:
case CHBT_BOARD_N110:
if (cause & ELMER0_GP_BIT6) { /* Marvell 88x2010 interrupt */
phy = adapter->port[0].phy;
phy_cause = phy->ops->interrupt_handler(phy);
if (phy_cause & cphy_cause_link_change)
- link_changed(adapter, 0);
+ t1_link_changed(adapter, 0);
+ }
+ break;
+ case CHBT_BOARD_8000:
+ case CHBT_BOARD_CHT110:
+ CH_DBG(adapter, INTR, "External interrupt cause 0x%x\n",
+ cause);
+ if (cause & ELMER0_GP_BIT1) { /* PMC3393 INTB */
+ struct cmac *mac = adapter->port[0].mac;
+
+ mac->ops->interrupt_handler(mac);
}
+ if (cause & ELMER0_GP_BIT5) { /* XPAK MOD_DETECT */
+ u32 mod_detect;
+
+ t1_tpi_read(adapter,
+ A_ELMER0_GPI_STAT, &mod_detect);
+ CH_MSG(adapter, INFO, LINK, "XPAK %s\n",
+ mod_detect ? "removed" : "inserted");
+ }
break;
+#ifdef CONFIG_CHELSIO_T1_COUGAR
+ case CHBT_BOARD_COUGAR:
+ if (adapter->params.nports == 1) {
+ if (cause & ELMER0_GP_BIT1) { /* Vitesse MAC */
+ struct cmac *mac = adapter->port[0].mac;
+ mac->ops->interrupt_handler(mac);
+ }
+ if (cause & ELMER0_GP_BIT5) { /* XPAK MOD_DETECT */
+ }
+ } else {
+ int i, port_bit;
+
+ for_each_port(adapter, i) {
+ port_bit = i ? i + 1 : 0;
+ if (!(cause & (1 << port_bit))) continue;
+
+ phy = adapter->port[i].phy;
+ phy_cause = phy->ops->interrupt_handler(phy);
+ if (phy_cause & cphy_cause_link_change)
+ t1_link_changed(adapter, i);
+ }
+ }
+ break;
+#endif
}
t1_tpi_write(adapter, A_ELMER0_INT_CAUSE, cause);
return 0;
@@ -445,11 +707,11 @@ int elmer0_ext_intr_handler(adapter_t *adapter)
void t1_interrupts_enable(adapter_t *adapter)
{
unsigned int i;
- u32 pl_intr;
- adapter->slow_intr_mask = F_PL_INTR_SGE_ERR;
+ adapter->slow_intr_mask = F_PL_INTR_SGE_ERR | F_PL_INTR_TP;
t1_sge_intr_enable(adapter->sge);
+ t1_tp_intr_enable(adapter->tp);
if (adapter->espi) {
adapter->slow_intr_mask |= F_PL_INTR_ESPI;
t1_espi_intr_enable(adapter->espi);
@@ -462,15 +724,17 @@ void t1_interrupts_enable(adapter_t *adapter)
}
/* Enable PCIX & external chip interrupts on ASIC boards. */
- pl_intr = readl(adapter->regs + A_PL_ENABLE);
+ if (t1_is_asic(adapter)) {
+ u32 pl_intr = readl(adapter->regs + A_PL_ENABLE);
- /* PCI-X interrupts */
- pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_ENABLE,
- 0xffffffff);
+ /* PCI-X interrupts */
+ pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_ENABLE,
+ 0xffffffff);
- adapter->slow_intr_mask |= F_PL_INTR_EXT | F_PL_INTR_PCIX;
- pl_intr |= F_PL_INTR_EXT | F_PL_INTR_PCIX;
- writel(pl_intr, adapter->regs + A_PL_ENABLE);
+ adapter->slow_intr_mask |= F_PL_INTR_EXT | F_PL_INTR_PCIX;
+ pl_intr |= F_PL_INTR_EXT | F_PL_INTR_PCIX;
+ writel(pl_intr, adapter->regs + A_PL_ENABLE);
+ }
}
/* Disables all interrupts. */
@@ -479,6 +743,7 @@ void t1_interrupts_disable(adapter_t* adapter)
unsigned int i;
t1_sge_intr_disable(adapter->sge);
+ t1_tp_intr_disable(adapter->tp);
if (adapter->espi)
t1_espi_intr_disable(adapter->espi);
@@ -489,7 +754,8 @@ void t1_interrupts_disable(adapter_t* adapter)
}
/* Disable PCIX & external chip interrupts. */
- writel(0, adapter->regs + A_PL_ENABLE);
+ if (t1_is_asic(adapter))
+ writel(0, adapter->regs + A_PL_ENABLE);
/* PCI-X interrupts */
pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_ENABLE, 0);
@@ -501,10 +767,9 @@ void t1_interrupts_disable(adapter_t* adapter)
void t1_interrupts_clear(adapter_t* adapter)
{
unsigned int i;
- u32 pl_intr;
-
t1_sge_intr_clear(adapter->sge);
+ t1_tp_intr_clear(adapter->tp);
if (adapter->espi)
t1_espi_intr_clear(adapter->espi);
@@ -515,10 +780,12 @@ void t1_interrupts_clear(adapter_t* adapter)
}
/* Enable interrupts for external devices. */
- pl_intr = readl(adapter->regs + A_PL_CAUSE);
+ if (t1_is_asic(adapter)) {
+ u32 pl_intr = readl(adapter->regs + A_PL_CAUSE);
- writel(pl_intr | F_PL_INTR_EXT | F_PL_INTR_PCIX,
- adapter->regs + A_PL_CAUSE);
+ writel(pl_intr | F_PL_INTR_EXT | F_PL_INTR_PCIX,
+ adapter->regs + A_PL_CAUSE);
+ }
/* PCI-X interrupts */
pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_CAUSE, 0xffffffff);
@@ -527,7 +794,7 @@ void t1_interrupts_clear(adapter_t* adapter)
/*
* Slow path interrupt handler for ASICs.
*/
-int t1_slow_intr_handler(adapter_t *adapter)
+static int asic_slow_intr(adapter_t *adapter)
{
u32 cause = readl(adapter->regs + A_PL_CAUSE);
@@ -536,89 +803,54 @@ int t1_slow_intr_handler(adapter_t *adapter)
return 0;
if (cause & F_PL_INTR_SGE_ERR)
t1_sge_intr_error_handler(adapter->sge);
+ if (cause & F_PL_INTR_TP)
+ t1_tp_intr_handler(adapter->tp);
if (cause & F_PL_INTR_ESPI)
t1_espi_intr_handler(adapter->espi);
if (cause & F_PL_INTR_PCIX)
t1_pci_intr_handler(adapter);
if (cause & F_PL_INTR_EXT)
- t1_elmer0_ext_intr(adapter);
+ t1_elmer0_ext_intr_handler(adapter);
/* Clear the interrupts just processed. */
writel(cause, adapter->regs + A_PL_CAUSE);
- (void)readl(adapter->regs + A_PL_CAUSE); /* flush writes */
+ readl(adapter->regs + A_PL_CAUSE); /* flush writes */
return 1;
}
-/* Pause deadlock avoidance parameters */
-#define DROP_MSEC 16
-#define DROP_PKTS_CNT 1
-
-static void set_csum_offload(adapter_t *adapter, u32 csum_bit, int enable)
-{
- u32 val = readl(adapter->regs + A_TP_GLOBAL_CONFIG);
-
- if (enable)
- val |= csum_bit;
- else
- val &= ~csum_bit;
- writel(val, adapter->regs + A_TP_GLOBAL_CONFIG);
-}
-
-void t1_tp_set_ip_checksum_offload(adapter_t *adapter, int enable)
-{
- set_csum_offload(adapter, F_IP_CSUM, enable);
-}
-
-void t1_tp_set_udp_checksum_offload(adapter_t *adapter, int enable)
-{
- set_csum_offload(adapter, F_UDP_CSUM, enable);
-}
-
-void t1_tp_set_tcp_checksum_offload(adapter_t *adapter, int enable)
+int t1_slow_intr_handler(adapter_t *adapter)
{
- set_csum_offload(adapter, F_TCP_CSUM, enable);
+#ifdef CONFIG_CHELSIO_T1_1G
+ if (!t1_is_asic(adapter))
+ return fpga_slow_intr(adapter);
+#endif
+ return asic_slow_intr(adapter);
}
-static void t1_tp_reset(adapter_t *adapter, unsigned int tp_clk)
+/* Power sequencing is a work-around for Intel's XPAKs. */
+static void power_sequence_xpak(adapter_t* adapter)
{
- u32 val;
-
- val = F_TP_IN_CSPI_CPL | F_TP_IN_CSPI_CHECK_IP_CSUM |
- F_TP_IN_CSPI_CHECK_TCP_CSUM | F_TP_IN_ESPI_ETHERNET;
- val |= F_TP_IN_ESPI_CHECK_IP_CSUM |
- F_TP_IN_ESPI_CHECK_TCP_CSUM;
- writel(val, adapter->regs + A_TP_IN_CONFIG);
- writel(F_TP_OUT_CSPI_CPL |
- F_TP_OUT_ESPI_ETHERNET |
- F_TP_OUT_ESPI_GENERATE_IP_CSUM |
- F_TP_OUT_ESPI_GENERATE_TCP_CSUM,
- adapter->regs + A_TP_OUT_CONFIG);
-
- val = readl(adapter->regs + A_TP_GLOBAL_CONFIG);
- val &= ~(F_IP_CSUM | F_UDP_CSUM | F_TCP_CSUM);
- writel(val, adapter->regs + A_TP_GLOBAL_CONFIG);
-
- /*
- * Enable pause frame deadlock prevention.
- */
- if (is_T2(adapter)) {
- u32 drop_ticks = DROP_MSEC * (tp_clk / 1000);
-
- writel(F_ENABLE_TX_DROP | F_ENABLE_TX_ERROR |
- V_DROP_TICKS_CNT(drop_ticks) |
- V_NUM_PKTS_DROPPED(DROP_PKTS_CNT),
- adapter->regs + A_TP_TX_DROP_CONFIG);
+ u32 mod_detect;
+ u32 gpo;
+
+ /* Check for XPAK */
+ t1_tpi_read(adapter, A_ELMER0_GPI_STAT, &mod_detect);
+ if (!(ELMER0_GP_BIT5 & mod_detect)) {
+ /* XPAK is present */
+ t1_tpi_read(adapter, A_ELMER0_GPO, &gpo);
+ gpo |= ELMER0_GP_BIT18;
+ t1_tpi_write(adapter, A_ELMER0_GPO, gpo);
}
-
- writel(F_TP_RESET, adapter->regs + A_TP_RESET);
}
int __devinit t1_get_board_rev(adapter_t *adapter, const struct board_info *bi,
struct adapter_params *p)
{
p->chip_version = bi->chip_term;
+ p->is_asic = (p->chip_version != CHBT_TERM_FPGA);
if (p->chip_version == CHBT_TERM_T1 ||
- p->chip_version == CHBT_TERM_T2) {
+ p->chip_version == CHBT_TERM_T2 ||
+ p->chip_version == CHBT_TERM_FPGA) {
u32 val = readl(adapter->regs + A_TP_PC_CONFIG);
val = G_TP_PC_REV(val);
@@ -640,11 +872,38 @@ int __devinit t1_get_board_rev(adapter_t *adapter, const struct board_info *bi,
static int board_init(adapter_t *adapter, const struct board_info *bi)
{
switch (bi->board) {
+ case CHBT_BOARD_8000:
case CHBT_BOARD_N110:
case CHBT_BOARD_N210:
- writel(V_TPIPAR(0xf), adapter->regs + A_TPI_PAR);
+ case CHBT_BOARD_CHT210:
+ case CHBT_BOARD_COUGAR:
+ t1_tpi_par(adapter, 0xf);
t1_tpi_write(adapter, A_ELMER0_GPO, 0x800);
break;
+ case CHBT_BOARD_CHT110:
+ t1_tpi_par(adapter, 0xf);
+ t1_tpi_write(adapter, A_ELMER0_GPO, 0x1800);
+
+ /* TBD XXX Might not need. This fixes a problem
+ * described in the Intel SR XPAK errata.
+ */
+ power_sequence_xpak(adapter);
+ break;
+#ifdef CONFIG_CHELSIO_T1_1G
+ case CHBT_BOARD_CHT204E:
+ /* add config space write here */
+ case CHBT_BOARD_CHT204:
+ case CHBT_BOARD_CHT204V:
+ case CHBT_BOARD_CHN204:
+ t1_tpi_par(adapter, 0xf);
+ t1_tpi_write(adapter, A_ELMER0_GPO, 0x804);
+ break;
+ case CHBT_BOARD_CHT101:
+ case CHBT_BOARD_7500:
+ t1_tpi_par(adapter, 0xf);
+ t1_tpi_write(adapter, A_ELMER0_GPO, 0x1804);
+ break;
+#endif
}
return 0;
}
@@ -666,11 +925,16 @@ int t1_init_hw_modules(adapter_t *adapter)
adapter->regs + A_MC5_CONFIG);
}
+#ifdef CONFIG_CHELSIO_T1_COUGAR
+ if (adapter->cspi && t1_cspi_init(adapter->cspi))
+ goto out_err;
+#endif
if (adapter->espi && t1_espi_init(adapter->espi, bi->chip_mac,
bi->espi_nports))
goto out_err;
- t1_tp_reset(adapter, bi->clock_core);
+ if (t1_tp_reset(adapter->tp, &adapter->params.tp, bi->clock_core))
+ goto out_err;
err = t1_sge_configure(adapter->sge, &adapter->params.sge);
if (err)
@@ -714,8 +978,14 @@ void t1_free_sw_modules(adapter_t *adapter)
if (adapter->sge)
t1_sge_destroy(adapter->sge);
+ if (adapter->tp)
+ t1_tp_destroy(adapter->tp);
if (adapter->espi)
t1_espi_destroy(adapter->espi);
+#ifdef CONFIG_CHELSIO_T1_COUGAR
+ if (adapter->cspi)
+ t1_cspi_destroy(adapter->cspi);
+#endif
}
static void __devinit init_link_config(struct link_config *lc,
@@ -735,6 +1005,13 @@ static void __devinit init_link_config(struct link_config *lc,
}
}
+#ifdef CONFIG_CHELSIO_T1_COUGAR
+ if (bi->clock_cspi && !(adapter->cspi = t1_cspi_create(adapter))) {
+ CH_ERR("%s: CSPI initialization failed\n",
+ adapter->name);
+ goto error;
+ }
+#endif
/*
* Allocate and initialize the data structures that hold the SW state of
@@ -762,6 +1039,13 @@ int __devinit t1_init_sw_modules(adapter_t *adapter,
goto error;
}
+ adapter->tp = t1_tp_create(adapter, &adapter->params.tp);
+ if (!adapter->tp) {
+ CH_ERR("%s: TP initialization failed\n",
+ adapter->name);
+ goto error;
+ }
+
board_init(adapter, bi);
bi->mdio_ops->init(adapter, bi);
if (bi->gphy->reset)
@@ -793,7 +1077,9 @@ int __devinit t1_init_sw_modules(adapter_t *adapter,
* Get the port's MAC addresses either from the EEPROM if one
* exists or the one hardcoded in the MAC.
*/
- if (vpd_macaddress_get(adapter, i, hw_addr)) {
+ if (!t1_is_asic(adapter) || bi->chip_mac == CHBT_MAC_DUMMY)
+ mac->ops->macaddress_get(mac, hw_addr);
+ else if (vpd_macaddress_get(adapter, i, hw_addr)) {
CH_ERR("%s: could not read MAC address from VPD ROM\n",
adapter->port[i].dev->name);
goto error;
@@ -806,7 +1092,7 @@ int __devinit t1_init_sw_modules(adapter_t *adapter,
t1_interrupts_clear(adapter);
return 0;
- error:
+error:
t1_free_sw_modules(adapter);
return -1;
}
diff --git a/drivers/net/chelsio/suni1x10gexp_regs.h b/drivers/net/chelsio/suni1x10gexp_regs.h
index 81816c2b708a..269d097dd927 100644
--- a/drivers/net/chelsio/suni1x10gexp_regs.h
+++ b/drivers/net/chelsio/suni1x10gexp_regs.h
@@ -32,6 +32,30 @@
#ifndef _CXGB_SUNI1x10GEXP_REGS_H_
#define _CXGB_SUNI1x10GEXP_REGS_H_
+/*
+** Space allocated for each Exact Match Filter
+** There are 8 filter configurations
+*/
+#define SUNI1x10GEXP_REG_SIZEOF_MAC_FILTER 0x0003
+
+#define mSUNI1x10GEXP_MAC_FILTER_OFFSET(filterId) ( (filterId) * SUNI1x10GEXP_REG_SIZEOF_MAC_FILTER )
+
+/*
+** Space allocated for VLAN-Id Filter
+** There are 8 filter configurations
+*/
+#define SUNI1x10GEXP_REG_SIZEOF_MAC_VID_FILTER 0x0001
+
+#define mSUNI1x10GEXP_MAC_VID_FILTER_OFFSET(filterId) ( (filterId) * SUNI1x10GEXP_REG_SIZEOF_MAC_VID_FILTER )
+
+/*
+** Space allocated for each MSTAT Counter
+*/
+#define SUNI1x10GEXP_REG_SIZEOF_MSTAT_COUNT 0x0004
+
+#define mSUNI1x10GEXP_MSTAT_COUNT_OFFSET(countId) ( (countId) * SUNI1x10GEXP_REG_SIZEOF_MSTAT_COUNT )
+
+
/******************************************************************************/
/** S/UNI-1x10GE-XP REGISTER ADDRESS MAP **/
/******************************************************************************/
@@ -39,33 +63,125 @@
/* to the S/UNI-1x10GE-XP Data Sheet for the signification of each bit */
/******************************************************************************/
+
+#define SUNI1x10GEXP_REG_IDENTIFICATION 0x0000
+#define SUNI1x10GEXP_REG_PRODUCT_REVISION 0x0001
+#define SUNI1x10GEXP_REG_CONFIG_AND_RESET_CONTROL 0x0002
+#define SUNI1x10GEXP_REG_LOOPBACK_MISC_CTRL 0x0003
#define SUNI1x10GEXP_REG_DEVICE_STATUS 0x0004
+#define SUNI1x10GEXP_REG_GLOBAL_PERFORMANCE_MONITOR_UPDATE 0x0005
+
+#define SUNI1x10GEXP_REG_MDIO_COMMAND 0x0006
+#define SUNI1x10GEXP_REG_MDIO_INTERRUPT_ENABLE 0x0007
+#define SUNI1x10GEXP_REG_MDIO_INTERRUPT_STATUS 0x0008
+#define SUNI1x10GEXP_REG_MMD_PHY_ADDRESS 0x0009
+#define SUNI1x10GEXP_REG_MMD_CONTROL_ADDRESS_DATA 0x000A
+#define SUNI1x10GEXP_REG_MDIO_READ_STATUS_DATA 0x000B
+
+#define SUNI1x10GEXP_REG_OAM_INTF_CTRL 0x000C
#define SUNI1x10GEXP_REG_MASTER_INTERRUPT_STATUS 0x000D
#define SUNI1x10GEXP_REG_GLOBAL_INTERRUPT_ENABLE 0x000E
+#define SUNI1x10GEXP_REG_FREE 0x000F
+
+#define SUNI1x10GEXP_REG_XTEF_MISC_CTRL 0x0010
+#define SUNI1x10GEXP_REG_XRF_MISC_CTRL 0x0011
+
+#define SUNI1x10GEXP_REG_SERDES_3125_CONFIG_1 0x0100
+#define SUNI1x10GEXP_REG_SERDES_3125_CONFIG_2 0x0101
#define SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_ENABLE 0x0102
+#define SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_VISIBLE 0x0103
#define SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_STATUS 0x0104
+#define SUNI1x10GEXP_REG_SERDES_3125_TEST_CONFIG 0x0107
+
#define SUNI1x10GEXP_REG_RXXG_CONFIG_1 0x2040
+#define SUNI1x10GEXP_REG_RXXG_CONFIG_2 0x2041
#define SUNI1x10GEXP_REG_RXXG_CONFIG_3 0x2042
#define SUNI1x10GEXP_REG_RXXG_INTERRUPT 0x2043
#define SUNI1x10GEXP_REG_RXXG_MAX_FRAME_LENGTH 0x2045
#define SUNI1x10GEXP_REG_RXXG_SA_15_0 0x2046
#define SUNI1x10GEXP_REG_RXXG_SA_31_16 0x2047
#define SUNI1x10GEXP_REG_RXXG_SA_47_32 0x2048
+#define SUNI1x10GEXP_REG_RXXG_RECEIVE_FIFO_THRESHOLD 0x2049
+#define mSUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_LOW(filterId) (0x204A + mSUNI1x10GEXP_MAC_FILTER_OFFSET(filterId))
+#define mSUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_MID(filterId) (0x204B + mSUNI1x10GEXP_MAC_FILTER_OFFSET(filterId))
+#define mSUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_HIGH(filterId)(0x204C + mSUNI1x10GEXP_MAC_FILTER_OFFSET(filterId))
+#define mSUNI1x10GEXP_REG_RXXG_EXACT_MATCH_VID(filterId) (0x2062 + mSUNI1x10GEXP_MAC_VID_FILTER_OFFSET(filterId)
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_0_LOW 0x204A
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_0_MID 0x204B
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_0_HIGH 0x204C
#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_LOW 0x204D
#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_MID 0x204E
#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_HIGH 0x204F
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_2_LOW 0x2050
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_2_MID 0x2051
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_2_HIGH 0x2052
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_3_LOW 0x2053
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_3_MID 0x2054
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_3_HIGH 0x2055
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_4_LOW 0x2056
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_4_MID 0x2057
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_4_HIGH 0x2058
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_5_LOW 0x2059
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_5_MID 0x205A
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_5_HIGH 0x205B
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_6_LOW 0x205C
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_6_MID 0x205D
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_6_HIGH 0x205E
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_7_LOW 0x205F
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_7_MID 0x2060
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_7_HIGH 0x2061
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_VID_0 0x2062
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_VID_1 0x2063
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_VID_2 0x2064
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_VID_3 0x2065
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_VID_4 0x2066
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_VID_5 0x2067
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_VID_6 0x2068
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_VID_7 0x2069
#define SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_LOW 0x206A
#define SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDLOW 0x206B
#define SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDHIGH 0x206C
#define SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_HIGH 0x206D
#define SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0 0x206E
+#define SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_1 0x206F
#define SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_2 0x2070
+
+#define SUNI1x10GEXP_REG_XRF_PATTERN_GEN_CTRL 0x2081
+#define SUNI1x10GEXP_REG_XRF_8BTB_ERR_COUNT_LANE_0 0x2084
+#define SUNI1x10GEXP_REG_XRF_8BTB_ERR_COUNT_LANE_1 0x2085
+#define SUNI1x10GEXP_REG_XRF_8BTB_ERR_COUNT_LANE_2 0x2086
+#define SUNI1x10GEXP_REG_XRF_8BTB_ERR_COUNT_LANE_3 0x2087
#define SUNI1x10GEXP_REG_XRF_INTERRUPT_ENABLE 0x2088
#define SUNI1x10GEXP_REG_XRF_INTERRUPT_STATUS 0x2089
+#define SUNI1x10GEXP_REG_XRF_ERR_STATUS 0x208A
#define SUNI1x10GEXP_REG_XRF_DIAG_INTERRUPT_ENABLE 0x208B
#define SUNI1x10GEXP_REG_XRF_DIAG_INTERRUPT_STATUS 0x208C
+#define SUNI1x10GEXP_REG_XRF_CODE_ERR_THRES 0x2092
+
+#define SUNI1x10GEXP_REG_RXOAM_CONFIG 0x20C0
+#define SUNI1x10GEXP_REG_RXOAM_FILTER_1_CONFIG 0x20C1
+#define SUNI1x10GEXP_REG_RXOAM_FILTER_2_CONFIG 0x20C2
+#define SUNI1x10GEXP_REG_RXOAM_CONFIG_2 0x20C3
+#define SUNI1x10GEXP_REG_RXOAM_HEC_CONFIG 0x20C4
+#define SUNI1x10GEXP_REG_RXOAM_HEC_ERR_THRES 0x20C5
#define SUNI1x10GEXP_REG_RXOAM_INTERRUPT_ENABLE 0x20C7
#define SUNI1x10GEXP_REG_RXOAM_INTERRUPT_STATUS 0x20C8
+#define SUNI1x10GEXP_REG_RXOAM_STATUS 0x20C9
+#define SUNI1x10GEXP_REG_RXOAM_HEC_ERR_COUNT 0x20CA
+#define SUNI1x10GEXP_REG_RXOAM_FIFO_OVERFLOW_COUNT 0x20CB
+#define SUNI1x10GEXP_REG_RXOAM_FILTER_MISMATCH_COUNT_LSB 0x20CC
+#define SUNI1x10GEXP_REG_RXOAM_FILTER_MISMATCH_COUNT_MSB 0x20CD
+#define SUNI1x10GEXP_REG_RXOAM_FILTER_1_MISMATCH_COUNT_LSB 0x20CE
+#define SUNI1x10GEXP_REG_RXOAM_FILTER_1_MISMATCH_COUNT_MSB 0x20CF
+#define SUNI1x10GEXP_REG_RXOAM_FILTER_2_MISMATCH_COUNT_LSB 0x20D0
+#define SUNI1x10GEXP_REG_RXOAM_FILTER_2_MISMATCH_COUNT_MSB 0x20D1
+#define SUNI1x10GEXP_REG_RXOAM_OAM_EXTRACT_COUNT_LSB 0x20D2
+#define SUNI1x10GEXP_REG_RXOAM_OAM_EXTRACT_COUNT_MSB 0x20D3
+#define SUNI1x10GEXP_REG_RXOAM_MINI_PACKET_COUNT_LSB 0x20D4
+#define SUNI1x10GEXP_REG_RXOAM_MINI_PACKET_COUNT_MSB 0x20D5
+#define SUNI1x10GEXP_REG_RXOAM_FILTER_MISMATCH_THRES_LSB 0x20D6
+#define SUNI1x10GEXP_REG_RXOAM_FILTER_MISMATCH_THRES_MSB 0x20D7
+
#define SUNI1x10GEXP_REG_MSTAT_CONTROL 0x2100
#define SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_0 0x2101
#define SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_1 0x2102
@@ -75,50 +191,321 @@
#define SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_1 0x2106
#define SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_2 0x2107
#define SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_3 0x2108
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_WRITE_ADDRESS 0x2109
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_WRITE_DATA_LOW 0x210A
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_WRITE_DATA_MIDDLE 0x210B
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_WRITE_DATA_HIGH 0x210C
+#define mSUNI1x10GEXP_REG_MSTAT_COUNTER_LOW(countId) (0x2110 + mSUNI1x10GEXP_MSTAT_COUNT_OFFSET(countId))
+#define mSUNI1x10GEXP_REG_MSTAT_COUNTER_MID(countId) (0x2111 + mSUNI1x10GEXP_MSTAT_COUNT_OFFSET(countId))
+#define mSUNI1x10GEXP_REG_MSTAT_COUNTER_HIGH(countId) (0x2112 + mSUNI1x10GEXP_MSTAT_COUNT_OFFSET(countId))
#define SUNI1x10GEXP_REG_MSTAT_COUNTER_0_LOW 0x2110
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_0_MID 0x2111
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_0_HIGH 0x2112
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_0_RESVD 0x2113
#define SUNI1x10GEXP_REG_MSTAT_COUNTER_1_LOW 0x2114
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_1_MID 0x2115
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_1_HIGH 0x2116
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_1_RESVD 0x2117
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_2_LOW 0x2118
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_2_MID 0x2119
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_2_HIGH 0x211A
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_2_RESVD 0x211B
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_3_LOW 0x211C
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_3_MID 0x211D
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_3_HIGH 0x211E
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_3_RESVD 0x211F
#define SUNI1x10GEXP_REG_MSTAT_COUNTER_4_LOW 0x2120
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_4_MID 0x2121
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_4_HIGH 0x2122
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_4_RESVD 0x2123
#define SUNI1x10GEXP_REG_MSTAT_COUNTER_5_LOW 0x2124
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_5_MID 0x2125
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_5_HIGH 0x2126
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_5_RESVD 0x2127
#define SUNI1x10GEXP_REG_MSTAT_COUNTER_6_LOW 0x2128
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_6_MID 0x2129
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_6_HIGH 0x212A
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_6_RESVD 0x212B
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_7_LOW 0x212C
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_7_MID 0x212D
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_7_HIGH 0x212E
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_7_RESVD 0x212F
#define SUNI1x10GEXP_REG_MSTAT_COUNTER_8_LOW 0x2130
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_8_MID 0x2131
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_8_HIGH 0x2132
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_8_RESVD 0x2133
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_9_LOW 0x2134
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_9_MID 0x2135
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_9_HIGH 0x2136
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_9_RESVD 0x2137
#define SUNI1x10GEXP_REG_MSTAT_COUNTER_10_LOW 0x2138
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_10_MID 0x2139
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_10_HIGH 0x213A
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_10_RESVD 0x213B
#define SUNI1x10GEXP_REG_MSTAT_COUNTER_11_LOW 0x213C
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_11_MID 0x213D
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_11_HIGH 0x213E
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_11_RESVD 0x213F
#define SUNI1x10GEXP_REG_MSTAT_COUNTER_12_LOW 0x2140
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_12_MID 0x2141
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_12_HIGH 0x2142
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_12_RESVD 0x2143
#define SUNI1x10GEXP_REG_MSTAT_COUNTER_13_LOW 0x2144
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_13_MID 0x2145
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_13_HIGH 0x2146
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_13_RESVD 0x2147
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_14_LOW 0x2148
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_14_MID 0x2149
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_14_HIGH 0x214A
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_14_RESVD 0x214B
#define SUNI1x10GEXP_REG_MSTAT_COUNTER_15_LOW 0x214C
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_15_MID 0x214D
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_15_HIGH 0x214E
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_15_RESVD 0x214F
#define SUNI1x10GEXP_REG_MSTAT_COUNTER_16_LOW 0x2150
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_16_MID 0x2151
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_16_HIGH 0x2152
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_16_RESVD 0x2153
#define SUNI1x10GEXP_REG_MSTAT_COUNTER_17_LOW 0x2154
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_17_MID 0x2155
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_17_HIGH 0x2156
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_17_RESVD 0x2157
#define SUNI1x10GEXP_REG_MSTAT_COUNTER_18_LOW 0x2158
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_18_MID 0x2159
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_18_HIGH 0x215A
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_18_RESVD 0x215B
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_19_LOW 0x215C
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_19_MID 0x215D
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_19_HIGH 0x215E
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_19_RESVD 0x215F
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_20_LOW 0x2160
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_20_MID 0x2161
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_20_HIGH 0x2162
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_20_RESVD 0x2163
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_21_LOW 0x2164
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_21_MID 0x2165
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_21_HIGH 0x2166
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_21_RESVD 0x2167
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_22_LOW 0x2168
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_22_MID 0x2169
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_22_HIGH 0x216A
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_22_RESVD 0x216B
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_23_LOW 0x216C
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_23_MID 0x216D
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_23_HIGH 0x216E
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_23_RESVD 0x216F
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_24_LOW 0x2170
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_24_MID 0x2171
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_24_HIGH 0x2172
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_24_RESVD 0x2173
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_25_LOW 0x2174
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_25_MID 0x2175
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_25_HIGH 0x2176
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_25_RESVD 0x2177
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_26_LOW 0x2178
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_26_MID 0x2179
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_26_HIGH 0x217a
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_26_RESVD 0x217b
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_27_LOW 0x217c
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_27_MID 0x217d
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_27_HIGH 0x217e
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_27_RESVD 0x217f
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_28_LOW 0x2180
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_28_MID 0x2181
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_28_HIGH 0x2182
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_28_RESVD 0x2183
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_29_LOW 0x2184
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_29_MID 0x2185
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_29_HIGH 0x2186
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_29_RESVD 0x2187
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_30_LOW 0x2188
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_30_MID 0x2189
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_30_HIGH 0x218A
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_30_RESVD 0x218B
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_31_LOW 0x218C
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_31_MID 0x218D
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_31_HIGH 0x218E
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_31_RESVD 0x218F
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_32_LOW 0x2190
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_32_MID 0x2191
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_32_HIGH 0x2192
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_32_RESVD 0x2193
#define SUNI1x10GEXP_REG_MSTAT_COUNTER_33_LOW 0x2194
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_33_MID 0x2195
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_33_HIGH 0x2196
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_33_RESVD 0x2197
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_34_LOW 0x2198
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_34_MID 0x2199
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_34_HIGH 0x219A
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_34_RESVD 0x219B
#define SUNI1x10GEXP_REG_MSTAT_COUNTER_35_LOW 0x219C
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_35_MID 0x219D
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_35_HIGH 0x219E
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_35_RESVD 0x219F
#define SUNI1x10GEXP_REG_MSTAT_COUNTER_36_LOW 0x21A0
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_36_MID 0x21A1
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_36_HIGH 0x21A2
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_36_RESVD 0x21A3
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_37_LOW 0x21A4
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_37_MID 0x21A5
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_37_HIGH 0x21A6
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_37_RESVD 0x21A7
#define SUNI1x10GEXP_REG_MSTAT_COUNTER_38_LOW 0x21A8
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_38_MID 0x21A9
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_38_HIGH 0x21AA
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_38_RESVD 0x21AB
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_39_LOW 0x21AC
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_39_MID 0x21AD
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_39_HIGH 0x21AE
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_39_RESVD 0x21AF
#define SUNI1x10GEXP_REG_MSTAT_COUNTER_40_LOW 0x21B0
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_40_MID 0x21B1
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_40_HIGH 0x21B2
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_40_RESVD 0x21B3
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_41_LOW 0x21B4
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_41_MID 0x21B5
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_41_HIGH 0x21B6
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_41_RESVD 0x21B7
#define SUNI1x10GEXP_REG_MSTAT_COUNTER_42_LOW 0x21B8
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_42_MID 0x21B9
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_42_HIGH 0x21BA
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_42_RESVD 0x21BB
#define SUNI1x10GEXP_REG_MSTAT_COUNTER_43_LOW 0x21BC
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_43_MID 0x21BD
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_43_HIGH 0x21BE
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_43_RESVD 0x21BF
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_44_LOW 0x21C0
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_44_MID 0x21C1
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_44_HIGH 0x21C2
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_44_RESVD 0x21C3
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_45_LOW 0x21C4
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_45_MID 0x21C5
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_45_HIGH 0x21C6
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_45_RESVD 0x21C7
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_46_LOW 0x21C8
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_46_MID 0x21C9
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_46_HIGH 0x21CA
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_46_RESVD 0x21CB
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_47_LOW 0x21CC
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_47_MID 0x21CD
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_47_HIGH 0x21CE
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_47_RESVD 0x21CF
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_48_LOW 0x21D0
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_48_MID 0x21D1
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_48_HIGH 0x21D2
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_48_RESVD 0x21D3
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_49_LOW 0x21D4
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_49_MID 0x21D5
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_49_HIGH 0x21D6
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_49_RESVD 0x21D7
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_50_LOW 0x21D8
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_50_MID 0x21D9
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_50_HIGH 0x21DA
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_50_RESVD 0x21DB
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_51_LOW 0x21DC
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_51_MID 0x21DD
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_51_HIGH 0x21DE
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_51_RESVD 0x21DF
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_52_LOW 0x21E0
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_52_MID 0x21E1
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_52_HIGH 0x21E2
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_52_RESVD 0x21E3
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_53_LOW 0x21E4
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_53_MID 0x21E5
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_53_HIGH 0x21E6
+#define SUNI1x10GEXP_CNTR_MAC_ETHERNET_NUM 51
+
+#define SUNI1x10GEXP_REG_IFLX_GLOBAL_CONFIG 0x2200
+#define SUNI1x10GEXP_REG_IFLX_CHANNEL_PROVISION 0x2201
#define SUNI1x10GEXP_REG_IFLX_FIFO_OVERFLOW_ENABLE 0x2209
#define SUNI1x10GEXP_REG_IFLX_FIFO_OVERFLOW_INTERRUPT 0x220A
+#define SUNI1x10GEXP_REG_IFLX_INDIR_CHANNEL_ADDRESS 0x220D
+#define SUNI1x10GEXP_REG_IFLX_INDIR_LOGICAL_FIFO_LOW_LIMIT_PROVISION 0x220E
+#define SUNI1x10GEXP_REG_IFLX_INDIR_LOGICAL_FIFO_HIGH_LIMIT 0x220F
+#define SUNI1x10GEXP_REG_IFLX_INDIR_FULL_ALMOST_FULL_STATUS_LIMIT 0x2210
+#define SUNI1x10GEXP_REG_IFLX_INDIR_EMPTY_ALMOST_EMPTY_STATUS_LIMIT 0x2211
+
+#define SUNI1x10GEXP_REG_PL4MOS_CONFIG 0x2240
+#define SUNI1x10GEXP_REG_PL4MOS_MASK 0x2241
+#define SUNI1x10GEXP_REG_PL4MOS_FAIRNESS_MASKING 0x2242
+#define SUNI1x10GEXP_REG_PL4MOS_MAXBURST1 0x2243
+#define SUNI1x10GEXP_REG_PL4MOS_MAXBURST2 0x2244
+#define SUNI1x10GEXP_REG_PL4MOS_TRANSFER_SIZE 0x2245
+
+#define SUNI1x10GEXP_REG_PL4ODP_CONFIG 0x2280
#define SUNI1x10GEXP_REG_PL4ODP_INTERRUPT_MASK 0x2282
#define SUNI1x10GEXP_REG_PL4ODP_INTERRUPT 0x2283
+#define SUNI1x10GEXP_REG_PL4ODP_CONFIG_MAX_T 0x2284
+
#define SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_STATUS 0x2300
#define SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_CHANGE 0x2301
#define SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_MASK 0x2302
+#define SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_LIMITS 0x2303
+#define SUNI1x10GEXP_REG_PL4IO_CALENDAR_REPETITIONS 0x2304
+#define SUNI1x10GEXP_REG_PL4IO_CONFIG 0x2305
+
#define SUNI1x10GEXP_REG_TXXG_CONFIG_1 0x3040
+#define SUNI1x10GEXP_REG_TXXG_CONFIG_2 0x3041
#define SUNI1x10GEXP_REG_TXXG_CONFIG_3 0x3042
#define SUNI1x10GEXP_REG_TXXG_INTERRUPT 0x3043
+#define SUNI1x10GEXP_REG_TXXG_STATUS 0x3044
#define SUNI1x10GEXP_REG_TXXG_MAX_FRAME_SIZE 0x3045
+#define SUNI1x10GEXP_REG_TXXG_MIN_FRAME_SIZE 0x3046
#define SUNI1x10GEXP_REG_TXXG_SA_15_0 0x3047
#define SUNI1x10GEXP_REG_TXXG_SA_31_16 0x3048
#define SUNI1x10GEXP_REG_TXXG_SA_47_32 0x3049
+#define SUNI1x10GEXP_REG_TXXG_PAUSE_TIMER 0x304D
+#define SUNI1x10GEXP_REG_TXXG_PAUSE_TIMER_INTERVAL 0x304E
+#define SUNI1x10GEXP_REG_TXXG_FILTER_ERROR_COUNTER 0x3051
+#define SUNI1x10GEXP_REG_TXXG_PAUSE_QUANTUM_CONFIG 0x3052
+
+#define SUNI1x10GEXP_REG_XTEF_CTRL 0x3080
#define SUNI1x10GEXP_REG_XTEF_INTERRUPT_STATUS 0x3084
#define SUNI1x10GEXP_REG_XTEF_INTERRUPT_ENABLE 0x3085
+#define SUNI1x10GEXP_REG_XTEF_VISIBILITY 0x3086
+
+#define SUNI1x10GEXP_REG_TXOAM_OAM_CONFIG 0x30C0
+#define SUNI1x10GEXP_REG_TXOAM_MINI_RATE_CONFIG 0x30C1
+#define SUNI1x10GEXP_REG_TXOAM_MINI_GAP_FIFO_CONFIG 0x30C2
+#define SUNI1x10GEXP_REG_TXOAM_P1P2_STATIC_VALUES 0x30C3
+#define SUNI1x10GEXP_REG_TXOAM_P3P4_STATIC_VALUES 0x30C4
+#define SUNI1x10GEXP_REG_TXOAM_P5P6_STATIC_VALUES 0x30C5
#define SUNI1x10GEXP_REG_TXOAM_INTERRUPT_ENABLE 0x30C6
#define SUNI1x10GEXP_REG_TXOAM_INTERRUPT_STATUS 0x30C7
+#define SUNI1x10GEXP_REG_TXOAM_INSERT_COUNT_LSB 0x30C8
+#define SUNI1x10GEXP_REG_TXOAM_INSERT_COUNT_MSB 0x30C9
+#define SUNI1x10GEXP_REG_TXOAM_OAM_MINI_COUNT_LSB 0x30CA
+#define SUNI1x10GEXP_REG_TXOAM_OAM_MINI_COUNT_MSB 0x30CB
+#define SUNI1x10GEXP_REG_TXOAM_P1P2_MINI_MASK 0x30CC
+#define SUNI1x10GEXP_REG_TXOAM_P3P4_MINI_MASK 0x30CD
+#define SUNI1x10GEXP_REG_TXOAM_P5P6_MINI_MASK 0x30CE
+#define SUNI1x10GEXP_REG_TXOAM_COSET 0x30CF
+#define SUNI1x10GEXP_REG_TXOAM_EMPTY_FIFO_INS_OP_CNT_LSB 0x30D0
+#define SUNI1x10GEXP_REG_TXOAM_EMPTY_FIFO_INS_OP_CNT_MSB 0x30D1
+#define SUNI1x10GEXP_REG_TXOAM_STATIC_VALUE_MINI_COUNT_LSB 0x30D2
+#define SUNI1x10GEXP_REG_TXOAM_STATIC_VALUE_MINI_COUNT_MSB 0x30D3
+
+
+#define SUNI1x10GEXP_REG_EFLX_GLOBAL_CONFIG 0x3200
+#define SUNI1x10GEXP_REG_EFLX_ERCU_GLOBAL_STATUS 0x3201
+#define SUNI1x10GEXP_REG_EFLX_INDIR_CHANNEL_ADDRESS 0x3202
+#define SUNI1x10GEXP_REG_EFLX_INDIR_FIFO_LOW_LIMIT 0x3203
+#define SUNI1x10GEXP_REG_EFLX_INDIR_FIFO_HIGH_LIMIT 0x3204
+#define SUNI1x10GEXP_REG_EFLX_INDIR_FULL_ALMOST_FULL_STATUS_AND_LIMIT 0x3205
+#define SUNI1x10GEXP_REG_EFLX_INDIR_EMPTY_ALMOST_EMPTY_STATUS_AND_LIMIT 0x3206
+#define SUNI1x10GEXP_REG_EFLX_INDIR_FIFO_CUT_THROUGH_THRESHOLD 0x3207
#define SUNI1x10GEXP_REG_EFLX_FIFO_OVERFLOW_ERROR_ENABLE 0x320C
#define SUNI1x10GEXP_REG_EFLX_FIFO_OVERFLOW_ERROR_INDICATION 0x320D
+#define SUNI1x10GEXP_REG_EFLX_CHANNEL_PROVISION 0x3210
+
+#define SUNI1x10GEXP_REG_PL4IDU_CONFIG 0x3280
#define SUNI1x10GEXP_REG_PL4IDU_INTERRUPT_MASK 0x3282
#define SUNI1x10GEXP_REG_PL4IDU_INTERRUPT 0x3283
+
+/*----------------------------------------*/
+#define SUNI1x10GEXP_REG_MAX_OFFSET 0x3480
+
/******************************************************************************/
/* -- End register offset definitions -- */
/******************************************************************************/
@@ -127,6 +514,81 @@
/** SUNI-1x10GE-XP REGISTER BIT MASKS **/
/******************************************************************************/
+#define SUNI1x10GEXP_BITMSK_BITS_1 0x00001
+#define SUNI1x10GEXP_BITMSK_BITS_2 0x00003
+#define SUNI1x10GEXP_BITMSK_BITS_3 0x00007
+#define SUNI1x10GEXP_BITMSK_BITS_4 0x0000f
+#define SUNI1x10GEXP_BITMSK_BITS_5 0x0001f
+#define SUNI1x10GEXP_BITMSK_BITS_6 0x0003f
+#define SUNI1x10GEXP_BITMSK_BITS_7 0x0007f
+#define SUNI1x10GEXP_BITMSK_BITS_8 0x000ff
+#define SUNI1x10GEXP_BITMSK_BITS_9 0x001ff
+#define SUNI1x10GEXP_BITMSK_BITS_10 0x003ff
+#define SUNI1x10GEXP_BITMSK_BITS_11 0x007ff
+#define SUNI1x10GEXP_BITMSK_BITS_12 0x00fff
+#define SUNI1x10GEXP_BITMSK_BITS_13 0x01fff
+#define SUNI1x10GEXP_BITMSK_BITS_14 0x03fff
+#define SUNI1x10GEXP_BITMSK_BITS_15 0x07fff
+#define SUNI1x10GEXP_BITMSK_BITS_16 0x0ffff
+
+#define mSUNI1x10GEXP_CLR_MSBITS_1(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_15)
+#define mSUNI1x10GEXP_CLR_MSBITS_2(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_14)
+#define mSUNI1x10GEXP_CLR_MSBITS_3(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_13)
+#define mSUNI1x10GEXP_CLR_MSBITS_4(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_12)
+#define mSUNI1x10GEXP_CLR_MSBITS_5(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_11)
+#define mSUNI1x10GEXP_CLR_MSBITS_6(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_10)
+#define mSUNI1x10GEXP_CLR_MSBITS_7(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_9)
+#define mSUNI1x10GEXP_CLR_MSBITS_8(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_8)
+#define mSUNI1x10GEXP_CLR_MSBITS_9(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_7)
+#define mSUNI1x10GEXP_CLR_MSBITS_10(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_6)
+#define mSUNI1x10GEXP_CLR_MSBITS_11(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_5)
+#define mSUNI1x10GEXP_CLR_MSBITS_12(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_4)
+#define mSUNI1x10GEXP_CLR_MSBITS_13(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_3)
+#define mSUNI1x10GEXP_CLR_MSBITS_14(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_2)
+#define mSUNI1x10GEXP_CLR_MSBITS_15(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_1)
+
+#define mSUNI1x10GEXP_GET_BIT(val, bitMsk) (((val)&(bitMsk)) ? 1:0)
+
+
+
+/*----------------------------------------------------------------------------
+ * Register 0x0001: S/UNI-1x10GE-XP Product Revision
+ * Bit 3-0 REVISION
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_REVISION 0x000F
+
+/*----------------------------------------------------------------------------
+ * Register 0x0002: S/UNI-1x10GE-XP Configuration and Reset Control
+ * Bit 2 XAUI_ARESETB
+ * Bit 1 PL4_ARESETB
+ * Bit 0 DRESETB
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_XAUI_ARESET 0x0004
+#define SUNI1x10GEXP_BITMSK_PL4_ARESET 0x0002
+#define SUNI1x10GEXP_BITMSK_DRESETB 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x0003: S/UNI-1x10GE-XP Loop Back and Miscellaneous Control
+ * Bit 11 PL4IO_OUTCLKSEL
+ * Bit 9 SYSPCSLB
+ * Bit 8 LINEPCSLB
+ * Bit 7 MSTAT_BYPASS
+ * Bit 6 RXXG_BYPASS
+ * Bit 5 TXXG_BYPASS
+ * Bit 4 SOP_PAD_EN
+ * Bit 1 LOS_INV
+ * Bit 0 OVERRIDE_LOS
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_PL4IO_OUTCLKSEL 0x0800
+#define SUNI1x10GEXP_BITMSK_SYSPCSLB 0x0200
+#define SUNI1x10GEXP_BITMSK_LINEPCSLB 0x0100
+#define SUNI1x10GEXP_BITMSK_MSTAT_BYPASS 0x0080
+#define SUNI1x10GEXP_BITMSK_RXXG_BYPASS 0x0040
+#define SUNI1x10GEXP_BITMSK_TXXG_BYPASS 0x0020
+#define SUNI1x10GEXP_BITMSK_SOP_PAD_EN 0x0010
+#define SUNI1x10GEXP_BITMSK_LOS_INV 0x0002
+#define SUNI1x10GEXP_BITMSK_OVERRIDE_LOS 0x0001
+
/*----------------------------------------------------------------------------
* Register 0x0004: S/UNI-1x10GE-XP Device Status
* Bit 9 TOP_SXRA_EXPIRED
@@ -141,7 +603,10 @@
* Bit 0 TOP_PL4_OUT_ROOL
*----------------------------------------------------------------------------*/
#define SUNI1x10GEXP_BITMSK_TOP_SXRA_EXPIRED 0x0200
+#define SUNI1x10GEXP_BITMSK_TOP_MDIO_BUSY 0x0100
+#define SUNI1x10GEXP_BITMSK_TOP_DTRB 0x0080
#define SUNI1x10GEXP_BITMSK_TOP_EXPIRED 0x0040
+#define SUNI1x10GEXP_BITMSK_TOP_PAUSED 0x0020
#define SUNI1x10GEXP_BITMSK_TOP_PL4_ID_DOOL 0x0010
#define SUNI1x10GEXP_BITMSK_TOP_PL4_IS_DOOL 0x0008
#define SUNI1x10GEXP_BITMSK_TOP_PL4_ID_ROOL 0x0004
@@ -149,12 +614,219 @@
#define SUNI1x10GEXP_BITMSK_TOP_PL4_OUT_ROOL 0x0001
/*----------------------------------------------------------------------------
+ * Register 0x0005: Global Performance Update and Clock Monitors
+ * Bit 15 TIP
+ * Bit 8 XAUI_REF_CLKA
+ * Bit 7 RXLANE3CLKA
+ * Bit 6 RXLANE2CLKA
+ * Bit 5 RXLANE1CLKA
+ * Bit 4 RXLANE0CLKA
+ * Bit 3 CSUCLKA
+ * Bit 2 TDCLKA
+ * Bit 1 RSCLKA
+ * Bit 0 RDCLKA
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_TIP 0x8000
+#define SUNI1x10GEXP_BITMSK_XAUI_REF_CLKA 0x0100
+#define SUNI1x10GEXP_BITMSK_RXLANE3CLKA 0x0080
+#define SUNI1x10GEXP_BITMSK_RXLANE2CLKA 0x0040
+#define SUNI1x10GEXP_BITMSK_RXLANE1CLKA 0x0020
+#define SUNI1x10GEXP_BITMSK_RXLANE0CLKA 0x0010
+#define SUNI1x10GEXP_BITMSK_CSUCLKA 0x0008
+#define SUNI1x10GEXP_BITMSK_TDCLKA 0x0004
+#define SUNI1x10GEXP_BITMSK_RSCLKA 0x0002
+#define SUNI1x10GEXP_BITMSK_RDCLKA 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x0006: MDIO Command
+ * Bit 4 MDIO_RDINC
+ * Bit 3 MDIO_RSTAT
+ * Bit 2 MDIO_LCTLD
+ * Bit 1 MDIO_LCTLA
+ * Bit 0 MDIO_SPRE
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_MDIO_RDINC 0x0010
+#define SUNI1x10GEXP_BITMSK_MDIO_RSTAT 0x0008
+#define SUNI1x10GEXP_BITMSK_MDIO_LCTLD 0x0004
+#define SUNI1x10GEXP_BITMSK_MDIO_LCTLA 0x0002
+#define SUNI1x10GEXP_BITMSK_MDIO_SPRE 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x0007: MDIO Interrupt Enable
+ * Bit 0 MDIO_BUSY_EN
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_MDIO_BUSY_EN 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x0008: MDIO Interrupt Status
+ * Bit 0 MDIO_BUSYI
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_MDIO_BUSYI 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x0009: MMD PHY Address
+ * Bit 12-8 MDIO_DEVADR
+ * Bit 4-0 MDIO_PRTADR
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_MDIO_DEVADR 0x1F00
+#define SUNI1x10GEXP_BITOFF_MDIO_DEVADR 8
+#define SUNI1x10GEXP_BITMSK_MDIO_PRTADR 0x001F
+#define SUNI1x10GEXP_BITOFF_MDIO_PRTADR 0
+
+/*----------------------------------------------------------------------------
+ * Register 0x000C: OAM Interface Control
+ * Bit 6 MDO_OD_ENB
+ * Bit 5 MDI_INV
+ * Bit 4 MDI_SEL
+ * Bit 3 RXOAMEN
+ * Bit 2 RXOAMCLKEN
+ * Bit 1 TXOAMEN
+ * Bit 0 TXOAMCLKEN
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_MDO_OD_ENB 0x0040
+#define SUNI1x10GEXP_BITMSK_MDI_INV 0x0020
+#define SUNI1x10GEXP_BITMSK_MDI_SEL 0x0010
+#define SUNI1x10GEXP_BITMSK_RXOAMEN 0x0008
+#define SUNI1x10GEXP_BITMSK_RXOAMCLKEN 0x0004
+#define SUNI1x10GEXP_BITMSK_TXOAMEN 0x0002
+#define SUNI1x10GEXP_BITMSK_TXOAMCLKEN 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x000D: S/UNI-1x10GE-XP Master Interrupt Status
+ * Bit 15 TOP_PL4IO_INT
+ * Bit 14 TOP_IRAM_INT
+ * Bit 13 TOP_ERAM_INT
+ * Bit 12 TOP_XAUI_INT
+ * Bit 11 TOP_MSTAT_INT
+ * Bit 10 TOP_RXXG_INT
+ * Bit 9 TOP_TXXG_INT
+ * Bit 8 TOP_XRF_INT
+ * Bit 7 TOP_XTEF_INT
+ * Bit 6 TOP_MDIO_BUSY_INT
+ * Bit 5 TOP_RXOAM_INT
+ * Bit 4 TOP_TXOAM_INT
+ * Bit 3 TOP_IFLX_INT
+ * Bit 2 TOP_EFLX_INT
+ * Bit 1 TOP_PL4ODP_INT
+ * Bit 0 TOP_PL4IDU_INT
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_TOP_PL4IO_INT 0x8000
+#define SUNI1x10GEXP_BITMSK_TOP_IRAM_INT 0x4000
+#define SUNI1x10GEXP_BITMSK_TOP_ERAM_INT 0x2000
+#define SUNI1x10GEXP_BITMSK_TOP_XAUI_INT 0x1000
+#define SUNI1x10GEXP_BITMSK_TOP_MSTAT_INT 0x0800
+#define SUNI1x10GEXP_BITMSK_TOP_RXXG_INT 0x0400
+#define SUNI1x10GEXP_BITMSK_TOP_TXXG_INT 0x0200
+#define SUNI1x10GEXP_BITMSK_TOP_XRF_INT 0x0100
+#define SUNI1x10GEXP_BITMSK_TOP_XTEF_INT 0x0080
+#define SUNI1x10GEXP_BITMSK_TOP_MDIO_BUSY_INT 0x0040
+#define SUNI1x10GEXP_BITMSK_TOP_RXOAM_INT 0x0020
+#define SUNI1x10GEXP_BITMSK_TOP_TXOAM_INT 0x0010
+#define SUNI1x10GEXP_BITMSK_TOP_IFLX_INT 0x0008
+#define SUNI1x10GEXP_BITMSK_TOP_EFLX_INT 0x0004
+#define SUNI1x10GEXP_BITMSK_TOP_PL4ODP_INT 0x0002
+#define SUNI1x10GEXP_BITMSK_TOP_PL4IDU_INT 0x0001
+
+/*----------------------------------------------------------------------------
* Register 0x000E:PM3393 Global interrupt enable
* Bit 15 TOP_INTE
*----------------------------------------------------------------------------*/
#define SUNI1x10GEXP_BITMSK_TOP_INTE 0x8000
/*----------------------------------------------------------------------------
+ * Register 0x0010: XTEF Miscellaneous Control
+ * Bit 7 RF_VAL
+ * Bit 6 RF_OVERRIDE
+ * Bit 5 LF_VAL
+ * Bit 4 LF_OVERRIDE
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_RF_VAL 0x0080
+#define SUNI1x10GEXP_BITMSK_RF_OVERRIDE 0x0040
+#define SUNI1x10GEXP_BITMSK_LF_VAL 0x0020
+#define SUNI1x10GEXP_BITMSK_LF_OVERRIDE 0x0010
+#define SUNI1x10GEXP_BITMSK_LFRF_OVERRIDE_VAL 0x00F0
+
+/*----------------------------------------------------------------------------
+ * Register 0x0011: XRF Miscellaneous Control
+ * Bit 6-4 EN_IDLE_REP
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_EN_IDLE_REP 0x0070
+
+/*----------------------------------------------------------------------------
+ * Register 0x0100: SERDES 3125 Configuration Register 1
+ * Bit 10 RXEQB_3
+ * Bit 8 RXEQB_2
+ * Bit 6 RXEQB_1
+ * Bit 4 RXEQB_0
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_RXEQB 0x0FF0
+#define SUNI1x10GEXP_BITOFF_RXEQB_3 10
+#define SUNI1x10GEXP_BITOFF_RXEQB_2 8
+#define SUNI1x10GEXP_BITOFF_RXEQB_1 6
+#define SUNI1x10GEXP_BITOFF_RXEQB_0 4
+
+/*----------------------------------------------------------------------------
+ * Register 0x0101: SERDES 3125 Configuration Register 2
+ * Bit 12 YSEL
+ * Bit 7 PRE_EMPH_3
+ * Bit 6 PRE_EMPH_2
+ * Bit 5 PRE_EMPH_1
+ * Bit 4 PRE_EMPH_0
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_YSEL 0x1000
+#define SUNI1x10GEXP_BITMSK_PRE_EMPH 0x00F0
+#define SUNI1x10GEXP_BITMSK_PRE_EMPH_3 0x0080
+#define SUNI1x10GEXP_BITMSK_PRE_EMPH_2 0x0040
+#define SUNI1x10GEXP_BITMSK_PRE_EMPH_1 0x0020
+#define SUNI1x10GEXP_BITMSK_PRE_EMPH_0 0x0010
+
+/*----------------------------------------------------------------------------
+ * Register 0x0102: SERDES 3125 Interrupt Enable Register
+ * Bit 3 LASIE
+ * Bit 2 SPLL_RAE
+ * Bit 1 MPLL_RAE
+ * Bit 0 PLL_LOCKE
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_LASIE 0x0008
+#define SUNI1x10GEXP_BITMSK_SPLL_RAE 0x0004
+#define SUNI1x10GEXP_BITMSK_MPLL_RAE 0x0002
+#define SUNI1x10GEXP_BITMSK_PLL_LOCKE 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x0103: SERDES 3125 Interrupt Visibility Register
+ * Bit 3 LASIV
+ * Bit 2 SPLL_RAV
+ * Bit 1 MPLL_RAV
+ * Bit 0 PLL_LOCKV
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_LASIV 0x0008
+#define SUNI1x10GEXP_BITMSK_SPLL_RAV 0x0004
+#define SUNI1x10GEXP_BITMSK_MPLL_RAV 0x0002
+#define SUNI1x10GEXP_BITMSK_PLL_LOCKV 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x0104: SERDES 3125 Interrupt Status Register
+ * Bit 3 LASII
+ * Bit 2 SPLL_RAI
+ * Bit 1 MPLL_RAI
+ * Bit 0 PLL_LOCKI
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_LASII 0x0008
+#define SUNI1x10GEXP_BITMSK_SPLL_RAI 0x0004
+#define SUNI1x10GEXP_BITMSK_MPLL_RAI 0x0002
+#define SUNI1x10GEXP_BITMSK_PLL_LOCKI 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x0107: SERDES 3125 Test Configuration
+ * Bit 12 DUALTX
+ * Bit 10 HC_1
+ * Bit 9 HC_0
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_DUALTX 0x1000
+#define SUNI1x10GEXP_BITMSK_HC 0x0600
+#define SUNI1x10GEXP_BITOFF_HC_0 9
+
+/*----------------------------------------------------------------------------
* Register 0x2040: RXXG Configuration 1
* Bit 15 RXXG_RXEN
* Bit 14 RXXG_ROCF
@@ -168,11 +840,84 @@
* Bit 2-0 RXXG_MIFG
*----------------------------------------------------------------------------*/
#define SUNI1x10GEXP_BITMSK_RXXG_RXEN 0x8000
+#define SUNI1x10GEXP_BITMSK_RXXG_ROCF 0x4000
+#define SUNI1x10GEXP_BITMSK_RXXG_PAD_STRIP 0x2000
#define SUNI1x10GEXP_BITMSK_RXXG_PUREP 0x0400
+#define SUNI1x10GEXP_BITMSK_RXXG_LONGP 0x0200
+#define SUNI1x10GEXP_BITMSK_RXXG_PARF 0x0100
#define SUNI1x10GEXP_BITMSK_RXXG_FLCHK 0x0080
+#define SUNI1x10GEXP_BITMSK_RXXG_PASS_CTRL 0x0020
#define SUNI1x10GEXP_BITMSK_RXXG_CRC_STRIP 0x0008
/*----------------------------------------------------------------------------
+ * Register 0x02041: RXXG Configuration 2
+ * Bit 7-0 RXXG_HDRSIZE
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_RXXG_HDRSIZE 0x00FF
+
+/*----------------------------------------------------------------------------
+ * Register 0x2042: RXXG Configuration 3
+ * Bit 15 RXXG_MIN_LERRE
+ * Bit 14 RXXG_MAX_LERRE
+ * Bit 12 RXXG_LINE_ERRE
+ * Bit 10 RXXG_RX_OVRE
+ * Bit 9 RXXG_ADR_FILTERE
+ * Bit 8 RXXG_ERR_FILTERE
+ * Bit 5 RXXG_PRMB_ERRE
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_RXXG_MIN_LERRE 0x8000
+#define SUNI1x10GEXP_BITMSK_RXXG_MAX_LERRE 0x4000
+#define SUNI1x10GEXP_BITMSK_RXXG_LINE_ERRE 0x1000
+#define SUNI1x10GEXP_BITMSK_RXXG_RX_OVRE 0x0400
+#define SUNI1x10GEXP_BITMSK_RXXG_ADR_FILTERE 0x0200
+#define SUNI1x10GEXP_BITMSK_RXXG_ERR_FILTERRE 0x0100
+#define SUNI1x10GEXP_BITMSK_RXXG_PRMB_ERRE 0x0020
+
+/*----------------------------------------------------------------------------
+ * Register 0x2043: RXXG Interrupt
+ * Bit 15 RXXG_MIN_LERRI
+ * Bit 14 RXXG_MAX_LERRI
+ * Bit 12 RXXG_LINE_ERRI
+ * Bit 10 RXXG_RX_OVRI
+ * Bit 9 RXXG_ADR_FILTERI
+ * Bit 8 RXXG_ERR_FILTERI
+ * Bit 5 RXXG_PRMB_ERRE
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_RXXG_MIN_LERRI 0x8000
+#define SUNI1x10GEXP_BITMSK_RXXG_MAX_LERRI 0x4000
+#define SUNI1x10GEXP_BITMSK_RXXG_LINE_ERRI 0x1000
+#define SUNI1x10GEXP_BITMSK_RXXG_RX_OVRI 0x0400
+#define SUNI1x10GEXP_BITMSK_RXXG_ADR_FILTERI 0x0200
+#define SUNI1x10GEXP_BITMSK_RXXG_ERR_FILTERI 0x0100
+#define SUNI1x10GEXP_BITMSK_RXXG_PRMB_ERRE 0x0020
+
+/*----------------------------------------------------------------------------
+ * Register 0x2049: RXXG Receive FIFO Threshold
+ * Bit 2-0 RXXG_CUT_THRU
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_RXXG_CUT_THRU 0x0007
+#define SUNI1x10GEXP_BITOFF_RXXG_CUT_THRU 0
+
+/*----------------------------------------------------------------------------
+ * Register 0x2062H - 0x2069: RXXG Exact Match VID
+ * Bit 11-0 RXXG_VID_MATCH
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_RXXG_VID_MATCH 0x0FFF
+#define SUNI1x10GEXP_BITOFF_RXXG_VID_MATCH 0
+
+/*----------------------------------------------------------------------------
+ * Register 0x206EH - 0x206F: RXXG Address Filter Control
+ * Bit 3 RXXG_FORWARD_ENABLE
+ * Bit 2 RXXG_VLAN_ENABLE
+ * Bit 1 RXXG_SRC_ADDR
+ * Bit 0 RXXG_MATCH_ENABLE
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_RXXG_FORWARD_ENABLE 0x0008
+#define SUNI1x10GEXP_BITMSK_RXXG_VLAN_ENABLE 0x0004
+#define SUNI1x10GEXP_BITMSK_RXXG_SRC_ADDR 0x0002
+#define SUNI1x10GEXP_BITMSK_RXXG_MATCH_ENABLE 0x0001
+
+/*----------------------------------------------------------------------------
* Register 0x2070: RXXG Address Filter Control 2
* Bit 1 RXXG_PMODE
* Bit 0 RXXG_MHASH_EN
@@ -181,15 +926,446 @@
#define SUNI1x10GEXP_BITMSK_RXXG_MHASH_EN 0x0001
/*----------------------------------------------------------------------------
+ * Register 0x2081: XRF Control Register 2
+ * Bit 6 EN_PKT_GEN
+ * Bit 4-2 PATT
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_EN_PKT_GEN 0x0040
+#define SUNI1x10GEXP_BITMSK_PATT 0x001C
+#define SUNI1x10GEXP_BITOFF_PATT 2
+
+/*----------------------------------------------------------------------------
+ * Register 0x2088: XRF Interrupt Enable
+ * Bit 12-9 LANE_HICERE
+ * Bit 8-5 HS_SD_LANEE
+ * Bit 4 ALIGN_STATUS_ERRE
+ * Bit 3-0 LANE_SYNC_STAT_ERRE
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_LANE_HICERE 0x1E00
+#define SUNI1x10GEXP_BITOFF_LANE_HICERE 9
+#define SUNI1x10GEXP_BITMSK_HS_SD_LANEE 0x01E0
+#define SUNI1x10GEXP_BITOFF_HS_SD_LANEE 5
+#define SUNI1x10GEXP_BITMSK_ALIGN_STATUS_ERRE 0x0010
+#define SUNI1x10GEXP_BITMSK_LANE_SYNC_STAT_ERRE 0x000F
+#define SUNI1x10GEXP_BITOFF_LANE_SYNC_STAT_ERRE 0
+
+/*----------------------------------------------------------------------------
+ * Register 0x2089: XRF Interrupt Status
+ * Bit 12-9 LANE_HICERI
+ * Bit 8-5 HS_SD_LANEI
+ * Bit 4 ALIGN_STATUS_ERRI
+ * Bit 3-0 LANE_SYNC_STAT_ERRI
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_LANE_HICERI 0x1E00
+#define SUNI1x10GEXP_BITOFF_LANE_HICERI 9
+#define SUNI1x10GEXP_BITMSK_HS_SD_LANEI 0x01E0
+#define SUNI1x10GEXP_BITOFF_HS_SD_LANEI 5
+#define SUNI1x10GEXP_BITMSK_ALIGN_STATUS_ERRI 0x0010
+#define SUNI1x10GEXP_BITMSK_LANE_SYNC_STAT_ERRI 0x000F
+#define SUNI1x10GEXP_BITOFF_LANE_SYNC_STAT_ERRI 0
+
+/*----------------------------------------------------------------------------
+ * Register 0x208A: XRF Error Status
+ * Bit 8-5 HS_SD_LANE
+ * Bit 4 ALIGN_STATUS_ERR
+ * Bit 3-0 LANE_SYNC_STAT_ERR
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_HS_SD_LANE3 0x0100
+#define SUNI1x10GEXP_BITMSK_HS_SD_LANE2 0x0080
+#define SUNI1x10GEXP_BITMSK_HS_SD_LANE1 0x0040
+#define SUNI1x10GEXP_BITMSK_HS_SD_LANE0 0x0020
+#define SUNI1x10GEXP_BITMSK_ALIGN_STATUS_ERR 0x0010
+#define SUNI1x10GEXP_BITMSK_LANE3_SYNC_STAT_ERR 0x0008
+#define SUNI1x10GEXP_BITMSK_LANE2_SYNC_STAT_ERR 0x0004
+#define SUNI1x10GEXP_BITMSK_LANE1_SYNC_STAT_ERR 0x0002
+#define SUNI1x10GEXP_BITMSK_LANE0_SYNC_STAT_ERR 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x208B: XRF Diagnostic Interrupt Enable
+ * Bit 7-4 LANE_OVERRUNE
+ * Bit 3-0 LANE_UNDERRUNE
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_LANE_OVERRUNE 0x00F0
+#define SUNI1x10GEXP_BITOFF_LANE_OVERRUNE 4
+#define SUNI1x10GEXP_BITMSK_LANE_UNDERRUNE 0x000F
+#define SUNI1x10GEXP_BITOFF_LANE_UNDERRUNE 0
+
+/*----------------------------------------------------------------------------
+ * Register 0x208C: XRF Diagnostic Interrupt Status
+ * Bit 7-4 LANE_OVERRUNI
+ * Bit 3-0 LANE_UNDERRUNI
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_LANE_OVERRUNI 0x00F0
+#define SUNI1x10GEXP_BITOFF_LANE_OVERRUNI 4
+#define SUNI1x10GEXP_BITMSK_LANE_UNDERRUNI 0x000F
+#define SUNI1x10GEXP_BITOFF_LANE_UNDERRUNI 0
+
+/*----------------------------------------------------------------------------
+ * Register 0x20C0: RXOAM Configuration
+ * Bit 15 RXOAM_BUSY
+ * Bit 14-12 RXOAM_F2_SEL
+ * Bit 10-8 RXOAM_F1_SEL
+ * Bit 7-6 RXOAM_FILTER_CTRL
+ * Bit 5-0 RXOAM_PX_EN
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_RXOAM_BUSY 0x8000
+#define SUNI1x10GEXP_BITMSK_RXOAM_F2_SEL 0x7000
+#define SUNI1x10GEXP_BITOFF_RXOAM_F2_SEL 12
+#define SUNI1x10GEXP_BITMSK_RXOAM_F1_SEL 0x0700
+#define SUNI1x10GEXP_BITOFF_RXOAM_F1_SEL 8
+#define SUNI1x10GEXP_BITMSK_RXOAM_FILTER_CTRL 0x00C0
+#define SUNI1x10GEXP_BITOFF_RXOAM_FILTER_CTRL 6
+#define SUNI1x10GEXP_BITMSK_RXOAM_PX_EN 0x003F
+#define SUNI1x10GEXP_BITOFF_RXOAM_PX_EN 0
+
+/*----------------------------------------------------------------------------
+ * Register 0x20C1,0x20C2: RXOAM Filter Configuration
+ * Bit 15-8 RXOAM_FX_MASK
+ * Bit 7-0 RXOAM_FX_VAL
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_RXOAM_FX_MASK 0xFF00
+#define SUNI1x10GEXP_BITOFF_RXOAM_FX_MASK 8
+#define SUNI1x10GEXP_BITMSK_RXOAM_FX_VAL 0x00FF
+#define SUNI1x10GEXP_BITOFF_RXOAM_FX_VAl 0
+
+/*----------------------------------------------------------------------------
+ * Register 0x20C3: RXOAM Configuration Register 2
+ * Bit 13 RXOAM_REC_BYTE_VAL
+ * Bit 11-10 RXOAM_BYPASS_MODE
+ * Bit 5-0 RXOAM_PX_CLEAR
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_RXOAM_REC_BYTE_VAL 0x2000
+#define SUNI1x10GEXP_BITMSK_RXOAM_BYPASS_MODE 0x0C00
+#define SUNI1x10GEXP_BITOFF_RXOAM_BYPASS_MODE 10
+#define SUNI1x10GEXP_BITMSK_RXOAM_PX_CLEAR 0x003F
+#define SUNI1x10GEXP_BITOFF_RXOAM_PX_CLEAR 0
+
+/*----------------------------------------------------------------------------
+ * Register 0x20C4: RXOAM HEC Configuration
+ * Bit 15-8 RXOAM_COSET
+ * Bit 2 RXOAM_HEC_ERR_PKT
+ * Bit 0 RXOAM_HEC_EN
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_RXOAM_COSET 0xFF00
+#define SUNI1x10GEXP_BITOFF_RXOAM_COSET 8
+#define SUNI1x10GEXP_BITMSK_RXOAM_HEC_ERR_PKT 0x0004
+#define SUNI1x10GEXP_BITMSK_RXOAM_HEC_EN 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x20C7: RXOAM Interrupt Enable
+ * Bit 10 RXOAM_FILTER_THRSHE
+ * Bit 9 RXOAM_OAM_ERRE
+ * Bit 8 RXOAM_HECE_THRSHE
+ * Bit 7 RXOAM_SOPE
+ * Bit 6 RXOAM_RFE
+ * Bit 5 RXOAM_LFE
+ * Bit 4 RXOAM_DV_ERRE
+ * Bit 3 RXOAM_DATA_INVALIDE
+ * Bit 2 RXOAM_FILTER_DROPE
+ * Bit 1 RXOAM_HECE
+ * Bit 0 RXOAM_OFLE
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_RXOAM_FILTER_THRSHE 0x0400
+#define SUNI1x10GEXP_BITMSK_RXOAM_OAM_ERRE 0x0200
+#define SUNI1x10GEXP_BITMSK_RXOAM_HECE_THRSHE 0x0100
+#define SUNI1x10GEXP_BITMSK_RXOAM_SOPE 0x0080
+#define SUNI1x10GEXP_BITMSK_RXOAM_RFE 0x0040
+#define SUNI1x10GEXP_BITMSK_RXOAM_LFE 0x0020
+#define SUNI1x10GEXP_BITMSK_RXOAM_DV_ERRE 0x0010
+#define SUNI1x10GEXP_BITMSK_RXOAM_DATA_INVALIDE 0x0008
+#define SUNI1x10GEXP_BITMSK_RXOAM_FILTER_DROPE 0x0004
+#define SUNI1x10GEXP_BITMSK_RXOAM_HECE 0x0002
+#define SUNI1x10GEXP_BITMSK_RXOAM_OFLE 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x20C8: RXOAM Interrupt Status
+ * Bit 10 RXOAM_FILTER_THRSHI
+ * Bit 9 RXOAM_OAM_ERRI
+ * Bit 8 RXOAM_HECE_THRSHI
+ * Bit 7 RXOAM_SOPI
+ * Bit 6 RXOAM_RFI
+ * Bit 5 RXOAM_LFI
+ * Bit 4 RXOAM_DV_ERRI
+ * Bit 3 RXOAM_DATA_INVALIDI
+ * Bit 2 RXOAM_FILTER_DROPI
+ * Bit 1 RXOAM_HECI
+ * Bit 0 RXOAM_OFLI
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_RXOAM_FILTER_THRSHI 0x0400
+#define SUNI1x10GEXP_BITMSK_RXOAM_OAM_ERRI 0x0200
+#define SUNI1x10GEXP_BITMSK_RXOAM_HECE_THRSHI 0x0100
+#define SUNI1x10GEXP_BITMSK_RXOAM_SOPI 0x0080
+#define SUNI1x10GEXP_BITMSK_RXOAM_RFI 0x0040
+#define SUNI1x10GEXP_BITMSK_RXOAM_LFI 0x0020
+#define SUNI1x10GEXP_BITMSK_RXOAM_DV_ERRI 0x0010
+#define SUNI1x10GEXP_BITMSK_RXOAM_DATA_INVALIDI 0x0008
+#define SUNI1x10GEXP_BITMSK_RXOAM_FILTER_DROPI 0x0004
+#define SUNI1x10GEXP_BITMSK_RXOAM_HECI 0x0002
+#define SUNI1x10GEXP_BITMSK_RXOAM_OFLI 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x20C9: RXOAM Status
+ * Bit 10 RXOAM_FILTER_THRSHV
+ * Bit 8 RXOAM_HECE_THRSHV
+ * Bit 6 RXOAM_RFV
+ * Bit 5 RXOAM_LFV
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_RXOAM_FILTER_THRSHV 0x0400
+#define SUNI1x10GEXP_BITMSK_RXOAM_HECE_THRSHV 0x0100
+#define SUNI1x10GEXP_BITMSK_RXOAM_RFV 0x0040
+#define SUNI1x10GEXP_BITMSK_RXOAM_LFV 0x0020
+
+/*----------------------------------------------------------------------------
* Register 0x2100: MSTAT Control
* Bit 2 MSTAT_WRITE
* Bit 1 MSTAT_CLEAR
* Bit 0 MSTAT_SNAP
*----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_MSTAT_WRITE 0x0004
#define SUNI1x10GEXP_BITMSK_MSTAT_CLEAR 0x0002
#define SUNI1x10GEXP_BITMSK_MSTAT_SNAP 0x0001
/*----------------------------------------------------------------------------
+ * Register 0x2109: MSTAT Counter Write Address
+ * Bit 5-0 MSTAT_WRITE_ADDRESS
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_MSTAT_WRITE_ADDRESS 0x003F
+#define SUNI1x10GEXP_BITOFF_MSTAT_WRITE_ADDRESS 0
+
+/*----------------------------------------------------------------------------
+ * Register 0x2200: IFLX Global Configuration Register
+ * Bit 15 IFLX_IRCU_ENABLE
+ * Bit 14 IFLX_IDSWT_ENABLE
+ * Bit 13-0 IFLX_IFD_CNT
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_IFLX_IRCU_ENABLE 0x8000
+#define SUNI1x10GEXP_BITMSK_IFLX_IDSWT_ENABLE 0x4000
+#define SUNI1x10GEXP_BITMSK_IFLX_IFD_CNT 0x3FFF
+#define SUNI1x10GEXP_BITOFF_IFLX_IFD_CNT 0
+
+/*----------------------------------------------------------------------------
+ * Register 0x2209: IFLX FIFO Overflow Enable
+ * Bit 0 IFLX_OVFE
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_IFLX_OVFE 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x220A: IFLX FIFO Overflow Interrupt
+ * Bit 0 IFLX_OVFI
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_IFLX_OVFI 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x220D: IFLX Indirect Channel Address
+ * Bit 15 IFLX_BUSY
+ * Bit 14 IFLX_RWB
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_IFLX_BUSY 0x8000
+#define SUNI1x10GEXP_BITMSK_IFLX_RWB 0x4000
+
+/*----------------------------------------------------------------------------
+ * Register 0x220E: IFLX Indirect Logical FIFO Low Limit & Provision
+ * Bit 9-0 IFLX_LOLIM
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_IFLX_LOLIM 0x03FF
+#define SUNI1x10GEXP_BITOFF_IFLX_LOLIM 0
+
+/*----------------------------------------------------------------------------
+ * Register 0x220F: IFLX Indirect Logical FIFO High Limit
+ * Bit 9-0 IFLX_HILIM
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_IFLX_HILIM 0x03FF
+#define SUNI1x10GEXP_BITOFF_IFLX_HILIM 0
+
+/*----------------------------------------------------------------------------
+ * Register 0x2210: IFLX Indirect Full/Almost Full Status & Limit
+ * Bit 15 IFLX_FULL
+ * Bit 14 IFLX_AFULL
+ * Bit 13-0 IFLX_AFTH
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_IFLX_FULL 0x8000
+#define SUNI1x10GEXP_BITMSK_IFLX_AFULL 0x4000
+#define SUNI1x10GEXP_BITMSK_IFLX_AFTH 0x3FFF
+#define SUNI1x10GEXP_BITOFF_IFLX_AFTH 0
+
+/*----------------------------------------------------------------------------
+ * Register 0x2211: IFLX Indirect Empty/Almost Empty Status & Limit
+ * Bit 15 IFLX_EMPTY
+ * Bit 14 IFLX_AEMPTY
+ * Bit 13-0 IFLX_AETH
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_IFLX_EMPTY 0x8000
+#define SUNI1x10GEXP_BITMSK_IFLX_AEMPTY 0x4000
+#define SUNI1x10GEXP_BITMSK_IFLX_AETH 0x3FFF
+#define SUNI1x10GEXP_BITOFF_IFLX_AETH 0
+
+/*----------------------------------------------------------------------------
+ * Register 0x2240: PL4MOS Configuration Register
+ * Bit 3 PL4MOS_RE_INIT
+ * Bit 2 PL4MOS_EN
+ * Bit 1 PL4MOS_NO_STATUS
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_PL4MOS_RE_INIT 0x0008
+#define SUNI1x10GEXP_BITMSK_PL4MOS_EN 0x0004
+#define SUNI1x10GEXP_BITMSK_PL4MOS_NO_STATUS 0x0002
+
+/*----------------------------------------------------------------------------
+ * Register 0x2243: PL4MOS MaxBurst1 Register
+ * Bit 11-0 PL4MOS_MAX_BURST1
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_PL4MOS_MAX_BURST1 0x0FFF
+#define SUNI1x10GEXP_BITOFF_PL4MOS_MAX_BURST1 0
+
+/*----------------------------------------------------------------------------
+ * Register 0x2244: PL4MOS MaxBurst2 Register
+ * Bit 11-0 PL4MOS_MAX_BURST2
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_PL4MOS_MAX_BURST2 0x0FFF
+#define SUNI1x10GEXP_BITOFF_PL4MOS_MAX_BURST2 0
+
+/*----------------------------------------------------------------------------
+ * Register 0x2245: PL4MOS Transfer Size Register
+ * Bit 7-0 PL4MOS_MAX_TRANSFER
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_PL4MOS_MAX_TRANSFER 0x00FF
+#define SUNI1x10GEXP_BITOFF_PL4MOS_MAX_TRANSFER 0
+
+/*----------------------------------------------------------------------------
+ * Register 0x2280: PL4ODP Configuration
+ * Bit 15-12 PL4ODP_REPEAT_T
+ * Bit 8 PL4ODP_SOP_RULE
+ * Bit 1 PL4ODP_EN_PORTS
+ * Bit 0 PL4ODP_EN_DFWD
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_PL4ODP_REPEAT_T 0xF000
+#define SUNI1x10GEXP_BITOFF_PL4ODP_REPEAT_T 12
+#define SUNI1x10GEXP_BITMSK_PL4ODP_SOP_RULE 0x0100
+#define SUNI1x10GEXP_BITMSK_PL4ODP_EN_PORTS 0x0002
+#define SUNI1x10GEXP_BITMSK_PL4ODP_EN_DFWD 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x2282: PL4ODP Interrupt Mask
+ * Bit 0 PL4ODP_OUT_DISE
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_PL4ODP_OUT_DISE 0x0001
+
+
+
+#define SUNI1x10GEXP_BITMSK_PL4ODP_PPE_EOPEOBE 0x0080
+#define SUNI1x10GEXP_BITMSK_PL4ODP_PPE_ERREOPE 0x0040
+#define SUNI1x10GEXP_BITMSK_PL4ODP_PPE_MEOPE 0x0008
+#define SUNI1x10GEXP_BITMSK_PL4ODP_PPE_MSOPE 0x0004
+#define SUNI1x10GEXP_BITMSK_PL4ODP_ES_OVRE 0x0002
+
+
+/*----------------------------------------------------------------------------
+ * Register 0x2283: PL4ODP Interrupt
+ * Bit 0 PL4ODP_OUT_DISI
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_PL4ODP_OUT_DISI 0x0001
+
+
+
+#define SUNI1x10GEXP_BITMSK_PL4ODP_PPE_EOPEOBI 0x0080
+#define SUNI1x10GEXP_BITMSK_PL4ODP_PPE_ERREOPI 0x0040
+#define SUNI1x10GEXP_BITMSK_PL4ODP_PPE_MEOPI 0x0008
+#define SUNI1x10GEXP_BITMSK_PL4ODP_PPE_MSOPI 0x0004
+#define SUNI1x10GEXP_BITMSK_PL4ODP_ES_OVRI 0x0002
+
+/*----------------------------------------------------------------------------
+ * Register 0x2300: PL4IO Lock Detect Status
+ * Bit 15 PL4IO_OUT_ROOLV
+ * Bit 12 PL4IO_IS_ROOLV
+ * Bit 11 PL4IO_DIP2_ERRV
+ * Bit 8 PL4IO_ID_ROOLV
+ * Bit 4 PL4IO_IS_DOOLV
+ * Bit 0 PL4IO_ID_DOOLV
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_PL4IO_OUT_ROOLV 0x8000
+#define SUNI1x10GEXP_BITMSK_PL4IO_IS_ROOLV 0x1000
+#define SUNI1x10GEXP_BITMSK_PL4IO_DIP2_ERRV 0x0800
+#define SUNI1x10GEXP_BITMSK_PL4IO_ID_ROOLV 0x0100
+#define SUNI1x10GEXP_BITMSK_PL4IO_IS_DOOLV 0x0010
+#define SUNI1x10GEXP_BITMSK_PL4IO_ID_DOOLV 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x2301: PL4IO Lock Detect Change
+ * Bit 15 PL4IO_OUT_ROOLI
+ * Bit 12 PL4IO_IS_ROOLI
+ * Bit 11 PL4IO_DIP2_ERRI
+ * Bit 8 PL4IO_ID_ROOLI
+ * Bit 4 PL4IO_IS_DOOLI
+ * Bit 0 PL4IO_ID_DOOLI
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_PL4IO_OUT_ROOLI 0x8000
+#define SUNI1x10GEXP_BITMSK_PL4IO_IS_ROOLI 0x1000
+#define SUNI1x10GEXP_BITMSK_PL4IO_DIP2_ERRI 0x0800
+#define SUNI1x10GEXP_BITMSK_PL4IO_ID_ROOLI 0x0100
+#define SUNI1x10GEXP_BITMSK_PL4IO_IS_DOOLI 0x0010
+#define SUNI1x10GEXP_BITMSK_PL4IO_ID_DOOLI 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x2302: PL4IO Lock Detect Mask
+ * Bit 15 PL4IO_OUT_ROOLE
+ * Bit 12 PL4IO_IS_ROOLE
+ * Bit 11 PL4IO_DIP2_ERRE
+ * Bit 8 PL4IO_ID_ROOLE
+ * Bit 4 PL4IO_IS_DOOLE
+ * Bit 0 PL4IO_ID_DOOLE
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_PL4IO_OUT_ROOLE 0x8000
+#define SUNI1x10GEXP_BITMSK_PL4IO_IS_ROOLE 0x1000
+#define SUNI1x10GEXP_BITMSK_PL4IO_DIP2_ERRE 0x0800
+#define SUNI1x10GEXP_BITMSK_PL4IO_ID_ROOLE 0x0100
+#define SUNI1x10GEXP_BITMSK_PL4IO_IS_DOOLE 0x0010
+#define SUNI1x10GEXP_BITMSK_PL4IO_ID_DOOLE 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x2303: PL4IO Lock Detect Limits
+ * Bit 15-8 PL4IO_REF_LIMIT
+ * Bit 7-0 PL4IO_TRAN_LIMIT
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_PL4IO_REF_LIMIT 0xFF00
+#define SUNI1x10GEXP_BITOFF_PL4IO_REF_LIMIT 8
+#define SUNI1x10GEXP_BITMSK_PL4IO_TRAN_LIMIT 0x00FF
+#define SUNI1x10GEXP_BITOFF_PL4IO_TRAN_LIMIT 0
+
+/*----------------------------------------------------------------------------
+ * Register 0x2304: PL4IO Calendar Repetitions
+ * Bit 15-8 PL4IO_IN_MUL
+ * Bit 7-0 PL4IO_OUT_MUL
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_PL4IO_IN_MUL 0xFF00
+#define SUNI1x10GEXP_BITOFF_PL4IO_IN_MUL 8
+#define SUNI1x10GEXP_BITMSK_PL4IO_OUT_MUL 0x00FF
+#define SUNI1x10GEXP_BITOFF_PL4IO_OUT_MUL 0
+
+/*----------------------------------------------------------------------------
+ * Register 0x2305: PL4IO Configuration
+ * Bit 15 PL4IO_DIP2_ERR_CHK
+ * Bit 11 PL4IO_ODAT_DIS
+ * Bit 10 PL4IO_TRAIN_DIS
+ * Bit 9 PL4IO_OSTAT_DIS
+ * Bit 8 PL4IO_ISTAT_DIS
+ * Bit 7 PL4IO_NO_ISTAT
+ * Bit 6 PL4IO_STAT_OUTSEL
+ * Bit 5 PL4IO_INSEL
+ * Bit 4 PL4IO_DLSEL
+ * Bit 1-0 PL4IO_OUTSEL
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_PL4IO_DIP2_ERR_CHK 0x8000
+#define SUNI1x10GEXP_BITMSK_PL4IO_ODAT_DIS 0x0800
+#define SUNI1x10GEXP_BITMSK_PL4IO_TRAIN_DIS 0x0400
+#define SUNI1x10GEXP_BITMSK_PL4IO_OSTAT_DIS 0x0200
+#define SUNI1x10GEXP_BITMSK_PL4IO_ISTAT_DIS 0x0100
+#define SUNI1x10GEXP_BITMSK_PL4IO_NO_ISTAT 0x0080
+#define SUNI1x10GEXP_BITMSK_PL4IO_STAT_OUTSEL 0x0040
+#define SUNI1x10GEXP_BITMSK_PL4IO_INSEL 0x0020
+#define SUNI1x10GEXP_BITMSK_PL4IO_DLSEL 0x0010
+#define SUNI1x10GEXP_BITMSK_PL4IO_OUTSEL 0x0003
+#define SUNI1x10GEXP_BITOFF_PL4IO_OUTSEL 0
+
+/*----------------------------------------------------------------------------
* Register 0x3040: TXXG Configuration Register 1
* Bit 15 TXXG_TXEN0
* Bit 13 TXXG_HOSTPAUSE
@@ -202,12 +1378,266 @@
* Bit 0 TXXG_SPRE
*----------------------------------------------------------------------------*/
#define SUNI1x10GEXP_BITMSK_TXXG_TXEN0 0x8000
+#define SUNI1x10GEXP_BITMSK_TXXG_HOSTPAUSE 0x2000
+#define SUNI1x10GEXP_BITMSK_TXXG_IPGT 0x1F80
#define SUNI1x10GEXP_BITOFF_TXXG_IPGT 7
#define SUNI1x10GEXP_BITMSK_TXXG_32BIT_ALIGN 0x0020
#define SUNI1x10GEXP_BITMSK_TXXG_CRCEN 0x0010
#define SUNI1x10GEXP_BITMSK_TXXG_FCTX 0x0008
#define SUNI1x10GEXP_BITMSK_TXXG_FCRX 0x0004
#define SUNI1x10GEXP_BITMSK_TXXG_PADEN 0x0002
+#define SUNI1x10GEXP_BITMSK_TXXG_SPRE 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x3041: TXXG Configuration Register 2
+ * Bit 7-0 TXXG_HDRSIZE
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_TXXG_HDRSIZE 0x00FF
+
+/*----------------------------------------------------------------------------
+ * Register 0x3042: TXXG Configuration Register 3
+ * Bit 15 TXXG_FIFO_ERRE
+ * Bit 14 TXXG_FIFO_UDRE
+ * Bit 13 TXXG_MAX_LERRE
+ * Bit 12 TXXG_MIN_LERRE
+ * Bit 11 TXXG_XFERE
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_TXXG_FIFO_ERRE 0x8000
+#define SUNI1x10GEXP_BITMSK_TXXG_FIFO_UDRE 0x4000
+#define SUNI1x10GEXP_BITMSK_TXXG_MAX_LERRE 0x2000
+#define SUNI1x10GEXP_BITMSK_TXXG_MIN_LERRE 0x1000
+#define SUNI1x10GEXP_BITMSK_TXXG_XFERE 0x0800
+
+/*----------------------------------------------------------------------------
+ * Register 0x3043: TXXG Interrupt
+ * Bit 15 TXXG_FIFO_ERRI
+ * Bit 14 TXXG_FIFO_UDRI
+ * Bit 13 TXXG_MAX_LERRI
+ * Bit 12 TXXG_MIN_LERRI
+ * Bit 11 TXXG_XFERI
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_TXXG_FIFO_ERRI 0x8000
+#define SUNI1x10GEXP_BITMSK_TXXG_FIFO_UDRI 0x4000
+#define SUNI1x10GEXP_BITMSK_TXXG_MAX_LERRI 0x2000
+#define SUNI1x10GEXP_BITMSK_TXXG_MIN_LERRI 0x1000
+#define SUNI1x10GEXP_BITMSK_TXXG_XFERI 0x0800
+
+/*----------------------------------------------------------------------------
+ * Register 0x3044: TXXG Status Register
+ * Bit 1 TXXG_TXACTIVE
+ * Bit 0 TXXG_PAUSED
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_TXXG_TXACTIVE 0x0002
+#define SUNI1x10GEXP_BITMSK_TXXG_PAUSED 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x3046: TXXG TX_MINFR - Transmit Min Frame Size Register
+ * Bit 7-0 TXXG_TX_MINFR
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_TXXG_TX_MINFR 0x00FF
+#define SUNI1x10GEXP_BITOFF_TXXG_TX_MINFR 0
+
+/*----------------------------------------------------------------------------
+ * Register 0x3052: TXXG Pause Quantum Value Configuration Register
+ * Bit 7-0 TXXG_FC_PAUSE_QNTM
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_TXXG_FC_PAUSE_QNTM 0x00FF
+#define SUNI1x10GEXP_BITOFF_TXXG_FC_PAUSE_QNTM 0
+
+/*----------------------------------------------------------------------------
+ * Register 0x3080: XTEF Control
+ * Bit 3-0 XTEF_FORCE_PARITY_ERR
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_XTEF_FORCE_PARITY_ERR 0x000F
+#define SUNI1x10GEXP_BITOFF_XTEF_FORCE_PARITY_ERR 0
+
+/*----------------------------------------------------------------------------
+ * Register 0x3084: XTEF Interrupt Event Register
+ * Bit 0 XTEF_LOST_SYNCI
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_XTEF_LOST_SYNCI 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x3085: XTEF Interrupt Enable Register
+ * Bit 0 XTEF_LOST_SYNCE
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_XTEF_LOST_SYNCE 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x3086: XTEF Visibility Register
+ * Bit 0 XTEF_LOST_SYNCV
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_XTEF_LOST_SYNCV 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x30C0: TXOAM OAM Configuration
+ * Bit 15 TXOAM_HEC_EN
+ * Bit 14 TXOAM_EMPTYCODE_EN
+ * Bit 13 TXOAM_FORCE_IDLE
+ * Bit 12 TXOAM_IGNORE_IDLE
+ * Bit 11-6 TXOAM_PX_OVERWRITE
+ * Bit 5-0 TXOAM_PX_SEL
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_TXOAM_HEC_EN 0x8000
+#define SUNI1x10GEXP_BITMSK_TXOAM_EMPTYCODE_EN 0x4000
+#define SUNI1x10GEXP_BITMSK_TXOAM_FORCE_IDLE 0x2000
+#define SUNI1x10GEXP_BITMSK_TXOAM_IGNORE_IDLE 0x1000
+#define SUNI1x10GEXP_BITMSK_TXOAM_PX_OVERWRITE 0x0FC0
+#define SUNI1x10GEXP_BITOFF_TXOAM_PX_OVERWRITE 6
+#define SUNI1x10GEXP_BITMSK_TXOAM_PX_SEL 0x003F
+#define SUNI1x10GEXP_BITOFF_TXOAM_PX_SEL 0
+
+/*----------------------------------------------------------------------------
+ * Register 0x30C1: TXOAM Mini-Packet Rate Configuration
+ * Bit 15 TXOAM_MINIDIS
+ * Bit 14 TXOAM_BUSY
+ * Bit 13 TXOAM_TRANS_EN
+ * Bit 10-0 TXOAM_MINIRATE
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_TXOAM_MINIDIS 0x8000
+#define SUNI1x10GEXP_BITMSK_TXOAM_BUSY 0x4000
+#define SUNI1x10GEXP_BITMSK_TXOAM_TRANS_EN 0x2000
+#define SUNI1x10GEXP_BITMSK_TXOAM_MINIRATE 0x07FF
+
+/*----------------------------------------------------------------------------
+ * Register 0x30C2: TXOAM Mini-Packet Gap and FIFO Configuration
+ * Bit 13-10 TXOAM_FTHRESH
+ * Bit 9-6 TXOAM_MINIPOST
+ * Bit 5-0 TXOAM_MINIPRE
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_TXOAM_FTHRESH 0x3C00
+#define SUNI1x10GEXP_BITOFF_TXOAM_FTHRESH 10
+#define SUNI1x10GEXP_BITMSK_TXOAM_MINIPOST 0x03C0
+#define SUNI1x10GEXP_BITOFF_TXOAM_MINIPOST 6
+#define SUNI1x10GEXP_BITMSK_TXOAM_MINIPRE 0x003F
+
+/*----------------------------------------------------------------------------
+ * Register 0x30C6: TXOAM Interrupt Enable
+ * Bit 2 TXOAM_SOP_ERRE
+ * Bit 1 TXOAM_OFLE
+ * Bit 0 TXOAM_ERRE
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_TXOAM_SOP_ERRE 0x0004
+#define SUNI1x10GEXP_BITMSK_TXOAM_OFLE 0x0002
+#define SUNI1x10GEXP_BITMSK_TXOAM_ERRE 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x30C7: TXOAM Interrupt Status
+ * Bit 2 TXOAM_SOP_ERRI
+ * Bit 1 TXOAM_OFLI
+ * Bit 0 TXOAM_ERRI
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_TXOAM_SOP_ERRI 0x0004
+#define SUNI1x10GEXP_BITMSK_TXOAM_OFLI 0x0002
+#define SUNI1x10GEXP_BITMSK_TXOAM_ERRI 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x30CF: TXOAM Coset
+ * Bit 7-0 TXOAM_COSET
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_TXOAM_COSET 0x00FF
+
+/*----------------------------------------------------------------------------
+ * Register 0x3200: EFLX Global Configuration
+ * Bit 15 EFLX_ERCU_EN
+ * Bit 7 EFLX_EN_EDSWT
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_EFLX_ERCU_EN 0x8000
+#define SUNI1x10GEXP_BITMSK_EFLX_EN_EDSWT 0x0080
+
+/*----------------------------------------------------------------------------
+ * Register 0x3201: EFLX ERCU Global Status
+ * Bit 13 EFLX_OVF_ERR
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_EFLX_OVF_ERR 0x2000
+
+/*----------------------------------------------------------------------------
+ * Register 0x3202: EFLX Indirect Channel Address
+ * Bit 15 EFLX_BUSY
+ * Bit 14 EFLX_RDWRB
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_EFLX_BUSY 0x8000
+#define SUNI1x10GEXP_BITMSK_EFLX_RDWRB 0x4000
+
+/*----------------------------------------------------------------------------
+ * Register 0x3203: EFLX Indirect Logical FIFO Low Limit
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_EFLX_LOLIM 0x03FF
+#define SUNI1x10GEXP_BITOFF_EFLX_LOLIM 0
+
+/*----------------------------------------------------------------------------
+ * Register 0x3204: EFLX Indirect Logical FIFO High Limit
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_EFLX_HILIM 0x03FF
+#define SUNI1x10GEXP_BITOFF_EFLX_HILIM 0
+
+/*----------------------------------------------------------------------------
+ * Register 0x3205: EFLX Indirect Full/Almost-Full Status and Limit
+ * Bit 15 EFLX_FULL
+ * Bit 14 EFLX_AFULL
+ * Bit 13-0 EFLX_AFTH
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_EFLX_FULL 0x8000
+#define SUNI1x10GEXP_BITMSK_EFLX_AFULL 0x4000
+#define SUNI1x10GEXP_BITMSK_EFLX_AFTH 0x3FFF
+#define SUNI1x10GEXP_BITOFF_EFLX_AFTH 0
+
+/*----------------------------------------------------------------------------
+ * Register 0x3206: EFLX Indirect Empty/Almost-Empty Status and Limit
+ * Bit 15 EFLX_EMPTY
+ * Bit 14 EFLX_AEMPTY
+ * Bit 13-0 EFLX_AETH
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_EFLX_EMPTY 0x8000
+#define SUNI1x10GEXP_BITMSK_EFLX_AEMPTY 0x4000
+#define SUNI1x10GEXP_BITMSK_EFLX_AETH 0x3FFF
+#define SUNI1x10GEXP_BITOFF_EFLX_AETH 0
+
+/*----------------------------------------------------------------------------
+ * Register 0x3207: EFLX Indirect FIFO Cut-Through Threshold
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_EFLX_CUT_THRU 0x3FFF
+#define SUNI1x10GEXP_BITOFF_EFLX_CUT_THRU 0
+
+/*----------------------------------------------------------------------------
+ * Register 0x320C: EFLX FIFO Overflow Error Enable
+ * Bit 0 EFLX_OVFE
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_EFLX_OVFE 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x320D: EFLX FIFO Overflow Error Indication
+ * Bit 0 EFLX_OVFI
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_EFLX_OVFI 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x3210: EFLX Channel Provision
+ * Bit 0 EFLX_PROV
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_EFLX_PROV 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x3280: PL4IDU Configuration
+ * Bit 2 PL4IDU_SYNCH_ON_TRAIN
+ * Bit 1 PL4IDU_EN_PORTS
+ * Bit 0 PL4IDU_EN_DFWD
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_PL4IDU_SYNCH_ON_TRAIN 0x0004
+#define SUNI1x10GEXP_BITMSK_PL4IDU_EN_PORTS 0x0002
+#define SUNI1x10GEXP_BITMSK_PL4IDU_EN_DFWD 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x3282: PL4IDU Interrupt Mask
+ * Bit 1 PL4IDU_DIP4E
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_PL4IDU_DIP4E 0x0002
+
+/*----------------------------------------------------------------------------
+ * Register 0x3283: PL4IDU Interrupt
+ * Bit 1 PL4IDU_DIP4I
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_PL4IDU_DIP4I 0x0002
#endif /* _CXGB_SUNI1x10GEXP_REGS_H_ */
diff --git a/drivers/net/chelsio/tp.c b/drivers/net/chelsio/tp.c
new file mode 100644
index 000000000000..0ca0b6e19e43
--- /dev/null
+++ b/drivers/net/chelsio/tp.c
@@ -0,0 +1,178 @@
+/* $Date: 2006/02/07 04:21:54 $ $RCSfile: tp.c,v $ $Revision: 1.73 $ */
+#include "common.h"
+#include "regs.h"
+#include "tp.h"
+#ifdef CONFIG_CHELSIO_T1_1G
+#include "fpga_defs.h"
+#endif
+
+struct petp {
+ adapter_t *adapter;
+};
+
+/* Pause deadlock avoidance parameters */
+#define DROP_MSEC 16
+#define DROP_PKTS_CNT 1
+
+static void tp_init(adapter_t * ap, const struct tp_params *p,
+ unsigned int tp_clk)
+{
+ if (t1_is_asic(ap)) {
+ u32 val;
+
+ val = F_TP_IN_CSPI_CPL | F_TP_IN_CSPI_CHECK_IP_CSUM |
+ F_TP_IN_CSPI_CHECK_TCP_CSUM | F_TP_IN_ESPI_ETHERNET;
+ if (!p->pm_size)
+ val |= F_OFFLOAD_DISABLE;
+ else
+ val |= F_TP_IN_ESPI_CHECK_IP_CSUM |
+ F_TP_IN_ESPI_CHECK_TCP_CSUM;
+ writel(val, ap->regs + A_TP_IN_CONFIG);
+ writel(F_TP_OUT_CSPI_CPL |
+ F_TP_OUT_ESPI_ETHERNET |
+ F_TP_OUT_ESPI_GENERATE_IP_CSUM |
+ F_TP_OUT_ESPI_GENERATE_TCP_CSUM,
+ ap->regs + A_TP_OUT_CONFIG);
+ writel(V_IP_TTL(64) |
+ F_PATH_MTU /* IP DF bit */ |
+ V_5TUPLE_LOOKUP(p->use_5tuple_mode) |
+ V_SYN_COOKIE_PARAMETER(29),
+ ap->regs + A_TP_GLOBAL_CONFIG);
+ /*
+ * Enable pause frame deadlock prevention.
+ */
+ if (is_T2(ap) && ap->params.nports > 1) {
+ u32 drop_ticks = DROP_MSEC * (tp_clk / 1000);
+
+ writel(F_ENABLE_TX_DROP | F_ENABLE_TX_ERROR |
+ V_DROP_TICKS_CNT(drop_ticks) |
+ V_NUM_PKTS_DROPPED(DROP_PKTS_CNT),
+ ap->regs + A_TP_TX_DROP_CONFIG);
+ }
+
+ }
+}
+
+void t1_tp_destroy(struct petp *tp)
+{
+ kfree(tp);
+}
+
+struct petp *__devinit t1_tp_create(adapter_t * adapter, struct tp_params *p)
+{
+ struct petp *tp = kzalloc(sizeof(*tp), GFP_KERNEL);
+ if (!tp)
+ return NULL;
+
+ tp->adapter = adapter;
+
+ return tp;
+}
+
+void t1_tp_intr_enable(struct petp *tp)
+{
+ u32 tp_intr = readl(tp->adapter->regs + A_PL_ENABLE);
+
+#ifdef CONFIG_CHELSIO_T1_1G
+ if (!t1_is_asic(tp->adapter)) {
+ /* FPGA */
+ writel(0xffffffff,
+ tp->adapter->regs + FPGA_TP_ADDR_INTERRUPT_ENABLE);
+ writel(tp_intr | FPGA_PCIX_INTERRUPT_TP,
+ tp->adapter->regs + A_PL_ENABLE);
+ } else
+#endif
+ {
+ /* We don't use any TP interrupts */
+ writel(0, tp->adapter->regs + A_TP_INT_ENABLE);
+ writel(tp_intr | F_PL_INTR_TP,
+ tp->adapter->regs + A_PL_ENABLE);
+ }
+}
+
+void t1_tp_intr_disable(struct petp *tp)
+{
+ u32 tp_intr = readl(tp->adapter->regs + A_PL_ENABLE);
+
+#ifdef CONFIG_CHELSIO_T1_1G
+ if (!t1_is_asic(tp->adapter)) {
+ /* FPGA */
+ writel(0, tp->adapter->regs + FPGA_TP_ADDR_INTERRUPT_ENABLE);
+ writel(tp_intr & ~FPGA_PCIX_INTERRUPT_TP,
+ tp->adapter->regs + A_PL_ENABLE);
+ } else
+#endif
+ {
+ writel(0, tp->adapter->regs + A_TP_INT_ENABLE);
+ writel(tp_intr & ~F_PL_INTR_TP,
+ tp->adapter->regs + A_PL_ENABLE);
+ }
+}
+
+void t1_tp_intr_clear(struct petp *tp)
+{
+#ifdef CONFIG_CHELSIO_T1_1G
+ if (!t1_is_asic(tp->adapter)) {
+ writel(0xffffffff,
+ tp->adapter->regs + FPGA_TP_ADDR_INTERRUPT_CAUSE);
+ writel(FPGA_PCIX_INTERRUPT_TP, tp->adapter->regs + A_PL_CAUSE);
+ return;
+ }
+#endif
+ writel(0xffffffff, tp->adapter->regs + A_TP_INT_CAUSE);
+ writel(F_PL_INTR_TP, tp->adapter->regs + A_PL_CAUSE);
+}
+
+int t1_tp_intr_handler(struct petp *tp)
+{
+ u32 cause;
+
+#ifdef CONFIG_CHELSIO_T1_1G
+ /* FPGA doesn't support TP interrupts. */
+ if (!t1_is_asic(tp->adapter))
+ return 1;
+#endif
+
+ cause = readl(tp->adapter->regs + A_TP_INT_CAUSE);
+ writel(cause, tp->adapter->regs + A_TP_INT_CAUSE);
+ return 0;
+}
+
+static void set_csum_offload(struct petp *tp, u32 csum_bit, int enable)
+{
+ u32 val = readl(tp->adapter->regs + A_TP_GLOBAL_CONFIG);
+
+ if (enable)
+ val |= csum_bit;
+ else
+ val &= ~csum_bit;
+ writel(val, tp->adapter->regs + A_TP_GLOBAL_CONFIG);
+}
+
+void t1_tp_set_ip_checksum_offload(struct petp *tp, int enable)
+{
+ set_csum_offload(tp, F_IP_CSUM, enable);
+}
+
+void t1_tp_set_udp_checksum_offload(struct petp *tp, int enable)
+{
+ set_csum_offload(tp, F_UDP_CSUM, enable);
+}
+
+void t1_tp_set_tcp_checksum_offload(struct petp *tp, int enable)
+{
+ set_csum_offload(tp, F_TCP_CSUM, enable);
+}
+
+/*
+ * Initialize TP state. tp_params contains initial settings for some TP
+ * parameters, particularly the one-time PM and CM settings.
+ */
+int t1_tp_reset(struct petp *tp, struct tp_params *p, unsigned int tp_clk)
+{
+ adapter_t *adapter = tp->adapter;
+
+ tp_init(adapter, p, tp_clk);
+ writel(F_TP_RESET, adapter->regs + A_TP_RESET);
+ return 0;
+}
diff --git a/drivers/net/chelsio/tp.h b/drivers/net/chelsio/tp.h
new file mode 100644
index 000000000000..32fc71e58913
--- /dev/null
+++ b/drivers/net/chelsio/tp.h
@@ -0,0 +1,73 @@
+/* $Date: 2005/03/07 23:59:05 $ $RCSfile: tp.h,v $ $Revision: 1.20 $ */
+#ifndef CHELSIO_TP_H
+#define CHELSIO_TP_H
+
+#include "common.h"
+
+#define TP_MAX_RX_COALESCING_SIZE 16224U
+
+struct tp_mib_statistics {
+
+ /* IP */
+ u32 ipInReceive_hi;
+ u32 ipInReceive_lo;
+ u32 ipInHdrErrors_hi;
+ u32 ipInHdrErrors_lo;
+ u32 ipInAddrErrors_hi;
+ u32 ipInAddrErrors_lo;
+ u32 ipInUnknownProtos_hi;
+ u32 ipInUnknownProtos_lo;
+ u32 ipInDiscards_hi;
+ u32 ipInDiscards_lo;
+ u32 ipInDelivers_hi;
+ u32 ipInDelivers_lo;
+ u32 ipOutRequests_hi;
+ u32 ipOutRequests_lo;
+ u32 ipOutDiscards_hi;
+ u32 ipOutDiscards_lo;
+ u32 ipOutNoRoutes_hi;
+ u32 ipOutNoRoutes_lo;
+ u32 ipReasmTimeout;
+ u32 ipReasmReqds;
+ u32 ipReasmOKs;
+ u32 ipReasmFails;
+
+ u32 reserved[8];
+
+ /* TCP */
+ u32 tcpActiveOpens;
+ u32 tcpPassiveOpens;
+ u32 tcpAttemptFails;
+ u32 tcpEstabResets;
+ u32 tcpOutRsts;
+ u32 tcpCurrEstab;
+ u32 tcpInSegs_hi;
+ u32 tcpInSegs_lo;
+ u32 tcpOutSegs_hi;
+ u32 tcpOutSegs_lo;
+ u32 tcpRetransSeg_hi;
+ u32 tcpRetransSeg_lo;
+ u32 tcpInErrs_hi;
+ u32 tcpInErrs_lo;
+ u32 tcpRtoMin;
+ u32 tcpRtoMax;
+};
+
+struct petp;
+struct tp_params;
+
+struct petp *t1_tp_create(adapter_t *adapter, struct tp_params *p);
+void t1_tp_destroy(struct petp *tp);
+
+void t1_tp_intr_disable(struct petp *tp);
+void t1_tp_intr_enable(struct petp *tp);
+void t1_tp_intr_clear(struct petp *tp);
+int t1_tp_intr_handler(struct petp *tp);
+
+void t1_tp_get_mib_statistics(adapter_t *adap, struct tp_mib_statistics *tps);
+void t1_tp_set_udp_checksum_offload(struct petp *tp, int enable);
+void t1_tp_set_tcp_checksum_offload(struct petp *tp, int enable);
+void t1_tp_set_ip_checksum_offload(struct petp *tp, int enable);
+int t1_tp_set_coalescing_size(struct petp *tp, unsigned int size);
+int t1_tp_reset(struct petp *tp, struct tp_params *p, unsigned int tp_clk);
+#endif
diff --git a/drivers/net/chelsio/vsc7326.c b/drivers/net/chelsio/vsc7326.c
new file mode 100644
index 000000000000..85dc3b1dc309
--- /dev/null
+++ b/drivers/net/chelsio/vsc7326.c
@@ -0,0 +1,725 @@
+/* $Date: 2006/04/28 19:20:06 $ $RCSfile: vsc7326.c,v $ $Revision: 1.19 $ */
+
+/* Driver for Vitesse VSC7326 (Schaumburg) MAC */
+
+#include "gmac.h"
+#include "elmer0.h"
+#include "vsc7326_reg.h"
+
+/* Update fast changing statistics every 15 seconds */
+#define STATS_TICK_SECS 15
+/* 30 minutes for full statistics update */
+#define MAJOR_UPDATE_TICKS (1800 / STATS_TICK_SECS)
+
+#define MAX_MTU 9600
+
+/* The egress WM value 0x01a01fff should be used only when the
+ * interface is down (MAC port disabled). This is a workaround
+ * for disabling the T2/MAC flow-control. When the interface is
+ * enabled, the WM value should be set to 0x014a03F0.
+ */
+#define WM_DISABLE 0x01a01fff
+#define WM_ENABLE 0x014a03F0
+
+struct init_table {
+ u32 addr;
+ u32 data;
+};
+
+struct _cmac_instance {
+ u32 index;
+ u32 ticks;
+};
+
+#define INITBLOCK_SLEEP 0xffffffff
+
+static void vsc_read(adapter_t *adapter, u32 addr, u32 *val)
+{
+ u32 status, vlo, vhi;
+ int i;
+
+ spin_lock_bh(&adapter->mac_lock);
+ t1_tpi_read(adapter, (addr << 2) + 4, &vlo);
+ i = 0;
+ do {
+ t1_tpi_read(adapter, (REG_LOCAL_STATUS << 2) + 4, &vlo);
+ t1_tpi_read(adapter, REG_LOCAL_STATUS << 2, &vhi);
+ status = (vhi << 16) | vlo;
+ i++;
+ } while (((status & 1) == 0) && (i < 50));
+ if (i == 50)
+ CH_ERR("Invalid tpi read from MAC, breaking loop.\n");
+
+ t1_tpi_read(adapter, (REG_LOCAL_DATA << 2) + 4, &vlo);
+ t1_tpi_read(adapter, REG_LOCAL_DATA << 2, &vhi);
+
+ *val = (vhi << 16) | vlo;
+
+ /* CH_ERR("rd: block: 0x%x sublock: 0x%x reg: 0x%x data: 0x%x\n",
+ ((addr&0xe000)>>13), ((addr&0x1e00)>>9),
+ ((addr&0x01fe)>>1), *val); */
+ spin_unlock_bh(&adapter->mac_lock);
+}
+
+static void vsc_write(adapter_t *adapter, u32 addr, u32 data)
+{
+ spin_lock_bh(&adapter->mac_lock);
+ t1_tpi_write(adapter, (addr << 2) + 4, data & 0xFFFF);
+ t1_tpi_write(adapter, addr << 2, (data >> 16) & 0xFFFF);
+ /* CH_ERR("wr: block: 0x%x sublock: 0x%x reg: 0x%x data: 0x%x\n",
+ ((addr&0xe000)>>13), ((addr&0x1e00)>>9),
+ ((addr&0x01fe)>>1), data); */
+ spin_unlock_bh(&adapter->mac_lock);
+}
+
+/* Hard reset the MAC. This wipes out *all* configuration. */
+static void vsc7326_full_reset(adapter_t* adapter)
+{
+ u32 val;
+ u32 result = 0xffff;
+
+ t1_tpi_read(adapter, A_ELMER0_GPO, &val);
+ val &= ~1;
+ t1_tpi_write(adapter, A_ELMER0_GPO, val);
+ udelay(2);
+ val |= 0x1; /* Enable mac MAC itself */
+ val |= 0x800; /* Turn off the red LED */
+ t1_tpi_write(adapter, A_ELMER0_GPO, val);
+ mdelay(1);
+ vsc_write(adapter, REG_SW_RESET, 0x80000001);
+ do {
+ mdelay(1);
+ vsc_read(adapter, REG_SW_RESET, &result);
+ } while (result != 0x0);
+}
+
+static struct init_table vsc7326_reset[] = {
+ { REG_IFACE_MODE, 0x00000000 },
+ { REG_CRC_CFG, 0x00000020 },
+ { REG_PLL_CLK_SPEED, 0x00050c00 },
+ { REG_PLL_CLK_SPEED, 0x00050c00 },
+ { REG_MSCH, 0x00002f14 },
+ { REG_SPI4_MISC, 0x00040409 },
+ { REG_SPI4_DESKEW, 0x00080000 },
+ { REG_SPI4_ING_SETUP2, 0x08080004 },
+ { REG_SPI4_ING_SETUP0, 0x04111004 },
+ { REG_SPI4_EGR_SETUP0, 0x80001a04 },
+ { REG_SPI4_ING_SETUP1, 0x02010000 },
+ { REG_AGE_INC(0), 0x00000000 },
+ { REG_AGE_INC(1), 0x00000000 },
+ { REG_ING_CONTROL, 0x0a200011 },
+ { REG_EGR_CONTROL, 0xa0010091 },
+};
+
+static struct init_table vsc7326_portinit[4][22] = {
+ { /* Port 0 */
+ /* FIFO setup */
+ { REG_DBG(0), 0x000004f0 },
+ { REG_HDX(0), 0x00073101 },
+ { REG_TEST(0,0), 0x00000022 },
+ { REG_TEST(1,0), 0x00000022 },
+ { REG_TOP_BOTTOM(0,0), 0x003f0000 },
+ { REG_TOP_BOTTOM(1,0), 0x00120000 },
+ { REG_HIGH_LOW_WM(0,0), 0x07460757 },
+ { REG_HIGH_LOW_WM(1,0), WM_DISABLE },
+ { REG_CT_THRHLD(0,0), 0x00000000 },
+ { REG_CT_THRHLD(1,0), 0x00000000 },
+ { REG_BUCKE(0), 0x0002ffff },
+ { REG_BUCKI(0), 0x0002ffff },
+ { REG_TEST(0,0), 0x00000020 },
+ { REG_TEST(1,0), 0x00000020 },
+ /* Port config */
+ { REG_MAX_LEN(0), 0x00002710 },
+ { REG_PORT_FAIL(0), 0x00000002 },
+ { REG_NORMALIZER(0), 0x00000a64 },
+ { REG_DENORM(0), 0x00000010 },
+ { REG_STICK_BIT(0), 0x03baa370 },
+ { REG_DEV_SETUP(0), 0x00000083 },
+ { REG_DEV_SETUP(0), 0x00000082 },
+ { REG_MODE_CFG(0), 0x0200259f },
+ },
+ { /* Port 1 */
+ /* FIFO setup */
+ { REG_DBG(1), 0x000004f0 },
+ { REG_HDX(1), 0x00073101 },
+ { REG_TEST(0,1), 0x00000022 },
+ { REG_TEST(1,1), 0x00000022 },
+ { REG_TOP_BOTTOM(0,1), 0x007e003f },
+ { REG_TOP_BOTTOM(1,1), 0x00240012 },
+ { REG_HIGH_LOW_WM(0,1), 0x07460757 },
+ { REG_HIGH_LOW_WM(1,1), WM_DISABLE },
+ { REG_CT_THRHLD(0,1), 0x00000000 },
+ { REG_CT_THRHLD(1,1), 0x00000000 },
+ { REG_BUCKE(1), 0x0002ffff },
+ { REG_BUCKI(1), 0x0002ffff },
+ { REG_TEST(0,1), 0x00000020 },
+ { REG_TEST(1,1), 0x00000020 },
+ /* Port config */
+ { REG_MAX_LEN(1), 0x00002710 },
+ { REG_PORT_FAIL(1), 0x00000002 },
+ { REG_NORMALIZER(1), 0x00000a64 },
+ { REG_DENORM(1), 0x00000010 },
+ { REG_STICK_BIT(1), 0x03baa370 },
+ { REG_DEV_SETUP(1), 0x00000083 },
+ { REG_DEV_SETUP(1), 0x00000082 },
+ { REG_MODE_CFG(1), 0x0200259f },
+ },
+ { /* Port 2 */
+ /* FIFO setup */
+ { REG_DBG(2), 0x000004f0 },
+ { REG_HDX(2), 0x00073101 },
+ { REG_TEST(0,2), 0x00000022 },
+ { REG_TEST(1,2), 0x00000022 },
+ { REG_TOP_BOTTOM(0,2), 0x00bd007e },
+ { REG_TOP_BOTTOM(1,2), 0x00360024 },
+ { REG_HIGH_LOW_WM(0,2), 0x07460757 },
+ { REG_HIGH_LOW_WM(1,2), WM_DISABLE },
+ { REG_CT_THRHLD(0,2), 0x00000000 },
+ { REG_CT_THRHLD(1,2), 0x00000000 },
+ { REG_BUCKE(2), 0x0002ffff },
+ { REG_BUCKI(2), 0x0002ffff },
+ { REG_TEST(0,2), 0x00000020 },
+ { REG_TEST(1,2), 0x00000020 },
+ /* Port config */
+ { REG_MAX_LEN(2), 0x00002710 },
+ { REG_PORT_FAIL(2), 0x00000002 },
+ { REG_NORMALIZER(2), 0x00000a64 },
+ { REG_DENORM(2), 0x00000010 },
+ { REG_STICK_BIT(2), 0x03baa370 },
+ { REG_DEV_SETUP(2), 0x00000083 },
+ { REG_DEV_SETUP(2), 0x00000082 },
+ { REG_MODE_CFG(2), 0x0200259f },
+ },
+ { /* Port 3 */
+ /* FIFO setup */
+ { REG_DBG(3), 0x000004f0 },
+ { REG_HDX(3), 0x00073101 },
+ { REG_TEST(0,3), 0x00000022 },
+ { REG_TEST(1,3), 0x00000022 },
+ { REG_TOP_BOTTOM(0,3), 0x00fc00bd },
+ { REG_TOP_BOTTOM(1,3), 0x00480036 },
+ { REG_HIGH_LOW_WM(0,3), 0x07460757 },
+ { REG_HIGH_LOW_WM(1,3), WM_DISABLE },
+ { REG_CT_THRHLD(0,3), 0x00000000 },
+ { REG_CT_THRHLD(1,3), 0x00000000 },
+ { REG_BUCKE(3), 0x0002ffff },
+ { REG_BUCKI(3), 0x0002ffff },
+ { REG_TEST(0,3), 0x00000020 },
+ { REG_TEST(1,3), 0x00000020 },
+ /* Port config */
+ { REG_MAX_LEN(3), 0x00002710 },
+ { REG_PORT_FAIL(3), 0x00000002 },
+ { REG_NORMALIZER(3), 0x00000a64 },
+ { REG_DENORM(3), 0x00000010 },
+ { REG_STICK_BIT(3), 0x03baa370 },
+ { REG_DEV_SETUP(3), 0x00000083 },
+ { REG_DEV_SETUP(3), 0x00000082 },
+ { REG_MODE_CFG(3), 0x0200259f },
+ },
+};
+
+static void run_table(adapter_t *adapter, struct init_table *ib, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ if (ib[i].addr == INITBLOCK_SLEEP) {
+ udelay( ib[i].data );
+ CH_ERR("sleep %d us\n",ib[i].data);
+ } else {
+ vsc_write( adapter, ib[i].addr, ib[i].data );
+ }
+ }
+}
+
+static int bist_rd(adapter_t *adapter, int moduleid, int address)
+{
+ int data=0;
+ u32 result=0;
+
+ if( (address != 0x0) &&
+ (address != 0x1) &&
+ (address != 0x2) &&
+ (address != 0xd) &&
+ (address != 0xe))
+ CH_ERR("No bist address: 0x%x\n", address);
+
+ data = ((0x00 << 24) | ((address & 0xff) << 16) | (0x00 << 8) |
+ ((moduleid & 0xff) << 0));
+ vsc_write(adapter, REG_RAM_BIST_CMD, data);
+
+ udelay(10);
+
+ vsc_read(adapter, REG_RAM_BIST_RESULT, &result);
+ if((result & (1<<9)) != 0x0)
+ CH_ERR("Still in bist read: 0x%x\n", result);
+ else if((result & (1<<8)) != 0x0)
+ CH_ERR("bist read error: 0x%x\n", result);
+
+ return(result & 0xff);
+}
+
+static int bist_wr(adapter_t *adapter, int moduleid, int address, int value)
+{
+ int data=0;
+ u32 result=0;
+
+ if( (address != 0x0) &&
+ (address != 0x1) &&
+ (address != 0x2) &&
+ (address != 0xd) &&
+ (address != 0xe))
+ CH_ERR("No bist address: 0x%x\n", address);
+
+ if( value>255 )
+ CH_ERR("Suspicious write out of range value: 0x%x\n", value);
+
+ data = ((0x01 << 24) | ((address & 0xff) << 16) | (value << 8) |
+ ((moduleid & 0xff) << 0));
+ vsc_write(adapter, REG_RAM_BIST_CMD, data);
+
+ udelay(5);
+
+ vsc_read(adapter, REG_RAM_BIST_CMD, &result);
+ if((result & (1<<27)) != 0x0)
+ CH_ERR("Still in bist write: 0x%x\n", result);
+ else if((result & (1<<26)) != 0x0)
+ CH_ERR("bist write error: 0x%x\n", result);
+
+ return(0);
+}
+
+static int run_bist(adapter_t *adapter, int moduleid)
+{
+ /*run bist*/
+ (void) bist_wr(adapter,moduleid, 0x00, 0x02);
+ (void) bist_wr(adapter,moduleid, 0x01, 0x01);
+
+ return(0);
+}
+
+static int check_bist(adapter_t *adapter, int moduleid)
+{
+ int result=0;
+ int column=0;
+ /*check bist*/
+ result = bist_rd(adapter,moduleid, 0x02);
+ column = ((bist_rd(adapter,moduleid, 0x0e)<<8) +
+ (bist_rd(adapter,moduleid, 0x0d)));
+ if ((result & 3) != 0x3)
+ CH_ERR("Result: 0x%x BIST error in ram %d, column: 0x%04x\n",
+ result, moduleid, column);
+ return(0);
+}
+
+static int enable_mem(adapter_t *adapter, int moduleid)
+{
+ /*enable mem*/
+ (void) bist_wr(adapter,moduleid, 0x00, 0x00);
+ return(0);
+}
+
+static int run_bist_all(adapter_t *adapter)
+{
+ int port=0;
+ u32 val=0;
+
+ vsc_write(adapter, REG_MEM_BIST, 0x5);
+ vsc_read(adapter, REG_MEM_BIST, &val);
+
+ for(port=0; port<12; port++){
+ vsc_write(adapter, REG_DEV_SETUP(port), 0x0);
+ }
+
+ udelay(300);
+ vsc_write(adapter, REG_SPI4_MISC, 0x00040409);
+ udelay(300);
+
+ (void) run_bist(adapter,13);
+ (void) run_bist(adapter,14);
+ (void) run_bist(adapter,20);
+ (void) run_bist(adapter,21);
+ mdelay(200);
+ (void) check_bist(adapter,13);
+ (void) check_bist(adapter,14);
+ (void) check_bist(adapter,20);
+ (void) check_bist(adapter,21);
+ udelay(100);
+ (void) enable_mem(adapter,13);
+ (void) enable_mem(adapter,14);
+ (void) enable_mem(adapter,20);
+ (void) enable_mem(adapter,21);
+ udelay(300);
+ vsc_write(adapter, REG_SPI4_MISC, 0x60040400);
+ udelay(300);
+ for(port=0; port<12; port++){
+ vsc_write(adapter, REG_DEV_SETUP(port), 0x1);
+ }
+ udelay(300);
+ vsc_write(adapter, REG_MEM_BIST, 0x0);
+ mdelay(10);
+ return(0);
+}
+
+static int mac_intr_handler(struct cmac *mac)
+{
+ return 0;
+}
+
+static int mac_intr_enable(struct cmac *mac)
+{
+ return 0;
+}
+
+static int mac_intr_disable(struct cmac *mac)
+{
+ return 0;
+}
+
+static int mac_intr_clear(struct cmac *mac)
+{
+ return 0;
+}
+
+/* Expect MAC address to be in network byte order. */
+static int mac_set_address(struct cmac* mac, u8 addr[6])
+{
+ u32 val;
+ int port = mac->instance->index;
+
+ vsc_write(mac->adapter, REG_MAC_LOW_ADDR(port),
+ (addr[3] << 16) | (addr[4] << 8) | addr[5]);
+ vsc_write(mac->adapter, REG_MAC_HIGH_ADDR(port),
+ (addr[0] << 16) | (addr[1] << 8) | addr[2]);
+
+ vsc_read(mac->adapter, REG_ING_FFILT_UM_EN, &val);
+ val &= ~0xf0000000;
+ vsc_write(mac->adapter, REG_ING_FFILT_UM_EN, val | (port << 28));
+
+ vsc_write(mac->adapter, REG_ING_FFILT_MASK0,
+ 0xffff0000 | (addr[4] << 8) | addr[5]);
+ vsc_write(mac->adapter, REG_ING_FFILT_MASK1,
+ 0xffff0000 | (addr[2] << 8) | addr[3]);
+ vsc_write(mac->adapter, REG_ING_FFILT_MASK2,
+ 0xffff0000 | (addr[0] << 8) | addr[1]);
+ return 0;
+}
+
+static int mac_get_address(struct cmac *mac, u8 addr[6])
+{
+ u32 addr_lo, addr_hi;
+ int port = mac->instance->index;
+
+ vsc_read(mac->adapter, REG_MAC_LOW_ADDR(port), &addr_lo);
+ vsc_read(mac->adapter, REG_MAC_HIGH_ADDR(port), &addr_hi);
+
+ addr[0] = (u8) (addr_hi >> 16);
+ addr[1] = (u8) (addr_hi >> 8);
+ addr[2] = (u8) addr_hi;
+ addr[3] = (u8) (addr_lo >> 16);
+ addr[4] = (u8) (addr_lo >> 8);
+ addr[5] = (u8) addr_lo;
+ return 0;
+}
+
+/* This is intended to reset a port, not the whole MAC */
+static int mac_reset(struct cmac *mac)
+{
+ int index = mac->instance->index;
+
+ run_table(mac->adapter, vsc7326_portinit[index],
+ ARRAY_SIZE(vsc7326_portinit[index]));
+
+ return 0;
+}
+
+static int mac_set_rx_mode(struct cmac *mac, struct t1_rx_mode *rm)
+{
+ u32 v;
+ int port = mac->instance->index;
+
+ vsc_read(mac->adapter, REG_ING_FFILT_UM_EN, &v);
+ v |= 1 << 12;
+
+ if (t1_rx_mode_promisc(rm))
+ v &= ~(1 << (port + 16));
+ else
+ v |= 1 << (port + 16);
+
+ vsc_write(mac->adapter, REG_ING_FFILT_UM_EN, v);
+ return 0;
+}
+
+static int mac_set_mtu(struct cmac *mac, int mtu)
+{
+ int port = mac->instance->index;
+
+ if (mtu > MAX_MTU)
+ return -EINVAL;
+
+ /* max_len includes header and FCS */
+ vsc_write(mac->adapter, REG_MAX_LEN(port), mtu + 14 + 4);
+ return 0;
+}
+
+static int mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex,
+ int fc)
+{
+ u32 v;
+ int enable, port = mac->instance->index;
+
+ if (speed >= 0 && speed != SPEED_10 && speed != SPEED_100 &&
+ speed != SPEED_1000)
+ return -1;
+ if (duplex > 0 && duplex != DUPLEX_FULL)
+ return -1;
+
+ if (speed >= 0) {
+ vsc_read(mac->adapter, REG_MODE_CFG(port), &v);
+ enable = v & 3; /* save tx/rx enables */
+ v &= ~0xf;
+ v |= 4; /* full duplex */
+ if (speed == SPEED_1000)
+ v |= 8; /* GigE */
+ enable |= v;
+ vsc_write(mac->adapter, REG_MODE_CFG(port), v);
+
+ if (speed == SPEED_1000)
+ v = 0x82;
+ else if (speed == SPEED_100)
+ v = 0x84;
+ else /* SPEED_10 */
+ v = 0x86;
+ vsc_write(mac->adapter, REG_DEV_SETUP(port), v | 1); /* reset */
+ vsc_write(mac->adapter, REG_DEV_SETUP(port), v);
+ vsc_read(mac->adapter, REG_DBG(port), &v);
+ v &= ~0xff00;
+ if (speed == SPEED_1000)
+ v |= 0x400;
+ else if (speed == SPEED_100)
+ v |= 0x2000;
+ else /* SPEED_10 */
+ v |= 0xff00;
+ vsc_write(mac->adapter, REG_DBG(port), v);
+
+ vsc_write(mac->adapter, REG_TX_IFG(port),
+ speed == SPEED_1000 ? 5 : 0x11);
+ if (duplex == DUPLEX_HALF)
+ enable = 0x0; /* 100 or 10 */
+ else if (speed == SPEED_1000)
+ enable = 0xc;
+ else /* SPEED_100 or 10 */
+ enable = 0x4;
+ enable |= 0x9 << 10; /* IFG1 */
+ enable |= 0x6 << 6; /* IFG2 */
+ enable |= 0x1 << 4; /* VLAN */
+ enable |= 0x3; /* RX/TX EN */
+ vsc_write(mac->adapter, REG_MODE_CFG(port), enable);
+
+ }
+
+ vsc_read(mac->adapter, REG_PAUSE_CFG(port), &v);
+ v &= 0xfff0ffff;
+ v |= 0x20000; /* xon/xoff */
+ if (fc & PAUSE_RX)
+ v |= 0x40000;
+ if (fc & PAUSE_TX)
+ v |= 0x80000;
+ if (fc == (PAUSE_RX | PAUSE_TX))
+ v |= 0x10000;
+ vsc_write(mac->adapter, REG_PAUSE_CFG(port), v);
+ return 0;
+}
+
+static int mac_enable(struct cmac *mac, int which)
+{
+ u32 val;
+ int port = mac->instance->index;
+
+ /* Write the correct WM value when the port is enabled. */
+ vsc_write(mac->adapter, REG_HIGH_LOW_WM(1,port), WM_ENABLE);
+
+ vsc_read(mac->adapter, REG_MODE_CFG(port), &val);
+ if (which & MAC_DIRECTION_RX)
+ val |= 0x2;
+ if (which & MAC_DIRECTION_TX)
+ val |= 1;
+ vsc_write(mac->adapter, REG_MODE_CFG(port), val);
+ return 0;
+}
+
+static int mac_disable(struct cmac *mac, int which)
+{
+ u32 val;
+ int i, port = mac->instance->index;
+
+ /* Reset the port, this also writes the correct WM value */
+ mac_reset(mac);
+
+ vsc_read(mac->adapter, REG_MODE_CFG(port), &val);
+ if (which & MAC_DIRECTION_RX)
+ val &= ~0x2;
+ if (which & MAC_DIRECTION_TX)
+ val &= ~0x1;
+ vsc_write(mac->adapter, REG_MODE_CFG(port), val);
+ vsc_read(mac->adapter, REG_MODE_CFG(port), &val);
+
+ /* Clear stats */
+ for (i = 0; i <= 0x3a; ++i)
+ vsc_write(mac->adapter, CRA(4, port, i), 0);
+
+ /* Clear sofware counters */
+ memset(&mac->stats, 0, sizeof(struct cmac_statistics));
+
+ return 0;
+}
+
+static void rmon_update(struct cmac *mac, unsigned int addr, u64 *stat)
+{
+ u32 v, lo;
+
+ vsc_read(mac->adapter, addr, &v);
+ lo = *stat;
+ *stat = *stat - lo + v;
+
+ if (v == 0)
+ return;
+
+ if (v < lo)
+ *stat += (1ULL << 32);
+}
+
+static void port_stats_update(struct cmac *mac)
+{
+ int port = mac->instance->index;
+
+ /* Rx stats */
+ rmon_update(mac, REG_RX_OK_BYTES(port), &mac->stats.RxOctetsOK);
+ rmon_update(mac, REG_RX_BAD_BYTES(port), &mac->stats.RxOctetsBad);
+ rmon_update(mac, REG_RX_UNICAST(port), &mac->stats.RxUnicastFramesOK);
+ rmon_update(mac, REG_RX_MULTICAST(port),
+ &mac->stats.RxMulticastFramesOK);
+ rmon_update(mac, REG_RX_BROADCAST(port),
+ &mac->stats.RxBroadcastFramesOK);
+ rmon_update(mac, REG_CRC(port), &mac->stats.RxFCSErrors);
+ rmon_update(mac, REG_RX_ALIGNMENT(port), &mac->stats.RxAlignErrors);
+ rmon_update(mac, REG_RX_OVERSIZE(port),
+ &mac->stats.RxFrameTooLongErrors);
+ rmon_update(mac, REG_RX_PAUSE(port), &mac->stats.RxPauseFrames);
+ rmon_update(mac, REG_RX_JABBERS(port), &mac->stats.RxJabberErrors);
+ rmon_update(mac, REG_RX_FRAGMENTS(port), &mac->stats.RxRuntErrors);
+ rmon_update(mac, REG_RX_UNDERSIZE(port), &mac->stats.RxRuntErrors);
+ rmon_update(mac, REG_RX_SYMBOL_CARRIER(port),
+ &mac->stats.RxSymbolErrors);
+ rmon_update(mac, REG_RX_SIZE_1519_TO_MAX(port),
+ &mac->stats.RxJumboFramesOK);
+
+ /* Tx stats (skip collision stats as we are full-duplex only) */
+ rmon_update(mac, REG_TX_OK_BYTES(port), &mac->stats.TxOctetsOK);
+ rmon_update(mac, REG_TX_UNICAST(port), &mac->stats.TxUnicastFramesOK);
+ rmon_update(mac, REG_TX_MULTICAST(port),
+ &mac->stats.TxMulticastFramesOK);
+ rmon_update(mac, REG_TX_BROADCAST(port),
+ &mac->stats.TxBroadcastFramesOK);
+ rmon_update(mac, REG_TX_PAUSE(port), &mac->stats.TxPauseFrames);
+ rmon_update(mac, REG_TX_UNDERRUN(port), &mac->stats.TxUnderrun);
+ rmon_update(mac, REG_TX_SIZE_1519_TO_MAX(port),
+ &mac->stats.TxJumboFramesOK);
+}
+
+/*
+ * This function is called periodically to accumulate the current values of the
+ * RMON counters into the port statistics. Since the counters are only 32 bits
+ * some of them can overflow in less than a minute at GigE speeds, so this
+ * function should be called every 30 seconds or so.
+ *
+ * To cut down on reading costs we update only the octet counters at each tick
+ * and do a full update at major ticks, which can be every 30 minutes or more.
+ */
+static const struct cmac_statistics *mac_update_statistics(struct cmac *mac,
+ int flag)
+{
+ if (flag == MAC_STATS_UPDATE_FULL ||
+ mac->instance->ticks >= MAJOR_UPDATE_TICKS) {
+ port_stats_update(mac);
+ mac->instance->ticks = 0;
+ } else {
+ int port = mac->instance->index;
+
+ rmon_update(mac, REG_RX_OK_BYTES(port),
+ &mac->stats.RxOctetsOK);
+ rmon_update(mac, REG_RX_BAD_BYTES(port),
+ &mac->stats.RxOctetsBad);
+ rmon_update(mac, REG_TX_OK_BYTES(port),
+ &mac->stats.TxOctetsOK);
+ mac->instance->ticks++;
+ }
+ return &mac->stats;
+}
+
+static void mac_destroy(struct cmac *mac)
+{
+ kfree(mac);
+}
+
+static struct cmac_ops vsc7326_ops = {
+ .destroy = mac_destroy,
+ .reset = mac_reset,
+ .interrupt_handler = mac_intr_handler,
+ .interrupt_enable = mac_intr_enable,
+ .interrupt_disable = mac_intr_disable,
+ .interrupt_clear = mac_intr_clear,
+ .enable = mac_enable,
+ .disable = mac_disable,
+ .set_mtu = mac_set_mtu,
+ .set_rx_mode = mac_set_rx_mode,
+ .set_speed_duplex_fc = mac_set_speed_duplex_fc,
+ .statistics_update = mac_update_statistics,
+ .macaddress_get = mac_get_address,
+ .macaddress_set = mac_set_address,
+};
+
+static struct cmac *vsc7326_mac_create(adapter_t *adapter, int index)
+{
+ struct cmac *mac;
+ u32 val;
+ int i;
+
+ mac = kzalloc(sizeof(*mac) + sizeof(cmac_instance), GFP_KERNEL);
+ if (!mac) return NULL;
+
+ mac->ops = &vsc7326_ops;
+ mac->instance = (cmac_instance *)(mac + 1);
+ mac->adapter = adapter;
+
+ mac->instance->index = index;
+ mac->instance->ticks = 0;
+
+ i = 0;
+ do {
+ u32 vhi, vlo;
+
+ vhi = vlo = 0;
+ t1_tpi_read(adapter, (REG_LOCAL_STATUS << 2) + 4, &vlo);
+ udelay(1);
+ t1_tpi_read(adapter, REG_LOCAL_STATUS << 2, &vhi);
+ udelay(5);
+ val = (vhi << 16) | vlo;
+ } while ((++i < 10000) && (val == 0xffffffff));
+
+ return mac;
+}
+
+static int vsc7326_mac_reset(adapter_t *adapter)
+{
+ vsc7326_full_reset(adapter);
+ (void) run_bist_all(adapter);
+ run_table(adapter, vsc7326_reset, ARRAY_SIZE(vsc7326_reset));
+ return 0;
+}
+
+struct gmac t1_vsc7326_ops = {
+ .stats_update_period = STATS_TICK_SECS,
+ .create = vsc7326_mac_create,
+ .reset = vsc7326_mac_reset,
+};
diff --git a/drivers/net/chelsio/vsc7326_reg.h b/drivers/net/chelsio/vsc7326_reg.h
new file mode 100644
index 000000000000..491bcf75c4fb
--- /dev/null
+++ b/drivers/net/chelsio/vsc7326_reg.h
@@ -0,0 +1,286 @@
+/* $Date: 2006/04/28 19:20:17 $ $RCSfile: vsc7326_reg.h,v $ $Revision: 1.5 $ */
+#ifndef _VSC7321_REG_H_
+#define _VSC7321_REG_H_
+
+/* Register definitions for Vitesse VSC7321 (Meigs II) MAC
+ *
+ * Straight off the data sheet, VMDS-10038 Rev 2.0 and
+ * PD0011-01-14-Meigs-II 2002-12-12
+ */
+
+/* Just 'cause it's in here doesn't mean it's used. */
+
+#define CRA(blk,sub,adr) ((((blk) & 0x7) << 13) | (((sub) & 0xf) << 9) | (((adr) & 0xff) << 1))
+
+/* System and CPU comm's registers */
+#define REG_CHIP_ID CRA(0x7,0xf,0x00) /* Chip ID */
+#define REG_BLADE_ID CRA(0x7,0xf,0x01) /* Blade ID */
+#define REG_SW_RESET CRA(0x7,0xf,0x02) /* Global Soft Reset */
+#define REG_MEM_BIST CRA(0x7,0xf,0x04) /* mem */
+#define REG_IFACE_MODE CRA(0x7,0xf,0x07) /* Interface mode */
+#define REG_MSCH CRA(0x7,0x2,0x06) /* CRC error count */
+#define REG_CRC_CNT CRA(0x7,0x2,0x0a) /* CRC error count */
+#define REG_CRC_CFG CRA(0x7,0x2,0x0b) /* CRC config */
+#define REG_SI_TRANSFER_SEL CRA(0x7,0xf,0x18) /* SI Transfer Select */
+#define REG_PLL_CLK_SPEED CRA(0x7,0xf,0x19) /* Clock Speed Selection */
+#define REG_SYS_CLK_SELECT CRA(0x7,0xf,0x1c) /* System Clock Select */
+#define REG_GPIO_CTRL CRA(0x7,0xf,0x1d) /* GPIO Control */
+#define REG_GPIO_OUT CRA(0x7,0xf,0x1e) /* GPIO Out */
+#define REG_GPIO_IN CRA(0x7,0xf,0x1f) /* GPIO In */
+#define REG_CPU_TRANSFER_SEL CRA(0x7,0xf,0x20) /* CPU Transfer Select */
+#define REG_LOCAL_DATA CRA(0x7,0xf,0xfe) /* Local CPU Data Register */
+#define REG_LOCAL_STATUS CRA(0x7,0xf,0xff) /* Local CPU Status Register */
+
+/* Aggregator registers */
+#define REG_AGGR_SETUP CRA(0x7,0x1,0x00) /* Aggregator Setup */
+#define REG_PMAP_TABLE CRA(0x7,0x1,0x01) /* Port map table */
+#define REG_MPLS_BIT0 CRA(0x7,0x1,0x08) /* MPLS bit0 position */
+#define REG_MPLS_BIT1 CRA(0x7,0x1,0x09) /* MPLS bit1 position */
+#define REG_MPLS_BIT2 CRA(0x7,0x1,0x0a) /* MPLS bit2 position */
+#define REG_MPLS_BIT3 CRA(0x7,0x1,0x0b) /* MPLS bit3 position */
+#define REG_MPLS_BITMASK CRA(0x7,0x1,0x0c) /* MPLS bit mask */
+#define REG_PRE_BIT0POS CRA(0x7,0x1,0x10) /* Preamble bit0 position */
+#define REG_PRE_BIT1POS CRA(0x7,0x1,0x11) /* Preamble bit1 position */
+#define REG_PRE_BIT2POS CRA(0x7,0x1,0x12) /* Preamble bit2 position */
+#define REG_PRE_BIT3POS CRA(0x7,0x1,0x13) /* Preamble bit3 position */
+#define REG_PRE_ERR_CNT CRA(0x7,0x1,0x14) /* Preamble parity error count */
+
+/* BIST registers */
+/*#define REG_RAM_BIST_CMD CRA(0x7,0x2,0x00)*/ /* RAM BIST Command Register */
+/*#define REG_RAM_BIST_RESULT CRA(0x7,0x2,0x01)*/ /* RAM BIST Read Status/Result */
+#define REG_RAM_BIST_CMD CRA(0x7,0x1,0x00) /* RAM BIST Command Register */
+#define REG_RAM_BIST_RESULT CRA(0x7,0x1,0x01) /* RAM BIST Read Status/Result */
+#define BIST_PORT_SELECT 0x00 /* BIST port select */
+#define BIST_COMMAND 0x01 /* BIST enable/disable */
+#define BIST_STATUS 0x02 /* BIST operation status */
+#define BIST_ERR_CNT_LSB 0x03 /* BIST error count lo 8b */
+#define BIST_ERR_CNT_MSB 0x04 /* BIST error count hi 8b */
+#define BIST_ERR_SEL_LSB 0x05 /* BIST error select lo 8b */
+#define BIST_ERR_SEL_MSB 0x06 /* BIST error select hi 8b */
+#define BIST_ERROR_STATE 0x07 /* BIST engine internal state */
+#define BIST_ERR_ADR0 0x08 /* BIST error address lo 8b */
+#define BIST_ERR_ADR1 0x09 /* BIST error address lomid 8b */
+#define BIST_ERR_ADR2 0x0a /* BIST error address himid 8b */
+#define BIST_ERR_ADR3 0x0b /* BIST error address hi 8b */
+
+/* FIFO registers
+ * ie = 0 for ingress, 1 for egress
+ * fn = FIFO number, 0-9
+ */
+#define REG_TEST(ie,fn) CRA(0x2,ie&1,0x00+fn) /* Mode & Test Register */
+#define REG_TOP_BOTTOM(ie,fn) CRA(0x2,ie&1,0x10+fn) /* FIFO Buffer Top & Bottom */
+#define REG_TAIL(ie,fn) CRA(0x2,ie&1,0x20+fn) /* FIFO Write Pointer */
+#define REG_HEAD(ie,fn) CRA(0x2,ie&1,0x30+fn) /* FIFO Read Pointer */
+#define REG_HIGH_LOW_WM(ie,fn) CRA(0x2,ie&1,0x40+fn) /* Flow Control Water Marks */
+#define REG_CT_THRHLD(ie,fn) CRA(0x2,ie&1,0x50+fn) /* Cut Through Threshold */
+#define REG_FIFO_DROP_CNT(ie,fn) CRA(0x2,ie&1,0x60+fn) /* Drop & CRC Error Counter */
+#define REG_DEBUG_BUF_CNT(ie,fn) CRA(0x2,ie&1,0x70+fn) /* Input Side Debug Counter */
+#define REG_BUCKI(fn) CRA(0x2,2,0x20+fn) /* Input Side Debug Counter */
+#define REG_BUCKE(fn) CRA(0x2,3,0x20+fn) /* Input Side Debug Counter */
+
+/* Traffic shaper buckets
+ * ie = 0 for ingress, 1 for egress
+ * bn = bucket number 0-10 (yes, 11 buckets)
+ */
+/* OK, this one's kinda ugly. Some hardware designers are perverse. */
+#define REG_TRAFFIC_SHAPER_BUCKET(ie,bn) CRA(0x2,ie&1,0x0a + (bn>7) | ((bn&7)<<4))
+#define REG_TRAFFIC_SHAPER_CONTROL(ie) CRA(0x2,ie&1,0x3b)
+
+#define REG_SRAM_ADR(ie) CRA(0x2,ie&1,0x0e) /* FIFO SRAM address */
+#define REG_SRAM_WR_STRB(ie) CRA(0x2,ie&1,0x1e) /* FIFO SRAM write strobe */
+#define REG_SRAM_RD_STRB(ie) CRA(0x2,ie&1,0x2e) /* FIFO SRAM read strobe */
+#define REG_SRAM_DATA_0(ie) CRA(0x2,ie&1,0x3e) /* FIFO SRAM data lo 8b */
+#define REG_SRAM_DATA_1(ie) CRA(0x2,ie&1,0x4e) /* FIFO SRAM data lomid 8b */
+#define REG_SRAM_DATA_2(ie) CRA(0x2,ie&1,0x5e) /* FIFO SRAM data himid 8b */
+#define REG_SRAM_DATA_3(ie) CRA(0x2,ie&1,0x6e) /* FIFO SRAM data hi 8b */
+#define REG_SRAM_DATA_BLK_TYPE(ie) CRA(0x2,ie&1,0x7e) /* FIFO SRAM tag */
+/* REG_ING_CONTROL equals REG_CONTROL with ie = 0, likewise REG_EGR_CONTROL is ie = 1 */
+#define REG_CONTROL(ie) CRA(0x2,ie&1,0x0f) /* FIFO control */
+#define REG_ING_CONTROL CRA(0x2,0x0,0x0f) /* Ingress control (alias) */
+#define REG_EGR_CONTROL CRA(0x2,0x1,0x0f) /* Egress control (alias) */
+#define REG_AGE_TIMER(ie) CRA(0x2,ie&1,0x1f) /* Aging timer */
+#define REG_AGE_INC(ie) CRA(0x2,ie&1,0x2f) /* Aging increment */
+#define DEBUG_OUT(ie) CRA(0x2,ie&1,0x3f) /* Output debug counter control */
+#define DEBUG_CNT(ie) CRA(0x2,ie&1,0x4f) /* Output debug counter */
+
+/* SPI4 interface */
+#define REG_SPI4_MISC CRA(0x5,0x0,0x00) /* Misc Register */
+#define REG_SPI4_STATUS CRA(0x5,0x0,0x01) /* CML Status */
+#define REG_SPI4_ING_SETUP0 CRA(0x5,0x0,0x02) /* Ingress Status Channel Setup */
+#define REG_SPI4_ING_SETUP1 CRA(0x5,0x0,0x03) /* Ingress Data Training Setup */
+#define REG_SPI4_ING_SETUP2 CRA(0x5,0x0,0x04) /* Ingress Data Burst Size Setup */
+#define REG_SPI4_EGR_SETUP0 CRA(0x5,0x0,0x05) /* Egress Status Channel Setup */
+#define REG_SPI4_DBG_CNT(n) CRA(0x5,0x0,0x10+n) /* Debug counters 0-9 */
+#define REG_SPI4_DBG_SETUP CRA(0x5,0x0,0x1A) /* Debug counters setup */
+#define REG_SPI4_TEST CRA(0x5,0x0,0x20) /* Test Setup Register */
+#define REG_TPGEN_UP0 CRA(0x5,0x0,0x21) /* Test Pattern generator user pattern 0 */
+#define REG_TPGEN_UP1 CRA(0x5,0x0,0x22) /* Test Pattern generator user pattern 1 */
+#define REG_TPCHK_UP0 CRA(0x5,0x0,0x23) /* Test Pattern checker user pattern 0 */
+#define REG_TPCHK_UP1 CRA(0x5,0x0,0x24) /* Test Pattern checker user pattern 1 */
+#define REG_TPSAM_P0 CRA(0x5,0x0,0x25) /* Sampled pattern 0 */
+#define REG_TPSAM_P1 CRA(0x5,0x0,0x26) /* Sampled pattern 1 */
+#define REG_TPERR_CNT CRA(0x5,0x0,0x27) /* Pattern checker error counter */
+#define REG_SPI4_STICKY CRA(0x5,0x0,0x30) /* Sticky bits register */
+#define REG_SPI4_DBG_INH CRA(0x5,0x0,0x31) /* Core egress & ingress inhibit */
+#define REG_SPI4_DBG_STATUS CRA(0x5,0x0,0x32) /* Sampled ingress status */
+#define REG_SPI4_DBG_GRANT CRA(0x5,0x0,0x33) /* Ingress cranted credit value */
+
+#define REG_SPI4_DESKEW CRA(0x5,0x0,0x43) /* Ingress cranted credit value */
+
+/* 10GbE MAC Block Registers */
+/* Note that those registers that are exactly the same for 10GbE as for
+ * tri-speed are only defined with the version that needs a port number.
+ * Pass 0xa in those cases.
+ *
+ * Also note that despite the presence of a MAC address register, this part
+ * does no ingress MAC address filtering. That register is used only for
+ * pause frame detection and generation.
+ */
+/* 10GbE specific, and different from tri-speed */
+#define REG_MISC_10G CRA(0x1,0xa,0x00) /* Misc 10GbE setup */
+#define REG_PAUSE_10G CRA(0x1,0xa,0x01) /* Pause register */
+#define REG_NORMALIZER_10G CRA(0x1,0xa,0x05) /* 10G normalizer */
+#define REG_STICKY_RX CRA(0x1,0xa,0x06) /* RX debug register */
+#define REG_DENORM_10G CRA(0x1,0xa,0x07) /* Denormalizer */
+#define REG_STICKY_TX CRA(0x1,0xa,0x08) /* TX sticky bits */
+#define REG_MAX_RXHIGH CRA(0x1,0xa,0x0a) /* XGMII lane 0-3 debug */
+#define REG_MAX_RXLOW CRA(0x1,0xa,0x0b) /* XGMII lane 4-7 debug */
+#define REG_MAC_TX_STICKY CRA(0x1,0xa,0x0c) /* MAC Tx state sticky debug */
+#define REG_MAC_TX_RUNNING CRA(0x1,0xa,0x0d) /* MAC Tx state running debug */
+#define REG_TX_ABORT_AGE CRA(0x1,0xa,0x14) /* Aged Tx frames discarded */
+#define REG_TX_ABORT_SHORT CRA(0x1,0xa,0x15) /* Short Tx frames discarded */
+#define REG_TX_ABORT_TAXI CRA(0x1,0xa,0x16) /* Taxi error frames discarded */
+#define REG_TX_ABORT_UNDERRUN CRA(0x1,0xa,0x17) /* Tx Underrun abort counter */
+#define REG_TX_DENORM_DISCARD CRA(0x1,0xa,0x18) /* Tx denormalizer discards */
+#define REG_XAUI_STAT_A CRA(0x1,0xa,0x20) /* XAUI status A */
+#define REG_XAUI_STAT_B CRA(0x1,0xa,0x21) /* XAUI status B */
+#define REG_XAUI_STAT_C CRA(0x1,0xa,0x22) /* XAUI status C */
+#define REG_XAUI_CONF_A CRA(0x1,0xa,0x23) /* XAUI configuration A */
+#define REG_XAUI_CONF_B CRA(0x1,0xa,0x24) /* XAUI configuration B */
+#define REG_XAUI_CODE_GRP_CNT CRA(0x1,0xa,0x25) /* XAUI code group error count */
+#define REG_XAUI_CONF_TEST_A CRA(0x1,0xa,0x26) /* XAUI test register A */
+#define REG_PDERRCNT CRA(0x1,0xa,0x27) /* XAUI test register B */
+
+/* pn = port number 0-9 for tri-speed, 10 for 10GbE */
+/* Both tri-speed and 10GbE */
+#define REG_MAX_LEN(pn) CRA(0x1,pn,0x02) /* Max length */
+#define REG_MAC_HIGH_ADDR(pn) CRA(0x1,pn,0x03) /* Upper 24 bits of MAC addr */
+#define REG_MAC_LOW_ADDR(pn) CRA(0x1,pn,0x04) /* Lower 24 bits of MAC addr */
+
+/* tri-speed only
+ * pn = port number, 0-9
+ */
+#define REG_MODE_CFG(pn) CRA(0x1,pn,0x00) /* Mode configuration */
+#define REG_PAUSE_CFG(pn) CRA(0x1,pn,0x01) /* Pause configuration */
+#define REG_NORMALIZER(pn) CRA(0x1,pn,0x05) /* Normalizer */
+#define REG_TBI_STATUS(pn) CRA(0x1,pn,0x06) /* TBI status */
+#define REG_PCS_STATUS_DBG(pn) CRA(0x1,pn,0x07) /* PCS status debug */
+#define REG_PCS_CTRL(pn) CRA(0x1,pn,0x08) /* PCS control */
+#define REG_TBI_CONFIG(pn) CRA(0x1,pn,0x09) /* TBI configuration */
+#define REG_STICK_BIT(pn) CRA(0x1,pn,0x0a) /* Sticky bits */
+#define REG_DEV_SETUP(pn) CRA(0x1,pn,0x0b) /* MAC clock/reset setup */
+#define REG_DROP_CNT(pn) CRA(0x1,pn,0x0c) /* Drop counter */
+#define REG_PORT_POS(pn) CRA(0x1,pn,0x0d) /* Preamble port position */
+#define REG_PORT_FAIL(pn) CRA(0x1,pn,0x0e) /* Preamble port position */
+#define REG_SERDES_CONF(pn) CRA(0x1,pn,0x0f) /* SerDes configuration */
+#define REG_SERDES_TEST(pn) CRA(0x1,pn,0x10) /* SerDes test */
+#define REG_SERDES_STAT(pn) CRA(0x1,pn,0x11) /* SerDes status */
+#define REG_SERDES_COM_CNT(pn) CRA(0x1,pn,0x12) /* SerDes comma counter */
+#define REG_DENORM(pn) CRA(0x1,pn,0x15) /* Frame denormalization */
+#define REG_DBG(pn) CRA(0x1,pn,0x16) /* Device 1G debug */
+#define REG_TX_IFG(pn) CRA(0x1,pn,0x18) /* Tx IFG config */
+#define REG_HDX(pn) CRA(0x1,pn,0x19) /* Half-duplex config */
+
+/* Statistics */
+/* pn = port number, 0-a, a = 10GbE */
+#define REG_RX_IN_BYTES(pn) CRA(0x4,pn,0x00) /* # Rx in octets */
+#define REG_RX_SYMBOL_CARRIER(pn) CRA(0x4,pn,0x01) /* Frames w/ symbol errors */
+#define REG_RX_PAUSE(pn) CRA(0x4,pn,0x02) /* # pause frames received */
+#define REG_RX_UNSUP_OPCODE(pn) CRA(0x4,pn,0x03) /* # control frames with unsupported opcode */
+#define REG_RX_OK_BYTES(pn) CRA(0x4,pn,0x04) /* # octets in good frames */
+#define REG_RX_BAD_BYTES(pn) CRA(0x4,pn,0x05) /* # octets in bad frames */
+#define REG_RX_UNICAST(pn) CRA(0x4,pn,0x06) /* # good unicast frames */
+#define REG_RX_MULTICAST(pn) CRA(0x4,pn,0x07) /* # good multicast frames */
+#define REG_RX_BROADCAST(pn) CRA(0x4,pn,0x08) /* # good broadcast frames */
+#define REG_CRC(pn) CRA(0x4,pn,0x09) /* # frames w/ bad CRC only */
+#define REG_RX_ALIGNMENT(pn) CRA(0x4,pn,0x0a) /* # frames w/ alignment err */
+#define REG_RX_UNDERSIZE(pn) CRA(0x4,pn,0x0b) /* # frames undersize */
+#define REG_RX_FRAGMENTS(pn) CRA(0x4,pn,0x0c) /* # frames undersize w/ crc err */
+#define REG_RX_IN_RANGE_LENGTH_ERROR(pn) CRA(0x4,pn,0x0d) /* # frames with length error */
+#define REG_RX_OUT_OF_RANGE_ERROR(pn) CRA(0x4,pn,0x0e) /* # frames with illegal length field */
+#define REG_RX_OVERSIZE(pn) CRA(0x4,pn,0x0f) /* # frames oversize */
+#define REG_RX_JABBERS(pn) CRA(0x4,pn,0x10) /* # frames oversize w/ crc err */
+#define REG_RX_SIZE_64(pn) CRA(0x4,pn,0x11) /* # frames 64 octets long */
+#define REG_RX_SIZE_65_TO_127(pn) CRA(0x4,pn,0x12) /* # frames 65-127 octets */
+#define REG_RX_SIZE_128_TO_255(pn) CRA(0x4,pn,0x13) /* # frames 128-255 */
+#define REG_RX_SIZE_256_TO_511(pn) CRA(0x4,pn,0x14) /* # frames 256-511 */
+#define REG_RX_SIZE_512_TO_1023(pn) CRA(0x4,pn,0x15) /* # frames 512-1023 */
+#define REG_RX_SIZE_1024_TO_1518(pn) CRA(0x4,pn,0x16) /* # frames 1024-1518 */
+#define REG_RX_SIZE_1519_TO_MAX(pn) CRA(0x4,pn,0x17) /* # frames 1519-max */
+
+#define REG_TX_OUT_BYTES(pn) CRA(0x4,pn,0x18) /* # octets tx */
+#define REG_TX_PAUSE(pn) CRA(0x4,pn,0x19) /* # pause frames sent */
+#define REG_TX_OK_BYTES(pn) CRA(0x4,pn,0x1a) /* # octets tx OK */
+#define REG_TX_UNICAST(pn) CRA(0x4,pn,0x1b) /* # frames unicast */
+#define REG_TX_MULTICAST(pn) CRA(0x4,pn,0x1c) /* # frames multicast */
+#define REG_TX_BROADCAST(pn) CRA(0x4,pn,0x1d) /* # frames broadcast */
+#define REG_TX_MULTIPLE_COLL(pn) CRA(0x4,pn,0x1e) /* # frames tx after multiple collisions */
+#define REG_TX_LATE_COLL(pn) CRA(0x4,pn,0x1f) /* # late collisions detected */
+#define REG_TX_XCOLL(pn) CRA(0x4,pn,0x20) /* # frames lost, excessive collisions */
+#define REG_TX_DEFER(pn) CRA(0x4,pn,0x21) /* # frames deferred on first tx attempt */
+#define REG_TX_XDEFER(pn) CRA(0x4,pn,0x22) /* # frames excessively deferred */
+#define REG_TX_CSENSE(pn) CRA(0x4,pn,0x23) /* carrier sense errors at frame end */
+#define REG_TX_SIZE_64(pn) CRA(0x4,pn,0x24) /* # frames 64 octets long */
+#define REG_TX_SIZE_65_TO_127(pn) CRA(0x4,pn,0x25) /* # frames 65-127 octets */
+#define REG_TX_SIZE_128_TO_255(pn) CRA(0x4,pn,0x26) /* # frames 128-255 */
+#define REG_TX_SIZE_256_TO_511(pn) CRA(0x4,pn,0x27) /* # frames 256-511 */
+#define REG_TX_SIZE_512_TO_1023(pn) CRA(0x4,pn,0x28) /* # frames 512-1023 */
+#define REG_TX_SIZE_1024_TO_1518(pn) CRA(0x4,pn,0x29) /* # frames 1024-1518 */
+#define REG_TX_SIZE_1519_TO_MAX(pn) CRA(0x4,pn,0x2a) /* # frames 1519-max */
+#define REG_TX_SINGLE_COLL(pn) CRA(0x4,pn,0x2b) /* # frames tx after single collision */
+#define REG_TX_BACKOFF2(pn) CRA(0x4,pn,0x2c) /* # frames tx ok after 2 backoffs/collisions */
+#define REG_TX_BACKOFF3(pn) CRA(0x4,pn,0x2d) /* after 3 backoffs/collisions */
+#define REG_TX_BACKOFF4(pn) CRA(0x4,pn,0x2e) /* after 4 */
+#define REG_TX_BACKOFF5(pn) CRA(0x4,pn,0x2f) /* after 5 */
+#define REG_TX_BACKOFF6(pn) CRA(0x4,pn,0x30) /* after 6 */
+#define REG_TX_BACKOFF7(pn) CRA(0x4,pn,0x31) /* after 7 */
+#define REG_TX_BACKOFF8(pn) CRA(0x4,pn,0x32) /* after 8 */
+#define REG_TX_BACKOFF9(pn) CRA(0x4,pn,0x33) /* after 9 */
+#define REG_TX_BACKOFF10(pn) CRA(0x4,pn,0x34) /* after 10 */
+#define REG_TX_BACKOFF11(pn) CRA(0x4,pn,0x35) /* after 11 */
+#define REG_TX_BACKOFF12(pn) CRA(0x4,pn,0x36) /* after 12 */
+#define REG_TX_BACKOFF13(pn) CRA(0x4,pn,0x37) /* after 13 */
+#define REG_TX_BACKOFF14(pn) CRA(0x4,pn,0x38) /* after 14 */
+#define REG_TX_BACKOFF15(pn) CRA(0x4,pn,0x39) /* after 15 */
+#define REG_TX_UNDERRUN(pn) CRA(0x4,pn,0x3a) /* # frames dropped from underrun */
+#define REG_RX_XGMII_PROT_ERR CRA(0x4,0xa,0x3b) /* # protocol errors detected on XGMII interface */
+#define REG_RX_IPG_SHRINK(pn) CRA(0x4,pn,0x3c) /* # of IPG shrinks detected */
+
+#define REG_STAT_STICKY1G(pn) CRA(0x4,pn,0x3e) /* tri-speed sticky bits */
+#define REG_STAT_STICKY10G CRA(0x4,0xa,0x3e) /* 10GbE sticky bits */
+#define REG_STAT_INIT(pn) CRA(0x4,pn,0x3f) /* Clear all statistics */
+
+/* MII-Management Block registers */
+/* These are for MII-M interface 0, which is the bidirectional LVTTL one. If
+ * we hooked up to the one with separate directions, the middle 0x0 needs to
+ * change to 0x1. And the current errata states that MII-M 1 doesn't work.
+ */
+
+#define REG_MIIM_STATUS CRA(0x3,0x0,0x00) /* MII-M Status */
+#define REG_MIIM_CMD CRA(0x3,0x0,0x01) /* MII-M Command */
+#define REG_MIIM_DATA CRA(0x3,0x0,0x02) /* MII-M Data */
+#define REG_MIIM_PRESCALE CRA(0x3,0x0,0x03) /* MII-M MDC Prescale */
+
+#define REG_ING_FFILT_UM_EN CRA(0x2, 0, 0xd)
+#define REG_ING_FFILT_BE_EN CRA(0x2, 0, 0x1d)
+#define REG_ING_FFILT_VAL0 CRA(0x2, 0, 0x2d)
+#define REG_ING_FFILT_VAL1 CRA(0x2, 0, 0x3d)
+#define REG_ING_FFILT_MASK0 CRA(0x2, 0, 0x4d)
+#define REG_ING_FFILT_MASK1 CRA(0x2, 0, 0x5d)
+#define REG_ING_FFILT_MASK2 CRA(0x2, 0, 0x6d)
+#define REG_ING_FFILT_ETYPE CRA(0x2, 0, 0x7d)
+
+
+/* Whew. */
+
+#endif
diff --git a/drivers/net/chelsio/vsc8244.c b/drivers/net/chelsio/vsc8244.c
new file mode 100644
index 000000000000..c493e783d459
--- /dev/null
+++ b/drivers/net/chelsio/vsc8244.c
@@ -0,0 +1,368 @@
+/*
+ * This file is part of the Chelsio T2 Ethernet driver.
+ *
+ * Copyright (C) 2005 Chelsio Communications. All rights reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the LICENSE file included in this
+ * release for licensing terms and conditions.
+ */
+
+#include "common.h"
+#include "cphy.h"
+#include "elmer0.h"
+
+#ifndef ADVERTISE_PAUSE_CAP
+# define ADVERTISE_PAUSE_CAP 0x400
+#endif
+#ifndef ADVERTISE_PAUSE_ASYM
+# define ADVERTISE_PAUSE_ASYM 0x800
+#endif
+
+/* Gigabit MII registers */
+#ifndef MII_CTRL1000
+# define MII_CTRL1000 9
+#endif
+
+#ifndef ADVERTISE_1000FULL
+# define ADVERTISE_1000FULL 0x200
+# define ADVERTISE_1000HALF 0x100
+#endif
+
+/* VSC8244 PHY specific registers. */
+enum {
+ VSC8244_INTR_ENABLE = 25,
+ VSC8244_INTR_STATUS = 26,
+ VSC8244_AUX_CTRL_STAT = 28,
+};
+
+enum {
+ VSC_INTR_RX_ERR = 1 << 0,
+ VSC_INTR_MS_ERR = 1 << 1, /* master/slave resolution error */
+ VSC_INTR_CABLE = 1 << 2, /* cable impairment */
+ VSC_INTR_FALSE_CARR = 1 << 3, /* false carrier */
+ VSC_INTR_MEDIA_CHG = 1 << 4, /* AMS media change */
+ VSC_INTR_RX_FIFO = 1 << 5, /* Rx FIFO over/underflow */
+ VSC_INTR_TX_FIFO = 1 << 6, /* Tx FIFO over/underflow */
+ VSC_INTR_DESCRAMBL = 1 << 7, /* descrambler lock-lost */
+ VSC_INTR_SYMBOL_ERR = 1 << 8, /* symbol error */
+ VSC_INTR_NEG_DONE = 1 << 10, /* autoneg done */
+ VSC_INTR_NEG_ERR = 1 << 11, /* autoneg error */
+ VSC_INTR_LINK_CHG = 1 << 13, /* link change */
+ VSC_INTR_ENABLE = 1 << 15, /* interrupt enable */
+};
+
+#define CFG_CHG_INTR_MASK (VSC_INTR_LINK_CHG | VSC_INTR_NEG_ERR | \
+ VSC_INTR_NEG_DONE)
+#define INTR_MASK (CFG_CHG_INTR_MASK | VSC_INTR_TX_FIFO | VSC_INTR_RX_FIFO | \
+ VSC_INTR_ENABLE)
+
+/* PHY specific auxiliary control & status register fields */
+#define S_ACSR_ACTIPHY_TMR 0
+#define M_ACSR_ACTIPHY_TMR 0x3
+#define V_ACSR_ACTIPHY_TMR(x) ((x) << S_ACSR_ACTIPHY_TMR)
+
+#define S_ACSR_SPEED 3
+#define M_ACSR_SPEED 0x3
+#define G_ACSR_SPEED(x) (((x) >> S_ACSR_SPEED) & M_ACSR_SPEED)
+
+#define S_ACSR_DUPLEX 5
+#define F_ACSR_DUPLEX (1 << S_ACSR_DUPLEX)
+
+#define S_ACSR_ACTIPHY 6
+#define F_ACSR_ACTIPHY (1 << S_ACSR_ACTIPHY)
+
+/*
+ * Reset the PHY. This PHY completes reset immediately so we never wait.
+ */
+static int vsc8244_reset(struct cphy *cphy, int wait)
+{
+ int err;
+ unsigned int ctl;
+
+ err = simple_mdio_read(cphy, MII_BMCR, &ctl);
+ if (err)
+ return err;
+
+ ctl &= ~BMCR_PDOWN;
+ ctl |= BMCR_RESET;
+ return simple_mdio_write(cphy, MII_BMCR, ctl);
+}
+
+static int vsc8244_intr_enable(struct cphy *cphy)
+{
+ simple_mdio_write(cphy, VSC8244_INTR_ENABLE, INTR_MASK);
+
+ /* Enable interrupts through Elmer */
+ if (t1_is_asic(cphy->adapter)) {
+ u32 elmer;
+
+ t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer);
+ elmer |= ELMER0_GP_BIT1;
+ if (is_T2(cphy->adapter)) {
+ elmer |= ELMER0_GP_BIT2|ELMER0_GP_BIT3|ELMER0_GP_BIT4;
+ }
+ t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer);
+ }
+
+ return 0;
+}
+
+static int vsc8244_intr_disable(struct cphy *cphy)
+{
+ simple_mdio_write(cphy, VSC8244_INTR_ENABLE, 0);
+
+ if (t1_is_asic(cphy->adapter)) {
+ u32 elmer;
+
+ t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer);
+ elmer &= ~ELMER0_GP_BIT1;
+ if (is_T2(cphy->adapter)) {
+ elmer &= ~(ELMER0_GP_BIT2|ELMER0_GP_BIT3|ELMER0_GP_BIT4);
+ }
+ t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer);
+ }
+
+ return 0;
+}
+
+static int vsc8244_intr_clear(struct cphy *cphy)
+{
+ u32 val;
+ u32 elmer;
+
+ /* Clear PHY interrupts by reading the register. */
+ simple_mdio_read(cphy, VSC8244_INTR_ENABLE, &val);
+
+ if (t1_is_asic(cphy->adapter)) {
+ t1_tpi_read(cphy->adapter, A_ELMER0_INT_CAUSE, &elmer);
+ elmer |= ELMER0_GP_BIT1;
+ if (is_T2(cphy->adapter)) {
+ elmer |= ELMER0_GP_BIT2|ELMER0_GP_BIT3|ELMER0_GP_BIT4;
+ }
+ t1_tpi_write(cphy->adapter, A_ELMER0_INT_CAUSE, elmer);
+ }
+
+ return 0;
+}
+
+/*
+ * Force the PHY speed and duplex. This also disables auto-negotiation, except
+ * for 1Gb/s, where auto-negotiation is mandatory.
+ */
+static int vsc8244_set_speed_duplex(struct cphy *phy, int speed, int duplex)
+{
+ int err;
+ unsigned int ctl;
+
+ err = simple_mdio_read(phy, MII_BMCR, &ctl);
+ if (err)
+ return err;
+
+ if (speed >= 0) {
+ ctl &= ~(BMCR_SPEED100 | BMCR_SPEED1000 | BMCR_ANENABLE);
+ if (speed == SPEED_100)
+ ctl |= BMCR_SPEED100;
+ else if (speed == SPEED_1000)
+ ctl |= BMCR_SPEED1000;
+ }
+ if (duplex >= 0) {
+ ctl &= ~(BMCR_FULLDPLX | BMCR_ANENABLE);
+ if (duplex == DUPLEX_FULL)
+ ctl |= BMCR_FULLDPLX;
+ }
+ if (ctl & BMCR_SPEED1000) /* auto-negotiation required for 1Gb/s */
+ ctl |= BMCR_ANENABLE;
+ return simple_mdio_write(phy, MII_BMCR, ctl);
+}
+
+int t1_mdio_set_bits(struct cphy *phy, int mmd, int reg, unsigned int bits)
+{
+ int ret;
+ unsigned int val;
+
+ ret = mdio_read(phy, mmd, reg, &val);
+ if (!ret)
+ ret = mdio_write(phy, mmd, reg, val | bits);
+ return ret;
+}
+
+static int vsc8244_autoneg_enable(struct cphy *cphy)
+{
+ return t1_mdio_set_bits(cphy, 0, MII_BMCR,
+ BMCR_ANENABLE | BMCR_ANRESTART);
+}
+
+static int vsc8244_autoneg_restart(struct cphy *cphy)
+{
+ return t1_mdio_set_bits(cphy, 0, MII_BMCR, BMCR_ANRESTART);
+}
+
+static int vsc8244_advertise(struct cphy *phy, unsigned int advertise_map)
+{
+ int err;
+ unsigned int val = 0;
+
+ err = simple_mdio_read(phy, MII_CTRL1000, &val);
+ if (err)
+ return err;
+
+ val &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL);
+ if (advertise_map & ADVERTISED_1000baseT_Half)
+ val |= ADVERTISE_1000HALF;
+ if (advertise_map & ADVERTISED_1000baseT_Full)
+ val |= ADVERTISE_1000FULL;
+
+ err = simple_mdio_write(phy, MII_CTRL1000, val);
+ if (err)
+ return err;
+
+ val = 1;
+ if (advertise_map & ADVERTISED_10baseT_Half)
+ val |= ADVERTISE_10HALF;
+ if (advertise_map & ADVERTISED_10baseT_Full)
+ val |= ADVERTISE_10FULL;
+ if (advertise_map & ADVERTISED_100baseT_Half)
+ val |= ADVERTISE_100HALF;
+ if (advertise_map & ADVERTISED_100baseT_Full)
+ val |= ADVERTISE_100FULL;
+ if (advertise_map & ADVERTISED_PAUSE)
+ val |= ADVERTISE_PAUSE_CAP;
+ if (advertise_map & ADVERTISED_ASYM_PAUSE)
+ val |= ADVERTISE_PAUSE_ASYM;
+ return simple_mdio_write(phy, MII_ADVERTISE, val);
+}
+
+static int vsc8244_get_link_status(struct cphy *cphy, int *link_ok,
+ int *speed, int *duplex, int *fc)
+{
+ unsigned int bmcr, status, lpa, adv;
+ int err, sp = -1, dplx = -1, pause = 0;
+
+ err = simple_mdio_read(cphy, MII_BMCR, &bmcr);
+ if (!err)
+ err = simple_mdio_read(cphy, MII_BMSR, &status);
+ if (err)
+ return err;
+
+ if (link_ok) {
+ /*
+ * BMSR_LSTATUS is latch-low, so if it is 0 we need to read it
+ * once more to get the current link state.
+ */
+ if (!(status & BMSR_LSTATUS))
+ err = simple_mdio_read(cphy, MII_BMSR, &status);
+ if (err)
+ return err;
+ *link_ok = (status & BMSR_LSTATUS) != 0;
+ }
+ if (!(bmcr & BMCR_ANENABLE)) {
+ dplx = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
+ if (bmcr & BMCR_SPEED1000)
+ sp = SPEED_1000;
+ else if (bmcr & BMCR_SPEED100)
+ sp = SPEED_100;
+ else
+ sp = SPEED_10;
+ } else if (status & BMSR_ANEGCOMPLETE) {
+ err = simple_mdio_read(cphy, VSC8244_AUX_CTRL_STAT, &status);
+ if (err)
+ return err;
+
+ dplx = (status & F_ACSR_DUPLEX) ? DUPLEX_FULL : DUPLEX_HALF;
+ sp = G_ACSR_SPEED(status);
+ if (sp == 0)
+ sp = SPEED_10;
+ else if (sp == 1)
+ sp = SPEED_100;
+ else
+ sp = SPEED_1000;
+
+ if (fc && dplx == DUPLEX_FULL) {
+ err = simple_mdio_read(cphy, MII_LPA, &lpa);
+ if (!err)
+ err = simple_mdio_read(cphy, MII_ADVERTISE,
+ &adv);
+ if (err)
+ return err;
+
+ if (lpa & adv & ADVERTISE_PAUSE_CAP)
+ pause = PAUSE_RX | PAUSE_TX;
+ else if ((lpa & ADVERTISE_PAUSE_CAP) &&
+ (lpa & ADVERTISE_PAUSE_ASYM) &&
+ (adv & ADVERTISE_PAUSE_ASYM))
+ pause = PAUSE_TX;
+ else if ((lpa & ADVERTISE_PAUSE_ASYM) &&
+ (adv & ADVERTISE_PAUSE_CAP))
+ pause = PAUSE_RX;
+ }
+ }
+ if (speed)
+ *speed = sp;
+ if (duplex)
+ *duplex = dplx;
+ if (fc)
+ *fc = pause;
+ return 0;
+}
+
+static int vsc8244_intr_handler(struct cphy *cphy)
+{
+ unsigned int cause;
+ int err, cphy_cause = 0;
+
+ err = simple_mdio_read(cphy, VSC8244_INTR_STATUS, &cause);
+ if (err)
+ return err;
+
+ cause &= INTR_MASK;
+ if (cause & CFG_CHG_INTR_MASK)
+ cphy_cause |= cphy_cause_link_change;
+ if (cause & (VSC_INTR_RX_FIFO | VSC_INTR_TX_FIFO))
+ cphy_cause |= cphy_cause_fifo_error;
+ return cphy_cause;
+}
+
+static void vsc8244_destroy(struct cphy *cphy)
+{
+ kfree(cphy);
+}
+
+static struct cphy_ops vsc8244_ops = {
+ .destroy = vsc8244_destroy,
+ .reset = vsc8244_reset,
+ .interrupt_enable = vsc8244_intr_enable,
+ .interrupt_disable = vsc8244_intr_disable,
+ .interrupt_clear = vsc8244_intr_clear,
+ .interrupt_handler = vsc8244_intr_handler,
+ .autoneg_enable = vsc8244_autoneg_enable,
+ .autoneg_restart = vsc8244_autoneg_restart,
+ .advertise = vsc8244_advertise,
+ .set_speed_duplex = vsc8244_set_speed_duplex,
+ .get_link_status = vsc8244_get_link_status
+};
+
+static struct cphy* vsc8244_phy_create(adapter_t *adapter, int phy_addr, struct mdio_ops *mdio_ops)
+{
+ struct cphy *cphy = kzalloc(sizeof(*cphy), GFP_KERNEL);
+
+ if (!cphy) return NULL;
+
+ cphy_init(cphy, adapter, phy_addr, &vsc8244_ops, mdio_ops);
+
+ return cphy;
+}
+
+
+static int vsc8244_phy_reset(adapter_t* adapter)
+{
+ return 0;
+}
+
+struct gphy t1_vsc8244_ops = {
+ vsc8244_phy_create,
+ vsc8244_phy_reset
+};
+
+
diff --git a/drivers/net/chelsio/vsc8244_reg.h b/drivers/net/chelsio/vsc8244_reg.h
new file mode 100644
index 000000000000..d3c1829055cb
--- /dev/null
+++ b/drivers/net/chelsio/vsc8244_reg.h
@@ -0,0 +1,172 @@
+/* $Date: 2005/11/23 16:28:53 $ $RCSfile: vsc8244_reg.h,v $ $Revision: 1.1 $ */
+#ifndef CHELSIO_MV8E1XXX_H
+#define CHELSIO_MV8E1XXX_H
+
+#ifndef BMCR_SPEED1000
+# define BMCR_SPEED1000 0x40
+#endif
+
+#ifndef ADVERTISE_PAUSE
+# define ADVERTISE_PAUSE 0x400
+#endif
+#ifndef ADVERTISE_PAUSE_ASYM
+# define ADVERTISE_PAUSE_ASYM 0x800
+#endif
+
+/* Gigabit MII registers */
+#define MII_GBMR 1 /* 1000Base-T mode register */
+#define MII_GBCR 9 /* 1000Base-T control register */
+#define MII_GBSR 10 /* 1000Base-T status register */
+
+/* 1000Base-T control register fields */
+#define GBCR_ADV_1000HALF 0x100
+#define GBCR_ADV_1000FULL 0x200
+#define GBCR_PREFER_MASTER 0x400
+#define GBCR_MANUAL_AS_MASTER 0x800
+#define GBCR_MANUAL_CONFIG_ENABLE 0x1000
+
+/* 1000Base-T status register fields */
+#define GBSR_LP_1000HALF 0x400
+#define GBSR_LP_1000FULL 0x800
+#define GBSR_REMOTE_OK 0x1000
+#define GBSR_LOCAL_OK 0x2000
+#define GBSR_LOCAL_MASTER 0x4000
+#define GBSR_MASTER_FAULT 0x8000
+
+/* Vitesse PHY interrupt status bits. */
+#if 0
+#define VSC8244_INTR_JABBER 0x0001
+#define VSC8244_INTR_POLARITY_CHNG 0x0002
+#define VSC8244_INTR_ENG_DETECT_CHNG 0x0010
+#define VSC8244_INTR_DOWNSHIFT 0x0020
+#define VSC8244_INTR_MDI_XOVER_CHNG 0x0040
+#define VSC8244_INTR_FIFO_OVER_UNDER 0x0080
+#define VSC8244_INTR_FALSE_CARRIER 0x0100
+#define VSC8244_INTR_SYMBOL_ERROR 0x0200
+#define VSC8244_INTR_LINK_CHNG 0x0400
+#define VSC8244_INTR_AUTONEG_DONE 0x0800
+#define VSC8244_INTR_PAGE_RECV 0x1000
+#define VSC8244_INTR_DUPLEX_CHNG 0x2000
+#define VSC8244_INTR_SPEED_CHNG 0x4000
+#define VSC8244_INTR_AUTONEG_ERR 0x8000
+#else
+//#define VSC8244_INTR_JABBER 0x0001
+//#define VSC8244_INTR_POLARITY_CHNG 0x0002
+//#define VSC8244_INTR_BIT2 0x0004
+//#define VSC8244_INTR_BIT3 0x0008
+#define VSC8244_INTR_RX_ERR 0x0001
+#define VSC8244_INTR_MASTER_SLAVE 0x0002
+#define VSC8244_INTR_CABLE_IMPAIRED 0x0004
+#define VSC8244_INTR_FALSE_CARRIER 0x0008
+//#define VSC8244_INTR_ENG_DETECT_CHNG 0x0010
+//#define VSC8244_INTR_DOWNSHIFT 0x0020
+//#define VSC8244_INTR_MDI_XOVER_CHNG 0x0040
+//#define VSC8244_INTR_FIFO_OVER_UNDER 0x0080
+#define VSC8244_INTR_BIT4 0x0010
+#define VSC8244_INTR_FIFO_RX 0x0020
+#define VSC8244_INTR_FIFO_OVER_UNDER 0x0040
+#define VSC8244_INTR_LOCK_LOST 0x0080
+//#define VSC8244_INTR_FALSE_CARRIER 0x0100
+//#define VSC8244_INTR_SYMBOL_ERROR 0x0200
+//#define VSC8244_INTR_LINK_CHNG 0x0400
+//#define VSC8244_INTR_AUTONEG_DONE 0x0800
+#define VSC8244_INTR_SYMBOL_ERROR 0x0100
+#define VSC8244_INTR_ENG_DETECT_CHNG 0x0200
+#define VSC8244_INTR_AUTONEG_DONE 0x0400
+#define VSC8244_INTR_AUTONEG_ERR 0x0800
+//#define VSC8244_INTR_PAGE_RECV 0x1000
+//#define VSC8244_INTR_DUPLEX_CHNG 0x2000
+//#define VSC8244_INTR_SPEED_CHNG 0x4000
+//#define VSC8244_INTR_AUTONEG_ERR 0x8000
+#define VSC8244_INTR_DUPLEX_CHNG 0x1000
+#define VSC8244_INTR_LINK_CHNG 0x2000
+#define VSC8244_INTR_SPEED_CHNG 0x4000
+#define VSC8244_INTR_STATUS 0x8000
+#endif
+
+
+/* Vitesse PHY specific registers. */
+#define VSC8244_SPECIFIC_CNTRL_REGISTER 16
+#define VSC8244_SPECIFIC_STATUS_REGISTER 0x1c
+#define VSC8244_INTERRUPT_ENABLE_REGISTER 0x19
+#define VSC8244_INTERRUPT_STATUS_REGISTER 0x1a
+#define VSC8244_EXT_PHY_SPECIFIC_CNTRL_REGISTER 20
+#define VSC8244_RECV_ERR_CNTR_REGISTER 21
+#define VSC8244_RES_REGISTER 22
+#define VSC8244_GLOBAL_STATUS_REGISTER 23
+#define VSC8244_LED_CONTROL_REGISTER 24
+#define VSC8244_MANUAL_LED_OVERRIDE_REGISTER 25
+#define VSC8244_EXT_PHY_SPECIFIC_CNTRL_2_REGISTER 26
+#define VSC8244_EXT_PHY_SPECIFIC_STATUS_REGISTER 27
+#define VSC8244_VIRTUAL_CABLE_TESTER_REGISTER 28
+#define VSC8244_EXTENDED_ADDR_REGISTER 29
+#define VSC8244_EXTENDED_REGISTER 30
+
+/* PHY specific control register fields */
+#define S_PSCR_MDI_XOVER_MODE 5
+#define M_PSCR_MDI_XOVER_MODE 0x3
+#define V_PSCR_MDI_XOVER_MODE(x) ((x) << S_PSCR_MDI_XOVER_MODE)
+#define G_PSCR_MDI_XOVER_MODE(x) (((x) >> S_PSCR_MDI_XOVER_MODE) & M_PSCR_MDI_XOVER_MODE)
+
+/* Extended PHY specific control register fields */
+#define S_DOWNSHIFT_ENABLE 8
+#define V_DOWNSHIFT_ENABLE (1 << S_DOWNSHIFT_ENABLE)
+
+#define S_DOWNSHIFT_CNT 9
+#define M_DOWNSHIFT_CNT 0x7
+#define V_DOWNSHIFT_CNT(x) ((x) << S_DOWNSHIFT_CNT)
+#define G_DOWNSHIFT_CNT(x) (((x) >> S_DOWNSHIFT_CNT) & M_DOWNSHIFT_CNT)
+
+/* PHY specific status register fields */
+#define S_PSSR_JABBER 0
+#define V_PSSR_JABBER (1 << S_PSSR_JABBER)
+
+#define S_PSSR_POLARITY 1
+#define V_PSSR_POLARITY (1 << S_PSSR_POLARITY)
+
+#define S_PSSR_RX_PAUSE 2
+#define V_PSSR_RX_PAUSE (1 << S_PSSR_RX_PAUSE)
+
+#define S_PSSR_TX_PAUSE 3
+#define V_PSSR_TX_PAUSE (1 << S_PSSR_TX_PAUSE)
+
+#define S_PSSR_ENERGY_DETECT 4
+#define V_PSSR_ENERGY_DETECT (1 << S_PSSR_ENERGY_DETECT)
+
+#define S_PSSR_DOWNSHIFT_STATUS 5
+#define V_PSSR_DOWNSHIFT_STATUS (1 << S_PSSR_DOWNSHIFT_STATUS)
+
+#define S_PSSR_MDI 6
+#define V_PSSR_MDI (1 << S_PSSR_MDI)
+
+#define S_PSSR_CABLE_LEN 7
+#define M_PSSR_CABLE_LEN 0x7
+#define V_PSSR_CABLE_LEN(x) ((x) << S_PSSR_CABLE_LEN)
+#define G_PSSR_CABLE_LEN(x) (((x) >> S_PSSR_CABLE_LEN) & M_PSSR_CABLE_LEN)
+
+//#define S_PSSR_LINK 10
+//#define S_PSSR_LINK 13
+#define S_PSSR_LINK 2
+#define V_PSSR_LINK (1 << S_PSSR_LINK)
+
+//#define S_PSSR_STATUS_RESOLVED 11
+//#define S_PSSR_STATUS_RESOLVED 10
+#define S_PSSR_STATUS_RESOLVED 15
+#define V_PSSR_STATUS_RESOLVED (1 << S_PSSR_STATUS_RESOLVED)
+
+#define S_PSSR_PAGE_RECEIVED 12
+#define V_PSSR_PAGE_RECEIVED (1 << S_PSSR_PAGE_RECEIVED)
+
+//#define S_PSSR_DUPLEX 13
+//#define S_PSSR_DUPLEX 12
+#define S_PSSR_DUPLEX 5
+#define V_PSSR_DUPLEX (1 << S_PSSR_DUPLEX)
+
+//#define S_PSSR_SPEED 14
+//#define S_PSSR_SPEED 14
+#define S_PSSR_SPEED 3
+#define M_PSSR_SPEED 0x3
+#define V_PSSR_SPEED(x) ((x) << S_PSSR_SPEED)
+#define G_PSSR_SPEED(x) (((x) >> S_PSSR_SPEED) & M_PSSR_SPEED)
+
+#endif
diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c
index 4ffc9b44a8e1..dec70c2b374a 100644
--- a/drivers/net/cs89x0.c
+++ b/drivers/net/cs89x0.c
@@ -588,10 +588,10 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
goto out2;
}
}
- printk(KERN_DEBUG "PP_addr at %x[%x]: 0x%x\n",
- ioaddr, ADD_PORT, readword(ioaddr, ADD_PORT));
ioaddr &= ~3;
+ printk(KERN_DEBUG "PP_addr at %x[%x]: 0x%x\n",
+ ioaddr, ADD_PORT, readword(ioaddr, ADD_PORT));
writeword(ioaddr, ADD_PORT, PP_ChipID);
tmp = readword(ioaddr, DATA_PORT);
diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c
index 8f514cc0debd..dc3ab3b5c8cb 100644
--- a/drivers/net/defxx.c
+++ b/drivers/net/defxx.c
@@ -192,6 +192,7 @@
* 04 Aug 2003 macro Converted to the DMA API.
* 14 Aug 2004 macro Fix device names reported.
* 14 Jun 2005 macro Use irqreturn_t.
+ * 23 Oct 2006 macro Big-endian host support.
*/
/* Include files */
@@ -218,8 +219,8 @@
/* Version information string should be updated prior to each new release! */
#define DRV_NAME "defxx"
-#define DRV_VERSION "v1.08"
-#define DRV_RELDATE "2005/06/14"
+#define DRV_VERSION "v1.09"
+#define DRV_RELDATE "2006/10/23"
static char version[] __devinitdata =
DRV_NAME ": " DRV_VERSION " " DRV_RELDATE
@@ -859,6 +860,7 @@ static int __devinit dfx_driver_init(struct net_device *dev,
print_name);
return(DFX_K_FAILURE);
}
+ data = cpu_to_le32(data);
memcpy(&bp->factory_mac_addr[0], &data, sizeof(u32));
if (dfx_hw_port_ctrl_req(bp, PI_PCTRL_M_MLA, PI_PDATA_A_MLA_K_HI, 0,
@@ -867,6 +869,7 @@ static int __devinit dfx_driver_init(struct net_device *dev,
print_name);
return(DFX_K_FAILURE);
}
+ data = cpu_to_le32(data);
memcpy(&bp->factory_mac_addr[4], &data, sizeof(u16));
/*
@@ -1085,27 +1088,23 @@ static int dfx_adap_init(DFX_board_t *bp, int get_buffers)
}
/*
- * Set base address of Descriptor Block and bring adapter to DMA_AVAILABLE state
+ * Set the base address of Descriptor Block and bring adapter
+ * to DMA_AVAILABLE state.
*
- * Note: We also set the literal and data swapping requirements in this
- * command. Since this driver presently runs on Intel platforms
- * which are Little Endian, we'll tell the adapter to byte swap
- * data only. This code will need to change when we support
- * Big Endian systems (eg. PowerPC).
+ * Note: We also set the literal and data swapping requirements
+ * in this command.
*
- * Assumption: 32-bit physical address of descriptor block is 8Kbyte
- * aligned. That is, bits 0-12 of the address must be zero.
+ * Assumption: 32-bit physical address of descriptor block
+ * is 8Kbyte aligned.
*/
-
- if (dfx_hw_port_ctrl_req(bp,
- PI_PCTRL_M_INIT,
- (u32) (bp->descr_block_phys | PI_PDATA_A_INIT_M_BSWAP_DATA),
- 0,
- NULL) != DFX_K_SUCCESS)
- {
- printk("%s: Could not set descriptor block address!\n", bp->dev->name);
- return(DFX_K_FAILURE);
- }
+ if (dfx_hw_port_ctrl_req(bp, PI_PCTRL_M_INIT,
+ (u32)(bp->descr_block_phys |
+ PI_PDATA_A_INIT_M_BSWAP_INIT),
+ 0, NULL) != DFX_K_SUCCESS) {
+ printk("%s: Could not set descriptor block address!\n",
+ bp->dev->name);
+ return DFX_K_FAILURE;
+ }
/* Set transmit flush timeout value */
diff --git a/drivers/net/defxx.h b/drivers/net/defxx.h
index 8b1e9a11ca21..2ce8f97253eb 100644
--- a/drivers/net/defxx.h
+++ b/drivers/net/defxx.h
@@ -25,6 +25,7 @@
* macros to DEFXX.C.
* 12-Sep-96 LVS Removed packet request header pointers.
* 04 Aug 2003 macro Converted to the DMA API.
+ * 23 Oct 2006 macro Big-endian host support.
*/
#ifndef _DEFXX_H_
@@ -1344,7 +1345,7 @@ typedef struct
/* Register definition structures are defined for both big and little endian systems */
-#ifndef BIG_ENDIAN
+#ifndef __BIG_ENDIAN
/* Little endian format of Type 1 Producer register */
@@ -1402,7 +1403,11 @@ typedef union
} index;
} PI_TYPE_2_CONSUMER;
-#else
+/* Define swapping required by DMA transfers. */
+#define PI_PDATA_A_INIT_M_BSWAP_INIT \
+ (PI_PDATA_A_INIT_M_BSWAP_DATA)
+
+#else /* __BIG_ENDIAN */
/* Big endian format of Type 1 Producer register */
@@ -1460,7 +1465,11 @@ typedef union
} index;
} PI_TYPE_2_CONSUMER;
-#endif /* #ifndef BIG_ENDIAN */
+/* Define swapping required by DMA transfers. */
+#define PI_PDATA_A_INIT_M_BSWAP_INIT \
+ (PI_PDATA_A_INIT_M_BSWAP_DATA | PI_PDATA_A_INIT_M_BSWAP_LITERAL)
+
+#endif /* __BIG_ENDIAN */
/* Define EISA controller register offsets */
diff --git a/drivers/net/depca.c b/drivers/net/depca.c
index f87f6e3dc721..5113eef755b9 100644
--- a/drivers/net/depca.c
+++ b/drivers/net/depca.c
@@ -1252,24 +1252,22 @@ static void set_multicast_list(struct net_device *dev)
struct depca_private *lp = (struct depca_private *) dev->priv;
u_long ioaddr = dev->base_addr;
- if (dev) {
- netif_stop_queue(dev);
- while (lp->tx_old != lp->tx_new); /* Wait for the ring to empty */
-
- STOP_DEPCA; /* Temporarily stop the depca. */
- depca_init_ring(dev); /* Initialize the descriptor rings */
+ netif_stop_queue(dev);
+ while (lp->tx_old != lp->tx_new); /* Wait for the ring to empty */
- if (dev->flags & IFF_PROMISC) { /* Set promiscuous mode */
- lp->init_block.mode |= PROM;
- } else {
- SetMulticastFilter(dev);
- lp->init_block.mode &= ~PROM; /* Unset promiscuous mode */
- }
+ STOP_DEPCA; /* Temporarily stop the depca. */
+ depca_init_ring(dev); /* Initialize the descriptor rings */
- LoadCSRs(dev); /* Reload CSR3 */
- InitRestartDepca(dev); /* Resume normal operation. */
- netif_start_queue(dev); /* Unlock the TX ring */
+ if (dev->flags & IFF_PROMISC) { /* Set promiscuous mode */
+ lp->init_block.mode |= PROM;
+ } else {
+ SetMulticastFilter(dev);
+ lp->init_block.mode &= ~PROM; /* Unset promiscuous mode */
}
+
+ LoadCSRs(dev); /* Reload CSR3 */
+ InitRestartDepca(dev); /* Resume normal operation. */
+ netif_start_queue(dev); /* Unlock the TX ring */
}
/*
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index e7737d02bb05..03bf164f9e8d 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -1215,7 +1215,7 @@ static void e100_setup_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb
* the literal in the instruction before the code is loaded, the
* driver can change the algorithm.
*
-* INTDELAY - This loads the dead-man timer with its inital value.
+* INTDELAY - This loads the dead-man timer with its initial value.
* When this timer expires the interrupt is asserted, and the
* timer is reset each time a new packet is received. (see
* BUNDLEMAX below to set the limit on number of chained packets)
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index 7ecce438d258..f091042b146e 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -59,6 +59,9 @@
#include <linux/capability.h>
#include <linux/in.h>
#include <linux/ip.h>
+#ifdef NETIF_F_TSO6
+#include <linux/ipv6.h>
+#endif
#include <linux/tcp.h>
#include <linux/udp.h>
#include <net/pkt_sched.h>
@@ -254,6 +257,17 @@ struct e1000_adapter {
spinlock_t tx_queue_lock;
#endif
atomic_t irq_sem;
+ unsigned int detect_link;
+ unsigned int total_tx_bytes;
+ unsigned int total_tx_packets;
+ unsigned int total_rx_bytes;
+ unsigned int total_rx_packets;
+ /* Interrupt Throttle Rate */
+ uint32_t itr;
+ uint32_t itr_setting;
+ uint16_t tx_itr;
+ uint16_t rx_itr;
+
struct work_struct reset_task;
uint8_t fc_autoneg;
@@ -262,6 +276,7 @@ struct e1000_adapter {
/* TX */
struct e1000_tx_ring *tx_ring; /* One per active queue */
+ unsigned int restart_queue;
unsigned long tx_queue_len;
uint32_t txd_cmd;
uint32_t tx_int_delay;
@@ -310,8 +325,6 @@ struct e1000_adapter {
uint64_t gorcl_old;
uint16_t rx_ps_bsize0;
- /* Interrupt Throttle Rate */
- uint32_t itr;
/* OS defined structs */
struct net_device *netdev;
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index c564adbd669b..da459f7177c6 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -85,6 +85,7 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
{ "tx_single_coll_ok", E1000_STAT(stats.scc) },
{ "tx_multi_coll_ok", E1000_STAT(stats.mcc) },
{ "tx_timeout_count", E1000_STAT(tx_timeout_count) },
+ { "tx_restart_queue", E1000_STAT(restart_queue) },
{ "rx_long_length_errors", E1000_STAT(stats.roc) },
{ "rx_short_length_errors", E1000_STAT(stats.ruc) },
{ "rx_align_errors", E1000_STAT(stats.algnerrc) },
@@ -133,9 +134,7 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
if (hw->autoneg == 1) {
ecmd->advertising |= ADVERTISED_Autoneg;
-
/* the e1000 autoneg seems to match ethtool nicely */
-
ecmd->advertising |= hw->autoneg_advertised;
}
@@ -285,7 +284,7 @@ e1000_set_pauseparam(struct net_device *netdev,
e1000_reset(adapter);
} else
retval = ((hw->media_type == e1000_media_type_fiber) ?
- e1000_setup_link(hw) : e1000_force_mac_fc(hw));
+ e1000_setup_link(hw) : e1000_force_mac_fc(hw));
clear_bit(__E1000_RESETTING, &adapter->flags);
return retval;
@@ -350,6 +349,13 @@ e1000_set_tso(struct net_device *netdev, uint32_t data)
else
netdev->features &= ~NETIF_F_TSO;
+#ifdef NETIF_F_TSO6
+ if (data)
+ netdev->features |= NETIF_F_TSO6;
+ else
+ netdev->features &= ~NETIF_F_TSO6;
+#endif
+
DPRINTK(PROBE, INFO, "TSO is %s\n", data ? "Enabled" : "Disabled");
adapter->tso_force = TRUE;
return 0;
@@ -774,7 +780,7 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
/* The status register is Read Only, so a write should fail.
* Some bits that get toggled are ignored.
*/
- switch (adapter->hw.mac_type) {
+ switch (adapter->hw.mac_type) {
/* there are several bits on newer hardware that are r/w */
case e1000_82571:
case e1000_82572:
@@ -802,12 +808,14 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
}
/* restore previous status */
E1000_WRITE_REG(&adapter->hw, STATUS, before);
+
if (adapter->hw.mac_type != e1000_ich8lan) {
REG_PATTERN_TEST(FCAL, 0xFFFFFFFF, 0xFFFFFFFF);
REG_PATTERN_TEST(FCAH, 0x0000FFFF, 0xFFFFFFFF);
REG_PATTERN_TEST(FCT, 0x0000FFFF, 0xFFFFFFFF);
REG_PATTERN_TEST(VET, 0x0000FFFF, 0xFFFFFFFF);
}
+
REG_PATTERN_TEST(RDTR, 0x0000FFFF, 0xFFFFFFFF);
REG_PATTERN_TEST(RDBAH, 0xFFFFFFFF, 0xFFFFFFFF);
REG_PATTERN_TEST(RDLEN, 0x000FFF80, 0x000FFFFF);
@@ -820,8 +828,9 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
REG_PATTERN_TEST(TDLEN, 0x000FFF80, 0x000FFFFF);
REG_SET_AND_CHECK(RCTL, 0xFFFFFFFF, 0x00000000);
+
before = (adapter->hw.mac_type == e1000_ich8lan ?
- 0x06C3B33E : 0x06DFB3FE);
+ 0x06C3B33E : 0x06DFB3FE);
REG_SET_AND_CHECK(RCTL, before, 0x003FFFFB);
REG_SET_AND_CHECK(TCTL, 0xFFFFFFFF, 0x00000000);
@@ -834,10 +843,10 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
REG_PATTERN_TEST(TDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
REG_PATTERN_TEST(TIDV, 0x0000FFFF, 0x0000FFFF);
value = (adapter->hw.mac_type == e1000_ich8lan ?
- E1000_RAR_ENTRIES_ICH8LAN : E1000_RAR_ENTRIES);
+ E1000_RAR_ENTRIES_ICH8LAN : E1000_RAR_ENTRIES);
for (i = 0; i < value; i++) {
REG_PATTERN_TEST(RA + (((i << 1) + 1) << 2), 0x8003FFFF,
- 0xFFFFFFFF);
+ 0xFFFFFFFF);
}
} else {
@@ -883,8 +892,7 @@ e1000_eeprom_test(struct e1000_adapter *adapter, uint64_t *data)
}
static irqreturn_t
-e1000_test_intr(int irq,
- void *data)
+e1000_test_intr(int irq, void *data)
{
struct net_device *netdev = (struct net_device *) data;
struct e1000_adapter *adapter = netdev_priv(netdev);
@@ -905,11 +913,11 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
/* NOTE: we don't test MSI interrupts here, yet */
/* Hook up test interrupt handler just for this test */
- if (!request_irq(irq, &e1000_test_intr, IRQF_PROBE_SHARED,
- netdev->name, netdev))
+ if (!request_irq(irq, &e1000_test_intr, IRQF_PROBE_SHARED, netdev->name,
+ netdev))
shared_int = FALSE;
else if (request_irq(irq, &e1000_test_intr, IRQF_SHARED,
- netdev->name, netdev)) {
+ netdev->name, netdev)) {
*data = 1;
return -1;
}
@@ -925,6 +933,7 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
if (adapter->hw.mac_type == e1000_ich8lan && i == 8)
continue;
+
/* Interrupt to test */
mask = 1 << i;
@@ -1674,7 +1683,7 @@ e1000_diag_test(struct net_device *netdev,
if (e1000_link_test(adapter, &data[4]))
eth_test->flags |= ETH_TEST_FL_FAILED;
- /* Offline tests aren't run; pass by default */
+ /* Online tests aren't run; pass by default */
data[0] = 0;
data[1] = 0;
data[2] = 0;
@@ -1717,6 +1726,7 @@ static int e1000_wol_exclusion(struct e1000_adapter *adapter, struct ethtool_wol
retval = 0;
break;
case E1000_DEV_ID_82571EB_QUAD_COPPER:
+ case E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE:
case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
/* quad port adapters only support WoL on port A */
if (!adapter->quad_port_a) {
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
index 65077f39da69..3655d902b0bd 100644
--- a/drivers/net/e1000/e1000_hw.c
+++ b/drivers/net/e1000/e1000_hw.c
@@ -385,6 +385,7 @@ e1000_set_mac_type(struct e1000_hw *hw)
case E1000_DEV_ID_82571EB_FIBER:
case E1000_DEV_ID_82571EB_SERDES:
case E1000_DEV_ID_82571EB_QUAD_COPPER:
+ case E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE:
hw->mac_type = e1000_82571;
break;
case E1000_DEV_ID_82572EI_COPPER:
@@ -408,6 +409,8 @@ e1000_set_mac_type(struct e1000_hw *hw)
case E1000_DEV_ID_ICH8_IGP_AMT:
case E1000_DEV_ID_ICH8_IGP_C:
case E1000_DEV_ID_ICH8_IFE:
+ case E1000_DEV_ID_ICH8_IFE_GT:
+ case E1000_DEV_ID_ICH8_IFE_G:
case E1000_DEV_ID_ICH8_IGP_M:
hw->mac_type = e1000_ich8lan;
break;
@@ -2367,6 +2370,7 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw)
/* Need to reset the PHY or these changes will be ignored */
mii_ctrl_reg |= MII_CR_RESET;
+
/* Disable MDI-X support for 10/100 */
} else if (hw->phy_type == e1000_phy_ife) {
ret_val = e1000_read_phy_reg(hw, IFE_PHY_MDIX_CONTROL, &phy_data);
@@ -2379,6 +2383,7 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw)
ret_val = e1000_write_phy_reg(hw, IFE_PHY_MDIX_CONTROL, phy_data);
if (ret_val)
return ret_val;
+
} else {
/* Clear Auto-Crossover to force MDI manually. IGP requires MDI
* forced whenever speed or duplex are forced.
@@ -3868,7 +3873,7 @@ e1000_phy_hw_reset(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*
-* Sets bit 15 of the MII Control regiser
+* Sets bit 15 of the MII Control register
******************************************************************************/
int32_t
e1000_phy_reset(struct e1000_hw *hw)
@@ -3940,14 +3945,15 @@ e1000_phy_powerdown_workaround(struct e1000_hw *hw)
E1000_WRITE_REG(hw, PHY_CTRL, reg | E1000_PHY_CTRL_GBE_DISABLE |
E1000_PHY_CTRL_NOND0A_GBE_DISABLE);
- /* Write VR power-down enable */
+ /* Write VR power-down enable - bits 9:8 should be 10b */
e1000_read_phy_reg(hw, IGP3_VR_CTRL, &phy_data);
- e1000_write_phy_reg(hw, IGP3_VR_CTRL, phy_data |
- IGP3_VR_CTRL_MODE_SHUT);
+ phy_data |= (1 << 9);
+ phy_data &= ~(1 << 8);
+ e1000_write_phy_reg(hw, IGP3_VR_CTRL, phy_data);
/* Read it back and test */
e1000_read_phy_reg(hw, IGP3_VR_CTRL, &phy_data);
- if ((phy_data & IGP3_VR_CTRL_MODE_SHUT) || retry)
+ if (((phy_data & IGP3_VR_CTRL_MODE_MASK) == IGP3_VR_CTRL_MODE_SHUT) || retry)
break;
/* Issue PHY reset and repeat at most one more time */
@@ -4549,7 +4555,7 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
case e1000_ich8lan:
{
int32_t i = 0;
- uint32_t flash_size = E1000_READ_ICH8_REG(hw, ICH8_FLASH_GFPREG);
+ uint32_t flash_size = E1000_READ_ICH_FLASH_REG(hw, ICH_FLASH_GFPREG);
eeprom->type = e1000_eeprom_ich8;
eeprom->use_eerd = FALSE;
@@ -4565,12 +4571,14 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
}
}
- hw->flash_base_addr = (flash_size & ICH8_GFPREG_BASE_MASK) *
- ICH8_FLASH_SECTOR_SIZE;
+ hw->flash_base_addr = (flash_size & ICH_GFPREG_BASE_MASK) *
+ ICH_FLASH_SECTOR_SIZE;
+
+ hw->flash_bank_size = ((flash_size >> 16) & ICH_GFPREG_BASE_MASK) + 1;
+ hw->flash_bank_size -= (flash_size & ICH_GFPREG_BASE_MASK);
+
+ hw->flash_bank_size *= ICH_FLASH_SECTOR_SIZE;
- hw->flash_bank_size = ((flash_size >> 16) & ICH8_GFPREG_BASE_MASK) + 1;
- hw->flash_bank_size -= (flash_size & ICH8_GFPREG_BASE_MASK);
- hw->flash_bank_size *= ICH8_FLASH_SECTOR_SIZE;
hw->flash_bank_size /= 2 * sizeof(uint16_t);
break;
@@ -5620,8 +5628,8 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
* signature is valid. We want to do this after the write
* has completed so that we don't mark the segment valid
* while the write is still in progress */
- if (i == E1000_ICH8_NVM_SIG_WORD)
- high_byte = E1000_ICH8_NVM_SIG_MASK | high_byte;
+ if (i == E1000_ICH_NVM_SIG_WORD)
+ high_byte = E1000_ICH_NVM_SIG_MASK | high_byte;
error = e1000_verify_write_ich8_byte(hw,
(i << 1) + new_bank_offset + 1, high_byte);
@@ -5643,18 +5651,18 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
* erase as well since these bits are 11 to start with
* and we need to change bit 14 to 0b */
e1000_read_ich8_byte(hw,
- E1000_ICH8_NVM_SIG_WORD * 2 + 1 + new_bank_offset,
+ E1000_ICH_NVM_SIG_WORD * 2 + 1 + new_bank_offset,
&high_byte);
high_byte &= 0xBF;
error = e1000_verify_write_ich8_byte(hw,
- E1000_ICH8_NVM_SIG_WORD * 2 + 1 + new_bank_offset, high_byte);
+ E1000_ICH_NVM_SIG_WORD * 2 + 1 + new_bank_offset, high_byte);
/* And invalidate the previously valid segment by setting
* its signature word (0x13) high_byte to 0b. This can be
* done without an erase because flash erase sets all bits
* to 1's. We can write 1's to 0's without an erase */
if (error == E1000_SUCCESS) {
error = e1000_verify_write_ich8_byte(hw,
- E1000_ICH8_NVM_SIG_WORD * 2 + 1 + old_bank_offset, 0);
+ E1000_ICH_NVM_SIG_WORD * 2 + 1 + old_bank_offset, 0);
}
/* Clear the now not used entry in the cache */
@@ -5841,6 +5849,7 @@ e1000_mta_set(struct e1000_hw *hw,
hash_reg = (hash_value >> 5) & 0x7F;
if (hw->mac_type == e1000_ich8lan)
hash_reg &= 0x1F;
+
hash_bit = hash_value & 0x1F;
mta = E1000_READ_REG_ARRAY(hw, MTA, hash_reg);
@@ -6026,6 +6035,7 @@ e1000_id_led_init(struct e1000_hw * hw)
else
eeprom_data = ID_LED_DEFAULT;
}
+
for (i = 0; i < 4; i++) {
temp = (eeprom_data >> (i << 2)) & led_mask;
switch (temp) {
@@ -8486,7 +8496,7 @@ e1000_ich8_cycle_init(struct e1000_hw *hw)
DEBUGFUNC("e1000_ich8_cycle_init");
- hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFSTS);
+ hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS);
/* May be check the Flash Des Valid bit in Hw status */
if (hsfsts.hsf_status.fldesvalid == 0) {
@@ -8499,7 +8509,7 @@ e1000_ich8_cycle_init(struct e1000_hw *hw)
hsfsts.hsf_status.flcerr = 1;
hsfsts.hsf_status.dael = 1;
- E1000_WRITE_ICH8_REG16(hw, ICH8_FLASH_HSFSTS, hsfsts.regval);
+ E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval);
/* Either we should have a hardware SPI cycle in progress bit to check
* against, in order to start a new cycle or FDONE bit should be changed
@@ -8514,13 +8524,13 @@ e1000_ich8_cycle_init(struct e1000_hw *hw)
/* There is no cycle running at present, so we can start a cycle */
/* Begin by setting Flash Cycle Done. */
hsfsts.hsf_status.flcdone = 1;
- E1000_WRITE_ICH8_REG16(hw, ICH8_FLASH_HSFSTS, hsfsts.regval);
+ E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval);
error = E1000_SUCCESS;
} else {
/* otherwise poll for sometime so the current cycle has a chance
* to end before giving up. */
- for (i = 0; i < ICH8_FLASH_COMMAND_TIMEOUT; i++) {
- hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFSTS);
+ for (i = 0; i < ICH_FLASH_COMMAND_TIMEOUT; i++) {
+ hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS);
if (hsfsts.hsf_status.flcinprog == 0) {
error = E1000_SUCCESS;
break;
@@ -8531,7 +8541,7 @@ e1000_ich8_cycle_init(struct e1000_hw *hw)
/* Successful in waiting for previous cycle to timeout,
* now set the Flash Cycle Done. */
hsfsts.hsf_status.flcdone = 1;
- E1000_WRITE_ICH8_REG16(hw, ICH8_FLASH_HSFSTS, hsfsts.regval);
+ E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval);
} else {
DEBUGOUT("Flash controller busy, cannot get access");
}
@@ -8553,13 +8563,13 @@ e1000_ich8_flash_cycle(struct e1000_hw *hw, uint32_t timeout)
uint32_t i = 0;
/* Start a cycle by writing 1 in Flash Cycle Go in Hw Flash Control */
- hsflctl.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFCTL);
+ hsflctl.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL);
hsflctl.hsf_ctrl.flcgo = 1;
- E1000_WRITE_ICH8_REG16(hw, ICH8_FLASH_HSFCTL, hsflctl.regval);
+ E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval);
/* wait till FDONE bit is set to 1 */
do {
- hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFSTS);
+ hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS);
if (hsfsts.hsf_status.flcdone == 1)
break;
udelay(1);
@@ -8593,10 +8603,10 @@ e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index,
DEBUGFUNC("e1000_read_ich8_data");
if (size < 1 || size > 2 || data == 0x0 ||
- index > ICH8_FLASH_LINEAR_ADDR_MASK)
+ index > ICH_FLASH_LINEAR_ADDR_MASK)
return error;
- flash_linear_address = (ICH8_FLASH_LINEAR_ADDR_MASK & index) +
+ flash_linear_address = (ICH_FLASH_LINEAR_ADDR_MASK & index) +
hw->flash_base_addr;
do {
@@ -8606,25 +8616,25 @@ e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index,
if (error != E1000_SUCCESS)
break;
- hsflctl.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFCTL);
+ hsflctl.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL);
/* 0b/1b corresponds to 1 or 2 byte size, respectively. */
hsflctl.hsf_ctrl.fldbcount = size - 1;
- hsflctl.hsf_ctrl.flcycle = ICH8_CYCLE_READ;
- E1000_WRITE_ICH8_REG16(hw, ICH8_FLASH_HSFCTL, hsflctl.regval);
+ hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_READ;
+ E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval);
/* Write the last 24 bits of index into Flash Linear address field in
* Flash Address */
/* TODO: TBD maybe check the index against the size of flash */
- E1000_WRITE_ICH8_REG(hw, ICH8_FLASH_FADDR, flash_linear_address);
+ E1000_WRITE_ICH_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_address);
- error = e1000_ich8_flash_cycle(hw, ICH8_FLASH_COMMAND_TIMEOUT);
+ error = e1000_ich8_flash_cycle(hw, ICH_FLASH_COMMAND_TIMEOUT);
/* Check if FCERR is set to 1, if set to 1, clear it and try the whole
* sequence a few more times, else read in (shift in) the Flash Data0,
* the order is least significant byte first msb to lsb */
if (error == E1000_SUCCESS) {
- flash_data = E1000_READ_ICH8_REG(hw, ICH8_FLASH_FDATA0);
+ flash_data = E1000_READ_ICH_FLASH_REG(hw, ICH_FLASH_FDATA0);
if (size == 1) {
*data = (uint8_t)(flash_data & 0x000000FF);
} else if (size == 2) {
@@ -8634,9 +8644,9 @@ e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index,
} else {
/* If we've gotten here, then things are probably completely hosed,
* but if the error condition is detected, it won't hurt to give
- * it another try...ICH8_FLASH_CYCLE_REPEAT_COUNT times.
+ * it another try...ICH_FLASH_CYCLE_REPEAT_COUNT times.
*/
- hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFSTS);
+ hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS);
if (hsfsts.hsf_status.flcerr == 1) {
/* Repeat for some time before giving up. */
continue;
@@ -8645,7 +8655,7 @@ e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index,
break;
}
}
- } while (count++ < ICH8_FLASH_CYCLE_REPEAT_COUNT);
+ } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT);
return error;
}
@@ -8672,10 +8682,10 @@ e1000_write_ich8_data(struct e1000_hw *hw, uint32_t index, uint32_t size,
DEBUGFUNC("e1000_write_ich8_data");
if (size < 1 || size > 2 || data > size * 0xff ||
- index > ICH8_FLASH_LINEAR_ADDR_MASK)
+ index > ICH_FLASH_LINEAR_ADDR_MASK)
return error;
- flash_linear_address = (ICH8_FLASH_LINEAR_ADDR_MASK & index) +
+ flash_linear_address = (ICH_FLASH_LINEAR_ADDR_MASK & index) +
hw->flash_base_addr;
do {
@@ -8685,34 +8695,34 @@ e1000_write_ich8_data(struct e1000_hw *hw, uint32_t index, uint32_t size,
if (error != E1000_SUCCESS)
break;
- hsflctl.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFCTL);
+ hsflctl.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL);
/* 0b/1b corresponds to 1 or 2 byte size, respectively. */
hsflctl.hsf_ctrl.fldbcount = size -1;
- hsflctl.hsf_ctrl.flcycle = ICH8_CYCLE_WRITE;
- E1000_WRITE_ICH8_REG16(hw, ICH8_FLASH_HSFCTL, hsflctl.regval);
+ hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE;
+ E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval);
/* Write the last 24 bits of index into Flash Linear address field in
* Flash Address */
- E1000_WRITE_ICH8_REG(hw, ICH8_FLASH_FADDR, flash_linear_address);
+ E1000_WRITE_ICH_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_address);
if (size == 1)
flash_data = (uint32_t)data & 0x00FF;
else
flash_data = (uint32_t)data;
- E1000_WRITE_ICH8_REG(hw, ICH8_FLASH_FDATA0, flash_data);
+ E1000_WRITE_ICH_FLASH_REG(hw, ICH_FLASH_FDATA0, flash_data);
/* check if FCERR is set to 1 , if set to 1, clear it and try the whole
* sequence a few more times else done */
- error = e1000_ich8_flash_cycle(hw, ICH8_FLASH_COMMAND_TIMEOUT);
+ error = e1000_ich8_flash_cycle(hw, ICH_FLASH_COMMAND_TIMEOUT);
if (error == E1000_SUCCESS) {
break;
} else {
/* If we're here, then things are most likely completely hosed,
* but if the error condition is detected, it won't hurt to give
- * it another try...ICH8_FLASH_CYCLE_REPEAT_COUNT times.
+ * it another try...ICH_FLASH_CYCLE_REPEAT_COUNT times.
*/
- hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFSTS);
+ hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS);
if (hsfsts.hsf_status.flcerr == 1) {
/* Repeat for some time before giving up. */
continue;
@@ -8721,7 +8731,7 @@ e1000_write_ich8_data(struct e1000_hw *hw, uint32_t index, uint32_t size,
break;
}
}
- } while (count++ < ICH8_FLASH_CYCLE_REPEAT_COUNT);
+ } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT);
return error;
}
@@ -8840,7 +8850,7 @@ e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t bank)
int32_t j = 0;
int32_t error_flag = 0;
- hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFSTS);
+ hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS);
/* Determine HW Sector size: Read BERASE bits of Hw flash Status register */
/* 00: The Hw sector is 256 bytes, hence we need to erase 16
@@ -8853,19 +8863,14 @@ e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t bank)
* 11: The Hw sector size is 64K bytes */
if (hsfsts.hsf_status.berasesz == 0x0) {
/* Hw sector size 256 */
- sub_sector_size = ICH8_FLASH_SEG_SIZE_256;
- bank_size = ICH8_FLASH_SECTOR_SIZE;
- iteration = ICH8_FLASH_SECTOR_SIZE / ICH8_FLASH_SEG_SIZE_256;
+ sub_sector_size = ICH_FLASH_SEG_SIZE_256;
+ bank_size = ICH_FLASH_SECTOR_SIZE;
+ iteration = ICH_FLASH_SECTOR_SIZE / ICH_FLASH_SEG_SIZE_256;
} else if (hsfsts.hsf_status.berasesz == 0x1) {
- bank_size = ICH8_FLASH_SEG_SIZE_4K;
- iteration = 1;
- } else if (hw->mac_type != e1000_ich8lan &&
- hsfsts.hsf_status.berasesz == 0x2) {
- /* 8K erase size invalid for ICH8 - added in for ICH9 */
- bank_size = ICH9_FLASH_SEG_SIZE_8K;
+ bank_size = ICH_FLASH_SEG_SIZE_4K;
iteration = 1;
} else if (hsfsts.hsf_status.berasesz == 0x3) {
- bank_size = ICH8_FLASH_SEG_SIZE_64K;
+ bank_size = ICH_FLASH_SEG_SIZE_64K;
iteration = 1;
} else {
return error;
@@ -8883,9 +8888,9 @@ e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t bank)
/* Write a value 11 (block Erase) in Flash Cycle field in Hw flash
* Control */
- hsflctl.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFCTL);
- hsflctl.hsf_ctrl.flcycle = ICH8_CYCLE_ERASE;
- E1000_WRITE_ICH8_REG16(hw, ICH8_FLASH_HSFCTL, hsflctl.regval);
+ hsflctl.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL);
+ hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE;
+ E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval);
/* Write the last 24 bits of an index within the block into Flash
* Linear address field in Flash Address. This probably needs to
@@ -8893,17 +8898,17 @@ e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t bank)
* the software bank size (4, 8 or 64 KBytes) */
flash_linear_address = bank * bank_size + j * sub_sector_size;
flash_linear_address += hw->flash_base_addr;
- flash_linear_address &= ICH8_FLASH_LINEAR_ADDR_MASK;
+ flash_linear_address &= ICH_FLASH_LINEAR_ADDR_MASK;
- E1000_WRITE_ICH8_REG(hw, ICH8_FLASH_FADDR, flash_linear_address);
+ E1000_WRITE_ICH_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_address);
- error = e1000_ich8_flash_cycle(hw, ICH8_FLASH_ERASE_TIMEOUT);
+ error = e1000_ich8_flash_cycle(hw, ICH_FLASH_ERASE_TIMEOUT);
/* Check if FCERR is set to 1. If 1, clear it and try the whole
* sequence a few more times else Done */
if (error == E1000_SUCCESS) {
break;
} else {
- hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFSTS);
+ hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS);
if (hsfsts.hsf_status.flcerr == 1) {
/* repeat for some time before giving up */
continue;
@@ -8912,7 +8917,7 @@ e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t bank)
break;
}
}
- } while ((count < ICH8_FLASH_CYCLE_REPEAT_COUNT) && !error_flag);
+ } while ((count < ICH_FLASH_CYCLE_REPEAT_COUNT) && !error_flag);
if (error_flag == 1)
break;
}
@@ -9013,5 +9018,3 @@ e1000_init_lcd_from_nvm(struct e1000_hw *hw)
return E1000_SUCCESS;
}
-
-
diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h
index 449a60303e07..3321fb13bfa9 100644
--- a/drivers/net/e1000/e1000_hw.h
+++ b/drivers/net/e1000/e1000_hw.h
@@ -128,11 +128,13 @@ typedef enum {
/* PCI bus widths */
typedef enum {
e1000_bus_width_unknown = 0,
+ /* These PCIe values should literally match the possible return values
+ * from config space */
+ e1000_bus_width_pciex_1 = 1,
+ e1000_bus_width_pciex_2 = 2,
+ e1000_bus_width_pciex_4 = 4,
e1000_bus_width_32,
e1000_bus_width_64,
- e1000_bus_width_pciex_1,
- e1000_bus_width_pciex_2,
- e1000_bus_width_pciex_4,
e1000_bus_width_reserved
} e1000_bus_width;
@@ -326,6 +328,7 @@ int32_t e1000_phy_hw_reset(struct e1000_hw *hw);
int32_t e1000_phy_reset(struct e1000_hw *hw);
int32_t e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
int32_t e1000_validate_mdi_setting(struct e1000_hw *hw);
+
void e1000_phy_powerdown_workaround(struct e1000_hw *hw);
/* EEPROM Functions */
@@ -390,7 +393,6 @@ int32_t e1000_mng_write_dhcp_info(struct e1000_hw *hw, uint8_t *buffer,
uint16_t length);
boolean_t e1000_check_mng_mode(struct e1000_hw *hw);
boolean_t e1000_enable_tx_pkt_filtering(struct e1000_hw *hw);
-
int32_t e1000_read_eeprom(struct e1000_hw *hw, uint16_t reg, uint16_t words, uint16_t *data);
int32_t e1000_validate_eeprom_checksum(struct e1000_hw *hw);
int32_t e1000_update_eeprom_checksum(struct e1000_hw *hw);
@@ -473,6 +475,7 @@ int32_t e1000_check_phy_reset_block(struct e1000_hw *hw);
#define E1000_DEV_ID_82571EB_FIBER 0x105F
#define E1000_DEV_ID_82571EB_SERDES 0x1060
#define E1000_DEV_ID_82571EB_QUAD_COPPER 0x10A4
+#define E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE 0x10BC
#define E1000_DEV_ID_82572EI_COPPER 0x107D
#define E1000_DEV_ID_82572EI_FIBER 0x107E
#define E1000_DEV_ID_82572EI_SERDES 0x107F
@@ -490,6 +493,8 @@ int32_t e1000_check_phy_reset_block(struct e1000_hw *hw);
#define E1000_DEV_ID_ICH8_IGP_AMT 0x104A
#define E1000_DEV_ID_ICH8_IGP_C 0x104B
#define E1000_DEV_ID_ICH8_IFE 0x104C
+#define E1000_DEV_ID_ICH8_IFE_GT 0x10C4
+#define E1000_DEV_ID_ICH8_IFE_G 0x10C5
#define E1000_DEV_ID_ICH8_IGP_M 0x104D
@@ -576,6 +581,7 @@ int32_t e1000_check_phy_reset_block(struct e1000_hw *hw);
* E1000_RAR_ENTRIES - 1 multicast addresses.
*/
#define E1000_RAR_ENTRIES 15
+
#define E1000_RAR_ENTRIES_ICH8LAN 6
#define MIN_NUMBER_OF_DESCRIPTORS 8
@@ -1335,9 +1341,9 @@ struct e1000_hw_stats {
uint64_t gotch;
uint64_t rnbc;
uint64_t ruc;
+ uint64_t rfc;
uint64_t roc;
uint64_t rlerrc;
- uint64_t rfc;
uint64_t rjc;
uint64_t mgprc;
uint64_t mgpdc;
@@ -1577,8 +1583,8 @@ struct e1000_hw {
#define E1000_HICR_FW_RESET 0xC0
#define E1000_SHADOW_RAM_WORDS 2048
-#define E1000_ICH8_NVM_SIG_WORD 0x13
-#define E1000_ICH8_NVM_SIG_MASK 0xC0
+#define E1000_ICH_NVM_SIG_WORD 0x13
+#define E1000_ICH_NVM_SIG_MASK 0xC0
/* EEPROM Read */
#define E1000_EERD_START 0x00000001 /* Start Read */
@@ -3172,6 +3178,7 @@ struct e1000_host_command_info {
#define IGP3_VR_CTRL \
PHY_REG(776, 18) /* Voltage regulator control register */
#define IGP3_VR_CTRL_MODE_SHUT 0x0200 /* Enter powerdown, shutdown VRs */
+#define IGP3_VR_CTRL_MODE_MASK 0x0300 /* Shutdown VR Mask */
#define IGP3_CAPABILITY \
PHY_REG(776, 19) /* IGP3 Capability Register */
@@ -3256,41 +3263,40 @@ struct e1000_host_command_info {
#define IFE_PSCL_PROBE_LEDS_OFF 0x0006 /* Force LEDs 0 and 2 off */
#define IFE_PSCL_PROBE_LEDS_ON 0x0007 /* Force LEDs 0 and 2 on */
-#define ICH8_FLASH_COMMAND_TIMEOUT 5000 /* 5000 uSecs - adjusted */
-#define ICH8_FLASH_ERASE_TIMEOUT 3000000 /* Up to 3 seconds - worst case */
-#define ICH8_FLASH_CYCLE_REPEAT_COUNT 10 /* 10 cycles */
-#define ICH8_FLASH_SEG_SIZE_256 256
-#define ICH8_FLASH_SEG_SIZE_4K 4096
-#define ICH9_FLASH_SEG_SIZE_8K 8192
-#define ICH8_FLASH_SEG_SIZE_64K 65536
-
-#define ICH8_CYCLE_READ 0x0
-#define ICH8_CYCLE_RESERVED 0x1
-#define ICH8_CYCLE_WRITE 0x2
-#define ICH8_CYCLE_ERASE 0x3
-
-#define ICH8_FLASH_GFPREG 0x0000
-#define ICH8_FLASH_HSFSTS 0x0004
-#define ICH8_FLASH_HSFCTL 0x0006
-#define ICH8_FLASH_FADDR 0x0008
-#define ICH8_FLASH_FDATA0 0x0010
-#define ICH8_FLASH_FRACC 0x0050
-#define ICH8_FLASH_FREG0 0x0054
-#define ICH8_FLASH_FREG1 0x0058
-#define ICH8_FLASH_FREG2 0x005C
-#define ICH8_FLASH_FREG3 0x0060
-#define ICH8_FLASH_FPR0 0x0074
-#define ICH8_FLASH_FPR1 0x0078
-#define ICH8_FLASH_SSFSTS 0x0090
-#define ICH8_FLASH_SSFCTL 0x0092
-#define ICH8_FLASH_PREOP 0x0094
-#define ICH8_FLASH_OPTYPE 0x0096
-#define ICH8_FLASH_OPMENU 0x0098
-
-#define ICH8_FLASH_REG_MAPSIZE 0x00A0
-#define ICH8_FLASH_SECTOR_SIZE 4096
-#define ICH8_GFPREG_BASE_MASK 0x1FFF
-#define ICH8_FLASH_LINEAR_ADDR_MASK 0x00FFFFFF
+#define ICH_FLASH_COMMAND_TIMEOUT 5000 /* 5000 uSecs - adjusted */
+#define ICH_FLASH_ERASE_TIMEOUT 3000000 /* Up to 3 seconds - worst case */
+#define ICH_FLASH_CYCLE_REPEAT_COUNT 10 /* 10 cycles */
+#define ICH_FLASH_SEG_SIZE_256 256
+#define ICH_FLASH_SEG_SIZE_4K 4096
+#define ICH_FLASH_SEG_SIZE_64K 65536
+
+#define ICH_CYCLE_READ 0x0
+#define ICH_CYCLE_RESERVED 0x1
+#define ICH_CYCLE_WRITE 0x2
+#define ICH_CYCLE_ERASE 0x3
+
+#define ICH_FLASH_GFPREG 0x0000
+#define ICH_FLASH_HSFSTS 0x0004
+#define ICH_FLASH_HSFCTL 0x0006
+#define ICH_FLASH_FADDR 0x0008
+#define ICH_FLASH_FDATA0 0x0010
+#define ICH_FLASH_FRACC 0x0050
+#define ICH_FLASH_FREG0 0x0054
+#define ICH_FLASH_FREG1 0x0058
+#define ICH_FLASH_FREG2 0x005C
+#define ICH_FLASH_FREG3 0x0060
+#define ICH_FLASH_FPR0 0x0074
+#define ICH_FLASH_FPR1 0x0078
+#define ICH_FLASH_SSFSTS 0x0090
+#define ICH_FLASH_SSFCTL 0x0092
+#define ICH_FLASH_PREOP 0x0094
+#define ICH_FLASH_OPTYPE 0x0096
+#define ICH_FLASH_OPMENU 0x0098
+
+#define ICH_FLASH_REG_MAPSIZE 0x00A0
+#define ICH_FLASH_SECTOR_SIZE 4096
+#define ICH_GFPREG_BASE_MASK 0x1FFF
+#define ICH_FLASH_LINEAR_ADDR_MASK 0x00FFFFFF
/* ICH8 GbE Flash Hardware Sequencing Flash Status Register bit breakdown */
/* Offset 04h HSFSTS */
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 03294400bc90..73f3a85fd238 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -27,6 +27,7 @@
*******************************************************************************/
#include "e1000.h"
+#include <net/ip6_checksum.h>
char e1000_driver_name[] = "e1000";
static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
@@ -35,7 +36,7 @@ static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
#else
#define DRIVERNAPI "-NAPI"
#endif
-#define DRV_VERSION "7.2.9-k4"DRIVERNAPI
+#define DRV_VERSION "7.3.15-k2"DRIVERNAPI
char e1000_driver_version[] = DRV_VERSION;
static char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
@@ -103,6 +104,9 @@ static struct pci_device_id e1000_pci_tbl[] = {
INTEL_E1000_ETHERNET_DEVICE(0x10B9),
INTEL_E1000_ETHERNET_DEVICE(0x10BA),
INTEL_E1000_ETHERNET_DEVICE(0x10BB),
+ INTEL_E1000_ETHERNET_DEVICE(0x10BC),
+ INTEL_E1000_ETHERNET_DEVICE(0x10C4),
+ INTEL_E1000_ETHERNET_DEVICE(0x10C5),
/* required last entry */
{0,}
};
@@ -154,6 +158,9 @@ static struct net_device_stats * e1000_get_stats(struct net_device *netdev);
static int e1000_change_mtu(struct net_device *netdev, int new_mtu);
static int e1000_set_mac(struct net_device *netdev, void *p);
static irqreturn_t e1000_intr(int irq, void *data);
+#ifdef CONFIG_PCI_MSI
+static irqreturn_t e1000_intr_msi(int irq, void *data);
+#endif
static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter,
struct e1000_tx_ring *tx_ring);
#ifdef CONFIG_E1000_NAPI
@@ -285,7 +292,7 @@ static int e1000_request_irq(struct e1000_adapter *adapter)
flags = IRQF_SHARED;
#ifdef CONFIG_PCI_MSI
- if (adapter->hw.mac_type > e1000_82547_rev_2) {
+ if (adapter->hw.mac_type >= e1000_82571) {
adapter->have_msi = TRUE;
if ((err = pci_enable_msi(adapter->pdev))) {
DPRINTK(PROBE, ERR,
@@ -293,8 +300,14 @@ static int e1000_request_irq(struct e1000_adapter *adapter)
adapter->have_msi = FALSE;
}
}
- if (adapter->have_msi)
+ if (adapter->have_msi) {
flags &= ~IRQF_SHARED;
+ err = request_irq(adapter->pdev->irq, &e1000_intr_msi, flags,
+ netdev->name, netdev);
+ if (err)
+ DPRINTK(PROBE, ERR,
+ "Unable to allocate interrupt Error: %d\n", err);
+ } else
#endif
if ((err = request_irq(adapter->pdev->irq, &e1000_intr, flags,
netdev->name, netdev)))
@@ -375,7 +388,7 @@ e1000_update_mng_vlan(struct e1000_adapter *adapter)
* e1000_release_hw_control resets {CTRL_EXT|FWSM}:DRV_LOAD bit.
* For ASF and Pass Through versions of f/w this means that the
* driver is no longer loaded. For AMT version (only with 82573) i
- * of the f/w this means that the netowrk i/f is closed.
+ * of the f/w this means that the network i/f is closed.
*
**/
@@ -416,7 +429,7 @@ e1000_release_hw_control(struct e1000_adapter *adapter)
* e1000_get_hw_control sets {CTRL_EXT|FWSM}:DRV_LOAD bit.
* For ASF and Pass Through versions of f/w this means that
* the driver is loaded. For AMT version (only with 82573)
- * of the f/w this means that the netowrk i/f is open.
+ * of the f/w this means that the network i/f is open.
*
**/
@@ -426,6 +439,7 @@ e1000_get_hw_control(struct e1000_adapter *adapter)
uint32_t ctrl_ext;
uint32_t swsm;
uint32_t extcnf;
+
/* Let firmware know the driver has taken over */
switch (adapter->hw.mac_type) {
case e1000_82571:
@@ -601,9 +615,6 @@ void
e1000_reset(struct e1000_adapter *adapter)
{
uint32_t pba, manc;
-#ifdef DISABLE_MULR
- uint32_t tctl;
-#endif
uint16_t fc_high_water_mark = E1000_FC_HIGH_DIFF;
/* Repartition Pba for greater than 9k mtu
@@ -670,12 +681,7 @@ e1000_reset(struct e1000_adapter *adapter)
e1000_reset_hw(&adapter->hw);
if (adapter->hw.mac_type >= e1000_82544)
E1000_WRITE_REG(&adapter->hw, WUC, 0);
-#ifdef DISABLE_MULR
- /* disable Multiple Reads in Transmit Control Register for debugging */
- tctl = E1000_READ_REG(hw, TCTL);
- E1000_WRITE_REG(hw, TCTL, tctl & ~E1000_TCTL_MULR);
-#endif
if (e1000_init_hw(&adapter->hw))
DPRINTK(PROBE, ERR, "Hardware Error\n");
e1000_update_mng_vlan(adapter);
@@ -851,9 +857,9 @@ e1000_probe(struct pci_dev *pdev,
(adapter->hw.mac_type != e1000_82547))
netdev->features |= NETIF_F_TSO;
-#ifdef NETIF_F_TSO_IPV6
+#ifdef NETIF_F_TSO6
if (adapter->hw.mac_type > e1000_82547_rev_2)
- netdev->features |= NETIF_F_TSO_IPV6;
+ netdev->features |= NETIF_F_TSO6;
#endif
#endif
if (pci_using_dac)
@@ -967,6 +973,7 @@ e1000_probe(struct pci_dev *pdev,
break;
case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
case E1000_DEV_ID_82571EB_QUAD_COPPER:
+ case E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE:
/* if quad port adapter, disable WoL on all but port A */
if (global_quad_port_a != 0)
adapter->eeprom_wol = 0;
@@ -1278,12 +1285,10 @@ e1000_open(struct net_device *netdev)
return -EBUSY;
/* allocate transmit descriptors */
-
if ((err = e1000_setup_all_tx_resources(adapter)))
goto err_setup_tx;
/* allocate receive descriptors */
-
if ((err = e1000_setup_all_rx_resources(adapter)))
goto err_setup_rx;
@@ -1568,6 +1573,8 @@ e1000_configure_tx(struct e1000_adapter *adapter)
if (hw->mac_type == e1000_82571 || hw->mac_type == e1000_82572) {
tarc = E1000_READ_REG(hw, TARC0);
+ /* set the speed mode bit, we'll clear it if we're not at
+ * gigabit link later */
tarc |= (1 << 21);
E1000_WRITE_REG(hw, TARC0, tarc);
} else if (hw->mac_type == e1000_80003es2lan) {
@@ -1582,8 +1589,11 @@ e1000_configure_tx(struct e1000_adapter *adapter)
e1000_config_collision_dist(hw);
/* Setup Transmit Descriptor Settings for eop descriptor */
- adapter->txd_cmd = E1000_TXD_CMD_IDE | E1000_TXD_CMD_EOP |
- E1000_TXD_CMD_IFCS;
+ adapter->txd_cmd = E1000_TXD_CMD_EOP | E1000_TXD_CMD_IFCS;
+
+ /* only set IDE if we are delaying interrupts using the timers */
+ if (adapter->tx_int_delay)
+ adapter->txd_cmd |= E1000_TXD_CMD_IDE;
if (hw->mac_type < e1000_82543)
adapter->txd_cmd |= E1000_TXD_CMD_RPS;
@@ -1820,8 +1830,11 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
/* Configure extra packet-split registers */
rfctl = E1000_READ_REG(&adapter->hw, RFCTL);
rfctl |= E1000_RFCTL_EXTEN;
- /* disable IPv6 packet split support */
- rfctl |= E1000_RFCTL_IPV6_DIS;
+ /* disable packet split support for IPv6 extension headers,
+ * because some malformed IPv6 headers can hang the RX */
+ rfctl |= (E1000_RFCTL_IPV6_EX_DIS |
+ E1000_RFCTL_NEW_IPV6_EXT_DIS);
+
E1000_WRITE_REG(&adapter->hw, RFCTL, rfctl);
rctl |= E1000_RCTL_DTYP_PS;
@@ -1884,7 +1897,7 @@ e1000_configure_rx(struct e1000_adapter *adapter)
if (hw->mac_type >= e1000_82540) {
E1000_WRITE_REG(hw, RADV, adapter->rx_abs_int_delay);
- if (adapter->itr > 1)
+ if (adapter->itr_setting != 0)
E1000_WRITE_REG(hw, ITR,
1000000000 / (adapter->itr * 256));
}
@@ -1894,11 +1907,11 @@ e1000_configure_rx(struct e1000_adapter *adapter)
/* Reset delay timers after every interrupt */
ctrl_ext |= E1000_CTRL_EXT_INT_TIMER_CLR;
#ifdef CONFIG_E1000_NAPI
- /* Auto-Mask interrupts upon ICR read. */
+ /* Auto-Mask interrupts upon ICR access */
ctrl_ext |= E1000_CTRL_EXT_IAME;
+ E1000_WRITE_REG(hw, IAM, 0xffffffff);
#endif
E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
- E1000_WRITE_REG(hw, IAM, ~0);
E1000_WRITE_FLUSH(hw);
}
@@ -1937,6 +1950,12 @@ e1000_configure_rx(struct e1000_adapter *adapter)
E1000_WRITE_REG(hw, RXCSUM, rxcsum);
}
+ /* enable early receives on 82573, only takes effect if using > 2048
+ * byte total frame size. for example only for jumbo frames */
+#define E1000_ERT_2048 0x100
+ if (hw->mac_type == e1000_82573)
+ E1000_WRITE_REG(hw, ERT, E1000_ERT_2048);
+
/* Enable Receives */
E1000_WRITE_REG(hw, RCTL, rctl);
}
@@ -1990,10 +2009,13 @@ e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter,
buffer_info->dma,
buffer_info->length,
PCI_DMA_TODEVICE);
+ buffer_info->dma = 0;
}
- if (buffer_info->skb)
+ if (buffer_info->skb) {
dev_kfree_skb_any(buffer_info->skb);
- memset(buffer_info, 0, sizeof(struct e1000_buffer));
+ buffer_info->skb = NULL;
+ }
+ /* buffer_info must be completely set up in the transmit path */
}
/**
@@ -2417,6 +2439,7 @@ e1000_watchdog(unsigned long data)
DPRINTK(LINK, INFO,
"Gigabit has been disabled, downgrading speed\n");
}
+
if (adapter->hw.mac_type == e1000_82573) {
e1000_enable_tx_pkt_filtering(&adapter->hw);
if (adapter->mng_vlan_id != adapter->hw.mng_cookie.vlan_id)
@@ -2461,13 +2484,12 @@ e1000_watchdog(unsigned long data)
if ((adapter->hw.mac_type == e1000_82571 ||
adapter->hw.mac_type == e1000_82572) &&
txb2b == 0) {
-#define SPEED_MODE_BIT (1 << 21)
uint32_t tarc0;
tarc0 = E1000_READ_REG(&adapter->hw, TARC0);
- tarc0 &= ~SPEED_MODE_BIT;
+ tarc0 &= ~(1 << 21);
E1000_WRITE_REG(&adapter->hw, TARC0, tarc0);
}
-
+
#ifdef NETIF_F_TSO
/* disable TSO for pcie and 10/100 speeds, to avoid
* some hardware issues */
@@ -2479,9 +2501,15 @@ e1000_watchdog(unsigned long data)
DPRINTK(PROBE,INFO,
"10/100 speed: disabling TSO\n");
netdev->features &= ~NETIF_F_TSO;
+#ifdef NETIF_F_TSO6
+ netdev->features &= ~NETIF_F_TSO6;
+#endif
break;
case SPEED_1000:
netdev->features |= NETIF_F_TSO;
+#ifdef NETIF_F_TSO6
+ netdev->features |= NETIF_F_TSO6;
+#endif
break;
default:
/* oops */
@@ -2548,19 +2576,6 @@ e1000_watchdog(unsigned long data)
}
}
- /* Dynamic mode for Interrupt Throttle Rate (ITR) */
- if (adapter->hw.mac_type >= e1000_82540 && adapter->itr == 1) {
- /* Symmetric Tx/Rx gets a reduced ITR=2000; Total
- * asymmetrical Tx or Rx gets ITR=8000; everyone
- * else is between 2000-8000. */
- uint32_t goc = (adapter->gotcl + adapter->gorcl) / 10000;
- uint32_t dif = (adapter->gotcl > adapter->gorcl ?
- adapter->gotcl - adapter->gorcl :
- adapter->gorcl - adapter->gotcl) / 10000;
- uint32_t itr = goc > 0 ? (dif * 6000 / goc + 2000) : 8000;
- E1000_WRITE_REG(&adapter->hw, ITR, 1000000000 / (itr * 256));
- }
-
/* Cause software interrupt to ensure rx ring is cleaned */
E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_RXDMT0);
@@ -2576,6 +2591,135 @@ e1000_watchdog(unsigned long data)
mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
}
+enum latency_range {
+ lowest_latency = 0,
+ low_latency = 1,
+ bulk_latency = 2,
+ latency_invalid = 255
+};
+
+/**
+ * e1000_update_itr - update the dynamic ITR value based on statistics
+ * Stores a new ITR value based on packets and byte
+ * counts during the last interrupt. The advantage of per interrupt
+ * computation is faster updates and more accurate ITR for the current
+ * traffic pattern. Constants in this function were computed
+ * based on theoretical maximum wire speed and thresholds were set based
+ * on testing data as well as attempting to minimize response time
+ * while increasing bulk throughput.
+ * this functionality is controlled by the InterruptThrottleRate module
+ * parameter (see e1000_param.c)
+ * @adapter: pointer to adapter
+ * @itr_setting: current adapter->itr
+ * @packets: the number of packets during this measurement interval
+ * @bytes: the number of bytes during this measurement interval
+ **/
+static unsigned int e1000_update_itr(struct e1000_adapter *adapter,
+ uint16_t itr_setting,
+ int packets,
+ int bytes)
+{
+ unsigned int retval = itr_setting;
+ struct e1000_hw *hw = &adapter->hw;
+
+ if (unlikely(hw->mac_type < e1000_82540))
+ goto update_itr_done;
+
+ if (packets == 0)
+ goto update_itr_done;
+
+
+ switch (itr_setting) {
+ case lowest_latency:
+ if ((packets < 5) && (bytes > 512))
+ retval = low_latency;
+ break;
+ case low_latency: /* 50 usec aka 20000 ints/s */
+ if (bytes > 10000) {
+ if ((packets < 10) ||
+ ((bytes/packets) > 1200))
+ retval = bulk_latency;
+ else if ((packets > 35))
+ retval = lowest_latency;
+ } else if (packets <= 2 && bytes < 512)
+ retval = lowest_latency;
+ break;
+ case bulk_latency: /* 250 usec aka 4000 ints/s */
+ if (bytes > 25000) {
+ if (packets > 35)
+ retval = low_latency;
+ } else {
+ if (bytes < 6000)
+ retval = low_latency;
+ }
+ break;
+ }
+
+update_itr_done:
+ return retval;
+}
+
+static void e1000_set_itr(struct e1000_adapter *adapter)
+{
+ struct e1000_hw *hw = &adapter->hw;
+ uint16_t current_itr;
+ uint32_t new_itr = adapter->itr;
+
+ if (unlikely(hw->mac_type < e1000_82540))
+ return;
+
+ /* for non-gigabit speeds, just fix the interrupt rate at 4000 */
+ if (unlikely(adapter->link_speed != SPEED_1000)) {
+ current_itr = 0;
+ new_itr = 4000;
+ goto set_itr_now;
+ }
+
+ adapter->tx_itr = e1000_update_itr(adapter,
+ adapter->tx_itr,
+ adapter->total_tx_packets,
+ adapter->total_tx_bytes);
+ adapter->rx_itr = e1000_update_itr(adapter,
+ adapter->rx_itr,
+ adapter->total_rx_packets,
+ adapter->total_rx_bytes);
+
+ current_itr = max(adapter->rx_itr, adapter->tx_itr);
+
+ /* conservative mode eliminates the lowest_latency setting */
+ if (current_itr == lowest_latency && (adapter->itr_setting == 3))
+ current_itr = low_latency;
+
+ switch (current_itr) {
+ /* counts and packets in update_itr are dependent on these numbers */
+ case lowest_latency:
+ new_itr = 70000;
+ break;
+ case low_latency:
+ new_itr = 20000; /* aka hwitr = ~200 */
+ break;
+ case bulk_latency:
+ new_itr = 4000;
+ break;
+ default:
+ break;
+ }
+
+set_itr_now:
+ if (new_itr != adapter->itr) {
+ /* this attempts to bias the interrupt rate towards Bulk
+ * by adding intermediate steps when interrupt rate is
+ * increasing */
+ new_itr = new_itr > adapter->itr ?
+ min(adapter->itr + (new_itr >> 2), new_itr) :
+ new_itr;
+ adapter->itr = new_itr;
+ E1000_WRITE_REG(hw, ITR, 1000000000 / (new_itr * 256));
+ }
+
+ return;
+}
+
#define E1000_TX_FLAGS_CSUM 0x00000001
#define E1000_TX_FLAGS_VLAN 0x00000002
#define E1000_TX_FLAGS_TSO 0x00000004
@@ -2616,7 +2760,7 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
0);
cmd_length = E1000_TXD_CMD_IP;
ipcse = skb->h.raw - skb->data - 1;
-#ifdef NETIF_F_TSO_IPV6
+#ifdef NETIF_F_TSO6
} else if (skb->protocol == htons(ETH_P_IPV6)) {
skb->nh.ipv6h->payload_len = 0;
skb->h.th->check =
@@ -2652,6 +2796,7 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
context_desc->cmd_and_length = cpu_to_le32(cmd_length);
buffer_info->time_stamp = jiffies;
+ buffer_info->next_to_watch = i;
if (++i == tx_ring->count) i = 0;
tx_ring->next_to_use = i;
@@ -2680,12 +2825,13 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
context_desc->upper_setup.tcp_fields.tucss = css;
- context_desc->upper_setup.tcp_fields.tucso = css + skb->csum;
+ context_desc->upper_setup.tcp_fields.tucso = css + skb->csum_offset;
context_desc->upper_setup.tcp_fields.tucse = 0;
context_desc->tcp_seg_setup.data = 0;
context_desc->cmd_and_length = cpu_to_le32(E1000_TXD_CMD_DEXT);
buffer_info->time_stamp = jiffies;
+ buffer_info->next_to_watch = i;
if (unlikely(++i == tx_ring->count)) i = 0;
tx_ring->next_to_use = i;
@@ -2754,6 +2900,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
size,
PCI_DMA_TODEVICE);
buffer_info->time_stamp = jiffies;
+ buffer_info->next_to_watch = i;
len -= size;
offset += size;
@@ -2793,6 +2940,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
size,
PCI_DMA_TODEVICE);
buffer_info->time_stamp = jiffies;
+ buffer_info->next_to_watch = i;
len -= size;
offset += size;
@@ -2858,6 +3006,9 @@ e1000_tx_queue(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
tx_ring->next_to_use = i;
writel(i, adapter->hw.hw_addr + tx_ring->tdt);
+ /* we need this if more than one processor can write to our tail
+ * at a time, it syncronizes IO on IA64/Altix systems */
+ mmiowb();
}
/**
@@ -2951,6 +3102,7 @@ static int __e1000_maybe_stop_tx(struct net_device *netdev, int size)
/* A reprieve! */
netif_start_queue(netdev);
+ ++adapter->restart_queue;
return 0;
}
@@ -3009,9 +3161,9 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
max_per_txd = min(mss << 2, max_per_txd);
max_txd_pwr = fls(max_per_txd) - 1;
- /* TSO Workaround for 82571/2/3 Controllers -- if skb->data
- * points to just header, pull a few bytes of payload from
- * frags into skb->data */
+ /* TSO Workaround for 82571/2/3 Controllers -- if skb->data
+ * points to just header, pull a few bytes of payload from
+ * frags into skb->data */
hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
if (skb->data_len && (hdr_len == (skb->len - skb->data_len))) {
switch (adapter->hw.mac_type) {
@@ -3316,12 +3468,12 @@ e1000_update_stats(struct e1000_adapter *adapter)
adapter->stats.roc += E1000_READ_REG(hw, ROC);
if (adapter->hw.mac_type != e1000_ich8lan) {
- adapter->stats.prc64 += E1000_READ_REG(hw, PRC64);
- adapter->stats.prc127 += E1000_READ_REG(hw, PRC127);
- adapter->stats.prc255 += E1000_READ_REG(hw, PRC255);
- adapter->stats.prc511 += E1000_READ_REG(hw, PRC511);
- adapter->stats.prc1023 += E1000_READ_REG(hw, PRC1023);
- adapter->stats.prc1522 += E1000_READ_REG(hw, PRC1522);
+ adapter->stats.prc64 += E1000_READ_REG(hw, PRC64);
+ adapter->stats.prc127 += E1000_READ_REG(hw, PRC127);
+ adapter->stats.prc255 += E1000_READ_REG(hw, PRC255);
+ adapter->stats.prc511 += E1000_READ_REG(hw, PRC511);
+ adapter->stats.prc1023 += E1000_READ_REG(hw, PRC1023);
+ adapter->stats.prc1522 += E1000_READ_REG(hw, PRC1522);
}
adapter->stats.symerrs += E1000_READ_REG(hw, SYMERRS);
@@ -3352,12 +3504,12 @@ e1000_update_stats(struct e1000_adapter *adapter)
adapter->stats.tpr += E1000_READ_REG(hw, TPR);
if (adapter->hw.mac_type != e1000_ich8lan) {
- adapter->stats.ptc64 += E1000_READ_REG(hw, PTC64);
- adapter->stats.ptc127 += E1000_READ_REG(hw, PTC127);
- adapter->stats.ptc255 += E1000_READ_REG(hw, PTC255);
- adapter->stats.ptc511 += E1000_READ_REG(hw, PTC511);
- adapter->stats.ptc1023 += E1000_READ_REG(hw, PTC1023);
- adapter->stats.ptc1522 += E1000_READ_REG(hw, PTC1522);
+ adapter->stats.ptc64 += E1000_READ_REG(hw, PTC64);
+ adapter->stats.ptc127 += E1000_READ_REG(hw, PTC127);
+ adapter->stats.ptc255 += E1000_READ_REG(hw, PTC255);
+ adapter->stats.ptc511 += E1000_READ_REG(hw, PTC511);
+ adapter->stats.ptc1023 += E1000_READ_REG(hw, PTC1023);
+ adapter->stats.ptc1522 += E1000_READ_REG(hw, PTC1522);
}
adapter->stats.mptc += E1000_READ_REG(hw, MPTC);
@@ -3383,18 +3535,17 @@ e1000_update_stats(struct e1000_adapter *adapter)
adapter->stats.icrxoc += E1000_READ_REG(hw, ICRXOC);
if (adapter->hw.mac_type != e1000_ich8lan) {
- adapter->stats.icrxptc += E1000_READ_REG(hw, ICRXPTC);
- adapter->stats.icrxatc += E1000_READ_REG(hw, ICRXATC);
- adapter->stats.ictxptc += E1000_READ_REG(hw, ICTXPTC);
- adapter->stats.ictxatc += E1000_READ_REG(hw, ICTXATC);
- adapter->stats.ictxqec += E1000_READ_REG(hw, ICTXQEC);
- adapter->stats.ictxqmtc += E1000_READ_REG(hw, ICTXQMTC);
- adapter->stats.icrxdmtc += E1000_READ_REG(hw, ICRXDMTC);
+ adapter->stats.icrxptc += E1000_READ_REG(hw, ICRXPTC);
+ adapter->stats.icrxatc += E1000_READ_REG(hw, ICRXATC);
+ adapter->stats.ictxptc += E1000_READ_REG(hw, ICTXPTC);
+ adapter->stats.ictxatc += E1000_READ_REG(hw, ICTXATC);
+ adapter->stats.ictxqec += E1000_READ_REG(hw, ICTXQEC);
+ adapter->stats.ictxqmtc += E1000_READ_REG(hw, ICTXQMTC);
+ adapter->stats.icrxdmtc += E1000_READ_REG(hw, ICRXDMTC);
}
}
/* Fill out the OS statistics structure */
-
adapter->net_stats.rx_packets = adapter->stats.gprc;
adapter->net_stats.tx_packets = adapter->stats.gptc;
adapter->net_stats.rx_bytes = adapter->stats.gorcl;
@@ -3426,7 +3577,6 @@ e1000_update_stats(struct e1000_adapter *adapter)
/* Tx Dropped needs to be maintained elsewhere */
/* Phy Stats */
-
if (hw->media_type == e1000_media_type_copper) {
if ((adapter->link_speed == SPEED_1000) &&
(!e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_tmp))) {
@@ -3442,6 +3592,95 @@ e1000_update_stats(struct e1000_adapter *adapter)
spin_unlock_irqrestore(&adapter->stats_lock, flags);
}
+#ifdef CONFIG_PCI_MSI
+
+/**
+ * e1000_intr_msi - Interrupt Handler
+ * @irq: interrupt number
+ * @data: pointer to a network interface device structure
+ **/
+
+static
+irqreturn_t e1000_intr_msi(int irq, void *data)
+{
+ struct net_device *netdev = data;
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
+#ifndef CONFIG_E1000_NAPI
+ int i;
+#endif
+
+ /* this code avoids the read of ICR but has to get 1000 interrupts
+ * at every link change event before it will notice the change */
+ if (++adapter->detect_link >= 1000) {
+ uint32_t icr = E1000_READ_REG(hw, ICR);
+#ifdef CONFIG_E1000_NAPI
+ /* read ICR disables interrupts using IAM, so keep up with our
+ * enable/disable accounting */
+ atomic_inc(&adapter->irq_sem);
+#endif
+ adapter->detect_link = 0;
+ if ((icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) &&
+ (icr & E1000_ICR_INT_ASSERTED)) {
+ hw->get_link_status = 1;
+ /* 80003ES2LAN workaround--
+ * For packet buffer work-around on link down event;
+ * disable receives here in the ISR and
+ * reset adapter in watchdog
+ */
+ if (netif_carrier_ok(netdev) &&
+ (adapter->hw.mac_type == e1000_80003es2lan)) {
+ /* disable receives */
+ uint32_t rctl = E1000_READ_REG(hw, RCTL);
+ E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN);
+ }
+ /* guard against interrupt when we're going down */
+ if (!test_bit(__E1000_DOWN, &adapter->flags))
+ mod_timer(&adapter->watchdog_timer,
+ jiffies + 1);
+ }
+ } else {
+ E1000_WRITE_REG(hw, ICR, (0xffffffff & ~(E1000_ICR_RXSEQ |
+ E1000_ICR_LSC)));
+ /* bummer we have to flush here, but things break otherwise as
+ * some event appears to be lost or delayed and throughput
+ * drops. In almost all tests this flush is un-necessary */
+ E1000_WRITE_FLUSH(hw);
+#ifdef CONFIG_E1000_NAPI
+ /* Interrupt Auto-Mask (IAM)...upon writing ICR, interrupts are
+ * masked. No need for the IMC write, but it does mean we
+ * should account for it ASAP. */
+ atomic_inc(&adapter->irq_sem);
+#endif
+ }
+
+#ifdef CONFIG_E1000_NAPI
+ if (likely(netif_rx_schedule_prep(netdev))) {
+ adapter->total_tx_bytes = 0;
+ adapter->total_tx_packets = 0;
+ adapter->total_rx_bytes = 0;
+ adapter->total_rx_packets = 0;
+ __netif_rx_schedule(netdev);
+ } else
+ e1000_irq_enable(adapter);
+#else
+ adapter->total_tx_bytes = 0;
+ adapter->total_rx_bytes = 0;
+ adapter->total_tx_packets = 0;
+ adapter->total_rx_packets = 0;
+
+ for (i = 0; i < E1000_MAX_INTR; i++)
+ if (unlikely(!adapter->clean_rx(adapter, adapter->rx_ring) &
+ !e1000_clean_tx_irq(adapter, adapter->tx_ring)))
+ break;
+
+ if (likely(adapter->itr_setting & 3))
+ e1000_set_itr(adapter);
+#endif
+
+ return IRQ_HANDLED;
+}
+#endif
/**
* e1000_intr - Interrupt Handler
@@ -3458,7 +3697,17 @@ e1000_intr(int irq, void *data)
uint32_t rctl, icr = E1000_READ_REG(hw, ICR);
#ifndef CONFIG_E1000_NAPI
int i;
-#else
+#endif
+ if (unlikely(!icr))
+ return IRQ_NONE; /* Not our interrupt */
+
+#ifdef CONFIG_E1000_NAPI
+ /* IMS will not auto-mask if INT_ASSERTED is not set, and if it is
+ * not set, then the adapter didn't send an interrupt */
+ if (unlikely(hw->mac_type >= e1000_82571 &&
+ !(icr & E1000_ICR_INT_ASSERTED)))
+ return IRQ_NONE;
+
/* Interrupt Auto-Mask...upon reading ICR,
* interrupts are masked. No need for the
* IMC write, but it does mean we should
@@ -3467,14 +3716,6 @@ e1000_intr(int irq, void *data)
atomic_inc(&adapter->irq_sem);
#endif
- if (unlikely(!icr)) {
-#ifdef CONFIG_E1000_NAPI
- if (hw->mac_type >= e1000_82571)
- e1000_irq_enable(adapter);
-#endif
- return IRQ_NONE; /* Not our interrupt */
- }
-
if (unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) {
hw->get_link_status = 1;
/* 80003ES2LAN workaround--
@@ -3495,13 +3736,20 @@ e1000_intr(int irq, void *data)
#ifdef CONFIG_E1000_NAPI
if (unlikely(hw->mac_type < e1000_82571)) {
+ /* disable interrupts, without the synchronize_irq bit */
atomic_inc(&adapter->irq_sem);
E1000_WRITE_REG(hw, IMC, ~0);
E1000_WRITE_FLUSH(hw);
}
- if (likely(netif_rx_schedule_prep(netdev)))
+ if (likely(netif_rx_schedule_prep(netdev))) {
+ adapter->total_tx_bytes = 0;
+ adapter->total_tx_packets = 0;
+ adapter->total_rx_bytes = 0;
+ adapter->total_rx_packets = 0;
__netif_rx_schedule(netdev);
- else
+ } else
+ /* this really should not happen! if it does it is basically a
+ * bug, but not a hard error, so enable ints and continue */
e1000_irq_enable(adapter);
#else
/* Writing IMC and IMS is needed for 82547.
@@ -3519,16 +3767,23 @@ e1000_intr(int irq, void *data)
E1000_WRITE_REG(hw, IMC, ~0);
}
+ adapter->total_tx_bytes = 0;
+ adapter->total_rx_bytes = 0;
+ adapter->total_tx_packets = 0;
+ adapter->total_rx_packets = 0;
+
for (i = 0; i < E1000_MAX_INTR; i++)
if (unlikely(!adapter->clean_rx(adapter, adapter->rx_ring) &
!e1000_clean_tx_irq(adapter, adapter->tx_ring)))
break;
+ if (likely(adapter->itr_setting & 3))
+ e1000_set_itr(adapter);
+
if (hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2)
e1000_irq_enable(adapter);
#endif
-
return IRQ_HANDLED;
}
@@ -3572,6 +3827,8 @@ e1000_clean(struct net_device *poll_dev, int *budget)
if ((!tx_cleaned && (work_done == 0)) ||
!netif_running(poll_dev)) {
quit_polling:
+ if (likely(adapter->itr_setting & 3))
+ e1000_set_itr(adapter);
netif_rx_complete(poll_dev);
e1000_irq_enable(adapter);
return 0;
@@ -3598,6 +3855,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
unsigned int count = 0;
#endif
boolean_t cleaned = FALSE;
+ unsigned int total_tx_bytes=0, total_tx_packets=0;
i = tx_ring->next_to_clean;
eop = tx_ring->buffer_info[i].next_to_watch;
@@ -3609,13 +3867,19 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
buffer_info = &tx_ring->buffer_info[i];
cleaned = (i == eop);
+ if (cleaned) {
+ /* this packet count is wrong for TSO but has a
+ * tendency to make dynamic ITR change more
+ * towards bulk */
+ total_tx_packets++;
+ total_tx_bytes += buffer_info->skb->len;
+ }
e1000_unmap_and_free_tx_resource(adapter, buffer_info);
- memset(tx_desc, 0, sizeof(struct e1000_tx_desc));
+ tx_desc->upper.data = 0;
if (unlikely(++i == tx_ring->count)) i = 0;
}
-
eop = tx_ring->buffer_info[i].next_to_watch;
eop_desc = E1000_TX_DESC(*tx_ring, eop);
#ifdef CONFIG_E1000_NAPI
@@ -3634,8 +3898,10 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
* sees the new next_to_clean.
*/
smp_mb();
- if (netif_queue_stopped(netdev))
+ if (netif_queue_stopped(netdev)) {
netif_wake_queue(netdev);
+ ++adapter->restart_queue;
+ }
}
if (adapter->detect_tx_hung) {
@@ -3673,6 +3939,8 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
netif_stop_queue(netdev);
}
}
+ adapter->total_tx_bytes += total_tx_bytes;
+ adapter->total_tx_packets += total_tx_packets;
return cleaned;
}
@@ -3752,6 +4020,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
unsigned int i;
int cleaned_count = 0;
boolean_t cleaned = FALSE;
+ unsigned int total_rx_bytes=0, total_rx_packets=0;
i = rx_ring->next_to_clean;
rx_desc = E1000_RX_DESC(*rx_ring, i);
@@ -3760,6 +4029,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
while (rx_desc->status & E1000_RXD_STAT_DD) {
struct sk_buff *skb;
u8 status;
+
#ifdef CONFIG_E1000_NAPI
if (*work_done >= work_to_do)
break;
@@ -3817,6 +4087,10 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
* done after the TBI_ACCEPT workaround above */
length -= 4;
+ /* probably a little skewed due to removing CRC */
+ total_rx_bytes += length;
+ total_rx_packets++;
+
/* code added for copybreak, this should improve
* performance for small packets with large amounts
* of reassembly being done in the stack */
@@ -3832,12 +4106,11 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
/* save the skb in buffer_info as good */
buffer_info->skb = skb;
skb = new_skb;
- skb_put(skb, length);
}
- } else
- skb_put(skb, length);
-
+ /* else just continue with the old one */
+ }
/* end copybreak code */
+ skb_put(skb, length);
/* Receive Checksum Offload */
e1000_rx_checksum(adapter,
@@ -3886,6 +4159,8 @@ next_desc:
if (cleaned_count)
adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
+ adapter->total_rx_packets += total_rx_packets;
+ adapter->total_rx_bytes += total_rx_bytes;
return cleaned;
}
@@ -3915,6 +4190,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
uint32_t length, staterr;
int cleaned_count = 0;
boolean_t cleaned = FALSE;
+ unsigned int total_rx_bytes=0, total_rx_packets=0;
i = rx_ring->next_to_clean;
rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
@@ -3999,7 +4275,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
goto copydone;
} /* if */
}
-
+
for (j = 0; j < adapter->rx_ps_pages; j++) {
if (!(length= le16_to_cpu(rx_desc->wb.upper.length[j])))
break;
@@ -4019,6 +4295,9 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
pskb_trim(skb, skb->len - 4);
copydone:
+ total_rx_bytes += skb->len;
+ total_rx_packets++;
+
e1000_rx_checksum(adapter, staterr,
le16_to_cpu(rx_desc->wb.lower.hi_dword.csum_ip.csum), skb);
skb->protocol = eth_type_trans(skb, netdev);
@@ -4067,6 +4346,8 @@ next_desc:
if (cleaned_count)
adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
+ adapter->total_rx_packets += total_rx_packets;
+ adapter->total_rx_bytes += total_rx_bytes;
return cleaned;
}
@@ -4234,7 +4515,7 @@ e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
}
skb = netdev_alloc_skb(netdev,
- adapter->rx_ps_bsize0 + NET_IP_ALIGN);
+ adapter->rx_ps_bsize0 + NET_IP_ALIGN);
if (unlikely(!skb)) {
adapter->alloc_rx_buff_failed++;
@@ -4511,7 +4792,6 @@ e1000_read_pcie_cap_reg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
return E1000_SUCCESS;
}
-
void
e1000_io_write(struct e1000_hw *hw, unsigned long port, uint32_t value)
{
@@ -4534,12 +4814,12 @@ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
if (adapter->hw.mac_type != e1000_ich8lan) {
- /* enable VLAN receive filtering */
- rctl = E1000_READ_REG(&adapter->hw, RCTL);
- rctl |= E1000_RCTL_VFE;
- rctl &= ~E1000_RCTL_CFIEN;
- E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
- e1000_update_mng_vlan(adapter);
+ /* enable VLAN receive filtering */
+ rctl = E1000_READ_REG(&adapter->hw, RCTL);
+ rctl |= E1000_RCTL_VFE;
+ rctl &= ~E1000_RCTL_CFIEN;
+ E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+ e1000_update_mng_vlan(adapter);
}
} else {
/* disable VLAN tag insert/strip */
@@ -4548,14 +4828,16 @@ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
if (adapter->hw.mac_type != e1000_ich8lan) {
- /* disable VLAN filtering */
- rctl = E1000_READ_REG(&adapter->hw, RCTL);
- rctl &= ~E1000_RCTL_VFE;
- E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
- if (adapter->mng_vlan_id != (uint16_t)E1000_MNG_VLAN_NONE) {
- e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
- adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
- }
+ /* disable VLAN filtering */
+ rctl = E1000_READ_REG(&adapter->hw, RCTL);
+ rctl &= ~E1000_RCTL_VFE;
+ E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+ if (adapter->mng_vlan_id !=
+ (uint16_t)E1000_MNG_VLAN_NONE) {
+ e1000_vlan_rx_kill_vid(netdev,
+ adapter->mng_vlan_id);
+ adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
+ }
}
}
diff --git a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h
index a464cb290621..18afc0c25dac 100644
--- a/drivers/net/e1000/e1000_osdep.h
+++ b/drivers/net/e1000/e1000_osdep.h
@@ -107,17 +107,16 @@ typedef enum {
#define E1000_WRITE_FLUSH(a) E1000_READ_REG(a, STATUS)
-#define E1000_WRITE_ICH8_REG(a, reg, value) ( \
+#define E1000_WRITE_ICH_FLASH_REG(a, reg, value) ( \
writel((value), ((a)->flash_address + reg)))
-#define E1000_READ_ICH8_REG(a, reg) ( \
+#define E1000_READ_ICH_FLASH_REG(a, reg) ( \
readl((a)->flash_address + reg))
-#define E1000_WRITE_ICH8_REG16(a, reg, value) ( \
+#define E1000_WRITE_ICH_FLASH_REG16(a, reg, value) ( \
writew((value), ((a)->flash_address + reg)))
-#define E1000_READ_ICH8_REG16(a, reg) ( \
+#define E1000_READ_ICH_FLASH_REG16(a, reg) ( \
readw((a)->flash_address + reg))
-
#endif /* _E1000_OSDEP_H_ */
diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c
index 9c3c1acefccc..cbfcd7f2889f 100644
--- a/drivers/net/e1000/e1000_param.c
+++ b/drivers/net/e1000/e1000_param.c
@@ -44,16 +44,6 @@
*/
#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET }
-/* Module Parameters are always initialized to -1, so that the driver
- * can tell the difference between no user specified value or the
- * user asking for the default value.
- * The true default values are loaded in when e1000_check_options is called.
- *
- * This is a GCC extension to ANSI C.
- * See the item "Labeled Elements in Initializers" in the section
- * "Extensions to the C Language Family" of the GCC documentation.
- */
-
#define E1000_PARAM(X, desc) \
static int __devinitdata X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \
static int num_##X = 0; \
@@ -67,7 +57,6 @@
*
* Default Value: 256
*/
-
E1000_PARAM(TxDescriptors, "Number of transmit descriptors");
/* Receive Descriptor Count
@@ -77,7 +66,6 @@ E1000_PARAM(TxDescriptors, "Number of transmit descriptors");
*
* Default Value: 256
*/
-
E1000_PARAM(RxDescriptors, "Number of receive descriptors");
/* User Specified Speed Override
@@ -90,7 +78,6 @@ E1000_PARAM(RxDescriptors, "Number of receive descriptors");
*
* Default Value: 0
*/
-
E1000_PARAM(Speed, "Speed setting");
/* User Specified Duplex Override
@@ -102,7 +89,6 @@ E1000_PARAM(Speed, "Speed setting");
*
* Default Value: 0
*/
-
E1000_PARAM(Duplex, "Duplex setting");
/* Auto-negotiation Advertisement Override
@@ -119,8 +105,9 @@ E1000_PARAM(Duplex, "Duplex setting");
*
* Default Value: 0x2F (copper); 0x20 (fiber)
*/
-
E1000_PARAM(AutoNeg, "Advertised auto-negotiation setting");
+#define AUTONEG_ADV_DEFAULT 0x2F
+#define AUTONEG_ADV_MASK 0x2F
/* User Specified Flow Control Override
*
@@ -132,8 +119,8 @@ E1000_PARAM(AutoNeg, "Advertised auto-negotiation setting");
*
* Default Value: Read flow control settings from the EEPROM
*/
-
E1000_PARAM(FlowControl, "Flow Control setting");
+#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL
/* XsumRX - Receive Checksum Offload Enable/Disable
*
@@ -144,53 +131,54 @@ E1000_PARAM(FlowControl, "Flow Control setting");
*
* Default Value: 1
*/
-
E1000_PARAM(XsumRX, "Disable or enable Receive Checksum offload");
/* Transmit Interrupt Delay in units of 1.024 microseconds
+ * Tx interrupt delay needs to typically be set to something non zero
*
* Valid Range: 0-65535
- *
- * Default Value: 64
*/
-
E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay");
+#define DEFAULT_TIDV 8
+#define MAX_TXDELAY 0xFFFF
+#define MIN_TXDELAY 0
/* Transmit Absolute Interrupt Delay in units of 1.024 microseconds
*
* Valid Range: 0-65535
- *
- * Default Value: 0
*/
-
E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay");
+#define DEFAULT_TADV 32
+#define MAX_TXABSDELAY 0xFFFF
+#define MIN_TXABSDELAY 0
/* Receive Interrupt Delay in units of 1.024 microseconds
+ * hardware will likely hang if you set this to anything but zero.
*
* Valid Range: 0-65535
- *
- * Default Value: 0
*/
-
E1000_PARAM(RxIntDelay, "Receive Interrupt Delay");
+#define DEFAULT_RDTR 0
+#define MAX_RXDELAY 0xFFFF
+#define MIN_RXDELAY 0
/* Receive Absolute Interrupt Delay in units of 1.024 microseconds
*
* Valid Range: 0-65535
- *
- * Default Value: 128
*/
-
E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
+#define DEFAULT_RADV 8
+#define MAX_RXABSDELAY 0xFFFF
+#define MIN_RXABSDELAY 0
/* Interrupt Throttle Rate (interrupts/sec)
*
- * Valid Range: 100-100000 (0=off, 1=dynamic)
- *
- * Default Value: 8000
+ * Valid Range: 100-100000 (0=off, 1=dynamic, 3=dynamic conservative)
*/
-
E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
+#define DEFAULT_ITR 3
+#define MAX_ITR 100000
+#define MIN_ITR 100
/* Enable Smart Power Down of the PHY
*
@@ -198,7 +186,6 @@ E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
*
* Default Value: 0 (disabled)
*/
-
E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");
/* Enable Kumeran Lock Loss workaround
@@ -207,33 +194,8 @@ E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");
*
* Default Value: 1 (enabled)
*/
-
E1000_PARAM(KumeranLockLoss, "Enable Kumeran lock loss workaround");
-#define AUTONEG_ADV_DEFAULT 0x2F
-#define AUTONEG_ADV_MASK 0x2F
-#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL
-
-#define DEFAULT_RDTR 0
-#define MAX_RXDELAY 0xFFFF
-#define MIN_RXDELAY 0
-
-#define DEFAULT_RADV 128
-#define MAX_RXABSDELAY 0xFFFF
-#define MIN_RXABSDELAY 0
-
-#define DEFAULT_TIDV 64
-#define MAX_TXDELAY 0xFFFF
-#define MIN_TXDELAY 0
-
-#define DEFAULT_TADV 64
-#define MAX_TXABSDELAY 0xFFFF
-#define MIN_TXABSDELAY 0
-
-#define DEFAULT_ITR 8000
-#define MAX_ITR 100000
-#define MIN_ITR 100
-
struct e1000_option {
enum { enable_option, range_option, list_option } type;
char *name;
@@ -510,15 +472,27 @@ e1000_check_options(struct e1000_adapter *adapter)
break;
case 1:
DPRINTK(PROBE, INFO, "%s set to dynamic mode\n",
- opt.name);
+ opt.name);
+ adapter->itr_setting = adapter->itr;
+ adapter->itr = 20000;
+ break;
+ case 3:
+ DPRINTK(PROBE, INFO,
+ "%s set to dynamic conservative mode\n",
+ opt.name);
+ adapter->itr_setting = adapter->itr;
+ adapter->itr = 20000;
break;
default:
e1000_validate_option(&adapter->itr, &opt,
- adapter);
+ adapter);
+ /* save the setting, because the dynamic bits change itr */
+ adapter->itr_setting = adapter->itr;
break;
}
} else {
- adapter->itr = opt.def;
+ adapter->itr_setting = opt.def;
+ adapter->itr = 20000;
}
}
{ /* Smart Power Down */
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index c5ed635bce36..439f41338291 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -110,6 +110,8 @@
* 0.55: 22 Mar 2006: Add flow control (pause frame).
* 0.56: 22 Mar 2006: Additional ethtool config and moduleparam support.
* 0.57: 14 May 2006: Mac address set in probe/remove and order corrections.
+ * 0.58: 30 Oct 2006: Added support for sideband management unit.
+ * 0.59: 30 Oct 2006: Added support for recoverable error.
*
* Known bugs:
* We suspect that on some hardware no TX done interrupts are generated.
@@ -126,7 +128,7 @@
#else
#define DRIVERNAPI
#endif
-#define FORCEDETH_VERSION "0.57"
+#define FORCEDETH_VERSION "0.59"
#define DRV_NAME "forcedeth"
#include <linux/module.h>
@@ -174,11 +176,12 @@
#define DEV_HAS_PAUSEFRAME_TX 0x0200 /* device supports tx pause frames */
#define DEV_HAS_STATISTICS 0x0400 /* device supports hw statistics */
#define DEV_HAS_TEST_EXTENDED 0x0800 /* device supports extended diagnostic test */
+#define DEV_HAS_MGMT_UNIT 0x1000 /* device supports management unit */
enum {
NvRegIrqStatus = 0x000,
#define NVREG_IRQSTAT_MIIEVENT 0x040
-#define NVREG_IRQSTAT_MASK 0x1ff
+#define NVREG_IRQSTAT_MASK 0x81ff
NvRegIrqMask = 0x004,
#define NVREG_IRQ_RX_ERROR 0x0001
#define NVREG_IRQ_RX 0x0002
@@ -189,15 +192,16 @@ enum {
#define NVREG_IRQ_LINK 0x0040
#define NVREG_IRQ_RX_FORCED 0x0080
#define NVREG_IRQ_TX_FORCED 0x0100
+#define NVREG_IRQ_RECOVER_ERROR 0x8000
#define NVREG_IRQMASK_THROUGHPUT 0x00df
#define NVREG_IRQMASK_CPU 0x0040
#define NVREG_IRQ_TX_ALL (NVREG_IRQ_TX_ERR|NVREG_IRQ_TX_OK|NVREG_IRQ_TX_FORCED)
#define NVREG_IRQ_RX_ALL (NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_RX_FORCED)
-#define NVREG_IRQ_OTHER (NVREG_IRQ_TIMER|NVREG_IRQ_LINK)
+#define NVREG_IRQ_OTHER (NVREG_IRQ_TIMER|NVREG_IRQ_LINK|NVREG_IRQ_RECOVER_ERROR)
#define NVREG_IRQ_UNKNOWN (~(NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_TX_ERR| \
NVREG_IRQ_TX_OK|NVREG_IRQ_TIMER|NVREG_IRQ_LINK|NVREG_IRQ_RX_FORCED| \
- NVREG_IRQ_TX_FORCED))
+ NVREG_IRQ_TX_FORCED|NVREG_IRQ_RECOVER_ERROR))
NvRegUnknownSetupReg6 = 0x008,
#define NVREG_UNKSETUP6_VAL 3
@@ -222,6 +226,15 @@ enum {
#define NVREG_MAC_RESET_ASSERT 0x0F3
NvRegTransmitterControl = 0x084,
#define NVREG_XMITCTL_START 0x01
+#define NVREG_XMITCTL_MGMT_ST 0x40000000
+#define NVREG_XMITCTL_SYNC_MASK 0x000f0000
+#define NVREG_XMITCTL_SYNC_NOT_READY 0x0
+#define NVREG_XMITCTL_SYNC_PHY_INIT 0x00040000
+#define NVREG_XMITCTL_MGMT_SEMA_MASK 0x00000f00
+#define NVREG_XMITCTL_MGMT_SEMA_FREE 0x0
+#define NVREG_XMITCTL_HOST_SEMA_MASK 0x0000f000
+#define NVREG_XMITCTL_HOST_SEMA_ACQ 0x0000f000
+#define NVREG_XMITCTL_HOST_LOADED 0x00004000
NvRegTransmitterStatus = 0x088,
#define NVREG_XMITSTAT_BUSY 0x01
@@ -304,8 +317,8 @@ enum {
#define NVREG_MIISTAT_LINKCHANGE 0x0008
#define NVREG_MIISTAT_MASK 0x000f
#define NVREG_MIISTAT_MASK2 0x000f
- NvRegUnknownSetupReg4 = 0x184,
-#define NVREG_UNKSETUP4_VAL 8
+ NvRegMIIMask = 0x184,
+#define NVREG_MII_LINKCHANGE 0x0008
NvRegAdapterControl = 0x188,
#define NVREG_ADAPTCTL_START 0x02
@@ -707,6 +720,7 @@ struct fe_priv {
unsigned int phy_model;
u16 gigabit;
int intr_test;
+ int recover_error;
/* General data: RO fields */
dma_addr_t ring_addr;
@@ -719,6 +733,7 @@ struct fe_priv {
u32 driver_data;
u32 register_size;
int rx_csum;
+ u32 mac_in_use;
void __iomem *base;
@@ -2443,6 +2458,23 @@ static irqreturn_t nv_nic_irq(int foo, void *data)
printk(KERN_DEBUG "%s: received irq with unknown events 0x%x. Please report\n",
dev->name, events);
}
+ if (unlikely(events & NVREG_IRQ_RECOVER_ERROR)) {
+ spin_lock(&np->lock);
+ /* disable interrupts on the nic */
+ if (!(np->msi_flags & NV_MSI_X_ENABLED))
+ writel(0, base + NvRegIrqMask);
+ else
+ writel(np->irqmask, base + NvRegIrqMask);
+ pci_push(base);
+
+ if (!np->in_shutdown) {
+ np->nic_poll_irq = np->irqmask;
+ np->recover_error = 1;
+ mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
+ }
+ spin_unlock(&np->lock);
+ break;
+ }
#ifdef CONFIG_FORCEDETH_NAPI
if (events & NVREG_IRQ_RX_ALL) {
netif_rx_schedule(dev);
@@ -2673,6 +2705,20 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data)
spin_unlock_irqrestore(&np->lock, flags);
np->link_timeout = jiffies + LINK_TIMEOUT;
}
+ if (events & NVREG_IRQ_RECOVER_ERROR) {
+ spin_lock_irq(&np->lock);
+ /* disable interrupts on the nic */
+ writel(NVREG_IRQ_OTHER, base + NvRegIrqMask);
+ pci_push(base);
+
+ if (!np->in_shutdown) {
+ np->nic_poll_irq |= NVREG_IRQ_OTHER;
+ np->recover_error = 1;
+ mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
+ }
+ spin_unlock_irq(&np->lock);
+ break;
+ }
if (events & (NVREG_IRQ_UNKNOWN)) {
printk(KERN_DEBUG "%s: received irq with unknown events 0x%x. Please report\n",
dev->name, events);
@@ -2902,6 +2948,42 @@ static void nv_do_nic_poll(unsigned long data)
}
np->nic_poll_irq = 0;
+ if (np->recover_error) {
+ np->recover_error = 0;
+ printk(KERN_INFO "forcedeth: MAC in recoverable error state\n");
+ if (netif_running(dev)) {
+ netif_tx_lock_bh(dev);
+ spin_lock(&np->lock);
+ /* stop engines */
+ nv_stop_rx(dev);
+ nv_stop_tx(dev);
+ nv_txrx_reset(dev);
+ /* drain rx queue */
+ nv_drain_rx(dev);
+ nv_drain_tx(dev);
+ /* reinit driver view of the rx queue */
+ set_bufsize(dev);
+ if (nv_init_ring(dev)) {
+ if (!np->in_shutdown)
+ mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
+ }
+ /* reinit nic view of the rx queue */
+ writel(np->rx_buf_sz, base + NvRegOffloadConfig);
+ setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING);
+ writel( ((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT),
+ base + NvRegRingSizes);
+ pci_push(base);
+ writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
+ pci_push(base);
+
+ /* restart rx engine */
+ nv_start_rx(dev);
+ nv_start_tx(dev);
+ spin_unlock(&np->lock);
+ netif_tx_unlock_bh(dev);
+ }
+ }
+
/* FIXME: Do we need synchronize_irq(dev->irq) here? */
writel(mask, base + NvRegIrqMask);
@@ -4030,6 +4112,54 @@ static void nv_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
/* nothing to do */
};
+/* The mgmt unit and driver use a semaphore to access the phy during init */
+static int nv_mgmt_acquire_sema(struct net_device *dev)
+{
+ u8 __iomem *base = get_hwbase(dev);
+ int i;
+ u32 tx_ctrl, mgmt_sema;
+
+ for (i = 0; i < 10; i++) {
+ mgmt_sema = readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_MGMT_SEMA_MASK;
+ if (mgmt_sema == NVREG_XMITCTL_MGMT_SEMA_FREE)
+ break;
+ msleep(500);
+ }
+
+ if (mgmt_sema != NVREG_XMITCTL_MGMT_SEMA_FREE)
+ return 0;
+
+ for (i = 0; i < 2; i++) {
+ tx_ctrl = readl(base + NvRegTransmitterControl);
+ tx_ctrl |= NVREG_XMITCTL_HOST_SEMA_ACQ;
+ writel(tx_ctrl, base + NvRegTransmitterControl);
+
+ /* verify that semaphore was acquired */
+ tx_ctrl = readl(base + NvRegTransmitterControl);
+ if (((tx_ctrl & NVREG_XMITCTL_HOST_SEMA_MASK) == NVREG_XMITCTL_HOST_SEMA_ACQ) &&
+ ((tx_ctrl & NVREG_XMITCTL_MGMT_SEMA_MASK) == NVREG_XMITCTL_MGMT_SEMA_FREE))
+ return 1;
+ else
+ udelay(50);
+ }
+
+ return 0;
+}
+
+/* Indicate to mgmt unit whether driver is loaded or not */
+static void nv_mgmt_driver_loaded(struct net_device *dev, int loaded)
+{
+ u8 __iomem *base = get_hwbase(dev);
+ u32 tx_ctrl;
+
+ tx_ctrl = readl(base + NvRegTransmitterControl);
+ if (loaded)
+ tx_ctrl |= NVREG_XMITCTL_HOST_LOADED;
+ else
+ tx_ctrl &= ~NVREG_XMITCTL_HOST_LOADED;
+ writel(tx_ctrl, base + NvRegTransmitterControl);
+}
+
static int nv_open(struct net_device *dev)
{
struct fe_priv *np = netdev_priv(dev);
@@ -4085,7 +4215,7 @@ static int nv_open(struct net_device *dev)
NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX,
KERN_INFO "open: SetupReg5, Bit 31 remained off\n");
- writel(0, base + NvRegUnknownSetupReg4);
+ writel(0, base + NvRegMIIMask);
writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus);
@@ -4111,7 +4241,7 @@ static int nv_open(struct net_device *dev)
writel((np->phyaddr << NVREG_ADAPTCTL_PHYSHIFT)|NVREG_ADAPTCTL_PHYVALID|NVREG_ADAPTCTL_RUNNING,
base + NvRegAdapterControl);
writel(NVREG_MIISPEED_BIT8|NVREG_MIIDELAY, base + NvRegMIISpeed);
- writel(NVREG_UNKSETUP4_VAL, base + NvRegUnknownSetupReg4);
+ writel(NVREG_MII_LINKCHANGE, base + NvRegMIIMask);
if (np->wolenabled)
writel(NVREG_WAKEUPFLAGS_ENABLE , base + NvRegWakeUpFlags);
@@ -4230,6 +4360,8 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
u8 __iomem *base;
int err, i;
u32 powerstate, txreg;
+ u32 phystate_orig = 0, phystate;
+ int phyinitialized = 0;
dev = alloc_etherdev(sizeof(struct fe_priv));
err = -ENOMEM;
@@ -4514,6 +4646,48 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
np->need_linktimer = 0;
}
+ /* clear phy state and temporarily halt phy interrupts */
+ writel(0, base + NvRegMIIMask);
+ phystate = readl(base + NvRegAdapterControl);
+ if (phystate & NVREG_ADAPTCTL_RUNNING) {
+ phystate_orig = 1;
+ phystate &= ~NVREG_ADAPTCTL_RUNNING;
+ writel(phystate, base + NvRegAdapterControl);
+ }
+ writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus);
+
+ if (id->driver_data & DEV_HAS_MGMT_UNIT) {
+ writel(0x1, base + 0x204); pci_push(base);
+ msleep(500);
+ /* management unit running on the mac? */
+ np->mac_in_use = readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_MGMT_ST;
+ if (np->mac_in_use) {
+ u32 mgmt_sync;
+ /* management unit setup the phy already? */
+ mgmt_sync = readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_MASK;
+ if (mgmt_sync == NVREG_XMITCTL_SYNC_NOT_READY) {
+ if (!nv_mgmt_acquire_sema(dev)) {
+ for (i = 0; i < 5000; i++) {
+ msleep(1);
+ mgmt_sync = readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_MASK;
+ if (mgmt_sync == NVREG_XMITCTL_SYNC_NOT_READY)
+ continue;
+ if (mgmt_sync == NVREG_XMITCTL_SYNC_PHY_INIT)
+ phyinitialized = 1;
+ break;
+ }
+ } else {
+ /* we need to init the phy */
+ }
+ } else if (mgmt_sync == NVREG_XMITCTL_SYNC_PHY_INIT) {
+ /* phy is inited by SMU */
+ phyinitialized = 1;
+ } else {
+ /* we need to init the phy */
+ }
+ }
+ }
+
/* find a suitable phy */
for (i = 1; i <= 32; i++) {
int id1, id2;
@@ -4545,8 +4719,14 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
goto out_error;
}
- /* reset it */
- phy_init(dev);
+ if (!phyinitialized) {
+ /* reset it */
+ phy_init(dev);
+ }
+
+ if (id->driver_data & DEV_HAS_MGMT_UNIT) {
+ nv_mgmt_driver_loaded(dev, 1);
+ }
/* set default link speed settings */
np->linkspeed = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
@@ -4565,6 +4745,10 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
return 0;
out_error:
+ if (phystate_orig)
+ writel(phystate|NVREG_ADAPTCTL_RUNNING, base + NvRegAdapterControl);
+ if (np->mac_in_use)
+ nv_mgmt_driver_loaded(dev, 0);
pci_set_drvdata(pci_dev, NULL);
out_freering:
free_rings(dev);
@@ -4594,6 +4778,9 @@ static void __devexit nv_remove(struct pci_dev *pci_dev)
writel(np->orig_mac[0], base + NvRegMacAddrA);
writel(np->orig_mac[1], base + NvRegMacAddrB);
+ if (np->mac_in_use)
+ nv_mgmt_driver_loaded(dev, 0);
+
/* free all structures */
free_rings(dev);
iounmap(get_hwbase(dev));
@@ -4603,6 +4790,50 @@ static void __devexit nv_remove(struct pci_dev *pci_dev)
pci_set_drvdata(pci_dev, NULL);
}
+#ifdef CONFIG_PM
+static int nv_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct fe_priv *np = netdev_priv(dev);
+
+ if (!netif_running(dev))
+ goto out;
+
+ netif_device_detach(dev);
+
+ // Gross.
+ nv_close(dev);
+
+ pci_save_state(pdev);
+ pci_enable_wake(pdev, pci_choose_state(pdev, state), np->wolenabled);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+out:
+ return 0;
+}
+
+static int nv_resume(struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ int rc = 0;
+
+ if (!netif_running(dev))
+ goto out;
+
+ netif_device_attach(dev);
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+ pci_enable_wake(pdev, PCI_D0, 0);
+
+ rc = nv_open(dev);
+out:
+ return rc;
+}
+#else
+#define nv_suspend NULL
+#define nv_resume NULL
+#endif /* CONFIG_PM */
+
static struct pci_device_id pci_tbl[] = {
{ /* nForce Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_1),
@@ -4658,43 +4889,59 @@ static struct pci_device_id pci_tbl[] = {
},
{ /* 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|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED,
+ .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|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
},
{ /* 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|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED,
+ .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|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
},
{ /* MCP61 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_16),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
},
{ /* MCP61 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_17),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
},
{ /* MCP61 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_18),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
},
{ /* MCP61 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_19),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
},
{ /* MCP65 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_20),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
},
{ /* MCP65 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_21),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
},
{ /* MCP65 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_22),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
},
{ /* MCP65 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_23),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
+ },
+ { /* MCP67 Ethernet Controller */
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_24),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
+ },
+ { /* MCP67 Ethernet Controller */
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_25),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
+ },
+ { /* MCP67 Ethernet Controller */
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_26),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
+ },
+ { /* MCP67 Ethernet Controller */
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_27),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
},
{0,},
};
@@ -4704,9 +4951,10 @@ static struct pci_driver driver = {
.id_table = pci_tbl,
.probe = nv_probe,
.remove = __devexit_p(nv_remove),
+ .suspend = nv_suspend,
+ .resume = nv_resume,
};
-
static int __init init_nic(void)
{
printk(KERN_INFO "forcedeth.c: Reverse Engineered nForce ethernet driver. Version %s.\n", FORCEDETH_VERSION);
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index cb3958704a87..889d3a13e95e 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -779,7 +779,8 @@ static int fs_init_phy(struct net_device *dev)
fep->oldspeed = 0;
fep->oldduplex = -1;
if(fep->fpi->bus_id)
- phydev = phy_connect(dev, fep->fpi->bus_id, &fs_adjust_link, 0);
+ phydev = phy_connect(dev, fep->fpi->bus_id, &fs_adjust_link, 0,
+ PHY_INTERFACE_MODE_MII);
else {
printk("No phy bus ID specified in BSP code\n");
return -EINVAL;
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index a06d8d1aaceb..baa35144134c 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -9,7 +9,7 @@
* Author: Andy Fleming
* Maintainer: Kumar Gala
*
- * Copyright (c) 2002-2004 Freescale Semiconductor, Inc.
+ * Copyright (c) 2002-2006 Freescale Semiconductor, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -133,6 +133,9 @@ static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr);
#ifdef CONFIG_GFAR_NAPI
static int gfar_poll(struct net_device *dev, int *budget);
#endif
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void gfar_netpoll(struct net_device *dev);
+#endif
int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit);
static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int length);
static void gfar_vlan_rx_register(struct net_device *netdev,
@@ -260,6 +263,9 @@ static int gfar_probe(struct platform_device *pdev)
dev->poll = gfar_poll;
dev->weight = GFAR_DEV_WEIGHT;
#endif
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ dev->poll_controller = gfar_netpoll;
+#endif
dev->stop = gfar_close;
dev->get_stats = gfar_get_stats;
dev->change_mtu = gfar_change_mtu;
@@ -392,6 +398,38 @@ static int gfar_remove(struct platform_device *pdev)
}
+/* Reads the controller's registers to determine what interface
+ * connects it to the PHY.
+ */
+static phy_interface_t gfar_get_interface(struct net_device *dev)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ u32 ecntrl = gfar_read(&priv->regs->ecntrl);
+
+ if (ecntrl & ECNTRL_SGMII_MODE)
+ return PHY_INTERFACE_MODE_SGMII;
+
+ if (ecntrl & ECNTRL_TBI_MODE) {
+ if (ecntrl & ECNTRL_REDUCED_MODE)
+ return PHY_INTERFACE_MODE_RTBI;
+ else
+ return PHY_INTERFACE_MODE_TBI;
+ }
+
+ if (ecntrl & ECNTRL_REDUCED_MODE) {
+ if (ecntrl & ECNTRL_REDUCED_MII_MODE)
+ return PHY_INTERFACE_MODE_RMII;
+ else
+ return PHY_INTERFACE_MODE_RGMII;
+ }
+
+ if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT)
+ return PHY_INTERFACE_MODE_GMII;
+
+ return PHY_INTERFACE_MODE_MII;
+}
+
+
/* Initializes driver's PHY state, and attaches to the PHY.
* Returns 0 on success.
*/
@@ -403,6 +441,7 @@ static int init_phy(struct net_device *dev)
SUPPORTED_1000baseT_Full : 0;
struct phy_device *phydev;
char phy_id[BUS_ID_SIZE];
+ phy_interface_t interface;
priv->oldlink = 0;
priv->oldspeed = 0;
@@ -410,7 +449,9 @@ static int init_phy(struct net_device *dev)
snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, priv->einfo->bus_id, priv->einfo->phy_id);
- phydev = phy_connect(dev, phy_id, &adjust_link, 0);
+ interface = gfar_get_interface(dev);
+
+ phydev = phy_connect(dev, phy_id, &adjust_link, 0, interface);
if (IS_ERR(phydev)) {
printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
@@ -1536,6 +1577,33 @@ static int gfar_poll(struct net_device *dev, int *budget)
}
#endif
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * Polling 'interrupt' - used by things like netconsole to send skbs
+ * without having to re-enable interrupts. It's not called while
+ * the interrupt routine is executing.
+ */
+static void gfar_netpoll(struct net_device *dev)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+
+ /* If the device has multiple interrupts, run tx/rx */
+ if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) {
+ disable_irq(priv->interruptTransmit);
+ disable_irq(priv->interruptReceive);
+ disable_irq(priv->interruptError);
+ gfar_interrupt(priv->interruptTransmit, dev);
+ enable_irq(priv->interruptError);
+ enable_irq(priv->interruptReceive);
+ enable_irq(priv->interruptTransmit);
+ } else {
+ disable_irq(priv->interruptTransmit);
+ gfar_interrupt(priv->interruptTransmit, dev);
+ enable_irq(priv->interruptTransmit);
+ }
+}
+#endif
+
/* The interrupt handler for devices with one interrupt */
static irqreturn_t gfar_interrupt(int irq, void *dev_id)
{
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index 9e81a50cf2be..39e9e321fcbc 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -160,7 +160,10 @@ extern const char gfar_driver_version[];
#define ECNTRL_INIT_SETTINGS 0x00001000
#define ECNTRL_TBI_MODE 0x00000020
+#define ECNTRL_REDUCED_MODE 0x00000010
#define ECNTRL_R100 0x00000008
+#define ECNTRL_REDUCED_MII_MODE 0x00000004
+#define ECNTRL_SGMII_MODE 0x00000002
#define MRBLR_INIT_SETTINGS DEFAULT_RX_BUFFER_SIZE
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 86b3bb9bec2d..92420f007b97 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -914,7 +914,7 @@ static void decode_prio_command(struct sixpack *sp, unsigned char cmd)
printk(KERN_DEBUG "6pack: protocol violation\n");
else
sp->status = 0;
- cmd &= !SIXP_RX_DCD_MASK;
+ cmd &= ~SIXP_RX_DCD_MASK;
}
sp->status = cmd & SIXP_PRIO_DATA_MASK;
} else { /* output watchdog char if idle */
diff --git a/drivers/net/hydra.c b/drivers/net/hydra.c
index 91326ea3e12b..f970bfbb9db2 100644
--- a/drivers/net/hydra.c
+++ b/drivers/net/hydra.c
@@ -31,7 +31,16 @@
#include <asm/amigahw.h>
#include <linux/zorro.h>
-#include "8390.h"
+#define EI_SHIFT(x) (ei_local->reg_offset[x])
+#define ei_inb(port) in_8(port)
+#define ei_outb(val,port) out_8(port,val)
+#define ei_inb_p(port) in_8(port)
+#define ei_outb_p(val,port) out_8(port,val)
+
+static const char version[] =
+ "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+
+#include "lib8390.c"
#define NE_EN0_DCFG (0x0e*2)
@@ -100,7 +109,7 @@ static int __devinit hydra_init(struct zorro_dev *z)
0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
};
- dev = alloc_ei_netdev();
+ dev = ____alloc_ei_netdev(0);
if (!dev)
return -ENOMEM;
SET_MODULE_OWNER(dev);
@@ -117,7 +126,7 @@ static int __devinit hydra_init(struct zorro_dev *z)
dev->irq = IRQ_AMIGA_PORTS;
/* Install the Interrupt handler */
- if (request_irq(IRQ_AMIGA_PORTS, ei_interrupt, IRQF_SHARED, "Hydra Ethernet",
+ if (request_irq(IRQ_AMIGA_PORTS, __ei_interrupt, IRQF_SHARED, "Hydra Ethernet",
dev)) {
free_netdev(dev);
return -EAGAIN;
@@ -139,10 +148,10 @@ static int __devinit hydra_init(struct zorro_dev *z)
dev->open = &hydra_open;
dev->stop = &hydra_close;
#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = ei_poll;
+ dev->poll_controller = __ei_poll;
#endif
- NS8390_init(dev, 0);
+ __NS8390_init(dev, 0);
err = register_netdev(dev);
if (err) {
@@ -164,7 +173,7 @@ static int __devinit hydra_init(struct zorro_dev *z)
static int hydra_open(struct net_device *dev)
{
- ei_open(dev);
+ __ei_open(dev);
return 0;
}
@@ -172,7 +181,7 @@ static int hydra_close(struct net_device *dev)
{
if (ei_debug > 1)
printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name);
- ei_close(dev);
+ __ei_close(dev);
return 0;
}
diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
index f56b00ee385e..f0d30cf67b5f 100644
--- a/drivers/net/ioc3-eth.c
+++ b/drivers/net/ioc3-eth.c
@@ -57,7 +57,6 @@
#include <net/ip.h>
#include <asm/byteorder.h>
-#include <asm/checksum.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/uaccess.h>
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index 14bda765c2fa..6e95645e7245 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -1793,10 +1793,8 @@ err_out_3:
err_out_2:
usb_free_urb(self->tx_urb);
err_out_1:
- for (i = 0; i < self->max_rx_urb; i++) {
- if (self->rx_urb[i])
- usb_free_urb(self->rx_urb[i]);
- }
+ for (i = 0; i < self->max_rx_urb; i++)
+ usb_free_urb(self->rx_urb[i]);
free_netdev(net);
err_out:
return ret;
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index d1ebb91ed278..e628126c9c49 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -1248,7 +1248,7 @@ ixgb_tx_csum(struct ixgb_adapter *adapter, struct sk_buff *skb)
if(likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
struct ixgb_buffer *buffer_info;
css = skb->h.raw - skb->data;
- cso = (skb->h.raw + skb->csum) - skb->data;
+ cso = css + skb->csum_offset;
i = adapter->tx_ring.next_to_use;
context_desc = IXGB_CONTEXT_DESC(adapter->tx_ring, i);
diff --git a/drivers/net/lib8390.c b/drivers/net/lib8390.c
new file mode 100644
index 000000000000..e726c06b8dc6
--- /dev/null
+++ b/drivers/net/lib8390.c
@@ -0,0 +1,1097 @@
+/* 8390.c: A general NS8390 ethernet driver core for linux. */
+/*
+ Written 1992-94 by Donald Becker.
+
+ Copyright 1993 United States Government as represented by the
+ Director, National Security Agency.
+
+ This software may be used and distributed according to the terms
+ of the GNU General Public License, incorporated herein by reference.
+
+ The author may be reached as becker@scyld.com, or C/O
+ Scyld Computing Corporation
+ 410 Severn Ave., Suite 210
+ Annapolis MD 21403
+
+
+ This is the chip-specific code for many 8390-based ethernet adaptors.
+ This is not a complete driver, it must be combined with board-specific
+ code such as ne.c, wd.c, 3c503.c, etc.
+
+ Seeing how at least eight drivers use this code, (not counting the
+ PCMCIA ones either) it is easy to break some card by what seems like
+ a simple innocent change. Please contact me or Donald if you think
+ you have found something that needs changing. -- PG
+
+
+ Changelog:
+
+ Paul Gortmaker : remove set_bit lock, other cleanups.
+ Paul Gortmaker : add ei_get_8390_hdr() so we can pass skb's to
+ ei_block_input() for eth_io_copy_and_sum().
+ Paul Gortmaker : exchange static int ei_pingpong for a #define,
+ also add better Tx error handling.
+ Paul Gortmaker : rewrite Rx overrun handling as per NS specs.
+ Alexey Kuznetsov : use the 8390's six bit hash multicast filter.
+ Paul Gortmaker : tweak ANK's above multicast changes a bit.
+ Paul Gortmaker : update packet statistics for v2.1.x
+ Alan Cox : support arbitary stupid port mappings on the
+ 68K Macintosh. Support >16bit I/O spaces
+ Paul Gortmaker : add kmod support for auto-loading of the 8390
+ module by all drivers that require it.
+ Alan Cox : Spinlocking work, added 'BUG_83C690'
+ Paul Gortmaker : Separate out Tx timeout code from Tx path.
+ Paul Gortmaker : Remove old unused single Tx buffer code.
+ Hayato Fujiwara : Add m32r support.
+ Paul Gortmaker : use skb_padto() instead of stack scratch area
+
+ Sources:
+ The National Semiconductor LAN Databook, and the 3Com 3c503 databook.
+
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/jiffies.h>
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/bitops.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fcntl.h>
+#include <linux/in.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/crc32.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#define NS8390_CORE
+#include "8390.h"
+
+#define BUG_83C690
+
+/* These are the operational function interfaces to board-specific
+ routines.
+ void reset_8390(struct net_device *dev)
+ Resets the board associated with DEV, including a hardware reset of
+ the 8390. This is only called when there is a transmit timeout, and
+ it is always followed by 8390_init().
+ void block_output(struct net_device *dev, int count, const unsigned char *buf,
+ int start_page)
+ Write the COUNT bytes of BUF to the packet buffer at START_PAGE. The
+ "page" value uses the 8390's 256-byte pages.
+ void get_8390_hdr(struct net_device *dev, struct e8390_hdr *hdr, int ring_page)
+ Read the 4 byte, page aligned 8390 header. *If* there is a
+ subsequent read, it will be of the rest of the packet.
+ void block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
+ Read COUNT bytes from the packet buffer into the skb data area. Start
+ reading from RING_OFFSET, the address as the 8390 sees it. This will always
+ follow the read of the 8390 header.
+*/
+#define ei_reset_8390 (ei_local->reset_8390)
+#define ei_block_output (ei_local->block_output)
+#define ei_block_input (ei_local->block_input)
+#define ei_get_8390_hdr (ei_local->get_8390_hdr)
+
+/* use 0 for production, 1 for verification, >2 for debug */
+#ifndef ei_debug
+int ei_debug = 1;
+#endif
+
+/* Index to functions. */
+static void ei_tx_intr(struct net_device *dev);
+static void ei_tx_err(struct net_device *dev);
+static void ei_tx_timeout(struct net_device *dev);
+static void ei_receive(struct net_device *dev);
+static void ei_rx_overrun(struct net_device *dev);
+
+/* Routines generic to NS8390-based boards. */
+static void NS8390_trigger_send(struct net_device *dev, unsigned int length,
+ int start_page);
+static void set_multicast_list(struct net_device *dev);
+static void do_set_multicast_list(struct net_device *dev);
+static void __NS8390_init(struct net_device *dev, int startp);
+
+/*
+ * SMP and the 8390 setup.
+ *
+ * The 8390 isnt exactly designed to be multithreaded on RX/TX. There is
+ * a page register that controls bank and packet buffer access. We guard
+ * this with ei_local->page_lock. Nobody should assume or set the page other
+ * than zero when the lock is not held. Lock holders must restore page 0
+ * before unlocking. Even pure readers must take the lock to protect in
+ * page 0.
+ *
+ * To make life difficult the chip can also be very slow. We therefore can't
+ * just use spinlocks. For the longer lockups we disable the irq the device
+ * sits on and hold the lock. We must hold the lock because there is a dual
+ * processor case other than interrupts (get stats/set multicast list in
+ * parallel with each other and transmit).
+ *
+ * Note: in theory we can just disable the irq on the card _but_ there is
+ * a latency on SMP irq delivery. So we can easily go "disable irq" "sync irqs"
+ * enter lock, take the queued irq. So we waddle instead of flying.
+ *
+ * Finally by special arrangement for the purpose of being generally
+ * annoying the transmit function is called bh atomic. That places
+ * restrictions on the user context callers as disable_irq won't save
+ * them.
+ */
+
+
+
+/**
+ * ei_open - Open/initialize the board.
+ * @dev: network device to initialize
+ *
+ * This routine goes all-out, setting everything
+ * up anew at each open, even though many of these registers should only
+ * need to be set once at boot.
+ */
+static int __ei_open(struct net_device *dev)
+{
+ unsigned long flags;
+ struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+
+ /* The card I/O part of the driver (e.g. 3c503) can hook a Tx timeout
+ wrapper that does e.g. media check & then calls ei_tx_timeout. */
+ if (dev->tx_timeout == NULL)
+ dev->tx_timeout = ei_tx_timeout;
+ if (dev->watchdog_timeo <= 0)
+ dev->watchdog_timeo = TX_TIMEOUT;
+
+ /*
+ * Grab the page lock so we own the register set, then call
+ * the init function.
+ */
+
+ spin_lock_irqsave(&ei_local->page_lock, flags);
+ __NS8390_init(dev, 1);
+ /* Set the flag before we drop the lock, That way the IRQ arrives
+ after its set and we get no silly warnings */
+ netif_start_queue(dev);
+ spin_unlock_irqrestore(&ei_local->page_lock, flags);
+ ei_local->irqlock = 0;
+ return 0;
+}
+
+/**
+ * ei_close - shut down network device
+ * @dev: network device to close
+ *
+ * Opposite of ei_open(). Only used when "ifconfig <devname> down" is done.
+ */
+static int __ei_close(struct net_device *dev)
+{
+ struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+ unsigned long flags;
+
+ /*
+ * Hold the page lock during close
+ */
+
+ spin_lock_irqsave(&ei_local->page_lock, flags);
+ __NS8390_init(dev, 0);
+ spin_unlock_irqrestore(&ei_local->page_lock, flags);
+ netif_stop_queue(dev);
+ return 0;
+}
+
+/**
+ * ei_tx_timeout - handle transmit time out condition
+ * @dev: network device which has apparently fallen asleep
+ *
+ * Called by kernel when device never acknowledges a transmit has
+ * completed (or failed) - i.e. never posted a Tx related interrupt.
+ */
+
+static void ei_tx_timeout(struct net_device *dev)
+{
+ unsigned long e8390_base = dev->base_addr;
+ struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+ int txsr, isr, tickssofar = jiffies - dev->trans_start;
+ unsigned long flags;
+
+#if defined(CONFIG_M32R) && defined(CONFIG_SMP)
+ unsigned long icucr;
+
+ local_irq_save(flags);
+ icucr = inl(M32R_ICU_CR1_PORTL);
+ icucr |= M32R_ICUCR_ISMOD11;
+ outl(icucr, M32R_ICU_CR1_PORTL);
+ local_irq_restore(flags);
+#endif
+ ei_local->stat.tx_errors++;
+
+ spin_lock_irqsave(&ei_local->page_lock, flags);
+ txsr = ei_inb(e8390_base+EN0_TSR);
+ isr = ei_inb(e8390_base+EN0_ISR);
+ spin_unlock_irqrestore(&ei_local->page_lock, flags);
+
+ printk(KERN_DEBUG "%s: Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n",
+ dev->name, (txsr & ENTSR_ABT) ? "excess collisions." :
+ (isr) ? "lost interrupt?" : "cable problem?", txsr, isr, tickssofar);
+
+ if (!isr && !ei_local->stat.tx_packets)
+ {
+ /* The 8390 probably hasn't gotten on the cable yet. */
+ ei_local->interface_num ^= 1; /* Try a different xcvr. */
+ }
+
+ /* Ugly but a reset can be slow, yet must be protected */
+
+ disable_irq_nosync_lockdep(dev->irq);
+ spin_lock(&ei_local->page_lock);
+
+ /* Try to restart the card. Perhaps the user has fixed something. */
+ ei_reset_8390(dev);
+ __NS8390_init(dev, 1);
+
+ spin_unlock(&ei_local->page_lock);
+ enable_irq_lockdep(dev->irq);
+ netif_wake_queue(dev);
+}
+
+/**
+ * ei_start_xmit - begin packet transmission
+ * @skb: packet to be sent
+ * @dev: network device to which packet is sent
+ *
+ * Sends a packet to an 8390 network device.
+ */
+
+static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ unsigned long e8390_base = dev->base_addr;
+ struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+ int send_length = skb->len, output_page;
+ unsigned long flags;
+ char buf[ETH_ZLEN];
+ char *data = skb->data;
+
+ if (skb->len < ETH_ZLEN) {
+ memset(buf, 0, ETH_ZLEN); /* more efficient than doing just the needed bits */
+ memcpy(buf, data, skb->len);
+ send_length = ETH_ZLEN;
+ data = buf;
+ }
+
+ /* Mask interrupts from the ethercard.
+ SMP: We have to grab the lock here otherwise the IRQ handler
+ on another CPU can flip window and race the IRQ mask set. We end
+ up trashing the mcast filter not disabling irqs if we don't lock */
+
+ spin_lock_irqsave(&ei_local->page_lock, flags);
+ ei_outb_p(0x00, e8390_base + EN0_IMR);
+ spin_unlock_irqrestore(&ei_local->page_lock, flags);
+
+
+ /*
+ * Slow phase with lock held.
+ */
+
+ disable_irq_nosync_lockdep_irqsave(dev->irq, &flags);
+
+ spin_lock(&ei_local->page_lock);
+
+ ei_local->irqlock = 1;
+
+ /*
+ * We have two Tx slots available for use. Find the first free
+ * slot, and then perform some sanity checks. With two Tx bufs,
+ * you get very close to transmitting back-to-back packets. With
+ * only one Tx buf, the transmitter sits idle while you reload the
+ * card, leaving a substantial gap between each transmitted packet.
+ */
+
+ if (ei_local->tx1 == 0)
+ {
+ output_page = ei_local->tx_start_page;
+ ei_local->tx1 = send_length;
+ if (ei_debug && ei_local->tx2 > 0)
+ printk(KERN_DEBUG "%s: idle transmitter tx2=%d, lasttx=%d, txing=%d.\n",
+ dev->name, ei_local->tx2, ei_local->lasttx, ei_local->txing);
+ }
+ else if (ei_local->tx2 == 0)
+ {
+ output_page = ei_local->tx_start_page + TX_PAGES/2;
+ ei_local->tx2 = send_length;
+ if (ei_debug && ei_local->tx1 > 0)
+ printk(KERN_DEBUG "%s: idle transmitter, tx1=%d, lasttx=%d, txing=%d.\n",
+ dev->name, ei_local->tx1, ei_local->lasttx, ei_local->txing);
+ }
+ else
+ { /* We should never get here. */
+ if (ei_debug)
+ printk(KERN_DEBUG "%s: No Tx buffers free! tx1=%d tx2=%d last=%d\n",
+ dev->name, ei_local->tx1, ei_local->tx2, ei_local->lasttx);
+ ei_local->irqlock = 0;
+ netif_stop_queue(dev);
+ ei_outb_p(ENISR_ALL, e8390_base + EN0_IMR);
+ spin_unlock(&ei_local->page_lock);
+ enable_irq_lockdep_irqrestore(dev->irq, &flags);
+ ei_local->stat.tx_errors++;
+ return 1;
+ }
+
+ /*
+ * Okay, now upload the packet and trigger a send if the transmitter
+ * isn't already sending. If it is busy, the interrupt handler will
+ * trigger the send later, upon receiving a Tx done interrupt.
+ */
+
+ ei_block_output(dev, send_length, data, output_page);
+
+ if (! ei_local->txing)
+ {
+ ei_local->txing = 1;
+ NS8390_trigger_send(dev, send_length, output_page);
+ dev->trans_start = jiffies;
+ if (output_page == ei_local->tx_start_page)
+ {
+ ei_local->tx1 = -1;
+ ei_local->lasttx = -1;
+ }
+ else
+ {
+ ei_local->tx2 = -1;
+ ei_local->lasttx = -2;
+ }
+ }
+ else ei_local->txqueue++;
+
+ if (ei_local->tx1 && ei_local->tx2)
+ netif_stop_queue(dev);
+ else
+ netif_start_queue(dev);
+
+ /* Turn 8390 interrupts back on. */
+ ei_local->irqlock = 0;
+ ei_outb_p(ENISR_ALL, e8390_base + EN0_IMR);
+
+ spin_unlock(&ei_local->page_lock);
+ enable_irq_lockdep_irqrestore(dev->irq, &flags);
+
+ dev_kfree_skb (skb);
+ ei_local->stat.tx_bytes += send_length;
+
+ return 0;
+}
+
+/**
+ * ei_interrupt - handle the interrupts from an 8390
+ * @irq: interrupt number
+ * @dev_id: a pointer to the net_device
+ *
+ * Handle the ether interface interrupts. We pull packets from
+ * the 8390 via the card specific functions and fire them at the networking
+ * stack. We also handle transmit completions and wake the transmit path if
+ * necessary. We also update the counters and do other housekeeping as
+ * needed.
+ */
+
+static irqreturn_t __ei_interrupt(int irq, void *dev_id)
+{
+ struct net_device *dev = dev_id;
+ unsigned long e8390_base = dev->base_addr;
+ int interrupts, nr_serviced = 0;
+ struct ei_device *ei_local = netdev_priv(dev);
+
+ /*
+ * Protect the irq test too.
+ */
+
+ spin_lock(&ei_local->page_lock);
+
+ if (ei_local->irqlock)
+ {
+#if 1 /* This might just be an interrupt for a PCI device sharing this line */
+ /* The "irqlock" check is only for testing. */
+ printk(ei_local->irqlock
+ ? "%s: Interrupted while interrupts are masked! isr=%#2x imr=%#2x.\n"
+ : "%s: Reentering the interrupt handler! isr=%#2x imr=%#2x.\n",
+ dev->name, ei_inb_p(e8390_base + EN0_ISR),
+ ei_inb_p(e8390_base + EN0_IMR));
+#endif
+ spin_unlock(&ei_local->page_lock);
+ return IRQ_NONE;
+ }
+
+ /* Change to page 0 and read the intr status reg. */
+ ei_outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD);
+ if (ei_debug > 3)
+ printk(KERN_DEBUG "%s: interrupt(isr=%#2.2x).\n", dev->name,
+ ei_inb_p(e8390_base + EN0_ISR));
+
+ /* !!Assumption!! -- we stay in page 0. Don't break this. */
+ while ((interrupts = ei_inb_p(e8390_base + EN0_ISR)) != 0
+ && ++nr_serviced < MAX_SERVICE)
+ {
+ if (!netif_running(dev)) {
+ printk(KERN_WARNING "%s: interrupt from stopped card\n", dev->name);
+ /* rmk - acknowledge the interrupts */
+ ei_outb_p(interrupts, e8390_base + EN0_ISR);
+ interrupts = 0;
+ break;
+ }
+ if (interrupts & ENISR_OVER)
+ ei_rx_overrun(dev);
+ else if (interrupts & (ENISR_RX+ENISR_RX_ERR))
+ {
+ /* Got a good (?) packet. */
+ ei_receive(dev);
+ }
+ /* Push the next to-transmit packet through. */
+ if (interrupts & ENISR_TX)
+ ei_tx_intr(dev);
+ else if (interrupts & ENISR_TX_ERR)
+ ei_tx_err(dev);
+
+ if (interrupts & ENISR_COUNTERS)
+ {
+ ei_local->stat.rx_frame_errors += ei_inb_p(e8390_base + EN0_COUNTER0);
+ ei_local->stat.rx_crc_errors += ei_inb_p(e8390_base + EN0_COUNTER1);
+ ei_local->stat.rx_missed_errors+= ei_inb_p(e8390_base + EN0_COUNTER2);
+ ei_outb_p(ENISR_COUNTERS, e8390_base + EN0_ISR); /* Ack intr. */
+ }
+
+ /* Ignore any RDC interrupts that make it back to here. */
+ if (interrupts & ENISR_RDC)
+ {
+ ei_outb_p(ENISR_RDC, e8390_base + EN0_ISR);
+ }
+
+ ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD);
+ }
+
+ if (interrupts && ei_debug)
+ {
+ ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD);
+ if (nr_serviced >= MAX_SERVICE)
+ {
+ /* 0xFF is valid for a card removal */
+ if(interrupts!=0xFF)
+ printk(KERN_WARNING "%s: Too much work at interrupt, status %#2.2x\n",
+ dev->name, interrupts);
+ ei_outb_p(ENISR_ALL, e8390_base + EN0_ISR); /* Ack. most intrs. */
+ } else {
+ printk(KERN_WARNING "%s: unknown interrupt %#2x\n", dev->name, interrupts);
+ ei_outb_p(0xff, e8390_base + EN0_ISR); /* Ack. all intrs. */
+ }
+ }
+ spin_unlock(&ei_local->page_lock);
+ return IRQ_RETVAL(nr_serviced > 0);
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void __ei_poll(struct net_device *dev)
+{
+ disable_irq_lockdep(dev->irq);
+ __ei_interrupt(dev->irq, dev);
+ enable_irq_lockdep(dev->irq);
+}
+#endif
+
+/**
+ * ei_tx_err - handle transmitter error
+ * @dev: network device which threw the exception
+ *
+ * A transmitter error has happened. Most likely excess collisions (which
+ * is a fairly normal condition). If the error is one where the Tx will
+ * have been aborted, we try and send another one right away, instead of
+ * letting the failed packet sit and collect dust in the Tx buffer. This
+ * is a much better solution as it avoids kernel based Tx timeouts, and
+ * an unnecessary card reset.
+ *
+ * Called with lock held.
+ */
+
+static void ei_tx_err(struct net_device *dev)
+{
+ unsigned long e8390_base = dev->base_addr;
+ struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+ unsigned char txsr = ei_inb_p(e8390_base+EN0_TSR);
+ unsigned char tx_was_aborted = txsr & (ENTSR_ABT+ENTSR_FU);
+
+#ifdef VERBOSE_ERROR_DUMP
+ printk(KERN_DEBUG "%s: transmitter error (%#2x): ", dev->name, txsr);
+ if (txsr & ENTSR_ABT)
+ printk("excess-collisions ");
+ if (txsr & ENTSR_ND)
+ printk("non-deferral ");
+ if (txsr & ENTSR_CRS)
+ printk("lost-carrier ");
+ if (txsr & ENTSR_FU)
+ printk("FIFO-underrun ");
+ if (txsr & ENTSR_CDH)
+ printk("lost-heartbeat ");
+ printk("\n");
+#endif
+
+ ei_outb_p(ENISR_TX_ERR, e8390_base + EN0_ISR); /* Ack intr. */
+
+ if (tx_was_aborted)
+ ei_tx_intr(dev);
+ else
+ {
+ ei_local->stat.tx_errors++;
+ if (txsr & ENTSR_CRS) ei_local->stat.tx_carrier_errors++;
+ if (txsr & ENTSR_CDH) ei_local->stat.tx_heartbeat_errors++;
+ if (txsr & ENTSR_OWC) ei_local->stat.tx_window_errors++;
+ }
+}
+
+/**
+ * ei_tx_intr - transmit interrupt handler
+ * @dev: network device for which tx intr is handled
+ *
+ * We have finished a transmit: check for errors and then trigger the next
+ * packet to be sent. Called with lock held.
+ */
+
+static void ei_tx_intr(struct net_device *dev)
+{
+ unsigned long e8390_base = dev->base_addr;
+ struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+ int status = ei_inb(e8390_base + EN0_TSR);
+
+ ei_outb_p(ENISR_TX, e8390_base + EN0_ISR); /* Ack intr. */
+
+ /*
+ * There are two Tx buffers, see which one finished, and trigger
+ * the send of another one if it exists.
+ */
+ ei_local->txqueue--;
+
+ if (ei_local->tx1 < 0)
+ {
+ if (ei_local->lasttx != 1 && ei_local->lasttx != -1)
+ printk(KERN_ERR "%s: bogus last_tx_buffer %d, tx1=%d.\n",
+ ei_local->name, ei_local->lasttx, ei_local->tx1);
+ ei_local->tx1 = 0;
+ if (ei_local->tx2 > 0)
+ {
+ ei_local->txing = 1;
+ NS8390_trigger_send(dev, ei_local->tx2, ei_local->tx_start_page + 6);
+ dev->trans_start = jiffies;
+ ei_local->tx2 = -1,
+ ei_local->lasttx = 2;
+ }
+ else ei_local->lasttx = 20, ei_local->txing = 0;
+ }
+ else if (ei_local->tx2 < 0)
+ {
+ if (ei_local->lasttx != 2 && ei_local->lasttx != -2)
+ printk("%s: bogus last_tx_buffer %d, tx2=%d.\n",
+ ei_local->name, ei_local->lasttx, ei_local->tx2);
+ ei_local->tx2 = 0;
+ if (ei_local->tx1 > 0)
+ {
+ ei_local->txing = 1;
+ NS8390_trigger_send(dev, ei_local->tx1, ei_local->tx_start_page);
+ dev->trans_start = jiffies;
+ ei_local->tx1 = -1;
+ ei_local->lasttx = 1;
+ }
+ else
+ ei_local->lasttx = 10, ei_local->txing = 0;
+ }
+// else printk(KERN_WARNING "%s: unexpected TX-done interrupt, lasttx=%d.\n",
+// dev->name, ei_local->lasttx);
+
+ /* Minimize Tx latency: update the statistics after we restart TXing. */
+ if (status & ENTSR_COL)
+ ei_local->stat.collisions++;
+ if (status & ENTSR_PTX)
+ ei_local->stat.tx_packets++;
+ else
+ {
+ ei_local->stat.tx_errors++;
+ if (status & ENTSR_ABT)
+ {
+ ei_local->stat.tx_aborted_errors++;
+ ei_local->stat.collisions += 16;
+ }
+ if (status & ENTSR_CRS)
+ ei_local->stat.tx_carrier_errors++;
+ if (status & ENTSR_FU)
+ ei_local->stat.tx_fifo_errors++;
+ if (status & ENTSR_CDH)
+ ei_local->stat.tx_heartbeat_errors++;
+ if (status & ENTSR_OWC)
+ ei_local->stat.tx_window_errors++;
+ }
+ netif_wake_queue(dev);
+}
+
+/**
+ * ei_receive - receive some packets
+ * @dev: network device with which receive will be run
+ *
+ * We have a good packet(s), get it/them out of the buffers.
+ * Called with lock held.
+ */
+
+static void ei_receive(struct net_device *dev)
+{
+ unsigned long e8390_base = dev->base_addr;
+ struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+ unsigned char rxing_page, this_frame, next_frame;
+ unsigned short current_offset;
+ int rx_pkt_count = 0;
+ struct e8390_pkt_hdr rx_frame;
+ int num_rx_pages = ei_local->stop_page-ei_local->rx_start_page;
+
+ while (++rx_pkt_count < 10)
+ {
+ int pkt_len, pkt_stat;
+
+ /* Get the rx page (incoming packet pointer). */
+ ei_outb_p(E8390_NODMA+E8390_PAGE1, e8390_base + E8390_CMD);
+ rxing_page = ei_inb_p(e8390_base + EN1_CURPAG);
+ ei_outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD);
+
+ /* Remove one frame from the ring. Boundary is always a page behind. */
+ this_frame = ei_inb_p(e8390_base + EN0_BOUNDARY) + 1;
+ if (this_frame >= ei_local->stop_page)
+ this_frame = ei_local->rx_start_page;
+
+ /* Someday we'll omit the previous, iff we never get this message.
+ (There is at least one clone claimed to have a problem.)
+
+ Keep quiet if it looks like a card removal. One problem here
+ is that some clones crash in roughly the same way.
+ */
+ if (ei_debug > 0 && this_frame != ei_local->current_page && (this_frame!=0x0 || rxing_page!=0xFF))
+ printk(KERN_ERR "%s: mismatched read page pointers %2x vs %2x.\n",
+ dev->name, this_frame, ei_local->current_page);
+
+ if (this_frame == rxing_page) /* Read all the frames? */
+ break; /* Done for now */
+
+ current_offset = this_frame << 8;
+ ei_get_8390_hdr(dev, &rx_frame, this_frame);
+
+ pkt_len = rx_frame.count - sizeof(struct e8390_pkt_hdr);
+ pkt_stat = rx_frame.status;
+
+ next_frame = this_frame + 1 + ((pkt_len+4)>>8);
+
+ /* Check for bogosity warned by 3c503 book: the status byte is never
+ written. This happened a lot during testing! This code should be
+ cleaned up someday. */
+ if (rx_frame.next != next_frame
+ && rx_frame.next != next_frame + 1
+ && rx_frame.next != next_frame - num_rx_pages
+ && rx_frame.next != next_frame + 1 - num_rx_pages) {
+ ei_local->current_page = rxing_page;
+ ei_outb(ei_local->current_page-1, e8390_base+EN0_BOUNDARY);
+ ei_local->stat.rx_errors++;
+ continue;
+ }
+
+ if (pkt_len < 60 || pkt_len > 1518)
+ {
+ if (ei_debug)
+ printk(KERN_DEBUG "%s: bogus packet size: %d, status=%#2x nxpg=%#2x.\n",
+ dev->name, rx_frame.count, rx_frame.status,
+ rx_frame.next);
+ ei_local->stat.rx_errors++;
+ ei_local->stat.rx_length_errors++;
+ }
+ else if ((pkt_stat & 0x0F) == ENRSR_RXOK)
+ {
+ struct sk_buff *skb;
+
+ skb = dev_alloc_skb(pkt_len+2);
+ if (skb == NULL)
+ {
+ if (ei_debug > 1)
+ printk(KERN_DEBUG "%s: Couldn't allocate a sk_buff of size %d.\n",
+ dev->name, pkt_len);
+ ei_local->stat.rx_dropped++;
+ break;
+ }
+ else
+ {
+ skb_reserve(skb,2); /* IP headers on 16 byte boundaries */
+ skb->dev = dev;
+ skb_put(skb, pkt_len); /* Make room */
+ ei_block_input(dev, pkt_len, skb, current_offset + sizeof(rx_frame));
+ skb->protocol=eth_type_trans(skb,dev);
+ netif_rx(skb);
+ dev->last_rx = jiffies;
+ ei_local->stat.rx_packets++;
+ ei_local->stat.rx_bytes += pkt_len;
+ if (pkt_stat & ENRSR_PHY)
+ ei_local->stat.multicast++;
+ }
+ }
+ else
+ {
+ if (ei_debug)
+ printk(KERN_DEBUG "%s: bogus packet: status=%#2x nxpg=%#2x size=%d\n",
+ dev->name, rx_frame.status, rx_frame.next,
+ rx_frame.count);
+ ei_local->stat.rx_errors++;
+ /* NB: The NIC counts CRC, frame and missed errors. */
+ if (pkt_stat & ENRSR_FO)
+ ei_local->stat.rx_fifo_errors++;
+ }
+ next_frame = rx_frame.next;
+
+ /* This _should_ never happen: it's here for avoiding bad clones. */
+ if (next_frame >= ei_local->stop_page) {
+ printk("%s: next frame inconsistency, %#2x\n", dev->name,
+ next_frame);
+ next_frame = ei_local->rx_start_page;
+ }
+ ei_local->current_page = next_frame;
+ ei_outb_p(next_frame-1, e8390_base+EN0_BOUNDARY);
+ }
+
+ /* We used to also ack ENISR_OVER here, but that would sometimes mask
+ a real overrun, leaving the 8390 in a stopped state with rec'vr off. */
+ ei_outb_p(ENISR_RX+ENISR_RX_ERR, e8390_base+EN0_ISR);
+ return;
+}
+
+/**
+ * ei_rx_overrun - handle receiver overrun
+ * @dev: network device which threw exception
+ *
+ * We have a receiver overrun: we have to kick the 8390 to get it started
+ * again. Problem is that you have to kick it exactly as NS prescribes in
+ * the updated datasheets, or "the NIC may act in an unpredictable manner."
+ * This includes causing "the NIC to defer indefinitely when it is stopped
+ * on a busy network." Ugh.
+ * Called with lock held. Don't call this with the interrupts off or your
+ * computer will hate you - it takes 10ms or so.
+ */
+
+static void ei_rx_overrun(struct net_device *dev)
+{
+ unsigned long e8390_base = dev->base_addr;
+ unsigned char was_txing, must_resend = 0;
+ struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+
+ /*
+ * Record whether a Tx was in progress and then issue the
+ * stop command.
+ */
+ was_txing = ei_inb_p(e8390_base+E8390_CMD) & E8390_TRANS;
+ ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
+
+ if (ei_debug > 1)
+ printk(KERN_DEBUG "%s: Receiver overrun.\n", dev->name);
+ ei_local->stat.rx_over_errors++;
+
+ /*
+ * Wait a full Tx time (1.2ms) + some guard time, NS says 1.6ms total.
+ * Early datasheets said to poll the reset bit, but now they say that
+ * it "is not a reliable indicator and subsequently should be ignored."
+ * We wait at least 10ms.
+ */
+
+ mdelay(10);
+
+ /*
+ * Reset RBCR[01] back to zero as per magic incantation.
+ */
+ ei_outb_p(0x00, e8390_base+EN0_RCNTLO);
+ ei_outb_p(0x00, e8390_base+EN0_RCNTHI);
+
+ /*
+ * See if any Tx was interrupted or not. According to NS, this
+ * step is vital, and skipping it will cause no end of havoc.
+ */
+
+ if (was_txing)
+ {
+ unsigned char tx_completed = ei_inb_p(e8390_base+EN0_ISR) & (ENISR_TX+ENISR_TX_ERR);
+ if (!tx_completed)
+ must_resend = 1;
+ }
+
+ /*
+ * Have to enter loopback mode and then restart the NIC before
+ * you are allowed to slurp packets up off the ring.
+ */
+ ei_outb_p(E8390_TXOFF, e8390_base + EN0_TXCR);
+ ei_outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, e8390_base + E8390_CMD);
+
+ /*
+ * Clear the Rx ring of all the debris, and ack the interrupt.
+ */
+ ei_receive(dev);
+ ei_outb_p(ENISR_OVER, e8390_base+EN0_ISR);
+
+ /*
+ * Leave loopback mode, and resend any packet that got stopped.
+ */
+ ei_outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR);
+ if (must_resend)
+ ei_outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START + E8390_TRANS, e8390_base + E8390_CMD);
+}
+
+/*
+ * Collect the stats. This is called unlocked and from several contexts.
+ */
+
+static struct net_device_stats *get_stats(struct net_device *dev)
+{
+ unsigned long ioaddr = dev->base_addr;
+ struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+ unsigned long flags;
+
+ /* If the card is stopped, just return the present stats. */
+ if (!netif_running(dev))
+ return &ei_local->stat;
+
+ spin_lock_irqsave(&ei_local->page_lock,flags);
+ /* Read the counter registers, assuming we are in page 0. */
+ ei_local->stat.rx_frame_errors += ei_inb_p(ioaddr + EN0_COUNTER0);
+ ei_local->stat.rx_crc_errors += ei_inb_p(ioaddr + EN0_COUNTER1);
+ ei_local->stat.rx_missed_errors+= ei_inb_p(ioaddr + EN0_COUNTER2);
+ spin_unlock_irqrestore(&ei_local->page_lock, flags);
+
+ return &ei_local->stat;
+}
+
+/*
+ * Form the 64 bit 8390 multicast table from the linked list of addresses
+ * associated with this dev structure.
+ */
+
+static inline void make_mc_bits(u8 *bits, struct net_device *dev)
+{
+ struct dev_mc_list *dmi;
+
+ for (dmi=dev->mc_list; dmi; dmi=dmi->next)
+ {
+ u32 crc;
+ if (dmi->dmi_addrlen != ETH_ALEN)
+ {
+ printk(KERN_INFO "%s: invalid multicast address length given.\n", dev->name);
+ continue;
+ }
+ crc = ether_crc(ETH_ALEN, dmi->dmi_addr);
+ /*
+ * The 8390 uses the 6 most significant bits of the
+ * CRC to index the multicast table.
+ */
+ bits[crc>>29] |= (1<<((crc>>26)&7));
+ }
+}
+
+/**
+ * do_set_multicast_list - set/clear multicast filter
+ * @dev: net device for which multicast filter is adjusted
+ *
+ * Set or clear the multicast filter for this adaptor. May be called
+ * from a BH in 2.1.x. Must be called with lock held.
+ */
+
+static void do_set_multicast_list(struct net_device *dev)
+{
+ unsigned long e8390_base = dev->base_addr;
+ int i;
+ struct ei_device *ei_local = (struct ei_device*)netdev_priv(dev);
+
+ if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI)))
+ {
+ memset(ei_local->mcfilter, 0, 8);
+ if (dev->mc_list)
+ make_mc_bits(ei_local->mcfilter, dev);
+ }
+ else
+ memset(ei_local->mcfilter, 0xFF, 8); /* mcast set to accept-all */
+
+ /*
+ * DP8390 manuals don't specify any magic sequence for altering
+ * the multicast regs on an already running card. To be safe, we
+ * ensure multicast mode is off prior to loading up the new hash
+ * table. If this proves to be not enough, we can always resort
+ * to stopping the NIC, loading the table and then restarting.
+ *
+ * Bug Alert! The MC regs on the SMC 83C690 (SMC Elite and SMC
+ * Elite16) appear to be write-only. The NS 8390 data sheet lists
+ * them as r/w so this is a bug. The SMC 83C790 (SMC Ultra and
+ * Ultra32 EISA) appears to have this bug fixed.
+ */
+
+ if (netif_running(dev))
+ ei_outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR);
+ ei_outb_p(E8390_NODMA + E8390_PAGE1, e8390_base + E8390_CMD);
+ for(i = 0; i < 8; i++)
+ {
+ ei_outb_p(ei_local->mcfilter[i], e8390_base + EN1_MULT_SHIFT(i));
+#ifndef BUG_83C690
+ if(ei_inb_p(e8390_base + EN1_MULT_SHIFT(i))!=ei_local->mcfilter[i])
+ printk(KERN_ERR "Multicast filter read/write mismap %d\n",i);
+#endif
+ }
+ ei_outb_p(E8390_NODMA + E8390_PAGE0, e8390_base + E8390_CMD);
+
+ if(dev->flags&IFF_PROMISC)
+ ei_outb_p(E8390_RXCONFIG | 0x18, e8390_base + EN0_RXCR);
+ else if(dev->flags&IFF_ALLMULTI || dev->mc_list)
+ ei_outb_p(E8390_RXCONFIG | 0x08, e8390_base + EN0_RXCR);
+ else
+ ei_outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR);
+ }
+
+/*
+ * Called without lock held. This is invoked from user context and may
+ * be parallel to just about everything else. Its also fairly quick and
+ * not called too often. Must protect against both bh and irq users
+ */
+
+static void set_multicast_list(struct net_device *dev)
+{
+ unsigned long flags;
+ struct ei_device *ei_local = (struct ei_device*)netdev_priv(dev);
+
+ spin_lock_irqsave(&ei_local->page_lock, flags);
+ do_set_multicast_list(dev);
+ spin_unlock_irqrestore(&ei_local->page_lock, flags);
+}
+
+/**
+ * ethdev_setup - init rest of 8390 device struct
+ * @dev: network device structure to init
+ *
+ * Initialize the rest of the 8390 device structure. Do NOT __init
+ * this, as it is used by 8390 based modular drivers too.
+ */
+
+static void ethdev_setup(struct net_device *dev)
+{
+ struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+ if (ei_debug > 1)
+ printk(version);
+
+ dev->hard_start_xmit = &ei_start_xmit;
+ dev->get_stats = get_stats;
+ dev->set_multicast_list = &set_multicast_list;
+
+ ether_setup(dev);
+
+ spin_lock_init(&ei_local->page_lock);
+}
+
+/**
+ * alloc_ei_netdev - alloc_etherdev counterpart for 8390
+ * @size: extra bytes to allocate
+ *
+ * Allocate 8390-specific net_device.
+ */
+static struct net_device *____alloc_ei_netdev(int size)
+{
+ return alloc_netdev(sizeof(struct ei_device) + size, "eth%d",
+ ethdev_setup);
+}
+
+
+
+
+/* This page of functions should be 8390 generic */
+/* Follow National Semi's recommendations for initializing the "NIC". */
+
+/**
+ * NS8390_init - initialize 8390 hardware
+ * @dev: network device to initialize
+ * @startp: boolean. non-zero value to initiate chip processing
+ *
+ * Must be called with lock held.
+ */
+
+static void __NS8390_init(struct net_device *dev, int startp)
+{
+ unsigned long e8390_base = dev->base_addr;
+ struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+ int i;
+ int endcfg = ei_local->word16
+ ? (0x48 | ENDCFG_WTS | (ei_local->bigendian ? ENDCFG_BOS : 0))
+ : 0x48;
+
+ if(sizeof(struct e8390_pkt_hdr)!=4)
+ panic("8390.c: header struct mispacked\n");
+ /* Follow National Semi's recommendations for initing the DP83902. */
+ ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); /* 0x21 */
+ ei_outb_p(endcfg, e8390_base + EN0_DCFG); /* 0x48 or 0x49 */
+ /* Clear the remote byte count registers. */
+ ei_outb_p(0x00, e8390_base + EN0_RCNTLO);
+ ei_outb_p(0x00, e8390_base + EN0_RCNTHI);
+ /* Set to monitor and loopback mode -- this is vital!. */
+ ei_outb_p(E8390_RXOFF, e8390_base + EN0_RXCR); /* 0x20 */
+ ei_outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); /* 0x02 */
+ /* Set the transmit page and receive ring. */
+ ei_outb_p(ei_local->tx_start_page, e8390_base + EN0_TPSR);
+ ei_local->tx1 = ei_local->tx2 = 0;
+ ei_outb_p(ei_local->rx_start_page, e8390_base + EN0_STARTPG);
+ ei_outb_p(ei_local->stop_page-1, e8390_base + EN0_BOUNDARY); /* 3c503 says 0x3f,NS0x26*/
+ ei_local->current_page = ei_local->rx_start_page; /* assert boundary+1 */
+ ei_outb_p(ei_local->stop_page, e8390_base + EN0_STOPPG);
+ /* Clear the pending interrupts and mask. */
+ ei_outb_p(0xFF, e8390_base + EN0_ISR);
+ ei_outb_p(0x00, e8390_base + EN0_IMR);
+
+ /* Copy the station address into the DS8390 registers. */
+
+ ei_outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, e8390_base+E8390_CMD); /* 0x61 */
+ for(i = 0; i < 6; i++)
+ {
+ ei_outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS_SHIFT(i));
+ if (ei_debug > 1 && ei_inb_p(e8390_base + EN1_PHYS_SHIFT(i))!=dev->dev_addr[i])
+ printk(KERN_ERR "Hw. address read/write mismap %d\n",i);
+ }
+
+ ei_outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG);
+ ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
+
+ netif_start_queue(dev);
+ ei_local->tx1 = ei_local->tx2 = 0;
+ ei_local->txing = 0;
+
+ if (startp)
+ {
+ ei_outb_p(0xff, e8390_base + EN0_ISR);
+ ei_outb_p(ENISR_ALL, e8390_base + EN0_IMR);
+ ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+E8390_CMD);
+ ei_outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR); /* xmit on. */
+ /* 3c503 TechMan says rxconfig only after the NIC is started. */
+ ei_outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR); /* rx on, */
+ do_set_multicast_list(dev); /* (re)load the mcast table */
+ }
+}
+
+/* Trigger a transmit start, assuming the length is valid.
+ Always called with the page lock held */
+
+static void NS8390_trigger_send(struct net_device *dev, unsigned int length,
+ int start_page)
+{
+ unsigned long e8390_base = dev->base_addr;
+ struct ei_device *ei_local __attribute((unused)) = (struct ei_device *) netdev_priv(dev);
+
+ ei_outb_p(E8390_NODMA+E8390_PAGE0, e8390_base+E8390_CMD);
+
+ if (ei_inb_p(e8390_base + E8390_CMD) & E8390_TRANS)
+ {
+ printk(KERN_WARNING "%s: trigger_send() called with the transmitter busy.\n",
+ dev->name);
+ return;
+ }
+ ei_outb_p(length & 0xff, e8390_base + EN0_TCNTLO);
+ ei_outb_p(length >> 8, e8390_base + EN0_TCNTHI);
+ ei_outb_p(start_page, e8390_base + EN0_TPSR);
+ ei_outb_p(E8390_NODMA+E8390_TRANS+E8390_START, e8390_base+E8390_CMD);
+}
diff --git a/drivers/net/mac8390.c b/drivers/net/mac8390.c
index ade6ff852e1a..a12bb64e3694 100644
--- a/drivers/net/mac8390.c
+++ b/drivers/net/mac8390.c
@@ -39,7 +39,16 @@
#include <asm/hwtest.h>
#include <asm/macints.h>
-#include "8390.h"
+static char version[] =
+ "mac8390.c: v0.4 2001-05-15 David Huggins-Daines <dhd@debian.org> and others\n";
+
+#define EI_SHIFT(x) (ei_local->reg_offset[x])
+#define ei_inb(port) in_8(port)
+#define ei_outb(val,port) out_8(port,val)
+#define ei_inb_p(port) in_8(port)
+#define ei_outb_p(val,port) out_8(port,val)
+
+#include "lib8390.c"
#define WD_START_PG 0x00 /* First page of TX buffer */
#define CABLETRON_RX_START_PG 0x00 /* First page of RX buffer */
@@ -116,9 +125,6 @@ static int useresources[] = {
1, /* dayna-lc */
};
-static char version[] __initdata =
- "mac8390.c: v0.4 2001-05-15 David Huggins-Daines <dhd@debian.org> and others\n";
-
extern enum mac8390_type mac8390_ident(struct nubus_dev * dev);
extern int mac8390_memsize(unsigned long membase);
extern int mac8390_memtest(struct net_device * dev);
@@ -237,7 +243,7 @@ struct net_device * __init mac8390_probe(int unit)
if (!MACH_IS_MAC)
return ERR_PTR(-ENODEV);
- dev = alloc_ei_netdev();
+ dev = ____alloc_ei_netdev(0);
if (!dev)
return ERR_PTR(-ENOMEM);
@@ -438,7 +444,7 @@ static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * nd
dev->open = &mac8390_open;
dev->stop = &mac8390_close;
#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = ei_poll;
+ dev->poll_controller = __ei_poll;
#endif
/* GAR, ei_status is actually a macro even though it looks global */
@@ -510,7 +516,7 @@ static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * nd
return -ENODEV;
}
- NS8390_init(dev, 0);
+ __NS8390_init(dev, 0);
/* Good, done, now spit out some messages */
printk(KERN_INFO "%s: %s in slot %X (type %s)\n",
@@ -532,8 +538,8 @@ static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * nd
static int mac8390_open(struct net_device *dev)
{
- ei_open(dev);
- if (request_irq(dev->irq, ei_interrupt, 0, "8390 Ethernet", dev)) {
+ __ei_open(dev);
+ if (request_irq(dev->irq, __ei_interrupt, 0, "8390 Ethernet", dev)) {
printk ("%s: unable to get IRQ %d.\n", dev->name, dev->irq);
return -EAGAIN;
}
@@ -543,7 +549,7 @@ static int mac8390_open(struct net_device *dev)
static int mac8390_close(struct net_device *dev)
{
free_irq(dev->irq, dev);
- ei_close(dev);
+ __ei_close(dev);
return 0;
}
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
new file mode 100644
index 000000000000..bd0ce98c939c
--- /dev/null
+++ b/drivers/net/macb.c
@@ -0,0 +1,1210 @@
+/*
+ * Atmel MACB Ethernet Controller driver
+ *
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/mii.h>
+#include <linux/mutex.h>
+#include <linux/dma-mapping.h>
+#include <linux/ethtool.h>
+#include <linux/platform_device.h>
+
+#include <asm/arch/board.h>
+
+#include "macb.h"
+
+#define to_net_dev(class) container_of(class, struct net_device, class_dev)
+
+#define RX_BUFFER_SIZE 128
+#define RX_RING_SIZE 512
+#define RX_RING_BYTES (sizeof(struct dma_desc) * RX_RING_SIZE)
+
+/* Make the IP header word-aligned (the ethernet header is 14 bytes) */
+#define RX_OFFSET 2
+
+#define TX_RING_SIZE 128
+#define DEF_TX_RING_PENDING (TX_RING_SIZE - 1)
+#define TX_RING_BYTES (sizeof(struct dma_desc) * TX_RING_SIZE)
+
+#define TX_RING_GAP(bp) \
+ (TX_RING_SIZE - (bp)->tx_pending)
+#define TX_BUFFS_AVAIL(bp) \
+ (((bp)->tx_tail <= (bp)->tx_head) ? \
+ (bp)->tx_tail + (bp)->tx_pending - (bp)->tx_head : \
+ (bp)->tx_tail - (bp)->tx_head - TX_RING_GAP(bp))
+#define NEXT_TX(n) (((n) + 1) & (TX_RING_SIZE - 1))
+
+#define NEXT_RX(n) (((n) + 1) & (RX_RING_SIZE - 1))
+
+/* minimum number of free TX descriptors before waking up TX process */
+#define MACB_TX_WAKEUP_THRESH (TX_RING_SIZE / 4)
+
+#define MACB_RX_INT_FLAGS (MACB_BIT(RCOMP) | MACB_BIT(RXUBR) \
+ | MACB_BIT(ISR_ROVR))
+
+static void __macb_set_hwaddr(struct macb *bp)
+{
+ u32 bottom;
+ u16 top;
+
+ bottom = cpu_to_le32(*((u32 *)bp->dev->dev_addr));
+ macb_writel(bp, SA1B, bottom);
+ top = cpu_to_le16(*((u16 *)(bp->dev->dev_addr + 4)));
+ macb_writel(bp, SA1T, top);
+}
+
+static void __init macb_get_hwaddr(struct macb *bp)
+{
+ u32 bottom;
+ u16 top;
+ u8 addr[6];
+
+ bottom = macb_readl(bp, SA1B);
+ top = macb_readl(bp, SA1T);
+
+ addr[0] = bottom & 0xff;
+ addr[1] = (bottom >> 8) & 0xff;
+ addr[2] = (bottom >> 16) & 0xff;
+ addr[3] = (bottom >> 24) & 0xff;
+ addr[4] = top & 0xff;
+ addr[5] = (top >> 8) & 0xff;
+
+ if (is_valid_ether_addr(addr))
+ memcpy(bp->dev->dev_addr, addr, sizeof(addr));
+}
+
+static void macb_enable_mdio(struct macb *bp)
+{
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&bp->lock, flags);
+ reg = macb_readl(bp, NCR);
+ reg |= MACB_BIT(MPE);
+ macb_writel(bp, NCR, reg);
+ macb_writel(bp, IER, MACB_BIT(MFD));
+ spin_unlock_irqrestore(&bp->lock, flags);
+}
+
+static void macb_disable_mdio(struct macb *bp)
+{
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&bp->lock, flags);
+ reg = macb_readl(bp, NCR);
+ reg &= ~MACB_BIT(MPE);
+ macb_writel(bp, NCR, reg);
+ macb_writel(bp, IDR, MACB_BIT(MFD));
+ spin_unlock_irqrestore(&bp->lock, flags);
+}
+
+static int macb_mdio_read(struct net_device *dev, int phy_id, int location)
+{
+ struct macb *bp = netdev_priv(dev);
+ int value;
+
+ mutex_lock(&bp->mdio_mutex);
+
+ macb_enable_mdio(bp);
+ macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF)
+ | MACB_BF(RW, MACB_MAN_READ)
+ | MACB_BF(PHYA, phy_id)
+ | MACB_BF(REGA, location)
+ | MACB_BF(CODE, MACB_MAN_CODE)));
+
+ wait_for_completion(&bp->mdio_complete);
+
+ value = MACB_BFEXT(DATA, macb_readl(bp, MAN));
+ macb_disable_mdio(bp);
+ mutex_unlock(&bp->mdio_mutex);
+
+ return value;
+}
+
+static void macb_mdio_write(struct net_device *dev, int phy_id,
+ int location, int val)
+{
+ struct macb *bp = netdev_priv(dev);
+
+ dev_dbg(&bp->pdev->dev, "mdio_write %02x:%02x <- %04x\n",
+ phy_id, location, val);
+
+ mutex_lock(&bp->mdio_mutex);
+ macb_enable_mdio(bp);
+
+ macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF)
+ | MACB_BF(RW, MACB_MAN_WRITE)
+ | MACB_BF(PHYA, phy_id)
+ | MACB_BF(REGA, location)
+ | MACB_BF(CODE, MACB_MAN_CODE)
+ | MACB_BF(DATA, val)));
+
+ wait_for_completion(&bp->mdio_complete);
+
+ macb_disable_mdio(bp);
+ mutex_unlock(&bp->mdio_mutex);
+}
+
+static int macb_phy_probe(struct macb *bp)
+{
+ int phy_address;
+ u16 phyid1, phyid2;
+
+ for (phy_address = 0; phy_address < 32; phy_address++) {
+ phyid1 = macb_mdio_read(bp->dev, phy_address, MII_PHYSID1);
+ phyid2 = macb_mdio_read(bp->dev, phy_address, MII_PHYSID2);
+
+ if (phyid1 != 0xffff && phyid1 != 0x0000
+ && phyid2 != 0xffff && phyid2 != 0x0000)
+ break;
+ }
+
+ if (phy_address == 32)
+ return -ENODEV;
+
+ dev_info(&bp->pdev->dev,
+ "detected PHY at address %d (ID %04x:%04x)\n",
+ phy_address, phyid1, phyid2);
+
+ bp->mii.phy_id = phy_address;
+ return 0;
+}
+
+static void macb_set_media(struct macb *bp, int media)
+{
+ u32 reg;
+
+ spin_lock_irq(&bp->lock);
+ reg = macb_readl(bp, NCFGR);
+ reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
+ if (media & (ADVERTISE_100HALF | ADVERTISE_100FULL))
+ reg |= MACB_BIT(SPD);
+ if (media & ADVERTISE_FULL)
+ reg |= MACB_BIT(FD);
+ macb_writel(bp, NCFGR, reg);
+ spin_unlock_irq(&bp->lock);
+}
+
+static void macb_check_media(struct macb *bp, int ok_to_print, int init_media)
+{
+ struct mii_if_info *mii = &bp->mii;
+ unsigned int old_carrier, new_carrier;
+ int advertise, lpa, media, duplex;
+
+ /* if forced media, go no further */
+ if (mii->force_media)
+ return;
+
+ /* check current and old link status */
+ old_carrier = netif_carrier_ok(mii->dev) ? 1 : 0;
+ new_carrier = (unsigned int) mii_link_ok(mii);
+
+ /* if carrier state did not change, assume nothing else did */
+ if (!init_media && old_carrier == new_carrier)
+ return;
+
+ /* no carrier, nothing much to do */
+ if (!new_carrier) {
+ netif_carrier_off(mii->dev);
+ printk(KERN_INFO "%s: link down\n", mii->dev->name);
+ return;
+ }
+
+ /*
+ * we have carrier, see who's on the other end
+ */
+ netif_carrier_on(mii->dev);
+
+ /* get MII advertise and LPA values */
+ if (!init_media && mii->advertising) {
+ advertise = mii->advertising;
+ } else {
+ advertise = mii->mdio_read(mii->dev, mii->phy_id, MII_ADVERTISE);
+ mii->advertising = advertise;
+ }
+ lpa = mii->mdio_read(mii->dev, mii->phy_id, MII_LPA);
+
+ /* figure out media and duplex from advertise and LPA values */
+ media = mii_nway_result(lpa & advertise);
+ duplex = (media & ADVERTISE_FULL) ? 1 : 0;
+
+ if (ok_to_print)
+ printk(KERN_INFO "%s: link up, %sMbps, %s-duplex, lpa 0x%04X\n",
+ mii->dev->name,
+ media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ? "100" : "10",
+ duplex ? "full" : "half", lpa);
+
+ mii->full_duplex = duplex;
+
+ /* Let the MAC know about the new link state */
+ macb_set_media(bp, media);
+}
+
+static void macb_update_stats(struct macb *bp)
+{
+ u32 __iomem *reg = bp->regs + MACB_PFR;
+ u32 *p = &bp->hw_stats.rx_pause_frames;
+ u32 *end = &bp->hw_stats.tx_pause_frames + 1;
+
+ WARN_ON((unsigned long)(end - p - 1) != (MACB_TPF - MACB_PFR) / 4);
+
+ for(; p < end; p++, reg++)
+ *p += readl(reg);
+}
+
+static void macb_periodic_task(void *arg)
+{
+ struct macb *bp = arg;
+
+ macb_update_stats(bp);
+ macb_check_media(bp, 1, 0);
+
+ schedule_delayed_work(&bp->periodic_task, HZ);
+}
+
+static void macb_tx(struct macb *bp)
+{
+ unsigned int tail;
+ unsigned int head;
+ u32 status;
+
+ status = macb_readl(bp, TSR);
+ macb_writel(bp, TSR, status);
+
+ dev_dbg(&bp->pdev->dev, "macb_tx status = %02lx\n",
+ (unsigned long)status);
+
+ if (status & MACB_BIT(UND)) {
+ printk(KERN_ERR "%s: TX underrun, resetting buffers\n",
+ bp->dev->name);
+ bp->tx_head = bp->tx_tail = 0;
+ }
+
+ if (!(status & MACB_BIT(COMP)))
+ /*
+ * This may happen when a buffer becomes complete
+ * between reading the ISR and scanning the
+ * descriptors. Nothing to worry about.
+ */
+ return;
+
+ head = bp->tx_head;
+ for (tail = bp->tx_tail; tail != head; tail = NEXT_TX(tail)) {
+ struct ring_info *rp = &bp->tx_skb[tail];
+ struct sk_buff *skb = rp->skb;
+ u32 bufstat;
+
+ BUG_ON(skb == NULL);
+
+ rmb();
+ bufstat = bp->tx_ring[tail].ctrl;
+
+ if (!(bufstat & MACB_BIT(TX_USED)))
+ break;
+
+ dev_dbg(&bp->pdev->dev, "skb %u (data %p) TX complete\n",
+ tail, skb->data);
+ dma_unmap_single(&bp->pdev->dev, rp->mapping, skb->len,
+ DMA_TO_DEVICE);
+ bp->stats.tx_packets++;
+ bp->stats.tx_bytes += skb->len;
+ rp->skb = NULL;
+ dev_kfree_skb_irq(skb);
+ }
+
+ bp->tx_tail = tail;
+ if (netif_queue_stopped(bp->dev) &&
+ TX_BUFFS_AVAIL(bp) > MACB_TX_WAKEUP_THRESH)
+ netif_wake_queue(bp->dev);
+}
+
+static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
+ unsigned int last_frag)
+{
+ unsigned int len;
+ unsigned int frag;
+ unsigned int offset = 0;
+ struct sk_buff *skb;
+
+ len = MACB_BFEXT(RX_FRMLEN, bp->rx_ring[last_frag].ctrl);
+
+ dev_dbg(&bp->pdev->dev, "macb_rx_frame frags %u - %u (len %u)\n",
+ first_frag, last_frag, len);
+
+ skb = dev_alloc_skb(len + RX_OFFSET);
+ if (!skb) {
+ bp->stats.rx_dropped++;
+ for (frag = first_frag; ; frag = NEXT_RX(frag)) {
+ bp->rx_ring[frag].addr &= ~MACB_BIT(RX_USED);
+ if (frag == last_frag)
+ break;
+ }
+ wmb();
+ return 1;
+ }
+
+ skb_reserve(skb, RX_OFFSET);
+ skb->dev = bp->dev;
+ skb->ip_summed = CHECKSUM_NONE;
+ skb_put(skb, len);
+
+ for (frag = first_frag; ; frag = NEXT_RX(frag)) {
+ unsigned int frag_len = RX_BUFFER_SIZE;
+
+ if (offset + frag_len > len) {
+ BUG_ON(frag != last_frag);
+ frag_len = len - offset;
+ }
+ memcpy(skb->data + offset,
+ bp->rx_buffers + (RX_BUFFER_SIZE * frag),
+ frag_len);
+ offset += RX_BUFFER_SIZE;
+ bp->rx_ring[frag].addr &= ~MACB_BIT(RX_USED);
+ wmb();
+
+ if (frag == last_frag)
+ break;
+ }
+
+ skb->protocol = eth_type_trans(skb, bp->dev);
+
+ bp->stats.rx_packets++;
+ bp->stats.rx_bytes += len;
+ bp->dev->last_rx = jiffies;
+ dev_dbg(&bp->pdev->dev, "received skb of length %u, csum: %08x\n",
+ skb->len, skb->csum);
+ netif_receive_skb(skb);
+
+ return 0;
+}
+
+/* Mark DMA descriptors from begin up to and not including end as unused */
+static void discard_partial_frame(struct macb *bp, unsigned int begin,
+ unsigned int end)
+{
+ unsigned int frag;
+
+ for (frag = begin; frag != end; frag = NEXT_RX(frag))
+ bp->rx_ring[frag].addr &= ~MACB_BIT(RX_USED);
+ wmb();
+
+ /*
+ * When this happens, the hardware stats registers for
+ * whatever caused this is updated, so we don't have to record
+ * anything.
+ */
+}
+
+static int macb_rx(struct macb *bp, int budget)
+{
+ int received = 0;
+ unsigned int tail = bp->rx_tail;
+ int first_frag = -1;
+
+ for (; budget > 0; tail = NEXT_RX(tail)) {
+ u32 addr, ctrl;
+
+ rmb();
+ addr = bp->rx_ring[tail].addr;
+ ctrl = bp->rx_ring[tail].ctrl;
+
+ if (!(addr & MACB_BIT(RX_USED)))
+ break;
+
+ if (ctrl & MACB_BIT(RX_SOF)) {
+ if (first_frag != -1)
+ discard_partial_frame(bp, first_frag, tail);
+ first_frag = tail;
+ }
+
+ if (ctrl & MACB_BIT(RX_EOF)) {
+ int dropped;
+ BUG_ON(first_frag == -1);
+
+ dropped = macb_rx_frame(bp, first_frag, tail);
+ first_frag = -1;
+ if (!dropped) {
+ received++;
+ budget--;
+ }
+ }
+ }
+
+ if (first_frag != -1)
+ bp->rx_tail = first_frag;
+ else
+ bp->rx_tail = tail;
+
+ return received;
+}
+
+static int macb_poll(struct net_device *dev, int *budget)
+{
+ struct macb *bp = netdev_priv(dev);
+ int orig_budget, work_done, retval = 0;
+ u32 status;
+
+ status = macb_readl(bp, RSR);
+ macb_writel(bp, RSR, status);
+
+ if (!status) {
+ /*
+ * This may happen if an interrupt was pending before
+ * this function was called last time, and no packets
+ * have been received since.
+ */
+ netif_rx_complete(dev);
+ goto out;
+ }
+
+ dev_dbg(&bp->pdev->dev, "poll: status = %08lx, budget = %d\n",
+ (unsigned long)status, *budget);
+
+ if (!(status & MACB_BIT(REC))) {
+ dev_warn(&bp->pdev->dev,
+ "No RX buffers complete, status = %02lx\n",
+ (unsigned long)status);
+ netif_rx_complete(dev);
+ goto out;
+ }
+
+ orig_budget = *budget;
+ if (orig_budget > dev->quota)
+ orig_budget = dev->quota;
+
+ work_done = macb_rx(bp, orig_budget);
+ if (work_done < orig_budget) {
+ netif_rx_complete(dev);
+ retval = 0;
+ } else {
+ retval = 1;
+ }
+
+ /*
+ * We've done what we can to clean the buffers. Make sure we
+ * get notified when new packets arrive.
+ */
+out:
+ macb_writel(bp, IER, MACB_RX_INT_FLAGS);
+
+ /* TODO: Handle errors */
+
+ return retval;
+}
+
+static irqreturn_t macb_interrupt(int irq, void *dev_id)
+{
+ struct net_device *dev = dev_id;
+ struct macb *bp = netdev_priv(dev);
+ u32 status;
+
+ status = macb_readl(bp, ISR);
+
+ if (unlikely(!status))
+ return IRQ_NONE;
+
+ spin_lock(&bp->lock);
+
+ while (status) {
+ if (status & MACB_BIT(MFD))
+ complete(&bp->mdio_complete);
+
+ /* close possible race with dev_close */
+ if (unlikely(!netif_running(dev))) {
+ macb_writel(bp, IDR, ~0UL);
+ break;
+ }
+
+ if (status & MACB_RX_INT_FLAGS) {
+ if (netif_rx_schedule_prep(dev)) {
+ /*
+ * There's no point taking any more interrupts
+ * until we have processed the buffers
+ */
+ macb_writel(bp, IDR, MACB_RX_INT_FLAGS);
+ dev_dbg(&bp->pdev->dev, "scheduling RX softirq\n");
+ __netif_rx_schedule(dev);
+ }
+ }
+
+ if (status & (MACB_BIT(TCOMP) | MACB_BIT(ISR_TUND)))
+ macb_tx(bp);
+
+ /*
+ * Link change detection isn't possible with RMII, so we'll
+ * add that if/when we get our hands on a full-blown MII PHY.
+ */
+
+ if (status & MACB_BIT(HRESP)) {
+ /*
+ * TODO: Reset the hardware, and maybe move the printk
+ * to a lower-priority context as well (work queue?)
+ */
+ printk(KERN_ERR "%s: DMA bus error: HRESP not OK\n",
+ dev->name);
+ }
+
+ status = macb_readl(bp, ISR);
+ }
+
+ spin_unlock(&bp->lock);
+
+ return IRQ_HANDLED;
+}
+
+static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct macb *bp = netdev_priv(dev);
+ dma_addr_t mapping;
+ unsigned int len, entry;
+ u32 ctrl;
+
+#ifdef DEBUG
+ int i;
+ dev_dbg(&bp->pdev->dev,
+ "start_xmit: len %u head %p data %p tail %p end %p\n",
+ skb->len, skb->head, skb->data, skb->tail, skb->end);
+ dev_dbg(&bp->pdev->dev,
+ "data:");
+ for (i = 0; i < 16; i++)
+ printk(" %02x", (unsigned int)skb->data[i]);
+ printk("\n");
+#endif
+
+ len = skb->len;
+ spin_lock_irq(&bp->lock);
+
+ /* This is a hard error, log it. */
+ if (TX_BUFFS_AVAIL(bp) < 1) {
+ netif_stop_queue(dev);
+ spin_unlock_irq(&bp->lock);
+ dev_err(&bp->pdev->dev,
+ "BUG! Tx Ring full when queue awake!\n");
+ dev_dbg(&bp->pdev->dev, "tx_head = %u, tx_tail = %u\n",
+ bp->tx_head, bp->tx_tail);
+ return 1;
+ }
+
+ entry = bp->tx_head;
+ dev_dbg(&bp->pdev->dev, "Allocated ring entry %u\n", entry);
+ mapping = dma_map_single(&bp->pdev->dev, skb->data,
+ len, DMA_TO_DEVICE);
+ bp->tx_skb[entry].skb = skb;
+ bp->tx_skb[entry].mapping = mapping;
+ dev_dbg(&bp->pdev->dev, "Mapped skb data %p to DMA addr %08lx\n",
+ skb->data, (unsigned long)mapping);
+
+ ctrl = MACB_BF(TX_FRMLEN, len);
+ ctrl |= MACB_BIT(TX_LAST);
+ if (entry == (TX_RING_SIZE - 1))
+ ctrl |= MACB_BIT(TX_WRAP);
+
+ bp->tx_ring[entry].addr = mapping;
+ bp->tx_ring[entry].ctrl = ctrl;
+ wmb();
+
+ entry = NEXT_TX(entry);
+ bp->tx_head = entry;
+
+ macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART));
+
+ if (TX_BUFFS_AVAIL(bp) < 1)
+ netif_stop_queue(dev);
+
+ spin_unlock_irq(&bp->lock);
+
+ dev->trans_start = jiffies;
+
+ return 0;
+}
+
+static void macb_free_consistent(struct macb *bp)
+{
+ if (bp->tx_skb) {
+ kfree(bp->tx_skb);
+ bp->tx_skb = NULL;
+ }
+ if (bp->rx_ring) {
+ dma_free_coherent(&bp->pdev->dev, RX_RING_BYTES,
+ bp->rx_ring, bp->rx_ring_dma);
+ bp->rx_ring = NULL;
+ }
+ if (bp->tx_ring) {
+ dma_free_coherent(&bp->pdev->dev, TX_RING_BYTES,
+ bp->tx_ring, bp->tx_ring_dma);
+ bp->tx_ring = NULL;
+ }
+ if (bp->rx_buffers) {
+ dma_free_coherent(&bp->pdev->dev,
+ RX_RING_SIZE * RX_BUFFER_SIZE,
+ bp->rx_buffers, bp->rx_buffers_dma);
+ bp->rx_buffers = NULL;
+ }
+}
+
+static int macb_alloc_consistent(struct macb *bp)
+{
+ int size;
+
+ size = TX_RING_SIZE * sizeof(struct ring_info);
+ bp->tx_skb = kmalloc(size, GFP_KERNEL);
+ if (!bp->tx_skb)
+ goto out_err;
+
+ size = RX_RING_BYTES;
+ bp->rx_ring = dma_alloc_coherent(&bp->pdev->dev, size,
+ &bp->rx_ring_dma, GFP_KERNEL);
+ if (!bp->rx_ring)
+ goto out_err;
+ dev_dbg(&bp->pdev->dev,
+ "Allocated RX ring of %d bytes at %08lx (mapped %p)\n",
+ size, (unsigned long)bp->rx_ring_dma, bp->rx_ring);
+
+ size = TX_RING_BYTES;
+ bp->tx_ring = dma_alloc_coherent(&bp->pdev->dev, size,
+ &bp->tx_ring_dma, GFP_KERNEL);
+ if (!bp->tx_ring)
+ goto out_err;
+ dev_dbg(&bp->pdev->dev,
+ "Allocated TX ring of %d bytes at %08lx (mapped %p)\n",
+ size, (unsigned long)bp->tx_ring_dma, bp->tx_ring);
+
+ size = RX_RING_SIZE * RX_BUFFER_SIZE;
+ bp->rx_buffers = dma_alloc_coherent(&bp->pdev->dev, size,
+ &bp->rx_buffers_dma, GFP_KERNEL);
+ if (!bp->rx_buffers)
+ goto out_err;
+ dev_dbg(&bp->pdev->dev,
+ "Allocated RX buffers of %d bytes at %08lx (mapped %p)\n",
+ size, (unsigned long)bp->rx_buffers_dma, bp->rx_buffers);
+
+ return 0;
+
+out_err:
+ macb_free_consistent(bp);
+ return -ENOMEM;
+}
+
+static void macb_init_rings(struct macb *bp)
+{
+ int i;
+ dma_addr_t addr;
+
+ addr = bp->rx_buffers_dma;
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ bp->rx_ring[i].addr = addr;
+ bp->rx_ring[i].ctrl = 0;
+ addr += RX_BUFFER_SIZE;
+ }
+ bp->rx_ring[RX_RING_SIZE - 1].addr |= MACB_BIT(RX_WRAP);
+
+ for (i = 0; i < TX_RING_SIZE; i++) {
+ bp->tx_ring[i].addr = 0;
+ bp->tx_ring[i].ctrl = MACB_BIT(TX_USED);
+ }
+ bp->tx_ring[TX_RING_SIZE - 1].ctrl |= MACB_BIT(TX_WRAP);
+
+ bp->rx_tail = bp->tx_head = bp->tx_tail = 0;
+}
+
+static void macb_reset_hw(struct macb *bp)
+{
+ /* Make sure we have the write buffer for ourselves */
+ wmb();
+
+ /*
+ * Disable RX and TX (XXX: Should we halt the transmission
+ * more gracefully?)
+ */
+ macb_writel(bp, NCR, 0);
+
+ /* Clear the stats registers (XXX: Update stats first?) */
+ macb_writel(bp, NCR, MACB_BIT(CLRSTAT));
+
+ /* Clear all status flags */
+ macb_writel(bp, TSR, ~0UL);
+ macb_writel(bp, RSR, ~0UL);
+
+ /* Disable all interrupts */
+ macb_writel(bp, IDR, ~0UL);
+ macb_readl(bp, ISR);
+}
+
+static void macb_init_hw(struct macb *bp)
+{
+ u32 config;
+
+ macb_reset_hw(bp);
+ __macb_set_hwaddr(bp);
+
+ config = macb_readl(bp, NCFGR) & MACB_BF(CLK, -1L);
+ config |= MACB_BIT(PAE); /* PAuse Enable */
+ config |= MACB_BIT(DRFCS); /* Discard Rx FCS */
+ if (bp->dev->flags & IFF_PROMISC)
+ config |= MACB_BIT(CAF); /* Copy All Frames */
+ if (!(bp->dev->flags & IFF_BROADCAST))
+ config |= MACB_BIT(NBC); /* No BroadCast */
+ macb_writel(bp, NCFGR, config);
+
+ /* Initialize TX and RX buffers */
+ macb_writel(bp, RBQP, bp->rx_ring_dma);
+ macb_writel(bp, TBQP, bp->tx_ring_dma);
+
+ /* Enable TX and RX */
+ macb_writel(bp, NCR, MACB_BIT(RE) | MACB_BIT(TE));
+
+ /* Enable interrupts */
+ macb_writel(bp, IER, (MACB_BIT(RCOMP)
+ | MACB_BIT(RXUBR)
+ | MACB_BIT(ISR_TUND)
+ | MACB_BIT(ISR_RLE)
+ | MACB_BIT(TXERR)
+ | MACB_BIT(TCOMP)
+ | MACB_BIT(ISR_ROVR)
+ | MACB_BIT(HRESP)));
+}
+
+static void macb_init_phy(struct net_device *dev)
+{
+ struct macb *bp = netdev_priv(dev);
+
+ /* Set some reasonable default settings */
+ macb_mdio_write(dev, bp->mii.phy_id, MII_ADVERTISE,
+ ADVERTISE_CSMA | ADVERTISE_ALL);
+ macb_mdio_write(dev, bp->mii.phy_id, MII_BMCR,
+ (BMCR_SPEED100 | BMCR_ANENABLE
+ | BMCR_ANRESTART | BMCR_FULLDPLX));
+}
+
+static int macb_open(struct net_device *dev)
+{
+ struct macb *bp = netdev_priv(dev);
+ int err;
+
+ dev_dbg(&bp->pdev->dev, "open\n");
+
+ if (!is_valid_ether_addr(dev->dev_addr))
+ return -EADDRNOTAVAIL;
+
+ err = macb_alloc_consistent(bp);
+ if (err) {
+ printk(KERN_ERR
+ "%s: Unable to allocate DMA memory (error %d)\n",
+ dev->name, err);
+ return err;
+ }
+
+ macb_init_rings(bp);
+ macb_init_hw(bp);
+ macb_init_phy(dev);
+
+ macb_check_media(bp, 1, 1);
+ netif_start_queue(dev);
+
+ schedule_delayed_work(&bp->periodic_task, HZ);
+
+ return 0;
+}
+
+static int macb_close(struct net_device *dev)
+{
+ struct macb *bp = netdev_priv(dev);
+ unsigned long flags;
+
+ cancel_rearming_delayed_work(&bp->periodic_task);
+
+ netif_stop_queue(dev);
+
+ spin_lock_irqsave(&bp->lock, flags);
+ macb_reset_hw(bp);
+ netif_carrier_off(dev);
+ spin_unlock_irqrestore(&bp->lock, flags);
+
+ macb_free_consistent(bp);
+
+ return 0;
+}
+
+static struct net_device_stats *macb_get_stats(struct net_device *dev)
+{
+ struct macb *bp = netdev_priv(dev);
+ struct net_device_stats *nstat = &bp->stats;
+ struct macb_stats *hwstat = &bp->hw_stats;
+
+ /* Convert HW stats into netdevice stats */
+ nstat->rx_errors = (hwstat->rx_fcs_errors +
+ hwstat->rx_align_errors +
+ hwstat->rx_resource_errors +
+ hwstat->rx_overruns +
+ hwstat->rx_oversize_pkts +
+ hwstat->rx_jabbers +
+ hwstat->rx_undersize_pkts +
+ hwstat->sqe_test_errors +
+ hwstat->rx_length_mismatch);
+ nstat->tx_errors = (hwstat->tx_late_cols +
+ hwstat->tx_excessive_cols +
+ hwstat->tx_underruns +
+ hwstat->tx_carrier_errors);
+ nstat->collisions = (hwstat->tx_single_cols +
+ hwstat->tx_multiple_cols +
+ hwstat->tx_excessive_cols);
+ nstat->rx_length_errors = (hwstat->rx_oversize_pkts +
+ hwstat->rx_jabbers +
+ hwstat->rx_undersize_pkts +
+ hwstat->rx_length_mismatch);
+ nstat->rx_over_errors = hwstat->rx_resource_errors;
+ nstat->rx_crc_errors = hwstat->rx_fcs_errors;
+ nstat->rx_frame_errors = hwstat->rx_align_errors;
+ nstat->rx_fifo_errors = hwstat->rx_overruns;
+ /* XXX: What does "missed" mean? */
+ nstat->tx_aborted_errors = hwstat->tx_excessive_cols;
+ nstat->tx_carrier_errors = hwstat->tx_carrier_errors;
+ nstat->tx_fifo_errors = hwstat->tx_underruns;
+ /* Don't know about heartbeat or window errors... */
+
+ return nstat;
+}
+
+static int macb_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct macb *bp = netdev_priv(dev);
+ int ret;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bp->lock, flags);
+ ret = mii_ethtool_gset(&bp->mii, cmd);
+ spin_unlock_irqrestore(&bp->lock, flags);
+
+ return ret;
+}
+
+static int macb_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct macb *bp = netdev_priv(dev);
+ int ret;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bp->lock, flags);
+ ret = mii_ethtool_sset(&bp->mii, cmd);
+ spin_unlock_irqrestore(&bp->lock, flags);
+
+ return ret;
+}
+
+static void macb_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+ struct macb *bp = netdev_priv(dev);
+
+ strcpy(info->driver, bp->pdev->dev.driver->name);
+ strcpy(info->version, "$Revision: 1.14 $");
+ strcpy(info->bus_info, bp->pdev->dev.bus_id);
+}
+
+static int macb_nway_reset(struct net_device *dev)
+{
+ struct macb *bp = netdev_priv(dev);
+ return mii_nway_restart(&bp->mii);
+}
+
+static struct ethtool_ops macb_ethtool_ops = {
+ .get_settings = macb_get_settings,
+ .set_settings = macb_set_settings,
+ .get_drvinfo = macb_get_drvinfo,
+ .nway_reset = macb_nway_reset,
+ .get_link = ethtool_op_get_link,
+};
+
+static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+ struct macb *bp = netdev_priv(dev);
+ int ret;
+ unsigned long flags;
+
+ if (!netif_running(dev))
+ return -EINVAL;
+
+ spin_lock_irqsave(&bp->lock, flags);
+ ret = generic_mii_ioctl(&bp->mii, if_mii(rq), cmd, NULL);
+ spin_unlock_irqrestore(&bp->lock, flags);
+
+ return ret;
+}
+
+static ssize_t macb_mii_show(const struct class_device *cd, char *buf,
+ unsigned long addr)
+{
+ struct net_device *dev = to_net_dev(cd);
+ struct macb *bp = netdev_priv(dev);
+ ssize_t ret = -EINVAL;
+
+ if (netif_running(dev)) {
+ int value;
+ value = macb_mdio_read(dev, bp->mii.phy_id, addr);
+ ret = sprintf(buf, "0x%04x\n", (uint16_t)value);
+ }
+
+ return ret;
+}
+
+#define MII_ENTRY(name, addr) \
+static ssize_t show_##name(struct class_device *cd, char *buf) \
+{ \
+ return macb_mii_show(cd, buf, addr); \
+} \
+static CLASS_DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
+
+MII_ENTRY(bmcr, MII_BMCR);
+MII_ENTRY(bmsr, MII_BMSR);
+MII_ENTRY(physid1, MII_PHYSID1);
+MII_ENTRY(physid2, MII_PHYSID2);
+MII_ENTRY(advertise, MII_ADVERTISE);
+MII_ENTRY(lpa, MII_LPA);
+MII_ENTRY(expansion, MII_EXPANSION);
+
+static struct attribute *macb_mii_attrs[] = {
+ &class_device_attr_bmcr.attr,
+ &class_device_attr_bmsr.attr,
+ &class_device_attr_physid1.attr,
+ &class_device_attr_physid2.attr,
+ &class_device_attr_advertise.attr,
+ &class_device_attr_lpa.attr,
+ &class_device_attr_expansion.attr,
+ NULL,
+};
+
+static struct attribute_group macb_mii_group = {
+ .name = "mii",
+ .attrs = macb_mii_attrs,
+};
+
+static void macb_unregister_sysfs(struct net_device *net)
+{
+ struct class_device *class_dev = &net->class_dev;
+
+ sysfs_remove_group(&class_dev->kobj, &macb_mii_group);
+}
+
+static int macb_register_sysfs(struct net_device *net)
+{
+ struct class_device *class_dev = &net->class_dev;
+ int ret;
+
+ ret = sysfs_create_group(&class_dev->kobj, &macb_mii_group);
+ if (ret)
+ printk(KERN_WARNING
+ "%s: sysfs mii attribute registration failed: %d\n",
+ net->name, ret);
+ return ret;
+}
+static int __devinit macb_probe(struct platform_device *pdev)
+{
+ struct eth_platform_data *pdata;
+ struct resource *regs;
+ struct net_device *dev;
+ struct macb *bp;
+ unsigned long pclk_hz;
+ u32 config;
+ int err = -ENXIO;
+
+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!regs) {
+ dev_err(&pdev->dev, "no mmio resource defined\n");
+ goto err_out;
+ }
+
+ err = -ENOMEM;
+ dev = alloc_etherdev(sizeof(*bp));
+ if (!dev) {
+ dev_err(&pdev->dev, "etherdev alloc failed, aborting.\n");
+ goto err_out;
+ }
+
+ SET_MODULE_OWNER(dev);
+ SET_NETDEV_DEV(dev, &pdev->dev);
+
+ /* TODO: Actually, we have some interesting features... */
+ dev->features |= 0;
+
+ bp = netdev_priv(dev);
+ bp->pdev = pdev;
+ bp->dev = dev;
+
+ spin_lock_init(&bp->lock);
+
+ bp->pclk = clk_get(&pdev->dev, "pclk");
+ if (IS_ERR(bp->pclk)) {
+ dev_err(&pdev->dev, "failed to get pclk\n");
+ goto err_out_free_dev;
+ }
+ bp->hclk = clk_get(&pdev->dev, "hclk");
+ if (IS_ERR(bp->hclk)) {
+ dev_err(&pdev->dev, "failed to get hclk\n");
+ goto err_out_put_pclk;
+ }
+
+ clk_enable(bp->pclk);
+ clk_enable(bp->hclk);
+
+ bp->regs = ioremap(regs->start, regs->end - regs->start + 1);
+ if (!bp->regs) {
+ dev_err(&pdev->dev, "failed to map registers, aborting.\n");
+ err = -ENOMEM;
+ goto err_out_disable_clocks;
+ }
+
+ dev->irq = platform_get_irq(pdev, 0);
+ err = request_irq(dev->irq, macb_interrupt, SA_SAMPLE_RANDOM,
+ dev->name, dev);
+ if (err) {
+ printk(KERN_ERR
+ "%s: Unable to request IRQ %d (error %d)\n",
+ dev->name, dev->irq, err);
+ goto err_out_iounmap;
+ }
+
+ dev->open = macb_open;
+ dev->stop = macb_close;
+ dev->hard_start_xmit = macb_start_xmit;
+ dev->get_stats = macb_get_stats;
+ dev->do_ioctl = macb_ioctl;
+ dev->poll = macb_poll;
+ dev->weight = 64;
+ dev->ethtool_ops = &macb_ethtool_ops;
+
+ dev->base_addr = regs->start;
+
+ INIT_WORK(&bp->periodic_task, macb_periodic_task, bp);
+ mutex_init(&bp->mdio_mutex);
+ init_completion(&bp->mdio_complete);
+
+ /* Set MII management clock divider */
+ pclk_hz = clk_get_rate(bp->pclk);
+ if (pclk_hz <= 20000000)
+ config = MACB_BF(CLK, MACB_CLK_DIV8);
+ else if (pclk_hz <= 40000000)
+ config = MACB_BF(CLK, MACB_CLK_DIV16);
+ else if (pclk_hz <= 80000000)
+ config = MACB_BF(CLK, MACB_CLK_DIV32);
+ else
+ config = MACB_BF(CLK, MACB_CLK_DIV64);
+ macb_writel(bp, NCFGR, config);
+
+ bp->mii.dev = dev;
+ bp->mii.mdio_read = macb_mdio_read;
+ bp->mii.mdio_write = macb_mdio_write;
+ bp->mii.phy_id_mask = 0x1f;
+ bp->mii.reg_num_mask = 0x1f;
+
+ macb_get_hwaddr(bp);
+ err = macb_phy_probe(bp);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to detect PHY, aborting.\n");
+ goto err_out_free_irq;
+ }
+
+ pdata = pdev->dev.platform_data;
+ if (pdata && pdata->is_rmii)
+ macb_writel(bp, USRIO, 0);
+ else
+ macb_writel(bp, USRIO, MACB_BIT(MII));
+
+ bp->tx_pending = DEF_TX_RING_PENDING;
+
+ err = register_netdev(dev);
+ if (err) {
+ dev_err(&pdev->dev, "Cannot register net device, aborting.\n");
+ goto err_out_free_irq;
+ }
+
+ platform_set_drvdata(pdev, dev);
+
+ macb_register_sysfs(dev);
+
+ printk(KERN_INFO "%s: Atmel MACB at 0x%08lx irq %d "
+ "(%02x:%02x:%02x:%02x:%02x:%02x)\n",
+ dev->name, dev->base_addr, dev->irq,
+ dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+ dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
+
+ return 0;
+
+err_out_free_irq:
+ free_irq(dev->irq, dev);
+err_out_iounmap:
+ iounmap(bp->regs);
+err_out_disable_clocks:
+ clk_disable(bp->hclk);
+ clk_disable(bp->pclk);
+ clk_put(bp->hclk);
+err_out_put_pclk:
+ clk_put(bp->pclk);
+err_out_free_dev:
+ free_netdev(dev);
+err_out:
+ platform_set_drvdata(pdev, NULL);
+ return err;
+}
+
+static int __devexit macb_remove(struct platform_device *pdev)
+{
+ struct net_device *dev;
+ struct macb *bp;
+
+ dev = platform_get_drvdata(pdev);
+
+ if (dev) {
+ bp = netdev_priv(dev);
+ macb_unregister_sysfs(dev);
+ unregister_netdev(dev);
+ free_irq(dev->irq, dev);
+ iounmap(bp->regs);
+ clk_disable(bp->hclk);
+ clk_disable(bp->pclk);
+ clk_put(bp->hclk);
+ clk_put(bp->pclk);
+ free_netdev(dev);
+ platform_set_drvdata(pdev, NULL);
+ }
+
+ return 0;
+}
+
+static struct platform_driver macb_driver = {
+ .probe = macb_probe,
+ .remove = __devexit_p(macb_remove),
+ .driver = {
+ .name = "macb",
+ },
+};
+
+static int __init macb_init(void)
+{
+ return platform_driver_register(&macb_driver);
+}
+
+static void __exit macb_exit(void)
+{
+ platform_driver_unregister(&macb_driver);
+}
+
+module_init(macb_init);
+module_exit(macb_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Atmel MACB Ethernet driver");
+MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>");
diff --git a/drivers/net/macb.h b/drivers/net/macb.h
new file mode 100644
index 000000000000..8c253db69881
--- /dev/null
+++ b/drivers/net/macb.h
@@ -0,0 +1,387 @@
+/*
+ * Atmel MACB Ethernet Controller driver
+ *
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef _MACB_H
+#define _MACB_H
+
+/* MACB register offsets */
+#define MACB_NCR 0x0000
+#define MACB_NCFGR 0x0004
+#define MACB_NSR 0x0008
+#define MACB_TSR 0x0014
+#define MACB_RBQP 0x0018
+#define MACB_TBQP 0x001c
+#define MACB_RSR 0x0020
+#define MACB_ISR 0x0024
+#define MACB_IER 0x0028
+#define MACB_IDR 0x002c
+#define MACB_IMR 0x0030
+#define MACB_MAN 0x0034
+#define MACB_PTR 0x0038
+#define MACB_PFR 0x003c
+#define MACB_FTO 0x0040
+#define MACB_SCF 0x0044
+#define MACB_MCF 0x0048
+#define MACB_FRO 0x004c
+#define MACB_FCSE 0x0050
+#define MACB_ALE 0x0054
+#define MACB_DTF 0x0058
+#define MACB_LCOL 0x005c
+#define MACB_EXCOL 0x0060
+#define MACB_TUND 0x0064
+#define MACB_CSE 0x0068
+#define MACB_RRE 0x006c
+#define MACB_ROVR 0x0070
+#define MACB_RSE 0x0074
+#define MACB_ELE 0x0078
+#define MACB_RJA 0x007c
+#define MACB_USF 0x0080
+#define MACB_STE 0x0084
+#define MACB_RLE 0x0088
+#define MACB_TPF 0x008c
+#define MACB_HRB 0x0090
+#define MACB_HRT 0x0094
+#define MACB_SA1B 0x0098
+#define MACB_SA1T 0x009c
+#define MACB_SA2B 0x00a0
+#define MACB_SA2T 0x00a4
+#define MACB_SA3B 0x00a8
+#define MACB_SA3T 0x00ac
+#define MACB_SA4B 0x00b0
+#define MACB_SA4T 0x00b4
+#define MACB_TID 0x00b8
+#define MACB_TPQ 0x00bc
+#define MACB_USRIO 0x00c0
+#define MACB_WOL 0x00c4
+
+/* Bitfields in NCR */
+#define MACB_LB_OFFSET 0
+#define MACB_LB_SIZE 1
+#define MACB_LLB_OFFSET 1
+#define MACB_LLB_SIZE 1
+#define MACB_RE_OFFSET 2
+#define MACB_RE_SIZE 1
+#define MACB_TE_OFFSET 3
+#define MACB_TE_SIZE 1
+#define MACB_MPE_OFFSET 4
+#define MACB_MPE_SIZE 1
+#define MACB_CLRSTAT_OFFSET 5
+#define MACB_CLRSTAT_SIZE 1
+#define MACB_INCSTAT_OFFSET 6
+#define MACB_INCSTAT_SIZE 1
+#define MACB_WESTAT_OFFSET 7
+#define MACB_WESTAT_SIZE 1
+#define MACB_BP_OFFSET 8
+#define MACB_BP_SIZE 1
+#define MACB_TSTART_OFFSET 9
+#define MACB_TSTART_SIZE 1
+#define MACB_THALT_OFFSET 10
+#define MACB_THALT_SIZE 1
+#define MACB_NCR_TPF_OFFSET 11
+#define MACB_NCR_TPF_SIZE 1
+#define MACB_TZQ_OFFSET 12
+#define MACB_TZQ_SIZE 1
+
+/* Bitfields in NCFGR */
+#define MACB_SPD_OFFSET 0
+#define MACB_SPD_SIZE 1
+#define MACB_FD_OFFSET 1
+#define MACB_FD_SIZE 1
+#define MACB_BIT_RATE_OFFSET 2
+#define MACB_BIT_RATE_SIZE 1
+#define MACB_JFRAME_OFFSET 3
+#define MACB_JFRAME_SIZE 1
+#define MACB_CAF_OFFSET 4
+#define MACB_CAF_SIZE 1
+#define MACB_NBC_OFFSET 5
+#define MACB_NBC_SIZE 1
+#define MACB_NCFGR_MTI_OFFSET 6
+#define MACB_NCFGR_MTI_SIZE 1
+#define MACB_UNI_OFFSET 7
+#define MACB_UNI_SIZE 1
+#define MACB_BIG_OFFSET 8
+#define MACB_BIG_SIZE 1
+#define MACB_EAE_OFFSET 9
+#define MACB_EAE_SIZE 1
+#define MACB_CLK_OFFSET 10
+#define MACB_CLK_SIZE 2
+#define MACB_RTY_OFFSET 12
+#define MACB_RTY_SIZE 1
+#define MACB_PAE_OFFSET 13
+#define MACB_PAE_SIZE 1
+#define MACB_RBOF_OFFSET 14
+#define MACB_RBOF_SIZE 2
+#define MACB_RLCE_OFFSET 16
+#define MACB_RLCE_SIZE 1
+#define MACB_DRFCS_OFFSET 17
+#define MACB_DRFCS_SIZE 1
+#define MACB_EFRHD_OFFSET 18
+#define MACB_EFRHD_SIZE 1
+#define MACB_IRXFCS_OFFSET 19
+#define MACB_IRXFCS_SIZE 1
+
+/* Bitfields in NSR */
+#define MACB_NSR_LINK_OFFSET 0
+#define MACB_NSR_LINK_SIZE 1
+#define MACB_MDIO_OFFSET 1
+#define MACB_MDIO_SIZE 1
+#define MACB_IDLE_OFFSET 2
+#define MACB_IDLE_SIZE 1
+
+/* Bitfields in TSR */
+#define MACB_UBR_OFFSET 0
+#define MACB_UBR_SIZE 1
+#define MACB_COL_OFFSET 1
+#define MACB_COL_SIZE 1
+#define MACB_TSR_RLE_OFFSET 2
+#define MACB_TSR_RLE_SIZE 1
+#define MACB_TGO_OFFSET 3
+#define MACB_TGO_SIZE 1
+#define MACB_BEX_OFFSET 4
+#define MACB_BEX_SIZE 1
+#define MACB_COMP_OFFSET 5
+#define MACB_COMP_SIZE 1
+#define MACB_UND_OFFSET 6
+#define MACB_UND_SIZE 1
+
+/* Bitfields in RSR */
+#define MACB_BNA_OFFSET 0
+#define MACB_BNA_SIZE 1
+#define MACB_REC_OFFSET 1
+#define MACB_REC_SIZE 1
+#define MACB_OVR_OFFSET 2
+#define MACB_OVR_SIZE 1
+
+/* Bitfields in ISR/IER/IDR/IMR */
+#define MACB_MFD_OFFSET 0
+#define MACB_MFD_SIZE 1
+#define MACB_RCOMP_OFFSET 1
+#define MACB_RCOMP_SIZE 1
+#define MACB_RXUBR_OFFSET 2
+#define MACB_RXUBR_SIZE 1
+#define MACB_TXUBR_OFFSET 3
+#define MACB_TXUBR_SIZE 1
+#define MACB_ISR_TUND_OFFSET 4
+#define MACB_ISR_TUND_SIZE 1
+#define MACB_ISR_RLE_OFFSET 5
+#define MACB_ISR_RLE_SIZE 1
+#define MACB_TXERR_OFFSET 6
+#define MACB_TXERR_SIZE 1
+#define MACB_TCOMP_OFFSET 7
+#define MACB_TCOMP_SIZE 1
+#define MACB_ISR_LINK_OFFSET 9
+#define MACB_ISR_LINK_SIZE 1
+#define MACB_ISR_ROVR_OFFSET 10
+#define MACB_ISR_ROVR_SIZE 1
+#define MACB_HRESP_OFFSET 11
+#define MACB_HRESP_SIZE 1
+#define MACB_PFR_OFFSET 12
+#define MACB_PFR_SIZE 1
+#define MACB_PTZ_OFFSET 13
+#define MACB_PTZ_SIZE 1
+
+/* Bitfields in MAN */
+#define MACB_DATA_OFFSET 0
+#define MACB_DATA_SIZE 16
+#define MACB_CODE_OFFSET 16
+#define MACB_CODE_SIZE 2
+#define MACB_REGA_OFFSET 18
+#define MACB_REGA_SIZE 5
+#define MACB_PHYA_OFFSET 23
+#define MACB_PHYA_SIZE 5
+#define MACB_RW_OFFSET 28
+#define MACB_RW_SIZE 2
+#define MACB_SOF_OFFSET 30
+#define MACB_SOF_SIZE 2
+
+/* Bitfields in USRIO */
+#define MACB_MII_OFFSET 0
+#define MACB_MII_SIZE 1
+#define MACB_EAM_OFFSET 1
+#define MACB_EAM_SIZE 1
+#define MACB_TX_PAUSE_OFFSET 2
+#define MACB_TX_PAUSE_SIZE 1
+#define MACB_TX_PAUSE_ZERO_OFFSET 3
+#define MACB_TX_PAUSE_ZERO_SIZE 1
+
+/* Bitfields in WOL */
+#define MACB_IP_OFFSET 0
+#define MACB_IP_SIZE 16
+#define MACB_MAG_OFFSET 16
+#define MACB_MAG_SIZE 1
+#define MACB_ARP_OFFSET 17
+#define MACB_ARP_SIZE 1
+#define MACB_SA1_OFFSET 18
+#define MACB_SA1_SIZE 1
+#define MACB_WOL_MTI_OFFSET 19
+#define MACB_WOL_MTI_SIZE 1
+
+/* Constants for CLK */
+#define MACB_CLK_DIV8 0
+#define MACB_CLK_DIV16 1
+#define MACB_CLK_DIV32 2
+#define MACB_CLK_DIV64 3
+
+/* Constants for MAN register */
+#define MACB_MAN_SOF 1
+#define MACB_MAN_WRITE 1
+#define MACB_MAN_READ 2
+#define MACB_MAN_CODE 2
+
+/* Bit manipulation macros */
+#define MACB_BIT(name) \
+ (1 << MACB_##name##_OFFSET)
+#define MACB_BF(name,value) \
+ (((value) & ((1 << MACB_##name##_SIZE) - 1)) \
+ << MACB_##name##_OFFSET)
+#define MACB_BFEXT(name,value)\
+ (((value) >> MACB_##name##_OFFSET) \
+ & ((1 << MACB_##name##_SIZE) - 1))
+#define MACB_BFINS(name,value,old) \
+ (((old) & ~(((1 << MACB_##name##_SIZE) - 1) \
+ << MACB_##name##_OFFSET)) \
+ | MACB_BF(name,value))
+
+/* Register access macros */
+#define macb_readl(port,reg) \
+ readl((port)->regs + MACB_##reg)
+#define macb_writel(port,reg,value) \
+ writel((value), (port)->regs + MACB_##reg)
+
+struct dma_desc {
+ u32 addr;
+ u32 ctrl;
+};
+
+/* DMA descriptor bitfields */
+#define MACB_RX_USED_OFFSET 0
+#define MACB_RX_USED_SIZE 1
+#define MACB_RX_WRAP_OFFSET 1
+#define MACB_RX_WRAP_SIZE 1
+#define MACB_RX_WADDR_OFFSET 2
+#define MACB_RX_WADDR_SIZE 30
+
+#define MACB_RX_FRMLEN_OFFSET 0
+#define MACB_RX_FRMLEN_SIZE 12
+#define MACB_RX_OFFSET_OFFSET 12
+#define MACB_RX_OFFSET_SIZE 2
+#define MACB_RX_SOF_OFFSET 14
+#define MACB_RX_SOF_SIZE 1
+#define MACB_RX_EOF_OFFSET 15
+#define MACB_RX_EOF_SIZE 1
+#define MACB_RX_CFI_OFFSET 16
+#define MACB_RX_CFI_SIZE 1
+#define MACB_RX_VLAN_PRI_OFFSET 17
+#define MACB_RX_VLAN_PRI_SIZE 3
+#define MACB_RX_PRI_TAG_OFFSET 20
+#define MACB_RX_PRI_TAG_SIZE 1
+#define MACB_RX_VLAN_TAG_OFFSET 21
+#define MACB_RX_VLAN_TAG_SIZE 1
+#define MACB_RX_TYPEID_MATCH_OFFSET 22
+#define MACB_RX_TYPEID_MATCH_SIZE 1
+#define MACB_RX_SA4_MATCH_OFFSET 23
+#define MACB_RX_SA4_MATCH_SIZE 1
+#define MACB_RX_SA3_MATCH_OFFSET 24
+#define MACB_RX_SA3_MATCH_SIZE 1
+#define MACB_RX_SA2_MATCH_OFFSET 25
+#define MACB_RX_SA2_MATCH_SIZE 1
+#define MACB_RX_SA1_MATCH_OFFSET 26
+#define MACB_RX_SA1_MATCH_SIZE 1
+#define MACB_RX_EXT_MATCH_OFFSET 28
+#define MACB_RX_EXT_MATCH_SIZE 1
+#define MACB_RX_UHASH_MATCH_OFFSET 29
+#define MACB_RX_UHASH_MATCH_SIZE 1
+#define MACB_RX_MHASH_MATCH_OFFSET 30
+#define MACB_RX_MHASH_MATCH_SIZE 1
+#define MACB_RX_BROADCAST_OFFSET 31
+#define MACB_RX_BROADCAST_SIZE 1
+
+#define MACB_TX_FRMLEN_OFFSET 0
+#define MACB_TX_FRMLEN_SIZE 11
+#define MACB_TX_LAST_OFFSET 15
+#define MACB_TX_LAST_SIZE 1
+#define MACB_TX_NOCRC_OFFSET 16
+#define MACB_TX_NOCRC_SIZE 1
+#define MACB_TX_BUF_EXHAUSTED_OFFSET 27
+#define MACB_TX_BUF_EXHAUSTED_SIZE 1
+#define MACB_TX_UNDERRUN_OFFSET 28
+#define MACB_TX_UNDERRUN_SIZE 1
+#define MACB_TX_ERROR_OFFSET 29
+#define MACB_TX_ERROR_SIZE 1
+#define MACB_TX_WRAP_OFFSET 30
+#define MACB_TX_WRAP_SIZE 1
+#define MACB_TX_USED_OFFSET 31
+#define MACB_TX_USED_SIZE 1
+
+struct ring_info {
+ struct sk_buff *skb;
+ dma_addr_t mapping;
+};
+
+/*
+ * Hardware-collected statistics. Used when updating the network
+ * device stats by a periodic timer.
+ */
+struct macb_stats {
+ u32 rx_pause_frames;
+ u32 tx_ok;
+ u32 tx_single_cols;
+ u32 tx_multiple_cols;
+ u32 rx_ok;
+ u32 rx_fcs_errors;
+ u32 rx_align_errors;
+ u32 tx_deferred;
+ u32 tx_late_cols;
+ u32 tx_excessive_cols;
+ u32 tx_underruns;
+ u32 tx_carrier_errors;
+ u32 rx_resource_errors;
+ u32 rx_overruns;
+ u32 rx_symbol_errors;
+ u32 rx_oversize_pkts;
+ u32 rx_jabbers;
+ u32 rx_undersize_pkts;
+ u32 sqe_test_errors;
+ u32 rx_length_mismatch;
+ u32 tx_pause_frames;
+};
+
+struct macb {
+ void __iomem *regs;
+
+ unsigned int rx_tail;
+ struct dma_desc *rx_ring;
+ void *rx_buffers;
+
+ unsigned int tx_head, tx_tail;
+ struct dma_desc *tx_ring;
+ struct ring_info *tx_skb;
+
+ spinlock_t lock;
+ struct platform_device *pdev;
+ struct clk *pclk;
+ struct clk *hclk;
+ struct net_device *dev;
+ struct net_device_stats stats;
+ struct macb_stats hw_stats;
+
+ dma_addr_t rx_ring_dma;
+ dma_addr_t tx_ring_dma;
+ dma_addr_t rx_buffers_dma;
+
+ unsigned int rx_pending, tx_pending;
+
+ struct work_struct periodic_task;
+
+ struct mutex mdio_mutex;
+ struct completion mdio_complete;
+ struct mii_if_info mii;
+};
+
+#endif /* _MACB_H */
diff --git a/drivers/net/meth.c b/drivers/net/meth.c
index c1aa60b9a982..e1d97cdf649e 100644
--- a/drivers/net/meth.c
+++ b/drivers/net/meth.c
@@ -33,7 +33,6 @@
#include <asm/ip32/ip32_ints.h>
#include <asm/io.h>
-#include <asm/checksum.h>
#include <asm/scatterlist.h>
#include <linux/dma-mapping.h>
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index 98703e086ee7..38df42802386 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -1955,7 +1955,7 @@ again:
flags = (MXGEFW_FLAGS_NO_TSO | MXGEFW_FLAGS_FIRST);
if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
cksum_offset = (skb->h.raw - skb->data);
- pseudo_hdr_offset = (skb->h.raw + skb->csum) - skb->data;
+ pseudo_hdr_offset = cksum_offset + skb->csum_offset;
/* If the headers are excessively large, then we must
* fall back to a software checksum */
if (unlikely(cksum_offset > 255 || pseudo_hdr_offset > 127)) {
diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c
index 7747bfd99f91..ee26ef52289f 100644
--- a/drivers/net/myri_sbus.c
+++ b/drivers/net/myri_sbus.c
@@ -39,7 +39,6 @@ static char version[] =
#include <asm/auxio.h>
#include <asm/pgtable.h>
#include <asm/irq.h>
-#include <asm/checksum.h>
#include "myri_sbus.h"
#include "myri_code.h"
diff --git a/drivers/net/ne-h8300.c b/drivers/net/ne-h8300.c
index eb893d7e8834..38fd525f0f13 100644
--- a/drivers/net/ne-h8300.c
+++ b/drivers/net/ne-h8300.c
@@ -33,6 +33,8 @@ static const char version1[] =
#include <asm/io.h>
#include <asm/irq.h>
+#define EI_SHIFT(x) (ei_local->reg_offset[x])
+
#include "8390.h"
#define DRV_NAME "ne-h8300"
@@ -52,6 +54,11 @@ static const char version1[] =
/* ---- No user-serviceable parts below ---- */
+static const char version[] =
+ "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+
+#include "lib8390.c"
+
#define NE_BASE (dev->base_addr)
#define NE_CMD 0x00
#define NE_DATAPORT (ei_status.word16?0x20:0x10) /* NatSemi-defined port window offset. */
@@ -162,7 +169,7 @@ static void cleanup_card(struct net_device *dev)
#ifndef MODULE
struct net_device * __init ne_probe(int unit)
{
- struct net_device *dev = alloc_ei_netdev();
+ struct net_device *dev = ____alloc_ei_netdev(0);
int err;
if (!dev)
@@ -283,7 +290,7 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
/* Snarf the interrupt now. There's no point in waiting since we cannot
share and the board will usually be enabled. */
- ret = request_irq(dev->irq, ei_interrupt, 0, name, dev);
+ ret = request_irq(dev->irq, __ei_interrupt, 0, name, dev);
if (ret) {
printk (" unable to get IRQ %d (errno=%d).\n", dev->irq, ret);
goto err_out;
@@ -318,9 +325,9 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
dev->open = &ne_open;
dev->stop = &ne_close;
#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = ei_poll;
+ dev->poll_controller = __ei_poll;
#endif
- NS8390_init(dev, 0);
+ __NS8390_init(dev, 0);
ret = register_netdev(dev);
if (ret)
@@ -335,7 +342,7 @@ err_out:
static int ne_open(struct net_device *dev)
{
- ei_open(dev);
+ __ei_open(dev);
return 0;
}
@@ -343,7 +350,7 @@ static int ne_close(struct net_device *dev)
{
if (ei_debug > 1)
printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name);
- ei_close(dev);
+ __ei_close(dev);
return 0;
}
@@ -584,7 +591,7 @@ retry:
if (time_after(jiffies, dma_start + 2*HZ/100)) { /* 20ms */
printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name);
ne_reset_8390(dev);
- NS8390_init(dev,1);
+ __NS8390_init(dev,1);
break;
}
@@ -620,7 +627,7 @@ int init_module(void)
int err;
for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
- struct net_device *dev = alloc_ei_netdev();
+ struct net_device *dev = ____alloc_ei_netdev(0);
if (!dev)
break;
if (io[this_dev]) {
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index bf58db29e2ed..69233f6aa05c 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -60,7 +60,6 @@ static struct netpoll np = {
.local_port = 6665,
.remote_port = 6666,
.remote_mac = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
- .drop = netpoll_queue,
};
static int configured = 0;
@@ -102,6 +101,8 @@ __setup("netconsole=", option_setup);
static int init_netconsole(void)
{
+ int err;
+
if(strlen(config))
option_setup(config);
@@ -110,8 +111,9 @@ static int init_netconsole(void)
return 0;
}
- if(netpoll_setup(&np))
- return -EINVAL;
+ err = netpoll_setup(&np);
+ if (err)
+ return err;
register_console(&netconsole);
printk(KERN_INFO "netconsole: network logging started\n");
diff --git a/drivers/net/netxen/Makefile b/drivers/net/netxen/Makefile
new file mode 100644
index 000000000000..a07cdc6f7384
--- /dev/null
+++ b/drivers/net/netxen/Makefile
@@ -0,0 +1,35 @@
+# Copyright (C) 2003 - 2006 NetXen, Inc.
+# All rights reserved.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA.
+#
+# The full GNU General Public License is included in this distribution
+# in the file called LICENSE.
+#
+# Contact Information:
+# info@netxen.com
+# NetXen,
+# 3965 Freedom Circle, Fourth floor,
+# Santa Clara, CA 95054
+#
+# Makefile for the NetXen NIC Driver
+#
+
+
+obj-$(CONFIG_NETXEN_NIC) := netxen_nic.o
+
+netxen_nic-y := netxen_nic_hw.o netxen_nic_main.o netxen_nic_init.o \
+ netxen_nic_isr.o netxen_nic_ethtool.o netxen_nic_niu.o
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
new file mode 100644
index 000000000000..d925053fe597
--- /dev/null
+++ b/drivers/net/netxen/netxen_nic.h
@@ -0,0 +1,1028 @@
+/*
+ * Copyright (C) 2003 - 2006 NetXen, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.
+ *
+ * Contact Information:
+ * info@netxen.com
+ * NetXen,
+ * 3965 Freedom Circle, Fourth floor,
+ * Santa Clara, CA 95054
+ */
+
+#ifndef _NETXEN_NIC_H_
+#define _NETXEN_NIC_H_
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/compiler.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ip.h>
+#include <linux/in.h>
+#include <linux/tcp.h>
+#include <linux/skbuff.h>
+#include <linux/version.h>
+
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+
+#include <linux/mm.h>
+#include <linux/mman.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/byteorder.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+
+#include "netxen_nic_hw.h"
+
+#define NETXEN_NIC_BUILD_NO "5"
+#define _NETXEN_NIC_LINUX_MAJOR 2
+#define _NETXEN_NIC_LINUX_MINOR 3
+#define _NETXEN_NIC_LINUX_SUBVERSION 59
+#define NETXEN_NIC_LINUX_VERSIONID "2.3.59" "-" NETXEN_NIC_BUILD_NO
+#define NETXEN_NIC_FW_VERSIONID "2.3.59"
+
+#define RCV_DESC_RINGSIZE \
+ (sizeof(struct rcv_desc) * adapter->max_rx_desc_count)
+#define STATUS_DESC_RINGSIZE \
+ (sizeof(struct status_desc)* adapter->max_rx_desc_count)
+#define TX_RINGSIZE \
+ (sizeof(struct netxen_cmd_buffer) * adapter->max_tx_desc_count)
+#define RCV_BUFFSIZE \
+ (sizeof(struct netxen_rx_buffer) * rcv_desc->max_rx_desc_count)
+#define find_diff_among(a,b,range) ((a)<(b)?((b)-(a)):((b)+(range)-(a)))
+
+#define NETXEN_NETDEV_STATUS 0x1
+
+#define ADDR_IN_WINDOW1(off) \
+ ((off > NETXEN_CRB_PCIX_HOST2) && (off < NETXEN_CRB_MAX)) ? 1 : 0
+
+/*
+ * normalize a 64MB crb address to 32MB PCI window
+ * To use NETXEN_CRB_NORMALIZE, window _must_ be set to 1
+ */
+#define NETXEN_CRB_NORMAL(reg) \
+ (reg) - NETXEN_CRB_PCIX_HOST2 + NETXEN_CRB_PCIX_HOST
+
+#define NETXEN_CRB_NORMALIZE(adapter, reg) \
+ pci_base_offset(adapter, NETXEN_CRB_NORMAL(reg))
+
+#define FIRST_PAGE_GROUP_START 0
+#define FIRST_PAGE_GROUP_END 0x400000
+
+#define SECOND_PAGE_GROUP_START 0x4000000
+#define SECOND_PAGE_GROUP_END 0x66BC000
+
+#define THIRD_PAGE_GROUP_START 0x70E4000
+#define THIRD_PAGE_GROUP_END 0x8000000
+
+#define FIRST_PAGE_GROUP_SIZE FIRST_PAGE_GROUP_END - FIRST_PAGE_GROUP_START
+#define SECOND_PAGE_GROUP_SIZE SECOND_PAGE_GROUP_END - SECOND_PAGE_GROUP_START
+#define THIRD_PAGE_GROUP_SIZE THIRD_PAGE_GROUP_END - THIRD_PAGE_GROUP_START
+
+#define MAX_RX_BUFFER_LENGTH 2000
+#define MAX_RX_JUMBO_BUFFER_LENGTH 9046
+#define RX_DMA_MAP_LEN (MAX_RX_BUFFER_LENGTH - NET_IP_ALIGN)
+#define RX_JUMBO_DMA_MAP_LEN \
+ (MAX_RX_JUMBO_BUFFER_LENGTH - NET_IP_ALIGN)
+#define NETXEN_ROM_ROUNDUP 0x80000000ULL
+
+/*
+ * Maximum number of ring contexts
+ */
+#define MAX_RING_CTX 1
+
+/* Opcodes to be used with the commands */
+enum {
+ TX_ETHER_PKT = 0x01,
+/* The following opcodes are for IP checksum */
+ TX_TCP_PKT,
+ TX_UDP_PKT,
+ TX_IP_PKT,
+ TX_TCP_LSO,
+ TX_IPSEC,
+ TX_IPSEC_CMD
+};
+
+/* The following opcodes are for internal consumption. */
+#define NETXEN_CONTROL_OP 0x10
+#define PEGNET_REQUEST 0x11
+
+#define MAX_NUM_CARDS 4
+
+#define MAX_BUFFERS_PER_CMD 32
+
+/*
+ * Following are the states of the Phantom. Phantom will set them and
+ * Host will read to check if the fields are correct.
+ */
+#define PHAN_INITIALIZE_START 0xff00
+#define PHAN_INITIALIZE_FAILED 0xffff
+#define PHAN_INITIALIZE_COMPLETE 0xff01
+
+/* Host writes the following to notify that it has done the init-handshake */
+#define PHAN_INITIALIZE_ACK 0xf00f
+
+#define NUM_RCV_DESC_RINGS 2 /* No of Rcv Descriptor contexts */
+
+/* descriptor types */
+#define RCV_DESC_NORMAL 0x01
+#define RCV_DESC_JUMBO 0x02
+#define RCV_DESC_NORMAL_CTXID 0
+#define RCV_DESC_JUMBO_CTXID 1
+
+#define RCV_DESC_TYPE(ID) \
+ ((ID == RCV_DESC_JUMBO_CTXID) ? RCV_DESC_JUMBO : RCV_DESC_NORMAL)
+
+#define MAX_CMD_DESCRIPTORS 1024
+#define MAX_RCV_DESCRIPTORS 32768
+#define MAX_JUMBO_RCV_DESCRIPTORS 1024
+#define MAX_RCVSTATUS_DESCRIPTORS MAX_RCV_DESCRIPTORS
+#define MAX_JUMBO_RCV_DESC MAX_JUMBO_RCV_DESCRIPTORS
+#define MAX_RCV_DESC MAX_RCV_DESCRIPTORS
+#define MAX_RCVSTATUS_DESC MAX_RCV_DESCRIPTORS
+#define NUM_RCV_DESC (MAX_RCV_DESC + MAX_JUMBO_RCV_DESCRIPTORS)
+#define MAX_EPG_DESCRIPTORS (MAX_CMD_DESCRIPTORS * 8)
+
+#define MIN_TX_COUNT 4096
+#define MIN_RX_COUNT 4096
+
+#define MAX_FRAME_SIZE 0x10000 /* 64K MAX size for LSO */
+
+#define PHAN_PEG_RCV_INITIALIZED 0xff01
+#define PHAN_PEG_RCV_START_INITIALIZE 0xff00
+
+#define get_next_index(index, length) \
+ (((index) + 1) & ((length) - 1))
+
+#define get_index_range(index,length,count) \
+ (((index) + (count)) & ((length) - 1))
+
+/*
+ * Following data structures describe the descriptors that will be used.
+ * Added fileds of tcpHdrSize and ipHdrSize, The driver needs to do it only when
+ * we are doing LSO (above the 1500 size packet) only.
+ */
+
+/*
+ * The size of reference handle been changed to 16 bits to pass the MSS fields
+ * for the LSO packet
+ */
+
+#define FLAGS_CHECKSUM_ENABLED 0x01
+#define FLAGS_LSO_ENABLED 0x02
+#define FLAGS_IPSEC_SA_ADD 0x04
+#define FLAGS_IPSEC_SA_DELETE 0x08
+#define FLAGS_VLAN_TAGGED 0x10
+
+#define CMD_DESC_TOTAL_LENGTH(cmd_desc) \
+ ((cmd_desc)->length_tcp_hdr & 0x00FFFFFF)
+#define CMD_DESC_TCP_HDR_OFFSET(cmd_desc) \
+ (((cmd_desc)->length_tcp_hdr >> 24) & 0x0FF)
+#define CMD_DESC_PORT(cmd_desc) ((cmd_desc)->port_ctxid & 0x0F)
+#define CMD_DESC_CTX_ID(cmd_desc) (((cmd_desc)->port_ctxid >> 4) & 0x0F)
+
+#define CMD_DESC_TOTAL_LENGTH_WRT(cmd_desc, var) \
+ ((cmd_desc)->length_tcp_hdr |= ((var) & 0x00FFFFFF))
+#define CMD_DESC_TCP_HDR_OFFSET_WRT(cmd_desc, var) \
+ ((cmd_desc)->length_tcp_hdr |= (((var) << 24) & 0xFF000000))
+#define CMD_DESC_PORT_WRT(cmd_desc, var) \
+ ((cmd_desc)->port_ctxid |= ((var) & 0x0F))
+
+struct cmd_desc_type0 {
+ u64 netxen_next; /* for fragments handled by Phantom */
+ union {
+ struct {
+ u32 addr_low_part2;
+ u32 addr_high_part2;
+ };
+ u64 addr_buffer2;
+ };
+
+ /* Bit pattern: 0-23 total length, 24-32 tcp header offset */
+ u32 length_tcp_hdr;
+ u8 ip_hdr_offset; /* For LSO only */
+ u8 num_of_buffers; /* total number of segments */
+ u8 flags; /* as defined above */
+ u8 opcode;
+
+ u16 reference_handle; /* changed to u16 to add mss */
+ u16 mss; /* passed by NDIS_PACKET for LSO */
+ /* Bit pattern 0-3 port, 0-3 ctx id */
+ u8 port_ctxid;
+ u8 total_hdr_length; /* LSO only : MAC+IP+TCP Hdr size */
+ u16 conn_id; /* IPSec offoad only */
+
+ union {
+ struct {
+ u32 addr_low_part3;
+ u32 addr_high_part3;
+ };
+ u64 addr_buffer3;
+ };
+
+ union {
+ struct {
+ u32 addr_low_part1;
+ u32 addr_high_part1;
+ };
+ u64 addr_buffer1;
+ };
+
+ u16 buffer1_length;
+ u16 buffer2_length;
+ u16 buffer3_length;
+ u16 buffer4_length;
+
+ union {
+ struct {
+ u32 addr_low_part4;
+ u32 addr_high_part4;
+ };
+ u64 addr_buffer4;
+ };
+
+} __attribute__ ((aligned(64)));
+
+/* Note: sizeof(rcv_desc) should always be a mutliple of 2 */
+struct rcv_desc {
+ u16 reference_handle;
+ u16 reserved;
+ u32 buffer_length; /* allocated buffer length (usually 2K) */
+ u64 addr_buffer;
+};
+
+/* opcode field in status_desc */
+#define RCV_NIC_PKT (0xA)
+#define STATUS_NIC_PKT ((RCV_NIC_PKT) << 12)
+
+/* for status field in status_desc */
+#define STATUS_NEED_CKSUM (1)
+#define STATUS_CKSUM_OK (2)
+
+/* owner bits of status_desc */
+#define STATUS_OWNER_HOST (0x1)
+#define STATUS_OWNER_PHANTOM (0x2)
+
+#define NETXEN_PROT_IP (1)
+#define NETXEN_PROT_UNKNOWN (0)
+
+/* Note: sizeof(status_desc) should always be a mutliple of 2 */
+#define STATUS_DESC_PORT(status_desc) \
+ ((status_desc)->port_status_type_op & 0x0F)
+#define STATUS_DESC_STATUS(status_desc) \
+ (((status_desc)->port_status_type_op >> 4) & 0x0F)
+#define STATUS_DESC_TYPE(status_desc) \
+ (((status_desc)->port_status_type_op >> 8) & 0x0F)
+#define STATUS_DESC_OPCODE(status_desc) \
+ (((status_desc)->port_status_type_op >> 12) & 0x0F)
+
+struct status_desc {
+ /* Bit pattern: 0-3 port, 4-7 status, 8-11 type, 12-15 opcode */
+ u16 port_status_type_op;
+ u16 total_length; /* NIC mode */
+ u16 reference_handle; /* handle for the associated packet */
+ /* Bit pattern: 0-1 owner, 2-5 protocol */
+ u16 owner; /* Owner of the descriptor */
+} __attribute__ ((aligned(8)));
+
+enum {
+ NETXEN_RCV_PEG_0 = 0,
+ NETXEN_RCV_PEG_1
+};
+/* The version of the main data structure */
+#define NETXEN_BDINFO_VERSION 1
+
+/* Magic number to let user know flash is programmed */
+#define NETXEN_BDINFO_MAGIC 0x12345678
+
+/* Max number of Gig ports on a Phantom board */
+#define NETXEN_MAX_PORTS 4
+
+typedef enum {
+ NETXEN_BRDTYPE_P1_BD = 0x0000,
+ NETXEN_BRDTYPE_P1_SB = 0x0001,
+ NETXEN_BRDTYPE_P1_SMAX = 0x0002,
+ NETXEN_BRDTYPE_P1_SOCK = 0x0003,
+
+ NETXEN_BRDTYPE_P2_SOCK_31 = 0x0008,
+ NETXEN_BRDTYPE_P2_SOCK_35 = 0x0009,
+ NETXEN_BRDTYPE_P2_SB35_4G = 0x000a,
+ NETXEN_BRDTYPE_P2_SB31_10G = 0x000b,
+ NETXEN_BRDTYPE_P2_SB31_2G = 0x000c,
+
+ NETXEN_BRDTYPE_P2_SB31_10G_IMEZ = 0x000d,
+ NETXEN_BRDTYPE_P2_SB31_10G_HMEZ = 0x000e,
+ NETXEN_BRDTYPE_P2_SB31_10G_CX4 = 0x000f
+} netxen_brdtype_t;
+
+typedef enum {
+ NETXEN_BRDMFG_INVENTEC = 1
+} netxen_brdmfg;
+
+typedef enum {
+ MEM_ORG_128Mbx4 = 0x0, /* DDR1 only */
+ MEM_ORG_128Mbx8 = 0x1, /* DDR1 only */
+ MEM_ORG_128Mbx16 = 0x2, /* DDR1 only */
+ MEM_ORG_256Mbx4 = 0x3,
+ MEM_ORG_256Mbx8 = 0x4,
+ MEM_ORG_256Mbx16 = 0x5,
+ MEM_ORG_512Mbx4 = 0x6,
+ MEM_ORG_512Mbx8 = 0x7,
+ MEM_ORG_512Mbx16 = 0x8,
+ MEM_ORG_1Gbx4 = 0x9,
+ MEM_ORG_1Gbx8 = 0xa,
+ MEM_ORG_1Gbx16 = 0xb,
+ MEM_ORG_2Gbx4 = 0xc,
+ MEM_ORG_2Gbx8 = 0xd,
+ MEM_ORG_2Gbx16 = 0xe,
+ MEM_ORG_128Mbx32 = 0x10002, /* GDDR only */
+ MEM_ORG_256Mbx32 = 0x10005 /* GDDR only */
+} netxen_mn_mem_org_t;
+
+typedef enum {
+ MEM_ORG_512Kx36 = 0x0,
+ MEM_ORG_1Mx36 = 0x1,
+ MEM_ORG_2Mx36 = 0x2
+} netxen_sn_mem_org_t;
+
+typedef enum {
+ MEM_DEPTH_4MB = 0x1,
+ MEM_DEPTH_8MB = 0x2,
+ MEM_DEPTH_16MB = 0x3,
+ MEM_DEPTH_32MB = 0x4,
+ MEM_DEPTH_64MB = 0x5,
+ MEM_DEPTH_128MB = 0x6,
+ MEM_DEPTH_256MB = 0x7,
+ MEM_DEPTH_512MB = 0x8,
+ MEM_DEPTH_1GB = 0x9,
+ MEM_DEPTH_2GB = 0xa,
+ MEM_DEPTH_4GB = 0xb,
+ MEM_DEPTH_8GB = 0xc,
+ MEM_DEPTH_16GB = 0xd,
+ MEM_DEPTH_32GB = 0xe
+} netxen_mem_depth_t;
+
+struct netxen_board_info {
+ u32 header_version;
+
+ u32 board_mfg;
+ u32 board_type;
+ u32 board_num;
+ u32 chip_id;
+ u32 chip_minor;
+ u32 chip_major;
+ u32 chip_pkg;
+ u32 chip_lot;
+
+ u32 port_mask; /* available niu ports */
+ u32 peg_mask; /* available pegs */
+ u32 icache_ok; /* can we run with icache? */
+ u32 dcache_ok; /* can we run with dcache? */
+ u32 casper_ok;
+
+ u32 mac_addr_lo_0;
+ u32 mac_addr_lo_1;
+ u32 mac_addr_lo_2;
+ u32 mac_addr_lo_3;
+
+ /* MN-related config */
+ u32 mn_sync_mode; /* enable/ sync shift cclk/ sync shift mclk */
+ u32 mn_sync_shift_cclk;
+ u32 mn_sync_shift_mclk;
+ u32 mn_wb_en;
+ u32 mn_crystal_freq; /* in MHz */
+ u32 mn_speed; /* in MHz */
+ u32 mn_org;
+ u32 mn_depth;
+ u32 mn_ranks_0; /* ranks per slot */
+ u32 mn_ranks_1; /* ranks per slot */
+ u32 mn_rd_latency_0;
+ u32 mn_rd_latency_1;
+ u32 mn_rd_latency_2;
+ u32 mn_rd_latency_3;
+ u32 mn_rd_latency_4;
+ u32 mn_rd_latency_5;
+ u32 mn_rd_latency_6;
+ u32 mn_rd_latency_7;
+ u32 mn_rd_latency_8;
+ u32 mn_dll_val[18];
+ u32 mn_mode_reg; /* MIU DDR Mode Register */
+ u32 mn_ext_mode_reg; /* MIU DDR Extended Mode Register */
+ u32 mn_timing_0; /* MIU Memory Control Timing Rgister */
+ u32 mn_timing_1; /* MIU Extended Memory Ctrl Timing Register */
+ u32 mn_timing_2; /* MIU Extended Memory Ctrl Timing2 Register */
+
+ /* SN-related config */
+ u32 sn_sync_mode; /* enable/ sync shift cclk / sync shift mclk */
+ u32 sn_pt_mode; /* pass through mode */
+ u32 sn_ecc_en;
+ u32 sn_wb_en;
+ u32 sn_crystal_freq;
+ u32 sn_speed;
+ u32 sn_org;
+ u32 sn_depth;
+ u32 sn_dll_tap;
+ u32 sn_rd_latency;
+
+ u32 mac_addr_hi_0;
+ u32 mac_addr_hi_1;
+ u32 mac_addr_hi_2;
+ u32 mac_addr_hi_3;
+
+ u32 magic; /* indicates flash has been initialized */
+
+ u32 mn_rdimm;
+ u32 mn_dll_override;
+
+};
+
+#define FLASH_NUM_PORTS (4)
+
+struct netxen_flash_mac_addr {
+ u32 flash_addr[32];
+};
+
+struct netxen_user_old_info {
+ u8 flash_md5[16];
+ u8 crbinit_md5[16];
+ u8 brdcfg_md5[16];
+ /* bootloader */
+ u32 bootld_version;
+ u32 bootld_size;
+ u8 bootld_md5[16];
+ /* image */
+ u32 image_version;
+ u32 image_size;
+ u8 image_md5[16];
+ /* primary image status */
+ u32 primary_status;
+ u32 secondary_present;
+
+ /* MAC address , 4 ports */
+ struct netxen_flash_mac_addr mac_addr[FLASH_NUM_PORTS];
+};
+#define FLASH_NUM_MAC_PER_PORT 32
+struct netxen_user_info {
+ u8 flash_md5[16 * 64];
+ /* bootloader */
+ u32 bootld_version;
+ u32 bootld_size;
+ /* image */
+ u32 image_version;
+ u32 image_size;
+ /* primary image status */
+ u32 primary_status;
+ u32 secondary_present;
+
+ /* MAC address , 4 ports, 32 address per port */
+ u64 mac_addr[FLASH_NUM_PORTS * FLASH_NUM_MAC_PER_PORT];
+ u32 sub_sys_id;
+ u8 serial_num[32];
+
+ /* Any user defined data */
+};
+
+/*
+ * Flash Layout - new format.
+ */
+struct netxen_new_user_info {
+ u8 flash_md5[16 * 64];
+ /* bootloader */
+ u32 bootld_version;
+ u32 bootld_size;
+ /* image */
+ u32 image_version;
+ u32 image_size;
+ /* primary image status */
+ u32 primary_status;
+ u32 secondary_present;
+
+ /* MAC address , 4 ports, 32 address per port */
+ u64 mac_addr[FLASH_NUM_PORTS * FLASH_NUM_MAC_PER_PORT];
+ u32 sub_sys_id;
+ u8 serial_num[32];
+
+ /* Any user defined data */
+};
+
+#define SECONDARY_IMAGE_PRESENT 0xb3b4b5b6
+#define SECONDARY_IMAGE_ABSENT 0xffffffff
+#define PRIMARY_IMAGE_GOOD 0x5a5a5a5a
+#define PRIMARY_IMAGE_BAD 0xffffffff
+
+/* Flash memory map */
+typedef enum {
+ CRBINIT_START = 0, /* Crbinit section */
+ BRDCFG_START = 0x4000, /* board config */
+ INITCODE_START = 0x6000, /* pegtune code */
+ BOOTLD_START = 0x10000, /* bootld */
+ IMAGE_START = 0x43000, /* compressed image */
+ SECONDARY_START = 0x200000, /* backup images */
+ PXE_START = 0x3E0000, /* user defined region */
+ USER_START = 0x3E8000, /* User defined region for new boards */
+ FIXED_START = 0x3F0000 /* backup of crbinit */
+} netxen_flash_map_t;
+
+#define USER_START_OLD PXE_START /* for backward compatibility */
+
+#define FLASH_START (CRBINIT_START)
+#define INIT_SECTOR (0)
+#define PRIMARY_START (BOOTLD_START)
+#define FLASH_CRBINIT_SIZE (0x4000)
+#define FLASH_BRDCFG_SIZE (sizeof(struct netxen_board_info))
+#define FLASH_USER_SIZE (sizeof(netxen_user_info)/sizeof(u32))
+#define FLASH_SECONDARY_SIZE (USER_START-SECONDARY_START)
+#define NUM_PRIMARY_SECTORS (0x20)
+#define NUM_CONFIG_SECTORS (1)
+#define PFX "netxen: "
+
+/* Note: Make sure to not call this before adapter->port is valid */
+#if !defined(NETXEN_DEBUG)
+#define DPRINTK(klevel, fmt, args...) do { \
+ } while (0)
+#else
+#define DPRINTK(klevel, fmt, args...) do { \
+ printk(KERN_##klevel PFX "%s: %s: " fmt, __FUNCTION__,\
+ (adapter != NULL && adapter->port != NULL && \
+ adapter->port[0] != NULL && \
+ adapter->port[0]->netdev != NULL) ? \
+ adapter->port[0]->netdev->name : NULL, \
+ ## args); } while(0)
+#endif
+
+/* Number of status descriptors to handle per interrupt */
+#define MAX_STATUS_HANDLE (128)
+
+/*
+ * netxen_skb_frag{} is to contain mapping info for each SG list. This
+ * has to be freed when DMA is complete. This is part of netxen_tx_buffer{}.
+ */
+struct netxen_skb_frag {
+ u64 dma;
+ u32 length;
+};
+
+/* Following defines are for the state of the buffers */
+#define NETXEN_BUFFER_FREE 0
+#define NETXEN_BUFFER_BUSY 1
+
+/*
+ * There will be one netxen_buffer per skb packet. These will be
+ * used to save the dma info for pci_unmap_page()
+ */
+struct netxen_cmd_buffer {
+ struct sk_buff *skb;
+ struct netxen_skb_frag frag_array[MAX_BUFFERS_PER_CMD + 1];
+ u32 total_length;
+ u32 mss;
+ u16 port;
+ u8 cmd;
+ u8 frag_count;
+ unsigned long time_stamp;
+ u32 state;
+ u32 no_of_descriptors;
+};
+
+/* In rx_buffer, we do not need multiple fragments as is a single buffer */
+struct netxen_rx_buffer {
+ struct sk_buff *skb;
+ u64 dma;
+ u16 ref_handle;
+ u16 state;
+};
+
+/* Board types */
+#define NETXEN_NIC_GBE 0x01
+#define NETXEN_NIC_XGBE 0x02
+
+/*
+ * One hardware_context{} per adapter
+ * contains interrupt info as well shared hardware info.
+ */
+struct netxen_hardware_context {
+ struct pci_dev *pdev;
+ void __iomem *pci_base0;
+ void __iomem *pci_base1;
+ void __iomem *pci_base2;
+
+ u8 revision_id;
+ u16 board_type;
+ u16 max_ports;
+ struct netxen_board_info boardcfg;
+ u32 xg_linkup;
+ u32 qg_linksup;
+ /* Address of cmd ring in Phantom */
+ struct cmd_desc_type0 *cmd_desc_head;
+ char *pauseaddr;
+ struct pci_dev *cmd_desc_pdev;
+ dma_addr_t cmd_desc_phys_addr;
+ dma_addr_t pause_physaddr;
+ struct pci_dev *pause_pdev;
+ struct netxen_adapter *adapter;
+};
+
+#define MINIMUM_ETHERNET_FRAME_SIZE 64 /* With FCS */
+#define ETHERNET_FCS_SIZE 4
+
+struct netxen_adapter_stats {
+ u64 ints;
+ u64 hostints;
+ u64 otherints;
+ u64 process_rcv;
+ u64 process_xmit;
+ u64 noxmitdone;
+ u64 xmitcsummed;
+ u64 post_called;
+ u64 posted;
+ u64 lastposted;
+ u64 goodskbposts;
+};
+
+/*
+ * Rcv Descriptor Context. One such per Rcv Descriptor. There may
+ * be one Rcv Descriptor for normal packets, one for jumbo and may be others.
+ */
+struct netxen_rcv_desc_ctx {
+ u32 flags;
+ u32 producer;
+ u32 rcv_pending; /* Num of bufs posted in phantom */
+ u32 rcv_free; /* Num of bufs in free list */
+ dma_addr_t phys_addr;
+ struct pci_dev *phys_pdev;
+ struct rcv_desc *desc_head; /* address of rx ring in Phantom */
+ u32 max_rx_desc_count;
+ u32 dma_size;
+ u32 skb_size;
+ struct netxen_rx_buffer *rx_buf_arr; /* rx buffers for receive */
+ int begin_alloc;
+};
+
+/*
+ * Receive context. There is one such structure per instance of the
+ * receive processing. Any state information that is relevant to
+ * the receive, and is must be in this structure. The global data may be
+ * present elsewhere.
+ */
+struct netxen_recv_context {
+ struct netxen_rcv_desc_ctx rcv_desc[NUM_RCV_DESC_RINGS];
+ u32 status_rx_producer;
+ u32 status_rx_consumer;
+ dma_addr_t rcv_status_desc_phys_addr;
+ struct pci_dev *rcv_status_desc_pdev;
+ struct status_desc *rcv_status_desc_head;
+};
+
+#define NETXEN_NIC_MSI_ENABLED 0x02
+
+struct netxen_drvops;
+
+struct netxen_adapter {
+ struct netxen_hardware_context ahw;
+ int port_count; /* Number of configured ports */
+ int active_ports; /* Number of open ports */
+ struct netxen_port *port[NETXEN_MAX_PORTS]; /* ptr to each port */
+ spinlock_t tx_lock;
+ spinlock_t lock;
+ struct work_struct watchdog_task;
+ struct work_struct tx_timeout_task;
+ struct timer_list watchdog_timer;
+
+ u32 curr_window;
+
+ u32 cmd_producer;
+ u32 cmd_consumer;
+
+ u32 last_cmd_consumer;
+ u32 max_tx_desc_count;
+ u32 max_rx_desc_count;
+ u32 max_jumbo_rx_desc_count;
+ /* Num of instances active on cmd buffer ring */
+ u32 proc_cmd_buf_counter;
+
+ u32 num_threads, total_threads; /*Use to keep track of xmit threads */
+
+ u32 flags;
+ u32 irq;
+ int driver_mismatch;
+ u32 temp;
+
+ struct netxen_adapter_stats stats;
+
+ struct netxen_cmd_buffer *cmd_buf_arr; /* Command buffers for xmit */
+
+ /*
+ * Receive instances. These can be either one per port,
+ * or one per peg, etc.
+ */
+ struct netxen_recv_context recv_ctx[MAX_RCV_CTX];
+
+ int is_up;
+ int work_done;
+ struct netxen_drvops *ops;
+}; /* netxen_adapter structure */
+
+/* Max number of xmit producer threads that can run simultaneously */
+#define MAX_XMIT_PRODUCERS 16
+
+struct netxen_port_stats {
+ u64 rcvdbadskb;
+ u64 xmitcalled;
+ u64 xmitedframes;
+ u64 xmitfinished;
+ u64 badskblen;
+ u64 nocmddescriptor;
+ u64 polled;
+ u64 uphappy;
+ u64 updropped;
+ u64 uplcong;
+ u64 uphcong;
+ u64 upmcong;
+ u64 updunno;
+ u64 skbfreed;
+ u64 txdropped;
+ u64 txnullskb;
+ u64 csummed;
+ u64 no_rcv;
+ u64 rxbytes;
+ u64 txbytes;
+};
+
+struct netxen_port {
+ struct netxen_adapter *adapter;
+
+ u16 portnum; /* GBE port number */
+ u16 link_speed;
+ u16 link_duplex;
+ u16 link_autoneg;
+
+ int flags;
+
+ struct net_device *netdev;
+ struct pci_dev *pdev;
+ struct net_device_stats net_stats;
+ struct netxen_port_stats stats;
+};
+
+#define PCI_OFFSET_FIRST_RANGE(adapter, off) \
+ ((adapter)->ahw.pci_base0 + (off))
+#define PCI_OFFSET_SECOND_RANGE(adapter, off) \
+ ((adapter)->ahw.pci_base1 + (off) - SECOND_PAGE_GROUP_START)
+#define PCI_OFFSET_THIRD_RANGE(adapter, off) \
+ ((adapter)->ahw.pci_base2 + (off) - THIRD_PAGE_GROUP_START)
+
+static inline void __iomem *pci_base_offset(struct netxen_adapter *adapter,
+ unsigned long off)
+{
+ if ((off < FIRST_PAGE_GROUP_END) && (off >= FIRST_PAGE_GROUP_START)) {
+ return (adapter->ahw.pci_base0 + off);
+ } else if ((off < SECOND_PAGE_GROUP_END) &&
+ (off >= SECOND_PAGE_GROUP_START)) {
+ return (adapter->ahw.pci_base1 + off - SECOND_PAGE_GROUP_START);
+ } else if ((off < THIRD_PAGE_GROUP_END) &&
+ (off >= THIRD_PAGE_GROUP_START)) {
+ return (adapter->ahw.pci_base2 + off - THIRD_PAGE_GROUP_START);
+ }
+ return NULL;
+}
+
+static inline void __iomem *pci_base(struct netxen_adapter *adapter,
+ unsigned long off)
+{
+ if ((off < FIRST_PAGE_GROUP_END) && (off >= FIRST_PAGE_GROUP_START)) {
+ return adapter->ahw.pci_base0;
+ } else if ((off < SECOND_PAGE_GROUP_END) &&
+ (off >= SECOND_PAGE_GROUP_START)) {
+ return adapter->ahw.pci_base1;
+ } else if ((off < THIRD_PAGE_GROUP_END) &&
+ (off >= THIRD_PAGE_GROUP_START)) {
+ return adapter->ahw.pci_base2;
+ }
+ return NULL;
+}
+
+struct netxen_drvops {
+ int (*enable_phy_interrupts) (struct netxen_adapter *, int);
+ int (*disable_phy_interrupts) (struct netxen_adapter *, int);
+ void (*handle_phy_intr) (struct netxen_adapter *);
+ int (*macaddr_set) (struct netxen_port *, netxen_ethernet_macaddr_t);
+ int (*set_mtu) (struct netxen_port *, int);
+ int (*set_promisc) (struct netxen_adapter *, int,
+ netxen_niu_prom_mode_t);
+ int (*unset_promisc) (struct netxen_adapter *, int,
+ netxen_niu_prom_mode_t);
+ int (*phy_read) (struct netxen_adapter *, long phy, long reg, u32 *);
+ int (*phy_write) (struct netxen_adapter *, long phy, long reg, u32 val);
+ int (*init_port) (struct netxen_adapter *, int);
+ void (*init_niu) (struct netxen_adapter *);
+ int (*stop_port) (struct netxen_adapter *, int);
+};
+
+extern char netxen_nic_driver_name[];
+
+int netxen_niu_xgbe_enable_phy_interrupts(struct netxen_adapter *adapter,
+ int port);
+int netxen_niu_gbe_enable_phy_interrupts(struct netxen_adapter *adapter,
+ int port);
+int netxen_niu_xgbe_disable_phy_interrupts(struct netxen_adapter *adapter,
+ int port);
+int netxen_niu_gbe_disable_phy_interrupts(struct netxen_adapter *adapter,
+ int port);
+int netxen_niu_xgbe_clear_phy_interrupts(struct netxen_adapter *adapter,
+ int port);
+int netxen_niu_gbe_clear_phy_interrupts(struct netxen_adapter *adapter,
+ int port);
+void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter);
+void netxen_nic_gbe_handle_phy_intr(struct netxen_adapter *adapter);
+void netxen_niu_gbe_set_mii_mode(struct netxen_adapter *adapter, int port,
+ long enable);
+void netxen_niu_gbe_set_gmii_mode(struct netxen_adapter *adapter, int port,
+ long enable);
+int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long phy, long reg,
+ __le32 * readval);
+int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long phy,
+ long reg, __le32 val);
+
+/* Functions available from netxen_nic_hw.c */
+int netxen_nic_set_mtu_xgb(struct netxen_port *port, int new_mtu);
+int netxen_nic_set_mtu_gb(struct netxen_port *port, int new_mtu);
+void netxen_nic_init_niu_gb(struct netxen_adapter *adapter);
+void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw);
+void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val);
+int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off);
+void netxen_nic_write_w0(struct netxen_adapter *adapter, u32 index, u32 value);
+void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 * value);
+
+int netxen_nic_get_board_info(struct netxen_adapter *adapter);
+int netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off, void *data,
+ int len);
+int netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data,
+ int len);
+void netxen_crb_writelit_adapter(struct netxen_adapter *adapter,
+ unsigned long off, int data);
+
+/* Functions from netxen_nic_init.c */
+void netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val);
+void netxen_load_firmware(struct netxen_adapter *adapter);
+int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose);
+int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp);
+int netxen_rom_fast_write(struct netxen_adapter *adapter, int addr, int data);
+int netxen_rom_se(struct netxen_adapter *adapter, int addr);
+int netxen_do_rom_se(struct netxen_adapter *adapter, int addr);
+
+/* Functions from netxen_nic_isr.c */
+void netxen_nic_isr_other(struct netxen_adapter *adapter);
+void netxen_indicate_link_status(struct netxen_adapter *adapter, u32 port,
+ u32 link);
+void netxen_handle_port_int(struct netxen_adapter *adapter, u32 port,
+ u32 enable);
+void netxen_nic_stop_all_ports(struct netxen_adapter *adapter);
+void netxen_initialize_adapter_sw(struct netxen_adapter *adapter);
+void netxen_initialize_adapter_hw(struct netxen_adapter *adapter);
+void *netxen_alloc(struct pci_dev *pdev, size_t sz, dma_addr_t * ptr,
+ struct pci_dev **used_dev);
+void netxen_initialize_adapter_ops(struct netxen_adapter *adapter);
+int netxen_init_firmware(struct netxen_adapter *adapter);
+void netxen_free_hw_resources(struct netxen_adapter *adapter);
+void netxen_tso_check(struct netxen_adapter *adapter,
+ struct cmd_desc_type0 *desc, struct sk_buff *skb);
+int netxen_nic_hw_resources(struct netxen_adapter *adapter);
+void netxen_nic_clear_stats(struct netxen_adapter *adapter);
+int
+netxen_nic_do_ioctl(struct netxen_adapter *adapter, void *u_data,
+ struct netxen_port *port);
+int netxen_nic_rx_has_work(struct netxen_adapter *adapter);
+int netxen_nic_tx_has_work(struct netxen_adapter *adapter);
+void netxen_watchdog_task(unsigned long v);
+void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx,
+ u32 ringid);
+void netxen_process_cmd_ring(unsigned long data);
+u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctx, int max);
+void netxen_nic_set_multi(struct net_device *netdev);
+int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu);
+int netxen_nic_set_mac(struct net_device *netdev, void *p);
+struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev);
+
+static inline void netxen_nic_disable_int(struct netxen_adapter *adapter)
+{
+ /*
+ * ISR_INT_MASK: Can be read from window 0 or 1.
+ */
+ writel(0x7ff, PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK));
+
+}
+
+static inline void netxen_nic_enable_int(struct netxen_adapter *adapter)
+{
+ u32 mask;
+
+ switch (adapter->ahw.board_type) {
+ case NETXEN_NIC_GBE:
+ mask = 0x77b;
+ break;
+ case NETXEN_NIC_XGBE:
+ mask = 0x77f;
+ break;
+ default:
+ mask = 0x7ff;
+ break;
+ }
+
+ writel(mask, PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK));
+
+ if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
+ mask = 0xbff;
+ writel(mask, PCI_OFFSET_SECOND_RANGE(adapter,
+ ISR_INT_TARGET_MASK));
+ }
+}
+
+/*
+ * NetXen Board information
+ */
+
+#define NETXEN_MAX_SHORT_NAME 16
+struct netxen_brdinfo {
+ netxen_brdtype_t brdtype; /* type of board */
+ long ports; /* max no of physical ports */
+ char short_name[NETXEN_MAX_SHORT_NAME];
+};
+
+static const struct netxen_brdinfo netxen_boards[] = {
+ {NETXEN_BRDTYPE_P2_SB31_10G_CX4, 1, "XGb CX4"},
+ {NETXEN_BRDTYPE_P2_SB31_10G_HMEZ, 1, "XGb HMEZ"},
+ {NETXEN_BRDTYPE_P2_SB31_10G_IMEZ, 2, "XGb IMEZ"},
+ {NETXEN_BRDTYPE_P2_SB31_10G, 1, "XGb XFP"},
+ {NETXEN_BRDTYPE_P2_SB35_4G, 4, "Quad Gb"},
+ {NETXEN_BRDTYPE_P2_SB31_2G, 2, "Dual Gb"},
+};
+
+#define NUM_SUPPORTED_BOARDS (sizeof(netxen_boards)/sizeof(struct netxen_brdinfo))
+
+static inline void get_brd_port_by_type(u32 type, int *ports)
+{
+ int i, found = 0;
+ for (i = 0; i < NUM_SUPPORTED_BOARDS; ++i) {
+ if (netxen_boards[i].brdtype == type) {
+ *ports = netxen_boards[i].ports;
+ found = 1;
+ break;
+ }
+ }
+ if (!found)
+ *ports = 0;
+}
+
+static inline void get_brd_name_by_type(u32 type, char *name)
+{
+ int i, found = 0;
+ for (i = 0; i < NUM_SUPPORTED_BOARDS; ++i) {
+ if (netxen_boards[i].brdtype == type) {
+ strcpy(name, netxen_boards[i].short_name);
+ found = 1;
+ break;
+ }
+
+ }
+ if (!found)
+ name = "Unknown";
+}
+
+int netxen_is_flash_supported(struct netxen_adapter *adapter);
+int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, u64 mac[]);
+
+extern void netxen_change_ringparam(struct netxen_adapter *adapter);
+extern int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr,
+ int *valp);
+
+extern struct ethtool_ops netxen_nic_ethtool_ops;
+
+#endif /* __NETXEN_NIC_H_ */
diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c
new file mode 100644
index 000000000000..9a914aeba5bc
--- /dev/null
+++ b/drivers/net/netxen/netxen_nic_ethtool.c
@@ -0,0 +1,741 @@
+/*
+ * Copyright (C) 2003 - 2006 NetXen, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.
+ *
+ * Contact Information:
+ * info@netxen.com
+ * NetXen,
+ * 3965 Freedom Circle, Fourth floor,
+ * Santa Clara, CA 95054
+ *
+ *
+ * ethtool support for netxen nic
+ *
+ */
+
+#include <linux/types.h>
+#include <asm/uaccess.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/version.h>
+
+#include "netxen_nic_hw.h"
+#include "netxen_nic.h"
+#include "netxen_nic_phan_reg.h"
+#include "netxen_nic_ioctl.h"
+
+struct netxen_nic_stats {
+ char stat_string[ETH_GSTRING_LEN];
+ int sizeof_stat;
+ int stat_offset;
+};
+
+#define NETXEN_NIC_STAT(m) sizeof(((struct netxen_port *)0)->m), \
+ offsetof(struct netxen_port, m)
+
+#define NETXEN_NIC_PORT_WINDOW 0x10000
+#define NETXEN_NIC_INVALID_DATA 0xDEADBEEF
+
+static const struct netxen_nic_stats netxen_nic_gstrings_stats[] = {
+ {"rcvd_bad_skb", NETXEN_NIC_STAT(stats.rcvdbadskb)},
+ {"xmit_called", NETXEN_NIC_STAT(stats.xmitcalled)},
+ {"xmited_frames", NETXEN_NIC_STAT(stats.xmitedframes)},
+ {"xmit_finished", NETXEN_NIC_STAT(stats.xmitfinished)},
+ {"bad_skb_len", NETXEN_NIC_STAT(stats.badskblen)},
+ {"no_cmd_desc", NETXEN_NIC_STAT(stats.nocmddescriptor)},
+ {"polled", NETXEN_NIC_STAT(stats.polled)},
+ {"uphappy", NETXEN_NIC_STAT(stats.uphappy)},
+ {"updropped", NETXEN_NIC_STAT(stats.updropped)},
+ {"uplcong", NETXEN_NIC_STAT(stats.uplcong)},
+ {"uphcong", NETXEN_NIC_STAT(stats.uphcong)},
+ {"upmcong", NETXEN_NIC_STAT(stats.upmcong)},
+ {"updunno", NETXEN_NIC_STAT(stats.updunno)},
+ {"skb_freed", NETXEN_NIC_STAT(stats.skbfreed)},
+ {"tx_dropped", NETXEN_NIC_STAT(stats.txdropped)},
+ {"tx_null_skb", NETXEN_NIC_STAT(stats.txnullskb)},
+ {"csummed", NETXEN_NIC_STAT(stats.csummed)},
+ {"no_rcv", NETXEN_NIC_STAT(stats.no_rcv)},
+ {"rx_bytes", NETXEN_NIC_STAT(stats.rxbytes)},
+ {"tx_bytes", NETXEN_NIC_STAT(stats.txbytes)},
+};
+
+#define NETXEN_NIC_STATS_LEN \
+ sizeof(netxen_nic_gstrings_stats) / sizeof(struct netxen_nic_stats)
+
+static const char netxen_nic_gstrings_test[][ETH_GSTRING_LEN] = {
+ "Register_Test_offline", "EEPROM_Test_offline",
+ "Interrupt_Test_offline", "Loopback_Test_offline",
+ "Link_Test_on_offline"
+};
+
+#define NETXEN_NIC_TEST_LEN sizeof(netxen_nic_gstrings_test) / ETH_GSTRING_LEN
+
+#define NETXEN_NIC_REGS_COUNT 42
+#define NETXEN_NIC_REGS_LEN (NETXEN_NIC_REGS_COUNT * sizeof(__le32))
+#define NETXEN_MAX_EEPROM_LEN 1024
+
+static int netxen_nic_get_eeprom_len(struct net_device *dev)
+{
+ struct netxen_port *port = netdev_priv(dev);
+ struct netxen_adapter *adapter = port->adapter;
+ int n;
+
+ if ((netxen_rom_fast_read(adapter, 0, &n) == 0)
+ && (n & NETXEN_ROM_ROUNDUP)) {
+ n &= ~NETXEN_ROM_ROUNDUP;
+ if (n < NETXEN_MAX_EEPROM_LEN)
+ return n;
+ }
+ return 0;
+}
+
+static void
+netxen_nic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
+{
+ struct netxen_port *port = netdev_priv(dev);
+ struct netxen_adapter *adapter = port->adapter;
+ u32 fw_major = 0;
+ u32 fw_minor = 0;
+ u32 fw_build = 0;
+
+ strncpy(drvinfo->driver, "netxen_nic", 32);
+ strncpy(drvinfo->version, NETXEN_NIC_LINUX_VERSIONID, 32);
+ fw_major = readl(NETXEN_CRB_NORMALIZE(adapter,
+ NETXEN_FW_VERSION_MAJOR));
+ fw_minor = readl(NETXEN_CRB_NORMALIZE(adapter,
+ NETXEN_FW_VERSION_MINOR));
+ fw_build = readl(NETXEN_CRB_NORMALIZE(adapter, NETXEN_FW_VERSION_SUB));
+ sprintf(drvinfo->fw_version, "%d.%d.%d", fw_major, fw_minor, fw_build);
+
+ strncpy(drvinfo->bus_info, pci_name(port->pdev), 32);
+ drvinfo->n_stats = NETXEN_NIC_STATS_LEN;
+ drvinfo->testinfo_len = NETXEN_NIC_TEST_LEN;
+ drvinfo->regdump_len = NETXEN_NIC_REGS_LEN;
+ drvinfo->eedump_len = netxen_nic_get_eeprom_len(dev);
+}
+
+static int
+netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+ struct netxen_port *port = netdev_priv(dev);
+ struct netxen_adapter *adapter = port->adapter;
+ struct netxen_board_info *boardinfo = &adapter->ahw.boardcfg;
+
+ /* read which mode */
+ if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
+ ecmd->supported = (SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_1000baseT_Half |
+ SUPPORTED_1000baseT_Full);
+
+ ecmd->advertising = (ADVERTISED_100baseT_Half |
+ ADVERTISED_100baseT_Full |
+ ADVERTISED_1000baseT_Half |
+ ADVERTISED_1000baseT_Full);
+
+ ecmd->port = PORT_TP;
+
+ if (netif_running(dev)) {
+ ecmd->speed = port->link_speed;
+ ecmd->duplex = port->link_duplex;
+ } else
+ return -EIO; /* link absent */
+ } else if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
+ ecmd->supported = (SUPPORTED_TP |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_10000baseT_Full);
+ ecmd->advertising = (ADVERTISED_TP |
+ ADVERTISED_1000baseT_Full |
+ ADVERTISED_10000baseT_Full);
+ ecmd->port = PORT_TP;
+
+ ecmd->speed = SPEED_10000;
+ ecmd->duplex = DUPLEX_FULL;
+ ecmd->autoneg = AUTONEG_DISABLE;
+ } else
+ return -EIO;
+
+ ecmd->phy_address = port->portnum;
+ ecmd->transceiver = XCVR_EXTERNAL;
+
+ switch ((netxen_brdtype_t) boardinfo->board_type) {
+ case NETXEN_BRDTYPE_P2_SB35_4G:
+ case NETXEN_BRDTYPE_P2_SB31_2G:
+ ecmd->supported |= SUPPORTED_Autoneg;
+ ecmd->advertising |= ADVERTISED_Autoneg;
+ case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
+ ecmd->supported |= SUPPORTED_TP;
+ ecmd->advertising |= ADVERTISED_TP;
+ ecmd->port = PORT_TP;
+ ecmd->autoneg = (boardinfo->board_type ==
+ NETXEN_BRDTYPE_P2_SB31_10G_CX4) ?
+ (AUTONEG_DISABLE) : (port->link_autoneg);
+ break;
+ case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ:
+ case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
+ ecmd->supported |= SUPPORTED_MII;
+ ecmd->advertising |= ADVERTISED_MII;
+ ecmd->port = PORT_FIBRE;
+ ecmd->autoneg = AUTONEG_DISABLE;
+ break;
+ case NETXEN_BRDTYPE_P2_SB31_10G:
+ ecmd->supported |= SUPPORTED_FIBRE;
+ ecmd->advertising |= ADVERTISED_FIBRE;
+ ecmd->port = PORT_FIBRE;
+ ecmd->autoneg = AUTONEG_DISABLE;
+ break;
+ default:
+ printk(KERN_ERR "netxen-nic: Unsupported board model %d\n",
+ (netxen_brdtype_t) boardinfo->board_type);
+ return -EIO;
+
+ }
+
+ return 0;
+}
+
+static int
+netxen_nic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+ struct netxen_port *port = netdev_priv(dev);
+ struct netxen_adapter *adapter = port->adapter;
+ __le32 status;
+
+ /* read which mode */
+ if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
+ /* autonegotiation */
+ if (adapter->ops->phy_write
+ && adapter->ops->phy_write(adapter, port->portnum,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG,
+ (__le32) ecmd->autoneg) != 0)
+ return -EIO;
+ else
+ port->link_autoneg = ecmd->autoneg;
+
+ if (adapter->ops->phy_read
+ && adapter->ops->phy_read(adapter, port->portnum,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
+ &status) != 0)
+ return -EIO;
+
+ /* speed */
+ switch (ecmd->speed) {
+ case SPEED_10:
+ netxen_set_phy_speed(status, 0);
+ break;
+ case SPEED_100:
+ netxen_set_phy_speed(status, 1);
+ break;
+ case SPEED_1000:
+ netxen_set_phy_speed(status, 2);
+ break;
+ }
+ /* set duplex mode */
+ if (ecmd->duplex == DUPLEX_HALF)
+ netxen_clear_phy_duplex(status);
+ if (ecmd->duplex == DUPLEX_FULL)
+ netxen_set_phy_duplex(status);
+ if (adapter->ops->phy_write
+ && adapter->ops->phy_write(adapter, port->portnum,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
+ *((int *)&status)) != 0)
+ return -EIO;
+ else {
+ port->link_speed = ecmd->speed;
+ port->link_duplex = ecmd->duplex;
+ }
+ } else
+ return -EOPNOTSUPP;
+
+ if (netif_running(dev)) {
+ dev->stop(dev);
+ dev->open(dev);
+ }
+ return 0;
+}
+
+static int netxen_nic_get_regs_len(struct net_device *dev)
+{
+ return NETXEN_NIC_REGS_LEN;
+}
+
+struct netxen_niu_regs {
+ __le32 reg[NETXEN_NIC_REGS_COUNT];
+};
+
+static struct netxen_niu_regs niu_registers[] = {
+ {
+ /* GB Mode */
+ {
+ NETXEN_NIU_GB_SERDES_RESET,
+ NETXEN_NIU_GB0_MII_MODE,
+ NETXEN_NIU_GB1_MII_MODE,
+ NETXEN_NIU_GB2_MII_MODE,
+ NETXEN_NIU_GB3_MII_MODE,
+ NETXEN_NIU_GB0_GMII_MODE,
+ NETXEN_NIU_GB1_GMII_MODE,
+ NETXEN_NIU_GB2_GMII_MODE,
+ NETXEN_NIU_GB3_GMII_MODE,
+ NETXEN_NIU_REMOTE_LOOPBACK,
+ NETXEN_NIU_GB0_HALF_DUPLEX,
+ NETXEN_NIU_GB1_HALF_DUPLEX,
+ NETXEN_NIU_RESET_SYS_FIFOS,
+ NETXEN_NIU_GB_CRC_DROP,
+ NETXEN_NIU_GB_DROP_WRONGADDR,
+ NETXEN_NIU_TEST_MUX_CTL,
+
+ NETXEN_NIU_GB_MAC_CONFIG_0(0),
+ NETXEN_NIU_GB_MAC_CONFIG_1(0),
+ NETXEN_NIU_GB_HALF_DUPLEX_CTRL(0),
+ NETXEN_NIU_GB_MAX_FRAME_SIZE(0),
+ NETXEN_NIU_GB_TEST_REG(0),
+ NETXEN_NIU_GB_MII_MGMT_CONFIG(0),
+ NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
+ NETXEN_NIU_GB_MII_MGMT_ADDR(0),
+ NETXEN_NIU_GB_MII_MGMT_CTRL(0),
+ NETXEN_NIU_GB_MII_MGMT_STATUS(0),
+ NETXEN_NIU_GB_MII_MGMT_INDICATE(0),
+ NETXEN_NIU_GB_INTERFACE_CTRL(0),
+ NETXEN_NIU_GB_INTERFACE_STATUS(0),
+ NETXEN_NIU_GB_STATION_ADDR_0(0),
+ NETXEN_NIU_GB_STATION_ADDR_1(0),
+ -1,
+ }
+ },
+ {
+ /* XG Mode */
+ {
+ NETXEN_NIU_XG_SINGLE_TERM,
+ NETXEN_NIU_XG_DRIVE_HI,
+ NETXEN_NIU_XG_DRIVE_LO,
+ NETXEN_NIU_XG_DTX,
+ NETXEN_NIU_XG_DEQ,
+ NETXEN_NIU_XG_WORD_ALIGN,
+ NETXEN_NIU_XG_RESET,
+ NETXEN_NIU_XG_POWER_DOWN,
+ NETXEN_NIU_XG_RESET_PLL,
+ NETXEN_NIU_XG_SERDES_LOOPBACK,
+ NETXEN_NIU_XG_DO_BYTE_ALIGN,
+ NETXEN_NIU_XG_TX_ENABLE,
+ NETXEN_NIU_XG_RX_ENABLE,
+ NETXEN_NIU_XG_STATUS,
+ NETXEN_NIU_XG_PAUSE_THRESHOLD,
+ NETXEN_NIU_XGE_CONFIG_0,
+ NETXEN_NIU_XGE_CONFIG_1,
+ NETXEN_NIU_XGE_IPG,
+ NETXEN_NIU_XGE_STATION_ADDR_0_HI,
+ NETXEN_NIU_XGE_STATION_ADDR_0_1,
+ NETXEN_NIU_XGE_STATION_ADDR_1_LO,
+ NETXEN_NIU_XGE_STATUS,
+ NETXEN_NIU_XGE_MAX_FRAME_SIZE,
+ NETXEN_NIU_XGE_PAUSE_FRAME_VALUE,
+ NETXEN_NIU_XGE_TX_BYTE_CNT,
+ NETXEN_NIU_XGE_TX_FRAME_CNT,
+ NETXEN_NIU_XGE_RX_BYTE_CNT,
+ NETXEN_NIU_XGE_RX_FRAME_CNT,
+ NETXEN_NIU_XGE_AGGR_ERROR_CNT,
+ NETXEN_NIU_XGE_MULTICAST_FRAME_CNT,
+ NETXEN_NIU_XGE_UNICAST_FRAME_CNT,
+ NETXEN_NIU_XGE_CRC_ERROR_CNT,
+ NETXEN_NIU_XGE_OVERSIZE_FRAME_ERR,
+ NETXEN_NIU_XGE_UNDERSIZE_FRAME_ERR,
+ NETXEN_NIU_XGE_LOCAL_ERROR_CNT,
+ NETXEN_NIU_XGE_REMOTE_ERROR_CNT,
+ NETXEN_NIU_XGE_CONTROL_CHAR_CNT,
+ NETXEN_NIU_XGE_PAUSE_FRAME_CNT,
+ -1,
+ }
+ }
+};
+
+static void
+netxen_nic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
+{
+ struct netxen_port *port = netdev_priv(dev);
+ struct netxen_adapter *adapter = port->adapter;
+ __le32 mode, *regs_buff = p;
+ void __iomem *addr;
+ int i, window;
+
+ memset(p, 0, NETXEN_NIC_REGS_LEN);
+ regs->version = (1 << 24) | (adapter->ahw.revision_id << 16) |
+ (port->pdev)->device;
+ /* which mode */
+ NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_MODE, &regs_buff[0]);
+ mode = regs_buff[0];
+
+ /* Common registers to all the modes */
+ NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_STRAP_VALUE_SAVE_HIGHER,
+ &regs_buff[2]);
+ /* GB/XGB Mode */
+ mode = (mode / 2) - 1;
+ window = 0;
+ if (mode <= 1) {
+ for (i = 3; niu_registers[mode].reg[i - 3] != -1; i++) {
+ /* GB: port specific registers */
+ if (mode == 0 && i >= 19)
+ window = port->portnum * NETXEN_NIC_PORT_WINDOW;
+
+ NETXEN_NIC_LOCKED_READ_REG(niu_registers[mode].
+ reg[i - 3] + window,
+ &regs_buff[i]);
+ }
+
+ }
+}
+
+static void
+netxen_nic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ wol->supported = WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC;
+ /* options can be added depending upon the mode */
+ wol->wolopts = 0;
+}
+
+static u32 netxen_nic_get_link(struct net_device *dev)
+{
+ struct netxen_port *port = netdev_priv(dev);
+ struct netxen_adapter *adapter = port->adapter;
+ __le32 status;
+
+ /* read which mode */
+ if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
+ if (adapter->ops->phy_read
+ && adapter->ops->phy_read(adapter, port->portnum,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
+ &status) != 0)
+ return -EIO;
+ else
+ return (netxen_get_phy_link(status));
+ } else if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
+ int val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_XG_STATE));
+ return val == XG_LINK_UP;
+ }
+ return -EIO;
+}
+
+static int
+netxen_nic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
+ u8 * bytes)
+{
+ struct netxen_port *port = netdev_priv(dev);
+ struct netxen_adapter *adapter = port->adapter;
+ int offset;
+
+ if (eeprom->len == 0)
+ return -EINVAL;
+
+ eeprom->magic = (port->pdev)->vendor | ((port->pdev)->device << 16);
+ for (offset = 0; offset < eeprom->len; offset++)
+ if (netxen_rom_fast_read
+ (adapter, (8 * offset) + 8, (int *)eeprom->data) == -1)
+ return -EIO;
+ return 0;
+}
+
+static void
+netxen_nic_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring)
+{
+ struct netxen_port *port = netdev_priv(dev);
+ struct netxen_adapter *adapter = port->adapter;
+ int i, j;
+
+ ring->rx_pending = 0;
+ for (i = 0; i < MAX_RCV_CTX; ++i) {
+ for (j = 0; j < NUM_RCV_DESC_RINGS; j++)
+ ring->rx_pending +=
+ adapter->recv_ctx[i].rcv_desc[j].rcv_pending;
+ }
+
+ ring->rx_max_pending = adapter->max_rx_desc_count;
+ ring->tx_max_pending = adapter->max_tx_desc_count;
+ ring->rx_mini_max_pending = 0;
+ ring->rx_mini_pending = 0;
+ ring->rx_jumbo_max_pending = 0;
+ ring->rx_jumbo_pending = 0;
+}
+
+static void
+netxen_nic_get_pauseparam(struct net_device *dev,
+ struct ethtool_pauseparam *pause)
+{
+ struct netxen_port *port = netdev_priv(dev);
+ struct netxen_adapter *adapter = port->adapter;
+ __le32 val;
+
+ if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
+ /* get flow control settings */
+ netxen_nic_read_w0(adapter,
+ NETXEN_NIU_GB_MAC_CONFIG_0(port->portnum),
+ (u32 *) & val);
+ pause->rx_pause = netxen_gb_get_rx_flowctl(val);
+ pause->tx_pause = netxen_gb_get_tx_flowctl(val);
+ /* get autoneg settings */
+ pause->autoneg = port->link_autoneg;
+ }
+}
+
+static int
+netxen_nic_set_pauseparam(struct net_device *dev,
+ struct ethtool_pauseparam *pause)
+{
+ struct netxen_port *port = netdev_priv(dev);
+ struct netxen_adapter *adapter = port->adapter;
+ __le32 val;
+ unsigned int autoneg;
+
+ /* read mode */
+ if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
+ /* set flow control */
+ netxen_nic_read_w0(adapter,
+ NETXEN_NIU_GB_MAC_CONFIG_0(port->portnum),
+ (u32 *) & val);
+ if (pause->tx_pause)
+ netxen_gb_tx_flowctl(val);
+ else
+ netxen_gb_unset_tx_flowctl(val);
+ if (pause->rx_pause)
+ netxen_gb_rx_flowctl(val);
+ else
+ netxen_gb_unset_rx_flowctl(val);
+
+ netxen_nic_write_w0(adapter,
+ NETXEN_NIU_GB_MAC_CONFIG_0(port->portnum),
+ *(u32 *) (&val));
+ /* set autoneg */
+ autoneg = pause->autoneg;
+ if (adapter->ops->phy_write
+ && adapter->ops->phy_write(adapter, port->portnum,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG,
+ (__le32) autoneg) != 0)
+ return -EIO;
+ else {
+ port->link_autoneg = pause->autoneg;
+ return 0;
+ }
+ } else
+ return -EOPNOTSUPP;
+}
+
+static int netxen_nic_reg_test(struct net_device *dev)
+{
+ struct netxen_port *port = netdev_priv(dev);
+ struct netxen_adapter *adapter = port->adapter;
+ u32 data_read, data_written, save;
+ __le32 mode;
+
+ /*
+ * first test the "Read Only" registers by writing which mode
+ */
+ netxen_nic_read_w0(adapter, NETXEN_NIU_MODE, &mode);
+ if (netxen_get_niu_enable_ge(mode)) { /* GB Mode */
+ netxen_nic_read_w0(adapter,
+ NETXEN_NIU_GB_MII_MGMT_STATUS(port->portnum),
+ &data_read);
+
+ save = data_read;
+ if (data_read)
+ data_written = data_read & NETXEN_NIC_INVALID_DATA;
+ else
+ data_written = NETXEN_NIC_INVALID_DATA;
+ netxen_nic_write_w0(adapter,
+ NETXEN_NIU_GB_MII_MGMT_STATUS(port->
+ portnum),
+ data_written);
+ netxen_nic_read_w0(adapter,
+ NETXEN_NIU_GB_MII_MGMT_STATUS(port->portnum),
+ &data_read);
+
+ if (data_written == data_read) {
+ netxen_nic_write_w0(adapter,
+ NETXEN_NIU_GB_MII_MGMT_STATUS(port->
+ portnum),
+ save);
+
+ return 0;
+ }
+
+ /* netxen_niu_gb_mii_mgmt_indicators is read only */
+ netxen_nic_read_w0(adapter,
+ NETXEN_NIU_GB_MII_MGMT_INDICATE(port->
+ portnum),
+ &data_read);
+
+ save = data_read;
+ if (data_read)
+ data_written = data_read & NETXEN_NIC_INVALID_DATA;
+ else
+ data_written = NETXEN_NIC_INVALID_DATA;
+ netxen_nic_write_w0(adapter,
+ NETXEN_NIU_GB_MII_MGMT_INDICATE(port->
+ portnum),
+ data_written);
+
+ netxen_nic_read_w0(adapter,
+ NETXEN_NIU_GB_MII_MGMT_INDICATE(port->
+ portnum),
+ &data_read);
+
+ if (data_written == data_read) {
+ netxen_nic_write_w0(adapter,
+ NETXEN_NIU_GB_MII_MGMT_INDICATE
+ (port->portnum), save);
+ return 0;
+ }
+
+ /* netxen_niu_gb_interface_status is read only */
+ netxen_nic_read_w0(adapter,
+ NETXEN_NIU_GB_INTERFACE_STATUS(port->
+ portnum),
+ &data_read);
+
+ save = data_read;
+ if (data_read)
+ data_written = data_read & NETXEN_NIC_INVALID_DATA;
+ else
+ data_written = NETXEN_NIC_INVALID_DATA;
+ netxen_nic_write_w0(adapter,
+ NETXEN_NIU_GB_INTERFACE_STATUS(port->
+ portnum),
+ data_written);
+
+ netxen_nic_read_w0(adapter,
+ NETXEN_NIU_GB_INTERFACE_STATUS(port->
+ portnum),
+ &data_read);
+
+ if (data_written == data_read) {
+ netxen_nic_write_w0(adapter,
+ NETXEN_NIU_GB_INTERFACE_STATUS
+ (port->portnum), save);
+
+ return 0;
+ }
+ } /* GB Mode */
+ return 1;
+}
+
+static int netxen_nic_diag_test_count(struct net_device *dev)
+{
+ return NETXEN_NIC_TEST_LEN;
+}
+
+static void
+netxen_nic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
+ u64 * data)
+{
+ if (eth_test->flags == ETH_TEST_FL_OFFLINE) { /* offline tests */
+ /* link test */
+ if (!(data[4] = (u64) netxen_nic_get_link(dev)))
+ eth_test->flags |= ETH_TEST_FL_FAILED;
+
+ if (netif_running(dev))
+ dev->stop(dev);
+
+ /* register tests */
+ if (!(data[0] = netxen_nic_reg_test(dev)))
+ eth_test->flags |= ETH_TEST_FL_FAILED;
+ /* other tests pass as of now */
+ data[1] = data[2] = data[3] = 1;
+ if (netif_running(dev))
+ dev->open(dev);
+ } else { /* online tests */
+ /* link test */
+ if (!(data[4] = (u64) netxen_nic_get_link(dev)))
+ eth_test->flags |= ETH_TEST_FL_FAILED;
+
+ /* other tests pass by default */
+ data[0] = data[1] = data[2] = data[3] = 1;
+ }
+}
+
+static void
+netxen_nic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
+{
+ int index;
+
+ switch (stringset) {
+ case ETH_SS_TEST:
+ memcpy(data, *netxen_nic_gstrings_test,
+ NETXEN_NIC_TEST_LEN * ETH_GSTRING_LEN);
+ break;
+ case ETH_SS_STATS:
+ for (index = 0; index < NETXEN_NIC_STATS_LEN; index++) {
+ memcpy(data + index * ETH_GSTRING_LEN,
+ netxen_nic_gstrings_stats[index].stat_string,
+ ETH_GSTRING_LEN);
+ }
+ break;
+ }
+}
+
+static int netxen_nic_get_stats_count(struct net_device *dev)
+{
+ return NETXEN_NIC_STATS_LEN;
+}
+
+static void
+netxen_nic_get_ethtool_stats(struct net_device *dev,
+ struct ethtool_stats *stats, u64 * data)
+{
+ struct netxen_port *port = netdev_priv(dev);
+ int index;
+
+ for (index = 0; index < NETXEN_NIC_STATS_LEN; index++) {
+ char *p =
+ (char *)port + netxen_nic_gstrings_stats[index].stat_offset;
+ data[index] =
+ (netxen_nic_gstrings_stats[index].sizeof_stat ==
+ sizeof(u64)) ? *(u64 *) p : *(u32 *) p;
+ }
+
+}
+
+struct ethtool_ops netxen_nic_ethtool_ops = {
+ .get_settings = netxen_nic_get_settings,
+ .set_settings = netxen_nic_set_settings,
+ .get_drvinfo = netxen_nic_get_drvinfo,
+ .get_regs_len = netxen_nic_get_regs_len,
+ .get_regs = netxen_nic_get_regs,
+ .get_wol = netxen_nic_get_wol,
+ .get_link = netxen_nic_get_link,
+ .get_eeprom_len = netxen_nic_get_eeprom_len,
+ .get_eeprom = netxen_nic_get_eeprom,
+ .get_ringparam = netxen_nic_get_ringparam,
+ .get_pauseparam = netxen_nic_get_pauseparam,
+ .set_pauseparam = netxen_nic_set_pauseparam,
+ .get_tx_csum = ethtool_op_get_tx_csum,
+ .set_tx_csum = ethtool_op_set_tx_csum,
+ .get_sg = ethtool_op_get_sg,
+ .set_sg = ethtool_op_set_sg,
+ .get_tso = ethtool_op_get_tso,
+ .set_tso = ethtool_op_set_tso,
+ .self_test_count = netxen_nic_diag_test_count,
+ .self_test = netxen_nic_diag_test,
+ .get_strings = netxen_nic_get_strings,
+ .get_stats_count = netxen_nic_get_stats_count,
+ .get_ethtool_stats = netxen_nic_get_ethtool_stats,
+ .get_perm_addr = ethtool_op_get_perm_addr,
+};
diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h
new file mode 100644
index 000000000000..72c6ec4ee2a0
--- /dev/null
+++ b/drivers/net/netxen/netxen_nic_hdr.h
@@ -0,0 +1,678 @@
+/*
+ * Copyright (C) 2003 - 2006 NetXen, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.
+ *
+ * Contact Information:
+ * info@netxen.com
+ * NetXen,
+ * 3965 Freedom Circle, Fourth floor,
+ * Santa Clara, CA 95054
+ */
+
+#ifndef __NETXEN_NIC_HDR_H_
+#define __NETXEN_NIC_HDR_H_
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/version.h>
+
+#include <asm/semaphore.h>
+#include <linux/spinlock.h>
+#include <asm/irq.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <asm/uaccess.h>
+#include <asm/string.h> /* for memset */
+
+/*
+ * The basic unit of access when reading/writing control registers.
+ */
+
+typedef __le32 netxen_crbword_t; /* single word in CRB space */
+
+enum {
+ NETXEN_HW_H0_CH_HUB_ADR = 0x05,
+ NETXEN_HW_H1_CH_HUB_ADR = 0x0E,
+ NETXEN_HW_H2_CH_HUB_ADR = 0x03,
+ NETXEN_HW_H3_CH_HUB_ADR = 0x01,
+ NETXEN_HW_H4_CH_HUB_ADR = 0x06,
+ NETXEN_HW_H5_CH_HUB_ADR = 0x07,
+ NETXEN_HW_H6_CH_HUB_ADR = 0x08
+};
+
+/* Hub 0 */
+enum {
+ NETXEN_HW_MN_CRB_AGT_ADR = 0x15,
+ NETXEN_HW_MS_CRB_AGT_ADR = 0x25
+};
+
+/* Hub 1 */
+enum {
+ NETXEN_HW_PS_CRB_AGT_ADR = 0x73,
+ NETXEN_HW_SS_CRB_AGT_ADR = 0x20,
+ NETXEN_HW_RPMX3_CRB_AGT_ADR = 0x0b,
+ NETXEN_HW_QMS_CRB_AGT_ADR = 0x00,
+ NETXEN_HW_SQGS0_CRB_AGT_ADR = 0x01,
+ NETXEN_HW_SQGS1_CRB_AGT_ADR = 0x02,
+ NETXEN_HW_SQGS2_CRB_AGT_ADR = 0x03,
+ NETXEN_HW_SQGS3_CRB_AGT_ADR = 0x04,
+ NETXEN_HW_C2C0_CRB_AGT_ADR = 0x58,
+ NETXEN_HW_C2C1_CRB_AGT_ADR = 0x59,
+ NETXEN_HW_C2C2_CRB_AGT_ADR = 0x5a,
+ NETXEN_HW_RPMX2_CRB_AGT_ADR = 0x0a,
+ NETXEN_HW_RPMX4_CRB_AGT_ADR = 0x0c,
+ NETXEN_HW_RPMX7_CRB_AGT_ADR = 0x0f,
+ NETXEN_HW_RPMX9_CRB_AGT_ADR = 0x12,
+ NETXEN_HW_SMB_CRB_AGT_ADR = 0x18
+};
+
+/* Hub 2 */
+enum {
+ NETXEN_HW_NIU_CRB_AGT_ADR = 0x31,
+ NETXEN_HW_I2C0_CRB_AGT_ADR = 0x19,
+ NETXEN_HW_I2C1_CRB_AGT_ADR = 0x29,
+
+ NETXEN_HW_SN_CRB_AGT_ADR = 0x10,
+ NETXEN_HW_I2Q_CRB_AGT_ADR = 0x20,
+ NETXEN_HW_LPC_CRB_AGT_ADR = 0x22,
+ NETXEN_HW_ROMUSB_CRB_AGT_ADR = 0x21,
+ NETXEN_HW_QM_CRB_AGT_ADR = 0x66,
+ NETXEN_HW_SQG0_CRB_AGT_ADR = 0x60,
+ NETXEN_HW_SQG1_CRB_AGT_ADR = 0x61,
+ NETXEN_HW_SQG2_CRB_AGT_ADR = 0x62,
+ NETXEN_HW_SQG3_CRB_AGT_ADR = 0x63,
+ NETXEN_HW_RPMX1_CRB_AGT_ADR = 0x09,
+ NETXEN_HW_RPMX5_CRB_AGT_ADR = 0x0d,
+ NETXEN_HW_RPMX6_CRB_AGT_ADR = 0x0e,
+ NETXEN_HW_RPMX8_CRB_AGT_ADR = 0x11
+};
+
+/* Hub 3 */
+enum {
+ NETXEN_HW_PH_CRB_AGT_ADR = 0x1A,
+ NETXEN_HW_SRE_CRB_AGT_ADR = 0x50,
+ NETXEN_HW_EG_CRB_AGT_ADR = 0x51,
+ NETXEN_HW_RPMX0_CRB_AGT_ADR = 0x08
+};
+
+/* Hub 4 */
+enum {
+ NETXEN_HW_PEGN0_CRB_AGT_ADR = 0x40,
+ NETXEN_HW_PEGN1_CRB_AGT_ADR,
+ NETXEN_HW_PEGN2_CRB_AGT_ADR,
+ NETXEN_HW_PEGN3_CRB_AGT_ADR,
+ NETXEN_HW_PEGNI_CRB_AGT_ADR,
+ NETXEN_HW_PEGND_CRB_AGT_ADR,
+ NETXEN_HW_PEGNC_CRB_AGT_ADR,
+ NETXEN_HW_PEGR0_CRB_AGT_ADR,
+ NETXEN_HW_PEGR1_CRB_AGT_ADR,
+ NETXEN_HW_PEGR2_CRB_AGT_ADR,
+ NETXEN_HW_PEGR3_CRB_AGT_ADR
+};
+
+/* Hub 5 */
+enum {
+ NETXEN_HW_PEGS0_CRB_AGT_ADR = 0x40,
+ NETXEN_HW_PEGS1_CRB_AGT_ADR,
+ NETXEN_HW_PEGS2_CRB_AGT_ADR,
+ NETXEN_HW_PEGS3_CRB_AGT_ADR,
+ NETXEN_HW_PEGSI_CRB_AGT_ADR,
+ NETXEN_HW_PEGSD_CRB_AGT_ADR,
+ NETXEN_HW_PEGSC_CRB_AGT_ADR
+};
+
+/* Hub 6 */
+enum {
+ NETXEN_HW_CAS0_CRB_AGT_ADR = 0x46,
+ NETXEN_HW_CAS1_CRB_AGT_ADR = 0x47,
+ NETXEN_HW_CAS2_CRB_AGT_ADR = 0x48,
+ NETXEN_HW_CAS3_CRB_AGT_ADR = 0x49,
+ NETXEN_HW_NCM_CRB_AGT_ADR = 0x16,
+ NETXEN_HW_TMR_CRB_AGT_ADR = 0x17,
+ NETXEN_HW_XDMA_CRB_AGT_ADR = 0x05,
+ NETXEN_HW_OCM0_CRB_AGT_ADR = 0x06,
+ NETXEN_HW_OCM1_CRB_AGT_ADR = 0x07
+};
+
+/* Floaters - non existent modules */
+#define NETXEN_HW_EFC_RPMX0_CRB_AGT_ADR 0x67
+
+/* This field defines PCI/X adr [25:20] of agents on the CRB */
+enum {
+ NETXEN_HW_PX_MAP_CRB_PH = 0,
+ NETXEN_HW_PX_MAP_CRB_PS,
+ NETXEN_HW_PX_MAP_CRB_MN,
+ NETXEN_HW_PX_MAP_CRB_MS,
+ NETXEN_HW_PX_MAP_CRB_PGR1,
+ NETXEN_HW_PX_MAP_CRB_SRE,
+ NETXEN_HW_PX_MAP_CRB_NIU,
+ NETXEN_HW_PX_MAP_CRB_QMN,
+ NETXEN_HW_PX_MAP_CRB_SQN0,
+ NETXEN_HW_PX_MAP_CRB_SQN1,
+ NETXEN_HW_PX_MAP_CRB_SQN2,
+ NETXEN_HW_PX_MAP_CRB_SQN3,
+ NETXEN_HW_PX_MAP_CRB_QMS,
+ NETXEN_HW_PX_MAP_CRB_SQS0,
+ NETXEN_HW_PX_MAP_CRB_SQS1,
+ NETXEN_HW_PX_MAP_CRB_SQS2,
+ NETXEN_HW_PX_MAP_CRB_SQS3,
+ NETXEN_HW_PX_MAP_CRB_PGN0,
+ NETXEN_HW_PX_MAP_CRB_PGN1,
+ NETXEN_HW_PX_MAP_CRB_PGN2,
+ NETXEN_HW_PX_MAP_CRB_PGN3,
+ NETXEN_HW_PX_MAP_CRB_PGND,
+ NETXEN_HW_PX_MAP_CRB_PGNI,
+ NETXEN_HW_PX_MAP_CRB_PGS0,
+ NETXEN_HW_PX_MAP_CRB_PGS1,
+ NETXEN_HW_PX_MAP_CRB_PGS2,
+ NETXEN_HW_PX_MAP_CRB_PGS3,
+ NETXEN_HW_PX_MAP_CRB_PGSD,
+ NETXEN_HW_PX_MAP_CRB_PGSI,
+ NETXEN_HW_PX_MAP_CRB_SN,
+ NETXEN_HW_PX_MAP_CRB_PGR2,
+ NETXEN_HW_PX_MAP_CRB_EG,
+ NETXEN_HW_PX_MAP_CRB_PH2,
+ NETXEN_HW_PX_MAP_CRB_PS2,
+ NETXEN_HW_PX_MAP_CRB_CAM,
+ NETXEN_HW_PX_MAP_CRB_CAS0,
+ NETXEN_HW_PX_MAP_CRB_CAS1,
+ NETXEN_HW_PX_MAP_CRB_CAS2,
+ NETXEN_HW_PX_MAP_CRB_C2C0,
+ NETXEN_HW_PX_MAP_CRB_C2C1,
+ NETXEN_HW_PX_MAP_CRB_TIMR,
+ NETXEN_HW_PX_MAP_CRB_PGR3,
+ NETXEN_HW_PX_MAP_CRB_RPMX1,
+ NETXEN_HW_PX_MAP_CRB_RPMX2,
+ NETXEN_HW_PX_MAP_CRB_RPMX3,
+ NETXEN_HW_PX_MAP_CRB_RPMX4,
+ NETXEN_HW_PX_MAP_CRB_RPMX5,
+ NETXEN_HW_PX_MAP_CRB_RPMX6,
+ NETXEN_HW_PX_MAP_CRB_RPMX7,
+ NETXEN_HW_PX_MAP_CRB_XDMA,
+ NETXEN_HW_PX_MAP_CRB_I2Q,
+ NETXEN_HW_PX_MAP_CRB_ROMUSB,
+ NETXEN_HW_PX_MAP_CRB_CAS3,
+ NETXEN_HW_PX_MAP_CRB_RPMX0,
+ NETXEN_HW_PX_MAP_CRB_RPMX8,
+ NETXEN_HW_PX_MAP_CRB_RPMX9,
+ NETXEN_HW_PX_MAP_CRB_OCM0,
+ NETXEN_HW_PX_MAP_CRB_OCM1,
+ NETXEN_HW_PX_MAP_CRB_SMB,
+ NETXEN_HW_PX_MAP_CRB_I2C0,
+ NETXEN_HW_PX_MAP_CRB_I2C1,
+ NETXEN_HW_PX_MAP_CRB_LPC,
+ NETXEN_HW_PX_MAP_CRB_PGNC,
+ NETXEN_HW_PX_MAP_CRB_PGR0
+};
+
+/* This field defines CRB adr [31:20] of the agents */
+
+#define NETXEN_HW_CRB_HUB_AGT_ADR_MN \
+ ((NETXEN_HW_H0_CH_HUB_ADR << 7) | NETXEN_HW_MN_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PH \
+ ((NETXEN_HW_H0_CH_HUB_ADR << 7) | NETXEN_HW_PH_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_MS \
+ ((NETXEN_HW_H0_CH_HUB_ADR << 7) | NETXEN_HW_MS_CRB_AGT_ADR)
+
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PS \
+ ((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_PS_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_SS \
+ ((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_SS_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_RPMX3 \
+ ((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_RPMX3_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_QMS \
+ ((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_QMS_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_SQS0 \
+ ((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_SQGS0_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_SQS1 \
+ ((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_SQGS1_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_SQS2 \
+ ((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_SQGS2_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_SQS3 \
+ ((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_SQGS3_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_C2C0 \
+ ((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_C2C0_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_C2C1 \
+ ((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_C2C1_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_RPMX2 \
+ ((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_RPMX2_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_RPMX4 \
+ ((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_RPMX4_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_RPMX7 \
+ ((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_RPMX7_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_RPMX9 \
+ ((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_RPMX9_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_SMB \
+ ((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_SMB_CRB_AGT_ADR)
+
+#define NETXEN_HW_CRB_HUB_AGT_ADR_NIU \
+ ((NETXEN_HW_H2_CH_HUB_ADR << 7) | NETXEN_HW_NIU_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_I2C0 \
+ ((NETXEN_HW_H2_CH_HUB_ADR << 7) | NETXEN_HW_I2C0_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_I2C1 \
+ ((NETXEN_HW_H2_CH_HUB_ADR << 7) | NETXEN_HW_I2C1_CRB_AGT_ADR)
+
+#define NETXEN_HW_CRB_HUB_AGT_ADR_SRE \
+ ((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_SRE_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_EG \
+ ((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_EG_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_RPMX0 \
+ ((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_RPMX0_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_QMN \
+ ((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_QM_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_SQN0 \
+ ((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_SQG0_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_SQN1 \
+ ((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_SQG1_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_SQN2 \
+ ((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_SQG2_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_SQN3 \
+ ((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_SQG3_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_RPMX1 \
+ ((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_RPMX1_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_RPMX5 \
+ ((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_RPMX5_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_RPMX6 \
+ ((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_RPMX6_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_RPMX8 \
+ ((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_RPMX8_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_CAS0 \
+ ((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_CAS0_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_CAS1 \
+ ((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_CAS1_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_CAS2 \
+ ((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_CAS2_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_CAS3 \
+ ((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_CAS3_CRB_AGT_ADR)
+
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGNI \
+ ((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGNI_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGND \
+ ((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGND_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGN0 \
+ ((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGN0_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGN1 \
+ ((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGN1_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGN2 \
+ ((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGN2_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGN3 \
+ ((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGN3_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGNC \
+ ((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGNC_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGR0 \
+ ((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGR0_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGR1 \
+ ((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGR1_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGR2 \
+ ((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGR2_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGR3 \
+ ((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGR3_CRB_AGT_ADR)
+
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGSI \
+ ((NETXEN_HW_H5_CH_HUB_ADR << 7) | NETXEN_HW_PEGSI_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGSD \
+ ((NETXEN_HW_H5_CH_HUB_ADR << 7) | NETXEN_HW_PEGSD_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGS0 \
+ ((NETXEN_HW_H5_CH_HUB_ADR << 7) | NETXEN_HW_PEGS0_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGS1 \
+ ((NETXEN_HW_H5_CH_HUB_ADR << 7) | NETXEN_HW_PEGS1_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGS2 \
+ ((NETXEN_HW_H5_CH_HUB_ADR << 7) | NETXEN_HW_PEGS2_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGS3 \
+ ((NETXEN_HW_H5_CH_HUB_ADR << 7) | NETXEN_HW_PEGS3_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGSC \
+ ((NETXEN_HW_H5_CH_HUB_ADR << 7) | NETXEN_HW_PEGSC_CRB_AGT_ADR)
+
+#define NETXEN_HW_CRB_HUB_AGT_ADR_CAM \
+ ((NETXEN_HW_H6_CH_HUB_ADR << 7) | NETXEN_HW_NCM_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_TIMR \
+ ((NETXEN_HW_H6_CH_HUB_ADR << 7) | NETXEN_HW_TMR_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_XDMA \
+ ((NETXEN_HW_H6_CH_HUB_ADR << 7) | NETXEN_HW_XDMA_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_SN \
+ ((NETXEN_HW_H6_CH_HUB_ADR << 7) | NETXEN_HW_SN_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_I2Q \
+ ((NETXEN_HW_H6_CH_HUB_ADR << 7) | NETXEN_HW_I2Q_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_ROMUSB \
+ ((NETXEN_HW_H6_CH_HUB_ADR << 7) | NETXEN_HW_ROMUSB_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_OCM0 \
+ ((NETXEN_HW_H6_CH_HUB_ADR << 7) | NETXEN_HW_OCM0_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_OCM1 \
+ ((NETXEN_HW_H6_CH_HUB_ADR << 7) | NETXEN_HW_OCM1_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_LPC \
+ ((NETXEN_HW_H6_CH_HUB_ADR << 7) | NETXEN_HW_LPC_CRB_AGT_ADR)
+
+/*
+ * MAX_RCV_CTX : The number of receive contexts that are available on
+ * the phantom.
+ */
+#define MAX_RCV_CTX 1
+
+#define NETXEN_SRE_INT_STATUS (NETXEN_CRB_SRE + 0x00034)
+#define NETXEN_SRE_PBI_ACTIVE_STATUS (NETXEN_CRB_SRE + 0x01014)
+#define NETXEN_SRE_L1RE_CTL (NETXEN_CRB_SRE + 0x03000)
+#define NETXEN_SRE_L2RE_CTL (NETXEN_CRB_SRE + 0x05000)
+#define NETXEN_SRE_BUF_CTL (NETXEN_CRB_SRE + 0x01000)
+
+#define NETXEN_DMA_BASE(U) (NETXEN_CRB_PCIX_MD + 0x20000 + ((U)<<16))
+#define NETXEN_DMA_COMMAND(U) (NETXEN_DMA_BASE(U) + 0x00008)
+
+#define NETXEN_I2Q_CLR_PCI_HI (NETXEN_CRB_I2Q + 0x00034)
+
+#define PEG_NETWORK_BASE(N) (NETXEN_CRB_PEG_NET_0 + (((N)&3) << 20))
+#define CRB_REG_EX_PC 0x3c
+
+#define ROMUSB_GLB (NETXEN_CRB_ROMUSB + 0x00000)
+#define ROMUSB_ROM (NETXEN_CRB_ROMUSB + 0x10000)
+
+#define NETXEN_ROMUSB_GLB_STATUS (ROMUSB_GLB + 0x0004)
+#define NETXEN_ROMUSB_GLB_SW_RESET (ROMUSB_GLB + 0x0008)
+#define NETXEN_ROMUSB_GLB_PAD_GPIO_I (ROMUSB_GLB + 0x000c)
+#define NETXEN_ROMUSB_GLB_CAS_RST (ROMUSB_GLB + 0x0038)
+#define NETXEN_ROMUSB_GLB_TEST_MUX_SEL (ROMUSB_GLB + 0x0044)
+#define NETXEN_ROMUSB_GLB_PEGTUNE_DONE (ROMUSB_GLB + 0x005c)
+#define NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL (ROMUSB_GLB + 0x00A8)
+
+#define NETXEN_ROMUSB_GPIO(n) (ROMUSB_GLB + 0x60 + (4 * (n)))
+
+#define NETXEN_ROMUSB_ROM_INSTR_OPCODE (ROMUSB_ROM + 0x0004)
+#define NETXEN_ROMUSB_ROM_ADDRESS (ROMUSB_ROM + 0x0008)
+#define NETXEN_ROMUSB_ROM_WDATA (ROMUSB_ROM + 0x000c)
+#define NETXEN_ROMUSB_ROM_ABYTE_CNT (ROMUSB_ROM + 0x0010)
+#define NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT (ROMUSB_ROM + 0x0014)
+#define NETXEN_ROMUSB_ROM_RDATA (ROMUSB_ROM + 0x0018)
+
+/* Lock IDs for ROM lock */
+#define ROM_LOCK_DRIVER 0x0d417340
+
+/******************************************************************************
+*
+* Definitions specific to M25P flash
+*
+*******************************************************************************
+* Instructions
+*/
+#define M25P_INSTR_WREN 0x06
+#define M25P_INSTR_WRDI 0x04
+#define M25P_INSTR_RDID 0x9f
+#define M25P_INSTR_RDSR 0x05
+#define M25P_INSTR_WRSR 0x01
+#define M25P_INSTR_READ 0x03
+#define M25P_INSTR_FAST_READ 0x0b
+#define M25P_INSTR_PP 0x02
+#define M25P_INSTR_SE 0xd8
+#define M25P_INSTR_BE 0xc7
+#define M25P_INSTR_DP 0xb9
+#define M25P_INSTR_RES 0xab
+
+/* all are 1MB windows */
+
+#define NETXEN_PCI_CRB_WINDOWSIZE 0x00100000
+#define NETXEN_PCI_CRB_WINDOW(A) \
+ (NETXEN_PCI_CRBSPACE + (A)*NETXEN_PCI_CRB_WINDOWSIZE)
+
+#define NETXEN_CRB_NIU NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_NIU)
+#define NETXEN_CRB_SRE NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_SRE)
+#define NETXEN_CRB_ROMUSB \
+ NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_ROMUSB)
+#define NETXEN_CRB_I2Q NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_I2Q)
+#define NETXEN_CRB_MAX NETXEN_PCI_CRB_WINDOW(64)
+
+#define NETXEN_CRB_PCIX_HOST NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PH)
+#define NETXEN_CRB_PCIX_HOST2 NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PH2)
+#define NETXEN_CRB_PEG_NET_0 NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PGN0)
+#define NETXEN_CRB_PEG_NET_1 NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PGN1)
+#define NETXEN_CRB_PEG_NET_2 NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PGN2)
+#define NETXEN_CRB_PEG_NET_3 NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PGN3)
+#define NETXEN_CRB_PEG_NET_D NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PGND)
+#define NETXEN_CRB_PEG_NET_I NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PGNI)
+#define NETXEN_CRB_DDR_NET NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_MN)
+
+#define NETXEN_CRB_PCIX_MD NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PS)
+#define NETXEN_CRB_PCIE NETXEN_CRB_PCIX_MD
+
+#define ISR_INT_VECTOR (NETXEN_PCIX_PS_REG(PCIX_INT_VECTOR))
+#define ISR_INT_MASK (NETXEN_PCIX_PS_REG(PCIX_INT_MASK))
+#define ISR_INT_MASK_SLOW (NETXEN_PCIX_PS_REG(PCIX_INT_MASK))
+#define ISR_INT_TARGET_STATUS (NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS))
+#define ISR_INT_TARGET_MASK (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK))
+
+#define NETXEN_PCI_MAPSIZE 128
+#define NETXEN_PCI_DDR_NET (0x00000000UL)
+#define NETXEN_PCI_QDR_NET (0x04000000UL)
+#define NETXEN_PCI_DIRECT_CRB (0x04400000UL)
+#define NETXEN_PCI_CAMQM_MAX (0x04ffffffUL)
+#define NETXEN_PCI_OCM0 (0x05000000UL)
+#define NETXEN_PCI_OCM0_MAX (0x050fffffUL)
+#define NETXEN_PCI_OCM1 (0x05100000UL)
+#define NETXEN_PCI_OCM1_MAX (0x051fffffUL)
+#define NETXEN_PCI_CRBSPACE (0x06000000UL)
+
+#define NETXEN_CRB_CAM NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_CAM)
+
+#define NETXEN_ADDR_DDR_NET (0x0000000000000000ULL)
+#define NETXEN_ADDR_DDR_NET_MAX (0x000000000fffffffULL)
+#define NETXEN_ADDR_OCM0 (0x0000000200000000ULL)
+#define NETXEN_ADDR_OCM0_MAX (0x00000002000fffffULL)
+#define NETXEN_ADDR_OCM1 (0x0000000200400000ULL)
+#define NETXEN_ADDR_OCM1_MAX (0x00000002004fffffULL)
+#define NETXEN_ADDR_QDR_NET (0x0000000300000000ULL)
+#define NETXEN_ADDR_QDR_NET_MAX (0x00000003003fffffULL)
+
+ /* 200ms delay in each loop */
+#define NETXEN_NIU_PHY_WAITLEN 200000
+ /* 10 seconds before we give up */
+#define NETXEN_NIU_PHY_WAITMAX 50
+#define NETXEN_NIU_MAX_GBE_PORTS 4
+
+#define NETXEN_NIU_MODE (NETXEN_CRB_NIU + 0x00000)
+
+#define NETXEN_NIU_XG_SINGLE_TERM (NETXEN_CRB_NIU + 0x00004)
+#define NETXEN_NIU_XG_DRIVE_HI (NETXEN_CRB_NIU + 0x00008)
+#define NETXEN_NIU_XG_DRIVE_LO (NETXEN_CRB_NIU + 0x0000c)
+#define NETXEN_NIU_XG_DTX (NETXEN_CRB_NIU + 0x00010)
+#define NETXEN_NIU_XG_DEQ (NETXEN_CRB_NIU + 0x00014)
+#define NETXEN_NIU_XG_WORD_ALIGN (NETXEN_CRB_NIU + 0x00018)
+#define NETXEN_NIU_XG_RESET (NETXEN_CRB_NIU + 0x0001c)
+#define NETXEN_NIU_XG_POWER_DOWN (NETXEN_CRB_NIU + 0x00020)
+#define NETXEN_NIU_XG_RESET_PLL (NETXEN_CRB_NIU + 0x00024)
+#define NETXEN_NIU_XG_SERDES_LOOPBACK (NETXEN_CRB_NIU + 0x00028)
+#define NETXEN_NIU_XG_DO_BYTE_ALIGN (NETXEN_CRB_NIU + 0x0002c)
+#define NETXEN_NIU_XG_TX_ENABLE (NETXEN_CRB_NIU + 0x00030)
+#define NETXEN_NIU_XG_RX_ENABLE (NETXEN_CRB_NIU + 0x00034)
+#define NETXEN_NIU_XG_STATUS (NETXEN_CRB_NIU + 0x00038)
+#define NETXEN_NIU_XG_PAUSE_THRESHOLD (NETXEN_CRB_NIU + 0x0003c)
+#define NETXEN_NIU_INT_MASK (NETXEN_CRB_NIU + 0x00040)
+#define NETXEN_NIU_ACTIVE_INT (NETXEN_CRB_NIU + 0x00044)
+#define NETXEN_NIU_MASKABLE_INT (NETXEN_CRB_NIU + 0x00048)
+
+#define NETXEN_NIU_STRAP_VALUE_SAVE_HIGHER (NETXEN_CRB_NIU + 0x0004c)
+
+#define NETXEN_NIU_GB_SERDES_RESET (NETXEN_CRB_NIU + 0x00050)
+#define NETXEN_NIU_GB0_GMII_MODE (NETXEN_CRB_NIU + 0x00054)
+#define NETXEN_NIU_GB0_MII_MODE (NETXEN_CRB_NIU + 0x00058)
+#define NETXEN_NIU_GB1_GMII_MODE (NETXEN_CRB_NIU + 0x0005c)
+#define NETXEN_NIU_GB1_MII_MODE (NETXEN_CRB_NIU + 0x00060)
+#define NETXEN_NIU_GB2_GMII_MODE (NETXEN_CRB_NIU + 0x00064)
+#define NETXEN_NIU_GB2_MII_MODE (NETXEN_CRB_NIU + 0x00068)
+#define NETXEN_NIU_GB3_GMII_MODE (NETXEN_CRB_NIU + 0x0006c)
+#define NETXEN_NIU_GB3_MII_MODE (NETXEN_CRB_NIU + 0x00070)
+#define NETXEN_NIU_REMOTE_LOOPBACK (NETXEN_CRB_NIU + 0x00074)
+#define NETXEN_NIU_GB0_HALF_DUPLEX (NETXEN_CRB_NIU + 0x00078)
+#define NETXEN_NIU_GB1_HALF_DUPLEX (NETXEN_CRB_NIU + 0x0007c)
+#define NETXEN_NIU_RESET_SYS_FIFOS (NETXEN_CRB_NIU + 0x00088)
+#define NETXEN_NIU_GB_CRC_DROP (NETXEN_CRB_NIU + 0x0008c)
+#define NETXEN_NIU_GB_DROP_WRONGADDR (NETXEN_CRB_NIU + 0x00090)
+#define NETXEN_NIU_TEST_MUX_CTL (NETXEN_CRB_NIU + 0x00094)
+#define NETXEN_NIU_XG_PAUSE_CTL (NETXEN_CRB_NIU + 0x00098)
+#define NETXEN_NIU_XG_PAUSE_LEVEL (NETXEN_CRB_NIU + 0x000dc)
+#define NETXEN_NIU_XG_SEL (NETXEN_CRB_NIU + 0x00128)
+
+#define NETXEN_NIU_FULL_LEVEL_XG (NETXEN_CRB_NIU + 0x00450)
+
+#define NETXEN_NIU_XG1_RESET (NETXEN_CRB_NIU + 0x0011c)
+#define NETXEN_NIU_XG1_POWER_DOWN (NETXEN_CRB_NIU + 0x00120)
+#define NETXEN_NIU_XG1_RESET_PLL (NETXEN_CRB_NIU + 0x00124)
+
+#define NETXEN_MAC_ADDR_CNTL_REG (NETXEN_CRB_NIU + 0x1000)
+
+#define NETXEN_MULTICAST_ADDR_HI_0 (NETXEN_CRB_NIU + 0x1010)
+#define NETXEN_MULTICAST_ADDR_HI_1 (NETXEN_CRB_NIU + 0x1014)
+#define NETXEN_MULTICAST_ADDR_HI_2 (NETXEN_CRB_NIU + 0x1018)
+#define NETXEN_MULTICAST_ADDR_HI_3 (NETXEN_CRB_NIU + 0x101c)
+
+#define NETXEN_NIU_GB_MAC_CONFIG_0(I) \
+ (NETXEN_CRB_NIU + 0x30000 + (I)*0x10000)
+#define NETXEN_NIU_GB_MAC_CONFIG_1(I) \
+ (NETXEN_CRB_NIU + 0x30004 + (I)*0x10000)
+#define NETXEN_NIU_GB_MAC_IPG_IFG(I) \
+ (NETXEN_CRB_NIU + 0x30008 + (I)*0x10000)
+#define NETXEN_NIU_GB_HALF_DUPLEX_CTRL(I) \
+ (NETXEN_CRB_NIU + 0x3000c + (I)*0x10000)
+#define NETXEN_NIU_GB_MAX_FRAME_SIZE(I) \
+ (NETXEN_CRB_NIU + 0x30010 + (I)*0x10000)
+#define NETXEN_NIU_GB_TEST_REG(I) \
+ (NETXEN_CRB_NIU + 0x3001c + (I)*0x10000)
+#define NETXEN_NIU_GB_MII_MGMT_CONFIG(I) \
+ (NETXEN_CRB_NIU + 0x30020 + (I)*0x10000)
+#define NETXEN_NIU_GB_MII_MGMT_COMMAND(I) \
+ (NETXEN_CRB_NIU + 0x30024 + (I)*0x10000)
+#define NETXEN_NIU_GB_MII_MGMT_ADDR(I) \
+ (NETXEN_CRB_NIU + 0x30028 + (I)*0x10000)
+#define NETXEN_NIU_GB_MII_MGMT_CTRL(I) \
+ (NETXEN_CRB_NIU + 0x3002c + (I)*0x10000)
+#define NETXEN_NIU_GB_MII_MGMT_STATUS(I) \
+ (NETXEN_CRB_NIU + 0x30030 + (I)*0x10000)
+#define NETXEN_NIU_GB_MII_MGMT_INDICATE(I) \
+ (NETXEN_CRB_NIU + 0x30034 + (I)*0x10000)
+#define NETXEN_NIU_GB_INTERFACE_CTRL(I) \
+ (NETXEN_CRB_NIU + 0x30038 + (I)*0x10000)
+#define NETXEN_NIU_GB_INTERFACE_STATUS(I) \
+ (NETXEN_CRB_NIU + 0x3003c + (I)*0x10000)
+#define NETXEN_NIU_GB_STATION_ADDR_0(I) \
+ (NETXEN_CRB_NIU + 0x30040 + (I)*0x10000)
+#define NETXEN_NIU_GB_STATION_ADDR_1(I) \
+ (NETXEN_CRB_NIU + 0x30044 + (I)*0x10000)
+
+#define NETXEN_NIU_XGE_CONFIG_0 (NETXEN_CRB_NIU + 0x70000)
+#define NETXEN_NIU_XGE_CONFIG_1 (NETXEN_CRB_NIU + 0x70004)
+#define NETXEN_NIU_XGE_IPG (NETXEN_CRB_NIU + 0x70008)
+#define NETXEN_NIU_XGE_STATION_ADDR_0_HI (NETXEN_CRB_NIU + 0x7000c)
+#define NETXEN_NIU_XGE_STATION_ADDR_0_1 (NETXEN_CRB_NIU + 0x70010)
+#define NETXEN_NIU_XGE_STATION_ADDR_1_LO (NETXEN_CRB_NIU + 0x70014)
+#define NETXEN_NIU_XGE_STATUS (NETXEN_CRB_NIU + 0x70018)
+#define NETXEN_NIU_XGE_MAX_FRAME_SIZE (NETXEN_CRB_NIU + 0x7001c)
+#define NETXEN_NIU_XGE_PAUSE_FRAME_VALUE (NETXEN_CRB_NIU + 0x70020)
+#define NETXEN_NIU_XGE_TX_BYTE_CNT (NETXEN_CRB_NIU + 0x70024)
+#define NETXEN_NIU_XGE_TX_FRAME_CNT (NETXEN_CRB_NIU + 0x70028)
+#define NETXEN_NIU_XGE_RX_BYTE_CNT (NETXEN_CRB_NIU + 0x7002c)
+#define NETXEN_NIU_XGE_RX_FRAME_CNT (NETXEN_CRB_NIU + 0x70030)
+#define NETXEN_NIU_XGE_AGGR_ERROR_CNT (NETXEN_CRB_NIU + 0x70034)
+#define NETXEN_NIU_XGE_MULTICAST_FRAME_CNT (NETXEN_CRB_NIU + 0x70038)
+#define NETXEN_NIU_XGE_UNICAST_FRAME_CNT (NETXEN_CRB_NIU + 0x7003c)
+#define NETXEN_NIU_XGE_CRC_ERROR_CNT (NETXEN_CRB_NIU + 0x70040)
+#define NETXEN_NIU_XGE_OVERSIZE_FRAME_ERR (NETXEN_CRB_NIU + 0x70044)
+#define NETXEN_NIU_XGE_UNDERSIZE_FRAME_ERR (NETXEN_CRB_NIU + 0x70048)
+#define NETXEN_NIU_XGE_LOCAL_ERROR_CNT (NETXEN_CRB_NIU + 0x7004c)
+#define NETXEN_NIU_XGE_REMOTE_ERROR_CNT (NETXEN_CRB_NIU + 0x70050)
+#define NETXEN_NIU_XGE_CONTROL_CHAR_CNT (NETXEN_CRB_NIU + 0x70054)
+#define NETXEN_NIU_XGE_PAUSE_FRAME_CNT (NETXEN_CRB_NIU + 0x70058)
+#define NETXEN_NIU_XG1_CONFIG_0 (NETXEN_CRB_NIU + 0x80000)
+#define NETXEN_NIU_XG1_CONFIG_1 (NETXEN_CRB_NIU + 0x80004)
+#define NETXEN_NIU_XG1_IPG (NETXEN_CRB_NIU + 0x80008)
+#define NETXEN_NIU_XG1_STATION_ADDR_0_HI (NETXEN_CRB_NIU + 0x8000c)
+#define NETXEN_NIU_XG1_STATION_ADDR_0_1 (NETXEN_CRB_NIU + 0x80010)
+#define NETXEN_NIU_XG1_STATION_ADDR_1_LO (NETXEN_CRB_NIU + 0x80014)
+#define NETXEN_NIU_XG1_STATUS (NETXEN_CRB_NIU + 0x80018)
+#define NETXEN_NIU_XG1_MAX_FRAME_SIZE (NETXEN_CRB_NIU + 0x8001c)
+#define NETXEN_NIU_XG1_PAUSE_FRAME_VALUE (NETXEN_CRB_NIU + 0x80020)
+#define NETXEN_NIU_XG1_TX_BYTE_CNT (NETXEN_CRB_NIU + 0x80024)
+#define NETXEN_NIU_XG1_TX_FRAME_CNT (NETXEN_CRB_NIU + 0x80028)
+#define NETXEN_NIU_XG1_RX_BYTE_CNT (NETXEN_CRB_NIU + 0x8002c)
+#define NETXEN_NIU_XG1_RX_FRAME_CNT (NETXEN_CRB_NIU + 0x80030)
+#define NETXEN_NIU_XG1_AGGR_ERROR_CNT (NETXEN_CRB_NIU + 0x80034)
+#define NETXEN_NIU_XG1_MULTICAST_FRAME_CNT (NETXEN_CRB_NIU + 0x80038)
+#define NETXEN_NIU_XG1_UNICAST_FRAME_CNT (NETXEN_CRB_NIU + 0x8003c)
+#define NETXEN_NIU_XG1_CRC_ERROR_CNT (NETXEN_CRB_NIU + 0x80040)
+#define NETXEN_NIU_XG1_OVERSIZE_FRAME_ERR (NETXEN_CRB_NIU + 0x80044)
+#define NETXEN_NIU_XG1_UNDERSIZE_FRAME_ERR (NETXEN_CRB_NIU + 0x80048)
+#define NETXEN_NIU_XG1_LOCAL_ERROR_CNT (NETXEN_CRB_NIU + 0x8004c)
+#define NETXEN_NIU_XG1_REMOTE_ERROR_CNT (NETXEN_CRB_NIU + 0x80050)
+#define NETXEN_NIU_XG1_CONTROL_CHAR_CNT (NETXEN_CRB_NIU + 0x80054)
+#define NETXEN_NIU_XG1_PAUSE_FRAME_CNT (NETXEN_CRB_NIU + 0x80058)
+
+/* XG Link status */
+#define XG_LINK_UP 0x10
+#define XG_LINK_DOWN 0x20
+
+#define NETXEN_CAM_RAM_BASE (NETXEN_CRB_CAM + 0x02000)
+#define NETXEN_CAM_RAM(reg) (NETXEN_CAM_RAM_BASE + (reg))
+#define NETXEN_FW_VERSION_MAJOR (NETXEN_CAM_RAM(0x150))
+#define NETXEN_FW_VERSION_MINOR (NETXEN_CAM_RAM(0x154))
+#define NETXEN_FW_VERSION_SUB (NETXEN_CAM_RAM(0x158))
+#define NETXEN_ROM_LOCK_ID (NETXEN_CAM_RAM(0x100))
+
+#define NETXEN_PHY_LOCK_ID (NETXEN_CAM_RAM(0x120))
+
+/* Lock IDs for PHY lock */
+#define PHY_LOCK_DRIVER 0x44524956
+
+/* Used for PS PCI Memory access */
+#define PCIX_PS_OP_ADDR_LO (0x10000)
+/* via CRB (PS side only) */
+#define PCIX_PS_OP_ADDR_HI (0x10004)
+
+#define PCIX_INT_VECTOR (0x10100)
+#define PCIX_INT_MASK (0x10104)
+
+#define PCIX_MN_WINDOW (0x10200)
+#define PCIX_MS_WINDOW (0x10204)
+#define PCIX_SN_WINDOW (0x10208)
+#define PCIX_CRB_WINDOW (0x10210)
+
+#define PCIX_TARGET_STATUS (0x10118)
+#define PCIX_TARGET_MASK (0x10128)
+
+#define PCIX_MSI_F0 (0x13000)
+
+#define PCIX_PS_MEM_SPACE (0x90000)
+
+#define NETXEN_PCIX_PH_REG(reg) (NETXEN_CRB_PCIE + (reg))
+#define NETXEN_PCIX_PS_REG(reg) (NETXEN_CRB_PCIX_MD + (reg))
+
+#define NETXEN_PCIE_REG(reg) (NETXEN_CRB_PCIE + (reg))
+
+#define PCIE_MAX_DMA_XFER_SIZE (0x1404c)
+
+#define PCIE_DCR 0x00d8
+
+#define PCIE_SEM2_LOCK (0x1c010) /* Flash lock */
+#define PCIE_SEM2_UNLOCK (0x1c014) /* Flash unlock */
+#define PCIE_SEM3_LOCK (0x1c018) /* Phy lock */
+#define PCIE_SEM3_UNLOCK (0x1c01c) /* Phy unlock */
+
+#define PCIE_TGT_SPLIT_CHICKEN (0x12080)
+
+#define PCIE_MAX_MASTER_SPLIT (0x14048)
+
+#endif /* __NETXEN_NIC_HDR_H_ */
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
new file mode 100644
index 000000000000..105c24f0ad4c
--- /dev/null
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -0,0 +1,1010 @@
+/*
+ * Copyright (C) 2003 - 2006 NetXen, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.
+ *
+ * Contact Information:
+ * info@netxen.com
+ * NetXen,
+ * 3965 Freedom Circle, Fourth floor,
+ * Santa Clara, CA 95054
+ *
+ *
+ * Source file for NIC routines to access the Phantom hardware
+ *
+ */
+
+#include "netxen_nic.h"
+#include "netxen_nic_hw.h"
+#include "netxen_nic_phan_reg.h"
+
+/* PCI Windowing for DDR regions. */
+
+#define ADDR_IN_RANGE(addr, low, high) \
+ (((addr) <= (high)) && ((addr) >= (low)))
+
+#define NETXEN_FLASH_BASE (BOOTLD_START)
+#define NETXEN_PHANTOM_MEM_BASE (NETXEN_FLASH_BASE)
+#define NETXEN_MAX_MTU 8000
+#define NETXEN_MIN_MTU 64
+#define NETXEN_ETH_FCS_SIZE 4
+#define NETXEN_ENET_HEADER_SIZE 14
+#define NETXEN_WINDOW_ONE 0x2000000 /*CRB Window: bit 25 of CRB address */
+#define NETXEN_FIRMWARE_LEN ((16 * 1024) / 4)
+#define NETXEN_NIU_HDRSIZE (0x1 << 6)
+#define NETXEN_NIU_TLRSIZE (0x1 << 5)
+
+#define lower32(x) ((u32)((x) & 0xffffffff))
+#define upper32(x) \
+ ((u32)(((unsigned long long)(x) >> 32) & 0xffffffff))
+
+#define NETXEN_NIC_ZERO_PAUSE_ADDR 0ULL
+#define NETXEN_NIC_UNIT_PAUSE_ADDR 0x200ULL
+#define NETXEN_NIC_EPG_PAUSE_ADDR1 0x2200010000c28001ULL
+#define NETXEN_NIC_EPG_PAUSE_ADDR2 0x0100088866554433ULL
+
+#define NETXEN_NIC_WINDOW_MARGIN 0x100000
+
+unsigned long netxen_nic_pci_set_window(struct netxen_adapter *adapter,
+ unsigned long long addr);
+void netxen_free_hw_resources(struct netxen_adapter *adapter);
+
+int netxen_nic_set_mac(struct net_device *netdev, void *p)
+{
+ struct netxen_port *port = netdev_priv(netdev);
+ struct netxen_adapter *adapter = port->adapter;
+ struct sockaddr *addr = p;
+
+ if (netif_running(netdev))
+ return -EBUSY;
+
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ DPRINTK(INFO, "valid ether addr\n");
+ memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+
+ if (adapter->ops->macaddr_set)
+ adapter->ops->macaddr_set(port, addr->sa_data);
+
+ return 0;
+}
+
+/*
+ * netxen_nic_set_multi - Multicast
+ */
+void netxen_nic_set_multi(struct net_device *netdev)
+{
+ struct netxen_port *port = netdev_priv(netdev);
+ struct netxen_adapter *adapter = port->adapter;
+ struct dev_mc_list *mc_ptr;
+ __le32 netxen_mac_addr_cntl_data = 0;
+
+ mc_ptr = netdev->mc_list;
+ if (netdev->flags & IFF_PROMISC) {
+ if (adapter->ops->set_promisc)
+ adapter->ops->set_promisc(adapter,
+ port->portnum,
+ NETXEN_NIU_PROMISC_MODE);
+ } else {
+ if (adapter->ops->unset_promisc &&
+ adapter->ahw.boardcfg.board_type
+ != NETXEN_BRDTYPE_P2_SB31_10G_IMEZ)
+ adapter->ops->unset_promisc(adapter,
+ port->portnum,
+ NETXEN_NIU_NON_PROMISC_MODE);
+ }
+ if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
+ netxen_nic_mcr_set_mode_select(netxen_mac_addr_cntl_data, 0x03);
+ netxen_nic_mcr_set_id_pool0(netxen_mac_addr_cntl_data, 0x00);
+ netxen_nic_mcr_set_id_pool1(netxen_mac_addr_cntl_data, 0x00);
+ netxen_nic_mcr_set_id_pool2(netxen_mac_addr_cntl_data, 0x00);
+ netxen_nic_mcr_set_id_pool3(netxen_mac_addr_cntl_data, 0x00);
+ netxen_nic_mcr_set_enable_xtnd0(netxen_mac_addr_cntl_data);
+ netxen_nic_mcr_set_enable_xtnd1(netxen_mac_addr_cntl_data);
+ netxen_nic_mcr_set_enable_xtnd2(netxen_mac_addr_cntl_data);
+ netxen_nic_mcr_set_enable_xtnd3(netxen_mac_addr_cntl_data);
+ } else {
+ netxen_nic_mcr_set_mode_select(netxen_mac_addr_cntl_data, 0x00);
+ netxen_nic_mcr_set_id_pool0(netxen_mac_addr_cntl_data, 0x00);
+ netxen_nic_mcr_set_id_pool1(netxen_mac_addr_cntl_data, 0x01);
+ netxen_nic_mcr_set_id_pool2(netxen_mac_addr_cntl_data, 0x02);
+ netxen_nic_mcr_set_id_pool3(netxen_mac_addr_cntl_data, 0x03);
+ }
+ writel(netxen_mac_addr_cntl_data,
+ NETXEN_CRB_NORMALIZE(adapter, NETXEN_MAC_ADDR_CNTL_REG));
+ if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
+ writel(netxen_mac_addr_cntl_data,
+ NETXEN_CRB_NORMALIZE(adapter,
+ NETXEN_MULTICAST_ADDR_HI_0));
+ } else {
+ writel(netxen_mac_addr_cntl_data,
+ NETXEN_CRB_NORMALIZE(adapter,
+ NETXEN_MULTICAST_ADDR_HI_1));
+ }
+ netxen_mac_addr_cntl_data = 0;
+ writel(netxen_mac_addr_cntl_data,
+ NETXEN_CRB_NORMALIZE(adapter, NETXEN_NIU_GB_DROP_WRONGADDR));
+}
+
+/*
+ * netxen_nic_change_mtu - Change the Maximum Transfer Unit
+ * @returns 0 on success, negative on failure
+ */
+int netxen_nic_change_mtu(struct net_device *netdev, int mtu)
+{
+ struct netxen_port *port = netdev_priv(netdev);
+ struct netxen_adapter *adapter = port->adapter;
+ int eff_mtu = mtu + NETXEN_ENET_HEADER_SIZE + NETXEN_ETH_FCS_SIZE;
+
+ if ((eff_mtu > NETXEN_MAX_MTU) || (eff_mtu < NETXEN_MIN_MTU)) {
+ printk(KERN_ERR "%s: %s %d is not supported.\n",
+ netxen_nic_driver_name, netdev->name, mtu);
+ return -EINVAL;
+ }
+
+ if (adapter->ops->set_mtu)
+ adapter->ops->set_mtu(port, mtu);
+ netdev->mtu = mtu;
+
+ return 0;
+}
+
+/*
+ * check if the firmware has been downloaded and ready to run and
+ * setup the address for the descriptors in the adapter
+ */
+int netxen_nic_hw_resources(struct netxen_adapter *adapter)
+{
+ struct netxen_hardware_context *hw = &adapter->ahw;
+ u32 state = 0;
+ void *addr;
+ void *pause_addr;
+ int loops = 0, err = 0;
+ int ctx, ring;
+ u32 card_cmdring = 0;
+ struct netxen_rcv_desc_crb *rcv_desc_crb = NULL;
+ struct netxen_recv_context *recv_ctx;
+ struct netxen_rcv_desc_ctx *rcv_desc;
+
+ DPRINTK(INFO, "crb_base: %lx %lx", NETXEN_PCI_CRBSPACE,
+ PCI_OFFSET_SECOND_RANGE(adapter, NETXEN_PCI_CRBSPACE));
+ DPRINTK(INFO, "cam base: %lx %lx", NETXEN_CRB_CAM,
+ pci_base_offset(adapter, NETXEN_CRB_CAM));
+ DPRINTK(INFO, "cam RAM: %lx %lx", NETXEN_CAM_RAM_BASE,
+ pci_base_offset(adapter, NETXEN_CAM_RAM_BASE));
+ DPRINTK(INFO, "NIC base:%lx %lx\n", NIC_CRB_BASE_PORT1,
+ pci_base_offset(adapter, NIC_CRB_BASE_PORT1));
+
+ /* Window 1 call */
+ card_cmdring = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_CMDRING));
+
+ DPRINTK(INFO, "Command Peg sends 0x%x for cmdring base\n",
+ card_cmdring);
+
+ for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
+ DPRINTK(INFO, "Command Peg ready..waiting for rcv peg\n");
+ loops = 0;
+ state = 0;
+ /* Window 1 call */
+ state = readl(NETXEN_CRB_NORMALIZE(adapter,
+ recv_crb_registers[ctx].
+ crb_rcvpeg_state));
+ while (state != PHAN_PEG_RCV_INITIALIZED && loops < 20) {
+ udelay(100);
+ /* Window 1 call */
+ state = readl(NETXEN_CRB_NORMALIZE(adapter,
+ recv_crb_registers
+ [ctx].
+ crb_rcvpeg_state));
+ loops++;
+ }
+ if (loops >= 20) {
+ printk(KERN_ERR "Rcv Peg initialization not complete:"
+ "%x.\n", state);
+ err = -EIO;
+ return err;
+ }
+ }
+ DPRINTK(INFO, "Recieve Peg ready too. starting stuff\n");
+
+ addr = netxen_alloc(adapter->ahw.pdev,
+ sizeof(struct cmd_desc_type0) *
+ adapter->max_tx_desc_count,
+ &hw->cmd_desc_phys_addr, &hw->cmd_desc_pdev);
+
+ if (addr == NULL) {
+ DPRINTK(ERR, "bad return from pci_alloc_consistent\n");
+ return -ENOMEM;
+ }
+
+ pause_addr = netxen_alloc(adapter->ahw.pdev, 512,
+ (dma_addr_t *) & hw->pause_physaddr,
+ &hw->pause_pdev);
+ if (pause_addr == NULL) {
+ DPRINTK(1, ERR, "bad return from pci_alloc_consistent\n");
+ return -ENOMEM;
+ }
+
+ hw->pauseaddr = (char *)pause_addr;
+ {
+ u64 *ptr = (u64 *) pause_addr;
+ *ptr++ = NETXEN_NIC_ZERO_PAUSE_ADDR;
+ *ptr++ = NETXEN_NIC_ZERO_PAUSE_ADDR;
+ *ptr++ = NETXEN_NIC_UNIT_PAUSE_ADDR;
+ *ptr++ = NETXEN_NIC_ZERO_PAUSE_ADDR;
+ *ptr++ = NETXEN_NIC_EPG_PAUSE_ADDR1;
+ *ptr++ = NETXEN_NIC_EPG_PAUSE_ADDR2;
+ }
+
+ hw->cmd_desc_head = (struct cmd_desc_type0 *)addr;
+
+ for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
+ recv_ctx = &adapter->recv_ctx[ctx];
+
+ for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
+ rcv_desc = &recv_ctx->rcv_desc[ring];
+ addr = netxen_alloc(adapter->ahw.pdev,
+ RCV_DESC_RINGSIZE,
+ &rcv_desc->phys_addr,
+ &rcv_desc->phys_pdev);
+ if (addr == NULL) {
+ DPRINTK(ERR, "bad return from "
+ "pci_alloc_consistent\n");
+ netxen_free_hw_resources(adapter);
+ err = -ENOMEM;
+ return err;
+ }
+ rcv_desc->desc_head = (struct rcv_desc *)addr;
+ }
+
+ addr = netxen_alloc(adapter->ahw.pdev, STATUS_DESC_RINGSIZE,
+ &recv_ctx->rcv_status_desc_phys_addr,
+ &recv_ctx->rcv_status_desc_pdev);
+ if (addr == NULL) {
+ DPRINTK(ERR, "bad return from"
+ " pci_alloc_consistent\n");
+ netxen_free_hw_resources(adapter);
+ err = -ENOMEM;
+ return err;
+ }
+ recv_ctx->rcv_status_desc_head = (struct status_desc *)addr;
+ for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
+ rcv_desc = &recv_ctx->rcv_desc[ring];
+ rcv_desc_crb =
+ &recv_crb_registers[ctx].rcv_desc_crb[ring];
+ DPRINTK(INFO, "ring #%d crb global ring reg 0x%x\n",
+ ring, rcv_desc_crb->crb_globalrcv_ring);
+ /* Window = 1 */
+ writel(lower32(rcv_desc->phys_addr),
+ NETXEN_CRB_NORMALIZE(adapter,
+ rcv_desc_crb->
+ crb_globalrcv_ring));
+ DPRINTK(INFO, "GLOBAL_RCV_RING ctx %d, addr 0x%x"
+ " val 0x%llx,"
+ " virt %p\n", ctx,
+ rcv_desc_crb->crb_globalrcv_ring,
+ (unsigned long long)rcv_desc->phys_addr,
+ +rcv_desc->desc_head);
+ }
+
+ /* Window = 1 */
+ writel(lower32(recv_ctx->rcv_status_desc_phys_addr),
+ NETXEN_CRB_NORMALIZE(adapter,
+ recv_crb_registers[ctx].
+ crb_rcvstatus_ring));
+ DPRINTK(INFO, "RCVSTATUS_RING, ctx %d, addr 0x%x,"
+ " val 0x%x,virt%p\n",
+ ctx,
+ recv_crb_registers[ctx].crb_rcvstatus_ring,
+ (unsigned long long)recv_ctx->rcv_status_desc_phys_addr,
+ recv_ctx->rcv_status_desc_head);
+ }
+ /* Window = 1 */
+ writel(lower32(hw->pause_physaddr),
+ NETXEN_CRB_NORMALIZE(adapter, CRB_PAUSE_ADDR_LO));
+ writel(upper32(hw->pause_physaddr),
+ NETXEN_CRB_NORMALIZE(adapter, CRB_PAUSE_ADDR_HI));
+
+ writel(lower32(hw->cmd_desc_phys_addr),
+ NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_CMD_ADDR_LO));
+ writel(upper32(hw->cmd_desc_phys_addr),
+ NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_CMD_ADDR_HI));
+ return err;
+}
+
+void netxen_free_hw_resources(struct netxen_adapter *adapter)
+{
+ struct netxen_recv_context *recv_ctx;
+ struct netxen_rcv_desc_ctx *rcv_desc;
+ int ctx, ring;
+
+ if (adapter->ahw.cmd_desc_head != NULL) {
+ pci_free_consistent(adapter->ahw.cmd_desc_pdev,
+ sizeof(struct cmd_desc_type0) *
+ adapter->max_tx_desc_count,
+ adapter->ahw.cmd_desc_head,
+ adapter->ahw.cmd_desc_phys_addr);
+ adapter->ahw.cmd_desc_head = NULL;
+ }
+ if (adapter->ahw.pauseaddr != NULL) {
+ pci_free_consistent(adapter->ahw.pause_pdev, 512,
+ adapter->ahw.pauseaddr,
+ adapter->ahw.pause_physaddr);
+ adapter->ahw.pauseaddr = NULL;
+ }
+
+ for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
+ recv_ctx = &adapter->recv_ctx[ctx];
+ for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
+ rcv_desc = &recv_ctx->rcv_desc[ring];
+
+ if (rcv_desc->desc_head != NULL) {
+ pci_free_consistent(rcv_desc->phys_pdev,
+ RCV_DESC_RINGSIZE,
+ rcv_desc->desc_head,
+ rcv_desc->phys_addr);
+ rcv_desc->desc_head = NULL;
+ }
+ }
+
+ if (recv_ctx->rcv_status_desc_head != NULL) {
+ pci_free_consistent(recv_ctx->rcv_status_desc_pdev,
+ STATUS_DESC_RINGSIZE,
+ recv_ctx->rcv_status_desc_head,
+ recv_ctx->
+ rcv_status_desc_phys_addr);
+ recv_ctx->rcv_status_desc_head = NULL;
+ }
+ }
+}
+
+void netxen_tso_check(struct netxen_adapter *adapter,
+ struct cmd_desc_type0 *desc, struct sk_buff *skb)
+{
+ if (desc->mss) {
+ desc->total_hdr_length = sizeof(struct ethhdr) +
+ ((skb->nh.iph)->ihl * sizeof(u32)) +
+ ((skb->h.th)->doff * sizeof(u32));
+ desc->opcode = TX_TCP_LSO;
+ } else if (skb->ip_summed == CHECKSUM_COMPLETE) {
+ if (skb->nh.iph->protocol == IPPROTO_TCP) {
+ desc->opcode = TX_TCP_PKT;
+ } else if (skb->nh.iph->protocol == IPPROTO_UDP) {
+ desc->opcode = TX_UDP_PKT;
+ } else {
+ return;
+ }
+ }
+ adapter->stats.xmitcsummed++;
+ CMD_DESC_TCP_HDR_OFFSET_WRT(desc, skb->h.raw - skb->data);
+ desc->length_tcp_hdr = cpu_to_le32(desc->length_tcp_hdr);
+ desc->ip_hdr_offset = skb->nh.raw - skb->data;
+}
+
+int netxen_is_flash_supported(struct netxen_adapter *adapter)
+{
+ const int locs[] = { 0, 0x4, 0x100, 0x4000, 0x4128 };
+ int addr, val01, val02, i, j;
+
+ /* if the flash size less than 4Mb, make huge war cry and die */
+ for (j = 1; j < 4; j++) {
+ addr = j * NETXEN_NIC_WINDOW_MARGIN;
+ for (i = 0; i < (sizeof(locs) / sizeof(locs[0])); i++) {
+ if (netxen_rom_fast_read(adapter, locs[i], &val01) == 0
+ && netxen_rom_fast_read(adapter, (addr + locs[i]),
+ &val02) == 0) {
+ if (val01 == val02)
+ return -1;
+ } else
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int netxen_get_flash_block(struct netxen_adapter *adapter, int base,
+ int size, u32 * buf)
+{
+ int i, addr;
+ u32 *ptr32;
+
+ addr = base;
+ ptr32 = buf;
+ for (i = 0; i < size / sizeof(u32); i++) {
+ if (netxen_rom_fast_read(adapter, addr, ptr32) == -1)
+ return -1;
+ ptr32++;
+ addr += sizeof(u32);
+ }
+ if ((char *)buf + size > (char *)ptr32) {
+ u32 local;
+
+ if (netxen_rom_fast_read(adapter, addr, &local) == -1)
+ return -1;
+ memcpy(ptr32, &local, (char *)buf + size - (char *)ptr32);
+ }
+
+ return 0;
+}
+
+int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, u64 mac[])
+{
+ u32 *pmac = (u32 *) & mac[0];
+
+ if (netxen_get_flash_block(adapter,
+ USER_START +
+ offsetof(struct netxen_new_user_info,
+ mac_addr),
+ FLASH_NUM_PORTS * sizeof(u64), pmac) == -1) {
+ return -1;
+ }
+ if (*mac == ~0ULL) {
+ if (netxen_get_flash_block(adapter,
+ USER_START_OLD +
+ offsetof(struct netxen_user_old_info,
+ mac_addr),
+ FLASH_NUM_PORTS * sizeof(u64),
+ pmac) == -1)
+ return -1;
+ if (*mac == ~0ULL)
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Changes the CRB window to the specified window.
+ */
+void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw)
+{
+ void __iomem *offset;
+ u32 tmp;
+ int count = 0;
+
+ if (adapter->curr_window == wndw)
+ return;
+
+ /*
+ * Move the CRB window.
+ * We need to write to the "direct access" region of PCI
+ * to avoid a race condition where the window register has
+ * not been successfully written across CRB before the target
+ * register address is received by PCI. The direct region bypasses
+ * the CRB bus.
+ */
+ offset =
+ PCI_OFFSET_SECOND_RANGE(adapter,
+ NETXEN_PCIX_PH_REG(PCIX_CRB_WINDOW));
+
+ if (wndw & 0x1)
+ wndw = NETXEN_WINDOW_ONE;
+
+ writel(wndw, offset);
+
+ /* MUST make sure window is set before we forge on... */
+ while ((tmp = readl(offset)) != wndw) {
+ printk(KERN_WARNING "%s: %s WARNING: CRB window value not "
+ "registered properly: 0x%08x.\n",
+ netxen_nic_driver_name, __FUNCTION__, tmp);
+ mdelay(1);
+ if (count >= 10)
+ break;
+ count++;
+ }
+
+ adapter->curr_window = wndw;
+}
+
+void netxen_load_firmware(struct netxen_adapter *adapter)
+{
+ int i;
+ long data, size = 0;
+ long flashaddr = NETXEN_FLASH_BASE, memaddr = NETXEN_PHANTOM_MEM_BASE;
+ u64 off;
+ void __iomem *addr;
+
+ size = NETXEN_FIRMWARE_LEN;
+ writel(1, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST));
+
+ for (i = 0; i < size; i++) {
+ if (netxen_rom_fast_read(adapter, flashaddr, (int *)&data) != 0) {
+ DPRINTK(ERR,
+ "Error in netxen_rom_fast_read(). Will skip"
+ "loading flash image\n");
+ return;
+ }
+ off = netxen_nic_pci_set_window(adapter, memaddr);
+ addr = pci_base_offset(adapter, off);
+ writel(data, addr);
+ flashaddr += 4;
+ memaddr += 4;
+ }
+ udelay(100);
+ /* make sure Casper is powered on */
+ writel(0x3fff,
+ NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL));
+ writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST));
+
+ udelay(100);
+}
+
+int
+netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data,
+ int len)
+{
+ void __iomem *addr;
+
+ if (ADDR_IN_WINDOW1(off)) {
+ addr = NETXEN_CRB_NORMALIZE(adapter, off);
+ } else { /* Window 0 */
+ addr = pci_base_offset(adapter, off);
+ netxen_nic_pci_change_crbwindow(adapter, 0);
+ }
+
+ DPRINTK(INFO, "writing to base %lx offset %llx addr %p"
+ " data %llx len %d\n",
+ pci_base(adapter, off), off, addr,
+ *(unsigned long long *)data, len);
+ if (!addr) {
+ netxen_nic_pci_change_crbwindow(adapter, 1);
+ return 1;
+ }
+
+ switch (len) {
+ case 1:
+ writeb(*(u8 *) data, addr);
+ break;
+ case 2:
+ writew(*(u16 *) data, addr);
+ break;
+ case 4:
+ writel(*(u32 *) data, addr);
+ break;
+ case 8:
+ writeq(*(u64 *) data, addr);
+ break;
+ default:
+ DPRINTK(INFO,
+ "writing data %lx to offset %llx, num words=%d\n",
+ *(unsigned long *)data, off, (len >> 3));
+
+ netxen_nic_hw_block_write64((u64 __iomem *) data, addr,
+ (len >> 3));
+ break;
+ }
+ if (!ADDR_IN_WINDOW1(off))
+ netxen_nic_pci_change_crbwindow(adapter, 1);
+
+ return 0;
+}
+
+int
+netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off, void *data,
+ int len)
+{
+ void __iomem *addr;
+
+ if (ADDR_IN_WINDOW1(off)) { /* Window 1 */
+ addr = NETXEN_CRB_NORMALIZE(adapter, off);
+ } else { /* Window 0 */
+ addr = pci_base_offset(adapter, off);
+ netxen_nic_pci_change_crbwindow(adapter, 0);
+ }
+
+ DPRINTK(INFO, "reading from base %lx offset %llx addr %p\n",
+ pci_base(adapter, off), off, addr);
+ if (!addr) {
+ netxen_nic_pci_change_crbwindow(adapter, 1);
+ return 1;
+ }
+ switch (len) {
+ case 1:
+ *(u8 *) data = readb(addr);
+ break;
+ case 2:
+ *(u16 *) data = readw(addr);
+ break;
+ case 4:
+ *(u32 *) data = readl(addr);
+ break;
+ case 8:
+ *(u64 *) data = readq(addr);
+ break;
+ default:
+ netxen_nic_hw_block_read64((u64 __iomem *) data, addr,
+ (len >> 3));
+ break;
+ }
+ DPRINTK(INFO, "read %lx\n", *(unsigned long *)data);
+
+ if (!ADDR_IN_WINDOW1(off))
+ netxen_nic_pci_change_crbwindow(adapter, 1);
+
+ return 0;
+}
+
+void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val)
+{ /* Only for window 1 */
+ void __iomem *addr;
+
+ addr = NETXEN_CRB_NORMALIZE(adapter, off);
+ DPRINTK(INFO, "writing to base %lx offset %llx addr %p data %x\n",
+ pci_base(adapter, off), off, addr);
+ writel(val, addr);
+
+}
+
+int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off)
+{ /* Only for window 1 */
+ void __iomem *addr;
+ int val;
+
+ addr = NETXEN_CRB_NORMALIZE(adapter, off);
+ DPRINTK(INFO, "reading from base %lx offset %llx addr %p\n",
+ adapter->ahw.pci_base, off, addr);
+ val = readl(addr);
+ writel(val, addr);
+
+ return val;
+}
+
+/* Change the window to 0, write and change back to window 1. */
+void netxen_nic_write_w0(struct netxen_adapter *adapter, u32 index, u32 value)
+{
+ void __iomem *addr;
+
+ netxen_nic_pci_change_crbwindow(adapter, 0);
+ addr = pci_base_offset(adapter, index);
+ writel(value, addr);
+ netxen_nic_pci_change_crbwindow(adapter, 1);
+}
+
+/* Change the window to 0, read and change back to window 1. */
+void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 * value)
+{
+ void __iomem *addr;
+
+ addr = pci_base_offset(adapter, index);
+
+ netxen_nic_pci_change_crbwindow(adapter, 0);
+ *value = readl(addr);
+ netxen_nic_pci_change_crbwindow(adapter, 1);
+}
+
+int netxen_pci_set_window_warning_count = 0;
+
+unsigned long
+netxen_nic_pci_set_window(struct netxen_adapter *adapter,
+ unsigned long long addr)
+{
+ static int ddr_mn_window = -1;
+ static int qdr_sn_window = -1;
+ int window;
+
+ if (ADDR_IN_RANGE(addr, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) {
+ /* DDR network side */
+ addr -= NETXEN_ADDR_DDR_NET;
+ window = (addr >> 25) & 0x3ff;
+ if (ddr_mn_window != window) {
+ ddr_mn_window = window;
+ writel(window, PCI_OFFSET_SECOND_RANGE(adapter,
+ NETXEN_PCIX_PH_REG
+ (PCIX_MN_WINDOW)));
+ /* MUST make sure window is set before we forge on... */
+ readl(PCI_OFFSET_SECOND_RANGE(adapter,
+ NETXEN_PCIX_PH_REG
+ (PCIX_MN_WINDOW)));
+ }
+ addr -= (window * NETXEN_WINDOW_ONE);
+ addr += NETXEN_PCI_DDR_NET;
+ } else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) {
+ addr -= NETXEN_ADDR_OCM0;
+ addr += NETXEN_PCI_OCM0;
+ } else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) {
+ addr -= NETXEN_ADDR_OCM1;
+ addr += NETXEN_PCI_OCM1;
+ } else
+ if (ADDR_IN_RANGE
+ (addr, NETXEN_ADDR_QDR_NET, NETXEN_ADDR_QDR_NET_MAX)) {
+ /* QDR network side */
+ addr -= NETXEN_ADDR_QDR_NET;
+ window = (addr >> 22) & 0x3f;
+ if (qdr_sn_window != window) {
+ qdr_sn_window = window;
+ writel((window << 22),
+ PCI_OFFSET_SECOND_RANGE(adapter,
+ NETXEN_PCIX_PH_REG
+ (PCIX_SN_WINDOW)));
+ /* MUST make sure window is set before we forge on... */
+ readl(PCI_OFFSET_SECOND_RANGE(adapter,
+ NETXEN_PCIX_PH_REG
+ (PCIX_SN_WINDOW)));
+ }
+ addr -= (window * 0x400000);
+ addr += NETXEN_PCI_QDR_NET;
+ } else {
+ /*
+ * peg gdb frequently accesses memory that doesn't exist,
+ * this limits the chit chat so debugging isn't slowed down.
+ */
+ if ((netxen_pci_set_window_warning_count++ < 8)
+ || (netxen_pci_set_window_warning_count % 64 == 0))
+ printk("%s: Warning:netxen_nic_pci_set_window()"
+ " Unknown address range!\n",
+ netxen_nic_driver_name);
+
+ }
+ return addr;
+}
+
+int netxen_nic_get_board_info(struct netxen_adapter *adapter)
+{
+ int rv = 0;
+ int addr = BRDCFG_START;
+ struct netxen_board_info *boardinfo;
+ int index;
+ u32 *ptr32;
+
+ boardinfo = &adapter->ahw.boardcfg;
+ ptr32 = (u32 *) boardinfo;
+
+ for (index = 0; index < sizeof(struct netxen_board_info) / sizeof(u32);
+ index++) {
+ if (netxen_rom_fast_read(adapter, addr, ptr32) == -1) {
+ return -EIO;
+ }
+ ptr32++;
+ addr += sizeof(u32);
+ }
+ if (boardinfo->magic != NETXEN_BDINFO_MAGIC) {
+ printk("%s: ERROR reading %s board config."
+ " Read %x, expected %x\n", netxen_nic_driver_name,
+ netxen_nic_driver_name,
+ boardinfo->magic, NETXEN_BDINFO_MAGIC);
+ rv = -1;
+ }
+ if (boardinfo->header_version != NETXEN_BDINFO_VERSION) {
+ printk("%s: Unknown board config version."
+ " Read %x, expected %x\n", netxen_nic_driver_name,
+ boardinfo->header_version, NETXEN_BDINFO_VERSION);
+ rv = -1;
+ }
+
+ DPRINTK(INFO, "Discovered board type:0x%x ", boardinfo->board_type);
+ switch ((netxen_brdtype_t) boardinfo->board_type) {
+ case NETXEN_BRDTYPE_P2_SB35_4G:
+ adapter->ahw.board_type = NETXEN_NIC_GBE;
+ break;
+ case NETXEN_BRDTYPE_P2_SB31_10G:
+ case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
+ case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ:
+ case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
+ adapter->ahw.board_type = NETXEN_NIC_XGBE;
+ break;
+ case NETXEN_BRDTYPE_P1_BD:
+ case NETXEN_BRDTYPE_P1_SB:
+ case NETXEN_BRDTYPE_P1_SMAX:
+ case NETXEN_BRDTYPE_P1_SOCK:
+ adapter->ahw.board_type = NETXEN_NIC_GBE;
+ break;
+ default:
+ printk("%s: Unknown(%x)\n", netxen_nic_driver_name,
+ boardinfo->board_type);
+ break;
+ }
+
+ return rv;
+}
+
+/* NIU access sections */
+
+int netxen_nic_set_mtu_gb(struct netxen_port *port, int new_mtu)
+{
+ struct netxen_adapter *adapter = port->adapter;
+ netxen_nic_write_w0(adapter,
+ NETXEN_NIU_GB_MAX_FRAME_SIZE(port->portnum),
+ new_mtu);
+ return 0;
+}
+
+int netxen_nic_set_mtu_xgb(struct netxen_port *port, int new_mtu)
+{
+ struct netxen_adapter *adapter = port->adapter;
+ new_mtu += NETXEN_NIU_HDRSIZE + NETXEN_NIU_TLRSIZE;
+ netxen_nic_write_w0(adapter, NETXEN_NIU_XGE_MAX_FRAME_SIZE, new_mtu);
+ return 0;
+}
+
+void netxen_nic_init_niu_gb(struct netxen_adapter *adapter)
+{
+ int portno;
+ for (portno = 0; portno < NETXEN_NIU_MAX_GBE_PORTS; portno++)
+ netxen_niu_gbe_init_port(adapter, portno);
+}
+
+void netxen_nic_stop_all_ports(struct netxen_adapter *adapter)
+{
+ int port_nr;
+ struct netxen_port *port;
+
+ for (port_nr = 0; port_nr < adapter->ahw.max_ports; port_nr++) {
+ port = adapter->port[port_nr];
+ if (adapter->ops->stop_port)
+ adapter->ops->stop_port(adapter, port->portnum);
+ }
+}
+
+void
+netxen_crb_writelit_adapter(struct netxen_adapter *adapter, unsigned long off,
+ int data)
+{
+ void __iomem *addr;
+
+ if (ADDR_IN_WINDOW1(off)) {
+ writel(data, NETXEN_CRB_NORMALIZE(adapter, off));
+ } else {
+ netxen_nic_pci_change_crbwindow(adapter, 0);
+ addr = pci_base_offset(adapter, off);
+ writel(data, addr);
+ netxen_nic_pci_change_crbwindow(adapter, 1);
+ }
+}
+
+void netxen_nic_set_link_parameters(struct netxen_port *port)
+{
+ struct netxen_adapter *adapter = port->adapter;
+ __le32 status;
+ u16 autoneg;
+ __le32 mode;
+
+ netxen_nic_read_w0(adapter, NETXEN_NIU_MODE, &mode);
+ if (netxen_get_niu_enable_ge(mode)) { /* Gb 10/100/1000 Mbps mode */
+ if (adapter->ops->phy_read
+ && adapter->ops->
+ phy_read(adapter, port->portnum,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
+ &status) == 0) {
+ if (netxen_get_phy_link(status)) {
+ switch (netxen_get_phy_speed(status)) {
+ case 0:
+ port->link_speed = SPEED_10;
+ break;
+ case 1:
+ port->link_speed = SPEED_100;
+ break;
+ case 2:
+ port->link_speed = SPEED_1000;
+ break;
+ default:
+ port->link_speed = -1;
+ break;
+ }
+ switch (netxen_get_phy_duplex(status)) {
+ case 0:
+ port->link_duplex = DUPLEX_HALF;
+ break;
+ case 1:
+ port->link_duplex = DUPLEX_FULL;
+ break;
+ default:
+ port->link_duplex = -1;
+ break;
+ }
+ if (adapter->ops->phy_read
+ && adapter->ops->
+ phy_read(adapter, port->portnum,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG,
+ (__le32 *) & autoneg) != 0)
+ port->link_autoneg = autoneg;
+ } else
+ goto link_down;
+ } else {
+ link_down:
+ port->link_speed = -1;
+ port->link_duplex = -1;
+ }
+ }
+}
+
+void netxen_nic_flash_print(struct netxen_adapter *adapter)
+{
+ int valid = 1;
+ u32 fw_major = 0;
+ u32 fw_minor = 0;
+ u32 fw_build = 0;
+ char brd_name[NETXEN_MAX_SHORT_NAME];
+ struct netxen_new_user_info user_info;
+ int i, addr = USER_START;
+ u32 *ptr32;
+
+ struct netxen_board_info *board_info = &(adapter->ahw.boardcfg);
+ if (board_info->magic != NETXEN_BDINFO_MAGIC) {
+ printk
+ ("NetXen Unknown board config, Read 0x%x expected as 0x%x\n",
+ board_info->magic, NETXEN_BDINFO_MAGIC);
+ valid = 0;
+ }
+ if (board_info->header_version != NETXEN_BDINFO_VERSION) {
+ printk("NetXen Unknown board config version."
+ " Read %x, expected %x\n",
+ board_info->header_version, NETXEN_BDINFO_VERSION);
+ valid = 0;
+ }
+ if (valid) {
+ ptr32 = (u32 *) & user_info;
+ for (i = 0;
+ i < sizeof(struct netxen_new_user_info) / sizeof(u32);
+ i++) {
+ if (netxen_rom_fast_read(adapter, addr, ptr32) == -1) {
+ printk("%s: ERROR reading %s board userarea.\n",
+ netxen_nic_driver_name,
+ netxen_nic_driver_name);
+ return;
+ }
+ ptr32++;
+ addr += sizeof(u32);
+ }
+ get_brd_name_by_type(board_info->board_type, brd_name);
+
+ printk("NetXen %s Board S/N %s Chip id 0x%x\n",
+ brd_name, user_info.serial_num, board_info->chip_id);
+
+ printk("NetXen %s Board #%d, Chip id 0x%x\n",
+ board_info->board_type == 0x0b ? "XGB" : "GBE",
+ board_info->board_num, board_info->chip_id);
+ fw_major = readl(NETXEN_CRB_NORMALIZE(adapter,
+ NETXEN_FW_VERSION_MAJOR));
+ fw_minor = readl(NETXEN_CRB_NORMALIZE(adapter,
+ NETXEN_FW_VERSION_MINOR));
+ fw_build =
+ readl(NETXEN_CRB_NORMALIZE(adapter, NETXEN_FW_VERSION_SUB));
+
+ printk("NetXen Firmware version %d.%d.%d\n", fw_major, fw_minor,
+ fw_build);
+ }
+ if (fw_major != _NETXEN_NIC_LINUX_MAJOR) {
+ printk(KERN_ERR "The mismatch in driver version and firmware "
+ "version major number\n"
+ "Driver version major number = %d \t"
+ "Firmware version major number = %d \n",
+ _NETXEN_NIC_LINUX_MAJOR, fw_major);
+ adapter->driver_mismatch = 1;
+ }
+ if (fw_minor != _NETXEN_NIC_LINUX_MINOR) {
+ printk(KERN_ERR "The mismatch in driver version and firmware "
+ "version minor number\n"
+ "Driver version minor number = %d \t"
+ "Firmware version minor number = %d \n",
+ _NETXEN_NIC_LINUX_MINOR, fw_minor);
+ adapter->driver_mismatch = 1;
+ }
+ if (adapter->driver_mismatch)
+ printk(KERN_INFO "Use the driver with version no %d.%d.xxx\n",
+ fw_major, fw_minor);
+}
+
+int netxen_crb_read_val(struct netxen_adapter *adapter, unsigned long off)
+{
+ int data;
+ netxen_nic_hw_read_wx(adapter, off, &data, 4);
+ return data;
+}
diff --git a/drivers/net/netxen/netxen_nic_hw.h b/drivers/net/netxen/netxen_nic_hw.h
new file mode 100644
index 000000000000..201a636b7ab8
--- /dev/null
+++ b/drivers/net/netxen/netxen_nic_hw.h
@@ -0,0 +1,482 @@
+/*
+ * Copyright (C) 2003 - 2006 NetXen, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.
+ *
+ * Contact Information:
+ * info@netxen.com
+ * NetXen,
+ * 3965 Freedom Circle, Fourth floor,
+ * Santa Clara, CA 95054
+ *
+ *
+ * Structures, enums, and macros for the MAC
+ *
+ */
+
+#ifndef __NETXEN_NIC_HW_H_
+#define __NETXEN_NIC_HW_H_
+
+#include "netxen_nic_hdr.h"
+
+/* Hardware memory size of 128 meg */
+#define NETXEN_MEMADDR_MAX (128 * 1024 * 1024)
+
+#ifndef readq
+static inline u64 readq(void __iomem * addr)
+{
+ return readl(addr) | (((u64) readl(addr + 4)) << 32LL);
+}
+#endif
+
+#ifndef writeq
+static inline void writeq(u64 val, void __iomem * addr)
+{
+ writel(((u32) (val)), (addr));
+ writel(((u32) (val >> 32)), (addr + 4));
+}
+#endif
+
+static inline void netxen_nic_hw_block_write64(u64 __iomem * data_ptr,
+ u64 __iomem * addr,
+ int num_words)
+{
+ int num;
+ for (num = 0; num < num_words; num++) {
+ writeq(readq((void __iomem *)data_ptr), addr);
+ addr++;
+ data_ptr++;
+ }
+}
+
+static inline void netxen_nic_hw_block_read64(u64 __iomem * data_ptr,
+ u64 __iomem * addr, int num_words)
+{
+ int num;
+ for (num = 0; num < num_words; num++) {
+ writeq(readq((void __iomem *)addr), data_ptr);
+ addr++;
+ data_ptr++;
+ }
+
+}
+
+struct netxen_adapter;
+
+#define NETXEN_PCI_MAPSIZE_BYTES (NETXEN_PCI_MAPSIZE << 20)
+
+#define NETXEN_NIC_LOCKED_READ_REG(X, Y) \
+ addr = pci_base_offset(adapter, (X)); \
+ *(u32 *)Y = readl(addr);
+
+struct netxen_port;
+void netxen_nic_set_link_parameters(struct netxen_port *port);
+void netxen_nic_flash_print(struct netxen_adapter *adapter);
+int netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off,
+ void *data, int len);
+void netxen_crb_writelit_adapter(struct netxen_adapter *adapter,
+ unsigned long off, int data);
+int netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off,
+ void *data, int len);
+
+typedef u8 netxen_ethernet_macaddr_t[6];
+
+/* Nibble or Byte mode for phy interface (GbE mode only) */
+typedef enum {
+ NETXEN_NIU_10_100_MB = 0,
+ NETXEN_NIU_1000_MB
+} netxen_niu_gbe_ifmode_t;
+
+#define _netxen_crb_get_bit(var, bit) ((var >> bit) & 0x1)
+
+/*
+ * NIU GB MAC Config Register 0 (applies to GB0, GB1, GB2, GB3)
+ *
+ * Bit 0 : enable_tx => 1:enable frame xmit, 0:disable
+ * Bit 1 : tx_synced => R/O: xmit enable synched to xmit stream
+ * Bit 2 : enable_rx => 1:enable frame recv, 0:disable
+ * Bit 3 : rx_synced => R/O: recv enable synched to recv stream
+ * Bit 4 : tx_flowctl => 1:enable pause frame generation, 0:disable
+ * Bit 5 : rx_flowctl => 1:act on recv'd pause frames, 0:ignore
+ * Bit 8 : loopback => 1:loop MAC xmits to MAC recvs, 0:normal
+ * Bit 16: tx_reset_pb => 1:reset frame xmit protocol blk, 0:no-op
+ * Bit 17: rx_reset_pb => 1:reset frame recv protocol blk, 0:no-op
+ * Bit 18: tx_reset_mac => 1:reset data/ctl multiplexer blk, 0:no-op
+ * Bit 19: rx_reset_mac => 1:reset ctl frames & timers blk, 0:no-op
+ * Bit 31: soft_reset => 1:reset the MAC and the SERDES, 0:no-op
+ */
+
+#define netxen_gb_enable_tx(config_word) \
+ set_bit(0, (unsigned long*)(&config_word))
+#define netxen_gb_enable_rx(config_word) \
+ set_bit(2, (unsigned long*)(&config_word))
+#define netxen_gb_tx_flowctl(config_word) \
+ set_bit(4, (unsigned long*)(&config_word))
+#define netxen_gb_rx_flowctl(config_word) \
+ set_bit(5, (unsigned long*)(&config_word))
+#define netxen_gb_tx_reset_pb(config_word) \
+ set_bit(16, (unsigned long*)(&config_word))
+#define netxen_gb_rx_reset_pb(config_word) \
+ set_bit(17, (unsigned long*)(&config_word))
+#define netxen_gb_tx_reset_mac(config_word) \
+ set_bit(18, (unsigned long*)(&config_word))
+#define netxen_gb_rx_reset_mac(config_word) \
+ set_bit(19, (unsigned long*)(&config_word))
+#define netxen_gb_soft_reset(config_word) \
+ set_bit(31, (unsigned long*)(&config_word))
+
+#define netxen_gb_unset_tx_flowctl(config_word) \
+ clear_bit(4, (unsigned long *)(&config_word))
+#define netxen_gb_unset_rx_flowctl(config_word) \
+ clear_bit(5, (unsigned long*)(&config_word))
+
+#define netxen_gb_get_tx_synced(config_word) \
+ _netxen_crb_get_bit((config_word), 1)
+#define netxen_gb_get_rx_synced(config_word) \
+ _netxen_crb_get_bit((config_word), 3)
+#define netxen_gb_get_tx_flowctl(config_word) \
+ _netxen_crb_get_bit((config_word), 4)
+#define netxen_gb_get_rx_flowctl(config_word) \
+ _netxen_crb_get_bit((config_word), 5)
+#define netxen_gb_get_soft_reset(config_word) \
+ _netxen_crb_get_bit((config_word), 31)
+
+/*
+ * NIU GB MAC Config Register 1 (applies to GB0, GB1, GB2, GB3)
+ *
+ * Bit 0 : duplex => 1:full duplex mode, 0:half duplex
+ * Bit 1 : crc_enable => 1:append CRC to xmit frames, 0:dont append
+ * Bit 2 : padshort => 1:pad short frames and add CRC, 0:dont pad
+ * Bit 4 : checklength => 1:check framelen with actual,0:dont check
+ * Bit 5 : hugeframes => 1:allow oversize xmit frames, 0:dont allow
+ * Bits 8-9 : intfmode => 01:nibble (10/100), 10:byte (1000)
+ * Bits 12-15 : preamblelen => preamble field length in bytes, default 7
+ */
+
+#define netxen_gb_set_duplex(config_word) \
+ set_bit(0, (unsigned long*)&config_word)
+#define netxen_gb_set_crc_enable(config_word) \
+ set_bit(1, (unsigned long*)&config_word)
+#define netxen_gb_set_padshort(config_word) \
+ set_bit(2, (unsigned long*)&config_word)
+#define netxen_gb_set_checklength(config_word) \
+ set_bit(4, (unsigned long*)&config_word)
+#define netxen_gb_set_hugeframes(config_word) \
+ set_bit(5, (unsigned long*)&config_word)
+#define netxen_gb_set_preamblelen(config_word, val) \
+ ((config_word) |= ((val) << 12) & 0xF000)
+#define netxen_gb_set_intfmode(config_word, val) \
+ ((config_word) |= ((val) << 8) & 0x300)
+
+#define netxen_gb_get_stationaddress_low(config_word) ((config_word) >> 16)
+
+#define netxen_gb_set_mii_mgmt_clockselect(config_word, val) \
+ ((config_word) |= ((val) & 0x07))
+#define netxen_gb_mii_mgmt_reset(config_word) \
+ set_bit(31, (unsigned long*)&config_word)
+#define netxen_gb_mii_mgmt_unset(config_word) \
+ clear_bit(31, (unsigned long*)&config_word)
+
+/*
+ * NIU GB MII Mgmt Command Register (applies to GB0, GB1, GB2, GB3)
+ * Bit 0 : read_cycle => 1:perform single read cycle, 0:no-op
+ * Bit 1 : scan_cycle => 1:perform continuous read cycles, 0:no-op
+ */
+
+#define netxen_gb_mii_mgmt_set_read_cycle(config_word) \
+ set_bit(0, (unsigned long*)&config_word)
+#define netxen_gb_mii_mgmt_reg_addr(config_word, val) \
+ ((config_word) |= ((val) & 0x1F))
+#define netxen_gb_mii_mgmt_phy_addr(config_word, val) \
+ ((config_word) |= (((val) & 0x1F) << 8))
+
+/*
+ * NIU GB MII Mgmt Indicators Register (applies to GB0, GB1, GB2, GB3)
+ * Read-only register.
+ * Bit 0 : busy => 1:performing an MII mgmt cycle, 0:idle
+ * Bit 1 : scanning => 1:scan operation in progress, 0:idle
+ * Bit 2 : notvalid => :mgmt result data not yet valid, 0:idle
+ */
+#define netxen_get_gb_mii_mgmt_busy(config_word) \
+ _netxen_crb_get_bit(config_word, 0)
+#define netxen_get_gb_mii_mgmt_scanning(config_word) \
+ _netxen_crb_get_bit(config_word, 1)
+#define netxen_get_gb_mii_mgmt_notvalid(config_word) \
+ _netxen_crb_get_bit(config_word, 2)
+
+/*
+ * PHY-Specific MII control/status registers.
+ */
+typedef enum {
+ NETXEN_NIU_GB_MII_MGMT_ADDR_CONTROL = 0,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_STATUS = 1,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_ID_0 = 2,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_ID_1 = 3,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG = 4,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_LNKPART = 5,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG_MORE = 6,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_NEXTPAGE_XMIT = 7,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_LNKPART_NEXTPAGE = 8,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_1000BT_CONTROL = 9,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_1000BT_STATUS = 10,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_EXTENDED_STATUS = 15,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL = 16,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS = 17,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_INT_ENABLE = 18,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS = 19,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL_MORE = 20,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_RECV_ERROR_COUNT = 21,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_LED_CONTROL = 24,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_LED_OVERRIDE = 25,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL_MORE_YET = 26,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS_MORE = 27
+} netxen_niu_phy_register_t;
+
+/*
+ * PHY-Specific Status Register (reg 17).
+ *
+ * Bit 0 : jabber => 1:jabber detected, 0:not
+ * Bit 1 : polarity => 1:polarity reversed, 0:normal
+ * Bit 2 : recvpause => 1:receive pause enabled, 0:disabled
+ * Bit 3 : xmitpause => 1:transmit pause enabled, 0:disabled
+ * Bit 4 : energydetect => 1:sleep, 0:active
+ * Bit 5 : downshift => 1:downshift, 0:no downshift
+ * Bit 6 : crossover => 1:MDIX (crossover), 0:MDI (no crossover)
+ * Bits 7-9 : cablelen => not valid in 10Mb/s mode
+ * 0:<50m, 1:50-80m, 2:80-110m, 3:110-140m, 4:>140m
+ * Bit 10 : link => 1:link up, 0:link down
+ * Bit 11 : resolved => 1:speed and duplex resolved, 0:not yet
+ * Bit 12 : pagercvd => 1:page received, 0:page not received
+ * Bit 13 : duplex => 1:full duplex, 0:half duplex
+ * Bits 14-15 : speed => 0:10Mb/s, 1:100Mb/s, 2:1000Mb/s, 3:rsvd
+ */
+
+#define netxen_get_phy_cablelen(config_word) (((config_word) >> 7) & 0x07)
+#define netxen_get_phy_speed(config_word) (((config_word) >> 14) & 0x03)
+
+#define netxen_set_phy_speed(config_word, val) \
+ ((config_word) |= ((val & 0x03) << 14))
+#define netxen_set_phy_duplex(config_word) \
+ set_bit(13, (unsigned long*)&config_word)
+#define netxen_clear_phy_duplex(config_word) \
+ clear_bit(13, (unsigned long*)&config_word)
+
+#define netxen_get_phy_jabber(config_word) \
+ _netxen_crb_get_bit(config_word, 0)
+#define netxen_get_phy_polarity(config_word) \
+ _netxen_crb_get_bit(config_word, 1)
+#define netxen_get_phy_recvpause(config_word) \
+ _netxen_crb_get_bit(config_word, 2)
+#define netxen_get_phy_xmitpause(config_word) \
+ _netxen_crb_get_bit(config_word, 3)
+#define netxen_get_phy_energydetect(config_word) \
+ _netxen_crb_get_bit(config_word, 4)
+#define netxen_get_phy_downshift(config_word) \
+ _netxen_crb_get_bit(config_word, 5)
+#define netxen_get_phy_crossover(config_word) \
+ _netxen_crb_get_bit(config_word, 6)
+#define netxen_get_phy_link(config_word) \
+ _netxen_crb_get_bit(config_word, 10)
+#define netxen_get_phy_resolved(config_word) \
+ _netxen_crb_get_bit(config_word, 11)
+#define netxen_get_phy_pagercvd(config_word) \
+ _netxen_crb_get_bit(config_word, 12)
+#define netxen_get_phy_duplex(config_word) \
+ _netxen_crb_get_bit(config_word, 13)
+
+/*
+ * Interrupt Register definition
+ * This definition applies to registers 18 and 19 (int enable and int status).
+ * Bit 0 : jabber
+ * Bit 1 : polarity_changed
+ * Bit 4 : energy_detect
+ * Bit 5 : downshift
+ * Bit 6 : mdi_xover_changed
+ * Bit 7 : fifo_over_underflow
+ * Bit 8 : false_carrier
+ * Bit 9 : symbol_error
+ * Bit 10: link_status_changed
+ * Bit 11: autoneg_completed
+ * Bit 12: page_received
+ * Bit 13: duplex_changed
+ * Bit 14: speed_changed
+ * Bit 15: autoneg_error
+ */
+
+#define netxen_get_phy_int_jabber(config_word) \
+ _netxen_crb_get_bit(config_word, 0)
+#define netxen_get_phy_int_polarity_changed(config_word) \
+ _netxen_crb_get_bit(config_word, 1)
+#define netxen_get_phy_int_energy_detect(config_word) \
+ _netxen_crb_get_bit(config_word, 4)
+#define netxen_get_phy_int_downshift(config_word) \
+ _netxen_crb_get_bit(config_word, 5)
+#define netxen_get_phy_int_mdi_xover_changed(config_word) \
+ _netxen_crb_get_bit(config_word, 6)
+#define netxen_get_phy_int_fifo_over_underflow(config_word) \
+ _netxen_crb_get_bit(config_word, 7)
+#define netxen_get_phy_int_false_carrier(config_word) \
+ _netxen_crb_get_bit(config_word, 8)
+#define netxen_get_phy_int_symbol_error(config_word) \
+ _netxen_crb_get_bit(config_word, 9)
+#define netxen_get_phy_int_link_status_changed(config_word) \
+ _netxen_crb_get_bit(config_word, 10)
+#define netxen_get_phy_int_autoneg_completed(config_word) \
+ _netxen_crb_get_bit(config_word, 11)
+#define netxen_get_phy_int_page_received(config_word) \
+ _netxen_crb_get_bit(config_word, 12)
+#define netxen_get_phy_int_duplex_changed(config_word) \
+ _netxen_crb_get_bit(config_word, 13)
+#define netxen_get_phy_int_speed_changed(config_word) \
+ _netxen_crb_get_bit(config_word, 14)
+#define netxen_get_phy_int_autoneg_error(config_word) \
+ _netxen_crb_get_bit(config_word, 15)
+
+#define netxen_set_phy_int_link_status_changed(config_word) \
+ set_bit(10, (unsigned long*)&config_word)
+#define netxen_set_phy_int_autoneg_completed(config_word) \
+ set_bit(11, (unsigned long*)&config_word)
+#define netxen_set_phy_int_speed_changed(config_word) \
+ set_bit(14, (unsigned long*)&config_word)
+
+/*
+ * NIU Mode Register.
+ * Bit 0 : enable FibreChannel
+ * Bit 1 : enable 10/100/1000 Ethernet
+ * Bit 2 : enable 10Gb Ethernet
+ */
+
+#define netxen_get_niu_enable_ge(config_word) \
+ _netxen_crb_get_bit(config_word, 1)
+
+/* Promiscous mode options (GbE mode only) */
+typedef enum {
+ NETXEN_NIU_PROMISC_MODE = 0,
+ NETXEN_NIU_NON_PROMISC_MODE
+} netxen_niu_prom_mode_t;
+
+/*
+ * NIU GB Drop CRC Register
+ *
+ * Bit 0 : drop_gb0 => 1:drop pkts with bad CRCs, 0:pass them on
+ * Bit 1 : drop_gb1 => 1:drop pkts with bad CRCs, 0:pass them on
+ * Bit 2 : drop_gb2 => 1:drop pkts with bad CRCs, 0:pass them on
+ * Bit 3 : drop_gb3 => 1:drop pkts with bad CRCs, 0:pass them on
+ */
+
+#define netxen_set_gb_drop_gb0(config_word) \
+ set_bit(0, (unsigned long*)&config_word)
+#define netxen_set_gb_drop_gb1(config_word) \
+ set_bit(1, (unsigned long*)&config_word)
+#define netxen_set_gb_drop_gb2(config_word) \
+ set_bit(2, (unsigned long*)&config_word)
+#define netxen_set_gb_drop_gb3(config_word) \
+ set_bit(3, (unsigned long*)&config_word)
+
+#define netxen_clear_gb_drop_gb0(config_word) \
+ clear_bit(0, (unsigned long*)&config_word)
+#define netxen_clear_gb_drop_gb1(config_word) \
+ clear_bit(1, (unsigned long*)&config_word)
+#define netxen_clear_gb_drop_gb2(config_word) \
+ clear_bit(2, (unsigned long*)&config_word)
+#define netxen_clear_gb_drop_gb3(config_word) \
+ clear_bit(3, (unsigned long*)&config_word)
+
+/*
+ * NIU XG MAC Config Register
+ *
+ * Bit 0 : tx_enable => 1:enable frame xmit, 0:disable
+ * Bit 2 : rx_enable => 1:enable frame recv, 0:disable
+ * Bit 4 : soft_reset => 1:reset the MAC , 0:no-op
+ * Bit 27: xaui_framer_reset
+ * Bit 28: xaui_rx_reset
+ * Bit 29: xaui_tx_reset
+ * Bit 30: xg_ingress_afifo_reset
+ * Bit 31: xg_egress_afifo_reset
+ */
+
+#define netxen_xg_soft_reset(config_word) \
+ set_bit(4, (unsigned long*)&config_word)
+
+/*
+ * MAC Control Register
+ *
+ * Bit 0-1 : id_pool0
+ * Bit 2 : enable_xtnd0
+ * Bit 4-5 : id_pool1
+ * Bit 6 : enable_xtnd1
+ * Bit 8-9 : id_pool2
+ * Bit 10 : enable_xtnd2
+ * Bit 12-13 : id_pool3
+ * Bit 14 : enable_xtnd3
+ * Bit 24-25 : mode_select
+ * Bit 28-31 : enable_pool
+ */
+
+#define netxen_nic_mcr_set_id_pool0(config, val) \
+ ((config) |= ((val) &0x03))
+#define netxen_nic_mcr_set_enable_xtnd0(config) \
+ (set_bit(3, (unsigned long *)&(config)))
+#define netxen_nic_mcr_set_id_pool1(config, val) \
+ ((config) |= (((val) & 0x03) << 4))
+#define netxen_nic_mcr_set_enable_xtnd1(config) \
+ (set_bit(6, (unsigned long *)&(config)))
+#define netxen_nic_mcr_set_id_pool2(config, val) \
+ ((config) |= (((val) & 0x03) << 8))
+#define netxen_nic_mcr_set_enable_xtnd2(config) \
+ (set_bit(10, (unsigned long *)&(config)))
+#define netxen_nic_mcr_set_id_pool3(config, val) \
+ ((config) |= (((val) & 0x03) << 12))
+#define netxen_nic_mcr_set_enable_xtnd3(config) \
+ (set_bit(14, (unsigned long *)&(config)))
+#define netxen_nic_mcr_set_mode_select(config, val) \
+ ((config) |= (((val) & 0x03) << 24))
+#define netxen_nic_mcr_set_enable_pool(config, val) \
+ ((config) |= (((val) & 0x0f) << 28))
+
+/* Set promiscuous mode for a GbE interface */
+int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter, int port,
+ netxen_niu_prom_mode_t mode);
+int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter,
+ int port, netxen_niu_prom_mode_t mode);
+
+/* get/set the MAC address for a given MAC */
+int netxen_niu_macaddr_get(struct netxen_adapter *adapter, int port,
+ netxen_ethernet_macaddr_t * addr);
+int netxen_niu_macaddr_set(struct netxen_port *port,
+ netxen_ethernet_macaddr_t addr);
+
+/* XG versons */
+int netxen_niu_xg_macaddr_get(struct netxen_adapter *adapter, int port,
+ netxen_ethernet_macaddr_t * addr);
+int netxen_niu_xg_macaddr_set(struct netxen_port *port,
+ netxen_ethernet_macaddr_t addr);
+
+/* Generic enable for GbE ports. Will detect the speed of the link. */
+int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port);
+
+int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port);
+
+/* Disable a GbE interface */
+int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter, int port);
+
+int netxen_niu_disable_xg_port(struct netxen_adapter *adapter, int port);
+
+#endif /* __NETXEN_NIC_HW_H_ */
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
new file mode 100644
index 000000000000..0dca029bc3e5
--- /dev/null
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -0,0 +1,1304 @@
+/*
+ * Copyright (C) 2003 - 2006 NetXen, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.
+ *
+ * Contact Information:
+ * info@netxen.com
+ * NetXen,
+ * 3965 Freedom Circle, Fourth floor,
+ * Santa Clara, CA 95054
+ *
+ *
+ * Source file for NIC routines to initialize the Phantom Hardware
+ *
+ */
+
+#include <linux/netdevice.h>
+#include <linux/delay.h>
+#include "netxen_nic.h"
+#include "netxen_nic_hw.h"
+#include "netxen_nic_ioctl.h"
+#include "netxen_nic_phan_reg.h"
+
+struct crb_addr_pair {
+ long addr;
+ long data;
+};
+
+#define NETXEN_MAX_CRB_XFORM 60
+static unsigned int crb_addr_xform[NETXEN_MAX_CRB_XFORM];
+#define NETXEN_ADDR_ERROR ((unsigned long ) 0xffffffff )
+
+#define crb_addr_transform(name) \
+ crb_addr_xform[NETXEN_HW_PX_MAP_CRB_##name] = \
+ NETXEN_HW_CRB_HUB_AGT_ADR_##name << 20
+
+#define NETXEN_NIC_XDMA_RESET 0x8000ff
+
+static inline void
+netxen_nic_locked_write_reg(struct netxen_adapter *adapter,
+ unsigned long off, int *data)
+{
+ void __iomem *addr = pci_base_offset(adapter, off);
+ writel(*data, addr);
+}
+
+static void crb_addr_transform_setup(void)
+{
+ crb_addr_transform(XDMA);
+ crb_addr_transform(TIMR);
+ crb_addr_transform(SRE);
+ crb_addr_transform(SQN3);
+ crb_addr_transform(SQN2);
+ crb_addr_transform(SQN1);
+ crb_addr_transform(SQN0);
+ crb_addr_transform(SQS3);
+ crb_addr_transform(SQS2);
+ crb_addr_transform(SQS1);
+ crb_addr_transform(SQS0);
+ crb_addr_transform(RPMX7);
+ crb_addr_transform(RPMX6);
+ crb_addr_transform(RPMX5);
+ crb_addr_transform(RPMX4);
+ crb_addr_transform(RPMX3);
+ crb_addr_transform(RPMX2);
+ crb_addr_transform(RPMX1);
+ crb_addr_transform(RPMX0);
+ crb_addr_transform(ROMUSB);
+ crb_addr_transform(SN);
+ crb_addr_transform(QMN);
+ crb_addr_transform(QMS);
+ crb_addr_transform(PGNI);
+ crb_addr_transform(PGND);
+ crb_addr_transform(PGN3);
+ crb_addr_transform(PGN2);
+ crb_addr_transform(PGN1);
+ crb_addr_transform(PGN0);
+ crb_addr_transform(PGSI);
+ crb_addr_transform(PGSD);
+ crb_addr_transform(PGS3);
+ crb_addr_transform(PGS2);
+ crb_addr_transform(PGS1);
+ crb_addr_transform(PGS0);
+ crb_addr_transform(PS);
+ crb_addr_transform(PH);
+ crb_addr_transform(NIU);
+ crb_addr_transform(I2Q);
+ crb_addr_transform(EG);
+ crb_addr_transform(MN);
+ crb_addr_transform(MS);
+ crb_addr_transform(CAS2);
+ crb_addr_transform(CAS1);
+ crb_addr_transform(CAS0);
+ crb_addr_transform(CAM);
+ crb_addr_transform(C2C1);
+ crb_addr_transform(C2C0);
+}
+
+int netxen_init_firmware(struct netxen_adapter *adapter)
+{
+ u32 state = 0, loops = 0, err = 0;
+
+ /* Window 1 call */
+ state = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
+
+ if (state == PHAN_INITIALIZE_ACK)
+ return 0;
+
+ while (state != PHAN_INITIALIZE_COMPLETE && loops < 2000) {
+ udelay(100);
+ /* Window 1 call */
+ state = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
+
+ loops++;
+ }
+ if (loops >= 2000) {
+ printk(KERN_ERR "Cmd Peg initialization not complete:%x.\n",
+ state);
+ err = -EIO;
+ return err;
+ }
+ /* Window 1 call */
+ writel(PHAN_INITIALIZE_ACK,
+ NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
+
+ return err;
+}
+
+#define NETXEN_ADDR_LIMIT 0xffffffffULL
+
+void *netxen_alloc(struct pci_dev *pdev, size_t sz, dma_addr_t * ptr,
+ struct pci_dev **used_dev)
+{
+ void *addr;
+
+ addr = pci_alloc_consistent(pdev, sz, ptr);
+ if ((unsigned long long)(*ptr) < NETXEN_ADDR_LIMIT) {
+ *used_dev = pdev;
+ return addr;
+ }
+ pci_free_consistent(pdev, sz, addr, *ptr);
+ addr = pci_alloc_consistent(NULL, sz, ptr);
+ *used_dev = NULL;
+ return addr;
+}
+
+void netxen_initialize_adapter_sw(struct netxen_adapter *adapter)
+{
+ int ctxid, ring;
+ u32 i;
+ u32 num_rx_bufs = 0;
+ struct netxen_rcv_desc_ctx *rcv_desc;
+
+ DPRINTK(INFO, "initializing some queues: %p\n", adapter);
+ for (ctxid = 0; ctxid < MAX_RCV_CTX; ++ctxid) {
+ for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
+ struct netxen_rx_buffer *rx_buf;
+ rcv_desc = &adapter->recv_ctx[ctxid].rcv_desc[ring];
+ rcv_desc->rcv_free = rcv_desc->max_rx_desc_count;
+ rcv_desc->begin_alloc = 0;
+ rx_buf = rcv_desc->rx_buf_arr;
+ num_rx_bufs = rcv_desc->max_rx_desc_count;
+ /*
+ * Now go through all of them, set reference handles
+ * and put them in the queues.
+ */
+ for (i = 0; i < num_rx_bufs; i++) {
+ rx_buf->ref_handle = i;
+ rx_buf->state = NETXEN_BUFFER_FREE;
+
+ DPRINTK(INFO, "Rx buf:ctx%d i(%d) rx_buf:"
+ "%p\n", ctxid, i, rx_buf);
+ rx_buf++;
+ }
+ }
+ }
+ DPRINTK(INFO, "initialized buffers for %s and %s\n",
+ "adapter->free_cmd_buf_list", "adapter->free_rxbuf");
+}
+
+void netxen_initialize_adapter_hw(struct netxen_adapter *adapter)
+{
+ int ports = 0;
+ struct netxen_board_info *board_info = &(adapter->ahw.boardcfg);
+
+ if (netxen_nic_get_board_info(adapter) != 0)
+ printk("%s: Error getting board config info.\n",
+ netxen_nic_driver_name);
+ get_brd_port_by_type(board_info->board_type, &ports);
+ if (ports == 0)
+ printk(KERN_ERR "%s: Unknown board type\n",
+ netxen_nic_driver_name);
+ adapter->ahw.max_ports = ports;
+}
+
+void netxen_initialize_adapter_ops(struct netxen_adapter *adapter)
+{
+ struct netxen_drvops *ops = adapter->ops;
+ switch (adapter->ahw.board_type) {
+ case NETXEN_NIC_GBE:
+ ops->enable_phy_interrupts =
+ netxen_niu_gbe_enable_phy_interrupts;
+ ops->disable_phy_interrupts =
+ netxen_niu_gbe_disable_phy_interrupts;
+ ops->handle_phy_intr = netxen_nic_gbe_handle_phy_intr;
+ ops->macaddr_set = netxen_niu_macaddr_set;
+ ops->set_mtu = netxen_nic_set_mtu_gb;
+ ops->set_promisc = netxen_niu_set_promiscuous_mode;
+ ops->unset_promisc = netxen_niu_set_promiscuous_mode;
+ ops->phy_read = netxen_niu_gbe_phy_read;
+ ops->phy_write = netxen_niu_gbe_phy_write;
+ ops->init_port = netxen_niu_gbe_init_port;
+ ops->init_niu = netxen_nic_init_niu_gb;
+ ops->stop_port = netxen_niu_disable_gbe_port;
+ break;
+
+ case NETXEN_NIC_XGBE:
+ ops->enable_phy_interrupts =
+ netxen_niu_xgbe_enable_phy_interrupts;
+ ops->disable_phy_interrupts =
+ netxen_niu_xgbe_disable_phy_interrupts;
+ ops->handle_phy_intr = netxen_nic_xgbe_handle_phy_intr;
+ ops->macaddr_set = netxen_niu_xg_macaddr_set;
+ ops->set_mtu = netxen_nic_set_mtu_xgb;
+ ops->init_port = netxen_niu_xg_init_port;
+ ops->set_promisc = netxen_niu_xg_set_promiscuous_mode;
+ ops->unset_promisc = netxen_niu_xg_set_promiscuous_mode;
+ ops->stop_port = netxen_niu_disable_xg_port;
+ break;
+
+ default:
+ break;
+ }
+}
+
+/*
+ * netxen_decode_crb_addr(0 - utility to translate from internal Phantom CRB
+ * address to external PCI CRB address.
+ */
+unsigned long netxen_decode_crb_addr(unsigned long addr)
+{
+ int i;
+ unsigned long base_addr, offset, pci_base;
+
+ crb_addr_transform_setup();
+
+ pci_base = NETXEN_ADDR_ERROR;
+ base_addr = addr & 0xfff00000;
+ offset = addr & 0x000fffff;
+
+ for (i = 0; i < NETXEN_MAX_CRB_XFORM; i++) {
+ if (crb_addr_xform[i] == base_addr) {
+ pci_base = i << 20;
+ break;
+ }
+ }
+ if (pci_base == NETXEN_ADDR_ERROR)
+ return pci_base;
+ else
+ return (pci_base + offset);
+}
+
+static long rom_max_timeout = 10000;
+static long rom_lock_timeout = 1000000;
+
+static inline int rom_lock(struct netxen_adapter *adapter)
+{
+ int iter;
+ u32 done = 0;
+ int timeout = 0;
+
+ while (!done) {
+ /* acquire semaphore2 from PCI HW block */
+ netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(PCIE_SEM2_LOCK),
+ &done);
+ if (done == 1)
+ break;
+ if (timeout >= rom_lock_timeout)
+ return -EIO;
+
+ timeout++;
+ /*
+ * Yield CPU
+ */
+ if (!in_atomic())
+ schedule();
+ else {
+ for (iter = 0; iter < 20; iter++)
+ cpu_relax(); /*This a nop instr on i386 */
+ }
+ }
+ netxen_nic_reg_write(adapter, NETXEN_ROM_LOCK_ID, ROM_LOCK_DRIVER);
+ return 0;
+}
+
+int netxen_wait_rom_done(struct netxen_adapter *adapter)
+{
+ long timeout = 0;
+ long done = 0;
+
+ while (done == 0) {
+ done = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_GLB_STATUS);
+ done &= 2;
+ timeout++;
+ if (timeout >= rom_max_timeout) {
+ printk("Timeout reached waiting for rom done");
+ return -EIO;
+ }
+ }
+ return 0;
+}
+
+static inline int netxen_rom_wren(struct netxen_adapter *adapter)
+{
+ /* Set write enable latch in ROM status register */
+ netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0);
+ netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE,
+ M25P_INSTR_WREN);
+ if (netxen_wait_rom_done(adapter)) {
+ return -1;
+ }
+ return 0;
+}
+
+static inline unsigned int netxen_rdcrbreg(struct netxen_adapter *adapter,
+ unsigned int addr)
+{
+ unsigned int data = 0xdeaddead;
+ data = netxen_nic_reg_read(adapter, addr);
+ return data;
+}
+
+static inline int netxen_do_rom_rdsr(struct netxen_adapter *adapter)
+{
+ netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE,
+ M25P_INSTR_RDSR);
+ if (netxen_wait_rom_done(adapter)) {
+ return -1;
+ }
+ return netxen_rdcrbreg(adapter, NETXEN_ROMUSB_ROM_RDATA);
+}
+
+static inline void netxen_rom_unlock(struct netxen_adapter *adapter)
+{
+ u32 val;
+
+ /* release semaphore2 */
+ netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(PCIE_SEM2_UNLOCK), &val);
+
+}
+
+int netxen_rom_wip_poll(struct netxen_adapter *adapter)
+{
+ long timeout = 0;
+ long wip = 1;
+ int val;
+ netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0);
+ while (wip != 0) {
+ val = netxen_do_rom_rdsr(adapter);
+ wip = val & 1;
+ timeout++;
+ if (timeout > rom_max_timeout) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static inline int do_rom_fast_write(struct netxen_adapter *adapter,
+ int addr, int data)
+{
+ if (netxen_rom_wren(adapter)) {
+ return -1;
+ }
+ netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_WDATA, data);
+ netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr);
+ netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3);
+ netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE,
+ M25P_INSTR_PP);
+ if (netxen_wait_rom_done(adapter)) {
+ netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0);
+ return -1;
+ }
+
+ return netxen_rom_wip_poll(adapter);
+}
+
+static inline int
+do_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp)
+{
+ netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr);
+ netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3);
+ udelay(100); /* prevent bursting on CRB */
+ netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
+ netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, 0xb);
+ if (netxen_wait_rom_done(adapter)) {
+ printk("Error waiting for rom done\n");
+ return -EIO;
+ }
+ /* reset abyte_cnt and dummy_byte_cnt */
+ netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0);
+ udelay(100); /* prevent bursting on CRB */
+ netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
+
+ *valp = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_ROM_RDATA);
+ return 0;
+}
+
+int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp)
+{
+ int ret;
+
+ if (rom_lock(adapter) != 0)
+ return -EIO;
+
+ ret = do_rom_fast_read(adapter, addr, valp);
+ netxen_rom_unlock(adapter);
+ return ret;
+}
+
+int netxen_rom_fast_write(struct netxen_adapter *adapter, int addr, int data)
+{
+ int ret = 0;
+
+ if (rom_lock(adapter) != 0) {
+ return -1;
+ }
+ ret = do_rom_fast_write(adapter, addr, data);
+ netxen_rom_unlock(adapter);
+ return ret;
+}
+int netxen_do_rom_se(struct netxen_adapter *adapter, int addr)
+{
+ netxen_rom_wren(adapter);
+ netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr);
+ netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3);
+ netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE,
+ M25P_INSTR_SE);
+ if (netxen_wait_rom_done(adapter)) {
+ netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0);
+ return -1;
+ }
+ return netxen_rom_wip_poll(adapter);
+}
+
+int netxen_rom_se(struct netxen_adapter *adapter, int addr)
+{
+ int ret = 0;
+ if (rom_lock(adapter) != 0) {
+ return -1;
+ }
+ ret = netxen_do_rom_se(adapter, addr);
+ netxen_rom_unlock(adapter);
+ return ret;
+}
+
+#define NETXEN_BOARDTYPE 0x4008
+#define NETXEN_BOARDNUM 0x400c
+#define NETXEN_CHIPNUM 0x4010
+#define NETXEN_ROMBUS_RESET 0xFFFFFFFF
+#define NETXEN_ROM_FIRST_BARRIER 0x800000000ULL
+#define NETXEN_ROM_FOUND_INIT 0x400
+
+int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
+{
+ int addr, val, status;
+ int n, i;
+ int init_delay = 0;
+ struct crb_addr_pair *buf;
+ unsigned long off;
+
+ /* resetall */
+ status = netxen_nic_get_board_info(adapter);
+ if (status)
+ printk("%s: netxen_pinit_from_rom: Error getting board info\n",
+ netxen_nic_driver_name);
+
+ netxen_crb_writelit_adapter(adapter, NETXEN_ROMUSB_GLB_SW_RESET,
+ NETXEN_ROMBUS_RESET);
+
+ if (verbose) {
+ int val;
+ if (netxen_rom_fast_read(adapter, NETXEN_BOARDTYPE, &val) == 0)
+ printk("P2 ROM board type: 0x%08x\n", val);
+ else
+ printk("Could not read board type\n");
+ if (netxen_rom_fast_read(adapter, NETXEN_BOARDNUM, &val) == 0)
+ printk("P2 ROM board num: 0x%08x\n", val);
+ else
+ printk("Could not read board number\n");
+ if (netxen_rom_fast_read(adapter, NETXEN_CHIPNUM, &val) == 0)
+ printk("P2 ROM chip num: 0x%08x\n", val);
+ else
+ printk("Could not read chip number\n");
+ }
+
+ if (netxen_rom_fast_read(adapter, 0, &n) == 0
+ && (n & NETXEN_ROM_FIRST_BARRIER)) {
+ n &= ~NETXEN_ROM_ROUNDUP;
+ if (n < NETXEN_ROM_FOUND_INIT) {
+ if (verbose)
+ printk("%s: %d CRB init values found"
+ " in ROM.\n", netxen_nic_driver_name, n);
+ } else {
+ printk("%s:n=0x%x Error! NetXen card flash not"
+ " initialized.\n", __FUNCTION__, n);
+ return -EIO;
+ }
+ buf = kcalloc(n, sizeof(struct crb_addr_pair), GFP_KERNEL);
+ if (buf == NULL) {
+ printk("%s: netxen_pinit_from_rom: Unable to calloc "
+ "memory.\n", netxen_nic_driver_name);
+ return -ENOMEM;
+ }
+ for (i = 0; i < n; i++) {
+ if (netxen_rom_fast_read(adapter, 8 * i + 4, &val) != 0
+ || netxen_rom_fast_read(adapter, 8 * i + 8,
+ &addr) != 0)
+ return -EIO;
+
+ buf[i].addr = addr;
+ buf[i].data = val;
+
+ if (verbose)
+ printk("%s: PCI: 0x%08x == 0x%08x\n",
+ netxen_nic_driver_name, (unsigned int)
+ netxen_decode_crb_addr((unsigned long)
+ addr), val);
+ }
+ for (i = 0; i < n; i++) {
+
+ off =
+ netxen_decode_crb_addr((unsigned long)buf[i].addr) +
+ NETXEN_PCI_CRBSPACE;
+ /* skipping cold reboot MAGIC */
+ if (off == NETXEN_CAM_RAM(0x1fc))
+ continue;
+
+ /* After writing this register, HW needs time for CRB */
+ /* to quiet down (else crb_window returns 0xffffffff) */
+ if (off == NETXEN_ROMUSB_GLB_SW_RESET) {
+ init_delay = 1;
+ /* hold xdma in reset also */
+ buf[i].data = NETXEN_NIC_XDMA_RESET;
+ }
+
+ if (ADDR_IN_WINDOW1(off)) {
+ writel(buf[i].data,
+ NETXEN_CRB_NORMALIZE(adapter, off));
+ } else {
+ netxen_nic_pci_change_crbwindow(adapter, 0);
+ writel(buf[i].data,
+ pci_base_offset(adapter, off));
+
+ netxen_nic_pci_change_crbwindow(adapter, 1);
+ }
+ if (init_delay == 1) {
+ ssleep(1);
+ init_delay = 0;
+ }
+ msleep(1);
+ }
+ kfree(buf);
+
+ /* disable_peg_cache_all */
+
+ /* unreset_net_cache */
+ netxen_nic_hw_read_wx(adapter, NETXEN_ROMUSB_GLB_SW_RESET, &val,
+ 4);
+ netxen_crb_writelit_adapter(adapter, NETXEN_ROMUSB_GLB_SW_RESET,
+ (val & 0xffffff0f));
+ /* p2dn replyCount */
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_CRB_PEG_NET_D + 0xec, 0x1e);
+ /* disable_peg_cache 0 */
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_CRB_PEG_NET_D + 0x4c, 8);
+ /* disable_peg_cache 1 */
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_CRB_PEG_NET_I + 0x4c, 8);
+
+ /* peg_clr_all */
+
+ /* peg_clr 0 */
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0x8,
+ 0);
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0xc,
+ 0);
+ /* peg_clr 1 */
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0x8,
+ 0);
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0xc,
+ 0);
+ /* peg_clr 2 */
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0x8,
+ 0);
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0xc,
+ 0);
+ /* peg_clr 3 */
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0x8,
+ 0);
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0xc,
+ 0);
+ }
+ return 0;
+}
+
+void netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val)
+{
+ u32 val = 0;
+ int loops = 0;
+
+ if (!pegtune_val) {
+ while (val != PHAN_INITIALIZE_COMPLETE && loops < 200000) {
+ udelay(100);
+ schedule();
+ val =
+ readl(NETXEN_CRB_NORMALIZE
+ (adapter, CRB_CMDPEG_STATE));
+ loops++;
+ }
+ if (val != PHAN_INITIALIZE_COMPLETE)
+ printk("WARNING: Initial boot wait loop failed...\n");
+ }
+}
+
+int netxen_nic_rx_has_work(struct netxen_adapter *adapter)
+{
+ int ctx;
+
+ for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
+ struct netxen_recv_context *recv_ctx =
+ &(adapter->recv_ctx[ctx]);
+ u32 consumer;
+ struct status_desc *desc_head;
+ struct status_desc *desc;
+
+ consumer = recv_ctx->status_rx_consumer;
+ desc_head = recv_ctx->rcv_status_desc_head;
+ desc = &desc_head[consumer];
+
+ if (((le16_to_cpu(desc->owner)) & STATUS_OWNER_HOST))
+ return 1;
+ }
+
+ return 0;
+}
+
+static inline int netxen_nic_check_temp(struct netxen_adapter *adapter)
+{
+ int port_num;
+ struct netxen_port *port;
+ struct net_device *netdev;
+ uint32_t temp, temp_state, temp_val;
+ int rv = 0;
+
+ temp = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_TEMP_STATE));
+
+ temp_state = nx_get_temp_state(temp);
+ temp_val = nx_get_temp_val(temp);
+
+ if (temp_state == NX_TEMP_PANIC) {
+ printk(KERN_ALERT
+ "%s: Device temperature %d degrees C exceeds"
+ " maximum allowed. Hardware has been shut down.\n",
+ netxen_nic_driver_name, temp_val);
+ for (port_num = 0; port_num < adapter->ahw.max_ports;
+ port_num++) {
+ port = adapter->port[port_num];
+ netdev = port->netdev;
+
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+ }
+ rv = 1;
+ } else if (temp_state == NX_TEMP_WARN) {
+ if (adapter->temp == NX_TEMP_NORMAL) {
+ printk(KERN_ALERT
+ "%s: Device temperature %d degrees C "
+ "exceeds operating range."
+ " Immediate action needed.\n",
+ netxen_nic_driver_name, temp_val);
+ }
+ } else {
+ if (adapter->temp == NX_TEMP_WARN) {
+ printk(KERN_INFO
+ "%s: Device temperature is now %d degrees C"
+ " in normal range.\n", netxen_nic_driver_name,
+ temp_val);
+ }
+ }
+ adapter->temp = temp_state;
+ return rv;
+}
+
+void netxen_watchdog_task(unsigned long v)
+{
+ int port_num;
+ struct netxen_port *port;
+ struct net_device *netdev;
+ struct netxen_adapter *adapter = (struct netxen_adapter *)v;
+
+ if (netxen_nic_check_temp(adapter))
+ return;
+
+ for (port_num = 0; port_num < adapter->ahw.max_ports; port_num++) {
+ port = adapter->port[port_num];
+ netdev = port->netdev;
+
+ if ((netif_running(netdev)) && !netif_carrier_ok(netdev)) {
+ printk(KERN_INFO "%s port %d, %s carrier is now ok\n",
+ netxen_nic_driver_name, port_num, netdev->name);
+ netif_carrier_on(netdev);
+ }
+
+ if (netif_queue_stopped(netdev))
+ netif_wake_queue(netdev);
+ }
+
+ if (adapter->ops->handle_phy_intr)
+ adapter->ops->handle_phy_intr(adapter);
+ mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
+}
+
+/*
+ * netxen_process_rcv() send the received packet to the protocol stack.
+ * and if the number of receives exceeds RX_BUFFERS_REFILL, then we
+ * invoke the routine to send more rx buffers to the Phantom...
+ */
+void
+netxen_process_rcv(struct netxen_adapter *adapter, int ctxid,
+ struct status_desc *desc)
+{
+ struct netxen_port *port = adapter->port[STATUS_DESC_PORT(desc)];
+ struct pci_dev *pdev = port->pdev;
+ struct net_device *netdev = port->netdev;
+ int index = le16_to_cpu(desc->reference_handle);
+ struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctxid]);
+ struct netxen_rx_buffer *buffer;
+ struct sk_buff *skb;
+ u32 length = le16_to_cpu(desc->total_length);
+ u32 desc_ctx;
+ struct netxen_rcv_desc_ctx *rcv_desc;
+ int ret;
+
+ desc_ctx = STATUS_DESC_TYPE(desc);
+ if (unlikely(desc_ctx >= NUM_RCV_DESC_RINGS)) {
+ printk("%s: %s Bad Rcv descriptor ring\n",
+ netxen_nic_driver_name, netdev->name);
+ return;
+ }
+
+ rcv_desc = &recv_ctx->rcv_desc[desc_ctx];
+ buffer = &rcv_desc->rx_buf_arr[index];
+
+ pci_unmap_single(pdev, buffer->dma, rcv_desc->dma_size,
+ PCI_DMA_FROMDEVICE);
+
+ skb = (struct sk_buff *)buffer->skb;
+
+ if (likely(STATUS_DESC_STATUS(desc) == STATUS_CKSUM_OK)) {
+ port->stats.csummed++;
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ } else
+ skb->ip_summed = CHECKSUM_NONE;
+ skb->dev = netdev;
+ skb_put(skb, length);
+ skb->protocol = eth_type_trans(skb, netdev);
+
+ ret = netif_receive_skb(skb);
+
+ /*
+ * RH: Do we need these stats on a regular basis. Can we get it from
+ * Linux stats.
+ */
+ switch (ret) {
+ case NET_RX_SUCCESS:
+ port->stats.uphappy++;
+ break;
+
+ case NET_RX_CN_LOW:
+ port->stats.uplcong++;
+ break;
+
+ case NET_RX_CN_MOD:
+ port->stats.upmcong++;
+ break;
+
+ case NET_RX_CN_HIGH:
+ port->stats.uphcong++;
+ break;
+
+ case NET_RX_DROP:
+ port->stats.updropped++;
+ break;
+
+ default:
+ port->stats.updunno++;
+ break;
+ }
+
+ netdev->last_rx = jiffies;
+
+ rcv_desc->rcv_free++;
+ rcv_desc->rcv_pending--;
+
+ /*
+ * We just consumed one buffer so post a buffer.
+ */
+ adapter->stats.post_called++;
+ buffer->skb = NULL;
+ buffer->state = NETXEN_BUFFER_FREE;
+
+ port->stats.no_rcv++;
+ port->stats.rxbytes += length;
+}
+
+/* Process Receive status ring */
+u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max)
+{
+ struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctxid]);
+ struct status_desc *desc_head = recv_ctx->rcv_status_desc_head;
+ struct status_desc *desc; /* used to read status desc here */
+ u32 consumer = recv_ctx->status_rx_consumer;
+ int count = 0, ring;
+
+ DPRINTK(INFO, "procesing receive\n");
+ /*
+ * we assume in this case that there is only one port and that is
+ * port #1...changes need to be done in firmware to indicate port
+ * number as part of the descriptor. This way we will be able to get
+ * the netdev which is associated with that device.
+ */
+ while (count < max) {
+ desc = &desc_head[consumer];
+ if (!((le16_to_cpu(desc->owner)) & STATUS_OWNER_HOST)) {
+ DPRINTK(ERR, "desc %p ownedby %x\n", desc, desc->owner);
+ break;
+ }
+ netxen_process_rcv(adapter, ctxid, desc);
+ desc->owner = STATUS_OWNER_PHANTOM;
+ consumer = (consumer + 1) & (adapter->max_rx_desc_count - 1);
+ count++;
+ }
+ if (count) {
+ for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
+ netxen_post_rx_buffers(adapter, ctxid, ring);
+ }
+ }
+
+ /* update the consumer index in phantom */
+ if (count) {
+ adapter->stats.process_rcv++;
+ recv_ctx->status_rx_consumer = consumer;
+
+ /* Window = 1 */
+ writel(consumer,
+ NETXEN_CRB_NORMALIZE(adapter,
+ recv_crb_registers[ctxid].
+ crb_rcv_status_consumer));
+ }
+
+ return count;
+}
+
+/* Process Command status ring */
+void netxen_process_cmd_ring(unsigned long data)
+{
+ u32 last_consumer;
+ u32 consumer;
+ struct netxen_adapter *adapter = (struct netxen_adapter *)data;
+ int count = 0;
+ struct netxen_cmd_buffer *buffer;
+ struct netxen_port *port; /* port #1 */
+ struct netxen_port *nport;
+ struct pci_dev *pdev;
+ struct netxen_skb_frag *frag;
+ u32 i;
+ struct sk_buff *skb = NULL;
+ int p;
+
+ spin_lock(&adapter->tx_lock);
+ last_consumer = adapter->last_cmd_consumer;
+ DPRINTK(INFO, "procesing xmit complete\n");
+ /* we assume in this case that there is only one port and that is
+ * port #1...changes need to be done in firmware to indicate port
+ * number as part of the descriptor. This way we will be able to get
+ * the netdev which is associated with that device.
+ */
+ consumer =
+ readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMD_CONSUMER_OFFSET));
+
+ if (last_consumer == consumer) { /* Ring is empty */
+ DPRINTK(INFO, "last_consumer %d == consumer %d\n",
+ last_consumer, consumer);
+ spin_unlock(&adapter->tx_lock);
+ return;
+ }
+
+ adapter->proc_cmd_buf_counter++;
+ adapter->stats.process_xmit++;
+ /*
+ * Not needed - does not seem to be used anywhere.
+ * adapter->cmd_consumer = consumer;
+ */
+ spin_unlock(&adapter->tx_lock);
+
+ while ((last_consumer != consumer) && (count < MAX_STATUS_HANDLE)) {
+ buffer = &adapter->cmd_buf_arr[last_consumer];
+ port = adapter->port[buffer->port];
+ pdev = port->pdev;
+ frag = &buffer->frag_array[0];
+ skb = buffer->skb;
+ if (skb && (cmpxchg(&buffer->skb, skb, 0) == skb)) {
+ pci_unmap_single(pdev, frag->dma, frag->length,
+ PCI_DMA_TODEVICE);
+ for (i = 1; i < buffer->frag_count; i++) {
+ DPRINTK(INFO, "getting fragment no %d\n", i);
+ frag++; /* Get the next frag */
+ pci_unmap_page(pdev, frag->dma, frag->length,
+ PCI_DMA_TODEVICE);
+ }
+
+ port->stats.skbfreed++;
+ dev_kfree_skb_any(skb);
+ skb = NULL;
+ } else if (adapter->proc_cmd_buf_counter == 1) {
+ port->stats.txnullskb++;
+ }
+ if (unlikely(netif_queue_stopped(port->netdev)
+ && netif_carrier_ok(port->netdev))
+ && ((jiffies - port->netdev->trans_start) >
+ port->netdev->watchdog_timeo)) {
+ schedule_work(&port->adapter->tx_timeout_task);
+ }
+
+ last_consumer = get_next_index(last_consumer,
+ adapter->max_tx_desc_count);
+ count++;
+ }
+ adapter->stats.noxmitdone += count;
+
+ count = 0;
+ spin_lock(&adapter->tx_lock);
+ if ((--adapter->proc_cmd_buf_counter) == 0) {
+ adapter->last_cmd_consumer = last_consumer;
+ while ((adapter->last_cmd_consumer != consumer)
+ && (count < MAX_STATUS_HANDLE)) {
+ buffer =
+ &adapter->cmd_buf_arr[adapter->last_cmd_consumer];
+ count++;
+ if (buffer->skb)
+ break;
+ else
+ adapter->last_cmd_consumer =
+ get_next_index(adapter->last_cmd_consumer,
+ adapter->max_tx_desc_count);
+ }
+ }
+ if (count) {
+ for (p = 0; p < adapter->ahw.max_ports; p++) {
+ nport = adapter->port[p];
+ if (netif_queue_stopped(nport->netdev)
+ && (nport->flags & NETXEN_NETDEV_STATUS)) {
+ netif_wake_queue(nport->netdev);
+ nport->flags &= ~NETXEN_NETDEV_STATUS;
+ }
+ }
+ }
+
+ spin_unlock(&adapter->tx_lock);
+ DPRINTK(INFO, "last consumer is %d in %s\n", last_consumer,
+ __FUNCTION__);
+}
+
+/*
+ * netxen_post_rx_buffers puts buffer in the Phantom memory
+ */
+void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
+{
+ struct pci_dev *pdev = adapter->ahw.pdev;
+ struct sk_buff *skb;
+ struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctx]);
+ struct netxen_rcv_desc_ctx *rcv_desc = NULL;
+ struct netxen_recv_crb *crbarea = &recv_crb_registers[ctx];
+ struct netxen_rcv_desc_crb *rcv_desc_crb = NULL;
+ u32 producer;
+ struct rcv_desc *pdesc;
+ struct netxen_rx_buffer *buffer;
+ int count = 0;
+ int index = 0;
+
+ adapter->stats.post_called++;
+ rcv_desc = &recv_ctx->rcv_desc[ringid];
+ rcv_desc_crb = &crbarea->rcv_desc_crb[ringid];
+
+ producer = rcv_desc->producer;
+ index = rcv_desc->begin_alloc;
+ buffer = &rcv_desc->rx_buf_arr[index];
+ /* We can start writing rx descriptors into the phantom memory. */
+ while (buffer->state == NETXEN_BUFFER_FREE) {
+ skb = dev_alloc_skb(rcv_desc->skb_size);
+ if (unlikely(!skb)) {
+ /*
+ * We need to schedule the posting of buffers to the pegs.
+ */
+ rcv_desc->begin_alloc = index;
+ DPRINTK(ERR, "netxen_post_rx_buffers: "
+ " allocated only %d buffers\n", count);
+ break;
+ }
+ count++; /* now there should be no failure */
+ pdesc = &rcv_desc->desc_head[producer];
+ skb_reserve(skb, NET_IP_ALIGN);
+ /*
+ * This will be setup when we receive the
+ * buffer after it has been filled
+ * skb->dev = netdev;
+ */
+ buffer->skb = skb;
+ buffer->state = NETXEN_BUFFER_BUSY;
+ buffer->dma = pci_map_single(pdev, skb->data,
+ rcv_desc->dma_size,
+ PCI_DMA_FROMDEVICE);
+ /* make a rcv descriptor */
+ pdesc->reference_handle = le16_to_cpu(buffer->ref_handle);
+ pdesc->buffer_length = le16_to_cpu(rcv_desc->dma_size);
+ pdesc->addr_buffer = cpu_to_le64(buffer->dma);
+ DPRINTK(INFO, "done writing descripter\n");
+ producer =
+ get_next_index(producer, rcv_desc->max_rx_desc_count);
+ index = get_next_index(index, rcv_desc->max_rx_desc_count);
+ buffer = &rcv_desc->rx_buf_arr[index];
+ }
+
+ /* if we did allocate buffers, then write the count to Phantom */
+ if (count) {
+ rcv_desc->begin_alloc = index;
+ rcv_desc->rcv_pending += count;
+ adapter->stats.lastposted = count;
+ adapter->stats.posted += count;
+ rcv_desc->producer = producer;
+ if (rcv_desc->rcv_free >= 32) {
+ rcv_desc->rcv_free = 0;
+ /* Window = 1 */
+ writel((producer - 1) &
+ (rcv_desc->max_rx_desc_count - 1),
+ NETXEN_CRB_NORMALIZE(adapter,
+ rcv_desc_crb->
+ crb_rcv_producer_offset));
+ wmb();
+ }
+ }
+}
+
+int netxen_nic_tx_has_work(struct netxen_adapter *adapter)
+{
+ if (find_diff_among(adapter->last_cmd_consumer,
+ adapter->cmd_producer,
+ adapter->max_tx_desc_count) > 0)
+ return 1;
+
+ return 0;
+}
+
+int
+netxen_nic_fill_statistics(struct netxen_adapter *adapter,
+ struct netxen_port *port,
+ struct netxen_statistics *netxen_stats)
+{
+ void __iomem *addr;
+
+ if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
+ netxen_nic_pci_change_crbwindow(adapter, 0);
+ NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_TX_BYTE_CNT,
+ &(netxen_stats->tx_bytes));
+ NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_TX_FRAME_CNT,
+ &(netxen_stats->tx_packets));
+ NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_RX_BYTE_CNT,
+ &(netxen_stats->rx_bytes));
+ NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_RX_FRAME_CNT,
+ &(netxen_stats->rx_packets));
+ NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_AGGR_ERROR_CNT,
+ &(netxen_stats->rx_errors));
+ NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_CRC_ERROR_CNT,
+ &(netxen_stats->rx_crc_errors));
+ NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_OVERSIZE_FRAME_ERR,
+ &(netxen_stats->
+ rx_long_length_error));
+ NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_UNDERSIZE_FRAME_ERR,
+ &(netxen_stats->
+ rx_short_length_error));
+
+ netxen_nic_pci_change_crbwindow(adapter, 1);
+ } else {
+ spin_lock_bh(&adapter->tx_lock);
+ netxen_stats->tx_bytes = port->stats.txbytes;
+ netxen_stats->tx_packets = port->stats.xmitedframes +
+ port->stats.xmitfinished;
+ netxen_stats->rx_bytes = port->stats.rxbytes;
+ netxen_stats->rx_packets = port->stats.no_rcv;
+ netxen_stats->rx_errors = port->stats.rcvdbadskb;
+ netxen_stats->tx_errors = port->stats.nocmddescriptor;
+ netxen_stats->rx_short_length_error = port->stats.uplcong;
+ netxen_stats->rx_long_length_error = port->stats.uphcong;
+ netxen_stats->rx_crc_errors = 0;
+ netxen_stats->rx_mac_errors = 0;
+ spin_unlock_bh(&adapter->tx_lock);
+ }
+ return 0;
+}
+
+void netxen_nic_clear_stats(struct netxen_adapter *adapter)
+{
+ struct netxen_port *port;
+ int port_num;
+
+ memset(&adapter->stats, 0, sizeof(adapter->stats));
+ for (port_num = 0; port_num < adapter->ahw.max_ports; port_num++) {
+ port = adapter->port[port_num];
+ memset(&port->stats, 0, sizeof(port->stats));
+ }
+}
+
+int
+netxen_nic_clear_statistics(struct netxen_adapter *adapter,
+ struct netxen_port *port)
+{
+ int data = 0;
+
+ netxen_nic_pci_change_crbwindow(adapter, 0);
+
+ netxen_nic_locked_write_reg(adapter, NETXEN_NIU_XGE_TX_BYTE_CNT, &data);
+ netxen_nic_locked_write_reg(adapter, NETXEN_NIU_XGE_TX_FRAME_CNT,
+ &data);
+ netxen_nic_locked_write_reg(adapter, NETXEN_NIU_XGE_RX_BYTE_CNT, &data);
+ netxen_nic_locked_write_reg(adapter, NETXEN_NIU_XGE_RX_FRAME_CNT,
+ &data);
+ netxen_nic_locked_write_reg(adapter, NETXEN_NIU_XGE_AGGR_ERROR_CNT,
+ &data);
+ netxen_nic_locked_write_reg(adapter, NETXEN_NIU_XGE_CRC_ERROR_CNT,
+ &data);
+ netxen_nic_locked_write_reg(adapter, NETXEN_NIU_XGE_OVERSIZE_FRAME_ERR,
+ &data);
+ netxen_nic_locked_write_reg(adapter, NETXEN_NIU_XGE_UNDERSIZE_FRAME_ERR,
+ &data);
+
+ netxen_nic_pci_change_crbwindow(adapter, 1);
+ netxen_nic_clear_stats(adapter);
+ return 0;
+}
+
+int
+netxen_nic_do_ioctl(struct netxen_adapter *adapter, void *u_data,
+ struct netxen_port *port)
+{
+ struct netxen_nic_ioctl_data data;
+ struct netxen_nic_ioctl_data *up_data;
+ int retval = 0;
+ struct netxen_statistics netxen_stats;
+
+ up_data = (void *)u_data;
+
+ DPRINTK(INFO, "doing ioctl for %p\n", adapter);
+ if (copy_from_user(&data, (void __user *)up_data, sizeof(data))) {
+ /* evil user tried to crash the kernel */
+ DPRINTK(ERR, "bad copy from userland: %d\n", (int)sizeof(data));
+ retval = -EFAULT;
+ goto error_out;
+ }
+
+ /* Shouldn't access beyond legal limits of "char u[64];" member */
+ if (!data.ptr && (data.size > sizeof(data.u))) {
+ /* evil user tried to crash the kernel */
+ DPRINTK(ERR, "bad size: %d\n", data.size);
+ retval = -EFAULT;
+ goto error_out;
+ }
+
+ switch (data.cmd) {
+ case netxen_nic_cmd_pci_read:
+ if ((retval = netxen_nic_hw_read_wx(adapter, data.off,
+ &(data.u), data.size)))
+ goto error_out;
+ if (copy_to_user
+ ((void __user *)&(up_data->u), &(data.u), data.size)) {
+ DPRINTK(ERR, "bad copy to userland: %d\n",
+ (int)sizeof(data));
+ retval = -EFAULT;
+ goto error_out;
+ }
+ data.rv = 0;
+ break;
+
+ case netxen_nic_cmd_pci_write:
+ data.rv = netxen_nic_hw_write_wx(adapter, data.off, &(data.u),
+ data.size);
+ break;
+
+ case netxen_nic_cmd_pci_config_read:
+ switch (data.size) {
+ case 1:
+ data.rv = pci_read_config_byte(adapter->ahw.pdev,
+ data.off,
+ (char *)&(data.u));
+ break;
+ case 2:
+ data.rv = pci_read_config_word(adapter->ahw.pdev,
+ data.off,
+ (short *)&(data.u));
+ break;
+ case 4:
+ data.rv = pci_read_config_dword(adapter->ahw.pdev,
+ data.off,
+ (u32 *) & (data.u));
+ break;
+ }
+ if (copy_to_user
+ ((void __user *)&(up_data->u), &(data.u), data.size)) {
+ DPRINTK(ERR, "bad copy to userland: %d\n",
+ (int)sizeof(data));
+ retval = -EFAULT;
+ goto error_out;
+ }
+ break;
+
+ case netxen_nic_cmd_pci_config_write:
+ switch (data.size) {
+ case 1:
+ data.rv = pci_write_config_byte(adapter->ahw.pdev,
+ data.off,
+ *(char *)&(data.u));
+ break;
+ case 2:
+ data.rv = pci_write_config_word(adapter->ahw.pdev,
+ data.off,
+ *(short *)&(data.u));
+ break;
+ case 4:
+ data.rv = pci_write_config_dword(adapter->ahw.pdev,
+ data.off,
+ *(u32 *) & (data.u));
+ break;
+ }
+ break;
+
+ case netxen_nic_cmd_get_stats:
+ data.rv =
+ netxen_nic_fill_statistics(adapter, port, &netxen_stats);
+ if (copy_to_user
+ ((void __user *)(up_data->ptr), (void *)&netxen_stats,
+ sizeof(struct netxen_statistics))) {
+ DPRINTK(ERR, "bad copy to userland: %d\n",
+ (int)sizeof(netxen_stats));
+ retval = -EFAULT;
+ goto error_out;
+ }
+ up_data->rv = data.rv;
+ break;
+
+ case netxen_nic_cmd_clear_stats:
+ data.rv = netxen_nic_clear_statistics(adapter, port);
+ up_data->rv = data.rv;
+ break;
+
+ case netxen_nic_cmd_get_version:
+ if (copy_to_user
+ ((void __user *)&(up_data->u), NETXEN_NIC_LINUX_VERSIONID,
+ sizeof(NETXEN_NIC_LINUX_VERSIONID))) {
+ DPRINTK(ERR, "bad copy to userland: %d\n",
+ (int)sizeof(data));
+ retval = -EFAULT;
+ goto error_out;
+ }
+ break;
+
+ default:
+ DPRINTK(INFO, "bad command %d for %p\n", data.cmd, adapter);
+ retval = -EOPNOTSUPP;
+ goto error_out;
+ }
+ put_user(data.rv, (u16 __user *) (&(up_data->rv)));
+ DPRINTK(INFO, "done ioctl for %p well.\n", adapter);
+
+ error_out:
+ return retval;
+}
diff --git a/drivers/net/netxen/netxen_nic_ioctl.h b/drivers/net/netxen/netxen_nic_ioctl.h
new file mode 100644
index 000000000000..23e53adbf123
--- /dev/null
+++ b/drivers/net/netxen/netxen_nic_ioctl.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2003 - 2006 NetXen, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.
+ *
+ * Contact Information:
+ * info@netxen.com
+ * NetXen,
+ * 3965 Freedom Circle, Fourth floor,
+ * Santa Clara, CA 95054
+ */
+
+#ifndef __NETXEN_NIC_IOCTL_H__
+#define __NETXEN_NIC_IOCTL_H__
+
+#include <linux/sockios.h>
+
+#define NETXEN_CMD_START SIOCDEVPRIVATE
+#define NETXEN_NIC_CMD (NETXEN_CMD_START + 1)
+#define NETXEN_NIC_NAME (NETXEN_CMD_START + 2)
+#define NETXEN_NIC_NAME_LEN 16
+#define NETXEN_NIC_NAME_RSP "NETXEN"
+
+typedef enum {
+ netxen_nic_cmd_none = 0,
+ netxen_nic_cmd_pci_read,
+ netxen_nic_cmd_pci_write,
+ netxen_nic_cmd_pci_mem_read,
+ netxen_nic_cmd_pci_mem_write,
+ netxen_nic_cmd_pci_config_read,
+ netxen_nic_cmd_pci_config_write,
+ netxen_nic_cmd_get_stats,
+ netxen_nic_cmd_clear_stats,
+ netxen_nic_cmd_get_version
+} netxen_nic_ioctl_cmd_t;
+
+struct netxen_nic_ioctl_data {
+ u32 cmd;
+ u32 unused1;
+ u64 off;
+ u32 size;
+ u32 rv;
+ char u[64];
+ void *ptr;
+};
+
+struct netxen_statistics {
+ u64 rx_packets;
+ u64 tx_packets;
+ u64 rx_bytes;
+ u64 rx_errors;
+ u64 tx_bytes;
+ u64 tx_errors;
+ u64 rx_crc_errors;
+ u64 rx_short_length_error;
+ u64 rx_long_length_error;
+ u64 rx_mac_errors;
+};
+
+#endif /* __NETXEN_NIC_IOCTL_H_ */
diff --git a/drivers/net/netxen/netxen_nic_isr.c b/drivers/net/netxen/netxen_nic_isr.c
new file mode 100644
index 000000000000..ae180fee8008
--- /dev/null
+++ b/drivers/net/netxen/netxen_nic_isr.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2003 - 2006 NetXen, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.
+ *
+ * Contact Information:
+ * info@netxen.com
+ * NetXen,
+ * 3965 Freedom Circle, Fourth floor,
+ * Santa Clara, CA 95054
+ */
+
+#include <linux/netdevice.h>
+#include <linux/delay.h>
+
+#include "netxen_nic.h"
+#include "netxen_nic_hw.h"
+#include "netxen_nic_phan_reg.h"
+
+/*
+ * netxen_nic_get_stats - Get System Network Statistics
+ * @netdev: network interface device structure
+ */
+struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
+{
+ struct netxen_port *port = netdev_priv(netdev);
+ struct net_device_stats *stats = &port->net_stats;
+
+ memset(stats, 0, sizeof(*stats));
+
+ /* total packets received */
+ stats->rx_packets = port->stats.no_rcv;
+ /* total packets transmitted */
+ stats->tx_packets = port->stats.xmitedframes + port->stats.xmitfinished;
+ /* total bytes received */
+ stats->rx_bytes = port->stats.rxbytes;
+ /* total bytes transmitted */
+ stats->tx_bytes = port->stats.txbytes;
+ /* bad packets received */
+ stats->rx_errors = port->stats.rcvdbadskb;
+ /* packet transmit problems */
+ stats->tx_errors = port->stats.nocmddescriptor;
+ /* no space in linux buffers */
+ stats->rx_dropped = port->stats.updropped;
+ /* no space available in linux */
+ stats->tx_dropped = port->stats.txdropped;
+
+ return stats;
+}
+
+void netxen_indicate_link_status(struct netxen_adapter *adapter, u32 portno,
+ u32 link)
+{
+ struct netxen_port *pport = adapter->port[portno];
+ struct net_device *netdev = pport->netdev;
+
+ if (link)
+ netif_carrier_on(netdev);
+ else
+ netif_carrier_off(netdev);
+}
+
+void netxen_handle_port_int(struct netxen_adapter *adapter, u32 portno,
+ u32 enable)
+{
+ __le32 int_src;
+ struct netxen_port *port;
+
+ /* This should clear the interrupt source */
+ if (adapter->ops->phy_read)
+ adapter->ops->phy_read(adapter, portno,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS,
+ &int_src);
+ if (int_src == 0) {
+ DPRINTK(INFO, "No phy interrupts for port #%d\n", portno);
+ return;
+ }
+ if (adapter->ops->disable_phy_interrupts)
+ adapter->ops->disable_phy_interrupts(adapter, portno);
+
+ port = adapter->port[portno];
+
+ if (netxen_get_phy_int_jabber(int_src))
+ DPRINTK(INFO, "NetXen: %s Jabber interrupt \n",
+ port->netdev->name);
+
+ if (netxen_get_phy_int_polarity_changed(int_src))
+ DPRINTK(INFO, "NetXen: %s POLARITY CHANGED int \n",
+ port->netdev->name);
+
+ if (netxen_get_phy_int_energy_detect(int_src))
+ DPRINTK(INFO, "NetXen: %s ENERGY DETECT INT \n",
+ port->netdev->name);
+
+ if (netxen_get_phy_int_downshift(int_src))
+ DPRINTK(INFO, "NetXen: %s DOWNSHIFT INT \n",
+ port->netdev->name);
+ /* write it down later.. */
+ if ((netxen_get_phy_int_speed_changed(int_src))
+ || (netxen_get_phy_int_link_status_changed(int_src))) {
+ __le32 status;
+
+ DPRINTK(INFO, "NetXen: %s SPEED CHANGED OR"
+ " LINK STATUS CHANGED \n", port->netdev->name);
+
+ if (adapter->ops->phy_read
+ && adapter->ops->phy_read(adapter, portno,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
+ &status) == 0) {
+ if (netxen_get_phy_int_link_status_changed(int_src)) {
+ if (netxen_get_phy_link(status)) {
+ netxen_niu_gbe_init_port(adapter,
+ portno);
+ printk("%s: %s Link UP\n",
+ netxen_nic_driver_name,
+ port->netdev->name);
+
+ } else {
+ printk("%s: %s Link DOWN\n",
+ netxen_nic_driver_name,
+ port->netdev->name);
+ }
+ netxen_indicate_link_status(adapter, portno,
+ netxen_get_phy_link
+ (status));
+ }
+ }
+ }
+ if (adapter->ops->enable_phy_interrupts)
+ adapter->ops->enable_phy_interrupts(adapter, portno);
+}
+
+void netxen_nic_isr_other(struct netxen_adapter *adapter)
+{
+ u32 portno;
+ u32 val, linkup, qg_linksup;
+
+ /* verify the offset */
+ val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_XG_STATE));
+ if (val == adapter->ahw.qg_linksup)
+ return;
+
+ qg_linksup = adapter->ahw.qg_linksup;
+ adapter->ahw.qg_linksup = val;
+ DPRINTK(1, INFO, "%s: link update 0x%08x\n", netxen_nic_driver_name,
+ val);
+ for (portno = 0; portno < NETXEN_NIU_MAX_GBE_PORTS; portno++) {
+ linkup = val & 1;
+ if (linkup != (qg_linksup & 1)) {
+ printk(KERN_INFO "%s: PORT %d link %s\n",
+ netxen_nic_driver_name, portno,
+ ((linkup == 0) ? "down" : "up"));
+ netxen_indicate_link_status(adapter, portno, linkup);
+ if (linkup)
+ netxen_nic_set_link_parameters(adapter->
+ port[portno]);
+
+ }
+ val = val >> 1;
+ qg_linksup = qg_linksup >> 1;
+ }
+
+ adapter->stats.otherints++;
+
+}
+
+void netxen_nic_gbe_handle_phy_intr(struct netxen_adapter *adapter)
+{
+ netxen_nic_isr_other(adapter);
+}
+
+void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter)
+{
+ struct net_device *netdev = adapter->port[0]->netdev;
+ u32 val;
+
+ /* WINDOW = 1 */
+ val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_XG_STATE));
+
+ if (adapter->ahw.xg_linkup == 1 && val != XG_LINK_UP) {
+ printk(KERN_INFO "%s: %s NIC Link is down\n",
+ netxen_nic_driver_name, netdev->name);
+ adapter->ahw.xg_linkup = 0;
+ /* read twice to clear sticky bits */
+ /* WINDOW = 0 */
+ netxen_nic_read_w0(adapter, NETXEN_NIU_XG_STATUS, &val);
+ netxen_nic_read_w0(adapter, NETXEN_NIU_XG_STATUS, &val);
+
+ if ((val & 0xffb) != 0xffb) {
+ printk(KERN_INFO "%s ISR: Sync/Align BAD: 0x%08x\n",
+ netxen_nic_driver_name, val);
+ }
+ } else if (adapter->ahw.xg_linkup == 0 && val == XG_LINK_UP) {
+ printk(KERN_INFO "%s: %s NIC Link is up\n",
+ netxen_nic_driver_name, netdev->name);
+ adapter->ahw.xg_linkup = 1;
+ }
+}
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
new file mode 100644
index 000000000000..1cb662d5bd76
--- /dev/null
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -0,0 +1,1161 @@
+/*
+ * Copyright (C) 2003 - 2006 NetXen, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.
+ *
+ * Contact Information:
+ * info@netxen.com
+ * NetXen,
+ * 3965 Freedom Circle, Fourth floor,
+ * Santa Clara, CA 95054
+ *
+ *
+ * Main source file for NetXen NIC Driver on Linux
+ *
+ */
+
+#include <linux/vmalloc.h>
+#include "netxen_nic_hw.h"
+
+#include "netxen_nic.h"
+#define DEFINE_GLOBAL_RECV_CRB
+#include "netxen_nic_phan_reg.h"
+#include "netxen_nic_ioctl.h"
+
+#include <linux/dma-mapping.h>
+#include <linux/vmalloc.h>
+
+#define PHAN_VENDOR_ID 0x4040
+
+MODULE_DESCRIPTION("NetXen Multi port (1/10) Gigabit Network Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(NETXEN_NIC_LINUX_VERSIONID);
+
+char netxen_nic_driver_name[] = "netxen";
+static char netxen_nic_driver_string[] = "NetXen Network Driver version "
+ NETXEN_NIC_LINUX_VERSIONID;
+
+#define NETXEN_NETDEV_WEIGHT 120
+#define NETXEN_ADAPTER_UP_MAGIC 777
+#define NETXEN_NIC_PEG_TUNE 0
+
+/* Local functions to NetXen NIC driver */
+static int __devinit netxen_nic_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent);
+static void __devexit netxen_nic_remove(struct pci_dev *pdev);
+static int netxen_nic_open(struct net_device *netdev);
+static int netxen_nic_close(struct net_device *netdev);
+static int netxen_nic_xmit_frame(struct sk_buff *, struct net_device *);
+static void netxen_tx_timeout(struct net_device *netdev);
+static void netxen_tx_timeout_task(struct net_device *netdev);
+static void netxen_watchdog(unsigned long);
+static int netxen_handle_int(struct netxen_adapter *, struct net_device *);
+static int netxen_nic_ioctl(struct net_device *netdev,
+ struct ifreq *ifr, int cmd);
+static int netxen_nic_poll(struct net_device *dev, int *budget);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void netxen_nic_poll_controller(struct net_device *netdev);
+#endif
+static irqreturn_t netxen_intr(int irq, void *data);
+
+/* PCI Device ID Table */
+static struct pci_device_id netxen_pci_tbl[] __devinitdata = {
+ {PCI_DEVICE(0x4040, 0x0001)},
+ {PCI_DEVICE(0x4040, 0x0002)},
+ {PCI_DEVICE(0x4040, 0x0003)},
+ {PCI_DEVICE(0x4040, 0x0004)},
+ {PCI_DEVICE(0x4040, 0x0005)},
+ {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, netxen_pci_tbl);
+
+/*
+ * netxen_nic_probe()
+ *
+ * The Linux system will invoke this after identifying the vendor ID and
+ * device Id in the pci_tbl supported by this module.
+ *
+ * A quad port card has one operational PCI config space, (function 0),
+ * which is used to access all four ports.
+ *
+ * This routine will initialize the adapter, and setup the global parameters
+ * along with the port's specific structure.
+ */
+static int __devinit
+netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ struct net_device *netdev = NULL;
+ struct netxen_adapter *adapter = NULL;
+ struct netxen_port *port = NULL;
+ u8 *mem_ptr0 = NULL;
+ u8 *mem_ptr1 = NULL;
+ u8 *mem_ptr2 = NULL;
+
+ unsigned long mem_base, mem_len;
+ int pci_using_dac, i, err;
+ int ring;
+ struct netxen_recv_context *recv_ctx = NULL;
+ struct netxen_rcv_desc_ctx *rcv_desc = NULL;
+ struct netxen_cmd_buffer *cmd_buf_arr = NULL;
+ u64 mac_addr[FLASH_NUM_PORTS + 1];
+ int valid_mac;
+
+ printk(KERN_INFO "%s \n", netxen_nic_driver_string);
+ if ((err = pci_enable_device(pdev)))
+ return err;
+ if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
+ err = -ENODEV;
+ goto err_out_disable_pdev;
+ }
+
+ if ((err = pci_request_regions(pdev, netxen_nic_driver_name)))
+ goto err_out_disable_pdev;
+
+ pci_set_master(pdev);
+ if ((pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) &&
+ (pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK) == 0))
+ pci_using_dac = 1;
+ else {
+ if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) ||
+ (err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)))
+ goto err_out_free_res;
+
+ pci_using_dac = 0;
+ }
+
+ /* remap phys address */
+ mem_base = pci_resource_start(pdev, 0); /* 0 is for BAR 0 */
+ mem_len = pci_resource_len(pdev, 0);
+
+ /* 128 Meg of memory */
+ mem_ptr0 = ioremap(mem_base, FIRST_PAGE_GROUP_SIZE);
+ mem_ptr1 =
+ ioremap(mem_base + SECOND_PAGE_GROUP_START, SECOND_PAGE_GROUP_SIZE);
+ mem_ptr2 =
+ ioremap(mem_base + THIRD_PAGE_GROUP_START, THIRD_PAGE_GROUP_SIZE);
+
+ if ((mem_ptr0 == 0UL) || (mem_ptr1 == 0UL) || (mem_ptr2 == 0UL)) {
+ DPRINTK(1, ERR,
+ "Cannot remap adapter memory aborting.:"
+ "0 -> %p, 1 -> %p, 2 -> %p\n",
+ mem_ptr0, mem_ptr1, mem_ptr2);
+
+ err = -EIO;
+ if (mem_ptr0)
+ iounmap(mem_ptr0);
+ if (mem_ptr1)
+ iounmap(mem_ptr1);
+ if (mem_ptr2)
+ iounmap(mem_ptr2);
+
+ goto err_out_free_res;
+ }
+
+/*
+ * Allocate a adapter structure which will manage all the initialization
+ * as well as the common resources for all ports...
+ * all the ports will have pointer to this adapter as well as Adapter
+ * will have pointers of all the ports structures.
+ */
+
+ /* One adapter structure for all 4 ports.... */
+ adapter = kzalloc(sizeof(struct netxen_adapter), GFP_KERNEL);
+ if (adapter == NULL) {
+ printk(KERN_ERR "%s: Could not allocate adapter memory:%d\n",
+ netxen_nic_driver_name,
+ (int)sizeof(struct netxen_adapter));
+ err = -ENOMEM;
+ goto err_out_iounmap;
+ }
+
+ adapter->max_tx_desc_count = MAX_CMD_DESCRIPTORS;
+ adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS;
+ adapter->max_jumbo_rx_desc_count = MAX_JUMBO_RCV_DESCRIPTORS;
+
+ pci_set_drvdata(pdev, adapter);
+
+ cmd_buf_arr = (struct netxen_cmd_buffer *)vmalloc(TX_RINGSIZE);
+ if (cmd_buf_arr == NULL) {
+ err = -ENOMEM;
+ goto err_out_free_adapter;
+ }
+ memset(cmd_buf_arr, 0, TX_RINGSIZE);
+
+ for (i = 0; i < MAX_RCV_CTX; ++i) {
+ recv_ctx = &adapter->recv_ctx[i];
+ for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
+ rcv_desc = &recv_ctx->rcv_desc[ring];
+ switch (RCV_DESC_TYPE(ring)) {
+ case RCV_DESC_NORMAL:
+ rcv_desc->max_rx_desc_count =
+ adapter->max_rx_desc_count;
+ rcv_desc->flags = RCV_DESC_NORMAL;
+ rcv_desc->dma_size = RX_DMA_MAP_LEN;
+ rcv_desc->skb_size = MAX_RX_BUFFER_LENGTH;
+ break;
+
+ case RCV_DESC_JUMBO:
+ rcv_desc->max_rx_desc_count =
+ adapter->max_jumbo_rx_desc_count;
+ rcv_desc->flags = RCV_DESC_JUMBO;
+ rcv_desc->dma_size = RX_JUMBO_DMA_MAP_LEN;
+ rcv_desc->skb_size = MAX_RX_JUMBO_BUFFER_LENGTH;
+ break;
+
+ }
+ rcv_desc->rx_buf_arr = (struct netxen_rx_buffer *)
+ vmalloc(RCV_BUFFSIZE);
+
+ if (rcv_desc->rx_buf_arr == NULL) {
+ err = -ENOMEM;
+ goto err_out_free_rx_buffer;
+ }
+ memset(rcv_desc->rx_buf_arr, 0, RCV_BUFFSIZE);
+ }
+
+ }
+
+ adapter->ops = kzalloc(sizeof(struct netxen_drvops), GFP_KERNEL);
+ if (adapter->ops == NULL) {
+ printk(KERN_ERR
+ "%s: Could not allocate memory for adapter->ops:%d\n",
+ netxen_nic_driver_name,
+ (int)sizeof(struct netxen_adapter));
+ err = -ENOMEM;
+ goto err_out_free_rx_buffer;
+ }
+
+ adapter->cmd_buf_arr = cmd_buf_arr;
+ adapter->ahw.pci_base0 = mem_ptr0;
+ adapter->ahw.pci_base1 = mem_ptr1;
+ adapter->ahw.pci_base2 = mem_ptr2;
+ spin_lock_init(&adapter->tx_lock);
+ spin_lock_init(&adapter->lock);
+#ifdef CONFIG_IA64
+ netxen_pinit_from_rom(adapter, 0);
+ udelay(500);
+ netxen_load_firmware(adapter);
+#endif
+
+ /* initialize the buffers in adapter */
+ netxen_initialize_adapter_sw(adapter);
+ /*
+ * Set the CRB window to invalid. If any register in window 0 is
+ * accessed it should set the window to 0 and then reset it to 1.
+ */
+ adapter->curr_window = 255;
+ /*
+ * Adapter in our case is quad port so initialize it before
+ * initializing the ports
+ */
+ netxen_initialize_adapter_hw(adapter); /* initialize the adapter */
+
+ netxen_initialize_adapter_ops(adapter);
+
+ init_timer(&adapter->watchdog_timer);
+ adapter->ahw.xg_linkup = 0;
+ adapter->watchdog_timer.function = &netxen_watchdog;
+ adapter->watchdog_timer.data = (unsigned long)adapter;
+ INIT_WORK(&adapter->watchdog_task,
+ (void (*)(void *))netxen_watchdog_task, adapter);
+ adapter->ahw.pdev = pdev;
+ adapter->proc_cmd_buf_counter = 0;
+ pci_read_config_byte(pdev, PCI_REVISION_ID, &adapter->ahw.revision_id);
+
+ if (pci_enable_msi(pdev)) {
+ adapter->flags &= ~NETXEN_NIC_MSI_ENABLED;
+ printk(KERN_WARNING "%s: unable to allocate MSI interrupt"
+ " error\n", netxen_nic_driver_name);
+ } else
+ adapter->flags |= NETXEN_NIC_MSI_ENABLED;
+
+ if (netxen_is_flash_supported(adapter) == 0 &&
+ netxen_get_flash_mac_addr(adapter, mac_addr) == 0)
+ valid_mac = 1;
+ else
+ valid_mac = 0;
+
+ /*
+ * Initialize all the CRB registers here.
+ */
+ writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMD_PRODUCER_OFFSET));
+ writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMD_CONSUMER_OFFSET));
+ writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_CMD_ADDR_LO));
+
+ /* Unlock the HW, prompting the boot sequence */
+ writel(1,
+ NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE));
+
+ /* Handshake with the card before we register the devices. */
+ netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
+
+ /* initialize the all the ports */
+
+ for (i = 0; i < adapter->ahw.max_ports; i++) {
+ netdev = alloc_etherdev(sizeof(struct netxen_port));
+ if (!netdev) {
+ printk(KERN_ERR "%s: could not allocate netdev for port"
+ " %d\n", netxen_nic_driver_name, i + 1);
+ goto err_out_free_dev;
+ }
+
+ SET_MODULE_OWNER(netdev);
+ SET_NETDEV_DEV(netdev, &pdev->dev);
+
+ port = netdev_priv(netdev);
+ port->netdev = netdev;
+ port->pdev = pdev;
+ port->adapter = adapter;
+ port->portnum = i; /* Gigabit port number from 0-3 */
+
+ netdev->open = netxen_nic_open;
+ netdev->stop = netxen_nic_close;
+ netdev->hard_start_xmit = netxen_nic_xmit_frame;
+ netdev->get_stats = netxen_nic_get_stats;
+ netdev->set_multicast_list = netxen_nic_set_multi;
+ netdev->set_mac_address = netxen_nic_set_mac;
+ netdev->change_mtu = netxen_nic_change_mtu;
+ netdev->do_ioctl = netxen_nic_ioctl;
+ netdev->tx_timeout = netxen_tx_timeout;
+ netdev->watchdog_timeo = HZ;
+
+ SET_ETHTOOL_OPS(netdev, &netxen_nic_ethtool_ops);
+ netdev->poll = netxen_nic_poll;
+ netdev->weight = NETXEN_NETDEV_WEIGHT;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ netdev->poll_controller = netxen_nic_poll_controller;
+#endif
+ /* ScatterGather support */
+ netdev->features = NETIF_F_SG;
+ netdev->features |= NETIF_F_IP_CSUM;
+ netdev->features |= NETIF_F_TSO;
+
+ if (pci_using_dac)
+ netdev->features |= NETIF_F_HIGHDMA;
+
+ if (valid_mac) {
+ unsigned char *p = (unsigned char *)&mac_addr[i];
+ netdev->dev_addr[0] = *(p + 5);
+ netdev->dev_addr[1] = *(p + 4);
+ netdev->dev_addr[2] = *(p + 3);
+ netdev->dev_addr[3] = *(p + 2);
+ netdev->dev_addr[4] = *(p + 1);
+ netdev->dev_addr[5] = *(p + 0);
+
+ memcpy(netdev->perm_addr, netdev->dev_addr,
+ netdev->addr_len);
+ if (!is_valid_ether_addr(netdev->perm_addr)) {
+ printk(KERN_ERR "%s: Bad MAC address "
+ "%02x:%02x:%02x:%02x:%02x:%02x.\n",
+ netxen_nic_driver_name,
+ netdev->dev_addr[0],
+ netdev->dev_addr[1],
+ netdev->dev_addr[2],
+ netdev->dev_addr[3],
+ netdev->dev_addr[4],
+ netdev->dev_addr[5]);
+ } else {
+ if (adapter->ops->macaddr_set)
+ adapter->ops->macaddr_set(port,
+ netdev->
+ dev_addr);
+ }
+ }
+ INIT_WORK(&adapter->tx_timeout_task,
+ (void (*)(void *))netxen_tx_timeout_task, netdev);
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+
+ if ((err = register_netdev(netdev))) {
+ printk(KERN_ERR "%s: register_netdev failed port #%d"
+ " aborting\n", netxen_nic_driver_name, i + 1);
+ err = -EIO;
+ free_netdev(netdev);
+ goto err_out_free_dev;
+ }
+ adapter->port_count++;
+ adapter->active_ports = 0;
+ adapter->port[i] = port;
+ }
+
+ /*
+ * delay a while to ensure that the Pegs are up & running.
+ * Otherwise, we might see some flaky behaviour.
+ */
+ udelay(100);
+
+ switch (adapter->ahw.board_type) {
+ case NETXEN_NIC_GBE:
+ printk("%s: QUAD GbE board initialized\n",
+ netxen_nic_driver_name);
+ break;
+
+ case NETXEN_NIC_XGBE:
+ printk("%s: XGbE board initialized\n", netxen_nic_driver_name);
+ break;
+ }
+
+ adapter->driver_mismatch = 0;
+
+ return 0;
+
+ err_out_free_dev:
+ if (adapter->flags & NETXEN_NIC_MSI_ENABLED)
+ pci_disable_msi(pdev);
+ for (i = 0; i < adapter->port_count; i++) {
+ port = adapter->port[i];
+ if ((port) && (port->netdev)) {
+ unregister_netdev(port->netdev);
+ free_netdev(port->netdev);
+ }
+ }
+ kfree(adapter->ops);
+
+ err_out_free_rx_buffer:
+ for (i = 0; i < MAX_RCV_CTX; ++i) {
+ recv_ctx = &adapter->recv_ctx[i];
+ for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
+ rcv_desc = &recv_ctx->rcv_desc[ring];
+ if (rcv_desc->rx_buf_arr != NULL) {
+ vfree(rcv_desc->rx_buf_arr);
+ rcv_desc->rx_buf_arr = NULL;
+ }
+ }
+ }
+
+ vfree(cmd_buf_arr);
+
+ kfree(adapter->port);
+
+ err_out_free_adapter:
+ pci_set_drvdata(pdev, NULL);
+ kfree(adapter);
+
+ err_out_iounmap:
+ iounmap(mem_ptr0);
+ iounmap(mem_ptr1);
+ iounmap(mem_ptr2);
+
+ err_out_free_res:
+ pci_release_regions(pdev);
+ err_out_disable_pdev:
+ pci_disable_device(pdev);
+ return err;
+}
+
+static void __devexit netxen_nic_remove(struct pci_dev *pdev)
+{
+ struct netxen_adapter *adapter;
+ struct netxen_port *port;
+ struct netxen_rx_buffer *buffer;
+ struct netxen_recv_context *recv_ctx;
+ struct netxen_rcv_desc_ctx *rcv_desc;
+ int i;
+ int ctxid, ring;
+
+ adapter = pci_get_drvdata(pdev);
+ if (adapter == NULL)
+ return;
+
+ netxen_nic_stop_all_ports(adapter);
+ /* leave the hw in the same state as reboot */
+ netxen_pinit_from_rom(adapter, 0);
+ udelay(500);
+ netxen_load_firmware(adapter);
+
+ if ((adapter->flags & NETXEN_NIC_MSI_ENABLED))
+ netxen_nic_disable_int(adapter);
+
+ udelay(500); /* Delay for a while to drain the DMA engines */
+ for (i = 0; i < adapter->port_count; i++) {
+ port = adapter->port[i];
+ if ((port) && (port->netdev)) {
+ unregister_netdev(port->netdev);
+ free_netdev(port->netdev);
+ }
+ }
+
+ if ((adapter->flags & NETXEN_NIC_MSI_ENABLED))
+ pci_disable_msi(pdev);
+ pci_set_drvdata(pdev, NULL);
+ if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC)
+ netxen_free_hw_resources(adapter);
+
+ iounmap(adapter->ahw.pci_base0);
+ iounmap(adapter->ahw.pci_base1);
+ iounmap(adapter->ahw.pci_base2);
+
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+
+ for (ctxid = 0; ctxid < MAX_RCV_CTX; ++ctxid) {
+ recv_ctx = &adapter->recv_ctx[ctxid];
+ for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
+ rcv_desc = &recv_ctx->rcv_desc[ring];
+ for (i = 0; i < rcv_desc->max_rx_desc_count; ++i) {
+ buffer = &(rcv_desc->rx_buf_arr[i]);
+ if (buffer->state == NETXEN_BUFFER_FREE)
+ continue;
+ pci_unmap_single(pdev, buffer->dma,
+ rcv_desc->dma_size,
+ PCI_DMA_FROMDEVICE);
+ if (buffer->skb != NULL)
+ dev_kfree_skb_any(buffer->skb);
+ }
+ vfree(rcv_desc->rx_buf_arr);
+ }
+ }
+
+ vfree(adapter->cmd_buf_arr);
+ kfree(adapter->ops);
+ kfree(adapter);
+}
+
+/*
+ * Called when a network interface is made active
+ * @returns 0 on success, negative value on failure
+ */
+static int netxen_nic_open(struct net_device *netdev)
+{
+ struct netxen_port *port = netdev_priv(netdev);
+ struct netxen_adapter *adapter = port->adapter;
+ int err = 0;
+ int ctx, ring;
+
+ if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) {
+ err = netxen_init_firmware(adapter);
+ if (err != 0) {
+ printk(KERN_ERR "Failed to init firmware\n");
+ return -EIO;
+ }
+ netxen_nic_flash_print(adapter);
+
+ /* setup all the resources for the Phantom... */
+ /* this include the descriptors for rcv, tx, and status */
+ netxen_nic_clear_stats(adapter);
+ err = netxen_nic_hw_resources(adapter);
+ if (err) {
+ printk(KERN_ERR "Error in setting hw resources:%d\n",
+ err);
+ return err;
+ }
+ if (adapter->ops->init_port
+ && adapter->ops->init_port(adapter, port->portnum) != 0) {
+ printk(KERN_ERR "%s: Failed to initialize port %d\n",
+ netxen_nic_driver_name, port->portnum);
+ netxen_free_hw_resources(adapter);
+ return -EIO;
+ }
+ if (adapter->ops->init_niu)
+ adapter->ops->init_niu(adapter);
+ for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
+ for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++)
+ netxen_post_rx_buffers(adapter, ctx, ring);
+ }
+ adapter->is_up = NETXEN_ADAPTER_UP_MAGIC;
+ }
+ adapter->active_ports++;
+ if (adapter->active_ports == 1) {
+ err = request_irq(adapter->ahw.pdev->irq, &netxen_intr,
+ SA_SHIRQ | SA_SAMPLE_RANDOM, netdev->name,
+ adapter);
+ if (err) {
+ printk(KERN_ERR "request_irq failed with: %d\n", err);
+ adapter->active_ports--;
+ return err;
+ }
+ adapter->irq = adapter->ahw.pdev->irq;
+ if (!adapter->driver_mismatch)
+ mod_timer(&adapter->watchdog_timer, jiffies);
+
+ netxen_nic_enable_int(adapter);
+ }
+
+ /* Done here again so that even if phantom sw overwrote it,
+ * we set it */
+ if (adapter->ops->macaddr_set)
+ adapter->ops->macaddr_set(port, netdev->dev_addr);
+ netxen_nic_set_link_parameters(port);
+
+ netxen_nic_set_multi(netdev);
+ if (!adapter->driver_mismatch)
+ netif_start_queue(netdev);
+
+ return 0;
+}
+
+/*
+ * netxen_nic_close - Disables a network interface entry point
+ */
+static int netxen_nic_close(struct net_device *netdev)
+{
+ struct netxen_port *port = netdev_priv(netdev);
+ struct netxen_adapter *adapter = port->adapter;
+ int i, j;
+ struct netxen_cmd_buffer *cmd_buff;
+ struct netxen_skb_frag *buffrag;
+
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+
+ adapter->active_ports--;
+
+ if (!adapter->active_ports) {
+ netxen_nic_disable_int(adapter);
+ if (adapter->irq)
+ free_irq(adapter->irq, adapter);
+ cmd_buff = adapter->cmd_buf_arr;
+ for (i = 0; i < adapter->max_tx_desc_count; i++) {
+ buffrag = cmd_buff->frag_array;
+ if (buffrag->dma) {
+ pci_unmap_single(port->pdev, buffrag->dma,
+ buffrag->length,
+ PCI_DMA_TODEVICE);
+ buffrag->dma = (u64) NULL;
+ }
+ for (j = 0; j < cmd_buff->frag_count; j++) {
+ buffrag++;
+ if (buffrag->dma) {
+ pci_unmap_page(port->pdev,
+ buffrag->dma,
+ buffrag->length,
+ PCI_DMA_TODEVICE);
+ buffrag->dma = (u64) NULL;
+ }
+ }
+ /* Free the skb we received in netxen_nic_xmit_frame */
+ if (cmd_buff->skb) {
+ dev_kfree_skb_any(cmd_buff->skb);
+ cmd_buff->skb = NULL;
+ }
+ cmd_buff++;
+ }
+ del_timer_sync(&adapter->watchdog_timer);
+ }
+
+ return 0;
+}
+
+static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+{
+ struct netxen_port *port = netdev_priv(netdev);
+ struct netxen_adapter *adapter = port->adapter;
+ struct netxen_hardware_context *hw = &adapter->ahw;
+ unsigned int first_seg_len = skb->len - skb->data_len;
+ struct netxen_skb_frag *buffrag;
+ unsigned int i;
+
+ u32 producer = 0;
+ u32 saved_producer = 0;
+ struct cmd_desc_type0 *hwdesc;
+ int k;
+ struct netxen_cmd_buffer *pbuf = NULL;
+ unsigned int tries = 0;
+ static int dropped_packet = 0;
+ int frag_count;
+ u32 local_producer = 0;
+ u32 max_tx_desc_count = 0;
+ u32 last_cmd_consumer = 0;
+ int no_of_desc;
+
+ port->stats.xmitcalled++;
+ frag_count = skb_shinfo(skb)->nr_frags + 1;
+
+ if (unlikely(skb->len <= 0)) {
+ dev_kfree_skb_any(skb);
+ port->stats.badskblen++;
+ return NETDEV_TX_OK;
+ }
+
+ if (frag_count > MAX_BUFFERS_PER_CMD) {
+ printk("%s: %s netxen_nic_xmit_frame: frag_count (%d)"
+ "too large, can handle only %d frags\n",
+ netxen_nic_driver_name, netdev->name,
+ frag_count, MAX_BUFFERS_PER_CMD);
+ port->stats.txdropped++;
+ if ((++dropped_packet & 0xff) == 0xff)
+ printk("%s: %s droppped packets = %d\n",
+ netxen_nic_driver_name, netdev->name,
+ dropped_packet);
+
+ return NETDEV_TX_OK;
+ }
+
+ /*
+ * Everything is set up. Now, we just need to transmit it out.
+ * Note that we have to copy the contents of buffer over to
+ * right place. Later on, this can be optimized out by de-coupling the
+ * producer index from the buffer index.
+ */
+ retry_getting_window:
+ spin_lock_bh(&adapter->tx_lock);
+ if (adapter->total_threads == MAX_XMIT_PRODUCERS) {
+ spin_unlock_bh(&adapter->tx_lock);
+ /*
+ * Yield CPU
+ */
+ if (!in_atomic())
+ schedule();
+ else {
+ for (i = 0; i < 20; i++)
+ cpu_relax(); /*This a nop instr on i386 */
+ }
+ goto retry_getting_window;
+ }
+ local_producer = adapter->cmd_producer;
+ /* There 4 fragments per descriptor */
+ no_of_desc = (frag_count + 3) >> 2;
+ if (netdev->features & NETIF_F_TSO) {
+ if (skb_shinfo(skb)->gso_size > 0) {
+
+ no_of_desc++;
+ if (((skb->nh.iph)->ihl * sizeof(u32)) +
+ ((skb->h.th)->doff * sizeof(u32)) +
+ sizeof(struct ethhdr) >
+ (sizeof(struct cmd_desc_type0) - NET_IP_ALIGN)) {
+ no_of_desc++;
+ }
+ }
+ }
+ k = adapter->cmd_producer;
+ max_tx_desc_count = adapter->max_tx_desc_count;
+ last_cmd_consumer = adapter->last_cmd_consumer;
+ if ((k + no_of_desc) >=
+ ((last_cmd_consumer <= k) ? last_cmd_consumer + max_tx_desc_count :
+ last_cmd_consumer)) {
+ spin_unlock_bh(&adapter->tx_lock);
+ if (tries == 0) {
+ local_bh_disable();
+ netxen_process_cmd_ring((unsigned long)adapter);
+ local_bh_enable();
+ ++tries;
+ goto retry_getting_window;
+ } else {
+ port->stats.nocmddescriptor++;
+ DPRINTK(ERR, "No command descriptors available,"
+ " producer = %d, consumer = %d count=%llu,"
+ " dropping packet\n", producer,
+ adapter->last_cmd_consumer,
+ port->stats.nocmddescriptor);
+
+ spin_lock_bh(&adapter->tx_lock);
+ netif_stop_queue(netdev);
+ port->flags |= NETXEN_NETDEV_STATUS;
+ spin_unlock_bh(&adapter->tx_lock);
+ return NETDEV_TX_BUSY;
+ }
+ }
+ k = get_index_range(k, max_tx_desc_count, no_of_desc);
+ adapter->cmd_producer = k;
+ adapter->total_threads++;
+ adapter->num_threads++;
+
+ spin_unlock_bh(&adapter->tx_lock);
+ /* Copy the descriptors into the hardware */
+ producer = local_producer;
+ saved_producer = producer;
+ hwdesc = &hw->cmd_desc_head[producer];
+ memset(hwdesc, 0, sizeof(struct cmd_desc_type0));
+ /* Take skb->data itself */
+ pbuf = &adapter->cmd_buf_arr[producer];
+ if ((netdev->features & NETIF_F_TSO) && skb_shinfo(skb)->gso_size > 0) {
+ pbuf->mss = skb_shinfo(skb)->gso_size;
+ hwdesc->mss = skb_shinfo(skb)->gso_size;
+ } else {
+ pbuf->mss = 0;
+ hwdesc->mss = 0;
+ }
+ pbuf->no_of_descriptors = no_of_desc;
+ pbuf->total_length = skb->len;
+ pbuf->skb = skb;
+ pbuf->cmd = TX_ETHER_PKT;
+ pbuf->frag_count = frag_count;
+ pbuf->port = port->portnum;
+ buffrag = &pbuf->frag_array[0];
+ buffrag->dma = pci_map_single(port->pdev, skb->data, first_seg_len,
+ PCI_DMA_TODEVICE);
+ buffrag->length = first_seg_len;
+ CMD_DESC_TOTAL_LENGTH_WRT(hwdesc, skb->len);
+ hwdesc->num_of_buffers = frag_count;
+ hwdesc->opcode = TX_ETHER_PKT;
+
+ CMD_DESC_PORT_WRT(hwdesc, port->portnum);
+ hwdesc->buffer1_length = cpu_to_le16(first_seg_len);
+ hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma);
+
+ for (i = 1, k = 1; i < frag_count; i++, k++) {
+ struct skb_frag_struct *frag;
+ int len, temp_len;
+ unsigned long offset;
+ dma_addr_t temp_dma;
+
+ /* move to next desc. if there is a need */
+ if ((i & 0x3) == 0) {
+ k = 0;
+ producer = get_next_index(producer,
+ adapter->max_tx_desc_count);
+ hwdesc = &hw->cmd_desc_head[producer];
+ memset(hwdesc, 0, sizeof(struct cmd_desc_type0));
+ }
+ frag = &skb_shinfo(skb)->frags[i - 1];
+ len = frag->size;
+ offset = frag->page_offset;
+
+ temp_len = len;
+ temp_dma = pci_map_page(port->pdev, frag->page, offset,
+ len, PCI_DMA_TODEVICE);
+
+ buffrag++;
+ buffrag->dma = temp_dma;
+ buffrag->length = temp_len;
+
+ DPRINTK(INFO, "for loop. i=%d k=%d\n", i, k);
+ switch (k) {
+ case 0:
+ hwdesc->buffer1_length = cpu_to_le16(temp_len);
+ hwdesc->addr_buffer1 = cpu_to_le64(temp_dma);
+ break;
+ case 1:
+ hwdesc->buffer2_length = cpu_to_le16(temp_len);
+ hwdesc->addr_buffer2 = cpu_to_le64(temp_dma);
+ break;
+ case 2:
+ hwdesc->buffer3_length = cpu_to_le16(temp_len);
+ hwdesc->addr_buffer3 = cpu_to_le64(temp_dma);
+ break;
+ case 3:
+ hwdesc->buffer4_length = temp_len;
+ hwdesc->addr_buffer4 = cpu_to_le64(temp_dma);
+ break;
+ }
+ frag++;
+ }
+ producer = get_next_index(producer, adapter->max_tx_desc_count);
+
+ /* might change opcode to TX_TCP_LSO */
+ netxen_tso_check(adapter, &hw->cmd_desc_head[saved_producer], skb);
+
+ /* For LSO, we need to copy the MAC/IP/TCP headers into
+ * the descriptor ring
+ */
+ if (hw->cmd_desc_head[saved_producer].opcode == TX_TCP_LSO) {
+ int hdr_len, first_hdr_len, more_hdr;
+ hdr_len = hw->cmd_desc_head[saved_producer].total_hdr_length;
+ if (hdr_len > (sizeof(struct cmd_desc_type0) - NET_IP_ALIGN)) {
+ first_hdr_len =
+ sizeof(struct cmd_desc_type0) - NET_IP_ALIGN;
+ more_hdr = 1;
+ } else {
+ first_hdr_len = hdr_len;
+ more_hdr = 0;
+ }
+ /* copy the MAC/IP/TCP headers to the cmd descriptor list */
+ hwdesc = &hw->cmd_desc_head[producer];
+
+ /* copy the first 64 bytes */
+ memcpy(((void *)hwdesc) + NET_IP_ALIGN,
+ (void *)(skb->data), first_hdr_len);
+ producer = get_next_index(producer, max_tx_desc_count);
+
+ if (more_hdr) {
+ hwdesc = &hw->cmd_desc_head[producer];
+ /* copy the next 64 bytes - should be enough except
+ * for pathological case
+ */
+ memcpy((void *)hwdesc, (void *)(skb->data) +
+ first_hdr_len, hdr_len - first_hdr_len);
+ producer = get_next_index(producer, max_tx_desc_count);
+ }
+ }
+ spin_lock_bh(&adapter->tx_lock);
+ port->stats.txbytes +=
+ CMD_DESC_TOTAL_LENGTH(&hw->cmd_desc_head[saved_producer]);
+ /* Code to update the adapter considering how many producer threads
+ are currently working */
+ if ((--adapter->num_threads) == 0) {
+ /* This is the last thread */
+ u32 crb_producer = adapter->cmd_producer;
+ writel(crb_producer,
+ NETXEN_CRB_NORMALIZE(adapter, CRB_CMD_PRODUCER_OFFSET));
+ wmb();
+ adapter->total_threads = 0;
+ } else {
+ u32 crb_producer = 0;
+ crb_producer =
+ readl(NETXEN_CRB_NORMALIZE
+ (adapter, CRB_CMD_PRODUCER_OFFSET));
+ if (crb_producer == local_producer) {
+ crb_producer = get_index_range(crb_producer,
+ max_tx_desc_count,
+ no_of_desc);
+ writel(crb_producer,
+ NETXEN_CRB_NORMALIZE(adapter,
+ CRB_CMD_PRODUCER_OFFSET));
+ wmb();
+ }
+ }
+
+ port->stats.xmitfinished++;
+ spin_unlock_bh(&adapter->tx_lock);
+
+ netdev->trans_start = jiffies;
+
+ DPRINTK(INFO, "wrote CMD producer %x to phantom\n", producer);
+
+ DPRINTK(INFO, "Done. Send\n");
+ return NETDEV_TX_OK;
+}
+
+static void netxen_watchdog(unsigned long v)
+{
+ struct netxen_adapter *adapter = (struct netxen_adapter *)v;
+ schedule_work(&adapter->watchdog_task);
+}
+
+static void netxen_tx_timeout(struct net_device *netdev)
+{
+ struct netxen_port *port = (struct netxen_port *)netdev_priv(netdev);
+ struct netxen_adapter *adapter = port->adapter;
+
+ schedule_work(&adapter->tx_timeout_task);
+}
+
+static void netxen_tx_timeout_task(struct net_device *netdev)
+{
+ struct netxen_port *port = (struct netxen_port *)netdev_priv(netdev);
+ unsigned long flags;
+
+ printk(KERN_ERR "%s %s: transmit timeout, resetting.\n",
+ netxen_nic_driver_name, netdev->name);
+
+ spin_lock_irqsave(&port->adapter->lock, flags);
+ netxen_nic_close(netdev);
+ netxen_nic_open(netdev);
+ spin_unlock_irqrestore(&port->adapter->lock, flags);
+ netdev->trans_start = jiffies;
+ netif_wake_queue(netdev);
+}
+
+static int
+netxen_handle_int(struct netxen_adapter *adapter, struct net_device *netdev)
+{
+ u32 ret = 0;
+
+ DPRINTK(INFO, "Entered handle ISR\n");
+
+ adapter->stats.ints++;
+
+ if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
+ int count = 0;
+ u32 mask;
+ netxen_nic_disable_int(adapter);
+ /* Window = 0 or 1 */
+ do {
+ writel(0xffffffff, PCI_OFFSET_SECOND_RANGE(adapter,
+ ISR_INT_TARGET_STATUS));
+ mask = readl(pci_base_offset(adapter, ISR_INT_VECTOR));
+ } while (((mask & 0x80) != 0) && (++count < 32));
+ if ((mask & 0x80) != 0)
+ printk("Could not disable interrupt completely\n");
+
+ }
+ adapter->stats.hostints++;
+
+ if (netxen_nic_rx_has_work(adapter) || netxen_nic_tx_has_work(adapter)) {
+ if (netif_rx_schedule_prep(netdev)) {
+ /*
+ * Interrupts are already disabled.
+ */
+ __netif_rx_schedule(netdev);
+ } else {
+ static unsigned int intcount = 0;
+ if ((++intcount & 0xfff) == 0xfff)
+ printk(KERN_ERR
+ "%s: %s interrupt %d while in poll\n",
+ netxen_nic_driver_name, netdev->name,
+ intcount);
+ }
+ ret = 1;
+ }
+
+ if (ret == 0) {
+ netxen_nic_enable_int(adapter);
+ }
+
+ return ret;
+}
+
+/*
+ * netxen_intr - Interrupt Handler
+ * @irq: interrupt number
+ * data points to adapter stucture (which may be handling more than 1 port
+ */
+irqreturn_t netxen_intr(int irq, void *data)
+{
+ struct netxen_adapter *adapter;
+ struct netxen_port *port;
+ struct net_device *netdev;
+ int i;
+
+ if (unlikely(!irq)) {
+ return IRQ_NONE; /* Not our interrupt */
+ }
+
+ adapter = (struct netxen_adapter *)data;
+ for (i = 0; i < adapter->ahw.max_ports; i++) {
+ port = adapter->port[i];
+ netdev = port->netdev;
+
+ /* process our status queue (for all 4 ports) */
+ netxen_handle_int(adapter, netdev);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int netxen_nic_poll(struct net_device *netdev, int *budget)
+{
+ struct netxen_port *port = (struct netxen_port *)netdev_priv(netdev);
+ struct netxen_adapter *adapter = port->adapter;
+ int work_to_do = min(*budget, netdev->quota);
+ int done = 1;
+ int ctx;
+ int this_work_done;
+
+ DPRINTK(INFO, "polling for %d descriptors\n", *budget);
+ port->stats.polled++;
+
+ adapter->work_done = 0;
+ for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
+ /*
+ * Fairness issue. This will give undue weight to the
+ * receive context 0.
+ */
+
+ /*
+ * To avoid starvation, we give each of our receivers,
+ * a fraction of the quota. Sometimes, it might happen that we
+ * have enough quota to process every packet, but since all the
+ * packets are on one context, it gets only half of the quota,
+ * and ends up not processing it.
+ */
+ this_work_done = netxen_process_rcv_ring(adapter, ctx,
+ work_to_do /
+ MAX_RCV_CTX);
+ adapter->work_done += this_work_done;
+ }
+
+ netdev->quota -= adapter->work_done;
+ *budget -= adapter->work_done;
+
+ if (adapter->work_done >= work_to_do
+ && netxen_nic_rx_has_work(adapter) != 0)
+ done = 0;
+
+ netxen_process_cmd_ring((unsigned long)adapter);
+
+ DPRINTK(INFO, "new work_done: %d work_to_do: %d\n",
+ adapter->work_done, work_to_do);
+ if (done) {
+ netif_rx_complete(netdev);
+ netxen_nic_enable_int(adapter);
+ }
+
+ return !done;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void netxen_nic_poll_controller(struct net_device *netdev)
+{
+ struct netxen_port *port = netdev_priv(netdev);
+ struct netxen_adapter *adapter = port->adapter;
+ disable_irq(adapter->irq);
+ netxen_intr(adapter->irq, adapter);
+ enable_irq(adapter->irq);
+}
+#endif
+/*
+ * netxen_nic_ioctl () We provide the tcl/phanmon support through these
+ * ioctls.
+ */
+static int
+netxen_nic_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+ int err = 0;
+ unsigned long nr_bytes = 0;
+ struct netxen_port *port = netdev_priv(netdev);
+ struct netxen_adapter *adapter = port->adapter;
+ char dev_name[NETXEN_NIC_NAME_LEN];
+
+ DPRINTK(INFO, "doing ioctl for %s\n", netdev->name);
+ switch (cmd) {
+ case NETXEN_NIC_CMD:
+ err = netxen_nic_do_ioctl(adapter, (void *)ifr->ifr_data, port);
+ break;
+
+ case NETXEN_NIC_NAME:
+ DPRINTK(INFO, "ioctl cmd for NetXen\n");
+ if (ifr->ifr_data) {
+ sprintf(dev_name, "%s-%d", NETXEN_NIC_NAME_RSP,
+ port->portnum);
+ nr_bytes = copy_to_user((char *)ifr->ifr_data, dev_name,
+ NETXEN_NIC_NAME_LEN);
+ if (nr_bytes)
+ err = -EIO;
+
+ }
+ break;
+
+ default:
+ DPRINTK(INFO, "ioctl cmd %x not supported\n", cmd);
+ err = -EOPNOTSUPP;
+ break;
+ }
+
+ return err;
+}
+
+static struct pci_driver netxen_driver = {
+ .name = netxen_nic_driver_name,
+ .id_table = netxen_pci_tbl,
+ .probe = netxen_nic_probe,
+ .remove = __devexit_p(netxen_nic_remove)
+};
+
+/* Driver Registration on NetXen card */
+
+static int __init netxen_init_module(void)
+{
+ return pci_module_init(&netxen_driver);
+}
+
+module_init(netxen_init_module);
+
+static void __exit netxen_exit_module(void)
+{
+ /*
+ * Wait for some time to allow the dma to drain, if any.
+ */
+ mdelay(5);
+ pci_unregister_driver(&netxen_driver);
+}
+
+module_exit(netxen_exit_module);
diff --git a/drivers/net/netxen/netxen_nic_niu.c b/drivers/net/netxen/netxen_nic_niu.c
new file mode 100644
index 000000000000..7950a04532e6
--- /dev/null
+++ b/drivers/net/netxen/netxen_nic_niu.c
@@ -0,0 +1,894 @@
+/*
+ * Copyright (C) 2003 - 2006 NetXen, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.
+ *
+ * Contact Information:
+ * info@netxen.com
+ * NetXen,
+ * 3965 Freedom Circle, Fourth floor,
+ * Santa Clara, CA 95054
+ *
+ *
+ * Provides access to the Network Interface Unit h/w block.
+ *
+ */
+
+#include "netxen_nic.h"
+
+#define NETXEN_GB_MAC_SOFT_RESET 0x80000000
+#define NETXEN_GB_MAC_RESET_PROT_BLK 0x000F0000
+#define NETXEN_GB_MAC_ENABLE_TX_RX 0x00000005
+#define NETXEN_GB_MAC_PAUSED_FRMS 0x00000020
+
+static long phy_lock_timeout = 100000000;
+
+static inline int phy_lock(void)
+{
+ int i;
+ int done = 0, timeout = 0;
+
+ while (!done) {
+ done = readl((void __iomem *)NETXEN_PCIE_REG(PCIE_SEM3_LOCK));
+ if (done == 1)
+ break;
+ if (timeout >= phy_lock_timeout) {
+ return -1;
+ }
+ timeout++;
+ if (!in_atomic())
+ schedule();
+ else {
+ for (i = 0; i < 20; i++)
+ cpu_relax();
+ }
+ }
+
+ writel(NETXEN_PHY_LOCK_ID, (void __iomem *)PHY_LOCK_DRIVER);
+ return 0;
+}
+
+static inline int phy_unlock(void)
+{
+ readl((void __iomem *)NETXEN_PCIE_REG(PCIE_SEM3_UNLOCK));
+ return 0;
+}
+
+/*
+ * netxen_niu_gbe_phy_read - read a register from the GbE PHY via
+ * mii management interface.
+ *
+ * Note: The MII management interface goes through port 0.
+ * Individual phys are addressed as follows:
+ * @param phy [15:8] phy id
+ * @param reg [7:0] register number
+ *
+ * @returns 0 on success
+ * -1 on error
+ *
+ */
+int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long phy,
+ long reg, __le32 * readval)
+{
+ long timeout = 0;
+ long result = 0;
+ long restore = 0;
+ __le32 address;
+ __le32 command;
+ __le32 status;
+ __le32 mac_cfg0;
+
+ if (phy_lock() != 0) {
+ return -1;
+ }
+
+ /*
+ * MII mgmt all goes through port 0 MAC interface,
+ * so it cannot be in reset
+ */
+
+ if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0),
+ &mac_cfg0, 4))
+ return -EIO;
+ if (netxen_gb_get_soft_reset(mac_cfg0)) {
+ __le32 temp;
+ temp = 0;
+ netxen_gb_tx_reset_pb(temp);
+ netxen_gb_rx_reset_pb(temp);
+ netxen_gb_tx_reset_mac(temp);
+ netxen_gb_rx_reset_mac(temp);
+ if (netxen_nic_hw_write_wx(adapter,
+ NETXEN_NIU_GB_MAC_CONFIG_0(0),
+ &temp, 4))
+ return -EIO;
+ restore = 1;
+ }
+
+ address = 0;
+ netxen_gb_mii_mgmt_reg_addr(address, reg);
+ netxen_gb_mii_mgmt_phy_addr(address, phy);
+ if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0),
+ &address, 4))
+ return -EIO;
+ command = 0; /* turn off any prior activity */
+ if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
+ &command, 4))
+ return -EIO;
+ /* send read command */
+ netxen_gb_mii_mgmt_set_read_cycle(command);
+ if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
+ &command, 4))
+ return -EIO;
+
+ status = 0;
+ do {
+ if (netxen_nic_hw_read_wx(adapter,
+ NETXEN_NIU_GB_MII_MGMT_INDICATE(0),
+ &status, 4))
+ return -EIO;
+ timeout++;
+ } while ((netxen_get_gb_mii_mgmt_busy(status)
+ || netxen_get_gb_mii_mgmt_notvalid(status))
+ && (timeout++ < NETXEN_NIU_PHY_WAITMAX));
+
+ if (timeout < NETXEN_NIU_PHY_WAITMAX) {
+ if (netxen_nic_hw_read_wx(adapter,
+ NETXEN_NIU_GB_MII_MGMT_STATUS(0),
+ readval, 4))
+ return -EIO;
+ result = 0;
+ } else
+ result = -1;
+
+ if (restore)
+ if (netxen_nic_hw_write_wx(adapter,
+ NETXEN_NIU_GB_MAC_CONFIG_0(0),
+ &mac_cfg0, 4))
+ return -EIO;
+ phy_unlock();
+ return result;
+}
+
+/*
+ * netxen_niu_gbe_phy_write - write a register to the GbE PHY via
+ * mii management interface.
+ *
+ * Note: The MII management interface goes through port 0.
+ * Individual phys are addressed as follows:
+ * @param phy [15:8] phy id
+ * @param reg [7:0] register number
+ *
+ * @returns 0 on success
+ * -1 on error
+ *
+ */
+int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter,
+ long phy, long reg, __le32 val)
+{
+ long timeout = 0;
+ long result = 0;
+ long restore = 0;
+ __le32 address;
+ __le32 command;
+ __le32 status;
+ __le32 mac_cfg0;
+
+ /*
+ * MII mgmt all goes through port 0 MAC interface, so it
+ * cannot be in reset
+ */
+
+ if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0),
+ &mac_cfg0, 4))
+ return -EIO;
+ if (netxen_gb_get_soft_reset(mac_cfg0)) {
+ __le32 temp;
+ temp = 0;
+ netxen_gb_tx_reset_pb(temp);
+ netxen_gb_rx_reset_pb(temp);
+ netxen_gb_tx_reset_mac(temp);
+ netxen_gb_rx_reset_mac(temp);
+
+ if (netxen_nic_hw_write_wx(adapter,
+ NETXEN_NIU_GB_MAC_CONFIG_0(0),
+ &temp, 4))
+ return -EIO;
+ restore = 1;
+ }
+
+ command = 0; /* turn off any prior activity */
+ if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
+ &command, 4))
+ return -EIO;
+
+ address = 0;
+ netxen_gb_mii_mgmt_reg_addr(address, reg);
+ netxen_gb_mii_mgmt_phy_addr(address, phy);
+ if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0),
+ &address, 4))
+ return -EIO;
+
+ if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CTRL(0),
+ &val, 4))
+ return -EIO;
+
+ status = 0;
+ do {
+ if (netxen_nic_hw_read_wx(adapter,
+ NETXEN_NIU_GB_MII_MGMT_INDICATE(0),
+ &status, 4))
+ return -EIO;
+ timeout++;
+ } while ((netxen_get_gb_mii_mgmt_busy(status))
+ && (timeout++ < NETXEN_NIU_PHY_WAITMAX));
+
+ if (timeout < NETXEN_NIU_PHY_WAITMAX)
+ result = 0;
+ else
+ result = -EIO;
+
+ /* restore the state of port 0 MAC in case we tampered with it */
+ if (restore)
+ if (netxen_nic_hw_write_wx(adapter,
+ NETXEN_NIU_GB_MAC_CONFIG_0(0),
+ &mac_cfg0, 4))
+ return -EIO;
+
+ return result;
+}
+
+int netxen_niu_xgbe_enable_phy_interrupts(struct netxen_adapter *adapter,
+ int port)
+{
+ netxen_crb_writelit_adapter(adapter, NETXEN_NIU_INT_MASK, 0x3f);
+ return 0;
+}
+
+int netxen_niu_gbe_enable_phy_interrupts(struct netxen_adapter *adapter,
+ int port)
+{
+ int result = 0;
+ __le32 enable = 0;
+ netxen_set_phy_int_link_status_changed(enable);
+ netxen_set_phy_int_autoneg_completed(enable);
+ netxen_set_phy_int_speed_changed(enable);
+
+ if (0 !=
+ netxen_niu_gbe_phy_write(adapter, port,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_INT_ENABLE,
+ enable))
+ result = -EIO;
+
+ return result;
+}
+
+int netxen_niu_xgbe_disable_phy_interrupts(struct netxen_adapter *adapter,
+ int port)
+{
+ netxen_crb_writelit_adapter(adapter, NETXEN_NIU_INT_MASK, 0x7f);
+ return 0;
+}
+
+int netxen_niu_gbe_disable_phy_interrupts(struct netxen_adapter *adapter,
+ int port)
+{
+ int result = 0;
+ if (0 !=
+ netxen_niu_gbe_phy_write(adapter, port,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_INT_ENABLE, 0))
+ result = -EIO;
+
+ return result;
+}
+
+int netxen_niu_xgbe_clear_phy_interrupts(struct netxen_adapter *adapter,
+ int port)
+{
+ netxen_crb_writelit_adapter(adapter, NETXEN_NIU_ACTIVE_INT, -1);
+ return 0;
+}
+
+int netxen_niu_gbe_clear_phy_interrupts(struct netxen_adapter *adapter,
+ int port)
+{
+ int result = 0;
+ if (0 !=
+ netxen_niu_gbe_phy_write(adapter, port,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS,
+ -EIO))
+ result = -EIO;
+
+ return result;
+}
+
+/*
+ * netxen_niu_gbe_set_mii_mode- Set 10/100 Mbit Mode for GbE MAC
+ *
+ */
+void netxen_niu_gbe_set_mii_mode(struct netxen_adapter *adapter,
+ int port, long enable)
+{
+ netxen_crb_writelit_adapter(adapter, NETXEN_NIU_MODE, 0x2);
+ netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+ 0x80000000);
+ netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+ 0x0000f0025);
+ netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_1(port),
+ 0xf1ff);
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_NIU_GB0_GMII_MODE + (port << 3), 0);
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_NIU_GB0_MII_MODE + (port << 3), 1);
+ netxen_crb_writelit_adapter(adapter,
+ (NETXEN_NIU_GB0_HALF_DUPLEX + port * 4), 0);
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_NIU_GB_MII_MGMT_CONFIG(port), 0x7);
+
+ if (enable) {
+ /*
+ * Do NOT enable flow control until a suitable solution for
+ * shutting down pause frames is found.
+ */
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_NIU_GB_MAC_CONFIG_0(port),
+ 0x5);
+ }
+
+ if (netxen_niu_gbe_enable_phy_interrupts(adapter, port))
+ printk(KERN_ERR PFX "ERROR enabling PHY interrupts\n");
+ if (netxen_niu_gbe_clear_phy_interrupts(adapter, port))
+ printk(KERN_ERR PFX "ERROR clearing PHY interrupts\n");
+}
+
+/*
+ * netxen_niu_gbe_set_gmii_mode- Set GbE Mode for GbE MAC
+ */
+void netxen_niu_gbe_set_gmii_mode(struct netxen_adapter *adapter,
+ int port, long enable)
+{
+ netxen_crb_writelit_adapter(adapter, NETXEN_NIU_MODE, 0x2);
+ netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+ 0x80000000);
+ netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+ 0x0000f0025);
+ netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_1(port),
+ 0xf2ff);
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_NIU_GB0_MII_MODE + (port << 3), 0);
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_NIU_GB0_GMII_MODE + (port << 3), 1);
+ netxen_crb_writelit_adapter(adapter,
+ (NETXEN_NIU_GB0_HALF_DUPLEX + port * 4), 0);
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_NIU_GB_MII_MGMT_CONFIG(port), 0x7);
+
+ if (enable) {
+ /*
+ * Do NOT enable flow control until a suitable solution for
+ * shutting down pause frames is found.
+ */
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_NIU_GB_MAC_CONFIG_0(port),
+ 0x5);
+ }
+
+ if (netxen_niu_gbe_enable_phy_interrupts(adapter, port))
+ printk(KERN_ERR PFX "ERROR enabling PHY interrupts\n");
+ if (netxen_niu_gbe_clear_phy_interrupts(adapter, port))
+ printk(KERN_ERR PFX "ERROR clearing PHY interrupts\n");
+}
+
+int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port)
+{
+ int result = 0;
+ __le32 status;
+ if (adapter->ops->disable_phy_interrupts)
+ adapter->ops->disable_phy_interrupts(adapter, port);
+ mdelay(2);
+
+ if (0 ==
+ netxen_niu_gbe_phy_read(adapter, port,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
+ (__le32 *) & status)) {
+ if (netxen_get_phy_link(status)) {
+ if (netxen_get_phy_speed(status) == 2) {
+ netxen_niu_gbe_set_gmii_mode(adapter, port, 1);
+ } else if ((netxen_get_phy_speed(status) == 1)
+ || (netxen_get_phy_speed(status) == 0)) {
+ netxen_niu_gbe_set_mii_mode(adapter, port, 1);
+ } else {
+ result = -1;
+ }
+
+ } else {
+ /*
+ * We don't have link. Cable must be unconnected.
+ * Enable phy interrupts so we take action when
+ * plugged in.
+ */
+
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_NIU_GB_MAC_CONFIG_0
+ (port),
+ NETXEN_GB_MAC_SOFT_RESET);
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_NIU_GB_MAC_CONFIG_0
+ (port),
+ NETXEN_GB_MAC_RESET_PROT_BLK
+ | NETXEN_GB_MAC_ENABLE_TX_RX
+ |
+ NETXEN_GB_MAC_PAUSED_FRMS);
+ if (netxen_niu_gbe_clear_phy_interrupts(adapter, port))
+ printk(KERN_ERR PFX
+ "ERROR clearing PHY interrupts\n");
+ if (netxen_niu_gbe_enable_phy_interrupts(adapter, port))
+ printk(KERN_ERR PFX
+ "ERROR enabling PHY interrupts\n");
+ if (netxen_niu_gbe_clear_phy_interrupts(adapter, port))
+ printk(KERN_ERR PFX
+ "ERROR clearing PHY interrupts\n");
+ result = -1;
+ }
+ } else {
+ result = -EIO;
+ }
+ return result;
+}
+
+int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port)
+{
+ long reg = 0, ret = 0;
+
+ if (adapter->ahw.boardcfg.board_type == NETXEN_BRDTYPE_P2_SB31_10G_IMEZ) {
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_NIU_XG1_CONFIG_0, 0x5);
+ /* XXX hack for Mez cards: both ports in promisc mode */
+ netxen_nic_hw_read_wx(adapter,
+ NETXEN_NIU_XGE_CONFIG_1, &reg, 4);
+ reg = (reg | 0x2000UL);
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_NIU_XGE_CONFIG_1, reg);
+ reg = 0;
+ netxen_nic_hw_read_wx(adapter,
+ NETXEN_NIU_XG1_CONFIG_1, &reg, 4);
+ reg = (reg | 0x2000UL);
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_NIU_XG1_CONFIG_1, reg);
+ }
+
+ return ret;
+}
+
+/*
+ * netxen_niu_gbe_handle_phy_interrupt - Handles GbE PHY interrupts
+ * @param enable 0 means don't enable the port
+ * 1 means enable (or re-enable) the port
+ */
+int netxen_niu_gbe_handle_phy_interrupt(struct netxen_adapter *adapter,
+ int port, long enable)
+{
+ int result = 0;
+ __le32 int_src;
+
+ printk(KERN_INFO PFX "NETXEN: Handling PHY interrupt on port %d"
+ " (device enable = %d)\n", (int)port, (int)enable);
+
+ /*
+ * The read of the PHY INT status will clear the pending
+ * interrupt status
+ */
+ if (netxen_niu_gbe_phy_read(adapter, port,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS,
+ &int_src) != 0)
+ result = -EINVAL;
+ else {
+ printk(KERN_INFO PFX "PHY Interrupt source = 0x%x \n", int_src);
+ if (netxen_get_phy_int_jabber(int_src))
+ printk(KERN_INFO PFX "jabber Interrupt ");
+ if (netxen_get_phy_int_polarity_changed(int_src))
+ printk(KERN_INFO PFX "polarity changed ");
+ if (netxen_get_phy_int_energy_detect(int_src))
+ printk(KERN_INFO PFX "energy detect \n");
+ if (netxen_get_phy_int_downshift(int_src))
+ printk(KERN_INFO PFX "downshift \n");
+ if (netxen_get_phy_int_mdi_xover_changed(int_src))
+ printk(KERN_INFO PFX "mdi_xover_changed ");
+ if (netxen_get_phy_int_fifo_over_underflow(int_src))
+ printk(KERN_INFO PFX "fifo_over_underflow ");
+ if (netxen_get_phy_int_false_carrier(int_src))
+ printk(KERN_INFO PFX "false_carrier ");
+ if (netxen_get_phy_int_symbol_error(int_src))
+ printk(KERN_INFO PFX "symbol_error ");
+ if (netxen_get_phy_int_autoneg_completed(int_src))
+ printk(KERN_INFO PFX "autoneg_completed ");
+ if (netxen_get_phy_int_page_received(int_src))
+ printk(KERN_INFO PFX "page_received ");
+ if (netxen_get_phy_int_duplex_changed(int_src))
+ printk(KERN_INFO PFX "duplex_changed ");
+ if (netxen_get_phy_int_autoneg_error(int_src))
+ printk(KERN_INFO PFX "autoneg_error ");
+ if ((netxen_get_phy_int_speed_changed(int_src))
+ || (netxen_get_phy_int_link_status_changed(int_src))) {
+ __le32 status;
+
+ printk(KERN_INFO PFX
+ "speed_changed or link status changed");
+ if (netxen_niu_gbe_phy_read
+ (adapter, port,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
+ &status) == 0) {
+ if (netxen_get_phy_speed(status) == 2) {
+ printk
+ (KERN_INFO PFX "Link speed changed"
+ " to 1000 Mbps\n");
+ netxen_niu_gbe_set_gmii_mode(adapter,
+ port,
+ enable);
+ } else if (netxen_get_phy_speed(status) == 1) {
+ printk
+ (KERN_INFO PFX "Link speed changed"
+ " to 100 Mbps\n");
+ netxen_niu_gbe_set_mii_mode(adapter,
+ port,
+ enable);
+ } else if (netxen_get_phy_speed(status) == 0) {
+ printk
+ (KERN_INFO PFX "Link speed changed"
+ " to 10 Mbps\n");
+ netxen_niu_gbe_set_mii_mode(adapter,
+ port,
+ enable);
+ } else {
+ printk(KERN_ERR PFX "ERROR reading"
+ "PHY status. Illegal speed.\n");
+ result = -1;
+ }
+ } else {
+ printk(KERN_ERR PFX
+ "ERROR reading PHY status.\n");
+ result = -1;
+ }
+
+ }
+ printk(KERN_INFO "\n");
+ }
+ return result;
+}
+
+/*
+ * Return the current station MAC address.
+ * Note that the passed-in value must already be in network byte order.
+ */
+int netxen_niu_macaddr_get(struct netxen_adapter *adapter,
+ int phy, netxen_ethernet_macaddr_t * addr)
+{
+ u64 result = 0;
+ __le32 stationhigh;
+ __le32 stationlow;
+
+ if (addr == NULL)
+ return -EINVAL;
+ if ((phy < 0) || (phy > 3))
+ return -EINVAL;
+
+ if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy),
+ &stationhigh, 4))
+ return -EIO;
+ if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy),
+ &stationlow, 4))
+ return -EIO;
+
+ result = (u64) netxen_gb_get_stationaddress_low(stationlow);
+ result |= (u64) stationhigh << 16;
+ memcpy(*addr, &result, sizeof(netxen_ethernet_macaddr_t));
+
+ return 0;
+}
+
+/*
+ * Set the station MAC address.
+ * Note that the passed-in value must already be in network byte order.
+ */
+int netxen_niu_macaddr_set(struct netxen_port *port,
+ netxen_ethernet_macaddr_t addr)
+{
+ __le32 temp = 0;
+ struct netxen_adapter *adapter = port->adapter;
+ int phy = port->portnum;
+ unsigned char mac_addr[MAX_ADDR_LEN];
+ int i;
+
+ for (i = 0; i < 10; i++) {
+ memcpy(&temp, addr, 2);
+ temp <<= 16;
+ if (netxen_nic_hw_write_wx
+ (adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy), &temp, 4))
+ return -EIO;
+
+ temp = 0;
+
+ memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32));
+ if (netxen_nic_hw_write_wx
+ (adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy), &temp, 4))
+ return -2;
+
+ netxen_niu_macaddr_get(adapter, phy,
+ (netxen_ethernet_macaddr_t *) mac_addr);
+ if (memcmp(mac_addr, addr, MAX_ADDR_LEN == 0))
+ break;
+ }
+
+ if (i == 10) {
+ printk(KERN_ERR "%s: cannot set Mac addr for %s\n",
+ netxen_nic_driver_name, port->netdev->name);
+ printk(KERN_ERR "MAC address set: "
+ "%02x:%02x:%02x:%02x:%02x:%02x.\n",
+ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
+
+ printk(KERN_ERR "MAC address get: "
+ "%02x:%02x:%02x:%02x:%02x:%02x.\n",
+ mac_addr[0],
+ mac_addr[1],
+ mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
+ }
+ return 0;
+}
+
+/* Enable a GbE interface */
+int netxen_niu_enable_gbe_port(struct netxen_adapter *adapter,
+ int port, netxen_niu_gbe_ifmode_t mode)
+{
+ __le32 mac_cfg0;
+ __le32 mac_cfg1;
+ __le32 mii_cfg;
+
+ if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
+ return -EINVAL;
+
+ mac_cfg0 = 0;
+ netxen_gb_soft_reset(mac_cfg0);
+ if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+ &mac_cfg0, 4))
+ return -EIO;
+ mac_cfg0 = 0;
+ netxen_gb_enable_tx(mac_cfg0);
+ netxen_gb_enable_rx(mac_cfg0);
+ netxen_gb_unset_rx_flowctl(mac_cfg0);
+ netxen_gb_tx_reset_pb(mac_cfg0);
+ netxen_gb_rx_reset_pb(mac_cfg0);
+ netxen_gb_tx_reset_mac(mac_cfg0);
+ netxen_gb_rx_reset_mac(mac_cfg0);
+
+ if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+ &mac_cfg0, 4))
+ return -EIO;
+ mac_cfg1 = 0;
+ netxen_gb_set_preamblelen(mac_cfg1, 0xf);
+ netxen_gb_set_duplex(mac_cfg1);
+ netxen_gb_set_crc_enable(mac_cfg1);
+ netxen_gb_set_padshort(mac_cfg1);
+ netxen_gb_set_checklength(mac_cfg1);
+ netxen_gb_set_hugeframes(mac_cfg1);
+
+ if (mode == NETXEN_NIU_10_100_MB) {
+ netxen_gb_set_intfmode(mac_cfg1, 1);
+ if (netxen_nic_hw_write_wx(adapter,
+ NETXEN_NIU_GB_MAC_CONFIG_1(port),
+ &mac_cfg1, 4))
+ return -EIO;
+
+ /* set mii mode */
+ netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB0_GMII_MODE +
+ (port << 3), 0);
+ netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB0_MII_MODE +
+ (port << 3), 1);
+
+ } else if (mode == NETXEN_NIU_1000_MB) {
+ netxen_gb_set_intfmode(mac_cfg1, 2);
+ if (netxen_nic_hw_write_wx(adapter,
+ NETXEN_NIU_GB_MAC_CONFIG_1(port),
+ &mac_cfg1, 4))
+ return -EIO;
+ /* set gmii mode */
+ netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB0_MII_MODE +
+ (port << 3), 0);
+ netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB0_GMII_MODE +
+ (port << 3), 1);
+ }
+ mii_cfg = 0;
+ netxen_gb_set_mii_mgmt_clockselect(mii_cfg, 7);
+ if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CONFIG(port),
+ &mii_cfg, 4))
+ return -EIO;
+ mac_cfg0 = 0;
+ netxen_gb_enable_tx(mac_cfg0);
+ netxen_gb_enable_rx(mac_cfg0);
+ netxen_gb_unset_rx_flowctl(mac_cfg0);
+ netxen_gb_unset_tx_flowctl(mac_cfg0);
+
+ if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+ &mac_cfg0, 4))
+ return -EIO;
+ return 0;
+}
+
+/* Disable a GbE interface */
+int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter, int port)
+{
+ __le32 mac_cfg0;
+
+ if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
+ return -EINVAL;
+
+ mac_cfg0 = 0;
+ netxen_gb_soft_reset(mac_cfg0);
+ if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+ &mac_cfg0, 4))
+ return -EIO;
+ return 0;
+}
+
+/* Disable an XG interface */
+int netxen_niu_disable_xg_port(struct netxen_adapter *adapter, int port)
+{
+ __le32 mac_cfg;
+
+ if (port != 0)
+ return -EINVAL;
+
+ mac_cfg = 0;
+ netxen_xg_soft_reset(mac_cfg);
+ if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XGE_CONFIG_0,
+ &mac_cfg, 4))
+ return -EIO;
+ return 0;
+}
+
+/* Set promiscuous mode for a GbE interface */
+int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter, int port,
+ netxen_niu_prom_mode_t mode)
+{
+ __le32 reg;
+
+ if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
+ return -EINVAL;
+
+ /* save previous contents */
+ if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR,
+ &reg, 4))
+ return -EIO;
+ if (mode == NETXEN_NIU_PROMISC_MODE) {
+ switch (port) {
+ case 0:
+ netxen_clear_gb_drop_gb0(reg);
+ break;
+ case 1:
+ netxen_clear_gb_drop_gb1(reg);
+ break;
+ case 2:
+ netxen_clear_gb_drop_gb2(reg);
+ break;
+ case 3:
+ netxen_clear_gb_drop_gb3(reg);
+ break;
+ default:
+ return -EIO;
+ }
+ } else {
+ switch (port) {
+ case 0:
+ netxen_set_gb_drop_gb0(reg);
+ break;
+ case 1:
+ netxen_set_gb_drop_gb1(reg);
+ break;
+ case 2:
+ netxen_set_gb_drop_gb2(reg);
+ break;
+ case 3:
+ netxen_set_gb_drop_gb3(reg);
+ break;
+ default:
+ return -EIO;
+ }
+ }
+ if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR,
+ &reg, 4))
+ return -EIO;
+ return 0;
+}
+
+/*
+ * Set the MAC address for an XG port
+ * Note that the passed-in value must already be in network byte order.
+ */
+int netxen_niu_xg_macaddr_set(struct netxen_port *port,
+ netxen_ethernet_macaddr_t addr)
+{
+ __le32 temp = 0;
+ struct netxen_adapter *adapter = port->adapter;
+
+ memcpy(&temp, addr, 2);
+ temp = cpu_to_le32(temp);
+ temp <<= 16;
+ if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
+ &temp, 4))
+ return -EIO;
+
+ temp = 0;
+
+ memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32));
+ temp = cpu_to_le32(temp);
+ if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI,
+ &temp, 4))
+ return -EIO;
+
+ return 0;
+}
+
+/*
+ * Return the current station MAC address.
+ * Note that the passed-in value must already be in network byte order.
+ */
+int netxen_niu_xg_macaddr_get(struct netxen_adapter *adapter, int phy,
+ netxen_ethernet_macaddr_t * addr)
+{
+ __le32 stationhigh;
+ __le32 stationlow;
+ u64 result;
+
+ if (addr == NULL)
+ return -EINVAL;
+ if (phy != 0)
+ return -EINVAL;
+
+ if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI,
+ &stationhigh, 4))
+ return -EIO;
+ if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
+ &stationlow, 4))
+ return -EIO;
+
+ result = ((u64) stationlow) >> 16;
+ result |= (u64) stationhigh << 16;
+ memcpy(*addr, &result, sizeof(netxen_ethernet_macaddr_t));
+
+ return 0;
+}
+
+int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter,
+ int port, netxen_niu_prom_mode_t mode)
+{
+ __le32 reg;
+
+ if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
+ return -EINVAL;
+
+ if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_XGE_CONFIG_1, &reg, 4))
+ return -EIO;
+ if (mode == NETXEN_NIU_PROMISC_MODE)
+ reg = (reg | 0x2000UL);
+ else
+ reg = (reg & ~0x2000UL);
+
+ netxen_crb_writelit_adapter(adapter, NETXEN_NIU_XGE_CONFIG_1, reg);
+
+ return 0;
+}
diff --git a/drivers/net/netxen/netxen_nic_phan_reg.h b/drivers/net/netxen/netxen_nic_phan_reg.h
new file mode 100644
index 000000000000..8181d436783f
--- /dev/null
+++ b/drivers/net/netxen/netxen_nic_phan_reg.h
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2003 - 2006 NetXen, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.
+ *
+ * Contact Information:
+ * info@netxen.com
+ * NetXen,
+ * 3965 Freedom Circle, Fourth floor,
+ * Santa Clara, CA 95054
+ */
+
+#ifndef __NIC_PHAN_REG_H_
+#define __NIC_PHAN_REG_H_
+
+/*
+ * CRB Registers or queue message done only at initialization time.
+ */
+
+/*
+ * The following 2 are the base adresses for the CRB registers and their
+ * offsets will be added to get addresses for the index addresses.
+ */
+#define NIC_CRB_BASE_PORT1 NETXEN_CAM_RAM(0x200)
+#define NIC_CRB_BASE_PORT2 NETXEN_CAM_RAM(0x250)
+
+#define NETXEN_NIC_REG(X) (NIC_CRB_BASE_PORT1+(X))
+
+/*
+ * CrbPortPhanCntrHi/Lo is used to pass the address of HostPhantomIndex address
+ * which can be read by the Phantom host to get producer/consumer indexes from
+ * Phantom/Casper. If it is not HOST_SHARED_MEMORY, then the following
+ * registers will be used for the addresses of the ring's shared memory
+ * on the Phantom.
+ */
+
+#define CRB_PHAN_CNTRL_LO_OFFSET NETXEN_NIC_REG(0x00)
+#define CRB_PHAN_CNTRL_HI_OFFSET NETXEN_NIC_REG(0x04)
+
+/* point to the indexes */
+#define CRB_CMD_PRODUCER_OFFSET NETXEN_NIC_REG(0x08)
+#define CRB_CMD_CONSUMER_OFFSET NETXEN_NIC_REG(0x0c)
+
+#define CRB_PAUSE_ADDR_LO NETXEN_NIC_REG(0x10)
+#define CRB_PAUSE_ADDR_HI NETXEN_NIC_REG(0x14)
+
+/* address of command descriptors in the host memory */
+#define CRB_HOST_CMD_ADDR_HI NETXEN_NIC_REG(0x30)
+#define CRB_HOST_CMD_ADDR_LO NETXEN_NIC_REG(0x34)
+
+/* The following 4 CRB registers are for doing performance coal */
+#define CRB_CMD_INTR_LOOP NETXEN_NIC_REG(0x38)
+#define CRB_CMD_DMA_LOOP NETXEN_NIC_REG(0x3c)
+#define CRB_RCV_INTR_LOOP NETXEN_NIC_REG(0x40)
+#define CRB_RCV_DMA_LOOP NETXEN_NIC_REG(0x44)
+
+/* Needed by the host to find out the state of Phantom's initialization */
+#define CRB_ENABLE_TX_INTR NETXEN_NIC_REG(0x4c)
+#define CRB_CMDPEG_STATE NETXEN_NIC_REG(0x50)
+#define CRB_CMDPEG_CMDRING NETXEN_NIC_REG(0x54)
+
+/* Interrupt coalescing parameters */
+#define CRB_GLOBAL_INT_COAL NETXEN_NIC_REG(0x80)
+#define CRB_INT_COAL_MODE NETXEN_NIC_REG(0x84)
+#define CRB_MAX_RCV_BUFS NETXEN_NIC_REG(0x88)
+#define CRB_TX_INT_THRESHOLD NETXEN_NIC_REG(0x8c)
+#define CRB_RX_PKT_TIMER NETXEN_NIC_REG(0x90)
+#define CRB_TX_PKT_TIMER NETXEN_NIC_REG(0x94)
+#define CRB_RX_PKT_CNT NETXEN_NIC_REG(0x98)
+#define CRB_RX_TMR_CNT NETXEN_NIC_REG(0x9c)
+#define CRB_INT_THRESH NETXEN_NIC_REG(0xa4)
+
+/* Register for communicating XG link status */
+#define CRB_XG_STATE NETXEN_NIC_REG(0xa0)
+
+/* Register for communicating card temperature */
+/* Upper 16 bits are temperature value. Lower 16 bits are the state */
+#define CRB_TEMP_STATE NETXEN_NIC_REG(0xa8)
+#define nx_get_temp_val(x) ((x) >> 16)
+#define nx_get_temp_state(x) ((x) & 0xffff)
+#define nx_encode_temp(val, state) (((val) << 16) | (state))
+
+/* Debug registers for controlling NIC pkt gen agent */
+#define CRB_AGENT_GO NETXEN_NIC_REG(0xb0)
+#define CRB_AGENT_TX_SIZE NETXEN_NIC_REG(0xb4)
+#define CRB_AGENT_TX_TYPE NETXEN_NIC_REG(0xb8)
+#define CRB_AGENT_TX_ADDR NETXEN_NIC_REG(0xbc)
+#define CRB_AGENT_TX_MSS NETXEN_NIC_REG(0xc0)
+
+/* Debug registers for observing NIC performance */
+#define CRB_TX_STATE NETXEN_NIC_REG(0xd0)
+#define CRB_TX_COUNT NETXEN_NIC_REG(0xd4)
+#define CRB_RX_STATE NETXEN_NIC_REG(0xd8)
+
+/* CRB registers per Rcv Descriptor ring */
+struct netxen_rcv_desc_crb {
+ u32 crb_rcv_producer_offset __attribute__ ((aligned(512)));
+ u32 crb_rcv_consumer_offset;
+ u32 crb_globalrcv_ring;
+};
+
+/*
+ * CRB registers used by the receive peg logic. One instance of these
+ * needs to be instantiated per instance of the receive peg.
+ */
+
+struct netxen_recv_crb {
+ struct netxen_rcv_desc_crb rcv_desc_crb[NUM_RCV_DESC_RINGS];
+ u32 crb_rcvstatus_ring;
+ u32 crb_rcv_status_producer;
+ u32 crb_rcv_status_consumer;
+ u32 crb_rcvpeg_state;
+};
+
+#if defined(DEFINE_GLOBAL_RECV_CRB)
+struct netxen_recv_crb recv_crb_registers[] = {
+ /*
+ * Instance 0.
+ */
+ {
+ /* rcv_desc_crb: */
+ {
+ {
+ /* crb_rcv_producer_offset: */
+ NETXEN_NIC_REG(0x18),
+ /* crb_rcv_consumer_offset: */
+ NETXEN_NIC_REG(0x1c),
+ /* crb_gloablrcv_ring: */
+ NETXEN_NIC_REG(0x20),
+ },
+ /* Jumbo frames */
+ {
+ /* crb_rcv_producer_offset: */
+ NETXEN_NIC_REG(0x100),
+ /* crb_rcv_consumer_offset: */
+ NETXEN_NIC_REG(0x104),
+ /* crb_gloablrcv_ring: */
+ NETXEN_NIC_REG(0x108),
+ }
+ },
+ /* crb_rcvstatus_ring: */
+ NETXEN_NIC_REG(0x24),
+ /* crb_rcv_status_producer: */
+ NETXEN_NIC_REG(0x28),
+ /* crb_rcv_status_consumer: */
+ NETXEN_NIC_REG(0x2c),
+ /* crb_rcvpeg_state: */
+ NETXEN_NIC_REG(0x48),
+
+ },
+ /*
+ * Instance 1,
+ */
+ {
+ /* rcv_desc_crb: */
+ {
+ {
+ /* crb_rcv_producer_offset: */
+ NETXEN_NIC_REG(0x80),
+ /* crb_rcv_consumer_offset: */
+ NETXEN_NIC_REG(0x84),
+ /* crb_globalrcv_ring: */
+ NETXEN_NIC_REG(0x88),
+ },
+ /* Jumbo frames */
+ {
+ /* crb_rcv_producer_offset: */
+ NETXEN_NIC_REG(0x10C),
+ /* crb_rcv_consumer_offset: */
+ NETXEN_NIC_REG(0x110),
+ /* crb_globalrcv_ring: */
+ NETXEN_NIC_REG(0x114),
+ }
+ },
+ /* crb_rcvstatus_ring: */
+ NETXEN_NIC_REG(0x8c),
+ /* crb_rcv_status_producer: */
+ NETXEN_NIC_REG(0x90),
+ /* crb_rcv_status_consumer: */
+ NETXEN_NIC_REG(0x94),
+ /* crb_rcvpeg_state: */
+ NETXEN_NIC_REG(0x98),
+ },
+};
+#else
+extern struct netxen_recv_crb recv_crb_registers[];
+#endif /* DEFINE_GLOBAL_RECEIVE_CRB */
+
+/*
+ * Temperature control.
+ */
+enum {
+ NX_TEMP_NORMAL = 0x1, /* Normal operating range */
+ NX_TEMP_WARN, /* Sound alert, temperature getting high */
+ NX_TEMP_PANIC /* Fatal error, hardware has shut down. */
+};
+
+#endif /* __NIC_PHAN_REG_H_ */
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index 0c00d182e7fd..c51cc5d8789a 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -1096,7 +1096,6 @@ static void ei_watchdog(u_long arg)
/* Check for pending interrupt with expired latency timer: with
this, we can limp along even if the interrupt is blocked */
- outb_p(E8390_NODMA+E8390_PAGE0, nic_base + E8390_CMD);
if (info->stale++ && (inb_p(nic_base + EN0_ISR) & ENISR_ALL)) {
if (!info->fast_poll)
printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index b79ec0d7480f..f994f129f3d8 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -56,13 +56,19 @@ config SMSC_PHY
---help---
Currently supports the LAN83C185 PHY
+config BROADCOM_PHY
+ tristate "Drivers for Broadcom PHYs"
+ depends on PHYLIB
+ ---help---
+ Currently supports the BCM5411, BCM5421 and BCM5461 PHYs.
+
config FIXED_PHY
tristate "Drivers for PHY emulation on fixed speed/link"
depends on PHYLIB
---help---
Adds the driver to PHY layer to cover the boards that do not have any PHY bound,
- but with the ability to manipulate with speed/link in software. The relavant MII
- speed/duplex parameters could be effectively handled in user-specified fuction.
+ but with the ability to manipulate the speed/link in software. The relevant MII
+ speed/duplex parameters could be effectively handled in a user-specified function.
Currently tested with mpc866ads.
config FIXED_MII_10_FDX
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 320f8323123f..bcd1efbd2a18 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -10,4 +10,5 @@ obj-$(CONFIG_LXT_PHY) += lxt.o
obj-$(CONFIG_QSEMI_PHY) += qsemi.o
obj-$(CONFIG_SMSC_PHY) += smsc.o
obj-$(CONFIG_VITESSE_PHY) += vitesse.o
+obj-$(CONFIG_BROADCOM_PHY) += broadcom.o
obj-$(CONFIG_FIXED_PHY) += fixed.o
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
new file mode 100644
index 000000000000..29666c85ed55
--- /dev/null
+++ b/drivers/net/phy/broadcom.c
@@ -0,0 +1,175 @@
+/*
+ * drivers/net/phy/broadcom.c
+ *
+ * Broadcom BCM5411, BCM5421 and BCM5461 Gigabit Ethernet
+ * transceivers.
+ *
+ * Copyright (c) 2006 Maciej W. Rozycki
+ *
+ * Inspired by code written by Amy Fong.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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/phy.h>
+
+#define MII_BCM54XX_ECR 0x10 /* BCM54xx extended control register */
+#define MII_BCM54XX_ECR_IM 0x1000 /* Interrupt mask */
+#define MII_BCM54XX_ECR_IF 0x0800 /* Interrupt force */
+
+#define MII_BCM54XX_ESR 0x11 /* BCM54xx extended status register */
+#define MII_BCM54XX_ESR_IS 0x1000 /* Interrupt status */
+
+#define MII_BCM54XX_ISR 0x1a /* BCM54xx interrupt status register */
+#define MII_BCM54XX_IMR 0x1b /* BCM54xx interrupt mask register */
+#define MII_BCM54XX_INT_CRCERR 0x0001 /* CRC error */
+#define MII_BCM54XX_INT_LINK 0x0002 /* Link status changed */
+#define MII_BCM54XX_INT_SPEED 0x0004 /* Link speed change */
+#define MII_BCM54XX_INT_DUPLEX 0x0008 /* Duplex mode changed */
+#define MII_BCM54XX_INT_LRS 0x0010 /* Local receiver status changed */
+#define MII_BCM54XX_INT_RRS 0x0020 /* Remote receiver status changed */
+#define MII_BCM54XX_INT_SSERR 0x0040 /* Scrambler synchronization error */
+#define MII_BCM54XX_INT_UHCD 0x0080 /* Unsupported HCD negotiated */
+#define MII_BCM54XX_INT_NHCD 0x0100 /* No HCD */
+#define MII_BCM54XX_INT_NHCDL 0x0200 /* No HCD link */
+#define MII_BCM54XX_INT_ANPR 0x0400 /* Auto-negotiation page received */
+#define MII_BCM54XX_INT_LC 0x0800 /* All counters below 128 */
+#define MII_BCM54XX_INT_HC 0x1000 /* Counter above 32768 */
+#define MII_BCM54XX_INT_MDIX 0x2000 /* MDIX status change */
+#define MII_BCM54XX_INT_PSERR 0x4000 /* Pair swap error */
+
+MODULE_DESCRIPTION("Broadcom PHY driver");
+MODULE_AUTHOR("Maciej W. Rozycki");
+MODULE_LICENSE("GPL");
+
+static int bcm54xx_config_init(struct phy_device *phydev)
+{
+ int reg, err;
+
+ reg = phy_read(phydev, MII_BCM54XX_ECR);
+ if (reg < 0)
+ return reg;
+
+ /* Mask interrupts globally. */
+ reg |= MII_BCM54XX_ECR_IM;
+ err = phy_write(phydev, MII_BCM54XX_ECR, reg);
+ if (err < 0)
+ return err;
+
+ /* Unmask events we are interested in. */
+ reg = ~(MII_BCM54XX_INT_DUPLEX |
+ MII_BCM54XX_INT_SPEED |
+ MII_BCM54XX_INT_LINK);
+ err = phy_write(phydev, MII_BCM54XX_IMR, reg);
+ if (err < 0)
+ return err;
+ return 0;
+}
+
+static int bcm54xx_ack_interrupt(struct phy_device *phydev)
+{
+ int reg;
+
+ /* Clear pending interrupts. */
+ reg = phy_read(phydev, MII_BCM54XX_ISR);
+ if (reg < 0)
+ return reg;
+
+ return 0;
+}
+
+static int bcm54xx_config_intr(struct phy_device *phydev)
+{
+ int reg, err;
+
+ reg = phy_read(phydev, MII_BCM54XX_ECR);
+ if (reg < 0)
+ return reg;
+
+ if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
+ reg &= ~MII_BCM54XX_ECR_IM;
+ else
+ reg |= MII_BCM54XX_ECR_IM;
+
+ err = phy_write(phydev, MII_BCM54XX_ECR, reg);
+ return err;
+}
+
+static struct phy_driver bcm5411_driver = {
+ .phy_id = 0x00206070,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Broadcom BCM5411",
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
+ .config_init = bcm54xx_config_init,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .ack_interrupt = bcm54xx_ack_interrupt,
+ .config_intr = bcm54xx_config_intr,
+ .driver = { .owner = THIS_MODULE },
+};
+
+static struct phy_driver bcm5421_driver = {
+ .phy_id = 0x002060e0,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Broadcom BCM5421",
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
+ .config_init = bcm54xx_config_init,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .ack_interrupt = bcm54xx_ack_interrupt,
+ .config_intr = bcm54xx_config_intr,
+ .driver = { .owner = THIS_MODULE },
+};
+
+static struct phy_driver bcm5461_driver = {
+ .phy_id = 0x002060c0,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Broadcom BCM5461",
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
+ .config_init = bcm54xx_config_init,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .ack_interrupt = bcm54xx_ack_interrupt,
+ .config_intr = bcm54xx_config_intr,
+ .driver = { .owner = THIS_MODULE },
+};
+
+static int __init broadcom_init(void)
+{
+ int ret;
+
+ ret = phy_driver_register(&bcm5411_driver);
+ if (ret)
+ goto out_5411;
+ ret = phy_driver_register(&bcm5421_driver);
+ if (ret)
+ goto out_5421;
+ ret = phy_driver_register(&bcm5461_driver);
+ if (ret)
+ goto out_5461;
+ return ret;
+
+out_5461:
+ phy_driver_unregister(&bcm5421_driver);
+out_5421:
+ phy_driver_unregister(&bcm5411_driver);
+out_5411:
+ return ret;
+}
+
+static void __exit broadcom_exit(void)
+{
+ phy_driver_unregister(&bcm5461_driver);
+ phy_driver_unregister(&bcm5421_driver);
+ phy_driver_unregister(&bcm5411_driver);
+}
+
+module_init(broadcom_init);
+module_exit(broadcom_exit);
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index a443976d5dcf..4044bb1ada86 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -7,6 +7,7 @@
* Author: Andy Fleming
*
* Copyright (c) 2004 Freescale Semiconductor, Inc.
+ * Copyright (c) 2006 Maciej W. Rozycki
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -32,6 +33,8 @@
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/phy.h>
+#include <linux/timer.h>
+#include <linux/workqueue.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -484,6 +487,9 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)
{
struct phy_device *phydev = phy_dat;
+ if (PHY_HALTED == phydev->state)
+ return IRQ_NONE; /* It can't be ours. */
+
/* The MDIO bus is not allowed to be written in interrupt
* context, so we need to disable the irq here. A work
* queue will write the PHY to disable and clear the
@@ -577,6 +583,13 @@ int phy_stop_interrupts(struct phy_device *phydev)
if (err)
phy_error(phydev);
+ /*
+ * Finish any pending work; we might have been scheduled
+ * to be called from keventd ourselves, though.
+ */
+ if (!current_is_keventd())
+ flush_scheduled_work();
+
free_irq(phydev->irq, phydev);
return err;
@@ -604,7 +617,8 @@ static void phy_change(struct work_struct *work)
enable_irq(phydev->irq);
/* Reenable interrupts */
- err = phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED);
+ if (PHY_HALTED != phydev->state)
+ err = phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED);
if (err)
goto irq_enable_err;
@@ -625,18 +639,24 @@ void phy_stop(struct phy_device *phydev)
if (PHY_HALTED == phydev->state)
goto out_unlock;
- if (phydev->irq != PHY_POLL) {
- /* Clear any pending interrupts */
- phy_clear_interrupt(phydev);
+ phydev->state = PHY_HALTED;
+ if (phydev->irq != PHY_POLL) {
/* Disable PHY Interrupts */
phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED);
- }
- phydev->state = PHY_HALTED;
+ /* Clear any pending interrupts */
+ phy_clear_interrupt(phydev);
+ }
out_unlock:
spin_unlock(&phydev->lock);
+
+ /*
+ * Cannot call flush_scheduled_work() here as desired because
+ * of rtnl_lock(), but PHY_HALTED shall guarantee phy_change()
+ * will not reenable interrupts.
+ */
}
@@ -694,60 +714,57 @@ static void phy_timer(unsigned long data)
break;
case PHY_AN:
+ err = phy_read_status(phydev);
+
+ if (err < 0)
+ break;
+
+ /* If the link is down, give up on
+ * negotiation for now */
+ if (!phydev->link) {
+ phydev->state = PHY_NOLINK;
+ netif_carrier_off(phydev->attached_dev);
+ phydev->adjust_link(phydev->attached_dev);
+ break;
+ }
+
/* Check if negotiation is done. Break
* if there's an error */
err = phy_aneg_done(phydev);
if (err < 0)
break;
- /* If auto-negotiation is done, we change to
- * either RUNNING, or NOLINK */
+ /* If AN is done, we're running */
if (err > 0) {
- err = phy_read_status(phydev);
+ phydev->state = PHY_RUNNING;
+ netif_carrier_on(phydev->attached_dev);
+ phydev->adjust_link(phydev->attached_dev);
+
+ } else if (0 == phydev->link_timeout--) {
+ int idx;
- if (err)
+ needs_aneg = 1;
+ /* If we have the magic_aneg bit,
+ * we try again */
+ if (phydev->drv->flags & PHY_HAS_MAGICANEG)
break;
- if (phydev->link) {
- phydev->state = PHY_RUNNING;
- netif_carrier_on(phydev->attached_dev);
- } else {
- phydev->state = PHY_NOLINK;
- netif_carrier_off(phydev->attached_dev);
- }
+ /* The timer expired, and we still
+ * don't have a setting, so we try
+ * forcing it until we find one that
+ * works, starting from the fastest speed,
+ * and working our way down */
+ idx = phy_find_valid(0, phydev->supported);
- phydev->adjust_link(phydev->attached_dev);
+ phydev->speed = settings[idx].speed;
+ phydev->duplex = settings[idx].duplex;
- } else if (0 == phydev->link_timeout--) {
- /* The counter expired, so either we
- * switch to forced mode, or the
- * magic_aneg bit exists, and we try aneg
- * again */
- if (!(phydev->drv->flags & PHY_HAS_MAGICANEG)) {
- int idx;
-
- /* We'll start from the
- * fastest speed, and work
- * our way down */
- idx = phy_find_valid(0,
- phydev->supported);
-
- phydev->speed = settings[idx].speed;
- phydev->duplex = settings[idx].duplex;
-
- phydev->autoneg = AUTONEG_DISABLE;
- phydev->state = PHY_FORCING;
- phydev->link_timeout =
- PHY_FORCE_TIMEOUT;
-
- pr_info("Trying %d/%s\n",
- phydev->speed,
- DUPLEX_FULL ==
- phydev->duplex ?
- "FULL" : "HALF");
- }
+ phydev->autoneg = AUTONEG_DISABLE;
- needs_aneg = 1;
+ pr_info("Trying %d/%s\n", phydev->speed,
+ DUPLEX_FULL ==
+ phydev->duplex ?
+ "FULL" : "HALF");
}
break;
case PHY_NOLINK:
@@ -763,7 +780,7 @@ static void phy_timer(unsigned long data)
}
break;
case PHY_FORCING:
- err = phy_read_status(phydev);
+ err = genphy_update_link(phydev);
if (err)
break;
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 3bbd5e70c209..b01fc70a57db 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -59,6 +59,7 @@ struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id)
dev->duplex = -1;
dev->pause = dev->asym_pause = 0;
dev->link = 1;
+ dev->interface = PHY_INTERFACE_MODE_GMII;
dev->autoneg = AUTONEG_ENABLE;
@@ -137,11 +138,12 @@ void phy_prepare_link(struct phy_device *phydev,
* the desired functionality.
*/
struct phy_device * phy_connect(struct net_device *dev, const char *phy_id,
- void (*handler)(struct net_device *), u32 flags)
+ void (*handler)(struct net_device *), u32 flags,
+ u32 interface)
{
struct phy_device *phydev;
- phydev = phy_attach(dev, phy_id, flags);
+ phydev = phy_attach(dev, phy_id, flags, interface);
if (IS_ERR(phydev))
return phydev;
@@ -186,7 +188,7 @@ static int phy_compare_id(struct device *dev, void *data)
}
struct phy_device *phy_attach(struct net_device *dev,
- const char *phy_id, u32 flags)
+ const char *phy_id, u32 flags, u32 interface)
{
struct bus_type *bus = &mdio_bus_type;
struct phy_device *phydev;
@@ -231,6 +233,20 @@ struct phy_device *phy_attach(struct net_device *dev,
phydev->dev_flags = flags;
+ phydev->interface = interface;
+
+ /* Do initial configuration here, now that
+ * we have certain key parameters
+ * (dev_flags and interface) */
+ if (phydev->drv->config_init) {
+ int err;
+
+ err = phydev->drv->config_init(phydev);
+
+ if (err < 0)
+ return ERR_PTR(err);
+ }
+
return phydev;
}
EXPORT_SYMBOL(phy_attach);
@@ -427,6 +443,7 @@ int genphy_update_link(struct phy_device *phydev)
return 0;
}
+EXPORT_SYMBOL(genphy_update_link);
/* genphy_read_status
*
@@ -611,13 +628,8 @@ static int phy_probe(struct device *dev)
spin_unlock(&phydev->lock);
- if (err < 0)
- return err;
-
- if (phydev->drv->config_init)
- err = phydev->drv->config_init(phydev);
-
return err;
+
}
static int phy_remove(struct device *dev)
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index f5802e7b08e9..c6de566188e4 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -860,7 +860,7 @@ static int __init ppp_init(void)
err = PTR_ERR(ppp_class);
goto out_chrdev;
}
- class_device_create(ppp_class, NULL, MKDEV(PPP_MAJOR, 0), NULL, "ppp");
+ device_create(ppp_class, NULL, MKDEV(PPP_MAJOR, 0), "ppp");
}
out:
@@ -2675,7 +2675,7 @@ static void __exit ppp_cleanup(void)
cardmap_destroy(&all_ppp_units);
if (unregister_chrdev(PPP_MAJOR, "ppp") != 0)
printk(KERN_ERR "PPP: failed to unregister PPP device\n");
- class_device_destroy(ppp_class, MKDEV(PPP_MAJOR, 0));
+ device_destroy(ppp_class, MKDEV(PPP_MAJOR, 0));
class_destroy(ppp_class);
}
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index 0adee733b761..315d5c3fc66a 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -393,7 +393,7 @@ static int pppoe_rcv(struct sk_buff *skb,
po = get_item((unsigned long) ph->sid, eth_hdr(skb)->h_source);
if (po != NULL)
- return sk_receive_skb(sk_pppox(po), skb);
+ return sk_receive_skb(sk_pppox(po), skb, 0);
drop:
kfree_skb(skb);
out:
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 1f9663a70823..85a392fab5cc 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -572,8 +572,8 @@ static void rtl8169_xmii_reset_enable(void __iomem *ioaddr)
{
unsigned int val;
- val = (mdio_read(ioaddr, MII_BMCR) | BMCR_RESET) & 0xffff;
- mdio_write(ioaddr, MII_BMCR, val);
+ mdio_write(ioaddr, MII_BMCR, BMCR_RESET);
+ val = mdio_read(ioaddr, MII_BMCR);
}
static void rtl8169_check_link_status(struct net_device *dev,
@@ -1407,6 +1407,22 @@ static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev,
free_netdev(dev);
}
+static void rtl8169_phy_reset(struct net_device *dev,
+ struct rtl8169_private *tp)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+ int i;
+
+ tp->phy_reset_enable(ioaddr);
+ for (i = 0; i < 100; i++) {
+ if (!tp->phy_reset_pending(ioaddr))
+ return;
+ msleep(1);
+ }
+ if (netif_msg_link(tp))
+ printk(KERN_ERR "%s: PHY reset failed.\n", dev->name);
+}
+
static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp)
{
void __iomem *ioaddr = tp->mmio_addr;
@@ -1435,6 +1451,8 @@ static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp)
rtl8169_link_option(board_idx, &autoneg, &speed, &duplex);
+ rtl8169_phy_reset(dev, tp);
+
rtl8169_set_speed(dev, autoneg, speed, duplex);
if ((RTL_R8(PHYstatus) & TBI_Enable) && netif_msg_link(tp))
@@ -1474,8 +1492,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
struct rtl8169_private *tp;
struct net_device *dev;
void __iomem *ioaddr;
- unsigned int i, pm_cap;
- int rc;
+ unsigned int pm_cap;
+ int i, rc;
if (netif_msg_drv(&debug)) {
printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n",
diff --git a/drivers/net/sk98lin/h/skdrv2nd.h b/drivers/net/sk98lin/h/skdrv2nd.h
index 778d9e618ebd..3fa67171e832 100644
--- a/drivers/net/sk98lin/h/skdrv2nd.h
+++ b/drivers/net/sk98lin/h/skdrv2nd.h
@@ -160,7 +160,7 @@ struct s_IOCTL {
/*
** Interim definition of SK_DRV_TIMER placed in this file until
-** common modules have boon finallized
+** common modules have been finalized
*/
#define SK_DRV_TIMER 11
#define SK_DRV_MODERATION_TIMER 1
diff --git a/drivers/net/sk98lin/skdim.c b/drivers/net/sk98lin/skdim.c
index 07c1b4c8699d..37ce03fb8de3 100644
--- a/drivers/net/sk98lin/skdim.c
+++ b/drivers/net/sk98lin/skdim.c
@@ -252,7 +252,7 @@ SkDimEnableModerationIfNeeded(SK_AC *pAC) {
/*******************************************************************************
** Function : SkDimDisplayModerationSettings
-** Description : Displays the current settings regaring interrupt moderation
+** Description : Displays the current settings regarding interrupt moderation
** Programmer : Ralph Roesler
** Last Modified: 22-mar-03
** Returns : void (!)
@@ -510,7 +510,7 @@ EnableIntMod(SK_AC *pAC) {
/*******************************************************************************
** Function : DisableIntMod()
-** Description : Disbles the interrupt moderation independent of what inter-
+** Description : Disables the interrupt moderation independent of what inter-
** rupts are running or not
** Programmer : Ralph Roesler
** Last Modified: 23-mar-03
diff --git a/drivers/net/sk98lin/skethtool.c b/drivers/net/sk98lin/skethtool.c
index e5cb5b548b88..36460694eb82 100644
--- a/drivers/net/sk98lin/skethtool.c
+++ b/drivers/net/sk98lin/skethtool.c
@@ -581,6 +581,30 @@ static int setRxCsum(struct net_device *dev, u32 data)
return 0;
}
+static int getRegsLen(struct net_device *dev)
+{
+ return 0x4000;
+}
+
+/*
+ * Returns copy of whole control register region
+ * Note: skip RAM address register because accessing it will
+ * cause bus hangs!
+ */
+static void getRegs(struct net_device *dev, struct ethtool_regs *regs,
+ void *p)
+{
+ DEV_NET *pNet = netdev_priv(dev);
+ const void __iomem *io = pNet->pAC->IoBase;
+
+ regs->version = 1;
+ memset(p, 0, regs->len);
+ memcpy_fromio(p, io, B3_RAM_ADDR);
+
+ memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1,
+ regs->len - B3_RI_WTO_R1);
+}
+
const struct ethtool_ops SkGeEthtoolOps = {
.get_settings = getSettings,
.set_settings = setSettings,
@@ -599,4 +623,6 @@ const struct ethtool_ops SkGeEthtoolOps = {
.set_tx_csum = setTxCsum,
.get_rx_csum = getRxCsum,
.set_rx_csum = setRxCsum,
+ .get_regs = getRegs,
+ .get_regs_len = getRegsLen,
};
diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
index d4913c3de2a1..12cbfd190dd7 100644
--- a/drivers/net/sk98lin/skge.c
+++ b/drivers/net/sk98lin/skge.c
@@ -113,6 +113,7 @@
#include <linux/init.h>
#include <linux/dma-mapping.h>
#include <linux/ip.h>
+#include <linux/mii.h>
#include "h/skdrv1st.h"
#include "h/skdrv2nd.h"
@@ -1561,7 +1562,7 @@ struct sk_buff *pMessage) /* pointer to send-message */
if (pMessage->ip_summed == CHECKSUM_PARTIAL) {
u16 hdrlen = pMessage->h.raw - pMessage->data;
- u16 offset = hdrlen + pMessage->csum;
+ u16 offset = hdrlen + pMessage->csum_offset;
if ((pMessage->h.ipiph->protocol == IPPROTO_UDP ) &&
(pAC->GIni.GIChipRev == 0) &&
@@ -1680,7 +1681,7 @@ struct sk_buff *pMessage) /* pointer to send-message */
*/
if (pMessage->ip_summed == CHECKSUM_PARTIAL) {
u16 hdrlen = pMessage->h.raw - pMessage->data;
- u16 offset = hdrlen + pMessage->csum;
+ u16 offset = hdrlen + pMessage->csum_offset;
Control = BMU_STFWD;
@@ -2843,6 +2844,56 @@ unsigned long Flags; /* for spin lock */
return(&pAC->stats);
} /* SkGeStats */
+/*
+ * Basic MII register access
+ */
+static int SkGeMiiIoctl(struct net_device *dev,
+ struct mii_ioctl_data *data, int cmd)
+{
+ DEV_NET *pNet = netdev_priv(dev);
+ SK_AC *pAC = pNet->pAC;
+ SK_IOC IoC = pAC->IoBase;
+ int Port = pNet->PortNr;
+ SK_GEPORT *pPrt = &pAC->GIni.GP[Port];
+ unsigned long Flags;
+ int err = 0;
+ int reg = data->reg_num & 0x1f;
+ SK_U16 val = data->val_in;
+
+ if (!netif_running(dev))
+ return -ENODEV; /* Phy still in reset */
+
+ spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+ switch(cmd) {
+ case SIOCGMIIPHY:
+ data->phy_id = pPrt->PhyAddr;
+
+ /* fallthru */
+ case SIOCGMIIREG:
+ if (pAC->GIni.GIGenesis)
+ SkXmPhyRead(pAC, IoC, Port, reg, &val);
+ else
+ SkGmPhyRead(pAC, IoC, Port, reg, &val);
+
+ data->val_out = val;
+ break;
+
+ case SIOCSMIIREG:
+ if (!capable(CAP_NET_ADMIN))
+ err = -EPERM;
+
+ else if (pAC->GIni.GIGenesis)
+ SkXmPhyWrite(pAC, IoC, Port, reg, val);
+ else
+ SkGmPhyWrite(pAC, IoC, Port, reg, val);
+ break;
+ default:
+ err = -EOPNOTSUPP;
+ }
+ spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+ return err;
+}
+
/*****************************************************************************
*
@@ -2876,6 +2927,9 @@ int HeaderLength = sizeof(SK_U32) + sizeof(SK_U32);
pNet = netdev_priv(dev);
pAC = pNet->pAC;
+ if (cmd == SIOCGMIIPHY || cmd == SIOCSMIIREG || cmd == SIOCGMIIREG)
+ return SkGeMiiIoctl(dev, if_mii(rq), cmd);
+
if(copy_from_user(&Ioctl, rq->ifr_data, sizeof(SK_GE_IOCTL))) {
return -EFAULT;
}
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index 3b67614372a7..b60f0451f6cd 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -2155,8 +2155,6 @@ static void yukon_link_down(struct skge_port *skge)
int port = skge->port;
u16 ctrl;
- gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);
-
ctrl = gma_read16(hw, port, GM_GP_CTRL);
ctrl &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
gma_write16(hw, port, GM_GP_CTRL, ctrl);
@@ -2168,7 +2166,6 @@ static void yukon_link_down(struct skge_port *skge)
gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, ctrl);
}
- yukon_reset(hw, port);
skge_link_down(skge);
yukon_init(hw, port);
@@ -2256,6 +2253,7 @@ static void skge_phy_reset(struct skge_port *skge)
{
struct skge_hw *hw = skge->hw;
int port = skge->port;
+ struct net_device *dev = hw->dev[port];
netif_stop_queue(skge->netdev);
netif_carrier_off(skge->netdev);
@@ -2269,6 +2267,8 @@ static void skge_phy_reset(struct skge_port *skge)
yukon_init(hw, port);
}
mutex_unlock(&hw->phy_mutex);
+
+ dev->set_multicast_list(dev);
}
/* Basic MII support */
@@ -2566,7 +2566,7 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev)
td->csum_offs = 0;
td->csum_start = offset;
- td->csum_write = offset + skb->csum;
+ td->csum_write = offset + skb->csum_offset;
} else
control = BMU_CHECK;
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 16616f5440d0..842abd9396c6 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -104,6 +104,7 @@ static const struct pci_device_id sky2_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) },
{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b00) }, /* DGE-560T */
{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4001) }, /* DGE-550SX */
+ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4B02) }, /* DGE-560SX */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4340) },
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4341) },
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4342) },
@@ -676,17 +677,15 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
/* Flush Rx MAC FIFO on any flow control or error */
sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), GMR_FS_ANY_ERR);
- /* Set threshold to 0xa (64 bytes)
- * ASF disabled so no need to do WA dev #4.30
- */
- sky2_write16(hw, SK_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF);
+ /* Set threshold to 0xa (64 bytes) + 1 to workaround pause bug */
+ sky2_write16(hw, SK_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF+1);
/* Configure Tx MAC FIFO */
sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR);
sky2_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON);
if (hw->chip_id == CHIP_ID_YUKON_EC_U) {
- sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 512/8);
+ sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8);
sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8);
if (hw->dev[port]->mtu > ETH_DATA_LEN) {
/* set Tx GMAC FIFO Almost Empty Threshold */
@@ -1060,7 +1059,8 @@ static int sky2_rx_start(struct sky2_port *sky2)
sky2->rx_put = sky2->rx_next = 0;
sky2_qset(hw, rxq);
- if (hw->chip_id == CHIP_ID_YUKON_EC_U && hw->chip_rev >= 2) {
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U &&
+ (hw->chip_rev == CHIP_REV_YU_EC_U_A1 || hw->chip_rev == CHIP_REV_YU_EC_U_B0)) {
/* MAC Rx RAM Read is controlled by hardware */
sky2_write32(hw, Q_ADDR(rxq, Q_F), F_M_RX_RAM_DIS);
}
@@ -1350,7 +1350,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
u32 tcpsum;
tcpsum = offset << 16; /* sum start */
- tcpsum |= offset + skb->csum; /* sum write */
+ tcpsum |= offset + skb->csum_offset; /* sum write */
ctrl = CALSUM | WR_SUM | INIT_SUM | LOCK_SUM;
if (skb->nh.iph->protocol == IPPROTO_UDP)
@@ -1453,7 +1453,7 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
if (unlikely(netif_msg_tx_done(sky2)))
printk(KERN_DEBUG "%s: tx done %u\n",
dev->name, idx);
- dev_kfree_skb(re->skb);
+ dev_kfree_skb_any(re->skb);
}
le->opcode = 0; /* paranoia */
@@ -1509,7 +1509,7 @@ static int sky2_down(struct net_device *dev)
/* WA for dev. #4.209 */
if (hw->chip_id == CHIP_ID_YUKON_EC_U
- && hw->chip_rev == CHIP_REV_YU_EC_U_A1)
+ && (hw->chip_rev == CHIP_REV_YU_EC_U_A1 || hw->chip_rev == CHIP_REV_YU_EC_U_B0))
sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
sky2->speed != SPEED_1000 ?
TX_STFW_ENA : TX_STFW_DIS);
@@ -2065,7 +2065,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
case OP_RXSTAT:
skb = sky2_receive(dev, length, status);
if (!skb)
- break;
+ goto force_update;
skb->protocol = eth_type_trans(skb, dev);
dev->last_rx = jiffies;
@@ -2081,8 +2081,8 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
/* Update receiver after 16 frames */
if (++buf_write[le->link] == RX_BUF_WRITE) {
- sky2_put_idx(hw, rxqaddr[le->link],
- sky2->rx_put);
+force_update:
+ sky2_put_idx(hw, rxqaddr[le->link], sky2->rx_put);
buf_write[le->link] = 0;
}
@@ -3311,7 +3311,7 @@ static irqreturn_t __devinit sky2_test_intr(int irq, void *dev_id)
return IRQ_NONE;
if (status & Y2_IS_IRQ_SW) {
- hw->msi_detected = 1;
+ hw->msi = 1;
wake_up(&hw->msi_wait);
sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ);
}
@@ -3330,7 +3330,7 @@ static int __devinit sky2_test_msi(struct sky2_hw *hw)
sky2_write32(hw, B0_IMSK, Y2_IS_IRQ_SW);
- err = request_irq(pdev->irq, sky2_test_intr, IRQF_SHARED, DRV_NAME, hw);
+ err = request_irq(pdev->irq, sky2_test_intr, 0, DRV_NAME, hw);
if (err) {
printk(KERN_ERR PFX "%s: cannot assign irq %d\n",
pci_name(pdev), pdev->irq);
@@ -3340,9 +3340,9 @@ static int __devinit sky2_test_msi(struct sky2_hw *hw)
sky2_write8(hw, B0_CTST, CS_ST_SW_IRQ);
sky2_read8(hw, B0_CTST);
- wait_event_timeout(hw->msi_wait, hw->msi_detected, HZ/10);
+ wait_event_timeout(hw->msi_wait, hw->msi, HZ/10);
- if (!hw->msi_detected) {
+ if (!hw->msi) {
/* MSI test failed, go back to INTx mode */
printk(KERN_INFO PFX "%s: No interrupt generated using MSI, "
"switching to INTx mode.\n",
@@ -3475,7 +3475,8 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
goto err_out_free_netdev;
}
- err = request_irq(pdev->irq, sky2_intr, IRQF_SHARED, dev->name, hw);
+ err = request_irq(pdev->irq, sky2_intr, hw->msi ? 0 : IRQF_SHARED,
+ dev->name, hw);
if (err) {
printk(KERN_ERR PFX "%s: cannot assign irq %d\n",
pci_name(pdev), pdev->irq);
@@ -3505,7 +3506,8 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
return 0;
err_out_unregister:
- pci_disable_msi(pdev);
+ if (hw->msi)
+ pci_disable_msi(pdev);
unregister_netdev(dev);
err_out_free_netdev:
free_netdev(dev);
@@ -3548,7 +3550,8 @@ static void __devexit sky2_remove(struct pci_dev *pdev)
sky2_read8(hw, B0_CTST);
free_irq(pdev->irq, hw);
- pci_disable_msi(pdev);
+ if (hw->msi)
+ pci_disable_msi(pdev);
pci_free_consistent(pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma);
pci_release_regions(pdev);
pci_disable_device(pdev);
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
index 6d2a23f66c9a..7760545edbf2 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/sky2.h
@@ -383,8 +383,13 @@ enum {
CHIP_REV_YU_EC_A2 = 1, /* Chip Rev. for Yukon-EC A2 */
CHIP_REV_YU_EC_A3 = 2, /* Chip Rev. for Yukon-EC A3 */
- CHIP_REV_YU_EC_U_A0 = 0,
- CHIP_REV_YU_EC_U_A1 = 1,
+ CHIP_REV_YU_EC_U_A0 = 1,
+ CHIP_REV_YU_EC_U_A1 = 2,
+ CHIP_REV_YU_EC_U_B0 = 3,
+
+ CHIP_REV_YU_FE_A1 = 1,
+ CHIP_REV_YU_FE_A2 = 2,
+
};
/* B2_Y2_CLK_GATE 8 bit Clock Gating (Yukon-2 only) */
@@ -1895,7 +1900,7 @@ struct sky2_hw {
dma_addr_t st_dma;
struct timer_list idle_timer;
- int msi_detected;
+ int msi;
wait_queue_head_t msi_wait;
};
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index f88fcac0e46a..f16f696c1ff2 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/spider_net.c
@@ -644,20 +644,12 @@ spider_net_prepare_tx_descr(struct spider_net_card *card,
struct spider_net_descr *descr;
dma_addr_t buf;
unsigned long flags;
- int length;
- length = skb->len;
- if (length < ETH_ZLEN) {
- if (skb_pad(skb, ETH_ZLEN-length))
- return 0;
- length = ETH_ZLEN;
- }
-
- buf = pci_map_single(card->pdev, skb->data, length, PCI_DMA_TODEVICE);
+ buf = pci_map_single(card->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
if (pci_dma_mapping_error(buf)) {
if (netif_msg_tx_err(card) && net_ratelimit())
pr_err("could not iommu-map packet (%p, %i). "
- "Dropping packet\n", skb->data, length);
+ "Dropping packet\n", skb->data, skb->len);
card->spider_stats.tx_iommu_map_error++;
return -ENOMEM;
}
@@ -667,7 +659,7 @@ spider_net_prepare_tx_descr(struct spider_net_card *card,
card->tx_chain.head = descr->next;
descr->buf_addr = buf;
- descr->buf_size = length;
+ descr->buf_size = skb->len;
descr->next_descr_addr = 0;
descr->skb = skb;
descr->data_status = 0;
@@ -802,8 +794,8 @@ spider_net_release_tx_chain(struct spider_net_card *card, int brutal)
/* unmap the skb */
if (skb) {
- int len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
- pci_unmap_single(card->pdev, buf_addr, len, PCI_DMA_TODEVICE);
+ pci_unmap_single(card->pdev, buf_addr, skb->len,
+ PCI_DMA_TODEVICE);
dev_kfree_skb(skb);
}
}
@@ -1641,7 +1633,7 @@ spider_net_enable_card(struct spider_net_card *card)
SPIDER_NET_INT2_MASK_VALUE);
spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR,
- SPIDER_NET_GDTBSTA | SPIDER_NET_GDTDCEIDIS);
+ SPIDER_NET_GDTBSTA);
}
/**
diff --git a/drivers/net/spider_net.h b/drivers/net/spider_net.h
index b3b46119b424..3e196df29790 100644
--- a/drivers/net/spider_net.h
+++ b/drivers/net/spider_net.h
@@ -24,7 +24,7 @@
#ifndef _SPIDER_NET_H
#define _SPIDER_NET_H
-#define VERSION "1.1 A"
+#define VERSION "1.6 A"
#include "sungem_phy.h"
@@ -217,8 +217,7 @@ extern char spider_net_driver_name[];
#define SPIDER_NET_GDTBSTA 0x00000300
#define SPIDER_NET_GDTDCEIDIS 0x00000002
#define SPIDER_NET_DMA_TX_VALUE SPIDER_NET_TX_DMA_EN | \
- SPIDER_NET_GDTBSTA | \
- SPIDER_NET_GDTDCEIDIS
+ SPIDER_NET_GDTBSTA
#define SPIDER_NET_DMA_TX_FEND_VALUE 0x00030003
@@ -328,7 +327,8 @@ enum spider_net_int2_status {
SPIDER_NET_GRISPDNGINT
};
-#define SPIDER_NET_TXINT ( (1 << SPIDER_NET_GDTFDCINT) )
+#define SPIDER_NET_TXINT ( (1 << SPIDER_NET_GDTFDCINT) | \
+ (1 << SPIDER_NET_GDTDCEINT) )
/* We rely on flagged descriptor interrupts */
#define SPIDER_NET_RXINT ( (1 << SPIDER_NET_GDAFDCINT) )
diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c
index 41c503d8bac4..c06ecc8002b9 100644
--- a/drivers/net/sundance.c
+++ b/drivers/net/sundance.c
@@ -264,8 +264,6 @@ enum alta_offsets {
ASICCtrl = 0x30,
EEData = 0x34,
EECtrl = 0x36,
- TxStartThresh = 0x3c,
- RxEarlyThresh = 0x3e,
FlashAddr = 0x40,
FlashData = 0x44,
TxStatus = 0x46,
@@ -790,6 +788,7 @@ static int netdev_open(struct net_device *dev)
{
struct netdev_private *np = netdev_priv(dev);
void __iomem *ioaddr = np->base;
+ unsigned long flags;
int i;
/* Do we need to reset the chip??? */
@@ -834,6 +833,10 @@ static int netdev_open(struct net_device *dev)
iowrite8(0x01, ioaddr + DebugCtrl1);
netif_start_queue(dev);
+ spin_lock_irqsave(&np->lock, flags);
+ reset_tx(dev);
+ spin_unlock_irqrestore(&np->lock, flags);
+
iowrite16 (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl1);
if (netif_msg_ifup(np))
@@ -1081,6 +1084,8 @@ reset_tx (struct net_device *dev)
/* free all tx skbuff */
for (i = 0; i < TX_RING_SIZE; i++) {
+ np->tx_ring[i].next_desc = 0;
+
skb = np->tx_skbuff[i];
if (skb) {
pci_unmap_single(np->pci_dev,
@@ -1096,6 +1101,10 @@ reset_tx (struct net_device *dev)
}
np->cur_tx = np->dirty_tx = 0;
np->cur_task = 0;
+
+ np->last_tx = NULL;
+ iowrite8(127, ioaddr + TxDMAPollPeriod);
+
iowrite16 (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl1);
return 0;
}
@@ -1111,6 +1120,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance)
int tx_cnt;
int tx_status;
int handled = 0;
+ int i;
do {
@@ -1153,21 +1163,24 @@ static irqreturn_t intr_handler(int irq, void *dev_instance)
np->stats.tx_fifo_errors++;
if (tx_status & 0x02)
np->stats.tx_window_errors++;
+
/*
** This reset has been verified on
** DFE-580TX boards ! phdm@macqel.be.
*/
if (tx_status & 0x10) { /* TxUnderrun */
- unsigned short txthreshold;
-
- txthreshold = ioread16 (ioaddr + TxStartThresh);
/* Restart Tx FIFO and transmitter */
sundance_reset(dev, (NetworkReset|FIFOReset|TxReset) << 16);
- iowrite16 (txthreshold, ioaddr + TxStartThresh);
/* No need to reset the Tx pointer here */
}
- /* Restart the Tx. */
- iowrite16 (TxEnable, ioaddr + MACCtrl1);
+ /* Restart the Tx. Need to make sure tx enabled */
+ i = 10;
+ do {
+ iowrite16(ioread16(ioaddr + MACCtrl1) | TxEnable, ioaddr + MACCtrl1);
+ if (ioread16(ioaddr + MACCtrl1) & TxEnabled)
+ break;
+ mdelay(1);
+ } while (--i);
}
/* Yup, this is a documentation bug. It cost me *hours*. */
iowrite16 (0, ioaddr + TxStatus);
@@ -1629,6 +1642,14 @@ static int netdev_close(struct net_device *dev)
struct sk_buff *skb;
int i;
+ /* Wait and kill tasklet */
+ tasklet_kill(&np->rx_tasklet);
+ tasklet_kill(&np->tx_tasklet);
+ np->cur_tx = 0;
+ np->dirty_tx = 0;
+ np->cur_task = 0;
+ np->last_tx = NULL;
+
netif_stop_queue(dev);
if (netif_msg_ifdown(np)) {
@@ -1643,12 +1664,26 @@ static int netdev_close(struct net_device *dev)
/* Disable interrupts by clearing the interrupt mask. */
iowrite16(0x0000, ioaddr + IntrEnable);
+ /* Disable Rx and Tx DMA for safely release resource */
+ iowrite32(0x500, ioaddr + DMACtrl);
+
/* Stop the chip's Tx and Rx processes. */
iowrite16(TxDisable | RxDisable | StatsDisable, ioaddr + MACCtrl1);
- /* Wait and kill tasklet */
- tasklet_kill(&np->rx_tasklet);
- tasklet_kill(&np->tx_tasklet);
+ for (i = 2000; i > 0; i--) {
+ if ((ioread32(ioaddr + DMACtrl) & 0xc000) == 0)
+ break;
+ mdelay(1);
+ }
+
+ iowrite16(GlobalReset | DMAReset | FIFOReset | NetworkReset,
+ ioaddr +ASICCtrl + 2);
+
+ for (i = 2000; i > 0; i--) {
+ if ((ioread16(ioaddr + ASICCtrl +2) & ResetBusy) == 0)
+ break;
+ mdelay(1);
+ }
#ifdef __i386__
if (netif_msg_hw(np)) {
@@ -1686,6 +1721,7 @@ static int netdev_close(struct net_device *dev)
}
}
for (i = 0; i < TX_RING_SIZE; i++) {
+ np->tx_ring[i].next_desc = 0;
skb = np->tx_skbuff[i];
if (skb) {
pci_unmap_single(np->pci_dev,
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index 004d651681ad..d03a9a849c06 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -1030,7 +1030,7 @@ static int gem_start_xmit(struct sk_buff *skb, struct net_device *dev)
u64 csum_start_off, csum_stuff_off;
csum_start_off = (u64) (skb->h.raw - skb->data);
- csum_stuff_off = (u64) ((skb->h.raw + skb->csum) - skb->data);
+ csum_stuff_off = csum_start_off + skb->csum_offset;
ctrl = (TXDCTRL_CENAB |
(csum_start_off << 15) |
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index 9d7cd130c19d..ec432ea879fb 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -2272,7 +2272,7 @@ static int happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev)
u32 csum_start_off, csum_stuff_off;
csum_start_off = (u32) (skb->h.raw - skb->data);
- csum_stuff_off = (u32) ((skb->h.raw + skb->csum) - skb->data);
+ csum_stuff_off = csum_start_off + skb->csum_offset;
tx_flags = (TXFLAG_OWN | TXFLAG_CSENABLE |
((csum_start_off << 14) & TXFLAG_CSBUFBEGIN) |
diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c
index cd142d0302bc..8f4ecc1109cb 100644
--- a/drivers/net/tokenring/olympic.c
+++ b/drivers/net/tokenring/olympic.c
@@ -1771,7 +1771,7 @@ static struct pci_driver olympic_driver = {
static int __init olympic_pci_init(void)
{
- return pci_module_init (&olympic_driver) ;
+ return pci_register_driver(&olympic_driver) ;
}
static void __exit olympic_pci_cleanup(void)
diff --git a/drivers/net/tsi108_eth.c b/drivers/net/tsi108_eth.c
new file mode 100644
index 000000000000..893808ab3742
--- /dev/null
+++ b/drivers/net/tsi108_eth.c
@@ -0,0 +1,1708 @@
+/*******************************************************************************
+
+ Copyright(c) 2006 Tundra Semiconductor 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 driver is based on the driver code originally developed
+ * for the Intel IOC80314 (ForestLake) Gigabit Ethernet by
+ * scott.wood@timesys.com * Copyright (C) 2003 TimeSys Corporation
+ *
+ * Currently changes from original version are:
+ * - porting to Tsi108-based platform and kernel 2.6 (kong.lai@tundra.com)
+ * - modifications to handle two ports independently and support for
+ * additional PHY devices (alexandre.bounine@tundra.com)
+ * - Get hardware information from platform device. (tie-fei.zang@freescale.com)
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/net.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/crc32.h>
+#include <linux/mii.h>
+#include <linux/device.h>
+#include <linux/pci.h>
+#include <linux/rtnetlink.h>
+#include <linux/timer.h>
+#include <linux/platform_device.h>
+#include <linux/etherdevice.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/tsi108.h>
+
+#include "tsi108_eth.h"
+
+#define MII_READ_DELAY 10000 /* max link wait time in msec */
+
+#define TSI108_RXRING_LEN 256
+
+/* NOTE: The driver currently does not support receiving packets
+ * larger than the buffer size, so don't decrease this (unless you
+ * want to add such support).
+ */
+#define TSI108_RXBUF_SIZE 1536
+
+#define TSI108_TXRING_LEN 256
+
+#define TSI108_TX_INT_FREQ 64
+
+/* Check the phy status every half a second. */
+#define CHECK_PHY_INTERVAL (HZ/2)
+
+static int tsi108_init_one(struct platform_device *pdev);
+static int tsi108_ether_remove(struct platform_device *pdev);
+
+struct tsi108_prv_data {
+ void __iomem *regs; /* Base of normal regs */
+ void __iomem *phyregs; /* Base of register bank used for PHY access */
+
+ unsigned int phy; /* Index of PHY for this interface */
+ unsigned int irq_num;
+ unsigned int id;
+
+ struct timer_list timer;/* Timer that triggers the check phy function */
+ unsigned int rxtail; /* Next entry in rxring to read */
+ unsigned int rxhead; /* Next entry in rxring to give a new buffer */
+ unsigned int rxfree; /* Number of free, allocated RX buffers */
+
+ unsigned int rxpending; /* Non-zero if there are still descriptors
+ * to be processed from a previous descriptor
+ * interrupt condition that has been cleared */
+
+ unsigned int txtail; /* Next TX descriptor to check status on */
+ unsigned int txhead; /* Next TX descriptor to use */
+
+ /* Number of free TX descriptors. This could be calculated from
+ * rxhead and rxtail if one descriptor were left unused to disambiguate
+ * full and empty conditions, but it's simpler to just keep track
+ * explicitly. */
+
+ unsigned int txfree;
+
+ unsigned int phy_ok; /* The PHY is currently powered on. */
+
+ /* PHY status (duplex is 1 for half, 2 for full,
+ * so that the default 0 indicates that neither has
+ * yet been configured). */
+
+ unsigned int link_up;
+ unsigned int speed;
+ unsigned int duplex;
+
+ tx_desc *txring;
+ rx_desc *rxring;
+ struct sk_buff *txskbs[TSI108_TXRING_LEN];
+ struct sk_buff *rxskbs[TSI108_RXRING_LEN];
+
+ dma_addr_t txdma, rxdma;
+
+ /* txlock nests in misclock and phy_lock */
+
+ spinlock_t txlock, misclock;
+
+ /* stats is used to hold the upper bits of each hardware counter,
+ * and tmpstats is used to hold the full values for returning
+ * to the caller of get_stats(). They must be separate in case
+ * an overflow interrupt occurs before the stats are consumed.
+ */
+
+ struct net_device_stats stats;
+ struct net_device_stats tmpstats;
+
+ /* These stats are kept separate in hardware, thus require individual
+ * fields for handling carry. They are combined in get_stats.
+ */
+
+ unsigned long rx_fcs; /* Add to rx_frame_errors */
+ unsigned long rx_short_fcs; /* Add to rx_frame_errors */
+ unsigned long rx_long_fcs; /* Add to rx_frame_errors */
+ unsigned long rx_underruns; /* Add to rx_length_errors */
+ unsigned long rx_overruns; /* Add to rx_length_errors */
+
+ unsigned long tx_coll_abort; /* Add to tx_aborted_errors/collisions */
+ unsigned long tx_pause_drop; /* Add to tx_aborted_errors */
+
+ unsigned long mc_hash[16];
+ u32 msg_enable; /* debug message level */
+ struct mii_if_info mii_if;
+ unsigned int init_media;
+};
+
+/* Structure for a device driver */
+
+static struct platform_driver tsi_eth_driver = {
+ .probe = tsi108_init_one,
+ .remove = tsi108_ether_remove,
+ .driver = {
+ .name = "tsi-ethernet",
+ },
+};
+
+static void tsi108_timed_checker(unsigned long dev_ptr);
+
+static void dump_eth_one(struct net_device *dev)
+{
+ struct tsi108_prv_data *data = netdev_priv(dev);
+
+ printk("Dumping %s...\n", dev->name);
+ printk("intstat %x intmask %x phy_ok %d"
+ " link %d speed %d duplex %d\n",
+ TSI_READ(TSI108_EC_INTSTAT),
+ TSI_READ(TSI108_EC_INTMASK), data->phy_ok,
+ data->link_up, data->speed, data->duplex);
+
+ printk("TX: head %d, tail %d, free %d, stat %x, estat %x, err %x\n",
+ data->txhead, data->txtail, data->txfree,
+ TSI_READ(TSI108_EC_TXSTAT),
+ TSI_READ(TSI108_EC_TXESTAT),
+ TSI_READ(TSI108_EC_TXERR));
+
+ printk("RX: head %d, tail %d, free %d, stat %x,"
+ " estat %x, err %x, pending %d\n\n",
+ data->rxhead, data->rxtail, data->rxfree,
+ TSI_READ(TSI108_EC_RXSTAT),
+ TSI_READ(TSI108_EC_RXESTAT),
+ TSI_READ(TSI108_EC_RXERR), data->rxpending);
+}
+
+/* Synchronization is needed between the thread and up/down events.
+ * Note that the PHY is accessed through the same registers for both
+ * interfaces, so this can't be made interface-specific.
+ */
+
+static DEFINE_SPINLOCK(phy_lock);
+
+static int tsi108_read_mii(struct tsi108_prv_data *data, int reg)
+{
+ unsigned i;
+
+ TSI_WRITE_PHY(TSI108_MAC_MII_ADDR,
+ (data->phy << TSI108_MAC_MII_ADDR_PHY) |
+ (reg << TSI108_MAC_MII_ADDR_REG));
+ TSI_WRITE_PHY(TSI108_MAC_MII_CMD, 0);
+ TSI_WRITE_PHY(TSI108_MAC_MII_CMD, TSI108_MAC_MII_CMD_READ);
+ for (i = 0; i < 100; i++) {
+ if (!(TSI_READ_PHY(TSI108_MAC_MII_IND) &
+ (TSI108_MAC_MII_IND_NOTVALID | TSI108_MAC_MII_IND_BUSY)))
+ break;
+ udelay(10);
+ }
+
+ if (i == 100)
+ return 0xffff;
+ else
+ return (TSI_READ_PHY(TSI108_MAC_MII_DATAIN));
+}
+
+static void tsi108_write_mii(struct tsi108_prv_data *data,
+ int reg, u16 val)
+{
+ unsigned i = 100;
+ TSI_WRITE_PHY(TSI108_MAC_MII_ADDR,
+ (data->phy << TSI108_MAC_MII_ADDR_PHY) |
+ (reg << TSI108_MAC_MII_ADDR_REG));
+ TSI_WRITE_PHY(TSI108_MAC_MII_DATAOUT, val);
+ while (i--) {
+ if(!(TSI_READ_PHY(TSI108_MAC_MII_IND) &
+ TSI108_MAC_MII_IND_BUSY))
+ break;
+ udelay(10);
+ }
+}
+
+static int tsi108_mdio_read(struct net_device *dev, int addr, int reg)
+{
+ struct tsi108_prv_data *data = netdev_priv(dev);
+ return tsi108_read_mii(data, reg);
+}
+
+static void tsi108_mdio_write(struct net_device *dev, int addr, int reg, int val)
+{
+ struct tsi108_prv_data *data = netdev_priv(dev);
+ tsi108_write_mii(data, reg, val);
+}
+
+static inline void tsi108_write_tbi(struct tsi108_prv_data *data,
+ int reg, u16 val)
+{
+ unsigned i = 1000;
+ TSI_WRITE(TSI108_MAC_MII_ADDR,
+ (0x1e << TSI108_MAC_MII_ADDR_PHY)
+ | (reg << TSI108_MAC_MII_ADDR_REG));
+ TSI_WRITE(TSI108_MAC_MII_DATAOUT, val);
+ while(i--) {
+ if(!(TSI_READ(TSI108_MAC_MII_IND) & TSI108_MAC_MII_IND_BUSY))
+ return;
+ udelay(10);
+ }
+ printk(KERN_ERR "%s function time out \n", __FUNCTION__);
+}
+
+static int mii_speed(struct mii_if_info *mii)
+{
+ int advert, lpa, val, media;
+ int lpa2 = 0;
+ int speed;
+
+ if (!mii_link_ok(mii))
+ return 0;
+
+ val = (*mii->mdio_read) (mii->dev, mii->phy_id, MII_BMSR);
+ if ((val & BMSR_ANEGCOMPLETE) == 0)
+ return 0;
+
+ advert = (*mii->mdio_read) (mii->dev, mii->phy_id, MII_ADVERTISE);
+ lpa = (*mii->mdio_read) (mii->dev, mii->phy_id, MII_LPA);
+ media = mii_nway_result(advert & lpa);
+
+ if (mii->supports_gmii)
+ lpa2 = mii->mdio_read(mii->dev, mii->phy_id, MII_STAT1000);
+
+ speed = lpa2 & (LPA_1000FULL | LPA_1000HALF) ? 1000 :
+ (media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ? 100 : 10);
+ return speed;
+}
+
+static void tsi108_check_phy(struct net_device *dev)
+{
+ struct tsi108_prv_data *data = netdev_priv(dev);
+ u32 mac_cfg2_reg, portctrl_reg;
+ u32 duplex;
+ u32 speed;
+ unsigned long flags;
+
+ /* Do a dummy read, as for some reason the first read
+ * after a link becomes up returns link down, even if
+ * it's been a while since the link came up.
+ */
+
+ spin_lock_irqsave(&phy_lock, flags);
+
+ if (!data->phy_ok)
+ goto out;
+
+ tsi108_read_mii(data, MII_BMSR);
+
+ duplex = mii_check_media(&data->mii_if, netif_msg_link(data), data->init_media);
+ data->init_media = 0;
+
+ if (netif_carrier_ok(dev)) {
+
+ speed = mii_speed(&data->mii_if);
+
+ if ((speed != data->speed) || duplex) {
+
+ mac_cfg2_reg = TSI_READ(TSI108_MAC_CFG2);
+ portctrl_reg = TSI_READ(TSI108_EC_PORTCTRL);
+
+ mac_cfg2_reg &= ~TSI108_MAC_CFG2_IFACE_MASK;
+
+ if (speed == 1000) {
+ mac_cfg2_reg |= TSI108_MAC_CFG2_GIG;
+ portctrl_reg &= ~TSI108_EC_PORTCTRL_NOGIG;
+ } else {
+ mac_cfg2_reg |= TSI108_MAC_CFG2_NOGIG;
+ portctrl_reg |= TSI108_EC_PORTCTRL_NOGIG;
+ }
+
+ data->speed = speed;
+
+ if (data->mii_if.full_duplex) {
+ mac_cfg2_reg |= TSI108_MAC_CFG2_FULLDUPLEX;
+ portctrl_reg &= ~TSI108_EC_PORTCTRL_HALFDUPLEX;
+ data->duplex = 2;
+ } else {
+ mac_cfg2_reg &= ~TSI108_MAC_CFG2_FULLDUPLEX;
+ portctrl_reg |= TSI108_EC_PORTCTRL_HALFDUPLEX;
+ data->duplex = 1;
+ }
+
+ TSI_WRITE(TSI108_MAC_CFG2, mac_cfg2_reg);
+ TSI_WRITE(TSI108_EC_PORTCTRL, portctrl_reg);
+
+ if (data->link_up == 0) {
+ /* The manual says it can take 3-4 usecs for the speed change
+ * to take effect.
+ */
+ udelay(5);
+
+ spin_lock(&data->txlock);
+ if (is_valid_ether_addr(dev->dev_addr) && data->txfree)
+ netif_wake_queue(dev);
+
+ data->link_up = 1;
+ spin_unlock(&data->txlock);
+ }
+ }
+
+ } else {
+ if (data->link_up == 1) {
+ netif_stop_queue(dev);
+ data->link_up = 0;
+ printk(KERN_NOTICE "%s : link is down\n", dev->name);
+ }
+
+ goto out;
+ }
+
+
+out:
+ spin_unlock_irqrestore(&phy_lock, flags);
+}
+
+static inline void
+tsi108_stat_carry_one(int carry, int carry_bit, int carry_shift,
+ unsigned long *upper)
+{
+ if (carry & carry_bit)
+ *upper += carry_shift;
+}
+
+static void tsi108_stat_carry(struct net_device *dev)
+{
+ struct tsi108_prv_data *data = netdev_priv(dev);
+ u32 carry1, carry2;
+
+ spin_lock_irq(&data->misclock);
+
+ carry1 = TSI_READ(TSI108_STAT_CARRY1);
+ carry2 = TSI_READ(TSI108_STAT_CARRY2);
+
+ TSI_WRITE(TSI108_STAT_CARRY1, carry1);
+ TSI_WRITE(TSI108_STAT_CARRY2, carry2);
+
+ tsi108_stat_carry_one(carry1, TSI108_STAT_CARRY1_RXBYTES,
+ TSI108_STAT_RXBYTES_CARRY, &data->stats.rx_bytes);
+
+ tsi108_stat_carry_one(carry1, TSI108_STAT_CARRY1_RXPKTS,
+ TSI108_STAT_RXPKTS_CARRY,
+ &data->stats.rx_packets);
+
+ tsi108_stat_carry_one(carry1, TSI108_STAT_CARRY1_RXFCS,
+ TSI108_STAT_RXFCS_CARRY, &data->rx_fcs);
+
+ tsi108_stat_carry_one(carry1, TSI108_STAT_CARRY1_RXMCAST,
+ TSI108_STAT_RXMCAST_CARRY,
+ &data->stats.multicast);
+
+ tsi108_stat_carry_one(carry1, TSI108_STAT_CARRY1_RXALIGN,
+ TSI108_STAT_RXALIGN_CARRY,
+ &data->stats.rx_frame_errors);
+
+ tsi108_stat_carry_one(carry1, TSI108_STAT_CARRY1_RXLENGTH,
+ TSI108_STAT_RXLENGTH_CARRY,
+ &data->stats.rx_length_errors);
+
+ tsi108_stat_carry_one(carry1, TSI108_STAT_CARRY1_RXRUNT,
+ TSI108_STAT_RXRUNT_CARRY, &data->rx_underruns);
+
+ tsi108_stat_carry_one(carry1, TSI108_STAT_CARRY1_RXJUMBO,
+ TSI108_STAT_RXJUMBO_CARRY, &data->rx_overruns);
+
+ tsi108_stat_carry_one(carry1, TSI108_STAT_CARRY1_RXFRAG,
+ TSI108_STAT_RXFRAG_CARRY, &data->rx_short_fcs);
+
+ tsi108_stat_carry_one(carry1, TSI108_STAT_CARRY1_RXJABBER,
+ TSI108_STAT_RXJABBER_CARRY, &data->rx_long_fcs);
+
+ tsi108_stat_carry_one(carry1, TSI108_STAT_CARRY1_RXDROP,
+ TSI108_STAT_RXDROP_CARRY,
+ &data->stats.rx_missed_errors);
+
+ tsi108_stat_carry_one(carry2, TSI108_STAT_CARRY2_TXBYTES,
+ TSI108_STAT_TXBYTES_CARRY, &data->stats.tx_bytes);
+
+ tsi108_stat_carry_one(carry2, TSI108_STAT_CARRY2_TXPKTS,
+ TSI108_STAT_TXPKTS_CARRY,
+ &data->stats.tx_packets);
+
+ tsi108_stat_carry_one(carry2, TSI108_STAT_CARRY2_TXEXDEF,
+ TSI108_STAT_TXEXDEF_CARRY,
+ &data->stats.tx_aborted_errors);
+
+ tsi108_stat_carry_one(carry2, TSI108_STAT_CARRY2_TXEXCOL,
+ TSI108_STAT_TXEXCOL_CARRY, &data->tx_coll_abort);
+
+ tsi108_stat_carry_one(carry2, TSI108_STAT_CARRY2_TXTCOL,
+ TSI108_STAT_TXTCOL_CARRY,
+ &data->stats.collisions);
+
+ tsi108_stat_carry_one(carry2, TSI108_STAT_CARRY2_TXPAUSE,
+ TSI108_STAT_TXPAUSEDROP_CARRY,
+ &data->tx_pause_drop);
+
+ spin_unlock_irq(&data->misclock);
+}
+
+/* Read a stat counter atomically with respect to carries.
+ * data->misclock must be held.
+ */
+static inline unsigned long
+tsi108_read_stat(struct tsi108_prv_data * data, int reg, int carry_bit,
+ int carry_shift, unsigned long *upper)
+{
+ int carryreg;
+ unsigned long val;
+
+ if (reg < 0xb0)
+ carryreg = TSI108_STAT_CARRY1;
+ else
+ carryreg = TSI108_STAT_CARRY2;
+
+ again:
+ val = TSI_READ(reg) | *upper;
+
+ /* Check to see if it overflowed, but the interrupt hasn't
+ * been serviced yet. If so, handle the carry here, and
+ * try again.
+ */
+
+ if (unlikely(TSI_READ(carryreg) & carry_bit)) {
+ *upper += carry_shift;
+ TSI_WRITE(carryreg, carry_bit);
+ goto again;
+ }
+
+ return val;
+}
+
+static struct net_device_stats *tsi108_get_stats(struct net_device *dev)
+{
+ unsigned long excol;
+
+ struct tsi108_prv_data *data = netdev_priv(dev);
+ spin_lock_irq(&data->misclock);
+
+ data->tmpstats.rx_packets =
+ tsi108_read_stat(data, TSI108_STAT_RXPKTS,
+ TSI108_STAT_CARRY1_RXPKTS,
+ TSI108_STAT_RXPKTS_CARRY, &data->stats.rx_packets);
+
+ data->tmpstats.tx_packets =
+ tsi108_read_stat(data, TSI108_STAT_TXPKTS,
+ TSI108_STAT_CARRY2_TXPKTS,
+ TSI108_STAT_TXPKTS_CARRY, &data->stats.tx_packets);
+
+ data->tmpstats.rx_bytes =
+ tsi108_read_stat(data, TSI108_STAT_RXBYTES,
+ TSI108_STAT_CARRY1_RXBYTES,
+ TSI108_STAT_RXBYTES_CARRY, &data->stats.rx_bytes);
+
+ data->tmpstats.tx_bytes =
+ tsi108_read_stat(data, TSI108_STAT_TXBYTES,
+ TSI108_STAT_CARRY2_TXBYTES,
+ TSI108_STAT_TXBYTES_CARRY, &data->stats.tx_bytes);
+
+ data->tmpstats.multicast =
+ tsi108_read_stat(data, TSI108_STAT_RXMCAST,
+ TSI108_STAT_CARRY1_RXMCAST,
+ TSI108_STAT_RXMCAST_CARRY, &data->stats.multicast);
+
+ excol = tsi108_read_stat(data, TSI108_STAT_TXEXCOL,
+ TSI108_STAT_CARRY2_TXEXCOL,
+ TSI108_STAT_TXEXCOL_CARRY,
+ &data->tx_coll_abort);
+
+ data->tmpstats.collisions =
+ tsi108_read_stat(data, TSI108_STAT_TXTCOL,
+ TSI108_STAT_CARRY2_TXTCOL,
+ TSI108_STAT_TXTCOL_CARRY, &data->stats.collisions);
+
+ data->tmpstats.collisions += excol;
+
+ data->tmpstats.rx_length_errors =
+ tsi108_read_stat(data, TSI108_STAT_RXLENGTH,
+ TSI108_STAT_CARRY1_RXLENGTH,
+ TSI108_STAT_RXLENGTH_CARRY,
+ &data->stats.rx_length_errors);
+
+ data->tmpstats.rx_length_errors +=
+ tsi108_read_stat(data, TSI108_STAT_RXRUNT,
+ TSI108_STAT_CARRY1_RXRUNT,
+ TSI108_STAT_RXRUNT_CARRY, &data->rx_underruns);
+
+ data->tmpstats.rx_length_errors +=
+ tsi108_read_stat(data, TSI108_STAT_RXJUMBO,
+ TSI108_STAT_CARRY1_RXJUMBO,
+ TSI108_STAT_RXJUMBO_CARRY, &data->rx_overruns);
+
+ data->tmpstats.rx_frame_errors =
+ tsi108_read_stat(data, TSI108_STAT_RXALIGN,
+ TSI108_STAT_CARRY1_RXALIGN,
+ TSI108_STAT_RXALIGN_CARRY,
+ &data->stats.rx_frame_errors);
+
+ data->tmpstats.rx_frame_errors +=
+ tsi108_read_stat(data, TSI108_STAT_RXFCS,
+ TSI108_STAT_CARRY1_RXFCS, TSI108_STAT_RXFCS_CARRY,
+ &data->rx_fcs);
+
+ data->tmpstats.rx_frame_errors +=
+ tsi108_read_stat(data, TSI108_STAT_RXFRAG,
+ TSI108_STAT_CARRY1_RXFRAG,
+ TSI108_STAT_RXFRAG_CARRY, &data->rx_short_fcs);
+
+ data->tmpstats.rx_missed_errors =
+ tsi108_read_stat(data, TSI108_STAT_RXDROP,
+ TSI108_STAT_CARRY1_RXDROP,
+ TSI108_STAT_RXDROP_CARRY,
+ &data->stats.rx_missed_errors);
+
+ /* These three are maintained by software. */
+ data->tmpstats.rx_fifo_errors = data->stats.rx_fifo_errors;
+ data->tmpstats.rx_crc_errors = data->stats.rx_crc_errors;
+
+ data->tmpstats.tx_aborted_errors =
+ tsi108_read_stat(data, TSI108_STAT_TXEXDEF,
+ TSI108_STAT_CARRY2_TXEXDEF,
+ TSI108_STAT_TXEXDEF_CARRY,
+ &data->stats.tx_aborted_errors);
+
+ data->tmpstats.tx_aborted_errors +=
+ tsi108_read_stat(data, TSI108_STAT_TXPAUSEDROP,
+ TSI108_STAT_CARRY2_TXPAUSE,
+ TSI108_STAT_TXPAUSEDROP_CARRY,
+ &data->tx_pause_drop);
+
+ data->tmpstats.tx_aborted_errors += excol;
+
+ data->tmpstats.tx_errors = data->tmpstats.tx_aborted_errors;
+ data->tmpstats.rx_errors = data->tmpstats.rx_length_errors +
+ data->tmpstats.rx_crc_errors +
+ data->tmpstats.rx_frame_errors +
+ data->tmpstats.rx_fifo_errors + data->tmpstats.rx_missed_errors;
+
+ spin_unlock_irq(&data->misclock);
+ return &data->tmpstats;
+}
+
+static void tsi108_restart_rx(struct tsi108_prv_data * data, struct net_device *dev)
+{
+ TSI_WRITE(TSI108_EC_RXQ_PTRHIGH,
+ TSI108_EC_RXQ_PTRHIGH_VALID);
+
+ TSI_WRITE(TSI108_EC_RXCTRL, TSI108_EC_RXCTRL_GO
+ | TSI108_EC_RXCTRL_QUEUE0);
+}
+
+static void tsi108_restart_tx(struct tsi108_prv_data * data)
+{
+ TSI_WRITE(TSI108_EC_TXQ_PTRHIGH,
+ TSI108_EC_TXQ_PTRHIGH_VALID);
+
+ TSI_WRITE(TSI108_EC_TXCTRL, TSI108_EC_TXCTRL_IDLEINT |
+ TSI108_EC_TXCTRL_GO | TSI108_EC_TXCTRL_QUEUE0);
+}
+
+/* txlock must be held by caller, with IRQs disabled, and
+ * with permission to re-enable them when the lock is dropped.
+ */
+static void tsi108_complete_tx(struct net_device *dev)
+{
+ struct tsi108_prv_data *data = netdev_priv(dev);
+ int tx;
+ struct sk_buff *skb;
+ int release = 0;
+
+ while (!data->txfree || data->txhead != data->txtail) {
+ tx = data->txtail;
+
+ if (data->txring[tx].misc & TSI108_TX_OWN)
+ break;
+
+ skb = data->txskbs[tx];
+
+ if (!(data->txring[tx].misc & TSI108_TX_OK))
+ printk("%s: bad tx packet, misc %x\n",
+ dev->name, data->txring[tx].misc);
+
+ data->txtail = (data->txtail + 1) % TSI108_TXRING_LEN;
+ data->txfree++;
+
+ if (data->txring[tx].misc & TSI108_TX_EOF) {
+ dev_kfree_skb_any(skb);
+ release++;
+ }
+ }
+
+ if (release) {
+ if (is_valid_ether_addr(dev->dev_addr) && data->link_up)
+ netif_wake_queue(dev);
+ }
+}
+
+static int tsi108_send_packet(struct sk_buff * skb, struct net_device *dev)
+{
+ struct tsi108_prv_data *data = netdev_priv(dev);
+ int frags = skb_shinfo(skb)->nr_frags + 1;
+ int i;
+
+ if (!data->phy_ok && net_ratelimit())
+ printk(KERN_ERR "%s: Transmit while PHY is down!\n", dev->name);
+
+ if (!data->link_up) {
+ printk(KERN_ERR "%s: Transmit while link is down!\n",
+ dev->name);
+ netif_stop_queue(dev);
+ return NETDEV_TX_BUSY;
+ }
+
+ if (data->txfree < MAX_SKB_FRAGS + 1) {
+ netif_stop_queue(dev);
+
+ if (net_ratelimit())
+ printk(KERN_ERR "%s: Transmit with full tx ring!\n",
+ dev->name);
+ return NETDEV_TX_BUSY;
+ }
+
+ if (data->txfree - frags < MAX_SKB_FRAGS + 1) {
+ netif_stop_queue(dev);
+ }
+
+ spin_lock_irq(&data->txlock);
+
+ for (i = 0; i < frags; i++) {
+ int misc = 0;
+ int tx = data->txhead;
+
+ /* This is done to mark every TSI108_TX_INT_FREQ tx buffers with
+ * the interrupt bit. TX descriptor-complete interrupts are
+ * enabled when the queue fills up, and masked when there is
+ * still free space. This way, when saturating the outbound
+ * link, the tx interrupts are kept to a reasonable level.
+ * When the queue is not full, reclamation of skbs still occurs
+ * as new packets are transmitted, or on a queue-empty
+ * interrupt.
+ */
+
+ if ((tx % TSI108_TX_INT_FREQ == 0) &&
+ ((TSI108_TXRING_LEN - data->txfree) >= TSI108_TX_INT_FREQ))
+ misc = TSI108_TX_INT;
+
+ data->txskbs[tx] = skb;
+
+ if (i == 0) {
+ data->txring[tx].buf0 = dma_map_single(NULL, skb->data,
+ skb->len - skb->data_len, DMA_TO_DEVICE);
+ data->txring[tx].len = skb->len - skb->data_len;
+ misc |= TSI108_TX_SOF;
+ } else {
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1];
+
+ data->txring[tx].buf0 =
+ dma_map_page(NULL, frag->page, frag->page_offset,
+ frag->size, DMA_TO_DEVICE);
+ data->txring[tx].len = frag->size;
+ }
+
+ if (i == frags - 1)
+ misc |= TSI108_TX_EOF;
+
+ if (netif_msg_pktdata(data)) {
+ int i;
+ printk("%s: Tx Frame contents (%d)\n", dev->name,
+ skb->len);
+ for (i = 0; i < skb->len; i++)
+ printk(" %2.2x", skb->data[i]);
+ printk(".\n");
+ }
+ data->txring[tx].misc = misc | TSI108_TX_OWN;
+
+ data->txhead = (data->txhead + 1) % TSI108_TXRING_LEN;
+ data->txfree--;
+ }
+
+ tsi108_complete_tx(dev);
+
+ /* This must be done after the check for completed tx descriptors,
+ * so that the tail pointer is correct.
+ */
+
+ if (!(TSI_READ(TSI108_EC_TXSTAT) & TSI108_EC_TXSTAT_QUEUE0))
+ tsi108_restart_tx(data);
+
+ spin_unlock_irq(&data->txlock);
+ return NETDEV_TX_OK;
+}
+
+static int tsi108_complete_rx(struct net_device *dev, int budget)
+{
+ struct tsi108_prv_data *data = netdev_priv(dev);
+ int done = 0;
+
+ while (data->rxfree && done != budget) {
+ int rx = data->rxtail;
+ struct sk_buff *skb;
+
+ if (data->rxring[rx].misc & TSI108_RX_OWN)
+ break;
+
+ skb = data->rxskbs[rx];
+ data->rxtail = (data->rxtail + 1) % TSI108_RXRING_LEN;
+ data->rxfree--;
+ done++;
+
+ if (data->rxring[rx].misc & TSI108_RX_BAD) {
+ spin_lock_irq(&data->misclock);
+
+ if (data->rxring[rx].misc & TSI108_RX_CRC)
+ data->stats.rx_crc_errors++;
+ if (data->rxring[rx].misc & TSI108_RX_OVER)
+ data->stats.rx_fifo_errors++;
+
+ spin_unlock_irq(&data->misclock);
+
+ dev_kfree_skb_any(skb);
+ continue;
+ }
+ if (netif_msg_pktdata(data)) {
+ int i;
+ printk("%s: Rx Frame contents (%d)\n",
+ dev->name, data->rxring[rx].len);
+ for (i = 0; i < data->rxring[rx].len; i++)
+ printk(" %2.2x", skb->data[i]);
+ printk(".\n");
+ }
+
+ skb->dev = dev;
+ skb_put(skb, data->rxring[rx].len);
+ skb->protocol = eth_type_trans(skb, dev);
+ netif_receive_skb(skb);
+ dev->last_rx = jiffies;
+ }
+
+ return done;
+}
+
+static int tsi108_refill_rx(struct net_device *dev, int budget)
+{
+ struct tsi108_prv_data *data = netdev_priv(dev);
+ int done = 0;
+
+ while (data->rxfree != TSI108_RXRING_LEN && done != budget) {
+ int rx = data->rxhead;
+ struct sk_buff *skb;
+
+ data->rxskbs[rx] = skb = dev_alloc_skb(TSI108_RXBUF_SIZE + 2);
+ if (!skb)
+ break;
+
+ skb_reserve(skb, 2); /* Align the data on a 4-byte boundary. */
+
+ data->rxring[rx].buf0 = dma_map_single(NULL, skb->data,
+ TSI108_RX_SKB_SIZE,
+ DMA_FROM_DEVICE);
+
+ /* Sometimes the hardware sets blen to zero after packet
+ * reception, even though the manual says that it's only ever
+ * modified by the driver.
+ */
+
+ data->rxring[rx].blen = TSI108_RX_SKB_SIZE;
+ data->rxring[rx].misc = TSI108_RX_OWN | TSI108_RX_INT;
+
+ data->rxhead = (data->rxhead + 1) % TSI108_RXRING_LEN;
+ data->rxfree++;
+ done++;
+ }
+
+ if (done != 0 && !(TSI_READ(TSI108_EC_RXSTAT) &
+ TSI108_EC_RXSTAT_QUEUE0))
+ tsi108_restart_rx(data, dev);
+
+ return done;
+}
+
+static int tsi108_poll(struct net_device *dev, int *budget)
+{
+ struct tsi108_prv_data *data = netdev_priv(dev);
+ u32 estat = TSI_READ(TSI108_EC_RXESTAT);
+ u32 intstat = TSI_READ(TSI108_EC_INTSTAT);
+ int total_budget = min(*budget, dev->quota);
+ int num_received = 0, num_filled = 0, budget_used;
+
+ intstat &= TSI108_INT_RXQUEUE0 | TSI108_INT_RXTHRESH |
+ TSI108_INT_RXOVERRUN | TSI108_INT_RXERROR | TSI108_INT_RXWAIT;
+
+ TSI_WRITE(TSI108_EC_RXESTAT, estat);
+ TSI_WRITE(TSI108_EC_INTSTAT, intstat);
+
+ if (data->rxpending || (estat & TSI108_EC_RXESTAT_Q0_DESCINT))
+ num_received = tsi108_complete_rx(dev, total_budget);
+
+ /* This should normally fill no more slots than the number of
+ * packets received in tsi108_complete_rx(). The exception
+ * is when we previously ran out of memory for RX SKBs. In that
+ * case, it's helpful to obey the budget, not only so that the
+ * CPU isn't hogged, but so that memory (which may still be low)
+ * is not hogged by one device.
+ *
+ * A work unit is considered to be two SKBs to allow us to catch
+ * up when the ring has shrunk due to out-of-memory but we're
+ * still removing the full budget's worth of packets each time.
+ */
+
+ if (data->rxfree < TSI108_RXRING_LEN)
+ num_filled = tsi108_refill_rx(dev, total_budget * 2);
+
+ if (intstat & TSI108_INT_RXERROR) {
+ u32 err = TSI_READ(TSI108_EC_RXERR);
+ TSI_WRITE(TSI108_EC_RXERR, err);
+
+ if (err) {
+ if (net_ratelimit())
+ printk(KERN_DEBUG "%s: RX error %x\n",
+ dev->name, err);
+
+ if (!(TSI_READ(TSI108_EC_RXSTAT) &
+ TSI108_EC_RXSTAT_QUEUE0))
+ tsi108_restart_rx(data, dev);
+ }
+ }
+
+ if (intstat & TSI108_INT_RXOVERRUN) {
+ spin_lock_irq(&data->misclock);
+ data->stats.rx_fifo_errors++;
+ spin_unlock_irq(&data->misclock);
+ }
+
+ budget_used = max(num_received, num_filled / 2);
+
+ *budget -= budget_used;
+ dev->quota -= budget_used;
+
+ if (budget_used != total_budget) {
+ data->rxpending = 0;
+ netif_rx_complete(dev);
+
+ TSI_WRITE(TSI108_EC_INTMASK,
+ TSI_READ(TSI108_EC_INTMASK)
+ & ~(TSI108_INT_RXQUEUE0
+ | TSI108_INT_RXTHRESH |
+ TSI108_INT_RXOVERRUN |
+ TSI108_INT_RXERROR |
+ TSI108_INT_RXWAIT));
+
+ /* IRQs are level-triggered, so no need to re-check */
+ return 0;
+ } else {
+ data->rxpending = 1;
+ }
+
+ return 1;
+}
+
+static void tsi108_rx_int(struct net_device *dev)
+{
+ struct tsi108_prv_data *data = netdev_priv(dev);
+
+ /* A race could cause dev to already be scheduled, so it's not an
+ * error if that happens (and interrupts shouldn't be re-masked,
+ * because that can cause harmful races, if poll has already
+ * unmasked them but not cleared LINK_STATE_SCHED).
+ *
+ * This can happen if this code races with tsi108_poll(), which masks
+ * the interrupts after tsi108_irq_one() read the mask, but before
+ * netif_rx_schedule is called. It could also happen due to calls
+ * from tsi108_check_rxring().
+ */
+
+ if (netif_rx_schedule_prep(dev)) {
+ /* Mask, rather than ack, the receive interrupts. The ack
+ * will happen in tsi108_poll().
+ */
+
+ TSI_WRITE(TSI108_EC_INTMASK,
+ TSI_READ(TSI108_EC_INTMASK) |
+ TSI108_INT_RXQUEUE0
+ | TSI108_INT_RXTHRESH |
+ TSI108_INT_RXOVERRUN | TSI108_INT_RXERROR |
+ TSI108_INT_RXWAIT);
+ __netif_rx_schedule(dev);
+ } else {
+ if (!netif_running(dev)) {
+ /* This can happen if an interrupt occurs while the
+ * interface is being brought down, as the START
+ * bit is cleared before the stop function is called.
+ *
+ * In this case, the interrupts must be masked, or
+ * they will continue indefinitely.
+ *
+ * There's a race here if the interface is brought down
+ * and then up in rapid succession, as the device could
+ * be made running after the above check and before
+ * the masking below. This will only happen if the IRQ
+ * thread has a lower priority than the task brining
+ * up the interface. Fixing this race would likely
+ * require changes in generic code.
+ */
+
+ TSI_WRITE(TSI108_EC_INTMASK,
+ TSI_READ
+ (TSI108_EC_INTMASK) |
+ TSI108_INT_RXQUEUE0 |
+ TSI108_INT_RXTHRESH |
+ TSI108_INT_RXOVERRUN |
+ TSI108_INT_RXERROR |
+ TSI108_INT_RXWAIT);
+ }
+ }
+}
+
+/* If the RX ring has run out of memory, try periodically
+ * to allocate some more, as otherwise poll would never
+ * get called (apart from the initial end-of-queue condition).
+ *
+ * This is called once per second (by default) from the thread.
+ */
+
+static void tsi108_check_rxring(struct net_device *dev)
+{
+ struct tsi108_prv_data *data = netdev_priv(dev);
+
+ /* A poll is scheduled, as opposed to caling tsi108_refill_rx
+ * directly, so as to keep the receive path single-threaded
+ * (and thus not needing a lock).
+ */
+
+ if (netif_running(dev) && data->rxfree < TSI108_RXRING_LEN / 4)
+ tsi108_rx_int(dev);
+}
+
+static void tsi108_tx_int(struct net_device *dev)
+{
+ struct tsi108_prv_data *data = netdev_priv(dev);
+ u32 estat = TSI_READ(TSI108_EC_TXESTAT);
+
+ TSI_WRITE(TSI108_EC_TXESTAT, estat);
+ TSI_WRITE(TSI108_EC_INTSTAT, TSI108_INT_TXQUEUE0 |
+ TSI108_INT_TXIDLE | TSI108_INT_TXERROR);
+ if (estat & TSI108_EC_TXESTAT_Q0_ERR) {
+ u32 err = TSI_READ(TSI108_EC_TXERR);
+ TSI_WRITE(TSI108_EC_TXERR, err);
+
+ if (err && net_ratelimit())
+ printk(KERN_ERR "%s: TX error %x\n", dev->name, err);
+ }
+
+ if (estat & (TSI108_EC_TXESTAT_Q0_DESCINT | TSI108_EC_TXESTAT_Q0_EOQ)) {
+ spin_lock(&data->txlock);
+ tsi108_complete_tx(dev);
+ spin_unlock(&data->txlock);
+ }
+}
+
+
+static irqreturn_t tsi108_irq(int irq, void *dev_id)
+{
+ struct net_device *dev = dev_id;
+ struct tsi108_prv_data *data = netdev_priv(dev);
+ u32 stat = TSI_READ(TSI108_EC_INTSTAT);
+
+ if (!(stat & TSI108_INT_ANY))
+ return IRQ_NONE; /* Not our interrupt */
+
+ stat &= ~TSI_READ(TSI108_EC_INTMASK);
+
+ if (stat & (TSI108_INT_TXQUEUE0 | TSI108_INT_TXIDLE |
+ TSI108_INT_TXERROR))
+ tsi108_tx_int(dev);
+ if (stat & (TSI108_INT_RXQUEUE0 | TSI108_INT_RXTHRESH |
+ TSI108_INT_RXWAIT | TSI108_INT_RXOVERRUN |
+ TSI108_INT_RXERROR))
+ tsi108_rx_int(dev);
+
+ if (stat & TSI108_INT_SFN) {
+ if (net_ratelimit())
+ printk(KERN_DEBUG "%s: SFN error\n", dev->name);
+ TSI_WRITE(TSI108_EC_INTSTAT, TSI108_INT_SFN);
+ }
+
+ if (stat & TSI108_INT_STATCARRY) {
+ tsi108_stat_carry(dev);
+ TSI_WRITE(TSI108_EC_INTSTAT, TSI108_INT_STATCARRY);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static void tsi108_stop_ethernet(struct net_device *dev)
+{
+ struct tsi108_prv_data *data = netdev_priv(dev);
+ int i = 1000;
+ /* Disable all TX and RX queues ... */
+ TSI_WRITE(TSI108_EC_TXCTRL, 0);
+ TSI_WRITE(TSI108_EC_RXCTRL, 0);
+
+ /* ...and wait for them to become idle */
+ while(i--) {
+ if(!(TSI_READ(TSI108_EC_TXSTAT) & TSI108_EC_TXSTAT_ACTIVE))
+ break;
+ udelay(10);
+ }
+ i = 1000;
+ while(i--){
+ if(!(TSI_READ(TSI108_EC_RXSTAT) & TSI108_EC_RXSTAT_ACTIVE))
+ return;
+ udelay(10);
+ }
+ printk(KERN_ERR "%s function time out \n", __FUNCTION__);
+}
+
+static void tsi108_reset_ether(struct tsi108_prv_data * data)
+{
+ TSI_WRITE(TSI108_MAC_CFG1, TSI108_MAC_CFG1_SOFTRST);
+ udelay(100);
+ TSI_WRITE(TSI108_MAC_CFG1, 0);
+
+ TSI_WRITE(TSI108_EC_PORTCTRL, TSI108_EC_PORTCTRL_STATRST);
+ udelay(100);
+ TSI_WRITE(TSI108_EC_PORTCTRL,
+ TSI_READ(TSI108_EC_PORTCTRL) &
+ ~TSI108_EC_PORTCTRL_STATRST);
+
+ TSI_WRITE(TSI108_EC_TXCFG, TSI108_EC_TXCFG_RST);
+ udelay(100);
+ TSI_WRITE(TSI108_EC_TXCFG,
+ TSI_READ(TSI108_EC_TXCFG) &
+ ~TSI108_EC_TXCFG_RST);
+
+ TSI_WRITE(TSI108_EC_RXCFG, TSI108_EC_RXCFG_RST);
+ udelay(100);
+ TSI_WRITE(TSI108_EC_RXCFG,
+ TSI_READ(TSI108_EC_RXCFG) &
+ ~TSI108_EC_RXCFG_RST);
+
+ TSI_WRITE(TSI108_MAC_MII_MGMT_CFG,
+ TSI_READ(TSI108_MAC_MII_MGMT_CFG) |
+ TSI108_MAC_MII_MGMT_RST);
+ udelay(100);
+ TSI_WRITE(TSI108_MAC_MII_MGMT_CFG,
+ (TSI_READ(TSI108_MAC_MII_MGMT_CFG) &
+ ~(TSI108_MAC_MII_MGMT_RST |
+ TSI108_MAC_MII_MGMT_CLK)) | 0x07);
+}
+
+static int tsi108_get_mac(struct net_device *dev)
+{
+ struct tsi108_prv_data *data = netdev_priv(dev);
+ u32 word1 = TSI_READ(TSI108_MAC_ADDR1);
+ u32 word2 = TSI_READ(TSI108_MAC_ADDR2);
+
+ /* Note that the octets are reversed from what the manual says,
+ * producing an even weirder ordering...
+ */
+ if (word2 == 0 && word1 == 0) {
+ dev->dev_addr[0] = 0x00;
+ dev->dev_addr[1] = 0x06;
+ dev->dev_addr[2] = 0xd2;
+ dev->dev_addr[3] = 0x00;
+ dev->dev_addr[4] = 0x00;
+ if (0x8 == data->phy)
+ dev->dev_addr[5] = 0x01;
+ else
+ dev->dev_addr[5] = 0x02;
+
+ word2 = (dev->dev_addr[0] << 16) | (dev->dev_addr[1] << 24);
+
+ word1 = (dev->dev_addr[2] << 0) | (dev->dev_addr[3] << 8) |
+ (dev->dev_addr[4] << 16) | (dev->dev_addr[5] << 24);
+
+ TSI_WRITE(TSI108_MAC_ADDR1, word1);
+ TSI_WRITE(TSI108_MAC_ADDR2, word2);
+ } else {
+ dev->dev_addr[0] = (word2 >> 16) & 0xff;
+ dev->dev_addr[1] = (word2 >> 24) & 0xff;
+ dev->dev_addr[2] = (word1 >> 0) & 0xff;
+ dev->dev_addr[3] = (word1 >> 8) & 0xff;
+ dev->dev_addr[4] = (word1 >> 16) & 0xff;
+ dev->dev_addr[5] = (word1 >> 24) & 0xff;
+ }
+
+ if (!is_valid_ether_addr(dev->dev_addr)) {
+ printk("KERN_ERR: word1: %08x, word2: %08x\n", word1, word2);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int tsi108_set_mac(struct net_device *dev, void *addr)
+{
+ struct tsi108_prv_data *data = netdev_priv(dev);
+ u32 word1, word2;
+ int i;
+
+ if (!is_valid_ether_addr(addr))
+ return -EINVAL;
+
+ for (i = 0; i < 6; i++)
+ /* +2 is for the offset of the HW addr type */
+ dev->dev_addr[i] = ((unsigned char *)addr)[i + 2];
+
+ word2 = (dev->dev_addr[0] << 16) | (dev->dev_addr[1] << 24);
+
+ word1 = (dev->dev_addr[2] << 0) | (dev->dev_addr[3] << 8) |
+ (dev->dev_addr[4] << 16) | (dev->dev_addr[5] << 24);
+
+ spin_lock_irq(&data->misclock);
+ TSI_WRITE(TSI108_MAC_ADDR1, word1);
+ TSI_WRITE(TSI108_MAC_ADDR2, word2);
+ spin_lock(&data->txlock);
+
+ if (data->txfree && data->link_up)
+ netif_wake_queue(dev);
+
+ spin_unlock(&data->txlock);
+ spin_unlock_irq(&data->misclock);
+ return 0;
+}
+
+/* Protected by dev->xmit_lock. */
+static void tsi108_set_rx_mode(struct net_device *dev)
+{
+ struct tsi108_prv_data *data = netdev_priv(dev);
+ u32 rxcfg = TSI_READ(TSI108_EC_RXCFG);
+
+ if (dev->flags & IFF_PROMISC) {
+ rxcfg &= ~(TSI108_EC_RXCFG_UC_HASH | TSI108_EC_RXCFG_MC_HASH);
+ rxcfg |= TSI108_EC_RXCFG_UFE | TSI108_EC_RXCFG_MFE;
+ goto out;
+ }
+
+ rxcfg &= ~(TSI108_EC_RXCFG_UFE | TSI108_EC_RXCFG_MFE);
+
+ if (dev->flags & IFF_ALLMULTI || dev->mc_count) {
+ int i;
+ struct dev_mc_list *mc = dev->mc_list;
+ rxcfg |= TSI108_EC_RXCFG_MFE | TSI108_EC_RXCFG_MC_HASH;
+
+ memset(data->mc_hash, 0, sizeof(data->mc_hash));
+
+ while (mc) {
+ u32 hash, crc;
+
+ if (mc->dmi_addrlen == 6) {
+ crc = ether_crc(6, mc->dmi_addr);
+ hash = crc >> 23;
+
+ __set_bit(hash, &data->mc_hash[0]);
+ } else {
+ printk(KERN_ERR
+ "%s: got multicast address of length %d "
+ "instead of 6.\n", dev->name,
+ mc->dmi_addrlen);
+ }
+
+ mc = mc->next;
+ }
+
+ TSI_WRITE(TSI108_EC_HASHADDR,
+ TSI108_EC_HASHADDR_AUTOINC |
+ TSI108_EC_HASHADDR_MCAST);
+
+ for (i = 0; i < 16; i++) {
+ /* The manual says that the hardware may drop
+ * back-to-back writes to the data register.
+ */
+ udelay(1);
+ TSI_WRITE(TSI108_EC_HASHDATA,
+ data->mc_hash[i]);
+ }
+ }
+
+ out:
+ TSI_WRITE(TSI108_EC_RXCFG, rxcfg);
+}
+
+static void tsi108_init_phy(struct net_device *dev)
+{
+ struct tsi108_prv_data *data = netdev_priv(dev);
+ u32 i = 0;
+ u16 phyval = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&phy_lock, flags);
+
+ tsi108_write_mii(data, MII_BMCR, BMCR_RESET);
+ while (i--){
+ if(!(tsi108_read_mii(data, MII_BMCR) & BMCR_RESET))
+ break;
+ udelay(10);
+ }
+ if (i == 0)
+ printk(KERN_ERR "%s function time out \n", __FUNCTION__);
+
+#if (TSI108_PHY_TYPE == PHY_BCM54XX) /* Broadcom BCM54xx PHY */
+ tsi108_write_mii(data, 0x09, 0x0300);
+ tsi108_write_mii(data, 0x10, 0x1020);
+ tsi108_write_mii(data, 0x1c, 0x8c00);
+#endif
+
+ tsi108_write_mii(data,
+ MII_BMCR,
+ BMCR_ANENABLE | BMCR_ANRESTART);
+ while (tsi108_read_mii(data, MII_BMCR) & BMCR_ANRESTART)
+ cpu_relax();
+
+ /* Set G/MII mode and receive clock select in TBI control #2. The
+ * second port won't work if this isn't done, even though we don't
+ * use TBI mode.
+ */
+
+ tsi108_write_tbi(data, 0x11, 0x30);
+
+ /* FIXME: It seems to take more than 2 back-to-back reads to the
+ * PHY_STAT register before the link up status bit is set.
+ */
+
+ data->link_up = 1;
+
+ while (!((phyval = tsi108_read_mii(data, MII_BMSR)) &
+ BMSR_LSTATUS)) {
+ if (i++ > (MII_READ_DELAY / 10)) {
+ data->link_up = 0;
+ break;
+ }
+ spin_unlock_irqrestore(&phy_lock, flags);
+ msleep(10);
+ spin_lock_irqsave(&phy_lock, flags);
+ }
+
+ printk(KERN_DEBUG "PHY_STAT reg contains %08x\n", phyval);
+ data->phy_ok = 1;
+ data->init_media = 1;
+ spin_unlock_irqrestore(&phy_lock, flags);
+}
+
+static void tsi108_kill_phy(struct net_device *dev)
+{
+ struct tsi108_prv_data *data = netdev_priv(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&phy_lock, flags);
+ tsi108_write_mii(data, MII_BMCR, BMCR_PDOWN);
+ data->phy_ok = 0;
+ spin_unlock_irqrestore(&phy_lock, flags);
+}
+
+static int tsi108_open(struct net_device *dev)
+{
+ int i;
+ struct tsi108_prv_data *data = netdev_priv(dev);
+ unsigned int rxring_size = TSI108_RXRING_LEN * sizeof(rx_desc);
+ unsigned int txring_size = TSI108_TXRING_LEN * sizeof(tx_desc);
+
+ i = request_irq(data->irq_num, tsi108_irq, 0, dev->name, dev);
+ if (i != 0) {
+ printk(KERN_ERR "tsi108_eth%d: Could not allocate IRQ%d.\n",
+ data->id, data->irq_num);
+ return i;
+ } else {
+ dev->irq = data->irq_num;
+ printk(KERN_NOTICE
+ "tsi108_open : Port %d Assigned IRQ %d to %s\n",
+ data->id, dev->irq, dev->name);
+ }
+
+ data->rxring = dma_alloc_coherent(NULL, rxring_size,
+ &data->rxdma, GFP_KERNEL);
+
+ if (!data->rxring) {
+ printk(KERN_DEBUG
+ "TSI108_ETH: failed to allocate memory for rxring!\n");
+ return -ENOMEM;
+ } else {
+ memset(data->rxring, 0, rxring_size);
+ }
+
+ data->txring = dma_alloc_coherent(NULL, txring_size,
+ &data->txdma, GFP_KERNEL);
+
+ if (!data->txring) {
+ printk(KERN_DEBUG
+ "TSI108_ETH: failed to allocate memory for txring!\n");
+ pci_free_consistent(0, rxring_size, data->rxring, data->rxdma);
+ return -ENOMEM;
+ } else {
+ memset(data->txring, 0, txring_size);
+ }
+
+ for (i = 0; i < TSI108_RXRING_LEN; i++) {
+ data->rxring[i].next0 = data->rxdma + (i + 1) * sizeof(rx_desc);
+ data->rxring[i].blen = TSI108_RXBUF_SIZE;
+ data->rxring[i].vlan = 0;
+ }
+
+ data->rxring[TSI108_RXRING_LEN - 1].next0 = data->rxdma;
+
+ data->rxtail = 0;
+ data->rxhead = 0;
+
+ for (i = 0; i < TSI108_RXRING_LEN; i++) {
+ struct sk_buff *skb = dev_alloc_skb(TSI108_RXBUF_SIZE + NET_IP_ALIGN);
+
+ if (!skb) {
+ /* Bah. No memory for now, but maybe we'll get
+ * some more later.
+ * For now, we'll live with the smaller ring.
+ */
+ printk(KERN_WARNING
+ "%s: Could only allocate %d receive skb(s).\n",
+ dev->name, i);
+ data->rxhead = i;
+ break;
+ }
+
+ data->rxskbs[i] = skb;
+ /* Align the payload on a 4-byte boundary */
+ skb_reserve(skb, 2);
+ data->rxskbs[i] = skb;
+ data->rxring[i].buf0 = virt_to_phys(data->rxskbs[i]->data);
+ data->rxring[i].misc = TSI108_RX_OWN | TSI108_RX_INT;
+ }
+
+ data->rxfree = i;
+ TSI_WRITE(TSI108_EC_RXQ_PTRLOW, data->rxdma);
+
+ for (i = 0; i < TSI108_TXRING_LEN; i++) {
+ data->txring[i].next0 = data->txdma + (i + 1) * sizeof(tx_desc);
+ data->txring[i].misc = 0;
+ }
+
+ data->txring[TSI108_TXRING_LEN - 1].next0 = data->txdma;
+ data->txtail = 0;
+ data->txhead = 0;
+ data->txfree = TSI108_TXRING_LEN;
+ TSI_WRITE(TSI108_EC_TXQ_PTRLOW, data->txdma);
+ tsi108_init_phy(dev);
+
+ setup_timer(&data->timer, tsi108_timed_checker, (unsigned long)dev);
+ mod_timer(&data->timer, jiffies + 1);
+
+ tsi108_restart_rx(data, dev);
+
+ TSI_WRITE(TSI108_EC_INTSTAT, ~0);
+
+ TSI_WRITE(TSI108_EC_INTMASK,
+ ~(TSI108_INT_TXQUEUE0 | TSI108_INT_RXERROR |
+ TSI108_INT_RXTHRESH | TSI108_INT_RXQUEUE0 |
+ TSI108_INT_RXOVERRUN | TSI108_INT_RXWAIT |
+ TSI108_INT_SFN | TSI108_INT_STATCARRY));
+
+ TSI_WRITE(TSI108_MAC_CFG1,
+ TSI108_MAC_CFG1_RXEN | TSI108_MAC_CFG1_TXEN);
+ netif_start_queue(dev);
+ return 0;
+}
+
+static int tsi108_close(struct net_device *dev)
+{
+ struct tsi108_prv_data *data = netdev_priv(dev);
+
+ netif_stop_queue(dev);
+
+ del_timer_sync(&data->timer);
+
+ tsi108_stop_ethernet(dev);
+ tsi108_kill_phy(dev);
+ TSI_WRITE(TSI108_EC_INTMASK, ~0);
+ TSI_WRITE(TSI108_MAC_CFG1, 0);
+
+ /* Check for any pending TX packets, and drop them. */
+
+ while (!data->txfree || data->txhead != data->txtail) {
+ int tx = data->txtail;
+ struct sk_buff *skb;
+ skb = data->txskbs[tx];
+ data->txtail = (data->txtail + 1) % TSI108_TXRING_LEN;
+ data->txfree++;
+ dev_kfree_skb(skb);
+ }
+
+ synchronize_irq(data->irq_num);
+ free_irq(data->irq_num, dev);
+
+ /* Discard the RX ring. */
+
+ while (data->rxfree) {
+ int rx = data->rxtail;
+ struct sk_buff *skb;
+
+ skb = data->rxskbs[rx];
+ data->rxtail = (data->rxtail + 1) % TSI108_RXRING_LEN;
+ data->rxfree--;
+ dev_kfree_skb(skb);
+ }
+
+ dma_free_coherent(0,
+ TSI108_RXRING_LEN * sizeof(rx_desc),
+ data->rxring, data->rxdma);
+ dma_free_coherent(0,
+ TSI108_TXRING_LEN * sizeof(tx_desc),
+ data->txring, data->txdma);
+
+ return 0;
+}
+
+static void tsi108_init_mac(struct net_device *dev)
+{
+ struct tsi108_prv_data *data = netdev_priv(dev);
+
+ TSI_WRITE(TSI108_MAC_CFG2, TSI108_MAC_CFG2_DFLT_PREAMBLE |
+ TSI108_MAC_CFG2_PADCRC);
+
+ TSI_WRITE(TSI108_EC_TXTHRESH,
+ (192 << TSI108_EC_TXTHRESH_STARTFILL) |
+ (192 << TSI108_EC_TXTHRESH_STOPFILL));
+
+ TSI_WRITE(TSI108_STAT_CARRYMASK1,
+ ~(TSI108_STAT_CARRY1_RXBYTES |
+ TSI108_STAT_CARRY1_RXPKTS |
+ TSI108_STAT_CARRY1_RXFCS |
+ TSI108_STAT_CARRY1_RXMCAST |
+ TSI108_STAT_CARRY1_RXALIGN |
+ TSI108_STAT_CARRY1_RXLENGTH |
+ TSI108_STAT_CARRY1_RXRUNT |
+ TSI108_STAT_CARRY1_RXJUMBO |
+ TSI108_STAT_CARRY1_RXFRAG |
+ TSI108_STAT_CARRY1_RXJABBER |
+ TSI108_STAT_CARRY1_RXDROP));
+
+ TSI_WRITE(TSI108_STAT_CARRYMASK2,
+ ~(TSI108_STAT_CARRY2_TXBYTES |
+ TSI108_STAT_CARRY2_TXPKTS |
+ TSI108_STAT_CARRY2_TXEXDEF |
+ TSI108_STAT_CARRY2_TXEXCOL |
+ TSI108_STAT_CARRY2_TXTCOL |
+ TSI108_STAT_CARRY2_TXPAUSE));
+
+ TSI_WRITE(TSI108_EC_PORTCTRL, TSI108_EC_PORTCTRL_STATEN);
+ TSI_WRITE(TSI108_MAC_CFG1, 0);
+
+ TSI_WRITE(TSI108_EC_RXCFG,
+ TSI108_EC_RXCFG_SE | TSI108_EC_RXCFG_BFE);
+
+ TSI_WRITE(TSI108_EC_TXQ_CFG, TSI108_EC_TXQ_CFG_DESC_INT |
+ TSI108_EC_TXQ_CFG_EOQ_OWN_INT |
+ TSI108_EC_TXQ_CFG_WSWP | (TSI108_PBM_PORT <<
+ TSI108_EC_TXQ_CFG_SFNPORT));
+
+ TSI_WRITE(TSI108_EC_RXQ_CFG, TSI108_EC_RXQ_CFG_DESC_INT |
+ TSI108_EC_RXQ_CFG_EOQ_OWN_INT |
+ TSI108_EC_RXQ_CFG_WSWP | (TSI108_PBM_PORT <<
+ TSI108_EC_RXQ_CFG_SFNPORT));
+
+ TSI_WRITE(TSI108_EC_TXQ_BUFCFG,
+ TSI108_EC_TXQ_BUFCFG_BURST256 |
+ TSI108_EC_TXQ_BUFCFG_BSWP | (TSI108_PBM_PORT <<
+ TSI108_EC_TXQ_BUFCFG_SFNPORT));
+
+ TSI_WRITE(TSI108_EC_RXQ_BUFCFG,
+ TSI108_EC_RXQ_BUFCFG_BURST256 |
+ TSI108_EC_RXQ_BUFCFG_BSWP | (TSI108_PBM_PORT <<
+ TSI108_EC_RXQ_BUFCFG_SFNPORT));
+
+ TSI_WRITE(TSI108_EC_INTMASK, ~0);
+}
+
+static int tsi108_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+ struct tsi108_prv_data *data = netdev_priv(dev);
+ return generic_mii_ioctl(&data->mii_if, if_mii(rq), cmd, NULL);
+}
+
+static int
+tsi108_init_one(struct platform_device *pdev)
+{
+ struct net_device *dev = NULL;
+ struct tsi108_prv_data *data = NULL;
+ hw_info *einfo;
+ int err = 0;
+
+ einfo = pdev->dev.platform_data;
+
+ if (NULL == einfo) {
+ printk(KERN_ERR "tsi-eth %d: Missing additional data!\n",
+ pdev->id);
+ return -ENODEV;
+ }
+
+ /* Create an ethernet device instance */
+
+ dev = alloc_etherdev(sizeof(struct tsi108_prv_data));
+ if (!dev) {
+ printk("tsi108_eth: Could not allocate a device structure\n");
+ return -ENOMEM;
+ }
+
+ printk("tsi108_eth%d: probe...\n", pdev->id);
+ data = netdev_priv(dev);
+
+ pr_debug("tsi108_eth%d:regs:phyresgs:phy:irq_num=0x%x:0x%x:0x%x:0x%x\n",
+ pdev->id, einfo->regs, einfo->phyregs,
+ einfo->phy, einfo->irq_num);
+
+ data->regs = ioremap(einfo->regs, 0x400);
+ if (NULL == data->regs) {
+ err = -ENOMEM;
+ goto regs_fail;
+ }
+
+ data->phyregs = ioremap(einfo->phyregs, 0x400);
+ if (NULL == data->phyregs) {
+ err = -ENOMEM;
+ goto regs_fail;
+ }
+/* MII setup */
+ data->mii_if.dev = dev;
+ data->mii_if.mdio_read = tsi108_mdio_read;
+ data->mii_if.mdio_write = tsi108_mdio_write;
+ data->mii_if.phy_id = einfo->phy;
+ data->mii_if.phy_id_mask = 0x1f;
+ data->mii_if.reg_num_mask = 0x1f;
+ data->mii_if.supports_gmii = mii_check_gmii_support(&data->mii_if);
+
+ data->phy = einfo->phy;
+ data->irq_num = einfo->irq_num;
+ data->id = pdev->id;
+ dev->open = tsi108_open;
+ dev->stop = tsi108_close;
+ dev->hard_start_xmit = tsi108_send_packet;
+ dev->set_mac_address = tsi108_set_mac;
+ dev->set_multicast_list = tsi108_set_rx_mode;
+ dev->get_stats = tsi108_get_stats;
+ dev->poll = tsi108_poll;
+ dev->do_ioctl = tsi108_do_ioctl;
+ dev->weight = 64; /* 64 is more suitable for GigE interface - klai */
+
+ /* Apparently, the Linux networking code won't use scatter-gather
+ * if the hardware doesn't do checksums. However, it's faster
+ * to checksum in place and use SG, as (among other reasons)
+ * the cache won't be dirtied (which then has to be flushed
+ * before DMA). The checksumming is done by the driver (via
+ * a new function skb_csum_dev() in net/core/skbuff.c).
+ */
+
+ dev->features = NETIF_F_HIGHDMA;
+ SET_MODULE_OWNER(dev);
+
+ spin_lock_init(&data->txlock);
+ spin_lock_init(&data->misclock);
+
+ tsi108_reset_ether(data);
+ tsi108_kill_phy(dev);
+
+ if ((err = tsi108_get_mac(dev)) != 0) {
+ printk(KERN_ERR "%s: Invalid MAC address. Please correct.\n",
+ dev->name);
+ goto register_fail;
+ }
+
+ tsi108_init_mac(dev);
+ err = register_netdev(dev);
+ if (err) {
+ printk(KERN_ERR "%s: Cannot register net device, aborting.\n",
+ dev->name);
+ goto register_fail;
+ }
+
+ printk(KERN_INFO "%s: Tsi108 Gigabit Ethernet, MAC: "
+ "%02x:%02x:%02x:%02x:%02x:%02x\n", dev->name,
+ dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+ dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
+#ifdef DEBUG
+ data->msg_enable = DEBUG;
+ dump_eth_one(dev);
+#endif
+
+ return 0;
+
+register_fail:
+ iounmap(data->regs);
+ iounmap(data->phyregs);
+
+regs_fail:
+ free_netdev(dev);
+ return err;
+}
+
+/* There's no way to either get interrupts from the PHY when
+ * something changes, or to have the Tsi108 automatically communicate
+ * with the PHY to reconfigure itself.
+ *
+ * Thus, we have to do it using a timer.
+ */
+
+static void tsi108_timed_checker(unsigned long dev_ptr)
+{
+ struct net_device *dev = (struct net_device *)dev_ptr;
+ struct tsi108_prv_data *data = netdev_priv(dev);
+
+ tsi108_check_phy(dev);
+ tsi108_check_rxring(dev);
+ mod_timer(&data->timer, jiffies + CHECK_PHY_INTERVAL);
+}
+
+static int tsi108_ether_init(void)
+{
+ int ret;
+ ret = platform_driver_register (&tsi_eth_driver);
+ if (ret < 0){
+ printk("tsi108_ether_init: error initializing ethernet "
+ "device\n");
+ return ret;
+ }
+ return 0;
+}
+
+static int tsi108_ether_remove(struct platform_device *pdev)
+{
+ struct net_device *dev = platform_get_drvdata(pdev);
+ struct tsi108_prv_data *priv = netdev_priv(dev);
+
+ unregister_netdev(dev);
+ tsi108_stop_ethernet(dev);
+ platform_set_drvdata(pdev, NULL);
+ iounmap(priv->regs);
+ iounmap(priv->phyregs);
+ free_netdev(dev);
+
+ return 0;
+}
+static void tsi108_ether_exit(void)
+{
+ platform_driver_unregister(&tsi_eth_driver);
+}
+
+module_init(tsi108_ether_init);
+module_exit(tsi108_ether_exit);
+
+MODULE_AUTHOR("Tundra Semiconductor Corporation");
+MODULE_DESCRIPTION("Tsi108 Gigabit Ethernet driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/tsi108_eth.h b/drivers/net/tsi108_eth.h
new file mode 100644
index 000000000000..77a769df228a
--- /dev/null
+++ b/drivers/net/tsi108_eth.h
@@ -0,0 +1,365 @@
+/*
+ * (C) Copyright 2005 Tundra Semiconductor Corp.
+ * Kong Lai, <kong.lai@tundra.com).
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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
+ */
+
+/*
+ * net/tsi108_eth.h - definitions for Tsi108 GIGE network controller.
+ */
+
+#ifndef __TSI108_ETH_H
+#define __TSI108_ETH_H
+
+#include <linux/types.h>
+
+#define TSI_WRITE(offset, val) \
+ out_be32((data->regs + (offset)), val)
+
+#define TSI_READ(offset) \
+ in_be32((data->regs + (offset)))
+
+#define TSI_WRITE_PHY(offset, val) \
+ out_be32((data->phyregs + (offset)), val)
+
+#define TSI_READ_PHY(offset) \
+ in_be32((data->phyregs + (offset)))
+
+/*
+ * PHY Configuration Options
+ *
+ * NOTE: Enable set of definitions corresponding to your board type
+ */
+#define PHY_MV88E 1 /* Marvel 88Exxxx PHY */
+#define PHY_BCM54XX 2 /* Broardcom BCM54xx PHY */
+#define TSI108_PHY_TYPE PHY_MV88E
+
+/*
+ * TSI108 GIGE port registers
+ */
+
+#define TSI108_ETH_PORT_NUM 2
+#define TSI108_PBM_PORT 2
+#define TSI108_SDRAM_PORT 4
+
+#define TSI108_MAC_CFG1 (0x000)
+#define TSI108_MAC_CFG1_SOFTRST (1 << 31)
+#define TSI108_MAC_CFG1_LOOPBACK (1 << 8)
+#define TSI108_MAC_CFG1_RXEN (1 << 2)
+#define TSI108_MAC_CFG1_TXEN (1 << 0)
+
+#define TSI108_MAC_CFG2 (0x004)
+#define TSI108_MAC_CFG2_DFLT_PREAMBLE (7 << 12)
+#define TSI108_MAC_CFG2_IFACE_MASK (3 << 8)
+#define TSI108_MAC_CFG2_NOGIG (1 << 8)
+#define TSI108_MAC_CFG2_GIG (2 << 8)
+#define TSI108_MAC_CFG2_PADCRC (1 << 2)
+#define TSI108_MAC_CFG2_FULLDUPLEX (1 << 0)
+
+#define TSI108_MAC_MII_MGMT_CFG (0x020)
+#define TSI108_MAC_MII_MGMT_CLK (7 << 0)
+#define TSI108_MAC_MII_MGMT_RST (1 << 31)
+
+#define TSI108_MAC_MII_CMD (0x024)
+#define TSI108_MAC_MII_CMD_READ (1 << 0)
+
+#define TSI108_MAC_MII_ADDR (0x028)
+#define TSI108_MAC_MII_ADDR_REG 0
+#define TSI108_MAC_MII_ADDR_PHY 8
+
+#define TSI108_MAC_MII_DATAOUT (0x02c)
+#define TSI108_MAC_MII_DATAIN (0x030)
+
+#define TSI108_MAC_MII_IND (0x034)
+#define TSI108_MAC_MII_IND_NOTVALID (1 << 2)
+#define TSI108_MAC_MII_IND_SCANNING (1 << 1)
+#define TSI108_MAC_MII_IND_BUSY (1 << 0)
+
+#define TSI108_MAC_IFCTRL (0x038)
+#define TSI108_MAC_IFCTRL_PHYMODE (1 << 24)
+
+#define TSI108_MAC_ADDR1 (0x040)
+#define TSI108_MAC_ADDR2 (0x044)
+
+#define TSI108_STAT_RXBYTES (0x06c)
+#define TSI108_STAT_RXBYTES_CARRY (1 << 24)
+
+#define TSI108_STAT_RXPKTS (0x070)
+#define TSI108_STAT_RXPKTS_CARRY (1 << 18)
+
+#define TSI108_STAT_RXFCS (0x074)
+#define TSI108_STAT_RXFCS_CARRY (1 << 12)
+
+#define TSI108_STAT_RXMCAST (0x078)
+#define TSI108_STAT_RXMCAST_CARRY (1 << 18)
+
+#define TSI108_STAT_RXALIGN (0x08c)
+#define TSI108_STAT_RXALIGN_CARRY (1 << 12)
+
+#define TSI108_STAT_RXLENGTH (0x090)
+#define TSI108_STAT_RXLENGTH_CARRY (1 << 12)
+
+#define TSI108_STAT_RXRUNT (0x09c)
+#define TSI108_STAT_RXRUNT_CARRY (1 << 12)
+
+#define TSI108_STAT_RXJUMBO (0x0a0)
+#define TSI108_STAT_RXJUMBO_CARRY (1 << 12)
+
+#define TSI108_STAT_RXFRAG (0x0a4)
+#define TSI108_STAT_RXFRAG_CARRY (1 << 12)
+
+#define TSI108_STAT_RXJABBER (0x0a8)
+#define TSI108_STAT_RXJABBER_CARRY (1 << 12)
+
+#define TSI108_STAT_RXDROP (0x0ac)
+#define TSI108_STAT_RXDROP_CARRY (1 << 12)
+
+#define TSI108_STAT_TXBYTES (0x0b0)
+#define TSI108_STAT_TXBYTES_CARRY (1 << 24)
+
+#define TSI108_STAT_TXPKTS (0x0b4)
+#define TSI108_STAT_TXPKTS_CARRY (1 << 18)
+
+#define TSI108_STAT_TXEXDEF (0x0c8)
+#define TSI108_STAT_TXEXDEF_CARRY (1 << 12)
+
+#define TSI108_STAT_TXEXCOL (0x0d8)
+#define TSI108_STAT_TXEXCOL_CARRY (1 << 12)
+
+#define TSI108_STAT_TXTCOL (0x0dc)
+#define TSI108_STAT_TXTCOL_CARRY (1 << 13)
+
+#define TSI108_STAT_TXPAUSEDROP (0x0e4)
+#define TSI108_STAT_TXPAUSEDROP_CARRY (1 << 12)
+
+#define TSI108_STAT_CARRY1 (0x100)
+#define TSI108_STAT_CARRY1_RXBYTES (1 << 16)
+#define TSI108_STAT_CARRY1_RXPKTS (1 << 15)
+#define TSI108_STAT_CARRY1_RXFCS (1 << 14)
+#define TSI108_STAT_CARRY1_RXMCAST (1 << 13)
+#define TSI108_STAT_CARRY1_RXALIGN (1 << 8)
+#define TSI108_STAT_CARRY1_RXLENGTH (1 << 7)
+#define TSI108_STAT_CARRY1_RXRUNT (1 << 4)
+#define TSI108_STAT_CARRY1_RXJUMBO (1 << 3)
+#define TSI108_STAT_CARRY1_RXFRAG (1 << 2)
+#define TSI108_STAT_CARRY1_RXJABBER (1 << 1)
+#define TSI108_STAT_CARRY1_RXDROP (1 << 0)
+
+#define TSI108_STAT_CARRY2 (0x104)
+#define TSI108_STAT_CARRY2_TXBYTES (1 << 13)
+#define TSI108_STAT_CARRY2_TXPKTS (1 << 12)
+#define TSI108_STAT_CARRY2_TXEXDEF (1 << 7)
+#define TSI108_STAT_CARRY2_TXEXCOL (1 << 3)
+#define TSI108_STAT_CARRY2_TXTCOL (1 << 2)
+#define TSI108_STAT_CARRY2_TXPAUSE (1 << 0)
+
+#define TSI108_STAT_CARRYMASK1 (0x108)
+#define TSI108_STAT_CARRYMASK2 (0x10c)
+
+#define TSI108_EC_PORTCTRL (0x200)
+#define TSI108_EC_PORTCTRL_STATRST (1 << 31)
+#define TSI108_EC_PORTCTRL_STATEN (1 << 28)
+#define TSI108_EC_PORTCTRL_NOGIG (1 << 18)
+#define TSI108_EC_PORTCTRL_HALFDUPLEX (1 << 16)
+
+#define TSI108_EC_INTSTAT (0x204)
+#define TSI108_EC_INTMASK (0x208)
+
+#define TSI108_INT_ANY (1 << 31)
+#define TSI108_INT_SFN (1 << 30)
+#define TSI108_INT_RXIDLE (1 << 29)
+#define TSI108_INT_RXABORT (1 << 28)
+#define TSI108_INT_RXERROR (1 << 27)
+#define TSI108_INT_RXOVERRUN (1 << 26)
+#define TSI108_INT_RXTHRESH (1 << 25)
+#define TSI108_INT_RXWAIT (1 << 24)
+#define TSI108_INT_RXQUEUE0 (1 << 16)
+#define TSI108_INT_STATCARRY (1 << 15)
+#define TSI108_INT_TXIDLE (1 << 13)
+#define TSI108_INT_TXABORT (1 << 12)
+#define TSI108_INT_TXERROR (1 << 11)
+#define TSI108_INT_TXUNDERRUN (1 << 10)
+#define TSI108_INT_TXTHRESH (1 << 9)
+#define TSI108_INT_TXWAIT (1 << 8)
+#define TSI108_INT_TXQUEUE0 (1 << 0)
+
+#define TSI108_EC_TXCFG (0x220)
+#define TSI108_EC_TXCFG_RST (1 << 31)
+
+#define TSI108_EC_TXCTRL (0x224)
+#define TSI108_EC_TXCTRL_IDLEINT (1 << 31)
+#define TSI108_EC_TXCTRL_ABORT (1 << 30)
+#define TSI108_EC_TXCTRL_GO (1 << 15)
+#define TSI108_EC_TXCTRL_QUEUE0 (1 << 0)
+
+#define TSI108_EC_TXSTAT (0x228)
+#define TSI108_EC_TXSTAT_ACTIVE (1 << 15)
+#define TSI108_EC_TXSTAT_QUEUE0 (1 << 0)
+
+#define TSI108_EC_TXESTAT (0x22c)
+#define TSI108_EC_TXESTAT_Q0_ERR (1 << 24)
+#define TSI108_EC_TXESTAT_Q0_DESCINT (1 << 16)
+#define TSI108_EC_TXESTAT_Q0_EOF (1 << 8)
+#define TSI108_EC_TXESTAT_Q0_EOQ (1 << 0)
+
+#define TSI108_EC_TXERR (0x278)
+
+#define TSI108_EC_TXQ_CFG (0x280)
+#define TSI108_EC_TXQ_CFG_DESC_INT (1 << 20)
+#define TSI108_EC_TXQ_CFG_EOQ_OWN_INT (1 << 19)
+#define TSI108_EC_TXQ_CFG_WSWP (1 << 11)
+#define TSI108_EC_TXQ_CFG_BSWP (1 << 10)
+#define TSI108_EC_TXQ_CFG_SFNPORT 0
+
+#define TSI108_EC_TXQ_BUFCFG (0x284)
+#define TSI108_EC_TXQ_BUFCFG_BURST8 (0 << 8)
+#define TSI108_EC_TXQ_BUFCFG_BURST32 (1 << 8)
+#define TSI108_EC_TXQ_BUFCFG_BURST128 (2 << 8)
+#define TSI108_EC_TXQ_BUFCFG_BURST256 (3 << 8)
+#define TSI108_EC_TXQ_BUFCFG_WSWP (1 << 11)
+#define TSI108_EC_TXQ_BUFCFG_BSWP (1 << 10)
+#define TSI108_EC_TXQ_BUFCFG_SFNPORT 0
+
+#define TSI108_EC_TXQ_PTRLOW (0x288)
+
+#define TSI108_EC_TXQ_PTRHIGH (0x28c)
+#define TSI108_EC_TXQ_PTRHIGH_VALID (1 << 31)
+
+#define TSI108_EC_TXTHRESH (0x230)
+#define TSI108_EC_TXTHRESH_STARTFILL 0
+#define TSI108_EC_TXTHRESH_STOPFILL 16
+
+#define TSI108_EC_RXCFG (0x320)
+#define TSI108_EC_RXCFG_RST (1 << 31)
+
+#define TSI108_EC_RXSTAT (0x328)
+#define TSI108_EC_RXSTAT_ACTIVE (1 << 15)
+#define TSI108_EC_RXSTAT_QUEUE0 (1 << 0)
+
+#define TSI108_EC_RXESTAT (0x32c)
+#define TSI108_EC_RXESTAT_Q0_ERR (1 << 24)
+#define TSI108_EC_RXESTAT_Q0_DESCINT (1 << 16)
+#define TSI108_EC_RXESTAT_Q0_EOF (1 << 8)
+#define TSI108_EC_RXESTAT_Q0_EOQ (1 << 0)
+
+#define TSI108_EC_HASHADDR (0x360)
+#define TSI108_EC_HASHADDR_AUTOINC (1 << 31)
+#define TSI108_EC_HASHADDR_DO1STREAD (1 << 30)
+#define TSI108_EC_HASHADDR_UNICAST (0 << 4)
+#define TSI108_EC_HASHADDR_MCAST (1 << 4)
+
+#define TSI108_EC_HASHDATA (0x364)
+
+#define TSI108_EC_RXQ_PTRLOW (0x388)
+
+#define TSI108_EC_RXQ_PTRHIGH (0x38c)
+#define TSI108_EC_RXQ_PTRHIGH_VALID (1 << 31)
+
+/* Station Enable -- accept packets destined for us */
+#define TSI108_EC_RXCFG_SE (1 << 13)
+/* Unicast Frame Enable -- for packets not destined for us */
+#define TSI108_EC_RXCFG_UFE (1 << 12)
+/* Multicast Frame Enable */
+#define TSI108_EC_RXCFG_MFE (1 << 11)
+/* Broadcast Frame Enable */
+#define TSI108_EC_RXCFG_BFE (1 << 10)
+#define TSI108_EC_RXCFG_UC_HASH (1 << 9)
+#define TSI108_EC_RXCFG_MC_HASH (1 << 8)
+
+#define TSI108_EC_RXQ_CFG (0x380)
+#define TSI108_EC_RXQ_CFG_DESC_INT (1 << 20)
+#define TSI108_EC_RXQ_CFG_EOQ_OWN_INT (1 << 19)
+#define TSI108_EC_RXQ_CFG_WSWP (1 << 11)
+#define TSI108_EC_RXQ_CFG_BSWP (1 << 10)
+#define TSI108_EC_RXQ_CFG_SFNPORT 0
+
+#define TSI108_EC_RXQ_BUFCFG (0x384)
+#define TSI108_EC_RXQ_BUFCFG_BURST8 (0 << 8)
+#define TSI108_EC_RXQ_BUFCFG_BURST32 (1 << 8)
+#define TSI108_EC_RXQ_BUFCFG_BURST128 (2 << 8)
+#define TSI108_EC_RXQ_BUFCFG_BURST256 (3 << 8)
+#define TSI108_EC_RXQ_BUFCFG_WSWP (1 << 11)
+#define TSI108_EC_RXQ_BUFCFG_BSWP (1 << 10)
+#define TSI108_EC_RXQ_BUFCFG_SFNPORT 0
+
+#define TSI108_EC_RXCTRL (0x324)
+#define TSI108_EC_RXCTRL_ABORT (1 << 30)
+#define TSI108_EC_RXCTRL_GO (1 << 15)
+#define TSI108_EC_RXCTRL_QUEUE0 (1 << 0)
+
+#define TSI108_EC_RXERR (0x378)
+
+#define TSI108_TX_EOF (1 << 0) /* End of frame; last fragment of packet */
+#define TSI108_TX_SOF (1 << 1) /* Start of frame; first frag. of packet */
+#define TSI108_TX_VLAN (1 << 2) /* Per-frame VLAN: enables VLAN override */
+#define TSI108_TX_HUGE (1 << 3) /* Huge frame enable */
+#define TSI108_TX_PAD (1 << 4) /* Pad the packet if too short */
+#define TSI108_TX_CRC (1 << 5) /* Generate CRC for this packet */
+#define TSI108_TX_INT (1 << 14) /* Generate an IRQ after frag. processed */
+#define TSI108_TX_RETRY (0xf << 16) /* 4 bit field indicating num. of retries */
+#define TSI108_TX_COL (1 << 20) /* Set if a collision occured */
+#define TSI108_TX_LCOL (1 << 24) /* Set if a late collision occured */
+#define TSI108_TX_UNDER (1 << 25) /* Set if a FIFO underrun occured */
+#define TSI108_TX_RLIM (1 << 26) /* Set if the retry limit was reached */
+#define TSI108_TX_OK (1 << 30) /* Set if the frame TX was successful */
+#define TSI108_TX_OWN (1 << 31) /* Set if the device owns the descriptor */
+
+/* Note: the descriptor layouts assume big-endian byte order. */
+typedef struct {
+ u32 buf0;
+ u32 buf1; /* Base address of buffer */
+ u32 next0; /* Address of next descriptor, if any */
+ u32 next1;
+ u16 vlan; /* VLAN, if override enabled for this packet */
+ u16 len; /* Length of buffer in bytes */
+ u32 misc; /* See TSI108_TX_* above */
+ u32 reserved0; /*reserved0 and reserved1 are added to make the desc */
+ u32 reserved1; /* 32-byte aligned */
+} __attribute__ ((aligned(32))) tx_desc;
+
+#define TSI108_RX_EOF (1 << 0) /* End of frame; last fragment of packet */
+#define TSI108_RX_SOF (1 << 1) /* Start of frame; first frag. of packet */
+#define TSI108_RX_VLAN (1 << 2) /* Set on SOF if packet has a VLAN */
+#define TSI108_RX_FTYPE (1 << 3) /* Length/Type field is type, not length */
+#define TSI108_RX_RUNT (1 << 4)/* Packet is less than minimum size */
+#define TSI108_RX_HASH (1 << 7)/* Hash table match */
+#define TSI108_RX_BAD (1 << 8) /* Bad frame */
+#define TSI108_RX_OVER (1 << 9) /* FIFO overrun occured */
+#define TSI108_RX_TRUNC (1 << 11) /* Packet truncated due to excess length */
+#define TSI108_RX_CRC (1 << 12) /* Packet had a CRC error */
+#define TSI108_RX_INT (1 << 13) /* Generate an IRQ after frag. processed */
+#define TSI108_RX_OWN (1 << 15) /* Set if the device owns the descriptor */
+
+#define TSI108_RX_SKB_SIZE 1536 /* The RX skb length */
+
+typedef struct {
+ u32 buf0; /* Base address of buffer */
+ u32 buf1; /* Base address of buffer */
+ u32 next0; /* Address of next descriptor, if any */
+ u32 next1; /* Address of next descriptor, if any */
+ u16 vlan; /* VLAN of received packet, first frag only */
+ u16 len; /* Length of received fragment in bytes */
+ u16 blen; /* Length of buffer in bytes */
+ u16 misc; /* See TSI108_RX_* above */
+ u32 reserved0; /* reserved0 and reserved1 are added to make the desc */
+ u32 reserved1; /* 32-byte aligned */
+} __attribute__ ((aligned(32))) rx_desc;
+
+#endif /* __TSI108_ETH_H */
diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
index f6b3a94e97bf..9d67f11422ec 100644
--- a/drivers/net/tulip/de2104x.c
+++ b/drivers/net/tulip/de2104x.c
@@ -1906,9 +1906,7 @@ fill_defaults:
de->media[i].csr15 = t21041_csr15[i];
}
- de->ee_data = kmalloc(DE_EEPROM_SIZE, GFP_KERNEL);
- if (de->ee_data)
- memcpy(de->ee_data, &ee_data[0], DE_EEPROM_SIZE);
+ de->ee_data = kmemdup(&ee_data[0], DE_EEPROM_SIZE, GFP_KERNEL);
return;
diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c
index 4dd8a0bae860..7f59a3d4fda2 100644
--- a/drivers/net/tulip/dmfe.c
+++ b/drivers/net/tulip/dmfe.c
@@ -187,7 +187,7 @@ struct rx_desc {
struct dmfe_board_info {
u32 chip_id; /* Chip vendor/Device ID */
u32 chip_revision; /* Chip revision */
- struct DEVICE *next_dev; /* next device */
+ struct DEVICE *dev; /* net device */
struct pci_dev *pdev; /* PCI device */
spinlock_t lock;
@@ -399,6 +399,8 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev,
/* Init system & device */
db = netdev_priv(dev);
+ db->dev = dev;
+
/* Allocate Tx/Rx descriptor memory */
db->desc_pool_ptr = pci_alloc_consistent(pdev, sizeof(struct tx_desc) * DESC_ALL_CNT + 0x20, &db->desc_pool_dma_ptr);
db->buf_pool_ptr = pci_alloc_consistent(pdev, TX_BUF_ALLOC * TX_DESC_CNT + 4, &db->buf_pool_dma_ptr);
@@ -426,6 +428,7 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev,
dev->poll_controller = &poll_dmfe;
#endif
dev->ethtool_ops = &netdev_ethtool_ops;
+ netif_carrier_off(db->dev);
spin_lock_init(&db->lock);
pci_read_config_dword(pdev, 0x50, &pci_pmr);
@@ -1050,6 +1053,7 @@ static void netdev_get_drvinfo(struct net_device *dev,
static const struct ethtool_ops netdev_ethtool_ops = {
.get_drvinfo = netdev_get_drvinfo,
+ .get_link = ethtool_op_get_link,
};
/*
@@ -1144,6 +1148,7 @@ static void dmfe_timer(unsigned long data)
/* Link Failed */
DMFE_DBUG(0, "Link Failed", tmp_cr12);
db->link_failed = 1;
+ netif_carrier_off(db->dev);
/* For Force 10/100M Half/Full mode: Enable Auto-Nego mode */
/* AUTO or force 1M Homerun/Longrun don't need */
@@ -1166,6 +1171,8 @@ static void dmfe_timer(unsigned long data)
if ( (db->media_mode & DMFE_AUTO) &&
dmfe_sense_speed(db) )
db->link_failed = 1;
+ else
+ netif_carrier_on(db->dev);
dmfe_process_mode(db);
/* SHOW_MEDIA_TYPE(db->op_mode); */
}
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index 3bf9e630404f..8ddea1da7c05 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -127,7 +127,6 @@ static const int multicast_filter_limit = 32;
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/in6.h>
-#include <asm/checksum.h>
#include <linux/version.h>
#include <linux/dma-mapping.h>
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index b37888011067..1f05511fa390 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -30,7 +30,7 @@
#include <linux/ethtool.h>
#include <linux/mii.h>
-#include <asm/of_device.h>
+#include <asm/of_platform.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
@@ -4301,12 +4301,12 @@ static int __init ucc_geth_init(void)
memcpy(&(ugeth_info[i]), &ugeth_primary_info,
sizeof(ugeth_primary_info));
- return of_register_driver(&ucc_geth_driver);
+ return of_register_platform_driver(&ucc_geth_driver);
}
static void __exit ucc_geth_exit(void)
{
- of_unregister_driver(&ucc_geth_driver);
+ of_unregister_platform_driver(&ucc_geth_driver);
}
module_init(ucc_geth_init);
diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig
index b5d0d7fb647a..d5ab9cf13257 100644
--- a/drivers/net/wan/Kconfig
+++ b/drivers/net/wan/Kconfig
@@ -57,44 +57,6 @@ config COSA
The driver will be compiled as a module: the
module will be called cosa.
-config DSCC4
- tristate "Etinc PCISYNC serial board support"
- depends on WAN && PCI && m
- help
- Driver for Etinc PCISYNC boards based on the Infineon (ex. Siemens)
- DSCC4 chipset.
-
- This is supposed to work with the four port card. Take a look at
- <http://www.cogenit.fr/dscc4/> for further information about the
- driver.
-
- To compile this driver as a module, choose M here: the
- module will be called dscc4.
-
-config DSCC4_PCISYNC
- bool "Etinc PCISYNC features"
- depends on DSCC4
- help
- Due to Etinc's design choice for its PCISYNC cards, some operations
- are only allowed on specific ports of the DSCC4. This option is the
- only way for the driver to know that it shouldn't return a success
- code for these operations.
-
- Please say Y if your card is an Etinc's PCISYNC.
-
-config DSCC4_PCI_RST
- bool "Hard reset support"
- depends on DSCC4
- help
- Various DSCC4 bugs forbid any reliable software reset of the ASIC.
- As a replacement, some vendors provide a way to assert the PCI #RST
- pin of DSCC4 through the GPIO port of the card. If you choose Y,
- the driver will make use of this feature before module removal
- (i.e. rmmod). The feature is known to be available on Commtech's
- cards. Contact your manufacturer for details.
-
- Say Y if your card supports this feature.
-
#
# Lan Media's board. Currently 1000, 1200, 5200, 5245
#
@@ -323,6 +285,44 @@ config FARSYNC
To compile this driver as a module, choose M here: the
module will be called farsync.
+config DSCC4
+ tristate "Etinc PCISYNC serial board support"
+ depends on HDLC && PCI && m
+ help
+ Driver for Etinc PCISYNC boards based on the Infineon (ex. Siemens)
+ DSCC4 chipset.
+
+ This is supposed to work with the four port card. Take a look at
+ <http://www.cogenit.fr/dscc4/> for further information about the
+ driver.
+
+ To compile this driver as a module, choose M here: the
+ module will be called dscc4.
+
+config DSCC4_PCISYNC
+ bool "Etinc PCISYNC features"
+ depends on DSCC4
+ help
+ Due to Etinc's design choice for its PCISYNC cards, some operations
+ are only allowed on specific ports of the DSCC4. This option is the
+ only way for the driver to know that it shouldn't return a success
+ code for these operations.
+
+ Please say Y if your card is an Etinc's PCISYNC.
+
+config DSCC4_PCI_RST
+ bool "Hard reset support"
+ depends on DSCC4
+ help
+ Various DSCC4 bugs forbid any reliable software reset of the ASIC.
+ As a replacement, some vendors provide a way to assert the PCI #RST
+ pin of DSCC4 through the GPIO port of the card. If you choose Y,
+ the driver will make use of this feature before module removal
+ (i.e. rmmod). The feature is known to be available on Commtech's
+ cards. Contact your manufacturer for details.
+
+ Say Y if your card supports this feature.
+
config DLCI
tristate "Frame Relay DLCI support"
depends on WAN
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index 0c07b8b7250d..10bcb48e80d0 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -595,7 +595,7 @@ static void atmel_join_bss(struct atmel_private *priv, int bss_index);
static void atmel_smooth_qual(struct atmel_private *priv);
static void atmel_writeAR(struct net_device *dev, u16 data);
static int probe_atmel_card(struct net_device *dev);
-static int reset_atmel_card(struct net_device *dev );
+static int reset_atmel_card(struct net_device *dev);
static void atmel_enter_state(struct atmel_private *priv, int new_state);
int atmel_open (struct net_device *dev);
@@ -784,11 +784,11 @@ static void tx_update_descriptor(struct atmel_private *priv, int is_bcast,
static int start_tx(struct sk_buff *skb, struct net_device *dev)
{
+ static const u8 SNAP_RFC1024[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
struct atmel_private *priv = netdev_priv(dev);
struct ieee80211_hdr_4addr header;
unsigned long flags;
u16 buff, frame_ctl, len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
- u8 SNAP_RFC1024[6] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
if (priv->card && priv->present_callback &&
!(*priv->present_callback)(priv->card)) {
@@ -1193,7 +1193,7 @@ static irqreturn_t service_interrupt(int irq, void *dev_id)
atmel_set_gcr(dev, GCR_ACKINT); /* acknowledge interrupt */
- for (i = 0; i < sizeof(irq_order)/sizeof(u8); i++)
+ for (i = 0; i < ARRAY_SIZE(irq_order); i++)
if (isr & irq_order[i])
break;
@@ -1345,10 +1345,10 @@ int atmel_open(struct net_device *dev)
atmel_set_mib8(priv, Phy_Mib_Type, PHY_MIB_REG_DOMAIN_POS, priv->reg_domain);
} else {
priv->reg_domain = atmel_get_mib8(priv, Phy_Mib_Type, PHY_MIB_REG_DOMAIN_POS);
- for (i = 0; i < sizeof(channel_table)/sizeof(channel_table[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(channel_table); i++)
if (priv->reg_domain == channel_table[i].reg_domain)
break;
- if (i == sizeof(channel_table)/sizeof(channel_table[0])) {
+ if (i == ARRAY_SIZE(channel_table)) {
priv->reg_domain = REG_DOMAIN_MKK1;
printk(KERN_ALERT "%s: failed to get regulatory domain: assuming MKK1.\n", dev->name);
}
@@ -1393,7 +1393,7 @@ static int atmel_validate_channel(struct atmel_private *priv, int channel)
else return suitable default channel */
int i;
- for (i = 0; i < sizeof(channel_table)/sizeof(channel_table[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(channel_table); i++)
if (priv->reg_domain == channel_table[i].reg_domain) {
if (channel >= channel_table[i].min &&
channel <= channel_table[i].max)
@@ -1437,7 +1437,7 @@ static int atmel_proc_output (char *buf, struct atmel_private *priv)
}
r = "<unknown>";
- for (i = 0; i < sizeof(channel_table)/sizeof(channel_table[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(channel_table); i++)
if (priv->reg_domain == channel_table[i].reg_domain)
r = channel_table[i].name;
@@ -1736,7 +1736,7 @@ static int atmel_set_encode(struct net_device *dev,
/* Disable the key */
priv->wep_key_len[index] = 0;
/* Check if the key is not marked as invalid */
- if(!(dwrq->flags & IW_ENCODE_NOKEY)) {
+ if (!(dwrq->flags & IW_ENCODE_NOKEY)) {
/* Cleanup */
memset(priv->wep_keys[index], 0, 13);
/* Copy the key in the driver */
@@ -1907,7 +1907,7 @@ static int atmel_get_encodeext(struct net_device *dev,
encoding->flags = idx + 1;
memset(ext, 0, sizeof(*ext));
-
+
if (!priv->wep_is_on) {
ext->alg = IW_ENCODE_ALG_NONE;
ext->key_len = 0;
@@ -2343,6 +2343,14 @@ static int atmel_get_scan(struct net_device *dev,
iwe.u.freq.e = 0;
current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_FREQ_LEN);
+ /* Add quality statistics */
+ iwe.cmd = IWEVQUAL;
+ iwe.u.qual.level = priv->BSSinfo[i].RSSI;
+ iwe.u.qual.qual = iwe.u.qual.level;
+ /* iwe.u.qual.noise = SOMETHING */
+ current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA , &iwe, IW_EV_QUAL_LEN);
+
+
iwe.cmd = SIOCGIWENCODE;
if (priv->BSSinfo[i].UsingWEP)
iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
@@ -2373,7 +2381,7 @@ static int atmel_get_range(struct net_device *dev,
range->min_nwid = 0x0000;
range->max_nwid = 0x0000;
range->num_channels = 0;
- for (j = 0; j < sizeof(channel_table)/sizeof(channel_table[0]); j++)
+ for (j = 0; j < ARRAY_SIZE(channel_table); j++)
if (priv->reg_domain == channel_table[j].reg_domain) {
range->num_channels = channel_table[j].max - channel_table[j].min + 1;
break;
@@ -2579,9 +2587,9 @@ static const struct iw_priv_args atmel_private_args[] = {
static const struct iw_handler_def atmel_handler_def =
{
- .num_standard = sizeof(atmel_handler)/sizeof(iw_handler),
- .num_private = sizeof(atmel_private_handler)/sizeof(iw_handler),
- .num_private_args = sizeof(atmel_private_args)/sizeof(struct iw_priv_args),
+ .num_standard = ARRAY_SIZE(atmel_handler),
+ .num_private = ARRAY_SIZE(atmel_private_handler),
+ .num_private_args = ARRAY_SIZE(atmel_private_args),
.standard = (iw_handler *) atmel_handler,
.private = (iw_handler *) atmel_private_handler,
.private_args = (struct iw_priv_args *) atmel_private_args,
@@ -2645,7 +2653,7 @@ static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
domain[REGDOMAINSZ] = 0;
rc = -EINVAL;
- for (i = 0; i < sizeof(channel_table)/sizeof(channel_table[0]); i++) {
+ for (i = 0; i < ARRAY_SIZE(channel_table); i++) {
/* strcasecmp doesn't exist in the library */
char *a = channel_table[i].name;
char *b = domain;
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
index 785664090bb4..5c410989c4d7 100644
--- a/drivers/net/wireless/atmel_cs.c
+++ b/drivers/net/wireless/atmel_cs.c
@@ -5,12 +5,12 @@
Copyright 2000-2001 ATMEL Corporation.
Copyright 2003 Simon Kelley.
- This code was developed from version 2.1.1 of the Atmel drivers,
- released by Atmel corp. under the GPL in December 2002. It also
- includes code from the Linux aironet drivers (C) Benjamin Reed,
- and the Linux PCMCIA package, (C) David Hinds.
+ This code was developed from version 2.1.1 of the Atmel drivers,
+ released by Atmel corp. under the GPL in December 2002. It also
+ includes code from the Linux aironet drivers (C) Benjamin Reed,
+ and the Linux PCMCIA package, (C) David Hinds.
- For all queries about this code, please contact the current author,
+ For all queries about this code, please contact the current author,
Simon Kelley <simon@thekelleys.org.uk> and not Atmel Corporation.
This program is free software; you can redistribute it and/or modify
@@ -87,7 +87,7 @@ MODULE_SUPPORTED_DEVICE("Atmel at76c50x PCMCIA cards");
event is received. The config() and release() entry points are
used to configure or release a socket, in response to card
insertion and ejection events. They are invoked from the atmel_cs
- event handler.
+ event handler.
*/
static int atmel_config(struct pcmcia_device *link);
@@ -133,22 +133,22 @@ static void atmel_detach(struct pcmcia_device *p_dev);
device IO routines can use a flag like this to throttle IO to a
card that is not ready to accept it.
*/
-
+
typedef struct local_info_t {
dev_node_t node;
struct net_device *eth_dev;
} local_info_t;
/*======================================================================
-
+
atmel_attach() creates an "instance" of the driver, allocating
local data structures for one device. The device is registered
with Card Services.
-
+
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 atmel_probe(struct pcmcia_device *p_dev)
@@ -184,12 +184,12 @@ static int atmel_probe(struct pcmcia_device *p_dev)
} /* atmel_attach */
/*======================================================================
-
+
This deletes a driver "instance". The device is de-registered
with Card 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 atmel_detach(struct pcmcia_device *link)
@@ -202,11 +202,11 @@ static void atmel_detach(struct pcmcia_device *link)
}
/*======================================================================
-
+
atmel_config() is scheduled to run after a CARD_INSERTION event
is received, to configure the PCMCIA socket, and to make the
device available to the system.
-
+
======================================================================*/
#define CS_CHECK(fn, ret) \
@@ -237,12 +237,12 @@ static int atmel_config(struct pcmcia_device *link)
did = handle_to_dev(link).driver_data;
DEBUG(0, "atmel_config(0x%p)\n", link);
-
+
tuple.Attributes = 0;
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
-
+
/*
This reads the card's CONFIG tuple to find its configuration
registers.
@@ -258,7 +258,7 @@ static int atmel_config(struct pcmcia_device *link)
In this loop, we scan the CIS for configuration table entries,
each of which describes a valid card configuration, including
voltage, IO window, memory window, and interrupt settings.
-
+
We make no assumptions about the card to be configured: we use
just the information available in the CIS. In an ideal world,
this would work for any PCMCIA card, but it requires a complete
@@ -274,17 +274,17 @@ static int atmel_config(struct pcmcia_device *link)
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;
if (cfg->index == 0) goto next_entry;
link->conf.ConfigIndex = cfg->index;
-
+
/* Does this card need audio output? */
if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
link->conf.Attributes |= CONF_ENABLE_SPKR;
link->conf.Status = CCSR_AUDIO_ENA;
}
-
+
/* Use power settings for Vcc and Vpp if present */
/* Note that the CIS values need to be rescaled */
if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
@@ -293,11 +293,11 @@ static int atmel_config(struct pcmcia_device *link)
else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
link->conf.Vpp =
dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
-
+
/* Do we need to allocate an interrupt? */
if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
link->conf.Attributes |= CONF_ENABLE_IRQ;
-
+
/* IO window settings */
link->io.NumPorts1 = link->io.NumPorts2 = 0;
if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
@@ -315,18 +315,18 @@ static int atmel_config(struct pcmcia_device *link)
link->io.NumPorts2 = io->win[1].len;
}
}
-
+
/* This reserves IO space but doesn't actually enable it */
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(link, &tuple));
}
-
+
/*
Allocate an interrupt line. Note that this does not assign a
handler to the interrupt, unless the 'Handler' member of the
@@ -334,31 +334,31 @@ static int atmel_config(struct pcmcia_device *link)
*/
if (link->conf.Attributes & CONF_ENABLE_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, &link->conf));
-
+
if (link->irq.AssignedIRQ == 0) {
- printk(KERN_ALERT
+ printk(KERN_ALERT
"atmel: cannot assign IRQ: check that CONFIG_ISA is set in kernel config.");
goto cs_failed;
}
-
- ((local_info_t*)link->priv)->eth_dev =
+
+ ((local_info_t*)link->priv)->eth_dev =
init_atmel_card(link->irq.AssignedIRQ,
link->io.BasePort1,
did ? did->driver_info : ATMEL_FW_TYPE_NONE,
&handle_to_dev(link),
- card_present,
+ card_present,
link);
- if (!((local_info_t*)link->priv)->eth_dev)
+ 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_node.
@@ -376,11 +376,11 @@ static int atmel_config(struct pcmcia_device *link)
}
/*======================================================================
-
+
After a card is removed, atmel_release() will unregister the
device, and release the PCMCIA configuration. If the device is
still open, this will be postponed until it is closed.
-
+
======================================================================*/
static void atmel_release(struct pcmcia_device *link)
@@ -517,7 +517,7 @@ static void atmel_cs_cleanup(void)
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.
+ POSSIBILITY OF SUCH DAMAGE.
*/
module_init(atmel_cs_init);
diff --git a/drivers/net/wireless/atmel_pci.c b/drivers/net/wireless/atmel_pci.c
index 3bfa791c323d..92f87fbe750f 100644
--- a/drivers/net/wireless/atmel_pci.c
+++ b/drivers/net/wireless/atmel_pci.c
@@ -53,18 +53,18 @@ static int __devinit atmel_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *pent)
{
struct net_device *dev;
-
+
if (pci_enable_device(pdev))
return -ENODEV;
-
+
pci_set_master(pdev);
-
- dev = init_atmel_card(pdev->irq, pdev->resource[1].start,
+
+ dev = init_atmel_card(pdev->irq, pdev->resource[1].start,
ATMEL_FW_TYPE_506,
&pdev->dev, NULL, NULL);
if (!dev)
return -ENODEV;
-
+
pci_set_drvdata(pdev, dev);
return 0;
}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h
index fbc0c087f53c..8286678513b9 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx.h
@@ -159,6 +159,7 @@
/* Chipcommon registers. */
#define BCM43xx_CHIPCOMMON_CAPABILITIES 0x04
+#define BCM43xx_CHIPCOMMON_CTL 0x28
#define BCM43xx_CHIPCOMMON_PLLONDELAY 0xB0
#define BCM43xx_CHIPCOMMON_FREFSELDELAY 0xB4
#define BCM43xx_CHIPCOMMON_SLOWCLKCTL 0xB8
@@ -172,6 +173,33 @@
/* SBTOPCI2 values. */
#define BCM43xx_SBTOPCI2_PREFETCH 0x4
#define BCM43xx_SBTOPCI2_BURST 0x8
+#define BCM43xx_SBTOPCI2_MEMREAD_MULTI 0x20
+
+/* PCI-E core registers. */
+#define BCM43xx_PCIECORE_REG_ADDR 0x0130
+#define BCM43xx_PCIECORE_REG_DATA 0x0134
+#define BCM43xx_PCIECORE_MDIO_CTL 0x0128
+#define BCM43xx_PCIECORE_MDIO_DATA 0x012C
+
+/* PCI-E registers. */
+#define BCM43xx_PCIE_TLP_WORKAROUND 0x0004
+#define BCM43xx_PCIE_DLLP_LINKCTL 0x0100
+
+/* PCI-E MDIO bits. */
+#define BCM43xx_PCIE_MDIO_ST 0x40000000
+#define BCM43xx_PCIE_MDIO_WT 0x10000000
+#define BCM43xx_PCIE_MDIO_DEV 22
+#define BCM43xx_PCIE_MDIO_REG 18
+#define BCM43xx_PCIE_MDIO_TA 0x00020000
+#define BCM43xx_PCIE_MDIO_TC 0x0100
+
+/* MDIO devices. */
+#define BCM43xx_MDIO_SERDES_RX 0x1F
+
+/* SERDES RX registers. */
+#define BCM43xx_SERDES_RXTIMER 0x2
+#define BCM43xx_SERDES_CDR 0x6
+#define BCM43xx_SERDES_CDR_BW 0x7
/* Chipcommon capabilities. */
#define BCM43xx_CAPABILITIES_PCTL 0x00040000
@@ -221,6 +249,7 @@
#define BCM43xx_COREID_USB20_HOST 0x819
#define BCM43xx_COREID_USB20_DEV 0x81a
#define BCM43xx_COREID_SDIO_HOST 0x81b
+#define BCM43xx_COREID_PCIE 0x820
/* Core Information Registers */
#define BCM43xx_CIR_BASE 0xf00
@@ -365,6 +394,9 @@
#define BCM43xx_DEFAULT_SHORT_RETRY_LIMIT 7
#define BCM43xx_DEFAULT_LONG_RETRY_LIMIT 4
+/* FIXME: the next line is a guess as to what the maximum RSSI value might be */
+#define RX_RSSI_MAX 60
+
/* Max size of a security key */
#define BCM43xx_SEC_KEYSIZE 16
/* Security algorithms. */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index 728a9b789fdf..2ec2e5afce67 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -130,6 +130,10 @@ MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for debugging.");
{ PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
/* Broadcom 4307 802.11b */
{ PCI_VENDOR_ID_BROADCOM, 0x4307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ /* Broadcom 4311 802.11(a)/b/g */
+ { PCI_VENDOR_ID_BROADCOM, 0x4311, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ /* Broadcom 4312 802.11a/b/g */
+ { PCI_VENDOR_ID_BROADCOM, 0x4312, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
/* Broadcom 4318 802.11b/g */
{ PCI_VENDOR_ID_BROADCOM, 0x4318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
/* Broadcom 4319 802.11a/b/g */
@@ -2600,8 +2604,9 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm)
/* fetch sb_id_hi from core information registers */
sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI);
- core_id = (sb_id_hi & 0xFFF0) >> 4;
- core_rev = (sb_id_hi & 0xF);
+ core_id = (sb_id_hi & 0x8FF0) >> 4;
+ core_rev = (sb_id_hi & 0x7000) >> 8;
+ core_rev |= (sb_id_hi & 0xF);
core_vendor = (sb_id_hi & 0xFFFF0000) >> 16;
/* if present, chipcommon is always core 0; read the chipid from it */
@@ -2679,14 +2684,10 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm)
bcm->chip_id, bcm->chip_rev);
dprintk(KERN_INFO PFX "Number of cores: %d\n", core_count);
if (bcm->core_chipcommon.available) {
- dprintk(KERN_INFO PFX "Core 0: ID 0x%x, rev 0x%x, vendor 0x%x, %s\n",
- core_id, core_rev, core_vendor,
- bcm43xx_core_enabled(bcm) ? "enabled" : "disabled");
- }
-
- if (bcm->core_chipcommon.available)
+ dprintk(KERN_INFO PFX "Core 0: ID 0x%x, rev 0x%x, vendor 0x%x\n",
+ core_id, core_rev, core_vendor);
current_core = 1;
- else
+ } else
current_core = 0;
for ( ; current_core < core_count; current_core++) {
struct bcm43xx_coreinfo *core;
@@ -2704,13 +2705,13 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm)
core_rev = (sb_id_hi & 0xF);
core_vendor = (sb_id_hi & 0xFFFF0000) >> 16;
- dprintk(KERN_INFO PFX "Core %d: ID 0x%x, rev 0x%x, vendor 0x%x, %s\n",
- current_core, core_id, core_rev, core_vendor,
- bcm43xx_core_enabled(bcm) ? "enabled" : "disabled" );
+ dprintk(KERN_INFO PFX "Core %d: ID 0x%x, rev 0x%x, vendor 0x%x\n",
+ current_core, core_id, core_rev, core_vendor);
core = NULL;
switch (core_id) {
case BCM43xx_COREID_PCI:
+ case BCM43xx_COREID_PCIE:
core = &bcm->core_pci;
if (core->available) {
printk(KERN_WARNING PFX "Multiple PCI cores found.\n");
@@ -2749,12 +2750,12 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm)
case 6:
case 7:
case 9:
+ case 10:
break;
default:
- printk(KERN_ERR PFX "Error: Unsupported 80211 core revision %u\n",
+ printk(KERN_WARNING PFX
+ "Unsupported 80211 core revision %u\n",
core_rev);
- err = -ENODEV;
- goto out;
}
bcm->nr_80211_available++;
core->priv = ext_80211;
@@ -2868,16 +2869,11 @@ static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm,
u32 sbimconfiglow;
u8 limit;
- if (bcm->chip_rev < 5) {
+ if (bcm->core_pci.rev <= 5 && bcm->core_pci.id != BCM43xx_COREID_PCIE) {
sbimconfiglow = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW);
sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK;
sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK;
- if (bcm->bustype == BCM43xx_BUSTYPE_PCI)
- sbimconfiglow |= 0x32;
- else if (bcm->bustype == BCM43xx_BUSTYPE_SB)
- sbimconfiglow |= 0x53;
- else
- assert(0);
+ sbimconfiglow |= 0x32;
bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, sbimconfiglow);
}
@@ -3004,22 +3000,64 @@ static void bcm43xx_pcicore_broadcast_value(struct bcm43xx_private *bcm,
static int bcm43xx_pcicore_commit_settings(struct bcm43xx_private *bcm)
{
- int err;
- struct bcm43xx_coreinfo *old_core;
+ int err = 0;
- old_core = bcm->current_core;
- err = bcm43xx_switch_core(bcm, &bcm->core_pci);
- if (err)
- goto out;
+ bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
- bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000);
+ if (bcm->core_chipcommon.available) {
+ err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
+ if (err)
+ goto out;
+
+ bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000);
+
+ /* this function is always called when a PCI core is mapped */
+ err = bcm43xx_switch_core(bcm, &bcm->core_pci);
+ if (err)
+ goto out;
+ } else
+ bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000);
+
+ bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
- bcm43xx_switch_core(bcm, old_core);
- assert(err == 0);
out:
return err;
}
+static u32 bcm43xx_pcie_reg_read(struct bcm43xx_private *bcm, u32 address)
+{
+ bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_ADDR, address);
+ return bcm43xx_read32(bcm, BCM43xx_PCIECORE_REG_DATA);
+}
+
+static void bcm43xx_pcie_reg_write(struct bcm43xx_private *bcm, u32 address,
+ u32 data)
+{
+ bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_ADDR, address);
+ bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_DATA, data);
+}
+
+static void bcm43xx_pcie_mdio_write(struct bcm43xx_private *bcm, u8 dev, u8 reg,
+ u16 data)
+{
+ int i;
+
+ bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_CTL, 0x0082);
+ bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_DATA, BCM43xx_PCIE_MDIO_ST |
+ BCM43xx_PCIE_MDIO_WT | (dev << BCM43xx_PCIE_MDIO_DEV) |
+ (reg << BCM43xx_PCIE_MDIO_REG) | BCM43xx_PCIE_MDIO_TA |
+ data);
+ udelay(10);
+
+ for (i = 0; i < 10; i++) {
+ if (bcm43xx_read32(bcm, BCM43xx_PCIECORE_MDIO_CTL) &
+ BCM43xx_PCIE_MDIO_TC)
+ break;
+ msleep(1);
+ }
+ bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_CTL, 0);
+}
+
/* Make an I/O Core usable. "core_mask" is the bitmask of the cores to enable.
* To enable core 0, pass a core_mask of 1<<0
*/
@@ -3039,7 +3077,8 @@ static int bcm43xx_setup_backplane_pci_connection(struct bcm43xx_private *bcm,
if (err)
goto out;
- if (bcm->core_pci.rev < 6) {
+ if (bcm->current_core->rev < 6 ||
+ bcm->current_core->id == BCM43xx_COREID_PCI) {
value = bcm43xx_read32(bcm, BCM43xx_CIR_SBINTVEC);
value |= (1 << backplane_flag_nr);
bcm43xx_write32(bcm, BCM43xx_CIR_SBINTVEC, value);
@@ -3057,21 +3096,46 @@ static int bcm43xx_setup_backplane_pci_connection(struct bcm43xx_private *bcm,
}
}
- value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2);
- value |= BCM43xx_SBTOPCI2_PREFETCH | BCM43xx_SBTOPCI2_BURST;
- bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value);
-
- if (bcm->core_pci.rev < 5) {
- value = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW);
- value |= (2 << BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT)
- & BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK;
- value |= (3 << BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT)
- & BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK;
- bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, value);
- err = bcm43xx_pcicore_commit_settings(bcm);
- assert(err == 0);
+ if (bcm->current_core->id == BCM43xx_COREID_PCI) {
+ value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2);
+ value |= BCM43xx_SBTOPCI2_PREFETCH | BCM43xx_SBTOPCI2_BURST;
+ bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value);
+
+ if (bcm->current_core->rev < 5) {
+ value = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW);
+ value |= (2 << BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT)
+ & BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK;
+ value |= (3 << BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT)
+ & BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK;
+ bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, value);
+ err = bcm43xx_pcicore_commit_settings(bcm);
+ assert(err == 0);
+ } else if (bcm->current_core->rev >= 11) {
+ value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2);
+ value |= BCM43xx_SBTOPCI2_MEMREAD_MULTI;
+ bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value);
+ }
+ } else {
+ if (bcm->current_core->rev == 0 || bcm->current_core->rev == 1) {
+ value = bcm43xx_pcie_reg_read(bcm, BCM43xx_PCIE_TLP_WORKAROUND);
+ value |= 0x8;
+ bcm43xx_pcie_reg_write(bcm, BCM43xx_PCIE_TLP_WORKAROUND,
+ value);
+ }
+ if (bcm->current_core->rev == 0) {
+ bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX,
+ BCM43xx_SERDES_RXTIMER, 0x8128);
+ bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX,
+ BCM43xx_SERDES_CDR, 0x0100);
+ bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX,
+ BCM43xx_SERDES_CDR_BW, 0x1466);
+ } else if (bcm->current_core->rev == 1) {
+ value = bcm43xx_pcie_reg_read(bcm, BCM43xx_PCIE_DLLP_LINKCTL);
+ value |= 0x40;
+ bcm43xx_pcie_reg_write(bcm, BCM43xx_PCIE_DLLP_LINKCTL,
+ value);
+ }
}
-
out_switch_back:
err = bcm43xx_switch_core(bcm, old_core);
out:
@@ -3140,43 +3204,17 @@ static void bcm43xx_periodic_every15sec(struct bcm43xx_private *bcm)
static void do_periodic_work(struct bcm43xx_private *bcm)
{
- unsigned int state;
-
- state = bcm->periodic_state;
- if (state % 8 == 0)
+ if (bcm->periodic_state % 8 == 0)
bcm43xx_periodic_every120sec(bcm);
- if (state % 4 == 0)
+ if (bcm->periodic_state % 4 == 0)
bcm43xx_periodic_every60sec(bcm);
- if (state % 2 == 0)
+ if (bcm->periodic_state % 2 == 0)
bcm43xx_periodic_every30sec(bcm);
- if (state % 1 == 0)
- bcm43xx_periodic_every15sec(bcm);
- bcm->periodic_state = state + 1;
+ bcm43xx_periodic_every15sec(bcm);
schedule_delayed_work(&bcm->periodic_work, HZ * 15);
}
-/* Estimate a "Badness" value based on the periodic work
- * state-machine state. "Badness" is worse (bigger), if the
- * periodic work will take longer.
- */
-static int estimate_periodic_work_badness(unsigned int state)
-{
- int badness = 0;
-
- if (state % 8 == 0) /* every 120 sec */
- badness += 10;
- if (state % 4 == 0) /* every 60 sec */
- badness += 5;
- if (state % 2 == 0) /* every 30 sec */
- badness += 1;
- if (state % 1 == 0) /* every 15 sec */
- badness += 1;
-
-#define BADNESS_LIMIT 4
- return badness;
-}
-
static void bcm43xx_periodic_work_handler(struct work_struct *work)
{
struct bcm43xx_private *bcm =
@@ -3184,12 +3222,10 @@ static void bcm43xx_periodic_work_handler(struct work_struct *work)
struct net_device *net_dev = bcm->net_dev;
unsigned long flags;
u32 savedirqs = 0;
- int badness;
unsigned long orig_trans_start = 0;
mutex_lock(&bcm->mutex);
- badness = estimate_periodic_work_badness(bcm->periodic_state);
- if (badness > BADNESS_LIMIT) {
+ if (unlikely(bcm->periodic_state % 4 == 0)) {
/* Periodic work will take a long time, so we want it to
* be preemtible.
*/
@@ -3221,7 +3257,7 @@ static void bcm43xx_periodic_work_handler(struct work_struct *work)
do_periodic_work(bcm);
- if (badness > BADNESS_LIMIT) {
+ if (unlikely(bcm->periodic_state % 4 == 0)) {
spin_lock_irqsave(&bcm->irq_lock, flags);
tasklet_enable(&bcm->isr_tasklet);
bcm43xx_interrupt_enable(bcm, savedirqs);
@@ -3232,6 +3268,7 @@ static void bcm43xx_periodic_work_handler(struct work_struct *work)
net_dev->trans_start = orig_trans_start;
}
mmiowb();
+ bcm->periodic_state++;
spin_unlock_irqrestore(&bcm->irq_lock, flags);
mutex_unlock(&bcm->mutex);
}
@@ -3677,7 +3714,7 @@ static int bcm43xx_read_phyinfo(struct bcm43xx_private *bcm)
bcm->ieee->freq_band = IEEE80211_24GHZ_BAND;
break;
case BCM43xx_PHYTYPE_G:
- if (phy_rev > 7)
+ if (phy_rev > 8)
phy_rev_ok = 0;
bcm->ieee->modulation = IEEE80211_OFDM_MODULATION |
IEEE80211_CCK_MODULATION;
@@ -3689,6 +3726,8 @@ static int bcm43xx_read_phyinfo(struct bcm43xx_private *bcm)
phy_type);
return -ENODEV;
};
+ bcm->ieee->perfect_rssi = RX_RSSI_MAX;
+ bcm->ieee->worst_rssi = 0;
if (!phy_rev_ok) {
printk(KERN_WARNING PFX "Invalid PHY Revision %x\n",
phy_rev);
@@ -3975,11 +4014,6 @@ static int bcm43xx_ieee80211_hard_start_xmit(struct ieee80211_txb *txb,
return NETDEV_TX_OK;
}
-static struct net_device_stats * bcm43xx_net_get_stats(struct net_device *net_dev)
-{
- return &(bcm43xx_priv(net_dev)->ieee->stats);
-}
-
static void bcm43xx_net_tx_timeout(struct net_device *net_dev)
{
struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
@@ -4093,7 +4127,6 @@ static int __devinit bcm43xx_init_one(struct pci_dev *pdev,
net_dev->open = bcm43xx_net_open;
net_dev->stop = bcm43xx_net_stop;
- net_dev->get_stats = bcm43xx_net_get_stats;
net_dev->tx_timeout = bcm43xx_net_tx_timeout;
#ifdef CONFIG_NET_POLL_CONTROLLER
net_dev->poll_controller = bcm43xx_net_poll_controller;
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_power.c b/drivers/net/wireless/bcm43xx/bcm43xx_power.c
index 6569da3a7a39..7e774f410953 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_power.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_power.c
@@ -153,8 +153,6 @@ int bcm43xx_pctl_init(struct bcm43xx_private *bcm)
int err, maxfreq;
struct bcm43xx_coreinfo *old_core;
- if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL))
- return 0;
old_core = bcm->current_core;
err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
if (err == -ENODEV)
@@ -162,11 +160,27 @@ int bcm43xx_pctl_init(struct bcm43xx_private *bcm)
if (err)
goto out;
- maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1);
- bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY,
- (maxfreq * 150 + 999999) / 1000000);
- bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_FREFSELDELAY,
- (maxfreq * 15 + 999999) / 1000000);
+ if (bcm->chip_id == 0x4321) {
+ if (bcm->chip_rev == 0)
+ bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_CTL, 0x03A4);
+ if (bcm->chip_rev == 1)
+ bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_CTL, 0x00A4);
+ }
+
+ if (bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL) {
+ if (bcm->current_core->rev >= 10) {
+ /* Set Idle Power clock rate to 1Mhz */
+ bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL,
+ (bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL)
+ & 0x0000FFFF) | 0x40000);
+ } else {
+ maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1);
+ bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY,
+ (maxfreq * 150 + 999999) / 1000000);
+ bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_FREFSELDELAY,
+ (maxfreq * 15 + 999999) / 1000000);
+ }
+ }
err = bcm43xx_switch_core(bcm, old_core);
assert(err == 0);
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
index d27016f8c736..a659442b9c15 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
@@ -47,9 +47,6 @@
#define BCM43xx_WX_VERSION 18
#define MAX_WX_STRING 80
-/* FIXME: the next line is a guess as to what the maximum RSSI value might be */
-#define RX_RSSI_MAX 60
-
static int bcm43xx_wx_get_name(struct net_device *net_dev,
struct iw_request_info *info,
@@ -693,6 +690,7 @@ static int bcm43xx_wx_set_swencryption(struct net_device *net_dev,
bcm->ieee->host_encrypt = !!on;
bcm->ieee->host_decrypt = !!on;
bcm->ieee->host_build_iv = !on;
+ bcm->ieee->host_strip_iv_icv = !on;
spin_unlock_irqrestore(&bcm->irq_lock, flags);
mutex_unlock(&bcm->mutex);
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
index 0159e4e93201..3e2462671690 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
@@ -544,24 +544,6 @@ int bcm43xx_rx(struct bcm43xx_private *bcm,
}
frame_ctl = le16_to_cpu(wlhdr->frame_ctl);
- if ((frame_ctl & IEEE80211_FCTL_PROTECTED) && !bcm->ieee->host_decrypt) {
- frame_ctl &= ~IEEE80211_FCTL_PROTECTED;
- wlhdr->frame_ctl = cpu_to_le16(frame_ctl);
- /* trim IV and ICV */
- /* FIXME: this must be done only for WEP encrypted packets */
- if (skb->len < 32) {
- dprintkl(KERN_ERR PFX "RX packet dropped (PROTECTED flag "
- "set and length < 32)\n");
- return -EINVAL;
- } else {
- memmove(skb->data + 4, skb->data, 24);
- skb_pull(skb, 4);
- skb_trim(skb, skb->len - 4);
- stats.len -= 8;
- }
- wlhdr = (struct ieee80211_hdr_4addr *)(skb->data);
- }
-
switch (WLAN_FC_GET_TYPE(frame_ctl)) {
case IEEE80211_FTYPE_MGMT:
ieee80211_rx_mgt(bcm->ieee, wlhdr, &stats);
diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c
index c2fa011be291..d1de9766c831 100644
--- a/drivers/net/wireless/hostap/hostap_pci.c
+++ b/drivers/net/wireless/hostap/hostap_pci.c
@@ -425,8 +425,14 @@ static int prism2_pci_suspend(struct pci_dev *pdev, pm_message_t state)
static int prism2_pci_resume(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
+ int err;
- pci_enable_device(pdev);
+ err = pci_enable_device(pdev);
+ if (err) {
+ printk(KERN_ERR "%s: pci_enable_device failed on resume\n",
+ dev->name);
+ return err;
+ }
pci_restore_state(pdev);
prism2_hw_config(dev, 0);
if (netif_running(dev)) {
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index 0f554373a60d..1bcd352a813b 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -5833,19 +5833,6 @@ static void ipw2100_tx_timeout(struct net_device *dev)
schedule_reset(priv);
}
-/*
- * TODO: reimplement it so that it reads statistics
- * from the adapter using ordinal tables
- * instead of/in addition to collecting them
- * in the driver
- */
-static struct net_device_stats *ipw2100_stats(struct net_device *dev)
-{
- struct ipw2100_priv *priv = ieee80211_priv(dev);
-
- return &priv->ieee->stats;
-}
-
static int ipw2100_wpa_enable(struct ipw2100_priv *priv, int value)
{
/* This is called when wpa_supplicant loads and closes the driver
@@ -6030,7 +6017,6 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev,
dev->open = ipw2100_open;
dev->stop = ipw2100_close;
dev->init = ipw2100_net_init;
- dev->get_stats = ipw2100_stats;
dev->ethtool_ops = &ipw2100_ethtool_ops;
dev->tx_timeout = ipw2100_tx_timeout;
dev->wireless_handlers = &ipw2100_wx_handler_def;
@@ -6428,6 +6414,7 @@ static int ipw2100_resume(struct pci_dev *pci_dev)
{
struct ipw2100_priv *priv = pci_get_drvdata(pci_dev);
struct net_device *dev = priv->net_dev;
+ int err;
u32 val;
if (IPW2100_PM_DISABLED)
@@ -6438,7 +6425,12 @@ static int ipw2100_resume(struct pci_dev *pci_dev)
IPW_DEBUG_INFO("%s: Coming out of suspend...\n", dev->name);
pci_set_power_state(pci_dev, PCI_D0);
- pci_enable_device(pci_dev);
+ err = pci_enable_device(pci_dev);
+ if (err) {
+ printk(KERN_ERR "%s: pci_enable_device failed on resume\n",
+ dev->name);
+ return err;
+ }
pci_restore_state(pci_dev);
/*
@@ -7573,11 +7565,10 @@ static int ipw2100_wx_set_genie(struct net_device *dev,
return -EINVAL;
if (wrqu->data.length) {
- buf = kmalloc(wrqu->data.length, GFP_KERNEL);
+ buf = kmemdup(extra, wrqu->data.length, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
- memcpy(buf, extra, wrqu->data.length);
kfree(ieee->wpa_ie);
ieee->wpa_ie = buf;
ieee->wpa_ie_len = wrqu->data.length;
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index 587a0918fa52..e82e56bb85e1 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -6938,8 +6938,8 @@ static int ipw_qos_association(struct ipw_priv *priv,
}
/*
-* handling the beaconing responces. if we get different QoS setting
-* of the network from the the associated setting adjust the QoS
+* handling the beaconing responses. if we get different QoS setting
+* off the network from the associated setting, adjust the QoS
* setting
*/
static int ipw_qos_association_resp(struct ipw_priv *priv,
@@ -11746,12 +11746,18 @@ static int ipw_pci_resume(struct pci_dev *pdev)
{
struct ipw_priv *priv = pci_get_drvdata(pdev);
struct net_device *dev = priv->net_dev;
+ int err;
u32 val;
printk(KERN_INFO "%s: Coming out of suspend...\n", dev->name);
pci_set_power_state(pdev, PCI_D0);
- pci_enable_device(pdev);
+ err = pci_enable_device(pdev);
+ if (err) {
+ printk(KERN_ERR "%s: pci_enable_device failed on resume\n",
+ dev->name);
+ return err;
+ }
pci_restore_state(pdev);
/*
diff --git a/drivers/net/wireless/orinoco_pci.h b/drivers/net/wireless/orinoco_pci.h
index be1abea4b64f..f4e5e06760c1 100644
--- a/drivers/net/wireless/orinoco_pci.h
+++ b/drivers/net/wireless/orinoco_pci.h
@@ -60,7 +60,12 @@ static int orinoco_pci_resume(struct pci_dev *pdev)
int err;
pci_set_power_state(pdev, 0);
- pci_enable_device(pdev);
+ err = pci_enable_device(pdev);
+ if (err) {
+ printk(KERN_ERR "%s: pci_enable_device failed on resume\n",
+ dev->name);
+ return err;
+ }
pci_restore_state(pdev);
err = request_irq(pdev->irq, orinoco_interrupt, IRQF_SHARED,
diff --git a/drivers/net/wireless/prism54/isl_38xx.c b/drivers/net/wireless/prism54/isl_38xx.c
index 23deee69974b..02fc67bccbd0 100644
--- a/drivers/net/wireless/prism54/isl_38xx.c
+++ b/drivers/net/wireless/prism54/isl_38xx.c
@@ -1,5 +1,4 @@
/*
- *
* Copyright (C) 2002 Intersil Americas Inc.
* Copyright (C) 2003-2004 Luis R. Rodriguez <mcgrof@ruslug.rutgers.edu>_
*
@@ -38,7 +37,7 @@
* isl38xx_disable_interrupts - disable all interrupts
* @device: pci memory base address
*
- * Instructs the device to disable all interrupt reporting by asserting
+ * Instructs the device to disable all interrupt reporting by asserting
* the IRQ line. New events may still show up in the interrupt identification
* register located at offset %ISL38XX_INT_IDENT_REG.
*/
@@ -204,17 +203,19 @@ isl38xx_interface_reset(void __iomem *device_base, dma_addr_t host_address)
/* enable the interrupt for detecting initialization */
/* Note: Do not enable other interrupts here. We want the
- * device to have come up first 100% before allowing any other
+ * device to have come up first 100% before allowing any other
* interrupts. */
isl38xx_w32_flush(device_base, ISL38XX_INT_IDENT_INIT, ISL38XX_INT_EN_REG);
udelay(ISL38XX_WRITEIO_DELAY); /* allow complete full reset */
}
void
-isl38xx_enable_common_interrupts(void __iomem *device_base) {
+isl38xx_enable_common_interrupts(void __iomem *device_base)
+{
u32 reg;
- reg = ( ISL38XX_INT_IDENT_UPDATE |
- ISL38XX_INT_IDENT_SLEEP | ISL38XX_INT_IDENT_WAKEUP);
+
+ reg = ISL38XX_INT_IDENT_UPDATE | ISL38XX_INT_IDENT_SLEEP |
+ ISL38XX_INT_IDENT_WAKEUP;
isl38xx_w32_flush(device_base, reg, ISL38XX_INT_EN_REG);
udelay(ISL38XX_WRITEIO_DELAY);
}
@@ -234,23 +235,21 @@ isl38xx_in_queue(isl38xx_control_block *cb, int queue)
/* send queues */
case ISL38XX_CB_TX_MGMTQ:
BUG_ON(delta > ISL38XX_CB_MGMT_QSIZE);
+
case ISL38XX_CB_TX_DATA_LQ:
case ISL38XX_CB_TX_DATA_HQ:
BUG_ON(delta > ISL38XX_CB_TX_QSIZE);
return delta;
- break;
/* receive queues */
case ISL38XX_CB_RX_MGMTQ:
BUG_ON(delta > ISL38XX_CB_MGMT_QSIZE);
return ISL38XX_CB_MGMT_QSIZE - delta;
- break;
case ISL38XX_CB_RX_DATA_LQ:
case ISL38XX_CB_RX_DATA_HQ:
BUG_ON(delta > ISL38XX_CB_RX_QSIZE);
return ISL38XX_CB_RX_QSIZE - delta;
- break;
}
BUG();
return 0;
diff --git a/drivers/net/wireless/prism54/isl_38xx.h b/drivers/net/wireless/prism54/isl_38xx.h
index 8af20980af8d..3fadcb6f5297 100644
--- a/drivers/net/wireless/prism54/isl_38xx.h
+++ b/drivers/net/wireless/prism54/isl_38xx.h
@@ -1,5 +1,4 @@
/*
- *
* Copyright (C) 2002 Intersil Americas Inc.
*
* This program is free software; you can redistribute it and/or modify
@@ -67,10 +66,10 @@
* @base: (host) memory base address of the device
* @val: 32bit value (host order) to write
* @offset: byte offset into @base to write value to
- *
+ *
* This helper takes care of writing a 32bit datum to the
- * specified offset into the device's pci memory space, and making sure
- * the pci memory buffers get flushed by performing one harmless read
+ * specified offset into the device's pci memory space, and making sure
+ * the pci memory buffers get flushed by performing one harmless read
* from the %ISL38XX_PCI_POSTING_FLUSH offset.
*/
static inline void
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
index e7700b4257eb..a87eb51886c8 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/prism54/isl_ioctl.c
@@ -1,5 +1,4 @@
/*
- *
* Copyright (C) 2002 Intersil Americas Inc.
* (C) 2003,2004 Aurelien Alleaume <slts@free.fr>
* (C) 2003 Herbert Valerio Riedel <hvr@gnu.org>
@@ -55,12 +54,12 @@ static const unsigned char scan_rate_list[] = { 2, 4, 11, 22,
* prism54_mib_mode_helper - MIB change mode helper function
* @mib: the &struct islpci_mib object to modify
* @iw_mode: new mode (%IW_MODE_*)
- *
+ *
* This is a helper function, hence it does not lock. Make sure
- * caller deals with locking *if* necessary. This function sets the
- * mode-dependent mib values and does the mapping of the Linux
- * Wireless API modes to Device firmware modes. It also checks for
- * correct valid Linux wireless modes.
+ * caller deals with locking *if* necessary. This function sets the
+ * mode-dependent mib values and does the mapping of the Linux
+ * Wireless API modes to Device firmware modes. It also checks for
+ * correct valid Linux wireless modes.
*/
static int
prism54_mib_mode_helper(islpci_private *priv, u32 iw_mode)
@@ -118,7 +117,7 @@ prism54_mib_mode_helper(islpci_private *priv, u32 iw_mode)
*
* this function initializes the struct given as @mib with defaults,
* of which many are retrieved from the global module parameter
- * variables.
+ * variables.
*/
void
@@ -134,7 +133,7 @@ prism54_mib_init(islpci_private *priv)
authen = CARD_DEFAULT_AUTHEN;
wep = CARD_DEFAULT_WEP;
filter = CARD_DEFAULT_FILTER; /* (0) Do not filter un-encrypted data */
- dot1x = CARD_DEFAULT_DOT1X;
+ dot1x = CARD_DEFAULT_DOT1X;
mlme = CARD_DEFAULT_MLME_MODE;
conformance = CARD_DEFAULT_CONFORMANCE;
power = 127;
@@ -229,7 +228,7 @@ prism54_get_wireless_stats(struct net_device *ndev)
} else
priv->iwstatistics.qual.updated = 0;
- /* Update our wireless stats, but do not schedule to often
+ /* Update our wireless stats, but do not schedule to often
* (max 1 HZ) */
if ((priv->stats_timestamp == 0) ||
time_after(jiffies, priv->stats_timestamp + 1 * HZ)) {
@@ -706,7 +705,7 @@ prism54_get_scan(struct net_device *ndev, struct iw_request_info *info,
* Starting with WE-17, the buffer can be as big as needed.
* But the device won't repport anything if you change the value
* of IWMAX_BSS=24. */
-
+
rvalue |= mgt_get_request(priv, DOT11_OID_BSSLIST, 0, NULL, &r);
bsslist = r.ptr;
@@ -786,7 +785,7 @@ prism54_get_essid(struct net_device *ndev, struct iw_request_info *info,
return rvalue;
}
-/* Provides no functionality, just completes the ioctl. In essence this is a
+/* Provides no functionality, just completes the ioctl. In essence this is a
* just a cosmetic ioctl.
*/
static int
@@ -1105,7 +1104,7 @@ prism54_set_encode(struct net_device *ndev, struct iw_request_info *info,
&key);
}
/*
- * If a valid key is set, encryption should be enabled
+ * If a valid key is set, encryption should be enabled
* (user may turn it off later).
* This is also how "iwconfig ethX key on" works
*/
@@ -1127,7 +1126,7 @@ prism54_set_encode(struct net_device *ndev, struct iw_request_info *info,
}
/* now read the flags */
if (dwrq->flags & IW_ENCODE_DISABLED) {
- /* Encoding disabled,
+ /* Encoding disabled,
* authen = DOT11_AUTH_OS;
* invoke = 0;
* exunencrypt = 0; */
@@ -1215,7 +1214,7 @@ prism54_get_txpower(struct net_device *ndev, struct iw_request_info *info,
vwrq->value = (s32) r.u / 4;
vwrq->fixed = 1;
/* radio is not turned of
- * btw: how is possible to turn off only the radio
+ * btw: how is possible to turn off only the radio
*/
vwrq->disabled = 0;
@@ -2355,17 +2354,17 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid,
handle_request(priv, mlme, oid);
send_formatted_event(priv, "Authenticate request (ex)", mlme, 1);
- if (priv->iw_mode != IW_MODE_MASTER
+ if (priv->iw_mode != IW_MODE_MASTER
&& mlmeex->state != DOT11_STATE_AUTHING)
break;
confirm = kmalloc(sizeof(struct obj_mlmeex) + 6, GFP_ATOMIC);
- if (!confirm)
+ if (!confirm)
break;
memcpy(&confirm->address, mlmeex->address, ETH_ALEN);
- printk(KERN_DEBUG "Authenticate from: address:\t%02x:%02x:%02x:%02x:%02x:%02x\n",
+ printk(KERN_DEBUG "Authenticate from: address:\t%02x:%02x:%02x:%02x:%02x:%02x\n",
mlmeex->address[0],
mlmeex->address[1],
mlmeex->address[2],
@@ -2399,10 +2398,10 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid,
handle_request(priv, mlme, oid);
send_formatted_event(priv, "Associate request (ex)", mlme, 1);
- if (priv->iw_mode != IW_MODE_MASTER
+ if (priv->iw_mode != IW_MODE_MASTER
&& mlmeex->state != DOT11_STATE_ASSOCING)
break;
-
+
confirm = kmalloc(sizeof(struct obj_mlmeex), GFP_ATOMIC);
if (!confirm)
@@ -2418,7 +2417,7 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid,
if (!wpa_ie_len) {
printk(KERN_DEBUG "No WPA IE found from "
- "address:\t%02x:%02x:%02x:%02x:%02x:%02x\n",
+ "address:\t%02x:%02x:%02x:%02x:%02x:%02x\n",
mlmeex->address[0],
mlmeex->address[1],
mlmeex->address[2],
@@ -2436,14 +2435,14 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid,
mgt_set_varlen(priv, oid, confirm, wpa_ie_len);
kfree(confirm);
-
+
break;
case DOT11_OID_REASSOCIATEEX:
handle_request(priv, mlme, oid);
send_formatted_event(priv, "Reassociate request (ex)", mlme, 1);
- if (priv->iw_mode != IW_MODE_MASTER
+ if (priv->iw_mode != IW_MODE_MASTER
&& mlmeex->state != DOT11_STATE_ASSOCING)
break;
@@ -2462,7 +2461,7 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid,
if (!wpa_ie_len) {
printk(KERN_DEBUG "No WPA IE found from "
- "address:\t%02x:%02x:%02x:%02x:%02x:%02x\n",
+ "address:\t%02x:%02x:%02x:%02x:%02x:%02x\n",
mlmeex->address[0],
mlmeex->address[1],
mlmeex->address[2],
@@ -2474,13 +2473,13 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid,
break;
}
- confirm->size = wpa_ie_len;
+ confirm->size = wpa_ie_len;
memcpy(&confirm->data, wpa_ie, wpa_ie_len);
mgt_set_varlen(priv, oid, confirm, wpa_ie_len);
kfree(confirm);
-
+
break;
default:
@@ -2547,10 +2546,10 @@ enum {
#define PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN \
((int) (&((struct prism2_hostapd_param *) 0)->u.generic_elem.data))
-/* Maximum length for algorithm names (-1 for nul termination)
+/* Maximum length for algorithm names (-1 for nul termination)
* used in ioctl() */
#define HOSTAP_CRYPT_ALG_NAME_LEN 16
-
+
struct prism2_hostapd_param {
u32 cmd;
u8 sta_addr[ETH_ALEN];
@@ -2623,7 +2622,7 @@ prism2_ioctl_set_encryption(struct net_device *dev,
&key);
}
/*
- * If a valid key is set, encryption should be enabled
+ * If a valid key is set, encryption should be enabled
* (user may turn it off later).
* This is also how "iwconfig ethX key on" works
*/
@@ -2645,7 +2644,7 @@ prism2_ioctl_set_encryption(struct net_device *dev,
}
/* now read the flags */
if (param->u.crypt.flags & IW_ENCODE_DISABLED) {
- /* Encoding disabled,
+ /* Encoding disabled,
* authen = DOT11_AUTH_OS;
* invoke = 0;
* exunencrypt = 0; */
@@ -2712,7 +2711,7 @@ prism2_ioctl_set_generic_element(struct net_device *ndev,
ret = mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, attach, len);
- if (ret == 0)
+ if (ret == 0)
printk(KERN_DEBUG "%s: WPA IE Attachment was set\n",
ndev->name);
}
@@ -2872,7 +2871,7 @@ prism54_set_wpa(struct net_device *ndev, struct iw_request_info *info,
mlme = DOT11_MLME_AUTO;
printk("%s: Disabling WPA\n", ndev->name);
break;
- case 2:
+ case 2:
case 1: /* WPA */
printk("%s: Enabling WPA\n", ndev->name);
break;
diff --git a/drivers/net/wireless/prism54/isl_ioctl.h b/drivers/net/wireless/prism54/isl_ioctl.h
index 0802fa64996f..bcfbfb9281d2 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.h
+++ b/drivers/net/wireless/prism54/isl_ioctl.h
@@ -1,5 +1,4 @@
/*
- *
* Copyright (C) 2002 Intersil Americas Inc.
* (C) 2003 Aurelien Alleaume <slts@free.fr>
* (C) 2003 Luis R. Rodriguez <mcgrof@ruslug.rutgers.edu>
diff --git a/drivers/net/wireless/prism54/isl_oid.h b/drivers/net/wireless/prism54/isl_oid.h
index 419edf7ccf1a..b7534c2869c8 100644
--- a/drivers/net/wireless/prism54/isl_oid.h
+++ b/drivers/net/wireless/prism54/isl_oid.h
@@ -1,6 +1,4 @@
/*
- *
- *
* Copyright (C) 2003 Herbert Valerio Riedel <hvr@gnu.org>
* Copyright (C) 2004 Luis R. Rodriguez <mcgrof@ruslug.rutgers.edu>
* Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
@@ -23,7 +21,7 @@
#if !defined(_ISL_OID_H)
#define _ISL_OID_H
-/*
+/*
* MIB related constant and structure definitions for communicating
* with the device firmware
*/
@@ -99,21 +97,21 @@ struct obj_attachment {
char data[0];
} __attribute__((packed));
-/*
+/*
* in case everything's ok, the inlined function below will be
* optimized away by the compiler...
*/
static inline void
__bug_on_wrong_struct_sizes(void)
{
- BUG_ON(sizeof (struct obj_ssid) != 34);
- BUG_ON(sizeof (struct obj_key) != 34);
- BUG_ON(sizeof (struct obj_mlme) != 12);
- BUG_ON(sizeof (struct obj_mlmeex) != 14);
- BUG_ON(sizeof (struct obj_buffer) != 8);
- BUG_ON(sizeof (struct obj_bss) != 60);
- BUG_ON(sizeof (struct obj_bsslist) != 4);
- BUG_ON(sizeof (struct obj_frequencies) != 2);
+ BUILD_BUG_ON(sizeof (struct obj_ssid) != 34);
+ BUILD_BUG_ON(sizeof (struct obj_key) != 34);
+ BUILD_BUG_ON(sizeof (struct obj_mlme) != 12);
+ BUILD_BUG_ON(sizeof (struct obj_mlmeex) != 14);
+ BUILD_BUG_ON(sizeof (struct obj_buffer) != 8);
+ BUILD_BUG_ON(sizeof (struct obj_bss) != 60);
+ BUILD_BUG_ON(sizeof (struct obj_bsslist) != 4);
+ BUILD_BUG_ON(sizeof (struct obj_frequencies) != 2);
}
enum dot11_state_t {
@@ -154,13 +152,13 @@ enum dot11_priv_t {
/* Prism "Nitro" / Frameburst / "Packet Frame Grouping"
* Value is in microseconds. Represents the # microseconds
- * the firmware will take to group frames before sending out then out
+ * the firmware will take to group frames before sending out then out
* together with a CSMA contention. Without this all frames are
- * sent with a CSMA contention.
- * Bibliography:
+ * sent with a CSMA contention.
+ * Bibliography:
* http://www.hpl.hp.com/personal/Jean_Tourrilhes/Papers/Packet.Frame.Grouping.html
*/
-enum dot11_maxframeburst_t {
+enum dot11_maxframeburst_t {
/* Values for DOT11_OID_MAXFRAMEBURST */
DOT11_MAXFRAMEBURST_OFF = 0, /* Card firmware default */
DOT11_MAXFRAMEBURST_MIXED_SAFE = 650, /* 802.11 a,b,g safe */
@@ -176,9 +174,9 @@ enum dot11_maxframeburst_t {
/* Support for 802.11 long and short frame preambles.
* Long preamble uses 128-bit sync field, 8-bit CRC
* Short preamble uses 56-bit sync field, 16-bit CRC
- *
+ *
* 802.11a -- not sure, both optionally ?
- * 802.11b supports long and optionally short
+ * 802.11b supports long and optionally short
* 802.11g supports both */
enum dot11_preamblesettings_t {
DOT11_PREAMBLESETTING_LONG = 0,
@@ -194,7 +192,7 @@ enum dot11_preamblesettings_t {
* Long uses 802.11a slot timing (9 usec ?)
* Short uses 802.11b slot timing (20 use ?) */
enum dot11_slotsettings_t {
- DOT11_SLOTSETTINGS_LONG = 0,
+ DOT11_SLOTSETTINGS_LONG = 0,
/* Allows *only* long 802.11b slot timing */
DOT11_SLOTSETTINGS_SHORT = 1,
/* Allows *only* long 802.11a slot timing */
@@ -203,7 +201,7 @@ enum dot11_slotsettings_t {
};
/* All you need to know, ERP is "Extended Rate PHY".
- * An Extended Rate PHY (ERP) STA or AP shall support three different
+ * An Extended Rate PHY (ERP) STA or AP shall support three different
* preamble and header formats:
* Long preamble (refer to above)
* Short preamble (refer to above)
@@ -221,7 +219,7 @@ enum do11_nonerpstatus_t {
/* (ERP is "Extended Rate PHY") Way to read NONERP is NON-ERP-*
* The key here is DOT11 NON ERP NEVER protects against
* NON ERP STA's. You *don't* want this unless
- * you know what you are doing. It means you will only
+ * you know what you are doing. It means you will only
* get Extended Rate capabilities */
enum dot11_nonerpprotection_t {
DOT11_NONERP_NEVER = 0,
@@ -229,13 +227,13 @@ enum dot11_nonerpprotection_t {
DOT11_NONERP_DYNAMIC = 2
};
-/* Preset OID configuration for 802.11 modes
- * Note: DOT11_OID_CW[MIN|MAX] hold the values of the
+/* Preset OID configuration for 802.11 modes
+ * Note: DOT11_OID_CW[MIN|MAX] hold the values of the
* DCS MIN|MAX backoff used */
enum dot11_profile_t { /* And set/allowed values */
/* Allowed values for DOT11_OID_PROFILES */
DOT11_PROFILE_B_ONLY = 0,
- /* DOT11_OID_RATES: 1, 2, 5.5, 11Mbps
+ /* DOT11_OID_RATES: 1, 2, 5.5, 11Mbps
* DOT11_OID_PREAMBLESETTINGS: DOT11_PREAMBLESETTING_DYNAMIC
* DOT11_OID_CWMIN: 31
* DOT11_OID_NONEPROTECTION: DOT11_NOERP_DYNAMIC
@@ -275,7 +273,7 @@ enum oid_inl_conformance_t {
OID_INL_CONFORMANCE_NONE = 0, /* Perform active scanning */
OID_INL_CONFORMANCE_STRICT = 1, /* Strictly adhere to 802.11d */
OID_INL_CONFORMANCE_FLEXIBLE = 2, /* Use passed 802.11d info to
- * determine channel AND/OR just make assumption that active
+ * determine channel AND/OR just make assumption that active
* channels are valid channels */
};
diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c
index e35fcb2543c4..f057fd9fcd79 100644
--- a/drivers/net/wireless/prism54/islpci_dev.c
+++ b/drivers/net/wireless/prism54/islpci_dev.c
@@ -1,5 +1,4 @@
/*
- *
* Copyright (C) 2002 Intersil Americas Inc.
* Copyright (C) 2003 Herbert Valerio Riedel <hvr@gnu.org>
* Copyright (C) 2003 Luis R. Rodriguez <mcgrof@ruslug.rutgers.edu>
@@ -413,7 +412,7 @@ prism54_bring_down(islpci_private *priv)
islpci_set_state(priv, PRV_STATE_PREBOOT);
/* disable all device interrupts in case they weren't */
- isl38xx_disable_interrupts(priv->device_base);
+ isl38xx_disable_interrupts(priv->device_base);
/* For safety reasons, we may want to ensure that no DMA transfer is
* currently in progress by emptying the TX and RX queues. */
@@ -480,7 +479,7 @@ islpci_reset_if(islpci_private *priv)
DEFINE_WAIT(wait);
prepare_to_wait(&priv->reset_done, &wait, TASK_UNINTERRUPTIBLE);
-
+
/* now the last step is to reset the interface */
isl38xx_interface_reset(priv->device_base, priv->device_host_address);
islpci_set_state(priv, PRV_STATE_PREINIT);
@@ -488,7 +487,7 @@ islpci_reset_if(islpci_private *priv)
for(count = 0; count < 2 && result; count++) {
/* The software reset acknowledge needs about 220 msec here.
* Be conservative and wait for up to one second. */
-
+
remaining = schedule_timeout_uninterruptible(HZ);
if(remaining > 0) {
@@ -496,7 +495,7 @@ islpci_reset_if(islpci_private *priv)
break;
}
- /* If we're here it's because our IRQ hasn't yet gone through.
+ /* If we're here it's because our IRQ hasn't yet gone through.
* Retry a bit more...
*/
printk(KERN_ERR "%s: no 'reset complete' IRQ seen - retrying\n",
@@ -514,7 +513,7 @@ islpci_reset_if(islpci_private *priv)
/* Now that the device is 100% up, let's allow
* for the other interrupts --
- * NOTE: this is not *yet* true since we've only allowed the
+ * NOTE: this is not *yet* true since we've only allowed the
* INIT interrupt on the IRQ line. We can perhaps poll
* the IRQ line until we know for sure the reset went through */
isl38xx_enable_common_interrupts(priv->device_base);
@@ -716,7 +715,7 @@ islpci_alloc_memory(islpci_private *priv)
prism54_acl_init(&priv->acl);
prism54_wpa_bss_ie_init(priv);
- if (mgt_init(priv))
+ if (mgt_init(priv))
goto out_free;
return 0;
diff --git a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h
index 2f7e525d0cf6..a9aa1662eaa4 100644
--- a/drivers/net/wireless/prism54/islpci_dev.h
+++ b/drivers/net/wireless/prism54/islpci_dev.h
@@ -1,6 +1,5 @@
/*
- *
- * Copyright (C) 2002 Intersil Americas Inc.
+ * Copyright (C) 2002 Intersil Americas Inc.
* Copyright (C) 2003 Herbert Valerio Riedel <hvr@gnu.org>
* Copyright (C) 2003 Luis R. Rodriguez <mcgrof@ruslug.rutgers.edu>
* Copyright (C) 2003 Aurelien Alleaume <slts@free.fr>
@@ -72,12 +71,12 @@ struct islpci_bss_wpa_ie {
u8 bssid[ETH_ALEN];
u8 wpa_ie[MAX_WPA_IE_LEN];
size_t wpa_ie_len;
-
+
};
typedef struct {
spinlock_t slock; /* generic spinlock; */
-
+
u32 priv_oid;
/* our mib cache */
@@ -85,7 +84,7 @@ typedef struct {
struct rw_semaphore mib_sem;
void **mib;
char nickname[IW_ESSID_MAX_SIZE+1];
-
+
/* Take care of the wireless stats */
struct work_struct stats_work;
struct semaphore stats_sem;
@@ -120,7 +119,7 @@ typedef struct {
struct net_device *ndev;
/* device queue interface members */
- struct isl38xx_cb *control_block; /* device control block
+ struct isl38xx_cb *control_block; /* device control block
(== driver_mem_address!) */
/* Each queue has three indexes:
diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c
index 103a37877733..b1122912ee2d 100644
--- a/drivers/net/wireless/prism54/islpci_eth.c
+++ b/drivers/net/wireless/prism54/islpci_eth.c
@@ -1,5 +1,4 @@
/*
- *
* Copyright (C) 2002 Intersil Americas Inc.
* Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
* This program is free software; you can redistribute it and/or modify
@@ -48,7 +47,7 @@ islpci_eth_cleanup_transmit(islpci_private *priv,
/* read the index of the first fragment to be freed */
index = priv->free_data_tx % ISL38XX_CB_TX_QSIZE;
- /* check for holes in the arrays caused by multi fragment frames
+ /* check for holes in the arrays caused by multi fragment frames
* searching for the last fragment of a frame */
if (priv->pci_map_tx_address[index] != (dma_addr_t) NULL) {
/* entry is the last fragment of a frame
@@ -253,6 +252,7 @@ islpci_monitor_rx(islpci_private *priv, struct sk_buff **skb)
* header and without the FCS. But there a is a bit that
* indicates if the packet is corrupted :-) */
struct rfmon_header *hdr = (struct rfmon_header *) (*skb)->data;
+
if (hdr->flags & 0x01)
/* This one is bad. Drop it ! */
return -1;
@@ -284,7 +284,7 @@ islpci_monitor_rx(islpci_private *priv, struct sk_buff **skb)
(struct avs_80211_1_header *) skb_push(*skb,
sizeof (struct
avs_80211_1_header));
-
+
avs->version = cpu_to_be32(P80211CAPTURE_VERSION);
avs->length = cpu_to_be32(sizeof (struct avs_80211_1_header));
avs->mactime = cpu_to_be64(le64_to_cpu(clock));
@@ -390,7 +390,7 @@ islpci_eth_receive(islpci_private *priv)
struct rx_annex_header *annex =
(struct rx_annex_header *) skb->data;
wstats.level = annex->rfmon.rssi;
- /* The noise value can be a bit outdated if nobody's
+ /* The noise value can be a bit outdated if nobody's
* reading wireless stats... */
wstats.noise = priv->local_iwstatistics.qual.noise;
wstats.qual = wstats.level - wstats.noise;
@@ -464,10 +464,8 @@ islpci_eth_receive(islpci_private *priv)
break;
}
/* update the fragment address */
- control_block->rx_data_low[index].address = cpu_to_le32((u32)
- priv->
- pci_map_rx_address
- [index]);
+ control_block->rx_data_low[index].address =
+ cpu_to_le32((u32)priv->pci_map_rx_address[index]);
wmb();
/* increment the driver read pointer */
@@ -485,9 +483,11 @@ void
islpci_do_reset_and_wake(struct work_struct *work)
{
islpci_private *priv = container_of(work, islpci_private, reset_task);
+
islpci_reset(priv, 1);
- netif_wake_queue(priv->ndev);
priv->reset_task_pending = 0;
+ smp_wmb();
+ netif_wake_queue(priv->ndev);
}
void
@@ -499,12 +499,14 @@ islpci_eth_tx_timeout(struct net_device *ndev)
/* increment the transmit error counter */
statistics->tx_errors++;
- printk(KERN_WARNING "%s: tx_timeout", ndev->name);
if (!priv->reset_task_pending) {
- priv->reset_task_pending = 1;
- printk(", scheduling a reset");
+ printk(KERN_WARNING
+ "%s: tx_timeout, scheduling reset", ndev->name);
netif_stop_queue(ndev);
+ priv->reset_task_pending = 1;
schedule_work(&priv->reset_task);
+ } else {
+ printk(KERN_WARNING
+ "%s: tx_timeout, waiting for reset", ndev->name);
}
- printk("\n");
}
diff --git a/drivers/net/wireless/prism54/islpci_eth.h b/drivers/net/wireless/prism54/islpci_eth.h
index 99d37eda9f01..5bf820defbd0 100644
--- a/drivers/net/wireless/prism54/islpci_eth.h
+++ b/drivers/net/wireless/prism54/islpci_eth.h
@@ -1,5 +1,4 @@
/*
- *
* Copyright (C) 2002 Intersil Americas Inc.
*
* This program is free software; you can redistribute it and/or modify
diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c
index f692dccf0d07..58257b40c043 100644
--- a/drivers/net/wireless/prism54/islpci_hotplug.c
+++ b/drivers/net/wireless/prism54/islpci_hotplug.c
@@ -1,5 +1,4 @@
/*
- *
* Copyright (C) 2002 Intersil Americas Inc.
* Copyright (C) 2003 Herbert Valerio Riedel <hvr@gnu.org>
*
@@ -40,8 +39,8 @@ static int init_pcitm = 0;
module_param(init_pcitm, int, 0);
/* In this order: vendor, device, subvendor, subdevice, class, class_mask,
- * driver_data
- * If you have an update for this please contact prism54-devel@prism54.org
+ * driver_data
+ * If you have an update for this please contact prism54-devel@prism54.org
* The latest list can be found at http://prism54.org/supported_cards.php */
static const struct pci_device_id prism54_id_tbl[] = {
/* Intersil PRISM Duette/Prism GT Wireless LAN adapter */
@@ -132,15 +131,15 @@ prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* 0x40 is the programmable timer to configure the response timeout (TRDY_TIMEOUT)
* 0x41 is the programmable timer to configure the retry timeout (RETRY_TIMEOUT)
- * The RETRY_TIMEOUT is used to set the number of retries that the core, as a
- * Master, will perform before abandoning a cycle. The default value for
- * RETRY_TIMEOUT is 0x80, which far exceeds the PCI 2.1 requirement for new
- * devices. A write of zero to the RETRY_TIMEOUT register disables this
- * function to allow use with any non-compliant legacy devices that may
- * execute more retries.
+ * The RETRY_TIMEOUT is used to set the number of retries that the core, as a
+ * Master, will perform before abandoning a cycle. The default value for
+ * RETRY_TIMEOUT is 0x80, which far exceeds the PCI 2.1 requirement for new
+ * devices. A write of zero to the RETRY_TIMEOUT register disables this
+ * function to allow use with any non-compliant legacy devices that may
+ * execute more retries.
*
- * Writing zero to both these two registers will disable both timeouts and
- * *can* solve problems caused by devices that are slow to respond.
+ * Writing zero to both these two registers will disable both timeouts and
+ * *can* solve problems caused by devices that are slow to respond.
* Make this configurable - MSW
*/
if ( init_pcitm >= 0 ) {
@@ -171,14 +170,15 @@ prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id)
pci_set_master(pdev);
/* enable MWI */
- pci_set_mwi(pdev);
+ if (!pci_set_mwi(pdev))
+ printk(KERN_INFO "%s: pci_set_mwi(pdev) succeeded\n", DRV_NAME);
/* setup the network device interface and its structure */
if (!(ndev = islpci_setup(pdev))) {
/* error configuring the driver as a network device */
printk(KERN_ERR "%s: could not configure network device\n",
DRV_NAME);
- goto do_pci_release_regions;
+ goto do_pci_clear_mwi;
}
priv = netdev_priv(ndev);
@@ -208,6 +208,8 @@ prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id)
pci_set_drvdata(pdev, NULL);
free_netdev(ndev);
priv = NULL;
+ do_pci_clear_mwi:
+ pci_clear_mwi(pdev);
do_pci_release_regions:
pci_release_regions(pdev);
do_pci_disable_device:
@@ -241,7 +243,7 @@ prism54_remove(struct pci_dev *pdev)
isl38xx_disable_interrupts(priv->device_base);
islpci_set_state(priv, PRV_STATE_OFF);
/* This bellow causes a lockup at rmmod time. It might be
- * because some interrupts still linger after rmmod time,
+ * because some interrupts still linger after rmmod time,
* see bug #17 */
/* pci_set_power_state(pdev, 3);*/ /* try to power-off */
}
@@ -255,6 +257,8 @@ prism54_remove(struct pci_dev *pdev)
free_netdev(ndev);
priv = NULL;
+ pci_clear_mwi(pdev);
+
pci_release_regions(pdev);
pci_disable_device(pdev);
@@ -288,12 +292,19 @@ prism54_resume(struct pci_dev *pdev)
{
struct net_device *ndev = pci_get_drvdata(pdev);
islpci_private *priv = ndev ? netdev_priv(ndev) : NULL;
- BUG_ON(!priv);
+ int err;
- pci_enable_device(pdev);
+ BUG_ON(!priv);
printk(KERN_NOTICE "%s: got resume request\n", ndev->name);
+ err = pci_enable_device(pdev);
+ if (err) {
+ printk(KERN_ERR "%s: pci_enable_device failed on resume\n",
+ ndev->name);
+ return err;
+ }
+
pci_restore_state(pdev);
/* alright let's go into the PREBOOT state */
diff --git a/drivers/net/wireless/prism54/islpci_mgt.c b/drivers/net/wireless/prism54/islpci_mgt.c
index 656ec9fa7128..2246f7930b4e 100644
--- a/drivers/net/wireless/prism54/islpci_mgt.c
+++ b/drivers/net/wireless/prism54/islpci_mgt.c
@@ -1,5 +1,4 @@
/*
- *
* Copyright (C) 2002 Intersil Americas Inc.
* Copyright 2004 Jens Maurer <Jens.Maurer@gmx.net>
*
@@ -502,7 +501,7 @@ islpci_mgt_transaction(struct net_device *ndev,
printk(KERN_WARNING "%s: timeout waiting for mgmt response\n",
ndev->name);
- /* TODO: we should reset the device here */
+ /* TODO: we should reset the device here */
out:
finish_wait(&priv->mgmt_wqueue, &wait);
up(&priv->mgmt_sem);
diff --git a/drivers/net/wireless/prism54/islpci_mgt.h b/drivers/net/wireless/prism54/islpci_mgt.h
index 2982be3363ef..fc53b587b722 100644
--- a/drivers/net/wireless/prism54/islpci_mgt.h
+++ b/drivers/net/wireless/prism54/islpci_mgt.h
@@ -1,5 +1,4 @@
/*
- *
* Copyright (C) 2002 Intersil Americas Inc.
* Copyright (C) 2003 Luis R. Rodriguez <mcgrof@ruslug.rutgers.edu>
*
@@ -36,8 +35,8 @@ extern int pc_debug;
/* General driver definitions */
-#define PCIDEVICE_LATENCY_TIMER_MIN 0x40
-#define PCIDEVICE_LATENCY_TIMER_VAL 0x50
+#define PCIDEVICE_LATENCY_TIMER_MIN 0x40
+#define PCIDEVICE_LATENCY_TIMER_VAL 0x50
/* Debugging verbose definitions */
#define SHOW_NOTHING 0x00 /* overrules everything */
diff --git a/drivers/net/wireless/prism54/oid_mgt.c b/drivers/net/wireless/prism54/oid_mgt.c
index ebb238785839..fbc52b6a3024 100644
--- a/drivers/net/wireless/prism54/oid_mgt.c
+++ b/drivers/net/wireless/prism54/oid_mgt.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2003,2004 Aurelien Alleaume <slts@free.fr>
*
* This program is free software; you can redistribute it and/or modify
@@ -503,7 +503,7 @@ mgt_set_varlen(islpci_private *priv, enum oid_num_t n, void *data, int extra_len
}
if (ret || response_op == PIMFOR_OP_ERROR)
ret = -EIO;
- } else
+ } else
ret = -EIO;
/* re-set given data to what it was */
@@ -727,7 +727,7 @@ mgt_commit(islpci_private *priv)
* MEDIUMLIMIT,BEACONPERIOD,DTIMPERIOD,ATIMWINDOW,LISTENINTERVAL
* FREQUENCY,EXTENDEDRATES.
*
- * The way to do this is to set ESSID. Note though that they may get
+ * The way to do this is to set ESSID. Note though that they may get
* unlatch before though by setting another OID. */
#if 0
void
diff --git a/drivers/net/wireless/prism54/prismcompat.h b/drivers/net/wireless/prism54/prismcompat.h
index d71eca55a302..aa1d1747784f 100644
--- a/drivers/net/wireless/prism54/prismcompat.h
+++ b/drivers/net/wireless/prism54/prismcompat.h
@@ -1,4 +1,4 @@
-/*
+/*
* (C) 2004 Margit Schubert-While <margitsw@t-online.de>
*
* This program is free software; you can redistribute it and/or modify
@@ -16,7 +16,7 @@
*
*/
-/*
+/*
* Compatibility header file to aid support of different kernel versions
*/
diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c
index 36b29ff05814..6cb66a356c96 100644
--- a/drivers/net/wireless/zd1201.c
+++ b/drivers/net/wireless/zd1201.c
@@ -1828,10 +1828,8 @@ err_start:
/* Leave the device in reset state */
zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0);
err_zd:
- if (zd->tx_urb)
- usb_free_urb(zd->tx_urb);
- if (zd->rx_urb)
- usb_free_urb(zd->rx_urb);
+ usb_free_urb(zd->tx_urb);
+ usb_free_urb(zd->rx_urb);
kfree(zd);
return err;
}
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index aa661b2b76c7..8be99ebbe1cd 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -1076,6 +1076,31 @@ static int set_mandatory_rates(struct zd_chip *chip, enum ieee80211_std std)
return zd_iowrite32_locked(chip, rates, CR_MANDATORY_RATE_TBL);
}
+int zd_chip_set_rts_cts_rate_locked(struct zd_chip *chip,
+ u8 rts_rate, int preamble)
+{
+ int rts_mod = ZD_RX_CCK;
+ u32 value = 0;
+
+ /* Modulation bit */
+ if (ZD_CS_TYPE(rts_rate) == ZD_CS_OFDM)
+ rts_mod = ZD_RX_OFDM;
+
+ dev_dbg_f(zd_chip_dev(chip), "rts_rate=%x preamble=%x\n",
+ rts_rate, preamble);
+
+ value |= rts_rate << RTSCTS_SH_RTS_RATE;
+ value |= rts_mod << RTSCTS_SH_RTS_MOD_TYPE;
+ value |= preamble << RTSCTS_SH_RTS_PMB_TYPE;
+ value |= preamble << RTSCTS_SH_CTS_PMB_TYPE;
+
+ /* We always send 11M self-CTS messages, like the vendor driver. */
+ value |= ZD_CCK_RATE_11M << RTSCTS_SH_CTS_RATE;
+ value |= ZD_RX_CCK << RTSCTS_SH_CTS_MOD_TYPE;
+
+ return zd_iowrite32_locked(chip, value, CR_RTS_CTS_RATE);
+}
+
int zd_chip_enable_hwint(struct zd_chip *chip)
{
int r;
@@ -1355,17 +1380,12 @@ out:
return r;
}
-int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates)
+int zd_chip_set_basic_rates_locked(struct zd_chip *chip, u16 cr_rates)
{
- int r;
-
- if (cr_rates & ~(CR_RATES_80211B|CR_RATES_80211G))
- return -EINVAL;
+ ZD_ASSERT((cr_rates & ~(CR_RATES_80211B | CR_RATES_80211G)) == 0);
+ dev_dbg_f(zd_chip_dev(chip), "%x\n", cr_rates);
- mutex_lock(&chip->mutex);
- r = zd_iowrite32_locked(chip, cr_rates, CR_BASIC_RATE_TBL);
- mutex_unlock(&chip->mutex);
- return r;
+ return zd_iowrite32_locked(chip, cr_rates, CR_BASIC_RATE_TBL);
}
static int ofdm_qual_db(u8 status_quality, u8 rate, unsigned int size)
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
index ae59597ce4e1..ca892b9a6448 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.h
+++ b/drivers/net/wireless/zd1211rw/zd_chip.h
@@ -337,24 +337,24 @@
#define CR_MAC_PS_STATE CTL_REG(0x050C)
#define CR_INTERRUPT CTL_REG(0x0510)
-#define INT_TX_COMPLETE 0x00000001
-#define INT_RX_COMPLETE 0x00000002
-#define INT_RETRY_FAIL 0x00000004
-#define INT_WAKEUP 0x00000008
-#define INT_DTIM_NOTIFY 0x00000020
-#define INT_CFG_NEXT_BCN 0x00000040
-#define INT_BUS_ABORT 0x00000080
-#define INT_TX_FIFO_READY 0x00000100
-#define INT_UART 0x00000200
-#define INT_TX_COMPLETE_EN 0x00010000
-#define INT_RX_COMPLETE_EN 0x00020000
-#define INT_RETRY_FAIL_EN 0x00040000
-#define INT_WAKEUP_EN 0x00080000
-#define INT_DTIM_NOTIFY_EN 0x00200000
-#define INT_CFG_NEXT_BCN_EN 0x00400000
-#define INT_BUS_ABORT_EN 0x00800000
-#define INT_TX_FIFO_READY_EN 0x01000000
-#define INT_UART_EN 0x02000000
+#define INT_TX_COMPLETE (1 << 0)
+#define INT_RX_COMPLETE (1 << 1)
+#define INT_RETRY_FAIL (1 << 2)
+#define INT_WAKEUP (1 << 3)
+#define INT_DTIM_NOTIFY (1 << 5)
+#define INT_CFG_NEXT_BCN (1 << 6)
+#define INT_BUS_ABORT (1 << 7)
+#define INT_TX_FIFO_READY (1 << 8)
+#define INT_UART (1 << 9)
+#define INT_TX_COMPLETE_EN (1 << 16)
+#define INT_RX_COMPLETE_EN (1 << 17)
+#define INT_RETRY_FAIL_EN (1 << 18)
+#define INT_WAKEUP_EN (1 << 19)
+#define INT_DTIM_NOTIFY_EN (1 << 21)
+#define INT_CFG_NEXT_BCN_EN (1 << 22)
+#define INT_BUS_ABORT_EN (1 << 23)
+#define INT_TX_FIFO_READY_EN (1 << 24)
+#define INT_UART_EN (1 << 25)
#define CR_TSF_LOW_PART CTL_REG(0x0514)
#define CR_TSF_HIGH_PART CTL_REG(0x0518)
@@ -398,18 +398,18 @@
* device will use a rate in this table that is less than or equal to the rate
* of the incoming frame which prompted the response */
#define CR_BASIC_RATE_TBL CTL_REG(0x0630)
-#define CR_RATE_1M 0x0001 /* 802.11b */
-#define CR_RATE_2M 0x0002 /* 802.11b */
-#define CR_RATE_5_5M 0x0004 /* 802.11b */
-#define CR_RATE_11M 0x0008 /* 802.11b */
-#define CR_RATE_6M 0x0100 /* 802.11g */
-#define CR_RATE_9M 0x0200 /* 802.11g */
-#define CR_RATE_12M 0x0400 /* 802.11g */
-#define CR_RATE_18M 0x0800 /* 802.11g */
-#define CR_RATE_24M 0x1000 /* 802.11g */
-#define CR_RATE_36M 0x2000 /* 802.11g */
-#define CR_RATE_48M 0x4000 /* 802.11g */
-#define CR_RATE_54M 0x8000 /* 802.11g */
+#define CR_RATE_1M (1 << 0) /* 802.11b */
+#define CR_RATE_2M (1 << 1) /* 802.11b */
+#define CR_RATE_5_5M (1 << 2) /* 802.11b */
+#define CR_RATE_11M (1 << 3) /* 802.11b */
+#define CR_RATE_6M (1 << 8) /* 802.11g */
+#define CR_RATE_9M (1 << 9) /* 802.11g */
+#define CR_RATE_12M (1 << 10) /* 802.11g */
+#define CR_RATE_18M (1 << 11) /* 802.11g */
+#define CR_RATE_24M (1 << 12) /* 802.11g */
+#define CR_RATE_36M (1 << 13) /* 802.11g */
+#define CR_RATE_48M (1 << 14) /* 802.11g */
+#define CR_RATE_54M (1 << 15) /* 802.11g */
#define CR_RATES_80211G 0xff00
#define CR_RATES_80211B 0x000f
@@ -420,15 +420,24 @@
#define CR_MANDATORY_RATE_TBL CTL_REG(0x0634)
#define CR_RTS_CTS_RATE CTL_REG(0x0638)
+/* These are all bit indexes in CR_RTS_CTS_RATE, so remember to shift. */
+#define RTSCTS_SH_RTS_RATE 0
+#define RTSCTS_SH_EXP_CTS_RATE 4
+#define RTSCTS_SH_RTS_MOD_TYPE 8
+#define RTSCTS_SH_RTS_PMB_TYPE 9
+#define RTSCTS_SH_CTS_RATE 16
+#define RTSCTS_SH_CTS_MOD_TYPE 24
+#define RTSCTS_SH_CTS_PMB_TYPE 25
+
#define CR_WEP_PROTECT CTL_REG(0x063C)
#define CR_RX_THRESHOLD CTL_REG(0x0640)
/* register for controlling the LEDS */
#define CR_LED CTL_REG(0x0644)
/* masks for controlling LEDs */
-#define LED1 0x0100
-#define LED2 0x0200
-#define LED_SW 0x0400
+#define LED1 (1 << 8)
+#define LED2 (1 << 9)
+#define LED_SW (1 << 10)
/* Seems to indicate that the configuration is over.
*/
@@ -455,18 +464,18 @@
* registers, so one could argue it is a LOCK bit. But calling it
* LOCK_PHY_REGS makes it confusing.
*/
-#define UNLOCK_PHY_REGS 0x0080
+#define UNLOCK_PHY_REGS (1 << 7)
#define CR_DEVICE_STATE CTL_REG(0x0684)
#define CR_UNDERRUN_CNT CTL_REG(0x0688)
#define CR_RX_FILTER CTL_REG(0x068c)
-#define RX_FILTER_ASSOC_RESPONSE 0x0002
-#define RX_FILTER_REASSOC_RESPONSE 0x0008
-#define RX_FILTER_PROBE_RESPONSE 0x0020
-#define RX_FILTER_BEACON 0x0100
-#define RX_FILTER_DISASSOC 0x0400
-#define RX_FILTER_AUTH 0x0800
+#define RX_FILTER_ASSOC_RESPONSE (1 << 1)
+#define RX_FILTER_REASSOC_RESPONSE (1 << 3)
+#define RX_FILTER_PROBE_RESPONSE (1 << 5)
+#define RX_FILTER_BEACON (1 << 8)
+#define RX_FILTER_DISASSOC (1 << 10)
+#define RX_FILTER_AUTH (1 << 11)
#define AP_RX_FILTER 0x0400feff
#define STA_RX_FILTER 0x0000ffff
@@ -794,6 +803,9 @@ void zd_chip_disable_rx(struct zd_chip *chip);
int zd_chip_enable_hwint(struct zd_chip *chip);
int zd_chip_disable_hwint(struct zd_chip *chip);
+int zd_chip_set_rts_cts_rate_locked(struct zd_chip *chip,
+ u8 rts_rate, int preamble);
+
static inline int zd_get_encryption_type(struct zd_chip *chip, u32 *type)
{
return zd_ioread32(chip, CR_ENCRYPTION_TYPE, type);
@@ -809,7 +821,17 @@ static inline int zd_chip_get_basic_rates(struct zd_chip *chip, u16 *cr_rates)
return zd_ioread16(chip, CR_BASIC_RATE_TBL, cr_rates);
}
-int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates);
+int zd_chip_set_basic_rates_locked(struct zd_chip *chip, u16 cr_rates);
+
+static inline int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates)
+{
+ int r;
+
+ mutex_lock(&chip->mutex);
+ r = zd_chip_set_basic_rates_locked(chip, cr_rates);
+ mutex_unlock(&chip->mutex);
+ return r;
+}
static inline int zd_chip_set_rx_filter(struct zd_chip *chip, u32 filter)
{
diff --git a/drivers/net/wireless/zd1211rw/zd_def.h b/drivers/net/wireless/zd1211rw/zd_def.h
index a13ec72eb304..fb22f62cf1f3 100644
--- a/drivers/net/wireless/zd1211rw/zd_def.h
+++ b/drivers/net/wireless/zd1211rw/zd_def.h
@@ -39,6 +39,7 @@ do { \
if (!(x)) { \
pr_debug("%s:%d ASSERT %s VIOLATED!\n", \
__FILE__, __LINE__, __stringify(x)); \
+ dump_stack(); \
} \
} while (0)
#else
diff --git a/drivers/net/wireless/zd1211rw/zd_ieee80211.c b/drivers/net/wireless/zd1211rw/zd_ieee80211.c
index 66905f7b61ff..189160efd2ae 100644
--- a/drivers/net/wireless/zd1211rw/zd_ieee80211.c
+++ b/drivers/net/wireless/zd1211rw/zd_ieee80211.c
@@ -37,7 +37,12 @@ static const struct channel_range channel_ranges[] = {
[ZD_REGDOMAIN_JAPAN] = { 1, 14},
[ZD_REGDOMAIN_SPAIN] = { 1, 14},
[ZD_REGDOMAIN_FRANCE] = { 1, 14},
- [ZD_REGDOMAIN_JAPAN_ADD] = {14, 15},
+
+ /* Japan originally only had channel 14 available (see CHNL_ID 0x40 in
+ * 802.11). However, in 2001 the range was extended to include channels
+ * 1-13. The ZyDAS devices still use the old region code but are
+ * designed to allow the extra channel access in Japan. */
+ [ZD_REGDOMAIN_JAPAN_ADD] = { 1, 15},
};
const struct channel_range *zd_channel_range(u8 regdomain)
@@ -133,9 +138,6 @@ int zd_find_channel(u8 *channel, const struct iw_freq *freq)
int i, r;
u32 mhz;
- if (!(freq->flags & IW_FREQ_FIXED))
- return 0;
-
if (freq->m < 1000) {
if (freq->m > NUM_CHANNELS || freq->m == 0)
return -EINVAL;
diff --git a/drivers/net/wireless/zd1211rw/zd_ieee80211.h b/drivers/net/wireless/zd1211rw/zd_ieee80211.h
index f63245b0d966..26b8298dff8c 100644
--- a/drivers/net/wireless/zd1211rw/zd_ieee80211.h
+++ b/drivers/net/wireless/zd1211rw/zd_ieee80211.h
@@ -50,6 +50,7 @@ static inline u8 zd_ofdm_plcp_header_rate(
return header->prefix[0] & 0xf;
}
+/* These are referred to as zd_rates */
#define ZD_OFDM_RATE_6M 0xb
#define ZD_OFDM_RATE_9M 0xf
#define ZD_OFDM_RATE_12M 0xa
@@ -64,7 +65,7 @@ struct cck_plcp_header {
u8 service;
__le16 length;
__le16 crc16;
-};
+} __attribute__((packed));
static inline u8 zd_cck_plcp_header_rate(const struct cck_plcp_header *header)
{
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 5e4f4b707375..44f3cfd4cc1d 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -32,6 +32,8 @@
static void ieee_init(struct ieee80211_device *ieee);
static void softmac_init(struct ieee80211softmac_device *sm);
+static void set_rts_cts_work(void *d);
+static void set_basic_rates_work(void *d);
static void housekeeping_init(struct zd_mac *mac);
static void housekeeping_enable(struct zd_mac *mac);
@@ -46,6 +48,8 @@ int zd_mac_init(struct zd_mac *mac,
memset(mac, 0, sizeof(*mac));
spin_lock_init(&mac->lock);
mac->netdev = netdev;
+ INIT_WORK(&mac->set_rts_cts_work, set_rts_cts_work, mac);
+ INIT_WORK(&mac->set_basic_rates_work, set_basic_rates_work, mac);
ieee_init(ieee);
softmac_init(ieee80211_priv(netdev));
@@ -213,6 +217,13 @@ int zd_mac_stop(struct net_device *netdev)
housekeeping_disable(mac);
ieee80211softmac_stop(netdev);
+ /* Ensure no work items are running or queued from this point */
+ cancel_delayed_work(&mac->set_rts_cts_work);
+ cancel_delayed_work(&mac->set_basic_rates_work);
+ flush_workqueue(zd_workqueue);
+ mac->updating_rts_rate = 0;
+ mac->updating_basic_rates = 0;
+
zd_chip_disable_hwint(chip);
zd_chip_switch_radio_off(chip);
zd_chip_disable_int(chip);
@@ -286,6 +297,186 @@ u8 zd_mac_get_regdomain(struct zd_mac *mac)
return regdomain;
}
+/* Fallback to lowest rate, if rate is unknown. */
+static u8 rate_to_zd_rate(u8 rate)
+{
+ switch (rate) {
+ case IEEE80211_CCK_RATE_2MB:
+ return ZD_CCK_RATE_2M;
+ case IEEE80211_CCK_RATE_5MB:
+ return ZD_CCK_RATE_5_5M;
+ case IEEE80211_CCK_RATE_11MB:
+ return ZD_CCK_RATE_11M;
+ case IEEE80211_OFDM_RATE_6MB:
+ return ZD_OFDM_RATE_6M;
+ case IEEE80211_OFDM_RATE_9MB:
+ return ZD_OFDM_RATE_9M;
+ case IEEE80211_OFDM_RATE_12MB:
+ return ZD_OFDM_RATE_12M;
+ case IEEE80211_OFDM_RATE_18MB:
+ return ZD_OFDM_RATE_18M;
+ case IEEE80211_OFDM_RATE_24MB:
+ return ZD_OFDM_RATE_24M;
+ case IEEE80211_OFDM_RATE_36MB:
+ return ZD_OFDM_RATE_36M;
+ case IEEE80211_OFDM_RATE_48MB:
+ return ZD_OFDM_RATE_48M;
+ case IEEE80211_OFDM_RATE_54MB:
+ return ZD_OFDM_RATE_54M;
+ }
+ return ZD_CCK_RATE_1M;
+}
+
+static u16 rate_to_cr_rate(u8 rate)
+{
+ switch (rate) {
+ case IEEE80211_CCK_RATE_2MB:
+ return CR_RATE_1M;
+ case IEEE80211_CCK_RATE_5MB:
+ return CR_RATE_5_5M;
+ case IEEE80211_CCK_RATE_11MB:
+ return CR_RATE_11M;
+ case IEEE80211_OFDM_RATE_6MB:
+ return CR_RATE_6M;
+ case IEEE80211_OFDM_RATE_9MB:
+ return CR_RATE_9M;
+ case IEEE80211_OFDM_RATE_12MB:
+ return CR_RATE_12M;
+ case IEEE80211_OFDM_RATE_18MB:
+ return CR_RATE_18M;
+ case IEEE80211_OFDM_RATE_24MB:
+ return CR_RATE_24M;
+ case IEEE80211_OFDM_RATE_36MB:
+ return CR_RATE_36M;
+ case IEEE80211_OFDM_RATE_48MB:
+ return CR_RATE_48M;
+ case IEEE80211_OFDM_RATE_54MB:
+ return CR_RATE_54M;
+ }
+ return CR_RATE_1M;
+}
+
+static void try_enable_tx(struct zd_mac *mac)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&mac->lock, flags);
+ if (mac->updating_rts_rate == 0 && mac->updating_basic_rates == 0)
+ netif_wake_queue(mac->netdev);
+ spin_unlock_irqrestore(&mac->lock, flags);
+}
+
+static void set_rts_cts_work(void *d)
+{
+ struct zd_mac *mac = d;
+ unsigned long flags;
+ u8 rts_rate;
+ unsigned int short_preamble;
+
+ mutex_lock(&mac->chip.mutex);
+
+ spin_lock_irqsave(&mac->lock, flags);
+ mac->updating_rts_rate = 0;
+ rts_rate = mac->rts_rate;
+ short_preamble = mac->short_preamble;
+ spin_unlock_irqrestore(&mac->lock, flags);
+
+ zd_chip_set_rts_cts_rate_locked(&mac->chip, rts_rate, short_preamble);
+ mutex_unlock(&mac->chip.mutex);
+
+ try_enable_tx(mac);
+}
+
+static void set_basic_rates_work(void *d)
+{
+ struct zd_mac *mac = d;
+ unsigned long flags;
+ u16 basic_rates;
+
+ mutex_lock(&mac->chip.mutex);
+
+ spin_lock_irqsave(&mac->lock, flags);
+ mac->updating_basic_rates = 0;
+ basic_rates = mac->basic_rates;
+ spin_unlock_irqrestore(&mac->lock, flags);
+
+ zd_chip_set_basic_rates_locked(&mac->chip, basic_rates);
+ mutex_unlock(&mac->chip.mutex);
+
+ try_enable_tx(mac);
+}
+
+static void bssinfo_change(struct net_device *netdev, u32 changes)
+{
+ struct zd_mac *mac = zd_netdev_mac(netdev);
+ struct ieee80211softmac_device *softmac = ieee80211_priv(netdev);
+ struct ieee80211softmac_bss_info *bssinfo = &softmac->bssinfo;
+ int need_set_rts_cts = 0;
+ int need_set_rates = 0;
+ u16 basic_rates;
+ unsigned long flags;
+
+ dev_dbg_f(zd_mac_dev(mac), "changes: %x\n", changes);
+
+ if (changes & IEEE80211SOFTMAC_BSSINFOCHG_SHORT_PREAMBLE) {
+ spin_lock_irqsave(&mac->lock, flags);
+ mac->short_preamble = bssinfo->short_preamble;
+ spin_unlock_irqrestore(&mac->lock, flags);
+ need_set_rts_cts = 1;
+ }
+
+ if (changes & IEEE80211SOFTMAC_BSSINFOCHG_RATES) {
+ /* Set RTS rate to highest available basic rate */
+ u8 rate = ieee80211softmac_highest_supported_rate(softmac,
+ &bssinfo->supported_rates, 1);
+ rate = rate_to_zd_rate(rate);
+
+ spin_lock_irqsave(&mac->lock, flags);
+ if (rate != mac->rts_rate) {
+ mac->rts_rate = rate;
+ need_set_rts_cts = 1;
+ }
+ spin_unlock_irqrestore(&mac->lock, flags);
+
+ /* Set basic rates */
+ need_set_rates = 1;
+ if (bssinfo->supported_rates.count == 0) {
+ /* Allow the device to be flexible */
+ basic_rates = CR_RATES_80211B | CR_RATES_80211G;
+ } else {
+ int i = 0;
+ basic_rates = 0;
+
+ for (i = 0; i < bssinfo->supported_rates.count; i++) {
+ u16 rate = bssinfo->supported_rates.rates[i];
+ if ((rate & IEEE80211_BASIC_RATE_MASK) == 0)
+ continue;
+
+ rate &= ~IEEE80211_BASIC_RATE_MASK;
+ basic_rates |= rate_to_cr_rate(rate);
+ }
+ }
+ spin_lock_irqsave(&mac->lock, flags);
+ mac->basic_rates = basic_rates;
+ spin_unlock_irqrestore(&mac->lock, flags);
+ }
+
+ /* Schedule any changes we made above */
+
+ spin_lock_irqsave(&mac->lock, flags);
+ if (need_set_rts_cts && !mac->updating_rts_rate) {
+ mac->updating_rts_rate = 1;
+ netif_stop_queue(mac->netdev);
+ queue_work(zd_workqueue, &mac->set_rts_cts_work);
+ }
+ if (need_set_rates && !mac->updating_basic_rates) {
+ mac->updating_basic_rates = 1;
+ netif_stop_queue(mac->netdev);
+ queue_work(zd_workqueue, &mac->set_basic_rates_work);
+ }
+ spin_unlock_irqrestore(&mac->lock, flags);
+}
+
static void set_channel(struct net_device *netdev, u8 channel)
{
struct zd_mac *mac = zd_netdev_mac(netdev);
@@ -295,7 +486,6 @@ static void set_channel(struct net_device *netdev, u8 channel)
zd_chip_set_channel(&mac->chip, channel);
}
-/* TODO: Should not work in Managed mode. */
int zd_mac_request_channel(struct zd_mac *mac, u8 channel)
{
unsigned long lock_flags;
@@ -317,31 +507,22 @@ int zd_mac_request_channel(struct zd_mac *mac, u8 channel)
return 0;
}
-int zd_mac_get_channel(struct zd_mac *mac, u8 *channel, u8 *flags)
+u8 zd_mac_get_channel(struct zd_mac *mac)
{
- struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
+ u8 channel = zd_chip_get_channel(&mac->chip);
- *channel = zd_chip_get_channel(&mac->chip);
- if (ieee->iw_mode != IW_MODE_INFRA) {
- spin_lock_irq(&mac->lock);
- *flags = *channel == mac->requested_channel ?
- MAC_FIXED_CHANNEL : 0;
- spin_unlock(&mac->lock);
- } else {
- *flags = 0;
- }
- dev_dbg_f(zd_mac_dev(mac), "channel %u flags %u\n", *channel, *flags);
- return 0;
+ dev_dbg_f(zd_mac_dev(mac), "channel %u\n", channel);
+ return channel;
}
/* If wrong rate is given, we are falling back to the slowest rate: 1MBit/s */
-static u8 cs_typed_rate(u8 cs_rate)
+static u8 zd_rate_typed(u8 zd_rate)
{
static const u8 typed_rates[16] = {
- [ZD_CS_CCK_RATE_1M] = ZD_CS_CCK|ZD_CS_CCK_RATE_1M,
- [ZD_CS_CCK_RATE_2M] = ZD_CS_CCK|ZD_CS_CCK_RATE_2M,
- [ZD_CS_CCK_RATE_5_5M] = ZD_CS_CCK|ZD_CS_CCK_RATE_5_5M,
- [ZD_CS_CCK_RATE_11M] = ZD_CS_CCK|ZD_CS_CCK_RATE_11M,
+ [ZD_CCK_RATE_1M] = ZD_CS_CCK|ZD_CCK_RATE_1M,
+ [ZD_CCK_RATE_2M] = ZD_CS_CCK|ZD_CCK_RATE_2M,
+ [ZD_CCK_RATE_5_5M] = ZD_CS_CCK|ZD_CCK_RATE_5_5M,
+ [ZD_CCK_RATE_11M] = ZD_CS_CCK|ZD_CCK_RATE_11M,
[ZD_OFDM_RATE_6M] = ZD_CS_OFDM|ZD_OFDM_RATE_6M,
[ZD_OFDM_RATE_9M] = ZD_CS_OFDM|ZD_OFDM_RATE_9M,
[ZD_OFDM_RATE_12M] = ZD_CS_OFDM|ZD_OFDM_RATE_12M,
@@ -353,37 +534,7 @@ static u8 cs_typed_rate(u8 cs_rate)
};
ZD_ASSERT(ZD_CS_RATE_MASK == 0x0f);
- return typed_rates[cs_rate & ZD_CS_RATE_MASK];
-}
-
-/* Fallback to lowest rate, if rate is unknown. */
-static u8 rate_to_cs_rate(u8 rate)
-{
- switch (rate) {
- case IEEE80211_CCK_RATE_2MB:
- return ZD_CS_CCK_RATE_2M;
- case IEEE80211_CCK_RATE_5MB:
- return ZD_CS_CCK_RATE_5_5M;
- case IEEE80211_CCK_RATE_11MB:
- return ZD_CS_CCK_RATE_11M;
- case IEEE80211_OFDM_RATE_6MB:
- return ZD_OFDM_RATE_6M;
- case IEEE80211_OFDM_RATE_9MB:
- return ZD_OFDM_RATE_9M;
- case IEEE80211_OFDM_RATE_12MB:
- return ZD_OFDM_RATE_12M;
- case IEEE80211_OFDM_RATE_18MB:
- return ZD_OFDM_RATE_18M;
- case IEEE80211_OFDM_RATE_24MB:
- return ZD_OFDM_RATE_24M;
- case IEEE80211_OFDM_RATE_36MB:
- return ZD_OFDM_RATE_36M;
- case IEEE80211_OFDM_RATE_48MB:
- return ZD_OFDM_RATE_48M;
- case IEEE80211_OFDM_RATE_54MB:
- return ZD_OFDM_RATE_54M;
- }
- return ZD_CS_CCK_RATE_1M;
+ return typed_rates[zd_rate & ZD_CS_RATE_MASK];
}
int zd_mac_set_mode(struct zd_mac *mac, u32 mode)
@@ -484,13 +635,13 @@ int zd_mac_get_range(struct zd_mac *mac, struct iw_range *range)
return 0;
}
-static int zd_calc_tx_length_us(u8 *service, u8 cs_rate, u16 tx_length)
+static int zd_calc_tx_length_us(u8 *service, u8 zd_rate, u16 tx_length)
{
static const u8 rate_divisor[] = {
- [ZD_CS_CCK_RATE_1M] = 1,
- [ZD_CS_CCK_RATE_2M] = 2,
- [ZD_CS_CCK_RATE_5_5M] = 11, /* bits must be doubled */
- [ZD_CS_CCK_RATE_11M] = 11,
+ [ZD_CCK_RATE_1M] = 1,
+ [ZD_CCK_RATE_2M] = 2,
+ [ZD_CCK_RATE_5_5M] = 11, /* bits must be doubled */
+ [ZD_CCK_RATE_11M] = 11,
[ZD_OFDM_RATE_6M] = 6,
[ZD_OFDM_RATE_9M] = 9,
[ZD_OFDM_RATE_12M] = 12,
@@ -504,15 +655,15 @@ static int zd_calc_tx_length_us(u8 *service, u8 cs_rate, u16 tx_length)
u32 bits = (u32)tx_length * 8;
u32 divisor;
- divisor = rate_divisor[cs_rate];
+ divisor = rate_divisor[zd_rate];
if (divisor == 0)
return -EINVAL;
- switch (cs_rate) {
- case ZD_CS_CCK_RATE_5_5M:
+ switch (zd_rate) {
+ case ZD_CCK_RATE_5_5M:
bits = (2*bits) + 10; /* round up to the next integer */
break;
- case ZD_CS_CCK_RATE_11M:
+ case ZD_CCK_RATE_11M:
if (service) {
u32 t = bits % 11;
*service &= ~ZD_PLCP_SERVICE_LENGTH_EXTENSION;
@@ -532,16 +683,16 @@ enum {
R2M_11A = 0x02,
};
-static u8 cs_rate_to_modulation(u8 cs_rate, int flags)
+static u8 zd_rate_to_modulation(u8 zd_rate, int flags)
{
u8 modulation;
- modulation = cs_typed_rate(cs_rate);
+ modulation = zd_rate_typed(zd_rate);
if (flags & R2M_SHORT_PREAMBLE) {
switch (ZD_CS_RATE(modulation)) {
- case ZD_CS_CCK_RATE_2M:
- case ZD_CS_CCK_RATE_5_5M:
- case ZD_CS_CCK_RATE_11M:
+ case ZD_CCK_RATE_2M:
+ case ZD_CCK_RATE_5_5M:
+ case ZD_CCK_RATE_11M:
modulation |= ZD_CS_CCK_PREA_SHORT;
return modulation;
}
@@ -558,39 +709,36 @@ static void cs_set_modulation(struct zd_mac *mac, struct zd_ctrlset *cs,
{
struct ieee80211softmac_device *softmac = ieee80211_priv(mac->netdev);
u16 ftype = WLAN_FC_GET_TYPE(le16_to_cpu(hdr->frame_ctl));
- u8 rate, cs_rate;
+ u8 rate, zd_rate;
int is_mgt = (ftype == IEEE80211_FTYPE_MGMT) != 0;
+ int is_multicast = is_multicast_ether_addr(hdr->addr1);
+ int short_preamble = ieee80211softmac_short_preamble_ok(softmac,
+ is_multicast, is_mgt);
+ int flags = 0;
+
+ /* FIXME: 802.11a? */
+ rate = ieee80211softmac_suggest_txrate(softmac, is_multicast, is_mgt);
- /* FIXME: 802.11a? short preamble? */
- rate = ieee80211softmac_suggest_txrate(softmac,
- is_multicast_ether_addr(hdr->addr1), is_mgt);
+ if (short_preamble)
+ flags |= R2M_SHORT_PREAMBLE;
- cs_rate = rate_to_cs_rate(rate);
- cs->modulation = cs_rate_to_modulation(cs_rate, 0);
+ zd_rate = rate_to_zd_rate(rate);
+ cs->modulation = zd_rate_to_modulation(zd_rate, flags);
}
static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,
struct ieee80211_hdr_4addr *header)
{
+ struct ieee80211softmac_device *softmac = ieee80211_priv(mac->netdev);
unsigned int tx_length = le16_to_cpu(cs->tx_length);
u16 fctl = le16_to_cpu(header->frame_ctl);
u16 ftype = WLAN_FC_GET_TYPE(fctl);
u16 stype = WLAN_FC_GET_STYPE(fctl);
/*
- * CONTROL:
- * - start at 0x00
- * - if fragment 0, enable bit 0
+ * CONTROL TODO:
* - if backoff needed, enable bit 0
* - if burst (backoff not needed) disable bit 0
- * - if multicast, enable bit 1
- * - if PS-POLL frame, enable bit 2
- * - if in INDEPENDENT_BSS mode and zd1205_DestPowerSave, then enable
- * bit 4 (FIXME: wtf)
- * - if frag_len > RTS threshold, set bit 5 as long if it isnt
- * multicast or mgt
- * - if bit 5 is set, and we are in OFDM mode, unset bit 5 and set bit
- * 7
*/
cs->control = 0;
@@ -607,17 +755,18 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,
if (stype == IEEE80211_STYPE_PSPOLL)
cs->control |= ZD_CS_PS_POLL_FRAME;
+ /* Unicast data frames over the threshold should have RTS */
if (!is_multicast_ether_addr(header->addr1) &&
- ftype != IEEE80211_FTYPE_MGMT &&
- tx_length > zd_netdev_ieee80211(mac->netdev)->rts)
- {
- /* FIXME: check the logic */
- if (ZD_CS_TYPE(cs->modulation) == ZD_CS_OFDM) {
- /* 802.11g */
- cs->control |= ZD_CS_SELF_CTS;
- } else { /* 802.11b */
- cs->control |= ZD_CS_RTS;
- }
+ ftype != IEEE80211_FTYPE_MGMT &&
+ tx_length > zd_netdev_ieee80211(mac->netdev)->rts)
+ cs->control |= ZD_CS_RTS;
+
+ /* Use CTS-to-self protection if required */
+ if (ZD_CS_TYPE(cs->modulation) == ZD_CS_OFDM &&
+ ieee80211softmac_protection_needed(softmac)) {
+ /* FIXME: avoid sending RTS *and* self-CTS, is that correct? */
+ cs->control &= ~ZD_CS_RTS;
+ cs->control |= ZD_CS_SELF_CTS;
}
/* FIXME: Management frame? */
@@ -721,7 +870,7 @@ struct zd_rt_hdr {
u8 rt_rate;
u16 rt_channel;
u16 rt_chbitmask;
-};
+} __attribute__((packed));
static void fill_rt_header(void *buffer, struct zd_mac *mac,
const struct ieee80211_rx_stats *stats,
@@ -782,9 +931,11 @@ static int is_data_packet_for_us(struct ieee80211_device *ieee,
(netdev->flags & IFF_PROMISC);
}
-/* Filters receiving packets. If it returns 1 send it to ieee80211_rx, if 0
- * return. If an error is detected -EINVAL is returned. ieee80211_rx_mgt() is
- * called here.
+/* Filters received packets. The function returns 1 if the packet should be
+ * forwarded to ieee80211_rx(). If the packet should be ignored the function
+ * returns 0. If an invalid packet is found the function returns -EINVAL.
+ *
+ * The function calls ieee80211_rx_mgt() directly.
*
* It has been based on ieee80211_rx_any.
*/
@@ -810,9 +961,9 @@ static int filter_rx(struct ieee80211_device *ieee,
ieee80211_rx_mgt(ieee, hdr, stats);
return 0;
case IEEE80211_FTYPE_CTL:
- /* Ignore invalid short buffers */
return 0;
case IEEE80211_FTYPE_DATA:
+ /* Ignore invalid short buffers */
if (length < sizeof(struct ieee80211_hdr_3addr))
return -EINVAL;
return is_data_packet_for_us(ieee, hdr);
@@ -993,6 +1144,7 @@ static void ieee_init(struct ieee80211_device *ieee)
static void softmac_init(struct ieee80211softmac_device *sm)
{
sm->set_channel = set_channel;
+ sm->bssinfo_change = bssinfo_change;
}
struct iw_statistics *zd_mac_get_wireless_stats(struct net_device *ndev)
@@ -1028,66 +1180,6 @@ struct iw_statistics *zd_mac_get_wireless_stats(struct net_device *ndev)
return iw_stats;
}
-#ifdef DEBUG
-static const char* decryption_types[] = {
- [ZD_RX_NO_WEP] = "none",
- [ZD_RX_WEP64] = "WEP64",
- [ZD_RX_TKIP] = "TKIP",
- [ZD_RX_AES] = "AES",
- [ZD_RX_WEP128] = "WEP128",
- [ZD_RX_WEP256] = "WEP256",
-};
-
-static const char *decryption_type_string(u8 type)
-{
- const char *s;
-
- if (type < ARRAY_SIZE(decryption_types)) {
- s = decryption_types[type];
- } else {
- s = NULL;
- }
- return s ? s : "unknown";
-}
-
-static int is_ofdm(u8 frame_status)
-{
- return (frame_status & ZD_RX_OFDM);
-}
-
-void zd_dump_rx_status(const struct rx_status *status)
-{
- const char* modulation;
- u8 quality;
-
- if (is_ofdm(status->frame_status)) {
- modulation = "ofdm";
- quality = status->signal_quality_ofdm;
- } else {
- modulation = "cck";
- quality = status->signal_quality_cck;
- }
- pr_debug("rx status %s strength %#04x qual %#04x decryption %s\n",
- modulation, status->signal_strength, quality,
- decryption_type_string(status->decryption_type));
- if (status->frame_status & ZD_RX_ERROR) {
- pr_debug("rx error %s%s%s%s%s%s\n",
- (status->frame_status & ZD_RX_TIMEOUT_ERROR) ?
- "timeout " : "",
- (status->frame_status & ZD_RX_FIFO_OVERRUN_ERROR) ?
- "fifo " : "",
- (status->frame_status & ZD_RX_DECRYPTION_ERROR) ?
- "decryption " : "",
- (status->frame_status & ZD_RX_CRC32_ERROR) ?
- "crc32 " : "",
- (status->frame_status & ZD_RX_NO_ADDR1_MATCH_ERROR) ?
- "addr1 " : "",
- (status->frame_status & ZD_RX_CRC16_ERROR) ?
- "crc16" : "");
- }
-}
-#endif /* DEBUG */
-
#define LINK_LED_WORK_DELAY HZ
static void link_led_handler(struct work_struct *work)
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h
index 7957cac3de25..08d6b8c08e75 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.h
+++ b/drivers/net/wireless/zd1211rw/zd_mac.h
@@ -20,6 +20,7 @@
#include <linux/wireless.h>
#include <linux/kernel.h>
+#include <linux/workqueue.h>
#include <net/ieee80211.h>
#include <net/ieee80211softmac.h>
@@ -48,10 +49,11 @@ struct zd_ctrlset {
#define ZD_CS_CCK 0x00
#define ZD_CS_OFDM 0x10
-#define ZD_CS_CCK_RATE_1M 0x00
-#define ZD_CS_CCK_RATE_2M 0x01
-#define ZD_CS_CCK_RATE_5_5M 0x02
-#define ZD_CS_CCK_RATE_11M 0x03
+/* These are referred to as zd_rates */
+#define ZD_CCK_RATE_1M 0x00
+#define ZD_CCK_RATE_2M 0x01
+#define ZD_CCK_RATE_5_5M 0x02
+#define ZD_CCK_RATE_11M 0x03
/* The rates for OFDM are encoded as in the PLCP header. Use ZD_OFDM_RATE_*.
*/
@@ -82,7 +84,7 @@ struct zd_ctrlset {
struct rx_length_info {
__le16 length[3];
__le16 tag;
-};
+} __attribute__((packed));
#define RX_LENGTH_INFO_TAG 0x697e
@@ -93,7 +95,7 @@ struct rx_status {
u8 signal_quality_ofdm;
u8 decryption_type;
u8 frame_status;
-};
+} __attribute__((packed));
/* rx_status field decryption_type */
#define ZD_RX_NO_WEP 0
@@ -116,10 +118,6 @@ struct rx_status {
#define ZD_RX_CRC16_ERROR 0x40
#define ZD_RX_ERROR 0x80
-enum mac_flags {
- MAC_FIXED_CHANNEL = 0x01,
-};
-
struct housekeeping {
struct delayed_work link_led_work;
};
@@ -130,15 +128,33 @@ struct zd_mac {
struct zd_chip chip;
spinlock_t lock;
struct net_device *netdev;
+
/* Unlocked reading possible */
struct iw_statistics iw_stats;
+
struct housekeeping housekeeping;
+ struct work_struct set_rts_cts_work;
+ struct work_struct set_basic_rates_work;
+
unsigned int stats_count;
u8 qual_buffer[ZD_MAC_STATS_BUFFER_SIZE];
u8 rssi_buffer[ZD_MAC_STATS_BUFFER_SIZE];
u8 regdomain;
u8 default_regdomain;
u8 requested_channel;
+
+ /* A bitpattern of cr_rates */
+ u16 basic_rates;
+
+ /* A zd_rate */
+ u8 rts_rate;
+
+ /* Short preamble (used for RTS/CTS) */
+ unsigned int short_preamble:1;
+
+ /* flags to indicate update in progress */
+ unsigned int updating_rts_rate:1;
+ unsigned int updating_basic_rates:1;
};
static inline struct ieee80211_device *zd_mac_to_ieee80211(struct zd_mac *mac)
@@ -180,7 +196,7 @@ int zd_mac_set_regdomain(struct zd_mac *zd_mac, u8 regdomain);
u8 zd_mac_get_regdomain(struct zd_mac *zd_mac);
int zd_mac_request_channel(struct zd_mac *mac, u8 channel);
-int zd_mac_get_channel(struct zd_mac *mac, u8 *channel, u8 *flags);
+u8 zd_mac_get_channel(struct zd_mac *mac);
int zd_mac_set_mode(struct zd_mac *mac, u32 mode);
int zd_mac_get_mode(struct zd_mac *mac, u32 *mode);
diff --git a/drivers/net/wireless/zd1211rw/zd_netdev.c b/drivers/net/wireless/zd1211rw/zd_netdev.c
index af3a7b36d078..60f1b0f6d45b 100644
--- a/drivers/net/wireless/zd1211rw/zd_netdev.c
+++ b/drivers/net/wireless/zd1211rw/zd_netdev.c
@@ -107,21 +107,10 @@ static int iw_get_freq(struct net_device *netdev,
struct iw_request_info *info,
union iwreq_data *req, char *extra)
{
- int r;
struct zd_mac *mac = zd_netdev_mac(netdev);
struct iw_freq *freq = &req->freq;
- u8 channel;
- u8 flags;
-
- r = zd_mac_get_channel(mac, &channel, &flags);
- if (r)
- return r;
- freq->flags = (flags & MAC_FIXED_CHANNEL) ?
- IW_FREQ_FIXED : IW_FREQ_AUTO;
- dev_dbg_f(zd_mac_dev(mac), "channel %s\n",
- (flags & MAC_FIXED_CHANNEL) ? "fixed" : "auto");
- return zd_channel_to_freq(freq, channel);
+ return zd_channel_to_freq(freq, zd_mac_get_channel(mac));
}
static int iw_set_mode(struct net_device *netdev,
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index 3faaeb2b7c89..aa782e88754b 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -47,11 +47,17 @@ static struct usb_device_id usb_ids[] = {
{ USB_DEVICE(0x0586, 0x3402), .driver_info = DEVICE_ZD1211 },
{ USB_DEVICE(0x0b3b, 0x5630), .driver_info = DEVICE_ZD1211 },
{ USB_DEVICE(0x0b05, 0x170c), .driver_info = DEVICE_ZD1211 },
+ { USB_DEVICE(0x1435, 0x0711), .driver_info = DEVICE_ZD1211 },
+ { USB_DEVICE(0x0586, 0x3409), .driver_info = DEVICE_ZD1211 },
+ { USB_DEVICE(0x0b3b, 0x1630), .driver_info = DEVICE_ZD1211 },
+ { USB_DEVICE(0x0586, 0x3401), .driver_info = DEVICE_ZD1211 },
+ { USB_DEVICE(0x14ea, 0xab13), .driver_info = DEVICE_ZD1211 },
/* ZD1211B */
{ USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B },
{ USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B },
{ USB_DEVICE(0x079b, 0x0062), .driver_info = DEVICE_ZD1211B },
{ USB_DEVICE(0x1582, 0x6003), .driver_info = DEVICE_ZD1211B },
+ { USB_DEVICE(0x050d, 0x705c), .driver_info = DEVICE_ZD1211B },
/* "Driverless" devices that need ejecting */
{ USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER },
{}
@@ -366,15 +372,6 @@ error:
return r;
}
-static void disable_read_regs_int(struct zd_usb *usb)
-{
- struct zd_usb_interrupt *intr = &usb->intr;
-
- spin_lock(&intr->lock);
- intr->read_regs_enabled = 0;
- spin_unlock(&intr->lock);
-}
-
#define urb_dev(urb) (&(urb)->dev->dev)
static inline void handle_regs_int(struct urb *urb)
@@ -596,6 +593,8 @@ static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer,
unsigned int l, k, n;
for (i = 0, l = 0;; i++) {
k = le16_to_cpu(get_unaligned(&length_info->length[i]));
+ if (k == 0)
+ return;
n = l+k;
if (n > length)
return;
@@ -1119,27 +1118,28 @@ static int __init usb_init(void)
{
int r;
- pr_debug("usb_init()\n");
+ pr_debug("%s usb_init()\n", driver.name);
zd_workqueue = create_singlethread_workqueue(driver.name);
if (zd_workqueue == NULL) {
- printk(KERN_ERR "%s: couldn't create workqueue\n", driver.name);
+ printk(KERN_ERR "%s couldn't create workqueue\n", driver.name);
return -ENOMEM;
}
r = usb_register(&driver);
if (r) {
- printk(KERN_ERR "usb_register() failed. Error number %d\n", r);
+ printk(KERN_ERR "%s usb_register() failed. Error number %d\n",
+ driver.name, r);
return r;
}
- pr_debug("zd1211rw initialized\n");
+ pr_debug("%s initialized\n", driver.name);
return 0;
}
static void __exit usb_exit(void)
{
- pr_debug("usb_exit()\n");
+ pr_debug("%s usb_exit()\n", driver.name);
usb_deregister(&driver);
destroy_workqueue(zd_workqueue);
}
@@ -1156,10 +1156,19 @@ static void prepare_read_regs_int(struct zd_usb *usb)
{
struct zd_usb_interrupt *intr = &usb->intr;
- spin_lock(&intr->lock);
+ spin_lock_irq(&intr->lock);
intr->read_regs_enabled = 1;
INIT_COMPLETION(intr->read_regs.completion);
- spin_unlock(&intr->lock);
+ spin_unlock_irq(&intr->lock);
+}
+
+static void disable_read_regs_int(struct zd_usb *usb)
+{
+ struct zd_usb_interrupt *intr = &usb->intr;
+
+ spin_lock_irq(&intr->lock);
+ intr->read_regs_enabled = 0;
+ spin_unlock_irq(&intr->lock);
}
static int get_results(struct zd_usb *usb, u16 *values,
@@ -1171,7 +1180,7 @@ static int get_results(struct zd_usb *usb, u16 *values,
struct read_regs_int *rr = &intr->read_regs;
struct usb_int_regs *regs = (struct usb_int_regs *)rr->buffer;
- spin_lock(&intr->lock);
+ spin_lock_irq(&intr->lock);
r = -EIO;
/* The created block size seems to be larger than expected.
@@ -1204,7 +1213,7 @@ static int get_results(struct zd_usb *usb, u16 *values,
r = 0;
error_unlock:
- spin_unlock(&intr->lock);
+ spin_unlock_irq(&intr->lock);
return r;
}
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.h b/drivers/net/wireless/zd1211rw/zd_usb.h
index e81a2d3cfffd..317d37c36679 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.h
+++ b/drivers/net/wireless/zd1211rw/zd_usb.h
@@ -74,17 +74,17 @@ enum control_requests {
struct usb_req_read_regs {
__le16 id;
__le16 addr[0];
-};
+} __attribute__((packed));
struct reg_data {
__le16 addr;
__le16 value;
-};
+} __attribute__((packed));
struct usb_req_write_regs {
__le16 id;
struct reg_data reg_writes[0];
-};
+} __attribute__((packed));
enum {
RF_IF_LE = 0x02,
@@ -101,7 +101,7 @@ struct usb_req_rfwrite {
/* RF2595: 24 */
__le16 bit_values[0];
/* (CR203 & ~(RF_IF_LE | RF_CLK | RF_DATA)) | (bit ? RF_DATA : 0) */
-};
+} __attribute__((packed));
/* USB interrupt */
@@ -118,12 +118,12 @@ enum usb_int_flags {
struct usb_int_header {
u8 type; /* must always be 1 */
u8 id;
-};
+} __attribute__((packed));
struct usb_int_regs {
struct usb_int_header hdr;
struct reg_data regs[0];
-};
+} __attribute__((packed));
struct usb_int_retry_fail {
struct usb_int_header hdr;
@@ -131,7 +131,7 @@ struct usb_int_retry_fail {
u8 _dummy;
u8 addr[ETH_ALEN];
u8 ibss_wakeup_dest;
-};
+} __attribute__((packed));
struct read_regs_int {
struct completion completion;
diff --git a/drivers/net/zorro8390.c b/drivers/net/zorro8390.c
index df04e050c647..d85e2ea0b6af 100644
--- a/drivers/net/zorro8390.c
+++ b/drivers/net/zorro8390.c
@@ -34,8 +34,16 @@
#include <asm/amigaints.h>
#include <asm/amigahw.h>
-#include "8390.h"
+#define EI_SHIFT(x) (ei_local->reg_offset[x])
+#define ei_inb(port) in_8(port)
+#define ei_outb(val,port) out_8(port,val)
+#define ei_inb_p(port) in_8(port)
+#define ei_outb_p(val,port) out_8(port,val)
+static const char version[] =
+ "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+
+#include "lib8390.c"
#define DRV_NAME "zorro8390"
@@ -114,7 +122,7 @@ static int __devinit zorro8390_init_one(struct zorro_dev *z,
break;
board = z->resource.start;
ioaddr = board+cards[i].offset;
- dev = alloc_ei_netdev();
+ dev = ____alloc_ei_netdev(0);
if (!dev)
return -ENOMEM;
SET_MODULE_OWNER(dev);
@@ -201,7 +209,7 @@ static int __devinit zorro8390_init(struct net_device *dev,
dev->irq = IRQ_AMIGA_PORTS;
/* Install the Interrupt handler */
- i = request_irq(IRQ_AMIGA_PORTS, ei_interrupt, IRQF_SHARED, DRV_NAME, dev);
+ i = request_irq(IRQ_AMIGA_PORTS, __ei_interrupt, IRQF_SHARED, DRV_NAME, dev);
if (i) return i;
for(i = 0; i < ETHER_ADDR_LEN; i++) {
@@ -226,10 +234,10 @@ static int __devinit zorro8390_init(struct net_device *dev,
dev->open = &zorro8390_open;
dev->stop = &zorro8390_close;
#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = ei_poll;
+ dev->poll_controller = __ei_poll;
#endif
- NS8390_init(dev, 0);
+ __NS8390_init(dev, 0);
err = register_netdev(dev);
if (err) {
free_irq(IRQ_AMIGA_PORTS, dev);
@@ -246,7 +254,7 @@ static int __devinit zorro8390_init(struct net_device *dev,
static int zorro8390_open(struct net_device *dev)
{
- ei_open(dev);
+ __ei_open(dev);
return 0;
}
@@ -254,7 +262,7 @@ static int zorro8390_close(struct net_device *dev)
{
if (ei_debug > 1)
printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name);
- ei_close(dev);
+ __ei_close(dev);
return 0;
}
@@ -405,7 +413,7 @@ static void zorro8390_block_output(struct net_device *dev, int count,
printk(KERN_ERR "%s: timeout waiting for Tx RDC.\n",
dev->name);
zorro8390_reset_8390(dev);
- NS8390_init(dev,1);
+ __NS8390_init(dev,1);
break;
}
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
index 68cb3a080050..fe3f5f5365c5 100644
--- a/drivers/parisc/ccio-dma.c
+++ b/drivers/parisc/ccio-dma.c
@@ -486,7 +486,7 @@ typedef unsigned long space_t;
** This bit tells U2 to do R/M/W for partial cachelines. "Streaming"
** data can avoid this if the mapping covers full cache lines.
** o STOP_MOST is needed for atomicity across cachelines.
-** Apperently only "some EISA devices" need this.
+** Apparently only "some EISA devices" need this.
** Using CONFIG_ISA is hack. Only the IOA with EISA under it needs
** to use this hint iff the EISA devices needs this feature.
** According to the U2 ERS, STOP_MOST enabled pages hurt performance.
diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c
index c2949b4367e5..12bab64a62a1 100644
--- a/drivers/parisc/iosapic.c
+++ b/drivers/parisc/iosapic.c
@@ -50,12 +50,12 @@
**
** PA Firmware
** -----------
-** PA-RISC platforms have two fundementally different types of firmware.
+** PA-RISC platforms have two fundamentally different types of firmware.
** For PCI devices, "Legacy" PDC initializes the "INTERRUPT_LINE" register
** and BARs similar to a traditional PC BIOS.
** The newer "PAT" firmware supports PDC calls which return tables.
-** PAT firmware only initializes PCI Console and Boot interface.
-** With these tables, the OS can progam all other PCI devices.
+** PAT firmware only initializes the PCI Console and Boot interface.
+** With these tables, the OS can program all other PCI devices.
**
** One such PAT PDC call returns the "Interrupt Routing Table" (IRT).
** The IRT maps each PCI slot's INTA-D "output" line to an I/O SAPIC
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 5f1b9f58070e..f1dd81a1d592 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -19,7 +19,7 @@ config PCI_MSI
config PCI_MULTITHREAD_PROBE
bool "PCI Multi-threaded probe (EXPERIMENTAL)"
- depends on PCI && EXPERIMENTAL && BROKEN
+ depends on PCI && EXPERIMENTAL
help
Say Y here if you want the PCI core to spawn a new thread for
every PCI device that is probed. This can cause a huge
@@ -27,14 +27,14 @@ config PCI_MULTITHREAD_PROBE
smaller speedup on single processor machines.
But it can also cause lots of bad things to happen. A number
- of PCI drivers can not properly handle running in this way,
+ of PCI drivers cannot properly handle running in this way,
some will just not work properly at all, while others might
decide to blow up power supplies with a huge load all at once,
so use this option at your own risk.
It is very unwise to use this option if you are not using a
boot process that can handle devices being created in any
- order. A program that can create persistant block and network
+ order. A program that can create persistent block and network
device names (like udev) is a good idea if you wish to use
this option.
diff --git a/drivers/pci/access.c b/drivers/pci/access.c
index ea16805a153c..73a58c73d526 100644
--- a/drivers/pci/access.c
+++ b/drivers/pci/access.c
@@ -1,6 +1,7 @@
#include <linux/pci.h>
#include <linux/module.h>
#include <linux/ioport.h>
+#include <linux/wait.h>
#include "pci.h"
@@ -63,30 +64,42 @@ EXPORT_SYMBOL(pci_bus_write_config_byte);
EXPORT_SYMBOL(pci_bus_write_config_word);
EXPORT_SYMBOL(pci_bus_write_config_dword);
-static u32 pci_user_cached_config(struct pci_dev *dev, int pos)
-{
- u32 data;
+/*
+ * The following routines are to prevent the user from accessing PCI config
+ * space when it's unsafe to do so. Some devices require this during BIST and
+ * we're required to prevent it during D-state transitions.
+ *
+ * We have a bit per device to indicate it's blocked and a global wait queue
+ * for callers to sleep on until devices are unblocked.
+ */
+static DECLARE_WAIT_QUEUE_HEAD(pci_ucfg_wait);
- data = dev->saved_config_space[pos/sizeof(dev->saved_config_space[0])];
- data >>= (pos % sizeof(dev->saved_config_space[0])) * 8;
- return data;
+static noinline void pci_wait_ucfg(struct pci_dev *dev)
+{
+ DECLARE_WAITQUEUE(wait, current);
+
+ __add_wait_queue(&pci_ucfg_wait, &wait);
+ do {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ spin_unlock_irq(&pci_lock);
+ schedule();
+ spin_lock_irq(&pci_lock);
+ } while (dev->block_ucfg_access);
+ __remove_wait_queue(&pci_ucfg_wait, &wait);
}
#define PCI_USER_READ_CONFIG(size,type) \
int pci_user_read_config_##size \
(struct pci_dev *dev, int pos, type *val) \
{ \
- unsigned long flags; \
int ret = 0; \
u32 data = -1; \
if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \
- spin_lock_irqsave(&pci_lock, flags); \
- if (likely(!dev->block_ucfg_access)) \
- ret = dev->bus->ops->read(dev->bus, dev->devfn, \
+ spin_lock_irq(&pci_lock); \
+ if (unlikely(dev->block_ucfg_access)) pci_wait_ucfg(dev); \
+ ret = dev->bus->ops->read(dev->bus, dev->devfn, \
pos, sizeof(type), &data); \
- else if (pos < sizeof(dev->saved_config_space)) \
- data = pci_user_cached_config(dev, pos); \
- spin_unlock_irqrestore(&pci_lock, flags); \
+ spin_unlock_irq(&pci_lock); \
*val = (type)data; \
return ret; \
}
@@ -95,14 +108,13 @@ int pci_user_read_config_##size \
int pci_user_write_config_##size \
(struct pci_dev *dev, int pos, type val) \
{ \
- unsigned long flags; \
int ret = -EIO; \
if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \
- spin_lock_irqsave(&pci_lock, flags); \
- if (likely(!dev->block_ucfg_access)) \
- ret = dev->bus->ops->write(dev->bus, dev->devfn, \
+ spin_lock_irq(&pci_lock); \
+ if (unlikely(dev->block_ucfg_access)) pci_wait_ucfg(dev); \
+ ret = dev->bus->ops->write(dev->bus, dev->devfn, \
pos, sizeof(type), val); \
- spin_unlock_irqrestore(&pci_lock, flags); \
+ spin_unlock_irq(&pci_lock); \
return ret; \
}
@@ -117,21 +129,23 @@ PCI_USER_WRITE_CONFIG(dword, u32)
* pci_block_user_cfg_access - Block userspace PCI config reads/writes
* @dev: pci device struct
*
- * This function blocks any userspace PCI config accesses from occurring.
- * When blocked, any writes will be bit bucketed and reads will return the
- * data saved using pci_save_state for the first 64 bytes of config
- * space and return 0xff for all other config reads.
- **/
+ * When user access is blocked, any reads or writes to config space will
+ * sleep until access is unblocked again. We don't allow nesting of
+ * block/unblock calls.
+ */
void pci_block_user_cfg_access(struct pci_dev *dev)
{
unsigned long flags;
+ int was_blocked;
- pci_save_state(dev);
-
- /* spinlock to synchronize with anyone reading config space now */
spin_lock_irqsave(&pci_lock, flags);
+ was_blocked = dev->block_ucfg_access;
dev->block_ucfg_access = 1;
spin_unlock_irqrestore(&pci_lock, flags);
+
+ /* If we BUG() inside the pci_lock, we're guaranteed to hose
+ * the machine */
+ BUG_ON(was_blocked);
}
EXPORT_SYMBOL_GPL(pci_block_user_cfg_access);
@@ -140,14 +154,19 @@ EXPORT_SYMBOL_GPL(pci_block_user_cfg_access);
* @dev: pci device struct
*
* This function allows userspace PCI config accesses to resume.
- **/
+ */
void pci_unblock_user_cfg_access(struct pci_dev *dev)
{
unsigned long flags;
- /* spinlock to synchronize with anyone reading saved config space */
spin_lock_irqsave(&pci_lock, flags);
+
+ /* This indicates a problem in the caller, but we don't need
+ * to kill them, unlike a double-block above. */
+ WARN_ON(!dev->block_ucfg_access);
+
dev->block_ucfg_access = 0;
+ wake_up_all(&pci_ucfg_wait);
spin_unlock_irqrestore(&pci_lock, flags);
}
EXPORT_SYMBOL_GPL(pci_unblock_user_cfg_access);
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h
index 59c5b242d86d..ddbadd95387e 100644
--- a/drivers/pci/hotplug/acpiphp.h
+++ b/drivers/pci/hotplug/acpiphp.h
@@ -62,10 +62,10 @@ struct acpiphp_slot;
struct slot {
struct hotplug_slot *hotplug_slot;
struct acpiphp_slot *acpi_slot;
+ struct hotplug_slot_info info;
+ char name[SLOT_NAME_SIZE];
};
-
-
/**
* struct acpiphp_bridge - PCI bridge information
*
diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c
index c57d9d5ce84e..40c79b03c7ef 100644
--- a/drivers/pci/hotplug/acpiphp_core.c
+++ b/drivers/pci/hotplug/acpiphp_core.c
@@ -303,25 +303,15 @@ static int __init init_acpi(void)
/* read initial number of slots */
if (!retval) {
num_slots = acpiphp_get_num_slots();
- if (num_slots == 0)
+ if (num_slots == 0) {
+ acpiphp_glue_exit();
retval = -ENODEV;
+ }
}
return retval;
}
-
-/**
- * make_slot_name - make a slot name that appears in pcihpfs
- * @slot: slot to name
- *
- */
-static void make_slot_name(struct slot *slot)
-{
- snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%u",
- slot->acpi_slot->sun);
-}
-
/**
* release_slot - free up the memory used by a slot
* @hotplug_slot: slot to free
@@ -332,8 +322,6 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
- kfree(slot->hotplug_slot->info);
- kfree(slot->hotplug_slot->name);
kfree(slot->hotplug_slot);
kfree(slot);
}
@@ -342,26 +330,19 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot)
{
struct slot *slot;
- struct hotplug_slot *hotplug_slot;
- struct hotplug_slot_info *hotplug_slot_info;
int retval = -ENOMEM;
slot = kzalloc(sizeof(*slot), GFP_KERNEL);
if (!slot)
goto error;
- slot->hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL);
+ slot->hotplug_slot = kzalloc(sizeof(*slot->hotplug_slot), GFP_KERNEL);
if (!slot->hotplug_slot)
goto error_slot;
- slot->hotplug_slot->info = kzalloc(sizeof(*hotplug_slot_info),
- GFP_KERNEL);
- if (!slot->hotplug_slot->info)
- goto error_hpslot;
+ slot->hotplug_slot->info = &slot->info;
- slot->hotplug_slot->name = kzalloc(SLOT_NAME_SIZE, GFP_KERNEL);
- if (!slot->hotplug_slot->name)
- goto error_info;
+ slot->hotplug_slot->name = slot->name;
slot->hotplug_slot->private = slot;
slot->hotplug_slot->release = &release_slot;
@@ -376,21 +357,17 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot)
slot->hotplug_slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN;
acpiphp_slot->slot = slot;
- make_slot_name(slot);
+ snprintf(slot->name, sizeof(slot->name), "%u", slot->acpi_slot->sun);
retval = pci_hp_register(slot->hotplug_slot);
if (retval) {
err("pci_hp_register failed with error %d\n", retval);
- goto error_name;
+ goto error_hpslot;
}
info("Slot [%s] registered\n", slot->hotplug_slot->name);
return 0;
-error_name:
- kfree(slot->hotplug_slot->name);
-error_info:
- kfree(slot->hotplug_slot->info);
error_hpslot:
kfree(slot->hotplug_slot);
error_slot:
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 16167b016266..0b9d0db1590a 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -1693,14 +1693,10 @@ void __exit acpiphp_glue_exit(void)
*/
int __init acpiphp_get_num_slots(void)
{
- struct list_head *node;
struct acpiphp_bridge *bridge;
- int num_slots;
-
- num_slots = 0;
+ int num_slots = 0;
- list_for_each (node, &bridge_list) {
- bridge = (struct acpiphp_bridge *)node;
+ list_for_each_entry (bridge, &bridge_list, list) {
dbg("Bus %04x:%02x has %d slot%s\n",
pci_domain_nr(bridge->pci_bus),
bridge->pci_bus->number, bridge->nr_slots,
diff --git a/drivers/pci/hotplug/ibmphp_hpc.c b/drivers/pci/hotplug/ibmphp_hpc.c
index c3ac98a0a6a6..f55ac3885cb3 100644
--- a/drivers/pci/hotplug/ibmphp_hpc.c
+++ b/drivers/pci/hotplug/ibmphp_hpc.c
@@ -531,7 +531,7 @@ static u8 hpc_readcmdtoindex (u8 cmd, u8 index)
*
* Action: issue a READ command to HPC
*
-* Input: pslot - can not be NULL for READ_ALLSTAT
+* Input: pslot - cannot be NULL for READ_ALLSTAT
* pstatus - can be NULL for READ_ALLSTAT
*
* Return 0 or error codes
diff --git a/drivers/pci/hotplug/ibmphp_pci.c b/drivers/pci/hotplug/ibmphp_pci.c
index d87a9e3eaeeb..d8f05d7a3c72 100644
--- a/drivers/pci/hotplug/ibmphp_pci.c
+++ b/drivers/pci/hotplug/ibmphp_pci.c
@@ -1371,12 +1371,12 @@ static int unconfigure_boot_bridge (u8 busno, u8 device, u8 function)
}
bus = ibmphp_find_res_bus (sec_number);
- debug ("bus->busno is %x\n", bus->busno);
- debug ("sec_number is %x\n", sec_number);
if (!bus) {
err ("cannot find Bus structure for the bridged device\n");
return -EINVAL;
}
+ debug("bus->busno is %x\n", bus->busno);
+ debug("sec_number is %x\n", sec_number);
ibmphp_remove_bus (bus, busno);
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index f93e81e2d2c7..f13f31323e85 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -521,14 +521,9 @@ static void __exit unload_pciehpd(void)
}
-static int hpdriver_context = 0;
-
static void pciehp_remove (struct pcie_device *device)
{
- printk("%s ENTRY\n", __FUNCTION__);
- printk("%s -> Call free_irq for irq = %d\n",
- __FUNCTION__, device->irq);
- free_irq(device->irq, &hpdriver_context);
+ /* XXX - Needs to be adapted to device driver model */
}
#ifdef CONFIG_PM
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 1c551c697c35..6d3f580f2666 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -718,8 +718,6 @@ static void hpc_release_ctlr(struct controller *ctrl)
if (php_ctlr->irq) {
free_irq(php_ctlr->irq, ctrl);
php_ctlr->irq = 0;
- if (!pcie_mch_quirk)
- pci_disable_msi(php_ctlr->pci_dev);
}
}
if (php_ctlr->pci_dev)
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
index 46825fee3ae4..72383467a0d5 100644
--- a/drivers/pci/hotplug/rpadlpar_core.c
+++ b/drivers/pci/hotplug/rpadlpar_core.c
@@ -63,7 +63,7 @@ static struct device_node *find_php_slot_pci_node(char *drc_name,
char *type;
int rc;
- while ((np = of_find_node_by_type(np, "pci"))) {
+ while ((np = of_find_node_by_name(np, "pci"))) {
rc = rpaphp_get_drc_props(np, NULL, &name, &type, NULL);
if (rc == 0)
if (!strcmp(drc_name, name) && !strcmp(drc_type, type))
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
index 141486df235b..71a2cb8baa4a 100644
--- a/drivers/pci/hotplug/rpaphp_core.c
+++ b/drivers/pci/hotplug/rpaphp_core.c
@@ -356,7 +356,7 @@ static int __init rpaphp_init(void)
info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
init_MUTEX(&rpaphp_sem);
- while ((dn = of_find_node_by_type(dn, "pci")))
+ while ((dn = of_find_node_by_name(dn, "pci")))
rpaphp_add_slot(dn);
return 0;
diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c
index b62ad31a9739..5d188c558386 100644
--- a/drivers/pci/hotplug/sgi_hotplug.c
+++ b/drivers/pci/hotplug/sgi_hotplug.c
@@ -205,21 +205,6 @@ static struct hotplug_slot * sn_hp_destroy(void)
return bss_hotplug_slot;
}
-static void sn_bus_alloc_data(struct pci_dev *dev)
-{
- struct pci_bus *subordinate_bus;
- struct pci_dev *child;
-
- sn_pci_fixup_slot(dev);
-
- /* Recursively sets up the sn_irq_info structs */
- if (dev->subordinate) {
- subordinate_bus = dev->subordinate;
- list_for_each_entry(child, &subordinate_bus->devices, bus_list)
- sn_bus_alloc_data(child);
- }
-}
-
static void sn_bus_free_data(struct pci_dev *dev)
{
struct pci_bus *subordinate_bus;
@@ -337,6 +322,11 @@ static int sn_slot_disable(struct hotplug_slot *bss_hotplug_slot,
return rc;
}
+/*
+ * Power up and configure the slot via a SAL call to PROM.
+ * Scan slot (and any children), do any platform specific fixup,
+ * and find device driver.
+ */
static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
{
struct slot *slot = bss_hotplug_slot->private;
@@ -345,6 +335,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
int func, num_funcs;
int new_ppb = 0;
int rc;
+ void pcibios_fixup_device_resources(struct pci_dev *);
/* Serialize the Linux PCI infrastructure */
mutex_lock(&sn_hotplug_mutex);
@@ -367,9 +358,6 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
return -ENODEV;
}
- sn_pci_controller_fixup(pci_domain_nr(slot->pci_bus),
- slot->pci_bus->number,
- slot->pci_bus);
/*
* Map SN resources for all functions on the card
* to the Linux PCI interface and tell the drivers
@@ -380,6 +368,13 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
PCI_DEVFN(slot->device_num + 1,
PCI_FUNC(func)));
if (dev) {
+ /* Need to do slot fixup on PPB before fixup of children
+ * (PPB's pcidev_info needs to be in pcidev_info list
+ * before child's SN_PCIDEV_INFO() call to setup
+ * pdi_host_pcidev_info).
+ */
+ pcibios_fixup_device_resources(dev);
+ sn_pci_fixup_slot(dev);
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
unsigned char sec_bus;
pci_read_config_byte(dev, PCI_SECONDARY_BUS,
@@ -387,12 +382,8 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
new_bus = pci_add_new_bus(dev->bus, dev,
sec_bus);
pci_scan_child_bus(new_bus);
- sn_pci_controller_fixup(pci_domain_nr(new_bus),
- new_bus->number,
- new_bus);
new_ppb = 1;
}
- sn_bus_alloc_data(dev);
pci_dev_put(dev);
}
}
diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h
index f0cca1772f9c..3898f5237144 100644
--- a/drivers/pci/msi.h
+++ b/drivers/pci/msi.h
@@ -6,14 +6,6 @@
#ifndef MSI_H
#define MSI_H
-/*
- * MSI-X Address Register
- */
-#define PCI_MSIX_FLAGS_QSIZE 0x7FF
-#define PCI_MSIX_FLAGS_ENABLE (1 << 15)
-#define PCI_MSIX_FLAGS_BIRMASK (7 << 0)
-#define PCI_MSIX_FLAGS_BITMASK (1 << 0)
-
#define PCI_MSIX_ENTRY_SIZE 16
#define PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET 0
#define PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET 4
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index bb7456c1dbac..a064f36a0805 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -36,6 +36,7 @@ acpi_query_osc (
struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
union acpi_object *out_obj;
u32 osc_dw0;
+ acpi_status *ret_status = (acpi_status *)retval;
/* Setting up input parameters */
@@ -56,6 +57,7 @@ acpi_query_osc (
if (ACPI_FAILURE (status)) {
printk(KERN_DEBUG
"Evaluate _OSC Set fails. Status = 0x%04x\n", status);
+ *ret_status = status;
return status;
}
out_obj = output.pointer;
@@ -90,6 +92,7 @@ acpi_query_osc (
query_osc_out:
kfree(output.pointer);
+ *ret_status = status;
return status;
}
@@ -166,6 +169,7 @@ run_osc_out:
acpi_status pci_osc_support_set(u32 flags)
{
u32 temp;
+ acpi_status retval;
if (!(flags & OSC_SUPPORT_MASKS)) {
return AE_TYPE;
@@ -179,9 +183,13 @@ acpi_status pci_osc_support_set(u32 flags)
acpi_get_devices ( PCI_ROOT_HID_STRING,
acpi_query_osc,
ctrlset_buf,
- NULL );
+ (void **) &retval );
ctrlset_buf[OSC_QUERY_TYPE] = !OSC_QUERY_ENABLE;
ctrlset_buf[OSC_CONTROL_TYPE] = temp;
+ if (ACPI_FAILURE(retval)) {
+ /* no osc support at all */
+ ctrlset_buf[OSC_SUPPORT_TYPE] = 0;
+ }
return AE_OK;
}
EXPORT_SYMBOL(pci_osc_support_set);
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 194f1d21d3d7..e5ae3a0c13bb 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -329,8 +329,8 @@ static int pci_default_resume(struct pci_dev *pci_dev)
/* restore the PCI config space */
pci_restore_state(pci_dev);
/* if the device was enabled before suspend, reenable */
- if (pci_dev->is_enabled)
- retval = pci_enable_device(pci_dev);
+ if (atomic_read(&pci_dev->enable_cnt))
+ retval = __pci_enable_device(pci_dev);
/* if the device was busmaster before the suspend, make it busmaster again */
if (pci_dev->is_busmaster)
pci_set_master(pci_dev);
@@ -445,9 +445,12 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner)
/* register with core */
error = driver_register(&drv->driver);
+ if (error)
+ return error;
- if (!error)
- error = pci_create_newid_file(drv);
+ error = pci_create_newid_file(drv);
+ if (error)
+ driver_unregister(&drv->driver);
return error;
}
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index f952bfea48a6..7a94076752d0 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -42,7 +42,6 @@ pci_config_attr(subsystem_vendor, "0x%04x\n");
pci_config_attr(subsystem_device, "0x%04x\n");
pci_config_attr(class, "0x%06x\n");
pci_config_attr(irq, "%u\n");
-pci_config_attr(is_enabled, "%u\n");
static ssize_t broken_parity_status_show(struct device *dev,
struct device_attribute *attr,
@@ -112,26 +111,36 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
(u8)(pci_dev->class >> 16), (u8)(pci_dev->class >> 8),
(u8)(pci_dev->class));
}
-static ssize_t
-is_enabled_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+
+static ssize_t is_enabled_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
{
+ ssize_t result = -EINVAL;
struct pci_dev *pdev = to_pci_dev(dev);
- int retval = 0;
/* this can crash the machine when done on the "wrong" device */
if (!capable(CAP_SYS_ADMIN))
return count;
- if (*buf == '0')
- pci_disable_device(pdev);
+ if (*buf == '0') {
+ if (atomic_read(&pdev->enable_cnt) != 0)
+ pci_disable_device(pdev);
+ else
+ result = -EIO;
+ } else if (*buf == '1')
+ result = pci_enable_device(pdev);
+
+ return result < 0 ? result : count;
+}
- if (*buf == '1')
- retval = pci_enable_device(pdev);
+static ssize_t is_enabled_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct pci_dev *pdev;
- if (retval)
- return retval;
- return count;
+ pdev = to_pci_dev (dev);
+ return sprintf (buf, "%u\n", atomic_read(&pdev->enable_cnt));
}
static ssize_t
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index a544997399b3..5a14b73cf3a1 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -490,6 +490,47 @@ static void pci_restore_pcie_state(struct pci_dev *dev)
kfree(save_state);
}
+
+static int pci_save_pcix_state(struct pci_dev *dev)
+{
+ int pos, i = 0;
+ struct pci_cap_saved_state *save_state;
+ u16 *cap;
+
+ pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
+ if (pos <= 0)
+ return 0;
+
+ save_state = kzalloc(sizeof(*save_state) + sizeof(u16), GFP_KERNEL);
+ if (!save_state) {
+ dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n");
+ return -ENOMEM;
+ }
+ cap = (u16 *)&save_state->data[0];
+
+ pci_read_config_word(dev, pos + PCI_X_CMD, &cap[i++]);
+ pci_add_saved_cap(dev, save_state);
+ return 0;
+}
+
+static void pci_restore_pcix_state(struct pci_dev *dev)
+{
+ int i = 0, pos;
+ struct pci_cap_saved_state *save_state;
+ u16 *cap;
+
+ save_state = pci_find_saved_cap(dev, PCI_CAP_ID_PCIX);
+ pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
+ if (!save_state || pos <= 0)
+ return;
+ cap = (u16 *)&save_state->data[0];
+
+ pci_write_config_word(dev, pos + PCI_X_CMD, cap[i++]);
+ pci_remove_saved_cap(save_state);
+ kfree(save_state);
+}
+
+
/**
* pci_save_state - save the PCI configuration space of a device before suspending
* @dev: - PCI device that we're dealing with
@@ -507,6 +548,8 @@ pci_save_state(struct pci_dev *dev)
return i;
if ((i = pci_save_pcie_state(dev)) != 0)
return i;
+ if ((i = pci_save_pcix_state(dev)) != 0)
+ return i;
return 0;
}
@@ -538,6 +581,7 @@ pci_restore_state(struct pci_dev *dev)
dev->saved_config_space[i]);
}
}
+ pci_restore_pcix_state(dev);
pci_restore_msi_state(dev);
pci_restore_msix_state(dev);
return 0;
@@ -568,30 +612,51 @@ pci_enable_device_bars(struct pci_dev *dev, int bars)
}
/**
- * pci_enable_device - Initialize device before it's used by a driver.
+ * __pci_enable_device - Initialize device before it's used by a driver.
* @dev: PCI device to be initialized
*
* Initialize device before it's used by a driver. Ask low-level code
* to enable I/O and memory. Wake up the device if it was suspended.
* Beware, this function can fail.
+ *
+ * Note this function is a backend and is not supposed to be called by
+ * normal code, use pci_enable_device() instead.
*/
int
-pci_enable_device(struct pci_dev *dev)
+__pci_enable_device(struct pci_dev *dev)
{
int err;
- if (dev->is_enabled)
- return 0;
-
err = pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1);
if (err)
return err;
pci_fixup_device(pci_fixup_enable, dev);
- dev->is_enabled = 1;
return 0;
}
/**
+ * pci_enable_device - Initialize device before it's used by a driver.
+ * @dev: PCI device to be initialized
+ *
+ * Initialize device before it's used by a driver. Ask low-level code
+ * to enable I/O and memory. Wake up the device if it was suspended.
+ * Beware, this function can fail.
+ *
+ * Note we don't actually enable the device many times if we call
+ * this function repeatedly (we just increment the count).
+ */
+int pci_enable_device(struct pci_dev *dev)
+{
+ int result;
+ if (atomic_add_return(1, &dev->enable_cnt) > 1)
+ return 0; /* already enabled */
+ result = __pci_enable_device(dev);
+ if (result < 0)
+ atomic_dec(&dev->enable_cnt);
+ return result;
+}
+
+/**
* pcibios_disable_device - disable arch specific PCI resources for device dev
* @dev: the PCI device to disable
*
@@ -607,12 +672,18 @@ void __attribute__ ((weak)) pcibios_disable_device (struct pci_dev *dev) {}
*
* Signal to the system that the PCI device is not in use by the system
* anymore. This only involves disabling PCI bus-mastering, if active.
+ *
+ * Note we don't actually disable the device until all callers of
+ * pci_device_enable() have called pci_device_disable().
*/
void
pci_disable_device(struct pci_dev *dev)
{
u16 pci_command;
+ if (atomic_sub_return(1, &dev->enable_cnt) != 0)
+ return;
+
if (dev->msi_enabled)
disable_msi_mode(dev, pci_find_capability(dev, PCI_CAP_ID_MSI),
PCI_CAP_ID_MSI);
@@ -628,7 +699,6 @@ pci_disable_device(struct pci_dev *dev)
dev->is_busmaster = 0;
pcibios_disable_device(dev);
- dev->is_enabled = 0;
}
/**
@@ -831,22 +901,38 @@ pci_set_master(struct pci_dev *dev)
pcibios_set_master(dev);
}
-#ifndef HAVE_ARCH_PCI_MWI
+#ifdef PCI_DISABLE_MWI
+int pci_set_mwi(struct pci_dev *dev)
+{
+ return 0;
+}
+
+void pci_clear_mwi(struct pci_dev *dev)
+{
+}
+
+#else
+
+#ifndef PCI_CACHE_LINE_BYTES
+#define PCI_CACHE_LINE_BYTES L1_CACHE_BYTES
+#endif
+
/* This can be overridden by arch code. */
-u8 pci_cache_line_size = L1_CACHE_BYTES >> 2;
+/* Don't forget this is measured in 32-bit words, not bytes */
+u8 pci_cache_line_size = PCI_CACHE_LINE_BYTES / 4;
/**
- * pci_generic_prep_mwi - helper function for pci_set_mwi
- * @dev: the PCI device for which MWI is enabled
+ * pci_set_cacheline_size - ensure the CACHE_LINE_SIZE register is programmed
+ * @dev: the PCI device for which MWI is to be enabled
*
- * Helper function for generic implementation of pcibios_prep_mwi
- * function. Originally copied from drivers/net/acenic.c.
+ * Helper function for pci_set_mwi.
+ * Originally copied from drivers/net/acenic.c.
* Copyright 1998-2001 by Jes Sorensen, <jes@trained-monkey.org>.
*
* RETURNS: An appropriate -ERRNO error value on error, or zero for success.
*/
static int
-pci_generic_prep_mwi(struct pci_dev *dev)
+pci_set_cacheline_size(struct pci_dev *dev)
{
u8 cacheline_size;
@@ -872,7 +958,6 @@ pci_generic_prep_mwi(struct pci_dev *dev)
return -EINVAL;
}
-#endif /* !HAVE_ARCH_PCI_MWI */
/**
* pci_set_mwi - enables memory-write-invalidate PCI transaction
@@ -890,12 +975,7 @@ pci_set_mwi(struct pci_dev *dev)
int rc;
u16 cmd;
-#ifdef HAVE_ARCH_PCI_MWI
- rc = pcibios_prep_mwi(dev);
-#else
- rc = pci_generic_prep_mwi(dev);
-#endif
-
+ rc = pci_set_cacheline_size(dev);
if (rc)
return rc;
@@ -926,6 +1006,7 @@ pci_clear_mwi(struct pci_dev *dev)
pci_write_config_word(dev, PCI_COMMAND, cmd);
}
}
+#endif /* ! PCI_DISABLE_MWI */
/**
* pci_intx - enables/disables PCI INTx for device dev
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 6bf327db5c5e..398852f526a6 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -1,5 +1,6 @@
/* Functions internal to the PCI core code */
+extern int __must_check __pci_enable_device(struct pci_dev *);
extern int pci_uevent(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size);
extern int pci_create_sysfs_dev_files(struct pci_dev *pdev);
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index e159d6604494..0eeac60042b3 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -679,6 +679,33 @@ static int pci_setup_device(struct pci_dev * dev)
pci_read_bases(dev, 6, PCI_ROM_ADDRESS);
pci_read_config_word(dev, PCI_SUBSYSTEM_VENDOR_ID, &dev->subsystem_vendor);
pci_read_config_word(dev, PCI_SUBSYSTEM_ID, &dev->subsystem_device);
+
+ /*
+ * Do the ugly legacy mode stuff here rather than broken chip
+ * quirk code. Legacy mode ATA controllers have fixed
+ * addresses. These are not always echoed in BAR0-3, and
+ * BAR0-3 in a few cases contain junk!
+ */
+ if (class == PCI_CLASS_STORAGE_IDE) {
+ u8 progif;
+ pci_read_config_byte(dev, PCI_CLASS_PROG, &progif);
+ if ((progif & 1) == 0) {
+ dev->resource[0].start = 0x1F0;
+ dev->resource[0].end = 0x1F7;
+ dev->resource[0].flags = IORESOURCE_IO;
+ dev->resource[1].start = 0x3F6;
+ dev->resource[1].end = 0x3F6;
+ dev->resource[1].flags = IORESOURCE_IO;
+ }
+ if ((progif & 4) == 0) {
+ dev->resource[2].start = 0x170;
+ dev->resource[2].end = 0x177;
+ dev->resource[2].flags = IORESOURCE_IO;
+ dev->resource[3].start = 0x376;
+ dev->resource[3].end = 0x376;
+ dev->resource[3].flags = IORESOURCE_IO;
+ }
+ }
break;
case PCI_HEADER_TYPE_BRIDGE: /* bridge header */
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 5b4483811691..9ca9b9bf6160 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -797,56 +797,6 @@ static void __init quirk_mediagx_master(struct pci_dev *dev)
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master );
/*
- * As per PCI spec, ignore base address registers 0-3 of the IDE controllers
- * running in Compatible mode (bits 0 and 2 in the ProgIf for primary and
- * secondary channels respectively). If the device reports Compatible mode
- * but does use BAR0-3 for address decoding, we assume that firmware has
- * programmed these BARs with standard values (0x1f0,0x3f4 and 0x170,0x374).
- * Exceptions (if they exist) must be handled in chip/architecture specific
- * fixups.
- *
- * Note: for non x86 people. You may need an arch specific quirk to handle
- * moving IDE devices to native mode as well. Some plug in card devices power
- * up in compatible mode and assume the BIOS will adjust them.
- *
- * Q: should we load the 0x1f0,0x3f4 into the registers or zap them as
- * we do now ? We don't want is pci_enable_device to come along
- * and assign new resources. Both approaches work for that.
- */
-static void __devinit quirk_ide_bases(struct pci_dev *dev)
-{
- struct resource *res;
- int first_bar = 2, last_bar = 0;
-
- if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE)
- return;
-
- res = &dev->resource[0];
-
- /* primary channel: ProgIf bit 0, BAR0, BAR1 */
- if (!(dev->class & 1) && (res[0].flags || res[1].flags)) {
- res[0].start = res[0].end = res[0].flags = 0;
- res[1].start = res[1].end = res[1].flags = 0;
- first_bar = 0;
- last_bar = 1;
- }
-
- /* secondary channel: ProgIf bit 2, BAR2, BAR3 */
- if (!(dev->class & 4) && (res[2].flags || res[3].flags)) {
- res[2].start = res[2].end = res[2].flags = 0;
- res[3].start = res[3].end = res[3].flags = 0;
- last_bar = 3;
- }
-
- if (!last_bar)
- return;
-
- printk(KERN_INFO "PCI: Ignoring BAR%d-%d of IDE controller %s\n",
- first_bar, last_bar, pci_name(dev));
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_ide_bases);
-
-/*
* Ensure C0 rev restreaming is off. This is normally done by
* the BIOS but in the odd case it is not the results are corruption
* hence the presence of a Linux check
@@ -880,11 +830,10 @@ static void __devinit quirk_svwks_csb5ide(struct pci_dev *pdev)
prog &= ~5;
pdev->class &= ~5;
pci_write_config_byte(pdev, PCI_CLASS_PROG, prog);
- /* need to re-assign BARs for compat mode */
- quirk_ide_bases(pdev);
+ /* PCI layer will sort out resources */
}
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, quirk_svwks_csb5ide );
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, quirk_svwks_csb5ide );
/*
* Intel 82801CAM ICH3-M datasheet says IDE modes must be the same
@@ -900,11 +849,9 @@ static void __init quirk_ide_samemode(struct pci_dev *pdev)
prog &= ~5;
pdev->class &= ~5;
pci_write_config_byte(pdev, PCI_CLASS_PROG, prog);
- /* need to re-assign BARs for compat mode */
- quirk_ide_bases(pdev);
}
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10, quirk_ide_samemode);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10, quirk_ide_samemode);
/* This was originally an Alpha specific thing, but it really fits here.
* The i82375 PCI/EISA bridge appears as non-classified. Fix that.
diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c
index e1dcefc69bb4..d087e0817715 100644
--- a/drivers/pci/rom.c
+++ b/drivers/pci/rom.c
@@ -81,7 +81,8 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
start = (loff_t)0xC0000;
*size = 0x20000; /* cover C000:0 through E000:0 */
} else {
- if (res->flags & IORESOURCE_ROM_COPY) {
+ if (res->flags &
+ (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY)) {
*size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
return (void __iomem *)(unsigned long)
pci_resource_start(pdev, PCI_ROM_RESOURCE);
@@ -165,7 +166,8 @@ void __iomem *pci_map_rom_copy(struct pci_dev *pdev, size_t *size)
if (!rom)
return NULL;
- if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_SHADOW))
+ if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_SHADOW |
+ IORESOURCE_ROM_BIOS_COPY))
return rom;
res->start = (unsigned long)kmalloc(*size, GFP_KERNEL);
@@ -191,7 +193,7 @@ void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom)
{
struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
- if (res->flags & IORESOURCE_ROM_COPY)
+ if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY))
return;
iounmap(rom);
@@ -215,6 +217,7 @@ void pci_remove_rom(struct pci_dev *pdev)
sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
if (!(res->flags & (IORESOURCE_ROM_ENABLE |
IORESOURCE_ROM_SHADOW |
+ IORESOURCE_ROM_BIOS_COPY |
IORESOURCE_ROM_COPY)))
pci_disable_rom(pdev);
}
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index e469a46a388b..ff14fd8f0cd1 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -1273,7 +1273,9 @@ static void pcmcia_bus_remove_socket(struct class_device *class_dev,
pccard_register_pcmcia(socket, NULL);
/* unregister any unbound devices */
+ mutex_lock(&socket->skt_mutex);
pcmcia_card_remove(socket, NULL);
+ mutex_unlock(&socket->skt_mutex);
pcmcia_put_socket(socket);
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index 579cd667b16f..6f11f6dfdd9d 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -145,6 +145,13 @@ int rtc_set_alarm(struct class_device *class_dev, struct rtc_wkalrm *alarm)
}
EXPORT_SYMBOL_GPL(rtc_set_alarm);
+/**
+ * rtc_update_irq - report RTC periodic, alarm, and/or update irqs
+ * @class_dev: the rtc's class device
+ * @num: how many irqs are being reported (usually one)
+ * @events: mask of RTC_IRQF with one or more of RTC_PF, RTC_AF, RTC_UF
+ * Context: in_interrupt(), irqs blocked
+ */
void rtc_update_irq(struct class_device *class_dev,
unsigned long num, unsigned long events)
{
@@ -201,12 +208,12 @@ int rtc_irq_register(struct class_device *class_dev, struct rtc_task *task)
if (task == NULL || task->func == NULL)
return -EINVAL;
- spin_lock(&rtc->irq_task_lock);
+ spin_lock_irq(&rtc->irq_task_lock);
if (rtc->irq_task == NULL) {
rtc->irq_task = task;
retval = 0;
}
- spin_unlock(&rtc->irq_task_lock);
+ spin_unlock_irq(&rtc->irq_task_lock);
return retval;
}
@@ -216,10 +223,10 @@ void rtc_irq_unregister(struct class_device *class_dev, struct rtc_task *task)
{
struct rtc_device *rtc = to_rtc_device(class_dev);
- spin_lock(&rtc->irq_task_lock);
+ spin_lock_irq(&rtc->irq_task_lock);
if (rtc->irq_task == task)
rtc->irq_task = NULL;
- spin_unlock(&rtc->irq_task_lock);
+ spin_unlock_irq(&rtc->irq_task_lock);
}
EXPORT_SYMBOL_GPL(rtc_irq_unregister);
@@ -265,3 +272,4 @@ int rtc_irq_set_freq(struct class_device *class_dev, struct rtc_task *task, int
}
return err;
}
+EXPORT_SYMBOL_GPL(rtc_irq_set_freq);
diff --git a/drivers/rtc/rtc-at91.c b/drivers/rtc/rtc-at91.c
index bd61e99540a3..5c8addcaf1fb 100644
--- a/drivers/rtc/rtc-at91.c
+++ b/drivers/rtc/rtc-at91.c
@@ -292,7 +292,8 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
AT91_RTC_CALEV);
ret = request_irq(AT91_ID_SYS, at91_rtc_interrupt,
- IRQF_SHARED, "at91_rtc", pdev);
+ IRQF_DISABLED | IRQF_SHARED,
+ "at91_rtc", pdev);
if (ret) {
printk(KERN_ERR "at91_rtc: IRQ %d already in use.\n",
AT91_ID_SYS);
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
index dcf5f86461f7..828b329e08e0 100644
--- a/drivers/rtc/rtc-dev.c
+++ b/drivers/rtc/rtc-dev.c
@@ -62,7 +62,9 @@ static void rtc_uie_task(struct work_struct *work)
int err;
err = rtc_read_time(&rtc->class_dev, &tm);
- spin_lock_irq(&rtc->irq_lock);
+
+ local_irq_disable();
+ spin_lock(&rtc->irq_lock);
if (rtc->stop_uie_polling || err) {
rtc->uie_task_active = 0;
} else if (rtc->oldsecs != tm.tm_sec) {
@@ -75,11 +77,11 @@ static void rtc_uie_task(struct work_struct *work)
} else if (schedule_work(&rtc->uie_task) == 0) {
rtc->uie_task_active = 0;
}
- spin_unlock_irq(&rtc->irq_lock);
+ spin_unlock(&rtc->irq_lock);
if (num)
rtc_update_irq(&rtc->class_dev, num, RTC_UF | RTC_IRQF);
+ local_irq_enable();
}
-
static void rtc_uie_timer(unsigned long data)
{
struct rtc_device *rtc = (struct rtc_device *)data;
@@ -215,7 +217,7 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
struct rtc_wkalrm alarm;
void __user *uarg = (void __user *) arg;
- /* check that the calles has appropriate permissions
+ /* check that the calling task has appropriate permissions
* for certain ioctls. doing this check here is useful
* to avoid duplicate code in each driver.
*/
@@ -239,10 +241,10 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
/* avoid conflicting IRQ users */
if (cmd == RTC_PIE_ON || cmd == RTC_PIE_OFF || cmd == RTC_IRQP_SET) {
- spin_lock(&rtc->irq_task_lock);
+ spin_lock_irq(&rtc->irq_task_lock);
if (rtc->irq_task)
err = -EBUSY;
- spin_unlock(&rtc->irq_task_lock);
+ spin_unlock_irq(&rtc->irq_task_lock);
if (err < 0)
return err;
@@ -300,6 +302,17 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
err = rtc_set_time(class_dev, &tm);
break;
+
+ case RTC_IRQP_READ:
+ if (ops->irq_set_freq)
+ err = put_user(rtc->irq_freq, (unsigned long *) arg);
+ break;
+
+ case RTC_IRQP_SET:
+ if (ops->irq_set_freq)
+ err = rtc_irq_set_freq(class_dev, rtc->irq_task, arg);
+ break;
+
#if 0
case RTC_EPOCH_SET:
#ifndef rtc_epoch
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c
index 78552e6e76aa..001eb1123a65 100644
--- a/drivers/rtc/rtc-ds1553.c
+++ b/drivers/rtc/rtc-ds1553.c
@@ -340,7 +340,8 @@ static int __init ds1553_rtc_probe(struct platform_device *pdev)
if (pdata->irq >= 0) {
writeb(0, ioaddr + RTC_INTERRUPTS);
- if (request_irq(pdata->irq, ds1553_rtc_interrupt, IRQF_SHARED,
+ if (request_irq(pdata->irq, ds1553_rtc_interrupt,
+ IRQF_DISABLED | IRQF_SHARED,
pdev->name, pdev) < 0) {
dev_warn(&pdev->dev, "interrupt not available.\n");
pdata->irq = -1;
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c
index 2a86632580f1..a44fe4efa216 100644
--- a/drivers/rtc/rtc-rs5c372.c
+++ b/drivers/rtc/rtc-rs5c372.c
@@ -126,13 +126,13 @@ static int rs5c372_get_trim(struct i2c_client *client, int *osc, int *trim)
return -EIO;
}
- dev_dbg(&client->dev, "%s: raw trim=%x\n", __FUNCTION__, *trim);
-
if (osc)
*osc = (buf & RS5C372_TRIM_XSL) ? 32000 : 32768;
- if (trim)
+ if (trim) {
*trim = buf & RS5C372_TRIM_MASK;
+ dev_dbg(&client->dev, "%s: raw trim=%x\n", __FUNCTION__, *trim);
+ }
return 0;
}
diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c
index bc4bd24508a2..6ef9c62d5032 100644
--- a/drivers/rtc/rtc-test.c
+++ b/drivers/rtc/rtc-test.c
@@ -99,6 +99,7 @@ static ssize_t test_irq_store(struct device *dev,
struct rtc_device *rtc = platform_get_drvdata(plat_dev);
retval = count;
+ local_irq_disable();
if (strncmp(buf, "tick", 4) == 0)
rtc_update_irq(&rtc->class_dev, 1, RTC_PF | RTC_IRQF);
else if (strncmp(buf, "alarm", 5) == 0)
@@ -107,6 +108,7 @@ static ssize_t test_irq_store(struct device *dev,
rtc_update_irq(&rtc->class_dev, 1, RTC_UF | RTC_IRQF);
else
retval = -EINVAL;
+ local_irq_enable();
return retval;
}
diff --git a/drivers/s390/net/claw.h b/drivers/s390/net/claw.h
index 969be465309c..1ee9a6f06541 100644
--- a/drivers/s390/net/claw.h
+++ b/drivers/s390/net/claw.h
@@ -29,7 +29,7 @@
#define CLAW_COMPLETE 0xff /* flag to indicate i/o completed */
/*-----------------------------------------------------*
-* CLAW control comand code *
+* CLAW control command code *
*------------------------------------------------------*/
#define SYSTEM_VALIDATE_REQUEST 0x01 /* System Validate request */
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index 16ac68c27a27..66a8aec6efa6 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -1147,7 +1147,7 @@ list_modified:
* get mac address for the relevant Multicast address
*/
static void
-lcs_get_mac_for_ipm(__u32 ipm, char *mac, struct net_device *dev)
+lcs_get_mac_for_ipm(__be32 ipm, char *mac, struct net_device *dev)
{
LCS_DBF_TEXT(4,trace, "getmac");
if (dev->type == ARPHRD_IEEE802_TR)
diff --git a/drivers/s390/net/lcs.h b/drivers/s390/net/lcs.h
index 93143932983b..b5247dc08b57 100644
--- a/drivers/s390/net/lcs.h
+++ b/drivers/s390/net/lcs.h
@@ -169,7 +169,7 @@ struct lcs_header {
} __attribute__ ((packed));
struct lcs_ip_mac_pair {
- __u32 ip_addr;
+ __be32 ip_addr;
__u8 mac_addr[LCS_MAC_LENGTH];
__u8 reserved[2];
} __attribute__ ((packed));
@@ -287,7 +287,7 @@ struct lcs_card {
enum lcs_dev_states state;
struct net_device *dev;
struct net_device_stats stats;
- unsigned short (*lan_type_trans)(struct sk_buff *skb,
+ __be16 (*lan_type_trans)(struct sk_buff *skb,
struct net_device *dev);
struct ccwgroup_device *gdev;
struct lcs_channel read;
diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c
index a363721cf28d..6bb558a9a032 100644
--- a/drivers/s390/net/qeth_eddp.c
+++ b/drivers/s390/net/qeth_eddp.c
@@ -258,7 +258,7 @@ qeth_eddp_create_segment_hdrs(struct qeth_eddp_context *ctx,
static inline void
qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp, int len,
- u32 *hcsum)
+ __wsum *hcsum)
{
struct skb_frag_struct *frag;
int left_in_frag;
@@ -305,7 +305,7 @@ qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp, int len,
static inline void
qeth_eddp_create_segment_data_tcp(struct qeth_eddp_context *ctx,
struct qeth_eddp_data *eddp, int data_len,
- u32 hcsum)
+ __wsum hcsum)
{
u8 *page;
int page_remainder;
@@ -349,10 +349,10 @@ qeth_eddp_create_segment_data_tcp(struct qeth_eddp_context *ctx,
((struct tcphdr *)eddp->th_in_ctx)->check = csum_fold(hcsum);
}
-static inline u32
+static inline __wsum
qeth_eddp_check_tcp4_hdr(struct qeth_eddp_data *eddp, int data_len)
{
- u32 phcsum; /* pseudo header checksum */
+ __wsum phcsum; /* pseudo header checksum */
QETH_DBF_TEXT(trace, 5, "eddpckt4");
eddp->th.tcp.h.check = 0;
@@ -363,11 +363,11 @@ qeth_eddp_check_tcp4_hdr(struct qeth_eddp_data *eddp, int data_len)
return csum_partial((u8 *)&eddp->th, eddp->thl, phcsum);
}
-static inline u32
+static inline __wsum
qeth_eddp_check_tcp6_hdr(struct qeth_eddp_data *eddp, int data_len)
{
- u32 proto;
- u32 phcsum; /* pseudo header checksum */
+ __be32 proto;
+ __wsum phcsum; /* pseudo header checksum */
QETH_DBF_TEXT(trace, 5, "eddpckt6");
eddp->th.tcp.h.check = 0;
@@ -405,7 +405,7 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
{
struct tcphdr *tcph;
int data_len;
- u32 hcsum;
+ __wsum hcsum;
QETH_DBF_TEXT(trace, 5, "eddpftcp");
eddp->skb_offset = sizeof(struct qeth_hdr) + eddp->nhl + eddp->thl;
@@ -433,22 +433,22 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
eddp->qh.hdr.l3.length = data_len + eddp->nhl +
eddp->thl;
/* prepare ip hdr */
- if (eddp->skb->protocol == ETH_P_IP){
- eddp->nh.ip4.h.tot_len = data_len + eddp->nhl +
- eddp->thl;
+ if (eddp->skb->protocol == htons(ETH_P_IP)){
+ eddp->nh.ip4.h.tot_len = htons(data_len + eddp->nhl +
+ eddp->thl);
eddp->nh.ip4.h.check = 0;
eddp->nh.ip4.h.check =
ip_fast_csum((u8 *)&eddp->nh.ip4.h,
eddp->nh.ip4.h.ihl);
} else
- eddp->nh.ip6.h.payload_len = data_len + eddp->thl;
+ eddp->nh.ip6.h.payload_len = htons(data_len + eddp->thl);
/* prepare tcp hdr */
if (data_len == (eddp->skb->len - eddp->skb_offset)){
/* last segment -> set FIN and PSH flags */
eddp->th.tcp.h.fin = tcph->fin;
eddp->th.tcp.h.psh = tcph->psh;
}
- if (eddp->skb->protocol == ETH_P_IP)
+ if (eddp->skb->protocol == htons(ETH_P_IP))
hcsum = qeth_eddp_check_tcp4_hdr(eddp, data_len);
else
hcsum = qeth_eddp_check_tcp6_hdr(eddp, data_len);
@@ -458,9 +458,9 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
if (eddp->skb_offset >= eddp->skb->len)
break;
/* prepare headers for next round */
- if (eddp->skb->protocol == ETH_P_IP)
- eddp->nh.ip4.h.id++;
- eddp->th.tcp.h.seq += data_len;
+ if (eddp->skb->protocol == htons(ETH_P_IP))
+ eddp->nh.ip4.h.id = htons(ntohs(eddp->nh.ip4.h.id) + 1);
+ eddp->th.tcp.h.seq = htonl(ntohl(eddp->th.tcp.h.seq) + data_len);
}
}
@@ -472,7 +472,7 @@ qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
QETH_DBF_TEXT(trace, 5, "eddpficx");
/* create our segmentation headers and copy original headers */
- if (skb->protocol == ETH_P_IP)
+ if (skb->protocol == htons(ETH_P_IP))
eddp = qeth_eddp_create_eddp_data(qhdr, (u8 *)skb->nh.iph,
skb->nh.iph->ihl*4,
(u8 *)skb->h.th, skb->h.th->doff*4);
@@ -490,7 +490,7 @@ qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
memcpy(&eddp->mac, eth_hdr(skb), ETH_HLEN);
#ifdef CONFIG_QETH_VLAN
if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)) {
- eddp->vlan[0] = __constant_htons(skb->protocol);
+ eddp->vlan[0] = skb->protocol;
eddp->vlan[1] = htons(vlan_tx_tag_get(skb));
}
#endif /* CONFIG_QETH_VLAN */
@@ -588,11 +588,11 @@ qeth_eddp_create_context_tcp(struct qeth_card *card, struct sk_buff *skb,
struct qeth_eddp_context *ctx = NULL;
QETH_DBF_TEXT(trace, 5, "creddpct");
- if (skb->protocol == ETH_P_IP)
+ if (skb->protocol == htons(ETH_P_IP))
ctx = qeth_eddp_create_context_generic(card, skb,
sizeof(struct qeth_hdr) + skb->nh.iph->ihl*4 +
skb->h.th->doff*4);
- else if (skb->protocol == ETH_P_IPV6)
+ else if (skb->protocol == htons(ETH_P_IPV6))
ctx = qeth_eddp_create_context_generic(card, skb,
sizeof(struct qeth_hdr) + sizeof(struct ipv6hdr) +
skb->h.th->doff*4);
diff --git a/drivers/s390/net/qeth_eddp.h b/drivers/s390/net/qeth_eddp.h
index cae9ba265056..103768d3bab2 100644
--- a/drivers/s390/net/qeth_eddp.h
+++ b/drivers/s390/net/qeth_eddp.h
@@ -54,7 +54,7 @@ qeth_eddp_check_buffers_for_context(struct qeth_qdio_out_q *,
struct qeth_eddp_data {
struct qeth_hdr qh;
struct ethhdr mac;
- u16 vlan[2];
+ __be16 vlan[2];
union {
struct {
struct iphdr h;
diff --git a/drivers/scsi/aic94xx/aic94xx_reg_def.h b/drivers/scsi/aic94xx/aic94xx_reg_def.h
index b79f45f3ad47..a11f4e6d8bd9 100644
--- a/drivers/scsi/aic94xx/aic94xx_reg_def.h
+++ b/drivers/scsi/aic94xx/aic94xx_reg_def.h
@@ -2000,7 +2000,7 @@
* The host accesses this scratch in a different manner from the
* central sequencer. The sequencer has to use CSEQ registers CSCRPAGE
* and CMnSCRPAGE to access the scratch memory. A flat mapping of the
- * scratch memory is avaliable for software convenience and to prevent
+ * scratch memory is available for software convenience and to prevent
* corruption while the sequencer is running. This memory is mapped
* onto addresses 800h - BFFh, total of 400h bytes.
*
diff --git a/drivers/scsi/aic94xx/aic94xx_sds.c b/drivers/scsi/aic94xx/aic94xx_sds.c
index de7c04d4254d..e5a0ec37e954 100644
--- a/drivers/scsi/aic94xx/aic94xx_sds.c
+++ b/drivers/scsi/aic94xx/aic94xx_sds.c
@@ -64,7 +64,7 @@ struct asd_ocm_dir {
#define OCM_INIT_DIR_ENTRIES 5
/***************************************************************************
-* OCM dircetory default
+* OCM directory default
***************************************************************************/
static struct asd_ocm_dir OCMDirInit =
{
@@ -73,7 +73,7 @@ static struct asd_ocm_dir OCMDirInit =
};
/***************************************************************************
-* OCM dircetory Entries default
+* OCM directory Entries default
***************************************************************************/
static struct asd_ocm_dir_ent OCMDirEntriesInit[OCM_INIT_DIR_ENTRIES] =
{
diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c
index 6cc2bc2f62be..adb8eb4f5fd1 100644
--- a/drivers/scsi/ncr53c8xx.c
+++ b/drivers/scsi/ncr53c8xx.c
@@ -185,7 +185,7 @@ static inline struct list_head *ncr_list_pop(struct list_head *head)
** power of 2 cache line size.
** Enhanced in linux-2.3.44 to provide a memory pool
** per pcidev to support dynamic dma mapping. (I would
-** have preferred a real bus astraction, btw).
+** have preferred a real bus abstraction, btw).
**
**==========================================================
*/
@@ -1438,7 +1438,7 @@ struct head {
** The first four bytes (scr_st[4]) are used inside the script by
** "COPY" commands.
** Because source and destination must have the same alignment
-** in a DWORD, the fields HAVE to be at the choosen offsets.
+** in a DWORD, the fields HAVE to be at the chosen offsets.
** xerr_st 0 (0x34) scratcha
** sync_st 1 (0x05) sxfer
** wide_st 3 (0x03) scntl3
@@ -1498,7 +1498,7 @@ struct head {
** the DSA (data structure address) register points
** to this substructure of the ccb.
** This substructure contains the header with
-** the script-processor-changable data and
+** the script-processor-changeable data and
** data blocks for the indirect move commands.
**
**----------------------------------------------------------
@@ -5107,7 +5107,7 @@ void ncr_complete (struct ncb *np, struct ccb *cp)
/*
** This CCB has been skipped by the NCR.
-** Queue it in the correponding unit queue.
+** Queue it in the corresponding unit queue.
*/
static void ncr_ccb_skipped(struct ncb *np, struct ccb *cp)
{
@@ -5896,8 +5896,8 @@ static void ncr_log_hard_error(struct ncb *np, u16 sist, u_char dstat)
**
** In normal cases, interrupt conditions occur one at a
** time. The ncr is able to stack in some extra registers
-** other interrupts that will occurs after the first one.
-** But severall interrupts may occur at the same time.
+** other interrupts that will occur after the first one.
+** But, several interrupts may occur at the same time.
**
** We probably should only try to deal with the normal
** case, but it seems that multiple interrupts occur in
@@ -6796,7 +6796,7 @@ void ncr_int_sir (struct ncb *np)
** The host status field is set to HS_NEGOTIATE to mark this
** situation.
**
-** If the target doesn't answer this message immidiately
+** If the target doesn't answer this message immediately
** (as required by the standard), the SIR_NEGO_FAIL interrupt
** will be raised eventually.
** The handler removes the HS_NEGOTIATE status, and sets the
diff --git a/drivers/scsi/ncr53c8xx.h b/drivers/scsi/ncr53c8xx.h
index cb8b7701431e..b39357d9af8d 100644
--- a/drivers/scsi/ncr53c8xx.h
+++ b/drivers/scsi/ncr53c8xx.h
@@ -218,7 +218,7 @@
** Same as option 1, but also deal with
** misconfigured interrupts.
**
-** - Edge triggerred instead of level sensitive.
+** - Edge triggered instead of level sensitive.
** - No interrupt line connected.
** - IRQ number misconfigured.
**
@@ -549,7 +549,7 @@ struct ncr_driver_setup {
/*
** Initial setup.
-** Can be overriden at startup by a command line.
+** Can be overridden at startup by a command line.
*/
#define SCSI_NCR_DRIVER_SETUP \
{ \
@@ -1093,7 +1093,7 @@ struct scr_tblsel {
**-----------------------------------------------------------
** On 810A, 860, 825A, 875, 895 and 896 chips the content
** of SFBR register can be used as data (SCR_SFBR_DATA).
-** The 896 has additionnal IO registers starting at
+** The 896 has additional IO registers starting at
** offset 0x80. Bit 7 of register offset is stored in
** bit 7 of the SCRIPTS instruction first DWORD.
**-----------------------------------------------------------
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 23334c8bc4c7..d895a1adb428 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -16,7 +16,7 @@ config SPI
controller and a chipselect. Most SPI slaves don't support
dynamic device discovery; some are even write-only or read-only.
- SPI is widely used by microcontollers to talk with sensors,
+ SPI is widely used by microcontrollers to talk with sensors,
eeprom and flash memory, codecs and various other controller
chips, analog to digital (and d-to-a) converters, and more.
MMC and SD cards can be accessed using SPI protocol; and for
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c
index 7ed34bb1c50f..8ed6c75adf0f 100644
--- a/drivers/usb/atm/speedtch.c
+++ b/drivers/usb/atm/speedtch.c
@@ -837,8 +837,8 @@ static int speedtch_bind(struct usbatm_data *usbatm,
const struct usb_endpoint_descriptor *endpoint_desc = &desc->endpoint[i].desc;
if ((endpoint_desc->bEndpointAddress == target_address)) {
- use_isoc = (endpoint_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
- USB_ENDPOINT_XFER_ISOC;
+ use_isoc =
+ usb_endpoint_xfer_isoc(endpoint_desc);
break;
}
}
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
index e39bb09f5af9..f2d196fa1e8b 100644
--- a/drivers/usb/atm/ueagle-atm.c
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -401,9 +401,8 @@ static int uea_send_modem_cmd(struct usb_device *usb,
int ret = -ENOMEM;
u8 *xfer_buff;
- xfer_buff = kmalloc(size, GFP_KERNEL);
+ xfer_buff = kmemdup(buff, size, GFP_KERNEL);
if (xfer_buff) {
- memcpy(xfer_buff, buff, size);
ret = usb_control_msg(usb,
usb_sndctrlpipe(usb, 0),
LOAD_INTERNAL,
@@ -595,14 +594,12 @@ static int uea_idma_write(struct uea_softc *sc, void *data, u32 size)
u8 *xfer_buff;
int bytes_read;
- xfer_buff = kmalloc(size, GFP_KERNEL);
+ xfer_buff = kmemdup(data, size, GFP_KERNEL);
if (!xfer_buff) {
uea_err(INS_TO_USBDEV(sc), "can't allocate xfer_buff\n");
return ret;
}
- memcpy(xfer_buff, data, size);
-
ret = usb_bulk_msg(sc->usb_dev,
usb_sndbulkpipe(sc->usb_dev, UEA_IDMA_PIPE),
xfer_buff, size, &bytes_read, BULK_TIMEOUT);
@@ -765,12 +762,11 @@ static int uea_request(struct uea_softc *sc,
u8 *xfer_buff;
int ret = -ENOMEM;
- xfer_buff = kmalloc(size, GFP_KERNEL);
+ xfer_buff = kmemdup(data, size, GFP_KERNEL);
if (!xfer_buff) {
uea_err(INS_TO_USBDEV(sc), "can't allocate xfer_buff\n");
return ret;
}
- memcpy(xfer_buff, data, size);
ret = usb_control_msg(sc->usb_dev, usb_sndctrlpipe(sc->usb_dev, 0),
UCDC_SEND_ENCAPSULATED_COMMAND,
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 6408e10fdbf8..7f1fa956dcdb 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -892,7 +892,7 @@ skip_normal_probe:
/* workaround for switched endpoints */
- if ((epread->bEndpointAddress & USB_DIR_IN) != USB_DIR_IN) {
+ if (!usb_endpoint_dir_in(epread)) {
/* descriptors are swapped */
struct usb_endpoint_descriptor *t;
dev_dbg(&intf->dev,"The data interface has switched endpoints");
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index 6e3b5358a760..f8324d8d06ac 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -72,6 +72,21 @@ config USB_SUSPEND
If you are unsure about this, say N here.
+config USB_MULTITHREAD_PROBE
+ bool "USB Multi-threaded probe (EXPERIMENTAL)"
+ depends on USB && EXPERIMENTAL
+ default n
+ help
+ Say Y here if you want the USB core to spawn a new thread for
+ every USB device that is probed. This can cause a small speedup
+ in boot times on systems with a lot of different USB devices.
+
+ This option should be safe to enable, but if any odd probing
+ problems are found, please disable it, or dynamically turn it
+ off in the /sys/module/usbcore/parameters/multithread_probe
+ file
+
+ When in doubt, say N.
config USB_OTG
bool
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index 3538c2fdadfe..ea398e5d50af 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -175,12 +175,13 @@ static char *usb_dump_endpoint_descriptor (
)
{
char dir, unit, *type;
- unsigned interval, in, bandwidth = 1;
+ unsigned interval, bandwidth = 1;
if (start > end)
return start;
- in = (desc->bEndpointAddress & USB_DIR_IN);
- dir = in ? 'I' : 'O';
+
+ dir = usb_endpoint_dir_in(desc) ? 'I' : 'O';
+
if (speed == USB_SPEED_HIGH) {
switch (le16_to_cpu(desc->wMaxPacketSize) & (0x03 << 11)) {
case 1 << 11: bandwidth = 2; break;
@@ -204,7 +205,7 @@ static char *usb_dump_endpoint_descriptor (
break;
case USB_ENDPOINT_XFER_BULK:
type = "Bulk";
- if (speed == USB_SPEED_HIGH && !in) /* uframes per NAK */
+ if (speed == USB_SPEED_HIGH && dir == 'O') /* uframes per NAK */
interval = desc->bInterval;
else
interval = 0;
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index fed92be63b5e..3ed4cb2d56d9 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -561,7 +561,7 @@ static int usbdev_open(struct inode *inode, struct file *file)
dev = inode->i_private;
if (!dev)
goto out;
- ret = usb_autoresume_device(dev, 1);
+ ret = usb_autoresume_device(dev);
if (ret)
goto out;
@@ -609,7 +609,7 @@ static int usbdev_release(struct inode *inode, struct file *file)
releaseintf(ps, ifnum);
}
destroy_all_async(ps);
- usb_autosuspend_device(dev, 1);
+ usb_autosuspend_device(dev);
usb_unlock_device(dev);
usb_put_dev(dev);
put_pid(ps->disc_pid);
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 113e484c763e..d6eb5ce1dd1d 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -205,7 +205,7 @@ static int usb_probe_interface(struct device *dev)
if (id) {
dev_dbg(dev, "%s - got id\n", __FUNCTION__);
- error = usb_autoresume_device(udev, 1);
+ error = usb_autoresume_device(udev);
if (error)
return error;
@@ -229,7 +229,7 @@ static int usb_probe_interface(struct device *dev)
} else
intf->condition = USB_INTERFACE_BOUND;
- usb_autosuspend_device(udev, 1);
+ usb_autosuspend_device(udev);
}
return error;
@@ -247,7 +247,7 @@ static int usb_unbind_interface(struct device *dev)
/* Autoresume for set_interface call below */
udev = interface_to_usbdev(intf);
- error = usb_autoresume_device(udev, 1);
+ error = usb_autoresume_device(udev);
/* release all urbs for this interface */
usb_disable_interface(interface_to_usbdev(intf), intf);
@@ -265,7 +265,7 @@ static int usb_unbind_interface(struct device *dev)
intf->needs_remote_wakeup = 0;
if (!error)
- usb_autosuspend_device(udev, 1);
+ usb_autosuspend_device(udev);
return 0;
}
@@ -408,6 +408,16 @@ static int usb_match_one_id(struct usb_interface *interface,
(id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
return 0;
+ /* The interface class, subclass, and protocol should never be
+ * checked for a match if the device class is Vendor Specific,
+ * unless the match record specifies the Vendor ID. */
+ if (dev->descriptor.bDeviceClass == USB_CLASS_VENDOR_SPEC &&
+ !(id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
+ (id->match_flags & (USB_DEVICE_ID_MATCH_INT_CLASS |
+ USB_DEVICE_ID_MATCH_INT_SUBCLASS |
+ USB_DEVICE_ID_MATCH_INT_PROTOCOL)))
+ return 0;
+
if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) &&
(id->bInterfaceClass != intf->desc.bInterfaceClass))
return 0;
@@ -476,7 +486,17 @@ static int usb_match_one_id(struct usb_interface *interface,
* most general; they let drivers bind to any interface on a
* multiple-function device. Use the USB_INTERFACE_INFO
* macro, or its siblings, to match class-per-interface style
- * devices (as recorded in bDeviceClass).
+ * devices (as recorded in bInterfaceClass).
+ *
+ * Note that an entry created by USB_INTERFACE_INFO won't match
+ * any interface if the device class is set to Vendor-Specific.
+ * This is deliberate; according to the USB spec the meanings of
+ * the interface class/subclass/protocol for these devices are also
+ * vendor-specific, and hence matching against a standard product
+ * class wouldn't work anyway. If you really want to use an
+ * interface-based match for such a device, create a match record
+ * that also specifies the vendor ID. (Unforunately there isn't a
+ * standard macro for creating records like this.)
*
* Within those groups, remember that not all combinations are
* meaningful. For example, don't give a product version range
@@ -505,7 +525,7 @@ const struct usb_device_id *usb_match_id(struct usb_interface *interface,
}
EXPORT_SYMBOL_GPL_FUTURE(usb_match_id);
-int usb_device_match(struct device *dev, struct device_driver *drv)
+static int usb_device_match(struct device *dev, struct device_driver *drv)
{
/* devices and interfaces are handled separately */
if (is_usb_device(dev)) {
@@ -790,7 +810,7 @@ EXPORT_SYMBOL_GPL_FUTURE(usb_deregister);
#ifdef CONFIG_PM
/* Caller has locked udev's pm_mutex */
-static int suspend_device(struct usb_device *udev, pm_message_t msg)
+static int usb_suspend_device(struct usb_device *udev, pm_message_t msg)
{
struct usb_device_driver *udriver;
int status = 0;
@@ -817,7 +837,7 @@ done:
}
/* Caller has locked udev's pm_mutex */
-static int resume_device(struct usb_device *udev)
+static int usb_resume_device(struct usb_device *udev)
{
struct usb_device_driver *udriver;
int status = 0;
@@ -843,7 +863,7 @@ done:
}
/* Caller has locked intf's usb_device's pm mutex */
-static int suspend_interface(struct usb_interface *intf, pm_message_t msg)
+static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg)
{
struct usb_driver *driver;
int status = 0;
@@ -880,7 +900,7 @@ done:
}
/* Caller has locked intf's usb_device's pm_mutex */
-static int resume_interface(struct usb_interface *intf)
+static int usb_resume_interface(struct usb_interface *intf)
{
struct usb_driver *driver;
int status = 0;
@@ -920,6 +940,44 @@ done:
return status;
}
+#ifdef CONFIG_USB_SUSPEND
+
+/* Internal routine to check whether we may autosuspend a device. */
+static int autosuspend_check(struct usb_device *udev)
+{
+ int i;
+ struct usb_interface *intf;
+
+ /* For autosuspend, fail fast if anything is in use.
+ * Also fail if any interfaces require remote wakeup but it
+ * isn't available. */
+ udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
+ if (udev->pm_usage_cnt > 0)
+ return -EBUSY;
+ if (udev->actconfig) {
+ for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+ intf = udev->actconfig->interface[i];
+ if (!is_active(intf))
+ continue;
+ if (intf->pm_usage_cnt > 0)
+ return -EBUSY;
+ if (intf->needs_remote_wakeup &&
+ !udev->do_remote_wakeup) {
+ dev_dbg(&udev->dev, "remote wakeup needed "
+ "for autosuspend\n");
+ return -EOPNOTSUPP;
+ }
+ }
+ }
+ return 0;
+}
+
+#else
+
+#define autosuspend_check(udev) 0
+
+#endif
+
/**
* usb_suspend_both - suspend a USB device and its interfaces
* @udev: the usb_device to suspend
@@ -971,52 +1029,34 @@ int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
- /* For autosuspend, fail fast if anything is in use.
- * Also fail if any interfaces require remote wakeup but it
- * isn't available. */
if (udev->auto_pm) {
- if (udev->pm_usage_cnt > 0)
- return -EBUSY;
- if (udev->actconfig) {
- for (; i < udev->actconfig->desc.bNumInterfaces; i++) {
- intf = udev->actconfig->interface[i];
- if (!is_active(intf))
- continue;
- if (intf->pm_usage_cnt > 0)
- return -EBUSY;
- if (intf->needs_remote_wakeup &&
- !udev->do_remote_wakeup) {
- dev_dbg(&udev->dev,
- "remote wakeup needed for autosuspend\n");
- return -EOPNOTSUPP;
- }
- }
- i = 0;
- }
+ status = autosuspend_check(udev);
+ if (status < 0)
+ return status;
}
/* Suspend all the interfaces and then udev itself */
if (udev->actconfig) {
for (; i < udev->actconfig->desc.bNumInterfaces; i++) {
intf = udev->actconfig->interface[i];
- status = suspend_interface(intf, msg);
+ status = usb_suspend_interface(intf, msg);
if (status != 0)
break;
}
}
if (status == 0)
- status = suspend_device(udev, msg);
+ status = usb_suspend_device(udev, msg);
/* If the suspend failed, resume interfaces that did get suspended */
if (status != 0) {
while (--i >= 0) {
intf = udev->actconfig->interface[i];
- resume_interface(intf);
+ usb_resume_interface(intf);
}
/* If the suspend succeeded, propagate it up the tree */
} else if (parent)
- usb_autosuspend_device(parent, 0);
+ usb_autosuspend_device(parent);
// dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
return status;
@@ -1064,9 +1104,25 @@ int usb_resume_both(struct usb_device *udev)
/* Propagate the resume up the tree, if necessary */
if (udev->state == USB_STATE_SUSPENDED) {
if (parent) {
- usb_pm_lock(parent);
- parent->auto_pm = 1;
- status = usb_resume_both(parent);
+ status = usb_autoresume_device(parent);
+ if (status == 0) {
+ status = usb_resume_device(udev);
+ if (status) {
+ usb_autosuspend_device(parent);
+
+ /* It's possible usb_resume_device()
+ * failed after the port was
+ * unsuspended, causing udev to be
+ * logically disconnected. We don't
+ * want usb_disconnect() to autosuspend
+ * the parent again, so tell it that
+ * udev disconnected while still
+ * suspended. */
+ if (udev->state ==
+ USB_STATE_NOTATTACHED)
+ udev->discon_suspended = 1;
+ }
+ }
} else {
/* We can't progagate beyond the USB subsystem,
@@ -1075,24 +1131,20 @@ int usb_resume_both(struct usb_device *udev)
if (udev->dev.parent->power.power_state.event !=
PM_EVENT_ON)
status = -EHOSTUNREACH;
- }
- if (status == 0)
- status = resume_device(udev);
- if (parent)
- usb_pm_unlock(parent);
+ else
+ status = usb_resume_device(udev);
+ }
} else {
/* Needed only for setting udev->dev.power.power_state.event
* and for possible debugging message. */
- status = resume_device(udev);
+ status = usb_resume_device(udev);
}
- /* Now the parent won't suspend until we are finished */
-
if (status == 0 && udev->actconfig) {
for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
intf = udev->actconfig->interface[i];
- resume_interface(intf);
+ usb_resume_interface(intf);
}
}
@@ -1102,39 +1154,53 @@ int usb_resume_both(struct usb_device *udev)
#ifdef CONFIG_USB_SUSPEND
+/* Internal routine to adjust a device's usage counter and change
+ * its autosuspend state.
+ */
+static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt)
+{
+ int status = 0;
+
+ usb_pm_lock(udev);
+ udev->pm_usage_cnt += inc_usage_cnt;
+ WARN_ON(udev->pm_usage_cnt < 0);
+ if (inc_usage_cnt >= 0 && udev->pm_usage_cnt > 0) {
+ udev->auto_pm = 1;
+ status = usb_resume_both(udev);
+ if (status != 0)
+ udev->pm_usage_cnt -= inc_usage_cnt;
+ } else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0)
+ queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
+ USB_AUTOSUSPEND_DELAY);
+ usb_pm_unlock(udev);
+ return status;
+}
+
/**
* usb_autosuspend_device - delayed autosuspend of a USB device and its interfaces
* @udev: the usb_device to autosuspend
- * @dec_usage_cnt: flag to decrement @udev's PM-usage counter
*
* This routine should be called when a core subsystem is finished using
* @udev and wants to allow it to autosuspend. Examples would be when
* @udev's device file in usbfs is closed or after a configuration change.
*
- * @dec_usage_cnt should be 1 if the subsystem previously incremented
- * @udev's usage counter (such as by passing 1 to usb_autoresume_device);
- * otherwise it should be 0.
- *
- * If the usage counter for @udev or any of its active interfaces is greater
- * than 0, the autosuspend request will not be queued. (If an interface
- * driver does not support autosuspend then its usage counter is permanently
- * positive.) Likewise, if an interface driver requires remote-wakeup
- * capability during autosuspend but remote wakeup is disabled, the
- * autosuspend will fail.
+ * @udev's usage counter is decremented. If it or any of the usage counters
+ * for an active interface is greater than 0, no autosuspend request will be
+ * queued. (If an interface driver does not support autosuspend then its
+ * usage counter is permanently positive.) Furthermore, if an interface
+ * driver requires remote-wakeup capability during autosuspend but remote
+ * wakeup is disabled, the autosuspend will fail.
*
* Often the caller will hold @udev's device lock, but this is not
* necessary.
*
* This routine can run only in process context.
*/
-void usb_autosuspend_device(struct usb_device *udev, int dec_usage_cnt)
+void usb_autosuspend_device(struct usb_device *udev)
{
- usb_pm_lock(udev);
- udev->pm_usage_cnt -= dec_usage_cnt;
- if (udev->pm_usage_cnt <= 0)
- queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
- USB_AUTOSUSPEND_DELAY);
- usb_pm_unlock(udev);
+ int status;
+
+ status = usb_autopm_do_device(udev, -1);
// dev_dbg(&udev->dev, "%s: cnt %d\n",
// __FUNCTION__, udev->pm_usage_cnt);
}
@@ -1142,44 +1208,59 @@ void usb_autosuspend_device(struct usb_device *udev, int dec_usage_cnt)
/**
* usb_autoresume_device - immediately autoresume a USB device and its interfaces
* @udev: the usb_device to autoresume
- * @inc_usage_cnt: flag to increment @udev's PM-usage counter
*
* This routine should be called when a core subsystem wants to use @udev
- * and needs to guarantee that it is not suspended. In addition, the
- * caller can prevent @udev from being autosuspended subsequently. (Note
- * that this will not prevent suspend events originating in the PM core.)
- * Examples would be when @udev's device file in usbfs is opened (autosuspend
- * should be prevented until the file is closed) or when a remote-wakeup
- * request is received (later autosuspends should not be prevented).
+ * and needs to guarantee that it is not suspended. No autosuspend will
+ * occur until usb_autosuspend_device is called. (Note that this will not
+ * prevent suspend events originating in the PM core.) Examples would be
+ * when @udev's device file in usbfs is opened or when a remote-wakeup
+ * request is received.
*
- * @inc_usage_cnt should be 1 to increment @udev's usage counter and prevent
- * autosuspends. This prevention will persist until the usage counter is
- * decremented again (such as by passing 1 to usb_autosuspend_device).
- * Otherwise @inc_usage_cnt should be 0 to leave the usage counter unchanged.
- * Regardless, if the autoresume fails then the usage counter is not
- * incremented.
+ * @udev's usage counter is incremented to prevent subsequent autosuspends.
+ * However if the autoresume fails then the usage counter is re-decremented.
*
* Often the caller will hold @udev's device lock, but this is not
* necessary (and attempting it might cause deadlock).
*
* This routine can run only in process context.
*/
-int usb_autoresume_device(struct usb_device *udev, int inc_usage_cnt)
+int usb_autoresume_device(struct usb_device *udev)
{
int status;
- usb_pm_lock(udev);
- udev->pm_usage_cnt += inc_usage_cnt;
- udev->auto_pm = 1;
- status = usb_resume_both(udev);
- if (status != 0)
- udev->pm_usage_cnt -= inc_usage_cnt;
- usb_pm_unlock(udev);
+ status = usb_autopm_do_device(udev, 1);
// dev_dbg(&udev->dev, "%s: status %d cnt %d\n",
// __FUNCTION__, status, udev->pm_usage_cnt);
return status;
}
+/* Internal routine to adjust an interface's usage counter and change
+ * its device's autosuspend state.
+ */
+static int usb_autopm_do_interface(struct usb_interface *intf,
+ int inc_usage_cnt)
+{
+ struct usb_device *udev = interface_to_usbdev(intf);
+ int status = 0;
+
+ usb_pm_lock(udev);
+ if (intf->condition == USB_INTERFACE_UNBOUND)
+ status = -ENODEV;
+ else {
+ intf->pm_usage_cnt += inc_usage_cnt;
+ if (inc_usage_cnt >= 0 && intf->pm_usage_cnt > 0) {
+ udev->auto_pm = 1;
+ status = usb_resume_both(udev);
+ if (status != 0)
+ intf->pm_usage_cnt -= inc_usage_cnt;
+ } else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0)
+ queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
+ USB_AUTOSUSPEND_DELAY);
+ }
+ usb_pm_unlock(udev);
+ return status;
+}
+
/**
* usb_autopm_put_interface - decrement a USB interface's PM-usage counter
* @intf: the usb_interface whose counter should be decremented
@@ -1213,17 +1294,11 @@ int usb_autoresume_device(struct usb_device *udev, int inc_usage_cnt)
*/
void usb_autopm_put_interface(struct usb_interface *intf)
{
- struct usb_device *udev = interface_to_usbdev(intf);
+ int status;
- usb_pm_lock(udev);
- if (intf->condition != USB_INTERFACE_UNBOUND &&
- --intf->pm_usage_cnt <= 0) {
- queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
- USB_AUTOSUSPEND_DELAY);
- }
- usb_pm_unlock(udev);
- // dev_dbg(&intf->dev, "%s: cnt %d\n",
- // __FUNCTION__, intf->pm_usage_cnt);
+ status = usb_autopm_do_interface(intf, -1);
+ // dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
+ // __FUNCTION__, status, intf->pm_usage_cnt);
}
EXPORT_SYMBOL_GPL(usb_autopm_put_interface);
@@ -1260,26 +1335,37 @@ EXPORT_SYMBOL_GPL(usb_autopm_put_interface);
*/
int usb_autopm_get_interface(struct usb_interface *intf)
{
- struct usb_device *udev = interface_to_usbdev(intf);
- int status;
+ int status;
- usb_pm_lock(udev);
- if (intf->condition == USB_INTERFACE_UNBOUND)
- status = -ENODEV;
- else {
- ++intf->pm_usage_cnt;
- udev->auto_pm = 1;
- status = usb_resume_both(udev);
- if (status != 0)
- --intf->pm_usage_cnt;
- }
- usb_pm_unlock(udev);
+ status = usb_autopm_do_interface(intf, 1);
// dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
// __FUNCTION__, status, intf->pm_usage_cnt);
return status;
}
EXPORT_SYMBOL_GPL(usb_autopm_get_interface);
+/**
+ * usb_autopm_set_interface - set a USB interface's autosuspend state
+ * @intf: the usb_interface whose state should be set
+ *
+ * This routine sets the autosuspend state of @intf's device according
+ * to @intf's usage counter, which the caller must have set previously.
+ * If the counter is <= 0, the device is autosuspended (if it isn't
+ * already suspended and if nothing else prevents the autosuspend). If
+ * the counter is > 0, the device is autoresumed (if it isn't already
+ * awake).
+ */
+int usb_autopm_set_interface(struct usb_interface *intf)
+{
+ int status;
+
+ status = usb_autopm_do_interface(intf, 0);
+ // dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
+ // __FUNCTION__, status, intf->pm_usage_cnt);
+ return status;
+}
+EXPORT_SYMBOL_GPL(usb_autopm_set_interface);
+
#endif /* CONFIG_USB_SUSPEND */
static int usb_suspend(struct device *dev, pm_message_t message)
diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c
index 3b2d137912be..c505b767cee1 100644
--- a/drivers/usb/core/endpoint.c
+++ b/drivers/usb/core/endpoint.c
@@ -10,15 +10,20 @@
*/
#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/idr.h>
#include <linux/usb.h>
#include "usb.h"
-/* endpoint stuff */
+#define MAX_ENDPOINT_MINORS (64*128*32)
+static int usb_endpoint_major;
+static DEFINE_IDR(endpoint_idr);
struct ep_device {
struct usb_endpoint_descriptor *desc;
struct usb_device *udev;
struct device dev;
+ int minor;
};
#define to_ep_device(_dev) \
container_of(_dev, struct ep_device, dev)
@@ -152,6 +157,55 @@ static struct attribute_group ep_dev_attr_grp = {
.attrs = ep_dev_attrs,
};
+static int usb_endpoint_major_init(void)
+{
+ dev_t dev;
+ int error;
+
+ error = alloc_chrdev_region(&dev, 0, MAX_ENDPOINT_MINORS,
+ "usb_endpoint");
+ if (error) {
+ err("unable to get a dynamic major for usb endpoints");
+ return error;
+ }
+ usb_endpoint_major = MAJOR(dev);
+
+ return error;
+}
+
+static void usb_endpoint_major_cleanup(void)
+{
+ unregister_chrdev_region(MKDEV(usb_endpoint_major, 0),
+ MAX_ENDPOINT_MINORS);
+}
+
+static int endpoint_get_minor(struct ep_device *ep_dev)
+{
+ static DEFINE_MUTEX(minor_lock);
+ int retval = -ENOMEM;
+ int id;
+
+ mutex_lock(&minor_lock);
+ if (idr_pre_get(&endpoint_idr, GFP_KERNEL) == 0)
+ goto exit;
+
+ retval = idr_get_new(&endpoint_idr, ep_dev, &id);
+ if (retval < 0) {
+ if (retval == -EAGAIN)
+ retval = -ENOMEM;
+ goto exit;
+ }
+ ep_dev->minor = id & MAX_ID_MASK;
+exit:
+ mutex_unlock(&minor_lock);
+ return retval;
+}
+
+static void endpoint_free_minor(struct ep_device *ep_dev)
+{
+ idr_remove(&endpoint_idr, ep_dev->minor);
+}
+
static struct endpoint_class {
struct kref kref;
struct class *class;
@@ -176,11 +230,20 @@ static int init_endpoint_class(void)
ep_class->class = class_create(THIS_MODULE, "usb_endpoint");
if (IS_ERR(ep_class->class)) {
result = IS_ERR(ep_class->class);
- kfree(ep_class);
- ep_class = NULL;
- goto exit;
+ goto class_create_error;
}
+ result = usb_endpoint_major_init();
+ if (result)
+ goto endpoint_major_error;
+
+ goto exit;
+
+endpoint_major_error:
+ class_destroy(ep_class->class);
+class_create_error:
+ kfree(ep_class);
+ ep_class = NULL;
exit:
return result;
}
@@ -191,6 +254,7 @@ static void release_endpoint_class(struct kref *kref)
class_destroy(ep_class->class);
kfree(ep_class);
ep_class = NULL;
+ usb_endpoint_major_cleanup();
}
static void destroy_endpoint_class(void)
@@ -213,7 +277,6 @@ int usb_create_ep_files(struct device *parent,
{
char name[8];
struct ep_device *ep_dev;
- int minor;
int retval;
retval = init_endpoint_class();
@@ -226,12 +289,16 @@ int usb_create_ep_files(struct device *parent,
goto error_alloc;
}
- /* fun calculation to determine the minor of this endpoint */
- minor = (((udev->bus->busnum - 1) * 128) * 16) + (udev->devnum - 1);
+ retval = endpoint_get_minor(ep_dev);
+ if (retval) {
+ dev_err(parent, "can not allocate minor number for %s",
+ ep_dev->dev.bus_id);
+ goto error_register;
+ }
ep_dev->desc = &endpoint->desc;
ep_dev->udev = udev;
- ep_dev->dev.devt = MKDEV(442, minor); // FIXME fake number...
+ ep_dev->dev.devt = MKDEV(usb_endpoint_major, ep_dev->minor);
ep_dev->dev.class = ep_class->class;
ep_dev->dev.parent = parent;
ep_dev->dev.release = ep_device_release;
@@ -241,7 +308,7 @@ int usb_create_ep_files(struct device *parent,
retval = device_register(&ep_dev->dev);
if (retval)
- goto error_register;
+ goto error_chrdev;
retval = sysfs_create_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
if (retval)
goto error_group;
@@ -261,6 +328,9 @@ error_group:
destroy_endpoint_class();
return retval;
+error_chrdev:
+ endpoint_free_minor(ep_dev);
+
error_register:
kfree(ep_dev);
error_alloc:
@@ -271,14 +341,16 @@ exit:
void usb_remove_ep_files(struct usb_host_endpoint *endpoint)
{
+ struct ep_device *ep_dev = endpoint->ep_dev;
- if (endpoint->ep_dev) {
+ if (ep_dev) {
char name[8];
sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress);
- sysfs_remove_link(&endpoint->ep_dev->dev.parent->kobj, name);
- sysfs_remove_group(&endpoint->ep_dev->dev.kobj, &ep_dev_attr_grp);
- device_unregister(&endpoint->ep_dev->dev);
+ sysfs_remove_link(&ep_dev->dev.parent->kobj, name);
+ sysfs_remove_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
+ endpoint_free_minor(ep_dev);
+ device_unregister(&ep_dev->dev);
endpoint->ep_dev = NULL;
destroy_endpoint_class();
}
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index afa2dd203329..10064af65d17 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -256,7 +256,9 @@ static const u8 hs_rh_config_descriptor [] = {
0x05, /* __u8 ep_bDescriptorType; Endpoint */
0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */
0x03, /* __u8 ep_bmAttributes; Interrupt */
- 0x02, 0x00, /* __le16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
+ /* __le16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8)
+ * see hub.c:hub_configure() for details. */
+ (USB_MAXCHILDREN + 1 + 7) / 8, 0x00,
0x0c /* __u8 ep_bInterval; (256ms -- usb 2.0 spec) */
};
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index ad0ffbe8f7d7..39186db1015f 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -31,6 +31,47 @@
#include "hcd.h"
#include "hub.h"
+struct usb_hub {
+ struct device *intfdev; /* the "interface" device */
+ struct usb_device *hdev;
+ struct urb *urb; /* for interrupt polling pipe */
+
+ /* buffer for urb ... with extra space in case of babble */
+ char (*buffer)[8];
+ dma_addr_t buffer_dma; /* DMA address for buffer */
+ union {
+ struct usb_hub_status hub;
+ struct usb_port_status port;
+ } *status; /* buffer for status reports */
+
+ int error; /* last reported error */
+ int nerrors; /* track consecutive errors */
+
+ struct list_head event_list; /* hubs w/data or errs ready */
+ unsigned long event_bits[1]; /* status change bitmask */
+ unsigned long change_bits[1]; /* ports with logical connect
+ status change */
+ unsigned long busy_bits[1]; /* ports being reset or
+ resumed */
+#if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */
+#error event_bits[] is too short!
+#endif
+
+ struct usb_hub_descriptor *descriptor; /* class descriptor */
+ struct usb_tt tt; /* Transaction Translator */
+
+ unsigned mA_per_port; /* current for each child */
+
+ unsigned limited_power:1;
+ unsigned quiescing:1;
+ unsigned activating:1;
+
+ unsigned has_indicators:1;
+ u8 indicator[USB_MAXCHILDREN];
+ struct work_struct leds;
+};
+
+
/* Protect struct usb_device->state and ->children members
* Note: Both are also protected by ->dev.sem, except that ->state can
* change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */
@@ -45,6 +86,16 @@ static DECLARE_WAIT_QUEUE_HEAD(khubd_wait);
static struct task_struct *khubd_task;
+/* multithreaded probe logic */
+static int multithread_probe =
+#ifdef CONFIG_USB_MULTITHREAD_PROBE
+ 1;
+#else
+ 0;
+#endif
+module_param(multithread_probe, bool, S_IRUGO);
+MODULE_PARM_DESC(multithread_probe, "Run each USB device probe in a new thread");
+
/* cycle leds on hubs that aren't blinking for attention */
static int blinkenlights = 0;
module_param (blinkenlights, bool, S_IRUGO);
@@ -277,6 +328,9 @@ static void kick_khubd(struct usb_hub *hub)
{
unsigned long flags;
+ /* Suppress autosuspend until khubd runs */
+ to_usb_interface(hub->intfdev)->pm_usage_cnt = 1;
+
spin_lock_irqsave(&hub_event_lock, flags);
if (list_empty(&hub->event_list)) {
list_add_tail(&hub->event_list, &hub_event_list);
@@ -459,7 +513,6 @@ static void hub_quiesce(struct usb_hub *hub)
/* (nonblocking) khubd and related activity won't re-trigger */
hub->quiescing = 1;
hub->activating = 0;
- hub->resume_root_hub = 0;
/* (blocking) stop khubd and related activity */
usb_kill_urb(hub->urb);
@@ -475,7 +528,7 @@ static void hub_activate(struct usb_hub *hub)
hub->quiescing = 0;
hub->activating = 1;
- hub->resume_root_hub = 0;
+
status = usb_submit_urb(hub->urb, GFP_NOIO);
if (status < 0)
dev_err(hub->intfdev, "activate --> %d\n", status);
@@ -761,7 +814,12 @@ static int hub_configure(struct usb_hub *hub,
dev_dbg(hub_dev, "%sover-current condition exists\n",
(hubstatus & HUB_STATUS_OVERCURRENT) ? "" : "no ");
- /* set up the interrupt endpoint */
+ /* set up the interrupt endpoint
+ * We use the EP's maxpacket size instead of (PORTS+1+7)/8
+ * bytes as USB2.0[11.12.3] says because some hubs are known
+ * to send more data (and thus cause overflow). For root hubs,
+ * maxpktsize is defined in hcd.c's fake endpoint descriptors
+ * to be big enough for at least USB_MAXCHILDREN ports. */
pipe = usb_rcvintpipe(hdev, endpoint->bEndpointAddress);
maxp = usb_maxpacket(hdev, pipe, usb_pipeout(pipe));
@@ -885,6 +943,7 @@ descriptor_error:
INIT_DELAYED_WORK(&hub->leds, led_work);
usb_set_intfdata (intf, hub);
+ intf->needs_remote_wakeup = 1;
if (hdev->speed == USB_SPEED_HIGH)
highspeed_hubs++;
@@ -982,6 +1041,8 @@ static void recursively_mark_NOTATTACHED(struct usb_device *udev)
if (udev->children[i])
recursively_mark_NOTATTACHED(udev->children[i]);
}
+ if (udev->state == USB_STATE_SUSPENDED)
+ udev->discon_suspended = 1;
udev->state = USB_STATE_NOTATTACHED;
}
@@ -1171,6 +1232,14 @@ void usb_disconnect(struct usb_device **pdev)
*pdev = NULL;
spin_unlock_irq(&device_state_lock);
+ /* Decrement the parent's count of unsuspended children */
+ if (udev->parent) {
+ usb_pm_lock(udev);
+ if (!udev->discon_suspended)
+ usb_autosuspend_device(udev->parent);
+ usb_pm_unlock(udev);
+ }
+
put_device(&udev->dev);
}
@@ -1193,29 +1262,17 @@ static inline void show_string(struct usb_device *udev, char *id, char *string)
static int __usb_port_suspend(struct usb_device *, int port1);
#endif
-/**
- * usb_new_device - perform initial device setup (usbcore-internal)
- * @udev: newly addressed device (in ADDRESS state)
- *
- * This is called with devices which have been enumerated, but not yet
- * configured. The device descriptor is available, but not descriptors
- * for any device configuration. The caller must have locked either
- * the parent hub (if udev is a normal device) or else the
- * usb_bus_list_lock (if udev is a root hub). The parent's pointer to
- * udev has already been installed, but udev is not yet visible through
- * sysfs or other filesystem code.
- *
- * Returns 0 for success (device is configured and listed, with its
- * interfaces, in sysfs); else a negative errno value.
- *
- * This call is synchronous, and may not be used in an interrupt context.
- *
- * Only the hub driver or root-hub registrar should ever call this.
- */
-int usb_new_device(struct usb_device *udev)
+static int __usb_new_device(void *void_data)
{
+ struct usb_device *udev = void_data;
int err;
+ /* Lock ourself into memory in order to keep a probe sequence
+ * sleeping in a new thread from allowing us to be unloaded.
+ */
+ if (!try_module_get(THIS_MODULE))
+ return -EINVAL;
+
err = usb_get_configuration(udev);
if (err < 0) {
dev_err(&udev->dev, "can't read configurations, error %d\n",
@@ -1311,13 +1368,56 @@ int usb_new_device(struct usb_device *udev)
goto fail;
}
- return 0;
+ /* Increment the parent's count of unsuspended children */
+ if (udev->parent)
+ usb_autoresume_device(udev->parent);
+
+exit:
+ module_put(THIS_MODULE);
+ return err;
fail:
usb_set_device_state(udev, USB_STATE_NOTATTACHED);
- return err;
+ goto exit;
}
+/**
+ * usb_new_device - perform initial device setup (usbcore-internal)
+ * @udev: newly addressed device (in ADDRESS state)
+ *
+ * This is called with devices which have been enumerated, but not yet
+ * configured. The device descriptor is available, but not descriptors
+ * for any device configuration. The caller must have locked either
+ * the parent hub (if udev is a normal device) or else the
+ * usb_bus_list_lock (if udev is a root hub). The parent's pointer to
+ * udev has already been installed, but udev is not yet visible through
+ * sysfs or other filesystem code.
+ *
+ * The return value for this function depends on if the
+ * multithread_probe variable is set or not. If it's set, it will
+ * return a if the probe thread was successfully created or not. If the
+ * variable is not set, it will return if the device is configured
+ * properly or not. interfaces, in sysfs); else a negative errno value.
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ *
+ * Only the hub driver or root-hub registrar should ever call this.
+ */
+int usb_new_device(struct usb_device *udev)
+{
+ struct task_struct *probe_task;
+ int ret = 0;
+
+ if (multithread_probe) {
+ probe_task = kthread_run(__usb_new_device, udev,
+ "usb-probe-%s", udev->devnum);
+ if (IS_ERR(probe_task))
+ ret = PTR_ERR(probe_task);
+ } else
+ ret = __usb_new_device(udev);
+
+ return ret;
+}
static int hub_port_status(struct usb_hub *hub, int port1,
u16 *status, u16 *change)
@@ -1325,10 +1425,12 @@ static int hub_port_status(struct usb_hub *hub, int port1,
int ret;
ret = get_port_status(hub->hdev, port1, &hub->status->port);
- if (ret < 0)
+ if (ret < 4) {
dev_err (hub->intfdev,
"%s failed (err = %d)\n", __FUNCTION__, ret);
- else {
+ if (ret >= 0)
+ ret = -EIO;
+ } else {
*status = le16_to_cpu(hub->status->port.wPortStatus);
*change = le16_to_cpu(hub->status->port.wPortChange);
ret = 0;
@@ -1676,6 +1778,12 @@ static int
hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
{
int status;
+ u16 portchange, portstatus;
+
+ /* Skip the initial Clear-Suspend step for a remote wakeup */
+ status = hub_port_status(hub, port1, &portstatus, &portchange);
+ if (status == 0 && !(portstatus & USB_PORT_STAT_SUSPEND))
+ goto SuspendCleared;
// dev_dbg(hub->intfdev, "resume port %d\n", port1);
@@ -1689,9 +1797,6 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
"can't resume port %d, status %d\n",
port1, status);
} else {
- u16 devstatus;
- u16 portchange;
-
/* drive resume for at least 20 msec */
if (udev)
dev_dbg(&udev->dev, "usb %sresume\n",
@@ -1706,16 +1811,15 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
* stop resume signaling. Then finish the resume
* sequence.
*/
- devstatus = portchange = 0;
- status = hub_port_status(hub, port1,
- &devstatus, &portchange);
+ status = hub_port_status(hub, port1, &portstatus, &portchange);
+SuspendCleared:
if (status < 0
- || (devstatus & LIVE_FLAGS) != LIVE_FLAGS
- || (devstatus & USB_PORT_STAT_SUSPEND) != 0
+ || (portstatus & LIVE_FLAGS) != LIVE_FLAGS
+ || (portstatus & USB_PORT_STAT_SUSPEND) != 0
) {
dev_dbg(hub->intfdev,
"port %d status %04x.%04x after resume, %d\n",
- port1, portchange, devstatus, status);
+ port1, portchange, portstatus, status);
if (status >= 0)
status = -ENODEV;
} else {
@@ -1776,23 +1880,16 @@ static int remote_wakeup(struct usb_device *udev)
{
int status = 0;
- /* All this just to avoid sending a port-resume message
- * to the parent hub! */
-
usb_lock_device(udev);
- usb_pm_lock(udev);
if (udev->state == USB_STATE_SUSPENDED) {
dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-");
- /* TRSMRCY = 10 msec */
- msleep(10);
- status = finish_port_resume(udev);
+ status = usb_autoresume_device(udev);
+
+ /* Give the interface drivers a chance to do something,
+ * then autosuspend the device again. */
if (status == 0)
- udev->dev.power.power_state.event = PM_EVENT_ON;
+ usb_autosuspend_device(udev);
}
- usb_pm_unlock(udev);
-
- if (status == 0)
- usb_autoresume_device(udev, 0);
usb_unlock_device(udev);
return status;
}
@@ -1856,6 +1953,8 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
}
}
+ dev_dbg(&intf->dev, "%s\n", __FUNCTION__);
+
/* "global suspend" of the downstream HC-to-USB interface */
if (!hdev->parent) {
struct usb_bus *bus = hdev->bus;
@@ -1878,10 +1977,12 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
static int hub_resume(struct usb_interface *intf)
{
- struct usb_device *hdev = interface_to_usbdev(intf);
struct usb_hub *hub = usb_get_intfdata (intf);
+ struct usb_device *hdev = hub->hdev;
int status;
+ dev_dbg(&intf->dev, "%s\n", __FUNCTION__);
+
/* "global resume" of the downstream HC-to-USB interface */
if (!hdev->parent) {
struct usb_bus *bus = hdev->bus;
@@ -1920,7 +2021,6 @@ void usb_resume_root_hub(struct usb_device *hdev)
{
struct usb_hub *hub = hdev_to_hub(hdev);
- hub->resume_root_hub = 1;
kick_khubd(hub);
}
@@ -2557,16 +2657,13 @@ static void hub_events(void)
intf = to_usb_interface(hub->intfdev);
hub_dev = &intf->dev;
- i = hub->resume_root_hub;
-
- dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x%s\n",
+ dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x\n",
hdev->state, hub->descriptor
? hub->descriptor->bNbrPorts
: 0,
/* NOTE: expects max 15 ports... */
(u16) hub->change_bits[0],
- (u16) hub->event_bits[0],
- i ? ", resume root" : "");
+ (u16) hub->event_bits[0]);
usb_get_intf(intf);
spin_unlock_irq(&hub_event_lock);
@@ -2587,16 +2684,16 @@ static void hub_events(void)
goto loop;
}
- /* Is this is a root hub wanting to reactivate the downstream
- * ports? If so, be sure the interface resumes even if its
- * stub "device" node was never suspended.
- */
- if (i)
- usb_autoresume_device(hdev, 0);
+ /* Autoresume */
+ ret = usb_autopm_get_interface(intf);
+ if (ret) {
+ dev_dbg(hub_dev, "Can't autoresume: %d\n", ret);
+ goto loop;
+ }
- /* If this is an inactive or suspended hub, do nothing */
+ /* If this is an inactive hub, do nothing */
if (hub->quiescing)
- goto loop;
+ goto loop_autopm;
if (hub->error) {
dev_dbg (hub_dev, "resetting for error %d\n",
@@ -2606,7 +2703,7 @@ static void hub_events(void)
if (ret) {
dev_dbg (hub_dev,
"error resetting hub: %d\n", ret);
- goto loop;
+ goto loop_autopm;
}
hub->nerrors = 0;
@@ -2734,6 +2831,10 @@ static void hub_events(void)
if (!hdev->parent && !hub->busy_bits[0])
usb_enable_root_hub_irq(hdev->bus);
+loop_autopm:
+ /* Allow autosuspend if we're not going to run again */
+ if (list_empty(&hub->event_list))
+ usb_autopm_enable(intf);
loop:
usb_unlock_device(hdev);
usb_put_intf(intf);
@@ -2775,6 +2876,7 @@ static struct usb_driver hub_driver = {
.post_reset = hub_post_reset,
.ioctl = hub_ioctl,
.id_table = hub_id_table,
+ .supports_autosuspend = 1,
};
int usb_hub_init(void)
@@ -2999,7 +3101,7 @@ int usb_reset_composite_device(struct usb_device *udev,
}
/* Prevent autosuspend during the reset */
- usb_autoresume_device(udev, 1);
+ usb_autoresume_device(udev);
if (iface && iface->condition != USB_INTERFACE_BINDING)
iface = NULL;
@@ -3042,7 +3144,7 @@ int usb_reset_composite_device(struct usb_device *udev,
}
}
- usb_autosuspend_device(udev, 1);
+ usb_autosuspend_device(udev);
return ret;
}
EXPORT_SYMBOL(usb_reset_composite_device);
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
index 035d3ef35888..cf9559c6c9b6 100644
--- a/drivers/usb/core/hub.h
+++ b/drivers/usb/core/hub.h
@@ -192,45 +192,4 @@ struct usb_tt_clear {
extern void usb_hub_tt_clear_buffer (struct usb_device *dev, int pipe);
-struct usb_hub {
- struct device *intfdev; /* the "interface" device */
- struct usb_device *hdev;
- struct urb *urb; /* for interrupt polling pipe */
-
- /* buffer for urb ... with extra space in case of babble */
- char (*buffer)[8];
- dma_addr_t buffer_dma; /* DMA address for buffer */
- union {
- struct usb_hub_status hub;
- struct usb_port_status port;
- } *status; /* buffer for status reports */
-
- int error; /* last reported error */
- int nerrors; /* track consecutive errors */
-
- struct list_head event_list; /* hubs w/data or errs ready */
- unsigned long event_bits[1]; /* status change bitmask */
- unsigned long change_bits[1]; /* ports with logical connect
- status change */
- unsigned long busy_bits[1]; /* ports being reset or
- resumed */
-#if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */
-#error event_bits[] is too short!
-#endif
-
- struct usb_hub_descriptor *descriptor; /* class descriptor */
- struct usb_tt tt; /* Transaction Translator */
-
- unsigned mA_per_port; /* current for each child */
-
- unsigned limited_power:1;
- unsigned quiescing:1;
- unsigned activating:1;
- unsigned resume_root_hub:1;
-
- unsigned has_indicators:1;
- enum hub_led_mode indicator[USB_MAXCHILDREN];
- struct delayed_work leds;
-};
-
#endif /* __LINUX_HUB_H */
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 89572bc021b1..7390b67c609d 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -764,7 +764,7 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
err = -EINVAL;
goto errout;
} else {
- dev->have_langid = -1;
+ dev->have_langid = 1;
dev->string_langid = tbuf[2] | (tbuf[3]<< 8);
/* always use the first langid listed */
dev_dbg (&dev->dev, "default language 0x%04x\n",
@@ -1398,7 +1398,7 @@ free_interfaces:
}
/* Wake up the device so we can send it the Set-Config request */
- ret = usb_autoresume_device(dev, 1);
+ ret = usb_autoresume_device(dev);
if (ret)
goto free_interfaces;
@@ -1421,7 +1421,7 @@ free_interfaces:
dev->actconfig = cp;
if (!cp) {
usb_set_device_state(dev, USB_STATE_ADDRESS);
- usb_autosuspend_device(dev, 1);
+ usb_autosuspend_device(dev);
goto free_interfaces;
}
usb_set_device_state(dev, USB_STATE_CONFIGURED);
@@ -1490,7 +1490,7 @@ free_interfaces:
usb_create_sysfs_intf_files (intf);
}
- usb_autosuspend_device(dev, 1);
+ usb_autosuspend_device(dev);
return 0;
}
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index ab2f68fc7d2d..02426d0b9a34 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -200,13 +200,6 @@ static void ksuspend_usb_cleanup(void)
destroy_workqueue(ksuspend_usb_wq);
}
-#else
-
-#define ksuspend_usb_init() 0
-#define ksuspend_usb_cleanup() do {} while (0)
-
-#endif
-
#ifdef CONFIG_USB_SUSPEND
/* usb_autosuspend_work - callback routine to autosuspend a USB device */
@@ -226,7 +219,14 @@ static void usb_autosuspend_work(struct work_struct *work)
static void usb_autosuspend_work(struct work_struct *work)
{}
-#endif
+#endif /* CONFIG_USB_SUSPEND */
+
+#else
+
+#define ksuspend_usb_init() 0
+#define ksuspend_usb_cleanup() do {} while (0)
+
+#endif /* CONFIG_PM */
/**
* usb_alloc_dev - usb device constructor (usbcore-internal)
@@ -538,138 +538,6 @@ int usb_get_current_frame_number(struct usb_device *dev)
return usb_hcd_get_frame_number (dev);
}
-/**
- * usb_endpoint_dir_in - check if the endpoint has IN direction
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint is of type IN, otherwise it returns false.
- */
-int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd)
-{
- return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN);
-}
-
-/**
- * usb_endpoint_dir_out - check if the endpoint has OUT direction
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint is of type OUT, otherwise it returns false.
- */
-int usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd)
-{
- return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
-}
-
-/**
- * usb_endpoint_xfer_bulk - check if the endpoint has bulk transfer type
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint is of type bulk, otherwise it returns false.
- */
-int usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd)
-{
- return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
- USB_ENDPOINT_XFER_BULK);
-}
-
-/**
- * usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint is of type interrupt, otherwise it returns
- * false.
- */
-int usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd)
-{
- return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
- USB_ENDPOINT_XFER_INT);
-}
-
-/**
- * usb_endpoint_xfer_isoc - check if the endpoint has isochronous transfer type
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint is of type isochronous, otherwise it returns
- * false.
- */
-int usb_endpoint_xfer_isoc(const struct usb_endpoint_descriptor *epd)
-{
- return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
- USB_ENDPOINT_XFER_ISOC);
-}
-
-/**
- * usb_endpoint_is_bulk_in - check if the endpoint is bulk IN
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has bulk transfer type and IN direction,
- * otherwise it returns false.
- */
-int usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd)
-{
- return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_in(epd));
-}
-
-/**
- * usb_endpoint_is_bulk_out - check if the endpoint is bulk OUT
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has bulk transfer type and OUT direction,
- * otherwise it returns false.
- */
-int usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd)
-{
- return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_out(epd));
-}
-
-/**
- * usb_endpoint_is_int_in - check if the endpoint is interrupt IN
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has interrupt transfer type and IN direction,
- * otherwise it returns false.
- */
-int usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd)
-{
- return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd));
-}
-
-/**
- * usb_endpoint_is_int_out - check if the endpoint is interrupt OUT
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has interrupt transfer type and OUT direction,
- * otherwise it returns false.
- */
-int usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd)
-{
- return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd));
-}
-
-/**
- * usb_endpoint_is_isoc_in - check if the endpoint is isochronous IN
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has isochronous transfer type and IN direction,
- * otherwise it returns false.
- */
-int usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *epd)
-{
- return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_in(epd));
-}
-
-/**
- * usb_endpoint_is_isoc_out - check if the endpoint is isochronous OUT
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has isochronous transfer type and OUT direction,
- * otherwise it returns false.
- */
-int usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor *epd)
-{
- return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_out(epd));
-}
-
/*-------------------------------------------------------------------*/
/*
* __usb_get_extra_descriptor() finds a descriptor of specific type in the
@@ -1103,18 +971,6 @@ EXPORT_SYMBOL(__usb_get_extra_descriptor);
EXPORT_SYMBOL(usb_find_device);
EXPORT_SYMBOL(usb_get_current_frame_number);
-EXPORT_SYMBOL_GPL(usb_endpoint_dir_in);
-EXPORT_SYMBOL_GPL(usb_endpoint_dir_out);
-EXPORT_SYMBOL_GPL(usb_endpoint_xfer_bulk);
-EXPORT_SYMBOL_GPL(usb_endpoint_xfer_int);
-EXPORT_SYMBOL_GPL(usb_endpoint_xfer_isoc);
-EXPORT_SYMBOL_GPL(usb_endpoint_is_bulk_in);
-EXPORT_SYMBOL_GPL(usb_endpoint_is_bulk_out);
-EXPORT_SYMBOL_GPL(usb_endpoint_is_int_in);
-EXPORT_SYMBOL_GPL(usb_endpoint_is_int_out);
-EXPORT_SYMBOL_GPL(usb_endpoint_is_isoc_in);
-EXPORT_SYMBOL_GPL(usb_endpoint_is_isoc_out);
-
EXPORT_SYMBOL (usb_buffer_alloc);
EXPORT_SYMBOL (usb_buffer_free);
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 13322e33f912..17830a81be14 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -64,14 +64,13 @@ static inline void usb_pm_unlock(struct usb_device *udev) {}
#define USB_AUTOSUSPEND_DELAY (HZ*2)
-extern void usb_autosuspend_device(struct usb_device *udev, int dec_busy_cnt);
-extern int usb_autoresume_device(struct usb_device *udev, int inc_busy_cnt);
+extern void usb_autosuspend_device(struct usb_device *udev);
+extern int usb_autoresume_device(struct usb_device *udev);
#else
-#define usb_autosuspend_device(udev, dec_busy_cnt) do {} while (0)
-static inline int usb_autoresume_device(struct usb_device *udev,
- int inc_busy_cnt)
+#define usb_autosuspend_device(udev) do {} while (0)
+static inline int usb_autoresume_device(struct usb_device *udev)
{
return 0;
}
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 107119c54301..d15bf22b9a03 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -1894,13 +1894,13 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net)
if (!eth_is_promisc (dev)) {
u8 *dest = skb->data;
- if (dest [0] & 0x01) {
+ if (is_multicast_ether_addr(dest)) {
u16 type;
/* ignores USB_CDC_PACKET_TYPE_MULTICAST and host
* SET_ETHERNET_MULTICAST_FILTERS requests
*/
- if (memcmp (dest, net->broadcast, ETH_ALEN) == 0)
+ if (is_broadcast_ether_addr(dest))
type = USB_CDC_PACKET_TYPE_BROADCAST;
else
type = USB_CDC_PACKET_TYPE_ALL_MULTICAST;
diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c
index 179259664c18..4a991564a03e 100644
--- a/drivers/usb/gadget/lh7a40x_udc.c
+++ b/drivers/usb/gadget/lh7a40x_udc.c
@@ -83,7 +83,6 @@ static int lh7a40x_queue(struct usb_ep *ep, struct usb_request *, gfp_t);
static int lh7a40x_dequeue(struct usb_ep *ep, struct usb_request *);
static int lh7a40x_set_halt(struct usb_ep *ep, int);
static int lh7a40x_fifo_status(struct usb_ep *ep);
-static int lh7a40x_fifo_status(struct usb_ep *ep);
static void lh7a40x_fifo_flush(struct usb_ep *ep);
static void lh7a40x_ep0_kick(struct lh7a40x_udc *dev, struct lh7a40x_ep *ep);
static void lh7a40x_handle_ep0(struct lh7a40x_udc *dev, u32 intr);
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index 3acc896a5d4c..0b590831582c 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -1040,6 +1040,7 @@ net2280_queue (struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
} /* else the irq handler advances the queue. */
+ ep->responded = 1;
if (req)
list_add_tail (&req->queue, &ep->queue);
done:
@@ -2188,7 +2189,8 @@ static void handle_ep_small (struct net2280_ep *ep)
ep->stopped = 1;
set_halt (ep);
mode = 2;
- } else if (!req && !ep->stopped)
+ } else if (ep->responded &&
+ !req && !ep->stopped)
write_fifo (ep, NULL);
}
} else {
@@ -2203,7 +2205,7 @@ static void handle_ep_small (struct net2280_ep *ep)
} else if (((t & (1 << DATA_OUT_PING_TOKEN_INTERRUPT))
&& req
&& req->req.actual == req->req.length)
- || !req) {
+ || (ep->responded && !req)) {
ep->dev->protocol_stall = 1;
set_halt (ep);
ep->stopped = 1;
@@ -2469,6 +2471,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
/* we made the hardware handle most lowlevel requests;
* everything else goes uplevel to the gadget code.
*/
+ ep->responded = 1;
switch (u.r.bRequest) {
case USB_REQ_GET_STATUS: {
struct net2280_ep *e;
@@ -2537,6 +2540,7 @@ delegate:
u.r.bRequestType, u.r.bRequest,
w_value, w_index, w_length,
readl (&ep->regs->ep_cfg));
+ ep->responded = 0;
spin_unlock (&dev->lock);
tmp = dev->driver->setup (&dev->gadget, &u.r);
spin_lock (&dev->lock);
diff --git a/drivers/usb/gadget/net2280.h b/drivers/usb/gadget/net2280.h
index 957d6df34015..44ca139983d8 100644
--- a/drivers/usb/gadget/net2280.h
+++ b/drivers/usb/gadget/net2280.h
@@ -110,7 +110,8 @@ struct net2280_ep {
out_overflow : 1,
stopped : 1,
is_in : 1,
- is_iso : 1;
+ is_iso : 1,
+ responded : 1;
};
static inline void allow_status (struct net2280_ep *ep)
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
index 671c24bc6d75..1ed506e95985 100644
--- a/drivers/usb/gadget/pxa2xx_udc.c
+++ b/drivers/usb/gadget/pxa2xx_udc.c
@@ -2472,6 +2472,7 @@ static struct pxa2xx_udc memory = {
#define PXA210_B1 0x00000123
#define PXA210_B0 0x00000122
#define IXP425_A0 0x000001c1
+#define IXP425_B0 0x000001f1
#define IXP465_AD 0x00000200
/*
@@ -2509,6 +2510,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
break;
#elif defined(CONFIG_ARCH_IXP4XX)
case IXP425_A0:
+ case IXP425_B0:
case IXP465_AD:
dev->has_cfr = 1;
out_dma = 0;
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index cf10cbc98f80..cc60759083bf 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -153,7 +153,7 @@ config USB_U132_HCD
adapter will *NOT* work with PC cards that do not contain an OHCI
controller.
- For those PC cards that contain multiple OHCI controllers only ther
+ For those PC cards that contain multiple OHCI controllers only the
first one is used.
The driver consists of two modules, the "ftdi-elan" module is a
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 9030994aba98..025d33313681 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -126,6 +126,11 @@ static unsigned park = 0;
module_param (park, uint, S_IRUGO);
MODULE_PARM_DESC (park, "park setting; 1-3 back-to-back async packets");
+/* for flakey hardware, ignore overcurrent indicators */
+static int ignore_oc = 0;
+module_param (ignore_oc, bool, S_IRUGO);
+MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications");
+
#define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
/*-------------------------------------------------------------------------*/
@@ -541,9 +546,10 @@ static int ehci_run (struct usb_hcd *hcd)
temp = HC_VERSION(readl (&ehci->caps->hc_capbase));
ehci_info (ehci,
- "USB %x.%x started, EHCI %x.%02x, driver %s\n",
+ "USB %x.%x started, EHCI %x.%02x, driver %s%s\n",
((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f),
- temp >> 8, temp & 0xff, DRIVER_VERSION);
+ temp >> 8, temp & 0xff, DRIVER_VERSION,
+ ignore_oc ? ", overcurrent ignored" : "");
writel (INTR_MASK, &ehci->regs->intr_enable); /* Turn On Interrupts */
@@ -613,9 +619,8 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
unsigned i = HCS_N_PORTS (ehci->hcs_params);
/* resume root hub? */
- status = readl (&ehci->regs->command);
- if (!(status & CMD_RUN))
- writel (status | CMD_RUN, &ehci->regs->command);
+ if (!(readl(&ehci->regs->command) & CMD_RUN))
+ usb_hcd_resume_root_hub(hcd);
while (i--) {
int pstatus = readl (&ehci->regs->port_status [i]);
@@ -632,7 +637,6 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
*/
ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);
- usb_hcd_resume_root_hub(hcd);
}
}
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 1b20722c102b..bfe5f307cba6 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -34,6 +34,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
int port;
+ int mask;
if (time_before (jiffies, ehci->next_statechange))
msleep(5);
@@ -51,14 +52,25 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
ehci->reclaim_ready = 1;
ehci_work(ehci);
- /* suspend any active/unsuspended ports, maybe allow wakeup */
+ /* Unlike other USB host controller types, EHCI doesn't have
+ * any notion of "global" or bus-wide suspend. The driver has
+ * to manually suspend all the active unsuspended ports, and
+ * then manually resume them in the bus_resume() routine.
+ */
+ ehci->bus_suspended = 0;
while (port--) {
u32 __iomem *reg = &ehci->regs->port_status [port];
u32 t1 = readl (reg) & ~PORT_RWC_BITS;
u32 t2 = t1;
- if ((t1 & PORT_PE) && !(t1 & PORT_OWNER))
+ /* keep track of which ports we suspend */
+ if ((t1 & PORT_PE) && !(t1 & PORT_OWNER) &&
+ !(t1 & PORT_SUSPEND)) {
t2 |= PORT_SUSPEND;
+ set_bit(port, &ehci->bus_suspended);
+ }
+
+ /* enable remote wakeup on all ports */
if (device_may_wakeup(&hcd->self.root_hub->dev))
t2 |= PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E;
else
@@ -76,6 +88,13 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
ehci_halt (ehci);
hcd->state = HC_STATE_SUSPENDED;
+ /* allow remote wakeup */
+ mask = INTR_MASK;
+ if (!device_may_wakeup(&hcd->self.root_hub->dev))
+ mask &= ~STS_PCD;
+ writel(mask, &ehci->regs->intr_enable);
+ readl(&ehci->regs->intr_enable);
+
ehci->next_statechange = jiffies + msecs_to_jiffies(10);
spin_unlock_irq (&ehci->lock);
return 0;
@@ -88,7 +107,6 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
u32 temp;
int i;
- int intr_enable;
if (time_before (jiffies, ehci->next_statechange))
msleep(5);
@@ -100,31 +118,30 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
* the last user of the controller, not reset/pm hardware keeping
* state we gave to it.
*/
+ temp = readl(&ehci->regs->intr_enable);
+ ehci_dbg(ehci, "resume root hub%s\n", temp ? "" : " after power loss");
- /* re-init operational registers in case we lost power */
- if (readl (&ehci->regs->intr_enable) == 0) {
- /* at least some APM implementations will try to deliver
- * IRQs right away, so delay them until we're ready.
- */
- intr_enable = 1;
- writel (0, &ehci->regs->segment);
- writel (ehci->periodic_dma, &ehci->regs->frame_list);
- writel ((u32)ehci->async->qh_dma, &ehci->regs->async_next);
- } else
- intr_enable = 0;
- ehci_dbg(ehci, "resume root hub%s\n",
- intr_enable ? " after power loss" : "");
+ /* at least some APM implementations will try to deliver
+ * IRQs right away, so delay them until we're ready.
+ */
+ writel(0, &ehci->regs->intr_enable);
+
+ /* re-init operational registers */
+ writel(0, &ehci->regs->segment);
+ writel(ehci->periodic_dma, &ehci->regs->frame_list);
+ writel((u32) ehci->async->qh_dma, &ehci->regs->async_next);
/* restore CMD_RUN, framelist size, and irq threshold */
writel (ehci->command, &ehci->regs->command);
- /* take ports out of suspend */
+ /* manually resume the ports we suspended during bus_suspend() */
i = HCS_N_PORTS (ehci->hcs_params);
while (i--) {
temp = readl (&ehci->regs->port_status [i]);
temp &= ~(PORT_RWC_BITS
| PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E);
- if (temp & PORT_SUSPEND) {
+ if (test_bit(i, &ehci->bus_suspended) &&
+ (temp & PORT_SUSPEND)) {
ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
temp |= PORT_RESUME;
}
@@ -134,11 +151,12 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
mdelay (20);
while (i--) {
temp = readl (&ehci->regs->port_status [i]);
- if ((temp & PORT_SUSPEND) == 0)
- continue;
- temp &= ~(PORT_RWC_BITS | PORT_RESUME);
- writel (temp, &ehci->regs->port_status [i]);
- ehci_vdbg (ehci, "resumed port %d\n", i + 1);
+ if (test_bit(i, &ehci->bus_suspended) &&
+ (temp & PORT_SUSPEND)) {
+ temp &= ~(PORT_RWC_BITS | PORT_RESUME);
+ writel (temp, &ehci->regs->port_status [i]);
+ ehci_vdbg (ehci, "resumed port %d\n", i + 1);
+ }
}
(void) readl (&ehci->regs->command);
@@ -157,8 +175,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
hcd->state = HC_STATE_RUNNING;
/* Now we can safely re-enable irqs */
- if (intr_enable)
- writel (INTR_MASK, &ehci->regs->intr_enable);
+ writel(INTR_MASK, &ehci->regs->intr_enable);
spin_unlock_irq (&ehci->lock);
return 0;
@@ -218,6 +235,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
{
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
u32 temp, status = 0;
+ u32 mask;
int ports, i, retval = 1;
unsigned long flags;
@@ -233,6 +251,18 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
retval++;
}
+ /* Some boards (mostly VIA?) report bogus overcurrent indications,
+ * causing massive log spam unless we completely ignore them. It
+ * may be relevant that VIA VT8235 controlers, where PORT_POWER is
+ * always set, seem to clear PORT_OCC and PORT_CSC when writing to
+ * PORT_POWER; that's surprising, but maybe within-spec.
+ */
+ if (!ignore_oc)
+ mask = PORT_CSC | PORT_PEC | PORT_OCC;
+ else
+ mask = PORT_CSC | PORT_PEC;
+ // PORT_RESUME from hardware ~= PORT_STAT_C_SUSPEND
+
/* no hub change reports (bit 0) for now (power, ...) */
/* port N changes (bit N)? */
@@ -250,8 +280,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
}
if (!(temp & PORT_CONNECT))
ehci->reset_done [i] = 0;
- if ((temp & (PORT_CSC | PORT_PEC | PORT_OCC)) != 0
- // PORT_STAT_C_SUSPEND?
+ if ((temp & mask) != 0
|| ((temp & PORT_RESUME) != 0
&& time_after (jiffies,
ehci->reset_done [i]))) {
@@ -319,6 +348,7 @@ static int ehci_hub_control (
u32 temp, status;
unsigned long flags;
int retval = 0;
+ unsigned selector;
/*
* FIXME: support SetPortFeatures USB_PORT_FEAT_INDICATOR.
@@ -417,7 +447,7 @@ static int ehci_hub_control (
status |= 1 << USB_PORT_FEAT_C_CONNECTION;
if (temp & PORT_PEC)
status |= 1 << USB_PORT_FEAT_C_ENABLE;
- if (temp & PORT_OCC)
+ if ((temp & PORT_OCC) && !ignore_oc)
status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT;
/* whoever resumes must GetPortStatus to complete it!! */
@@ -506,6 +536,8 @@ static int ehci_hub_control (
}
break;
case SetPortFeature:
+ selector = wIndex >> 8;
+ wIndex &= 0xff;
if (!wIndex || wIndex > ports)
goto error;
wIndex--;
@@ -559,6 +591,22 @@ static int ehci_hub_control (
}
writel (temp, &ehci->regs->port_status [wIndex]);
break;
+
+ /* For downstream facing ports (these): one hub port is put
+ * into test mode according to USB2 11.24.2.13, then the hub
+ * must be reset (which for root hub now means rmmod+modprobe,
+ * or else system reboot). See EHCI 2.3.9 and 4.14 for info
+ * about the EHCI-specific stuff.
+ */
+ case USB_PORT_FEAT_TEST:
+ if (!selector || selector > 5)
+ goto error;
+ ehci_quiesce(ehci);
+ ehci_halt(ehci);
+ temp |= selector << 16;
+ writel (temp, &ehci->regs->port_status [wIndex]);
+ break;
+
default:
goto error;
}
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index e51c1ed81ac4..4bc7970ba3ef 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -257,9 +257,7 @@ static int ehci_pci_suspend(struct usb_hcd *hcd, pm_message_t message)
static int ehci_pci_resume(struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- unsigned port;
struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
- int retval = -EINVAL;
// maybe restore FLADJ
@@ -269,27 +267,19 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
/* Mark hardware accessible again as we are out of D3 state by now */
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
- /* If CF is clear, we lost PCI Vaux power and need to restart. */
- if (readl(&ehci->regs->configured_flag) != FLAG_CF)
- goto restart;
-
- /* If any port is suspended (or owned by the companion),
- * we know we can/must resume the HC (and mustn't reset it).
- * We just defer that to the root hub code.
+ /* If CF is still set, we maintained PCI Vaux power.
+ * Just undo the effect of ehci_pci_suspend().
*/
- for (port = HCS_N_PORTS(ehci->hcs_params); port > 0; ) {
- u32 status;
- port--;
- status = readl(&ehci->regs->port_status [port]);
- if (!(status & PORT_POWER))
- continue;
- if (status & (PORT_SUSPEND | PORT_RESUME | PORT_OWNER)) {
- usb_hcd_resume_root_hub(hcd);
- return 0;
- }
+ if (readl(&ehci->regs->configured_flag) == FLAG_CF) {
+ int mask = INTR_MASK;
+
+ if (!device_may_wakeup(&hcd->self.root_hub->dev))
+ mask &= ~STS_PCD;
+ writel(mask, &ehci->regs->intr_enable);
+ readl(&ehci->regs->intr_enable);
+ return 0;
}
-restart:
ehci_dbg(ehci, "lost power, restarting\n");
usb_root_hub_lost_power(hcd->self.root_hub);
@@ -307,13 +297,15 @@ restart:
ehci_work(ehci);
spin_unlock_irq(&ehci->lock);
- /* restart; khubd will disconnect devices */
- retval = ehci_run(hcd);
-
/* here we "know" root ports should always stay powered */
ehci_port_power(ehci, 1);
- return retval;
+ writel(ehci->command, &ehci->regs->command);
+ writel(FLAG_CF, &ehci->regs->configured_flag);
+ readl(&ehci->regs->command); /* unblock posted writes */
+
+ hcd->state = HC_STATE_SUSPENDED;
+ return 0;
}
#endif
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index bbc3082a73d7..74dbc6c8228f 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -74,6 +74,7 @@ struct ehci_hcd { /* one per controller */
/* per root hub port */
unsigned long reset_done [EHCI_MAX_ROOT_PORTS];
+ unsigned long bus_suspended;
/* per-HC memory pools (could be per-bus, but ...) */
struct dma_pool *qh_pool; /* qh per active urb */
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index ea4714e557e4..a95275a401b1 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -729,6 +729,16 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
ohci->next_statechange = jiffies + STATECHANGE_DELAY;
ohci_writel(ohci, OHCI_INTR_RD | OHCI_INTR_RHSC,
&regs->intrstatus);
+
+ /* NOTE: Vendors didn't always make the same implementation
+ * choices for RHSC. Many followed the spec; RHSC triggers
+ * on an edge, like setting and maybe clearing a port status
+ * change bit. With others it's level-triggered, active
+ * until khubd clears all the port status change bits. We'll
+ * always disable it here and rely on polling until khubd
+ * re-enables it.
+ */
+ ohci_writel(ohci, OHCI_INTR_RHSC, &regs->intrdisable);
usb_hcd_poll_rh_status(hcd);
}
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 6995ea36f2e8..2441642cb7b4 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -41,7 +41,11 @@ static void ohci_rhsc_enable (struct usb_hcd *hcd)
{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
- ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
+ spin_lock_irq(&ohci->lock);
+ if (!ohci->autostop)
+ del_timer(&hcd->rh_timer); /* Prevent next poll */
+ ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
+ spin_unlock_irq(&ohci->lock);
}
#define OHCI_SCHED_ENABLES \
@@ -50,6 +54,9 @@ static void ohci_rhsc_enable (struct usb_hcd *hcd)
static void dl_done_list (struct ohci_hcd *);
static void finish_unlinks (struct ohci_hcd *, u16);
+#ifdef CONFIG_PM
+static int ohci_restart(struct ohci_hcd *ohci);
+
static int ohci_rh_suspend (struct ohci_hcd *ohci, int autostop)
__releases(ohci->lock)
__acquires(ohci->lock)
@@ -132,8 +139,6 @@ static inline struct ed *find_head (struct ed *ed)
return ed;
}
-static int ohci_restart (struct ohci_hcd *ohci);
-
/* caller has locked the root hub */
static int ohci_rh_resume (struct ohci_hcd *ohci)
__releases(ohci->lock)
@@ -169,7 +174,7 @@ __acquires(ohci->lock)
break;
case OHCI_USB_RESUME:
/* HCFS changes sometime after INTR_RD */
- ohci_info(ohci, "%swakeup\n",
+ ohci_dbg(ohci, "%swakeup root hub\n",
autostopped ? "auto-" : "");
break;
case OHCI_USB_OPER:
@@ -181,7 +186,6 @@ __acquires(ohci->lock)
ohci_dbg (ohci, "lost power\n");
status = -EBUSY;
}
-#ifdef CONFIG_PM
if (status == -EBUSY) {
if (!autostopped) {
spin_unlock_irq (&ohci->lock);
@@ -191,25 +195,12 @@ __acquires(ohci->lock)
}
return status;
}
-#endif
if (status != -EINPROGRESS)
return status;
if (autostopped)
goto skip_resume;
spin_unlock_irq (&ohci->lock);
- temp = ohci->num_ports;
- while (temp--) {
- u32 stat = ohci_readl (ohci,
- &ohci->regs->roothub.portstatus [temp]);
-
- /* force global, not selective, resume */
- if (!(stat & RH_PS_PSS))
- continue;
- ohci_writel (ohci, RH_PS_POCI,
- &ohci->regs->roothub.portstatus [temp]);
- }
-
/* Some controllers (lucent erratum) need extra-long delays */
msleep (20 /* usb 11.5.1.10 */ + 12 /* 32 msec counter */ + 1);
@@ -217,6 +208,7 @@ __acquires(ohci->lock)
temp &= OHCI_CTRL_HCFS;
if (temp != OHCI_USB_RESUME) {
ohci_err (ohci, "controller won't resume\n");
+ spin_lock_irq(&ohci->lock);
return -EBUSY;
}
@@ -296,8 +288,6 @@ skip_resume:
return 0;
}
-#ifdef CONFIG_PM
-
static int ohci_bus_suspend (struct usb_hcd *hcd)
{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
@@ -335,6 +325,83 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
return rc;
}
+/* Carry out polling-, autostop-, and autoresume-related state changes */
+static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
+ int any_connected)
+{
+ int poll_rh = 1;
+
+ switch (ohci->hc_control & OHCI_CTRL_HCFS) {
+
+ case OHCI_USB_OPER:
+ /* keep on polling until we know a device is connected
+ * and RHSC is enabled */
+ if (!ohci->autostop) {
+ if (any_connected ||
+ !device_may_wakeup(&ohci_to_hcd(ohci)
+ ->self.root_hub->dev)) {
+ if (ohci_readl(ohci, &ohci->regs->intrenable) &
+ OHCI_INTR_RHSC)
+ poll_rh = 0;
+ } else {
+ ohci->autostop = 1;
+ ohci->next_statechange = jiffies + HZ;
+ }
+
+ /* if no devices have been attached for one second, autostop */
+ } else {
+ if (changed || any_connected) {
+ ohci->autostop = 0;
+ ohci->next_statechange = jiffies +
+ STATECHANGE_DELAY;
+ } else if (time_after_eq(jiffies,
+ ohci->next_statechange)
+ && !ohci->ed_rm_list
+ && !(ohci->hc_control &
+ OHCI_SCHED_ENABLES)) {
+ ohci_rh_suspend(ohci, 1);
+ }
+ }
+ break;
+
+ /* if there is a port change, autostart or ask to be resumed */
+ case OHCI_USB_SUSPEND:
+ case OHCI_USB_RESUME:
+ if (changed) {
+ if (ohci->autostop)
+ ohci_rh_resume(ohci);
+ else
+ usb_hcd_resume_root_hub(ohci_to_hcd(ohci));
+ } else {
+ /* everything is idle, no need for polling */
+ poll_rh = 0;
+ }
+ break;
+ }
+ return poll_rh;
+}
+
+#else /* CONFIG_PM */
+
+static inline int ohci_rh_resume(struct ohci_hcd *ohci)
+{
+ return 0;
+}
+
+/* Carry out polling-related state changes.
+ * autostop isn't used when CONFIG_PM is turned off.
+ */
+static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
+ int any_connected)
+{
+ int poll_rh = 1;
+
+ /* keep on polling until RHSC is enabled */
+ if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC)
+ poll_rh = 0;
+ return poll_rh;
+}
+
#endif /* CONFIG_PM */
/*-------------------------------------------------------------------------*/
@@ -346,7 +413,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
int i, changed = 0, length = 1;
- int any_connected = 0, rhsc_enabled = 1;
+ int any_connected = 0;
unsigned long flags;
spin_lock_irqsave (&ohci->lock, flags);
@@ -387,67 +454,8 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
}
}
- /* NOTE: vendors didn't always make the same implementation
- * choices for RHSC. Sometimes it triggers on an edge (like
- * setting and maybe clearing a port status change bit); and
- * it's level-triggered on other silicon, active until khubd
- * clears all active port status change bits. If it's still
- * set (level-triggered) we must disable it and rely on
- * polling until khubd re-enables it.
- */
- if (ohci_readl (ohci, &ohci->regs->intrstatus) & OHCI_INTR_RHSC) {
- ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrdisable);
- (void) ohci_readl (ohci, &ohci->regs->intrdisable);
- rhsc_enabled = 0;
- }
- hcd->poll_rh = 1;
-
- /* carry out appropriate state changes */
- switch (ohci->hc_control & OHCI_CTRL_HCFS) {
-
- case OHCI_USB_OPER:
- /* keep on polling until we know a device is connected
- * and RHSC is enabled */
- if (!ohci->autostop) {
- if (any_connected) {
- if (rhsc_enabled)
- hcd->poll_rh = 0;
- } else {
- ohci->autostop = 1;
- ohci->next_statechange = jiffies + HZ;
- }
-
- /* if no devices have been attached for one second, autostop */
- } else {
- if (changed || any_connected) {
- ohci->autostop = 0;
- ohci->next_statechange = jiffies +
- STATECHANGE_DELAY;
- } else if (device_may_wakeup(&hcd->self.root_hub->dev)
- && time_after_eq(jiffies,
- ohci->next_statechange)
- && !ohci->ed_rm_list
- && !(ohci->hc_control &
- OHCI_SCHED_ENABLES)) {
- ohci_rh_suspend (ohci, 1);
- }
- }
- break;
-
- /* if there is a port change, autostart or ask to be resumed */
- case OHCI_USB_SUSPEND:
- case OHCI_USB_RESUME:
- if (changed) {
- if (ohci->autostop)
- ohci_rh_resume (ohci);
- else
- usb_hcd_resume_root_hub (hcd);
- } else {
- /* everything is idle, no need for polling */
- hcd->poll_rh = 0;
- }
- break;
- }
+ hcd->poll_rh = ohci_root_hub_state_changes(ohci, changed,
+ any_connected);
done:
spin_unlock_irqrestore (&ohci->lock, flags);
diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
index 4f95a249c913..a9d7119e3176 100644
--- a/drivers/usb/host/u132-hcd.c
+++ b/drivers/usb/host/u132-hcd.c
@@ -71,7 +71,7 @@ static int distrust_firmware = 1;
module_param(distrust_firmware, bool, 0);
MODULE_PARM_DESC(distrust_firmware, "true to distrust firmware power/overcurren"
"t setup");
-DECLARE_WAIT_QUEUE_HEAD(u132_hcd_wait);
+static DECLARE_WAIT_QUEUE_HEAD(u132_hcd_wait);
/*
* u132_module_lock exists to protect access to global variables
*
@@ -205,13 +205,9 @@ struct u132 {
struct u132_port port[MAX_U132_PORTS];
struct u132_endp *endp[MAX_U132_ENDPS];
};
-int usb_ftdi_elan_read_reg(struct platform_device *pdev, u32 *data);
-int usb_ftdi_elan_read_pcimem(struct platform_device *pdev, u8 addressofs,
- u8 width, u32 *data);
-int usb_ftdi_elan_write_pcimem(struct platform_device *pdev, u8 addressofs,
- u8 width, u32 data);
+
/*
-* these can not be inlines because we need the structure offset!!
+* these cannot be inlines because we need the structure offset!!
* Does anyone have a better way?????
*/
#define u132_read_pcimem(u132, member, data) \
@@ -3031,7 +3027,7 @@ static struct hc_driver u132_hc_driver = {
* This function may be called by the USB core whilst the "usb_all_devices_rwsem"
* is held for writing, thus this module must not call usb_remove_hcd()
* synchronously - but instead should immediately stop activity to the
-* device and ansynchronously call usb_remove_hcd()
+* device and asynchronously call usb_remove_hcd()
*/
static int __devexit u132_remove(struct platform_device *pdev)
{
@@ -3227,7 +3223,7 @@ static int u132_resume(struct platform_device *pdev)
#define u132_resume NULL
#endif
/*
-* this driver is loaded explicitely by ftdi_u132
+* this driver is loaded explicitly by ftdi_u132
*
* the platform_driver struct is static because it is per type of module
*/
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
index 3038ed0700d3..8ccddf74534a 100644
--- a/drivers/usb/image/microtek.c
+++ b/drivers/usb/image/microtek.c
@@ -796,7 +796,7 @@ static int mts_usb_probe(struct usb_interface *intf,
new_desc->context.scsi_status = kmalloc(1, GFP_KERNEL);
if (!new_desc->context.scsi_status)
- goto out_kfree2;
+ goto out_free_urb;
new_desc->usb_dev = dev;
new_desc->usb_intf = intf;
@@ -822,18 +822,20 @@ static int mts_usb_probe(struct usb_interface *intf,
new_desc->host = scsi_host_alloc(&mts_scsi_host_template,
sizeof(new_desc));
if (!new_desc->host)
- goto out_free_urb;
+ goto out_kfree2;
new_desc->host->hostdata[0] = (unsigned long)new_desc;
if (scsi_add_host(new_desc->host, NULL)) {
err_retval = -EIO;
- goto out_free_urb;
+ goto out_host_put;
}
scsi_scan_host(new_desc->host);
usb_set_intfdata(intf, new_desc);
return 0;
+ out_host_put:
+ scsi_host_put(new_desc->host);
out_kfree2:
kfree(new_desc->context.scsi_status);
out_free_urb:
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig
index 20db36448ab3..661af7aa6236 100644
--- a/drivers/usb/input/Kconfig
+++ b/drivers/usb/input/Kconfig
@@ -221,6 +221,7 @@ config USB_TOUCHSCREEN
- ITM
- some other eTurboTouch
- Gunze AHL61
+ - DMC TSC-10/25
Have a look at <http://linux.chapter7.ch/touchkit/> for
a usage description and the required user-space stuff.
@@ -258,6 +259,11 @@ config USB_TOUCHSCREEN_GUNZE
bool "Gunze AHL61 device support" if EMBEDDED
depends on USB_TOUCHSCREEN
+config USB_TOUCHSCREEN_DMC_TSC10
+ default y
+ bool "DMC TSC-10/25 device support" if EMBEDDED
+ depends on USB_TOUCHSCREEN
+
config USB_YEALINK
tristate "Yealink usb-p1k voip phone"
depends on USB && INPUT && EXPERIMENTAL
diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c
index f659f3028ad2..ff23318dc301 100644
--- a/drivers/usb/input/ati_remote.c
+++ b/drivers/usb/input/ati_remote.c
@@ -630,19 +630,14 @@ static int ati_remote_alloc_buffers(struct usb_device *udev,
*/
static void ati_remote_free_buffers(struct ati_remote *ati_remote)
{
- if (ati_remote->irq_urb)
- usb_free_urb(ati_remote->irq_urb);
+ usb_free_urb(ati_remote->irq_urb);
+ usb_free_urb(ati_remote->out_urb);
- if (ati_remote->out_urb)
- usb_free_urb(ati_remote->out_urb);
+ usb_buffer_free(ati_remote->udev, DATA_BUFSIZE,
+ ati_remote->inbuf, ati_remote->inbuf_dma);
- if (ati_remote->inbuf)
- usb_buffer_free(ati_remote->udev, DATA_BUFSIZE,
- ati_remote->inbuf, ati_remote->inbuf_dma);
-
- if (ati_remote->outbuf)
- usb_buffer_free(ati_remote->udev, DATA_BUFSIZE,
- ati_remote->inbuf, ati_remote->outbuf_dma);
+ usb_buffer_free(ati_remote->udev, DATA_BUFSIZE,
+ ati_remote->outbuf, ati_remote->outbuf_dma);
}
static void ati_remote_input_init(struct ati_remote *ati_remote)
diff --git a/drivers/usb/input/ati_remote2.c b/drivers/usb/input/ati_remote2.c
index f982a2b4a7f9..83f1f79db7c7 100644
--- a/drivers/usb/input/ati_remote2.c
+++ b/drivers/usb/input/ati_remote2.c
@@ -372,8 +372,7 @@ static void ati_remote2_urb_cleanup(struct ati_remote2 *ar2)
int i;
for (i = 0; i < 2; i++) {
- if (ar2->urb[i])
- usb_free_urb(ar2->urb[i]);
+ usb_free_urb(ar2->urb[i]);
if (ar2->buf[i])
usb_buffer_free(ar2->udev, 4, ar2->buf[i], ar2->buf_dma[i]);
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index ebc9e823a46e..4295bab4f1e2 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -968,21 +968,30 @@ static void hid_retry_timeout(unsigned long _hid)
hid_io_error(hid);
}
-/* Workqueue routine to reset the device */
+/* Workqueue routine to reset the device or clear a halt */
static void hid_reset(struct work_struct *work)
{
struct hid_device *hid =
container_of(work, struct hid_device, reset_work);
- int rc_lock, rc;
-
- dev_dbg(&hid->intf->dev, "resetting device\n");
- rc = rc_lock = usb_lock_device_for_reset(hid->dev, hid->intf);
- if (rc_lock >= 0) {
- rc = usb_reset_composite_device(hid->dev, hid->intf);
- if (rc_lock)
- usb_unlock_device(hid->dev);
+ int rc_lock, rc = 0;
+
+ if (test_bit(HID_CLEAR_HALT, &hid->iofl)) {
+ dev_dbg(&hid->intf->dev, "clear halt\n");
+ rc = usb_clear_halt(hid->dev, hid->urbin->pipe);
+ clear_bit(HID_CLEAR_HALT, &hid->iofl);
+ hid_start_in(hid);
+ }
+
+ else if (test_bit(HID_RESET_PENDING, &hid->iofl)) {
+ dev_dbg(&hid->intf->dev, "resetting device\n");
+ rc = rc_lock = usb_lock_device_for_reset(hid->dev, hid->intf);
+ if (rc_lock >= 0) {
+ rc = usb_reset_composite_device(hid->dev, hid->intf);
+ if (rc_lock)
+ usb_unlock_device(hid->dev);
+ }
+ clear_bit(HID_RESET_PENDING, &hid->iofl);
}
- clear_bit(HID_RESET_PENDING, &hid->iofl);
switch (rc) {
case 0:
@@ -1024,9 +1033,8 @@ static void hid_io_error(struct hid_device *hid)
/* Retries failed, so do a port reset */
if (!test_and_set_bit(HID_RESET_PENDING, &hid->iofl)) {
- if (schedule_work(&hid->reset_work))
- goto done;
- clear_bit(HID_RESET_PENDING, &hid->iofl);
+ schedule_work(&hid->reset_work);
+ goto done;
}
}
@@ -1050,6 +1058,11 @@ static void hid_irq_in(struct urb *urb)
hid->retry_delay = 0;
hid_input_report(HID_INPUT_REPORT, urb, 1);
break;
+ case -EPIPE: /* stall */
+ clear_bit(HID_IN_RUNNING, &hid->iofl);
+ set_bit(HID_CLEAR_HALT, &hid->iofl);
+ schedule_work(&hid->reset_work);
+ return;
case -ECONNRESET: /* unlink */
case -ENOENT:
case -ESHUTDOWN: /* unplug */
@@ -1628,6 +1641,19 @@ void hid_init_reports(struct hid_device *hid)
#define USB_VENDOR_ID_APPLE 0x05ac
#define USB_DEVICE_ID_APPLE_MIGHTYMOUSE 0x0304
+#define USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI 0x020e
+#define USB_DEVICE_ID_APPLE_FOUNTAIN_ISO 0x020f
+#define USB_DEVICE_ID_APPLE_GEYSER_ANSI 0x0214
+#define USB_DEVICE_ID_APPLE_GEYSER_ISO 0x0215
+#define USB_DEVICE_ID_APPLE_GEYSER_JIS 0x0216
+#define USB_DEVICE_ID_APPLE_GEYSER3_ANSI 0x0217
+#define USB_DEVICE_ID_APPLE_GEYSER3_ISO 0x0218
+#define USB_DEVICE_ID_APPLE_GEYSER3_JIS 0x0219
+#define USB_DEVICE_ID_APPLE_GEYSER4_ANSI 0x021a
+#define USB_DEVICE_ID_APPLE_GEYSER4_ISO 0x021b
+#define USB_DEVICE_ID_APPLE_GEYSER4_JIS 0x021c
+#define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a
+#define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b
#define USB_VENDOR_ID_CHERRY 0x046a
#define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023
@@ -1795,17 +1821,19 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION },
- { USB_VENDOR_ID_APPLE, 0x020E, HID_QUIRK_POWERBOOK_HAS_FN },
- { USB_VENDOR_ID_APPLE, 0x020F, HID_QUIRK_POWERBOOK_HAS_FN },
- { USB_VENDOR_ID_APPLE, 0x0214, HID_QUIRK_POWERBOOK_HAS_FN },
- { USB_VENDOR_ID_APPLE, 0x0215, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
- { USB_VENDOR_ID_APPLE, 0x0216, HID_QUIRK_POWERBOOK_HAS_FN },
- { USB_VENDOR_ID_APPLE, 0x0217, HID_QUIRK_POWERBOOK_HAS_FN },
- { USB_VENDOR_ID_APPLE, 0x0218, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
- { USB_VENDOR_ID_APPLE, 0x0219, HID_QUIRK_POWERBOOK_HAS_FN },
- { USB_VENDOR_ID_APPLE, 0x021B, HID_QUIRK_POWERBOOK_HAS_FN },
- { USB_VENDOR_ID_APPLE, 0x030A, HID_QUIRK_POWERBOOK_HAS_FN },
- { USB_VENDOR_ID_APPLE, 0x030B, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN },
{ USB_VENDOR_ID_PANJIT, 0x0001, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_PANJIT, 0x0002, HID_QUIRK_IGNORE },
@@ -1986,7 +2014,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0)
interval = hid_mousepoll_interval;
- if (endpoint->bEndpointAddress & USB_DIR_IN) {
+ if (usb_endpoint_dir_in(endpoint)) {
if (hid->urbin)
continue;
if (!(hid->urbin = usb_alloc_urb(0, GFP_KERNEL)))
@@ -2068,13 +2096,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
return hid;
fail:
-
- if (hid->urbin)
- usb_free_urb(hid->urbin);
- if (hid->urbout)
- usb_free_urb(hid->urbout);
- if (hid->urbctrl)
- usb_free_urb(hid->urbctrl);
+ usb_free_urb(hid->urbin);
+ usb_free_urb(hid->urbout);
+ usb_free_urb(hid->urbctrl);
hid_free_buffers(dev, hid);
hid_free_device(hid);
@@ -2105,8 +2129,7 @@ static void hid_disconnect(struct usb_interface *intf)
usb_free_urb(hid->urbin);
usb_free_urb(hid->urbctrl);
- if (hid->urbout)
- usb_free_urb(hid->urbout);
+ usb_free_urb(hid->urbout);
hid_free_buffers(hid->dev, hid);
hid_free_device(hid);
diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h
index 0e76e6dcac37..2a9bf07944c0 100644
--- a/drivers/usb/input/hid.h
+++ b/drivers/usb/input/hid.h
@@ -385,6 +385,7 @@ struct hid_control_fifo {
#define HID_IN_RUNNING 3
#define HID_RESET_PENDING 4
#define HID_SUSPENDED 5
+#define HID_CLEAR_HALT 6
struct hid_input {
struct list_head list;
diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c
index c73285cf8558..dac88640eab6 100644
--- a/drivers/usb/input/usbkbd.c
+++ b/drivers/usb/input/usbkbd.c
@@ -208,10 +208,8 @@ static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd)
static void usb_kbd_free_mem(struct usb_device *dev, struct usb_kbd *kbd)
{
- if (kbd->irq)
- usb_free_urb(kbd->irq);
- if (kbd->led)
- usb_free_urb(kbd->led);
+ usb_free_urb(kbd->irq);
+ usb_free_urb(kbd->led);
if (kbd->new)
usb_buffer_free(dev, 8, kbd->new, kbd->new_dma);
if (kbd->cr)
@@ -236,9 +234,7 @@ static int usb_kbd_probe(struct usb_interface *iface,
return -ENODEV;
endpoint = &interface->endpoint[0].desc;
- if (!(endpoint->bEndpointAddress & USB_DIR_IN))
- return -ENODEV;
- if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
+ if (!usb_endpoint_is_int_in(endpoint))
return -ENODEV;
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
diff --git a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c
index cbbbea332ed7..68a55642c082 100644
--- a/drivers/usb/input/usbmouse.c
+++ b/drivers/usb/input/usbmouse.c
@@ -126,9 +126,7 @@ static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_i
return -ENODEV;
endpoint = &interface->endpoint[0].desc;
- if (!(endpoint->bEndpointAddress & USB_DIR_IN))
- return -ENODEV;
- if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
+ if (!usb_endpoint_is_int_in(endpoint))
return -ENODEV;
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
diff --git a/drivers/usb/input/usbtouchscreen.c b/drivers/usb/input/usbtouchscreen.c
index 933ceddf3dee..49704d4ed0e2 100644
--- a/drivers/usb/input/usbtouchscreen.c
+++ b/drivers/usb/input/usbtouchscreen.c
@@ -8,6 +8,7 @@
* - PanJit TouchSet
* - eTurboTouch
* - Gunze AHL61
+ * - DMC TSC-10/25
*
* Copyright (C) 2004-2006 by Daniel Ritz <daniel.ritz@gmx.ch>
* Copyright (C) by Todd E. Johnson (mtouchusb.c)
@@ -30,6 +31,8 @@
* - ITM parts are from itmtouch.c
* - 3M parts are from mtouchusb.c
* - PanJit parts are from an unmerged driver by Lanslott Gish
+ * - DMC TSC 10/25 are from Holger Schurig, with ideas from an unmerged
+ * driver from Marius Vollmer
*
*****************************************************************************/
@@ -44,7 +47,7 @@
#include <linux/usb/input.h>
-#define DRIVER_VERSION "v0.4"
+#define DRIVER_VERSION "v0.5"
#define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>"
#define DRIVER_DESC "USB Touchscreen Driver"
@@ -103,6 +106,7 @@ enum {
DEVTYPE_ITM,
DEVTYPE_ETURBO,
DEVTYPE_GUNZE,
+ DEVTYPE_DMC_TSC10,
};
static struct usb_device_id usbtouch_devices[] = {
@@ -139,6 +143,10 @@ static struct usb_device_id usbtouch_devices[] = {
{USB_DEVICE(0x0637, 0x0001), .driver_info = DEVTYPE_GUNZE},
#endif
+#ifdef CONFIG_USB_TOUCHSCREEN_DMC_TSC10
+ {USB_DEVICE(0x0afa, 0x03e8), .driver_info = DEVTYPE_DMC_TSC10},
+#endif
+
{}
};
@@ -313,6 +321,80 @@ static int gunze_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *
#endif
/*****************************************************************************
+ * DMC TSC-10/25 Part
+ *
+ * Documentation about the controller and it's protocol can be found at
+ * http://www.dmccoltd.com/files/controler/tsc10usb_pi_e.pdf
+ * http://www.dmccoltd.com/files/controler/tsc25_usb_e.pdf
+ */
+#ifdef CONFIG_USB_TOUCHSCREEN_DMC_TSC10
+
+/* supported data rates. currently using 130 */
+#define TSC10_RATE_POINT 0x50
+#define TSC10_RATE_30 0x40
+#define TSC10_RATE_50 0x41
+#define TSC10_RATE_80 0x42
+#define TSC10_RATE_100 0x43
+#define TSC10_RATE_130 0x44
+#define TSC10_RATE_150 0x45
+
+/* commands */
+#define TSC10_CMD_RESET 0x55
+#define TSC10_CMD_RATE 0x05
+#define TSC10_CMD_DATA1 0x01
+
+static int dmc_tsc10_init(struct usbtouch_usb *usbtouch)
+{
+ struct usb_device *dev = usbtouch->udev;
+ int ret;
+ unsigned char buf[2];
+
+ /* reset */
+ buf[0] = buf[1] = 0xFF;
+ ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0),
+ TSC10_CMD_RESET,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0, 0, buf, 2, USB_CTRL_SET_TIMEOUT);
+ if (ret < 0)
+ return ret;
+ if (buf[0] != 0x06 || buf[1] != 0x00)
+ return -ENODEV;
+
+ /* set coordinate output rate */
+ buf[0] = buf[1] = 0xFF;
+ ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0),
+ TSC10_CMD_RATE,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT);
+ if (ret < 0)
+ return ret;
+ if (buf[0] != 0x06 || buf[1] != 0x00)
+ return -ENODEV;
+
+ /* start sending data */
+ ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0),
+ TSC10_CMD_DATA1,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+
+static int dmc_tsc10_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+{
+ *x = ((pkt[2] & 0x03) << 8) | pkt[1];
+ *y = ((pkt[4] & 0x03) << 8) | pkt[3];
+ *touch = pkt[0] & 0x01;
+
+ return 1;
+}
+#endif
+
+
+/*****************************************************************************
* the different device descriptors
*/
static struct usbtouch_device_info usbtouch_dev_info[] = {
@@ -389,6 +471,18 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
.read_data = gunze_read_data,
},
#endif
+
+#ifdef CONFIG_USB_TOUCHSCREEN_DMC_TSC10
+ [DEVTYPE_DMC_TSC10] = {
+ .min_xc = 0x0,
+ .max_xc = 0x03ff,
+ .min_yc = 0x0,
+ .max_yc = 0x03ff,
+ .rept_size = 5,
+ .init = dmc_tsc10_init,
+ .read_data = dmc_tsc10_read_data,
+ },
+#endif
};
diff --git a/drivers/usb/input/wacom.h b/drivers/usb/input/wacom.h
index 1cf08f02c50e..d85abfc5ab58 100644
--- a/drivers/usb/input/wacom.h
+++ b/drivers/usb/input/wacom.h
@@ -110,7 +110,6 @@ struct wacom_combo {
};
extern int wacom_wac_irq(struct wacom_wac * wacom_wac, void * wcombo);
-extern void wacom_sys_irq(struct urb *urb);
extern void wacom_report_abs(void *wcombo, unsigned int abs_type, int abs_data);
extern void wacom_report_rel(void *wcombo, unsigned int rel_type, int rel_data);
extern void wacom_report_key(void *wcombo, unsigned int key_type, int key_data);
diff --git a/drivers/usb/input/wacom_sys.c b/drivers/usb/input/wacom_sys.c
index 3498b893b53b..e7cc20ab8155 100644
--- a/drivers/usb/input/wacom_sys.c
+++ b/drivers/usb/input/wacom_sys.c
@@ -42,7 +42,7 @@ static struct input_dev * get_input_dev(struct wacom_combo *wcombo)
return wcombo->wacom->dev;
}
-void wacom_sys_irq(struct urb *urb)
+static void wacom_sys_irq(struct urb *urb)
{
struct wacom *wacom = urb->context;
struct wacom_combo wcombo;
diff --git a/drivers/usb/input/yealink.c b/drivers/usb/input/yealink.c
index 905bf6398257..2268ca311ade 100644
--- a/drivers/usb/input/yealink.c
+++ b/drivers/usb/input/yealink.c
@@ -859,10 +859,8 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
interface = intf->cur_altsetting;
endpoint = &interface->endpoint[0].desc;
- if (!(endpoint->bEndpointAddress & USB_DIR_IN))
- return -EIO;
- if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
- return -EIO;
+ if (!usb_endpoint_is_int_in(endpoint))
+ return -ENODEV;
yld = kzalloc(sizeof(struct yealink_dev), GFP_KERNEL);
if (!yld)
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
index 11dc59540cda..2cba07d31971 100644
--- a/drivers/usb/misc/Makefile
+++ b/drivers/usb/misc/Makefile
@@ -4,6 +4,7 @@
#
obj-$(CONFIG_USB_ADUTUX) += adutux.o
+obj-$(CONFIG_USB_APPLEDISPLAY) += appledisplay.o
obj-$(CONFIG_USB_AUERSWALD) += auerswald.o
obj-$(CONFIG_USB_CYPRESS_CY7C63)+= cypress_cy7c63.o
obj-$(CONFIG_USB_CYTHERM) += cytherm.o
diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c
index 6b23a1def9fe..ba30ca6a14aa 100644
--- a/drivers/usb/misc/appledisplay.c
+++ b/drivers/usb/misc/appledisplay.c
@@ -216,10 +216,7 @@ static int appledisplay_probe(struct usb_interface *iface,
iface_desc = iface->cur_altsetting;
for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
endpoint = &iface_desc->endpoint[i].desc;
- if (!int_in_endpointAddr &&
- (endpoint->bEndpointAddress & USB_DIR_IN) &&
- ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
- USB_ENDPOINT_XFER_INT)) {
+ if (!int_in_endpointAddr && usb_endpoint_is_int_in(endpoint)) {
/* we found an interrupt in endpoint */
int_in_endpointAddr = endpoint->bEndpointAddress;
break;
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
index e4971d6aaafb..c703f73e1655 100644
--- a/drivers/usb/misc/auerswald.c
+++ b/drivers/usb/misc/auerswald.c
@@ -704,9 +704,7 @@ static void auerbuf_free (pauerbuf_t bp)
{
kfree(bp->bufp);
kfree(bp->dr);
- if (bp->urbp) {
- usb_free_urb(bp->urbp);
- }
+ usb_free_urb(bp->urbp);
kfree(bp);
}
@@ -1155,8 +1153,7 @@ static void auerswald_int_release (pauerswald_t cp)
dbg ("auerswald_int_release");
/* stop the int endpoint */
- if (cp->inturbp)
- usb_kill_urb (cp->inturbp);
+ usb_kill_urb (cp->inturbp);
/* deallocate memory */
auerswald_int_free (cp);
diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c
index 1fd9cb85f4ca..5c0a26cbd128 100644
--- a/drivers/usb/misc/emi26.c
+++ b/drivers/usb/misc/emi26.c
@@ -53,13 +53,12 @@ static void __exit emi26_exit (void);
static int emi26_writememory (struct usb_device *dev, int address, unsigned char *data, int length, __u8 request)
{
int result;
- unsigned char *buffer = kmalloc (length, GFP_KERNEL);
+ unsigned char *buffer = kmemdup(data, length, GFP_KERNEL);
if (!buffer) {
err("emi26: kmalloc(%d) failed.", length);
return -ENOMEM;
}
- memcpy (buffer, data, length);
/* Note: usb_control_msg returns negative value on error or length of the
* data that was written! */
result = usb_control_msg (dev, usb_sndctrlpipe(dev, 0), request, 0x40, address, 0, buffer, length, 300);
diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c
index fe351371f274..23153eac0dfa 100644
--- a/drivers/usb/misc/emi62.c
+++ b/drivers/usb/misc/emi62.c
@@ -61,13 +61,12 @@ static void __exit emi62_exit (void);
static int emi62_writememory (struct usb_device *dev, int address, unsigned char *data, int length, __u8 request)
{
int result;
- unsigned char *buffer = kmalloc (length, GFP_KERNEL);
+ unsigned char *buffer = kmemdup(data, length, GFP_KERNEL);
if (!buffer) {
err("emi62: kmalloc(%d) failed.", length);
return -ENOMEM;
}
- memcpy (buffer, data, length);
/* Note: usb_control_msg returns negative value on error or length of the
* data that was written! */
result = usb_control_msg (dev, usb_sndctrlpipe(dev, 0), request, 0x40, address, 0, buffer, length, 300);
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c
index e4e2cf2ba915..18b1925032a8 100644
--- a/drivers/usb/misc/ftdi-elan.c
+++ b/drivers/usb/misc/ftdi-elan.c
@@ -272,7 +272,7 @@ void ftdi_elan_gone_away(struct platform_device *pdev)
EXPORT_SYMBOL_GPL(ftdi_elan_gone_away);
-void ftdi_release_platform_dev(struct device *dev)
+static void ftdi_release_platform_dev(struct device *dev)
{
dev->parent = NULL;
}
@@ -1399,14 +1399,6 @@ static int ftdi_elan_read_reg(struct usb_ftdi *ftdi, u32 *data)
}
}
-int usb_ftdi_elan_read_reg(struct platform_device *pdev, u32 *data)
-{
- struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
- return ftdi_elan_read_reg(ftdi, data);
-}
-
-
-EXPORT_SYMBOL_GPL(usb_ftdi_elan_read_reg);
static int ftdi_elan_read_config(struct usb_ftdi *ftdi, int config_offset,
u8 width, u32 *data)
{
@@ -2606,10 +2598,7 @@ static int ftdi_elan_probe(struct usb_interface *interface,
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
endpoint = &iface_desc->endpoint[i].desc;
if (!ftdi->bulk_in_endpointAddr &&
- ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
- == USB_DIR_IN) && ((endpoint->bmAttributes &
- USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK))
- {
+ usb_endpoint_is_bulk_in(endpoint)) {
buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
ftdi->bulk_in_size = buffer_size;
ftdi->bulk_in_endpointAddr = endpoint->bEndpointAddress;
@@ -2622,10 +2611,7 @@ static int ftdi_elan_probe(struct usb_interface *interface,
}
}
if (!ftdi->bulk_out_endpointAddr &&
- ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
- == USB_DIR_OUT) && ((endpoint->bmAttributes &
- USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK))
- {
+ usb_endpoint_is_bulk_out(endpoint)) {
ftdi->bulk_out_endpointAddr =
endpoint->bEndpointAddress;
}
diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c
index 8e6e195a22ba..c9418535bef8 100644
--- a/drivers/usb/misc/idmouse.c
+++ b/drivers/usb/misc/idmouse.c
@@ -125,12 +125,12 @@ static DEFINE_MUTEX(disconnect_mutex);
static int idmouse_create_image(struct usb_idmouse *dev)
{
- int bytes_read = 0;
- int bulk_read = 0;
- int result = 0;
+ int bytes_read;
+ int bulk_read;
+ int result;
memcpy(dev->bulk_in_buffer, HEADER, sizeof(HEADER)-1);
- bytes_read += sizeof(HEADER)-1;
+ bytes_read = sizeof(HEADER)-1;
/* reset the device and set a fast blink rate */
result = ftip_command(dev, FTIP_RELEASE, 0, 0);
@@ -208,9 +208,9 @@ static inline void idmouse_delete(struct usb_idmouse *dev)
static int idmouse_open(struct inode *inode, struct file *file)
{
- struct usb_idmouse *dev = NULL;
+ struct usb_idmouse *dev;
struct usb_interface *interface;
- int result = 0;
+ int result;
/* prevent disconnects */
mutex_lock(&disconnect_mutex);
@@ -305,7 +305,7 @@ static ssize_t idmouse_read(struct file *file, char __user *buffer, size_t count
loff_t * ppos)
{
struct usb_idmouse *dev;
- int result = 0;
+ int result;
dev = (struct usb_idmouse *) file->private_data;
@@ -329,7 +329,7 @@ static int idmouse_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(interface);
- struct usb_idmouse *dev = NULL;
+ struct usb_idmouse *dev;
struct usb_host_interface *iface_desc;
struct usb_endpoint_descriptor *endpoint;
int result;
@@ -350,11 +350,7 @@ static int idmouse_probe(struct usb_interface *interface,
/* set up the endpoint information - use only the first bulk-in endpoint */
endpoint = &iface_desc->endpoint[0].desc;
- if (!dev->bulk_in_endpointAddr
- && (endpoint->bEndpointAddress & USB_DIR_IN)
- && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
- USB_ENDPOINT_XFER_BULK)) {
-
+ if (!dev->bulk_in_endpointAddr && usb_endpoint_is_bulk_in(endpoint)) {
/* we found a bulk in endpoint */
dev->orig_bi_size = le16_to_cpu(endpoint->wMaxPacketSize);
dev->bulk_in_size = 0x200; /* works _much_ faster */
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
index 27089497e717..5dce797bddb7 100644
--- a/drivers/usb/misc/legousbtower.c
+++ b/drivers/usb/misc/legousbtower.c
@@ -317,12 +317,8 @@ static inline void tower_delete (struct lego_usb_tower *dev)
tower_abort_transfers (dev);
/* free data structures */
- if (dev->interrupt_in_urb != NULL) {
- usb_free_urb (dev->interrupt_in_urb);
- }
- if (dev->interrupt_out_urb != NULL) {
- usb_free_urb (dev->interrupt_out_urb);
- }
+ usb_free_urb(dev->interrupt_in_urb);
+ usb_free_urb(dev->interrupt_out_urb);
kfree (dev->read_buffer);
kfree (dev->interrupt_in_buffer);
kfree (dev->interrupt_out_buffer);
@@ -502,15 +498,11 @@ static void tower_abort_transfers (struct lego_usb_tower *dev)
if (dev->interrupt_in_running) {
dev->interrupt_in_running = 0;
mb();
- if (dev->interrupt_in_urb != NULL && dev->udev) {
+ if (dev->udev)
usb_kill_urb (dev->interrupt_in_urb);
- }
- }
- if (dev->interrupt_out_busy) {
- if (dev->interrupt_out_urb != NULL && dev->udev) {
- usb_kill_urb (dev->interrupt_out_urb);
- }
}
+ if (dev->interrupt_out_busy && dev->udev)
+ usb_kill_urb(dev->interrupt_out_urb);
exit:
dbg(2, "%s: leave", __FUNCTION__);
@@ -898,14 +890,11 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
endpoint = &iface_desc->endpoint[i].desc;
- if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) &&
- ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
- dev->interrupt_in_endpoint = endpoint;
- }
-
- if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) &&
- ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
- dev->interrupt_out_endpoint = endpoint;
+ if (usb_endpoint_xfer_int(endpoint)) {
+ if (usb_endpoint_dir_in(endpoint))
+ dev->interrupt_in_endpoint = endpoint;
+ else
+ dev->interrupt_out_endpoint = endpoint;
}
}
if(dev->interrupt_in_endpoint == NULL) {
diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c
index 33e716c6a79b..9659c79e187e 100644
--- a/drivers/usb/misc/phidgetkit.c
+++ b/drivers/usb/misc/phidgetkit.c
@@ -554,7 +554,7 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic
return -ENODEV;
endpoint = &interface->endpoint[0].desc;
- if (!(endpoint->bEndpointAddress & 0x80))
+ if (!usb_endpoint_dir_in(endpoint))
return -ENODEV;
/*
* bmAttributes
@@ -653,8 +653,7 @@ out2:
device_remove_file(kit->dev, &dev_output_attrs[i]);
out:
if (kit) {
- if (kit->irq)
- usb_free_urb(kit->irq);
+ usb_free_urb(kit->irq);
if (kit->data)
usb_buffer_free(dev, URB_INT_SIZE, kit->data, kit->data_dma);
if (kit->dev)
diff --git a/drivers/usb/misc/phidgetmotorcontrol.c b/drivers/usb/misc/phidgetmotorcontrol.c
index 0385ffcc7419..2bb4fa572bb7 100644
--- a/drivers/usb/misc/phidgetmotorcontrol.c
+++ b/drivers/usb/misc/phidgetmotorcontrol.c
@@ -324,7 +324,7 @@ static int motorcontrol_probe(struct usb_interface *intf, const struct usb_devic
return -ENODEV;
endpoint = &interface->endpoint[0].desc;
- if (!(endpoint->bEndpointAddress & 0x80))
+ if (!usb_endpoint_dir_in(endpoint))
return -ENODEV;
/*
@@ -393,8 +393,7 @@ out2:
device_remove_file(mc->dev, &dev_attrs[i]);
out:
if (mc) {
- if (mc->irq)
- usb_free_urb(mc->irq);
+ usb_free_urb(mc->irq);
if (mc->data)
usb_buffer_free(dev, URB_INT_SIZE, mc->data, mc->data_dma);
if (mc->dev)
diff --git a/drivers/usb/misc/usb_u132.h b/drivers/usb/misc/usb_u132.h
index 551ba8906d62..dc2e5a31caec 100644
--- a/drivers/usb/misc/usb_u132.h
+++ b/drivers/usb/misc/usb_u132.h
@@ -52,7 +52,7 @@
* the kernel to load the "u132-hcd" module.
*
* The "ftdi-u132" module provides the interface to the inserted
-* PC card and the "u132-hcd" module uses the API to send and recieve
+* PC card and the "u132-hcd" module uses the API to send and receive
* data. The API features call-backs, so that part of the "u132-hcd"
* module code will run in the context of one of the kernel threads
* of the "ftdi-u132" module.
@@ -95,3 +95,7 @@ int usb_ftdi_elan_edset_setup(struct platform_device *pdev, u8 ed_number,
int halted, int skipped, int actual, int non_null));
int usb_ftdi_elan_edset_flush(struct platform_device *pdev, u8 ed_number,
void *endp);
+int usb_ftdi_elan_read_pcimem(struct platform_device *pdev, int mem_offset,
+ u8 width, u32 *data);
+int usb_ftdi_elan_write_pcimem(struct platform_device *pdev, int mem_offset,
+ u8 width, u32 data);
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 7c2cbdf81d20..194065dbb51f 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -138,7 +138,7 @@ get_endpoints (struct usbtest_dev *dev, struct usb_interface *intf)
default:
continue;
}
- if (e->desc.bEndpointAddress & USB_DIR_IN) {
+ if (usb_endpoint_dir_in(&e->desc)) {
if (!in)
in = e;
} else {
@@ -147,7 +147,7 @@ get_endpoints (struct usbtest_dev *dev, struct usb_interface *intf)
}
continue;
try_iso:
- if (e->desc.bEndpointAddress & USB_DIR_IN) {
+ if (usb_endpoint_dir_in(&e->desc)) {
if (!iso_in)
iso_in = e;
} else {
diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c
index 881841e600de..95e682e2c9d6 100644
--- a/drivers/usb/net/asix.c
+++ b/drivers/usb/net/asix.c
@@ -249,9 +249,9 @@ asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
req->bRequest = cmd;
- req->wValue = value;
- req->wIndex = index;
- req->wLength = size;
+ req->wValue = cpu_to_le16(value);
+ req->wIndex = cpu_to_le16(index);
+ req->wLength = cpu_to_le16(size);
usb_fill_control_urb(urb, dev->udev,
usb_sndctrlpipe(dev->udev, 0),
diff --git a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c
index f740325abac4..907b820a5faf 100644
--- a/drivers/usb/net/catc.c
+++ b/drivers/usb/net/catc.c
@@ -786,14 +786,10 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
if ((!catc->ctrl_urb) || (!catc->tx_urb) ||
(!catc->rx_urb) || (!catc->irq_urb)) {
err("No free urbs available.");
- if (catc->ctrl_urb)
- usb_free_urb(catc->ctrl_urb);
- if (catc->tx_urb)
- usb_free_urb(catc->tx_urb);
- if (catc->rx_urb)
- usb_free_urb(catc->rx_urb);
- if (catc->irq_urb)
- usb_free_urb(catc->irq_urb);
+ usb_free_urb(catc->ctrl_urb);
+ usb_free_urb(catc->tx_urb);
+ usb_free_urb(catc->rx_urb);
+ usb_free_urb(catc->irq_urb);
free_netdev(netdev);
return -ENOMEM;
}
diff --git a/drivers/usb/net/cdc_ether.c b/drivers/usb/net/cdc_ether.c
index f6971b88349d..44a91547146e 100644
--- a/drivers/usb/net/cdc_ether.c
+++ b/drivers/usb/net/cdc_ether.c
@@ -200,8 +200,7 @@ next_desc:
dev->status = &info->control->cur_altsetting->endpoint [0];
desc = &dev->status->desc;
- if (desc->bmAttributes != USB_ENDPOINT_XFER_INT
- || !(desc->bEndpointAddress & USB_DIR_IN)
+ if (!usb_endpoint_is_int_in(desc)
|| (le16_to_cpu(desc->wMaxPacketSize)
< sizeof(struct usb_cdc_notification))
|| !desc->bInterval) {
diff --git a/drivers/usb/net/net1080.c b/drivers/usb/net/net1080.c
index ce00de8f13a1..a77410562e12 100644
--- a/drivers/usb/net/net1080.c
+++ b/drivers/usb/net/net1080.c
@@ -237,12 +237,12 @@ static inline void nc_dump_usbctl(struct usbnet *dev, u16 usbctl)
#define STATUS_CONN_OTHER (1 << 14)
#define STATUS_SUSPEND_OTHER (1 << 13)
#define STATUS_MAILBOX_OTHER (1 << 12)
-#define STATUS_PACKETS_OTHER(n) (((n) >> 8) && 0x03)
+#define STATUS_PACKETS_OTHER(n) (((n) >> 8) & 0x03)
#define STATUS_CONN_THIS (1 << 6)
#define STATUS_SUSPEND_THIS (1 << 5)
#define STATUS_MAILBOX_THIS (1 << 4)
-#define STATUS_PACKETS_THIS(n) (((n) >> 0) && 0x03)
+#define STATUS_PACKETS_THIS(n) (((n) >> 0) & 0x03)
#define STATUS_UNSPEC_MASK 0x0c8c
#define STATUS_NOISE_MASK ((u16)~(0x0303|STATUS_UNSPEC_MASK))
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
index 78cf6f091285..b5690b3834e3 100644
--- a/drivers/usb/net/pegasus.c
+++ b/drivers/usb/net/pegasus.c
@@ -163,6 +163,7 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
/* using ATOMIC, we'd never wake up if we slept */
if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) {
+ set_current_state(TASK_RUNNING);
if (ret == -ENODEV)
netif_device_detach(pegasus->net);
if (netif_msg_drv(pegasus))
diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
index 79b5474fe234..327f97555679 100644
--- a/drivers/usb/net/usbnet.c
+++ b/drivers/usb/net/usbnet.c
@@ -116,7 +116,7 @@ int usbnet_get_endpoints(struct usbnet *dev, struct usb_interface *intf)
e = alt->endpoint + ep;
switch (e->desc.bmAttributes) {
case USB_ENDPOINT_XFER_INT:
- if (!(e->desc.bEndpointAddress & USB_DIR_IN))
+ if (!usb_endpoint_dir_in(&e->desc))
continue;
intr = 1;
/* FALLTHROUGH */
@@ -125,7 +125,7 @@ int usbnet_get_endpoints(struct usbnet *dev, struct usb_interface *intf)
default:
continue;
}
- if (e->desc.bEndpointAddress & USB_DIR_IN) {
+ if (usb_endpoint_dir_in(&e->desc)) {
if (!intr && !in)
in = e;
else if (intr && !status)
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 2a8dd4cc943d..2f4d303ee36f 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -554,6 +554,17 @@ config USB_SERIAL_OMNINET
To compile this driver as a module, choose M here: the
module will be called omninet.
+config USB_SERIAL_DEBUG
+ tristate "USB Debugging Device"
+ depends on USB_SERIAL
+ help
+ Say Y here if you have a USB debugging device used to recieve
+ debugging data from another machine. The most common of these
+ devices is the NetChip TurboCONNECT device.
+
+ To compile this driver as a module, choose M here: the
+ module will be called usb-debug.
+
config USB_EZUSB
bool
depends on USB_SERIAL_KEYSPAN_PDA || USB_SERIAL_XIRCOM || USB_SERIAL_KEYSPAN || USB_SERIAL_WHITEHEAT
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index a5047dc599bb..61166ad450e6 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o
obj-$(CONFIG_USB_SERIAL_CP2101) += cp2101.o
obj-$(CONFIG_USB_SERIAL_CYBERJACK) += cyberjack.o
obj-$(CONFIG_USB_SERIAL_CYPRESS_M8) += cypress_m8.o
+obj-$(CONFIG_USB_SERIAL_DEBUG) += usb_debug.o
obj-$(CONFIG_USB_SERIAL_DIGI_ACCELEPORT) += digi_acceleport.o
obj-$(CONFIG_USB_SERIAL_EDGEPORT) += io_edgeport.o
obj-$(CONFIG_USB_SERIAL_EDGEPORT_TI) += io_ti.o
diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c
index 2a4ac9bd6a3a..86bcf63b6ba5 100644
--- a/drivers/usb/serial/aircable.c
+++ b/drivers/usb/serial/aircable.c
@@ -272,8 +272,11 @@ static void aircable_read(struct work_struct *work)
*/
tty = port->tty;
- if (!tty)
+ if (!tty) {
schedule_work(&priv->rx_work);
+ err("%s - No tty available", __FUNCTION__);
+ return ;
+ }
count = min(64, serial_buf_data_avail(priv->rx_buf));
@@ -307,9 +310,7 @@ static int aircable_probe(struct usb_serial *serial,
for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
endpoint = &iface_desc->endpoint[i].desc;
- if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
- ((endpoint->bmAttributes & 3) == 0x02)) {
- /* we found our bulk out endpoint */
+ if (usb_endpoint_is_bulk_out(endpoint)) {
dbg("found bulk out on endpoint %d", i);
++num_bulk_out;
}
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c
index 7f5d546da39a..96c73726d74a 100644
--- a/drivers/usb/serial/airprime.c
+++ b/drivers/usb/serial/airprime.c
@@ -19,6 +19,7 @@
static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */
{ USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */
+ { USB_DEVICE(0x1410, 0x1430) }, /* Novatel Merlin XU870 HSDPA/3G */
{ USB_DEVICE(0x1410, 0x1100) }, /* ExpressCard34 Qualcomm 3G CDMA */
{ },
};
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index ca52f12f0e24..863966c1c5ac 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -85,10 +85,9 @@ static int ark3116_attach(struct usb_serial *serial)
int i;
for (i = 0; i < serial->num_ports; ++i) {
- priv = kmalloc(sizeof (struct ark3116_private), GFP_KERNEL);
+ priv = kzalloc(sizeof(struct ark3116_private), GFP_KERNEL);
if (!priv)
goto cleanup;
- memset(priv, 0x00, sizeof (struct ark3116_private));
spin_lock_init(&priv->lock);
usb_set_serial_port_data(serial->port[i], priv);
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
index 3a9073dbfe6a..7167728d764c 100644
--- a/drivers/usb/serial/console.c
+++ b/drivers/usb/serial/console.c
@@ -166,19 +166,17 @@ static int usb_console_setup(struct console *co, char *options)
if (serial->type->set_termios) {
/* build up a fake tty structure so that the open call has something
* to look at to get the cflag value */
- tty = kmalloc (sizeof (*tty), GFP_KERNEL);
+ tty = kzalloc(sizeof(*tty), GFP_KERNEL);
if (!tty) {
err ("no more memory");
return -ENOMEM;
}
- termios = kmalloc (sizeof (*termios), GFP_KERNEL);
+ termios = kzalloc(sizeof(*termios), GFP_KERNEL);
if (!termios) {
err ("no more memory");
kfree (tty);
return -ENOMEM;
}
- memset (tty, 0x00, sizeof(*tty));
- memset (termios, 0x00, sizeof(*termios));
termios->c_cflag = cflag;
tty->termios = termios;
port->tty = tty;
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index f2e89a083659..093f303b3189 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -1684,15 +1684,14 @@ static int __init cypress_init(void)
info(DRIVER_DESC " " DRIVER_VERSION);
return 0;
+
failed_usb_register:
- usb_deregister(&cypress_driver);
-failed_ca42v2_register:
usb_serial_deregister(&cypress_ca42v2_device);
-failed_hidcom_register:
+failed_ca42v2_register:
usb_serial_deregister(&cypress_hidcom_device);
-failed_em_register:
+failed_hidcom_register:
usb_serial_deregister(&cypress_earthmate_device);
-
+failed_em_register:
return retval;
}
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index fd159b040bfb..83d0e21145b0 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -157,7 +157,7 @@
* to TASK_RUNNING will be lost and write_chan's subsequent call to
* schedule() will never return (unless it catches a signal).
* This race condition occurs because write_bulk_callback() (and thus
-* the wakeup) are called asynchonously from an interrupt, rather than
+* the wakeup) are called asynchronously from an interrupt, rather than
* from the scheduler. We can avoid the race by calling the wakeup
* from the scheduler queue and that's our fix: Now, at the end of
* write_bulk_callback() we queue up a wakeup call on the scheduler
diff --git a/drivers/usb/serial/ezusb.c b/drivers/usb/serial/ezusb.c
index 5169c2d154ab..97ee718b1da2 100644
--- a/drivers/usb/serial/ezusb.c
+++ b/drivers/usb/serial/ezusb.c
@@ -31,12 +31,11 @@ int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *da
return -ENODEV;
}
- transfer_buffer = kmalloc (length, GFP_KERNEL);
+ transfer_buffer = kmemdup(data, length, GFP_KERNEL);
if (!transfer_buffer) {
dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, length);
return -ENOMEM;
}
- memcpy (transfer_buffer, data, length);
result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), bRequest, 0x40, address, 0, transfer_buffer, length, 3000);
kfree (transfer_buffer);
return result;
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 88ed5c1d236c..72e4d48f51e9 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -1390,8 +1390,7 @@ static void ftdi_close (struct usb_serial_port *port, struct file *filp)
flush_scheduled_work();
/* shutdown our bulk read */
- if (port->read_urb)
- usb_kill_urb(port->read_urb);
+ usb_kill_urb(port->read_urb);
} /* ftdi_close */
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index 4543152a9966..6530d391ebed 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -1523,12 +1523,11 @@ static int garmin_attach (struct usb_serial *serial)
dbg("%s", __FUNCTION__);
- garmin_data_p = kmalloc (sizeof(struct garmin_data), GFP_KERNEL);
+ garmin_data_p = kzalloc(sizeof(struct garmin_data), GFP_KERNEL);
if (garmin_data_p == NULL) {
dev_err(&port->dev, "%s - Out of memory\n", __FUNCTION__);
return -ENOMEM;
}
- memset (garmin_data_p, 0, sizeof(struct garmin_data));
init_timer(&garmin_data_p->timer);
spin_lock_init(&garmin_data_p->lock);
INIT_LIST_HEAD(&garmin_data_p->pktlist);
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index 91bd3014ef1e..d06547a13f28 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -1038,9 +1038,7 @@ static void edge_close (struct usb_serial_port *port, struct file * filp)
edge_port->open = FALSE;
edge_port->openPending = FALSE;
- if (edge_port->write_urb) {
- usb_kill_urb(edge_port->write_urb);
- }
+ usb_kill_urb(edge_port->write_urb);
if (edge_port->write_urb) {
/* if this urb had a transfer buffer already (old transfer) free it */
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index 2a4bb66691ad..d3b9a351cef8 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -206,10 +206,9 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
dbg("%s", __FUNCTION__);
- buf_flow_init = kmalloc(16, GFP_KERNEL);
+ buf_flow_init = kmemdup(buf_flow_static, 16, GFP_KERNEL);
if (!buf_flow_init)
return -ENOMEM;
- memcpy(buf_flow_init, buf_flow_static, 16);
if (port->tty)
port->tty->low_latency = 1;
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 53be824eb1bf..7639652cec42 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -2306,22 +2306,16 @@ static void keyspan_shutdown (struct usb_serial *serial)
}
/* Now free them */
- if (s_priv->instat_urb)
- usb_free_urb(s_priv->instat_urb);
- if (s_priv->glocont_urb)
- usb_free_urb(s_priv->glocont_urb);
+ usb_free_urb(s_priv->instat_urb);
+ usb_free_urb(s_priv->glocont_urb);
for (i = 0; i < serial->num_ports; ++i) {
port = serial->port[i];
p_priv = usb_get_serial_port_data(port);
- if (p_priv->inack_urb)
- usb_free_urb(p_priv->inack_urb);
- if (p_priv->outcont_urb)
- usb_free_urb(p_priv->outcont_urb);
+ usb_free_urb(p_priv->inack_urb);
+ usb_free_urb(p_priv->outcont_urb);
for (j = 0; j < 2; j++) {
- if (p_priv->in_urbs[j])
- usb_free_urb(p_priv->in_urbs[j]);
- if (p_priv->out_urbs[j])
- usb_free_urb(p_priv->out_urbs[j]);
+ usb_free_urb(p_priv->in_urbs[j]);
+ usb_free_urb(p_priv->out_urbs[j]);
}
}
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index ff03331e0bcf..237289920f03 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -185,13 +185,11 @@ static int kobil_startup (struct usb_serial *serial)
for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {
endpoint = &altsetting->endpoint[i];
- if (((endpoint->desc.bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) &&
- ((endpoint->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
+ if (usb_endpoint_is_int_out(&endpoint->desc)) {
dbg("%s Found interrupt out endpoint. Address: %d", __FUNCTION__, endpoint->desc.bEndpointAddress);
priv->write_int_endpoint_address = endpoint->desc.bEndpointAddress;
}
- if (((endpoint->desc.bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) &&
- ((endpoint->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
+ if (usb_endpoint_is_int_in(&endpoint->desc)) {
dbg("%s Found interrupt in endpoint. Address: %d", __FUNCTION__, endpoint->desc.bEndpointAddress);
priv->read_int_endpoint_address = endpoint->desc.bEndpointAddress;
}
@@ -355,8 +353,7 @@ static void kobil_close (struct usb_serial_port *port, struct file *filp)
usb_free_urb( port->write_urb );
port->write_urb = NULL;
}
- if (port->interrupt_in_urb)
- usb_kill_urb(port->interrupt_in_urb);
+ usb_kill_urb(port->interrupt_in_urb);
}
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index b7582cc496dc..a906e500a02b 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -358,10 +358,8 @@ static int mct_u232_startup (struct usb_serial *serial)
/* Puh, that's dirty */
port = serial->port[0];
rport = serial->port[1];
- if (port->read_urb) {
- /* No unlinking, it wasn't submitted yet. */
- usb_free_urb(port->read_urb);
- }
+ /* No unlinking, it wasn't submitted yet. */
+ usb_free_urb(port->read_urb);
port->read_urb = rport->interrupt_in_urb;
rport->interrupt_in_urb = NULL;
port->read_urb->context = port;
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 5b71962d0351..02c89e10b2cf 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -2596,12 +2596,11 @@ static int mos7840_startup(struct usb_serial *serial)
/* set up port private structures */
for (i = 0; i < serial->num_ports; ++i) {
- mos7840_port = kmalloc(sizeof(struct moschip_port), GFP_KERNEL);
+ mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
if (mos7840_port == NULL) {
err("%s - Out of memory", __FUNCTION__);
return -ENOMEM;
}
- memset(mos7840_port, 0, sizeof(struct moschip_port));
/* Initialize all port interrupt end point to port 0 int endpoint *
* Our device has only one interrupt end point comman to all port */
diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c
index 0610409a6568..054abee81652 100644
--- a/drivers/usb/serial/navman.c
+++ b/drivers/usb/serial/navman.c
@@ -95,8 +95,7 @@ static void navman_close(struct usb_serial_port *port, struct file *filp)
{
dbg("%s - port %d", __FUNCTION__, port->number);
- if (port->interrupt_in_urb)
- usb_kill_urb(port->interrupt_in_urb);
+ usb_kill_urb(port->interrupt_in_urb);
}
static int navman_write(struct usb_serial_port *port,
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index 07400c0c8a8c..ae98d8cbdbb8 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -228,6 +228,7 @@ static int product_5052_count;
/* null entry */
static struct usb_device_id ti_id_table_3410[1+TI_EXTRA_VID_PID_COUNT+1] = {
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
+ { USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) },
};
static struct usb_device_id ti_id_table_5052[4+TI_EXTRA_VID_PID_COUNT+1] = {
@@ -239,6 +240,7 @@ static struct usb_device_id ti_id_table_5052[4+TI_EXTRA_VID_PID_COUNT+1] = {
static struct usb_device_id ti_id_table_combined[] = {
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
+ { USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_5052_BOOT_PRODUCT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_5152_BOOT_PRODUCT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_5052_EEPROM_PRODUCT_ID) },
@@ -459,13 +461,12 @@ static int ti_startup(struct usb_serial *serial)
/* set up port structures */
for (i = 0; i < serial->num_ports; ++i) {
- tport = kmalloc(sizeof(struct ti_port), GFP_KERNEL);
+ tport = kzalloc(sizeof(struct ti_port), GFP_KERNEL);
if (tport == NULL) {
dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__);
status = -ENOMEM;
goto free_tports;
}
- memset(tport, 0, sizeof(struct ti_port));
spin_lock_init(&tport->tp_lock);
tport->tp_uart_base_addr = (i == 0 ? TI_UART1_BASE_ADDR : TI_UART2_BASE_ADDR);
tport->tp_flags = low_latency ? ASYNC_LOW_LATENCY : 0;
diff --git a/drivers/usb/serial/ti_usb_3410_5052.h b/drivers/usb/serial/ti_usb_3410_5052.h
index 02c1aeb9e1b8..b5541bf991ba 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.h
+++ b/drivers/usb/serial/ti_usb_3410_5052.h
@@ -28,6 +28,7 @@
/* Vendor and product ids */
#define TI_VENDOR_ID 0x0451
#define TI_3410_PRODUCT_ID 0x3410
+#define TI_3410_EZ430_ID 0xF430 /* TI ez430 development tool */
#define TI_5052_BOOT_PRODUCT_ID 0x5052 /* no EEPROM, no firmware */
#define TI_5152_BOOT_PRODUCT_ID 0x5152 /* no EEPROM, no firmware */
#define TI_5052_EEPROM_PRODUCT_ID 0x505A /* EEPROM, no firmware */
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 2cfba8488a93..3d5072f14b8d 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -953,32 +953,28 @@ probe_error:
port = serial->port[i];
if (!port)
continue;
- if (port->read_urb)
- usb_free_urb (port->read_urb);
+ usb_free_urb(port->read_urb);
kfree(port->bulk_in_buffer);
}
for (i = 0; i < num_bulk_out; ++i) {
port = serial->port[i];
if (!port)
continue;
- if (port->write_urb)
- usb_free_urb (port->write_urb);
+ usb_free_urb(port->write_urb);
kfree(port->bulk_out_buffer);
}
for (i = 0; i < num_interrupt_in; ++i) {
port = serial->port[i];
if (!port)
continue;
- if (port->interrupt_in_urb)
- usb_free_urb (port->interrupt_in_urb);
+ usb_free_urb(port->interrupt_in_urb);
kfree(port->interrupt_in_buffer);
}
for (i = 0; i < num_interrupt_out; ++i) {
port = serial->port[i];
if (!port)
continue;
- if (port->interrupt_out_urb)
- usb_free_urb (port->interrupt_out_urb);
+ usb_free_urb(port->interrupt_out_urb);
kfree(port->interrupt_out_buffer);
}
diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c
new file mode 100644
index 000000000000..257a5e436873
--- /dev/null
+++ b/drivers/usb/serial/usb_debug.c
@@ -0,0 +1,65 @@
+/*
+ * USB Debug cable driver
+ *
+ * Copyright (C) 2006 Greg Kroah-Hartman <greg@kroah.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 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 <linux/usb/serial.h>
+
+static struct usb_device_id id_table [] = {
+ { USB_DEVICE(0x0525, 0x127a) },
+ { },
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static struct usb_driver debug_driver = {
+ .name = "debug",
+ .probe = usb_serial_probe,
+ .disconnect = usb_serial_disconnect,
+ .id_table = id_table,
+ .no_dynamic_id = 1,
+};
+
+static struct usb_serial_driver debug_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "debug",
+ },
+ .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 debug_init(void)
+{
+ int retval;
+
+ retval = usb_serial_register(&debug_device);
+ if (retval)
+ return retval;
+ retval = usb_register(&debug_driver);
+ if (retval)
+ usb_serial_deregister(&debug_device);
+ return retval;
+}
+
+static void __exit debug_exit(void)
+{
+ usb_deregister(&debug_driver);
+ usb_serial_deregister(&debug_device);
+}
+
+module_init(debug_init);
+module_exit(debug_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index befe2e11a041..eef5eaa5fa0b 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -348,8 +348,7 @@ static void visor_close (struct usb_serial_port *port, struct file * filp)
/* shutdown our urbs */
usb_kill_urb(port->read_urb);
- if (port->interrupt_in_urb)
- usb_kill_urb(port->interrupt_in_urb);
+ usb_kill_urb(port->interrupt_in_urb);
/* Try to send shutdown message, if the device is gone, this will just fail. */
transfer_buffer = kmalloc (0x12, GFP_KERNEL);
diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c
index 3baf448e300d..3a158d58441f 100644
--- a/drivers/usb/storage/onetouch.c
+++ b/drivers/usb/storage/onetouch.c
@@ -142,10 +142,7 @@ int onetouch_connect_input(struct us_data *ss)
return -ENODEV;
endpoint = &interface->endpoint[2].desc;
- if (!(endpoint->bEndpointAddress & USB_DIR_IN))
- return -ENODEV;
- if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
- != USB_ENDPOINT_XFER_INT)
+ if (!usb_endpoint_is_int_in(endpoint))
return -ENODEV;
pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index efb047f431e8..db8b26012c75 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -1318,6 +1318,16 @@ UNUSUAL_DEV( 0x1019, 0x0c55, 0x0000, 0x0110,
US_SC_DEVICE, US_PR_DEVICE, usb_stor_ucr61s2b_init,
0 ),
+/* Reported by Jaco Kroon <jaco@kroon.co.za>
+ * The usb-storage module found on the Digitech GNX4 (and supposedly other
+ * devices) misbehaves and causes a bunch of invalid I/O errors.
+ */
+UNUSUAL_DEV( 0x1210, 0x0003, 0x0100, 0x0100,
+ "Digitech HMG",
+ "DigiTech Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE ),
+
/* Reported by Vilius Bilinkevicius <vilisas AT xxx DOT lt) */
UNUSUAL_DEV( 0x132b, 0x000b, 0x0001, 0x0001,
"Minolta",
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index b8d6031b0975..b401084b3d22 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -740,18 +740,16 @@ static int get_pipes(struct us_data *us)
ep = &altsetting->endpoint[i].desc;
/* Is it a BULK endpoint? */
- if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
- == USB_ENDPOINT_XFER_BULK) {
+ if (usb_endpoint_xfer_bulk(ep)) {
/* BULK in or out? */
- if (ep->bEndpointAddress & USB_DIR_IN)
+ if (usb_endpoint_dir_in(ep))
ep_in = ep;
else
ep_out = ep;
}
/* Is it an interrupt endpoint? */
- else if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
- == USB_ENDPOINT_XFER_INT) {
+ else if (usb_endpoint_xfer_int(ep)) {
ep_int = ep;
}
}
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 93ffcdd95f50..e973a87fbb01 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1296,14 +1296,14 @@ register_framebuffer(struct fb_info *fb_info)
break;
fb_info->node = i;
- fb_info->class_device = class_device_create(fb_class, NULL, MKDEV(FB_MAJOR, i),
- fb_info->device, "fb%d", i);
- if (IS_ERR(fb_info->class_device)) {
+ fb_info->dev = device_create(fb_class, fb_info->device,
+ MKDEV(FB_MAJOR, i), "fb%d", i);
+ if (IS_ERR(fb_info->dev)) {
/* Not fatal */
- printk(KERN_WARNING "Unable to create class_device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->class_device));
- fb_info->class_device = NULL;
+ printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev));
+ fb_info->dev = NULL;
} else
- fb_init_class_device(fb_info);
+ fb_init_device(fb_info);
if (fb_info->pixmap.addr == NULL) {
fb_info->pixmap.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL);
@@ -1356,8 +1356,8 @@ unregister_framebuffer(struct fb_info *fb_info)
fb_destroy_modelist(&fb_info->modelist);
registered_fb[i]=NULL;
num_registered_fb--;
- fb_cleanup_class_device(fb_info);
- class_device_destroy(fb_class, MKDEV(FB_MAJOR, i));
+ fb_cleanup_device(fb_info);
+ device_destroy(fb_class, MKDEV(FB_MAJOR, i));
event.info = fb_info;
fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event);
return 0;
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
index d3a50417ed9a..323bdf6fc7d5 100644
--- a/drivers/video/fbsysfs.c
+++ b/drivers/video/fbsysfs.c
@@ -73,7 +73,7 @@ EXPORT_SYMBOL(framebuffer_alloc);
*
* @info: frame buffer info structure
*
- * Drop the reference count of the class_device embedded in the
+ * Drop the reference count of the device embedded in the
* framebuffer info structure.
*
*/
@@ -120,10 +120,10 @@ static int mode_string(char *buf, unsigned int offset,
m, mode->xres, mode->yres, v, mode->refresh);
}
-static ssize_t store_mode(struct class_device *class_device, const char * buf,
- size_t count)
+static ssize_t store_mode(struct device *device, struct device_attribute *attr,
+ const char *buf, size_t count)
{
- struct fb_info *fb_info = class_get_devdata(class_device);
+ struct fb_info *fb_info = dev_get_drvdata(device);
char mstr[100];
struct fb_var_screeninfo var;
struct fb_modelist *modelist;
@@ -151,9 +151,10 @@ static ssize_t store_mode(struct class_device *class_device, const char * buf,
return -EINVAL;
}
-static ssize_t show_mode(struct class_device *class_device, char *buf)
+static ssize_t show_mode(struct device *device, struct device_attribute *attr,
+ char *buf)
{
- struct fb_info *fb_info = class_get_devdata(class_device);
+ struct fb_info *fb_info = dev_get_drvdata(device);
if (!fb_info->mode)
return 0;
@@ -161,10 +162,11 @@ static ssize_t show_mode(struct class_device *class_device, char *buf)
return mode_string(buf, 0, fb_info->mode);
}
-static ssize_t store_modes(struct class_device *class_device, const char * buf,
- size_t count)
+static ssize_t store_modes(struct device *device,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
- struct fb_info *fb_info = class_get_devdata(class_device);
+ struct fb_info *fb_info = dev_get_drvdata(device);
LIST_HEAD(old_list);
int i = count / sizeof(struct fb_videomode);
@@ -186,9 +188,10 @@ static ssize_t store_modes(struct class_device *class_device, const char * buf,
return 0;
}
-static ssize_t show_modes(struct class_device *class_device, char *buf)
+static ssize_t show_modes(struct device *device, struct device_attribute *attr,
+ char *buf)
{
- struct fb_info *fb_info = class_get_devdata(class_device);
+ struct fb_info *fb_info = dev_get_drvdata(device);
unsigned int i;
struct list_head *pos;
struct fb_modelist *modelist;
@@ -203,10 +206,10 @@ static ssize_t show_modes(struct class_device *class_device, char *buf)
return i;
}
-static ssize_t store_bpp(struct class_device *class_device, const char * buf,
- size_t count)
+static ssize_t store_bpp(struct device *device, struct device_attribute *attr,
+ const char *buf, size_t count)
{
- struct fb_info *fb_info = class_get_devdata(class_device);
+ struct fb_info *fb_info = dev_get_drvdata(device);
struct fb_var_screeninfo var;
char ** last = NULL;
int err;
@@ -218,16 +221,18 @@ static ssize_t store_bpp(struct class_device *class_device, const char * buf,
return count;
}
-static ssize_t show_bpp(struct class_device *class_device, char *buf)
+static ssize_t show_bpp(struct device *device, struct device_attribute *attr,
+ char *buf)
{
- struct fb_info *fb_info = class_get_devdata(class_device);
+ struct fb_info *fb_info = dev_get_drvdata(device);
return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->var.bits_per_pixel);
}
-static ssize_t store_rotate(struct class_device *class_device, const char *buf,
- size_t count)
+static ssize_t store_rotate(struct device *device,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
- struct fb_info *fb_info = class_get_devdata(class_device);
+ struct fb_info *fb_info = dev_get_drvdata(device);
struct fb_var_screeninfo var;
char **last = NULL;
int err;
@@ -242,17 +247,19 @@ static ssize_t store_rotate(struct class_device *class_device, const char *buf,
}
-static ssize_t show_rotate(struct class_device *class_device, char *buf)
+static ssize_t show_rotate(struct device *device,
+ struct device_attribute *attr, char *buf)
{
- struct fb_info *fb_info = class_get_devdata(class_device);
+ struct fb_info *fb_info = dev_get_drvdata(device);
return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->var.rotate);
}
-static ssize_t store_virtual(struct class_device *class_device,
- const char * buf, size_t count)
+static ssize_t store_virtual(struct device *device,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
- struct fb_info *fb_info = class_get_devdata(class_device);
+ struct fb_info *fb_info = dev_get_drvdata(device);
struct fb_var_screeninfo var;
char *last = NULL;
int err;
@@ -269,23 +276,26 @@ static ssize_t store_virtual(struct class_device *class_device,
return count;
}
-static ssize_t show_virtual(struct class_device *class_device, char *buf)
+static ssize_t show_virtual(struct device *device,
+ struct device_attribute *attr, char *buf)
{
- struct fb_info *fb_info = class_get_devdata(class_device);
+ struct fb_info *fb_info = dev_get_drvdata(device);
return snprintf(buf, PAGE_SIZE, "%d,%d\n", fb_info->var.xres_virtual,
fb_info->var.yres_virtual);
}
-static ssize_t show_stride(struct class_device *class_device, char *buf)
+static ssize_t show_stride(struct device *device,
+ struct device_attribute *attr, char *buf)
{
- struct fb_info *fb_info = class_get_devdata(class_device);
+ struct fb_info *fb_info = dev_get_drvdata(device);
return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->fix.line_length);
}
-static ssize_t store_blank(struct class_device *class_device, const char * buf,
- size_t count)
+static ssize_t store_blank(struct device *device,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
- struct fb_info *fb_info = class_get_devdata(class_device);
+ struct fb_info *fb_info = dev_get_drvdata(device);
char *last = NULL;
int err;
@@ -299,42 +309,48 @@ static ssize_t store_blank(struct class_device *class_device, const char * buf,
return count;
}
-static ssize_t show_blank(struct class_device *class_device, char *buf)
+static ssize_t show_blank(struct device *device,
+ struct device_attribute *attr, char *buf)
{
-// struct fb_info *fb_info = class_get_devdata(class_device);
+// struct fb_info *fb_info = dev_get_drvdata(device);
return 0;
}
-static ssize_t store_console(struct class_device *class_device,
- const char * buf, size_t count)
+static ssize_t store_console(struct device *device,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
-// struct fb_info *fb_info = class_get_devdata(class_device);
+// struct fb_info *fb_info = dev_get_drvdata(device);
return 0;
}
-static ssize_t show_console(struct class_device *class_device, char *buf)
+static ssize_t show_console(struct device *device,
+ struct device_attribute *attr, char *buf)
{
-// struct fb_info *fb_info = class_get_devdata(class_device);
+// struct fb_info *fb_info = dev_get_drvdata(device);
return 0;
}
-static ssize_t store_cursor(struct class_device *class_device,
- const char * buf, size_t count)
+static ssize_t store_cursor(struct device *device,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
-// struct fb_info *fb_info = class_get_devdata(class_device);
+// struct fb_info *fb_info = dev_get_drvdata(device);
return 0;
}
-static ssize_t show_cursor(struct class_device *class_device, char *buf)
+static ssize_t show_cursor(struct device *device,
+ struct device_attribute *attr, char *buf)
{
-// struct fb_info *fb_info = class_get_devdata(class_device);
+// struct fb_info *fb_info = dev_get_drvdata(device);
return 0;
}
-static ssize_t store_pan(struct class_device *class_device, const char * buf,
- size_t count)
+static ssize_t store_pan(struct device *device,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
- struct fb_info *fb_info = class_get_devdata(class_device);
+ struct fb_info *fb_info = dev_get_drvdata(device);
struct fb_var_screeninfo var;
char *last = NULL;
int err;
@@ -355,24 +371,27 @@ static ssize_t store_pan(struct class_device *class_device, const char * buf,
return count;
}
-static ssize_t show_pan(struct class_device *class_device, char *buf)
+static ssize_t show_pan(struct device *device,
+ struct device_attribute *attr, char *buf)
{
- struct fb_info *fb_info = class_get_devdata(class_device);
+ struct fb_info *fb_info = dev_get_drvdata(device);
return snprintf(buf, PAGE_SIZE, "%d,%d\n", fb_info->var.xoffset,
fb_info->var.xoffset);
}
-static ssize_t show_name(struct class_device *class_device, char *buf)
+static ssize_t show_name(struct device *device,
+ struct device_attribute *attr, char *buf)
{
- struct fb_info *fb_info = class_get_devdata(class_device);
+ struct fb_info *fb_info = dev_get_drvdata(device);
return snprintf(buf, PAGE_SIZE, "%s\n", fb_info->fix.id);
}
-static ssize_t store_fbstate(struct class_device *class_device,
- const char *buf, size_t count)
+static ssize_t store_fbstate(struct device *device,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
- struct fb_info *fb_info = class_get_devdata(class_device);
+ struct fb_info *fb_info = dev_get_drvdata(device);
u32 state;
char *last = NULL;
@@ -385,17 +404,19 @@ static ssize_t store_fbstate(struct class_device *class_device,
return count;
}
-static ssize_t show_fbstate(struct class_device *class_device, char *buf)
+static ssize_t show_fbstate(struct device *device,
+ struct device_attribute *attr, char *buf)
{
- struct fb_info *fb_info = class_get_devdata(class_device);
+ struct fb_info *fb_info = dev_get_drvdata(device);
return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->state);
}
#ifdef CONFIG_FB_BACKLIGHT
-static ssize_t store_bl_curve(struct class_device *class_device,
- const char *buf, size_t count)
+static ssize_t store_bl_curve(struct device *device,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
- struct fb_info *fb_info = class_get_devdata(class_device);
+ struct fb_info *fb_info = dev_get_drvdata(device);
u8 tmp_curve[FB_BACKLIGHT_LEVELS];
unsigned int i;
@@ -432,9 +453,10 @@ static ssize_t store_bl_curve(struct class_device *class_device,
return count;
}
-static ssize_t show_bl_curve(struct class_device *class_device, char *buf)
+static ssize_t show_bl_curve(struct device *device,
+ struct device_attribute *attr, char *buf)
{
- struct fb_info *fb_info = class_get_devdata(class_device);
+ struct fb_info *fb_info = dev_get_drvdata(device);
ssize_t len = 0;
unsigned int i;
@@ -465,7 +487,7 @@ static ssize_t show_bl_curve(struct class_device *class_device, char *buf)
/* 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[] = {
+static struct device_attribute 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(console, S_IRUGO|S_IWUSR, show_console, store_console),
@@ -483,17 +505,16 @@ static struct class_device_attribute class_device_attrs[] = {
#endif
};
-int fb_init_class_device(struct fb_info *fb_info)
+int fb_init_device(struct fb_info *fb_info)
{
int i, error = 0;
- class_set_devdata(fb_info->class_device, fb_info);
+ dev_set_drvdata(fb_info->dev, fb_info);
fb_info->class_flag |= FB_SYSFS_FLAG_ATTR;
- for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) {
- error = class_device_create_file(fb_info->class_device,
- &class_device_attrs[i]);
+ for (i = 0; i < ARRAY_SIZE(device_attrs); i++) {
+ error = device_create_file(fb_info->dev, &device_attrs[i]);
if (error)
break;
@@ -501,22 +522,20 @@ int fb_init_class_device(struct fb_info *fb_info)
if (error) {
while (--i >= 0)
- class_device_remove_file(fb_info->class_device,
- &class_device_attrs[i]);
+ device_remove_file(fb_info->dev, &device_attrs[i]);
fb_info->class_flag &= ~FB_SYSFS_FLAG_ATTR;
}
return 0;
}
-void fb_cleanup_class_device(struct fb_info *fb_info)
+void fb_cleanup_device(struct fb_info *fb_info)
{
unsigned int i;
if (fb_info->class_flag & FB_SYSFS_FLAG_ATTR) {
- for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
- class_device_remove_file(fb_info->class_device,
- &class_device_attrs[i]);
+ for (i = 0; i < ARRAY_SIZE(device_attrs); i++)
+ device_remove_file(fb_info->dev, &device_attrs[i]);
fb_info->class_flag &= ~FB_SYSFS_FLAG_ATTR;
}
diff --git a/fs/Kconfig b/fs/Kconfig
index 7b1511d50b05..b3b5aa0edff9 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -972,7 +972,7 @@ config SYSFS
Some system agents rely on the information in sysfs to operate.
/sbin/hotplug uses device and object attributes in sysfs to assist in
- delegating policy decisions, like persistantly naming devices.
+ delegating policy decisions, like persistently naming devices.
sysfs is currently used by the block subsystem to mount the root
partition. If sysfs is disabled you must specify the boot device on
@@ -1145,7 +1145,7 @@ config BEFS_FS
help
The BeOS File System (BeFS) is the native file system of Be, Inc's
BeOS. Notable features include support for arbitrary attributes
- on files and directories, and database-like indeces on selected
+ on files and directories, and database-like indices on selected
attributes. (Also note that this driver doesn't make those features
available at this time). It is a 64 bit filesystem, so it supports
extremely large volumes and files.
diff --git a/fs/aio.c b/fs/aio.c
index ca1c5180a17f..287a1bc7a182 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -367,8 +367,7 @@ void fastcall __put_ioctx(struct kioctx *ctx)
{
unsigned nr_events = ctx->max_reqs;
- if (unlikely(ctx->reqs_active))
- BUG();
+ BUG_ON(ctx->reqs_active);
cancel_delayed_work(&ctx->wq);
flush_workqueue(aio_wq);
@@ -505,8 +504,7 @@ static int __aio_put_req(struct kioctx *ctx, struct kiocb *req)
assert_spin_locked(&ctx->ctx_lock);
req->ki_users --;
- if (unlikely(req->ki_users < 0))
- BUG();
+ BUG_ON(req->ki_users < 0);
if (likely(req->ki_users))
return 0;
list_del(&req->ki_list); /* remove from active_reqs */
diff --git a/fs/bio.c b/fs/bio.c
index c6c07ca5b5a9..50c40ce2cead 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -560,10 +560,8 @@ struct bio *bio_copy_user(request_queue_t *q, unsigned long uaddr,
break;
}
- if (bio_add_pc_page(q, bio, page, bytes, 0) < bytes) {
- ret = -EINVAL;
+ if (bio_add_pc_page(q, bio, page, bytes, 0) < bytes)
break;
- }
len -= bytes;
}
@@ -622,10 +620,9 @@ static struct bio *__bio_map_user_iov(request_queue_t *q,
nr_pages += end - start;
/*
- * transfer and buffer must be aligned to at least hardsector
- * size for now, in the future we can relax this restriction
+ * buffer must be aligned to at least hardsector size for now
*/
- if ((uaddr & queue_dma_alignment(q)) || (len & queue_dma_alignment(q)))
+ if (uaddr & queue_dma_alignment(q))
return ERR_PTR(-EINVAL);
}
@@ -751,7 +748,6 @@ struct bio *bio_map_user_iov(request_queue_t *q, struct block_device *bdev,
int write_to_vm)
{
struct bio *bio;
- int len = 0, i;
bio = __bio_map_user_iov(q, bdev, iov, iov_count, write_to_vm);
@@ -766,18 +762,7 @@ struct bio *bio_map_user_iov(request_queue_t *q, struct block_device *bdev,
*/
bio_get(bio);
- for (i = 0; i < iov_count; i++)
- len += iov[i].iov_len;
-
- if (bio->bi_size == len)
- return bio;
-
- /*
- * don't support partial mappings
- */
- bio_endio(bio, bio->bi_size, 0);
- bio_unmap_user(bio);
- return ERR_PTR(-EINVAL);
+ return bio;
}
static void __bio_unmap_user(struct bio *bio)
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 1ad8c9fcc742..c4fa91b8b62f 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -318,6 +318,7 @@ int cifs_get_inode_info(struct inode **pinode,
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
char *tmp_path;
char *buf = NULL;
+ int adjustTZ = FALSE;
pTcon = cifs_sb->tcon;
cFYI(1,("Getting info on %s", search_path));
@@ -348,6 +349,7 @@ int cifs_get_inode_info(struct inode **pinode,
pfindData, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
+ adjustTZ = TRUE;
}
}
@@ -444,6 +446,10 @@ int cifs_get_inode_info(struct inode **pinode,
inode->i_ctime =
cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
cFYI(0, ("Attributes came in as 0x%x", attr));
+ if(adjustTZ && (pTcon->ses) && (pTcon->ses->server)) {
+ inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj;
+ inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj;
+ }
/* set default mode. will override for dirs below */
if (atomic_read(&cifsInfo->inUse) == 0)
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 0bee8b7e521a..8e259969354b 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -69,17 +69,30 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
rc = -EOPNOTSUPP;
}
-/* if (!rc) */
- {
- /* renew_parental_timestamps(old_file);
- inode->i_nlink++;
- mark_inode_dirty(inode);
- d_instantiate(direntry, inode); */
- /* BB add call to either mark inode dirty or refresh its data and timestamp to current time */
+ d_drop(direntry); /* force new lookup from server of target */
+
+ /* if source file is cached (oplocked) revalidate will not go to server
+ until the file is closed or oplock broken so update nlinks locally */
+ if(old_file->d_inode) {
+ cifsInode = CIFS_I(old_file->d_inode);
+ if(rc == 0) {
+ old_file->d_inode->i_nlink++;
+ old_file->d_inode->i_ctime = CURRENT_TIME;
+ /* parent dir timestamps will update from srv
+ within a second, would it really be worth it
+ to set the parent dir cifs inode time to zero
+ to force revalidate (faster) for it too? */
+ }
+ /* if not oplocked will force revalidate to get info
+ on source file from srv */
+ cifsInode->time = 0;
+
+ /* Will update parent dir timestamps from srv within a second.
+ Would it really be worth it to set the parent dir (cifs
+ inode) time field to zero to force revalidate on parent
+ directory faster ie
+ CIFS_I(inode)->time = 0; */
}
- d_drop(direntry); /* force new lookup from server */
- cifsInode = CIFS_I(old_file->d_inode);
- cifsInode->time = 0; /* will force revalidate to go get info when needed */
cifs_hl_exit:
kfree(fromName);
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index a736d44989c4..137d76c3f90a 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -21,6 +21,7 @@
#include <linux/mount.h>
#include <linux/pagemap.h>
#include <linux/init.h>
+#include <linux/kobject.h>
#include <linux/namei.h>
#include <linux/debugfs.h>
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 136175a69332..f63a7755fe86 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -820,7 +820,8 @@ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat)
crypt_stat->tfm = crypto_alloc_blkcipher(full_alg_name, 0,
CRYPTO_ALG_ASYNC);
kfree(full_alg_name);
- if (!crypt_stat->tfm) {
+ if (IS_ERR(crypt_stat->tfm)) {
+ rc = PTR_ERR(crypt_stat->tfm);
ecryptfs_printk(KERN_ERR, "cryptfs: init_crypt_ctx(): "
"Error initializing cipher [%s]\n",
crypt_stat->cipher);
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index cfc8f81e60d0..c71a6c092ad9 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -138,6 +138,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
struct fuse_entry_out outarg;
struct fuse_conn *fc;
struct fuse_req *req;
+ struct fuse_req *forget_req;
struct dentry *parent;
/* Doesn't hurt to "reset" the validity timeout */
@@ -152,25 +153,33 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
if (IS_ERR(req))
return 0;
+ forget_req = fuse_get_req(fc);
+ if (IS_ERR(forget_req)) {
+ fuse_put_request(fc, req);
+ return 0;
+ }
+
parent = dget_parent(entry);
fuse_lookup_init(req, parent->d_inode, entry, &outarg);
request_send(fc, req);
dput(parent);
err = req->out.h.error;
+ fuse_put_request(fc, req);
/* Zero nodeid is same as -ENOENT */
if (!err && !outarg.nodeid)
err = -ENOENT;
if (!err) {
struct fuse_inode *fi = get_fuse_inode(inode);
if (outarg.nodeid != get_node_id(inode)) {
- fuse_send_forget(fc, req, outarg.nodeid, 1);
+ fuse_send_forget(fc, forget_req,
+ outarg.nodeid, 1);
return 0;
}
spin_lock(&fc->lock);
fi->nlookup ++;
spin_unlock(&fc->lock);
}
- fuse_put_request(fc, req);
+ fuse_put_request(fc, forget_req);
if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
return 0;
@@ -221,6 +230,7 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
struct inode *inode = NULL;
struct fuse_conn *fc = get_fuse_conn(dir);
struct fuse_req *req;
+ struct fuse_req *forget_req;
if (entry->d_name.len > FUSE_NAME_MAX)
return ERR_PTR(-ENAMETOOLONG);
@@ -229,9 +239,16 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
if (IS_ERR(req))
return ERR_PTR(PTR_ERR(req));
+ forget_req = fuse_get_req(fc);
+ if (IS_ERR(forget_req)) {
+ fuse_put_request(fc, req);
+ return ERR_PTR(PTR_ERR(forget_req));
+ }
+
fuse_lookup_init(req, dir, entry, &outarg);
request_send(fc, req);
err = req->out.h.error;
+ fuse_put_request(fc, req);
/* Zero nodeid is same as -ENOENT, but with valid timeout */
if (!err && outarg.nodeid &&
(invalid_nodeid(outarg.nodeid) || !valid_mode(outarg.attr.mode)))
@@ -240,11 +257,11 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
&outarg.attr);
if (!inode) {
- fuse_send_forget(fc, req, outarg.nodeid, 1);
+ fuse_send_forget(fc, forget_req, outarg.nodeid, 1);
return ERR_PTR(-ENOMEM);
}
}
- fuse_put_request(fc, req);
+ fuse_put_request(fc, forget_req);
if (err && err != -ENOENT)
return ERR_PTR(err);
@@ -388,6 +405,13 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
struct fuse_entry_out outarg;
struct inode *inode;
int err;
+ struct fuse_req *forget_req;
+
+ forget_req = fuse_get_req(fc);
+ if (IS_ERR(forget_req)) {
+ fuse_put_request(fc, req);
+ return PTR_ERR(forget_req);
+ }
req->in.h.nodeid = get_node_id(dir);
req->out.numargs = 1;
@@ -395,24 +419,24 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
req->out.args[0].value = &outarg;
request_send(fc, req);
err = req->out.h.error;
- if (err) {
- fuse_put_request(fc, req);
- return err;
- }
+ fuse_put_request(fc, req);
+ if (err)
+ goto out_put_forget_req;
+
err = -EIO;
if (invalid_nodeid(outarg.nodeid))
- goto out_put_request;
+ goto out_put_forget_req;
if ((outarg.attr.mode ^ mode) & S_IFMT)
- goto out_put_request;
+ goto out_put_forget_req;
inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
&outarg.attr);
if (!inode) {
- fuse_send_forget(fc, req, outarg.nodeid, 1);
+ fuse_send_forget(fc, forget_req, outarg.nodeid, 1);
return -ENOMEM;
}
- fuse_put_request(fc, req);
+ fuse_put_request(fc, forget_req);
if (S_ISDIR(inode->i_mode)) {
struct dentry *alias;
@@ -434,8 +458,8 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
fuse_invalidate_attr(dir);
return 0;
- out_put_request:
- fuse_put_request(fc, req);
+ out_put_forget_req:
+ fuse_put_request(fc, forget_req);
return err;
}
diff --git a/fs/jfs/jfs_filsys.h b/fs/jfs/jfs_filsys.h
index 9901928668cf..eb550b339bb8 100644
--- a/fs/jfs/jfs_filsys.h
+++ b/fs/jfs/jfs_filsys.h
@@ -81,7 +81,7 @@
#define JFS_SWAP_BYTES 0x00100000 /* running on big endian computer */
/* Directory index */
-#define JFS_DIR_INDEX 0x00200000 /* Persistant index for */
+#define JFS_DIR_INDEX 0x00200000 /* Persistent index for */
/* directory entries */
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c
index 8dfefe41a8da..75f819dc0255 100644
--- a/fs/nfs/nfsroot.c
+++ b/fs/nfs/nfsroot.c
@@ -98,7 +98,7 @@
static char nfs_root_name[256] __initdata = "";
/* Address of NFS server */
-static __u32 servaddr __initdata = 0;
+static __be32 servaddr __initdata = 0;
/* Name of directory to mount */
static char nfs_path[NFS_MAXPATHLEN] __initdata = { 0, };
@@ -327,7 +327,7 @@ static int __init root_nfs_name(char *name)
*/
static int __init root_nfs_addr(void)
{
- if ((servaddr = root_server_addr) == INADDR_NONE) {
+ if ((servaddr = root_server_addr) == htonl(INADDR_NONE)) {
printk(KERN_ERR "Root-NFS: No NFS server available, giving up.\n");
return -1;
}
@@ -411,7 +411,7 @@ __setup("nfsroot=", nfs_root_setup);
* Construct sockaddr_in from address and port number.
*/
static inline void
-set_sockaddr(struct sockaddr_in *sin, __u32 addr, __u16 port)
+set_sockaddr(struct sockaddr_in *sin, __be32 addr, __be16 port)
{
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = addr;
@@ -468,14 +468,13 @@ static int __init root_nfs_ports(void)
dprintk("Root-NFS: Portmapper on server returned %d "
"as nfsd port\n", port);
}
- nfs_port = htons(nfs_port);
if ((port = root_nfs_getport(NFS_MNT_PROGRAM, mountd_ver, proto)) < 0) {
printk(KERN_ERR "Root-NFS: Unable to get mountd port "
"number from server, using default\n");
port = mountd_port;
}
- mount_port = htons(port);
+ mount_port = port;
dprintk("Root-NFS: mountd port is %d\n", port);
return 0;
@@ -496,7 +495,7 @@ static int __init root_nfs_get_handle(void)
int version = (nfs_data.flags & NFS_MOUNT_VER3) ?
NFS_MNT3_VERSION : NFS_MNT_VERSION;
- set_sockaddr(&sin, servaddr, mount_port);
+ set_sockaddr(&sin, servaddr, htons(mount_port));
status = nfsroot_mount(&sin, nfs_path, &fh, version, protocol);
if (status < 0)
printk(KERN_ERR "Root-NFS: Server returned error %d "
@@ -519,6 +518,6 @@ void * __init nfs_root_data(void)
|| root_nfs_ports() < 0
|| root_nfs_get_handle() < 0)
return NULL;
- set_sockaddr((struct sockaddr_in *) &nfs_data.addr, servaddr, nfs_port);
+ set_sockaddr((struct sockaddr_in *) &nfs_data.addr, servaddr, htons(nfs_port));
return (void*)&nfs_data;
}
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 8df27401d292..795319c54f72 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -442,7 +442,8 @@ static int mountstats_open(struct inode *inode, struct file *file)
if (task) {
task_lock(task);
- namespace = task->nsproxy->namespace;
+ if (task->nsproxy)
+ namespace = task->nsproxy->namespace;
if (namespace)
get_namespace(namespace);
task_unlock(task);
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index b67ce9354048..ac14318c81ba 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -74,7 +74,8 @@ static int reiserfs_file_release(struct inode *inode, struct file *filp)
igrab(inode);
reiserfs_warning(inode->i_sb,
"pinning inode %lu because the "
- "preallocation can't be freed");
+ "preallocation can't be freed",
+ inode->i_ino);
goto out;
}
}
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index cd1bb75ceb24..7280a23ef344 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -1464,7 +1464,7 @@ static int flush_journal_list(struct super_block *s,
}
/* if someone has this block in a newer transaction, just make
- ** sure they are commited, and don't try writing it to disk
+ ** sure they are committed, and don't try writing it to disk
*/
if (pjl) {
if (atomic_read(&pjl->j_commit_left))
@@ -3385,7 +3385,7 @@ static int remove_from_transaction(struct super_block *p_s_sb,
/*
** for any cnode in a journal list, it can only be dirtied of all the
-** transactions that include it are commited to disk.
+** transactions that include it are committed to disk.
** this checks through each transaction, and returns 1 if you are allowed to dirty,
** and 0 if you aren't
**
@@ -3427,7 +3427,7 @@ static int can_dirty(struct reiserfs_journal_cnode *cn)
}
/* syncs the commit blocks, but does not force the real buffers to disk
-** will wait until the current transaction is done/commited before returning
+** will wait until the current transaction is done/committed before returning
*/
int journal_end_sync(struct reiserfs_transaction_handle *th,
struct super_block *p_s_sb, unsigned long nblocks)
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index 7bdb0ed443e1..1e4d68590178 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -41,7 +41,7 @@
#include <linux/reiserfs_xattr.h>
#include <linux/reiserfs_acl.h>
#include <asm/uaccess.h>
-#include <asm/checksum.h>
+#include <net/checksum.h>
#include <linux/smp_lock.h>
#include <linux/stat.h>
#include <asm/semaphore.h>
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 3aa3434621ca..a5782e8c7f07 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -372,6 +372,51 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
return error;
}
+int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent)
+{
+ struct dentry *old_parent_dentry, *new_parent_dentry, *new_dentry;
+ struct sysfs_dirent *new_parent_sd, *sd;
+ int error;
+
+ if (!new_parent)
+ return -EINVAL;
+
+ old_parent_dentry = kobj->parent ?
+ kobj->parent->dentry : sysfs_mount->mnt_sb->s_root;
+ new_parent_dentry = new_parent->dentry;
+
+again:
+ mutex_lock(&old_parent_dentry->d_inode->i_mutex);
+ if (!mutex_trylock(&new_parent_dentry->d_inode->i_mutex)) {
+ mutex_unlock(&old_parent_dentry->d_inode->i_mutex);
+ goto again;
+ }
+
+ new_parent_sd = new_parent_dentry->d_fsdata;
+ sd = kobj->dentry->d_fsdata;
+
+ new_dentry = lookup_one_len(kobj->name, new_parent_dentry,
+ strlen(kobj->name));
+ if (IS_ERR(new_dentry)) {
+ error = PTR_ERR(new_dentry);
+ goto out;
+ } else
+ error = 0;
+ d_add(new_dentry, NULL);
+ d_move(kobj->dentry, new_dentry);
+ dput(new_dentry);
+
+ /* Remove from old parent's list and insert into new parent's list. */
+ list_del_init(&sd->s_sibling);
+ list_add(&sd->s_sibling, &new_parent_sd->s_children);
+
+out:
+ mutex_unlock(&new_parent_dentry->d_inode->i_mutex);
+ mutex_unlock(&old_parent_dentry->d_inode->i_mutex);
+
+ return error;
+}
+
static int sysfs_dir_open(struct inode *inode, struct file *file)
{
struct dentry * dentry = file->f_dentry;
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 298303b5a716..95c165101c98 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -190,6 +190,9 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t
count = PAGE_SIZE - 1;
error = copy_from_user(buffer->page,buf,count);
buffer->needs_read_fill = 1;
+ /* if buf is assumed to contain a string, terminate it by \0,
+ so e.g. sscanf() can scan the string easily */
+ buffer->page[count] = 0;
return error ? -EFAULT : count;
}
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index f338e40bd544..fdd10953b2b6 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -357,7 +357,7 @@ struct device *acpi_get_physical_device(acpi_handle);
/* helper */
acpi_handle acpi_get_child(acpi_handle, acpi_integer);
acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int);
-#define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->firmware_data))
+#define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->archdata.acpi_handle))
#endif /* CONFIG_ACPI */
diff --git a/include/asm-alpha/checksum.h b/include/asm-alpha/checksum.h
index a5c9f08447fb..d3854bbf0a9e 100644
--- a/include/asm-alpha/checksum.h
+++ b/include/asm-alpha/checksum.h
@@ -7,21 +7,20 @@
* This is a version of ip_compute_csum() optimized for IP headers,
* which always checksum on 4 octet boundaries.
*/
-extern unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl);
+extern __sum16 ip_fast_csum(const void *iph, unsigned int ihl);
/*
* computes the checksum of the TCP/UDP pseudo-header
* returns a 16-bit checksum, already complemented
*/
-extern unsigned short int csum_tcpudp_magic(unsigned long saddr,
- unsigned long daddr,
+extern __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
unsigned short len,
unsigned short proto,
- unsigned int sum);
+ __wsum sum);
-unsigned int csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr,
+__wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
unsigned short len, unsigned short proto,
- unsigned int sum);
+ __wsum sum);
/*
* computes the checksum of a memory block at buff, length len,
@@ -35,7 +34,7 @@ unsigned int csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr,
*
* it's best to have buff aligned on a 32-bit boundary
*/
-extern unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
+extern __wsum csum_partial(const void *buff, int len, __wsum sum);
/*
* the same as csum_partial, but copies from src while it
@@ -44,9 +43,9 @@ extern unsigned int csum_partial(const unsigned char * buff, int len, unsigned i
* here even more important to align src and dst on a 32-bit (or even
* better 64-bit) boundary
*/
-unsigned int csum_partial_copy_from_user(const char __user *src, char *dst, int len, unsigned int sum, int *errp);
+__wsum csum_partial_copy_from_user(const void __user *src, void *dst, int len, __wsum sum, int *errp);
-unsigned int csum_partial_copy_nocheck(const char *src, char *dst, int len, unsigned int sum);
+__wsum csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum);
/*
@@ -54,24 +53,23 @@ unsigned int csum_partial_copy_nocheck(const char *src, char *dst, int len, unsi
* in icmp.c
*/
-extern unsigned short ip_compute_csum(unsigned char * buff, int len);
+extern __sum16 ip_compute_csum(const void *buff, int len);
/*
* Fold a partial checksum without adding pseudo headers
*/
-static inline unsigned short csum_fold(unsigned int sum)
+static inline __sum16 csum_fold(__wsum csum)
{
+ u32 sum = (__force u32)csum;
sum = (sum & 0xffff) + (sum >> 16);
sum = (sum & 0xffff) + (sum >> 16);
- return ~sum;
+ return (__force __sum16)~sum;
}
#define _HAVE_ARCH_IPV6_CSUM
-extern unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
- struct in6_addr *daddr,
- __u32 len,
- unsigned short proto,
- unsigned int sum);
-
+extern __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+ const struct in6_addr *daddr,
+ __u32 len, unsigned short proto,
+ __wsum sum);
#endif
diff --git a/include/asm-alpha/device.h b/include/asm-alpha/device.h
new file mode 100644
index 000000000000..d8f9872b0e2d
--- /dev/null
+++ b/include/asm-alpha/device.h
@@ -0,0 +1,7 @@
+/*
+ * Arch specific extensions to struct device
+ *
+ * This file is released under the GPLv2
+ */
+#include <asm-generic/device.h>
+
diff --git a/include/asm-arm/arch-ebsa110/io.h b/include/asm-arm/arch-ebsa110/io.h
index ae048441c9ed..722c5e086285 100644
--- a/include/asm-arm/arch-ebsa110/io.h
+++ b/include/asm-arm/arch-ebsa110/io.h
@@ -27,9 +27,9 @@ void __outw(u16 val, unsigned int port);
u32 __inl(unsigned int port);
void __outl(u32 val, unsigned int port);
-u8 __readb(void __iomem *addr);
-u16 __readw(void __iomem *addr);
-u32 __readl(void __iomem *addr);
+u8 __readb(const volatile void __iomem *addr);
+u16 __readw(const volatile void __iomem *addr);
+u32 __readl(const volatile void __iomem *addr);
void __writeb(u8 val, void __iomem *addr);
void __writew(u16 val, void __iomem *addr);
@@ -64,8 +64,14 @@ void __writel(u32 val, void __iomem *addr);
#define writew(v,b) __writew(v,b)
#define writel(v,b) __writel(v,b)
-#define __arch_ioremap(cookie,sz,c) ((void __iomem *)(cookie))
-#define __arch_iounmap(cookie) do { } while (0)
+static inline void __iomem *__arch_ioremap(unsigned long cookie, size_t size,
+ unsigned int flags)
+{
+ return (void __iomem *)cookie;
+}
+
+#define __arch_ioremap __arch_ioremap
+#define __arch_iounmap(cookie) do { } while (0)
extern void insb(unsigned int port, void *buf, int sz);
extern void insw(unsigned int port, void *buf, int sz);
diff --git a/include/asm-arm/arch-pxa/udc.h b/include/asm-arm/arch-pxa/udc.h
index 121cd241115d..646480d37256 100644
--- a/include/asm-arm/arch-pxa/udc.h
+++ b/include/asm-arm/arch-pxa/udc.h
@@ -4,23 +4,8 @@
* This supports machine-specific differences in how the PXA2xx
* USB Device Controller (UDC) is wired.
*
- * It is set in linux/arch/arm/mach-pxa/<machine>.c and used in
- * the probe routine of linux/drivers/usb/gadget/pxa2xx_udc.c
*/
-struct pxa2xx_udc_mach_info {
- int (*udc_is_connected)(void); /* do we see host? */
- void (*udc_command)(int cmd);
-#define PXA2XX_UDC_CMD_CONNECT 0 /* let host see us */
-#define PXA2XX_UDC_CMD_DISCONNECT 1 /* so host won't see us */
-
- /* Boards following the design guidelines in the developer's manual,
- * with on-chip GPIOs not Lubbock's wierd hardware, can have a sane
- * VBUS IRQ and omit the methods above. Store the GPIO number
- * here; for GPIO 0, also mask in one of the pxa_gpio_mode() bits.
- */
- u16 gpio_vbus; /* high == vbus present */
- u16 gpio_pullup; /* high == pullup activated */
-};
+#include <asm/mach/udc_pxa2xx.h>
extern void pxa_set_udc_info(struct pxa2xx_udc_mach_info *info);
diff --git a/include/asm-arm/checksum.h b/include/asm-arm/checksum.h
index 747bdd31a74b..8c0bb5bb14ee 100644
--- a/include/asm-arm/checksum.h
+++ b/include/asm-arm/checksum.h
@@ -23,7 +23,7 @@
*
* it's best to have buff aligned on a 32-bit boundary
*/
-unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
+__wsum csum_partial(const void *buff, int len, __wsum sum);
/*
* the same as csum_partial, but copies from src while it
@@ -33,26 +33,18 @@ unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
* better 64-bit) boundary
*/
-unsigned int
-csum_partial_copy_nocheck(const char *src, char *dst, int len, int sum);
+__wsum
+csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum);
-unsigned int
-csum_partial_copy_from_user(const char __user *src, char *dst, int len, int sum, int *err_ptr);
-
-/*
- * This is the old (and unsafe) way of doing checksums, a warning message will
- * be printed if it is used and an exception occurs.
- *
- * this functions should go away after some time.
- */
-#define csum_partial_copy(src,dst,len,sum) csum_partial_copy_nocheck(src,dst,len,sum)
+__wsum
+csum_partial_copy_from_user(const void __user *src, void *dst, int len, __wsum sum, int *err_ptr);
/*
* This is a version of ip_compute_csum() optimized for IP headers,
* which always checksum on 4 octet boundaries.
*/
-static inline unsigned short
-ip_fast_csum(unsigned char * iph, unsigned int ihl)
+static inline __sum16
+ip_fast_csum(const void *iph, unsigned int ihl)
{
unsigned int sum, tmp1;
@@ -78,14 +70,13 @@ ip_fast_csum(unsigned char * iph, unsigned int ihl)
: "=r" (sum), "=r" (iph), "=r" (ihl), "=r" (tmp1)
: "1" (iph), "2" (ihl)
: "cc", "memory");
- return sum;
+ return (__force __sum16)sum;
}
/*
* Fold a partial checksum without adding pseudo headers
*/
-static inline unsigned int
-csum_fold(unsigned int sum)
+static inline __sum16 csum_fold(__wsum sum)
{
__asm__(
"adds %0, %1, %1, lsl #16 @ csum_fold \n\
@@ -93,21 +84,25 @@ csum_fold(unsigned int sum)
: "=r" (sum)
: "r" (sum)
: "cc");
- return (~sum) >> 16;
+ return (__force __sum16)(~(__force u32)sum >> 16);
}
-static inline unsigned int
-csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len,
- unsigned int proto, unsigned int sum)
+static inline __wsum
+csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
+ unsigned short proto, __wsum sum)
{
__asm__(
"adds %0, %1, %2 @ csum_tcpudp_nofold \n\
- adcs %0, %0, %3 \n\
- adcs %0, %0, %4 \n\
- adcs %0, %0, %5 \n\
+ adcs %0, %0, %3 \n"
+#ifdef __ARMEB__
+ "adcs %0, %0, %4 \n"
+#else
+ "adcs %0, %0, %4, lsl #8 \n"
+#endif
+ "adcs %0, %0, %5 \n\
adc %0, %0, #0"
: "=&r"(sum)
- : "r" (sum), "r" (daddr), "r" (saddr), "r" (ntohs(len)), "Ir" (ntohs(proto))
+ : "r" (sum), "r" (daddr), "r" (saddr), "r" (len), "Ir" (htons(proto))
: "cc");
return sum;
}
@@ -115,23 +110,27 @@ csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len,
* computes the checksum of the TCP/UDP pseudo-header
* returns a 16-bit checksum, already complemented
*/
-static inline unsigned short int
-csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, unsigned short len,
- unsigned int proto, unsigned int sum)
+static inline __sum16
+csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len,
+ unsigned short proto, __wsum sum)
{
__asm__(
"adds %0, %1, %2 @ csum_tcpudp_magic \n\
- adcs %0, %0, %3 \n\
- adcs %0, %0, %4 \n\
- adcs %0, %0, %5 \n\
+ adcs %0, %0, %3 \n"
+#ifdef __ARMEB__
+ "adcs %0, %0, %4 \n"
+#else
+ "adcs %0, %0, %4, lsl #8 \n"
+#endif
+ "adcs %0, %0, %5 \n\
adc %0, %0, #0 \n\
adds %0, %0, %0, lsl #16 \n\
addcs %0, %0, #0x10000 \n\
mvn %0, %0"
: "=&r"(sum)
- : "r" (sum), "r" (daddr), "r" (saddr), "r" (ntohs(len)), "Ir" (ntohs(proto))
+ : "r" (sum), "r" (daddr), "r" (saddr), "r" (len), "Ir" (htons(proto))
: "cc");
- return sum >> 16;
+ return (__force __sum16)((__force u32)sum >> 16);
}
@@ -139,20 +138,20 @@ csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, unsigned short len,
* this routine is used for miscellaneous IP-like checksums, mainly
* in icmp.c
*/
-static inline unsigned short
-ip_compute_csum(unsigned char * buff, int len)
+static inline __sum16
+ip_compute_csum(const void *buff, int len)
{
return csum_fold(csum_partial(buff, len, 0));
}
#define _HAVE_ARCH_IPV6_CSUM
-extern unsigned long
-__csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr, __u32 len,
- __u32 proto, unsigned int sum);
+extern __wsum
+__csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr, __be32 len,
+ __be32 proto, __wsum sum);
-static inline unsigned short int
-csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr, __u32 len,
- unsigned short proto, unsigned int sum)
+static inline __sum16
+csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr, __u32 len,
+ unsigned short proto, __wsum sum)
{
return csum_fold(__csum_ipv6_magic(saddr, daddr, htonl(len),
htonl(proto), sum));
diff --git a/include/asm-arm/device.h b/include/asm-arm/device.h
new file mode 100644
index 000000000000..d8f9872b0e2d
--- /dev/null
+++ b/include/asm-arm/device.h
@@ -0,0 +1,7 @@
+/*
+ * Arch specific extensions to struct device
+ *
+ * This file is released under the GPLv2
+ */
+#include <asm-generic/device.h>
+
diff --git a/include/asm-arm/dma-mapping.h b/include/asm-arm/dma-mapping.h
index 55eb4dc3253d..666617711c81 100644
--- a/include/asm-arm/dma-mapping.h
+++ b/include/asm-arm/dma-mapping.h
@@ -12,6 +12,10 @@
* uncached, unwrite-buffered mapped memory space for use with DMA
* devices. This is the "generic" version. The PCI specific version
* is in pci.h
+ *
+ * Note: Drivers should NOT use this function directly, as it will break
+ * platforms with CONFIG_DMABOUNCE.
+ * Use the driver DMA support - see dma-mapping.h (dma_sync_*)
*/
extern void consistent_sync(void *kaddr, size_t size, int rw);
diff --git a/include/asm-arm/mach/udc_pxa2xx.h b/include/asm-arm/mach/udc_pxa2xx.h
new file mode 100644
index 000000000000..ff0a95715a07
--- /dev/null
+++ b/include/asm-arm/mach/udc_pxa2xx.h
@@ -0,0 +1,26 @@
+/*
+ * linux/include/asm-arm/mach/udc_pxa2xx.h
+ *
+ * This supports machine-specific differences in how the PXA2xx
+ * USB Device Controller (UDC) is wired.
+ *
+ * It is set in linux/arch/arm/mach-pxa/<machine>.c or in
+ * linux/arch/mach-ixp4xx/<machine>.c and used in
+ * the probe routine of linux/drivers/usb/gadget/pxa2xx_udc.c
+ */
+
+struct pxa2xx_udc_mach_info {
+ int (*udc_is_connected)(void); /* do we see host? */
+ void (*udc_command)(int cmd);
+#define PXA2XX_UDC_CMD_CONNECT 0 /* let host see us */
+#define PXA2XX_UDC_CMD_DISCONNECT 1 /* so host won't see us */
+
+ /* Boards following the design guidelines in the developer's manual,
+ * with on-chip GPIOs not Lubbock's wierd hardware, can have a sane
+ * VBUS IRQ and omit the methods above. Store the GPIO number
+ * here; for GPIO 0, also mask in one of the pxa_gpio_mode() bits.
+ */
+ u16 gpio_vbus; /* high == vbus present */
+ u16 gpio_pullup; /* high == pullup activated */
+};
+
diff --git a/include/asm-arm26/checksum.h b/include/asm-arm26/checksum.h
index d4256d5f3a7c..f2b4b0a403bd 100644
--- a/include/asm-arm26/checksum.h
+++ b/include/asm-arm26/checksum.h
@@ -23,7 +23,7 @@
*
* it's best to have buff aligned on a 32-bit boundary
*/
-unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
+__wsum csum_partial(const void *buff, int len, __wsum sum);
/*
* the same as csum_partial, but copies from src while it
@@ -33,26 +33,18 @@ unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
* better 64-bit) boundary
*/
-unsigned int
-csum_partial_copy_nocheck(const char *src, char *dst, int len, int sum);
+__wsum
+csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum);
-unsigned int
-csum_partial_copy_from_user(const char __user *src, char *dst, int len, int sum, int *err_ptr);
-
-/*
- * This is the old (and unsafe) way of doing checksums, a warning message will
- * be printed if it is used and an exception occurs.
- *
- * this functions should go away after some time.
- */
-#define csum_partial_copy(src,dst,len,sum) csum_partial_copy_nocheck(src,dst,len,sum)
+__wsum
+csum_partial_copy_from_user(const void __user *src, void *dst, int len, __wsum sum, int *err_ptr);
/*
* This is a version of ip_compute_csum() optimized for IP headers,
* which always checksum on 4 octet boundaries.
*/
-static inline unsigned short
-ip_fast_csum(unsigned char * iph, unsigned int ihl)
+static inline __sum16
+ip_fast_csum(const void *iph, unsigned int ihl)
{
unsigned int sum, tmp1;
@@ -78,14 +70,13 @@ ip_fast_csum(unsigned char * iph, unsigned int ihl)
: "=r" (sum), "=r" (iph), "=r" (ihl), "=r" (tmp1)
: "1" (iph), "2" (ihl)
: "cc");
- return sum;
+ return (__force __sum16)sum;
}
/*
* Fold a partial checksum without adding pseudo headers
*/
-static inline unsigned int
-csum_fold(unsigned int sum)
+static inline __sum16 csum_fold(__wsum sum)
{
__asm__(
"adds %0, %1, %1, lsl #16 @ csum_fold \n\
@@ -93,12 +84,12 @@ csum_fold(unsigned int sum)
: "=r" (sum)
: "r" (sum)
: "cc");
- return (~sum) >> 16;
+ return (__force __sum16)(~(__force u32)sum >> 16);
}
-static inline unsigned int
-csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len,
- unsigned int proto, unsigned int sum)
+static inline __wsum
+csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
+ unsigned short proto, __wsum sum)
{
__asm__(
"adds %0, %1, %2 @ csum_tcpudp_nofold \n\
@@ -107,7 +98,7 @@ csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len,
adcs %0, %0, %5 \n\
adc %0, %0, #0"
: "=&r"(sum)
- : "r" (sum), "r" (daddr), "r" (saddr), "r" (ntohs(len)), "Ir" (ntohs(proto))
+ : "r" (sum), "r" (daddr), "r" (saddr), "r" (htons(len)), "Ir" (htons(proto))
: "cc");
return sum;
}
@@ -115,9 +106,9 @@ csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len,
* computes the checksum of the TCP/UDP pseudo-header
* returns a 16-bit checksum, already complemented
*/
-static inline unsigned short int
-csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, unsigned short len,
- unsigned int proto, unsigned int sum)
+static inline __sum16
+csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len,
+ unsigned short proto, __wsum sum)
{
__asm__(
"adds %0, %1, %2 @ csum_tcpudp_magic \n\
@@ -129,9 +120,9 @@ csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, unsigned short len,
addcs %0, %0, #0x10000 \n\
mvn %0, %0"
: "=&r"(sum)
- : "r" (sum), "r" (daddr), "r" (saddr), "r" (ntohs(len)), "Ir" (ntohs(proto))
+ : "r" (sum), "r" (daddr), "r" (saddr), "r" (htons(len)), "Ir" (htons(proto))
: "cc");
- return sum >> 16;
+ return (__force __sum16)((__force u32)sum >> 16);
}
@@ -139,20 +130,20 @@ csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, unsigned short len,
* this routine is used for miscellaneous IP-like checksums, mainly
* in icmp.c
*/
-static inline unsigned short
-ip_compute_csum(unsigned char * buff, int len)
+static inline __sum16
+ip_compute_csum(const void *buff, int len)
{
return csum_fold(csum_partial(buff, len, 0));
}
#define _HAVE_ARCH_IPV6_CSUM
-extern unsigned long
-__csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr, __u32 len,
- __u32 proto, unsigned int sum);
+extern __wsum
+__csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr, __be32 len,
+ __be32 proto, __wsum sum);
-static inline unsigned short int
-csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr, __u32 len,
- unsigned short proto, unsigned int sum)
+static inline __sum16
+csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr, __u32 len,
+ unsigned short proto, __wsum sum)
{
return csum_fold(__csum_ipv6_magic(saddr, daddr, htonl(len),
htonl(proto), sum));
diff --git a/include/asm-arm26/device.h b/include/asm-arm26/device.h
new file mode 100644
index 000000000000..d8f9872b0e2d
--- /dev/null
+++ b/include/asm-arm26/device.h
@@ -0,0 +1,7 @@
+/*
+ * Arch specific extensions to struct device
+ *
+ * This file is released under the GPLv2
+ */
+#include <asm-generic/device.h>
+
diff --git a/include/asm-avr32/checksum.h b/include/asm-avr32/checksum.h
index 41b7af09edc4..af9d53f0f5d2 100644
--- a/include/asm-avr32/checksum.h
+++ b/include/asm-avr32/checksum.h
@@ -20,8 +20,7 @@
*
* it's best to have buff aligned on a 32-bit boundary
*/
-unsigned int csum_partial(const unsigned char * buff, int len,
- unsigned int sum);
+__wsum csum_partial(const void *buff, int len, __wsum sum);
/*
* the same as csum_partial, but copies from src while it
@@ -30,8 +29,8 @@ unsigned int csum_partial(const unsigned char * buff, int len,
* here even more important to align src and dst on a 32-bit (or even
* better 64-bit) boundary
*/
-unsigned int csum_partial_copy_generic(const char *src, char *dst, int len,
- int sum, int *src_err_ptr,
+__wsum csum_partial_copy_generic(const void *src, void *dst, int len,
+ __wsum sum, int *src_err_ptr,
int *dst_err_ptr);
/*
@@ -42,17 +41,17 @@ unsigned int csum_partial_copy_generic(const char *src, char *dst, int len,
* verify_area().
*/
static inline
-unsigned int csum_partial_copy_nocheck(const char *src, char *dst,
- int len, int sum)
+__wsum csum_partial_copy_nocheck(const void *src, void *dst,
+ int len, __wsum sum)
{
return csum_partial_copy_generic(src, dst, len, sum, NULL, NULL);
}
static inline
-unsigned int csum_partial_copy_from_user (const char __user *src, char *dst,
- int len, int sum, int *err_ptr)
+__wsum csum_partial_copy_from_user(const void __user *src, void *dst,
+ int len, __wsum sum, int *err_ptr)
{
- return csum_partial_copy_generic((const char __force *)src, dst, len,
+ return csum_partial_copy_generic((const void __force *)src, dst, len,
sum, err_ptr, NULL);
}
@@ -60,8 +59,7 @@ unsigned int csum_partial_copy_from_user (const char __user *src, char *dst,
* This is a version of ip_compute_csum() optimized for IP headers,
* which always checksum on 4 octet boundaries.
*/
-static inline unsigned short ip_fast_csum(unsigned char *iph,
- unsigned int ihl)
+static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
{
unsigned int sum, tmp;
@@ -90,14 +88,14 @@ static inline unsigned short ip_fast_csum(unsigned char *iph,
: "=r"(sum), "=r"(iph), "=r"(ihl), "=r"(tmp)
: "1"(iph), "2"(ihl)
: "memory", "cc");
- return sum;
+ return (__force __sum16)sum;
}
/*
* Fold a partial checksum
*/
-static inline unsigned int csum_fold(unsigned int sum)
+static inline __sum16 csum_fold(__wsum sum)
{
unsigned int tmp;
@@ -109,21 +107,20 @@ static inline unsigned int csum_fold(unsigned int sum)
: "=&r"(sum), "=&r"(tmp)
: "0"(sum));
- return ~sum;
+ return (__force __sum16)~sum;
}
-static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
- unsigned long daddr,
+static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
unsigned short len,
unsigned short proto,
- unsigned int sum)
+ __wsum sum)
{
asm(" add %0, %1\n"
" adc %0, %0, %2\n"
" adc %0, %0, %3\n"
" acr %0"
: "=r"(sum)
- : "r"(daddr), "r"(saddr), "r"(ntohs(len) | (proto << 16)),
+ : "r"(daddr), "r"(saddr), "r"(len + proto),
"0"(sum)
: "cc");
@@ -134,11 +131,10 @@ static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
* computes the checksum of the TCP/UDP pseudo-header
* returns a 16-bit checksum, already complemented
*/
-static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
- unsigned long daddr,
+static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
unsigned short len,
unsigned short proto,
- unsigned int sum)
+ __wsum sum)
{
return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
}
@@ -148,7 +144,7 @@ static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
* in icmp.c
*/
-static inline unsigned short ip_compute_csum(unsigned char * buff, int len)
+static inline __sum16 ip_compute_csum(const void *buff, int len)
{
return csum_fold(csum_partial(buff, len, 0));
}
diff --git a/include/asm-avr32/device.h b/include/asm-avr32/device.h
new file mode 100644
index 000000000000..d8f9872b0e2d
--- /dev/null
+++ b/include/asm-avr32/device.h
@@ -0,0 +1,7 @@
+/*
+ * Arch specific extensions to struct device
+ *
+ * This file is released under the GPLv2
+ */
+#include <asm-generic/device.h>
+
diff --git a/include/asm-cris/arch-v10/checksum.h b/include/asm-cris/arch-v10/checksum.h
index 633f234f336b..b8000c5d7fe1 100644
--- a/include/asm-cris/arch-v10/checksum.h
+++ b/include/asm-cris/arch-v10/checksum.h
@@ -8,11 +8,11 @@
* to split all of those into 16-bit components, then add.
*/
-static inline unsigned int
-csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len,
- unsigned short proto, unsigned int sum)
+static inline __wsum
+csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
+ unsigned short proto, __wsum sum)
{
- int res;
+ __wsum res;
__asm__ ("add.d %2, %0\n\t"
"ax\n\t"
"add.d %3, %0\n\t"
@@ -21,7 +21,7 @@ csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len,
"ax\n\t"
"addq 0, %0\n"
: "=r" (res)
- : "0" (sum), "r" (daddr), "r" (saddr), "r" ((ntohs(len) << 16) + (proto << 8)));
+ : "0" (sum), "r" (daddr), "r" (saddr), "r" ((len + proto) << 8));
return res;
}
diff --git a/include/asm-cris/arch-v32/checksum.h b/include/asm-cris/arch-v32/checksum.h
index 97ef89efea62..e5dcfce6e0dc 100644
--- a/include/asm-cris/arch-v32/checksum.h
+++ b/include/asm-cris/arch-v32/checksum.h
@@ -9,11 +9,11 @@
* checksum. Which means it would be necessary to split all those into
* 16-bit components and then add.
*/
-static inline unsigned int
-csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr,
- unsigned short len, unsigned short proto, unsigned int sum)
+static inline __wsum
+csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
+ unsigned short len, unsigned short proto, __wsum sum)
{
- int res;
+ __wsum res;
__asm__ __volatile__ ("add.d %2, %0\n\t"
"addc %3, %0\n\t"
@@ -21,7 +21,7 @@ csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr,
"addc 0, %0\n\t"
: "=r" (res)
: "0" (sum), "r" (daddr), "r" (saddr), \
- "r" ((ntohs(len) << 16) + (proto << 8)));
+ "r" ((len + proto) << 8));
return res;
}
diff --git a/include/asm-cris/checksum.h b/include/asm-cris/checksum.h
index 26a7719bbb84..180dbf2757b0 100644
--- a/include/asm-cris/checksum.h
+++ b/include/asm-cris/checksum.h
@@ -17,7 +17,7 @@
*
* it's best to have buff aligned on a 32-bit boundary
*/
-unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
+__wsum csum_partial(const void *buff, int len, __wsum sum);
/*
* the same as csum_partial, but copies from src while it
@@ -27,26 +27,23 @@ unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
* better 64-bit) boundary
*/
-unsigned int csum_partial_copy_nocheck(const char *src, char *dst,
- int len, unsigned int sum);
+__wsum csum_partial_copy_nocheck(const void *src, void *dst,
+ int len, __wsum sum);
/*
* Fold a partial checksum into a word
*/
-static inline unsigned int csum_fold(unsigned int sum)
+static inline __sum16 csum_fold(__wsum csum)
{
- /* the while loop is unnecessary really, it's always enough with two
- iterations */
-
- while(sum >> 16)
- sum = (sum & 0xffff) + (sum >> 16); /* add in end-around carry */
-
- return ~sum;
+ u32 sum = (__force u32)csum;
+ sum = (sum & 0xffff) + (sum >> 16); /* add in end-around carry */
+ sum = (sum & 0xffff) + (sum >> 16); /* add in end-around carry */
+ return (__force __sum16)~sum;
}
-extern unsigned int csum_partial_copy_from_user(const char *src, char *dst,
- int len, unsigned int sum,
+extern __wsum csum_partial_copy_from_user(const void __user *src, void *dst,
+ int len, __wsum sum,
int *errptr);
/*
@@ -55,8 +52,7 @@ extern unsigned int csum_partial_copy_from_user(const char *src, char *dst,
*
*/
-static inline unsigned short ip_fast_csum(unsigned char * iph,
- unsigned int ihl)
+static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
{
return csum_fold(csum_partial(iph, ihl * 4, 0));
}
@@ -66,11 +62,10 @@ static inline unsigned short ip_fast_csum(unsigned char * iph,
* returns a 16-bit checksum, already complemented
*/
-static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
- unsigned long daddr,
+static inline __sum16 int csum_tcpudp_magic(__be32 saddr, __be32 daddr,
unsigned short len,
unsigned short proto,
- unsigned int sum)
+ __wsum sum)
{
return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
}
@@ -80,7 +75,8 @@ static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
* in icmp.c
*/
-static inline unsigned short ip_compute_csum(unsigned char * buff, int len) {
+static inline __sum16 ip_compute_csum(const void *buff, int len)
+{
return csum_fold (csum_partial(buff, len, 0));
}
diff --git a/include/asm-cris/device.h b/include/asm-cris/device.h
new file mode 100644
index 000000000000..d8f9872b0e2d
--- /dev/null
+++ b/include/asm-cris/device.h
@@ -0,0 +1,7 @@
+/*
+ * Arch specific extensions to struct device
+ *
+ * This file is released under the GPLv2
+ */
+#include <asm-generic/device.h>
+
diff --git a/include/asm-frv/checksum.h b/include/asm-frv/checksum.h
index 42bf0db2287a..9b1689850187 100644
--- a/include/asm-frv/checksum.h
+++ b/include/asm-frv/checksum.h
@@ -26,7 +26,7 @@
*
* it's best to have buff aligned on a 32-bit boundary
*/
-unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
+__wsum csum_partial(const void *buff, int len, __wsum sum);
/*
* the same as csum_partial, but copies from src while it
@@ -35,7 +35,7 @@ unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
* here even more important to align src and dst on a 32-bit (or even
* better 64-bit) boundary
*/
-unsigned int csum_partial_copy(const char *src, char *dst, int len, int sum);
+__wsum csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum);
/*
* the same as csum_partial_copy, but copies from user space.
@@ -43,11 +43,8 @@ unsigned int csum_partial_copy(const char *src, char *dst, int len, int sum);
* here even more important to align src and dst on a 32-bit (or even
* better 64-bit) boundary
*/
-extern unsigned int csum_partial_copy_from_user(const char __user *src, char *dst,
- int len, int sum, int *csum_err);
-
-#define csum_partial_copy_nocheck(src, dst, len, sum) \
- csum_partial_copy((src), (dst), (len), (sum))
+extern __wsum csum_partial_copy_from_user(const void __user *src, void *dst,
+ int len, __wsum sum, int *csum_err);
/*
* This is a version of ip_compute_csum() optimized for IP headers,
@@ -55,7 +52,7 @@ extern unsigned int csum_partial_copy_from_user(const char __user *src, char *ds
*
*/
static inline
-unsigned short ip_fast_csum(unsigned char *iph, unsigned int ihl)
+__sum16 ip_fast_csum(const void *iph, unsigned int ihl)
{
unsigned int tmp, inc, sum = 0;
@@ -81,13 +78,13 @@ unsigned short ip_fast_csum(unsigned char *iph, unsigned int ihl)
: "icc0", "icc1"
);
- return ~sum;
+ return (__force __sum16)~sum;
}
/*
* Fold a partial checksum
*/
-static inline unsigned int csum_fold(unsigned int sum)
+static inline __sum16 csum_fold(__wsum sum)
{
unsigned int tmp;
@@ -100,16 +97,16 @@ static inline unsigned int csum_fold(unsigned int sum)
: "0"(sum)
);
- return ~sum;
+ return (__force __sum16)~sum;
}
/*
* computes the checksum of the TCP/UDP pseudo-header
* returns a 16-bit checksum, already complemented
*/
-static inline unsigned int
-csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len,
- unsigned short proto, unsigned int sum)
+static inline __wsum
+csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
+ unsigned short proto, __wsum sum)
{
asm(" addcc %1,%0,%0,icc0 \n"
" addxcc %2,%0,%0,icc0 \n"
@@ -122,9 +119,9 @@ csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len,
return sum;
}
-static inline unsigned short int
-csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, unsigned short len,
- unsigned short proto, unsigned int sum)
+static inline __sum16
+csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len,
+ unsigned short proto, __wsum sum)
{
return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
}
@@ -133,12 +130,12 @@ csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, unsigned short len,
* this routine is used for miscellaneous IP-like checksums, mainly
* in icmp.c
*/
-extern unsigned short ip_compute_csum(const unsigned char * buff, int len);
+extern __sum16 ip_compute_csum(const void *buff, int len);
#define _HAVE_ARCH_IPV6_CSUM
-static inline unsigned short int
-csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr,
- __u32 len, unsigned short proto, unsigned int sum)
+static inline __sum16
+csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr,
+ __u32 len, unsigned short proto, __wsum sum)
{
unsigned long tmp, tmp2;
@@ -177,7 +174,7 @@ csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr,
: "icc0"
);
- return ~sum;
+ return (__force __sum16)~sum;
}
#endif /* _ASM_CHECKSUM_H */
diff --git a/include/asm-frv/device.h b/include/asm-frv/device.h
new file mode 100644
index 000000000000..d8f9872b0e2d
--- /dev/null
+++ b/include/asm-frv/device.h
@@ -0,0 +1,7 @@
+/*
+ * Arch specific extensions to struct device
+ *
+ * This file is released under the GPLv2
+ */
+#include <asm-generic/device.h>
+
diff --git a/include/asm-generic/device.h b/include/asm-generic/device.h
new file mode 100644
index 000000000000..c17c9600f220
--- /dev/null
+++ b/include/asm-generic/device.h
@@ -0,0 +1,12 @@
+/*
+ * Arch specific extensions to struct device
+ *
+ * This file is released under the GPLv2
+ */
+#ifndef _ASM_GENERIC_DEVICE_H
+#define _ASM_GENERIC_DEVICE_H
+
+struct dev_archdata {
+};
+
+#endif /* _ASM_GENERIC_DEVICE_H */
diff --git a/include/asm-h8300/checksum.h b/include/asm-h8300/checksum.h
index 3051931dd301..98724e12508c 100644
--- a/include/asm-h8300/checksum.h
+++ b/include/asm-h8300/checksum.h
@@ -13,7 +13,7 @@
*
* it's best to have buff aligned on a 32-bit boundary
*/
-unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
+__wsum csum_partial(const void *buff, int len, __wsum sum);
/*
* the same as csum_partial, but copies from src while it
@@ -23,7 +23,7 @@ unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
* better 64-bit) boundary
*/
-unsigned int csum_partial_copy(const char *src, char *dst, int len, int sum);
+__wsum csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum);
/*
@@ -33,20 +33,17 @@ unsigned int csum_partial_copy(const char *src, char *dst, int len, int sum);
* better 64-bit) boundary
*/
-extern unsigned int csum_partial_copy_from_user(const char *src, char *dst,
- int len, int sum, int *csum_err);
+extern __wsum csum_partial_copy_from_user(const void __user *src, void *dst,
+ int len, __wsum sum, int *csum_err);
-#define csum_partial_copy_nocheck(src, dst, len, sum) \
- csum_partial_copy((src), (dst), (len), (sum))
-
-unsigned short ip_fast_csum(unsigned char *iph, unsigned int ihl);
+__sum16 ip_fast_csum(const void *iph, unsigned int ihl);
/*
* Fold a partial checksum
*/
-static inline unsigned int csum_fold(unsigned int sum)
+static inline __sum16 csum_fold(__wsum sum)
{
__asm__("mov.l %0,er0\n\t"
"add.w e0,r0\n\t"
@@ -58,7 +55,7 @@ static inline unsigned int csum_fold(unsigned int sum)
: "=r"(sum)
: "0"(sum)
: "er0");
- return ~sum;
+ return (__force __sum16)~sum;
}
@@ -67,9 +64,9 @@ static inline unsigned int csum_fold(unsigned int sum)
* returns a 16-bit checksum, already complemented
*/
-static inline unsigned int
-csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len,
- unsigned short proto, unsigned int sum)
+static inline __wsum
+csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
+ unsigned short proto, __wsum sum)
{
__asm__ ("sub.l er0,er0\n\t"
"add.l %2,%0\n\t"
@@ -88,9 +85,9 @@ csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len,
return sum;
}
-static inline unsigned short int
-csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, unsigned short len,
- unsigned short proto, unsigned int sum)
+static inline __sum16
+csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len,
+ unsigned short proto, __wsum sum)
{
return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
}
@@ -100,6 +97,6 @@ csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, unsigned short len,
* in icmp.c
*/
-extern unsigned short ip_compute_csum(const unsigned char * buff, int len);
+extern __sum16 ip_compute_csum(const void *buff, int len);
#endif /* _H8300_CHECKSUM_H */
diff --git a/include/asm-h8300/device.h b/include/asm-h8300/device.h
new file mode 100644
index 000000000000..d8f9872b0e2d
--- /dev/null
+++ b/include/asm-h8300/device.h
@@ -0,0 +1,7 @@
+/*
+ * Arch specific extensions to struct device
+ *
+ * This file is released under the GPLv2
+ */
+#include <asm-generic/device.h>
+
diff --git a/include/asm-i386/checksum.h b/include/asm-i386/checksum.h
index 67d3630c4e89..75194abbe8ee 100644
--- a/include/asm-i386/checksum.h
+++ b/include/asm-i386/checksum.h
@@ -17,7 +17,7 @@
*
* it's best to have buff aligned on a 32-bit boundary
*/
-asmlinkage unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
+asmlinkage __wsum csum_partial(const void *buff, int len, __wsum sum);
/*
* the same as csum_partial, but copies from src while it
@@ -27,8 +27,8 @@ asmlinkage unsigned int csum_partial(const unsigned char * buff, int len, unsign
* better 64-bit) boundary
*/
-asmlinkage unsigned int csum_partial_copy_generic(const unsigned char *src, unsigned char *dst,
- int len, int sum, int *src_err_ptr, int *dst_err_ptr);
+asmlinkage __wsum csum_partial_copy_generic(const void *src, void *dst,
+ int len, __wsum sum, int *src_err_ptr, int *dst_err_ptr);
/*
* Note: when you get a NULL pointer exception here this means someone
@@ -38,18 +38,18 @@ asmlinkage unsigned int csum_partial_copy_generic(const unsigned char *src, unsi
* access_ok().
*/
static __inline__
-unsigned int csum_partial_copy_nocheck (const unsigned char *src, unsigned char *dst,
- int len, int sum)
+__wsum csum_partial_copy_nocheck (const void *src, void *dst,
+ int len, __wsum sum)
{
return csum_partial_copy_generic ( src, dst, len, sum, NULL, NULL);
}
static __inline__
-unsigned int csum_partial_copy_from_user(const unsigned char __user *src, unsigned char *dst,
- int len, int sum, int *err_ptr)
+__wsum csum_partial_copy_from_user(const void __user *src, void *dst,
+ int len, __wsum sum, int *err_ptr)
{
might_sleep();
- return csum_partial_copy_generic((__force unsigned char *)src, dst,
+ return csum_partial_copy_generic((__force void *)src, dst,
len, sum, err_ptr, NULL);
}
@@ -60,8 +60,7 @@ unsigned int csum_partial_copy_from_user(const unsigned char __user *src, unsign
* By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
* Arnt Gulbrandsen.
*/
-static inline unsigned short ip_fast_csum(unsigned char * iph,
- unsigned int ihl)
+static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
{
unsigned int sum;
@@ -89,29 +88,29 @@ static inline unsigned short ip_fast_csum(unsigned char * iph,
: "=r" (sum), "=r" (iph), "=r" (ihl)
: "1" (iph), "2" (ihl)
: "memory");
- return(sum);
+ return (__force __sum16)sum;
}
/*
* Fold a partial checksum
*/
-static inline unsigned int csum_fold(unsigned int sum)
+static inline __sum16 csum_fold(__wsum sum)
{
__asm__(
"addl %1, %0 ;\n"
"adcl $0xffff, %0 ;\n"
: "=r" (sum)
- : "r" (sum << 16), "0" (sum & 0xffff0000)
+ : "r" ((__force u32)sum << 16),
+ "0" ((__force u32)sum & 0xffff0000)
);
- return (~sum) >> 16;
+ return (__force __sum16)(~(__force u32)sum >> 16);
}
-static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
- unsigned long daddr,
- unsigned short len,
- unsigned short proto,
- unsigned int sum)
+static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
+ unsigned short len,
+ unsigned short proto,
+ __wsum sum)
{
__asm__(
"addl %1, %0 ;\n"
@@ -119,7 +118,7 @@ static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
"adcl %3, %0 ;\n"
"adcl $0, %0 ;\n"
: "=r" (sum)
- : "g" (daddr), "g"(saddr), "g"((ntohs(len)<<16)+proto*256), "0"(sum));
+ : "g" (daddr), "g"(saddr), "g"((len + proto) << 8), "0"(sum));
return sum;
}
@@ -127,11 +126,10 @@ static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
* computes the checksum of the TCP/UDP pseudo-header
* returns a 16-bit checksum, already complemented
*/
-static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
- unsigned long daddr,
+static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
unsigned short len,
unsigned short proto,
- unsigned int sum)
+ __wsum sum)
{
return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
}
@@ -141,17 +139,16 @@ static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
* in icmp.c
*/
-static inline unsigned short ip_compute_csum(unsigned char * buff, int len)
+static inline __sum16 ip_compute_csum(const void *buff, int len)
{
return csum_fold (csum_partial(buff, len, 0));
}
#define _HAVE_ARCH_IPV6_CSUM
-static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
- struct in6_addr *daddr,
- __u32 len,
- unsigned short proto,
- unsigned int sum)
+static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+ const struct in6_addr *daddr,
+ __u32 len, unsigned short proto,
+ __wsum sum)
{
__asm__(
"addl 0(%1), %0 ;\n"
@@ -176,19 +173,19 @@ static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
* Copy and checksum to user
*/
#define HAVE_CSUM_COPY_USER
-static __inline__ unsigned int csum_and_copy_to_user(const unsigned char *src,
- unsigned char __user *dst,
- int len, int sum,
+static __inline__ __wsum csum_and_copy_to_user(const void *src,
+ void __user *dst,
+ int len, __wsum sum,
int *err_ptr)
{
might_sleep();
if (access_ok(VERIFY_WRITE, dst, len))
- return csum_partial_copy_generic(src, (__force unsigned char *)dst, len, sum, NULL, err_ptr);
+ return csum_partial_copy_generic(src, (__force void *)dst, len, sum, NULL, err_ptr);
if (len)
*err_ptr = -EFAULT;
- return -1; /* invalid checksum */
+ return (__force __wsum)-1; /* invalid checksum */
}
#endif
diff --git a/include/asm-i386/device.h b/include/asm-i386/device.h
new file mode 100644
index 000000000000..849604c70e6b
--- /dev/null
+++ b/include/asm-i386/device.h
@@ -0,0 +1,15 @@
+/*
+ * Arch specific extensions to struct device
+ *
+ * This file is released under the GPLv2
+ */
+#ifndef _ASM_I386_DEVICE_H
+#define _ASM_I386_DEVICE_H
+
+struct dev_archdata {
+#ifdef CONFIG_ACPI
+ void *acpi_handle;
+#endif
+};
+
+#endif /* _ASM_I386_DEVICE_H */
diff --git a/include/asm-i386/mach-summit/mach_apic.h b/include/asm-i386/mach-summit/mach_apic.h
index ef0671e5d5c5..43e5bd8f4a19 100644
--- a/include/asm-i386/mach-summit/mach_apic.h
+++ b/include/asm-i386/mach-summit/mach_apic.h
@@ -88,7 +88,11 @@ static inline void clustered_apic_check(void)
static inline int apicid_to_node(int logical_apicid)
{
+#ifdef CONFIG_SMP
return apicid_2_node[hard_smp_processor_id()];
+#else
+ return 0;
+#endif
}
/* Mapping from cpu number to logical apicid */
diff --git a/include/asm-ia64/checksum.h b/include/asm-ia64/checksum.h
index 1f230ff8ea81..bd40f4756ce1 100644
--- a/include/asm-ia64/checksum.h
+++ b/include/asm-ia64/checksum.h
@@ -10,23 +10,21 @@
* This is a version of ip_compute_csum() optimized for IP headers,
* which always checksum on 4 octet boundaries.
*/
-extern unsigned short ip_fast_csum (unsigned char * iph, unsigned int ihl);
+extern __sum16 ip_fast_csum(const void *iph, unsigned int ihl);
/*
* Computes the checksum of the TCP/UDP pseudo-header returns a 16-bit
* checksum, already complemented
*/
-extern unsigned short int csum_tcpudp_magic (unsigned long saddr,
- unsigned long daddr,
+extern __sum16 csum_tcpudp_magic (__be32 saddr, __be32 daddr,
unsigned short len,
unsigned short proto,
- unsigned int sum);
+ __wsum sum);
-extern unsigned int csum_tcpudp_nofold (unsigned long saddr,
- unsigned long daddr,
+extern __wsum csum_tcpudp_nofold (__be32 saddr, __be32 daddr,
unsigned short len,
unsigned short proto,
- unsigned int sum);
+ __wsum sum);
/*
* Computes the checksum of a memory block at buff, length len,
@@ -40,8 +38,7 @@ extern unsigned int csum_tcpudp_nofold (unsigned long saddr,
*
* it's best to have buff aligned on a 32-bit boundary
*/
-extern unsigned int csum_partial (const unsigned char * buff, int len,
- unsigned int sum);
+extern __wsum csum_partial(const void *buff, int len, __wsum sum);
/*
* Same as csum_partial, but copies from src while it checksums.
@@ -49,28 +46,28 @@ extern unsigned int csum_partial (const unsigned char * buff, int len,
* Here it is even more important to align src and dst on a 32-bit (or
* even better 64-bit) boundary.
*/
-extern unsigned int csum_partial_copy_from_user (const char *src, char *dst,
- int len, unsigned int sum,
+extern __wsum csum_partial_copy_from_user(const void __user *src, void *dst,
+ int len, __wsum sum,
int *errp);
-extern unsigned int csum_partial_copy_nocheck (const char *src, char *dst,
- int len, unsigned int sum);
+extern __wsum csum_partial_copy_nocheck(const void *src, void *dst,
+ int len, __wsum sum);
/*
* This routine is used for miscellaneous IP-like checksums, mainly in
* icmp.c
*/
-extern unsigned short ip_compute_csum (unsigned char *buff, int len);
+extern __sum16 ip_compute_csum(const void *buff, int len);
/*
* Fold a partial checksum without adding pseudo headers.
*/
-static inline unsigned short
-csum_fold (unsigned int sum)
+static inline __sum16 csum_fold(__wsum csum)
{
+ u32 sum = (__force u32)csum;
sum = (sum & 0xffff) + (sum >> 16);
sum = (sum & 0xffff) + (sum >> 16);
- return ~sum;
+ return (__force __sum16)~sum;
}
#endif /* _ASM_IA64_CHECKSUM_H */
diff --git a/include/asm-ia64/device.h b/include/asm-ia64/device.h
new file mode 100644
index 000000000000..3db6daf7f251
--- /dev/null
+++ b/include/asm-ia64/device.h
@@ -0,0 +1,15 @@
+/*
+ * Arch specific extensions to struct device
+ *
+ * This file is released under the GPLv2
+ */
+#ifndef _ASM_IA64_DEVICE_H
+#define _ASM_IA64_DEVICE_H
+
+struct dev_archdata {
+#ifdef CONFIG_ACPI
+ void *acpi_handle;
+#endif
+};
+
+#endif /* _ASM_IA64_DEVICE_H */
diff --git a/include/asm-ia64/io.h b/include/asm-ia64/io.h
index 855c30af72a9..6311e168cd34 100644
--- a/include/asm-ia64/io.h
+++ b/include/asm-ia64/io.h
@@ -32,7 +32,7 @@
*/
#define IO_SPACE_LIMIT 0xffffffffffffffffUL
-#define MAX_IO_SPACES_BITS 4
+#define MAX_IO_SPACES_BITS 8
#define MAX_IO_SPACES (1UL << MAX_IO_SPACES_BITS)
#define IO_SPACE_BITS 24
#define IO_SPACE_SIZE (1UL << IO_SPACE_BITS)
diff --git a/include/asm-ia64/machvec.h b/include/asm-ia64/machvec.h
index 7ffbddf5306f..8f784f8e45b0 100644
--- a/include/asm-ia64/machvec.h
+++ b/include/asm-ia64/machvec.h
@@ -36,6 +36,7 @@ typedef int ia64_mv_pci_legacy_read_t (struct pci_bus *, u16 port, u32 *val,
typedef int ia64_mv_pci_legacy_write_t (struct pci_bus *, u16 port, u32 val,
u8 size);
typedef void ia64_mv_migrate_t(struct task_struct * task);
+typedef void ia64_mv_pci_fixup_bus_t (struct pci_bus *);
/* DMA-mapping interface: */
typedef void ia64_mv_dma_init (void);
@@ -95,6 +96,11 @@ machvec_noop_task (struct task_struct *task)
{
}
+static inline void
+machvec_noop_bus (struct pci_bus *bus)
+{
+}
+
extern void machvec_setup (char **);
extern void machvec_timer_interrupt (int, void *);
extern void machvec_dma_sync_single (struct device *, dma_addr_t, size_t, int);
@@ -159,6 +165,7 @@ extern void machvec_tlb_migrate_finish (struct mm_struct *);
# define platform_migrate ia64_mv.migrate
# define platform_setup_msi_irq ia64_mv.setup_msi_irq
# define platform_teardown_msi_irq ia64_mv.teardown_msi_irq
+# define platform_pci_fixup_bus ia64_mv.pci_fixup_bus
# endif
/* __attribute__((__aligned__(16))) is required to make size of the
@@ -210,6 +217,7 @@ struct ia64_machine_vector {
ia64_mv_migrate_t *migrate;
ia64_mv_setup_msi_irq_t *setup_msi_irq;
ia64_mv_teardown_msi_irq_t *teardown_msi_irq;
+ ia64_mv_pci_fixup_bus_t *pci_fixup_bus;
} __attribute__((__aligned__(16))); /* align attrib? see above comment */
#define MACHVEC_INIT(name) \
@@ -257,6 +265,7 @@ struct ia64_machine_vector {
platform_migrate, \
platform_setup_msi_irq, \
platform_teardown_msi_irq, \
+ platform_pci_fixup_bus, \
}
extern struct ia64_machine_vector ia64_mv;
@@ -416,5 +425,8 @@ extern int ia64_pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size
#ifndef platform_teardown_msi_irq
# define platform_teardown_msi_irq ((ia64_mv_teardown_msi_irq_t*)NULL)
#endif
+#ifndef platform_pci_fixup_bus
+# define platform_pci_fixup_bus machvec_noop_bus
+#endif
#endif /* _ASM_IA64_MACHVEC_H */
diff --git a/include/asm-ia64/machvec_sn2.h b/include/asm-ia64/machvec_sn2.h
index c54b165b1c17..83325f6db03e 100644
--- a/include/asm-ia64/machvec_sn2.h
+++ b/include/asm-ia64/machvec_sn2.h
@@ -69,6 +69,7 @@ extern ia64_mv_dma_supported sn_dma_supported;
extern ia64_mv_migrate_t sn_migrate;
extern ia64_mv_setup_msi_irq_t sn_setup_msi_irq;
extern ia64_mv_teardown_msi_irq_t sn_teardown_msi_irq;
+extern ia64_mv_pci_fixup_bus_t sn_pci_fixup_bus;
/*
@@ -127,6 +128,7 @@ extern ia64_mv_teardown_msi_irq_t sn_teardown_msi_irq;
#define platform_setup_msi_irq ((ia64_mv_setup_msi_irq_t*)NULL)
#define platform_teardown_msi_irq ((ia64_mv_teardown_msi_irq_t*)NULL)
#endif
+#define platform_pci_fixup_bus sn_pci_fixup_bus
#include <asm/sn/io.h>
diff --git a/include/asm-ia64/pci.h b/include/asm-ia64/pci.h
index ef616fd4cb1b..825eb7d882e6 100644
--- a/include/asm-ia64/pci.h
+++ b/include/asm-ia64/pci.h
@@ -26,16 +26,18 @@ void pcibios_config_init(void);
struct pci_dev;
/*
- * PCI_DMA_BUS_IS_PHYS should be set to 1 if there is _necessarily_ a direct correspondence
- * between device bus addresses and CPU physical addresses. Platforms with a hardware I/O
- * MMU _must_ turn this off to suppress the bounce buffer handling code in the block and
- * network device layers. Platforms with separate bus address spaces _must_ turn this off
- * and provide a device DMA mapping implementation that takes care of the necessary
+ * PCI_DMA_BUS_IS_PHYS should be set to 1 if there is _necessarily_ a direct
+ * correspondence between device bus addresses and CPU physical addresses.
+ * Platforms with a hardware I/O MMU _must_ turn this off to suppress the
+ * bounce buffer handling code in the block and network device layers.
+ * Platforms with separate bus address spaces _must_ turn this off and provide
+ * a device DMA mapping implementation that takes care of the necessary
* address translation.
*
- * For now, the ia64 platforms which may have separate/multiple bus address spaces all
- * have I/O MMUs which support the merging of physically discontiguous buffers, so we can
- * use that as the sole factor to determine the setting of PCI_DMA_BUS_IS_PHYS.
+ * For now, the ia64 platforms which may have separate/multiple bus address
+ * spaces all have I/O MMUs which support the merging of physically
+ * discontiguous buffers, so we can use that as the sole factor to determine
+ * the setting of PCI_DMA_BUS_IS_PHYS.
*/
extern unsigned long ia64_max_iommu_merge_mask;
#define PCI_DMA_BUS_IS_PHYS (ia64_max_iommu_merge_mask == ~0UL)
@@ -52,9 +54,6 @@ pcibios_penalize_isa_irq (int irq, int active)
/* We don't do dynamic PCI IRQ allocation */
}
-#define HAVE_ARCH_PCI_MWI 1
-extern int pcibios_prep_mwi (struct pci_dev *);
-
#include <asm-generic/pci-dma-compat.h>
/* pci_unmap_{single,page} is not a nop, thus... */
diff --git a/include/asm-ia64/sn/acpi.h b/include/asm-ia64/sn/acpi.h
new file mode 100644
index 000000000000..2850a7ef5e71
--- /dev/null
+++ b/include/asm-ia64/sn/acpi.h
@@ -0,0 +1,16 @@
+/*
+ * 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 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#ifndef _ASM_IA64_SN_ACPI_H
+#define _ASM_IA64_SN_ACPI_H
+
+#include "acpi/acglobal.h"
+
+#define SN_ACPI_BASE_SUPPORT() (acpi_gbl_DSDT->oem_revision >= 0x20101)
+
+#endif /* _ASM_IA64_SN_ACPI_H */
diff --git a/include/asm-ia64/sn/pcidev.h b/include/asm-ia64/sn/pcidev.h
index eac3561574be..9fe89a93d880 100644
--- a/include/asm-ia64/sn/pcidev.h
+++ b/include/asm-ia64/sn/pcidev.h
@@ -3,7 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1992 - 1997, 2000-2005 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 1992 - 1997, 2000-2006 Silicon Graphics, Inc. All rights reserved.
*/
#ifndef _ASM_IA64_SN_PCI_PCIDEV_H
#define _ASM_IA64_SN_PCI_PCIDEV_H
@@ -12,31 +12,29 @@
/*
* In ia64, pci_dev->sysdata must be a *pci_controller. To provide access to
- * the pcidev_info structs for all devices under a controller, we extend the
- * definition of pci_controller, via sn_pci_controller, to include a list
- * of pcidev_info.
+ * the pcidev_info structs for all devices under a controller, we keep a
+ * list of pcidev_info under pci_controller->platform_data.
*/
-struct sn_pci_controller {
- struct pci_controller pci_controller;
+struct sn_platform_data {
+ void *provider_soft;
struct list_head pcidev_info;
};
-#define SN_PCI_CONTROLLER(dev) ((struct sn_pci_controller *) dev->sysdata)
+#define SN_PLATFORM_DATA(busdev) \
+ ((struct sn_platform_data *)(PCI_CONTROLLER(busdev)->platform_data))
#define SN_PCIDEV_INFO(dev) sn_pcidev_info_get(dev)
-#define SN_PCIBUS_BUSSOFT_INFO(pci_bus) \
- (struct pcibus_info *)((struct pcibus_bussoft *)(PCI_CONTROLLER((pci_bus))->platform_data))
/*
* Given a pci_bus, return the sn pcibus_bussoft struct. Note that
* this only works for root busses, not for busses represented by PPB's.
*/
#define SN_PCIBUS_BUSSOFT(pci_bus) \
- ((struct pcibus_bussoft *)(PCI_CONTROLLER((pci_bus))->platform_data))
+ ((struct pcibus_bussoft *)(SN_PLATFORM_DATA(pci_bus)->provider_soft))
#define SN_PCIBUS_BUSSOFT_INFO(pci_bus) \
- (struct pcibus_info *)((struct pcibus_bussoft *)(PCI_CONTROLLER((pci_bus))->platform_data))
+ ((struct pcibus_info *)(SN_PLATFORM_DATA(pci_bus)->provider_soft))
/*
* Given a struct pci_dev, return the sn pcibus_bussoft struct. Note
* that this is not equivalent to SN_PCIBUS_BUSSOFT(pci_dev->bus) due
@@ -72,8 +70,6 @@ extern void sn_irq_fixup(struct pci_dev *pci_dev,
struct sn_irq_info *sn_irq_info);
extern void sn_irq_unfixup(struct pci_dev *pci_dev);
extern struct pcidev_info * sn_pcidev_info_get(struct pci_dev *);
-extern void sn_pci_controller_fixup(int segment, int busnum,
- struct pci_bus *bus);
extern void sn_bus_store_sysdata(struct pci_dev *dev);
extern void sn_bus_free_sysdata(void);
extern void sn_generate_path(struct pci_bus *pci_bus, char *address);
diff --git a/include/asm-ia64/sn/sn_feature_sets.h b/include/asm-ia64/sn/sn_feature_sets.h
index 30dcfa442e53..bfdc36273ed4 100644
--- a/include/asm-ia64/sn/sn_feature_sets.h
+++ b/include/asm-ia64/sn/sn_feature_sets.h
@@ -44,8 +44,14 @@ extern int sn_prom_feature_available(int id);
* Once enabled, a feature cannot be disabled.
*
* By default, features are disabled unless explicitly enabled.
+ *
+ * These defines must be kept in sync with the corresponding
+ * PROM definitions in feature_sets.h.
*/
#define OSF_MCA_SLV_TO_OS_INIT_SLV 0
#define OSF_FEAT_LOG_SBES 1
+#define OSF_ACPI_ENABLE 2
+#define OSF_PCISEGMENT_ENABLE 3
+
#endif /* _ASM_IA64_SN_FEATURE_SETS_H */
diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h
index ba826b3f75bb..be5d83ad7cb1 100644
--- a/include/asm-ia64/sn/sn_sal.h
+++ b/include/asm-ia64/sn/sn_sal.h
@@ -77,6 +77,7 @@
#define SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST 0x02000058 // deprecated
#define SN_SAL_IOIF_GET_DEVICE_DMAFLUSH_LIST 0x0200005a
+#define SN_SAL_IOIF_INIT 0x0200005f
#define SN_SAL_HUB_ERROR_INTERRUPT 0x02000060
#define SN_SAL_BTE_RECOVER 0x02000061
#define SN_SAL_RESERVED_DO_NOT_USE 0x02000062
diff --git a/include/asm-m32r/checksum.h b/include/asm-m32r/checksum.h
index 877ebf46e9ff..a7a7c4f44abe 100644
--- a/include/asm-m32r/checksum.h
+++ b/include/asm-m32r/checksum.h
@@ -31,8 +31,7 @@
*
* it's best to have buff aligned on a 32-bit boundary
*/
-asmlinkage unsigned int csum_partial(const unsigned char *buff,
- int len, unsigned int sum);
+asmlinkage __wsum csum_partial(const void *buff, int len, __wsum sum);
/*
* The same as csum_partial, but copies from src while it checksums.
@@ -40,24 +39,22 @@ asmlinkage unsigned int csum_partial(const unsigned char *buff,
* Here even more important to align src and dst on a 32-bit (or even
* better 64-bit) boundary
*/
-extern unsigned int csum_partial_copy_nocheck(const unsigned char *src,
- unsigned char *dst,
- int len, unsigned int sum);
+extern __wsum csum_partial_copy_nocheck(const void *src, void *dst,
+ int len, __wsum sum);
/*
* This is a new version of the above that records errors it finds in *errp,
* but continues and zeros thre rest of the buffer.
*/
-extern unsigned int csum_partial_copy_from_user(const unsigned char __user *src,
- unsigned char *dst,
- int len, unsigned int sum,
+extern __wsum csum_partial_copy_from_user(const void __user *src, void *dst,
+ int len, __wsum sum,
int *err_ptr);
/*
* Fold a partial checksum
*/
-static inline unsigned int csum_fold(unsigned int sum)
+static inline __sum16 csum_fold(__wsum sum)
{
unsigned long tmpreg;
__asm__(
@@ -72,16 +69,17 @@ static inline unsigned int csum_fold(unsigned int sum)
: "0" (sum)
: "cbit"
);
- return sum;
+ return (__force __sum16)sum;
}
/*
* This is a version of ip_compute_csum() optimized for IP headers,
* which always checksum on 4 octet boundaries.
*/
-static inline unsigned short ip_fast_csum(unsigned char * iph,
- unsigned int ihl) {
- unsigned long sum, tmpreg0, tmpreg1;
+static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
+{
+ unsigned long tmpreg0, tmpreg1;
+ __wsum sum;
__asm__ __volatile__(
" ld %0, @%1+ \n"
@@ -115,16 +113,15 @@ static inline unsigned short ip_fast_csum(unsigned char * iph,
return csum_fold(sum);
}
-static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
- unsigned long daddr,
+static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
unsigned short len,
unsigned short proto,
- unsigned int sum)
+ __wsum sum)
{
#if defined(__LITTLE_ENDIAN)
- unsigned long len_proto = (ntohs(len)<<16)+proto*256;
+ unsigned long len_proto = (proto + len) << 8;
#else
- unsigned long len_proto = (proto<<16)+len;
+ unsigned long len_proto = proto + len;
#endif
unsigned long tmpreg;
@@ -147,11 +144,10 @@ static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
* computes the checksum of the TCP/UDP pseudo-header
* returns a 16-bit checksum, already complemented
*/
-static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
- unsigned long daddr,
+static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
unsigned short len,
unsigned short proto,
- unsigned int sum)
+ __wsum sum)
{
return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
}
@@ -161,16 +157,16 @@ static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
* in icmp.c
*/
-static inline unsigned short ip_compute_csum(unsigned char * buff, int len) {
+static inline __sum16 ip_compute_csum(const void *buff, int len)
+{
return csum_fold (csum_partial(buff, len, 0));
}
#define _HAVE_ARCH_IPV6_CSUM
-static inline unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
- struct in6_addr *daddr,
- __u16 len,
- unsigned short proto,
- unsigned int sum)
+static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+ const struct in6_addr *daddr,
+ __u32 len, unsigned short proto,
+ __wsum sum)
{
unsigned long tmpreg0, tmpreg1, tmpreg2, tmpreg3;
__asm__(
@@ -197,7 +193,7 @@ static inline unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
: "=&r" (sum), "=&r" (tmpreg0), "=&r" (tmpreg1),
"=&r" (tmpreg2), "=&r" (tmpreg3)
: "r" (saddr), "r" (daddr),
- "r" (htonl((__u32) (len))), "r" (htonl(proto)), "0" (sum)
+ "r" (htonl(len)), "r" (htonl(proto)), "0" (sum)
: "cbit"
);
diff --git a/include/asm-m32r/device.h b/include/asm-m32r/device.h
new file mode 100644
index 000000000000..d8f9872b0e2d
--- /dev/null
+++ b/include/asm-m32r/device.h
@@ -0,0 +1,7 @@
+/*
+ * Arch specific extensions to struct device
+ *
+ * This file is released under the GPLv2
+ */
+#include <asm-generic/device.h>
+
diff --git a/include/asm-m68k/checksum.h b/include/asm-m68k/checksum.h
index 17280ef719f5..494f9aec37ea 100644
--- a/include/asm-m68k/checksum.h
+++ b/include/asm-m68k/checksum.h
@@ -15,7 +15,7 @@
*
* it's best to have buff aligned on a 32-bit boundary
*/
-unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
+__wsum csum_partial(const void *buff, int len, __wsum sum);
/*
* the same as csum_partial, but copies from src while it
@@ -25,22 +25,21 @@ unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
* better 64-bit) boundary
*/
-extern unsigned int csum_partial_copy_from_user(const unsigned char __user *src,
- unsigned char *dst,
- int len, int sum,
+extern __wsum csum_partial_copy_from_user(const void __user *src,
+ void *dst,
+ int len, __wsum sum,
int *csum_err);
-extern unsigned int csum_partial_copy_nocheck(const unsigned char *src,
- unsigned char *dst, int len,
- int sum);
+extern __wsum csum_partial_copy_nocheck(const void *src,
+ void *dst, int len,
+ __wsum sum);
/*
* This is a version of ip_compute_csum() optimized for IP headers,
* which always checksum on 4 octet boundaries.
*
*/
-static inline unsigned short
-ip_fast_csum(unsigned char *iph, unsigned int ihl)
+static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
{
unsigned int sum = 0;
unsigned long tmp;
@@ -58,29 +57,29 @@ ip_fast_csum(unsigned char *iph, unsigned int ihl)
: "=d" (sum), "=&a" (iph), "=&d" (ihl), "=&d" (tmp)
: "0" (sum), "1" (iph), "2" (ihl)
: "memory");
- return ~sum;
+ return (__force __sum16)~sum;
}
/*
* Fold a partial checksum
*/
-static inline unsigned int csum_fold(unsigned int sum)
+static inline __sum16 csum_fold(__wsum sum)
{
- unsigned int tmp = sum;
+ unsigned int tmp = (__force u32)sum;
__asm__("swap %1\n\t"
"addw %1, %0\n\t"
"clrw %1\n\t"
"addxw %1, %0"
: "=&d" (sum), "=&d" (tmp)
: "0" (sum), "1" (tmp));
- return ~sum;
+ return (__force __sum16)~sum;
}
-static inline unsigned int
-csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len,
- unsigned short proto, unsigned int sum)
+static inline __wsum
+csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
+ unsigned short proto, __wsum sum)
{
__asm__ ("addl %2,%0\n\t"
"addxl %3,%0\n\t"
@@ -98,9 +97,9 @@ csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len,
* computes the checksum of the TCP/UDP pseudo-header
* returns a 16-bit checksum, already complemented
*/
-static inline unsigned short int
-csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, unsigned short len,
- unsigned short proto, unsigned int sum)
+static inline __sum16
+csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len,
+ unsigned short proto, __wsum sum)
{
return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
}
@@ -110,16 +109,15 @@ csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, unsigned short len,
* in icmp.c
*/
-static inline unsigned short
-ip_compute_csum(unsigned char * buff, int len)
+static inline __sum16 ip_compute_csum(const void *buff, int len)
{
return csum_fold (csum_partial(buff, len, 0));
}
#define _HAVE_ARCH_IPV6_CSUM
-static __inline__ unsigned short int
-csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr,
- __u32 len, unsigned short proto, unsigned int sum)
+static __inline__ __sum16
+csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr,
+ __u32 len, unsigned short proto, __wsum sum)
{
register unsigned long tmp;
__asm__("addl %2@,%0\n\t"
diff --git a/include/asm-m68k/device.h b/include/asm-m68k/device.h
new file mode 100644
index 000000000000..d8f9872b0e2d
--- /dev/null
+++ b/include/asm-m68k/device.h
@@ -0,0 +1,7 @@
+/*
+ * Arch specific extensions to struct device
+ *
+ * This file is released under the GPLv2
+ */
+#include <asm-generic/device.h>
+
diff --git a/include/asm-m68knommu/checksum.h b/include/asm-m68knommu/checksum.h
index 294ec7583ac9..81883482ffb1 100644
--- a/include/asm-m68knommu/checksum.h
+++ b/include/asm-m68knommu/checksum.h
@@ -15,7 +15,7 @@
*
* it's best to have buff aligned on a 32-bit boundary
*/
-unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
+__wsum csum_partial(const void *buff, int len, __wsum sum);
/*
* the same as csum_partial, but copies from src while it
@@ -25,8 +25,8 @@ unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
* better 64-bit) boundary
*/
-unsigned int csum_partial_copy(const unsigned char *src, unsigned char *dst,
- int len, int sum);
+__wsum csum_partial_copy_nocheck(const void *src, void *dst,
+ int len, __wsum sum);
/*
@@ -36,33 +36,31 @@ unsigned int csum_partial_copy(const unsigned char *src, unsigned char *dst,
* better 64-bit) boundary
*/
-extern unsigned int csum_partial_copy_from_user(const unsigned char *src,
- unsigned char *dst, int len, int sum, int *csum_err);
+extern __wsum csum_partial_copy_from_user(const void __user *src,
+ void *dst, int len, __wsum sum, int *csum_err);
-#define csum_partial_copy_nocheck(src, dst, len, sum) \
- csum_partial_copy((src), (dst), (len), (sum))
-
-unsigned short ip_fast_csum(unsigned char *iph, unsigned int ihl);
+__sum16 ip_fast_csum(const void *iph, unsigned int ihl);
/*
* Fold a partial checksum
*/
-static inline unsigned int csum_fold(unsigned int sum)
+static inline __sum16 csum_fold(__wsum sum)
{
+ unsigned int tmp = (__force u32)sum;
#ifdef CONFIG_COLDFIRE
- sum = (sum & 0xffff) + (sum >> 16);
- sum = (sum & 0xffff) + (sum >> 16);
+ tmp = (tmp & 0xffff) + (tmp >> 16);
+ tmp = (tmp & 0xffff) + (tmp >> 16);
+ return (__force __sum16)~tmp;
#else
- unsigned int tmp = sum;
__asm__("swap %1\n\t"
"addw %1, %0\n\t"
"clrw %1\n\t"
"addxw %1, %0"
: "=&d" (sum), "=&d" (tmp)
: "0" (sum), "1" (sum));
+ return (__force __sum16)~sum;
#endif
- return ~sum;
}
@@ -71,9 +69,9 @@ static inline unsigned int csum_fold(unsigned int sum)
* returns a 16-bit checksum, already complemented
*/
-static inline unsigned int
-csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len,
- unsigned short proto, unsigned int sum)
+static inline __wsum
+csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
+ unsigned short proto, __wsum sum)
{
__asm__ ("addl %1,%0\n\t"
"addxl %4,%0\n\t"
@@ -86,9 +84,9 @@ csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len,
return sum;
}
-static inline unsigned short int
-csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, unsigned short len,
- unsigned short proto, unsigned int sum)
+static inline __sum16
+csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len,
+ unsigned short proto, __wsum sum)
{
return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
}
@@ -98,12 +96,12 @@ csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, unsigned short len,
* in icmp.c
*/
-extern unsigned short ip_compute_csum(const unsigned char * buff, int len);
+extern __sum16 ip_compute_csum(const void *buff, int len);
#define _HAVE_ARCH_IPV6_CSUM
-static __inline__ unsigned short int
-csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr,
- __u32 len, unsigned short proto, unsigned int sum)
+static __inline__ __sum16
+csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr,
+ __u32 len, unsigned short proto, __wsum sum)
{
register unsigned long tmp;
__asm__("addl %2@,%0\n\t"
diff --git a/include/asm-m68knommu/device.h b/include/asm-m68knommu/device.h
new file mode 100644
index 000000000000..d8f9872b0e2d
--- /dev/null
+++ b/include/asm-m68knommu/device.h
@@ -0,0 +1,7 @@
+/*
+ * Arch specific extensions to struct device
+ *
+ * This file is released under the GPLv2
+ */
+#include <asm-generic/device.h>
+
diff --git a/include/asm-m68knommu/mcfmbus.h b/include/asm-m68knommu/mcfmbus.h
index 13df9d41bd1a..319899c47a2c 100644
--- a/include/asm-m68knommu/mcfmbus.h
+++ b/include/asm-m68knommu/mcfmbus.h
@@ -37,7 +37,7 @@
#define MCFMBUS_MFDR_MBC(a) ((a)&0x3F) /*M-Bus Clock*/
/*
-* Define bit flags in Controll Register
+* Define bit flags in Control Register
*/
#define MCFMBUS_MBCR_MEN (0x80) /* M-Bus Enable */
diff --git a/include/asm-mips/addrspace.h b/include/asm-mips/addrspace.h
index 45c706e34df1..c6275088cf65 100644
--- a/include/asm-mips/addrspace.h
+++ b/include/asm-mips/addrspace.h
@@ -19,12 +19,16 @@
#define _ATYPE_
#define _ATYPE32_
#define _ATYPE64_
-#define _LLCONST_(x) x
+#define _CONST64_(x) x
#else
#define _ATYPE_ __PTRDIFF_TYPE__
#define _ATYPE32_ int
-#define _ATYPE64_ long long
-#define _LLCONST_(x) x ## LL
+#define _ATYPE64_ __s64
+#ifdef CONFIG_64BIT
+#define _CONST64_(x) x ## L
+#else
+#define _CONST64_(x) x ## LL
+#endif
#endif
/*
@@ -48,7 +52,7 @@
*/
#define CPHYSADDR(a) ((_ACAST32_(a)) & 0x1fffffff)
#define XPHYSADDR(a) ((_ACAST64_(a)) & \
- _LLCONST_(0x000000ffffffffff))
+ _CONST64_(0x000000ffffffffff))
#ifdef CONFIG_64BIT
@@ -57,14 +61,14 @@
* The compatibility segments use the full 64-bit sign extended value. Note
* the R8000 doesn't have them so don't reference these in generic MIPS code.
*/
-#define XKUSEG _LLCONST_(0x0000000000000000)
-#define XKSSEG _LLCONST_(0x4000000000000000)
-#define XKPHYS _LLCONST_(0x8000000000000000)
-#define XKSEG _LLCONST_(0xc000000000000000)
-#define CKSEG0 _LLCONST_(0xffffffff80000000)
-#define CKSEG1 _LLCONST_(0xffffffffa0000000)
-#define CKSSEG _LLCONST_(0xffffffffc0000000)
-#define CKSEG3 _LLCONST_(0xffffffffe0000000)
+#define XKUSEG _CONST64_(0x0000000000000000)
+#define XKSSEG _CONST64_(0x4000000000000000)
+#define XKPHYS _CONST64_(0x8000000000000000)
+#define XKSEG _CONST64_(0xc000000000000000)
+#define CKSEG0 _CONST64_(0xffffffff80000000)
+#define CKSEG1 _CONST64_(0xffffffffa0000000)
+#define CKSSEG _CONST64_(0xffffffffc0000000)
+#define CKSEG3 _CONST64_(0xffffffffe0000000)
#define CKSEG0ADDR(a) (CPHYSADDR(a) | CKSEG0)
#define CKSEG1ADDR(a) (CPHYSADDR(a) | CKSEG1)
@@ -122,7 +126,7 @@
#define PHYS_TO_XKSEG_UNCACHED(p) PHYS_TO_XKPHYS(K_CALG_UNCACHED,(p))
#define PHYS_TO_XKSEG_CACHED(p) PHYS_TO_XKPHYS(K_CALG_COH_SHAREABLE,(p))
#define XKPHYS_TO_PHYS(p) ((p) & TO_PHYS_MASK)
-#define PHYS_TO_XKPHYS(cm,a) (_LLCONST_(0x8000000000000000) | \
+#define PHYS_TO_XKPHYS(cm,a) (_CONST64_(0x8000000000000000) | \
((cm)<<59) | (a))
#if defined (CONFIG_CPU_R4300) \
@@ -132,20 +136,20 @@
|| defined (CONFIG_CPU_NEVADA) \
|| defined (CONFIG_CPU_TX49XX) \
|| defined (CONFIG_CPU_MIPS64)
-#define TO_PHYS_MASK _LLCONST_(0x0000000fffffffff) /* 2^^36 - 1 */
+#define TO_PHYS_MASK _CONST64_(0x0000000fffffffff) /* 2^^36 - 1 */
#endif
#if defined (CONFIG_CPU_R8000)
/* We keep KUSIZE consistent with R4000 for now (2^^40) instead of (2^^48) */
-#define TO_PHYS_MASK _LLCONST_(0x000000ffffffffff) /* 2^^40 - 1 */
+#define TO_PHYS_MASK _CONST64_(0x000000ffffffffff) /* 2^^40 - 1 */
#endif
#if defined (CONFIG_CPU_R10000)
-#define TO_PHYS_MASK _LLCONST_(0x000000ffffffffff) /* 2^^40 - 1 */
+#define TO_PHYS_MASK _CONST64_(0x000000ffffffffff) /* 2^^40 - 1 */
#endif
#if defined(CONFIG_CPU_SB1) || defined(CONFIG_CPU_SB1A)
-#define TO_PHYS_MASK _LLCONST_(0x00000fffffffffff) /* 2^^44 - 1 */
+#define TO_PHYS_MASK _CONST64_(0x00000fffffffffff) /* 2^^44 - 1 */
#endif
#ifndef CONFIG_CPU_R8000
@@ -155,7 +159,7 @@
* in order to catch bugs in the source code.
*/
-#define COMPAT_K1BASE32 _LLCONST_(0xffffffffa0000000)
+#define COMPAT_K1BASE32 _CONST64_(0xffffffffa0000000)
#define PHYS_TO_COMPATK1(x) ((x) | COMPAT_K1BASE32) /* 32-bit compat k1 */
#endif
diff --git a/include/asm-mips/atomic.h b/include/asm-mips/atomic.h
index e64abc0d8221..7978d8e11647 100644
--- a/include/asm-mips/atomic.h
+++ b/include/asm-mips/atomic.h
@@ -9,16 +9,8 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1996, 97, 99, 2000, 03, 04 by Ralf Baechle
+ * Copyright (C) 1996, 97, 99, 2000, 03, 04, 06 by Ralf Baechle
*/
-
-/*
- * As workaround for the ATOMIC_DEC_AND_LOCK / atomic_dec_and_lock mess in
- * <linux/spinlock.h> we have to include <linux/spinlock.h> outside the
- * main big wrapper ...
- */
-#include <linux/spinlock.h>
-
#ifndef _ASM_ATOMIC_H
#define _ASM_ATOMIC_H
diff --git a/include/asm-mips/bitops.h b/include/asm-mips/bitops.h
index 1bb89c5a10ee..b9007411b60f 100644
--- a/include/asm-mips/bitops.h
+++ b/include/asm-mips/bitops.h
@@ -10,31 +10,26 @@
#define _ASM_BITOPS_H
#include <linux/compiler.h>
+#include <linux/irqflags.h>
#include <linux/types.h>
#include <asm/bug.h>
#include <asm/byteorder.h> /* sigh ... */
#include <asm/cpu-features.h>
+#include <asm/sgidefs.h>
+#include <asm/war.h>
#if (_MIPS_SZLONG == 32)
#define SZLONG_LOG 5
#define SZLONG_MASK 31UL
#define __LL "ll "
#define __SC "sc "
-#define cpu_to_lelongp(x) cpu_to_le32p((__u32 *) (x))
#elif (_MIPS_SZLONG == 64)
#define SZLONG_LOG 6
#define SZLONG_MASK 63UL
#define __LL "lld "
#define __SC "scd "
-#define cpu_to_lelongp(x) cpu_to_le64p((__u64 *) (x))
#endif
-#ifdef __KERNEL__
-
-#include <linux/irqflags.h>
-#include <asm/sgidefs.h>
-#include <asm/war.h>
-
/*
* clear_bit() doesn't provide any barrier for the compiler.
*/
@@ -42,20 +37,6 @@
#define smp_mb__after_clear_bit() smp_mb()
/*
- * Only disable interrupt for kernel mode stuff to keep usermode stuff
- * that dares to use kernel include files alive.
- */
-
-#define __bi_flags unsigned long flags
-#define __bi_local_irq_save(x) local_irq_save(x)
-#define __bi_local_irq_restore(x) local_irq_restore(x)
-#else
-#define __bi_flags
-#define __bi_local_irq_save(x)
-#define __bi_local_irq_restore(x)
-#endif /* __KERNEL__ */
-
-/*
* set_bit - Atomically set a bit in memory
* @nr: the bit to set
* @addr: the address to start counting from
@@ -93,13 +74,13 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
} else {
volatile unsigned long *a = addr;
unsigned long mask;
- __bi_flags;
+ unsigned long flags;
a += nr >> SZLONG_LOG;
mask = 1UL << (nr & SZLONG_MASK);
- __bi_local_irq_save(flags);
+ local_irq_save(flags);
*a |= mask;
- __bi_local_irq_restore(flags);
+ local_irq_restore(flags);
}
}
@@ -141,13 +122,13 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
} else {
volatile unsigned long *a = addr;
unsigned long mask;
- __bi_flags;
+ unsigned long flags;
a += nr >> SZLONG_LOG;
mask = 1UL << (nr & SZLONG_MASK);
- __bi_local_irq_save(flags);
+ local_irq_save(flags);
*a &= ~mask;
- __bi_local_irq_restore(flags);
+ local_irq_restore(flags);
}
}
@@ -191,13 +172,13 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
} else {
volatile unsigned long *a = addr;
unsigned long mask;
- __bi_flags;
+ unsigned long flags;
a += nr >> SZLONG_LOG;
mask = 1UL << (nr & SZLONG_MASK);
- __bi_local_irq_save(flags);
+ local_irq_save(flags);
*a ^= mask;
- __bi_local_irq_restore(flags);
+ local_irq_restore(flags);
}
}
@@ -258,14 +239,14 @@ static inline int test_and_set_bit(unsigned long nr,
volatile unsigned long *a = addr;
unsigned long mask;
int retval;
- __bi_flags;
+ unsigned long flags;
a += nr >> SZLONG_LOG;
mask = 1UL << (nr & SZLONG_MASK);
- __bi_local_irq_save(flags);
+ local_irq_save(flags);
retval = (mask & *a) != 0;
*a |= mask;
- __bi_local_irq_restore(flags);
+ local_irq_restore(flags);
return retval;
}
@@ -330,14 +311,14 @@ static inline int test_and_clear_bit(unsigned long nr,
volatile unsigned long *a = addr;
unsigned long mask;
int retval;
- __bi_flags;
+ unsigned long flags;
a += nr >> SZLONG_LOG;
mask = 1UL << (nr & SZLONG_MASK);
- __bi_local_irq_save(flags);
+ local_irq_save(flags);
retval = (mask & *a) != 0;
*a &= ~mask;
- __bi_local_irq_restore(flags);
+ local_irq_restore(flags);
return retval;
}
@@ -399,23 +380,19 @@ static inline int test_and_change_bit(unsigned long nr,
} else {
volatile unsigned long *a = addr;
unsigned long mask, retval;
- __bi_flags;
+ unsigned long flags;
a += nr >> SZLONG_LOG;
mask = 1UL << (nr & SZLONG_MASK);
- __bi_local_irq_save(flags);
+ local_irq_save(flags);
retval = (mask & *a) != 0;
*a ^= mask;
- __bi_local_irq_restore(flags);
+ local_irq_restore(flags);
return retval;
}
}
-#undef __bi_flags
-#undef __bi_local_irq_save
-#undef __bi_local_irq_restore
-
#include <asm-generic/bitops/non-atomic.h>
/*
diff --git a/include/asm-mips/bug.h b/include/asm-mips/bug.h
index 7b4739dc8f3f..4d560a533940 100644
--- a/include/asm-mips/bug.h
+++ b/include/asm-mips/bug.h
@@ -1,6 +1,7 @@
#ifndef __ASM_BUG_H
#define __ASM_BUG_H
+#include <asm/sgidefs.h>
#ifdef CONFIG_BUG
@@ -13,6 +14,17 @@ do { \
#define HAVE_ARCH_BUG
+#if (_MIPS_ISA > _MIPS_ISA_MIPS1)
+
+#define BUG_ON(condition) \
+do { \
+ __asm__ __volatile__("tne $0, %0" : : "r" (condition)); \
+} while (0)
+
+#define HAVE_ARCH_BUG_ON
+
+#endif /* _MIPS_ISA > _MIPS_ISA_MIPS1 */
+
#endif
#include <asm-generic/bug.h>
diff --git a/include/asm-mips/checksum.h b/include/asm-mips/checksum.h
index a5e6050ec0f3..9b768c3b96b3 100644
--- a/include/asm-mips/checksum.h
+++ b/include/asm-mips/checksum.h
@@ -27,23 +27,22 @@
*
* it's best to have buff aligned on a 32-bit boundary
*/
-unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum);
+__wsum csum_partial(const void *buff, int len, __wsum sum);
/*
* this is a new version of the above that records errors it finds in *errp,
* but continues and zeros the rest of the buffer.
*/
-unsigned int csum_partial_copy_from_user(const unsigned char __user *src,
- unsigned char *dst, int len,
- unsigned int sum, int *errp);
+__wsum csum_partial_copy_from_user(const void __user *src,
+ void *dst, int len,
+ __wsum sum, int *errp);
/*
* Copy and checksum to user
*/
#define HAVE_CSUM_COPY_USER
-static inline unsigned int csum_and_copy_to_user (const unsigned char *src,
- unsigned char __user *dst,
- int len, int sum,
+static inline __wsum csum_and_copy_to_user (const void *src, void __user *dst,
+ int len, __wsum sum,
int *err_ptr)
{
might_sleep();
@@ -51,7 +50,7 @@ static inline unsigned int csum_and_copy_to_user (const unsigned char *src,
if (copy_to_user(dst, src, len)) {
*err_ptr = -EFAULT;
- return -1;
+ return (__force __wsum)-1;
}
return sum;
@@ -61,13 +60,13 @@ static inline unsigned int csum_and_copy_to_user (const unsigned char *src,
* the same as csum_partial, but copies from user space (but on MIPS
* we have just one address space, so this is identical to the above)
*/
-unsigned int csum_partial_copy_nocheck(const unsigned char *src, unsigned char *dst,
- int len, unsigned int sum);
+__wsum csum_partial_copy_nocheck(const void *src, void *dst,
+ int len, __wsum sum);
/*
* Fold a partial checksum without adding pseudo headers
*/
-static inline unsigned short int csum_fold(unsigned int sum)
+static inline __sum16 csum_fold(__wsum sum)
{
__asm__(
" .set push # csum_fold\n"
@@ -82,7 +81,7 @@ static inline unsigned short int csum_fold(unsigned int sum)
: "=r" (sum)
: "0" (sum));
- return sum;
+ return (__force __sum16)sum;
}
/*
@@ -92,10 +91,10 @@ static inline unsigned short int csum_fold(unsigned int sum)
* By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
* Arnt Gulbrandsen.
*/
-static inline unsigned short ip_fast_csum(unsigned char *iph, unsigned int ihl)
+static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
{
- unsigned int *word = (unsigned int *) iph;
- unsigned int *stop = word + ihl;
+ const unsigned int *word = iph;
+ const unsigned int *stop = word + ihl;
unsigned int csum;
int carry;
@@ -123,9 +122,9 @@ static inline unsigned short ip_fast_csum(unsigned char *iph, unsigned int ihl)
return csum_fold(csum);
}
-static inline unsigned int csum_tcpudp_nofold(unsigned long saddr,
- unsigned long daddr, unsigned short len, unsigned short proto,
- unsigned int sum)
+static inline __wsum csum_tcpudp_nofold(__be32 saddr,
+ __be32 daddr, unsigned short len, unsigned short proto,
+ __wsum sum)
{
__asm__(
" .set push # csum_tcpudp_nofold\n"
@@ -155,9 +154,9 @@ static inline unsigned int csum_tcpudp_nofold(unsigned long saddr,
: "=r" (sum)
: "0" (daddr), "r"(saddr),
#ifdef __MIPSEL__
- "r" (((unsigned long)htons(len)<<16) + proto*256),
+ "r" ((proto + len) << 8),
#else
- "r" (((unsigned long)(proto)<<16) + len),
+ "r" (proto + len),
#endif
"r" (sum));
@@ -168,11 +167,10 @@ static inline unsigned int csum_tcpudp_nofold(unsigned long saddr,
* computes the checksum of the TCP/UDP pseudo-header
* returns a 16-bit checksum, already complemented
*/
-static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
- unsigned long daddr,
+static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
unsigned short len,
unsigned short proto,
- unsigned int sum)
+ __wsum sum)
{
return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
}
@@ -181,17 +179,16 @@ static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
* this routine is used for miscellaneous IP-like checksums, mainly
* in icmp.c
*/
-static inline unsigned short ip_compute_csum(unsigned char * buff, int len)
+static inline __sum16 ip_compute_csum(const void *buff, int len)
{
return csum_fold(csum_partial(buff, len, 0));
}
#define _HAVE_ARCH_IPV6_CSUM
-static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
- struct in6_addr *daddr,
- __u32 len,
- unsigned short proto,
- unsigned int sum)
+static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+ const struct in6_addr *daddr,
+ __u32 len, unsigned short proto,
+ __wsum sum)
{
__asm__(
" .set push # csum_ipv6_magic\n"
diff --git a/include/asm-mips/cpu-info.h b/include/asm-mips/cpu-info.h
index a2f0c8ea9160..610d0cdeaa9e 100644
--- a/include/asm-mips/cpu-info.h
+++ b/include/asm-mips/cpu-info.h
@@ -22,12 +22,12 @@
* Descriptor for a cache
*/
struct cache_desc {
- unsigned short linesz; /* Size of line in bytes */
- unsigned short ways; /* Number of ways */
- unsigned short sets; /* Number of lines per set */
unsigned int waysize; /* Bytes per way */
- unsigned int waybit; /* Bits to select in a cache set */
- unsigned int flags; /* Flags describing cache properties */
+ unsigned short sets; /* Number of lines per set */
+ unsigned char ways; /* Number of ways */
+ unsigned char linesz; /* Size of line in bytes */
+ unsigned char waybit; /* Bits to select in a cache set */
+ unsigned char flags; /* Flags describing cache properties */
};
/*
diff --git a/include/asm-mips/dec/kn02.h b/include/asm-mips/dec/kn02.h
index 8319ad77b250..93430b5f4724 100644
--- a/include/asm-mips/dec/kn02.h
+++ b/include/asm-mips/dec/kn02.h
@@ -82,11 +82,9 @@
#ifndef __ASSEMBLY__
-#include <linux/spinlock.h>
#include <linux/types.h>
extern u32 cached_kn02_csr;
-extern spinlock_t kn02_lock;
extern void init_kn02_irqs(int base);
#endif
diff --git a/include/asm-mips/device.h b/include/asm-mips/device.h
new file mode 100644
index 000000000000..d8f9872b0e2d
--- /dev/null
+++ b/include/asm-mips/device.h
@@ -0,0 +1,7 @@
+/*
+ * Arch specific extensions to struct device
+ *
+ * This file is released under the GPLv2
+ */
+#include <asm-generic/device.h>
+
diff --git a/include/asm-mips/dma.h b/include/asm-mips/dma.h
index e85849ac165f..23f789c80845 100644
--- a/include/asm-mips/dma.h
+++ b/include/asm-mips/dma.h
@@ -74,7 +74,9 @@
*
*/
+#ifndef GENERIC_ISA_DMA_SUPPORT_BROKEN
#define MAX_DMA_CHANNELS 8
+#endif
/*
* The maximum address in KSEG0 that we can perform a DMA transfer to on this
diff --git a/include/asm-mips/gt64120.h b/include/asm-mips/gt64120.h
index 2edd171bb6cd..4bf8e28f8850 100644
--- a/include/asm-mips/gt64120.h
+++ b/include/asm-mips/gt64120.h
@@ -451,6 +451,13 @@
#define GT_SDRAM_OPMODE_OP_MODE 3
#define GT_SDRAM_OPMODE_OP_CBR 4
+#define GT_TC_CONTROL_ENTC0_SHF 0
+#define GT_TC_CONTROL_ENTC0_MSK (MSK(1) << GT_TC_CONTROL_ENTC0_SHF)
+#define GT_TC_CONTROL_ENTC0_BIT GT_TC_CONTROL_ENTC0_MSK
+#define GT_TC_CONTROL_SELTC0_SHF 1
+#define GT_TC_CONTROL_SELTC0_MSK (MSK(1) << GT_TC_CONTROL_SELTC0_SHF)
+#define GT_TC_CONTROL_SELTC0_BIT GT_TC_CONTROL_SELTC0_MSK
+
#define GT_PCI0_BARE_SWSCS3BOOTDIS_SHF 0
#define GT_PCI0_BARE_SWSCS3BOOTDIS_MSK (MSK(1) << GT_PCI0_BARE_SWSCS3BOOTDIS_SHF)
@@ -523,6 +530,13 @@
#define GT_PCI0_CMD_SWORDSWAP_MSK (MSK(1) << GT_PCI0_CMD_SWORDSWAP_SHF)
#define GT_PCI0_CMD_SWORDSWAP_BIT GT_PCI0_CMD_SWORDSWAP_MSK
+#define GT_INTR_T0EXP_SHF 8
+#define GT_INTR_T0EXP_MSK (MSK(1) << GT_INTR_T0EXP_SHF)
+#define GT_INTR_T0EXP_BIT GT_INTR_T0EXP_MSK
+#define GT_INTR_RETRYCTR0_SHF 20
+#define GT_INTR_RETRYCTR0_MSK (MSK(1) << GT_INTR_RETRYCTR0_SHF)
+#define GT_INTR_RETRYCTR0_BIT GT_INTR_RETRYCTR0_MSK
+
/*
* Misc
*/
diff --git a/include/asm-mips/io.h b/include/asm-mips/io.h
index bc5f3c53155f..d77b657c09c7 100644
--- a/include/asm-mips/io.h
+++ b/include/asm-mips/io.h
@@ -113,7 +113,7 @@ static inline void set_io_port_base(unsigned long base)
* almost all conceivable cases a device driver should not be using
* this function
*/
-static inline unsigned long virt_to_phys(volatile void * address)
+static inline unsigned long virt_to_phys(volatile const void *address)
{
return (unsigned long)address - PAGE_OFFSET;
}
diff --git a/include/asm-mips/irq.h b/include/asm-mips/irq.h
index 35a05ca5560c..67657089efa7 100644
--- a/include/asm-mips/irq.h
+++ b/include/asm-mips/irq.h
@@ -24,8 +24,6 @@ static inline int irq_canonicalize(int irq)
#define irq_canonicalize(irq) (irq) /* Sane hardware, sane code ... */
#endif
-extern asmlinkage unsigned int do_IRQ(unsigned int irq);
-
#ifdef CONFIG_MIPS_MT_SMTC
/*
* Clear interrupt mask handling "backstop" if irq_hwmask
@@ -43,8 +41,6 @@ do { \
#define __DO_IRQ_SMTC_HOOK() do { } while (0)
#endif
-#ifdef CONFIG_PREEMPT
-
/*
* do_IRQ handles all normal device IRQ's (the special
* SMP cross-CPU interrupts have their own specific
@@ -57,12 +53,10 @@ do { \
do { \
irq_enter(); \
__DO_IRQ_SMTC_HOOK(); \
- __do_IRQ((irq)); \
+ generic_handle_irq(irq); \
irq_exit(); \
} while (0)
-#endif
-
extern void arch_init_irq(void);
extern void spurious_interrupt(void);
diff --git a/include/asm-mips/kexec.h b/include/asm-mips/kexec.h
new file mode 100644
index 000000000000..b25267ebcb09
--- /dev/null
+++ b/include/asm-mips/kexec.h
@@ -0,0 +1,32 @@
+/*
+ * kexec.h for kexec
+ * Created by <nschichan@corp.free.fr> on Thu Oct 12 14:59:34 2006
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#ifndef _MIPS_KEXEC
+# define _MIPS_KEXEC
+
+/* Maximum physical address we can use pages from */
+#define KEXEC_SOURCE_MEMORY_LIMIT (0x20000000)
+/* Maximum address we can reach in physical address mode */
+#define KEXEC_DESTINATION_MEMORY_LIMIT (0x20000000)
+ /* Maximum address we can use for the control code buffer */
+#define KEXEC_CONTROL_MEMORY_LIMIT (0x20000000)
+
+#define KEXEC_CONTROL_CODE_SIZE 4096
+
+/* The native architecture */
+#define KEXEC_ARCH KEXEC_ARCH_MIPS
+
+#define MAX_NOTE_BYTES 1024
+
+static inline void crash_setup_regs(struct pt_regs *newregs,
+ struct pt_regs *oldregs)
+{
+ /* Dummy implementation for now */
+}
+
+#endif /* !_MIPS_KEXEC */
diff --git a/include/asm-mips/mach-au1x00/au1xxx_ide.h b/include/asm-mips/mach-au1x00/au1xxx_ide.h
index 301e71300779..e9fa252f8a3f 100644
--- a/include/asm-mips/mach-au1x00/au1xxx_ide.h
+++ b/include/asm-mips/mach-au1x00/au1xxx_ide.h
@@ -170,10 +170,8 @@ int __init auide_probe(void);
static int auide_dma_host_on(ide_drive_t *drive);
static int auide_dma_lostirq(ide_drive_t *drive);
static int auide_dma_on(ide_drive_t *drive);
- static void auide_ddma_tx_callback(int irq, void *param,
- struct pt_regs *regs);
- static void auide_ddma_rx_callback(int irq, void *param,
- struct pt_regs *regs);
+ static void auide_ddma_tx_callback(int irq, void *param);
+ static void auide_ddma_rx_callback(int irq, void *param);
static int auide_dma_off_quietly(ide_drive_t *drive);
#endif /* end CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA */
diff --git a/include/asm-mips/mach-cobalt/cobalt.h b/include/asm-mips/mach-cobalt/cobalt.h
index b3c5ecbec03c..00b0fc68d5cb 100644
--- a/include/asm-mips/mach-cobalt/cobalt.h
+++ b/include/asm-mips/mach-cobalt/cobalt.h
@@ -67,34 +67,9 @@
#define COBALT_BRD_ID_QUBE2 0x5
#define COBALT_BRD_ID_RAQ2 0x6
-/*
- * Galileo chipset access macros for the Cobalt. The base address for
- * the GT64111 chip is 0x14000000
- *
- * Most of this really should go into a separate GT64111 header file.
- */
-#define GT64111_IO_BASE 0x10000000UL
-#define GT64111_IO_END 0x11ffffffUL
-#define GT64111_MEM_BASE 0x12000000UL
-#define GT64111_MEM_END 0x13ffffffUL
-#define GT64111_BASE 0x14000000UL
-#define GALILEO_REG(ofs) CKSEG1ADDR(GT64111_BASE + (unsigned long)(ofs))
-
-#define GALILEO_INL(port) (*(volatile unsigned int *) GALILEO_REG(port))
-#define GALILEO_OUTL(val, port) \
-do { \
- *(volatile unsigned int *) GALILEO_REG(port) = (val); \
-} while (0)
-
-#define GALILEO_INTR_T0EXP (1 << 8)
-#define GALILEO_INTR_RETRY_CTR (1 << 20)
-
-#define GALILEO_ENTC0 0x01
-#define GALILEO_SELTC0 0x02
-
#define PCI_CFG_SET(devfn,where) \
- GALILEO_OUTL((0x80000000 | (PCI_SLOT (devfn) << 11) | \
- (PCI_FUNC (devfn) << 8) | (where)), GT_PCI0_CFGADDR_OFS)
+ GT_WRITE(GT_PCI0_CFGADDR_OFS, (0x80000000 | (PCI_SLOT (devfn) << 11) | \
+ (PCI_FUNC (devfn) << 8) | (where)))
#define COBALT_LED_PORT (*(volatile unsigned char *) CKSEG1ADDR(0x1c000000))
# define COBALT_LED_BAR_LEFT (1 << 0) /* Qube */
diff --git a/include/asm-mips/mach-cobalt/mach-gt64120.h b/include/asm-mips/mach-cobalt/mach-gt64120.h
index 587fc4378f44..ae9c5523c7ef 100644
--- a/include/asm-mips/mach-cobalt/mach-gt64120.h
+++ b/include/asm-mips/mach-cobalt/mach-gt64120.h
@@ -1 +1,27 @@
-/* there's something here ... in the dark */
+/*
+ * Copyright (C) 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
+ * 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 _COBALT_MACH_GT64120_H
+#define _COBALT_MACH_GT64120_H
+
+/*
+ * Cobalt uses GT64111. GT64111 is almost the same as GT64120.
+ */
+
+#define GT64120_BASE CKSEG1ADDR(GT_DEF_BASE)
+
+#endif /* _COBALT_MACH_GT64120_H */
diff --git a/include/asm-mips/mipsregs.h b/include/asm-mips/mipsregs.h
index 1f318d707998..9985cb7c16e7 100644
--- a/include/asm-mips/mipsregs.h
+++ b/include/asm-mips/mipsregs.h
@@ -545,62 +545,6 @@
#define MIPS_FPIR_L (_ULCAST_(1) << 21)
#define MIPS_FPIR_F64 (_ULCAST_(1) << 22)
-/*
- * R10000 performance counter definitions.
- *
- * FIXME: The R10000 performance counter opens a nice way to implement CPU
- * time accounting with a precission of one cycle. I don't have
- * R10000 silicon but just a manual, so ...
- */
-
-/*
- * Events counted by counter #0
- */
-#define CE0_CYCLES 0
-#define CE0_INSN_ISSUED 1
-#define CE0_LPSC_ISSUED 2
-#define CE0_S_ISSUED 3
-#define CE0_SC_ISSUED 4
-#define CE0_SC_FAILED 5
-#define CE0_BRANCH_DECODED 6
-#define CE0_QW_WB_SECONDARY 7
-#define CE0_CORRECTED_ECC_ERRORS 8
-#define CE0_ICACHE_MISSES 9
-#define CE0_SCACHE_I_MISSES 10
-#define CE0_SCACHE_I_WAY_MISSPREDICTED 11
-#define CE0_EXT_INTERVENTIONS_REQ 12
-#define CE0_EXT_INVALIDATE_REQ 13
-#define CE0_VIRTUAL_COHERENCY_COND 14
-#define CE0_INSN_GRADUATED 15
-
-/*
- * Events counted by counter #1
- */
-#define CE1_CYCLES 0
-#define CE1_INSN_GRADUATED 1
-#define CE1_LPSC_GRADUATED 2
-#define CE1_S_GRADUATED 3
-#define CE1_SC_GRADUATED 4
-#define CE1_FP_INSN_GRADUATED 5
-#define CE1_QW_WB_PRIMARY 6
-#define CE1_TLB_REFILL 7
-#define CE1_BRANCH_MISSPREDICTED 8
-#define CE1_DCACHE_MISS 9
-#define CE1_SCACHE_D_MISSES 10
-#define CE1_SCACHE_D_WAY_MISSPREDICTED 11
-#define CE1_EXT_INTERVENTION_HITS 12
-#define CE1_EXT_INVALIDATE_REQ 13
-#define CE1_SP_HINT_TO_CEXCL_SC_BLOCKS 14
-#define CE1_SP_HINT_TO_SHARED_SC_BLOCKS 15
-
-/*
- * These flags define in which privilege mode the counters count events
- */
-#define CEB_USER 8 /* Count events in user mode, EXL = ERL = 0 */
-#define CEB_SUPERVISOR 4 /* Count events in supvervisor mode EXL = ERL = 0 */
-#define CEB_KERNEL 2 /* Count events in kernel mode EXL = ERL = 0 */
-#define CEB_EXL 1 /* Count events with EXL = 1, ERL = 0 */
-
#ifndef __ASSEMBLY__
/*
diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h
index 85b258ee7090..0dc1a45c27ed 100644
--- a/include/asm-mips/page.h
+++ b/include/asm-mips/page.h
@@ -34,7 +34,9 @@
#ifndef __ASSEMBLY__
+#include <linux/pfn.h>
#include <asm/cpu-features.h>
+#include <asm/io.h>
extern void clear_page(void * page);
extern void copy_page(void * to, void * from);
@@ -134,8 +136,14 @@ typedef struct { unsigned long pgprot; } pgprot_t;
/* to align the pointer to the (next) page boundary */
#define PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
-#define __pa(x) ((unsigned long) (x) - PAGE_OFFSET)
-#define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET))
+#if defined(CONFIG_64BIT) && !defined(CONFIG_BUILD_ELF64)
+#define __pa_page_offset(x) ((unsigned long)(x) < CKSEG0 ? PAGE_OFFSET : CKSEG0)
+#else
+#define __pa_page_offset(x) PAGE_OFFSET
+#endif
+#define __pa(x) ((unsigned long)(x) - __pa_page_offset(x))
+#define __pa_symbol(x) __pa(RELOC_HIDE((unsigned long)(x),0))
+#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET))
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
@@ -160,8 +168,8 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#endif
-#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
-#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
+#define virt_to_page(kaddr) pfn_to_page(PFN_DOWN(virt_to_phys(kaddr)))
+#define virt_addr_valid(kaddr) pfn_valid(PFN_DOWN(virt_to_phys(kaddr)))
#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
diff --git a/include/asm-mips/pgtable-64.h b/include/asm-mips/pgtable-64.h
index 7e7320300aa3..b9b1e86493ee 100644
--- a/include/asm-mips/pgtable-64.h
+++ b/include/asm-mips/pgtable-64.h
@@ -14,6 +14,7 @@
#include <asm/addrspace.h>
#include <asm/page.h>
#include <asm/cachectl.h>
+#include <asm/fixmap.h>
#include <asm-generic/pgtable-nopud.h>
@@ -103,6 +104,13 @@
#define VMALLOC_START MAP_BASE
#define VMALLOC_END \
(VMALLOC_START + PTRS_PER_PGD * PTRS_PER_PMD * PTRS_PER_PTE * PAGE_SIZE)
+#if defined(CONFIG_MODULES) && !defined(CONFIG_BUILD_ELF64) && \
+ VMALLOC_START != CKSSEG
+/* Load modules into 32bit-compatible segment. */
+#define MODULE_START CKSSEG
+#define MODULE_END (FIXADDR_START-2*PAGE_SIZE)
+extern pgd_t module_pg_dir[PTRS_PER_PGD];
+#endif
#define pte_ERROR(e) \
printk("%s:%d: bad pte %016lx.\n", __FILE__, __LINE__, pte_val(e))
@@ -174,7 +182,12 @@ static inline void pud_clear(pud_t *pudp)
#define __pmd_offset(address) pmd_index(address)
/* to find an entry in a kernel page-table-directory */
+#ifdef MODULE_START
+#define pgd_offset_k(address) \
+ ((address) >= MODULE_START ? module_pg_dir : pgd_offset(&init_mm, 0UL))
+#else
#define pgd_offset_k(address) pgd_offset(&init_mm, 0UL)
+#endif
#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
diff --git a/include/asm-mips/pgtable.h b/include/asm-mips/pgtable.h
index 1ca4d1e185c7..f2e1325fec6c 100644
--- a/include/asm-mips/pgtable.h
+++ b/include/asm-mips/pgtable.h
@@ -67,7 +67,7 @@ extern unsigned long empty_zero_page;
extern unsigned long zero_page_mask;
#define ZERO_PAGE(vaddr) \
- (virt_to_page(empty_zero_page + (((unsigned long)(vaddr)) & zero_page_mask)))
+ (virt_to_page((void *)(empty_zero_page + (((unsigned long)(vaddr)) & zero_page_mask))))
#define __HAVE_ARCH_MOVE_PTE
#define move_pte(pte, prot, old_addr, new_addr) \
diff --git a/include/asm-mips/ptrace.h b/include/asm-mips/ptrace.h
index 5f3a9075cd28..30bf555faeaa 100644
--- a/include/asm-mips/ptrace.h
+++ b/include/asm-mips/ptrace.h
@@ -80,8 +80,6 @@ struct pt_regs {
#define instruction_pointer(regs) ((regs)->cp0_epc)
#define profile_pc(regs) instruction_pointer(regs)
-extern void show_regs(struct pt_regs *);
-
extern asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit);
#endif
diff --git a/include/asm-mips/time.h b/include/asm-mips/time.h
index 625acd337bc3..a632cef830a2 100644
--- a/include/asm-mips/time.h
+++ b/include/asm-mips/time.h
@@ -21,6 +21,7 @@
#include <linux/ptrace.h>
#include <linux/rtc.h>
#include <linux/spinlock.h>
+#include <linux/clocksource.h>
extern spinlock_t rtc_lock;
@@ -44,12 +45,10 @@ extern int (*mips_timer_state)(void);
extern void (*mips_timer_ack)(void);
/*
- * High precision timer functions.
- * If mips_hpt_read is NULL, an R4k-compatible timer setup is attempted.
+ * High precision timer clocksource.
+ * If .read is NULL, an R4k-compatible timer setup is attempted.
*/
-extern unsigned int (*mips_hpt_read)(void);
-extern void (*mips_hpt_init)(void);
-extern unsigned int mips_hpt_mask;
+extern struct clocksource clocksource_mips;
/*
* to_tm() converts system time back to (year, mon, day, hour, min, sec).
diff --git a/include/asm-parisc/checksum.h b/include/asm-parisc/checksum.h
index 229cb56fdb7a..cc3ec1bd8919 100644
--- a/include/asm-parisc/checksum.h
+++ b/include/asm-parisc/checksum.h
@@ -15,7 +15,7 @@
*
* it's best to have buff aligned on a 32-bit boundary
*/
-extern unsigned int csum_partial(const unsigned char *, int, unsigned int);
+extern __wsum csum_partial(const void *, int, __wsum);
/*
* The same as csum_partial, but copies from src while it checksums.
@@ -23,15 +23,14 @@ extern unsigned int csum_partial(const unsigned char *, int, unsigned int);
* Here even more important to align src and dst on a 32-bit (or even
* better 64-bit) boundary
*/
-extern unsigned int csum_partial_copy_nocheck(const unsigned char *, unsigned char *,
- int, unsigned int);
+extern __wsum csum_partial_copy_nocheck(const void *, void *, int, __wsum);
/*
* this is a new version of the above that records errors it finds in *errp,
* but continues and zeros the rest of the buffer.
*/
-extern unsigned int csum_partial_copy_from_user(const unsigned char __user *src,
- unsigned char *dst, int len, unsigned int sum, int *errp);
+extern __wsum csum_partial_copy_from_user(const void __user *src,
+ void *dst, int len, __wsum sum, int *errp);
/*
* Optimized for IP headers, which always checksum on 4 octet boundaries.
@@ -39,11 +38,10 @@ extern unsigned int csum_partial_copy_from_user(const unsigned char __user *src,
* Written by Randolph Chung <tausq@debian.org>, and then mucked with by
* LaMont Jones <lamont@debian.org>
*/
-static inline unsigned short ip_fast_csum(unsigned char * iph,
- unsigned int ihl) {
+static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
+{
unsigned int sum;
-
__asm__ __volatile__ (
" ldws,ma 4(%1), %0\n"
" addib,<= -4, %2, 2f\n"
@@ -69,27 +67,27 @@ static inline unsigned short ip_fast_csum(unsigned char * iph,
: "1" (iph), "2" (ihl)
: "r19", "r20", "r21" );
- return(sum);
+ return (__force __sum16)sum;
}
/*
* Fold a partial checksum
*/
-static inline unsigned int csum_fold(unsigned int sum)
+static inline __sum16 csum_fold(__wsum csum)
{
+ u32 sum = (__force u32)csum;
/* add the swapped two 16-bit halves of sum,
a possible carry from adding the two 16-bit halves,
will carry from the lower half into the upper half,
giving us the correct sum in the upper half. */
sum += (sum << 16) + (sum >> 16);
- return (~sum) >> 16;
+ return (__force __sum16)(~sum >> 16);
}
-static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
- unsigned long daddr,
+static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
unsigned short len,
unsigned short proto,
- unsigned int sum)
+ __wsum sum)
{
__asm__(
" add %1, %0, %0\n"
@@ -97,19 +95,18 @@ static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
" addc %3, %0, %0\n"
" addc %%r0, %0, %0\n"
: "=r" (sum)
- : "r" (daddr), "r"(saddr), "r"((proto<<16)+len), "0"(sum));
- return sum;
+ : "r" (daddr), "r"(saddr), "r"(proto+len), "0"(sum));
+ return sum;
}
/*
* computes the checksum of the TCP/UDP pseudo-header
* returns a 16-bit checksum, already complemented
*/
-static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
- unsigned long daddr,
+static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
unsigned short len,
unsigned short proto,
- unsigned int sum)
+ __wsum sum)
{
return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
}
@@ -118,17 +115,17 @@ static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
* this routine is used for miscellaneous IP-like checksums, mainly
* in icmp.c
*/
-static inline unsigned short ip_compute_csum(unsigned char * buf, int len) {
+static inline __sum16 ip_compute_csum(const void *buf, int len)
+{
return csum_fold (csum_partial(buf, len, 0));
}
#define _HAVE_ARCH_IPV6_CSUM
-static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
- struct in6_addr *daddr,
- __u16 len,
- unsigned short proto,
- unsigned int sum)
+static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+ const struct in6_addr *daddr,
+ __u32 len, unsigned short proto,
+ __wsum sum)
{
__asm__ __volatile__ (
@@ -193,9 +190,9 @@ static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
* Copy and checksum to user
*/
#define HAVE_CSUM_COPY_USER
-static __inline__ unsigned int csum_and_copy_to_user (const unsigned char *src,
- unsigned char __user *dst,
- int len, int sum,
+static __inline__ __wsum csum_and_copy_to_user(const void *src,
+ void __user *dst,
+ int len, __wsum sum,
int *err_ptr)
{
/* code stolen from include/asm-mips64 */
@@ -203,7 +200,7 @@ static __inline__ unsigned int csum_and_copy_to_user (const unsigned char *src,
if (copy_to_user(dst, src, len)) {
*err_ptr = -EFAULT;
- return -1;
+ return (__force __wsum)-1;
}
return sum;
diff --git a/include/asm-parisc/device.h b/include/asm-parisc/device.h
new file mode 100644
index 000000000000..d8f9872b0e2d
--- /dev/null
+++ b/include/asm-parisc/device.h
@@ -0,0 +1,7 @@
+/*
+ * Arch specific extensions to struct device
+ *
+ * This file is released under the GPLv2
+ */
+#include <asm-generic/device.h>
+
diff --git a/include/asm-parisc/dma.h b/include/asm-parisc/dma.h
index da2cf373e31c..31ad0f05af3d 100644
--- a/include/asm-parisc/dma.h
+++ b/include/asm-parisc/dma.h
@@ -17,10 +17,10 @@
/*
** DMA_CHUNK_SIZE is used by the SCSI mid-layer to break up
-** (or rather not merge) DMA's into managable chunks.
+** (or rather not merge) DMAs into manageable chunks.
** On parisc, this is more of the software/tuning constraint
-** rather than the HW. I/O MMU allocation alogorithms can be
-** faster with smaller size is (to some degree).
+** rather than the HW. I/O MMU allocation algorithms can be
+** faster with smaller sizes (to some degree).
*/
#define DMA_CHUNK_SIZE (BITS_PER_LONG*PAGE_SIZE)
diff --git a/include/asm-parisc/pci.h b/include/asm-parisc/pci.h
index 7b8ad118d2fe..7b3be9ac0dda 100644
--- a/include/asm-parisc/pci.h
+++ b/include/asm-parisc/pci.h
@@ -149,7 +149,7 @@ extern int parisc_bus_is_phys; /* in arch/parisc/kernel/setup.c */
/*
** Most PCI devices (eg Tulip, NCR720) also export the same registers
** to both MMIO and I/O port space. Due to poor performance of I/O Port
-** access under HP PCI bus adapters, strongly reccomend use of MMIO
+** access under HP PCI bus adapters, strongly recommend the use of MMIO
** address space.
**
** While I'm at it more PA programming notes:
diff --git a/include/asm-parisc/ropes.h b/include/asm-parisc/ropes.h
index 5542dd00472b..007a880615eb 100644
--- a/include/asm-parisc/ropes.h
+++ b/include/asm-parisc/ropes.h
@@ -14,7 +14,7 @@
#endif
/*
-** The number of pdir entries to "free" before issueing
+** The number of pdir entries to "free" before issuing
** a read to PCOM register to flush out PCOM writes.
** Interacts with allocation granularity (ie 4 or 8 entries
** allocated and free'd/purged at a time might make this
diff --git a/include/asm-parisc/semaphore.h b/include/asm-parisc/semaphore.h
index c9ee41cd0707..d45827a21f94 100644
--- a/include/asm-parisc/semaphore.h
+++ b/include/asm-parisc/semaphore.h
@@ -115,7 +115,8 @@ extern __inline__ int down_interruptible(struct semaphore * sem)
*/
extern __inline__ int down_trylock(struct semaphore * sem)
{
- int flags, count;
+ unsigned long flags;
+ int count;
spin_lock_irqsave(&sem->sentry, flags);
count = sem->count - 1;
@@ -131,7 +132,8 @@ extern __inline__ int down_trylock(struct semaphore * sem)
*/
extern __inline__ void up(struct semaphore * sem)
{
- int flags;
+ unsigned long flags;
+
spin_lock_irqsave(&sem->sentry, flags);
if (sem->count < 0) {
__up(sem);
diff --git a/include/asm-powerpc/checksum.h b/include/asm-powerpc/checksum.h
index 609ecbbd7210..7cdf358337cf 100644
--- a/include/asm-powerpc/checksum.h
+++ b/include/asm-powerpc/checksum.h
@@ -14,17 +14,16 @@
* which always checksum on 4 octet boundaries. ihl is the number
* of 32-bit words and is always >= 5.
*/
-extern unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl);
+extern __sum16 ip_fast_csum(const void *iph, unsigned int ihl);
/*
* computes the checksum of the TCP/UDP pseudo-header
* returns a 16-bit checksum, already complemented
*/
-extern unsigned short csum_tcpudp_magic(unsigned long saddr,
- unsigned long daddr,
+extern __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
unsigned short len,
unsigned short proto,
- unsigned int sum);
+ __wsum sum);
/*
* computes the checksum of a memory block at buff, length len,
@@ -38,8 +37,7 @@ extern unsigned short csum_tcpudp_magic(unsigned long saddr,
*
* it's best to have buff aligned on a 32-bit boundary
*/
-extern unsigned int csum_partial(const unsigned char * buff, int len,
- unsigned int sum);
+extern __wsum csum_partial(const void *buff, int len, __wsum sum);
/*
* Computes the checksum of a memory block at src, length len,
@@ -51,20 +49,15 @@ extern unsigned int csum_partial(const unsigned char * buff, int len,
* Like csum_partial, this must be called with even lengths,
* except for the last fragment.
*/
-extern unsigned int csum_partial_copy_generic(const char *src, char *dst,
- int len, unsigned int sum,
+extern __wsum csum_partial_copy_generic(const void *src, void *dst,
+ int len, __wsum sum,
int *src_err, int *dst_err);
/*
* the same as csum_partial, but copies from src to dst while it
* checksums.
*/
-unsigned int csum_partial_copy_nocheck(const char *src,
- char *dst,
- int len,
- unsigned int sum);
-
#define csum_partial_copy_from_user(src, dst, len, sum, errp) \
- csum_partial_copy_generic((src), (dst), (len), (sum), (errp), NULL)
+ csum_partial_copy_generic((__force const void *)(src), (dst), (len), (sum), (errp), NULL)
#define csum_partial_copy_nocheck(src, dst, len, sum) \
csum_partial_copy_generic((src), (dst), (len), (sum), NULL, NULL)
@@ -74,7 +67,7 @@ unsigned int csum_partial_copy_nocheck(const char *src,
* turns a 32-bit partial checksum (e.g. from csum_partial) into a
* 1's complement 16-bit checksum.
*/
-static inline unsigned int csum_fold(unsigned int sum)
+static inline __sum16 csum_fold(__wsum sum)
{
unsigned int tmp;
@@ -83,41 +76,32 @@ static inline unsigned int csum_fold(unsigned int sum)
/* if there is a carry from adding the two 16-bit halves,
it will carry from the lower half into the upper half,
giving us the correct sum in the upper half. */
- sum = ~(sum + tmp) >> 16;
- return sum;
+ return (__force __sum16)(~((__force u32)sum + tmp) >> 16);
}
/*
* this routine is used for miscellaneous IP-like checksums, mainly
* in icmp.c
*/
-static inline unsigned short ip_compute_csum(unsigned char * buff, int len)
+static inline __sum16 ip_compute_csum(const void *buff, int len)
{
return csum_fold(csum_partial(buff, len, 0));
}
-#ifdef __powerpc64__
-static inline u32 csum_tcpudp_nofold(u32 saddr,
- u32 daddr,
+static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
unsigned short len,
unsigned short proto,
- unsigned int sum)
+ __wsum sum)
{
- unsigned long s = sum;
+#ifdef __powerpc64__
+ unsigned long s = (__force u32)sum;
- s += saddr;
- s += daddr;
- s += (proto << 16) + len;
+ s += (__force u32)saddr;
+ s += (__force u32)daddr;
+ s += proto + len;
s += (s >> 32);
- return (u32) s;
-}
+ return (__force __wsum) s;
#else
-static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
- unsigned long daddr,
- unsigned short len,
- unsigned short proto,
- unsigned int sum)
-{
__asm__("\n\
addc %0,%0,%1 \n\
adde %0,%0,%2 \n\
@@ -125,10 +109,9 @@ static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
addze %0,%0 \n\
"
: "=r" (sum)
- : "r" (daddr), "r"(saddr), "r"((proto<<16)+len), "0"(sum));
- return sum;
-}
-
+ : "r" (daddr), "r"(saddr), "r"(proto + len), "0"(sum));
+ return sum;
#endif
+}
#endif /* __KERNEL__ */
#endif
diff --git a/include/asm-powerpc/device.h b/include/asm-powerpc/device.h
new file mode 100644
index 000000000000..d8f9872b0e2d
--- /dev/null
+++ b/include/asm-powerpc/device.h
@@ -0,0 +1,7 @@
+/*
+ * Arch specific extensions to struct device
+ *
+ * This file is released under the GPLv2
+ */
+#include <asm-generic/device.h>
+
diff --git a/include/asm-powerpc/pci.h b/include/asm-powerpc/pci.h
index 46afd29b904e..721c97f09b20 100644
--- a/include/asm-powerpc/pci.h
+++ b/include/asm-powerpc/pci.h
@@ -62,19 +62,13 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
}
#ifdef CONFIG_PPC64
-#define HAVE_ARCH_PCI_MWI 1
-static inline int pcibios_prep_mwi(struct pci_dev *dev)
-{
- /*
- * We would like to avoid touching the cacheline size or MWI bit
- * but we cant do that with the current pcibios_prep_mwi
- * interface. pSeries firmware sets the cacheline size (which is not
- * the cpu cacheline size in all cases) and hardware treats MWI
- * the same as memory write. So we dont touch the cacheline size
- * here and allow the generic code to set the MWI bit.
- */
- return 0;
-}
+
+/*
+ * We want to avoid touching the cacheline size or MWI bit.
+ * pSeries firmware sets the cacheline size (which is not the cpu cacheline
+ * size in all cases) and hardware treats MWI the same as memory write.
+ */
+#define PCI_DISABLE_MWI
extern struct dma_mapping_ops pci_dma_ops;
diff --git a/include/asm-ppc/device.h b/include/asm-ppc/device.h
new file mode 100644
index 000000000000..d8f9872b0e2d
--- /dev/null
+++ b/include/asm-ppc/device.h
@@ -0,0 +1,7 @@
+/*
+ * Arch specific extensions to struct device
+ *
+ * This file is released under the GPLv2
+ */
+#include <asm-generic/device.h>
+
diff --git a/include/asm-s390/checksum.h b/include/asm-s390/checksum.h
index 37c362d89fad..0a3cd7ec8451 100644
--- a/include/asm-s390/checksum.h
+++ b/include/asm-s390/checksum.h
@@ -27,8 +27,8 @@
*
* it's best to have buff aligned on a 32-bit boundary
*/
-static inline unsigned int
-csum_partial(const unsigned char * buff, int len, unsigned int sum)
+static inline __wsum
+csum_partial(const void *buff, int len, __wsum sum)
{
register unsigned long reg2 asm("2") = (unsigned long) buff;
register unsigned long reg3 asm("3") = (unsigned long) len;
@@ -49,9 +49,9 @@ csum_partial(const unsigned char * buff, int len, unsigned int sum)
* Copy from userspace and compute checksum. If we catch an exception
* then zero the rest of the buffer.
*/
-static inline unsigned int
-csum_partial_copy_from_user(const char __user *src, char *dst,
- int len, unsigned int sum,
+static inline __wsum
+csum_partial_copy_from_user(const void __user *src, void *dst,
+ int len, __wsum sum,
int *err_ptr)
{
int missing;
@@ -66,8 +66,8 @@ csum_partial_copy_from_user(const char __user *src, char *dst,
}
-static inline unsigned int
-csum_partial_copy_nocheck (const char *src, char *dst, int len, unsigned int sum)
+static inline __wsum
+csum_partial_copy_nocheck (const void *src, void *dst, int len, __wsum sum)
{
memcpy(dst,src,len);
return csum_partial(dst, len, sum);
@@ -76,8 +76,7 @@ csum_partial_copy_nocheck (const char *src, char *dst, int len, unsigned int sum
/*
* Fold a partial checksum without adding pseudo headers
*/
-static inline unsigned short
-csum_fold(unsigned int sum)
+static inline __sum16 csum_fold(__wsum sum)
{
#ifndef __s390x__
register_pair rp;
@@ -100,7 +99,7 @@ csum_fold(unsigned int sum)
" srl %0,16\n" /* %0 = H+L+C */
: "+&d" (sum) : : "cc", "2", "3");
#endif /* __s390x__ */
- return ((unsigned short) ~sum);
+ return (__force __sum16) ~sum;
}
/*
@@ -108,8 +107,7 @@ csum_fold(unsigned int sum)
* which always checksum on 4 octet boundaries.
*
*/
-static inline unsigned short
-ip_fast_csum(unsigned char *iph, unsigned int ihl)
+static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
{
return csum_fold(csum_partial(iph, ihl*4, 0));
}
@@ -118,10 +116,10 @@ ip_fast_csum(unsigned char *iph, unsigned int ihl)
* computes the checksum of the TCP/UDP pseudo-header
* returns a 32-bit checksum
*/
-static inline unsigned int
-csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr,
+static inline __wsum
+csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
unsigned short len, unsigned short proto,
- unsigned int sum)
+ __wsum sum)
{
#ifndef __s390x__
asm volatile(
@@ -137,12 +135,12 @@ csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr,
"1:"
: "+&d" (sum) : "d" (daddr) : "cc");
asm volatile(
- " alr %0,%1\n" /* sum += (len<<16) + (proto<<8) */
+ " alr %0,%1\n" /* sum += len + proto */
" brc 12,2f\n"
" ahi %0,1\n" /* add carry */
"2:"
: "+&d" (sum)
- : "d" (((unsigned int) len<<16) + (unsigned int) proto)
+ : "d" (len + proto)
: "cc");
#else /* __s390x__ */
asm volatile(
@@ -153,7 +151,7 @@ csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr,
"0: algr %0,%2\n" /* sum += daddr */
" brc 12,1f\n"
" aghi %0,1\n" /* add carry */
- "1: algfr %0,%3\n" /* sum += (len<<16) + proto */
+ "1: algfr %0,%3\n" /* sum += len + proto */
" brc 12,2f\n"
" aghi %0,1\n" /* add carry */
"2: srlg 0,%0,32\n"
@@ -163,7 +161,7 @@ csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr,
"3: llgfr %0,%0"
: "+&d" (sum)
: "d" (saddr), "d" (daddr),
- "d" (((unsigned int) len<<16) + (unsigned int) proto)
+ "d" (len + proto)
: "cc", "0");
#endif /* __s390x__ */
return sum;
@@ -174,10 +172,10 @@ csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr,
* returns a 16-bit checksum, already complemented
*/
-static inline unsigned short int
-csum_tcpudp_magic(unsigned long saddr, unsigned long daddr,
+static inline __sum16
+csum_tcpudp_magic(__be32 saddr, __be32 daddr,
unsigned short len, unsigned short proto,
- unsigned int sum)
+ __wsum sum)
{
return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
}
@@ -187,8 +185,7 @@ csum_tcpudp_magic(unsigned long saddr, unsigned long daddr,
* in icmp.c
*/
-static inline unsigned short
-ip_compute_csum(unsigned char * buff, int len)
+static inline __sum16 ip_compute_csum(const void *buff, int len)
{
return csum_fold(csum_partial(buff, len, 0));
}
diff --git a/include/asm-s390/device.h b/include/asm-s390/device.h
new file mode 100644
index 000000000000..d8f9872b0e2d
--- /dev/null
+++ b/include/asm-s390/device.h
@@ -0,0 +1,7 @@
+/*
+ * Arch specific extensions to struct device
+ *
+ * This file is released under the GPLv2
+ */
+#include <asm-generic/device.h>
+
diff --git a/include/asm-sh/checksum.h b/include/asm-sh/checksum.h
index 08168afe6746..d44344c88e73 100644
--- a/include/asm-sh/checksum.h
+++ b/include/asm-sh/checksum.h
@@ -23,7 +23,7 @@
*
* it's best to have buff aligned on a 32-bit boundary
*/
-asmlinkage unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
+asmlinkage __wsum csum_partial(const void *buff, int len, __wsum sum);
/*
* the same as csum_partial, but copies from src while it
@@ -33,8 +33,8 @@ asmlinkage unsigned int csum_partial(const unsigned char * buff, int len, unsign
* better 64-bit) boundary
*/
-asmlinkage unsigned int csum_partial_copy_generic(const unsigned char *src, unsigned char *dst,
- int len, int sum, int *src_err_ptr, int *dst_err_ptr);
+asmlinkage __wsum csum_partial_copy_generic(const void *src, void *dst,
+ int len, __wsum sum, int *src_err_ptr, int *dst_err_ptr);
/*
* Note: when you get a NULL pointer exception here this means someone
@@ -44,24 +44,25 @@ asmlinkage unsigned int csum_partial_copy_generic(const unsigned char *src, unsi
* access_ok().
*/
static __inline__
-unsigned int csum_partial_copy_nocheck (const unsigned char *src, unsigned char *dst,
- int len, int sum)
+__wsum csum_partial_copy_nocheck(const void *src, void *dst,
+ int len, __wsum sum)
{
return csum_partial_copy_generic ( src, dst, len, sum, NULL, NULL);
}
static __inline__
-unsigned int csum_partial_copy_from_user (const unsigned char *src, unsigned char *dst,
- int len, int sum, int *err_ptr)
+__wsum csum_partial_copy_from_user(const void __user *src, void *dst,
+ int len, __wsum sum, int *err_ptr)
{
- return csum_partial_copy_generic ( src, dst, len, sum, err_ptr, NULL);
+ return csum_partial_copy_generic((__force const void *)src, dst,
+ len, sum, err_ptr, NULL);
}
/*
* Fold a partial checksum
*/
-static __inline__ unsigned int csum_fold(unsigned int sum)
+static __inline__ __sum16 csum_fold(__wsum sum)
{
unsigned int __dummy;
__asm__("swap.w %0, %1\n\t"
@@ -74,7 +75,7 @@ static __inline__ unsigned int csum_fold(unsigned int sum)
: "=r" (sum), "=&r" (__dummy)
: "0" (sum)
: "t");
- return sum;
+ return (__force __sum16)sum;
}
/*
@@ -84,7 +85,7 @@ static __inline__ unsigned int csum_fold(unsigned int sum)
* i386 version by Jorge Cwik <jorge@laser.satlink.net>, adapted
* for linux by * Arnt Gulbrandsen.
*/
-static __inline__ unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl)
+static __inline__ __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
{
unsigned int sum, __dummy0, __dummy1;
@@ -112,16 +113,15 @@ static __inline__ unsigned short ip_fast_csum(unsigned char * iph, unsigned int
return csum_fold(sum);
}
-static __inline__ unsigned long csum_tcpudp_nofold(unsigned long saddr,
- unsigned long daddr,
+static __inline__ __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
unsigned short len,
unsigned short proto,
- unsigned int sum)
+ __wsum sum)
{
#ifdef __LITTLE_ENDIAN__
- unsigned long len_proto = (ntohs(len)<<16)+proto*256;
+ unsigned long len_proto = (proto + len) << 8;
#else
- unsigned long len_proto = (proto<<16)+len;
+ unsigned long len_proto = proto + len;
#endif
__asm__("clrt\n\t"
"addc %0, %1\n\t"
@@ -139,11 +139,10 @@ static __inline__ unsigned long csum_tcpudp_nofold(unsigned long saddr,
* computes the checksum of the TCP/UDP pseudo-header
* returns a 16-bit checksum, already complemented
*/
-static __inline__ unsigned short int csum_tcpudp_magic(unsigned long saddr,
- unsigned long daddr,
+static __inline__ __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
unsigned short len,
unsigned short proto,
- unsigned int sum)
+ __wsum sum)
{
return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
}
@@ -153,18 +152,17 @@ static __inline__ unsigned short int csum_tcpudp_magic(unsigned long saddr,
* in icmp.c
*/
-static __inline__ unsigned short ip_compute_csum(unsigned char * buff, int len)
+static __inline__ __sum16 ip_compute_csum(const void *buff, int len)
{
return csum_fold (csum_partial(buff, len, 0));
}
#define _HAVE_ARCH_IPV6_CSUM
#ifdef CONFIG_IPV6
-static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
- struct in6_addr *daddr,
- __u32 len,
- unsigned short proto,
- unsigned int sum)
+static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+ const struct in6_addr *daddr,
+ __u32 len, unsigned short proto,
+ __wsum sum)
{
unsigned int __dummy;
__asm__("clrt\n\t"
@@ -201,17 +199,18 @@ static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
* Copy and checksum to user
*/
#define HAVE_CSUM_COPY_USER
-static __inline__ unsigned int csum_and_copy_to_user (const unsigned char *src,
- unsigned char __user *dst,
- int len, int sum,
+static __inline__ __wsum csum_and_copy_to_user (const void *src,
+ void __user *dst,
+ int len, __wsum sum,
int *err_ptr)
{
if (access_ok(VERIFY_WRITE, dst, len))
- return csum_partial_copy_generic(src, dst, len, sum, NULL, err_ptr);
+ return csum_partial_copy_generic((__force const void *)src,
+ dst, len, sum, NULL, err_ptr);
if (len)
*err_ptr = -EFAULT;
- return -1; /* invalid checksum */
+ return (__force __wsum)-1; /* invalid checksum */
}
#endif /* __ASM_SH_CHECKSUM_H */
diff --git a/include/asm-sh/device.h b/include/asm-sh/device.h
new file mode 100644
index 000000000000..d8f9872b0e2d
--- /dev/null
+++ b/include/asm-sh/device.h
@@ -0,0 +1,7 @@
+/*
+ * Arch specific extensions to struct device
+ *
+ * This file is released under the GPLv2
+ */
+#include <asm-generic/device.h>
+
diff --git a/include/asm-sh64/checksum.h b/include/asm-sh64/checksum.h
index fd034e9ae6e3..ba594ccb42e5 100644
--- a/include/asm-sh64/checksum.h
+++ b/include/asm-sh64/checksum.h
@@ -26,8 +26,7 @@
*
* it's best to have buff aligned on a 32-bit boundary
*/
-asmlinkage unsigned int csum_partial(const unsigned char *buff, int len,
- unsigned int sum);
+asmlinkage __wsum csum_partial(const void *buff, int len, __wsum sum);
/*
* Note: when you get a NULL pointer exception here this means someone
@@ -38,46 +37,34 @@ asmlinkage unsigned int csum_partial(const unsigned char *buff, int len,
*/
-unsigned int csum_partial_copy_nocheck(const char *src, char *dst, int len,
- unsigned int sum);
+__wsum csum_partial_copy_nocheck(const void *src, void *dst, int len,
+ __wsum sum);
-unsigned int csum_partial_copy_from_user(const char *src, char *dst,
- int len, int sum, int *err_ptr);
+__wsum csum_partial_copy_from_user(const void __user *src, void *dst,
+ int len, __wsum sum, int *err_ptr);
-/*
- * These are the old (and unsafe) way of doing checksums, a warning message will be
- * printed if they are used and an exeption occurs.
- *
- * these functions should go away after some time.
- */
-
-#define csum_partial_copy_fromuser csum_partial_copy
-
-unsigned int csum_partial_copy(const char *src, char *dst, int len,
- unsigned int sum);
-
-static inline unsigned short csum_fold(unsigned int sum)
+static inline __sum16 csum_fold(__wsum csum)
{
+ u32 sum = (__force u32)csum;
sum = (sum & 0xffff) + (sum >> 16);
sum = (sum & 0xffff) + (sum >> 16);
- return ~(sum);
+ return (__force __sum16)~sum;
}
-unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl);
+__sum16 ip_fast_csum(const void *iph, unsigned int ihl);
-unsigned long csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr,
+__wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
unsigned short len, unsigned short proto,
- unsigned int sum);
+ __wsum sum);
/*
* computes the checksum of the TCP/UDP pseudo-header
* returns a 16-bit checksum, already complemented
*/
-static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
- unsigned long daddr,
+static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
unsigned short len,
unsigned short proto,
- unsigned int sum)
+ __wsum sum)
{
return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
}
@@ -86,7 +73,7 @@ static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
* this routine is used for miscellaneous IP-like checksums, mainly
* in icmp.c
*/
-static inline unsigned short ip_compute_csum(unsigned char * buff, int len)
+static inline __sum16 ip_compute_csum(const void *buff, int len)
{
return csum_fold(csum_partial(buff, len, 0));
}
diff --git a/include/asm-sh64/device.h b/include/asm-sh64/device.h
new file mode 100644
index 000000000000..d8f9872b0e2d
--- /dev/null
+++ b/include/asm-sh64/device.h
@@ -0,0 +1,7 @@
+/*
+ * Arch specific extensions to struct device
+ *
+ * This file is released under the GPLv2
+ */
+#include <asm-generic/device.h>
+
diff --git a/include/asm-sparc/checksum.h b/include/asm-sparc/checksum.h
index 286158108974..267e631e9bbc 100644
--- a/include/asm-sparc/checksum.h
+++ b/include/asm-sparc/checksum.h
@@ -30,7 +30,7 @@
*
* it's best to have buff aligned on a 32-bit boundary
*/
-extern unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
+extern __wsum csum_partial(const void *buff, int len, __wsum sum);
/* the same as csum_partial, but copies from fs:src while it
* checksums
@@ -41,9 +41,8 @@ extern unsigned int csum_partial(const unsigned char * buff, int len, unsigned i
extern unsigned int __csum_partial_copy_sparc_generic (const unsigned char *, unsigned char *);
-static inline unsigned int
-csum_partial_copy_nocheck (const unsigned char *src, unsigned char *dst, int len,
- unsigned int sum)
+static inline __wsum
+csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
{
register unsigned int ret asm("o0") = (unsigned int)src;
register char *d asm("o1") = dst;
@@ -57,42 +56,36 @@ csum_partial_copy_nocheck (const unsigned char *src, unsigned char *dst, int len
: "o2", "o3", "o4", "o5", "o7",
"g2", "g3", "g4", "g5", "g7",
"memory", "cc");
- return ret;
+ return (__force __wsum)ret;
}
-static inline unsigned int
-csum_partial_copy_from_user(const unsigned char __user *src, unsigned char *dst, int len,
- unsigned int sum, int *err)
+static inline __wsum
+csum_partial_copy_from_user(const void __user *src, void *dst, int len,
+ __wsum sum, int *err)
{
- if (!access_ok (VERIFY_READ, src, len)) {
- *err = -EFAULT;
- memset (dst, 0, len);
- return sum;
- } else {
- register unsigned long ret asm("o0") = (unsigned long)src;
- register char *d asm("o1") = dst;
- register int l asm("g1") = len;
- register unsigned int s asm("g7") = sum;
+ register unsigned long ret asm("o0") = (unsigned long)src;
+ register char *d asm("o1") = dst;
+ register int l asm("g1") = len;
+ register __wsum s asm("g7") = sum;
- __asm__ __volatile__ (
- ".section __ex_table,#alloc\n\t"
- ".align 4\n\t"
- ".word 1f,2\n\t"
- ".previous\n"
- "1:\n\t"
- "call __csum_partial_copy_sparc_generic\n\t"
- " st %8, [%%sp + 64]\n"
- : "=&r" (ret), "=&r" (d), "=&r" (l), "=&r" (s)
- : "0" (ret), "1" (d), "2" (l), "3" (s), "r" (err)
- : "o2", "o3", "o4", "o5", "o7", "g2", "g3", "g4", "g5",
- "cc", "memory");
- return ret;
- }
- }
+ __asm__ __volatile__ (
+ ".section __ex_table,#alloc\n\t"
+ ".align 4\n\t"
+ ".word 1f,2\n\t"
+ ".previous\n"
+ "1:\n\t"
+ "call __csum_partial_copy_sparc_generic\n\t"
+ " st %8, [%%sp + 64]\n"
+ : "=&r" (ret), "=&r" (d), "=&r" (l), "=&r" (s)
+ : "0" (ret), "1" (d), "2" (l), "3" (s), "r" (err)
+ : "o2", "o3", "o4", "o5", "o7", "g2", "g3", "g4", "g5",
+ "cc", "memory");
+ return (__force __wsum)ret;
+}
-static inline unsigned int
-csum_partial_copy_to_user(const unsigned char *src, unsigned char __user *dst, int len,
- unsigned int sum, int *err)
+static inline __wsum
+csum_partial_copy_to_user(const void *src, void __user *dst, int len,
+ __wsum sum, int *err)
{
if (!access_ok (VERIFY_WRITE, dst, len)) {
*err = -EFAULT;
@@ -101,7 +94,7 @@ csum_partial_copy_to_user(const unsigned char *src, unsigned char __user *dst, i
register unsigned long ret asm("o0") = (unsigned long)src;
register char __user *d asm("o1") = dst;
register int l asm("g1") = len;
- register unsigned int s asm("g7") = sum;
+ register __wsum s asm("g7") = sum;
__asm__ __volatile__ (
".section __ex_table,#alloc\n\t"
@@ -116,7 +109,7 @@ csum_partial_copy_to_user(const unsigned char *src, unsigned char __user *dst, i
: "o2", "o3", "o4", "o5", "o7",
"g2", "g3", "g4", "g5",
"cc", "memory");
- return ret;
+ return (__force __wsum)ret;
}
}
@@ -126,10 +119,9 @@ csum_partial_copy_to_user(const unsigned char *src, unsigned char __user *dst, i
/* ihl is always 5 or greater, almost always is 5, and iph is word aligned
* the majority of the time.
*/
-static inline unsigned short ip_fast_csum(const unsigned char *iph,
- unsigned int ihl)
+static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
{
- unsigned short sum;
+ __sum16 sum;
/* Note: We must read %2 before we touch %0 for the first time,
* because GCC can legitimately use the same register for
@@ -164,7 +156,7 @@ static inline unsigned short ip_fast_csum(const unsigned char *iph,
}
/* Fold a partial checksum without adding pseudo headers. */
-static inline unsigned int csum_fold(unsigned int sum)
+static inline __sum16 csum_fold(__wsum sum)
{
unsigned int tmp;
@@ -173,23 +165,22 @@ static inline unsigned int csum_fold(unsigned int sum)
"addx\t%1, %%g0, %1\n\t"
"xnor\t%%g0, %1, %0"
: "=&r" (sum), "=r" (tmp)
- : "0" (sum), "1" (sum<<16)
+ : "0" (sum), "1" ((__force u32)sum<<16)
: "cc");
- return sum;
+ return (__force __sum16)sum;
}
-static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
- unsigned long daddr,
- unsigned int len,
+static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
+ unsigned short len,
unsigned short proto,
- unsigned int sum)
+ __wsum sum)
{
__asm__ __volatile__("addcc\t%1, %0, %0\n\t"
"addxcc\t%2, %0, %0\n\t"
"addxcc\t%3, %0, %0\n\t"
"addx\t%0, %%g0, %0\n\t"
: "=r" (sum), "=r" (saddr)
- : "r" (daddr), "r" ((proto<<16)+len), "0" (sum),
+ : "r" (daddr), "r" (proto + len), "0" (sum),
"1" (saddr)
: "cc");
return sum;
@@ -199,22 +190,20 @@ static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
* computes the checksum of the TCP/UDP pseudo-header
* returns a 16-bit checksum, already complemented
*/
-static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
- unsigned long daddr,
+static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
unsigned short len,
unsigned short proto,
- unsigned int sum)
+ __wsum sum)
{
return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
}
#define _HAVE_ARCH_IPV6_CSUM
-static inline unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
- struct in6_addr *daddr,
- __u32 len,
- unsigned short proto,
- unsigned int sum)
+static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+ const struct in6_addr *daddr,
+ __u32 len, unsigned short proto,
+ __wsum sum)
{
__asm__ __volatile__ (
"addcc %3, %4, %%g4\n\t"
@@ -245,7 +234,7 @@ static inline unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
}
/* this routine is used for miscellaneous IP-like checksums, mainly in icmp.c */
-static inline unsigned short ip_compute_csum(unsigned char * buff, int len)
+static inline __sum16 ip_compute_csum(const void *buff, int len)
{
return csum_fold(csum_partial(buff, len, 0));
}
diff --git a/include/asm-sparc/device.h b/include/asm-sparc/device.h
new file mode 100644
index 000000000000..d8f9872b0e2d
--- /dev/null
+++ b/include/asm-sparc/device.h
@@ -0,0 +1,7 @@
+/*
+ * Arch specific extensions to struct device
+ *
+ * This file is released under the GPLv2
+ */
+#include <asm-generic/device.h>
+
diff --git a/include/asm-sparc64/checksum.h b/include/asm-sparc64/checksum.h
index dc8bed246fc9..70a006da7634 100644
--- a/include/asm-sparc64/checksum.h
+++ b/include/asm-sparc64/checksum.h
@@ -30,7 +30,7 @@
*
* it's best to have buff aligned on a 32-bit boundary
*/
-extern unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
+extern __wsum csum_partial(const void * buff, int len, __wsum sum);
/* the same as csum_partial, but copies from user space while it
* checksums
@@ -38,52 +38,50 @@ extern unsigned int csum_partial(const unsigned char * buff, int len, unsigned i
* here even more important to align src and dst on a 32-bit (or even
* better 64-bit) boundary
*/
-extern unsigned int csum_partial_copy_nocheck(const unsigned char *src,
- unsigned char *dst,
- int len, unsigned int sum);
-
-extern long __csum_partial_copy_from_user(const unsigned char __user *src,
- unsigned char *dst, int len,
- unsigned int sum);
-
-static inline unsigned int
-csum_partial_copy_from_user(const unsigned char __user *src,
- unsigned char *dst, int len,
- unsigned int sum, int *err)
+extern __wsum csum_partial_copy_nocheck(const void *src, void *dst,
+ int len, __wsum sum);
+
+extern long __csum_partial_copy_from_user(const void __user *src,
+ void *dst, int len,
+ __wsum sum);
+
+static inline __wsum
+csum_partial_copy_from_user(const void __user *src,
+ void *dst, int len,
+ __wsum sum, int *err)
{
long ret = __csum_partial_copy_from_user(src, dst, len, sum);
if (ret < 0)
*err = -EFAULT;
- return (unsigned int) ret;
+ return (__force __wsum) ret;
}
/*
* Copy and checksum to user
*/
#define HAVE_CSUM_COPY_USER
-extern long __csum_partial_copy_to_user(const unsigned char *src,
- unsigned char __user *dst, int len,
- unsigned int sum);
-
-static inline unsigned int
-csum_and_copy_to_user(const unsigned char *src,
- unsigned char __user *dst, int len,
- unsigned int sum, int *err)
+extern long __csum_partial_copy_to_user(const void *src,
+ void __user *dst, int len,
+ __wsum sum);
+
+static inline __wsum
+csum_and_copy_to_user(const void *src,
+ void __user *dst, int len,
+ __wsum sum, int *err)
{
long ret = __csum_partial_copy_to_user(src, dst, len, sum);
if (ret < 0)
*err = -EFAULT;
- return (unsigned int) ret;
+ return (__force __wsum) ret;
}
/* ihl is always 5 or greater, almost always is 5, and iph is word aligned
* the majority of the time.
*/
-extern unsigned short ip_fast_csum(__const__ unsigned char *iph,
- unsigned int ihl);
+extern __sum16 ip_fast_csum(const void *iph, unsigned int ihl);
/* Fold a partial checksum without adding pseudo headers. */
-static inline unsigned short csum_fold(unsigned int sum)
+static inline __sum16 csum_fold(__wsum sum)
{
unsigned int tmp;
@@ -93,16 +91,15 @@ static inline unsigned short csum_fold(unsigned int sum)
" addc %1, %%g0, %1\n"
" xnor %%g0, %1, %0\n"
: "=&r" (sum), "=r" (tmp)
- : "0" (sum), "1" (sum<<16)
+ : "0" (sum), "1" ((__force u32)sum<<16)
: "cc");
- return (sum & 0xffff);
+ return (__force __sum16)sum;
}
-static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
- unsigned long daddr,
+static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
unsigned int len,
unsigned short proto,
- unsigned int sum)
+ __wsum sum)
{
__asm__ __volatile__(
" addcc %1, %0, %0\n"
@@ -110,7 +107,7 @@ static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
" addccc %3, %0, %0\n"
" addc %0, %%g0, %0\n"
: "=r" (sum), "=r" (saddr)
- : "r" (daddr), "r" ((proto<<16)+len), "0" (sum), "1" (saddr)
+ : "r" (daddr), "r" (proto + len), "0" (sum), "1" (saddr)
: "cc");
return sum;
}
@@ -119,22 +116,20 @@ static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
* computes the checksum of the TCP/UDP pseudo-header
* returns a 16-bit checksum, already complemented
*/
-static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
- unsigned long daddr,
+static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
unsigned short len,
unsigned short proto,
- unsigned int sum)
+ __wsum sum)
{
return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
}
#define _HAVE_ARCH_IPV6_CSUM
-static inline unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
- struct in6_addr *daddr,
- __u32 len,
- unsigned short proto,
- unsigned int sum)
+static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+ const struct in6_addr *daddr,
+ __u32 len, unsigned short proto,
+ __wsum sum)
{
__asm__ __volatile__ (
" addcc %3, %4, %%g7\n"
@@ -165,7 +160,7 @@ static inline unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
}
/* this routine is used for miscellaneous IP-like checksums, mainly in icmp.c */
-static inline unsigned short ip_compute_csum(unsigned char * buff, int len)
+static inline __sum16 ip_compute_csum(const void *buff, int len)
{
return csum_fold(csum_partial(buff, len, 0));
}
diff --git a/include/asm-sparc64/device.h b/include/asm-sparc64/device.h
new file mode 100644
index 000000000000..d8f9872b0e2d
--- /dev/null
+++ b/include/asm-sparc64/device.h
@@ -0,0 +1,7 @@
+/*
+ * Arch specific extensions to struct device
+ *
+ * This file is released under the GPLv2
+ */
+#include <asm-generic/device.h>
+
diff --git a/include/asm-sparc64/pci.h b/include/asm-sparc64/pci.h
index e1ea67bc32f2..ca6560288ae8 100644
--- a/include/asm-sparc64/pci.h
+++ b/include/asm-sparc64/pci.h
@@ -18,6 +18,8 @@
#define PCI_IRQ_NONE 0xffffffff
+#define PCI_CACHE_LINE_BYTES 64
+
static inline void pcibios_set_master(struct pci_dev *dev)
{
/* No special bus mastering setup handling */
@@ -291,10 +293,6 @@ extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state,
int write_combine);
-/* Platform specific MWI support. */
-#define HAVE_ARCH_PCI_MWI
-extern int pcibios_prep_mwi(struct pci_dev *dev);
-
extern void
pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
struct resource *res);
diff --git a/include/asm-um/device.h b/include/asm-um/device.h
new file mode 100644
index 000000000000..d8f9872b0e2d
--- /dev/null
+++ b/include/asm-um/device.h
@@ -0,0 +1,7 @@
+/*
+ * Arch specific extensions to struct device
+ *
+ * This file is released under the GPLv2
+ */
+#include <asm-generic/device.h>
+
diff --git a/include/asm-v850/checksum.h b/include/asm-v850/checksum.h
index 4df5e71098f9..d1dddd938262 100644
--- a/include/asm-v850/checksum.h
+++ b/include/asm-v850/checksum.h
@@ -26,8 +26,7 @@
*
* it's best to have buff aligned on a 32-bit boundary
*/
-extern unsigned int csum_partial (const unsigned char * buff, int len,
- unsigned int sum);
+extern __wsum csum_partial(const void *buff, int len, __wsum sum);
/*
* the same as csum_partial, but copies from src while it
@@ -36,8 +35,8 @@ extern unsigned int csum_partial (const unsigned char * buff, int len,
* here even more important to align src and dst on a 32-bit (or even
* better 64-bit) boundary
*/
-extern unsigned csum_partial_copy (const unsigned char *src,
- unsigned char *dst, int len, unsigned sum);
+extern __wsum csum_partial_copy_nocheck(const void *src,
+ void *dst, int len, __wsum sum);
/*
@@ -46,20 +45,17 @@ extern unsigned csum_partial_copy (const unsigned char *src,
* here even more important to align src and dst on a 32-bit (or even
* better 64-bit) boundary
*/
-extern unsigned csum_partial_copy_from_user (const unsigned char *src,
- unsigned char *dst,
- int len, unsigned sum,
+extern __wsum csum_partial_copy_from_user (const void *src,
+ void *dst,
+ int len, __wsum sum,
int *csum_err);
-#define csum_partial_copy_nocheck(src, dst, len, sum) \
- csum_partial_copy ((src), (dst), (len), (sum))
-
-unsigned short ip_fast_csum (unsigned char *iph, unsigned int ihl);
+__sum16 ip_fast_csum(const void *iph, unsigned int ihl);
/*
* Fold a partial checksum
*/
-static inline unsigned int csum_fold (unsigned long sum)
+static inline __sum16 csum_fold (__wsum sum)
{
unsigned int result;
/*
@@ -68,7 +64,7 @@ static inline unsigned int csum_fold (unsigned long sum)
add %1, %0 H L H+L+C H+L
*/
asm ("hsw %1, %0; add %1, %0" : "=&r" (result) : "r" (sum));
- return (~result) >> 16;
+ return (__force __sum16)(~result >> 16);
}
@@ -76,10 +72,10 @@ static inline unsigned int csum_fold (unsigned long sum)
* computes the checksum of the TCP/UDP pseudo-header
* returns a 16-bit checksum, already complemented
*/
-static inline unsigned int
-csum_tcpudp_nofold (unsigned long saddr, unsigned long daddr,
+static inline __wsum
+csum_tcpudp_nofold (__be32 saddr, __be32 daddr,
unsigned short len,
- unsigned short proto, unsigned int sum)
+ unsigned short proto, __wsum sum)
{
int __carry;
__asm__ ("add %2, %0;"
@@ -93,15 +89,15 @@ csum_tcpudp_nofold (unsigned long saddr, unsigned long daddr,
"add %1, %0"
: "=&r" (sum), "=&r" (__carry)
: "r" (daddr), "r" (saddr),
- "r" (ntohs (len) + (proto << 8)),
+ "r" ((len + proto) << 8),
"0" (sum));
return sum;
}
-static inline unsigned short int
-csum_tcpudp_magic (unsigned long saddr, unsigned long daddr,
+static inline __sum16
+csum_tcpudp_magic (__be32 saddr, __be32 daddr,
unsigned short len,
- unsigned short proto, unsigned int sum)
+ unsigned short proto, __wsum sum)
{
return csum_fold (csum_tcpudp_nofold (saddr, daddr, len, proto, sum));
}
@@ -110,7 +106,7 @@ csum_tcpudp_magic (unsigned long saddr, unsigned long daddr,
* this routine is used for miscellaneous IP-like checksums, mainly
* in icmp.c
*/
-extern unsigned short ip_compute_csum (const unsigned char * buff, int len);
+extern __sum16 ip_compute_csum(const void *buff, int len);
#endif /* __V850_CHECKSUM_H__ */
diff --git a/include/asm-v850/device.h b/include/asm-v850/device.h
new file mode 100644
index 000000000000..d8f9872b0e2d
--- /dev/null
+++ b/include/asm-v850/device.h
@@ -0,0 +1,7 @@
+/*
+ * Arch specific extensions to struct device
+ *
+ * This file is released under the GPLv2
+ */
+#include <asm-generic/device.h>
+
diff --git a/include/asm-x86_64/checksum.h b/include/asm-x86_64/checksum.h
index 989469e8e0b7..419fe88a0342 100644
--- a/include/asm-x86_64/checksum.h
+++ b/include/asm-x86_64/checksum.h
@@ -19,15 +19,16 @@
* the last step before putting a checksum into a packet.
* Make sure not to mix with 64bit checksums.
*/
-static inline unsigned int csum_fold(unsigned int sum)
+static inline __sum16 csum_fold(__wsum sum)
{
__asm__(
" addl %1,%0\n"
" adcl $0xffff,%0"
: "=r" (sum)
- : "r" (sum << 16), "0" (sum & 0xffff0000)
+ : "r" ((__force u32)sum << 16),
+ "0" ((__force u32)sum & 0xffff0000)
);
- return (~sum) >> 16;
+ return (__force __sum16)(~(__force u32)sum >> 16);
}
/*
@@ -43,7 +44,7 @@ static inline unsigned int csum_fold(unsigned int sum)
* iph: ipv4 header
* ihl: length of header / 4
*/
-static inline unsigned short ip_fast_csum(unsigned char *iph, unsigned int ihl)
+static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
{
unsigned int sum;
@@ -70,7 +71,7 @@ static inline unsigned short ip_fast_csum(unsigned char *iph, unsigned int ihl)
: "=r" (sum), "=r" (iph), "=r" (ihl)
: "1" (iph), "2" (ihl)
: "memory");
- return(sum);
+ return (__force __sum16)sum;
}
/**
@@ -84,16 +85,17 @@ static inline unsigned short ip_fast_csum(unsigned char *iph, unsigned int ihl)
* Returns the pseudo header checksum the input data. Result is
* 32bit unfolded.
*/
-static inline unsigned long
-csum_tcpudp_nofold(unsigned saddr, unsigned daddr, unsigned short len,
- unsigned short proto, unsigned int sum)
+static inline __wsum
+csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
+ unsigned short proto, __wsum sum)
{
asm(" addl %1, %0\n"
" adcl %2, %0\n"
" adcl %3, %0\n"
" adcl $0, %0\n"
: "=r" (sum)
- : "g" (daddr), "g" (saddr), "g" ((ntohs(len)<<16)+proto*256), "0" (sum));
+ : "g" (daddr), "g" (saddr),
+ "g" ((len + proto)<<8), "0" (sum));
return sum;
}
@@ -109,9 +111,9 @@ csum_tcpudp_nofold(unsigned saddr, unsigned daddr, unsigned short len,
* Returns the 16bit pseudo header checksum the input data already
* complemented and ready to be filled in.
*/
-static inline unsigned short int
-csum_tcpudp_magic(unsigned long saddr, unsigned long daddr,
- unsigned short len, unsigned short proto, unsigned int sum)
+static inline __sum16
+csum_tcpudp_magic(__be32 saddr, __be32 daddr,
+ unsigned short len, unsigned short proto, __wsum sum)
{
return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
}
@@ -126,25 +128,25 @@ csum_tcpudp_magic(unsigned long saddr, unsigned long daddr,
* Before filling it in it needs to be csum_fold()'ed.
* buff should be aligned to a 64bit boundary if possible.
*/
-extern unsigned int csum_partial(const unsigned char *buff, unsigned len, unsigned int sum);
+extern __wsum csum_partial(const void *buff, int len, __wsum sum);
#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER 1
#define HAVE_CSUM_COPY_USER 1
/* Do not call this directly. Use the wrappers below */
-extern unsigned long csum_partial_copy_generic(const unsigned char *src, const unsigned char *dst,
- unsigned len,
- unsigned sum,
+extern __wsum csum_partial_copy_generic(const void *src, const void *dst,
+ int len,
+ __wsum sum,
int *src_err_ptr, int *dst_err_ptr);
-extern unsigned int csum_partial_copy_from_user(const unsigned char __user *src, unsigned char *dst,
- int len, unsigned int isum, int *errp);
-extern unsigned int csum_partial_copy_to_user(const unsigned char *src, unsigned char __user *dst,
- int len, unsigned int isum, int *errp);
-extern unsigned int csum_partial_copy_nocheck(const unsigned char *src, unsigned char *dst, int len,
- unsigned int sum);
+extern __wsum csum_partial_copy_from_user(const void __user *src, void *dst,
+ int len, __wsum isum, int *errp);
+extern __wsum csum_partial_copy_to_user(const void *src, void __user *dst,
+ int len, __wsum isum, int *errp);
+extern __wsum csum_partial_copy_nocheck(const void *src, void *dst, int len,
+ __wsum sum);
/* Old names. To be removed. */
#define csum_and_copy_to_user csum_partial_copy_to_user
@@ -158,7 +160,7 @@ extern unsigned int csum_partial_copy_nocheck(const unsigned char *src, unsigned
* Returns the 16bit folded/inverted checksum of the passed buffer.
* Ready to fill in.
*/
-extern unsigned short ip_compute_csum(unsigned char * buff, int len);
+extern __sum16 ip_compute_csum(const void *buff, int len);
/**
* csum_ipv6_magic - Compute checksum of an IPv6 pseudo header.
@@ -176,9 +178,9 @@ extern unsigned short ip_compute_csum(unsigned char * buff, int len);
struct in6_addr;
#define _HAVE_ARCH_IPV6_CSUM 1
-extern unsigned short
-csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr,
- __u32 len, unsigned short proto, unsigned int sum);
+extern __sum16
+csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr,
+ __u32 len, unsigned short proto, __wsum sum);
static inline unsigned add32_with_carry(unsigned a, unsigned b)
{
diff --git a/include/asm-x86_64/device.h b/include/asm-x86_64/device.h
new file mode 100644
index 000000000000..3afa03f33a36
--- /dev/null
+++ b/include/asm-x86_64/device.h
@@ -0,0 +1,15 @@
+/*
+ * Arch specific extensions to struct device
+ *
+ * This file is released under the GPLv2
+ */
+#ifndef _ASM_X86_64_DEVICE_H
+#define _ASM_X86_64_DEVICE_H
+
+struct dev_archdata {
+#ifdef CONFIG_ACPI
+ void *acpi_handle;
+#endif
+};
+
+#endif /* _ASM_X86_64_DEVICE_H */
diff --git a/include/asm-xtensa/checksum.h b/include/asm-xtensa/checksum.h
index 03114f8d1e18..5435aff9a4b7 100644
--- a/include/asm-xtensa/checksum.h
+++ b/include/asm-xtensa/checksum.h
@@ -26,7 +26,7 @@
*
* it's best to have buff aligned on a 32-bit boundary
*/
-asmlinkage unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
+asmlinkage __wsum csum_partial(const void *buff, int len, __wsum sum);
/*
* the same as csum_partial, but copies from src while it
@@ -36,7 +36,7 @@ asmlinkage unsigned int csum_partial(const unsigned char * buff, int len, unsign
* better 64-bit) boundary
*/
-asmlinkage unsigned int csum_partial_copy_generic( const char *src, char *dst, int len, int sum,
+asmlinkage __wsum csum_partial_copy_generic(const void *src, void *dst, int len, __wsum sum,
int *src_err_ptr, int *dst_err_ptr);
/*
@@ -46,34 +46,25 @@ asmlinkage unsigned int csum_partial_copy_generic( const char *src, char *dst, i
* If you use these functions directly please don't forget the access_ok().
*/
static inline
-unsigned int csum_partial_copy_nocheck ( const char *src, char *dst,
- int len, int sum)
+__wsum csum_partial_copy_nocheck(const void *src, void *dst,
+ int len, __wsum sum)
{
- return csum_partial_copy_generic ( src, dst, len, sum, NULL, NULL);
+ return csum_partial_copy_generic(src, dst, len, sum, NULL, NULL);
}
static inline
-unsigned int csum_partial_copy_from_user ( const char *src, char *dst,
- int len, int sum, int *err_ptr)
+__wsum csum_partial_copy_from_user(const void __user *src, void *dst,
+ int len, __wsum sum, int *err_ptr)
{
- return csum_partial_copy_generic ( src, dst, len, sum, err_ptr, NULL);
+ return csum_partial_copy_generic((__force const void *)src, dst,
+ len, sum, err_ptr, NULL);
}
/*
- * These are the old (and unsafe) way of doing checksums, a warning message will be
- * printed if they are used and an exeption occurs.
- *
- * these functions should go away after some time.
- */
-
-#define csum_partial_copy_fromuser csum_partial_copy
-unsigned int csum_partial_copy( const char *src, char *dst, int len, int sum);
-
-/*
* Fold a partial checksum
*/
-static __inline__ unsigned int csum_fold(unsigned int sum)
+static __inline__ __sum16 csum_fold(__wsum sum)
{
unsigned int __dummy;
__asm__("extui %1, %0, 16, 16\n\t"
@@ -87,14 +78,14 @@ static __inline__ unsigned int csum_fold(unsigned int sum)
"extui %0, %0, 0, 16\n\t"
: "=r" (sum), "=&r" (__dummy)
: "0" (sum));
- return sum;
+ return (__force __sum16)sum;
}
/*
* This is a version of ip_compute_csum() optimized for IP headers,
* which always checksum on 4 octet boundaries.
*/
-static __inline__ unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl)
+static __inline__ __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
{
unsigned int sum, tmp, endaddr;
@@ -127,17 +118,16 @@ static __inline__ unsigned short ip_fast_csum(unsigned char * iph, unsigned int
return csum_fold(sum);
}
-static __inline__ unsigned long csum_tcpudp_nofold(unsigned long saddr,
- unsigned long daddr,
+static __inline__ __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
unsigned short len,
unsigned short proto,
- unsigned int sum)
+ __wsum sum)
{
#ifdef __XTENSA_EL__
- unsigned long len_proto = (ntohs(len)<<16)+proto*256;
+ unsigned long len_proto = (len + proto) << 8;
#elif defined(__XTENSA_EB__)
- unsigned long len_proto = (proto<<16)+len;
+ unsigned long len_proto = len + proto;
#else
# error processor byte order undefined!
#endif
@@ -162,11 +152,10 @@ static __inline__ unsigned long csum_tcpudp_nofold(unsigned long saddr,
* computes the checksum of the TCP/UDP pseudo-header
* returns a 16-bit checksum, already complemented
*/
-static __inline__ unsigned short int csum_tcpudp_magic(unsigned long saddr,
- unsigned long daddr,
+static __inline__ __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
unsigned short len,
unsigned short proto,
- unsigned int sum)
+ __wsum sum)
{
return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
}
@@ -176,17 +165,16 @@ static __inline__ unsigned short int csum_tcpudp_magic(unsigned long saddr,
* in icmp.c
*/
-static __inline__ unsigned short ip_compute_csum(unsigned char * buff, int len)
+static __inline__ __sum16 ip_compute_csum(const void *buff, int len)
{
return csum_fold (csum_partial(buff, len, 0));
}
#define _HAVE_ARCH_IPV6_CSUM
-static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
- struct in6_addr *daddr,
- __u32 len,
- unsigned short proto,
- unsigned int sum)
+static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+ const struct in6_addr *daddr,
+ __u32 len, unsigned short proto,
+ __wsum sum)
{
unsigned int __dummy;
__asm__("l32i %1, %2, 0\n\t"
@@ -248,8 +236,8 @@ static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
* Copy and checksum to user
*/
#define HAVE_CSUM_COPY_USER
-static __inline__ unsigned int csum_and_copy_to_user (const char *src, char *dst,
- int len, int sum, int *err_ptr)
+static __inline__ __wsum csum_and_copy_to_user(const void *src, void __user *dst,
+ int len, __wsum sum, int *err_ptr)
{
if (access_ok(VERIFY_WRITE, dst, len))
return csum_partial_copy_generic(src, dst, len, sum, NULL, err_ptr);
@@ -257,6 +245,6 @@ static __inline__ unsigned int csum_and_copy_to_user (const char *src, char *dst
if (len)
*err_ptr = -EFAULT;
- return -1; /* invalid checksum */
+ return (__force __wsum)-1; /* invalid checksum */
}
#endif
diff --git a/include/asm-xtensa/device.h b/include/asm-xtensa/device.h
new file mode 100644
index 000000000000..d8f9872b0e2d
--- /dev/null
+++ b/include/asm-xtensa/device.h
@@ -0,0 +1,7 @@
+/*
+ * Arch specific extensions to struct device
+ *
+ * This file is released under the GPLv2
+ */
+#include <asm-generic/device.h>
+
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index a1155a2beb32..ff433126361f 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -60,8 +60,6 @@ header-y += fadvise.h
header-y += fd.h
header-y += fdreg.h
header-y += fib_rules.h
-header-y += ftape-header-segment.h
-header-y += ftape-vendors.h
header-y += fuse.h
header-y += futex.h
header-y += genetlink.h
@@ -193,7 +191,6 @@ unifdef-y += cuda.h
unifdef-y += cyclades.h
unifdef-y += dccp.h
unifdef-y += dirent.h
-unifdef-y += divert.h
unifdef-y += dlm.h
unifdef-y += elfcore.h
unifdef-y += errno.h
@@ -207,7 +204,6 @@ unifdef-y += fcntl.h
unifdef-y += filter.h
unifdef-y += flat.h
unifdef-y += fs.h
-unifdef-y += ftape.h
unifdef-y += gameport.h
unifdef-y += generic_serial.h
unifdef-y += genhd.h
@@ -342,6 +338,5 @@ unifdef-y += wait.h
unifdef-y += wanrouter.h
unifdef-y += watchdog.h
unifdef-y += xfrm.h
-unifdef-y += zftape.h
objhdr-y += version.h
diff --git a/include/linux/atmarp.h b/include/linux/atmarp.h
index 24f82338f59a..ee108f9e9cb7 100644
--- a/include/linux/atmarp.h
+++ b/include/linux/atmarp.h
@@ -37,7 +37,7 @@ enum atmarp_ctrl_type {
struct atmarp_ctrl {
enum atmarp_ctrl_type type; /* message type */
int itf_num;/* interface number (if present) */
- uint32_t ip; /* IP address (act_need only) */
+ __be32 ip; /* IP address (act_need only) */
};
#endif
diff --git a/include/linux/atmbr2684.h b/include/linux/atmbr2684.h
index 7981b733f1ef..969fb6c9e1cc 100644
--- a/include/linux/atmbr2684.h
+++ b/include/linux/atmbr2684.h
@@ -86,8 +86,8 @@ struct atm_backend_br2684 {
* efficient per-if in/out filters, this support will be removed
*/
struct br2684_filter {
- __u32 prefix; /* network byte order */
- __u32 netmask; /* 0 = disable filter */
+ __be32 prefix; /* network byte order */
+ __be32 netmask; /* 0 = disable filter */
};
struct br2684_filter_set {
diff --git a/include/linux/atmmpc.h b/include/linux/atmmpc.h
index 5fbfa68136d3..ea1650425a12 100644
--- a/include/linux/atmmpc.h
+++ b/include/linux/atmmpc.h
@@ -13,7 +13,7 @@
struct atmmpc_ioc {
int dev_num;
- uint32_t ipaddr; /* the IP address of the shortcut */
+ __be32 ipaddr; /* the IP address of the shortcut */
int type; /* ingress or egress */
};
@@ -21,8 +21,8 @@ typedef struct in_ctrl_info {
uint8_t Last_NHRP_CIE_code;
uint8_t Last_Q2931_cause_value;
uint8_t eg_MPC_ATM_addr[ATM_ESA_LEN];
- uint32_t tag;
- uint32_t in_dst_ip; /* IP address this ingress MPC sends packets to */
+ __be32 tag;
+ __be32 in_dst_ip; /* IP address this ingress MPC sends packets to */
uint16_t holding_time;
uint32_t request_id;
} in_ctrl_info;
@@ -30,10 +30,10 @@ typedef struct in_ctrl_info {
typedef struct eg_ctrl_info {
uint8_t DLL_header[256];
uint8_t DH_length;
- uint32_t cache_id;
- uint32_t tag;
- uint32_t mps_ip;
- uint32_t eg_dst_ip; /* IP address to which ingress MPC sends packets */
+ __be32 cache_id;
+ __be32 tag;
+ __be32 mps_ip;
+ __be32 eg_dst_ip; /* IP address to which ingress MPC sends packets */
uint8_t in_MPC_data_ATM_addr[ATM_ESA_LEN];
uint16_t holding_time;
} eg_ctrl_info;
@@ -49,7 +49,7 @@ struct mpc_parameters {
struct k_message {
uint16_t type;
- uint32_t ip_mask;
+ __be32 ip_mask;
uint8_t MPS_ctrl[ATM_ESA_LEN];
union {
in_ctrl_info in_info;
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 7bfcde2d5578..e1c7286165ff 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -678,10 +678,11 @@ extern void __blk_stop_queue(request_queue_t *q);
extern void blk_run_queue(request_queue_t *);
extern void blk_start_queueing(request_queue_t *);
extern void blk_queue_activity_fn(request_queue_t *, activity_fn *, void *);
-extern int blk_rq_map_user(request_queue_t *, struct request *, void __user *, unsigned int);
-extern int blk_rq_unmap_user(struct bio *, unsigned int);
+extern int blk_rq_map_user(request_queue_t *, struct request *, void __user *, unsigned long);
+extern int blk_rq_unmap_user(struct request *);
extern int blk_rq_map_kern(request_queue_t *, struct request *, void *, unsigned int, gfp_t);
-extern int blk_rq_map_user_iov(request_queue_t *, struct request *, struct sg_iovec *, int);
+extern int blk_rq_map_user_iov(request_queue_t *, struct request *,
+ struct sg_iovec *, int, unsigned int);
extern int blk_execute_rq(request_queue_t *, struct gendisk *,
struct request *, int);
extern void blk_execute_rq_nowait(request_queue_t *, struct gendisk *,
diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h
index b99a714fcac6..3680ff9a30ed 100644
--- a/include/linux/blktrace_api.h
+++ b/include/linux/blktrace_api.h
@@ -50,6 +50,15 @@ enum blktrace_act {
};
/*
+ * Notify events.
+ */
+enum blktrace_notify {
+ __BLK_TN_PROCESS = 0, /* establish pid/name mapping */
+ __BLK_TN_TIMESTAMP, /* include system clock */
+};
+
+
+/*
* Trace actions in full. Additionally, read or write is masked
*/
#define BLK_TA_QUEUE (__BLK_TA_QUEUE | BLK_TC_ACT(BLK_TC_QUEUE))
@@ -68,6 +77,9 @@ enum blktrace_act {
#define BLK_TA_BOUNCE (__BLK_TA_BOUNCE)
#define BLK_TA_REMAP (__BLK_TA_REMAP | BLK_TC_ACT(BLK_TC_QUEUE))
+#define BLK_TN_PROCESS (__BLK_TN_PROCESS | BLK_TC_ACT(BLK_TC_NOTIFY))
+#define BLK_TN_TIMESTAMP (__BLK_TN_TIMESTAMP | BLK_TC_ACT(BLK_TC_NOTIFY))
+
#define BLK_IO_TRACE_MAGIC 0x65617400
#define BLK_IO_TRACE_VERSION 0x07
diff --git a/include/linux/dccp.h b/include/linux/dccp.h
index 53553c99cad6..ed6cc8962d87 100644
--- a/include/linux/dccp.h
+++ b/include/linux/dccp.h
@@ -30,7 +30,7 @@ struct dccp_hdr {
#else
#error "Adjust your <asm/byteorder.h> defines"
#endif
- __u16 dccph_checksum;
+ __sum16 dccph_checksum;
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 dccph_x:1,
dccph_type:4,
@@ -175,17 +175,21 @@ enum {
DCCPC_CCID3 = 3,
};
-/* DCCP features */
-enum {
- DCCPF_RESERVED = 0,
- DCCPF_CCID = 1,
- DCCPF_SEQUENCE_WINDOW = 3,
- DCCPF_ACK_RATIO = 5,
- DCCPF_SEND_ACK_VECTOR = 6,
- DCCPF_SEND_NDP_COUNT = 7,
- /* 10-127 reserved */
- DCCPF_MIN_CCID_SPECIFIC = 128,
- DCCPF_MAX_CCID_SPECIFIC = 255,
+/* DCCP features (RFC 4340 section 6.4) */
+ enum {
+ DCCPF_RESERVED = 0,
+ DCCPF_CCID = 1,
+ DCCPF_SHORT_SEQNOS = 2, /* XXX: not yet implemented */
+ DCCPF_SEQUENCE_WINDOW = 3,
+ DCCPF_ECN_INCAPABLE = 4, /* XXX: not yet implemented */
+ DCCPF_ACK_RATIO = 5,
+ DCCPF_SEND_ACK_VECTOR = 6,
+ DCCPF_SEND_NDP_COUNT = 7,
+ DCCPF_MIN_CSUM_COVER = 8,
+ DCCPF_DATA_CHECKSUM = 9, /* XXX: not yet implemented */
+ /* 10-127 reserved */
+ DCCPF_MIN_CCID_SPECIFIC = 128,
+ DCCPF_MAX_CCID_SPECIFIC = 255,
};
/* this structure is argument to DCCP_SOCKOPT_CHANGE_X */
@@ -196,13 +200,16 @@ struct dccp_so_feat {
};
/* DCCP socket options */
-#define DCCP_SOCKOPT_PACKET_SIZE 1
+#define DCCP_SOCKOPT_PACKET_SIZE 1 /* XXX deprecated, without effect */
#define DCCP_SOCKOPT_SERVICE 2
#define DCCP_SOCKOPT_CHANGE_L 3
#define DCCP_SOCKOPT_CHANGE_R 4
+#define DCCP_SOCKOPT_SEND_CSCOV 10
+#define DCCP_SOCKOPT_RECV_CSCOV 11
#define DCCP_SOCKOPT_CCID_RX_INFO 128
#define DCCP_SOCKOPT_CCID_TX_INFO 192
+/* maximum number of services provided on the same listening port */
#define DCCP_SERVICE_LIST_MAX_LEN 32
#ifdef __KERNEL__
@@ -256,6 +263,13 @@ static inline struct dccp_hdr *dccp_hdr(const struct sk_buff *skb)
return (struct dccp_hdr *)skb->h.raw;
}
+static inline struct dccp_hdr *dccp_zeroed_hdr(struct sk_buff *skb, int headlen)
+{
+ skb->h.raw = skb_push(skb, headlen);
+ memset(skb->h.raw, 0, headlen);
+ return dccp_hdr(skb);
+}
+
static inline struct dccp_hdr_ext *dccp_hdrx(const struct sk_buff *skb)
{
return (struct dccp_hdr_ext *)(skb->h.raw + sizeof(struct dccp_hdr));
@@ -342,6 +356,9 @@ static inline unsigned int dccp_hdr_len(const struct sk_buff *skb)
* @dccpms_ccid - Congestion Control Id (CCID) (section 10)
* @dccpms_send_ack_vector - Send Ack Vector Feature (section 11.5)
* @dccpms_send_ndp_count - Send NDP Count Feature (7.7.2)
+ * @dccpms_ack_ratio - Ack Ratio Feature (section 11.3)
+ * @dccpms_pending - List of features being negotiated
+ * @dccpms_conf -
*/
struct dccp_minisock {
__u64 dccpms_sequence_window;
@@ -439,12 +456,25 @@ struct dccp_ackvec;
* @dccps_gss - greatest sequence number sent
* @dccps_gsr - greatest valid sequence number received
* @dccps_gar - greatest valid ack number received on a non-Sync; initialized to %dccps_iss
+ * @dccps_service - first (passive sock) or unique (active sock) service code
+ * @dccps_service_list - second .. last service code on passive socket
* @dccps_timestamp_time - time of latest TIMESTAMP option
* @dccps_timestamp_echo - latest timestamp received on a TIMESTAMP option
- * @dccps_packet_size - Set thru setsockopt
- * @dccps_role - Role of this sock, one of %dccp_role
+ * @dccps_l_ack_ratio -
+ * @dccps_r_ack_ratio -
+ * @dccps_pcslen - sender partial checksum coverage (via sockopt)
+ * @dccps_pcrlen - receiver partial checksum coverage (via sockopt)
* @dccps_ndp_count - number of Non Data Packets since last data packet
+ * @dccps_mss_cache -
+ * @dccps_minisock -
* @dccps_hc_rx_ackvec - rx half connection ack vector
+ * @dccps_hc_rx_ccid -
+ * @dccps_hc_tx_ccid -
+ * @dccps_options_received -
+ * @dccps_epoch -
+ * @dccps_role - Role of this sock, one of %dccp_role
+ * @dccps_hc_rx_insert_options -
+ * @dccps_hc_tx_insert_options -
* @dccps_xmit_timer - timer for when CCID is not ready to send
*/
struct dccp_sock {
@@ -464,9 +494,10 @@ struct dccp_sock {
struct dccp_service_list *dccps_service_list;
struct timeval dccps_timestamp_time;
__u32 dccps_timestamp_echo;
- __u32 dccps_packet_size;
__u16 dccps_l_ack_ratio;
__u16 dccps_r_ack_ratio;
+ __u16 dccps_pcslen;
+ __u16 dccps_pcrlen;
unsigned long dccps_ndp_count;
__u32 dccps_mss_cache;
struct dccp_minisock dccps_minisock;
diff --git a/include/linux/device.h b/include/linux/device.h
index 9d4f6a963936..583a341e016c 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -21,6 +21,7 @@
#include <linux/pm.h>
#include <asm/semaphore.h>
#include <asm/atomic.h>
+#include <asm/device.h>
#define DEVICE_NAME_SIZE 50
#define DEVICE_NAME_HALF __stringify(20) /* Less than half to accommodate slop */
@@ -42,6 +43,8 @@ struct bus_type {
struct klist klist_devices;
struct klist klist_drivers;
+ struct blocking_notifier_head bus_notifier;
+
struct bus_attribute * bus_attrs;
struct device_attribute * dev_attrs;
struct driver_attribute * drv_attrs;
@@ -75,6 +78,29 @@ int __must_check bus_for_each_drv(struct bus_type *bus,
struct device_driver *start, void *data,
int (*fn)(struct device_driver *, void *));
+/*
+ * Bus notifiers: Get notified of addition/removal of devices
+ * and binding/unbinding of drivers to devices.
+ * In the long run, it should be a replacement for the platform
+ * notify hooks.
+ */
+struct notifier_block;
+
+extern int bus_register_notifier(struct bus_type *bus,
+ struct notifier_block *nb);
+extern int bus_unregister_notifier(struct bus_type *bus,
+ struct notifier_block *nb);
+
+/* All 4 notifers below get called with the target struct device *
+ * as an argument. Note that those functions are likely to be called
+ * with the device semaphore held in the core, so be careful.
+ */
+#define BUS_NOTIFY_ADD_DEVICE 0x00000001 /* device added */
+#define BUS_NOTIFY_DEL_DEVICE 0x00000002 /* device removed */
+#define BUS_NOTIFY_BOUND_DRIVER 0x00000003 /* driver bound to device */
+#define BUS_NOTIFY_UNBIND_DRIVER 0x00000004 /* driver about to be
+ unbound */
+
/* driverfs interface for exporting bus attributes */
struct bus_attribute {
@@ -343,8 +369,6 @@ struct device {
void *driver_data; /* data private to the driver */
void *platform_data; /* Platform specific data, device
core doesn't touch it */
- void *firmware_data; /* Firmware specific data (e.g. ACPI,
- BIOS data),reserved for device core*/
struct dev_pm_info power;
u64 *dma_mask; /* dma mask (if dma'able device) */
@@ -358,6 +382,8 @@ struct device {
struct dma_coherent_mem *dma_mem; /* internal for coherent mem
override */
+ /* arch specific additions */
+ struct dev_archdata archdata;
/* class_device migration path */
struct list_head node;
@@ -395,7 +421,10 @@ extern int __must_check device_add(struct device * dev);
extern void device_del(struct device * dev);
extern int device_for_each_child(struct device *, void *,
int (*fn)(struct device *, void *));
+extern struct device *device_find_child(struct device *, void *data,
+ int (*match)(struct device *, void *));
extern int device_rename(struct device *dev, char *new_name);
+extern int device_move(struct device *dev, struct device *new_parent);
/*
* Manual binding of a device to driver. See drivers/base/bus.c
@@ -415,8 +444,6 @@ extern struct device *device_create(struct class *cls, struct device *parent,
__attribute__((format(printf,4,5)));
extern void device_destroy(struct class *cls, dev_t devt);
-extern int virtual_device_parent(struct device *dev);
-
/*
* Platform "fixup" functions - allow the platform to have their say
* about devices and actions that the general device layer doesn't
diff --git a/include/linux/divert.h b/include/linux/divert.h
deleted file mode 100644
index 8fb4e9de6843..000000000000
--- a/include/linux/divert.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Frame Diversion, Benoit Locher <Benoit.Locher@skf.com>
- *
- * Changes:
- * 06/09/2000 BL: initial version
- *
- */
-
-#ifndef _LINUX_DIVERT_H
-#define _LINUX_DIVERT_H
-
-#include <asm/types.h>
-
-#define MAX_DIVERT_PORTS 8 /* Max number of ports to divert (tcp, udp) */
-
-/* Divertable protocols */
-#define DIVERT_PROTO_NONE 0x0000
-#define DIVERT_PROTO_IP 0x0001
-#define DIVERT_PROTO_ICMP 0x0002
-#define DIVERT_PROTO_TCP 0x0004
-#define DIVERT_PROTO_UDP 0x0008
-
-/*
- * This is an Ethernet Frame Diverter option block
- */
-struct divert_blk
-{
- int divert; /* are we active */
- unsigned int protos; /* protocols */
- __u16 tcp_dst[MAX_DIVERT_PORTS]; /* specific tcp dst ports to divert */
- __u16 tcp_src[MAX_DIVERT_PORTS]; /* specific tcp src ports to divert */
- __u16 udp_dst[MAX_DIVERT_PORTS]; /* specific udp dst ports to divert */
- __u16 udp_src[MAX_DIVERT_PORTS]; /* specific udp src ports to divert */
-};
-
-/*
- * Diversion control block, for configuration with the userspace tool
- * divert
- */
-
-typedef union _divert_cf_arg
-{
- __s16 int16;
- __u16 uint16;
- __s32 int32;
- __u32 uint32;
- __s64 int64;
- __u64 uint64;
- void __user *ptr;
-} divert_cf_arg;
-
-
-struct divert_cf
-{
- int cmd; /* Command */
- divert_cf_arg arg1,
- arg2,
- arg3;
- int dev_index; /* device index (eth0=0, etc...) */
-};
-
-
-/* Diversion commands */
-#define DIVCMD_DIVERT 1 /* ENABLE/DISABLE diversion */
-#define DIVCMD_IP 2 /* ENABLE/DISABLE whold IP diversion */
-#define DIVCMD_TCP 3 /* ENABLE/DISABLE whold TCP diversion */
-#define DIVCMD_TCPDST 4 /* ADD/REMOVE TCP DST port for diversion */
-#define DIVCMD_TCPSRC 5 /* ADD/REMOVE TCP SRC port for diversion */
-#define DIVCMD_UDP 6 /* ENABLE/DISABLE whole UDP diversion */
-#define DIVCMD_UDPDST 7 /* ADD/REMOVE UDP DST port for diversion */
-#define DIVCMD_UDPSRC 8 /* ADD/REMOVE UDP SRC port for diversion */
-#define DIVCMD_ICMP 9 /* ENABLE/DISABLE whole ICMP diversion */
-#define DIVCMD_GETSTATUS 10 /* GET the status of the diverter */
-#define DIVCMD_RESET 11 /* Reset the diverter on the specified dev */
-#define DIVCMD_GETVERSION 12 /* Retrieve the diverter code version (char[32]) */
-
-/* General syntax of the commands:
- *
- * DIVCMD_xxxxxx(arg1, arg2, arg3, dev_index)
- *
- * SIOCSIFDIVERT:
- * DIVCMD_DIVERT(DIVARG1_ENABLE|DIVARG1_DISABLE, , ,ifindex)
- * DIVCMD_IP(DIVARG1_ENABLE|DIVARG1_DISABLE, , , ifindex)
- * DIVCMD_TCP(DIVARG1_ENABLE|DIVARG1_DISABLE, , , ifindex)
- * DIVCMD_TCPDST(DIVARG1_ADD|DIVARG1_REMOVE, port, , ifindex)
- * DIVCMD_TCPSRC(DIVARG1_ADD|DIVARG1_REMOVE, port, , ifindex)
- * DIVCMD_UDP(DIVARG1_ENABLE|DIVARG1_DISABLE, , , ifindex)
- * DIVCMD_UDPDST(DIVARG1_ADD|DIVARG1_REMOVE, port, , ifindex)
- * DIVCMD_UDPSRC(DIVARG1_ADD|DIVARG1_REMOVE, port, , ifindex)
- * DIVCMD_ICMP(DIVARG1_ENABLE|DIVARG1_DISABLE, , , ifindex)
- * DIVCMD_RESET(, , , ifindex)
- *
- * SIOGIFDIVERT:
- * DIVCMD_GETSTATUS(divert_blk, , , ifindex)
- * DIVCMD_GETVERSION(string[3])
- */
-
-
-/* Possible values for arg1 */
-#define DIVARG1_ENABLE 0 /* ENABLE something */
-#define DIVARG1_DISABLE 1 /* DISABLE something */
-#define DIVARG1_ADD 2 /* ADD something */
-#define DIVARG1_REMOVE 3 /* REMOVE something */
-
-
-#ifdef __KERNEL__
-
-/* diverter functions */
-#include <linux/skbuff.h>
-
-#ifdef CONFIG_NET_DIVERT
-#include <linux/netdevice.h>
-
-int alloc_divert_blk(struct net_device *);
-void free_divert_blk(struct net_device *);
-int divert_ioctl(unsigned int cmd, struct divert_cf __user *arg);
-void divert_frame(struct sk_buff *skb);
-static inline void handle_diverter(struct sk_buff *skb)
-{
- /* if diversion is supported on device, then divert */
- if (skb->dev->divert && skb->dev->divert->divert)
- divert_frame(skb);
-}
-
-#else
-# define alloc_divert_blk(dev) (0)
-# define free_divert_blk(dev) do {} while (0)
-# define divert_ioctl(cmd, arg) (-ENOPKG)
-# define handle_diverter(skb) do {} while (0)
-#endif
-#endif
-#endif /* _LINUX_DIVERT_H */
diff --git a/include/linux/elevator.h b/include/linux/elevator.h
index 2fa9f1144228..a24931d24404 100644
--- a/include/linux/elevator.h
+++ b/include/linux/elevator.h
@@ -21,11 +21,11 @@ typedef void (elevator_completed_req_fn) (request_queue_t *, struct request *);
typedef int (elevator_may_queue_fn) (request_queue_t *, int);
typedef int (elevator_set_req_fn) (request_queue_t *, struct request *, gfp_t);
-typedef void (elevator_put_req_fn) (request_queue_t *, struct request *);
+typedef void (elevator_put_req_fn) (struct request *);
typedef void (elevator_activate_req_fn) (request_queue_t *, struct request *);
typedef void (elevator_deactivate_req_fn) (request_queue_t *, struct request *);
-typedef void *(elevator_init_fn) (request_queue_t *, elevator_t *);
+typedef void *(elevator_init_fn) (request_queue_t *);
typedef void (elevator_exit_fn) (elevator_t *);
struct elevator_ops
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 3e69241e6a81..fa23e0671bb3 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -774,8 +774,8 @@ struct fb_info {
#endif
struct fb_ops *fbops;
- struct device *device;
- struct class_device *class_device; /* sysfs per device attrs */
+ struct device *device; /* This is the parent */
+ struct device *dev; /* This is this fb device */
int class_flag; /* private sysfs flags */
#ifdef CONFIG_FB_TILEBLITTING
struct fb_tile_ops *tileops; /* Tile Blitting */
@@ -910,8 +910,8 @@ static inline void __fb_pad_aligned_buffer(u8 *dst, u32 d_pitch,
/* drivers/video/fbsysfs.c */
extern struct fb_info *framebuffer_alloc(size_t size, struct device *dev);
extern void framebuffer_release(struct fb_info *info);
-extern int fb_init_class_device(struct fb_info *fb_info);
-extern void fb_cleanup_class_device(struct fb_info *head);
+extern int fb_init_device(struct fb_info *fb_info);
+extern void fb_cleanup_device(struct fb_info *head);
extern void fb_bl_default_curve(struct fb_info *fb_info, u8 off, u8 min, u8 max);
/* drivers/video/fbmon.c */
diff --git a/include/linux/fib_rules.h b/include/linux/fib_rules.h
index 4418c8d9d479..8270aac2aa5d 100644
--- a/include/linux/fib_rules.h
+++ b/include/linux/fib_rules.h
@@ -6,6 +6,7 @@
/* rule is permanent, and cannot be deleted */
#define FIB_RULE_PERMANENT 1
+#define FIB_RULE_INVERT 2
struct fib_rule_hdr
{
@@ -34,7 +35,7 @@ enum
FRA_UNUSED3,
FRA_UNUSED4,
FRA_UNUSED5,
- FRA_FWMARK, /* netfilter mark */
+ FRA_FWMARK, /* mark */
FRA_FLOW, /* flow/class id */
FRA_UNUSED6,
FRA_UNUSED7,
diff --git a/include/linux/ftape-header-segment.h b/include/linux/ftape-header-segment.h
deleted file mode 100644
index 4732218f0708..000000000000
--- a/include/linux/ftape-header-segment.h
+++ /dev/null
@@ -1,122 +0,0 @@
-#ifndef _FTAPE_HEADER_SEGMENT_H
-#define _FTAPE_HEADER_SEGMENT_H
-
-/*
- * Copyright (C) 1996-1997 Claus-Justus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/include/linux/ftape-header-segment.h,v $
- * $Revision: 1.2 $
- * $Date: 1997/10/05 19:19:28 $
- *
- * This file defines some offsets into the header segment of a
- * floppy tape cartridge. For use with the QIC-40/80/3010/3020
- * floppy-tape driver "ftape" for Linux.
- */
-
-#define FT_SIGNATURE 0 /* must be 0xaa55aa55 */
-#define FT_FMT_CODE 4
-#define FT_REV_LEVEL 5 /* only for QIC-80 since. Rev. L (== 0x0c) */
-#define FT_HSEG_1 6 /* first header segment, except for format code 6 */
-#define FT_HSEG_2 8 /* second header segment, except for format code 6 */
-#define FT_FRST_SEG 10 /* first data segment, except for format code 6 */
-#define FT_LAST_SEG 12 /* last data segment, except for format code 6 */
-#define FT_FMT_DATE 14 /* date and time of most recent format, see below */
-#define FT_WR_DATE 18 /* date and time of most recent write or format */
-#define FT_SPT 24 /* segments per track */
-#define FT_TPC 26 /* tracks per cartridge */
-#define FT_FHM 27 /* floppy drive head (maximum of it) */
-#define FT_FTM 28 /* floppy track max. */
-#define FT_FSM 29 /* floppy sector max. (128) */
-#define FT_LABEL 30 /* floppy tape label */
-#define FT_LABEL_DATE 74 /* date and time the tape label was written */
-#define FT_LABEL_SZ (FT_LABEL_DATE - FT_LABEL)
-#define FT_CMAP_START 78 /* starting segment of compression map */
-#define FT_FMT_ERROR 128 /* must be set to 0xff if remainder gets lost during
- * tape format
- */
-#define FT_SEG_CNT 130 /* number of seg. written, formatted or verified
- * through lifetime of tape (why not read?)
- */
-#define FT_INIT_DATE 138 /* date and time of initial tape format */
-#define FT_FMT_CNT 142 /* number of times tape has been formatted */
-#define FT_FSL_CNT 144 /* number of segments in failed sector log */
-#define FT_MK_CODE 146 /* id string of tape manufacturer */
-#define FT_LOT_CODE 190 /* tape manufacturer lot code */
-#define FT_6_HSEG_1 234 /* first header segment for format code 6 */
-#define FT_6_HSEG_2 238 /* second header segment for format code 6 */
-#define FT_6_FRST_SEG 242 /* first data segment for format code 6 */
-#define FT_6_LAST_SEG 246 /* last data segment for format code 6 */
-
-#define FT_FSL 256
-#define FT_HEADER_END 256 /* space beyond this point:
- * format codes 2, 3 and 5:
- * - failed sector log until byte 2047
- * - bad sector map in the reamining part of segment
- * format codes 4 and 6:
- * - bad sector map starts hear
- */
-
-
-/* value to be stored at the FT_SIGNATURE offset
- */
-#define FT_HSEG_MAGIC 0xaa55aa55
-#define FT_D2G_MAGIC 0x82288228 /* Ditto 2GB */
-
-/* data and time encoding: */
-#define FT_YEAR_SHIFT 25
-#define FT_YEAR_MASK 0xfe000000
-#define FT_YEAR_0 1970
-#define FT_YEAR_MAX 127
-#define FT_YEAR(year) ((((year)-FT_YEAR_0)<<FT_YEAR_SHIFT)&FT_YEAR_MASK)
-
-#define FT_TIME_SHIFT 0
-#define FT_TIME_MASK 0x01FFFFFF
-#define FT_TIME_MAX 0x01ea6dff /* last second of a year */
-#define FT_TIME(mo,d,h,m,s) \
- ((((s)+60*((m)+60*((h)+24*((d)+31*(mo))))) & FT_TIME_MASK))
-
-#define FT_TIME_STAMP(y,mo,d,h,m,s) (FT_YEAR(y) | FT_TIME(mo,d,h,m,s))
-
-/* values for the format code field */
-typedef enum {
- fmt_normal = 2, /* QIC-80 post Rev. B 205Ft or 307Ft tape */
- fmt_1100ft = 3, /* QIC-80 post Rev. B 1100Ft tape */
- fmt_var = 4, /* QIC-80 post Rev. B variabel length format */
- fmt_425ft = 5, /* QIC-80 post Rev. B 425Ft tape */
- fmt_big = 6 /* QIC-3010/3020 variable length tape with more
- * than 2^16 segments per tape
- */
-} ft_format_type;
-
-/* definitions for the failed sector log */
-#define FT_FSL_SIZE (2 * FT_SECTOR_SIZE - FT_HEADER_END)
-#define FT_FSL_MAX_ENTRIES (FT_FSL_SIZE/sizeof(__u32))
-
-typedef struct ft_fsl_entry {
- __u16 segment;
- __u16 date;
-} __attribute__ ((packed)) ft_fsl_entry;
-
-
-/* date encoding for the failed sector log
- * month: 1..12, day: 1..31, year: 1970..2097
- */
-#define FT_FSL_TIME_STAMP(y,m,d) \
- (((((y) - FT_YEAR_0)<<9)&0xfe00) | (((m)<<5)&0x01e0) | ((d)&0x001f))
-
-#endif /* _FTAPE_HEADER_SEGMENT_H */
diff --git a/include/linux/ftape-vendors.h b/include/linux/ftape-vendors.h
deleted file mode 100644
index ec1a81f059e5..000000000000
--- a/include/linux/ftape-vendors.h
+++ /dev/null
@@ -1,137 +0,0 @@
-#ifndef _FTAPE_VENDORS_H
-#define _FTAPE_VENDORS_H
-
-/*
- * Copyright (C) 1993-1996 Bas Laarhoven,
- * (C) 1996-1997 Claus-Justus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/include/linux/ftape-vendors.h,v $
- * $Revision: 1.6 $
- * $Date: 1997/10/09 15:38:11 $
- *
- * This file contains the supported drive types with their
- * QIC-117 spec. vendor code and drive dependent configuration
- * information.
- */
-
-typedef enum {
- unknown_wake_up = 0,
- no_wake_up,
- wake_up_colorado,
- wake_up_mountain,
- wake_up_insight,
-} wake_up_types;
-
-typedef struct {
- wake_up_types wake_up; /* see wake_up_types */
- char *name; /* Text describing the drive */
-} wakeup_method;
-
-/* Note: order of entries in WAKEUP_METHODS must be so that a variable
- * of type wake_up_types can be used as an index in the array.
- */
-#define WAKEUP_METHODS { \
- { unknown_wake_up, "Unknown" }, \
- { no_wake_up, "None" }, \
- { wake_up_colorado, "Colorado" }, \
- { wake_up_mountain, "Mountain" }, \
- { wake_up_insight, "Motor-on" }, \
-}
-
-typedef struct {
- unsigned int vendor_id; /* vendor id from drive */
- int speed; /* maximum tape transport speed (ips) */
- wake_up_types wake_up; /* see wake_up_types */
- char *name; /* Text describing the drive */
-} vendor_struct;
-
-#define UNKNOWN_VENDOR (-1)
-
-#define QIC117_VENDORS { \
-/* see _vendor_struct */ \
- { 0x00000, 82, wake_up_colorado, "Colorado DJ-10 (old)" }, \
- { 0x00047, 90, wake_up_colorado, "Colorado DJ-10/DJ-20" }, \
- { 0x011c2, 84, wake_up_colorado, "Colorado 700" }, \
- { 0x011c3, 90, wake_up_colorado, "Colorado 1400" }, \
- { 0x011c4, 84, wake_up_colorado, "Colorado DJ-10/DJ-20 (new)" }, \
- { 0x011c5, 84, wake_up_colorado, "HP Colorado T1000" }, \
- { 0x011c6, 90, wake_up_colorado, "HP Colorado T3000" }, \
- { 0x00005, 45, wake_up_mountain, "Archive 5580i" }, \
- { 0x10005, 50, wake_up_insight, "Insight 80Mb, Irwin 80SX" }, \
- { 0x00140, 74, wake_up_mountain, "Archive S.Hornet [Identity/Escom]" }, \
- { 0x00146, 72, wake_up_mountain, "Archive 31250Q [Escom]" }, \
- { 0x0014a, 100, wake_up_mountain, "Archive XL9250i [Conner/Escom]" }, \
- { 0x0014c, 98, wake_up_mountain, "Conner C250MQT" }, \
- { 0x0014e, 80, wake_up_mountain, "Conner C250MQ" }, \
- { 0x00150, 80, wake_up_mountain, "Conner TSM420R/TST800R" }, \
- { 0x00152, 80, wake_up_mountain, "Conner TSM850R" }, \
- { 0x00156, 80, wake_up_mountain, "Conner TSM850R/1700R/TST3200R" }, \
- { 0x00180, 0, wake_up_mountain, "Summit SE 150" }, \
- { 0x00181, 85, wake_up_mountain, "Summit SE 250, Mountain FS8000" }, \
- { 0x001c1, 82, no_wake_up, "Wangtek 3040F" }, \
- { 0x001c8, 64, no_wake_up, "Wangtek 3080F" }, \
- { 0x001c8, 64, wake_up_colorado, "Wangtek 3080F" }, \
- { 0x001ca, 67, no_wake_up, "Wangtek 3080F (new)" }, \
- { 0x001cc, 77, wake_up_colorado, "Wangtek 3200 / Teac 700" }, \
- { 0x001cd, 75, wake_up_colorado, "Reveal TB1400" }, \
- { 0x00380, 85, wake_up_colorado, "Exabyte Eagle-96" }, \
- { 0x00381, 85, wake_up_colorado, "Exabyte Eagle TR-3" }, \
- { 0x00382, 85, wake_up_colorado, "Exabyte Eagle TR-3" }, \
- { 0x003ce, 77, wake_up_colorado, "Teac 800" }, \
- { 0x003cf, 0, wake_up_colorado, "Teac FT3010TR" }, \
- { 0x08880, 64, no_wake_up, "Iomega 250, Ditto 800" }, \
- { 0x08880, 64, wake_up_colorado, "Iomega 250, Ditto 800" }, \
- { 0x08880, 64, wake_up_insight, "Iomega 250, Ditto 800" }, \
- { 0x08881, 80, wake_up_colorado, "Iomega 700" }, \
- { 0x08882, 80, wake_up_colorado, "Iomega 3200" }, \
- { 0x08883, 80, wake_up_colorado, "Iomega DITTO 2GB" }, \
- { 0x00021, 70, no_wake_up, "AIWA CT-803" }, \
- { 0x004c0, 80, no_wake_up, "AIWA TD-S1600" }, \
- { 0x00021, 0, wake_up_mountain, "COREtape QIC80" }, \
- { 0x00441, 0, wake_up_mountain, "ComByte DoublePlay" }, \
- { 0x00481, 127, wake_up_mountain, "PERTEC MyTape 800" }, \
- { 0x00483, 130, wake_up_mountain, "PERTEC MyTape 3200" }, \
- { UNKNOWN_VENDOR, 0, no_wake_up, "unknown" } \
-}
-
-#define QIC117_MAKE_CODES { \
- { 0, "Unassigned" }, \
- { 1, "Alloy Computer Products" }, \
- { 2, "3M" }, \
- { 3, "Tandberg Data" }, \
- { 4, "Colorado" }, \
- { 5, "Archive/Conner" }, \
- { 6, "Mountain/Summit Memory Systems" }, \
- { 7, "Wangtek/Rexon/Tecmar" }, \
- { 8, "Sony" }, \
- { 9, "Cipher Data Products" }, \
- { 10, "Irwin Magnetic Systems" }, \
- { 11, "Braemar" }, \
- { 12, "Verbatim" }, \
- { 13, "Core International" }, \
- { 14, "Exabyte" }, \
- { 15, "Teac" }, \
- { 16, "Gigatek" }, \
- { 17, "ComByte" }, \
- { 18, "PERTEC Memories" }, \
- { 19, "Aiwa" }, \
- { 71, "Colorado" }, \
- { 546, "Iomega Inc" }, \
-}
-
-#endif /* _FTAPE_VENDORS_H */
diff --git a/include/linux/ftape.h b/include/linux/ftape.h
deleted file mode 100644
index 7e7038cba86a..000000000000
--- a/include/linux/ftape.h
+++ /dev/null
@@ -1,201 +0,0 @@
-#ifndef _FTAPE_H
-#define _FTAPE_H
-
-/*
- * Copyright (C) 1994-1996 Bas Laarhoven,
- * (C) 1996-1997 Claus-Justus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/include/linux/ftape.h,v $
- * $Revision: 1.17.6.4 $
- * $Date: 1997/11/25 01:52:54 $
- *
- * This file contains global definitions, typedefs and macro's
- * for the QIC-40/80/3010/3020 floppy-tape driver for Linux.
- */
-
-#define FTAPE_VERSION "ftape v3.04d 25/11/97"
-
-#ifdef __KERNEL__
-#include <linux/interrupt.h>
-#include <linux/mm.h>
-#endif
-#include <linux/types.h>
-#include <linux/mtio.h>
-
-#define FT_SECTOR(x) (x+1) /* sector offset into real sector */
-#define FT_SECTOR_SIZE 1024
-#define FT_SECTORS_PER_SEGMENT 32
-#define FT_ECC_SECTORS 3
-#define FT_SEGMENT_SIZE ((FT_SECTORS_PER_SEGMENT - FT_ECC_SECTORS) * FT_SECTOR_SIZE)
-#define FT_BUFF_SIZE (FT_SECTORS_PER_SEGMENT * FT_SECTOR_SIZE)
-
-/*
- * bits of the minor device number that define drive selection
- * methods. Could be used one day to access multiple tape
- * drives on the same controller.
- */
-#define FTAPE_SEL_A 0
-#define FTAPE_SEL_B 1
-#define FTAPE_SEL_C 2
-#define FTAPE_SEL_D 3
-#define FTAPE_SEL_MASK 3
-#define FTAPE_SEL(unit) ((unit) & FTAPE_SEL_MASK)
-#define FTAPE_NO_REWIND 4 /* mask for minor nr */
-
-/* the following two may be reported when MTIOCGET is requested ... */
-typedef union {
- struct {
- __u8 error;
- __u8 command;
- } error;
- long space;
-} ft_drive_error;
-typedef union {
- struct {
- __u8 drive_status;
- __u8 drive_config;
- __u8 tape_status;
- } status;
- long space;
-} ft_drive_status;
-
-#ifdef __KERNEL__
-
-#define FT_RQM_DELAY 12
-#define FT_MILLISECOND 1
-#define FT_SECOND 1000
-#define FT_FOREVER -1
-#ifndef HZ
-#error "HZ undefined."
-#endif
-#define FT_USPT (1000000/HZ) /* microseconds per tick */
-
-/* This defines the number of retries that the driver will allow
- * before giving up (and letting a higher level handle the error).
- */
-#ifdef TESTING
-#define FT_SOFT_RETRIES 1 /* number of low level retries */
-#define FT_RETRIES_ON_ECC_ERROR 3 /* ecc error when correcting segment */
-#else
-#define FT_SOFT_RETRIES 6 /* number of low level retries (triple) */
-#define FT_RETRIES_ON_ECC_ERROR 3 /* ecc error when correcting segment */
-#endif
-
-#ifndef THE_FTAPE_MAINTAINER
-#define THE_FTAPE_MAINTAINER "the ftape maintainer"
-#endif
-
-/* Initialize missing configuration parameters.
- */
-#ifndef CONFIG_FT_NR_BUFFERS
-# define CONFIG_FT_NR_BUFFERS 3
-#endif
-#ifndef CONFIG_FT_FDC_THR
-# define CONFIG_FT_FDC_THR 8
-#endif
-#ifndef CONFIG_FT_FDC_MAX_RATE
-# define CONFIG_FT_FDC_MAX_RATE 2000
-#endif
-#ifndef CONFIG_FT_FDC_BASE
-# define CONFIG_FT_FDC_BASE 0
-#endif
-#ifndef CONFIG_FT_FDC_IRQ
-# define CONFIG_FT_FDC_IRQ 0
-#endif
-#ifndef CONFIG_FT_FDC_DMA
-# define CONFIG_FT_FDC_DMA 0
-#endif
-
-/* Turn some booleans into numbers.
- */
-#ifdef CONFIG_FT_PROBE_FC10
-# undef CONFIG_FT_PROBE_FC10
-# define CONFIG_FT_PROBE_FC10 1
-#else
-# define CONFIG_FT_PROBE_FC10 0
-#endif
-#ifdef CONFIG_FT_MACH2
-# undef CONFIG_FT_MACH2
-# define CONFIG_FT_MACH2 1
-#else
-# define CONFIG_FT_MACH2 0
-#endif
-
-/* Insert default settings
- */
-#if CONFIG_FT_PROBE_FC10 == 1
-# if CONFIG_FT_FDC_BASE == 0
-# undef CONFIG_FT_FDC_BASE
-# define CONFIG_FT_FDC_BASE 0x180
-# endif
-# if CONFIG_FT_FDC_IRQ == 0
-# undef CONFIG_FT_FDC_IRQ
-# define CONFIG_FT_FDC_IRQ 9
-# endif
-# if CONFIG_FT_FDC_DMA == 0
-# undef CONFIG_FT_FDC_DMA
-# define CONFIG_FT_FDC_DMA 3
-# endif
-#elif CONFIG_FT_MACH2 == 1 /* CONFIG_FT_PROBE_FC10 == 1 */
-# if CONFIG_FT_FDC_BASE == 0
-# undef CONFIG_FT_FDC_BASE
-# define CONFIG_FT_FDC_BASE 0x1E0
-# endif
-# if CONFIG_FT_FDC_IRQ == 0
-# undef CONFIG_FT_FDC_IRQ
-# define CONFIG_FT_FDC_IRQ 6
-# endif
-# if CONFIG_FT_FDC_DMA == 0
-# undef CONFIG_FT_FDC_DMA
-# define CONFIG_FT_FDC_DMA 2
-# endif
-#elif defined(CONFIG_FT_ALT_FDC) /* CONFIG_FT_MACH2 */
-# if CONFIG_FT_FDC_BASE == 0
-# undef CONFIG_FT_FDC_BASE
-# define CONFIG_FT_FDC_BASE 0x370
-# endif
-# if CONFIG_FT_FDC_IRQ == 0
-# undef CONFIG_FT_FDC_IRQ
-# define CONFIG_FT_FDC_IRQ 6
-# endif
-# if CONFIG_FT_FDC_DMA == 0
-# undef CONFIG_FT_FDC_DMA
-# define CONFIG_FT_FDC_DMA 2
-# endif
-#else /* CONFIG_FT_ALT_FDC */
-# if CONFIG_FT_FDC_BASE == 0
-# undef CONFIG_FT_FDC_BASE
-# define CONFIG_FT_FDC_BASE 0x3f0
-# endif
-# if CONFIG_FT_FDC_IRQ == 0
-# undef CONFIG_FT_FDC_IRQ
-# define CONFIG_FT_FDC_IRQ 6
-# endif
-# if CONFIG_FT_FDC_DMA == 0
-# undef CONFIG_FT_FDC_DMA
-# define CONFIG_FT_FDC_DMA 2
-# endif
-#endif /* standard FDC */
-
-/* some useful macro's
- */
-#define NR_ITEMS(x) (int)(sizeof(x)/ sizeof(*x))
-
-#endif /* __KERNEL__ */
-
-#endif
diff --git a/include/linux/icmp.h b/include/linux/icmp.h
index 878cfe4e587f..24da4fbc1a2f 100644
--- a/include/linux/icmp.h
+++ b/include/linux/icmp.h
@@ -68,7 +68,7 @@
struct icmphdr {
__u8 type;
__u8 code;
- __be16 checksum;
+ __sum16 checksum;
union {
struct {
__be16 id;
diff --git a/include/linux/icmpv6.h b/include/linux/icmpv6.h
index c771a7db9871..68d3526c3a05 100644
--- a/include/linux/icmpv6.h
+++ b/include/linux/icmpv6.h
@@ -7,17 +7,17 @@ struct icmp6hdr {
__u8 icmp6_type;
__u8 icmp6_code;
- __u16 icmp6_cksum;
+ __sum16 icmp6_cksum;
union {
- __u32 un_data32[1];
- __u16 un_data16[2];
+ __be32 un_data32[1];
+ __be16 un_data16[2];
__u8 un_data8[4];
struct icmpv6_echo {
- __u16 identifier;
- __u16 sequence;
+ __be16 identifier;
+ __be16 sequence;
} u_echo;
struct icmpv6_nd_advt {
@@ -53,7 +53,7 @@ struct icmp6hdr {
#else
#error "Please fix <asm/byteorder.h>"
#endif
- __u16 rt_lifetime;
+ __be16 rt_lifetime;
} u_nd_ra;
} icmp6_dataun;
diff --git a/include/linux/if_packet.h b/include/linux/if_packet.h
index b92558549d27..99393ef3af39 100644
--- a/include/linux/if_packet.h
+++ b/include/linux/if_packet.h
@@ -1,17 +1,19 @@
#ifndef __LINUX_IF_PACKET_H
#define __LINUX_IF_PACKET_H
+#include <linux/types.h>
+
struct sockaddr_pkt
{
unsigned short spkt_family;
unsigned char spkt_device[14];
- unsigned short spkt_protocol;
+ __be16 spkt_protocol;
};
struct sockaddr_ll
{
unsigned short sll_family;
- unsigned short sll_protocol;
+ __be16 sll_protocol;
int sll_ifindex;
unsigned short sll_hatype;
unsigned char sll_pkttype;
diff --git a/include/linux/if_tunnel.h b/include/linux/if_tunnel.h
index bef9f8fd93b3..8de079ba1107 100644
--- a/include/linux/if_tunnel.h
+++ b/include/linux/if_tunnel.h
@@ -19,10 +19,10 @@ struct ip_tunnel_parm
{
char name[IFNAMSIZ];
int link;
- __u16 i_flags;
- __u16 o_flags;
- __u32 i_key;
- __u32 o_key;
+ __be16 i_flags;
+ __be16 o_flags;
+ __be32 i_key;
+ __be32 o_key;
struct iphdr iph;
};
diff --git a/include/linux/igmp.h b/include/linux/igmp.h
index 21dd56905271..6e7ea2f0a57c 100644
--- a/include/linux/igmp.h
+++ b/include/linux/igmp.h
@@ -30,7 +30,7 @@ struct igmphdr
{
__u8 type;
__u8 code; /* For newer IGMP */
- __be16 csum;
+ __sum16 csum;
__be32 group;
};
diff --git a/include/linux/in.h b/include/linux/in.h
index 2619859f6e1b..1912e7c0bc26 100644
--- a/include/linux/in.h
+++ b/include/linux/in.h
@@ -45,6 +45,7 @@ enum {
IPPROTO_COMP = 108, /* Compression Header protocol */
IPPROTO_SCTP = 132, /* Stream Control Transport Protocol */
+ IPPROTO_UDPLITE = 136, /* UDP-Lite (RFC 3828) */
IPPROTO_RAW = 255, /* Raw IP packets */
IPPROTO_MAX
diff --git a/include/linux/in6.h b/include/linux/in6.h
index f28621f638e0..4e8350ae8869 100644
--- a/include/linux/in6.h
+++ b/include/linux/in6.h
@@ -54,7 +54,7 @@ extern const struct in6_addr in6addr_loopback;
struct sockaddr_in6 {
unsigned short int sin6_family; /* AF_INET6 */
__be16 sin6_port; /* Transport layer port # */
- __u32 sin6_flowinfo; /* IPv6 flow information */
+ __be32 sin6_flowinfo; /* IPv6 flow information */
struct in6_addr sin6_addr; /* IPv6 address */
__u32 sin6_scope_id; /* scope id (new in RFC2553) */
};
@@ -72,7 +72,7 @@ struct ipv6_mreq {
struct in6_flowlabel_req
{
struct in6_addr flr_dst;
- __u32 flr_label;
+ __be32 flr_label;
__u8 flr_action;
__u8 flr_share;
__u16 flr_flags;
diff --git a/include/linux/inet.h b/include/linux/inet.h
index b7c6da7d6d32..675a7dbe86f8 100644
--- a/include/linux/inet.h
+++ b/include/linux/inet.h
@@ -46,7 +46,7 @@
#include <linux/types.h>
extern __be32 in_aton(const char *str);
-extern int in4_pton(const char *src, int srclen, u8 *dst, char delim, const char **end);
-extern int in6_pton(const char *src, int srclen, u8 *dst, char delim, const char **end);
+extern int in4_pton(const char *src, int srclen, u8 *dst, int delim, const char **end);
+extern int in6_pton(const char *src, int srclen, u8 *dst, int delim, const char **end);
#endif
#endif /* _LINUX_INET_H */
diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
index 5a0ab04627bc..c0f7aec331c2 100644
--- a/include/linux/inetdevice.h
+++ b/include/linux/inetdevice.h
@@ -124,12 +124,13 @@ static __inline__ int inet_ifa_match(__be32 addr, struct in_ifaddr *ifa)
* Check if a mask is acceptable.
*/
-static __inline__ int bad_mask(u32 mask, u32 addr)
+static __inline__ int bad_mask(__be32 mask, __be32 addr)
{
+ __u32 hmask;
if (addr & (mask = ~mask))
return 1;
- mask = ntohl(mask);
- if (mask & (mask+1))
+ hmask = ntohl(mask);
+ if (hmask & (hmask+1))
return 1;
return 0;
}
@@ -190,11 +191,12 @@ static __inline__ __be32 inet_make_mask(int logmask)
return 0;
}
-static __inline__ int inet_mask_len(__u32 mask)
+static __inline__ int inet_mask_len(__be32 mask)
{
- if (!(mask = ntohl(mask)))
+ __u32 hmask = ntohl(mask);
+ if (!hmask)
return 0;
- return 32 - ffz(~mask);
+ return 32 - ffz(~hmask);
}
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index d42c83399071..cf8696d4a138 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -89,6 +89,7 @@ struct resource_list {
#define IORESOURCE_ROM_ENABLE (1<<0) /* ROM is enabled, same as PCI_ROM_ADDRESS_ENABLE */
#define IORESOURCE_ROM_SHADOW (1<<1) /* ROM is copy at C000:0 */
#define IORESOURCE_ROM_COPY (1<<2) /* ROM is alloc'd copy, resource field overlaid */
+#define IORESOURCE_ROM_BIOS_COPY (1<<3) /* ROM is BIOS copy, resource field overlaid */
/* PC/ISA/whatever - the normal PC address spaces: IO and memory */
extern struct resource ioport_resource;
diff --git a/include/linux/ip.h b/include/linux/ip.h
index ecee9bb27d0e..1d36b971a8b5 100644
--- a/include/linux/ip.h
+++ b/include/linux/ip.h
@@ -98,7 +98,7 @@ struct iphdr {
__be16 frag_off;
__u8 ttl;
__u8 protocol;
- __be16 check;
+ __sum16 check;
__be32 saddr;
__be32 daddr;
/*The options start here. */
diff --git a/include/linux/ip6_tunnel.h b/include/linux/ip6_tunnel.h
index 5c23aeb104ca..af3f4a70f3df 100644
--- a/include/linux/ip6_tunnel.h
+++ b/include/linux/ip6_tunnel.h
@@ -25,7 +25,7 @@ struct ip6_tnl_parm {
__u8 proto; /* tunnel protocol */
__u8 encap_limit; /* encapsulation limit for tunnel */
__u8 hop_limit; /* hop limit for tunnel */
- __u32 flowinfo; /* traffic class and flowlabel for tunnel */
+ __be32 flowinfo; /* traffic class and flowlabel for tunnel */
__u32 flags; /* tunnel flags */
struct in6_addr laddr; /* local tunnel end-point address */
struct in6_addr raddr; /* remote tunnel end-point address */
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 4f435c59de06..f8241130f5ea 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -274,7 +274,7 @@ struct ipv6_pinfo {
struct in6_addr *saddr_cache;
#endif
- __u32 flow_label;
+ __be32 flow_label;
__u32 frag_size;
__s16 hop_limit;
__s16 mcast_hops;
diff --git a/include/linux/ixjuser.h b/include/linux/ixjuser.h
index fd1756d3a47e..88b45895746d 100644
--- a/include/linux/ixjuser.h
+++ b/include/linux/ixjuser.h
@@ -315,7 +315,7 @@ typedef struct {
* structures. If the freq0 variable is non-zero, the tone table contents
* for the tone_index are updated to the frequencies and gains defined. It
* should be noted that DTMF tones cannot be reassigned, so if DTMF tone
-* table indexs are used in a cadence the frequency and gain variables will
+* table indexes are used in a cadence the frequency and gain variables will
* be ignored.
*
* If the array elements contain frequency parameters the driver will
diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h
index c8d5f207c3d4..0ec6e28bccd2 100644
--- a/include/linux/jiffies.h
+++ b/include/linux/jiffies.h
@@ -74,7 +74,7 @@
#define __jiffy_data __attribute__((section(".data")))
/*
- * The 64-bit value is not volatile - you MUST NOT read it
+ * The 64-bit value is not atomic - you MUST NOT read it
* without sampling the sequence number in xtime_lock.
* get_jiffies_64() will do this for you as appropriate.
*/
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 24b611147adb..6738283ac385 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -30,8 +30,10 @@ extern const char linux_banner[];
#define STACK_MAGIC 0xdeadbeef
+#define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1)
+#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
+
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-#define ALIGN(x,a) (((x)+(a)-1UL)&~((a)-1UL))
#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
@@ -63,7 +65,7 @@ struct user;
* context (spinlock, irq-handler, ...).
*
* This is a useful debugging help to be able to catch problems early and not
- * be biten later when the calling function happens to sleep when it is not
+ * be bitten later when the calling function happens to sleep when it is not
* supposed to.
*/
#ifdef CONFIG_PREEMPT_VOLUNTARY
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index 6427949ddf99..a4ede62b339d 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -122,6 +122,8 @@ extern struct kimage *kexec_crash_image;
#define KEXEC_ARCH_IA_64 (50 << 16)
#define KEXEC_ARCH_S390 (22 << 16)
#define KEXEC_ARCH_SH (42 << 16)
+#define KEXEC_ARCH_MIPS_LE (10 << 16)
+#define KEXEC_ARCH_MIPS ( 8 << 16)
#define KEXEC_FLAGS (KEXEC_ON_CRASH) /* List of defined/legal kexec flags */
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index bcd9cd173c2c..d1c8d28fa92e 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -47,6 +47,7 @@ enum kobject_action {
KOBJ_UMOUNT = (__force kobject_action_t) 0x05, /* umount event for block devices (broken) */
KOBJ_OFFLINE = (__force kobject_action_t) 0x06, /* device offline */
KOBJ_ONLINE = (__force kobject_action_t) 0x07, /* device online */
+ KOBJ_MOVE = (__force kobject_action_t) 0x08, /* device move */
};
struct kobject {
@@ -76,6 +77,7 @@ extern int __must_check kobject_add(struct kobject *);
extern void kobject_del(struct kobject *);
extern int __must_check kobject_rename(struct kobject *, const char *new_name);
+extern int __must_check kobject_move(struct kobject *, struct kobject *);
extern int __must_check kobject_register(struct kobject *);
extern void kobject_unregister(struct kobject *);
@@ -264,6 +266,8 @@ extern int __must_check subsys_create_file(struct subsystem * ,
#if defined(CONFIG_HOTPLUG)
void kobject_uevent(struct kobject *kobj, enum kobject_action action);
+void kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
+ char *envp[]);
int add_uevent_var(char **envp, int num_envp, int *cur_index,
char *buffer, int buffer_size, int *cur_len,
@@ -271,6 +275,10 @@ int add_uevent_var(char **envp, int num_envp, int *cur_index,
__attribute__((format (printf, 7, 8)));
#else
static inline void kobject_uevent(struct kobject *kobj, enum kobject_action action) { }
+static inline void kobject_uevent_env(struct kobject *kobj,
+ enum kobject_action action,
+ char *envp[])
+{ }
static inline int add_uevent_var(char **envp, int num_envp, int *cur_index,
char *buffer, int buffer_size, int *cur_len,
diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h
index b03cfb91e228..326da7d500c7 100644
--- a/include/linux/miscdevice.h
+++ b/include/linux/miscdevice.h
@@ -31,15 +31,14 @@
#define HPET_MINOR 228
struct device;
-struct class_device;
struct miscdevice {
int minor;
const char *name;
const struct file_operations *fops;
struct list_head list;
- struct device *dev;
- struct class_device *class;
+ struct device *parent;
+ struct device *this_device;
};
extern int misc_register(struct miscdevice * misc);
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 991a37382a22..d0e6a5497614 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -39,6 +39,10 @@ struct mmc_csd {
write_misalign:1;
};
+struct mmc_ext_csd {
+ unsigned int hs_max_dtr;
+};
+
struct sd_scr {
unsigned char sda_vsn;
unsigned char bus_widths;
@@ -46,6 +50,10 @@ struct sd_scr {
#define SD_SCR_BUS_WIDTH_4 (1<<2)
};
+struct sd_switch_caps {
+ unsigned int hs_max_dtr;
+};
+
struct mmc_host;
/*
@@ -62,12 +70,15 @@ struct mmc_card {
#define MMC_STATE_BAD (1<<2) /* unrecognised device */
#define MMC_STATE_SDCARD (1<<3) /* is an SD card */
#define MMC_STATE_READONLY (1<<4) /* card is read-only */
+#define MMC_STATE_HIGHSPEED (1<<5) /* card is in high speed mode */
u32 raw_cid[4]; /* raw card CID */
u32 raw_csd[4]; /* raw card CSD */
u32 raw_scr[2]; /* raw card SCR */
struct mmc_cid cid; /* card identification */
struct mmc_csd csd; /* card specific */
+ struct mmc_ext_csd ext_csd; /* mmc v4 extended card specific */
struct sd_scr scr; /* extra SD information */
+ struct sd_switch_caps sw_caps; /* switch (CMD6) caps */
};
#define mmc_card_present(c) ((c)->state & MMC_STATE_PRESENT)
@@ -75,12 +86,14 @@ struct mmc_card {
#define mmc_card_bad(c) ((c)->state & MMC_STATE_BAD)
#define mmc_card_sd(c) ((c)->state & MMC_STATE_SDCARD)
#define mmc_card_readonly(c) ((c)->state & MMC_STATE_READONLY)
+#define mmc_card_highspeed(c) ((c)->state & MMC_STATE_HIGHSPEED)
#define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT)
#define mmc_card_set_dead(c) ((c)->state |= MMC_STATE_DEAD)
#define mmc_card_set_bad(c) ((c)->state |= MMC_STATE_BAD)
#define mmc_card_set_sd(c) ((c)->state |= MMC_STATE_SDCARD)
#define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
+#define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED)
#define mmc_card_name(c) ((c)->cid.prod_name)
#define mmc_card_id(c) ((c)->dev.bus_id)
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 8b08ef3820f2..c15ae1986b98 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -74,8 +74,8 @@ struct mmc_card;
struct device;
struct mmc_host {
- struct device *dev;
- struct class_device class_dev;
+ struct device *parent;
+ struct device class_dev;
int index;
const struct mmc_host_ops *ops;
unsigned int f_min;
@@ -125,8 +125,8 @@ static inline void *mmc_priv(struct mmc_host *host)
return (void *)host->private;
}
-#define mmc_dev(x) ((x)->dev)
-#define mmc_hostname(x) ((x)->class_dev.class_id)
+#define mmc_dev(x) ((x)->parent)
+#define mmc_hostname(x) ((x)->class_dev.bus_id)
extern int mmc_suspend_host(struct mmc_host *, pm_message_t);
extern int mmc_resume_host(struct mmc_host *);
diff --git a/include/linux/mmc/protocol.h b/include/linux/mmc/protocol.h
index 08dec8d9e703..2dce60c43f4b 100644
--- a/include/linux/mmc/protocol.h
+++ b/include/linux/mmc/protocol.h
@@ -25,14 +25,16 @@
#ifndef MMC_MMC_PROTOCOL_H
#define MMC_MMC_PROTOCOL_H
-/* Standard MMC commands (3.1) type argument response */
+/* Standard MMC commands (4.1) type argument response */
/* class 1 */
#define MMC_GO_IDLE_STATE 0 /* bc */
#define MMC_SEND_OP_COND 1 /* bcr [31:0] OCR R3 */
#define MMC_ALL_SEND_CID 2 /* bcr R2 */
#define MMC_SET_RELATIVE_ADDR 3 /* ac [31:16] RCA R1 */
#define MMC_SET_DSR 4 /* bc [31:16] RCA */
+#define MMC_SWITCH 6 /* ac [31:0] See below R1b */
#define MMC_SELECT_CARD 7 /* ac [31:16] RCA R1 */
+#define MMC_SEND_EXT_CSD 8 /* adtc R1 */
#define MMC_SEND_CSD 9 /* ac [31:16] RCA R2 */
#define MMC_SEND_CID 10 /* ac [31:16] RCA R2 */
#define MMC_READ_DAT_UNTIL_STOP 11 /* adtc [31:0] dadr R1 */
@@ -80,6 +82,7 @@
/* class 8 */
/* This is basically the same command as for MMC with some quirks. */
#define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */
+#define SD_SWITCH 6 /* adtc [31:0] See below R1 */
/* Application commands */
#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */
@@ -88,6 +91,30 @@
#define SD_APP_SEND_SCR 51 /* adtc R1 */
/*
+ * MMC_SWITCH argument format:
+ *
+ * [31:26] Always 0
+ * [25:24] Access Mode
+ * [23:16] Location of target Byte in EXT_CSD
+ * [15:08] Value Byte
+ * [07:03] Always 0
+ * [02:00] Command Set
+ */
+
+/*
+ * SD_SWITCH argument format:
+ *
+ * [31] Check (0) or switch (1)
+ * [30:24] Reserved (0)
+ * [23:20] Function group 6
+ * [19:16] Function group 5
+ * [15:12] Function group 4
+ * [11:8] Function group 3
+ * [7:4] Function group 2
+ * [3:0] Function group 1
+ */
+
+/*
MMC status in R1
Type
e : error bit
@@ -230,13 +257,54 @@ struct _mmc_csd {
#define CSD_STRUCT_VER_1_0 0 /* Valid for system specification 1.0 - 1.2 */
#define CSD_STRUCT_VER_1_1 1 /* Valid for system specification 1.4 - 2.2 */
-#define CSD_STRUCT_VER_1_2 2 /* Valid for system specification 3.1 */
+#define CSD_STRUCT_VER_1_2 2 /* Valid for system specification 3.1 - 3.2 - 3.31 - 4.0 - 4.1 */
+#define CSD_STRUCT_EXT_CSD 3 /* Version is coded in CSD_STRUCTURE in EXT_CSD */
#define CSD_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.2 */
#define CSD_SPEC_VER_1 1 /* Implements system specification 1.4 */
#define CSD_SPEC_VER_2 2 /* Implements system specification 2.0 - 2.2 */
-#define CSD_SPEC_VER_3 3 /* Implements system specification 3.1 */
+#define CSD_SPEC_VER_3 3 /* Implements system specification 3.1 - 3.2 - 3.31 */
+#define CSD_SPEC_VER_4 4 /* Implements system specification 4.0 - 4.1 */
+
+/*
+ * EXT_CSD fields
+ */
+
+#define EXT_CSD_BUS_WIDTH 183 /* R/W */
+#define EXT_CSD_HS_TIMING 185 /* R/W */
+#define EXT_CSD_CARD_TYPE 196 /* RO */
+
+/*
+ * EXT_CSD field definitions
+ */
+
+#define EXT_CSD_CMD_SET_NORMAL (1<<0)
+#define EXT_CSD_CMD_SET_SECURE (1<<1)
+#define EXT_CSD_CMD_SET_CPSECURE (1<<2)
+
+#define EXT_CSD_CARD_TYPE_26 (1<<0) /* Card can run at 26MHz */
+#define EXT_CSD_CARD_TYPE_52 (1<<1) /* Card can run at 52MHz */
+
+#define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */
+#define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */
+#define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */
+
+/*
+ * MMC_SWITCH access modes
+ */
+
+#define MMC_SWITCH_MODE_CMD_SET 0x00 /* Change the command set */
+#define MMC_SWITCH_MODE_SET_BITS 0x01 /* Set bits which are 1 in value */
+#define MMC_SWITCH_MODE_CLEAR_BITS 0x02 /* Clear bits which are 1 in value */
+#define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target to value */
+
+/*
+ * SCR field definitions
+ */
+#define SCR_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.01 */
+#define SCR_SPEC_VER_1 1 /* Implements system specification 1.10 */
+#define SCR_SPEC_VER_2 2 /* Implements system specification 2.00 */
/*
* SD bus widths
diff --git a/include/linux/module.h b/include/linux/module.h
index d1d00ce8f4ed..9258ffd8a7f0 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -264,6 +264,7 @@ struct module
struct module_attribute *modinfo_attrs;
const char *version;
const char *srcversion;
+ struct kobject *drivers_dir;
/* Exported symbols */
const struct kernel_symbol *syms;
diff --git a/include/linux/mqueue.h b/include/linux/mqueue.h
index 8db9d75541a6..8b5a79615fbf 100644
--- a/include/linux/mqueue.h
+++ b/include/linux/mqueue.h
@@ -18,8 +18,6 @@
#ifndef _LINUX_MQUEUE_H
#define _LINUX_MQUEUE_H
-#include <linux/types.h>
-
#define MQ_PRIO_MAX 32768
/* per-uid limit of kernel memory used by mqueue, in bytes */
#define MQ_BYTES_MAX 819200
diff --git a/include/linux/mv643xx.h b/include/linux/mv643xx.h
index edfa012fad3a..aff25c000abf 100644
--- a/include/linux/mv643xx.h
+++ b/include/linux/mv643xx.h
@@ -724,7 +724,7 @@
#define MV643XX_ETH_RX_FIFO_URGENT_THRESHOLD_REG(port) (0x2470 + (port<<10))
#define MV643XX_ETH_TX_FIFO_URGENT_THRESHOLD_REG(port) (0x2474 + (port<<10))
#define MV643XX_ETH_RX_MINIMAL_FRAME_SIZE_REG(port) (0x247c + (port<<10))
-#define MV643XX_ETH_RX_DISCARDED_FRAMES_COUNTER(port) (0x2484 + (port<<10)
+#define MV643XX_ETH_RX_DISCARDED_FRAMES_COUNTER(port) (0x2484 + (port<<10))
#define MV643XX_ETH_PORT_DEBUG_0_REG(port) (0x248c + (port<<10))
#define MV643XX_ETH_PORT_DEBUG_1_REG(port) (0x2490 + (port<<10))
#define MV643XX_ETH_PORT_INTERNAL_ADDR_ERROR_REG(port) (0x2494 + (port<<10))
@@ -1135,7 +1135,7 @@ struct mv64xxx_i2c_pdata {
#define MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_1 (1<<19)
#define MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_2 (1<<20)
#define MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_3 ((1<<20) | (1<<19))
-#define MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_4 ((1<<21)
+#define MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_4 (1<<21)
#define MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_5 ((1<<21) | (1<<19))
#define MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_6 ((1<<21) | (1<<20))
#define MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_7 ((1<<21) | (1<<20) | (1<<19))
diff --git a/include/linux/net.h b/include/linux/net.h
index 15c733b816f0..6f0dfeba509a 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -196,7 +196,7 @@ extern struct socket *sockfd_lookup(int fd, int *err);
extern int net_ratelimit(void);
#define net_random() random32()
-#define net_srandom(seed) srandom32(seed)
+#define net_srandom(seed) srandom32((__force u32)seed)
extern int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
struct kvec *vec, size_t num, size_t len);
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 9264139bd8df..949eada46ce1 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -38,7 +38,6 @@
#include <linux/percpu.h>
#include <linux/dmaengine.h>
-struct divert_blk;
struct vlan_group;
struct ethtool_ops;
struct netpoll_info;
@@ -67,6 +66,10 @@ struct netpoll_info;
#define NET_RX_CN_HIGH 4 /* The storm is here */
#define NET_RX_BAD 5 /* packet dropped due to kernel error */
+/* NET_XMIT_CN is special. It does not guarantee that this packet is lost. It
+ * indicates that the device will soon be dropping packets, or already drops
+ * some packets of the same priority; prompting us to send less aggressively. */
+#define net_xmit_eval(e) ((e) == NET_XMIT_CN? 0 : (e))
#define net_xmit_errno(e) ((e) != NET_XMIT_CN ? -ENOBUFS : 0)
#endif
@@ -93,8 +96,10 @@ struct netpoll_info;
#endif
#endif
-#if !defined(CONFIG_NET_IPIP) && \
- !defined(CONFIG_IPV6) && !defined(CONFIG_IPV6_MODULE)
+#if !defined(CONFIG_NET_IPIP) && !defined(CONFIG_NET_IPIP_MODULE) && \
+ !defined(CONFIG_NET_IPGRE) && !defined(CONFIG_NET_IPGRE_MODULE) && \
+ !defined(CONFIG_IPV6_SIT) && !defined(CONFIG_IPV6_SIT_MODULE) && \
+ !defined(CONFIG_IPV6_TUNNEL) && !defined(CONFIG_IPV6_TUNNEL_MODULE)
#define MAX_HEADER LL_MAX_HEADER
#else
#define MAX_HEADER (LL_MAX_HEADER + 48)
@@ -191,7 +196,7 @@ struct hh_cache
* NOTE: For VLANs, this will be the
* encapuslated type. --BLG
*/
- int hh_len; /* length of header */
+ u16 hh_len; /* length of header */
int (*hh_output)(struct sk_buff *skb);
rwlock_t hh_lock;
@@ -515,11 +520,6 @@ struct net_device
/* bridge stuff */
struct net_bridge_port *br_port;
-#ifdef CONFIG_NET_DIVERT
- /* this will get initialized at each interface type init routine */
- struct divert_blk *divert;
-#endif /* CONFIG_NET_DIVERT */
-
/* class/net/name entry */
struct class_device class_dev;
/* space for optional statistics and wireless sysfs groups */
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index b7e67d1d4382..d4c4c5120bc0 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -117,6 +117,16 @@ void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n);
int nf_register_sockopt(struct nf_sockopt_ops *reg);
void nf_unregister_sockopt(struct nf_sockopt_ops *reg);
+#ifdef CONFIG_SYSCTL
+/* Sysctl registration */
+struct ctl_table_header *nf_register_sysctl_table(struct ctl_table *path,
+ struct ctl_table *table);
+void nf_unregister_sysctl_table(struct ctl_table_header *header,
+ struct ctl_table *table);
+extern struct ctl_table nf_net_netfilter_sysctl_path[];
+extern struct ctl_table nf_net_ipv4_netfilter_sysctl_path[];
+#endif /* CONFIG_SYSCTL */
+
extern struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS];
/* those NF_LOG_* defines and struct nf_loginfo are legacy definitios that will
@@ -282,15 +292,31 @@ extern void nf_invalidate_cache(int pf);
Returns true or false. */
extern int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len);
-extern u_int16_t nf_csum_update(u_int32_t oldval, u_int32_t newval,
- u_int32_t csum);
-extern u_int16_t nf_proto_csum_update(struct sk_buff *skb,
- u_int32_t oldval, u_int32_t newval,
- u_int16_t csum, int pseudohdr);
+static inline void nf_csum_replace4(__sum16 *sum, __be32 from, __be32 to)
+{
+ __be32 diff[] = { ~from, to };
+
+ *sum = csum_fold(csum_partial((char *)diff, sizeof(diff), ~csum_unfold(*sum)));
+}
+
+static inline void nf_csum_replace2(__sum16 *sum, __be16 from, __be16 to)
+{
+ nf_csum_replace4(sum, (__force __be32)from, (__force __be32)to);
+}
+
+extern void nf_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb,
+ __be32 from, __be32 to, int pseudohdr);
+
+static inline void nf_proto_csum_replace2(__sum16 *sum, struct sk_buff *skb,
+ __be16 from, __be16 to, int pseudohdr)
+{
+ nf_proto_csum_replace4(sum, skb, (__force __be32)from,
+ (__force __be32)to, pseudohdr);
+}
struct nf_afinfo {
unsigned short family;
- unsigned int (*checksum)(struct sk_buff *skb, unsigned int hook,
+ __sum16 (*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);
@@ -305,12 +331,12 @@ static inline struct nf_afinfo *nf_get_afinfo(unsigned short family)
return rcu_dereference(nf_afinfo[family]);
}
-static inline unsigned int
+static inline __sum16
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;
+ __sum16 csum = 0;
rcu_read_lock();
afinfo = nf_get_afinfo(family);
@@ -331,7 +357,7 @@ extern void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *);
static inline void
nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, int family)
{
-#ifdef CONFIG_IP_NF_NAT_NEEDED
+#if defined(CONFIG_IP_NF_NAT_NEEDED) || defined(CONFIG_NF_NAT_NEEDED)
void (*decodefn)(struct sk_buff *, struct flowi *);
if (family == AF_INET && (decodefn = ip_nat_decode_session) != NULL)
diff --git a/include/linux/netfilter/Kbuild b/include/linux/netfilter/Kbuild
index 312bd2ffee33..6328175a1c3a 100644
--- a/include/linux/netfilter/Kbuild
+++ b/include/linux/netfilter/Kbuild
@@ -14,6 +14,7 @@ header-y += xt_dscp.h
header-y += xt_DSCP.h
header-y += xt_esp.h
header-y += xt_helper.h
+header-y += xt_hashlimit.h
header-y += xt_length.h
header-y += xt_limit.h
header-y += xt_mac.h
@@ -21,6 +22,7 @@ header-y += xt_mark.h
header-y += xt_MARK.h
header-y += xt_multiport.h
header-y += xt_NFQUEUE.h
+header-y += xt_NFLOG.h
header-y += xt_pkttype.h
header-y += xt_policy.h
header-y += xt_realm.h
diff --git a/include/linux/netfilter/nf_conntrack_amanda.h b/include/linux/netfilter/nf_conntrack_amanda.h
new file mode 100644
index 000000000000..26c223544ae8
--- /dev/null
+++ b/include/linux/netfilter/nf_conntrack_amanda.h
@@ -0,0 +1,10 @@
+#ifndef _NF_CONNTRACK_AMANDA_H
+#define _NF_CONNTRACK_AMANDA_H
+/* AMANDA tracking. */
+
+extern unsigned int (*nf_nat_amanda_hook)(struct sk_buff **pskb,
+ enum ip_conntrack_info ctinfo,
+ unsigned int matchoff,
+ unsigned int matchlen,
+ struct nf_conntrack_expect *exp);
+#endif /* _NF_CONNTRACK_AMANDA_H */
diff --git a/include/linux/netfilter/nf_conntrack_ftp.h b/include/linux/netfilter/nf_conntrack_ftp.h
index ad4a41c9ce93..81453ea7e4c2 100644
--- a/include/linux/netfilter/nf_conntrack_ftp.h
+++ b/include/linux/netfilter/nf_conntrack_ftp.h
@@ -3,16 +3,16 @@
/* FTP tracking. */
/* This enum is exposed to userspace */
-enum ip_ct_ftp_type
+enum nf_ct_ftp_type
{
/* PORT command from client */
- IP_CT_FTP_PORT,
+ NF_CT_FTP_PORT,
/* PASV response from server */
- IP_CT_FTP_PASV,
+ NF_CT_FTP_PASV,
/* EPRT command from client */
- IP_CT_FTP_EPRT,
+ NF_CT_FTP_EPRT,
/* EPSV response from server */
- IP_CT_FTP_EPSV,
+ NF_CT_FTP_EPSV,
};
#ifdef __KERNEL__
@@ -21,23 +21,23 @@ enum ip_ct_ftp_type
#define NUM_SEQ_TO_REMEMBER 2
/* This structure exists only once per master */
-struct ip_ct_ftp_master {
+struct nf_ct_ftp_master {
/* Valid seq positions for cmd matching after newline */
u_int32_t seq_aft_nl[IP_CT_DIR_MAX][NUM_SEQ_TO_REMEMBER];
/* 0 means seq_match_aft_nl not set */
int seq_aft_nl_num[IP_CT_DIR_MAX];
};
-struct ip_conntrack_expect;
+struct nf_conntrack_expect;
/* For NAT to hook in when we find a packet which describes what other
* connection we should expect. */
-extern unsigned int (*ip_nat_ftp_hook)(struct sk_buff **pskb,
+extern unsigned int (*nf_nat_ftp_hook)(struct sk_buff **pskb,
enum ip_conntrack_info ctinfo,
- enum ip_ct_ftp_type type,
+ enum nf_ct_ftp_type type,
unsigned int matchoff,
unsigned int matchlen,
- struct ip_conntrack_expect *exp,
+ struct nf_conntrack_expect *exp,
u32 *seq);
#endif /* __KERNEL__ */
diff --git a/include/linux/netfilter/nf_conntrack_h323.h b/include/linux/netfilter/nf_conntrack_h323.h
new file mode 100644
index 000000000000..08e2f4977c2e
--- /dev/null
+++ b/include/linux/netfilter/nf_conntrack_h323.h
@@ -0,0 +1,92 @@
+#ifndef _NF_CONNTRACK_H323_H
+#define _NF_CONNTRACK_H323_H
+
+#ifdef __KERNEL__
+
+#include <linux/netfilter/nf_conntrack_h323_asn1.h>
+
+#define RAS_PORT 1719
+#define Q931_PORT 1720
+#define H323_RTP_CHANNEL_MAX 4 /* Audio, video, FAX and other */
+
+/* This structure exists only once per master */
+struct nf_ct_h323_master {
+
+ /* Original and NATed Q.931 or H.245 signal ports */
+ __be16 sig_port[IP_CT_DIR_MAX];
+
+ /* Original and NATed RTP ports */
+ __be16 rtp_port[H323_RTP_CHANNEL_MAX][IP_CT_DIR_MAX];
+
+ union {
+ /* RAS connection timeout */
+ u_int32_t timeout;
+
+ /* Next TPKT length (for separate TPKT header and data) */
+ u_int16_t tpkt_len[IP_CT_DIR_MAX];
+ };
+};
+
+struct nf_conn;
+
+extern int get_h225_addr(struct nf_conn *ct, unsigned char *data,
+ TransportAddress *taddr,
+ union nf_conntrack_address *addr, __be16 *port);
+extern void nf_conntrack_h245_expect(struct nf_conn *new,
+ struct nf_conntrack_expect *this);
+extern void nf_conntrack_q931_expect(struct nf_conn *new,
+ struct nf_conntrack_expect *this);
+extern int (*set_h245_addr_hook) (struct sk_buff **pskb,
+ unsigned char **data, int dataoff,
+ H245_TransportAddress *taddr,
+ union nf_conntrack_address *addr,
+ __be16 port);
+extern int (*set_h225_addr_hook) (struct sk_buff **pskb,
+ unsigned char **data, int dataoff,
+ TransportAddress *taddr,
+ union nf_conntrack_address *addr,
+ __be16 port);
+extern int (*set_sig_addr_hook) (struct sk_buff **pskb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data,
+ TransportAddress *taddr, int count);
+extern int (*set_ras_addr_hook) (struct sk_buff **pskb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data,
+ TransportAddress *taddr, int count);
+extern int (*nat_rtp_rtcp_hook) (struct sk_buff **pskb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ H245_TransportAddress *taddr,
+ __be16 port, __be16 rtp_port,
+ struct nf_conntrack_expect *rtp_exp,
+ struct nf_conntrack_expect *rtcp_exp);
+extern int (*nat_t120_hook) (struct sk_buff **pskb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ H245_TransportAddress *taddr, __be16 port,
+ struct nf_conntrack_expect *exp);
+extern int (*nat_h245_hook) (struct sk_buff **pskb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ TransportAddress *taddr, __be16 port,
+ struct nf_conntrack_expect *exp);
+extern int (*nat_callforwarding_hook) (struct sk_buff **pskb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ TransportAddress *taddr,
+ __be16 port,
+ struct nf_conntrack_expect *exp);
+extern int (*nat_q931_hook) (struct sk_buff **pskb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, TransportAddress *taddr,
+ int idx, __be16 port,
+ struct nf_conntrack_expect *exp);
+
+#endif
+
+#endif
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h b/include/linux/netfilter/nf_conntrack_h323_asn1.h
index c6e9a0b6d30b..8dab5968fc7e 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h
+++ b/include/linux/netfilter/nf_conntrack_h323_asn1.h
@@ -1,6 +1,6 @@
/****************************************************************************
- * ip_conntrack_helper_h323_asn1.h - BER and PER decoding library for H.323
- * conntrack/NAT module.
+ * ip_conntrack_h323_asn1.h - BER and PER decoding library for H.323
+ * conntrack/NAT module.
*
* Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@users.sourceforge.net>
*
@@ -34,13 +34,13 @@
*
****************************************************************************/
-#ifndef _IP_CONNTRACK_HELPER_H323_ASN1_H_
-#define _IP_CONNTRACK_HELPER_H323_ASN1_H_
+#ifndef _NF_CONNTRACK_HELPER_H323_ASN1_H_
+#define _NF_CONNTRACK_HELPER_H323_ASN1_H_
/*****************************************************************************
* H.323 Types
****************************************************************************/
-#include "ip_conntrack_helper_h323_types.h"
+#include "nf_conntrack_h323_types.h"
typedef struct {
enum {
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h b/include/linux/netfilter/nf_conntrack_h323_types.h
index 3d4a773799fc..38d74d5c9700 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h
+++ b/include/linux/netfilter/nf_conntrack_h323_types.h
@@ -10,6 +10,11 @@ typedef struct TransportAddress_ipAddress { /* SEQUENCE */
unsigned ip;
} TransportAddress_ipAddress;
+typedef struct TransportAddress_ip6Address { /* SEQUENCE */
+ int options; /* No use */
+ unsigned ip6;
+} TransportAddress_ip6Address;
+
typedef struct TransportAddress { /* CHOICE */
enum {
eTransportAddress_ipAddress,
@@ -22,6 +27,7 @@ typedef struct TransportAddress { /* CHOICE */
} choice;
union {
TransportAddress_ipAddress ipAddress;
+ TransportAddress_ip6Address ip6Address;
};
} TransportAddress;
@@ -93,6 +99,11 @@ typedef struct UnicastAddress_iPAddress { /* SEQUENCE */
unsigned network;
} UnicastAddress_iPAddress;
+typedef struct UnicastAddress_iP6Address { /* SEQUENCE */
+ int options; /* No use */
+ unsigned network;
+} UnicastAddress_iP6Address;
+
typedef struct UnicastAddress { /* CHOICE */
enum {
eUnicastAddress_iPAddress,
@@ -105,6 +116,7 @@ typedef struct UnicastAddress { /* CHOICE */
} choice;
union {
UnicastAddress_iPAddress iPAddress;
+ UnicastAddress_iP6Address iP6Address;
};
} UnicastAddress;
diff --git a/include/linux/netfilter/nf_conntrack_irc.h b/include/linux/netfilter/nf_conntrack_irc.h
new file mode 100644
index 000000000000..2ab6b8255911
--- /dev/null
+++ b/include/linux/netfilter/nf_conntrack_irc.h
@@ -0,0 +1,15 @@
+#ifndef _NF_CONNTRACK_IRC_H
+#define _NF_CONNTRACK_IRC_H
+
+#ifdef __KERNEL__
+
+#define IRC_PORT 6667
+
+extern unsigned int (*nf_nat_irc_hook)(struct sk_buff **pskb,
+ enum ip_conntrack_info ctinfo,
+ unsigned int matchoff,
+ unsigned int matchlen,
+ struct nf_conntrack_expect *exp);
+
+#endif /* __KERNEL__ */
+#endif /* _NF_CONNTRACK_IRC_H */
diff --git a/include/linux/netfilter/nf_conntrack_pptp.h b/include/linux/netfilter/nf_conntrack_pptp.h
new file mode 100644
index 000000000000..fb049ec11ff2
--- /dev/null
+++ b/include/linux/netfilter/nf_conntrack_pptp.h
@@ -0,0 +1,321 @@
+/* PPTP constants and structs */
+#ifndef _NF_CONNTRACK_PPTP_H
+#define _NF_CONNTRACK_PPTP_H
+
+/* state of the control session */
+enum pptp_ctrlsess_state {
+ PPTP_SESSION_NONE, /* no session present */
+ PPTP_SESSION_ERROR, /* some session error */
+ PPTP_SESSION_STOPREQ, /* stop_sess request seen */
+ PPTP_SESSION_REQUESTED, /* start_sess request seen */
+ PPTP_SESSION_CONFIRMED, /* session established */
+};
+
+/* state of the call inside the control session */
+enum pptp_ctrlcall_state {
+ PPTP_CALL_NONE,
+ PPTP_CALL_ERROR,
+ PPTP_CALL_OUT_REQ,
+ PPTP_CALL_OUT_CONF,
+ PPTP_CALL_IN_REQ,
+ PPTP_CALL_IN_REP,
+ PPTP_CALL_IN_CONF,
+ PPTP_CALL_CLEAR_REQ,
+};
+
+/* conntrack private data */
+struct nf_ct_pptp_master {
+ enum pptp_ctrlsess_state sstate; /* session state */
+ enum pptp_ctrlcall_state cstate; /* call state */
+ __be16 pac_call_id; /* call id of PAC */
+ __be16 pns_call_id; /* call id of PNS */
+
+ /* in pre-2.6.11 this used to be per-expect. Now it is per-conntrack
+ * and therefore imposes a fixed limit on the number of maps */
+ struct nf_ct_gre_keymap *keymap[IP_CT_DIR_MAX];
+};
+
+struct nf_nat_pptp {
+ __be16 pns_call_id; /* NAT'ed PNS call id */
+ __be16 pac_call_id; /* NAT'ed PAC call id */
+};
+
+#ifdef __KERNEL__
+
+#define PPTP_CONTROL_PORT 1723
+
+#define PPTP_PACKET_CONTROL 1
+#define PPTP_PACKET_MGMT 2
+
+#define PPTP_MAGIC_COOKIE 0x1a2b3c4d
+
+struct pptp_pkt_hdr {
+ __u16 packetLength;
+ __be16 packetType;
+ __be32 magicCookie;
+};
+
+/* PptpControlMessageType values */
+#define PPTP_START_SESSION_REQUEST 1
+#define PPTP_START_SESSION_REPLY 2
+#define PPTP_STOP_SESSION_REQUEST 3
+#define PPTP_STOP_SESSION_REPLY 4
+#define PPTP_ECHO_REQUEST 5
+#define PPTP_ECHO_REPLY 6
+#define PPTP_OUT_CALL_REQUEST 7
+#define PPTP_OUT_CALL_REPLY 8
+#define PPTP_IN_CALL_REQUEST 9
+#define PPTP_IN_CALL_REPLY 10
+#define PPTP_IN_CALL_CONNECT 11
+#define PPTP_CALL_CLEAR_REQUEST 12
+#define PPTP_CALL_DISCONNECT_NOTIFY 13
+#define PPTP_WAN_ERROR_NOTIFY 14
+#define PPTP_SET_LINK_INFO 15
+
+#define PPTP_MSG_MAX 15
+
+/* PptpGeneralError values */
+#define PPTP_ERROR_CODE_NONE 0
+#define PPTP_NOT_CONNECTED 1
+#define PPTP_BAD_FORMAT 2
+#define PPTP_BAD_VALUE 3
+#define PPTP_NO_RESOURCE 4
+#define PPTP_BAD_CALLID 5
+#define PPTP_REMOVE_DEVICE_ERROR 6
+
+struct PptpControlHeader {
+ __be16 messageType;
+ __u16 reserved;
+};
+
+/* FramingCapability Bitmap Values */
+#define PPTP_FRAME_CAP_ASYNC 0x1
+#define PPTP_FRAME_CAP_SYNC 0x2
+
+/* BearerCapability Bitmap Values */
+#define PPTP_BEARER_CAP_ANALOG 0x1
+#define PPTP_BEARER_CAP_DIGITAL 0x2
+
+struct PptpStartSessionRequest {
+ __be16 protocolVersion;
+ __u16 reserved1;
+ __be32 framingCapability;
+ __be32 bearerCapability;
+ __be16 maxChannels;
+ __be16 firmwareRevision;
+ __u8 hostName[64];
+ __u8 vendorString[64];
+};
+
+/* PptpStartSessionResultCode Values */
+#define PPTP_START_OK 1
+#define PPTP_START_GENERAL_ERROR 2
+#define PPTP_START_ALREADY_CONNECTED 3
+#define PPTP_START_NOT_AUTHORIZED 4
+#define PPTP_START_UNKNOWN_PROTOCOL 5
+
+struct PptpStartSessionReply {
+ __be16 protocolVersion;
+ __u8 resultCode;
+ __u8 generalErrorCode;
+ __be32 framingCapability;
+ __be32 bearerCapability;
+ __be16 maxChannels;
+ __be16 firmwareRevision;
+ __u8 hostName[64];
+ __u8 vendorString[64];
+};
+
+/* PptpStopReasons */
+#define PPTP_STOP_NONE 1
+#define PPTP_STOP_PROTOCOL 2
+#define PPTP_STOP_LOCAL_SHUTDOWN 3
+
+struct PptpStopSessionRequest {
+ __u8 reason;
+ __u8 reserved1;
+ __u16 reserved2;
+};
+
+/* PptpStopSessionResultCode */
+#define PPTP_STOP_OK 1
+#define PPTP_STOP_GENERAL_ERROR 2
+
+struct PptpStopSessionReply {
+ __u8 resultCode;
+ __u8 generalErrorCode;
+ __u16 reserved1;
+};
+
+struct PptpEchoRequest {
+ __be32 identNumber;
+};
+
+/* PptpEchoReplyResultCode */
+#define PPTP_ECHO_OK 1
+#define PPTP_ECHO_GENERAL_ERROR 2
+
+struct PptpEchoReply {
+ __be32 identNumber;
+ __u8 resultCode;
+ __u8 generalErrorCode;
+ __u16 reserved;
+};
+
+/* PptpFramingType */
+#define PPTP_ASYNC_FRAMING 1
+#define PPTP_SYNC_FRAMING 2
+#define PPTP_DONT_CARE_FRAMING 3
+
+/* PptpCallBearerType */
+#define PPTP_ANALOG_TYPE 1
+#define PPTP_DIGITAL_TYPE 2
+#define PPTP_DONT_CARE_BEARER_TYPE 3
+
+struct PptpOutCallRequest {
+ __be16 callID;
+ __be16 callSerialNumber;
+ __be32 minBPS;
+ __be32 maxBPS;
+ __be32 bearerType;
+ __be32 framingType;
+ __be16 packetWindow;
+ __be16 packetProcDelay;
+ __be16 phoneNumberLength;
+ __u16 reserved1;
+ __u8 phoneNumber[64];
+ __u8 subAddress[64];
+};
+
+/* PptpCallResultCode */
+#define PPTP_OUTCALL_CONNECT 1
+#define PPTP_OUTCALL_GENERAL_ERROR 2
+#define PPTP_OUTCALL_NO_CARRIER 3
+#define PPTP_OUTCALL_BUSY 4
+#define PPTP_OUTCALL_NO_DIAL_TONE 5
+#define PPTP_OUTCALL_TIMEOUT 6
+#define PPTP_OUTCALL_DONT_ACCEPT 7
+
+struct PptpOutCallReply {
+ __be16 callID;
+ __be16 peersCallID;
+ __u8 resultCode;
+ __u8 generalErrorCode;
+ __be16 causeCode;
+ __be32 connectSpeed;
+ __be16 packetWindow;
+ __be16 packetProcDelay;
+ __be32 physChannelID;
+};
+
+struct PptpInCallRequest {
+ __be16 callID;
+ __be16 callSerialNumber;
+ __be32 callBearerType;
+ __be32 physChannelID;
+ __be16 dialedNumberLength;
+ __be16 dialingNumberLength;
+ __u8 dialedNumber[64];
+ __u8 dialingNumber[64];
+ __u8 subAddress[64];
+};
+
+/* PptpInCallResultCode */
+#define PPTP_INCALL_ACCEPT 1
+#define PPTP_INCALL_GENERAL_ERROR 2
+#define PPTP_INCALL_DONT_ACCEPT 3
+
+struct PptpInCallReply {
+ __be16 callID;
+ __be16 peersCallID;
+ __u8 resultCode;
+ __u8 generalErrorCode;
+ __be16 packetWindow;
+ __be16 packetProcDelay;
+ __u16 reserved;
+};
+
+struct PptpInCallConnected {
+ __be16 peersCallID;
+ __u16 reserved;
+ __be32 connectSpeed;
+ __be16 packetWindow;
+ __be16 packetProcDelay;
+ __be32 callFramingType;
+};
+
+struct PptpClearCallRequest {
+ __be16 callID;
+ __u16 reserved;
+};
+
+struct PptpCallDisconnectNotify {
+ __be16 callID;
+ __u8 resultCode;
+ __u8 generalErrorCode;
+ __be16 causeCode;
+ __u16 reserved;
+ __u8 callStatistics[128];
+};
+
+struct PptpWanErrorNotify {
+ __be16 peersCallID;
+ __u16 reserved;
+ __be32 crcErrors;
+ __be32 framingErrors;
+ __be32 hardwareOverRuns;
+ __be32 bufferOverRuns;
+ __be32 timeoutErrors;
+ __be32 alignmentErrors;
+};
+
+struct PptpSetLinkInfo {
+ __be16 peersCallID;
+ __u16 reserved;
+ __be32 sendAccm;
+ __be32 recvAccm;
+};
+
+union pptp_ctrl_union {
+ struct PptpStartSessionRequest sreq;
+ struct PptpStartSessionReply srep;
+ struct PptpStopSessionRequest streq;
+ struct PptpStopSessionReply strep;
+ struct PptpOutCallRequest ocreq;
+ struct PptpOutCallReply ocack;
+ struct PptpInCallRequest icreq;
+ struct PptpInCallReply icack;
+ struct PptpInCallConnected iccon;
+ struct PptpClearCallRequest clrreq;
+ struct PptpCallDisconnectNotify disc;
+ struct PptpWanErrorNotify wanerr;
+ struct PptpSetLinkInfo setlink;
+};
+
+/* crap needed for nf_conntrack_compat.h */
+struct nf_conn;
+struct nf_conntrack_expect;
+enum ip_conntrack_info;
+
+extern int
+(*nf_nat_pptp_hook_outbound)(struct sk_buff **pskb,
+ struct nf_conn *ct, enum ip_conntrack_info ctinfo,
+ struct PptpControlHeader *ctlh,
+ union pptp_ctrl_union *pptpReq);
+
+extern int
+(*nf_nat_pptp_hook_inbound)(struct sk_buff **pskb,
+ struct nf_conn *ct, enum ip_conntrack_info ctinfo,
+ struct PptpControlHeader *ctlh,
+ union pptp_ctrl_union *pptpReq);
+
+extern void
+(*nf_nat_pptp_hook_exp_gre)(struct nf_conntrack_expect *exp_orig,
+ struct nf_conntrack_expect *exp_reply);
+
+extern void
+(*nf_nat_pptp_hook_expectfn)(struct nf_conn *ct,
+ struct nf_conntrack_expect *exp);
+
+#endif /* __KERNEL__ */
+#endif /* _NF_CONNTRACK_PPTP_H */
diff --git a/include/linux/netfilter/nf_conntrack_proto_gre.h b/include/linux/netfilter/nf_conntrack_proto_gre.h
new file mode 100644
index 000000000000..4e6bbce04ff8
--- /dev/null
+++ b/include/linux/netfilter/nf_conntrack_proto_gre.h
@@ -0,0 +1,112 @@
+#ifndef _CONNTRACK_PROTO_GRE_H
+#define _CONNTRACK_PROTO_GRE_H
+#include <asm/byteorder.h>
+
+/* GRE PROTOCOL HEADER */
+
+/* GRE Version field */
+#define GRE_VERSION_1701 0x0
+#define GRE_VERSION_PPTP 0x1
+
+/* GRE Protocol field */
+#define GRE_PROTOCOL_PPTP 0x880B
+
+/* GRE Flags */
+#define GRE_FLAG_C 0x80
+#define GRE_FLAG_R 0x40
+#define GRE_FLAG_K 0x20
+#define GRE_FLAG_S 0x10
+#define GRE_FLAG_A 0x80
+
+#define GRE_IS_C(f) ((f)&GRE_FLAG_C)
+#define GRE_IS_R(f) ((f)&GRE_FLAG_R)
+#define GRE_IS_K(f) ((f)&GRE_FLAG_K)
+#define GRE_IS_S(f) ((f)&GRE_FLAG_S)
+#define GRE_IS_A(f) ((f)&GRE_FLAG_A)
+
+/* GRE is a mess: Four different standards */
+struct gre_hdr {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ __u16 rec:3,
+ srr:1,
+ seq:1,
+ key:1,
+ routing:1,
+ csum:1,
+ version:3,
+ reserved:4,
+ ack:1;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ __u16 csum:1,
+ routing:1,
+ key:1,
+ seq:1,
+ srr:1,
+ rec:3,
+ ack:1,
+ reserved:4,
+ version:3;
+#else
+#error "Adjust your <asm/byteorder.h> defines"
+#endif
+ __be16 protocol;
+};
+
+/* modified GRE header for PPTP */
+struct gre_hdr_pptp {
+ __u8 flags; /* bitfield */
+ __u8 version; /* should be GRE_VERSION_PPTP */
+ __be16 protocol; /* should be GRE_PROTOCOL_PPTP */
+ __be16 payload_len; /* size of ppp payload, not inc. gre header */
+ __be16 call_id; /* peer's call_id for this session */
+ __be32 seq; /* sequence number. Present if S==1 */
+ __be32 ack; /* seq number of highest packet recieved by */
+ /* sender in this session */
+};
+
+struct nf_ct_gre {
+ unsigned int stream_timeout;
+ unsigned int timeout;
+};
+
+#ifdef __KERNEL__
+#include <net/netfilter/nf_conntrack_tuple.h>
+
+struct nf_conn;
+
+/* structure for original <-> reply keymap */
+struct nf_ct_gre_keymap {
+ struct list_head list;
+ struct nf_conntrack_tuple tuple;
+};
+
+/* add new tuple->key_reply pair to keymap */
+int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir,
+ struct nf_conntrack_tuple *t);
+
+/* delete keymap entries */
+void nf_ct_gre_keymap_destroy(struct nf_conn *ct);
+
+/* get pointer to gre key, if present */
+static inline __be32 *gre_key(struct gre_hdr *greh)
+{
+ if (!greh->key)
+ return NULL;
+ if (greh->csum || greh->routing)
+ return (__be32 *)(greh+sizeof(*greh)+4);
+ return (__be32 *)(greh+sizeof(*greh));
+}
+
+/* get pointer ot gre csum, if present */
+static inline __sum16 *gre_csum(struct gre_hdr *greh)
+{
+ if (!greh->csum)
+ return NULL;
+ return (__sum16 *)(greh+sizeof(*greh));
+}
+
+extern void nf_ct_gre_keymap_flush(void);
+extern void nf_nat_need_gre(void);
+
+#endif /* __KERNEL__ */
+#endif /* _CONNTRACK_PROTO_GRE_H */
diff --git a/include/linux/netfilter/nf_conntrack_sctp.h b/include/linux/netfilter/nf_conntrack_sctp.h
index b8994d9fd1a9..5cf2c115cce4 100644
--- a/include/linux/netfilter/nf_conntrack_sctp.h
+++ b/include/linux/netfilter/nf_conntrack_sctp.h
@@ -20,7 +20,7 @@ struct ip_ct_sctp
{
enum sctp_conntrack state;
- u_int32_t vtag[IP_CT_DIR_MAX];
+ __be32 vtag[IP_CT_DIR_MAX];
u_int32_t ttag[IP_CT_DIR_MAX];
};
diff --git a/include/linux/netfilter/nf_conntrack_sip.h b/include/linux/netfilter/nf_conntrack_sip.h
new file mode 100644
index 000000000000..bb7f2041db74
--- /dev/null
+++ b/include/linux/netfilter/nf_conntrack_sip.h
@@ -0,0 +1,41 @@
+#ifndef __NF_CONNTRACK_SIP_H__
+#define __NF_CONNTRACK_SIP_H__
+#ifdef __KERNEL__
+
+#define SIP_PORT 5060
+#define SIP_TIMEOUT 3600
+
+enum sip_header_pos {
+ POS_REG_REQ_URI,
+ POS_REQ_URI,
+ POS_FROM,
+ POS_TO,
+ POS_VIA,
+ POS_CONTACT,
+ POS_CONTENT,
+ POS_MEDIA,
+ POS_OWNER_IP4,
+ POS_CONNECTION_IP4,
+ POS_OWNER_IP6,
+ POS_CONNECTION_IP6,
+ POS_SDP_HEADER,
+};
+
+extern unsigned int (*nf_nat_sip_hook)(struct sk_buff **pskb,
+ enum ip_conntrack_info ctinfo,
+ struct nf_conn *ct,
+ const char **dptr);
+extern unsigned int (*nf_nat_sdp_hook)(struct sk_buff **pskb,
+ enum ip_conntrack_info ctinfo,
+ struct nf_conntrack_expect *exp,
+ const char *dptr);
+
+extern int ct_sip_get_info(struct nf_conn *ct, const char *dptr, size_t dlen,
+ unsigned int *matchoff, unsigned int *matchlen,
+ enum sip_header_pos pos);
+extern int ct_sip_lnlen(const char *line, const char *limit);
+extern const char *ct_sip_search(const char *needle, const char *haystack,
+ size_t needle_len, size_t haystack_len,
+ int case_sensitive);
+#endif /* __KERNEL__ */
+#endif /* __NF_CONNTRACK_SIP_H__ */
diff --git a/include/linux/netfilter/nf_conntrack_tftp.h b/include/linux/netfilter/nf_conntrack_tftp.h
new file mode 100644
index 000000000000..0d79b7ae051f
--- /dev/null
+++ b/include/linux/netfilter/nf_conntrack_tftp.h
@@ -0,0 +1,20 @@
+#ifndef _NF_CONNTRACK_TFTP_H
+#define _NF_CONNTRACK_TFTP_H
+
+#define TFTP_PORT 69
+
+struct tftphdr {
+ __be16 opcode;
+};
+
+#define TFTP_OPCODE_READ 1
+#define TFTP_OPCODE_WRITE 2
+#define TFTP_OPCODE_DATA 3
+#define TFTP_OPCODE_ACK 4
+#define TFTP_OPCODE_ERROR 5
+
+extern unsigned int (*nf_nat_tftp_hook)(struct sk_buff **pskb,
+ enum ip_conntrack_info ctinfo,
+ struct nf_conntrack_expect *exp);
+
+#endif /* _NF_CONNTRACK_TFTP_H */
diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h
index 6d8e3e5a80e9..1e9c821f152d 100644
--- a/include/linux/netfilter/nfnetlink.h
+++ b/include/linux/netfilter/nfnetlink.h
@@ -78,7 +78,7 @@ struct nfattr
struct nfgenmsg {
u_int8_t nfgen_family; /* AF_xxx */
u_int8_t version; /* nfnetlink version */
- u_int16_t res_id; /* resource id */
+ __be16 res_id; /* resource id */
};
#define NFNETLINK_V0 0
diff --git a/include/linux/netfilter/nfnetlink_log.h b/include/linux/netfilter/nfnetlink_log.h
index 87b92f8b988f..5966afa026e9 100644
--- a/include/linux/netfilter/nfnetlink_log.h
+++ b/include/linux/netfilter/nfnetlink_log.h
@@ -16,24 +16,22 @@ enum nfulnl_msg_types {
};
struct nfulnl_msg_packet_hdr {
- u_int16_t hw_protocol; /* hw protocol (network order) */
+ __be16 hw_protocol; /* hw protocol (network order) */
u_int8_t hook; /* netfilter hook */
u_int8_t _pad;
};
struct nfulnl_msg_packet_hw {
- u_int16_t hw_addrlen;
+ __be16 hw_addrlen;
u_int16_t _pad;
u_int8_t hw_addr[8];
};
struct nfulnl_msg_packet_timestamp {
- aligned_u64 sec;
- aligned_u64 usec;
+ aligned_be64 sec;
+ aligned_be64 usec;
};
-#define NFULNL_PREFIXLEN 30 /* just like old log target */
-
enum nfulnl_attr_type {
NFULA_UNSPEC,
NFULA_PACKET_HDR,
@@ -67,7 +65,7 @@ struct nfulnl_msg_config_cmd {
} __attribute__ ((packed));
struct nfulnl_msg_config_mode {
- u_int32_t copy_range;
+ __be32 copy_range;
u_int8_t copy_mode;
u_int8_t _pad;
} __attribute__ ((packed));
diff --git a/include/linux/netfilter/nfnetlink_queue.h b/include/linux/netfilter/nfnetlink_queue.h
index 36af0360b56d..83e789633e35 100644
--- a/include/linux/netfilter/nfnetlink_queue.h
+++ b/include/linux/netfilter/nfnetlink_queue.h
@@ -13,20 +13,20 @@ enum nfqnl_msg_types {
};
struct nfqnl_msg_packet_hdr {
- u_int32_t packet_id; /* unique ID of packet in queue */
- u_int16_t hw_protocol; /* hw protocol (network order) */
+ __be32 packet_id; /* unique ID of packet in queue */
+ __be16 hw_protocol; /* hw protocol (network order) */
u_int8_t hook; /* netfilter hook */
} __attribute__ ((packed));
struct nfqnl_msg_packet_hw {
- u_int16_t hw_addrlen;
+ __be16 hw_addrlen;
u_int16_t _pad;
u_int8_t hw_addr[8];
};
struct nfqnl_msg_packet_timestamp {
- aligned_u64 sec;
- aligned_u64 usec;
+ aligned_be64 sec;
+ aligned_be64 usec;
};
enum nfqnl_attr_type {
@@ -47,8 +47,8 @@ enum nfqnl_attr_type {
#define NFQA_MAX (__NFQA_MAX - 1)
struct nfqnl_msg_verdict_hdr {
- u_int32_t verdict;
- u_int32_t id;
+ __be32 verdict;
+ __be32 id;
};
@@ -63,7 +63,7 @@ enum nfqnl_msg_config_cmds {
struct nfqnl_msg_config_cmd {
u_int8_t command; /* nfqnl_msg_config_cmds */
u_int8_t _pad;
- u_int16_t pf; /* AF_xxx for PF_[UN]BIND */
+ __be16 pf; /* AF_xxx for PF_[UN]BIND */
};
enum nfqnl_config_mode {
@@ -73,7 +73,7 @@ enum nfqnl_config_mode {
};
struct nfqnl_msg_config_params {
- u_int32_t copy_range;
+ __be32 copy_range;
u_int8_t copy_mode; /* enum nfqnl_config_mode */
} __attribute__ ((packed));
@@ -82,6 +82,7 @@ enum nfqnl_attr_config {
NFQA_CFG_UNSPEC,
NFQA_CFG_CMD, /* nfqnl_msg_config_cmd */
NFQA_CFG_PARAMS, /* nfqnl_msg_config_params */
+ NFQA_CFG_QUEUE_MAXLEN, /* u_int32_t */
__NFQA_CFG_MAX
};
#define NFQA_CFG_MAX (__NFQA_CFG_MAX-1)
diff --git a/include/linux/netfilter/xt_NFLOG.h b/include/linux/netfilter/xt_NFLOG.h
new file mode 100644
index 000000000000..cdcd0ed58f7a
--- /dev/null
+++ b/include/linux/netfilter/xt_NFLOG.h
@@ -0,0 +1,18 @@
+#ifndef _XT_NFLOG_TARGET
+#define _XT_NFLOG_TARGET
+
+#define XT_NFLOG_DEFAULT_GROUP 0x1
+#define XT_NFLOG_DEFAULT_THRESHOLD 1
+
+#define XT_NFLOG_MASK 0x0
+
+struct xt_nflog_info {
+ u_int32_t len;
+ u_int16_t group;
+ u_int16_t threshold;
+ u_int16_t flags;
+ u_int16_t pad;
+ char prefix[64];
+};
+
+#endif /* _XT_NFLOG_TARGET */
diff --git a/include/linux/netfilter/xt_conntrack.h b/include/linux/netfilter/xt_conntrack.h
index 4c2d9945ca54..70b6f718cf4c 100644
--- a/include/linux/netfilter/xt_conntrack.h
+++ b/include/linux/netfilter/xt_conntrack.h
@@ -29,14 +29,14 @@
struct ip_conntrack_old_tuple
{
struct {
- __u32 ip;
+ __be32 ip;
union {
__u16 all;
} u;
} src;
struct {
- __u32 ip;
+ __be32 ip;
union {
__u16 all;
} u;
diff --git a/include/linux/netfilter/xt_hashlimit.h b/include/linux/netfilter/xt_hashlimit.h
new file mode 100644
index 000000000000..b4556b8edbfd
--- /dev/null
+++ b/include/linux/netfilter/xt_hashlimit.h
@@ -0,0 +1,40 @@
+#ifndef _XT_HASHLIMIT_H
+#define _XT_HASHLIMIT_H
+
+/* timings are in milliseconds. */
+#define XT_HASHLIMIT_SCALE 10000
+/* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490
+ seconds, or one every 59 hours. */
+
+/* details of this structure hidden by the implementation */
+struct xt_hashlimit_htable;
+
+#define XT_HASHLIMIT_HASH_DIP 0x0001
+#define XT_HASHLIMIT_HASH_DPT 0x0002
+#define XT_HASHLIMIT_HASH_SIP 0x0004
+#define XT_HASHLIMIT_HASH_SPT 0x0008
+
+struct hashlimit_cfg {
+ u_int32_t mode; /* bitmask of IPT_HASHLIMIT_HASH_* */
+ u_int32_t avg; /* Average secs between packets * scale */
+ u_int32_t burst; /* Period multiplier for upper limit. */
+
+ /* user specified */
+ u_int32_t size; /* how many buckets */
+ u_int32_t max; /* max number of entries */
+ u_int32_t gc_interval; /* gc interval */
+ u_int32_t expire; /* when do entries expire? */
+};
+
+struct xt_hashlimit_info {
+ char name [IFNAMSIZ]; /* name */
+ struct hashlimit_cfg cfg;
+ struct xt_hashlimit_htable *hinfo;
+
+ /* Used internally by the kernel */
+ union {
+ void *ptr;
+ struct xt_hashlimit_info *master;
+ } u;
+};
+#endif /*_XT_HASHLIMIT_H*/
diff --git a/include/linux/netfilter/xt_policy.h b/include/linux/netfilter/xt_policy.h
index a8132ec076fb..45654d359a68 100644
--- a/include/linux/netfilter/xt_policy.h
+++ b/include/linux/netfilter/xt_policy.h
@@ -39,7 +39,7 @@ struct xt_policy_elem
union xt_policy_addr smask;
union xt_policy_addr daddr;
union xt_policy_addr dmask;
- u_int32_t spi;
+ __be32 spi;
u_int32_t reqid;
u_int8_t proto;
u_int8_t mode;
diff --git a/include/linux/netfilter_bridge.h b/include/linux/netfilter_bridge.h
index 9a4dd11af86e..6c4613f8ad75 100644
--- a/include/linux/netfilter_bridge.h
+++ b/include/linux/netfilter_bridge.h
@@ -64,7 +64,7 @@ static inline int nf_bridge_pad(const struct sk_buff *skb)
struct bridge_skb_cb {
union {
- __u32 ipv4;
+ __be32 ipv4;
} daddr;
};
diff --git a/include/linux/netfilter_bridge/ebt_802_3.h b/include/linux/netfilter_bridge/ebt_802_3.h
index b9f712c14a0a..07f044ff1a6b 100644
--- a/include/linux/netfilter_bridge/ebt_802_3.h
+++ b/include/linux/netfilter_bridge/ebt_802_3.h
@@ -28,21 +28,21 @@ struct hdr_ui {
uint8_t ssap;
uint8_t ctrl;
uint8_t orig[3];
- uint16_t type;
+ __be16 type;
};
struct hdr_ni {
uint8_t dsap;
uint8_t ssap;
- uint16_t ctrl;
+ __be16 ctrl;
uint8_t orig[3];
- uint16_t type;
+ __be16 type;
};
struct ebt_802_3_hdr {
uint8_t daddr[6];
uint8_t saddr[6];
- uint16_t len;
+ __be16 len;
union {
struct hdr_ui ui;
struct hdr_ni ni;
@@ -61,7 +61,7 @@ static inline struct ebt_802_3_hdr *ebt_802_3_hdr(const struct sk_buff *skb)
struct ebt_802_3_info
{
uint8_t sap;
- uint16_t type;
+ __be16 type;
uint8_t bitmask;
uint8_t invflags;
};
diff --git a/include/linux/netfilter_bridge/ebt_among.h b/include/linux/netfilter_bridge/ebt_among.h
index 307c1fed8511..7654069233ca 100644
--- a/include/linux/netfilter_bridge/ebt_among.h
+++ b/include/linux/netfilter_bridge/ebt_among.h
@@ -32,7 +32,7 @@
struct ebt_mac_wormhash_tuple
{
uint32_t cmp[2];
- uint32_t ip;
+ __be32 ip;
};
struct ebt_mac_wormhash
diff --git a/include/linux/netfilter_bridge/ebt_arp.h b/include/linux/netfilter_bridge/ebt_arp.h
index 537ec6b487a2..97e4dbde1f89 100644
--- a/include/linux/netfilter_bridge/ebt_arp.h
+++ b/include/linux/netfilter_bridge/ebt_arp.h
@@ -14,13 +14,13 @@
struct ebt_arp_info
{
- uint16_t htype;
- uint16_t ptype;
- uint16_t opcode;
- uint32_t saddr;
- uint32_t smsk;
- uint32_t daddr;
- uint32_t dmsk;
+ __be16 htype;
+ __be16 ptype;
+ __be16 opcode;
+ __be32 saddr;
+ __be32 smsk;
+ __be32 daddr;
+ __be32 dmsk;
unsigned char smaddr[ETH_ALEN];
unsigned char smmsk[ETH_ALEN];
unsigned char dmaddr[ETH_ALEN];
diff --git a/include/linux/netfilter_bridge/ebt_ip.h b/include/linux/netfilter_bridge/ebt_ip.h
index 7247385cdcb1..d6847475bf2e 100644
--- a/include/linux/netfilter_bridge/ebt_ip.h
+++ b/include/linux/netfilter_bridge/ebt_ip.h
@@ -28,10 +28,10 @@
/* the same values are used for the invflags */
struct ebt_ip_info
{
- uint32_t saddr;
- uint32_t daddr;
- uint32_t smsk;
- uint32_t dmsk;
+ __be32 saddr;
+ __be32 daddr;
+ __be32 smsk;
+ __be32 dmsk;
uint8_t tos;
uint8_t protocol;
uint8_t bitmask;
diff --git a/include/linux/netfilter_bridge/ebt_nat.h b/include/linux/netfilter_bridge/ebt_nat.h
index 26fd90da4cd6..435b886a51aa 100644
--- a/include/linux/netfilter_bridge/ebt_nat.h
+++ b/include/linux/netfilter_bridge/ebt_nat.h
@@ -1,6 +1,7 @@
#ifndef __LINUX_BRIDGE_EBT_NAT_H
#define __LINUX_BRIDGE_EBT_NAT_H
+#define NAT_ARP_BIT (0x00000010)
struct ebt_nat_info
{
unsigned char mac[ETH_ALEN];
diff --git a/include/linux/netfilter_bridge/ebt_vlan.h b/include/linux/netfilter_bridge/ebt_vlan.h
index cb1fcc41565f..1d98be4031e7 100644
--- a/include/linux/netfilter_bridge/ebt_vlan.h
+++ b/include/linux/netfilter_bridge/ebt_vlan.h
@@ -10,7 +10,7 @@
struct ebt_vlan_info {
uint16_t id; /* VLAN ID {1-4095} */
uint8_t prio; /* VLAN User Priority {0-7} */
- uint16_t encap; /* VLAN Encapsulated frame code {0-65535} */
+ __be16 encap; /* VLAN Encapsulated frame code {0-65535} */
uint8_t bitmask; /* Args bitmask bit 1=1 - ID arg,
bit 2=1 User-Priority arg, bit 3=1 encap*/
uint8_t invflags; /* Inverse bitmask bit 1=1 - inversed ID arg,
diff --git a/include/linux/netfilter_bridge/ebtables.h b/include/linux/netfilter_bridge/ebtables.h
index b1a7cc90877b..94e0a7dc0cb2 100644
--- a/include/linux/netfilter_bridge/ebtables.h
+++ b/include/linux/netfilter_bridge/ebtables.h
@@ -26,6 +26,10 @@
#define EBT_CONTINUE -3
#define EBT_RETURN -4
#define NUM_STANDARD_TARGETS 4
+/* ebtables target modules store the verdict inside an int. We can
+ * reclaim a part of this int for backwards compatible extensions.
+ * The 4 lsb are more than enough to store the verdict. */
+#define EBT_VERDICT_BITS 0x0000000F
struct ebt_counter
{
@@ -42,6 +46,23 @@ struct ebt_replace
/* total size of the entries */
unsigned int entries_size;
/* start of the chains */
+ struct ebt_entries __user *hook_entry[NF_BR_NUMHOOKS];
+ /* nr of counters userspace expects back */
+ unsigned int num_counters;
+ /* where the kernel will put the old counters */
+ struct ebt_counter __user *counters;
+ char __user *entries;
+};
+
+struct ebt_replace_kernel
+{
+ char name[EBT_TABLE_MAXNAMELEN];
+ unsigned int valid_hooks;
+ /* nr of rules in the table */
+ unsigned int nentries;
+ /* total size of the entries */
+ unsigned int entries_size;
+ /* start of the chains */
struct ebt_entries *hook_entry[NF_BR_NUMHOOKS];
/* nr of counters userspace expects back */
unsigned int num_counters;
@@ -141,7 +162,7 @@ struct ebt_entry {
/* this needs to be the first field */
unsigned int bitmask;
unsigned int invflags;
- uint16_t ethproto;
+ __be16 ethproto;
/* the physical in-dev */
char in[IFNAMSIZ];
/* the logical in-dev */
@@ -251,7 +272,7 @@ struct ebt_table
{
struct list_head list;
char name[EBT_TABLE_MAXNAMELEN];
- struct ebt_replace *table;
+ struct ebt_replace_kernel *table;
unsigned int valid_hooks;
rwlock_t lock;
/* e.g. could be the table explicitly only allows certain
diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h
index 5b63a231a76b..5821eb5a0a3e 100644
--- a/include/linux/netfilter_ipv4.h
+++ b/include/linux/netfilter_ipv4.h
@@ -79,7 +79,7 @@ enum nf_ip_hook_priorities {
#ifdef __KERNEL__
extern int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type);
extern int ip_xfrm_me_harder(struct sk_buff **pskb);
-extern unsigned int nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
+extern __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
unsigned int dataoff, u_int8_t protocol);
#endif /*__KERNEL__*/
diff --git a/include/linux/netfilter_ipv4/Kbuild b/include/linux/netfilter_ipv4/Kbuild
index 591c1a809c00..180337801a86 100644
--- a/include/linux/netfilter_ipv4/Kbuild
+++ b/include/linux/netfilter_ipv4/Kbuild
@@ -1,6 +1,4 @@
header-y += ip_conntrack_helper.h
-header-y += ip_conntrack_helper_h323_asn1.h
-header-y += ip_conntrack_helper_h323_types.h
header-y += ip_conntrack_protocol.h
header-y += ip_conntrack_sctp.h
header-y += ip_conntrack_tcp.h
diff --git a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h
index 64e868034c4a..61da56941dce 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack.h
@@ -277,7 +277,7 @@ extern struct ip_conntrack_expect *
__ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple);
extern struct ip_conntrack_expect *
-ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple);
+ip_conntrack_expect_find_get(const struct ip_conntrack_tuple *tuple);
extern struct ip_conntrack_tuple_hash *
__ip_conntrack_find(const struct ip_conntrack_tuple *tuple,
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_ftp.h b/include/linux/netfilter_ipv4/ip_conntrack_ftp.h
index 63811934de4d..2129fc3972ac 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_ftp.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_ftp.h
@@ -1,6 +1,44 @@
#ifndef _IP_CONNTRACK_FTP_H
#define _IP_CONNTRACK_FTP_H
+/* FTP tracking. */
-#include <linux/netfilter/nf_conntrack_ftp.h>
+/* This enum is exposed to userspace */
+enum ip_ct_ftp_type
+{
+ /* PORT command from client */
+ IP_CT_FTP_PORT,
+ /* PASV response from server */
+ IP_CT_FTP_PASV,
+ /* EPRT command from client */
+ IP_CT_FTP_EPRT,
+ /* EPSV response from server */
+ IP_CT_FTP_EPSV,
+};
+
+#ifdef __KERNEL__
+
+#define FTP_PORT 21
+
+#define NUM_SEQ_TO_REMEMBER 2
+/* This structure exists only once per master */
+struct ip_ct_ftp_master {
+ /* Valid seq positions for cmd matching after newline */
+ u_int32_t seq_aft_nl[IP_CT_DIR_MAX][NUM_SEQ_TO_REMEMBER];
+ /* 0 means seq_match_aft_nl not set */
+ int seq_aft_nl_num[IP_CT_DIR_MAX];
+};
+
+struct ip_conntrack_expect;
+
+/* For NAT to hook in when we find a packet which describes what other
+ * connection we should expect. */
+extern unsigned int (*ip_nat_ftp_hook)(struct sk_buff **pskb,
+ enum ip_conntrack_info ctinfo,
+ enum ip_ct_ftp_type type,
+ unsigned int matchoff,
+ unsigned int matchlen,
+ struct ip_conntrack_expect *exp,
+ u32 *seq);
+#endif /* __KERNEL__ */
#endif /* _IP_CONNTRACK_FTP_H */
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_h323.h b/include/linux/netfilter_ipv4/ip_conntrack_h323.h
index 943cc6a4871d..18f769818f4e 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_h323.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_h323.h
@@ -3,7 +3,7 @@
#ifdef __KERNEL__
-#include <linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h>
+#include <linux/netfilter/nf_conntrack_h323_asn1.h>
#define RAS_PORT 1719
#define Q931_PORT 1720
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h b/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h
index 1d853aa873eb..e371e0fc1672 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h
@@ -102,11 +102,11 @@ static inline __be32 *gre_key(struct gre_hdr *greh)
}
/* get pointer ot gre csum, if present */
-static inline u_int16_t *gre_csum(struct gre_hdr *greh)
+static inline __sum16 *gre_csum(struct gre_hdr *greh)
{
if (!greh->csum)
return NULL;
- return (u_int16_t *) (greh+sizeof(*greh));
+ return (__sum16 *) (greh+sizeof(*greh));
}
#endif /* __KERNEL__ */
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_sip.h b/include/linux/netfilter_ipv4/ip_conntrack_sip.h
index 913dad66c0fb..bef6c646defa 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_sip.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_sip.h
@@ -5,23 +5,18 @@
#define SIP_PORT 5060
#define SIP_TIMEOUT 3600
-#define POS_VIA 0
-#define POS_CONTACT 1
-#define POS_CONTENT 2
-#define POS_MEDIA 3
-#define POS_OWNER 4
-#define POS_CONNECTION 5
-#define POS_REQ_HEADER 6
-#define POS_SDP_HEADER 7
-
-struct sip_header_nfo {
- const char *lname;
- const char *sname;
- const char *ln_str;
- size_t lnlen;
- size_t snlen;
- size_t ln_strlen;
- int (*match_len)(const char *, const char *, int *);
+enum sip_header_pos {
+ POS_REG_REQ_URI,
+ POS_REQ_URI,
+ POS_FROM,
+ POS_TO,
+ POS_VIA,
+ POS_CONTACT,
+ POS_CONTENT,
+ POS_MEDIA,
+ POS_OWNER,
+ POS_CONNECTION,
+ POS_SDP_HEADER,
};
extern unsigned int (*ip_nat_sip_hook)(struct sk_buff **pskb,
@@ -36,9 +31,10 @@ extern unsigned int (*ip_nat_sdp_hook)(struct sk_buff **pskb,
extern int ct_sip_get_info(const char *dptr, size_t dlen,
unsigned int *matchoff,
unsigned int *matchlen,
- struct sip_header_nfo *hnfo);
+ enum sip_header_pos pos);
extern int ct_sip_lnlen(const char *line, const char *limit);
extern const char *ct_sip_search(const char *needle, const char *haystack,
- size_t needle_len, size_t haystack_len);
+ size_t needle_len, size_t haystack_len,
+ int case_sensitive);
#endif /* __KERNEL__ */
#endif /* __IP_CONNTRACK_SIP_H__ */
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_tftp.h b/include/linux/netfilter_ipv4/ip_conntrack_tftp.h
index cde9729aa173..a404fc0abf0e 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_tftp.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_tftp.h
@@ -4,7 +4,7 @@
#define TFTP_PORT 69
struct tftphdr {
- u_int16_t opcode;
+ __be16 opcode;
};
#define TFTP_OPCODE_READ 1
diff --git a/include/linux/netfilter_ipv4/ipt_LOG.h b/include/linux/netfilter_ipv4/ipt_LOG.h
index 892f9a33fea8..90fa6525ef9c 100644
--- a/include/linux/netfilter_ipv4/ipt_LOG.h
+++ b/include/linux/netfilter_ipv4/ipt_LOG.h
@@ -6,7 +6,7 @@
#define IPT_LOG_TCPOPT 0x02 /* Log TCP options */
#define IPT_LOG_IPOPT 0x04 /* Log IP options */
#define IPT_LOG_UID 0x08 /* Log UID owning local socket */
-#define IPT_LOG_NFLOG 0x10 /* Log using nf_log backend */
+#define IPT_LOG_NFLOG 0x10 /* Unsupported, don't reuse */
#define IPT_LOG_MASK 0x1f
struct ipt_log_info {
diff --git a/include/linux/netfilter_ipv4/ipt_hashlimit.h b/include/linux/netfilter_ipv4/ipt_hashlimit.h
index ac2cb64ecd76..5662120a3d7b 100644
--- a/include/linux/netfilter_ipv4/ipt_hashlimit.h
+++ b/include/linux/netfilter_ipv4/ipt_hashlimit.h
@@ -1,40 +1,14 @@
#ifndef _IPT_HASHLIMIT_H
#define _IPT_HASHLIMIT_H
-/* timings are in milliseconds. */
-#define IPT_HASHLIMIT_SCALE 10000
-/* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490
- seconds, or one every 59 hours. */
+#include <linux/netfilter/xt_hashlimit.h>
-/* details of this structure hidden by the implementation */
-struct ipt_hashlimit_htable;
+#define IPT_HASHLIMIT_SCALE XT_HASHLIMIT_SCALE
+#define IPT_HASHLIMIT_HASH_DIP XT_HASHLIMIT_HASH_DIP
+#define IPT_HASHLIMIT_HASH_DPT XT_HASHLIMIT_HASH_DPT
+#define IPT_HASHLIMIT_HASH_SIP XT_HASHLIMIT_HASH_SIP
+#define IPT_HASHLIMIT_HASH_SPT XT_HASHLIMIT_HASH_SPT
-#define IPT_HASHLIMIT_HASH_DIP 0x0001
-#define IPT_HASHLIMIT_HASH_DPT 0x0002
-#define IPT_HASHLIMIT_HASH_SIP 0x0004
-#define IPT_HASHLIMIT_HASH_SPT 0x0008
+#define ipt_hashlimit_info xt_hashlimit_info
-struct hashlimit_cfg {
- u_int32_t mode; /* bitmask of IPT_HASHLIMIT_HASH_* */
- u_int32_t avg; /* Average secs between packets * scale */
- u_int32_t burst; /* Period multiplier for upper limit. */
-
- /* user specified */
- u_int32_t size; /* how many buckets */
- u_int32_t max; /* max number of entries */
- u_int32_t gc_interval; /* gc interval */
- u_int32_t expire; /* when do entries expire? */
-};
-
-struct ipt_hashlimit_info {
- char name [IFNAMSIZ]; /* name */
- struct hashlimit_cfg cfg;
- struct ipt_hashlimit_htable *hinfo;
-
- /* Used internally by the kernel */
- union {
- void *ptr;
- struct ipt_hashlimit_info *master;
- } u;
-};
-#endif /*_IPT_HASHLIMIT_H*/
+#endif /* _IPT_HASHLIMIT_H */
diff --git a/include/linux/netfilter_ipv6.h b/include/linux/netfilter_ipv6.h
index d97e268cdfe5..ab81a6dc94ea 100644
--- a/include/linux/netfilter_ipv6.h
+++ b/include/linux/netfilter_ipv6.h
@@ -74,7 +74,7 @@ enum nf_ip6_hook_priorities {
#ifdef CONFIG_NETFILTER
extern int ip6_route_me_harder(struct sk_buff *skb);
-extern unsigned int nf_ip6_checksum(struct sk_buff *skb, unsigned int hook,
+extern __sum16 nf_ip6_checksum(struct sk_buff *skb, unsigned int hook,
unsigned int dataoff, u_int8_t protocol);
extern int ipv6_netfilter_init(void);
diff --git a/include/linux/netfilter_ipv6/ip6t_LOG.h b/include/linux/netfilter_ipv6/ip6t_LOG.h
index 060c1a1c6c60..0d0119b0458c 100644
--- a/include/linux/netfilter_ipv6/ip6t_LOG.h
+++ b/include/linux/netfilter_ipv6/ip6t_LOG.h
@@ -6,7 +6,7 @@
#define IP6T_LOG_TCPOPT 0x02 /* Log TCP options */
#define IP6T_LOG_IPOPT 0x04 /* Log IP options */
#define IP6T_LOG_UID 0x08 /* Log UID owning local socket */
-#define IP6T_LOG_NFLOG 0x10 /* Log using nf_log backend */
+#define IP6T_LOG_NFLOG 0x10 /* Unsupported, don't use */
#define IP6T_LOG_MASK 0x1f
struct ip6t_log_info {
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index 66411622e06e..b3b9b609ee89 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -141,7 +141,6 @@ struct netlink_skb_parms
{
struct ucred creds; /* Skb credentials */
__u32 pid;
- __u32 dst_pid;
__u32 dst_group;
kernel_cap_t eff_cap;
__u32 loginuid; /* Login (audit) uid */
@@ -174,6 +173,7 @@ int netlink_sendskb(struct sock *sk, struct sk_buff *skb, int protocol);
*/
#define NLMSG_GOODORDER 0
#define NLMSG_GOODSIZE (SKB_MAX_ORDER(0, NLMSG_GOODORDER))
+#define NLMSG_DEFAULT_SIZE (NLMSG_GOODSIZE - NLMSG_HDRLEN)
struct netlink_callback
diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h
index 1efe60c5c00c..2cc9867b1626 100644
--- a/include/linux/netpoll.h
+++ b/include/linux/netpoll.h
@@ -12,26 +12,27 @@
#include <linux/rcupdate.h>
#include <linux/list.h>
-struct netpoll;
-
struct netpoll {
struct net_device *dev;
- char dev_name[16], *name;
+ char dev_name[IFNAMSIZ];
+ const char *name;
void (*rx_hook)(struct netpoll *, int, char *, int);
- void (*drop)(struct sk_buff *skb);
+
u32 local_ip, remote_ip;
u16 local_port, remote_port;
- unsigned char local_mac[6], remote_mac[6];
+ u8 local_mac[ETH_ALEN], remote_mac[ETH_ALEN];
};
struct netpoll_info {
+ atomic_t refcnt;
spinlock_t poll_lock;
int poll_owner;
- int tries;
int rx_flags;
spinlock_t rx_lock;
struct netpoll *rx_np; /* netpoll that registered an rx_hook */
struct sk_buff_head arp_tx; /* list of arp requests to reply to */
+ struct sk_buff_head txq;
+ struct work_struct tx_work;
};
void netpoll_poll(struct netpoll *np);
@@ -42,7 +43,7 @@ int netpoll_trap(void);
void netpoll_set_trap(int trap);
void netpoll_cleanup(struct netpoll *np);
int __netpoll_rx(struct sk_buff *skb);
-void netpoll_queue(struct sk_buff *skb);
+
#ifdef CONFIG_NETPOLL
static inline int netpoll_rx(struct sk_buff *skb)
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 45228c1a1195..625ffea98561 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -318,7 +318,7 @@ extern void put_nfs_open_context(struct nfs_open_context *ctx);
extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, int mode);
/* linux/net/ipv4/ipconfig.c: trims ip addr off front of name, too. */
-extern u32 root_nfs_parse_addr(char *name); /*__init*/
+extern __be32 root_nfs_parse_addr(char *name); /*__init*/
static inline void nfs_fattr_init(struct nfs_fattr *fattr)
{
diff --git a/include/linux/nsproxy.h b/include/linux/nsproxy.h
index f6baecdeecd6..971d1c6dfc4b 100644
--- a/include/linux/nsproxy.h
+++ b/include/linux/nsproxy.h
@@ -45,8 +45,10 @@ static inline void exit_task_namespaces(struct task_struct *p)
{
struct nsproxy *ns = p->nsproxy;
if (ns) {
- put_nsproxy(ns);
+ task_lock(p);
p->nsproxy = NULL;
+ task_unlock(p);
+ put_nsproxy(ns);
}
}
#endif
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 09be0f81b27b..01c707261f9c 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -51,6 +51,7 @@
#include <linux/list.h>
#include <linux/compiler.h>
#include <linux/errno.h>
+#include <asm/atomic.h>
#include <linux/device.h>
/* File state for mmap()s on /proc/bus/pci/X/Y */
@@ -159,7 +160,6 @@ struct pci_dev {
unsigned int transparent:1; /* Transparent PCI bridge */
unsigned int multifunction:1;/* Part of multi-function device */
/* keep track of device state */
- unsigned int is_enabled:1; /* pci_enable_device has been called */
unsigned int is_busmaster:1; /* device is busmaster */
unsigned int no_msi:1; /* device may not use msi */
unsigned int no_d1d2:1; /* only allow d0 or d3 */
@@ -167,6 +167,7 @@ struct pci_dev {
unsigned int broken_parity_status:1; /* Device generates false positive parity */
unsigned int msi_enabled:1;
unsigned int msix_enabled:1;
+ atomic_t enable_cnt; /* pci_enable_device has been called */
u32 saved_config_space[16]; /* config space saved at suspend time */
struct hlist_head saved_cap_space;
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index fa4e1d799782..c09da1e30c54 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1213,6 +1213,10 @@
#define PCI_DEVICE_ID_NVIDIA_NVENET_21 0x0451
#define PCI_DEVICE_ID_NVIDIA_NVENET_22 0x0452
#define PCI_DEVICE_ID_NVIDIA_NVENET_23 0x0453
+#define PCI_DEVICE_ID_NVIDIA_NVENET_24 0x054C
+#define PCI_DEVICE_ID_NVIDIA_NVENET_25 0x054D
+#define PCI_DEVICE_ID_NVIDIA_NVENET_26 0x054E
+#define PCI_DEVICE_ID_NVIDIA_NVENET_27 0x054F
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE 0x0560
#define PCI_VENDOR_ID_IMS 0x10e0
@@ -1893,6 +1897,7 @@
#define PCI_VENDOR_ID_BROADCOM 0x14e4
#define PCI_DEVICE_ID_TIGON3_5752 0x1600
#define PCI_DEVICE_ID_TIGON3_5752M 0x1601
+#define PCI_DEVICE_ID_NX2_5709 0x1639
#define PCI_DEVICE_ID_TIGON3_5700 0x1644
#define PCI_DEVICE_ID_TIGON3_5701 0x1645
#define PCI_DEVICE_ID_TIGON3_5702 0x1646
@@ -2211,6 +2216,13 @@
#define PCI_DEVICE_ID_INTEL_ICH8_4 0x2815
#define PCI_DEVICE_ID_INTEL_ICH8_5 0x283e
#define PCI_DEVICE_ID_INTEL_ICH8_6 0x2850
+#define PCI_DEVICE_ID_INTEL_ICH9_0 0x2910
+#define PCI_DEVICE_ID_INTEL_ICH9_1 0x2911
+#define PCI_DEVICE_ID_INTEL_ICH9_2 0x2912
+#define PCI_DEVICE_ID_INTEL_ICH9_3 0x2913
+#define PCI_DEVICE_ID_INTEL_ICH9_4 0x2914
+#define PCI_DEVICE_ID_INTEL_ICH9_5 0x2915
+#define PCI_DEVICE_ID_INTEL_ICH9_6 0x2930
#define PCI_DEVICE_ID_INTEL_82855PM_HB 0x3340
#define PCI_DEVICE_ID_INTEL_82830_HB 0x3575
#define PCI_DEVICE_ID_INTEL_82830_CGC 0x3577
diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h
index c321316f1bc7..064b1dc71c22 100644
--- a/include/linux/pci_regs.h
+++ b/include/linux/pci_regs.h
@@ -292,6 +292,12 @@
#define PCI_MSI_DATA_64 12 /* 16 bits of data for 64-bit devices */
#define PCI_MSI_MASK_BIT 16 /* Mask bits register */
+/* MSI-X registers (these are at offset PCI_MSI_FLAGS) */
+#define PCI_MSIX_FLAGS_QSIZE 0x7FF
+#define PCI_MSIX_FLAGS_ENABLE (1 << 15)
+#define PCI_MSIX_FLAGS_BIRMASK (7 << 0)
+#define PCI_MSIX_FLAGS_BITMASK (1 << 0)
+
/* CompactPCI Hotswap Register */
#define PCI_CHSWP_CSR 2 /* Control and Status Register */
diff --git a/include/linux/pfkeyv2.h b/include/linux/pfkeyv2.h
index d5dd471da225..0f0b880c4280 100644
--- a/include/linux/pfkeyv2.h
+++ b/include/linux/pfkeyv2.h
@@ -32,7 +32,7 @@ struct sadb_ext {
struct sadb_sa {
uint16_t sadb_sa_len;
uint16_t sadb_sa_exttype;
- uint32_t sadb_sa_spi;
+ __be32 sadb_sa_spi;
uint8_t sadb_sa_replay;
uint8_t sadb_sa_state;
uint8_t sadb_sa_auth;
@@ -211,7 +211,7 @@ struct sadb_x_nat_t_type {
struct sadb_x_nat_t_port {
uint16_t sadb_x_nat_t_port_len;
uint16_t sadb_x_nat_t_port_exttype;
- uint16_t sadb_x_nat_t_port_port;
+ __be16 sadb_x_nat_t_port_port;
uint16_t sadb_x_nat_t_port_reserved;
} __attribute__((packed));
/* sizeof(struct sadb_x_nat_t_port) == 8 */
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 9447a57ee8a9..edd4c88ca7d8 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -20,6 +20,10 @@
#include <linux/spinlock.h>
#include <linux/device.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/timer.h>
+#include <linux/workqueue.h>
#define PHY_BASIC_FEATURES (SUPPORTED_10baseT_Half | \
SUPPORTED_10baseT_Full | \
@@ -43,15 +47,26 @@
#define PHY_HAS_INTERRUPT 0x00000001
#define PHY_HAS_MAGICANEG 0x00000002
+/* Interface Mode definitions */
+typedef enum {
+ PHY_INTERFACE_MODE_MII,
+ PHY_INTERFACE_MODE_GMII,
+ PHY_INTERFACE_MODE_SGMII,
+ PHY_INTERFACE_MODE_TBI,
+ PHY_INTERFACE_MODE_RMII,
+ PHY_INTERFACE_MODE_RGMII,
+ PHY_INTERFACE_MODE_RTBI
+} phy_interface_t;
+
#define MII_BUS_MAX 4
-#define PHY_INIT_TIMEOUT 100000
+#define PHY_INIT_TIMEOUT 100000
#define PHY_STATE_TIME 1
#define PHY_FORCE_TIMEOUT 10
#define PHY_AN_TIMEOUT 10
-#define PHY_MAX_ADDR 32
+#define PHY_MAX_ADDR 32
/* Used when trying to connect to a specific phy (mii bus id:phy device id) */
#define PHY_ID_FMT "%x:%02x"
@@ -83,8 +98,8 @@ struct mii_bus {
int *irq;
};
-#define PHY_INTERRUPT_DISABLED 0x0
-#define PHY_INTERRUPT_ENABLED 0x80000000
+#define PHY_INTERRUPT_DISABLED 0x0
+#define PHY_INTERRUPT_ENABLED 0x80000000
/* PHY state machine states:
*
@@ -226,6 +241,8 @@ struct phy_device {
u32 dev_flags;
+ phy_interface_t interface;
+
/* Bus address of the PHY (0-32) */
int addr;
@@ -341,9 +358,10 @@ struct phy_device* get_phy_device(struct mii_bus *bus, int addr);
int phy_clear_interrupt(struct phy_device *phydev);
int phy_config_interrupt(struct phy_device *phydev, u32 interrupts);
struct phy_device * phy_attach(struct net_device *dev,
- const char *phy_id, u32 flags);
+ const char *phy_id, u32 flags, phy_interface_t interface);
struct phy_device * phy_connect(struct net_device *dev, const char *phy_id,
- void (*handler)(struct net_device *), u32 flags);
+ void (*handler)(struct net_device *), u32 flags,
+ phy_interface_t interface);
void phy_disconnect(struct phy_device *phydev);
void phy_detach(struct phy_device *phydev);
void phy_start(struct phy_device *phydev);
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index 29cd6dee13db..20f47b81d3fa 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -58,6 +58,12 @@ struct platform_driver {
extern int platform_driver_register(struct platform_driver *);
extern void platform_driver_unregister(struct platform_driver *);
+/* non-hotpluggable platform devices may use this so that probe() and
+ * its support may live in __init sections, conserving runtime memory.
+ */
+extern int platform_driver_probe(struct platform_driver *driver,
+ int (*probe)(struct platform_device *));
+
#define platform_get_drvdata(_dev) dev_get_drvdata(&(_dev)->dev)
#define platform_set_drvdata(_dev,data) dev_set_drvdata(&(_dev)->dev, (data))
diff --git a/include/linux/random.h b/include/linux/random.h
index 0248b30e306d..01ad71033d65 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -51,16 +51,16 @@ extern void add_interrupt_randomness(int irq);
extern void get_random_bytes(void *buf, int nbytes);
void generate_random_uuid(unsigned char uuid_out[16]);
-extern __u32 secure_ip_id(__u32 daddr);
-extern u32 secure_ipv4_port_ephemeral(__u32 saddr, __u32 daddr, __u16 dport);
-extern u32 secure_ipv6_port_ephemeral(const __u32 *saddr, const __u32 *daddr,
- __u16 dport);
-extern __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
- __u16 sport, __u16 dport);
-extern __u32 secure_tcpv6_sequence_number(__u32 *saddr, __u32 *daddr,
- __u16 sport, __u16 dport);
-extern u64 secure_dccp_sequence_number(__u32 saddr, __u32 daddr,
- __u16 sport, __u16 dport);
+extern __u32 secure_ip_id(__be32 daddr);
+extern u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport);
+extern u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
+ __be16 dport);
+extern __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
+ __be16 sport, __be16 dport);
+extern __u32 secure_tcpv6_sequence_number(__be32 *saddr, __be32 *daddr,
+ __be16 sport, __be16 dport);
+extern u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
+ __be16 sport, __be16 dport);
#ifndef MODULE
extern struct file_operations random_fops, urandom_fops;
diff --git a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h
index 6610103f23e1..3a28742d86f9 100644
--- a/include/linux/reiserfs_fs_sb.h
+++ b/include/linux/reiserfs_fs_sb.h
@@ -430,7 +430,7 @@ enum reiserfs_mount_options {
/* -o hash={tea, rupasov, r5, detect} is meant for properly mounting
** reiserfs disks from 3.5.19 or earlier. 99% of the time, this option
** is not required. If the normal autodection code can't determine which
-** hash to use (because both hases had the same value for a file)
+** hash to use (because both hashes had the same value for a file)
** use this option to force a specific hash. It won't allow you to override
** the existing hash on the FS, so if you have a tea hash disk, and mount
** with -o hash=rupasov, the mount will fail.
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 3a18addaed4c..493297acdae8 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -81,8 +81,6 @@ enum {
RTM_NEWPREFIX = 52,
#define RTM_NEWPREFIX RTM_NEWPREFIX
- RTM_GETPREFIX = 54,
-#define RTM_GETPREFIX RTM_GETPREFIX
RTM_GETMULTICAST = 58,
#define RTM_GETMULTICAST RTM_GETMULTICAST
@@ -587,6 +585,9 @@ extern int rtnl_notify(struct sk_buff *skb, u32 pid, u32 group,
struct nlmsghdr *nlh, gfp_t flags);
extern void rtnl_set_sk_err(u32 group, int error);
extern int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics);
+extern int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst,
+ u32 id, u32 ts, u32 tsage, long expires,
+ u32 error);
extern void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data);
diff --git a/include/linux/sctp.h b/include/linux/sctp.h
index 6ec66dec29f7..35108fe7a686 100644
--- a/include/linux/sctp.h
+++ b/include/linux/sctp.h
@@ -57,17 +57,17 @@
/* Section 3.1. SCTP Common Header Format */
typedef struct sctphdr {
- __u16 source;
- __u16 dest;
- __u32 vtag;
- __u32 checksum;
+ __be16 source;
+ __be16 dest;
+ __be32 vtag;
+ __be32 checksum;
} __attribute__((packed)) sctp_sctphdr_t;
/* Section 3.2. Chunk Field Descriptions. */
typedef struct sctp_chunkhdr {
__u8 type;
__u8 flags;
- __u16 length;
+ __be16 length;
} __attribute__((packed)) sctp_chunkhdr_t;
@@ -153,8 +153,8 @@ enum { SCTP_CHUNK_FLAG_T = 0x01 };
*/
typedef struct sctp_paramhdr {
- __u16 type;
- __u16 length;
+ __be16 type;
+ __be16 length;
} __attribute__((packed)) sctp_paramhdr_t;
typedef enum {
@@ -203,10 +203,10 @@ enum { SCTP_PARAM_ACTION_MASK = __constant_htons(0xc000), };
/* RFC 2960 Section 3.3.1 Payload Data (DATA) (0) */
typedef struct sctp_datahdr {
- __u32 tsn;
- __u16 stream;
- __u16 ssn;
- __u32 ppid;
+ __be32 tsn;
+ __be16 stream;
+ __be16 ssn;
+ __be32 ppid;
__u8 payload[0];
} __attribute__((packed)) sctp_datahdr_t;
@@ -232,11 +232,11 @@ enum { SCTP_DATA_FRAG_MASK = 0x03, };
* endpoints.
*/
typedef struct sctp_inithdr {
- __u32 init_tag;
- __u32 a_rwnd;
- __u16 num_outbound_streams;
- __u16 num_inbound_streams;
- __u32 initial_tsn;
+ __be32 init_tag;
+ __be32 a_rwnd;
+ __be16 num_outbound_streams;
+ __be16 num_inbound_streams;
+ __be32 initial_tsn;
__u8 params[0];
} __attribute__((packed)) sctp_inithdr_t;
@@ -261,7 +261,7 @@ typedef struct sctp_ipv6addr_param {
/* Section 3.3.2.1 Cookie Preservative (9) */
typedef struct sctp_cookie_preserve_param {
sctp_paramhdr_t param_hdr;
- uint32_t lifespan_increment;
+ __be32 lifespan_increment;
} __attribute__((packed)) sctp_cookie_preserve_param_t;
/* Section 3.3.2.1 Host Name Address (11) */
@@ -273,7 +273,7 @@ typedef struct sctp_hostname_param {
/* Section 3.3.2.1 Supported Address Types (12) */
typedef struct sctp_supported_addrs_param {
sctp_paramhdr_t param_hdr;
- uint16_t types[0];
+ __be16 types[0];
} __attribute__((packed)) sctp_supported_addrs_param_t;
/* Appendix A. ECN Capable (32768) */
@@ -284,7 +284,7 @@ typedef struct sctp_ecn_capable_param {
/* ADDIP Section 3.2.6 Adaption Layer Indication */
typedef struct sctp_adaption_ind_param {
struct sctp_paramhdr param_hdr;
- __u32 adaption_ind;
+ __be32 adaption_ind;
} __attribute__((packed)) sctp_adaption_ind_param_t;
/* RFC 2960. Section 3.3.3 Initiation Acknowledgement (INIT ACK) (2):
@@ -316,11 +316,11 @@ typedef struct sctp_unrecognized_param {
*/
typedef struct sctp_gap_ack_block {
- __u16 start;
- __u16 end;
+ __be16 start;
+ __be16 end;
} __attribute__((packed)) sctp_gap_ack_block_t;
-typedef uint32_t sctp_dup_tsn_t;
+typedef __be32 sctp_dup_tsn_t;
typedef union {
sctp_gap_ack_block_t gab;
@@ -328,10 +328,10 @@ typedef union {
} sctp_sack_variable_t;
typedef struct sctp_sackhdr {
- __u32 cum_tsn_ack;
- __u32 a_rwnd;
- __u16 num_gap_ack_blocks;
- __u16 num_dup_tsns;
+ __be32 cum_tsn_ack;
+ __be32 a_rwnd;
+ __be16 num_gap_ack_blocks;
+ __be16 num_dup_tsns;
sctp_sack_variable_t variable[0];
} __attribute__((packed)) sctp_sackhdr_t;
@@ -371,7 +371,7 @@ typedef struct sctp_abort_chunk {
* and the highest consecutive acking value.
*/
typedef struct sctp_shutdownhdr {
- __u32 cum_tsn_ack;
+ __be32 cum_tsn_ack;
} __attribute__((packed)) sctp_shutdownhdr_t;
struct sctp_shutdown_chunk_t {
@@ -382,8 +382,8 @@ struct sctp_shutdown_chunk_t {
/* RFC 2960. Section 3.3.10 Operation Error (ERROR) (9) */
typedef struct sctp_errhdr {
- __u16 cause;
- __u16 length;
+ __be16 cause;
+ __be16 length;
__u8 variable[0];
} __attribute__((packed)) sctp_errhdr_t;
@@ -462,7 +462,7 @@ typedef enum {
* Explicit Congestion Notification Echo (ECNE) (12)
*/
typedef struct sctp_ecnehdr {
- __u32 lowest_tsn;
+ __be32 lowest_tsn;
} sctp_ecnehdr_t;
typedef struct sctp_ecne_chunk {
@@ -474,7 +474,7 @@ typedef struct sctp_ecne_chunk {
* Congestion Window Reduced (CWR) (13)
*/
typedef struct sctp_cwrhdr {
- __u32 lowest_tsn;
+ __be32 lowest_tsn;
} sctp_cwrhdr_t;
typedef struct sctp_cwr_chunk {
@@ -529,12 +529,12 @@ typedef struct sctp_cwr_chunk {
* chunks this field MUST be filled in.
*/
struct sctp_fwdtsn_skip {
- __u16 stream;
- __u16 ssn;
+ __be16 stream;
+ __be16 ssn;
} __attribute__((packed));
struct sctp_fwdtsn_hdr {
- __u32 new_cum_tsn;
+ __be32 new_cum_tsn;
struct sctp_fwdtsn_skip skip[0];
} __attribute((packed));
@@ -578,11 +578,11 @@ struct sctp_fwdtsn_chunk {
*/
typedef struct sctp_addip_param {
sctp_paramhdr_t param_hdr;
- __u32 crr_id;
+ __be32 crr_id;
} __attribute__((packed)) sctp_addip_param_t;
typedef struct sctp_addiphdr {
- __u32 serial;
+ __be32 serial;
__u8 params[0];
} __attribute__((packed)) sctp_addiphdr_t;
diff --git a/include/linux/security.h b/include/linux/security.h
index b200b9856f32..83cdefae9931 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -826,6 +826,8 @@ struct request_sock;
* Sets the openreq's sid to socket's sid with MLS portion taken from peer sid.
* @inet_csk_clone:
* Sets the new child socket's sid to the openreq sid.
+ * @inet_conn_established:
+ * Sets the connection's peersid to the secmark on skb.
* @req_classify_flow:
* Sets the flow's sid to the openreq sid.
*
@@ -836,10 +838,8 @@ struct request_sock;
* used by the XFRM system.
* @sec_ctx contains the security context information being provided by
* the user-level policy update program (e.g., setkey).
- * @sk refers to the sock from which to derive the security context.
* Allocate a security structure to the xp->security field; the security
- * field is initialized to NULL when the xfrm_policy is allocated. Only
- * one of sec_ctx or sock can be specified.
+ * field is initialized to NULL when the xfrm_policy is allocated.
* Return 0 if operation was successful (memory to allocate, legal context)
* @xfrm_policy_clone_security:
* @old contains an existing xfrm_policy in the SPD.
@@ -858,9 +858,6 @@ struct request_sock;
* Database by the XFRM system.
* @sec_ctx contains the security context information being provided by
* the user-level SA generation program (e.g., setkey or racoon).
- * @polsec contains the security context information associated with a xfrm
- * policy rule from which to take the base context. polsec must be NULL
- * when sec_ctx is specified.
* @secid contains the secid from which to take the mls portion of the context.
* Allocate a security structure to the x->security field; the security
* field is initialized to NULL when the xfrm_state is allocated. Set the
@@ -889,11 +886,6 @@ struct request_sock;
* @xp contains the policy to check for a match.
* @fl contains the flow to check for a match.
* Return 1 if there is a match.
- * @xfrm_flow_state_match:
- * @fl contains the flow key to match.
- * @xfrm points to the xfrm_state to match.
- * @xp points to the xfrm_policy to match.
- * Return 1 if there is a match.
* @xfrm_decode_session:
* @skb points to skb to decode.
* @secid points to the flow key secid to set.
@@ -1373,25 +1365,24 @@ struct security_operations {
int (*inet_conn_request)(struct sock *sk, struct sk_buff *skb,
struct request_sock *req);
void (*inet_csk_clone)(struct sock *newsk, const struct request_sock *req);
+ void (*inet_conn_established)(struct sock *sk, struct sk_buff *skb);
void (*req_classify_flow)(const struct request_sock *req, struct flowi *fl);
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
int (*xfrm_policy_alloc_security) (struct xfrm_policy *xp,
- struct xfrm_user_sec_ctx *sec_ctx, struct sock *sk);
+ struct xfrm_user_sec_ctx *sec_ctx);
int (*xfrm_policy_clone_security) (struct xfrm_policy *old, struct xfrm_policy *new);
void (*xfrm_policy_free_security) (struct xfrm_policy *xp);
int (*xfrm_policy_delete_security) (struct xfrm_policy *xp);
int (*xfrm_state_alloc_security) (struct xfrm_state *x,
- struct xfrm_user_sec_ctx *sec_ctx, struct xfrm_sec_ctx *polsec,
+ struct xfrm_user_sec_ctx *sec_ctx,
u32 secid);
void (*xfrm_state_free_security) (struct xfrm_state *x);
int (*xfrm_state_delete_security) (struct xfrm_state *x);
int (*xfrm_policy_lookup)(struct xfrm_policy *xp, u32 fl_secid, u8 dir);
int (*xfrm_state_pol_flow_match)(struct xfrm_state *x,
struct xfrm_policy *xp, struct flowi *fl);
- int (*xfrm_flow_state_match)(struct flowi *fl, struct xfrm_state *xfrm,
- struct xfrm_policy *xp);
int (*xfrm_decode_session)(struct sk_buff *skb, u32 *secid, int ckall);
#endif /* CONFIG_SECURITY_NETWORK_XFRM */
@@ -2966,9 +2957,15 @@ static inline void security_inet_csk_clone(struct sock *newsk,
{
security_ops->inet_csk_clone(newsk, req);
}
+
+static inline void security_inet_conn_established(struct sock *sk,
+ struct sk_buff *skb)
+{
+ security_ops->inet_conn_established(sk, skb);
+}
#else /* CONFIG_SECURITY_NETWORK */
static inline int security_unix_stream_connect(struct socket * sock,
- struct socket * other,
+ struct socket * other,
struct sock * newsk)
{
return 0;
@@ -3115,12 +3112,17 @@ static inline void security_inet_csk_clone(struct sock *newsk,
const struct request_sock *req)
{
}
+
+static inline void security_inet_conn_established(struct sock *sk,
+ struct sk_buff *skb)
+{
+}
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx)
{
- return security_ops->xfrm_policy_alloc_security(xp, sec_ctx, NULL);
+ return security_ops->xfrm_policy_alloc_security(xp, sec_ctx);
}
static inline int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new)
@@ -3141,7 +3143,7 @@ static inline int security_xfrm_policy_delete(struct xfrm_policy *xp)
static inline int security_xfrm_state_alloc(struct xfrm_state *x,
struct xfrm_user_sec_ctx *sec_ctx)
{
- return security_ops->xfrm_state_alloc_security(x, sec_ctx, NULL, 0);
+ return security_ops->xfrm_state_alloc_security(x, sec_ctx, 0);
}
static inline int security_xfrm_state_alloc_acquire(struct xfrm_state *x,
@@ -3149,7 +3151,11 @@ static inline int security_xfrm_state_alloc_acquire(struct xfrm_state *x,
{
if (!polsec)
return 0;
- return security_ops->xfrm_state_alloc_security(x, NULL, polsec, secid);
+ /*
+ * We want the context to be taken from secid which is usually
+ * from the sock.
+ */
+ return security_ops->xfrm_state_alloc_security(x, NULL, secid);
}
static inline int security_xfrm_state_delete(struct xfrm_state *x)
@@ -3173,12 +3179,6 @@ static inline int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
return security_ops->xfrm_state_pol_flow_match(x, xp, fl);
}
-static inline int security_xfrm_flow_state_match(struct flowi *fl,
- struct xfrm_state *xfrm, struct xfrm_policy *xp)
-{
- return security_ops->xfrm_flow_state_match(fl, xfrm, xp);
-}
-
static inline int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid)
{
return security_ops->xfrm_decode_session(skb, secid, 1);
@@ -3242,12 +3242,6 @@ static inline int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
return 1;
}
-static inline int security_xfrm_flow_state_match(struct flowi *fl,
- struct xfrm_state *xfrm, struct xfrm_policy *xp)
-{
- return 1;
-}
-
static inline int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid)
{
return 0;
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 85577a4ffa61..14ec16d2d9ba 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -139,7 +139,7 @@ struct skb_shared_info {
/* Warning: this field is not always filled in (UFO)! */
unsigned short gso_segs;
unsigned short gso_type;
- unsigned int ip6_frag_id;
+ __be32 ip6_frag_id;
struct sk_buff *frag_list;
skb_frag_t frags[MAX_SKB_FRAGS];
};
@@ -216,7 +216,7 @@ enum {
* @tail: Tail pointer
* @end: End pointer
* @destructor: Destruct function
- * @nfmark: Can be used for communication between hooks
+ * @mark: Generic packet mark
* @nfct: Associated connection, if any
* @ipvs_property: skbuff is owned by ipvs
* @nfctinfo: Relationship of this skb to the connection
@@ -273,8 +273,11 @@ struct sk_buff {
unsigned int len,
data_len,
- mac_len,
- csum;
+ mac_len;
+ union {
+ __wsum csum;
+ __u32 csum_offset;
+ };
__u32 priority;
__u8 local_df:1,
cloned:1,
@@ -295,7 +298,6 @@ struct sk_buff {
#ifdef CONFIG_BRIDGE_NETFILTER
struct nf_bridge_info *nf_bridge;
#endif
- __u32 nfmark;
#endif /* CONFIG_NETFILTER */
#ifdef CONFIG_NET_SCHED
__u16 tc_index; /* traffic control index */
@@ -310,6 +312,7 @@ struct sk_buff {
__u32 secmark;
#endif
+ __u32 mark;
/* These elements must be at the end, see alloc_skb() for details. */
unsigned int truesize;
@@ -1199,8 +1202,7 @@ static inline int skb_add_data(struct sk_buff *skb,
if (skb->ip_summed == CHECKSUM_NONE) {
int err = 0;
- unsigned int csum = csum_and_copy_from_user(from,
- skb_put(skb, copy),
+ __wsum csum = csum_and_copy_from_user(from, skb_put(skb, copy),
copy, 0, &err);
if (!err) {
skb->csum = csum_block_add(skb->csum, csum, off);
@@ -1335,15 +1337,15 @@ extern int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb,
extern void skb_free_datagram(struct sock *sk, struct sk_buff *skb);
extern void skb_kill_datagram(struct sock *sk, struct sk_buff *skb,
unsigned int flags);
-extern unsigned int skb_checksum(const struct sk_buff *skb, int offset,
- int len, unsigned int csum);
+extern __wsum skb_checksum(const struct sk_buff *skb, int offset,
+ int len, __wsum csum);
extern int skb_copy_bits(const struct sk_buff *skb, int offset,
void *to, int len);
extern int skb_store_bits(const struct sk_buff *skb, int offset,
void *from, int len);
-extern unsigned int skb_copy_and_csum_bits(const struct sk_buff *skb,
+extern __wsum skb_copy_and_csum_bits(const struct sk_buff *skb,
int offset, u8 *to, int len,
- unsigned int csum);
+ __wsum csum);
extern void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to);
extern void skb_split(struct sk_buff *skb,
struct sk_buff *skb1, const u32 len);
@@ -1399,7 +1401,7 @@ static inline void skb_set_timestamp(struct sk_buff *skb, const struct timeval *
extern void __net_timestamp(struct sk_buff *skb);
-extern unsigned int __skb_checksum_complete(struct sk_buff *skb);
+extern __sum16 __skb_checksum_complete(struct sk_buff *skb);
/**
* skb_checksum_complete - Calculate checksum of an entire packet
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 361409094649..92cd38efad7f 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -264,6 +264,7 @@ struct ucred {
#define SOL_IPV6 41
#define SOL_ICMPV6 58
#define SOL_SCTP 132
+#define SOL_UDPLITE 136 /* UDP-Lite (RFC 3828) */
#define SOL_RAW 255
#define SOL_IPX 256
#define SOL_AX25 257
@@ -292,7 +293,7 @@ extern int memcpy_fromiovecend(unsigned char *kdata, struct iovec *iov,
extern int csum_partial_copy_fromiovecend(unsigned char *kdata,
struct iovec *iov,
int offset,
- unsigned int len, int *csump);
+ unsigned int len, __wsum *csump);
extern int verify_iovec(struct msghdr *m, struct iovec *iov, char *address, int mode);
extern int memcpy_toiovec(struct iovec *v, unsigned char *kdata, int len);
diff --git a/include/linux/sockios.h b/include/linux/sockios.h
index e6b9d1d36ea2..abef7596655a 100644
--- a/include/linux/sockios.h
+++ b/include/linux/sockios.h
@@ -72,8 +72,8 @@
#define SIOCGIFTXQLEN 0x8942 /* Get the tx queue length */
#define SIOCSIFTXQLEN 0x8943 /* Set the tx queue length */
-#define SIOCGIFDIVERT 0x8944 /* Frame diversion support */
-#define SIOCSIFDIVERT 0x8945 /* Set frame diversion options */
+/* SIOCGIFDIVERT was: 0x8944 Frame diversion support */
+/* SIOCSIFDIVERT was: 0x8945 Set frame diversion options */
#define SIOCETHTOOL 0x8946 /* Ethtool interface */
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
index b800d2d68b32..8451052ca66f 100644
--- a/include/linux/spinlock.h
+++ b/include/linux/spinlock.h
@@ -183,13 +183,27 @@ do { \
#define read_lock(lock) _read_lock(lock)
#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
+
#define spin_lock_irqsave(lock, flags) flags = _spin_lock_irqsave(lock)
#define read_lock_irqsave(lock, flags) flags = _read_lock_irqsave(lock)
#define write_lock_irqsave(lock, flags) flags = _write_lock_irqsave(lock)
+
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+#define spin_lock_irqsave_nested(lock, flags, subclass) \
+ flags = _spin_lock_irqsave_nested(lock, subclass)
+#else
+#define spin_lock_irqsave_nested(lock, flags, subclass) \
+ flags = _spin_lock_irqsave(lock)
+#endif
+
#else
+
#define spin_lock_irqsave(lock, flags) _spin_lock_irqsave(lock, flags)
#define read_lock_irqsave(lock, flags) _read_lock_irqsave(lock, flags)
#define write_lock_irqsave(lock, flags) _write_lock_irqsave(lock, flags)
+#define spin_lock_irqsave_nested(lock, flags, subclass) \
+ spin_lock_irqsave(lock, flags)
+
#endif
#define spin_lock_irq(lock) _spin_lock_irq(lock)
diff --git a/include/linux/spinlock_api_smp.h b/include/linux/spinlock_api_smp.h
index 8828b8155e9c..8a2307ce7296 100644
--- a/include/linux/spinlock_api_smp.h
+++ b/include/linux/spinlock_api_smp.h
@@ -32,6 +32,8 @@ void __lockfunc _read_lock_irq(rwlock_t *lock) __acquires(lock);
void __lockfunc _write_lock_irq(rwlock_t *lock) __acquires(lock);
unsigned long __lockfunc _spin_lock_irqsave(spinlock_t *lock)
__acquires(lock);
+unsigned long __lockfunc _spin_lock_irqsave_nested(spinlock_t *lock, int subclass)
+ __acquires(lock);
unsigned long __lockfunc _read_lock_irqsave(rwlock_t *lock)
__acquires(lock);
unsigned long __lockfunc _write_lock_irqsave(rwlock_t *lock)
diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h
index ac69e5511606..9a527c364394 100644
--- a/include/linux/sunrpc/xdr.h
+++ b/include/linux/sunrpc/xdr.h
@@ -151,7 +151,7 @@ typedef struct {
struct sk_buff *skb;
unsigned int offset;
size_t count;
- unsigned int csum;
+ __wsum csum;
} skb_reader_t;
typedef size_t (*skb_read_actor_t)(skb_reader_t *desc, void *to, size_t len);
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index d98562f1df76..94316a98e0d0 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -426,6 +426,8 @@ enum
NET_CIPSOV4_CACHE_BUCKET_SIZE=119,
NET_CIPSOV4_RBM_OPTFMT=120,
NET_CIPSOV4_RBM_STRICTVALID=121,
+ NET_TCP_AVAIL_CONG_CONTROL=122,
+ NET_TCP_ALLOWED_CONG_CONTROL=123,
};
enum {
@@ -604,16 +606,6 @@ enum {
NET_DCCP_DEFAULT=1,
};
-/* /proc/sys/net/dccp/default */
-enum {
- NET_DCCP_DEFAULT_SEQ_WINDOW = 1,
- NET_DCCP_DEFAULT_RX_CCID = 2,
- NET_DCCP_DEFAULT_TX_CCID = 3,
- NET_DCCP_DEFAULT_ACK_RATIO = 4,
- NET_DCCP_DEFAULT_SEND_ACKVEC = 5,
- NET_DCCP_DEFAULT_SEND_NDP = 6,
-};
-
/* /proc/sys/net/ipx */
enum {
NET_IPX_PPROP_BROADCASTING=1,
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index 6d5c43d31dec..2129d1b6c874 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -97,6 +97,9 @@ extern int __must_check
sysfs_rename_dir(struct kobject *, const char *new_name);
extern int __must_check
+sysfs_move_dir(struct kobject *, struct kobject *);
+
+extern int __must_check
sysfs_create_file(struct kobject *, const struct attribute *);
extern int __must_check
@@ -142,6 +145,11 @@ static inline int sysfs_rename_dir(struct kobject * k, const char *new_name)
return 0;
}
+static inline int sysfs_move_dir(struct kobject * k, struct kobject * new_parent)
+{
+ return 0;
+}
+
static inline int sysfs_create_file(struct kobject * k, const struct attribute * a)
{
return 0;
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 2d36f6db3706..3cc70d1a3504 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -19,6 +19,7 @@
#include <linux/types.h>
#include <asm/byteorder.h>
+#include <linux/socket.h>
struct tcphdr {
__be16 source;
@@ -51,7 +52,7 @@ struct tcphdr {
#error "Adjust your <asm/byteorder.h> defines"
#endif
__be16 window;
- __be16 check;
+ __sum16 check;
__be16 urg_ptr;
};
@@ -94,6 +95,7 @@ enum {
#define TCP_INFO 11 /* Information about this connection. */
#define TCP_QUICKACK 12 /* Block/reenable quick acks */
#define TCP_CONGESTION 13 /* Congestion control algorithm */
+#define TCP_MD5SIG 14 /* TCP MD5 Signature (RFC2385) */
#define TCPI_OPT_TIMESTAMPS 1
#define TCPI_OPT_SACK 2
@@ -157,6 +159,17 @@ struct tcp_info
__u32 tcpi_total_retrans;
};
+/* for TCP_MD5SIG socket option */
+#define TCP_MD5SIG_MAXKEYLEN 80
+
+struct tcp_md5sig {
+ struct __kernel_sockaddr_storage tcpm_addr; /* address associated */
+ __u16 __tcpm_pad1; /* zero */
+ __u16 tcpm_keylen; /* key length */
+ __u32 __tcpm_pad2; /* zero */
+ __u8 tcpm_key[TCP_MD5SIG_MAXKEYLEN]; /* key (binary) */
+};
+
#ifdef __KERNEL__
#include <linux/skbuff.h>
@@ -172,17 +185,17 @@ struct tcp_sack_block_wire {
};
struct tcp_sack_block {
- __u32 start_seq;
- __u32 end_seq;
+ u32 start_seq;
+ u32 end_seq;
};
struct tcp_options_received {
/* PAWS/RTTM data */
long ts_recent_stamp;/* Time we stored ts_recent (for aging) */
- __u32 ts_recent; /* Time stamp to echo next */
- __u32 rcv_tsval; /* Time stamp value */
- __u32 rcv_tsecr; /* Time stamp echo reply */
- __u16 saw_tstamp : 1, /* Saw TIMESTAMP on last packet */
+ u32 ts_recent; /* Time stamp to echo next */
+ u32 rcv_tsval; /* Time stamp value */
+ u32 rcv_tsecr; /* Time stamp echo reply */
+ u16 saw_tstamp : 1, /* Saw TIMESTAMP on last packet */
tstamp_ok : 1, /* TIMESTAMP seen on SYN packet */
dsack : 1, /* D-SACK is scheduled */
wscale_ok : 1, /* Wscale seen on SYN packet */
@@ -190,16 +203,20 @@ struct tcp_options_received {
snd_wscale : 4, /* Window scaling received from sender */
rcv_wscale : 4; /* Window scaling to send to receiver */
/* SACKs data */
- __u8 eff_sacks; /* Size of SACK array to send with next packet */
- __u8 num_sacks; /* Number of SACK blocks */
- __u16 user_mss; /* mss requested by user in ioctl */
- __u16 mss_clamp; /* Maximal mss, negotiated at connection setup */
+ u8 eff_sacks; /* Size of SACK array to send with next packet */
+ u8 num_sacks; /* Number of SACK blocks */
+ u16 user_mss; /* mss requested by user in ioctl */
+ u16 mss_clamp; /* Maximal mss, negotiated at connection setup */
};
struct tcp_request_sock {
- struct inet_request_sock req;
- __u32 rcv_isn;
- __u32 snt_isn;
+ struct inet_request_sock req;
+#ifdef CONFIG_TCP_MD5SIG
+ /* Only used by TCP MD5 Signature so far. */
+ struct tcp_request_sock_ops *af_specific;
+#endif
+ u32 rcv_isn;
+ u32 snt_isn;
};
static inline struct tcp_request_sock *tcp_rsk(const struct request_sock *req)
@@ -210,7 +227,8 @@ static inline struct tcp_request_sock *tcp_rsk(const struct request_sock *req)
struct tcp_sock {
/* inet_connection_sock has to be the first member of tcp_sock */
struct inet_connection_sock inet_conn;
- int tcp_header_len; /* Bytes of tcp header to send */
+ u16 tcp_header_len; /* Bytes of tcp header to send */
+ u16 xmit_size_goal; /* Goal for segmenting output packets */
/*
* Header prediction flags
@@ -223,13 +241,13 @@ struct tcp_sock {
* read the code and the spec side by side (and laugh ...)
* See RFC793 and RFC1122. The RFC writes these in capitals.
*/
- __u32 rcv_nxt; /* What we want to receive next */
- __u32 snd_nxt; /* Next sequence we send */
+ u32 rcv_nxt; /* What we want to receive next */
+ u32 snd_nxt; /* Next sequence we send */
- __u32 snd_una; /* First byte we want an ack for */
- __u32 snd_sml; /* Last byte of the most recently transmitted small packet */
- __u32 rcv_tstamp; /* timestamp of last received ACK (for keepalives) */
- __u32 lsndtime; /* timestamp of last sent data packet (for restart window) */
+ u32 snd_una; /* First byte we want an ack for */
+ u32 snd_sml; /* Last byte of the most recently transmitted small packet */
+ u32 rcv_tstamp; /* timestamp of last received ACK (for keepalives) */
+ u32 lsndtime; /* timestamp of last sent data packet (for restart window) */
/* Data for direct copy to user */
struct {
@@ -247,32 +265,30 @@ struct tcp_sock {
#endif
} ucopy;
- __u32 snd_wl1; /* Sequence for window update */
- __u32 snd_wnd; /* The window we expect to receive */
- __u32 max_window; /* Maximal window ever seen from peer */
- __u32 mss_cache; /* Cached effective mss, not including SACKS */
- __u16 xmit_size_goal; /* Goal for segmenting output packets */
- /* XXX Two bytes hole, try to pack */
+ u32 snd_wl1; /* Sequence for window update */
+ u32 snd_wnd; /* The window we expect to receive */
+ u32 max_window; /* Maximal window ever seen from peer */
+ u32 mss_cache; /* Cached effective mss, not including SACKS */
- __u32 window_clamp; /* Maximal window to advertise */
- __u32 rcv_ssthresh; /* Current window clamp */
+ u32 window_clamp; /* Maximal window to advertise */
+ u32 rcv_ssthresh; /* Current window clamp */
- __u32 frto_highmark; /* snd_nxt when RTO occurred */
- __u8 reordering; /* Packet reordering metric. */
- __u8 frto_counter; /* Number of new acks after RTO */
- __u8 nonagle; /* Disable Nagle algorithm? */
- __u8 keepalive_probes; /* num of allowed keep alive probes */
+ u32 frto_highmark; /* snd_nxt when RTO occurred */
+ u8 reordering; /* Packet reordering metric. */
+ u8 frto_counter; /* Number of new acks after RTO */
+ u8 nonagle; /* Disable Nagle algorithm? */
+ u8 keepalive_probes; /* num of allowed keep alive probes */
/* RTT measurement */
- __u32 srtt; /* smoothed round trip time << 3 */
- __u32 mdev; /* medium deviation */
- __u32 mdev_max; /* maximal mdev for the last rtt period */
- __u32 rttvar; /* smoothed mdev_max */
- __u32 rtt_seq; /* sequence number to update rttvar */
-
- __u32 packets_out; /* Packets which are "in flight" */
- __u32 left_out; /* Packets which leaved network */
- __u32 retrans_out; /* Retransmitted packets out */
+ u32 srtt; /* smoothed round trip time << 3 */
+ u32 mdev; /* medium deviation */
+ u32 mdev_max; /* maximal mdev for the last rtt period */
+ u32 rttvar; /* smoothed mdev_max */
+ u32 rtt_seq; /* sequence number to update rttvar */
+
+ u32 packets_out; /* Packets which are "in flight" */
+ u32 left_out; /* Packets which leaved network */
+ u32 retrans_out; /* Retransmitted packets out */
/*
* Options received (usually on last packet, some only on SYN packets).
*/
@@ -281,20 +297,20 @@ struct tcp_sock {
/*
* Slow start and congestion control (see also Nagle, and Karn & Partridge)
*/
- __u32 snd_ssthresh; /* Slow start size threshold */
- __u32 snd_cwnd; /* Sending congestion window */
- __u16 snd_cwnd_cnt; /* Linear increase counter */
- __u16 snd_cwnd_clamp; /* Do not allow snd_cwnd to grow above this */
- __u32 snd_cwnd_used;
- __u32 snd_cwnd_stamp;
+ u32 snd_ssthresh; /* Slow start size threshold */
+ u32 snd_cwnd; /* Sending congestion window */
+ u16 snd_cwnd_cnt; /* Linear increase counter */
+ u16 snd_cwnd_clamp; /* Do not allow snd_cwnd to grow above this */
+ u32 snd_cwnd_used;
+ u32 snd_cwnd_stamp;
struct sk_buff_head out_of_order_queue; /* Out of order segments go here */
- __u32 rcv_wnd; /* Current receiver window */
- __u32 rcv_wup; /* rcv_nxt on last window update sent */
- __u32 write_seq; /* Tail(+1) of data held in tcp send buffer */
- __u32 pushed_seq; /* Last pushed seq, required to talk to windows */
- __u32 copied_seq; /* Head of yet unread data */
+ u32 rcv_wnd; /* Current receiver window */
+ u32 rcv_wup; /* rcv_nxt on last window update sent */
+ u32 write_seq; /* Tail(+1) of data held in tcp send buffer */
+ u32 pushed_seq; /* Last pushed seq, required to talk to windows */
+ u32 copied_seq; /* Head of yet unread data */
/* SACKs data */
struct tcp_sack_block duplicate_sack[1]; /* D-SACK block */
@@ -315,26 +331,26 @@ struct tcp_sock {
int retransmit_cnt_hint;
int forward_cnt_hint;
- __u16 advmss; /* Advertised MSS */
- __u16 prior_ssthresh; /* ssthresh saved at recovery start */
- __u32 lost_out; /* Lost packets */
- __u32 sacked_out; /* SACK'd packets */
- __u32 fackets_out; /* FACK'd packets */
- __u32 high_seq; /* snd_nxt at onset of congestion */
+ u16 advmss; /* Advertised MSS */
+ u16 prior_ssthresh; /* ssthresh saved at recovery start */
+ u32 lost_out; /* Lost packets */
+ u32 sacked_out; /* SACK'd packets */
+ u32 fackets_out; /* FACK'd packets */
+ u32 high_seq; /* snd_nxt at onset of congestion */
- __u32 retrans_stamp; /* Timestamp of the last retransmit,
+ u32 retrans_stamp; /* Timestamp of the last retransmit,
* also used in SYN-SENT to remember stamp of
* the first SYN. */
- __u32 undo_marker; /* tracking retrans started here. */
+ u32 undo_marker; /* tracking retrans started here. */
int undo_retrans; /* number of undoable retransmissions. */
- __u32 urg_seq; /* Seq of received urgent pointer */
- __u16 urg_data; /* Saved octet of OOB data and control flags */
- __u8 urg_mode; /* In urgent mode */
- __u8 ecn_flags; /* ECN status bits. */
- __u32 snd_up; /* Urgent pointer */
+ u32 urg_seq; /* Seq of received urgent pointer */
+ u16 urg_data; /* Saved octet of OOB data and control flags */
+ u8 urg_mode; /* In urgent mode */
+ u8 ecn_flags; /* ECN status bits. */
+ u32 snd_up; /* Urgent pointer */
- __u32 total_retrans; /* Total retransmits for entire connection */
- __u32 bytes_acked; /* Appropriate Byte Counting - RFC3465 */
+ u32 total_retrans; /* Total retransmits for entire connection */
+ u32 bytes_acked; /* Appropriate Byte Counting - RFC3465 */
unsigned int keepalive_time; /* time before keep alive takes place */
unsigned int keepalive_intvl; /* time interval between keep alive probes */
@@ -342,27 +358,35 @@ struct tcp_sock {
unsigned long last_synq_overflow;
- __u32 tso_deferred;
+ u32 tso_deferred;
/* Receiver side RTT estimation */
struct {
- __u32 rtt;
- __u32 seq;
- __u32 time;
+ u32 rtt;
+ u32 seq;
+ u32 time;
} rcv_rtt_est;
/* Receiver queue space */
struct {
int space;
- __u32 seq;
- __u32 time;
+ u32 seq;
+ u32 time;
} rcvq_space;
/* TCP-specific MTU probe information. */
struct {
- __u32 probe_seq_start;
- __u32 probe_seq_end;
+ u32 probe_seq_start;
+ u32 probe_seq_end;
} mtu_probe;
+
+#ifdef CONFIG_TCP_MD5SIG
+/* TCP AF-Specific parts; only used by MD5 Signature support so far */
+ struct tcp_sock_af_ops *af_specific;
+
+/* TCP MD5 Signagure Option information */
+ struct tcp_md5sig_info *md5sig_info;
+#endif
};
static inline struct tcp_sock *tcp_sk(const struct sock *sk)
@@ -372,11 +396,15 @@ static inline struct tcp_sock *tcp_sk(const struct sock *sk)
struct tcp_timewait_sock {
struct inet_timewait_sock tw_sk;
- __u32 tw_rcv_nxt;
- __u32 tw_snd_nxt;
- __u32 tw_rcv_wnd;
- __u32 tw_ts_recent;
+ u32 tw_rcv_nxt;
+ u32 tw_snd_nxt;
+ u32 tw_rcv_wnd;
+ u32 tw_ts_recent;
long tw_ts_recent_stamp;
+#ifdef CONFIG_TCP_MD5SIG
+ u16 tw_md5_keylen;
+ u8 tw_md5_key[TCP_MD5SIG_MAXKEYLEN];
+#endif
};
static inline struct tcp_timewait_sock *tcp_twsk(const struct sock *sk)
diff --git a/include/linux/textsearch.h b/include/linux/textsearch.h
index 7dac8f04d28e..004808a6df1d 100644
--- a/include/linux/textsearch.h
+++ b/include/linux/textsearch.h
@@ -20,7 +20,7 @@ struct ts_config;
/**
* struct ts_state - search state
* @offset: offset for next match
- * @cb: control buffer, for persistant variables of get_next_block()
+ * @cb: control buffer, for persistent variables of get_next_block()
*/
struct ts_state
{
@@ -71,7 +71,7 @@ struct ts_config
* Called repeatedly until 0 is returned. Must assign the
* head of the next block of data to &*dst and return the length
* of the block or 0 if at the end. consumed == 0 indicates
- * a new search. May store/read persistant values in state->cb.
+ * a new search. May store/read persistent values in state->cb.
*/
unsigned int (*get_next_block)(unsigned int consumed,
const u8 **dst,
diff --git a/include/linux/tfrc.h b/include/linux/tfrc.h
index 7dab7831c3cb..31a9b25276fe 100644
--- a/include/linux/tfrc.h
+++ b/include/linux/tfrc.h
@@ -1,7 +1,8 @@
#ifndef _LINUX_TFRC_H_
#define _LINUX_TFRC_H_
/*
- * include/linux/tfrc.h
+ * TFRC - Data Structures for the TCP-Friendly Rate Control congestion
+ * control mechanism as specified in RFC 3448.
*
* Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
* Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz>
@@ -13,15 +14,30 @@
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
-
#include <linux/types.h>
+/** tfrc_rx_info - TFRC Receiver Data Structure
+ *
+ * @tfrcrx_x_recv: receiver estimate of sending rate (3.2.2)
+ * @tfrcrx_rtt: round-trip-time (communicated by sender)
+ * @tfrcrx_p: current estimate of loss event rate (3.2.2)
+ */
struct tfrc_rx_info {
__u32 tfrcrx_x_recv;
__u32 tfrcrx_rtt;
__u32 tfrcrx_p;
};
+/** tfrc_tx_info - TFRC Sender Data Structure
+ *
+ * @tfrctx_x: computed transmit rate (4.3 (4))
+ * @tfrctx_x_recv: receiver estimate of send rate (4.3)
+ * @tfrctx_x_calc: return value of throughput equation (3.1)
+ * @tfrctx_rtt: (moving average) estimate of RTT (4.3)
+ * @tfrctx_p: current loss event rate (5.4)
+ * @tfrctx_rto: estimate of RTO, equals 4*RTT (4.3)
+ * @tfrctx_ipi: inter-packet interval (4.6)
+ */
struct tfrc_tx_info {
__u32 tfrctx_x;
__u32 tfrctx_x_recv;
diff --git a/include/linux/tipc_config.h b/include/linux/tipc_config.h
index 33a653913d94..b0c916d1f375 100644
--- a/include/linux/tipc_config.h
+++ b/include/linux/tipc_config.h
@@ -194,34 +194,34 @@
struct tipc_node_info {
- __u32 addr; /* network address of node */
- __u32 up; /* 0=down, 1= up */
+ __be32 addr; /* network address of node */
+ __be32 up; /* 0=down, 1= up */
};
struct tipc_link_info {
- __u32 dest; /* network address of peer node */
- __u32 up; /* 0=down, 1=up */
+ __be32 dest; /* network address of peer node */
+ __be32 up; /* 0=down, 1=up */
char str[TIPC_MAX_LINK_NAME]; /* link name */
};
struct tipc_bearer_config {
- __u32 priority; /* Range [1,31]. Override per link */
- __u32 detect_scope;
+ __be32 priority; /* Range [1,31]. Override per link */
+ __be32 detect_scope;
char name[TIPC_MAX_BEARER_NAME];
};
struct tipc_link_config {
- __u32 value;
+ __be32 value;
char name[TIPC_MAX_LINK_NAME];
};
#define TIPC_NTQ_ALLTYPES 0x80000000
struct tipc_name_table_query {
- __u32 depth; /* 1:type, 2:+name info, 3:+port info, 4+:+debug info */
- __u32 type; /* {t,l,u} info ignored if high bit of "depth" is set */
- __u32 lowbound; /* (i.e. displays all entries of name table) */
- __u32 upbound;
+ __be32 depth; /* 1:type, 2:+name info, 3:+port info, 4+:+debug info */
+ __be32 type; /* {t,l,u} info ignored if high bit of "depth" is set */
+ __be32 lowbound; /* (i.e. displays all entries of name table) */
+ __be32 upbound;
};
/*
@@ -262,8 +262,8 @@ struct tipc_route_info {
*/
struct tlv_desc {
- __u16 tlv_len; /* TLV length (descriptor + value) */
- __u16 tlv_type; /* TLV identifier */
+ __be16 tlv_len; /* TLV length (descriptor + value) */
+ __be16 tlv_type; /* TLV identifier */
};
#define TLV_ALIGNTO 4
@@ -377,9 +377,9 @@ struct tipc_genlmsghdr {
struct tipc_cfg_msg_hdr
{
- __u32 tcm_len; /* Message length (including header) */
- __u16 tcm_type; /* Command type */
- __u16 tcm_flags; /* Additional flags */
+ __be32 tcm_len; /* Message length (including header) */
+ __be16 tcm_type; /* Command type */
+ __be16 tcm_flags; /* Additional flags */
char tcm_reserved[8]; /* Unused */
};
diff --git a/include/linux/tty.h b/include/linux/tty.h
index c1f716446161..f717f0898238 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -276,9 +276,8 @@ extern int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc);
extern int tty_unregister_ldisc(int disc);
extern int tty_register_driver(struct tty_driver *driver);
extern int tty_unregister_driver(struct tty_driver *driver);
-extern struct class_device *tty_register_device(struct tty_driver *driver,
- unsigned index,
- struct device *dev);
+extern struct device *tty_register_device(struct tty_driver *driver,
+ unsigned index, struct device *dev);
extern void tty_unregister_device(struct tty_driver *driver, unsigned index);
extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp,
int buflen);
diff --git a/include/linux/types.h b/include/linux/types.h
index 750f085fa564..745c409ebbb5 100644
--- a/include/linux/types.h
+++ b/include/linux/types.h
@@ -128,6 +128,8 @@ typedef __s64 int64_t;
/* this is a special 64bit data type that is 8-byte aligned */
#define aligned_u64 unsigned long long __attribute__((aligned(8)))
+#define aligned_be64 __be64 __attribute__((aligned(8)))
+#define aligned_le64 __le64 __attribute__((aligned(8)))
/**
* The type used for indexing onto a disc or disc partition.
@@ -180,6 +182,8 @@ typedef __u32 __bitwise __be32;
typedef __u64 __bitwise __le64;
typedef __u64 __bitwise __be64;
#endif
+typedef __u16 __bitwise __sum16;
+typedef __u32 __bitwise __wsum;
#ifdef __KERNEL__
typedef unsigned __bitwise__ gfp_t;
diff --git a/include/linux/udp.h b/include/linux/udp.h
index 014b41d1e308..7e08c07efe0f 100644
--- a/include/linux/udp.h
+++ b/include/linux/udp.h
@@ -23,7 +23,7 @@ struct udphdr {
__be16 source;
__be16 dest;
__be16 len;
- __be16 check;
+ __sum16 check;
};
/* UDP socket options */
@@ -38,6 +38,7 @@ struct udphdr {
#include <linux/types.h>
#include <net/inet_sock.h>
+#define UDP_HTABLE_SIZE 128
struct udp_sock {
/* inet_sock has to be the first member */
@@ -50,12 +51,23 @@ struct udp_sock {
* when the socket is uncorked.
*/
__u16 len; /* total length of pending frames */
+ /*
+ * Fields specific to UDP-Lite.
+ */
+ __u16 pcslen;
+ __u16 pcrlen;
+/* indicator bits used by pcflag: */
+#define UDPLITE_BIT 0x1 /* set by udplite proto init function */
+#define UDPLITE_SEND_CC 0x2 /* set via udplite setsockopt */
+#define UDPLITE_RECV_CC 0x4 /* set via udplite setsocktopt */
+ __u8 pcflag; /* marks socket as UDP-Lite if > 0 */
};
static inline struct udp_sock *udp_sk(const struct sock *sk)
{
return (struct udp_sock *)sk;
}
+#define IS_UDPLITE(__sk) (udp_sk(__sk)->pcflag)
#endif
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 06ce7a626040..aab5b1b72021 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -313,8 +313,13 @@ struct usb_bus {
/* This is arbitrary.
* From USB 2.0 spec Table 11-13, offset 7, a hub can
* have up to 255 ports. The most yet reported is 10.
+ *
+ * Current Wireless USB host hardware (Intel i1480 for example) allows
+ * up to 22 devices to connect. Upcoming hardware might raise that
+ * limit. Because the arrays need to add a bit for hub status data, we
+ * do 31, so plus one evens out to four bytes.
*/
-#define USB_MAXCHILDREN (16)
+#define USB_MAXCHILDREN (31)
struct usb_tt;
@@ -357,7 +362,8 @@ struct usb_device {
u8 portnum; /* Parent port number (origin 1) */
u8 level; /* Number of USB hub ancestors */
- int have_langid; /* whether string_langid is valid */
+ unsigned discon_suspended:1; /* Disconnected while suspended */
+ unsigned have_langid:1; /* whether string_langid is valid */
int string_langid; /* language ID for strings */
/* static strings from the device */
@@ -410,14 +416,37 @@ extern struct usb_device *usb_find_device(u16 vendor_id, u16 product_id);
/* USB autosuspend and autoresume */
#ifdef CONFIG_USB_SUSPEND
+extern int usb_autopm_set_interface(struct usb_interface *intf);
extern int usb_autopm_get_interface(struct usb_interface *intf);
extern void usb_autopm_put_interface(struct usb_interface *intf);
+static inline void usb_autopm_enable(struct usb_interface *intf)
+{
+ intf->pm_usage_cnt = 0;
+ usb_autopm_set_interface(intf);
+}
+
+static inline void usb_autopm_disable(struct usb_interface *intf)
+{
+ intf->pm_usage_cnt = 1;
+ usb_autopm_set_interface(intf);
+}
+
#else
-#define usb_autopm_get_interface(intf) 0
-#define usb_autopm_put_interface(intf) do {} while (0)
-#endif
+static inline int usb_autopm_set_interface(struct usb_interface *intf)
+{ return 0; }
+
+static inline int usb_autopm_get_interface(struct usb_interface *intf)
+{ return 0; }
+
+static inline void usb_autopm_put_interface(struct usb_interface *intf)
+{ }
+static inline void usb_autopm_enable(struct usb_interface *intf)
+{ }
+static inline void usb_autopm_disable(struct usb_interface *intf)
+{ }
+#endif
/*-------------------------------------------------------------------------*/
@@ -490,17 +519,137 @@ static inline int usb_make_path (struct usb_device *dev, char *buf,
/*-------------------------------------------------------------------------*/
-extern int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd);
-extern int usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd);
-extern int usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd);
-extern int usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd);
-extern int usb_endpoint_xfer_isoc(const struct usb_endpoint_descriptor *epd);
-extern int usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd);
-extern int usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd);
-extern int usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd);
-extern int usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd);
-extern int usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *epd);
-extern int usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor *epd);
+/**
+ * usb_endpoint_dir_in - check if the endpoint has IN direction
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type IN, otherwise it returns false.
+ */
+static inline int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd)
+{
+ return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN);
+}
+
+/**
+ * usb_endpoint_dir_out - check if the endpoint has OUT direction
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type OUT, otherwise it returns false.
+ */
+static inline int usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd)
+{
+ return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
+}
+
+/**
+ * usb_endpoint_xfer_bulk - check if the endpoint has bulk transfer type
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type bulk, otherwise it returns false.
+ */
+static inline int usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd)
+{
+ return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+ USB_ENDPOINT_XFER_BULK);
+}
+
+/**
+ * usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type interrupt, otherwise it returns
+ * false.
+ */
+static inline int usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd)
+{
+ return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+ USB_ENDPOINT_XFER_INT);
+}
+
+/**
+ * usb_endpoint_xfer_isoc - check if the endpoint has isochronous transfer type
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type isochronous, otherwise it returns
+ * false.
+ */
+static inline int usb_endpoint_xfer_isoc(const struct usb_endpoint_descriptor *epd)
+{
+ return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+ USB_ENDPOINT_XFER_ISOC);
+}
+
+/**
+ * usb_endpoint_is_bulk_in - check if the endpoint is bulk IN
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has bulk transfer type and IN direction,
+ * otherwise it returns false.
+ */
+static inline int usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd)
+{
+ return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_in(epd));
+}
+
+/**
+ * usb_endpoint_is_bulk_out - check if the endpoint is bulk OUT
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has bulk transfer type and OUT direction,
+ * otherwise it returns false.
+ */
+static inline int usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd)
+{
+ return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_out(epd));
+}
+
+/**
+ * usb_endpoint_is_int_in - check if the endpoint is interrupt IN
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has interrupt transfer type and IN direction,
+ * otherwise it returns false.
+ */
+static inline int usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd)
+{
+ return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd));
+}
+
+/**
+ * usb_endpoint_is_int_out - check if the endpoint is interrupt OUT
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has interrupt transfer type and OUT direction,
+ * otherwise it returns false.
+ */
+static inline int usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd)
+{
+ return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd));
+}
+
+/**
+ * usb_endpoint_is_isoc_in - check if the endpoint is isochronous IN
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has isochronous transfer type and IN direction,
+ * otherwise it returns false.
+ */
+static inline int usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *epd)
+{
+ return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_in(epd));
+}
+
+/**
+ * usb_endpoint_is_isoc_out - check if the endpoint is isochronous OUT
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has isochronous transfer type and OUT direction,
+ * otherwise it returns false.
+ */
+static inline int usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor *epd)
+{
+ return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_out(epd));
+}
/*-------------------------------------------------------------------------*/
diff --git a/include/linux/wireless.h b/include/linux/wireless.h
index a50a0130fd9e..7c269f4992eb 100644
--- a/include/linux/wireless.h
+++ b/include/linux/wireless.h
@@ -546,6 +546,8 @@
/* MLME requests (SIOCSIWMLME / struct iw_mlme) */
#define IW_MLME_DEAUTH 0
#define IW_MLME_DISASSOC 1
+#define IW_MLME_AUTH 2
+#define IW_MLME_ASSOC 3
/* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */
#define IW_AUTH_INDEX 0x0FFF
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
index 8ae7f744917b..088ba8113f7e 100644
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -211,8 +211,8 @@ struct xfrm_user_tmpl {
struct xfrm_encap_tmpl {
__u16 encap_type;
- __u16 encap_sport;
- __u16 encap_dport;
+ __be16 encap_sport;
+ __be16 encap_dport;
xfrm_address_t encap_oa;
};
@@ -289,7 +289,9 @@ struct xfrm_usersa_id {
struct xfrm_aevent_id {
struct xfrm_usersa_id sa_id;
+ xfrm_address_t saddr;
__u32 flags;
+ __u32 reqid;
};
struct xfrm_userspi_info {
diff --git a/include/linux/zftape.h b/include/linux/zftape.h
deleted file mode 100644
index b057c65366c6..000000000000
--- a/include/linux/zftape.h
+++ /dev/null
@@ -1,87 +0,0 @@
-#ifndef _ZFTAPE_H
-#define _ZFTAPE_H
-
-/*
- * Copyright (C) 1996, 1997 Claus-Justus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/include/linux/zftape.h,v $
- * $Revision: 1.12 $
- * $Date: 1997/10/21 11:02:37 $
- *
- * Special ioctl and other global info for the zftape VFS
- * interface for the QIC-40/80/3010/3020 floppy-tape driver for
- * Linux.
- */
-
-#define ZFTAPE_VERSION "zftape for " FTAPE_VERSION
-
-#include <linux/ftape.h>
-
-#define ZFTAPE_LABEL "Ftape - The Linux Floppy Tape Project!"
-
-/* Bits of the minor device number that control the operation mode */
-#define ZFT_Q80_MODE (1 << 3)
-#define ZFT_ZIP_MODE (1 << 4)
-#define ZFT_RAW_MODE (1 << 5)
-#define ZFT_MINOR_OP_MASK (ZFT_Q80_MODE | \
- ZFT_ZIP_MODE | \
- ZFT_RAW_MODE)
-#define ZFT_MINOR_MASK (FTAPE_SEL_MASK | \
- ZFT_MINOR_OP_MASK | \
- FTAPE_NO_REWIND)
-
-#ifdef ZFT_OBSOLETE
-struct mtblksz {
- unsigned int mt_blksz;
-};
-#define MTIOC_ZFTAPE_GETBLKSZ _IOR('m', 104, struct mtblksz)
-#endif
-
-#ifdef __KERNEL__
-
-extern int zft_init(void);
-
-static inline __s64 zft_div_blksz(__s64 value, __u32 blk_sz)
-{
- if (blk_sz == 1) {
- return value;
- } else {
- return (__s64)(((__u32)(value >> 10) + (blk_sz >> 10) - 1)
- / (blk_sz >> 10));
- }
-}
-
-static inline __s64 zft_mul_blksz(__s64 value, __u32 blk_sz)
-{
- if (blk_sz == 1) {
- return value;
- } else {
- /* if blk_sz != 1, then it is a multiple of 1024. In
- * this case, `value' will also fit into 32 bits.
- *
- * Actually, this limits the capacity to 42
- * bits. This is (2^32)*1024, roughly a thousand
- * times 2GB, or 3 Terabytes. Hopefully this is enough
- */
- return(__s64)(((__u32)(value)*(blk_sz>>10))<<10);
- }
-}
-
-#endif
-
-#endif
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index 44f1b673f916..88df8fc814e4 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -35,9 +35,9 @@ struct prefix_info {
#else
#error "Please fix <asm/byteorder.h>"
#endif
- __u32 valid;
- __u32 prefered;
- __u32 reserved2;
+ __be32 valid;
+ __be32 prefered;
+ __be32 reserved2;
struct in6_addr prefix;
};
@@ -183,7 +183,7 @@ static __inline__ u8 ipv6_addr_hash(const struct in6_addr *addr)
* This will include the IEEE address token on links that support it.
*/
- word = addr->s6_addr32[2] ^ addr->s6_addr32[3];
+ word = (__force u32)(addr->s6_addr32[2] ^ addr->s6_addr32[3]);
word ^= (word >> 16);
word ^= (word >> 8);
diff --git a/include/net/arp.h b/include/net/arp.h
index 6a3d9a7d302b..f02664568600 100644
--- a/include/net/arp.h
+++ b/include/net/arp.h
@@ -16,7 +16,7 @@ extern void arp_send(int type, int ptype, __be32 dest_ip,
struct net_device *dev, __be32 src_ip,
unsigned char *dest_hw, unsigned char *src_hw, unsigned char *th);
extern int arp_bind_neighbour(struct dst_entry *dst);
-extern int arp_mc_map(u32 addr, u8 *haddr, struct net_device *dev, int dir);
+extern int arp_mc_map(__be32 addr, u8 *haddr, struct net_device *dev, int dir);
extern void arp_ifdown(struct net_device *dev);
extern struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
diff --git a/include/net/atmclip.h b/include/net/atmclip.h
index 90fcc98e676f..b5a51a7bb364 100644
--- a/include/net/atmclip.h
+++ b/include/net/atmclip.h
@@ -36,7 +36,7 @@ struct clip_vcc {
struct atmarp_entry {
- u32 ip; /* IP address */
+ __be32 ip; /* IP address */
struct clip_vcc *vccs; /* active VCCs; NULL if resolution is
pending */
unsigned long expires; /* entry expiration time */
diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h
index 89d743cfdfdf..3c563f02907c 100644
--- a/include/net/bluetooth/rfcomm.h
+++ b/include/net/bluetooth/rfcomm.h
@@ -124,7 +124,7 @@ struct rfcomm_pn {
u8 flow_ctrl;
u8 priority;
u8 ack_timer;
- u16 mtu;
+ __le16 mtu;
u8 max_retrans;
u8 credits;
} __attribute__ ((packed));
@@ -136,7 +136,7 @@ struct rfcomm_rpn {
u8 flow_ctrl;
u8 xon_char;
u8 xoff_char;
- u16 param_mask;
+ __le16 param_mask;
} __attribute__ ((packed));
struct rfcomm_rls {
diff --git a/include/net/checksum.h b/include/net/checksum.h
index e3ea7cc2c728..124246172a88 100644
--- a/include/net/checksum.h
+++ b/include/net/checksum.h
@@ -27,8 +27,8 @@
#ifndef _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
static inline
-unsigned int csum_and_copy_from_user (const unsigned char __user *src, unsigned char *dst,
- int len, int sum, int *err_ptr)
+__wsum csum_and_copy_from_user (const void __user *src, void *dst,
+ int len, __wsum sum, int *err_ptr)
{
if (access_ok(VERIFY_READ, src, len))
return csum_partial_copy_from_user(src, dst, len, sum, err_ptr);
@@ -41,8 +41,8 @@ unsigned int csum_and_copy_from_user (const unsigned char __user *src, unsigned
#endif
#ifndef HAVE_CSUM_COPY_USER
-static __inline__ unsigned int csum_and_copy_to_user
-(const unsigned char *src, unsigned char __user *dst, int len, unsigned int sum, int *err_ptr)
+static __inline__ __wsum csum_and_copy_to_user
+(const void *src, void __user *dst, int len, __wsum sum, int *err_ptr)
{
sum = csum_partial(src, len, sum);
@@ -53,35 +53,44 @@ static __inline__ unsigned int csum_and_copy_to_user
if (len)
*err_ptr = -EFAULT;
- return -1; /* invalid checksum */
+ return (__force __wsum)-1; /* invalid checksum */
}
#endif
-static inline unsigned int csum_add(unsigned int csum, unsigned int addend)
+static inline __wsum csum_add(__wsum csum, __wsum addend)
{
- csum += addend;
- return csum + (csum < addend);
+ u32 res = (__force u32)csum;
+ res += (__force u32)addend;
+ return (__force __wsum)(res + (res < (__force u32)addend));
}
-static inline unsigned int csum_sub(unsigned int csum, unsigned int addend)
+static inline __wsum csum_sub(__wsum csum, __wsum addend)
{
return csum_add(csum, ~addend);
}
-static inline unsigned int
-csum_block_add(unsigned int csum, unsigned int csum2, int offset)
+static inline __wsum
+csum_block_add(__wsum csum, __wsum csum2, int offset)
{
+ u32 sum = (__force u32)csum2;
if (offset&1)
- csum2 = ((csum2&0xFF00FF)<<8)+((csum2>>8)&0xFF00FF);
- return csum_add(csum, csum2);
+ sum = ((sum&0xFF00FF)<<8)+((sum>>8)&0xFF00FF);
+ return csum_add(csum, (__force __wsum)sum);
}
-static inline unsigned int
-csum_block_sub(unsigned int csum, unsigned int csum2, int offset)
+static inline __wsum
+csum_block_sub(__wsum csum, __wsum csum2, int offset)
{
+ u32 sum = (__force u32)csum2;
if (offset&1)
- csum2 = ((csum2&0xFF00FF)<<8)+((csum2>>8)&0xFF00FF);
- return csum_sub(csum, csum2);
+ sum = ((sum&0xFF00FF)<<8)+((sum>>8)&0xFF00FF);
+ return csum_sub(csum, (__force __wsum)sum);
}
+static inline __wsum csum_unfold(__sum16 n)
+{
+ return (__force __wsum)n;
+}
+
+#define CSUM_MANGLED_0 ((__force __sum16)0xffff)
#endif
diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h
index 718b4d9c891f..4c9522c5178f 100644
--- a/include/net/cipso_ipv4.h
+++ b/include/net/cipso_ipv4.h
@@ -58,10 +58,10 @@
#define CIPSO_V4_MAP_PASS 2
/* limits */
-#define CIPSO_V4_MAX_REM_LVLS 256
+#define CIPSO_V4_MAX_REM_LVLS 255
#define CIPSO_V4_INV_LVL 0x80000000
#define CIPSO_V4_MAX_LOC_LVLS (CIPSO_V4_INV_LVL - 1)
-#define CIPSO_V4_MAX_REM_CATS 65536
+#define CIPSO_V4_MAX_REM_CATS 65534
#define CIPSO_V4_INV_CAT 0x80000000
#define CIPSO_V4_MAX_LOC_CATS (CIPSO_V4_INV_CAT - 1)
diff --git a/include/net/dsfield.h b/include/net/dsfield.h
index a79c9e075f7f..eb65bf2e2502 100644
--- a/include/net/dsfield.h
+++ b/include/net/dsfield.h
@@ -20,14 +20,14 @@ static inline __u8 ipv4_get_dsfield(struct iphdr *iph)
static inline __u8 ipv6_get_dsfield(struct ipv6hdr *ipv6h)
{
- return ntohs(*(__u16 *) ipv6h) >> 4;
+ return ntohs(*(__be16 *) ipv6h) >> 4;
}
static inline void ipv4_change_dsfield(struct iphdr *iph,__u8 mask,
__u8 value)
{
- __u32 check = ntohs(iph->check);
+ __u32 check = ntohs((__force __be16)iph->check);
__u8 dsfield;
dsfield = (iph->tos & mask) | value;
@@ -35,7 +35,7 @@ static inline void ipv4_change_dsfield(struct iphdr *iph,__u8 mask,
if ((check+1) >> 16) check = (check+1) & 0xffff;
check -= dsfield;
check += check >> 16; /* adjust carry */
- iph->check = htons(check);
+ iph->check = (__force __sum16)htons(check);
iph->tos = dsfield;
}
@@ -45,9 +45,9 @@ static inline void ipv6_change_dsfield(struct ipv6hdr *ipv6h,__u8 mask,
{
__u16 tmp;
- tmp = ntohs(*(__u16 *) ipv6h);
+ tmp = ntohs(*(__be16 *) ipv6h);
tmp = (tmp & ((mask << 4) | 0xf00f)) | (value << 4);
- *(__u16 *) ipv6h = htons(tmp);
+ *(__be16 *) ipv6h = htons(tmp);
}
diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h
index 8e2f473d3e82..bc3c26494c3d 100644
--- a/include/net/fib_rules.h
+++ b/include/net/fib_rules.h
@@ -13,6 +13,8 @@ struct fib_rule
atomic_t refcnt;
int ifindex;
char ifname[IFNAMSIZ];
+ u32 mark;
+ u32 mark_mask;
u32 pref;
u32 flags;
u32 table;
@@ -50,6 +52,7 @@ struct fib_rules_ops
struct nlmsghdr *,
struct fib_rule_hdr *);
u32 (*default_pref)(void);
+ size_t (*nlmsg_payload)(struct fib_rule *);
int nlgroup;
struct nla_policy *policy;
@@ -57,6 +60,13 @@ struct fib_rules_ops
struct module *owner;
};
+#define FRA_GENERIC_POLICY \
+ [FRA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, \
+ [FRA_PRIORITY] = { .type = NLA_U32 }, \
+ [FRA_FWMARK] = { .type = NLA_U32 }, \
+ [FRA_FWMASK] = { .type = NLA_U32 }, \
+ [FRA_TABLE] = { .type = NLA_U32 }
+
static inline void fib_rule_get(struct fib_rule *rule)
{
atomic_inc(&rule->refcnt);
diff --git a/include/net/flow.h b/include/net/flow.h
index 5cda27cd9deb..ce4b10d8b412 100644
--- a/include/net/flow.h
+++ b/include/net/flow.h
@@ -13,12 +13,12 @@
struct flowi {
int oif;
int iif;
+ __u32 mark;
union {
struct {
__be32 daddr;
__be32 saddr;
- __u32 fwmark;
__u8 tos;
__u8 scope;
} ip4_u;
@@ -26,28 +26,23 @@ struct flowi {
struct {
struct in6_addr daddr;
struct in6_addr saddr;
- __u32 fwmark;
- __u32 flowlabel;
+ __be32 flowlabel;
} ip6_u;
struct {
__le16 daddr;
__le16 saddr;
- __u32 fwmark;
__u8 scope;
} dn_u;
} nl_u;
#define fld_dst nl_u.dn_u.daddr
#define fld_src nl_u.dn_u.saddr
-#define fld_fwmark nl_u.dn_u.fwmark
#define fld_scope nl_u.dn_u.scope
#define fl6_dst nl_u.ip6_u.daddr
#define fl6_src nl_u.ip6_u.saddr
-#define fl6_fwmark nl_u.ip6_u.fwmark
#define fl6_flowlabel nl_u.ip6_u.flowlabel
#define fl4_dst nl_u.ip4_u.daddr
#define fl4_src nl_u.ip4_u.saddr
-#define fl4_fwmark nl_u.ip4_u.fwmark
#define fl4_tos nl_u.ip4_u.tos
#define fl4_scope nl_u.ip4_u.scope
diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index b619314218a6..adff4c898d50 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -53,6 +53,7 @@ struct genl_info
* @policy: attribute validation policy
* @doit: standard command callback
* @dumpit: callback for dumpers
+ * @done: completion callback for dumps
* @ops_list: operations list
*/
struct genl_ops
@@ -64,6 +65,7 @@ struct genl_ops
struct genl_info *info);
int (*dumpit)(struct sk_buff *skb,
struct netlink_callback *cb);
+ int (*done)(struct netlink_callback *cb);
struct list_head ops_list;
};
@@ -79,34 +81,51 @@ extern struct sock *genl_sock;
* @skb: socket buffer holding the message
* @pid: netlink pid the message is addressed to
* @seq: sequence number (usually the one of the sender)
- * @type: netlink message type
- * @hdrlen: length of the user specific header
+ * @family: generic netlink family
* @flags netlink message flags
* @cmd: generic netlink command
- * @version: version
*
* Returns pointer to user specific header
*/
static inline void *genlmsg_put(struct sk_buff *skb, u32 pid, u32 seq,
- int type, int hdrlen, int flags,
- u8 cmd, u8 version)
+ struct genl_family *family, int flags, u8 cmd)
{
struct nlmsghdr *nlh;
struct genlmsghdr *hdr;
- nlh = nlmsg_put(skb, pid, seq, type, GENL_HDRLEN + hdrlen, flags);
+ nlh = nlmsg_put(skb, pid, seq, family->id, GENL_HDRLEN +
+ family->hdrsize, flags);
if (nlh == NULL)
return NULL;
hdr = nlmsg_data(nlh);
hdr->cmd = cmd;
- hdr->version = version;
+ hdr->version = family->version;
hdr->reserved = 0;
return (char *) hdr + GENL_HDRLEN;
}
/**
+ * genlmsg_put_reply - Add generic netlink header to a reply message
+ * @skb: socket buffer holding the message
+ * @info: receiver info
+ * @family: generic netlink family
+ * @flags: netlink message flags
+ * @cmd: generic netlink command
+ *
+ * Returns pointer to user specific header
+ */
+static inline void *genlmsg_put_reply(struct sk_buff *skb,
+ struct genl_info *info,
+ struct genl_family *family,
+ int flags, u8 cmd)
+{
+ return genlmsg_put(skb, info->snd_pid, info->snd_seq, family,
+ flags, cmd);
+}
+
+/**
* genlmsg_end - Finalize a generic netlink message
* @skb: socket buffer the message is stored in
* @hdr: user specific header
@@ -150,6 +169,16 @@ static inline int genlmsg_unicast(struct sk_buff *skb, u32 pid)
}
/**
+ * genlmsg_reply - reply to a request
+ * @skb: netlink message to be sent back
+ * @info: receiver information
+ */
+static inline int genlmsg_reply(struct sk_buff *skb, struct genl_info *info)
+{
+ return genlmsg_unicast(skb, info->snd_pid);
+}
+
+/**
* gennlmsg_data - head of message payload
* @gnlh: genetlink messsage header
*/
@@ -187,4 +216,15 @@ static inline int genlmsg_total_size(int payload)
return NLMSG_ALIGN(genlmsg_msg_size(payload));
}
+/**
+ * genlmsg_new - Allocate a new generic netlink message
+ * @payload: size of the message payload
+ * @flags: the type of memory to allocate.
+ */
+static inline struct sk_buff *genlmsg_new(size_t payload, gfp_t flags)
+{
+ return nlmsg_new(genlmsg_total_size(payload), flags);
+}
+
+
#endif /* __NET_GENERIC_NETLINK_H */
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index b174ebb277a9..e6af381e206d 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -1037,6 +1037,10 @@ struct ieee80211_device {
/* host performs multicast decryption */
int host_mc_decrypt;
+ /* host should strip IV and ICV from protected frames */
+ /* meaningful only when hardware decryption is being used */
+ int host_strip_iv_icv;
+
int host_open_frag;
int host_build_iv;
int ieee802_1x; /* is IEEE 802.1X used */
@@ -1076,6 +1080,8 @@ struct ieee80211_device {
int perfect_rssi;
int worst_rssi;
+ u16 prev_seq_ctl; /* used to drop duplicate frames */
+
/* Callback functions */
void (*set_security) (struct net_device * dev,
struct ieee80211_security * sec);
diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h
index 34489c13c119..3ec7d07346d6 100644
--- a/include/net/if_inet6.h
+++ b/include/net/if_inet6.h
@@ -152,6 +152,7 @@ struct ifacaddr6
struct ipv6_devstat {
struct proc_dir_entry *proc_dir_entry;
+ DEFINE_SNMP_STAT(struct ipstats_mib, ipv6);
DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6);
};
diff --git a/include/net/inet6_connection_sock.h b/include/net/inet6_connection_sock.h
index b33b438bffcc..16aa96a6a53b 100644
--- a/include/net/inet6_connection_sock.h
+++ b/include/net/inet6_connection_sock.h
@@ -27,7 +27,7 @@ extern int inet6_csk_bind_conflict(const struct sock *sk,
extern struct request_sock *inet6_csk_search_req(const struct sock *sk,
struct request_sock ***prevp,
- const __u16 rport,
+ const __be16 rport,
const struct in6_addr *raddr,
const struct in6_addr *laddr,
const int iif);
@@ -38,5 +38,5 @@ extern void inet6_csk_reqsk_queue_hash_add(struct sock *sk,
extern void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr);
-extern int inet6_csk_xmit(struct sk_buff *skb, int ipfragok);
+extern int inet6_csk_xmit(struct sk_buff *skb, struct sock *sk, int ipfragok);
#endif /* _INET6_CONNECTION_SOCK_H */
diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h
index bc6a71dce984..c28e424f53d9 100644
--- a/include/net/inet6_hashtables.h
+++ b/include/net/inet6_hashtables.h
@@ -26,11 +26,11 @@ struct inet_hashinfo;
/* I have no idea if this is a good hash for v6 or not. -DaveM */
static inline unsigned int inet6_ehashfn(const struct in6_addr *laddr, const u16 lport,
- const struct in6_addr *faddr, const u16 fport)
+ const struct in6_addr *faddr, const __be16 fport)
{
- unsigned int hashent = (lport ^ fport);
+ unsigned int hashent = (lport ^ (__force u16)fport);
- hashent ^= (laddr->s6_addr32[3] ^ faddr->s6_addr32[3]);
+ hashent ^= (__force u32)(laddr->s6_addr32[3] ^ faddr->s6_addr32[3]);
hashent ^= hashent >> 16;
hashent ^= hashent >> 8;
return hashent;
@@ -43,7 +43,7 @@ static inline int inet6_sk_ehashfn(const struct sock *sk)
const struct in6_addr *laddr = &np->rcv_saddr;
const struct in6_addr *faddr = &np->daddr;
const __u16 lport = inet->num;
- const __u16 fport = inet->dport;
+ const __be16 fport = inet->dport;
return inet6_ehashfn(laddr, lport, faddr, fport);
}
@@ -57,7 +57,7 @@ extern void __inet6_hash(struct inet_hashinfo *hashinfo, struct sock *sk);
*/
extern struct sock *__inet6_lookup_established(struct inet_hashinfo *hashinfo,
const struct in6_addr *saddr,
- const u16 sport,
+ const __be16 sport,
const struct in6_addr *daddr,
const u16 hnum,
const int dif);
@@ -69,7 +69,7 @@ extern struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo,
static inline struct sock *__inet6_lookup(struct inet_hashinfo *hashinfo,
const struct in6_addr *saddr,
- const u16 sport,
+ const __be16 sport,
const struct in6_addr *daddr,
const u16 hnum,
const int dif)
@@ -83,8 +83,8 @@ static inline struct sock *__inet6_lookup(struct inet_hashinfo *hashinfo,
}
extern struct sock *inet6_lookup(struct inet_hashinfo *hashinfo,
- const struct in6_addr *saddr, const u16 sport,
- const struct in6_addr *daddr, const u16 dport,
+ const struct in6_addr *saddr, const __be16 sport,
+ const struct in6_addr *daddr, const __be16 dport,
const int dif);
#endif /* defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) */
#endif /* _INET6_HASHTABLES_H */
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
index 0bcf9f237e1f..cccea051e922 100644
--- a/include/net/inet_connection_sock.h
+++ b/include/net/inet_connection_sock.h
@@ -36,7 +36,8 @@ struct tcp_congestion_ops;
* (i.e. things that depend on the address family)
*/
struct inet_connection_sock_af_ops {
- int (*queue_xmit)(struct sk_buff *skb, int ipfragok);
+ int (*queue_xmit)(struct sk_buff *skb, struct sock *sk,
+ int ipfragok);
void (*send_check)(struct sock *sk, int len,
struct sk_buff *skb);
int (*rebuild_header)(struct sock *sk);
@@ -45,7 +46,8 @@ struct inet_connection_sock_af_ops {
struct request_sock *req,
struct dst_entry *dst);
int (*remember_stamp)(struct sock *sk);
- __u16 net_header_len;
+ u16 net_header_len;
+ u16 sockaddr_len;
int (*setsockopt)(struct sock *sk, int level, int optname,
char __user *optval, int optlen);
int (*getsockopt)(struct sock *sk, int level, int optname,
@@ -57,7 +59,6 @@ struct inet_connection_sock_af_ops {
int level, int optname,
char __user *optval, int __user *optlen);
void (*addr2sockaddr)(struct sock *sk, struct sockaddr *);
- int sockaddr_len;
};
/** inet_connection_sock - INET connection oriented sock
diff --git a/include/net/inet_ecn.h b/include/net/inet_ecn.h
index 7849844a4911..10117c8503e8 100644
--- a/include/net/inet_ecn.h
+++ b/include/net/inet_ecn.h
@@ -53,7 +53,7 @@ static inline __u8 INET_ECN_encapsulate(__u8 outer, __u8 inner)
static inline int IP_ECN_set_ce(struct iphdr *iph)
{
- u32 check = iph->check;
+ u32 check = (__force u32)iph->check;
u32 ecn = (iph->tos + 1) & INET_ECN_MASK;
/*
@@ -71,9 +71,9 @@ static inline int IP_ECN_set_ce(struct iphdr *iph)
* INET_ECN_ECT_1 => check += htons(0xFFFD)
* INET_ECN_ECT_0 => check += htons(0xFFFE)
*/
- check += htons(0xFFFB) + htons(ecn);
+ check += (__force u16)htons(0xFFFB) + (__force u16)htons(ecn);
- iph->check = check + (check>=0xFFFF);
+ iph->check = (__force __sum16)(check + (check>=0xFFFF));
iph->tos |= INET_ECN_CE;
return 1;
}
@@ -95,13 +95,13 @@ static inline int IP6_ECN_set_ce(struct ipv6hdr *iph)
{
if (INET_ECN_is_not_ect(ipv6_get_dsfield(iph)))
return 0;
- *(u32*)iph |= htonl(INET_ECN_CE << 20);
+ *(__be32*)iph |= htonl(INET_ECN_CE << 20);
return 1;
}
static inline void IP6_ECN_clear(struct ipv6hdr *iph)
{
- *(u32*)iph &= ~htonl(INET_ECN_MASK << 20);
+ *(__be32*)iph &= ~htonl(INET_ECN_MASK << 20);
}
static inline void ipv6_copy_dscp(struct ipv6hdr *outer, struct ipv6hdr *inner)
diff --git a/include/net/ip.h b/include/net/ip.h
index b6d95e553401..83cb9ac5554e 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -97,7 +97,7 @@ 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);
+extern int ip_queue_xmit(struct sk_buff *skb, struct sock *sk, int ipfragok);
extern void ip_init(void);
extern int ip_append_data(struct sock *sk,
int getfrag(void *from, char *to, int offset, int len,
@@ -123,7 +123,7 @@ extern int ip4_datagram_connect(struct sock *sk,
* multicast packets.
*/
-static inline void ip_tr_mc_map(u32 addr, char *buf)
+static inline void ip_tr_mc_map(__be32 addr, char *buf)
{
buf[0]=0xC0;
buf[1]=0x00;
@@ -135,7 +135,7 @@ static inline void ip_tr_mc_map(u32 addr, char *buf)
struct ip_reply_arg {
struct kvec iov[1];
- u32 csum;
+ __wsum csum;
int csumoffset; /* u16 offset of csum in iov[0].iov_base */
/* -1 if not needed */
};
@@ -192,9 +192,9 @@ extern void ipfrag_init(void);
static inline
int ip_decrease_ttl(struct iphdr *iph)
{
- u32 check = iph->check;
- check += htons(0x0100);
- iph->check = check + (check>=0xFFFF);
+ u32 check = (__force u32)iph->check;
+ check += (__force u32)htons(0x0100);
+ iph->check = (__force __sum16)(check + (check>=0xFFFF));
return --iph->ttl;
}
@@ -238,9 +238,9 @@ static inline void ip_select_ident_more(struct iphdr *iph, struct dst_entry *dst
* Map a multicast IP onto multicast MAC for type ethernet.
*/
-static inline void ip_eth_mc_map(u32 addr, char *buf)
+static inline void ip_eth_mc_map(__be32 naddr, char *buf)
{
- addr=ntohl(addr);
+ __u32 addr=ntohl(naddr);
buf[0]=0x01;
buf[1]=0x00;
buf[2]=0x5e;
@@ -256,13 +256,14 @@ static inline void ip_eth_mc_map(u32 addr, char *buf)
* Leave P_Key as 0 to be filled in by driver.
*/
-static inline void ip_ib_mc_map(u32 addr, char *buf)
+static inline void ip_ib_mc_map(__be32 naddr, char *buf)
{
+ __u32 addr;
buf[0] = 0; /* Reserved */
buf[1] = 0xff; /* Multicast QPN */
buf[2] = 0xff;
buf[3] = 0xff;
- addr = ntohl(addr);
+ addr = ntohl(naddr);
buf[4] = 0xff;
buf[5] = 0x12; /* link local scope */
buf[6] = 0x40; /* IPv4 signature */
diff --git a/include/net/ip6_checksum.h b/include/net/ip6_checksum.h
index 3dfc885bdf25..68e2b32cf1d6 100644
--- a/include/net/ip6_checksum.h
+++ b/include/net/ip6_checksum.h
@@ -34,60 +34,60 @@
#ifndef _HAVE_ARCH_IPV6_CSUM
-static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
- struct in6_addr *daddr,
- __u16 len,
- unsigned short proto,
- unsigned int csum)
+static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+ const struct in6_addr *daddr,
+ __u32 len, unsigned short proto,
+ __wsum csum)
{
int carry;
__u32 ulen;
__u32 uproto;
+ __u32 sum = (__force u32)csum;
- csum += saddr->s6_addr32[0];
- carry = (csum < saddr->s6_addr32[0]);
- csum += carry;
+ sum += (__force u32)saddr->s6_addr32[0];
+ carry = (sum < (__force u32)saddr->s6_addr32[0]);
+ sum += carry;
- csum += saddr->s6_addr32[1];
- carry = (csum < saddr->s6_addr32[1]);
- csum += carry;
+ sum += (__force u32)saddr->s6_addr32[1];
+ carry = (sum < (__force u32)saddr->s6_addr32[1]);
+ sum += carry;
- csum += saddr->s6_addr32[2];
- carry = (csum < saddr->s6_addr32[2]);
- csum += carry;
+ sum += (__force u32)saddr->s6_addr32[2];
+ carry = (sum < (__force u32)saddr->s6_addr32[2]);
+ sum += carry;
- csum += saddr->s6_addr32[3];
- carry = (csum < saddr->s6_addr32[3]);
- csum += carry;
+ sum += (__force u32)saddr->s6_addr32[3];
+ carry = (sum < (__force u32)saddr->s6_addr32[3]);
+ sum += carry;
- csum += daddr->s6_addr32[0];
- carry = (csum < daddr->s6_addr32[0]);
- csum += carry;
+ sum += (__force u32)daddr->s6_addr32[0];
+ carry = (sum < (__force u32)daddr->s6_addr32[0]);
+ sum += carry;
- csum += daddr->s6_addr32[1];
- carry = (csum < daddr->s6_addr32[1]);
- csum += carry;
+ sum += (__force u32)daddr->s6_addr32[1];
+ carry = (sum < (__force u32)daddr->s6_addr32[1]);
+ sum += carry;
- csum += daddr->s6_addr32[2];
- carry = (csum < daddr->s6_addr32[2]);
- csum += carry;
+ sum += (__force u32)daddr->s6_addr32[2];
+ carry = (sum < (__force u32)daddr->s6_addr32[2]);
+ sum += carry;
- csum += daddr->s6_addr32[3];
- carry = (csum < daddr->s6_addr32[3]);
- csum += carry;
+ sum += (__force u32)daddr->s6_addr32[3];
+ carry = (sum < (__force u32)daddr->s6_addr32[3]);
+ sum += carry;
- ulen = htonl((__u32) len);
- csum += ulen;
- carry = (csum < ulen);
- csum += carry;
+ ulen = (__force u32)htonl((__u32) len);
+ sum += ulen;
+ carry = (sum < ulen);
+ sum += carry;
- uproto = htonl(proto);
- csum += uproto;
- carry = (csum < uproto);
- csum += carry;
+ uproto = (__force u32)htonl(proto);
+ sum += uproto;
+ carry = (sum < uproto);
+ sum += carry;
- return csum_fold(csum);
+ return csum_fold((__force __wsum)csum);
}
#endif
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index e4438de3bd6b..f9cde44f93b4 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -107,6 +107,11 @@ struct rt6_info
u8 rt6i_protocol;
};
+static inline struct inet6_dev *ip6_dst_idev(struct dst_entry *dst)
+{
+ return ((struct rt6_info *)dst)->rt6i_idev;
+}
+
struct fib6_walker_t
{
struct fib6_walker_t *prev, *next;
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index c14b70ed4c57..4e927ebd1cb3 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -20,7 +20,7 @@ struct route_info {
route_pref:2,
reserved_h:3;
#endif
- __u32 lifetime;
+ __be32 lifetime;
__u8 prefix[0]; /* 0,8 or 16 */
};
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 949b932d2f08..36c635ca1aa6 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -115,7 +115,7 @@ struct fib_result {
struct fib_result_nl {
__be32 fl_addr; /* To be looked up*/
- u32 fl_fwmark;
+ u32 fl_mark;
unsigned char fl_tos;
unsigned char fl_scope;
unsigned char tb_id_in;
diff --git a/include/net/ip_mp_alg.h b/include/net/ip_mp_alg.h
index beffdd66ad74..25b56571e54b 100644
--- a/include/net/ip_mp_alg.h
+++ b/include/net/ip_mp_alg.h
@@ -88,9 +88,7 @@ static inline int multipath_comparekeys(const struct flowi *flp1,
return flp1->fl4_dst == flp2->fl4_dst &&
flp1->fl4_src == flp2->fl4_src &&
flp1->oif == flp2->oif &&
-#ifdef CONFIG_IP_ROUTE_FWMARK
- flp1->fl4_fwmark == flp2->fl4_fwmark &&
-#endif
+ flp1->mark == flp2->mark &&
!((flp1->fl4_tos ^ flp2->fl4_tos) &
(IPTOS_RT_MASK | RTO_ONLINK));
}
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 903108e583f8..672564e5a81d 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -988,14 +988,20 @@ extern int ip_vs_make_skb_writable(struct sk_buff **pskb, int len);
extern void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp,
struct ip_vs_conn *cp, int dir);
-extern u16 ip_vs_checksum_complete(struct sk_buff *skb, int offset);
+extern __sum16 ip_vs_checksum_complete(struct sk_buff *skb, int offset);
-static inline u16 ip_vs_check_diff(u32 old, u32 new, u16 oldsum)
+static inline __wsum ip_vs_check_diff4(__be32 old, __be32 new, __wsum oldsum)
{
- u32 diff[2] = { old, new };
+ __be32 diff[2] = { ~old, new };
- return csum_fold(csum_partial((char *) diff, sizeof(diff),
- oldsum ^ 0xFFFF));
+ return csum_partial((char *) diff, sizeof(diff), oldsum);
+}
+
+static inline __wsum ip_vs_check_diff2(__be16 old, __be16 new, __wsum oldsum)
+{
+ __be16 diff[2] = { ~old, new };
+
+ return csum_partial((char *) diff, sizeof(diff), oldsum);
}
#endif /* __KERNEL__ */
diff --git a/include/net/ipconfig.h b/include/net/ipconfig.h
index 2a1fe996fbc6..3924d7d2cb11 100644
--- a/include/net/ipconfig.h
+++ b/include/net/ipconfig.h
@@ -11,12 +11,12 @@
extern int ic_proto_enabled; /* Protocols enabled (see IC_xxx) */
extern int ic_set_manually; /* IPconfig parameters set manually */
-extern u32 ic_myaddr; /* My IP address */
-extern u32 ic_gateway; /* Gateway IP address */
+extern __be32 ic_myaddr; /* My IP address */
+extern __be32 ic_gateway; /* Gateway IP address */
-extern u32 ic_servaddr; /* Boot server IP address */
+extern __be32 ic_servaddr; /* Boot server IP address */
-extern u32 root_server_addr; /* Address of NFS server */
+extern __be32 root_server_addr; /* Address of NFS server */
extern u8 root_server_path[]; /* Path to mount as root */
diff --git a/include/net/ipip.h b/include/net/ipip.h
index f490c3cbe377..7cdc914322f0 100644
--- a/include/net/ipip.h
+++ b/include/net/ipip.h
@@ -35,7 +35,7 @@ struct ip_tunnel
ip_send_check(iph); \
\
err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev, dst_output);\
- if (err == NET_XMIT_SUCCESS || err == NET_XMIT_CN) { \
+ if (net_xmit_eval(err) == 0) { \
stats->tx_bytes += pkt_len; \
stats->tx_packets++; \
} else { \
@@ -44,8 +44,4 @@ struct ip_tunnel
} \
} while (0)
-
-extern int sit_init(void);
-extern void sit_cleanup(void);
-
#endif
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 8223c4410b4b..00328b71a08c 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -95,10 +95,10 @@
*/
struct frag_hdr {
- unsigned char nexthdr;
- unsigned char reserved;
- unsigned short frag_off;
- __u32 identification;
+ __u8 nexthdr;
+ __u8 reserved;
+ __be16 frag_off;
+ __be32 identification;
};
#define IP6_MF 0x0001
@@ -113,9 +113,24 @@ extern int sysctl_mld_max_msf;
/* MIBs */
DECLARE_SNMP_STAT(struct ipstats_mib, ipv6_statistics);
-#define IP6_INC_STATS(field) SNMP_INC_STATS(ipv6_statistics, field)
-#define IP6_INC_STATS_BH(field) SNMP_INC_STATS_BH(ipv6_statistics, field)
-#define IP6_INC_STATS_USER(field) SNMP_INC_STATS_USER(ipv6_statistics, field)
+#define IP6_INC_STATS(idev,field) ({ \
+ struct inet6_dev *_idev = (idev); \
+ if (likely(_idev != NULL)) \
+ SNMP_INC_STATS(_idev->stats.ipv6, field); \
+ SNMP_INC_STATS(ipv6_statistics, field); \
+})
+#define IP6_INC_STATS_BH(idev,field) ({ \
+ struct inet6_dev *_idev = (idev); \
+ if (likely(_idev != NULL)) \
+ SNMP_INC_STATS_BH(_idev->stats.ipv6, field); \
+ SNMP_INC_STATS_BH(ipv6_statistics, field); \
+})
+#define IP6_INC_STATS_USER(idev,field) ({ \
+ struct inet6_dev *_idev = (idev); \
+ if (likely(_idev != NULL)) \
+ SNMP_INC_STATS_USER(_idev->stats.ipv6, field); \
+ SNMP_INC_STATS_USER(ipv6_statistics, field); \
+})
DECLARE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics);
#define ICMP6_INC_STATS(idev, field) ({ \
struct inet6_dev *_idev = (idev); \
@@ -143,9 +158,13 @@ DECLARE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics);
SNMP_INC_STATS_OFFSET_BH(icmpv6_statistics, field, _offset); \
})
DECLARE_SNMP_STAT(struct udp_mib, udp_stats_in6);
-#define UDP6_INC_STATS(field) SNMP_INC_STATS(udp_stats_in6, field)
-#define UDP6_INC_STATS_BH(field) SNMP_INC_STATS_BH(udp_stats_in6, field)
-#define UDP6_INC_STATS_USER(field) SNMP_INC_STATS_USER(udp_stats_in6, field)
+DECLARE_SNMP_STAT(struct udp_mib, udplite_stats_in6);
+#define UDP6_INC_STATS_BH(field, is_udplite) do { \
+ if (is_udplite) SNMP_INC_STATS_BH(udplite_stats_in6, field); \
+ else SNMP_INC_STATS_BH(udp_stats_in6, field); } while(0)
+#define UDP6_INC_STATS_USER(field, is_udplite) do { \
+ if (is_udplite) SNMP_INC_STATS_USER(udplite_stats_in6, field); \
+ else SNMP_INC_STATS_USER(udp_stats_in6, field); } while(0)
int snmp6_register_dev(struct inet6_dev *idev);
int snmp6_unregister_dev(struct inet6_dev *idev);
@@ -191,7 +210,7 @@ struct ipv6_txoptions
struct ip6_flowlabel
{
struct ip6_flowlabel *next;
- u32 label;
+ __be32 label;
struct in6_addr dst;
struct ipv6_txoptions *opt;
atomic_t users;
@@ -211,7 +230,7 @@ struct ipv6_fl_socklist
struct ip6_flowlabel *fl;
};
-extern struct ip6_flowlabel *fl6_sock_lookup(struct sock *sk, u32 label);
+extern struct ip6_flowlabel *fl6_sock_lookup(struct sock *sk, __be32 label);
extern struct ipv6_txoptions *fl6_merge_options(struct ipv6_txoptions * opt_space,
struct ip6_flowlabel * fl,
struct ipv6_txoptions * fopt);
@@ -375,22 +394,15 @@ static inline int ipv6_addr_any(const struct in6_addr *a)
*/
static inline int __ipv6_addr_diff(const void *token1, const void *token2, int addrlen)
{
- const __u32 *a1 = token1, *a2 = token2;
+ const __be32 *a1 = token1, *a2 = token2;
int i;
addrlen >>= 2;
for (i = 0; i < addrlen; i++) {
- __u32 xb = a1[i] ^ a2[i];
- if (xb) {
- int j = 31;
-
- xb = ntohl(xb);
- while ((xb & (1 << j)) == 0)
- j--;
-
- return (i * 32 + 31 - j);
- }
+ __be32 xb = a1[i] ^ a2[i];
+ if (xb)
+ return i * 32 + 32 - fls(ntohl(xb));
}
/*
@@ -544,7 +556,7 @@ extern int ip6_datagram_connect(struct sock *sk,
struct sockaddr *addr, int addr_len);
extern int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len);
-extern void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, u16 port,
+extern void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, __be16 port,
u32 info, u8 *payload);
extern void ipv6_local_error(struct sock *sk, int err, struct flowi *fl, u32 info);
@@ -589,6 +601,8 @@ extern int tcp6_proc_init(void);
extern void tcp6_proc_exit(void);
extern int udp6_proc_init(void);
extern void udp6_proc_exit(void);
+extern int udplite6_proc_init(void);
+extern void udplite6_proc_exit(void);
extern int ipv6_misc_proc_init(void);
extern void ipv6_misc_proc_exit(void);
diff --git a/include/net/irda/irlap_frame.h b/include/net/irda/irlap_frame.h
index 9dd54a5002b2..641f88e848bd 100644
--- a/include/net/irda/irlap_frame.h
+++ b/include/net/irda/irlap_frame.h
@@ -91,8 +91,8 @@ struct xid_frame {
__u8 caddr; /* Connection address */
__u8 control;
__u8 ident; /* Should always be XID_FORMAT */
- __u32 saddr; /* Source device address */
- __u32 daddr; /* Destination device address */
+ __le32 saddr; /* Source device address */
+ __le32 daddr; /* Destination device address */
__u8 flags; /* Discovery flags */
__u8 slotnr;
__u8 version;
@@ -101,15 +101,15 @@ struct xid_frame {
struct test_frame {
__u8 caddr; /* Connection address */
__u8 control;
- __u32 saddr; /* Source device address */
- __u32 daddr; /* Destination device address */
+ __le32 saddr; /* Source device address */
+ __le32 daddr; /* Destination device address */
} IRDA_PACK;
struct ua_frame {
__u8 caddr;
__u8 control;
- __u32 saddr; /* Source device address */
- __u32 daddr; /* Dest device address */
+ __le32 saddr; /* Source device address */
+ __le32 daddr; /* Dest device address */
} IRDA_PACK;
struct dm_frame {
@@ -135,8 +135,8 @@ struct i_frame {
struct snrm_frame {
__u8 caddr;
__u8 control;
- __u32 saddr;
- __u32 daddr;
+ __le32 saddr;
+ __le32 daddr;
__u8 ncaddr;
} IRDA_PACK;
diff --git a/include/net/llc_pdu.h b/include/net/llc_pdu.h
index 8f6306581fa7..aa33a477c3fb 100644
--- a/include/net/llc_pdu.h
+++ b/include/net/llc_pdu.h
@@ -252,9 +252,9 @@ static inline void llc_pdu_header_init(struct sk_buff *skb, u8 type,
*/
static inline void llc_pdu_decode_sa(struct sk_buff *skb, u8 *sa)
{
- if (skb->protocol == ntohs(ETH_P_802_2))
+ if (skb->protocol == htons(ETH_P_802_2))
memcpy(sa, eth_hdr(skb)->h_source, ETH_ALEN);
- else if (skb->protocol == ntohs(ETH_P_TR_802_2)) {
+ else if (skb->protocol == htons(ETH_P_TR_802_2)) {
memcpy(sa, tr_hdr(skb)->saddr, ETH_ALEN);
*sa &= 0x7F;
}
@@ -269,9 +269,9 @@ static inline void llc_pdu_decode_sa(struct sk_buff *skb, u8 *sa)
*/
static inline void llc_pdu_decode_da(struct sk_buff *skb, u8 *da)
{
- if (skb->protocol == ntohs(ETH_P_802_2))
+ if (skb->protocol == htons(ETH_P_802_2))
memcpy(da, eth_hdr(skb)->h_dest, ETH_ALEN);
- else if (skb->protocol == ntohs(ETH_P_TR_802_2))
+ else if (skb->protocol == htons(ETH_P_TR_802_2))
memcpy(da, tr_hdr(skb)->daddr, ETH_ALEN);
}
@@ -345,7 +345,7 @@ static inline void llc_pdu_init_as_test_rsp(struct sk_buff *skb,
pdu->ctrl_1 = LLC_PDU_TYPE_U;
pdu->ctrl_1 |= LLC_1_PDU_CMD_TEST;
pdu->ctrl_1 |= LLC_U_PF_BIT_MASK;
- if (ev_skb->protocol == ntohs(ETH_P_802_2)) {
+ if (ev_skb->protocol == htons(ETH_P_802_2)) {
struct llc_pdu_un *ev_pdu = llc_pdu_un_hdr(ev_skb);
int dsize;
diff --git a/include/net/ndisc.h b/include/net/ndisc.h
index d3915dabe6de..475b10c575b3 100644
--- a/include/net/ndisc.h
+++ b/include/net/ndisc.h
@@ -66,8 +66,8 @@ struct rs_msg {
struct ra_msg {
struct icmp6hdr icmph;
- __u32 reachable_time;
- __u32 retrans_timer;
+ __be32 reachable_time;
+ __be32 retrans_timer;
};
struct nd_opt_hdr {
diff --git a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
index 91684436af8e..1401ccc051c4 100644
--- a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
+++ b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
@@ -9,32 +9,35 @@
#ifndef _NF_CONNTRACK_IPV4_H
#define _NF_CONNTRACK_IPV4_H
-#ifdef CONFIG_IP_NF_NAT_NEEDED
-#include <linux/netfilter_ipv4/ip_nat.h>
+#ifdef CONFIG_NF_NAT_NEEDED
+#include <net/netfilter/nf_nat.h>
+#include <linux/netfilter/nf_conntrack_pptp.h>
/* per conntrack: nat application helper private data */
-union ip_conntrack_nat_help {
+union nf_conntrack_nat_help {
/* insert nat helper private data here */
+ struct nf_nat_pptp nat_pptp_info;
};
-struct nf_conntrack_ipv4_nat {
- struct ip_nat_info info;
- union ip_conntrack_nat_help help;
+struct nf_conn_nat {
+ struct nf_nat_info info;
+ union nf_conntrack_nat_help help;
#if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \
defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE)
int masq_index;
#endif
};
-#endif /* CONFIG_IP_NF_NAT_NEEDED */
-
-struct nf_conntrack_ipv4 {
-#ifdef CONFIG_IP_NF_NAT_NEEDED
- struct nf_conntrack_ipv4_nat *nat;
-#endif
-};
+#endif /* CONFIG_NF_NAT_NEEDED */
/* Returns new sk_buff, or NULL */
struct sk_buff *
nf_ct_ipv4_ct_gather_frags(struct sk_buff *skb);
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4;
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4;
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp;
+
+extern int nf_conntrack_ipv4_compat_init(void);
+extern void nf_conntrack_ipv4_compat_fini(void);
+
#endif /*_NF_CONNTRACK_IPV4_H*/
diff --git a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
new file mode 100644
index 000000000000..b4b6049e01fa
--- /dev/null
+++ b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
@@ -0,0 +1,25 @@
+#ifndef _NF_CONNTRACK_IPV6_H
+#define _NF_CONNTRACK_IPV6_H
+
+extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6;
+
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6;
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6;
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6;
+
+extern int nf_ct_ipv6_skip_exthdr(struct sk_buff *skb, int start,
+ u8 *nexthdrp, int len);
+
+extern int nf_ct_frag6_init(void);
+extern void nf_ct_frag6_cleanup(void);
+extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb);
+extern void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb,
+ struct net_device *in,
+ struct net_device *out,
+ int (*okfn)(struct sk_buff *));
+
+extern unsigned int nf_ct_frag6_timeout;
+extern unsigned int nf_ct_frag6_low_thresh;
+extern unsigned int nf_ct_frag6_high_thresh;
+
+#endif /* _NF_CONNTRACK_IPV6_H*/
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index 1fbd8193d5f1..032b36a0e378 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -21,6 +21,7 @@
#include <linux/netfilter/nf_conntrack_tcp.h>
#include <linux/netfilter/nf_conntrack_sctp.h>
+#include <linux/netfilter/nf_conntrack_proto_gre.h>
#include <net/netfilter/ipv4/nf_conntrack_icmp.h>
#include <net/netfilter/ipv6/nf_conntrack_icmpv6.h>
@@ -33,6 +34,7 @@ union nf_conntrack_proto {
struct ip_ct_tcp tcp;
struct ip_ct_icmp icmp;
struct nf_ct_icmpv6 icmpv6;
+ struct nf_ct_gre gre;
};
union nf_conntrack_expect_proto {
@@ -41,11 +43,15 @@ union nf_conntrack_expect_proto {
/* Add protocol helper include file here */
#include <linux/netfilter/nf_conntrack_ftp.h>
+#include <linux/netfilter/nf_conntrack_pptp.h>
+#include <linux/netfilter/nf_conntrack_h323.h>
/* per conntrack: application helper private data */
union nf_conntrack_help {
/* insert conntrack helper private data (master) here */
- struct ip_ct_ftp_master ct_ftp_info;
+ struct nf_ct_ftp_master ct_ftp_info;
+ struct nf_ct_pptp_master ct_pptp_info;
+ struct nf_ct_h323_master ct_h323_info;
};
#include <linux/types.h>
@@ -79,6 +85,8 @@ struct nf_conn_help {
#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
+#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
+
struct nf_conn
{
/* Usage count in here is 1 for hash table/destruct timer, 1 per skb,
@@ -124,44 +132,6 @@ struct nf_conn
char data[0];
};
-struct nf_conntrack_expect
-{
- /* Internal linked list (global expectation list) */
- struct list_head list;
-
- /* We expect this tuple, with the following mask */
- struct nf_conntrack_tuple tuple, mask;
-
- /* Function to call after setup and insertion */
- void (*expectfn)(struct nf_conn *new,
- struct nf_conntrack_expect *this);
-
- /* The conntrack of the master connection */
- struct nf_conn *master;
-
- /* Timer function; deletes the expectation. */
- struct timer_list timeout;
-
- /* Usage count. */
- atomic_t use;
-
- /* Unique ID */
- unsigned int id;
-
- /* Flags */
- unsigned int flags;
-
-#ifdef CONFIG_NF_NAT_NEEDED
- /* This is the original per-proto part, used to map the
- * expected connection the way the recipient expects. */
- union nf_conntrack_manip_proto saved_proto;
- /* Direction relative to the master connection. */
- enum ip_conntrack_dir dir;
-#endif
-};
-
-#define NF_CT_EXPECT_PERMANENT 0x1
-
static inline struct nf_conn *
nf_ct_tuplehash_to_ctrack(const struct nf_conntrack_tuple_hash *hash)
{
@@ -208,16 +178,6 @@ __nf_conntrack_find(const struct nf_conntrack_tuple *tuple,
extern void nf_conntrack_hash_insert(struct nf_conn *ct);
-extern struct nf_conntrack_expect *
-__nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple);
-
-extern struct nf_conntrack_expect *
-nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple);
-
-extern void nf_ct_unlink_expect(struct nf_conntrack_expect *exp);
-
-extern void nf_ct_remove_expectations(struct nf_conn *ct);
-
extern void nf_conntrack_flush(void);
extern struct nf_conntrack_helper *
@@ -289,89 +249,12 @@ static inline int nf_ct_is_dying(struct nf_conn *ct)
extern unsigned int nf_conntrack_htable_size;
extern int nf_conntrack_checksum;
+extern atomic_t nf_conntrack_count;
+extern int nf_conntrack_max;
+DECLARE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat);
#define NF_CT_STAT_INC(count) (__get_cpu_var(nf_conntrack_stat).count++)
-#ifdef CONFIG_NF_CONNTRACK_EVENTS
-#include <linux/notifier.h>
-#include <linux/interrupt.h>
-
-struct nf_conntrack_ecache {
- struct nf_conn *ct;
- unsigned int events;
-};
-DECLARE_PER_CPU(struct nf_conntrack_ecache, nf_conntrack_ecache);
-
-#define CONNTRACK_ECACHE(x) (__get_cpu_var(nf_conntrack_ecache).x)
-
-extern struct atomic_notifier_head nf_conntrack_chain;
-extern struct atomic_notifier_head nf_conntrack_expect_chain;
-
-static inline int nf_conntrack_register_notifier(struct notifier_block *nb)
-{
- return atomic_notifier_chain_register(&nf_conntrack_chain, nb);
-}
-
-static inline int nf_conntrack_unregister_notifier(struct notifier_block *nb)
-{
- return atomic_notifier_chain_unregister(&nf_conntrack_chain, nb);
-}
-
-static inline int
-nf_conntrack_expect_register_notifier(struct notifier_block *nb)
-{
- return atomic_notifier_chain_register(&nf_conntrack_expect_chain, nb);
-}
-
-static inline int
-nf_conntrack_expect_unregister_notifier(struct notifier_block *nb)
-{
- return atomic_notifier_chain_unregister(&nf_conntrack_expect_chain,
- nb);
-}
-
-extern void nf_ct_deliver_cached_events(const struct nf_conn *ct);
-extern void __nf_ct_event_cache_init(struct nf_conn *ct);
-
-static inline void
-nf_conntrack_event_cache(enum ip_conntrack_events event,
- const struct sk_buff *skb)
-{
- struct nf_conn *ct = (struct nf_conn *)skb->nfct;
- struct nf_conntrack_ecache *ecache;
-
- local_bh_disable();
- ecache = &__get_cpu_var(nf_conntrack_ecache);
- if (ct != ecache->ct)
- __nf_ct_event_cache_init(ct);
- ecache->events |= event;
- local_bh_enable();
-}
-
-static inline void nf_conntrack_event(enum ip_conntrack_events event,
- struct nf_conn *ct)
-{
- if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct))
- atomic_notifier_call_chain(&nf_conntrack_chain, event, ct);
-}
-
-static inline void
-nf_conntrack_expect_event(enum ip_conntrack_expect_events event,
- struct nf_conntrack_expect *exp)
-{
- atomic_notifier_call_chain(&nf_conntrack_expect_chain, event, exp);
-}
-#else /* CONFIG_NF_CONNTRACK_EVENTS */
-static inline void nf_conntrack_event_cache(enum ip_conntrack_events event,
- const struct sk_buff *skb) {}
-static inline void nf_conntrack_event(enum ip_conntrack_events event,
- struct nf_conn *ct) {}
-static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) {}
-static inline void
-nf_conntrack_expect_event(enum ip_conntrack_expect_events event,
- struct nf_conntrack_expect *exp) {}
-#endif /* CONFIG_NF_CONNTRACK_EVENTS */
-
/* no helper, no nat */
#define NF_CT_F_BASIC 0
/* for helper */
@@ -387,17 +270,45 @@ nf_conntrack_unregister_cache(u_int32_t features);
/* valid combinations:
* basic: nf_conn, nf_conn .. nf_conn_help
- * nat: nf_conn .. nf_conn_nat, nf_conn .. nf_conn_nat, nf_conn help
+ * nat: nf_conn .. nf_conn_nat, nf_conn .. nf_conn_nat .. nf_conn help
*/
+#ifdef CONFIG_NF_NAT_NEEDED
+static inline struct nf_conn_nat *nfct_nat(const struct nf_conn *ct)
+{
+ unsigned int offset = sizeof(struct nf_conn);
+
+ if (!(ct->features & NF_CT_F_NAT))
+ return NULL;
+
+ offset = ALIGN(offset, __alignof__(struct nf_conn_nat));
+ return (struct nf_conn_nat *) ((void *)ct + offset);
+}
+
static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct)
{
unsigned int offset = sizeof(struct nf_conn);
if (!(ct->features & NF_CT_F_HELP))
return NULL;
+ if (ct->features & NF_CT_F_NAT) {
+ offset = ALIGN(offset, __alignof__(struct nf_conn_nat));
+ offset += sizeof(struct nf_conn_nat);
+ }
+ offset = ALIGN(offset, __alignof__(struct nf_conn_help));
return (struct nf_conn_help *) ((void *)ct + offset);
}
+#else /* No NAT */
+static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct)
+{
+ unsigned int offset = sizeof(struct nf_conn);
+
+ if (!(ct->features & NF_CT_F_HELP))
+ return NULL;
+ offset = ALIGN(offset, __alignof__(struct nf_conn_help));
+ return (struct nf_conn_help *) ((void *)ct + offset);
+}
+#endif /* CONFIG_NF_NAT_NEEDED */
#endif /* __KERNEL__ */
#endif /* _NF_CONNTRACK_H */
diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h
index da254525a4ce..7fdc72c01356 100644
--- a/include/net/netfilter/nf_conntrack_core.h
+++ b/include/net/netfilter/nf_conntrack_core.h
@@ -13,6 +13,9 @@
#define _NF_CONNTRACK_CORE_H
#include <linux/netfilter.h>
+#include <net/netfilter/nf_conntrack_l3proto.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
+#include <net/netfilter/nf_conntrack_ecache.h>
/* This header is used to share core functionality between the
standalone connection tracking module, and the compatibility layer's use
@@ -29,7 +32,7 @@ extern struct nf_conntrack_l3proto *nf_ct_find_l3proto(u_int16_t pf);
/* Like above, but you already have conntrack read lock. */
extern struct nf_conntrack_l3proto *__nf_ct_find_l3proto(u_int16_t l3proto);
-struct nf_conntrack_protocol;
+struct nf_conntrack_l4proto;
extern int
nf_ct_get_tuple(const struct sk_buff *skb,
@@ -39,13 +42,13 @@ nf_ct_get_tuple(const struct sk_buff *skb,
u_int8_t protonum,
struct nf_conntrack_tuple *tuple,
const struct nf_conntrack_l3proto *l3proto,
- const struct nf_conntrack_protocol *protocol);
+ const struct nf_conntrack_l4proto *l4proto);
extern int
nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
const struct nf_conntrack_tuple *orig,
const struct nf_conntrack_l3proto *l3proto,
- const struct nf_conntrack_protocol *protocol);
+ const struct nf_conntrack_l4proto *l4proto);
/* Find a connection corresponding to a tuple. */
extern struct nf_conntrack_tuple_hash *
@@ -70,7 +73,14 @@ static inline int nf_conntrack_confirm(struct sk_buff **pskb)
extern void __nf_conntrack_attach(struct sk_buff *nskb, struct sk_buff *skb);
+int
+print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple,
+ struct nf_conntrack_l3proto *l3proto,
+ struct nf_conntrack_l4proto *proto);
+
extern struct list_head *nf_conntrack_hash;
extern struct list_head nf_conntrack_expect_list;
extern rwlock_t nf_conntrack_lock ;
+extern struct list_head unconfirmed;
+
#endif /* _NF_CONNTRACK_CORE_H */
diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h
new file mode 100644
index 000000000000..b62a8a9ec9d8
--- /dev/null
+++ b/include/net/netfilter/nf_conntrack_ecache.h
@@ -0,0 +1,95 @@
+/*
+ * connection tracking event cache.
+ */
+
+#ifndef _NF_CONNTRACK_ECACHE_H
+#define _NF_CONNTRACK_ECACHE_H
+#include <net/netfilter/nf_conntrack.h>
+
+#include <linux/notifier.h>
+#include <linux/interrupt.h>
+#include <net/netfilter/nf_conntrack_expect.h>
+
+#ifdef CONFIG_NF_CONNTRACK_EVENTS
+struct nf_conntrack_ecache {
+ struct nf_conn *ct;
+ unsigned int events;
+};
+DECLARE_PER_CPU(struct nf_conntrack_ecache, nf_conntrack_ecache);
+
+#define CONNTRACK_ECACHE(x) (__get_cpu_var(nf_conntrack_ecache).x)
+
+extern struct atomic_notifier_head nf_conntrack_chain;
+extern struct atomic_notifier_head nf_conntrack_expect_chain;
+
+static inline int nf_conntrack_register_notifier(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_register(&nf_conntrack_chain, nb);
+}
+
+static inline int nf_conntrack_unregister_notifier(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_unregister(&nf_conntrack_chain, nb);
+}
+
+static inline int
+nf_conntrack_expect_register_notifier(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_register(&nf_conntrack_expect_chain, nb);
+}
+
+static inline int
+nf_conntrack_expect_unregister_notifier(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_unregister(&nf_conntrack_expect_chain,
+ nb);
+}
+
+extern void nf_ct_deliver_cached_events(const struct nf_conn *ct);
+extern void __nf_ct_event_cache_init(struct nf_conn *ct);
+extern void nf_ct_event_cache_flush(void);
+
+static inline void
+nf_conntrack_event_cache(enum ip_conntrack_events event,
+ const struct sk_buff *skb)
+{
+ struct nf_conn *ct = (struct nf_conn *)skb->nfct;
+ struct nf_conntrack_ecache *ecache;
+
+ local_bh_disable();
+ ecache = &__get_cpu_var(nf_conntrack_ecache);
+ if (ct != ecache->ct)
+ __nf_ct_event_cache_init(ct);
+ ecache->events |= event;
+ local_bh_enable();
+}
+
+static inline void nf_conntrack_event(enum ip_conntrack_events event,
+ struct nf_conn *ct)
+{
+ if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct))
+ atomic_notifier_call_chain(&nf_conntrack_chain, event, ct);
+}
+
+static inline void
+nf_conntrack_expect_event(enum ip_conntrack_expect_events event,
+ struct nf_conntrack_expect *exp)
+{
+ atomic_notifier_call_chain(&nf_conntrack_expect_chain, event, exp);
+}
+
+#else /* CONFIG_NF_CONNTRACK_EVENTS */
+
+static inline void nf_conntrack_event_cache(enum ip_conntrack_events event,
+ const struct sk_buff *skb) {}
+static inline void nf_conntrack_event(enum ip_conntrack_events event,
+ struct nf_conn *ct) {}
+static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) {}
+static inline void
+nf_conntrack_expect_event(enum ip_conntrack_expect_events event,
+ struct nf_conntrack_expect *exp) {}
+static inline void nf_ct_event_cache_flush(void) {}
+#endif /* CONFIG_NF_CONNTRACK_EVENTS */
+
+#endif /*_NF_CONNTRACK_ECACHE_H*/
+
diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h
new file mode 100644
index 000000000000..cef3136e22a3
--- /dev/null
+++ b/include/net/netfilter/nf_conntrack_expect.h
@@ -0,0 +1,80 @@
+/*
+ * connection tracking expectations.
+ */
+
+#ifndef _NF_CONNTRACK_EXPECT_H
+#define _NF_CONNTRACK_EXPECT_H
+#include <net/netfilter/nf_conntrack.h>
+
+extern struct list_head nf_conntrack_expect_list;
+extern kmem_cache_t *nf_conntrack_expect_cachep;
+extern struct file_operations exp_file_ops;
+
+struct nf_conntrack_expect
+{
+ /* Internal linked list (global expectation list) */
+ struct list_head list;
+
+ /* We expect this tuple, with the following mask */
+ struct nf_conntrack_tuple tuple, mask;
+
+ /* Function to call after setup and insertion */
+ void (*expectfn)(struct nf_conn *new,
+ struct nf_conntrack_expect *this);
+
+ /* Helper to assign to new connection */
+ struct nf_conntrack_helper *helper;
+
+ /* The conntrack of the master connection */
+ struct nf_conn *master;
+
+ /* Timer function; deletes the expectation. */
+ struct timer_list timeout;
+
+ /* Usage count. */
+ atomic_t use;
+
+ /* Unique ID */
+ unsigned int id;
+
+ /* Flags */
+ unsigned int flags;
+
+#ifdef CONFIG_NF_NAT_NEEDED
+ __be32 saved_ip;
+ /* This is the original per-proto part, used to map the
+ * expected connection the way the recipient expects. */
+ union nf_conntrack_man_proto saved_proto;
+ /* Direction relative to the master connection. */
+ enum ip_conntrack_dir dir;
+#endif
+};
+
+#define NF_CT_EXPECT_PERMANENT 0x1
+
+
+struct nf_conntrack_expect *
+__nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple);
+
+struct nf_conntrack_expect *
+nf_conntrack_expect_find_get(const struct nf_conntrack_tuple *tuple);
+
+struct nf_conntrack_expect *
+find_expectation(const struct nf_conntrack_tuple *tuple);
+
+void nf_ct_unlink_expect(struct nf_conntrack_expect *exp);
+void nf_ct_remove_expectations(struct nf_conn *ct);
+void nf_conntrack_unexpect_related(struct nf_conntrack_expect *exp);
+
+/* Allocate space for an expectation: this is mandatory before calling
+ nf_conntrack_expect_related. You will have to call put afterwards. */
+struct nf_conntrack_expect *nf_conntrack_expect_alloc(struct nf_conn *me);
+void nf_conntrack_expect_init(struct nf_conntrack_expect *, int,
+ union nf_conntrack_address *,
+ union nf_conntrack_address *,
+ u_int8_t, __be16 *, __be16 *);
+void nf_conntrack_expect_put(struct nf_conntrack_expect *exp);
+int nf_conntrack_expect_related(struct nf_conntrack_expect *expect);
+
+#endif /*_NF_CONNTRACK_EXPECT_H*/
+
diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h
index 86ec8174ad02..8c72ac9f0ab8 100644
--- a/include/net/netfilter/nf_conntrack_helper.h
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -34,20 +34,22 @@ struct nf_conntrack_helper
struct nf_conn *ct,
enum ip_conntrack_info conntrackinfo);
+ void (*destroy)(struct nf_conn *ct);
+
int (*to_nfattr)(struct sk_buff *skb, const struct nf_conn *ct);
};
-extern int nf_conntrack_helper_register(struct nf_conntrack_helper *);
-extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *);
+extern struct nf_conntrack_helper *
+__nf_ct_helper_find(const struct nf_conntrack_tuple *tuple);
-/* Allocate space for an expectation: this is mandatory before calling
- nf_conntrack_expect_related. You will have to call put afterwards. */
-extern struct nf_conntrack_expect *
-nf_conntrack_expect_alloc(struct nf_conn *master);
-extern void nf_conntrack_expect_put(struct nf_conntrack_expect *exp);
+extern struct nf_conntrack_helper *
+nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple);
-/* Add an expected connection: can have more than one per connection */
-extern int nf_conntrack_expect_related(struct nf_conntrack_expect *exp);
-extern void nf_conntrack_unexpect_related(struct nf_conntrack_expect *exp);
+extern struct nf_conntrack_helper *
+__nf_conntrack_helper_find_byname(const char *name);
+
+extern void nf_ct_helper_put(struct nf_conntrack_helper *helper);
+extern int nf_conntrack_helper_register(struct nf_conntrack_helper *);
+extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *);
#endif /*_NF_CONNTRACK_HELPER_H*/
diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h
index dac43b15a5b0..664ddcffe00d 100644
--- a/include/net/netfilter/nf_conntrack_l3proto.h
+++ b/include/net/netfilter/nf_conntrack_l3proto.h
@@ -18,9 +18,6 @@ struct nfattr;
struct nf_conntrack_l3proto
{
- /* Next pointer. */
- struct list_head list;
-
/* L3 Protocol Family number. ex) PF_INET */
u_int16_t l3proto;
@@ -78,6 +75,12 @@ struct nf_conntrack_l3proto
int (*nfattr_to_tuple)(struct nfattr *tb[],
struct nf_conntrack_tuple *t);
+#ifdef CONFIG_SYSCTL
+ struct ctl_table_header *ctl_table_header;
+ struct ctl_table *ctl_table_path;
+ struct ctl_table *ctl_table;
+#endif /* CONFIG_SYSCTL */
+
/* Module (if any) which this is connected to. */
struct module *me;
};
@@ -86,7 +89,7 @@ extern struct nf_conntrack_l3proto *nf_ct_l3protos[AF_MAX];
/* Protocol registration. */
extern int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto);
-extern void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto);
+extern int nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto);
extern struct nf_conntrack_l3proto *
nf_ct_l3proto_find_get(u_int16_t l3proto);
@@ -96,13 +99,13 @@ extern void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p);
/* Existing built-in protocols */
extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4;
extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6;
-extern struct nf_conntrack_l3proto nf_conntrack_generic_l3proto;
+extern struct nf_conntrack_l3proto nf_conntrack_l3proto_generic;
static inline struct nf_conntrack_l3proto *
__nf_ct_l3proto_find(u_int16_t l3proto)
{
if (unlikely(l3proto >= AF_MAX))
- return &nf_conntrack_generic_l3proto;
+ return &nf_conntrack_l3proto_generic;
return nf_ct_l3protos[l3proto];
}
diff --git a/include/net/netfilter/nf_conntrack_protocol.h b/include/net/netfilter/nf_conntrack_l4proto.h
index 1f33737fcea5..fc8af08ff542 100644
--- a/include/net/netfilter/nf_conntrack_protocol.h
+++ b/include/net/netfilter/nf_conntrack_l4proto.h
@@ -1,5 +1,5 @@
/*
- * Header for use in defining a given protocol for connection tracking.
+ * Header for use in defining a given L4 protocol for connection tracking.
*
* 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
* - generalized L3 protocol dependent part.
@@ -7,23 +7,20 @@
* Derived from include/linux/netfiter_ipv4/ip_conntrack_protcol.h
*/
-#ifndef _NF_CONNTRACK_PROTOCOL_H
-#define _NF_CONNTRACK_PROTOCOL_H
+#ifndef _NF_CONNTRACK_L4PROTO_H
+#define _NF_CONNTRACK_L4PROTO_H
#include <net/netfilter/nf_conntrack.h>
struct seq_file;
struct nfattr;
-struct nf_conntrack_protocol
+struct nf_conntrack_l4proto
{
- /* Next pointer. */
- struct list_head list;
-
/* L3 Protocol number. */
u_int16_t l3proto;
- /* Protocol number. */
- u_int8_t proto;
+ /* L4 Protocol number. */
+ u_int8_t l4proto;
/* Protocol name */
const char *name;
@@ -79,30 +76,40 @@ struct nf_conntrack_protocol
int (*nfattr_to_tuple)(struct nfattr *tb[],
struct nf_conntrack_tuple *t);
+#ifdef CONFIG_SYSCTL
+ struct ctl_table_header **ctl_table_header;
+ struct ctl_table *ctl_table;
+ unsigned int *ctl_table_users;
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+ struct ctl_table_header *ctl_compat_table_header;
+ struct ctl_table *ctl_compat_table;
+#endif
+#endif
+
/* Module (if any) which this is connected to. */
struct module *me;
};
/* Existing built-in protocols */
-extern struct nf_conntrack_protocol nf_conntrack_protocol_tcp6;
-extern struct nf_conntrack_protocol nf_conntrack_protocol_udp4;
-extern struct nf_conntrack_protocol nf_conntrack_protocol_udp6;
-extern struct nf_conntrack_protocol nf_conntrack_generic_protocol;
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6;
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4;
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6;
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_generic;
#define MAX_NF_CT_PROTO 256
-extern struct nf_conntrack_protocol **nf_ct_protos[PF_MAX];
+extern struct nf_conntrack_l4proto **nf_ct_protos[PF_MAX];
-extern struct nf_conntrack_protocol *
-__nf_ct_proto_find(u_int16_t l3proto, u_int8_t protocol);
+extern struct nf_conntrack_l4proto *
+__nf_ct_l4proto_find(u_int16_t l3proto, u_int8_t l4proto);
-extern struct nf_conntrack_protocol *
-nf_ct_proto_find_get(u_int16_t l3proto, u_int8_t protocol);
+extern struct nf_conntrack_l4proto *
+nf_ct_l4proto_find_get(u_int16_t l3proto, u_int8_t protocol);
-extern void nf_ct_proto_put(struct nf_conntrack_protocol *p);
+extern void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p);
/* Protocol registration. */
-extern int nf_conntrack_protocol_register(struct nf_conntrack_protocol *proto);
-extern void nf_conntrack_protocol_unregister(struct nf_conntrack_protocol *proto);
+extern int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *proto);
+extern int nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *proto);
/* Generic netlink helpers */
extern int nf_ct_port_tuple_to_nfattr(struct sk_buff *skb,
diff --git a/include/net/netfilter/nf_conntrack_tuple.h b/include/net/netfilter/nf_conntrack_tuple.h
index 530ef1f75283..5d72b16e876f 100644
--- a/include/net/netfilter/nf_conntrack_tuple.h
+++ b/include/net/netfilter/nf_conntrack_tuple.h
@@ -24,10 +24,10 @@
/* The l3 protocol-specific manipulable parts of the tuple: always in
network order! */
-union nf_conntrack_man_l3proto {
+union nf_conntrack_address {
u_int32_t all[NF_CT_TUPLE_L3SIZE];
- u_int32_t ip;
- u_int32_t ip6[4];
+ __be32 ip;
+ __be32 ip6[4];
};
/* The protocol-specific manipulable parts of the tuple: always in
@@ -38,23 +38,26 @@ union nf_conntrack_man_proto
u_int16_t all;
struct {
- u_int16_t port;
+ __be16 port;
} tcp;
struct {
- u_int16_t port;
+ __be16 port;
} udp;
struct {
- u_int16_t id;
+ __be16 id;
} icmp;
struct {
- u_int16_t port;
+ __be16 port;
} sctp;
+ struct {
+ __be16 key; /* GRE key is 32bit, PPtP only uses 16bit */
+ } gre;
};
/* The manipulable part of the tuple. */
struct nf_conntrack_man
{
- union nf_conntrack_man_l3proto u3;
+ union nf_conntrack_address u3;
union nf_conntrack_man_proto u;
/* Layer 3 protocol */
u_int16_t l3num;
@@ -67,27 +70,26 @@ struct nf_conntrack_tuple
/* These are the parts of the tuple which are fixed. */
struct {
- union {
- u_int32_t all[NF_CT_TUPLE_L3SIZE];
- u_int32_t ip;
- u_int32_t ip6[4];
- } u3;
+ union nf_conntrack_address u3;
union {
/* Add other protocols here. */
u_int16_t all;
struct {
- u_int16_t port;
+ __be16 port;
} tcp;
struct {
- u_int16_t port;
+ __be16 port;
} udp;
struct {
u_int8_t type, code;
} icmp;
struct {
- u_int16_t port;
+ __be16 port;
} sctp;
+ struct {
+ __be16 key;
+ } gre;
} u;
/* The protocol. */
diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h
new file mode 100644
index 000000000000..61c62068ca6b
--- /dev/null
+++ b/include/net/netfilter/nf_nat.h
@@ -0,0 +1,77 @@
+#ifndef _NF_NAT_H
+#define _NF_NAT_H
+#include <linux/netfilter_ipv4.h>
+#include <net/netfilter/nf_conntrack_tuple.h>
+
+#define NF_NAT_MAPPING_TYPE_MAX_NAMELEN 16
+
+enum nf_nat_manip_type
+{
+ IP_NAT_MANIP_SRC,
+ IP_NAT_MANIP_DST
+};
+
+/* SRC manip occurs POST_ROUTING or LOCAL_IN */
+#define HOOK2MANIP(hooknum) ((hooknum) != NF_IP_POST_ROUTING && (hooknum) != NF_IP_LOCAL_IN)
+
+#define IP_NAT_RANGE_MAP_IPS 1
+#define IP_NAT_RANGE_PROTO_SPECIFIED 2
+
+/* NAT sequence number modifications */
+struct nf_nat_seq {
+ /* position of the last TCP sequence number modification (if any) */
+ u_int32_t correction_pos;
+
+ /* sequence number offset before and after last modification */
+ int16_t offset_before, offset_after;
+};
+
+/* Single range specification. */
+struct nf_nat_range
+{
+ /* Set to OR of flags above. */
+ unsigned int flags;
+
+ /* Inclusive: network order. */
+ __be32 min_ip, max_ip;
+
+ /* Inclusive: network order */
+ union nf_conntrack_man_proto min, max;
+};
+
+/* For backwards compat: don't use in modern code. */
+struct nf_nat_multi_range_compat
+{
+ unsigned int rangesize; /* Must be 1. */
+
+ /* hangs off end. */
+ struct nf_nat_range range[1];
+};
+
+#ifdef __KERNEL__
+#include <linux/list.h>
+
+/* The structure embedded in the conntrack structure. */
+struct nf_nat_info
+{
+ struct list_head bysource;
+ struct nf_nat_seq seq[IP_CT_DIR_MAX];
+};
+
+struct nf_conn;
+
+/* Set up the info structure to map into this range. */
+extern unsigned int nf_nat_setup_info(struct nf_conn *ct,
+ const struct nf_nat_range *range,
+ unsigned int hooknum);
+
+/* Is this tuple already taken? (not by us)*/
+extern int nf_nat_used_tuple(const struct nf_conntrack_tuple *tuple,
+ const struct nf_conn *ignored_conntrack);
+
+extern int nf_nat_module_is_loaded;
+
+#else /* !__KERNEL__: iptables wants this to compile. */
+#define nf_nat_multi_range nf_nat_multi_range_compat
+#endif /*__KERNEL__*/
+#endif
diff --git a/include/net/netfilter/nf_nat_core.h b/include/net/netfilter/nf_nat_core.h
new file mode 100644
index 000000000000..9778ffa93440
--- /dev/null
+++ b/include/net/netfilter/nf_nat_core.h
@@ -0,0 +1,27 @@
+#ifndef _NF_NAT_CORE_H
+#define _NF_NAT_CORE_H
+#include <linux/list.h>
+#include <net/netfilter/nf_conntrack.h>
+
+/* This header used to share core functionality between the standalone
+ NAT module, and the compatibility layer's use of NAT for masquerading. */
+
+extern unsigned int nf_nat_packet(struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned int hooknum,
+ struct sk_buff **pskb);
+
+extern int nf_nat_icmp_reply_translation(struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned int hooknum,
+ struct sk_buff **pskb);
+
+static inline int nf_nat_initialized(struct nf_conn *ct,
+ enum nf_nat_manip_type manip)
+{
+ if (manip == IP_NAT_MANIP_SRC)
+ return test_bit(IPS_SRC_NAT_DONE_BIT, &ct->status);
+ else
+ return test_bit(IPS_DST_NAT_DONE_BIT, &ct->status);
+}
+#endif /* _NF_NAT_CORE_H */
diff --git a/include/net/netfilter/nf_nat_helper.h b/include/net/netfilter/nf_nat_helper.h
new file mode 100644
index 000000000000..ec98ecf95fc8
--- /dev/null
+++ b/include/net/netfilter/nf_nat_helper.h
@@ -0,0 +1,32 @@
+#ifndef _NF_NAT_HELPER_H
+#define _NF_NAT_HELPER_H
+/* NAT protocol helper routines. */
+
+#include <net/netfilter/nf_conntrack.h>
+
+struct sk_buff;
+
+/* These return true or false. */
+extern int nf_nat_mangle_tcp_packet(struct sk_buff **skb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned int match_offset,
+ unsigned int match_len,
+ const char *rep_buffer,
+ unsigned int rep_len);
+extern int nf_nat_mangle_udp_packet(struct sk_buff **skb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned int match_offset,
+ unsigned int match_len,
+ const char *rep_buffer,
+ unsigned int rep_len);
+extern int nf_nat_seq_adjust(struct sk_buff **pskb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo);
+
+/* Setup NAT on this expected conntrack so it follows master, but goes
+ * to port ct->master->saved_proto. */
+extern void nf_nat_follow_master(struct nf_conn *ct,
+ struct nf_conntrack_expect *this);
+#endif
diff --git a/include/net/netfilter/nf_nat_protocol.h b/include/net/netfilter/nf_nat_protocol.h
new file mode 100644
index 000000000000..a9ec5ef61468
--- /dev/null
+++ b/include/net/netfilter/nf_nat_protocol.h
@@ -0,0 +1,70 @@
+/* Header for use in defining a given protocol. */
+#ifndef _NF_NAT_PROTOCOL_H
+#define _NF_NAT_PROTOCOL_H
+#include <net/netfilter/nf_nat.h>
+#include <linux/netfilter/nfnetlink_conntrack.h>
+
+struct nf_nat_range;
+
+struct nf_nat_protocol
+{
+ /* Protocol name */
+ const char *name;
+
+ /* Protocol number. */
+ unsigned int protonum;
+
+ struct module *me;
+
+ /* Translate a packet to the target according to manip type.
+ Return true if succeeded. */
+ int (*manip_pkt)(struct sk_buff **pskb,
+ unsigned int iphdroff,
+ const struct nf_conntrack_tuple *tuple,
+ enum nf_nat_manip_type maniptype);
+
+ /* Is the manipable part of the tuple between min and max incl? */
+ int (*in_range)(const struct nf_conntrack_tuple *tuple,
+ enum nf_nat_manip_type maniptype,
+ const union nf_conntrack_man_proto *min,
+ const union nf_conntrack_man_proto *max);
+
+ /* Alter the per-proto part of the tuple (depending on
+ maniptype), to give a unique tuple in the given range if
+ possible; return false if not. Per-protocol part of tuple
+ is initialized to the incoming packet. */
+ int (*unique_tuple)(struct nf_conntrack_tuple *tuple,
+ const struct nf_nat_range *range,
+ enum nf_nat_manip_type maniptype,
+ const struct nf_conn *ct);
+
+ int (*range_to_nfattr)(struct sk_buff *skb,
+ const struct nf_nat_range *range);
+
+ int (*nfattr_to_range)(struct nfattr *tb[],
+ struct nf_nat_range *range);
+};
+
+/* Protocol registration. */
+extern int nf_nat_protocol_register(struct nf_nat_protocol *proto);
+extern void nf_nat_protocol_unregister(struct nf_nat_protocol *proto);
+
+extern struct nf_nat_protocol *nf_nat_proto_find_get(u_int8_t protocol);
+extern void nf_nat_proto_put(struct nf_nat_protocol *proto);
+
+/* Built-in protocols. */
+extern struct nf_nat_protocol nf_nat_protocol_tcp;
+extern struct nf_nat_protocol nf_nat_protocol_udp;
+extern struct nf_nat_protocol nf_nat_protocol_icmp;
+extern struct nf_nat_protocol nf_nat_unknown_protocol;
+
+extern int init_protocols(void) __init;
+extern void cleanup_protocols(void);
+extern struct nf_nat_protocol *find_nat_proto(u_int16_t protonum);
+
+extern int nf_nat_port_range_to_nfattr(struct sk_buff *skb,
+ const struct nf_nat_range *range);
+extern int nf_nat_port_nfattr_to_range(struct nfattr *tb[],
+ struct nf_nat_range *range);
+
+#endif /*_NF_NAT_PROTO_H*/
diff --git a/include/net/netfilter/nf_nat_rule.h b/include/net/netfilter/nf_nat_rule.h
new file mode 100644
index 000000000000..f191c672bcc6
--- /dev/null
+++ b/include/net/netfilter/nf_nat_rule.h
@@ -0,0 +1,35 @@
+#ifndef _NF_NAT_RULE_H
+#define _NF_NAT_RULE_H
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_nat.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+
+/* Compatibility definitions for ipt_FOO modules */
+#define ip_nat_range nf_nat_range
+#define ip_conntrack_tuple nf_conntrack_tuple
+#define ip_conntrack_get nf_ct_get
+#define ip_conntrack nf_conn
+#define ip_nat_setup_info nf_nat_setup_info
+#define ip_nat_multi_range_compat nf_nat_multi_range_compat
+#define ip_ct_iterate_cleanup nf_ct_iterate_cleanup
+#define IP_NF_ASSERT NF_CT_ASSERT
+
+extern int nf_nat_rule_init(void) __init;
+extern void nf_nat_rule_cleanup(void);
+extern int nf_nat_rule_find(struct sk_buff **pskb,
+ unsigned int hooknum,
+ const struct net_device *in,
+ const struct net_device *out,
+ struct nf_conn *ct,
+ struct nf_nat_info *info);
+
+extern unsigned int
+alloc_null_binding(struct nf_conn *ct,
+ struct nf_nat_info *info,
+ unsigned int hooknum);
+
+extern unsigned int
+alloc_null_binding_confirmed(struct nf_conn *ct,
+ struct nf_nat_info *info,
+ unsigned int hooknum);
+#endif /* _NF_NAT_RULE_H */
diff --git a/include/net/netlabel.h b/include/net/netlabel.h
index 12c214b9eadf..83da7e1f0d3d 100644
--- a/include/net/netlabel.h
+++ b/include/net/netlabel.h
@@ -111,13 +111,34 @@ struct netlbl_lsm_cache {
void (*free) (const void *data);
void *data;
};
+/* The catmap bitmap field MUST be a power of two in length and large
+ * enough to hold at least 240 bits. Special care (i.e. check the code!)
+ * should be used when changing these values as the LSM implementation
+ * probably has functions which rely on the sizes of these types to speed
+ * processing. */
+#define NETLBL_CATMAP_MAPTYPE u64
+#define NETLBL_CATMAP_MAPCNT 4
+#define NETLBL_CATMAP_MAPSIZE (sizeof(NETLBL_CATMAP_MAPTYPE) * 8)
+#define NETLBL_CATMAP_SIZE (NETLBL_CATMAP_MAPSIZE * \
+ NETLBL_CATMAP_MAPCNT)
+#define NETLBL_CATMAP_BIT (NETLBL_CATMAP_MAPTYPE)0x01
+struct netlbl_lsm_secattr_catmap {
+ u32 startbit;
+ NETLBL_CATMAP_MAPTYPE bitmap[NETLBL_CATMAP_MAPCNT];
+ struct netlbl_lsm_secattr_catmap *next;
+};
+#define NETLBL_SECATTR_NONE 0x00000000
+#define NETLBL_SECATTR_DOMAIN 0x00000001
+#define NETLBL_SECATTR_CACHE 0x00000002
+#define NETLBL_SECATTR_MLS_LVL 0x00000004
+#define NETLBL_SECATTR_MLS_CAT 0x00000008
struct netlbl_lsm_secattr {
+ u32 flags;
+
char *domain;
u32 mls_lvl;
- u32 mls_lvl_vld;
- unsigned char *mls_cat;
- size_t mls_cat_len;
+ struct netlbl_lsm_secattr_catmap *mls_cat;
struct netlbl_lsm_cache *cache;
};
@@ -165,18 +186,54 @@ static inline void netlbl_secattr_cache_free(struct netlbl_lsm_cache *cache)
}
/**
+ * netlbl_secattr_catmap_alloc - Allocate a LSM secattr catmap
+ * @flags: memory allocation flags
+ *
+ * Description:
+ * Allocate memory for a LSM secattr catmap, returns a pointer on success, NULL
+ * on failure.
+ *
+ */
+static inline struct netlbl_lsm_secattr_catmap *netlbl_secattr_catmap_alloc(
+ gfp_t flags)
+{
+ return kzalloc(sizeof(struct netlbl_lsm_secattr_catmap), flags);
+}
+
+/**
+ * netlbl_secattr_catmap_free - Free a LSM secattr catmap
+ * @catmap: the category bitmap
+ *
+ * Description:
+ * Free a LSM secattr catmap.
+ *
+ */
+static inline void netlbl_secattr_catmap_free(
+ struct netlbl_lsm_secattr_catmap *catmap)
+{
+ struct netlbl_lsm_secattr_catmap *iter;
+
+ do {
+ iter = catmap;
+ catmap = catmap->next;
+ kfree(iter);
+ } while (catmap);
+}
+
+/**
* netlbl_secattr_init - Initialize a netlbl_lsm_secattr struct
* @secattr: the struct to initialize
*
* Description:
- * Initialize an already allocated netlbl_lsm_secattr struct. Returns zero on
- * success, negative values on error.
+ * Initialize an already allocated netlbl_lsm_secattr struct.
*
*/
-static inline int netlbl_secattr_init(struct netlbl_lsm_secattr *secattr)
+static inline void netlbl_secattr_init(struct netlbl_lsm_secattr *secattr)
{
- memset(secattr, 0, sizeof(*secattr));
- return 0;
+ secattr->flags = 0;
+ secattr->domain = NULL;
+ secattr->mls_cat = NULL;
+ secattr->cache = NULL;
}
/**
@@ -193,7 +250,8 @@ static inline void netlbl_secattr_destroy(struct netlbl_lsm_secattr *secattr)
if (secattr->cache)
netlbl_secattr_cache_free(secattr->cache);
kfree(secattr->domain);
- kfree(secattr->mls_cat);
+ if (secattr->mls_cat)
+ netlbl_secattr_catmap_free(secattr->mls_cat);
}
/**
@@ -205,7 +263,7 @@ static inline void netlbl_secattr_destroy(struct netlbl_lsm_secattr *secattr)
* pointer on success, or NULL on failure.
*
*/
-static inline struct netlbl_lsm_secattr *netlbl_secattr_alloc(int flags)
+static inline struct netlbl_lsm_secattr *netlbl_secattr_alloc(gfp_t flags)
{
return kzalloc(sizeof(struct netlbl_lsm_secattr), flags);
}
@@ -224,6 +282,51 @@ static inline void netlbl_secattr_free(struct netlbl_lsm_secattr *secattr)
kfree(secattr);
}
+#ifdef CONFIG_NETLABEL
+int netlbl_secattr_catmap_walk(struct netlbl_lsm_secattr_catmap *catmap,
+ u32 offset);
+int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap *catmap,
+ u32 offset);
+int netlbl_secattr_catmap_setbit(struct netlbl_lsm_secattr_catmap *catmap,
+ u32 bit,
+ gfp_t flags);
+int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap,
+ u32 start,
+ u32 end,
+ gfp_t flags);
+#else
+static inline int netlbl_secattr_catmap_walk(
+ struct netlbl_lsm_secattr_catmap *catmap,
+ u32 offset)
+{
+ return -ENOENT;
+}
+
+static inline int netlbl_secattr_catmap_walk_rng(
+ struct netlbl_lsm_secattr_catmap *catmap,
+ u32 offset)
+{
+ return -ENOENT;
+}
+
+static inline int netlbl_secattr_catmap_setbit(
+ struct netlbl_lsm_secattr_catmap *catmap,
+ u32 bit,
+ gfp_t flags)
+{
+ return 0;
+}
+
+static inline int netlbl_secattr_catmap_setrng(
+ struct netlbl_lsm_secattr_catmap *catmap,
+ u32 start,
+ u32 end,
+ gfp_t flags)
+{
+ return 0;
+}
+#endif
+
/*
* LSM protocol operations
*/
diff --git a/include/net/netlink.h b/include/net/netlink.h
index ce5cba19c393..fd75fd65d59e 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -500,14 +500,15 @@ static inline struct nlmsghdr *nlmsg_put_answer(struct sk_buff *skb,
/**
* nlmsg_new - Allocate a new netlink message
- * @size: maximum size of message
+ * @payload: size of the message payload
* @flags: the type of memory to allocate.
*
- * Use NLMSG_GOODSIZE if size isn't know and you need a good default size.
+ * Use NLMSG_DEFAULT_SIZE if the size of the payload isn't known
+ * and a good default is needed.
*/
-static inline struct sk_buff *nlmsg_new(int size, gfp_t flags)
+static inline struct sk_buff *nlmsg_new(size_t payload, gfp_t flags)
{
- return alloc_skb(size, flags);
+ return alloc_skb(nlmsg_total_size(payload), flags);
}
/**
@@ -828,6 +829,9 @@ static inline int nla_put_msecs(struct sk_buff *skb, int attrtype,
#define NLA_PUT_U16(skb, attrtype, value) \
NLA_PUT_TYPE(skb, u16, attrtype, value)
+#define NLA_PUT_LE16(skb, attrtype, value) \
+ NLA_PUT_TYPE(skb, __le16, attrtype, value)
+
#define NLA_PUT_U32(skb, attrtype, value) \
NLA_PUT_TYPE(skb, u32, attrtype, value)
@@ -874,6 +878,15 @@ static inline u16 nla_get_u16(struct nlattr *nla)
}
/**
+ * nla_get_le16 - return payload of __le16 attribute
+ * @nla: __le16 netlink attribute
+ */
+static inline __le16 nla_get_le16(struct nlattr *nla)
+{
+ return *(__le16 *) nla_data(nla);
+}
+
+/**
* nla_get_u8 - return payload of u8 attribute
* @nla: u8 netlink attribute
*/
diff --git a/include/net/protocol.h b/include/net/protocol.h
index c643bce64e55..105bf12b0c79 100644
--- a/include/net/protocol.h
+++ b/include/net/protocol.h
@@ -50,7 +50,7 @@ struct inet6_protocol
void (*err_handler)(struct sk_buff *skb,
struct inet6_skb_parm *opt,
int type, int code, int offset,
- __u32 info);
+ __be32 info);
int (*gso_send_check)(struct sk_buff *skb);
struct sk_buff *(*gso_segment)(struct sk_buff *skb,
@@ -71,7 +71,7 @@ struct inet_protosw {
/* These two fields form the lookup key. */
unsigned short type; /* This is the 2nd argument to socket(2). */
- int protocol; /* This is the L4 protocol number. */
+ unsigned short protocol; /* This is the L4 protocol number. */
struct proto *prot;
const struct proto_ops *ops;
diff --git a/include/net/rawv6.h b/include/net/rawv6.h
index 14476a71725e..af8960878ef4 100644
--- a/include/net/rawv6.h
+++ b/include/net/rawv6.h
@@ -21,7 +21,7 @@ extern void rawv6_err(struct sock *sk,
struct sk_buff *skb,
struct inet6_skb_parm *opt,
int type, int code,
- int offset, u32 info);
+ int offset, __be32 info);
#endif
diff --git a/include/net/request_sock.h b/include/net/request_sock.h
index 8e165ca16bd8..e37baaf2080b 100644
--- a/include/net/request_sock.h
+++ b/include/net/request_sock.h
@@ -28,14 +28,15 @@ struct proto;
struct request_sock_ops {
int family;
- kmem_cache_t *slab;
int obj_size;
+ kmem_cache_t *slab;
int (*rtx_syn_ack)(struct sock *sk,
struct request_sock *req,
struct dst_entry *dst);
void (*send_ack)(struct sk_buff *skb,
struct request_sock *req);
- void (*send_reset)(struct sk_buff *skb);
+ void (*send_reset)(struct sock *sk,
+ struct sk_buff *skb);
void (*destructor)(struct request_sock *req);
};
@@ -51,12 +52,13 @@ struct request_sock {
u32 rcv_wnd; /* rcv_wnd offered first time */
u32 ts_recent;
unsigned long expires;
- struct request_sock_ops *rsk_ops;
+ const struct request_sock_ops *rsk_ops;
struct sock *sk;
u32 secid;
+ u32 peer_secid;
};
-static inline struct request_sock *reqsk_alloc(struct request_sock_ops *ops)
+static inline struct request_sock *reqsk_alloc(const struct request_sock_ops *ops)
{
struct request_sock *req = kmem_cache_alloc(ops->slab, SLAB_ATOMIC);
@@ -120,7 +122,7 @@ struct request_sock_queue {
};
extern int reqsk_queue_alloc(struct request_sock_queue *queue,
- const int nr_table_entries);
+ unsigned int nr_table_entries);
static inline struct listen_sock *reqsk_queue_yank_listen_sk(struct request_sock_queue *queue)
{
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index b0e9108a4e18..82086392735a 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -60,6 +60,7 @@ struct Qdisc_class_ops
int (*graft)(struct Qdisc *, unsigned long cl,
struct Qdisc *, struct Qdisc **);
struct Qdisc * (*leaf)(struct Qdisc *, unsigned long cl);
+ void (*qlen_notify)(struct Qdisc *, unsigned long);
/* Class manipulation routines */
unsigned long (*get)(struct Qdisc *, u32 classid);
@@ -144,7 +145,7 @@ struct tcf_proto
void *root;
int (*classify)(struct sk_buff*, struct tcf_proto*,
struct tcf_result *);
- u32 protocol;
+ __be16 protocol;
/* All the rest */
u32 prio;
@@ -172,9 +173,10 @@ extern void dev_activate(struct net_device *dev);
extern void dev_deactivate(struct net_device *dev);
extern void qdisc_reset(struct Qdisc *qdisc);
extern void qdisc_destroy(struct Qdisc *qdisc);
+extern void qdisc_tree_decrease_qlen(struct Qdisc *qdisc, unsigned int n);
extern struct Qdisc *qdisc_alloc(struct net_device *dev, struct Qdisc_ops *ops);
extern struct Qdisc *qdisc_create_dflt(struct net_device *dev,
- struct Qdisc_ops *ops);
+ struct Qdisc_ops *ops, u32 parentid);
static inline void
tcf_destroy(struct tcf_proto *tp)
diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h
index 807d6f1ef4b5..6114c4f54b0a 100644
--- a/include/net/sctp/command.h
+++ b/include/net/sctp/command.h
@@ -116,9 +116,11 @@ typedef enum {
typedef union {
__s32 i32;
__u32 u32;
+ __be32 be32;
__u16 u16;
__u8 u8;
int error;
+ __be16 err;
sctp_state_t state;
sctp_event_timeout_t to;
unsigned long zero;
@@ -164,9 +166,11 @@ SCTP_## name (type arg) \
SCTP_ARG_CONSTRUCTOR(I32, __s32, i32)
SCTP_ARG_CONSTRUCTOR(U32, __u32, u32)
+SCTP_ARG_CONSTRUCTOR(BE32, __be32, be32)
SCTP_ARG_CONSTRUCTOR(U16, __u16, u16)
SCTP_ARG_CONSTRUCTOR(U8, __u8, u8)
SCTP_ARG_CONSTRUCTOR(ERROR, int, error)
+SCTP_ARG_CONSTRUCTOR(PERR, __be16, err) /* protocol error */
SCTP_ARG_CONSTRUCTOR(STATE, sctp_state_t, state)
SCTP_ARG_CONSTRUCTOR(TO, sctp_event_timeout_t, to)
SCTP_ARG_CONSTRUCTOR(PTR, void *, ptr)
diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h
index 6c632e26f72d..5ddb85599863 100644
--- a/include/net/sctp/constants.h
+++ b/include/net/sctp/constants.h
@@ -356,7 +356,7 @@ typedef enum {
* addresses.
*/
#define IS_IPV4_UNUSABLE_ADDRESS(a) \
- ((INADDR_BROADCAST == *a) || \
+ ((htonl(INADDR_BROADCAST) == *a) || \
(MULTICAST(*a)) || \
(((unsigned char *)(a))[0] == 0) || \
((((unsigned char *)(a))[0] == 198) && \
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 764e3af5be93..215461f18db1 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -585,7 +585,7 @@ static inline int ipver2af(__u8 ipver)
}
/* Convert from an address parameter type to an address family. */
-static inline int param_type2af(__u16 type)
+static inline int param_type2af(__be16 type)
{
switch (type) {
case SCTP_PARAM_IPV4_ADDRESS:
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index de313de4fefe..3269ed1cc222 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -213,7 +213,7 @@ struct sctp_chunk *sctp_make_shutdown_ack(const struct sctp_association *asoc,
const struct sctp_chunk *);
struct sctp_chunk *sctp_make_shutdown_complete(const struct sctp_association *,
const struct sctp_chunk *);
-void sctp_init_cause(struct sctp_chunk *, __u16 cause, const void *, size_t);
+void sctp_init_cause(struct sctp_chunk *, __be16 cause, const void *, size_t);
struct sctp_chunk *sctp_make_abort(const struct sctp_association *,
const struct sctp_chunk *,
const size_t hint);
@@ -236,14 +236,14 @@ struct sctp_chunk *sctp_make_heartbeat_ack(const struct sctp_association *,
const size_t paylen);
struct sctp_chunk *sctp_make_op_error(const struct sctp_association *,
const struct sctp_chunk *chunk,
- __u16 cause_code,
+ __be16 cause_code,
const void *payload,
size_t paylen);
struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *,
union sctp_addr *,
struct sockaddr *,
- int, __u16);
+ int, __be16);
struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc,
union sctp_addr *addr);
struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 60b684470db8..c089f93ba591 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -537,7 +537,7 @@ struct sctp_af {
struct net_device *);
void (*dst_saddr) (union sctp_addr *saddr,
struct dst_entry *dst,
- unsigned short port);
+ __be16 port);
int (*cmp_addr) (const union sctp_addr *addr1,
const union sctp_addr *addr2);
void (*addr_copy) (union sctp_addr *dst,
@@ -553,14 +553,14 @@ struct sctp_af {
struct sock *sk);
void (*from_addr_param) (union sctp_addr *,
union sctp_addr_param *,
- __u16 port, int iif);
+ __be16 port, int iif);
int (*to_addr_param) (const union sctp_addr *,
union sctp_addr_param *);
int (*addr_valid) (union sctp_addr *,
struct sctp_sock *,
const struct sk_buff *);
sctp_scope_t (*scope) (union sctp_addr *);
- void (*inaddr_any) (union sctp_addr *, unsigned short);
+ void (*inaddr_any) (union sctp_addr *, __be16);
int (*is_any) (const union sctp_addr *);
int (*available) (union sctp_addr *,
struct sctp_sock *);
@@ -587,7 +587,7 @@ struct sctp_pf {
struct sctp_sock *);
int (*bind_verify) (struct sctp_sock *, union sctp_addr *);
int (*send_verify) (struct sctp_sock *, union sctp_addr *);
- int (*supported_addrs)(const struct sctp_sock *, __u16 *);
+ int (*supported_addrs)(const struct sctp_sock *, __be16 *);
struct sock *(*create_accept_sk) (struct sock *sk,
struct sctp_association *asoc);
void (*addr_v4map) (struct sctp_sock *, union sctp_addr *);
@@ -1270,7 +1270,7 @@ struct sctp_endpoint {
* this here so we pre-allocate this once and can re-use
* on every receive.
*/
- __u8 digest[SCTP_SIGNATURE_SIZE];
+ __u8 *digest;
/* sendbuf acct. policy. */
__u32 sndbuf_policy;
@@ -1314,6 +1314,13 @@ int sctp_process_init(struct sctp_association *, sctp_cid_t cid,
__u32 sctp_generate_tag(const struct sctp_endpoint *);
__u32 sctp_generate_tsn(const struct sctp_endpoint *);
+struct sctp_inithdr_host {
+ __u32 init_tag;
+ __u32 a_rwnd;
+ __u16 num_outbound_streams;
+ __u16 num_inbound_streams;
+ __u32 initial_tsn;
+};
/* RFC2960
*
@@ -1482,9 +1489,9 @@ struct sctp_association {
/* This mask is used to disable sending the ASCONF chunk
* with specified parameter to peer.
*/
- __u16 addip_disabled_mask;
+ __be16 addip_disabled_mask;
- struct sctp_inithdr i;
+ struct sctp_inithdr_host i;
int cookie_len;
void *cookie;
diff --git a/include/net/sctp/tsnmap.h b/include/net/sctp/tsnmap.h
index 021947da70ea..70a824df6f60 100644
--- a/include/net/sctp/tsnmap.h
+++ b/include/net/sctp/tsnmap.h
@@ -105,7 +105,7 @@ struct sctp_tsnmap {
* every SACK. Store up to SCTP_MAX_DUP_TSNS worth of
* information.
*/
- __u32 dup_tsns[SCTP_MAX_DUP_TSNS];
+ __be32 dup_tsns[SCTP_MAX_DUP_TSNS];
__u16 num_dup_tsns;
/* Record gap ack block information here. */
@@ -162,7 +162,7 @@ static inline __u16 sctp_tsnmap_num_dups(struct sctp_tsnmap *map)
}
/* Return pointer to duplicate tsn array as needed by SACK. */
-static inline __u32 *sctp_tsnmap_get_dups(struct sctp_tsnmap *map)
+static inline __be32 *sctp_tsnmap_get_dups(struct sctp_tsnmap *map)
{
map->num_dup_tsns = 0;
return map->dup_tsns;
diff --git a/include/net/sock.h b/include/net/sock.h
index ac286a353032..26fc0b16bc0c 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -745,7 +745,13 @@ static inline int sk_stream_wmem_schedule(struct sock *sk, int size)
*/
#define sock_owned_by_user(sk) ((sk)->sk_lock.owner)
-extern void FASTCALL(lock_sock(struct sock *sk));
+extern void FASTCALL(lock_sock_nested(struct sock *sk, int subclass));
+
+static inline void lock_sock(struct sock *sk)
+{
+ lock_sock_nested(sk, 0);
+}
+
extern void FASTCALL(release_sock(struct sock *sk));
/* BH context may only use the following locking interface. */
@@ -883,18 +889,23 @@ static inline int sk_filter(struct sock *sk, struct sk_buff *skb)
}
/**
- * sk_filter_release: Release a socket filter
- * @rcu: rcu_head that contains the sk_filter info to remove
- *
- * Remove a filter from a socket and release its resources.
+ * sk_filter_rcu_free: Free a socket filter
+ * @rcu: rcu_head that contains the sk_filter to free
*/
-
static inline void sk_filter_rcu_free(struct rcu_head *rcu)
{
struct sk_filter *fp = container_of(rcu, struct sk_filter, rcu);
kfree(fp);
}
+/**
+ * sk_filter_release: Release a socket filter
+ * @sk: socket
+ * @fp: filter to remove
+ *
+ * Remove a filter from a socket and release its resources.
+ */
+
static inline void sk_filter_release(struct sock *sk, struct sk_filter *fp)
{
unsigned int size = sk_filter_len(fp);
@@ -943,7 +954,8 @@ static inline void sock_put(struct sock *sk)
sk_free(sk);
}
-extern int sk_receive_skb(struct sock *sk, struct sk_buff *skb);
+extern int sk_receive_skb(struct sock *sk, struct sk_buff *skb,
+ const int nested);
/* Detach socket from process context.
* Announce socket dead, detach it from wait queue and inode.
@@ -1077,7 +1089,7 @@ static inline int skb_copy_to_page(struct sock *sk, char __user *from,
{
if (skb->ip_summed == CHECKSUM_NONE) {
int err = 0;
- unsigned int csum = csum_and_copy_from_user(from,
+ __wsum csum = csum_and_copy_from_user(from,
page_address(page) + off,
copy, 0, &err);
if (err)
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 7a093d0aa0fe..c99774f15eba 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -28,6 +28,7 @@
#include <linux/percpu.h>
#include <linux/skbuff.h>
#include <linux/dmaengine.h>
+#include <linux/crypto.h>
#include <net/inet_connection_sock.h>
#include <net/inet_timewait_sock.h>
@@ -138,7 +139,6 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo);
#define MAX_TCP_SYNCNT 127
#define TCP_SYNQ_INTERVAL (HZ/5) /* Period of SYNACK timer */
-#define TCP_SYNQ_HSIZE 512 /* Size of SYNACK hash table */
#define TCP_PAWS_24DAYS (60 * 60 * 24 * 24)
#define TCP_PAWS_MSL 60 /* Per-host timestamps are invalidated
@@ -162,6 +162,7 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo);
#define TCPOPT_SACK_PERM 4 /* SACK Permitted */
#define TCPOPT_SACK 5 /* SACK Block */
#define TCPOPT_TIMESTAMP 8 /* Better RTT estimations/PAWS */
+#define TCPOPT_MD5SIG 19 /* MD5 Signature (RFC2385) */
/*
* TCP option lengths
@@ -171,6 +172,7 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo);
#define TCPOLEN_WINDOW 3
#define TCPOLEN_SACK_PERM 2
#define TCPOLEN_TIMESTAMP 10
+#define TCPOLEN_MD5SIG 18
/* But this is what stacks really send out. */
#define TCPOLEN_TSTAMP_ALIGNED 12
@@ -179,6 +181,7 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo);
#define TCPOLEN_SACK_BASE 2
#define TCPOLEN_SACK_BASE_ALIGNED 4
#define TCPOLEN_SACK_PERBLOCK 8
+#define TCPOLEN_MD5SIG_ALIGNED 20
/* Flags in tp->nonagle */
#define TCP_NAGLE_OFF 1 /* Nagle's algo is disabled */
@@ -300,6 +303,8 @@ extern void tcp_cleanup_rbuf(struct sock *sk, int copied);
extern int tcp_twsk_unique(struct sock *sk,
struct sock *sktw, void *twp);
+extern void tcp_twsk_destructor(struct sock *sk);
+
static inline void tcp_dec_quickack_mode(struct sock *sk,
const unsigned int pkts)
{
@@ -621,8 +626,12 @@ enum tcp_ca_event {
* Interface for adding new TCP congestion control handlers
*/
#define TCP_CA_NAME_MAX 16
+#define TCP_CA_MAX 128
+#define TCP_CA_BUF_MAX (TCP_CA_NAME_MAX*TCP_CA_MAX)
+
struct tcp_congestion_ops {
struct list_head list;
+ int non_restricted;
/* initialize private data (optional) */
void (*init)(struct sock *sk);
@@ -660,6 +669,9 @@ extern void tcp_init_congestion_control(struct sock *sk);
extern void tcp_cleanup_congestion_control(struct sock *sk);
extern int tcp_set_default_congestion_control(const char *name);
extern void tcp_get_default_congestion_control(char *name);
+extern void tcp_get_available_congestion_control(char *buf, size_t len);
+extern void tcp_get_allowed_congestion_control(char *buf, size_t len);
+extern int tcp_set_allowed_congestion_control(char *allowed);
extern int tcp_set_congestion_control(struct sock *sk, const char *name);
extern void tcp_slow_start(struct tcp_sock *tp);
@@ -795,14 +807,14 @@ static inline void tcp_update_wl(struct tcp_sock *tp, u32 ack, u32 seq)
/*
* Calculate(/check) TCP checksum
*/
-static inline u16 tcp_v4_check(struct tcphdr *th, int len,
- unsigned long saddr, unsigned long daddr,
- unsigned long base)
+static inline __sum16 tcp_v4_check(struct tcphdr *th, int len,
+ __be32 saddr, __be32 daddr,
+ __wsum base)
{
return csum_tcpudp_magic(saddr,daddr,len,IPPROTO_TCP,base);
}
-static inline int __tcp_checksum_complete(struct sk_buff *skb)
+static inline __sum16 __tcp_checksum_complete(struct sk_buff *skb)
{
return __skb_checksum_complete(skb);
}
@@ -1058,6 +1070,114 @@ static inline void clear_all_retrans_hints(struct tcp_sock *tp){
tp->fastpath_skb_hint = NULL;
}
+/* MD5 Signature */
+struct crypto_hash;
+
+/* - key database */
+struct tcp_md5sig_key {
+ u8 *key;
+ u8 keylen;
+};
+
+struct tcp4_md5sig_key {
+ u8 *key;
+ u16 keylen;
+ __be32 addr;
+};
+
+struct tcp6_md5sig_key {
+ u8 *key;
+ u16 keylen;
+#if 0
+ u32 scope_id; /* XXX */
+#endif
+ struct in6_addr addr;
+};
+
+/* - sock block */
+struct tcp_md5sig_info {
+ struct tcp4_md5sig_key *keys4;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ struct tcp6_md5sig_key *keys6;
+ u32 entries6;
+ u32 alloced6;
+#endif
+ u32 entries4;
+ u32 alloced4;
+};
+
+/* - pseudo header */
+struct tcp4_pseudohdr {
+ __be32 saddr;
+ __be32 daddr;
+ __u8 pad;
+ __u8 protocol;
+ __be16 len;
+};
+
+struct tcp6_pseudohdr {
+ struct in6_addr saddr;
+ struct in6_addr daddr;
+ __be32 len;
+ __be32 protocol; /* including padding */
+};
+
+union tcp_md5sum_block {
+ struct tcp4_pseudohdr ip4;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ struct tcp6_pseudohdr ip6;
+#endif
+};
+
+/* - pool: digest algorithm, hash description and scratch buffer */
+struct tcp_md5sig_pool {
+ struct hash_desc md5_desc;
+ union tcp_md5sum_block md5_blk;
+};
+
+#define TCP_MD5SIG_MAXKEYS (~(u32)0) /* really?! */
+
+/* - functions */
+extern int tcp_v4_calc_md5_hash(char *md5_hash,
+ struct tcp_md5sig_key *key,
+ struct sock *sk,
+ struct dst_entry *dst,
+ struct request_sock *req,
+ struct tcphdr *th,
+ int protocol, int tcplen);
+extern struct tcp_md5sig_key *tcp_v4_md5_lookup(struct sock *sk,
+ struct sock *addr_sk);
+
+extern int tcp_v4_md5_do_add(struct sock *sk,
+ __be32 addr,
+ u8 *newkey,
+ u8 newkeylen);
+
+extern int tcp_v4_md5_do_del(struct sock *sk,
+ __be32 addr);
+
+extern struct tcp_md5sig_pool **tcp_alloc_md5sig_pool(void);
+extern void tcp_free_md5sig_pool(void);
+
+extern struct tcp_md5sig_pool *__tcp_get_md5sig_pool(int cpu);
+extern void __tcp_put_md5sig_pool(void);
+
+static inline
+struct tcp_md5sig_pool *tcp_get_md5sig_pool(void)
+{
+ int cpu = get_cpu();
+ struct tcp_md5sig_pool *ret = __tcp_get_md5sig_pool(cpu);
+ if (!ret)
+ put_cpu();
+ return ret;
+}
+
+static inline void tcp_put_md5sig_pool(void)
+{
+ __tcp_put_md5sig_pool();
+ put_cpu();
+}
+
/* /proc */
enum tcp_seq_states {
TCP_SEQ_STATE_LISTENING,
@@ -1097,6 +1217,35 @@ extern int tcp4_proc_init(void);
extern void tcp4_proc_exit(void);
#endif
+/* TCP af-specific functions */
+struct tcp_sock_af_ops {
+#ifdef CONFIG_TCP_MD5SIG
+ struct tcp_md5sig_key *(*md5_lookup) (struct sock *sk,
+ struct sock *addr_sk);
+ int (*calc_md5_hash) (char *location,
+ struct tcp_md5sig_key *md5,
+ struct sock *sk,
+ struct dst_entry *dst,
+ struct request_sock *req,
+ struct tcphdr *th,
+ int protocol, int len);
+ int (*md5_add) (struct sock *sk,
+ struct sock *addr_sk,
+ u8 *newkey,
+ u8 len);
+ int (*md5_parse) (struct sock *sk,
+ char __user *optval,
+ int optlen);
+#endif
+};
+
+struct tcp_request_sock_ops {
+#ifdef CONFIG_TCP_MD5SIG
+ struct tcp_md5sig_key *(*md5_lookup) (struct sock *sk,
+ struct request_sock *req);
+#endif
+};
+
extern void tcp_v4_init(struct net_proto_family *ops);
extern void tcp_init(void);
diff --git a/include/net/timewait_sock.h b/include/net/timewait_sock.h
index be293d795e38..d7a306ea560d 100644
--- a/include/net/timewait_sock.h
+++ b/include/net/timewait_sock.h
@@ -31,6 +31,9 @@ static inline int twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
static inline void twsk_destructor(struct sock *sk)
{
+ BUG_ON(sk == NULL);
+ BUG_ON(sk->sk_prot == NULL);
+ BUG_ON(sk->sk_prot->twsk_prot == NULL);
if (sk->sk_prot->twsk_prot->twsk_destructor != NULL)
sk->sk_prot->twsk_prot->twsk_destructor(sk);
}
diff --git a/include/net/tipc/tipc_bearer.h b/include/net/tipc/tipc_bearer.h
index e07136d74c2f..2151a80cdf30 100644
--- a/include/net/tipc/tipc_bearer.h
+++ b/include/net/tipc/tipc_bearer.h
@@ -58,7 +58,7 @@
*/
struct tipc_media_addr {
- __u32 type; /* bearer type (network byte order) */
+ __be32 type; /* bearer type (network byte order) */
union {
__u8 eth_addr[6]; /* 48 bit Ethernet addr (byte array) */
#if 0
diff --git a/include/net/tipc/tipc_msg.h b/include/net/tipc/tipc_msg.h
index 4d096eebc93f..fb42eb7a86a5 100644
--- a/include/net/tipc/tipc_msg.h
+++ b/include/net/tipc/tipc_msg.h
@@ -40,7 +40,7 @@
#ifdef __KERNEL__
struct tipc_msg {
- u32 hdr[15];
+ __be32 hdr[15];
};
diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h
index 61f724c1036f..409da3a9a455 100644
--- a/include/net/transp_v6.h
+++ b/include/net/transp_v6.h
@@ -11,6 +11,7 @@
extern struct proto rawv6_prot;
extern struct proto udpv6_prot;
+extern struct proto udplitev6_prot;
extern struct proto tcpv6_prot;
struct flowi;
@@ -24,6 +25,7 @@ extern void ipv6_destopt_init(void);
/* transport protocols */
extern void rawv6_init(void);
extern void udpv6_init(void);
+extern void udplitev6_init(void);
extern void tcpv6_init(void);
extern int udpv6_connect(struct sock *sk,
diff --git a/include/net/udp.h b/include/net/udp.h
index db0c05f67546..1548d68d45da 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -26,9 +26,28 @@
#include <net/inet_sock.h>
#include <net/sock.h>
#include <net/snmp.h>
+#include <net/ip.h>
+#include <linux/ipv6.h>
#include <linux/seq_file.h>
-#define UDP_HTABLE_SIZE 128
+/**
+ * struct udp_skb_cb - UDP(-Lite) private variables
+ *
+ * @header: private variables used by IPv4/IPv6
+ * @cscov: checksum coverage length (UDP-Lite only)
+ * @partial_cov: if set indicates partial csum coverage
+ */
+struct udp_skb_cb {
+ union {
+ struct inet_skb_parm h4;
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+ struct inet6_skb_parm h6;
+#endif
+ } header;
+ __u16 cscov;
+ __u8 partial_cov;
+};
+#define UDP_SKB_CB(__skb) ((struct udp_skb_cb *)((__skb)->cb))
extern struct hlist_head udp_hash[UDP_HTABLE_SIZE];
extern rwlock_t udp_hash_lock;
@@ -47,6 +66,62 @@ extern struct proto udp_prot;
struct sk_buff;
+/*
+ * Generic checksumming routines for UDP(-Lite) v4 and v6
+ */
+static inline __sum16 __udp_lib_checksum_complete(struct sk_buff *skb)
+{
+ if (! UDP_SKB_CB(skb)->partial_cov)
+ return __skb_checksum_complete(skb);
+ return csum_fold(skb_checksum(skb, 0, UDP_SKB_CB(skb)->cscov,
+ skb->csum));
+}
+
+static inline int udp_lib_checksum_complete(struct sk_buff *skb)
+{
+ return skb->ip_summed != CHECKSUM_UNNECESSARY &&
+ __udp_lib_checksum_complete(skb);
+}
+
+/**
+ * udp_csum_outgoing - compute UDPv4/v6 checksum over fragments
+ * @sk: socket we are writing to
+ * @skb: sk_buff containing the filled-in UDP header
+ * (checksum field must be zeroed out)
+ */
+static inline __wsum udp_csum_outgoing(struct sock *sk, struct sk_buff *skb)
+{
+ __wsum csum = csum_partial(skb->h.raw, sizeof(struct udphdr), 0);
+
+ skb_queue_walk(&sk->sk_write_queue, skb) {
+ csum = csum_add(csum, skb->csum);
+ }
+ return csum;
+}
+
+/* hash routines shared between UDPv4/6 and UDP-Litev4/6 */
+static inline void udp_lib_hash(struct sock *sk)
+{
+ BUG();
+}
+
+static inline void udp_lib_unhash(struct sock *sk)
+{
+ write_lock_bh(&udp_hash_lock);
+ if (sk_del_node_init(sk)) {
+ inet_sk(sk)->num = 0;
+ sock_prot_dec_use(sk->sk_prot);
+ }
+ write_unlock_bh(&udp_hash_lock);
+}
+
+static inline void udp_lib_close(struct sock *sk, long timeout)
+{
+ sk_common_release(sk);
+}
+
+
+/* net/ipv4/udp.c */
extern int udp_get_port(struct sock *sk, unsigned short snum,
int (*saddr_cmp)(const struct sock *, const struct sock *));
extern void udp_err(struct sk_buff *, u32);
@@ -59,23 +134,36 @@ extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
extern int udp_disconnect(struct sock *sk, int flags);
extern unsigned int udp_poll(struct file *file, struct socket *sock,
poll_table *wait);
+extern int udp_lib_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen);
+extern int udp_lib_setsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int optlen,
+ int (*push_pending_frames)(struct sock *));
DECLARE_SNMP_STAT(struct udp_mib, udp_statistics);
-#define UDP_INC_STATS(field) SNMP_INC_STATS(udp_statistics, field)
-#define UDP_INC_STATS_BH(field) SNMP_INC_STATS_BH(udp_statistics, field)
-#define UDP_INC_STATS_USER(field) SNMP_INC_STATS_USER(udp_statistics, field)
+/*
+ * SNMP statistics for UDP and UDP-Lite
+ */
+#define UDP_INC_STATS_USER(field, is_udplite) do { \
+ if (is_udplite) SNMP_INC_STATS_USER(udplite_statistics, field); \
+ else SNMP_INC_STATS_USER(udp_statistics, field); } while(0)
+#define UDP_INC_STATS_BH(field, is_udplite) do { \
+ if (is_udplite) SNMP_INC_STATS_BH(udplite_statistics, field); \
+ else SNMP_INC_STATS_BH(udp_statistics, field); } while(0)
/* /proc */
struct udp_seq_afinfo {
struct module *owner;
char *name;
sa_family_t family;
+ struct hlist_head *hashtable;
int (*seq_show) (struct seq_file *m, void *v);
struct file_operations *seq_fops;
};
struct udp_iter_state {
sa_family_t family;
+ struct hlist_head *hashtable;
int bucket;
struct seq_operations seq_ops;
};
diff --git a/include/net/udplite.h b/include/net/udplite.h
new file mode 100644
index 000000000000..67ac51424307
--- /dev/null
+++ b/include/net/udplite.h
@@ -0,0 +1,151 @@
+/*
+ * Definitions for the UDP-Lite (RFC 3828) code.
+ */
+#ifndef _UDPLITE_H
+#define _UDPLITE_H
+
+#include <net/ip6_checksum.h>
+
+/* UDP-Lite socket options */
+#define UDPLITE_SEND_CSCOV 10 /* sender partial coverage (as sent) */
+#define UDPLITE_RECV_CSCOV 11 /* receiver partial coverage (threshold ) */
+
+extern struct proto udplite_prot;
+extern struct hlist_head udplite_hash[UDP_HTABLE_SIZE];
+
+/* UDP-Lite does not have a standardized MIB yet, so we inherit from UDP */
+DECLARE_SNMP_STAT(struct udp_mib, udplite_statistics);
+
+/*
+ * Checksum computation is all in software, hence simpler getfrag.
+ */
+static __inline__ int udplite_getfrag(void *from, char *to, int offset,
+ int len, int odd, struct sk_buff *skb)
+{
+ return memcpy_fromiovecend(to, (struct iovec *) from, offset, len);
+}
+
+/* Designate sk as UDP-Lite socket */
+static inline int udplite_sk_init(struct sock *sk)
+{
+ udp_sk(sk)->pcflag = UDPLITE_BIT;
+ return 0;
+}
+
+/*
+ * Checksumming routines
+ */
+static inline int udplite_checksum_init(struct sk_buff *skb, struct udphdr *uh)
+{
+ u16 cscov;
+
+ /* In UDPv4 a zero checksum means that the transmitter generated no
+ * checksum. UDP-Lite (like IPv6) mandates checksums, hence packets
+ * with a zero checksum field are illegal. */
+ if (uh->check == 0) {
+ LIMIT_NETDEBUG(KERN_DEBUG "UDPLITE: zeroed checksum field\n");
+ return 1;
+ }
+
+ UDP_SKB_CB(skb)->partial_cov = 0;
+ cscov = ntohs(uh->len);
+
+ if (cscov == 0) /* Indicates that full coverage is required. */
+ cscov = skb->len;
+ else if (cscov < 8 || cscov > skb->len) {
+ /*
+ * Coverage length violates RFC 3828: log and discard silently.
+ */
+ LIMIT_NETDEBUG(KERN_DEBUG "UDPLITE: bad csum coverage %d/%d\n",
+ cscov, skb->len);
+ return 1;
+
+ } else if (cscov < skb->len)
+ UDP_SKB_CB(skb)->partial_cov = 1;
+
+ UDP_SKB_CB(skb)->cscov = cscov;
+
+ /*
+ * There is no known NIC manufacturer supporting UDP-Lite yet,
+ * hence ip_summed is always (re-)set to CHECKSUM_NONE.
+ */
+ skb->ip_summed = CHECKSUM_NONE;
+
+ return 0;
+}
+
+static __inline__ int udplite4_csum_init(struct sk_buff *skb, struct udphdr *uh)
+{
+ int rc = udplite_checksum_init(skb, uh);
+
+ if (!rc)
+ skb->csum = csum_tcpudp_nofold(skb->nh.iph->saddr,
+ skb->nh.iph->daddr,
+ skb->len, IPPROTO_UDPLITE, 0);
+ return rc;
+}
+
+static __inline__ int udplite6_csum_init(struct sk_buff *skb, struct udphdr *uh)
+{
+ int rc = udplite_checksum_init(skb, uh);
+
+ if (!rc)
+ skb->csum = ~csum_unfold(csum_ipv6_magic(&skb->nh.ipv6h->saddr,
+ &skb->nh.ipv6h->daddr,
+ skb->len, IPPROTO_UDPLITE, 0));
+ return rc;
+}
+
+static inline int udplite_sender_cscov(struct udp_sock *up, struct udphdr *uh)
+{
+ int cscov = up->len;
+
+ /*
+ * Sender has set `partial coverage' option on UDP-Lite socket
+ */
+ if (up->pcflag & UDPLITE_SEND_CC) {
+ if (up->pcslen < up->len) {
+ /* up->pcslen == 0 means that full coverage is required,
+ * partial coverage only if 0 < up->pcslen < up->len */
+ if (0 < up->pcslen) {
+ cscov = up->pcslen;
+ }
+ uh->len = htons(up->pcslen);
+ }
+ /*
+ * NOTE: Causes for the error case `up->pcslen > up->len':
+ * (i) Application error (will not be penalized).
+ * (ii) Payload too big for send buffer: data is split
+ * into several packets, each with its own header.
+ * In this case (e.g. last segment), coverage may
+ * exceed packet length.
+ * Since packets with coverage length > packet length are
+ * illegal, we fall back to the defaults here.
+ */
+ }
+ return cscov;
+}
+
+static inline __wsum udplite_csum_outgoing(struct sock *sk, struct sk_buff *skb)
+{
+ int off, len, cscov = udplite_sender_cscov(udp_sk(sk), skb->h.uh);
+ __wsum csum = 0;
+
+ skb->ip_summed = CHECKSUM_NONE; /* no HW support for checksumming */
+
+ skb_queue_walk(&sk->sk_write_queue, skb) {
+ off = skb->h.raw - skb->data;
+ len = skb->len - off;
+
+ csum = skb_checksum(skb, off, (cscov > len)? len : cscov, csum);
+
+ if ((cscov -= len) <= 0)
+ break;
+ }
+ return csum;
+}
+
+extern void udplite4_register(void);
+extern int udplite_get_port(struct sock *sk, unsigned short snum,
+ int (*scmp)(const struct sock *, const struct sock *));
+#endif /* _UDPLITE_H */
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 737fdb2ee8a4..15ec19dcf9c8 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -310,6 +310,8 @@ struct xfrm_tmpl
/* Source address of tunnel. Ignored, if it is not a tunnel. */
xfrm_address_t saddr;
+ unsigned short encap_family;
+
__u32 reqid;
/* Mode: transport, tunnel etc. */
@@ -340,18 +342,19 @@ struct xfrm_policy
atomic_t refcnt;
struct timer_list timer;
- u8 type;
u32 priority;
u32 index;
struct xfrm_selector selector;
struct xfrm_lifetime_cfg lft;
struct xfrm_lifetime_cur curlft;
struct dst_entry *bundles;
- __u16 family;
- __u8 action;
- __u8 flags;
- __u8 dead;
- __u8 xfrm_nr;
+ u16 family;
+ u8 type;
+ u8 action;
+ u8 flags;
+ u8 dead;
+ u8 xfrm_nr;
+ /* XXX 1 byte hole, try to pack */
struct xfrm_sec_ctx *security;
struct xfrm_tmpl xfrm_vec[XFRM_MAX_DEPTH];
};
@@ -379,7 +382,7 @@ struct xfrm_mgr
int (*notify)(struct xfrm_state *x, struct km_event *c);
int (*acquire)(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *xp, int dir);
struct xfrm_policy *(*compile_policy)(struct sock *sk, int opt, u8 *data, int len, int *dir);
- int (*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport);
+ int (*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport);
int (*notify_policy)(struct xfrm_policy *x, int dir, struct km_event *c);
int (*report)(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr);
};
@@ -468,6 +471,7 @@ __be16 xfrm_flowi_sport(struct flowi *fl)
switch(fl->proto) {
case IPPROTO_TCP:
case IPPROTO_UDP:
+ case IPPROTO_UDPLITE:
case IPPROTO_SCTP:
port = fl->fl_ip_sport;
break;
@@ -493,6 +497,7 @@ __be16 xfrm_flowi_dport(struct flowi *fl)
switch(fl->proto) {
case IPPROTO_TCP:
case IPPROTO_UDP:
+ case IPPROTO_UDPLITE:
case IPPROTO_SCTP:
port = fl->fl_ip_dport;
break;
@@ -506,40 +511,8 @@ __be16 xfrm_flowi_dport(struct flowi *fl)
return port;
}
-static inline int
-__xfrm4_selector_match(struct xfrm_selector *sel, struct flowi *fl)
-{
- return addr_match(&fl->fl4_dst, &sel->daddr, sel->prefixlen_d) &&
- addr_match(&fl->fl4_src, &sel->saddr, sel->prefixlen_s) &&
- !((xfrm_flowi_dport(fl) ^ sel->dport) & sel->dport_mask) &&
- !((xfrm_flowi_sport(fl) ^ sel->sport) & sel->sport_mask) &&
- (fl->proto == sel->proto || !sel->proto) &&
- (fl->oif == sel->ifindex || !sel->ifindex);
-}
-
-static inline int
-__xfrm6_selector_match(struct xfrm_selector *sel, struct flowi *fl)
-{
- return addr_match(&fl->fl6_dst, &sel->daddr, sel->prefixlen_d) &&
- addr_match(&fl->fl6_src, &sel->saddr, sel->prefixlen_s) &&
- !((xfrm_flowi_dport(fl) ^ sel->dport) & sel->dport_mask) &&
- !((xfrm_flowi_sport(fl) ^ sel->sport) & sel->sport_mask) &&
- (fl->proto == sel->proto || !sel->proto) &&
- (fl->oif == sel->ifindex || !sel->ifindex);
-}
-
-static inline int
-xfrm_selector_match(struct xfrm_selector *sel, struct flowi *fl,
- unsigned short family)
-{
- switch (family) {
- case AF_INET:
- return __xfrm4_selector_match(sel, fl);
- case AF_INET6:
- return __xfrm6_selector_match(sel, fl);
- }
- return 0;
-}
+extern int xfrm_selector_match(struct xfrm_selector *sel, struct flowi *fl,
+ unsigned short family);
#ifdef CONFIG_SECURITY_NETWORK_XFRM
/* If neither has a context --> match
@@ -887,8 +860,7 @@ struct xfrm_tunnel {
struct xfrm6_tunnel {
int (*handler)(struct sk_buff *skb);
int (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt,
- int type, int code, int offset, __u32 info);
-
+ int type, int code, int offset, __be32 info);
struct xfrm6_tunnel *next;
int priority;
};
@@ -951,9 +923,9 @@ extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
xfrm_address_t *saddr, u8 proto);
extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler);
extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler);
-extern u32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr);
+extern __be32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr);
extern void xfrm6_tunnel_free_spi(xfrm_address_t *saddr);
-extern u32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr);
+extern __be32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr);
extern int xfrm6_output(struct sk_buff *skb);
extern int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb,
u8 **prevhdr);
@@ -1000,7 +972,7 @@ extern int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *xdst,
extern void xfrm_init_pmtu(struct dst_entry *dst);
extern wait_queue_head_t km_waitq;
-extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport);
+extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport);
extern void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid);
extern int km_report(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr);
@@ -1033,7 +1005,7 @@ static inline int xfrm_addr_cmp(xfrm_address_t *a, xfrm_address_t *b,
switch (family) {
default:
case AF_INET:
- return a->a4 - b->a4;
+ return (__force __u32)a->a4 - (__force __u32)b->a4;
case AF_INET6:
return ipv6_addr_cmp((struct in6_addr *)a,
(struct in6_addr *)b);
diff --git a/include/rdma/ib_cm.h b/include/rdma/ib_cm.h
index c9b4738be9d6..5c070176d9ab 100644
--- a/include/rdma/ib_cm.h
+++ b/include/rdma/ib_cm.h
@@ -60,6 +60,7 @@ enum ib_cm_state {
};
enum ib_cm_lap_state {
+ IB_CM_LAP_UNINIT,
IB_CM_LAP_IDLE,
IB_CM_LAP_SENT,
IB_CM_LAP_RCVD,
@@ -443,13 +444,20 @@ int ib_send_cm_drep(struct ib_cm_id *cm_id,
u8 private_data_len);
/**
- * ib_cm_establish - Forces a connection state to established.
+ * ib_cm_notify - Notifies the CM of an event reported to the consumer.
* @cm_id: Connection identifier to transition to established.
+ * @event: Type of event.
*
- * This routine should be invoked by users who receive messages on a
- * connected QP before an RTU has been received.
+ * This routine should be invoked by users to notify the CM of relevant
+ * communication events. Events that should be reported to the CM and
+ * when to report them are:
+ *
+ * IB_EVENT_COMM_EST - Used when a message is received on a connected
+ * QP before an RTU has been received.
+ * IB_EVENT_PATH_MIG - Notifies the CM that the connection has failed over
+ * to the alternate path.
*/
-int ib_cm_establish(struct ib_cm_id *cm_id);
+int ib_cm_notify(struct ib_cm_id *cm_id, enum ib_event_type event);
/**
* ib_send_cm_rej - Sends a connection rejection message to the
diff --git a/include/rdma/ib_user_cm.h b/include/rdma/ib_user_cm.h
index 066c20b7cdfb..37650afb982c 100644
--- a/include/rdma/ib_user_cm.h
+++ b/include/rdma/ib_user_cm.h
@@ -38,7 +38,7 @@
#include <rdma/ib_user_sa.h>
-#define IB_USER_CM_ABI_VERSION 4
+#define IB_USER_CM_ABI_VERSION 5
enum {
IB_USER_CM_CMD_CREATE_ID,
@@ -46,7 +46,7 @@ enum {
IB_USER_CM_CMD_ATTR_ID,
IB_USER_CM_CMD_LISTEN,
- IB_USER_CM_CMD_ESTABLISH,
+ IB_USER_CM_CMD_NOTIFY,
IB_USER_CM_CMD_SEND_REQ,
IB_USER_CM_CMD_SEND_REP,
@@ -117,8 +117,9 @@ struct ib_ucm_listen {
__u32 reserved;
};
-struct ib_ucm_establish {
+struct ib_ucm_notify {
__u32 id;
+ __u32 event;
};
struct ib_ucm_private_data {
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
index 9ccc0365aa89..1f989fb42c70 100644
--- a/include/scsi/libsas.h
+++ b/include/scsi/libsas.h
@@ -35,6 +35,7 @@
#include <scsi/scsi_device.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_transport_sas.h>
+#include <asm/scatterlist.h>
struct block_device;
diff --git a/include/sound/core.h b/include/sound/core.h
index fa1ca0127bab..a994bea09cd6 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -132,6 +132,7 @@ struct snd_card {
int shutdown; /* this card is going down */
int free_on_last_close; /* free in context of file_release */
wait_queue_head_t shutdown_sleep;
+ struct device *parent;
struct device *dev;
#ifdef CONFIG_PM
@@ -187,13 +188,14 @@ struct snd_minor {
int device; /* device number */
const struct file_operations *f_ops; /* file operations */
void *private_data; /* private data for f_ops->open */
- struct class_device *class_dev; /* class device for sysfs */
+ struct device *dev; /* device for sysfs */
};
/* sound.c */
extern int snd_major;
extern int snd_ecards_limit;
+extern struct class *sound_class;
void snd_request_card(int card);
@@ -203,7 +205,7 @@ int snd_register_device(int type, struct snd_card *card, int dev,
int snd_unregister_device(int type, struct snd_card *card, int dev);
void *snd_lookup_minor_data(unsigned int minor, int type);
int snd_add_device_sysfs_file(int type, struct snd_card *card, int dev,
- const struct class_device_attribute *attr);
+ struct device_attribute *attr);
#ifdef CONFIG_SND_OSSEMUL
int snd_register_oss_device(int type, struct snd_card *card, int dev,
@@ -255,7 +257,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file);
int snd_card_file_remove(struct snd_card *card, struct file *file);
#ifndef snd_card_set_dev
-#define snd_card_set_dev(card,devptr) ((card)->dev = (devptr))
+#define snd_card_set_dev(card,devptr) ((card)->parent = (devptr))
#endif
/* device.c */
diff --git a/include/sound/version.h b/include/sound/version.h
index 52fd6879b86e..17137f3a3b6f 100644
--- a/include/sound/version.h
+++ b/include/sound/version.h
@@ -1,3 +1,3 @@
/* include/version.h. Generated by alsa/ksync script. */
#define CONFIG_SND_VERSION "1.0.13"
-#define CONFIG_SND_DATE " (Sun Oct 22 08:56:16 2006 UTC)"
+#define CONFIG_SND_DATE " (Tue Nov 28 14:07:24 2006 UTC)"
diff --git a/init/Kconfig b/init/Kconfig
index 176f7e5136c7..14d484606fab 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -249,6 +249,26 @@ config CPUSETS
Say N if unsure.
+config SYSFS_DEPRECATED
+ bool "Create deprecated sysfs files"
+ default y
+ help
+ This option creates deprecated symlinks such as the
+ "device"-link, the <subsystem>:<name>-link, and the
+ "bus"-link. It may also add deprecated key in the
+ uevent environment.
+ None of these features or values should be used today, as
+ they export driver core implementation details to userspace
+ or export properties which can't be kept stable across kernel
+ releases.
+
+ If enabled, this option will also move any device structures
+ that belong to a class, back into the /sys/class heirachy, in
+ order to support older versions of udev.
+
+ If you are using a distro that was released in 2006 or later,
+ it should be safe to say N here.
+
config RELAY
bool "Kernel->user space relay support (formerly relayfs)"
help
diff --git a/kernel/fork.c b/kernel/fork.c
index 3da978eec791..8cdd3e72ba55 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1315,9 +1315,8 @@ struct task_struct * __devinit fork_idle(int cpu)
struct pt_regs regs;
task = copy_process(CLONE_VM, 0, idle_regs(&regs), 0, NULL, NULL, 0);
- if (!task)
- return ERR_PTR(-ENOMEM);
- init_idle(task, cpu);
+ if (!IS_ERR(task))
+ init_idle(task, cpu);
return task;
}
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index 42aa6f1a3f0f..a681912bc89a 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -231,10 +231,10 @@ fastcall unsigned int __do_IRQ(unsigned int irq)
spin_unlock(&desc->lock);
action_ret = handle_IRQ_event(irq, action);
-
- spin_lock(&desc->lock);
if (!noirqdebug)
note_interrupt(irq, desc, action_ret);
+
+ spin_lock(&desc->lock);
if (likely(!(desc->status & IRQ_PENDING)))
break;
desc->status &= ~IRQ_PENDING;
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c
index 9c7e2e4c1fe7..543ea2e5ad93 100644
--- a/kernel/irq/spurious.c
+++ b/kernel/irq/spurious.c
@@ -147,11 +147,7 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc,
if (unlikely(irqfixup)) {
/* Don't punish working computers */
if ((irqfixup == 2 && irq == 0) || action_ret == IRQ_NONE) {
- int ok;
-
- spin_unlock(&desc->lock);
- ok = misrouted_irq(irq);
- spin_lock(&desc->lock);
+ int ok = misrouted_irq(irq);
if (action_ret == IRQ_NONE)
desc->irqs_unhandled -= ok;
}
diff --git a/kernel/kmod.c b/kernel/kmod.c
index 7dc7a9dad6ac..8d2bea09a4ec 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -311,14 +311,14 @@ int call_usermodehelper_pipe(char *path, char **argv, char **envp,
return 0;
f = create_write_pipe();
- if (!f)
- return -ENOMEM;
+ if (IS_ERR(f))
+ return PTR_ERR(f);
*filp = f;
f = create_read_pipe(f);
- if (!f) {
+ if (IS_ERR(f)) {
free_write_pipe(*filp);
- return -ENOMEM;
+ return PTR_ERR(f);
}
sub_info.stdin = f;
diff --git a/kernel/module.c b/kernel/module.c
index f0166563c602..45e01cb60101 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -1086,22 +1086,35 @@ static int mod_sysfs_setup(struct module *mod,
goto out;
kobj_set_kset_s(&mod->mkobj, module_subsys);
mod->mkobj.mod = mod;
- err = kobject_register(&mod->mkobj.kobj);
+
+ /* delay uevent until full sysfs population */
+ kobject_init(&mod->mkobj.kobj);
+ err = kobject_add(&mod->mkobj.kobj);
if (err)
goto out;
+ mod->drivers_dir = kobject_add_dir(&mod->mkobj.kobj, "drivers");
+ if (!mod->drivers_dir)
+ goto out_unreg;
+
err = module_param_sysfs_setup(mod, kparam, num_params);
if (err)
- goto out_unreg;
+ goto out_unreg_drivers;
err = module_add_modinfo_attrs(mod);
if (err)
- goto out_unreg;
+ goto out_unreg_param;
+ kobject_uevent(&mod->mkobj.kobj, KOBJ_ADD);
return 0;
+out_unreg_drivers:
+ kobject_unregister(mod->drivers_dir);
+out_unreg_param:
+ module_param_sysfs_remove(mod);
out_unreg:
- kobject_unregister(&mod->mkobj.kobj);
+ kobject_del(&mod->mkobj.kobj);
+ kobject_put(&mod->mkobj.kobj);
out:
return err;
}
@@ -1110,6 +1123,7 @@ static void mod_kobject_remove(struct module *mod)
{
module_remove_modinfo_attrs(mod);
module_param_sysfs_remove(mod);
+ kobject_unregister(mod->drivers_dir);
kobject_unregister(&mod->mkobj.kobj);
}
@@ -2275,11 +2289,14 @@ void print_modules(void)
void module_add_driver(struct module *mod, struct device_driver *drv)
{
+ int no_warn;
+
if (!mod || !drv)
return;
- /* Don't check return code; this call is idempotent */
- sysfs_create_link(&drv->kobj, &mod->mkobj.kobj, "module");
+ /* Don't check return codes; these calls are idempotent */
+ no_warn = sysfs_create_link(&drv->kobj, &mod->mkobj.kobj, "module");
+ no_warn = sysfs_create_link(mod->drivers_dir, &drv->kobj, drv->name);
}
EXPORT_SYMBOL(module_add_driver);
@@ -2288,6 +2305,8 @@ void module_remove_driver(struct device_driver *drv)
if (!drv)
return;
sysfs_remove_link(&drv->kobj, "module");
+ if (drv->owner && drv->owner->drivers_dir)
+ sysfs_remove_link(drv->owner->drivers_dir, drv->name);
}
EXPORT_SYMBOL(module_remove_driver);
diff --git a/kernel/spinlock.c b/kernel/spinlock.c
index 476c3741511b..2c6c2bf85514 100644
--- a/kernel/spinlock.c
+++ b/kernel/spinlock.c
@@ -293,6 +293,27 @@ void __lockfunc _spin_lock_nested(spinlock_t *lock, int subclass)
}
EXPORT_SYMBOL(_spin_lock_nested);
+unsigned long __lockfunc _spin_lock_irqsave_nested(spinlock_t *lock, int subclass)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ preempt_disable();
+ spin_acquire(&lock->dep_map, subclass, 0, _RET_IP_);
+ /*
+ * On lockdep we dont want the hand-coded irq-enable of
+ * _raw_spin_lock_flags() code, because lockdep assumes
+ * that interrupts are not re-enabled during lock-acquire:
+ */
+#ifdef CONFIG_PROVE_SPIN_LOCKING
+ _raw_spin_lock(lock);
+#else
+ _raw_spin_lock_flags(lock, &flags);
+#endif
+ return flags;
+}
+
+EXPORT_SYMBOL(_spin_lock_irqsave_nested);
#endif
diff --git a/kernel/taskstats.c b/kernel/taskstats.c
index f45c5e70773c..d3d28919d4b4 100644
--- a/kernel/taskstats.c
+++ b/kernel/taskstats.c
@@ -77,8 +77,7 @@ static int prepare_reply(struct genl_info *info, u8 cmd, struct sk_buff **skbp,
/*
* If new attributes are added, please revisit this allocation
*/
- size = nlmsg_total_size(genlmsg_total_size(size));
- skb = nlmsg_new(size, GFP_KERNEL);
+ skb = genlmsg_new(size, GFP_KERNEL);
if (!skb)
return -ENOMEM;
@@ -86,13 +85,9 @@ static int prepare_reply(struct genl_info *info, u8 cmd, struct sk_buff **skbp,
int seq = get_cpu_var(taskstats_seqnum)++;
put_cpu_var(taskstats_seqnum);
- reply = genlmsg_put(skb, 0, seq,
- family.id, 0, 0,
- cmd, family.version);
+ reply = genlmsg_put(skb, 0, seq, &family, 0, cmd);
} else
- reply = genlmsg_put(skb, info->snd_pid, info->snd_seq,
- family.id, 0, 0,
- cmd, family.version);
+ reply = genlmsg_put_reply(skb, info, &family, 0, cmd);
if (reply == NULL) {
nlmsg_free(skb);
return -EINVAL;
diff --git a/kernel/unwind.c b/kernel/unwind.c
index f7e50d16dbf6..ed0a21d4a902 100644
--- a/kernel/unwind.c
+++ b/kernel/unwind.c
@@ -938,8 +938,11 @@ int unwind(struct unwind_frame_info *frame)
else {
retAddrReg = state.version <= 1 ? *ptr++ : get_uleb128(&ptr, end);
/* skip augmentation */
- if (((const char *)(cie + 2))[1] == 'z')
- ptr += get_uleb128(&ptr, end);
+ if (((const char *)(cie + 2))[1] == 'z') {
+ uleb128_t augSize = get_uleb128(&ptr, end);
+
+ ptr += augSize;
+ }
if (ptr > end
|| retAddrReg >= ARRAY_SIZE(reg_info)
|| REG_INVALID(retAddrReg)
@@ -963,9 +966,7 @@ int unwind(struct unwind_frame_info *frame)
if (cie == NULL || fde == NULL) {
#ifdef CONFIG_FRAME_POINTER
unsigned long top, bottom;
-#endif
-#ifdef CONFIG_FRAME_POINTER
top = STACK_TOP(frame->task);
bottom = STACK_BOTTOM(frame->task);
# if FRAME_RETADDR_OFFSET < 0
diff --git a/lib/kobject.c b/lib/kobject.c
index 7dd5c0e9d996..744a4b102c7f 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -311,6 +311,56 @@ int kobject_rename(struct kobject * kobj, const char *new_name)
}
/**
+ * kobject_move - move object to another parent
+ * @kobj: object in question.
+ * @new_parent: object's new parent
+ */
+
+int kobject_move(struct kobject *kobj, struct kobject *new_parent)
+{
+ int error;
+ struct kobject *old_parent;
+ const char *devpath = NULL;
+ char *devpath_string = NULL;
+ char *envp[2];
+
+ kobj = kobject_get(kobj);
+ if (!kobj)
+ return -EINVAL;
+ new_parent = kobject_get(new_parent);
+ if (!new_parent) {
+ error = -EINVAL;
+ goto out;
+ }
+ /* old object path */
+ devpath = kobject_get_path(kobj, GFP_KERNEL);
+ if (!devpath) {
+ error = -ENOMEM;
+ goto out;
+ }
+ devpath_string = kmalloc(strlen(devpath) + 15, GFP_KERNEL);
+ if (!devpath_string) {
+ error = -ENOMEM;
+ goto out;
+ }
+ sprintf(devpath_string, "DEVPATH_OLD=%s", devpath);
+ envp[0] = devpath_string;
+ envp[1] = NULL;
+ error = sysfs_move_dir(kobj, new_parent);
+ if (error)
+ goto out;
+ old_parent = kobj->parent;
+ kobj->parent = new_parent;
+ kobject_put(old_parent);
+ kobject_uevent_env(kobj, KOBJ_MOVE, envp);
+out:
+ kobject_put(kobj);
+ kfree(devpath_string);
+ kfree(devpath);
+ return error;
+}
+
+/**
* kobject_del - unlink kobject from hierarchy.
* @kobj: object.
*/
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index 7f20e7b857cb..a1922765ff31 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -50,18 +50,22 @@ static char *action_to_string(enum kobject_action action)
return "offline";
case KOBJ_ONLINE:
return "online";
+ case KOBJ_MOVE:
+ return "move";
default:
return NULL;
}
}
/**
- * kobject_uevent - notify userspace by ending an uevent
+ * kobject_uevent_env - send an uevent with environmental data
*
- * @action: action that is happening (usually KOBJ_ADD and KOBJ_REMOVE)
+ * @action: action that is happening (usually KOBJ_MOVE)
* @kobj: struct kobject that the action is happening to
+ * @envp_ext: pointer to environmental data
*/
-void kobject_uevent(struct kobject *kobj, enum kobject_action action)
+void kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
+ char *envp_ext[])
{
char **envp;
char *buffer;
@@ -76,6 +80,7 @@ void kobject_uevent(struct kobject *kobj, enum kobject_action action)
char *seq_buff;
int i = 0;
int retval;
+ int j;
pr_debug("%s\n", __FUNCTION__);
@@ -134,7 +139,8 @@ void kobject_uevent(struct kobject *kobj, enum kobject_action action)
scratch += sprintf (scratch, "DEVPATH=%s", devpath) + 1;
envp [i++] = scratch;
scratch += sprintf(scratch, "SUBSYSTEM=%s", subsystem) + 1;
-
+ for (j = 0; envp_ext && envp_ext[j]; j++)
+ envp[i++] = envp_ext[j];
/* just reserve the space, overwrite it after kset call has returned */
envp[i++] = seq_buff = scratch;
scratch += strlen("SEQNUM=18446744073709551616") + 1;
@@ -200,6 +206,20 @@ exit:
kfree(envp);
return;
}
+
+EXPORT_SYMBOL_GPL(kobject_uevent_env);
+
+/**
+ * kobject_uevent - notify userspace by ending an uevent
+ *
+ * @action: action that is happening (usually KOBJ_ADD and KOBJ_REMOVE)
+ * @kobj: struct kobject that the action is happening to
+ */
+void kobject_uevent(struct kobject *kobj, enum kobject_action action)
+{
+ kobject_uevent_env(kobj, action, NULL);
+}
+
EXPORT_SYMBOL_GPL(kobject_uevent);
/**
diff --git a/lib/textsearch.c b/lib/textsearch.c
index 2cb4a437942e..98bcadc01185 100644
--- a/lib/textsearch.c
+++ b/lib/textsearch.c
@@ -40,7 +40,7 @@
* configuration according to the specified parameters.
* (3) User starts the search(es) by calling _find() or _next() to
* fetch subsequent occurrences. A state variable is provided
- * to the algorihtm to store persistant variables.
+ * to the algorihtm to store persistent variables.
* (4) Core eventually resets the search offset and forwards the find()
* request to the algorithm.
* (5) Algorithm calls get_next_block() provided by the user continously
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index bf2f6cff1d6a..aa6fcc7ca66f 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -2612,6 +2612,9 @@ unsigned long __init find_min_pfn_for_node(unsigned long nid)
{
int i;
+ /* Regions in the early_node_map can be in any order */
+ sort_node_map();
+
/* Assuming a sorted map, the first range found has the starting pfn */
for_each_active_range_index_in_nid(i, nid)
return early_node_map[i].start_pfn;
@@ -2680,9 +2683,6 @@ void __init free_area_init_nodes(unsigned long *max_zone_pfn)
max(max_zone_pfn[i], arch_zone_lowest_possible_pfn[i]);
}
- /* Regions in the early_node_map can be in any order */
- sort_node_map();
-
/* Print out the zone ranges */
printk("Zone PFN ranges:\n");
for (i = 0; i < MAX_NR_ZONES; i++)
diff --git a/net/802/hippi.c b/net/802/hippi.c
index 6d7fed3dd99a..579e2ddf5ebe 100644
--- a/net/802/hippi.c
+++ b/net/802/hippi.c
@@ -36,7 +36,6 @@
#include <net/arp.h>
#include <net/sock.h>
#include <asm/uaccess.h>
-#include <asm/checksum.h>
#include <asm/system.h>
/*
diff --git a/net/Kconfig b/net/Kconfig
index 67e39ad8b8b6..7dfc94920697 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -75,7 +75,7 @@ config NETWORK_SECMARK
If you are unsure how to answer this question, answer N.
menuconfig NETFILTER
- bool "Network packet filtering (replaces ipchains)"
+ bool "Network packet filtering framework (Netfilter)"
---help---
Netfilter is a framework for filtering and mangling network packets
that pass through your Linux box.
@@ -175,33 +175,6 @@ source "net/ipx/Kconfig"
source "drivers/net/appletalk/Kconfig"
source "net/x25/Kconfig"
source "net/lapb/Kconfig"
-
-config NET_DIVERT
- bool "Frame Diverter (EXPERIMENTAL)"
- depends on EXPERIMENTAL && BROKEN
- ---help---
- The Frame Diverter allows you to divert packets from the
- network, that are not aimed at the interface receiving it (in
- promisc. mode). Typically, a Linux box setup as an Ethernet bridge
- with the Frames Diverter on, can do some *really* transparent www
- caching using a Squid proxy for example.
-
- This is very useful when you don't want to change your router's
- config (or if you simply don't have access to it).
-
- The other possible usages of diverting Ethernet Frames are
- numberous:
- - reroute smtp traffic to another interface
- - traffic-shape certain network streams
- - transparently proxy smtp connections
- - etc...
-
- For more informations, please refer to:
- <http://diverter.sourceforge.net/>
- <http://perso.wanadoo.fr/magpie/EtherDivert.html>
-
- If unsure, say N.
-
source "net/econet/Kconfig"
source "net/wanrouter/Kconfig"
source "net/sched/Kconfig"
diff --git a/net/atm/Makefile b/net/atm/Makefile
index 89656d6c0b90..cc50bd1ff1de 100644
--- a/net/atm/Makefile
+++ b/net/atm/Makefile
@@ -7,10 +7,7 @@ mpoa-objs := mpc.o mpoa_caches.o mpoa_proc.o
obj-$(CONFIG_ATM) += atm.o
obj-$(CONFIG_ATM_CLIP) += clip.o
-atm-$(subst m,y,$(CONFIG_ATM_CLIP)) += ipcommon.o
obj-$(CONFIG_ATM_BR2684) += br2684.o
-atm-$(subst m,y,$(CONFIG_ATM_BR2684)) += ipcommon.o
-atm-$(subst m,y,$(CONFIG_NET_SCH_ATM)) += ipcommon.o
atm-$(CONFIG_PROC_FS) += proc.o
obj-$(CONFIG_ATM_LANE) += lec.o
diff --git a/net/atm/br2684.c b/net/atm/br2684.c
index d00cca97eb33..83a1c1b1d6cd 100644
--- a/net/atm/br2684.c
+++ b/net/atm/br2684.c
@@ -23,7 +23,6 @@ Author: Marcell GAL, 2000, XDSL Ltd, Hungary
#include <linux/atmbr2684.h>
#include "common.h"
-#include "ipcommon.h"
/*
* Define this to use a version of the code which interacts with the higher
@@ -372,7 +371,7 @@ static int br2684_setfilt(struct atm_vcc *atmvcc, void __user *arg)
/* Returns 1 if packet should be dropped */
static inline int
-packet_fails_filter(u16 type, struct br2684_vcc *brvcc, struct sk_buff *skb)
+packet_fails_filter(__be16 type, struct br2684_vcc *brvcc, struct sk_buff *skb)
{
if (brvcc->filter.netmask == 0)
return 0; /* no filter in place */
@@ -500,11 +499,12 @@ Note: we do not have explicit unassign, but look at _push()
*/
int err;
struct br2684_vcc *brvcc;
- struct sk_buff_head copy;
struct sk_buff *skb;
+ struct sk_buff_head *rq;
struct br2684_dev *brdev;
struct net_device *net_dev;
struct atm_backend_br2684 be;
+ unsigned long flags;
if (copy_from_user(&be, arg, sizeof be))
return -EFAULT;
@@ -554,12 +554,30 @@ Note: we do not have explicit unassign, but look at _push()
brvcc->old_push = atmvcc->push;
barrier();
atmvcc->push = br2684_push;
- skb_queue_head_init(&copy);
- skb_migrate(&sk_atm(atmvcc)->sk_receive_queue, &copy);
- while ((skb = skb_dequeue(&copy)) != NULL) {
+
+ rq = &sk_atm(atmvcc)->sk_receive_queue;
+
+ spin_lock_irqsave(&rq->lock, flags);
+ if (skb_queue_empty(rq)) {
+ skb = NULL;
+ } else {
+ /* NULL terminate the list. */
+ rq->prev->next = NULL;
+ skb = rq->next;
+ }
+ rq->prev = rq->next = (struct sk_buff *)rq;
+ rq->qlen = 0;
+ spin_unlock_irqrestore(&rq->lock, flags);
+
+ while (skb) {
+ struct sk_buff *next = skb->next;
+
+ skb->next = skb->prev = NULL;
BRPRIV(skb->dev)->stats.rx_bytes -= skb->len;
BRPRIV(skb->dev)->stats.rx_packets--;
br2684_push(atmvcc, skb);
+
+ skb = next;
}
__module_get(THIS_MODULE);
return 0;
diff --git a/net/atm/clip.c b/net/atm/clip.c
index 7af2c411da82..5f8a1d222720 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -38,7 +38,6 @@
#include "common.h"
#include "resources.h"
-#include "ipcommon.h"
#include <net/atmclip.h>
@@ -54,7 +53,7 @@ static struct atm_vcc *atmarpd;
static struct neigh_table clip_tbl;
static struct timer_list idle_timer;
-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, __be32 ip)
{
struct sock *sk;
struct atmarp_ctrl *ctrl;
@@ -220,7 +219,7 @@ static void clip_push(struct atm_vcc *vcc, struct sk_buff *skb)
|| memcmp(skb->data, llc_oui, sizeof (llc_oui)))
skb->protocol = htons(ETH_P_IP);
else {
- skb->protocol = ((u16 *) skb->data)[3];
+ skb->protocol = ((__be16 *) skb->data)[3];
skb_pull(skb, RFC1483LLC_LEN);
if (skb->protocol == htons(ETH_P_ARP)) {
PRIV(skb->dev)->stats.rx_packets++;
@@ -430,7 +429,7 @@ static int clip_start_xmit(struct sk_buff *skb, struct net_device *dev)
here = skb_push(skb, RFC1483LLC_LEN);
memcpy(here, llc_oui, sizeof(llc_oui));
- ((u16 *) here)[3] = skb->protocol;
+ ((__be16 *) here)[3] = skb->protocol;
}
atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
ATM_SKB(skb)->atm_options = vcc->atm_options;
@@ -469,8 +468,9 @@ static struct net_device_stats *clip_get_stats(struct net_device *dev)
static int clip_mkip(struct atm_vcc *vcc, int timeout)
{
struct clip_vcc *clip_vcc;
- struct sk_buff_head copy;
struct sk_buff *skb;
+ struct sk_buff_head *rq;
+ unsigned long flags;
if (!vcc->push)
return -EBADFD;
@@ -490,10 +490,26 @@ static int clip_mkip(struct atm_vcc *vcc, int timeout)
clip_vcc->old_pop = vcc->pop;
vcc->push = clip_push;
vcc->pop = clip_pop;
- skb_queue_head_init(&copy);
- skb_migrate(&sk_atm(vcc)->sk_receive_queue, &copy);
+
+ rq = &sk_atm(vcc)->sk_receive_queue;
+
+ spin_lock_irqsave(&rq->lock, flags);
+ if (skb_queue_empty(rq)) {
+ skb = NULL;
+ } else {
+ /* NULL terminate the list. */
+ rq->prev->next = NULL;
+ skb = rq->next;
+ }
+ rq->prev = rq->next = (struct sk_buff *)rq;
+ rq->qlen = 0;
+ spin_unlock_irqrestore(&rq->lock, flags);
+
/* re-process everything received between connection setup and MKIP */
- while ((skb = skb_dequeue(&copy)) != NULL)
+ while (skb) {
+ struct sk_buff *next = skb->next;
+
+ skb->next = skb->prev = NULL;
if (!clip_devs) {
atm_return(vcc, skb->truesize);
kfree_skb(skb);
@@ -506,10 +522,13 @@ static int clip_mkip(struct atm_vcc *vcc, int timeout)
PRIV(skb->dev)->stats.rx_bytes -= len;
kfree_skb(skb);
}
+
+ skb = next;
+ }
return 0;
}
-static int clip_setentry(struct atm_vcc *vcc, u32 ip)
+static int clip_setentry(struct atm_vcc *vcc, __be32 ip)
{
struct neighbour *neigh;
struct atmarp_entry *entry;
@@ -752,7 +771,7 @@ static int clip_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
err = clip_mkip(vcc, arg);
break;
case ATMARP_SETENTRY:
- err = clip_setentry(vcc, arg);
+ err = clip_setentry(vcc, (__force __be32)arg);
break;
case ATMARP_ENCAP:
err = clip_encap(vcc, arg);
diff --git a/net/atm/ipcommon.c b/net/atm/ipcommon.c
deleted file mode 100644
index 1d3de42fada0..000000000000
--- a/net/atm/ipcommon.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/* net/atm/ipcommon.c - Common items for all ways of doing IP over ATM */
-
-/* Written 1996-2000 by Werner Almesberger, EPFL LRC/ICA */
-
-
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/in.h>
-#include <linux/atmdev.h>
-#include <linux/atmclip.h>
-
-#include "common.h"
-#include "ipcommon.h"
-
-
-#if 0
-#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
-#else
-#define DPRINTK(format,args...)
-#endif
-
-
-/*
- * skb_migrate appends the list at "from" to "to", emptying "from" in the
- * process. skb_migrate is atomic with respect to all other skb operations on
- * "from" and "to". Note that it locks both lists at the same time, so to deal
- * with the lock ordering, the locks are taken in address order.
- *
- * This function should live in skbuff.c or skbuff.h.
- */
-
-
-void skb_migrate(struct sk_buff_head *from, struct sk_buff_head *to)
-{
- unsigned long flags;
- struct sk_buff *skb_from = (struct sk_buff *) from;
- struct sk_buff *skb_to = (struct sk_buff *) to;
- struct sk_buff *prev;
-
- if ((unsigned long) from < (unsigned long) to) {
- spin_lock_irqsave(&from->lock, flags);
- spin_lock_nested(&to->lock, SINGLE_DEPTH_NESTING);
- } else {
- spin_lock_irqsave(&to->lock, flags);
- spin_lock_nested(&from->lock, SINGLE_DEPTH_NESTING);
- }
- prev = from->prev;
- from->next->prev = to->prev;
- prev->next = skb_to;
- to->prev->next = from->next;
- to->prev = from->prev;
- to->qlen += from->qlen;
- spin_unlock(&to->lock);
- from->prev = skb_from;
- from->next = skb_from;
- from->qlen = 0;
- spin_unlock_irqrestore(&from->lock, flags);
-}
-
-
-EXPORT_SYMBOL(skb_migrate);
diff --git a/net/atm/ipcommon.h b/net/atm/ipcommon.h
deleted file mode 100644
index d72165f60939..000000000000
--- a/net/atm/ipcommon.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* net/atm/ipcommon.h - Common items for all ways of doing IP over ATM */
-
-/* Written 1996-2000 by Werner Almesberger, EPFL LRC/ICA */
-
-
-#ifndef NET_ATM_IPCOMMON_H
-#define NET_ATM_IPCOMMON_H
-
-
-#include <linux/string.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/atmdev.h>
-
-/*
- * Appends all skbs from "from" to "to". The operation is atomic with respect
- * to all other skb operations on "from" or "to".
- */
-
-void skb_migrate(struct sk_buff_head *from,struct sk_buff_head *to);
-
-#endif
diff --git a/net/atm/lec.c b/net/atm/lec.c
index e801fff69dc0..3fc0abeeaf34 100644
--- a/net/atm/lec.c
+++ b/net/atm/lec.c
@@ -204,9 +204,9 @@ static unsigned char *get_tr_dst(unsigned char *packet, unsigned char *rdesc)
memset(rdesc, 0, ETH_ALEN);
/* offset 4 comes from LAN destination field in LE control frames */
if (trh->rcf & htons((uint16_t) TR_RCF_DIR_BIT))
- memcpy(&rdesc[4], &trh->rseg[num_rdsc - 2], sizeof(uint16_t));
+ memcpy(&rdesc[4], &trh->rseg[num_rdsc - 2], sizeof(__be16));
else {
- memcpy(&rdesc[4], &trh->rseg[1], sizeof(uint16_t));
+ memcpy(&rdesc[4], &trh->rseg[1], sizeof(__be16));
rdesc[5] = ((ntohs(trh->rseg[0]) & 0x000f) | (rdesc[5] & 0xf0));
}
@@ -775,7 +775,7 @@ static void lec_push(struct atm_vcc *vcc, struct sk_buff *skb)
unsigned char *src, *dst;
atm_return(vcc, skb->truesize);
- if (*(uint16_t *) skb->data == htons(priv->lecid) ||
+ if (*(__be16 *) skb->data == htons(priv->lecid) ||
!priv->lecd || !(dev->flags & IFF_UP)) {
/*
* Probably looping back, or if lecd is missing,
@@ -1321,11 +1321,10 @@ static int lane2_resolve(struct net_device *dev, u8 *dst_mac, int force,
if (table == NULL)
return -1;
- *tlvs = kmalloc(table->sizeoftlvs, GFP_ATOMIC);
+ *tlvs = kmemdup(table->tlvs, table->sizeoftlvs, GFP_ATOMIC);
if (*tlvs == NULL)
return -1;
- memcpy(*tlvs, table->tlvs, table->sizeoftlvs);
*sizeoftlvs = table->sizeoftlvs;
return 0;
@@ -1364,11 +1363,10 @@ static int lane2_associate_req(struct net_device *dev, u8 *lan_dst,
kfree(priv->tlvs); /* NULL if there was no previous association */
- priv->tlvs = kmalloc(sizeoftlvs, GFP_KERNEL);
+ priv->tlvs = kmemdup(tlvs, sizeoftlvs, GFP_KERNEL);
if (priv->tlvs == NULL)
return (0);
priv->sizeoftlvs = sizeoftlvs;
- memcpy(priv->tlvs, tlvs, sizeoftlvs);
skb = alloc_skb(sizeoftlvs, GFP_ATOMIC);
if (skb == NULL)
@@ -1409,12 +1407,10 @@ static void lane2_associate_ind(struct net_device *dev, u8 *mac_addr,
kfree(entry->tlvs);
- entry->tlvs = kmalloc(sizeoftlvs, GFP_KERNEL);
+ entry->tlvs = kmemdup(tlvs, sizeoftlvs, GFP_KERNEL);
if (entry->tlvs == NULL)
return;
-
entry->sizeoftlvs = sizeoftlvs;
- memcpy(entry->tlvs, tlvs, sizeoftlvs);
#endif
#if 0
printk("lec.c: lane2_associate_ind()\n");
diff --git a/net/atm/lec.h b/net/atm/lec.h
index 984e8e6e083a..99136babd535 100644
--- a/net/atm/lec.h
+++ b/net/atm/lec.h
@@ -14,14 +14,14 @@
#define LEC_HEADER_LEN 16
struct lecdatahdr_8023 {
- unsigned short le_header;
+ __be16 le_header;
unsigned char h_dest[ETH_ALEN];
unsigned char h_source[ETH_ALEN];
- unsigned short h_type;
+ __be16 h_type;
};
struct lecdatahdr_8025 {
- unsigned short le_header;
+ __be16 le_header;
unsigned char ac_pad;
unsigned char fc;
unsigned char h_dest[ETH_ALEN];
diff --git a/net/atm/mpc.c b/net/atm/mpc.c
index 0d2b994af511..c18f73715ef9 100644
--- a/net/atm/mpc.c
+++ b/net/atm/mpc.c
@@ -152,7 +152,7 @@ static struct mpoa_client *find_mpc_by_lec(struct net_device *dev)
/*
* Overwrites the old entry or makes a new one.
*/
-struct atm_mpoa_qos *atm_mpoa_add_qos(uint32_t dst_ip, struct atm_qos *qos)
+struct atm_mpoa_qos *atm_mpoa_add_qos(__be32 dst_ip, struct atm_qos *qos)
{
struct atm_mpoa_qos *entry;
@@ -177,7 +177,7 @@ struct atm_mpoa_qos *atm_mpoa_add_qos(uint32_t dst_ip, struct atm_qos *qos)
return entry;
}
-struct atm_mpoa_qos *atm_mpoa_search_qos(uint32_t dst_ip)
+struct atm_mpoa_qos *atm_mpoa_search_qos(__be32 dst_ip)
{
struct atm_mpoa_qos *qos;
@@ -460,11 +460,11 @@ static int send_via_shortcut(struct sk_buff *skb, struct mpoa_client *mpc)
in_cache_entry *entry;
struct iphdr *iph;
char *buff;
- uint32_t ipaddr = 0;
+ __be32 ipaddr = 0;
static struct {
struct llc_snap_hdr hdr;
- uint32_t tag;
+ __be32 tag;
} tagged_llc_snap_hdr = {
{0xaa, 0xaa, 0x03, {0x00, 0x00, 0x00}, {0x88, 0x4c}},
0
@@ -559,7 +559,7 @@ static int atm_mpoa_vcc_attach(struct atm_vcc *vcc, void __user *arg)
struct mpoa_client *mpc;
struct atmmpc_ioc ioc_data;
in_cache_entry *in_entry;
- uint32_t ipaddr;
+ __be32 ipaddr;
bytes_left = copy_from_user(&ioc_data, arg, sizeof(struct atmmpc_ioc));
if (bytes_left != 0) {
@@ -638,7 +638,7 @@ static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb)
struct sk_buff *new_skb;
eg_cache_entry *eg;
struct mpoa_client *mpc;
- uint32_t tag;
+ __be32 tag;
char *tmp;
ddprintk("mpoa: (%s) mpc_push:\n", dev->name);
@@ -683,7 +683,7 @@ static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb)
}
tmp = skb->data + sizeof(struct llc_snap_hdr);
- tag = *(uint32_t *)tmp;
+ tag = *(__be32 *)tmp;
eg = mpc->eg_ops->get_by_tag(tag, mpc);
if (eg == NULL) {
@@ -1029,7 +1029,7 @@ static int mpoa_event_listener(struct notifier_block *mpoa_notifier, unsigned lo
static void MPOA_trigger_rcvd(struct k_message *msg, struct mpoa_client *mpc)
{
- uint32_t dst_ip = msg->content.in_info.in_dst_ip;
+ __be32 dst_ip = msg->content.in_info.in_dst_ip;
in_cache_entry *entry;
entry = mpc->in_ops->get(dst_ip, mpc);
@@ -1066,7 +1066,7 @@ static void MPOA_trigger_rcvd(struct k_message *msg, struct mpoa_client *mpc)
*/
static void check_qos_and_open_shortcut(struct k_message *msg, struct mpoa_client *client, in_cache_entry *entry)
{
- uint32_t dst_ip = msg->content.in_info.in_dst_ip;
+ __be32 dst_ip = msg->content.in_info.in_dst_ip;
struct atm_mpoa_qos *qos = atm_mpoa_search_qos(dst_ip);
eg_cache_entry *eg_entry = client->eg_ops->get_by_src_ip(dst_ip, client);
@@ -1102,7 +1102,7 @@ static void check_qos_and_open_shortcut(struct k_message *msg, struct mpoa_clien
static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *mpc)
{
- uint32_t dst_ip = msg->content.in_info.in_dst_ip;
+ __be32 dst_ip = msg->content.in_info.in_dst_ip;
in_cache_entry *entry = mpc->in_ops->get(dst_ip, mpc);
dprintk("mpoa: (%s) MPOA_res_reply_rcvd: ip %u.%u.%u.%u\n", mpc->dev->name, NIPQUAD(dst_ip));
@@ -1148,8 +1148,8 @@ static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *mpc)
static void ingress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc)
{
- uint32_t dst_ip = msg->content.in_info.in_dst_ip;
- uint32_t mask = msg->ip_mask;
+ __be32 dst_ip = msg->content.in_info.in_dst_ip;
+ __be32 mask = msg->ip_mask;
in_cache_entry *entry = mpc->in_ops->get_with_mask(dst_ip, mpc, mask);
if(entry == NULL){
@@ -1173,7 +1173,7 @@ static void ingress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc)
static void egress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc)
{
- uint32_t cache_id = msg->content.eg_info.cache_id;
+ __be32 cache_id = msg->content.eg_info.cache_id;
eg_cache_entry *entry = mpc->eg_ops->get_by_cache_id(cache_id, mpc);
if (entry == NULL) {
@@ -1322,13 +1322,12 @@ static void set_mps_mac_addr_rcvd(struct k_message *msg, struct mpoa_client *cli
if(client->number_of_mps_macs)
kfree(client->mps_macs);
client->number_of_mps_macs = 0;
- client->mps_macs = kmalloc(ETH_ALEN,GFP_KERNEL);
+ client->mps_macs = kmemdup(msg->MPS_ctrl, ETH_ALEN, GFP_KERNEL);
if (client->mps_macs == NULL) {
printk("mpoa: set_mps_mac_addr_rcvd: out of memory\n");
return;
}
client->number_of_mps_macs = 1;
- memcpy(client->mps_macs, msg->MPS_ctrl, ETH_ALEN);
return;
}
diff --git a/net/atm/mpc.h b/net/atm/mpc.h
index 3c7981a229e8..51f460d005c3 100644
--- a/net/atm/mpc.h
+++ b/net/atm/mpc.h
@@ -36,14 +36,14 @@ struct mpoa_client {
struct atm_mpoa_qos {
struct atm_mpoa_qos *next;
- uint32_t ipaddr;
+ __be32 ipaddr;
struct atm_qos qos;
};
/* MPOA QoS operations */
-struct atm_mpoa_qos *atm_mpoa_add_qos(uint32_t dst_ip, struct atm_qos *qos);
-struct atm_mpoa_qos *atm_mpoa_search_qos(uint32_t dst_ip);
+struct atm_mpoa_qos *atm_mpoa_add_qos(__be32 dst_ip, struct atm_qos *qos);
+struct atm_mpoa_qos *atm_mpoa_search_qos(__be32 dst_ip);
int atm_mpoa_delete_qos(struct atm_mpoa_qos *qos);
/* Display QoS entries. This is for the procfs */
diff --git a/net/atm/mpoa_caches.c b/net/atm/mpoa_caches.c
index fbf13cdcf46e..697a081533b5 100644
--- a/net/atm/mpoa_caches.c
+++ b/net/atm/mpoa_caches.c
@@ -22,7 +22,7 @@
#define ddprintk(format,args...)
#endif
-static in_cache_entry *in_cache_get(uint32_t dst_ip,
+static in_cache_entry *in_cache_get(__be32 dst_ip,
struct mpoa_client *client)
{
in_cache_entry *entry;
@@ -42,9 +42,9 @@ static in_cache_entry *in_cache_get(uint32_t dst_ip,
return NULL;
}
-static in_cache_entry *in_cache_get_with_mask(uint32_t dst_ip,
+static in_cache_entry *in_cache_get_with_mask(__be32 dst_ip,
struct mpoa_client *client,
- uint32_t mask)
+ __be32 mask)
{
in_cache_entry *entry;
@@ -84,10 +84,10 @@ static in_cache_entry *in_cache_get_by_vcc(struct atm_vcc *vcc,
return NULL;
}
-static in_cache_entry *in_cache_add_entry(uint32_t dst_ip,
+static in_cache_entry *in_cache_add_entry(__be32 dst_ip,
struct mpoa_client *client)
{
- in_cache_entry* entry = kmalloc(sizeof(in_cache_entry), GFP_KERNEL);
+ in_cache_entry *entry = kzalloc(sizeof(in_cache_entry), GFP_KERNEL);
if (entry == NULL) {
printk("mpoa: mpoa_caches.c: new_in_cache_entry: out of memory\n");
@@ -95,7 +95,6 @@ static in_cache_entry *in_cache_add_entry(uint32_t dst_ip,
}
dprintk("mpoa: mpoa_caches.c: adding an ingress entry, ip = %u.%u.%u.%u\n", NIPQUAD(dst_ip));
- memset(entry,0,sizeof(in_cache_entry));
atomic_set(&entry->use, 1);
dprintk("mpoa: mpoa_caches.c: new_in_cache_entry: about to lock\n");
@@ -319,7 +318,7 @@ static void in_destroy_cache(struct mpoa_client *mpc)
return;
}
-static eg_cache_entry *eg_cache_get_by_cache_id(uint32_t cache_id, struct mpoa_client *mpc)
+static eg_cache_entry *eg_cache_get_by_cache_id(__be32 cache_id, struct mpoa_client *mpc)
{
eg_cache_entry *entry;
@@ -339,7 +338,7 @@ static eg_cache_entry *eg_cache_get_by_cache_id(uint32_t cache_id, struct mpoa_c
}
/* This can be called from any context since it saves CPU flags */
-static eg_cache_entry *eg_cache_get_by_tag(uint32_t tag, struct mpoa_client *mpc)
+static eg_cache_entry *eg_cache_get_by_tag(__be32 tag, struct mpoa_client *mpc)
{
unsigned long flags;
eg_cache_entry *entry;
@@ -380,7 +379,7 @@ static eg_cache_entry *eg_cache_get_by_vcc(struct atm_vcc *vcc, struct mpoa_clie
return NULL;
}
-static eg_cache_entry *eg_cache_get_by_src_ip(uint32_t ipaddr, struct mpoa_client *mpc)
+static eg_cache_entry *eg_cache_get_by_src_ip(__be32 ipaddr, struct mpoa_client *mpc)
{
eg_cache_entry *entry;
@@ -447,7 +446,7 @@ static void eg_cache_remove_entry(eg_cache_entry *entry,
static eg_cache_entry *eg_cache_add_entry(struct k_message *msg, struct mpoa_client *client)
{
- eg_cache_entry *entry = kmalloc(sizeof(eg_cache_entry), GFP_KERNEL);
+ eg_cache_entry *entry = kzalloc(sizeof(eg_cache_entry), GFP_KERNEL);
if (entry == NULL) {
printk("mpoa: mpoa_caches.c: new_eg_cache_entry: out of memory\n");
@@ -455,7 +454,6 @@ static eg_cache_entry *eg_cache_add_entry(struct k_message *msg, struct mpoa_cli
}
dprintk("mpoa: mpoa_caches.c: adding an egress entry, ip = %u.%u.%u.%u, this should be our IP\n", NIPQUAD(msg->content.eg_info.eg_dst_ip));
- memset(entry, 0, sizeof(eg_cache_entry));
atomic_set(&entry->use, 1);
dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry: about to lock\n");
diff --git a/net/atm/mpoa_caches.h b/net/atm/mpoa_caches.h
index 6c9886a03d0b..84de977def2e 100644
--- a/net/atm/mpoa_caches.h
+++ b/net/atm/mpoa_caches.h
@@ -29,12 +29,12 @@ typedef struct in_cache_entry {
} in_cache_entry;
struct in_cache_ops{
- in_cache_entry *(*add_entry)(uint32_t dst_ip,
+ in_cache_entry *(*add_entry)(__be32 dst_ip,
struct mpoa_client *client);
- in_cache_entry *(*get)(uint32_t dst_ip, struct mpoa_client *client);
- in_cache_entry *(*get_with_mask)(uint32_t dst_ip,
+ in_cache_entry *(*get)(__be32 dst_ip, struct mpoa_client *client);
+ in_cache_entry *(*get_with_mask)(__be32 dst_ip,
struct mpoa_client *client,
- uint32_t mask);
+ __be32 mask);
in_cache_entry *(*get_by_vcc)(struct atm_vcc *vcc,
struct mpoa_client *client);
void (*put)(in_cache_entry *entry);
@@ -56,17 +56,17 @@ typedef struct eg_cache_entry{
struct atm_vcc *shortcut;
uint32_t packets_rcvd;
uint16_t entry_state;
- uint32_t latest_ip_addr; /* The src IP address of the last packet */
+ __be32 latest_ip_addr; /* The src IP address of the last packet */
struct eg_ctrl_info ctrl_info;
atomic_t use;
} eg_cache_entry;
struct eg_cache_ops{
eg_cache_entry *(*add_entry)(struct k_message *msg, struct mpoa_client *client);
- eg_cache_entry *(*get_by_cache_id)(uint32_t cache_id, struct mpoa_client *client);
- eg_cache_entry *(*get_by_tag)(uint32_t cache_id, struct mpoa_client *client);
+ eg_cache_entry *(*get_by_cache_id)(__be32 cache_id, struct mpoa_client *client);
+ eg_cache_entry *(*get_by_tag)(__be32 cache_id, struct mpoa_client *client);
eg_cache_entry *(*get_by_vcc)(struct atm_vcc *vcc, struct mpoa_client *client);
- eg_cache_entry *(*get_by_src_ip)(uint32_t ipaddr, struct mpoa_client *client);
+ eg_cache_entry *(*get_by_src_ip)(__be32 ipaddr, struct mpoa_client *client);
void (*put)(eg_cache_entry *entry);
void (*remove_entry)(eg_cache_entry *entry, struct mpoa_client *client);
void (*update)(eg_cache_entry *entry, uint16_t holding_time);
diff --git a/net/atm/mpoa_proc.c b/net/atm/mpoa_proc.c
index d37b8911b3ab..3844c85d602f 100644
--- a/net/atm/mpoa_proc.c
+++ b/net/atm/mpoa_proc.c
@@ -231,14 +231,14 @@ static int parse_qos(const char *buff)
*/
unsigned char ip[4];
int tx_pcr, tx_sdu, rx_pcr, rx_sdu;
- uint32_t ipaddr;
+ __be32 ipaddr;
struct atm_qos qos;
memset(&qos, 0, sizeof(struct atm_qos));
if (sscanf(buff, "del %hhu.%hhu.%hhu.%hhu",
ip, ip+1, ip+2, ip+3) == 4) {
- ipaddr = *(uint32_t *)ip;
+ ipaddr = *(__be32 *)ip;
return atm_mpoa_delete_qos(atm_mpoa_search_qos(ipaddr));
}
@@ -250,7 +250,7 @@ static int parse_qos(const char *buff)
ip, ip+1, ip+2, ip+3, &tx_pcr, &tx_sdu, &rx_pcr, &rx_sdu) != 8)
return 0;
- ipaddr = *(uint32_t *)ip;
+ ipaddr = *(__be32 *)ip;
qos.txtp.traffic_class = ATM_CBR;
qos.txtp.max_pcr = tx_pcr;
qos.txtp.max_sdu = tx_sdu;
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index 000695c48583..6cabf6d8a751 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -906,13 +906,13 @@ struct sock *ax25_make_new(struct sock *osk, struct ax25_dev *ax25_dev)
ax25->source_addr = oax25->source_addr;
if (oax25->digipeat != NULL) {
- if ((ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
+ ax25->digipeat = kmemdup(oax25->digipeat, sizeof(ax25_digi),
+ GFP_ATOMIC);
+ if (ax25->digipeat == NULL) {
sk_free(sk);
ax25_cb_put(ax25);
return NULL;
}
-
- memcpy(ax25->digipeat, oax25->digipeat, sizeof(ax25_digi));
}
sk->sk_protinfo = ax25;
diff --git a/net/ax25/ax25_out.c b/net/ax25/ax25_out.c
index d7736e585336..f84047d1e8ce 100644
--- a/net/ax25/ax25_out.c
+++ b/net/ax25/ax25_out.c
@@ -70,11 +70,11 @@ ax25_cb *ax25_send_frame(struct sk_buff *skb, int paclen, ax25_address *src, ax2
ax25->dest_addr = *dest;
if (digi != NULL) {
- if ((ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
+ ax25->digipeat = kmemdup(digi, sizeof(*digi), GFP_ATOMIC);
+ if (ax25->digipeat == NULL) {
ax25_cb_put(ax25);
return NULL;
}
- memcpy(ax25->digipeat, digi, sizeof(ax25_digi));
}
switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c
index 51b7bdaf27eb..8580356ace5c 100644
--- a/net/ax25/ax25_route.c
+++ b/net/ax25/ax25_route.c
@@ -432,11 +432,12 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr)
}
if (ax25_rt->digipeat != NULL) {
- if ((ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
+ ax25->digipeat = kmemdup(ax25_rt->digipeat, sizeof(ax25_digi),
+ GFP_ATOMIC);
+ if (ax25->digipeat == NULL) {
err = -ENOMEM;
goto put;
}
- memcpy(ax25->digipeat, ax25_rt->digipeat, sizeof(ax25_digi));
ax25_adjust_path(addr, ax25->digipeat);
}
diff --git a/net/ax25/sysctl_net_ax25.c b/net/ax25/sysctl_net_ax25.c
index 867d42537979..d23a27f25d2f 100644
--- a/net/ax25/sysctl_net_ax25.c
+++ b/net/ax25/sysctl_net_ax25.c
@@ -209,7 +209,9 @@ void ax25_register_sysctl(void)
}
for (n = 0, ax25_dev = ax25_dev_list; ax25_dev != NULL; ax25_dev = ax25_dev->next) {
- ctl_table *child = kmalloc(sizeof(ax25_param_table), GFP_ATOMIC);
+ struct ctl_table *child = kmemdup(ax25_param_table,
+ sizeof(ax25_param_table),
+ GFP_ATOMIC);
if (!child) {
while (n--)
kfree(ax25_table[n].child);
@@ -217,7 +219,6 @@ void ax25_register_sysctl(void)
spin_unlock_bh(&ax25_dev_lock);
return;
}
- memcpy(child, ax25_param_table, sizeof(ax25_param_table));
ax25_table[n].child = ax25_dev->systable = child;
ax25_table[n].ctl_name = n + 1;
ax25_table[n].procname = ax25_dev->dev->name;
diff --git a/net/bluetooth/bnep/bnep.h b/net/bluetooth/bnep/bnep.h
index bbb1ed7097a9..0b6cd0e2528d 100644
--- a/net/bluetooth/bnep/bnep.h
+++ b/net/bluetooth/bnep/bnep.h
@@ -95,14 +95,14 @@ struct bnep_setup_conn_req {
struct bnep_set_filter_req {
__u8 type;
__u8 ctrl;
- __u16 len;
+ __be16 len;
__u8 list[0];
} __attribute__((packed));
struct bnep_control_rsp {
__u8 type;
__u8 ctrl;
- __u16 resp;
+ __be16 resp;
} __attribute__((packed));
struct bnep_ext_hdr {
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
index 4d3424c2421c..7ba6470dc507 100644
--- a/net/bluetooth/bnep/core.c
+++ b/net/bluetooth/bnep/core.c
@@ -117,18 +117,18 @@ static int bnep_send_rsp(struct bnep_session *s, u8 ctrl, u16 resp)
static inline void bnep_set_default_proto_filter(struct bnep_session *s)
{
/* (IPv4, ARP) */
- s->proto_filter[0].start = htons(0x0800);
- s->proto_filter[0].end = htons(0x0806);
+ s->proto_filter[0].start = ETH_P_IP;
+ s->proto_filter[0].end = ETH_P_ARP;
/* (RARP, AppleTalk) */
- s->proto_filter[1].start = htons(0x8035);
- s->proto_filter[1].end = htons(0x80F3);
+ s->proto_filter[1].start = ETH_P_RARP;
+ s->proto_filter[1].end = ETH_P_AARP;
/* (IPX, IPv6) */
- s->proto_filter[2].start = htons(0x8137);
- s->proto_filter[2].end = htons(0x86DD);
+ s->proto_filter[2].start = ETH_P_IPX;
+ s->proto_filter[2].end = ETH_P_IPV6;
}
#endif
-static int bnep_ctrl_set_netfilter(struct bnep_session *s, u16 *data, int len)
+static int bnep_ctrl_set_netfilter(struct bnep_session *s, __be16 *data, int len)
{
int n;
@@ -150,8 +150,8 @@ static int bnep_ctrl_set_netfilter(struct bnep_session *s, u16 *data, int len)
int i;
for (i = 0; i < n; i++) {
- f[i].start = get_unaligned(data++);
- f[i].end = get_unaligned(data++);
+ f[i].start = ntohs(get_unaligned(data++));
+ f[i].end = ntohs(get_unaligned(data++));
BT_DBG("proto filter start %d end %d",
f[i].start, f[i].end);
@@ -180,7 +180,7 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len)
if (len < 2)
return -EILSEQ;
- n = ntohs(get_unaligned((u16 *) data));
+ n = ntohs(get_unaligned((__be16 *) data));
data += 2; len -= 2;
if (len < n)
@@ -332,7 +332,7 @@ static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
if (!skb_pull(skb, __bnep_rx_hlen[type & BNEP_TYPE_MASK]))
goto badframe;
- s->eh.h_proto = get_unaligned((u16 *) (skb->data - 2));
+ s->eh.h_proto = get_unaligned((__be16 *) (skb->data - 2));
if (type & BNEP_EXT_HEADER) {
if (bnep_rx_extension(s, skb) < 0)
@@ -343,7 +343,7 @@ static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
if (ntohs(s->eh.h_proto) == 0x8100) {
if (!skb_pull(skb, 4))
goto badframe;
- s->eh.h_proto = get_unaligned((u16 *) (skb->data - 2));
+ s->eh.h_proto = get_unaligned((__be16 *) (skb->data - 2));
}
/* We have to alloc new skb and copy data here :(. Because original skb
@@ -365,7 +365,7 @@ static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
case BNEP_COMPRESSED_SRC_ONLY:
memcpy(__skb_put(nskb, ETH_ALEN), s->eh.h_dest, ETH_ALEN);
memcpy(__skb_put(nskb, ETH_ALEN), skb->mac.raw, ETH_ALEN);
- put_unaligned(s->eh.h_proto, (u16 *) __skb_put(nskb, 2));
+ put_unaligned(s->eh.h_proto, (__be16 *) __skb_put(nskb, 2));
break;
case BNEP_COMPRESSED_DST_ONLY:
@@ -375,7 +375,7 @@ static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
case BNEP_GENERAL:
memcpy(__skb_put(nskb, ETH_ALEN * 2), skb->mac.raw, ETH_ALEN * 2);
- put_unaligned(s->eh.h_proto, (u16 *) __skb_put(nskb, 2));
+ put_unaligned(s->eh.h_proto, (__be16 *) __skb_put(nskb, 2));
break;
}
diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c
index 7f7b27db6a8f..67a002a9751a 100644
--- a/net/bluetooth/bnep/netdev.c
+++ b/net/bluetooth/bnep/netdev.c
@@ -158,14 +158,15 @@ static inline int bnep_net_mc_filter(struct sk_buff *skb, struct bnep_session *s
static inline u16 bnep_net_eth_proto(struct sk_buff *skb)
{
struct ethhdr *eh = (void *) skb->data;
+ u16 proto = ntohs(eh->h_proto);
- if (ntohs(eh->h_proto) >= 1536)
- return eh->h_proto;
+ if (proto >= 1536)
+ return proto;
- if (get_unaligned((u16 *) skb->data) == 0xFFFF)
- return htons(ETH_P_802_3);
+ if (get_unaligned((__be16 *) skb->data) == htons(0xFFFF))
+ return ETH_P_802_3;
- return htons(ETH_P_802_2);
+ return ETH_P_802_2;
}
static inline int bnep_net_proto_filter(struct sk_buff *skb, struct bnep_session *s)
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index bbf78e6a7bc3..29a8fa4d3728 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -770,7 +770,7 @@ static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int fl
long timeo;
int err = 0;
- lock_sock(sk);
+ lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
if (sk->sk_state != BT_LISTEN) {
err = -EBADFD;
@@ -792,7 +792,7 @@ static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int fl
release_sock(sk);
timeo = schedule_timeout(timeo);
- lock_sock(sk);
+ lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
if (sk->sk_state != BT_LISTEN) {
err = -EBADFD;
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index ddc4e9d5963e..278c8676906a 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -854,7 +854,7 @@ int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci,
rpn->flow_ctrl = flow_ctrl_settings;
rpn->xon_char = xon_char;
rpn->xoff_char = xoff_char;
- rpn->param_mask = param_mask;
+ rpn->param_mask = cpu_to_le16(param_mask);
*ptr = __fcs(buf); ptr++;
@@ -1018,7 +1018,7 @@ static void rfcomm_make_uih(struct sk_buff *skb, u8 addr)
if (len > 127) {
hdr = (void *) skb_push(skb, 4);
- put_unaligned(htobs(__len16(len)), (u16 *) &hdr->len);
+ put_unaligned(htobs(__len16(len)), (__le16 *) &hdr->len);
} else {
hdr = (void *) skb_push(skb, 3);
hdr->len = __len8(len);
@@ -1343,7 +1343,7 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
/* Check for sane values, ignore/accept bit_rate, 8 bits, 1 stop bit,
* no parity, no flow control lines, normal XON/XOFF chars */
- if (rpn->param_mask & RFCOMM_RPN_PM_BITRATE) {
+ if (rpn->param_mask & cpu_to_le16(RFCOMM_RPN_PM_BITRATE)) {
bit_rate = rpn->bit_rate;
if (bit_rate != RFCOMM_RPN_BR_115200) {
BT_DBG("RPN bit rate mismatch 0x%x", bit_rate);
@@ -1352,7 +1352,7 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
}
}
- if (rpn->param_mask & RFCOMM_RPN_PM_DATA) {
+ if (rpn->param_mask & cpu_to_le16(RFCOMM_RPN_PM_DATA)) {
data_bits = __get_rpn_data_bits(rpn->line_settings);
if (data_bits != RFCOMM_RPN_DATA_8) {
BT_DBG("RPN data bits mismatch 0x%x", data_bits);
@@ -1361,7 +1361,7 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
}
}
- if (rpn->param_mask & RFCOMM_RPN_PM_STOP) {
+ if (rpn->param_mask & cpu_to_le16(RFCOMM_RPN_PM_STOP)) {
stop_bits = __get_rpn_stop_bits(rpn->line_settings);
if (stop_bits != RFCOMM_RPN_STOP_1) {
BT_DBG("RPN stop bits mismatch 0x%x", stop_bits);
@@ -1370,7 +1370,7 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
}
}
- if (rpn->param_mask & RFCOMM_RPN_PM_PARITY) {
+ if (rpn->param_mask & cpu_to_le16(RFCOMM_RPN_PM_PARITY)) {
parity = __get_rpn_parity(rpn->line_settings);
if (parity != RFCOMM_RPN_PARITY_NONE) {
BT_DBG("RPN parity mismatch 0x%x", parity);
@@ -1379,7 +1379,7 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
}
}
- if (rpn->param_mask & RFCOMM_RPN_PM_FLOW) {
+ if (rpn->param_mask & cpu_to_le16(RFCOMM_RPN_PM_FLOW)) {
flow_ctrl = rpn->flow_ctrl;
if (flow_ctrl != RFCOMM_RPN_FLOW_NONE) {
BT_DBG("RPN flow ctrl mismatch 0x%x", flow_ctrl);
@@ -1388,7 +1388,7 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
}
}
- if (rpn->param_mask & RFCOMM_RPN_PM_XON) {
+ if (rpn->param_mask & cpu_to_le16(RFCOMM_RPN_PM_XON)) {
xon_char = rpn->xon_char;
if (xon_char != RFCOMM_RPN_XON_CHAR) {
BT_DBG("RPN XON char mismatch 0x%x", xon_char);
@@ -1397,7 +1397,7 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
}
}
- if (rpn->param_mask & RFCOMM_RPN_PM_XOFF) {
+ if (rpn->param_mask & cpu_to_le16(RFCOMM_RPN_PM_XOFF)) {
xoff_char = rpn->xoff_char;
if (xoff_char != RFCOMM_RPN_XOFF_CHAR) {
BT_DBG("RPN XOFF char mismatch 0x%x", xoff_char);
diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
index 4e4119a12139..4c61a7e0a86e 100644
--- a/net/bridge/br_ioctl.c
+++ b/net/bridge/br_ioctl.c
@@ -58,12 +58,13 @@ static int get_fdb_entries(struct net_bridge *br, void __user *userbuf,
{
int num;
void *buf;
- size_t size = maxnum * sizeof(struct __fdb_entry);
+ size_t size;
- if (size > PAGE_SIZE) {
- size = PAGE_SIZE;
+ /* Clamp size to PAGE_SIZE, test maxnum to avoid overflow */
+ if (maxnum > PAGE_SIZE/sizeof(struct __fdb_entry))
maxnum = PAGE_SIZE/sizeof(struct __fdb_entry);
- }
+
+ size = maxnum * sizeof(struct __fdb_entry);
buf = kmalloc(size, GFP_USER);
if (!buf)
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index ac181be13d83..ac47ba2ba028 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -40,7 +40,6 @@
#include <net/route.h>
#include <asm/uaccess.h>
-#include <asm/checksum.h>
#include "br_private.h"
#ifdef CONFIG_SYSCTL
#include <linux/sysctl.h>
@@ -381,7 +380,7 @@ static int check_hbh_len(struct sk_buff *skb)
case IPV6_TLV_JUMBO:
if (skb->nh.raw[off + 1] != 4 || (off & 3) != 2)
goto bad;
- pkt_len = ntohl(*(u32 *) (skb->nh.raw + off + 2));
+ pkt_len = ntohl(*(__be32 *) (skb->nh.raw + off + 2));
if (pkt_len <= IPV6_MAXPLEN ||
skb->nh.ipv6h->payload_len)
goto bad;
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 8f661195d09d..a9139682c49b 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -15,6 +15,18 @@
#include <net/netlink.h>
#include "br_private.h"
+static inline size_t br_nlmsg_size(void)
+{
+ return NLMSG_ALIGN(sizeof(struct ifinfomsg))
+ + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
+ + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */
+ + nla_total_size(4) /* IFLA_MASTER */
+ + nla_total_size(4) /* IFLA_MTU */
+ + nla_total_size(4) /* IFLA_LINK */
+ + nla_total_size(1) /* IFLA_OPERSTATE */
+ + nla_total_size(1); /* IFLA_PROTINFO */
+}
+
/*
* Create one netlink message for one interface
* Contains port and master info as well as carrier and bridge state.
@@ -24,51 +36,43 @@ static int br_fill_ifinfo(struct sk_buff *skb, const struct net_bridge_port *por
{
const struct net_bridge *br = port->br;
const struct net_device *dev = port->dev;
- struct ifinfomsg *r;
+ struct ifinfomsg *hdr;
struct nlmsghdr *nlh;
- unsigned char *b = skb->tail;
- u32 mtu = dev->mtu;
u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN;
- u8 portstate = port->state;
pr_debug("br_fill_info event %d port %s master %s\n",
event, dev->name, br->dev->name);
- nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*r), flags);
- r = NLMSG_DATA(nlh);
- r->ifi_family = AF_BRIDGE;
- r->__ifi_pad = 0;
- r->ifi_type = dev->type;
- r->ifi_index = dev->ifindex;
- r->ifi_flags = dev_get_flags(dev);
- r->ifi_change = 0;
+ nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags);
+ if (nlh == NULL)
+ return -ENOBUFS;
- RTA_PUT(skb, IFLA_IFNAME, strlen(dev->name)+1, dev->name);
+ hdr = nlmsg_data(nlh);
+ hdr->ifi_family = AF_BRIDGE;
+ hdr->__ifi_pad = 0;
+ hdr->ifi_type = dev->type;
+ hdr->ifi_index = dev->ifindex;
+ hdr->ifi_flags = dev_get_flags(dev);
+ hdr->ifi_change = 0;
- RTA_PUT(skb, IFLA_MASTER, sizeof(int), &br->dev->ifindex);
+ NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name);
+ NLA_PUT_U32(skb, IFLA_MASTER, br->dev->ifindex);
+ NLA_PUT_U32(skb, IFLA_MTU, dev->mtu);
+ NLA_PUT_U8(skb, IFLA_OPERSTATE, operstate);
if (dev->addr_len)
- RTA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr);
+ NLA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr);
- RTA_PUT(skb, IFLA_MTU, sizeof(mtu), &mtu);
if (dev->ifindex != dev->iflink)
- RTA_PUT(skb, IFLA_LINK, sizeof(int), &dev->iflink);
-
-
- RTA_PUT(skb, IFLA_OPERSTATE, sizeof(operstate), &operstate);
+ NLA_PUT_U32(skb, IFLA_LINK, dev->iflink);
if (event == RTM_NEWLINK)
- RTA_PUT(skb, IFLA_PROTINFO, sizeof(portstate), &portstate);
-
- nlh->nlmsg_len = skb->tail - b;
-
- return skb->len;
+ NLA_PUT_U8(skb, IFLA_PROTINFO, port->state);
-nlmsg_failure:
-rtattr_failure:
+ return nlmsg_end(skb, nlh);
- skb_trim(skb, b - skb->data);
- return -EINVAL;
+nla_put_failure:
+ return nlmsg_cancel(skb, nlh);
}
/*
@@ -77,19 +81,16 @@ rtattr_failure:
void br_ifinfo_notify(int event, struct net_bridge_port *port)
{
struct sk_buff *skb;
- int payload = sizeof(struct ifinfomsg) + 128;
int err = -ENOBUFS;
pr_debug("bridge notify event=%d\n", event);
- skb = nlmsg_new(nlmsg_total_size(payload), GFP_ATOMIC);
+ skb = nlmsg_new(br_nlmsg_size(), GFP_ATOMIC);
if (skb == NULL)
goto errout;
err = br_fill_ifinfo(skb, port, 0, 0, event, 0);
- if (err < 0) {
- kfree_skb(skb);
- goto errout;
- }
+ /* failure implies BUG in br_nlmsg_size() */
+ BUG_ON(err < 0);
err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
errout:
@@ -104,25 +105,18 @@ static int br_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
{
struct net_device *dev;
int idx;
- int s_idx = cb->args[0];
- int err = 0;
read_lock(&dev_base_lock);
for (dev = dev_base, idx = 0; dev; dev = dev->next) {
- struct net_bridge_port *p = dev->br_port;
-
/* not a bridge port */
- if (!p)
- continue;
-
- if (idx < s_idx)
- goto cont;
+ if (dev->br_port == NULL || idx < cb->args[0])
+ goto skip;
- err = br_fill_ifinfo(skb, p, NETLINK_CB(cb->skb).pid,
- cb->nlh->nlmsg_seq, RTM_NEWLINK, NLM_F_MULTI);
- if (err <= 0)
+ if (br_fill_ifinfo(skb, dev->br_port, NETLINK_CB(cb->skb).pid,
+ cb->nlh->nlmsg_seq, RTM_NEWLINK,
+ NLM_F_MULTI) < 0)
break;
-cont:
+skip:
++idx;
}
read_unlock(&dev_base_lock);
@@ -138,26 +132,27 @@ cont:
*/
static int br_rtm_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
{
- struct rtattr **rta = arg;
- struct ifinfomsg *ifm = NLMSG_DATA(nlh);
+ struct ifinfomsg *ifm;
+ struct nlattr *protinfo;
struct net_device *dev;
struct net_bridge_port *p;
u8 new_state;
+ if (nlmsg_len(nlh) < sizeof(*ifm))
+ return -EINVAL;
+
+ ifm = nlmsg_data(nlh);
if (ifm->ifi_family != AF_BRIDGE)
return -EPFNOSUPPORT;
- /* Must pass valid state as PROTINFO */
- if (rta[IFLA_PROTINFO-1]) {
- u8 *pstate = RTA_DATA(rta[IFLA_PROTINFO-1]);
- new_state = *pstate;
- } else
+ protinfo = nlmsg_find_attr(nlh, sizeof(*ifm), IFLA_PROTINFO);
+ if (!protinfo || nla_len(protinfo) < sizeof(u8))
return -EINVAL;
+ new_state = nla_get_u8(protinfo);
if (new_state > BR_STATE_BLOCKING)
return -EINVAL;
- /* Find bridge port */
dev = __dev_get_by_index(ifm->ifi_index);
if (!dev)
return -ENODEV;
@@ -170,10 +165,8 @@ static int br_rtm_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
if (p->br->stp_enabled)
return -EBUSY;
- if (!netif_running(dev))
- return -ENETDOWN;
-
- if (!netif_carrier_ok(dev) && new_state != BR_STATE_DISABLED)
+ if (!netif_running(dev) ||
+ (!netif_carrier_ok(dev) && new_state != BR_STATE_DISABLED))
return -ENETDOWN;
p->state = new_state;
diff --git a/net/bridge/netfilter/ebt_802_3.c b/net/bridge/netfilter/ebt_802_3.c
index d42f63f5e9f8..9abbc09ccdc3 100644
--- a/net/bridge/netfilter/ebt_802_3.c
+++ b/net/bridge/netfilter/ebt_802_3.c
@@ -17,7 +17,7 @@ static int ebt_filter_802_3(const struct sk_buff *skb, const struct net_device *
{
struct ebt_802_3_info *info = (struct ebt_802_3_info *)data;
struct ebt_802_3_hdr *hdr = ebt_802_3_hdr(skb);
- uint16_t type = hdr->llc.ui.ctrl & IS_UI ? hdr->llc.ui.type : hdr->llc.ni.type;
+ __be16 type = hdr->llc.ui.ctrl & IS_UI ? hdr->llc.ui.type : hdr->llc.ni.type;
if (info->bitmask & EBT_802_3_SAP) {
if (FWINV(info->sap != hdr->llc.ui.ssap, EBT_802_3_SAP))
diff --git a/net/bridge/netfilter/ebt_among.c b/net/bridge/netfilter/ebt_among.c
index a614485828af..ce97c4285f9a 100644
--- a/net/bridge/netfilter/ebt_among.c
+++ b/net/bridge/netfilter/ebt_among.c
@@ -15,7 +15,7 @@
#include <linux/module.h>
static int ebt_mac_wormhash_contains(const struct ebt_mac_wormhash *wh,
- const char *mac, uint32_t ip)
+ const char *mac, __be32 ip)
{
/* You may be puzzled as to how this code works.
* Some tricks were used, refer to
@@ -70,7 +70,7 @@ static int ebt_mac_wormhash_check_integrity(const struct ebt_mac_wormhash
return 0;
}
-static int get_ip_dst(const struct sk_buff *skb, uint32_t *addr)
+static int get_ip_dst(const struct sk_buff *skb, __be32 *addr)
{
if (eth_hdr(skb)->h_proto == htons(ETH_P_IP)) {
struct iphdr _iph, *ih;
@@ -81,16 +81,16 @@ static int get_ip_dst(const struct sk_buff *skb, uint32_t *addr)
*addr = ih->daddr;
} else if (eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) {
struct arphdr _arph, *ah;
- uint32_t buf, *bp;
+ __be32 buf, *bp;
ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph);
if (ah == NULL ||
- ah->ar_pln != sizeof(uint32_t) ||
+ ah->ar_pln != sizeof(__be32) ||
ah->ar_hln != ETH_ALEN)
return -1;
bp = skb_header_pointer(skb, sizeof(struct arphdr) +
- 2 * ETH_ALEN + sizeof(uint32_t),
- sizeof(uint32_t), &buf);
+ 2 * ETH_ALEN + sizeof(__be32),
+ sizeof(__be32), &buf);
if (bp == NULL)
return -1;
*addr = *bp;
@@ -98,7 +98,7 @@ static int get_ip_dst(const struct sk_buff *skb, uint32_t *addr)
return 0;
}
-static int get_ip_src(const struct sk_buff *skb, uint32_t *addr)
+static int get_ip_src(const struct sk_buff *skb, __be32 *addr)
{
if (eth_hdr(skb)->h_proto == htons(ETH_P_IP)) {
struct iphdr _iph, *ih;
@@ -109,15 +109,15 @@ static int get_ip_src(const struct sk_buff *skb, uint32_t *addr)
*addr = ih->saddr;
} else if (eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) {
struct arphdr _arph, *ah;
- uint32_t buf, *bp;
+ __be32 buf, *bp;
ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph);
if (ah == NULL ||
- ah->ar_pln != sizeof(uint32_t) ||
+ ah->ar_pln != sizeof(__be32) ||
ah->ar_hln != ETH_ALEN)
return -1;
bp = skb_header_pointer(skb, sizeof(struct arphdr) +
- ETH_ALEN, sizeof(uint32_t), &buf);
+ ETH_ALEN, sizeof(__be32), &buf);
if (bp == NULL)
return -1;
*addr = *bp;
@@ -133,7 +133,7 @@ static int ebt_filter_among(const struct sk_buff *skb,
struct ebt_among_info *info = (struct ebt_among_info *) data;
const char *dmac, *smac;
const struct ebt_mac_wormhash *wh_dst, *wh_src;
- uint32_t dip = 0, sip = 0;
+ __be32 dip = 0, sip = 0;
wh_dst = ebt_among_wh_dst(info);
wh_src = ebt_among_wh_src(info);
diff --git a/net/bridge/netfilter/ebt_arp.c b/net/bridge/netfilter/ebt_arp.c
index a6c81d9f73b8..9c599800a900 100644
--- a/net/bridge/netfilter/ebt_arp.c
+++ b/net/bridge/netfilter/ebt_arp.c
@@ -35,10 +35,10 @@ static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in
return EBT_NOMATCH;
if (info->bitmask & (EBT_ARP_SRC_IP | EBT_ARP_DST_IP)) {
- uint32_t _addr, *ap;
+ __be32 _addr, *ap;
/* IPv4 addresses are always 4 bytes */
- if (ah->ar_pln != sizeof(uint32_t))
+ if (ah->ar_pln != sizeof(__be32))
return EBT_NOMATCH;
if (info->bitmask & EBT_ARP_SRC_IP) {
ap = skb_header_pointer(skb, sizeof(struct arphdr) +
@@ -53,7 +53,7 @@ static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in
if (info->bitmask & EBT_ARP_DST_IP) {
ap = skb_header_pointer(skb, sizeof(struct arphdr) +
- 2*ah->ar_hln+sizeof(uint32_t),
+ 2*ah->ar_hln+sizeof(__be32),
sizeof(_addr), &_addr);
if (ap == NULL)
return EBT_NOMATCH;
diff --git a/net/bridge/netfilter/ebt_ip.c b/net/bridge/netfilter/ebt_ip.c
index 65b665ce57b5..e4c642448e1b 100644
--- a/net/bridge/netfilter/ebt_ip.c
+++ b/net/bridge/netfilter/ebt_ip.c
@@ -20,8 +20,8 @@
#include <linux/module.h>
struct tcpudphdr {
- uint16_t src;
- uint16_t dst;
+ __be16 src;
+ __be16 dst;
};
static int ebt_filter_ip(const struct sk_buff *skb, const struct net_device *in,
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c
index 466ed3440b74..a184f879f253 100644
--- a/net/bridge/netfilter/ebt_log.c
+++ b/net/bridge/netfilter/ebt_log.c
@@ -38,8 +38,8 @@ static int ebt_log_check(const char *tablename, unsigned int hookmask,
struct tcpudphdr
{
- uint16_t src;
- uint16_t dst;
+ __be16 src;
+ __be16 dst;
};
struct arppayload
@@ -130,7 +130,7 @@ ebt_log_packet(unsigned int pf, unsigned int hooknum,
* then log the ARP payload */
if (ah->ar_hrd == htons(1) &&
ah->ar_hln == ETH_ALEN &&
- ah->ar_pln == sizeof(uint32_t)) {
+ ah->ar_pln == sizeof(__be32)) {
struct arppayload _arpp, *ap;
ap = skb_header_pointer(skb, sizeof(_arph),
diff --git a/net/bridge/netfilter/ebt_mark.c b/net/bridge/netfilter/ebt_mark.c
index b54306a934e5..62d23c7b25e6 100644
--- a/net/bridge/netfilter/ebt_mark.c
+++ b/net/bridge/netfilter/ebt_mark.c
@@ -25,15 +25,15 @@ static int ebt_target_mark(struct sk_buff **pskb, unsigned int hooknr,
int action = info->target & -16;
if (action == MARK_SET_VALUE)
- (*pskb)->nfmark = info->mark;
+ (*pskb)->mark = info->mark;
else if (action == MARK_OR_VALUE)
- (*pskb)->nfmark |= info->mark;
+ (*pskb)->mark |= info->mark;
else if (action == MARK_AND_VALUE)
- (*pskb)->nfmark &= info->mark;
+ (*pskb)->mark &= info->mark;
else
- (*pskb)->nfmark ^= info->mark;
+ (*pskb)->mark ^= info->mark;
- return info->target | -16;
+ return info->target | ~EBT_VERDICT_BITS;
}
static int ebt_target_mark_check(const char *tablename, unsigned int hookmask,
@@ -44,13 +44,13 @@ static int ebt_target_mark_check(const char *tablename, unsigned int hookmask,
if (datalen != EBT_ALIGN(sizeof(struct ebt_mark_t_info)))
return -EINVAL;
- tmp = info->target | -16;
+ tmp = info->target | ~EBT_VERDICT_BITS;
if (BASE_CHAIN && tmp == EBT_RETURN)
return -EINVAL;
CLEAR_BASE_CHAIN_BIT;
if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0)
return -EINVAL;
- tmp = info->target & -16;
+ tmp = info->target & ~EBT_VERDICT_BITS;
if (tmp != MARK_SET_VALUE && tmp != MARK_OR_VALUE &&
tmp != MARK_AND_VALUE && tmp != MARK_XOR_VALUE)
return -EINVAL;
diff --git a/net/bridge/netfilter/ebt_mark_m.c b/net/bridge/netfilter/ebt_mark_m.c
index a6413e4b4982..025869ee0b68 100644
--- a/net/bridge/netfilter/ebt_mark_m.c
+++ b/net/bridge/netfilter/ebt_mark_m.c
@@ -19,8 +19,8 @@ static int ebt_filter_mark(const struct sk_buff *skb,
struct ebt_mark_m_info *info = (struct ebt_mark_m_info *) data;
if (info->bitmask & EBT_MARK_OR)
- return !(!!(skb->nfmark & info->mask) ^ info->invert);
- return !(((skb->nfmark & info->mask) == info->mark) ^ info->invert);
+ return !(!!(skb->mark & info->mask) ^ info->invert);
+ return !(((skb->mark & info->mask) == info->mark) ^ info->invert);
}
static int ebt_mark_check(const char *tablename, unsigned int hookmask,
diff --git a/net/bridge/netfilter/ebt_snat.c b/net/bridge/netfilter/ebt_snat.c
index cbb33e24ca8a..a50722182bfe 100644
--- a/net/bridge/netfilter/ebt_snat.c
+++ b/net/bridge/netfilter/ebt_snat.c
@@ -12,6 +12,8 @@
#include <linux/netfilter_bridge/ebt_nat.h>
#include <linux/module.h>
#include <net/sock.h>
+#include <linux/if_arp.h>
+#include <net/arp.h>
static int ebt_target_snat(struct sk_buff **pskb, unsigned int hooknr,
const struct net_device *in, const struct net_device *out,
@@ -31,24 +33,43 @@ static int ebt_target_snat(struct sk_buff **pskb, unsigned int hooknr,
*pskb = nskb;
}
memcpy(eth_hdr(*pskb)->h_source, info->mac, ETH_ALEN);
- return info->target;
+ if (!(info->target & NAT_ARP_BIT) &&
+ eth_hdr(*pskb)->h_proto == htons(ETH_P_ARP)) {
+ struct arphdr _ah, *ap;
+
+ ap = skb_header_pointer(*pskb, 0, sizeof(_ah), &_ah);
+ if (ap == NULL)
+ return EBT_DROP;
+ if (ap->ar_hln != ETH_ALEN)
+ goto out;
+ if (skb_store_bits(*pskb, sizeof(_ah), info->mac,ETH_ALEN))
+ return EBT_DROP;
+ }
+out:
+ return info->target | ~EBT_VERDICT_BITS;
}
static int ebt_target_snat_check(const char *tablename, unsigned int hookmask,
const struct ebt_entry *e, void *data, unsigned int datalen)
{
struct ebt_nat_info *info = (struct ebt_nat_info *) data;
+ int tmp;
if (datalen != EBT_ALIGN(sizeof(struct ebt_nat_info)))
return -EINVAL;
- if (BASE_CHAIN && info->target == EBT_RETURN)
+ tmp = info->target | ~EBT_VERDICT_BITS;
+ if (BASE_CHAIN && tmp == EBT_RETURN)
return -EINVAL;
CLEAR_BASE_CHAIN_BIT;
if (strcmp(tablename, "nat"))
return -EINVAL;
if (hookmask & ~(1 << NF_BR_POST_ROUTING))
return -EINVAL;
- if (INVALID_TARGET)
+
+ if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0)
+ return -EINVAL;
+ tmp = info->target | EBT_VERDICT_BITS;
+ if ((tmp & ~NAT_ARP_BIT) != ~NAT_ARP_BIT)
return -EINVAL;
return 0;
}
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c
index 9f950db3b76f..c1af68b5a29c 100644
--- a/net/bridge/netfilter/ebt_ulog.c
+++ b/net/bridge/netfilter/ebt_ulog.c
@@ -168,7 +168,7 @@ static void ebt_ulog_packet(unsigned int hooknr, const struct sk_buff *skb,
if (ub->qlen == 1)
skb_set_timestamp(ub->skb, &pm->stamp);
pm->data_len = copy_len;
- pm->mark = skb->nfmark;
+ pm->mark = skb->mark;
pm->hook = hooknr;
if (uloginfo->prefix != NULL)
strcpy(pm->prefix, uloginfo->prefix);
diff --git a/net/bridge/netfilter/ebt_vlan.c b/net/bridge/netfilter/ebt_vlan.c
index a2b452862b73..7ee377622964 100644
--- a/net/bridge/netfilter/ebt_vlan.c
+++ b/net/bridge/netfilter/ebt_vlan.c
@@ -55,7 +55,7 @@ ebt_filter_vlan(const struct sk_buff *skb,
unsigned short id; /* VLAN ID, given from frame TCI */
unsigned char prio; /* user_priority, given from frame TCI */
/* VLAN encapsulated Type/Length field, given from orig frame */
- unsigned short encap;
+ __be16 encap;
fp = skb_header_pointer(skb, 0, sizeof(_frame), &_frame);
if (fp == NULL)
diff --git a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c
index 9a6e548e148b..d37ce0478938 100644
--- a/net/bridge/netfilter/ebtable_broute.c
+++ b/net/bridge/netfilter/ebtable_broute.c
@@ -23,7 +23,7 @@ static struct ebt_entries initial_chain = {
.policy = EBT_ACCEPT,
};
-static struct ebt_replace initial_table =
+static struct ebt_replace_kernel initial_table =
{
.name = "broute",
.valid_hooks = 1 << NF_BR_BROUTING,
diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c
index 3d5bd44f2395..127135ead2d5 100644
--- a/net/bridge/netfilter/ebtable_filter.c
+++ b/net/bridge/netfilter/ebtable_filter.c
@@ -30,7 +30,7 @@ static struct ebt_entries initial_chains[] =
},
};
-static struct ebt_replace initial_table =
+static struct ebt_replace_kernel initial_table =
{
.name = "filter",
.valid_hooks = FILTER_VALID_HOOKS,
diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c
index 04dd42efda1d..9c50488b62eb 100644
--- a/net/bridge/netfilter/ebtable_nat.c
+++ b/net/bridge/netfilter/ebtable_nat.c
@@ -30,7 +30,7 @@ static struct ebt_entries initial_chains[] =
}
};
-static struct ebt_replace initial_table =
+static struct ebt_replace_kernel initial_table =
{
.name = "nat",
.valid_hooks = NAT_VALID_HOOKS,
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 9f85666f29f7..bee558a41800 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -338,10 +338,11 @@ ebt_check_match(struct ebt_entry_match *m, struct ebt_entry *e,
const char *name, unsigned int hookmask, unsigned int *cnt)
{
struct ebt_match *match;
+ size_t left = ((char *)e + e->watchers_offset) - (char *)m;
int ret;
- if (((char *)m) + m->match_size + sizeof(struct ebt_entry_match) >
- ((char *)e) + e->watchers_offset)
+ if (left < sizeof(struct ebt_entry_match) ||
+ left - sizeof(struct ebt_entry_match) < m->match_size)
return -EINVAL;
match = find_match_lock(m->u.name, &ret, &ebt_mutex);
if (!match)
@@ -367,10 +368,11 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e,
const char *name, unsigned int hookmask, unsigned int *cnt)
{
struct ebt_watcher *watcher;
+ size_t left = ((char *)e + e->target_offset) - (char *)w;
int ret;
- if (((char *)w) + w->watcher_size + sizeof(struct ebt_entry_watcher) >
- ((char *)e) + e->target_offset)
+ if (left < sizeof(struct ebt_entry_watcher) ||
+ left - sizeof(struct ebt_entry_watcher) < w->watcher_size)
return -EINVAL;
watcher = find_watcher_lock(w->u.name, &ret, &ebt_mutex);
if (!watcher)
@@ -391,35 +393,91 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e,
return 0;
}
+static int ebt_verify_pointers(struct ebt_replace *repl,
+ struct ebt_table_info *newinfo)
+{
+ unsigned int limit = repl->entries_size;
+ unsigned int valid_hooks = repl->valid_hooks;
+ unsigned int offset = 0;
+ int i;
+
+ for (i = 0; i < NF_BR_NUMHOOKS; i++)
+ newinfo->hook_entry[i] = NULL;
+
+ newinfo->entries_size = repl->entries_size;
+ newinfo->nentries = repl->nentries;
+
+ while (offset < limit) {
+ size_t left = limit - offset;
+ struct ebt_entry *e = (void *)newinfo->entries + offset;
+
+ if (left < sizeof(unsigned int))
+ break;
+
+ for (i = 0; i < NF_BR_NUMHOOKS; i++) {
+ if ((valid_hooks & (1 << i)) == 0)
+ continue;
+ if ((char __user *)repl->hook_entry[i] ==
+ repl->entries + offset)
+ break;
+ }
+
+ if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) {
+ if (e->bitmask != 0) {
+ /* we make userspace set this right,
+ so there is no misunderstanding */
+ BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set "
+ "in distinguisher\n");
+ return -EINVAL;
+ }
+ if (i != NF_BR_NUMHOOKS)
+ newinfo->hook_entry[i] = (struct ebt_entries *)e;
+ if (left < sizeof(struct ebt_entries))
+ break;
+ offset += sizeof(struct ebt_entries);
+ } else {
+ if (left < sizeof(struct ebt_entry))
+ break;
+ if (left < e->next_offset)
+ break;
+ offset += e->next_offset;
+ }
+ }
+ if (offset != limit) {
+ BUGPRINT("entries_size too small\n");
+ return -EINVAL;
+ }
+
+ /* check if all valid hooks have a chain */
+ for (i = 0; i < NF_BR_NUMHOOKS; i++) {
+ if (!newinfo->hook_entry[i] &&
+ (valid_hooks & (1 << i))) {
+ BUGPRINT("Valid hook without chain\n");
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
/*
* this one is very careful, as it is the first function
* to parse the userspace data
*/
static inline int
ebt_check_entry_size_and_hooks(struct ebt_entry *e,
- struct ebt_table_info *newinfo, char *base, char *limit,
- struct ebt_entries **hook_entries, unsigned int *n, unsigned int *cnt,
- unsigned int *totalcnt, unsigned int *udc_cnt, unsigned int valid_hooks)
+ struct ebt_table_info *newinfo,
+ unsigned int *n, unsigned int *cnt,
+ unsigned int *totalcnt, unsigned int *udc_cnt)
{
int i;
for (i = 0; i < NF_BR_NUMHOOKS; i++) {
- if ((valid_hooks & (1 << i)) == 0)
- continue;
- if ( (char *)hook_entries[i] - base ==
- (char *)e - newinfo->entries)
+ if ((void *)e == (void *)newinfo->hook_entry[i])
break;
}
/* beginning of a new chain
if i == NF_BR_NUMHOOKS it must be a user defined chain */
- if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) {
- if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) != 0) {
- /* we make userspace set this right,
- so there is no misunderstanding */
- BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set "
- "in distinguisher\n");
- return -EINVAL;
- }
+ if (i != NF_BR_NUMHOOKS || !e->bitmask) {
/* this checks if the previous chain has as many entries
as it said it has */
if (*n != *cnt) {
@@ -427,12 +485,6 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
"in the chain\n");
return -EINVAL;
}
- /* before we look at the struct, be sure it is not too big */
- if ((char *)hook_entries[i] + sizeof(struct ebt_entries)
- > limit) {
- BUGPRINT("entries_size too small\n");
- return -EINVAL;
- }
if (((struct ebt_entries *)e)->policy != EBT_DROP &&
((struct ebt_entries *)e)->policy != EBT_ACCEPT) {
/* only RETURN from udc */
@@ -444,8 +496,6 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
}
if (i == NF_BR_NUMHOOKS) /* it's a user defined chain */
(*udc_cnt)++;
- else
- newinfo->hook_entry[i] = (struct ebt_entries *)e;
if (((struct ebt_entries *)e)->counter_offset != *totalcnt) {
BUGPRINT("counter_offset != totalcnt");
return -EINVAL;
@@ -466,7 +516,6 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
BUGPRINT("target size too small\n");
return -EINVAL;
}
-
(*cnt)++;
(*totalcnt)++;
return 0;
@@ -485,17 +534,14 @@ struct ebt_cl_stack
*/
static inline int
ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,
- struct ebt_entries **hook_entries, unsigned int *n, unsigned int valid_hooks,
- struct ebt_cl_stack *udc)
+ unsigned int *n, struct ebt_cl_stack *udc)
{
int i;
/* we're only interested in chain starts */
- if (e->bitmask & EBT_ENTRY_OR_ENTRIES)
+ if (e->bitmask)
return 0;
for (i = 0; i < NF_BR_NUMHOOKS; i++) {
- if ((valid_hooks & (1 << i)) == 0)
- continue;
if (newinfo->hook_entry[i] == (struct ebt_entries *)e)
break;
}
@@ -541,7 +587,7 @@ ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt)
{
struct ebt_entry_target *t;
- if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) == 0)
+ if (e->bitmask == 0)
return 0;
/* we're done */
if (cnt && (*cnt)-- == 0)
@@ -558,16 +604,17 @@ ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt)
static inline int
ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
- const char *name, unsigned int *cnt, unsigned int valid_hooks,
+ const char *name, unsigned int *cnt,
struct ebt_cl_stack *cl_s, unsigned int udc_cnt)
{
struct ebt_entry_target *t;
struct ebt_target *target;
unsigned int i, j, hook = 0, hookmask = 0;
+ size_t gap = e->next_offset - e->target_offset;
int ret;
/* don't mess with the struct ebt_entries */
- if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) == 0)
+ if (e->bitmask == 0)
return 0;
if (e->bitmask & ~EBT_F_MASK) {
@@ -584,7 +631,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
}
/* what hook do we belong to? */
for (i = 0; i < NF_BR_NUMHOOKS; i++) {
- if ((valid_hooks & (1 << i)) == 0)
+ if (!newinfo->hook_entry[i])
continue;
if ((char *)newinfo->hook_entry[i] < (char *)e)
hook = i;
@@ -625,8 +672,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
t->u.target = target;
if (t->u.target == &ebt_standard_target) {
- if (e->target_offset + sizeof(struct ebt_standard_target) >
- e->next_offset) {
+ if (gap < sizeof(struct ebt_standard_target)) {
BUGPRINT("Standard target size too big\n");
ret = -EFAULT;
goto cleanup_watchers;
@@ -637,8 +683,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
ret = -EFAULT;
goto cleanup_watchers;
}
- } else if ((e->target_offset + t->target_size +
- sizeof(struct ebt_entry_target) > e->next_offset) ||
+ } else if (t->target_size > gap - sizeof(struct ebt_entry_target) ||
(t->u.target->check &&
t->u.target->check(name, hookmask, e, t->data, t->target_size) != 0)){
module_put(t->u.target->me);
@@ -708,7 +753,9 @@ static int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s
BUGPRINT("loop\n");
return -1;
}
- /* this can't be 0, so the above test is correct */
+ if (cl_s[i].hookmask & (1 << hooknr))
+ goto letscontinue;
+ /* this can't be 0, so the loop test is correct */
cl_s[i].cs.n = pos + 1;
pos = 0;
cl_s[i].cs.e = ((void *)e + e->next_offset);
@@ -728,42 +775,35 @@ letscontinue:
}
/* do the parsing of the table/chains/entries/matches/watchers/targets, heh */
-static int translate_table(struct ebt_replace *repl,
- struct ebt_table_info *newinfo)
+static int translate_table(char *name, struct ebt_table_info *newinfo)
{
unsigned int i, j, k, udc_cnt;
int ret;
struct ebt_cl_stack *cl_s = NULL; /* used in the checking for chain loops */
i = 0;
- while (i < NF_BR_NUMHOOKS && !(repl->valid_hooks & (1 << i)))
+ while (i < NF_BR_NUMHOOKS && !newinfo->hook_entry[i])
i++;
if (i == NF_BR_NUMHOOKS) {
BUGPRINT("No valid hooks specified\n");
return -EINVAL;
}
- if (repl->hook_entry[i] != (struct ebt_entries *)repl->entries) {
+ if (newinfo->hook_entry[i] != (struct ebt_entries *)newinfo->entries) {
BUGPRINT("Chains don't start at beginning\n");
return -EINVAL;
}
/* make sure chains are ordered after each other in same order
as their corresponding hooks */
for (j = i + 1; j < NF_BR_NUMHOOKS; j++) {
- if (!(repl->valid_hooks & (1 << j)))
+ if (!newinfo->hook_entry[j])
continue;
- if ( repl->hook_entry[j] <= repl->hook_entry[i] ) {
+ if (newinfo->hook_entry[j] <= newinfo->hook_entry[i]) {
BUGPRINT("Hook order must be followed\n");
return -EINVAL;
}
i = j;
}
- for (i = 0; i < NF_BR_NUMHOOKS; i++)
- newinfo->hook_entry[i] = NULL;
-
- newinfo->entries_size = repl->entries_size;
- newinfo->nentries = repl->nentries;
-
/* do some early checkings and initialize some things */
i = 0; /* holds the expected nr. of entries for the chain */
j = 0; /* holds the up to now counted entries for the chain */
@@ -771,9 +811,8 @@ static int translate_table(struct ebt_replace *repl,
newinfo->nentries afterwards */
udc_cnt = 0; /* will hold the nr. of user defined chains (udc) */
ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
- ebt_check_entry_size_and_hooks, newinfo, repl->entries,
- repl->entries + repl->entries_size, repl->hook_entry, &i, &j, &k,
- &udc_cnt, repl->valid_hooks);
+ ebt_check_entry_size_and_hooks, newinfo,
+ &i, &j, &k, &udc_cnt);
if (ret != 0)
return ret;
@@ -788,15 +827,6 @@ static int translate_table(struct ebt_replace *repl,
return -EINVAL;
}
- /* check if all valid hooks have a chain */
- for (i = 0; i < NF_BR_NUMHOOKS; i++) {
- if (newinfo->hook_entry[i] == NULL &&
- (repl->valid_hooks & (1 << i))) {
- BUGPRINT("Valid hook without chain\n");
- return -EINVAL;
- }
- }
-
/* get the location of the udc, put them in an array
while we're at it, allocate the chainstack */
if (udc_cnt) {
@@ -824,8 +854,7 @@ static int translate_table(struct ebt_replace *repl,
return -ENOMEM;
i = 0; /* the i'th udc */
EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
- ebt_get_udc_positions, newinfo, repl->hook_entry, &i,
- repl->valid_hooks, cl_s);
+ ebt_get_udc_positions, newinfo, &i, cl_s);
/* sanity check */
if (i != udc_cnt) {
BUGPRINT("i != udc_cnt\n");
@@ -836,7 +865,7 @@ static int translate_table(struct ebt_replace *repl,
/* Check for loops */
for (i = 0; i < NF_BR_NUMHOOKS; i++)
- if (repl->valid_hooks & (1 << i))
+ if (newinfo->hook_entry[i])
if (check_chainloops(newinfo->hook_entry[i],
cl_s, udc_cnt, i, newinfo->entries)) {
vfree(cl_s);
@@ -856,8 +885,7 @@ static int translate_table(struct ebt_replace *repl,
/* used to know what we need to clean up if something goes wrong */
i = 0;
ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
- ebt_check_entry, newinfo, repl->name, &i, repl->valid_hooks,
- cl_s, udc_cnt);
+ ebt_check_entry, newinfo, name, &i, cl_s, udc_cnt);
if (ret != 0) {
EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
ebt_cleanup_entry, &i);
@@ -954,7 +982,11 @@ static int do_replace(void __user *user, unsigned int len)
/* this can get initialized by translate_table() */
newinfo->chainstack = NULL;
- ret = translate_table(&tmp, newinfo);
+ ret = ebt_verify_pointers(&tmp, newinfo);
+ if (ret != 0)
+ goto free_counterstmp;
+
+ ret = translate_table(tmp.name, newinfo);
if (ret != 0)
goto free_counterstmp;
@@ -1125,35 +1157,47 @@ int ebt_register_table(struct ebt_table *table)
{
struct ebt_table_info *newinfo;
struct ebt_table *t;
+ struct ebt_replace_kernel *repl;
int ret, i, countersize;
+ void *p;
- if (!table || !table->table ||!table->table->entries ||
- table->table->entries_size == 0 ||
- table->table->counters || table->private) {
+ if (!table || !(repl = table->table) || !repl->entries ||
+ repl->entries_size == 0 ||
+ repl->counters || table->private) {
BUGPRINT("Bad table data for ebt_register_table!!!\n");
return -EINVAL;
}
- countersize = COUNTER_OFFSET(table->table->nentries) *
+ countersize = COUNTER_OFFSET(repl->nentries) *
(highest_possible_processor_id()+1);
newinfo = vmalloc(sizeof(*newinfo) + countersize);
ret = -ENOMEM;
if (!newinfo)
return -ENOMEM;
- newinfo->entries = vmalloc(table->table->entries_size);
- if (!(newinfo->entries))
+ p = vmalloc(repl->entries_size);
+ if (!p)
goto free_newinfo;
- memcpy(newinfo->entries, table->table->entries,
- table->table->entries_size);
+ memcpy(p, repl->entries, repl->entries_size);
+ newinfo->entries = p;
+
+ newinfo->entries_size = repl->entries_size;
+ newinfo->nentries = repl->nentries;
if (countersize)
memset(newinfo->counters, 0, countersize);
/* fill in newinfo and parse the entries */
newinfo->chainstack = NULL;
- ret = translate_table(table->table, newinfo);
+ for (i = 0; i < NF_BR_NUMHOOKS; i++) {
+ if ((repl->valid_hooks & (1 << i)) == 0)
+ newinfo->hook_entry[i] = NULL;
+ else
+ newinfo->hook_entry[i] = p +
+ ((char *)repl->hook_entry[i] - repl->entries);
+ }
+ ret = translate_table(repl->name, newinfo);
if (ret != 0) {
BUGPRINT("Translate_table failed\n");
goto free_chainstack;
@@ -1277,33 +1321,33 @@ free_tmp:
}
static inline int ebt_make_matchname(struct ebt_entry_match *m,
- char *base, char *ubase)
+ char *base, char __user *ubase)
{
- char *hlp = ubase - base + (char *)m;
+ char __user *hlp = ubase + ((char *)m - base);
if (copy_to_user(hlp, m->u.match->name, EBT_FUNCTION_MAXNAMELEN))
return -EFAULT;
return 0;
}
static inline int ebt_make_watchername(struct ebt_entry_watcher *w,
- char *base, char *ubase)
+ char *base, char __user *ubase)
{
- char *hlp = ubase - base + (char *)w;
+ char __user *hlp = ubase + ((char *)w - base);
if (copy_to_user(hlp , w->u.watcher->name, EBT_FUNCTION_MAXNAMELEN))
return -EFAULT;
return 0;
}
-static inline int ebt_make_names(struct ebt_entry *e, char *base, char *ubase)
+static inline int ebt_make_names(struct ebt_entry *e, char *base, char __user *ubase)
{
int ret;
- char *hlp;
+ char __user *hlp;
struct ebt_entry_target *t;
- if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) == 0)
+ if (e->bitmask == 0)
return 0;
- hlp = ubase - base + (char *)e + e->target_offset;
+ hlp = ubase + (((char *)e + e->target_offset) - base);
t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
ret = EBT_MATCH_ITERATE(e, ebt_make_matchname, base, ubase);
diff --git a/net/core/Makefile b/net/core/Makefile
index 119568077dab..73272d506e93 100644
--- a/net/core/Makefile
+++ b/net/core/Makefile
@@ -12,7 +12,6 @@ obj-y += dev.o ethtool.o dev_mcast.o dst.o netevent.o \
obj-$(CONFIG_XFRM) += flow.o
obj-$(CONFIG_SYSFS) += net-sysfs.o
-obj-$(CONFIG_NET_DIVERT) += dv.o
obj-$(CONFIG_NET_PKTGEN) += pktgen.o
obj-$(CONFIG_WIRELESS_EXT) += wireless.o
obj-$(CONFIG_NETPOLL) += netpoll.o
diff --git a/net/core/datagram.c b/net/core/datagram.c
index f558c61aecc7..797fdd4352ce 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -321,7 +321,7 @@ fault:
static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
u8 __user *to, int len,
- unsigned int *csump)
+ __wsum *csump)
{
int start = skb_headlen(skb);
int pos = 0;
@@ -350,7 +350,7 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
end = start + skb_shinfo(skb)->frags[i].size;
if ((copy = end - offset) > 0) {
- unsigned int csum2;
+ __wsum csum2;
int err = 0;
u8 *vaddr;
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
@@ -386,7 +386,7 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
end = start + list->len;
if ((copy = end - offset) > 0) {
- unsigned int csum2 = 0;
+ __wsum csum2 = 0;
if (copy > len)
copy = len;
if (skb_copy_and_csum_datagram(list,
@@ -411,11 +411,11 @@ fault:
return -EFAULT;
}
-unsigned int __skb_checksum_complete(struct sk_buff *skb)
+__sum16 __skb_checksum_complete(struct sk_buff *skb)
{
- unsigned int sum;
+ __sum16 sum;
- sum = (u16)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum));
+ sum = csum_fold(skb_checksum(skb, 0, skb->len, skb->csum));
if (likely(!sum)) {
if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE))
netdev_rx_csum_fault(skb->dev);
@@ -441,7 +441,7 @@ EXPORT_SYMBOL(__skb_checksum_complete);
int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb,
int hlen, struct iovec *iov)
{
- unsigned int csum;
+ __wsum csum;
int chunk = skb->len - hlen;
/* Skip filled elements.
@@ -460,7 +460,7 @@ int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb,
if (skb_copy_and_csum_datagram(skb, hlen, iov->iov_base,
chunk, &csum))
goto fault;
- if ((unsigned short)csum_fold(csum))
+ if (csum_fold(csum))
goto csum_error;
if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE))
netdev_rx_csum_fault(skb->dev);
diff --git a/net/core/dev.c b/net/core/dev.c
index 81c426adcd1e..59d058a3b504 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -98,7 +98,6 @@
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/if_bridge.h>
-#include <linux/divert.h>
#include <net/dst.h>
#include <net/pkt_sched.h>
#include <net/checksum.h>
@@ -1170,7 +1169,7 @@ EXPORT_SYMBOL(netif_device_attach);
*/
int skb_checksum_help(struct sk_buff *skb)
{
- unsigned int csum;
+ __wsum csum;
int ret = 0, offset = skb->h.raw - skb->data;
if (skb->ip_summed == CHECKSUM_COMPLETE)
@@ -1192,9 +1191,9 @@ int skb_checksum_help(struct sk_buff *skb)
offset = skb->tail - skb->h.raw;
BUG_ON(offset <= 0);
- BUG_ON(skb->csum + 2 > offset);
+ BUG_ON(skb->csum_offset + 2 > offset);
- *(u16*)(skb->h.raw + skb->csum) = csum_fold(csum);
+ *(__sum16*)(skb->h.raw + skb->csum_offset) = csum_fold(csum);
out_set_summed:
skb->ip_summed = CHECKSUM_NONE;
@@ -1216,7 +1215,7 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features)
{
struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
struct packet_type *ptype;
- int type = skb->protocol;
+ __be16 type = skb->protocol;
int err;
BUG_ON(skb_shinfo(skb)->frag_list);
@@ -1767,7 +1766,7 @@ int netif_receive_skb(struct sk_buff *skb)
struct packet_type *ptype, *pt_prev;
struct net_device *orig_dev;
int ret = NET_RX_DROP;
- unsigned short type;
+ __be16 type;
/* if we've gotten here through NAPI, check netpoll */
if (skb->dev->poll && netpoll_rx(skb))
@@ -1827,8 +1826,6 @@ int netif_receive_skb(struct sk_buff *skb)
ncls:
#endif
- handle_diverter(skb);
-
if (handle_bridge(&skb, &pt_prev, &ret, orig_dev))
goto out;
@@ -2898,10 +2895,6 @@ int register_netdevice(struct net_device *dev)
spin_lock_init(&dev->ingress_lock);
#endif
- ret = alloc_divert_blk(dev);
- if (ret)
- goto out;
-
dev->iflink = -1;
/* Init, if this function is available */
@@ -2910,13 +2903,13 @@ int register_netdevice(struct net_device *dev)
if (ret) {
if (ret > 0)
ret = -EIO;
- goto out_err;
+ goto out;
}
}
if (!dev_valid_name(dev->name)) {
ret = -EINVAL;
- goto out_err;
+ goto out;
}
dev->ifindex = dev_new_index();
@@ -2930,7 +2923,7 @@ int register_netdevice(struct net_device *dev)
= hlist_entry(p, struct net_device, name_hlist);
if (!strncmp(d->name, dev->name, IFNAMSIZ)) {
ret = -EEXIST;
- goto out_err;
+ goto out;
}
}
@@ -2974,7 +2967,7 @@ int register_netdevice(struct net_device *dev)
ret = netdev_register_sysfs(dev);
if (ret)
- goto out_err;
+ goto out;
dev->reg_state = NETREG_REGISTERED;
/*
@@ -3001,9 +2994,6 @@ int register_netdevice(struct net_device *dev)
out:
return ret;
-out_err:
- free_divert_blk(dev);
- goto out;
}
/**
@@ -3035,15 +3025,6 @@ int register_netdev(struct net_device *dev)
goto out;
}
- /*
- * Back compatibility hook. Kill this one in 2.5
- */
- if (dev->name[0] == 0 || dev->name[0] == ' ') {
- err = dev_alloc_name(dev, "eth%d");
- if (err < 0)
- goto out;
- }
-
err = register_netdevice(dev);
out:
rtnl_unlock();
@@ -3329,8 +3310,6 @@ int unregister_netdevice(struct net_device *dev)
/* Notifier chain MUST detach us from master device. */
BUG_TRAP(!dev->master);
- free_divert_blk(dev);
-
/* Finish processing unregister after unlock */
net_set_todo(dev);
diff --git a/net/core/dv.c b/net/core/dv.c
deleted file mode 100644
index 29ee77f15932..000000000000
--- a/net/core/dv.c
+++ /dev/null
@@ -1,546 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * Generic frame diversion
- *
- * Authors:
- * Benoit LOCHER: initial integration within the kernel with support for ethernet
- * Dave Miller: improvement on the code (correctness, performance and source files)
- *
- */
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/in.h>
-#include <linux/inet.h>
-#include <linux/ip.h>
-#include <linux/udp.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/capability.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <net/dst.h>
-#include <net/arp.h>
-#include <net/sock.h>
-#include <net/ipv6.h>
-#include <net/ip.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/checksum.h>
-#include <linux/divert.h>
-#include <linux/sockios.h>
-
-const char sysctl_divert_version[32]="0.46"; /* Current version */
-
-static int __init dv_init(void)
-{
- return 0;
-}
-module_init(dv_init);
-
-/*
- * Allocate a divert_blk for a device. This must be an ethernet nic.
- */
-int alloc_divert_blk(struct net_device *dev)
-{
- int alloc_size = (sizeof(struct divert_blk) + 3) & ~3;
-
- dev->divert = NULL;
- if (dev->type == ARPHRD_ETHER) {
- 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;
- }
- dev_hold(dev);
- }
-
- return 0;
-}
-
-/*
- * Free a divert_blk allocated by the above function, if it was
- * allocated on that device.
- */
-void free_divert_blk(struct net_device *dev)
-{
- if (dev->divert) {
- kfree(dev->divert);
- dev->divert=NULL;
- dev_put(dev);
- }
-}
-
-/*
- * Adds a tcp/udp (source or dest) port to an array
- */
-static int add_port(u16 ports[], u16 port)
-{
- int i;
-
- if (port == 0)
- return -EINVAL;
-
- /* Storing directly in network format for performance,
- * thanks Dave :)
- */
- port = htons(port);
-
- for (i = 0; i < MAX_DIVERT_PORTS; i++) {
- if (ports[i] == port)
- return -EALREADY;
- }
-
- for (i = 0; i < MAX_DIVERT_PORTS; i++) {
- if (ports[i] == 0) {
- ports[i] = port;
- return 0;
- }
- }
-
- return -ENOBUFS;
-}
-
-/*
- * Removes a port from an array tcp/udp (source or dest)
- */
-static int remove_port(u16 ports[], u16 port)
-{
- int i;
-
- if (port == 0)
- return -EINVAL;
-
- /* Storing directly in network format for performance,
- * thanks Dave !
- */
- port = htons(port);
-
- for (i = 0; i < MAX_DIVERT_PORTS; i++) {
- if (ports[i] == port) {
- ports[i] = 0;
- return 0;
- }
- }
-
- return -EINVAL;
-}
-
-/* Some basic sanity checks on the arguments passed to divert_ioctl() */
-static int check_args(struct divert_cf *div_cf, struct net_device **dev)
-{
- char devname[32];
- int ret;
-
- if (dev == NULL)
- return -EFAULT;
-
- /* GETVERSION: all other args are unused */
- if (div_cf->cmd == DIVCMD_GETVERSION)
- return 0;
-
- /* Network device index should reasonably be between 0 and 1000 :) */
- if (div_cf->dev_index < 0 || div_cf->dev_index > 1000)
- return -EINVAL;
-
- /* Let's try to find the ifname */
- sprintf(devname, "eth%d", div_cf->dev_index);
- *dev = dev_get_by_name(devname);
-
- /* dev should NOT be null */
- if (*dev == NULL)
- return -EINVAL;
-
- ret = 0;
-
- /* user issuing the ioctl must be a super one :) */
- if (!capable(CAP_SYS_ADMIN)) {
- ret = -EPERM;
- goto out;
- }
-
- /* Device must have a divert_blk member NOT null */
- if ((*dev)->divert == NULL)
- ret = -EINVAL;
-out:
- dev_put(*dev);
- return ret;
-}
-
-/*
- * control function of the diverter
- */
-#if 0
-#define DVDBG(a) \
- printk(KERN_DEBUG "divert_ioctl() line %d %s\n", __LINE__, (a))
-#else
-#define DVDBG(a)
-#endif
-
-int divert_ioctl(unsigned int cmd, struct divert_cf __user *arg)
-{
- struct divert_cf div_cf;
- struct divert_blk *div_blk;
- struct net_device *dev;
- int ret;
-
- switch (cmd) {
- case SIOCGIFDIVERT:
- DVDBG("SIOCGIFDIVERT, copy_from_user");
- if (copy_from_user(&div_cf, arg, sizeof(struct divert_cf)))
- return -EFAULT;
- DVDBG("before check_args");
- ret = check_args(&div_cf, &dev);
- if (ret)
- return ret;
- DVDBG("after checkargs");
- div_blk = dev->divert;
-
- DVDBG("befre switch()");
- switch (div_cf.cmd) {
- case DIVCMD_GETSTATUS:
- /* Now, just give the user the raw divert block
- * for him to play with :)
- */
- if (copy_to_user(div_cf.arg1.ptr, dev->divert,
- sizeof(struct divert_blk)))
- return -EFAULT;
- break;
-
- case DIVCMD_GETVERSION:
- DVDBG("GETVERSION: checking ptr");
- if (div_cf.arg1.ptr == NULL)
- return -EINVAL;
- DVDBG("GETVERSION: copying data to userland");
- if (copy_to_user(div_cf.arg1.ptr,
- sysctl_divert_version, 32))
- return -EFAULT;
- DVDBG("GETVERSION: data copied");
- break;
-
- default:
- return -EINVAL;
- }
-
- break;
-
- case SIOCSIFDIVERT:
- if (copy_from_user(&div_cf, arg, sizeof(struct divert_cf)))
- return -EFAULT;
-
- ret = check_args(&div_cf, &dev);
- if (ret)
- return ret;
-
- div_blk = dev->divert;
-
- switch(div_cf.cmd) {
- case DIVCMD_RESET:
- div_blk->divert = 0;
- div_blk->protos = DIVERT_PROTO_NONE;
- memset(div_blk->tcp_dst, 0,
- MAX_DIVERT_PORTS * sizeof(u16));
- memset(div_blk->tcp_src, 0,
- MAX_DIVERT_PORTS * sizeof(u16));
- memset(div_blk->udp_dst, 0,
- MAX_DIVERT_PORTS * sizeof(u16));
- memset(div_blk->udp_src, 0,
- MAX_DIVERT_PORTS * sizeof(u16));
- return 0;
-
- case DIVCMD_DIVERT:
- switch(div_cf.arg1.int32) {
- case DIVARG1_ENABLE:
- if (div_blk->divert)
- return -EALREADY;
- div_blk->divert = 1;
- break;
-
- case DIVARG1_DISABLE:
- if (!div_blk->divert)
- return -EALREADY;
- div_blk->divert = 0;
- break;
-
- default:
- return -EINVAL;
- }
-
- break;
-
- case DIVCMD_IP:
- switch(div_cf.arg1.int32) {
- case DIVARG1_ENABLE:
- if (div_blk->protos & DIVERT_PROTO_IP)
- return -EALREADY;
- div_blk->protos |= DIVERT_PROTO_IP;
- break;
-
- case DIVARG1_DISABLE:
- if (!(div_blk->protos & DIVERT_PROTO_IP))
- return -EALREADY;
- div_blk->protos &= ~DIVERT_PROTO_IP;
- break;
-
- default:
- return -EINVAL;
- }
-
- break;
-
- case DIVCMD_TCP:
- switch(div_cf.arg1.int32) {
- case DIVARG1_ENABLE:
- if (div_blk->protos & DIVERT_PROTO_TCP)
- return -EALREADY;
- div_blk->protos |= DIVERT_PROTO_TCP;
- break;
-
- case DIVARG1_DISABLE:
- if (!(div_blk->protos & DIVERT_PROTO_TCP))
- return -EALREADY;
- div_blk->protos &= ~DIVERT_PROTO_TCP;
- break;
-
- default:
- return -EINVAL;
- }
-
- break;
-
- case DIVCMD_TCPDST:
- switch(div_cf.arg1.int32) {
- case DIVARG1_ADD:
- return add_port(div_blk->tcp_dst,
- div_cf.arg2.uint16);
-
- case DIVARG1_REMOVE:
- return remove_port(div_blk->tcp_dst,
- div_cf.arg2.uint16);
-
- default:
- return -EINVAL;
- }
-
- break;
-
- case DIVCMD_TCPSRC:
- switch(div_cf.arg1.int32) {
- case DIVARG1_ADD:
- return add_port(div_blk->tcp_src,
- div_cf.arg2.uint16);
-
- case DIVARG1_REMOVE:
- return remove_port(div_blk->tcp_src,
- div_cf.arg2.uint16);
-
- default:
- return -EINVAL;
- }
-
- break;
-
- case DIVCMD_UDP:
- switch(div_cf.arg1.int32) {
- case DIVARG1_ENABLE:
- if (div_blk->protos & DIVERT_PROTO_UDP)
- return -EALREADY;
- div_blk->protos |= DIVERT_PROTO_UDP;
- break;
-
- case DIVARG1_DISABLE:
- if (!(div_blk->protos & DIVERT_PROTO_UDP))
- return -EALREADY;
- div_blk->protos &= ~DIVERT_PROTO_UDP;
- break;
-
- default:
- return -EINVAL;
- }
-
- break;
-
- case DIVCMD_UDPDST:
- switch(div_cf.arg1.int32) {
- case DIVARG1_ADD:
- return add_port(div_blk->udp_dst,
- div_cf.arg2.uint16);
-
- case DIVARG1_REMOVE:
- return remove_port(div_blk->udp_dst,
- div_cf.arg2.uint16);
-
- default:
- return -EINVAL;
- }
-
- break;
-
- case DIVCMD_UDPSRC:
- switch(div_cf.arg1.int32) {
- case DIVARG1_ADD:
- return add_port(div_blk->udp_src,
- div_cf.arg2.uint16);
-
- case DIVARG1_REMOVE:
- return remove_port(div_blk->udp_src,
- div_cf.arg2.uint16);
-
- default:
- return -EINVAL;
- }
-
- break;
-
- case DIVCMD_ICMP:
- switch(div_cf.arg1.int32) {
- case DIVARG1_ENABLE:
- if (div_blk->protos & DIVERT_PROTO_ICMP)
- return -EALREADY;
- div_blk->protos |= DIVERT_PROTO_ICMP;
- break;
-
- case DIVARG1_DISABLE:
- if (!(div_blk->protos & DIVERT_PROTO_ICMP))
- return -EALREADY;
- div_blk->protos &= ~DIVERT_PROTO_ICMP;
- break;
-
- default:
- return -EINVAL;
- }
-
- break;
-
- default:
- return -EINVAL;
- }
-
- break;
-
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-
-/*
- * Check if packet should have its dest mac address set to the box itself
- * for diversion
- */
-
-#define ETH_DIVERT_FRAME(skb) \
- memcpy(eth_hdr(skb), skb->dev->dev_addr, ETH_ALEN); \
- skb->pkt_type=PACKET_HOST
-
-void divert_frame(struct sk_buff *skb)
-{
- struct ethhdr *eth = eth_hdr(skb);
- struct iphdr *iph;
- struct tcphdr *tcph;
- struct udphdr *udph;
- struct divert_blk *divert = skb->dev->divert;
- int i, src, dst;
- unsigned char *skb_data_end = skb->data + skb->len;
-
- /* Packet is already aimed at us, return */
- if (!compare_ether_addr(eth->h_dest, skb->dev->dev_addr))
- return;
-
- /* proto is not IP, do nothing */
- if (eth->h_proto != htons(ETH_P_IP))
- return;
-
- /* Divert all IP frames ? */
- if (divert->protos & DIVERT_PROTO_IP) {
- ETH_DIVERT_FRAME(skb);
- return;
- }
-
- /* Check for possible (maliciously) malformed IP frame (thanks Dave) */
- iph = (struct iphdr *) skb->data;
- if (((iph->ihl<<2)+(unsigned char*)(iph)) >= skb_data_end) {
- printk(KERN_INFO "divert: malformed IP packet !\n");
- return;
- }
-
- switch (iph->protocol) {
- /* Divert all ICMP frames ? */
- case IPPROTO_ICMP:
- if (divert->protos & DIVERT_PROTO_ICMP) {
- ETH_DIVERT_FRAME(skb);
- return;
- }
- break;
-
- /* Divert all TCP frames ? */
- case IPPROTO_TCP:
- if (divert->protos & DIVERT_PROTO_TCP) {
- ETH_DIVERT_FRAME(skb);
- return;
- }
-
- /* Check for possible (maliciously) malformed IP
- * frame (thanx Dave)
- */
- tcph = (struct tcphdr *)
- (((unsigned char *)iph) + (iph->ihl<<2));
- if (((unsigned char *)(tcph+1)) >= skb_data_end) {
- printk(KERN_INFO "divert: malformed TCP packet !\n");
- return;
- }
-
- /* Divert some tcp dst/src ports only ?*/
- for (i = 0; i < MAX_DIVERT_PORTS; i++) {
- dst = divert->tcp_dst[i];
- src = divert->tcp_src[i];
- if ((dst && dst == tcph->dest) ||
- (src && src == tcph->source)) {
- ETH_DIVERT_FRAME(skb);
- return;
- }
- }
- break;
-
- /* Divert all UDP frames ? */
- case IPPROTO_UDP:
- if (divert->protos & DIVERT_PROTO_UDP) {
- ETH_DIVERT_FRAME(skb);
- return;
- }
-
- /* Check for possible (maliciously) malformed IP
- * packet (thanks Dave)
- */
- udph = (struct udphdr *)
- (((unsigned char *)iph) + (iph->ihl<<2));
- if (((unsigned char *)(udph+1)) >= skb_data_end) {
- printk(KERN_INFO
- "divert: malformed UDP packet !\n");
- return;
- }
-
- /* Divert some udp dst/src ports only ? */
- for (i = 0; i < MAX_DIVERT_PORTS; i++) {
- dst = divert->udp_dst[i];
- src = divert->udp_src[i];
- if ((dst && dst == udph->dest) ||
- (src && src == udph->source)) {
- ETH_DIVERT_FRAME(skb);
- return;
- }
- }
- break;
- }
-}
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 6b0e63cacd93..1df6cd4568d3 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -107,6 +107,22 @@ out:
EXPORT_SYMBOL_GPL(fib_rules_unregister);
+static int fib_rule_match(struct fib_rule *rule, struct fib_rules_ops *ops,
+ struct flowi *fl, int flags)
+{
+ int ret = 0;
+
+ if (rule->ifindex && (rule->ifindex != fl->iif))
+ goto out;
+
+ if ((rule->mark ^ fl->mark) & rule->mark_mask)
+ goto out;
+
+ ret = ops->match(rule, fl, flags);
+out:
+ return (rule->flags & FIB_RULE_INVERT) ? !ret : ret;
+}
+
int fib_rules_lookup(struct fib_rules_ops *ops, struct flowi *fl,
int flags, struct fib_lookup_arg *arg)
{
@@ -116,10 +132,7 @@ int fib_rules_lookup(struct fib_rules_ops *ops, struct flowi *fl,
rcu_read_lock();
list_for_each_entry_rcu(rule, ops->rules_list, list) {
- if (rule->ifindex && (rule->ifindex != fl->iif))
- continue;
-
- if (!ops->match(rule, fl, flags))
+ if (!fib_rule_match(rule, ops, fl, flags))
continue;
err = ops->action(rule, fl, flags, arg);
@@ -179,6 +192,18 @@ int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
rule->ifindex = dev->ifindex;
}
+ if (tb[FRA_FWMARK]) {
+ rule->mark = nla_get_u32(tb[FRA_FWMARK]);
+ if (rule->mark)
+ /* compatibility: if the mark value is non-zero all bits
+ * are compared unless a mask is explicitly specified.
+ */
+ rule->mark_mask = 0xFFFFFFFF;
+ }
+
+ if (tb[FRA_FWMASK])
+ rule->mark_mask = nla_get_u32(tb[FRA_FWMASK]);
+
rule->action = frh->action;
rule->flags = frh->flags;
rule->table = frh_get_table(frh, tb);
@@ -250,6 +275,14 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
nla_strcmp(tb[FRA_IFNAME], rule->ifname))
continue;
+ if (tb[FRA_FWMARK] &&
+ (rule->mark != nla_get_u32(tb[FRA_FWMARK])))
+ continue;
+
+ if (tb[FRA_FWMASK] &&
+ (rule->mark_mask != nla_get_u32(tb[FRA_FWMASK])))
+ continue;
+
if (!ops->compare(rule, frh, tb))
continue;
@@ -273,6 +306,22 @@ errout:
return err;
}
+static inline size_t fib_rule_nlmsg_size(struct fib_rules_ops *ops,
+ struct fib_rule *rule)
+{
+ size_t payload = NLMSG_ALIGN(sizeof(struct fib_rule_hdr))
+ + nla_total_size(IFNAMSIZ) /* FRA_IFNAME */
+ + nla_total_size(4) /* FRA_PRIORITY */
+ + nla_total_size(4) /* FRA_TABLE */
+ + nla_total_size(4) /* FRA_FWMARK */
+ + nla_total_size(4); /* FRA_FWMASK */
+
+ if (ops->nlmsg_payload)
+ payload += ops->nlmsg_payload(rule);
+
+ return payload;
+}
+
static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
u32 pid, u32 seq, int type, int flags,
struct fib_rules_ops *ops)
@@ -298,6 +347,12 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
if (rule->pref)
NLA_PUT_U32(skb, FRA_PRIORITY, rule->pref);
+ if (rule->mark)
+ NLA_PUT_U32(skb, FRA_FWMARK, rule->mark);
+
+ if (rule->mark_mask || rule->mark)
+ NLA_PUT_U32(skb, FRA_FWMASK, rule->mark_mask);
+
if (ops->fill(rule, skb, nlh, frh) < 0)
goto nla_put_failure;
@@ -345,15 +400,13 @@ static void notify_rule_change(int event, struct fib_rule *rule,
struct sk_buff *skb;
int err = -ENOBUFS;
- skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+ skb = nlmsg_new(fib_rule_nlmsg_size(ops, rule), GFP_KERNEL);
if (skb == NULL)
goto errout;
err = fib_nl_fill_rule(skb, rule, pid, nlh->nlmsg_seq, event, 0, ops);
- if (err < 0) {
- kfree_skb(skb);
- goto errout;
- }
+ /* failure implies BUG in fib_rule_nlmsg_size() */
+ BUG_ON(err < 0);
err = rtnl_notify(skb, pid, ops->nlgroup, nlh, GFP_KERNEL);
errout:
diff --git a/net/core/filter.c b/net/core/filter.c
index 6732782a5a40..0df843b667f4 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -178,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(get_unaligned((u32 *)ptr));
+ A = ntohl(get_unaligned((__be32 *)ptr));
continue;
}
break;
@@ -187,7 +187,7 @@ load_w:
load_h:
ptr = load_pointer(skb, k, 2, &tmp);
if (ptr != NULL) {
- A = ntohs(get_unaligned((u16 *)ptr));
+ A = ntohs(get_unaligned((__be16 *)ptr));
continue;
}
break;
@@ -261,7 +261,7 @@ load_b:
*/
switch (k-SKF_AD_OFF) {
case SKF_AD_PROTOCOL:
- A = htons(skb->protocol);
+ A = ntohs(skb->protocol);
continue;
case SKF_AD_PKTTYPE:
A = skb->pkt_type;
diff --git a/net/core/iovec.c b/net/core/iovec.c
index 65e4b56fbc77..04b249c40b5b 100644
--- a/net/core/iovec.c
+++ b/net/core/iovec.c
@@ -158,9 +158,9 @@ int memcpy_fromiovecend(unsigned char *kdata, struct iovec *iov, int offset,
* call to this function will be unaligned also.
*/
int csum_partial_copy_fromiovecend(unsigned char *kdata, struct iovec *iov,
- int offset, unsigned int len, int *csump)
+ int offset, unsigned int len, __wsum *csump)
{
- int csum = *csump;
+ __wsum csum = *csump;
int partial_cnt = 0, err = 0;
/* Skip over the finished iovecs */
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index b4b478353b27..ba509a4a8e92 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -1266,10 +1266,9 @@ void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
struct neigh_table *tbl)
{
- struct neigh_parms *p = kmalloc(sizeof(*p), GFP_KERNEL);
+ struct neigh_parms *p = kmemdup(&tbl->parms, sizeof(*p), GFP_KERNEL);
if (p) {
- memcpy(p, &tbl->parms, sizeof(*p));
p->tbl = tbl;
atomic_set(&p->refcnt, 1);
INIT_RCU_HEAD(&p->rcu_head);
@@ -2410,20 +2409,27 @@ static struct file_operations neigh_stat_seq_fops = {
#endif /* CONFIG_PROC_FS */
#ifdef CONFIG_ARPD
+static inline size_t neigh_nlmsg_size(void)
+{
+ return NLMSG_ALIGN(sizeof(struct ndmsg))
+ + nla_total_size(MAX_ADDR_LEN) /* NDA_DST */
+ + nla_total_size(MAX_ADDR_LEN) /* NDA_LLADDR */
+ + nla_total_size(sizeof(struct nda_cacheinfo))
+ + nla_total_size(4); /* NDA_PROBES */
+}
+
static void __neigh_notify(struct neighbour *n, int type, int flags)
{
struct sk_buff *skb;
int err = -ENOBUFS;
- skb = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC);
+ skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC);
if (skb == NULL)
goto errout;
err = neigh_fill_info(skb, n, 0, 0, type, flags);
- if (err < 0) {
- kfree_skb(skb);
- goto errout;
- }
+ /* failure implies BUG in neigh_nlmsg_size() */
+ BUG_ON(err < 0);
err = rtnl_notify(skb, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
errout:
@@ -2618,14 +2624,14 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
int p_id, int pdev_id, char *p_name,
proc_handler *handler, ctl_handler *strategy)
{
- struct neigh_sysctl_table *t = kmalloc(sizeof(*t), GFP_KERNEL);
+ struct neigh_sysctl_table *t = kmemdup(&neigh_sysctl_template,
+ sizeof(*t), GFP_KERNEL);
const char *dev_name_source = NULL;
char *dev_name = NULL;
int err = 0;
if (!t)
return -ENOBUFS;
- memcpy(t, &neigh_sysctl_template, sizeof(*t));
t->neigh_vars[0].data = &p->mcast_probes;
t->neigh_vars[1].data = &p->ucast_probes;
t->neigh_vars[2].data = &p->app_probes;
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 63f24c914ddb..b3c559b9ac35 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -34,18 +34,12 @@
#define MAX_UDP_CHUNK 1460
#define MAX_SKBS 32
#define MAX_QUEUE_DEPTH (MAX_SKBS / 2)
-#define MAX_RETRIES 20000
-static DEFINE_SPINLOCK(skb_list_lock);
-static int nr_skbs;
-static struct sk_buff *skbs;
-
-static DEFINE_SPINLOCK(queue_lock);
-static int queue_depth;
-static struct sk_buff *queue_head, *queue_tail;
+static struct sk_buff_head skb_pool;
static atomic_t trapped;
+#define USEC_PER_POLL 50
#define NETPOLL_RX_ENABLED 1
#define NETPOLL_RX_DROP 2
@@ -58,52 +52,34 @@ static void arp_reply(struct sk_buff *skb);
static void queue_process(struct work_struct *work)
{
- unsigned long flags;
+ struct netpoll_info *npinfo =
+ container_of(work, struct netpoll_info, tx_work.work);
struct sk_buff *skb;
- while (queue_head) {
- spin_lock_irqsave(&queue_lock, flags);
-
- skb = queue_head;
- queue_head = skb->next;
- if (skb == queue_tail)
- queue_head = NULL;
-
- queue_depth--;
-
- spin_unlock_irqrestore(&queue_lock, flags);
-
- dev_queue_xmit(skb);
- }
-}
+ while ((skb = skb_dequeue(&npinfo->txq))) {
+ struct net_device *dev = skb->dev;
-static DECLARE_WORK(send_queue, queue_process);
+ if (!netif_device_present(dev) || !netif_running(dev)) {
+ __kfree_skb(skb);
+ continue;
+ }
-void netpoll_queue(struct sk_buff *skb)
-{
- unsigned long flags;
+ netif_tx_lock_bh(dev);
+ if (netif_queue_stopped(dev) ||
+ dev->hard_start_xmit(skb, dev) != NETDEV_TX_OK) {
+ skb_queue_head(&npinfo->txq, skb);
+ netif_tx_unlock_bh(dev);
- if (queue_depth == MAX_QUEUE_DEPTH) {
- __kfree_skb(skb);
- return;
+ schedule_delayed_work(&npinfo->tx_work, HZ/10);
+ return;
+ }
}
-
- spin_lock_irqsave(&queue_lock, flags);
- if (!queue_head)
- queue_head = skb;
- else
- queue_tail->next = skb;
- queue_tail = skb;
- queue_depth++;
- spin_unlock_irqrestore(&queue_lock, flags);
-
- schedule_work(&send_queue);
}
-static int checksum_udp(struct sk_buff *skb, struct udphdr *uh,
- unsigned short ulen, u32 saddr, u32 daddr)
+static __sum16 checksum_udp(struct sk_buff *skb, struct udphdr *uh,
+ unsigned short ulen, __be32 saddr, __be32 daddr)
{
- unsigned int psum;
+ __wsum psum;
if (uh->check == 0 || skb->ip_summed == CHECKSUM_UNNECESSARY)
return 0;
@@ -111,7 +87,7 @@ static int checksum_udp(struct sk_buff *skb, struct udphdr *uh,
psum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0);
if (skb->ip_summed == CHECKSUM_COMPLETE &&
- !(u16)csum_fold(csum_add(psum, skb->csum)))
+ !csum_fold(csum_add(psum, skb->csum)))
return 0;
skb->csum = psum;
@@ -167,12 +143,11 @@ static void service_arp_queue(struct netpoll_info *npi)
arp_reply(skb);
skb = skb_dequeue(&npi->arp_tx);
}
- return;
}
void netpoll_poll(struct netpoll *np)
{
- if(!np->dev || !netif_running(np->dev) || !np->dev->poll_controller)
+ if (!np->dev || !netif_running(np->dev) || !np->dev->poll_controller)
return;
/* Process pending work on NIC */
@@ -190,17 +165,15 @@ static void refill_skbs(void)
struct sk_buff *skb;
unsigned long flags;
- spin_lock_irqsave(&skb_list_lock, flags);
- while (nr_skbs < MAX_SKBS) {
+ spin_lock_irqsave(&skb_pool.lock, flags);
+ while (skb_pool.qlen < MAX_SKBS) {
skb = alloc_skb(MAX_SKB_SIZE, GFP_ATOMIC);
if (!skb)
break;
- skb->next = skbs;
- skbs = skb;
- nr_skbs++;
+ __skb_queue_tail(&skb_pool, skb);
}
- spin_unlock_irqrestore(&skb_list_lock, flags);
+ spin_unlock_irqrestore(&skb_pool.lock, flags);
}
static void zap_completion_queue(void)
@@ -219,7 +192,7 @@ static void zap_completion_queue(void)
while (clist != NULL) {
struct sk_buff *skb = clist;
clist = clist->next;
- if(skb->destructor)
+ if (skb->destructor)
dev_kfree_skb_any(skb); /* put this one back */
else
__kfree_skb(skb);
@@ -229,38 +202,25 @@ static void zap_completion_queue(void)
put_cpu_var(softnet_data);
}
-static struct sk_buff * find_skb(struct netpoll *np, int len, int reserve)
+static struct sk_buff *find_skb(struct netpoll *np, int len, int reserve)
{
- int once = 1, count = 0;
- unsigned long flags;
- struct sk_buff *skb = NULL;
+ int count = 0;
+ struct sk_buff *skb;
zap_completion_queue();
+ refill_skbs();
repeat:
- if (nr_skbs < MAX_SKBS)
- refill_skbs();
skb = alloc_skb(len, GFP_ATOMIC);
+ if (!skb)
+ skb = skb_dequeue(&skb_pool);
if (!skb) {
- spin_lock_irqsave(&skb_list_lock, flags);
- skb = skbs;
- if (skb) {
- skbs = skb->next;
- skb->next = NULL;
- nr_skbs--;
+ if (++count < 10) {
+ netpoll_poll(np);
+ goto repeat;
}
- spin_unlock_irqrestore(&skb_list_lock, flags);
- }
-
- if(!skb) {
- count++;
- if (once && (count == 1000000)) {
- printk("out of netpoll skbs!\n");
- once = 0;
- }
- netpoll_poll(np);
- goto repeat;
+ return NULL;
}
atomic_set(&skb->users, 1);
@@ -270,50 +230,40 @@ repeat:
static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
{
- int status;
- struct netpoll_info *npinfo;
-
- if (!np || !np->dev || !netif_running(np->dev)) {
- __kfree_skb(skb);
- return;
- }
-
- npinfo = np->dev->npinfo;
-
- /* avoid recursion */
- if (npinfo->poll_owner == smp_processor_id() ||
- np->dev->xmit_lock_owner == smp_processor_id()) {
- if (np->drop)
- np->drop(skb);
- else
- __kfree_skb(skb);
- return;
- }
-
- do {
- npinfo->tries--;
- netif_tx_lock(np->dev);
+ int status = NETDEV_TX_BUSY;
+ unsigned long tries;
+ struct net_device *dev = np->dev;
+ struct netpoll_info *npinfo = np->dev->npinfo;
+
+ if (!npinfo || !netif_running(dev) || !netif_device_present(dev)) {
+ __kfree_skb(skb);
+ return;
+ }
+
+ /* don't get messages out of order, and no recursion */
+ if (skb_queue_len(&npinfo->txq) == 0 &&
+ npinfo->poll_owner != smp_processor_id() &&
+ netif_tx_trylock(dev)) {
+ /* try until next clock tick */
+ for (tries = jiffies_to_usecs(1)/USEC_PER_POLL; tries > 0; --tries) {
+ if (!netif_queue_stopped(dev))
+ status = dev->hard_start_xmit(skb, dev);
- /*
- * network drivers do not expect to be called if the queue is
- * stopped.
- */
- status = NETDEV_TX_BUSY;
- if (!netif_queue_stopped(np->dev))
- status = np->dev->hard_start_xmit(skb, np->dev);
+ if (status == NETDEV_TX_OK)
+ break;
- netif_tx_unlock(np->dev);
+ /* tickle device maybe there is some cleanup */
+ netpoll_poll(np);
- /* success */
- if(!status) {
- npinfo->tries = MAX_RETRIES; /* reset */
- return;
+ udelay(USEC_PER_POLL);
}
+ netif_tx_unlock(dev);
+ }
- /* transmit busy */
- netpoll_poll(np);
- udelay(50);
- } while (npinfo->tries > 0);
+ if (status != NETDEV_TX_OK) {
+ skb_queue_tail(&npinfo->txq, skb);
+ schedule_delayed_work(&npinfo->tx_work,0);
+ }
}
void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
@@ -345,7 +295,7 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
udp_len, IPPROTO_UDP,
csum_partial((unsigned char *)udph, udp_len, 0));
if (udph->check == 0)
- udph->check = -1;
+ udph->check = CSUM_MANGLED_0;
skb->nh.iph = iph = (struct iphdr *)skb_push(skb, sizeof(*iph));
@@ -379,7 +329,7 @@ static void arp_reply(struct sk_buff *skb)
struct arphdr *arp;
unsigned char *arp_ptr;
int size, type = ARPOP_REPLY, ptype = ETH_P_ARP;
- u32 sip, tip;
+ __be32 sip, tip;
struct sk_buff *send_skb;
struct netpoll *np = NULL;
@@ -431,8 +381,8 @@ static void arp_reply(struct sk_buff *skb)
if (np->dev->hard_header &&
np->dev->hard_header(send_skb, skb->dev, ptype,
- np->remote_mac, np->local_mac,
- send_skb->len) < 0) {
+ np->remote_mac, np->local_mac,
+ send_skb->len) < 0) {
kfree_skb(send_skb);
return;
}
@@ -470,7 +420,6 @@ int __netpoll_rx(struct sk_buff *skb)
struct netpoll_info *npi = skb->dev->npinfo;
struct netpoll *np = npi->rx_np;
-
if (!np)
goto out;
if (skb->dev->type != ARPHRD_ETHER)
@@ -543,47 +492,47 @@ int netpoll_parse_options(struct netpoll *np, char *opt)
{
char *cur=opt, *delim;
- if(*cur != '@') {
+ if (*cur != '@') {
if ((delim = strchr(cur, '@')) == NULL)
goto parse_failed;
- *delim=0;
- np->local_port=simple_strtol(cur, NULL, 10);
- cur=delim;
+ *delim = 0;
+ np->local_port = simple_strtol(cur, NULL, 10);
+ cur = delim;
}
cur++;
printk(KERN_INFO "%s: local port %d\n", np->name, np->local_port);
- if(*cur != '/') {
+ if (*cur != '/') {
if ((delim = strchr(cur, '/')) == NULL)
goto parse_failed;
- *delim=0;
- np->local_ip=ntohl(in_aton(cur));
- cur=delim;
+ *delim = 0;
+ np->local_ip = ntohl(in_aton(cur));
+ cur = delim;
printk(KERN_INFO "%s: local IP %d.%d.%d.%d\n",
np->name, HIPQUAD(np->local_ip));
}
cur++;
- if ( *cur != ',') {
+ if (*cur != ',') {
/* parse out dev name */
if ((delim = strchr(cur, ',')) == NULL)
goto parse_failed;
- *delim=0;
+ *delim = 0;
strlcpy(np->dev_name, cur, sizeof(np->dev_name));
- cur=delim;
+ cur = delim;
}
cur++;
printk(KERN_INFO "%s: interface %s\n", np->name, np->dev_name);
- if ( *cur != '@' ) {
+ if (*cur != '@') {
/* dst port */
if ((delim = strchr(cur, '@')) == NULL)
goto parse_failed;
- *delim=0;
- np->remote_port=simple_strtol(cur, NULL, 10);
- cur=delim;
+ *delim = 0;
+ np->remote_port = simple_strtol(cur, NULL, 10);
+ cur = delim;
}
cur++;
printk(KERN_INFO "%s: remote port %d\n", np->name, np->remote_port);
@@ -591,42 +540,41 @@ int netpoll_parse_options(struct netpoll *np, char *opt)
/* dst ip */
if ((delim = strchr(cur, '/')) == NULL)
goto parse_failed;
- *delim=0;
- np->remote_ip=ntohl(in_aton(cur));
- cur=delim+1;
+ *delim = 0;
+ np->remote_ip = ntohl(in_aton(cur));
+ cur = delim + 1;
printk(KERN_INFO "%s: remote IP %d.%d.%d.%d\n",
- np->name, HIPQUAD(np->remote_ip));
+ np->name, HIPQUAD(np->remote_ip));
- if( *cur != 0 )
- {
+ if (*cur != 0) {
/* MAC address */
if ((delim = strchr(cur, ':')) == NULL)
goto parse_failed;
- *delim=0;
- np->remote_mac[0]=simple_strtol(cur, NULL, 16);
- cur=delim+1;
+ *delim = 0;
+ np->remote_mac[0] = simple_strtol(cur, NULL, 16);
+ cur = delim + 1;
if ((delim = strchr(cur, ':')) == NULL)
goto parse_failed;
- *delim=0;
- np->remote_mac[1]=simple_strtol(cur, NULL, 16);
- cur=delim+1;
+ *delim = 0;
+ np->remote_mac[1] = simple_strtol(cur, NULL, 16);
+ cur = delim + 1;
if ((delim = strchr(cur, ':')) == NULL)
goto parse_failed;
- *delim=0;
- np->remote_mac[2]=simple_strtol(cur, NULL, 16);
- cur=delim+1;
+ *delim = 0;
+ np->remote_mac[2] = simple_strtol(cur, NULL, 16);
+ cur = delim + 1;
if ((delim = strchr(cur, ':')) == NULL)
goto parse_failed;
- *delim=0;
- np->remote_mac[3]=simple_strtol(cur, NULL, 16);
- cur=delim+1;
+ *delim = 0;
+ np->remote_mac[3] = simple_strtol(cur, NULL, 16);
+ cur = delim + 1;
if ((delim = strchr(cur, ':')) == NULL)
goto parse_failed;
- *delim=0;
- np->remote_mac[4]=simple_strtol(cur, NULL, 16);
- cur=delim+1;
- np->remote_mac[5]=simple_strtol(cur, NULL, 16);
+ *delim = 0;
+ np->remote_mac[4] = simple_strtol(cur, NULL, 16);
+ cur = delim + 1;
+ np->remote_mac[5] = simple_strtol(cur, NULL, 16);
}
printk(KERN_INFO "%s: remote ethernet address "
@@ -653,34 +601,44 @@ int netpoll_setup(struct netpoll *np)
struct in_device *in_dev;
struct netpoll_info *npinfo;
unsigned long flags;
+ int err;
if (np->dev_name)
ndev = dev_get_by_name(np->dev_name);
if (!ndev) {
printk(KERN_ERR "%s: %s doesn't exist, aborting.\n",
np->name, np->dev_name);
- return -1;
+ return -ENODEV;
}
np->dev = ndev;
if (!ndev->npinfo) {
npinfo = kmalloc(sizeof(*npinfo), GFP_KERNEL);
- if (!npinfo)
+ if (!npinfo) {
+ err = -ENOMEM;
goto release;
+ }
npinfo->rx_flags = 0;
npinfo->rx_np = NULL;
spin_lock_init(&npinfo->poll_lock);
npinfo->poll_owner = -1;
- npinfo->tries = MAX_RETRIES;
+
spin_lock_init(&npinfo->rx_lock);
skb_queue_head_init(&npinfo->arp_tx);
- } else
+ skb_queue_head_init(&npinfo->txq);
+ INIT_DELAYED_WORK(&npinfo->tx_work, queue_process);
+
+ atomic_set(&npinfo->refcnt, 1);
+ } else {
npinfo = ndev->npinfo;
+ atomic_inc(&npinfo->refcnt);
+ }
if (!ndev->poll_controller) {
printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n",
np->name, np->dev_name);
+ err = -ENOTSUPP;
goto release;
}
@@ -691,13 +649,14 @@ int netpoll_setup(struct netpoll *np)
np->name, np->dev_name);
rtnl_lock();
- if (dev_change_flags(ndev, ndev->flags | IFF_UP) < 0) {
+ err = dev_open(ndev);
+ rtnl_unlock();
+
+ if (err) {
printk(KERN_ERR "%s: failed to open %s\n",
- np->name, np->dev_name);
- rtnl_unlock();
+ np->name, ndev->name);
goto release;
}
- rtnl_unlock();
atleast = jiffies + HZ/10;
atmost = jiffies + 4*HZ;
@@ -735,6 +694,7 @@ int netpoll_setup(struct netpoll *np)
rcu_read_unlock();
printk(KERN_ERR "%s: no IP address for %s, aborting\n",
np->name, np->dev_name);
+ err = -EDESTADDRREQ;
goto release;
}
@@ -767,9 +727,16 @@ int netpoll_setup(struct netpoll *np)
kfree(npinfo);
np->dev = NULL;
dev_put(ndev);
- return -1;
+ return err;
}
+static int __init netpoll_init(void)
+{
+ skb_queue_head_init(&skb_pool);
+ return 0;
+}
+core_initcall(netpoll_init);
+
void netpoll_cleanup(struct netpoll *np)
{
struct netpoll_info *npinfo;
@@ -777,12 +744,25 @@ void netpoll_cleanup(struct netpoll *np)
if (np->dev) {
npinfo = np->dev->npinfo;
- if (npinfo && npinfo->rx_np == np) {
- spin_lock_irqsave(&npinfo->rx_lock, flags);
- npinfo->rx_np = NULL;
- npinfo->rx_flags &= ~NETPOLL_RX_ENABLED;
- spin_unlock_irqrestore(&npinfo->rx_lock, flags);
+ if (npinfo) {
+ if (npinfo->rx_np == np) {
+ spin_lock_irqsave(&npinfo->rx_lock, flags);
+ npinfo->rx_np = NULL;
+ npinfo->rx_flags &= ~NETPOLL_RX_ENABLED;
+ spin_unlock_irqrestore(&npinfo->rx_lock, flags);
+ }
+
+ np->dev->npinfo = NULL;
+ if (atomic_dec_and_test(&npinfo->refcnt)) {
+ skb_queue_purge(&npinfo->arp_tx);
+ skb_queue_purge(&npinfo->txq);
+ cancel_rearming_delayed_work(&npinfo->tx_work);
+ flush_scheduled_work();
+
+ kfree(npinfo);
+ }
}
+
dev_put(np->dev);
}
@@ -809,4 +789,3 @@ EXPORT_SYMBOL(netpoll_setup);
EXPORT_SYMBOL(netpoll_cleanup);
EXPORT_SYMBOL(netpoll_send_udp);
EXPORT_SYMBOL(netpoll_poll);
-EXPORT_SYMBOL(netpoll_queue);
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 733d86d0a4fb..1897a3a385d8 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -207,7 +207,7 @@ static struct proc_dir_entry *pg_proc_dir = NULL;
#define SVLAN_TAG_SIZE(x) ((x)->svlan_id == 0xffff ? 0 : 4)
struct flow_state {
- __u32 cur_daddr;
+ __be32 cur_daddr;
int count;
};
@@ -282,10 +282,10 @@ struct pktgen_dev {
/* If we're doing ranges, random or incremental, then this
* defines the min/max for those ranges.
*/
- __u32 saddr_min; /* inclusive, source IP address */
- __u32 saddr_max; /* exclusive, source IP address */
- __u32 daddr_min; /* inclusive, dest IP address */
- __u32 daddr_max; /* exclusive, dest IP address */
+ __be32 saddr_min; /* inclusive, source IP address */
+ __be32 saddr_max; /* exclusive, source IP address */
+ __be32 daddr_min; /* inclusive, dest IP address */
+ __be32 daddr_max; /* exclusive, dest IP address */
__u16 udp_src_min; /* inclusive, source UDP port */
__u16 udp_src_max; /* exclusive, source UDP port */
@@ -317,8 +317,8 @@ struct pktgen_dev {
__u32 cur_dst_mac_offset;
__u32 cur_src_mac_offset;
- __u32 cur_saddr;
- __u32 cur_daddr;
+ __be32 cur_saddr;
+ __be32 cur_daddr;
__u16 cur_udp_dst;
__u16 cur_udp_src;
__u32 cur_pkt_size;
@@ -350,10 +350,10 @@ struct pktgen_dev {
};
struct pktgen_hdr {
- __u32 pgh_magic;
- __u32 seq_num;
- __u32 tv_sec;
- __u32 tv_usec;
+ __be32 pgh_magic;
+ __be32 seq_num;
+ __be32 tv_sec;
+ __be32 tv_usec;
};
struct pktgen_thread {
@@ -2160,7 +2160,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
for(i = 0; i < pkt_dev->nr_labels; i++)
if (pkt_dev->labels[i] & MPLS_STACK_BOTTOM)
pkt_dev->labels[i] = MPLS_STACK_BOTTOM |
- (pktgen_random() &
+ ((__force __be32)pktgen_random() &
htonl(0x000fffff));
}
@@ -2220,29 +2220,25 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
if (pkt_dev->cflows && pkt_dev->flows[flow].count != 0) {
pkt_dev->cur_daddr = pkt_dev->flows[flow].cur_daddr;
} else {
-
- if ((imn = ntohl(pkt_dev->daddr_min)) < (imx =
- ntohl(pkt_dev->
- daddr_max)))
- {
+ imn = ntohl(pkt_dev->daddr_min);
+ imx = ntohl(pkt_dev->daddr_max);
+ if (imn < imx) {
__u32 t;
+ __be32 s;
if (pkt_dev->flags & F_IPDST_RND) {
- t = ((pktgen_random() % (imx - imn)) +
- imn);
- t = htonl(t);
+ t = pktgen_random() % (imx - imn) + imn;
+ s = htonl(t);
- while (LOOPBACK(t) || MULTICAST(t)
- || BADCLASS(t) || ZERONET(t)
- || LOCAL_MCAST(t)) {
- t = ((pktgen_random() %
- (imx - imn)) + imn);
- t = htonl(t);
+ while (LOOPBACK(s) || MULTICAST(s)
+ || BADCLASS(s) || ZERONET(s)
+ || LOCAL_MCAST(s)) {
+ t = (pktgen_random() %
+ (imx - imn)) + imn;
+ s = htonl(t);
}
- pkt_dev->cur_daddr = t;
- }
-
- else {
+ pkt_dev->cur_daddr = s;
+ } else {
t = ntohl(pkt_dev->cur_daddr);
t++;
if (t > imx) {
@@ -2270,7 +2266,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
for (i = 0; i < 4; i++) {
pkt_dev->cur_in6_daddr.s6_addr32[i] =
- ((pktgen_random() |
+ (((__force __be32)pktgen_random() |
pkt_dev->min_in6_daddr.s6_addr32[i]) &
pkt_dev->max_in6_daddr.s6_addr32[i]);
}
@@ -2377,7 +2373,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr));
memcpy(eth, pkt_dev->hh, 12);
- *(u16 *) & eth[12] = protocol;
+ *(__be16 *) & eth[12] = protocol;
/* Eth + IPh + UDPh + mpls */
datalen = pkt_dev->cur_pkt_size - 14 - 20 - 8 -
@@ -2497,7 +2493,7 @@ static unsigned int scan_ip6(const char *s, char ip[16])
char suffix[16];
unsigned int prefixlen = 0;
unsigned int suffixlen = 0;
- __u32 tmp;
+ __be32 tmp;
for (i = 0; i < 16; i++)
ip[i] = 0;
@@ -2713,7 +2709,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr));
memcpy(eth, pkt_dev->hh, 12);
- *(u16 *) & eth[12] = protocol;
+ *(__be16 *) & eth[12] = protocol;
/* Eth + IPh + UDPh + mpls */
datalen = pkt_dev->cur_pkt_size - 14 -
@@ -2732,11 +2728,11 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
udph->len = htons(datalen + sizeof(struct udphdr));
udph->check = 0; /* No checksum */
- *(u32 *) iph = __constant_htonl(0x60000000); /* Version + flow */
+ *(__be32 *) iph = __constant_htonl(0x60000000); /* Version + flow */
if (pkt_dev->traffic_class) {
/* Version + traffic class + flow (0) */
- *(u32 *)iph |= htonl(0x60000000 | (pkt_dev->traffic_class << 20));
+ *(__be32 *)iph |= htonl(0x60000000 | (pkt_dev->traffic_class << 20));
}
iph->hop_limit = 32;
diff --git a/net/core/request_sock.c b/net/core/request_sock.c
index 79ebd75fbe4d..5f0818d815e6 100644
--- a/net/core/request_sock.c
+++ b/net/core/request_sock.c
@@ -15,6 +15,7 @@
#include <linux/random.h>
#include <linux/slab.h>
#include <linux/string.h>
+#include <linux/vmalloc.h>
#include <net/request_sock.h>
@@ -29,22 +30,31 @@
* it is absolutely not enough even at 100conn/sec. 256 cures most
* of problems. This value is adjusted to 128 for very small machines
* (<=32Mb of memory) and to 1024 on normal or better ones (>=256Mb).
- * Further increasing requires to change hash table size.
+ * Note : Dont forget somaxconn that may limit backlog too.
*/
int sysctl_max_syn_backlog = 256;
int reqsk_queue_alloc(struct request_sock_queue *queue,
- const int nr_table_entries)
+ unsigned int nr_table_entries)
{
- const int lopt_size = sizeof(struct listen_sock) +
- nr_table_entries * sizeof(struct request_sock *);
- struct listen_sock *lopt = kzalloc(lopt_size, GFP_KERNEL);
-
+ size_t lopt_size = sizeof(struct listen_sock);
+ struct listen_sock *lopt;
+
+ nr_table_entries = min_t(u32, nr_table_entries, sysctl_max_syn_backlog);
+ nr_table_entries = max_t(u32, nr_table_entries, 8);
+ nr_table_entries = roundup_pow_of_two(nr_table_entries + 1);
+ lopt_size += nr_table_entries * sizeof(struct request_sock *);
+ if (lopt_size > PAGE_SIZE)
+ lopt = __vmalloc(lopt_size,
+ GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO,
+ PAGE_KERNEL);
+ else
+ lopt = kzalloc(lopt_size, GFP_KERNEL);
if (lopt == NULL)
return -ENOMEM;
- for (lopt->max_qlen_log = 6;
- (1 << lopt->max_qlen_log) < sysctl_max_syn_backlog;
+ for (lopt->max_qlen_log = 3;
+ (1 << lopt->max_qlen_log) < nr_table_entries;
lopt->max_qlen_log++);
get_random_bytes(&lopt->hash_rnd, sizeof(lopt->hash_rnd));
@@ -65,9 +75,11 @@ void reqsk_queue_destroy(struct request_sock_queue *queue)
{
/* make all the listen_opt local to us */
struct listen_sock *lopt = reqsk_queue_yank_listen_sk(queue);
+ size_t lopt_size = sizeof(struct listen_sock) +
+ lopt->nr_table_entries * sizeof(struct request_sock *);
if (lopt->qlen != 0) {
- int i;
+ unsigned int i;
for (i = 0; i < lopt->nr_table_entries; i++) {
struct request_sock *req;
@@ -81,7 +93,10 @@ void reqsk_queue_destroy(struct request_sock_queue *queue)
}
BUG_TRAP(lopt->qlen == 0);
- kfree(lopt);
+ if (lopt_size > PAGE_SIZE)
+ vfree(lopt);
+ else
+ kfree(lopt);
}
EXPORT_SYMBOL(reqsk_queue_destroy);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 02f3c7947898..e76539a5eb5e 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -108,7 +108,6 @@ static const int rtm_min[RTM_NR_FAMILIES] =
[RTM_FAM(RTM_NEWTCLASS)] = NLMSG_LENGTH(sizeof(struct tcmsg)),
[RTM_FAM(RTM_NEWTFILTER)] = NLMSG_LENGTH(sizeof(struct tcmsg)),
[RTM_FAM(RTM_NEWACTION)] = NLMSG_LENGTH(sizeof(struct tcamsg)),
- [RTM_FAM(RTM_NEWPREFIX)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
[RTM_FAM(RTM_GETMULTICAST)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
[RTM_FAM(RTM_GETANYCAST)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
};
@@ -213,6 +212,26 @@ nla_put_failure:
return nla_nest_cancel(skb, mx);
}
+int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst, u32 id,
+ u32 ts, u32 tsage, long expires, u32 error)
+{
+ struct rta_cacheinfo ci = {
+ .rta_lastuse = jiffies_to_clock_t(jiffies - dst->lastuse),
+ .rta_used = dst->__use,
+ .rta_clntref = atomic_read(&(dst->__refcnt)),
+ .rta_error = error,
+ .rta_id = id,
+ .rta_ts = ts,
+ .rta_tsage = tsage,
+ };
+
+ if (expires)
+ ci.rta_expires = jiffies_to_clock_t(expires);
+
+ return nla_put(skb, RTA_CACHEINFO, sizeof(ci), &ci);
+}
+
+EXPORT_SYMBOL_GPL(rtnl_put_cacheinfo);
static void set_operstate(struct net_device *dev, unsigned char transition)
{
@@ -273,6 +292,25 @@ static void copy_rtnl_link_stats(struct rtnl_link_stats *a,
a->tx_compressed = b->tx_compressed;
};
+static inline size_t if_nlmsg_size(int iwbuflen)
+{
+ return NLMSG_ALIGN(sizeof(struct ifinfomsg))
+ + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
+ + nla_total_size(IFNAMSIZ) /* IFLA_QDISC */
+ + nla_total_size(sizeof(struct rtnl_link_ifmap))
+ + nla_total_size(sizeof(struct rtnl_link_stats))
+ + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */
+ + nla_total_size(MAX_ADDR_LEN) /* IFLA_BROADCAST */
+ + nla_total_size(4) /* IFLA_TXQLEN */
+ + nla_total_size(4) /* IFLA_WEIGHT */
+ + nla_total_size(4) /* IFLA_MTU */
+ + nla_total_size(4) /* IFLA_LINK */
+ + nla_total_size(4) /* IFLA_MASTER */
+ + nla_total_size(1) /* IFLA_OPERSTATE */
+ + nla_total_size(1) /* IFLA_LINKMODE */
+ + nla_total_size(iwbuflen);
+}
+
static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
void *iwbuf, int iwbuflen, int type, u32 pid,
u32 seq, u32 change, unsigned int flags)
@@ -558,7 +596,7 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
struct sk_buff *nskb;
char *iw_buf = NULL, *iw = NULL;
int iw_buf_len = 0;
- int err, payload;
+ int err;
err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
if (err < 0)
@@ -587,9 +625,7 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
}
#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
- payload = NLMSG_ALIGN(sizeof(struct ifinfomsg) +
- nla_total_size(iw_buf_len));
- nskb = nlmsg_new(nlmsg_total_size(payload), GFP_KERNEL);
+ nskb = nlmsg_new(if_nlmsg_size(iw_buf_len), GFP_KERNEL);
if (nskb == NULL) {
err = -ENOBUFS;
goto errout;
@@ -597,10 +633,8 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
err = rtnl_fill_ifinfo(nskb, dev, iw, iw_buf_len, RTM_NEWLINK,
NETLINK_CB(skb).pid, nlh->nlmsg_seq, 0, 0);
- if (err <= 0) {
- kfree_skb(nskb);
- goto errout;
- }
+ /* failure impilies BUG in if_nlmsg_size or wireless_rtnetlink_get */
+ BUG_ON(err < 0);
err = rtnl_unicast(nskb, NETLINK_CB(skb).pid);
errout:
@@ -639,15 +673,13 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
struct sk_buff *skb;
int err = -ENOBUFS;
- skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+ skb = nlmsg_new(if_nlmsg_size(0), GFP_KERNEL);
if (skb == NULL)
goto errout;
err = rtnl_fill_ifinfo(skb, dev, NULL, 0, type, 0, 0, change, 0);
- if (err < 0) {
- kfree_skb(skb);
- goto errout;
- }
+ /* failure implies BUG in if_nlmsg_size() */
+ BUG_ON(err < 0);
err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_KERNEL);
errout:
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index b8b106358040..a90bc439488e 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -473,8 +473,8 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
#endif
C(protocol);
n->destructor = NULL;
+ C(mark);
#ifdef CONFIG_NETFILTER
- C(nfmark);
C(nfct);
nf_conntrack_get(skb->nfct);
C(nfctinfo);
@@ -534,8 +534,8 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
new->pkt_type = old->pkt_type;
new->tstamp = old->tstamp;
new->destructor = NULL;
+ new->mark = old->mark;
#ifdef CONFIG_NETFILTER
- new->nfmark = old->nfmark;
new->nfct = old->nfct;
nf_conntrack_get(old->nfct);
new->nfctinfo = old->nfctinfo;
@@ -1240,8 +1240,8 @@ EXPORT_SYMBOL(skb_store_bits);
/* Checksum skb data. */
-unsigned int skb_checksum(const struct sk_buff *skb, int offset,
- int len, unsigned int csum)
+__wsum skb_checksum(const struct sk_buff *skb, int offset,
+ int len, __wsum csum)
{
int start = skb_headlen(skb);
int i, copy = start - offset;
@@ -1265,7 +1265,7 @@ unsigned int skb_checksum(const struct sk_buff *skb, int offset,
end = start + skb_shinfo(skb)->frags[i].size;
if ((copy = end - offset) > 0) {
- unsigned int csum2;
+ __wsum csum2;
u8 *vaddr;
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
@@ -1294,7 +1294,7 @@ unsigned int skb_checksum(const struct sk_buff *skb, int offset,
end = start + list->len;
if ((copy = end - offset) > 0) {
- unsigned int csum2;
+ __wsum csum2;
if (copy > len)
copy = len;
csum2 = skb_checksum(list, offset - start,
@@ -1315,8 +1315,8 @@ unsigned int skb_checksum(const struct sk_buff *skb, int offset,
/* Both of above in one bottle. */
-unsigned int skb_copy_and_csum_bits(const struct sk_buff *skb, int offset,
- u8 *to, int len, unsigned int csum)
+__wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset,
+ u8 *to, int len, __wsum csum)
{
int start = skb_headlen(skb);
int i, copy = start - offset;
@@ -1342,7 +1342,7 @@ unsigned int skb_copy_and_csum_bits(const struct sk_buff *skb, int offset,
end = start + skb_shinfo(skb)->frags[i].size;
if ((copy = end - offset) > 0) {
- unsigned int csum2;
+ __wsum csum2;
u8 *vaddr;
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
@@ -1368,7 +1368,7 @@ unsigned int skb_copy_and_csum_bits(const struct sk_buff *skb, int offset,
struct sk_buff *list = skb_shinfo(skb)->frag_list;
for (; list; list = list->next) {
- unsigned int csum2;
+ __wsum csum2;
int end;
BUG_TRAP(start <= offset + len);
@@ -1396,7 +1396,7 @@ unsigned int skb_copy_and_csum_bits(const struct sk_buff *skb, int offset,
void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to)
{
- unsigned int csum;
+ __wsum csum;
long csstart;
if (skb->ip_summed == CHECKSUM_PARTIAL)
@@ -1414,9 +1414,9 @@ void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to)
skb->len - csstart, 0);
if (skb->ip_summed == CHECKSUM_PARTIAL) {
- long csstuff = csstart + skb->csum;
+ long csstuff = csstart + skb->csum_offset;
- *((unsigned short *)(to + csstuff)) = csum_fold(csum);
+ *((__sum16 *)(to + csstuff)) = csum_fold(csum);
}
}
diff --git a/net/core/sock.c b/net/core/sock.c
index ee6cd2541d35..ab8fafadb4ba 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -270,7 +270,7 @@ out:
}
EXPORT_SYMBOL(sock_queue_rcv_skb);
-int sk_receive_skb(struct sock *sk, struct sk_buff *skb)
+int sk_receive_skb(struct sock *sk, struct sk_buff *skb, const int nested)
{
int rc = NET_RX_SUCCESS;
@@ -279,7 +279,10 @@ int sk_receive_skb(struct sock *sk, struct sk_buff *skb)
skb->dev = NULL;
- bh_lock_sock(sk);
+ if (nested)
+ bh_lock_sock_nested(sk);
+ else
+ bh_lock_sock(sk);
if (!sock_owned_by_user(sk)) {
/*
* trylock + unlock semantics:
@@ -1527,7 +1530,7 @@ void sock_init_data(struct socket *sock, struct sock *sk)
atomic_set(&sk->sk_refcnt, 1);
}
-void fastcall lock_sock(struct sock *sk)
+void fastcall lock_sock_nested(struct sock *sk, int subclass)
{
might_sleep();
spin_lock_bh(&sk->sk_lock.slock);
@@ -1538,11 +1541,11 @@ void fastcall lock_sock(struct sock *sk)
/*
* The sk_lock has mutex_lock() semantics here:
*/
- mutex_acquire(&sk->sk_lock.dep_map, 0, 0, _RET_IP_);
+ mutex_acquire(&sk->sk_lock.dep_map, subclass, 0, _RET_IP_);
local_bh_enable();
}
-EXPORT_SYMBOL(lock_sock);
+EXPORT_SYMBOL(lock_sock_nested);
void fastcall release_sock(struct sock *sk)
{
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
index 02534131d88e..1e75b1585460 100644
--- a/net/core/sysctl_net_core.c
+++ b/net/core/sysctl_net_core.c
@@ -21,10 +21,6 @@ extern __u32 sysctl_rmem_max;
extern int sysctl_core_destroy_delay;
-#ifdef CONFIG_NET_DIVERT
-extern char sysctl_divert_version[];
-#endif /* CONFIG_NET_DIVERT */
-
#ifdef CONFIG_XFRM
extern u32 sysctl_xfrm_aevent_etime;
extern u32 sysctl_xfrm_aevent_rseqth;
@@ -105,16 +101,6 @@ ctl_table core_table[] = {
.mode = 0644,
.proc_handler = &proc_dointvec
},
-#ifdef CONFIG_NET_DIVERT
- {
- .ctl_name = NET_CORE_DIVERT_VERSION,
- .procname = "divert_version",
- .data = (void *)sysctl_divert_version,
- .maxlen = 32,
- .mode = 0444,
- .proc_handler = &proc_dostring
- },
-#endif /* CONFIG_NET_DIVERT */
#ifdef CONFIG_XFRM
{
.ctl_name = NET_CORE_AEVENT_ETIME,
diff --git a/net/core/utils.c b/net/core/utils.c
index d93fe64f6693..61556065f07e 100644
--- a/net/core/utils.c
+++ b/net/core/utils.c
@@ -88,7 +88,7 @@ EXPORT_SYMBOL(in_aton);
#define IN6PTON_NULL 0x20000000 /* first/tail */
#define IN6PTON_UNKNOWN 0x40000000
-static inline int digit2bin(char c, char delim)
+static inline int digit2bin(char c, int delim)
{
if (c == delim || c == '\0')
return IN6PTON_DELIM;
@@ -99,7 +99,7 @@ static inline int digit2bin(char c, char delim)
return IN6PTON_UNKNOWN;
}
-static inline int xdigit2bin(char c, char delim)
+static inline int xdigit2bin(char c, int delim)
{
if (c == delim || c == '\0')
return IN6PTON_DELIM;
@@ -113,12 +113,14 @@ static inline int xdigit2bin(char c, char delim)
return (IN6PTON_XDIGIT | (c - 'a' + 10));
if (c >= 'A' && c <= 'F')
return (IN6PTON_XDIGIT | (c - 'A' + 10));
+ if (delim == -1)
+ return IN6PTON_DELIM;
return IN6PTON_UNKNOWN;
}
int in4_pton(const char *src, int srclen,
u8 *dst,
- char delim, const char **end)
+ int delim, const char **end)
{
const char *s;
u8 *d;
@@ -173,7 +175,7 @@ EXPORT_SYMBOL(in4_pton);
int in6_pton(const char *src, int srclen,
u8 *dst,
- char delim, const char **end)
+ int delim, const char **end)
{
const char *s, *tok = NULL;
u8 *d, *dc = NULL;
diff --git a/net/dccp/Kconfig b/net/dccp/Kconfig
index ef8919cca74b..b8a68dd41000 100644
--- a/net/dccp/Kconfig
+++ b/net/dccp/Kconfig
@@ -38,6 +38,9 @@ config IP_DCCP_DEBUG
---help---
Only use this if you're hacking DCCP.
+ When compiling DCCP as a module, this debugging output can be toggled
+ by setting the parameter dccp_debug of the `dccp' module to 0 or 1.
+
Just say N.
config NET_DCCPPROBE
@@ -49,7 +52,7 @@ config NET_DCCPPROBE
DCCP congestion avoidance modules. If you don't understand
what was just said, you don't need it: say N.
- Documentation on how to use the packet generator can be found
+ Documentation on how to use DCCP connection probing can be found
at http://linux-net.osdl.org/index.php/DccpProbe
To compile this code as a module, choose M here: the
diff --git a/net/dccp/Makefile b/net/dccp/Makefile
index 17ed99c46617..f4f8793aafff 100644
--- a/net/dccp/Makefile
+++ b/net/dccp/Makefile
@@ -1,13 +1,13 @@
-obj-$(CONFIG_IPV6) += dccp_ipv6.o
-
-dccp_ipv6-y := ipv6.o
-
obj-$(CONFIG_IP_DCCP) += dccp.o dccp_ipv4.o
dccp-y := ccid.o feat.o input.o minisocks.o options.o output.o proto.o timer.o
dccp_ipv4-y := ipv4.o
+# build dccp_ipv6 as module whenever either IPv6 or DCCP is a module
+obj-$(subst y,$(CONFIG_IP_DCCP),$(CONFIG_IPV6)) += dccp_ipv6.o
+dccp_ipv6-y := ipv6.o
+
dccp-$(CONFIG_IP_DCCP_ACKVEC) += ackvec.o
obj-$(CONFIG_INET_DCCP_DIAG) += dccp_diag.o
diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c
index f8208874ac7d..bdf1bb7a82c0 100644
--- a/net/dccp/ackvec.c
+++ b/net/dccp/ackvec.c
@@ -67,15 +67,16 @@ static void dccp_ackvec_insert_avr(struct dccp_ackvec *av,
int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
{
struct dccp_sock *dp = dccp_sk(sk);
-#ifdef CONFIG_IP_DCCP_DEBUG
- const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
- "CLIENT tx: " : "server tx: ";
-#endif
struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec;
- int len = av->dccpav_vec_len + 2;
+ /* Figure out how many options do we need to represent the ackvec */
+ const u16 nr_opts = (av->dccpav_vec_len +
+ DCCP_MAX_ACKVEC_OPT_LEN - 1) /
+ DCCP_MAX_ACKVEC_OPT_LEN;
+ u16 len = av->dccpav_vec_len + 2 * nr_opts, i;
struct timeval now;
u32 elapsed_time;
- unsigned char *to, *from;
+ const unsigned char *tail, *from;
+ unsigned char *to;
struct dccp_ackvec_record *avr;
if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
@@ -94,24 +95,37 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
DCCP_SKB_CB(skb)->dccpd_opt_len += len;
- to = skb_push(skb, len);
- *to++ = DCCPO_ACK_VECTOR_0;
- *to++ = len;
-
+ to = skb_push(skb, len);
len = av->dccpav_vec_len;
from = av->dccpav_buf + av->dccpav_buf_head;
+ tail = av->dccpav_buf + DCCP_MAX_ACKVEC_LEN;
+
+ for (i = 0; i < nr_opts; ++i) {
+ int copylen = len;
- /* Check if buf_head wraps */
- if ((int)av->dccpav_buf_head + len > DCCP_MAX_ACKVEC_LEN) {
- const u32 tailsize = DCCP_MAX_ACKVEC_LEN - av->dccpav_buf_head;
+ if (len > DCCP_MAX_ACKVEC_OPT_LEN)
+ copylen = DCCP_MAX_ACKVEC_OPT_LEN;
+
+ *to++ = DCCPO_ACK_VECTOR_0;
+ *to++ = copylen + 2;
+
+ /* Check if buf_head wraps */
+ if (from + copylen > tail) {
+ const u16 tailsize = tail - from;
+
+ memcpy(to, from, tailsize);
+ to += tailsize;
+ len -= tailsize;
+ copylen -= tailsize;
+ from = av->dccpav_buf;
+ }
- memcpy(to, from, tailsize);
- to += tailsize;
- len -= tailsize;
- from = av->dccpav_buf;
+ memcpy(to, from, copylen);
+ from += copylen;
+ to += copylen;
+ len -= copylen;
}
- memcpy(to, from, len);
/*
* From RFC 4340, A.2:
*
@@ -129,9 +143,9 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
dccp_ackvec_insert_avr(av, avr);
- dccp_pr_debug("%sACK Vector 0, len=%d, ack_seqno=%llu, "
+ dccp_pr_debug("%s ACK Vector 0, len=%d, ack_seqno=%llu, "
"ack_ackno=%llu\n",
- debug_prefix, avr->dccpavr_sent_len,
+ dccp_role(sk), avr->dccpavr_sent_len,
(unsigned long long)avr->dccpavr_ack_seqno,
(unsigned long long)avr->dccpavr_ack_ackno);
return 0;
@@ -145,7 +159,6 @@ struct dccp_ackvec *dccp_ackvec_alloc(const gfp_t priority)
av->dccpav_buf_head = DCCP_MAX_ACKVEC_LEN - 1;
av->dccpav_buf_ackno = DCCP_MAX_SEQNO + 1;
av->dccpav_buf_nonce = av->dccpav_buf_nonce = 0;
- av->dccpav_ack_ptr = 0;
av->dccpav_time.tv_sec = 0;
av->dccpav_time.tv_usec = 0;
av->dccpav_vec_len = 0;
@@ -174,13 +187,13 @@ void dccp_ackvec_free(struct dccp_ackvec *av)
}
static inline u8 dccp_ackvec_state(const struct dccp_ackvec *av,
- const u8 index)
+ const u32 index)
{
return av->dccpav_buf[index] & DCCP_ACKVEC_STATE_MASK;
}
static inline u8 dccp_ackvec_len(const struct dccp_ackvec *av,
- const u8 index)
+ const u32 index)
{
return av->dccpav_buf[index] & DCCP_ACKVEC_LEN_MASK;
}
@@ -280,7 +293,7 @@ int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk,
* could reduce the complexity of this scan.)
*/
u64 delta = dccp_delta_seqno(ackno, av->dccpav_buf_ackno);
- u8 index = av->dccpav_buf_head;
+ u32 index = av->dccpav_buf_head;
while (1) {
const u8 len = dccp_ackvec_len(av, index);
@@ -322,21 +335,18 @@ out_duplicate:
#ifdef CONFIG_IP_DCCP_DEBUG
void dccp_ackvector_print(const u64 ackno, const unsigned char *vector, int len)
{
- if (!dccp_debug)
- return;
-
- printk("ACK vector len=%d, ackno=%llu |", len,
- (unsigned long long)ackno);
+ dccp_pr_debug_cat("ACK vector len=%d, ackno=%llu |", len,
+ (unsigned long long)ackno);
while (len--) {
const u8 state = (*vector & DCCP_ACKVEC_STATE_MASK) >> 6;
const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK;
- printk("%d,%d|", state, rl);
+ dccp_pr_debug_cat("%d,%d|", state, rl);
++vector;
}
- printk("\n");
+ dccp_pr_debug_cat("\n");
}
void dccp_ackvec_print(const struct dccp_ackvec *av)
@@ -380,24 +390,20 @@ void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av, struct sock *sk,
*/
list_for_each_entry_reverse(avr, &av->dccpav_records, dccpavr_node) {
if (ackno == avr->dccpavr_ack_seqno) {
-#ifdef CONFIG_IP_DCCP_DEBUG
- struct dccp_sock *dp = dccp_sk(sk);
- const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
- "CLIENT rx ack: " : "server rx ack: ";
-#endif
- dccp_pr_debug("%sACK packet 0, len=%d, ack_seqno=%llu, "
+ dccp_pr_debug("%s ACK packet 0, len=%d, ack_seqno=%llu, "
"ack_ackno=%llu, ACKED!\n",
- debug_prefix, 1,
+ dccp_role(sk), 1,
(unsigned long long)avr->dccpavr_ack_seqno,
(unsigned long long)avr->dccpavr_ack_ackno);
dccp_ackvec_throw_record(av, avr);
break;
- }
+ } else if (avr->dccpavr_ack_seqno > ackno)
+ break; /* old news */
}
}
static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av,
- struct sock *sk, u64 ackno,
+ struct sock *sk, u64 *ackno,
const unsigned char len,
const unsigned char *vector)
{
@@ -420,7 +426,7 @@ static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av,
const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK;
u64 ackno_end_rl;
- dccp_set_seqno(&ackno_end_rl, ackno - rl);
+ dccp_set_seqno(&ackno_end_rl, *ackno - rl);
/*
* If our AVR sequence number is greater than the ack, go
@@ -428,25 +434,19 @@ static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av,
*/
list_for_each_entry_from(avr, &av->dccpav_records,
dccpavr_node) {
- if (!after48(avr->dccpavr_ack_seqno, ackno))
+ if (!after48(avr->dccpavr_ack_seqno, *ackno))
goto found;
}
/* End of the dccpav_records list, not found, exit */
break;
found:
- if (between48(avr->dccpavr_ack_seqno, ackno_end_rl, ackno)) {
+ if (between48(avr->dccpavr_ack_seqno, ackno_end_rl, *ackno)) {
const u8 state = *vector & DCCP_ACKVEC_STATE_MASK;
if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED) {
-#ifdef CONFIG_IP_DCCP_DEBUG
- struct dccp_sock *dp = dccp_sk(sk);
- const char *debug_prefix =
- dp->dccps_role == DCCP_ROLE_CLIENT ?
- "CLIENT rx ack: " : "server rx ack: ";
-#endif
- dccp_pr_debug("%sACK vector 0, len=%d, "
+ dccp_pr_debug("%s ACK vector 0, len=%d, "
"ack_seqno=%llu, ack_ackno=%llu, "
"ACKED!\n",
- debug_prefix, len,
+ dccp_role(sk), len,
(unsigned long long)
avr->dccpavr_ack_seqno,
(unsigned long long)
@@ -460,27 +460,23 @@ found:
*/
}
- dccp_set_seqno(&ackno, ackno_end_rl - 1);
+ dccp_set_seqno(ackno, ackno_end_rl - 1);
++vector;
}
}
int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb,
- const u8 opt, const u8 *value, const u8 len)
+ u64 *ackno, const u8 opt, const u8 *value, const u8 len)
{
- if (len > DCCP_MAX_ACKVEC_LEN)
+ if (len > DCCP_MAX_ACKVEC_OPT_LEN)
return -1;
/* dccp_ackvector_print(DCCP_SKB_CB(skb)->dccpd_ack_seq, value, len); */
dccp_ackvec_check_rcv_ackvector(dccp_sk(sk)->dccps_hc_rx_ackvec, sk,
- DCCP_SKB_CB(skb)->dccpd_ack_seq,
- len, value);
+ ackno, len, value);
return 0;
}
-static char dccp_ackvec_slab_msg[] __initdata =
- KERN_CRIT "DCCP: Unable to create ack vectors slab caches\n";
-
int __init dccp_ackvec_init(void)
{
dccp_ackvec_slab = kmem_cache_create("dccp_ackvec",
@@ -502,7 +498,7 @@ out_destroy_slab:
kmem_cache_destroy(dccp_ackvec_slab);
dccp_ackvec_slab = NULL;
out_err:
- printk(dccp_ackvec_slab_msg);
+ DCCP_CRIT("Unable to create Ack Vector slab cache");
return -ENOBUFS;
}
diff --git a/net/dccp/ackvec.h b/net/dccp/ackvec.h
index cf8f20ce23a9..96504a3b16e4 100644
--- a/net/dccp/ackvec.h
+++ b/net/dccp/ackvec.h
@@ -17,7 +17,9 @@
#include <linux/types.h>
/* Read about the ECN nonce to see why it is 253 */
-#define DCCP_MAX_ACKVEC_LEN 253
+#define DCCP_MAX_ACKVEC_OPT_LEN 253
+/* We can spread an ack vector across multiple options */
+#define DCCP_MAX_ACKVEC_LEN (DCCP_MAX_ACKVEC_OPT_LEN * 2)
#define DCCP_ACKVEC_STATE_RECEIVED 0
#define DCCP_ACKVEC_STATE_ECN_MARKED (1 << 6)
@@ -41,7 +43,6 @@
* Ack Vectors it has recently sent. For each packet sent carrying an
* Ack Vector, it remembers four variables:
*
- * @dccpav_ack_ptr - the value of buf_head at the time of acknowledgement.
* @dccpav_records - list of dccp_ackvec_record
* @dccpav_ack_nonce - the one-bit sum of the ECN Nonces for all State 0.
*
@@ -52,9 +53,8 @@ struct dccp_ackvec {
u64 dccpav_buf_ackno;
struct list_head dccpav_records;
struct timeval dccpav_time;
- u8 dccpav_buf_head;
- u8 dccpav_ack_ptr;
- u8 dccpav_vec_len;
+ u16 dccpav_buf_head;
+ u16 dccpav_vec_len;
u8 dccpav_buf_nonce;
u8 dccpav_ack_nonce;
u8 dccpav_buf[DCCP_MAX_ACKVEC_LEN];
@@ -77,9 +77,9 @@ struct dccp_ackvec_record {
struct list_head dccpavr_node;
u64 dccpavr_ack_seqno;
u64 dccpavr_ack_ackno;
- u8 dccpavr_ack_ptr;
+ u16 dccpavr_ack_ptr;
+ u16 dccpavr_sent_len;
u8 dccpavr_ack_nonce;
- u8 dccpavr_sent_len;
};
struct sock;
@@ -98,7 +98,8 @@ extern int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk,
extern void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av,
struct sock *sk, const u64 ackno);
extern int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb,
- const u8 opt, const u8 *value, const u8 len);
+ u64 *ackno, const u8 opt,
+ const u8 *value, const u8 len);
extern int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb);
@@ -137,7 +138,8 @@ static inline void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av,
}
static inline int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb,
- const u8 opt, const u8 *value, const u8 len)
+ const u64 *ackno, const u8 opt,
+ const u8 *value, const u8 len)
{
return -1;
}
diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h
index f7eb6c613414..c7c29514dce8 100644
--- a/net/dccp/ccid.h
+++ b/net/dccp/ccid.h
@@ -52,9 +52,9 @@ struct ccid_operations {
unsigned char len, u16 idx,
unsigned char* value);
int (*ccid_hc_tx_send_packet)(struct sock *sk,
- struct sk_buff *skb, int len);
- void (*ccid_hc_tx_packet_sent)(struct sock *sk, int more,
- int len);
+ struct sk_buff *skb);
+ void (*ccid_hc_tx_packet_sent)(struct sock *sk,
+ int more, unsigned int len);
void (*ccid_hc_rx_get_info)(struct sock *sk,
struct tcp_info *info);
void (*ccid_hc_tx_get_info)(struct sock *sk,
@@ -94,16 +94,16 @@ extern void ccid_hc_rx_delete(struct ccid *ccid, struct sock *sk);
extern void ccid_hc_tx_delete(struct ccid *ccid, struct sock *sk);
static inline int ccid_hc_tx_send_packet(struct ccid *ccid, struct sock *sk,
- struct sk_buff *skb, int len)
+ struct sk_buff *skb)
{
int rc = 0;
if (ccid->ccid_ops->ccid_hc_tx_send_packet != NULL)
- rc = ccid->ccid_ops->ccid_hc_tx_send_packet(sk, skb, len);
+ rc = ccid->ccid_ops->ccid_hc_tx_send_packet(sk, skb);
return rc;
}
static inline void ccid_hc_tx_packet_sent(struct ccid *ccid, struct sock *sk,
- int more, int len)
+ int more, unsigned int len)
{
if (ccid->ccid_ops->ccid_hc_tx_packet_sent != NULL)
ccid->ccid_ops->ccid_hc_tx_packet_sent(sk, more, len);
diff --git a/net/dccp/ccids/Kconfig b/net/dccp/ccids/Kconfig
index 8533dabfb9f8..dac89166eb18 100644
--- a/net/dccp/ccids/Kconfig
+++ b/net/dccp/ccids/Kconfig
@@ -28,13 +28,20 @@ config IP_DCCP_CCID2
This text was extracted from RFC 4340 (sec. 10.1),
http://www.ietf.org/rfc/rfc4340.txt
+ To compile this CCID as a module, choose M here: the module will be
+ called dccp_ccid2.
+
If in doubt, say M.
config IP_DCCP_CCID2_DEBUG
- bool "CCID2 debug"
+ bool "CCID2 debugging messages"
depends on IP_DCCP_CCID2
---help---
- Enable CCID2 debug messages.
+ Enable CCID2-specific debugging messages.
+
+ When compiling CCID2 as a module, this debugging output can
+ additionally be toggled by setting the ccid2_debug module
+ parameter to 0 or 1.
If in doubt, say N.
@@ -62,10 +69,24 @@ config IP_DCCP_CCID3
This text was extracted from RFC 4340 (sec. 10.2),
http://www.ietf.org/rfc/rfc4340.txt
+ To compile this CCID as a module, choose M here: the module will be
+ called dccp_ccid3.
+
If in doubt, say M.
config IP_DCCP_TFRC_LIB
depends on IP_DCCP_CCID3
def_tristate IP_DCCP_CCID3
+config IP_DCCP_CCID3_DEBUG
+ bool "CCID3 debugging messages"
+ depends on IP_DCCP_CCID3
+ ---help---
+ Enable CCID3-specific debugging messages.
+
+ When compiling CCID3 as a module, this debugging output can
+ additionally be toggled by setting the ccid3_debug module
+ parameter to 0 or 1.
+
+ If in doubt, say N.
endmenu
diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c
index 162032baeac0..2555be8f4790 100644
--- a/net/dccp/ccids/ccid2.c
+++ b/net/dccp/ccids/ccid2.c
@@ -33,18 +33,11 @@
#include "../dccp.h"
#include "ccid2.h"
-static int ccid2_debug;
#ifdef CONFIG_IP_DCCP_CCID2_DEBUG
-#define ccid2_pr_debug(format, a...) \
- do { if (ccid2_debug) \
- printk(KERN_DEBUG "%s: " format, __FUNCTION__, ##a); \
- } while (0)
-#else
-#define ccid2_pr_debug(format, a...)
-#endif
+static int ccid2_debug;
+#define ccid2_pr_debug(format, a...) DCCP_PR_DEBUG(ccid2_debug, format, ##a)
-#ifdef CONFIG_IP_DCCP_CCID2_DEBUG
static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hctx)
{
int len = 0;
@@ -86,7 +79,8 @@ static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hctx)
BUG_ON(len != hctx->ccid2hctx_seqbufc * CCID2_SEQBUF_LEN);
}
#else
-#define ccid2_hc_tx_check_sanity(hctx) do {} while (0)
+#define ccid2_pr_debug(format, a...)
+#define ccid2_hc_tx_check_sanity(hctx)
#endif
static int ccid2_hc_tx_alloc_seq(struct ccid2_hc_tx_sock *hctx, int num,
@@ -131,8 +125,7 @@ static int ccid2_hc_tx_alloc_seq(struct ccid2_hc_tx_sock *hctx, int num,
return 0;
}
-static int ccid2_hc_tx_send_packet(struct sock *sk,
- struct sk_buff *skb, int len)
+static int ccid2_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
{
struct ccid2_hc_tx_sock *hctx;
@@ -274,7 +267,7 @@ static void ccid2_start_rto_timer(struct sock *sk)
jiffies + hctx->ccid2hctx_rto);
}
-static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, int len)
+static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, unsigned int len)
{
struct dccp_sock *dp = dccp_sk(sk);
struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
@@ -426,7 +419,7 @@ static int ccid2_ackvector(struct sock *sk, struct sk_buff *skb, int offset,
return -1;
out_invalid_option:
- BUG_ON(1); /* should never happen... options were previously parsed ! */
+ DCCP_BUG("Invalid option - this should not happen (previous parsing)!");
return -1;
}
@@ -619,7 +612,17 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
}
ackno = DCCP_SKB_CB(skb)->dccpd_ack_seq;
- seqp = hctx->ccid2hctx_seqh->ccid2s_prev;
+ if (after48(ackno, hctx->ccid2hctx_high_ack))
+ hctx->ccid2hctx_high_ack = ackno;
+
+ seqp = hctx->ccid2hctx_seqt;
+ while (before48(seqp->ccid2s_seq, ackno)) {
+ seqp = seqp->ccid2s_next;
+ if (seqp == hctx->ccid2hctx_seqh) {
+ seqp = hctx->ccid2hctx_seqh->ccid2s_prev;
+ break;
+ }
+ }
/* If in slow-start, cwnd can increase at most Ack Ratio / 2 packets for
* this single ack. I round up.
@@ -697,7 +700,14 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
/* The state about what is acked should be correct now
* Check for NUMDUPACK
*/
- seqp = hctx->ccid2hctx_seqh->ccid2s_prev;
+ seqp = hctx->ccid2hctx_seqt;
+ while (before48(seqp->ccid2s_seq, hctx->ccid2hctx_high_ack)) {
+ seqp = seqp->ccid2s_next;
+ if (seqp == hctx->ccid2hctx_seqh) {
+ seqp = hctx->ccid2hctx_seqh->ccid2s_prev;
+ break;
+ }
+ }
done = 0;
while (1) {
if (seqp->ccid2s_acked) {
@@ -771,6 +781,7 @@ static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)
hctx->ccid2hctx_lastrtt = 0;
hctx->ccid2hctx_rpdupack = -1;
hctx->ccid2hctx_last_cong = jiffies;
+ hctx->ccid2hctx_high_ack = 0;
hctx->ccid2hctx_rtotimer.function = &ccid2_hc_tx_rto_expire;
hctx->ccid2hctx_rtotimer.data = (unsigned long)sk;
@@ -823,8 +834,10 @@ static struct ccid_operations ccid2 = {
.ccid_hc_rx_packet_recv = ccid2_hc_rx_packet_recv,
};
+#ifdef CONFIG_IP_DCCP_CCID2_DEBUG
module_param(ccid2_debug, int, 0444);
MODULE_PARM_DESC(ccid2_debug, "Enable debug messages");
+#endif
static __init int ccid2_module_init(void)
{
diff --git a/net/dccp/ccids/ccid2.h b/net/dccp/ccids/ccid2.h
index 5b2ef4acb300..ebd79499c85a 100644
--- a/net/dccp/ccids/ccid2.h
+++ b/net/dccp/ccids/ccid2.h
@@ -35,7 +35,7 @@ struct ccid2_seq {
struct ccid2_seq *ccid2s_next;
};
-#define CCID2_SEQBUF_LEN 256
+#define CCID2_SEQBUF_LEN 1024
#define CCID2_SEQBUF_MAX 128
/** struct ccid2_hc_tx_sock - CCID2 TX half connection
@@ -72,6 +72,7 @@ struct ccid2_hc_tx_sock {
int ccid2hctx_rpdupack;
int ccid2hctx_sendwait;
unsigned long ccid2hctx_last_cong;
+ u64 ccid2hctx_high_ack;
};
struct ccid2_hc_rx_sock {
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index cec23ad286de..70ebe705eb75 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -60,13 +60,11 @@ static u32 usecs_div(const u32 a, const u32 b)
return (b >= 2 * div) ? tmp / (b / div) : tmp;
}
-static int ccid3_debug;
-#ifdef CCID3_DEBUG
-#define ccid3_pr_debug(format, a...) \
- do { if (ccid3_debug) \
- printk(KERN_DEBUG "%s: " format, __FUNCTION__, ##a); \
- } while (0)
+
+#ifdef CONFIG_IP_DCCP_CCID3_DEBUG
+static int ccid3_debug;
+#define ccid3_pr_debug(format, a...) DCCP_PR_DEBUG(ccid3_debug, format, ##a)
#else
#define ccid3_pr_debug(format, a...)
#endif
@@ -75,15 +73,7 @@ static struct dccp_tx_hist *ccid3_tx_hist;
static struct dccp_rx_hist *ccid3_rx_hist;
static struct dccp_li_hist *ccid3_li_hist;
-/* TFRC sender states */
-enum ccid3_hc_tx_states {
- TFRC_SSTATE_NO_SENT = 1,
- TFRC_SSTATE_NO_FBACK,
- TFRC_SSTATE_FBACK,
- TFRC_SSTATE_TERM,
-};
-
-#ifdef CCID3_DEBUG
+#ifdef CONFIG_IP_DCCP_CCID3_DEBUG
static const char *ccid3_tx_state_name(enum ccid3_hc_tx_states state)
{
static char *ccid3_state_names[] = {
@@ -110,25 +100,24 @@ static void ccid3_hc_tx_set_state(struct sock *sk,
hctx->ccid3hctx_state = state;
}
-/* Calculate new t_ipi (inter packet interval) by t_ipi = s / X_inst */
-static inline void ccid3_calc_new_t_ipi(struct ccid3_hc_tx_sock *hctx)
+/*
+ * Recalculate scheduled nominal send time t_nom, inter-packet interval
+ * t_ipi, and delta value. Should be called after each change to X.
+ */
+static inline void ccid3_update_send_time(struct ccid3_hc_tx_sock *hctx)
{
- /*
- * If no feedback spec says t_ipi is 1 second (set elsewhere and then
- * doubles after every no feedback timer (separate function)
- */
- if (hctx->ccid3hctx_state != TFRC_SSTATE_NO_FBACK)
- hctx->ccid3hctx_t_ipi = usecs_div(hctx->ccid3hctx_s,
- hctx->ccid3hctx_x);
-}
+ timeval_sub_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi);
-/* Calculate new delta by delta = min(t_ipi / 2, t_gran / 2) */
-static inline void ccid3_calc_new_delta(struct ccid3_hc_tx_sock *hctx)
-{
+ /* Calculate new t_ipi (inter packet interval) by t_ipi = s / X_inst */
+ hctx->ccid3hctx_t_ipi = usecs_div(hctx->ccid3hctx_s, hctx->ccid3hctx_x);
+
+ /* Update nominal send time with regard to the new t_ipi */
+ timeval_add_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi);
+
+ /* Calculate new delta by delta = min(t_ipi / 2, t_gran / 2) */
hctx->ccid3hctx_delta = min_t(u32, hctx->ccid3hctx_t_ipi / 2,
TFRC_OPSYS_HALF_TIME_GRAN);
}
-
/*
* Update X by
* If (p > 0)
@@ -139,76 +128,85 @@ static inline void ccid3_calc_new_delta(struct ccid3_hc_tx_sock *hctx)
* X = max(min(2 * X, 2 * X_recv), s / R);
* tld = now;
*/
-static void ccid3_hc_tx_update_x(struct sock *sk)
+static void ccid3_hc_tx_update_x(struct sock *sk, struct timeval *now)
+
{
struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
+ const __u32 old_x = hctx->ccid3hctx_x;
/* To avoid large error in calcX */
if (hctx->ccid3hctx_p >= TFRC_SMALLEST_P) {
hctx->ccid3hctx_x_calc = tfrc_calc_x(hctx->ccid3hctx_s,
hctx->ccid3hctx_rtt,
hctx->ccid3hctx_p);
- hctx->ccid3hctx_x = max_t(u32, min_t(u32, hctx->ccid3hctx_x_calc,
- 2 * hctx->ccid3hctx_x_recv),
- (hctx->ccid3hctx_s /
- TFRC_MAX_BACK_OFF_TIME));
- } else {
- struct timeval now;
+ hctx->ccid3hctx_x = max_t(u32, min(hctx->ccid3hctx_x_calc,
+ hctx->ccid3hctx_x_recv * 2),
+ hctx->ccid3hctx_s / TFRC_T_MBI);
+
+ } else if (timeval_delta(now, &hctx->ccid3hctx_t_ld) >=
+ hctx->ccid3hctx_rtt) {
+ hctx->ccid3hctx_x = max(min(hctx->ccid3hctx_x_recv,
+ hctx->ccid3hctx_x ) * 2,
+ usecs_div(hctx->ccid3hctx_s,
+ hctx->ccid3hctx_rtt) );
+ hctx->ccid3hctx_t_ld = *now;
+ } else
+ ccid3_pr_debug("Not changing X\n");
- dccp_timestamp(sk, &now);
- if (timeval_delta(&now, &hctx->ccid3hctx_t_ld) >=
- hctx->ccid3hctx_rtt) {
- hctx->ccid3hctx_x = max_t(u32, min_t(u32, hctx->ccid3hctx_x_recv,
- hctx->ccid3hctx_x) * 2,
- usecs_div(hctx->ccid3hctx_s,
- hctx->ccid3hctx_rtt));
- hctx->ccid3hctx_t_ld = now;
- }
- }
+ if (hctx->ccid3hctx_x != old_x)
+ ccid3_update_send_time(hctx);
+}
+
+/*
+ * Track the mean packet size `s' (cf. RFC 4342, 5.3 and RFC 3448, 4.1)
+ * @len: DCCP packet payload size in bytes
+ */
+static inline void ccid3_hc_tx_update_s(struct ccid3_hc_tx_sock *hctx, int len)
+{
+ if (unlikely(len == 0))
+ ccid3_pr_debug("Packet payload length is 0 - not updating\n");
+ else
+ hctx->ccid3hctx_s = hctx->ccid3hctx_s == 0 ? len :
+ (9 * hctx->ccid3hctx_s + len) / 10;
+ /*
+ * Note: We could do a potential optimisation here - when `s' changes,
+ * recalculate sending rate and consequently t_ipi, t_delta, and
+ * t_now. This is however non-standard, and the benefits are not
+ * clear, so it is currently left out.
+ */
}
static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
{
struct sock *sk = (struct sock *)data;
- unsigned long next_tmout = 0;
struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
+ unsigned long t_nfb = USEC_PER_SEC / 5;
bh_lock_sock(sk);
if (sock_owned_by_user(sk)) {
/* Try again later. */
/* XXX: set some sensible MIB */
- sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
- jiffies + HZ / 5);
- goto out;
+ goto restart_timer;
}
ccid3_pr_debug("%s, sk=%p, state=%s\n", dccp_role(sk), sk,
ccid3_tx_state_name(hctx->ccid3hctx_state));
switch (hctx->ccid3hctx_state) {
- case TFRC_SSTATE_TERM:
- goto out;
case TFRC_SSTATE_NO_FBACK:
- /* Halve send rate */
- hctx->ccid3hctx_x /= 2;
- if (hctx->ccid3hctx_x < (hctx->ccid3hctx_s /
- TFRC_MAX_BACK_OFF_TIME))
- hctx->ccid3hctx_x = (hctx->ccid3hctx_s /
- TFRC_MAX_BACK_OFF_TIME);
+ /* RFC 3448, 4.4: Halve send rate directly */
+ hctx->ccid3hctx_x = min_t(u32, hctx->ccid3hctx_x / 2,
+ hctx->ccid3hctx_s / TFRC_T_MBI);
ccid3_pr_debug("%s, sk=%p, state=%s, updated tx rate to %d "
"bytes/s\n",
dccp_role(sk), sk,
ccid3_tx_state_name(hctx->ccid3hctx_state),
hctx->ccid3hctx_x);
- next_tmout = max_t(u32, 2 * usecs_div(hctx->ccid3hctx_s,
- hctx->ccid3hctx_x),
- TFRC_INITIAL_TIMEOUT);
- /*
- * FIXME - not sure above calculation is correct. See section
- * 5 of CCID3 11 should adjust tx_t_ipi and double that to
- * achieve it really
- */
+ /* The value of R is still undefined and so we can not recompute
+ * the timout value. Keep initial value as per [RFC 4342, 5]. */
+ t_nfb = TFRC_INITIAL_TIMEOUT;
+ ccid3_update_send_time(hctx);
break;
case TFRC_SSTATE_FBACK:
/*
@@ -218,6 +216,8 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
if (!hctx->ccid3hctx_idle ||
(hctx->ccid3hctx_x_recv >=
4 * usecs_div(hctx->ccid3hctx_s, hctx->ccid3hctx_rtt))) {
+ struct timeval now;
+
ccid3_pr_debug("%s, sk=%p, state=%s, not idle\n",
dccp_role(sk), sk,
ccid3_tx_state_name(hctx->ccid3hctx_state));
@@ -235,55 +235,60 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
if (hctx->ccid3hctx_p < TFRC_SMALLEST_P ||
hctx->ccid3hctx_x_calc > 2 * hctx->ccid3hctx_x_recv)
hctx->ccid3hctx_x_recv = max_t(u32, hctx->ccid3hctx_x_recv / 2,
- hctx->ccid3hctx_s / (2 * TFRC_MAX_BACK_OFF_TIME));
+ hctx->ccid3hctx_s / (2 * TFRC_T_MBI));
else
hctx->ccid3hctx_x_recv = hctx->ccid3hctx_x_calc / 4;
/* Update sending rate */
- ccid3_hc_tx_update_x(sk);
+ dccp_timestamp(sk, &now);
+ ccid3_hc_tx_update_x(sk, &now);
}
/*
* Schedule no feedback timer to expire in
- * max(4 * R, 2 * s / X)
+ * max(4 * R, 2 * s/X) = max(4 * R, 2 * t_ipi)
*/
- next_tmout = max_t(u32, hctx->ccid3hctx_t_rto,
- 2 * usecs_div(hctx->ccid3hctx_s,
- hctx->ccid3hctx_x));
+ t_nfb = max(4 * hctx->ccid3hctx_rtt, 2 * hctx->ccid3hctx_t_ipi);
break;
- default:
- printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n",
- __FUNCTION__, dccp_role(sk), sk, hctx->ccid3hctx_state);
- dump_stack();
+ case TFRC_SSTATE_NO_SENT:
+ DCCP_BUG("Illegal %s state NO_SENT, sk=%p", dccp_role(sk), sk);
+ /* fall through */
+ case TFRC_SSTATE_TERM:
goto out;
}
- sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
- jiffies + max_t(u32, 1, usecs_to_jiffies(next_tmout)));
hctx->ccid3hctx_idle = 1;
+
+restart_timer:
+ sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
+ jiffies + usecs_to_jiffies(t_nfb));
out:
bh_unlock_sock(sk);
sock_put(sk);
}
-static int ccid3_hc_tx_send_packet(struct sock *sk,
- struct sk_buff *skb, int len)
+/*
+ * returns
+ * > 0: delay (in msecs) that should pass before actually sending
+ * = 0: can send immediately
+ * < 0: error condition; do not send packet
+ */
+static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
{
struct dccp_sock *dp = dccp_sk(sk);
struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
struct dccp_tx_hist_entry *new_packet;
struct timeval now;
long delay;
- int rc = -ENOTCONN;
- BUG_ON(hctx == NULL || hctx->ccid3hctx_state == TFRC_SSTATE_TERM);
+ BUG_ON(hctx == NULL);
- /* Check if pure ACK or Terminating*/
/*
- * XXX: We only call this function for DATA and DATAACK, on, these
- * packets can have zero length, but why the comment about "pure ACK"?
+ * This function is called only for Data and DataAck packets. Sending
+ * zero-sized Data(Ack)s is theoretically possible, but for congestion
+ * control this case is pathological - ignore it.
*/
- if (unlikely(len == 0))
- goto out;
+ if (unlikely(skb->len == 0))
+ return -EBADMSG;
/* See if last packet allocated was not sent */
new_packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist);
@@ -291,12 +296,10 @@ static int ccid3_hc_tx_send_packet(struct sock *sk,
new_packet = dccp_tx_hist_entry_new(ccid3_tx_hist,
SLAB_ATOMIC);
- rc = -ENOBUFS;
if (unlikely(new_packet == NULL)) {
- LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, not enough "
- "mem to add to history, send refused\n",
- __FUNCTION__, dccp_role(sk), sk);
- goto out;
+ DCCP_WARN("%s, sk=%p, not enough mem to add to history,"
+ "send refused\n", dccp_role(sk), sk);
+ return -ENOBUFS;
}
dccp_tx_hist_add_entry(&hctx->ccid3hctx_hist, new_packet);
@@ -311,123 +314,94 @@ static int ccid3_hc_tx_send_packet(struct sock *sk,
hctx->ccid3hctx_last_win_count = 0;
hctx->ccid3hctx_t_last_win_count = now;
ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK);
- hctx->ccid3hctx_t_ipi = TFRC_INITIAL_IPI;
- /* Set nominal send time for initial packet */
+ /* Set initial sending rate to 1 packet per second */
+ ccid3_hc_tx_update_s(hctx, skb->len);
+ hctx->ccid3hctx_x = hctx->ccid3hctx_s;
+
+ /* First timeout, according to [RFC 3448, 4.2], is 1 second */
+ hctx->ccid3hctx_t_ipi = USEC_PER_SEC;
+ /* Initial delta: minimum of 0.5 sec and t_gran/2 */
+ hctx->ccid3hctx_delta = TFRC_OPSYS_HALF_TIME_GRAN;
+
+ /* Set t_0 for initial packet */
hctx->ccid3hctx_t_nom = now;
- timeval_add_usecs(&hctx->ccid3hctx_t_nom,
- hctx->ccid3hctx_t_ipi);
- ccid3_calc_new_delta(hctx);
- rc = 0;
break;
case TFRC_SSTATE_NO_FBACK:
case TFRC_SSTATE_FBACK:
- delay = (timeval_delta(&now, &hctx->ccid3hctx_t_nom) -
- hctx->ccid3hctx_delta);
- delay /= -1000;
- /* divide by -1000 is to convert to ms and get sign right */
- rc = delay > 0 ? delay : 0;
- break;
- default:
- printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n",
- __FUNCTION__, dccp_role(sk), sk, hctx->ccid3hctx_state);
- dump_stack();
- rc = -EINVAL;
+ delay = timeval_delta(&hctx->ccid3hctx_t_nom, &now);
+ /*
+ * Scheduling of packet transmissions [RFC 3448, 4.6]
+ *
+ * if (t_now > t_nom - delta)
+ * // send the packet now
+ * else
+ * // send the packet in (t_nom - t_now) milliseconds.
+ */
+ if (delay >= hctx->ccid3hctx_delta)
+ return delay / 1000L;
break;
+ case TFRC_SSTATE_TERM:
+ DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk);
+ return -EINVAL;
}
- /* Can we send? if so add options and add to packet history */
- if (rc == 0) {
- dp->dccps_hc_tx_insert_options = 1;
- new_packet->dccphtx_ccval =
- DCCP_SKB_CB(skb)->dccpd_ccval =
- hctx->ccid3hctx_last_win_count;
- timeval_add_usecs(&hctx->ccid3hctx_t_nom,
- hctx->ccid3hctx_t_ipi);
- }
-out:
- return rc;
+ /* prepare to send now (add options etc.) */
+ dp->dccps_hc_tx_insert_options = 1;
+ new_packet->dccphtx_ccval = DCCP_SKB_CB(skb)->dccpd_ccval =
+ hctx->ccid3hctx_last_win_count;
+ timeval_add_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi);
+
+ return 0;
}
-static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len)
+static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, unsigned int len)
{
const struct dccp_sock *dp = dccp_sk(sk);
struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
struct timeval now;
+ unsigned long quarter_rtt;
+ struct dccp_tx_hist_entry *packet;
- BUG_ON(hctx == NULL || hctx->ccid3hctx_state == TFRC_SSTATE_TERM);
+ BUG_ON(hctx == NULL);
dccp_timestamp(sk, &now);
- /* check if we have sent a data packet */
- if (len > 0) {
- unsigned long quarter_rtt;
- struct dccp_tx_hist_entry *packet;
+ ccid3_hc_tx_update_s(hctx, len);
- packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist);
- if (unlikely(packet == NULL)) {
- LIMIT_NETDEBUG(KERN_WARNING "%s: packet doesn't "
- "exists in history!\n", __FUNCTION__);
- return;
- }
- if (unlikely(packet->dccphtx_sent)) {
- LIMIT_NETDEBUG(KERN_WARNING "%s: no unsent packet in "
- "history!\n", __FUNCTION__);
- return;
- }
- packet->dccphtx_tstamp = now;
- packet->dccphtx_seqno = dp->dccps_gss;
- /*
- * Check if win_count have changed
- * Algorithm in "8.1. Window Counter Value" in RFC 4342.
- */
- quarter_rtt = timeval_delta(&now, &hctx->ccid3hctx_t_last_win_count);
- if (likely(hctx->ccid3hctx_rtt > 8))
- quarter_rtt /= hctx->ccid3hctx_rtt / 4;
-
- if (quarter_rtt > 0) {
- hctx->ccid3hctx_t_last_win_count = now;
- hctx->ccid3hctx_last_win_count = (hctx->ccid3hctx_last_win_count +
- min_t(unsigned long, quarter_rtt, 5)) % 16;
- ccid3_pr_debug("%s, sk=%p, window changed from "
- "%u to %u!\n",
- dccp_role(sk), sk,
- packet->dccphtx_ccval,
- hctx->ccid3hctx_last_win_count);
- }
-
- hctx->ccid3hctx_idle = 0;
- packet->dccphtx_rtt = hctx->ccid3hctx_rtt;
- packet->dccphtx_sent = 1;
- } else
- ccid3_pr_debug("%s, sk=%p, seqno=%llu NOT inserted!\n",
- dccp_role(sk), sk, dp->dccps_gss);
-
- switch (hctx->ccid3hctx_state) {
- case TFRC_SSTATE_NO_SENT:
- /* if first wasn't pure ack */
- if (len != 0)
- printk(KERN_CRIT "%s: %s, First packet sent is noted "
- "as a data packet\n",
- __FUNCTION__, dccp_role(sk));
+ packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist);
+ if (unlikely(packet == NULL)) {
+ DCCP_WARN("packet doesn't exist in history!\n");
return;
- case TFRC_SSTATE_NO_FBACK:
- case TFRC_SSTATE_FBACK:
- if (len > 0) {
- timeval_sub_usecs(&hctx->ccid3hctx_t_nom,
- hctx->ccid3hctx_t_ipi);
- ccid3_calc_new_t_ipi(hctx);
- ccid3_calc_new_delta(hctx);
- timeval_add_usecs(&hctx->ccid3hctx_t_nom,
- hctx->ccid3hctx_t_ipi);
- }
- break;
- default:
- printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n",
- __FUNCTION__, dccp_role(sk), sk, hctx->ccid3hctx_state);
- dump_stack();
- break;
}
+ if (unlikely(packet->dccphtx_sent)) {
+ DCCP_WARN("no unsent packet in history!\n");
+ return;
+ }
+ packet->dccphtx_tstamp = now;
+ packet->dccphtx_seqno = dp->dccps_gss;
+ /*
+ * Check if win_count have changed
+ * Algorithm in "8.1. Window Counter Value" in RFC 4342.
+ */
+ quarter_rtt = timeval_delta(&now, &hctx->ccid3hctx_t_last_win_count);
+ if (likely(hctx->ccid3hctx_rtt > 8))
+ quarter_rtt /= hctx->ccid3hctx_rtt / 4;
+
+ if (quarter_rtt > 0) {
+ hctx->ccid3hctx_t_last_win_count = now;
+ hctx->ccid3hctx_last_win_count = (hctx->ccid3hctx_last_win_count +
+ min_t(unsigned long, quarter_rtt, 5)) % 16;
+ ccid3_pr_debug("%s, sk=%p, window changed from "
+ "%u to %u!\n",
+ dccp_role(sk), sk,
+ packet->dccphtx_ccval,
+ hctx->ccid3hctx_last_win_count);
+ }
+
+ hctx->ccid3hctx_idle = 0;
+ packet->dccphtx_rtt = hctx->ccid3hctx_rtt;
+ packet->dccphtx_sent = 1;
}
static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
@@ -437,13 +411,13 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
struct ccid3_options_received *opt_recv;
struct dccp_tx_hist_entry *packet;
struct timeval now;
- unsigned long next_tmout;
+ unsigned long t_nfb;
u32 t_elapsed;
u32 pinv;
u32 x_recv;
u32 r_sample;
- BUG_ON(hctx == NULL || hctx->ccid3hctx_state == TFRC_SSTATE_TERM);
+ BUG_ON(hctx == NULL);
/* we are only interested in ACKs */
if (!(DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK ||
@@ -457,9 +431,6 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
pinv = opt_recv->ccid3or_loss_event_rate;
switch (hctx->ccid3hctx_state) {
- case TFRC_SSTATE_NO_SENT:
- /* FIXME: what to do here? */
- return;
case TFRC_SSTATE_NO_FBACK:
case TFRC_SSTATE_FBACK:
/* Calculate new round trip sample by
@@ -468,11 +439,10 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
packet = dccp_tx_hist_find_entry(&hctx->ccid3hctx_hist,
DCCP_SKB_CB(skb)->dccpd_ack_seq);
if (unlikely(packet == NULL)) {
- LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, seqno "
- "%llu(%s) does't exist in history!\n",
- __FUNCTION__, dccp_role(sk), sk,
+ DCCP_WARN("%s, sk=%p, seqno %llu(%s) does't exist "
+ "in history!\n", dccp_role(sk), sk,
(unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq,
- dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type));
+ dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type));
return;
}
@@ -480,9 +450,8 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
dccp_timestamp(sk, &now);
r_sample = timeval_delta(&now, &packet->dccphtx_tstamp);
if (unlikely(r_sample <= t_elapsed))
- LIMIT_NETDEBUG(KERN_WARNING "%s: r_sample=%uus, "
- "t_elapsed=%uus\n",
- __FUNCTION__, r_sample, t_elapsed);
+ DCCP_WARN("r_sample=%uus,t_elapsed=%uus\n",
+ r_sample, t_elapsed);
else
r_sample -= t_elapsed;
@@ -495,20 +464,26 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
* q is a constant, RFC 3448 recomments 0.9
*/
if (hctx->ccid3hctx_state == TFRC_SSTATE_NO_FBACK) {
+ /* Use Larger Initial Windows [RFC 4342, sec. 5]
+ * We deviate in that we use `s' instead of `MSS'. */
+ u16 w_init = max( 4 * hctx->ccid3hctx_s,
+ max(2 * hctx->ccid3hctx_s, 4380));
+ hctx->ccid3hctx_rtt = r_sample;
+ hctx->ccid3hctx_x = usecs_div(w_init, r_sample);
+ hctx->ccid3hctx_t_ld = now;
+
+ ccid3_update_send_time(hctx);
ccid3_hc_tx_set_state(sk, TFRC_SSTATE_FBACK);
- hctx->ccid3hctx_rtt = r_sample;
- } else
+ } else {
hctx->ccid3hctx_rtt = (hctx->ccid3hctx_rtt * 9) / 10 +
r_sample / 10;
+ ccid3_hc_tx_update_x(sk, &now);
+ }
ccid3_pr_debug("%s, sk=%p, New RTT estimate=%uus, "
"r_sample=%us\n", dccp_role(sk), sk,
hctx->ccid3hctx_rtt, r_sample);
- /* Update timeout interval */
- hctx->ccid3hctx_t_rto = max_t(u32, 4 * hctx->ccid3hctx_rtt,
- USEC_PER_SEC);
-
/* Update receive rate */
hctx->ccid3hctx_x_recv = x_recv;/* X_recv in bytes per sec */
@@ -528,49 +503,41 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
/* unschedule no feedback timer */
sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer);
- /* Update sending rate */
- ccid3_hc_tx_update_x(sk);
-
- /* Update next send time */
- timeval_sub_usecs(&hctx->ccid3hctx_t_nom,
- hctx->ccid3hctx_t_ipi);
- ccid3_calc_new_t_ipi(hctx);
- timeval_add_usecs(&hctx->ccid3hctx_t_nom,
- hctx->ccid3hctx_t_ipi);
- ccid3_calc_new_delta(hctx);
-
/* remove all packets older than the one acked from history */
dccp_tx_hist_purge_older(ccid3_tx_hist,
&hctx->ccid3hctx_hist, packet);
/*
* As we have calculated new ipi, delta, t_nom it is possible that
- * we now can send a packet, so wake up dccp_wait_for_ccids.
+ * we now can send a packet, so wake up dccp_wait_for_ccid
*/
sk->sk_write_space(sk);
+ /* Update timeout interval. We use the alternative variant of
+ * [RFC 3448, 3.1] which sets the upper bound of t_rto to one
+ * second, as it is suggested for TCP (see RFC 2988, 2.4). */
+ hctx->ccid3hctx_t_rto = max_t(u32, 4 * hctx->ccid3hctx_rtt,
+ USEC_PER_SEC );
/*
* Schedule no feedback timer to expire in
- * max(4 * R, 2 * s / X)
+ * max(4 * R, 2 * s/X) = max(4 * R, 2 * t_ipi)
*/
- next_tmout = max(hctx->ccid3hctx_t_rto,
- 2 * usecs_div(hctx->ccid3hctx_s,
- hctx->ccid3hctx_x));
+ t_nfb = max(4 * hctx->ccid3hctx_rtt, 2 * hctx->ccid3hctx_t_ipi);
ccid3_pr_debug("%s, sk=%p, Scheduled no feedback timer to "
"expire in %lu jiffies (%luus)\n",
dccp_role(sk), sk,
- usecs_to_jiffies(next_tmout), next_tmout);
+ usecs_to_jiffies(t_nfb), t_nfb);
sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
- jiffies + max_t(u32, 1, usecs_to_jiffies(next_tmout)));
+ jiffies + usecs_to_jiffies(t_nfb));
/* set idle flag */
hctx->ccid3hctx_idle = 1;
break;
- default:
- printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n",
- __FUNCTION__, dccp_role(sk), sk, hctx->ccid3hctx_state);
- dump_stack();
+ case TFRC_SSTATE_NO_SENT:
+ DCCP_WARN("Illegal ACK received - no packet has been sent\n");
+ /* fall through */
+ case TFRC_SSTATE_TERM: /* ignore feedback when closing */
break;
}
}
@@ -610,9 +577,9 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
switch (option) {
case TFRC_OPT_LOSS_EVENT_RATE:
if (unlikely(len != 4)) {
- LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, invalid "
- "len for TFRC_OPT_LOSS_EVENT_RATE\n",
- __FUNCTION__, dccp_role(sk), sk);
+ DCCP_WARN("%s, sk=%p, invalid len %d "
+ "for TFRC_OPT_LOSS_EVENT_RATE\n",
+ dccp_role(sk), sk, len);
rc = -EINVAL;
} else {
opt_recv->ccid3or_loss_event_rate = ntohl(*(__be32 *)value);
@@ -631,9 +598,9 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
break;
case TFRC_OPT_RECEIVE_RATE:
if (unlikely(len != 4)) {
- LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, invalid "
- "len for TFRC_OPT_RECEIVE_RATE\n",
- __FUNCTION__, dccp_role(sk), sk);
+ DCCP_WARN("%s, sk=%p, invalid len %d "
+ "for TFRC_OPT_RECEIVE_RATE\n",
+ dccp_role(sk), sk, len);
rc = -EINVAL;
} else {
opt_recv->ccid3or_receive_rate = ntohl(*(__be32 *)value);
@@ -649,18 +616,9 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk)
{
- struct dccp_sock *dp = dccp_sk(sk);
struct ccid3_hc_tx_sock *hctx = ccid_priv(ccid);
- if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE &&
- dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE)
- hctx->ccid3hctx_s = dp->dccps_packet_size;
- else
- hctx->ccid3hctx_s = TFRC_STD_PACKET_SIZE;
-
- /* Set transmission rate to 1 packet per second */
- hctx->ccid3hctx_x = hctx->ccid3hctx_s;
- hctx->ccid3hctx_t_rto = USEC_PER_SEC;
+ hctx->ccid3hctx_s = 0;
hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT;
INIT_LIST_HEAD(&hctx->ccid3hctx_hist);
@@ -688,14 +646,7 @@ static void ccid3_hc_tx_exit(struct sock *sk)
* RX Half Connection methods
*/
-/* TFRC receiver states */
-enum ccid3_hc_rx_states {
- TFRC_RSTATE_NO_DATA = 1,
- TFRC_RSTATE_DATA,
- TFRC_RSTATE_TERM = 127,
-};
-
-#ifdef CCID3_DEBUG
+#ifdef CONFIG_IP_DCCP_CCID3_DEBUG
static const char *ccid3_rx_state_name(enum ccid3_hc_rx_states state)
{
static char *ccid3_rx_state_names[] = {
@@ -721,6 +672,15 @@ static void ccid3_hc_rx_set_state(struct sock *sk,
hcrx->ccid3hcrx_state = state;
}
+static inline void ccid3_hc_rx_update_s(struct ccid3_hc_rx_sock *hcrx, int len)
+{
+ if (unlikely(len == 0)) /* don't update on empty packets (e.g. ACKs) */
+ ccid3_pr_debug("Packet payload length is 0 - not updating\n");
+ else
+ hcrx->ccid3hcrx_s = hcrx->ccid3hcrx_s == 0 ? len :
+ (9 * hcrx->ccid3hcrx_s + len) / 10;
+}
+
static void ccid3_hc_rx_send_feedback(struct sock *sk)
{
struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
@@ -743,18 +703,15 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk)
delta);
}
break;
- default:
- printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n",
- __FUNCTION__, dccp_role(sk), sk, hcrx->ccid3hcrx_state);
- dump_stack();
+ case TFRC_RSTATE_TERM:
+ DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk);
return;
}
packet = dccp_rx_hist_find_data_packet(&hcrx->ccid3hcrx_hist);
if (unlikely(packet == NULL)) {
- LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, no data packet "
- "in history!\n",
- __FUNCTION__, dccp_role(sk), sk);
+ DCCP_WARN("%s, sk=%p, no data packet in history!\n",
+ dccp_role(sk), sk);
return;
}
@@ -842,29 +799,29 @@ static u32 ccid3_hc_rx_calc_first_li(struct sock *sk)
}
if (unlikely(step == 0)) {
- LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, packet history "
- "contains no data packets!\n",
- __FUNCTION__, dccp_role(sk), sk);
+ DCCP_WARN("%s, sk=%p, packet history has no data packets!\n",
+ dccp_role(sk), sk);
return ~0;
}
if (unlikely(interval == 0)) {
- LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, Could not find a "
- "win_count interval > 0. Defaulting to 1\n",
- __FUNCTION__, dccp_role(sk), sk);
+ DCCP_WARN("%s, sk=%p, Could not find a win_count interval > 0."
+ "Defaulting to 1\n", dccp_role(sk), sk);
interval = 1;
}
found:
if (!tail) {
- LIMIT_NETDEBUG(KERN_WARNING "%s: tail is null\n",
- __FUNCTION__);
+ DCCP_CRIT("tail is null\n");
return ~0;
}
rtt = timeval_delta(&tstamp, &tail->dccphrx_tstamp) * 4 / interval;
ccid3_pr_debug("%s, sk=%p, approximated RTT to %uus\n",
dccp_role(sk), sk, rtt);
- if (rtt == 0)
- rtt = 1;
+
+ if (rtt == 0) {
+ DCCP_WARN("RTT==0, setting to 1\n");
+ rtt = 1;
+ }
dccp_timestamp(sk, &tstamp);
delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback);
@@ -878,9 +835,7 @@ found:
tmp2 = (u32)tmp1;
if (!tmp2) {
- LIMIT_NETDEBUG(KERN_WARNING "tmp2 = 0 "
- "%s: x_recv = %u, rtt =%u\n",
- __FUNCTION__, x_recv, rtt);
+ DCCP_CRIT("tmp2 = 0, x_recv = %u, rtt =%u\n", x_recv, rtt);
return ~0;
}
@@ -926,8 +881,7 @@ static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss)
entry = dccp_li_hist_entry_new(ccid3_li_hist, SLAB_ATOMIC);
if (entry == NULL) {
- printk(KERN_CRIT "%s: out of memory\n",__FUNCTION__);
- dump_stack();
+ DCCP_BUG("out of memory - can not allocate entry");
return;
}
@@ -1002,13 +956,10 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
const struct dccp_options_received *opt_recv;
struct dccp_rx_hist_entry *packet;
struct timeval now;
- u8 win_count;
u32 p_prev, rtt_prev, r_sample, t_elapsed;
- int loss;
+ int loss, payload_size;
- BUG_ON(hcrx == NULL ||
- !(hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA ||
- hcrx->ccid3hcrx_state == TFRC_RSTATE_DATA));
+ BUG_ON(hcrx == NULL);
opt_recv = &dccp_sk(sk)->dccps_options_received;
@@ -1026,9 +977,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
t_elapsed = opt_recv->dccpor_elapsed_time * 10;
if (unlikely(r_sample <= t_elapsed))
- LIMIT_NETDEBUG(KERN_WARNING "%s: r_sample=%uus, "
- "t_elapsed=%uus\n",
- __FUNCTION__, r_sample, t_elapsed);
+ DCCP_WARN("r_sample=%uus, t_elapsed=%uus\n",
+ r_sample, t_elapsed);
else
r_sample -= t_elapsed;
@@ -1052,19 +1002,19 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
packet = dccp_rx_hist_entry_new(ccid3_rx_hist, sk, opt_recv->dccpor_ndp,
skb, SLAB_ATOMIC);
if (unlikely(packet == NULL)) {
- LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, Not enough mem to "
- "add rx packet to history, consider it lost!\n",
- __FUNCTION__, dccp_role(sk), sk);
+ DCCP_WARN("%s, sk=%p, Not enough mem to add rx packet "
+ "to history, consider it lost!\n", dccp_role(sk), sk);
return;
}
- win_count = packet->dccphrx_ccval;
-
loss = ccid3_hc_rx_detect_loss(sk, packet);
if (DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK)
return;
+ payload_size = skb->len - dccp_hdr(skb)->dccph_doff * 4;
+ ccid3_hc_rx_update_s(hcrx, payload_size);
+
switch (hcrx->ccid3hcrx_state) {
case TFRC_RSTATE_NO_DATA:
ccid3_pr_debug("%s, sk=%p(%s), skb=%p, sending initial "
@@ -1075,8 +1025,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
ccid3_hc_rx_set_state(sk, TFRC_RSTATE_DATA);
return;
case TFRC_RSTATE_DATA:
- hcrx->ccid3hcrx_bytes_recv += skb->len -
- dccp_hdr(skb)->dccph_doff * 4;
+ hcrx->ccid3hcrx_bytes_recv += payload_size;
if (loss)
break;
@@ -1087,10 +1036,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
ccid3_hc_rx_send_feedback(sk);
}
return;
- default:
- printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n",
- __FUNCTION__, dccp_role(sk), sk, hcrx->ccid3hcrx_state);
- dump_stack();
+ case TFRC_RSTATE_TERM:
+ DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk);
return;
}
@@ -1107,10 +1054,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
/* Scaling up by 1000000 as fixed decimal */
if (i_mean != 0)
hcrx->ccid3hcrx_p = 1000000 / i_mean;
- } else {
- printk(KERN_CRIT "%s: empty loss hist\n",__FUNCTION__);
- dump_stack();
- }
+ } else
+ DCCP_BUG("empty loss history");
if (hcrx->ccid3hcrx_p > p_prev) {
ccid3_hc_rx_send_feedback(sk);
@@ -1120,22 +1065,16 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk)
{
- struct dccp_sock *dp = dccp_sk(sk);
struct ccid3_hc_rx_sock *hcrx = ccid_priv(ccid);
ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
- if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE &&
- dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE)
- hcrx->ccid3hcrx_s = dp->dccps_packet_size;
- else
- hcrx->ccid3hcrx_s = TFRC_STD_PACKET_SIZE;
-
hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA;
INIT_LIST_HEAD(&hcrx->ccid3hcrx_hist);
INIT_LIST_HEAD(&hcrx->ccid3hcrx_li_hist);
dccp_timestamp(sk, &hcrx->ccid3hcrx_tstamp_last_ack);
hcrx->ccid3hcrx_tstamp_last_feedback = hcrx->ccid3hcrx_tstamp_last_ack;
+ hcrx->ccid3hcrx_s = 0;
hcrx->ccid3hcrx_rtt = 5000; /* XXX 5ms for now... */
return 0;
}
@@ -1261,8 +1200,10 @@ static struct ccid_operations ccid3 = {
.ccid_hc_tx_getsockopt = ccid3_hc_tx_getsockopt,
};
+#ifdef CONFIG_IP_DCCP_CCID3_DEBUG
module_param(ccid3_debug, int, 0444);
MODULE_PARM_DESC(ccid3_debug, "Enable debug messages");
+#endif
static __init int ccid3_module_init(void)
{
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h
index 0a2cb7536d26..27cb20ae1da8 100644
--- a/net/dccp/ccids/ccid3.h
+++ b/net/dccp/ccids/ccid3.h
@@ -42,20 +42,14 @@
#include <linux/tfrc.h>
#include "../ccid.h"
-#define TFRC_MIN_PACKET_SIZE 16
-#define TFRC_STD_PACKET_SIZE 256
-#define TFRC_MAX_PACKET_SIZE 65535
-
-/* Two seconds as per CCID3 spec */
+/* Two seconds as per RFC 3448 4.2 */
#define TFRC_INITIAL_TIMEOUT (2 * USEC_PER_SEC)
-#define TFRC_INITIAL_IPI (USEC_PER_SEC / 4)
-
/* In usecs - half the scheduling granularity as per RFC3448 4.6 */
#define TFRC_OPSYS_HALF_TIME_GRAN (USEC_PER_SEC / (2 * HZ))
-/* In seconds */
-#define TFRC_MAX_BACK_OFF_TIME 64
+/* Parameter t_mbi from [RFC 3448, 4.3]: backoff interval in seconds */
+#define TFRC_T_MBI 64
#define TFRC_SMALLEST_P 40
@@ -73,26 +67,36 @@ struct ccid3_options_received {
u32 ccid3or_receive_rate;
};
-/** struct ccid3_hc_tx_sock - CCID3 sender half connection sock
+/* TFRC sender states */
+enum ccid3_hc_tx_states {
+ TFRC_SSTATE_NO_SENT = 1,
+ TFRC_SSTATE_NO_FBACK,
+ TFRC_SSTATE_FBACK,
+ TFRC_SSTATE_TERM,
+};
+
+/** struct ccid3_hc_tx_sock - CCID3 sender half-connection socket
*
- * @ccid3hctx_state - Sender state
- * @ccid3hctx_x - Current sending rate
- * @ccid3hctx_x_recv - Receive rate
- * @ccid3hctx_x_calc - Calculated send (?) rate
- * @ccid3hctx_s - Packet size
- * @ccid3hctx_rtt - Estimate of current round trip time in usecs
- * @@ccid3hctx_p - Current loss event rate (0-1) scaled by 1000000
- * @ccid3hctx_last_win_count - Last window counter sent
- * @ccid3hctx_t_last_win_count - Timestamp of earliest packet
- * with last_win_count value sent
- * @ccid3hctx_no_feedback_timer - Handle to no feedback timer
- * @ccid3hctx_idle - FIXME
- * @ccid3hctx_t_ld - Time last doubled during slow start
- * @ccid3hctx_t_nom - Nominal send time of next packet
- * @ccid3hctx_t_ipi - Interpacket (send) interval
- * @ccid3hctx_delta - Send timer delta
- * @ccid3hctx_hist - Packet history
- */
+ * @ccid3hctx_x - Current sending rate
+ * @ccid3hctx_x_recv - Receive rate
+ * @ccid3hctx_x_calc - Calculated send rate (RFC 3448, 3.1)
+ * @ccid3hctx_rtt - Estimate of current round trip time in usecs
+ * @ccid3hctx_p - Current loss event rate (0-1) scaled by 1000000
+ * @ccid3hctx_s - Packet size
+ * @ccid3hctx_t_rto - Retransmission Timeout (RFC 3448, 3.1)
+ * @ccid3hctx_t_ipi - Interpacket (send) interval (RFC 3448, 4.6)
+ * @ccid3hctx_state - Sender state, one of %ccid3_hc_tx_states
+ * @ccid3hctx_last_win_count - Last window counter sent
+ * @ccid3hctx_t_last_win_count - Timestamp of earliest packet
+ * with last_win_count value sent
+ * @ccid3hctx_no_feedback_timer - Handle to no feedback timer
+ * @ccid3hctx_idle - Flag indicating that sender is idling
+ * @ccid3hctx_t_ld - Time last doubled during slow start
+ * @ccid3hctx_t_nom - Nominal send time of next packet
+ * @ccid3hctx_delta - Send timer delta
+ * @ccid3hctx_hist - Packet history
+ * @ccid3hctx_options_received - Parsed set of retrieved options
+ */
struct ccid3_hc_tx_sock {
struct tfrc_tx_info ccid3hctx_tfrc;
#define ccid3hctx_x ccid3hctx_tfrc.tfrctx_x
@@ -103,7 +107,7 @@ struct ccid3_hc_tx_sock {
#define ccid3hctx_t_rto ccid3hctx_tfrc.tfrctx_rto
#define ccid3hctx_t_ipi ccid3hctx_tfrc.tfrctx_ipi
u16 ccid3hctx_s;
- u8 ccid3hctx_state;
+ enum ccid3_hc_tx_states ccid3hctx_state:8;
u8 ccid3hctx_last_win_count;
u8 ccid3hctx_idle;
struct timeval ccid3hctx_t_last_win_count;
@@ -115,23 +119,48 @@ struct ccid3_hc_tx_sock {
struct ccid3_options_received ccid3hctx_options_received;
};
+/* TFRC receiver states */
+enum ccid3_hc_rx_states {
+ TFRC_RSTATE_NO_DATA = 1,
+ TFRC_RSTATE_DATA,
+ TFRC_RSTATE_TERM = 127,
+};
+
+/** struct ccid3_hc_rx_sock - CCID3 receiver half-connection socket
+ *
+ * @ccid3hcrx_x_recv - Receiver estimate of send rate (RFC 3448 4.3)
+ * @ccid3hcrx_rtt - Receiver estimate of rtt (non-standard)
+ * @ccid3hcrx_p - current loss event rate (RFC 3448 5.4)
+ * @ccid3hcrx_seqno_nonloss - Last received non-loss sequence number
+ * @ccid3hcrx_ccval_nonloss - Last received non-loss Window CCVal
+ * @ccid3hcrx_ccval_last_counter - Tracks window counter (RFC 4342, 8.1)
+ * @ccid3hcrx_state - receiver state, one of %ccid3_hc_rx_states
+ * @ccid3hcrx_bytes_recv - Total sum of DCCP payload bytes
+ * @ccid3hcrx_tstamp_last_feedback - Time at which last feedback was sent
+ * @ccid3hcrx_tstamp_last_ack - Time at which last feedback was sent
+ * @ccid3hcrx_hist - Packet history
+ * @ccid3hcrx_li_hist - Loss Interval History
+ * @ccid3hcrx_s - Received packet size in bytes
+ * @ccid3hcrx_pinv - Inverse of Loss Event Rate (RFC 4342, sec. 8.5)
+ * @ccid3hcrx_elapsed_time - Time since packet reception
+ */
struct ccid3_hc_rx_sock {
- struct tfrc_rx_info ccid3hcrx_tfrc;
-#define ccid3hcrx_x_recv ccid3hcrx_tfrc.tfrcrx_x_recv
-#define ccid3hcrx_rtt ccid3hcrx_tfrc.tfrcrx_rtt
-#define ccid3hcrx_p ccid3hcrx_tfrc.tfrcrx_p
- u64 ccid3hcrx_seqno_nonloss:48,
- ccid3hcrx_ccval_nonloss:4,
- ccid3hcrx_state:8,
- ccid3hcrx_ccval_last_counter:4;
- u32 ccid3hcrx_bytes_recv;
- struct timeval ccid3hcrx_tstamp_last_feedback;
- struct timeval ccid3hcrx_tstamp_last_ack;
- struct list_head ccid3hcrx_hist;
- struct list_head ccid3hcrx_li_hist;
- u16 ccid3hcrx_s;
- u32 ccid3hcrx_pinv;
- u32 ccid3hcrx_elapsed_time;
+ struct tfrc_rx_info ccid3hcrx_tfrc;
+#define ccid3hcrx_x_recv ccid3hcrx_tfrc.tfrcrx_x_recv
+#define ccid3hcrx_rtt ccid3hcrx_tfrc.tfrcrx_rtt
+#define ccid3hcrx_p ccid3hcrx_tfrc.tfrcrx_p
+ u64 ccid3hcrx_seqno_nonloss:48,
+ ccid3hcrx_ccval_nonloss:4,
+ ccid3hcrx_ccval_last_counter:4;
+ enum ccid3_hc_rx_states ccid3hcrx_state:8;
+ u32 ccid3hcrx_bytes_recv;
+ struct timeval ccid3hcrx_tstamp_last_feedback;
+ struct timeval ccid3hcrx_tstamp_last_ack;
+ struct list_head ccid3hcrx_hist;
+ struct list_head ccid3hcrx_li_hist;
+ u16 ccid3hcrx_s;
+ u32 ccid3hcrx_pinv;
+ u32 ccid3hcrx_elapsed_time;
};
static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk)
diff --git a/net/dccp/ccids/lib/loss_interval.c b/net/dccp/ccids/lib/loss_interval.c
index 906c81ab9d4f..48b9b93f8acb 100644
--- a/net/dccp/ccids/lib/loss_interval.c
+++ b/net/dccp/ccids/lib/loss_interval.c
@@ -13,7 +13,7 @@
#include <linux/module.h>
#include <net/sock.h>
-
+#include "../../dccp.h"
#include "loss_interval.h"
struct dccp_li_hist *dccp_li_hist_new(const char *name)
@@ -109,7 +109,7 @@ u32 dccp_li_hist_calc_i_mean(struct list_head *list)
i_tot = max(i_tot0, i_tot1);
if (!w_tot) {
- LIMIT_NETDEBUG(KERN_WARNING "%s: w_tot = 0\n", __FUNCTION__);
+ DCCP_WARN("w_tot = 0\n");
return 1;
}
@@ -128,7 +128,7 @@ int dccp_li_hist_interval_new(struct dccp_li_hist *hist,
entry = dccp_li_hist_entry_new(hist, SLAB_ATOMIC);
if (entry == NULL) {
dccp_li_hist_purge(hist, list);
- dump_stack();
+ DCCP_BUG("loss interval list entry is NULL");
return 0;
}
entry->dccplih_interval = ~0;
diff --git a/net/dccp/ccids/lib/tfrc_equation.c b/net/dccp/ccids/lib/tfrc_equation.c
index 44076e0c6591..2601012383fb 100644
--- a/net/dccp/ccids/lib/tfrc_equation.c
+++ b/net/dccp/ccids/lib/tfrc_equation.c
@@ -13,9 +13,8 @@
*/
#include <linux/module.h>
-
#include <asm/div64.h>
-
+#include "../../dccp.h"
#include "tfrc.h"
#define TFRC_CALC_X_ARRSIZE 500
@@ -588,8 +587,10 @@ u32 tfrc_calc_x(u16 s, u32 R, u32 p)
/* p should be 0 unless there is a bug in my code */
index = 0;
- if (R == 0)
+ if (R == 0) {
+ DCCP_WARN("RTT==0, setting to 1\n");
R = 1; /* RTT can't be zero or else divide by zero */
+ }
BUG_ON(index >= TFRC_CALC_X_ARRSIZE);
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index 272e8584564e..68886986c8e4 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -18,15 +18,33 @@
#include <net/tcp.h>
#include "ackvec.h"
+/*
+ * DCCP - specific warning and debugging macros.
+ */
+#define DCCP_WARN(fmt, a...) LIMIT_NETDEBUG(KERN_WARNING "%s: " fmt, \
+ __FUNCTION__, ##a)
+#define DCCP_CRIT(fmt, a...) printk(KERN_CRIT fmt " at %s:%d/%s()\n", ##a, \
+ __FILE__, __LINE__, __FUNCTION__)
+#define DCCP_BUG(a...) do { DCCP_CRIT("BUG: " a); dump_stack(); } while(0)
+#define DCCP_BUG_ON(cond) do { if (unlikely((cond) != 0)) \
+ DCCP_BUG("\"%s\" holds (exception!)", \
+ __stringify(cond)); \
+ } while (0)
+
+#ifdef MODULE
+#define DCCP_PRINTK(enable, fmt, args...) do { if (enable) \
+ printk(fmt, ##args); \
+ } while(0)
+#else
+#define DCCP_PRINTK(enable, fmt, args...) printk(fmt, ##args)
+#endif
+#define DCCP_PR_DEBUG(enable, fmt, a...) DCCP_PRINTK(enable, KERN_DEBUG \
+ "%s: " fmt, __FUNCTION__, ##a)
+
#ifdef CONFIG_IP_DCCP_DEBUG
extern int dccp_debug;
-
-#define dccp_pr_debug(format, a...) \
- do { if (dccp_debug) \
- printk(KERN_DEBUG "%s: " format, __FUNCTION__ , ##a); \
- } while (0)
-#define dccp_pr_debug_cat(format, a...) do { if (dccp_debug) \
- printk(format, ##a); } while (0)
+#define dccp_pr_debug(format, a...) DCCP_PR_DEBUG(dccp_debug, format, ##a)
+#define dccp_pr_debug_cat(format, a...) DCCP_PRINTK(dccp_debug, format, ##a)
#else
#define dccp_pr_debug(format, a...)
#define dccp_pr_debug_cat(format, a...)
@@ -35,17 +53,21 @@ extern int dccp_debug;
extern struct inet_hashinfo dccp_hashinfo;
extern atomic_t dccp_orphan_count;
-extern int dccp_tw_count;
-extern void dccp_tw_deschedule(struct inet_timewait_sock *tw);
extern void dccp_time_wait(struct sock *sk, int state, int timeo);
-/* FIXME: Right size this */
-#define DCCP_MAX_OPT_LEN 128
-
-#define DCCP_MAX_PACKET_HDR 32
-
-#define MAX_DCCP_HEADER (DCCP_MAX_PACKET_HDR + DCCP_MAX_OPT_LEN + MAX_HEADER)
+/*
+ * Set safe upper bounds for header and option length. Since Data Offset is 8
+ * bits (RFC 4340, sec. 5.1), the total header length can never be more than
+ * 4 * 255 = 1020 bytes. The largest possible header length is 28 bytes (X=1):
+ * - DCCP-Response with ACK Subheader and 4 bytes of Service code OR
+ * - DCCP-Reset with ACK Subheader and 4 bytes of Reset Code fields
+ * Hence a safe upper bound for the maximum option length is 1020-28 = 992
+ */
+#define MAX_DCCP_SPECIFIC_HEADER (255 * sizeof(int))
+#define DCCP_MAX_PACKET_HDR 28
+#define DCCP_MAX_OPT_LEN (MAX_DCCP_SPECIFIC_HEADER - DCCP_MAX_PACKET_HDR)
+#define MAX_DCCP_HEADER (MAX_DCCP_SPECIFIC_HEADER + MAX_HEADER)
#define DCCP_TIMEWAIT_LEN (60 * HZ) /* how long to wait to destroy TIME-WAIT
* state, about 60 seconds */
@@ -58,6 +80,20 @@ extern void dccp_time_wait(struct sock *sk, int state, int timeo);
#define DCCP_RTO_MAX ((unsigned)(120 * HZ)) /* FIXME: using TCP value */
+#define DCCP_XMIT_TIMEO 30000 /* Time/msecs for blocking transmit per packet */
+
+/* sysctl variables for DCCP */
+extern int sysctl_dccp_request_retries;
+extern int sysctl_dccp_retries1;
+extern int sysctl_dccp_retries2;
+extern int sysctl_dccp_feat_sequence_window;
+extern int sysctl_dccp_feat_rx_ccid;
+extern int sysctl_dccp_feat_tx_ccid;
+extern int sysctl_dccp_feat_ack_ratio;
+extern int sysctl_dccp_feat_send_ack_vector;
+extern int sysctl_dccp_feat_send_ndp_count;
+extern int sysctl_dccp_tx_qlen;
+
/* is seq1 < seq2 ? */
static inline int before48(const u64 seq1, const u64 seq2)
{
@@ -123,10 +159,36 @@ DECLARE_SNMP_STAT(struct dccp_mib, dccp_statistics);
#define DCCP_ADD_STATS_USER(field, val) \
SNMP_ADD_STATS_USER(dccp_statistics, field, val)
+/*
+ * Checksumming routines
+ */
+static inline int dccp_csum_coverage(const struct sk_buff *skb)
+{
+ const struct dccp_hdr* dh = dccp_hdr(skb);
+
+ if (dh->dccph_cscov == 0)
+ return skb->len;
+ return (dh->dccph_doff + dh->dccph_cscov - 1) * sizeof(u32);
+}
+
+static inline void dccp_csum_outgoing(struct sk_buff *skb)
+{
+ int cov = dccp_csum_coverage(skb);
+
+ if (cov >= skb->len)
+ dccp_hdr(skb)->dccph_cscov = 0;
+
+ skb->csum = skb_checksum(skb, 0, (cov > skb->len)? skb->len : cov, 0);
+}
+
+extern void dccp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb);
+
extern int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb);
extern void dccp_send_ack(struct sock *sk);
extern void dccp_send_delayed_ack(struct sock *sk);
+extern void dccp_reqsk_send_ack(struct sk_buff *sk, struct request_sock *rsk);
+
extern void dccp_send_sync(struct sock *sk, const u64 seq,
const enum dccp_pkt_type pkt_type);
@@ -147,18 +209,7 @@ extern const char *dccp_state_name(const int state);
extern void dccp_set_state(struct sock *sk, const int state);
extern void dccp_done(struct sock *sk);
-static inline void dccp_openreq_init(struct request_sock *req,
- struct dccp_sock *dp,
- struct sk_buff *skb)
-{
- /*
- * FIXME: fill in the other req fields from the DCCP options
- * received
- */
- inet_rsk(req)->rmt_port = dccp_hdr(skb)->dccph_sport;
- inet_rsk(req)->acked = 0;
- req->rcv_wnd = 0;
-}
+extern void dccp_reqsk_init(struct request_sock *req, struct sk_buff *skb);
extern int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb);
@@ -217,14 +268,9 @@ extern void dccp_shutdown(struct sock *sk, int how);
extern int inet_dccp_listen(struct socket *sock, int backlog);
extern unsigned int dccp_poll(struct file *file, struct socket *sock,
poll_table *wait);
-extern void dccp_v4_send_check(struct sock *sk, int len,
- struct sk_buff *skb);
extern int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr,
int addr_len);
-extern int dccp_v4_checksum(const struct sk_buff *skb,
- const __be32 saddr, const __be32 daddr);
-
extern int dccp_send_reset(struct sock *sk, enum dccp_reset_codes code);
extern void dccp_send_close(struct sock *sk, const int active);
extern int dccp_invalid_packet(struct sk_buff *skb);
diff --git a/net/dccp/feat.c b/net/dccp/feat.c
index a1b0682ee77c..4dc487f27a1f 100644
--- a/net/dccp/feat.c
+++ b/net/dccp/feat.c
@@ -12,7 +12,6 @@
#include <linux/module.h>
-#include "dccp.h"
#include "ccid.h"
#include "feat.h"
@@ -23,9 +22,17 @@ int dccp_feat_change(struct dccp_minisock *dmsk, u8 type, u8 feature,
{
struct dccp_opt_pend *opt;
- dccp_pr_debug("feat change type=%d feat=%d\n", type, feature);
+ dccp_feat_debug(type, feature, *val);
- /* XXX sanity check feat change request */
+ if (!dccp_feat_is_valid_type(type)) {
+ DCCP_WARN("option type %d invalid in negotiation\n", type);
+ return 1;
+ }
+ if (!dccp_feat_is_valid_length(type, feature, len)) {
+ DCCP_WARN("invalid length %d\n", len);
+ return 1;
+ }
+ /* XXX add further sanity checks */
/* check if that feature is already being negotiated */
list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) {
@@ -95,14 +102,14 @@ static int dccp_feat_update_ccid(struct sock *sk, u8 type, u8 new_ccid_nr)
/* XXX taking only u8 vals */
static int dccp_feat_update(struct sock *sk, u8 type, u8 feat, u8 val)
{
- dccp_pr_debug("changing [%d] feat %d to %d\n", type, feat, val);
+ dccp_feat_debug(type, feat, val);
switch (feat) {
case DCCPF_CCID:
return dccp_feat_update_ccid(sk, type, val);
default:
- dccp_pr_debug("IMPLEMENT changing [%d] feat %d to %d\n",
- type, feat, val);
+ dccp_pr_debug("UNIMPLEMENTED: %s(%d, ...)\n",
+ dccp_feat_typename(type), feat);
break;
}
return 0;
@@ -162,7 +169,8 @@ static int dccp_feat_reconcile(struct sock *sk, struct dccp_opt_pend *opt,
break;
default:
- WARN_ON(1); /* XXX implement res */
+ DCCP_BUG("Fell through, feat=%d", opt->dccpop_feat);
+ /* XXX implement res */
return -EFAULT;
}
@@ -265,10 +273,10 @@ static int dccp_feat_nn(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len)
u8 *copy;
int rc;
- /* NN features must be change L */
- if (type == DCCPO_CHANGE_R) {
- dccp_pr_debug("received CHANGE_R %d for NN feat %d\n",
- type, feature);
+ /* NN features must be Change L (sec. 6.3.2) */
+ if (type != DCCPO_CHANGE_L) {
+ dccp_pr_debug("received %s for NN feature %d\n",
+ dccp_feat_typename(type), feature);
return -EFAULT;
}
@@ -279,12 +287,11 @@ static int dccp_feat_nn(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len)
if (opt == NULL)
return -ENOMEM;
- copy = kmalloc(len, GFP_ATOMIC);
+ copy = kmemdup(val, len, GFP_ATOMIC);
if (copy == NULL) {
kfree(opt);
return -ENOMEM;
}
- memcpy(copy, val, len);
opt->dccpop_type = DCCPO_CONFIRM_R; /* NN can only confirm R */
opt->dccpop_feat = feature;
@@ -299,7 +306,8 @@ static int dccp_feat_nn(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len)
return rc;
}
- dccp_pr_debug("Confirming NN feature %d (val=%d)\n", feature, *copy);
+ dccp_feat_debug(type, feature, *copy);
+
list_add_tail(&opt->dccpop_node, &dmsk->dccpms_conf);
return 0;
@@ -318,14 +326,19 @@ static void dccp_feat_empty_confirm(struct dccp_minisock *dmsk,
return;
}
- opt->dccpop_type = type == DCCPO_CHANGE_L ? DCCPO_CONFIRM_R :
- DCCPO_CONFIRM_L;
+ switch (type) {
+ case DCCPO_CHANGE_L: opt->dccpop_type = DCCPO_CONFIRM_R; break;
+ case DCCPO_CHANGE_R: opt->dccpop_type = DCCPO_CONFIRM_L; break;
+ default: DCCP_WARN("invalid type %d\n", type); return;
+
+ }
opt->dccpop_feat = feature;
opt->dccpop_val = NULL;
opt->dccpop_len = 0;
/* change feature */
- dccp_pr_debug("Empty confirm feature %d type %d\n", feature, type);
+ dccp_pr_debug("Empty %s(%d)\n", dccp_feat_typename(type), feature);
+
list_add_tail(&opt->dccpop_node, &dmsk->dccpms_conf);
}
@@ -359,7 +372,7 @@ int dccp_feat_change_recv(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len)
{
int rc;
- dccp_pr_debug("got feat change type=%d feat=%d\n", type, feature);
+ dccp_feat_debug(type, feature, *val);
/* figure out if it's SP or NN feature */
switch (feature) {
@@ -375,6 +388,8 @@ int dccp_feat_change_recv(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len)
/* XXX implement other features */
default:
+ dccp_pr_debug("UNIMPLEMENTED: not handling %s(%d, ...)\n",
+ dccp_feat_typename(type), feature);
rc = -EFAULT;
break;
}
@@ -403,20 +418,27 @@ int dccp_feat_confirm_recv(struct sock *sk, u8 type, u8 feature,
u8 t;
struct dccp_opt_pend *opt;
struct dccp_minisock *dmsk = dccp_msk(sk);
- int rc = 1;
+ int found = 0;
int all_confirmed = 1;
- dccp_pr_debug("got feat confirm type=%d feat=%d\n", type, feature);
-
- /* XXX sanity check type & feat */
+ dccp_feat_debug(type, feature, *val);
/* locate our change request */
- t = type == DCCPO_CONFIRM_L ? DCCPO_CHANGE_R : DCCPO_CHANGE_L;
+ switch (type) {
+ case DCCPO_CONFIRM_L: t = DCCPO_CHANGE_R; break;
+ case DCCPO_CONFIRM_R: t = DCCPO_CHANGE_L; break;
+ default: DCCP_WARN("invalid type %d\n", type);
+ return 1;
+
+ }
+ /* XXX sanity check feature value */
list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) {
if (!opt->dccpop_conf && opt->dccpop_type == t &&
opt->dccpop_feat == feature) {
- /* we found it */
+ found = 1;
+ dccp_pr_debug("feature %d found\n", opt->dccpop_feat);
+
/* XXX do sanity check */
opt->dccpop_conf = 1;
@@ -425,9 +447,7 @@ int dccp_feat_confirm_recv(struct sock *sk, u8 type, u8 feature,
dccp_feat_update(sk, opt->dccpop_type,
opt->dccpop_feat, *val);
- dccp_pr_debug("feat %d type %d confirmed %d\n",
- feature, type, *val);
- rc = 0;
+ /* XXX check the return value of dccp_feat_update */
break;
}
@@ -446,9 +466,9 @@ int dccp_feat_confirm_recv(struct sock *sk, u8 type, u8 feature,
inet_csk_clear_xmit_timer(sk, ICSK_TIME_RETRANS);
}
- if (rc)
- dccp_pr_debug("feat %d type %d never requested\n",
- feature, type);
+ if (!found)
+ dccp_pr_debug("%s(%d, ...) never requested\n",
+ dccp_feat_typename(type), feature);
return 0;
}
@@ -501,20 +521,18 @@ int dccp_feat_clone(struct sock *oldsk, struct sock *newsk)
list_for_each_entry(opt, &olddmsk->dccpms_pending, dccpop_node) {
struct dccp_opt_pend *newopt;
/* copy the value of the option */
- u8 *val = kmalloc(opt->dccpop_len, GFP_ATOMIC);
+ u8 *val = kmemdup(opt->dccpop_val, opt->dccpop_len, GFP_ATOMIC);
if (val == NULL)
goto out_clean;
- memcpy(val, opt->dccpop_val, opt->dccpop_len);
- newopt = kmalloc(sizeof(*newopt), GFP_ATOMIC);
+ newopt = kmemdup(opt, sizeof(*newopt), GFP_ATOMIC);
if (newopt == NULL) {
kfree(val);
goto out_clean;
}
/* insert the option */
- memcpy(newopt, opt, sizeof(*newopt));
newopt->dccpop_val = val;
list_add_tail(&newopt->dccpop_node, &newdmsk->dccpms_pending);
@@ -545,10 +563,9 @@ static int __dccp_feat_init(struct dccp_minisock *dmsk, u8 type, u8 feat,
u8 *val, u8 len)
{
int rc = -ENOMEM;
- u8 *copy = kmalloc(len, GFP_KERNEL);
+ u8 *copy = kmemdup(val, len, GFP_KERNEL);
if (copy != NULL) {
- memcpy(copy, val, len);
rc = dccp_feat_change(dmsk, type, feat, copy, len, GFP_KERNEL);
if (rc)
kfree(copy);
@@ -583,3 +600,45 @@ out:
}
EXPORT_SYMBOL_GPL(dccp_feat_init);
+
+#ifdef CONFIG_IP_DCCP_DEBUG
+const char *dccp_feat_typename(const u8 type)
+{
+ switch(type) {
+ case DCCPO_CHANGE_L: return("ChangeL");
+ case DCCPO_CONFIRM_L: return("ConfirmL");
+ case DCCPO_CHANGE_R: return("ChangeR");
+ case DCCPO_CONFIRM_R: return("ConfirmR");
+ /* the following case must not appear in feature negotation */
+ default: dccp_pr_debug("unknown type %d [BUG!]\n", type);
+ }
+ return NULL;
+}
+
+EXPORT_SYMBOL_GPL(dccp_feat_typename);
+
+const char *dccp_feat_name(const u8 feat)
+{
+ static const char *feature_names[] = {
+ [DCCPF_RESERVED] = "Reserved",
+ [DCCPF_CCID] = "CCID",
+ [DCCPF_SHORT_SEQNOS] = "Allow Short Seqnos",
+ [DCCPF_SEQUENCE_WINDOW] = "Sequence Window",
+ [DCCPF_ECN_INCAPABLE] = "ECN Incapable",
+ [DCCPF_ACK_RATIO] = "Ack Ratio",
+ [DCCPF_SEND_ACK_VECTOR] = "Send ACK Vector",
+ [DCCPF_SEND_NDP_COUNT] = "Send NDP Count",
+ [DCCPF_MIN_CSUM_COVER] = "Min. Csum Coverage",
+ [DCCPF_DATA_CHECKSUM] = "Send Data Checksum",
+ };
+ if (feat >= DCCPF_MIN_CCID_SPECIFIC)
+ return "CCID-specific";
+
+ if (dccp_feat_is_reserved(feat))
+ return feature_names[DCCPF_RESERVED];
+
+ return feature_names[feat];
+}
+
+EXPORT_SYMBOL_GPL(dccp_feat_name);
+#endif /* CONFIG_IP_DCCP_DEBUG */
diff --git a/net/dccp/feat.h b/net/dccp/feat.h
index cee553d416ca..2c373ad7edcf 100644
--- a/net/dccp/feat.h
+++ b/net/dccp/feat.h
@@ -12,9 +12,46 @@
*/
#include <linux/types.h>
+#include "dccp.h"
-struct sock;
-struct dccp_minisock;
+static inline int dccp_feat_is_valid_length(u8 type, u8 feature, u8 len)
+{
+ /* sec. 6.1: Confirm has at least length 3,
+ * sec. 6.2: Change has at least length 4 */
+ if (len < 3)
+ return 1;
+ if (len < 4 && (type == DCCPO_CHANGE_L || type == DCCPO_CHANGE_R))
+ return 1;
+ /* XXX: add per-feature length validation (sec. 6.6.8) */
+ return 0;
+}
+
+static inline int dccp_feat_is_reserved(const u8 feat)
+{
+ return (feat > DCCPF_DATA_CHECKSUM &&
+ feat < DCCPF_MIN_CCID_SPECIFIC) ||
+ feat == DCCPF_RESERVED;
+}
+
+/* feature negotiation knows only these four option types (RFC 4340, sec. 6) */
+static inline int dccp_feat_is_valid_type(const u8 optnum)
+{
+ return optnum >= DCCPO_CHANGE_L && optnum <= DCCPO_CONFIRM_R;
+
+}
+
+#ifdef CONFIG_IP_DCCP_DEBUG
+extern const char *dccp_feat_typename(const u8 type);
+extern const char *dccp_feat_name(const u8 feat);
+
+static inline void dccp_feat_debug(const u8 type, const u8 feat, const u8 val)
+{
+ dccp_pr_debug("%s(%s (%d), %d)\n", dccp_feat_typename(type),
+ dccp_feat_name(feat), feat, val);
+}
+#else
+#define dccp_feat_debug(type, feat, val)
+#endif /* CONFIG_IP_DCCP_DEBUG */
extern int dccp_feat_change(struct dccp_minisock *dmsk, u8 type, u8 feature,
u8 *val, u8 len, gfp_t gfp);
@@ -26,11 +63,4 @@ extern void dccp_feat_clean(struct dccp_minisock *dmsk);
extern int dccp_feat_clone(struct sock *oldsk, struct sock *newsk);
extern int dccp_feat_init(struct dccp_minisock *dmsk);
-extern int dccp_feat_default_sequence_window;
-extern int dccp_feat_default_rx_ccid;
-extern int dccp_feat_default_tx_ccid;
-extern int dccp_feat_default_ack_ratio;
-extern int dccp_feat_default_send_ack_vector;
-extern int dccp_feat_default_send_ndp_count;
-
#endif /* _DCCP_FEAT_H */
diff --git a/net/dccp/input.c b/net/dccp/input.c
index 1d24881ac0ab..7371a2f3acf4 100644
--- a/net/dccp/input.c
+++ b/net/dccp/input.c
@@ -128,21 +128,18 @@ static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb)
DCCP_PKT_WITHOUT_ACK_SEQ))
dp->dccps_gar = DCCP_SKB_CB(skb)->dccpd_ack_seq;
} else {
- LIMIT_NETDEBUG(KERN_WARNING "DCCP: Step 6 failed for %s packet, "
- "(LSWL(%llu) <= P.seqno(%llu) <= S.SWH(%llu)) and "
- "(P.ackno %s or LAWL(%llu) <= P.ackno(%llu) <= S.AWH(%llu), "
- "sending SYNC...\n",
- dccp_packet_name(dh->dccph_type),
- (unsigned long long) lswl,
- (unsigned long long)
- DCCP_SKB_CB(skb)->dccpd_seq,
- (unsigned long long) dp->dccps_swh,
- (DCCP_SKB_CB(skb)->dccpd_ack_seq ==
+ DCCP_WARN("DCCP: Step 6 failed for %s packet, "
+ "(LSWL(%llu) <= P.seqno(%llu) <= S.SWH(%llu)) and "
+ "(P.ackno %s or LAWL(%llu) <= P.ackno(%llu) <= S.AWH(%llu), "
+ "sending SYNC...\n", dccp_packet_name(dh->dccph_type),
+ (unsigned long long) lswl,
+ (unsigned long long) DCCP_SKB_CB(skb)->dccpd_seq,
+ (unsigned long long) dp->dccps_swh,
+ (DCCP_SKB_CB(skb)->dccpd_ack_seq ==
DCCP_PKT_WITHOUT_ACK_SEQ) ? "doesn't exist" : "exists",
- (unsigned long long) lawl,
- (unsigned long long)
- DCCP_SKB_CB(skb)->dccpd_ack_seq,
- (unsigned long long) dp->dccps_awh);
+ (unsigned long long) lawl,
+ (unsigned long long) DCCP_SKB_CB(skb)->dccpd_ack_seq,
+ (unsigned long long) dp->dccps_awh);
dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq, DCCP_PKT_SYNC);
return -1;
}
@@ -431,29 +428,25 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
/*
* Step 3: Process LISTEN state
- * (Continuing from dccp_v4_do_rcv and dccp_v6_do_rcv)
*
* If S.state == LISTEN,
- * If P.type == Request or P contains a valid Init Cookie
- * option,
- * * Must scan the packet's options to check for an Init
- * Cookie. Only the Init Cookie is processed here,
- * however; other options are processed in Step 8. This
- * scan need only be performed if the endpoint uses Init
- * Cookies *
- * * Generate a new socket and switch to that socket *
- * Set S := new socket for this port pair
- * S.state = RESPOND
- * Choose S.ISS (initial seqno) or set from Init Cookie
- * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie
- * Continue with S.state == RESPOND
- * * A Response packet will be generated in Step 11 *
- * Otherwise,
- * Generate Reset(No Connection) unless P.type == Reset
- * Drop packet and return
- *
- * NOTE: the check for the packet types is done in
- * dccp_rcv_state_process
+ * If P.type == Request or P contains a valid Init Cookie option,
+ * (* Must scan the packet's options to check for Init
+ * Cookies. Only Init Cookies are processed here,
+ * however; other options are processed in Step 8. This
+ * scan need only be performed if the endpoint uses Init
+ * Cookies *)
+ * (* Generate a new socket and switch to that socket *)
+ * Set S := new socket for this port pair
+ * S.state = RESPOND
+ * Choose S.ISS (initial seqno) or set from Init Cookies
+ * Initialize S.GAR := S.ISS
+ * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init
+ * Cookies Continue with S.state == RESPOND
+ * (* A Response packet will be generated in Step 11 *)
+ * Otherwise,
+ * Generate Reset(No Connection) unless P.type == Reset
+ * Drop packet and return
*/
if (sk->sk_state == DCCP_LISTEN) {
if (dh->dccph_type == DCCP_PKT_REQUEST) {
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index e08e7688a263..ff81679c9f17 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -113,13 +113,8 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
/* OK, now commit destination to socket. */
sk_setup_caps(sk, &rt->u.dst);
- dp->dccps_gar =
- dp->dccps_iss = secure_dccp_sequence_number(inet->saddr,
- inet->daddr,
- inet->sport,
- usin->sin_port);
- dccp_update_gss(sk, dp->dccps_iss);
-
+ dp->dccps_iss = secure_dccp_sequence_number(inet->saddr, inet->daddr,
+ inet->sport, inet->dport);
inet->id = dp->dccps_iss ^ jiffies;
err = dccp_connect(sk);
@@ -193,86 +188,6 @@ static inline void dccp_do_pmtu_discovery(struct sock *sk,
} /* else let the usual retransmit timer handle it */
}
-static void dccp_v4_reqsk_send_ack(struct sk_buff *rxskb,
- struct request_sock *req)
-{
- int err;
- struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh;
- const u32 dccp_hdr_ack_len = sizeof(struct dccp_hdr) +
- sizeof(struct dccp_hdr_ext) +
- sizeof(struct dccp_hdr_ack_bits);
- struct sk_buff *skb;
-
- if (((struct rtable *)rxskb->dst)->rt_type != RTN_LOCAL)
- return;
-
- skb = alloc_skb(dccp_v4_ctl_socket->sk->sk_prot->max_header, GFP_ATOMIC);
- if (skb == NULL)
- return;
-
- /* Reserve space for headers. */
- skb_reserve(skb, dccp_v4_ctl_socket->sk->sk_prot->max_header);
-
- skb->dst = dst_clone(rxskb->dst);
-
- skb->h.raw = skb_push(skb, dccp_hdr_ack_len);
- dh = dccp_hdr(skb);
- memset(dh, 0, dccp_hdr_ack_len);
-
- /* Build DCCP header and checksum it. */
- dh->dccph_type = DCCP_PKT_ACK;
- dh->dccph_sport = rxdh->dccph_dport;
- dh->dccph_dport = rxdh->dccph_sport;
- dh->dccph_doff = dccp_hdr_ack_len / 4;
- dh->dccph_x = 1;
-
- dccp_hdr_set_seq(dh, DCCP_SKB_CB(rxskb)->dccpd_ack_seq);
- dccp_hdr_set_ack(dccp_hdr_ack_bits(skb),
- DCCP_SKB_CB(rxskb)->dccpd_seq);
-
- bh_lock_sock(dccp_v4_ctl_socket->sk);
- err = ip_build_and_send_pkt(skb, dccp_v4_ctl_socket->sk,
- rxskb->nh.iph->daddr,
- rxskb->nh.iph->saddr, NULL);
- bh_unlock_sock(dccp_v4_ctl_socket->sk);
-
- if (err == NET_XMIT_CN || err == 0) {
- DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
- DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS);
- }
-}
-
-static int dccp_v4_send_response(struct sock *sk, struct request_sock *req,
- struct dst_entry *dst)
-{
- int err = -1;
- struct sk_buff *skb;
-
- /* First, grab a route. */
-
- if (dst == NULL && (dst = inet_csk_route_req(sk, req)) == NULL)
- goto out;
-
- skb = dccp_make_response(sk, dst, req);
- if (skb != NULL) {
- const struct inet_request_sock *ireq = inet_rsk(req);
- struct dccp_hdr *dh = dccp_hdr(skb);
-
- dh->dccph_checksum = dccp_v4_checksum(skb, ireq->loc_addr,
- ireq->rmt_addr);
- memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
- err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr,
- ireq->rmt_addr,
- ireq->opt);
- if (err == NET_XMIT_CN)
- err = 0;
- }
-
-out:
- dst_release(dst);
- return err;
-}
-
/*
* This routine is called by the ICMP module when it gets some sort of error
* condition. If err < 0 then the socket should be closed and the error
@@ -329,7 +244,7 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
seq = dccp_hdr_seq(skb);
if (sk->sk_state != DCCP_LISTEN &&
!between48(seq, dp->dccps_swl, dp->dccps_swh)) {
- NET_INC_STATS(LINUX_MIB_OUTOFWINDOWICMPS);
+ NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS);
goto out;
}
@@ -429,19 +344,24 @@ out:
sock_put(sk);
}
-/* This routine computes an IPv4 DCCP checksum. */
-void dccp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb)
+static inline __sum16 dccp_v4_csum_finish(struct sk_buff *skb,
+ __be32 src, __be32 dst)
+{
+ return csum_tcpudp_magic(src, dst, skb->len, IPPROTO_DCCP, skb->csum);
+}
+
+void dccp_v4_send_check(struct sock *sk, int unused, struct sk_buff *skb)
{
const struct inet_sock *inet = inet_sk(sk);
struct dccp_hdr *dh = dccp_hdr(skb);
- dh->dccph_checksum = dccp_v4_checksum(skb, inet->saddr, inet->daddr);
+ dccp_csum_outgoing(skb);
+ dh->dccph_checksum = dccp_v4_csum_finish(skb, inet->saddr, inet->daddr);
}
EXPORT_SYMBOL_GPL(dccp_v4_send_check);
-static inline u64 dccp_v4_init_sequence(const struct sock *sk,
- const struct sk_buff *skb)
+static inline u64 dccp_v4_init_sequence(const struct sk_buff *skb)
{
return secure_dccp_sequence_number(skb->nh.iph->daddr,
skb->nh.iph->saddr,
@@ -449,95 +369,6 @@ static inline u64 dccp_v4_init_sequence(const struct sock *sk,
dccp_hdr(skb)->dccph_sport);
}
-static struct request_sock_ops dccp_request_sock_ops;
-
-int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
-{
- struct inet_request_sock *ireq;
- struct dccp_sock dp;
- struct request_sock *req;
- struct dccp_request_sock *dreq;
- const __be32 saddr = skb->nh.iph->saddr;
- const __be32 daddr = skb->nh.iph->daddr;
- const __be32 service = dccp_hdr_request(skb)->dccph_req_service;
- struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
- __u8 reset_code = DCCP_RESET_CODE_TOO_BUSY;
-
- /* Never answer to DCCP_PKT_REQUESTs send to broadcast or multicast */
- if (((struct rtable *)skb->dst)->rt_flags &
- (RTCF_BROADCAST | RTCF_MULTICAST)) {
- reset_code = DCCP_RESET_CODE_NO_CONNECTION;
- goto drop;
- }
-
- if (dccp_bad_service_code(sk, service)) {
- reset_code = DCCP_RESET_CODE_BAD_SERVICE_CODE;
- goto drop;
- }
- /*
- * TW buckets are converted to open requests without
- * limitations, they conserve resources and peer is
- * evidently real one.
- */
- if (inet_csk_reqsk_queue_is_full(sk))
- goto drop;
-
- /*
- * Accept backlog is full. If we have already queued enough
- * of warm entries in syn queue, drop request. It is better than
- * clogging syn queue with openreqs with exponentially increasing
- * timeout.
- */
- if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
- goto drop;
-
- req = reqsk_alloc(&dccp_request_sock_ops);
- if (req == NULL)
- goto drop;
-
- if (dccp_parse_options(sk, skb))
- goto drop_and_free;
-
- dccp_openreq_init(req, &dp, skb);
-
- if (security_inet_conn_request(sk, skb, req))
- goto drop_and_free;
-
- ireq = inet_rsk(req);
- ireq->loc_addr = daddr;
- ireq->rmt_addr = saddr;
- req->rcv_wnd = dccp_feat_default_sequence_window;
- ireq->opt = NULL;
-
- /*
- * Step 3: Process LISTEN state
- *
- * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie
- *
- * In fact we defer setting S.GSR, S.SWL, S.SWH to
- * dccp_create_openreq_child.
- */
- dreq = dccp_rsk(req);
- dreq->dreq_isr = dcb->dccpd_seq;
- dreq->dreq_iss = dccp_v4_init_sequence(sk, skb);
- dreq->dreq_service = service;
-
- if (dccp_v4_send_response(sk, req, NULL))
- goto drop_and_free;
-
- inet_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT);
- return 0;
-
-drop_and_free:
- reqsk_free(req);
-drop:
- DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS);
- dcb->dccpd_reset_code = reset_code;
- return -1;
-}
-
-EXPORT_SYMBOL_GPL(dccp_v4_conn_request);
-
/*
* The three way handshake has completed - we got a valid ACK or DATAACK -
* now create the new socket.
@@ -623,47 +454,6 @@ static struct sock *dccp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
return sk;
}
-int dccp_v4_checksum(const struct sk_buff *skb, const __be32 saddr,
- const __be32 daddr)
-{
- const struct dccp_hdr* dh = dccp_hdr(skb);
- int checksum_len;
- u32 tmp;
-
- if (dh->dccph_cscov == 0)
- checksum_len = skb->len;
- else {
- checksum_len = (dh->dccph_cscov + dh->dccph_x) * sizeof(u32);
- checksum_len = checksum_len < skb->len ? checksum_len :
- skb->len;
- }
-
- tmp = csum_partial((unsigned char *)dh, checksum_len, 0);
- return csum_tcpudp_magic(saddr, daddr, checksum_len,
- IPPROTO_DCCP, tmp);
-}
-
-EXPORT_SYMBOL_GPL(dccp_v4_checksum);
-
-static int dccp_v4_verify_checksum(struct sk_buff *skb,
- const __be32 saddr, const __be32 daddr)
-{
- struct dccp_hdr *dh = dccp_hdr(skb);
- int checksum_len;
- u32 tmp;
-
- if (dh->dccph_cscov == 0)
- checksum_len = skb->len;
- else {
- checksum_len = (dh->dccph_cscov + dh->dccph_x) * sizeof(u32);
- checksum_len = checksum_len < skb->len ? checksum_len :
- skb->len;
- }
- tmp = csum_partial((unsigned char *)dh, checksum_len, 0);
- return csum_tcpudp_magic(saddr, daddr, checksum_len,
- IPPROTO_DCCP, tmp) == 0 ? 0 : -1;
-}
-
static struct dst_entry* dccp_v4_route_skb(struct sock *sk,
struct sk_buff *skb)
{
@@ -689,7 +479,37 @@ static struct dst_entry* dccp_v4_route_skb(struct sock *sk,
return &rt->u.dst;
}
-static void dccp_v4_ctl_send_reset(struct sk_buff *rxskb)
+static int dccp_v4_send_response(struct sock *sk, struct request_sock *req,
+ struct dst_entry *dst)
+{
+ int err = -1;
+ struct sk_buff *skb;
+
+ /* First, grab a route. */
+
+ if (dst == NULL && (dst = inet_csk_route_req(sk, req)) == NULL)
+ goto out;
+
+ skb = dccp_make_response(sk, dst, req);
+ if (skb != NULL) {
+ const struct inet_request_sock *ireq = inet_rsk(req);
+ struct dccp_hdr *dh = dccp_hdr(skb);
+
+ dh->dccph_checksum = dccp_v4_csum_finish(skb, ireq->loc_addr,
+ ireq->rmt_addr);
+ memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
+ err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr,
+ ireq->rmt_addr,
+ ireq->opt);
+ err = net_xmit_eval(err);
+ }
+
+out:
+ dst_release(dst);
+ return err;
+}
+
+static void dccp_v4_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb)
{
int err;
struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh;
@@ -698,7 +518,7 @@ static void dccp_v4_ctl_send_reset(struct sk_buff *rxskb)
sizeof(struct dccp_hdr_reset);
struct sk_buff *skb;
struct dst_entry *dst;
- u64 seqno;
+ u64 seqno = 0;
/* Never send a reset in response to a reset. */
if (rxdh->dccph_type == DCCP_PKT_RESET)
@@ -720,9 +540,7 @@ static void dccp_v4_ctl_send_reset(struct sk_buff *rxskb)
skb_reserve(skb, dccp_v4_ctl_socket->sk->sk_prot->max_header);
skb->dst = dst_clone(dst);
- skb->h.raw = skb_push(skb, dccp_hdr_reset_len);
- dh = dccp_hdr(skb);
- memset(dh, 0, dccp_hdr_reset_len);
+ dh = dccp_zeroed_hdr(skb, dccp_hdr_reset_len);
/* Build DCCP header and checksum it. */
dh->dccph_type = DCCP_PKT_RESET;
@@ -734,16 +552,15 @@ static void dccp_v4_ctl_send_reset(struct sk_buff *rxskb)
DCCP_SKB_CB(rxskb)->dccpd_reset_code;
/* See "8.3.1. Abnormal Termination" in RFC 4340 */
- seqno = 0;
if (DCCP_SKB_CB(rxskb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)
dccp_set_seqno(&seqno, DCCP_SKB_CB(rxskb)->dccpd_ack_seq + 1);
dccp_hdr_set_seq(dh, seqno);
- dccp_hdr_set_ack(dccp_hdr_ack_bits(skb),
- DCCP_SKB_CB(rxskb)->dccpd_seq);
+ dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), DCCP_SKB_CB(rxskb)->dccpd_seq);
- dh->dccph_checksum = dccp_v4_checksum(skb, rxskb->nh.iph->saddr,
- rxskb->nh.iph->daddr);
+ dccp_csum_outgoing(skb);
+ dh->dccph_checksum = dccp_v4_csum_finish(skb, rxskb->nh.iph->saddr,
+ rxskb->nh.iph->daddr);
bh_lock_sock(dccp_v4_ctl_socket->sk);
err = ip_build_and_send_pkt(skb, dccp_v4_ctl_socket->sk,
@@ -751,7 +568,7 @@ static void dccp_v4_ctl_send_reset(struct sk_buff *rxskb)
rxskb->nh.iph->saddr, NULL);
bh_unlock_sock(dccp_v4_ctl_socket->sk);
- if (err == NET_XMIT_CN || err == 0) {
+ if (net_xmit_eval(err) == 0) {
DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS);
}
@@ -759,6 +576,103 @@ out:
dst_release(dst);
}
+static void dccp_v4_reqsk_destructor(struct request_sock *req)
+{
+ kfree(inet_rsk(req)->opt);
+}
+
+static struct request_sock_ops dccp_request_sock_ops __read_mostly = {
+ .family = PF_INET,
+ .obj_size = sizeof(struct dccp_request_sock),
+ .rtx_syn_ack = dccp_v4_send_response,
+ .send_ack = dccp_reqsk_send_ack,
+ .destructor = dccp_v4_reqsk_destructor,
+ .send_reset = dccp_v4_ctl_send_reset,
+};
+
+int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
+{
+ struct inet_request_sock *ireq;
+ struct request_sock *req;
+ struct dccp_request_sock *dreq;
+ const __be32 service = dccp_hdr_request(skb)->dccph_req_service;
+ struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
+ __u8 reset_code = DCCP_RESET_CODE_TOO_BUSY;
+
+ /* Never answer to DCCP_PKT_REQUESTs send to broadcast or multicast */
+ if (((struct rtable *)skb->dst)->rt_flags &
+ (RTCF_BROADCAST | RTCF_MULTICAST)) {
+ reset_code = DCCP_RESET_CODE_NO_CONNECTION;
+ goto drop;
+ }
+
+ if (dccp_bad_service_code(sk, service)) {
+ reset_code = DCCP_RESET_CODE_BAD_SERVICE_CODE;
+ goto drop;
+ }
+ /*
+ * TW buckets are converted to open requests without
+ * limitations, they conserve resources and peer is
+ * evidently real one.
+ */
+ if (inet_csk_reqsk_queue_is_full(sk))
+ goto drop;
+
+ /*
+ * Accept backlog is full. If we have already queued enough
+ * of warm entries in syn queue, drop request. It is better than
+ * clogging syn queue with openreqs with exponentially increasing
+ * timeout.
+ */
+ if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
+ goto drop;
+
+ req = reqsk_alloc(&dccp_request_sock_ops);
+ if (req == NULL)
+ goto drop;
+
+ if (dccp_parse_options(sk, skb))
+ goto drop_and_free;
+
+ dccp_reqsk_init(req, skb);
+
+ if (security_inet_conn_request(sk, skb, req))
+ goto drop_and_free;
+
+ ireq = inet_rsk(req);
+ ireq->loc_addr = skb->nh.iph->daddr;
+ ireq->rmt_addr = skb->nh.iph->saddr;
+ ireq->opt = NULL;
+
+ /*
+ * Step 3: Process LISTEN state
+ *
+ * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie
+ *
+ * In fact we defer setting S.GSR, S.SWL, S.SWH to
+ * dccp_create_openreq_child.
+ */
+ dreq = dccp_rsk(req);
+ dreq->dreq_isr = dcb->dccpd_seq;
+ dreq->dreq_iss = dccp_v4_init_sequence(skb);
+ dreq->dreq_service = service;
+
+ if (dccp_v4_send_response(sk, req, NULL))
+ goto drop_and_free;
+
+ inet_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT);
+ return 0;
+
+drop_and_free:
+ reqsk_free(req);
+drop:
+ DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS);
+ dcb->dccpd_reset_code = reset_code;
+ return -1;
+}
+
+EXPORT_SYMBOL_GPL(dccp_v4_conn_request);
+
int dccp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
{
struct dccp_hdr *dh = dccp_hdr(skb);
@@ -771,24 +685,23 @@ int dccp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
/*
* Step 3: Process LISTEN state
- * If S.state == LISTEN,
- * If P.type == Request or P contains a valid Init Cookie
- * option,
- * * Must scan the packet's options to check for an Init
- * Cookie. Only the Init Cookie is processed here,
- * however; other options are processed in Step 8. This
- * scan need only be performed if the endpoint uses Init
- * Cookies *
- * * Generate a new socket and switch to that socket *
- * Set S := new socket for this port pair
- * S.state = RESPOND
- * Choose S.ISS (initial seqno) or set from Init Cookie
- * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie
- * Continue with S.state == RESPOND
- * * A Response packet will be generated in Step 11 *
- * Otherwise,
- * Generate Reset(No Connection) unless P.type == Reset
- * Drop packet and return
+ * If P.type == Request or P contains a valid Init Cookie option,
+ * (* Must scan the packet's options to check for Init
+ * Cookies. Only Init Cookies are processed here,
+ * however; other options are processed in Step 8. This
+ * scan need only be performed if the endpoint uses Init
+ * Cookies *)
+ * (* Generate a new socket and switch to that socket *)
+ * Set S := new socket for this port pair
+ * S.state = RESPOND
+ * Choose S.ISS (initial seqno) or set from Init Cookies
+ * Initialize S.GAR := S.ISS
+ * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookies
+ * Continue with S.state == RESPOND
+ * (* A Response packet will be generated in Step 11 *)
+ * Otherwise,
+ * Generate Reset(No Connection) unless P.type == Reset
+ * Drop packet and return
*
* NOTE: the check for the packet types is done in
* dccp_rcv_state_process
@@ -811,7 +724,7 @@ int dccp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
return 0;
reset:
- dccp_v4_ctl_send_reset(skb);
+ dccp_v4_ctl_send_reset(sk, skb);
discard:
kfree_skb(skb);
return 0;
@@ -819,60 +732,74 @@ discard:
EXPORT_SYMBOL_GPL(dccp_v4_do_rcv);
+/**
+ * dccp_invalid_packet - check for malformed packets
+ * Implements RFC 4340, 8.5: Step 1: Check header basics
+ * Packets that fail these checks are ignored and do not receive Resets.
+ */
int dccp_invalid_packet(struct sk_buff *skb)
{
const struct dccp_hdr *dh;
+ unsigned int cscov;
if (skb->pkt_type != PACKET_HOST)
return 1;
+ /* If the packet is shorter than 12 bytes, drop packet and return */
if (!pskb_may_pull(skb, sizeof(struct dccp_hdr))) {
- LIMIT_NETDEBUG(KERN_WARNING "DCCP: pskb_may_pull failed\n");
+ DCCP_WARN("pskb_may_pull failed\n");
return 1;
}
dh = dccp_hdr(skb);
- /* If the packet type is not understood, drop packet and return */
+ /* If P.type is not understood, drop packet and return */
if (dh->dccph_type >= DCCP_PKT_INVALID) {
- LIMIT_NETDEBUG(KERN_WARNING "DCCP: invalid packet type\n");
+ DCCP_WARN("invalid packet type\n");
return 1;
}
/*
- * If P.Data Offset is too small for packet type, or too large for
- * packet, drop packet and return
+ * If P.Data Offset is too small for packet type, drop packet and return
*/
if (dh->dccph_doff < dccp_hdr_len(skb) / sizeof(u32)) {
- LIMIT_NETDEBUG(KERN_WARNING "DCCP: P.Data Offset(%u) "
- "too small 1\n",
- dh->dccph_doff);
+ DCCP_WARN("P.Data Offset(%u) too small\n", dh->dccph_doff);
return 1;
}
-
+ /*
+ * If P.Data Offset is too too large for packet, drop packet and return
+ */
if (!pskb_may_pull(skb, dh->dccph_doff * sizeof(u32))) {
- LIMIT_NETDEBUG(KERN_WARNING "DCCP: P.Data Offset(%u) "
- "too small 2\n",
- dh->dccph_doff);
+ DCCP_WARN("P.Data Offset(%u) too large\n", dh->dccph_doff);
return 1;
}
- dh = dccp_hdr(skb);
-
/*
* If P.type is not Data, Ack, or DataAck and P.X == 0 (the packet
* has short sequence numbers), drop packet and return
*/
- if (dh->dccph_x == 0 &&
- dh->dccph_type != DCCP_PKT_DATA &&
- dh->dccph_type != DCCP_PKT_ACK &&
- dh->dccph_type != DCCP_PKT_DATAACK) {
- LIMIT_NETDEBUG(KERN_WARNING "DCCP: P.type (%s) not Data, Ack "
- "nor DataAck and P.X == 0\n",
- dccp_packet_name(dh->dccph_type));
+ if (dh->dccph_type >= DCCP_PKT_DATA &&
+ dh->dccph_type <= DCCP_PKT_DATAACK && dh->dccph_x == 0) {
+ DCCP_WARN("P.type (%s) not Data || [Data]Ack, while P.X == 0\n",
+ dccp_packet_name(dh->dccph_type));
return 1;
}
+ /*
+ * If P.CsCov is too large for the packet size, drop packet and return.
+ * This must come _before_ checksumming (not as RFC 4340 suggests).
+ */
+ cscov = dccp_csum_coverage(skb);
+ if (cscov > skb->len) {
+ DCCP_WARN("P.CsCov %u exceeds packet length %d\n",
+ dh->dccph_cscov, skb->len);
+ return 1;
+ }
+
+ /* If header checksum is incorrect, drop packet and return.
+ * (This step is completed in the AF-dependent functions.) */
+ skb->csum = skb_checksum(skb, 0, cscov, 0);
+
return 0;
}
@@ -883,17 +810,16 @@ static int dccp_v4_rcv(struct sk_buff *skb)
{
const struct dccp_hdr *dh;
struct sock *sk;
+ int min_cov;
- /* Step 1: Check header basics: */
+ /* Step 1: Check header basics */
if (dccp_invalid_packet(skb))
goto discard_it;
- /* If the header checksum is incorrect, drop packet and return */
- if (dccp_v4_verify_checksum(skb, skb->nh.iph->saddr,
- skb->nh.iph->daddr) < 0) {
- LIMIT_NETDEBUG(KERN_WARNING "%s: incorrect header checksum\n",
- __FUNCTION__);
+ /* Step 1: If header checksum is incorrect, drop packet and return */
+ if (dccp_v4_csum_finish(skb, skb->nh.iph->saddr, skb->nh.iph->daddr)) {
+ DCCP_WARN("dropped packet with invalid checksum\n");
goto discard_it;
}
@@ -915,8 +841,7 @@ static int dccp_v4_rcv(struct sk_buff *skb)
dccp_pr_debug_cat("\n");
} else {
DCCP_SKB_CB(skb)->dccpd_ack_seq = dccp_hdr_ack_seq(skb);
- dccp_pr_debug_cat(", ack=%llu\n",
- (unsigned long long)
+ dccp_pr_debug_cat(", ack=%llu\n", (unsigned long long)
DCCP_SKB_CB(skb)->dccpd_ack_seq);
}
@@ -930,8 +855,6 @@ static int dccp_v4_rcv(struct sk_buff *skb)
/*
* Step 2:
* If no socket ...
- * Generate Reset(No Connection) unless P.type == Reset
- * Drop packet and return
*/
if (sk == NULL) {
dccp_pr_debug("failed to look up flow ID in table and "
@@ -945,45 +868,55 @@ static int dccp_v4_rcv(struct sk_buff *skb)
* Generate Reset(No Connection) unless P.type == Reset
* Drop packet and return
*/
-
if (sk->sk_state == DCCP_TIME_WAIT) {
- dccp_pr_debug("sk->sk_state == DCCP_TIME_WAIT: "
- "do_time_wait\n");
- goto do_time_wait;
+ dccp_pr_debug("sk->sk_state == DCCP_TIME_WAIT: do_time_wait\n");
+ inet_twsk_put(inet_twsk(sk));
+ goto no_dccp_socket;
+ }
+
+ /*
+ * RFC 4340, sec. 9.2.1: Minimum Checksum Coverage
+ * o if MinCsCov = 0, only packets with CsCov = 0 are accepted
+ * o if MinCsCov > 0, also accept packets with CsCov >= MinCsCov
+ */
+ min_cov = dccp_sk(sk)->dccps_pcrlen;
+ if (dh->dccph_cscov && (min_cov == 0 || dh->dccph_cscov < min_cov)) {
+ dccp_pr_debug("Packet CsCov %d does not satisfy MinCsCov %d\n",
+ dh->dccph_cscov, min_cov);
+ /* FIXME: "Such packets SHOULD be reported using Data Dropped
+ * options (Section 11.7) with Drop Code 0, Protocol
+ * Constraints." */
+ goto discard_and_relse;
}
if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
goto discard_and_relse;
nf_reset(skb);
- return sk_receive_skb(sk, skb);
+ return sk_receive_skb(sk, skb, 1);
no_dccp_socket:
if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
goto discard_it;
/*
* Step 2:
+ * If no socket ...
* Generate Reset(No Connection) unless P.type == Reset
* Drop packet and return
*/
if (dh->dccph_type != DCCP_PKT_RESET) {
DCCP_SKB_CB(skb)->dccpd_reset_code =
DCCP_RESET_CODE_NO_CONNECTION;
- dccp_v4_ctl_send_reset(skb);
+ dccp_v4_ctl_send_reset(sk, skb);
}
discard_it:
- /* Discard frame. */
kfree_skb(skb);
return 0;
discard_and_relse:
sock_put(sk);
goto discard_it;
-
-do_time_wait:
- inet_twsk_put(inet_twsk(sk));
- goto no_dccp_socket;
}
static struct inet_connection_sock_af_ops dccp_ipv4_af_ops = {
@@ -1017,20 +950,6 @@ static int dccp_v4_init_sock(struct sock *sk)
return err;
}
-static void dccp_v4_reqsk_destructor(struct request_sock *req)
-{
- kfree(inet_rsk(req)->opt);
-}
-
-static struct request_sock_ops dccp_request_sock_ops = {
- .family = PF_INET,
- .obj_size = sizeof(struct dccp_request_sock),
- .rtx_syn_ack = dccp_v4_send_response,
- .send_ack = dccp_v4_reqsk_send_ack,
- .destructor = dccp_v4_reqsk_destructor,
- .send_reset = dccp_v4_ctl_send_reset,
-};
-
static struct timewait_sock_ops dccp_timewait_sock_ops = {
.twsk_obj_size = sizeof(struct inet_timewait_sock),
};
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index fc4242c0767c..c7aaa2574f52 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -36,13 +36,6 @@
/* Socket used for sending RSTs and ACKs */
static struct socket *dccp_v6_ctl_socket;
-static void dccp_v6_ctl_send_reset(struct sk_buff *skb);
-static void dccp_v6_reqsk_send_ack(struct sk_buff *skb,
- struct request_sock *req);
-static void dccp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb);
-
-static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb);
-
static struct inet_connection_sock_af_ops dccp_ipv6_mapped;
static struct inet_connection_sock_af_ops dccp_ipv6_af_ops;
@@ -65,205 +58,37 @@ static void dccp_v6_hash(struct sock *sk)
}
}
-static inline u16 dccp_v6_check(struct dccp_hdr *dh, int len,
- struct in6_addr *saddr,
- struct in6_addr *daddr,
- unsigned long base)
+/* add pseudo-header to DCCP checksum stored in skb->csum */
+static inline __sum16 dccp_v6_csum_finish(struct sk_buff *skb,
+ struct in6_addr *saddr,
+ struct in6_addr *daddr)
{
- return csum_ipv6_magic(saddr, daddr, len, IPPROTO_DCCP, base);
+ return csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_DCCP, skb->csum);
}
-static __u32 dccp_v6_init_sequence(struct sock *sk, struct sk_buff *skb)
+static inline void dccp_v6_send_check(struct sock *sk, int unused_value,
+ struct sk_buff *skb)
{
- const struct dccp_hdr *dh = dccp_hdr(skb);
-
- if (skb->protocol == htons(ETH_P_IPV6))
- return secure_tcpv6_sequence_number(skb->nh.ipv6h->daddr.s6_addr32,
- skb->nh.ipv6h->saddr.s6_addr32,
- dh->dccph_dport,
- dh->dccph_sport);
+ struct ipv6_pinfo *np = inet6_sk(sk);
+ struct dccp_hdr *dh = dccp_hdr(skb);
- return secure_dccp_sequence_number(skb->nh.iph->daddr,
- skb->nh.iph->saddr,
- dh->dccph_dport,
- dh->dccph_sport);
+ dccp_csum_outgoing(skb);
+ dh->dccph_checksum = dccp_v6_csum_finish(skb, &np->saddr, &np->daddr);
}
-static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
- int addr_len)
+static inline __u32 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr,
+ __be16 sport, __be16 dport )
{
- struct sockaddr_in6 *usin = (struct sockaddr_in6 *)uaddr;
- struct inet_connection_sock *icsk = inet_csk(sk);
- struct inet_sock *inet = inet_sk(sk);
- struct ipv6_pinfo *np = inet6_sk(sk);
- struct dccp_sock *dp = dccp_sk(sk);
- struct in6_addr *saddr = NULL, *final_p = NULL, final;
- struct flowi fl;
- struct dst_entry *dst;
- int addr_type;
- int err;
-
- dp->dccps_role = DCCP_ROLE_CLIENT;
-
- if (addr_len < SIN6_LEN_RFC2133)
- return -EINVAL;
-
- if (usin->sin6_family != AF_INET6)
- return -EAFNOSUPPORT;
-
- memset(&fl, 0, sizeof(fl));
-
- if (np->sndflow) {
- fl.fl6_flowlabel = usin->sin6_flowinfo & IPV6_FLOWINFO_MASK;
- IP6_ECN_flow_init(fl.fl6_flowlabel);
- if (fl.fl6_flowlabel & IPV6_FLOWLABEL_MASK) {
- struct ip6_flowlabel *flowlabel;
- flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel);
- if (flowlabel == NULL)
- return -EINVAL;
- ipv6_addr_copy(&usin->sin6_addr, &flowlabel->dst);
- fl6_sock_release(flowlabel);
- }
- }
- /*
- * connect() to INADDR_ANY means loopback (BSD'ism).
- */
- if (ipv6_addr_any(&usin->sin6_addr))
- usin->sin6_addr.s6_addr[15] = 1;
-
- addr_type = ipv6_addr_type(&usin->sin6_addr);
-
- if (addr_type & IPV6_ADDR_MULTICAST)
- return -ENETUNREACH;
-
- if (addr_type & IPV6_ADDR_LINKLOCAL) {
- if (addr_len >= sizeof(struct sockaddr_in6) &&
- usin->sin6_scope_id) {
- /* If interface is set while binding, indices
- * must coincide.
- */
- if (sk->sk_bound_dev_if &&
- sk->sk_bound_dev_if != usin->sin6_scope_id)
- return -EINVAL;
-
- sk->sk_bound_dev_if = usin->sin6_scope_id;
- }
-
- /* Connect to link-local address requires an interface */
- if (!sk->sk_bound_dev_if)
- return -EINVAL;
- }
-
- ipv6_addr_copy(&np->daddr, &usin->sin6_addr);
- np->flow_label = fl.fl6_flowlabel;
-
- /*
- * DCCP over IPv4
- */
- if (addr_type == IPV6_ADDR_MAPPED) {
- u32 exthdrlen = icsk->icsk_ext_hdr_len;
- struct sockaddr_in sin;
-
- SOCK_DEBUG(sk, "connect: ipv4 mapped\n");
-
- if (__ipv6_only_sock(sk))
- return -ENETUNREACH;
-
- sin.sin_family = AF_INET;
- sin.sin_port = usin->sin6_port;
- sin.sin_addr.s_addr = usin->sin6_addr.s6_addr32[3];
-
- icsk->icsk_af_ops = &dccp_ipv6_mapped;
- sk->sk_backlog_rcv = dccp_v4_do_rcv;
-
- err = dccp_v4_connect(sk, (struct sockaddr *)&sin, sizeof(sin));
- if (err) {
- icsk->icsk_ext_hdr_len = exthdrlen;
- icsk->icsk_af_ops = &dccp_ipv6_af_ops;
- sk->sk_backlog_rcv = dccp_v6_do_rcv;
- goto failure;
- } else {
- ipv6_addr_set(&np->saddr, 0, 0, htonl(0x0000FFFF),
- inet->saddr);
- ipv6_addr_set(&np->rcv_saddr, 0, 0, htonl(0x0000FFFF),
- inet->rcv_saddr);
- }
-
- return err;
- }
-
- if (!ipv6_addr_any(&np->rcv_saddr))
- saddr = &np->rcv_saddr;
-
- fl.proto = IPPROTO_DCCP;
- ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
- ipv6_addr_copy(&fl.fl6_src, saddr ? saddr : &np->saddr);
- fl.oif = sk->sk_bound_dev_if;
- fl.fl_ip_dport = usin->sin6_port;
- fl.fl_ip_sport = inet->sport;
- security_sk_classify_flow(sk, &fl);
-
- if (np->opt != NULL && np->opt->srcrt != NULL) {
- const struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
-
- ipv6_addr_copy(&final, &fl.fl6_dst);
- ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
- final_p = &final;
- }
-
- err = ip6_dst_lookup(sk, &dst, &fl);
- if (err)
- goto failure;
-
- if (final_p)
- ipv6_addr_copy(&fl.fl6_dst, final_p);
-
- err = xfrm_lookup(&dst, &fl, sk, 0);
- if (err < 0)
- goto failure;
-
- if (saddr == NULL) {
- saddr = &fl.fl6_src;
- ipv6_addr_copy(&np->rcv_saddr, saddr);
- }
-
- /* set the source address */
- ipv6_addr_copy(&np->saddr, saddr);
- inet->rcv_saddr = LOOPBACK4_IPV6;
-
- __ip6_dst_store(sk, dst, NULL, NULL);
-
- icsk->icsk_ext_hdr_len = 0;
- if (np->opt != NULL)
- icsk->icsk_ext_hdr_len = (np->opt->opt_flen +
- np->opt->opt_nflen);
-
- inet->dport = usin->sin6_port;
-
- dccp_set_state(sk, DCCP_REQUESTING);
- err = inet6_hash_connect(&dccp_death_row, sk);
- if (err)
- goto late_failure;
- /* FIXME */
-#if 0
- dp->dccps_gar = secure_dccp_v6_sequence_number(np->saddr.s6_addr32,
- np->daddr.s6_addr32,
- inet->sport,
- inet->dport);
-#endif
- err = dccp_connect(sk);
- if (err)
- goto late_failure;
+ return secure_tcpv6_sequence_number(saddr, daddr, sport, dport);
+}
- return 0;
+static inline __u32 dccp_v6_init_sequence(struct sk_buff *skb)
+{
+ return secure_dccpv6_sequence_number(skb->nh.ipv6h->daddr.s6_addr32,
+ skb->nh.ipv6h->saddr.s6_addr32,
+ dccp_hdr(skb)->dccph_dport,
+ dccp_hdr(skb)->dccph_sport );
-late_failure:
- dccp_set_state(sk, DCCP_CLOSED);
- __sk_dst_reset(sk);
-failure:
- inet->dport = 0;
- sk->sk_route_caps = 0;
- return err;
}
static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
@@ -464,16 +289,12 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req,
if (skb != NULL) {
struct dccp_hdr *dh = dccp_hdr(skb);
- dh->dccph_checksum = dccp_v6_check(dh, skb->len,
- &ireq6->loc_addr,
- &ireq6->rmt_addr,
- csum_partial((char *)dh,
- skb->len,
- skb->csum));
+ dh->dccph_checksum = dccp_v6_csum_finish(skb,
+ &ireq6->loc_addr,
+ &ireq6->rmt_addr);
ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr);
err = ip6_xmit(sk, skb, &fl, opt, 0);
- if (err == NET_XMIT_CN)
- err = 0;
+ err = net_xmit_eval(err);
}
done:
@@ -489,32 +310,7 @@ static void dccp_v6_reqsk_destructor(struct request_sock *req)
kfree_skb(inet6_rsk(req)->pktopts);
}
-static struct request_sock_ops dccp6_request_sock_ops = {
- .family = AF_INET6,
- .obj_size = sizeof(struct dccp6_request_sock),
- .rtx_syn_ack = dccp_v6_send_response,
- .send_ack = dccp_v6_reqsk_send_ack,
- .destructor = dccp_v6_reqsk_destructor,
- .send_reset = dccp_v6_ctl_send_reset,
-};
-
-static struct timewait_sock_ops dccp6_timewait_sock_ops = {
- .twsk_obj_size = sizeof(struct dccp6_timewait_sock),
-};
-
-static void dccp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb)
-{
- struct ipv6_pinfo *np = inet6_sk(sk);
- struct dccp_hdr *dh = dccp_hdr(skb);
-
- dh->dccph_checksum = csum_ipv6_magic(&np->saddr, &np->daddr,
- len, IPPROTO_DCCP,
- csum_partial((char *)dh,
- dh->dccph_doff << 2,
- skb->csum));
-}
-
-static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb)
+static void dccp_v6_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb)
{
struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh;
const u32 dccp_hdr_reset_len = sizeof(struct dccp_hdr) +
@@ -522,7 +318,7 @@ static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb)
sizeof(struct dccp_hdr_reset);
struct sk_buff *skb;
struct flowi fl;
- u64 seqno;
+ u64 seqno = 0;
if (rxdh->dccph_type == DCCP_PKT_RESET)
return;
@@ -537,9 +333,7 @@ static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb)
skb_reserve(skb, dccp_v6_ctl_socket->sk->sk_prot->max_header);
- skb->h.raw = skb_push(skb, dccp_hdr_reset_len);
- dh = dccp_hdr(skb);
- memset(dh, 0, dccp_hdr_reset_len);
+ dh = dccp_zeroed_hdr(skb, dccp_hdr_reset_len);
/* Swap the send and the receive. */
dh->dccph_type = DCCP_PKT_RESET;
@@ -551,20 +345,20 @@ static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb)
DCCP_SKB_CB(rxskb)->dccpd_reset_code;
/* See "8.3.1. Abnormal Termination" in RFC 4340 */
- seqno = 0;
if (DCCP_SKB_CB(rxskb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)
dccp_set_seqno(&seqno, DCCP_SKB_CB(rxskb)->dccpd_ack_seq + 1);
dccp_hdr_set_seq(dh, seqno);
- dccp_hdr_set_ack(dccp_hdr_ack_bits(skb),
- DCCP_SKB_CB(rxskb)->dccpd_seq);
+ dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), DCCP_SKB_CB(rxskb)->dccpd_seq);
+
+ dccp_csum_outgoing(skb);
+ dh->dccph_checksum = dccp_v6_csum_finish(skb, &rxskb->nh.ipv6h->saddr,
+ &rxskb->nh.ipv6h->daddr);
memset(&fl, 0, sizeof(fl));
ipv6_addr_copy(&fl.fl6_dst, &rxskb->nh.ipv6h->saddr);
ipv6_addr_copy(&fl.fl6_src, &rxskb->nh.ipv6h->daddr);
- dh->dccph_checksum = csum_ipv6_magic(&fl.fl6_src, &fl.fl6_dst,
- sizeof(*dh), IPPROTO_DCCP,
- skb->csum);
+
fl.proto = IPPROTO_DCCP;
fl.oif = inet6_iif(rxskb);
fl.fl_ip_dport = dh->dccph_dport;
@@ -584,60 +378,14 @@ static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb)
kfree_skb(skb);
}
-static void dccp_v6_reqsk_send_ack(struct sk_buff *rxskb,
- struct request_sock *req)
-{
- struct flowi fl;
- struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh;
- const u32 dccp_hdr_ack_len = sizeof(struct dccp_hdr) +
- sizeof(struct dccp_hdr_ext) +
- sizeof(struct dccp_hdr_ack_bits);
- struct sk_buff *skb;
-
- skb = alloc_skb(dccp_v6_ctl_socket->sk->sk_prot->max_header,
- GFP_ATOMIC);
- if (skb == NULL)
- return;
-
- skb_reserve(skb, dccp_v6_ctl_socket->sk->sk_prot->max_header);
-
- skb->h.raw = skb_push(skb, dccp_hdr_ack_len);
- dh = dccp_hdr(skb);
- memset(dh, 0, dccp_hdr_ack_len);
-
- /* Build DCCP header and checksum it. */
- dh->dccph_type = DCCP_PKT_ACK;
- dh->dccph_sport = rxdh->dccph_dport;
- dh->dccph_dport = rxdh->dccph_sport;
- dh->dccph_doff = dccp_hdr_ack_len / 4;
- dh->dccph_x = 1;
-
- dccp_hdr_set_seq(dh, DCCP_SKB_CB(rxskb)->dccpd_ack_seq);
- dccp_hdr_set_ack(dccp_hdr_ack_bits(skb),
- DCCP_SKB_CB(rxskb)->dccpd_seq);
-
- memset(&fl, 0, sizeof(fl));
- ipv6_addr_copy(&fl.fl6_dst, &rxskb->nh.ipv6h->saddr);
- ipv6_addr_copy(&fl.fl6_src, &rxskb->nh.ipv6h->daddr);
-
- /* FIXME: calculate checksum, IPv4 also should... */
-
- fl.proto = IPPROTO_DCCP;
- fl.oif = inet6_iif(rxskb);
- fl.fl_ip_dport = dh->dccph_dport;
- fl.fl_ip_sport = dh->dccph_sport;
- security_req_classify_flow(req, &fl);
-
- if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) {
- if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) {
- ip6_xmit(dccp_v6_ctl_socket->sk, skb, &fl, NULL, 0);
- DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
- return;
- }
- }
-
- kfree_skb(skb);
-}
+static struct request_sock_ops dccp6_request_sock_ops = {
+ .family = AF_INET6,
+ .obj_size = sizeof(struct dccp6_request_sock),
+ .rtx_syn_ack = dccp_v6_send_response,
+ .send_ack = dccp_reqsk_send_ack,
+ .destructor = dccp_v6_reqsk_destructor,
+ .send_reset = dccp_v6_ctl_send_reset,
+};
static struct sock *dccp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
{
@@ -672,7 +420,6 @@ static struct sock *dccp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
{
- struct dccp_sock dp;
struct request_sock *req;
struct dccp_request_sock *dreq;
struct inet6_request_sock *ireq6;
@@ -704,9 +451,10 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
if (req == NULL)
goto drop;
- /* FIXME: process options */
+ if (dccp_parse_options(sk, skb))
+ goto drop_and_free;
- dccp_openreq_init(req, &dp, skb);
+ dccp_reqsk_init(req, skb);
if (security_inet_conn_request(sk, skb, req))
goto drop_and_free;
@@ -714,7 +462,6 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
ireq6 = inet6_rsk(req);
ipv6_addr_copy(&ireq6->rmt_addr, &skb->nh.ipv6h->saddr);
ipv6_addr_copy(&ireq6->loc_addr, &skb->nh.ipv6h->daddr);
- req->rcv_wnd = dccp_feat_default_sequence_window;
ireq6->pktopts = NULL;
if (ipv6_opt_accepted(sk, skb) ||
@@ -733,14 +480,14 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
/*
* Step 3: Process LISTEN state
*
- * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie
+ * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie
*
- * In fact we defer setting S.GSR, S.SWL, S.SWH to
- * dccp_create_openreq_child.
+ * In fact we defer setting S.GSR, S.SWL, S.SWH to
+ * dccp_create_openreq_child.
*/
dreq = dccp_rsk(req);
dreq->dreq_isr = dcb->dccpd_seq;
- dreq->dreq_iss = dccp_v6_init_sequence(sk, skb);
+ dreq->dreq_iss = dccp_v6_init_sequence(skb);
dreq->dreq_service = service;
if (dccp_v6_send_response(sk, req, NULL))
@@ -990,18 +737,46 @@ static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
--ANK (980728)
*/
if (np->rxopt.all)
+ /*
+ * FIXME: Add handling of IPV6_PKTOPTIONS skb. See the comments below
+ * (wrt ipv6_pktopions) and net/ipv6/tcp_ipv6.c for an example.
+ */
opt_skb = skb_clone(skb, GFP_ATOMIC);
if (sk->sk_state == DCCP_OPEN) { /* Fast path */
if (dccp_rcv_established(sk, skb, dccp_hdr(skb), skb->len))
goto reset;
if (opt_skb) {
- /* This is where we would goto ipv6_pktoptions. */
+ /* XXX This is where we would goto ipv6_pktoptions. */
__kfree_skb(opt_skb);
}
return 0;
}
+ /*
+ * Step 3: Process LISTEN state
+ * If S.state == LISTEN,
+ * If P.type == Request or P contains a valid Init Cookie option,
+ * (* Must scan the packet's options to check for Init
+ * Cookies. Only Init Cookies are processed here,
+ * however; other options are processed in Step 8. This
+ * scan need only be performed if the endpoint uses Init
+ * Cookies *)
+ * (* Generate a new socket and switch to that socket *)
+ * Set S := new socket for this port pair
+ * S.state = RESPOND
+ * Choose S.ISS (initial seqno) or set from Init Cookies
+ * Initialize S.GAR := S.ISS
+ * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookies
+ * Continue with S.state == RESPOND
+ * (* A Response packet will be generated in Step 11 *)
+ * Otherwise,
+ * Generate Reset(No Connection) unless P.type == Reset
+ * Drop packet and return
+ *
+ * NOTE: the check for the packet types is done in
+ * dccp_rcv_state_process
+ */
if (sk->sk_state == DCCP_LISTEN) {
struct sock *nsk = dccp_v6_hnd_req(sk, skb);
@@ -1024,13 +799,13 @@ static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
if (dccp_rcv_state_process(sk, skb, dccp_hdr(skb), skb->len))
goto reset;
if (opt_skb) {
- /* This is where we would goto ipv6_pktoptions. */
+ /* XXX This is where we would goto ipv6_pktoptions. */
__kfree_skb(opt_skb);
}
return 0;
reset:
- dccp_v6_ctl_send_reset(skb);
+ dccp_v6_ctl_send_reset(sk, skb);
discard:
if (opt_skb != NULL)
__kfree_skb(opt_skb);
@@ -1043,12 +818,20 @@ static int dccp_v6_rcv(struct sk_buff **pskb)
const struct dccp_hdr *dh;
struct sk_buff *skb = *pskb;
struct sock *sk;
+ int min_cov;
- /* Step 1: Check header basics: */
+ /* Step 1: Check header basics */
if (dccp_invalid_packet(skb))
goto discard_it;
+ /* Step 1: If header checksum is incorrect, drop packet and return. */
+ if (dccp_v6_csum_finish(skb, &skb->nh.ipv6h->saddr,
+ &skb->nh.ipv6h->daddr)) {
+ DCCP_WARN("dropped packet with invalid checksum\n");
+ goto discard_it;
+ }
+
dh = dccp_hdr(skb);
DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(skb);
@@ -1068,11 +851,12 @@ static int dccp_v6_rcv(struct sk_buff **pskb)
/*
* Step 2:
* If no socket ...
- * Generate Reset(No Connection) unless P.type == Reset
- * Drop packet and return
*/
- if (sk == NULL)
+ if (sk == NULL) {
+ dccp_pr_debug("failed to look up flow ID in table and "
+ "get corresponding socket\n");
goto no_dccp_socket;
+ }
/*
* Step 2:
@@ -1080,43 +864,226 @@ static int dccp_v6_rcv(struct sk_buff **pskb)
* Generate Reset(No Connection) unless P.type == Reset
* Drop packet and return
*/
- if (sk->sk_state == DCCP_TIME_WAIT)
- goto do_time_wait;
+ if (sk->sk_state == DCCP_TIME_WAIT) {
+ dccp_pr_debug("sk->sk_state == DCCP_TIME_WAIT: do_time_wait\n");
+ inet_twsk_put(inet_twsk(sk));
+ goto no_dccp_socket;
+ }
+
+ /*
+ * RFC 4340, sec. 9.2.1: Minimum Checksum Coverage
+ * o if MinCsCov = 0, only packets with CsCov = 0 are accepted
+ * o if MinCsCov > 0, also accept packets with CsCov >= MinCsCov
+ */
+ min_cov = dccp_sk(sk)->dccps_pcrlen;
+ if (dh->dccph_cscov && (min_cov == 0 || dh->dccph_cscov < min_cov)) {
+ dccp_pr_debug("Packet CsCov %d does not satisfy MinCsCov %d\n",
+ dh->dccph_cscov, min_cov);
+ /* FIXME: send Data Dropped option (see also dccp_v4_rcv) */
+ goto discard_and_relse;
+ }
if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
goto discard_and_relse;
- return sk_receive_skb(sk, skb) ? -1 : 0;
+ return sk_receive_skb(sk, skb, 1) ? -1 : 0;
no_dccp_socket:
if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
goto discard_it;
/*
* Step 2:
+ * If no socket ...
* Generate Reset(No Connection) unless P.type == Reset
* Drop packet and return
*/
if (dh->dccph_type != DCCP_PKT_RESET) {
DCCP_SKB_CB(skb)->dccpd_reset_code =
DCCP_RESET_CODE_NO_CONNECTION;
- dccp_v6_ctl_send_reset(skb);
+ dccp_v6_ctl_send_reset(sk, skb);
}
-discard_it:
-
- /*
- * Discard frame
- */
+discard_it:
kfree_skb(skb);
return 0;
discard_and_relse:
sock_put(sk);
goto discard_it;
+}
-do_time_wait:
- inet_twsk_put(inet_twsk(sk));
- goto no_dccp_socket;
+static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
+ int addr_len)
+{
+ struct sockaddr_in6 *usin = (struct sockaddr_in6 *)uaddr;
+ struct inet_connection_sock *icsk = inet_csk(sk);
+ struct inet_sock *inet = inet_sk(sk);
+ struct ipv6_pinfo *np = inet6_sk(sk);
+ struct dccp_sock *dp = dccp_sk(sk);
+ struct in6_addr *saddr = NULL, *final_p = NULL, final;
+ struct flowi fl;
+ struct dst_entry *dst;
+ int addr_type;
+ int err;
+
+ dp->dccps_role = DCCP_ROLE_CLIENT;
+
+ if (addr_len < SIN6_LEN_RFC2133)
+ return -EINVAL;
+
+ if (usin->sin6_family != AF_INET6)
+ return -EAFNOSUPPORT;
+
+ memset(&fl, 0, sizeof(fl));
+
+ if (np->sndflow) {
+ fl.fl6_flowlabel = usin->sin6_flowinfo & IPV6_FLOWINFO_MASK;
+ IP6_ECN_flow_init(fl.fl6_flowlabel);
+ if (fl.fl6_flowlabel & IPV6_FLOWLABEL_MASK) {
+ struct ip6_flowlabel *flowlabel;
+ flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel);
+ if (flowlabel == NULL)
+ return -EINVAL;
+ ipv6_addr_copy(&usin->sin6_addr, &flowlabel->dst);
+ fl6_sock_release(flowlabel);
+ }
+ }
+ /*
+ * connect() to INADDR_ANY means loopback (BSD'ism).
+ */
+ if (ipv6_addr_any(&usin->sin6_addr))
+ usin->sin6_addr.s6_addr[15] = 1;
+
+ addr_type = ipv6_addr_type(&usin->sin6_addr);
+
+ if (addr_type & IPV6_ADDR_MULTICAST)
+ return -ENETUNREACH;
+
+ if (addr_type & IPV6_ADDR_LINKLOCAL) {
+ if (addr_len >= sizeof(struct sockaddr_in6) &&
+ usin->sin6_scope_id) {
+ /* If interface is set while binding, indices
+ * must coincide.
+ */
+ if (sk->sk_bound_dev_if &&
+ sk->sk_bound_dev_if != usin->sin6_scope_id)
+ return -EINVAL;
+
+ sk->sk_bound_dev_if = usin->sin6_scope_id;
+ }
+
+ /* Connect to link-local address requires an interface */
+ if (!sk->sk_bound_dev_if)
+ return -EINVAL;
+ }
+
+ ipv6_addr_copy(&np->daddr, &usin->sin6_addr);
+ np->flow_label = fl.fl6_flowlabel;
+
+ /*
+ * DCCP over IPv4
+ */
+ if (addr_type == IPV6_ADDR_MAPPED) {
+ u32 exthdrlen = icsk->icsk_ext_hdr_len;
+ struct sockaddr_in sin;
+
+ SOCK_DEBUG(sk, "connect: ipv4 mapped\n");
+
+ if (__ipv6_only_sock(sk))
+ return -ENETUNREACH;
+
+ sin.sin_family = AF_INET;
+ sin.sin_port = usin->sin6_port;
+ sin.sin_addr.s_addr = usin->sin6_addr.s6_addr32[3];
+
+ icsk->icsk_af_ops = &dccp_ipv6_mapped;
+ sk->sk_backlog_rcv = dccp_v4_do_rcv;
+
+ err = dccp_v4_connect(sk, (struct sockaddr *)&sin, sizeof(sin));
+ if (err) {
+ icsk->icsk_ext_hdr_len = exthdrlen;
+ icsk->icsk_af_ops = &dccp_ipv6_af_ops;
+ sk->sk_backlog_rcv = dccp_v6_do_rcv;
+ goto failure;
+ } else {
+ ipv6_addr_set(&np->saddr, 0, 0, htonl(0x0000FFFF),
+ inet->saddr);
+ ipv6_addr_set(&np->rcv_saddr, 0, 0, htonl(0x0000FFFF),
+ inet->rcv_saddr);
+ }
+
+ return err;
+ }
+
+ if (!ipv6_addr_any(&np->rcv_saddr))
+ saddr = &np->rcv_saddr;
+
+ fl.proto = IPPROTO_DCCP;
+ ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
+ ipv6_addr_copy(&fl.fl6_src, saddr ? saddr : &np->saddr);
+ fl.oif = sk->sk_bound_dev_if;
+ fl.fl_ip_dport = usin->sin6_port;
+ fl.fl_ip_sport = inet->sport;
+ security_sk_classify_flow(sk, &fl);
+
+ if (np->opt != NULL && np->opt->srcrt != NULL) {
+ const struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
+
+ ipv6_addr_copy(&final, &fl.fl6_dst);
+ ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+ final_p = &final;
+ }
+
+ err = ip6_dst_lookup(sk, &dst, &fl);
+ if (err)
+ goto failure;
+
+ if (final_p)
+ ipv6_addr_copy(&fl.fl6_dst, final_p);
+
+ err = xfrm_lookup(&dst, &fl, sk, 0);
+ if (err < 0)
+ goto failure;
+
+ if (saddr == NULL) {
+ saddr = &fl.fl6_src;
+ ipv6_addr_copy(&np->rcv_saddr, saddr);
+ }
+
+ /* set the source address */
+ ipv6_addr_copy(&np->saddr, saddr);
+ inet->rcv_saddr = LOOPBACK4_IPV6;
+
+ __ip6_dst_store(sk, dst, NULL, NULL);
+
+ icsk->icsk_ext_hdr_len = 0;
+ if (np->opt != NULL)
+ icsk->icsk_ext_hdr_len = (np->opt->opt_flen +
+ np->opt->opt_nflen);
+
+ inet->dport = usin->sin6_port;
+
+ dccp_set_state(sk, DCCP_REQUESTING);
+ err = inet6_hash_connect(&dccp_death_row, sk);
+ if (err)
+ goto late_failure;
+
+ dp->dccps_iss = secure_dccpv6_sequence_number(np->saddr.s6_addr32,
+ np->daddr.s6_addr32,
+ inet->sport, inet->dport);
+ err = dccp_connect(sk);
+ if (err)
+ goto late_failure;
+
+ return 0;
+
+late_failure:
+ dccp_set_state(sk, DCCP_CLOSED);
+ __sk_dst_reset(sk);
+failure:
+ inet->dport = 0;
+ sk->sk_route_caps = 0;
+ return err;
}
static struct inet_connection_sock_af_ops dccp_ipv6_af_ops = {
@@ -1179,6 +1146,10 @@ static int dccp_v6_destroy_sock(struct sock *sk)
return inet6_destroy_sock(sk);
}
+static struct timewait_sock_ops dccp6_timewait_sock_ops = {
+ .twsk_obj_size = sizeof(struct dccp6_timewait_sock),
+};
+
static struct proto dccp_v6_prot = {
.name = "DCCPv6",
.owner = THIS_MODULE,
diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c
index 36db5be2a9e9..4c9e26775f72 100644
--- a/net/dccp/minisocks.c
+++ b/net/dccp/minisocks.c
@@ -11,6 +11,7 @@
*/
#include <linux/dccp.h>
+#include <linux/kernel.h>
#include <linux/skbuff.h>
#include <linux/timer.h>
@@ -82,8 +83,7 @@ void dccp_time_wait(struct sock *sk, int state, int timeo)
* socket up. We've got bigger problems than
* non-graceful socket closings.
*/
- LIMIT_NETDEBUG(KERN_INFO "DCCP: time wait bucket "
- "table overflow\n");
+ DCCP_WARN("time wait bucket table overflow\n");
}
dccp_done(sk);
@@ -96,8 +96,8 @@ struct sock *dccp_create_openreq_child(struct sock *sk,
/*
* Step 3: Process LISTEN state
*
- * // Generate a new socket and switch to that socket
- * Set S := new socket for this port pair
+ * (* Generate a new socket and switch to that socket *)
+ * Set S := new socket for this port pair
*/
struct sock *newsk = inet_csk_clone(sk, req, GFP_ATOMIC);
@@ -146,9 +146,9 @@ out_free:
/*
* Step 3: Process LISTEN state
*
- * Choose S.ISS (initial seqno) or set from Init Cookie
- * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init
- * Cookie
+ * Choose S.ISS (initial seqno) or set from Init Cookies
+ * Initialize S.GAR := S.ISS
+ * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookies
*/
/* See dccp_v4_conn_request */
@@ -194,15 +194,17 @@ struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
/* Check for retransmitted REQUEST */
if (dccp_hdr(skb)->dccph_type == DCCP_PKT_REQUEST) {
- if (after48(DCCP_SKB_CB(skb)->dccpd_seq,
- dccp_rsk(req)->dreq_isr)) {
- struct dccp_request_sock *dreq = dccp_rsk(req);
+ struct dccp_request_sock *dreq = dccp_rsk(req);
+ if (after48(DCCP_SKB_CB(skb)->dccpd_seq, dreq->dreq_isr)) {
dccp_pr_debug("Retransmitted REQUEST\n");
- /* Send another RESPONSE packet */
- dccp_set_seqno(&dreq->dreq_iss, dreq->dreq_iss + 1);
- dccp_set_seqno(&dreq->dreq_isr,
- DCCP_SKB_CB(skb)->dccpd_seq);
+ dreq->dreq_isr = DCCP_SKB_CB(skb)->dccpd_seq;
+ /*
+ * Send another RESPONSE packet
+ * To protect against Request floods, increment retrans
+ * counter (backoff, monitored by dccp_response_timer).
+ */
+ req->retrans++;
req->rsk_ops->rtx_syn_ack(sk, req, NULL);
}
/* Network Duplicate, discard packet */
@@ -242,7 +244,7 @@ listen_overflow:
DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_TOO_BUSY;
drop:
if (dccp_hdr(skb)->dccph_type != DCCP_PKT_RESET)
- req->rsk_ops->send_reset(skb);
+ req->rsk_ops->send_reset(sk, skb);
inet_csk_reqsk_queue_drop(sk, req, prev);
goto out;
@@ -282,3 +284,19 @@ int dccp_child_process(struct sock *parent, struct sock *child,
}
EXPORT_SYMBOL_GPL(dccp_child_process);
+
+void dccp_reqsk_send_ack(struct sk_buff *skb, struct request_sock *rsk)
+{
+ DCCP_BUG("DCCP-ACK packets are never sent in LISTEN/RESPOND state");
+}
+
+EXPORT_SYMBOL_GPL(dccp_reqsk_send_ack);
+
+void dccp_reqsk_init(struct request_sock *req, struct sk_buff *skb)
+{
+ inet_rsk(req)->rmt_port = dccp_hdr(skb)->dccph_sport;
+ inet_rsk(req)->acked = 0;
+ req->rcv_wnd = sysctl_dccp_feat_sequence_window;
+}
+
+EXPORT_SYMBOL_GPL(dccp_reqsk_init);
diff --git a/net/dccp/options.c b/net/dccp/options.c
index fb0db1f7cd7b..f398b43bc055 100644
--- a/net/dccp/options.c
+++ b/net/dccp/options.c
@@ -22,23 +22,23 @@
#include "dccp.h"
#include "feat.h"
-int dccp_feat_default_sequence_window = DCCPF_INITIAL_SEQUENCE_WINDOW;
-int dccp_feat_default_rx_ccid = DCCPF_INITIAL_CCID;
-int dccp_feat_default_tx_ccid = DCCPF_INITIAL_CCID;
-int dccp_feat_default_ack_ratio = DCCPF_INITIAL_ACK_RATIO;
-int dccp_feat_default_send_ack_vector = DCCPF_INITIAL_SEND_ACK_VECTOR;
-int dccp_feat_default_send_ndp_count = DCCPF_INITIAL_SEND_NDP_COUNT;
+int sysctl_dccp_feat_sequence_window = DCCPF_INITIAL_SEQUENCE_WINDOW;
+int sysctl_dccp_feat_rx_ccid = DCCPF_INITIAL_CCID;
+int sysctl_dccp_feat_tx_ccid = DCCPF_INITIAL_CCID;
+int sysctl_dccp_feat_ack_ratio = DCCPF_INITIAL_ACK_RATIO;
+int sysctl_dccp_feat_send_ack_vector = DCCPF_INITIAL_SEND_ACK_VECTOR;
+int sysctl_dccp_feat_send_ndp_count = DCCPF_INITIAL_SEND_NDP_COUNT;
-EXPORT_SYMBOL_GPL(dccp_feat_default_sequence_window);
+EXPORT_SYMBOL_GPL(sysctl_dccp_feat_sequence_window);
void dccp_minisock_init(struct dccp_minisock *dmsk)
{
- dmsk->dccpms_sequence_window = dccp_feat_default_sequence_window;
- dmsk->dccpms_rx_ccid = dccp_feat_default_rx_ccid;
- dmsk->dccpms_tx_ccid = dccp_feat_default_tx_ccid;
- dmsk->dccpms_ack_ratio = dccp_feat_default_ack_ratio;
- dmsk->dccpms_send_ack_vector = dccp_feat_default_send_ack_vector;
- dmsk->dccpms_send_ndp_count = dccp_feat_default_send_ndp_count;
+ dmsk->dccpms_sequence_window = sysctl_dccp_feat_sequence_window;
+ dmsk->dccpms_rx_ccid = sysctl_dccp_feat_rx_ccid;
+ dmsk->dccpms_tx_ccid = sysctl_dccp_feat_tx_ccid;
+ dmsk->dccpms_ack_ratio = sysctl_dccp_feat_ack_ratio;
+ dmsk->dccpms_send_ack_vector = sysctl_dccp_feat_send_ack_vector;
+ dmsk->dccpms_send_ndp_count = sysctl_dccp_feat_send_ndp_count;
}
static u32 dccp_decode_value_var(const unsigned char *bf, const u8 len)
@@ -60,12 +60,9 @@ static u32 dccp_decode_value_var(const unsigned char *bf, const u8 len)
int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
{
struct dccp_sock *dp = dccp_sk(sk);
-#ifdef CONFIG_IP_DCCP_DEBUG
- const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
- "CLIENT rx opt: " : "server rx opt: ";
-#endif
const struct dccp_hdr *dh = dccp_hdr(skb);
const u8 pkt_type = DCCP_SKB_CB(skb)->dccpd_type;
+ u64 ackno = DCCP_SKB_CB(skb)->dccpd_ack_seq;
unsigned char *options = (unsigned char *)dh + dccp_hdr_len(skb);
unsigned char *opt_ptr = options;
const unsigned char *opt_end = (unsigned char *)dh +
@@ -119,7 +116,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
goto out_invalid_option;
opt_recv->dccpor_ndp = dccp_decode_value_var(value, len);
- dccp_pr_debug("%sNDP count=%d\n", debug_prefix,
+ dccp_pr_debug("%s rx opt: NDP count=%d\n", dccp_role(sk),
opt_recv->dccpor_ndp);
break;
case DCCPO_CHANGE_L:
@@ -153,7 +150,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
break;
if (dccp_msk(sk)->dccpms_send_ack_vector &&
- dccp_ackvec_parse(sk, skb, opt, value, len))
+ dccp_ackvec_parse(sk, skb, &ackno, opt, value, len))
goto out_invalid_option;
break;
case DCCPO_TIMESTAMP:
@@ -165,8 +162,8 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
dp->dccps_timestamp_echo = opt_recv->dccpor_timestamp;
dccp_timestamp(sk, &dp->dccps_timestamp_time);
- dccp_pr_debug("%sTIMESTAMP=%u, ackno=%llu\n",
- debug_prefix, opt_recv->dccpor_timestamp,
+ dccp_pr_debug("%s rx opt: TIMESTAMP=%u, ackno=%llu\n",
+ dccp_role(sk), opt_recv->dccpor_timestamp,
(unsigned long long)
DCCP_SKB_CB(skb)->dccpd_ack_seq);
break;
@@ -176,8 +173,8 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
opt_recv->dccpor_timestamp_echo = ntohl(*(__be32 *)value);
- dccp_pr_debug("%sTIMESTAMP_ECHO=%u, len=%d, ackno=%llu, ",
- debug_prefix,
+ dccp_pr_debug("%s rx opt: TIMESTAMP_ECHO=%u, len=%d, "
+ "ackno=%llu, ", dccp_role(sk),
opt_recv->dccpor_timestamp_echo,
len + 2,
(unsigned long long)
@@ -211,8 +208,8 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
if (elapsed_time > opt_recv->dccpor_elapsed_time)
opt_recv->dccpor_elapsed_time = elapsed_time;
- dccp_pr_debug("%sELAPSED_TIME=%d\n", debug_prefix,
- elapsed_time);
+ dccp_pr_debug("%s rx opt: ELAPSED_TIME=%d\n",
+ dccp_role(sk), elapsed_time);
break;
/*
* From RFC 4340, sec. 10.3:
@@ -242,9 +239,8 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
}
break;
default:
- pr_info("DCCP(%p): option %d(len=%d) not "
- "implemented, ignoring\n",
- sk, opt, len);
+ DCCP_CRIT("DCCP(%p): option %d(len=%d) not "
+ "implemented, ignoring", sk, opt, len);
break;
}
@@ -261,7 +257,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
out_invalid_option:
DCCP_INC_STATS_BH(DCCP_MIB_INVALIDOPT);
DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_OPTION_ERROR;
- pr_info("DCCP(%p): invalid option %d, len=%d\n", sk, opt, len);
+ DCCP_WARN("DCCP(%p): invalid option %d, len=%d", sk, opt, len);
return -1;
}
@@ -451,8 +447,7 @@ static int dccp_insert_feat_opt(struct sk_buff *skb, u8 type, u8 feat,
u8 *to;
if (DCCP_SKB_CB(skb)->dccpd_opt_len + len + 3 > DCCP_MAX_OPT_LEN) {
- LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small"
- " to insert feature %d option!\n", feat);
+ DCCP_WARN("packet too small for feature %d option!\n", feat);
return -1;
}
@@ -465,8 +460,10 @@ static int dccp_insert_feat_opt(struct sk_buff *skb, u8 type, u8 feat,
if (len)
memcpy(to, val, len);
- dccp_pr_debug("option %d feat %d len %d\n", type, feat, len);
+ dccp_pr_debug("%s(%s (%d), ...), length %d\n",
+ dccp_feat_typename(type),
+ dccp_feat_name(feat), feat, len);
return 0;
}
diff --git a/net/dccp/output.c b/net/dccp/output.c
index 7102e3aed4ca..400c30b6fcae 100644
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -88,16 +88,15 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
return -EPROTO;
}
- skb->h.raw = skb_push(skb, dccp_header_size);
- dh = dccp_hdr(skb);
/* Build DCCP header and checksum it. */
- memset(dh, 0, dccp_header_size);
+ dh = dccp_zeroed_hdr(skb, dccp_header_size);
dh->dccph_type = dcb->dccpd_type;
dh->dccph_sport = inet->sport;
dh->dccph_dport = inet->dport;
dh->dccph_doff = (dccp_header_size + dcb->dccpd_opt_len) / 4;
dh->dccph_ccval = dcb->dccpd_ccval;
+ dh->dccph_cscov = dp->dccps_pcslen;
/* XXX For now we're using only 48 bits sequence numbers */
dh->dccph_x = 1;
@@ -117,7 +116,7 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
break;
}
- icsk->icsk_af_ops->send_check(sk, skb->len, skb);
+ icsk->icsk_af_ops->send_check(sk, 0, skb);
if (set_ack)
dccp_event_ack_sent(sk);
@@ -125,17 +124,8 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
- err = icsk->icsk_af_ops->queue_xmit(skb, 0);
- if (err <= 0)
- return err;
-
- /* NET_XMIT_CN is special. It does not guarantee,
- * that this packet is lost. It tells that device
- * is about to start to drop packets or already
- * drops some packets of the same priority and
- * invokes us to send less aggressively.
- */
- return err == NET_XMIT_CN ? 0 : err;
+ err = icsk->icsk_af_ops->queue_xmit(skb, sk, 0);
+ return net_xmit_eval(err);
}
return -ENOBUFS;
}
@@ -205,8 +195,7 @@ static int dccp_wait_for_ccid(struct sock *sk, struct sk_buff *skb,
if (signal_pending(current))
goto do_interrupted;
- rc = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb,
- skb->len);
+ rc = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb);
if (rc <= 0)
break;
delay = msecs_to_jiffies(rc);
@@ -251,25 +240,23 @@ void dccp_write_xmit(struct sock *sk, int block)
{
struct dccp_sock *dp = dccp_sk(sk);
struct sk_buff *skb;
- long timeo = 30000; /* If a packet is taking longer than 2 secs
- we have other issues */
+ long timeo = DCCP_XMIT_TIMEO; /* If a packet is taking longer than
+ this we have other issues */
while ((skb = skb_peek(&sk->sk_write_queue))) {
- int err = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb,
- skb->len);
+ int err = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb);
if (err > 0) {
if (!block) {
sk_reset_timer(sk, &dp->dccps_xmit_timer,
msecs_to_jiffies(err)+jiffies);
break;
- } else
+ } else {
err = dccp_wait_for_ccid(sk, skb, &timeo);
- if (err) {
- printk(KERN_CRIT "%s:err at dccp_wait_for_ccid"
- " %d\n", __FUNCTION__, err);
- dump_stack();
+ timeo = DCCP_XMIT_TIMEO;
}
+ if (err)
+ DCCP_BUG("err=%d after dccp_wait_for_ccid", err);
}
skb_dequeue(&sk->sk_write_queue);
@@ -291,12 +278,9 @@ void dccp_write_xmit(struct sock *sk, int block)
err = dccp_transmit_skb(sk, skb);
ccid_hc_tx_packet_sent(dp->dccps_hc_tx_ccid, sk, 0, len);
- if (err) {
- printk(KERN_CRIT "%s:err from "
- "ccid_hc_tx_packet_sent %d\n",
- __FUNCTION__, err);
- dump_stack();
- }
+ if (err)
+ DCCP_BUG("err=%d after ccid_hc_tx_packet_sent",
+ err);
} else
kfree(skb);
}
@@ -329,9 +313,10 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
skb_reserve(skb, sk->sk_prot->max_header);
skb->dst = dst_clone(dst);
- skb->csum = 0;
dreq = dccp_rsk(req);
+ if (inet_rsk(req)->acked) /* increase ISS upon retransmission */
+ dccp_inc_seqno(&dreq->dreq_iss);
DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESPONSE;
DCCP_SKB_CB(skb)->dccpd_seq = dreq->dreq_iss;
@@ -340,10 +325,8 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
return NULL;
}
- skb->h.raw = skb_push(skb, dccp_header_size);
-
- dh = dccp_hdr(skb);
- memset(dh, 0, dccp_header_size);
+ /* Build and checksum header */
+ dh = dccp_zeroed_hdr(skb, dccp_header_size);
dh->dccph_sport = inet_sk(sk)->sport;
dh->dccph_dport = inet_rsk(req)->rmt_port;
@@ -355,6 +338,10 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dreq->dreq_isr);
dccp_hdr_response(skb)->dccph_resp_service = dreq->dreq_service;
+ dccp_csum_outgoing(skb);
+
+ /* We use `acked' to remember that a Response was already sent. */
+ inet_rsk(req)->acked = 1;
DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
return skb;
}
@@ -379,7 +366,6 @@ static struct sk_buff *dccp_make_reset(struct sock *sk, struct dst_entry *dst,
skb_reserve(skb, sk->sk_prot->max_header);
skb->dst = dst_clone(dst);
- skb->csum = 0;
dccp_inc_seqno(&dp->dccps_gss);
@@ -392,10 +378,7 @@ static struct sk_buff *dccp_make_reset(struct sock *sk, struct dst_entry *dst,
return NULL;
}
- skb->h.raw = skb_push(skb, dccp_header_size);
-
- dh = dccp_hdr(skb);
- memset(dh, 0, dccp_header_size);
+ dh = dccp_zeroed_hdr(skb, dccp_header_size);
dh->dccph_sport = inet_sk(sk)->sport;
dh->dccph_dport = inet_sk(sk)->dport;
@@ -407,7 +390,7 @@ static struct sk_buff *dccp_make_reset(struct sock *sk, struct dst_entry *dst,
dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dp->dccps_gsr);
dccp_hdr_reset(skb)->dccph_reset_code = code;
- inet_csk(sk)->icsk_af_ops->send_check(sk, skb->len, skb);
+ inet_csk(sk)->icsk_af_ops->send_check(sk, 0, skb);
DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
return skb;
@@ -426,9 +409,8 @@ int dccp_send_reset(struct sock *sk, enum dccp_reset_codes code)
code);
if (skb != NULL) {
memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
- err = inet_csk(sk)->icsk_af_ops->queue_xmit(skb, 0);
- if (err == NET_XMIT_CN)
- err = 0;
+ err = inet_csk(sk)->icsk_af_ops->queue_xmit(skb, sk, 0);
+ return net_xmit_eval(err);
}
}
@@ -449,7 +431,6 @@ static inline void dccp_connect_init(struct sock *sk)
dccp_sync_mss(sk, dst_mtu(dst));
- dccp_update_gss(sk, dp->dccps_iss);
/*
* SWL and AWL are initially adjusted so that they are not less than
* the initial Sequence Numbers received and sent, respectively:
@@ -458,8 +439,13 @@ static inline void dccp_connect_init(struct sock *sk)
* These adjustments MUST be applied only at the beginning of the
* connection.
*/
+ dccp_update_gss(sk, dp->dccps_iss);
dccp_set_seqno(&dp->dccps_awl, max48(dp->dccps_awl, dp->dccps_iss));
+ /* S.GAR - greatest valid acknowledgement number received on a non-Sync;
+ * initialized to S.ISS (sec. 8.5) */
+ dp->dccps_gar = dp->dccps_iss;
+
icsk->icsk_retransmits = 0;
init_timer(&dp->dccps_xmit_timer);
dp->dccps_xmit_timer.data = (unsigned long)sk;
@@ -481,7 +467,6 @@ int dccp_connect(struct sock *sk)
skb_reserve(skb, sk->sk_prot->max_header);
DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_REQUEST;
- skb->csum = 0;
dccp_skb_entail(sk, skb);
dccp_transmit_skb(sk, skb_clone(skb, GFP_KERNEL));
@@ -513,7 +498,6 @@ void dccp_send_ack(struct sock *sk)
/* Reserve space for headers */
skb_reserve(skb, sk->sk_prot->max_header);
- skb->csum = 0;
DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_ACK;
dccp_transmit_skb(sk, skb);
}
@@ -567,7 +551,6 @@ void dccp_send_sync(struct sock *sk, const u64 seq,
/* Reserve space for headers and prepare control bits. */
skb_reserve(skb, sk->sk_prot->max_header);
- skb->csum = 0;
DCCP_SKB_CB(skb)->dccpd_type = pkt_type;
DCCP_SKB_CB(skb)->dccpd_seq = seq;
@@ -593,7 +576,6 @@ void dccp_send_close(struct sock *sk, const int active)
/* Reserve space for headers and prepare control bits. */
skb_reserve(skb, sk->sk_prot->max_header);
- skb->csum = 0;
DCCP_SKB_CB(skb)->dccpd_type = dp->dccps_role == DCCP_ROLE_CLIENT ?
DCCP_PKT_CLOSE : DCCP_PKT_CLOSEREQ;
diff --git a/net/dccp/probe.c b/net/dccp/probe.c
index 146496fce2e2..f81e37de35d5 100644
--- a/net/dccp/probe.c
+++ b/net/dccp/probe.c
@@ -106,8 +106,10 @@ static int jdccp_sendmsg(struct kiocb *iocb, struct sock *sk,
}
static struct jprobe dccp_send_probe = {
- .kp = { .addr = (kprobe_opcode_t *)&dccp_sendmsg, },
- .entry = (kprobe_opcode_t *)&jdccp_sendmsg,
+ .kp = {
+ .symbol_name = "dccp_sendmsg",
+ },
+ .entry = JPROBE_ENTRY(jdccp_sendmsg),
};
static int dccpprobe_open(struct inode *inode, struct file *file)
@@ -160,6 +162,8 @@ static __init int dccpprobe_init(void)
init_waitqueue_head(&dccpw.wait);
spin_lock_init(&dccpw.lock);
dccpw.fifo = kfifo_alloc(bufsize, GFP_KERNEL, &dccpw.lock);
+ if (IS_ERR(dccpw.fifo))
+ return PTR_ERR(dccpw.fifo);
if (!proc_net_fops_create(procname, S_IRUSR, &dccpprobe_fops))
goto err0;
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 72cbdcfc2c65..5ec47d9ee447 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -52,6 +52,9 @@ struct inet_hashinfo __cacheline_aligned dccp_hashinfo = {
EXPORT_SYMBOL_GPL(dccp_hashinfo);
+/* the maximum queue length for tx in packets. 0 is no limit */
+int sysctl_dccp_tx_qlen __read_mostly = 5;
+
void dccp_set_state(struct sock *sk, const int state)
{
const int oldstate = sk->sk_state;
@@ -212,6 +215,7 @@ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
dccp_init_xmit_timers(sk);
icsk->icsk_rto = DCCP_TIMEOUT_INIT;
+ icsk->icsk_syn_retries = sysctl_dccp_request_retries;
sk->sk_state = DCCP_CLOSED;
sk->sk_write_space = dccp_write_space;
icsk->icsk_sync_mss = dccp_sync_mss;
@@ -262,12 +266,12 @@ int dccp_destroy_sock(struct sock *sk)
EXPORT_SYMBOL_GPL(dccp_destroy_sock);
-static inline int dccp_listen_start(struct sock *sk)
+static inline int dccp_listen_start(struct sock *sk, int backlog)
{
struct dccp_sock *dp = dccp_sk(sk);
dp->dccps_role = DCCP_ROLE_LISTEN;
- return inet_csk_listen_start(sk, TCP_SYNQ_HSIZE);
+ return inet_csk_listen_start(sk, backlog);
}
int dccp_disconnect(struct sock *sk, int flags)
@@ -451,9 +455,8 @@ out_free_val:
static int do_dccp_setsockopt(struct sock *sk, int level, int optname,
char __user *optval, int optlen)
{
- struct dccp_sock *dp;
- int err;
- int val;
+ struct dccp_sock *dp = dccp_sk(sk);
+ int val, err = 0;
if (optlen < sizeof(int))
return -EINVAL;
@@ -465,14 +468,11 @@ static int do_dccp_setsockopt(struct sock *sk, int level, int optname,
return dccp_setsockopt_service(sk, val, optval, optlen);
lock_sock(sk);
- dp = dccp_sk(sk);
- err = 0;
-
switch (optname) {
case DCCP_SOCKOPT_PACKET_SIZE:
- dp->dccps_packet_size = val;
+ DCCP_WARN("sockopt(PACKET_SIZE) is deprecated: fix your app\n");
+ err = 0;
break;
-
case DCCP_SOCKOPT_CHANGE_L:
if (optlen != sizeof(struct dccp_so_feat))
err = -EINVAL;
@@ -481,7 +481,6 @@ static int do_dccp_setsockopt(struct sock *sk, int level, int optname,
(struct dccp_so_feat __user *)
optval);
break;
-
case DCCP_SOCKOPT_CHANGE_R:
if (optlen != sizeof(struct dccp_so_feat))
err = -EINVAL;
@@ -490,12 +489,26 @@ static int do_dccp_setsockopt(struct sock *sk, int level, int optname,
(struct dccp_so_feat __user *)
optval);
break;
-
+ case DCCP_SOCKOPT_SEND_CSCOV: /* sender side, RFC 4340, sec. 9.2 */
+ if (val < 0 || val > 15)
+ err = -EINVAL;
+ else
+ dp->dccps_pcslen = val;
+ break;
+ case DCCP_SOCKOPT_RECV_CSCOV: /* receiver side, RFC 4340 sec. 9.2.1 */
+ if (val < 0 || val > 15)
+ err = -EINVAL;
+ else {
+ dp->dccps_pcrlen = val;
+ /* FIXME: add feature negotiation,
+ * ChangeL(MinimumChecksumCoverage, val) */
+ }
+ break;
default:
err = -ENOPROTOOPT;
break;
}
-
+
release_sock(sk);
return err;
}
@@ -569,12 +582,17 @@ static int do_dccp_getsockopt(struct sock *sk, int level, int optname,
switch (optname) {
case DCCP_SOCKOPT_PACKET_SIZE:
- val = dp->dccps_packet_size;
- len = sizeof(dp->dccps_packet_size);
- break;
+ DCCP_WARN("sockopt(PACKET_SIZE) is deprecated: fix your app\n");
+ return 0;
case DCCP_SOCKOPT_SERVICE:
return dccp_getsockopt_service(sk, len,
(__be32 __user *)optval, optlen);
+ case DCCP_SOCKOPT_SEND_CSCOV:
+ val = dp->dccps_pcslen;
+ break;
+ case DCCP_SOCKOPT_RECV_CSCOV:
+ val = dp->dccps_pcrlen;
+ break;
case 128 ... 191:
return ccid_hc_rx_getsockopt(dp->dccps_hc_rx_ccid, sk, optname,
len, (u32 __user *)optval, optlen);
@@ -630,6 +648,13 @@ int dccp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
return -EMSGSIZE;
lock_sock(sk);
+
+ if (sysctl_dccp_tx_qlen &&
+ (sk->sk_write_queue.qlen >= sysctl_dccp_tx_qlen)) {
+ rc = -EAGAIN;
+ goto out_release;
+ }
+
timeo = sock_sndtimeo(sk, noblock);
/*
@@ -788,7 +813,7 @@ int inet_dccp_listen(struct socket *sock, int backlog)
* FIXME: here it probably should be sk->sk_prot->listen_start
* see tcp_listen_start
*/
- err = dccp_listen_start(sk);
+ err = dccp_listen_start(sk, backlog);
if (err)
goto out;
}
@@ -1008,8 +1033,7 @@ static int __init dccp_init(void)
} while (!dccp_hashinfo.ehash && --ehash_order > 0);
if (!dccp_hashinfo.ehash) {
- printk(KERN_CRIT "Failed to allocate DCCP "
- "established hash table\n");
+ DCCP_CRIT("Failed to allocate DCCP established hash table");
goto out_free_bind_bucket_cachep;
}
@@ -1031,7 +1055,7 @@ static int __init dccp_init(void)
} while (!dccp_hashinfo.bhash && --bhash_order >= 0);
if (!dccp_hashinfo.bhash) {
- printk(KERN_CRIT "Failed to allocate DCCP bind hash table\n");
+ DCCP_CRIT("Failed to allocate DCCP bind hash table");
goto out_free_dccp_ehash;
}
diff --git a/net/dccp/sysctl.c b/net/dccp/sysctl.c
index 38bc157876f3..fdcfca3e9208 100644
--- a/net/dccp/sysctl.c
+++ b/net/dccp/sysctl.c
@@ -11,6 +11,7 @@
#include <linux/mm.h>
#include <linux/sysctl.h>
+#include "dccp.h"
#include "feat.h"
#ifndef CONFIG_SYSCTL
@@ -19,53 +20,76 @@
static struct ctl_table dccp_default_table[] = {
{
- .ctl_name = NET_DCCP_DEFAULT_SEQ_WINDOW,
.procname = "seq_window",
- .data = &dccp_feat_default_sequence_window,
- .maxlen = sizeof(dccp_feat_default_sequence_window),
+ .data = &sysctl_dccp_feat_sequence_window,
+ .maxlen = sizeof(sysctl_dccp_feat_sequence_window),
.mode = 0644,
.proc_handler = proc_dointvec,
},
{
- .ctl_name = NET_DCCP_DEFAULT_RX_CCID,
.procname = "rx_ccid",
- .data = &dccp_feat_default_rx_ccid,
- .maxlen = sizeof(dccp_feat_default_rx_ccid),
+ .data = &sysctl_dccp_feat_rx_ccid,
+ .maxlen = sizeof(sysctl_dccp_feat_rx_ccid),
.mode = 0644,
.proc_handler = proc_dointvec,
},
{
- .ctl_name = NET_DCCP_DEFAULT_TX_CCID,
.procname = "tx_ccid",
- .data = &dccp_feat_default_tx_ccid,
- .maxlen = sizeof(dccp_feat_default_tx_ccid),
+ .data = &sysctl_dccp_feat_tx_ccid,
+ .maxlen = sizeof(sysctl_dccp_feat_tx_ccid),
.mode = 0644,
.proc_handler = proc_dointvec,
},
{
- .ctl_name = NET_DCCP_DEFAULT_ACK_RATIO,
.procname = "ack_ratio",
- .data = &dccp_feat_default_ack_ratio,
- .maxlen = sizeof(dccp_feat_default_ack_ratio),
+ .data = &sysctl_dccp_feat_ack_ratio,
+ .maxlen = sizeof(sysctl_dccp_feat_ack_ratio),
.mode = 0644,
.proc_handler = proc_dointvec,
},
{
- .ctl_name = NET_DCCP_DEFAULT_SEND_ACKVEC,
.procname = "send_ackvec",
- .data = &dccp_feat_default_send_ack_vector,
- .maxlen = sizeof(dccp_feat_default_send_ack_vector),
+ .data = &sysctl_dccp_feat_send_ack_vector,
+ .maxlen = sizeof(sysctl_dccp_feat_send_ack_vector),
.mode = 0644,
.proc_handler = proc_dointvec,
},
{
- .ctl_name = NET_DCCP_DEFAULT_SEND_NDP,
.procname = "send_ndp",
- .data = &dccp_feat_default_send_ndp_count,
- .maxlen = sizeof(dccp_feat_default_send_ndp_count),
+ .data = &sysctl_dccp_feat_send_ndp_count,
+ .maxlen = sizeof(sysctl_dccp_feat_send_ndp_count),
.mode = 0644,
.proc_handler = proc_dointvec,
},
+ {
+ .procname = "request_retries",
+ .data = &sysctl_dccp_request_retries,
+ .maxlen = sizeof(sysctl_dccp_request_retries),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
+ {
+ .procname = "retries1",
+ .data = &sysctl_dccp_retries1,
+ .maxlen = sizeof(sysctl_dccp_retries1),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
+ {
+ .procname = "retries2",
+ .data = &sysctl_dccp_retries2,
+ .maxlen = sizeof(sysctl_dccp_retries2),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
+ {
+ .procname = "tx_qlen",
+ .data = &sysctl_dccp_tx_qlen,
+ .maxlen = sizeof(sysctl_dccp_tx_qlen),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
+
{ .ctl_name = 0, }
};
diff --git a/net/dccp/timer.c b/net/dccp/timer.c
index 8447742f5615..e8f519e7f481 100644
--- a/net/dccp/timer.c
+++ b/net/dccp/timer.c
@@ -15,15 +15,10 @@
#include "dccp.h"
-static void dccp_write_timer(unsigned long data);
-static void dccp_keepalive_timer(unsigned long data);
-static void dccp_delack_timer(unsigned long data);
-
-void dccp_init_xmit_timers(struct sock *sk)
-{
- inet_csk_init_xmit_timers(sk, &dccp_write_timer, &dccp_delack_timer,
- &dccp_keepalive_timer);
-}
+/* sysctl variables governing numbers of retransmission attempts */
+int sysctl_dccp_request_retries __read_mostly = TCP_SYN_RETRIES;
+int sysctl_dccp_retries1 __read_mostly = TCP_RETR1;
+int sysctl_dccp_retries2 __read_mostly = TCP_RETR2;
static void dccp_write_err(struct sock *sk)
{
@@ -44,11 +39,10 @@ static int dccp_write_timeout(struct sock *sk)
if (sk->sk_state == DCCP_REQUESTING || sk->sk_state == DCCP_PARTOPEN) {
if (icsk->icsk_retransmits != 0)
dst_negative_advice(&sk->sk_dst_cache);
- retry_until = icsk->icsk_syn_retries ? :
- /* FIXME! */ 3 /* FIXME! sysctl_tcp_syn_retries */;
+ retry_until = icsk->icsk_syn_retries ?
+ : sysctl_dccp_request_retries;
} else {
- if (icsk->icsk_retransmits >=
- /* FIXME! sysctl_tcp_retries1 */ 5 /* FIXME! */) {
+ if (icsk->icsk_retransmits >= sysctl_dccp_retries1) {
/* NOTE. draft-ietf-tcpimpl-pmtud-01.txt requires pmtu
black hole detection. :-(
@@ -72,7 +66,7 @@ static int dccp_write_timeout(struct sock *sk)
dst_negative_advice(&sk->sk_dst_cache);
}
- retry_until = /* FIXME! */ 15 /* FIXME! sysctl_tcp_retries2 */;
+ retry_until = sysctl_dccp_retries2;
/*
* FIXME: see tcp_write_timout and tcp_out_of_resources
*/
@@ -86,53 +80,6 @@ static int dccp_write_timeout(struct sock *sk)
return 0;
}
-/* This is the same as tcp_delack_timer, sans prequeue & mem_reclaim stuff */
-static void dccp_delack_timer(unsigned long data)
-{
- struct sock *sk = (struct sock *)data;
- struct inet_connection_sock *icsk = inet_csk(sk);
-
- bh_lock_sock(sk);
- if (sock_owned_by_user(sk)) {
- /* Try again later. */
- icsk->icsk_ack.blocked = 1;
- NET_INC_STATS_BH(LINUX_MIB_DELAYEDACKLOCKED);
- sk_reset_timer(sk, &icsk->icsk_delack_timer,
- jiffies + TCP_DELACK_MIN);
- goto out;
- }
-
- if (sk->sk_state == DCCP_CLOSED ||
- !(icsk->icsk_ack.pending & ICSK_ACK_TIMER))
- goto out;
- if (time_after(icsk->icsk_ack.timeout, jiffies)) {
- sk_reset_timer(sk, &icsk->icsk_delack_timer,
- icsk->icsk_ack.timeout);
- goto out;
- }
-
- icsk->icsk_ack.pending &= ~ICSK_ACK_TIMER;
-
- if (inet_csk_ack_scheduled(sk)) {
- if (!icsk->icsk_ack.pingpong) {
- /* Delayed ACK missed: inflate ATO. */
- icsk->icsk_ack.ato = min(icsk->icsk_ack.ato << 1,
- icsk->icsk_rto);
- } else {
- /* Delayed ACK missed: leave pingpong mode and
- * deflate ATO.
- */
- icsk->icsk_ack.pingpong = 0;
- icsk->icsk_ack.ato = TCP_ATO_MIN;
- }
- dccp_send_ack(sk);
- NET_INC_STATS_BH(LINUX_MIB_DELAYEDACKS);
- }
-out:
- bh_unlock_sock(sk);
- sock_put(sk);
-}
-
/*
* The DCCP retransmit timer.
*/
@@ -142,7 +89,7 @@ static void dccp_retransmit_timer(struct sock *sk)
/* retransmit timer is used for feature negotiation throughout
* connection. In this case, no packet is re-transmitted, but rather an
- * ack is generated and pending changes are splaced into its options.
+ * ack is generated and pending changes are placed into its options.
*/
if (sk->sk_send_head == NULL) {
dccp_pr_debug("feat negotiation retransmit timeout %p\n", sk);
@@ -154,9 +101,11 @@ static void dccp_retransmit_timer(struct sock *sk)
/*
* sk->sk_send_head has to have one skb with
* DCCP_SKB_CB(skb)->dccpd_type set to one of the retransmittable DCCP
- * packet types (REQUEST, RESPONSE, the ACK in the 3way handshake
- * (PARTOPEN timer), etc).
- */
+ * packet types. The only packets eligible for retransmission are:
+ * -- Requests in client-REQUEST state (sec. 8.1.1)
+ * -- Acks in client-PARTOPEN state (sec. 8.1.5)
+ * -- CloseReq in server-CLOSEREQ state (sec. 8.3)
+ * -- Close in node-CLOSING state (sec. 8.3) */
BUG_TRAP(sk->sk_send_head != NULL);
/*
@@ -194,7 +143,7 @@ backoff:
icsk->icsk_rto = min(icsk->icsk_rto << 1, DCCP_RTO_MAX);
inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto,
DCCP_RTO_MAX);
- if (icsk->icsk_retransmits > 3 /* FIXME: sysctl_dccp_retries1 */)
+ if (icsk->icsk_retransmits > sysctl_dccp_retries1)
__sk_dst_reset(sk);
out:;
}
@@ -264,3 +213,56 @@ out:
bh_unlock_sock(sk);
sock_put(sk);
}
+
+/* This is the same as tcp_delack_timer, sans prequeue & mem_reclaim stuff */
+static void dccp_delack_timer(unsigned long data)
+{
+ struct sock *sk = (struct sock *)data;
+ struct inet_connection_sock *icsk = inet_csk(sk);
+
+ bh_lock_sock(sk);
+ if (sock_owned_by_user(sk)) {
+ /* Try again later. */
+ icsk->icsk_ack.blocked = 1;
+ NET_INC_STATS_BH(LINUX_MIB_DELAYEDACKLOCKED);
+ sk_reset_timer(sk, &icsk->icsk_delack_timer,
+ jiffies + TCP_DELACK_MIN);
+ goto out;
+ }
+
+ if (sk->sk_state == DCCP_CLOSED ||
+ !(icsk->icsk_ack.pending & ICSK_ACK_TIMER))
+ goto out;
+ if (time_after(icsk->icsk_ack.timeout, jiffies)) {
+ sk_reset_timer(sk, &icsk->icsk_delack_timer,
+ icsk->icsk_ack.timeout);
+ goto out;
+ }
+
+ icsk->icsk_ack.pending &= ~ICSK_ACK_TIMER;
+
+ if (inet_csk_ack_scheduled(sk)) {
+ if (!icsk->icsk_ack.pingpong) {
+ /* Delayed ACK missed: inflate ATO. */
+ icsk->icsk_ack.ato = min(icsk->icsk_ack.ato << 1,
+ icsk->icsk_rto);
+ } else {
+ /* Delayed ACK missed: leave pingpong mode and
+ * deflate ATO.
+ */
+ icsk->icsk_ack.pingpong = 0;
+ icsk->icsk_ack.ato = TCP_ATO_MIN;
+ }
+ dccp_send_ack(sk);
+ NET_INC_STATS_BH(LINUX_MIB_DELAYEDACKS);
+ }
+out:
+ bh_unlock_sock(sk);
+ sock_put(sk);
+}
+
+void dccp_init_xmit_timers(struct sock *sk)
+{
+ inet_csk_init_xmit_timers(sk, &dccp_write_timer, &dccp_delack_timer,
+ &dccp_keepalive_timer);
+}
diff --git a/net/decnet/Kconfig b/net/decnet/Kconfig
index 36e72cb145b0..7914fd619c5c 100644
--- a/net/decnet/Kconfig
+++ b/net/decnet/Kconfig
@@ -41,11 +41,3 @@ config DECNET_ROUTER
See <file:Documentation/networking/decnet.txt> for more information.
-config DECNET_ROUTE_FWMARK
- bool "DECnet: use FWMARK value as routing key (EXPERIMENTAL)"
- depends on DECNET_ROUTER && NETFILTER
- help
- If you say Y here, you will be able to specify different routes for
- packets with different FWMARK ("firewalling mark") values
- (see ipchains(8), "-m" argument).
-
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index 01861feb608d..0b9d4c955154 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -38,7 +38,6 @@
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/skbuff.h>
-#include <linux/rtnetlink.h>
#include <linux/sysctl.h>
#include <linux/notifier.h>
#include <asm/uaccess.h>
@@ -47,6 +46,7 @@
#include <net/dst.h>
#include <net/flow.h>
#include <net/fib_rules.h>
+#include <net/netlink.h>
#include <net/dn.h>
#include <net/dn_dev.h>
#include <net/dn_route.h>
@@ -73,7 +73,7 @@ static BLOCKING_NOTIFIER_HEAD(dnaddr_chain);
static struct dn_dev *dn_dev_create(struct net_device *dev, int *err);
static void dn_dev_delete(struct net_device *dev);
-static void rtmsg_ifa(int event, struct dn_ifaddr *ifa);
+static void dn_ifaddr_notify(int event, struct dn_ifaddr *ifa);
static int dn_eth_up(struct net_device *);
static void dn_eth_down(struct net_device *);
@@ -255,12 +255,10 @@ static void dn_dev_sysctl_register(struct net_device *dev, struct dn_dev_parms *
struct dn_dev_sysctl_table *t;
int i;
- t = kmalloc(sizeof(*t), GFP_KERNEL);
+ t = kmemdup(&dn_dev_sysctl, sizeof(*t), GFP_KERNEL);
if (t == NULL)
return;
- memcpy(t, &dn_dev_sysctl, sizeof(*t));
-
for(i = 0; i < ARRAY_SIZE(t->dn_dev_vars) - 1; i++) {
long offset = (long)t->dn_dev_vars[i].data;
t->dn_dev_vars[i].data = ((char *)parms) + offset;
@@ -442,7 +440,7 @@ static void dn_dev_del_ifa(struct dn_dev *dn_db, struct dn_ifaddr **ifap, int de
}
}
- rtmsg_ifa(RTM_DELADDR, ifa1);
+ dn_ifaddr_notify(RTM_DELADDR, ifa1);
blocking_notifier_call_chain(&dnaddr_chain, NETDEV_DOWN, ifa1);
if (destroy) {
dn_dev_free_ifa(ifa1);
@@ -477,7 +475,7 @@ static int dn_dev_insert_ifa(struct dn_dev *dn_db, struct dn_ifaddr *ifa)
ifa->ifa_next = dn_db->ifa_list;
dn_db->ifa_list = ifa;
- rtmsg_ifa(RTM_NEWADDR, ifa);
+ dn_ifaddr_notify(RTM_NEWADDR, ifa);
blocking_notifier_call_chain(&dnaddr_chain, NETDEV_UP, ifa);
return 0;
@@ -647,41 +645,62 @@ static struct dn_dev *dn_dev_by_index(int ifindex)
return dn_dev;
}
-static int dn_dev_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+static struct nla_policy dn_ifa_policy[IFA_MAX+1] __read_mostly = {
+ [IFA_ADDRESS] = { .type = NLA_U16 },
+ [IFA_LOCAL] = { .type = NLA_U16 },
+ [IFA_LABEL] = { .type = NLA_STRING,
+ .len = IFNAMSIZ - 1 },
+};
+
+static int dn_nl_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
{
- struct rtattr **rta = arg;
+ struct nlattr *tb[IFA_MAX+1];
struct dn_dev *dn_db;
- struct ifaddrmsg *ifm = NLMSG_DATA(nlh);
+ struct ifaddrmsg *ifm;
struct dn_ifaddr *ifa, **ifap;
+ int err = -EADDRNOTAVAIL;
+
+ err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, dn_ifa_policy);
+ if (err < 0)
+ goto errout;
+ ifm = nlmsg_data(nlh);
if ((dn_db = dn_dev_by_index(ifm->ifa_index)) == NULL)
- return -EADDRNOTAVAIL;
+ goto errout;
+
+ for (ifap = &dn_db->ifa_list; (ifa = *ifap); ifap = &ifa->ifa_next) {
+ if (tb[IFA_LOCAL] &&
+ nla_memcmp(tb[IFA_LOCAL], &ifa->ifa_local, 2))
+ continue;
- for(ifap = &dn_db->ifa_list; (ifa=*ifap) != NULL; ifap = &ifa->ifa_next) {
- void *tmp = rta[IFA_LOCAL-1];
- if ((tmp && memcmp(RTA_DATA(tmp), &ifa->ifa_local, 2)) ||
- (rta[IFA_LABEL-1] && rtattr_strcmp(rta[IFA_LABEL-1], ifa->ifa_label)))
+ if (tb[IFA_LABEL] && nla_strcmp(tb[IFA_LABEL], ifa->ifa_label))
continue;
dn_dev_del_ifa(dn_db, ifap, 1);
return 0;
}
- return -EADDRNOTAVAIL;
+errout:
+ return err;
}
-static int dn_dev_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+static int dn_nl_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
{
- struct rtattr **rta = arg;
+ struct nlattr *tb[IFA_MAX+1];
struct net_device *dev;
struct dn_dev *dn_db;
- struct ifaddrmsg *ifm = NLMSG_DATA(nlh);
+ struct ifaddrmsg *ifm;
struct dn_ifaddr *ifa;
- int rv;
+ int err;
- if (rta[IFA_LOCAL-1] == NULL)
+ err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, dn_ifa_policy);
+ if (err < 0)
+ return err;
+
+ if (tb[IFA_LOCAL] == NULL)
return -EINVAL;
+ ifm = nlmsg_data(nlh);
if ((dev = __dev_get_by_index(ifm->ifa_index)) == NULL)
return -ENODEV;
@@ -695,69 +714,77 @@ static int dn_dev_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *a
if ((ifa = dn_dev_alloc_ifa()) == NULL)
return -ENOBUFS;
- if (!rta[IFA_ADDRESS - 1])
- rta[IFA_ADDRESS - 1] = rta[IFA_LOCAL - 1];
- memcpy(&ifa->ifa_local, RTA_DATA(rta[IFA_LOCAL-1]), 2);
- memcpy(&ifa->ifa_address, RTA_DATA(rta[IFA_ADDRESS-1]), 2);
+ if (tb[IFA_ADDRESS] == NULL)
+ tb[IFA_ADDRESS] = tb[IFA_LOCAL];
+
+ ifa->ifa_local = nla_get_le16(tb[IFA_LOCAL]);
+ ifa->ifa_address = nla_get_le16(tb[IFA_ADDRESS]);
ifa->ifa_flags = ifm->ifa_flags;
ifa->ifa_scope = ifm->ifa_scope;
ifa->ifa_dev = dn_db;
- if (rta[IFA_LABEL-1])
- rtattr_strlcpy(ifa->ifa_label, rta[IFA_LABEL-1], IFNAMSIZ);
+
+ if (tb[IFA_LABEL])
+ nla_strlcpy(ifa->ifa_label, tb[IFA_LABEL], IFNAMSIZ);
else
memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
- rv = dn_dev_insert_ifa(dn_db, ifa);
- if (rv)
+ err = dn_dev_insert_ifa(dn_db, ifa);
+ if (err)
dn_dev_free_ifa(ifa);
- return rv;
+
+ return err;
}
-static int dn_dev_fill_ifaddr(struct sk_buff *skb, struct dn_ifaddr *ifa,
- u32 pid, u32 seq, int event, unsigned int flags)
+static inline size_t dn_ifaddr_nlmsg_size(void)
+{
+ return NLMSG_ALIGN(sizeof(struct ifaddrmsg))
+ + nla_total_size(IFNAMSIZ) /* IFA_LABEL */
+ + nla_total_size(2) /* IFA_ADDRESS */
+ + nla_total_size(2); /* IFA_LOCAL */
+}
+
+static int dn_nl_fill_ifaddr(struct sk_buff *skb, struct dn_ifaddr *ifa,
+ u32 pid, u32 seq, int event, unsigned int flags)
{
struct ifaddrmsg *ifm;
struct nlmsghdr *nlh;
- unsigned char *b = skb->tail;
- nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags);
- ifm = NLMSG_DATA(nlh);
+ nlh = nlmsg_put(skb, pid, seq, event, sizeof(*ifm), flags);
+ if (nlh == NULL)
+ return -ENOBUFS;
+ ifm = nlmsg_data(nlh);
ifm->ifa_family = AF_DECnet;
ifm->ifa_prefixlen = 16;
ifm->ifa_flags = ifa->ifa_flags | IFA_F_PERMANENT;
ifm->ifa_scope = ifa->ifa_scope;
ifm->ifa_index = ifa->ifa_dev->dev->ifindex;
+
if (ifa->ifa_address)
- RTA_PUT(skb, IFA_ADDRESS, 2, &ifa->ifa_address);
+ NLA_PUT_LE16(skb, IFA_ADDRESS, ifa->ifa_address);
if (ifa->ifa_local)
- RTA_PUT(skb, IFA_LOCAL, 2, &ifa->ifa_local);
+ NLA_PUT_LE16(skb, IFA_LOCAL, ifa->ifa_local);
if (ifa->ifa_label[0])
- RTA_PUT(skb, IFA_LABEL, IFNAMSIZ, &ifa->ifa_label);
- nlh->nlmsg_len = skb->tail - b;
- return skb->len;
+ NLA_PUT_STRING(skb, IFA_LABEL, ifa->ifa_label);
+
+ return nlmsg_end(skb, nlh);
-nlmsg_failure:
-rtattr_failure:
- skb_trim(skb, b - skb->data);
- return -1;
+nla_put_failure:
+ return nlmsg_cancel(skb, nlh);
}
-static void rtmsg_ifa(int event, struct dn_ifaddr *ifa)
+static void dn_ifaddr_notify(int event, struct dn_ifaddr *ifa)
{
struct sk_buff *skb;
- int payload = sizeof(struct ifaddrmsg) + 128;
int err = -ENOBUFS;
- skb = alloc_skb(nlmsg_total_size(payload), GFP_KERNEL);
+ skb = alloc_skb(dn_ifaddr_nlmsg_size(), GFP_KERNEL);
if (skb == NULL)
goto errout;
- err = dn_dev_fill_ifaddr(skb, ifa, 0, 0, event, 0);
- if (err < 0) {
- kfree_skb(skb);
- goto errout;
- }
+ err = dn_nl_fill_ifaddr(skb, ifa, 0, 0, event, 0);
+ /* failure implies BUG in dn_ifaddr_nlmsg_size() */
+ BUG_ON(err < 0);
err = rtnl_notify(skb, 0, RTNLGRP_DECnet_IFADDR, NULL, GFP_KERNEL);
errout:
@@ -765,39 +792,43 @@ errout:
rtnl_set_sk_err(RTNLGRP_DECnet_IFADDR, err);
}
-static int dn_dev_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
+static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
{
- int idx, dn_idx;
- int s_idx, s_dn_idx;
+ int idx, dn_idx = 0, skip_ndevs, skip_naddr;
struct net_device *dev;
struct dn_dev *dn_db;
struct dn_ifaddr *ifa;
- s_idx = cb->args[0];
- s_dn_idx = dn_idx = cb->args[1];
+ skip_ndevs = cb->args[0];
+ skip_naddr = cb->args[1];
+
read_lock(&dev_base_lock);
- for(dev = dev_base, idx = 0; dev; dev = dev->next, idx++) {
- if (idx < s_idx)
+ for (dev = dev_base, idx = 0; dev; dev = dev->next, idx++) {
+ if (idx < skip_ndevs)
continue;
- if (idx > s_idx)
- s_dn_idx = 0;
+ else if (idx > skip_ndevs) {
+ /* Only skip over addresses for first dev dumped
+ * in this iteration (idx == skip_ndevs) */
+ skip_naddr = 0;
+ }
+
if ((dn_db = dev->dn_ptr) == NULL)
continue;
- for(ifa = dn_db->ifa_list, dn_idx = 0; ifa; ifa = ifa->ifa_next, dn_idx++) {
- if (dn_idx < s_dn_idx)
+ for (ifa = dn_db->ifa_list, dn_idx = 0; ifa;
+ ifa = ifa->ifa_next, dn_idx++) {
+ if (dn_idx < skip_naddr)
continue;
- if (dn_dev_fill_ifaddr(skb, ifa,
- NETLINK_CB(cb->skb).pid,
- cb->nlh->nlmsg_seq,
- RTM_NEWADDR,
- NLM_F_MULTI) <= 0)
+ if (dn_nl_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid,
+ cb->nlh->nlmsg_seq, RTM_NEWADDR,
+ NLM_F_MULTI) < 0)
goto done;
}
}
done:
read_unlock(&dev_base_lock);
+
cb->args[0] = idx;
cb->args[1] = dn_idx;
@@ -1414,9 +1445,9 @@ static struct file_operations dn_dev_seq_fops = {
static struct rtnetlink_link dnet_rtnetlink_table[RTM_NR_MSGTYPES] =
{
- [RTM_NEWADDR - RTM_BASE] = { .doit = dn_dev_rtm_newaddr, },
- [RTM_DELADDR - RTM_BASE] = { .doit = dn_dev_rtm_deladdr, },
- [RTM_GETADDR - RTM_BASE] = { .dumpit = dn_dev_dump_ifaddr, },
+ [RTM_NEWADDR - RTM_BASE] = { .doit = dn_nl_newaddr, },
+ [RTM_DELADDR - RTM_BASE] = { .doit = dn_nl_deladdr, },
+ [RTM_GETADDR - RTM_BASE] = { .dumpit = dn_nl_dump_ifaddr, },
#ifdef CONFIG_DECNET_ROUTER
[RTM_NEWROUTE - RTM_BASE] = { .doit = dn_fib_rtm_newroute, },
[RTM_DELROUTE - RTM_BASE] = { .doit = dn_fib_rtm_delroute, },
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c
index ff0ebe99137d..7322bb36e825 100644
--- a/net/decnet/dn_neigh.c
+++ b/net/decnet/dn_neigh.c
@@ -591,7 +591,6 @@ static int dn_neigh_seq_open(struct inode *inode, struct file *file)
seq = file->private_data;
seq->private = s;
- memset(s, 0, sizeof(*s));
out:
return rc;
out_kfree:
diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c
index 7683d4f754d2..39a6cf7fb566 100644
--- a/net/decnet/dn_nsp_in.c
+++ b/net/decnet/dn_nsp_in.c
@@ -804,7 +804,7 @@ got_it:
goto free_out;
}
- return sk_receive_skb(sk, skb);
+ return sk_receive_skb(sk, skb, 0);
}
return dn_nsp_no_socket(skb, reason);
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index 23489f7232d2..9881933167bd 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -269,9 +269,7 @@ static inline int compare_keys(struct flowi *fl1, struct flowi *fl2)
{
return ((fl1->nl_u.dn_u.daddr ^ fl2->nl_u.dn_u.daddr) |
(fl1->nl_u.dn_u.saddr ^ fl2->nl_u.dn_u.saddr) |
-#ifdef CONFIG_DECNET_ROUTE_FWMARK
- (fl1->nl_u.dn_u.fwmark ^ fl2->nl_u.dn_u.fwmark) |
-#endif
+ (fl1->mark ^ fl2->mark) |
(fl1->nl_u.dn_u.scope ^ fl2->nl_u.dn_u.scope) |
(fl1->oif ^ fl2->oif) |
(fl1->iif ^ fl2->iif)) == 0;
@@ -882,10 +880,8 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *old
{ .daddr = oldflp->fld_dst,
.saddr = oldflp->fld_src,
.scope = RT_SCOPE_UNIVERSE,
-#ifdef CONFIG_DECNET_ROUTE_FWMARK
- .fwmark = oldflp->fld_fwmark
-#endif
} },
+ .mark = oldflp->mark,
.iif = loopback_dev.ifindex,
.oif = oldflp->oif };
struct dn_route *rt = NULL;
@@ -903,7 +899,7 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *old
"dn_route_output_slow: dst=%04x src=%04x mark=%d"
" iif=%d oif=%d\n", dn_ntohs(oldflp->fld_dst),
dn_ntohs(oldflp->fld_src),
- oldflp->fld_fwmark, loopback_dev.ifindex, oldflp->oif);
+ oldflp->mark, loopback_dev.ifindex, oldflp->oif);
/* If we have an output interface, verify its a DECnet device */
if (oldflp->oif) {
@@ -1108,9 +1104,7 @@ make_route:
rt->fl.fld_dst = oldflp->fld_dst;
rt->fl.oif = oldflp->oif;
rt->fl.iif = 0;
-#ifdef CONFIG_DECNET_ROUTE_FWMARK
- rt->fl.fld_fwmark = oldflp->fld_fwmark;
-#endif
+ rt->fl.mark = oldflp->mark;
rt->rt_saddr = fl.fld_src;
rt->rt_daddr = fl.fld_dst;
@@ -1178,9 +1172,7 @@ static int __dn_route_output_key(struct dst_entry **pprt, const struct flowi *fl
rt = rcu_dereference(rt->u.rt_next)) {
if ((flp->fld_dst == rt->fl.fld_dst) &&
(flp->fld_src == rt->fl.fld_src) &&
-#ifdef CONFIG_DECNET_ROUTE_FWMARK
- (flp->fld_fwmark == rt->fl.fld_fwmark) &&
-#endif
+ (flp->mark == rt->fl.mark) &&
(rt->fl.iif == 0) &&
(rt->fl.oif == flp->oif)) {
rt->u.dst.lastuse = jiffies;
@@ -1235,10 +1227,8 @@ static int dn_route_input_slow(struct sk_buff *skb)
{ .daddr = cb->dst,
.saddr = cb->src,
.scope = RT_SCOPE_UNIVERSE,
-#ifdef CONFIG_DECNET_ROUTE_FWMARK
- .fwmark = skb->nfmark
-#endif
} },
+ .mark = skb->mark,
.iif = skb->dev->ifindex };
struct dn_fib_res res = { .fi = NULL, .type = RTN_UNREACHABLE };
int err = -EINVAL;
@@ -1385,7 +1375,7 @@ make_route:
rt->fl.fld_dst = cb->dst;
rt->fl.oif = 0;
rt->fl.iif = in_dev->ifindex;
- rt->fl.fld_fwmark = fl.fld_fwmark;
+ rt->fl.mark = fl.mark;
rt->u.dst.flags = DST_HOST;
rt->u.dst.neighbour = neigh;
@@ -1457,9 +1447,7 @@ int dn_route_input(struct sk_buff *skb)
if ((rt->fl.fld_src == cb->src) &&
(rt->fl.fld_dst == cb->dst) &&
(rt->fl.oif == 0) &&
-#ifdef CONFIG_DECNET_ROUTE_FWMARK
- (rt->fl.fld_fwmark == skb->nfmark) &&
-#endif
+ (rt->fl.mark == skb->mark) &&
(rt->fl.iif == cb->iif)) {
rt->u.dst.lastuse = jiffies;
dst_hold(&rt->u.dst);
@@ -1481,7 +1469,7 @@ static int dn_rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
struct rtmsg *r;
struct nlmsghdr *nlh;
unsigned char *b = skb->tail;
- struct rta_cacheinfo ci;
+ long expires;
nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*r), flags);
r = NLMSG_DATA(nlh);
@@ -1514,16 +1502,10 @@ static int dn_rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
RTA_PUT(skb, RTA_GATEWAY, 2, &rt->rt_gateway);
if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0)
goto rtattr_failure;
- ci.rta_lastuse = jiffies_to_clock_t(jiffies - rt->u.dst.lastuse);
- ci.rta_used = rt->u.dst.__use;
- ci.rta_clntref = atomic_read(&rt->u.dst.__refcnt);
- if (rt->u.dst.expires)
- ci.rta_expires = jiffies_to_clock_t(rt->u.dst.expires - jiffies);
- else
- ci.rta_expires = 0;
- ci.rta_error = rt->u.dst.error;
- ci.rta_id = ci.rta_ts = ci.rta_tsage = 0;
- RTA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci);
+ expires = rt->u.dst.expires ? rt->u.dst.expires - jiffies : 0;
+ if (rtnl_put_cacheinfo(skb, &rt->u.dst, 0, 0, 0, expires,
+ rt->u.dst.error) < 0)
+ goto rtattr_failure;
if (rt->fl.iif)
RTA_PUT(skb, RTA_IIF, sizeof(int), &rt->fl.iif);
@@ -1604,8 +1586,6 @@ int dn_cache_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, void *arg)
if (rtm->rtm_flags & RTM_F_NOTIFY)
rt->rt_flags |= RTCF_NOTIFY;
- NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
-
err = dn_rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, RTM_NEWROUTE, 0, 0);
if (err == 0)
diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c
index 590e0a72495c..e32d0c3d5a96 100644
--- a/net/decnet/dn_rules.c
+++ b/net/decnet/dn_rules.c
@@ -45,10 +45,6 @@ struct dn_fib_rule
__le16 dstmask;
__le16 srcmap;
u8 flags;
-#ifdef CONFIG_DECNET_ROUTE_FWMARK
- u32 fwmark;
- u32 fwmask;
-#endif
};
static struct dn_fib_rule default_rule = {
@@ -112,13 +108,9 @@ errout:
}
static struct nla_policy dn_fib_rule_policy[FRA_MAX+1] __read_mostly = {
- [FRA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 },
- [FRA_PRIORITY] = { .type = NLA_U32 },
+ FRA_GENERIC_POLICY,
[FRA_SRC] = { .type = NLA_U16 },
[FRA_DST] = { .type = NLA_U16 },
- [FRA_FWMARK] = { .type = NLA_U32 },
- [FRA_FWMASK] = { .type = NLA_U32 },
- [FRA_TABLE] = { .type = NLA_U32 },
};
static int dn_fib_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
@@ -131,11 +123,6 @@ static int dn_fib_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
((daddr ^ r->dst) & r->dstmask))
return 0;
-#ifdef CONFIG_DECNET_ROUTE_FWMARK
- if ((r->fwmark ^ fl->fld_fwmark) & r->fwmask)
- return 0;
-#endif
-
return 1;
}
@@ -169,20 +156,6 @@ static int dn_fib_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
if (tb[FRA_DST])
r->dst = nla_get_u16(tb[FRA_DST]);
-#ifdef CONFIG_DECNET_ROUTE_FWMARK
- if (tb[FRA_FWMARK]) {
- r->fwmark = nla_get_u32(tb[FRA_FWMARK]);
- if (r->fwmark)
- /* compatibility: if the mark value is non-zero all bits
- * are compared unless a mask is explicitly specified.
- */
- r->fwmask = 0xFFFFFFFF;
- }
-
- if (tb[FRA_FWMASK])
- r->fwmask = nla_get_u32(tb[FRA_FWMASK]);
-#endif
-
r->src_len = frh->src_len;
r->srcmask = dnet_make_mask(r->src_len);
r->dst_len = frh->dst_len;
@@ -203,14 +176,6 @@ static int dn_fib_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
if (frh->dst_len && (r->dst_len != frh->dst_len))
return 0;
-#ifdef CONFIG_DECNET_ROUTE_FWMARK
- if (tb[FRA_FWMARK] && (r->fwmark != nla_get_u32(tb[FRA_FWMARK])))
- return 0;
-
- if (tb[FRA_FWMASK] && (r->fwmask != nla_get_u32(tb[FRA_FWMASK])))
- return 0;
-#endif
-
if (tb[FRA_SRC] && (r->src != nla_get_u16(tb[FRA_SRC])))
return 0;
@@ -248,12 +213,6 @@ static int dn_fib_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
frh->src_len = r->src_len;
frh->tos = 0;
-#ifdef CONFIG_DECNET_ROUTE_FWMARK
- if (r->fwmark)
- NLA_PUT_U32(skb, FRA_FWMARK, r->fwmark);
- if (r->fwmask || r->fwmark)
- NLA_PUT_U32(skb, FRA_FWMASK, r->fwmask);
-#endif
if (r->dst_len)
NLA_PUT_U16(skb, FRA_DST, r->dst);
if (r->src_len)
diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c
index 317904bb5896..bdbc3f431668 100644
--- a/net/decnet/dn_table.c
+++ b/net/decnet/dn_table.c
@@ -263,6 +263,32 @@ static int dn_fib_nh_match(struct rtmsg *r, struct nlmsghdr *nlh, struct dn_kern
return 0;
}
+static inline size_t dn_fib_nlmsg_size(struct dn_fib_info *fi)
+{
+ size_t payload = NLMSG_ALIGN(sizeof(struct rtmsg))
+ + nla_total_size(4) /* RTA_TABLE */
+ + nla_total_size(2) /* RTA_DST */
+ + nla_total_size(4); /* RTA_PRIORITY */
+
+ /* space for nested metrics */
+ payload += nla_total_size((RTAX_MAX * nla_total_size(4)));
+
+ if (fi->fib_nhs) {
+ /* Also handles the special case fib_nhs == 1 */
+
+ /* each nexthop is packed in an attribute */
+ size_t nhsize = nla_total_size(sizeof(struct rtnexthop));
+
+ /* may contain a gateway attribute */
+ nhsize += nla_total_size(4);
+
+ /* all nexthops are packed in a nested attribute */
+ payload += nla_total_size(fi->fib_nhs * nhsize);
+ }
+
+ return payload;
+}
+
static int dn_fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
u32 tb_id, u8 type, u8 scope, void *dst, int dst_len,
struct dn_fib_info *fi, unsigned int flags)
@@ -335,17 +361,15 @@ static void dn_rtmsg_fib(int event, struct dn_fib_node *f, int z, u32 tb_id,
u32 pid = req ? req->pid : 0;
int err = -ENOBUFS;
- skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+ skb = nlmsg_new(dn_fib_nlmsg_size(DN_FIB_INFO(f)), GFP_KERNEL);
if (skb == NULL)
goto errout;
err = dn_fib_dump_info(skb, pid, nlh->nlmsg_seq, event, tb_id,
f->fn_type, f->fn_scope, &f->fn_key, z,
DN_FIB_INFO(f), 0);
- if (err < 0) {
- kfree_skb(skb);
- goto errout;
- }
+ /* failure implies BUG in dn_fib_nlmsg_size() */
+ BUG_ON(err < 0);
err = rtnl_notify(skb, pid, RTNLGRP_DECnet_ROUTE, nlh, GFP_KERNEL);
errout:
@@ -807,10 +831,11 @@ struct dn_fib_table *dn_fib_get_table(u32 n, int create)
printk(KERN_DEBUG "DECnet: BUG! Attempt to create routing table from interrupt\n");
return NULL;
}
- if ((t = kmalloc(sizeof(struct dn_fib_table) + sizeof(struct dn_hash), GFP_KERNEL)) == NULL)
- return NULL;
- memset(t, 0, sizeof(struct dn_fib_table));
+ t = kzalloc(sizeof(struct dn_fib_table) + sizeof(struct dn_hash),
+ GFP_KERNEL);
+ if (t == NULL)
+ return NULL;
t->n = n;
t->insert = dn_fib_table_insert;
@@ -818,7 +843,6 @@ struct dn_fib_table *dn_fib_get_table(u32 n, int create)
t->lookup = dn_fib_table_lookup;
t->flush = dn_fib_table_flush;
t->dump = dn_fib_table_dump;
- memset(t->data, 0, sizeof(struct dn_hash));
hlist_add_head_rcu(&t->hlist, &dn_fib_table_hash[h]);
return t;
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
index 4bd78c8cfb26..2d31bf3f05c5 100644
--- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c
@@ -60,7 +60,6 @@
#include <net/ip.h>
#include <asm/uaccess.h>
#include <asm/system.h>
-#include <asm/checksum.h>
__setup("ether=", netdev_boot_setup);
diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c
index 13b1e5fff7e4..b1c6d1f717d9 100644
--- a/net/ieee80211/ieee80211_module.c
+++ b/net/ieee80211/ieee80211_module.c
@@ -67,7 +67,7 @@ static int ieee80211_networks_allocate(struct ieee80211_device *ieee)
return 0;
ieee->networks =
- kmalloc(MAX_NETWORK_COUNT * sizeof(struct ieee80211_network),
+ kzalloc(MAX_NETWORK_COUNT * sizeof(struct ieee80211_network),
GFP_KERNEL);
if (!ieee->networks) {
printk(KERN_WARNING "%s: Out of memory allocating beacons\n",
@@ -75,9 +75,6 @@ static int ieee80211_networks_allocate(struct ieee80211_device *ieee)
return -ENOMEM;
}
- memset(ieee->networks, 0,
- MAX_NETWORK_COUNT * sizeof(struct ieee80211_network));
-
return 0;
}
@@ -118,6 +115,21 @@ static void ieee80211_networks_initialize(struct ieee80211_device *ieee)
&ieee->network_free_list);
}
+static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
+{
+ if ((new_mtu < 68) || (new_mtu > IEEE80211_DATA_LEN))
+ return -EINVAL;
+ dev->mtu = new_mtu;
+ return 0;
+}
+
+static struct net_device_stats *ieee80211_generic_get_stats(
+ struct net_device *dev)
+{
+ struct ieee80211_device *ieee = netdev_priv(dev);
+ return &ieee->stats;
+}
+
struct net_device *alloc_ieee80211(int sizeof_priv)
{
struct ieee80211_device *ieee;
@@ -133,6 +145,11 @@ struct net_device *alloc_ieee80211(int sizeof_priv)
}
ieee = netdev_priv(dev);
dev->hard_start_xmit = ieee80211_xmit;
+ dev->change_mtu = ieee80211_change_mtu;
+
+ /* Drivers are free to override this if the generic implementation
+ * does not meet their needs. */
+ dev->get_stats = ieee80211_generic_get_stats;
ieee->dev = dev;
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index 2759312a4204..d97e5412e31b 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -415,17 +415,16 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
ieee->host_mc_decrypt : ieee->host_decrypt;
if (can_be_decrypted) {
- int idx = 0;
if (skb->len >= hdrlen + 3) {
/* Top two-bits of byte 3 are the key index */
- idx = skb->data[hdrlen + 3] >> 6;
+ keyidx = skb->data[hdrlen + 3] >> 6;
}
- /* ieee->crypt[] is WEP_KEY (4) in length. Given that idx
- * is only allowed 2-bits of storage, no value of idx can
- * be provided via above code that would result in idx
+ /* ieee->crypt[] is WEP_KEY (4) in length. Given that keyidx
+ * is only allowed 2-bits of storage, no value of keyidx can
+ * be provided via above code that would result in keyidx
* being out of range */
- crypt = ieee->crypt[idx];
+ crypt = ieee->crypt[keyidx];
#ifdef NOT_YET
sta = NULL;
@@ -479,6 +478,11 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
goto rx_exit;
}
#endif
+ /* drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.29) */
+ if (sc == ieee->prev_seq_ctl)
+ goto rx_dropped;
+ else
+ ieee->prev_seq_ctl = sc;
/* Data frame - extract src/dst addresses */
if (skb->len < IEEE80211_3ADDR_LEN)
@@ -655,6 +659,51 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
goto rx_dropped;
}
+ /* If the frame was decrypted in hardware, we may need to strip off
+ * any security data (IV, ICV, etc) that was left behind */
+ if (!can_be_decrypted && (fc & IEEE80211_FCTL_PROTECTED) &&
+ ieee->host_strip_iv_icv) {
+ int trimlen = 0;
+
+ /* Top two-bits of byte 3 are the key index */
+ if (skb->len >= hdrlen + 3)
+ keyidx = skb->data[hdrlen + 3] >> 6;
+
+ /* To strip off any security data which appears before the
+ * payload, we simply increase hdrlen (as the header gets
+ * chopped off immediately below). For the security data which
+ * appears after the payload, we use skb_trim. */
+
+ switch (ieee->sec.encode_alg[keyidx]) {
+ case SEC_ALG_WEP:
+ /* 4 byte IV */
+ hdrlen += 4;
+ /* 4 byte ICV */
+ trimlen = 4;
+ break;
+ case SEC_ALG_TKIP:
+ /* 4 byte IV, 4 byte ExtIV */
+ hdrlen += 8;
+ /* 8 byte MIC, 4 byte ICV */
+ trimlen = 12;
+ break;
+ case SEC_ALG_CCMP:
+ /* 8 byte CCMP header */
+ hdrlen += 8;
+ /* 8 byte MIC */
+ trimlen = 8;
+ break;
+ }
+
+ if (skb->len < trimlen)
+ goto rx_dropped;
+
+ __skb_trim(skb, skb->len - trimlen);
+
+ if (skb->len < hdrlen)
+ goto rx_dropped;
+ }
+
/* skb: hdr + (possible reassembled) full plaintext payload */
payload = skb->data + hdrlen;
@@ -1255,12 +1304,11 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element
case MFIE_TYPE_IBSS_DFS:
if (network->ibss_dfs)
break;
- network->ibss_dfs =
- kmalloc(info_element->len, GFP_ATOMIC);
+ network->ibss_dfs = kmemdup(info_element->data,
+ info_element->len,
+ GFP_ATOMIC);
if (!network->ibss_dfs)
return 1;
- memcpy(network->ibss_dfs, info_element->data,
- info_element->len);
network->flags |= NETWORK_HAS_IBSS_DFS;
break;
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index ae254497ba3d..854fc13cd78d 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -390,7 +390,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
* this stack is providing the full 802.11 header, one will
* eventually be affixed to this fragment -- so we must account
* for it when determining the amount of payload space. */
- bytes_per_frag = frag_size - IEEE80211_3ADDR_LEN;
+ bytes_per_frag = frag_size - hdr_len;
if (ieee->config &
(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
bytes_per_frag -= IEEE80211_FCS_LEN;
@@ -412,7 +412,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
} else {
nr_frags = 1;
bytes_per_frag = bytes_last_frag = bytes;
- frag_size = bytes + IEEE80211_3ADDR_LEN;
+ frag_size = bytes + hdr_len;
}
rts_required = (frag_size > ieee->rts
diff --git a/net/ieee80211/softmac/ieee80211softmac_auth.c b/net/ieee80211/softmac/ieee80211softmac_auth.c
index 2ae1833b657a..6012705aa4f8 100644
--- a/net/ieee80211/softmac/ieee80211softmac_auth.c
+++ b/net/ieee80211/softmac/ieee80211softmac_auth.c
@@ -161,7 +161,7 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth)
/* Make sure that we've got an auth queue item for this request */
if(aq == NULL)
{
- printkl(KERN_DEBUG PFX "Authentication response received from "MAC_FMT" but no queue item exists.\n", MAC_ARG(auth->header.addr2));
+ dprintkl(KERN_DEBUG PFX "Authentication response received from "MAC_FMT" but no queue item exists.\n", MAC_ARG(auth->header.addr2));
/* Error #? */
return -1;
}
@@ -169,7 +169,7 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth)
/* Check for out of order authentication */
if(!net->authenticating)
{
- printkl(KERN_DEBUG PFX "Authentication response received from "MAC_FMT" but did not request authentication.\n",MAC_ARG(auth->header.addr2));
+ dprintkl(KERN_DEBUG PFX "Authentication response received from "MAC_FMT" but did not request authentication.\n",MAC_ARG(auth->header.addr2));
return -1;
}
@@ -219,10 +219,16 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth)
net->challenge_len = *data++;
if (net->challenge_len > WLAN_AUTH_CHALLENGE_LEN)
net->challenge_len = WLAN_AUTH_CHALLENGE_LEN;
- if (net->challenge != NULL)
- kfree(net->challenge);
- net->challenge = kmalloc(net->challenge_len, GFP_ATOMIC);
- memcpy(net->challenge, data, net->challenge_len);
+ kfree(net->challenge);
+ net->challenge = kmemdup(data, net->challenge_len,
+ GFP_ATOMIC);
+ if (net->challenge == NULL) {
+ printkl(KERN_NOTICE PFX "Shared Key "
+ "Authentication failed due to "
+ "memory shortage.\n");
+ spin_unlock_irqrestore(&mac->lock, flags);
+ break;
+ }
aq->state = IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE;
/* We reuse the work struct from the auth request here.
@@ -345,7 +351,7 @@ ieee80211softmac_deauth_req(struct ieee80211softmac_device *mac,
/* Make sure the network is authenticated */
if (!net->authenticated)
{
- printkl(KERN_DEBUG PFX "Can't send deauthentication packet, network is not authenticated.\n");
+ dprintkl(KERN_DEBUG PFX "Can't send deauthentication packet, network is not authenticated.\n");
/* Error okay? */
return -EPERM;
}
@@ -379,7 +385,7 @@ ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *de
net = ieee80211softmac_get_network_by_bssid(mac, deauth->header.addr2);
if (net == NULL) {
- printkl(KERN_DEBUG PFX "Received deauthentication packet from "MAC_FMT", but that network is unknown.\n",
+ dprintkl(KERN_DEBUG PFX "Received deauthentication packet from "MAC_FMT", but that network is unknown.\n",
MAC_ARG(deauth->header.addr2));
return 0;
}
@@ -387,7 +393,7 @@ ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *de
/* Make sure the network is authenticated */
if(!net->authenticated)
{
- printkl(KERN_DEBUG PFX "Can't perform deauthentication, network is not authenticated.\n");
+ dprintkl(KERN_DEBUG PFX "Can't perform deauthentication, network is not authenticated.\n");
/* Error okay? */
return -EPERM;
}
diff --git a/net/ieee80211/softmac/ieee80211softmac_scan.c b/net/ieee80211/softmac/ieee80211softmac_scan.c
index a8326076581a..0c85d6c24cdb 100644
--- a/net/ieee80211/softmac/ieee80211softmac_scan.c
+++ b/net/ieee80211/softmac/ieee80211softmac_scan.c
@@ -47,7 +47,6 @@ 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);
@@ -137,7 +136,8 @@ void ieee80211softmac_scan(struct work_struct *work)
si->started = 0;
spin_unlock_irqrestore(&sm->lock, flags);
- dprintk(PFX "Scanning finished\n");
+ dprintk(PFX "Scanning finished: scanned %d channels starting with channel %d\n",
+ sm->scaninfo->number_channels, sm->scaninfo->channels[0].channel);
ieee80211softmac_scan_finished(sm);
complete_all(&sm->scaninfo->finished);
}
@@ -186,8 +186,6 @@ int ieee80211softmac_start_scan_implementation(struct net_device *dev)
sm->scaninfo->channels = sm->ieee->geo.bg;
sm->scaninfo->number_channels = sm->ieee->geo.bg_channels;
}
- dprintk(PFX "Start scanning with channel: %d\n", sm->scaninfo->channels[0].channel);
- dprintk(PFX "Scanning %d channels\n", sm->scaninfo->number_channels);
sm->scaninfo->current_channel_idx = 0;
sm->scaninfo->started = 1;
sm->scaninfo->stop = 0;
@@ -251,7 +249,6 @@ 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/ipv4/Kconfig b/net/ipv4/Kconfig
index 5572071af735..503e7059e312 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -104,13 +104,6 @@ config IP_MULTIPLE_TABLES
If unsure, say N.
-config IP_ROUTE_FWMARK
- bool "IP: use netfilter MARK value as routing key"
- depends on IP_MULTIPLE_TABLES && NETFILTER
- help
- If you say Y here, you will be able to specify different routes for
- packets with different mark values (see iptables(8), MARK target).
-
config IP_ROUTE_MULTIPATH
bool "IP: equal cost multipath"
depends on IP_ADVANCED_ROUTER
@@ -625,5 +618,17 @@ config DEFAULT_TCP_CONG
default "reno" if DEFAULT_RENO
default "cubic"
+config TCP_MD5SIG
+ bool "TCP: MD5 Signature Option support (RFC2385) (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ select CRYPTO
+ select CRYPTO_MD5
+ ---help---
+ RFC2385 specifices a method of giving MD5 protection to TCP sessions.
+ Its main (only?) use is to protect BGP sessions between core routers
+ on the Internet.
+
+ If unsure, say N.
+
source "net/ipv4/ipvs/Kconfig"
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index 15645c51520c..7a068626feea 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -8,7 +8,8 @@ obj-y := route.o inetpeer.o protocol.o \
inet_timewait_sock.o inet_connection_sock.o \
tcp.o tcp_input.o tcp_output.o tcp_timer.o tcp_ipv4.o \
tcp_minisocks.o tcp_cong.o \
- datagram.o raw.o udp.o arp.o icmp.o devinet.o af_inet.o igmp.o \
+ datagram.o raw.o udp.o udplite.o \
+ arp.o icmp.o devinet.o af_inet.o igmp.o \
sysctl_net_ipv4.o fib_frontend.o fib_semantics.o
obj-$(CONFIG_IP_FIB_HASH) += fib_hash.o
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index edcf0932ac6d..1144900d37f6 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -104,6 +104,7 @@
#include <net/inet_connection_sock.h>
#include <net/tcp.h>
#include <net/udp.h>
+#include <net/udplite.h>
#include <linux/skbuff.h>
#include <net/sock.h>
#include <net/raw.h>
@@ -204,7 +205,7 @@ int inet_listen(struct socket *sock, int backlog)
* we can only allow the backlog to be adjusted.
*/
if (old_state != TCP_LISTEN) {
- err = inet_csk_listen_start(sk, TCP_SYNQ_HSIZE);
+ err = inet_csk_listen_start(sk, backlog);
if (err)
goto out;
}
@@ -643,7 +644,7 @@ int inet_getname(struct socket *sock, struct sockaddr *uaddr,
sin->sin_port = inet->dport;
sin->sin_addr.s_addr = inet->daddr;
} else {
- __u32 addr = inet->rcv_saddr;
+ __be32 addr = inet->rcv_saddr;
if (!addr)
addr = inet->saddr;
sin->sin_port = inet->sport;
@@ -994,8 +995,8 @@ static int inet_sk_reselect_saddr(struct sock *sk)
struct inet_sock *inet = inet_sk(sk);
int err;
struct rtable *rt;
- __u32 old_saddr = inet->saddr;
- __u32 new_saddr;
+ __be32 old_saddr = inet->saddr;
+ __be32 new_saddr;
__be32 daddr = inet->daddr;
if (inet->opt && inet->opt->srr)
@@ -1223,10 +1224,13 @@ static int __init init_ipv4_mibs(void)
tcp_statistics[1] = alloc_percpu(struct tcp_mib);
udp_statistics[0] = alloc_percpu(struct udp_mib);
udp_statistics[1] = alloc_percpu(struct udp_mib);
+ udplite_statistics[0] = alloc_percpu(struct udp_mib);
+ udplite_statistics[1] = alloc_percpu(struct udp_mib);
if (!
(net_statistics[0] && net_statistics[1] && ip_statistics[0]
&& ip_statistics[1] && tcp_statistics[0] && tcp_statistics[1]
- && udp_statistics[0] && udp_statistics[1]))
+ && udp_statistics[0] && udp_statistics[1]
+ && udplite_statistics[0] && udplite_statistics[1] ) )
return -ENOMEM;
(void) tcp_mib_init();
@@ -1313,6 +1317,8 @@ static int __init inet_init(void)
/* Setup TCP slab cache for open requests. */
tcp_init();
+ /* Add UDP-Lite (RFC 3828) */
+ udplite4_register();
/*
* Set the ICMP layer up
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index 99542977e47e..67a5509e26fc 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -14,7 +14,7 @@
* into IP header for icv calculation. Options are already checked
* for validity, so paranoia is not required. */
-static int ip_clear_mutable_options(struct iphdr *iph, u32 *daddr)
+static int ip_clear_mutable_options(struct iphdr *iph, __be32 *daddr)
{
unsigned char * optptr = (unsigned char*)(iph+1);
int l = iph->ihl*4 - sizeof(struct iphdr);
@@ -162,7 +162,7 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
iph->frag_off = 0;
iph->check = 0;
if (ihl > sizeof(*iph)) {
- u32 dummy;
+ __be32 dummy;
if (ip_clear_mutable_options(iph, &dummy))
goto out;
}
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index cfb5d3de9c84..3981e8be9ab8 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -203,7 +203,7 @@ struct neigh_table arp_tbl = {
.gc_thresh3 = 1024,
};
-int arp_mc_map(u32 addr, u8 *haddr, struct net_device *dev, int dir)
+int arp_mc_map(__be32 addr, u8 *haddr, struct net_device *dev, int dir)
{
switch (dev->type) {
case ARPHRD_ETHER:
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index 6460233407c7..60aafb4a8adf 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -319,6 +319,7 @@ static int cipso_v4_cache_check(const unsigned char *key,
entry->activity += 1;
atomic_inc(&entry->lsm_data->refcount);
secattr->cache = entry->lsm_data;
+ secattr->flags |= NETLBL_SECATTR_CACHE;
if (prev_entry == NULL) {
spin_unlock_bh(&cipso_v4_cache[bkt].lock);
return 0;
@@ -377,12 +378,11 @@ int cipso_v4_cache_add(const struct sk_buff *skb,
entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
if (entry == NULL)
return -ENOMEM;
- entry->key = kmalloc(cipso_ptr_len, GFP_ATOMIC);
+ entry->key = kmemdup(cipso_ptr, cipso_ptr_len, GFP_ATOMIC);
if (entry->key == NULL) {
ret_val = -ENOMEM;
goto cache_add_failure;
}
- memcpy(entry->key, cipso_ptr, cipso_ptr_len);
entry->key_len = cipso_ptr_len;
entry->hash = cipso_v4_map_cache_hash(cipso_ptr, cipso_ptr_len);
atomic_inc(&secattr->cache->refcount);
@@ -447,8 +447,30 @@ static struct cipso_v4_doi *cipso_v4_doi_search(u32 doi)
*/
int cipso_v4_doi_add(struct cipso_v4_doi *doi_def)
{
+ u32 iter;
+
if (doi_def == NULL || doi_def->doi == CIPSO_V4_DOI_UNKNOWN)
return -EINVAL;
+ for (iter = 0; iter < CIPSO_V4_TAG_MAXCNT; iter++) {
+ switch (doi_def->tags[iter]) {
+ case CIPSO_V4_TAG_RBITMAP:
+ break;
+ case CIPSO_V4_TAG_RANGE:
+ if (doi_def->type != CIPSO_V4_MAP_PASS)
+ return -EINVAL;
+ break;
+ case CIPSO_V4_TAG_INVALID:
+ if (iter == 0)
+ return -EINVAL;
+ break;
+ case CIPSO_V4_TAG_ENUM:
+ if (doi_def->type != CIPSO_V4_MAP_PASS)
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
doi_def->valid = 1;
INIT_RCU_HEAD(&doi_def->rcu);
@@ -805,8 +827,7 @@ static int cipso_v4_map_cat_rbm_valid(const struct cipso_v4_doi *doi_def,
/**
* cipso_v4_map_cat_rbm_hton - Perform a category mapping from host to network
* @doi_def: the DOI definition
- * @host_cat: the category bitmap in host format
- * @host_cat_len: the length of the host's category bitmap in bytes
+ * @secattr: the security attributes
* @net_cat: the zero'd out category bitmap in network/CIPSO format
* @net_cat_len: the length of the CIPSO bitmap in bytes
*
@@ -817,59 +838,51 @@ static int cipso_v4_map_cat_rbm_valid(const struct cipso_v4_doi *doi_def,
*
*/
static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def,
- const unsigned char *host_cat,
- u32 host_cat_len,
+ const struct netlbl_lsm_secattr *secattr,
unsigned char *net_cat,
u32 net_cat_len)
{
int host_spot = -1;
- u32 net_spot;
+ u32 net_spot = CIPSO_V4_INV_CAT;
u32 net_spot_max = 0;
- u32 host_clen_bits = host_cat_len * 8;
u32 net_clen_bits = net_cat_len * 8;
- u32 host_cat_size;
- u32 *host_cat_array;
+ u32 host_cat_size = 0;
+ u32 *host_cat_array = NULL;
- switch (doi_def->type) {
- case CIPSO_V4_MAP_PASS:
- net_spot_max = host_cat_len;
- while (net_spot_max > 0 && host_cat[net_spot_max - 1] == 0)
- net_spot_max--;
- if (net_spot_max > net_cat_len)
- return -EINVAL;
- memcpy(net_cat, host_cat, net_spot_max);
- return net_spot_max;
- case CIPSO_V4_MAP_STD:
+ if (doi_def->type == CIPSO_V4_MAP_STD) {
host_cat_size = doi_def->map.std->cat.local_size;
host_cat_array = doi_def->map.std->cat.local;
- for (;;) {
- host_spot = cipso_v4_bitmap_walk(host_cat,
- host_clen_bits,
- host_spot + 1,
- 1);
- if (host_spot < 0)
- break;
+ }
+
+ for (;;) {
+ host_spot = netlbl_secattr_catmap_walk(secattr->mls_cat,
+ host_spot + 1);
+ if (host_spot < 0)
+ break;
+
+ switch (doi_def->type) {
+ case CIPSO_V4_MAP_PASS:
+ net_spot = host_spot;
+ break;
+ case CIPSO_V4_MAP_STD:
if (host_spot >= host_cat_size)
return -EPERM;
-
net_spot = host_cat_array[host_spot];
- if (net_spot >= net_clen_bits)
- return -ENOSPC;
- cipso_v4_bitmap_setbit(net_cat, net_spot, 1);
-
- if (net_spot > net_spot_max)
- net_spot_max = net_spot;
+ if (net_spot >= CIPSO_V4_INV_CAT)
+ return -EPERM;
+ break;
}
+ if (net_spot >= net_clen_bits)
+ return -ENOSPC;
+ cipso_v4_bitmap_setbit(net_cat, net_spot, 1);
- if (host_spot == -2)
- return -EFAULT;
-
- if (++net_spot_max % 8)
- return net_spot_max / 8 + 1;
- return net_spot_max / 8;
+ if (net_spot > net_spot_max)
+ net_spot_max = net_spot;
}
- return -EINVAL;
+ if (++net_spot_max % 8)
+ return net_spot_max / 8 + 1;
+ return net_spot_max / 8;
}
/**
@@ -877,102 +890,333 @@ static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def,
* @doi_def: the DOI definition
* @net_cat: the category bitmap in network/CIPSO format
* @net_cat_len: the length of the CIPSO bitmap in bytes
- * @host_cat: the zero'd out category bitmap in host format
- * @host_cat_len: the length of the host's category bitmap in bytes
+ * @secattr: the security attributes
*
* Description:
* Perform a label mapping to translate a CIPSO bitmap to the correct local
- * MLS category bitmap using the given DOI definition. Returns the minimum
- * size in bytes of the host bitmap on success, negative values otherwise.
+ * MLS category bitmap using the given DOI definition. Returns zero on
+ * success, negative values on failure.
*
*/
static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def,
const unsigned char *net_cat,
u32 net_cat_len,
- unsigned char *host_cat,
- u32 host_cat_len)
+ struct netlbl_lsm_secattr *secattr)
{
- u32 host_spot;
- u32 host_spot_max = 0;
+ int ret_val;
int net_spot = -1;
+ u32 host_spot = CIPSO_V4_INV_CAT;
u32 net_clen_bits = net_cat_len * 8;
- u32 host_clen_bits = host_cat_len * 8;
- u32 net_cat_size;
- u32 *net_cat_array;
+ u32 net_cat_size = 0;
+ u32 *net_cat_array = NULL;
- switch (doi_def->type) {
- case CIPSO_V4_MAP_PASS:
- if (net_cat_len > host_cat_len)
- return -EINVAL;
- memcpy(host_cat, net_cat, net_cat_len);
- return net_cat_len;
- case CIPSO_V4_MAP_STD:
+ if (doi_def->type == CIPSO_V4_MAP_STD) {
net_cat_size = doi_def->map.std->cat.cipso_size;
net_cat_array = doi_def->map.std->cat.cipso;
- for (;;) {
- net_spot = cipso_v4_bitmap_walk(net_cat,
- net_clen_bits,
- net_spot + 1,
- 1);
- if (net_spot < 0)
- break;
- if (net_spot >= net_cat_size ||
- net_cat_array[net_spot] >= CIPSO_V4_INV_CAT)
- return -EPERM;
+ }
- host_spot = net_cat_array[net_spot];
- if (host_spot >= host_clen_bits)
- return -ENOSPC;
- cipso_v4_bitmap_setbit(host_cat, host_spot, 1);
+ for (;;) {
+ net_spot = cipso_v4_bitmap_walk(net_cat,
+ net_clen_bits,
+ net_spot + 1,
+ 1);
+ if (net_spot < 0) {
+ if (net_spot == -2)
+ return -EFAULT;
+ return 0;
+ }
- if (host_spot > host_spot_max)
- host_spot_max = host_spot;
+ switch (doi_def->type) {
+ case CIPSO_V4_MAP_PASS:
+ host_spot = net_spot;
+ break;
+ case CIPSO_V4_MAP_STD:
+ if (net_spot >= net_cat_size)
+ return -EPERM;
+ host_spot = net_cat_array[net_spot];
+ if (host_spot >= CIPSO_V4_INV_CAT)
+ return -EPERM;
+ break;
}
+ ret_val = netlbl_secattr_catmap_setbit(secattr->mls_cat,
+ host_spot,
+ GFP_ATOMIC);
+ if (ret_val != 0)
+ return ret_val;
+ }
+
+ return -EINVAL;
+}
+
+/**
+ * cipso_v4_map_cat_enum_valid - Checks to see if the categories are valid
+ * @doi_def: the DOI definition
+ * @enumcat: category list
+ * @enumcat_len: length of the category list in bytes
+ *
+ * Description:
+ * Checks the given categories against the given DOI definition and returns a
+ * negative value if any of the categories do not have a valid mapping and a
+ * zero value if all of the categories are valid.
+ *
+ */
+static int cipso_v4_map_cat_enum_valid(const struct cipso_v4_doi *doi_def,
+ const unsigned char *enumcat,
+ u32 enumcat_len)
+{
+ u16 cat;
+ int cat_prev = -1;
+ u32 iter;
+
+ if (doi_def->type != CIPSO_V4_MAP_PASS || enumcat_len & 0x01)
+ return -EFAULT;
+
+ for (iter = 0; iter < enumcat_len; iter += 2) {
+ cat = ntohs(*((__be16 *)&enumcat[iter]));
+ if (cat <= cat_prev)
+ return -EFAULT;
+ cat_prev = cat;
+ }
+
+ return 0;
+}
+
+/**
+ * cipso_v4_map_cat_enum_hton - Perform a category mapping from host to network
+ * @doi_def: the DOI definition
+ * @secattr: the security attributes
+ * @net_cat: the zero'd out category list in network/CIPSO format
+ * @net_cat_len: the length of the CIPSO category list in bytes
+ *
+ * Description:
+ * Perform a label mapping to translate a local MLS category bitmap to the
+ * correct CIPSO category list using the given DOI definition. Returns the
+ * size in bytes of the network category bitmap on success, negative values
+ * otherwise.
+ *
+ */
+static int cipso_v4_map_cat_enum_hton(const struct cipso_v4_doi *doi_def,
+ const struct netlbl_lsm_secattr *secattr,
+ unsigned char *net_cat,
+ u32 net_cat_len)
+{
+ int cat = -1;
+ u32 cat_iter = 0;
+
+ for (;;) {
+ cat = netlbl_secattr_catmap_walk(secattr->mls_cat, cat + 1);
+ if (cat < 0)
+ break;
+ if ((cat_iter + 2) > net_cat_len)
+ return -ENOSPC;
+
+ *((__be16 *)&net_cat[cat_iter]) = htons(cat);
+ cat_iter += 2;
+ }
+
+ return cat_iter;
+}
+
+/**
+ * cipso_v4_map_cat_enum_ntoh - Perform a category mapping from network to host
+ * @doi_def: the DOI definition
+ * @net_cat: the category list in network/CIPSO format
+ * @net_cat_len: the length of the CIPSO bitmap in bytes
+ * @secattr: the security attributes
+ *
+ * Description:
+ * Perform a label mapping to translate a CIPSO category list to the correct
+ * local MLS category bitmap using the given DOI definition. Returns zero on
+ * success, negative values on failure.
+ *
+ */
+static int cipso_v4_map_cat_enum_ntoh(const struct cipso_v4_doi *doi_def,
+ const unsigned char *net_cat,
+ u32 net_cat_len,
+ struct netlbl_lsm_secattr *secattr)
+{
+ int ret_val;
+ u32 iter;
+
+ for (iter = 0; iter < net_cat_len; iter += 2) {
+ ret_val = netlbl_secattr_catmap_setbit(secattr->mls_cat,
+ ntohs(*((__be16 *)&net_cat[iter])),
+ GFP_ATOMIC);
+ if (ret_val != 0)
+ return ret_val;
+ }
+
+ return 0;
+}
+
+/**
+ * cipso_v4_map_cat_rng_valid - Checks to see if the categories are valid
+ * @doi_def: the DOI definition
+ * @rngcat: category list
+ * @rngcat_len: length of the category list in bytes
+ *
+ * Description:
+ * Checks the given categories against the given DOI definition and returns a
+ * negative value if any of the categories do not have a valid mapping and a
+ * zero value if all of the categories are valid.
+ *
+ */
+static int cipso_v4_map_cat_rng_valid(const struct cipso_v4_doi *doi_def,
+ const unsigned char *rngcat,
+ u32 rngcat_len)
+{
+ u16 cat_high;
+ u16 cat_low;
+ u32 cat_prev = CIPSO_V4_MAX_REM_CATS + 1;
+ u32 iter;
- if (net_spot == -2)
+ if (doi_def->type != CIPSO_V4_MAP_PASS || rngcat_len & 0x01)
+ return -EFAULT;
+
+ for (iter = 0; iter < rngcat_len; iter += 4) {
+ cat_high = ntohs(*((__be16 *)&rngcat[iter]));
+ if ((iter + 4) <= rngcat_len)
+ cat_low = ntohs(*((__be16 *)&rngcat[iter + 2]));
+ else
+ cat_low = 0;
+
+ if (cat_high > cat_prev)
return -EFAULT;
- if (++host_spot_max % 8)
- return host_spot_max / 8 + 1;
- return host_spot_max / 8;
+ cat_prev = cat_low;
}
- return -EINVAL;
+ return 0;
+}
+
+/**
+ * cipso_v4_map_cat_rng_hton - Perform a category mapping from host to network
+ * @doi_def: the DOI definition
+ * @secattr: the security attributes
+ * @net_cat: the zero'd out category list in network/CIPSO format
+ * @net_cat_len: the length of the CIPSO category list in bytes
+ *
+ * Description:
+ * Perform a label mapping to translate a local MLS category bitmap to the
+ * correct CIPSO category list using the given DOI definition. Returns the
+ * size in bytes of the network category bitmap on success, negative values
+ * otherwise.
+ *
+ */
+static int cipso_v4_map_cat_rng_hton(const struct cipso_v4_doi *doi_def,
+ const struct netlbl_lsm_secattr *secattr,
+ unsigned char *net_cat,
+ u32 net_cat_len)
+{
+ /* The constant '16' is not random, it is the maximum number of
+ * high/low category range pairs as permitted by the CIPSO draft based
+ * on a maximum IPv4 header length of 60 bytes - the BUG_ON() assertion
+ * does a sanity check to make sure we don't overflow the array. */
+ int iter = -1;
+ u16 array[16];
+ u32 array_cnt = 0;
+ u32 cat_size = 0;
+
+ BUG_ON(net_cat_len > 30);
+
+ for (;;) {
+ iter = netlbl_secattr_catmap_walk(secattr->mls_cat, iter + 1);
+ if (iter < 0)
+ break;
+ cat_size += (iter == 0 ? 0 : sizeof(u16));
+ if (cat_size > net_cat_len)
+ return -ENOSPC;
+ array[array_cnt++] = iter;
+
+ iter = netlbl_secattr_catmap_walk_rng(secattr->mls_cat, iter);
+ if (iter < 0)
+ return -EFAULT;
+ cat_size += sizeof(u16);
+ if (cat_size > net_cat_len)
+ return -ENOSPC;
+ array[array_cnt++] = iter;
+ }
+
+ for (iter = 0; array_cnt > 0;) {
+ *((__be16 *)&net_cat[iter]) = htons(array[--array_cnt]);
+ iter += 2;
+ array_cnt--;
+ if (array[array_cnt] != 0) {
+ *((__be16 *)&net_cat[iter]) = htons(array[array_cnt]);
+ iter += 2;
+ }
+ }
+
+ return cat_size;
+}
+
+/**
+ * cipso_v4_map_cat_rng_ntoh - Perform a category mapping from network to host
+ * @doi_def: the DOI definition
+ * @net_cat: the category list in network/CIPSO format
+ * @net_cat_len: the length of the CIPSO bitmap in bytes
+ * @secattr: the security attributes
+ *
+ * Description:
+ * Perform a label mapping to translate a CIPSO category list to the correct
+ * local MLS category bitmap using the given DOI definition. Returns zero on
+ * success, negative values on failure.
+ *
+ */
+static int cipso_v4_map_cat_rng_ntoh(const struct cipso_v4_doi *doi_def,
+ const unsigned char *net_cat,
+ u32 net_cat_len,
+ struct netlbl_lsm_secattr *secattr)
+{
+ int ret_val;
+ u32 net_iter;
+ u16 cat_low;
+ u16 cat_high;
+
+ for(net_iter = 0; net_iter < net_cat_len; net_iter += 4) {
+ cat_high = ntohs(*((__be16 *)&net_cat[net_iter]));
+ if ((net_iter + 4) <= net_cat_len)
+ cat_low = ntohs(*((__be16 *)&net_cat[net_iter + 2]));
+ else
+ cat_low = 0;
+
+ ret_val = netlbl_secattr_catmap_setrng(secattr->mls_cat,
+ cat_low,
+ cat_high,
+ GFP_ATOMIC);
+ if (ret_val != 0)
+ return ret_val;
+ }
+
+ return 0;
}
/*
* Protocol Handling Functions
*/
+#define CIPSO_V4_OPT_LEN_MAX 40
#define CIPSO_V4_HDR_LEN 6
/**
* cipso_v4_gentag_hdr - Generate a CIPSO option header
* @doi_def: the DOI definition
- * @len: the total tag length in bytes
+ * @len: the total tag length in bytes, not including this header
* @buf: the CIPSO option buffer
*
* Description:
- * Write a CIPSO header into the beginning of @buffer. Return zero on success,
- * negative values on failure.
+ * Write a CIPSO header into the beginning of @buffer.
*
*/
-static int cipso_v4_gentag_hdr(const struct cipso_v4_doi *doi_def,
- u32 len,
- unsigned char *buf)
+static void cipso_v4_gentag_hdr(const struct cipso_v4_doi *doi_def,
+ unsigned char *buf,
+ u32 len)
{
- if (CIPSO_V4_HDR_LEN + len > 40)
- return -ENOSPC;
-
buf[0] = IPOPT_CIPSO;
buf[1] = CIPSO_V4_HDR_LEN + len;
- *(u32 *)&buf[2] = htonl(doi_def->doi);
-
- return 0;
+ *(__be32 *)&buf[2] = htonl(doi_def->doi);
}
-#define CIPSO_V4_TAG1_CAT_LEN 30
-
/**
* cipso_v4_gentag_rbm - Generate a CIPSO restricted bitmap tag (type #1)
* @doi_def: the DOI definition
@@ -983,83 +1227,249 @@ static int cipso_v4_gentag_hdr(const struct cipso_v4_doi *doi_def,
* Description:
* Generate a CIPSO option using the restricted bitmap tag, tag type #1. The
* actual buffer length may be larger than the indicated size due to
- * translation between host and network category bitmaps. Returns zero on
- * success, negative values on failure.
+ * translation between host and network category bitmaps. Returns the size of
+ * the tag on success, negative values on failure.
*
*/
static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def,
const struct netlbl_lsm_secattr *secattr,
- unsigned char **buffer,
- u32 *buffer_len)
+ unsigned char *buffer,
+ u32 buffer_len)
{
- int ret_val = -EPERM;
- unsigned char *buf = NULL;
- u32 buf_len;
+ int ret_val;
+ u32 tag_len;
u32 level;
- if (secattr->mls_cat) {
- buf = kzalloc(CIPSO_V4_HDR_LEN + 4 + CIPSO_V4_TAG1_CAT_LEN,
- GFP_ATOMIC);
- if (buf == NULL)
- return -ENOMEM;
+ if ((secattr->flags & NETLBL_SECATTR_MLS_LVL) == 0)
+ return -EPERM;
+
+ ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level);
+ if (ret_val != 0)
+ return ret_val;
+ if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
ret_val = cipso_v4_map_cat_rbm_hton(doi_def,
- secattr->mls_cat,
- secattr->mls_cat_len,
- &buf[CIPSO_V4_HDR_LEN + 4],
- CIPSO_V4_TAG1_CAT_LEN);
+ secattr,
+ &buffer[4],
+ buffer_len - 4);
if (ret_val < 0)
- goto gentag_failure;
+ return ret_val;
/* This will send packets using the "optimized" format when
* possibile as specified in section 3.4.2.6 of the
* CIPSO draft. */
- if (cipso_v4_rbm_optfmt && (ret_val > 0 && ret_val < 10))
- ret_val = 10;
+ if (cipso_v4_rbm_optfmt && ret_val > 0 && ret_val <= 10)
+ tag_len = 14;
+ else
+ tag_len = 4 + ret_val;
+ } else
+ tag_len = 4;
+
+ buffer[0] = 0x01;
+ buffer[1] = tag_len;
+ buffer[3] = level;
+
+ return tag_len;
+}
- buf_len = 4 + ret_val;
- } else {
- buf = kzalloc(CIPSO_V4_HDR_LEN + 4, GFP_ATOMIC);
- if (buf == NULL)
+/**
+ * cipso_v4_parsetag_rbm - Parse a CIPSO restricted bitmap tag
+ * @doi_def: the DOI definition
+ * @tag: the CIPSO tag
+ * @secattr: the security attributes
+ *
+ * Description:
+ * Parse a CIPSO restricted bitmap tag (tag type #1) and return the security
+ * attributes in @secattr. Return zero on success, negatives values on
+ * failure.
+ *
+ */
+static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def,
+ const unsigned char *tag,
+ struct netlbl_lsm_secattr *secattr)
+{
+ int ret_val;
+ u8 tag_len = tag[1];
+ u32 level;
+
+ ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level);
+ if (ret_val != 0)
+ return ret_val;
+ secattr->mls_lvl = level;
+ secattr->flags |= NETLBL_SECATTR_MLS_LVL;
+
+ if (tag_len > 4) {
+ secattr->mls_cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
+ if (secattr->mls_cat == NULL)
return -ENOMEM;
- buf_len = 4;
+
+ ret_val = cipso_v4_map_cat_rbm_ntoh(doi_def,
+ &tag[4],
+ tag_len - 4,
+ secattr);
+ if (ret_val != 0) {
+ netlbl_secattr_catmap_free(secattr->mls_cat);
+ return ret_val;
+ }
+
+ secattr->flags |= NETLBL_SECATTR_MLS_CAT;
}
+ return 0;
+}
+
+/**
+ * cipso_v4_gentag_enum - Generate a CIPSO enumerated tag (type #2)
+ * @doi_def: the DOI definition
+ * @secattr: the security attributes
+ * @buffer: the option buffer
+ * @buffer_len: length of buffer in bytes
+ *
+ * Description:
+ * Generate a CIPSO option using the enumerated tag, tag type #2. Returns the
+ * size of the tag on success, negative values on failure.
+ *
+ */
+static int cipso_v4_gentag_enum(const struct cipso_v4_doi *doi_def,
+ const struct netlbl_lsm_secattr *secattr,
+ unsigned char *buffer,
+ u32 buffer_len)
+{
+ int ret_val;
+ u32 tag_len;
+ u32 level;
+
+ if (!(secattr->flags & NETLBL_SECATTR_MLS_LVL))
+ return -EPERM;
+
ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level);
if (ret_val != 0)
- goto gentag_failure;
+ return ret_val;
+
+ if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
+ ret_val = cipso_v4_map_cat_enum_hton(doi_def,
+ secattr,
+ &buffer[4],
+ buffer_len - 4);
+ if (ret_val < 0)
+ return ret_val;
+
+ tag_len = 4 + ret_val;
+ } else
+ tag_len = 4;
+
+ buffer[0] = 0x02;
+ buffer[1] = tag_len;
+ buffer[3] = level;
- ret_val = cipso_v4_gentag_hdr(doi_def, buf_len, buf);
+ return tag_len;
+}
+
+/**
+ * cipso_v4_parsetag_enum - Parse a CIPSO enumerated tag
+ * @doi_def: the DOI definition
+ * @tag: the CIPSO tag
+ * @secattr: the security attributes
+ *
+ * Description:
+ * Parse a CIPSO enumerated tag (tag type #2) and return the security
+ * attributes in @secattr. Return zero on success, negatives values on
+ * failure.
+ *
+ */
+static int cipso_v4_parsetag_enum(const struct cipso_v4_doi *doi_def,
+ const unsigned char *tag,
+ struct netlbl_lsm_secattr *secattr)
+{
+ int ret_val;
+ u8 tag_len = tag[1];
+ u32 level;
+
+ ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level);
if (ret_val != 0)
- goto gentag_failure;
+ return ret_val;
+ secattr->mls_lvl = level;
+ secattr->flags |= NETLBL_SECATTR_MLS_LVL;
+
+ if (tag_len > 4) {
+ secattr->mls_cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
+ if (secattr->mls_cat == NULL)
+ return -ENOMEM;
- buf[CIPSO_V4_HDR_LEN] = 0x01;
- buf[CIPSO_V4_HDR_LEN + 1] = buf_len;
- buf[CIPSO_V4_HDR_LEN + 3] = level;
+ ret_val = cipso_v4_map_cat_enum_ntoh(doi_def,
+ &tag[4],
+ tag_len - 4,
+ secattr);
+ if (ret_val != 0) {
+ netlbl_secattr_catmap_free(secattr->mls_cat);
+ return ret_val;
+ }
- *buffer = buf;
- *buffer_len = CIPSO_V4_HDR_LEN + buf_len;
+ secattr->flags |= NETLBL_SECATTR_MLS_CAT;
+ }
return 0;
+}
-gentag_failure:
- kfree(buf);
- return ret_val;
+/**
+ * cipso_v4_gentag_rng - Generate a CIPSO ranged tag (type #5)
+ * @doi_def: the DOI definition
+ * @secattr: the security attributes
+ * @buffer: the option buffer
+ * @buffer_len: length of buffer in bytes
+ *
+ * Description:
+ * Generate a CIPSO option using the ranged tag, tag type #5. Returns the
+ * size of the tag on success, negative values on failure.
+ *
+ */
+static int cipso_v4_gentag_rng(const struct cipso_v4_doi *doi_def,
+ const struct netlbl_lsm_secattr *secattr,
+ unsigned char *buffer,
+ u32 buffer_len)
+{
+ int ret_val;
+ u32 tag_len;
+ u32 level;
+
+ if (!(secattr->flags & NETLBL_SECATTR_MLS_LVL))
+ return -EPERM;
+
+ ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level);
+ if (ret_val != 0)
+ return ret_val;
+
+ if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
+ ret_val = cipso_v4_map_cat_rng_hton(doi_def,
+ secattr,
+ &buffer[4],
+ buffer_len - 4);
+ if (ret_val < 0)
+ return ret_val;
+
+ tag_len = 4 + ret_val;
+ } else
+ tag_len = 4;
+
+ buffer[0] = 0x05;
+ buffer[1] = tag_len;
+ buffer[3] = level;
+
+ return tag_len;
}
/**
- * cipso_v4_parsetag_rbm - Parse a CIPSO restricted bitmap tag
+ * cipso_v4_parsetag_rng - Parse a CIPSO ranged tag
* @doi_def: the DOI definition
* @tag: the CIPSO tag
* @secattr: the security attributes
*
* Description:
- * Parse a CIPSO restricted bitmap tag (tag type #1) and return the security
- * attributes in @secattr. Return zero on success, negatives values on
- * failure.
+ * Parse a CIPSO ranged tag (tag type #5) and return the security attributes
+ * in @secattr. Return zero on success, negatives values on failure.
*
*/
-static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def,
+static int cipso_v4_parsetag_rng(const struct cipso_v4_doi *doi_def,
const unsigned char *tag,
struct netlbl_lsm_secattr *secattr)
{
@@ -1071,32 +1481,23 @@ static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def,
if (ret_val != 0)
return ret_val;
secattr->mls_lvl = level;
- secattr->mls_lvl_vld = 1;
+ secattr->flags |= NETLBL_SECATTR_MLS_LVL;
if (tag_len > 4) {
- switch (doi_def->type) {
- case CIPSO_V4_MAP_PASS:
- secattr->mls_cat_len = tag_len - 4;
- break;
- case CIPSO_V4_MAP_STD:
- secattr->mls_cat_len =
- doi_def->map.std->cat.local_size;
- break;
- }
- secattr->mls_cat = kzalloc(secattr->mls_cat_len, GFP_ATOMIC);
+ secattr->mls_cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
if (secattr->mls_cat == NULL)
return -ENOMEM;
- ret_val = cipso_v4_map_cat_rbm_ntoh(doi_def,
+ ret_val = cipso_v4_map_cat_rng_ntoh(doi_def,
&tag[4],
tag_len - 4,
- secattr->mls_cat,
- secattr->mls_cat_len);
- if (ret_val < 0) {
- kfree(secattr->mls_cat);
+ secattr);
+ if (ret_val != 0) {
+ netlbl_secattr_catmap_free(secattr->mls_cat);
return ret_val;
}
- secattr->mls_cat_len = ret_val;
+
+ secattr->flags |= NETLBL_SECATTR_MLS_CAT;
}
return 0;
@@ -1140,7 +1541,7 @@ int cipso_v4_validate(unsigned char **option)
}
rcu_read_lock();
- doi_def = cipso_v4_doi_getdef(ntohl(*((u32 *)&opt[2])));
+ doi_def = cipso_v4_doi_search(ntohl(*((__be32 *)&opt[2])));
if (doi_def == NULL) {
err_offset = 2;
goto validate_return_locked;
@@ -1191,6 +1592,44 @@ int cipso_v4_validate(unsigned char **option)
}
}
break;
+ case CIPSO_V4_TAG_ENUM:
+ if (tag_len < 4) {
+ err_offset = opt_iter + 1;
+ goto validate_return_locked;
+ }
+
+ if (cipso_v4_map_lvl_valid(doi_def,
+ tag[3]) < 0) {
+ err_offset = opt_iter + 3;
+ goto validate_return_locked;
+ }
+ if (tag_len > 4 &&
+ cipso_v4_map_cat_enum_valid(doi_def,
+ &tag[4],
+ tag_len - 4) < 0) {
+ err_offset = opt_iter + 4;
+ goto validate_return_locked;
+ }
+ break;
+ case CIPSO_V4_TAG_RANGE:
+ if (tag_len < 4) {
+ err_offset = opt_iter + 1;
+ goto validate_return_locked;
+ }
+
+ if (cipso_v4_map_lvl_valid(doi_def,
+ tag[3]) < 0) {
+ err_offset = opt_iter + 3;
+ goto validate_return_locked;
+ }
+ if (tag_len > 4 &&
+ cipso_v4_map_cat_rng_valid(doi_def,
+ &tag[4],
+ tag_len - 4) < 0) {
+ err_offset = opt_iter + 4;
+ goto validate_return_locked;
+ }
+ break;
default:
err_offset = opt_iter;
goto validate_return_locked;
@@ -1265,7 +1704,7 @@ int cipso_v4_socket_setattr(const struct socket *sock,
{
int ret_val = -EPERM;
u32 iter;
- unsigned char *buf = NULL;
+ unsigned char *buf;
u32 buf_len = 0;
u32 opt_len;
struct ip_options *opt = NULL;
@@ -1281,17 +1720,40 @@ int cipso_v4_socket_setattr(const struct socket *sock,
if (sk == NULL)
return 0;
+ /* We allocate the maximum CIPSO option size here so we are probably
+ * being a little wasteful, but it makes our life _much_ easier later
+ * on and after all we are only talking about 40 bytes. */
+ buf_len = CIPSO_V4_OPT_LEN_MAX;
+ buf = kmalloc(buf_len, GFP_ATOMIC);
+ if (buf == NULL) {
+ ret_val = -ENOMEM;
+ goto socket_setattr_failure;
+ }
+
/* XXX - This code assumes only one tag per CIPSO option which isn't
* really a good assumption to make but since we only support the MAC
* tags right now it is a safe assumption. */
iter = 0;
do {
+ memset(buf, 0, buf_len);
switch (doi_def->tags[iter]) {
case CIPSO_V4_TAG_RBITMAP:
ret_val = cipso_v4_gentag_rbm(doi_def,
- secattr,
- &buf,
- &buf_len);
+ secattr,
+ &buf[CIPSO_V4_HDR_LEN],
+ buf_len - CIPSO_V4_HDR_LEN);
+ break;
+ case CIPSO_V4_TAG_ENUM:
+ ret_val = cipso_v4_gentag_enum(doi_def,
+ secattr,
+ &buf[CIPSO_V4_HDR_LEN],
+ buf_len - CIPSO_V4_HDR_LEN);
+ break;
+ case CIPSO_V4_TAG_RANGE:
+ ret_val = cipso_v4_gentag_rng(doi_def,
+ secattr,
+ &buf[CIPSO_V4_HDR_LEN],
+ buf_len - CIPSO_V4_HDR_LEN);
break;
default:
ret_val = -EPERM;
@@ -1299,11 +1761,13 @@ int cipso_v4_socket_setattr(const struct socket *sock,
}
iter++;
- } while (ret_val != 0 &&
+ } while (ret_val < 0 &&
iter < CIPSO_V4_TAG_MAXCNT &&
doi_def->tags[iter] != CIPSO_V4_TAG_INVALID);
- if (ret_val != 0)
+ if (ret_val < 0)
goto socket_setattr_failure;
+ cipso_v4_gentag_hdr(doi_def, buf, ret_val);
+ buf_len = CIPSO_V4_HDR_LEN + ret_val;
/* We can't use ip_options_get() directly because it makes a call to
* ip_options_get_alloc() which allocates memory with GFP_KERNEL and
@@ -1370,19 +1834,33 @@ int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
if (ret_val == 0)
return ret_val;
- doi = ntohl(*(u32 *)&cipso_ptr[2]);
+ doi = ntohl(*(__be32 *)&cipso_ptr[2]);
rcu_read_lock();
- doi_def = cipso_v4_doi_getdef(doi);
+ doi_def = cipso_v4_doi_search(doi);
if (doi_def == NULL) {
rcu_read_unlock();
return -ENOMSG;
}
+
+ /* XXX - This code assumes only one tag per CIPSO option which isn't
+ * really a good assumption to make but since we only support the MAC
+ * tags right now it is a safe assumption. */
switch (cipso_ptr[6]) {
case CIPSO_V4_TAG_RBITMAP:
ret_val = cipso_v4_parsetag_rbm(doi_def,
&cipso_ptr[6],
secattr);
break;
+ case CIPSO_V4_TAG_ENUM:
+ ret_val = cipso_v4_parsetag_enum(doi_def,
+ &cipso_ptr[6],
+ secattr);
+ break;
+ case CIPSO_V4_TAG_RANGE:
+ ret_val = cipso_v4_parsetag_rng(doi_def,
+ &cipso_ptr[6],
+ secattr);
+ break;
}
rcu_read_unlock();
@@ -1430,23 +1908,30 @@ int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
u32 doi;
struct cipso_v4_doi *doi_def;
- if (!CIPSO_V4_OPTEXIST(skb))
- return -ENOMSG;
cipso_ptr = CIPSO_V4_OPTPTR(skb);
if (cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr) == 0)
return 0;
- doi = ntohl(*(u32 *)&cipso_ptr[2]);
+ doi = ntohl(*(__be32 *)&cipso_ptr[2]);
rcu_read_lock();
- doi_def = cipso_v4_doi_getdef(doi);
+ doi_def = cipso_v4_doi_search(doi);
if (doi_def == NULL)
goto skbuff_getattr_return;
+
+ /* XXX - This code assumes only one tag per CIPSO option which isn't
+ * really a good assumption to make but since we only support the MAC
+ * tags right now it is a safe assumption. */
switch (cipso_ptr[6]) {
case CIPSO_V4_TAG_RBITMAP:
ret_val = cipso_v4_parsetag_rbm(doi_def,
&cipso_ptr[6],
secattr);
break;
+ case CIPSO_V4_TAG_ENUM:
+ ret_val = cipso_v4_parsetag_enum(doi_def,
+ &cipso_ptr[6],
+ secattr);
+ break;
}
skbuff_getattr_return:
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 7602c79a389b..2fd899160f85 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -577,20 +577,20 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg
* Determine a default network mask, based on the IP address.
*/
-static __inline__ int inet_abc_len(u32 addr)
+static __inline__ int inet_abc_len(__be32 addr)
{
int rc = -1; /* Something else, probably a multicast. */
if (ZERONET(addr))
rc = 0;
else {
- addr = ntohl(addr);
+ __u32 haddr = ntohl(addr);
- if (IN_CLASSA(addr))
+ if (IN_CLASSA(haddr))
rc = 8;
- else if (IN_CLASSB(addr))
+ else if (IN_CLASSB(haddr))
rc = 16;
- else if (IN_CLASSC(addr))
+ else if (IN_CLASSC(haddr))
rc = 24;
}
@@ -1120,6 +1120,16 @@ static struct notifier_block ip_netdev_notifier = {
.notifier_call =inetdev_event,
};
+static inline size_t inet_nlmsg_size(void)
+{
+ return NLMSG_ALIGN(sizeof(struct ifaddrmsg))
+ + nla_total_size(4) /* IFA_ADDRESS */
+ + nla_total_size(4) /* IFA_LOCAL */
+ + nla_total_size(4) /* IFA_BROADCAST */
+ + nla_total_size(4) /* IFA_ANYCAST */
+ + nla_total_size(IFNAMSIZ); /* IFA_LABEL */
+}
+
static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
u32 pid, u32 seq, int event, unsigned int flags)
{
@@ -1208,15 +1218,13 @@ static void rtmsg_ifa(int event, struct in_ifaddr* ifa, struct nlmsghdr *nlh,
u32 seq = nlh ? nlh->nlmsg_seq : 0;
int err = -ENOBUFS;
- skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+ skb = nlmsg_new(inet_nlmsg_size(), GFP_KERNEL);
if (skb == NULL)
goto errout;
err = inet_fill_ifaddr(skb, ifa, pid, seq, event, 0);
- if (err < 0) {
- kfree_skb(skb);
- goto errout;
- }
+ /* failure implies BUG in inet_nlmsg_size() */
+ BUG_ON(err < 0);
err = rtnl_notify(skb, pid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL);
errout:
@@ -1556,12 +1564,12 @@ static void devinet_sysctl_register(struct in_device *in_dev,
{
int i;
struct net_device *dev = in_dev ? in_dev->dev : NULL;
- struct devinet_sysctl_table *t = kmalloc(sizeof(*t), GFP_KERNEL);
+ struct devinet_sysctl_table *t = kmemdup(&devinet_sysctl, sizeof(*t),
+ GFP_KERNEL);
char *dev_name = NULL;
if (!t)
return;
- memcpy(t, &devinet_sysctl, sizeof(*t));
for (i = 0; i < ARRAY_SIZE(t->devinet_vars) - 1; i++) {
t->devinet_vars[i].data += (char *)p - (char *)&ipv4_devconf;
t->devinet_vars[i].de = NULL;
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index b5c205b57669..f2c6776ea0e6 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -67,7 +67,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
if (x->encap) {
struct xfrm_encap_tmpl *encap = x->encap;
struct udphdr *uh;
- u32 *udpdata32;
+ __be32 *udpdata32;
uh = (struct udphdr *)esph;
uh->source = encap->encap_sport;
@@ -81,7 +81,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
esph = (struct ip_esp_hdr *)(uh + 1);
break;
case UDP_ENCAP_ESPINUDP_NON_IKE:
- udpdata32 = (u32 *)(uh + 1);
+ udpdata32 = (__be32 *)(uh + 1);
udpdata32[0] = udpdata32[1] = 0;
esph = (struct ip_esp_hdr *)(udpdata32 + 2);
break;
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index af0190d8b6c0..d47b72af89ed 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -768,8 +768,8 @@ static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb )
{
struct fib_result res;
- struct flowi fl = { .nl_u = { .ip4_u = { .daddr = frn->fl_addr,
- .fwmark = frn->fl_fwmark,
+ struct flowi fl = { .mark = frn->fl_mark,
+ .nl_u = { .ip4_u = { .daddr = frn->fl_addr,
.tos = frn->fl_tos,
.scope = frn->fl_scope } } };
if (tb) {
@@ -811,7 +811,6 @@ static void nl_fib_input(struct sock *sk, int len)
pid = nlh->nlmsg_pid; /*pid of sending process */
NETLINK_CB(skb).pid = 0; /* from kernel */
- NETLINK_CB(skb).dst_pid = pid;
NETLINK_CB(skb).dst_group = 0; /* unicast */
netlink_unicast(sk, skb, pid, MSG_DONTWAIT);
}
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 0852b9cd065a..b837c33e0404 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -44,10 +44,6 @@ struct fib4_rule
__be32 srcmask;
__be32 dst;
__be32 dstmask;
-#ifdef CONFIG_IP_ROUTE_FWMARK
- u32 fwmark;
- u32 fwmask;
-#endif
#ifdef CONFIG_NET_CLS_ROUTE
u32 tclassid;
#endif
@@ -160,11 +156,6 @@ static int fib4_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
if (r->tos && (r->tos != fl->fl4_tos))
return 0;
-#ifdef CONFIG_IP_ROUTE_FWMARK
- if ((r->fwmark ^ fl->fl4_fwmark) & r->fwmask)
- return 0;
-#endif
-
return 1;
}
@@ -179,14 +170,10 @@ static struct fib_table *fib_empty_table(void)
}
static struct nla_policy fib4_rule_policy[FRA_MAX+1] __read_mostly = {
- [FRA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 },
- [FRA_PRIORITY] = { .type = NLA_U32 },
+ FRA_GENERIC_POLICY,
[FRA_SRC] = { .type = NLA_U32 },
[FRA_DST] = { .type = NLA_U32 },
- [FRA_FWMARK] = { .type = NLA_U32 },
- [FRA_FWMASK] = { .type = NLA_U32 },
[FRA_FLOW] = { .type = NLA_U32 },
- [FRA_TABLE] = { .type = NLA_U32 },
};
static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
@@ -220,20 +207,6 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
if (tb[FRA_DST])
rule4->dst = nla_get_be32(tb[FRA_DST]);
-#ifdef CONFIG_IP_ROUTE_FWMARK
- if (tb[FRA_FWMARK]) {
- rule4->fwmark = nla_get_u32(tb[FRA_FWMARK]);
- if (rule4->fwmark)
- /* compatibility: if the mark value is non-zero all bits
- * are compared unless a mask is explicitly specified.
- */
- rule4->fwmask = 0xFFFFFFFF;
- }
-
- if (tb[FRA_FWMASK])
- rule4->fwmask = nla_get_u32(tb[FRA_FWMASK]);
-#endif
-
#ifdef CONFIG_NET_CLS_ROUTE
if (tb[FRA_FLOW])
rule4->tclassid = nla_get_u32(tb[FRA_FLOW]);
@@ -264,14 +237,6 @@ static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
if (frh->tos && (rule4->tos != frh->tos))
return 0;
-#ifdef CONFIG_IP_ROUTE_FWMARK
- if (tb[FRA_FWMARK] && (rule4->fwmark != nla_get_u32(tb[FRA_FWMARK])))
- return 0;
-
- if (tb[FRA_FWMASK] && (rule4->fwmask != nla_get_u32(tb[FRA_FWMASK])))
- return 0;
-#endif
-
#ifdef CONFIG_NET_CLS_ROUTE
if (tb[FRA_FLOW] && (rule4->tclassid != nla_get_u32(tb[FRA_FLOW])))
return 0;
@@ -296,14 +261,6 @@ static int fib4_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
frh->src_len = rule4->src_len;
frh->tos = rule4->tos;
-#ifdef CONFIG_IP_ROUTE_FWMARK
- if (rule4->fwmark)
- NLA_PUT_U32(skb, FRA_FWMARK, rule4->fwmark);
-
- if (rule4->fwmask || rule4->fwmark)
- NLA_PUT_U32(skb, FRA_FWMASK, rule4->fwmask);
-#endif
-
if (rule4->dst_len)
NLA_PUT_BE32(skb, FRA_DST, rule4->dst);
@@ -342,6 +299,13 @@ static u32 fib4_rule_default_pref(void)
return 0;
}
+static size_t fib4_rule_nlmsg_payload(struct fib_rule *rule)
+{
+ return nla_total_size(4) /* dst */
+ + nla_total_size(4) /* src */
+ + nla_total_size(4); /* flow */
+}
+
static struct fib_rules_ops fib4_rules_ops = {
.family = AF_INET,
.rule_size = sizeof(struct fib4_rule),
@@ -351,6 +315,7 @@ static struct fib_rules_ops fib4_rules_ops = {
.compare = fib4_rule_compare,
.fill = fib4_rule_fill,
.default_pref = fib4_rule_default_pref,
+ .nlmsg_payload = fib4_rule_nlmsg_payload,
.nlgroup = RTNLGRP_IPV4_RULE,
.policy = fib4_rule_policy,
.rules_list = &fib4_rules,
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 884d176e0082..e63b8a98fb4d 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -273,25 +273,49 @@ int ip_fib_check_default(__be32 gw, struct net_device *dev)
return -1;
}
+static inline size_t fib_nlmsg_size(struct fib_info *fi)
+{
+ size_t payload = NLMSG_ALIGN(sizeof(struct rtmsg))
+ + nla_total_size(4) /* RTA_TABLE */
+ + nla_total_size(4) /* RTA_DST */
+ + nla_total_size(4) /* RTA_PRIORITY */
+ + nla_total_size(4); /* RTA_PREFSRC */
+
+ /* space for nested metrics */
+ payload += nla_total_size((RTAX_MAX * nla_total_size(4)));
+
+ if (fi->fib_nhs) {
+ /* Also handles the special case fib_nhs == 1 */
+
+ /* each nexthop is packed in an attribute */
+ size_t nhsize = nla_total_size(sizeof(struct rtnexthop));
+
+ /* may contain flow and gateway attribute */
+ nhsize += 2 * nla_total_size(4);
+
+ /* all nexthops are packed in a nested attribute */
+ payload += nla_total_size(fi->fib_nhs * nhsize);
+ }
+
+ return payload;
+}
+
void rtmsg_fib(int event, __be32 key, struct fib_alias *fa,
int dst_len, u32 tb_id, struct nl_info *info)
{
struct sk_buff *skb;
- int payload = sizeof(struct rtmsg) + 256;
u32 seq = info->nlh ? info->nlh->nlmsg_seq : 0;
int err = -ENOBUFS;
- skb = nlmsg_new(nlmsg_total_size(payload), GFP_KERNEL);
+ skb = nlmsg_new(fib_nlmsg_size(fa->fa_info), GFP_KERNEL);
if (skb == NULL)
goto errout;
err = fib_dump_info(skb, info->pid, seq, event, tb_id,
fa->fa_type, fa->fa_scope, key, dst_len,
fa->fa_tos, fa->fa_info, 0);
- if (err < 0) {
- kfree_skb(skb);
- goto errout;
- }
+ /* failure implies BUG in fib_nlmsg_size() */
+ BUG_ON(err < 0);
err = rtnl_notify(skb, info->pid, RTNLGRP_IPV4_ROUTE,
info->nlh, GFP_KERNEL);
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index b39a37a47545..40cf0d0e1b83 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -332,7 +332,7 @@ static int icmp_glue_bits(void *from, char *to, int offset, int len, int odd,
struct sk_buff *skb)
{
struct icmp_bxm *icmp_param = (struct icmp_bxm *)from;
- unsigned int csum;
+ __wsum csum;
csum = skb_copy_and_csum_bits(icmp_param->skb,
icmp_param->offset + offset,
@@ -356,7 +356,7 @@ static void icmp_push_reply(struct icmp_bxm *icmp_param,
ip_flush_pending_frames(icmp_socket->sk);
else if ((skb = skb_peek(&icmp_socket->sk->sk_write_queue)) != NULL) {
struct icmphdr *icmph = skb->h.icmph;
- unsigned int csum = 0;
+ __wsum csum = 0;
struct sk_buff *skb1;
skb_queue_walk(&icmp_socket->sk->sk_write_queue, skb1) {
@@ -931,7 +931,7 @@ int icmp_rcv(struct sk_buff *skb)
switch (skb->ip_summed) {
case CHECKSUM_COMPLETE:
- if (!(u16)csum_fold(skb->csum))
+ if (!csum_fold(skb->csum))
break;
/* fall through */
case CHECKSUM_NONE:
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 6eee71647b7c..0017ccb01d6d 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -932,7 +932,7 @@ int igmp_rcv(struct sk_buff *skb)
switch (skb->ip_summed) {
case CHECKSUM_COMPLETE:
- if (!(u16)csum_fold(skb->csum))
+ if (!csum_fold(skb->csum))
break;
/* fall through */
case CHECKSUM_NONE:
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 96bbe2a0aa1b..9d68837888d3 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -343,7 +343,7 @@ struct dst_entry* inet_csk_route_req(struct sock *sk,
EXPORT_SYMBOL_GPL(inet_csk_route_req);
static inline u32 inet_synq_hash(const __be32 raddr, const __be16 rport,
- const u32 rnd, const u16 synq_hsize)
+ const u32 rnd, const u32 synq_hsize)
{
return jhash_2words((__force u32)raddr, (__force u32)rport, rnd) & (synq_hsize - 1);
}
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index d5b5dec075b8..476cb6084c75 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -144,7 +144,7 @@ static struct net_device *ipgre_fb_tunnel_dev;
*/
#define HASH_SIZE 16
-#define HASH(addr) ((addr^(addr>>4))&0xF)
+#define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF)
static struct ip_tunnel *tunnels[4][HASH_SIZE];
@@ -157,7 +157,7 @@ static DEFINE_RWLOCK(ipgre_lock);
/* Given src, dst and key, find appropriate for input tunnel. */
-static struct ip_tunnel * ipgre_tunnel_lookup(u32 remote, u32 local, u32 key)
+static struct ip_tunnel * ipgre_tunnel_lookup(__be32 remote, __be32 local, __be32 key)
{
unsigned h0 = HASH(remote);
unsigned h1 = HASH(key);
@@ -194,9 +194,9 @@ static struct ip_tunnel * ipgre_tunnel_lookup(u32 remote, u32 local, u32 key)
static struct ip_tunnel **ipgre_bucket(struct ip_tunnel *t)
{
- u32 remote = t->parms.iph.daddr;
- u32 local = t->parms.iph.saddr;
- u32 key = t->parms.i_key;
+ __be32 remote = t->parms.iph.daddr;
+ __be32 local = t->parms.iph.saddr;
+ __be32 key = t->parms.i_key;
unsigned h = HASH(key);
int prio = 0;
@@ -236,9 +236,9 @@ static void ipgre_tunnel_unlink(struct ip_tunnel *t)
static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int create)
{
- u32 remote = parms->iph.daddr;
- u32 local = parms->iph.saddr;
- u32 key = parms->i_key;
+ __be32 remote = parms->iph.daddr;
+ __be32 local = parms->iph.saddr;
+ __be32 key = parms->i_key;
struct ip_tunnel *t, **tp, *nt;
struct net_device *dev;
unsigned h = HASH(key);
@@ -319,12 +319,12 @@ static void ipgre_err(struct sk_buff *skb, u32 info)
*/
struct iphdr *iph = (struct iphdr*)skb->data;
- u16 *p = (u16*)(skb->data+(iph->ihl<<2));
+ __be16 *p = (__be16*)(skb->data+(iph->ihl<<2));
int grehlen = (iph->ihl<<2) + 4;
int type = skb->h.icmph->type;
int code = skb->h.icmph->code;
struct ip_tunnel *t;
- u16 flags;
+ __be16 flags;
flags = p[0];
if (flags&(GRE_CSUM|GRE_KEY|GRE_SEQ|GRE_ROUTING|GRE_VERSION)) {
@@ -370,7 +370,7 @@ static void ipgre_err(struct sk_buff *skb, u32 info)
}
read_lock(&ipgre_lock);
- t = ipgre_tunnel_lookup(iph->daddr, iph->saddr, (flags&GRE_KEY) ? *(((u32*)p) + (grehlen>>2) - 1) : 0);
+ t = ipgre_tunnel_lookup(iph->daddr, iph->saddr, (flags&GRE_KEY) ? *(((__be32*)p) + (grehlen>>2) - 1) : 0);
if (t == NULL || t->parms.iph.daddr == 0 || MULTICAST(t->parms.iph.daddr))
goto out;
@@ -388,14 +388,14 @@ out:
#else
struct iphdr *iph = (struct iphdr*)dp;
struct iphdr *eiph;
- u16 *p = (u16*)(dp+(iph->ihl<<2));
+ __be16 *p = (__be16*)(dp+(iph->ihl<<2));
int type = skb->h.icmph->type;
int code = skb->h.icmph->code;
int rel_type = 0;
int rel_code = 0;
__be32 rel_info = 0;
__u32 n = 0;
- u16 flags;
+ __be16 flags;
int grehlen = (iph->ihl<<2) + 4;
struct sk_buff *skb2;
struct flowi fl;
@@ -556,9 +556,9 @@ static int ipgre_rcv(struct sk_buff *skb)
{
struct iphdr *iph;
u8 *h;
- u16 flags;
- u16 csum = 0;
- u32 key = 0;
+ __be16 flags;
+ __sum16 csum = 0;
+ __be32 key = 0;
u32 seqno = 0;
struct ip_tunnel *tunnel;
int offset = 4;
@@ -568,7 +568,7 @@ static int ipgre_rcv(struct sk_buff *skb)
iph = skb->nh.iph;
h = skb->data;
- flags = *(u16*)h;
+ flags = *(__be16*)h;
if (flags&(GRE_CSUM|GRE_KEY|GRE_ROUTING|GRE_SEQ|GRE_VERSION)) {
/* - Version must be 0.
@@ -580,7 +580,7 @@ static int ipgre_rcv(struct sk_buff *skb)
if (flags&GRE_CSUM) {
switch (skb->ip_summed) {
case CHECKSUM_COMPLETE:
- csum = (u16)csum_fold(skb->csum);
+ csum = csum_fold(skb->csum);
if (!csum)
break;
/* fall through */
@@ -592,11 +592,11 @@ static int ipgre_rcv(struct sk_buff *skb)
offset += 4;
}
if (flags&GRE_KEY) {
- key = *(u32*)(h + offset);
+ key = *(__be32*)(h + offset);
offset += 4;
}
if (flags&GRE_SEQ) {
- seqno = ntohl(*(u32*)(h + offset));
+ seqno = ntohl(*(__be32*)(h + offset));
offset += 4;
}
}
@@ -605,7 +605,7 @@ static int ipgre_rcv(struct sk_buff *skb)
if ((tunnel = ipgre_tunnel_lookup(iph->saddr, iph->daddr, key)) != NULL) {
secpath_reset(skb);
- skb->protocol = *(u16*)(h + 2);
+ skb->protocol = *(__be16*)(h + 2);
/* WCCP version 1 and 2 protocol decoding.
* - Change protocol to IP
* - When dealing with WCCPv2, Skip extra 4 bytes in GRE header
@@ -673,13 +673,13 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
struct iphdr *old_iph = skb->nh.iph;
struct iphdr *tiph;
u8 tos;
- u16 df;
+ __be16 df;
struct rtable *rt; /* Route to the other host */
struct net_device *tdev; /* Device to other host */
struct iphdr *iph; /* Our new IP header */
int max_headroom; /* The extra header space needed */
int gre_hlen;
- u32 dst;
+ __be32 dst;
int mtu;
if (tunnel->recursion++) {
@@ -860,11 +860,11 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
iph->ttl = dst_metric(&rt->u.dst, RTAX_HOPLIMIT);
}
- ((u16*)(iph+1))[0] = tunnel->parms.o_flags;
- ((u16*)(iph+1))[1] = skb->protocol;
+ ((__be16*)(iph+1))[0] = tunnel->parms.o_flags;
+ ((__be16*)(iph+1))[1] = skb->protocol;
if (tunnel->parms.o_flags&(GRE_KEY|GRE_CSUM|GRE_SEQ)) {
- u32 *ptr = (u32*)(((u8*)iph) + tunnel->hlen - 4);
+ __be32 *ptr = (__be32*)(((u8*)iph) + tunnel->hlen - 4);
if (tunnel->parms.o_flags&GRE_SEQ) {
++tunnel->o_seqno;
@@ -877,7 +877,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
}
if (tunnel->parms.o_flags&GRE_CSUM) {
*ptr = 0;
- *(__u16*)ptr = ip_compute_csum((void*)(iph+1), skb->len - sizeof(struct iphdr));
+ *(__sum16*)ptr = ip_compute_csum((void*)(iph+1), skb->len - sizeof(struct iphdr));
}
}
@@ -1068,7 +1068,7 @@ static int ipgre_header(struct sk_buff *skb, struct net_device *dev, unsigned sh
{
struct ip_tunnel *t = netdev_priv(dev);
struct iphdr *iph = (struct iphdr *)skb_push(skb, t->hlen);
- u16 *p = (u16*)(iph+1);
+ __be16 *p = (__be16*)(iph+1);
memcpy(iph, &t->parms.iph, sizeof(struct iphdr));
p[0] = t->parms.o_flags;
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index fc195a44fc2e..1da3d32f8289 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -288,9 +288,8 @@ int ip_output(struct sk_buff *skb)
!(IPCB(skb)->flags & IPSKB_REROUTED));
}
-int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
+int ip_queue_xmit(struct sk_buff *skb, struct sock *sk, int ipfragok)
{
- struct sock *sk = skb->sk;
struct inet_sock *inet = inet_sk(sk);
struct ip_options *opt = inet->opt;
struct rtable *rt;
@@ -342,7 +341,7 @@ packet_routed:
/* OK, we know where to send it, allocate and build IP header. */
iph = (struct iphdr *) skb_push(skb, sizeof(struct iphdr) + (opt ? opt->optlen : 0));
- *((__u16 *)iph) = htons((4 << 12) | (5 << 8) | (inet->tos & 0xff));
+ *((__be16 *)iph) = htons((4 << 12) | (5 << 8) | (inet->tos & 0xff));
iph->tot_len = htons(skb->len);
if (ip_dont_fragment(sk, &rt->u.dst) && !ipfragok)
iph->frag_off = htons(IP_DF);
@@ -386,6 +385,7 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from)
dst_release(to->dst);
to->dst = dst_clone(from->dst);
to->dev = from->dev;
+ to->mark = from->mark;
/* Copy the flags to each fragment. */
IPCB(to)->flags = IPCB(from)->flags;
@@ -394,7 +394,6 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from)
to->tc_index = from->tc_index;
#endif
#ifdef CONFIG_NETFILTER
- to->nfmark = from->nfmark;
/* Connection association is same as pre-frag packet */
nf_conntrack_put(to->nfct);
to->nfct = from->nfct;
@@ -683,7 +682,7 @@ ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk
if (memcpy_fromiovecend(to, iov, offset, len) < 0)
return -EFAULT;
} else {
- unsigned int csum = 0;
+ __wsum csum = 0;
if (csum_partial_copy_fromiovecend(to, iov, offset, len, &csum) < 0)
return -EFAULT;
skb->csum = csum_block_add(skb->csum, csum, odd);
@@ -691,11 +690,11 @@ ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk
return 0;
}
-static inline unsigned int
+static inline __wsum
csum_page(struct page *page, int offset, int copy)
{
char *kaddr;
- unsigned int csum;
+ __wsum csum;
kaddr = kmap(page);
csum = csum_partial(kaddr + offset, copy, 0);
kunmap(page);
@@ -1167,7 +1166,7 @@ ssize_t ip_append_page(struct sock *sk, struct page *page,
}
if (skb->ip_summed == CHECKSUM_NONE) {
- unsigned int csum;
+ __wsum csum;
csum = csum_page(page, offset, len);
skb->csum = csum_block_add(skb->csum, csum, skb->len);
}
@@ -1315,7 +1314,7 @@ void ip_flush_pending_frames(struct sock *sk)
static int ip_reply_glue_bits(void *dptr, char *to, int offset,
int len, int odd, struct sk_buff *skb)
{
- unsigned int csum;
+ __wsum csum;
csum = csum_partial_copy_nocheck(dptr+offset, to, len, 0);
skb->csum = csum_block_add(skb->csum, csum, odd);
@@ -1385,7 +1384,7 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar
&ipc, rt, MSG_DONTWAIT);
if ((skb = skb_peek(&sk->sk_write_queue)) != NULL) {
if (arg->csumoffset >= 0)
- *((u16 *)skb->h.raw + arg->csumoffset) = csum_fold(csum_add(skb->csum, arg->csum));
+ *((__sum16 *)skb->h.raw + arg->csumoffset) = csum_fold(csum_add(skb->csum, arg->csum));
skb->ip_summed = CHECKSUM_NONE;
ip_push_pending_frames(sk);
}
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 4b132953bcc2..57d4bae6f080 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -355,7 +355,7 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len)
sin = (struct sockaddr_in *)msg->msg_name;
if (sin) {
sin->sin_family = AF_INET;
- sin->sin_addr.s_addr = *(u32*)(skb->nh.raw + serr->addr_offset);
+ sin->sin_addr.s_addr = *(__be32*)(skb->nh.raw + serr->addr_offset);
sin->sin_port = serr->port;
memset(&sin->sin_zero, 0, sizeof(sin->sin_zero));
}
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index 955a07abb91d..afa60b9a003f 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -101,6 +101,7 @@
#define CONF_NAMESERVERS_MAX 3 /* Maximum number of nameservers
- '3' from resolv.h */
+#define NONE __constant_htonl(INADDR_NONE)
/*
* Public IP configuration
@@ -129,19 +130,19 @@ int ic_proto_enabled __initdata = 0
static int ic_host_name_set __initdata = 0; /* Host name set by us? */
-u32 ic_myaddr = INADDR_NONE; /* My IP address */
-static u32 ic_netmask = INADDR_NONE; /* Netmask for local subnet */
-u32 ic_gateway = INADDR_NONE; /* Gateway IP address */
+__be32 ic_myaddr = NONE; /* My IP address */
+static __be32 ic_netmask = NONE; /* Netmask for local subnet */
+__be32 ic_gateway = NONE; /* Gateway IP address */
-u32 ic_servaddr = INADDR_NONE; /* Boot server IP address */
+__be32 ic_servaddr = NONE; /* Boot server IP address */
-u32 root_server_addr = INADDR_NONE; /* Address of NFS server */
+__be32 root_server_addr = NONE; /* Address of NFS server */
u8 root_server_path[256] = { 0, }; /* Path to mount as root */
/* Persistent data: */
static int ic_proto_used; /* Protocol used, if any */
-static u32 ic_nameservers[CONF_NAMESERVERS_MAX]; /* DNS Server IP addresses */
+static __be32 ic_nameservers[CONF_NAMESERVERS_MAX]; /* DNS Server IP addresses */
static u8 ic_domain[64]; /* DNS (not NIS) domain name */
/*
@@ -172,7 +173,7 @@ struct ic_device {
struct net_device *dev;
unsigned short flags;
short able;
- u32 xid;
+ __be32 xid;
};
static struct ic_device *ic_first_dev __initdata = NULL;/* List of open device */
@@ -223,7 +224,7 @@ static int __init ic_open_devs(void)
d->flags = oflags;
d->able = able;
if (able & IC_BOOTP)
- get_random_bytes(&d->xid, sizeof(u32));
+ get_random_bytes(&d->xid, sizeof(__be32));
else
d->xid = 0;
ic_proto_have_if |= able;
@@ -269,7 +270,7 @@ static void __init ic_close_devs(void)
*/
static inline void
-set_sockaddr(struct sockaddr_in *sin, u32 addr, u16 port)
+set_sockaddr(struct sockaddr_in *sin, __be32 addr, __be16 port)
{
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = addr;
@@ -332,7 +333,7 @@ static int __init ic_setup_routes(void)
{
/* No need to setup device routes, only the default route... */
- if (ic_gateway != INADDR_NONE) {
+ if (ic_gateway != NONE) {
struct rtentry rm;
int err;
@@ -368,10 +369,10 @@ static int __init ic_defaults(void)
if (!ic_host_name_set)
sprintf(init_utsname()->nodename, "%u.%u.%u.%u", NIPQUAD(ic_myaddr));
- if (root_server_addr == INADDR_NONE)
+ if (root_server_addr == NONE)
root_server_addr = ic_servaddr;
- if (ic_netmask == INADDR_NONE) {
+ if (ic_netmask == NONE) {
if (IN_CLASSA(ntohl(ic_myaddr)))
ic_netmask = htonl(IN_CLASSA_NET);
else if (IN_CLASSB(ntohl(ic_myaddr)))
@@ -420,7 +421,7 @@ ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
{
struct arphdr *rarp;
unsigned char *rarp_ptr;
- u32 sip, tip;
+ __be32 sip, tip;
unsigned char *sha, *tha; /* s for "source", t for "target" */
struct ic_device *d;
@@ -485,12 +486,12 @@ ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
goto drop_unlock;
/* Discard packets which are not from specified server. */
- if (ic_servaddr != INADDR_NONE && ic_servaddr != sip)
+ if (ic_servaddr != NONE && ic_servaddr != sip)
goto drop_unlock;
/* We have a winner! */
ic_dev = dev;
- if (ic_myaddr == INADDR_NONE)
+ if (ic_myaddr == NONE)
ic_myaddr = tip;
ic_servaddr = sip;
ic_got_reply = IC_RARP;
@@ -530,13 +531,13 @@ struct bootp_pkt { /* BOOTP packet format */
u8 htype; /* HW address type */
u8 hlen; /* HW address length */
u8 hops; /* Used only by gateways */
- u32 xid; /* Transaction ID */
- u16 secs; /* Seconds since we started */
- u16 flags; /* Just what it says */
- u32 client_ip; /* Client's IP address if known */
- u32 your_ip; /* Assigned IP address */
- u32 server_ip; /* (Next, e.g. NFS) Server's IP address */
- u32 relay_ip; /* IP address of BOOTP relay */
+ __be32 xid; /* Transaction ID */
+ __be16 secs; /* Seconds since we started */
+ __be16 flags; /* Just what it says */
+ __be32 client_ip; /* Client's IP address if known */
+ __be32 your_ip; /* Assigned IP address */
+ __be32 server_ip; /* (Next, e.g. NFS) Server's IP address */
+ __be32 relay_ip; /* IP address of BOOTP relay */
u8 hw_addr[16]; /* Client's HW address */
u8 serv_name[64]; /* Server host name */
u8 boot_file[128]; /* Name of boot file */
@@ -576,7 +577,7 @@ static const u8 ic_bootp_cookie[4] = { 99, 130, 83, 99 };
static void __init
ic_dhcp_init_options(u8 *options)
{
- u8 mt = ((ic_servaddr == INADDR_NONE)
+ u8 mt = ((ic_servaddr == NONE)
? DHCPDISCOVER : DHCPREQUEST);
u8 *e = options;
@@ -666,7 +667,7 @@ static inline void ic_bootp_init(void)
int i;
for (i = 0; i < CONF_NAMESERVERS_MAX; i++)
- ic_nameservers[i] = INADDR_NONE;
+ ic_nameservers[i] = NONE;
dev_add_pack(&bootp_packet_type);
}
@@ -708,7 +709,7 @@ static void __init ic_bootp_send_if(struct ic_device *d, unsigned long jiffies_d
h->frag_off = htons(IP_DF);
h->ttl = 64;
h->protocol = IPPROTO_UDP;
- h->daddr = INADDR_BROADCAST;
+ h->daddr = htonl(INADDR_BROADCAST);
h->check = ip_fast_csum((unsigned char *) h, h->ihl);
/* Construct UDP header */
@@ -730,8 +731,8 @@ static void __init ic_bootp_send_if(struct ic_device *d, unsigned long jiffies_d
b->htype = dev->type; /* can cause undefined behavior */
}
b->hlen = dev->addr_len;
- b->your_ip = INADDR_NONE;
- b->server_ip = INADDR_NONE;
+ b->your_ip = NONE;
+ b->server_ip = NONE;
memcpy(b->hw_addr, dev->dev_addr, dev->addr_len);
b->secs = htons(jiffies_diff / HZ);
b->xid = d->xid;
@@ -788,11 +789,11 @@ static void __init ic_do_bootp_ext(u8 *ext)
switch (*ext++) {
case 1: /* Subnet mask */
- if (ic_netmask == INADDR_NONE)
+ if (ic_netmask == NONE)
memcpy(&ic_netmask, ext+1, 4);
break;
case 3: /* Default gateway */
- if (ic_gateway == INADDR_NONE)
+ if (ic_gateway == NONE)
memcpy(&ic_gateway, ext+1, 4);
break;
case 6: /* DNS server */
@@ -800,7 +801,7 @@ static void __init ic_do_bootp_ext(u8 *ext)
if (servers > CONF_NAMESERVERS_MAX)
servers = CONF_NAMESERVERS_MAX;
for (i = 0; i < servers; i++) {
- if (ic_nameservers[i] == INADDR_NONE)
+ if (ic_nameservers[i] == NONE)
memcpy(&ic_nameservers[i], ext+1+4*i, 4);
}
break;
@@ -917,7 +918,7 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str
#ifdef IPCONFIG_DHCP
if (ic_proto_enabled & IC_USE_DHCP) {
- u32 server_id = INADDR_NONE;
+ __be32 server_id = NONE;
int mt = 0;
ext = &b->exten[4];
@@ -949,7 +950,7 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str
/* While in the process of accepting one offer,
* ignore all others.
*/
- if (ic_myaddr != INADDR_NONE)
+ if (ic_myaddr != NONE)
goto drop_unlock;
/* Let's accept that offer. */
@@ -965,7 +966,7 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str
* precedence over the bootp header one if
* they are different.
*/
- if ((server_id != INADDR_NONE) &&
+ if ((server_id != NONE) &&
(b->server_ip != server_id))
b->server_ip = ic_servaddr;
break;
@@ -979,8 +980,8 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str
default:
/* Urque. Forget it*/
- ic_myaddr = INADDR_NONE;
- ic_servaddr = INADDR_NONE;
+ ic_myaddr = NONE;
+ ic_servaddr = NONE;
goto drop_unlock;
};
@@ -1004,9 +1005,9 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str
ic_dev = dev;
ic_myaddr = b->your_ip;
ic_servaddr = b->server_ip;
- if (ic_gateway == INADDR_NONE && b->relay_ip)
+ if (ic_gateway == NONE && b->relay_ip)
ic_gateway = b->relay_ip;
- if (ic_nameservers[0] == INADDR_NONE)
+ if (ic_nameservers[0] == NONE)
ic_nameservers[0] = ic_servaddr;
ic_got_reply = IC_BOOTP;
@@ -1150,7 +1151,7 @@ static int __init ic_dynamic(void)
#endif
if (!ic_got_reply) {
- ic_myaddr = INADDR_NONE;
+ ic_myaddr = NONE;
return -1;
}
@@ -1182,12 +1183,12 @@ static int pnp_seq_show(struct seq_file *seq, void *v)
seq_printf(seq,
"domain %s\n", ic_domain);
for (i = 0; i < CONF_NAMESERVERS_MAX; i++) {
- if (ic_nameservers[i] != INADDR_NONE)
+ if (ic_nameservers[i] != NONE)
seq_printf(seq,
"nameserver %u.%u.%u.%u\n",
NIPQUAD(ic_nameservers[i]));
}
- if (ic_servaddr != INADDR_NONE)
+ if (ic_servaddr != NONE)
seq_printf(seq,
"bootserver %u.%u.%u.%u\n",
NIPQUAD(ic_servaddr));
@@ -1213,9 +1214,9 @@ static struct file_operations pnp_seq_fops = {
* need to have root_server_addr set _before_ IPConfig gets called as it
* can override it.
*/
-u32 __init root_nfs_parse_addr(char *name)
+__be32 __init root_nfs_parse_addr(char *name)
{
- u32 addr;
+ __be32 addr;
int octets = 0;
char *cp, *cq;
@@ -1237,7 +1238,7 @@ u32 __init root_nfs_parse_addr(char *name)
addr = in_aton(name);
memmove(name, cp, strlen(cp) + 1);
} else
- addr = INADDR_NONE;
+ addr = NONE;
return addr;
}
@@ -1248,7 +1249,7 @@ u32 __init root_nfs_parse_addr(char *name)
static int __init ip_auto_config(void)
{
- u32 addr;
+ __be32 addr;
#ifdef CONFIG_PROC_FS
proc_net_fops_create("pnp", S_IRUGO, &pnp_seq_fops);
@@ -1277,11 +1278,11 @@ static int __init ip_auto_config(void)
* interfaces and no default was set), use BOOTP or RARP to get the
* missing values.
*/
- if (ic_myaddr == INADDR_NONE ||
+ if (ic_myaddr == NONE ||
#ifdef CONFIG_ROOT_NFS
(MAJOR(ROOT_DEV) == UNNAMED_MAJOR
- && root_server_addr == INADDR_NONE
- && ic_servaddr == INADDR_NONE) ||
+ && root_server_addr == NONE
+ && ic_servaddr == NONE) ||
#endif
ic_first_dev->next) {
#ifdef IPCONFIG_DYNAMIC
@@ -1334,7 +1335,7 @@ static int __init ip_auto_config(void)
}
addr = root_nfs_parse_addr(root_server_path);
- if (root_server_addr == INADDR_NONE)
+ if (root_server_addr == NONE)
root_server_addr = addr;
/*
@@ -1461,19 +1462,19 @@ static int __init ip_auto_config_setup(char *addrs)
switch (num) {
case 0:
if ((ic_myaddr = in_aton(ip)) == INADDR_ANY)
- ic_myaddr = INADDR_NONE;
+ ic_myaddr = NONE;
break;
case 1:
if ((ic_servaddr = in_aton(ip)) == INADDR_ANY)
- ic_servaddr = INADDR_NONE;
+ ic_servaddr = NONE;
break;
case 2:
if ((ic_gateway = in_aton(ip)) == INADDR_ANY)
- ic_gateway = INADDR_NONE;
+ ic_gateway = NONE;
break;
case 3:
if ((ic_netmask = in_aton(ip)) == INADDR_ANY)
- ic_netmask = INADDR_NONE;
+ ic_netmask = NONE;
break;
case 4:
if ((dp = strchr(ip, '.'))) {
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 0c4556529228..9d719d664e5b 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -118,7 +118,7 @@
#include <net/xfrm.h>
#define HASH_SIZE 16
-#define HASH(addr) ((addr^(addr>>4))&0xF)
+#define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF)
static int ipip_fb_tunnel_init(struct net_device *dev);
static int ipip_tunnel_init(struct net_device *dev);
@@ -134,7 +134,7 @@ static struct ip_tunnel **tunnels[4] = { tunnels_wc, tunnels_l, tunnels_r, tunne
static DEFINE_RWLOCK(ipip_lock);
-static struct ip_tunnel * ipip_tunnel_lookup(u32 remote, u32 local)
+static struct ip_tunnel * ipip_tunnel_lookup(__be32 remote, __be32 local)
{
unsigned h0 = HASH(remote);
unsigned h1 = HASH(local);
@@ -160,8 +160,8 @@ static struct ip_tunnel * ipip_tunnel_lookup(u32 remote, u32 local)
static struct ip_tunnel **ipip_bucket(struct ip_tunnel *t)
{
- u32 remote = t->parms.iph.daddr;
- u32 local = t->parms.iph.saddr;
+ __be32 remote = t->parms.iph.daddr;
+ __be32 local = t->parms.iph.saddr;
unsigned h = 0;
int prio = 0;
@@ -203,8 +203,8 @@ static void ipip_tunnel_link(struct ip_tunnel *t)
static struct ip_tunnel * ipip_tunnel_locate(struct ip_tunnel_parm *parms, int create)
{
- u32 remote = parms->iph.daddr;
- u32 local = parms->iph.saddr;
+ __be32 remote = parms->iph.daddr;
+ __be32 local = parms->iph.saddr;
struct ip_tunnel *t, **tp, *nt;
struct net_device *dev;
unsigned h = 0;
@@ -519,13 +519,13 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
struct net_device_stats *stats = &tunnel->stat;
struct iphdr *tiph = &tunnel->parms.iph;
u8 tos = tunnel->parms.iph.tos;
- u16 df = tiph->frag_off;
+ __be16 df = tiph->frag_off;
struct rtable *rt; /* Route to the other host */
struct net_device *tdev; /* Device to other host */
struct iphdr *old_iph = skb->nh.iph;
struct iphdr *iph; /* Our new IP header */
int max_headroom; /* The extra header space needed */
- u32 dst = tiph->daddr;
+ __be32 dst = tiph->daddr;
int mtu;
if (tunnel->recursion++) {
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 97cfa97c8abb..efcf45ecc818 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -1493,7 +1493,7 @@ static int pim_rcv(struct sk_buff * skb)
if (pim->type != ((PIM_VERSION<<4)|(PIM_REGISTER)) ||
(pim->flags&PIM_NULL_REGISTER) ||
(ip_compute_csum((void *)pim, sizeof(*pim)) != 0 &&
- (u16)csum_fold(skb_checksum(skb, 0, skb->len, 0))))
+ csum_fold(skb_checksum(skb, 0, skb->len, 0))))
goto drop;
/* check if the inner packet is destined to mcast group */
diff --git a/net/ipv4/ipvs/ip_vs_app.c b/net/ipv4/ipvs/ip_vs_app.c
index e7752334d296..6c40899aa161 100644
--- a/net/ipv4/ipvs/ip_vs_app.c
+++ b/net/ipv4/ipvs/ip_vs_app.c
@@ -80,10 +80,9 @@ ip_vs_app_inc_new(struct ip_vs_app *app, __u16 proto, __u16 port)
if (!pp->unregister_app)
return -EOPNOTSUPP;
- inc = kmalloc(sizeof(struct ip_vs_app), GFP_KERNEL);
+ inc = kmemdup(app, sizeof(*inc), GFP_KERNEL);
if (!inc)
return -ENOMEM;
- memcpy(inc, app, sizeof(*inc));
INIT_LIST_HEAD(&inc->p_list);
INIT_LIST_HEAD(&inc->incs_list);
inc->app = app;
diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c
index 1445bb47fea4..34257520a3a6 100644
--- a/net/ipv4/ipvs/ip_vs_core.c
+++ b/net/ipv4/ipvs/ip_vs_core.c
@@ -536,9 +536,9 @@ static unsigned int ip_vs_post_routing(unsigned int hooknum,
return NF_STOP;
}
-u16 ip_vs_checksum_complete(struct sk_buff *skb, int offset)
+__sum16 ip_vs_checksum_complete(struct sk_buff *skb, int offset)
{
- return (u16) csum_fold(skb_checksum(skb, offset, skb->len - offset, 0));
+ return csum_fold(skb_checksum(skb, offset, skb->len - offset, 0));
}
static inline struct sk_buff *
diff --git a/net/ipv4/ipvs/ip_vs_proto.c b/net/ipv4/ipvs/ip_vs_proto.c
index c4528b5c800d..e844ddb82b9a 100644
--- a/net/ipv4/ipvs/ip_vs_proto.c
+++ b/net/ipv4/ipvs/ip_vs_proto.c
@@ -118,13 +118,7 @@ void ip_vs_protocol_timeout_change(int flags)
int *
ip_vs_create_timeout_table(int *table, int size)
{
- int *t;
-
- t = kmalloc(size, GFP_ATOMIC);
- if (t == NULL)
- return NULL;
- memcpy(t, table, size);
- return t;
+ return kmemdup(table, size, GFP_ATOMIC);
}
diff --git a/net/ipv4/ipvs/ip_vs_proto_tcp.c b/net/ipv4/ipvs/ip_vs_proto_tcp.c
index 6ff05c3a32e6..16a9ebee2fe6 100644
--- a/net/ipv4/ipvs/ip_vs_proto_tcp.c
+++ b/net/ipv4/ipvs/ip_vs_proto_tcp.c
@@ -84,7 +84,7 @@ tcp_conn_schedule(struct sk_buff *skb,
}
if (th->syn &&
- (svc = ip_vs_service_get(skb->nfmark, skb->nh.iph->protocol,
+ (svc = ip_vs_service_get(skb->mark, skb->nh.iph->protocol,
skb->nh.iph->daddr, th->dest))) {
if (ip_vs_todrop()) {
/*
@@ -116,9 +116,9 @@ tcp_fast_csum_update(struct tcphdr *tcph, __be32 oldip, __be32 newip,
__be16 oldport, __be16 newport)
{
tcph->check =
- ip_vs_check_diff(~oldip, newip,
- ip_vs_check_diff(oldport ^ htons(0xFFFF),
- newport, tcph->check));
+ csum_fold(ip_vs_check_diff4(oldip, newip,
+ ip_vs_check_diff2(oldport, newport,
+ ~csum_unfold(tcph->check))));
}
@@ -490,16 +490,18 @@ tcp_state_transition(struct ip_vs_conn *cp, int direction,
static struct list_head tcp_apps[TCP_APP_TAB_SIZE];
static DEFINE_SPINLOCK(tcp_app_lock);
-static inline __u16 tcp_app_hashkey(__u16 port)
+static inline __u16 tcp_app_hashkey(__be16 port)
{
- return ((port >> TCP_APP_TAB_BITS) ^ port) & TCP_APP_TAB_MASK;
+ return (((__force u16)port >> TCP_APP_TAB_BITS) ^ (__force u16)port)
+ & TCP_APP_TAB_MASK;
}
static int tcp_register_app(struct ip_vs_app *inc)
{
struct ip_vs_app *i;
- __u16 hash, port = inc->port;
+ __u16 hash;
+ __be16 port = inc->port;
int ret = 0;
hash = tcp_app_hashkey(port);
diff --git a/net/ipv4/ipvs/ip_vs_proto_udp.c b/net/ipv4/ipvs/ip_vs_proto_udp.c
index 691c8b637b29..03f0a414cfa4 100644
--- a/net/ipv4/ipvs/ip_vs_proto_udp.c
+++ b/net/ipv4/ipvs/ip_vs_proto_udp.c
@@ -89,7 +89,7 @@ udp_conn_schedule(struct sk_buff *skb, struct ip_vs_protocol *pp,
return 0;
}
- if ((svc = ip_vs_service_get(skb->nfmark, skb->nh.iph->protocol,
+ if ((svc = ip_vs_service_get(skb->mark, skb->nh.iph->protocol,
skb->nh.iph->daddr, uh->dest))) {
if (ip_vs_todrop()) {
/*
@@ -121,11 +121,11 @@ udp_fast_csum_update(struct udphdr *uhdr, __be32 oldip, __be32 newip,
__be16 oldport, __be16 newport)
{
uhdr->check =
- ip_vs_check_diff(~oldip, newip,
- ip_vs_check_diff(oldport ^ htons(0xFFFF),
- newport, uhdr->check));
+ csum_fold(ip_vs_check_diff4(oldip, newip,
+ ip_vs_check_diff2(oldport, newport,
+ ~csum_unfold(uhdr->check))));
if (!uhdr->check)
- uhdr->check = -1;
+ uhdr->check = CSUM_MANGLED_0;
}
static int
@@ -173,7 +173,7 @@ udp_snat_handler(struct sk_buff **pskb,
cp->protocol,
(*pskb)->csum);
if (udph->check == 0)
- udph->check = -1;
+ udph->check = CSUM_MANGLED_0;
IP_VS_DBG(11, "O-pkt: %s O-csum=%d (+%zd)\n",
pp->name, udph->check,
(char*)&(udph->check) - (char*)udph);
@@ -228,7 +228,7 @@ udp_dnat_handler(struct sk_buff **pskb,
cp->protocol,
(*pskb)->csum);
if (udph->check == 0)
- udph->check = -1;
+ udph->check = CSUM_MANGLED_0;
(*pskb)->ip_summed = CHECKSUM_UNNECESSARY;
}
return 1;
@@ -282,16 +282,18 @@ udp_csum_check(struct sk_buff *skb, struct ip_vs_protocol *pp)
static struct list_head udp_apps[UDP_APP_TAB_SIZE];
static DEFINE_SPINLOCK(udp_app_lock);
-static inline __u16 udp_app_hashkey(__u16 port)
+static inline __u16 udp_app_hashkey(__be16 port)
{
- return ((port >> UDP_APP_TAB_BITS) ^ port) & UDP_APP_TAB_MASK;
+ return (((__force u16)port >> UDP_APP_TAB_BITS) ^ (__force u16)port)
+ & UDP_APP_TAB_MASK;
}
static int udp_register_app(struct ip_vs_app *inc)
{
struct ip_vs_app *i;
- __u16 hash, port = inc->port;
+ __u16 hash;
+ __be16 port = inc->port;
int ret = 0;
hash = udp_app_hashkey(port);
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index e2005c6810a4..a68966059b50 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -27,9 +27,7 @@ int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type)
fl.nl_u.ip4_u.saddr = iph->saddr;
fl.nl_u.ip4_u.tos = RT_TOS(iph->tos);
fl.oif = (*pskb)->sk ? (*pskb)->sk->sk_bound_dev_if : 0;
-#ifdef CONFIG_IP_ROUTE_FWMARK
- fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark;
-#endif
+ fl.mark = (*pskb)->mark;
if (ip_route_output_key(&rt, &fl) != 0)
return -1;
@@ -164,17 +162,17 @@ static int nf_ip_reroute(struct sk_buff **pskb, const struct nf_info *info)
return 0;
}
-unsigned int nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
+__sum16 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;
+ __sum16 csum = 0;
switch (skb->ip_summed) {
case CHECKSUM_COMPLETE:
if (hook != NF_IP_PRE_ROUTING && hook != NF_IP_LOCAL_IN)
break;
- if ((protocol == 0 && !(u16)csum_fold(skb->csum)) ||
+ if ((protocol == 0 && !csum_fold(skb->csum)) ||
!csum_tcpudp_magic(iph->saddr, iph->daddr,
skb->len - dataoff, protocol,
skb->csum)) {
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index d88c292f118c..363df9976c9d 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -6,7 +6,7 @@ menu "IP: Netfilter Configuration"
depends on INET && NETFILTER
config NF_CONNTRACK_IPV4
- tristate "IPv4 support for new connection tracking (EXPERIMENTAL)"
+ tristate "IPv4 connection tracking support (required for NAT) (EXPERIMENTAL)"
depends on EXPERIMENTAL && NF_CONNTRACK
---help---
Connection tracking keeps a record of what packets have passed
@@ -19,21 +19,18 @@ config NF_CONNTRACK_IPV4
To compile it as a module, choose M here. If unsure, say N.
-# connection tracking, helpers and protocols
-config IP_NF_CONNTRACK
- tristate "Connection tracking (required for masq/NAT)"
- ---help---
- Connection tracking keeps a record of what packets have passed
- through your machine, in order to figure out how they are related
- into connections.
-
- This is required to do Masquerading or other kinds of Network
- Address Translation (except for Fast NAT). It can also be used to
- enhance packet filtering (see `Connection state match support'
- below).
+config NF_CONNTRACK_PROC_COMPAT
+ bool "proc/sysctl compatibility with old connection tracking"
+ depends on NF_CONNTRACK_IPV4
+ default y
+ help
+ This option enables /proc and sysctl compatibility with the old
+ layer 3 dependant connection tracking. This is needed to keep
+ old programs that have not been adapted to the new names working.
- To compile it as a module, choose M here. If unsure, say N.
+ If unsure, say Y.
+# connection tracking, helpers and protocols
config IP_NF_CT_ACCT
bool "Connection tracking flow accounting"
depends on IP_NF_CONNTRACK
@@ -315,20 +312,6 @@ config IP_NF_MATCH_ADDRTYPE
If you want to compile it as a module, say M here and read
<file:Documentation/modules.txt>. If unsure, say `N'.
-config IP_NF_MATCH_HASHLIMIT
- tristate 'hashlimit match support'
- depends on IP_NF_IPTABLES
- help
- This option adds a new iptables `hashlimit' match.
-
- As opposed to `limit', this match dynamically creates a hash table
- of limit buckets, based on your selection of source/destination
- ip addresses and/or ports.
-
- It enables you to express policies like `10kpps for any given
- destination IP' or `500pps from any given source IP' with a single
- IPtables rule.
-
# `filter', generic and specific targets
config IP_NF_FILTER
tristate "Packet filtering"
@@ -404,7 +387,7 @@ config IP_NF_TARGET_TCPMSS
To compile it as a module, choose M here. If unsure, say N.
-# NAT + specific targets
+# NAT + specific targets: ip_conntrack
config IP_NF_NAT
tristate "Full NAT"
depends on IP_NF_IPTABLES && IP_NF_CONNTRACK
@@ -415,14 +398,30 @@ config IP_NF_NAT
To compile it as a module, choose M here. If unsure, say N.
+# NAT + specific targets: nf_conntrack
+config NF_NAT
+ tristate "Full NAT"
+ depends on IP_NF_IPTABLES && NF_CONNTRACK
+ help
+ The Full NAT option allows masquerading, port forwarding and other
+ forms of full Network Address Port Translation. It is controlled by
+ the `nat' table in iptables: see the man page for iptables(8).
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config IP_NF_NAT_NEEDED
bool
- depends on IP_NF_NAT != n
+ depends on IP_NF_NAT
+ default y
+
+config NF_NAT_NEEDED
+ bool
+ depends on NF_NAT
default y
config IP_NF_TARGET_MASQUERADE
tristate "MASQUERADE target support"
- depends on IP_NF_NAT
+ depends on (NF_NAT || IP_NF_NAT)
help
Masquerading is a special case of NAT: all outgoing connections are
changed to seem to come from a particular interface's address, and
@@ -434,7 +433,7 @@ config IP_NF_TARGET_MASQUERADE
config IP_NF_TARGET_REDIRECT
tristate "REDIRECT target support"
- depends on IP_NF_NAT
+ depends on (NF_NAT || IP_NF_NAT)
help
REDIRECT is a special case of NAT: all incoming connections are
mapped onto the incoming interface's address, causing the packets to
@@ -445,7 +444,7 @@ config IP_NF_TARGET_REDIRECT
config IP_NF_TARGET_NETMAP
tristate "NETMAP target support"
- depends on IP_NF_NAT
+ depends on (NF_NAT || IP_NF_NAT)
help
NETMAP is an implementation of static 1:1 NAT mapping of network
addresses. It maps the network address part, while keeping the host
@@ -456,7 +455,7 @@ config IP_NF_TARGET_NETMAP
config IP_NF_TARGET_SAME
tristate "SAME target support"
- depends on IP_NF_NAT
+ depends on (NF_NAT || IP_NF_NAT)
help
This option adds a `SAME' target, which works like the standard SNAT
target, but attempts to give clients the same IP for all connections.
@@ -478,19 +477,52 @@ config IP_NF_NAT_SNMP_BASIC
To compile it as a module, choose M here. If unsure, say N.
+config NF_NAT_SNMP_BASIC
+ tristate "Basic SNMP-ALG support (EXPERIMENTAL)"
+ depends on EXPERIMENTAL && NF_NAT
+ ---help---
+
+ This module implements an Application Layer Gateway (ALG) for
+ SNMP payloads. In conjunction with NAT, it allows a network
+ management system to access multiple private networks with
+ conflicting addresses. It works by modifying IP addresses
+ inside SNMP payloads to match IP-layer NAT mapping.
+
+ This is the "basic" form of SNMP-ALG, as described in RFC 2962
+
+ To compile it as a module, choose M here. If unsure, say N.
+
+# If they want FTP, set to $CONFIG_IP_NF_NAT (m or y),
+# or $CONFIG_IP_NF_FTP (m or y), whichever is weaker.
+# From kconfig-language.txt:
+#
+# <expr> '&&' <expr> (6)
+#
+# (6) Returns the result of min(/expr/, /expr/).
+config NF_NAT_PROTO_GRE
+ tristate
+ depends on NF_NAT && NF_CT_PROTO_GRE
+
+config IP_NF_NAT_FTP
+ tristate
+ depends on IP_NF_IPTABLES && IP_NF_CONNTRACK && IP_NF_NAT
+ default IP_NF_NAT && IP_NF_FTP
+
+config NF_NAT_FTP
+ tristate
+ depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT
+ default NF_NAT && NF_CONNTRACK_FTP
+
config IP_NF_NAT_IRC
tristate
depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
default IP_NF_NAT if IP_NF_IRC=y
default m if IP_NF_IRC=m
-# If they want FTP, set to $CONFIG_IP_NF_NAT (m or y),
-# or $CONFIG_IP_NF_FTP (m or y), whichever is weaker. Argh.
-config IP_NF_NAT_FTP
+config NF_NAT_IRC
tristate
- depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
- default IP_NF_NAT if IP_NF_FTP=y
- default m if IP_NF_FTP=m
+ depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT
+ default NF_NAT && NF_CONNTRACK_IRC
config IP_NF_NAT_TFTP
tristate
@@ -498,30 +530,56 @@ config IP_NF_NAT_TFTP
default IP_NF_NAT if IP_NF_TFTP=y
default m if IP_NF_TFTP=m
+config NF_NAT_TFTP
+ tristate
+ depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT
+ default NF_NAT && NF_CONNTRACK_TFTP
+
config IP_NF_NAT_AMANDA
tristate
depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
default IP_NF_NAT if IP_NF_AMANDA=y
default m if IP_NF_AMANDA=m
+config NF_NAT_AMANDA
+ tristate
+ depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT
+ default NF_NAT && NF_CONNTRACK_AMANDA
+
config IP_NF_NAT_PPTP
tristate
depends on IP_NF_NAT!=n && IP_NF_PPTP!=n
default IP_NF_NAT if IP_NF_PPTP=y
default m if IP_NF_PPTP=m
+config NF_NAT_PPTP
+ tristate
+ depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT
+ default NF_NAT && NF_CONNTRACK_PPTP
+ select NF_NAT_PROTO_GRE
+
config IP_NF_NAT_H323
tristate
depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
default IP_NF_NAT if IP_NF_H323=y
default m if IP_NF_H323=m
+config NF_NAT_H323
+ tristate
+ depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT
+ default NF_NAT && NF_CONNTRACK_H323
+
config IP_NF_NAT_SIP
tristate
depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
default IP_NF_NAT if IP_NF_SIP=y
default m if IP_NF_SIP=m
+config NF_NAT_SIP
+ tristate
+ depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT
+ default NF_NAT && NF_CONNTRACK_SIP
+
# mangle + specific targets
config IP_NF_MANGLE
tristate "Packet mangling"
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 09aaed1a8063..15e741aeb291 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -5,17 +5,23 @@
# objects for the standalone - connection tracking / NAT
ip_conntrack-objs := ip_conntrack_standalone.o ip_conntrack_core.o ip_conntrack_proto_generic.o ip_conntrack_proto_tcp.o ip_conntrack_proto_udp.o ip_conntrack_proto_icmp.o
ip_nat-objs := ip_nat_core.o ip_nat_helper.o ip_nat_proto_unknown.o ip_nat_proto_tcp.o ip_nat_proto_udp.o ip_nat_proto_icmp.o
+nf_nat-objs := nf_nat_core.o nf_nat_helper.o nf_nat_proto_unknown.o nf_nat_proto_tcp.o nf_nat_proto_udp.o nf_nat_proto_icmp.o
+ifneq ($(CONFIG_NF_NAT),)
+iptable_nat-objs := nf_nat_rule.o nf_nat_standalone.o
+else
iptable_nat-objs := ip_nat_rule.o ip_nat_standalone.o
+endif
ip_conntrack_pptp-objs := ip_conntrack_helper_pptp.o ip_conntrack_proto_gre.o
ip_nat_pptp-objs := ip_nat_helper_pptp.o ip_nat_proto_gre.o
-ip_conntrack_h323-objs := ip_conntrack_helper_h323.o ip_conntrack_helper_h323_asn1.o
+ip_conntrack_h323-objs := ip_conntrack_helper_h323.o ../../netfilter/nf_conntrack_h323_asn1.o
ip_nat_h323-objs := ip_nat_helper_h323.o
# connection tracking
obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
obj-$(CONFIG_IP_NF_NAT) += ip_nat.o
+obj-$(CONFIG_NF_NAT) += nf_nat.o
# conntrack netlink interface
obj-$(CONFIG_IP_NF_CONNTRACK_NETLINK) += ip_conntrack_netlink.o
@@ -34,7 +40,7 @@ obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
obj-$(CONFIG_IP_NF_SIP) += ip_conntrack_sip.o
obj-$(CONFIG_IP_NF_NETBIOS_NS) += ip_conntrack_netbios_ns.o
-# NAT helpers
+# NAT helpers (ip_conntrack)
obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o
obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o
@@ -43,6 +49,19 @@ obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
obj-$(CONFIG_IP_NF_NAT_SIP) += ip_nat_sip.o
+# NAT helpers (nf_conntrack)
+obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_amanda.o
+obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o
+obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o
+obj-$(CONFIG_NF_NAT_IRC) += nf_nat_irc.o
+obj-$(CONFIG_NF_NAT_PPTP) += nf_nat_pptp.o
+obj-$(CONFIG_NF_NAT_SIP) += nf_nat_sip.o
+obj-$(CONFIG_NF_NAT_SNMP_BASIC) += nf_nat_snmp_basic.o
+obj-$(CONFIG_NF_NAT_TFTP) += nf_nat_tftp.o
+
+# NAT protocols (nf_nat)
+obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o
+
# generic IP tables
obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
@@ -50,10 +69,10 @@ obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
obj-$(CONFIG_IP_NF_FILTER) += iptable_filter.o
obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o
obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o
+obj-$(CONFIG_NF_NAT) += iptable_nat.o
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_OWNER) += ipt_owner.o
obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
@@ -89,6 +108,11 @@ obj-$(CONFIG_IP_NF_QUEUE) += ip_queue.o
# objects for l3 independent conntrack
nf_conntrack_ipv4-objs := nf_conntrack_l3proto_ipv4.o nf_conntrack_proto_icmp.o
+ifeq ($(CONFIG_NF_CONNTRACK_PROC_COMPAT),y)
+ifeq ($(CONFIG_PROC_FS),y)
+nf_conntrack_ipv4-objs += nf_conntrack_l3proto_ipv4_compat.o
+endif
+endif
# l3 independent conntrack
obj-$(CONFIG_NF_CONNTRACK_IPV4) += nf_conntrack_ipv4.o
diff --git a/net/ipv4/netfilter/ip_conntrack_amanda.c b/net/ipv4/netfilter/ip_conntrack_amanda.c
index 6c7383a8e42b..ad246ba7790b 100644
--- a/net/ipv4/netfilter/ip_conntrack_amanda.c
+++ b/net/ipv4/netfilter/ip_conntrack_amanda.c
@@ -92,6 +92,7 @@ static int help(struct sk_buff **pskb,
char pbuf[sizeof("65535")], *tmp;
u_int16_t port, len;
int ret = NF_ACCEPT;
+ typeof(ip_nat_amanda_hook) ip_nat_amanda;
/* Only look at packets from the Amanda server */
if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL)
@@ -161,9 +162,11 @@ static int help(struct sk_buff **pskb,
exp->mask.dst.protonum = 0xFF;
exp->mask.dst.u.tcp.port = htons(0xFFFF);
- if (ip_nat_amanda_hook)
- ret = ip_nat_amanda_hook(pskb, ctinfo, off - dataoff,
- len, exp);
+ /* RCU read locked by nf_hook_slow */
+ ip_nat_amanda = rcu_dereference(ip_nat_amanda_hook);
+ if (ip_nat_amanda)
+ ret = ip_nat_amanda(pskb, ctinfo, off - dataoff,
+ len, exp);
else if (ip_conntrack_expect_related(exp) != 0)
ret = NF_DROP;
ip_conntrack_expect_put(exp);
@@ -180,7 +183,7 @@ static struct ip_conntrack_helper amanda_helper = {
.help = help,
.name = "amanda",
- .tuple = { .src = { .u = { __constant_htons(10080) } },
+ .tuple = { .src = { .u = { .udp = {.port = __constant_htons(10080) } } },
.dst = { .protonum = IPPROTO_UDP },
},
.mask = { .src = { .u = { 0xFFFF } },
diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
index 143c4668538b..f4b0e68a16d2 100644
--- a/net/ipv4/netfilter/ip_conntrack_core.c
+++ b/net/ipv4/netfilter/ip_conntrack_core.c
@@ -40,9 +40,6 @@
/* ip_conntrack_lock protects the main hash table, protocol/helper/expected
registrations, conntrack timers*/
-#define ASSERT_READ_LOCK(x)
-#define ASSERT_WRITE_LOCK(x)
-
#include <linux/netfilter_ipv4/ip_conntrack.h>
#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
@@ -201,7 +198,6 @@ ip_ct_invert_tuple(struct ip_conntrack_tuple *inverse,
/* ip_conntrack_expect helper functions */
void ip_ct_unlink_expect(struct ip_conntrack_expect *exp)
{
- ASSERT_WRITE_LOCK(&ip_conntrack_lock);
IP_NF_ASSERT(!timer_pending(&exp->timeout));
list_del(&exp->list);
CONNTRACK_STAT_INC(expect_delete);
@@ -225,22 +221,22 @@ __ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple)
struct ip_conntrack_expect *i;
list_for_each_entry(i, &ip_conntrack_expect_list, list) {
- if (ip_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) {
- atomic_inc(&i->use);
+ if (ip_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask))
return i;
- }
}
return NULL;
}
/* Just find a expectation corresponding to a tuple. */
struct ip_conntrack_expect *
-ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple)
+ip_conntrack_expect_find_get(const struct ip_conntrack_tuple *tuple)
{
struct ip_conntrack_expect *i;
read_lock_bh(&ip_conntrack_lock);
i = __ip_conntrack_expect_find(tuple);
+ if (i)
+ atomic_inc(&i->use);
read_unlock_bh(&ip_conntrack_lock);
return i;
@@ -294,7 +290,6 @@ static void
clean_from_lists(struct ip_conntrack *ct)
{
DEBUGP("clean_from_lists(%p)\n", ct);
- ASSERT_WRITE_LOCK(&ip_conntrack_lock);
list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
list_del(&ct->tuplehash[IP_CT_DIR_REPLY].list);
@@ -373,7 +368,6 @@ __ip_conntrack_find(const struct ip_conntrack_tuple *tuple,
struct ip_conntrack_tuple_hash *h;
unsigned int hash = hash_conntrack(tuple);
- ASSERT_READ_LOCK(&ip_conntrack_lock);
list_for_each_entry(h, &ip_conntrack_hash[hash], list) {
if (tuplehash_to_ctrack(h) != ignored_conntrack &&
ip_ct_tuple_equal(tuple, &h->tuple)) {
diff --git a/net/ipv4/netfilter/ip_conntrack_ftp.c b/net/ipv4/netfilter/ip_conntrack_ftp.c
index 93dcf960662f..0410c99cacae 100644
--- a/net/ipv4/netfilter/ip_conntrack_ftp.c
+++ b/net/ipv4/netfilter/ip_conntrack_ftp.c
@@ -310,6 +310,7 @@ static int help(struct sk_buff **pskb,
struct ip_conntrack_expect *exp;
unsigned int i;
int found = 0, ends_in_nl;
+ typeof(ip_nat_ftp_hook) ip_nat_ftp;
/* Until there's been traffic both ways, don't look in packets. */
if (ctinfo != IP_CT_ESTABLISHED
@@ -433,9 +434,10 @@ static int help(struct sk_buff **pskb,
/* Now, NAT might want to mangle the packet, and register the
* (possibly changed) expectation itself. */
- if (ip_nat_ftp_hook)
- ret = ip_nat_ftp_hook(pskb, ctinfo, search[dir][i].ftptype,
- matchoff, matchlen, exp, &seq);
+ ip_nat_ftp = rcu_dereference(ip_nat_ftp_hook);
+ if (ip_nat_ftp)
+ ret = ip_nat_ftp(pskb, ctinfo, search[dir][i].ftptype,
+ matchoff, matchlen, exp, &seq);
else {
/* Can't expect this? Best to drop packet now. */
if (ip_conntrack_expect_related(exp) != 0)
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323.c b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
index 7b7441202bfd..aabfe1c06905 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323.c
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
@@ -237,6 +237,7 @@ static int expect_rtp_rtcp(struct sk_buff **pskb, struct ip_conntrack *ct,
u_int16_t rtp_port;
struct ip_conntrack_expect *rtp_exp;
struct ip_conntrack_expect *rtcp_exp;
+ typeof(nat_rtp_rtcp_hook) nat_rtp_rtcp;
/* Read RTP or RTCP address */
if (!get_h245_addr(*data, addr, &ip, &port) ||
@@ -279,11 +280,11 @@ static int expect_rtp_rtcp(struct sk_buff **pskb, struct ip_conntrack *ct,
rtcp_exp->flags = 0;
if (ct->tuplehash[dir].tuple.src.ip !=
- ct->tuplehash[!dir].tuple.dst.ip && nat_rtp_rtcp_hook) {
+ ct->tuplehash[!dir].tuple.dst.ip &&
+ (nat_rtp_rtcp = rcu_dereference(nat_rtp_rtcp_hook))) {
/* NAT needed */
- ret = nat_rtp_rtcp_hook(pskb, ct, ctinfo, data, dataoff,
- addr, port, rtp_port, rtp_exp,
- rtcp_exp);
+ ret = nat_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
+ addr, port, rtp_port, rtp_exp, rtcp_exp);
} else { /* Conntrack only */
rtp_exp->expectfn = NULL;
rtcp_exp->expectfn = NULL;
@@ -328,6 +329,7 @@ static int expect_t120(struct sk_buff **pskb,
__be32 ip;
u_int16_t port;
struct ip_conntrack_expect *exp = NULL;
+ typeof(nat_t120_hook) nat_t120;
/* Read T.120 address */
if (!get_h245_addr(*data, addr, &ip, &port) ||
@@ -350,10 +352,11 @@ static int expect_t120(struct sk_buff **pskb,
exp->flags = IP_CT_EXPECT_PERMANENT; /* Accept multiple channels */
if (ct->tuplehash[dir].tuple.src.ip !=
- ct->tuplehash[!dir].tuple.dst.ip && nat_t120_hook) {
+ ct->tuplehash[!dir].tuple.dst.ip &&
+ (nat_t120 = rcu_dereference(nat_t120_hook))) {
/* NAT needed */
- ret = nat_t120_hook(pskb, ct, ctinfo, data, dataoff, addr,
- port, exp);
+ ret = nat_t120(pskb, ct, ctinfo, data, dataoff, addr,
+ port, exp);
} else { /* Conntrack only */
exp->expectfn = NULL;
if (ip_conntrack_expect_related(exp) == 0) {
@@ -651,6 +654,7 @@ static int expect_h245(struct sk_buff **pskb, struct ip_conntrack *ct,
__be32 ip;
u_int16_t port;
struct ip_conntrack_expect *exp = NULL;
+ typeof(nat_h245_hook) nat_h245;
/* Read h245Address */
if (!get_h225_addr(*data, addr, &ip, &port) ||
@@ -673,10 +677,11 @@ static int expect_h245(struct sk_buff **pskb, struct ip_conntrack *ct,
exp->flags = 0;
if (ct->tuplehash[dir].tuple.src.ip !=
- ct->tuplehash[!dir].tuple.dst.ip && nat_h245_hook) {
+ ct->tuplehash[!dir].tuple.dst.ip &&
+ (nat_h245 = rcu_dereference(nat_h245_hook))) {
/* NAT needed */
- ret = nat_h245_hook(pskb, ct, ctinfo, data, dataoff, addr,
- port, exp);
+ ret = nat_h245(pskb, ct, ctinfo, data, dataoff, addr,
+ port, exp);
} else { /* Conntrack only */
exp->expectfn = ip_conntrack_h245_expect;
@@ -712,6 +717,7 @@ static int expect_callforwarding(struct sk_buff **pskb,
__be32 ip;
u_int16_t port;
struct ip_conntrack_expect *exp = NULL;
+ typeof(nat_callforwarding_hook) nat_callforwarding;
/* Read alternativeAddress */
if (!get_h225_addr(*data, addr, &ip, &port) || port == 0)
@@ -759,10 +765,11 @@ static int expect_callforwarding(struct sk_buff **pskb,
exp->flags = 0;
if (ct->tuplehash[dir].tuple.src.ip !=
- ct->tuplehash[!dir].tuple.dst.ip && nat_callforwarding_hook) {
+ ct->tuplehash[!dir].tuple.dst.ip &&
+ (nat_callforwarding = rcu_dereference(nat_callforwarding_hook))) {
/* Need NAT */
- ret = nat_callforwarding_hook(pskb, ct, ctinfo, data, dataoff,
- addr, port, exp);
+ ret = nat_callforwarding(pskb, ct, ctinfo, data, dataoff,
+ addr, port, exp);
} else { /* Conntrack only */
exp->expectfn = ip_conntrack_q931_expect;
@@ -793,6 +800,7 @@ static int process_setup(struct sk_buff **pskb, struct ip_conntrack *ct,
int i;
__be32 ip;
u_int16_t port;
+ typeof(set_h225_addr_hook) set_h225_addr;
DEBUGP("ip_ct_q931: Setup\n");
@@ -803,8 +811,10 @@ static int process_setup(struct sk_buff **pskb, struct ip_conntrack *ct,
return -1;
}
+ set_h225_addr = rcu_dereference(set_h225_addr_hook);
+
if ((setup->options & eSetup_UUIE_destCallSignalAddress) &&
- (set_h225_addr_hook) &&
+ (set_h225_addr) &&
get_h225_addr(*data, &setup->destCallSignalAddress, &ip, &port) &&
ip != ct->tuplehash[!dir].tuple.src.ip) {
DEBUGP("ip_ct_q931: set destCallSignalAddress "
@@ -812,17 +822,17 @@ static int process_setup(struct sk_buff **pskb, struct ip_conntrack *ct,
NIPQUAD(ip), port,
NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port));
- ret = set_h225_addr_hook(pskb, data, dataoff,
- &setup->destCallSignalAddress,
- ct->tuplehash[!dir].tuple.src.ip,
- ntohs(ct->tuplehash[!dir].tuple.src.
- u.tcp.port));
+ ret = set_h225_addr(pskb, data, dataoff,
+ &setup->destCallSignalAddress,
+ ct->tuplehash[!dir].tuple.src.ip,
+ ntohs(ct->tuplehash[!dir].tuple.src.
+ u.tcp.port));
if (ret < 0)
return -1;
}
if ((setup->options & eSetup_UUIE_sourceCallSignalAddress) &&
- (set_h225_addr_hook) &&
+ (set_h225_addr) &&
get_h225_addr(*data, &setup->sourceCallSignalAddress, &ip, &port)
&& ip != ct->tuplehash[!dir].tuple.dst.ip) {
DEBUGP("ip_ct_q931: set sourceCallSignalAddress "
@@ -830,11 +840,11 @@ static int process_setup(struct sk_buff **pskb, struct ip_conntrack *ct,
NIPQUAD(ip), port,
NIPQUAD(ct->tuplehash[!dir].tuple.dst.ip),
ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port));
- ret = set_h225_addr_hook(pskb, data, dataoff,
- &setup->sourceCallSignalAddress,
- ct->tuplehash[!dir].tuple.dst.ip,
- ntohs(ct->tuplehash[!dir].tuple.dst.
- u.tcp.port));
+ ret = set_h225_addr(pskb, data, dataoff,
+ &setup->sourceCallSignalAddress,
+ ct->tuplehash[!dir].tuple.dst.ip,
+ ntohs(ct->tuplehash[!dir].tuple.dst.
+ u.tcp.port));
if (ret < 0)
return -1;
}
@@ -1153,7 +1163,7 @@ static struct ip_conntrack_helper ip_conntrack_helper_q931 = {
.me = THIS_MODULE,
.max_expected = H323_RTP_CHANNEL_MAX * 4 + 4 /* T.120 and H.245 */ ,
.timeout = 240,
- .tuple = {.src = {.u = {__constant_htons(Q931_PORT)}},
+ .tuple = {.src = {.u = {.tcp = {.port = __constant_htons(Q931_PORT)}}},
.dst = {.protonum = IPPROTO_TCP}},
.mask = {.src = {.u = {0xFFFF}},
.dst = {.protonum = 0xFF}},
@@ -1231,6 +1241,7 @@ static int expect_q931(struct sk_buff **pskb, struct ip_conntrack *ct,
__be32 ip;
u_int16_t port;
struct ip_conntrack_expect *exp;
+ typeof(nat_q931_hook) nat_q931;
/* Look for the first related address */
for (i = 0; i < count; i++) {
@@ -1258,9 +1269,9 @@ static int expect_q931(struct sk_buff **pskb, struct ip_conntrack *ct,
exp->mask.dst.protonum = 0xFF;
exp->flags = IP_CT_EXPECT_PERMANENT; /* Accept multiple calls */
- if (nat_q931_hook) { /* Need NAT */
- ret = nat_q931_hook(pskb, ct, ctinfo, data, addr, i,
- port, exp);
+ nat_q931 = rcu_dereference(nat_q931_hook);
+ if (nat_q931) { /* Need NAT */
+ ret = nat_q931(pskb, ct, ctinfo, data, addr, i, port, exp);
} else { /* Conntrack only */
exp->expectfn = ip_conntrack_q931_expect;
@@ -1288,11 +1299,14 @@ static int process_grq(struct sk_buff **pskb, struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, GatekeeperRequest * grq)
{
+ typeof(set_ras_addr_hook) set_ras_addr;
+
DEBUGP("ip_ct_ras: GRQ\n");
- if (set_ras_addr_hook) /* NATed */
- return set_ras_addr_hook(pskb, ct, ctinfo, data,
- &grq->rasAddress, 1);
+ set_ras_addr = rcu_dereference(set_ras_addr_hook);
+ if (set_ras_addr) /* NATed */
+ return set_ras_addr(pskb, ct, ctinfo, data,
+ &grq->rasAddress, 1);
return 0;
}
@@ -1362,6 +1376,7 @@ static int process_rrq(struct sk_buff **pskb, struct ip_conntrack *ct,
{
struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
int ret;
+ typeof(set_ras_addr_hook) set_ras_addr;
DEBUGP("ip_ct_ras: RRQ\n");
@@ -1371,10 +1386,11 @@ static int process_rrq(struct sk_buff **pskb, struct ip_conntrack *ct,
if (ret < 0)
return -1;
- if (set_ras_addr_hook) {
- ret = set_ras_addr_hook(pskb, ct, ctinfo, data,
- rrq->rasAddress.item,
- rrq->rasAddress.count);
+ set_ras_addr = rcu_dereference(set_ras_addr_hook);
+ if (set_ras_addr) {
+ ret = set_ras_addr(pskb, ct, ctinfo, data,
+ rrq->rasAddress.item,
+ rrq->rasAddress.count);
if (ret < 0)
return -1;
}
@@ -1397,13 +1413,15 @@ static int process_rcf(struct sk_buff **pskb, struct ip_conntrack *ct,
int dir = CTINFO2DIR(ctinfo);
int ret;
struct ip_conntrack_expect *exp;
+ typeof(set_sig_addr_hook) set_sig_addr;
DEBUGP("ip_ct_ras: RCF\n");
- if (set_sig_addr_hook) {
- ret = set_sig_addr_hook(pskb, ct, ctinfo, data,
- rcf->callSignalAddress.item,
- rcf->callSignalAddress.count);
+ set_sig_addr = rcu_dereference(set_sig_addr_hook);
+ if (set_sig_addr) {
+ ret = set_sig_addr(pskb, ct, ctinfo, data,
+ rcf->callSignalAddress.item,
+ rcf->callSignalAddress.count);
if (ret < 0)
return -1;
}
@@ -1417,7 +1435,7 @@ static int process_rcf(struct sk_buff **pskb, struct ip_conntrack *ct,
DEBUGP
("ip_ct_ras: set RAS connection timeout to %u seconds\n",
info->timeout);
- ip_ct_refresh_acct(ct, ctinfo, NULL, info->timeout * HZ);
+ ip_ct_refresh(ct, *pskb, info->timeout * HZ);
/* Set expect timeout */
read_lock_bh(&ip_conntrack_lock);
@@ -1448,13 +1466,15 @@ static int process_urq(struct sk_buff **pskb, struct ip_conntrack *ct,
struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
int dir = CTINFO2DIR(ctinfo);
int ret;
+ typeof(set_sig_addr_hook) set_sig_addr;
DEBUGP("ip_ct_ras: URQ\n");
- if (set_sig_addr_hook) {
- ret = set_sig_addr_hook(pskb, ct, ctinfo, data,
- urq->callSignalAddress.item,
- urq->callSignalAddress.count);
+ set_sig_addr = rcu_dereference(set_sig_addr_hook);
+ if (set_sig_addr) {
+ ret = set_sig_addr(pskb, ct, ctinfo, data,
+ urq->callSignalAddress.item,
+ urq->callSignalAddress.count);
if (ret < 0)
return -1;
}
@@ -1465,7 +1485,7 @@ static int process_urq(struct sk_buff **pskb, struct ip_conntrack *ct,
info->sig_port[!dir] = 0;
/* Give it 30 seconds for UCF or URJ */
- ip_ct_refresh_acct(ct, ctinfo, NULL, 30 * HZ);
+ ip_ct_refresh(ct, *pskb, 30 * HZ);
return 0;
}
@@ -1479,28 +1499,30 @@ static int process_arq(struct sk_buff **pskb, struct ip_conntrack *ct,
int dir = CTINFO2DIR(ctinfo);
__be32 ip;
u_int16_t port;
+ typeof(set_h225_addr_hook) set_h225_addr;
DEBUGP("ip_ct_ras: ARQ\n");
+ set_h225_addr = rcu_dereference(set_h225_addr_hook);
if ((arq->options & eAdmissionRequest_destCallSignalAddress) &&
get_h225_addr(*data, &arq->destCallSignalAddress, &ip, &port) &&
ip == ct->tuplehash[dir].tuple.src.ip &&
- port == info->sig_port[dir] && set_h225_addr_hook) {
+ port == info->sig_port[dir] && set_h225_addr) {
/* Answering ARQ */
- return set_h225_addr_hook(pskb, data, 0,
- &arq->destCallSignalAddress,
- ct->tuplehash[!dir].tuple.dst.ip,
- info->sig_port[!dir]);
+ return set_h225_addr(pskb, data, 0,
+ &arq->destCallSignalAddress,
+ ct->tuplehash[!dir].tuple.dst.ip,
+ info->sig_port[!dir]);
}
if ((arq->options & eAdmissionRequest_srcCallSignalAddress) &&
get_h225_addr(*data, &arq->srcCallSignalAddress, &ip, &port) &&
- ip == ct->tuplehash[dir].tuple.src.ip && set_h225_addr_hook) {
+ ip == ct->tuplehash[dir].tuple.src.ip && set_h225_addr) {
/* Calling ARQ */
- return set_h225_addr_hook(pskb, data, 0,
- &arq->srcCallSignalAddress,
- ct->tuplehash[!dir].tuple.dst.ip,
- port);
+ return set_h225_addr(pskb, data, 0,
+ &arq->srcCallSignalAddress,
+ ct->tuplehash[!dir].tuple.dst.ip,
+ port);
}
return 0;
@@ -1516,6 +1538,7 @@ static int process_acf(struct sk_buff **pskb, struct ip_conntrack *ct,
__be32 ip;
u_int16_t port;
struct ip_conntrack_expect *exp;
+ typeof(set_sig_addr_hook) set_sig_addr;
DEBUGP("ip_ct_ras: ACF\n");
@@ -1523,10 +1546,10 @@ static int process_acf(struct sk_buff **pskb, struct ip_conntrack *ct,
return 0;
if (ip == ct->tuplehash[dir].tuple.dst.ip) { /* Answering ACF */
- if (set_sig_addr_hook)
- return set_sig_addr_hook(pskb, ct, ctinfo, data,
- &acf->destCallSignalAddress,
- 1);
+ set_sig_addr = rcu_dereference(set_sig_addr_hook);
+ if (set_sig_addr)
+ return set_sig_addr(pskb, ct, ctinfo, data,
+ &acf->destCallSignalAddress, 1);
return 0;
}
@@ -1566,11 +1589,14 @@ static int process_lrq(struct sk_buff **pskb, struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, LocationRequest * lrq)
{
+ typeof(set_ras_addr_hook) set_ras_addr;
+
DEBUGP("ip_ct_ras: LRQ\n");
- if (set_ras_addr_hook)
- return set_ras_addr_hook(pskb, ct, ctinfo, data,
- &lrq->replyAddress, 1);
+ set_ras_addr = rcu_dereference(set_ras_addr_hook);
+ if (set_ras_addr)
+ return set_ras_addr(pskb, ct, ctinfo, data,
+ &lrq->replyAddress, 1);
return 0;
}
@@ -1629,20 +1655,24 @@ static int process_irr(struct sk_buff **pskb, struct ip_conntrack *ct,
unsigned char **data, InfoRequestResponse * irr)
{
int ret;
+ typeof(set_ras_addr_hook) set_ras_addr;
+ typeof(set_sig_addr_hook) set_sig_addr;
DEBUGP("ip_ct_ras: IRR\n");
- if (set_ras_addr_hook) {
- ret = set_ras_addr_hook(pskb, ct, ctinfo, data,
- &irr->rasAddress, 1);
+ set_ras_addr = rcu_dereference(set_ras_addr_hook);
+ if (set_ras_addr) {
+ ret = set_ras_addr(pskb, ct, ctinfo, data,
+ &irr->rasAddress, 1);
if (ret < 0)
return -1;
}
- if (set_sig_addr_hook) {
- ret = set_sig_addr_hook(pskb, ct, ctinfo, data,
- irr->callSignalAddress.item,
- irr->callSignalAddress.count);
+ set_sig_addr = rcu_dereference(set_sig_addr_hook);
+ if (set_sig_addr) {
+ ret = set_sig_addr(pskb, ct, ctinfo, data,
+ irr->callSignalAddress.item,
+ irr->callSignalAddress.count);
if (ret < 0)
return -1;
}
@@ -1746,7 +1776,7 @@ static struct ip_conntrack_helper ip_conntrack_helper_ras = {
.me = THIS_MODULE,
.max_expected = 32,
.timeout = 240,
- .tuple = {.src = {.u = {__constant_htons(RAS_PORT)}},
+ .tuple = {.src = {.u = {.tcp = {.port = __constant_htons(RAS_PORT)}}},
.dst = {.protonum = IPPROTO_UDP}},
.mask = {.src = {.u = {0xFFFE}},
.dst = {.protonum = 0xFF}},
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
index a2af5e0c7f99..4d19373bbf0d 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
+++ b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
@@ -124,6 +124,8 @@ EXPORT_SYMBOL(pptp_msg_name);
static void pptp_expectfn(struct ip_conntrack *ct,
struct ip_conntrack_expect *exp)
{
+ typeof(ip_nat_pptp_hook_expectfn) ip_nat_pptp_expectfn;
+
DEBUGP("increasing timeouts\n");
/* increase timeout of GRE data channel conntrack entry */
@@ -133,7 +135,9 @@ static void pptp_expectfn(struct ip_conntrack *ct,
/* Can you see how rusty this code is, compared with the pre-2.6.11
* one? That's what happened to my shiny newnat of 2002 ;( -HW */
- if (!ip_nat_pptp_hook_expectfn) {
+ rcu_read_lock();
+ ip_nat_pptp_expectfn = rcu_dereference(ip_nat_pptp_hook_expectfn);
+ if (!ip_nat_pptp_expectfn) {
struct ip_conntrack_tuple inv_t;
struct ip_conntrack_expect *exp_other;
@@ -142,7 +146,7 @@ static void pptp_expectfn(struct ip_conntrack *ct,
DEBUGP("trying to unexpect other dir: ");
DUMP_TUPLE(&inv_t);
- exp_other = ip_conntrack_expect_find(&inv_t);
+ exp_other = ip_conntrack_expect_find_get(&inv_t);
if (exp_other) {
/* delete other expectation. */
DEBUGP("found\n");
@@ -153,8 +157,9 @@ static void pptp_expectfn(struct ip_conntrack *ct,
}
} else {
/* we need more than simple inversion */
- ip_nat_pptp_hook_expectfn(ct, exp);
+ ip_nat_pptp_expectfn(ct, exp);
}
+ rcu_read_unlock();
}
static int destroy_sibling_or_exp(const struct ip_conntrack_tuple *t)
@@ -176,7 +181,7 @@ static int destroy_sibling_or_exp(const struct ip_conntrack_tuple *t)
ip_conntrack_put(sibling);
return 1;
} else {
- exp = ip_conntrack_expect_find(t);
+ exp = ip_conntrack_expect_find_get(t);
if (exp) {
DEBUGP("unexpect_related of expect %p\n", exp);
ip_conntrack_unexpect_related(exp);
@@ -226,6 +231,7 @@ exp_gre(struct ip_conntrack *ct,
{
struct ip_conntrack_expect *exp_orig, *exp_reply;
int ret = 1;
+ typeof(ip_nat_pptp_hook_exp_gre) ip_nat_pptp_exp_gre;
exp_orig = ip_conntrack_expect_alloc(ct);
if (exp_orig == NULL)
@@ -262,8 +268,9 @@ exp_gre(struct ip_conntrack *ct,
exp_reply->tuple.dst.u.gre.key = peer_callid;
exp_reply->tuple.dst.protonum = IPPROTO_GRE;
- if (ip_nat_pptp_hook_exp_gre)
- ip_nat_pptp_hook_exp_gre(exp_orig, exp_reply);
+ ip_nat_pptp_exp_gre = rcu_dereference(ip_nat_pptp_hook_exp_gre);
+ if (ip_nat_pptp_exp_gre)
+ ip_nat_pptp_exp_gre(exp_orig, exp_reply);
if (ip_conntrack_expect_related(exp_orig) != 0)
goto out_put_both;
if (ip_conntrack_expect_related(exp_reply) != 0)
@@ -303,6 +310,7 @@ pptp_inbound_pkt(struct sk_buff **pskb,
struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
u_int16_t msg;
__be16 cid = 0, pcid = 0;
+ typeof(ip_nat_pptp_hook_inbound) ip_nat_pptp_inbound;
msg = ntohs(ctlh->messageType);
DEBUGP("inbound control message %s\n", pptp_msg_name[msg]);
@@ -402,9 +410,9 @@ pptp_inbound_pkt(struct sk_buff **pskb,
goto invalid;
}
- if (ip_nat_pptp_hook_inbound)
- return ip_nat_pptp_hook_inbound(pskb, ct, ctinfo, ctlh,
- pptpReq);
+ ip_nat_pptp_inbound = rcu_dereference(ip_nat_pptp_hook_inbound);
+ if (ip_nat_pptp_inbound)
+ return ip_nat_pptp_inbound(pskb, ct, ctinfo, ctlh, pptpReq);
return NF_ACCEPT;
invalid:
@@ -427,6 +435,7 @@ pptp_outbound_pkt(struct sk_buff **pskb,
struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
u_int16_t msg;
__be16 cid = 0, pcid = 0;
+ typeof(ip_nat_pptp_hook_outbound) ip_nat_pptp_outbound;
msg = ntohs(ctlh->messageType);
DEBUGP("outbound control message %s\n", pptp_msg_name[msg]);
@@ -492,9 +501,9 @@ pptp_outbound_pkt(struct sk_buff **pskb,
goto invalid;
}
- if (ip_nat_pptp_hook_outbound)
- return ip_nat_pptp_hook_outbound(pskb, ct, ctinfo, ctlh,
- pptpReq);
+ ip_nat_pptp_outbound = rcu_dereference(ip_nat_pptp_hook_outbound);
+ if (ip_nat_pptp_outbound)
+ return ip_nat_pptp_outbound(pskb, ct, ctinfo, ctlh, pptpReq);
return NF_ACCEPT;
invalid:
diff --git a/net/ipv4/netfilter/ip_conntrack_irc.c b/net/ipv4/netfilter/ip_conntrack_irc.c
index 75f7c3db1619..91832eca4106 100644
--- a/net/ipv4/netfilter/ip_conntrack_irc.c
+++ b/net/ipv4/netfilter/ip_conntrack_irc.c
@@ -114,6 +114,7 @@ static int help(struct sk_buff **pskb,
u_int16_t dcc_port;
int i, ret = NF_ACCEPT;
char *addr_beg_p, *addr_end_p;
+ typeof(ip_nat_irc_hook) ip_nat_irc;
DEBUGP("entered\n");
@@ -222,11 +223,12 @@ static int help(struct sk_buff **pskb,
{ .tcp = { htons(0xFFFF) } }, 0xFF }});
exp->expectfn = NULL;
exp->flags = 0;
- if (ip_nat_irc_hook)
- ret = ip_nat_irc_hook(pskb, ctinfo,
- addr_beg_p - ib_ptr,
- addr_end_p - addr_beg_p,
- exp);
+ ip_nat_irc = rcu_dereference(ip_nat_irc_hook);
+ if (ip_nat_irc)
+ ret = ip_nat_irc(pskb, ctinfo,
+ addr_beg_p - ib_ptr,
+ addr_end_p - addr_beg_p,
+ exp);
else if (ip_conntrack_expect_related(exp) != 0)
ret = NF_DROP;
ip_conntrack_expect_put(exp);
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c
index 262d0d44ec1b..5fcf91d617cd 100644
--- a/net/ipv4/netfilter/ip_conntrack_netlink.c
+++ b/net/ipv4/netfilter/ip_conntrack_netlink.c
@@ -153,6 +153,7 @@ ctnetlink_dump_protoinfo(struct sk_buff *skb, const struct ip_conntrack *ct)
return ret;
nfattr_failure:
+ ip_conntrack_proto_put(proto);
return -1;
}
@@ -319,8 +320,6 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
} else if (events & (IPCT_NEW | IPCT_RELATED)) {
type = IPCTNL_MSG_CT_NEW;
flags = NLM_F_CREATE|NLM_F_EXCL;
- /* dump everything */
- events = ~0UL;
group = NFNLGRP_CONNTRACK_NEW;
} else if (events & (IPCT_STATUS | IPCT_PROTOINFO)) {
type = IPCTNL_MSG_CT_NEW;
@@ -355,28 +354,35 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_REPLY)) < 0)
goto nfattr_failure;
NFA_NEST_END(skb, nest_parms);
-
- /* NAT stuff is now a status flag */
- if ((events & IPCT_STATUS || events & IPCT_NATINFO)
- && ctnetlink_dump_status(skb, ct) < 0)
- goto nfattr_failure;
- if (events & IPCT_REFRESH
- && ctnetlink_dump_timeout(skb, ct) < 0)
- goto nfattr_failure;
- if (events & IPCT_PROTOINFO
- && ctnetlink_dump_protoinfo(skb, ct) < 0)
- goto nfattr_failure;
- if (events & IPCT_HELPINFO
- && ctnetlink_dump_helpinfo(skb, ct) < 0)
- goto nfattr_failure;
- if (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
- ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0)
- goto nfattr_failure;
+ if (events & IPCT_DESTROY) {
+ if (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
+ ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0)
+ goto nfattr_failure;
+ } else {
+ if (ctnetlink_dump_status(skb, ct) < 0)
+ goto nfattr_failure;
- if (events & IPCT_MARK
- && ctnetlink_dump_mark(skb, ct) < 0)
- goto nfattr_failure;
+ if (ctnetlink_dump_timeout(skb, ct) < 0)
+ goto nfattr_failure;
+
+ if (events & IPCT_PROTOINFO
+ && ctnetlink_dump_protoinfo(skb, ct) < 0)
+ goto nfattr_failure;
+
+ if ((events & IPCT_HELPER || ct->helper)
+ && ctnetlink_dump_helpinfo(skb, ct) < 0)
+ goto nfattr_failure;
+
+ if ((events & IPCT_MARK || ct->mark)
+ && ctnetlink_dump_mark(skb, ct) < 0)
+ goto nfattr_failure;
+
+ if (events & IPCT_COUNTER_FILLING &&
+ (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
+ ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0))
+ goto nfattr_failure;
+ }
nlh->nlmsg_len = skb->tail - b;
nfnetlink_send(skb, 0, group, 0);
@@ -742,7 +748,6 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
ip_conntrack_put(ct);
return -ENOMEM;
}
- NETLINK_CB(skb2).dst_pid = NETLINK_CB(skb).pid;
err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq,
IPCTNL_MSG_CT_NEW, 1, ct);
@@ -945,9 +950,11 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
ct->timeout.expires = jiffies + ct->timeout.expires * HZ;
ct->status |= IPS_CONFIRMED;
- err = ctnetlink_change_status(ct, cda);
- if (err < 0)
- goto err;
+ if (cda[CTA_STATUS-1]) {
+ err = ctnetlink_change_status(ct, cda);
+ if (err < 0)
+ goto err;
+ }
if (cda[CTA_PROTOINFO-1]) {
err = ctnetlink_change_protoinfo(ct, cda);
@@ -1256,7 +1263,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
if (err < 0)
return err;
- exp = ip_conntrack_expect_find(&tuple);
+ exp = ip_conntrack_expect_find_get(&tuple);
if (!exp)
return -ENOENT;
@@ -1272,8 +1279,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
if (!skb2)
goto out;
- NETLINK_CB(skb2).dst_pid = NETLINK_CB(skb).pid;
-
+
err = ctnetlink_exp_fill_info(skb2, NETLINK_CB(skb).pid,
nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW,
1, exp);
@@ -1310,7 +1316,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
return err;
/* bump usage count to 2 */
- exp = ip_conntrack_expect_find(&tuple);
+ exp = ip_conntrack_expect_find_get(&tuple);
if (!exp)
return -ENOENT;
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_gre.c b/net/ipv4/netfilter/ip_conntrack_proto_gre.c
index 5fe026f467d3..ac1c49ef36a9 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_gre.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_gre.c
@@ -34,8 +34,6 @@
#include <linux/interrupt.h>
static DEFINE_RWLOCK(ip_ct_gre_lock);
-#define ASSERT_READ_LOCK(x)
-#define ASSERT_WRITE_LOCK(x)
#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
diff --git a/net/ipv4/netfilter/ip_conntrack_sip.c b/net/ipv4/netfilter/ip_conntrack_sip.c
index f4f75995a9e4..3a26d63eed88 100644
--- a/net/ipv4/netfilter/ip_conntrack_sip.c
+++ b/net/ipv4/netfilter/ip_conntrack_sip.c
@@ -52,20 +52,56 @@ unsigned int (*ip_nat_sdp_hook)(struct sk_buff **pskb,
const char *dptr);
EXPORT_SYMBOL_GPL(ip_nat_sdp_hook);
-int ct_sip_get_info(const char *dptr, size_t dlen,
- unsigned int *matchoff,
- unsigned int *matchlen,
- struct sip_header_nfo *hnfo);
-EXPORT_SYMBOL_GPL(ct_sip_get_info);
-
-
static int digits_len(const char *dptr, const char *limit, int *shift);
static int epaddr_len(const char *dptr, const char *limit, int *shift);
static int skp_digits_len(const char *dptr, const char *limit, int *shift);
static int skp_epaddr_len(const char *dptr, const char *limit, int *shift);
-struct sip_header_nfo ct_sip_hdrs[] = {
- { /* Via header */
+struct sip_header_nfo {
+ const char *lname;
+ const char *sname;
+ const char *ln_str;
+ size_t lnlen;
+ size_t snlen;
+ size_t ln_strlen;
+ int case_sensitive;
+ int (*match_len)(const char *, const char *, int *);
+};
+
+static struct sip_header_nfo ct_sip_hdrs[] = {
+ [POS_REG_REQ_URI] = { /* SIP REGISTER request URI */
+ .lname = "sip:",
+ .lnlen = sizeof("sip:") - 1,
+ .ln_str = ":",
+ .ln_strlen = sizeof(":") - 1,
+ .match_len = epaddr_len
+ },
+ [POS_REQ_URI] = { /* SIP request URI */
+ .lname = "sip:",
+ .lnlen = sizeof("sip:") - 1,
+ .ln_str = "@",
+ .ln_strlen = sizeof("@") - 1,
+ .match_len = epaddr_len
+ },
+ [POS_FROM] = { /* SIP From header */
+ .lname = "From:",
+ .lnlen = sizeof("From:") - 1,
+ .sname = "\r\nf:",
+ .snlen = sizeof("\r\nf:") - 1,
+ .ln_str = "sip:",
+ .ln_strlen = sizeof("sip:") - 1,
+ .match_len = skp_epaddr_len,
+ },
+ [POS_TO] = { /* SIP To header */
+ .lname = "To:",
+ .lnlen = sizeof("To:") - 1,
+ .sname = "\r\nt:",
+ .snlen = sizeof("\r\nt:") - 1,
+ .ln_str = "sip:",
+ .ln_strlen = sizeof("sip:") - 1,
+ .match_len = skp_epaddr_len,
+ },
+ [POS_VIA] = { /* SIP Via header */
.lname = "Via:",
.lnlen = sizeof("Via:") - 1,
.sname = "\r\nv:",
@@ -74,7 +110,7 @@ struct sip_header_nfo ct_sip_hdrs[] = {
.ln_strlen = sizeof("UDP ") - 1,
.match_len = epaddr_len,
},
- { /* Contact header */
+ [POS_CONTACT] = { /* SIP Contact header */
.lname = "Contact:",
.lnlen = sizeof("Contact:") - 1,
.sname = "\r\nm:",
@@ -83,7 +119,7 @@ struct sip_header_nfo ct_sip_hdrs[] = {
.ln_strlen = sizeof("sip:") - 1,
.match_len = skp_epaddr_len
},
- { /* Content length header */
+ [POS_CONTENT] = { /* SIP Content length header */
.lname = "Content-Length:",
.lnlen = sizeof("Content-Length:") - 1,
.sname = "\r\nl:",
@@ -92,7 +128,8 @@ struct sip_header_nfo ct_sip_hdrs[] = {
.ln_strlen = sizeof(":") - 1,
.match_len = skp_digits_len
},
- { /* SDP media info */
+ [POS_MEDIA] = { /* SDP media info */
+ .case_sensitive = 1,
.lname = "\nm=",
.lnlen = sizeof("\nm=") - 1,
.sname = "\rm=",
@@ -101,7 +138,8 @@ struct sip_header_nfo ct_sip_hdrs[] = {
.ln_strlen = sizeof("audio ") - 1,
.match_len = digits_len
},
- { /* SDP owner address*/
+ [POS_OWNER] = { /* SDP owner address*/
+ .case_sensitive = 1,
.lname = "\no=",
.lnlen = sizeof("\no=") - 1,
.sname = "\ro=",
@@ -110,7 +148,8 @@ struct sip_header_nfo ct_sip_hdrs[] = {
.ln_strlen = sizeof("IN IP4 ") - 1,
.match_len = epaddr_len
},
- { /* SDP connection info */
+ [POS_CONNECTION] = { /* SDP connection info */
+ .case_sensitive = 1,
.lname = "\nc=",
.lnlen = sizeof("\nc=") - 1,
.sname = "\rc=",
@@ -119,16 +158,8 @@ struct sip_header_nfo ct_sip_hdrs[] = {
.ln_strlen = sizeof("IN IP4 ") - 1,
.match_len = epaddr_len
},
- { /* Requests headers */
- .lname = "sip:",
- .lnlen = sizeof("sip:") - 1,
- .sname = "sip:",
- .snlen = sizeof("sip:") - 1, /* yes, i know.. ;) */
- .ln_str = "@",
- .ln_strlen = sizeof("@") - 1,
- .match_len = epaddr_len
- },
- { /* SDP version header */
+ [POS_SDP_HEADER] = { /* SDP version header */
+ .case_sensitive = 1,
.lname = "\nv=",
.lnlen = sizeof("\nv=") - 1,
.sname = "\rv=",
@@ -138,7 +169,6 @@ struct sip_header_nfo ct_sip_hdrs[] = {
.match_len = digits_len
}
};
-EXPORT_SYMBOL_GPL(ct_sip_hdrs);
/* get line lenght until first CR or LF seen. */
int ct_sip_lnlen(const char *line, const char *limit)
@@ -159,13 +189,19 @@ EXPORT_SYMBOL_GPL(ct_sip_lnlen);
/* Linear string search, case sensitive. */
const char *ct_sip_search(const char *needle, const char *haystack,
- size_t needle_len, size_t haystack_len)
+ size_t needle_len, size_t haystack_len,
+ int case_sensitive)
{
const char *limit = haystack + (haystack_len - needle_len);
while (haystack <= limit) {
- if (memcmp(haystack, needle, needle_len) == 0)
- return haystack;
+ if (case_sensitive) {
+ if (strncmp(haystack, needle, needle_len) == 0)
+ return haystack;
+ } else {
+ if (strnicmp(haystack, needle, needle_len) == 0)
+ return haystack;
+ }
haystack++;
}
return NULL;
@@ -263,8 +299,9 @@ static int skp_epaddr_len(const char *dptr, const char *limit, int *shift)
int ct_sip_get_info(const char *dptr, size_t dlen,
unsigned int *matchoff,
unsigned int *matchlen,
- struct sip_header_nfo *hnfo)
+ enum sip_header_pos pos)
{
+ struct sip_header_nfo *hnfo = &ct_sip_hdrs[pos];
const char *limit, *aux, *k = dptr;
int shift = 0;
@@ -272,12 +309,14 @@ int ct_sip_get_info(const char *dptr, size_t dlen,
while (dptr <= limit) {
if ((strncmp(dptr, hnfo->lname, hnfo->lnlen) != 0) &&
- (strncmp(dptr, hnfo->sname, hnfo->snlen) != 0)) {
+ (hnfo->sname == NULL ||
+ strncmp(dptr, hnfo->sname, hnfo->snlen) != 0)) {
dptr++;
continue;
}
aux = ct_sip_search(hnfo->ln_str, dptr, hnfo->ln_strlen,
- ct_sip_lnlen(dptr, limit));
+ ct_sip_lnlen(dptr, limit),
+ hnfo->case_sensitive);
if (!aux) {
DEBUGP("'%s' not found in '%s'.\n", hnfo->ln_str,
hnfo->lname);
@@ -298,6 +337,7 @@ int ct_sip_get_info(const char *dptr, size_t dlen,
DEBUGP("%s header not found.\n", hnfo->lname);
return 0;
}
+EXPORT_SYMBOL_GPL(ct_sip_get_info);
static int set_expected_rtp(struct sk_buff **pskb,
struct ip_conntrack *ct,
@@ -308,6 +348,7 @@ static int set_expected_rtp(struct sk_buff **pskb,
struct ip_conntrack_expect *exp;
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
int ret;
+ typeof(ip_nat_sdp_hook) ip_nat_sdp;
exp = ip_conntrack_expect_alloc(ct);
if (exp == NULL)
@@ -328,8 +369,9 @@ static int set_expected_rtp(struct sk_buff **pskb,
exp->expectfn = NULL;
exp->flags = 0;
- if (ip_nat_sdp_hook)
- ret = ip_nat_sdp_hook(pskb, ctinfo, exp, dptr);
+ ip_nat_sdp = rcu_dereference(ip_nat_sdp_hook);
+ if (ip_nat_sdp)
+ ret = ip_nat_sdp(pskb, ctinfo, exp, dptr);
else {
if (ip_conntrack_expect_related(exp) != 0)
ret = NF_DROP;
@@ -351,6 +393,7 @@ static int sip_help(struct sk_buff **pskb,
int matchoff, matchlen;
__be32 ipaddr;
u_int16_t port;
+ typeof(ip_nat_sip_hook) ip_nat_sip;
/* No Data ? */
dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
@@ -368,8 +411,9 @@ static int sip_help(struct sk_buff **pskb,
goto out;
}
- if (ip_nat_sip_hook) {
- if (!ip_nat_sip_hook(pskb, ctinfo, ct, &dptr)) {
+ ip_nat_sip = rcu_dereference(ip_nat_sip_hook);
+ if (ip_nat_sip) {
+ if (!ip_nat_sip(pskb, ctinfo, ct, &dptr)) {
ret = NF_DROP;
goto out;
}
@@ -389,7 +433,7 @@ static int sip_help(struct sk_buff **pskb,
}
/* Get ip and port address from SDP packet. */
if (ct_sip_get_info(dptr, datalen, &matchoff, &matchlen,
- &ct_sip_hdrs[POS_CONNECTION]) > 0) {
+ POS_CONNECTION) > 0) {
/* We'll drop only if there are parse problems. */
if (parse_ipaddr(dptr + matchoff, NULL, &ipaddr,
@@ -398,7 +442,7 @@ static int sip_help(struct sk_buff **pskb,
goto out;
}
if (ct_sip_get_info(dptr, datalen, &matchoff, &matchlen,
- &ct_sip_hdrs[POS_MEDIA]) > 0) {
+ POS_MEDIA) > 0) {
port = simple_strtoul(dptr + matchoff, NULL, 10);
if (port < 1024) {
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index 02135756562e..86efb5449676 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -28,9 +28,6 @@
#include <net/ip.h>
#include <net/route.h>
-#define ASSERT_READ_LOCK(x)
-#define ASSERT_WRITE_LOCK(x)
-
#include <linux/netfilter_ipv4/ip_conntrack.h>
#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
#include <linux/netfilter_ipv4/ip_conntrack_core.h>
@@ -139,7 +136,6 @@ static int ct_seq_show(struct seq_file *s, void *v)
const struct ip_conntrack *conntrack = tuplehash_to_ctrack(hash);
struct ip_conntrack_protocol *proto;
- ASSERT_READ_LOCK(&ip_conntrack_lock);
IP_NF_ASSERT(conntrack);
/* we only want to print DIR_ORIGINAL */
@@ -926,7 +922,7 @@ EXPORT_SYMBOL(__ip_ct_refresh_acct);
EXPORT_SYMBOL(ip_conntrack_expect_alloc);
EXPORT_SYMBOL(ip_conntrack_expect_put);
EXPORT_SYMBOL_GPL(__ip_conntrack_expect_find);
-EXPORT_SYMBOL_GPL(ip_conntrack_expect_find);
+EXPORT_SYMBOL_GPL(ip_conntrack_expect_find_get);
EXPORT_SYMBOL(ip_conntrack_expect_related);
EXPORT_SYMBOL(ip_conntrack_unexpect_related);
EXPORT_SYMBOL_GPL(ip_conntrack_expect_list);
diff --git a/net/ipv4/netfilter/ip_conntrack_tftp.c b/net/ipv4/netfilter/ip_conntrack_tftp.c
index fe0b634dd377..ef56de2eff0c 100644
--- a/net/ipv4/netfilter/ip_conntrack_tftp.c
+++ b/net/ipv4/netfilter/ip_conntrack_tftp.c
@@ -50,6 +50,7 @@ static int tftp_help(struct sk_buff **pskb,
struct tftphdr _tftph, *tfh;
struct ip_conntrack_expect *exp;
unsigned int ret = NF_ACCEPT;
+ typeof(ip_nat_tftp_hook) ip_nat_tftp;
tfh = skb_header_pointer(*pskb,
(*pskb)->nh.iph->ihl*4+sizeof(struct udphdr),
@@ -81,8 +82,9 @@ static int tftp_help(struct sk_buff **pskb,
DEBUGP("expect: ");
DUMP_TUPLE(&exp->tuple);
DUMP_TUPLE(&exp->mask);
- if (ip_nat_tftp_hook)
- ret = ip_nat_tftp_hook(pskb, ctinfo, exp);
+ ip_nat_tftp = rcu_dereference(ip_nat_tftp_hook);
+ if (ip_nat_tftp)
+ ret = ip_nat_tftp(pskb, ctinfo, exp);
else if (ip_conntrack_expect_related(exp) != 0)
ret = NF_DROP;
ip_conntrack_expect_put(exp);
diff --git a/net/ipv4/netfilter/ip_nat_amanda.c b/net/ipv4/netfilter/ip_nat_amanda.c
index 3a888715bbf3..85df1a9aed33 100644
--- a/net/ipv4/netfilter/ip_nat_amanda.c
+++ b/net/ipv4/netfilter/ip_nat_amanda.c
@@ -70,15 +70,14 @@ static unsigned int help(struct sk_buff **pskb,
static void __exit ip_nat_amanda_fini(void)
{
- ip_nat_amanda_hook = NULL;
- /* Make sure noone calls it, meanwhile. */
- synchronize_net();
+ rcu_assign_pointer(ip_nat_amanda_hook, NULL);
+ synchronize_rcu();
}
static int __init ip_nat_amanda_init(void)
{
- BUG_ON(ip_nat_amanda_hook);
- ip_nat_amanda_hook = help;
+ BUG_ON(rcu_dereference(ip_nat_amanda_hook));
+ rcu_assign_pointer(ip_nat_amanda_hook, help);
return 0;
}
diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c
index 4b6260a97408..9d1a5175dcd4 100644
--- a/net/ipv4/netfilter/ip_nat_core.c
+++ b/net/ipv4/netfilter/ip_nat_core.c
@@ -362,12 +362,10 @@ manip_pkt(u_int16_t proto,
iph = (void *)(*pskb)->data + iphdroff;
if (maniptype == IP_NAT_MANIP_SRC) {
- iph->check = nf_csum_update(~iph->saddr, target->src.ip,
- iph->check);
+ nf_csum_replace4(&iph->check, iph->saddr, target->src.ip);
iph->saddr = target->src.ip;
} else {
- iph->check = nf_csum_update(~iph->daddr, target->dst.ip,
- iph->check);
+ nf_csum_replace4(&iph->check, iph->daddr, target->dst.ip);
iph->daddr = target->dst.ip;
}
return 1;
diff --git a/net/ipv4/netfilter/ip_nat_ftp.c b/net/ipv4/netfilter/ip_nat_ftp.c
index a71c233d8112..913960e1380f 100644
--- a/net/ipv4/netfilter/ip_nat_ftp.c
+++ b/net/ipv4/netfilter/ip_nat_ftp.c
@@ -156,15 +156,14 @@ static unsigned int ip_nat_ftp(struct sk_buff **pskb,
static void __exit ip_nat_ftp_fini(void)
{
- ip_nat_ftp_hook = NULL;
- /* Make sure noone calls it, meanwhile. */
- synchronize_net();
+ rcu_assign_pointer(ip_nat_ftp_hook, NULL);
+ synchronize_rcu();
}
static int __init ip_nat_ftp_init(void)
{
- BUG_ON(ip_nat_ftp_hook);
- ip_nat_ftp_hook = ip_nat_ftp;
+ BUG_ON(rcu_dereference(ip_nat_ftp_hook));
+ rcu_assign_pointer(ip_nat_ftp_hook, ip_nat_ftp);
return 0;
}
diff --git a/net/ipv4/netfilter/ip_nat_helper.c b/net/ipv4/netfilter/ip_nat_helper.c
index 3bf858480558..ee80feb4b2a9 100644
--- a/net/ipv4/netfilter/ip_nat_helper.c
+++ b/net/ipv4/netfilter/ip_nat_helper.c
@@ -188,10 +188,8 @@ ip_nat_mangle_tcp_packet(struct sk_buff **pskb,
csum_partial((char *)tcph,
datalen, 0));
} else
- tcph->check = nf_proto_csum_update(*pskb,
- htons(oldlen) ^ htons(0xFFFF),
- htons(datalen),
- tcph->check, 1);
+ nf_proto_csum_replace2(&tcph->check, *pskb,
+ htons(oldlen), htons(datalen), 1);
if (rep_len != match_len) {
set_bit(IPS_SEQ_ADJUST_BIT, &ct->status);
@@ -264,12 +262,10 @@ ip_nat_mangle_udp_packet(struct sk_buff **pskb,
csum_partial((char *)udph,
datalen, 0));
if (!udph->check)
- udph->check = -1;
+ udph->check = CSUM_MANGLED_0;
} else
- udph->check = nf_proto_csum_update(*pskb,
- htons(oldlen) ^ htons(0xFFFF),
- htons(datalen),
- udph->check, 1);
+ nf_proto_csum_replace2(&udph->check, *pskb,
+ htons(oldlen), htons(datalen), 1);
return 1;
}
EXPORT_SYMBOL(ip_nat_mangle_udp_packet);
@@ -307,14 +303,10 @@ sack_adjust(struct sk_buff *skb,
ntohl(sack->start_seq), new_start_seq,
ntohl(sack->end_seq), new_end_seq);
- tcph->check = nf_proto_csum_update(skb,
- ~sack->start_seq,
- new_start_seq,
- tcph->check, 0);
- tcph->check = nf_proto_csum_update(skb,
- ~sack->end_seq,
- new_end_seq,
- tcph->check, 0);
+ nf_proto_csum_replace4(&tcph->check, skb,
+ sack->start_seq, new_start_seq, 0);
+ nf_proto_csum_replace4(&tcph->check, skb,
+ sack->end_seq, new_end_seq, 0);
sack->start_seq = new_start_seq;
sack->end_seq = new_end_seq;
sackoff += sizeof(*sack);
@@ -397,10 +389,8 @@ ip_nat_seq_adjust(struct sk_buff **pskb,
else
newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_before);
- tcph->check = nf_proto_csum_update(*pskb, ~tcph->seq, newseq,
- tcph->check, 0);
- tcph->check = nf_proto_csum_update(*pskb, ~tcph->ack_seq, newack,
- tcph->check, 0);
+ nf_proto_csum_replace4(&tcph->check, *pskb, tcph->seq, newseq, 0);
+ nf_proto_csum_replace4(&tcph->check, *pskb, tcph->ack_seq, newack, 0);
DEBUGP("Adjusting sequence number from %u->%u, ack from %u->%u\n",
ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq),
diff --git a/net/ipv4/netfilter/ip_nat_helper_h323.c b/net/ipv4/netfilter/ip_nat_helper_h323.c
index 4a7d34466ee2..bdc99ef6159e 100644
--- a/net/ipv4/netfilter/ip_nat_helper_h323.c
+++ b/net/ipv4/netfilter/ip_nat_helper_h323.c
@@ -563,25 +563,25 @@ static int nat_callforwarding(struct sk_buff **pskb, struct ip_conntrack *ct,
/****************************************************************************/
static int __init init(void)
{
- BUG_ON(set_h245_addr_hook != NULL);
- BUG_ON(set_h225_addr_hook != NULL);
- BUG_ON(set_sig_addr_hook != NULL);
- BUG_ON(set_ras_addr_hook != NULL);
- BUG_ON(nat_rtp_rtcp_hook != NULL);
- BUG_ON(nat_t120_hook != NULL);
- BUG_ON(nat_h245_hook != NULL);
- BUG_ON(nat_callforwarding_hook != NULL);
- BUG_ON(nat_q931_hook != NULL);
-
- set_h245_addr_hook = set_h245_addr;
- set_h225_addr_hook = set_h225_addr;
- set_sig_addr_hook = set_sig_addr;
- set_ras_addr_hook = set_ras_addr;
- nat_rtp_rtcp_hook = nat_rtp_rtcp;
- nat_t120_hook = nat_t120;
- nat_h245_hook = nat_h245;
- nat_callforwarding_hook = nat_callforwarding;
- nat_q931_hook = nat_q931;
+ BUG_ON(rcu_dereference(set_h245_addr_hook) != NULL);
+ BUG_ON(rcu_dereference(set_h225_addr_hook) != NULL);
+ BUG_ON(rcu_dereference(set_sig_addr_hook) != NULL);
+ BUG_ON(rcu_dereference(set_ras_addr_hook) != NULL);
+ BUG_ON(rcu_dereference(nat_rtp_rtcp_hook) != NULL);
+ BUG_ON(rcu_dereference(nat_t120_hook) != NULL);
+ BUG_ON(rcu_dereference(nat_h245_hook) != NULL);
+ BUG_ON(rcu_dereference(nat_callforwarding_hook) != NULL);
+ BUG_ON(rcu_dereference(nat_q931_hook) != NULL);
+
+ rcu_assign_pointer(set_h245_addr_hook, set_h245_addr);
+ rcu_assign_pointer(set_h225_addr_hook, set_h225_addr);
+ rcu_assign_pointer(set_sig_addr_hook, set_sig_addr);
+ rcu_assign_pointer(set_ras_addr_hook, set_ras_addr);
+ rcu_assign_pointer(nat_rtp_rtcp_hook, nat_rtp_rtcp);
+ rcu_assign_pointer(nat_t120_hook, nat_t120);
+ rcu_assign_pointer(nat_h245_hook, nat_h245);
+ rcu_assign_pointer(nat_callforwarding_hook, nat_callforwarding);
+ rcu_assign_pointer(nat_q931_hook, nat_q931);
DEBUGP("ip_nat_h323: init success\n");
return 0;
@@ -590,16 +590,16 @@ static int __init init(void)
/****************************************************************************/
static void __exit fini(void)
{
- set_h245_addr_hook = NULL;
- set_h225_addr_hook = NULL;
- set_sig_addr_hook = NULL;
- set_ras_addr_hook = NULL;
- nat_rtp_rtcp_hook = NULL;
- nat_t120_hook = NULL;
- nat_h245_hook = NULL;
- nat_callforwarding_hook = NULL;
- nat_q931_hook = NULL;
- synchronize_net();
+ rcu_assign_pointer(set_h245_addr_hook, NULL);
+ rcu_assign_pointer(set_h225_addr_hook, NULL);
+ rcu_assign_pointer(set_sig_addr_hook, NULL);
+ rcu_assign_pointer(set_ras_addr_hook, NULL);
+ rcu_assign_pointer(nat_rtp_rtcp_hook, NULL);
+ rcu_assign_pointer(nat_t120_hook, NULL);
+ rcu_assign_pointer(nat_h245_hook, NULL);
+ rcu_assign_pointer(nat_callforwarding_hook, NULL);
+ rcu_assign_pointer(nat_q931_hook, NULL);
+ synchronize_rcu();
}
/****************************************************************************/
diff --git a/net/ipv4/netfilter/ip_nat_helper_pptp.c b/net/ipv4/netfilter/ip_nat_helper_pptp.c
index 329fdcd7d702..ec957bbb5366 100644
--- a/net/ipv4/netfilter/ip_nat_helper_pptp.c
+++ b/net/ipv4/netfilter/ip_nat_helper_pptp.c
@@ -101,7 +101,7 @@ static void pptp_nat_expected(struct ip_conntrack *ct,
DEBUGP("trying to unexpect other dir: ");
DUMP_TUPLE(&t);
- other_exp = ip_conntrack_expect_find(&t);
+ other_exp = ip_conntrack_expect_find_get(&t);
if (other_exp) {
ip_conntrack_unexpect_related(other_exp);
ip_conntrack_expect_put(other_exp);
@@ -315,17 +315,17 @@ static int __init ip_nat_helper_pptp_init(void)
if (ret < 0)
return ret;
- BUG_ON(ip_nat_pptp_hook_outbound);
- ip_nat_pptp_hook_outbound = &pptp_outbound_pkt;
+ BUG_ON(rcu_dereference(ip_nat_pptp_hook_outbound));
+ rcu_assign_pointer(ip_nat_pptp_hook_outbound, pptp_outbound_pkt);
- BUG_ON(ip_nat_pptp_hook_inbound);
- ip_nat_pptp_hook_inbound = &pptp_inbound_pkt;
+ BUG_ON(rcu_dereference(ip_nat_pptp_hook_inbound));
+ rcu_assign_pointer(ip_nat_pptp_hook_inbound, pptp_inbound_pkt);
- BUG_ON(ip_nat_pptp_hook_exp_gre);
- ip_nat_pptp_hook_exp_gre = &pptp_exp_gre;
+ BUG_ON(rcu_dereference(ip_nat_pptp_hook_exp_gre));
+ rcu_assign_pointer(ip_nat_pptp_hook_exp_gre, pptp_exp_gre);
- BUG_ON(ip_nat_pptp_hook_expectfn);
- ip_nat_pptp_hook_expectfn = &pptp_nat_expected;
+ BUG_ON(rcu_dereference(ip_nat_pptp_hook_expectfn));
+ rcu_assign_pointer(ip_nat_pptp_hook_expectfn, pptp_nat_expected);
printk("ip_nat_pptp version %s loaded\n", IP_NAT_PPTP_VERSION);
return 0;
@@ -335,14 +335,13 @@ static void __exit ip_nat_helper_pptp_fini(void)
{
DEBUGP("cleanup_module\n" );
- ip_nat_pptp_hook_expectfn = NULL;
- ip_nat_pptp_hook_exp_gre = NULL;
- ip_nat_pptp_hook_inbound = NULL;
- ip_nat_pptp_hook_outbound = NULL;
+ rcu_assign_pointer(ip_nat_pptp_hook_expectfn, NULL);
+ rcu_assign_pointer(ip_nat_pptp_hook_exp_gre, NULL);
+ rcu_assign_pointer(ip_nat_pptp_hook_inbound, NULL);
+ rcu_assign_pointer(ip_nat_pptp_hook_outbound, NULL);
+ synchronize_rcu();
ip_nat_proto_gre_fini();
- /* Make sure noone calls it, meanwhile */
- synchronize_net();
printk("ip_nat_pptp version %s unloaded\n", IP_NAT_PPTP_VERSION);
}
diff --git a/net/ipv4/netfilter/ip_nat_irc.c b/net/ipv4/netfilter/ip_nat_irc.c
index a767123e082c..feb26b48f1d5 100644
--- a/net/ipv4/netfilter/ip_nat_irc.c
+++ b/net/ipv4/netfilter/ip_nat_irc.c
@@ -98,15 +98,14 @@ static unsigned int help(struct sk_buff **pskb,
static void __exit ip_nat_irc_fini(void)
{
- ip_nat_irc_hook = NULL;
- /* Make sure noone calls it, meanwhile. */
- synchronize_net();
+ rcu_assign_pointer(ip_nat_irc_hook, NULL);
+ synchronize_rcu();
}
static int __init ip_nat_irc_init(void)
{
- BUG_ON(ip_nat_irc_hook);
- ip_nat_irc_hook = help;
+ BUG_ON(rcu_dereference(ip_nat_irc_hook));
+ rcu_assign_pointer(ip_nat_irc_hook, help);
return 0;
}
diff --git a/net/ipv4/netfilter/ip_nat_proto_gre.c b/net/ipv4/netfilter/ip_nat_proto_gre.c
index bf91f9312b3c..95810202d849 100644
--- a/net/ipv4/netfilter/ip_nat_proto_gre.c
+++ b/net/ipv4/netfilter/ip_nat_proto_gre.c
@@ -129,11 +129,9 @@ gre_manip_pkt(struct sk_buff **pskb,
}
if (greh->csum) {
/* FIXME: Never tested this code... */
- *(gre_csum(greh)) =
- nf_proto_csum_update(*pskb,
- ~*(gre_key(greh)),
- tuple->dst.u.gre.key,
- *(gre_csum(greh)), 0);
+ nf_proto_csum_replace4(gre_csum(greh), *pskb,
+ *(gre_key(greh)),
+ tuple->dst.u.gre.key, 0);
}
*(gre_key(greh)) = tuple->dst.u.gre.key;
break;
diff --git a/net/ipv4/netfilter/ip_nat_proto_icmp.c b/net/ipv4/netfilter/ip_nat_proto_icmp.c
index 3f6efc13ac74..fb716edd5bc6 100644
--- a/net/ipv4/netfilter/ip_nat_proto_icmp.c
+++ b/net/ipv4/netfilter/ip_nat_proto_icmp.c
@@ -24,8 +24,8 @@ icmp_in_range(const struct ip_conntrack_tuple *tuple,
const union ip_conntrack_manip_proto *min,
const union ip_conntrack_manip_proto *max)
{
- return (tuple->src.u.icmp.id >= min->icmp.id
- && tuple->src.u.icmp.id <= max->icmp.id);
+ return ntohs(tuple->src.u.icmp.id) >= ntohs(min->icmp.id) &&
+ ntohs(tuple->src.u.icmp.id) <= ntohs(max->icmp.id);
}
static int
@@ -66,10 +66,8 @@ icmp_manip_pkt(struct sk_buff **pskb,
return 0;
hdr = (struct icmphdr *)((*pskb)->data + hdroff);
- hdr->checksum = nf_proto_csum_update(*pskb,
- hdr->un.echo.id ^ htons(0xFFFF),
- tuple->src.u.icmp.id,
- hdr->checksum, 0);
+ nf_proto_csum_replace2(&hdr->checksum, *pskb,
+ hdr->un.echo.id, tuple->src.u.icmp.id, 0);
hdr->un.echo.id = tuple->src.u.icmp.id;
return 1;
}
diff --git a/net/ipv4/netfilter/ip_nat_proto_tcp.c b/net/ipv4/netfilter/ip_nat_proto_tcp.c
index 12deb13b93b1..b586d18b3fb3 100644
--- a/net/ipv4/netfilter/ip_nat_proto_tcp.c
+++ b/net/ipv4/netfilter/ip_nat_proto_tcp.c
@@ -129,9 +129,8 @@ tcp_manip_pkt(struct sk_buff **pskb,
if (hdrsize < sizeof(*hdr))
return 1;
- hdr->check = nf_proto_csum_update(*pskb, ~oldip, newip, hdr->check, 1);
- hdr->check = nf_proto_csum_update(*pskb, oldport ^ htons(0xFFFF), newport,
- hdr->check, 0);
+ nf_proto_csum_replace4(&hdr->check, *pskb, oldip, newip, 1);
+ nf_proto_csum_replace2(&hdr->check, *pskb, oldport, newport, 0);
return 1;
}
diff --git a/net/ipv4/netfilter/ip_nat_proto_udp.c b/net/ipv4/netfilter/ip_nat_proto_udp.c
index 4bbec7730d18..5ced0877b32f 100644
--- a/net/ipv4/netfilter/ip_nat_proto_udp.c
+++ b/net/ipv4/netfilter/ip_nat_proto_udp.c
@@ -115,13 +115,10 @@ udp_manip_pkt(struct sk_buff **pskb,
}
if (hdr->check || (*pskb)->ip_summed == CHECKSUM_PARTIAL) {
- hdr->check = nf_proto_csum_update(*pskb, ~oldip, newip,
- hdr->check, 1);
- hdr->check = nf_proto_csum_update(*pskb,
- *portptr ^ htons(0xFFFF), newport,
- hdr->check, 0);
+ nf_proto_csum_replace4(&hdr->check, *pskb, oldip, newip, 1);
+ nf_proto_csum_replace2(&hdr->check, *pskb, *portptr, newport, 0);
if (!hdr->check)
- hdr->check = -1;
+ hdr->check = CSUM_MANGLED_0;
}
*portptr = newport;
return 1;
diff --git a/net/ipv4/netfilter/ip_nat_sip.c b/net/ipv4/netfilter/ip_nat_sip.c
index 71fc2730a007..6223abc924ff 100644
--- a/net/ipv4/netfilter/ip_nat_sip.c
+++ b/net/ipv4/netfilter/ip_nat_sip.c
@@ -29,27 +29,70 @@ MODULE_DESCRIPTION("SIP NAT helper");
#define DEBUGP(format, args...)
#endif
-extern struct sip_header_nfo ct_sip_hdrs[];
+struct addr_map {
+ struct {
+ char src[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
+ char dst[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
+ unsigned int srclen, srciplen;
+ unsigned int dstlen, dstiplen;
+ } addr[IP_CT_DIR_MAX];
+};
+
+static void addr_map_init(struct ip_conntrack *ct, struct addr_map *map)
+{
+ struct ip_conntrack_tuple *t;
+ enum ip_conntrack_dir dir;
+ unsigned int n;
+
+ for (dir = 0; dir < IP_CT_DIR_MAX; dir++) {
+ t = &ct->tuplehash[dir].tuple;
+
+ n = sprintf(map->addr[dir].src, "%u.%u.%u.%u",
+ NIPQUAD(t->src.ip));
+ map->addr[dir].srciplen = n;
+ n += sprintf(map->addr[dir].src + n, ":%u",
+ ntohs(t->src.u.udp.port));
+ map->addr[dir].srclen = n;
+
+ n = sprintf(map->addr[dir].dst, "%u.%u.%u.%u",
+ NIPQUAD(t->dst.ip));
+ map->addr[dir].dstiplen = n;
+ n += sprintf(map->addr[dir].dst + n, ":%u",
+ ntohs(t->dst.u.udp.port));
+ map->addr[dir].dstlen = n;
+ }
+}
-static unsigned int mangle_sip_packet(struct sk_buff **pskb,
- enum ip_conntrack_info ctinfo,
- struct ip_conntrack *ct,
- const char **dptr, size_t dlen,
- char *buffer, int bufflen,
- struct sip_header_nfo *hnfo)
+static int map_sip_addr(struct sk_buff **pskb, enum ip_conntrack_info ctinfo,
+ struct ip_conntrack *ct, const char **dptr, size_t dlen,
+ enum sip_header_pos pos, struct addr_map *map)
{
- unsigned int matchlen, matchoff;
+ enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+ unsigned int matchlen, matchoff, addrlen;
+ char *addr;
- if (ct_sip_get_info(*dptr, dlen, &matchoff, &matchlen, hnfo) <= 0)
- return 0;
+ if (ct_sip_get_info(*dptr, dlen, &matchoff, &matchlen, pos) <= 0)
+ return 1;
+
+ if ((matchlen == map->addr[dir].srciplen ||
+ matchlen == map->addr[dir].srclen) &&
+ memcmp(*dptr + matchoff, map->addr[dir].src, matchlen) == 0) {
+ addr = map->addr[!dir].dst;
+ addrlen = map->addr[!dir].dstlen;
+ } else if ((matchlen == map->addr[dir].dstiplen ||
+ matchlen == map->addr[dir].dstlen) &&
+ memcmp(*dptr + matchoff, map->addr[dir].dst, matchlen) == 0) {
+ addr = map->addr[!dir].src;
+ addrlen = map->addr[!dir].srclen;
+ } else
+ return 1;
if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
- matchoff, matchlen, buffer, bufflen))
+ matchoff, matchlen, addr, addrlen))
return 0;
-
- /* We need to reload this. Thanks Patrick. */
*dptr = (*pskb)->data + (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
return 1;
+
}
static unsigned int ip_nat_sip(struct sk_buff **pskb,
@@ -57,70 +100,61 @@ static unsigned int ip_nat_sip(struct sk_buff **pskb,
struct ip_conntrack *ct,
const char **dptr)
{
- enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
- char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
- unsigned int bufflen, dataoff;
- __be32 ip;
- __be16 port;
+ enum sip_header_pos pos;
+ struct addr_map map;
+ int dataoff, datalen;
dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
+ datalen = (*pskb)->len - dataoff;
+ if (datalen < sizeof("SIP/2.0") - 1)
+ return NF_DROP;
+
+ addr_map_init(ct, &map);
+
+ /* Basic rules: requests and responses. */
+ if (strncmp(*dptr, "SIP/2.0", sizeof("SIP/2.0") - 1) != 0) {
+ /* 10.2: Constructing the REGISTER Request:
+ *
+ * The "userinfo" and "@" components of the SIP URI MUST NOT
+ * be present.
+ */
+ if (datalen >= sizeof("REGISTER") - 1 &&
+ strncmp(*dptr, "REGISTER", sizeof("REGISTER") - 1) == 0)
+ pos = POS_REG_REQ_URI;
+ else
+ pos = POS_REQ_URI;
+
+ if (!map_sip_addr(pskb, ctinfo, ct, dptr, datalen, pos, &map))
+ return NF_DROP;
+ }
+
+ if (!map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_FROM, &map) ||
+ !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_TO, &map) ||
+ !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_VIA, &map) ||
+ !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_CONTACT, &map))
+ return NF_DROP;
+ return NF_ACCEPT;
+}
- ip = ct->tuplehash[!dir].tuple.dst.ip;
- port = ct->tuplehash[!dir].tuple.dst.u.udp.port;
- bufflen = sprintf(buffer, "%u.%u.%u.%u:%u", NIPQUAD(ip), ntohs(port));
+static unsigned int mangle_sip_packet(struct sk_buff **pskb,
+ enum ip_conntrack_info ctinfo,
+ struct ip_conntrack *ct,
+ const char **dptr, size_t dlen,
+ char *buffer, int bufflen,
+ enum sip_header_pos pos)
+{
+ unsigned int matchlen, matchoff;
- /* short packet ? */
- if (((*pskb)->len - dataoff) < (sizeof("SIP/2.0") - 1))
+ if (ct_sip_get_info(*dptr, dlen, &matchoff, &matchlen, pos) <= 0)
return 0;
- /* Basic rules: requests and responses. */
- if (memcmp(*dptr, "SIP/2.0", sizeof("SIP/2.0") - 1) == 0) {
- const char *aux;
-
- if ((ctinfo) < IP_CT_IS_REPLY) {
- mangle_sip_packet(pskb, ctinfo, ct, dptr,
- (*pskb)->len - dataoff,
- buffer, bufflen,
- &ct_sip_hdrs[POS_CONTACT]);
- return 1;
- }
+ if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
+ matchoff, matchlen, buffer, bufflen))
+ return 0;
- if (!mangle_sip_packet(pskb, ctinfo, ct, dptr,
- (*pskb)->len - dataoff,
- buffer, bufflen, &ct_sip_hdrs[POS_VIA]))
- return 0;
-
- /* This search should ignore case, but later.. */
- aux = ct_sip_search("CSeq:", *dptr, sizeof("CSeq:") - 1,
- (*pskb)->len - dataoff);
- if (!aux)
- return 0;
-
- if (!ct_sip_search("REGISTER", aux, sizeof("REGISTER"),
- ct_sip_lnlen(aux, *dptr + (*pskb)->len - dataoff)))
- return 1;
-
- return mangle_sip_packet(pskb, ctinfo, ct, dptr,
- (*pskb)->len - dataoff,
- buffer, bufflen,
- &ct_sip_hdrs[POS_CONTACT]);
- }
- if ((ctinfo) < IP_CT_IS_REPLY) {
- if (!mangle_sip_packet(pskb, ctinfo, ct, dptr,
- (*pskb)->len - dataoff,
- buffer, bufflen, &ct_sip_hdrs[POS_VIA]))
- return 0;
-
- /* Mangle Contact if exists only. - watch udp_nat_mangle()! */
- mangle_sip_packet(pskb, ctinfo, ct, dptr, (*pskb)->len - dataoff,
- buffer, bufflen, &ct_sip_hdrs[POS_CONTACT]);
- return 1;
- }
- /* This mangle requests headers. */
- return mangle_sip_packet(pskb, ctinfo, ct, dptr,
- ct_sip_lnlen(*dptr,
- *dptr + (*pskb)->len - dataoff),
- buffer, bufflen, &ct_sip_hdrs[POS_REQ_HEADER]);
+ /* We need to reload this. Thanks Patrick. */
+ *dptr = (*pskb)->data + (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
+ return 1;
}
static int mangle_content_len(struct sk_buff **pskb,
@@ -136,7 +170,7 @@ static int mangle_content_len(struct sk_buff **pskb,
/* Get actual SDP lenght */
if (ct_sip_get_info(dptr, (*pskb)->len - dataoff, &matchoff,
- &matchlen, &ct_sip_hdrs[POS_SDP_HEADER]) > 0) {
+ &matchlen, POS_SDP_HEADER) > 0) {
/* since ct_sip_get_info() give us a pointer passing 'v='
we need to add 2 bytes in this count. */
@@ -144,7 +178,7 @@ static int mangle_content_len(struct sk_buff **pskb,
/* Now, update SDP lenght */
if (ct_sip_get_info(dptr, (*pskb)->len - dataoff, &matchoff,
- &matchlen, &ct_sip_hdrs[POS_CONTENT]) > 0) {
+ &matchlen, POS_CONTENT) > 0) {
bufflen = sprintf(buffer, "%u", c_len);
@@ -170,17 +204,17 @@ static unsigned int mangle_sdp(struct sk_buff **pskb,
/* Mangle owner and contact info. */
bufflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(newip));
if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
- buffer, bufflen, &ct_sip_hdrs[POS_OWNER]))
+ buffer, bufflen, POS_OWNER))
return 0;
if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
- buffer, bufflen, &ct_sip_hdrs[POS_CONNECTION]))
+ buffer, bufflen, POS_CONNECTION))
return 0;
/* Mangle media port. */
bufflen = sprintf(buffer, "%u", port);
if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
- buffer, bufflen, &ct_sip_hdrs[POS_MEDIA]))
+ buffer, bufflen, POS_MEDIA))
return 0;
return mangle_content_len(pskb, ctinfo, ct, dptr);
@@ -230,18 +264,17 @@ static unsigned int ip_nat_sdp(struct sk_buff **pskb,
static void __exit fini(void)
{
- ip_nat_sip_hook = NULL;
- ip_nat_sdp_hook = NULL;
- /* Make sure noone calls it, meanwhile. */
- synchronize_net();
+ rcu_assign_pointer(ip_nat_sip_hook, NULL);
+ rcu_assign_pointer(ip_nat_sdp_hook, NULL);
+ synchronize_rcu();
}
static int __init init(void)
{
- BUG_ON(ip_nat_sip_hook);
- BUG_ON(ip_nat_sdp_hook);
- ip_nat_sip_hook = ip_nat_sip;
- ip_nat_sdp_hook = ip_nat_sdp;
+ BUG_ON(rcu_dereference(ip_nat_sip_hook));
+ BUG_ON(rcu_dereference(ip_nat_sdp_hook));
+ rcu_assign_pointer(ip_nat_sip_hook, ip_nat_sip);
+ rcu_assign_pointer(ip_nat_sdp_hook, ip_nat_sdp);
return 0;
}
diff --git a/net/ipv4/netfilter/ip_nat_snmp_basic.c b/net/ipv4/netfilter/ip_nat_snmp_basic.c
index 168f45fa1898..c3d9f3b090c4 100644
--- a/net/ipv4/netfilter/ip_nat_snmp_basic.c
+++ b/net/ipv4/netfilter/ip_nat_snmp_basic.c
@@ -64,7 +64,7 @@ MODULE_DESCRIPTION("Basic SNMP Application Layer Gateway");
#define SNMP_PORT 161
#define SNMP_TRAP_PORT 162
-#define NOCT1(n) (u_int8_t )((n) & 0xff)
+#define NOCT1(n) (*(u8 *)n)
static int debug;
static DEFINE_SPINLOCK(snmp_lock);
@@ -613,7 +613,7 @@ struct snmp_v1_trap
static inline void mangle_address(unsigned char *begin,
unsigned char *addr,
const struct oct1_map *map,
- u_int16_t *check);
+ __sum16 *check);
struct snmp_cnv
{
unsigned int class;
@@ -873,38 +873,24 @@ static unsigned char snmp_request_decode(struct asn1_ctx *ctx,
* Fast checksum update for possibly oddly-aligned UDP byte, from the
* code example in the draft.
*/
-static void fast_csum(unsigned char *csum,
+static void fast_csum(__sum16 *csum,
const unsigned char *optr,
const unsigned char *nptr,
- int odd)
+ int offset)
{
- long x, old, new;
-
- x = csum[0] * 256 + csum[1];
-
- x =~ x & 0xFFFF;
-
- if (odd) old = optr[0] * 256;
- else old = optr[0];
-
- x -= old & 0xFFFF;
- if (x <= 0) {
- x--;
- x &= 0xFFFF;
- }
-
- if (odd) new = nptr[0] * 256;
- else new = nptr[0];
-
- x += new & 0xFFFF;
- if (x & 0x10000) {
- x++;
- x &= 0xFFFF;
+ unsigned char s[4];
+
+ if (offset & 1) {
+ s[0] = s[2] = 0;
+ s[1] = ~*optr;
+ s[3] = *nptr;
+ } else {
+ s[1] = s[3] = 0;
+ s[0] = ~*optr;
+ s[2] = *nptr;
}
-
- x =~ x & 0xFFFF;
- csum[0] = x / 256;
- csum[1] = x & 0xFF;
+
+ *csum = csum_fold(csum_partial(s, 4, ~csum_unfold(*csum)));
}
/*
@@ -915,9 +901,9 @@ static void fast_csum(unsigned char *csum,
static inline void mangle_address(unsigned char *begin,
unsigned char *addr,
const struct oct1_map *map,
- u_int16_t *check)
+ __sum16 *check)
{
- if (map->from == NOCT1(*addr)) {
+ if (map->from == NOCT1(addr)) {
u_int32_t old;
if (debug)
@@ -927,11 +913,8 @@ static inline void mangle_address(unsigned char *begin,
/* Update UDP checksum if being used */
if (*check) {
- unsigned char odd = !((addr - begin) % 2);
-
- fast_csum((unsigned char *)check,
- &map->from, &map->to, odd);
-
+ fast_csum(check,
+ &map->from, &map->to, addr - begin);
}
if (debug)
@@ -943,7 +926,7 @@ static inline void mangle_address(unsigned char *begin,
static unsigned char snmp_trap_decode(struct asn1_ctx *ctx,
struct snmp_v1_trap *trap,
const struct oct1_map *map,
- u_int16_t *check)
+ __sum16 *check)
{
unsigned int cls, con, tag, len;
unsigned char *end;
@@ -1037,7 +1020,7 @@ static void hex_dump(unsigned char *buf, size_t len)
static int snmp_parse_mangle(unsigned char *msg,
u_int16_t len,
const struct oct1_map *map,
- u_int16_t *check)
+ __sum16 *check)
{
unsigned char *eoc, *end;
unsigned int cls, con, tag, vers, pdutype;
@@ -1223,12 +1206,12 @@ static int snmp_translate(struct ip_conntrack *ct,
*/
if (dir == IP_CT_DIR_ORIGINAL) {
/* SNAT traps */
- map.from = NOCT1(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip);
- map.to = NOCT1(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip);
+ map.from = NOCT1(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip);
+ map.to = NOCT1(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip);
} else {
/* DNAT replies */
- map.from = NOCT1(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip);
- map.to = NOCT1(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip);
+ map.from = NOCT1(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip);
+ map.to = NOCT1(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip);
}
if (map.from == map.to)
@@ -1294,11 +1277,11 @@ static struct ip_conntrack_helper snmp_helper = {
.help = help,
.name = "snmp",
- .tuple = { .src = { .u = { __constant_htons(SNMP_PORT) } },
- .dst = { .protonum = IPPROTO_UDP },
+ .tuple = {.src = {.u = {.udp = {.port = __constant_htons(SNMP_PORT)}}},
+ .dst = {.protonum = IPPROTO_UDP},
},
- .mask = { .src = { .u = { 0xFFFF } },
- .dst = { .protonum = 0xFF },
+ .mask = {.src = {.u = {0xFFFF}},
+ .dst = {.protonum = 0xFF},
},
};
@@ -1309,11 +1292,11 @@ static struct ip_conntrack_helper snmp_trap_helper = {
.help = help,
.name = "snmp_trap",
- .tuple = { .src = { .u = { __constant_htons(SNMP_TRAP_PORT) } },
- .dst = { .protonum = IPPROTO_UDP },
+ .tuple = {.src = {.u = {.udp = {.port = __constant_htons(SNMP_TRAP_PORT)}}},
+ .dst = {.protonum = IPPROTO_UDP},
},
- .mask = { .src = { .u = { 0xFFFF } },
- .dst = { .protonum = 0xFF },
+ .mask = {.src = {.u = {0xFFFF}},
+ .dst = {.protonum = 0xFF},
},
};
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index d85d2de50449..ad66328baa5d 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -44,12 +44,6 @@
#define DEBUGP(format, args...)
#endif
-#define HOOKNAME(hooknum) ((hooknum) == NF_IP_POST_ROUTING ? "POST_ROUTING" \
- : ((hooknum) == NF_IP_PRE_ROUTING ? "PRE_ROUTING" \
- : ((hooknum) == NF_IP_LOCAL_OUT ? "LOCAL_OUT" \
- : ((hooknum) == NF_IP_LOCAL_IN ? "LOCAL_IN" \
- : "*ERROR*")))
-
#ifdef CONFIG_XFRM
static void nat_decode_session(struct sk_buff *skb, struct flowi *fl)
{
diff --git a/net/ipv4/netfilter/ip_nat_tftp.c b/net/ipv4/netfilter/ip_nat_tftp.c
index 94a78015451c..604793536fc1 100644
--- a/net/ipv4/netfilter/ip_nat_tftp.c
+++ b/net/ipv4/netfilter/ip_nat_tftp.c
@@ -55,15 +55,14 @@ static unsigned int help(struct sk_buff **pskb,
static void __exit ip_nat_tftp_fini(void)
{
- ip_nat_tftp_hook = NULL;
- /* Make sure noone calls it, meanwhile. */
- synchronize_net();
+ rcu_assign_pointer(ip_nat_tftp_hook, NULL);
+ synchronize_rcu();
}
static int __init ip_nat_tftp_init(void)
{
- BUG_ON(ip_nat_tftp_hook);
- ip_nat_tftp_hook = help;
+ BUG_ON(rcu_dereference(ip_nat_tftp_hook));
+ rcu_assign_pointer(ip_nat_tftp_hook, help);
return 0;
}
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index 97556cc2e4e0..cd520df4dcf4 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -243,7 +243,7 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp)
pmsg->data_len = data_len;
pmsg->timestamp_sec = entry->skb->tstamp.off_sec;
pmsg->timestamp_usec = entry->skb->tstamp.off_usec;
- pmsg->mark = entry->skb->nfmark;
+ pmsg->mark = entry->skb->mark;
pmsg->hook = entry->info->hook;
pmsg->hw_protocol = entry->skb->protocol;
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 7a29d6e7baa7..098365062234 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -40,8 +40,6 @@
#define DEBUGP
#endif
-#define ASSERT_READ_LOCK(x)
-
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
MODULE_DESCRIPTION("iptables target for CLUSTERIP");
@@ -123,7 +121,6 @@ __clusterip_config_find(__be32 clusterip)
{
struct list_head *pos;
- ASSERT_READ_LOCK(&clusterip_lock);
list_for_each(pos, &clusterip_configs) {
struct clusterip_config *c = list_entry(pos,
struct clusterip_config, list);
@@ -170,7 +167,6 @@ clusterip_config_init(struct ipt_clusterip_tgt_info *i, __be32 ip,
struct net_device *dev)
{
struct clusterip_config *c;
- char buffer[16];
c = kzalloc(sizeof(*c), GFP_ATOMIC);
if (!c)
@@ -187,12 +183,17 @@ clusterip_config_init(struct ipt_clusterip_tgt_info *i, __be32 ip,
atomic_set(&c->entries, 1);
#ifdef CONFIG_PROC_FS
- /* create proc dir entry */
- sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(ip));
- c->pde = create_proc_entry(buffer, S_IWUSR|S_IRUSR, clusterip_procdir);
- if (!c->pde) {
- kfree(c);
- return NULL;
+ {
+ char buffer[16];
+
+ /* create proc dir entry */
+ sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(ip));
+ c->pde = create_proc_entry(buffer, S_IWUSR|S_IRUSR,
+ clusterip_procdir);
+ if (!c->pde) {
+ kfree(c);
+ return NULL;
+ }
}
c->pde->proc_fops = &clusterip_proc_fops;
c->pde->data = c;
@@ -205,6 +206,7 @@ clusterip_config_init(struct ipt_clusterip_tgt_info *i, __be32 ip,
return c;
}
+#ifdef CONFIG_PROC_FS
static int
clusterip_add_node(struct clusterip_config *c, u_int16_t nodenum)
{
@@ -232,6 +234,7 @@ clusterip_del_node(struct clusterip_config *c, u_int16_t nodenum)
return 1;
}
+#endif
static inline u_int32_t
clusterip_hashfn(struct sk_buff *skb, struct clusterip_config *config)
@@ -737,8 +740,10 @@ static int __init ipt_clusterip_init(void)
CLUSTERIP_VERSION);
return 0;
+#ifdef CONFIG_PROC_FS
cleanup_hook:
nf_unregister_hook(&cip_arp_ops);
+#endif /* CONFIG_PROC_FS */
cleanup_target:
ipt_unregister_target(&clusterip_tgt);
return ret;
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c
index 1aa4517fbcdb..b55d670a24df 100644
--- a/net/ipv4/netfilter/ipt_ECN.c
+++ b/net/ipv4/netfilter/ipt_ECN.c
@@ -28,17 +28,16 @@ static inline int
set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
{
struct iphdr *iph = (*pskb)->nh.iph;
- u_int16_t oldtos;
if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) {
+ __u8 oldtos;
if (!skb_make_writable(pskb, sizeof(struct iphdr)))
return 0;
iph = (*pskb)->nh.iph;
oldtos = iph->tos;
iph->tos &= ~IPT_ECN_IP_MASK;
iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK);
- iph->check = nf_csum_update(htons(oldtos) ^ htons(0xFFFF),
- htons(iph->tos), iph->check);
+ nf_csum_replace2(&iph->check, htons(oldtos), htons(iph->tos));
}
return 1;
}
@@ -72,10 +71,8 @@ set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
if (einfo->operation & IPT_ECN_OP_SET_CWR)
tcph->cwr = einfo->proto.tcp.cwr;
- tcph->check = nf_proto_csum_update((*pskb),
- oldval ^ htons(0xFFFF),
- ((__be16 *)tcph)[6],
- tcph->check, 0);
+ nf_proto_csum_replace2(&tcph->check, *pskb,
+ oldval, ((__be16 *)tcph)[6], 0);
return 1;
}
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
index 7dc820df8bc5..c96de16fefae 100644
--- a/net/ipv4/netfilter/ipt_LOG.c
+++ b/net/ipv4/netfilter/ipt_LOG.c
@@ -171,11 +171,15 @@ static void dump_packet(const struct nf_loginfo *info,
}
break;
}
- case IPPROTO_UDP: {
+ case IPPROTO_UDP:
+ case IPPROTO_UDPLITE: {
struct udphdr _udph, *uh;
- /* Max length: 10 "PROTO=UDP " */
- printk("PROTO=UDP ");
+ if (ih->protocol == IPPROTO_UDP)
+ /* Max length: 10 "PROTO=UDP " */
+ printk("PROTO=UDP " );
+ else /* Max length: 14 "PROTO=UDPLITE " */
+ printk("PROTO=UDPLITE ");
if (ntohs(ih->frag_off) & IP_OFFSET)
break;
@@ -341,6 +345,7 @@ static void dump_packet(const struct nf_loginfo *info,
/* IP: 40+46+6+11+127 = 230 */
/* TCP: 10+max(25,20+30+13+9+32+11+127) = 252 */
/* UDP: 10+max(25,20) = 35 */
+ /* UDPLITE: 14+max(25,20) = 39 */
/* ICMP: 11+max(25, 18+25+max(19,14,24+3+n+10,3+n+10)) = 91+n */
/* ESP: 10+max(25)+15 = 50 */
/* AH: 9+max(25)+15 = 49 */
@@ -425,13 +430,8 @@ ipt_log_target(struct sk_buff **pskb,
li.u.log.level = loginfo->level;
li.u.log.logflags = loginfo->logflags;
- if (loginfo->logflags & IPT_LOG_NFLOG)
- nf_log_packet(PF_INET, hooknum, *pskb, in, out, &li,
- "%s", loginfo->prefix);
- else
- ipt_log_packet(PF_INET, hooknum, *pskb, in, out, &li,
- loginfo->prefix);
-
+ ipt_log_packet(PF_INET, hooknum, *pskb, in, out, &li,
+ loginfo->prefix);
return IPT_CONTINUE;
}
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index 3dbfcfac8a84..28b9233956b5 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -2,7 +2,7 @@
(depending on route). */
/* (C) 1999-2001 Paul `Rusty' Russell
- * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
+ * (C) 2002-2006 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
@@ -20,7 +20,11 @@
#include <net/checksum.h>
#include <net/route.h>
#include <linux/netfilter_ipv4.h>
+#ifdef CONFIG_NF_NAT_NEEDED
+#include <net/netfilter/nf_nat_rule.h>
+#else
#include <linux/netfilter_ipv4/ip_nat_rule.h>
+#endif
#include <linux/netfilter_ipv4/ip_tables.h>
MODULE_LICENSE("GPL");
@@ -65,23 +69,33 @@ masquerade_target(struct sk_buff **pskb,
const struct xt_target *target,
const void *targinfo)
{
+#ifdef CONFIG_NF_NAT_NEEDED
+ struct nf_conn_nat *nat;
+#endif
struct ip_conntrack *ct;
enum ip_conntrack_info ctinfo;
- const struct ip_nat_multi_range_compat *mr;
struct ip_nat_range newrange;
+ const struct ip_nat_multi_range_compat *mr;
struct rtable *rt;
__be32 newsrc;
IP_NF_ASSERT(hooknum == NF_IP_POST_ROUTING);
ct = ip_conntrack_get(*pskb, &ctinfo);
+#ifdef CONFIG_NF_NAT_NEEDED
+ nat = nfct_nat(ct);
+#endif
IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED
|| ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY));
/* Source address is 0.0.0.0 - locally generated packet that is
* probably not supposed to be masqueraded.
*/
+#ifdef CONFIG_NF_NAT_NEEDED
+ if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip == 0)
+#else
if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip == 0)
+#endif
return NF_ACCEPT;
mr = targinfo;
@@ -93,7 +107,11 @@ masquerade_target(struct sk_buff **pskb,
}
write_lock_bh(&masq_lock);
+#ifdef CONFIG_NF_NAT_NEEDED
+ nat->masq_index = out->ifindex;
+#else
ct->nat.masq_index = out->ifindex;
+#endif
write_unlock_bh(&masq_lock);
/* Transfer from original range. */
@@ -109,10 +127,17 @@ masquerade_target(struct sk_buff **pskb,
static inline int
device_cmp(struct ip_conntrack *i, void *ifindex)
{
+#ifdef CONFIG_NF_NAT_NEEDED
+ struct nf_conn_nat *nat = nfct_nat(i);
+#endif
int ret;
read_lock_bh(&masq_lock);
+#ifdef CONFIG_NF_NAT_NEEDED
+ ret = (nat->masq_index == (int)(long)ifindex);
+#else
ret = (i->nat.masq_index == (int)(long)ifindex);
+#endif
read_unlock_bh(&masq_lock);
return ret;
diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c
index 58a88f227108..9390e90f2b25 100644
--- a/net/ipv4/netfilter/ipt_NETMAP.c
+++ b/net/ipv4/netfilter/ipt_NETMAP.c
@@ -15,7 +15,11 @@
#include <linux/netdevice.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
+#ifdef CONFIG_NF_NAT_NEEDED
+#include <net/netfilter/nf_nat_rule.h>
+#else
#include <linux/netfilter_ipv4/ip_nat_rule.h>
+#endif
#define MODULENAME "NETMAP"
MODULE_LICENSE("GPL");
diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c
index c0dcfe9d610c..462eceb3a1b1 100644
--- a/net/ipv4/netfilter/ipt_REDIRECT.c
+++ b/net/ipv4/netfilter/ipt_REDIRECT.c
@@ -1,6 +1,6 @@
/* Redirect. Simple mapping which alters dst to a local IP address. */
/* (C) 1999-2001 Paul `Rusty' Russell
- * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
+ * (C) 2002-2006 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
@@ -18,7 +18,11 @@
#include <net/protocol.h>
#include <net/checksum.h>
#include <linux/netfilter_ipv4.h>
+#ifdef CONFIG_NF_NAT_NEEDED
+#include <net/netfilter/nf_nat_rule.h>
+#else
#include <linux/netfilter_ipv4/ip_nat_rule.h>
+#endif
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index ad0312d0e4fd..f0319e5ee437 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -76,7 +76,7 @@ static void send_reset(struct sk_buff *oldskb, int hook)
/* This packet will not be the same as the other: clear nf fields */
nf_reset(nskb);
- nskb->nfmark = 0;
+ nskb->mark = 0;
skb_init_secmark(nskb);
tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
@@ -114,6 +114,14 @@ static void send_reset(struct sk_buff *oldskb, int hook)
tcph->window = 0;
tcph->urg_ptr = 0;
+ /* Adjust TCP checksum */
+ tcph->check = 0;
+ tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr),
+ nskb->nh.iph->saddr,
+ nskb->nh.iph->daddr,
+ csum_partial((char *)tcph,
+ sizeof(struct tcphdr), 0));
+
/* Set DF, id = 0 */
nskb->nh.iph->frag_off = htons(IP_DF);
nskb->nh.iph->id = 0;
@@ -129,14 +137,8 @@ static void send_reset(struct sk_buff *oldskb, int hook)
if (ip_route_me_harder(&nskb, addr_type))
goto free_nskb;
- /* Adjust TCP checksum */
nskb->ip_summed = CHECKSUM_NONE;
- tcph->check = 0;
- tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr),
- nskb->nh.iph->saddr,
- nskb->nh.iph->daddr,
- csum_partial((char *)tcph,
- sizeof(struct tcphdr), 0));
+
/* Adjust IP TTL */
nskb->nh.iph->ttl = dst_metric(nskb->dst, RTAX_HOPLIMIT);
diff --git a/net/ipv4/netfilter/ipt_SAME.c b/net/ipv4/netfilter/ipt_SAME.c
index b38b13328d73..3dcf29411337 100644
--- a/net/ipv4/netfilter/ipt_SAME.c
+++ b/net/ipv4/netfilter/ipt_SAME.c
@@ -34,7 +34,11 @@
#include <net/protocol.h>
#include <net/checksum.h>
#include <linux/netfilter_ipv4.h>
+#ifdef CONFIG_NF_NAT_NEEDED
+#include <net/netfilter/nf_nat_rule.h>
+#else
#include <linux/netfilter_ipv4/ip_nat_rule.h>
+#endif
#include <linux/netfilter_ipv4/ipt_SAME.h>
MODULE_LICENSE("GPL");
@@ -152,11 +156,17 @@ same_target(struct sk_buff **pskb,
Here we calculate the index in same->iparray which
holds the ipaddress we should use */
+#ifdef CONFIG_NF_NAT_NEEDED
+ tmpip = ntohl(t->src.u3.ip);
+
+ if (!(same->info & IPT_SAME_NODST))
+ tmpip += ntohl(t->dst.u3.ip);
+#else
tmpip = ntohl(t->src.ip);
if (!(same->info & IPT_SAME_NODST))
tmpip += ntohl(t->dst.ip);
-
+#endif
aindex = tmpip % same->ipnum;
new_ip = htonl(same->iparray[aindex]);
diff --git a/net/ipv4/netfilter/ipt_TCPMSS.c b/net/ipv4/netfilter/ipt_TCPMSS.c
index 108b6b76311f..93eb5c3c1884 100644
--- a/net/ipv4/netfilter/ipt_TCPMSS.c
+++ b/net/ipv4/netfilter/ipt_TCPMSS.c
@@ -97,10 +97,8 @@ ipt_tcpmss_target(struct sk_buff **pskb,
opt[i+2] = (newmss & 0xff00) >> 8;
opt[i+3] = (newmss & 0x00ff);
- tcph->check = nf_proto_csum_update(*pskb,
- htons(oldmss)^htons(0xFFFF),
- htons(newmss),
- tcph->check, 0);
+ nf_proto_csum_replace2(&tcph->check, *pskb,
+ htons(oldmss), htons(newmss), 0);
return IPT_CONTINUE;
}
}
@@ -126,28 +124,22 @@ ipt_tcpmss_target(struct sk_buff **pskb,
opt = (u_int8_t *)tcph + sizeof(struct tcphdr);
memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr));
- tcph->check = nf_proto_csum_update(*pskb,
- htons(tcplen) ^ htons(0xFFFF),
- htons(tcplen + TCPOLEN_MSS),
- tcph->check, 1);
+ nf_proto_csum_replace2(&tcph->check, *pskb,
+ htons(tcplen), htons(tcplen + TCPOLEN_MSS), 1);
opt[0] = TCPOPT_MSS;
opt[1] = TCPOLEN_MSS;
opt[2] = (newmss & 0xff00) >> 8;
opt[3] = (newmss & 0x00ff);
- tcph->check = nf_proto_csum_update(*pskb, htonl(~0), *((__be32 *)opt),
- tcph->check, 0);
+ nf_proto_csum_replace4(&tcph->check, *pskb, 0, *((__be32 *)opt), 0);
oldval = ((__be16 *)tcph)[6];
tcph->doff += TCPOLEN_MSS/4;
- tcph->check = nf_proto_csum_update(*pskb,
- oldval ^ htons(0xFFFF),
- ((__be16 *)tcph)[6],
- tcph->check, 0);
+ nf_proto_csum_replace2(&tcph->check, *pskb,
+ oldval, ((__be16 *)tcph)[6], 0);
newtotlen = htons(ntohs(iph->tot_len) + TCPOLEN_MSS);
- iph->check = nf_csum_update(iph->tot_len ^ htons(0xFFFF),
- newtotlen, iph->check);
+ nf_csum_replace2(&iph->check, iph->tot_len, newtotlen);
iph->tot_len = newtotlen;
return IPT_CONTINUE;
}
diff --git a/net/ipv4/netfilter/ipt_TOS.c b/net/ipv4/netfilter/ipt_TOS.c
index 83b80b3a5d2f..18e74ac4d425 100644
--- a/net/ipv4/netfilter/ipt_TOS.c
+++ b/net/ipv4/netfilter/ipt_TOS.c
@@ -30,16 +30,15 @@ target(struct sk_buff **pskb,
{
const struct ipt_tos_target_info *tosinfo = targinfo;
struct iphdr *iph = (*pskb)->nh.iph;
- u_int16_t oldtos;
if ((iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) {
+ __u8 oldtos;
if (!skb_make_writable(pskb, sizeof(struct iphdr)))
return NF_DROP;
iph = (*pskb)->nh.iph;
oldtos = iph->tos;
iph->tos = (iph->tos & IPTOS_PREC_MASK) | tosinfo->tos;
- iph->check = nf_csum_update(htons(oldtos) ^ htons(0xFFFF),
- htons(iph->tos), iph->check);
+ nf_csum_replace2(&iph->check, htons(oldtos), htons(iph->tos));
}
return IPT_CONTINUE;
}
diff --git a/net/ipv4/netfilter/ipt_TTL.c b/net/ipv4/netfilter/ipt_TTL.c
index ac9517d62af0..fffe5ca82e91 100644
--- a/net/ipv4/netfilter/ipt_TTL.c
+++ b/net/ipv4/netfilter/ipt_TTL.c
@@ -54,9 +54,8 @@ ipt_ttl_target(struct sk_buff **pskb,
}
if (new_ttl != iph->ttl) {
- iph->check = nf_csum_update(htons((iph->ttl << 8)) ^ htons(0xFFFF),
- htons(new_ttl << 8),
- iph->check);
+ nf_csum_replace2(&iph->check, htons(iph->ttl << 8),
+ htons(new_ttl << 8));
iph->ttl = new_ttl;
}
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index 2b104ea54f48..dbd34783a64d 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -239,7 +239,7 @@ static void ipt_ulog_packet(unsigned int hooknum,
pm->data_len = copy_len;
pm->timestamp_sec = skb->tstamp.off_sec;
pm->timestamp_usec = skb->tstamp.off_usec;
- pm->mark = skb->nfmark;
+ pm->mark = skb->mark;
pm->hook = hooknum;
if (prefix != NULL)
strncpy(pm->prefix, prefix, sizeof(pm->prefix));
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index b91f3582359b..af2939889444 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -132,7 +132,7 @@ ipt_local_hook(unsigned int hook,
unsigned int ret;
u_int8_t tos;
__be32 saddr, daddr;
- unsigned long nfmark;
+ u_int32_t mark;
/* root is playing with raw sockets. */
if ((*pskb)->len < sizeof(struct iphdr)
@@ -143,7 +143,7 @@ ipt_local_hook(unsigned int hook,
}
/* Save things which could affect route */
- nfmark = (*pskb)->nfmark;
+ mark = (*pskb)->mark;
saddr = (*pskb)->nh.iph->saddr;
daddr = (*pskb)->nh.iph->daddr;
tos = (*pskb)->nh.iph->tos;
@@ -153,9 +153,7 @@ ipt_local_hook(unsigned int hook,
if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE
&& ((*pskb)->nh.iph->saddr != saddr
|| (*pskb)->nh.iph->daddr != daddr
-#ifdef CONFIG_IP_ROUTE_FWMARK
- || (*pskb)->nfmark != nfmark
-#endif
+ || (*pskb)->mark != mark
|| (*pskb)->nh.iph->tos != tos))
if (ip_route_me_harder(pskb, RTN_UNSPEC))
ret = NF_DROP;
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index 0af803df82b0..471b638cedec 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -27,7 +27,7 @@
#include <linux/netfilter_ipv4.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_helper.h>
-#include <net/netfilter/nf_conntrack_protocol.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_l3proto.h>
#include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
@@ -38,12 +38,10 @@
#define DEBUGP(format, args...)
#endif
-DECLARE_PER_CPU(struct nf_conntrack_stat, nf_conntrack_stat);
-
static int ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
struct nf_conntrack_tuple *tuple)
{
- u_int32_t _addrs[2], *ap;
+ __be32 _addrs[2], *ap;
ap = skb_header_pointer(skb, nhoff + offsetof(struct iphdr, saddr),
sizeof(u_int32_t) * 2, _addrs);
if (ap == NULL)
@@ -113,10 +111,12 @@ ipv4_prepare(struct sk_buff **pskb, unsigned int hooknum, unsigned int *dataoff,
return NF_ACCEPT;
}
-int nat_module_is_loaded = 0;
+int nf_nat_module_is_loaded = 0;
+EXPORT_SYMBOL_GPL(nf_nat_module_is_loaded);
+
static u_int32_t ipv4_get_features(const struct nf_conntrack_tuple *tuple)
{
- if (nat_module_is_loaded)
+ if (nf_nat_module_is_loaded)
return NF_CT_F_NAT;
return NF_CT_F_BASIC;
@@ -268,43 +268,59 @@ static struct nf_hook_ops ipv4_conntrack_ops[] = {
},
};
-#ifdef CONFIG_SYSCTL
-/* From nf_conntrack_proto_icmp.c */
-extern unsigned int nf_ct_icmp_timeout;
-static struct ctl_table_header *nf_ct_ipv4_sysctl_header;
+#if defined(CONFIG_SYSCTL) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
+static int log_invalid_proto_min = 0;
+static int log_invalid_proto_max = 255;
-static ctl_table nf_ct_sysctl_table[] = {
+static ctl_table ip_ct_sysctl_table[] = {
{
- .ctl_name = NET_NF_CONNTRACK_ICMP_TIMEOUT,
- .procname = "nf_conntrack_icmp_timeout",
- .data = &nf_ct_icmp_timeout,
- .maxlen = sizeof(unsigned int),
+ .ctl_name = NET_IPV4_NF_CONNTRACK_MAX,
+ .procname = "ip_conntrack_max",
+ .data = &nf_conntrack_max,
+ .maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = &proc_dointvec_jiffies,
+ .proc_handler = &proc_dointvec,
},
- { .ctl_name = 0 }
-};
-
-static ctl_table nf_ct_netfilter_table[] = {
{
- .ctl_name = NET_NETFILTER,
- .procname = "netfilter",
- .mode = 0555,
- .child = nf_ct_sysctl_table,
+ .ctl_name = NET_IPV4_NF_CONNTRACK_COUNT,
+ .procname = "ip_conntrack_count",
+ .data = &nf_conntrack_count,
+ .maxlen = sizeof(int),
+ .mode = 0444,
+ .proc_handler = &proc_dointvec,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_BUCKETS,
+ .procname = "ip_conntrack_buckets",
+ .data = &nf_conntrack_htable_size,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0444,
+ .proc_handler = &proc_dointvec,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_CHECKSUM,
+ .procname = "ip_conntrack_checksum",
+ .data = &nf_conntrack_checksum,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
},
- { .ctl_name = 0 }
-};
-
-static ctl_table nf_ct_net_table[] = {
{
- .ctl_name = CTL_NET,
- .procname = "net",
- .mode = 0555,
- .child = nf_ct_netfilter_table,
+ .ctl_name = NET_IPV4_NF_CONNTRACK_LOG_INVALID,
+ .procname = "ip_conntrack_log_invalid",
+ .data = &nf_ct_log_invalid,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .strategy = &sysctl_intvec,
+ .extra1 = &log_invalid_proto_min,
+ .extra2 = &log_invalid_proto_max,
},
- { .ctl_name = 0 }
+ {
+ .ctl_name = 0
+ }
};
-#endif
+#endif /* CONFIG_SYSCTL && CONFIG_NF_CONNTRACK_PROC_COMPAT */
/* Fast function for those who don't want to parse /proc (and I don't
blame them). */
@@ -396,10 +412,8 @@ static int ipv4_nfattr_to_tuple(struct nfattr *tb[],
if (nfattr_bad_size(tb, CTA_IP_MAX, cta_min_ip))
return -EINVAL;
- t->src.u3.ip =
- *(u_int32_t *)NFA_DATA(tb[CTA_IP_V4_SRC-1]);
- t->dst.u3.ip =
- *(u_int32_t *)NFA_DATA(tb[CTA_IP_V4_DST-1]);
+ t->src.u3.ip = *(__be32 *)NFA_DATA(tb[CTA_IP_V4_SRC-1]);
+ t->dst.u3.ip = *(__be32 *)NFA_DATA(tb[CTA_IP_V4_DST-1]);
return 0;
}
@@ -426,14 +440,15 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 = {
.tuple_to_nfattr = ipv4_tuple_to_nfattr,
.nfattr_to_tuple = ipv4_nfattr_to_tuple,
#endif
+#if defined(CONFIG_SYSCTL) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
+ .ctl_table_path = nf_net_ipv4_netfilter_sysctl_path,
+ .ctl_table = ip_ct_sysctl_table,
+#endif
.me = THIS_MODULE,
};
-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;
-
MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET));
+MODULE_ALIAS("ip_conntrack");
MODULE_LICENSE("GPL");
static int __init nf_conntrack_l3proto_ipv4_init(void)
@@ -448,19 +463,19 @@ static int __init nf_conntrack_l3proto_ipv4_init(void)
return ret;
}
- ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp4);
+ ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_tcp4);
if (ret < 0) {
printk("nf_conntrack_ipv4: can't register tcp.\n");
goto cleanup_sockopt;
}
- ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_udp4);
+ ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udp4);
if (ret < 0) {
printk("nf_conntrack_ipv4: can't register udp.\n");
goto cleanup_tcp;
}
- ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_icmp);
+ ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_icmp);
if (ret < 0) {
printk("nf_conntrack_ipv4: can't register icmp.\n");
goto cleanup_udp;
@@ -478,28 +493,24 @@ static int __init nf_conntrack_l3proto_ipv4_init(void)
printk("nf_conntrack_ipv4: can't register hooks.\n");
goto cleanup_ipv4;
}
-#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;
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
+ ret = nf_conntrack_ipv4_compat_init();
+ if (ret < 0)
goto cleanup_hooks;
- }
#endif
return ret;
-
-#ifdef CONFIG_SYSCTL
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
cleanup_hooks:
- nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
+ nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
#endif
cleanup_ipv4:
nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
cleanup_icmp:
- nf_conntrack_protocol_unregister(&nf_conntrack_protocol_icmp);
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmp);
cleanup_udp:
- nf_conntrack_protocol_unregister(&nf_conntrack_protocol_udp4);
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp4);
cleanup_tcp:
- nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp4);
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp4);
cleanup_sockopt:
nf_unregister_sockopt(&so_getorigdst);
return ret;
@@ -508,18 +519,16 @@ static int __init nf_conntrack_l3proto_ipv4_init(void)
static void __exit nf_conntrack_l3proto_ipv4_fini(void)
{
synchronize_net();
-#ifdef CONFIG_SYSCTL
- unregister_sysctl_table(nf_ct_ipv4_sysctl_header);
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
+ nf_conntrack_ipv4_compat_fini();
#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_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmp);
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp4);
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp4);
nf_unregister_sockopt(&so_getorigdst);
}
module_init(nf_conntrack_l3proto_ipv4_init);
module_exit(nf_conntrack_l3proto_ipv4_fini);
-
-EXPORT_SYMBOL(nf_ct_ipv4_gather_frags);
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
new file mode 100644
index 000000000000..3b31bc649608
--- /dev/null
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
@@ -0,0 +1,412 @@
+/* ip_conntrack proc compat - based on ip_conntrack_standalone.c
+ *
+ * (C) 1999-2001 Paul `Rusty' Russell
+ * (C) 2002-2006 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/types.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/percpu.h>
+
+#include <linux/netfilter.h>
+#include <net/netfilter/nf_conntrack_core.h>
+#include <net/netfilter/nf_conntrack_l3proto.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
+#include <net/netfilter/nf_conntrack_expect.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+#ifdef CONFIG_NF_CT_ACCT
+static unsigned int
+seq_print_counters(struct seq_file *s,
+ const struct ip_conntrack_counter *counter)
+{
+ return seq_printf(s, "packets=%llu bytes=%llu ",
+ (unsigned long long)counter->packets,
+ (unsigned long long)counter->bytes);
+}
+#else
+#define seq_print_counters(x, y) 0
+#endif
+
+struct ct_iter_state {
+ unsigned int bucket;
+};
+
+static struct list_head *ct_get_first(struct seq_file *seq)
+{
+ struct ct_iter_state *st = seq->private;
+
+ for (st->bucket = 0;
+ st->bucket < nf_conntrack_htable_size;
+ st->bucket++) {
+ if (!list_empty(&nf_conntrack_hash[st->bucket]))
+ return nf_conntrack_hash[st->bucket].next;
+ }
+ return NULL;
+}
+
+static struct list_head *ct_get_next(struct seq_file *seq, struct list_head *head)
+{
+ struct ct_iter_state *st = seq->private;
+
+ head = head->next;
+ while (head == &nf_conntrack_hash[st->bucket]) {
+ if (++st->bucket >= nf_conntrack_htable_size)
+ return NULL;
+ head = nf_conntrack_hash[st->bucket].next;
+ }
+ return head;
+}
+
+static struct list_head *ct_get_idx(struct seq_file *seq, loff_t pos)
+{
+ struct list_head *head = ct_get_first(seq);
+
+ if (head)
+ while (pos && (head = ct_get_next(seq, head)))
+ pos--;
+ return pos ? NULL : head;
+}
+
+static void *ct_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ read_lock_bh(&nf_conntrack_lock);
+ return ct_get_idx(seq, *pos);
+}
+
+static void *ct_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ (*pos)++;
+ return ct_get_next(s, v);
+}
+
+static void ct_seq_stop(struct seq_file *s, void *v)
+{
+ read_unlock_bh(&nf_conntrack_lock);
+}
+
+static int ct_seq_show(struct seq_file *s, void *v)
+{
+ const struct nf_conntrack_tuple_hash *hash = v;
+ const struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(hash);
+ struct nf_conntrack_l3proto *l3proto;
+ struct nf_conntrack_l4proto *l4proto;
+
+ NF_CT_ASSERT(ct);
+
+ /* we only want to print DIR_ORIGINAL */
+ if (NF_CT_DIRECTION(hash))
+ return 0;
+ if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num != AF_INET)
+ return 0;
+
+ l3proto = __nf_ct_l3proto_find(ct->tuplehash[IP_CT_DIR_ORIGINAL]
+ .tuple.src.l3num);
+ NF_CT_ASSERT(l3proto);
+ l4proto = __nf_ct_l4proto_find(ct->tuplehash[IP_CT_DIR_ORIGINAL]
+ .tuple.src.l3num,
+ ct->tuplehash[IP_CT_DIR_ORIGINAL]
+ .tuple.dst.protonum);
+ NF_CT_ASSERT(l4proto);
+
+ if (seq_printf(s, "%-8s %u %ld ",
+ l4proto->name,
+ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum,
+ timer_pending(&ct->timeout)
+ ? (long)(ct->timeout.expires - jiffies)/HZ : 0) != 0)
+ return -ENOSPC;
+
+ if (l3proto->print_conntrack(s, ct))
+ return -ENOSPC;
+
+ if (l4proto->print_conntrack(s, ct))
+ return -ENOSPC;
+
+ if (print_tuple(s, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
+ l3proto, l4proto))
+ return -ENOSPC;
+
+ if (seq_print_counters(s, &ct->counters[IP_CT_DIR_ORIGINAL]))
+ return -ENOSPC;
+
+ if (!(test_bit(IPS_SEEN_REPLY_BIT, &ct->status)))
+ if (seq_printf(s, "[UNREPLIED] "))
+ return -ENOSPC;
+
+ if (print_tuple(s, &ct->tuplehash[IP_CT_DIR_REPLY].tuple,
+ l3proto, l4proto))
+ return -ENOSPC;
+
+ if (seq_print_counters(s, &ct->counters[IP_CT_DIR_REPLY]))
+ return -ENOSPC;
+
+ if (test_bit(IPS_ASSURED_BIT, &ct->status))
+ if (seq_printf(s, "[ASSURED] "))
+ return -ENOSPC;
+
+#ifdef CONFIG_NF_CONNTRACK_MARK
+ if (seq_printf(s, "mark=%u ", ct->mark))
+ return -ENOSPC;
+#endif
+
+#ifdef CONFIG_NF_CONNTRACK_SECMARK
+ if (seq_printf(s, "secmark=%u ", ct->secmark))
+ return -ENOSPC;
+#endif
+
+ if (seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use)))
+ return -ENOSPC;
+
+ return 0;
+}
+
+static struct seq_operations ct_seq_ops = {
+ .start = ct_seq_start,
+ .next = ct_seq_next,
+ .stop = ct_seq_stop,
+ .show = ct_seq_show
+};
+
+static int ct_open(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq;
+ struct ct_iter_state *st;
+ int ret;
+
+ st = kmalloc(sizeof(struct ct_iter_state), GFP_KERNEL);
+ if (st == NULL)
+ return -ENOMEM;
+ ret = seq_open(file, &ct_seq_ops);
+ if (ret)
+ goto out_free;
+ seq = file->private_data;
+ seq->private = st;
+ memset(st, 0, sizeof(struct ct_iter_state));
+ return ret;
+out_free:
+ kfree(st);
+ return ret;
+}
+
+static struct file_operations ct_file_ops = {
+ .owner = THIS_MODULE,
+ .open = ct_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release_private,
+};
+
+/* expects */
+static void *exp_seq_start(struct seq_file *s, loff_t *pos)
+{
+ struct list_head *e = &nf_conntrack_expect_list;
+ loff_t i;
+
+ /* strange seq_file api calls stop even if we fail,
+ * thus we need to grab lock since stop unlocks */
+ read_lock_bh(&nf_conntrack_lock);
+
+ if (list_empty(e))
+ return NULL;
+
+ for (i = 0; i <= *pos; i++) {
+ e = e->next;
+ if (e == &nf_conntrack_expect_list)
+ return NULL;
+ }
+ return e;
+}
+
+static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ struct list_head *e = v;
+
+ ++*pos;
+ e = e->next;
+
+ if (e == &nf_conntrack_expect_list)
+ return NULL;
+
+ return e;
+}
+
+static void exp_seq_stop(struct seq_file *s, void *v)
+{
+ read_unlock_bh(&nf_conntrack_lock);
+}
+
+static int exp_seq_show(struct seq_file *s, void *v)
+{
+ struct nf_conntrack_expect *exp = v;
+
+ if (exp->tuple.src.l3num != AF_INET)
+ return 0;
+
+ if (exp->timeout.function)
+ seq_printf(s, "%ld ", timer_pending(&exp->timeout)
+ ? (long)(exp->timeout.expires - jiffies)/HZ : 0);
+ else
+ seq_printf(s, "- ");
+
+ seq_printf(s, "proto=%u ", exp->tuple.dst.protonum);
+
+ print_tuple(s, &exp->tuple,
+ __nf_ct_l3proto_find(exp->tuple.src.l3num),
+ __nf_ct_l4proto_find(exp->tuple.src.l3num,
+ exp->tuple.dst.protonum));
+ return seq_putc(s, '\n');
+}
+
+static struct seq_operations exp_seq_ops = {
+ .start = exp_seq_start,
+ .next = exp_seq_next,
+ .stop = exp_seq_stop,
+ .show = exp_seq_show
+};
+
+static int exp_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &exp_seq_ops);
+}
+
+static struct file_operations ip_exp_file_ops = {
+ .owner = THIS_MODULE,
+ .open = exp_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release
+};
+
+static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ int cpu;
+
+ if (*pos == 0)
+ return SEQ_START_TOKEN;
+
+ for (cpu = *pos-1; cpu < NR_CPUS; ++cpu) {
+ if (!cpu_possible(cpu))
+ continue;
+ *pos = cpu+1;
+ return &per_cpu(nf_conntrack_stat, cpu);
+ }
+
+ return NULL;
+}
+
+static void *ct_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ int cpu;
+
+ for (cpu = *pos; cpu < NR_CPUS; ++cpu) {
+ if (!cpu_possible(cpu))
+ continue;
+ *pos = cpu+1;
+ return &per_cpu(nf_conntrack_stat, cpu);
+ }
+
+ return NULL;
+}
+
+static void ct_cpu_seq_stop(struct seq_file *seq, void *v)
+{
+}
+
+static int ct_cpu_seq_show(struct seq_file *seq, void *v)
+{
+ unsigned int nr_conntracks = atomic_read(&nf_conntrack_count);
+ struct ip_conntrack_stat *st = v;
+
+ if (v == SEQ_START_TOKEN) {
+ seq_printf(seq, "entries searched found new invalid ignore delete delete_list insert insert_failed drop early_drop icmp_error expect_new expect_create expect_delete\n");
+ return 0;
+ }
+
+ seq_printf(seq, "%08x %08x %08x %08x %08x %08x %08x %08x "
+ "%08x %08x %08x %08x %08x %08x %08x %08x \n",
+ nr_conntracks,
+ st->searched,
+ st->found,
+ st->new,
+ st->invalid,
+ st->ignore,
+ st->delete,
+ st->delete_list,
+ st->insert,
+ st->insert_failed,
+ st->drop,
+ st->early_drop,
+ st->error,
+
+ st->expect_new,
+ st->expect_create,
+ st->expect_delete
+ );
+ return 0;
+}
+
+static struct seq_operations ct_cpu_seq_ops = {
+ .start = ct_cpu_seq_start,
+ .next = ct_cpu_seq_next,
+ .stop = ct_cpu_seq_stop,
+ .show = ct_cpu_seq_show,
+};
+
+static int ct_cpu_seq_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &ct_cpu_seq_ops);
+}
+
+static struct file_operations ct_cpu_seq_fops = {
+ .owner = THIS_MODULE,
+ .open = ct_cpu_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release_private,
+};
+
+int __init nf_conntrack_ipv4_compat_init(void)
+{
+ struct proc_dir_entry *proc, *proc_exp, *proc_stat;
+
+ proc = proc_net_fops_create("ip_conntrack", 0440, &ct_file_ops);
+ if (!proc)
+ goto err1;
+
+ proc_exp = proc_net_fops_create("ip_conntrack_expect", 0440,
+ &ip_exp_file_ops);
+ if (!proc_exp)
+ goto err2;
+
+ proc_stat = create_proc_entry("ip_conntrack", S_IRUGO, proc_net_stat);
+ if (!proc_stat)
+ goto err3;
+
+ proc_stat->proc_fops = &ct_cpu_seq_fops;
+ proc_stat->owner = THIS_MODULE;
+
+ return 0;
+
+err3:
+ proc_net_remove("ip_conntrack_expect");
+err2:
+ proc_net_remove("ip_conntrack");
+err1:
+ return -ENOMEM;
+}
+
+void __exit nf_conntrack_ipv4_compat_fini(void)
+{
+ remove_proc_entry("ip_conntrack", proc_net_stat);
+ proc_net_remove("ip_conntrack_expect");
+ proc_net_remove("ip_conntrack");
+}
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
index 790f00d500c3..db9e7c45d3b4 100644
--- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
@@ -22,10 +22,10 @@
#include <net/checksum.h>
#include <linux/netfilter_ipv4.h>
#include <net/netfilter/nf_conntrack_tuple.h>
-#include <net/netfilter/nf_conntrack_protocol.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_core.h>
-unsigned long nf_ct_icmp_timeout __read_mostly = 30*HZ;
+static unsigned long nf_ct_icmp_timeout __read_mostly = 30*HZ;
#if 0
#define DEBUGP printk
@@ -152,7 +152,7 @@ icmp_error_message(struct sk_buff *skb,
struct icmphdr icmp;
struct iphdr ip;
} _in, *inside;
- struct nf_conntrack_protocol *innerproto;
+ struct nf_conntrack_l4proto *innerproto;
struct nf_conntrack_tuple_hash *h;
int dataoff;
@@ -170,7 +170,7 @@ icmp_error_message(struct sk_buff *skb,
return -NF_ACCEPT;
}
- innerproto = __nf_ct_proto_find(PF_INET, inside->ip.protocol);
+ innerproto = __nf_ct_l4proto_find(PF_INET, inside->ip.protocol);
dataoff = skb->nh.iph->ihl*4 + sizeof(inside->icmp);
/* Are they talking about one of our connections? */
if (!nf_ct_get_tuple(skb, dataoff, dataoff + inside->ip.ihl*4, PF_INET,
@@ -311,7 +311,7 @@ static int icmp_nfattr_to_tuple(struct nfattr *tb[],
tuple->dst.u.icmp.code =
*(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_CODE-1]);
tuple->src.u.icmp.id =
- *(u_int16_t *)NFA_DATA(tb[CTA_PROTO_ICMP_ID-1]);
+ *(__be16 *)NFA_DATA(tb[CTA_PROTO_ICMP_ID-1]);
if (tuple->dst.u.icmp.type >= sizeof(invmap)
|| !invmap[tuple->dst.u.icmp.type])
@@ -321,11 +321,42 @@ static int icmp_nfattr_to_tuple(struct nfattr *tb[],
}
#endif
-struct nf_conntrack_protocol nf_conntrack_protocol_icmp =
+#ifdef CONFIG_SYSCTL
+static struct ctl_table_header *icmp_sysctl_header;
+static struct ctl_table icmp_sysctl_table[] = {
+ {
+ .ctl_name = NET_NF_CONNTRACK_ICMP_TIMEOUT,
+ .procname = "nf_conntrack_icmp_timeout",
+ .data = &nf_ct_icmp_timeout,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = 0
+ }
+};
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+static struct ctl_table icmp_compat_sysctl_table[] = {
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT,
+ .procname = "ip_conntrack_icmp_timeout",
+ .data = &nf_ct_icmp_timeout,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = 0
+ }
+};
+#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
+#endif /* CONFIG_SYSCTL */
+
+struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp =
{
- .list = { NULL, NULL },
.l3proto = PF_INET,
- .proto = IPPROTO_ICMP,
+ .l4proto = IPPROTO_ICMP,
.name = "icmp",
.pkt_to_tuple = icmp_pkt_to_tuple,
.invert_tuple = icmp_invert_tuple,
@@ -341,6 +372,12 @@ struct nf_conntrack_protocol nf_conntrack_protocol_icmp =
.tuple_to_nfattr = icmp_tuple_to_nfattr,
.nfattr_to_tuple = icmp_nfattr_to_tuple,
#endif
+#ifdef CONFIG_SYSCTL
+ .ctl_table_header = &icmp_sysctl_header,
+ .ctl_table = icmp_sysctl_table,
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+ .ctl_compat_table = icmp_compat_sysctl_table,
+#endif
+#endif
};
-
-EXPORT_SYMBOL(nf_conntrack_protocol_icmp);
+EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_icmp);
diff --git a/net/ipv4/netfilter/nf_nat_amanda.c b/net/ipv4/netfilter/nf_nat_amanda.c
new file mode 100644
index 000000000000..0f17098917bc
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_amanda.c
@@ -0,0 +1,78 @@
+/* Amanda extension for TCP NAT alteration.
+ * (C) 2002 by Brian J. Murrell <netfilter@interlinx.bc.ca>
+ * based on a copy of HW's ip_nat_irc.c as well as other modules
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/udp.h>
+
+#include <net/netfilter/nf_nat_helper.h>
+#include <net/netfilter/nf_nat_rule.h>
+#include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_conntrack_expect.h>
+#include <linux/netfilter/nf_conntrack_amanda.h>
+
+MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>");
+MODULE_DESCRIPTION("Amanda NAT helper");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ip_nat_amanda");
+
+static unsigned int help(struct sk_buff **pskb,
+ enum ip_conntrack_info ctinfo,
+ unsigned int matchoff,
+ unsigned int matchlen,
+ struct nf_conntrack_expect *exp)
+{
+ char buffer[sizeof("65535")];
+ u_int16_t port;
+ unsigned int ret;
+
+ /* Connection comes from client. */
+ exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
+ exp->dir = IP_CT_DIR_ORIGINAL;
+
+ /* When you see the packet, we need to NAT it the same as the
+ * this one (ie. same IP: it will be TCP and master is UDP). */
+ exp->expectfn = nf_nat_follow_master;
+
+ /* Try to get same port: if not, try to change it. */
+ for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
+ exp->tuple.dst.u.tcp.port = htons(port);
+ if (nf_conntrack_expect_related(exp) == 0)
+ break;
+ }
+
+ if (port == 0)
+ return NF_DROP;
+
+ sprintf(buffer, "%u", port);
+ ret = nf_nat_mangle_udp_packet(pskb, exp->master, ctinfo,
+ matchoff, matchlen,
+ buffer, strlen(buffer));
+ if (ret != NF_ACCEPT)
+ nf_conntrack_unexpect_related(exp);
+ return ret;
+}
+
+static void __exit nf_nat_amanda_fini(void)
+{
+ rcu_assign_pointer(nf_nat_amanda_hook, NULL);
+ synchronize_rcu();
+}
+
+static int __init nf_nat_amanda_init(void)
+{
+ BUG_ON(rcu_dereference(nf_nat_amanda_hook));
+ rcu_assign_pointer(nf_nat_amanda_hook, help);
+ return 0;
+}
+
+module_init(nf_nat_amanda_init);
+module_exit(nf_nat_amanda_fini);
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c
new file mode 100644
index 000000000000..86a92272b053
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_core.c
@@ -0,0 +1,647 @@
+/* NAT for netfilter; shared with compatibility layer. */
+
+/* (C) 1999-2001 Paul `Rusty' Russell
+ * (C) 2002-2006 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/timer.h>
+#include <linux/skbuff.h>
+#include <linux/vmalloc.h>
+#include <net/checksum.h>
+#include <net/icmp.h>
+#include <net/ip.h>
+#include <net/tcp.h> /* For tcp_prot in getorigdst */
+#include <linux/icmp.h>
+#include <linux/udp.h>
+#include <linux/jhash.h>
+
+#include <linux/netfilter_ipv4.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_core.h>
+#include <net/netfilter/nf_nat.h>
+#include <net/netfilter/nf_nat_protocol.h>
+#include <net/netfilter/nf_nat_core.h>
+#include <net/netfilter/nf_nat_helper.h>
+#include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_conntrack_l3proto.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+static DEFINE_RWLOCK(nf_nat_lock);
+
+static struct nf_conntrack_l3proto *l3proto = NULL;
+
+/* Calculated at init based on memory size */
+static unsigned int nf_nat_htable_size;
+
+static struct list_head *bysource;
+
+#define MAX_IP_NAT_PROTO 256
+static struct nf_nat_protocol *nf_nat_protos[MAX_IP_NAT_PROTO];
+
+static inline struct nf_nat_protocol *
+__nf_nat_proto_find(u_int8_t protonum)
+{
+ return nf_nat_protos[protonum];
+}
+
+struct nf_nat_protocol *
+nf_nat_proto_find_get(u_int8_t protonum)
+{
+ struct nf_nat_protocol *p;
+
+ /* we need to disable preemption to make sure 'p' doesn't get
+ * removed until we've grabbed the reference */
+ preempt_disable();
+ p = __nf_nat_proto_find(protonum);
+ if (!try_module_get(p->me))
+ p = &nf_nat_unknown_protocol;
+ preempt_enable();
+
+ return p;
+}
+EXPORT_SYMBOL_GPL(nf_nat_proto_find_get);
+
+void
+nf_nat_proto_put(struct nf_nat_protocol *p)
+{
+ module_put(p->me);
+}
+EXPORT_SYMBOL_GPL(nf_nat_proto_put);
+
+/* We keep an extra hash for each conntrack, for fast searching. */
+static inline unsigned int
+hash_by_src(const struct nf_conntrack_tuple *tuple)
+{
+ /* Original src, to ensure we map it consistently if poss. */
+ return jhash_3words((__force u32)tuple->src.u3.ip, tuple->src.u.all,
+ tuple->dst.protonum, 0) % nf_nat_htable_size;
+}
+
+/* Noone using conntrack by the time this called. */
+static void nf_nat_cleanup_conntrack(struct nf_conn *conn)
+{
+ struct nf_conn_nat *nat;
+ if (!(conn->status & IPS_NAT_DONE_MASK))
+ return;
+
+ nat = nfct_nat(conn);
+ write_lock_bh(&nf_nat_lock);
+ list_del(&nat->info.bysource);
+ write_unlock_bh(&nf_nat_lock);
+}
+
+/* Is this tuple already taken? (not by us) */
+int
+nf_nat_used_tuple(const struct nf_conntrack_tuple *tuple,
+ const struct nf_conn *ignored_conntrack)
+{
+ /* Conntrack tracking doesn't keep track of outgoing tuples; only
+ incoming ones. NAT means they don't have a fixed mapping,
+ so we invert the tuple and look for the incoming reply.
+
+ We could keep a separate hash if this proves too slow. */
+ struct nf_conntrack_tuple reply;
+
+ nf_ct_invert_tuplepr(&reply, tuple);
+ return nf_conntrack_tuple_taken(&reply, ignored_conntrack);
+}
+EXPORT_SYMBOL(nf_nat_used_tuple);
+
+/* If we source map this tuple so reply looks like reply_tuple, will
+ * that meet the constraints of range. */
+static int
+in_range(const struct nf_conntrack_tuple *tuple,
+ const struct nf_nat_range *range)
+{
+ struct nf_nat_protocol *proto;
+
+ proto = __nf_nat_proto_find(tuple->dst.protonum);
+ /* If we are supposed to map IPs, then we must be in the
+ range specified, otherwise let this drag us onto a new src IP. */
+ if (range->flags & IP_NAT_RANGE_MAP_IPS) {
+ if (ntohl(tuple->src.u3.ip) < ntohl(range->min_ip) ||
+ ntohl(tuple->src.u3.ip) > ntohl(range->max_ip))
+ return 0;
+ }
+
+ if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) ||
+ proto->in_range(tuple, IP_NAT_MANIP_SRC,
+ &range->min, &range->max))
+ return 1;
+
+ return 0;
+}
+
+static inline int
+same_src(const struct nf_conn *ct,
+ const struct nf_conntrack_tuple *tuple)
+{
+ const struct nf_conntrack_tuple *t;
+
+ t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
+ return (t->dst.protonum == tuple->dst.protonum &&
+ t->src.u3.ip == tuple->src.u3.ip &&
+ t->src.u.all == tuple->src.u.all);
+}
+
+/* Only called for SRC manip */
+static int
+find_appropriate_src(const struct nf_conntrack_tuple *tuple,
+ struct nf_conntrack_tuple *result,
+ const struct nf_nat_range *range)
+{
+ unsigned int h = hash_by_src(tuple);
+ struct nf_conn_nat *nat;
+ struct nf_conn *ct;
+
+ read_lock_bh(&nf_nat_lock);
+ list_for_each_entry(nat, &bysource[h], info.bysource) {
+ ct = (struct nf_conn *)((char *)nat - offsetof(struct nf_conn, data));
+ if (same_src(ct, tuple)) {
+ /* Copy source part from reply tuple. */
+ nf_ct_invert_tuplepr(result,
+ &ct->tuplehash[IP_CT_DIR_REPLY].tuple);
+ result->dst = tuple->dst;
+
+ if (in_range(result, range)) {
+ read_unlock_bh(&nf_nat_lock);
+ return 1;
+ }
+ }
+ }
+ read_unlock_bh(&nf_nat_lock);
+ return 0;
+}
+
+/* For [FUTURE] fragmentation handling, we want the least-used
+ src-ip/dst-ip/proto triple. Fairness doesn't come into it. Thus
+ if the range specifies 1.2.3.4 ports 10000-10005 and 1.2.3.5 ports
+ 1-65535, we don't do pro-rata allocation based on ports; we choose
+ the ip with the lowest src-ip/dst-ip/proto usage.
+*/
+static void
+find_best_ips_proto(struct nf_conntrack_tuple *tuple,
+ const struct nf_nat_range *range,
+ const struct nf_conn *ct,
+ enum nf_nat_manip_type maniptype)
+{
+ __be32 *var_ipp;
+ /* Host order */
+ u_int32_t minip, maxip, j;
+
+ /* No IP mapping? Do nothing. */
+ if (!(range->flags & IP_NAT_RANGE_MAP_IPS))
+ return;
+
+ if (maniptype == IP_NAT_MANIP_SRC)
+ var_ipp = &tuple->src.u3.ip;
+ else
+ var_ipp = &tuple->dst.u3.ip;
+
+ /* Fast path: only one choice. */
+ if (range->min_ip == range->max_ip) {
+ *var_ipp = range->min_ip;
+ return;
+ }
+
+ /* Hashing source and destination IPs gives a fairly even
+ * spread in practice (if there are a small number of IPs
+ * involved, there usually aren't that many connections
+ * anyway). The consistency means that servers see the same
+ * client coming from the same IP (some Internet Banking sites
+ * like this), even across reboots. */
+ minip = ntohl(range->min_ip);
+ maxip = ntohl(range->max_ip);
+ j = jhash_2words((__force u32)tuple->src.u3.ip,
+ (__force u32)tuple->dst.u3.ip, 0);
+ *var_ipp = htonl(minip + j % (maxip - minip + 1));
+}
+
+/* Manipulate the tuple into the range given. For NF_IP_POST_ROUTING,
+ * we change the source to map into the range. For NF_IP_PRE_ROUTING
+ * and NF_IP_LOCAL_OUT, we change the destination to map into the
+ * range. It might not be possible to get a unique tuple, but we try.
+ * At worst (or if we race), we will end up with a final duplicate in
+ * __ip_conntrack_confirm and drop the packet. */
+static void
+get_unique_tuple(struct nf_conntrack_tuple *tuple,
+ const struct nf_conntrack_tuple *orig_tuple,
+ const struct nf_nat_range *range,
+ struct nf_conn *ct,
+ enum nf_nat_manip_type maniptype)
+{
+ struct nf_nat_protocol *proto;
+
+ /* 1) If this srcip/proto/src-proto-part is currently mapped,
+ and that same mapping gives a unique tuple within the given
+ range, use that.
+
+ This is only required for source (ie. NAT/masq) mappings.
+ So far, we don't do local source mappings, so multiple
+ manips not an issue. */
+ if (maniptype == IP_NAT_MANIP_SRC) {
+ if (find_appropriate_src(orig_tuple, tuple, range)) {
+ DEBUGP("get_unique_tuple: Found current src map\n");
+ if (!nf_nat_used_tuple(tuple, ct))
+ return;
+ }
+ }
+
+ /* 2) Select the least-used IP/proto combination in the given
+ range. */
+ *tuple = *orig_tuple;
+ find_best_ips_proto(tuple, range, ct, maniptype);
+
+ /* 3) The per-protocol part of the manip is made to map into
+ the range to make a unique tuple. */
+
+ proto = nf_nat_proto_find_get(orig_tuple->dst.protonum);
+
+ /* Only bother mapping if it's not already in range and unique */
+ if ((!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) ||
+ proto->in_range(tuple, maniptype, &range->min, &range->max)) &&
+ !nf_nat_used_tuple(tuple, ct)) {
+ nf_nat_proto_put(proto);
+ return;
+ }
+
+ /* Last change: get protocol to try to obtain unique tuple. */
+ proto->unique_tuple(tuple, range, maniptype, ct);
+
+ nf_nat_proto_put(proto);
+}
+
+unsigned int
+nf_nat_setup_info(struct nf_conn *ct,
+ const struct nf_nat_range *range,
+ unsigned int hooknum)
+{
+ struct nf_conntrack_tuple curr_tuple, new_tuple;
+ struct nf_conn_nat *nat = nfct_nat(ct);
+ struct nf_nat_info *info = &nat->info;
+ int have_to_hash = !(ct->status & IPS_NAT_DONE_MASK);
+ enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum);
+
+ NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING ||
+ hooknum == NF_IP_POST_ROUTING ||
+ hooknum == NF_IP_LOCAL_IN ||
+ hooknum == NF_IP_LOCAL_OUT);
+ BUG_ON(nf_nat_initialized(ct, maniptype));
+
+ /* What we've got will look like inverse of reply. Normally
+ this is what is in the conntrack, except for prior
+ manipulations (future optimization: if num_manips == 0,
+ orig_tp =
+ conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple) */
+ nf_ct_invert_tuplepr(&curr_tuple,
+ &ct->tuplehash[IP_CT_DIR_REPLY].tuple);
+
+ get_unique_tuple(&new_tuple, &curr_tuple, range, ct, maniptype);
+
+ if (!nf_ct_tuple_equal(&new_tuple, &curr_tuple)) {
+ struct nf_conntrack_tuple reply;
+
+ /* Alter conntrack table so will recognize replies. */
+ nf_ct_invert_tuplepr(&reply, &new_tuple);
+ nf_conntrack_alter_reply(ct, &reply);
+
+ /* Non-atomic: we own this at the moment. */
+ if (maniptype == IP_NAT_MANIP_SRC)
+ ct->status |= IPS_SRC_NAT;
+ else
+ ct->status |= IPS_DST_NAT;
+ }
+
+ /* Place in source hash if this is the first time. */
+ if (have_to_hash) {
+ unsigned int srchash;
+
+ srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+ write_lock_bh(&nf_nat_lock);
+ list_add(&info->bysource, &bysource[srchash]);
+ write_unlock_bh(&nf_nat_lock);
+ }
+
+ /* It's done. */
+ if (maniptype == IP_NAT_MANIP_DST)
+ set_bit(IPS_DST_NAT_DONE_BIT, &ct->status);
+ else
+ set_bit(IPS_SRC_NAT_DONE_BIT, &ct->status);
+
+ return NF_ACCEPT;
+}
+EXPORT_SYMBOL(nf_nat_setup_info);
+
+/* Returns true if succeeded. */
+static int
+manip_pkt(u_int16_t proto,
+ struct sk_buff **pskb,
+ unsigned int iphdroff,
+ const struct nf_conntrack_tuple *target,
+ enum nf_nat_manip_type maniptype)
+{
+ struct iphdr *iph;
+ struct nf_nat_protocol *p;
+
+ if (!skb_make_writable(pskb, iphdroff + sizeof(*iph)))
+ return 0;
+
+ iph = (void *)(*pskb)->data + iphdroff;
+
+ /* Manipulate protcol part. */
+ p = nf_nat_proto_find_get(proto);
+ if (!p->manip_pkt(pskb, iphdroff, target, maniptype)) {
+ nf_nat_proto_put(p);
+ return 0;
+ }
+ nf_nat_proto_put(p);
+
+ iph = (void *)(*pskb)->data + iphdroff;
+
+ if (maniptype == IP_NAT_MANIP_SRC) {
+ nf_csum_replace4(&iph->check, iph->saddr, target->src.u3.ip);
+ iph->saddr = target->src.u3.ip;
+ } else {
+ nf_csum_replace4(&iph->check, iph->daddr, target->dst.u3.ip);
+ iph->daddr = target->dst.u3.ip;
+ }
+ return 1;
+}
+
+/* Do packet manipulations according to nf_nat_setup_info. */
+unsigned int nf_nat_packet(struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned int hooknum,
+ struct sk_buff **pskb)
+{
+ enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+ unsigned long statusbit;
+ enum nf_nat_manip_type mtype = HOOK2MANIP(hooknum);
+
+ if (mtype == IP_NAT_MANIP_SRC)
+ statusbit = IPS_SRC_NAT;
+ else
+ statusbit = IPS_DST_NAT;
+
+ /* Invert if this is reply dir. */
+ if (dir == IP_CT_DIR_REPLY)
+ statusbit ^= IPS_NAT_MASK;
+
+ /* Non-atomic: these bits don't change. */
+ if (ct->status & statusbit) {
+ struct nf_conntrack_tuple target;
+
+ /* We are aiming to look like inverse of other direction. */
+ nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple);
+
+ if (!manip_pkt(target.dst.protonum, pskb, 0, &target, mtype))
+ return NF_DROP;
+ }
+ return NF_ACCEPT;
+}
+EXPORT_SYMBOL_GPL(nf_nat_packet);
+
+/* Dir is direction ICMP is coming from (opposite to packet it contains) */
+int nf_nat_icmp_reply_translation(struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned int hooknum,
+ struct sk_buff **pskb)
+{
+ struct {
+ struct icmphdr icmp;
+ struct iphdr ip;
+ } *inside;
+ struct nf_conntrack_tuple inner, target;
+ int hdrlen = (*pskb)->nh.iph->ihl * 4;
+ enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+ unsigned long statusbit;
+ enum nf_nat_manip_type manip = HOOK2MANIP(hooknum);
+
+ if (!skb_make_writable(pskb, hdrlen + sizeof(*inside)))
+ return 0;
+
+ inside = (void *)(*pskb)->data + (*pskb)->nh.iph->ihl*4;
+
+ /* We're actually going to mangle it beyond trivial checksum
+ adjustment, so make sure the current checksum is correct. */
+ if (nf_ip_checksum(*pskb, hooknum, hdrlen, 0))
+ return 0;
+
+ /* Must be RELATED */
+ NF_CT_ASSERT((*pskb)->nfctinfo == IP_CT_RELATED ||
+ (*pskb)->nfctinfo == IP_CT_RELATED+IP_CT_IS_REPLY);
+
+ /* Redirects on non-null nats must be dropped, else they'll
+ start talking to each other without our translation, and be
+ confused... --RR */
+ if (inside->icmp.type == ICMP_REDIRECT) {
+ /* If NAT isn't finished, assume it and drop. */
+ if ((ct->status & IPS_NAT_DONE_MASK) != IPS_NAT_DONE_MASK)
+ return 0;
+
+ if (ct->status & IPS_NAT_MASK)
+ return 0;
+ }
+
+ DEBUGP("icmp_reply_translation: translating error %p manp %u dir %s\n",
+ *pskb, manip, dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY");
+
+ if (!nf_ct_get_tuple(*pskb,
+ (*pskb)->nh.iph->ihl*4 + sizeof(struct icmphdr),
+ (*pskb)->nh.iph->ihl*4 +
+ sizeof(struct icmphdr) + inside->ip.ihl*4,
+ (u_int16_t)AF_INET,
+ inside->ip.protocol,
+ &inner,
+ l3proto,
+ __nf_ct_l4proto_find((u_int16_t)PF_INET,
+ inside->ip.protocol)))
+ return 0;
+
+ /* Change inner back to look like incoming packet. We do the
+ opposite manip on this hook to normal, because it might not
+ pass all hooks (locally-generated ICMP). Consider incoming
+ packet: PREROUTING (DST manip), routing produces ICMP, goes
+ through POSTROUTING (which must correct the DST manip). */
+ if (!manip_pkt(inside->ip.protocol, pskb,
+ (*pskb)->nh.iph->ihl*4 + sizeof(inside->icmp),
+ &ct->tuplehash[!dir].tuple,
+ !manip))
+ return 0;
+
+ if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
+ /* Reloading "inside" here since manip_pkt inner. */
+ inside = (void *)(*pskb)->data + (*pskb)->nh.iph->ihl*4;
+ inside->icmp.checksum = 0;
+ inside->icmp.checksum =
+ csum_fold(skb_checksum(*pskb, hdrlen,
+ (*pskb)->len - hdrlen, 0));
+ }
+
+ /* Change outer to look the reply to an incoming packet
+ * (proto 0 means don't invert per-proto part). */
+ if (manip == IP_NAT_MANIP_SRC)
+ statusbit = IPS_SRC_NAT;
+ else
+ statusbit = IPS_DST_NAT;
+
+ /* Invert if this is reply dir. */
+ if (dir == IP_CT_DIR_REPLY)
+ statusbit ^= IPS_NAT_MASK;
+
+ if (ct->status & statusbit) {
+ nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple);
+ if (!manip_pkt(0, pskb, 0, &target, manip))
+ return 0;
+ }
+
+ return 1;
+}
+EXPORT_SYMBOL_GPL(nf_nat_icmp_reply_translation);
+
+/* Protocol registration. */
+int nf_nat_protocol_register(struct nf_nat_protocol *proto)
+{
+ int ret = 0;
+
+ write_lock_bh(&nf_nat_lock);
+ if (nf_nat_protos[proto->protonum] != &nf_nat_unknown_protocol) {
+ ret = -EBUSY;
+ goto out;
+ }
+ nf_nat_protos[proto->protonum] = proto;
+ out:
+ write_unlock_bh(&nf_nat_lock);
+ return ret;
+}
+EXPORT_SYMBOL(nf_nat_protocol_register);
+
+/* Noone stores the protocol anywhere; simply delete it. */
+void nf_nat_protocol_unregister(struct nf_nat_protocol *proto)
+{
+ write_lock_bh(&nf_nat_lock);
+ nf_nat_protos[proto->protonum] = &nf_nat_unknown_protocol;
+ write_unlock_bh(&nf_nat_lock);
+
+ /* Someone could be still looking at the proto in a bh. */
+ synchronize_net();
+}
+EXPORT_SYMBOL(nf_nat_protocol_unregister);
+
+#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
+ defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
+int
+nf_nat_port_range_to_nfattr(struct sk_buff *skb,
+ const struct nf_nat_range *range)
+{
+ NFA_PUT(skb, CTA_PROTONAT_PORT_MIN, sizeof(__be16),
+ &range->min.tcp.port);
+ NFA_PUT(skb, CTA_PROTONAT_PORT_MAX, sizeof(__be16),
+ &range->max.tcp.port);
+
+ return 0;
+
+nfattr_failure:
+ return -1;
+}
+EXPORT_SYMBOL_GPL(nf_nat_port_nfattr_to_range);
+
+int
+nf_nat_port_nfattr_to_range(struct nfattr *tb[], struct nf_nat_range *range)
+{
+ int ret = 0;
+
+ /* we have to return whether we actually parsed something or not */
+
+ if (tb[CTA_PROTONAT_PORT_MIN-1]) {
+ ret = 1;
+ range->min.tcp.port =
+ *(__be16 *)NFA_DATA(tb[CTA_PROTONAT_PORT_MIN-1]);
+ }
+
+ if (!tb[CTA_PROTONAT_PORT_MAX-1]) {
+ if (ret)
+ range->max.tcp.port = range->min.tcp.port;
+ } else {
+ ret = 1;
+ range->max.tcp.port =
+ *(__be16 *)NFA_DATA(tb[CTA_PROTONAT_PORT_MAX-1]);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(nf_nat_port_range_to_nfattr);
+#endif
+
+static int __init nf_nat_init(void)
+{
+ size_t i;
+
+ /* Leave them the same for the moment. */
+ nf_nat_htable_size = nf_conntrack_htable_size;
+
+ /* One vmalloc for both hash tables */
+ bysource = vmalloc(sizeof(struct list_head) * nf_nat_htable_size);
+ if (!bysource)
+ return -ENOMEM;
+
+ /* Sew in builtin protocols. */
+ write_lock_bh(&nf_nat_lock);
+ for (i = 0; i < MAX_IP_NAT_PROTO; i++)
+ nf_nat_protos[i] = &nf_nat_unknown_protocol;
+ nf_nat_protos[IPPROTO_TCP] = &nf_nat_protocol_tcp;
+ nf_nat_protos[IPPROTO_UDP] = &nf_nat_protocol_udp;
+ nf_nat_protos[IPPROTO_ICMP] = &nf_nat_protocol_icmp;
+ write_unlock_bh(&nf_nat_lock);
+
+ for (i = 0; i < nf_nat_htable_size; i++) {
+ INIT_LIST_HEAD(&bysource[i]);
+ }
+
+ /* FIXME: Man, this is a hack. <SIGH> */
+ NF_CT_ASSERT(nf_conntrack_destroyed == NULL);
+ nf_conntrack_destroyed = &nf_nat_cleanup_conntrack;
+
+ /* Initialize fake conntrack so that NAT will skip it */
+ nf_conntrack_untracked.status |= IPS_NAT_DONE_MASK;
+
+ l3proto = nf_ct_l3proto_find_get((u_int16_t)AF_INET);
+ return 0;
+}
+
+/* Clear NAT section of all conntracks, in case we're loaded again. */
+static int clean_nat(struct nf_conn *i, void *data)
+{
+ struct nf_conn_nat *nat = nfct_nat(i);
+
+ if (!nat)
+ return 0;
+ memset(nat, 0, sizeof(nat));
+ i->status &= ~(IPS_NAT_MASK | IPS_NAT_DONE_MASK | IPS_SEQ_ADJUST);
+ return 0;
+}
+
+static void __exit nf_nat_cleanup(void)
+{
+ nf_ct_iterate_cleanup(&clean_nat, NULL);
+ nf_conntrack_destroyed = NULL;
+ vfree(bysource);
+ nf_ct_l3proto_put(l3proto);
+}
+
+MODULE_LICENSE("GPL");
+
+module_init(nf_nat_init);
+module_exit(nf_nat_cleanup);
diff --git a/net/ipv4/netfilter/nf_nat_ftp.c b/net/ipv4/netfilter/nf_nat_ftp.c
new file mode 100644
index 000000000000..751b59801755
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_ftp.c
@@ -0,0 +1,179 @@
+/* FTP extension for TCP NAT alteration. */
+
+/* (C) 1999-2001 Paul `Rusty' Russell
+ * (C) 2002-2006 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/moduleparam.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/netfilter_ipv4.h>
+#include <net/netfilter/nf_nat.h>
+#include <net/netfilter/nf_nat_helper.h>
+#include <net/netfilter/nf_nat_rule.h>
+#include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_conntrack_expect.h>
+#include <linux/netfilter/nf_conntrack_ftp.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Rusty Russell <rusty@rustcorp.com.au>");
+MODULE_DESCRIPTION("ftp NAT helper");
+MODULE_ALIAS("ip_nat_ftp");
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+/* FIXME: Time out? --RR */
+
+static int
+mangle_rfc959_packet(struct sk_buff **pskb,
+ __be32 newip,
+ u_int16_t port,
+ unsigned int matchoff,
+ unsigned int matchlen,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ u32 *seq)
+{
+ char buffer[sizeof("nnn,nnn,nnn,nnn,nnn,nnn")];
+
+ sprintf(buffer, "%u,%u,%u,%u,%u,%u",
+ NIPQUAD(newip), port>>8, port&0xFF);
+
+ DEBUGP("calling nf_nat_mangle_tcp_packet\n");
+
+ *seq += strlen(buffer) - matchlen;
+ return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff,
+ matchlen, buffer, strlen(buffer));
+}
+
+/* |1|132.235.1.2|6275| */
+static int
+mangle_eprt_packet(struct sk_buff **pskb,
+ __be32 newip,
+ u_int16_t port,
+ unsigned int matchoff,
+ unsigned int matchlen,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ u32 *seq)
+{
+ char buffer[sizeof("|1|255.255.255.255|65535|")];
+
+ sprintf(buffer, "|1|%u.%u.%u.%u|%u|", NIPQUAD(newip), port);
+
+ DEBUGP("calling nf_nat_mangle_tcp_packet\n");
+
+ *seq += strlen(buffer) - matchlen;
+ return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff,
+ matchlen, buffer, strlen(buffer));
+}
+
+/* |1|132.235.1.2|6275| */
+static int
+mangle_epsv_packet(struct sk_buff **pskb,
+ __be32 newip,
+ u_int16_t port,
+ unsigned int matchoff,
+ unsigned int matchlen,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ u32 *seq)
+{
+ char buffer[sizeof("|||65535|")];
+
+ sprintf(buffer, "|||%u|", port);
+
+ DEBUGP("calling nf_nat_mangle_tcp_packet\n");
+
+ *seq += strlen(buffer) - matchlen;
+ return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff,
+ matchlen, buffer, strlen(buffer));
+}
+
+static int (*mangle[])(struct sk_buff **, __be32, u_int16_t,
+ unsigned int, unsigned int, struct nf_conn *,
+ enum ip_conntrack_info, u32 *seq)
+= {
+ [NF_CT_FTP_PORT] = mangle_rfc959_packet,
+ [NF_CT_FTP_PASV] = mangle_rfc959_packet,
+ [NF_CT_FTP_EPRT] = mangle_eprt_packet,
+ [NF_CT_FTP_EPSV] = mangle_epsv_packet
+};
+
+/* So, this packet has hit the connection tracking matching code.
+ Mangle it, and change the expectation to match the new version. */
+static unsigned int nf_nat_ftp(struct sk_buff **pskb,
+ enum ip_conntrack_info ctinfo,
+ enum nf_ct_ftp_type type,
+ unsigned int matchoff,
+ unsigned int matchlen,
+ struct nf_conntrack_expect *exp,
+ u32 *seq)
+{
+ __be32 newip;
+ u_int16_t port;
+ int dir = CTINFO2DIR(ctinfo);
+ struct nf_conn *ct = exp->master;
+
+ DEBUGP("FTP_NAT: type %i, off %u len %u\n", type, matchoff, matchlen);
+
+ /* Connection will come from wherever this packet goes, hence !dir */
+ newip = ct->tuplehash[!dir].tuple.dst.u3.ip;
+ exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
+ exp->dir = !dir;
+
+ /* When you see the packet, we need to NAT it the same as the
+ * this one. */
+ exp->expectfn = nf_nat_follow_master;
+
+ /* Try to get same port: if not, try to change it. */
+ for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
+ exp->tuple.dst.u.tcp.port = htons(port);
+ if (nf_conntrack_expect_related(exp) == 0)
+ break;
+ }
+
+ if (port == 0)
+ return NF_DROP;
+
+ if (!mangle[type](pskb, newip, port, matchoff, matchlen, ct, ctinfo,
+ seq)) {
+ nf_conntrack_unexpect_related(exp);
+ return NF_DROP;
+ }
+ return NF_ACCEPT;
+}
+
+static void __exit nf_nat_ftp_fini(void)
+{
+ rcu_assign_pointer(nf_nat_ftp_hook, NULL);
+ synchronize_rcu();
+}
+
+static int __init nf_nat_ftp_init(void)
+{
+ BUG_ON(rcu_dereference(nf_nat_ftp_hook));
+ rcu_assign_pointer(nf_nat_ftp_hook, nf_nat_ftp);
+ return 0;
+}
+
+/* Prior to 2.6.11, we had a ports param. No longer, but don't break users. */
+static int warn_set(const char *val, struct kernel_param *kp)
+{
+ printk(KERN_INFO KBUILD_MODNAME
+ ": kernel >= 2.6.10 only uses 'ports' for conntrack modules\n");
+ return 0;
+}
+module_param_call(ports, warn_set, NULL, NULL, 0);
+
+module_init(nf_nat_ftp_init);
+module_exit(nf_nat_ftp_fini);
diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c
new file mode 100644
index 000000000000..fb9ab0114c23
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_h323.c
@@ -0,0 +1,596 @@
+/*
+ * H.323 extension for NAT alteration.
+ *
+ * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
+ *
+ * This source code is licensed under General Public License version 2.
+ *
+ * Based on the 'brute force' H.323 NAT module by
+ * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/tcp.h>
+#include <net/tcp.h>
+
+#include <net/netfilter/nf_nat.h>
+#include <net/netfilter/nf_nat_helper.h>
+#include <net/netfilter/nf_nat_rule.h>
+#include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_conntrack_expect.h>
+#include <linux/netfilter/nf_conntrack_h323.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+/****************************************************************************/
+static int set_addr(struct sk_buff **pskb,
+ unsigned char **data, int dataoff,
+ unsigned int addroff, __be32 ip, __be16 port)
+{
+ enum ip_conntrack_info ctinfo;
+ struct nf_conn *ct = ip_conntrack_get(*pskb, &ctinfo);
+ struct {
+ __be32 ip;
+ __be16 port;
+ } __attribute__ ((__packed__)) buf;
+ struct tcphdr _tcph, *th;
+
+ buf.ip = ip;
+ buf.port = port;
+ addroff += dataoff;
+
+ if ((*pskb)->nh.iph->protocol == IPPROTO_TCP) {
+ if (!nf_nat_mangle_tcp_packet(pskb, ct, ctinfo,
+ addroff, sizeof(buf),
+ (char *) &buf, sizeof(buf))) {
+ if (net_ratelimit())
+ printk("nf_nat_h323: nf_nat_mangle_tcp_packet"
+ " error\n");
+ return -1;
+ }
+
+ /* Relocate data pointer */
+ th = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl * 4,
+ sizeof(_tcph), &_tcph);
+ if (th == NULL)
+ return -1;
+ *data = (*pskb)->data + (*pskb)->nh.iph->ihl * 4 +
+ th->doff * 4 + dataoff;
+ } else {
+ if (!nf_nat_mangle_udp_packet(pskb, ct, ctinfo,
+ addroff, sizeof(buf),
+ (char *) &buf, sizeof(buf))) {
+ if (net_ratelimit())
+ printk("nf_nat_h323: nf_nat_mangle_udp_packet"
+ " error\n");
+ return -1;
+ }
+ /* nf_nat_mangle_udp_packet uses skb_make_writable() to copy
+ * or pull everything in a linear buffer, so we can safely
+ * use the skb pointers now */
+ *data = (*pskb)->data + (*pskb)->nh.iph->ihl * 4 +
+ sizeof(struct udphdr);
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+static int set_h225_addr(struct sk_buff **pskb,
+ unsigned char **data, int dataoff,
+ TransportAddress *taddr,
+ union nf_conntrack_address *addr, __be16 port)
+{
+ return set_addr(pskb, data, dataoff, taddr->ipAddress.ip,
+ addr->ip, port);
+}
+
+/****************************************************************************/
+static int set_h245_addr(struct sk_buff **pskb,
+ unsigned char **data, int dataoff,
+ H245_TransportAddress *taddr,
+ union nf_conntrack_address *addr, __be16 port)
+{
+ return set_addr(pskb, data, dataoff,
+ taddr->unicastAddress.iPAddress.network,
+ addr->ip, port);
+}
+
+/****************************************************************************/
+static int set_sig_addr(struct sk_buff **pskb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data,
+ TransportAddress *taddr, int count)
+{
+ struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
+ int dir = CTINFO2DIR(ctinfo);
+ int i;
+ __be16 port;
+ union nf_conntrack_address addr;
+
+ for (i = 0; i < count; i++) {
+ if (get_h225_addr(ct, *data, &taddr[i], &addr, &port)) {
+ if (addr.ip == ct->tuplehash[dir].tuple.src.u3.ip &&
+ port == info->sig_port[dir]) {
+ /* GW->GK */
+
+ /* Fix for Gnomemeeting */
+ if (i > 0 &&
+ get_h225_addr(ct, *data, &taddr[0],
+ &addr, &port) &&
+ (ntohl(addr.ip) & 0xff000000) == 0x7f000000)
+ i = 0;
+
+ DEBUGP
+ ("nf_nat_ras: set signal address "
+ "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+ NIPQUAD(ip), port,
+ NIPQUAD(ct->tuplehash[!dir].tuple.dst.
+ ip), info->sig_port[!dir]);
+ return set_h225_addr(pskb, data, 0, &taddr[i],
+ &ct->tuplehash[!dir].
+ tuple.dst.u3,
+ info->sig_port[!dir]);
+ } else if (addr.ip == ct->tuplehash[dir].tuple.dst.u3.ip &&
+ port == info->sig_port[dir]) {
+ /* GK->GW */
+ DEBUGP
+ ("nf_nat_ras: set signal address "
+ "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+ NIPQUAD(ip), port,
+ NIPQUAD(ct->tuplehash[!dir].tuple.src.
+ ip), info->sig_port[!dir]);
+ return set_h225_addr(pskb, data, 0, &taddr[i],
+ &ct->tuplehash[!dir].
+ tuple.src.u3,
+ info->sig_port[!dir]);
+ }
+ }
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+static int set_ras_addr(struct sk_buff **pskb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data,
+ TransportAddress *taddr, int count)
+{
+ int dir = CTINFO2DIR(ctinfo);
+ int i;
+ __be16 port;
+ union nf_conntrack_address addr;
+
+ for (i = 0; i < count; i++) {
+ if (get_h225_addr(ct, *data, &taddr[i], &addr, &port) &&
+ addr.ip == ct->tuplehash[dir].tuple.src.u3.ip &&
+ port == ct->tuplehash[dir].tuple.src.u.udp.port) {
+ DEBUGP("nf_nat_ras: set rasAddress "
+ "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+ NIPQUAD(ip), ntohs(port),
+ NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip),
+ ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.
+ port));
+ return set_h225_addr(pskb, data, 0, &taddr[i],
+ &ct->tuplehash[!dir].tuple.dst.u3,
+ ct->tuplehash[!dir].tuple.
+ dst.u.udp.port);
+ }
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+static int nat_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ H245_TransportAddress *taddr,
+ __be16 port, __be16 rtp_port,
+ struct nf_conntrack_expect *rtp_exp,
+ struct nf_conntrack_expect *rtcp_exp)
+{
+ struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
+ int dir = CTINFO2DIR(ctinfo);
+ int i;
+ u_int16_t nated_port;
+
+ /* Set expectations for NAT */
+ rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port;
+ rtp_exp->expectfn = nf_nat_follow_master;
+ rtp_exp->dir = !dir;
+ rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port;
+ rtcp_exp->expectfn = nf_nat_follow_master;
+ rtcp_exp->dir = !dir;
+
+ /* Lookup existing expects */
+ for (i = 0; i < H323_RTP_CHANNEL_MAX; i++) {
+ if (info->rtp_port[i][dir] == rtp_port) {
+ /* Expected */
+
+ /* Use allocated ports first. This will refresh
+ * the expects */
+ rtp_exp->tuple.dst.u.udp.port = info->rtp_port[i][dir];
+ rtcp_exp->tuple.dst.u.udp.port =
+ htons(ntohs(info->rtp_port[i][dir]) + 1);
+ break;
+ } else if (info->rtp_port[i][dir] == 0) {
+ /* Not expected */
+ break;
+ }
+ }
+
+ /* Run out of expectations */
+ if (i >= H323_RTP_CHANNEL_MAX) {
+ if (net_ratelimit())
+ printk("nf_nat_h323: out of expectations\n");
+ return 0;
+ }
+
+ /* Try to get a pair of ports. */
+ for (nated_port = ntohs(rtp_exp->tuple.dst.u.udp.port);
+ nated_port != 0; nated_port += 2) {
+ rtp_exp->tuple.dst.u.udp.port = htons(nated_port);
+ if (nf_conntrack_expect_related(rtp_exp) == 0) {
+ rtcp_exp->tuple.dst.u.udp.port =
+ htons(nated_port + 1);
+ if (nf_conntrack_expect_related(rtcp_exp) == 0)
+ break;
+ nf_conntrack_unexpect_related(rtp_exp);
+ }
+ }
+
+ if (nated_port == 0) { /* No port available */
+ if (net_ratelimit())
+ printk("nf_nat_h323: out of RTP ports\n");
+ return 0;
+ }
+
+ /* Modify signal */
+ if (set_h245_addr(pskb, data, dataoff, taddr,
+ &ct->tuplehash[!dir].tuple.dst.u3,
+ htons((port & htons(1)) ? nated_port + 1 :
+ nated_port)) == 0) {
+ /* Save ports */
+ info->rtp_port[i][dir] = rtp_port;
+ info->rtp_port[i][!dir] = htons(nated_port);
+ } else {
+ nf_conntrack_unexpect_related(rtp_exp);
+ nf_conntrack_unexpect_related(rtcp_exp);
+ return -1;
+ }
+
+ /* Success */
+ DEBUGP("nf_nat_h323: expect RTP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+ NIPQUAD(rtp_exp->tuple.src.ip),
+ ntohs(rtp_exp->tuple.src.u.udp.port),
+ NIPQUAD(rtp_exp->tuple.dst.ip),
+ ntohs(rtp_exp->tuple.dst.u.udp.port));
+ DEBUGP("nf_nat_h323: expect RTCP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+ NIPQUAD(rtcp_exp->tuple.src.ip),
+ ntohs(rtcp_exp->tuple.src.u.udp.port),
+ NIPQUAD(rtcp_exp->tuple.dst.ip),
+ ntohs(rtcp_exp->tuple.dst.u.udp.port));
+
+ return 0;
+}
+
+/****************************************************************************/
+static int nat_t120(struct sk_buff **pskb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ H245_TransportAddress *taddr, __be16 port,
+ struct nf_conntrack_expect *exp)
+{
+ int dir = CTINFO2DIR(ctinfo);
+ u_int16_t nated_port = ntohs(port);
+
+ /* Set expectations for NAT */
+ exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
+ exp->expectfn = nf_nat_follow_master;
+ exp->dir = !dir;
+
+ /* Try to get same port: if not, try to change it. */
+ for (; nated_port != 0; nated_port++) {
+ exp->tuple.dst.u.tcp.port = htons(nated_port);
+ if (nf_conntrack_expect_related(exp) == 0)
+ break;
+ }
+
+ if (nated_port == 0) { /* No port available */
+ if (net_ratelimit())
+ printk("nf_nat_h323: out of TCP ports\n");
+ return 0;
+ }
+
+ /* Modify signal */
+ if (set_h245_addr(pskb, data, dataoff, taddr,
+ &ct->tuplehash[!dir].tuple.dst.u3,
+ htons(nated_port)) < 0) {
+ nf_conntrack_unexpect_related(exp);
+ return -1;
+ }
+
+ DEBUGP("nf_nat_h323: expect T.120 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+ NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
+ NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
+
+ return 0;
+}
+
+/****************************************************************************/
+static int nat_h245(struct sk_buff **pskb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ TransportAddress *taddr, __be16 port,
+ struct nf_conntrack_expect *exp)
+{
+ struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
+ int dir = CTINFO2DIR(ctinfo);
+ u_int16_t nated_port = ntohs(port);
+
+ /* Set expectations for NAT */
+ exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
+ exp->expectfn = nf_nat_follow_master;
+ exp->dir = !dir;
+
+ /* Check existing expects */
+ if (info->sig_port[dir] == port)
+ nated_port = ntohs(info->sig_port[!dir]);
+
+ /* Try to get same port: if not, try to change it. */
+ for (; nated_port != 0; nated_port++) {
+ exp->tuple.dst.u.tcp.port = htons(nated_port);
+ if (nf_conntrack_expect_related(exp) == 0)
+ break;
+ }
+
+ if (nated_port == 0) { /* No port available */
+ if (net_ratelimit())
+ printk("nf_nat_q931: out of TCP ports\n");
+ return 0;
+ }
+
+ /* Modify signal */
+ if (set_h225_addr(pskb, data, dataoff, taddr,
+ &ct->tuplehash[!dir].tuple.dst.u3,
+ htons(nated_port)) == 0) {
+ /* Save ports */
+ info->sig_port[dir] = port;
+ info->sig_port[!dir] = htons(nated_port);
+ } else {
+ nf_conntrack_unexpect_related(exp);
+ return -1;
+ }
+
+ DEBUGP("nf_nat_q931: expect H.245 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+ NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
+ NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
+
+ return 0;
+}
+
+/****************************************************************************
+ * This conntrack expect function replaces nf_conntrack_q931_expect()
+ * which was set by nf_conntrack_h323.c.
+ ****************************************************************************/
+static void ip_nat_q931_expect(struct nf_conn *new,
+ struct nf_conntrack_expect *this)
+{
+ struct ip_nat_range range;
+
+ if (this->tuple.src.u3.ip != 0) { /* Only accept calls from GK */
+ nf_nat_follow_master(new, this);
+ return;
+ }
+
+ /* This must be a fresh one. */
+ BUG_ON(new->status & IPS_NAT_DONE_MASK);
+
+ /* Change src to where master sends to */
+ range.flags = IP_NAT_RANGE_MAP_IPS;
+ range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.u3.ip;
+
+ /* hook doesn't matter, but it has to do source manip */
+ nf_nat_setup_info(new, &range, NF_IP_POST_ROUTING);
+
+ /* For DST manip, map port here to where it's expected. */
+ range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);
+ range.min = range.max = this->saved_proto;
+ range.min_ip = range.max_ip =
+ new->master->tuplehash[!this->dir].tuple.src.u3.ip;
+
+ /* hook doesn't matter, but it has to do destination manip */
+ nf_nat_setup_info(new, &range, NF_IP_PRE_ROUTING);
+}
+
+/****************************************************************************/
+static int nat_q931(struct sk_buff **pskb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, TransportAddress *taddr, int idx,
+ __be16 port, struct nf_conntrack_expect *exp)
+{
+ struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
+ int dir = CTINFO2DIR(ctinfo);
+ u_int16_t nated_port = ntohs(port);
+ union nf_conntrack_address addr;
+
+ /* Set expectations for NAT */
+ exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
+ exp->expectfn = ip_nat_q931_expect;
+ exp->dir = !dir;
+
+ /* Check existing expects */
+ if (info->sig_port[dir] == port)
+ nated_port = ntohs(info->sig_port[!dir]);
+
+ /* Try to get same port: if not, try to change it. */
+ for (; nated_port != 0; nated_port++) {
+ exp->tuple.dst.u.tcp.port = htons(nated_port);
+ if (nf_conntrack_expect_related(exp) == 0)
+ break;
+ }
+
+ if (nated_port == 0) { /* No port available */
+ if (net_ratelimit())
+ printk("nf_nat_ras: out of TCP ports\n");
+ return 0;
+ }
+
+ /* Modify signal */
+ if (set_h225_addr(pskb, data, 0, &taddr[idx],
+ &ct->tuplehash[!dir].tuple.dst.u3,
+ htons(nated_port)) == 0) {
+ /* Save ports */
+ info->sig_port[dir] = port;
+ info->sig_port[!dir] = htons(nated_port);
+
+ /* Fix for Gnomemeeting */
+ if (idx > 0 &&
+ get_h225_addr(ct, *data, &taddr[0], &addr, &port) &&
+ (ntohl(addr.ip) & 0xff000000) == 0x7f000000) {
+ set_h225_addr_hook(pskb, data, 0, &taddr[0],
+ &ct->tuplehash[!dir].tuple.dst.u3,
+ info->sig_port[!dir]);
+ }
+ } else {
+ nf_conntrack_unexpect_related(exp);
+ return -1;
+ }
+
+ /* Success */
+ DEBUGP("nf_nat_ras: expect Q.931 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+ NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
+ NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
+
+ return 0;
+}
+
+/****************************************************************************/
+static void ip_nat_callforwarding_expect(struct nf_conn *new,
+ struct nf_conntrack_expect *this)
+{
+ struct nf_nat_range range;
+
+ /* This must be a fresh one. */
+ BUG_ON(new->status & IPS_NAT_DONE_MASK);
+
+ /* Change src to where master sends to */
+ range.flags = IP_NAT_RANGE_MAP_IPS;
+ range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.u3.ip;
+
+ /* hook doesn't matter, but it has to do source manip */
+ nf_nat_setup_info(new, &range, NF_IP_POST_ROUTING);
+
+ /* For DST manip, map port here to where it's expected. */
+ range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);
+ range.min = range.max = this->saved_proto;
+ range.min_ip = range.max_ip = this->saved_ip;
+
+ /* hook doesn't matter, but it has to do destination manip */
+ nf_nat_setup_info(new, &range, NF_IP_PRE_ROUTING);
+}
+
+/****************************************************************************/
+static int nat_callforwarding(struct sk_buff **pskb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ TransportAddress *taddr, __be16 port,
+ struct nf_conntrack_expect *exp)
+{
+ int dir = CTINFO2DIR(ctinfo);
+ u_int16_t nated_port;
+
+ /* Set expectations for NAT */
+ exp->saved_ip = exp->tuple.dst.u3.ip;
+ exp->tuple.dst.u3.ip = ct->tuplehash[!dir].tuple.dst.u3.ip;
+ exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
+ exp->expectfn = ip_nat_callforwarding_expect;
+ exp->dir = !dir;
+
+ /* Try to get same port: if not, try to change it. */
+ for (nated_port = ntohs(port); nated_port != 0; nated_port++) {
+ exp->tuple.dst.u.tcp.port = htons(nated_port);
+ if (nf_conntrack_expect_related(exp) == 0)
+ break;
+ }
+
+ if (nated_port == 0) { /* No port available */
+ if (net_ratelimit())
+ printk("nf_nat_q931: out of TCP ports\n");
+ return 0;
+ }
+
+ /* Modify signal */
+ if (!set_h225_addr(pskb, data, dataoff, taddr,
+ &ct->tuplehash[!dir].tuple.dst.u3,
+ htons(nated_port)) == 0) {
+ nf_conntrack_unexpect_related(exp);
+ return -1;
+ }
+
+ /* Success */
+ DEBUGP("nf_nat_q931: expect Call Forwarding "
+ "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+ NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
+ NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
+
+ return 0;
+}
+
+/****************************************************************************/
+static int __init init(void)
+{
+ BUG_ON(rcu_dereference(set_h245_addr_hook) != NULL);
+ BUG_ON(rcu_dereference(set_h225_addr_hook) != NULL);
+ BUG_ON(rcu_dereference(set_sig_addr_hook) != NULL);
+ BUG_ON(rcu_dereference(set_ras_addr_hook) != NULL);
+ BUG_ON(rcu_dereference(nat_rtp_rtcp_hook) != NULL);
+ BUG_ON(rcu_dereference(nat_t120_hook) != NULL);
+ BUG_ON(rcu_dereference(nat_h245_hook) != NULL);
+ BUG_ON(rcu_dereference(nat_callforwarding_hook) != NULL);
+ BUG_ON(rcu_dereference(nat_q931_hook) != NULL);
+
+ rcu_assign_pointer(set_h245_addr_hook, set_h245_addr);
+ rcu_assign_pointer(set_h225_addr_hook, set_h225_addr);
+ rcu_assign_pointer(set_sig_addr_hook, set_sig_addr);
+ rcu_assign_pointer(set_ras_addr_hook, set_ras_addr);
+ rcu_assign_pointer(nat_rtp_rtcp_hook, nat_rtp_rtcp);
+ rcu_assign_pointer(nat_t120_hook, nat_t120);
+ rcu_assign_pointer(nat_h245_hook, nat_h245);
+ rcu_assign_pointer(nat_callforwarding_hook, nat_callforwarding);
+ rcu_assign_pointer(nat_q931_hook, nat_q931);
+
+ DEBUGP("nf_nat_h323: init success\n");
+ return 0;
+}
+
+/****************************************************************************/
+static void __exit fini(void)
+{
+ rcu_assign_pointer(set_h245_addr_hook, NULL);
+ rcu_assign_pointer(set_h225_addr_hook, NULL);
+ rcu_assign_pointer(set_sig_addr_hook, NULL);
+ rcu_assign_pointer(set_ras_addr_hook, NULL);
+ rcu_assign_pointer(nat_rtp_rtcp_hook, NULL);
+ rcu_assign_pointer(nat_t120_hook, NULL);
+ rcu_assign_pointer(nat_h245_hook, NULL);
+ rcu_assign_pointer(nat_callforwarding_hook, NULL);
+ rcu_assign_pointer(nat_q931_hook, NULL);
+ synchronize_rcu();
+}
+
+/****************************************************************************/
+module_init(init);
+module_exit(fini);
+
+MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
+MODULE_DESCRIPTION("H.323 NAT helper");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ip_nat_h323");
diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c
new file mode 100644
index 000000000000..98fbfc84d183
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_helper.c
@@ -0,0 +1,433 @@
+/* ip_nat_helper.c - generic support functions for NAT helpers
+ *
+ * (C) 2000-2002 Harald Welte <laforge@netfilter.org>
+ * (C) 2003-2006 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/kmod.h>
+#include <linux/types.h>
+#include <linux/timer.h>
+#include <linux/skbuff.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <net/checksum.h>
+#include <net/tcp.h>
+
+#include <linux/netfilter_ipv4.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_conntrack_expect.h>
+#include <net/netfilter/nf_nat.h>
+#include <net/netfilter/nf_nat_protocol.h>
+#include <net/netfilter/nf_nat_core.h>
+#include <net/netfilter/nf_nat_helper.h>
+
+#if 0
+#define DEBUGP printk
+#define DUMP_OFFSET(x) printk("offset_before=%d, offset_after=%d, correction_pos=%u\n", x->offset_before, x->offset_after, x->correction_pos);
+#else
+#define DEBUGP(format, args...)
+#define DUMP_OFFSET(x)
+#endif
+
+static DEFINE_SPINLOCK(nf_nat_seqofs_lock);
+
+/* Setup TCP sequence correction given this change at this sequence */
+static inline void
+adjust_tcp_sequence(u32 seq,
+ int sizediff,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo)
+{
+ int dir;
+ struct nf_nat_seq *this_way, *other_way;
+ struct nf_conn_nat *nat = nfct_nat(ct);
+
+ DEBUGP("nf_nat_resize_packet: old_size = %u, new_size = %u\n",
+ (*skb)->len, new_size);
+
+ dir = CTINFO2DIR(ctinfo);
+
+ this_way = &nat->info.seq[dir];
+ other_way = &nat->info.seq[!dir];
+
+ DEBUGP("nf_nat_resize_packet: Seq_offset before: ");
+ DUMP_OFFSET(this_way);
+
+ spin_lock_bh(&nf_nat_seqofs_lock);
+
+ /* SYN adjust. If it's uninitialized, or this is after last
+ * correction, record it: we don't handle more than one
+ * adjustment in the window, but do deal with common case of a
+ * retransmit */
+ if (this_way->offset_before == this_way->offset_after ||
+ before(this_way->correction_pos, seq)) {
+ this_way->correction_pos = seq;
+ this_way->offset_before = this_way->offset_after;
+ this_way->offset_after += sizediff;
+ }
+ spin_unlock_bh(&nf_nat_seqofs_lock);
+
+ DEBUGP("nf_nat_resize_packet: Seq_offset after: ");
+ DUMP_OFFSET(this_way);
+}
+
+/* Frobs data inside this packet, which is linear. */
+static void mangle_contents(struct sk_buff *skb,
+ unsigned int dataoff,
+ unsigned int match_offset,
+ unsigned int match_len,
+ const char *rep_buffer,
+ unsigned int rep_len)
+{
+ unsigned char *data;
+
+ BUG_ON(skb_is_nonlinear(skb));
+ data = (unsigned char *)skb->nh.iph + dataoff;
+
+ /* move post-replacement */
+ memmove(data + match_offset + rep_len,
+ data + match_offset + match_len,
+ skb->tail - (data + match_offset + match_len));
+
+ /* insert data from buffer */
+ memcpy(data + match_offset, rep_buffer, rep_len);
+
+ /* update skb info */
+ if (rep_len > match_len) {
+ DEBUGP("nf_nat_mangle_packet: Extending packet by "
+ "%u from %u bytes\n", rep_len - match_len,
+ skb->len);
+ skb_put(skb, rep_len - match_len);
+ } else {
+ DEBUGP("nf_nat_mangle_packet: Shrinking packet from "
+ "%u from %u bytes\n", match_len - rep_len,
+ skb->len);
+ __skb_trim(skb, skb->len + rep_len - match_len);
+ }
+
+ /* fix IP hdr checksum information */
+ skb->nh.iph->tot_len = htons(skb->len);
+ ip_send_check(skb->nh.iph);
+}
+
+/* Unusual, but possible case. */
+static int enlarge_skb(struct sk_buff **pskb, unsigned int extra)
+{
+ struct sk_buff *nskb;
+
+ if ((*pskb)->len + extra > 65535)
+ return 0;
+
+ nskb = skb_copy_expand(*pskb, skb_headroom(*pskb), extra, GFP_ATOMIC);
+ if (!nskb)
+ return 0;
+
+ /* Transfer socket to new skb. */
+ if ((*pskb)->sk)
+ skb_set_owner_w(nskb, (*pskb)->sk);
+ kfree_skb(*pskb);
+ *pskb = nskb;
+ return 1;
+}
+
+/* Generic function for mangling variable-length address changes inside
+ * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX
+ * command in FTP).
+ *
+ * Takes care about all the nasty sequence number changes, checksumming,
+ * skb enlargement, ...
+ *
+ * */
+int
+nf_nat_mangle_tcp_packet(struct sk_buff **pskb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned int match_offset,
+ unsigned int match_len,
+ const char *rep_buffer,
+ unsigned int rep_len)
+{
+ struct iphdr *iph;
+ struct tcphdr *tcph;
+ int oldlen, datalen;
+
+ if (!skb_make_writable(pskb, (*pskb)->len))
+ return 0;
+
+ if (rep_len > match_len &&
+ rep_len - match_len > skb_tailroom(*pskb) &&
+ !enlarge_skb(pskb, rep_len - match_len))
+ return 0;
+
+ SKB_LINEAR_ASSERT(*pskb);
+
+ iph = (*pskb)->nh.iph;
+ tcph = (void *)iph + iph->ihl*4;
+
+ oldlen = (*pskb)->len - iph->ihl*4;
+ mangle_contents(*pskb, iph->ihl*4 + tcph->doff*4,
+ match_offset, match_len, rep_buffer, rep_len);
+
+ datalen = (*pskb)->len - iph->ihl*4;
+ if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
+ tcph->check = 0;
+ tcph->check = tcp_v4_check(tcph, datalen,
+ iph->saddr, iph->daddr,
+ csum_partial((char *)tcph,
+ datalen, 0));
+ } else
+ nf_proto_csum_replace2(&tcph->check, *pskb,
+ htons(oldlen), htons(datalen), 1);
+
+ if (rep_len != match_len) {
+ set_bit(IPS_SEQ_ADJUST_BIT, &ct->status);
+ adjust_tcp_sequence(ntohl(tcph->seq),
+ (int)rep_len - (int)match_len,
+ ct, ctinfo);
+ /* Tell TCP window tracking about seq change */
+ nf_conntrack_tcp_update(*pskb, (*pskb)->nh.iph->ihl*4,
+ ct, CTINFO2DIR(ctinfo));
+ }
+ return 1;
+}
+EXPORT_SYMBOL(nf_nat_mangle_tcp_packet);
+
+/* Generic function for mangling variable-length address changes inside
+ * NATed UDP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX
+ * command in the Amanda protocol)
+ *
+ * Takes care about all the nasty sequence number changes, checksumming,
+ * skb enlargement, ...
+ *
+ * XXX - This function could be merged with nf_nat_mangle_tcp_packet which
+ * should be fairly easy to do.
+ */
+int
+nf_nat_mangle_udp_packet(struct sk_buff **pskb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned int match_offset,
+ unsigned int match_len,
+ const char *rep_buffer,
+ unsigned int rep_len)
+{
+ struct iphdr *iph;
+ struct udphdr *udph;
+ int datalen, oldlen;
+
+ /* UDP helpers might accidentally mangle the wrong packet */
+ iph = (*pskb)->nh.iph;
+ if ((*pskb)->len < iph->ihl*4 + sizeof(*udph) +
+ match_offset + match_len)
+ return 0;
+
+ if (!skb_make_writable(pskb, (*pskb)->len))
+ return 0;
+
+ if (rep_len > match_len &&
+ rep_len - match_len > skb_tailroom(*pskb) &&
+ !enlarge_skb(pskb, rep_len - match_len))
+ return 0;
+
+ iph = (*pskb)->nh.iph;
+ udph = (void *)iph + iph->ihl*4;
+
+ oldlen = (*pskb)->len - iph->ihl*4;
+ mangle_contents(*pskb, iph->ihl*4 + sizeof(*udph),
+ match_offset, match_len, rep_buffer, rep_len);
+
+ /* update the length of the UDP packet */
+ datalen = (*pskb)->len - iph->ihl*4;
+ udph->len = htons(datalen);
+
+ /* fix udp checksum if udp checksum was previously calculated */
+ if (!udph->check && (*pskb)->ip_summed != CHECKSUM_PARTIAL)
+ return 1;
+
+ if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
+ udph->check = 0;
+ udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr,
+ datalen, IPPROTO_UDP,
+ csum_partial((char *)udph,
+ datalen, 0));
+ if (!udph->check)
+ udph->check = CSUM_MANGLED_0;
+ } else
+ nf_proto_csum_replace2(&udph->check, *pskb,
+ htons(oldlen), htons(datalen), 1);
+
+ return 1;
+}
+EXPORT_SYMBOL(nf_nat_mangle_udp_packet);
+
+/* Adjust one found SACK option including checksum correction */
+static void
+sack_adjust(struct sk_buff *skb,
+ struct tcphdr *tcph,
+ unsigned int sackoff,
+ unsigned int sackend,
+ struct nf_nat_seq *natseq)
+{
+ while (sackoff < sackend) {
+ struct tcp_sack_block_wire *sack;
+ __be32 new_start_seq, new_end_seq;
+
+ sack = (void *)skb->data + sackoff;
+ if (after(ntohl(sack->start_seq) - natseq->offset_before,
+ natseq->correction_pos))
+ new_start_seq = htonl(ntohl(sack->start_seq)
+ - natseq->offset_after);
+ else
+ new_start_seq = htonl(ntohl(sack->start_seq)
+ - natseq->offset_before);
+
+ if (after(ntohl(sack->end_seq) - natseq->offset_before,
+ natseq->correction_pos))
+ new_end_seq = htonl(ntohl(sack->end_seq)
+ - natseq->offset_after);
+ else
+ new_end_seq = htonl(ntohl(sack->end_seq)
+ - natseq->offset_before);
+
+ DEBUGP("sack_adjust: start_seq: %d->%d, end_seq: %d->%d\n",
+ ntohl(sack->start_seq), new_start_seq,
+ ntohl(sack->end_seq), new_end_seq);
+
+ nf_proto_csum_replace4(&tcph->check, skb,
+ sack->start_seq, new_start_seq, 0);
+ nf_proto_csum_replace4(&tcph->check, skb,
+ sack->end_seq, new_end_seq, 0);
+ sack->start_seq = new_start_seq;
+ sack->end_seq = new_end_seq;
+ sackoff += sizeof(*sack);
+ }
+}
+
+/* TCP SACK sequence number adjustment */
+static inline unsigned int
+nf_nat_sack_adjust(struct sk_buff **pskb,
+ struct tcphdr *tcph,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo)
+{
+ unsigned int dir, optoff, optend;
+ struct nf_conn_nat *nat = nfct_nat(ct);
+
+ optoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct tcphdr);
+ optend = (*pskb)->nh.iph->ihl*4 + tcph->doff*4;
+
+ if (!skb_make_writable(pskb, optend))
+ return 0;
+
+ dir = CTINFO2DIR(ctinfo);
+
+ while (optoff < optend) {
+ /* Usually: option, length. */
+ unsigned char *op = (*pskb)->data + optoff;
+
+ switch (op[0]) {
+ case TCPOPT_EOL:
+ return 1;
+ case TCPOPT_NOP:
+ optoff++;
+ continue;
+ default:
+ /* no partial options */
+ if (optoff + 1 == optend ||
+ optoff + op[1] > optend ||
+ op[1] < 2)
+ return 0;
+ if (op[0] == TCPOPT_SACK &&
+ op[1] >= 2+TCPOLEN_SACK_PERBLOCK &&
+ ((op[1] - 2) % TCPOLEN_SACK_PERBLOCK) == 0)
+ sack_adjust(*pskb, tcph, optoff+2,
+ optoff+op[1],
+ &nat->info.seq[!dir]);
+ optoff += op[1];
+ }
+ }
+ return 1;
+}
+
+/* TCP sequence number adjustment. Returns 1 on success, 0 on failure */
+int
+nf_nat_seq_adjust(struct sk_buff **pskb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo)
+{
+ struct tcphdr *tcph;
+ int dir;
+ __be32 newseq, newack;
+ struct nf_conn_nat *nat = nfct_nat(ct);
+ struct nf_nat_seq *this_way, *other_way;
+
+ dir = CTINFO2DIR(ctinfo);
+
+ this_way = &nat->info.seq[dir];
+ other_way = &nat->info.seq[!dir];
+
+ if (!skb_make_writable(pskb, (*pskb)->nh.iph->ihl*4+sizeof(*tcph)))
+ return 0;
+
+ tcph = (void *)(*pskb)->data + (*pskb)->nh.iph->ihl*4;
+ if (after(ntohl(tcph->seq), this_way->correction_pos))
+ newseq = htonl(ntohl(tcph->seq) + this_way->offset_after);
+ else
+ newseq = htonl(ntohl(tcph->seq) + this_way->offset_before);
+
+ if (after(ntohl(tcph->ack_seq) - other_way->offset_before,
+ other_way->correction_pos))
+ newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_after);
+ else
+ newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_before);
+
+ nf_proto_csum_replace4(&tcph->check, *pskb, tcph->seq, newseq, 0);
+ nf_proto_csum_replace4(&tcph->check, *pskb, tcph->ack_seq, newack, 0);
+
+ DEBUGP("Adjusting sequence number from %u->%u, ack from %u->%u\n",
+ ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq),
+ ntohl(newack));
+
+ tcph->seq = newseq;
+ tcph->ack_seq = newack;
+
+ if (!nf_nat_sack_adjust(pskb, tcph, ct, ctinfo))
+ return 0;
+
+ nf_conntrack_tcp_update(*pskb, (*pskb)->nh.iph->ihl*4, ct, dir);
+
+ return 1;
+}
+EXPORT_SYMBOL(nf_nat_seq_adjust);
+
+/* Setup NAT on this expected conntrack so it follows master. */
+/* If we fail to get a free NAT slot, we'll get dropped on confirm */
+void nf_nat_follow_master(struct nf_conn *ct,
+ struct nf_conntrack_expect *exp)
+{
+ struct nf_nat_range range;
+
+ /* This must be a fresh one. */
+ BUG_ON(ct->status & IPS_NAT_DONE_MASK);
+
+ /* Change src to where master sends to */
+ range.flags = IP_NAT_RANGE_MAP_IPS;
+ range.min_ip = range.max_ip
+ = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip;
+ /* hook doesn't matter, but it has to do source manip */
+ nf_nat_setup_info(ct, &range, NF_IP_POST_ROUTING);
+
+ /* For DST manip, map port here to where it's expected. */
+ range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);
+ range.min = range.max = exp->saved_proto;
+ range.min_ip = range.max_ip
+ = ct->master->tuplehash[!exp->dir].tuple.src.u3.ip;
+ /* hook doesn't matter, but it has to do destination manip */
+ nf_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING);
+}
+EXPORT_SYMBOL(nf_nat_follow_master);
diff --git a/net/ipv4/netfilter/nf_nat_irc.c b/net/ipv4/netfilter/nf_nat_irc.c
new file mode 100644
index 000000000000..9b8c0daea744
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_irc.c
@@ -0,0 +1,101 @@
+/* IRC extension for TCP NAT alteration.
+ *
+ * (C) 2000-2001 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2004 Rusty Russell <rusty@rustcorp.com.au> IBM Corporation
+ * based on a copy of RR's ip_nat_ftp.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.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/tcp.h>
+#include <linux/kernel.h>
+
+#include <net/netfilter/nf_nat.h>
+#include <net/netfilter/nf_nat_helper.h>
+#include <net/netfilter/nf_nat_rule.h>
+#include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_conntrack_expect.h>
+#include <linux/netfilter/nf_conntrack_irc.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
+MODULE_DESCRIPTION("IRC (DCC) NAT helper");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ip_nat_irc");
+
+static unsigned int help(struct sk_buff **pskb,
+ enum ip_conntrack_info ctinfo,
+ unsigned int matchoff,
+ unsigned int matchlen,
+ struct nf_conntrack_expect *exp)
+{
+ char buffer[sizeof("4294967296 65635")];
+ u_int32_t ip;
+ u_int16_t port;
+ unsigned int ret;
+
+ DEBUGP("IRC_NAT: info (seq %u + %u) in %u\n",
+ expect->seq, exp_irc_info->len, ntohl(tcph->seq));
+
+ /* Reply comes from server. */
+ exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
+ exp->dir = IP_CT_DIR_REPLY;
+ exp->expectfn = nf_nat_follow_master;
+
+ /* Try to get same port: if not, try to change it. */
+ for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
+ exp->tuple.dst.u.tcp.port = htons(port);
+ if (nf_conntrack_expect_related(exp) == 0)
+ break;
+ }
+
+ if (port == 0)
+ return NF_DROP;
+
+ ip = ntohl(exp->master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip);
+ sprintf(buffer, "%u %u", ip, port);
+ DEBUGP("nf_nat_irc: inserting '%s' == %u.%u.%u.%u, port %u\n",
+ buffer, NIPQUAD(ip), port);
+
+ ret = nf_nat_mangle_tcp_packet(pskb, exp->master, ctinfo,
+ matchoff, matchlen, buffer,
+ strlen(buffer));
+ if (ret != NF_ACCEPT)
+ nf_conntrack_unexpect_related(exp);
+ return ret;
+}
+
+static void __exit nf_nat_irc_fini(void)
+{
+ rcu_assign_pointer(nf_nat_irc_hook, NULL);
+ synchronize_rcu();
+}
+
+static int __init nf_nat_irc_init(void)
+{
+ BUG_ON(rcu_dereference(nf_nat_irc_hook));
+ rcu_assign_pointer(nf_nat_irc_hook, help);
+ return 0;
+}
+
+/* Prior to 2.6.11, we had a ports param. No longer, but don't break users. */
+static int warn_set(const char *val, struct kernel_param *kp)
+{
+ printk(KERN_INFO KBUILD_MODNAME
+ ": kernel >= 2.6.10 only uses 'ports' for conntrack modules\n");
+ return 0;
+}
+module_param_call(ports, warn_set, NULL, NULL, 0);
+
+module_init(nf_nat_irc_init);
+module_exit(nf_nat_irc_fini);
diff --git a/net/ipv4/netfilter/nf_nat_pptp.c b/net/ipv4/netfilter/nf_nat_pptp.c
new file mode 100644
index 000000000000..0ae45b79a4eb
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_pptp.c
@@ -0,0 +1,315 @@
+/*
+ * nf_nat_pptp.c
+ *
+ * NAT support for PPTP (Point to Point Tunneling Protocol).
+ * PPTP is a a protocol for creating virtual private networks.
+ * It is a specification defined by Microsoft and some vendors
+ * working with Microsoft. PPTP is built on top of a modified
+ * version of the Internet Generic Routing Encapsulation Protocol.
+ * GRE is defined in RFC 1701 and RFC 1702. Documentation of
+ * PPTP can be found in RFC 2637
+ *
+ * (C) 2000-2005 by Harald Welte <laforge@gnumonks.org>
+ *
+ * Development of this code funded by Astaro AG (http://www.astaro.com/)
+ *
+ * TODO: - NAT to a unique tuple, not to TCP source port
+ * (needs netfilter tuple reservation)
+ */
+
+#include <linux/module.h>
+#include <linux/tcp.h>
+
+#include <net/netfilter/nf_nat.h>
+#include <net/netfilter/nf_nat_helper.h>
+#include <net/netfilter/nf_nat_rule.h>
+#include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_conntrack_expect.h>
+#include <linux/netfilter/nf_conntrack_proto_gre.h>
+#include <linux/netfilter/nf_conntrack_pptp.h>
+
+#define NF_NAT_PPTP_VERSION "3.0"
+
+#define REQ_CID(req, off) (*(__be16 *)((char *)(req) + (off)))
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
+MODULE_DESCRIPTION("Netfilter NAT helper module for PPTP");
+MODULE_ALIAS("ip_nat_pptp");
+
+#if 0
+extern const char *pptp_msg_name[];
+#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, \
+ __FUNCTION__, ## args)
+#else
+#define DEBUGP(format, args...)
+#endif
+
+static void pptp_nat_expected(struct nf_conn *ct,
+ struct nf_conntrack_expect *exp)
+{
+ struct nf_conn *master = ct->master;
+ struct nf_conntrack_expect *other_exp;
+ struct nf_conntrack_tuple t;
+ struct nf_ct_pptp_master *ct_pptp_info;
+ struct nf_nat_pptp *nat_pptp_info;
+ struct ip_nat_range range;
+
+ ct_pptp_info = &nfct_help(master)->help.ct_pptp_info;
+ nat_pptp_info = &nfct_nat(master)->help.nat_pptp_info;
+
+ /* And here goes the grand finale of corrosion... */
+ if (exp->dir == IP_CT_DIR_ORIGINAL) {
+ DEBUGP("we are PNS->PAC\n");
+ /* therefore, build tuple for PAC->PNS */
+ t.src.l3num = AF_INET;
+ t.src.u3.ip = master->tuplehash[!exp->dir].tuple.src.u3.ip;
+ t.src.u.gre.key = ct_pptp_info->pac_call_id;
+ t.dst.u3.ip = master->tuplehash[!exp->dir].tuple.dst.u3.ip;
+ t.dst.u.gre.key = ct_pptp_info->pns_call_id;
+ t.dst.protonum = IPPROTO_GRE;
+ } else {
+ DEBUGP("we are PAC->PNS\n");
+ /* build tuple for PNS->PAC */
+ t.src.l3num = AF_INET;
+ t.src.u3.ip = master->tuplehash[exp->dir].tuple.src.u3.ip;
+ t.src.u.gre.key = nat_pptp_info->pns_call_id;
+ t.dst.u3.ip = master->tuplehash[exp->dir].tuple.dst.u3.ip;
+ t.dst.u.gre.key = nat_pptp_info->pac_call_id;
+ t.dst.protonum = IPPROTO_GRE;
+ }
+
+ DEBUGP("trying to unexpect other dir: ");
+ NF_CT_DUMP_TUPLE(&t);
+ other_exp = nf_conntrack_expect_find_get(&t);
+ if (other_exp) {
+ nf_conntrack_unexpect_related(other_exp);
+ nf_conntrack_expect_put(other_exp);
+ DEBUGP("success\n");
+ } else {
+ DEBUGP("not found!\n");
+ }
+
+ /* This must be a fresh one. */
+ BUG_ON(ct->status & IPS_NAT_DONE_MASK);
+
+ /* Change src to where master sends to */
+ range.flags = IP_NAT_RANGE_MAP_IPS;
+ range.min_ip = range.max_ip
+ = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip;
+ if (exp->dir == IP_CT_DIR_ORIGINAL) {
+ range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
+ range.min = range.max = exp->saved_proto;
+ }
+ /* hook doesn't matter, but it has to do source manip */
+ nf_nat_setup_info(ct, &range, NF_IP_POST_ROUTING);
+
+ /* For DST manip, map port here to where it's expected. */
+ range.flags = IP_NAT_RANGE_MAP_IPS;
+ range.min_ip = range.max_ip
+ = ct->master->tuplehash[!exp->dir].tuple.src.u3.ip;
+ if (exp->dir == IP_CT_DIR_REPLY) {
+ range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
+ range.min = range.max = exp->saved_proto;
+ }
+ /* hook doesn't matter, but it has to do destination manip */
+ nf_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING);
+}
+
+/* outbound packets == from PNS to PAC */
+static int
+pptp_outbound_pkt(struct sk_buff **pskb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ struct PptpControlHeader *ctlh,
+ union pptp_ctrl_union *pptpReq)
+
+{
+ struct nf_ct_pptp_master *ct_pptp_info;
+ struct nf_nat_pptp *nat_pptp_info;
+ u_int16_t msg;
+ __be16 new_callid;
+ unsigned int cid_off;
+
+ ct_pptp_info = &nfct_help(ct)->help.ct_pptp_info;
+ nat_pptp_info = &nfct_nat(ct)->help.nat_pptp_info;
+
+ new_callid = ct_pptp_info->pns_call_id;
+
+ switch (msg = ntohs(ctlh->messageType)) {
+ case PPTP_OUT_CALL_REQUEST:
+ cid_off = offsetof(union pptp_ctrl_union, ocreq.callID);
+ /* FIXME: ideally we would want to reserve a call ID
+ * here. current netfilter NAT core is not able to do
+ * this :( For now we use TCP source port. This breaks
+ * multiple calls within one control session */
+
+ /* save original call ID in nat_info */
+ nat_pptp_info->pns_call_id = ct_pptp_info->pns_call_id;
+
+ /* don't use tcph->source since we are at a DSTmanip
+ * hook (e.g. PREROUTING) and pkt is not mangled yet */
+ new_callid = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.tcp.port;
+
+ /* save new call ID in ct info */
+ ct_pptp_info->pns_call_id = new_callid;
+ break;
+ case PPTP_IN_CALL_REPLY:
+ cid_off = offsetof(union pptp_ctrl_union, icack.callID);
+ break;
+ case PPTP_CALL_CLEAR_REQUEST:
+ cid_off = offsetof(union pptp_ctrl_union, clrreq.callID);
+ break;
+ default:
+ DEBUGP("unknown outbound packet 0x%04x:%s\n", msg,
+ (msg <= PPTP_MSG_MAX)?
+ pptp_msg_name[msg]:pptp_msg_name[0]);
+ /* fall through */
+ case PPTP_SET_LINK_INFO:
+ /* only need to NAT in case PAC is behind NAT box */
+ case PPTP_START_SESSION_REQUEST:
+ case PPTP_START_SESSION_REPLY:
+ case PPTP_STOP_SESSION_REQUEST:
+ case PPTP_STOP_SESSION_REPLY:
+ case PPTP_ECHO_REQUEST:
+ case PPTP_ECHO_REPLY:
+ /* no need to alter packet */
+ return NF_ACCEPT;
+ }
+
+ /* only OUT_CALL_REQUEST, IN_CALL_REPLY, CALL_CLEAR_REQUEST pass
+ * down to here */
+ DEBUGP("altering call id from 0x%04x to 0x%04x\n",
+ ntohs(REQ_CID(pptpReq, cid_off)), ntohs(new_callid));
+
+ /* mangle packet */
+ if (nf_nat_mangle_tcp_packet(pskb, ct, ctinfo,
+ cid_off + sizeof(struct pptp_pkt_hdr) +
+ sizeof(struct PptpControlHeader),
+ sizeof(new_callid), (char *)&new_callid,
+ sizeof(new_callid)) == 0)
+ return NF_DROP;
+ return NF_ACCEPT;
+}
+
+static void
+pptp_exp_gre(struct nf_conntrack_expect *expect_orig,
+ struct nf_conntrack_expect *expect_reply)
+{
+ struct nf_conn *ct = expect_orig->master;
+ struct nf_ct_pptp_master *ct_pptp_info;
+ struct nf_nat_pptp *nat_pptp_info;
+
+ ct_pptp_info = &nfct_help(ct)->help.ct_pptp_info;
+ nat_pptp_info = &nfct_nat(ct)->help.nat_pptp_info;
+
+ /* save original PAC call ID in nat_info */
+ nat_pptp_info->pac_call_id = ct_pptp_info->pac_call_id;
+
+ /* alter expectation for PNS->PAC direction */
+ expect_orig->saved_proto.gre.key = ct_pptp_info->pns_call_id;
+ expect_orig->tuple.src.u.gre.key = nat_pptp_info->pns_call_id;
+ expect_orig->tuple.dst.u.gre.key = ct_pptp_info->pac_call_id;
+ expect_orig->dir = IP_CT_DIR_ORIGINAL;
+
+ /* alter expectation for PAC->PNS direction */
+ expect_reply->saved_proto.gre.key = nat_pptp_info->pns_call_id;
+ expect_reply->tuple.src.u.gre.key = nat_pptp_info->pac_call_id;
+ expect_reply->tuple.dst.u.gre.key = ct_pptp_info->pns_call_id;
+ expect_reply->dir = IP_CT_DIR_REPLY;
+}
+
+/* inbound packets == from PAC to PNS */
+static int
+pptp_inbound_pkt(struct sk_buff **pskb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ struct PptpControlHeader *ctlh,
+ union pptp_ctrl_union *pptpReq)
+{
+ struct nf_nat_pptp *nat_pptp_info;
+ u_int16_t msg;
+ __be16 new_pcid;
+ unsigned int pcid_off;
+
+ nat_pptp_info = &nfct_nat(ct)->help.nat_pptp_info;
+ new_pcid = nat_pptp_info->pns_call_id;
+
+ switch (msg = ntohs(ctlh->messageType)) {
+ case PPTP_OUT_CALL_REPLY:
+ pcid_off = offsetof(union pptp_ctrl_union, ocack.peersCallID);
+ break;
+ case PPTP_IN_CALL_CONNECT:
+ pcid_off = offsetof(union pptp_ctrl_union, iccon.peersCallID);
+ break;
+ case PPTP_IN_CALL_REQUEST:
+ /* only need to nat in case PAC is behind NAT box */
+ return NF_ACCEPT;
+ case PPTP_WAN_ERROR_NOTIFY:
+ pcid_off = offsetof(union pptp_ctrl_union, wanerr.peersCallID);
+ break;
+ case PPTP_CALL_DISCONNECT_NOTIFY:
+ pcid_off = offsetof(union pptp_ctrl_union, disc.callID);
+ break;
+ case PPTP_SET_LINK_INFO:
+ pcid_off = offsetof(union pptp_ctrl_union, setlink.peersCallID);
+ break;
+ default:
+ DEBUGP("unknown inbound packet %s\n", (msg <= PPTP_MSG_MAX)?
+ pptp_msg_name[msg]:pptp_msg_name[0]);
+ /* fall through */
+ case PPTP_START_SESSION_REQUEST:
+ case PPTP_START_SESSION_REPLY:
+ case PPTP_STOP_SESSION_REQUEST:
+ case PPTP_STOP_SESSION_REPLY:
+ case PPTP_ECHO_REQUEST:
+ case PPTP_ECHO_REPLY:
+ /* no need to alter packet */
+ return NF_ACCEPT;
+ }
+
+ /* only OUT_CALL_REPLY, IN_CALL_CONNECT, IN_CALL_REQUEST,
+ * WAN_ERROR_NOTIFY, CALL_DISCONNECT_NOTIFY pass down here */
+
+ /* mangle packet */
+ DEBUGP("altering peer call id from 0x%04x to 0x%04x\n",
+ ntohs(REQ_CID(pptpReq, pcid_off)), ntohs(new_pcid));
+
+ if (nf_nat_mangle_tcp_packet(pskb, ct, ctinfo,
+ pcid_off + sizeof(struct pptp_pkt_hdr) +
+ sizeof(struct PptpControlHeader),
+ sizeof(new_pcid), (char *)&new_pcid,
+ sizeof(new_pcid)) == 0)
+ return NF_DROP;
+ return NF_ACCEPT;
+}
+
+static int __init nf_nat_helper_pptp_init(void)
+{
+ nf_nat_need_gre();
+
+ BUG_ON(rcu_dereference(nf_nat_pptp_hook_outbound));
+ rcu_assign_pointer(nf_nat_pptp_hook_outbound, pptp_outbound_pkt);
+
+ BUG_ON(rcu_dereference(nf_nat_pptp_hook_inbound));
+ rcu_assign_pointer(nf_nat_pptp_hook_inbound, pptp_inbound_pkt);
+
+ BUG_ON(rcu_dereference(nf_nat_pptp_hook_exp_gre));
+ rcu_assign_pointer(nf_nat_pptp_hook_exp_gre, pptp_exp_gre);
+
+ BUG_ON(rcu_dereference(nf_nat_pptp_hook_expectfn));
+ rcu_assign_pointer(nf_nat_pptp_hook_expectfn, pptp_nat_expected);
+ return 0;
+}
+
+static void __exit nf_nat_helper_pptp_fini(void)
+{
+ rcu_assign_pointer(nf_nat_pptp_hook_expectfn, NULL);
+ rcu_assign_pointer(nf_nat_pptp_hook_exp_gre, NULL);
+ rcu_assign_pointer(nf_nat_pptp_hook_inbound, NULL);
+ rcu_assign_pointer(nf_nat_pptp_hook_outbound, NULL);
+ synchronize_rcu();
+}
+
+module_init(nf_nat_helper_pptp_init);
+module_exit(nf_nat_helper_pptp_fini);
diff --git a/net/ipv4/netfilter/nf_nat_proto_gre.c b/net/ipv4/netfilter/nf_nat_proto_gre.c
new file mode 100644
index 000000000000..d3de579e09d2
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_proto_gre.c
@@ -0,0 +1,179 @@
+/*
+ * nf_nat_proto_gre.c
+ *
+ * NAT protocol helper module for GRE.
+ *
+ * GRE is a generic encapsulation protocol, which is generally not very
+ * suited for NAT, as it has no protocol-specific part as port numbers.
+ *
+ * It has an optional key field, which may help us distinguishing two
+ * connections between the same two hosts.
+ *
+ * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784
+ *
+ * PPTP is built on top of a modified version of GRE, and has a mandatory
+ * field called "CallID", which serves us for the same purpose as the key
+ * field in plain GRE.
+ *
+ * Documentation about PPTP can be found in RFC 2637
+ *
+ * (C) 2000-2005 by Harald Welte <laforge@gnumonks.org>
+ *
+ * Development of this code funded by Astaro AG (http://www.astaro.com/)
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+
+#include <net/netfilter/nf_nat.h>
+#include <net/netfilter/nf_nat_rule.h>
+#include <net/netfilter/nf_nat_protocol.h>
+#include <linux/netfilter/nf_conntrack_proto_gre.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
+MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE");
+
+#if 0
+#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, \
+ __FUNCTION__, ## args)
+#else
+#define DEBUGP(x, args...)
+#endif
+
+/* is key in given range between min and max */
+static int
+gre_in_range(const struct nf_conntrack_tuple *tuple,
+ enum nf_nat_manip_type maniptype,
+ const union nf_conntrack_man_proto *min,
+ const union nf_conntrack_man_proto *max)
+{
+ __be16 key;
+
+ if (maniptype == IP_NAT_MANIP_SRC)
+ key = tuple->src.u.gre.key;
+ else
+ key = tuple->dst.u.gre.key;
+
+ return ntohs(key) >= ntohs(min->gre.key) &&
+ ntohs(key) <= ntohs(max->gre.key);
+}
+
+/* generate unique tuple ... */
+static int
+gre_unique_tuple(struct nf_conntrack_tuple *tuple,
+ const struct nf_nat_range *range,
+ enum nf_nat_manip_type maniptype,
+ const struct nf_conn *conntrack)
+{
+ static u_int16_t key;
+ __be16 *keyptr;
+ unsigned int min, i, range_size;
+
+ if (maniptype == IP_NAT_MANIP_SRC)
+ keyptr = &tuple->src.u.gre.key;
+ else
+ keyptr = &tuple->dst.u.gre.key;
+
+ if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
+ DEBUGP("%p: NATing GRE PPTP\n", conntrack);
+ min = 1;
+ range_size = 0xffff;
+ } else {
+ min = ntohs(range->min.gre.key);
+ range_size = ntohs(range->max.gre.key) - min + 1;
+ }
+
+ DEBUGP("min = %u, range_size = %u\n", min, range_size);
+
+ for (i = 0; i < range_size; i++, key++) {
+ *keyptr = htons(min + key % range_size);
+ if (!nf_nat_used_tuple(tuple, conntrack))
+ return 1;
+ }
+
+ DEBUGP("%p: no NAT mapping\n", conntrack);
+ return 0;
+}
+
+/* manipulate a GRE packet according to maniptype */
+static int
+gre_manip_pkt(struct sk_buff **pskb, unsigned int iphdroff,
+ const struct nf_conntrack_tuple *tuple,
+ enum nf_nat_manip_type maniptype)
+{
+ struct gre_hdr *greh;
+ struct gre_hdr_pptp *pgreh;
+ struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
+ unsigned int hdroff = iphdroff + iph->ihl * 4;
+
+ /* pgreh includes two optional 32bit fields which are not required
+ * to be there. That's where the magic '8' comes from */
+ if (!skb_make_writable(pskb, hdroff + sizeof(*pgreh) - 8))
+ return 0;
+
+ greh = (void *)(*pskb)->data + hdroff;
+ pgreh = (struct gre_hdr_pptp *)greh;
+
+ /* we only have destination manip of a packet, since 'source key'
+ * is not present in the packet itself */
+ if (maniptype != IP_NAT_MANIP_DST)
+ return 1;
+ switch (greh->version) {
+ case 0:
+ if (!greh->key) {
+ DEBUGP("can't nat GRE w/o key\n");
+ break;
+ }
+ if (greh->csum) {
+ /* FIXME: Never tested this code... */
+ nf_proto_csum_replace4(gre_csum(greh), *pskb,
+ *(gre_key(greh)),
+ tuple->dst.u.gre.key, 0);
+ }
+ *(gre_key(greh)) = tuple->dst.u.gre.key;
+ break;
+ case GRE_VERSION_PPTP:
+ DEBUGP("call_id -> 0x%04x\n", ntohs(tuple->dst.u.gre.key));
+ pgreh->call_id = tuple->dst.u.gre.key;
+ break;
+ default:
+ DEBUGP("can't nat unknown GRE version\n");
+ return 0;
+ }
+ return 1;
+}
+
+static struct nf_nat_protocol gre __read_mostly = {
+ .name = "GRE",
+ .protonum = IPPROTO_GRE,
+ .manip_pkt = gre_manip_pkt,
+ .in_range = gre_in_range,
+ .unique_tuple = gre_unique_tuple,
+#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
+ defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
+ .range_to_nfattr = nf_nat_port_range_to_nfattr,
+ .nfattr_to_range = nf_nat_port_nfattr_to_range,
+#endif
+};
+
+int __init nf_nat_proto_gre_init(void)
+{
+ return nf_nat_protocol_register(&gre);
+}
+
+void __exit nf_nat_proto_gre_fini(void)
+{
+ nf_nat_protocol_unregister(&gre);
+}
+
+module_init(nf_nat_proto_gre_init);
+module_exit(nf_nat_proto_gre_fini);
+
+void nf_nat_need_gre(void)
+{
+ return;
+}
+EXPORT_SYMBOL_GPL(nf_nat_need_gre);
diff --git a/net/ipv4/netfilter/nf_nat_proto_icmp.c b/net/ipv4/netfilter/nf_nat_proto_icmp.c
new file mode 100644
index 000000000000..dcfd772972d7
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_proto_icmp.c
@@ -0,0 +1,86 @@
+/* (C) 1999-2001 Paul `Rusty' Russell
+ * (C) 2002-2006 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/types.h>
+#include <linux/init.h>
+#include <linux/ip.h>
+#include <linux/icmp.h>
+
+#include <linux/netfilter.h>
+#include <net/netfilter/nf_nat.h>
+#include <net/netfilter/nf_nat_core.h>
+#include <net/netfilter/nf_nat_rule.h>
+#include <net/netfilter/nf_nat_protocol.h>
+
+static int
+icmp_in_range(const struct nf_conntrack_tuple *tuple,
+ enum nf_nat_manip_type maniptype,
+ const union nf_conntrack_man_proto *min,
+ const union nf_conntrack_man_proto *max)
+{
+ return ntohs(tuple->src.u.icmp.id) >= ntohs(min->icmp.id) &&
+ ntohs(tuple->src.u.icmp.id) <= ntohs(max->icmp.id);
+}
+
+static int
+icmp_unique_tuple(struct nf_conntrack_tuple *tuple,
+ const struct nf_nat_range *range,
+ enum nf_nat_manip_type maniptype,
+ const struct nf_conn *ct)
+{
+ static u_int16_t id;
+ unsigned int range_size;
+ unsigned int i;
+
+ range_size = ntohs(range->max.icmp.id) - ntohs(range->min.icmp.id) + 1;
+ /* If no range specified... */
+ if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED))
+ range_size = 0xFFFF;
+
+ for (i = 0; i < range_size; i++, id++) {
+ tuple->src.u.icmp.id = htons(ntohs(range->min.icmp.id) +
+ (id % range_size));
+ if (!nf_nat_used_tuple(tuple, ct))
+ return 1;
+ }
+ return 0;
+}
+
+static int
+icmp_manip_pkt(struct sk_buff **pskb,
+ unsigned int iphdroff,
+ const struct nf_conntrack_tuple *tuple,
+ enum nf_nat_manip_type maniptype)
+{
+ struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
+ struct icmphdr *hdr;
+ unsigned int hdroff = iphdroff + iph->ihl*4;
+
+ if (!skb_make_writable(pskb, hdroff + sizeof(*hdr)))
+ return 0;
+
+ hdr = (struct icmphdr *)((*pskb)->data + hdroff);
+ nf_proto_csum_replace2(&hdr->checksum, *pskb,
+ hdr->un.echo.id, tuple->src.u.icmp.id, 0);
+ hdr->un.echo.id = tuple->src.u.icmp.id;
+ return 1;
+}
+
+struct nf_nat_protocol nf_nat_protocol_icmp = {
+ .name = "ICMP",
+ .protonum = IPPROTO_ICMP,
+ .me = THIS_MODULE,
+ .manip_pkt = icmp_manip_pkt,
+ .in_range = icmp_in_range,
+ .unique_tuple = icmp_unique_tuple,
+#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
+ defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
+ .range_to_nfattr = nf_nat_port_range_to_nfattr,
+ .nfattr_to_range = nf_nat_port_nfattr_to_range,
+#endif
+};
diff --git a/net/ipv4/netfilter/nf_nat_proto_tcp.c b/net/ipv4/netfilter/nf_nat_proto_tcp.c
new file mode 100644
index 000000000000..7e26a7e9bee1
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_proto_tcp.c
@@ -0,0 +1,148 @@
+/* (C) 1999-2001 Paul `Rusty' Russell
+ * (C) 2002-2006 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/types.h>
+#include <linux/init.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+
+#include <linux/netfilter.h>
+#include <linux/netfilter/nfnetlink_conntrack.h>
+#include <net/netfilter/nf_nat.h>
+#include <net/netfilter/nf_nat_rule.h>
+#include <net/netfilter/nf_nat_protocol.h>
+#include <net/netfilter/nf_nat_core.h>
+
+static int
+tcp_in_range(const struct nf_conntrack_tuple *tuple,
+ enum nf_nat_manip_type maniptype,
+ const union nf_conntrack_man_proto *min,
+ const union nf_conntrack_man_proto *max)
+{
+ __be16 port;
+
+ if (maniptype == IP_NAT_MANIP_SRC)
+ port = tuple->src.u.tcp.port;
+ else
+ port = tuple->dst.u.tcp.port;
+
+ return ntohs(port) >= ntohs(min->tcp.port) &&
+ ntohs(port) <= ntohs(max->tcp.port);
+}
+
+static int
+tcp_unique_tuple(struct nf_conntrack_tuple *tuple,
+ const struct nf_nat_range *range,
+ enum nf_nat_manip_type maniptype,
+ const struct nf_conn *ct)
+{
+ static u_int16_t port;
+ __be16 *portptr;
+ unsigned int range_size, min, i;
+
+ if (maniptype == IP_NAT_MANIP_SRC)
+ portptr = &tuple->src.u.tcp.port;
+ else
+ portptr = &tuple->dst.u.tcp.port;
+
+ /* If no range specified... */
+ if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
+ /* If it's dst rewrite, can't change port */
+ if (maniptype == IP_NAT_MANIP_DST)
+ return 0;
+
+ /* Map privileged onto privileged. */
+ if (ntohs(*portptr) < 1024) {
+ /* Loose convention: >> 512 is credential passing */
+ if (ntohs(*portptr)<512) {
+ min = 1;
+ range_size = 511 - min + 1;
+ } else {
+ min = 600;
+ range_size = 1023 - min + 1;
+ }
+ } else {
+ min = 1024;
+ range_size = 65535 - 1024 + 1;
+ }
+ } else {
+ min = ntohs(range->min.tcp.port);
+ range_size = ntohs(range->max.tcp.port) - min + 1;
+ }
+
+ for (i = 0; i < range_size; i++, port++) {
+ *portptr = htons(min + port % range_size);
+ if (!nf_nat_used_tuple(tuple, ct))
+ return 1;
+ }
+ return 0;
+}
+
+static int
+tcp_manip_pkt(struct sk_buff **pskb,
+ unsigned int iphdroff,
+ const struct nf_conntrack_tuple *tuple,
+ enum nf_nat_manip_type maniptype)
+{
+ struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
+ struct tcphdr *hdr;
+ unsigned int hdroff = iphdroff + iph->ihl*4;
+ __be32 oldip, newip;
+ __be16 *portptr, newport, oldport;
+ int hdrsize = 8; /* TCP connection tracking guarantees this much */
+
+ /* this could be a inner header returned in icmp packet; in such
+ cases we cannot update the checksum field since it is outside of
+ the 8 bytes of transport layer headers we are guaranteed */
+ if ((*pskb)->len >= hdroff + sizeof(struct tcphdr))
+ hdrsize = sizeof(struct tcphdr);
+
+ if (!skb_make_writable(pskb, hdroff + hdrsize))
+ return 0;
+
+ iph = (struct iphdr *)((*pskb)->data + iphdroff);
+ hdr = (struct tcphdr *)((*pskb)->data + hdroff);
+
+ if (maniptype == IP_NAT_MANIP_SRC) {
+ /* Get rid of src ip and src pt */
+ oldip = iph->saddr;
+ newip = tuple->src.u3.ip;
+ newport = tuple->src.u.tcp.port;
+ portptr = &hdr->source;
+ } else {
+ /* Get rid of dst ip and dst pt */
+ oldip = iph->daddr;
+ newip = tuple->dst.u3.ip;
+ newport = tuple->dst.u.tcp.port;
+ portptr = &hdr->dest;
+ }
+
+ oldport = *portptr;
+ *portptr = newport;
+
+ if (hdrsize < sizeof(*hdr))
+ return 1;
+
+ nf_proto_csum_replace4(&hdr->check, *pskb, oldip, newip, 1);
+ nf_proto_csum_replace2(&hdr->check, *pskb, oldport, newport, 0);
+ return 1;
+}
+
+struct nf_nat_protocol nf_nat_protocol_tcp = {
+ .name = "TCP",
+ .protonum = IPPROTO_TCP,
+ .me = THIS_MODULE,
+ .manip_pkt = tcp_manip_pkt,
+ .in_range = tcp_in_range,
+ .unique_tuple = tcp_unique_tuple,
+#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
+ defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
+ .range_to_nfattr = nf_nat_port_range_to_nfattr,
+ .nfattr_to_range = nf_nat_port_nfattr_to_range,
+#endif
+};
diff --git a/net/ipv4/netfilter/nf_nat_proto_udp.c b/net/ipv4/netfilter/nf_nat_proto_udp.c
new file mode 100644
index 000000000000..ab0ce4c8699f
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_proto_udp.c
@@ -0,0 +1,138 @@
+/* (C) 1999-2001 Paul `Rusty' Russell
+ * (C) 2002-2006 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/types.h>
+#include <linux/init.h>
+#include <linux/ip.h>
+#include <linux/udp.h>
+
+#include <linux/netfilter.h>
+#include <net/netfilter/nf_nat.h>
+#include <net/netfilter/nf_nat_core.h>
+#include <net/netfilter/nf_nat_rule.h>
+#include <net/netfilter/nf_nat_protocol.h>
+
+static int
+udp_in_range(const struct nf_conntrack_tuple *tuple,
+ enum nf_nat_manip_type maniptype,
+ const union nf_conntrack_man_proto *min,
+ const union nf_conntrack_man_proto *max)
+{
+ __be16 port;
+
+ if (maniptype == IP_NAT_MANIP_SRC)
+ port = tuple->src.u.udp.port;
+ else
+ port = tuple->dst.u.udp.port;
+
+ return ntohs(port) >= ntohs(min->udp.port) &&
+ ntohs(port) <= ntohs(max->udp.port);
+}
+
+static int
+udp_unique_tuple(struct nf_conntrack_tuple *tuple,
+ const struct nf_nat_range *range,
+ enum nf_nat_manip_type maniptype,
+ const struct nf_conn *ct)
+{
+ static u_int16_t port;
+ __be16 *portptr;
+ unsigned int range_size, min, i;
+
+ if (maniptype == IP_NAT_MANIP_SRC)
+ portptr = &tuple->src.u.udp.port;
+ else
+ portptr = &tuple->dst.u.udp.port;
+
+ /* If no range specified... */
+ if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
+ /* If it's dst rewrite, can't change port */
+ if (maniptype == IP_NAT_MANIP_DST)
+ return 0;
+
+ if (ntohs(*portptr) < 1024) {
+ /* Loose convention: >> 512 is credential passing */
+ if (ntohs(*portptr)<512) {
+ min = 1;
+ range_size = 511 - min + 1;
+ } else {
+ min = 600;
+ range_size = 1023 - min + 1;
+ }
+ } else {
+ min = 1024;
+ range_size = 65535 - 1024 + 1;
+ }
+ } else {
+ min = ntohs(range->min.udp.port);
+ range_size = ntohs(range->max.udp.port) - min + 1;
+ }
+
+ for (i = 0; i < range_size; i++, port++) {
+ *portptr = htons(min + port % range_size);
+ if (!nf_nat_used_tuple(tuple, ct))
+ return 1;
+ }
+ return 0;
+}
+
+static int
+udp_manip_pkt(struct sk_buff **pskb,
+ unsigned int iphdroff,
+ const struct nf_conntrack_tuple *tuple,
+ enum nf_nat_manip_type maniptype)
+{
+ struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
+ struct udphdr *hdr;
+ unsigned int hdroff = iphdroff + iph->ihl*4;
+ __be32 oldip, newip;
+ __be16 *portptr, newport;
+
+ if (!skb_make_writable(pskb, hdroff + sizeof(*hdr)))
+ return 0;
+
+ iph = (struct iphdr *)((*pskb)->data + iphdroff);
+ hdr = (struct udphdr *)((*pskb)->data + hdroff);
+
+ if (maniptype == IP_NAT_MANIP_SRC) {
+ /* Get rid of src ip and src pt */
+ oldip = iph->saddr;
+ newip = tuple->src.u3.ip;
+ newport = tuple->src.u.udp.port;
+ portptr = &hdr->source;
+ } else {
+ /* Get rid of dst ip and dst pt */
+ oldip = iph->daddr;
+ newip = tuple->dst.u3.ip;
+ newport = tuple->dst.u.udp.port;
+ portptr = &hdr->dest;
+ }
+ if (hdr->check || (*pskb)->ip_summed == CHECKSUM_PARTIAL) {
+ nf_proto_csum_replace4(&hdr->check, *pskb, oldip, newip, 1);
+ nf_proto_csum_replace2(&hdr->check, *pskb, *portptr, newport,
+ 0);
+ if (!hdr->check)
+ hdr->check = CSUM_MANGLED_0;
+ }
+ *portptr = newport;
+ return 1;
+}
+
+struct nf_nat_protocol nf_nat_protocol_udp = {
+ .name = "UDP",
+ .protonum = IPPROTO_UDP,
+ .me = THIS_MODULE,
+ .manip_pkt = udp_manip_pkt,
+ .in_range = udp_in_range,
+ .unique_tuple = udp_unique_tuple,
+#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
+ defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
+ .range_to_nfattr = nf_nat_port_range_to_nfattr,
+ .nfattr_to_range = nf_nat_port_nfattr_to_range,
+#endif
+};
diff --git a/net/ipv4/netfilter/nf_nat_proto_unknown.c b/net/ipv4/netfilter/nf_nat_proto_unknown.c
new file mode 100644
index 000000000000..f50d0203f9c0
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_proto_unknown.c
@@ -0,0 +1,54 @@
+/* The "unknown" protocol. This is what is used for protocols we
+ * don't understand. It's returned by ip_ct_find_proto().
+ */
+
+/* (C) 1999-2001 Paul `Rusty' Russell
+ * (C) 2002-2006 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/types.h>
+#include <linux/init.h>
+
+#include <linux/netfilter.h>
+#include <net/netfilter/nf_nat.h>
+#include <net/netfilter/nf_nat_rule.h>
+#include <net/netfilter/nf_nat_protocol.h>
+
+static int unknown_in_range(const struct nf_conntrack_tuple *tuple,
+ enum nf_nat_manip_type manip_type,
+ const union nf_conntrack_man_proto *min,
+ const union nf_conntrack_man_proto *max)
+{
+ return 1;
+}
+
+static int unknown_unique_tuple(struct nf_conntrack_tuple *tuple,
+ const struct nf_nat_range *range,
+ enum nf_nat_manip_type maniptype,
+ const struct nf_conn *ct)
+{
+ /* Sorry: we can't help you; if it's not unique, we can't frob
+ anything. */
+ return 0;
+}
+
+static int
+unknown_manip_pkt(struct sk_buff **pskb,
+ unsigned int iphdroff,
+ const struct nf_conntrack_tuple *tuple,
+ enum nf_nat_manip_type maniptype)
+{
+ return 1;
+}
+
+struct nf_nat_protocol nf_nat_unknown_protocol = {
+ .name = "unknown",
+ /* .me isn't set: getting a ref to this cannot fail. */
+ .manip_pkt = unknown_manip_pkt,
+ .in_range = unknown_in_range,
+ .unique_tuple = unknown_unique_tuple,
+};
diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c
new file mode 100644
index 000000000000..b868ee0195d4
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_rule.c
@@ -0,0 +1,343 @@
+/* (C) 1999-2001 Paul `Rusty' Russell
+ * (C) 2002-2006 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.
+ */
+
+/* Everything about the rules for NAT. */
+#include <linux/types.h>
+#include <linux/ip.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/skbuff.h>
+#include <linux/proc_fs.h>
+#include <net/checksum.h>
+#include <net/route.h>
+#include <linux/bitops.h>
+
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <net/netfilter/nf_nat.h>
+#include <net/netfilter/nf_nat_core.h>
+#include <net/netfilter/nf_nat_rule.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+#define NAT_VALID_HOOKS ((1<<NF_IP_PRE_ROUTING) | (1<<NF_IP_POST_ROUTING) | (1<<NF_IP_LOCAL_OUT))
+
+static struct
+{
+ struct ipt_replace repl;
+ struct ipt_standard entries[3];
+ struct ipt_error term;
+} nat_initial_table __initdata = {
+ .repl = {
+ .name = "nat",
+ .valid_hooks = NAT_VALID_HOOKS,
+ .num_entries = 4,
+ .size = sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error),
+ .hook_entry = {
+ [NF_IP_PRE_ROUTING] = 0,
+ [NF_IP_POST_ROUTING] = sizeof(struct ipt_standard),
+ [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 },
+ .underflow = {
+ [NF_IP_PRE_ROUTING] = 0,
+ [NF_IP_POST_ROUTING] = sizeof(struct ipt_standard),
+ [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 },
+ },
+ .entries = {
+ /* PRE_ROUTING */
+ {
+ .entry = {
+ .target_offset = sizeof(struct ipt_entry),
+ .next_offset = sizeof(struct ipt_standard),
+ },
+ .target = {
+ .target = {
+ .u = {
+ .target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)),
+ },
+ },
+ .verdict = -NF_ACCEPT - 1,
+ },
+ },
+ /* POST_ROUTING */
+ {
+ .entry = {
+ .target_offset = sizeof(struct ipt_entry),
+ .next_offset = sizeof(struct ipt_standard),
+ },
+ .target = {
+ .target = {
+ .u = {
+ .target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)),
+ },
+ },
+ .verdict = -NF_ACCEPT - 1,
+ },
+ },
+ /* LOCAL_OUT */
+ {
+ .entry = {
+ .target_offset = sizeof(struct ipt_entry),
+ .next_offset = sizeof(struct ipt_standard),
+ },
+ .target = {
+ .target = {
+ .u = {
+ .target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)),
+ },
+ },
+ .verdict = -NF_ACCEPT - 1,
+ },
+ },
+ },
+ /* ERROR */
+ .term = {
+ .entry = {
+ .target_offset = sizeof(struct ipt_entry),
+ .next_offset = sizeof(struct ipt_error),
+ },
+ .target = {
+ .target = {
+ .u = {
+ .user = {
+ .target_size = IPT_ALIGN(sizeof(struct ipt_error_target)),
+ .name = IPT_ERROR_TARGET,
+ },
+ },
+ },
+ .errorname = "ERROR",
+ },
+ }
+};
+
+static struct ipt_table nat_table = {
+ .name = "nat",
+ .valid_hooks = NAT_VALID_HOOKS,
+ .lock = RW_LOCK_UNLOCKED,
+ .me = THIS_MODULE,
+ .af = AF_INET,
+};
+
+/* Source NAT */
+static unsigned int ipt_snat_target(struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ unsigned int hooknum,
+ const struct xt_target *target,
+ const void *targinfo)
+{
+ struct nf_conn *ct;
+ enum ip_conntrack_info ctinfo;
+ const struct nf_nat_multi_range_compat *mr = targinfo;
+
+ NF_CT_ASSERT(hooknum == NF_IP_POST_ROUTING);
+
+ ct = nf_ct_get(*pskb, &ctinfo);
+
+ /* Connection must be valid and new. */
+ NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED ||
+ ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY));
+ NF_CT_ASSERT(out);
+
+ return nf_nat_setup_info(ct, &mr->range[0], hooknum);
+}
+
+/* Before 2.6.11 we did implicit source NAT if required. Warn about change. */
+static void warn_if_extra_mangle(__be32 dstip, __be32 srcip)
+{
+ static int warned = 0;
+ struct flowi fl = { .nl_u = { .ip4_u = { .daddr = dstip } } };
+ struct rtable *rt;
+
+ if (ip_route_output_key(&rt, &fl) != 0)
+ return;
+
+ if (rt->rt_src != srcip && !warned) {
+ printk("NAT: no longer support implicit source local NAT\n");
+ printk("NAT: packet src %u.%u.%u.%u -> dst %u.%u.%u.%u\n",
+ NIPQUAD(srcip), NIPQUAD(dstip));
+ warned = 1;
+ }
+ ip_rt_put(rt);
+}
+
+static unsigned int ipt_dnat_target(struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ unsigned int hooknum,
+ const struct xt_target *target,
+ const void *targinfo)
+{
+ struct nf_conn *ct;
+ enum ip_conntrack_info ctinfo;
+ const struct nf_nat_multi_range_compat *mr = targinfo;
+
+ NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING ||
+ hooknum == NF_IP_LOCAL_OUT);
+
+ ct = nf_ct_get(*pskb, &ctinfo);
+
+ /* Connection must be valid and new. */
+ NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED));
+
+ if (hooknum == NF_IP_LOCAL_OUT &&
+ mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)
+ warn_if_extra_mangle((*pskb)->nh.iph->daddr,
+ mr->range[0].min_ip);
+
+ return nf_nat_setup_info(ct, &mr->range[0], hooknum);
+}
+
+static int ipt_snat_checkentry(const char *tablename,
+ const void *entry,
+ const struct xt_target *target,
+ void *targinfo,
+ unsigned int hook_mask)
+{
+ struct nf_nat_multi_range_compat *mr = targinfo;
+
+ /* Must be a valid range */
+ if (mr->rangesize != 1) {
+ printk("SNAT: multiple ranges no longer supported\n");
+ return 0;
+ }
+ return 1;
+}
+
+static int ipt_dnat_checkentry(const char *tablename,
+ const void *entry,
+ const struct xt_target *target,
+ void *targinfo,
+ unsigned int hook_mask)
+{
+ struct nf_nat_multi_range_compat *mr = targinfo;
+
+ /* Must be a valid range */
+ if (mr->rangesize != 1) {
+ printk("DNAT: multiple ranges no longer supported\n");
+ return 0;
+ }
+ return 1;
+}
+
+inline unsigned int
+alloc_null_binding(struct nf_conn *ct,
+ struct nf_nat_info *info,
+ unsigned int hooknum)
+{
+ /* Force range to this IP; let proto decide mapping for
+ per-proto parts (hence not IP_NAT_RANGE_PROTO_SPECIFIED).
+ Use reply in case it's already been mangled (eg local packet).
+ */
+ __be32 ip
+ = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
+ ? ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip
+ : ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip);
+ struct nf_nat_range range
+ = { IP_NAT_RANGE_MAP_IPS, ip, ip, { 0 }, { 0 } };
+
+ DEBUGP("Allocating NULL binding for %p (%u.%u.%u.%u)\n",
+ ct, NIPQUAD(ip));
+ return nf_nat_setup_info(ct, &range, hooknum);
+}
+
+unsigned int
+alloc_null_binding_confirmed(struct nf_conn *ct,
+ struct nf_nat_info *info,
+ unsigned int hooknum)
+{
+ __be32 ip
+ = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
+ ? ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip
+ : ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip);
+ u_int16_t all
+ = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
+ ? ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.all
+ : ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.all);
+ struct nf_nat_range range
+ = { IP_NAT_RANGE_MAP_IPS, ip, ip, { all }, { all } };
+
+ DEBUGP("Allocating NULL binding for confirmed %p (%u.%u.%u.%u)\n",
+ ct, NIPQUAD(ip));
+ return nf_nat_setup_info(ct, &range, hooknum);
+}
+
+int nf_nat_rule_find(struct sk_buff **pskb,
+ unsigned int hooknum,
+ const struct net_device *in,
+ const struct net_device *out,
+ struct nf_conn *ct,
+ struct nf_nat_info *info)
+{
+ int ret;
+
+ ret = ipt_do_table(pskb, hooknum, in, out, &nat_table);
+
+ if (ret == NF_ACCEPT) {
+ if (!nf_nat_initialized(ct, HOOK2MANIP(hooknum)))
+ /* NUL mapping */
+ ret = alloc_null_binding(ct, info, hooknum);
+ }
+ return ret;
+}
+
+static struct ipt_target ipt_snat_reg = {
+ .name = "SNAT",
+ .target = ipt_snat_target,
+ .targetsize = sizeof(struct nf_nat_multi_range_compat),
+ .table = "nat",
+ .hooks = 1 << NF_IP_POST_ROUTING,
+ .checkentry = ipt_snat_checkentry,
+ .family = AF_INET,
+};
+
+static struct xt_target ipt_dnat_reg = {
+ .name = "DNAT",
+ .target = ipt_dnat_target,
+ .targetsize = sizeof(struct nf_nat_multi_range_compat),
+ .table = "nat",
+ .hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT),
+ .checkentry = ipt_dnat_checkentry,
+ .family = AF_INET,
+};
+
+int __init nf_nat_rule_init(void)
+{
+ int ret;
+
+ ret = ipt_register_table(&nat_table, &nat_initial_table.repl);
+ if (ret != 0)
+ return ret;
+ ret = xt_register_target(&ipt_snat_reg);
+ if (ret != 0)
+ goto unregister_table;
+
+ ret = xt_register_target(&ipt_dnat_reg);
+ if (ret != 0)
+ goto unregister_snat;
+
+ return ret;
+
+ unregister_snat:
+ xt_unregister_target(&ipt_snat_reg);
+ unregister_table:
+ ipt_unregister_table(&nat_table);
+
+ return ret;
+}
+
+void nf_nat_rule_cleanup(void)
+{
+ xt_unregister_target(&ipt_dnat_reg);
+ xt_unregister_target(&ipt_snat_reg);
+ ipt_unregister_table(&nat_table);
+}
diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c
new file mode 100644
index 000000000000..3d524b957310
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_sip.c
@@ -0,0 +1,283 @@
+/* SIP extension for UDP NAT alteration.
+ *
+ * (C) 2005 by Christian Hentschel <chentschel@arnet.com.ar>
+ * based on RR's ip_nat_ftp.c and other modules.
+ *
+ * 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/udp.h>
+
+#include <net/netfilter/nf_nat.h>
+#include <net/netfilter/nf_nat_helper.h>
+#include <net/netfilter/nf_nat_rule.h>
+#include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_conntrack_expect.h>
+#include <linux/netfilter/nf_conntrack_sip.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com.ar>");
+MODULE_DESCRIPTION("SIP NAT helper");
+MODULE_ALIAS("ip_nat_sip");
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+struct addr_map {
+ struct {
+ char src[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
+ char dst[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
+ unsigned int srclen, srciplen;
+ unsigned int dstlen, dstiplen;
+ } addr[IP_CT_DIR_MAX];
+};
+
+static void addr_map_init(struct nf_conn *ct, struct addr_map *map)
+{
+ struct nf_conntrack_tuple *t;
+ enum ip_conntrack_dir dir;
+ unsigned int n;
+
+ for (dir = 0; dir < IP_CT_DIR_MAX; dir++) {
+ t = &ct->tuplehash[dir].tuple;
+
+ n = sprintf(map->addr[dir].src, "%u.%u.%u.%u",
+ NIPQUAD(t->src.u3.ip));
+ map->addr[dir].srciplen = n;
+ n += sprintf(map->addr[dir].src + n, ":%u",
+ ntohs(t->src.u.udp.port));
+ map->addr[dir].srclen = n;
+
+ n = sprintf(map->addr[dir].dst, "%u.%u.%u.%u",
+ NIPQUAD(t->dst.u3.ip));
+ map->addr[dir].dstiplen = n;
+ n += sprintf(map->addr[dir].dst + n, ":%u",
+ ntohs(t->dst.u.udp.port));
+ map->addr[dir].dstlen = n;
+ }
+}
+
+static int map_sip_addr(struct sk_buff **pskb, enum ip_conntrack_info ctinfo,
+ struct nf_conn *ct, const char **dptr, size_t dlen,
+ enum sip_header_pos pos, struct addr_map *map)
+{
+ enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+ unsigned int matchlen, matchoff, addrlen;
+ char *addr;
+
+ if (ct_sip_get_info(ct, *dptr, dlen, &matchoff, &matchlen, pos) <= 0)
+ return 1;
+
+ if ((matchlen == map->addr[dir].srciplen ||
+ matchlen == map->addr[dir].srclen) &&
+ memcmp(*dptr + matchoff, map->addr[dir].src, matchlen) == 0) {
+ addr = map->addr[!dir].dst;
+ addrlen = map->addr[!dir].dstlen;
+ } else if ((matchlen == map->addr[dir].dstiplen ||
+ matchlen == map->addr[dir].dstlen) &&
+ memcmp(*dptr + matchoff, map->addr[dir].dst, matchlen) == 0) {
+ addr = map->addr[!dir].src;
+ addrlen = map->addr[!dir].srclen;
+ } else
+ return 1;
+
+ if (!nf_nat_mangle_udp_packet(pskb, ct, ctinfo,
+ matchoff, matchlen, addr, addrlen))
+ return 0;
+ *dptr = (*pskb)->data + (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
+ return 1;
+
+}
+
+static unsigned int ip_nat_sip(struct sk_buff **pskb,
+ enum ip_conntrack_info ctinfo,
+ struct nf_conn *ct,
+ const char **dptr)
+{
+ enum sip_header_pos pos;
+ struct addr_map map;
+ int dataoff, datalen;
+
+ dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
+ datalen = (*pskb)->len - dataoff;
+ if (datalen < sizeof("SIP/2.0") - 1)
+ return NF_DROP;
+
+ addr_map_init(ct, &map);
+
+ /* Basic rules: requests and responses. */
+ if (strncmp(*dptr, "SIP/2.0", sizeof("SIP/2.0") - 1) != 0) {
+ /* 10.2: Constructing the REGISTER Request:
+ *
+ * The "userinfo" and "@" components of the SIP URI MUST NOT
+ * be present.
+ */
+ if (datalen >= sizeof("REGISTER") - 1 &&
+ strncmp(*dptr, "REGISTER", sizeof("REGISTER") - 1) == 0)
+ pos = POS_REG_REQ_URI;
+ else
+ pos = POS_REQ_URI;
+
+ if (!map_sip_addr(pskb, ctinfo, ct, dptr, datalen, pos, &map))
+ return NF_DROP;
+ }
+
+ if (!map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_FROM, &map) ||
+ !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_TO, &map) ||
+ !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_VIA, &map) ||
+ !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_CONTACT, &map))
+ return NF_DROP;
+ return NF_ACCEPT;
+}
+
+static unsigned int mangle_sip_packet(struct sk_buff **pskb,
+ enum ip_conntrack_info ctinfo,
+ struct nf_conn *ct,
+ const char **dptr, size_t dlen,
+ char *buffer, int bufflen,
+ enum sip_header_pos pos)
+{
+ unsigned int matchlen, matchoff;
+
+ if (ct_sip_get_info(ct, *dptr, dlen, &matchoff, &matchlen, pos) <= 0)
+ return 0;
+
+ if (!nf_nat_mangle_udp_packet(pskb, ct, ctinfo,
+ matchoff, matchlen, buffer, bufflen))
+ return 0;
+
+ /* We need to reload this. Thanks Patrick. */
+ *dptr = (*pskb)->data + (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
+ return 1;
+}
+
+static int mangle_content_len(struct sk_buff **pskb,
+ enum ip_conntrack_info ctinfo,
+ struct nf_conn *ct,
+ const char *dptr)
+{
+ unsigned int dataoff, matchoff, matchlen;
+ char buffer[sizeof("65536")];
+ int bufflen;
+
+ dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
+
+ /* Get actual SDP lenght */
+ if (ct_sip_get_info(ct, dptr, (*pskb)->len - dataoff, &matchoff,
+ &matchlen, POS_SDP_HEADER) > 0) {
+
+ /* since ct_sip_get_info() give us a pointer passing 'v='
+ we need to add 2 bytes in this count. */
+ int c_len = (*pskb)->len - dataoff - matchoff + 2;
+
+ /* Now, update SDP length */
+ if (ct_sip_get_info(ct, dptr, (*pskb)->len - dataoff, &matchoff,
+ &matchlen, POS_CONTENT) > 0) {
+
+ bufflen = sprintf(buffer, "%u", c_len);
+ return nf_nat_mangle_udp_packet(pskb, ct, ctinfo,
+ matchoff, matchlen,
+ buffer, bufflen);
+ }
+ }
+ return 0;
+}
+
+static unsigned int mangle_sdp(struct sk_buff **pskb,
+ enum ip_conntrack_info ctinfo,
+ struct nf_conn *ct,
+ __be32 newip, u_int16_t port,
+ const char *dptr)
+{
+ char buffer[sizeof("nnn.nnn.nnn.nnn")];
+ unsigned int dataoff, bufflen;
+
+ dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
+
+ /* Mangle owner and contact info. */
+ bufflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(newip));
+ if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
+ buffer, bufflen, POS_OWNER_IP4))
+ return 0;
+
+ if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
+ buffer, bufflen, POS_CONNECTION_IP4))
+ return 0;
+
+ /* Mangle media port. */
+ bufflen = sprintf(buffer, "%u", port);
+ if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
+ buffer, bufflen, POS_MEDIA))
+ return 0;
+
+ return mangle_content_len(pskb, ctinfo, ct, dptr);
+}
+
+/* So, this packet has hit the connection tracking matching code.
+ Mangle it, and change the expectation to match the new version. */
+static unsigned int ip_nat_sdp(struct sk_buff **pskb,
+ enum ip_conntrack_info ctinfo,
+ struct nf_conntrack_expect *exp,
+ const char *dptr)
+{
+ struct nf_conn *ct = exp->master;
+ enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+ __be32 newip;
+ u_int16_t port;
+
+ DEBUGP("ip_nat_sdp():\n");
+
+ /* Connection will come from reply */
+ newip = ct->tuplehash[!dir].tuple.dst.u3.ip;
+
+ exp->tuple.dst.u3.ip = newip;
+ exp->saved_proto.udp.port = exp->tuple.dst.u.udp.port;
+ exp->dir = !dir;
+
+ /* When you see the packet, we need to NAT it the same as the
+ this one. */
+ exp->expectfn = nf_nat_follow_master;
+
+ /* Try to get same port: if not, try to change it. */
+ for (port = ntohs(exp->saved_proto.udp.port); port != 0; port++) {
+ exp->tuple.dst.u.udp.port = htons(port);
+ if (nf_conntrack_expect_related(exp) == 0)
+ break;
+ }
+
+ if (port == 0)
+ return NF_DROP;
+
+ if (!mangle_sdp(pskb, ctinfo, ct, newip, port, dptr)) {
+ nf_conntrack_unexpect_related(exp);
+ return NF_DROP;
+ }
+ return NF_ACCEPT;
+}
+
+static void __exit nf_nat_sip_fini(void)
+{
+ rcu_assign_pointer(nf_nat_sip_hook, NULL);
+ rcu_assign_pointer(nf_nat_sdp_hook, NULL);
+ synchronize_rcu();
+}
+
+static int __init nf_nat_sip_init(void)
+{
+ BUG_ON(rcu_dereference(nf_nat_sip_hook));
+ BUG_ON(rcu_dereference(nf_nat_sdp_hook));
+ rcu_assign_pointer(nf_nat_sip_hook, ip_nat_sip);
+ rcu_assign_pointer(nf_nat_sdp_hook, ip_nat_sdp);
+ return 0;
+}
+
+module_init(nf_nat_sip_init);
+module_exit(nf_nat_sip_fini);
diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c
new file mode 100644
index 000000000000..f12528fe1bf9
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c
@@ -0,0 +1,1332 @@
+/*
+ * nf_nat_snmp_basic.c
+ *
+ * Basic SNMP Application Layer Gateway
+ *
+ * This IP NAT module is intended for use with SNMP network
+ * discovery and monitoring applications where target networks use
+ * conflicting private address realms.
+ *
+ * Static NAT is used to remap the networks from the view of the network
+ * management system at the IP layer, and this module remaps some application
+ * layer addresses to match.
+ *
+ * The simplest form of ALG is performed, where only tagged IP addresses
+ * are modified. The module does not need to be MIB aware and only scans
+ * messages at the ASN.1/BER level.
+ *
+ * Currently, only SNMPv1 and SNMPv2 are supported.
+ *
+ * More information on ALG and associated issues can be found in
+ * RFC 2962
+ *
+ * The ASB.1/BER parsing code is derived from the gxsnmp package by Gregory
+ * McLean & Jochen Friedrich, stripped down for use in the kernel.
+ *
+ * Copyright (c) 2000 RP Internet (www.rpi.net.au).
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You 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
+ *
+ * Author: James Morris <jmorris@intercode.com.au>
+ *
+ * Updates:
+ * 2000-08-06: Convert to new helper API (Harald Welte).
+ *
+ */
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/udp.h>
+#include <net/checksum.h>
+#include <net/udp.h>
+
+#include <net/netfilter/nf_nat.h>
+#include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_nat_helper.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
+MODULE_DESCRIPTION("Basic SNMP Application Layer Gateway");
+MODULE_ALIAS("ip_nat_snmp_basic");
+
+#define SNMP_PORT 161
+#define SNMP_TRAP_PORT 162
+#define NOCT1(n) (*(u8 *)n)
+
+static int debug;
+static DEFINE_SPINLOCK(snmp_lock);
+
+/*
+ * Application layer address mapping mimics the NAT mapping, but
+ * only for the first octet in this case (a more flexible system
+ * can be implemented if needed).
+ */
+struct oct1_map
+{
+ u_int8_t from;
+ u_int8_t to;
+};
+
+
+/*****************************************************************************
+ *
+ * Basic ASN.1 decoding routines (gxsnmp author Dirk Wisse)
+ *
+ *****************************************************************************/
+
+/* Class */
+#define ASN1_UNI 0 /* Universal */
+#define ASN1_APL 1 /* Application */
+#define ASN1_CTX 2 /* Context */
+#define ASN1_PRV 3 /* Private */
+
+/* Tag */
+#define ASN1_EOC 0 /* End Of Contents */
+#define ASN1_BOL 1 /* Boolean */
+#define ASN1_INT 2 /* Integer */
+#define ASN1_BTS 3 /* Bit String */
+#define ASN1_OTS 4 /* Octet String */
+#define ASN1_NUL 5 /* Null */
+#define ASN1_OJI 6 /* Object Identifier */
+#define ASN1_OJD 7 /* Object Description */
+#define ASN1_EXT 8 /* External */
+#define ASN1_SEQ 16 /* Sequence */
+#define ASN1_SET 17 /* Set */
+#define ASN1_NUMSTR 18 /* Numerical String */
+#define ASN1_PRNSTR 19 /* Printable String */
+#define ASN1_TEXSTR 20 /* Teletext String */
+#define ASN1_VIDSTR 21 /* Video String */
+#define ASN1_IA5STR 22 /* IA5 String */
+#define ASN1_UNITIM 23 /* Universal Time */
+#define ASN1_GENTIM 24 /* General Time */
+#define ASN1_GRASTR 25 /* Graphical String */
+#define ASN1_VISSTR 26 /* Visible String */
+#define ASN1_GENSTR 27 /* General String */
+
+/* Primitive / Constructed methods*/
+#define ASN1_PRI 0 /* Primitive */
+#define ASN1_CON 1 /* Constructed */
+
+/*
+ * Error codes.
+ */
+#define ASN1_ERR_NOERROR 0
+#define ASN1_ERR_DEC_EMPTY 2
+#define ASN1_ERR_DEC_EOC_MISMATCH 3
+#define ASN1_ERR_DEC_LENGTH_MISMATCH 4
+#define ASN1_ERR_DEC_BADVALUE 5
+
+/*
+ * ASN.1 context.
+ */
+struct asn1_ctx
+{
+ int error; /* Error condition */
+ unsigned char *pointer; /* Octet just to be decoded */
+ unsigned char *begin; /* First octet */
+ unsigned char *end; /* Octet after last octet */
+};
+
+/*
+ * Octet string (not null terminated)
+ */
+struct asn1_octstr
+{
+ unsigned char *data;
+ unsigned int len;
+};
+
+static void asn1_open(struct asn1_ctx *ctx,
+ unsigned char *buf,
+ unsigned int len)
+{
+ ctx->begin = buf;
+ ctx->end = buf + len;
+ ctx->pointer = buf;
+ ctx->error = ASN1_ERR_NOERROR;
+}
+
+static unsigned char asn1_octet_decode(struct asn1_ctx *ctx, unsigned char *ch)
+{
+ if (ctx->pointer >= ctx->end) {
+ ctx->error = ASN1_ERR_DEC_EMPTY;
+ return 0;
+ }
+ *ch = *(ctx->pointer)++;
+ return 1;
+}
+
+static unsigned char asn1_tag_decode(struct asn1_ctx *ctx, unsigned int *tag)
+{
+ unsigned char ch;
+
+ *tag = 0;
+
+ do
+ {
+ if (!asn1_octet_decode(ctx, &ch))
+ return 0;
+ *tag <<= 7;
+ *tag |= ch & 0x7F;
+ } while ((ch & 0x80) == 0x80);
+ return 1;
+}
+
+static unsigned char asn1_id_decode(struct asn1_ctx *ctx,
+ unsigned int *cls,
+ unsigned int *con,
+ unsigned int *tag)
+{
+ unsigned char ch;
+
+ if (!asn1_octet_decode(ctx, &ch))
+ return 0;
+
+ *cls = (ch & 0xC0) >> 6;
+ *con = (ch & 0x20) >> 5;
+ *tag = (ch & 0x1F);
+
+ if (*tag == 0x1F) {
+ if (!asn1_tag_decode(ctx, tag))
+ return 0;
+ }
+ return 1;
+}
+
+static unsigned char asn1_length_decode(struct asn1_ctx *ctx,
+ unsigned int *def,
+ unsigned int *len)
+{
+ unsigned char ch, cnt;
+
+ if (!asn1_octet_decode(ctx, &ch))
+ return 0;
+
+ if (ch == 0x80)
+ *def = 0;
+ else {
+ *def = 1;
+
+ if (ch < 0x80)
+ *len = ch;
+ else {
+ cnt = (unsigned char) (ch & 0x7F);
+ *len = 0;
+
+ while (cnt > 0) {
+ if (!asn1_octet_decode(ctx, &ch))
+ return 0;
+ *len <<= 8;
+ *len |= ch;
+ cnt--;
+ }
+ }
+ }
+ return 1;
+}
+
+static unsigned char asn1_header_decode(struct asn1_ctx *ctx,
+ unsigned char **eoc,
+ unsigned int *cls,
+ unsigned int *con,
+ unsigned int *tag)
+{
+ unsigned int def, len;
+
+ if (!asn1_id_decode(ctx, cls, con, tag))
+ return 0;
+
+ def = len = 0;
+ if (!asn1_length_decode(ctx, &def, &len))
+ return 0;
+
+ if (def)
+ *eoc = ctx->pointer + len;
+ else
+ *eoc = NULL;
+ return 1;
+}
+
+static unsigned char asn1_eoc_decode(struct asn1_ctx *ctx, unsigned char *eoc)
+{
+ unsigned char ch;
+
+ if (eoc == 0) {
+ if (!asn1_octet_decode(ctx, &ch))
+ return 0;
+
+ if (ch != 0x00) {
+ ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
+ return 0;
+ }
+
+ if (!asn1_octet_decode(ctx, &ch))
+ return 0;
+
+ if (ch != 0x00) {
+ ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
+ return 0;
+ }
+ return 1;
+ } else {
+ if (ctx->pointer != eoc) {
+ ctx->error = ASN1_ERR_DEC_LENGTH_MISMATCH;
+ return 0;
+ }
+ return 1;
+ }
+}
+
+static unsigned char asn1_null_decode(struct asn1_ctx *ctx, unsigned char *eoc)
+{
+ ctx->pointer = eoc;
+ return 1;
+}
+
+static unsigned char asn1_long_decode(struct asn1_ctx *ctx,
+ unsigned char *eoc,
+ long *integer)
+{
+ unsigned char ch;
+ unsigned int len;
+
+ if (!asn1_octet_decode(ctx, &ch))
+ return 0;
+
+ *integer = (signed char) ch;
+ len = 1;
+
+ while (ctx->pointer < eoc) {
+ if (++len > sizeof (long)) {
+ ctx->error = ASN1_ERR_DEC_BADVALUE;
+ return 0;
+ }
+
+ if (!asn1_octet_decode(ctx, &ch))
+ return 0;
+
+ *integer <<= 8;
+ *integer |= ch;
+ }
+ return 1;
+}
+
+static unsigned char asn1_uint_decode(struct asn1_ctx *ctx,
+ unsigned char *eoc,
+ unsigned int *integer)
+{
+ unsigned char ch;
+ unsigned int len;
+
+ if (!asn1_octet_decode(ctx, &ch))
+ return 0;
+
+ *integer = ch;
+ if (ch == 0) len = 0;
+ else len = 1;
+
+ while (ctx->pointer < eoc) {
+ if (++len > sizeof (unsigned int)) {
+ ctx->error = ASN1_ERR_DEC_BADVALUE;
+ return 0;
+ }
+
+ if (!asn1_octet_decode(ctx, &ch))
+ return 0;
+
+ *integer <<= 8;
+ *integer |= ch;
+ }
+ return 1;
+}
+
+static unsigned char asn1_ulong_decode(struct asn1_ctx *ctx,
+ unsigned char *eoc,
+ unsigned long *integer)
+{
+ unsigned char ch;
+ unsigned int len;
+
+ if (!asn1_octet_decode(ctx, &ch))
+ return 0;
+
+ *integer = ch;
+ if (ch == 0) len = 0;
+ else len = 1;
+
+ while (ctx->pointer < eoc) {
+ if (++len > sizeof (unsigned long)) {
+ ctx->error = ASN1_ERR_DEC_BADVALUE;
+ return 0;
+ }
+
+ if (!asn1_octet_decode(ctx, &ch))
+ return 0;
+
+ *integer <<= 8;
+ *integer |= ch;
+ }
+ return 1;
+}
+
+static unsigned char asn1_octets_decode(struct asn1_ctx *ctx,
+ unsigned char *eoc,
+ unsigned char **octets,
+ unsigned int *len)
+{
+ unsigned char *ptr;
+
+ *len = 0;
+
+ *octets = kmalloc(eoc - ctx->pointer, GFP_ATOMIC);
+ if (*octets == NULL) {
+ if (net_ratelimit())
+ printk("OOM in bsalg (%d)\n", __LINE__);
+ return 0;
+ }
+
+ ptr = *octets;
+ while (ctx->pointer < eoc) {
+ if (!asn1_octet_decode(ctx, (unsigned char *)ptr++)) {
+ kfree(*octets);
+ *octets = NULL;
+ return 0;
+ }
+ (*len)++;
+ }
+ return 1;
+}
+
+static unsigned char asn1_subid_decode(struct asn1_ctx *ctx,
+ unsigned long *subid)
+{
+ unsigned char ch;
+
+ *subid = 0;
+
+ do {
+ if (!asn1_octet_decode(ctx, &ch))
+ return 0;
+
+ *subid <<= 7;
+ *subid |= ch & 0x7F;
+ } while ((ch & 0x80) == 0x80);
+ return 1;
+}
+
+static unsigned char asn1_oid_decode(struct asn1_ctx *ctx,
+ unsigned char *eoc,
+ unsigned long **oid,
+ unsigned int *len)
+{
+ unsigned long subid;
+ unsigned int size;
+ unsigned long *optr;
+
+ size = eoc - ctx->pointer + 1;
+ *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC);
+ if (*oid == NULL) {
+ if (net_ratelimit())
+ printk("OOM in bsalg (%d)\n", __LINE__);
+ return 0;
+ }
+
+ optr = *oid;
+
+ if (!asn1_subid_decode(ctx, &subid)) {
+ kfree(*oid);
+ *oid = NULL;
+ return 0;
+ }
+
+ if (subid < 40) {
+ optr [0] = 0;
+ optr [1] = subid;
+ } else if (subid < 80) {
+ optr [0] = 1;
+ optr [1] = subid - 40;
+ } else {
+ optr [0] = 2;
+ optr [1] = subid - 80;
+ }
+
+ *len = 2;
+ optr += 2;
+
+ while (ctx->pointer < eoc) {
+ if (++(*len) > size) {
+ ctx->error = ASN1_ERR_DEC_BADVALUE;
+ kfree(*oid);
+ *oid = NULL;
+ return 0;
+ }
+
+ if (!asn1_subid_decode(ctx, optr++)) {
+ kfree(*oid);
+ *oid = NULL;
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/*****************************************************************************
+ *
+ * SNMP decoding routines (gxsnmp author Dirk Wisse)
+ *
+ *****************************************************************************/
+
+/* SNMP Versions */
+#define SNMP_V1 0
+#define SNMP_V2C 1
+#define SNMP_V2 2
+#define SNMP_V3 3
+
+/* Default Sizes */
+#define SNMP_SIZE_COMM 256
+#define SNMP_SIZE_OBJECTID 128
+#define SNMP_SIZE_BUFCHR 256
+#define SNMP_SIZE_BUFINT 128
+#define SNMP_SIZE_SMALLOBJECTID 16
+
+/* Requests */
+#define SNMP_PDU_GET 0
+#define SNMP_PDU_NEXT 1
+#define SNMP_PDU_RESPONSE 2
+#define SNMP_PDU_SET 3
+#define SNMP_PDU_TRAP1 4
+#define SNMP_PDU_BULK 5
+#define SNMP_PDU_INFORM 6
+#define SNMP_PDU_TRAP2 7
+
+/* Errors */
+#define SNMP_NOERROR 0
+#define SNMP_TOOBIG 1
+#define SNMP_NOSUCHNAME 2
+#define SNMP_BADVALUE 3
+#define SNMP_READONLY 4
+#define SNMP_GENERROR 5
+#define SNMP_NOACCESS 6
+#define SNMP_WRONGTYPE 7
+#define SNMP_WRONGLENGTH 8
+#define SNMP_WRONGENCODING 9
+#define SNMP_WRONGVALUE 10
+#define SNMP_NOCREATION 11
+#define SNMP_INCONSISTENTVALUE 12
+#define SNMP_RESOURCEUNAVAILABLE 13
+#define SNMP_COMMITFAILED 14
+#define SNMP_UNDOFAILED 15
+#define SNMP_AUTHORIZATIONERROR 16
+#define SNMP_NOTWRITABLE 17
+#define SNMP_INCONSISTENTNAME 18
+
+/* General SNMP V1 Traps */
+#define SNMP_TRAP_COLDSTART 0
+#define SNMP_TRAP_WARMSTART 1
+#define SNMP_TRAP_LINKDOWN 2
+#define SNMP_TRAP_LINKUP 3
+#define SNMP_TRAP_AUTFAILURE 4
+#define SNMP_TRAP_EQPNEIGHBORLOSS 5
+#define SNMP_TRAP_ENTSPECIFIC 6
+
+/* SNMPv1 Types */
+#define SNMP_NULL 0
+#define SNMP_INTEGER 1 /* l */
+#define SNMP_OCTETSTR 2 /* c */
+#define SNMP_DISPLAYSTR 2 /* c */
+#define SNMP_OBJECTID 3 /* ul */
+#define SNMP_IPADDR 4 /* uc */
+#define SNMP_COUNTER 5 /* ul */
+#define SNMP_GAUGE 6 /* ul */
+#define SNMP_TIMETICKS 7 /* ul */
+#define SNMP_OPAQUE 8 /* c */
+
+/* Additional SNMPv2 Types */
+#define SNMP_UINTEGER 5 /* ul */
+#define SNMP_BITSTR 9 /* uc */
+#define SNMP_NSAP 10 /* uc */
+#define SNMP_COUNTER64 11 /* ul */
+#define SNMP_NOSUCHOBJECT 12
+#define SNMP_NOSUCHINSTANCE 13
+#define SNMP_ENDOFMIBVIEW 14
+
+union snmp_syntax
+{
+ unsigned char uc[0]; /* 8 bit unsigned */
+ char c[0]; /* 8 bit signed */
+ unsigned long ul[0]; /* 32 bit unsigned */
+ long l[0]; /* 32 bit signed */
+};
+
+struct snmp_object
+{
+ unsigned long *id;
+ unsigned int id_len;
+ unsigned short type;
+ unsigned int syntax_len;
+ union snmp_syntax syntax;
+};
+
+struct snmp_request
+{
+ unsigned long id;
+ unsigned int error_status;
+ unsigned int error_index;
+};
+
+struct snmp_v1_trap
+{
+ unsigned long *id;
+ unsigned int id_len;
+ unsigned long ip_address; /* pointer */
+ unsigned int general;
+ unsigned int specific;
+ unsigned long time;
+};
+
+/* SNMP types */
+#define SNMP_IPA 0
+#define SNMP_CNT 1
+#define SNMP_GGE 2
+#define SNMP_TIT 3
+#define SNMP_OPQ 4
+#define SNMP_C64 6
+
+/* SNMP errors */
+#define SERR_NSO 0
+#define SERR_NSI 1
+#define SERR_EOM 2
+
+static inline void mangle_address(unsigned char *begin,
+ unsigned char *addr,
+ const struct oct1_map *map,
+ __sum16 *check);
+struct snmp_cnv
+{
+ unsigned int class;
+ unsigned int tag;
+ int syntax;
+};
+
+static struct snmp_cnv snmp_conv [] =
+{
+ {ASN1_UNI, ASN1_NUL, SNMP_NULL},
+ {ASN1_UNI, ASN1_INT, SNMP_INTEGER},
+ {ASN1_UNI, ASN1_OTS, SNMP_OCTETSTR},
+ {ASN1_UNI, ASN1_OTS, SNMP_DISPLAYSTR},
+ {ASN1_UNI, ASN1_OJI, SNMP_OBJECTID},
+ {ASN1_APL, SNMP_IPA, SNMP_IPADDR},
+ {ASN1_APL, SNMP_CNT, SNMP_COUNTER}, /* Counter32 */
+ {ASN1_APL, SNMP_GGE, SNMP_GAUGE}, /* Gauge32 == Unsigned32 */
+ {ASN1_APL, SNMP_TIT, SNMP_TIMETICKS},
+ {ASN1_APL, SNMP_OPQ, SNMP_OPAQUE},
+
+ /* SNMPv2 data types and errors */
+ {ASN1_UNI, ASN1_BTS, SNMP_BITSTR},
+ {ASN1_APL, SNMP_C64, SNMP_COUNTER64},
+ {ASN1_CTX, SERR_NSO, SNMP_NOSUCHOBJECT},
+ {ASN1_CTX, SERR_NSI, SNMP_NOSUCHINSTANCE},
+ {ASN1_CTX, SERR_EOM, SNMP_ENDOFMIBVIEW},
+ {0, 0, -1}
+};
+
+static unsigned char snmp_tag_cls2syntax(unsigned int tag,
+ unsigned int cls,
+ unsigned short *syntax)
+{
+ struct snmp_cnv *cnv;
+
+ cnv = snmp_conv;
+
+ while (cnv->syntax != -1) {
+ if (cnv->tag == tag && cnv->class == cls) {
+ *syntax = cnv->syntax;
+ return 1;
+ }
+ cnv++;
+ }
+ return 0;
+}
+
+static unsigned char snmp_object_decode(struct asn1_ctx *ctx,
+ struct snmp_object **obj)
+{
+ unsigned int cls, con, tag, len, idlen;
+ unsigned short type;
+ unsigned char *eoc, *end, *p;
+ unsigned long *lp, *id;
+ unsigned long ul;
+ long l;
+
+ *obj = NULL;
+ id = NULL;
+
+ if (!asn1_header_decode(ctx, &eoc, &cls, &con, &tag))
+ return 0;
+
+ if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ)
+ return 0;
+
+ if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
+ return 0;
+
+ if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OJI)
+ return 0;
+
+ if (!asn1_oid_decode(ctx, end, &id, &idlen))
+ return 0;
+
+ if (!asn1_header_decode(ctx, &end, &cls, &con, &tag)) {
+ kfree(id);
+ return 0;
+ }
+
+ if (con != ASN1_PRI) {
+ kfree(id);
+ return 0;
+ }
+
+ type = 0;
+ if (!snmp_tag_cls2syntax(tag, cls, &type)) {
+ kfree(id);
+ return 0;
+ }
+
+ l = 0;
+ switch (type) {
+ case SNMP_INTEGER:
+ len = sizeof(long);
+ if (!asn1_long_decode(ctx, end, &l)) {
+ kfree(id);
+ return 0;
+ }
+ *obj = kmalloc(sizeof(struct snmp_object) + len,
+ GFP_ATOMIC);
+ if (*obj == NULL) {
+ kfree(id);
+ if (net_ratelimit())
+ printk("OOM in bsalg (%d)\n", __LINE__);
+ return 0;
+ }
+ (*obj)->syntax.l[0] = l;
+ break;
+ case SNMP_OCTETSTR:
+ case SNMP_OPAQUE:
+ if (!asn1_octets_decode(ctx, end, &p, &len)) {
+ kfree(id);
+ return 0;
+ }
+ *obj = kmalloc(sizeof(struct snmp_object) + len,
+ GFP_ATOMIC);
+ if (*obj == NULL) {
+ kfree(id);
+ if (net_ratelimit())
+ printk("OOM in bsalg (%d)\n", __LINE__);
+ return 0;
+ }
+ memcpy((*obj)->syntax.c, p, len);
+ kfree(p);
+ break;
+ case SNMP_NULL:
+ case SNMP_NOSUCHOBJECT:
+ case SNMP_NOSUCHINSTANCE:
+ case SNMP_ENDOFMIBVIEW:
+ len = 0;
+ *obj = kmalloc(sizeof(struct snmp_object), GFP_ATOMIC);
+ if (*obj == NULL) {
+ kfree(id);
+ if (net_ratelimit())
+ printk("OOM in bsalg (%d)\n", __LINE__);
+ return 0;
+ }
+ if (!asn1_null_decode(ctx, end)) {
+ kfree(id);
+ kfree(*obj);
+ *obj = NULL;
+ return 0;
+ }
+ break;
+ case SNMP_OBJECTID:
+ if (!asn1_oid_decode(ctx, end, (unsigned long **)&lp, &len)) {
+ kfree(id);
+ return 0;
+ }
+ len *= sizeof(unsigned long);
+ *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
+ if (*obj == NULL) {
+ kfree(lp);
+ kfree(id);
+ if (net_ratelimit())
+ printk("OOM in bsalg (%d)\n", __LINE__);
+ return 0;
+ }
+ memcpy((*obj)->syntax.ul, lp, len);
+ kfree(lp);
+ break;
+ case SNMP_IPADDR:
+ if (!asn1_octets_decode(ctx, end, &p, &len)) {
+ kfree(id);
+ return 0;
+ }
+ if (len != 4) {
+ kfree(p);
+ kfree(id);
+ return 0;
+ }
+ *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
+ if (*obj == NULL) {
+ kfree(p);
+ kfree(id);
+ if (net_ratelimit())
+ printk("OOM in bsalg (%d)\n", __LINE__);
+ return 0;
+ }
+ memcpy((*obj)->syntax.uc, p, len);
+ kfree(p);
+ break;
+ case SNMP_COUNTER:
+ case SNMP_GAUGE:
+ case SNMP_TIMETICKS:
+ len = sizeof(unsigned long);
+ if (!asn1_ulong_decode(ctx, end, &ul)) {
+ kfree(id);
+ return 0;
+ }
+ *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
+ if (*obj == NULL) {
+ kfree(id);
+ if (net_ratelimit())
+ printk("OOM in bsalg (%d)\n", __LINE__);
+ return 0;
+ }
+ (*obj)->syntax.ul[0] = ul;
+ break;
+ default:
+ kfree(id);
+ return 0;
+ }
+
+ (*obj)->syntax_len = len;
+ (*obj)->type = type;
+ (*obj)->id = id;
+ (*obj)->id_len = idlen;
+
+ if (!asn1_eoc_decode(ctx, eoc)) {
+ kfree(id);
+ kfree(*obj);
+ *obj = NULL;
+ return 0;
+ }
+ return 1;
+}
+
+static unsigned char snmp_request_decode(struct asn1_ctx *ctx,
+ struct snmp_request *request)
+{
+ unsigned int cls, con, tag;
+ unsigned char *end;
+
+ if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
+ return 0;
+
+ if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
+ return 0;
+
+ if (!asn1_ulong_decode(ctx, end, &request->id))
+ return 0;
+
+ if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
+ return 0;
+
+ if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
+ return 0;
+
+ if (!asn1_uint_decode(ctx, end, &request->error_status))
+ return 0;
+
+ if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
+ return 0;
+
+ if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
+ return 0;
+
+ if (!asn1_uint_decode(ctx, end, &request->error_index))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Fast checksum update for possibly oddly-aligned UDP byte, from the
+ * code example in the draft.
+ */
+static void fast_csum(__sum16 *csum,
+ const unsigned char *optr,
+ const unsigned char *nptr,
+ int offset)
+{
+ unsigned char s[4];
+
+ if (offset & 1) {
+ s[0] = s[2] = 0;
+ s[1] = ~*optr;
+ s[3] = *nptr;
+ } else {
+ s[1] = s[3] = 0;
+ s[0] = ~*optr;
+ s[2] = *nptr;
+ }
+
+ *csum = csum_fold(csum_partial(s, 4, ~csum_unfold(*csum)));
+}
+
+/*
+ * Mangle IP address.
+ * - begin points to the start of the snmp messgae
+ * - addr points to the start of the address
+ */
+static inline void mangle_address(unsigned char *begin,
+ unsigned char *addr,
+ const struct oct1_map *map,
+ __sum16 *check)
+{
+ if (map->from == NOCT1(addr)) {
+ u_int32_t old;
+
+ if (debug)
+ memcpy(&old, (unsigned char *)addr, sizeof(old));
+
+ *addr = map->to;
+
+ /* Update UDP checksum if being used */
+ if (*check) {
+ fast_csum(check,
+ &map->from, &map->to, addr - begin);
+
+ }
+
+ if (debug)
+ printk(KERN_DEBUG "bsalg: mapped %u.%u.%u.%u to "
+ "%u.%u.%u.%u\n", NIPQUAD(old), NIPQUAD(*addr));
+ }
+}
+
+static unsigned char snmp_trap_decode(struct asn1_ctx *ctx,
+ struct snmp_v1_trap *trap,
+ const struct oct1_map *map,
+ __sum16 *check)
+{
+ unsigned int cls, con, tag, len;
+ unsigned char *end;
+
+ if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
+ return 0;
+
+ if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OJI)
+ return 0;
+
+ if (!asn1_oid_decode(ctx, end, &trap->id, &trap->id_len))
+ return 0;
+
+ if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
+ goto err_id_free;
+
+ if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_IPA) ||
+ (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_OTS)))
+ goto err_id_free;
+
+ if (!asn1_octets_decode(ctx, end, (unsigned char **)&trap->ip_address, &len))
+ goto err_id_free;
+
+ /* IPv4 only */
+ if (len != 4)
+ goto err_addr_free;
+
+ mangle_address(ctx->begin, ctx->pointer - 4, map, check);
+
+ if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
+ goto err_addr_free;
+
+ if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
+ goto err_addr_free;
+
+ if (!asn1_uint_decode(ctx, end, &trap->general))
+ goto err_addr_free;
+
+ if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
+ goto err_addr_free;
+
+ if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
+ goto err_addr_free;
+
+ if (!asn1_uint_decode(ctx, end, &trap->specific))
+ goto err_addr_free;
+
+ if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
+ goto err_addr_free;
+
+ if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_TIT) ||
+ (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_INT)))
+ goto err_addr_free;
+
+ if (!asn1_ulong_decode(ctx, end, &trap->time))
+ goto err_addr_free;
+
+ return 1;
+
+err_addr_free:
+ kfree((unsigned long *)trap->ip_address);
+
+err_id_free:
+ kfree(trap->id);
+
+ return 0;
+}
+
+/*****************************************************************************
+ *
+ * Misc. routines
+ *
+ *****************************************************************************/
+
+static void hex_dump(unsigned char *buf, size_t len)
+{
+ size_t i;
+
+ for (i = 0; i < len; i++) {
+ if (i && !(i % 16))
+ printk("\n");
+ printk("%02x ", *(buf + i));
+ }
+ printk("\n");
+}
+
+/*
+ * Parse and mangle SNMP message according to mapping.
+ * (And this is the fucking 'basic' method).
+ */
+static int snmp_parse_mangle(unsigned char *msg,
+ u_int16_t len,
+ const struct oct1_map *map,
+ __sum16 *check)
+{
+ unsigned char *eoc, *end;
+ unsigned int cls, con, tag, vers, pdutype;
+ struct asn1_ctx ctx;
+ struct asn1_octstr comm;
+ struct snmp_object **obj;
+
+ if (debug > 1)
+ hex_dump(msg, len);
+
+ asn1_open(&ctx, msg, len);
+
+ /*
+ * Start of SNMP message.
+ */
+ if (!asn1_header_decode(&ctx, &eoc, &cls, &con, &tag))
+ return 0;
+ if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ)
+ return 0;
+
+ /*
+ * Version 1 or 2 handled.
+ */
+ if (!asn1_header_decode(&ctx, &end, &cls, &con, &tag))
+ return 0;
+ if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
+ return 0;
+ if (!asn1_uint_decode (&ctx, end, &vers))
+ return 0;
+ if (debug > 1)
+ printk(KERN_DEBUG "bsalg: snmp version: %u\n", vers + 1);
+ if (vers > 1)
+ return 1;
+
+ /*
+ * Community.
+ */
+ if (!asn1_header_decode (&ctx, &end, &cls, &con, &tag))
+ return 0;
+ if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OTS)
+ return 0;
+ if (!asn1_octets_decode(&ctx, end, &comm.data, &comm.len))
+ return 0;
+ if (debug > 1) {
+ unsigned int i;
+
+ printk(KERN_DEBUG "bsalg: community: ");
+ for (i = 0; i < comm.len; i++)
+ printk("%c", comm.data[i]);
+ printk("\n");
+ }
+ kfree(comm.data);
+
+ /*
+ * PDU type
+ */
+ if (!asn1_header_decode(&ctx, &eoc, &cls, &con, &pdutype))
+ return 0;
+ if (cls != ASN1_CTX || con != ASN1_CON)
+ return 0;
+ if (debug > 1) {
+ unsigned char *pdus[] = {
+ [SNMP_PDU_GET] = "get",
+ [SNMP_PDU_NEXT] = "get-next",
+ [SNMP_PDU_RESPONSE] = "response",
+ [SNMP_PDU_SET] = "set",
+ [SNMP_PDU_TRAP1] = "trapv1",
+ [SNMP_PDU_BULK] = "bulk",
+ [SNMP_PDU_INFORM] = "inform",
+ [SNMP_PDU_TRAP2] = "trapv2"
+ };
+
+ if (pdutype > SNMP_PDU_TRAP2)
+ printk(KERN_DEBUG "bsalg: bad pdu type %u\n", pdutype);
+ else
+ printk(KERN_DEBUG "bsalg: pdu: %s\n", pdus[pdutype]);
+ }
+ if (pdutype != SNMP_PDU_RESPONSE &&
+ pdutype != SNMP_PDU_TRAP1 && pdutype != SNMP_PDU_TRAP2)
+ return 1;
+
+ /*
+ * Request header or v1 trap
+ */
+ if (pdutype == SNMP_PDU_TRAP1) {
+ struct snmp_v1_trap trap;
+ unsigned char ret = snmp_trap_decode(&ctx, &trap, map, check);
+
+ if (ret) {
+ kfree(trap.id);
+ kfree((unsigned long *)trap.ip_address);
+ } else
+ return ret;
+
+ } else {
+ struct snmp_request req;
+
+ if (!snmp_request_decode(&ctx, &req))
+ return 0;
+
+ if (debug > 1)
+ printk(KERN_DEBUG "bsalg: request: id=0x%lx error_status=%u "
+ "error_index=%u\n", req.id, req.error_status,
+ req.error_index);
+ }
+
+ /*
+ * Loop through objects, look for IP addresses to mangle.
+ */
+ if (!asn1_header_decode(&ctx, &eoc, &cls, &con, &tag))
+ return 0;
+
+ if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ)
+ return 0;
+
+ obj = kmalloc(sizeof(struct snmp_object), GFP_ATOMIC);
+ if (obj == NULL) {
+ if (net_ratelimit())
+ printk(KERN_WARNING "OOM in bsalg(%d)\n", __LINE__);
+ return 0;
+ }
+
+ while (!asn1_eoc_decode(&ctx, eoc)) {
+ unsigned int i;
+
+ if (!snmp_object_decode(&ctx, obj)) {
+ if (*obj) {
+ kfree((*obj)->id);
+ kfree(*obj);
+ }
+ kfree(obj);
+ return 0;
+ }
+
+ if (debug > 1) {
+ printk(KERN_DEBUG "bsalg: object: ");
+ for (i = 0; i < (*obj)->id_len; i++) {
+ if (i > 0)
+ printk(".");
+ printk("%lu", (*obj)->id[i]);
+ }
+ printk(": type=%u\n", (*obj)->type);
+
+ }
+
+ if ((*obj)->type == SNMP_IPADDR)
+ mangle_address(ctx.begin, ctx.pointer - 4 , map, check);
+
+ kfree((*obj)->id);
+ kfree(*obj);
+ }
+ kfree(obj);
+
+ if (!asn1_eoc_decode(&ctx, eoc))
+ return 0;
+
+ return 1;
+}
+
+/*****************************************************************************
+ *
+ * NAT routines.
+ *
+ *****************************************************************************/
+
+/*
+ * SNMP translation routine.
+ */
+static int snmp_translate(struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ struct sk_buff **pskb)
+{
+ struct iphdr *iph = (*pskb)->nh.iph;
+ struct udphdr *udph = (struct udphdr *)((__be32 *)iph + iph->ihl);
+ u_int16_t udplen = ntohs(udph->len);
+ u_int16_t paylen = udplen - sizeof(struct udphdr);
+ int dir = CTINFO2DIR(ctinfo);
+ struct oct1_map map;
+
+ /*
+ * Determine mappping for application layer addresses based
+ * on NAT manipulations for the packet.
+ */
+ if (dir == IP_CT_DIR_ORIGINAL) {
+ /* SNAT traps */
+ map.from = NOCT1(&ct->tuplehash[dir].tuple.src.u3.ip);
+ map.to = NOCT1(&ct->tuplehash[!dir].tuple.dst.u3.ip);
+ } else {
+ /* DNAT replies */
+ map.from = NOCT1(&ct->tuplehash[dir].tuple.src.u3.ip);
+ map.to = NOCT1(&ct->tuplehash[!dir].tuple.dst.u3.ip);
+ }
+
+ if (map.from == map.to)
+ return NF_ACCEPT;
+
+ if (!snmp_parse_mangle((unsigned char *)udph + sizeof(struct udphdr),
+ paylen, &map, &udph->check)) {
+ if (net_ratelimit())
+ printk(KERN_WARNING "bsalg: parser failed\n");
+ return NF_DROP;
+ }
+ return NF_ACCEPT;
+}
+
+/* We don't actually set up expectations, just adjust internal IP
+ * addresses if this is being NATted */
+static int help(struct sk_buff **pskb, unsigned int protoff,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo)
+{
+ int dir = CTINFO2DIR(ctinfo);
+ unsigned int ret;
+ struct iphdr *iph = (*pskb)->nh.iph;
+ struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl);
+
+ /* SNMP replies and originating SNMP traps get mangled */
+ if (udph->source == htons(SNMP_PORT) && dir != IP_CT_DIR_REPLY)
+ return NF_ACCEPT;
+ if (udph->dest == htons(SNMP_TRAP_PORT) && dir != IP_CT_DIR_ORIGINAL)
+ return NF_ACCEPT;
+
+ /* No NAT? */
+ if (!(ct->status & IPS_NAT_MASK))
+ return NF_ACCEPT;
+
+ /*
+ * Make sure the packet length is ok. So far, we were only guaranteed
+ * to have a valid length IP header plus 8 bytes, which means we have
+ * enough room for a UDP header. Just verify the UDP length field so we
+ * can mess around with the payload.
+ */
+ if (ntohs(udph->len) != (*pskb)->len - (iph->ihl << 2)) {
+ if (net_ratelimit())
+ printk(KERN_WARNING "SNMP: dropping malformed packet "
+ "src=%u.%u.%u.%u dst=%u.%u.%u.%u\n",
+ NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
+ return NF_DROP;
+ }
+
+ if (!skb_make_writable(pskb, (*pskb)->len))
+ return NF_DROP;
+
+ spin_lock_bh(&snmp_lock);
+ ret = snmp_translate(ct, ctinfo, pskb);
+ spin_unlock_bh(&snmp_lock);
+ return ret;
+}
+
+static struct nf_conntrack_helper snmp_helper __read_mostly = {
+ .max_expected = 0,
+ .timeout = 180,
+ .me = THIS_MODULE,
+ .help = help,
+ .name = "snmp",
+ .tuple.src.l3num = AF_INET,
+ .tuple.src.u.udp.port = __constant_htons(SNMP_PORT),
+ .tuple.dst.protonum = IPPROTO_UDP,
+ .mask.src.l3num = 0xFFFF,
+ .mask.src.u.udp.port = __constant_htons(0xFFFF),
+ .mask.dst.protonum = 0xFF,
+};
+
+static struct nf_conntrack_helper snmp_trap_helper __read_mostly = {
+ .max_expected = 0,
+ .timeout = 180,
+ .me = THIS_MODULE,
+ .help = help,
+ .name = "snmp_trap",
+ .tuple.src.l3num = AF_INET,
+ .tuple.src.u.udp.port = __constant_htons(SNMP_TRAP_PORT),
+ .tuple.dst.protonum = IPPROTO_UDP,
+ .mask.src.l3num = 0xFFFF,
+ .mask.src.u.udp.port = __constant_htons(0xFFFF),
+ .mask.dst.protonum = 0xFF,
+};
+
+/*****************************************************************************
+ *
+ * Module stuff.
+ *
+ *****************************************************************************/
+
+static int __init nf_nat_snmp_basic_init(void)
+{
+ int ret = 0;
+
+ ret = nf_conntrack_helper_register(&snmp_helper);
+ if (ret < 0)
+ return ret;
+ ret = nf_conntrack_helper_register(&snmp_trap_helper);
+ if (ret < 0) {
+ nf_conntrack_helper_unregister(&snmp_helper);
+ return ret;
+ }
+ return ret;
+}
+
+static void __exit nf_nat_snmp_basic_fini(void)
+{
+ nf_conntrack_helper_unregister(&snmp_helper);
+ nf_conntrack_helper_unregister(&snmp_trap_helper);
+}
+
+module_init(nf_nat_snmp_basic_init);
+module_exit(nf_nat_snmp_basic_fini);
+
+module_param(debug, int, 0600);
diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c
new file mode 100644
index 000000000000..730a7a44c883
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_standalone.c
@@ -0,0 +1,406 @@
+/* (C) 1999-2001 Paul `Rusty' Russell
+ * (C) 2002-2006 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/types.h>
+#include <linux/icmp.h>
+#include <linux/ip.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/proc_fs.h>
+#include <net/ip.h>
+#include <net/checksum.h>
+#include <linux/spinlock.h>
+
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_core.h>
+#include <net/netfilter/nf_nat.h>
+#include <net/netfilter/nf_nat_rule.h>
+#include <net/netfilter/nf_nat_protocol.h>
+#include <net/netfilter/nf_nat_core.h>
+#include <net/netfilter/nf_nat_helper.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+#define HOOKNAME(hooknum) ((hooknum) == NF_IP_POST_ROUTING ? "POST_ROUTING" \
+ : ((hooknum) == NF_IP_PRE_ROUTING ? "PRE_ROUTING" \
+ : ((hooknum) == NF_IP_LOCAL_OUT ? "LOCAL_OUT" \
+ : ((hooknum) == NF_IP_LOCAL_IN ? "LOCAL_IN" \
+ : "*ERROR*")))
+
+#ifdef CONFIG_XFRM
+static void nat_decode_session(struct sk_buff *skb, struct flowi *fl)
+{
+ struct nf_conn *ct;
+ struct nf_conntrack_tuple *t;
+ enum ip_conntrack_info ctinfo;
+ enum ip_conntrack_dir dir;
+ unsigned long statusbit;
+
+ ct = nf_ct_get(skb, &ctinfo);
+ if (ct == NULL)
+ return;
+ dir = CTINFO2DIR(ctinfo);
+ t = &ct->tuplehash[dir].tuple;
+
+ if (dir == IP_CT_DIR_ORIGINAL)
+ statusbit = IPS_DST_NAT;
+ else
+ statusbit = IPS_SRC_NAT;
+
+ if (ct->status & statusbit) {
+ fl->fl4_dst = t->dst.u3.ip;
+ if (t->dst.protonum == IPPROTO_TCP ||
+ t->dst.protonum == IPPROTO_UDP)
+ fl->fl_ip_dport = t->dst.u.tcp.port;
+ }
+
+ statusbit ^= IPS_NAT_MASK;
+
+ if (ct->status & statusbit) {
+ fl->fl4_src = t->src.u3.ip;
+ if (t->dst.protonum == IPPROTO_TCP ||
+ t->dst.protonum == IPPROTO_UDP)
+ fl->fl_ip_sport = t->src.u.tcp.port;
+ }
+}
+#endif
+
+static unsigned int
+nf_nat_fn(unsigned int hooknum,
+ struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ struct nf_conn *ct;
+ enum ip_conntrack_info ctinfo;
+ struct nf_conn_nat *nat;
+ struct nf_nat_info *info;
+ /* maniptype == SRC for postrouting. */
+ enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum);
+
+ /* We never see fragments: conntrack defrags on pre-routing
+ and local-out, and nf_nat_out protects post-routing. */
+ NF_CT_ASSERT(!((*pskb)->nh.iph->frag_off
+ & htons(IP_MF|IP_OFFSET)));
+
+ ct = nf_ct_get(*pskb, &ctinfo);
+ /* Can't track? It's not due to stress, or conntrack would
+ have dropped it. Hence it's the user's responsibilty to
+ packet filter it out, or implement conntrack/NAT for that
+ protocol. 8) --RR */
+ if (!ct) {
+ /* Exception: ICMP redirect to new connection (not in
+ hash table yet). We must not let this through, in
+ case we're doing NAT to the same network. */
+ if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) {
+ struct icmphdr _hdr, *hp;
+
+ hp = skb_header_pointer(*pskb,
+ (*pskb)->nh.iph->ihl*4,
+ sizeof(_hdr), &_hdr);
+ if (hp != NULL &&
+ hp->type == ICMP_REDIRECT)
+ return NF_DROP;
+ }
+ return NF_ACCEPT;
+ }
+
+ /* Don't try to NAT if this packet is not conntracked */
+ if (ct == &nf_conntrack_untracked)
+ return NF_ACCEPT;
+
+ nat = nfct_nat(ct);
+ if (!nat)
+ return NF_DROP;
+
+ switch (ctinfo) {
+ case IP_CT_RELATED:
+ case IP_CT_RELATED+IP_CT_IS_REPLY:
+ if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) {
+ if (!nf_nat_icmp_reply_translation(ct, ctinfo,
+ hooknum, pskb))
+ return NF_DROP;
+ else
+ return NF_ACCEPT;
+ }
+ /* Fall thru... (Only ICMPs can be IP_CT_IS_REPLY) */
+ case IP_CT_NEW:
+ info = &nat->info;
+
+ /* Seen it before? This can happen for loopback, retrans,
+ or local packets.. */
+ if (!nf_nat_initialized(ct, maniptype)) {
+ unsigned int ret;
+
+ if (unlikely(nf_ct_is_confirmed(ct)))
+ /* NAT module was loaded late */
+ ret = alloc_null_binding_confirmed(ct, info,
+ hooknum);
+ else if (hooknum == NF_IP_LOCAL_IN)
+ /* LOCAL_IN hook doesn't have a chain! */
+ ret = alloc_null_binding(ct, info, hooknum);
+ else
+ ret = nf_nat_rule_find(pskb, hooknum, in, out,
+ ct, info);
+
+ if (ret != NF_ACCEPT) {
+ return ret;
+ }
+ } else
+ DEBUGP("Already setup manip %s for ct %p\n",
+ maniptype == IP_NAT_MANIP_SRC ? "SRC" : "DST",
+ ct);
+ break;
+
+ default:
+ /* ESTABLISHED */
+ NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED ||
+ ctinfo == (IP_CT_ESTABLISHED+IP_CT_IS_REPLY));
+ info = &nat->info;
+ }
+
+ NF_CT_ASSERT(info);
+ return nf_nat_packet(ct, ctinfo, hooknum, pskb);
+}
+
+static unsigned int
+nf_nat_in(unsigned int hooknum,
+ struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ unsigned int ret;
+ __be32 daddr = (*pskb)->nh.iph->daddr;
+
+ ret = nf_nat_fn(hooknum, pskb, in, out, okfn);
+ if (ret != NF_DROP && ret != NF_STOLEN &&
+ daddr != (*pskb)->nh.iph->daddr) {
+ dst_release((*pskb)->dst);
+ (*pskb)->dst = NULL;
+ }
+ return ret;
+}
+
+static unsigned int
+nf_nat_out(unsigned int hooknum,
+ struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+#ifdef CONFIG_XFRM
+ struct nf_conn *ct;
+ enum ip_conntrack_info ctinfo;
+#endif
+ unsigned int ret;
+
+ /* root is playing with raw sockets. */
+ if ((*pskb)->len < sizeof(struct iphdr) ||
+ (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
+ return NF_ACCEPT;
+
+ ret = nf_nat_fn(hooknum, pskb, in, out, okfn);
+#ifdef CONFIG_XFRM
+ if (ret != NF_DROP && ret != NF_STOLEN &&
+ (ct = nf_ct_get(*pskb, &ctinfo)) != NULL) {
+ enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+
+ if (ct->tuplehash[dir].tuple.src.u3.ip !=
+ ct->tuplehash[!dir].tuple.dst.u3.ip
+ || ct->tuplehash[dir].tuple.src.u.all !=
+ ct->tuplehash[!dir].tuple.dst.u.all
+ )
+ return ip_xfrm_me_harder(pskb) == 0 ? ret : NF_DROP;
+ }
+#endif
+ return ret;
+}
+
+static unsigned int
+nf_nat_local_fn(unsigned int hooknum,
+ struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ struct nf_conn *ct;
+ enum ip_conntrack_info ctinfo;
+ unsigned int ret;
+
+ /* root is playing with raw sockets. */
+ if ((*pskb)->len < sizeof(struct iphdr) ||
+ (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
+ return NF_ACCEPT;
+
+ ret = nf_nat_fn(hooknum, pskb, in, out, okfn);
+ if (ret != NF_DROP && ret != NF_STOLEN &&
+ (ct = nf_ct_get(*pskb, &ctinfo)) != NULL) {
+ enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+
+ if (ct->tuplehash[dir].tuple.dst.u3.ip !=
+ ct->tuplehash[!dir].tuple.src.u3.ip
+#ifdef CONFIG_XFRM
+ || ct->tuplehash[dir].tuple.dst.u.all !=
+ ct->tuplehash[!dir].tuple.src.u.all
+#endif
+ )
+ if (ip_route_me_harder(pskb, RTN_UNSPEC))
+ ret = NF_DROP;
+ }
+ return ret;
+}
+
+static unsigned int
+nf_nat_adjust(unsigned int hooknum,
+ struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ struct nf_conn *ct;
+ enum ip_conntrack_info ctinfo;
+
+ ct = nf_ct_get(*pskb, &ctinfo);
+ if (ct && test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) {
+ DEBUGP("nf_nat_standalone: adjusting sequence number\n");
+ if (!nf_nat_seq_adjust(pskb, ct, ctinfo))
+ return NF_DROP;
+ }
+ return NF_ACCEPT;
+}
+
+/* We must be after connection tracking and before packet filtering. */
+
+static struct nf_hook_ops nf_nat_ops[] = {
+ /* Before packet filtering, change destination */
+ {
+ .hook = nf_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 = nf_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 = nf_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 = nf_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 = nf_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 = nf_nat_adjust,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_LOCAL_IN,
+ .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
+ },
+};
+
+static int __init nf_nat_standalone_init(void)
+{
+ int size, ret = 0;
+
+ need_conntrack();
+
+ size = ALIGN(sizeof(struct nf_conn), __alignof__(struct nf_conn_nat)) +
+ sizeof(struct nf_conn_nat);
+ ret = nf_conntrack_register_cache(NF_CT_F_NAT, "nf_nat:base", size);
+ if (ret < 0) {
+ printk(KERN_ERR "nf_nat_init: Unable to create slab cache\n");
+ return ret;
+ }
+
+ size = ALIGN(size, __alignof__(struct nf_conn_help)) +
+ sizeof(struct nf_conn_help);
+ ret = nf_conntrack_register_cache(NF_CT_F_NAT|NF_CT_F_HELP,
+ "nf_nat:help", size);
+ if (ret < 0) {
+ printk(KERN_ERR "nf_nat_init: Unable to create slab cache\n");
+ goto cleanup_register_cache;
+ }
+#ifdef CONFIG_XFRM
+ BUG_ON(ip_nat_decode_session != NULL);
+ ip_nat_decode_session = nat_decode_session;
+#endif
+ ret = nf_nat_rule_init();
+ if (ret < 0) {
+ printk("nf_nat_init: can't setup rules.\n");
+ goto cleanup_decode_session;
+ }
+ ret = nf_register_hooks(nf_nat_ops, ARRAY_SIZE(nf_nat_ops));
+ if (ret < 0) {
+ printk("nf_nat_init: can't register hooks.\n");
+ goto cleanup_rule_init;
+ }
+ nf_nat_module_is_loaded = 1;
+ return ret;
+
+ cleanup_rule_init:
+ nf_nat_rule_cleanup();
+ cleanup_decode_session:
+#ifdef CONFIG_XFRM
+ ip_nat_decode_session = NULL;
+ synchronize_net();
+#endif
+ nf_conntrack_unregister_cache(NF_CT_F_NAT|NF_CT_F_HELP);
+ cleanup_register_cache:
+ nf_conntrack_unregister_cache(NF_CT_F_NAT);
+ return ret;
+}
+
+static void __exit nf_nat_standalone_fini(void)
+{
+ nf_unregister_hooks(nf_nat_ops, ARRAY_SIZE(nf_nat_ops));
+ nf_nat_rule_cleanup();
+ nf_nat_module_is_loaded = 0;
+#ifdef CONFIG_XFRM
+ ip_nat_decode_session = NULL;
+ synchronize_net();
+#endif
+ /* Conntrack caches are unregistered in nf_conntrack_cleanup */
+}
+
+module_init(nf_nat_standalone_init);
+module_exit(nf_nat_standalone_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ip_nat");
diff --git a/net/ipv4/netfilter/nf_nat_tftp.c b/net/ipv4/netfilter/nf_nat_tftp.c
new file mode 100644
index 000000000000..2566b79de224
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_tftp.c
@@ -0,0 +1,52 @@
+/* (C) 2001-2002 Magnus Boden <mb@ozaba.mine.nu>
+ *
+ * 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/moduleparam.h>
+#include <linux/udp.h>
+
+#include <net/netfilter/nf_nat_helper.h>
+#include <net/netfilter/nf_nat_rule.h>
+#include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_conntrack_expect.h>
+#include <linux/netfilter/nf_conntrack_tftp.h>
+
+MODULE_AUTHOR("Magnus Boden <mb@ozaba.mine.nu>");
+MODULE_DESCRIPTION("TFTP NAT helper");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ip_nat_tftp");
+
+static unsigned int help(struct sk_buff **pskb,
+ enum ip_conntrack_info ctinfo,
+ struct nf_conntrack_expect *exp)
+{
+ struct nf_conn *ct = exp->master;
+
+ exp->saved_proto.udp.port
+ = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port;
+ exp->dir = IP_CT_DIR_REPLY;
+ exp->expectfn = nf_nat_follow_master;
+ if (nf_conntrack_expect_related(exp) != 0)
+ return NF_DROP;
+ return NF_ACCEPT;
+}
+
+static void __exit nf_nat_tftp_fini(void)
+{
+ rcu_assign_pointer(nf_nat_tftp_hook, NULL);
+ synchronize_rcu();
+}
+
+static int __init nf_nat_tftp_init(void)
+{
+ BUG_ON(rcu_dereference(nf_nat_tftp_hook));
+ rcu_assign_pointer(nf_nat_tftp_hook, help);
+ return 0;
+}
+
+module_init(nf_nat_tftp_init);
+module_exit(nf_nat_tftp_fini);
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index 9c6cbe3d9fb8..cd873da54cbe 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -38,6 +38,7 @@
#include <net/protocol.h>
#include <net/tcp.h>
#include <net/udp.h>
+#include <net/udplite.h>
#include <linux/inetdevice.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
@@ -66,6 +67,7 @@ static int sockstat_seq_show(struct seq_file *seq, void *v)
tcp_death_row.tw_count, atomic_read(&tcp_sockets_allocated),
atomic_read(&tcp_memory_allocated));
seq_printf(seq, "UDP: inuse %d\n", fold_prot_inuse(&udp_prot));
+ seq_printf(seq, "UDPLITE: inuse %d\n", fold_prot_inuse(&udplite_prot));
seq_printf(seq, "RAW: inuse %d\n", fold_prot_inuse(&raw_prot));
seq_printf(seq, "FRAG: inuse %d memory %d\n", ip_frag_nqueues,
atomic_read(&ip_frag_mem));
@@ -304,6 +306,17 @@ static int snmp_seq_show(struct seq_file *seq, void *v)
fold_field((void **) udp_statistics,
snmp4_udp_list[i].entry));
+ /* the UDP and UDP-Lite MIBs are the same */
+ seq_puts(seq, "\nUdpLite:");
+ for (i = 0; snmp4_udp_list[i].name != NULL; i++)
+ seq_printf(seq, " %s", snmp4_udp_list[i].name);
+
+ seq_puts(seq, "\nUdpLite:");
+ for (i = 0; snmp4_udp_list[i].name != NULL; i++)
+ seq_printf(seq, " %lu",
+ fold_field((void **) udplite_statistics,
+ snmp4_udp_list[i].entry) );
+
seq_putc(seq, '\n');
return 0;
}
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 5c31dead2bdc..a6c63bbd9ddb 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -854,8 +854,8 @@ static void raw_seq_stop(struct seq_file *seq, void *v)
static __inline__ char *get_raw_sock(struct sock *sp, char *tmpbuf, int i)
{
struct inet_sock *inet = inet_sk(sp);
- unsigned int dest = inet->daddr,
- src = inet->rcv_saddr;
+ __be32 dest = inet->daddr,
+ src = inet->rcv_saddr;
__u16 destp = 0,
srcp = inet->num;
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 925ee4dfc32c..9f3924c4905e 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -566,11 +566,9 @@ static inline u32 rt_score(struct rtable *rt)
static inline int compare_keys(struct flowi *fl1, struct flowi *fl2)
{
- return ((fl1->nl_u.ip4_u.daddr ^ fl2->nl_u.ip4_u.daddr) |
- (fl1->nl_u.ip4_u.saddr ^ fl2->nl_u.ip4_u.saddr) |
-#ifdef CONFIG_IP_ROUTE_FWMARK
- (fl1->nl_u.ip4_u.fwmark ^ fl2->nl_u.ip4_u.fwmark) |
-#endif
+ return ((__force u32)((fl1->nl_u.ip4_u.daddr ^ fl2->nl_u.ip4_u.daddr) |
+ (fl1->nl_u.ip4_u.saddr ^ fl2->nl_u.ip4_u.saddr)) |
+ (fl1->mark ^ fl2->mark) |
(*(u16 *)&fl1->nl_u.ip4_u.tos ^
*(u16 *)&fl2->nl_u.ip4_u.tos) |
(fl1->oif ^ fl2->oif) |
@@ -1643,9 +1641,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
rth->fl.fl4_dst = daddr;
rth->rt_dst = daddr;
rth->fl.fl4_tos = tos;
-#ifdef CONFIG_IP_ROUTE_FWMARK
- rth->fl.fl4_fwmark= skb->nfmark;
-#endif
+ rth->fl.mark = skb->mark;
rth->fl.fl4_src = saddr;
rth->rt_src = saddr;
#ifdef CONFIG_NET_CLS_ROUTE
@@ -1789,9 +1785,7 @@ static inline int __mkroute_input(struct sk_buff *skb,
rth->fl.fl4_dst = daddr;
rth->rt_dst = daddr;
rth->fl.fl4_tos = tos;
-#ifdef CONFIG_IP_ROUTE_FWMARK
- rth->fl.fl4_fwmark= skb->nfmark;
-#endif
+ rth->fl.mark = skb->mark;
rth->fl.fl4_src = saddr;
rth->rt_src = saddr;
rth->rt_gateway = daddr;
@@ -1920,10 +1914,8 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
.saddr = saddr,
.tos = tos,
.scope = RT_SCOPE_UNIVERSE,
-#ifdef CONFIG_IP_ROUTE_FWMARK
- .fwmark = skb->nfmark
-#endif
} },
+ .mark = skb->mark,
.iif = dev->ifindex };
unsigned flags = 0;
u32 itag = 0;
@@ -2034,9 +2026,7 @@ local_input:
rth->fl.fl4_dst = daddr;
rth->rt_dst = daddr;
rth->fl.fl4_tos = tos;
-#ifdef CONFIG_IP_ROUTE_FWMARK
- rth->fl.fl4_fwmark= skb->nfmark;
-#endif
+ rth->fl.mark = skb->mark;
rth->fl.fl4_src = saddr;
rth->rt_src = saddr;
#ifdef CONFIG_NET_CLS_ROUTE
@@ -2113,9 +2103,7 @@ int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr,
rth->fl.fl4_src == saddr &&
rth->fl.iif == iif &&
rth->fl.oif == 0 &&
-#ifdef CONFIG_IP_ROUTE_FWMARK
- rth->fl.fl4_fwmark == skb->nfmark &&
-#endif
+ rth->fl.mark == skb->mark &&
rth->fl.fl4_tos == tos) {
rth->u.dst.lastuse = jiffies;
dst_hold(&rth->u.dst);
@@ -2239,9 +2227,7 @@ static inline int __mkroute_output(struct rtable **result,
rth->fl.fl4_tos = tos;
rth->fl.fl4_src = oldflp->fl4_src;
rth->fl.oif = oldflp->oif;
-#ifdef CONFIG_IP_ROUTE_FWMARK
- rth->fl.fl4_fwmark= oldflp->fl4_fwmark;
-#endif
+ rth->fl.mark = oldflp->mark;
rth->rt_dst = fl->fl4_dst;
rth->rt_src = fl->fl4_src;
rth->rt_iif = oldflp->oif ? : dev_out->ifindex;
@@ -2385,10 +2371,8 @@ static int ip_route_output_slow(struct rtable **rp, const struct flowi *oldflp)
.scope = ((tos & RTO_ONLINK) ?
RT_SCOPE_LINK :
RT_SCOPE_UNIVERSE),
-#ifdef CONFIG_IP_ROUTE_FWMARK
- .fwmark = oldflp->fl4_fwmark
-#endif
} },
+ .mark = oldflp->mark,
.iif = loopback_dev.ifindex,
.oif = oldflp->oif };
struct fib_result res;
@@ -2583,9 +2567,7 @@ int __ip_route_output_key(struct rtable **rp, const struct flowi *flp)
rth->fl.fl4_src == flp->fl4_src &&
rth->fl.iif == 0 &&
rth->fl.oif == flp->oif &&
-#ifdef CONFIG_IP_ROUTE_FWMARK
- rth->fl.fl4_fwmark == flp->fl4_fwmark &&
-#endif
+ rth->fl.mark == flp->mark &&
!((rth->fl.fl4_tos ^ flp->fl4_tos) &
(IPTOS_RT_MASK | RTO_ONLINK))) {
@@ -2647,7 +2629,8 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
struct rtable *rt = (struct rtable*)skb->dst;
struct rtmsg *r;
struct nlmsghdr *nlh;
- struct rta_cacheinfo ci;
+ long expires;
+ u32 id = 0, ts = 0, tsage = 0, error;
nlh = nlmsg_put(skb, pid, seq, event, sizeof(*r), flags);
if (nlh == NULL)
@@ -2694,20 +2677,13 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0)
goto nla_put_failure;
- ci.rta_lastuse = jiffies_to_clock_t(jiffies - rt->u.dst.lastuse);
- ci.rta_used = rt->u.dst.__use;
- ci.rta_clntref = atomic_read(&rt->u.dst.__refcnt);
- if (rt->u.dst.expires)
- ci.rta_expires = jiffies_to_clock_t(rt->u.dst.expires - jiffies);
- else
- ci.rta_expires = 0;
- ci.rta_error = rt->u.dst.error;
- ci.rta_id = ci.rta_ts = ci.rta_tsage = 0;
+ error = rt->u.dst.error;
+ expires = rt->u.dst.expires ? rt->u.dst.expires - jiffies : 0;
if (rt->peer) {
- ci.rta_id = rt->peer->ip_id_count;
+ id = rt->peer->ip_id_count;
if (rt->peer->tcp_ts_stamp) {
- ci.rta_ts = rt->peer->tcp_ts;
- ci.rta_tsage = xtime.tv_sec - rt->peer->tcp_ts_stamp;
+ ts = rt->peer->tcp_ts;
+ tsage = xtime.tv_sec - rt->peer->tcp_ts_stamp;
}
}
@@ -2726,7 +2702,7 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
} else {
if (err == -EMSGSIZE)
goto nla_put_failure;
- ci.rta_error = err;
+ error = err;
}
}
} else
@@ -2734,7 +2710,9 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
NLA_PUT_U32(skb, RTA_IIF, rt->fl.iif);
}
- NLA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci);
+ if (rtnl_put_cacheinfo(skb, &rt->u.dst, id, ts, tsage,
+ expires, error) < 0)
+ goto nla_put_failure;
return nlmsg_end(skb, nlh);
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index 661e0a4bca72..6b19530905af 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -35,23 +35,23 @@ module_init(init_syncookies);
#define COOKIEBITS 24 /* Upper bits store count */
#define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1)
-static u32 cookie_hash(u32 saddr, u32 daddr, u32 sport, u32 dport,
+static u32 cookie_hash(__be32 saddr, __be32 daddr, __be16 sport, __be16 dport,
u32 count, int c)
{
__u32 tmp[16 + 5 + SHA_WORKSPACE_WORDS];
memcpy(tmp + 3, syncookie_secret[c], sizeof(syncookie_secret[c]));
- tmp[0] = saddr;
- tmp[1] = daddr;
- tmp[2] = (sport << 16) + dport;
+ tmp[0] = (__force u32)saddr;
+ tmp[1] = (__force u32)daddr;
+ tmp[2] = ((__force u32)sport << 16) + (__force u32)dport;
tmp[3] = count;
sha_transform(tmp + 16, (__u8 *)tmp, tmp + 16 + 5);
return tmp[17];
}
-static __u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr, __u16 sport,
- __u16 dport, __u32 sseq, __u32 count,
+static __u32 secure_tcp_syn_cookie(__be32 saddr, __be32 daddr, __be16 sport,
+ __be16 dport, __u32 sseq, __u32 count,
__u32 data)
{
/*
@@ -80,8 +80,8 @@ static __u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr, __u16 sport,
* "maxdiff" if the current (passed-in) "count". The return value
* is (__u32)-1 if this test fails.
*/
-static __u32 check_tcp_syn_cookie(__u32 cookie, __u32 saddr, __u32 daddr,
- __u16 sport, __u16 dport, __u32 sseq,
+static __u32 check_tcp_syn_cookie(__u32 cookie, __be32 saddr, __be32 daddr,
+ __be16 sport, __be16 dport, __u32 sseq,
__u32 count, __u32 maxdiff)
{
__u32 diff;
@@ -220,7 +220,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
}
ireq = inet_rsk(req);
treq = tcp_rsk(req);
- treq->rcv_isn = htonl(skb->h.th->seq) - 1;
+ treq->rcv_isn = ntohl(skb->h.th->seq) - 1;
treq->snt_isn = cookie;
req->mss = mss;
ireq->rmt_port = skb->h.th->source;
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 15061b314411..dfcf47f10f88 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -129,6 +129,67 @@ static int sysctl_tcp_congestion_control(ctl_table *table, int __user *name,
return ret;
}
+static int proc_tcp_available_congestion_control(ctl_table *ctl,
+ int write, struct file * filp,
+ void __user *buffer, size_t *lenp,
+ loff_t *ppos)
+{
+ ctl_table tbl = { .maxlen = TCP_CA_BUF_MAX, };
+ int ret;
+
+ tbl.data = kmalloc(tbl.maxlen, GFP_USER);
+ if (!tbl.data)
+ return -ENOMEM;
+ tcp_get_available_congestion_control(tbl.data, TCP_CA_BUF_MAX);
+ ret = proc_dostring(&tbl, write, filp, buffer, lenp, ppos);
+ kfree(tbl.data);
+ return ret;
+}
+
+static int proc_allowed_congestion_control(ctl_table *ctl,
+ int write, struct file * filp,
+ void __user *buffer, size_t *lenp,
+ loff_t *ppos)
+{
+ ctl_table tbl = { .maxlen = TCP_CA_BUF_MAX };
+ int ret;
+
+ tbl.data = kmalloc(tbl.maxlen, GFP_USER);
+ if (!tbl.data)
+ return -ENOMEM;
+
+ tcp_get_allowed_congestion_control(tbl.data, tbl.maxlen);
+ ret = proc_dostring(&tbl, write, filp, buffer, lenp, ppos);
+ if (write && ret == 0)
+ ret = tcp_set_allowed_congestion_control(tbl.data);
+ kfree(tbl.data);
+ return ret;
+}
+
+static int strategy_allowed_congestion_control(ctl_table *table, int __user *name,
+ int nlen, void __user *oldval,
+ size_t __user *oldlenp,
+ void __user *newval, size_t newlen,
+ void **context)
+{
+ ctl_table tbl = { .maxlen = TCP_CA_BUF_MAX };
+ int ret;
+
+ tbl.data = kmalloc(tbl.maxlen, GFP_USER);
+ if (!tbl.data)
+ return -ENOMEM;
+
+ tcp_get_available_congestion_control(tbl.data, tbl.maxlen);
+ ret = sysctl_string(&tbl, name, nlen, oldval, oldlenp, newval, newlen,
+ context);
+ if (ret == 0 && newval && newlen)
+ ret = tcp_set_allowed_congestion_control(tbl.data);
+ kfree(tbl.data);
+
+ return ret;
+
+}
+
ctl_table ipv4_table[] = {
{
.ctl_name = NET_IPV4_TCP_TIMESTAMPS,
@@ -731,6 +792,21 @@ ctl_table ipv4_table[] = {
.proc_handler = &proc_dointvec,
},
#endif /* CONFIG_NETLABEL */
+ {
+ .ctl_name = NET_TCP_AVAIL_CONG_CONTROL,
+ .procname = "tcp_available_congestion_control",
+ .maxlen = TCP_CA_BUF_MAX,
+ .mode = 0444,
+ .proc_handler = &proc_tcp_available_congestion_control,
+ },
+ {
+ .ctl_name = NET_TCP_ALLOWED_CONG_CONTROL,
+ .procname = "tcp_allowed_congestion_control",
+ .maxlen = TCP_CA_BUF_MAX,
+ .mode = 0644,
+ .proc_handler = &proc_allowed_congestion_control,
+ .strategy = &strategy_allowed_congestion_control,
+ },
{ .ctl_name = 0 }
};
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index c05e8edaf544..090c690627e5 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -258,6 +258,7 @@
#include <linux/bootmem.h>
#include <linux/cache.h>
#include <linux/err.h>
+#include <linux/crypto.h>
#include <net/icmp.h>
#include <net/tcp.h>
@@ -462,11 +463,12 @@ static inline int forced_push(struct tcp_sock *tp)
static inline void skb_entail(struct sock *sk, struct tcp_sock *tp,
struct sk_buff *skb)
{
- skb->csum = 0;
- TCP_SKB_CB(skb)->seq = tp->write_seq;
- TCP_SKB_CB(skb)->end_seq = tp->write_seq;
- TCP_SKB_CB(skb)->flags = TCPCB_FLAG_ACK;
- TCP_SKB_CB(skb)->sacked = 0;
+ struct tcp_skb_cb *tcb = TCP_SKB_CB(skb);
+
+ skb->csum = 0;
+ tcb->seq = tcb->end_seq = tp->write_seq;
+ tcb->flags = TCPCB_FLAG_ACK;
+ tcb->sacked = 0;
skb_header_release(skb);
__skb_queue_tail(&sk->sk_write_queue, skb);
sk_charge_skb(sk, skb);
@@ -1942,6 +1944,13 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
}
break;
+#ifdef CONFIG_TCP_MD5SIG
+ case TCP_MD5SIG:
+ /* Read the IP->Key mappings from userspace */
+ err = tp->af_specific->md5_parse(sk, optval, optlen);
+ break;
+#endif
+
default:
err = -ENOPROTOOPT;
break;
@@ -2154,7 +2163,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features)
struct tcphdr *th;
unsigned thlen;
unsigned int seq;
- unsigned int delta;
+ __be32 delta;
unsigned int oldlen;
unsigned int len;
@@ -2207,7 +2216,8 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features)
do {
th->fin = th->psh = 0;
- th->check = ~csum_fold(th->check + delta);
+ th->check = ~csum_fold((__force __wsum)((__force u32)th->check +
+ (__force u32)delta));
if (skb->ip_summed != CHECKSUM_PARTIAL)
th->check = csum_fold(csum_partial(skb->h.raw, thlen,
skb->csum));
@@ -2221,7 +2231,8 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features)
} while (skb->next);
delta = htonl(oldlen + (skb->tail - skb->h.raw) + skb->data_len);
- th->check = ~csum_fold(th->check + delta);
+ th->check = ~csum_fold((__force __wsum)((__force u32)th->check +
+ (__force u32)delta));
if (skb->ip_summed != CHECKSUM_PARTIAL)
th->check = csum_fold(csum_partial(skb->h.raw, thlen,
skb->csum));
@@ -2231,6 +2242,135 @@ out:
}
EXPORT_SYMBOL(tcp_tso_segment);
+#ifdef CONFIG_TCP_MD5SIG
+static unsigned long tcp_md5sig_users;
+static struct tcp_md5sig_pool **tcp_md5sig_pool;
+static DEFINE_SPINLOCK(tcp_md5sig_pool_lock);
+
+static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool **pool)
+{
+ int cpu;
+ for_each_possible_cpu(cpu) {
+ struct tcp_md5sig_pool *p = *per_cpu_ptr(pool, cpu);
+ if (p) {
+ if (p->md5_desc.tfm)
+ crypto_free_hash(p->md5_desc.tfm);
+ kfree(p);
+ p = NULL;
+ }
+ }
+ free_percpu(pool);
+}
+
+void tcp_free_md5sig_pool(void)
+{
+ struct tcp_md5sig_pool **pool = NULL;
+
+ spin_lock(&tcp_md5sig_pool_lock);
+ if (--tcp_md5sig_users == 0) {
+ pool = tcp_md5sig_pool;
+ tcp_md5sig_pool = NULL;
+ }
+ spin_unlock(&tcp_md5sig_pool_lock);
+ if (pool)
+ __tcp_free_md5sig_pool(pool);
+}
+
+EXPORT_SYMBOL(tcp_free_md5sig_pool);
+
+static struct tcp_md5sig_pool **__tcp_alloc_md5sig_pool(void)
+{
+ int cpu;
+ struct tcp_md5sig_pool **pool;
+
+ pool = alloc_percpu(struct tcp_md5sig_pool *);
+ if (!pool)
+ return NULL;
+
+ for_each_possible_cpu(cpu) {
+ struct tcp_md5sig_pool *p;
+ struct crypto_hash *hash;
+
+ p = kzalloc(sizeof(*p), GFP_KERNEL);
+ if (!p)
+ goto out_free;
+ *per_cpu_ptr(pool, cpu) = p;
+
+ hash = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC);
+ if (!hash || IS_ERR(hash))
+ goto out_free;
+
+ p->md5_desc.tfm = hash;
+ }
+ return pool;
+out_free:
+ __tcp_free_md5sig_pool(pool);
+ return NULL;
+}
+
+struct tcp_md5sig_pool **tcp_alloc_md5sig_pool(void)
+{
+ struct tcp_md5sig_pool **pool;
+ int alloc = 0;
+
+retry:
+ spin_lock(&tcp_md5sig_pool_lock);
+ pool = tcp_md5sig_pool;
+ if (tcp_md5sig_users++ == 0) {
+ alloc = 1;
+ spin_unlock(&tcp_md5sig_pool_lock);
+ } else if (!pool) {
+ tcp_md5sig_users--;
+ spin_unlock(&tcp_md5sig_pool_lock);
+ cpu_relax();
+ goto retry;
+ } else
+ spin_unlock(&tcp_md5sig_pool_lock);
+
+ if (alloc) {
+ /* we cannot hold spinlock here because this may sleep. */
+ struct tcp_md5sig_pool **p = __tcp_alloc_md5sig_pool();
+ spin_lock(&tcp_md5sig_pool_lock);
+ if (!p) {
+ tcp_md5sig_users--;
+ spin_unlock(&tcp_md5sig_pool_lock);
+ return NULL;
+ }
+ pool = tcp_md5sig_pool;
+ if (pool) {
+ /* oops, it has already been assigned. */
+ spin_unlock(&tcp_md5sig_pool_lock);
+ __tcp_free_md5sig_pool(p);
+ } else {
+ tcp_md5sig_pool = pool = p;
+ spin_unlock(&tcp_md5sig_pool_lock);
+ }
+ }
+ return pool;
+}
+
+EXPORT_SYMBOL(tcp_alloc_md5sig_pool);
+
+struct tcp_md5sig_pool *__tcp_get_md5sig_pool(int cpu)
+{
+ struct tcp_md5sig_pool **p;
+ spin_lock(&tcp_md5sig_pool_lock);
+ p = tcp_md5sig_pool;
+ if (p)
+ tcp_md5sig_users++;
+ spin_unlock(&tcp_md5sig_pool_lock);
+ return (p ? *per_cpu_ptr(p, cpu) : NULL);
+}
+
+EXPORT_SYMBOL(__tcp_get_md5sig_pool);
+
+void __tcp_put_md5sig_pool(void) {
+ __tcp_free_md5sig_pool(tcp_md5sig_pool);
+}
+
+EXPORT_SYMBOL(__tcp_put_md5sig_pool);
+#endif
+
extern void __skb_cb_too_small_for_tcp(int, int);
extern struct tcp_congestion_ops tcp_reno;
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c
index 1e2982f4acd4..5ca7723d0798 100644
--- a/net/ipv4/tcp_cong.c
+++ b/net/ipv4/tcp_cong.c
@@ -113,7 +113,7 @@ int tcp_set_default_congestion_control(const char *name)
spin_lock(&tcp_cong_list_lock);
ca = tcp_ca_find(name);
#ifdef CONFIG_KMOD
- if (!ca) {
+ if (!ca && capable(CAP_SYS_MODULE)) {
spin_unlock(&tcp_cong_list_lock);
request_module("tcp_%s", name);
@@ -123,6 +123,7 @@ int tcp_set_default_congestion_control(const char *name)
#endif
if (ca) {
+ ca->non_restricted = 1; /* default is always allowed */
list_move(&ca->list, &tcp_cong_list);
ret = 0;
}
@@ -139,6 +140,22 @@ static int __init tcp_congestion_default(void)
late_initcall(tcp_congestion_default);
+/* Build string with list of available congestion control values */
+void tcp_get_available_congestion_control(char *buf, size_t maxlen)
+{
+ struct tcp_congestion_ops *ca;
+ size_t offs = 0;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(ca, &tcp_cong_list, list) {
+ offs += snprintf(buf + offs, maxlen - offs,
+ "%s%s",
+ offs == 0 ? "" : " ", ca->name);
+
+ }
+ rcu_read_unlock();
+}
+
/* Get current default congestion control */
void tcp_get_default_congestion_control(char *name)
{
@@ -152,6 +169,64 @@ void tcp_get_default_congestion_control(char *name)
rcu_read_unlock();
}
+/* Built list of non-restricted congestion control values */
+void tcp_get_allowed_congestion_control(char *buf, size_t maxlen)
+{
+ struct tcp_congestion_ops *ca;
+ size_t offs = 0;
+
+ *buf = '\0';
+ rcu_read_lock();
+ list_for_each_entry_rcu(ca, &tcp_cong_list, list) {
+ if (!ca->non_restricted)
+ continue;
+ offs += snprintf(buf + offs, maxlen - offs,
+ "%s%s",
+ offs == 0 ? "" : " ", ca->name);
+
+ }
+ rcu_read_unlock();
+}
+
+/* Change list of non-restricted congestion control */
+int tcp_set_allowed_congestion_control(char *val)
+{
+ struct tcp_congestion_ops *ca;
+ char *clone, *name;
+ int ret = 0;
+
+ clone = kstrdup(val, GFP_USER);
+ if (!clone)
+ return -ENOMEM;
+
+ spin_lock(&tcp_cong_list_lock);
+ /* pass 1 check for bad entries */
+ while ((name = strsep(&clone, " ")) && *name) {
+ ca = tcp_ca_find(name);
+ if (!ca) {
+ ret = -ENOENT;
+ goto out;
+ }
+ }
+
+ /* pass 2 clear */
+ list_for_each_entry_rcu(ca, &tcp_cong_list, list)
+ ca->non_restricted = 0;
+
+ /* pass 3 mark as allowed */
+ while ((name = strsep(&val, " ")) && *name) {
+ ca = tcp_ca_find(name);
+ WARN_ON(!ca);
+ if (ca)
+ ca->non_restricted = 1;
+ }
+out:
+ spin_unlock(&tcp_cong_list_lock);
+
+ return ret;
+}
+
+
/* Change congestion control for socket */
int tcp_set_congestion_control(struct sock *sk, const char *name)
{
@@ -161,12 +236,25 @@ int tcp_set_congestion_control(struct sock *sk, const char *name)
rcu_read_lock();
ca = tcp_ca_find(name);
+ /* no change asking for existing value */
if (ca == icsk->icsk_ca_ops)
goto out;
+#ifdef CONFIG_KMOD
+ /* not found attempt to autoload module */
+ if (!ca && capable(CAP_SYS_MODULE)) {
+ rcu_read_unlock();
+ request_module("tcp_%s", name);
+ rcu_read_lock();
+ ca = tcp_ca_find(name);
+ }
+#endif
if (!ca)
err = -ENOENT;
+ else if (!(ca->non_restricted || capable(CAP_NET_ADMIN)))
+ err = -EPERM;
+
else if (!try_module_get(ca->owner))
err = -EBUSY;
@@ -268,6 +356,7 @@ EXPORT_SYMBOL_GPL(tcp_reno_min_cwnd);
struct tcp_congestion_ops tcp_reno = {
.name = "reno",
+ .non_restricted = 1,
.owner = THIS_MODULE,
.ssthresh = tcp_reno_ssthresh,
.cong_avoid = tcp_reno_cong_avoid,
diff --git a/net/ipv4/tcp_htcp.c b/net/ipv4/tcp_htcp.c
index 283be3cb4667..753987a1048f 100644
--- a/net/ipv4/tcp_htcp.c
+++ b/net/ipv4/tcp_htcp.c
@@ -26,12 +26,12 @@ struct htcp {
u32 alpha; /* Fixed point arith, << 7 */
u8 beta; /* Fixed point arith, << 7 */
u8 modeswitch; /* Delay modeswitch until we had at least one congestion event */
- u32 last_cong; /* Time since last congestion event end */
- u32 undo_last_cong;
u16 pkts_acked;
u32 packetcount;
u32 minRTT;
u32 maxRTT;
+ u32 last_cong; /* Time since last congestion event end */
+ u32 undo_last_cong;
u32 undo_maxRTT;
u32 undo_old_maxB;
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index cf06accbe687..9304034c0c47 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -2677,6 +2677,14 @@ void tcp_parse_options(struct sk_buff *skb, struct tcp_options_received *opt_rx,
opt_rx->sack_ok) {
TCP_SKB_CB(skb)->sacked = (ptr - 2) - (unsigned char *)th;
}
+#ifdef CONFIG_TCP_MD5SIG
+ case TCPOPT_MD5SIG:
+ /*
+ * The MD5 Hash has already been
+ * checked (see tcp_v{4,6}_do_rcv()).
+ */
+ break;
+#endif
};
ptr+=opsize-2;
length-=opsize;
@@ -3782,9 +3790,9 @@ static int tcp_copy_to_iovec(struct sock *sk, struct sk_buff *skb, int hlen)
return err;
}
-static int __tcp_checksum_complete_user(struct sock *sk, struct sk_buff *skb)
+static __sum16 __tcp_checksum_complete_user(struct sock *sk, struct sk_buff *skb)
{
- int result;
+ __sum16 result;
if (sock_owned_by_user(sk)) {
local_bh_enable();
@@ -4230,6 +4238,8 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
mb();
tcp_set_state(sk, TCP_ESTABLISHED);
+ security_inet_conn_established(sk, skb);
+
/* Make sure socket is routed, for correct metrics. */
icsk->icsk_af_ops->rebuild_header(sk);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 22ef8bd26620..a1222d6968c4 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -78,6 +78,9 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <linux/crypto.h>
+#include <linux/scatterlist.h>
+
int sysctl_tcp_tw_reuse __read_mostly;
int sysctl_tcp_low_latency __read_mostly;
@@ -89,10 +92,19 @@ static struct socket *tcp_socket;
void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb);
+#ifdef CONFIG_TCP_MD5SIG
+static struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk,
+ __be32 addr);
+static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
+ __be32 saddr, __be32 daddr,
+ struct tcphdr *th, int protocol,
+ int tcplen);
+#endif
+
struct inet_hashinfo __cacheline_aligned tcp_hashinfo = {
- .lhash_lock = __RW_LOCK_UNLOCKED(tcp_hashinfo.lhash_lock),
- .lhash_users = ATOMIC_INIT(0),
- .lhash_wait = __WAIT_QUEUE_HEAD_INITIALIZER(tcp_hashinfo.lhash_wait),
+ .lhash_lock = __RW_LOCK_UNLOCKED(tcp_hashinfo.lhash_lock),
+ .lhash_users = ATOMIC_INIT(0),
+ .lhash_wait = __WAIT_QUEUE_HEAD_INITIALIZER(tcp_hashinfo.lhash_wait),
};
static int tcp_v4_get_port(struct sock *sk, unsigned short snum)
@@ -111,7 +123,7 @@ void tcp_unhash(struct sock *sk)
inet_unhash(&tcp_hashinfo, sk);
}
-static inline __u32 tcp_v4_init_sequence(struct sock *sk, struct sk_buff *skb)
+static inline __u32 tcp_v4_init_sequence(struct sk_buff *skb)
{
return secure_tcp_sequence_number(skb->nh.iph->daddr,
skb->nh.iph->saddr,
@@ -205,13 +217,14 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
if (tcp_death_row.sysctl_tw_recycle &&
!tp->rx_opt.ts_recent_stamp && rt->rt_dst == daddr) {
struct inet_peer *peer = rt_get_peer(rt);
-
- /* VJ's idea. We save last timestamp seen from
- * the destination in peer table, when entering state TIME-WAIT
- * and initialize rx_opt.ts_recent from it, when trying new connection.
+ /*
+ * VJ's idea. We save last timestamp seen from
+ * the destination in peer table, when entering state
+ * TIME-WAIT * and initialize rx_opt.ts_recent from it,
+ * when trying new connection.
*/
-
- if (peer && peer->tcp_ts_stamp + TCP_PAWS_MSL >= xtime.tv_sec) {
+ if (peer != NULL &&
+ peer->tcp_ts_stamp + TCP_PAWS_MSL >= xtime.tv_sec) {
tp->rx_opt.ts_recent_stamp = peer->tcp_ts_stamp;
tp->rx_opt.ts_recent = peer->tcp_ts;
}
@@ -236,7 +249,8 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
if (err)
goto failure;
- err = ip_route_newports(&rt, IPPROTO_TCP, inet->sport, inet->dport, sk);
+ err = ip_route_newports(&rt, IPPROTO_TCP,
+ inet->sport, inet->dport, sk);
if (err)
goto failure;
@@ -260,7 +274,10 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
return 0;
failure:
- /* This unhashes the socket and releases the local port, if necessary. */
+ /*
+ * This unhashes the socket and releases the local port,
+ * if necessary.
+ */
tcp_set_state(sk, TCP_CLOSE);
ip_rt_put(rt);
sk->sk_route_caps = 0;
@@ -485,8 +502,9 @@ void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb)
struct tcphdr *th = skb->h.th;
if (skb->ip_summed == CHECKSUM_PARTIAL) {
- th->check = ~tcp_v4_check(th, len, inet->saddr, inet->daddr, 0);
- skb->csum = offsetof(struct tcphdr, check);
+ th->check = ~tcp_v4_check(th, len,
+ inet->saddr, inet->daddr, 0);
+ skb->csum_offset = offsetof(struct tcphdr, check);
} else {
th->check = tcp_v4_check(th, len, inet->saddr, inet->daddr,
csum_partial((char *)th,
@@ -508,7 +526,7 @@ int tcp_v4_gso_send_check(struct sk_buff *skb)
th->check = 0;
th->check = ~tcp_v4_check(th, skb->len, iph->saddr, iph->daddr, 0);
- skb->csum = offsetof(struct tcphdr, check);
+ skb->csum_offset = offsetof(struct tcphdr, check);
skb->ip_summed = CHECKSUM_PARTIAL;
return 0;
}
@@ -526,11 +544,19 @@ int tcp_v4_gso_send_check(struct sk_buff *skb)
* Exception: precedence violation. We do not implement it in any case.
*/
-static void tcp_v4_send_reset(struct sk_buff *skb)
+static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
{
struct tcphdr *th = skb->h.th;
- struct tcphdr rth;
+ struct {
+ struct tcphdr th;
+#ifdef CONFIG_TCP_MD5SIG
+ __be32 opt[(TCPOLEN_MD5SIG_ALIGNED >> 2)];
+#endif
+ } rep;
struct ip_reply_arg arg;
+#ifdef CONFIG_TCP_MD5SIG
+ struct tcp_md5sig_key *key;
+#endif
/* Never send a reset in response to a reset. */
if (th->rst)
@@ -540,29 +566,49 @@ static void tcp_v4_send_reset(struct sk_buff *skb)
return;
/* Swap the send and the receive. */
- memset(&rth, 0, sizeof(struct tcphdr));
- rth.dest = th->source;
- rth.source = th->dest;
- rth.doff = sizeof(struct tcphdr) / 4;
- rth.rst = 1;
+ memset(&rep, 0, sizeof(rep));
+ rep.th.dest = th->source;
+ rep.th.source = th->dest;
+ rep.th.doff = sizeof(struct tcphdr) / 4;
+ rep.th.rst = 1;
if (th->ack) {
- rth.seq = th->ack_seq;
+ rep.th.seq = th->ack_seq;
} else {
- rth.ack = 1;
- rth.ack_seq = htonl(ntohl(th->seq) + th->syn + th->fin +
- skb->len - (th->doff << 2));
+ rep.th.ack = 1;
+ rep.th.ack_seq = htonl(ntohl(th->seq) + th->syn + th->fin +
+ skb->len - (th->doff << 2));
}
- memset(&arg, 0, sizeof arg);
- arg.iov[0].iov_base = (unsigned char *)&rth;
- arg.iov[0].iov_len = sizeof rth;
+ memset(&arg, 0, sizeof(arg));
+ arg.iov[0].iov_base = (unsigned char *)&rep;
+ arg.iov[0].iov_len = sizeof(rep.th);
+
+#ifdef CONFIG_TCP_MD5SIG
+ key = sk ? tcp_v4_md5_do_lookup(sk, skb->nh.iph->daddr) : NULL;
+ if (key) {
+ rep.opt[0] = htonl((TCPOPT_NOP << 24) |
+ (TCPOPT_NOP << 16) |
+ (TCPOPT_MD5SIG << 8) |
+ TCPOLEN_MD5SIG);
+ /* Update length and the length the header thinks exists */
+ arg.iov[0].iov_len += TCPOLEN_MD5SIG_ALIGNED;
+ rep.th.doff = arg.iov[0].iov_len / 4;
+
+ tcp_v4_do_calc_md5_hash((__u8 *)&rep.opt[1],
+ key,
+ skb->nh.iph->daddr,
+ skb->nh.iph->saddr,
+ &rep.th, IPPROTO_TCP,
+ arg.iov[0].iov_len);
+ }
+#endif
arg.csum = csum_tcpudp_nofold(skb->nh.iph->daddr,
- skb->nh.iph->saddr, /*XXX*/
+ skb->nh.iph->saddr, /* XXX */
sizeof(struct tcphdr), IPPROTO_TCP, 0);
arg.csumoffset = offsetof(struct tcphdr, check) / 2;
- ip_send_reply(tcp_socket->sk, skb, &arg, sizeof rth);
+ ip_send_reply(tcp_socket->sk, skb, &arg, arg.iov[0].iov_len);
TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
TCP_INC_STATS_BH(TCP_MIB_OUTRSTS);
@@ -572,28 +618,37 @@ static void tcp_v4_send_reset(struct sk_buff *skb)
outside socket context is ugly, certainly. What can I do?
*/
-static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
+static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk,
+ struct sk_buff *skb, u32 seq, u32 ack,
u32 win, u32 ts)
{
struct tcphdr *th = skb->h.th;
struct {
struct tcphdr th;
- u32 tsopt[TCPOLEN_TSTAMP_ALIGNED >> 2];
+ __be32 opt[(TCPOLEN_TSTAMP_ALIGNED >> 2)
+#ifdef CONFIG_TCP_MD5SIG
+ + (TCPOLEN_MD5SIG_ALIGNED >> 2)
+#endif
+ ];
} rep;
struct ip_reply_arg arg;
+#ifdef CONFIG_TCP_MD5SIG
+ struct tcp_md5sig_key *key;
+ struct tcp_md5sig_key tw_key;
+#endif
memset(&rep.th, 0, sizeof(struct tcphdr));
- memset(&arg, 0, sizeof arg);
+ memset(&arg, 0, sizeof(arg));
arg.iov[0].iov_base = (unsigned char *)&rep;
arg.iov[0].iov_len = sizeof(rep.th);
if (ts) {
- rep.tsopt[0] = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
- (TCPOPT_TIMESTAMP << 8) |
- TCPOLEN_TIMESTAMP);
- rep.tsopt[1] = htonl(tcp_time_stamp);
- rep.tsopt[2] = htonl(ts);
- arg.iov[0].iov_len = sizeof(rep);
+ rep.opt[0] = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
+ (TCPOPT_TIMESTAMP << 8) |
+ TCPOLEN_TIMESTAMP);
+ rep.opt[1] = htonl(tcp_time_stamp);
+ rep.opt[2] = htonl(ts);
+ arg.iov[0].iov_len = TCPOLEN_TSTAMP_ALIGNED;
}
/* Swap the send and the receive. */
@@ -605,8 +660,44 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
rep.th.ack = 1;
rep.th.window = htons(win);
+#ifdef CONFIG_TCP_MD5SIG
+ /*
+ * The SKB holds an imcoming packet, but may not have a valid ->sk
+ * pointer. This is especially the case when we're dealing with a
+ * TIME_WAIT ack, because the sk structure is long gone, and only
+ * the tcp_timewait_sock remains. So the md5 key is stashed in that
+ * structure, and we use it in preference. I believe that (twsk ||
+ * skb->sk) holds true, but we program defensively.
+ */
+ if (!twsk && skb->sk) {
+ key = tcp_v4_md5_do_lookup(skb->sk, skb->nh.iph->daddr);
+ } else if (twsk && twsk->tw_md5_keylen) {
+ tw_key.key = twsk->tw_md5_key;
+ tw_key.keylen = twsk->tw_md5_keylen;
+ key = &tw_key;
+ } else
+ key = NULL;
+
+ if (key) {
+ int offset = (ts) ? 3 : 0;
+
+ rep.opt[offset++] = htonl((TCPOPT_NOP << 24) |
+ (TCPOPT_NOP << 16) |
+ (TCPOPT_MD5SIG << 8) |
+ TCPOLEN_MD5SIG);
+ arg.iov[0].iov_len += TCPOLEN_MD5SIG_ALIGNED;
+ rep.th.doff = arg.iov[0].iov_len/4;
+
+ tcp_v4_do_calc_md5_hash((__u8 *)&rep.opt[offset],
+ key,
+ skb->nh.iph->daddr,
+ skb->nh.iph->saddr,
+ &rep.th, IPPROTO_TCP,
+ arg.iov[0].iov_len);
+ }
+#endif
arg.csum = csum_tcpudp_nofold(skb->nh.iph->daddr,
- skb->nh.iph->saddr, /*XXX*/
+ skb->nh.iph->saddr, /* XXX */
arg.iov[0].iov_len, IPPROTO_TCP, 0);
arg.csumoffset = offsetof(struct tcphdr, check) / 2;
@@ -618,17 +709,20 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb)
{
struct inet_timewait_sock *tw = inet_twsk(sk);
- const struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
+ struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
- tcp_v4_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
- tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, tcptw->tw_ts_recent);
+ tcp_v4_send_ack(tcptw, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
+ tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
+ tcptw->tw_ts_recent);
inet_twsk_put(tw);
}
-static void tcp_v4_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req)
+static void tcp_v4_reqsk_send_ack(struct sk_buff *skb,
+ struct request_sock *req)
{
- tcp_v4_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd,
+ tcp_v4_send_ack(NULL, skb, tcp_rsk(req)->snt_isn + 1,
+ tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd,
req->ts_recent);
}
@@ -662,8 +756,7 @@ static int tcp_v4_send_synack(struct sock *sk, struct request_sock *req,
err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr,
ireq->rmt_addr,
ireq->opt);
- if (err == NET_XMIT_CN)
- err = 0;
+ err = net_xmit_eval(err);
}
out:
@@ -715,7 +808,423 @@ static struct ip_options *tcp_v4_save_options(struct sock *sk,
return dopt;
}
-struct request_sock_ops tcp_request_sock_ops = {
+#ifdef CONFIG_TCP_MD5SIG
+/*
+ * RFC2385 MD5 checksumming requires a mapping of
+ * IP address->MD5 Key.
+ * We need to maintain these in the sk structure.
+ */
+
+/* Find the Key structure for an address. */
+static struct tcp_md5sig_key *
+ tcp_v4_md5_do_lookup(struct sock *sk, __be32 addr)
+{
+ struct tcp_sock *tp = tcp_sk(sk);
+ int i;
+
+ if (!tp->md5sig_info || !tp->md5sig_info->entries4)
+ return NULL;
+ for (i = 0; i < tp->md5sig_info->entries4; i++) {
+ if (tp->md5sig_info->keys4[i].addr == addr)
+ return (struct tcp_md5sig_key *)
+ &tp->md5sig_info->keys4[i];
+ }
+ return NULL;
+}
+
+struct tcp_md5sig_key *tcp_v4_md5_lookup(struct sock *sk,
+ struct sock *addr_sk)
+{
+ return tcp_v4_md5_do_lookup(sk, inet_sk(addr_sk)->daddr);
+}
+
+EXPORT_SYMBOL(tcp_v4_md5_lookup);
+
+static struct tcp_md5sig_key *tcp_v4_reqsk_md5_lookup(struct sock *sk,
+ struct request_sock *req)
+{
+ return tcp_v4_md5_do_lookup(sk, inet_rsk(req)->rmt_addr);
+}
+
+/* This can be called on a newly created socket, from other files */
+int tcp_v4_md5_do_add(struct sock *sk, __be32 addr,
+ u8 *newkey, u8 newkeylen)
+{
+ /* Add Key to the list */
+ struct tcp4_md5sig_key *key;
+ struct tcp_sock *tp = tcp_sk(sk);
+ struct tcp4_md5sig_key *keys;
+
+ key = (struct tcp4_md5sig_key *)tcp_v4_md5_do_lookup(sk, addr);
+ if (key) {
+ /* Pre-existing entry - just update that one. */
+ kfree(key->key);
+ key->key = newkey;
+ key->keylen = newkeylen;
+ } else {
+ struct tcp_md5sig_info *md5sig;
+
+ if (!tp->md5sig_info) {
+ tp->md5sig_info = kzalloc(sizeof(*tp->md5sig_info),
+ GFP_ATOMIC);
+ if (!tp->md5sig_info) {
+ kfree(newkey);
+ return -ENOMEM;
+ }
+ }
+ if (tcp_alloc_md5sig_pool() == NULL) {
+ kfree(newkey);
+ return -ENOMEM;
+ }
+ md5sig = tp->md5sig_info;
+
+ if (md5sig->alloced4 == md5sig->entries4) {
+ keys = kmalloc((sizeof(*keys) *
+ (md5sig->entries4 + 1)), GFP_ATOMIC);
+ if (!keys) {
+ kfree(newkey);
+ tcp_free_md5sig_pool();
+ return -ENOMEM;
+ }
+
+ if (md5sig->entries4)
+ memcpy(keys, md5sig->keys4,
+ sizeof(*keys) * md5sig->entries4);
+
+ /* Free old key list, and reference new one */
+ if (md5sig->keys4)
+ kfree(md5sig->keys4);
+ md5sig->keys4 = keys;
+ md5sig->alloced4++;
+ }
+ md5sig->entries4++;
+ md5sig->keys4[md5sig->entries4 - 1].addr = addr;
+ md5sig->keys4[md5sig->entries4 - 1].key = newkey;
+ md5sig->keys4[md5sig->entries4 - 1].keylen = newkeylen;
+ }
+ return 0;
+}
+
+EXPORT_SYMBOL(tcp_v4_md5_do_add);
+
+static int tcp_v4_md5_add_func(struct sock *sk, struct sock *addr_sk,
+ u8 *newkey, u8 newkeylen)
+{
+ return tcp_v4_md5_do_add(sk, inet_sk(addr_sk)->daddr,
+ newkey, newkeylen);
+}
+
+int tcp_v4_md5_do_del(struct sock *sk, __be32 addr)
+{
+ struct tcp_sock *tp = tcp_sk(sk);
+ int i;
+
+ for (i = 0; i < tp->md5sig_info->entries4; i++) {
+ if (tp->md5sig_info->keys4[i].addr == addr) {
+ /* Free the key */
+ kfree(tp->md5sig_info->keys4[i].key);
+ tp->md5sig_info->entries4--;
+
+ if (tp->md5sig_info->entries4 == 0) {
+ kfree(tp->md5sig_info->keys4);
+ tp->md5sig_info->keys4 = NULL;
+ } else if (tp->md5sig_info->entries4 != i) {
+ /* Need to do some manipulation */
+ memcpy(&tp->md5sig_info->keys4[i],
+ &tp->md5sig_info->keys4[i+1],
+ (tp->md5sig_info->entries4 - i) *
+ sizeof(struct tcp4_md5sig_key));
+ }
+ tcp_free_md5sig_pool();
+ return 0;
+ }
+ }
+ return -ENOENT;
+}
+
+EXPORT_SYMBOL(tcp_v4_md5_do_del);
+
+static void tcp_v4_clear_md5_list(struct sock *sk)
+{
+ struct tcp_sock *tp = tcp_sk(sk);
+
+ /* Free each key, then the set of key keys,
+ * the crypto element, and then decrement our
+ * hold on the last resort crypto.
+ */
+ if (tp->md5sig_info->entries4) {
+ int i;
+ for (i = 0; i < tp->md5sig_info->entries4; i++)
+ kfree(tp->md5sig_info->keys4[i].key);
+ tp->md5sig_info->entries4 = 0;
+ tcp_free_md5sig_pool();
+ }
+ if (tp->md5sig_info->keys4) {
+ kfree(tp->md5sig_info->keys4);
+ tp->md5sig_info->keys4 = NULL;
+ tp->md5sig_info->alloced4 = 0;
+ }
+}
+
+static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval,
+ int optlen)
+{
+ struct tcp_md5sig cmd;
+ struct sockaddr_in *sin = (struct sockaddr_in *)&cmd.tcpm_addr;
+ u8 *newkey;
+
+ if (optlen < sizeof(cmd))
+ return -EINVAL;
+
+ if (copy_from_user(&cmd, optval, sizeof(cmd)))
+ return -EFAULT;
+
+ if (sin->sin_family != AF_INET)
+ return -EINVAL;
+
+ if (!cmd.tcpm_key || !cmd.tcpm_keylen) {
+ if (!tcp_sk(sk)->md5sig_info)
+ return -ENOENT;
+ return tcp_v4_md5_do_del(sk, sin->sin_addr.s_addr);
+ }
+
+ if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN)
+ return -EINVAL;
+
+ if (!tcp_sk(sk)->md5sig_info) {
+ struct tcp_sock *tp = tcp_sk(sk);
+ struct tcp_md5sig_info *p = kzalloc(sizeof(*p), GFP_KERNEL);
+
+ if (!p)
+ return -EINVAL;
+
+ tp->md5sig_info = p;
+
+ }
+
+ newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL);
+ if (!newkey)
+ return -ENOMEM;
+ return tcp_v4_md5_do_add(sk, sin->sin_addr.s_addr,
+ newkey, cmd.tcpm_keylen);
+}
+
+static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
+ __be32 saddr, __be32 daddr,
+ struct tcphdr *th, int protocol,
+ int tcplen)
+{
+ struct scatterlist sg[4];
+ __u16 data_len;
+ int block = 0;
+ __sum16 old_checksum;
+ struct tcp_md5sig_pool *hp;
+ struct tcp4_pseudohdr *bp;
+ struct hash_desc *desc;
+ int err;
+ unsigned int nbytes = 0;
+
+ /*
+ * Okay, so RFC2385 is turned on for this connection,
+ * so we need to generate the MD5 hash for the packet now.
+ */
+
+ hp = tcp_get_md5sig_pool();
+ if (!hp)
+ goto clear_hash_noput;
+
+ bp = &hp->md5_blk.ip4;
+ desc = &hp->md5_desc;
+
+ /*
+ * 1. the TCP pseudo-header (in the order: source IP address,
+ * destination IP address, zero-padded protocol number, and
+ * segment length)
+ */
+ bp->saddr = saddr;
+ bp->daddr = daddr;
+ bp->pad = 0;
+ bp->protocol = protocol;
+ bp->len = htons(tcplen);
+ sg_set_buf(&sg[block++], bp, sizeof(*bp));
+ nbytes += sizeof(*bp);
+
+ /* 2. the TCP header, excluding options, and assuming a
+ * checksum of zero/
+ */
+ old_checksum = th->check;
+ th->check = 0;
+ sg_set_buf(&sg[block++], th, sizeof(struct tcphdr));
+ nbytes += sizeof(struct tcphdr);
+
+ /* 3. the TCP segment data (if any) */
+ data_len = tcplen - (th->doff << 2);
+ if (data_len > 0) {
+ unsigned char *data = (unsigned char *)th + (th->doff << 2);
+ sg_set_buf(&sg[block++], data, data_len);
+ nbytes += data_len;
+ }
+
+ /* 4. an independently-specified key or password, known to both
+ * TCPs and presumably connection-specific
+ */
+ sg_set_buf(&sg[block++], key->key, key->keylen);
+ nbytes += key->keylen;
+
+ /* Now store the Hash into the packet */
+ err = crypto_hash_init(desc);
+ if (err)
+ goto clear_hash;
+ err = crypto_hash_update(desc, sg, nbytes);
+ if (err)
+ goto clear_hash;
+ err = crypto_hash_final(desc, md5_hash);
+ if (err)
+ goto clear_hash;
+
+ /* Reset header, and free up the crypto */
+ tcp_put_md5sig_pool();
+ th->check = old_checksum;
+
+out:
+ return 0;
+clear_hash:
+ tcp_put_md5sig_pool();
+clear_hash_noput:
+ memset(md5_hash, 0, 16);
+ goto out;
+}
+
+int tcp_v4_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
+ struct sock *sk,
+ struct dst_entry *dst,
+ struct request_sock *req,
+ struct tcphdr *th, int protocol,
+ int tcplen)
+{
+ __be32 saddr, daddr;
+
+ if (sk) {
+ saddr = inet_sk(sk)->saddr;
+ daddr = inet_sk(sk)->daddr;
+ } else {
+ struct rtable *rt = (struct rtable *)dst;
+ BUG_ON(!rt);
+ saddr = rt->rt_src;
+ daddr = rt->rt_dst;
+ }
+ return tcp_v4_do_calc_md5_hash(md5_hash, key,
+ saddr, daddr,
+ th, protocol, tcplen);
+}
+
+EXPORT_SYMBOL(tcp_v4_calc_md5_hash);
+
+static int tcp_v4_inbound_md5_hash(struct sock *sk, struct sk_buff *skb)
+{
+ /*
+ * This gets called for each TCP segment that arrives
+ * so we want to be efficient.
+ * We have 3 drop cases:
+ * o No MD5 hash and one expected.
+ * o MD5 hash and we're not expecting one.
+ * o MD5 hash and its wrong.
+ */
+ __u8 *hash_location = NULL;
+ struct tcp_md5sig_key *hash_expected;
+ struct iphdr *iph = skb->nh.iph;
+ struct tcphdr *th = skb->h.th;
+ int length = (th->doff << 2) - sizeof(struct tcphdr);
+ int genhash;
+ unsigned char *ptr;
+ unsigned char newhash[16];
+
+ hash_expected = tcp_v4_md5_do_lookup(sk, iph->saddr);
+
+ /*
+ * If the TCP option length is less than the TCP_MD5SIG
+ * option length, then we can shortcut
+ */
+ if (length < TCPOLEN_MD5SIG) {
+ if (hash_expected)
+ return 1;
+ else
+ return 0;
+ }
+
+ /* Okay, we can't shortcut - we have to grub through the options */
+ ptr = (unsigned char *)(th + 1);
+ while (length > 0) {
+ int opcode = *ptr++;
+ int opsize;
+
+ switch (opcode) {
+ case TCPOPT_EOL:
+ goto done_opts;
+ case TCPOPT_NOP:
+ length--;
+ continue;
+ default:
+ opsize = *ptr++;
+ if (opsize < 2)
+ goto done_opts;
+ if (opsize > length)
+ goto done_opts;
+
+ if (opcode == TCPOPT_MD5SIG) {
+ hash_location = ptr;
+ goto done_opts;
+ }
+ }
+ ptr += opsize-2;
+ length -= opsize;
+ }
+done_opts:
+ /* We've parsed the options - do we have a hash? */
+ if (!hash_expected && !hash_location)
+ return 0;
+
+ if (hash_expected && !hash_location) {
+ LIMIT_NETDEBUG(KERN_INFO "MD5 Hash NOT expected but found "
+ "(" NIPQUAD_FMT ", %d)->(" NIPQUAD_FMT ", %d)\n",
+ NIPQUAD(iph->saddr), ntohs(th->source),
+ NIPQUAD(iph->daddr), ntohs(th->dest));
+ return 1;
+ }
+
+ if (!hash_expected && hash_location) {
+ LIMIT_NETDEBUG(KERN_INFO "MD5 Hash NOT expected but found "
+ "(" NIPQUAD_FMT ", %d)->(" NIPQUAD_FMT ", %d)\n",
+ NIPQUAD(iph->saddr), ntohs(th->source),
+ NIPQUAD(iph->daddr), ntohs(th->dest));
+ return 1;
+ }
+
+ /* Okay, so this is hash_expected and hash_location -
+ * so we need to calculate the checksum.
+ */
+ genhash = tcp_v4_do_calc_md5_hash(newhash,
+ hash_expected,
+ iph->saddr, iph->daddr,
+ th, sk->sk_protocol,
+ skb->len);
+
+ if (genhash || memcmp(hash_location, newhash, 16) != 0) {
+ if (net_ratelimit()) {
+ printk(KERN_INFO "MD5 Hash failed for "
+ "(" NIPQUAD_FMT ", %d)->(" NIPQUAD_FMT ", %d)%s\n",
+ NIPQUAD(iph->saddr), ntohs(th->source),
+ NIPQUAD(iph->daddr), ntohs(th->dest),
+ genhash ? " tcp_v4_calc_md5_hash failed" : "");
+ }
+ return 1;
+ }
+ return 0;
+}
+
+#endif
+
+struct request_sock_ops tcp_request_sock_ops __read_mostly = {
.family = PF_INET,
.obj_size = sizeof(struct tcp_request_sock),
.rtx_syn_ack = tcp_v4_send_synack,
@@ -724,9 +1233,16 @@ struct request_sock_ops tcp_request_sock_ops = {
.send_reset = tcp_v4_send_reset,
};
+#ifdef CONFIG_TCP_MD5SIG
+static struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = {
+ .md5_lookup = tcp_v4_reqsk_md5_lookup,
+};
+#endif
+
static struct timewait_sock_ops tcp_timewait_sock_ops = {
.twsk_obj_size = sizeof(struct tcp_timewait_sock),
.twsk_unique = tcp_twsk_unique,
+ .twsk_destructor= tcp_twsk_destructor,
};
int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
@@ -774,6 +1290,10 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
if (!req)
goto drop;
+#ifdef CONFIG_TCP_MD5SIG
+ tcp_rsk(req)->af_specific = &tcp_request_sock_ipv4_ops;
+#endif
+
tcp_clear_options(&tmp_opt);
tmp_opt.mss_clamp = 536;
tmp_opt.user_mss = tcp_sk(sk)->rx_opt.user_mss;
@@ -859,7 +1379,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
goto drop_and_free;
}
- isn = tcp_v4_init_sequence(sk, skb);
+ isn = tcp_v4_init_sequence(skb);
}
tcp_rsk(req)->snt_isn = isn;
@@ -892,6 +1412,9 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
struct inet_sock *newinet;
struct tcp_sock *newtp;
struct sock *newsk;
+#ifdef CONFIG_TCP_MD5SIG
+ struct tcp_md5sig_key *key;
+#endif
if (sk_acceptq_is_full(sk))
goto exit_overflow;
@@ -926,6 +1449,22 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
newtp->advmss = dst_metric(dst, RTAX_ADVMSS);
tcp_initialize_rcv_mss(newsk);
+#ifdef CONFIG_TCP_MD5SIG
+ /* Copy over the MD5 key from the original socket */
+ if ((key = tcp_v4_md5_do_lookup(sk, newinet->daddr)) != NULL) {
+ /*
+ * We're using one, so create a matching key
+ * on the newsk structure. If we fail to get
+ * memory, then we end up not copying the key
+ * across. Shucks.
+ */
+ char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC);
+ if (newkey != NULL)
+ tcp_v4_md5_do_add(newsk, inet_sk(sk)->daddr,
+ newkey, key->keylen);
+ }
+#endif
+
__inet_hash(&tcp_hashinfo, newsk, 0);
__inet_inherit_port(&tcp_hashinfo, sk, newsk);
@@ -971,7 +1510,7 @@ static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
return sk;
}
-static int tcp_v4_checksum_init(struct sk_buff *skb)
+static __sum16 tcp_v4_checksum_init(struct sk_buff *skb)
{
if (skb->ip_summed == CHECKSUM_COMPLETE) {
if (!tcp_v4_check(skb->h.th, skb->len, skb->nh.iph->saddr,
@@ -1001,10 +1540,24 @@ static int tcp_v4_checksum_init(struct sk_buff *skb)
*/
int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
{
+ struct sock *rsk;
+#ifdef CONFIG_TCP_MD5SIG
+ /*
+ * We really want to reject the packet as early as possible
+ * if:
+ * o We're expecting an MD5'd packet and this is no MD5 tcp option
+ * o There is an MD5 option and we're not expecting one
+ */
+ if (tcp_v4_inbound_md5_hash(sk, skb))
+ goto discard;
+#endif
+
if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */
TCP_CHECK_TIMER(sk);
- if (tcp_rcv_established(sk, skb, skb->h.th, skb->len))
+ if (tcp_rcv_established(sk, skb, skb->h.th, skb->len)) {
+ rsk = sk;
goto reset;
+ }
TCP_CHECK_TIMER(sk);
return 0;
}
@@ -1018,20 +1571,24 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
goto discard;
if (nsk != sk) {
- if (tcp_child_process(sk, nsk, skb))
+ if (tcp_child_process(sk, nsk, skb)) {
+ rsk = nsk;
goto reset;
+ }
return 0;
}
}
TCP_CHECK_TIMER(sk);
- if (tcp_rcv_state_process(sk, skb, skb->h.th, skb->len))
+ if (tcp_rcv_state_process(sk, skb, skb->h.th, skb->len)) {
+ rsk = sk;
goto reset;
+ }
TCP_CHECK_TIMER(sk);
return 0;
reset:
- tcp_v4_send_reset(skb);
+ tcp_v4_send_reset(rsk, skb);
discard:
kfree_skb(skb);
/* Be careful here. If this function gets more complicated and
@@ -1140,7 +1697,7 @@ no_tcp_socket:
bad_packet:
TCP_INC_STATS_BH(TCP_MIB_INERRS);
} else {
- tcp_v4_send_reset(skb);
+ tcp_v4_send_reset(NULL, skb);
}
discard_it:
@@ -1263,6 +1820,15 @@ struct inet_connection_sock_af_ops ipv4_specific = {
#endif
};
+#ifdef CONFIG_TCP_MD5SIG
+static struct tcp_sock_af_ops tcp_sock_ipv4_specific = {
+ .md5_lookup = tcp_v4_md5_lookup,
+ .calc_md5_hash = tcp_v4_calc_md5_hash,
+ .md5_add = tcp_v4_md5_add_func,
+ .md5_parse = tcp_v4_parse_md5_keys,
+};
+#endif
+
/* NOTE: A lot of things set to zero explicitly by call to
* sk_alloc() so need not be done here.
*/
@@ -1302,6 +1868,9 @@ static int tcp_v4_init_sock(struct sock *sk)
icsk->icsk_af_ops = &ipv4_specific;
icsk->icsk_sync_mss = tcp_sync_mss;
+#ifdef CONFIG_TCP_MD5SIG
+ tp->af_specific = &tcp_sock_ipv4_specific;
+#endif
sk->sk_sndbuf = sysctl_tcp_wmem[1];
sk->sk_rcvbuf = sysctl_tcp_rmem[1];
@@ -1325,6 +1894,15 @@ int tcp_v4_destroy_sock(struct sock *sk)
/* Cleans up our, hopefully empty, out_of_order_queue. */
__skb_queue_purge(&tp->out_of_order_queue);
+#ifdef CONFIG_TCP_MD5SIG
+ /* Clean up the MD5 key list, if any */
+ if (tp->md5sig_info) {
+ tcp_v4_clear_md5_list(sk);
+ kfree(tp->md5sig_info);
+ tp->md5sig_info = NULL;
+ }
+#endif
+
#ifdef CONFIG_NET_DMA
/* Cleans up our sk_async_wait_queue */
__skb_queue_purge(&sk->sk_async_wait_queue);
@@ -1385,7 +1963,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
if (st->state == TCP_SEQ_STATE_OPENREQ) {
struct request_sock *req = cur;
- icsk = inet_csk(st->syn_wait_sk);
+ icsk = inet_csk(st->syn_wait_sk);
req = req->dl_next;
while (1) {
while (req) {
@@ -1395,7 +1973,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
}
req = req->dl_next;
}
- if (++st->sbucket >= TCP_SYNQ_HSIZE)
+ if (++st->sbucket >= icsk->icsk_accept_queue.listen_opt->nr_table_entries)
break;
get_req:
req = icsk->icsk_accept_queue.listen_opt->syn_table[st->sbucket];
@@ -1543,7 +2121,7 @@ static void *established_get_idx(struct seq_file *seq, loff_t pos)
while (rc && pos) {
rc = established_get_next(seq, rc);
--pos;
- }
+ }
return rc;
}
@@ -1672,7 +2250,7 @@ int tcp_proc_register(struct tcp_seq_afinfo *afinfo)
afinfo->seq_fops->read = seq_read;
afinfo->seq_fops->llseek = seq_lseek;
afinfo->seq_fops->release = seq_release_private;
-
+
p = proc_net_fops_create(afinfo->name, S_IRUGO, afinfo->seq_fops);
if (p)
p->data = afinfo;
@@ -1686,7 +2264,7 @@ void tcp_proc_unregister(struct tcp_seq_afinfo *afinfo)
if (!afinfo)
return;
proc_net_remove(afinfo->name);
- memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops));
+ memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops));
}
static void get_openreq4(struct sock *sk, struct request_sock *req,
@@ -1721,8 +2299,8 @@ static void get_tcp4_sock(struct sock *sp, char *tmpbuf, int i)
struct tcp_sock *tp = tcp_sk(sp);
const struct inet_connection_sock *icsk = inet_csk(sp);
struct inet_sock *inet = inet_sk(sp);
- unsigned int dest = inet->daddr;
- unsigned int src = inet->rcv_saddr;
+ __be32 dest = inet->daddr;
+ __be32 src = inet->rcv_saddr;
__u16 destp = ntohs(inet->dport);
__u16 srcp = ntohs(inet->sport);
@@ -1744,7 +2322,8 @@ static void get_tcp4_sock(struct sock *sp, char *tmpbuf, int i)
"%08X %5d %8d %lu %d %p %u %u %u %u %d",
i, src, srcp, dest, destp, sp->sk_state,
tp->write_seq - tp->snd_una,
- (sp->sk_state == TCP_LISTEN) ? sp->sk_ack_backlog : (tp->rcv_nxt - tp->copied_seq),
+ sp->sk_state == TCP_LISTEN ? sp->sk_ack_backlog :
+ (tp->rcv_nxt - tp->copied_seq),
timer_active,
jiffies_to_clock_t(timer_expires - jiffies),
icsk->icsk_retransmits,
@@ -1759,7 +2338,8 @@ static void get_tcp4_sock(struct sock *sp, char *tmpbuf, int i)
tp->snd_ssthresh >= 0xFFFF ? -1 : tp->snd_ssthresh);
}
-static void get_timewait4_sock(struct inet_timewait_sock *tw, char *tmpbuf, int i)
+static void get_timewait4_sock(struct inet_timewait_sock *tw,
+ char *tmpbuf, int i)
{
__be32 dest, src;
__u16 destp, srcp;
@@ -1872,7 +2452,8 @@ struct proto tcp_prot = {
void __init tcp_v4_init(struct net_proto_family *ops)
{
- if (inet_csk_ctl_sock_create(&tcp_socket, PF_INET, SOCK_RAW, IPPROTO_TCP) < 0)
+ if (inet_csk_ctl_sock_create(&tcp_socket, PF_INET, SOCK_RAW,
+ IPPROTO_TCP) < 0)
panic("Failed to create the TCP control socket.\n");
}
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index af7b2c986b1f..4a3889dd1943 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -305,6 +305,28 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
tw->tw_ipv6only = np->ipv6only;
}
#endif
+
+#ifdef CONFIG_TCP_MD5SIG
+ /*
+ * The timewait bucket does not have the key DB from the
+ * sock structure. We just make a quick copy of the
+ * md5 key being used (if indeed we are using one)
+ * so the timewait ack generating code has the key.
+ */
+ do {
+ struct tcp_md5sig_key *key;
+ memset(tcptw->tw_md5_key, 0, sizeof(tcptw->tw_md5_key));
+ tcptw->tw_md5_keylen = 0;
+ key = tp->af_specific->md5_lookup(sk, sk);
+ if (key != NULL) {
+ memcpy(&tcptw->tw_md5_key, key->key, key->keylen);
+ tcptw->tw_md5_keylen = key->keylen;
+ if (tcp_alloc_md5sig_pool() == NULL)
+ BUG();
+ }
+ } while(0);
+#endif
+
/* Linkage updates. */
__inet_twsk_hashdance(tw, sk, &tcp_hashinfo);
@@ -328,14 +350,24 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
* socket up. We've got bigger problems than
* non-graceful socket closings.
*/
- if (net_ratelimit())
- printk(KERN_INFO "TCP: time wait bucket table overflow\n");
+ LIMIT_NETDEBUG(KERN_INFO "TCP: time wait bucket table overflow\n");
}
tcp_update_metrics(sk);
tcp_done(sk);
}
+void tcp_twsk_destructor(struct sock *sk)
+{
+#ifdef CONFIG_TCP_MD5SIG
+ struct tcp_timewait_sock *twsk = tcp_twsk(sk);
+ if (twsk->tw_md5_keylen)
+ tcp_put_md5sig_pool();
+#endif
+}
+
+EXPORT_SYMBOL_GPL(tcp_twsk_destructor);
+
/* This is not only more efficient than what we used to do, it eliminates
* a lot of code duplication between IPv4/IPv6 SYN recv processing. -DaveM
*
@@ -434,6 +466,11 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
newtp->rx_opt.ts_recent_stamp = 0;
newtp->tcp_header_len = sizeof(struct tcphdr);
}
+#ifdef CONFIG_TCP_MD5SIG
+ newtp->md5sig_info = NULL; /*XXX*/
+ if (newtp->af_specific->md5_lookup(sk, newsk))
+ newtp->tcp_header_len += TCPOLEN_MD5SIG_ALIGNED;
+#endif
if (skb->len >= TCP_MIN_RCVMSS+newtp->tcp_header_len)
newicsk->icsk_ack.last_seg_size = skb->len - newtp->tcp_header_len;
newtp->rx_opt.mss_clamp = req->mss;
@@ -454,7 +491,7 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
struct request_sock **prev)
{
struct tcphdr *th = skb->h.th;
- u32 flg = tcp_flag_word(th) & (TCP_FLAG_RST|TCP_FLAG_SYN|TCP_FLAG_ACK);
+ __be32 flg = tcp_flag_word(th) & (TCP_FLAG_RST|TCP_FLAG_SYN|TCP_FLAG_ACK);
int paws_reject = 0;
struct tcp_options_received tmp_opt;
struct sock *child;
@@ -616,6 +653,30 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
req, NULL);
if (child == NULL)
goto listen_overflow;
+#ifdef CONFIG_TCP_MD5SIG
+ else {
+ /* Copy over the MD5 key from the original socket */
+ struct tcp_md5sig_key *key;
+ struct tcp_sock *tp = tcp_sk(sk);
+ key = tp->af_specific->md5_lookup(sk, child);
+ if (key != NULL) {
+ /*
+ * We're using one, so create a matching key on the
+ * newsk structure. If we fail to get memory then we
+ * end up not copying the key across. Shucks.
+ */
+ char *newkey = kmemdup(key->key, key->keylen,
+ GFP_ATOMIC);
+ if (newkey) {
+ if (!tcp_alloc_md5sig_pool())
+ BUG();
+ tp->af_specific->md5_add(child, child,
+ newkey,
+ key->keylen);
+ }
+ }
+ }
+#endif
inet_csk_reqsk_queue_unlink(sk, req, prev);
inet_csk_reqsk_queue_removed(sk, req);
@@ -632,7 +693,7 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
embryonic_reset:
NET_INC_STATS_BH(LINUX_MIB_EMBRYONICRSTS);
if (!(flg & TCP_FLAG_RST))
- req->rsk_ops->send_reset(skb);
+ req->rsk_ops->send_reset(sk, skb);
inet_csk_reqsk_queue_drop(sk, req, prev);
return NULL;
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index ca406157724c..32c1a972fa31 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -270,7 +270,7 @@ static u16 tcp_select_window(struct sock *sk)
}
static void tcp_build_and_update_options(__be32 *ptr, struct tcp_sock *tp,
- __u32 tstamp)
+ __u32 tstamp, __u8 **md5_hash)
{
if (tp->rx_opt.tstamp_ok) {
*ptr++ = htonl((TCPOPT_NOP << 24) |
@@ -298,16 +298,29 @@ static void tcp_build_and_update_options(__be32 *ptr, struct tcp_sock *tp,
tp->rx_opt.eff_sacks--;
}
}
+#ifdef CONFIG_TCP_MD5SIG
+ if (md5_hash) {
+ *ptr++ = htonl((TCPOPT_NOP << 24) |
+ (TCPOPT_NOP << 16) |
+ (TCPOPT_MD5SIG << 8) |
+ TCPOLEN_MD5SIG);
+ *md5_hash = (__u8 *)ptr;
+ }
+#endif
}
/* Construct a tcp options header for a SYN or SYN_ACK packet.
* If this is every changed make sure to change the definition of
* MAX_SYN_SIZE to match the new maximum number of options that you
* can generate.
+ *
+ * Note - that with the RFC2385 TCP option, we make room for the
+ * 16 byte MD5 hash. This will be filled in later, so the pointer for the
+ * location to be filled is passed back up.
*/
static void tcp_syn_build_options(__be32 *ptr, int mss, int ts, int sack,
int offer_wscale, int wscale, __u32 tstamp,
- __u32 ts_recent)
+ __u32 ts_recent, __u8 **md5_hash)
{
/* We always get an MSS option.
* The option bytes which will be seen in normal data
@@ -346,6 +359,20 @@ static void tcp_syn_build_options(__be32 *ptr, int mss, int ts, int sack,
(TCPOPT_WINDOW << 16) |
(TCPOLEN_WINDOW << 8) |
(wscale));
+#ifdef CONFIG_TCP_MD5SIG
+ /*
+ * If MD5 is enabled, then we set the option, and include the size
+ * (always 18). The actual MD5 hash is added just before the
+ * packet is sent.
+ */
+ if (md5_hash) {
+ *ptr++ = htonl((TCPOPT_NOP << 24) |
+ (TCPOPT_NOP << 16) |
+ (TCPOPT_MD5SIG << 8) |
+ TCPOLEN_MD5SIG);
+ *md5_hash = (__u8 *) ptr;
+ }
+#endif
}
/* This routine actually transmits TCP packets queued in by
@@ -366,6 +393,10 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
struct tcp_sock *tp;
struct tcp_skb_cb *tcb;
int tcp_header_size;
+#ifdef CONFIG_TCP_MD5SIG
+ struct tcp_md5sig_key *md5;
+ __u8 *md5_hash_location;
+#endif
struct tcphdr *th;
int sysctl_flags;
int err;
@@ -424,9 +455,18 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
if (tcp_packets_in_flight(tp) == 0)
tcp_ca_event(sk, CA_EVENT_TX_START);
+#ifdef CONFIG_TCP_MD5SIG
+ /*
+ * Are we doing MD5 on this segment? If so - make
+ * room for it.
+ */
+ md5 = tp->af_specific->md5_lookup(sk, sk);
+ if (md5)
+ tcp_header_size += TCPOLEN_MD5SIG_ALIGNED;
+#endif
+
th = (struct tcphdr *) skb_push(skb, tcp_header_size);
skb->h.th = th;
- skb_set_owner_w(skb, sk);
/* Build TCP header and checksum it. */
th->source = inet->sport;
@@ -461,13 +501,34 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
(sysctl_flags & SYSCTL_FLAG_WSCALE),
tp->rx_opt.rcv_wscale,
tcb->when,
- tp->rx_opt.ts_recent);
+ tp->rx_opt.ts_recent,
+
+#ifdef CONFIG_TCP_MD5SIG
+ md5 ? &md5_hash_location :
+#endif
+ NULL);
} else {
tcp_build_and_update_options((__be32 *)(th + 1),
- tp, tcb->when);
+ tp, tcb->when,
+#ifdef CONFIG_TCP_MD5SIG
+ md5 ? &md5_hash_location :
+#endif
+ NULL);
TCP_ECN_send(sk, tp, skb, tcp_header_size);
}
+#ifdef CONFIG_TCP_MD5SIG
+ /* Calculate the MD5 hash, as we have all we need now */
+ if (md5) {
+ tp->af_specific->calc_md5_hash(md5_hash_location,
+ md5,
+ sk, NULL, NULL,
+ skb->h.th,
+ sk->sk_protocol,
+ skb->len);
+ }
+#endif
+
icsk->icsk_af_ops->send_check(sk, skb->len, skb);
if (likely(tcb->flags & TCPCB_FLAG_ACK))
@@ -479,19 +540,13 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
if (after(tcb->end_seq, tp->snd_nxt) || tcb->seq == tcb->end_seq)
TCP_INC_STATS(TCP_MIB_OUTSEGS);
- err = icsk->icsk_af_ops->queue_xmit(skb, 0);
+ err = icsk->icsk_af_ops->queue_xmit(skb, sk, 0);
if (likely(err <= 0))
return err;
tcp_enter_cwr(sk);
- /* NET_XMIT_CN is special. It does not guarantee,
- * that this packet is lost. It tells that device
- * is about to start to drop packets or already
- * drops some packets of the same priority and
- * invokes us to send less aggressively.
- */
- return err == NET_XMIT_CN ? 0 : err;
+ return net_xmit_eval(err);
#undef SYSCTL_FLAG_TSTAMPS
#undef SYSCTL_FLAG_WSCALE
@@ -847,6 +902,11 @@ unsigned int tcp_current_mss(struct sock *sk, int large_allowed)
mss_now -= (TCPOLEN_SACK_BASE_ALIGNED +
(tp->rx_opt.eff_sacks * TCPOLEN_SACK_PERBLOCK));
+#ifdef CONFIG_TCP_MD5SIG
+ if (tp->af_specific->md5_lookup(sk, sk))
+ mss_now -= TCPOLEN_MD5SIG_ALIGNED;
+#endif
+
xmit_size_goal = mss_now;
if (doing_tso) {
@@ -2040,6 +2100,10 @@ struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst,
struct tcphdr *th;
int tcp_header_size;
struct sk_buff *skb;
+#ifdef CONFIG_TCP_MD5SIG
+ struct tcp_md5sig_key *md5;
+ __u8 *md5_hash_location;
+#endif
skb = sock_wmalloc(sk, MAX_TCP_HEADER + 15, 1, GFP_ATOMIC);
if (skb == NULL)
@@ -2055,6 +2119,13 @@ struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst,
(ireq->wscale_ok ? TCPOLEN_WSCALE_ALIGNED : 0) +
/* SACK_PERM is in the place of NOP NOP of TS */
((ireq->sack_ok && !ireq->tstamp_ok) ? TCPOLEN_SACKPERM_ALIGNED : 0));
+
+#ifdef CONFIG_TCP_MD5SIG
+ /* Are we doing MD5 on this segment? If so - make room for it */
+ md5 = tcp_rsk(req)->af_specific->md5_lookup(sk, req);
+ if (md5)
+ tcp_header_size += TCPOLEN_MD5SIG_ALIGNED;
+#endif
skb->h.th = th = (struct tcphdr *) skb_push(skb, tcp_header_size);
memset(th, 0, sizeof(struct tcphdr));
@@ -2092,11 +2163,29 @@ struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst,
tcp_syn_build_options((__be32 *)(th + 1), dst_metric(dst, RTAX_ADVMSS), ireq->tstamp_ok,
ireq->sack_ok, ireq->wscale_ok, ireq->rcv_wscale,
TCP_SKB_CB(skb)->when,
- req->ts_recent);
+ req->ts_recent,
+ (
+#ifdef CONFIG_TCP_MD5SIG
+ md5 ? &md5_hash_location :
+#endif
+ NULL)
+ );
skb->csum = 0;
th->doff = (tcp_header_size >> 2);
TCP_INC_STATS(TCP_MIB_OUTSEGS);
+
+#ifdef CONFIG_TCP_MD5SIG
+ /* Okay, we have all we need - do the md5 hash if needed */
+ if (md5) {
+ tp->af_specific->calc_md5_hash(md5_hash_location,
+ md5,
+ NULL, dst, req,
+ skb->h.th, sk->sk_protocol,
+ skb->len);
+ }
+#endif
+
return skb;
}
@@ -2115,6 +2204,11 @@ static void tcp_connect_init(struct sock *sk)
tp->tcp_header_len = sizeof(struct tcphdr) +
(sysctl_tcp_timestamps ? TCPOLEN_TSTAMP_ALIGNED : 0);
+#ifdef CONFIG_TCP_MD5SIG
+ if (tp->af_specific->md5_lookup(sk, sk) != NULL)
+ tp->tcp_header_len += TCPOLEN_MD5SIG_ALIGNED;
+#endif
+
/* If user gave his TCP_MAXSEG, record it to clamp */
if (tp->rx_opt.user_mss)
tp->rx_opt.mss_clamp = tp->rx_opt.user_mss;
diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c
index 4be336f17883..f230eeecf092 100644
--- a/net/ipv4/tcp_probe.c
+++ b/net/ipv4/tcp_probe.c
@@ -156,6 +156,8 @@ static __init int tcpprobe_init(void)
init_waitqueue_head(&tcpw.wait);
spin_lock_init(&tcpw.lock);
tcpw.fifo = kfifo_alloc(bufsize, GFP_KERNEL, &tcpw.lock);
+ if (IS_ERR(tcpw.fifo))
+ return PTR_ERR(tcpw.fifo);
if (!proc_net_fops_create(procname, S_IRUSR, &tcpprobe_fops))
goto err0;
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index fb09ade5897b..3355c276b611 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -297,7 +297,7 @@ static void tcp_retransmit_timer(struct sock *sk)
if (net_ratelimit()) {
struct inet_sock *inet = inet_sk(sk);
printk(KERN_DEBUG "TCP: Treason uncloaked! Peer %u.%u.%u.%u:%u/%u shrinks window %u:%u. Repaired.\n",
- NIPQUAD(inet->daddr), htons(inet->dport),
+ NIPQUAD(inet->daddr), ntohs(inet->dport),
inet->num, tp->snd_una, tp->snd_nxt);
}
#endif
diff --git a/net/ipv4/tcp_vegas.c b/net/ipv4/tcp_vegas.c
index a3b7aa015a2f..ddc4bcc5785e 100644
--- a/net/ipv4/tcp_vegas.c
+++ b/net/ipv4/tcp_vegas.c
@@ -42,8 +42,8 @@
* with V_PARAM_SHIFT bits to the right of the binary point.
*/
#define V_PARAM_SHIFT 1
-static int alpha = 1<<V_PARAM_SHIFT;
-static int beta = 3<<V_PARAM_SHIFT;
+static int alpha = 2<<V_PARAM_SHIFT;
+static int beta = 4<<V_PARAM_SHIFT;
static int gamma = 1<<V_PARAM_SHIFT;
module_param(alpha, int, 0644);
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 865d75214a9a..035915fc9ed3 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -92,22 +92,16 @@
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/inet.h>
-#include <linux/ipv6.h>
#include <linux/netdevice.h>
-#include <net/snmp.h>
-#include <net/ip.h>
#include <net/tcp_states.h>
-#include <net/protocol.h>
#include <linux/skbuff.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
-#include <net/sock.h>
-#include <net/udp.h>
#include <net/icmp.h>
#include <net/route.h>
-#include <net/inet_common.h>
#include <net/checksum.h>
#include <net/xfrm.h>
+#include "udp_impl.h"
/*
* Snmp MIB for the UDP layer
@@ -120,26 +114,30 @@ DEFINE_RWLOCK(udp_hash_lock);
static int udp_port_rover;
-static inline int udp_lport_inuse(u16 num)
+static inline int __udp_lib_lport_inuse(__u16 num, struct hlist_head udptable[])
{
struct sock *sk;
struct hlist_node *node;
- sk_for_each(sk, node, &udp_hash[num & (UDP_HTABLE_SIZE - 1)])
+ sk_for_each(sk, node, &udptable[num & (UDP_HTABLE_SIZE - 1)])
if (inet_sk(sk)->num == num)
return 1;
return 0;
}
/**
- * udp_get_port - common port lookup for IPv4 and IPv6
+ * __udp_lib_get_port - UDP/-Lite port lookup for IPv4 and IPv6
*
* @sk: socket struct in question
* @snum: port number to look up
+ * @udptable: hash list table, must be of UDP_HTABLE_SIZE
+ * @port_rover: pointer to record of last unallocated port
* @saddr_comp: AF-dependent comparison of bound local IP addresses
*/
-int udp_get_port(struct sock *sk, unsigned short snum,
- int (*saddr_cmp)(const struct sock *sk1, const struct sock *sk2))
+int __udp_lib_get_port(struct sock *sk, unsigned short snum,
+ struct hlist_head udptable[], int *port_rover,
+ int (*saddr_comp)(const struct sock *sk1,
+ const struct sock *sk2 ) )
{
struct hlist_node *node;
struct hlist_head *head;
@@ -150,15 +148,15 @@ int udp_get_port(struct sock *sk, unsigned short snum,
if (snum == 0) {
int best_size_so_far, best, result, i;
- if (udp_port_rover > sysctl_local_port_range[1] ||
- udp_port_rover < sysctl_local_port_range[0])
- udp_port_rover = sysctl_local_port_range[0];
+ if (*port_rover > sysctl_local_port_range[1] ||
+ *port_rover < sysctl_local_port_range[0])
+ *port_rover = sysctl_local_port_range[0];
best_size_so_far = 32767;
- best = result = udp_port_rover;
+ best = result = *port_rover;
for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) {
int size;
- head = &udp_hash[result & (UDP_HTABLE_SIZE - 1)];
+ head = &udptable[result & (UDP_HTABLE_SIZE - 1)];
if (hlist_empty(head)) {
if (result > sysctl_local_port_range[1])
result = sysctl_local_port_range[0] +
@@ -179,15 +177,15 @@ int udp_get_port(struct sock *sk, unsigned short snum,
result = sysctl_local_port_range[0]
+ ((result - sysctl_local_port_range[0]) &
(UDP_HTABLE_SIZE - 1));
- if (!udp_lport_inuse(result))
+ if (! __udp_lib_lport_inuse(result, udptable))
break;
}
if (i >= (1 << 16) / UDP_HTABLE_SIZE)
goto fail;
gotit:
- udp_port_rover = snum = result;
+ *port_rover = snum = result;
} else {
- head = &udp_hash[snum & (UDP_HTABLE_SIZE - 1)];
+ head = &udptable[snum & (UDP_HTABLE_SIZE - 1)];
sk_for_each(sk2, node, head)
if (inet_sk(sk2)->num == snum &&
@@ -195,12 +193,12 @@ gotit:
(!sk2->sk_reuse || !sk->sk_reuse) &&
(!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if
|| sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
- (*saddr_cmp)(sk, sk2) )
+ (*saddr_comp)(sk, sk2) )
goto fail;
}
inet_sk(sk)->num = snum;
if (sk_unhashed(sk)) {
- head = &udp_hash[snum & (UDP_HTABLE_SIZE - 1)];
+ head = &udptable[snum & (UDP_HTABLE_SIZE - 1)];
sk_add_node(sk, head);
sock_prot_inc_use(sk->sk_prot);
}
@@ -210,7 +208,13 @@ fail:
return error;
}
-static inline int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
+__inline__ int udp_get_port(struct sock *sk, unsigned short snum,
+ int (*scmp)(const struct sock *, const struct sock *))
+{
+ return __udp_lib_get_port(sk, snum, udp_hash, &udp_port_rover, scmp);
+}
+
+inline int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
{
struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2);
@@ -224,34 +228,20 @@ static inline int udp_v4_get_port(struct sock *sk, unsigned short snum)
return udp_get_port(sk, snum, ipv4_rcv_saddr_equal);
}
-
-static void udp_v4_hash(struct sock *sk)
-{
- BUG();
-}
-
-static void udp_v4_unhash(struct sock *sk)
-{
- write_lock_bh(&udp_hash_lock);
- if (sk_del_node_init(sk)) {
- inet_sk(sk)->num = 0;
- sock_prot_dec_use(sk->sk_prot);
- }
- write_unlock_bh(&udp_hash_lock);
-}
-
/* UDP is nearly always wildcards out the wazoo, it makes no sense to try
* harder than this. -DaveM
*/
-static struct sock *udp_v4_lookup_longway(__be32 saddr, __be16 sport,
- __be32 daddr, __be16 dport, int dif)
+static struct sock *__udp4_lib_lookup(__be32 saddr, __be16 sport,
+ __be32 daddr, __be16 dport,
+ int dif, struct hlist_head udptable[])
{
struct sock *sk, *result = NULL;
struct hlist_node *node;
unsigned short hnum = ntohs(dport);
int badness = -1;
- sk_for_each(sk, node, &udp_hash[hnum & (UDP_HTABLE_SIZE - 1)]) {
+ read_lock(&udp_hash_lock);
+ sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) {
struct inet_sock *inet = inet_sk(sk);
if (inet->num == hnum && !ipv6_only_sock(sk)) {
@@ -285,20 +275,10 @@ static struct sock *udp_v4_lookup_longway(__be32 saddr, __be16 sport,
}
}
}
- return result;
-}
-
-static __inline__ struct sock *udp_v4_lookup(__be32 saddr, __be16 sport,
- __be32 daddr, __be16 dport, int dif)
-{
- struct sock *sk;
-
- read_lock(&udp_hash_lock);
- sk = udp_v4_lookup_longway(saddr, sport, daddr, dport, dif);
- if (sk)
- sock_hold(sk);
+ if (result)
+ sock_hold(result);
read_unlock(&udp_hash_lock);
- return sk;
+ return result;
}
static inline struct sock *udp_v4_mcast_next(struct sock *sk,
@@ -340,7 +320,7 @@ found:
* to find the appropriate port.
*/
-void udp_err(struct sk_buff *skb, u32 info)
+void __udp4_lib_err(struct sk_buff *skb, u32 info, struct hlist_head udptable[])
{
struct inet_sock *inet;
struct iphdr *iph = (struct iphdr*)skb->data;
@@ -351,7 +331,8 @@ void udp_err(struct sk_buff *skb, u32 info)
int harderr;
int err;
- sk = udp_v4_lookup(iph->daddr, uh->dest, iph->saddr, uh->source, skb->dev->ifindex);
+ sk = __udp4_lib_lookup(iph->daddr, uh->dest, iph->saddr, uh->source,
+ skb->dev->ifindex, udptable );
if (sk == NULL) {
ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
return; /* No socket for error */
@@ -405,6 +386,11 @@ out:
sock_put(sk);
}
+__inline__ void udp_err(struct sk_buff *skb, u32 info)
+{
+ return __udp4_lib_err(skb, info, udp_hash);
+}
+
/*
* Throw away all pending data and cancel the corking. Socket is locked.
*/
@@ -419,16 +405,58 @@ static void udp_flush_pending_frames(struct sock *sk)
}
}
+/**
+ * udp4_hwcsum_outgoing - handle outgoing HW checksumming
+ * @sk: socket we are sending on
+ * @skb: sk_buff containing the filled-in UDP header
+ * (checksum field must be zeroed out)
+ */
+static void udp4_hwcsum_outgoing(struct sock *sk, struct sk_buff *skb,
+ __be32 src, __be32 dst, int len )
+{
+ unsigned int offset;
+ struct udphdr *uh = skb->h.uh;
+ __wsum csum = 0;
+
+ if (skb_queue_len(&sk->sk_write_queue) == 1) {
+ /*
+ * Only one fragment on the socket.
+ */
+ skb->csum_offset = offsetof(struct udphdr, check);
+ uh->check = ~csum_tcpudp_magic(src, dst, len, IPPROTO_UDP, 0);
+ } else {
+ /*
+ * HW-checksum won't work as there are two or more
+ * fragments on the socket so that all csums of sk_buffs
+ * should be together
+ */
+ offset = skb->h.raw - skb->data;
+ skb->csum = skb_checksum(skb, offset, skb->len - offset, 0);
+
+ skb->ip_summed = CHECKSUM_NONE;
+
+ skb_queue_walk(&sk->sk_write_queue, skb) {
+ csum = csum_add(csum, skb->csum);
+ }
+
+ uh->check = csum_tcpudp_magic(src, dst, len, IPPROTO_UDP, csum);
+ if (uh->check == 0)
+ uh->check = CSUM_MANGLED_0;
+ }
+}
+
/*
* Push out all pending data as one UDP datagram. Socket is locked.
*/
-static int udp_push_pending_frames(struct sock *sk, struct udp_sock *up)
+static int udp_push_pending_frames(struct sock *sk)
{
+ struct udp_sock *up = udp_sk(sk);
struct inet_sock *inet = inet_sk(sk);
struct flowi *fl = &inet->cork.fl;
struct sk_buff *skb;
struct udphdr *uh;
int err = 0;
+ __wsum csum = 0;
/* Grab the skbuff where UDP header space exists. */
if ((skb = skb_peek(&sk->sk_write_queue)) == NULL)
@@ -443,52 +471,28 @@ static int udp_push_pending_frames(struct sock *sk, struct udp_sock *up)
uh->len = htons(up->len);
uh->check = 0;
- if (sk->sk_no_check == UDP_CSUM_NOXMIT) {
+ if (up->pcflag) /* UDP-Lite */
+ csum = udplite_csum_outgoing(sk, skb);
+
+ else if (sk->sk_no_check == UDP_CSUM_NOXMIT) { /* UDP csum disabled */
+
skb->ip_summed = CHECKSUM_NONE;
goto send;
- }
- if (skb_queue_len(&sk->sk_write_queue) == 1) {
- /*
- * Only one fragment on the socket.
- */
- if (skb->ip_summed == CHECKSUM_PARTIAL) {
- skb->csum = offsetof(struct udphdr, check);
- uh->check = ~csum_tcpudp_magic(fl->fl4_src, fl->fl4_dst,
- up->len, IPPROTO_UDP, 0);
- } else {
- skb->csum = csum_partial((char *)uh,
- sizeof(struct udphdr), skb->csum);
- uh->check = csum_tcpudp_magic(fl->fl4_src, fl->fl4_dst,
- up->len, IPPROTO_UDP, skb->csum);
- if (uh->check == 0)
- uh->check = -1;
- }
- } else {
- unsigned int csum = 0;
- /*
- * HW-checksum won't work as there are two or more
- * fragments on the socket so that all csums of sk_buffs
- * should be together.
- */
- if (skb->ip_summed == CHECKSUM_PARTIAL) {
- int offset = (unsigned char *)uh - skb->data;
- skb->csum = skb_checksum(skb, offset, skb->len - offset, 0);
+ } else if (skb->ip_summed == CHECKSUM_PARTIAL) { /* UDP hardware csum */
- skb->ip_summed = CHECKSUM_NONE;
- } else {
- skb->csum = csum_partial((char *)uh,
- sizeof(struct udphdr), skb->csum);
- }
+ udp4_hwcsum_outgoing(sk, skb, fl->fl4_src,fl->fl4_dst, up->len);
+ goto send;
+
+ } else /* `normal' UDP */
+ csum = udp_csum_outgoing(sk, skb);
+
+ /* add protocol-dependent pseudo-header */
+ uh->check = csum_tcpudp_magic(fl->fl4_src, fl->fl4_dst, up->len,
+ sk->sk_protocol, csum );
+ if (uh->check == 0)
+ uh->check = CSUM_MANGLED_0;
- skb_queue_walk(&sk->sk_write_queue, skb) {
- csum = csum_add(csum, skb->csum);
- }
- uh->check = csum_tcpudp_magic(fl->fl4_src, fl->fl4_dst,
- up->len, IPPROTO_UDP, csum);
- if (uh->check == 0)
- uh->check = -1;
- }
send:
err = ip_push_pending_frames(sk);
out:
@@ -497,12 +501,6 @@ out:
return err;
}
-
-static unsigned short udp_check(struct udphdr *uh, int len, __be32 saddr, __be32 daddr, unsigned long base)
-{
- return(csum_tcpudp_magic(saddr, daddr, len, IPPROTO_UDP, base));
-}
-
int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
size_t len)
{
@@ -516,8 +514,9 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
__be32 daddr, faddr, saddr;
__be16 dport;
u8 tos;
- int err;
+ int err, is_udplite = up->pcflag;
int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
+ int (*getfrag)(void *, char *, int, int, int, struct sk_buff *);
if (len > 0xFFFF)
return -EMSGSIZE;
@@ -622,7 +621,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
{ .daddr = faddr,
.saddr = saddr,
.tos = tos } },
- .proto = IPPROTO_UDP,
+ .proto = sk->sk_protocol,
.uli_u = { .ports =
{ .sport = inet->sport,
.dport = dport } } };
@@ -668,13 +667,14 @@ back_from_confirm:
do_append_data:
up->len += ulen;
- err = ip_append_data(sk, ip_generic_getfrag, msg->msg_iov, ulen,
- sizeof(struct udphdr), &ipc, rt,
+ getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag;
+ err = ip_append_data(sk, getfrag, msg->msg_iov, ulen,
+ sizeof(struct udphdr), &ipc, rt,
corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags);
if (err)
udp_flush_pending_frames(sk);
else if (!corkreq)
- err = udp_push_pending_frames(sk, up);
+ err = udp_push_pending_frames(sk);
else if (unlikely(skb_queue_empty(&sk->sk_write_queue)))
up->pending = 0;
release_sock(sk);
@@ -684,7 +684,7 @@ out:
if (free)
kfree(ipc.opt);
if (!err) {
- UDP_INC_STATS_USER(UDP_MIB_OUTDATAGRAMS);
+ UDP_INC_STATS_USER(UDP_MIB_OUTDATAGRAMS, is_udplite);
return len;
}
/*
@@ -695,7 +695,7 @@ out:
* seems like overkill.
*/
if (err == -ENOBUFS || test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) {
- UDP_INC_STATS_USER(UDP_MIB_SNDBUFERRORS);
+ UDP_INC_STATS_USER(UDP_MIB_SNDBUFERRORS, is_udplite);
}
return err;
@@ -707,8 +707,8 @@ do_confirm:
goto out;
}
-static int udp_sendpage(struct sock *sk, struct page *page, int offset,
- size_t size, int flags)
+int udp_sendpage(struct sock *sk, struct page *page, int offset,
+ size_t size, int flags)
{
struct udp_sock *up = udp_sk(sk);
int ret;
@@ -747,7 +747,7 @@ static int udp_sendpage(struct sock *sk, struct page *page, int offset,
up->len += size;
if (!(up->corkflag || (flags&MSG_MORE)))
- ret = udp_push_pending_frames(sk, up);
+ ret = udp_push_pending_frames(sk);
if (!ret)
ret = size;
out:
@@ -795,29 +795,18 @@ int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
return(0);
}
-static __inline__ int __udp_checksum_complete(struct sk_buff *skb)
-{
- return __skb_checksum_complete(skb);
-}
-
-static __inline__ int udp_checksum_complete(struct sk_buff *skb)
-{
- return skb->ip_summed != CHECKSUM_UNNECESSARY &&
- __udp_checksum_complete(skb);
-}
-
/*
* This should be easy, if there is something there we
* return it, otherwise we block.
*/
-static int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
- size_t len, int noblock, int flags, int *addr_len)
+int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+ size_t len, int noblock, int flags, int *addr_len)
{
struct inet_sock *inet = inet_sk(sk);
struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name;
struct sk_buff *skb;
- int copied, err;
+ int copied, err, copy_only, is_udplite = IS_UDPLITE(sk);
/*
* Check any passed addresses
@@ -839,15 +828,25 @@ try_again:
msg->msg_flags |= MSG_TRUNC;
}
- if (skb->ip_summed==CHECKSUM_UNNECESSARY) {
- err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov,
- copied);
- } else if (msg->msg_flags&MSG_TRUNC) {
- if (__udp_checksum_complete(skb))
+ /*
+ * Decide whether to checksum and/or copy data.
+ *
+ * UDP: checksum may have been computed in HW,
+ * (re-)compute it if message is truncated.
+ * UDP-Lite: always needs to checksum, no HW support.
+ */
+ copy_only = (skb->ip_summed==CHECKSUM_UNNECESSARY);
+
+ if (is_udplite || (!copy_only && msg->msg_flags&MSG_TRUNC)) {
+ if (__udp_lib_checksum_complete(skb))
goto csum_copy_err;
- err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov,
- copied);
- } else {
+ copy_only = 1;
+ }
+
+ if (copy_only)
+ err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr),
+ msg->msg_iov, copied );
+ else {
err = skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov);
if (err == -EINVAL)
@@ -880,7 +879,7 @@ out:
return err;
csum_copy_err:
- UDP_INC_STATS_BH(UDP_MIB_INERRORS);
+ UDP_INC_STATS_BH(UDP_MIB_INERRORS, is_udplite);
skb_kill_datagram(sk, skb, flags);
@@ -912,11 +911,6 @@ int udp_disconnect(struct sock *sk, int flags)
return 0;
}
-static void udp_close(struct sock *sk, long timeout)
-{
- sk_common_release(sk);
-}
-
/* return:
* 1 if the the UDP system should process it
* 0 if we should drop this packet
@@ -928,23 +922,32 @@ static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb)
return 1;
#else
struct udp_sock *up = udp_sk(sk);
- struct udphdr *uh = skb->h.uh;
+ struct udphdr *uh;
struct iphdr *iph;
int iphlen, len;
- __u8 *udpdata = (__u8 *)uh + sizeof(struct udphdr);
- __be32 *udpdata32 = (__be32 *)udpdata;
+ __u8 *udpdata;
+ __be32 *udpdata32;
__u16 encap_type = up->encap_type;
/* if we're overly short, let UDP handle it */
- if (udpdata > skb->tail)
+ len = skb->len - sizeof(struct udphdr);
+ if (len <= 0)
return 1;
/* if this is not encapsulated socket, then just return now */
if (!encap_type)
return 1;
- len = skb->tail - udpdata;
+ /* If this is a paged skb, make sure we pull up
+ * whatever data we need to look at. */
+ if (!pskb_may_pull(skb, sizeof(struct udphdr) + min(len, 8)))
+ return 1;
+
+ /* Now we can get the pointers */
+ uh = skb->h.uh;
+ udpdata = (__u8 *)uh + sizeof(struct udphdr);
+ udpdata32 = (__be32 *)udpdata;
switch (encap_type) {
default:
@@ -1013,7 +1016,7 @@ static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb)
* Note that in the success and error cases, the skb is assumed to
* have either been requeued or freed.
*/
-static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
+int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
{
struct udp_sock *up = udp_sk(sk);
int rc;
@@ -1021,10 +1024,8 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
/*
* Charge it to the socket, dropping if the queue is full.
*/
- if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) {
- kfree_skb(skb);
- return -1;
- }
+ if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
+ goto drop;
nf_reset(skb);
if (up->encap_type) {
@@ -1048,31 +1049,68 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
if (ret < 0) {
/* process the ESP packet */
ret = xfrm4_rcv_encap(skb, up->encap_type);
- UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS);
+ UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag);
return -ret;
}
/* FALLTHROUGH -- it's a UDP Packet */
}
- if (sk->sk_filter && skb->ip_summed != CHECKSUM_UNNECESSARY) {
- if (__udp_checksum_complete(skb)) {
- UDP_INC_STATS_BH(UDP_MIB_INERRORS);
- kfree_skb(skb);
- return -1;
+ /*
+ * UDP-Lite specific tests, ignored on UDP sockets
+ */
+ if ((up->pcflag & UDPLITE_RECV_CC) && UDP_SKB_CB(skb)->partial_cov) {
+
+ /*
+ * MIB statistics other than incrementing the error count are
+ * disabled for the following two types of errors: these depend
+ * on the application settings, not on the functioning of the
+ * protocol stack as such.
+ *
+ * RFC 3828 here recommends (sec 3.3): "There should also be a
+ * way ... to ... at least let the receiving application block
+ * delivery of packets with coverage values less than a value
+ * provided by the application."
+ */
+ if (up->pcrlen == 0) { /* full coverage was set */
+ LIMIT_NETDEBUG(KERN_WARNING "UDPLITE: partial coverage "
+ "%d while full coverage %d requested\n",
+ UDP_SKB_CB(skb)->cscov, skb->len);
+ goto drop;
}
+ /* The next case involves violating the min. coverage requested
+ * by the receiver. This is subtle: if receiver wants x and x is
+ * greater than the buffersize/MTU then receiver will complain
+ * that it wants x while sender emits packets of smaller size y.
+ * Therefore the above ...()->partial_cov statement is essential.
+ */
+ if (UDP_SKB_CB(skb)->cscov < up->pcrlen) {
+ LIMIT_NETDEBUG(KERN_WARNING
+ "UDPLITE: coverage %d too small, need min %d\n",
+ UDP_SKB_CB(skb)->cscov, up->pcrlen);
+ goto drop;
+ }
+ }
+
+ if (sk->sk_filter && skb->ip_summed != CHECKSUM_UNNECESSARY) {
+ if (__udp_lib_checksum_complete(skb))
+ goto drop;
skb->ip_summed = CHECKSUM_UNNECESSARY;
}
if ((rc = sock_queue_rcv_skb(sk,skb)) < 0) {
/* Note that an ENOMEM error is charged twice */
if (rc == -ENOMEM)
- UDP_INC_STATS_BH(UDP_MIB_RCVBUFERRORS);
- UDP_INC_STATS_BH(UDP_MIB_INERRORS);
- kfree_skb(skb);
- return -1;
+ UDP_INC_STATS_BH(UDP_MIB_RCVBUFERRORS, up->pcflag);
+ goto drop;
}
- UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS);
+
+ UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag);
return 0;
+
+drop:
+ UDP_INC_STATS_BH(UDP_MIB_INERRORS, up->pcflag);
+ kfree_skb(skb);
+ return -1;
}
/*
@@ -1081,14 +1119,16 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
* Note: called only from the BH handler context,
* so we don't need to lock the hashes.
*/
-static int udp_v4_mcast_deliver(struct sk_buff *skb, struct udphdr *uh,
- __be32 saddr, __be32 daddr)
+static int __udp4_lib_mcast_deliver(struct sk_buff *skb,
+ struct udphdr *uh,
+ __be32 saddr, __be32 daddr,
+ struct hlist_head udptable[])
{
struct sock *sk;
int dif;
read_lock(&udp_hash_lock);
- sk = sk_head(&udp_hash[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)]);
+ sk = sk_head(&udptable[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)]);
dif = skb->dev->ifindex;
sk = udp_v4_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif);
if (sk) {
@@ -1122,65 +1162,75 @@ static int udp_v4_mcast_deliver(struct sk_buff *skb, struct udphdr *uh,
* Otherwise, csum completion requires chacksumming packet body,
* including udp header and folding it to skb->csum.
*/
-static void udp_checksum_init(struct sk_buff *skb, struct udphdr *uh,
- unsigned short ulen, __be32 saddr, __be32 daddr)
+static inline void udp4_csum_init(struct sk_buff *skb, struct udphdr *uh)
{
if (uh->check == 0) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
} else if (skb->ip_summed == CHECKSUM_COMPLETE) {
- if (!udp_check(uh, ulen, saddr, daddr, skb->csum))
+ if (!csum_tcpudp_magic(skb->nh.iph->saddr, skb->nh.iph->daddr,
+ skb->len, IPPROTO_UDP, skb->csum ))
skb->ip_summed = CHECKSUM_UNNECESSARY;
}
if (skb->ip_summed != CHECKSUM_UNNECESSARY)
- skb->csum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0);
+ skb->csum = csum_tcpudp_nofold(skb->nh.iph->saddr,
+ skb->nh.iph->daddr,
+ skb->len, IPPROTO_UDP, 0);
/* Probably, we should checksum udp header (it should be in cache
* in any case) and data in tiny packets (< rx copybreak).
*/
+
+ /* UDP = UDP-Lite with a non-partial checksum coverage */
+ UDP_SKB_CB(skb)->partial_cov = 0;
}
/*
* All we need to do is get the socket, and then do a checksum.
*/
-int udp_rcv(struct sk_buff *skb)
+int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
+ int is_udplite)
{
struct sock *sk;
- struct udphdr *uh;
+ struct udphdr *uh = skb->h.uh;
unsigned short ulen;
struct rtable *rt = (struct rtable*)skb->dst;
__be32 saddr = skb->nh.iph->saddr;
__be32 daddr = skb->nh.iph->daddr;
- int len = skb->len;
/*
- * Validate the packet and the UDP length.
+ * Validate the packet.
*/
if (!pskb_may_pull(skb, sizeof(struct udphdr)))
- goto no_header;
-
- uh = skb->h.uh;
+ goto drop; /* No space for header. */
ulen = ntohs(uh->len);
-
- if (ulen > len || ulen < sizeof(*uh))
+ if (ulen > skb->len)
goto short_packet;
- if (pskb_trim_rcsum(skb, ulen))
- goto short_packet;
+ if(! is_udplite ) { /* UDP validates ulen. */
+
+ if (ulen < sizeof(*uh) || pskb_trim_rcsum(skb, ulen))
+ goto short_packet;
- udp_checksum_init(skb, uh, ulen, saddr, daddr);
+ udp4_csum_init(skb, uh);
+
+ } else { /* UDP-Lite validates cscov. */
+ if (udplite4_csum_init(skb, uh))
+ goto csum_error;
+ }
if(rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))
- return udp_v4_mcast_deliver(skb, uh, saddr, daddr);
+ return __udp4_lib_mcast_deliver(skb, uh, saddr, daddr, udptable);
- sk = udp_v4_lookup(saddr, uh->source, daddr, uh->dest, skb->dev->ifindex);
+ sk = __udp4_lib_lookup(saddr, uh->source, daddr, uh->dest,
+ skb->dev->ifindex, udptable );
if (sk != NULL) {
int ret = udp_queue_rcv_skb(sk, skb);
sock_put(sk);
/* a return value > 0 means to resubmit the input, but
- * it it wants the return to be -protocol, or 0
+ * it wants the return to be -protocol, or 0
*/
if (ret > 0)
return -ret;
@@ -1192,10 +1242,10 @@ int udp_rcv(struct sk_buff *skb)
nf_reset(skb);
/* No socket. Drop packet silently, if checksum is wrong */
- if (udp_checksum_complete(skb))
+ if (udp_lib_checksum_complete(skb))
goto csum_error;
- UDP_INC_STATS_BH(UDP_MIB_NOPORTS);
+ UDP_INC_STATS_BH(UDP_MIB_NOPORTS, is_udplite);
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
/*
@@ -1206,36 +1256,40 @@ int udp_rcv(struct sk_buff *skb)
return(0);
short_packet:
- LIMIT_NETDEBUG(KERN_DEBUG "UDP: short packet: From %u.%u.%u.%u:%u %d/%d to %u.%u.%u.%u:%u\n",
+ LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: short packet: From %u.%u.%u.%u:%u %d/%d to %u.%u.%u.%u:%u\n",
+ is_udplite? "-Lite" : "",
NIPQUAD(saddr),
ntohs(uh->source),
ulen,
- len,
+ skb->len,
NIPQUAD(daddr),
ntohs(uh->dest));
-no_header:
- UDP_INC_STATS_BH(UDP_MIB_INERRORS);
- kfree_skb(skb);
- return(0);
+ goto drop;
csum_error:
/*
* RFC1122: OK. Discards the bad packet silently (as far as
* the network is concerned, anyway) as per 4.1.3.4 (MUST).
*/
- LIMIT_NETDEBUG(KERN_DEBUG "UDP: bad checksum. From %d.%d.%d.%d:%d to %d.%d.%d.%d:%d ulen %d\n",
+ LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: bad checksum. From %d.%d.%d.%d:%d to %d.%d.%d.%d:%d ulen %d\n",
+ is_udplite? "-Lite" : "",
NIPQUAD(saddr),
ntohs(uh->source),
NIPQUAD(daddr),
ntohs(uh->dest),
ulen);
drop:
- UDP_INC_STATS_BH(UDP_MIB_INERRORS);
+ UDP_INC_STATS_BH(UDP_MIB_INERRORS, is_udplite);
kfree_skb(skb);
return(0);
}
-static int udp_destroy_sock(struct sock *sk)
+__inline__ int udp_rcv(struct sk_buff *skb)
+{
+ return __udp4_lib_rcv(skb, udp_hash, 0);
+}
+
+int udp_destroy_sock(struct sock *sk)
{
lock_sock(sk);
udp_flush_pending_frames(sk);
@@ -1246,8 +1300,9 @@ static int udp_destroy_sock(struct sock *sk)
/*
* Socket option code for UDP
*/
-static int do_udp_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen)
+int udp_lib_setsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int optlen,
+ int (*push_pending_frames)(struct sock *))
{
struct udp_sock *up = udp_sk(sk);
int val;
@@ -1266,7 +1321,7 @@ static int do_udp_setsockopt(struct sock *sk, int level, int optname,
} else {
up->corkflag = 0;
lock_sock(sk);
- udp_push_pending_frames(sk, up);
+ (*push_pending_frames)(sk);
release_sock(sk);
}
break;
@@ -1284,6 +1339,32 @@ static int do_udp_setsockopt(struct sock *sk, int level, int optname,
}
break;
+ /*
+ * UDP-Lite's partial checksum coverage (RFC 3828).
+ */
+ /* The sender sets actual checksum coverage length via this option.
+ * The case coverage > packet length is handled by send module. */
+ case UDPLITE_SEND_CSCOV:
+ if (!up->pcflag) /* Disable the option on UDP sockets */
+ return -ENOPROTOOPT;
+ if (val != 0 && val < 8) /* Illegal coverage: use default (8) */
+ val = 8;
+ up->pcslen = val;
+ up->pcflag |= UDPLITE_SEND_CC;
+ break;
+
+ /* The receiver specifies a minimum checksum coverage value. To make
+ * sense, this should be set to at least 8 (as done below). If zero is
+ * used, this again means full checksum coverage. */
+ case UDPLITE_RECV_CSCOV:
+ if (!up->pcflag) /* Disable the option on UDP sockets */
+ return -ENOPROTOOPT;
+ if (val != 0 && val < 8) /* Avoid silly minimal values. */
+ val = 8;
+ up->pcrlen = val;
+ up->pcflag |= UDPLITE_RECV_CC;
+ break;
+
default:
err = -ENOPROTOOPT;
break;
@@ -1292,26 +1373,28 @@ static int do_udp_setsockopt(struct sock *sk, int level, int optname,
return err;
}
-static int udp_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen)
+int udp_setsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int optlen)
{
- if (level != SOL_UDP)
- return ip_setsockopt(sk, level, optname, optval, optlen);
- return do_udp_setsockopt(sk, level, optname, optval, optlen);
+ if (level == SOL_UDP || level == SOL_UDPLITE)
+ return udp_lib_setsockopt(sk, level, optname, optval, optlen,
+ udp_push_pending_frames);
+ return ip_setsockopt(sk, level, optname, optval, optlen);
}
#ifdef CONFIG_COMPAT
-static int compat_udp_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen)
+int compat_udp_setsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int optlen)
{
- if (level != SOL_UDP)
- return compat_ip_setsockopt(sk, level, optname, optval, optlen);
- return do_udp_setsockopt(sk, level, optname, optval, optlen);
+ if (level == SOL_UDP || level == SOL_UDPLITE)
+ return udp_lib_setsockopt(sk, level, optname, optval, optlen,
+ udp_push_pending_frames);
+ return compat_ip_setsockopt(sk, level, optname, optval, optlen);
}
#endif
-static int do_udp_getsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int __user *optlen)
+int udp_lib_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen)
{
struct udp_sock *up = udp_sk(sk);
int val, len;
@@ -1333,6 +1416,16 @@ static int do_udp_getsockopt(struct sock *sk, int level, int optname,
val = up->encap_type;
break;
+ /* The following two cannot be changed on UDP sockets, the return is
+ * always 0 (which corresponds to the full checksum coverage of UDP). */
+ case UDPLITE_SEND_CSCOV:
+ val = up->pcslen;
+ break;
+
+ case UDPLITE_RECV_CSCOV:
+ val = up->pcrlen;
+ break;
+
default:
return -ENOPROTOOPT;
};
@@ -1344,21 +1437,21 @@ static int do_udp_getsockopt(struct sock *sk, int level, int optname,
return 0;
}
-static int udp_getsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int __user *optlen)
+int udp_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen)
{
- if (level != SOL_UDP)
- return ip_getsockopt(sk, level, optname, optval, optlen);
- return do_udp_getsockopt(sk, level, optname, optval, optlen);
+ if (level == SOL_UDP || level == SOL_UDPLITE)
+ return udp_lib_getsockopt(sk, level, optname, optval, optlen);
+ return ip_getsockopt(sk, level, optname, optval, optlen);
}
#ifdef CONFIG_COMPAT
-static int compat_udp_getsockopt(struct sock *sk, int level, int optname,
+int compat_udp_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen)
{
- if (level != SOL_UDP)
- return compat_ip_getsockopt(sk, level, optname, optval, optlen);
- return do_udp_getsockopt(sk, level, optname, optval, optlen);
+ if (level == SOL_UDP || level == SOL_UDPLITE)
+ return udp_lib_getsockopt(sk, level, optname, optval, optlen);
+ return compat_ip_getsockopt(sk, level, optname, optval, optlen);
}
#endif
/**
@@ -1378,7 +1471,8 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait)
{
unsigned int mask = datagram_poll(file, sock, wait);
struct sock *sk = sock->sk;
-
+ int is_lite = IS_UDPLITE(sk);
+
/* Check for false positives due to checksum errors */
if ( (mask & POLLRDNORM) &&
!(file->f_flags & O_NONBLOCK) &&
@@ -1388,8 +1482,8 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait)
spin_lock_bh(&rcvq->lock);
while ((skb = skb_peek(rcvq)) != NULL) {
- if (udp_checksum_complete(skb)) {
- UDP_INC_STATS_BH(UDP_MIB_INERRORS);
+ if (udp_lib_checksum_complete(skb)) {
+ UDP_INC_STATS_BH(UDP_MIB_INERRORS, is_lite);
__skb_unlink(skb, rcvq);
kfree_skb(skb);
} else {
@@ -1411,7 +1505,7 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait)
struct proto udp_prot = {
.name = "UDP",
.owner = THIS_MODULE,
- .close = udp_close,
+ .close = udp_lib_close,
.connect = ip4_datagram_connect,
.disconnect = udp_disconnect,
.ioctl = udp_ioctl,
@@ -1422,8 +1516,8 @@ struct proto udp_prot = {
.recvmsg = udp_recvmsg,
.sendpage = udp_sendpage,
.backlog_rcv = udp_queue_rcv_skb,
- .hash = udp_v4_hash,
- .unhash = udp_v4_unhash,
+ .hash = udp_lib_hash,
+ .unhash = udp_lib_unhash,
.get_port = udp_v4_get_port,
.obj_size = sizeof(struct udp_sock),
#ifdef CONFIG_COMPAT
@@ -1442,7 +1536,7 @@ static struct sock *udp_get_first(struct seq_file *seq)
for (state->bucket = 0; state->bucket < UDP_HTABLE_SIZE; ++state->bucket) {
struct hlist_node *node;
- sk_for_each(sk, node, &udp_hash[state->bucket]) {
+ sk_for_each(sk, node, state->hashtable + state->bucket) {
if (sk->sk_family == state->family)
goto found;
}
@@ -1463,7 +1557,7 @@ try_again:
} while (sk && sk->sk_family != state->family);
if (!sk && ++state->bucket < UDP_HTABLE_SIZE) {
- sk = sk_head(&udp_hash[state->bucket]);
+ sk = sk_head(state->hashtable + state->bucket);
goto try_again;
}
return sk;
@@ -1513,6 +1607,7 @@ static int udp_seq_open(struct inode *inode, struct file *file)
if (!s)
goto out;
s->family = afinfo->family;
+ s->hashtable = afinfo->hashtable;
s->seq_ops.start = udp_seq_start;
s->seq_ops.next = udp_seq_next;
s->seq_ops.show = afinfo->seq_show;
@@ -1579,7 +1674,7 @@ static void udp4_format_sock(struct sock *sp, char *tmpbuf, int bucket)
atomic_read(&sp->sk_refcnt), sp);
}
-static int udp4_seq_show(struct seq_file *seq, void *v)
+int udp4_seq_show(struct seq_file *seq, void *v)
{
if (v == SEQ_START_TOKEN)
seq_printf(seq, "%-127s\n",
@@ -1602,6 +1697,7 @@ static struct udp_seq_afinfo udp4_seq_afinfo = {
.owner = THIS_MODULE,
.name = "udp",
.family = AF_INET,
+ .hashtable = udp_hash,
.seq_show = udp4_seq_show,
.seq_fops = &udp4_seq_fops,
};
@@ -1624,6 +1720,8 @@ EXPORT_SYMBOL(udp_ioctl);
EXPORT_SYMBOL(udp_get_port);
EXPORT_SYMBOL(udp_prot);
EXPORT_SYMBOL(udp_sendmsg);
+EXPORT_SYMBOL(udp_lib_getsockopt);
+EXPORT_SYMBOL(udp_lib_setsockopt);
EXPORT_SYMBOL(udp_poll);
#ifdef CONFIG_PROC_FS
diff --git a/net/ipv4/udp_impl.h b/net/ipv4/udp_impl.h
new file mode 100644
index 000000000000..f6f4277ba6dc
--- /dev/null
+++ b/net/ipv4/udp_impl.h
@@ -0,0 +1,38 @@
+#ifndef _UDP4_IMPL_H
+#define _UDP4_IMPL_H
+#include <net/udp.h>
+#include <net/udplite.h>
+#include <net/protocol.h>
+#include <net/inet_common.h>
+
+extern int __udp4_lib_rcv(struct sk_buff *, struct hlist_head [], int );
+extern void __udp4_lib_err(struct sk_buff *, u32, struct hlist_head []);
+
+extern int __udp_lib_get_port(struct sock *sk, unsigned short snum,
+ struct hlist_head udptable[], int *port_rover,
+ int (*)(const struct sock*,const struct sock*));
+extern int ipv4_rcv_saddr_equal(const struct sock *, const struct sock *);
+
+
+extern int udp_setsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int optlen);
+extern int udp_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen);
+
+#ifdef CONFIG_COMPAT
+extern int compat_udp_setsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int optlen);
+extern int compat_udp_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen);
+#endif
+extern int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+ size_t len, int noblock, int flags, int *addr_len);
+extern int udp_sendpage(struct sock *sk, struct page *page, int offset,
+ size_t size, int flags);
+extern int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb);
+extern int udp_destroy_sock(struct sock *sk);
+
+#ifdef CONFIG_PROC_FS
+extern int udp4_seq_show(struct seq_file *seq, void *v);
+#endif
+#endif /* _UDP4_IMPL_H */
diff --git a/net/ipv4/udplite.c b/net/ipv4/udplite.c
new file mode 100644
index 000000000000..b28fe1edf98b
--- /dev/null
+++ b/net/ipv4/udplite.c
@@ -0,0 +1,119 @@
+/*
+ * UDPLITE An implementation of the UDP-Lite protocol (RFC 3828).
+ *
+ * Version: $Id: udplite.c,v 1.25 2006/10/19 07:22:36 gerrit Exp $
+ *
+ * Authors: Gerrit Renker <gerrit@erg.abdn.ac.uk>
+ *
+ * Changes:
+ * Fixes:
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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 "udp_impl.h"
+DEFINE_SNMP_STAT(struct udp_mib, udplite_statistics) __read_mostly;
+
+struct hlist_head udplite_hash[UDP_HTABLE_SIZE];
+static int udplite_port_rover;
+
+int udplite_get_port(struct sock *sk, unsigned short p,
+ int (*c)(const struct sock *, const struct sock *))
+{
+ return __udp_lib_get_port(sk, p, udplite_hash, &udplite_port_rover, c);
+}
+
+static int udplite_v4_get_port(struct sock *sk, unsigned short snum)
+{
+ return udplite_get_port(sk, snum, ipv4_rcv_saddr_equal);
+}
+
+static int udplite_rcv(struct sk_buff *skb)
+{
+ return __udp4_lib_rcv(skb, udplite_hash, 1);
+}
+
+static void udplite_err(struct sk_buff *skb, u32 info)
+{
+ return __udp4_lib_err(skb, info, udplite_hash);
+}
+
+static struct net_protocol udplite_protocol = {
+ .handler = udplite_rcv,
+ .err_handler = udplite_err,
+ .no_policy = 1,
+};
+
+struct proto udplite_prot = {
+ .name = "UDP-Lite",
+ .owner = THIS_MODULE,
+ .close = udp_lib_close,
+ .connect = ip4_datagram_connect,
+ .disconnect = udp_disconnect,
+ .ioctl = udp_ioctl,
+ .init = udplite_sk_init,
+ .destroy = udp_destroy_sock,
+ .setsockopt = udp_setsockopt,
+ .getsockopt = udp_getsockopt,
+ .sendmsg = udp_sendmsg,
+ .recvmsg = udp_recvmsg,
+ .sendpage = udp_sendpage,
+ .backlog_rcv = udp_queue_rcv_skb,
+ .hash = udp_lib_hash,
+ .unhash = udp_lib_unhash,
+ .get_port = udplite_v4_get_port,
+ .obj_size = sizeof(struct udp_sock),
+#ifdef CONFIG_COMPAT
+ .compat_setsockopt = compat_udp_setsockopt,
+ .compat_getsockopt = compat_udp_getsockopt,
+#endif
+};
+
+static struct inet_protosw udplite4_protosw = {
+ .type = SOCK_DGRAM,
+ .protocol = IPPROTO_UDPLITE,
+ .prot = &udplite_prot,
+ .ops = &inet_dgram_ops,
+ .capability = -1,
+ .no_check = 0, /* must checksum (RFC 3828) */
+ .flags = INET_PROTOSW_PERMANENT,
+};
+
+#ifdef CONFIG_PROC_FS
+static struct file_operations udplite4_seq_fops;
+static struct udp_seq_afinfo udplite4_seq_afinfo = {
+ .owner = THIS_MODULE,
+ .name = "udplite",
+ .family = AF_INET,
+ .hashtable = udplite_hash,
+ .seq_show = udp4_seq_show,
+ .seq_fops = &udplite4_seq_fops,
+};
+#endif
+
+void __init udplite4_register(void)
+{
+ if (proto_register(&udplite_prot, 1))
+ goto out_register_err;
+
+ if (inet_add_protocol(&udplite_protocol, IPPROTO_UDPLITE) < 0)
+ goto out_unregister_proto;
+
+ inet_register_protosw(&udplite4_protosw);
+
+#ifdef CONFIG_PROC_FS
+ if (udp_proc_register(&udplite4_seq_afinfo)) /* udplite4_proc_init() */
+ printk(KERN_ERR "%s: Cannot register /proc!\n", __FUNCTION__);
+#endif
+ return;
+
+out_unregister_proto:
+ proto_unregister(&udplite_prot);
+out_register_err:
+ printk(KERN_CRIT "%s: Cannot add UDP-Lite protocol.\n", __FUNCTION__);
+}
+
+EXPORT_SYMBOL(udplite_hash);
+EXPORT_SYMBOL(udplite_prot);
+EXPORT_SYMBOL(udplite_get_port);
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 1bed0cdf53e3..d4107bb701b5 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -72,8 +72,8 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
struct dst_entry *dst, *dst_prev;
struct rtable *rt0 = (struct rtable*)(*dst_p);
struct rtable *rt = rt0;
- u32 remote = fl->fl4_dst;
- u32 local = fl->fl4_src;
+ __be32 remote = fl->fl4_dst;
+ __be32 local = fl->fl4_src;
struct flowi fl_tunnel = {
.nl_u = {
.ip4_u = {
@@ -199,11 +199,12 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl)
if (!(iph->frag_off & htons(IP_MF | IP_OFFSET))) {
switch (iph->protocol) {
case IPPROTO_UDP:
+ case IPPROTO_UDPLITE:
case IPPROTO_TCP:
case IPPROTO_SCTP:
case IPPROTO_DCCP:
if (pskb_may_pull(skb, xprth + 4 - skb->data)) {
- u16 *ports = (u16 *)xprth;
+ __be16 *ports = (__be16 *)xprth;
fl->fl_ip_sport = ports[0];
fl->fl_ip_dport = ports[1];
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index 6e48f52e197c..deb4101a2a81 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -196,10 +196,3 @@ config IPV6_SUBTREES
If unsure, say N.
-config IPV6_ROUTE_FWMARK
- bool "IPv6: use netfilter MARK value as routing key"
- depends on IPV6_MULTIPLE_TABLES && NETFILTER
- ---help---
- If you say Y here, you will be able to specify different routes for
- packets with different mark values (see iptables(8), MARK target).
-
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
index addcc011bc01..8bacda109b7f 100644
--- a/net/ipv6/Makefile
+++ b/net/ipv6/Makefile
@@ -5,8 +5,8 @@
obj-$(CONFIG_IPV6) += ipv6.o
ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \
- route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o raw.o \
- protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \
+ route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o udplite.o \
+ raw.o protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \
exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \
ip6_flowlabel.o ipv6_syms.o inet6_connection_sock.o
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index b312a5f7a759..a5e8d207a51b 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -232,7 +232,7 @@ static inline unsigned ipv6_addr_scope2type(unsigned scope)
int __ipv6_addr_type(const struct in6_addr *addr)
{
- u32 st;
+ __be32 st;
st = addr->s6_addr32[0];
@@ -1164,7 +1164,7 @@ record_it:
int ipv6_get_saddr(struct dst_entry *dst,
struct in6_addr *daddr, struct in6_addr *saddr)
{
- return ipv6_dev_get_saddr(dst ? ((struct rt6_info *)dst)->rt6i_idev->dev : NULL, daddr, saddr);
+ return ipv6_dev_get_saddr(dst ? ip6_dst_idev(dst)->dev : NULL, daddr, saddr);
}
@@ -3098,10 +3098,9 @@ static inline int rt_scope(int ifa_scope)
static inline int inet6_ifaddr_msgsize(void)
{
- return nlmsg_total_size(sizeof(struct ifaddrmsg) +
- nla_total_size(16) +
- nla_total_size(sizeof(struct ifa_cacheinfo)) +
- 128);
+ return NLMSG_ALIGN(sizeof(struct ifaddrmsg))
+ + nla_total_size(16) /* IFA_ADDRESS */
+ + nla_total_size(sizeof(struct ifa_cacheinfo));
}
static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
@@ -3329,10 +3328,8 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh,
err = inet6_fill_ifaddr(skb, ifa, NETLINK_CB(in_skb).pid,
nlh->nlmsg_seq, RTM_NEWADDR, 0);
- if (err < 0) {
- kfree_skb(skb);
- goto errout_ifa;
- }
+ /* failure implies BUG in inet6_ifaddr_msgsize() */
+ BUG_ON(err < 0);
err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid);
errout_ifa:
@@ -3351,10 +3348,8 @@ static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa)
goto errout;
err = inet6_fill_ifaddr(skb, ifa, 0, 0, event, 0);
- if (err < 0) {
- kfree_skb(skb);
- goto errout;
- }
+ /* failure implies BUG in inet6_ifaddr_msgsize() */
+ BUG_ON(err < 0);
err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
errout:
@@ -3365,6 +3360,8 @@ errout:
static void inline ipv6_store_devconf(struct ipv6_devconf *cnf,
__s32 *array, int bytes)
{
+ BUG_ON(bytes < (DEVCONF_MAX * 4));
+
memset(array, 0, bytes);
array[DEVCONF_FORWARDING] = cnf->forwarding;
array[DEVCONF_HOPLIMIT] = cnf->hop_limit;
@@ -3397,80 +3394,76 @@ static void inline ipv6_store_devconf(struct ipv6_devconf *cnf,
array[DEVCONF_PROXY_NDP] = cnf->proxy_ndp;
}
-/* Maximum length of ifinfomsg attributes */
-#define INET6_IFINFO_RTA_SPACE \
- RTA_SPACE(IFNAMSIZ) /* IFNAME */ + \
- RTA_SPACE(MAX_ADDR_LEN) /* ADDRESS */ + \
- RTA_SPACE(sizeof(u32)) /* MTU */ + \
- RTA_SPACE(sizeof(int)) /* LINK */ + \
- RTA_SPACE(0) /* PROTINFO */ + \
- RTA_SPACE(sizeof(u32)) /* FLAGS */ + \
- RTA_SPACE(sizeof(struct ifla_cacheinfo)) /* CACHEINFO */ + \
- RTA_SPACE(sizeof(__s32[DEVCONF_MAX])) /* CONF */
+static inline size_t inet6_if_nlmsg_size(void)
+{
+ return NLMSG_ALIGN(sizeof(struct ifinfomsg))
+ + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
+ + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */
+ + nla_total_size(4) /* IFLA_MTU */
+ + nla_total_size(4) /* IFLA_LINK */
+ + nla_total_size( /* IFLA_PROTINFO */
+ nla_total_size(4) /* IFLA_INET6_FLAGS */
+ + nla_total_size(sizeof(struct ifla_cacheinfo))
+ + nla_total_size(DEVCONF_MAX * 4) /* IFLA_INET6_CONF */
+ );
+}
static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
u32 pid, u32 seq, int event, unsigned int flags)
{
- struct net_device *dev = idev->dev;
- __s32 *array = NULL;
- struct ifinfomsg *r;
- struct nlmsghdr *nlh;
- unsigned char *b = skb->tail;
- struct rtattr *subattr;
- __u32 mtu = dev->mtu;
- struct ifla_cacheinfo ci;
-
- nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*r), flags);
- r = NLMSG_DATA(nlh);
- r->ifi_family = AF_INET6;
- r->__ifi_pad = 0;
- r->ifi_type = dev->type;
- r->ifi_index = dev->ifindex;
- r->ifi_flags = dev_get_flags(dev);
- r->ifi_change = 0;
-
- RTA_PUT(skb, IFLA_IFNAME, strlen(dev->name)+1, dev->name);
+ struct net_device *dev = idev->dev;
+ struct nlattr *conf;
+ struct ifinfomsg *hdr;
+ struct nlmsghdr *nlh;
+ void *protoinfo;
+ struct ifla_cacheinfo ci;
+
+ nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags);
+ if (nlh == NULL)
+ return -ENOBUFS;
+
+ hdr = nlmsg_data(nlh);
+ hdr->ifi_family = AF_INET6;
+ hdr->__ifi_pad = 0;
+ hdr->ifi_type = dev->type;
+ hdr->ifi_index = dev->ifindex;
+ hdr->ifi_flags = dev_get_flags(dev);
+ hdr->ifi_change = 0;
+
+ NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name);
if (dev->addr_len)
- RTA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr);
+ NLA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr);
- RTA_PUT(skb, IFLA_MTU, sizeof(mtu), &mtu);
+ NLA_PUT_U32(skb, IFLA_MTU, dev->mtu);
if (dev->ifindex != dev->iflink)
- RTA_PUT(skb, IFLA_LINK, sizeof(int), &dev->iflink);
-
- subattr = (struct rtattr*)skb->tail;
+ NLA_PUT_U32(skb, IFLA_LINK, dev->iflink);
- RTA_PUT(skb, IFLA_PROTINFO, 0, NULL);
+ protoinfo = nla_nest_start(skb, IFLA_PROTINFO);
+ if (protoinfo == NULL)
+ goto nla_put_failure;
- /* return the device flags */
- RTA_PUT(skb, IFLA_INET6_FLAGS, sizeof(__u32), &idev->if_flags);
+ NLA_PUT_U32(skb, IFLA_INET6_FLAGS, idev->if_flags);
- /* return interface cacheinfo */
ci.max_reasm_len = IPV6_MAXPLEN;
ci.tstamp = (__u32)(TIME_DELTA(idev->tstamp, INITIAL_JIFFIES) / HZ * 100
+ TIME_DELTA(idev->tstamp, INITIAL_JIFFIES) % HZ * 100 / HZ);
ci.reachable_time = idev->nd_parms->reachable_time;
ci.retrans_time = idev->nd_parms->retrans_time;
- RTA_PUT(skb, IFLA_INET6_CACHEINFO, sizeof(ci), &ci);
-
- /* return the device sysctl params */
- if ((array = kmalloc(DEVCONF_MAX * sizeof(*array), GFP_ATOMIC)) == NULL)
- goto rtattr_failure;
- ipv6_store_devconf(&idev->cnf, array, DEVCONF_MAX * sizeof(*array));
- RTA_PUT(skb, IFLA_INET6_CONF, DEVCONF_MAX * sizeof(*array), array);
+ NLA_PUT(skb, IFLA_INET6_CACHEINFO, sizeof(ci), &ci);
+
+ conf = nla_reserve(skb, IFLA_INET6_CONF, DEVCONF_MAX * sizeof(s32));
+ if (conf == NULL)
+ goto nla_put_failure;
+ ipv6_store_devconf(&idev->cnf, nla_data(conf), nla_len(conf));
/* XXX - Statistics/MC not implemented */
- subattr->rta_len = skb->tail - (u8*)subattr;
- nlh->nlmsg_len = skb->tail - b;
- kfree(array);
- return skb->len;
+ nla_nest_end(skb, protoinfo);
+ return nlmsg_end(skb, nlh);
-nlmsg_failure:
-rtattr_failure:
- kfree(array);
- skb_trim(skb, b - skb->data);
- return -1;
+nla_put_failure:
+ return nlmsg_cancel(skb, nlh);
}
static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
@@ -3501,18 +3494,15 @@ static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
void inet6_ifinfo_notify(int event, struct inet6_dev *idev)
{
struct sk_buff *skb;
- int payload = sizeof(struct ifinfomsg) + INET6_IFINFO_RTA_SPACE;
int err = -ENOBUFS;
- skb = nlmsg_new(nlmsg_total_size(payload), GFP_ATOMIC);
+ skb = nlmsg_new(inet6_if_nlmsg_size(), GFP_ATOMIC);
if (skb == NULL)
goto errout;
err = inet6_fill_ifinfo(skb, idev, 0, 0, event, 0);
- if (err < 0) {
- kfree_skb(skb);
- goto errout;
- }
+ /* failure implies BUG in inet6_if_nlmsg_size() */
+ BUG_ON(err < 0);
err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
errout:
@@ -3520,22 +3510,26 @@ errout:
rtnl_set_sk_err(RTNLGRP_IPV6_IFADDR, err);
}
-/* Maximum length of prefix_cacheinfo attributes */
-#define INET6_PREFIX_RTA_SPACE \
- RTA_SPACE(sizeof(((struct prefix_info *)NULL)->prefix)) /* ADDRESS */ + \
- RTA_SPACE(sizeof(struct prefix_cacheinfo)) /* CACHEINFO */
+static inline size_t inet6_prefix_nlmsg_size(void)
+{
+ return NLMSG_ALIGN(sizeof(struct prefixmsg))
+ + nla_total_size(sizeof(struct in6_addr))
+ + nla_total_size(sizeof(struct prefix_cacheinfo));
+}
static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev,
- struct prefix_info *pinfo, u32 pid, u32 seq,
- int event, unsigned int flags)
+ struct prefix_info *pinfo, u32 pid, u32 seq,
+ int event, unsigned int flags)
{
- struct prefixmsg *pmsg;
- struct nlmsghdr *nlh;
- unsigned char *b = skb->tail;
+ struct prefixmsg *pmsg;
+ struct nlmsghdr *nlh;
struct prefix_cacheinfo ci;
- nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*pmsg), flags);
- pmsg = NLMSG_DATA(nlh);
+ nlh = nlmsg_put(skb, pid, seq, event, sizeof(*pmsg), flags);
+ if (nlh == NULL)
+ return -ENOBUFS;
+
+ pmsg = nlmsg_data(nlh);
pmsg->prefix_family = AF_INET6;
pmsg->prefix_pad1 = 0;
pmsg->prefix_pad2 = 0;
@@ -3543,44 +3537,37 @@ static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev,
pmsg->prefix_len = pinfo->prefix_len;
pmsg->prefix_type = pinfo->type;
pmsg->prefix_pad3 = 0;
-
pmsg->prefix_flags = 0;
if (pinfo->onlink)
pmsg->prefix_flags |= IF_PREFIX_ONLINK;
if (pinfo->autoconf)
pmsg->prefix_flags |= IF_PREFIX_AUTOCONF;
- RTA_PUT(skb, PREFIX_ADDRESS, sizeof(pinfo->prefix), &pinfo->prefix);
+ NLA_PUT(skb, PREFIX_ADDRESS, sizeof(pinfo->prefix), &pinfo->prefix);
ci.preferred_time = ntohl(pinfo->prefered);
ci.valid_time = ntohl(pinfo->valid);
- RTA_PUT(skb, PREFIX_CACHEINFO, sizeof(ci), &ci);
+ NLA_PUT(skb, PREFIX_CACHEINFO, sizeof(ci), &ci);
- nlh->nlmsg_len = skb->tail - b;
- return skb->len;
+ return nlmsg_end(skb, nlh);
-nlmsg_failure:
-rtattr_failure:
- skb_trim(skb, b - skb->data);
- return -1;
+nla_put_failure:
+ return nlmsg_cancel(skb, nlh);
}
static void inet6_prefix_notify(int event, struct inet6_dev *idev,
struct prefix_info *pinfo)
{
struct sk_buff *skb;
- int payload = sizeof(struct prefixmsg) + INET6_PREFIX_RTA_SPACE;
int err = -ENOBUFS;
- skb = nlmsg_new(nlmsg_total_size(payload), GFP_ATOMIC);
+ skb = nlmsg_new(inet6_prefix_nlmsg_size(), GFP_ATOMIC);
if (skb == NULL)
goto errout;
err = inet6_fill_prefix(skb, idev, pinfo, 0, 0, event, 0);
- if (err < 0) {
- kfree_skb(skb);
- goto errout;
- }
+ /* failure implies BUG in inet6_prefix_nlmsg_size() */
+ BUG_ON(err < 0);
err = rtnl_notify(skb, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC);
errout:
@@ -3982,10 +3969,9 @@ static void addrconf_sysctl_register(struct inet6_dev *idev, struct ipv6_devconf
struct addrconf_sysctl_table *t;
char *dev_name = NULL;
- t = kmalloc(sizeof(*t), GFP_KERNEL);
+ t = kmemdup(&addrconf_sysctl, sizeof(*t), GFP_KERNEL);
if (t == NULL)
return;
- memcpy(t, &addrconf_sysctl, sizeof(*t));
for (i=0; t->addrconf_vars[i].data; i++) {
t->addrconf_vars[i].data += (char*)p - (char*)&ipv6_devconf;
t->addrconf_vars[i].de = NULL;
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 858cae29581c..87c8f54872b7 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -49,6 +49,7 @@
#include <net/ip.h>
#include <net/ipv6.h>
#include <net/udp.h>
+#include <net/udplite.h>
#include <net/tcp.h>
#include <net/ipip.h>
#include <net/protocol.h>
@@ -221,7 +222,7 @@ lookup_protocol:
* the user to assign a number at socket
* creation time automatically shares.
*/
- inet->sport = ntohs(inet->num);
+ inet->sport = htons(inet->num);
sk->sk_prot->hash(sk);
}
if (sk->sk_prot->init) {
@@ -341,7 +342,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
sk->sk_userlocks |= SOCK_BINDADDR_LOCK;
if (snum)
sk->sk_userlocks |= SOCK_BINDPORT_LOCK;
- inet->sport = ntohs(inet->num);
+ inet->sport = htons(inet->num);
inet->dport = 0;
inet->daddr = 0;
out:
@@ -678,7 +679,7 @@ int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb)
if (np->rxopt.all) {
if ((opt->hop && (np->rxopt.bits.hopopts ||
np->rxopt.bits.ohopopts)) ||
- ((IPV6_FLOWINFO_MASK & *(u32*)skb->nh.raw) &&
+ ((IPV6_FLOWINFO_MASK & *(__be32*)skb->nh.raw) &&
np->rxopt.bits.rxflow) ||
(opt->srcrt && (np->rxopt.bits.srcrt ||
np->rxopt.bits.osrcrt)) ||
@@ -737,8 +738,13 @@ static int __init init_ipv6_mibs(void)
if (snmp6_mib_init((void **)udp_stats_in6, sizeof (struct udp_mib),
__alignof__(struct udp_mib)) < 0)
goto err_udp_mib;
+ if (snmp6_mib_init((void **)udplite_stats_in6, sizeof (struct udp_mib),
+ __alignof__(struct udp_mib)) < 0)
+ goto err_udplite_mib;
return 0;
+err_udplite_mib:
+ snmp6_mib_free((void **)udp_stats_in6);
err_udp_mib:
snmp6_mib_free((void **)icmpv6_statistics);
err_icmp_mib:
@@ -753,6 +759,7 @@ static void cleanup_ipv6_mibs(void)
snmp6_mib_free((void **)ipv6_statistics);
snmp6_mib_free((void **)icmpv6_statistics);
snmp6_mib_free((void **)udp_stats_in6);
+ snmp6_mib_free((void **)udplite_stats_in6);
}
static int __init inet6_init(void)
@@ -780,10 +787,14 @@ static int __init inet6_init(void)
if (err)
goto out_unregister_tcp_proto;
- err = proto_register(&rawv6_prot, 1);
+ err = proto_register(&udplitev6_prot, 1);
if (err)
goto out_unregister_udp_proto;
+ err = proto_register(&rawv6_prot, 1);
+ if (err)
+ goto out_unregister_udplite_proto;
+
/* Register the socket-side information for inet6_create. */
for(r = &inetsw6[0]; r < &inetsw6[SOCK_MAX]; ++r)
@@ -837,6 +848,8 @@ static int __init inet6_init(void)
goto proc_tcp6_fail;
if (udp6_proc_init())
goto proc_udp6_fail;
+ if (udplite6_proc_init())
+ goto proc_udplite6_fail;
if (ipv6_misc_proc_init())
goto proc_misc6_fail;
@@ -862,6 +875,7 @@ static int __init inet6_init(void)
/* Init v6 transport protocols. */
udpv6_init();
+ udplitev6_init();
tcpv6_init();
ipv6_packet_init();
@@ -879,6 +893,8 @@ proc_if6_fail:
proc_anycast6_fail:
ipv6_misc_proc_exit();
proc_misc6_fail:
+ udplite6_proc_exit();
+proc_udplite6_fail:
udp6_proc_exit();
proc_udp6_fail:
tcp6_proc_exit();
@@ -902,6 +918,8 @@ out_unregister_sock:
sock_unregister(PF_INET6);
out_unregister_raw_proto:
proto_unregister(&rawv6_prot);
+out_unregister_udplite_proto:
+ proto_unregister(&udplitev6_prot);
out_unregister_udp_proto:
proto_unregister(&udpv6_prot);
out_unregister_tcp_proto:
@@ -919,6 +937,7 @@ static void __exit inet6_exit(void)
ac6_proc_exit();
ipv6_misc_proc_exit();
udp6_proc_exit();
+ udplite6_proc_exit();
tcp6_proc_exit();
raw6_proc_exit();
#endif
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index b0d83e8e4252..12c5a4dec09e 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -354,10 +354,9 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
if (!pskb_may_pull(skb, ah_hlen))
goto out;
- tmp_hdr = kmalloc(hdr_len, GFP_ATOMIC);
+ tmp_hdr = kmemdup(skb->nh.raw, hdr_len, GFP_ATOMIC);
if (!tmp_hdr)
goto out;
- memcpy(tmp_hdr, skb->nh.raw, hdr_len);
if (ipv6_clear_mutable_options(skb->nh.ipv6h, hdr_len, XFRM_POLICY_IN))
goto free_out;
skb->nh.ipv6h->priority = 0;
@@ -397,7 +396,7 @@ out:
}
static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
- int type, int code, int offset, __u32 info)
+ int type, int code, int offset, __be32 info)
{
struct ipv6hdr *iph = (struct ipv6hdr*)skb->data;
struct ip_auth_hdr *ah = (struct ip_auth_hdr*)(skb->data+offset);
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 7206747022fc..5c94fea90e97 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -207,7 +207,7 @@ out:
}
void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err,
- u16 port, u32 info, u8 *payload)
+ __be16 port, u32 info, u8 *payload)
{
struct ipv6_pinfo *np = inet6_sk(sk);
struct icmp6hdr *icmph = (struct icmp6hdr *)skb->h.raw;
@@ -318,13 +318,13 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
ipv6_addr_copy(&sin->sin6_addr,
(struct in6_addr *)(skb->nh.raw + serr->addr_offset));
if (np->sndflow)
- sin->sin6_flowinfo = *(u32*)(skb->nh.raw + serr->addr_offset - 24) & IPV6_FLOWINFO_MASK;
+ sin->sin6_flowinfo = *(__be32*)(skb->nh.raw + serr->addr_offset - 24) & IPV6_FLOWINFO_MASK;
if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL)
sin->sin6_scope_id = IP6CB(skb)->iif;
} else {
ipv6_addr_set(&sin->sin6_addr, 0, 0,
htonl(0xffff),
- *(u32*)(skb->nh.raw + serr->addr_offset));
+ *(__be32*)(skb->nh.raw + serr->addr_offset));
}
}
@@ -397,12 +397,12 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)
}
if (np->rxopt.bits.rxtclass) {
- int tclass = (ntohl(*(u32 *)skb->nh.ipv6h) >> 20) & 0xff;
+ int tclass = (ntohl(*(__be32 *)skb->nh.ipv6h) >> 20) & 0xff;
put_cmsg(msg, SOL_IPV6, IPV6_TCLASS, sizeof(tclass), &tclass);
}
- if (np->rxopt.bits.rxflow && (*(u32*)skb->nh.raw & IPV6_FLOWINFO_MASK)) {
- u32 flowinfo = *(u32*)skb->nh.raw & IPV6_FLOWINFO_MASK;
+ if (np->rxopt.bits.rxflow && (*(__be32*)skb->nh.raw & IPV6_FLOWINFO_MASK)) {
+ __be32 flowinfo = *(__be32*)skb->nh.raw & IPV6_FLOWINFO_MASK;
put_cmsg(msg, SOL_IPV6, IPV6_FLOWINFO, sizeof(flowinfo), &flowinfo);
}
@@ -560,12 +560,12 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
}
if (fl->fl6_flowlabel&IPV6_FLOWINFO_MASK) {
- if ((fl->fl6_flowlabel^*(u32 *)CMSG_DATA(cmsg))&~IPV6_FLOWINFO_MASK) {
+ if ((fl->fl6_flowlabel^*(__be32 *)CMSG_DATA(cmsg))&~IPV6_FLOWINFO_MASK) {
err = -EINVAL;
goto exit_f;
}
}
- fl->fl6_flowlabel = IPV6_FLOWINFO_MASK & *(u32 *)CMSG_DATA(cmsg);
+ fl->fl6_flowlabel = IPV6_FLOWINFO_MASK & *(__be32 *)CMSG_DATA(cmsg);
break;
case IPV6_2292HOPOPTS:
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index e78680a9985b..25dcf69cd807 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -256,7 +256,7 @@ static u32 esp6_get_max_size(struct xfrm_state *x, int mtu)
}
static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
- int type, int code, int offset, __u32 info)
+ int type, int code, int offset, __be32 info)
{
struct ipv6hdr *iph = (struct ipv6hdr*)skb->data;
struct ipv6_esp_hdr *esph = (struct ipv6_esp_hdr*)(skb->data+offset);
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 88c96b10684c..0711f92d6a12 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -284,10 +284,12 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp)
#ifdef CONFIG_IPV6_MIP6
__u16 dstbuf;
#endif
+ struct dst_entry *dst;
if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
!pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
- IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+ IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
+ IPSTATS_MIB_INHDRERRORS);
kfree_skb(skb);
return -1;
}
@@ -298,7 +300,9 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp)
dstbuf = opt->dst1;
#endif
+ dst = dst_clone(skb->dst);
if (ip6_parse_tlv(tlvprocdestopt_lst, skbp)) {
+ dst_release(dst);
skb = *skbp;
skb->h.raw += ((skb->h.raw[1]+1)<<3);
opt = IP6CB(skb);
@@ -310,7 +314,8 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp)
return 1;
}
- IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+ IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS);
+ dst_release(dst);
return -1;
}
@@ -365,7 +370,8 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
!pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
- IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+ IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
+ IPSTATS_MIB_INHDRERRORS);
kfree_skb(skb);
return -1;
}
@@ -374,7 +380,8 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr) ||
skb->pkt_type != PACKET_HOST) {
- IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
+ IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
+ IPSTATS_MIB_INADDRERRORS);
kfree_skb(skb);
return -1;
}
@@ -388,7 +395,8 @@ looped_back:
* processed by own
*/
if (!addr) {
- IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
+ IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
+ IPSTATS_MIB_INADDRERRORS);
kfree_skb(skb);
return -1;
}
@@ -410,7 +418,8 @@ looped_back:
switch (hdr->type) {
case IPV6_SRCRT_TYPE_0:
if (hdr->hdrlen & 0x01) {
- IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+ IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
+ IPSTATS_MIB_INHDRERRORS);
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->hdrlen) - skb->nh.raw);
return -1;
}
@@ -419,14 +428,16 @@ looped_back:
case IPV6_SRCRT_TYPE_2:
/* Silently discard invalid RTH type 2 */
if (hdr->hdrlen != 2 || hdr->segments_left != 1) {
- IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+ IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
+ IPSTATS_MIB_INHDRERRORS);
kfree_skb(skb);
return -1;
}
break;
#endif
default:
- IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+ IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
+ IPSTATS_MIB_INHDRERRORS);
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw);
return -1;
}
@@ -439,7 +450,8 @@ looped_back:
n = hdr->hdrlen >> 1;
if (hdr->segments_left > n) {
- IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+ IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
+ IPSTATS_MIB_INHDRERRORS);
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->segments_left) - skb->nh.raw);
return -1;
}
@@ -449,12 +461,14 @@ looped_back:
*/
if (skb_cloned(skb)) {
struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
- kfree_skb(skb);
/* the copy is a forwarded packet */
if (skb2 == NULL) {
- IP6_INC_STATS_BH(IPSTATS_MIB_OUTDISCARDS);
+ IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
+ IPSTATS_MIB_OUTDISCARDS);
+ kfree_skb(skb);
return -1;
}
+ kfree_skb(skb);
*skbp = skb = skb2;
opt = IP6CB(skb2);
hdr = (struct ipv6_rt_hdr *) skb2->h.raw;
@@ -475,12 +489,14 @@ looped_back:
if (xfrm6_input_addr(skb, (xfrm_address_t *)addr,
(xfrm_address_t *)&skb->nh.ipv6h->saddr,
IPPROTO_ROUTING) < 0) {
- IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
+ IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
+ IPSTATS_MIB_INADDRERRORS);
kfree_skb(skb);
return -1;
}
if (!ipv6_chk_home_addr(addr)) {
- IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
+ IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
+ IPSTATS_MIB_INADDRERRORS);
kfree_skb(skb);
return -1;
}
@@ -491,7 +507,8 @@ looped_back:
}
if (ipv6_addr_is_multicast(addr)) {
- IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
+ IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
+ IPSTATS_MIB_INADDRERRORS);
kfree_skb(skb);
return -1;
}
@@ -510,7 +527,8 @@ looped_back:
if (skb->dst->dev->flags&IFF_LOOPBACK) {
if (skb->nh.ipv6h->hop_limit <= 1) {
- IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+ IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
+ IPSTATS_MIB_INHDRERRORS);
icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
0, skb->dev);
kfree_skb(skb);
@@ -632,24 +650,25 @@ static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff)
if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) {
LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n",
skb->nh.raw[optoff+1]);
- IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+ IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
+ IPSTATS_MIB_INHDRERRORS);
goto drop;
}
- pkt_len = ntohl(*(u32*)(skb->nh.raw+optoff+2));
+ pkt_len = ntohl(*(__be32*)(skb->nh.raw+optoff+2));
if (pkt_len <= IPV6_MAXPLEN) {
- IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+ IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS);
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2);
return 0;
}
if (skb->nh.ipv6h->payload_len) {
- IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+ IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS);
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff);
return 0;
}
if (pkt_len > skb->len - sizeof(struct ipv6hdr)) {
- IP6_INC_STATS_BH(IPSTATS_MIB_INTRUNCATEDPKTS);
+ IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INTRUNCATEDPKTS);
goto drop;
}
diff --git a/net/ipv6/exthdrs_core.c b/net/ipv6/exthdrs_core.c
index 315bc1fbec3f..21cbbbddaf4d 100644
--- a/net/ipv6/exthdrs_core.c
+++ b/net/ipv6/exthdrs_core.c
@@ -77,7 +77,7 @@ int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp)
if (hp == NULL)
return -1;
if (nexthdr == NEXTHDR_FRAGMENT) {
- unsigned short _frag_off, *fp;
+ __be16 _frag_off, *fp;
fp = skb_header_pointer(skb,
start+offsetof(struct frag_hdr,
frag_off),
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index 1896ecb52899..0862809ffcf7 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -25,10 +25,6 @@ struct fib6_rule
struct fib_rule common;
struct rt6key src;
struct rt6key dst;
-#ifdef CONFIG_IPV6_ROUTE_FWMARK
- u32 fwmark;
- u32 fwmask;
-#endif
u8 tclass;
};
@@ -67,7 +63,7 @@ struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags,
fib_rule_put(arg.rule);
if (arg.result)
- return (struct dst_entry *) arg.result;
+ return arg.result;
dst_hold(&ip6_null_entry.u.dst);
return &ip6_null_entry.u.dst;
@@ -130,22 +126,13 @@ static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
if (r->tclass && r->tclass != ((ntohl(fl->fl6_flowlabel) >> 20) & 0xff))
return 0;
-#ifdef CONFIG_IPV6_ROUTE_FWMARK
- if ((r->fwmark ^ fl->fl6_fwmark) & r->fwmask)
- return 0;
-#endif
-
return 1;
}
static struct nla_policy fib6_rule_policy[FRA_MAX+1] __read_mostly = {
- [FRA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 },
- [FRA_PRIORITY] = { .type = NLA_U32 },
+ FRA_GENERIC_POLICY,
[FRA_SRC] = { .len = sizeof(struct in6_addr) },
[FRA_DST] = { .len = sizeof(struct in6_addr) },
- [FRA_FWMARK] = { .type = NLA_U32 },
- [FRA_FWMASK] = { .type = NLA_U32 },
- [FRA_TABLE] = { .type = NLA_U32 },
};
static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
@@ -155,8 +142,7 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
int err = -EINVAL;
struct fib6_rule *rule6 = (struct fib6_rule *) rule;
- if (frh->src_len > 128 || frh->dst_len > 128 ||
- (frh->tos & ~IPV6_FLOWINFO_MASK))
+ if (frh->src_len > 128 || frh->dst_len > 128)
goto errout;
if (rule->action == FR_ACT_TO_TBL) {
@@ -177,23 +163,6 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
nla_memcpy(&rule6->dst.addr, tb[FRA_DST],
sizeof(struct in6_addr));
-#ifdef CONFIG_IPV6_ROUTE_FWMARK
- if (tb[FRA_FWMARK]) {
- rule6->fwmark = nla_get_u32(tb[FRA_FWMARK]);
- if (rule6->fwmark) {
- /*
- * if the mark value is non-zero,
- * all bits are compared by default
- * unless a mask is explicitly specified.
- */
- rule6->fwmask = 0xFFFFFFFF;
- }
- }
-
- if (tb[FRA_FWMASK])
- rule6->fwmask = nla_get_u32(tb[FRA_FWMASK]);
-#endif
-
rule6->src.plen = frh->src_len;
rule6->dst.plen = frh->dst_len;
rule6->tclass = frh->tos;
@@ -225,14 +194,6 @@ static int fib6_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
nla_memcmp(tb[FRA_DST], &rule6->dst.addr, sizeof(struct in6_addr)))
return 0;
-#ifdef CONFIG_IPV6_ROUTE_FWMARK
- if (tb[FRA_FWMARK] && (rule6->fwmark != nla_get_u32(tb[FRA_FWMARK])))
- return 0;
-
- if (tb[FRA_FWMASK] && (rule6->fwmask != nla_get_u32(tb[FRA_FWMASK])))
- return 0;
-#endif
-
return 1;
}
@@ -254,14 +215,6 @@ static int fib6_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
NLA_PUT(skb, FRA_SRC, sizeof(struct in6_addr),
&rule6->src.addr);
-#ifdef CONFIG_IPV6_ROUTE_FWMARK
- if (rule6->fwmark)
- NLA_PUT_U32(skb, FRA_FWMARK, rule6->fwmark);
-
- if (rule6->fwmask || rule6->fwmark)
- NLA_PUT_U32(skb, FRA_FWMASK, rule6->fwmask);
-#endif
-
return 0;
nla_put_failure:
@@ -278,6 +231,12 @@ static u32 fib6_rule_default_pref(void)
return 0x3FFF;
}
+static size_t fib6_rule_nlmsg_payload(struct fib_rule *rule)
+{
+ return nla_total_size(16) /* dst */
+ + nla_total_size(16); /* src */
+}
+
static struct fib_rules_ops fib6_rules_ops = {
.family = AF_INET6,
.rule_size = sizeof(struct fib6_rule),
@@ -287,6 +246,7 @@ static struct fib_rules_ops fib6_rules_ops = {
.compare = fib6_rule_compare,
.fill = fib6_rule_fill,
.default_pref = fib6_rule_default_pref,
+ .nlmsg_payload = fib6_rule_nlmsg_payload,
.nlgroup = RTNLGRP_IPV6_RULE,
.policy = fib6_rule_policy,
.rules_list = &fib6_rules,
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 4ec876066b3f..3dcc4b7f41b4 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -177,7 +177,8 @@ static inline int icmpv6_xrlim_allow(struct sock *sk, int type,
*/
dst = ip6_route_output(sk, fl);
if (dst->error) {
- IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES);
+ IP6_INC_STATS(ip6_dst_idev(dst),
+ IPSTATS_MIB_OUTNOROUTES);
} else if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) {
res = 1;
} else {
@@ -233,7 +234,7 @@ static int icmpv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct
len, fl->proto,
skb->csum);
} else {
- u32 tmp_csum = 0;
+ __wsum tmp_csum = 0;
skb_queue_walk(&sk->sk_write_queue, skb) {
tmp_csum = csum_add(tmp_csum, skb->csum);
@@ -241,13 +242,11 @@ static int icmpv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct
tmp_csum = csum_partial((char *)icmp6h,
sizeof(struct icmp6hdr), tmp_csum);
- tmp_csum = csum_ipv6_magic(&fl->fl6_src,
- &fl->fl6_dst,
- len, fl->proto, tmp_csum);
- icmp6h->icmp6_cksum = tmp_csum;
+ icmp6h->icmp6_cksum = csum_ipv6_magic(&fl->fl6_src,
+ &fl->fl6_dst,
+ len, fl->proto,
+ tmp_csum);
}
- if (icmp6h->icmp6_cksum == 0)
- icmp6h->icmp6_cksum = -1;
ip6_push_pending_frames(sk);
out:
return err;
@@ -263,7 +262,7 @@ static int icmpv6_getfrag(void *from, char *to, int offset, int len, int odd, st
{
struct icmpv6_msg *msg = (struct icmpv6_msg *) from;
struct sk_buff *org_skb = msg->skb;
- __u32 csum = 0;
+ __wsum csum = 0;
csum = skb_copy_and_csum_bits(org_skb, msg->offset + offset,
to, len, csum);
@@ -555,7 +554,7 @@ out:
icmpv6_xmit_unlock();
}
-static void icmpv6_notify(struct sk_buff *skb, int type, int code, u32 info)
+static void icmpv6_notify(struct sk_buff *skb, int type, int code, __be32 info)
{
struct in6_addr *saddr, *daddr;
struct inet6_protocol *ipprot;
@@ -637,8 +636,8 @@ static int icmpv6_rcv(struct sk_buff **pskb)
break;
/* fall through */
case CHECKSUM_NONE:
- skb->csum = ~csum_ipv6_magic(saddr, daddr, skb->len,
- IPPROTO_ICMPV6, 0);
+ skb->csum = ~csum_unfold(csum_ipv6_magic(saddr, daddr, skb->len,
+ IPPROTO_ICMPV6, 0));
if (__skb_checksum_complete(skb)) {
LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [" NIP6_FMT " > " NIP6_FMT "]\n",
NIP6(*saddr), NIP6(*daddr));
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index 827f41d1478b..c700302ad51a 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -52,20 +52,20 @@ EXPORT_SYMBOL_GPL(inet6_csk_bind_conflict);
/*
* request_sock (formerly open request) hash tables.
*/
-static u32 inet6_synq_hash(const struct in6_addr *raddr, const u16 rport,
+static u32 inet6_synq_hash(const struct in6_addr *raddr, const __be16 rport,
const u32 rnd, const u16 synq_hsize)
{
- u32 a = raddr->s6_addr32[0];
- u32 b = raddr->s6_addr32[1];
- u32 c = raddr->s6_addr32[2];
+ u32 a = (__force u32)raddr->s6_addr32[0];
+ u32 b = (__force u32)raddr->s6_addr32[1];
+ u32 c = (__force u32)raddr->s6_addr32[2];
a += JHASH_GOLDEN_RATIO;
b += JHASH_GOLDEN_RATIO;
c += rnd;
__jhash_mix(a, b, c);
- a += raddr->s6_addr32[3];
- b += (u32)rport;
+ a += (__force u32)raddr->s6_addr32[3];
+ b += (__force u32)rport;
__jhash_mix(a, b, c);
return c & (synq_hsize - 1);
@@ -73,7 +73,7 @@ static u32 inet6_synq_hash(const struct in6_addr *raddr, const u16 rport,
struct request_sock *inet6_csk_search_req(const struct sock *sk,
struct request_sock ***prevp,
- const __u16 rport,
+ const __be16 rport,
const struct in6_addr *raddr,
const struct in6_addr *laddr,
const int iif)
@@ -139,9 +139,8 @@ void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr * uaddr)
EXPORT_SYMBOL_GPL(inet6_csk_addr2sockaddr);
-int inet6_csk_xmit(struct sk_buff *skb, int ipfragok)
+int inet6_csk_xmit(struct sk_buff *skb, struct sock *sk, int ipfragok)
{
- struct sock *sk = skb->sk;
struct inet_sock *inet = inet_sk(sk);
struct ipv6_pinfo *np = inet6_sk(sk);
struct flowi fl;
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index 8accd1fbeeda..b7e5bae0e347 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -57,7 +57,7 @@ EXPORT_SYMBOL(__inet6_hash);
*/
struct sock *__inet6_lookup_established(struct inet_hashinfo *hashinfo,
const struct in6_addr *saddr,
- const u16 sport,
+ const __be16 sport,
const struct in6_addr *daddr,
const u16 hnum,
const int dif)
@@ -146,8 +146,8 @@ struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo,
EXPORT_SYMBOL_GPL(inet6_lookup_listener);
struct sock *inet6_lookup(struct inet_hashinfo *hashinfo,
- const struct in6_addr *saddr, const u16 sport,
- const struct in6_addr *daddr, const u16 dport,
+ const struct in6_addr *saddr, const __be16 sport,
+ const struct in6_addr *daddr, const __be16 dport,
const int dif)
{
struct sock *sk;
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index f98ca30d7c1f..bf526115e518 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -139,9 +139,9 @@ static __inline__ u32 fib6_new_sernum(void)
* test bit
*/
-static __inline__ int addr_bit_set(void *token, int fn_bit)
+static __inline__ __be32 addr_bit_set(void *token, int fn_bit)
{
- __u32 *addr = token;
+ __be32 *addr = token;
return htonl(1 << ((~fn_bit)&0x1F)) & addr[fn_bit>>5];
}
@@ -434,7 +434,7 @@ static struct fib6_node * fib6_add_1(struct fib6_node *root, void *addr,
struct fib6_node *pn = NULL;
struct rt6key *key;
int bit;
- int dir = 0;
+ __be32 dir = 0;
__u32 sernum = fib6_new_sernum();
RT6_TRACE("fib6_add_1\n");
@@ -829,7 +829,7 @@ static struct fib6_node * fib6_lookup_1(struct fib6_node *root,
struct lookup_args *args)
{
struct fib6_node *fn;
- int dir;
+ __be32 dir;
if (unlikely(args->offset == 0))
return NULL;
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index 6d4533b58dca..624fae251f4e 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -61,7 +61,7 @@ static DEFINE_RWLOCK(ip6_fl_lock);
static DEFINE_RWLOCK(ip6_sk_fl_lock);
-static __inline__ struct ip6_flowlabel * __fl_lookup(u32 label)
+static __inline__ struct ip6_flowlabel * __fl_lookup(__be32 label)
{
struct ip6_flowlabel *fl;
@@ -72,7 +72,7 @@ static __inline__ struct ip6_flowlabel * __fl_lookup(u32 label)
return NULL;
}
-static struct ip6_flowlabel * fl_lookup(u32 label)
+static struct ip6_flowlabel * fl_lookup(__be32 label)
{
struct ip6_flowlabel *fl;
@@ -153,7 +153,7 @@ static void ip6_fl_gc(unsigned long dummy)
write_unlock(&ip6_fl_lock);
}
-static int fl_intern(struct ip6_flowlabel *fl, __u32 label)
+static int fl_intern(struct ip6_flowlabel *fl, __be32 label)
{
fl->label = label & IPV6_FLOWLABEL_MASK;
@@ -182,7 +182,7 @@ static int fl_intern(struct ip6_flowlabel *fl, __u32 label)
/* Socket flowlabel lists */
-struct ip6_flowlabel * fl6_sock_lookup(struct sock *sk, u32 label)
+struct ip6_flowlabel * fl6_sock_lookup(struct sock *sk, __be32 label)
{
struct ipv6_fl_socklist *sfl;
struct ipv6_pinfo *np = inet6_sk(sk);
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 6b8e6d76a58b..ad0b8abcdf4b 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -60,14 +60,22 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
{
struct ipv6hdr *hdr;
u32 pkt_len;
+ struct inet6_dev *idev;
- if (skb->pkt_type == PACKET_OTHERHOST)
- goto drop;
+ if (skb->pkt_type == PACKET_OTHERHOST) {
+ kfree_skb(skb);
+ return 0;
+ }
+
+ rcu_read_lock();
- IP6_INC_STATS_BH(IPSTATS_MIB_INRECEIVES);
+ idev = __in6_dev_get(skb->dev);
+
+ IP6_INC_STATS_BH(idev, IPSTATS_MIB_INRECEIVES);
if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
- IP6_INC_STATS_BH(IPSTATS_MIB_INDISCARDS);
+ IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDISCARDS);
+ rcu_read_unlock();
goto out;
}
@@ -84,7 +92,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
* arrived via the sending interface (ethX), because of the
* nature of scoping architecture. --yoshfuji
*/
- IP6CB(skb)->iif = skb->dst ? ((struct rt6_info *)skb->dst)->rt6i_idev->dev->ifindex : dev->ifindex;
+ IP6CB(skb)->iif = skb->dst ? ip6_dst_idev(skb->dst)->dev->ifindex : dev->ifindex;
if (unlikely(!pskb_may_pull(skb, sizeof(*hdr))))
goto err;
@@ -104,7 +112,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
if (pkt_len + sizeof(struct ipv6hdr) > skb->len)
goto truncated;
if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr))) {
- IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+ IP6_INC_STATS_BH(idev, IPSTATS_MIB_INHDRERRORS);
goto drop;
}
hdr = skb->nh.ipv6h;
@@ -112,17 +120,21 @@ 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) < 0) {
- IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+ IP6_INC_STATS_BH(idev, IPSTATS_MIB_INHDRERRORS);
+ rcu_read_unlock();
return 0;
}
}
+ rcu_read_unlock();
+
return NF_HOOK(PF_INET6,NF_IP6_PRE_ROUTING, skb, dev, NULL, ip6_rcv_finish);
truncated:
- IP6_INC_STATS_BH(IPSTATS_MIB_INTRUNCATEDPKTS);
+ IP6_INC_STATS_BH(idev, IPSTATS_MIB_INTRUNCATEDPKTS);
err:
- IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+ IP6_INC_STATS_BH(idev, IPSTATS_MIB_INHDRERRORS);
drop:
+ rcu_read_unlock();
kfree_skb(skb);
out:
return 0;
@@ -140,6 +152,7 @@ static inline int ip6_input_finish(struct sk_buff *skb)
unsigned int nhoff;
int nexthdr;
u8 hash;
+ struct inet6_dev *idev;
/*
* Parse extension headers
@@ -147,6 +160,7 @@ static inline int ip6_input_finish(struct sk_buff *skb)
rcu_read_lock();
resubmit:
+ idev = ip6_dst_idev(skb->dst);
if (!pskb_pull(skb, skb->h.raw - skb->data))
goto discard;
nhoff = IP6CB(skb)->nhoff;
@@ -185,24 +199,24 @@ resubmit:
if (ret > 0)
goto resubmit;
else if (ret == 0)
- IP6_INC_STATS_BH(IPSTATS_MIB_INDELIVERS);
+ IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDELIVERS);
} else {
if (!raw_sk) {
if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
- IP6_INC_STATS_BH(IPSTATS_MIB_INUNKNOWNPROTOS);
+ IP6_INC_STATS_BH(idev, IPSTATS_MIB_INUNKNOWNPROTOS);
icmpv6_send(skb, ICMPV6_PARAMPROB,
ICMPV6_UNK_NEXTHDR, nhoff,
skb->dev);
}
} else
- IP6_INC_STATS_BH(IPSTATS_MIB_INDELIVERS);
+ IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDELIVERS);
kfree_skb(skb);
}
rcu_read_unlock();
return 0;
discard:
- IP6_INC_STATS_BH(IPSTATS_MIB_INDISCARDS);
+ IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDISCARDS);
rcu_read_unlock();
kfree_skb(skb);
return 0;
@@ -219,7 +233,7 @@ int ip6_mc_input(struct sk_buff *skb)
struct ipv6hdr *hdr;
int deliver;
- IP6_INC_STATS_BH(IPSTATS_MIB_INMCASTPKTS);
+ IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INMCASTPKTS);
hdr = skb->nh.ipv6h;
deliver = likely(!(skb->dev->flags & (IFF_PROMISC|IFF_ALLMULTI))) ||
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 66716911962e..e05ecbb1412d 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -88,7 +88,7 @@ static inline int ip6_output_finish(struct sk_buff *skb)
} else if (dst->neighbour)
return dst->neighbour->output(skb);
- IP6_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
+ IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
kfree_skb(skb);
return -EINVAL;
@@ -118,6 +118,7 @@ static int ip6_output2(struct sk_buff *skb)
if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr)) {
struct ipv6_pinfo* np = skb->sk ? inet6_sk(skb->sk) : NULL;
+ struct inet6_dev *idev = ip6_dst_idev(skb->dst);
if (!(dev->flags & IFF_LOOPBACK) && (!np || np->mc_loop) &&
ipv6_chk_mcast_addr(dev, &skb->nh.ipv6h->daddr,
@@ -133,13 +134,13 @@ static int ip6_output2(struct sk_buff *skb)
ip6_dev_loopback_xmit);
if (skb->nh.ipv6h->hop_limit == 0) {
- IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS);
+ IP6_INC_STATS(idev, IPSTATS_MIB_OUTDISCARDS);
kfree_skb(skb);
return 0;
}
}
- IP6_INC_STATS(IPSTATS_MIB_OUTMCASTPKTS);
+ IP6_INC_STATS(idev, IPSTATS_MIB_OUTMCASTPKTS);
}
return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb,NULL, skb->dev,ip6_output_finish);
@@ -182,12 +183,14 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
if (skb_headroom(skb) < head_room) {
struct sk_buff *skb2 = skb_realloc_headroom(skb, head_room);
- kfree_skb(skb);
- skb = skb2;
- if (skb == NULL) {
- IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS);
+ if (skb2 == NULL) {
+ IP6_INC_STATS(ip6_dst_idev(skb->dst),
+ IPSTATS_MIB_OUTDISCARDS);
+ kfree_skb(skb);
return -ENOBUFS;
}
+ kfree_skb(skb);
+ skb = skb2;
if (sk)
skb_set_owner_w(skb, sk);
}
@@ -217,7 +220,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
if (tclass < 0)
tclass = 0;
- *(u32 *)hdr = htonl(0x60000000 | (tclass << 20)) | fl->fl6_flowlabel;
+ *(__be32 *)hdr = htonl(0x60000000 | (tclass << 20)) | fl->fl6_flowlabel;
hdr->payload_len = htons(seg_len);
hdr->nexthdr = proto;
@@ -230,7 +233,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
mtu = dst_mtu(dst);
if ((skb->len <= mtu) || ipfragok || skb_is_gso(skb)) {
- IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
+ IP6_INC_STATS(ip6_dst_idev(skb->dst),
+ IPSTATS_MIB_OUTREQUESTS);
return NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev,
dst_output);
}
@@ -239,7 +243,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
printk(KERN_DEBUG "IPv6: sending pkt_too_big to self\n");
skb->dev = dst->dev;
icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev);
- IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS);
+ IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS);
kfree_skb(skb);
return -EMSGSIZE;
}
@@ -267,7 +271,7 @@ int ip6_nd_hdr(struct sock *sk, struct sk_buff *skb, struct net_device *dev,
hdr = (struct ipv6hdr *) skb_put(skb, sizeof(struct ipv6hdr));
skb->nh.ipv6h = hdr;
- *(u32*)hdr = htonl(0x60000000);
+ *(__be32*)hdr = htonl(0x60000000);
hdr->payload_len = htons(len);
hdr->nexthdr = proto;
@@ -373,7 +377,7 @@ int ip6_forward(struct sk_buff *skb)
goto error;
if (!xfrm6_policy_check(NULL, XFRM_POLICY_FWD, skb)) {
- IP6_INC_STATS(IPSTATS_MIB_INDISCARDS);
+ IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_INDISCARDS);
goto drop;
}
@@ -406,7 +410,7 @@ int ip6_forward(struct sk_buff *skb)
skb->dev = dst->dev;
icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
0, skb->dev);
- IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+ IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS);
kfree_skb(skb);
return -ETIMEDOUT;
@@ -419,13 +423,13 @@ int ip6_forward(struct sk_buff *skb)
if (proxied > 0)
return ip6_input(skb);
else if (proxied < 0) {
- IP6_INC_STATS(IPSTATS_MIB_INDISCARDS);
+ IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_INDISCARDS);
goto drop;
}
}
if (!xfrm6_route_forward(skb)) {
- IP6_INC_STATS(IPSTATS_MIB_INDISCARDS);
+ IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_INDISCARDS);
goto drop;
}
dst = skb->dst;
@@ -464,14 +468,14 @@ int ip6_forward(struct sk_buff *skb)
/* Again, force OUTPUT device used as source address */
skb->dev = dst->dev;
icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, dst_mtu(dst), skb->dev);
- IP6_INC_STATS_BH(IPSTATS_MIB_INTOOBIGERRORS);
- IP6_INC_STATS_BH(IPSTATS_MIB_FRAGFAILS);
+ IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INTOOBIGERRORS);
+ IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_FRAGFAILS);
kfree_skb(skb);
return -EMSGSIZE;
}
if (skb_cow(skb, dst->dev->hard_header_len)) {
- IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS);
+ IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_OUTDISCARDS);
goto drop;
}
@@ -481,11 +485,11 @@ int ip6_forward(struct sk_buff *skb)
hdr->hop_limit--;
- IP6_INC_STATS_BH(IPSTATS_MIB_OUTFORWDATAGRAMS);
+ IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_OUTFORWDATAGRAMS);
return NF_HOOK(PF_INET6,NF_IP6_FORWARD, skb, skb->dev, dst->dev, ip6_forward_finish);
error:
- IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
+ IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INADDRERRORS);
drop:
kfree_skb(skb);
return -EINVAL;
@@ -499,12 +503,12 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from)
dst_release(to->dst);
to->dst = dst_clone(from->dst);
to->dev = from->dev;
+ to->mark = from->mark;
#ifdef CONFIG_NET_SCHED
to->tc_index = from->tc_index;
#endif
#ifdef CONFIG_NETFILTER
- to->nfmark = from->nfmark;
/* Connection association is same as pre-frag packet */
nf_conntrack_put(to->nfct);
to->nfct = from->nfct;
@@ -571,7 +575,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
struct ipv6hdr *tmp_hdr;
struct frag_hdr *fh;
unsigned int mtu, hlen, left, len;
- u32 frag_id = 0;
+ __be32 frag_id = 0;
int ptr, offset = 0, err=0;
u8 *prevhdr, nexthdr = 0;
@@ -620,14 +624,13 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
skb_shinfo(skb)->frag_list = NULL;
/* BUILD HEADER */
- tmp_hdr = kmalloc(hlen, GFP_ATOMIC);
+ tmp_hdr = kmemdup(skb->nh.raw, hlen, GFP_ATOMIC);
if (!tmp_hdr) {
- IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS);
+ IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS);
return -ENOMEM;
}
*prevhdr = NEXTHDR_FRAGMENT;
- memcpy(tmp_hdr, skb->nh.raw, hlen);
__skb_pull(skb, hlen);
fh = (struct frag_hdr*)__skb_push(skb, sizeof(struct frag_hdr));
skb->nh.raw = __skb_push(skb, hlen);
@@ -643,7 +646,8 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
skb->data_len = first_len - skb_headlen(skb);
skb->len = first_len;
skb->nh.ipv6h->payload_len = htons(first_len - sizeof(struct ipv6hdr));
-
+
+ dst_hold(&rt->u.dst);
for (;;) {
/* Prepare header of the next frame,
@@ -667,7 +671,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
err = output(skb);
if(!err)
- IP6_INC_STATS(IPSTATS_MIB_FRAGCREATES);
+ IP6_INC_STATS(ip6_dst_idev(&rt->u.dst), IPSTATS_MIB_FRAGCREATES);
if (err || !frag)
break;
@@ -680,7 +684,8 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
kfree(tmp_hdr);
if (err == 0) {
- IP6_INC_STATS(IPSTATS_MIB_FRAGOKS);
+ IP6_INC_STATS(ip6_dst_idev(&rt->u.dst), IPSTATS_MIB_FRAGOKS);
+ dst_release(&rt->u.dst);
return 0;
}
@@ -690,7 +695,8 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
frag = skb;
}
- IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS);
+ IP6_INC_STATS(ip6_dst_idev(&rt->u.dst), IPSTATS_MIB_FRAGFAILS);
+ dst_release(&rt->u.dst);
return err;
}
@@ -723,7 +729,8 @@ slow_path:
if ((frag = alloc_skb(len+hlen+sizeof(struct frag_hdr)+LL_RESERVED_SPACE(rt->u.dst.dev), GFP_ATOMIC)) == NULL) {
NETDEBUG(KERN_INFO "IPv6: frag: no memory for new fragment!\n");
- IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS);
+ IP6_INC_STATS(ip6_dst_idev(skb->dst),
+ IPSTATS_MIB_FRAGFAILS);
err = -ENOMEM;
goto fail;
}
@@ -784,15 +791,17 @@ slow_path:
if (err)
goto fail;
- IP6_INC_STATS(IPSTATS_MIB_FRAGCREATES);
+ IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGCREATES);
}
+ IP6_INC_STATS(ip6_dst_idev(skb->dst),
+ IPSTATS_MIB_FRAGOKS);
kfree_skb(skb);
- IP6_INC_STATS(IPSTATS_MIB_FRAGOKS);
return err;
fail:
+ IP6_INC_STATS(ip6_dst_idev(skb->dst),
+ IPSTATS_MIB_FRAGFAILS);
kfree_skb(skb);
- IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS);
return err;
}
@@ -1265,7 +1274,7 @@ alloc_new_skb:
return 0;
error:
inet->cork.length -= length;
- IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS);
+ IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS);
return err;
}
@@ -1311,7 +1320,7 @@ int ip6_push_pending_frames(struct sock *sk)
skb->nh.ipv6h = hdr = (struct ipv6hdr*) skb_push(skb, sizeof(struct ipv6hdr));
- *(u32*)hdr = fl->fl6_flowlabel |
+ *(__be32*)hdr = fl->fl6_flowlabel |
htonl(0x60000000 | ((int)np->cork.tclass << 20));
if (skb->len <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN)
@@ -1326,7 +1335,7 @@ int ip6_push_pending_frames(struct sock *sk)
skb->priority = sk->sk_priority;
skb->dst = dst_clone(&rt->u.dst);
- IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
+ IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS);
err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dst->dev, dst_output);
if (err) {
if (err > 0)
@@ -1357,7 +1366,8 @@ void ip6_flush_pending_frames(struct sock *sk)
struct sk_buff *skb;
while ((skb = __skb_dequeue_tail(&sk->sk_write_queue)) != NULL) {
- IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS);
+ IP6_INC_STATS(ip6_dst_idev(skb->dst),
+ IPSTATS_MIB_OUTDISCARDS);
kfree_skb(skb);
}
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index b9f40290d12a..8d918348f5bb 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -66,7 +66,7 @@ MODULE_LICENSE("GPL");
#define HASH_SIZE 32
-#define HASH(addr) (((addr)->s6_addr32[0] ^ (addr)->s6_addr32[1] ^ \
+#define HASH(addr) ((__force u32)((addr)->s6_addr32[0] ^ (addr)->s6_addr32[1] ^ \
(addr)->s6_addr32[2] ^ (addr)->s6_addr32[3]) & \
(HASH_SIZE - 1))
@@ -215,11 +215,10 @@ ip6ip6_tnl_unlink(struct ip6_tnl *t)
* Create tunnel matching given parameters.
*
* Return:
- * 0 on success
+ * created tunnel or NULL
**/
-static int
-ip6_tnl_create(struct ip6_tnl_parm *p, struct ip6_tnl **pt)
+static struct ip6_tnl *ip6_tnl_create(struct ip6_tnl_parm *p)
{
struct net_device *dev;
struct ip6_tnl *t;
@@ -236,11 +235,11 @@ ip6_tnl_create(struct ip6_tnl_parm *p, struct ip6_tnl **pt)
break;
}
if (i == IP6_TNL_MAX)
- return -ENOBUFS;
+ goto failed;
}
dev = alloc_netdev(sizeof (*t), name, ip6ip6_tnl_dev_setup);
if (dev == NULL)
- return -ENOMEM;
+ goto failed;
t = netdev_priv(dev);
dev->init = ip6ip6_tnl_dev_init;
@@ -248,13 +247,13 @@ ip6_tnl_create(struct ip6_tnl_parm *p, struct ip6_tnl **pt)
if ((err = register_netdevice(dev)) < 0) {
free_netdev(dev);
- return err;
+ goto failed;
}
dev_hold(dev);
-
ip6ip6_tnl_link(t);
- *pt = t;
- return 0;
+ return t;
+failed:
+ return NULL;
}
/**
@@ -268,32 +267,23 @@ ip6_tnl_create(struct ip6_tnl_parm *p, struct ip6_tnl **pt)
* tunnel device is created and registered for use.
*
* Return:
- * 0 if tunnel located or created,
- * -EINVAL if parameters incorrect,
- * -ENODEV if no matching tunnel available
+ * matching tunnel or NULL
**/
-static int
-ip6ip6_tnl_locate(struct ip6_tnl_parm *p, struct ip6_tnl **pt, int create)
+static struct ip6_tnl *ip6ip6_tnl_locate(struct ip6_tnl_parm *p, int create)
{
struct in6_addr *remote = &p->raddr;
struct in6_addr *local = &p->laddr;
struct ip6_tnl *t;
- if (p->proto != IPPROTO_IPV6)
- return -EINVAL;
-
for (t = *ip6ip6_bucket(p); t; t = t->next) {
if (ipv6_addr_equal(local, &t->parms.laddr) &&
- ipv6_addr_equal(remote, &t->parms.raddr)) {
- *pt = t;
- return (create ? -EEXIST : 0);
- }
+ ipv6_addr_equal(remote, &t->parms.raddr))
+ return t;
}
if (!create)
- return -ENODEV;
-
- return ip6_tnl_create(p, pt);
+ return NULL;
+ return ip6_tnl_create(p);
}
/**
@@ -391,7 +381,7 @@ parse_tlv_tnl_enc_lim(struct sk_buff *skb, __u8 * raw)
static int
ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
- int type, int code, int offset, __u32 info)
+ int type, int code, int offset, __be32 info)
{
struct ipv6hdr *ipv6h = (struct ipv6hdr *) skb->data;
struct ip6_tnl *t;
@@ -434,12 +424,9 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
}
break;
case ICMPV6_PARAMPROB:
- /* ignore if parameter problem not caused by a tunnel
- encapsulation limit sub-option */
- if (code != ICMPV6_HDR_FIELD) {
- break;
- }
- teli = parse_tlv_tnl_enc_lim(skb, skb->data);
+ teli = 0;
+ if (code == ICMPV6_HDR_FIELD)
+ teli = parse_tlv_tnl_enc_lim(skb, skb->data);
if (teli && teli == ntohl(info) - 2) {
tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->data[teli];
@@ -451,6 +438,10 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
"tunnel!\n", t->parms.name);
rel_msg = 1;
}
+ } else if (net_ratelimit()) {
+ printk(KERN_WARNING
+ "%s: Recipient unable to parse tunneled "
+ "packet!\n ", t->parms.name);
}
break;
case ICMPV6_PKT_TOOBIG:
@@ -470,6 +461,7 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
if (rel_msg && pskb_may_pull(skb, offset + sizeof (*ipv6h))) {
struct rt6_info *rt;
struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
+
if (!skb2)
goto out;
@@ -504,6 +496,27 @@ static inline void ip6ip6_ecn_decapsulate(struct ipv6hdr *outer_iph,
if (INET_ECN_is_ce(ipv6_get_dsfield(outer_iph)))
IP6_ECN_set_ce(inner_iph);
}
+static inline int ip6_tnl_rcv_ctl(struct ip6_tnl *t)
+{
+ struct ip6_tnl_parm *p = &t->parms;
+ int ret = 0;
+
+ if (p->flags & IP6_TNL_F_CAP_RCV) {
+ struct net_device *ldev = NULL;
+
+ if (p->link)
+ ldev = dev_get_by_index(p->link);
+
+ if ((ipv6_addr_is_multicast(&p->laddr) ||
+ likely(ipv6_chk_addr(&p->laddr, ldev, 0))) &&
+ likely(!ipv6_chk_addr(&p->raddr, NULL, 0)))
+ ret = 1;
+
+ if (ldev)
+ dev_put(ldev);
+ }
+ return ret;
+}
/**
* ip6ip6_rcv - decapsulate IPv6 packet and retransmit it locally
@@ -528,7 +541,7 @@ ip6ip6_rcv(struct sk_buff *skb)
goto discard;
}
- if (!(t->parms.flags & IP6_TNL_F_CAP_RCV)) {
+ if (!ip6_tnl_rcv_ctl(t)) {
t->stat.rx_dropped++;
read_unlock(&ip6ip6_lock);
goto discard;
@@ -560,31 +573,23 @@ discard:
return 0;
}
-static inline struct ipv6_txoptions *create_tel(__u8 encap_limit)
-{
- struct ipv6_tlv_tnl_enc_lim *tel;
- struct ipv6_txoptions *opt;
- __u8 *raw;
-
- int opt_len = sizeof(*opt) + 8;
-
- if (!(opt = kzalloc(opt_len, GFP_ATOMIC))) {
- return NULL;
- }
- opt->tot_len = opt_len;
- opt->dst0opt = (struct ipv6_opt_hdr *) (opt + 1);
- opt->opt_nflen = 8;
+struct ipv6_tel_txoption {
+ struct ipv6_txoptions ops;
+ __u8 dst_opt[8];
+};
- tel = (struct ipv6_tlv_tnl_enc_lim *) (opt->dst0opt + 1);
- tel->type = IPV6_TLV_TNL_ENCAP_LIMIT;
- tel->length = 1;
- tel->encap_limit = encap_limit;
+static void init_tel_txopt(struct ipv6_tel_txoption *opt, __u8 encap_limit)
+{
+ memset(opt, 0, sizeof(struct ipv6_tel_txoption));
- raw = (__u8 *) opt->dst0opt;
- raw[5] = IPV6_TLV_PADN;
- raw[6] = 1;
+ opt->dst_opt[2] = IPV6_TLV_TNL_ENCAP_LIMIT;
+ opt->dst_opt[3] = 1;
+ opt->dst_opt[4] = encap_limit;
+ opt->dst_opt[5] = IPV6_TLV_PADN;
+ opt->dst_opt[6] = 1;
- return opt;
+ opt->ops.dst0opt = (struct ipv6_opt_hdr *) opt->dst_opt;
+ opt->ops.opt_nflen = 8;
}
/**
@@ -607,6 +612,34 @@ ip6ip6_tnl_addr_conflict(struct ip6_tnl *t, struct ipv6hdr *hdr)
return ipv6_addr_equal(&t->parms.raddr, &hdr->saddr);
}
+static inline int ip6_tnl_xmit_ctl(struct ip6_tnl *t)
+{
+ struct ip6_tnl_parm *p = &t->parms;
+ int ret = 0;
+
+ if (p->flags & IP6_TNL_F_CAP_XMIT) {
+ struct net_device *ldev = NULL;
+
+ if (p->link)
+ ldev = dev_get_by_index(p->link);
+
+ if (unlikely(!ipv6_chk_addr(&p->laddr, ldev, 0)))
+ printk(KERN_WARNING
+ "%s xmit: Local address not yet configured!\n",
+ p->name);
+ else if (!ipv6_addr_is_multicast(&p->raddr) &&
+ unlikely(ipv6_chk_addr(&p->raddr, NULL, 0)))
+ printk(KERN_WARNING
+ "%s xmit: Routing loop! "
+ "Remote address found on this node!\n",
+ p->name);
+ else
+ ret = 1;
+ if (ldev)
+ dev_put(ldev);
+ }
+ return ret;
+}
/**
* ip6ip6_tnl_xmit - encapsulate packet and send
* @skb: the outgoing socket buffer
@@ -626,8 +659,8 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
struct ip6_tnl *t = netdev_priv(dev);
struct net_device_stats *stats = &t->stat;
struct ipv6hdr *ipv6h = skb->nh.ipv6h;
- struct ipv6_txoptions *opt = NULL;
int encap_limit = -1;
+ struct ipv6_tel_txoption opt;
__u16 offset;
struct flowi fl;
struct dst_entry *dst;
@@ -644,10 +677,9 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
goto tx_err;
}
if (skb->protocol != htons(ETH_P_IPV6) ||
- !(t->parms.flags & IP6_TNL_F_CAP_XMIT) ||
- ip6ip6_tnl_addr_conflict(t, ipv6h)) {
+ !ip6_tnl_xmit_ctl(t) || ip6ip6_tnl_addr_conflict(t, ipv6h))
goto tx_err;
- }
+
if ((offset = parse_tlv_tnl_enc_lim(skb, skb->nh.raw)) > 0) {
struct ipv6_tlv_tnl_enc_lim *tel;
tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->nh.raw[offset];
@@ -657,20 +689,17 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
goto tx_err;
}
encap_limit = tel->encap_limit - 1;
- } else if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) {
+ } else if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
encap_limit = t->parms.encap_limit;
- }
+
memcpy(&fl, &t->fl, sizeof (fl));
proto = fl.proto;
dsfield = ipv6_get_dsfield(ipv6h);
if ((t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS))
- fl.fl6_flowlabel |= (*(__u32 *) ipv6h & IPV6_TCLASS_MASK);
+ fl.fl6_flowlabel |= (*(__be32 *) ipv6h & IPV6_TCLASS_MASK);
if ((t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL))
- fl.fl6_flowlabel |= (*(__u32 *) ipv6h & IPV6_FLOWLABEL_MASK);
-
- if (encap_limit >= 0 && (opt = create_tel(encap_limit)) == NULL)
- goto tx_err;
+ fl.fl6_flowlabel |= (*(__be32 *) ipv6h & IPV6_FLOWLABEL_MASK);
if ((dst = ip6_tnl_dst_check(t)) != NULL)
dst_hold(dst);
@@ -692,7 +721,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
goto tx_err_dst_release;
}
mtu = dst_mtu(dst) - sizeof (*ipv6h);
- if (opt) {
+ if (encap_limit >= 0) {
max_headroom += 8;
mtu -= 8;
}
@@ -730,12 +759,13 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
skb->h.raw = skb->nh.raw;
- if (opt)
- ipv6_push_nfrag_opts(skb, opt, &proto, NULL);
-
+ if (encap_limit >= 0) {
+ init_tel_txopt(&opt, encap_limit);
+ ipv6_push_nfrag_opts(skb, &opt.ops, &proto, NULL);
+ }
skb->nh.raw = skb_push(skb, sizeof(struct ipv6hdr));
ipv6h = skb->nh.ipv6h;
- *(u32*)ipv6h = fl.fl6_flowlabel | htonl(0x60000000);
+ *(__be32*)ipv6h = fl.fl6_flowlabel | htonl(0x60000000);
dsfield = INET_ECN_encapsulate(0, dsfield);
ipv6_change_dsfield(ipv6h, ~INET_ECN_MASK, dsfield);
ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
@@ -748,7 +778,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL,
skb->dst->dev, dst_output);
- if (err == NET_XMIT_SUCCESS || err == NET_XMIT_CN) {
+ if (net_xmit_eval(err) == 0) {
stats->tx_bytes += pkt_len;
stats->tx_packets++;
} else {
@@ -756,9 +786,6 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
stats->tx_aborted_errors++;
}
ip6_tnl_dst_store(t, dst);
-
- kfree(opt);
-
t->recursion--;
return 0;
tx_err_link_failure:
@@ -766,7 +793,6 @@ tx_err_link_failure:
dst_link_failure(skb);
tx_err_dst_release:
dst_release(dst);
- kfree(opt);
tx_err:
stats->tx_errors++;
stats->tx_dropped++;
@@ -778,39 +804,19 @@ tx_err:
static void ip6_tnl_set_cap(struct ip6_tnl *t)
{
struct ip6_tnl_parm *p = &t->parms;
- struct in6_addr *laddr = &p->laddr;
- struct in6_addr *raddr = &p->raddr;
- int ltype = ipv6_addr_type(laddr);
- int rtype = ipv6_addr_type(raddr);
+ int ltype = ipv6_addr_type(&p->laddr);
+ int rtype = ipv6_addr_type(&p->raddr);
p->flags &= ~(IP6_TNL_F_CAP_XMIT|IP6_TNL_F_CAP_RCV);
- if (ltype != IPV6_ADDR_ANY && rtype != IPV6_ADDR_ANY &&
- ((ltype|rtype) &
- (IPV6_ADDR_UNICAST|
- IPV6_ADDR_LOOPBACK|IPV6_ADDR_LINKLOCAL|
- IPV6_ADDR_MAPPED|IPV6_ADDR_RESERVED)) == IPV6_ADDR_UNICAST) {
- struct net_device *ldev = NULL;
- int l_ok = 1;
- int r_ok = 1;
-
- if (p->link)
- ldev = dev_get_by_index(p->link);
-
- if (ltype&IPV6_ADDR_UNICAST && !ipv6_chk_addr(laddr, ldev, 0))
- l_ok = 0;
-
- if (rtype&IPV6_ADDR_UNICAST && ipv6_chk_addr(raddr, NULL, 0))
- r_ok = 0;
-
- if (l_ok && r_ok) {
- if (ltype&IPV6_ADDR_UNICAST)
- p->flags |= IP6_TNL_F_CAP_XMIT;
- if (rtype&IPV6_ADDR_UNICAST)
- p->flags |= IP6_TNL_F_CAP_RCV;
- }
- if (ldev)
- dev_put(ldev);
+ if (ltype & (IPV6_ADDR_UNICAST|IPV6_ADDR_MULTICAST) &&
+ rtype & (IPV6_ADDR_UNICAST|IPV6_ADDR_MULTICAST) &&
+ !((ltype|rtype) & IPV6_ADDR_LOOPBACK) &&
+ (!((ltype|rtype) & IPV6_ADDR_LINKLOCAL) || p->link)) {
+ if (ltype&IPV6_ADDR_UNICAST)
+ p->flags |= IP6_TNL_F_CAP_XMIT;
+ if (rtype&IPV6_ADDR_UNICAST)
+ p->flags |= IP6_TNL_F_CAP_RCV;
}
}
@@ -844,8 +850,11 @@ static void ip6ip6_tnl_link_config(struct ip6_tnl *t)
dev->iflink = p->link;
if (p->flags & IP6_TNL_F_CAP_XMIT) {
+ int strict = (ipv6_addr_type(&p->raddr) &
+ (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL));
+
struct rt6_info *rt = rt6_lookup(&p->raddr, &p->laddr,
- p->link, 0);
+ p->link, strict);
if (rt == NULL)
return;
@@ -920,26 +929,20 @@ static int
ip6ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
int err = 0;
- int create;
struct ip6_tnl_parm p;
struct ip6_tnl *t = NULL;
switch (cmd) {
case SIOCGETTUNNEL:
if (dev == ip6ip6_fb_tnl_dev) {
- if (copy_from_user(&p,
- ifr->ifr_ifru.ifru_data,
- sizeof (p))) {
+ if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p))) {
err = -EFAULT;
break;
}
- if ((err = ip6ip6_tnl_locate(&p, &t, 0)) == -ENODEV)
- t = netdev_priv(dev);
- else if (err)
- break;
- } else
+ t = ip6ip6_tnl_locate(&p, 0);
+ }
+ if (t == NULL)
t = netdev_priv(dev);
-
memcpy(&p, &t->parms, sizeof (p));
if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof (p))) {
err = -EFAULT;
@@ -948,35 +951,36 @@ ip6ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
case SIOCADDTUNNEL:
case SIOCCHGTUNNEL:
err = -EPERM;
- create = (cmd == SIOCADDTUNNEL);
if (!capable(CAP_NET_ADMIN))
break;
- if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p))) {
- err = -EFAULT;
+ err = -EFAULT;
+ if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p)))
break;
- }
- if (!create && dev != ip6ip6_fb_tnl_dev) {
- t = netdev_priv(dev);
- }
- if (!t && (err = ip6ip6_tnl_locate(&p, &t, create))) {
+ err = -EINVAL;
+ if (p.proto != IPPROTO_IPV6)
break;
- }
- if (cmd == SIOCCHGTUNNEL) {
- if (t->dev != dev) {
- err = -EEXIST;
- break;
- }
+ t = ip6ip6_tnl_locate(&p, cmd == SIOCADDTUNNEL);
+ if (dev != ip6ip6_fb_tnl_dev && cmd == SIOCCHGTUNNEL) {
+ if (t != NULL) {
+ if (t->dev != dev) {
+ err = -EEXIST;
+ break;
+ }
+ } else
+ t = netdev_priv(dev);
+
ip6ip6_tnl_unlink(t);
err = ip6ip6_tnl_change(t, &p);
ip6ip6_tnl_link(t);
netdev_state_change(dev);
}
- if (copy_to_user(ifr->ifr_ifru.ifru_data,
- &t->parms, sizeof (p))) {
- err = -EFAULT;
- } else {
+ if (t) {
err = 0;
- }
+ if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof (p)))
+ err = -EFAULT;
+
+ } else
+ err = (cmd == SIOCADDTUNNEL ? -ENOBUFS : -ENOENT);
break;
case SIOCDELTUNNEL:
err = -EPERM;
@@ -984,22 +988,18 @@ ip6ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
break;
if (dev == ip6ip6_fb_tnl_dev) {
- if (copy_from_user(&p, ifr->ifr_ifru.ifru_data,
- sizeof (p))) {
- err = -EFAULT;
+ err = -EFAULT;
+ if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p)))
break;
- }
- err = ip6ip6_tnl_locate(&p, &t, 0);
- if (err)
+ err = -ENOENT;
+ if ((t = ip6ip6_tnl_locate(&p, 0)) == NULL)
break;
- if (t == netdev_priv(ip6ip6_fb_tnl_dev)) {
- err = -EPERM;
+ err = -EPERM;
+ if (t->dev == ip6ip6_fb_tnl_dev)
break;
- }
- } else {
- t = netdev_priv(dev);
+ dev = t->dev;
}
- err = unregister_netdevice(t->dev);
+ err = unregister_netdevice(dev);
break;
default:
err = -EINVAL;
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index 71f59f18ede8..511730b67e97 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -176,7 +176,7 @@ out_ok:
}
static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
- int type, int code, int offset, __u32 info)
+ int type, int code, int offset, __be32 info)
{
__be32 spi;
struct ipv6hdr *iph = (struct ipv6hdr*)skb->data;
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index de6b91981b30..1eafcfc95e81 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -51,6 +51,7 @@
#include <net/inet_common.h>
#include <net/tcp.h>
#include <net/udp.h>
+#include <net/udplite.h>
#include <net/xfrm.h>
#include <asm/uaccess.h>
@@ -239,6 +240,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
struct sk_buff *pktopt;
if (sk->sk_protocol != IPPROTO_UDP &&
+ sk->sk_protocol != IPPROTO_UDPLITE &&
sk->sk_protocol != IPPROTO_TCP)
break;
@@ -276,11 +278,15 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
sk->sk_family = PF_INET;
tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
} else {
+ struct proto *prot = &udp_prot;
+
+ if (sk->sk_protocol == IPPROTO_UDPLITE)
+ prot = &udplite_prot;
local_bh_disable();
sock_prot_dec_use(sk->sk_prot);
- sock_prot_inc_use(&udp_prot);
+ sock_prot_inc_use(prot);
local_bh_enable();
- sk->sk_prot = &udp_prot;
+ sk->sk_prot = prot;
sk->sk_socket->ops = &inet_dgram_ops;
sk->sk_family = PF_INET;
}
@@ -813,6 +819,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
switch (optname) {
case IPV6_ADDRFORM:
if (sk->sk_protocol != IPPROTO_UDP &&
+ sk->sk_protocol != IPPROTO_UDPLITE &&
sk->sk_protocol != IPPROTO_TCP)
return -EINVAL;
if (sk->sk_state != TCP_ESTABLISHED)
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 3b114e3fa2f8..a1c231a04ac2 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -83,7 +83,7 @@
struct mld2_grec {
__u8 grec_type;
__u8 grec_auxwords;
- __u16 grec_nsrcs;
+ __be16 grec_nsrcs;
struct in6_addr grec_mca;
struct in6_addr grec_src[0];
};
@@ -91,18 +91,18 @@ struct mld2_grec {
struct mld2_report {
__u8 type;
__u8 resv1;
- __u16 csum;
- __u16 resv2;
- __u16 ngrec;
+ __sum16 csum;
+ __be16 resv2;
+ __be16 ngrec;
struct mld2_grec grec[0];
};
struct mld2_query {
__u8 type;
__u8 code;
- __u16 csum;
- __u16 mrc;
- __u16 resv1;
+ __sum16 csum;
+ __be16 mrc;
+ __be16 resv1;
struct in6_addr mca;
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 qrv:3,
@@ -116,7 +116,7 @@ struct mld2_query {
#error "Please fix <asm/byteorder.h>"
#endif
__u8 qqic;
- __u16 nsrcs;
+ __be16 nsrcs;
struct in6_addr srcs[0];
};
@@ -1465,7 +1465,7 @@ static void mld_sendpack(struct sk_buff *skb)
struct inet6_dev *idev = in6_dev_get(skb->dev);
int err;
- IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
+ IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS);
payload_len = skb->tail - (unsigned char *)skb->nh.ipv6h -
sizeof(struct ipv6hdr);
mldlen = skb->tail - skb->h.raw;
@@ -1477,9 +1477,9 @@ static void mld_sendpack(struct sk_buff *skb)
mld_dev_queue_xmit);
if (!err) {
ICMP6_INC_STATS(idev,ICMP6_MIB_OUTMSGS);
- IP6_INC_STATS(IPSTATS_MIB_OUTMCASTPKTS);
+ IP6_INC_STATS(idev, IPSTATS_MIB_OUTMCASTPKTS);
} else
- IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS);
+ IP6_INC_STATS(idev, IPSTATS_MIB_OUTDISCARDS);
if (likely(idev != NULL))
in6_dev_put(idev);
@@ -1763,7 +1763,10 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
IPV6_TLV_ROUTERALERT, 2, 0, 0,
IPV6_TLV_PADN, 0 };
- IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
+ rcu_read_lock();
+ IP6_INC_STATS(__in6_dev_get(dev),
+ IPSTATS_MIB_OUTREQUESTS);
+ rcu_read_unlock();
snd_addr = addr;
if (type == ICMPV6_MGM_REDUCTION) {
snd_addr = &all_routers;
@@ -1777,7 +1780,10 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
skb = sock_alloc_send_skb(sk, LL_RESERVED_SPACE(dev) + full_len, 1, &err);
if (skb == NULL) {
- IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS);
+ rcu_read_lock();
+ IP6_INC_STATS(__in6_dev_get(dev),
+ IPSTATS_MIB_OUTDISCARDS);
+ rcu_read_unlock();
return;
}
@@ -1816,9 +1822,9 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
else
ICMP6_INC_STATS(idev, ICMP6_MIB_OUTGROUPMEMBRESPONSES);
ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
- IP6_INC_STATS(IPSTATS_MIB_OUTMCASTPKTS);
+ IP6_INC_STATS(idev, IPSTATS_MIB_OUTMCASTPKTS);
} else
- IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS);
+ IP6_INC_STATS(idev, IPSTATS_MIB_OUTDISCARDS);
if (likely(idev != NULL))
in6_dev_put(idev);
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c
index 7ccdc8fc5a31..be7dd7db65d7 100644
--- a/net/ipv6/mip6.c
+++ b/net/ipv6/mip6.c
@@ -262,10 +262,10 @@ static int mip6_destopt_reject(struct xfrm_state *x, struct sk_buff *skb, struct
sel.proto = fl->proto;
sel.dport = xfrm_flowi_dport(fl);
if (sel.dport)
- sel.dport_mask = ~((__u16)0);
+ sel.dport_mask = htons(~0);
sel.sport = xfrm_flowi_sport(fl);
if (sel.sport)
- sel.sport_mask = ~((__u16)0);
+ sel.sport_mask = htons(~0);
sel.ifindex = fl->oif;
err = km_report(IPPROTO_DSTOPTS, &sel,
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 73eb8c33e9f0..56ea92837307 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -472,7 +472,9 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
inc_opt = 0;
}
- skb = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev),
+ skb = sock_alloc_send_skb(sk,
+ (MAX_HEADER + sizeof(struct ipv6hdr) +
+ len + LL_RESERVED_SPACE(dev)),
1, &err);
if (skb == NULL) {
@@ -513,7 +515,7 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
skb->dst = dst;
idev = in6_dev_get(dst->dev);
- IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
+ IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS);
err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
if (!err) {
ICMP6_INC_STATS(idev, ICMP6_MIB_OUTNEIGHBORADVERTISEMENTS);
@@ -561,7 +563,9 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
if (send_llinfo)
len += ndisc_opt_addr_space(dev);
- skb = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev),
+ skb = sock_alloc_send_skb(sk,
+ (MAX_HEADER + sizeof(struct ipv6hdr) +
+ len + LL_RESERVED_SPACE(dev)),
1, &err);
if (skb == NULL) {
ND_PRINTK0(KERN_ERR
@@ -597,7 +601,7 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
/* send it! */
skb->dst = dst;
idev = in6_dev_get(dst->dev);
- IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
+ IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS);
err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
if (!err) {
ICMP6_INC_STATS(idev, ICMP6_MIB_OUTNEIGHBORSOLICITS);
@@ -636,7 +640,9 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
if (dev->addr_len)
len += ndisc_opt_addr_space(dev);
- skb = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev),
+ skb = sock_alloc_send_skb(sk,
+ (MAX_HEADER + sizeof(struct ipv6hdr) +
+ len + LL_RESERVED_SPACE(dev)),
1, &err);
if (skb == NULL) {
ND_PRINTK0(KERN_ERR
@@ -670,7 +676,7 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
/* send it! */
skb->dst = dst;
idev = in6_dev_get(dst->dev);
- IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
+ IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS);
err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
if (!err) {
ICMP6_INC_STATS(idev, ICMP6_MIB_OUTROUTERSOLICITS);
@@ -1261,10 +1267,11 @@ skip_defrtr:
}
if (ndopts.nd_opts_mtu) {
+ __be32 n;
u32 mtu;
- memcpy(&mtu, ((u8*)(ndopts.nd_opts_mtu+1))+2, sizeof(mtu));
- mtu = ntohl(mtu);
+ memcpy(&n, ((u8*)(ndopts.nd_opts_mtu+1))+2, sizeof(mtu));
+ mtu = ntohl(n);
if (mtu < IPV6_MIN_MTU || mtu > skb->dev->mtu) {
ND_PRINTK2(KERN_WARNING
@@ -1446,7 +1453,9 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
rd_len &= ~0x7;
len += rd_len;
- buff = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev),
+ buff = sock_alloc_send_skb(sk,
+ (MAX_HEADER + sizeof(struct ipv6hdr) +
+ len + LL_RESERVED_SPACE(dev)),
1, &err);
if (buff == NULL) {
ND_PRINTK0(KERN_ERR
@@ -1504,7 +1513,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
buff->dst = dst;
idev = in6_dev_get(dst->dev);
- IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
+ IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS);
err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, buff, NULL, dst->dev, dst_output);
if (!err) {
ICMP6_INC_STATS(idev, ICMP6_MIB_OUTREDIRECTS);
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
index 580b1aba6722..f6294e5bcb31 100644
--- a/net/ipv6/netfilter.c
+++ b/net/ipv6/netfilter.c
@@ -31,7 +31,7 @@ int ip6_route_me_harder(struct sk_buff *skb)
#endif
if (dst->error) {
- IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES);
+ IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
LIMIT_NETDEBUG(KERN_DEBUG "ip6_route_me_harder: No more route.\n");
dst_release(dst);
return -EINVAL;
@@ -80,11 +80,11 @@ static int nf_ip6_reroute(struct sk_buff **pskb, const struct nf_info *info)
return 0;
}
-unsigned int nf_ip6_checksum(struct sk_buff *skb, unsigned int hook,
+__sum16 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;
+ __sum16 csum = 0;
switch (skb->ip_summed) {
case CHECKSUM_COMPLETE:
@@ -100,12 +100,13 @@ unsigned int nf_ip6_checksum(struct sk_buff *skb, unsigned int hook,
}
/* fall through */
case CHECKSUM_NONE:
- skb->csum = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
+ skb->csum = ~csum_unfold(
+ csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
skb->len - dataoff,
protocol,
csum_sub(0,
skb_checksum(skb, 0,
- dataoff, 0)));
+ dataoff, 0))));
csum = __skb_checksum_complete(skb);
}
return csum;
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index d7c45a9c15fe..fc3e5eb4bc3f 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -6,7 +6,7 @@ menu "IPv6: Netfilter Configuration (EXPERIMENTAL)"
depends on INET && IPV6 && NETFILTER && EXPERIMENTAL
config NF_CONNTRACK_IPV6
- tristate "IPv6 support for new connection tracking (EXPERIMENTAL)"
+ tristate "IPv6 connection tracking support (EXPERIMENTAL)"
depends on EXPERIMENTAL && NF_CONNTRACK
---help---
Connection tracking keeps a record of what packets have passed
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index 9fec832ee08b..d4d9f182441a 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -241,7 +241,7 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp)
pmsg->data_len = data_len;
pmsg->timestamp_sec = entry->skb->tstamp.off_sec;
pmsg->timestamp_usec = entry->skb->tstamp.off_usec;
- pmsg->mark = entry->skb->nfmark;
+ pmsg->mark = entry->skb->mark;
pmsg->hook = entry->info->hook;
pmsg->hw_protocol = entry->skb->protocol;
@@ -620,6 +620,7 @@ static ctl_table ipq_root_table[] = {
{ .ctl_name = 0 }
};
+#ifdef CONFIG_PROC_FS
static int
ipq_get_info(char *buffer, char **start, off_t offset, int length)
{
@@ -653,6 +654,7 @@ ipq_get_info(char *buffer, char **start, off_t offset, int length)
len = 0;
return len;
}
+#endif /* CONFIG_PROC_FS */
static struct nf_queue_handler nfqh = {
.name = "ip6_queue",
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 204e02162d49..f63fb86d7c7b 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -1481,7 +1481,8 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
if (hp == NULL)
return -EBADMSG;
if (nexthdr == NEXTHDR_FRAGMENT) {
- unsigned short _frag_off, *fp;
+ unsigned short _frag_off;
+ __be16 *fp;
fp = skb_header_pointer(skb,
start+offsetof(struct frag_hdr,
frag_off),
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
index 0cf537d30185..33b1faa90d74 100644
--- a/net/ipv6/netfilter/ip6t_LOG.c
+++ b/net/ipv6/netfilter/ip6t_LOG.c
@@ -69,9 +69,9 @@ static void dump_packet(const struct nf_loginfo *info,
/* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */
printk("LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ",
ntohs(ih->payload_len) + sizeof(struct ipv6hdr),
- (ntohl(*(u_int32_t *)ih) & 0x0ff00000) >> 20,
+ (ntohl(*(__be32 *)ih) & 0x0ff00000) >> 20,
ih->hop_limit,
- (ntohl(*(u_int32_t *)ih) & 0x000fffff));
+ (ntohl(*(__be32 *)ih) & 0x000fffff));
fragment = 0;
ptr = ip6hoff + sizeof(struct ipv6hdr);
@@ -270,11 +270,15 @@ static void dump_packet(const struct nf_loginfo *info,
}
break;
}
- case IPPROTO_UDP: {
+ case IPPROTO_UDP:
+ case IPPROTO_UDPLITE: {
struct udphdr _udph, *uh;
- /* Max length: 10 "PROTO=UDP " */
- printk("PROTO=UDP ");
+ if (currenthdr == IPPROTO_UDP)
+ /* Max length: 10 "PROTO=UDP " */
+ printk("PROTO=UDP " );
+ else /* Max length: 14 "PROTO=UDPLITE " */
+ printk("PROTO=UDPLITE ");
if (fragment)
break;
@@ -436,13 +440,8 @@ ip6t_log_target(struct sk_buff **pskb,
li.u.log.level = loginfo->level;
li.u.log.logflags = loginfo->logflags;
- if (loginfo->logflags & IP6T_LOG_NFLOG)
- nf_log_packet(PF_INET6, hooknum, *pskb, in, out, &li,
- "%s", loginfo->prefix);
- else
- ip6t_log_packet(PF_INET6, hooknum, *pskb, in, out, &li,
- loginfo->prefix);
-
+ ip6t_log_packet(PF_INET6, hooknum, *pskb, in, out, &li,
+ loginfo->prefix);
return IP6T_CONTINUE;
}
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index 386ea260e767..6250e86a6ddc 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -149,11 +149,10 @@ ip6t_local_hook(unsigned int hook,
int (*okfn)(struct sk_buff *))
{
- unsigned long nfmark;
unsigned int ret;
struct in6_addr saddr, daddr;
u_int8_t hop_limit;
- u_int32_t flowlabel;
+ u_int32_t flowlabel, mark;
#if 0
/* root is playing with raw sockets. */
@@ -165,10 +164,10 @@ ip6t_local_hook(unsigned int hook,
}
#endif
- /* save source/dest address, nfmark, hoplimit, flowlabel, priority, */
+ /* save source/dest address, mark, hoplimit, flowlabel, priority, */
memcpy(&saddr, &(*pskb)->nh.ipv6h->saddr, sizeof(saddr));
memcpy(&daddr, &(*pskb)->nh.ipv6h->daddr, sizeof(daddr));
- nfmark = (*pskb)->nfmark;
+ mark = (*pskb)->mark;
hop_limit = (*pskb)->nh.ipv6h->hop_limit;
/* flowlabel and prio (includes version, which shouldn't change either */
@@ -179,7 +178,7 @@ ip6t_local_hook(unsigned int hook,
if (ret != NF_DROP && ret != NF_STOLEN
&& (memcmp(&(*pskb)->nh.ipv6h->saddr, &saddr, sizeof(saddr))
|| memcmp(&(*pskb)->nh.ipv6h->daddr, &daddr, sizeof(daddr))
- || (*pskb)->nfmark != nfmark
+ || (*pskb)->mark != mark
|| (*pskb)->nh.ipv6h->hop_limit != hop_limit))
return ip6_route_me_harder(*pskb) == 0 ? ret : NF_DROP;
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index e5e53fff9e38..a20615ffccff 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -33,7 +33,7 @@
#include <linux/netfilter_ipv6.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_helper.h>
-#include <net/netfilter/nf_conntrack_protocol.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_l3proto.h>
#include <net/netfilter/nf_conntrack_core.h>
@@ -43,8 +43,6 @@
#define DEBUGP(format, args...)
#endif
-DECLARE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat);
-
static int ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
struct nf_conntrack_tuple *tuple)
{
@@ -211,11 +209,6 @@ out:
return nf_conntrack_confirm(pskb);
}
-extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb);
-extern void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb,
- struct net_device *in,
- struct net_device *out,
- int (*okfn)(struct sk_buff *));
static unsigned int ipv6_defrag(unsigned int hooknum,
struct sk_buff **pskb,
const struct net_device *in,
@@ -331,26 +324,7 @@ static struct nf_hook_ops ipv6_conntrack_ops[] = {
};
#ifdef CONFIG_SYSCTL
-
-/* From nf_conntrack_proto_icmpv6.c */
-extern unsigned int nf_ct_icmpv6_timeout;
-
-/* From nf_conntrack_reasm.c */
-extern unsigned int nf_ct_frag6_timeout;
-extern unsigned int nf_ct_frag6_low_thresh;
-extern unsigned int nf_ct_frag6_high_thresh;
-
-static struct ctl_table_header *nf_ct_ipv6_sysctl_header;
-
-static ctl_table nf_ct_sysctl_table[] = {
- {
- .ctl_name = NET_NF_CONNTRACK_ICMPV6_TIMEOUT,
- .procname = "nf_conntrack_icmpv6_timeout",
- .data = &nf_ct_icmpv6_timeout,
- .maxlen = sizeof(unsigned int),
- .mode = 0644,
- .proc_handler = &proc_dointvec_jiffies,
- },
+static ctl_table nf_ct_ipv6_sysctl_table[] = {
{
.ctl_name = NET_NF_CONNTRACK_FRAG6_TIMEOUT,
.procname = "nf_conntrack_frag6_timeout",
@@ -377,26 +351,6 @@ static ctl_table nf_ct_sysctl_table[] = {
},
{ .ctl_name = 0 }
};
-
-static ctl_table nf_ct_netfilter_table[] = {
- {
- .ctl_name = NET_NETFILTER,
- .procname = "netfilter",
- .mode = 0555,
- .child = nf_ct_sysctl_table,
- },
- { .ctl_name = 0 }
-};
-
-static ctl_table nf_ct_net_table[] = {
- {
- .ctl_name = CTL_NET,
- .procname = "net",
- .mode = 0555,
- .child = nf_ct_netfilter_table,
- },
- { .ctl_name = 0 }
-};
#endif
#if defined(CONFIG_NF_CT_NETLINK) || \
@@ -454,16 +408,14 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 = {
.tuple_to_nfattr = ipv6_tuple_to_nfattr,
.nfattr_to_tuple = ipv6_nfattr_to_tuple,
#endif
+#ifdef CONFIG_SYSCTL
+ .ctl_table_path = nf_net_netfilter_sysctl_path,
+ .ctl_table = nf_ct_ipv6_sysctl_table,
+#endif
.get_features = ipv6_get_features,
.me = THIS_MODULE,
};
-extern struct nf_conntrack_protocol nf_conntrack_protocol_tcp6;
-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);
-
MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6));
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>");
@@ -479,19 +431,19 @@ static int __init nf_conntrack_l3proto_ipv6_init(void)
printk("nf_conntrack_ipv6: can't initialize frag6.\n");
return ret;
}
- ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp6);
+ ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_tcp6);
if (ret < 0) {
printk("nf_conntrack_ipv6: can't register tcp.\n");
goto cleanup_frag6;
}
- ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_udp6);
+ ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udp6);
if (ret < 0) {
printk("nf_conntrack_ipv6: can't register udp.\n");
goto cleanup_tcp;
}
- ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_icmpv6);
+ ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_icmpv6);
if (ret < 0) {
printk("nf_conntrack_ipv6: can't register icmpv6.\n");
goto cleanup_udp;
@@ -510,28 +462,16 @@ static int __init nf_conntrack_l3proto_ipv6_init(void)
"hook.\n");
goto cleanup_ipv6;
}
-#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_hooks;
- }
-#endif
return ret;
-#ifdef CONFIG_SYSCTL
- cleanup_hooks:
- nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
-#endif
cleanup_ipv6:
nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6);
cleanup_icmpv6:
- nf_conntrack_protocol_unregister(&nf_conntrack_protocol_icmpv6);
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmpv6);
cleanup_udp:
- nf_conntrack_protocol_unregister(&nf_conntrack_protocol_udp6);
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp6);
cleanup_tcp:
- nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp6);
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp6);
cleanup_frag6:
nf_ct_frag6_cleanup();
return ret;
@@ -540,14 +480,11 @@ static int __init nf_conntrack_l3proto_ipv6_init(void)
static void __exit nf_conntrack_l3proto_ipv6_fini(void)
{
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_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmpv6);
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp6);
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp6);
nf_ct_frag6_cleanup();
}
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
index 34d447208ffd..3905cacc69af 100644
--- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
@@ -29,11 +29,11 @@
#include <linux/seq_file.h>
#include <linux/netfilter_ipv6.h>
#include <net/netfilter/nf_conntrack_tuple.h>
-#include <net/netfilter/nf_conntrack_protocol.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/ipv6/nf_conntrack_icmpv6.h>
-unsigned long nf_ct_icmpv6_timeout __read_mostly = 30*HZ;
+static unsigned long nf_ct_icmpv6_timeout __read_mostly = 30*HZ;
#if 0
#define DEBUGP printk
@@ -142,9 +142,6 @@ static int icmpv6_new(struct nf_conn *conntrack,
return 1;
}
-extern int
-nf_ct_ipv6_skip_exthdr(struct sk_buff *skb, int start, u8 *nexthdrp, int len);
-extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6;
static int
icmpv6_error_message(struct sk_buff *skb,
unsigned int icmp6off,
@@ -155,7 +152,7 @@ icmpv6_error_message(struct sk_buff *skb,
struct nf_conntrack_tuple_hash *h;
struct icmp6hdr _hdr, *hp;
unsigned int inip6off;
- struct nf_conntrack_protocol *inproto;
+ struct nf_conntrack_l4proto *inproto;
u_int8_t inprotonum;
unsigned int inprotoff;
@@ -185,7 +182,7 @@ icmpv6_error_message(struct sk_buff *skb,
return -NF_ACCEPT;
}
- inproto = __nf_ct_proto_find(PF_INET6, inprotonum);
+ inproto = __nf_ct_l4proto_find(PF_INET6, inprotonum);
/* Are they talking about one of our connections? */
if (!nf_ct_get_tuple(skb, inip6off, inprotoff, PF_INET6, inprotonum,
@@ -290,7 +287,7 @@ static int icmpv6_nfattr_to_tuple(struct nfattr *tb[],
tuple->dst.u.icmp.code =
*(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMPV6_CODE-1]);
tuple->src.u.icmp.id =
- *(u_int16_t *)NFA_DATA(tb[CTA_PROTO_ICMPV6_ID-1]);
+ *(__be16 *)NFA_DATA(tb[CTA_PROTO_ICMPV6_ID-1]);
if (tuple->dst.u.icmp.type < 128
|| tuple->dst.u.icmp.type - 128 >= sizeof(invmap)
@@ -301,10 +298,27 @@ static int icmpv6_nfattr_to_tuple(struct nfattr *tb[],
}
#endif
-struct nf_conntrack_protocol nf_conntrack_protocol_icmpv6 =
+#ifdef CONFIG_SYSCTL
+static struct ctl_table_header *icmpv6_sysctl_header;
+static struct ctl_table icmpv6_sysctl_table[] = {
+ {
+ .ctl_name = NET_NF_CONNTRACK_ICMPV6_TIMEOUT,
+ .procname = "nf_conntrack_icmpv6_timeout",
+ .data = &nf_ct_icmpv6_timeout,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = 0
+ }
+};
+#endif /* CONFIG_SYSCTL */
+
+struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 =
{
.l3proto = PF_INET6,
- .proto = IPPROTO_ICMPV6,
+ .l4proto = IPPROTO_ICMPV6,
.name = "icmpv6",
.pkt_to_tuple = icmpv6_pkt_to_tuple,
.invert_tuple = icmpv6_invert_tuple,
@@ -318,6 +332,10 @@ struct nf_conntrack_protocol nf_conntrack_protocol_icmpv6 =
.tuple_to_nfattr = icmpv6_tuple_to_nfattr,
.nfattr_to_tuple = icmpv6_nfattr_to_tuple,
#endif
+#ifdef CONFIG_SYSCTL
+ .ctl_table_header = &icmpv6_sysctl_header,
+ .ctl_table = icmpv6_sysctl_table,
+#endif
};
-EXPORT_SYMBOL(nf_conntrack_protocol_icmpv6);
+EXPORT_SYMBOL(nf_conntrack_l4proto_icmpv6);
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index bf93c1ea6be9..37e5fca923aa 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -72,7 +72,7 @@ struct nf_ct_frag6_queue
struct hlist_node list;
struct list_head lru_list; /* lru list member */
- __u32 id; /* fragment id */
+ __be32 id; /* fragment id */
struct in6_addr saddr;
struct in6_addr daddr;
@@ -115,28 +115,28 @@ static __inline__ void fq_unlink(struct nf_ct_frag6_queue *fq)
write_unlock(&nf_ct_frag6_lock);
}
-static unsigned int ip6qhashfn(u32 id, struct in6_addr *saddr,
+static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr,
struct in6_addr *daddr)
{
u32 a, b, c;
- a = saddr->s6_addr32[0];
- b = saddr->s6_addr32[1];
- c = saddr->s6_addr32[2];
+ a = (__force u32)saddr->s6_addr32[0];
+ b = (__force u32)saddr->s6_addr32[1];
+ c = (__force u32)saddr->s6_addr32[2];
a += JHASH_GOLDEN_RATIO;
b += JHASH_GOLDEN_RATIO;
c += nf_ct_frag6_hash_rnd;
__jhash_mix(a, b, c);
- a += saddr->s6_addr32[3];
- b += daddr->s6_addr32[0];
- c += daddr->s6_addr32[1];
+ a += (__force u32)saddr->s6_addr32[3];
+ b += (__force u32)daddr->s6_addr32[0];
+ c += (__force u32)daddr->s6_addr32[1];
__jhash_mix(a, b, c);
- a += daddr->s6_addr32[2];
- b += daddr->s6_addr32[3];
- c += id;
+ a += (__force u32)daddr->s6_addr32[2];
+ b += (__force u32)daddr->s6_addr32[3];
+ c += (__force u32)id;
__jhash_mix(a, b, c);
return c & (FRAG6Q_HASHSZ - 1);
@@ -338,7 +338,7 @@ static struct nf_ct_frag6_queue *nf_ct_frag6_intern(unsigned int hash,
static struct nf_ct_frag6_queue *
-nf_ct_frag6_create(unsigned int hash, u32 id, struct in6_addr *src, struct in6_addr *dst)
+nf_ct_frag6_create(unsigned int hash, __be32 id, struct in6_addr *src, struct in6_addr *dst)
{
struct nf_ct_frag6_queue *fq;
@@ -366,7 +366,7 @@ oom:
}
static __inline__ struct nf_ct_frag6_queue *
-fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst)
+fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst)
{
struct nf_ct_frag6_queue *fq;
struct hlist_node *n;
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index efee7a6301a8..35249d8487bb 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -49,6 +49,8 @@ static int sockstat6_seq_show(struct seq_file *seq, void *v)
fold_prot_inuse(&tcpv6_prot));
seq_printf(seq, "UDP6: inuse %d\n",
fold_prot_inuse(&udpv6_prot));
+ seq_printf(seq, "UDPLITE6: inuse %d\n",
+ fold_prot_inuse(&udplitev6_prot));
seq_printf(seq, "RAW6: inuse %d\n",
fold_prot_inuse(&rawv6_prot));
seq_printf(seq, "FRAG6: inuse %d memory %d\n",
@@ -133,6 +135,14 @@ static struct snmp_mib snmp6_udp6_list[] = {
SNMP_MIB_SENTINEL
};
+static struct snmp_mib snmp6_udplite6_list[] = {
+ SNMP_MIB_ITEM("UdpLite6InDatagrams", UDP_MIB_INDATAGRAMS),
+ SNMP_MIB_ITEM("UdpLite6NoPorts", UDP_MIB_NOPORTS),
+ SNMP_MIB_ITEM("UdpLite6InErrors", UDP_MIB_INERRORS),
+ SNMP_MIB_ITEM("UdpLite6OutDatagrams", UDP_MIB_OUTDATAGRAMS),
+ SNMP_MIB_SENTINEL
+};
+
static unsigned long
fold_field(void *mib[], int offt)
{
@@ -161,11 +171,13 @@ static int snmp6_seq_show(struct seq_file *seq, void *v)
if (idev) {
seq_printf(seq, "%-32s\t%u\n", "ifIndex", idev->dev->ifindex);
+ snmp6_seq_show_item(seq, (void **)idev->stats.ipv6, snmp6_ipstats_list);
snmp6_seq_show_item(seq, (void **)idev->stats.icmpv6, snmp6_icmp6_list);
} else {
snmp6_seq_show_item(seq, (void **)ipv6_statistics, snmp6_ipstats_list);
snmp6_seq_show_item(seq, (void **)icmpv6_statistics, snmp6_icmp6_list);
snmp6_seq_show_item(seq, (void **)udp_stats_in6, snmp6_udp6_list);
+ snmp6_seq_show_item(seq, (void **)udplite_stats_in6, snmp6_udplite6_list);
}
return 0;
}
@@ -281,6 +293,9 @@ int snmp6_alloc_dev(struct inet6_dev *idev)
if (!idev || !idev->dev)
return -EINVAL;
+ if (snmp6_mib_init((void **)idev->stats.ipv6, sizeof(struct ipstats_mib),
+ __alignof__(struct ipstats_mib)) < 0)
+ goto err_ip;
if (snmp6_mib_init((void **)idev->stats.icmpv6, sizeof(struct icmpv6_mib),
__alignof__(struct icmpv6_mib)) < 0)
goto err_icmp;
@@ -288,12 +303,15 @@ int snmp6_alloc_dev(struct inet6_dev *idev)
return 0;
err_icmp:
+ snmp6_mib_free((void **)idev->stats.ipv6);
+err_ip:
return err;
}
int snmp6_free_dev(struct inet6_dev *idev)
{
snmp6_mib_free((void **)idev->stats.icmpv6);
+ snmp6_mib_free((void **)idev->stats.ipv6);
return 0;
}
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index d6dedc4aec77..c2e629d6aea4 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -220,7 +220,7 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
struct inet_sock *inet = inet_sk(sk);
struct ipv6_pinfo *np = inet6_sk(sk);
struct sockaddr_in6 *addr = (struct sockaddr_in6 *) uaddr;
- __u32 v4addr = 0;
+ __be32 v4addr = 0;
int addr_type;
int err;
@@ -290,7 +290,7 @@ out:
void rawv6_err(struct sock *sk, struct sk_buff *skb,
struct inet6_skb_parm *opt,
- int type, int code, int offset, u32 info)
+ int type, int code, int offset, __be32 info)
{
struct inet_sock *inet = inet_sk(sk);
struct ipv6_pinfo *np = inet6_sk(sk);
@@ -370,9 +370,9 @@ int rawv6_rcv(struct sock *sk, struct sk_buff *skb)
skb->ip_summed = CHECKSUM_UNNECESSARY;
}
if (skb->ip_summed != CHECKSUM_UNNECESSARY)
- skb->csum = ~csum_ipv6_magic(&skb->nh.ipv6h->saddr,
+ skb->csum = ~csum_unfold(csum_ipv6_magic(&skb->nh.ipv6h->saddr,
&skb->nh.ipv6h->daddr,
- skb->len, inet->num, 0);
+ skb->len, inet->num, 0));
if (inet->hdrincl) {
if (skb_checksum_complete(skb)) {
@@ -479,8 +479,8 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi *fl,
int offset;
int len;
int total_len;
- u32 tmp_csum;
- u16 csum;
+ __wsum tmp_csum;
+ __sum16 csum;
if (!rp->checksum)
goto send;
@@ -530,16 +530,15 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi *fl,
/* in case cksum was not initialized */
if (unlikely(csum))
- tmp_csum = csum_sub(tmp_csum, csum);
+ tmp_csum = csum_sub(tmp_csum, csum_unfold(csum));
- tmp_csum = csum_ipv6_magic(&fl->fl6_src,
+ csum = csum_ipv6_magic(&fl->fl6_src,
&fl->fl6_dst,
total_len, fl->proto, tmp_csum);
- if (tmp_csum == 0)
- tmp_csum = -1;
+ if (csum == 0 && fl->proto == IPPROTO_UDP)
+ csum = CSUM_MANGLED_0;
- csum = tmp_csum;
if (skb_store_bits(skb, offset, &csum, 2))
BUG();
@@ -586,7 +585,7 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length,
if (err)
goto error_fault;
- IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
+ IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS);
err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
dst_output);
if (err > 0)
@@ -600,7 +599,7 @@ error_fault:
err = -EFAULT;
kfree_skb(skb);
error:
- IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS);
+ IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS);
return err;
}
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index f39bbedd1327..6f9a9046510f 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -47,6 +47,7 @@
#include <net/snmp.h>
#include <net/ipv6.h>
+#include <net/ip6_route.h>
#include <net/protocol.h>
#include <net/transp_v6.h>
#include <net/rawv6.h>
@@ -76,7 +77,7 @@ struct frag_queue
struct hlist_node list;
struct list_head lru_list; /* lru list member */
- __u32 id; /* fragment id */
+ __be32 id; /* fragment id */
struct in6_addr saddr;
struct in6_addr daddr;
@@ -124,28 +125,28 @@ static __inline__ void fq_unlink(struct frag_queue *fq)
* 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,
+static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr,
struct in6_addr *daddr)
{
u32 a, b, c;
- a = saddr->s6_addr32[0];
- b = saddr->s6_addr32[1];
- c = saddr->s6_addr32[2];
+ a = (__force u32)saddr->s6_addr32[0];
+ b = (__force u32)saddr->s6_addr32[1];
+ c = (__force u32)saddr->s6_addr32[2];
a += JHASH_GOLDEN_RATIO;
b += JHASH_GOLDEN_RATIO;
c += ip6_frag_hash_rnd;
__jhash_mix(a, b, c);
- a += saddr->s6_addr32[3];
- b += daddr->s6_addr32[0];
- c += daddr->s6_addr32[1];
+ a += (__force u32)saddr->s6_addr32[3];
+ b += (__force u32)daddr->s6_addr32[0];
+ c += (__force u32)daddr->s6_addr32[1];
__jhash_mix(a, b, c);
- a += daddr->s6_addr32[2];
- b += daddr->s6_addr32[3];
- c += id;
+ a += (__force u32)daddr->s6_addr32[2];
+ b += (__force u32)daddr->s6_addr32[3];
+ c += (__force u32)id;
__jhash_mix(a, b, c);
return c & (IP6Q_HASHSZ - 1);
@@ -257,7 +258,7 @@ static __inline__ void fq_kill(struct frag_queue *fq)
}
}
-static void ip6_evictor(void)
+static void ip6_evictor(struct inet6_dev *idev)
{
struct frag_queue *fq;
struct list_head *tmp;
@@ -284,14 +285,14 @@ static void ip6_evictor(void)
spin_unlock(&fq->lock);
fq_put(fq, &work);
- IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
+ IP6_INC_STATS_BH(idev, IPSTATS_MIB_REASMFAILS);
}
}
static void ip6_frag_expire(unsigned long data)
{
struct frag_queue *fq = (struct frag_queue *) data;
- struct net_device *dev;
+ struct net_device *dev = NULL;
spin_lock(&fq->lock);
@@ -300,17 +301,19 @@ static void ip6_frag_expire(unsigned long data)
fq_kill(fq);
- IP6_INC_STATS_BH(IPSTATS_MIB_REASMTIMEOUT);
- IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
+ dev = dev_get_by_index(fq->iif);
+ if (!dev)
+ goto out;
+
+ rcu_read_lock();
+ IP6_INC_STATS_BH(__in6_dev_get(dev), IPSTATS_MIB_REASMTIMEOUT);
+ IP6_INC_STATS_BH(__in6_dev_get(dev), IPSTATS_MIB_REASMFAILS);
+ rcu_read_unlock();
/* Don't send error if the first segment did not arrive. */
if (!(fq->last_in&FIRST_IN) || !fq->fragments)
goto out;
- dev = dev_get_by_index(fq->iif);
- if (!dev)
- goto out;
-
/*
But use as source device on which LAST ARRIVED
segment was received. And do not use fq->dev
@@ -318,8 +321,9 @@ static void ip6_frag_expire(unsigned long data)
*/
fq->fragments->dev = dev;
icmpv6_send(fq->fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0, dev);
- dev_put(dev);
out:
+ if (dev)
+ dev_put(dev);
spin_unlock(&fq->lock);
fq_put(fq, NULL);
}
@@ -366,7 +370,8 @@ static struct frag_queue *ip6_frag_intern(struct frag_queue *fq_in)
static struct frag_queue *
-ip6_frag_create(u32 id, struct in6_addr *src, struct in6_addr *dst)
+ip6_frag_create(__be32 id, struct in6_addr *src, struct in6_addr *dst,
+ struct inet6_dev *idev)
{
struct frag_queue *fq;
@@ -386,12 +391,13 @@ ip6_frag_create(u32 id, struct in6_addr *src, struct in6_addr *dst)
return ip6_frag_intern(fq);
oom:
- IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
+ IP6_INC_STATS_BH(idev, IPSTATS_MIB_REASMFAILS);
return NULL;
}
static __inline__ struct frag_queue *
-fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst)
+fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst,
+ struct inet6_dev *idev)
{
struct frag_queue *fq;
struct hlist_node *n;
@@ -410,7 +416,7 @@ fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst)
}
read_unlock(&ip6_frag_lock);
- return ip6_frag_create(id, src, dst);
+ return ip6_frag_create(id, src, dst, idev);
}
@@ -428,7 +434,8 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
((u8 *) (fhdr + 1) - (u8 *) (skb->nh.ipv6h + 1)));
if ((unsigned int)end > IPV6_MAXPLEN) {
- IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+ IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
+ IPSTATS_MIB_INHDRERRORS);
icmpv6_param_prob(skb,ICMPV6_HDR_FIELD, (u8*)&fhdr->frag_off - skb->nh.raw);
return;
}
@@ -455,7 +462,8 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
/* RFC2460 says always send parameter problem in
* this case. -DaveM
*/
- IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+ IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
+ IPSTATS_MIB_INHDRERRORS);
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
offsetof(struct ipv6hdr, payload_len));
return;
@@ -571,7 +579,7 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
return;
err:
- IP6_INC_STATS(IPSTATS_MIB_REASMFAILS);
+ IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMFAILS);
kfree_skb(skb);
}
@@ -665,7 +673,9 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
if (head->ip_summed == CHECKSUM_COMPLETE)
head->csum = csum_partial(head->nh.raw, head->h.raw-head->nh.raw, head->csum);
- IP6_INC_STATS_BH(IPSTATS_MIB_REASMOKS);
+ rcu_read_lock();
+ IP6_INC_STATS_BH(__in6_dev_get(dev), IPSTATS_MIB_REASMOKS);
+ rcu_read_unlock();
fq->fragments = NULL;
return 1;
@@ -677,7 +687,9 @@ out_oom:
if (net_ratelimit())
printk(KERN_DEBUG "ip6_frag_reasm: no memory for reassembly\n");
out_fail:
- IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
+ rcu_read_lock();
+ IP6_INC_STATS_BH(__in6_dev_get(dev), IPSTATS_MIB_REASMFAILS);
+ rcu_read_unlock();
return -1;
}
@@ -691,16 +703,16 @@ static int ipv6_frag_rcv(struct sk_buff **skbp)
hdr = skb->nh.ipv6h;
- IP6_INC_STATS_BH(IPSTATS_MIB_REASMREQDS);
+ IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMREQDS);
/* Jumbo payload inhibits frag. header */
if (hdr->payload_len==0) {
- IP6_INC_STATS(IPSTATS_MIB_INHDRERRORS);
+ IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS);
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw-skb->nh.raw);
return -1;
}
if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+sizeof(struct frag_hdr))) {
- IP6_INC_STATS(IPSTATS_MIB_INHDRERRORS);
+ IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS);
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw-skb->nh.raw);
return -1;
}
@@ -711,16 +723,17 @@ static int ipv6_frag_rcv(struct sk_buff **skbp)
if (!(fhdr->frag_off & htons(0xFFF9))) {
/* It is not a fragmented frame */
skb->h.raw += sizeof(struct frag_hdr);
- IP6_INC_STATS_BH(IPSTATS_MIB_REASMOKS);
+ IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMOKS);
IP6CB(skb)->nhoff = (u8*)fhdr - skb->nh.raw;
return 1;
}
if (atomic_read(&ip6_frag_mem) > sysctl_ip6frag_high_thresh)
- ip6_evictor();
+ ip6_evictor(ip6_dst_idev(skb->dst));
- if ((fq = fq_find(fhdr->identification, &hdr->saddr, &hdr->daddr)) != NULL) {
+ if ((fq = fq_find(fhdr->identification, &hdr->saddr, &hdr->daddr,
+ ip6_dst_idev(skb->dst))) != NULL) {
int ret = -1;
spin_lock(&fq->lock);
@@ -736,7 +749,7 @@ static int ipv6_frag_rcv(struct sk_buff **skbp)
return ret;
}
- IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
+ IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMFAILS);
kfree_skb(skb);
return -1;
}
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index b39ae99122d5..9f80518aacbd 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -440,7 +440,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
if (pref == ICMPV6_ROUTER_PREF_INVALID)
pref = ICMPV6_ROUTER_PREF_MEDIUM;
- lifetime = htonl(rinfo->lifetime);
+ lifetime = ntohl(rinfo->lifetime);
if (lifetime == 0xffffffff) {
/* infinity */
} else if (lifetime > 0x7fffffff/HZ) {
@@ -711,12 +711,10 @@ void ip6_route_input(struct sk_buff *skb)
.ip6_u = {
.daddr = iph->daddr,
.saddr = iph->saddr,
-#ifdef CONFIG_IPV6_ROUTE_FWMARK
- .fwmark = skb->nfmark,
-#endif
- .flowlabel = (* (u32 *) iph)&IPV6_FLOWINFO_MASK,
+ .flowlabel = (* (__be32 *) iph)&IPV6_FLOWINFO_MASK,
},
},
+ .mark = skb->mark,
.proto = iph->nexthdr,
};
@@ -942,7 +940,7 @@ struct dst_entry *ndisc_dst_alloc(struct net_device *dev,
fib6_force_start_gc();
out:
- return (struct dst_entry *)rt;
+ return &rt->u.dst;
}
int ndisc_dst_gc(int *more)
@@ -1225,7 +1223,7 @@ out:
if (idev)
in6_dev_put(idev);
if (rt)
- dst_free((struct dst_entry *) rt);
+ dst_free(&rt->u.dst);
return err;
}
@@ -1751,9 +1749,9 @@ static inline int ip6_pkt_drop(struct sk_buff *skb, int code)
{
int type = ipv6_addr_type(&skb->nh.ipv6h->daddr);
if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED)
- IP6_INC_STATS(IPSTATS_MIB_INADDRERRORS);
+ IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_INADDRERRORS);
- IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES);
+ IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_OUTNOROUTES);
icmpv6_send(skb, ICMPV6_DEST_UNREACH, code, 0, skb->dev);
kfree_skb(skb);
return 0;
@@ -1824,7 +1822,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
rt->rt6i_flags |= RTF_LOCAL;
rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway);
if (rt->rt6i_nexthop == NULL) {
- dst_free((struct dst_entry *) rt);
+ dst_free(&rt->u.dst);
return ERR_PTR(-ENOMEM);
}
@@ -2008,6 +2006,20 @@ int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
return ip6_route_add(&cfg);
}
+static inline size_t rt6_nlmsg_size(void)
+{
+ return NLMSG_ALIGN(sizeof(struct rtmsg))
+ + nla_total_size(16) /* RTA_SRC */
+ + nla_total_size(16) /* RTA_DST */
+ + nla_total_size(16) /* RTA_GATEWAY */
+ + nla_total_size(16) /* RTA_PREFSRC */
+ + nla_total_size(4) /* RTA_TABLE */
+ + nla_total_size(4) /* RTA_IIF */
+ + nla_total_size(4) /* RTA_OIF */
+ + nla_total_size(4) /* RTA_PRIORITY */
+ + nla_total_size(sizeof(struct rta_cacheinfo));
+}
+
static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
struct in6_addr *dst, struct in6_addr *src,
int iif, int type, u32 pid, u32 seq,
@@ -2015,7 +2027,7 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
{
struct rtmsg *rtm;
struct nlmsghdr *nlh;
- struct rta_cacheinfo ci;
+ long expires;
u32 table;
if (prefix) { /* user wants prefix routes only */
@@ -2089,18 +2101,11 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
NLA_PUT_U32(skb, RTA_OIF, rt->rt6i_dev->ifindex);
NLA_PUT_U32(skb, RTA_PRIORITY, rt->rt6i_metric);
- ci.rta_lastuse = jiffies_to_clock_t(jiffies - rt->u.dst.lastuse);
- if (rt->rt6i_expires)
- ci.rta_expires = jiffies_to_clock_t(rt->rt6i_expires - jiffies);
- else
- ci.rta_expires = 0;
- ci.rta_used = rt->u.dst.__use;
- ci.rta_clntref = atomic_read(&rt->u.dst.__refcnt);
- ci.rta_error = rt->u.dst.error;
- ci.rta_id = 0;
- ci.rta_ts = 0;
- ci.rta_tsage = 0;
- NLA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci);
+
+ expires = rt->rt6i_expires ? rt->rt6i_expires - jiffies : 0;
+ if (rtnl_put_cacheinfo(skb, &rt->u.dst, 0, 0, 0,
+ expires, rt->u.dst.error) < 0)
+ goto nla_put_failure;
return nlmsg_end(skb, nlh);
@@ -2202,7 +2207,6 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info)
struct sk_buff *skb;
u32 pid = 0, seq = 0;
struct nlmsghdr *nlh = NULL;
- int payload = sizeof(struct rtmsg) + 256;
int err = -ENOBUFS;
if (info) {
@@ -2212,15 +2216,13 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info)
seq = nlh->nlmsg_seq;
}
- skb = nlmsg_new(nlmsg_total_size(payload), gfp_any());
+ skb = nlmsg_new(rt6_nlmsg_size(), gfp_any());
if (skb == NULL)
goto errout;
err = rt6_fill_node(skb, rt, NULL, NULL, 0, event, pid, seq, 0, 0);
- if (err < 0) {
- kfree_skb(skb);
- goto errout;
- }
+ /* failure implies BUG in rt6_nlmsg_size() */
+ BUG_ON(err < 0);
err = rtnl_notify(skb, pid, RTNLGRP_IPV6_ROUTE, nlh, gfp_any());
errout:
@@ -2248,7 +2250,6 @@ struct rt6_proc_arg
static int rt6_info_route(struct rt6_info *rt, void *p_arg)
{
struct rt6_proc_arg *arg = (struct rt6_proc_arg *) p_arg;
- int i;
if (arg->skip < arg->offset / RT6_INFO_LEN) {
arg->skip++;
@@ -2258,38 +2259,28 @@ static int rt6_info_route(struct rt6_info *rt, void *p_arg)
if (arg->len >= arg->length)
return 0;
- for (i=0; i<16; i++) {
- sprintf(arg->buffer + arg->len, "%02x",
- rt->rt6i_dst.addr.s6_addr[i]);
- arg->len += 2;
- }
- arg->len += sprintf(arg->buffer + arg->len, " %02x ",
+ arg->len += sprintf(arg->buffer + arg->len,
+ NIP6_SEQFMT " %02x ",
+ NIP6(rt->rt6i_dst.addr),
rt->rt6i_dst.plen);
#ifdef CONFIG_IPV6_SUBTREES
- for (i=0; i<16; i++) {
- sprintf(arg->buffer + arg->len, "%02x",
- rt->rt6i_src.addr.s6_addr[i]);
- arg->len += 2;
- }
- arg->len += sprintf(arg->buffer + arg->len, " %02x ",
+ arg->len += sprintf(arg->buffer + arg->len,
+ NIP6_SEQFMT " %02x ",
+ NIP6(rt->rt6i_src.addr),
rt->rt6i_src.plen);
#else
- sprintf(arg->buffer + arg->len,
- "00000000000000000000000000000000 00 ");
- arg->len += 36;
+ arg->len += sprintf(arg->buffer + arg->len,
+ "00000000000000000000000000000000 00 ");
#endif
if (rt->rt6i_nexthop) {
- for (i=0; i<16; i++) {
- sprintf(arg->buffer + arg->len, "%02x",
- rt->rt6i_nexthop->primary_key[i]);
- arg->len += 2;
- }
+ arg->len += sprintf(arg->buffer + arg->len,
+ NIP6_SEQFMT,
+ NIP6(*((struct in6_addr *)rt->rt6i_nexthop->primary_key)));
} else {
- sprintf(arg->buffer + arg->len,
- "00000000000000000000000000000000");
- arg->len += 32;
+ arg->len += sprintf(arg->buffer + arg->len,
+ "00000000000000000000000000000000");
}
arg->len += sprintf(arg->buffer + arg->len,
" %08x %08x %08x %08x %8s\n",
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index be699f85b2c7..77b7b0911438 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -60,7 +60,7 @@
*/
#define HASH_SIZE 16
-#define HASH(addr) ((addr^(addr>>4))&0xF)
+#define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF)
static int ipip6_fb_tunnel_init(struct net_device *dev);
static int ipip6_tunnel_init(struct net_device *dev);
@@ -76,7 +76,7 @@ static struct ip_tunnel **tunnels[4] = { tunnels_wc, tunnels_l, tunnels_r, tunne
static DEFINE_RWLOCK(ipip6_lock);
-static struct ip_tunnel * ipip6_tunnel_lookup(u32 remote, u32 local)
+static struct ip_tunnel * ipip6_tunnel_lookup(__be32 remote, __be32 local)
{
unsigned h0 = HASH(remote);
unsigned h1 = HASH(local);
@@ -102,8 +102,8 @@ static struct ip_tunnel * ipip6_tunnel_lookup(u32 remote, u32 local)
static struct ip_tunnel ** ipip6_bucket(struct ip_tunnel *t)
{
- u32 remote = t->parms.iph.daddr;
- u32 local = t->parms.iph.saddr;
+ __be32 remote = t->parms.iph.daddr;
+ __be32 local = t->parms.iph.saddr;
unsigned h = 0;
int prio = 0;
@@ -144,8 +144,8 @@ static void ipip6_tunnel_link(struct ip_tunnel *t)
static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int create)
{
- u32 remote = parms->iph.daddr;
- u32 local = parms->iph.saddr;
+ __be32 remote = parms->iph.daddr;
+ __be32 local = parms->iph.saddr;
struct ip_tunnel *t, **tp, *nt;
struct net_device *dev;
unsigned h = 0;
@@ -405,9 +405,9 @@ out:
/* Returns the embedded IPv4 address if the IPv6 address
comes from 6to4 (RFC 3056) addr space */
-static inline u32 try_6to4(struct in6_addr *v6dst)
+static inline __be32 try_6to4(struct in6_addr *v6dst)
{
- u32 dst = 0;
+ __be32 dst = 0;
if (v6dst->s6_addr16[0] == htons(0x2002)) {
/* 6to4 v6 addr has 16 bits prefix, 32 v4addr, 16 SLA, ... */
@@ -432,7 +432,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
struct net_device *tdev; /* Device to other host */
struct iphdr *iph; /* Our new IP header */
int max_headroom; /* The extra header space needed */
- u32 dst = tiph->daddr;
+ __be32 dst = tiph->daddr;
int mtu;
struct in6_addr *addr6;
int addr_type;
@@ -809,7 +809,7 @@ static void __exit sit_destroy_tunnels(void)
}
}
-void __exit sit_cleanup(void)
+static void __exit sit_cleanup(void)
{
inet_del_protocol(&sit_protocol, IPPROTO_IPV6);
@@ -819,7 +819,7 @@ void __exit sit_cleanup(void)
rtnl_unlock();
}
-int __init sit_init(void)
+static int __init sit_init(void)
{
int err;
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 4c2a7c0cafef..c25e930c2c69 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -66,10 +66,13 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <linux/crypto.h>
+#include <linux/scatterlist.h>
+
/* Socket used for sending RSTs and ACKs */
static struct socket *tcp6_socket;
-static void tcp_v6_send_reset(struct sk_buff *skb);
+static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb);
static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req);
static void tcp_v6_send_check(struct sock *sk, int len,
struct sk_buff *skb);
@@ -78,6 +81,10 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb);
static struct inet_connection_sock_af_ops ipv6_mapped;
static struct inet_connection_sock_af_ops ipv6_specific;
+#ifdef CONFIG_TCP_MD5SIG
+static struct tcp_sock_af_ops tcp_sock_ipv6_specific;
+static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific;
+#endif
static int tcp_v6_get_port(struct sock *sk, unsigned short snum)
{
@@ -98,27 +105,20 @@ static void tcp_v6_hash(struct sock *sk)
}
}
-static __inline__ u16 tcp_v6_check(struct tcphdr *th, int len,
+static __inline__ __sum16 tcp_v6_check(struct tcphdr *th, int len,
struct in6_addr *saddr,
struct in6_addr *daddr,
- unsigned long base)
+ __wsum base)
{
return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base);
}
-static __u32 tcp_v6_init_sequence(struct sock *sk, struct sk_buff *skb)
+static __u32 tcp_v6_init_sequence(struct sk_buff *skb)
{
- if (skb->protocol == htons(ETH_P_IPV6)) {
- return secure_tcpv6_sequence_number(skb->nh.ipv6h->daddr.s6_addr32,
- skb->nh.ipv6h->saddr.s6_addr32,
- skb->h.th->dest,
- skb->h.th->source);
- } else {
- return secure_tcp_sequence_number(skb->nh.iph->daddr,
- skb->nh.iph->saddr,
- skb->h.th->dest,
- skb->h.th->source);
- }
+ return secure_tcpv6_sequence_number(skb->nh.ipv6h->daddr.s6_addr32,
+ skb->nh.ipv6h->saddr.s6_addr32,
+ skb->h.th->dest,
+ skb->h.th->source);
}
static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
@@ -215,6 +215,9 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
icsk->icsk_af_ops = &ipv6_mapped;
sk->sk_backlog_rcv = tcp_v4_do_rcv;
+#ifdef CONFIG_TCP_MD5SIG
+ tp->af_specific = &tcp_sock_ipv6_mapped_specific;
+#endif
err = tcp_v4_connect(sk, (struct sockaddr *)&sin, sizeof(sin));
@@ -222,6 +225,9 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
icsk->icsk_ext_hdr_len = exthdrlen;
icsk->icsk_af_ops = &ipv6_specific;
sk->sk_backlog_rcv = tcp_v6_do_rcv;
+#ifdef CONFIG_TCP_MD5SIG
+ tp->af_specific = &tcp_sock_ipv6_specific;
+#endif
goto failure;
} else {
ipv6_addr_set(&np->saddr, 0, 0, htonl(0x0000FFFF),
@@ -310,7 +316,7 @@ failure:
}
static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
- int type, int code, int offset, __u32 info)
+ int type, int code, int offset, __be32 info)
{
struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data;
const struct tcphdr *th = (struct tcphdr *)(skb->data+offset);
@@ -509,8 +515,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr);
err = ip6_xmit(sk, skb, &fl, opt, 0);
- if (err == NET_XMIT_CN)
- err = 0;
+ err = net_xmit_eval(err);
}
done:
@@ -526,7 +531,396 @@ static void tcp_v6_reqsk_destructor(struct request_sock *req)
kfree_skb(inet6_rsk(req)->pktopts);
}
-static struct request_sock_ops tcp6_request_sock_ops = {
+#ifdef CONFIG_TCP_MD5SIG
+static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk,
+ struct in6_addr *addr)
+{
+ struct tcp_sock *tp = tcp_sk(sk);
+ int i;
+
+ BUG_ON(tp == NULL);
+
+ if (!tp->md5sig_info || !tp->md5sig_info->entries6)
+ return NULL;
+
+ for (i = 0; i < tp->md5sig_info->entries6; i++) {
+ if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, addr) == 0)
+ return (struct tcp_md5sig_key *)&tp->md5sig_info->keys6[i];
+ }
+ return NULL;
+}
+
+static struct tcp_md5sig_key *tcp_v6_md5_lookup(struct sock *sk,
+ struct sock *addr_sk)
+{
+ return tcp_v6_md5_do_lookup(sk, &inet6_sk(addr_sk)->daddr);
+}
+
+static struct tcp_md5sig_key *tcp_v6_reqsk_md5_lookup(struct sock *sk,
+ struct request_sock *req)
+{
+ return tcp_v6_md5_do_lookup(sk, &inet6_rsk(req)->rmt_addr);
+}
+
+static int tcp_v6_md5_do_add(struct sock *sk, struct in6_addr *peer,
+ char *newkey, u8 newkeylen)
+{
+ /* Add key to the list */
+ struct tcp6_md5sig_key *key;
+ struct tcp_sock *tp = tcp_sk(sk);
+ struct tcp6_md5sig_key *keys;
+
+ key = (struct tcp6_md5sig_key*) tcp_v6_md5_do_lookup(sk, peer);
+ if (key) {
+ /* modify existing entry - just update that one */
+ kfree(key->key);
+ key->key = newkey;
+ key->keylen = newkeylen;
+ } else {
+ /* reallocate new list if current one is full. */
+ if (!tp->md5sig_info) {
+ tp->md5sig_info = kzalloc(sizeof(*tp->md5sig_info), GFP_ATOMIC);
+ if (!tp->md5sig_info) {
+ kfree(newkey);
+ return -ENOMEM;
+ }
+ }
+ tcp_alloc_md5sig_pool();
+ if (tp->md5sig_info->alloced6 == tp->md5sig_info->entries6) {
+ keys = kmalloc((sizeof (tp->md5sig_info->keys6[0]) *
+ (tp->md5sig_info->entries6 + 1)), GFP_ATOMIC);
+
+ if (!keys) {
+ tcp_free_md5sig_pool();
+ kfree(newkey);
+ return -ENOMEM;
+ }
+
+ if (tp->md5sig_info->entries6)
+ memmove(keys, tp->md5sig_info->keys6,
+ (sizeof (tp->md5sig_info->keys6[0]) *
+ tp->md5sig_info->entries6));
+
+ kfree(tp->md5sig_info->keys6);
+ tp->md5sig_info->keys6 = keys;
+ tp->md5sig_info->alloced6++;
+ }
+
+ ipv6_addr_copy(&tp->md5sig_info->keys6[tp->md5sig_info->entries6].addr,
+ peer);
+ tp->md5sig_info->keys6[tp->md5sig_info->entries6].key = newkey;
+ tp->md5sig_info->keys6[tp->md5sig_info->entries6].keylen = newkeylen;
+
+ tp->md5sig_info->entries6++;
+ }
+ return 0;
+}
+
+static int tcp_v6_md5_add_func(struct sock *sk, struct sock *addr_sk,
+ u8 *newkey, __u8 newkeylen)
+{
+ return tcp_v6_md5_do_add(sk, &inet6_sk(addr_sk)->daddr,
+ newkey, newkeylen);
+}
+
+static int tcp_v6_md5_do_del(struct sock *sk, struct in6_addr *peer)
+{
+ struct tcp_sock *tp = tcp_sk(sk);
+ int i;
+
+ for (i = 0; i < tp->md5sig_info->entries6; i++) {
+ if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, peer) == 0) {
+ /* Free the key */
+ kfree(tp->md5sig_info->keys6[i].key);
+ tp->md5sig_info->entries6--;
+
+ if (tp->md5sig_info->entries6 == 0) {
+ kfree(tp->md5sig_info->keys6);
+ tp->md5sig_info->keys6 = NULL;
+
+ tcp_free_md5sig_pool();
+
+ return 0;
+ } else {
+ /* shrink the database */
+ if (tp->md5sig_info->entries6 != i)
+ memmove(&tp->md5sig_info->keys6[i],
+ &tp->md5sig_info->keys6[i+1],
+ (tp->md5sig_info->entries6 - i)
+ * sizeof (tp->md5sig_info->keys6[0]));
+ }
+ }
+ }
+ return -ENOENT;
+}
+
+static void tcp_v6_clear_md5_list (struct sock *sk)
+{
+ struct tcp_sock *tp = tcp_sk(sk);
+ int i;
+
+ if (tp->md5sig_info->entries6) {
+ for (i = 0; i < tp->md5sig_info->entries6; i++)
+ kfree(tp->md5sig_info->keys6[i].key);
+ tp->md5sig_info->entries6 = 0;
+ tcp_free_md5sig_pool();
+ }
+
+ kfree(tp->md5sig_info->keys6);
+ tp->md5sig_info->keys6 = NULL;
+ tp->md5sig_info->alloced6 = 0;
+
+ if (tp->md5sig_info->entries4) {
+ for (i = 0; i < tp->md5sig_info->entries4; i++)
+ kfree(tp->md5sig_info->keys4[i].key);
+ tp->md5sig_info->entries4 = 0;
+ tcp_free_md5sig_pool();
+ }
+
+ kfree(tp->md5sig_info->keys4);
+ tp->md5sig_info->keys4 = NULL;
+ tp->md5sig_info->alloced4 = 0;
+}
+
+static int tcp_v6_parse_md5_keys (struct sock *sk, char __user *optval,
+ int optlen)
+{
+ struct tcp_md5sig cmd;
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&cmd.tcpm_addr;
+ u8 *newkey;
+
+ if (optlen < sizeof(cmd))
+ return -EINVAL;
+
+ if (copy_from_user(&cmd, optval, sizeof(cmd)))
+ return -EFAULT;
+
+ if (sin6->sin6_family != AF_INET6)
+ return -EINVAL;
+
+ if (!cmd.tcpm_keylen) {
+ if (!tcp_sk(sk)->md5sig_info)
+ return -ENOENT;
+ if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_MAPPED)
+ return tcp_v4_md5_do_del(sk, sin6->sin6_addr.s6_addr32[3]);
+ return tcp_v6_md5_do_del(sk, &sin6->sin6_addr);
+ }
+
+ if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN)
+ return -EINVAL;
+
+ if (!tcp_sk(sk)->md5sig_info) {
+ struct tcp_sock *tp = tcp_sk(sk);
+ struct tcp_md5sig_info *p;
+
+ p = kzalloc(sizeof(struct tcp_md5sig_info), GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
+
+ tp->md5sig_info = p;
+ }
+
+ newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL);
+ if (!newkey)
+ return -ENOMEM;
+ if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_MAPPED) {
+ return tcp_v4_md5_do_add(sk, sin6->sin6_addr.s6_addr32[3],
+ newkey, cmd.tcpm_keylen);
+ }
+ return tcp_v6_md5_do_add(sk, &sin6->sin6_addr, newkey, cmd.tcpm_keylen);
+}
+
+static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
+ struct in6_addr *saddr,
+ struct in6_addr *daddr,
+ struct tcphdr *th, int protocol,
+ int tcplen)
+{
+ struct scatterlist sg[4];
+ __u16 data_len;
+ int block = 0;
+ __sum16 cksum;
+ struct tcp_md5sig_pool *hp;
+ struct tcp6_pseudohdr *bp;
+ struct hash_desc *desc;
+ int err;
+ unsigned int nbytes = 0;
+
+ hp = tcp_get_md5sig_pool();
+ if (!hp) {
+ printk(KERN_WARNING "%s(): hash pool not found...\n", __FUNCTION__);
+ goto clear_hash_noput;
+ }
+ bp = &hp->md5_blk.ip6;
+ desc = &hp->md5_desc;
+
+ /* 1. TCP pseudo-header (RFC2460) */
+ ipv6_addr_copy(&bp->saddr, saddr);
+ ipv6_addr_copy(&bp->daddr, daddr);
+ bp->len = htonl(tcplen);
+ bp->protocol = htonl(protocol);
+
+ sg_set_buf(&sg[block++], bp, sizeof(*bp));
+ nbytes += sizeof(*bp);
+
+ /* 2. TCP header, excluding options */
+ cksum = th->check;
+ th->check = 0;
+ sg_set_buf(&sg[block++], th, sizeof(*th));
+ nbytes += sizeof(*th);
+
+ /* 3. TCP segment data (if any) */
+ data_len = tcplen - (th->doff << 2);
+ if (data_len > 0) {
+ u8 *data = (u8 *)th + (th->doff << 2);
+ sg_set_buf(&sg[block++], data, data_len);
+ nbytes += data_len;
+ }
+
+ /* 4. shared key */
+ sg_set_buf(&sg[block++], key->key, key->keylen);
+ nbytes += key->keylen;
+
+ /* Now store the hash into the packet */
+ err = crypto_hash_init(desc);
+ if (err) {
+ printk(KERN_WARNING "%s(): hash_init failed\n", __FUNCTION__);
+ goto clear_hash;
+ }
+ err = crypto_hash_update(desc, sg, nbytes);
+ if (err) {
+ printk(KERN_WARNING "%s(): hash_update failed\n", __FUNCTION__);
+ goto clear_hash;
+ }
+ err = crypto_hash_final(desc, md5_hash);
+ if (err) {
+ printk(KERN_WARNING "%s(): hash_final failed\n", __FUNCTION__);
+ goto clear_hash;
+ }
+
+ /* Reset header, and free up the crypto */
+ tcp_put_md5sig_pool();
+ th->check = cksum;
+out:
+ return 0;
+clear_hash:
+ tcp_put_md5sig_pool();
+clear_hash_noput:
+ memset(md5_hash, 0, 16);
+ goto out;
+}
+
+static int tcp_v6_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
+ struct sock *sk,
+ struct dst_entry *dst,
+ struct request_sock *req,
+ struct tcphdr *th, int protocol,
+ int tcplen)
+{
+ struct in6_addr *saddr, *daddr;
+
+ if (sk) {
+ saddr = &inet6_sk(sk)->saddr;
+ daddr = &inet6_sk(sk)->daddr;
+ } else {
+ saddr = &inet6_rsk(req)->loc_addr;
+ daddr = &inet6_rsk(req)->rmt_addr;
+ }
+ return tcp_v6_do_calc_md5_hash(md5_hash, key,
+ saddr, daddr,
+ th, protocol, tcplen);
+}
+
+static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb)
+{
+ __u8 *hash_location = NULL;
+ struct tcp_md5sig_key *hash_expected;
+ struct ipv6hdr *ip6h = skb->nh.ipv6h;
+ struct tcphdr *th = skb->h.th;
+ int length = (th->doff << 2) - sizeof (*th);
+ int genhash;
+ u8 *ptr;
+ u8 newhash[16];
+
+ hash_expected = tcp_v6_md5_do_lookup(sk, &ip6h->saddr);
+
+ /* If the TCP option is too short, we can short cut */
+ if (length < TCPOLEN_MD5SIG)
+ return hash_expected ? 1 : 0;
+
+ /* parse options */
+ ptr = (u8*)(th + 1);
+ while (length > 0) {
+ int opcode = *ptr++;
+ int opsize;
+
+ switch(opcode) {
+ case TCPOPT_EOL:
+ goto done_opts;
+ case TCPOPT_NOP:
+ length--;
+ continue;
+ default:
+ opsize = *ptr++;
+ if (opsize < 2 || opsize > length)
+ goto done_opts;
+ if (opcode == TCPOPT_MD5SIG) {
+ hash_location = ptr;
+ goto done_opts;
+ }
+ }
+ ptr += opsize - 2;
+ length -= opsize;
+ }
+
+done_opts:
+ /* do we have a hash as expected? */
+ if (!hash_expected) {
+ if (!hash_location)
+ return 0;
+ if (net_ratelimit()) {
+ printk(KERN_INFO "MD5 Hash NOT expected but found "
+ "(" NIP6_FMT ", %u)->"
+ "(" NIP6_FMT ", %u)\n",
+ NIP6(ip6h->saddr), ntohs(th->source),
+ NIP6(ip6h->daddr), ntohs(th->dest));
+ }
+ return 1;
+ }
+
+ if (!hash_location) {
+ if (net_ratelimit()) {
+ printk(KERN_INFO "MD5 Hash expected but NOT found "
+ "(" NIP6_FMT ", %u)->"
+ "(" NIP6_FMT ", %u)\n",
+ NIP6(ip6h->saddr), ntohs(th->source),
+ NIP6(ip6h->daddr), ntohs(th->dest));
+ }
+ return 1;
+ }
+
+ /* check the signature */
+ genhash = tcp_v6_do_calc_md5_hash(newhash,
+ hash_expected,
+ &ip6h->saddr, &ip6h->daddr,
+ th, sk->sk_protocol,
+ skb->len);
+ if (genhash || memcmp(hash_location, newhash, 16) != 0) {
+ if (net_ratelimit()) {
+ printk(KERN_INFO "MD5 Hash %s for "
+ "(" NIP6_FMT ", %u)->"
+ "(" NIP6_FMT ", %u)\n",
+ genhash ? "failed" : "mismatch",
+ NIP6(ip6h->saddr), ntohs(th->source),
+ NIP6(ip6h->daddr), ntohs(th->dest));
+ }
+ return 1;
+ }
+ return 0;
+}
+#endif
+
+static struct request_sock_ops tcp6_request_sock_ops __read_mostly = {
.family = AF_INET6,
.obj_size = sizeof(struct tcp6_request_sock),
.rtx_syn_ack = tcp_v6_send_synack,
@@ -535,9 +929,16 @@ static struct request_sock_ops tcp6_request_sock_ops = {
.send_reset = tcp_v6_send_reset
};
+#ifdef CONFIG_TCP_MD5SIG
+static struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = {
+ .md5_lookup = tcp_v6_reqsk_md5_lookup,
+};
+#endif
+
static struct timewait_sock_ops tcp6_timewait_sock_ops = {
.twsk_obj_size = sizeof(struct tcp6_timewait_sock),
.twsk_unique = tcp_twsk_unique,
+ .twsk_destructor= tcp_twsk_destructor,
};
static void tcp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb)
@@ -547,7 +948,7 @@ static void tcp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb)
if (skb->ip_summed == CHECKSUM_PARTIAL) {
th->check = ~csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, 0);
- skb->csum = offsetof(struct tcphdr, check);
+ skb->csum_offset = offsetof(struct tcphdr, check);
} else {
th->check = csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP,
csum_partial((char *)th, th->doff<<2,
@@ -569,16 +970,20 @@ static int tcp_v6_gso_send_check(struct sk_buff *skb)
th->check = 0;
th->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, skb->len,
IPPROTO_TCP, 0);
- skb->csum = offsetof(struct tcphdr, check);
+ skb->csum_offset = offsetof(struct tcphdr, check);
skb->ip_summed = CHECKSUM_PARTIAL;
return 0;
}
-static void tcp_v6_send_reset(struct sk_buff *skb)
+static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
{
struct tcphdr *th = skb->h.th, *t1;
struct sk_buff *buff;
struct flowi fl;
+ int tot_len = sizeof(*th);
+#ifdef CONFIG_TCP_MD5SIG
+ struct tcp_md5sig_key *key;
+#endif
if (th->rst)
return;
@@ -586,25 +991,35 @@ static void tcp_v6_send_reset(struct sk_buff *skb)
if (!ipv6_unicast_destination(skb))
return;
+#ifdef CONFIG_TCP_MD5SIG
+ if (sk)
+ key = tcp_v6_md5_do_lookup(sk, &skb->nh.ipv6h->daddr);
+ else
+ key = NULL;
+
+ if (key)
+ tot_len += TCPOLEN_MD5SIG_ALIGNED;
+#endif
+
/*
* We need to grab some memory, and put together an RST,
* and then put it into the queue to be sent.
*/
- buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + sizeof(struct tcphdr),
+ buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + tot_len,
GFP_ATOMIC);
if (buff == NULL)
return;
- skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + sizeof(struct tcphdr));
+ skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len);
- t1 = (struct tcphdr *) skb_push(buff,sizeof(struct tcphdr));
+ t1 = (struct tcphdr *) skb_push(buff, tot_len);
/* Swap the send and the receive. */
memset(t1, 0, sizeof(*t1));
t1->dest = th->source;
t1->source = th->dest;
- t1->doff = sizeof(*t1)/4;
+ t1->doff = tot_len / 4;
t1->rst = 1;
if(th->ack) {
@@ -615,6 +1030,22 @@ static void tcp_v6_send_reset(struct sk_buff *skb)
+ skb->len - (th->doff<<2));
}
+#ifdef CONFIG_TCP_MD5SIG
+ if (key) {
+ __be32 *opt = (__be32*)(t1 + 1);
+ opt[0] = htonl((TCPOPT_NOP << 24) |
+ (TCPOPT_NOP << 16) |
+ (TCPOPT_MD5SIG << 8) |
+ TCPOLEN_MD5SIG);
+ tcp_v6_do_calc_md5_hash((__u8*)&opt[1],
+ key,
+ &skb->nh.ipv6h->daddr,
+ &skb->nh.ipv6h->saddr,
+ t1, IPPROTO_TCP,
+ tot_len);
+ }
+#endif
+
buff->csum = csum_partial((char *)t1, sizeof(*t1), 0);
memset(&fl, 0, sizeof(fl));
@@ -645,15 +1076,37 @@ static void tcp_v6_send_reset(struct sk_buff *skb)
kfree_skb(buff);
}
-static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts)
+static void tcp_v6_send_ack(struct tcp_timewait_sock *tw,
+ struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts)
{
struct tcphdr *th = skb->h.th, *t1;
struct sk_buff *buff;
struct flowi fl;
int tot_len = sizeof(struct tcphdr);
+ __be32 *topt;
+#ifdef CONFIG_TCP_MD5SIG
+ struct tcp_md5sig_key *key;
+ struct tcp_md5sig_key tw_key;
+#endif
+
+#ifdef CONFIG_TCP_MD5SIG
+ if (!tw && skb->sk) {
+ key = tcp_v6_md5_do_lookup(skb->sk, &skb->nh.ipv6h->daddr);
+ } else if (tw && tw->tw_md5_keylen) {
+ tw_key.key = tw->tw_md5_key;
+ tw_key.keylen = tw->tw_md5_keylen;
+ key = &tw_key;
+ } else {
+ key = NULL;
+ }
+#endif
if (ts)
tot_len += TCPOLEN_TSTAMP_ALIGNED;
+#ifdef CONFIG_TCP_MD5SIG
+ if (key)
+ tot_len += TCPOLEN_MD5SIG_ALIGNED;
+#endif
buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + tot_len,
GFP_ATOMIC);
@@ -673,15 +1126,29 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32
t1->ack_seq = htonl(ack);
t1->ack = 1;
t1->window = htons(win);
+
+ topt = (__be32 *)(t1 + 1);
if (ts) {
- u32 *ptr = (u32*)(t1 + 1);
- *ptr++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
- (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP);
- *ptr++ = htonl(tcp_time_stamp);
- *ptr = htonl(ts);
+ *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
+ (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP);
+ *topt++ = htonl(tcp_time_stamp);
+ *topt = htonl(ts);
}
+#ifdef CONFIG_TCP_MD5SIG
+ if (key) {
+ *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
+ (TCPOPT_MD5SIG << 8) | TCPOLEN_MD5SIG);
+ tcp_v6_do_calc_md5_hash((__u8 *)topt,
+ key,
+ &skb->nh.ipv6h->daddr,
+ &skb->nh.ipv6h->saddr,
+ t1, IPPROTO_TCP,
+ tot_len);
+ }
+#endif
+
buff->csum = csum_partial((char *)t1, tot_len, 0);
memset(&fl, 0, sizeof(fl));
@@ -712,9 +1179,9 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32
static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb)
{
struct inet_timewait_sock *tw = inet_twsk(sk);
- const struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
+ struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
- tcp_v6_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
+ tcp_v6_send_ack(tcptw, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
tcptw->tw_ts_recent);
@@ -723,7 +1190,7 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb)
static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req)
{
- tcp_v6_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent);
+ tcp_v6_send_ack(NULL, skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent);
}
@@ -794,6 +1261,10 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
if (req == NULL)
goto drop;
+#ifdef CONFIG_TCP_MD5SIG
+ tcp_rsk(req)->af_specific = &tcp_request_sock_ipv6_ops;
+#endif
+
tcp_clear_options(&tmp_opt);
tmp_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr);
tmp_opt.user_mss = tp->rx_opt.user_mss;
@@ -822,7 +1293,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
treq->iif = inet6_iif(skb);
if (isn == 0)
- isn = tcp_v6_init_sequence(sk,skb);
+ isn = tcp_v6_init_sequence(skb);
tcp_rsk(req)->snt_isn = isn;
@@ -852,6 +1323,9 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
struct tcp_sock *newtp;
struct sock *newsk;
struct ipv6_txoptions *opt;
+#ifdef CONFIG_TCP_MD5SIG
+ struct tcp_md5sig_key *key;
+#endif
if (skb->protocol == htons(ETH_P_IP)) {
/*
@@ -882,6 +1356,10 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
inet_csk(newsk)->icsk_af_ops = &ipv6_mapped;
newsk->sk_backlog_rcv = tcp_v4_do_rcv;
+#ifdef CONFIG_TCP_MD5SIG
+ newtp->af_specific = &tcp_sock_ipv6_mapped_specific;
+#endif
+
newnp->pktoptions = NULL;
newnp->opt = NULL;
newnp->mcast_oif = inet6_iif(skb);
@@ -1016,6 +1494,21 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
newinet->daddr = newinet->saddr = newinet->rcv_saddr = LOOPBACK4_IPV6;
+#ifdef CONFIG_TCP_MD5SIG
+ /* Copy over the MD5 key from the original socket */
+ if ((key = tcp_v6_md5_do_lookup(sk, &newnp->daddr)) != NULL) {
+ /* We're using one, so create a matching key
+ * on the newsk structure. If we fail to get
+ * memory, then we end up not copying the key
+ * across. Shucks.
+ */
+ char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC);
+ if (newkey != NULL)
+ tcp_v6_md5_do_add(newsk, &inet6_sk(sk)->daddr,
+ newkey, key->keylen);
+ }
+#endif
+
__inet6_hash(&tcp_hashinfo, newsk);
inet_inherit_port(&tcp_hashinfo, sk, newsk);
@@ -1031,7 +1524,7 @@ out:
return NULL;
}
-static int tcp_v6_checksum_init(struct sk_buff *skb)
+static __sum16 tcp_v6_checksum_init(struct sk_buff *skb)
{
if (skb->ip_summed == CHECKSUM_COMPLETE) {
if (!tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr,
@@ -1041,8 +1534,8 @@ static int tcp_v6_checksum_init(struct sk_buff *skb)
}
}
- skb->csum = ~tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr,
- &skb->nh.ipv6h->daddr, 0);
+ skb->csum = ~csum_unfold(tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr,
+ &skb->nh.ipv6h->daddr, 0));
if (skb->len <= 76) {
return __skb_checksum_complete(skb);
@@ -1075,6 +1568,11 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
if (skb->protocol == htons(ETH_P_IP))
return tcp_v4_do_rcv(sk, skb);
+#ifdef CONFIG_TCP_MD5SIG
+ if (tcp_v6_inbound_md5_hash (sk, skb))
+ goto discard;
+#endif
+
if (sk_filter(sk, skb))
goto discard;
@@ -1140,7 +1638,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
return 0;
reset:
- tcp_v6_send_reset(skb);
+ tcp_v6_send_reset(sk, skb);
discard:
if (opt_skb)
__kfree_skb(opt_skb);
@@ -1265,7 +1763,7 @@ no_tcp_socket:
bad_packet:
TCP_INC_STATS_BH(TCP_MIB_INERRS);
} else {
- tcp_v6_send_reset(skb);
+ tcp_v6_send_reset(NULL, skb);
}
discard_it:
@@ -1344,6 +1842,15 @@ static struct inet_connection_sock_af_ops ipv6_specific = {
#endif
};
+#ifdef CONFIG_TCP_MD5SIG
+static struct tcp_sock_af_ops tcp_sock_ipv6_specific = {
+ .md5_lookup = tcp_v6_md5_lookup,
+ .calc_md5_hash = tcp_v6_calc_md5_hash,
+ .md5_add = tcp_v6_md5_add_func,
+ .md5_parse = tcp_v6_parse_md5_keys,
+};
+#endif
+
/*
* TCP over IPv4 via INET6 API
*/
@@ -1366,6 +1873,15 @@ static struct inet_connection_sock_af_ops ipv6_mapped = {
#endif
};
+#ifdef CONFIG_TCP_MD5SIG
+static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific = {
+ .md5_lookup = tcp_v4_md5_lookup,
+ .calc_md5_hash = tcp_v4_calc_md5_hash,
+ .md5_add = tcp_v6_md5_add_func,
+ .md5_parse = tcp_v6_parse_md5_keys,
+};
+#endif
+
/* NOTE: A lot of things set to zero explicitly by call to
* sk_alloc() so need not be done here.
*/
@@ -1405,6 +1921,10 @@ static int tcp_v6_init_sock(struct sock *sk)
sk->sk_write_space = sk_stream_write_space;
sock_set_flag(sk, SOCK_USE_WRITE_QUEUE);
+#ifdef CONFIG_TCP_MD5SIG
+ tp->af_specific = &tcp_sock_ipv6_specific;
+#endif
+
sk->sk_sndbuf = sysctl_tcp_wmem[1];
sk->sk_rcvbuf = sysctl_tcp_rmem[1];
@@ -1415,6 +1935,11 @@ static int tcp_v6_init_sock(struct sock *sk)
static int tcp_v6_destroy_sock(struct sock *sk)
{
+#ifdef CONFIG_TCP_MD5SIG
+ /* Clean up the MD5 key list */
+ if (tcp_sk(sk)->md5sig_info)
+ tcp_v6_clear_md5_list(sk);
+#endif
tcp_v4_destroy_sock(sk);
return inet6_destroy_sock(sk);
}
diff --git a/net/ipv6/tunnel6.c b/net/ipv6/tunnel6.c
index 0ef9a35798d1..918d07dd1219 100644
--- a/net/ipv6/tunnel6.c
+++ b/net/ipv6/tunnel6.c
@@ -104,7 +104,7 @@ drop:
}
static void tunnel6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
- int type, int code, int offset, __u32 info)
+ int type, int code, int offset, __be32 info)
{
struct xfrm6_tunnel *handler;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index c83f23e51c46..f52a5c3cc0a3 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -38,26 +38,18 @@
#include <linux/skbuff.h>
#include <asm/uaccess.h>
-#include <net/sock.h>
-#include <net/snmp.h>
-
-#include <net/ipv6.h>
#include <net/ndisc.h>
#include <net/protocol.h>
#include <net/transp_v6.h>
#include <net/ip6_route.h>
-#include <net/addrconf.h>
-#include <net/ip.h>
-#include <net/udp.h>
#include <net/raw.h>
-#include <net/inet_common.h>
#include <net/tcp_states.h>
-
#include <net/ip6_checksum.h>
#include <net/xfrm.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include "udp_impl.h"
DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6) __read_mostly;
@@ -66,23 +58,9 @@ static inline int udp_v6_get_port(struct sock *sk, unsigned short snum)
return udp_get_port(sk, snum, ipv6_rcv_saddr_equal);
}
-static void udp_v6_hash(struct sock *sk)
-{
- BUG();
-}
-
-static void udp_v6_unhash(struct sock *sk)
-{
- write_lock_bh(&udp_hash_lock);
- if (sk_del_node_init(sk)) {
- inet_sk(sk)->num = 0;
- sock_prot_dec_use(sk->sk_prot);
- }
- write_unlock_bh(&udp_hash_lock);
-}
-
-static struct sock *udp_v6_lookup(struct in6_addr *saddr, u16 sport,
- struct in6_addr *daddr, u16 dport, int dif)
+static struct sock *__udp6_lib_lookup(struct in6_addr *saddr, __be16 sport,
+ struct in6_addr *daddr, __be16 dport,
+ int dif, struct hlist_head udptable[])
{
struct sock *sk, *result = NULL;
struct hlist_node *node;
@@ -90,7 +68,7 @@ static struct sock *udp_v6_lookup(struct in6_addr *saddr, u16 sport,
int badness = -1;
read_lock(&udp_hash_lock);
- sk_for_each(sk, node, &udp_hash[hnum & (UDP_HTABLE_SIZE - 1)]) {
+ sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) {
struct inet_sock *inet = inet_sk(sk);
if (inet->num == hnum && sk->sk_family == PF_INET6) {
@@ -132,20 +110,11 @@ static struct sock *udp_v6_lookup(struct in6_addr *saddr, u16 sport,
}
/*
- *
- */
-
-static void udpv6_close(struct sock *sk, long timeout)
-{
- sk_common_release(sk);
-}
-
-/*
* This should be easy, if there is something there we
* return it, otherwise we block.
*/
-static int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk,
+int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk,
struct msghdr *msg, size_t len,
int noblock, int flags, int *addr_len)
{
@@ -153,7 +122,7 @@ static int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk,
struct inet_sock *inet = inet_sk(sk);
struct sk_buff *skb;
size_t copied;
- int err;
+ int err, copy_only, is_udplite = IS_UDPLITE(sk);
if (addr_len)
*addr_len=sizeof(struct sockaddr_in6);
@@ -172,15 +141,21 @@ try_again:
msg->msg_flags |= MSG_TRUNC;
}
- if (skb->ip_summed==CHECKSUM_UNNECESSARY) {
- err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov,
- copied);
- } else if (msg->msg_flags&MSG_TRUNC) {
- if (__skb_checksum_complete(skb))
+ /*
+ * Decide whether to checksum and/or copy data.
+ */
+ copy_only = (skb->ip_summed==CHECKSUM_UNNECESSARY);
+
+ if (is_udplite || (!copy_only && msg->msg_flags&MSG_TRUNC)) {
+ if (__udp_lib_checksum_complete(skb))
goto csum_copy_err;
- err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov,
- copied);
- } else {
+ copy_only = 1;
+ }
+
+ if (copy_only)
+ err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr),
+ msg->msg_iov, copied );
+ else {
err = skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov);
if (err == -EINVAL)
goto csum_copy_err;
@@ -231,14 +206,15 @@ csum_copy_err:
skb_kill_datagram(sk, skb, flags);
if (flags & MSG_DONTWAIT) {
- UDP6_INC_STATS_USER(UDP_MIB_INERRORS);
+ UDP6_INC_STATS_USER(UDP_MIB_INERRORS, is_udplite);
return -EAGAIN;
}
goto try_again;
}
-static void udpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
- int type, int code, int offset, __u32 info)
+void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+ int type, int code, int offset, __be32 info,
+ struct hlist_head udptable[] )
{
struct ipv6_pinfo *np;
struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data;
@@ -248,8 +224,8 @@ static void udpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
struct sock *sk;
int err;
- sk = udp_v6_lookup(daddr, uh->dest, saddr, uh->source, inet6_iif(skb));
-
+ sk = __udp6_lib_lookup(daddr, uh->dest,
+ saddr, uh->source, inet6_iif(skb), udptable);
if (sk == NULL)
return;
@@ -270,36 +246,60 @@ out:
sock_put(sk);
}
-static inline int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
+static __inline__ void udpv6_err(struct sk_buff *skb,
+ struct inet6_skb_parm *opt, int type,
+ int code, int offset, __be32 info )
+{
+ return __udp6_lib_err(skb, opt, type, code, offset, info, udp_hash);
+}
+
+int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
{
+ struct udp_sock *up = udp_sk(sk);
int rc;
- if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) {
- kfree_skb(skb);
- return -1;
- }
+ if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
+ goto drop;
- if (skb_checksum_complete(skb)) {
- UDP6_INC_STATS_BH(UDP_MIB_INERRORS);
- kfree_skb(skb);
- return 0;
+ /*
+ * UDP-Lite specific tests, ignored on UDP sockets (see net/ipv4/udp.c).
+ */
+ if ((up->pcflag & UDPLITE_RECV_CC) && UDP_SKB_CB(skb)->partial_cov) {
+
+ if (up->pcrlen == 0) { /* full coverage was set */
+ LIMIT_NETDEBUG(KERN_WARNING "UDPLITE6: partial coverage"
+ " %d while full coverage %d requested\n",
+ UDP_SKB_CB(skb)->cscov, skb->len);
+ goto drop;
+ }
+ if (UDP_SKB_CB(skb)->cscov < up->pcrlen) {
+ LIMIT_NETDEBUG(KERN_WARNING "UDPLITE6: coverage %d "
+ "too small, need min %d\n",
+ UDP_SKB_CB(skb)->cscov, up->pcrlen);
+ goto drop;
+ }
}
+ if (udp_lib_checksum_complete(skb))
+ goto drop;
+
if ((rc = sock_queue_rcv_skb(sk,skb)) < 0) {
/* Note that an ENOMEM error is charged twice */
if (rc == -ENOMEM)
- UDP6_INC_STATS_BH(UDP_MIB_RCVBUFERRORS);
- UDP6_INC_STATS_BH(UDP_MIB_INERRORS);
- kfree_skb(skb);
- return 0;
+ UDP6_INC_STATS_BH(UDP_MIB_RCVBUFERRORS, up->pcflag);
+ goto drop;
}
- UDP6_INC_STATS_BH(UDP_MIB_INDATAGRAMS);
+ UDP6_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag);
return 0;
+drop:
+ UDP6_INC_STATS_BH(UDP_MIB_INERRORS, up->pcflag);
+ kfree_skb(skb);
+ return -1;
}
static struct sock *udp_v6_mcast_next(struct sock *sk,
- u16 loc_port, struct in6_addr *loc_addr,
- u16 rmt_port, struct in6_addr *rmt_addr,
+ __be16 loc_port, struct in6_addr *loc_addr,
+ __be16 rmt_port, struct in6_addr *rmt_addr,
int dif)
{
struct hlist_node *node;
@@ -338,15 +338,15 @@ static struct sock *udp_v6_mcast_next(struct sock *sk,
* Note: called only from the BH handler context,
* so we don't need to lock the hashes.
*/
-static void udpv6_mcast_deliver(struct udphdr *uh,
- struct in6_addr *saddr, struct in6_addr *daddr,
- struct sk_buff *skb)
+static int __udp6_lib_mcast_deliver(struct sk_buff *skb, struct in6_addr *saddr,
+ struct in6_addr *daddr, struct hlist_head udptable[])
{
struct sock *sk, *sk2;
+ const struct udphdr *uh = skb->h.uh;
int dif;
read_lock(&udp_hash_lock);
- sk = sk_head(&udp_hash[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)]);
+ sk = sk_head(&udptable[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)]);
dif = inet6_iif(skb);
sk = udp_v6_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif);
if (!sk) {
@@ -364,9 +364,35 @@ static void udpv6_mcast_deliver(struct udphdr *uh,
udpv6_queue_rcv_skb(sk, skb);
out:
read_unlock(&udp_hash_lock);
+ return 0;
+}
+
+static inline int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh)
+
+{
+ if (uh->check == 0) {
+ /* RFC 2460 section 8.1 says that we SHOULD log
+ this error. Well, it is reasonable.
+ */
+ LIMIT_NETDEBUG(KERN_INFO "IPv6: udp checksum is 0\n");
+ return 1;
+ }
+ if (skb->ip_summed == CHECKSUM_COMPLETE &&
+ !csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr,
+ skb->len, IPPROTO_UDP, skb->csum ))
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+ if (skb->ip_summed != CHECKSUM_UNNECESSARY)
+ skb->csum = ~csum_unfold(csum_ipv6_magic(&skb->nh.ipv6h->saddr,
+ &skb->nh.ipv6h->daddr,
+ skb->len, IPPROTO_UDP,
+ 0));
+
+ return (UDP_SKB_CB(skb)->partial_cov = 0);
}
-static int udpv6_rcv(struct sk_buff **pskb)
+int __udp6_lib_rcv(struct sk_buff **pskb, struct hlist_head udptable[],
+ int is_udplite)
{
struct sk_buff *skb = *pskb;
struct sock *sk;
@@ -383,44 +409,39 @@ static int udpv6_rcv(struct sk_buff **pskb)
uh = skb->h.uh;
ulen = ntohs(uh->len);
+ if (ulen > skb->len)
+ goto short_packet;
- /* Check for jumbo payload */
- if (ulen == 0)
- ulen = skb->len;
+ if(! is_udplite ) { /* UDP validates ulen. */
- if (ulen > skb->len || ulen < sizeof(*uh))
- goto short_packet;
+ /* Check for jumbo payload */
+ if (ulen == 0)
+ ulen = skb->len;
- if (uh->check == 0) {
- /* RFC 2460 section 8.1 says that we SHOULD log
- this error. Well, it is reasonable.
- */
- LIMIT_NETDEBUG(KERN_INFO "IPv6: udp checksum is 0\n");
- goto discard;
- }
+ if (ulen < sizeof(*uh))
+ goto short_packet;
- if (ulen < skb->len) {
- if (pskb_trim_rcsum(skb, ulen))
- goto discard;
- saddr = &skb->nh.ipv6h->saddr;
- daddr = &skb->nh.ipv6h->daddr;
- uh = skb->h.uh;
- }
+ if (ulen < skb->len) {
+ if (pskb_trim_rcsum(skb, ulen))
+ goto short_packet;
+ saddr = &skb->nh.ipv6h->saddr;
+ daddr = &skb->nh.ipv6h->daddr;
+ uh = skb->h.uh;
+ }
- if (skb->ip_summed == CHECKSUM_COMPLETE &&
- !csum_ipv6_magic(saddr, daddr, ulen, IPPROTO_UDP, skb->csum))
- skb->ip_summed = CHECKSUM_UNNECESSARY;
+ if (udp6_csum_init(skb, uh))
+ goto discard;
- if (skb->ip_summed != CHECKSUM_UNNECESSARY)
- skb->csum = ~csum_ipv6_magic(saddr, daddr, ulen, IPPROTO_UDP, 0);
+ } else { /* UDP-Lite validates cscov. */
+ if (udplite6_csum_init(skb, uh))
+ goto discard;
+ }
/*
* Multicast receive code
*/
- if (ipv6_addr_is_multicast(daddr)) {
- udpv6_mcast_deliver(uh, saddr, daddr, skb);
- return 0;
- }
+ if (ipv6_addr_is_multicast(daddr))
+ return __udp6_lib_mcast_deliver(skb, saddr, daddr, udptable);
/* Unicast */
@@ -428,15 +449,16 @@ static int udpv6_rcv(struct sk_buff **pskb)
* check socket cache ... must talk to Alan about his plans
* for sock caches... i'll skip this for now.
*/
- sk = udp_v6_lookup(saddr, uh->source, daddr, uh->dest, inet6_iif(skb));
+ sk = __udp6_lib_lookup(saddr, uh->source,
+ daddr, uh->dest, inet6_iif(skb), udptable);
if (sk == NULL) {
if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
goto discard;
- if (skb_checksum_complete(skb))
+ if (udp_lib_checksum_complete(skb))
goto discard;
- UDP6_INC_STATS_BH(UDP_MIB_NOPORTS);
+ UDP6_INC_STATS_BH(UDP_MIB_NOPORTS, is_udplite);
icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, dev);
@@ -451,14 +473,20 @@ static int udpv6_rcv(struct sk_buff **pskb)
return(0);
short_packet:
- if (net_ratelimit())
- printk(KERN_DEBUG "UDP: short packet: %d/%u\n", ulen, skb->len);
+ LIMIT_NETDEBUG(KERN_DEBUG "UDP%sv6: short packet: %d/%u\n",
+ is_udplite? "-Lite" : "", ulen, skb->len);
discard:
- UDP6_INC_STATS_BH(UDP_MIB_INERRORS);
+ UDP6_INC_STATS_BH(UDP_MIB_INERRORS, is_udplite);
kfree_skb(skb);
return(0);
}
+
+static __inline__ int udpv6_rcv(struct sk_buff **pskb)
+{
+ return __udp6_lib_rcv(pskb, udp_hash, 0);
+}
+
/*
* Throw away all pending data and cancel the corking. Socket is locked.
*/
@@ -477,13 +505,15 @@ static void udp_v6_flush_pending_frames(struct sock *sk)
* Sending
*/
-static int udp_v6_push_pending_frames(struct sock *sk, struct udp_sock *up)
+static int udp_v6_push_pending_frames(struct sock *sk)
{
struct sk_buff *skb;
struct udphdr *uh;
+ struct udp_sock *up = udp_sk(sk);
struct inet_sock *inet = inet_sk(sk);
struct flowi *fl = &inet->cork.fl;
int err = 0;
+ __wsum csum = 0;
/* Grab the skbuff where UDP header space exists. */
if ((skb = skb_peek(&sk->sk_write_queue)) == NULL)
@@ -498,35 +528,17 @@ static int udp_v6_push_pending_frames(struct sock *sk, struct udp_sock *up)
uh->len = htons(up->len);
uh->check = 0;
- if (sk->sk_no_check == UDP_CSUM_NOXMIT) {
- skb->ip_summed = CHECKSUM_NONE;
- goto send;
- }
-
- if (skb_queue_len(&sk->sk_write_queue) == 1) {
- skb->csum = csum_partial((char *)uh,
- sizeof(struct udphdr), skb->csum);
- uh->check = csum_ipv6_magic(&fl->fl6_src,
- &fl->fl6_dst,
- up->len, fl->proto, skb->csum);
- } else {
- u32 tmp_csum = 0;
-
- skb_queue_walk(&sk->sk_write_queue, skb) {
- tmp_csum = csum_add(tmp_csum, skb->csum);
- }
- tmp_csum = csum_partial((char *)uh,
- sizeof(struct udphdr), tmp_csum);
- tmp_csum = csum_ipv6_magic(&fl->fl6_src,
- &fl->fl6_dst,
- up->len, fl->proto, tmp_csum);
- uh->check = tmp_csum;
+ if (up->pcflag)
+ csum = udplite_csum_outgoing(sk, skb);
+ else
+ csum = udp_csum_outgoing(sk, skb);
- }
+ /* add protocol-dependent pseudo-header */
+ uh->check = csum_ipv6_magic(&fl->fl6_src, &fl->fl6_dst,
+ up->len, fl->proto, csum );
if (uh->check == 0)
- uh->check = -1;
+ uh->check = CSUM_MANGLED_0;
-send:
err = ip6_push_pending_frames(sk);
out:
up->len = 0;
@@ -534,7 +546,7 @@ out:
return err;
}
-static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk,
+int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk,
struct msghdr *msg, size_t len)
{
struct ipv6_txoptions opt_space;
@@ -554,6 +566,8 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk,
int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
int err;
int connected = 0;
+ int is_udplite = up->pcflag;
+ int (*getfrag)(void *, char *, int, int, int, struct sk_buff *);
/* destination address check */
if (sin6) {
@@ -694,7 +708,7 @@ do_udp_sendmsg:
opt = fl6_merge_options(&opt_space, flowlabel, opt);
opt = ipv6_fixup_options(&opt_space, opt);
- fl.proto = IPPROTO_UDP;
+ fl.proto = sk->sk_protocol;
ipv6_addr_copy(&fl.fl6_dst, daddr);
if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr))
ipv6_addr_copy(&fl.fl6_src, &np->saddr);
@@ -761,14 +775,15 @@ back_from_confirm:
do_append_data:
up->len += ulen;
- err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, ulen,
+ getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag;
+ err = ip6_append_data(sk, getfrag, msg->msg_iov, ulen,
sizeof(struct udphdr), hlimit, tclass, opt, &fl,
(struct rt6_info*)dst,
corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags);
if (err)
udp_v6_flush_pending_frames(sk);
else if (!corkreq)
- err = udp_v6_push_pending_frames(sk, up);
+ err = udp_v6_push_pending_frames(sk);
else if (unlikely(skb_queue_empty(&sk->sk_write_queue)))
up->pending = 0;
@@ -793,7 +808,7 @@ do_append_data:
out:
fl6_sock_release(flowlabel);
if (!err) {
- UDP6_INC_STATS_USER(UDP_MIB_OUTDATAGRAMS);
+ UDP6_INC_STATS_USER(UDP_MIB_OUTDATAGRAMS, is_udplite);
return len;
}
/*
@@ -804,7 +819,7 @@ out:
* seems like overkill.
*/
if (err == -ENOBUFS || test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) {
- UDP6_INC_STATS_USER(UDP_MIB_SNDBUFERRORS);
+ UDP6_INC_STATS_USER(UDP_MIB_SNDBUFERRORS, is_udplite);
}
return err;
@@ -816,7 +831,7 @@ do_confirm:
goto out;
}
-static int udpv6_destroy_sock(struct sock *sk)
+int udpv6_destroy_sock(struct sock *sk)
{
lock_sock(sk);
udp_v6_flush_pending_frames(sk);
@@ -830,119 +845,41 @@ static int udpv6_destroy_sock(struct sock *sk)
/*
* Socket option code for UDP
*/
-static int do_udpv6_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen)
-{
- struct udp_sock *up = udp_sk(sk);
- int val;
- int err = 0;
-
- if(optlen<sizeof(int))
- return -EINVAL;
-
- if (get_user(val, (int __user *)optval))
- return -EFAULT;
-
- switch(optname) {
- case UDP_CORK:
- if (val != 0) {
- up->corkflag = 1;
- } else {
- up->corkflag = 0;
- lock_sock(sk);
- udp_v6_push_pending_frames(sk, up);
- release_sock(sk);
- }
- break;
-
- case UDP_ENCAP:
- switch (val) {
- case 0:
- up->encap_type = val;
- break;
- default:
- err = -ENOPROTOOPT;
- break;
- }
- break;
-
- default:
- err = -ENOPROTOOPT;
- break;
- };
-
- return err;
-}
-
-static int udpv6_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen)
+int udpv6_setsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int optlen)
{
- if (level != SOL_UDP)
- return ipv6_setsockopt(sk, level, optname, optval, optlen);
- return do_udpv6_setsockopt(sk, level, optname, optval, optlen);
+ if (level == SOL_UDP || level == SOL_UDPLITE)
+ return udp_lib_setsockopt(sk, level, optname, optval, optlen,
+ udp_v6_push_pending_frames);
+ return ipv6_setsockopt(sk, level, optname, optval, optlen);
}
#ifdef CONFIG_COMPAT
-static int compat_udpv6_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen)
+int compat_udpv6_setsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int optlen)
{
- if (level != SOL_UDP)
- return compat_ipv6_setsockopt(sk, level, optname,
- optval, optlen);
- return do_udpv6_setsockopt(sk, level, optname, optval, optlen);
+ if (level == SOL_UDP || level == SOL_UDPLITE)
+ return udp_lib_setsockopt(sk, level, optname, optval, optlen,
+ udp_v6_push_pending_frames);
+ return compat_ipv6_setsockopt(sk, level, optname, optval, optlen);
}
#endif
-static int do_udpv6_getsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int __user *optlen)
-{
- struct udp_sock *up = udp_sk(sk);
- int val, len;
-
- if(get_user(len,optlen))
- return -EFAULT;
-
- len = min_t(unsigned int, len, sizeof(int));
-
- if(len < 0)
- return -EINVAL;
-
- switch(optname) {
- case UDP_CORK:
- val = up->corkflag;
- break;
-
- case UDP_ENCAP:
- val = up->encap_type;
- break;
-
- default:
- return -ENOPROTOOPT;
- };
-
- if(put_user(len, optlen))
- return -EFAULT;
- if(copy_to_user(optval, &val,len))
- return -EFAULT;
- return 0;
-}
-
-static int udpv6_getsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int __user *optlen)
+int udpv6_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen)
{
- if (level != SOL_UDP)
- return ipv6_getsockopt(sk, level, optname, optval, optlen);
- return do_udpv6_getsockopt(sk, level, optname, optval, optlen);
+ if (level == SOL_UDP || level == SOL_UDPLITE)
+ return udp_lib_getsockopt(sk, level, optname, optval, optlen);
+ return ipv6_getsockopt(sk, level, optname, optval, optlen);
}
#ifdef CONFIG_COMPAT
-static int compat_udpv6_getsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int __user *optlen)
+int compat_udpv6_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen)
{
- if (level != SOL_UDP)
- return compat_ipv6_getsockopt(sk, level, optname,
- optval, optlen);
- return do_udpv6_getsockopt(sk, level, optname, optval, optlen);
+ if (level == SOL_UDP || level == SOL_UDPLITE)
+ return udp_lib_getsockopt(sk, level, optname, optval, optlen);
+ return compat_ipv6_getsockopt(sk, level, optname, optval, optlen);
}
#endif
@@ -983,7 +920,7 @@ static void udp6_sock_seq_show(struct seq_file *seq, struct sock *sp, int bucket
atomic_read(&sp->sk_refcnt), sp);
}
-static int udp6_seq_show(struct seq_file *seq, void *v)
+int udp6_seq_show(struct seq_file *seq, void *v)
{
if (v == SEQ_START_TOKEN)
seq_printf(seq,
@@ -1002,6 +939,7 @@ static struct udp_seq_afinfo udp6_seq_afinfo = {
.owner = THIS_MODULE,
.name = "udp6",
.family = AF_INET6,
+ .hashtable = udp_hash,
.seq_show = udp6_seq_show,
.seq_fops = &udp6_seq_fops,
};
@@ -1021,7 +959,7 @@ void udp6_proc_exit(void) {
struct proto udpv6_prot = {
.name = "UDPv6",
.owner = THIS_MODULE,
- .close = udpv6_close,
+ .close = udp_lib_close,
.connect = ip6_datagram_connect,
.disconnect = udp_disconnect,
.ioctl = udp_ioctl,
@@ -1031,8 +969,8 @@ struct proto udpv6_prot = {
.sendmsg = udpv6_sendmsg,
.recvmsg = udpv6_recvmsg,
.backlog_rcv = udpv6_queue_rcv_skb,
- .hash = udp_v6_hash,
- .unhash = udp_v6_unhash,
+ .hash = udp_lib_hash,
+ .unhash = udp_lib_unhash,
.get_port = udp_v6_get_port,
.obj_size = sizeof(struct udp6_sock),
#ifdef CONFIG_COMPAT
diff --git a/net/ipv6/udp_impl.h b/net/ipv6/udp_impl.h
new file mode 100644
index 000000000000..ec9878899128
--- /dev/null
+++ b/net/ipv6/udp_impl.h
@@ -0,0 +1,34 @@
+#ifndef _UDP6_IMPL_H
+#define _UDP6_IMPL_H
+#include <net/udp.h>
+#include <net/udplite.h>
+#include <net/protocol.h>
+#include <net/addrconf.h>
+#include <net/inet_common.h>
+
+extern int __udp6_lib_rcv(struct sk_buff **, struct hlist_head [], int );
+extern void __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *,
+ int , int , int , __be32 , struct hlist_head []);
+
+extern int udpv6_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen);
+extern int udpv6_setsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int optlen);
+#ifdef CONFIG_COMPAT
+extern int compat_udpv6_setsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int optlen);
+extern int compat_udpv6_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen);
+#endif
+extern int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk,
+ struct msghdr *msg, size_t len);
+extern int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk,
+ struct msghdr *msg, size_t len,
+ int noblock, int flags, int *addr_len);
+extern int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb);
+extern int udpv6_destroy_sock(struct sock *sk);
+
+#ifdef CONFIG_PROC_FS
+extern int udp6_seq_show(struct seq_file *seq, void *v);
+#endif
+#endif /* _UDP6_IMPL_H */
diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c
new file mode 100644
index 000000000000..629f97162fbc
--- /dev/null
+++ b/net/ipv6/udplite.c
@@ -0,0 +1,105 @@
+/*
+ * UDPLITEv6 An implementation of the UDP-Lite protocol over IPv6.
+ * See also net/ipv4/udplite.c
+ *
+ * Version: $Id: udplite.c,v 1.9 2006/10/19 08:28:10 gerrit Exp $
+ *
+ * Authors: Gerrit Renker <gerrit@erg.abdn.ac.uk>
+ *
+ * Changes:
+ * Fixes:
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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 "udp_impl.h"
+
+DEFINE_SNMP_STAT(struct udp_mib, udplite_stats_in6) __read_mostly;
+
+static int udplitev6_rcv(struct sk_buff **pskb)
+{
+ return __udp6_lib_rcv(pskb, udplite_hash, 1);
+}
+
+static void udplitev6_err(struct sk_buff *skb,
+ struct inet6_skb_parm *opt,
+ int type, int code, int offset, __be32 info)
+{
+ return __udp6_lib_err(skb, opt, type, code, offset, info, udplite_hash);
+}
+
+static struct inet6_protocol udplitev6_protocol = {
+ .handler = udplitev6_rcv,
+ .err_handler = udplitev6_err,
+ .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
+};
+
+static int udplite_v6_get_port(struct sock *sk, unsigned short snum)
+{
+ return udplite_get_port(sk, snum, ipv6_rcv_saddr_equal);
+}
+
+struct proto udplitev6_prot = {
+ .name = "UDPLITEv6",
+ .owner = THIS_MODULE,
+ .close = udp_lib_close,
+ .connect = ip6_datagram_connect,
+ .disconnect = udp_disconnect,
+ .ioctl = udp_ioctl,
+ .init = udplite_sk_init,
+ .destroy = udpv6_destroy_sock,
+ .setsockopt = udpv6_setsockopt,
+ .getsockopt = udpv6_getsockopt,
+ .sendmsg = udpv6_sendmsg,
+ .recvmsg = udpv6_recvmsg,
+ .backlog_rcv = udpv6_queue_rcv_skb,
+ .hash = udp_lib_hash,
+ .unhash = udp_lib_unhash,
+ .get_port = udplite_v6_get_port,
+ .obj_size = sizeof(struct udp6_sock),
+#ifdef CONFIG_COMPAT
+ .compat_setsockopt = compat_udpv6_setsockopt,
+ .compat_getsockopt = compat_udpv6_getsockopt,
+#endif
+};
+
+static struct inet_protosw udplite6_protosw = {
+ .type = SOCK_DGRAM,
+ .protocol = IPPROTO_UDPLITE,
+ .prot = &udplitev6_prot,
+ .ops = &inet6_dgram_ops,
+ .capability = -1,
+ .no_check = 0,
+ .flags = INET_PROTOSW_PERMANENT,
+};
+
+void __init udplitev6_init(void)
+{
+ if (inet6_add_protocol(&udplitev6_protocol, IPPROTO_UDPLITE) < 0)
+ printk(KERN_ERR "%s: Could not register.\n", __FUNCTION__);
+
+ inet6_register_protosw(&udplite6_protosw);
+}
+
+#ifdef CONFIG_PROC_FS
+static struct file_operations udplite6_seq_fops;
+static struct udp_seq_afinfo udplite6_seq_afinfo = {
+ .owner = THIS_MODULE,
+ .name = "udplite6",
+ .family = AF_INET6,
+ .hashtable = udplite_hash,
+ .seq_show = udp6_seq_show,
+ .seq_fops = &udplite6_seq_fops,
+};
+
+int __init udplite6_proc_init(void)
+{
+ return udp_proc_register(&udplite6_seq_afinfo);
+}
+
+void udplite6_proc_exit(void)
+{
+ udp_proc_unregister(&udplite6_seq_afinfo);
+}
+#endif
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index d400f8fae129..8dffd4daae9c 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -274,11 +274,12 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl)
break;
case IPPROTO_UDP:
+ case IPPROTO_UDPLITE:
case IPPROTO_TCP:
case IPPROTO_SCTP:
case IPPROTO_DCCP:
if (pskb_may_pull(skb, skb->nh.raw + offset + 4 - skb->data)) {
- u16 *ports = (u16 *)exthdr;
+ __be16 *ports = (__be16 *)exthdr;
fl->fl_ip_sport = ports[0];
fl->fl_ip_dport = ports[1];
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index 7931e4f898d4..01a5c52a2be3 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -62,7 +62,7 @@ static unsigned inline xfrm6_tunnel_spi_hash_byaddr(xfrm_address_t *addr)
{
unsigned h;
- h = addr->a6[0] ^ addr->a6[1] ^ addr->a6[2] ^ addr->a6[3];
+ h = (__force u32)(addr->a6[0] ^ addr->a6[1] ^ addr->a6[2] ^ addr->a6[3]);
h ^= h >> 16;
h ^= h >> 8;
h &= XFRM6_TUNNEL_SPI_BYADDR_HSIZE - 1;
@@ -126,7 +126,7 @@ static struct xfrm6_tunnel_spi *__xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr)
return NULL;
}
-u32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr)
+__be32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr)
{
struct xfrm6_tunnel_spi *x6spi;
u32 spi;
@@ -196,7 +196,7 @@ out:
return spi;
}
-u32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr)
+__be32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr)
{
struct xfrm6_tunnel_spi *x6spi;
u32 spi;
@@ -265,7 +265,7 @@ static int xfrm6_tunnel_rcv(struct sk_buff *skb)
}
static int xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
- int type, int code, int offset, __u32 info)
+ int type, int code, int offset, __be32 info)
{
/* xfrm6_tunnel native err handling */
switch (type) {
diff --git a/net/irda/iriap.c b/net/irda/iriap.c
index 415cf4eec23b..8cfd076c4c12 100644
--- a/net/irda/iriap.c
+++ b/net/irda/iriap.c
@@ -172,7 +172,7 @@ struct iriap_cb *iriap_open(__u8 slsap_sel, int mode, void *priv,
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
- self = kmalloc(sizeof(struct iriap_cb), GFP_ATOMIC);
+ self = kzalloc(sizeof(*self), GFP_ATOMIC);
if (!self) {
IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
return NULL;
@@ -181,7 +181,6 @@ struct iriap_cb *iriap_open(__u8 slsap_sel, int mode, void *priv,
/*
* Initialize instance
*/
- memset(self, 0, sizeof(struct iriap_cb));
self->magic = IAS_MAGIC;
self->mode = mode;
@@ -451,12 +450,12 @@ static void iriap_getvaluebyclass_confirm(struct iriap_cb *self,
n = 2;
/* Get length, MSB first */
- len = be16_to_cpu(get_unaligned((__u16 *)(fp+n))); n += 2;
+ len = be16_to_cpu(get_unaligned((__be16 *)(fp+n))); n += 2;
IRDA_DEBUG(4, "%s(), len=%d\n", __FUNCTION__, len);
/* Get object ID, MSB first */
- obj_id = be16_to_cpu(get_unaligned((__u16 *)(fp+n))); n += 2;
+ obj_id = be16_to_cpu(get_unaligned((__be16 *)(fp+n))); n += 2;
type = fp[n++];
IRDA_DEBUG(4, "%s(), Value type = %d\n", __FUNCTION__, type);
@@ -506,7 +505,7 @@ static void iriap_getvaluebyclass_confirm(struct iriap_cb *self,
value = irias_new_string_value(fp+n);
break;
case IAS_OCT_SEQ:
- value_len = be16_to_cpu(get_unaligned((__u16 *)(fp+n)));
+ value_len = be16_to_cpu(get_unaligned((__be16 *)(fp+n)));
n += 2;
/* Will truncate to IAS_MAX_OCTET_STRING bytes */
@@ -544,7 +543,7 @@ static void iriap_getvaluebyclass_response(struct iriap_cb *self,
{
struct sk_buff *tx_skb;
int n;
- __u32 tmp_be32;
+ __be32 tmp_be32;
__be16 tmp_be16;
__u8 *fp;
diff --git a/net/irda/irias_object.c b/net/irda/irias_object.c
index 56292ab7d652..b1ee99a59c0c 100644
--- a/net/irda/irias_object.c
+++ b/net/irda/irias_object.c
@@ -501,13 +501,12 @@ struct ias_value *irias_new_octseq_value(__u8 *octseq , int len)
len = IAS_MAX_OCTET_STRING;
value->len = len;
- value->t.oct_seq = kmalloc(len, GFP_ATOMIC);
+ value->t.oct_seq = kmemdup(octseq, len, GFP_ATOMIC);
if (value->t.oct_seq == NULL){
IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
kfree(value);
return NULL;
}
- memcpy(value->t.oct_seq, octseq , len);
return value;
}
@@ -522,7 +521,6 @@ struct ias_value *irias_new_missing_value(void)
}
value->type = IAS_MISSING;
- value->len = 0;
return value;
}
diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c
index 9b962f247714..2bb04ac09329 100644
--- a/net/irda/irlan/irlan_common.c
+++ b/net/irda/irlan/irlan_common.c
@@ -995,7 +995,7 @@ static int __irlan_insert_param(struct sk_buff *skb, char *param, int type,
{
__u8 *frame;
__u8 param_len;
- __u16 tmp_le; /* Temporary value in little endian format */
+ __le16 tmp_le; /* Temporary value in little endian format */
int n=0;
if (skb == NULL) {
diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c
index fede83763095..7e5d12ab3b90 100644
--- a/net/irda/irlmp.c
+++ b/net/irda/irlmp.c
@@ -641,15 +641,13 @@ struct lsap_cb *irlmp_dup(struct lsap_cb *orig, void *instance)
}
/* Allocate a new instance */
- new = kmalloc(sizeof(struct lsap_cb), GFP_ATOMIC);
+ new = kmemdup(orig, sizeof(*new), GFP_ATOMIC);
if (!new) {
IRDA_DEBUG(0, "%s(), unable to kmalloc\n", __FUNCTION__);
spin_unlock_irqrestore(&irlmp->unconnected_lsaps->hb_spinlock,
flags);
return NULL;
}
- /* Dup */
- memcpy(new, orig, sizeof(struct lsap_cb));
/* new->lap = orig->lap; => done in the memcpy() */
/* new->slsap_sel = orig->slsap_sel; => done in the memcpy() */
new->conn_skb = NULL;
diff --git a/net/irda/irqueue.c b/net/irda/irqueue.c
index 1ba8c7106639..1d26cd33ea13 100644
--- a/net/irda/irqueue.c
+++ b/net/irda/irqueue.c
@@ -356,14 +356,13 @@ hashbin_t *hashbin_new(int type)
/*
* Allocate new hashbin
*/
- hashbin = kmalloc( sizeof(hashbin_t), GFP_ATOMIC);
+ hashbin = kzalloc(sizeof(*hashbin), GFP_ATOMIC);
if (!hashbin)
return NULL;
/*
* Initialize structure
*/
- memset(hashbin, 0, sizeof(hashbin_t));
hashbin->hb_type = type;
hashbin->magic = HB_MAGIC;
//hashbin->hb_current = NULL;
diff --git a/net/irda/irttp.c b/net/irda/irttp.c
index 3c2e70b77df1..9c446a72ff1f 100644
--- a/net/irda/irttp.c
+++ b/net/irda/irttp.c
@@ -1147,7 +1147,7 @@ int irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel,
frame[3] = 0x02; /* Value length */
put_unaligned(cpu_to_be16((__u16) max_sdu_size),
- (__u16 *)(frame+4));
+ (__be16 *)(frame+4));
} else {
/* Insert plain TTP header */
frame = skb_push(tx_skb, TTP_HEADER);
@@ -1394,7 +1394,7 @@ int irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size,
frame[3] = 0x02; /* Value length */
put_unaligned(cpu_to_be16((__u16) max_sdu_size),
- (__u16 *)(frame+4));
+ (__be16 *)(frame+4));
} else {
/* Insert TTP header */
frame = skb_push(tx_skb, TTP_HEADER);
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 20ff7cca1d07..0e1dbfbb9b10 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -1767,11 +1767,11 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq)
/* addresses present only in tunnel mode */
if (t->mode == XFRM_MODE_TUNNEL) {
- switch (xp->family) {
+ struct sockaddr *sa;
+ sa = (struct sockaddr *)(rq+1);
+ switch(sa->sa_family) {
case AF_INET:
- sin = (void*)(rq+1);
- if (sin->sin_family != AF_INET)
- return -EINVAL;
+ sin = (struct sockaddr_in*)sa;
t->saddr.a4 = sin->sin_addr.s_addr;
sin++;
if (sin->sin_family != AF_INET)
@@ -1780,9 +1780,7 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq)
break;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
case AF_INET6:
- sin6 = (void *)(rq+1);
- if (sin6->sin6_family != AF_INET6)
- return -EINVAL;
+ sin6 = (struct sockaddr_in6*)sa;
memcpy(t->saddr.a6, &sin6->sin6_addr, sizeof(struct in6_addr));
sin6++;
if (sin6->sin6_family != AF_INET6)
@@ -1793,7 +1791,10 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq)
default:
return -EINVAL;
}
- }
+ t->encap_family = sa->sa_family;
+ } else
+ t->encap_family = xp->family;
+
/* No way to set this via kame pfkey */
t->aalgos = t->ealgos = t->calgos = ~0;
xp->xfrm_nr++;
@@ -1830,18 +1831,25 @@ static inline int pfkey_xfrm_policy2sec_ctx_size(struct xfrm_policy *xp)
static int pfkey_xfrm_policy2msg_size(struct xfrm_policy *xp)
{
+ struct xfrm_tmpl *t;
int sockaddr_size = pfkey_sockaddr_size(xp->family);
- int socklen = (xp->family == AF_INET ?
- sizeof(struct sockaddr_in) :
- sizeof(struct sockaddr_in6));
+ int socklen = 0;
+ int i;
+
+ for (i=0; i<xp->xfrm_nr; i++) {
+ t = xp->xfrm_vec + i;
+ socklen += (t->encap_family == AF_INET ?
+ sizeof(struct sockaddr_in) :
+ sizeof(struct sockaddr_in6));
+ }
return sizeof(struct sadb_msg) +
(sizeof(struct sadb_lifetime) * 3) +
(sizeof(struct sadb_address) * 2) +
(sockaddr_size * 2) +
sizeof(struct sadb_x_policy) +
- (xp->xfrm_nr * (sizeof(struct sadb_x_ipsecrequest) +
- (socklen * 2))) +
+ (xp->xfrm_nr * sizeof(struct sadb_x_ipsecrequest)) +
+ (socklen * 2) +
pfkey_xfrm_policy2sec_ctx_size(xp);
}
@@ -1999,7 +2007,9 @@ static void pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, i
req_size = sizeof(struct sadb_x_ipsecrequest);
if (t->mode == XFRM_MODE_TUNNEL)
- req_size += 2*socklen;
+ req_size += ((t->encap_family == AF_INET ?
+ sizeof(struct sockaddr_in) :
+ sizeof(struct sockaddr_in6)) * 2);
else
size -= 2*socklen;
rq = (void*)skb_put(skb, req_size);
@@ -2015,7 +2025,7 @@ static void pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, i
rq->sadb_x_ipsecrequest_level = IPSEC_LEVEL_USE;
rq->sadb_x_ipsecrequest_reqid = t->reqid;
if (t->mode == XFRM_MODE_TUNNEL) {
- switch (xp->family) {
+ switch (t->encap_family) {
case AF_INET:
sin = (void*)(rq+1);
sin->sin_family = AF_INET;
@@ -2938,7 +2948,7 @@ out:
return NULL;
}
-static int pfkey_send_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport)
+static int pfkey_send_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport)
{
struct sk_buff *skb;
struct sadb_msg *hdr;
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
index 2652ead96c64..190bb3e05188 100644
--- a/net/llc/af_llc.c
+++ b/net/llc/af_llc.c
@@ -64,7 +64,7 @@ static inline u16 llc_ui_next_link_no(int sap)
*
* Given an ARP header type return the corresponding ethernet protocol.
*/
-static inline u16 llc_proto_type(u16 arphrd)
+static inline __be16 llc_proto_type(u16 arphrd)
{
return arphrd == ARPHRD_IEEE802_TR ?
htons(ETH_P_TR_802_2) : htons(ETH_P_802_2);
diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c
index 94d2368ade92..db82aff6e40f 100644
--- a/net/llc/llc_input.c
+++ b/net/llc/llc_input.c
@@ -115,8 +115,8 @@ static inline int llc_fixup_skb(struct sk_buff *skb)
skb->h.raw += llc_len;
skb_pull(skb, llc_len);
if (skb->protocol == htons(ETH_P_802_2)) {
- u16 pdulen = eth_hdr(skb)->h_proto,
- data_size = ntohs(pdulen) - llc_len;
+ __be16 pdulen = eth_hdr(skb)->h_proto;
+ u16 data_size = ntohs(pdulen) - llc_len;
if (unlikely(pskb_trim_rcsum(skb, data_size)))
return 0;
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index f619c6527266..3a66878a1829 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -25,19 +25,57 @@ config NETFILTER_NETLINK_LOG
and is also scheduled to replace the old syslog-based ipt_LOG
and ip6t_LOG modules.
-config NF_CONNTRACK
- tristate "Layer 3 Independent Connection tracking (EXPERIMENTAL)"
- depends on EXPERIMENTAL && IP_NF_CONNTRACK=n
- default n
- ---help---
+config NF_CONNTRACK_ENABLED
+ tristate "Netfilter connection tracking support"
+ help
Connection tracking keeps a record of what packets have passed
through your machine, in order to figure out how they are related
into connections.
+ This is required to do Masquerading or other kinds of Network
+ Address Translation (except for Fast NAT). It can also be used to
+ enhance packet filtering (see `Connection state match support'
+ below).
+
+ To compile it as a module, choose M here. If unsure, say N.
+
+choice
+ prompt "Netfilter connection tracking support"
+ depends on NF_CONNTRACK_ENABLED
+
+config NF_CONNTRACK_SUPPORT
+ bool "Layer 3 Independent Connection tracking (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ help
Layer 3 independent connection tracking is experimental scheme
which generalize ip_conntrack to support other layer 3 protocols.
- To compile it as a module, choose M here. If unsure, say N.
+ This is required to do Masquerading or other kinds of Network
+ Address Translation (except for Fast NAT). It can also be used to
+ enhance packet filtering (see `Connection state match support'
+ below).
+
+config IP_NF_CONNTRACK_SUPPORT
+ bool "Layer 3 Dependent Connection tracking (OBSOLETE)"
+ help
+ The old, Layer 3 dependent ip_conntrack subsystem of netfilter.
+
+ This is required to do Masquerading or other kinds of Network
+ Address Translation (except for Fast NAT). It can also be used to
+ enhance packet filtering (see `Connection state match support'
+ below).
+
+endchoice
+
+config NF_CONNTRACK
+ tristate
+ default m if NF_CONNTRACK_SUPPORT && NF_CONNTRACK_ENABLED=m
+ default y if NF_CONNTRACK_SUPPORT && NF_CONNTRACK_ENABLED=y
+
+config IP_NF_CONNTRACK
+ tristate
+ default m if IP_NF_CONNTRACK_SUPPORT && NF_CONNTRACK_ENABLED=m
+ default y if IP_NF_CONNTRACK_SUPPORT && NF_CONNTRACK_ENABLED=y
config NF_CT_ACCT
bool "Connection tracking flow accounting"
@@ -82,8 +120,12 @@ config NF_CONNTRACK_EVENTS
If unsure, say `N'.
+config NF_CT_PROTO_GRE
+ tristate
+ depends on EXPERIMENTAL && NF_CONNTRACK
+
config NF_CT_PROTO_SCTP
- tristate 'SCTP protocol on new connection tracking support (EXPERIMENTAL)'
+ tristate 'SCTP protocol connection tracking support (EXPERIMENTAL)'
depends on EXPERIMENTAL && NF_CONNTRACK
default n
help
@@ -93,8 +135,23 @@ config NF_CT_PROTO_SCTP
If you want to compile it as a module, say M here and read
Documentation/modules.txt. If unsure, say `N'.
+config NF_CONNTRACK_AMANDA
+ tristate "Amanda backup protocol support (EXPERIMENTAL)"
+ depends on EXPERIMENTAL && NF_CONNTRACK
+ select TEXTSEARCH
+ select TEXTSEARCH_KMP
+ help
+ If you are running the Amanda backup package <http://www.amanda.org/>
+ on this machine or machines that will be MASQUERADED through this
+ machine, then you may want to enable this feature. This allows the
+ connection tracking and natting code to allow the sub-channels that
+ Amanda requires for communication of the backup data, messages and
+ index.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config NF_CONNTRACK_FTP
- tristate "FTP support on new connection tracking (EXPERIMENTAL)"
+ tristate "FTP protocol support (EXPERIMENTAL)"
depends on EXPERIMENTAL && NF_CONNTRACK
help
Tracking FTP connections is problematic: special helpers are
@@ -107,6 +164,101 @@ config NF_CONNTRACK_FTP
To compile it as a module, choose M here. If unsure, say N.
+config NF_CONNTRACK_H323
+ tristate "H.323 protocol support (EXPERIMENTAL)"
+ depends on EXPERIMENTAL && NF_CONNTRACK
+ help
+ H.323 is a VoIP signalling protocol from ITU-T. As one of the most
+ important VoIP protocols, it is widely used by voice hardware and
+ software including voice gateways, IP phones, Netmeeting, OpenPhone,
+ Gnomemeeting, etc.
+
+ With this module you can support H.323 on a connection tracking/NAT
+ firewall.
+
+ This module supports RAS, Fast Start, H.245 Tunnelling, Call
+ Forwarding, RTP/RTCP and T.120 based audio, video, fax, chat,
+ whiteboard, file transfer, etc. For more information, please
+ visit http://nath323.sourceforge.net/.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
+config NF_CONNTRACK_IRC
+ tristate "IRC protocol support (EXPERIMENTAL)"
+ depends on EXPERIMENTAL && NF_CONNTRACK
+ help
+ There is a commonly-used extension to IRC called
+ Direct Client-to-Client Protocol (DCC). This enables users to send
+ files to each other, and also chat to each other without the need
+ of a server. DCC Sending is used anywhere you send files over IRC,
+ and DCC Chat is most commonly used by Eggdrop bots. If you are
+ using NAT, this extension will enable you to send files and initiate
+ chats. Note that you do NOT need this extension to get files or
+ have others initiate chats, or everything else in IRC.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
+config NF_CONNTRACK_NETBIOS_NS
+ tristate "NetBIOS name service protocol support (EXPERIMENTAL)"
+ depends on EXPERIMENTAL && NF_CONNTRACK
+ help
+ NetBIOS name service requests are sent as broadcast messages from an
+ unprivileged port and responded to with unicast messages to the
+ same port. This make them hard to firewall properly because connection
+ tracking doesn't deal with broadcasts. This helper tracks locally
+ originating NetBIOS name service requests and the corresponding
+ responses. It relies on correct IP address configuration, specifically
+ netmask and broadcast address. When properly configured, the output
+ of "ip address show" should look similar to this:
+
+ $ ip -4 address show eth0
+ 4: eth0: <BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast qlen 1000
+ inet 172.16.2.252/24 brd 172.16.2.255 scope global eth0
+
+ To compile it as a module, choose M here. If unsure, say N.
+
+config NF_CONNTRACK_PPTP
+ tristate "PPtP protocol support (EXPERIMENTAL)"
+ depends on EXPERIMENTAL && NF_CONNTRACK
+ select NF_CT_PROTO_GRE
+ help
+ This module adds support for PPTP (Point to Point Tunnelling
+ Protocol, RFC2637) connection tracking and NAT.
+
+ If you are running PPTP sessions over a stateful firewall or NAT
+ box, you may want to enable this feature.
+
+ Please note that not all PPTP modes of operation are supported yet.
+ Specifically these limitations exist:
+ - Blindy assumes that control connections are always established
+ in PNS->PAC direction. This is a violation of RFC2637.
+ - Only supports a single call within each session
+
+ To compile it as a module, choose M here. If unsure, say N.
+
+config NF_CONNTRACK_SIP
+ tristate "SIP protocol support (EXPERIMENTAL)"
+ depends on EXPERIMENTAL && NF_CONNTRACK
+ help
+ SIP is an application-layer control protocol that can establish,
+ modify, and terminate multimedia sessions (conferences) such as
+ Internet telephony calls. With the ip_conntrack_sip and
+ the nf_nat_sip modules you can support the protocol on a connection
+ tracking/NATing firewall.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
+config NF_CONNTRACK_TFTP
+ tristate "TFTP protocol support (EXPERIMENTAL)"
+ depends on EXPERIMENTAL && NF_CONNTRACK
+ help
+ TFTP connection tracking helper, this is required depending
+ on how restrictive your ruleset is.
+ If you are using a tftp client behind -j SNAT or -j MASQUERADING
+ you will need this.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config NF_CT_NETLINK
tristate 'Connection tracking netlink interface (EXPERIMENTAL)'
depends on EXPERIMENTAL && NF_CONNTRACK && NETFILTER_NETLINK
@@ -184,6 +336,17 @@ config NETFILTER_XT_TARGET_NFQUEUE
To compile it as a module, choose M here. If unsure, say N.
+config NETFILTER_XT_TARGET_NFLOG
+ tristate '"NFLOG" target support'
+ depends on NETFILTER_XTABLES
+ help
+ This option enables the NFLOG target, which allows to LOG
+ messages through the netfilter logging API, which can use
+ either the old LOG target, the old ULOG target or nfnetlink_log
+ as backend.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config NETFILTER_XT_TARGET_NOTRACK
tristate '"NOTRACK" target support'
depends on NETFILTER_XTABLES
@@ -464,5 +627,19 @@ config NETFILTER_XT_MATCH_TCPMSS
To compile it as a module, choose M here. If unsure, say N.
+config NETFILTER_XT_MATCH_HASHLIMIT
+ tristate '"hashlimit" match support'
+ depends on NETFILTER_XTABLES
+ help
+ This option adds a `hashlimit' match.
+
+ As opposed to `limit', this match dynamically creates a hash table
+ of limit buckets, based on your selection of source/destination
+ addresses and/or ports.
+
+ It enables you to express policies like `10kpps for any given
+ destination address' or `500pps from any given source address'
+ with a single rule.
+
endmenu
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index a74be492fd0a..5dc5574f7e99 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -1,7 +1,10 @@
netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o
-nf_conntrack-objs := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o
+
+nf_conntrack-y := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_proto.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o
+nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o
obj-$(CONFIG_NETFILTER) = netfilter.o
+obj-$(CONFIG_SYSCTL) += nf_sysctl.o
obj-$(CONFIG_NETFILTER_NETLINK) += nfnetlink.o
obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o
@@ -11,13 +14,23 @@ obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o
obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o
# SCTP protocol connection tracking
+obj-$(CONFIG_NF_CT_PROTO_GRE) += nf_conntrack_proto_gre.o
obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o
# netlink interface for nf_conntrack
obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o
# connection tracking helpers
+nf_conntrack_h323-objs := nf_conntrack_h323_main.o nf_conntrack_h323_asn1.o
+
+obj-$(CONFIG_NF_CONNTRACK_AMANDA) += nf_conntrack_amanda.o
obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o
+obj-$(CONFIG_NF_CONNTRACK_H323) += nf_conntrack_h323.o
+obj-$(CONFIG_NF_CONNTRACK_IRC) += nf_conntrack_irc.o
+obj-$(CONFIG_NF_CONNTRACK_NETBIOS_NS) += nf_conntrack_netbios_ns.o
+obj-$(CONFIG_NF_CONNTRACK_PPTP) += nf_conntrack_pptp.o
+obj-$(CONFIG_NF_CONNTRACK_SIP) += nf_conntrack_sip.o
+obj-$(CONFIG_NF_CONNTRACK_TFTP) += nf_conntrack_tftp.o
# generic X tables
obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
@@ -28,6 +41,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o
obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o
obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o
obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
+obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o
obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o
obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o
obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o
@@ -56,3 +70,4 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_STATISTIC) += xt_statistic.o
obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o
obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o
obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_HASHLIMIT) += xt_hashlimit.o
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index d80b935b3a92..291b8c6862f1 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -28,7 +28,7 @@
static DEFINE_SPINLOCK(afinfo_lock);
-struct nf_afinfo *nf_afinfo[NPROTO];
+struct nf_afinfo *nf_afinfo[NPROTO] __read_mostly;
EXPORT_SYMBOL(nf_afinfo);
int nf_register_afinfo(struct nf_afinfo *afinfo)
@@ -54,7 +54,7 @@ EXPORT_SYMBOL_GPL(nf_unregister_afinfo);
* of skbuffs queued for userspace, and not deregister a hook unless
* this is zero, but that sucks. Now, we simply check when the
* packets come back: if the hook is gone, the packet is discarded. */
-struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS];
+struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS] __read_mostly;
EXPORT_SYMBOL(nf_hooks);
static DEFINE_SPINLOCK(nf_hook_lock);
@@ -222,28 +222,21 @@ copy_skb:
}
EXPORT_SYMBOL(skb_make_writable);
-u_int16_t nf_csum_update(u_int32_t oldval, u_int32_t newval, u_int32_t csum)
-{
- u_int32_t diff[] = { oldval, newval };
-
- return csum_fold(csum_partial((char *)diff, sizeof(diff), ~csum));
-}
-EXPORT_SYMBOL(nf_csum_update);
-
-u_int16_t nf_proto_csum_update(struct sk_buff *skb,
- u_int32_t oldval, u_int32_t newval,
- u_int16_t csum, int pseudohdr)
+void nf_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb,
+ __be32 from, __be32 to, int pseudohdr)
{
+ __be32 diff[] = { ~from, to };
if (skb->ip_summed != CHECKSUM_PARTIAL) {
- csum = nf_csum_update(oldval, newval, csum);
+ *sum = csum_fold(csum_partial((char *)diff, sizeof(diff),
+ ~csum_unfold(*sum)));
if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr)
- skb->csum = nf_csum_update(oldval, newval, skb->csum);
+ skb->csum = ~csum_partial((char *)diff, sizeof(diff),
+ ~skb->csum);
} else if (pseudohdr)
- csum = ~nf_csum_update(oldval, newval, ~csum);
-
- return csum;
+ *sum = ~csum_fold(csum_partial((char *)diff, sizeof(diff),
+ csum_unfold(*sum)));
}
-EXPORT_SYMBOL(nf_proto_csum_update);
+EXPORT_SYMBOL(nf_proto_csum_replace4);
/* This does not belong here, but locally generated errors need it if connection
tracking in use: without this, connection may not be in hash table, and hence
diff --git a/net/netfilter/nf_conntrack_amanda.c b/net/netfilter/nf_conntrack_amanda.c
new file mode 100644
index 000000000000..b8869eab7650
--- /dev/null
+++ b/net/netfilter/nf_conntrack_amanda.c
@@ -0,0 +1,238 @@
+/* Amanda extension for IP connection tracking
+ *
+ * (C) 2002 by Brian J. Murrell <netfilter@interlinx.bc.ca>
+ * based on HW's ip_conntrack_irc.c as well as other modules
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/textsearch.h>
+#include <linux/skbuff.h>
+#include <linux/in.h>
+#include <linux/udp.h>
+#include <linux/netfilter.h>
+
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_expect.h>
+#include <net/netfilter/nf_conntrack_ecache.h>
+#include <net/netfilter/nf_conntrack_helper.h>
+#include <linux/netfilter/nf_conntrack_amanda.h>
+
+static unsigned int master_timeout __read_mostly = 300;
+static char *ts_algo = "kmp";
+
+MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>");
+MODULE_DESCRIPTION("Amanda connection tracking module");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ip_conntrack_amanda");
+
+module_param(master_timeout, uint, 0600);
+MODULE_PARM_DESC(master_timeout, "timeout for the master connection");
+module_param(ts_algo, charp, 0400);
+MODULE_PARM_DESC(ts_algo, "textsearch algorithm to use (default kmp)");
+
+unsigned int (*nf_nat_amanda_hook)(struct sk_buff **pskb,
+ enum ip_conntrack_info ctinfo,
+ unsigned int matchoff,
+ unsigned int matchlen,
+ struct nf_conntrack_expect *exp)
+ __read_mostly;
+EXPORT_SYMBOL_GPL(nf_nat_amanda_hook);
+
+enum amanda_strings {
+ SEARCH_CONNECT,
+ SEARCH_NEWLINE,
+ SEARCH_DATA,
+ SEARCH_MESG,
+ SEARCH_INDEX,
+};
+
+static struct {
+ char *string;
+ size_t len;
+ struct ts_config *ts;
+} search[] __read_mostly = {
+ [SEARCH_CONNECT] = {
+ .string = "CONNECT ",
+ .len = 8,
+ },
+ [SEARCH_NEWLINE] = {
+ .string = "\n",
+ .len = 1,
+ },
+ [SEARCH_DATA] = {
+ .string = "DATA ",
+ .len = 5,
+ },
+ [SEARCH_MESG] = {
+ .string = "MESG ",
+ .len = 5,
+ },
+ [SEARCH_INDEX] = {
+ .string = "INDEX ",
+ .len = 6,
+ },
+};
+
+static int amanda_help(struct sk_buff **pskb,
+ unsigned int protoff,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo)
+{
+ struct ts_state ts;
+ struct nf_conntrack_expect *exp;
+ struct nf_conntrack_tuple *tuple;
+ unsigned int dataoff, start, stop, off, i;
+ char pbuf[sizeof("65535")], *tmp;
+ u_int16_t len;
+ __be16 port;
+ int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
+ int ret = NF_ACCEPT;
+ typeof(nf_nat_amanda_hook) nf_nat_amanda;
+
+ /* Only look at packets from the Amanda server */
+ if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL)
+ return NF_ACCEPT;
+
+ /* increase the UDP timeout of the master connection as replies from
+ * Amanda clients to the server can be quite delayed */
+ nf_ct_refresh(ct, *pskb, master_timeout * HZ);
+
+ /* No data? */
+ dataoff = protoff + sizeof(struct udphdr);
+ if (dataoff >= (*pskb)->len) {
+ if (net_ratelimit())
+ printk("amanda_help: skblen = %u\n", (*pskb)->len);
+ return NF_ACCEPT;
+ }
+
+ memset(&ts, 0, sizeof(ts));
+ start = skb_find_text(*pskb, dataoff, (*pskb)->len,
+ search[SEARCH_CONNECT].ts, &ts);
+ if (start == UINT_MAX)
+ goto out;
+ start += dataoff + search[SEARCH_CONNECT].len;
+
+ memset(&ts, 0, sizeof(ts));
+ stop = skb_find_text(*pskb, start, (*pskb)->len,
+ search[SEARCH_NEWLINE].ts, &ts);
+ if (stop == UINT_MAX)
+ goto out;
+ stop += start;
+
+ for (i = SEARCH_DATA; i <= SEARCH_INDEX; i++) {
+ memset(&ts, 0, sizeof(ts));
+ off = skb_find_text(*pskb, start, stop, search[i].ts, &ts);
+ if (off == UINT_MAX)
+ continue;
+ off += start + search[i].len;
+
+ len = min_t(unsigned int, sizeof(pbuf) - 1, stop - off);
+ if (skb_copy_bits(*pskb, off, pbuf, len))
+ break;
+ pbuf[len] = '\0';
+
+ port = htons(simple_strtoul(pbuf, &tmp, 10));
+ len = tmp - pbuf;
+ if (port == 0 || len > 5)
+ break;
+
+ exp = nf_conntrack_expect_alloc(ct);
+ if (exp == NULL) {
+ ret = NF_DROP;
+ goto out;
+ }
+ tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
+ nf_conntrack_expect_init(exp, family,
+ &tuple->src.u3, &tuple->dst.u3,
+ IPPROTO_TCP, NULL, &port);
+
+ nf_nat_amanda = rcu_dereference(nf_nat_amanda_hook);
+ if (nf_nat_amanda && ct->status & IPS_NAT_MASK)
+ ret = nf_nat_amanda(pskb, ctinfo, off - dataoff,
+ len, exp);
+ else if (nf_conntrack_expect_related(exp) != 0)
+ ret = NF_DROP;
+ nf_conntrack_expect_put(exp);
+ }
+
+out:
+ return ret;
+}
+
+static struct nf_conntrack_helper amanda_helper[2] __read_mostly = {
+ {
+ .name = "amanda",
+ .max_expected = 3,
+ .timeout = 180,
+ .me = THIS_MODULE,
+ .help = amanda_help,
+ .tuple.src.l3num = AF_INET,
+ .tuple.src.u.udp.port = __constant_htons(10080),
+ .tuple.dst.protonum = IPPROTO_UDP,
+ .mask.src.l3num = 0xFFFF,
+ .mask.src.u.udp.port = __constant_htons(0xFFFF),
+ .mask.dst.protonum = 0xFF,
+ },
+ {
+ .name = "amanda",
+ .max_expected = 3,
+ .timeout = 180,
+ .me = THIS_MODULE,
+ .help = amanda_help,
+ .tuple.src.l3num = AF_INET6,
+ .tuple.src.u.udp.port = __constant_htons(10080),
+ .tuple.dst.protonum = IPPROTO_UDP,
+ .mask.src.l3num = 0xFFFF,
+ .mask.src.u.udp.port = __constant_htons(0xFFFF),
+ .mask.dst.protonum = 0xFF,
+ },
+};
+
+static void __exit nf_conntrack_amanda_fini(void)
+{
+ int i;
+
+ nf_conntrack_helper_unregister(&amanda_helper[0]);
+ nf_conntrack_helper_unregister(&amanda_helper[1]);
+ for (i = 0; i < ARRAY_SIZE(search); i++)
+ textsearch_destroy(search[i].ts);
+}
+
+static int __init nf_conntrack_amanda_init(void)
+{
+ int ret, i;
+
+ ret = -ENOMEM;
+ for (i = 0; i < ARRAY_SIZE(search); i++) {
+ search[i].ts = textsearch_prepare(ts_algo, search[i].string,
+ search[i].len,
+ GFP_KERNEL, TS_AUTOLOAD);
+ if (search[i].ts == NULL)
+ goto err1;
+ }
+ ret = nf_conntrack_helper_register(&amanda_helper[0]);
+ if (ret < 0)
+ goto err1;
+ ret = nf_conntrack_helper_register(&amanda_helper[1]);
+ if (ret < 0)
+ goto err2;
+ return 0;
+
+err2:
+ nf_conntrack_helper_unregister(&amanda_helper[0]);
+err1:
+ for (; i >= 0; i--) {
+ if (search[i].ts)
+ textsearch_destroy(search[i].ts);
+ }
+ return ret;
+}
+
+module_init(nf_conntrack_amanda_init);
+module_exit(nf_conntrack_amanda_fini);
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 836541e509fe..93d97d9f9da8 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -47,14 +47,10 @@
#include <linux/netdevice.h>
#include <linux/socket.h>
-/* This rwlock protects the main hash table, protocol/helper/expected
- registrations, conntrack timers*/
-#define ASSERT_READ_LOCK(x)
-#define ASSERT_WRITE_LOCK(x)
-
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_l3proto.h>
-#include <net/netfilter/nf_conntrack_protocol.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
+#include <net/netfilter/nf_conntrack_expect.h>
#include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_core.h>
@@ -67,92 +63,32 @@
#endif
DEFINE_RWLOCK(nf_conntrack_lock);
+EXPORT_SYMBOL_GPL(nf_conntrack_lock);
/* nf_conntrack_standalone needs this */
atomic_t nf_conntrack_count = ATOMIC_INIT(0);
+EXPORT_SYMBOL_GPL(nf_conntrack_count);
-void (*nf_conntrack_destroyed)(struct nf_conn *conntrack) = NULL;
-LIST_HEAD(nf_conntrack_expect_list);
-struct nf_conntrack_protocol **nf_ct_protos[PF_MAX] __read_mostly;
-struct nf_conntrack_l3proto *nf_ct_l3protos[PF_MAX] __read_mostly;
-static LIST_HEAD(helpers);
-unsigned int nf_conntrack_htable_size __read_mostly = 0;
-int nf_conntrack_max __read_mostly;
-struct list_head *nf_conntrack_hash __read_mostly;
-static kmem_cache_t *nf_conntrack_expect_cachep __read_mostly;
-struct nf_conn nf_conntrack_untracked;
-unsigned int nf_ct_log_invalid __read_mostly;
-static LIST_HEAD(unconfirmed);
-static int nf_conntrack_vmalloc __read_mostly;
-
-static unsigned int nf_conntrack_next_id;
-static unsigned int nf_conntrack_expect_next_id;
-#ifdef CONFIG_NF_CONNTRACK_EVENTS
-ATOMIC_NOTIFIER_HEAD(nf_conntrack_chain);
-ATOMIC_NOTIFIER_HEAD(nf_conntrack_expect_chain);
+void (*nf_conntrack_destroyed)(struct nf_conn *conntrack);
+EXPORT_SYMBOL_GPL(nf_conntrack_destroyed);
-DEFINE_PER_CPU(struct nf_conntrack_ecache, nf_conntrack_ecache);
+unsigned int nf_conntrack_htable_size __read_mostly;
+EXPORT_SYMBOL_GPL(nf_conntrack_htable_size);
-/* deliver cached events and clear cache entry - must be called with locally
- * disabled softirqs */
-static inline void
-__nf_ct_deliver_cached_events(struct nf_conntrack_ecache *ecache)
-{
- DEBUGP("ecache: delivering events for %p\n", ecache->ct);
- if (nf_ct_is_confirmed(ecache->ct) && !nf_ct_is_dying(ecache->ct)
- && ecache->events)
- atomic_notifier_call_chain(&nf_conntrack_chain, ecache->events,
- ecache->ct);
-
- ecache->events = 0;
- nf_ct_put(ecache->ct);
- ecache->ct = NULL;
-}
+int nf_conntrack_max __read_mostly;
+EXPORT_SYMBOL_GPL(nf_conntrack_max);
-/* Deliver all cached events for a particular conntrack. This is called
- * by code prior to async packet handling for freeing the skb */
-void nf_ct_deliver_cached_events(const struct nf_conn *ct)
-{
- struct nf_conntrack_ecache *ecache;
+struct list_head *nf_conntrack_hash __read_mostly;
+EXPORT_SYMBOL_GPL(nf_conntrack_hash);
- local_bh_disable();
- ecache = &__get_cpu_var(nf_conntrack_ecache);
- if (ecache->ct == ct)
- __nf_ct_deliver_cached_events(ecache);
- local_bh_enable();
-}
+struct nf_conn nf_conntrack_untracked __read_mostly;
+EXPORT_SYMBOL_GPL(nf_conntrack_untracked);
-/* Deliver cached events for old pending events, if current conntrack != old */
-void __nf_ct_event_cache_init(struct nf_conn *ct)
-{
- struct nf_conntrack_ecache *ecache;
-
- /* take care of delivering potentially old events */
- ecache = &__get_cpu_var(nf_conntrack_ecache);
- BUG_ON(ecache->ct == ct);
- if (ecache->ct)
- __nf_ct_deliver_cached_events(ecache);
- /* initialize for this conntrack/packet */
- ecache->ct = ct;
- nf_conntrack_get(&ct->ct_general);
-}
-
-/* flush the event cache - touches other CPU's data and must not be called
- * while packets are still passing through the code */
-static void nf_ct_event_cache_flush(void)
-{
- struct nf_conntrack_ecache *ecache;
- int cpu;
+unsigned int nf_ct_log_invalid __read_mostly;
+LIST_HEAD(unconfirmed);
+static int nf_conntrack_vmalloc __read_mostly;
- for_each_possible_cpu(cpu) {
- ecache = &per_cpu(nf_conntrack_ecache, cpu);
- if (ecache->ct)
- nf_ct_put(ecache->ct);
- }
-}
-#else
-static inline void nf_ct_event_cache_flush(void) {}
-#endif /* CONFIG_NF_CONNTRACK_EVENTS */
+static unsigned int nf_conntrack_next_id;
DEFINE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat);
EXPORT_PER_CPU_SYMBOL(nf_conntrack_stat);
@@ -184,85 +120,6 @@ DEFINE_RWLOCK(nf_ct_cache_lock);
/* This avoids calling kmem_cache_create() with same name simultaneously */
static DEFINE_MUTEX(nf_ct_cache_mutex);
-extern struct nf_conntrack_protocol nf_conntrack_generic_protocol;
-struct nf_conntrack_protocol *
-__nf_ct_proto_find(u_int16_t l3proto, u_int8_t protocol)
-{
- if (unlikely(l3proto >= AF_MAX || nf_ct_protos[l3proto] == NULL))
- return &nf_conntrack_generic_protocol;
-
- return nf_ct_protos[l3proto][protocol];
-}
-
-/* this is guaranteed to always return a valid protocol helper, since
- * it falls back to generic_protocol */
-struct nf_conntrack_protocol *
-nf_ct_proto_find_get(u_int16_t l3proto, u_int8_t protocol)
-{
- struct nf_conntrack_protocol *p;
-
- preempt_disable();
- p = __nf_ct_proto_find(l3proto, protocol);
- if (!try_module_get(p->me))
- p = &nf_conntrack_generic_protocol;
- preempt_enable();
-
- return p;
-}
-
-void nf_ct_proto_put(struct nf_conntrack_protocol *p)
-{
- module_put(p->me);
-}
-
-struct nf_conntrack_l3proto *
-nf_ct_l3proto_find_get(u_int16_t l3proto)
-{
- struct nf_conntrack_l3proto *p;
-
- preempt_disable();
- p = __nf_ct_l3proto_find(l3proto);
- if (!try_module_get(p->me))
- p = &nf_conntrack_generic_l3proto;
- preempt_enable();
-
- return p;
-}
-
-void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p)
-{
- module_put(p->me);
-}
-
-int
-nf_ct_l3proto_try_module_get(unsigned short l3proto)
-{
- int ret;
- struct nf_conntrack_l3proto *p;
-
-retry: p = nf_ct_l3proto_find_get(l3proto);
- if (p == &nf_conntrack_generic_l3proto) {
- ret = request_module("nf_conntrack-%d", l3proto);
- if (!ret)
- goto retry;
-
- return -EPROTOTYPE;
- }
-
- return 0;
-}
-
-void nf_ct_l3proto_module_put(unsigned short l3proto)
-{
- struct nf_conntrack_l3proto *p;
-
- preempt_disable();
- p = __nf_ct_l3proto_find(l3proto);
- preempt_enable();
-
- module_put(p->me);
-}
-
static int nf_conntrack_hash_rnd_initted;
static unsigned int nf_conntrack_hash_rnd;
@@ -363,6 +220,7 @@ out_up_mutex:
mutex_unlock(&nf_ct_cache_mutex);
return ret;
}
+EXPORT_SYMBOL_GPL(nf_conntrack_register_cache);
/* FIXME: In the current, only nf_conntrack_cleanup() can call this function. */
void nf_conntrack_unregister_cache(u_int32_t features)
@@ -397,6 +255,7 @@ void nf_conntrack_unregister_cache(u_int32_t features)
mutex_unlock(&nf_ct_cache_mutex);
}
+EXPORT_SYMBOL_GPL(nf_conntrack_unregister_cache);
int
nf_ct_get_tuple(const struct sk_buff *skb,
@@ -406,7 +265,7 @@ nf_ct_get_tuple(const struct sk_buff *skb,
u_int8_t protonum,
struct nf_conntrack_tuple *tuple,
const struct nf_conntrack_l3proto *l3proto,
- const struct nf_conntrack_protocol *protocol)
+ const struct nf_conntrack_l4proto *l4proto)
{
NF_CT_TUPLE_U_BLANK(tuple);
@@ -417,14 +276,15 @@ nf_ct_get_tuple(const struct sk_buff *skb,
tuple->dst.protonum = protonum;
tuple->dst.dir = IP_CT_DIR_ORIGINAL;
- return protocol->pkt_to_tuple(skb, dataoff, tuple);
+ return l4proto->pkt_to_tuple(skb, dataoff, tuple);
}
+EXPORT_SYMBOL_GPL(nf_ct_get_tuple);
int
nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
const struct nf_conntrack_tuple *orig,
const struct nf_conntrack_l3proto *l3proto,
- const struct nf_conntrack_protocol *protocol)
+ const struct nf_conntrack_l4proto *l4proto)
{
NF_CT_TUPLE_U_BLANK(inverse);
@@ -435,111 +295,14 @@ nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
inverse->dst.dir = !orig->dst.dir;
inverse->dst.protonum = orig->dst.protonum;
- return protocol->invert_tuple(inverse, orig);
-}
-
-/* nf_conntrack_expect helper functions */
-void nf_ct_unlink_expect(struct nf_conntrack_expect *exp)
-{
- struct nf_conn_help *master_help = nfct_help(exp->master);
-
- NF_CT_ASSERT(master_help);
- ASSERT_WRITE_LOCK(&nf_conntrack_lock);
- NF_CT_ASSERT(!timer_pending(&exp->timeout));
-
- list_del(&exp->list);
- NF_CT_STAT_INC(expect_delete);
- master_help->expecting--;
- nf_conntrack_expect_put(exp);
-}
-
-static void expectation_timed_out(unsigned long ul_expect)
-{
- struct nf_conntrack_expect *exp = (void *)ul_expect;
-
- write_lock_bh(&nf_conntrack_lock);
- nf_ct_unlink_expect(exp);
- write_unlock_bh(&nf_conntrack_lock);
- nf_conntrack_expect_put(exp);
-}
-
-struct nf_conntrack_expect *
-__nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple)
-{
- struct nf_conntrack_expect *i;
-
- list_for_each_entry(i, &nf_conntrack_expect_list, list) {
- if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) {
- atomic_inc(&i->use);
- return i;
- }
- }
- return NULL;
-}
-
-/* Just find a expectation corresponding to a tuple. */
-struct nf_conntrack_expect *
-nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple)
-{
- struct nf_conntrack_expect *i;
-
- read_lock_bh(&nf_conntrack_lock);
- i = __nf_conntrack_expect_find(tuple);
- read_unlock_bh(&nf_conntrack_lock);
-
- return i;
-}
-
-/* If an expectation for this connection is found, it gets delete from
- * global list then returned. */
-static struct nf_conntrack_expect *
-find_expectation(const struct nf_conntrack_tuple *tuple)
-{
- struct nf_conntrack_expect *i;
-
- list_for_each_entry(i, &nf_conntrack_expect_list, list) {
- /* If master is not in hash table yet (ie. packet hasn't left
- this machine yet), how can other end know about expected?
- Hence these are not the droids you are looking for (if
- master ct never got confirmed, we'd hold a reference to it
- and weird things would happen to future packets). */
- if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)
- && nf_ct_is_confirmed(i->master)) {
- if (i->flags & NF_CT_EXPECT_PERMANENT) {
- atomic_inc(&i->use);
- return i;
- } else if (del_timer(&i->timeout)) {
- nf_ct_unlink_expect(i);
- return i;
- }
- }
- }
- return NULL;
-}
-
-/* delete all expectations for this conntrack */
-void nf_ct_remove_expectations(struct nf_conn *ct)
-{
- struct nf_conntrack_expect *i, *tmp;
- struct nf_conn_help *help = nfct_help(ct);
-
- /* Optimization: most connection never expect any others. */
- if (!help || help->expecting == 0)
- return;
-
- list_for_each_entry_safe(i, tmp, &nf_conntrack_expect_list, list) {
- if (i->master == ct && del_timer(&i->timeout)) {
- nf_ct_unlink_expect(i);
- nf_conntrack_expect_put(i);
- }
- }
+ return l4proto->invert_tuple(inverse, orig);
}
+EXPORT_SYMBOL_GPL(nf_ct_invert_tuple);
static void
clean_from_lists(struct nf_conn *ct)
{
DEBUGP("clean_from_lists(%p)\n", ct);
- ASSERT_WRITE_LOCK(&nf_conntrack_lock);
list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
list_del(&ct->tuplehash[IP_CT_DIR_REPLY].list);
@@ -551,8 +314,9 @@ static void
destroy_conntrack(struct nf_conntrack *nfct)
{
struct nf_conn *ct = (struct nf_conn *)nfct;
+ struct nf_conn_help *help = nfct_help(ct);
struct nf_conntrack_l3proto *l3proto;
- struct nf_conntrack_protocol *proto;
+ struct nf_conntrack_l4proto *l4proto;
DEBUGP("destroy_conntrack(%p)\n", ct);
NF_CT_ASSERT(atomic_read(&nfct->use) == 0);
@@ -561,6 +325,9 @@ destroy_conntrack(struct nf_conntrack *nfct)
nf_conntrack_event(IPCT_DESTROY, ct);
set_bit(IPS_DYING_BIT, &ct->status);
+ if (help && help->helper && help->helper->destroy)
+ help->helper->destroy(ct);
+
/* To make sure we don't get any weird locking issues here:
* destroy_conntrack() MUST NOT be called with a write lock
* to nf_conntrack_lock!!! -HW */
@@ -568,9 +335,9 @@ destroy_conntrack(struct nf_conntrack *nfct)
if (l3proto && l3proto->destroy)
l3proto->destroy(ct);
- proto = __nf_ct_proto_find(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.l3num, ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum);
- if (proto && proto->destroy)
- proto->destroy(ct);
+ l4proto = __nf_ct_l4proto_find(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.l3num, ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum);
+ if (l4proto && l4proto->destroy)
+ l4proto->destroy(ct);
if (nf_conntrack_destroyed)
nf_conntrack_destroyed(ct);
@@ -618,7 +385,6 @@ __nf_conntrack_find(const struct nf_conntrack_tuple *tuple,
struct nf_conntrack_tuple_hash *h;
unsigned int hash = hash_conntrack(tuple);
- ASSERT_READ_LOCK(&nf_conntrack_lock);
list_for_each_entry(h, &nf_conntrack_hash[hash], list) {
if (nf_ct_tuplehash_to_ctrack(h) != ignored_conntrack &&
nf_ct_tuple_equal(tuple, &h->tuple)) {
@@ -630,6 +396,7 @@ __nf_conntrack_find(const struct nf_conntrack_tuple *tuple,
return NULL;
}
+EXPORT_SYMBOL_GPL(__nf_conntrack_find);
/* Find a connection corresponding to a tuple. */
struct nf_conntrack_tuple_hash *
@@ -646,6 +413,7 @@ nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple,
return h;
}
+EXPORT_SYMBOL_GPL(nf_conntrack_find_get);
static void __nf_conntrack_hash_insert(struct nf_conn *ct,
unsigned int hash,
@@ -669,6 +437,7 @@ void nf_conntrack_hash_insert(struct nf_conn *ct)
__nf_conntrack_hash_insert(ct, hash, repl_hash);
write_unlock_bh(&nf_conntrack_lock);
}
+EXPORT_SYMBOL_GPL(nf_conntrack_hash_insert);
/* Confirm a connection given skb; places it in hash table */
int
@@ -746,6 +515,7 @@ out:
write_unlock_bh(&nf_conntrack_lock);
return NF_DROP;
}
+EXPORT_SYMBOL_GPL(__nf_conntrack_confirm);
/* Returns true if a connection correspondings to the tuple (required
for NAT). */
@@ -761,6 +531,7 @@ nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple,
return h != NULL;
}
+EXPORT_SYMBOL_GPL(nf_conntrack_tuple_taken);
/* There's a small race here where we may free a just-assured
connection. Too bad: we're in trouble anyway. */
@@ -794,53 +565,13 @@ static int early_drop(struct list_head *chain)
return dropped;
}
-static struct nf_conntrack_helper *
-__nf_ct_helper_find(const struct nf_conntrack_tuple *tuple)
-{
- struct nf_conntrack_helper *h;
-
- list_for_each_entry(h, &helpers, list) {
- if (nf_ct_tuple_mask_cmp(tuple, &h->tuple, &h->mask))
- return h;
- }
- return NULL;
-}
-
-struct nf_conntrack_helper *
-nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple)
-{
- struct nf_conntrack_helper *helper;
-
- /* need nf_conntrack_lock to assure that helper exists until
- * try_module_get() is called */
- read_lock_bh(&nf_conntrack_lock);
-
- helper = __nf_ct_helper_find(tuple);
- if (helper) {
- /* need to increase module usage count to assure helper will
- * not go away while the caller is e.g. busy putting a
- * conntrack in the hash that uses the helper */
- if (!try_module_get(helper->me))
- helper = NULL;
- }
-
- read_unlock_bh(&nf_conntrack_lock);
-
- return helper;
-}
-
-void nf_ct_helper_put(struct nf_conntrack_helper *helper)
-{
- module_put(helper->me);
-}
-
static struct nf_conn *
__nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
const struct nf_conntrack_tuple *repl,
- const struct nf_conntrack_l3proto *l3proto)
+ const struct nf_conntrack_l3proto *l3proto,
+ u_int32_t features)
{
struct nf_conn *conntrack = NULL;
- u_int32_t features = 0;
struct nf_conntrack_helper *helper;
if (unlikely(!nf_conntrack_hash_rnd_initted)) {
@@ -866,12 +597,13 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
}
/* find features needed by this conntrack. */
- features = l3proto->get_features(orig);
+ features |= l3proto->get_features(orig);
/* FIXME: protect helper list per RCU */
read_lock_bh(&nf_conntrack_lock);
helper = __nf_ct_helper_find(repl);
- if (helper)
+ /* NAT might want to assign a helper later */
+ if (helper || features & NF_CT_F_NAT)
features |= NF_CT_F_HELP;
read_unlock_bh(&nf_conntrack_lock);
@@ -893,12 +625,6 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
memset(conntrack, 0, nf_ct_cache[features].size);
conntrack->features = features;
- if (helper) {
- struct nf_conn_help *help = nfct_help(conntrack);
- NF_CT_ASSERT(help);
- help->helper = helper;
- }
-
atomic_set(&conntrack->ct_general.use, 1);
conntrack->ct_general.destroy = destroy_conntrack;
conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *orig;
@@ -922,8 +648,9 @@ struct nf_conn *nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
struct nf_conntrack_l3proto *l3proto;
l3proto = __nf_ct_l3proto_find(orig->src.l3num);
- return __nf_conntrack_alloc(orig, repl, l3proto);
+ return __nf_conntrack_alloc(orig, repl, l3proto, 0);
}
+EXPORT_SYMBOL_GPL(nf_conntrack_alloc);
void nf_conntrack_free(struct nf_conn *conntrack)
{
@@ -934,32 +661,40 @@ void nf_conntrack_free(struct nf_conn *conntrack)
kmem_cache_free(nf_ct_cache[features].cachep, conntrack);
atomic_dec(&nf_conntrack_count);
}
+EXPORT_SYMBOL_GPL(nf_conntrack_free);
/* Allocate a new conntrack: we return -ENOMEM if classification
failed due to stress. Otherwise it really is unclassifiable. */
static struct nf_conntrack_tuple_hash *
init_conntrack(const struct nf_conntrack_tuple *tuple,
struct nf_conntrack_l3proto *l3proto,
- struct nf_conntrack_protocol *protocol,
+ struct nf_conntrack_l4proto *l4proto,
struct sk_buff *skb,
unsigned int dataoff)
{
struct nf_conn *conntrack;
struct nf_conntrack_tuple repl_tuple;
struct nf_conntrack_expect *exp;
+ u_int32_t features = 0;
- if (!nf_ct_invert_tuple(&repl_tuple, tuple, l3proto, protocol)) {
+ if (!nf_ct_invert_tuple(&repl_tuple, tuple, l3proto, l4proto)) {
DEBUGP("Can't invert tuple.\n");
return NULL;
}
- conntrack = __nf_conntrack_alloc(tuple, &repl_tuple, l3proto);
+ read_lock_bh(&nf_conntrack_lock);
+ exp = __nf_conntrack_expect_find(tuple);
+ if (exp && exp->helper)
+ features = NF_CT_F_HELP;
+ read_unlock_bh(&nf_conntrack_lock);
+
+ conntrack = __nf_conntrack_alloc(tuple, &repl_tuple, l3proto, features);
if (conntrack == NULL || IS_ERR(conntrack)) {
DEBUGP("Can't allocate conntrack.\n");
return (struct nf_conntrack_tuple_hash *)conntrack;
}
- if (!protocol->new(conntrack, skb, dataoff)) {
+ if (!l4proto->new(conntrack, skb, dataoff)) {
nf_conntrack_free(conntrack);
DEBUGP("init conntrack: can't track with proto module\n");
return NULL;
@@ -974,6 +709,8 @@ init_conntrack(const struct nf_conntrack_tuple *tuple,
/* Welcome, Mr. Bond. We've been expecting you... */
__set_bit(IPS_EXPECTED_BIT, &conntrack->status);
conntrack->master = exp->master;
+ if (exp->helper)
+ nfct_help(conntrack)->helper = exp->helper;
#ifdef CONFIG_NF_CONNTRACK_MARK
conntrack->mark = exp->master->mark;
#endif
@@ -982,8 +719,13 @@ init_conntrack(const struct nf_conntrack_tuple *tuple,
#endif
nf_conntrack_get(&conntrack->master->ct_general);
NF_CT_STAT_INC(expect_new);
- } else
+ } else {
+ struct nf_conn_help *help = nfct_help(conntrack);
+
+ if (help)
+ help->helper = __nf_ct_helper_find(&repl_tuple);
NF_CT_STAT_INC(new);
+ }
/* Overload tuple linked list to put us in unconfirmed list. */
list_add(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL].list, &unconfirmed);
@@ -1006,7 +748,7 @@ resolve_normal_ct(struct sk_buff *skb,
u_int16_t l3num,
u_int8_t protonum,
struct nf_conntrack_l3proto *l3proto,
- struct nf_conntrack_protocol *proto,
+ struct nf_conntrack_l4proto *l4proto,
int *set_reply,
enum ip_conntrack_info *ctinfo)
{
@@ -1016,7 +758,7 @@ resolve_normal_ct(struct sk_buff *skb,
if (!nf_ct_get_tuple(skb, (unsigned int)(skb->nh.raw - skb->data),
dataoff, l3num, protonum, &tuple, l3proto,
- proto)) {
+ l4proto)) {
DEBUGP("resolve_normal_ct: Can't get tuple\n");
return NULL;
}
@@ -1024,7 +766,7 @@ resolve_normal_ct(struct sk_buff *skb,
/* look for tuple match */
h = nf_conntrack_find_get(&tuple, NULL);
if (!h) {
- h = init_conntrack(&tuple, l3proto, proto, skb, dataoff);
+ h = init_conntrack(&tuple, l3proto, l4proto, skb, dataoff);
if (!h)
return NULL;
if (IS_ERR(h))
@@ -1062,7 +804,7 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb)
struct nf_conn *ct;
enum ip_conntrack_info ctinfo;
struct nf_conntrack_l3proto *l3proto;
- struct nf_conntrack_protocol *proto;
+ struct nf_conntrack_l4proto *l4proto;
unsigned int dataoff;
u_int8_t protonum;
int set_reply = 0;
@@ -1080,19 +822,19 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb)
return -ret;
}
- proto = __nf_ct_proto_find((u_int16_t)pf, protonum);
+ l4proto = __nf_ct_l4proto_find((u_int16_t)pf, protonum);
/* It may be an special packet, error, unclean...
* inverse of the return code tells to the netfilter
* core what to do with the packet. */
- if (proto->error != NULL &&
- (ret = proto->error(*pskb, dataoff, &ctinfo, pf, hooknum)) <= 0) {
+ if (l4proto->error != NULL &&
+ (ret = l4proto->error(*pskb, dataoff, &ctinfo, pf, hooknum)) <= 0) {
NF_CT_STAT_INC(error);
NF_CT_STAT_INC(invalid);
return -ret;
}
- ct = resolve_normal_ct(*pskb, dataoff, pf, protonum, l3proto, proto,
+ ct = resolve_normal_ct(*pskb, dataoff, pf, protonum, l3proto, l4proto,
&set_reply, &ctinfo);
if (!ct) {
/* Not valid part of a connection */
@@ -1108,7 +850,7 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb)
NF_CT_ASSERT((*pskb)->nfct);
- ret = proto->packet(ct, *pskb, dataoff, ctinfo, pf, hooknum);
+ ret = l4proto->packet(ct, *pskb, dataoff, ctinfo, pf, hooknum);
if (ret < 0) {
/* Invalid: inverse of the return code tells
* the netfilter core what to do */
@@ -1124,255 +866,38 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb)
return ret;
}
+EXPORT_SYMBOL_GPL(nf_conntrack_in);
int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,
const struct nf_conntrack_tuple *orig)
{
return nf_ct_invert_tuple(inverse, orig,
__nf_ct_l3proto_find(orig->src.l3num),
- __nf_ct_proto_find(orig->src.l3num,
+ __nf_ct_l4proto_find(orig->src.l3num,
orig->dst.protonum));
}
+EXPORT_SYMBOL_GPL(nf_ct_invert_tuplepr);
-/* Would two expected things clash? */
-static inline int expect_clash(const struct nf_conntrack_expect *a,
- const struct nf_conntrack_expect *b)
-{
- /* Part covered by intersection of masks must be unequal,
- otherwise they clash */
- struct nf_conntrack_tuple intersect_mask;
- int count;
-
- intersect_mask.src.l3num = a->mask.src.l3num & b->mask.src.l3num;
- intersect_mask.src.u.all = a->mask.src.u.all & b->mask.src.u.all;
- intersect_mask.dst.u.all = a->mask.dst.u.all & b->mask.dst.u.all;
- intersect_mask.dst.protonum = a->mask.dst.protonum
- & b->mask.dst.protonum;
-
- for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++){
- intersect_mask.src.u3.all[count] =
- a->mask.src.u3.all[count] & b->mask.src.u3.all[count];
- }
-
- for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++){
- intersect_mask.dst.u3.all[count] =
- a->mask.dst.u3.all[count] & b->mask.dst.u3.all[count];
- }
-
- return nf_ct_tuple_mask_cmp(&a->tuple, &b->tuple, &intersect_mask);
-}
-
-static inline int expect_matches(const struct nf_conntrack_expect *a,
- const struct nf_conntrack_expect *b)
-{
- return a->master == b->master
- && nf_ct_tuple_equal(&a->tuple, &b->tuple)
- && nf_ct_tuple_equal(&a->mask, &b->mask);
-}
-
-/* Generally a bad idea to call this: could have matched already. */
-void nf_conntrack_unexpect_related(struct nf_conntrack_expect *exp)
-{
- struct nf_conntrack_expect *i;
-
- write_lock_bh(&nf_conntrack_lock);
- /* choose the the oldest expectation to evict */
- list_for_each_entry_reverse(i, &nf_conntrack_expect_list, list) {
- if (expect_matches(i, exp) && del_timer(&i->timeout)) {
- nf_ct_unlink_expect(i);
- write_unlock_bh(&nf_conntrack_lock);
- nf_conntrack_expect_put(i);
- return;
- }
- }
- write_unlock_bh(&nf_conntrack_lock);
-}
-
-/* We don't increase the master conntrack refcount for non-fulfilled
- * conntracks. During the conntrack destruction, the expectations are
- * always killed before the conntrack itself */
-struct nf_conntrack_expect *nf_conntrack_expect_alloc(struct nf_conn *me)
-{
- struct nf_conntrack_expect *new;
-
- new = kmem_cache_alloc(nf_conntrack_expect_cachep, GFP_ATOMIC);
- if (!new) {
- DEBUGP("expect_related: OOM allocating expect\n");
- return NULL;
- }
- new->master = me;
- atomic_set(&new->use, 1);
- return new;
-}
-
-void nf_conntrack_expect_put(struct nf_conntrack_expect *exp)
-{
- if (atomic_dec_and_test(&exp->use))
- kmem_cache_free(nf_conntrack_expect_cachep, exp);
-}
-
-static void nf_conntrack_expect_insert(struct nf_conntrack_expect *exp)
-{
- struct nf_conn_help *master_help = nfct_help(exp->master);
-
- atomic_inc(&exp->use);
- master_help->expecting++;
- list_add(&exp->list, &nf_conntrack_expect_list);
-
- init_timer(&exp->timeout);
- exp->timeout.data = (unsigned long)exp;
- exp->timeout.function = expectation_timed_out;
- exp->timeout.expires = jiffies + master_help->helper->timeout * HZ;
- add_timer(&exp->timeout);
-
- exp->id = ++nf_conntrack_expect_next_id;
- atomic_inc(&exp->use);
- NF_CT_STAT_INC(expect_create);
-}
-
-/* Race with expectations being used means we could have none to find; OK. */
-static void evict_oldest_expect(struct nf_conn *master)
-{
- struct nf_conntrack_expect *i;
-
- list_for_each_entry_reverse(i, &nf_conntrack_expect_list, list) {
- if (i->master == master) {
- if (del_timer(&i->timeout)) {
- nf_ct_unlink_expect(i);
- nf_conntrack_expect_put(i);
- }
- break;
- }
- }
-}
-
-static inline int refresh_timer(struct nf_conntrack_expect *i)
-{
- struct nf_conn_help *master_help = nfct_help(i->master);
-
- if (!del_timer(&i->timeout))
- return 0;
-
- i->timeout.expires = jiffies + master_help->helper->timeout*HZ;
- add_timer(&i->timeout);
- return 1;
-}
-
-int nf_conntrack_expect_related(struct nf_conntrack_expect *expect)
+/* Alter reply tuple (maybe alter helper). This is for NAT, and is
+ implicitly racy: see __nf_conntrack_confirm */
+void nf_conntrack_alter_reply(struct nf_conn *ct,
+ const struct nf_conntrack_tuple *newreply)
{
- struct nf_conntrack_expect *i;
- struct nf_conn *master = expect->master;
- struct nf_conn_help *master_help = nfct_help(master);
- int ret;
-
- NF_CT_ASSERT(master_help);
-
- DEBUGP("nf_conntrack_expect_related %p\n", related_to);
- DEBUGP("tuple: "); NF_CT_DUMP_TUPLE(&expect->tuple);
- DEBUGP("mask: "); NF_CT_DUMP_TUPLE(&expect->mask);
-
- write_lock_bh(&nf_conntrack_lock);
- list_for_each_entry(i, &nf_conntrack_expect_list, list) {
- if (expect_matches(i, expect)) {
- /* Refresh timer: if it's dying, ignore.. */
- if (refresh_timer(i)) {
- ret = 0;
- goto out;
- }
- } else if (expect_clash(i, expect)) {
- ret = -EBUSY;
- goto out;
- }
- }
- /* Will be over limit? */
- if (master_help->helper->max_expected &&
- master_help->expecting >= master_help->helper->max_expected)
- evict_oldest_expect(master);
-
- nf_conntrack_expect_insert(expect);
- nf_conntrack_expect_event(IPEXP_NEW, expect);
- ret = 0;
-out:
- write_unlock_bh(&nf_conntrack_lock);
- return ret;
-}
-
-int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
-{
- int ret;
- BUG_ON(me->timeout == 0);
-
- ret = nf_conntrack_register_cache(NF_CT_F_HELP, "nf_conntrack:help",
- sizeof(struct nf_conn)
- + sizeof(struct nf_conn_help)
- + __alignof__(struct nf_conn_help));
- if (ret < 0) {
- printk(KERN_ERR "nf_conntrack_helper_reigster: Unable to create slab cache for conntracks\n");
- return ret;
- }
- write_lock_bh(&nf_conntrack_lock);
- list_add(&me->list, &helpers);
- write_unlock_bh(&nf_conntrack_lock);
-
- return 0;
-}
-
-struct nf_conntrack_helper *
-__nf_conntrack_helper_find_byname(const char *name)
-{
- struct nf_conntrack_helper *h;
-
- list_for_each_entry(h, &helpers, list) {
- if (!strcmp(h->name, name))
- return h;
- }
-
- return NULL;
-}
-
-static inline void unhelp(struct nf_conntrack_tuple_hash *i,
- const struct nf_conntrack_helper *me)
-{
- struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(i);
struct nf_conn_help *help = nfct_help(ct);
- if (help && help->helper == me) {
- nf_conntrack_event(IPCT_HELPER, ct);
- help->helper = NULL;
- }
-}
-
-void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me)
-{
- unsigned int i;
- struct nf_conntrack_tuple_hash *h;
- struct nf_conntrack_expect *exp, *tmp;
-
- /* Need write lock here, to delete helper. */
write_lock_bh(&nf_conntrack_lock);
- list_del(&me->list);
-
- /* Get rid of expectations */
- list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, list) {
- struct nf_conn_help *help = nfct_help(exp->master);
- if (help->helper == me && del_timer(&exp->timeout)) {
- nf_ct_unlink_expect(exp);
- nf_conntrack_expect_put(exp);
- }
- }
+ /* Should be unconfirmed, so not in hash table yet */
+ NF_CT_ASSERT(!nf_ct_is_confirmed(ct));
- /* Get rid of expecteds, set helpers to NULL. */
- list_for_each_entry(h, &unconfirmed, list)
- unhelp(h, me);
- for (i = 0; i < nf_conntrack_htable_size; i++) {
- list_for_each_entry(h, &nf_conntrack_hash[i], list)
- unhelp(h, me);
- }
- write_unlock_bh(&nf_conntrack_lock);
+ DEBUGP("Altering reply tuple of %p to ", ct);
+ NF_CT_DUMP_TUPLE(newreply);
- /* Someone could be still looking at the helper in a bh. */
- synchronize_net();
+ ct->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply;
+ if (!ct->master && help && help->expecting == 0)
+ help->helper = __nf_ct_helper_find(newreply);
+ write_unlock_bh(&nf_conntrack_lock);
}
+EXPORT_SYMBOL_GPL(nf_conntrack_alter_reply);
/* Refresh conntrack for this many jiffies and do accounting if do_acct is 1 */
void __nf_ct_refresh_acct(struct nf_conn *ct,
@@ -1399,9 +924,14 @@ void __nf_ct_refresh_acct(struct nf_conn *ct,
ct->timeout.expires = extra_jiffies;
event = IPCT_REFRESH;
} else {
- /* Need del_timer for race avoidance (may already be dying). */
- if (del_timer(&ct->timeout)) {
- ct->timeout.expires = jiffies + extra_jiffies;
+ unsigned long newtime = jiffies + extra_jiffies;
+
+ /* Only update the timeout if the new timeout is at least
+ HZ jiffies from the old timeout. Need del_timer for race
+ avoidance (may already be dying). */
+ if (newtime - ct->timeout.expires >= HZ
+ && del_timer(&ct->timeout)) {
+ ct->timeout.expires = newtime;
add_timer(&ct->timeout);
event = IPCT_REFRESH;
}
@@ -1412,9 +942,10 @@ void __nf_ct_refresh_acct(struct nf_conn *ct,
ct->counters[CTINFO2DIR(ctinfo)].packets++;
ct->counters[CTINFO2DIR(ctinfo)].bytes +=
skb->len - (unsigned int)(skb->nh.raw - skb->data);
- if ((ct->counters[CTINFO2DIR(ctinfo)].packets & 0x80000000)
- || (ct->counters[CTINFO2DIR(ctinfo)].bytes & 0x80000000))
- event |= IPCT_COUNTER_FILLING;
+
+ if ((ct->counters[CTINFO2DIR(ctinfo)].packets & 0x80000000)
+ || (ct->counters[CTINFO2DIR(ctinfo)].bytes & 0x80000000))
+ event |= IPCT_COUNTER_FILLING;
}
#endif
@@ -1424,6 +955,7 @@ void __nf_ct_refresh_acct(struct nf_conn *ct,
if (event)
nf_conntrack_event_cache(event, skb);
}
+EXPORT_SYMBOL_GPL(__nf_ct_refresh_acct);
#if defined(CONFIG_NF_CT_NETLINK) || \
defined(CONFIG_NF_CT_NETLINK_MODULE)
@@ -1448,6 +980,7 @@ int nf_ct_port_tuple_to_nfattr(struct sk_buff *skb,
nfattr_failure:
return -1;
}
+EXPORT_SYMBOL_GPL(nf_ct_port_tuple_to_nfattr);
static const size_t cta_min_proto[CTA_PROTO_MAX] = {
[CTA_PROTO_SRC_PORT-1] = sizeof(u_int16_t),
@@ -1463,13 +996,12 @@ int nf_ct_port_nfattr_to_tuple(struct nfattr *tb[],
if (nfattr_bad_size(tb, CTA_PROTO_MAX, cta_min_proto))
return -EINVAL;
- t->src.u.tcp.port =
- *(u_int16_t *)NFA_DATA(tb[CTA_PROTO_SRC_PORT-1]);
- t->dst.u.tcp.port =
- *(u_int16_t *)NFA_DATA(tb[CTA_PROTO_DST_PORT-1]);
+ t->src.u.tcp.port = *(__be16 *)NFA_DATA(tb[CTA_PROTO_SRC_PORT-1]);
+ t->dst.u.tcp.port = *(__be16 *)NFA_DATA(tb[CTA_PROTO_DST_PORT-1]);
return 0;
}
+EXPORT_SYMBOL_GPL(nf_ct_port_nfattr_to_tuple);
#endif
/* Used by ipt_REJECT and ip6t_REJECT. */
@@ -1490,6 +1022,7 @@ void __nf_conntrack_attach(struct sk_buff *nskb, struct sk_buff *skb)
nskb->nfctinfo = ctinfo;
nf_conntrack_get(nskb->nfct);
}
+EXPORT_SYMBOL_GPL(__nf_conntrack_attach);
static inline int
do_iter(const struct nf_conntrack_tuple_hash *i,
@@ -1543,6 +1076,7 @@ nf_ct_iterate_cleanup(int (*iter)(struct nf_conn *i, void *data), void *data)
nf_ct_put(ct);
}
}
+EXPORT_SYMBOL_GPL(nf_ct_iterate_cleanup);
static int kill_all(struct nf_conn *i, void *data)
{
@@ -1562,6 +1096,7 @@ void nf_conntrack_flush()
{
nf_ct_iterate_cleanup(kill_all, NULL);
}
+EXPORT_SYMBOL_GPL(nf_conntrack_flush);
/* Mishearing the voices in his head, our hero wonders how he's
supposed to kill the mall. */
@@ -1599,6 +1134,8 @@ void nf_conntrack_cleanup(void)
free_conntrack_hash(nf_conntrack_hash, nf_conntrack_vmalloc,
nf_conntrack_htable_size);
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_generic);
+
/* free l3proto protocol tables */
for (i = 0; i < PF_MAX; i++)
if (nf_ct_protos[i]) {
@@ -1724,10 +1261,14 @@ int __init nf_conntrack_init(void)
goto err_free_conntrack_slab;
}
+ ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_generic);
+ if (ret < 0)
+ goto out_free_expect_slab;
+
/* Don't NEED lock here, but good form anyway. */
write_lock_bh(&nf_conntrack_lock);
- for (i = 0; i < PF_MAX; i++)
- nf_ct_l3protos[i] = &nf_conntrack_generic_l3proto;
+ for (i = 0; i < AF_MAX; i++)
+ nf_ct_l3protos[i] = &nf_conntrack_l3proto_generic;
write_unlock_bh(&nf_conntrack_lock);
/* For use by REJECT target */
@@ -1741,6 +1282,8 @@ int __init nf_conntrack_init(void)
return ret;
+out_free_expect_slab:
+ kmem_cache_destroy(nf_conntrack_expect_cachep);
err_free_conntrack_slab:
nf_conntrack_unregister_cache(NF_CT_F_BASIC);
err_free_hash:
diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c
new file mode 100644
index 000000000000..1a223e0c0856
--- /dev/null
+++ b/net/netfilter/nf_conntrack_ecache.c
@@ -0,0 +1,93 @@
+/* Event cache for netfilter. */
+
+/* (C) 1999-2001 Paul `Rusty' Russell
+ * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
+ * (C) 2003,2004 USAGI/WIDE Project <http://www.linux-ipv6.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/types.h>
+#include <linux/netfilter.h>
+#include <linux/skbuff.h>
+#include <linux/vmalloc.h>
+#include <linux/stddef.h>
+#include <linux/err.h>
+#include <linux/percpu.h>
+#include <linux/notifier.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_core.h>
+
+ATOMIC_NOTIFIER_HEAD(nf_conntrack_chain);
+EXPORT_SYMBOL_GPL(nf_conntrack_chain);
+
+ATOMIC_NOTIFIER_HEAD(nf_conntrack_expect_chain);
+EXPORT_SYMBOL_GPL(nf_conntrack_expect_chain);
+
+DEFINE_PER_CPU(struct nf_conntrack_ecache, nf_conntrack_ecache);
+EXPORT_PER_CPU_SYMBOL_GPL(nf_conntrack_ecache);
+
+/* deliver cached events and clear cache entry - must be called with locally
+ * disabled softirqs */
+static inline void
+__nf_ct_deliver_cached_events(struct nf_conntrack_ecache *ecache)
+{
+ if (nf_ct_is_confirmed(ecache->ct) && !nf_ct_is_dying(ecache->ct)
+ && ecache->events)
+ atomic_notifier_call_chain(&nf_conntrack_chain, ecache->events,
+ ecache->ct);
+
+ ecache->events = 0;
+ nf_ct_put(ecache->ct);
+ ecache->ct = NULL;
+}
+
+/* Deliver all cached events for a particular conntrack. This is called
+ * by code prior to async packet handling for freeing the skb */
+void nf_ct_deliver_cached_events(const struct nf_conn *ct)
+{
+ struct nf_conntrack_ecache *ecache;
+
+ local_bh_disable();
+ ecache = &__get_cpu_var(nf_conntrack_ecache);
+ if (ecache->ct == ct)
+ __nf_ct_deliver_cached_events(ecache);
+ local_bh_enable();
+}
+EXPORT_SYMBOL_GPL(nf_ct_deliver_cached_events);
+
+/* Deliver cached events for old pending events, if current conntrack != old */
+void __nf_ct_event_cache_init(struct nf_conn *ct)
+{
+ struct nf_conntrack_ecache *ecache;
+
+ /* take care of delivering potentially old events */
+ ecache = &__get_cpu_var(nf_conntrack_ecache);
+ BUG_ON(ecache->ct == ct);
+ if (ecache->ct)
+ __nf_ct_deliver_cached_events(ecache);
+ /* initialize for this conntrack/packet */
+ ecache->ct = ct;
+ nf_conntrack_get(&ct->ct_general);
+}
+EXPORT_SYMBOL_GPL(__nf_ct_event_cache_init);
+
+/* flush the event cache - touches other CPU's data and must not be called
+ * while packets are still passing through the code */
+void nf_ct_event_cache_flush(void)
+{
+ struct nf_conntrack_ecache *ecache;
+ int cpu;
+
+ for_each_possible_cpu(cpu) {
+ ecache = &per_cpu(nf_conntrack_ecache, cpu);
+ if (ecache->ct)
+ nf_ct_put(ecache->ct);
+ }
+}
+
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
new file mode 100644
index 000000000000..588d37937046
--- /dev/null
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -0,0 +1,442 @@
+/* Expectation handling for nf_conntrack. */
+
+/* (C) 1999-2001 Paul `Rusty' Russell
+ * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
+ * (C) 2003,2004 USAGI/WIDE Project <http://www.linux-ipv6.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/types.h>
+#include <linux/netfilter.h>
+#include <linux/skbuff.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/stddef.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/percpu.h>
+#include <linux/kernel.h>
+
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_core.h>
+#include <net/netfilter/nf_conntrack_expect.h>
+#include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_conntrack_tuple.h>
+
+LIST_HEAD(nf_conntrack_expect_list);
+EXPORT_SYMBOL_GPL(nf_conntrack_expect_list);
+
+kmem_cache_t *nf_conntrack_expect_cachep __read_mostly;
+static unsigned int nf_conntrack_expect_next_id;
+
+/* nf_conntrack_expect helper functions */
+void nf_ct_unlink_expect(struct nf_conntrack_expect *exp)
+{
+ struct nf_conn_help *master_help = nfct_help(exp->master);
+
+ NF_CT_ASSERT(master_help);
+ NF_CT_ASSERT(!timer_pending(&exp->timeout));
+
+ list_del(&exp->list);
+ NF_CT_STAT_INC(expect_delete);
+ master_help->expecting--;
+ nf_conntrack_expect_put(exp);
+}
+EXPORT_SYMBOL_GPL(nf_ct_unlink_expect);
+
+static void expectation_timed_out(unsigned long ul_expect)
+{
+ struct nf_conntrack_expect *exp = (void *)ul_expect;
+
+ write_lock_bh(&nf_conntrack_lock);
+ nf_ct_unlink_expect(exp);
+ write_unlock_bh(&nf_conntrack_lock);
+ nf_conntrack_expect_put(exp);
+}
+
+struct nf_conntrack_expect *
+__nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple)
+{
+ struct nf_conntrack_expect *i;
+
+ list_for_each_entry(i, &nf_conntrack_expect_list, list) {
+ if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask))
+ return i;
+ }
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(__nf_conntrack_expect_find);
+
+/* Just find a expectation corresponding to a tuple. */
+struct nf_conntrack_expect *
+nf_conntrack_expect_find_get(const struct nf_conntrack_tuple *tuple)
+{
+ struct nf_conntrack_expect *i;
+
+ read_lock_bh(&nf_conntrack_lock);
+ i = __nf_conntrack_expect_find(tuple);
+ if (i)
+ atomic_inc(&i->use);
+ read_unlock_bh(&nf_conntrack_lock);
+
+ return i;
+}
+EXPORT_SYMBOL_GPL(nf_conntrack_expect_find_get);
+
+/* If an expectation for this connection is found, it gets delete from
+ * global list then returned. */
+struct nf_conntrack_expect *
+find_expectation(const struct nf_conntrack_tuple *tuple)
+{
+ struct nf_conntrack_expect *i;
+
+ list_for_each_entry(i, &nf_conntrack_expect_list, list) {
+ /* If master is not in hash table yet (ie. packet hasn't left
+ this machine yet), how can other end know about expected?
+ Hence these are not the droids you are looking for (if
+ master ct never got confirmed, we'd hold a reference to it
+ and weird things would happen to future packets). */
+ if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)
+ && nf_ct_is_confirmed(i->master)) {
+ if (i->flags & NF_CT_EXPECT_PERMANENT) {
+ atomic_inc(&i->use);
+ return i;
+ } else if (del_timer(&i->timeout)) {
+ nf_ct_unlink_expect(i);
+ return i;
+ }
+ }
+ }
+ return NULL;
+}
+
+/* delete all expectations for this conntrack */
+void nf_ct_remove_expectations(struct nf_conn *ct)
+{
+ struct nf_conntrack_expect *i, *tmp;
+ struct nf_conn_help *help = nfct_help(ct);
+
+ /* Optimization: most connection never expect any others. */
+ if (!help || help->expecting == 0)
+ return;
+
+ list_for_each_entry_safe(i, tmp, &nf_conntrack_expect_list, list) {
+ if (i->master == ct && del_timer(&i->timeout)) {
+ nf_ct_unlink_expect(i);
+ nf_conntrack_expect_put(i);
+ }
+ }
+}
+EXPORT_SYMBOL_GPL(nf_ct_remove_expectations);
+
+/* Would two expected things clash? */
+static inline int expect_clash(const struct nf_conntrack_expect *a,
+ const struct nf_conntrack_expect *b)
+{
+ /* Part covered by intersection of masks must be unequal,
+ otherwise they clash */
+ struct nf_conntrack_tuple intersect_mask;
+ int count;
+
+ intersect_mask.src.l3num = a->mask.src.l3num & b->mask.src.l3num;
+ intersect_mask.src.u.all = a->mask.src.u.all & b->mask.src.u.all;
+ intersect_mask.dst.u.all = a->mask.dst.u.all & b->mask.dst.u.all;
+ intersect_mask.dst.protonum = a->mask.dst.protonum
+ & b->mask.dst.protonum;
+
+ for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++){
+ intersect_mask.src.u3.all[count] =
+ a->mask.src.u3.all[count] & b->mask.src.u3.all[count];
+ }
+
+ for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++){
+ intersect_mask.dst.u3.all[count] =
+ a->mask.dst.u3.all[count] & b->mask.dst.u3.all[count];
+ }
+
+ return nf_ct_tuple_mask_cmp(&a->tuple, &b->tuple, &intersect_mask);
+}
+
+static inline int expect_matches(const struct nf_conntrack_expect *a,
+ const struct nf_conntrack_expect *b)
+{
+ return a->master == b->master
+ && nf_ct_tuple_equal(&a->tuple, &b->tuple)
+ && nf_ct_tuple_equal(&a->mask, &b->mask);
+}
+
+/* Generally a bad idea to call this: could have matched already. */
+void nf_conntrack_unexpect_related(struct nf_conntrack_expect *exp)
+{
+ struct nf_conntrack_expect *i;
+
+ write_lock_bh(&nf_conntrack_lock);
+ /* choose the the oldest expectation to evict */
+ list_for_each_entry_reverse(i, &nf_conntrack_expect_list, list) {
+ if (expect_matches(i, exp) && del_timer(&i->timeout)) {
+ nf_ct_unlink_expect(i);
+ write_unlock_bh(&nf_conntrack_lock);
+ nf_conntrack_expect_put(i);
+ return;
+ }
+ }
+ write_unlock_bh(&nf_conntrack_lock);
+}
+EXPORT_SYMBOL_GPL(nf_conntrack_unexpect_related);
+
+/* We don't increase the master conntrack refcount for non-fulfilled
+ * conntracks. During the conntrack destruction, the expectations are
+ * always killed before the conntrack itself */
+struct nf_conntrack_expect *nf_conntrack_expect_alloc(struct nf_conn *me)
+{
+ struct nf_conntrack_expect *new;
+
+ new = kmem_cache_alloc(nf_conntrack_expect_cachep, GFP_ATOMIC);
+ if (!new)
+ return NULL;
+
+ new->master = me;
+ atomic_set(&new->use, 1);
+ return new;
+}
+EXPORT_SYMBOL_GPL(nf_conntrack_expect_alloc);
+
+void nf_conntrack_expect_init(struct nf_conntrack_expect *exp, int family,
+ union nf_conntrack_address *saddr,
+ union nf_conntrack_address *daddr,
+ u_int8_t proto, __be16 *src, __be16 *dst)
+{
+ int len;
+
+ if (family == AF_INET)
+ len = 4;
+ else
+ len = 16;
+
+ exp->flags = 0;
+ exp->expectfn = NULL;
+ exp->helper = NULL;
+ exp->tuple.src.l3num = family;
+ exp->tuple.dst.protonum = proto;
+ exp->mask.src.l3num = 0xFFFF;
+ exp->mask.dst.protonum = 0xFF;
+
+ if (saddr) {
+ memcpy(&exp->tuple.src.u3, saddr, len);
+ if (sizeof(exp->tuple.src.u3) > len)
+ /* address needs to be cleared for nf_ct_tuple_equal */
+ memset((void *)&exp->tuple.src.u3 + len, 0x00,
+ sizeof(exp->tuple.src.u3) - len);
+ memset(&exp->mask.src.u3, 0xFF, len);
+ if (sizeof(exp->mask.src.u3) > len)
+ memset((void *)&exp->mask.src.u3 + len, 0x00,
+ sizeof(exp->mask.src.u3) - len);
+ } else {
+ memset(&exp->tuple.src.u3, 0x00, sizeof(exp->tuple.src.u3));
+ memset(&exp->mask.src.u3, 0x00, sizeof(exp->mask.src.u3));
+ }
+
+ if (daddr) {
+ memcpy(&exp->tuple.dst.u3, daddr, len);
+ if (sizeof(exp->tuple.dst.u3) > len)
+ /* address needs to be cleared for nf_ct_tuple_equal */
+ memset((void *)&exp->tuple.dst.u3 + len, 0x00,
+ sizeof(exp->tuple.dst.u3) - len);
+ memset(&exp->mask.dst.u3, 0xFF, len);
+ if (sizeof(exp->mask.dst.u3) > len)
+ memset((void *)&exp->mask.dst.u3 + len, 0x00,
+ sizeof(exp->mask.dst.u3) - len);
+ } else {
+ memset(&exp->tuple.dst.u3, 0x00, sizeof(exp->tuple.dst.u3));
+ memset(&exp->mask.dst.u3, 0x00, sizeof(exp->mask.dst.u3));
+ }
+
+ if (src) {
+ exp->tuple.src.u.all = (__force u16)*src;
+ exp->mask.src.u.all = 0xFFFF;
+ } else {
+ exp->tuple.src.u.all = 0;
+ exp->mask.src.u.all = 0;
+ }
+
+ if (dst) {
+ exp->tuple.dst.u.all = (__force u16)*dst;
+ exp->mask.dst.u.all = 0xFFFF;
+ } else {
+ exp->tuple.dst.u.all = 0;
+ exp->mask.dst.u.all = 0;
+ }
+}
+EXPORT_SYMBOL_GPL(nf_conntrack_expect_init);
+
+void nf_conntrack_expect_put(struct nf_conntrack_expect *exp)
+{
+ if (atomic_dec_and_test(&exp->use))
+ kmem_cache_free(nf_conntrack_expect_cachep, exp);
+}
+EXPORT_SYMBOL_GPL(nf_conntrack_expect_put);
+
+static void nf_conntrack_expect_insert(struct nf_conntrack_expect *exp)
+{
+ struct nf_conn_help *master_help = nfct_help(exp->master);
+
+ atomic_inc(&exp->use);
+ master_help->expecting++;
+ list_add(&exp->list, &nf_conntrack_expect_list);
+
+ init_timer(&exp->timeout);
+ exp->timeout.data = (unsigned long)exp;
+ exp->timeout.function = expectation_timed_out;
+ exp->timeout.expires = jiffies + master_help->helper->timeout * HZ;
+ add_timer(&exp->timeout);
+
+ exp->id = ++nf_conntrack_expect_next_id;
+ atomic_inc(&exp->use);
+ NF_CT_STAT_INC(expect_create);
+}
+
+/* Race with expectations being used means we could have none to find; OK. */
+static void evict_oldest_expect(struct nf_conn *master)
+{
+ struct nf_conntrack_expect *i;
+
+ list_for_each_entry_reverse(i, &nf_conntrack_expect_list, list) {
+ if (i->master == master) {
+ if (del_timer(&i->timeout)) {
+ nf_ct_unlink_expect(i);
+ nf_conntrack_expect_put(i);
+ }
+ break;
+ }
+ }
+}
+
+static inline int refresh_timer(struct nf_conntrack_expect *i)
+{
+ struct nf_conn_help *master_help = nfct_help(i->master);
+
+ if (!del_timer(&i->timeout))
+ return 0;
+
+ i->timeout.expires = jiffies + master_help->helper->timeout*HZ;
+ add_timer(&i->timeout);
+ return 1;
+}
+
+int nf_conntrack_expect_related(struct nf_conntrack_expect *expect)
+{
+ struct nf_conntrack_expect *i;
+ struct nf_conn *master = expect->master;
+ struct nf_conn_help *master_help = nfct_help(master);
+ int ret;
+
+ NF_CT_ASSERT(master_help);
+
+ write_lock_bh(&nf_conntrack_lock);
+ list_for_each_entry(i, &nf_conntrack_expect_list, list) {
+ if (expect_matches(i, expect)) {
+ /* Refresh timer: if it's dying, ignore.. */
+ if (refresh_timer(i)) {
+ ret = 0;
+ goto out;
+ }
+ } else if (expect_clash(i, expect)) {
+ ret = -EBUSY;
+ goto out;
+ }
+ }
+ /* Will be over limit? */
+ if (master_help->helper->max_expected &&
+ master_help->expecting >= master_help->helper->max_expected)
+ evict_oldest_expect(master);
+
+ nf_conntrack_expect_insert(expect);
+ nf_conntrack_expect_event(IPEXP_NEW, expect);
+ ret = 0;
+out:
+ write_unlock_bh(&nf_conntrack_lock);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(nf_conntrack_expect_related);
+
+#ifdef CONFIG_PROC_FS
+static void *exp_seq_start(struct seq_file *s, loff_t *pos)
+{
+ struct list_head *e = &nf_conntrack_expect_list;
+ loff_t i;
+
+ /* strange seq_file api calls stop even if we fail,
+ * thus we need to grab lock since stop unlocks */
+ read_lock_bh(&nf_conntrack_lock);
+
+ if (list_empty(e))
+ return NULL;
+
+ for (i = 0; i <= *pos; i++) {
+ e = e->next;
+ if (e == &nf_conntrack_expect_list)
+ return NULL;
+ }
+ return e;
+}
+
+static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ struct list_head *e = v;
+
+ ++*pos;
+ e = e->next;
+
+ if (e == &nf_conntrack_expect_list)
+ return NULL;
+
+ return e;
+}
+
+static void exp_seq_stop(struct seq_file *s, void *v)
+{
+ read_unlock_bh(&nf_conntrack_lock);
+}
+
+static int exp_seq_show(struct seq_file *s, void *v)
+{
+ struct nf_conntrack_expect *expect = v;
+
+ if (expect->timeout.function)
+ seq_printf(s, "%ld ", timer_pending(&expect->timeout)
+ ? (long)(expect->timeout.expires - jiffies)/HZ : 0);
+ else
+ seq_printf(s, "- ");
+ seq_printf(s, "l3proto = %u proto=%u ",
+ expect->tuple.src.l3num,
+ expect->tuple.dst.protonum);
+ print_tuple(s, &expect->tuple,
+ __nf_ct_l3proto_find(expect->tuple.src.l3num),
+ __nf_ct_l4proto_find(expect->tuple.src.l3num,
+ expect->tuple.dst.protonum));
+ return seq_putc(s, '\n');
+}
+
+static struct seq_operations exp_seq_ops = {
+ .start = exp_seq_start,
+ .next = exp_seq_next,
+ .stop = exp_seq_stop,
+ .show = exp_seq_show
+};
+
+static int exp_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &exp_seq_ops);
+}
+
+struct file_operations exp_file_ops = {
+ .owner = THIS_MODULE,
+ .open = exp_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release
+};
+#endif /* CONFIG_PROC_FS */
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
index 0c17a5bd112b..92a947168761 100644
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -26,12 +26,15 @@
#include <net/tcp.h>
#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_expect.h>
+#include <net/netfilter/nf_conntrack_ecache.h>
#include <net/netfilter/nf_conntrack_helper.h>
#include <linux/netfilter/nf_conntrack_ftp.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Rusty Russell <rusty@rustcorp.com.au>");
MODULE_DESCRIPTION("ftp connection tracking helper");
+MODULE_ALIAS("ip_conntrack_ftp");
/* This is slow, but it's simple. --RR */
static char *ftp_buffer;
@@ -48,7 +51,7 @@ module_param(loose, bool, 0600);
unsigned int (*nf_nat_ftp_hook)(struct sk_buff **pskb,
enum ip_conntrack_info ctinfo,
- enum ip_ct_ftp_type type,
+ enum nf_ct_ftp_type type,
unsigned int matchoff,
unsigned int matchlen,
struct nf_conntrack_expect *exp,
@@ -71,7 +74,7 @@ static struct ftp_search {
size_t plen;
char skip;
char term;
- enum ip_ct_ftp_type ftptype;
+ enum nf_ct_ftp_type ftptype;
int (*getnum)(const char *, size_t, struct nf_conntrack_man *, char);
} search[IP_CT_DIR_MAX][2] = {
[IP_CT_DIR_ORIGINAL] = {
@@ -80,7 +83,7 @@ static struct ftp_search {
.plen = sizeof("PORT") - 1,
.skip = ' ',
.term = '\r',
- .ftptype = IP_CT_FTP_PORT,
+ .ftptype = NF_CT_FTP_PORT,
.getnum = try_rfc959,
},
{
@@ -88,7 +91,7 @@ static struct ftp_search {
.plen = sizeof("EPRT") - 1,
.skip = ' ',
.term = '\r',
- .ftptype = IP_CT_FTP_EPRT,
+ .ftptype = NF_CT_FTP_EPRT,
.getnum = try_eprt,
},
},
@@ -98,7 +101,7 @@ static struct ftp_search {
.plen = sizeof("227 ") - 1,
.skip = '(',
.term = ')',
- .ftptype = IP_CT_FTP_PASV,
+ .ftptype = NF_CT_FTP_PASV,
.getnum = try_rfc959,
},
{
@@ -106,7 +109,7 @@ static struct ftp_search {
.plen = sizeof("229 ") - 1,
.skip = '(',
.term = ')',
- .ftptype = IP_CT_FTP_EPSV,
+ .ftptype = NF_CT_FTP_EPSV,
.getnum = try_epsv_response,
},
},
@@ -171,7 +174,7 @@ static int try_rfc959(const char *data, size_t dlen,
/* Grab port: number up to delimiter */
static int get_port(const char *data, int start, size_t dlen, char delim,
- u_int16_t *port)
+ __be16 *port)
{
u_int16_t tmp_port = 0;
int i;
@@ -317,7 +320,7 @@ static int find_pattern(const char *data, size_t dlen,
}
/* Look up to see if we're just after a \n. */
-static int find_nl_seq(u32 seq, const struct ip_ct_ftp_master *info, int dir)
+static int find_nl_seq(u32 seq, const struct nf_ct_ftp_master *info, int dir)
{
unsigned int i;
@@ -328,7 +331,7 @@ static int find_nl_seq(u32 seq, const struct ip_ct_ftp_master *info, int dir)
}
/* We don't update if it's older than what we have. */
-static void update_nl_seq(u32 nl_seq, struct ip_ct_ftp_master *info, int dir,
+static void update_nl_seq(u32 nl_seq, struct nf_ct_ftp_master *info, int dir,
struct sk_buff *skb)
{
unsigned int i, oldest = NUM_SEQ_TO_REMEMBER;
@@ -364,12 +367,12 @@ static int help(struct sk_buff **pskb,
u32 seq;
int dir = CTINFO2DIR(ctinfo);
unsigned int matchlen, matchoff;
- struct ip_ct_ftp_master *ct_ftp_info = &nfct_help(ct)->help.ct_ftp_info;
+ struct nf_ct_ftp_master *ct_ftp_info = &nfct_help(ct)->help.ct_ftp_info;
struct nf_conntrack_expect *exp;
struct nf_conntrack_man cmd = {};
-
unsigned int i;
int found = 0, ends_in_nl;
+ typeof(nf_nat_ftp_hook) nf_nat_ftp;
/* Until there's been traffic both ways, don't look in packets. */
if (ctinfo != IP_CT_ESTABLISHED
@@ -500,12 +503,12 @@ static int help(struct sk_buff **pskb,
.u = { .tcp = { 0 }},
},
.dst = { .protonum = 0xFF,
- .u = { .tcp = { 0xFFFF }},
+ .u = { .tcp = { __constant_htons(0xFFFF) }},
},
};
if (cmd.l3num == PF_INET) {
- exp->mask.src.u3.ip = 0xFFFFFFFF;
- exp->mask.dst.u3.ip = 0xFFFFFFFF;
+ exp->mask.src.u3.ip = htonl(0xFFFFFFFF);
+ exp->mask.dst.u3.ip = htonl(0xFFFFFFFF);
} else {
memset(exp->mask.src.u3.ip6, 0xFF,
sizeof(exp->mask.src.u3.ip6));
@@ -514,13 +517,15 @@ static int help(struct sk_buff **pskb,
}
exp->expectfn = NULL;
+ exp->helper = NULL;
exp->flags = 0;
/* Now, NAT might want to mangle the packet, and register the
* (possibly changed) expectation itself. */
- if (nf_nat_ftp_hook)
- ret = nf_nat_ftp_hook(pskb, ctinfo, search[dir][i].ftptype,
- matchoff, matchlen, exp, &seq);
+ nf_nat_ftp = rcu_dereference(nf_nat_ftp_hook);
+ if (nf_nat_ftp && ct->status & IPS_NAT_MASK)
+ ret = nf_nat_ftp(pskb, ctinfo, search[dir][i].ftptype,
+ matchoff, matchlen, exp, &seq);
else {
/* Can't expect this? Best to drop packet now. */
if (nf_conntrack_expect_related(exp) != 0)
@@ -584,7 +589,8 @@ static int __init nf_conntrack_ftp_init(void)
for (j = 0; j < 2; j++) {
ftp[i][j].tuple.src.u.tcp.port = htons(ports[i]);
ftp[i][j].tuple.dst.protonum = IPPROTO_TCP;
- ftp[i][j].mask.src.u.tcp.port = 0xFFFF;
+ ftp[i][j].mask.src.l3num = 0xFFFF;
+ ftp[i][j].mask.src.u.tcp.port = htons(0xFFFF);
ftp[i][j].mask.dst.protonum = 0xFF;
ftp[i][j].max_expected = 1;
ftp[i][j].timeout = 5 * 60; /* 5 Minutes */
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c b/net/netfilter/nf_conntrack_h323_asn1.c
index 26dfecadb335..f6fad713d484 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c
+++ b/net/netfilter/nf_conntrack_h323_asn1.c
@@ -15,7 +15,7 @@
#else
#include <stdio.h>
#endif
-#include <linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h>
+#include <linux/netfilter/nf_conntrack_h323_asn1.h>
/* Trace Flag */
#ifndef H323_TRACE
@@ -144,7 +144,7 @@ static decoder_t Decoders[] = {
/****************************************************************************
* H.323 Types
****************************************************************************/
-#include "ip_conntrack_helper_h323_types.c"
+#include "nf_conntrack_h323_types.c"
/****************************************************************************
* Functions
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c
new file mode 100644
index 000000000000..6d8568959f82
--- /dev/null
+++ b/net/netfilter/nf_conntrack_h323_main.c
@@ -0,0 +1,1856 @@
+/*
+ * H.323 connection tracking helper
+ *
+ * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
+ *
+ * This source code is licensed under General Public License version 2.
+ *
+ * Based on the 'brute force' H.323 connection tracking module by
+ * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * For more information, please see http://nath323.sourceforge.net/
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/ctype.h>
+#include <linux/inet.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/udp.h>
+#include <linux/tcp.h>
+#include <linux/skbuff.h>
+#include <net/route.h>
+#include <net/ip6_route.h>
+
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_core.h>
+#include <net/netfilter/nf_conntrack_tuple.h>
+#include <net/netfilter/nf_conntrack_expect.h>
+#include <net/netfilter/nf_conntrack_ecache.h>
+#include <net/netfilter/nf_conntrack_helper.h>
+#include <linux/netfilter/nf_conntrack_h323.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+/* Parameters */
+static unsigned int default_rrq_ttl __read_mostly = 300;
+module_param(default_rrq_ttl, uint, 0600);
+MODULE_PARM_DESC(default_rrq_ttl, "use this TTL if it's missing in RRQ");
+
+static int gkrouted_only __read_mostly = 1;
+module_param(gkrouted_only, int, 0600);
+MODULE_PARM_DESC(gkrouted_only, "only accept calls from gatekeeper");
+
+static int callforward_filter __read_mostly = 1;
+module_param(callforward_filter, bool, 0600);
+MODULE_PARM_DESC(callforward_filter, "only create call forwarding expectations "
+ "if both endpoints are on different sides "
+ "(determined by routing information)");
+
+/* Hooks for NAT */
+int (*set_h245_addr_hook) (struct sk_buff **pskb,
+ unsigned char **data, int dataoff,
+ H245_TransportAddress *taddr,
+ union nf_conntrack_address *addr, __be16 port)
+ __read_mostly;
+int (*set_h225_addr_hook) (struct sk_buff **pskb,
+ unsigned char **data, int dataoff,
+ TransportAddress *taddr,
+ union nf_conntrack_address *addr, __be16 port)
+ __read_mostly;
+int (*set_sig_addr_hook) (struct sk_buff **pskb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data,
+ TransportAddress *taddr, int count) __read_mostly;
+int (*set_ras_addr_hook) (struct sk_buff **pskb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data,
+ TransportAddress *taddr, int count) __read_mostly;
+int (*nat_rtp_rtcp_hook) (struct sk_buff **pskb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ H245_TransportAddress *taddr,
+ __be16 port, __be16 rtp_port,
+ struct nf_conntrack_expect *rtp_exp,
+ struct nf_conntrack_expect *rtcp_exp) __read_mostly;
+int (*nat_t120_hook) (struct sk_buff **pskb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ H245_TransportAddress *taddr, __be16 port,
+ struct nf_conntrack_expect *exp) __read_mostly;
+int (*nat_h245_hook) (struct sk_buff **pskb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ TransportAddress *taddr, __be16 port,
+ struct nf_conntrack_expect *exp) __read_mostly;
+int (*nat_callforwarding_hook) (struct sk_buff **pskb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ TransportAddress *taddr, __be16 port,
+ struct nf_conntrack_expect *exp) __read_mostly;
+int (*nat_q931_hook) (struct sk_buff **pskb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, TransportAddress *taddr, int idx,
+ __be16 port, struct nf_conntrack_expect *exp)
+ __read_mostly;
+
+static DEFINE_SPINLOCK(nf_h323_lock);
+static char *h323_buffer;
+
+static struct nf_conntrack_helper nf_conntrack_helper_h245;
+static struct nf_conntrack_helper nf_conntrack_helper_q931[];
+static struct nf_conntrack_helper nf_conntrack_helper_ras[];
+
+/****************************************************************************/
+static int get_tpkt_data(struct sk_buff **pskb, unsigned int protoff,
+ struct nf_conn *ct, enum ip_conntrack_info ctinfo,
+ unsigned char **data, int *datalen, int *dataoff)
+{
+ struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
+ int dir = CTINFO2DIR(ctinfo);
+ struct tcphdr _tcph, *th;
+ int tcpdatalen;
+ int tcpdataoff;
+ unsigned char *tpkt;
+ int tpktlen;
+ int tpktoff;
+
+ /* Get TCP header */
+ th = skb_header_pointer(*pskb, protoff, sizeof(_tcph), &_tcph);
+ if (th == NULL)
+ return 0;
+
+ /* Get TCP data offset */
+ tcpdataoff = protoff + th->doff * 4;
+
+ /* Get TCP data length */
+ tcpdatalen = (*pskb)->len - tcpdataoff;
+ if (tcpdatalen <= 0) /* No TCP data */
+ goto clear_out;
+
+ if (*data == NULL) { /* first TPKT */
+ /* Get first TPKT pointer */
+ tpkt = skb_header_pointer(*pskb, tcpdataoff, tcpdatalen,
+ h323_buffer);
+ BUG_ON(tpkt == NULL);
+
+ /* Validate TPKT identifier */
+ if (tcpdatalen < 4 || tpkt[0] != 0x03 || tpkt[1] != 0) {
+ /* Netmeeting sends TPKT header and data separately */
+ if (info->tpkt_len[dir] > 0) {
+ DEBUGP("nf_ct_h323: previous packet "
+ "indicated separate TPKT data of %hu "
+ "bytes\n", info->tpkt_len[dir]);
+ if (info->tpkt_len[dir] <= tcpdatalen) {
+ /* Yes, there was a TPKT header
+ * received */
+ *data = tpkt;
+ *datalen = info->tpkt_len[dir];
+ *dataoff = 0;
+ goto out;
+ }
+
+ /* Fragmented TPKT */
+ if (net_ratelimit())
+ printk("nf_ct_h323: "
+ "fragmented TPKT\n");
+ goto clear_out;
+ }
+
+ /* It is not even a TPKT */
+ return 0;
+ }
+ tpktoff = 0;
+ } else { /* Next TPKT */
+ tpktoff = *dataoff + *datalen;
+ tcpdatalen -= tpktoff;
+ if (tcpdatalen <= 4) /* No more TPKT */
+ goto clear_out;
+ tpkt = *data + *datalen;
+
+ /* Validate TPKT identifier */
+ if (tpkt[0] != 0x03 || tpkt[1] != 0)
+ goto clear_out;
+ }
+
+ /* Validate TPKT length */
+ tpktlen = tpkt[2] * 256 + tpkt[3];
+ if (tpktlen < 4)
+ goto clear_out;
+ if (tpktlen > tcpdatalen) {
+ if (tcpdatalen == 4) { /* Separate TPKT header */
+ /* Netmeeting sends TPKT header and data separately */
+ DEBUGP("nf_ct_h323: separate TPKT header indicates "
+ "there will be TPKT data of %hu bytes\n",
+ tpktlen - 4);
+ info->tpkt_len[dir] = tpktlen - 4;
+ return 0;
+ }
+
+ if (net_ratelimit())
+ printk("nf_ct_h323: incomplete TPKT (fragmented?)\n");
+ goto clear_out;
+ }
+
+ /* This is the encapsulated data */
+ *data = tpkt + 4;
+ *datalen = tpktlen - 4;
+ *dataoff = tpktoff + 4;
+
+ out:
+ /* Clear TPKT length */
+ info->tpkt_len[dir] = 0;
+ return 1;
+
+ clear_out:
+ info->tpkt_len[dir] = 0;
+ return 0;
+}
+
+/****************************************************************************/
+static int get_h245_addr(struct nf_conn *ct, unsigned char *data,
+ H245_TransportAddress *taddr,
+ union nf_conntrack_address *addr, __be16 *port)
+{
+ unsigned char *p;
+ int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
+ int len;
+
+ if (taddr->choice != eH245_TransportAddress_unicastAddress)
+ return 0;
+
+ switch (taddr->unicastAddress.choice) {
+ case eUnicastAddress_iPAddress:
+ if (family != AF_INET)
+ return 0;
+ p = data + taddr->unicastAddress.iPAddress.network;
+ len = 4;
+ break;
+ case eUnicastAddress_iP6Address:
+ if (family != AF_INET6)
+ return 0;
+ p = data + taddr->unicastAddress.iP6Address.network;
+ len = 16;
+ break;
+ default:
+ return 0;
+ }
+
+ memcpy(addr, p, len);
+ memset((void *)addr + len, 0, sizeof(*addr) - len);
+ memcpy(port, p + len, sizeof(__be16));
+
+ return 1;
+}
+
+/****************************************************************************/
+static int expect_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ H245_TransportAddress *taddr)
+{
+ int dir = CTINFO2DIR(ctinfo);
+ int ret = 0;
+ __be16 port;
+ __be16 rtp_port, rtcp_port;
+ union nf_conntrack_address addr;
+ struct nf_conntrack_expect *rtp_exp;
+ struct nf_conntrack_expect *rtcp_exp;
+ typeof(nat_rtp_rtcp_hook) nat_rtp_rtcp;
+
+ /* Read RTP or RTCP address */
+ if (!get_h245_addr(ct, *data, taddr, &addr, &port) ||
+ memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) ||
+ port == 0)
+ return 0;
+
+ /* RTP port is even */
+ port &= htons(~1);
+ rtp_port = port;
+ rtcp_port = htons(ntohs(port) + 1);
+
+ /* Create expect for RTP */
+ if ((rtp_exp = nf_conntrack_expect_alloc(ct)) == NULL)
+ return -1;
+ nf_conntrack_expect_init(rtp_exp, ct->tuplehash[!dir].tuple.src.l3num,
+ &ct->tuplehash[!dir].tuple.src.u3,
+ &ct->tuplehash[!dir].tuple.dst.u3,
+ IPPROTO_UDP, NULL, &rtp_port);
+
+ /* Create expect for RTCP */
+ if ((rtcp_exp = nf_conntrack_expect_alloc(ct)) == NULL) {
+ nf_conntrack_expect_put(rtp_exp);
+ return -1;
+ }
+ nf_conntrack_expect_init(rtcp_exp, ct->tuplehash[!dir].tuple.src.l3num,
+ &ct->tuplehash[!dir].tuple.src.u3,
+ &ct->tuplehash[!dir].tuple.dst.u3,
+ IPPROTO_UDP, NULL, &rtcp_port);
+
+ if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
+ &ct->tuplehash[!dir].tuple.dst.u3,
+ sizeof(ct->tuplehash[dir].tuple.src.u3)) &&
+ (nat_rtp_rtcp = rcu_dereference(nat_rtp_rtcp_hook)) &&
+ ct->status & IPS_NAT_MASK) {
+ /* NAT needed */
+ ret = nat_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
+ taddr, port, rtp_port, rtp_exp, rtcp_exp);
+ } else { /* Conntrack only */
+ if (nf_conntrack_expect_related(rtp_exp) == 0) {
+ if (nf_conntrack_expect_related(rtcp_exp) == 0) {
+ DEBUGP("nf_ct_h323: expect RTP ");
+ NF_CT_DUMP_TUPLE(&rtp_exp->tuple);
+ DEBUGP("nf_ct_h323: expect RTCP ");
+ NF_CT_DUMP_TUPLE(&rtcp_exp->tuple);
+ } else {
+ nf_conntrack_unexpect_related(rtp_exp);
+ ret = -1;
+ }
+ } else
+ ret = -1;
+ }
+
+ nf_conntrack_expect_put(rtp_exp);
+ nf_conntrack_expect_put(rtcp_exp);
+
+ return ret;
+}
+
+/****************************************************************************/
+static int expect_t120(struct sk_buff **pskb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ H245_TransportAddress *taddr)
+{
+ int dir = CTINFO2DIR(ctinfo);
+ int ret = 0;
+ __be16 port;
+ union nf_conntrack_address addr;
+ struct nf_conntrack_expect *exp;
+ typeof(nat_t120_hook) nat_t120;
+
+ /* Read T.120 address */
+ if (!get_h245_addr(ct, *data, taddr, &addr, &port) ||
+ memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) ||
+ port == 0)
+ return 0;
+
+ /* Create expect for T.120 connections */
+ if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
+ return -1;
+ nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
+ &ct->tuplehash[!dir].tuple.src.u3,
+ &ct->tuplehash[!dir].tuple.dst.u3,
+ IPPROTO_TCP, NULL, &port);
+ exp->flags = NF_CT_EXPECT_PERMANENT; /* Accept multiple channels */
+
+ if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
+ &ct->tuplehash[!dir].tuple.dst.u3,
+ sizeof(ct->tuplehash[dir].tuple.src.u3)) &&
+ (nat_t120 = rcu_dereference(nat_t120_hook)) &&
+ ct->status & IPS_NAT_MASK) {
+ /* NAT needed */
+ ret = nat_t120(pskb, ct, ctinfo, data, dataoff, taddr,
+ port, exp);
+ } else { /* Conntrack only */
+ if (nf_conntrack_expect_related(exp) == 0) {
+ DEBUGP("nf_ct_h323: expect T.120 ");
+ NF_CT_DUMP_TUPLE(&exp->tuple);
+ } else
+ ret = -1;
+ }
+
+ nf_conntrack_expect_put(exp);
+
+ return ret;
+}
+
+/****************************************************************************/
+static int process_h245_channel(struct sk_buff **pskb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ H2250LogicalChannelParameters *channel)
+{
+ int ret;
+
+ if (channel->options & eH2250LogicalChannelParameters_mediaChannel) {
+ /* RTP */
+ ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
+ &channel->mediaChannel);
+ if (ret < 0)
+ return -1;
+ }
+
+ if (channel->
+ options & eH2250LogicalChannelParameters_mediaControlChannel) {
+ /* RTCP */
+ ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
+ &channel->mediaControlChannel);
+ if (ret < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+static int process_olc(struct sk_buff **pskb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ OpenLogicalChannel *olc)
+{
+ int ret;
+
+ DEBUGP("nf_ct_h323: OpenLogicalChannel\n");
+
+ if (olc->forwardLogicalChannelParameters.multiplexParameters.choice ==
+ eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)
+ {
+ ret = process_h245_channel(pskb, ct, ctinfo, data, dataoff,
+ &olc->
+ forwardLogicalChannelParameters.
+ multiplexParameters.
+ h2250LogicalChannelParameters);
+ if (ret < 0)
+ return -1;
+ }
+
+ if ((olc->options &
+ eOpenLogicalChannel_reverseLogicalChannelParameters) &&
+ (olc->reverseLogicalChannelParameters.options &
+ eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters)
+ && (olc->reverseLogicalChannelParameters.multiplexParameters.
+ choice ==
+ eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters))
+ {
+ ret =
+ process_h245_channel(pskb, ct, ctinfo, data, dataoff,
+ &olc->
+ reverseLogicalChannelParameters.
+ multiplexParameters.
+ h2250LogicalChannelParameters);
+ if (ret < 0)
+ return -1;
+ }
+
+ if ((olc->options & eOpenLogicalChannel_separateStack) &&
+ olc->forwardLogicalChannelParameters.dataType.choice ==
+ eDataType_data &&
+ olc->forwardLogicalChannelParameters.dataType.data.application.
+ choice == eDataApplicationCapability_application_t120 &&
+ olc->forwardLogicalChannelParameters.dataType.data.application.
+ t120.choice == eDataProtocolCapability_separateLANStack &&
+ olc->separateStack.networkAddress.choice ==
+ eNetworkAccessParameters_networkAddress_localAreaAddress) {
+ ret = expect_t120(pskb, ct, ctinfo, data, dataoff,
+ &olc->separateStack.networkAddress.
+ localAreaAddress);
+ if (ret < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+static int process_olca(struct sk_buff **pskb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ OpenLogicalChannelAck *olca)
+{
+ H2250LogicalChannelAckParameters *ack;
+ int ret;
+
+ DEBUGP("nf_ct_h323: OpenLogicalChannelAck\n");
+
+ if ((olca->options &
+ eOpenLogicalChannelAck_reverseLogicalChannelParameters) &&
+ (olca->reverseLogicalChannelParameters.options &
+ eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters)
+ && (olca->reverseLogicalChannelParameters.multiplexParameters.
+ choice ==
+ eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters))
+ {
+ ret = process_h245_channel(pskb, ct, ctinfo, data, dataoff,
+ &olca->
+ reverseLogicalChannelParameters.
+ multiplexParameters.
+ h2250LogicalChannelParameters);
+ if (ret < 0)
+ return -1;
+ }
+
+ if ((olca->options &
+ eOpenLogicalChannelAck_forwardMultiplexAckParameters) &&
+ (olca->forwardMultiplexAckParameters.choice ==
+ eOpenLogicalChannelAck_forwardMultiplexAckParameters_h2250LogicalChannelAckParameters))
+ {
+ ack = &olca->forwardMultiplexAckParameters.
+ h2250LogicalChannelAckParameters;
+ if (ack->options &
+ eH2250LogicalChannelAckParameters_mediaChannel) {
+ /* RTP */
+ ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
+ &ack->mediaChannel);
+ if (ret < 0)
+ return -1;
+ }
+
+ if (ack->options &
+ eH2250LogicalChannelAckParameters_mediaControlChannel) {
+ /* RTCP */
+ ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
+ &ack->mediaControlChannel);
+ if (ret < 0)
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+static int process_h245(struct sk_buff **pskb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ MultimediaSystemControlMessage *mscm)
+{
+ switch (mscm->choice) {
+ case eMultimediaSystemControlMessage_request:
+ if (mscm->request.choice ==
+ eRequestMessage_openLogicalChannel) {
+ return process_olc(pskb, ct, ctinfo, data, dataoff,
+ &mscm->request.openLogicalChannel);
+ }
+ DEBUGP("nf_ct_h323: H.245 Request %d\n",
+ mscm->request.choice);
+ break;
+ case eMultimediaSystemControlMessage_response:
+ if (mscm->response.choice ==
+ eResponseMessage_openLogicalChannelAck) {
+ return process_olca(pskb, ct, ctinfo, data, dataoff,
+ &mscm->response.
+ openLogicalChannelAck);
+ }
+ DEBUGP("nf_ct_h323: H.245 Response %d\n",
+ mscm->response.choice);
+ break;
+ default:
+ DEBUGP("nf_ct_h323: H.245 signal %d\n", mscm->choice);
+ break;
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+static int h245_help(struct sk_buff **pskb, unsigned int protoff,
+ struct nf_conn *ct, enum ip_conntrack_info ctinfo)
+{
+ static MultimediaSystemControlMessage mscm;
+ unsigned char *data = NULL;
+ int datalen;
+ int dataoff;
+ int ret;
+
+ /* Until there's been traffic both ways, don't look in packets. */
+ if (ctinfo != IP_CT_ESTABLISHED &&
+ ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
+ return NF_ACCEPT;
+ }
+ DEBUGP("nf_ct_h245: skblen = %u\n", (*pskb)->len);
+
+ spin_lock_bh(&nf_h323_lock);
+
+ /* Process each TPKT */
+ while (get_tpkt_data(pskb, protoff, ct, ctinfo,
+ &data, &datalen, &dataoff)) {
+ DEBUGP("nf_ct_h245: TPKT len=%d ", datalen);
+ NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
+
+ /* Decode H.245 signal */
+ ret = DecodeMultimediaSystemControlMessage(data, datalen,
+ &mscm);
+ if (ret < 0) {
+ if (net_ratelimit())
+ printk("nf_ct_h245: decoding error: %s\n",
+ ret == H323_ERROR_BOUND ?
+ "out of bound" : "out of range");
+ /* We don't drop when decoding error */
+ break;
+ }
+
+ /* Process H.245 signal */
+ if (process_h245(pskb, ct, ctinfo, &data, dataoff, &mscm) < 0)
+ goto drop;
+ }
+
+ spin_unlock_bh(&nf_h323_lock);
+ return NF_ACCEPT;
+
+ drop:
+ spin_unlock_bh(&nf_h323_lock);
+ if (net_ratelimit())
+ printk("nf_ct_h245: packet dropped\n");
+ return NF_DROP;
+}
+
+/****************************************************************************/
+static struct nf_conntrack_helper nf_conntrack_helper_h245 __read_mostly = {
+ .name = "H.245",
+ .me = THIS_MODULE,
+ .max_expected = H323_RTP_CHANNEL_MAX * 4 + 2 /* T.120 */,
+ .timeout = 240,
+ .tuple.dst.protonum = IPPROTO_UDP,
+ .mask.src.u.udp.port = __constant_htons(0xFFFF),
+ .mask.dst.protonum = 0xFF,
+ .help = h245_help
+};
+
+/****************************************************************************/
+int get_h225_addr(struct nf_conn *ct, unsigned char *data,
+ TransportAddress *taddr,
+ union nf_conntrack_address *addr, __be16 *port)
+{
+ unsigned char *p;
+ int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
+ int len;
+
+ switch (taddr->choice) {
+ case eTransportAddress_ipAddress:
+ if (family != AF_INET)
+ return 0;
+ p = data + taddr->ipAddress.ip;
+ len = 4;
+ break;
+ case eTransportAddress_ip6Address:
+ if (family != AF_INET6)
+ return 0;
+ p = data + taddr->ip6Address.ip6;
+ len = 16;
+ break;
+ default:
+ return 0;
+ }
+
+ memcpy(addr, p, len);
+ memset((void *)addr + len, 0, sizeof(*addr) - len);
+ memcpy(port, p + len, sizeof(__be16));
+
+ return 1;
+}
+
+/****************************************************************************/
+static int expect_h245(struct sk_buff **pskb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ TransportAddress *taddr)
+{
+ int dir = CTINFO2DIR(ctinfo);
+ int ret = 0;
+ __be16 port;
+ union nf_conntrack_address addr;
+ struct nf_conntrack_expect *exp;
+ typeof(nat_h245_hook) nat_h245;
+
+ /* Read h245Address */
+ if (!get_h225_addr(ct, *data, taddr, &addr, &port) ||
+ memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) ||
+ port == 0)
+ return 0;
+
+ /* Create expect for h245 connection */
+ if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
+ return -1;
+ nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
+ &ct->tuplehash[!dir].tuple.src.u3,
+ &ct->tuplehash[!dir].tuple.dst.u3,
+ IPPROTO_TCP, NULL, &port);
+ exp->helper = &nf_conntrack_helper_h245;
+
+ if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
+ &ct->tuplehash[!dir].tuple.dst.u3,
+ sizeof(ct->tuplehash[dir].tuple.src.u3)) &&
+ (nat_h245 = rcu_dereference(nat_h245_hook)) &&
+ ct->status & IPS_NAT_MASK) {
+ /* NAT needed */
+ ret = nat_h245(pskb, ct, ctinfo, data, dataoff, taddr,
+ port, exp);
+ } else { /* Conntrack only */
+ if (nf_conntrack_expect_related(exp) == 0) {
+ DEBUGP("nf_ct_q931: expect H.245 ");
+ NF_CT_DUMP_TUPLE(&exp->tuple);
+ } else
+ ret = -1;
+ }
+
+ nf_conntrack_expect_put(exp);
+
+ return ret;
+}
+
+/* If the calling party is on the same side of the forward-to party,
+ * we don't need to track the second call */
+static int callforward_do_filter(union nf_conntrack_address *src,
+ union nf_conntrack_address *dst,
+ int family)
+{
+ struct flowi fl1, fl2;
+ int ret = 0;
+
+ memset(&fl1, 0, sizeof(fl1));
+ memset(&fl2, 0, sizeof(fl2));
+
+ switch (family) {
+ case AF_INET: {
+ struct rtable *rt1, *rt2;
+
+ fl1.fl4_dst = src->ip;
+ fl2.fl4_dst = dst->ip;
+ if (ip_route_output_key(&rt1, &fl1) == 0) {
+ if (ip_route_output_key(&rt2, &fl2) == 0) {
+ if (rt1->rt_gateway == rt2->rt_gateway &&
+ rt1->u.dst.dev == rt2->u.dst.dev)
+ ret = 1;
+ dst_release(&rt2->u.dst);
+ }
+ dst_release(&rt1->u.dst);
+ }
+ break;
+ }
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ case AF_INET6: {
+ struct rt6_info *rt1, *rt2;
+
+ memcpy(&fl1.fl6_dst, src, sizeof(fl1.fl6_dst));
+ memcpy(&fl2.fl6_dst, dst, sizeof(fl2.fl6_dst));
+ rt1 = (struct rt6_info *)ip6_route_output(NULL, &fl1);
+ if (rt1) {
+ rt2 = (struct rt6_info *)ip6_route_output(NULL, &fl2);
+ if (rt2) {
+ if (!memcmp(&rt1->rt6i_gateway, &rt2->rt6i_gateway,
+ sizeof(rt1->rt6i_gateway)) &&
+ rt1->u.dst.dev == rt2->u.dst.dev)
+ ret = 1;
+ dst_release(&rt2->u.dst);
+ }
+ dst_release(&rt1->u.dst);
+ }
+ break;
+ }
+#endif
+ }
+ return ret;
+
+}
+
+/****************************************************************************/
+static int expect_callforwarding(struct sk_buff **pskb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ TransportAddress *taddr)
+{
+ int dir = CTINFO2DIR(ctinfo);
+ int ret = 0;
+ __be16 port;
+ union nf_conntrack_address addr;
+ struct nf_conntrack_expect *exp;
+ typeof(nat_callforwarding_hook) nat_callforwarding;
+
+ /* Read alternativeAddress */
+ if (!get_h225_addr(ct, *data, taddr, &addr, &port) || port == 0)
+ return 0;
+
+ /* If the calling party is on the same side of the forward-to party,
+ * we don't need to track the second call */
+ if (callforward_filter &&
+ callforward_do_filter(&addr, &ct->tuplehash[!dir].tuple.src.u3,
+ ct->tuplehash[!dir].tuple.src.l3num)) {
+ DEBUGP("nf_ct_q931: Call Forwarding not tracked\n");
+ return 0;
+ }
+
+ /* Create expect for the second call leg */
+ if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
+ return -1;
+ nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
+ &ct->tuplehash[!dir].tuple.src.u3, &addr,
+ IPPROTO_TCP, NULL, &port);
+ exp->helper = nf_conntrack_helper_q931;
+
+ if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
+ &ct->tuplehash[!dir].tuple.dst.u3,
+ sizeof(ct->tuplehash[dir].tuple.src.u3)) &&
+ (nat_callforwarding = rcu_dereference(nat_callforwarding_hook)) &&
+ ct->status & IPS_NAT_MASK) {
+ /* Need NAT */
+ ret = nat_callforwarding(pskb, ct, ctinfo, data, dataoff,
+ taddr, port, exp);
+ } else { /* Conntrack only */
+ if (nf_conntrack_expect_related(exp) == 0) {
+ DEBUGP("nf_ct_q931: expect Call Forwarding ");
+ NF_CT_DUMP_TUPLE(&exp->tuple);
+ } else
+ ret = -1;
+ }
+
+ nf_conntrack_expect_put(exp);
+
+ return ret;
+}
+
+/****************************************************************************/
+static int process_setup(struct sk_buff **pskb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ Setup_UUIE *setup)
+{
+ int dir = CTINFO2DIR(ctinfo);
+ int ret;
+ int i;
+ __be16 port;
+ union nf_conntrack_address addr;
+ typeof(set_h225_addr_hook) set_h225_addr;
+
+ DEBUGP("nf_ct_q931: Setup\n");
+
+ if (setup->options & eSetup_UUIE_h245Address) {
+ ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
+ &setup->h245Address);
+ if (ret < 0)
+ return -1;
+ }
+
+ set_h225_addr = rcu_dereference(set_h225_addr_hook);
+ if ((setup->options & eSetup_UUIE_destCallSignalAddress) &&
+ (set_h225_addr) && ct->status && IPS_NAT_MASK &&
+ get_h225_addr(ct, *data, &setup->destCallSignalAddress,
+ &addr, &port) &&
+ memcmp(&addr, &ct->tuplehash[!dir].tuple.src.u3, sizeof(addr))) {
+ DEBUGP("nf_ct_q931: set destCallSignalAddress "
+ NIP6_FMT ":%hu->" NIP6_FMT ":%hu\n",
+ NIP6(*(struct in6_addr *)&addr), ntohs(port),
+ NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.src.u3),
+ ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port));
+ ret = set_h225_addr(pskb, data, dataoff,
+ &setup->destCallSignalAddress,
+ &ct->tuplehash[!dir].tuple.src.u3,
+ ct->tuplehash[!dir].tuple.src.u.tcp.port);
+ if (ret < 0)
+ return -1;
+ }
+
+ if ((setup->options & eSetup_UUIE_sourceCallSignalAddress) &&
+ (set_h225_addr) && ct->status & IPS_NAT_MASK &&
+ get_h225_addr(ct, *data, &setup->sourceCallSignalAddress,
+ &addr, &port) &&
+ memcmp(&addr, &ct->tuplehash[!dir].tuple.dst.u3, sizeof(addr))) {
+ DEBUGP("nf_ct_q931: set sourceCallSignalAddress "
+ NIP6_FMT ":%hu->" NIP6_FMT ":%hu\n",
+ NIP6(*(struct in6_addr *)&addr), ntohs(port),
+ NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.dst.u3),
+ ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port));
+ ret = set_h225_addr(pskb, data, dataoff,
+ &setup->sourceCallSignalAddress,
+ &ct->tuplehash[!dir].tuple.dst.u3,
+ ct->tuplehash[!dir].tuple.dst.u.tcp.port);
+ if (ret < 0)
+ return -1;
+ }
+
+ if (setup->options & eSetup_UUIE_fastStart) {
+ for (i = 0; i < setup->fastStart.count; i++) {
+ ret = process_olc(pskb, ct, ctinfo, data, dataoff,
+ &setup->fastStart.item[i]);
+ if (ret < 0)
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+static int process_callproceeding(struct sk_buff **pskb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ CallProceeding_UUIE *callproc)
+{
+ int ret;
+ int i;
+
+ DEBUGP("nf_ct_q931: CallProceeding\n");
+
+ if (callproc->options & eCallProceeding_UUIE_h245Address) {
+ ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
+ &callproc->h245Address);
+ if (ret < 0)
+ return -1;
+ }
+
+ if (callproc->options & eCallProceeding_UUIE_fastStart) {
+ for (i = 0; i < callproc->fastStart.count; i++) {
+ ret = process_olc(pskb, ct, ctinfo, data, dataoff,
+ &callproc->fastStart.item[i]);
+ if (ret < 0)
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+static int process_connect(struct sk_buff **pskb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ Connect_UUIE *connect)
+{
+ int ret;
+ int i;
+
+ DEBUGP("nf_ct_q931: Connect\n");
+
+ if (connect->options & eConnect_UUIE_h245Address) {
+ ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
+ &connect->h245Address);
+ if (ret < 0)
+ return -1;
+ }
+
+ if (connect->options & eConnect_UUIE_fastStart) {
+ for (i = 0; i < connect->fastStart.count; i++) {
+ ret = process_olc(pskb, ct, ctinfo, data, dataoff,
+ &connect->fastStart.item[i]);
+ if (ret < 0)
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+static int process_alerting(struct sk_buff **pskb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ Alerting_UUIE *alert)
+{
+ int ret;
+ int i;
+
+ DEBUGP("nf_ct_q931: Alerting\n");
+
+ if (alert->options & eAlerting_UUIE_h245Address) {
+ ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
+ &alert->h245Address);
+ if (ret < 0)
+ return -1;
+ }
+
+ if (alert->options & eAlerting_UUIE_fastStart) {
+ for (i = 0; i < alert->fastStart.count; i++) {
+ ret = process_olc(pskb, ct, ctinfo, data, dataoff,
+ &alert->fastStart.item[i]);
+ if (ret < 0)
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+static int process_information(struct sk_buff **pskb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ Information_UUIE *info)
+{
+ int ret;
+ int i;
+
+ DEBUGP("nf_ct_q931: Information\n");
+
+ if (info->options & eInformation_UUIE_fastStart) {
+ for (i = 0; i < info->fastStart.count; i++) {
+ ret = process_olc(pskb, ct, ctinfo, data, dataoff,
+ &info->fastStart.item[i]);
+ if (ret < 0)
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+static int process_facility(struct sk_buff **pskb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ Facility_UUIE *facility)
+{
+ int ret;
+ int i;
+
+ DEBUGP("nf_ct_q931: Facility\n");
+
+ if (facility->reason.choice == eFacilityReason_callForwarded) {
+ if (facility->options & eFacility_UUIE_alternativeAddress)
+ return expect_callforwarding(pskb, ct, ctinfo, data,
+ dataoff,
+ &facility->
+ alternativeAddress);
+ return 0;
+ }
+
+ if (facility->options & eFacility_UUIE_h245Address) {
+ ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
+ &facility->h245Address);
+ if (ret < 0)
+ return -1;
+ }
+
+ if (facility->options & eFacility_UUIE_fastStart) {
+ for (i = 0; i < facility->fastStart.count; i++) {
+ ret = process_olc(pskb, ct, ctinfo, data, dataoff,
+ &facility->fastStart.item[i]);
+ if (ret < 0)
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+static int process_progress(struct sk_buff **pskb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ Progress_UUIE *progress)
+{
+ int ret;
+ int i;
+
+ DEBUGP("nf_ct_q931: Progress\n");
+
+ if (progress->options & eProgress_UUIE_h245Address) {
+ ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
+ &progress->h245Address);
+ if (ret < 0)
+ return -1;
+ }
+
+ if (progress->options & eProgress_UUIE_fastStart) {
+ for (i = 0; i < progress->fastStart.count; i++) {
+ ret = process_olc(pskb, ct, ctinfo, data, dataoff,
+ &progress->fastStart.item[i]);
+ if (ret < 0)
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+static int process_q931(struct sk_buff **pskb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff, Q931 *q931)
+{
+ H323_UU_PDU *pdu = &q931->UUIE.h323_uu_pdu;
+ int i;
+ int ret = 0;
+
+ switch (pdu->h323_message_body.choice) {
+ case eH323_UU_PDU_h323_message_body_setup:
+ ret = process_setup(pskb, ct, ctinfo, data, dataoff,
+ &pdu->h323_message_body.setup);
+ break;
+ case eH323_UU_PDU_h323_message_body_callProceeding:
+ ret = process_callproceeding(pskb, ct, ctinfo, data, dataoff,
+ &pdu->h323_message_body.
+ callProceeding);
+ break;
+ case eH323_UU_PDU_h323_message_body_connect:
+ ret = process_connect(pskb, ct, ctinfo, data, dataoff,
+ &pdu->h323_message_body.connect);
+ break;
+ case eH323_UU_PDU_h323_message_body_alerting:
+ ret = process_alerting(pskb, ct, ctinfo, data, dataoff,
+ &pdu->h323_message_body.alerting);
+ break;
+ case eH323_UU_PDU_h323_message_body_information:
+ ret = process_information(pskb, ct, ctinfo, data, dataoff,
+ &pdu->h323_message_body.
+ information);
+ break;
+ case eH323_UU_PDU_h323_message_body_facility:
+ ret = process_facility(pskb, ct, ctinfo, data, dataoff,
+ &pdu->h323_message_body.facility);
+ break;
+ case eH323_UU_PDU_h323_message_body_progress:
+ ret = process_progress(pskb, ct, ctinfo, data, dataoff,
+ &pdu->h323_message_body.progress);
+ break;
+ default:
+ DEBUGP("nf_ct_q931: Q.931 signal %d\n",
+ pdu->h323_message_body.choice);
+ break;
+ }
+
+ if (ret < 0)
+ return -1;
+
+ if (pdu->options & eH323_UU_PDU_h245Control) {
+ for (i = 0; i < pdu->h245Control.count; i++) {
+ ret = process_h245(pskb, ct, ctinfo, data, dataoff,
+ &pdu->h245Control.item[i]);
+ if (ret < 0)
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+static int q931_help(struct sk_buff **pskb, unsigned int protoff,
+ struct nf_conn *ct, enum ip_conntrack_info ctinfo)
+{
+ static Q931 q931;
+ unsigned char *data = NULL;
+ int datalen;
+ int dataoff;
+ int ret;
+
+ /* Until there's been traffic both ways, don't look in packets. */
+ if (ctinfo != IP_CT_ESTABLISHED &&
+ ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
+ return NF_ACCEPT;
+ }
+ DEBUGP("nf_ct_q931: skblen = %u\n", (*pskb)->len);
+
+ spin_lock_bh(&nf_h323_lock);
+
+ /* Process each TPKT */
+ while (get_tpkt_data(pskb, protoff, ct, ctinfo,
+ &data, &datalen, &dataoff)) {
+ DEBUGP("nf_ct_q931: TPKT len=%d ", datalen);
+ NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
+
+ /* Decode Q.931 signal */
+ ret = DecodeQ931(data, datalen, &q931);
+ if (ret < 0) {
+ if (net_ratelimit())
+ printk("nf_ct_q931: decoding error: %s\n",
+ ret == H323_ERROR_BOUND ?
+ "out of bound" : "out of range");
+ /* We don't drop when decoding error */
+ break;
+ }
+
+ /* Process Q.931 signal */
+ if (process_q931(pskb, ct, ctinfo, &data, dataoff, &q931) < 0)
+ goto drop;
+ }
+
+ spin_unlock_bh(&nf_h323_lock);
+ return NF_ACCEPT;
+
+ drop:
+ spin_unlock_bh(&nf_h323_lock);
+ if (net_ratelimit())
+ printk("nf_ct_q931: packet dropped\n");
+ return NF_DROP;
+}
+
+/****************************************************************************/
+static struct nf_conntrack_helper nf_conntrack_helper_q931[] __read_mostly = {
+ {
+ .name = "Q.931",
+ .me = THIS_MODULE,
+ /* T.120 and H.245 */
+ .max_expected = H323_RTP_CHANNEL_MAX * 4 + 4,
+ .timeout = 240,
+ .tuple.src.l3num = AF_INET,
+ .tuple.src.u.tcp.port = __constant_htons(Q931_PORT),
+ .tuple.dst.protonum = IPPROTO_TCP,
+ .mask.src.l3num = 0xFFFF,
+ .mask.src.u.tcp.port = __constant_htons(0xFFFF),
+ .mask.dst.protonum = 0xFF,
+ .help = q931_help
+ },
+ {
+ .name = "Q.931",
+ .me = THIS_MODULE,
+ /* T.120 and H.245 */
+ .max_expected = H323_RTP_CHANNEL_MAX * 4 + 4,
+ .timeout = 240,
+ .tuple.src.l3num = AF_INET6,
+ .tuple.src.u.tcp.port = __constant_htons(Q931_PORT),
+ .tuple.dst.protonum = IPPROTO_TCP,
+ .mask.src.l3num = 0xFFFF,
+ .mask.src.u.tcp.port = __constant_htons(0xFFFF),
+ .mask.dst.protonum = 0xFF,
+ .help = q931_help
+ },
+};
+
+/****************************************************************************/
+static unsigned char *get_udp_data(struct sk_buff **pskb, unsigned int protoff,
+ int *datalen)
+{
+ struct udphdr _uh, *uh;
+ int dataoff;
+
+ uh = skb_header_pointer(*pskb, protoff, sizeof(_uh), &_uh);
+ if (uh == NULL)
+ return NULL;
+ dataoff = protoff + sizeof(_uh);
+ if (dataoff >= (*pskb)->len)
+ return NULL;
+ *datalen = (*pskb)->len - dataoff;
+ return skb_header_pointer(*pskb, dataoff, *datalen, h323_buffer);
+}
+
+/****************************************************************************/
+static struct nf_conntrack_expect *find_expect(struct nf_conn *ct,
+ union nf_conntrack_address *addr,
+ __be16 port)
+{
+ struct nf_conntrack_expect *exp;
+ struct nf_conntrack_tuple tuple;
+
+ memset(&tuple.src.u3, 0, sizeof(tuple.src.u3));
+ tuple.src.u.tcp.port = 0;
+ memcpy(&tuple.dst.u3, addr, sizeof(tuple.dst.u3));
+ tuple.dst.u.tcp.port = port;
+ tuple.dst.protonum = IPPROTO_TCP;
+
+ exp = __nf_conntrack_expect_find(&tuple);
+ if (exp && exp->master == ct)
+ return exp;
+ return NULL;
+}
+
+/****************************************************************************/
+static int set_expect_timeout(struct nf_conntrack_expect *exp,
+ unsigned timeout)
+{
+ if (!exp || !del_timer(&exp->timeout))
+ return 0;
+
+ exp->timeout.expires = jiffies + timeout * HZ;
+ add_timer(&exp->timeout);
+
+ return 1;
+}
+
+/****************************************************************************/
+static int expect_q931(struct sk_buff **pskb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data,
+ TransportAddress *taddr, int count)
+{
+ struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
+ int dir = CTINFO2DIR(ctinfo);
+ int ret = 0;
+ int i;
+ __be16 port;
+ union nf_conntrack_address addr;
+ struct nf_conntrack_expect *exp;
+ typeof(nat_q931_hook) nat_q931;
+
+ /* Look for the first related address */
+ for (i = 0; i < count; i++) {
+ if (get_h225_addr(ct, *data, &taddr[i], &addr, &port) &&
+ memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3,
+ sizeof(addr)) == 0 && port != 0)
+ break;
+ }
+
+ if (i >= count) /* Not found */
+ return 0;
+
+ /* Create expect for Q.931 */
+ if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
+ return -1;
+ nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
+ gkrouted_only ? /* only accept calls from GK? */
+ &ct->tuplehash[!dir].tuple.src.u3 :
+ NULL,
+ &ct->tuplehash[!dir].tuple.dst.u3,
+ IPPROTO_TCP, NULL, &port);
+ exp->helper = nf_conntrack_helper_q931;
+ exp->flags = NF_CT_EXPECT_PERMANENT; /* Accept multiple calls */
+
+ nat_q931 = rcu_dereference(nat_q931_hook);
+ if (nat_q931 && ct->status & IPS_NAT_MASK) { /* Need NAT */
+ ret = nat_q931(pskb, ct, ctinfo, data, taddr, i, port, exp);
+ } else { /* Conntrack only */
+ if (nf_conntrack_expect_related(exp) == 0) {
+ DEBUGP("nf_ct_ras: expect Q.931 ");
+ NF_CT_DUMP_TUPLE(&exp->tuple);
+
+ /* Save port for looking up expect in processing RCF */
+ info->sig_port[dir] = port;
+ } else
+ ret = -1;
+ }
+
+ nf_conntrack_expect_put(exp);
+
+ return ret;
+}
+
+/****************************************************************************/
+static int process_grq(struct sk_buff **pskb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, GatekeeperRequest *grq)
+{
+ typeof(set_ras_addr_hook) set_ras_addr;
+
+ DEBUGP("nf_ct_ras: GRQ\n");
+
+ set_ras_addr = rcu_dereference(set_ras_addr_hook);
+ if (set_ras_addr && ct->status & IPS_NAT_MASK) /* NATed */
+ return set_ras_addr(pskb, ct, ctinfo, data,
+ &grq->rasAddress, 1);
+ return 0;
+}
+
+/****************************************************************************/
+static int process_gcf(struct sk_buff **pskb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, GatekeeperConfirm *gcf)
+{
+ int dir = CTINFO2DIR(ctinfo);
+ int ret = 0;
+ __be16 port;
+ union nf_conntrack_address addr;
+ struct nf_conntrack_expect *exp;
+
+ DEBUGP("nf_ct_ras: GCF\n");
+
+ if (!get_h225_addr(ct, *data, &gcf->rasAddress, &addr, &port))
+ return 0;
+
+ /* Registration port is the same as discovery port */
+ if (!memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) &&
+ port == ct->tuplehash[dir].tuple.src.u.udp.port)
+ return 0;
+
+ /* Avoid RAS expectation loops. A GCF is never expected. */
+ if (test_bit(IPS_EXPECTED_BIT, &ct->status))
+ return 0;
+
+ /* Need new expect */
+ if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
+ return -1;
+ nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
+ &ct->tuplehash[!dir].tuple.src.u3, &addr,
+ IPPROTO_UDP, NULL, &port);
+ exp->helper = nf_conntrack_helper_ras;
+
+ if (nf_conntrack_expect_related(exp) == 0) {
+ DEBUGP("nf_ct_ras: expect RAS ");
+ NF_CT_DUMP_TUPLE(&exp->tuple);
+ } else
+ ret = -1;
+
+ nf_conntrack_expect_put(exp);
+
+ return ret;
+}
+
+/****************************************************************************/
+static int process_rrq(struct sk_buff **pskb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, RegistrationRequest *rrq)
+{
+ struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
+ int ret;
+ typeof(set_ras_addr_hook) set_ras_addr;
+
+ DEBUGP("nf_ct_ras: RRQ\n");
+
+ ret = expect_q931(pskb, ct, ctinfo, data,
+ rrq->callSignalAddress.item,
+ rrq->callSignalAddress.count);
+ if (ret < 0)
+ return -1;
+
+ set_ras_addr = rcu_dereference(set_ras_addr_hook);
+ if (set_ras_addr && ct->status & IPS_NAT_MASK) {
+ ret = set_ras_addr(pskb, ct, ctinfo, data,
+ rrq->rasAddress.item,
+ rrq->rasAddress.count);
+ if (ret < 0)
+ return -1;
+ }
+
+ if (rrq->options & eRegistrationRequest_timeToLive) {
+ DEBUGP("nf_ct_ras: RRQ TTL = %u seconds\n", rrq->timeToLive);
+ info->timeout = rrq->timeToLive;
+ } else
+ info->timeout = default_rrq_ttl;
+
+ return 0;
+}
+
+/****************************************************************************/
+static int process_rcf(struct sk_buff **pskb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, RegistrationConfirm *rcf)
+{
+ struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
+ int dir = CTINFO2DIR(ctinfo);
+ int ret;
+ struct nf_conntrack_expect *exp;
+ typeof(set_sig_addr_hook) set_sig_addr;
+
+ DEBUGP("nf_ct_ras: RCF\n");
+
+ set_sig_addr = rcu_dereference(set_sig_addr_hook);
+ if (set_sig_addr && ct->status & IPS_NAT_MASK) {
+ ret = set_sig_addr(pskb, ct, ctinfo, data,
+ rcf->callSignalAddress.item,
+ rcf->callSignalAddress.count);
+ if (ret < 0)
+ return -1;
+ }
+
+ if (rcf->options & eRegistrationConfirm_timeToLive) {
+ DEBUGP("nf_ct_ras: RCF TTL = %u seconds\n", rcf->timeToLive);
+ info->timeout = rcf->timeToLive;
+ }
+
+ if (info->timeout > 0) {
+ DEBUGP
+ ("nf_ct_ras: set RAS connection timeout to %u seconds\n",
+ info->timeout);
+ nf_ct_refresh(ct, *pskb, info->timeout * HZ);
+
+ /* Set expect timeout */
+ read_lock_bh(&nf_conntrack_lock);
+ exp = find_expect(ct, &ct->tuplehash[dir].tuple.dst.u3,
+ info->sig_port[!dir]);
+ if (exp) {
+ DEBUGP("nf_ct_ras: set Q.931 expect "
+ "timeout to %u seconds for",
+ info->timeout);
+ NF_CT_DUMP_TUPLE(&exp->tuple);
+ set_expect_timeout(exp, info->timeout);
+ }
+ read_unlock_bh(&nf_conntrack_lock);
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+static int process_urq(struct sk_buff **pskb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, UnregistrationRequest *urq)
+{
+ struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
+ int dir = CTINFO2DIR(ctinfo);
+ int ret;
+ typeof(set_sig_addr_hook) set_sig_addr;
+
+ DEBUGP("nf_ct_ras: URQ\n");
+
+ set_sig_addr = rcu_dereference(set_sig_addr_hook);
+ if (set_sig_addr && ct->status & IPS_NAT_MASK) {
+ ret = set_sig_addr(pskb, ct, ctinfo, data,
+ urq->callSignalAddress.item,
+ urq->callSignalAddress.count);
+ if (ret < 0)
+ return -1;
+ }
+
+ /* Clear old expect */
+ nf_ct_remove_expectations(ct);
+ info->sig_port[dir] = 0;
+ info->sig_port[!dir] = 0;
+
+ /* Give it 30 seconds for UCF or URJ */
+ nf_ct_refresh(ct, *pskb, 30 * HZ);
+
+ return 0;
+}
+
+/****************************************************************************/
+static int process_arq(struct sk_buff **pskb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, AdmissionRequest *arq)
+{
+ struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
+ int dir = CTINFO2DIR(ctinfo);
+ __be16 port;
+ union nf_conntrack_address addr;
+ typeof(set_h225_addr_hook) set_h225_addr;
+
+ DEBUGP("nf_ct_ras: ARQ\n");
+
+ set_h225_addr = rcu_dereference(set_h225_addr_hook);
+ if ((arq->options & eAdmissionRequest_destCallSignalAddress) &&
+ get_h225_addr(ct, *data, &arq->destCallSignalAddress,
+ &addr, &port) &&
+ !memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) &&
+ port == info->sig_port[dir] &&
+ set_h225_addr && ct->status & IPS_NAT_MASK) {
+ /* Answering ARQ */
+ return set_h225_addr(pskb, data, 0,
+ &arq->destCallSignalAddress,
+ &ct->tuplehash[!dir].tuple.dst.u3,
+ info->sig_port[!dir]);
+ }
+
+ if ((arq->options & eAdmissionRequest_srcCallSignalAddress) &&
+ get_h225_addr(ct, *data, &arq->srcCallSignalAddress,
+ &addr, &port) &&
+ !memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) &&
+ set_h225_addr && ct->status & IPS_NAT_MASK) {
+ /* Calling ARQ */
+ return set_h225_addr(pskb, data, 0,
+ &arq->srcCallSignalAddress,
+ &ct->tuplehash[!dir].tuple.dst.u3,
+ port);
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+static int process_acf(struct sk_buff **pskb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, AdmissionConfirm *acf)
+{
+ int dir = CTINFO2DIR(ctinfo);
+ int ret = 0;
+ __be16 port;
+ union nf_conntrack_address addr;
+ struct nf_conntrack_expect *exp;
+ typeof(set_sig_addr_hook) set_sig_addr;
+
+ DEBUGP("nf_ct_ras: ACF\n");
+
+ if (!get_h225_addr(ct, *data, &acf->destCallSignalAddress,
+ &addr, &port))
+ return 0;
+
+ if (!memcmp(&addr, &ct->tuplehash[dir].tuple.dst.u3, sizeof(addr))) {
+ /* Answering ACF */
+ set_sig_addr = rcu_dereference(set_sig_addr_hook);
+ if (set_sig_addr && ct->status & IPS_NAT_MASK)
+ return set_sig_addr(pskb, ct, ctinfo, data,
+ &acf->destCallSignalAddress, 1);
+ return 0;
+ }
+
+ /* Need new expect */
+ if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
+ return -1;
+ nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
+ &ct->tuplehash[!dir].tuple.src.u3, &addr,
+ IPPROTO_TCP, NULL, &port);
+ exp->flags = NF_CT_EXPECT_PERMANENT;
+ exp->helper = nf_conntrack_helper_q931;
+
+ if (nf_conntrack_expect_related(exp) == 0) {
+ DEBUGP("nf_ct_ras: expect Q.931 ");
+ NF_CT_DUMP_TUPLE(&exp->tuple);
+ } else
+ ret = -1;
+
+ nf_conntrack_expect_put(exp);
+
+ return ret;
+}
+
+/****************************************************************************/
+static int process_lrq(struct sk_buff **pskb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, LocationRequest *lrq)
+{
+ typeof(set_ras_addr_hook) set_ras_addr;
+
+ DEBUGP("nf_ct_ras: LRQ\n");
+
+ set_ras_addr = rcu_dereference(set_ras_addr_hook);
+ if (set_ras_addr && ct->status & IPS_NAT_MASK)
+ return set_ras_addr(pskb, ct, ctinfo, data,
+ &lrq->replyAddress, 1);
+ return 0;
+}
+
+/****************************************************************************/
+static int process_lcf(struct sk_buff **pskb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, LocationConfirm *lcf)
+{
+ int dir = CTINFO2DIR(ctinfo);
+ int ret = 0;
+ __be16 port;
+ union nf_conntrack_address addr;
+ struct nf_conntrack_expect *exp;
+
+ DEBUGP("nf_ct_ras: LCF\n");
+
+ if (!get_h225_addr(ct, *data, &lcf->callSignalAddress,
+ &addr, &port))
+ return 0;
+
+ /* Need new expect for call signal */
+ if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
+ return -1;
+ nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
+ &ct->tuplehash[!dir].tuple.src.u3, &addr,
+ IPPROTO_TCP, NULL, &port);
+ exp->flags = NF_CT_EXPECT_PERMANENT;
+ exp->helper = nf_conntrack_helper_q931;
+
+ if (nf_conntrack_expect_related(exp) == 0) {
+ DEBUGP("nf_ct_ras: expect Q.931 ");
+ NF_CT_DUMP_TUPLE(&exp->tuple);
+ } else
+ ret = -1;
+
+ nf_conntrack_expect_put(exp);
+
+ /* Ignore rasAddress */
+
+ return ret;
+}
+
+/****************************************************************************/
+static int process_irr(struct sk_buff **pskb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, InfoRequestResponse *irr)
+{
+ int ret;
+ typeof(set_ras_addr_hook) set_ras_addr;
+ typeof(set_sig_addr_hook) set_sig_addr;
+
+ DEBUGP("nf_ct_ras: IRR\n");
+
+ set_ras_addr = rcu_dereference(set_ras_addr_hook);
+ if (set_ras_addr && ct->status & IPS_NAT_MASK) {
+ ret = set_ras_addr(pskb, ct, ctinfo, data,
+ &irr->rasAddress, 1);
+ if (ret < 0)
+ return -1;
+ }
+
+ set_sig_addr = rcu_dereference(set_sig_addr_hook);
+ if (set_sig_addr && ct->status & IPS_NAT_MASK) {
+ ret = set_sig_addr(pskb, ct, ctinfo, data,
+ irr->callSignalAddress.item,
+ irr->callSignalAddress.count);
+ if (ret < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+static int process_ras(struct sk_buff **pskb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, RasMessage *ras)
+{
+ switch (ras->choice) {
+ case eRasMessage_gatekeeperRequest:
+ return process_grq(pskb, ct, ctinfo, data,
+ &ras->gatekeeperRequest);
+ case eRasMessage_gatekeeperConfirm:
+ return process_gcf(pskb, ct, ctinfo, data,
+ &ras->gatekeeperConfirm);
+ case eRasMessage_registrationRequest:
+ return process_rrq(pskb, ct, ctinfo, data,
+ &ras->registrationRequest);
+ case eRasMessage_registrationConfirm:
+ return process_rcf(pskb, ct, ctinfo, data,
+ &ras->registrationConfirm);
+ case eRasMessage_unregistrationRequest:
+ return process_urq(pskb, ct, ctinfo, data,
+ &ras->unregistrationRequest);
+ case eRasMessage_admissionRequest:
+ return process_arq(pskb, ct, ctinfo, data,
+ &ras->admissionRequest);
+ case eRasMessage_admissionConfirm:
+ return process_acf(pskb, ct, ctinfo, data,
+ &ras->admissionConfirm);
+ case eRasMessage_locationRequest:
+ return process_lrq(pskb, ct, ctinfo, data,
+ &ras->locationRequest);
+ case eRasMessage_locationConfirm:
+ return process_lcf(pskb, ct, ctinfo, data,
+ &ras->locationConfirm);
+ case eRasMessage_infoRequestResponse:
+ return process_irr(pskb, ct, ctinfo, data,
+ &ras->infoRequestResponse);
+ default:
+ DEBUGP("nf_ct_ras: RAS message %d\n", ras->choice);
+ break;
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+static int ras_help(struct sk_buff **pskb, unsigned int protoff,
+ struct nf_conn *ct, enum ip_conntrack_info ctinfo)
+{
+ static RasMessage ras;
+ unsigned char *data;
+ int datalen = 0;
+ int ret;
+
+ DEBUGP("nf_ct_ras: skblen = %u\n", (*pskb)->len);
+
+ spin_lock_bh(&nf_h323_lock);
+
+ /* Get UDP data */
+ data = get_udp_data(pskb, protoff, &datalen);
+ if (data == NULL)
+ goto accept;
+ DEBUGP("nf_ct_ras: RAS message len=%d ", datalen);
+ NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
+
+ /* Decode RAS message */
+ ret = DecodeRasMessage(data, datalen, &ras);
+ if (ret < 0) {
+ if (net_ratelimit())
+ printk("nf_ct_ras: decoding error: %s\n",
+ ret == H323_ERROR_BOUND ?
+ "out of bound" : "out of range");
+ goto accept;
+ }
+
+ /* Process RAS message */
+ if (process_ras(pskb, ct, ctinfo, &data, &ras) < 0)
+ goto drop;
+
+ accept:
+ spin_unlock_bh(&nf_h323_lock);
+ return NF_ACCEPT;
+
+ drop:
+ spin_unlock_bh(&nf_h323_lock);
+ if (net_ratelimit())
+ printk("nf_ct_ras: packet dropped\n");
+ return NF_DROP;
+}
+
+/****************************************************************************/
+static struct nf_conntrack_helper nf_conntrack_helper_ras[] __read_mostly = {
+ {
+ .name = "RAS",
+ .me = THIS_MODULE,
+ .max_expected = 32,
+ .timeout = 240,
+ .tuple.src.l3num = AF_INET,
+ .tuple.src.u.udp.port = __constant_htons(RAS_PORT),
+ .tuple.dst.protonum = IPPROTO_UDP,
+ .mask.src.l3num = 0xFFFF,
+ .mask.src.u.udp.port = __constant_htons(0xFFFF),
+ .mask.dst.protonum = 0xFF,
+ .help = ras_help,
+ },
+ {
+ .name = "RAS",
+ .me = THIS_MODULE,
+ .max_expected = 32,
+ .timeout = 240,
+ .tuple.src.l3num = AF_INET6,
+ .tuple.src.u.udp.port = __constant_htons(RAS_PORT),
+ .tuple.dst.protonum = IPPROTO_UDP,
+ .mask.src.l3num = 0xFFFF,
+ .mask.src.u.udp.port = __constant_htons(0xFFFF),
+ .mask.dst.protonum = 0xFF,
+ .help = ras_help,
+ },
+};
+
+/****************************************************************************/
+static void __exit nf_conntrack_h323_fini(void)
+{
+ nf_conntrack_helper_unregister(&nf_conntrack_helper_ras[1]);
+ nf_conntrack_helper_unregister(&nf_conntrack_helper_ras[0]);
+ nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[1]);
+ nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[0]);
+ kfree(h323_buffer);
+ DEBUGP("nf_ct_h323: fini\n");
+}
+
+/****************************************************************************/
+static int __init nf_conntrack_h323_init(void)
+{
+ int ret;
+
+ h323_buffer = kmalloc(65536, GFP_KERNEL);
+ if (!h323_buffer)
+ return -ENOMEM;
+ ret = nf_conntrack_helper_register(&nf_conntrack_helper_q931[0]);
+ if (ret < 0)
+ goto err1;
+ ret = nf_conntrack_helper_register(&nf_conntrack_helper_q931[1]);
+ if (ret < 0)
+ goto err2;
+ ret = nf_conntrack_helper_register(&nf_conntrack_helper_ras[0]);
+ if (ret < 0)
+ goto err3;
+ ret = nf_conntrack_helper_register(&nf_conntrack_helper_ras[1]);
+ if (ret < 0)
+ goto err4;
+ DEBUGP("nf_ct_h323: init success\n");
+ return 0;
+
+err4:
+ nf_conntrack_helper_unregister(&nf_conntrack_helper_ras[0]);
+err3:
+ nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[1]);
+err2:
+ nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[0]);
+err1:
+ return ret;
+}
+
+/****************************************************************************/
+module_init(nf_conntrack_h323_init);
+module_exit(nf_conntrack_h323_fini);
+
+EXPORT_SYMBOL_GPL(get_h225_addr);
+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_callforwarding_hook);
+EXPORT_SYMBOL_GPL(nat_q931_hook);
+
+MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
+MODULE_DESCRIPTION("H.323 connection tracking helper");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ip_conntrack_h323");
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c b/net/netfilter/nf_conntrack_h323_types.c
index 4b359618bedd..4c6f8b3b1208 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c
+++ b/net/netfilter/nf_conntrack_h323_types.c
@@ -36,7 +36,8 @@ static field_t _TransportAddress_ipxAddress[] = { /* SEQUENCE */
};
static field_t _TransportAddress_ip6Address[] = { /* SEQUENCE */
- {FNAME("ip") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
+ {FNAME("ip") OCTSTR, FIXD, 16, 0, DECODE,
+ offsetof(TransportAddress_ip6Address, ip6), NULL},
{FNAME("port") INT, WORD, 0, 0, SKIP, 0, NULL},
};
@@ -65,8 +66,8 @@ static field_t _TransportAddress[] = { /* CHOICE */
_TransportAddress_ipSourceRoute},
{FNAME("ipxAddress") SEQ, 0, 3, 3, SKIP, 0,
_TransportAddress_ipxAddress},
- {FNAME("ip6Address") SEQ, 0, 2, 2, SKIP | EXT, 0,
- _TransportAddress_ip6Address},
+ {FNAME("ip6Address") SEQ, 0, 2, 2, DECODE | EXT,
+ offsetof(TransportAddress, ip6Address), _TransportAddress_ip6Address},
{FNAME("netBios") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
{FNAME("nsap") OCTSTR, 5, 1, 0, SKIP, 0, NULL},
{FNAME("nonStandardAddress") SEQ, 0, 2, 2, SKIP, 0,
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
new file mode 100644
index 000000000000..0743be4434b0
--- /dev/null
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -0,0 +1,155 @@
+/* Helper handling for netfilter. */
+
+/* (C) 1999-2001 Paul `Rusty' Russell
+ * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
+ * (C) 2003,2004 USAGI/WIDE Project <http://www.linux-ipv6.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/types.h>
+#include <linux/netfilter.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/vmalloc.h>
+#include <linux/stddef.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_l3proto.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
+#include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_conntrack_core.h>
+
+static __read_mostly LIST_HEAD(helpers);
+
+struct nf_conntrack_helper *
+__nf_ct_helper_find(const struct nf_conntrack_tuple *tuple)
+{
+ struct nf_conntrack_helper *h;
+
+ list_for_each_entry(h, &helpers, list) {
+ if (nf_ct_tuple_mask_cmp(tuple, &h->tuple, &h->mask))
+ return h;
+ }
+ return NULL;
+}
+
+struct nf_conntrack_helper *
+nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple)
+{
+ struct nf_conntrack_helper *helper;
+
+ /* need nf_conntrack_lock to assure that helper exists until
+ * try_module_get() is called */
+ read_lock_bh(&nf_conntrack_lock);
+
+ helper = __nf_ct_helper_find(tuple);
+ if (helper) {
+ /* need to increase module usage count to assure helper will
+ * not go away while the caller is e.g. busy putting a
+ * conntrack in the hash that uses the helper */
+ if (!try_module_get(helper->me))
+ helper = NULL;
+ }
+
+ read_unlock_bh(&nf_conntrack_lock);
+
+ return helper;
+}
+EXPORT_SYMBOL_GPL(nf_ct_helper_find_get);
+
+void nf_ct_helper_put(struct nf_conntrack_helper *helper)
+{
+ module_put(helper->me);
+}
+EXPORT_SYMBOL_GPL(nf_ct_helper_put);
+
+struct nf_conntrack_helper *
+__nf_conntrack_helper_find_byname(const char *name)
+{
+ struct nf_conntrack_helper *h;
+
+ list_for_each_entry(h, &helpers, list) {
+ if (!strcmp(h->name, name))
+ return h;
+ }
+
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(__nf_conntrack_helper_find_byname);
+
+static inline int unhelp(struct nf_conntrack_tuple_hash *i,
+ const struct nf_conntrack_helper *me)
+{
+ struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(i);
+ struct nf_conn_help *help = nfct_help(ct);
+
+ if (help && help->helper == me) {
+ nf_conntrack_event(IPCT_HELPER, ct);
+ help->helper = NULL;
+ }
+ return 0;
+}
+
+int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
+{
+ int size, ret;
+
+ BUG_ON(me->timeout == 0);
+
+ size = ALIGN(sizeof(struct nf_conn), __alignof__(struct nf_conn_help)) +
+ sizeof(struct nf_conn_help);
+ ret = nf_conntrack_register_cache(NF_CT_F_HELP, "nf_conntrack:help",
+ size);
+ if (ret < 0) {
+ printk(KERN_ERR "nf_conntrack_helper_register: Unable to create slab cache for conntracks\n");
+ return ret;
+ }
+ write_lock_bh(&nf_conntrack_lock);
+ list_add(&me->list, &helpers);
+ write_unlock_bh(&nf_conntrack_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(nf_conntrack_helper_register);
+
+void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me)
+{
+ unsigned int i;
+ struct nf_conntrack_tuple_hash *h;
+ struct nf_conntrack_expect *exp, *tmp;
+
+ /* Need write lock here, to delete helper. */
+ write_lock_bh(&nf_conntrack_lock);
+ list_del(&me->list);
+
+ /* Get rid of expectations */
+ list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, list) {
+ struct nf_conn_help *help = nfct_help(exp->master);
+ if ((help->helper == me || exp->helper == me) &&
+ del_timer(&exp->timeout)) {
+ nf_ct_unlink_expect(exp);
+ nf_conntrack_expect_put(exp);
+ }
+ }
+
+ /* Get rid of expecteds, set helpers to NULL. */
+ list_for_each_entry(h, &unconfirmed, list)
+ unhelp(h, me);
+ for (i = 0; i < nf_conntrack_htable_size; i++) {
+ list_for_each_entry(h, &nf_conntrack_hash[i], list)
+ unhelp(h, me);
+ }
+ write_unlock_bh(&nf_conntrack_lock);
+
+ /* Someone could be still looking at the helper in a bh. */
+ synchronize_net();
+}
+EXPORT_SYMBOL_GPL(nf_conntrack_helper_unregister);
diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c
new file mode 100644
index 000000000000..ed01db634399
--- /dev/null
+++ b/net/netfilter/nf_conntrack_irc.c
@@ -0,0 +1,281 @@
+/* IRC extension for IP connection tracking, Version 1.21
+ * (C) 2000-2002 by Harald Welte <laforge@gnumonks.org>
+ * based on RR's ip_conntrack_ftp.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.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/skbuff.h>
+#include <linux/in.h>
+#include <linux/tcp.h>
+#include <linux/netfilter.h>
+
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_expect.h>
+#include <net/netfilter/nf_conntrack_helper.h>
+#include <linux/netfilter/nf_conntrack_irc.h>
+
+#define MAX_PORTS 8
+static unsigned short ports[MAX_PORTS];
+static int ports_c;
+static unsigned int max_dcc_channels = 8;
+static unsigned int dcc_timeout __read_mostly = 300;
+/* This is slow, but it's simple. --RR */
+static char *irc_buffer;
+static DEFINE_SPINLOCK(irc_buffer_lock);
+
+unsigned int (*nf_nat_irc_hook)(struct sk_buff **pskb,
+ enum ip_conntrack_info ctinfo,
+ unsigned int matchoff,
+ unsigned int matchlen,
+ struct nf_conntrack_expect *exp) __read_mostly;
+EXPORT_SYMBOL_GPL(nf_nat_irc_hook);
+
+MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
+MODULE_DESCRIPTION("IRC (DCC) connection tracking helper");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ip_conntrack_irc");
+
+module_param_array(ports, ushort, &ports_c, 0400);
+MODULE_PARM_DESC(ports, "port numbers of IRC servers");
+module_param(max_dcc_channels, uint, 0400);
+MODULE_PARM_DESC(max_dcc_channels, "max number of expected DCC channels per "
+ "IRC session");
+module_param(dcc_timeout, uint, 0400);
+MODULE_PARM_DESC(dcc_timeout, "timeout on for unestablished DCC channels");
+
+static const char *dccprotos[] = {
+ "SEND ", "CHAT ", "MOVE ", "TSEND ", "SCHAT "
+};
+
+#define MINMATCHLEN 5
+
+#if 0
+#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s:" format, \
+ __FILE__, __FUNCTION__ , ## args)
+#else
+#define DEBUGP(format, args...)
+#endif
+
+/* tries to get the ip_addr and port out of a dcc command
+ * return value: -1 on failure, 0 on success
+ * data pointer to first byte of DCC command data
+ * data_end pointer to last byte of dcc command data
+ * ip returns parsed ip of dcc command
+ * port returns parsed port of dcc command
+ * ad_beg_p returns pointer to first byte of addr data
+ * ad_end_p returns pointer to last byte of addr data
+ */
+static int parse_dcc(char *data, char *data_end, u_int32_t *ip,
+ u_int16_t *port, char **ad_beg_p, char **ad_end_p)
+{
+ /* at least 12: "AAAAAAAA P\1\n" */
+ while (*data++ != ' ')
+ if (data > data_end - 12)
+ return -1;
+
+ *ad_beg_p = data;
+ *ip = simple_strtoul(data, &data, 10);
+
+ /* skip blanks between ip and port */
+ while (*data == ' ') {
+ if (data >= data_end)
+ return -1;
+ data++;
+ }
+
+ *port = simple_strtoul(data, &data, 10);
+ *ad_end_p = data;
+
+ return 0;
+}
+
+static int help(struct sk_buff **pskb, unsigned int protoff,
+ struct nf_conn *ct, enum ip_conntrack_info ctinfo)
+{
+ unsigned int dataoff;
+ struct tcphdr _tcph, *th;
+ char *data, *data_limit, *ib_ptr;
+ int dir = CTINFO2DIR(ctinfo);
+ struct nf_conntrack_expect *exp;
+ struct nf_conntrack_tuple *tuple;
+ u_int32_t dcc_ip;
+ u_int16_t dcc_port;
+ __be16 port;
+ int i, ret = NF_ACCEPT;
+ char *addr_beg_p, *addr_end_p;
+ typeof(nf_nat_irc_hook) nf_nat_irc;
+
+ /* If packet is coming from IRC server */
+ if (dir == IP_CT_DIR_REPLY)
+ return NF_ACCEPT;
+
+ /* Until there's been traffic both ways, don't look in packets. */
+ if (ctinfo != IP_CT_ESTABLISHED &&
+ ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY)
+ return NF_ACCEPT;
+
+ /* Not a full tcp header? */
+ th = skb_header_pointer(*pskb, protoff, sizeof(_tcph), &_tcph);
+ if (th == NULL)
+ return NF_ACCEPT;
+
+ /* No data? */
+ dataoff = protoff + th->doff*4;
+ if (dataoff >= (*pskb)->len)
+ return NF_ACCEPT;
+
+ spin_lock_bh(&irc_buffer_lock);
+ ib_ptr = skb_header_pointer(*pskb, dataoff, (*pskb)->len - dataoff,
+ irc_buffer);
+ BUG_ON(ib_ptr == NULL);
+
+ data = ib_ptr;
+ data_limit = ib_ptr + (*pskb)->len - dataoff;
+
+ /* strlen("\1DCC SENT t AAAAAAAA P\1\n")=24
+ * 5+MINMATCHLEN+strlen("t AAAAAAAA P\1\n")=14 */
+ while (data < data_limit - (19 + MINMATCHLEN)) {
+ if (memcmp(data, "\1DCC ", 5)) {
+ data++;
+ continue;
+ }
+ data += 5;
+ /* we have at least (19+MINMATCHLEN)-5 bytes valid data left */
+
+ DEBUGP("DCC found in master %u.%u.%u.%u:%u %u.%u.%u.%u:%u...\n",
+ NIPQUAD(iph->saddr), ntohs(th->source),
+ NIPQUAD(iph->daddr), ntohs(th->dest));
+
+ for (i = 0; i < ARRAY_SIZE(dccprotos); i++) {
+ if (memcmp(data, dccprotos[i], strlen(dccprotos[i]))) {
+ /* no match */
+ continue;
+ }
+ data += strlen(dccprotos[i]);
+ DEBUGP("DCC %s detected\n", dccprotos[i]);
+
+ /* we have at least
+ * (19+MINMATCHLEN)-5-dccprotos[i].matchlen bytes valid
+ * data left (== 14/13 bytes) */
+ if (parse_dcc((char *)data, data_limit, &dcc_ip,
+ &dcc_port, &addr_beg_p, &addr_end_p)) {
+ DEBUGP("unable to parse dcc command\n");
+ continue;
+ }
+ DEBUGP("DCC bound ip/port: %u.%u.%u.%u:%u\n",
+ HIPQUAD(dcc_ip), dcc_port);
+
+ /* dcc_ip can be the internal OR external (NAT'ed) IP */
+ tuple = &ct->tuplehash[dir].tuple;
+ if (tuple->src.u3.ip != htonl(dcc_ip) &&
+ tuple->dst.u3.ip != htonl(dcc_ip)) {
+ if (net_ratelimit())
+ printk(KERN_WARNING
+ "Forged DCC command from "
+ "%u.%u.%u.%u: %u.%u.%u.%u:%u\n",
+ NIPQUAD(tuple->src.u3.ip),
+ HIPQUAD(dcc_ip), dcc_port);
+ continue;
+ }
+
+ exp = nf_conntrack_expect_alloc(ct);
+ if (exp == NULL) {
+ ret = NF_DROP;
+ goto out;
+ }
+ tuple = &ct->tuplehash[!dir].tuple;
+ port = htons(dcc_port);
+ nf_conntrack_expect_init(exp, tuple->src.l3num,
+ NULL, &tuple->dst.u3,
+ IPPROTO_TCP, NULL, &port);
+
+ nf_nat_irc = rcu_dereference(nf_nat_irc_hook);
+ if (nf_nat_irc && ct->status & IPS_NAT_MASK)
+ ret = nf_nat_irc(pskb, ctinfo,
+ addr_beg_p - ib_ptr,
+ addr_end_p - addr_beg_p,
+ exp);
+ else if (nf_conntrack_expect_related(exp) != 0)
+ ret = NF_DROP;
+ nf_conntrack_expect_put(exp);
+ goto out;
+ }
+ }
+ out:
+ spin_unlock_bh(&irc_buffer_lock);
+ return ret;
+}
+
+static struct nf_conntrack_helper irc[MAX_PORTS] __read_mostly;
+static char irc_names[MAX_PORTS][sizeof("irc-65535")] __read_mostly;
+
+static void nf_conntrack_irc_fini(void);
+
+static int __init nf_conntrack_irc_init(void)
+{
+ int i, ret;
+ char *tmpname;
+
+ if (max_dcc_channels < 1) {
+ printk("nf_ct_irc: max_dcc_channels must not be zero\n");
+ return -EINVAL;
+ }
+
+ irc_buffer = kmalloc(65536, GFP_KERNEL);
+ if (!irc_buffer)
+ return -ENOMEM;
+
+ /* If no port given, default to standard irc port */
+ if (ports_c == 0)
+ ports[ports_c++] = IRC_PORT;
+
+ for (i = 0; i < ports_c; i++) {
+ irc[i].tuple.src.l3num = AF_INET;
+ irc[i].tuple.src.u.tcp.port = htons(ports[i]);
+ irc[i].tuple.dst.protonum = IPPROTO_TCP;
+ irc[i].mask.src.l3num = 0xFFFF;
+ irc[i].mask.src.u.tcp.port = htons(0xFFFF);
+ irc[i].mask.dst.protonum = 0xFF;
+ irc[i].max_expected = max_dcc_channels;
+ irc[i].timeout = dcc_timeout;
+ irc[i].me = THIS_MODULE;
+ irc[i].help = help;
+
+ tmpname = &irc_names[i][0];
+ if (ports[i] == IRC_PORT)
+ sprintf(tmpname, "irc");
+ else
+ sprintf(tmpname, "irc-%u", i);
+ irc[i].name = tmpname;
+
+ ret = nf_conntrack_helper_register(&irc[i]);
+ if (ret) {
+ printk("nf_ct_irc: failed to register helper "
+ "for pf: %u port: %u\n",
+ irc[i].tuple.src.l3num, ports[i]);
+ nf_conntrack_irc_fini();
+ return ret;
+ }
+ }
+ return 0;
+}
+
+/* This function is intentionally _NOT_ defined as __exit, because
+ * it is needed by the init function */
+static void nf_conntrack_irc_fini(void)
+{
+ int i;
+
+ for (i = 0; i < ports_c; i++)
+ nf_conntrack_helper_unregister(&irc[i]);
+ kfree(irc_buffer);
+}
+
+module_init(nf_conntrack_irc_init);
+module_exit(nf_conntrack_irc_fini);
diff --git a/net/netfilter/nf_conntrack_l3proto_generic.c b/net/netfilter/nf_conntrack_l3proto_generic.c
index 21e0bc91cf23..a3d31c3ac8e6 100644
--- a/net/netfilter/nf_conntrack_l3proto_generic.c
+++ b/net/netfilter/nf_conntrack_l3proto_generic.c
@@ -26,7 +26,7 @@
#include <linux/netfilter_ipv4.h>
#include <net/netfilter/nf_conntrack.h>
-#include <net/netfilter/nf_conntrack_protocol.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_l3proto.h>
#include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
@@ -37,8 +37,6 @@
#define DEBUGP(format, args...)
#endif
-DECLARE_PER_CPU(struct nf_conntrack_stat, nf_conntrack_stat);
-
static int generic_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
struct nf_conntrack_tuple *tuple)
{
@@ -84,7 +82,7 @@ static u_int32_t generic_get_features(const struct nf_conntrack_tuple *tuple)
return NF_CT_F_BASIC;
}
-struct nf_conntrack_l3proto nf_conntrack_generic_l3proto = {
+struct nf_conntrack_l3proto nf_conntrack_l3proto_generic = {
.l3proto = PF_UNSPEC,
.name = "unknown",
.pkt_to_tuple = generic_pkt_to_tuple,
@@ -94,3 +92,4 @@ struct nf_conntrack_l3proto nf_conntrack_generic_l3proto = {
.prepare = generic_prepare,
.get_features = generic_get_features,
};
+EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_generic);
diff --git a/net/netfilter/nf_conntrack_netbios_ns.c b/net/netfilter/nf_conntrack_netbios_ns.c
new file mode 100644
index 000000000000..a5b234e444dc
--- /dev/null
+++ b/net/netfilter/nf_conntrack_netbios_ns.c
@@ -0,0 +1,126 @@
+/*
+ * NetBIOS name service broadcast connection tracking helper
+ *
+ * (c) 2005 Patrick McHardy <kaber@trash.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+/*
+ * This helper tracks locally originating NetBIOS name service
+ * requests by issuing permanent expectations (valid until
+ * timing out) matching all reply connections from the
+ * destination network. The only NetBIOS specific thing is
+ * actually the port number.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/if_addr.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/netfilter.h>
+#include <net/route.h>
+
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_conntrack_expect.h>
+
+#define NMBD_PORT 137
+
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_DESCRIPTION("NetBIOS name service broadcast connection tracking helper");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ip_conntrack_netbios_ns");
+
+static unsigned int timeout __read_mostly = 3;
+module_param(timeout, uint, 0400);
+MODULE_PARM_DESC(timeout, "timeout for master connection/replies in seconds");
+
+static int help(struct sk_buff **pskb, unsigned int protoff,
+ struct nf_conn *ct, enum ip_conntrack_info ctinfo)
+{
+ struct nf_conntrack_expect *exp;
+ struct iphdr *iph = (*pskb)->nh.iph;
+ struct rtable *rt = (struct rtable *)(*pskb)->dst;
+ struct in_device *in_dev;
+ __be32 mask = 0;
+
+ /* we're only interested in locally generated packets */
+ if ((*pskb)->sk == NULL)
+ goto out;
+ if (rt == NULL || !(rt->rt_flags & RTCF_BROADCAST))
+ goto out;
+ if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL)
+ goto out;
+
+ rcu_read_lock();
+ in_dev = __in_dev_get_rcu(rt->u.dst.dev);
+ if (in_dev != NULL) {
+ for_primary_ifa(in_dev) {
+ if (ifa->ifa_broadcast == iph->daddr) {
+ mask = ifa->ifa_mask;
+ break;
+ }
+ } endfor_ifa(in_dev);
+ }
+ rcu_read_unlock();
+
+ if (mask == 0)
+ goto out;
+
+ exp = nf_conntrack_expect_alloc(ct);
+ if (exp == NULL)
+ goto out;
+
+ exp->tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
+ exp->tuple.src.u.udp.port = htons(NMBD_PORT);
+
+ exp->mask.src.u3.ip = mask;
+ exp->mask.src.u.udp.port = htons(0xFFFF);
+ exp->mask.dst.u3.ip = htonl(0xFFFFFFFF);
+ exp->mask.dst.u.udp.port = htons(0xFFFF);
+ exp->mask.dst.protonum = 0xFF;
+
+ exp->expectfn = NULL;
+ exp->flags = NF_CT_EXPECT_PERMANENT;
+
+ nf_conntrack_expect_related(exp);
+ nf_conntrack_expect_put(exp);
+
+ nf_ct_refresh(ct, *pskb, timeout * HZ);
+out:
+ return NF_ACCEPT;
+}
+
+static struct nf_conntrack_helper helper __read_mostly = {
+ .name = "netbios-ns",
+ .tuple.src.l3num = AF_INET,
+ .tuple.src.u.udp.port = __constant_htons(NMBD_PORT),
+ .tuple.dst.protonum = IPPROTO_UDP,
+ .mask.src.l3num = 0xFFFF,
+ .mask.src.u.udp.port = __constant_htons(0xFFFF),
+ .mask.dst.protonum = 0xFF,
+ .max_expected = 1,
+ .me = THIS_MODULE,
+ .help = help,
+};
+
+static int __init nf_conntrack_netbios_ns_init(void)
+{
+ helper.timeout = timeout;
+ return nf_conntrack_helper_register(&helper);
+}
+
+static void __exit nf_conntrack_netbios_ns_fini(void)
+{
+ nf_conntrack_helper_unregister(&helper);
+}
+
+module_init(nf_conntrack_netbios_ns_init);
+module_exit(nf_conntrack_netbios_ns_fini);
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index bd0156a28ecd..bd1d2de75e45 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -35,10 +35,15 @@
#include <linux/netfilter.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_core.h>
+#include <net/netfilter/nf_conntrack_expect.h>
#include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_l3proto.h>
-#include <net/netfilter/nf_conntrack_protocol.h>
-#include <linux/netfilter_ipv4/ip_nat_protocol.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
+#include <net/netfilter/nf_conntrack_tuple.h>
+#ifdef CONFIG_NF_NAT_NEEDED
+#include <net/netfilter/nf_nat_core.h>
+#include <net/netfilter/nf_nat_protocol.h>
+#endif
#include <linux/netfilter/nfnetlink.h>
#include <linux/netfilter/nfnetlink_conntrack.h>
@@ -50,15 +55,15 @@ static char __initdata version[] = "0.93";
static inline int
ctnetlink_dump_tuples_proto(struct sk_buff *skb,
const struct nf_conntrack_tuple *tuple,
- struct nf_conntrack_protocol *proto)
+ struct nf_conntrack_l4proto *l4proto)
{
int ret = 0;
struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO);
NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum);
- if (likely(proto->tuple_to_nfattr))
- ret = proto->tuple_to_nfattr(skb, tuple);
+ if (likely(l4proto->tuple_to_nfattr))
+ ret = l4proto->tuple_to_nfattr(skb, tuple);
NFA_NEST_END(skb, nest_parms);
@@ -93,7 +98,7 @@ ctnetlink_dump_tuples(struct sk_buff *skb,
{
int ret;
struct nf_conntrack_l3proto *l3proto;
- struct nf_conntrack_protocol *proto;
+ struct nf_conntrack_l4proto *l4proto;
l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
ret = ctnetlink_dump_tuples_ip(skb, tuple, l3proto);
@@ -102,9 +107,9 @@ ctnetlink_dump_tuples(struct sk_buff *skb,
if (unlikely(ret < 0))
return ret;
- proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum);
- ret = ctnetlink_dump_tuples_proto(skb, tuple, proto);
- nf_ct_proto_put(proto);
+ l4proto = nf_ct_l4proto_find_get(tuple->src.l3num, tuple->dst.protonum);
+ ret = ctnetlink_dump_tuples_proto(skb, tuple, l4proto);
+ nf_ct_l4proto_put(l4proto);
return ret;
}
@@ -112,7 +117,7 @@ ctnetlink_dump_tuples(struct sk_buff *skb,
static inline int
ctnetlink_dump_status(struct sk_buff *skb, const struct nf_conn *ct)
{
- u_int32_t status = htonl((u_int32_t) ct->status);
+ __be32 status = htonl((u_int32_t) ct->status);
NFA_PUT(skb, CTA_STATUS, sizeof(status), &status);
return 0;
@@ -124,7 +129,7 @@ static inline int
ctnetlink_dump_timeout(struct sk_buff *skb, const struct nf_conn *ct)
{
long timeout_l = ct->timeout.expires - jiffies;
- u_int32_t timeout;
+ __be32 timeout;
if (timeout_l < 0)
timeout = 0;
@@ -141,26 +146,27 @@ nfattr_failure:
static inline int
ctnetlink_dump_protoinfo(struct sk_buff *skb, const struct nf_conn *ct)
{
- struct nf_conntrack_protocol *proto = nf_ct_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num, ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum);
+ struct nf_conntrack_l4proto *l4proto = nf_ct_l4proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num, ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum);
struct nfattr *nest_proto;
int ret;
- if (!proto->to_nfattr) {
- nf_ct_proto_put(proto);
+ if (!l4proto->to_nfattr) {
+ nf_ct_l4proto_put(l4proto);
return 0;
}
nest_proto = NFA_NEST(skb, CTA_PROTOINFO);
- ret = proto->to_nfattr(skb, nest_proto, ct);
+ ret = l4proto->to_nfattr(skb, nest_proto, ct);
- nf_ct_proto_put(proto);
+ nf_ct_l4proto_put(l4proto);
NFA_NEST_END(skb, nest_proto);
return ret;
nfattr_failure:
+ nf_ct_l4proto_put(l4proto);
return -1;
}
@@ -194,7 +200,7 @@ ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *ct,
{
enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG;
struct nfattr *nest_count = NFA_NEST(skb, type);
- u_int32_t tmp;
+ __be32 tmp;
tmp = htonl(ct->counters[dir].packets);
NFA_PUT(skb, CTA_COUNTERS32_PACKETS, sizeof(u_int32_t), &tmp);
@@ -217,7 +223,7 @@ nfattr_failure:
static inline int
ctnetlink_dump_mark(struct sk_buff *skb, const struct nf_conn *ct)
{
- u_int32_t mark = htonl(ct->mark);
+ __be32 mark = htonl(ct->mark);
NFA_PUT(skb, CTA_MARK, sizeof(u_int32_t), &mark);
return 0;
@@ -232,7 +238,7 @@ nfattr_failure:
static inline int
ctnetlink_dump_id(struct sk_buff *skb, const struct nf_conn *ct)
{
- u_int32_t id = htonl(ct->id);
+ __be32 id = htonl(ct->id);
NFA_PUT(skb, CTA_ID, sizeof(u_int32_t), &id);
return 0;
@@ -243,7 +249,7 @@ nfattr_failure:
static inline int
ctnetlink_dump_use(struct sk_buff *skb, const struct nf_conn *ct)
{
- u_int32_t use = htonl(atomic_read(&ct->ct_general.use));
+ __be32 use = htonl(atomic_read(&ct->ct_general.use));
NFA_PUT(skb, CTA_USE, sizeof(u_int32_t), &use);
return 0;
@@ -329,8 +335,6 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
} else if (events & (IPCT_NEW | IPCT_RELATED)) {
type = IPCTNL_MSG_CT_NEW;
flags = NLM_F_CREATE|NLM_F_EXCL;
- /* dump everything */
- events = ~0UL;
group = NFNLGRP_CONNTRACK_NEW;
} else if (events & (IPCT_STATUS | IPCT_PROTOINFO)) {
type = IPCTNL_MSG_CT_NEW;
@@ -365,28 +369,35 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_REPLY)) < 0)
goto nfattr_failure;
NFA_NEST_END(skb, nest_parms);
-
- /* NAT stuff is now a status flag */
- if ((events & IPCT_STATUS || events & IPCT_NATINFO)
- && ctnetlink_dump_status(skb, ct) < 0)
- goto nfattr_failure;
- if (events & IPCT_REFRESH
- && ctnetlink_dump_timeout(skb, ct) < 0)
- goto nfattr_failure;
- if (events & IPCT_PROTOINFO
- && ctnetlink_dump_protoinfo(skb, ct) < 0)
- goto nfattr_failure;
- if (events & IPCT_HELPINFO
- && ctnetlink_dump_helpinfo(skb, ct) < 0)
- goto nfattr_failure;
- if (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
- ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0)
- goto nfattr_failure;
+ if (events & IPCT_DESTROY) {
+ if (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
+ ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0)
+ goto nfattr_failure;
+ } else {
+ if (ctnetlink_dump_status(skb, ct) < 0)
+ goto nfattr_failure;
- if (events & IPCT_MARK
- && ctnetlink_dump_mark(skb, ct) < 0)
- goto nfattr_failure;
+ if (ctnetlink_dump_timeout(skb, ct) < 0)
+ goto nfattr_failure;
+
+ if (events & IPCT_PROTOINFO
+ && ctnetlink_dump_protoinfo(skb, ct) < 0)
+ goto nfattr_failure;
+
+ if ((events & IPCT_HELPER || nfct_help(ct))
+ && ctnetlink_dump_helpinfo(skb, ct) < 0)
+ goto nfattr_failure;
+
+ if ((events & IPCT_MARK || ct->mark)
+ && ctnetlink_dump_mark(skb, ct) < 0)
+ goto nfattr_failure;
+
+ if (events & IPCT_COUNTER_FILLING &&
+ (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
+ ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0))
+ goto nfattr_failure;
+ }
nlh->nlmsg_len = skb->tail - b;
nfnetlink_send(skb, 0, group, 0);
@@ -423,7 +434,7 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
restart:
list_for_each_prev(i, &nf_conntrack_hash[cb->args[0]]) {
h = (struct nf_conntrack_tuple_hash *) i;
- if (DIRECTION(h) != IP_CT_DIR_ORIGINAL)
+ if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL)
continue;
ct = nf_ct_tuplehash_to_ctrack(h);
/* Dump entries of a given L3 protocol number.
@@ -491,7 +502,7 @@ ctnetlink_parse_tuple_proto(struct nfattr *attr,
struct nf_conntrack_tuple *tuple)
{
struct nfattr *tb[CTA_PROTO_MAX];
- struct nf_conntrack_protocol *proto;
+ struct nf_conntrack_l4proto *l4proto;
int ret = 0;
nfattr_parse_nested(tb, CTA_PROTO_MAX, attr);
@@ -503,12 +514,12 @@ ctnetlink_parse_tuple_proto(struct nfattr *attr,
return -EINVAL;
tuple->dst.protonum = *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_NUM-1]);
- proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum);
+ l4proto = nf_ct_l4proto_find_get(tuple->src.l3num, tuple->dst.protonum);
- if (likely(proto->nfattr_to_tuple))
- ret = proto->nfattr_to_tuple(tb, tuple);
+ if (likely(l4proto->nfattr_to_tuple))
+ ret = l4proto->nfattr_to_tuple(tb, tuple);
- nf_ct_proto_put(proto);
+ nf_ct_l4proto_put(l4proto);
return ret;
}
@@ -549,28 +560,28 @@ ctnetlink_parse_tuple(struct nfattr *cda[], struct nf_conntrack_tuple *tuple,
return 0;
}
-#ifdef CONFIG_IP_NF_NAT_NEEDED
+#ifdef CONFIG_NF_NAT_NEEDED
static const size_t cta_min_protonat[CTA_PROTONAT_MAX] = {
[CTA_PROTONAT_PORT_MIN-1] = sizeof(u_int16_t),
[CTA_PROTONAT_PORT_MAX-1] = sizeof(u_int16_t),
};
-static int ctnetlink_parse_nat_proto(struct nfattr *attr,
+static int nfnetlink_parse_nat_proto(struct nfattr *attr,
const struct nf_conn *ct,
- struct ip_nat_range *range)
+ struct nf_nat_range *range)
{
struct nfattr *tb[CTA_PROTONAT_MAX];
- struct ip_nat_protocol *npt;
+ struct nf_nat_protocol *npt;
nfattr_parse_nested(tb, CTA_PROTONAT_MAX, attr);
if (nfattr_bad_size(tb, CTA_PROTONAT_MAX, cta_min_protonat))
return -EINVAL;
- npt = ip_nat_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum);
+ npt = nf_nat_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum);
if (!npt->nfattr_to_range) {
- ip_nat_proto_put(npt);
+ nf_nat_proto_put(npt);
return 0;
}
@@ -578,7 +589,7 @@ static int ctnetlink_parse_nat_proto(struct nfattr *attr,
if (npt->nfattr_to_range(tb, range) > 0)
range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
- ip_nat_proto_put(npt);
+ nf_nat_proto_put(npt);
return 0;
}
@@ -589,8 +600,8 @@ static const size_t cta_min_nat[CTA_NAT_MAX] = {
};
static inline int
-ctnetlink_parse_nat(struct nfattr *nat,
- const struct nf_conn *ct, struct ip_nat_range *range)
+nfnetlink_parse_nat(struct nfattr *nat,
+ const struct nf_conn *ct, struct nf_nat_range *range)
{
struct nfattr *tb[CTA_NAT_MAX];
int err;
@@ -603,12 +614,12 @@ ctnetlink_parse_nat(struct nfattr *nat,
return -EINVAL;
if (tb[CTA_NAT_MINIP-1])
- range->min_ip = *(u_int32_t *)NFA_DATA(tb[CTA_NAT_MINIP-1]);
+ range->min_ip = *(__be32 *)NFA_DATA(tb[CTA_NAT_MINIP-1]);
if (!tb[CTA_NAT_MAXIP-1])
range->max_ip = range->min_ip;
else
- range->max_ip = *(u_int32_t *)NFA_DATA(tb[CTA_NAT_MAXIP-1]);
+ range->max_ip = *(__be32 *)NFA_DATA(tb[CTA_NAT_MAXIP-1]);
if (range->min_ip)
range->flags |= IP_NAT_RANGE_MAP_IPS;
@@ -616,7 +627,7 @@ ctnetlink_parse_nat(struct nfattr *nat,
if (!tb[CTA_NAT_PROTO-1])
return 0;
- err = ctnetlink_parse_nat_proto(tb[CTA_NAT_PROTO-1], ct, range);
+ err = nfnetlink_parse_nat_proto(tb[CTA_NAT_PROTO-1], ct, range);
if (err < 0)
return err;
@@ -681,7 +692,7 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
ct = nf_ct_tuplehash_to_ctrack(h);
if (cda[CTA_ID-1]) {
- u_int32_t id = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_ID-1]));
+ u_int32_t id = ntohl(*(__be32 *)NFA_DATA(cda[CTA_ID-1]));
if (ct->id != id) {
nf_ct_put(ct);
return -ENOENT;
@@ -751,7 +762,6 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
nf_ct_put(ct);
return -ENOMEM;
}
- NETLINK_CB(skb2).dst_pid = NETLINK_CB(skb).pid;
err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq,
IPCTNL_MSG_CT_NEW, 1, ct);
@@ -775,7 +785,7 @@ static inline int
ctnetlink_change_status(struct nf_conn *ct, struct nfattr *cda[])
{
unsigned long d;
- unsigned status = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_STATUS-1]));
+ unsigned int status = ntohl(*(__be32 *)NFA_DATA(cda[CTA_STATUS-1]));
d = ct->status ^ status;
if (d & (IPS_EXPECTED|IPS_CONFIRMED|IPS_DYING))
@@ -792,35 +802,35 @@ ctnetlink_change_status(struct nf_conn *ct, struct nfattr *cda[])
return -EINVAL;
if (cda[CTA_NAT_SRC-1] || cda[CTA_NAT_DST-1]) {
-#ifndef CONFIG_IP_NF_NAT_NEEDED
+#ifndef CONFIG_NF_NAT_NEEDED
return -EINVAL;
#else
- struct ip_nat_range range;
+ struct nf_nat_range range;
if (cda[CTA_NAT_DST-1]) {
- if (ctnetlink_parse_nat(cda[CTA_NAT_DST-1], ct,
+ if (nfnetlink_parse_nat(cda[CTA_NAT_DST-1], ct,
&range) < 0)
return -EINVAL;
- if (ip_nat_initialized(ct,
+ if (nf_nat_initialized(ct,
HOOK2MANIP(NF_IP_PRE_ROUTING)))
return -EEXIST;
- ip_nat_setup_info(ct, &range, hooknum);
+ nf_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING);
}
if (cda[CTA_NAT_SRC-1]) {
- if (ctnetlink_parse_nat(cda[CTA_NAT_SRC-1], ct,
+ if (nfnetlink_parse_nat(cda[CTA_NAT_SRC-1], ct,
&range) < 0)
return -EINVAL;
- if (ip_nat_initialized(ct,
+ if (nf_nat_initialized(ct,
HOOK2MANIP(NF_IP_POST_ROUTING)))
return -EEXIST;
- ip_nat_setup_info(ct, &range, hooknum);
+ nf_nat_setup_info(ct, &range, NF_IP_POST_ROUTING);
}
#endif
}
/* Be careful here, modifying NAT bits can screw up things,
* so don't let users modify them directly if they don't pass
- * ip_nat_range. */
+ * nf_nat_range. */
ct->status |= status & ~(IPS_NAT_DONE_MASK | IPS_NAT_MASK);
return 0;
}
@@ -874,7 +884,7 @@ ctnetlink_change_helper(struct nf_conn *ct, struct nfattr *cda[])
static inline int
ctnetlink_change_timeout(struct nf_conn *ct, struct nfattr *cda[])
{
- u_int32_t timeout = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_TIMEOUT-1]));
+ u_int32_t timeout = ntohl(*(__be32 *)NFA_DATA(cda[CTA_TIMEOUT-1]));
if (!del_timer(&ct->timeout))
return -ETIME;
@@ -889,18 +899,18 @@ static inline int
ctnetlink_change_protoinfo(struct nf_conn *ct, struct nfattr *cda[])
{
struct nfattr *tb[CTA_PROTOINFO_MAX], *attr = cda[CTA_PROTOINFO-1];
- struct nf_conntrack_protocol *proto;
+ struct nf_conntrack_l4proto *l4proto;
u_int16_t npt = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum;
u_int16_t l3num = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
int err = 0;
nfattr_parse_nested(tb, CTA_PROTOINFO_MAX, attr);
- proto = nf_ct_proto_find_get(l3num, npt);
+ l4proto = nf_ct_l4proto_find_get(l3num, npt);
- if (proto->from_nfattr)
- err = proto->from_nfattr(tb, ct);
- nf_ct_proto_put(proto);
+ if (l4proto->from_nfattr)
+ err = l4proto->from_nfattr(tb, ct);
+ nf_ct_l4proto_put(l4proto);
return err;
}
@@ -936,7 +946,7 @@ ctnetlink_change_conntrack(struct nf_conn *ct, struct nfattr *cda[])
#if defined(CONFIG_NF_CONNTRACK_MARK)
if (cda[CTA_MARK-1])
- ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
+ ct->mark = ntohl(*(__be32 *)NFA_DATA(cda[CTA_MARK-1]));
#endif
return 0;
@@ -949,6 +959,7 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
{
struct nf_conn *ct;
int err = -EINVAL;
+ struct nf_conn_help *help;
ct = nf_conntrack_alloc(otuple, rtuple);
if (ct == NULL || IS_ERR(ct))
@@ -956,14 +967,16 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
if (!cda[CTA_TIMEOUT-1])
goto err;
- ct->timeout.expires = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_TIMEOUT-1]));
+ ct->timeout.expires = ntohl(*(__be32 *)NFA_DATA(cda[CTA_TIMEOUT-1]));
ct->timeout.expires = jiffies + ct->timeout.expires * HZ;
ct->status |= IPS_CONFIRMED;
- err = ctnetlink_change_status(ct, cda);
- if (err < 0)
- goto err;
+ if (cda[CTA_STATUS-1]) {
+ err = ctnetlink_change_status(ct, cda);
+ if (err < 0)
+ goto err;
+ }
if (cda[CTA_PROTOINFO-1]) {
err = ctnetlink_change_protoinfo(ct, cda);
@@ -973,12 +986,19 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
#if defined(CONFIG_NF_CONNTRACK_MARK)
if (cda[CTA_MARK-1])
- ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
+ ct->mark = ntohl(*(__be32 *)NFA_DATA(cda[CTA_MARK-1]));
#endif
+ help = nfct_help(ct);
+ if (help)
+ help->helper = nf_ct_helper_find_get(rtuple);
+
add_timer(&ct->timeout);
nf_conntrack_hash_insert(ct);
+ if (help && help->helper)
+ nf_ct_helper_put(help->helper);
+
return 0;
err:
@@ -1072,7 +1092,7 @@ ctnetlink_exp_dump_mask(struct sk_buff *skb,
{
int ret;
struct nf_conntrack_l3proto *l3proto;
- struct nf_conntrack_protocol *proto;
+ struct nf_conntrack_l4proto *l4proto;
struct nfattr *nest_parms = NFA_NEST(skb, CTA_EXPECT_MASK);
l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
@@ -1082,9 +1102,9 @@ ctnetlink_exp_dump_mask(struct sk_buff *skb,
if (unlikely(ret < 0))
goto nfattr_failure;
- proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum);
- ret = ctnetlink_dump_tuples_proto(skb, mask, proto);
- nf_ct_proto_put(proto);
+ l4proto = nf_ct_l4proto_find_get(tuple->src.l3num, tuple->dst.protonum);
+ ret = ctnetlink_dump_tuples_proto(skb, mask, l4proto);
+ nf_ct_l4proto_put(l4proto);
if (unlikely(ret < 0))
goto nfattr_failure;
@@ -1101,8 +1121,8 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb,
const struct nf_conntrack_expect *exp)
{
struct nf_conn *master = exp->master;
- u_int32_t timeout = htonl((exp->timeout.expires - jiffies) / HZ);
- u_int32_t id = htonl(exp->id);
+ __be32 timeout = htonl((exp->timeout.expires - jiffies) / HZ);
+ __be32 id = htonl(exp->id);
if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0)
goto nfattr_failure;
@@ -1275,12 +1295,12 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
if (err < 0)
return err;
- exp = nf_conntrack_expect_find(&tuple);
+ exp = nf_conntrack_expect_find_get(&tuple);
if (!exp)
return -ENOENT;
if (cda[CTA_EXPECT_ID-1]) {
- u_int32_t id = *(u_int32_t *)NFA_DATA(cda[CTA_EXPECT_ID-1]);
+ __be32 id = *(__be32 *)NFA_DATA(cda[CTA_EXPECT_ID-1]);
if (exp->id != ntohl(id)) {
nf_conntrack_expect_put(exp);
return -ENOENT;
@@ -1291,8 +1311,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
if (!skb2)
goto out;
- NETLINK_CB(skb2).dst_pid = NETLINK_CB(skb).pid;
-
+
err = ctnetlink_exp_fill_info(skb2, NETLINK_CB(skb).pid,
nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW,
1, exp);
@@ -1331,13 +1350,12 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
return err;
/* bump usage count to 2 */
- exp = nf_conntrack_expect_find(&tuple);
+ exp = nf_conntrack_expect_find_get(&tuple);
if (!exp)
return -ENOENT;
if (cda[CTA_EXPECT_ID-1]) {
- u_int32_t id =
- *(u_int32_t *)NFA_DATA(cda[CTA_EXPECT_ID-1]);
+ __be32 id = *(__be32 *)NFA_DATA(cda[CTA_EXPECT_ID-1]);
if (exp->id != ntohl(id)) {
nf_conntrack_expect_put(exp);
return -ENOENT;
@@ -1433,6 +1451,7 @@ ctnetlink_create_expect(struct nfattr *cda[], u_int8_t u3)
exp->expectfn = NULL;
exp->flags = 0;
exp->master = ct;
+ exp->helper = NULL;
memcpy(&exp->tuple, &tuple, sizeof(struct nf_conntrack_tuple));
memcpy(&exp->mask, &mask, sizeof(struct nf_conntrack_tuple));
@@ -1529,6 +1548,7 @@ static struct nfnetlink_subsystem ctnl_exp_subsys = {
.cb = ctnl_exp_cb,
};
+MODULE_ALIAS("ip_conntrack_netlink");
MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK);
MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_EXP);
diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c
new file mode 100644
index 000000000000..f0ff00e0d052
--- /dev/null
+++ b/net/netfilter/nf_conntrack_pptp.c
@@ -0,0 +1,607 @@
+/*
+ * Connection tracking support for PPTP (Point to Point Tunneling Protocol).
+ * PPTP is a a protocol for creating virtual private networks.
+ * It is a specification defined by Microsoft and some vendors
+ * working with Microsoft. PPTP is built on top of a modified
+ * version of the Internet Generic Routing Encapsulation Protocol.
+ * GRE is defined in RFC 1701 and RFC 1702. Documentation of
+ * PPTP can be found in RFC 2637
+ *
+ * (C) 2000-2005 by Harald Welte <laforge@gnumonks.org>
+ *
+ * Development of this code funded by Astaro AG (http://www.astaro.com/)
+ *
+ * Limitations:
+ * - We blindly assume that control connections are always
+ * established in PNS->PAC direction. This is a violation
+ * of RFFC2673
+ * - We can only support one single call within each session
+ * TODO:
+ * - testing of incoming PPTP calls
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/in.h>
+#include <linux/tcp.h>
+
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_core.h>
+#include <net/netfilter/nf_conntrack_helper.h>
+#include <linux/netfilter/nf_conntrack_proto_gre.h>
+#include <linux/netfilter/nf_conntrack_pptp.h>
+
+#define NF_CT_PPTP_VERSION "3.1"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
+MODULE_DESCRIPTION("Netfilter connection tracking helper module for PPTP");
+MODULE_ALIAS("ip_conntrack_pptp");
+
+static DEFINE_SPINLOCK(nf_pptp_lock);
+
+int
+(*nf_nat_pptp_hook_outbound)(struct sk_buff **pskb,
+ struct nf_conn *ct, enum ip_conntrack_info ctinfo,
+ struct PptpControlHeader *ctlh,
+ union pptp_ctrl_union *pptpReq) __read_mostly;
+EXPORT_SYMBOL_GPL(nf_nat_pptp_hook_outbound);
+
+int
+(*nf_nat_pptp_hook_inbound)(struct sk_buff **pskb,
+ struct nf_conn *ct, enum ip_conntrack_info ctinfo,
+ struct PptpControlHeader *ctlh,
+ union pptp_ctrl_union *pptpReq) __read_mostly;
+EXPORT_SYMBOL_GPL(nf_nat_pptp_hook_inbound);
+
+void
+(*nf_nat_pptp_hook_exp_gre)(struct nf_conntrack_expect *expect_orig,
+ struct nf_conntrack_expect *expect_reply)
+ __read_mostly;
+EXPORT_SYMBOL_GPL(nf_nat_pptp_hook_exp_gre);
+
+void
+(*nf_nat_pptp_hook_expectfn)(struct nf_conn *ct,
+ struct nf_conntrack_expect *exp) __read_mostly;
+EXPORT_SYMBOL_GPL(nf_nat_pptp_hook_expectfn);
+
+#if 0
+/* PptpControlMessageType names */
+const char *pptp_msg_name[] = {
+ "UNKNOWN_MESSAGE",
+ "START_SESSION_REQUEST",
+ "START_SESSION_REPLY",
+ "STOP_SESSION_REQUEST",
+ "STOP_SESSION_REPLY",
+ "ECHO_REQUEST",
+ "ECHO_REPLY",
+ "OUT_CALL_REQUEST",
+ "OUT_CALL_REPLY",
+ "IN_CALL_REQUEST",
+ "IN_CALL_REPLY",
+ "IN_CALL_CONNECT",
+ "CALL_CLEAR_REQUEST",
+ "CALL_DISCONNECT_NOTIFY",
+ "WAN_ERROR_NOTIFY",
+ "SET_LINK_INFO"
+};
+EXPORT_SYMBOL(pptp_msg_name);
+#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, __FUNCTION__, ## args)
+#else
+#define DEBUGP(format, args...)
+#endif
+
+#define SECS *HZ
+#define MINS * 60 SECS
+#define HOURS * 60 MINS
+
+#define PPTP_GRE_TIMEOUT (10 MINS)
+#define PPTP_GRE_STREAM_TIMEOUT (5 HOURS)
+
+static void pptp_expectfn(struct nf_conn *ct,
+ struct nf_conntrack_expect *exp)
+{
+ typeof(nf_nat_pptp_hook_expectfn) nf_nat_pptp_expectfn;
+ DEBUGP("increasing timeouts\n");
+
+ /* increase timeout of GRE data channel conntrack entry */
+ ct->proto.gre.timeout = PPTP_GRE_TIMEOUT;
+ ct->proto.gre.stream_timeout = PPTP_GRE_STREAM_TIMEOUT;
+
+ /* Can you see how rusty this code is, compared with the pre-2.6.11
+ * one? That's what happened to my shiny newnat of 2002 ;( -HW */
+
+ rcu_read_lock();
+ nf_nat_pptp_expectfn = rcu_dereference(nf_nat_pptp_hook_expectfn);
+ if (nf_nat_pptp_expectfn && ct->status & IPS_NAT_MASK)
+ nf_nat_pptp_expectfn(ct, exp);
+ else {
+ struct nf_conntrack_tuple inv_t;
+ struct nf_conntrack_expect *exp_other;
+
+ /* obviously this tuple inversion only works until you do NAT */
+ nf_ct_invert_tuplepr(&inv_t, &exp->tuple);
+ DEBUGP("trying to unexpect other dir: ");
+ NF_CT_DUMP_TUPLE(&inv_t);
+
+ exp_other = nf_conntrack_expect_find_get(&inv_t);
+ if (exp_other) {
+ /* delete other expectation. */
+ DEBUGP("found\n");
+ nf_conntrack_unexpect_related(exp_other);
+ nf_conntrack_expect_put(exp_other);
+ } else {
+ DEBUGP("not found\n");
+ }
+ }
+ rcu_read_unlock();
+}
+
+static int destroy_sibling_or_exp(const struct nf_conntrack_tuple *t)
+{
+ struct nf_conntrack_tuple_hash *h;
+ struct nf_conntrack_expect *exp;
+ struct nf_conn *sibling;
+
+ DEBUGP("trying to timeout ct or exp for tuple ");
+ NF_CT_DUMP_TUPLE(t);
+
+ h = nf_conntrack_find_get(t, NULL);
+ if (h) {
+ sibling = nf_ct_tuplehash_to_ctrack(h);
+ DEBUGP("setting timeout of conntrack %p to 0\n", sibling);
+ sibling->proto.gre.timeout = 0;
+ sibling->proto.gre.stream_timeout = 0;
+ if (del_timer(&sibling->timeout))
+ sibling->timeout.function((unsigned long)sibling);
+ nf_ct_put(sibling);
+ return 1;
+ } else {
+ exp = nf_conntrack_expect_find_get(t);
+ if (exp) {
+ DEBUGP("unexpect_related of expect %p\n", exp);
+ nf_conntrack_unexpect_related(exp);
+ nf_conntrack_expect_put(exp);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* timeout GRE data connections */
+static void pptp_destroy_siblings(struct nf_conn *ct)
+{
+ struct nf_conn_help *help = nfct_help(ct);
+ struct nf_conntrack_tuple t;
+
+ nf_ct_gre_keymap_destroy(ct);
+
+ /* try original (pns->pac) tuple */
+ memcpy(&t, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, sizeof(t));
+ t.dst.protonum = IPPROTO_GRE;
+ t.src.u.gre.key = help->help.ct_pptp_info.pns_call_id;
+ t.dst.u.gre.key = help->help.ct_pptp_info.pac_call_id;
+ if (!destroy_sibling_or_exp(&t))
+ DEBUGP("failed to timeout original pns->pac ct/exp\n");
+
+ /* try reply (pac->pns) tuple */
+ memcpy(&t, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, sizeof(t));
+ t.dst.protonum = IPPROTO_GRE;
+ t.src.u.gre.key = help->help.ct_pptp_info.pac_call_id;
+ t.dst.u.gre.key = help->help.ct_pptp_info.pns_call_id;
+ if (!destroy_sibling_or_exp(&t))
+ DEBUGP("failed to timeout reply pac->pns ct/exp\n");
+}
+
+/* expect GRE connections (PNS->PAC and PAC->PNS direction) */
+static int exp_gre(struct nf_conn *ct, __be16 callid, __be16 peer_callid)
+{
+ struct nf_conntrack_expect *exp_orig, *exp_reply;
+ enum ip_conntrack_dir dir;
+ int ret = 1;
+ typeof(nf_nat_pptp_hook_exp_gre) nf_nat_pptp_exp_gre;
+
+ exp_orig = nf_conntrack_expect_alloc(ct);
+ if (exp_orig == NULL)
+ goto out;
+
+ exp_reply = nf_conntrack_expect_alloc(ct);
+ if (exp_reply == NULL)
+ goto out_put_orig;
+
+ /* original direction, PNS->PAC */
+ dir = IP_CT_DIR_ORIGINAL;
+ nf_conntrack_expect_init(exp_orig, ct->tuplehash[dir].tuple.src.l3num,
+ &ct->tuplehash[dir].tuple.src.u3,
+ &ct->tuplehash[dir].tuple.dst.u3,
+ IPPROTO_GRE, &peer_callid, &callid);
+ exp_orig->expectfn = pptp_expectfn;
+
+ /* reply direction, PAC->PNS */
+ dir = IP_CT_DIR_REPLY;
+ nf_conntrack_expect_init(exp_reply, ct->tuplehash[dir].tuple.src.l3num,
+ &ct->tuplehash[dir].tuple.src.u3,
+ &ct->tuplehash[dir].tuple.dst.u3,
+ IPPROTO_GRE, &callid, &peer_callid);
+ exp_reply->expectfn = pptp_expectfn;
+
+ nf_nat_pptp_exp_gre = rcu_dereference(nf_nat_pptp_hook_exp_gre);
+ if (nf_nat_pptp_exp_gre && ct->status & IPS_NAT_MASK)
+ nf_nat_pptp_exp_gre(exp_orig, exp_reply);
+ if (nf_conntrack_expect_related(exp_orig) != 0)
+ goto out_put_both;
+ if (nf_conntrack_expect_related(exp_reply) != 0)
+ goto out_unexpect_orig;
+
+ /* Add GRE keymap entries */
+ if (nf_ct_gre_keymap_add(ct, IP_CT_DIR_ORIGINAL, &exp_orig->tuple) != 0)
+ goto out_unexpect_both;
+ if (nf_ct_gre_keymap_add(ct, IP_CT_DIR_REPLY, &exp_reply->tuple) != 0) {
+ nf_ct_gre_keymap_destroy(ct);
+ goto out_unexpect_both;
+ }
+ ret = 0;
+
+out_put_both:
+ nf_conntrack_expect_put(exp_reply);
+out_put_orig:
+ nf_conntrack_expect_put(exp_orig);
+out:
+ return ret;
+
+out_unexpect_both:
+ nf_conntrack_unexpect_related(exp_reply);
+out_unexpect_orig:
+ nf_conntrack_unexpect_related(exp_orig);
+ goto out_put_both;
+}
+
+static inline int
+pptp_inbound_pkt(struct sk_buff **pskb,
+ struct PptpControlHeader *ctlh,
+ union pptp_ctrl_union *pptpReq,
+ unsigned int reqlen,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo)
+{
+ struct nf_ct_pptp_master *info = &nfct_help(ct)->help.ct_pptp_info;
+ u_int16_t msg;
+ __be16 cid = 0, pcid = 0;
+ typeof(nf_nat_pptp_hook_inbound) nf_nat_pptp_inbound;
+
+ msg = ntohs(ctlh->messageType);
+ DEBUGP("inbound control message %s\n", pptp_msg_name[msg]);
+
+ switch (msg) {
+ case PPTP_START_SESSION_REPLY:
+ /* server confirms new control session */
+ if (info->sstate < PPTP_SESSION_REQUESTED)
+ goto invalid;
+ if (pptpReq->srep.resultCode == PPTP_START_OK)
+ info->sstate = PPTP_SESSION_CONFIRMED;
+ else
+ info->sstate = PPTP_SESSION_ERROR;
+ break;
+
+ case PPTP_STOP_SESSION_REPLY:
+ /* server confirms end of control session */
+ if (info->sstate > PPTP_SESSION_STOPREQ)
+ goto invalid;
+ if (pptpReq->strep.resultCode == PPTP_STOP_OK)
+ info->sstate = PPTP_SESSION_NONE;
+ else
+ info->sstate = PPTP_SESSION_ERROR;
+ break;
+
+ case PPTP_OUT_CALL_REPLY:
+ /* server accepted call, we now expect GRE frames */
+ if (info->sstate != PPTP_SESSION_CONFIRMED)
+ goto invalid;
+ if (info->cstate != PPTP_CALL_OUT_REQ &&
+ info->cstate != PPTP_CALL_OUT_CONF)
+ goto invalid;
+
+ cid = pptpReq->ocack.callID;
+ pcid = pptpReq->ocack.peersCallID;
+ if (info->pns_call_id != pcid)
+ goto invalid;
+ DEBUGP("%s, CID=%X, PCID=%X\n", pptp_msg_name[msg],
+ ntohs(cid), ntohs(pcid));
+
+ if (pptpReq->ocack.resultCode == PPTP_OUTCALL_CONNECT) {
+ info->cstate = PPTP_CALL_OUT_CONF;
+ info->pac_call_id = cid;
+ exp_gre(ct, cid, pcid);
+ } else
+ info->cstate = PPTP_CALL_NONE;
+ break;
+
+ case PPTP_IN_CALL_REQUEST:
+ /* server tells us about incoming call request */
+ if (info->sstate != PPTP_SESSION_CONFIRMED)
+ goto invalid;
+
+ cid = pptpReq->icreq.callID;
+ DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid));
+ info->cstate = PPTP_CALL_IN_REQ;
+ info->pac_call_id = cid;
+ break;
+
+ case PPTP_IN_CALL_CONNECT:
+ /* server tells us about incoming call established */
+ if (info->sstate != PPTP_SESSION_CONFIRMED)
+ goto invalid;
+ if (info->cstate != PPTP_CALL_IN_REP &&
+ info->cstate != PPTP_CALL_IN_CONF)
+ goto invalid;
+
+ pcid = pptpReq->iccon.peersCallID;
+ cid = info->pac_call_id;
+
+ if (info->pns_call_id != pcid)
+ goto invalid;
+
+ DEBUGP("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(pcid));
+ info->cstate = PPTP_CALL_IN_CONF;
+
+ /* we expect a GRE connection from PAC to PNS */
+ exp_gre(ct, cid, pcid);
+ break;
+
+ case PPTP_CALL_DISCONNECT_NOTIFY:
+ /* server confirms disconnect */
+ cid = pptpReq->disc.callID;
+ DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid));
+ info->cstate = PPTP_CALL_NONE;
+
+ /* untrack this call id, unexpect GRE packets */
+ pptp_destroy_siblings(ct);
+ break;
+
+ case PPTP_WAN_ERROR_NOTIFY:
+ case PPTP_ECHO_REQUEST:
+ case PPTP_ECHO_REPLY:
+ /* I don't have to explain these ;) */
+ break;
+
+ default:
+ goto invalid;
+ }
+
+ nf_nat_pptp_inbound = rcu_dereference(nf_nat_pptp_hook_inbound);
+ if (nf_nat_pptp_inbound && ct->status & IPS_NAT_MASK)
+ return nf_nat_pptp_inbound(pskb, ct, ctinfo, ctlh, pptpReq);
+ return NF_ACCEPT;
+
+invalid:
+ DEBUGP("invalid %s: type=%d cid=%u pcid=%u "
+ "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n",
+ msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0],
+ msg, ntohs(cid), ntohs(pcid), info->cstate, info->sstate,
+ ntohs(info->pns_call_id), ntohs(info->pac_call_id));
+ return NF_ACCEPT;
+}
+
+static inline int
+pptp_outbound_pkt(struct sk_buff **pskb,
+ struct PptpControlHeader *ctlh,
+ union pptp_ctrl_union *pptpReq,
+ unsigned int reqlen,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo)
+{
+ struct nf_ct_pptp_master *info = &nfct_help(ct)->help.ct_pptp_info;
+ u_int16_t msg;
+ __be16 cid = 0, pcid = 0;
+ typeof(nf_nat_pptp_hook_outbound) nf_nat_pptp_outbound;
+
+ msg = ntohs(ctlh->messageType);
+ DEBUGP("outbound control message %s\n", pptp_msg_name[msg]);
+
+ switch (msg) {
+ case PPTP_START_SESSION_REQUEST:
+ /* client requests for new control session */
+ if (info->sstate != PPTP_SESSION_NONE)
+ goto invalid;
+ info->sstate = PPTP_SESSION_REQUESTED;
+ break;
+
+ case PPTP_STOP_SESSION_REQUEST:
+ /* client requests end of control session */
+ info->sstate = PPTP_SESSION_STOPREQ;
+ break;
+
+ case PPTP_OUT_CALL_REQUEST:
+ /* client initiating connection to server */
+ if (info->sstate != PPTP_SESSION_CONFIRMED)
+ goto invalid;
+ info->cstate = PPTP_CALL_OUT_REQ;
+ /* track PNS call id */
+ cid = pptpReq->ocreq.callID;
+ DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid));
+ info->pns_call_id = cid;
+ break;
+
+ case PPTP_IN_CALL_REPLY:
+ /* client answers incoming call */
+ if (info->cstate != PPTP_CALL_IN_REQ &&
+ info->cstate != PPTP_CALL_IN_REP)
+ goto invalid;
+
+ cid = pptpReq->icack.callID;
+ pcid = pptpReq->icack.peersCallID;
+ if (info->pac_call_id != pcid)
+ goto invalid;
+ DEBUGP("%s, CID=%X PCID=%X\n", pptp_msg_name[msg],
+ ntohs(cid), ntohs(pcid));
+
+ if (pptpReq->icack.resultCode == PPTP_INCALL_ACCEPT) {
+ /* part two of the three-way handshake */
+ info->cstate = PPTP_CALL_IN_REP;
+ info->pns_call_id = cid;
+ } else
+ info->cstate = PPTP_CALL_NONE;
+ break;
+
+ case PPTP_CALL_CLEAR_REQUEST:
+ /* client requests hangup of call */
+ if (info->sstate != PPTP_SESSION_CONFIRMED)
+ goto invalid;
+ /* FUTURE: iterate over all calls and check if
+ * call ID is valid. We don't do this without newnat,
+ * because we only know about last call */
+ info->cstate = PPTP_CALL_CLEAR_REQ;
+ break;
+
+ case PPTP_SET_LINK_INFO:
+ case PPTP_ECHO_REQUEST:
+ case PPTP_ECHO_REPLY:
+ /* I don't have to explain these ;) */
+ break;
+
+ default:
+ goto invalid;
+ }
+
+ nf_nat_pptp_outbound = rcu_dereference(nf_nat_pptp_hook_outbound);
+ if (nf_nat_pptp_outbound && ct->status & IPS_NAT_MASK)
+ return nf_nat_pptp_outbound(pskb, ct, ctinfo, ctlh, pptpReq);
+ return NF_ACCEPT;
+
+invalid:
+ DEBUGP("invalid %s: type=%d cid=%u pcid=%u "
+ "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n",
+ msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0],
+ msg, ntohs(cid), ntohs(pcid), info->cstate, info->sstate,
+ ntohs(info->pns_call_id), ntohs(info->pac_call_id));
+ return NF_ACCEPT;
+}
+
+static const unsigned int pptp_msg_size[] = {
+ [PPTP_START_SESSION_REQUEST] = sizeof(struct PptpStartSessionRequest),
+ [PPTP_START_SESSION_REPLY] = sizeof(struct PptpStartSessionReply),
+ [PPTP_STOP_SESSION_REQUEST] = sizeof(struct PptpStopSessionRequest),
+ [PPTP_STOP_SESSION_REPLY] = sizeof(struct PptpStopSessionReply),
+ [PPTP_OUT_CALL_REQUEST] = sizeof(struct PptpOutCallRequest),
+ [PPTP_OUT_CALL_REPLY] = sizeof(struct PptpOutCallReply),
+ [PPTP_IN_CALL_REQUEST] = sizeof(struct PptpInCallRequest),
+ [PPTP_IN_CALL_REPLY] = sizeof(struct PptpInCallReply),
+ [PPTP_IN_CALL_CONNECT] = sizeof(struct PptpInCallConnected),
+ [PPTP_CALL_CLEAR_REQUEST] = sizeof(struct PptpClearCallRequest),
+ [PPTP_CALL_DISCONNECT_NOTIFY] = sizeof(struct PptpCallDisconnectNotify),
+ [PPTP_WAN_ERROR_NOTIFY] = sizeof(struct PptpWanErrorNotify),
+ [PPTP_SET_LINK_INFO] = sizeof(struct PptpSetLinkInfo),
+};
+
+/* track caller id inside control connection, call expect_related */
+static int
+conntrack_pptp_help(struct sk_buff **pskb, unsigned int protoff,
+ struct nf_conn *ct, enum ip_conntrack_info ctinfo)
+
+{
+ int dir = CTINFO2DIR(ctinfo);
+ struct nf_ct_pptp_master *info = &nfct_help(ct)->help.ct_pptp_info;
+ struct tcphdr _tcph, *tcph;
+ struct pptp_pkt_hdr _pptph, *pptph;
+ struct PptpControlHeader _ctlh, *ctlh;
+ union pptp_ctrl_union _pptpReq, *pptpReq;
+ unsigned int tcplen = (*pskb)->len - protoff;
+ unsigned int datalen, reqlen, nexthdr_off;
+ int oldsstate, oldcstate;
+ int ret;
+ u_int16_t msg;
+
+ /* don't do any tracking before tcp handshake complete */
+ if (ctinfo != IP_CT_ESTABLISHED &&
+ ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY)
+ return NF_ACCEPT;
+
+ nexthdr_off = protoff;
+ tcph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_tcph), &_tcph);
+ BUG_ON(!tcph);
+ nexthdr_off += tcph->doff * 4;
+ datalen = tcplen - tcph->doff * 4;
+
+ pptph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_pptph), &_pptph);
+ if (!pptph) {
+ DEBUGP("no full PPTP header, can't track\n");
+ return NF_ACCEPT;
+ }
+ nexthdr_off += sizeof(_pptph);
+ datalen -= sizeof(_pptph);
+
+ /* if it's not a control message we can't do anything with it */
+ if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL ||
+ ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) {
+ DEBUGP("not a control packet\n");
+ return NF_ACCEPT;
+ }
+
+ ctlh = skb_header_pointer(*pskb, nexthdr_off, sizeof(_ctlh), &_ctlh);
+ if (!ctlh)
+ return NF_ACCEPT;
+ nexthdr_off += sizeof(_ctlh);
+ datalen -= sizeof(_ctlh);
+
+ reqlen = datalen;
+ msg = ntohs(ctlh->messageType);
+ if (msg > 0 && msg <= PPTP_MSG_MAX && reqlen < pptp_msg_size[msg])
+ return NF_ACCEPT;
+ if (reqlen > sizeof(*pptpReq))
+ reqlen = sizeof(*pptpReq);
+
+ pptpReq = skb_header_pointer(*pskb, nexthdr_off, reqlen, &_pptpReq);
+ if (!pptpReq)
+ return NF_ACCEPT;
+
+ oldsstate = info->sstate;
+ oldcstate = info->cstate;
+
+ spin_lock_bh(&nf_pptp_lock);
+
+ /* FIXME: We just blindly assume that the control connection is always
+ * established from PNS->PAC. However, RFC makes no guarantee */
+ if (dir == IP_CT_DIR_ORIGINAL)
+ /* client -> server (PNS -> PAC) */
+ ret = pptp_outbound_pkt(pskb, ctlh, pptpReq, reqlen, ct,
+ ctinfo);
+ else
+ /* server -> client (PAC -> PNS) */
+ ret = pptp_inbound_pkt(pskb, ctlh, pptpReq, reqlen, ct,
+ ctinfo);
+ DEBUGP("sstate: %d->%d, cstate: %d->%d\n",
+ oldsstate, info->sstate, oldcstate, info->cstate);
+ spin_unlock_bh(&nf_pptp_lock);
+
+ return ret;
+}
+
+/* control protocol helper */
+static struct nf_conntrack_helper pptp __read_mostly = {
+ .name = "pptp",
+ .me = THIS_MODULE,
+ .max_expected = 2,
+ .timeout = 5 * 60,
+ .tuple.src.l3num = AF_INET,
+ .tuple.src.u.tcp.port = __constant_htons(PPTP_CONTROL_PORT),
+ .tuple.dst.protonum = IPPROTO_TCP,
+ .mask.src.l3num = 0xffff,
+ .mask.src.u.tcp.port = __constant_htons(0xffff),
+ .mask.dst.protonum = 0xff,
+ .help = conntrack_pptp_help,
+ .destroy = pptp_destroy_siblings,
+};
+
+static int __init nf_conntrack_pptp_init(void)
+{
+ return nf_conntrack_helper_register(&pptp);
+}
+
+static void __exit nf_conntrack_pptp_fini(void)
+{
+ nf_conntrack_helper_unregister(&pptp);
+ nf_ct_gre_keymap_flush();
+}
+
+module_init(nf_conntrack_pptp_init);
+module_exit(nf_conntrack_pptp_fini);
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c
new file mode 100644
index 000000000000..1a61b72712cd
--- /dev/null
+++ b/net/netfilter/nf_conntrack_proto.c
@@ -0,0 +1,410 @@
+/* L3/L4 protocol support for nf_conntrack. */
+
+/* (C) 1999-2001 Paul `Rusty' Russell
+ * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
+ * (C) 2003,2004 USAGI/WIDE Project <http://www.linux-ipv6.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/types.h>
+#include <linux/netfilter.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/skbuff.h>
+#include <linux/vmalloc.h>
+#include <linux/stddef.h>
+#include <linux/err.h>
+#include <linux/percpu.h>
+#include <linux/moduleparam.h>
+#include <linux/notifier.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_l3proto.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
+#include <net/netfilter/nf_conntrack_core.h>
+
+struct nf_conntrack_l4proto **nf_ct_protos[PF_MAX] __read_mostly;
+struct nf_conntrack_l3proto *nf_ct_l3protos[AF_MAX] __read_mostly;
+EXPORT_SYMBOL_GPL(nf_ct_l3protos);
+
+#ifdef CONFIG_SYSCTL
+static DEFINE_MUTEX(nf_ct_proto_sysctl_mutex);
+
+static int
+nf_ct_register_sysctl(struct ctl_table_header **header, struct ctl_table *path,
+ struct ctl_table *table, unsigned int *users)
+{
+ if (*header == NULL) {
+ *header = nf_register_sysctl_table(path, table);
+ if (*header == NULL)
+ return -ENOMEM;
+ }
+ if (users != NULL)
+ (*users)++;
+ return 0;
+}
+
+static void
+nf_ct_unregister_sysctl(struct ctl_table_header **header,
+ struct ctl_table *table, unsigned int *users)
+{
+ if (users != NULL && --*users > 0)
+ return;
+ nf_unregister_sysctl_table(*header, table);
+ *header = NULL;
+}
+#endif
+
+struct nf_conntrack_l4proto *
+__nf_ct_l4proto_find(u_int16_t l3proto, u_int8_t l4proto)
+{
+ if (unlikely(l3proto >= AF_MAX || nf_ct_protos[l3proto] == NULL))
+ return &nf_conntrack_l4proto_generic;
+
+ return nf_ct_protos[l3proto][l4proto];
+}
+EXPORT_SYMBOL_GPL(__nf_ct_l4proto_find);
+
+/* this is guaranteed to always return a valid protocol helper, since
+ * it falls back to generic_protocol */
+struct nf_conntrack_l4proto *
+nf_ct_l4proto_find_get(u_int16_t l3proto, u_int8_t l4proto)
+{
+ struct nf_conntrack_l4proto *p;
+
+ preempt_disable();
+ p = __nf_ct_l4proto_find(l3proto, l4proto);
+ if (!try_module_get(p->me))
+ p = &nf_conntrack_l4proto_generic;
+ preempt_enable();
+
+ return p;
+}
+EXPORT_SYMBOL_GPL(nf_ct_l4proto_find_get);
+
+void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p)
+{
+ module_put(p->me);
+}
+EXPORT_SYMBOL_GPL(nf_ct_l4proto_put);
+
+struct nf_conntrack_l3proto *
+nf_ct_l3proto_find_get(u_int16_t l3proto)
+{
+ struct nf_conntrack_l3proto *p;
+
+ preempt_disable();
+ p = __nf_ct_l3proto_find(l3proto);
+ if (!try_module_get(p->me))
+ p = &nf_conntrack_l3proto_generic;
+ preempt_enable();
+
+ return p;
+}
+EXPORT_SYMBOL_GPL(nf_ct_l3proto_find_get);
+
+void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p)
+{
+ module_put(p->me);
+}
+EXPORT_SYMBOL_GPL(nf_ct_l3proto_put);
+
+int
+nf_ct_l3proto_try_module_get(unsigned short l3proto)
+{
+ int ret;
+ struct nf_conntrack_l3proto *p;
+
+retry: p = nf_ct_l3proto_find_get(l3proto);
+ if (p == &nf_conntrack_l3proto_generic) {
+ ret = request_module("nf_conntrack-%d", l3proto);
+ if (!ret)
+ goto retry;
+
+ return -EPROTOTYPE;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(nf_ct_l3proto_try_module_get);
+
+void nf_ct_l3proto_module_put(unsigned short l3proto)
+{
+ struct nf_conntrack_l3proto *p;
+
+ preempt_disable();
+ p = __nf_ct_l3proto_find(l3proto);
+ preempt_enable();
+
+ module_put(p->me);
+}
+EXPORT_SYMBOL_GPL(nf_ct_l3proto_module_put);
+
+static int kill_l3proto(struct nf_conn *i, void *data)
+{
+ return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num ==
+ ((struct nf_conntrack_l3proto *)data)->l3proto);
+}
+
+static int kill_l4proto(struct nf_conn *i, void *data)
+{
+ struct nf_conntrack_l4proto *l4proto;
+ l4proto = (struct nf_conntrack_l4proto *)data;
+ return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum ==
+ l4proto->l4proto) &&
+ (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num ==
+ l4proto->l3proto);
+}
+
+static int nf_ct_l3proto_register_sysctl(struct nf_conntrack_l3proto *l3proto)
+{
+ int err = 0;
+
+#ifdef CONFIG_SYSCTL
+ mutex_lock(&nf_ct_proto_sysctl_mutex);
+ if (l3proto->ctl_table != NULL) {
+ err = nf_ct_register_sysctl(&l3proto->ctl_table_header,
+ l3proto->ctl_table_path,
+ l3proto->ctl_table, NULL);
+ }
+ mutex_unlock(&nf_ct_proto_sysctl_mutex);
+#endif
+ return err;
+}
+
+static void nf_ct_l3proto_unregister_sysctl(struct nf_conntrack_l3proto *l3proto)
+{
+#ifdef CONFIG_SYSCTL
+ mutex_lock(&nf_ct_proto_sysctl_mutex);
+ if (l3proto->ctl_table_header != NULL)
+ nf_ct_unregister_sysctl(&l3proto->ctl_table_header,
+ l3proto->ctl_table, NULL);
+ mutex_unlock(&nf_ct_proto_sysctl_mutex);
+#endif
+}
+
+int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto)
+{
+ int ret = 0;
+
+ if (proto->l3proto >= AF_MAX) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ write_lock_bh(&nf_conntrack_lock);
+ if (nf_ct_l3protos[proto->l3proto] != &nf_conntrack_l3proto_generic) {
+ ret = -EBUSY;
+ goto out_unlock;
+ }
+ nf_ct_l3protos[proto->l3proto] = proto;
+ write_unlock_bh(&nf_conntrack_lock);
+
+ ret = nf_ct_l3proto_register_sysctl(proto);
+ if (ret < 0)
+ nf_conntrack_l3proto_unregister(proto);
+ return ret;
+
+out_unlock:
+ write_unlock_bh(&nf_conntrack_lock);
+out:
+ return ret;
+}
+EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_register);
+
+int nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto)
+{
+ int ret = 0;
+
+ if (proto->l3proto >= AF_MAX) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ write_lock_bh(&nf_conntrack_lock);
+ if (nf_ct_l3protos[proto->l3proto] != proto) {
+ write_unlock_bh(&nf_conntrack_lock);
+ ret = -EBUSY;
+ goto out;
+ }
+
+ nf_ct_l3protos[proto->l3proto] = &nf_conntrack_l3proto_generic;
+ write_unlock_bh(&nf_conntrack_lock);
+
+ nf_ct_l3proto_unregister_sysctl(proto);
+
+ /* Somebody could be still looking at the proto in bh. */
+ synchronize_net();
+
+ /* Remove all contrack entries for this protocol */
+ nf_ct_iterate_cleanup(kill_l3proto, proto);
+
+out:
+ return ret;
+}
+EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_unregister);
+
+static int nf_ct_l4proto_register_sysctl(struct nf_conntrack_l4proto *l4proto)
+{
+ int err = 0;
+
+#ifdef CONFIG_SYSCTL
+ mutex_lock(&nf_ct_proto_sysctl_mutex);
+ if (l4proto->ctl_table != NULL) {
+ err = nf_ct_register_sysctl(l4proto->ctl_table_header,
+ nf_net_netfilter_sysctl_path,
+ l4proto->ctl_table,
+ l4proto->ctl_table_users);
+ if (err < 0)
+ goto out;
+ }
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+ if (l4proto->ctl_compat_table != NULL) {
+ err = nf_ct_register_sysctl(&l4proto->ctl_compat_table_header,
+ nf_net_ipv4_netfilter_sysctl_path,
+ l4proto->ctl_compat_table, NULL);
+ if (err == 0)
+ goto out;
+ nf_ct_unregister_sysctl(l4proto->ctl_table_header,
+ l4proto->ctl_table,
+ l4proto->ctl_table_users);
+ }
+#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
+out:
+ mutex_unlock(&nf_ct_proto_sysctl_mutex);
+#endif /* CONFIG_SYSCTL */
+ return err;
+}
+
+static void nf_ct_l4proto_unregister_sysctl(struct nf_conntrack_l4proto *l4proto)
+{
+#ifdef CONFIG_SYSCTL
+ mutex_lock(&nf_ct_proto_sysctl_mutex);
+ if (l4proto->ctl_table_header != NULL &&
+ *l4proto->ctl_table_header != NULL)
+ nf_ct_unregister_sysctl(l4proto->ctl_table_header,
+ l4proto->ctl_table,
+ l4proto->ctl_table_users);
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+ if (l4proto->ctl_compat_table_header != NULL)
+ nf_ct_unregister_sysctl(&l4proto->ctl_compat_table_header,
+ l4proto->ctl_compat_table, NULL);
+#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
+ mutex_unlock(&nf_ct_proto_sysctl_mutex);
+#endif /* CONFIG_SYSCTL */
+}
+
+/* FIXME: Allow NULL functions and sub in pointers to generic for
+ them. --RR */
+int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto)
+{
+ int ret = 0;
+
+ if (l4proto->l3proto >= PF_MAX) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ if (l4proto == &nf_conntrack_l4proto_generic)
+ return nf_ct_l4proto_register_sysctl(l4proto);
+
+retry:
+ write_lock_bh(&nf_conntrack_lock);
+ if (nf_ct_protos[l4proto->l3proto]) {
+ if (nf_ct_protos[l4proto->l3proto][l4proto->l4proto]
+ != &nf_conntrack_l4proto_generic) {
+ ret = -EBUSY;
+ goto out_unlock;
+ }
+ } else {
+ /* l3proto may be loaded latter. */
+ struct nf_conntrack_l4proto **proto_array;
+ int i;
+
+ write_unlock_bh(&nf_conntrack_lock);
+
+ proto_array = (struct nf_conntrack_l4proto **)
+ kmalloc(MAX_NF_CT_PROTO *
+ sizeof(struct nf_conntrack_l4proto *),
+ GFP_KERNEL);
+ if (proto_array == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ for (i = 0; i < MAX_NF_CT_PROTO; i++)
+ proto_array[i] = &nf_conntrack_l4proto_generic;
+
+ write_lock_bh(&nf_conntrack_lock);
+ if (nf_ct_protos[l4proto->l3proto]) {
+ /* bad timing, but no problem */
+ write_unlock_bh(&nf_conntrack_lock);
+ kfree(proto_array);
+ } else {
+ nf_ct_protos[l4proto->l3proto] = proto_array;
+ write_unlock_bh(&nf_conntrack_lock);
+ }
+
+ /*
+ * Just once because array is never freed until unloading
+ * nf_conntrack.ko
+ */
+ goto retry;
+ }
+
+ nf_ct_protos[l4proto->l3proto][l4proto->l4proto] = l4proto;
+ write_unlock_bh(&nf_conntrack_lock);
+
+ ret = nf_ct_l4proto_register_sysctl(l4proto);
+ if (ret < 0)
+ nf_conntrack_l4proto_unregister(l4proto);
+ return ret;
+
+out_unlock:
+ write_unlock_bh(&nf_conntrack_lock);
+out:
+ return ret;
+}
+EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_register);
+
+int nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *l4proto)
+{
+ int ret = 0;
+
+ if (l4proto->l3proto >= PF_MAX) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ if (l4proto == &nf_conntrack_l4proto_generic) {
+ nf_ct_l4proto_unregister_sysctl(l4proto);
+ goto out;
+ }
+
+ write_lock_bh(&nf_conntrack_lock);
+ if (nf_ct_protos[l4proto->l3proto][l4proto->l4proto]
+ != l4proto) {
+ write_unlock_bh(&nf_conntrack_lock);
+ ret = -EBUSY;
+ goto out;
+ }
+ nf_ct_protos[l4proto->l3proto][l4proto->l4proto]
+ = &nf_conntrack_l4proto_generic;
+ write_unlock_bh(&nf_conntrack_lock);
+
+ nf_ct_l4proto_unregister_sysctl(l4proto);
+
+ /* Somebody could be still looking at the proto in bh. */
+ synchronize_net();
+
+ /* Remove all contrack entries for this protocol */
+ nf_ct_iterate_cleanup(kill_l4proto, l4proto);
+
+out:
+ return ret;
+}
+EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_unregister);
diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c
index 26408bb0955b..69902531c236 100644
--- a/net/netfilter/nf_conntrack_proto_generic.c
+++ b/net/netfilter/nf_conntrack_proto_generic.c
@@ -15,9 +15,9 @@
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/netfilter.h>
-#include <net/netfilter/nf_conntrack_protocol.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
-unsigned int nf_ct_generic_timeout __read_mostly = 600*HZ;
+static unsigned int nf_ct_generic_timeout __read_mostly = 600*HZ;
static int generic_pkt_to_tuple(const struct sk_buff *skb,
unsigned int dataoff,
@@ -71,10 +71,42 @@ static int new(struct nf_conn *conntrack, const struct sk_buff *skb,
return 1;
}
-struct nf_conntrack_protocol nf_conntrack_generic_protocol =
+#ifdef CONFIG_SYSCTL
+static struct ctl_table_header *generic_sysctl_header;
+static struct ctl_table generic_sysctl_table[] = {
+ {
+ .ctl_name = NET_NF_CONNTRACK_GENERIC_TIMEOUT,
+ .procname = "nf_conntrack_generic_timeout",
+ .data = &nf_ct_generic_timeout,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = 0
+ }
+};
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+static struct ctl_table generic_compat_sysctl_table[] = {
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT,
+ .procname = "ip_conntrack_generic_timeout",
+ .data = &nf_ct_generic_timeout,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = 0
+ }
+};
+#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
+#endif /* CONFIG_SYSCTL */
+
+struct nf_conntrack_l4proto nf_conntrack_l4proto_generic =
{
.l3proto = PF_UNSPEC,
- .proto = 0,
+ .l4proto = 0,
.name = "unknown",
.pkt_to_tuple = generic_pkt_to_tuple,
.invert_tuple = generic_invert_tuple,
@@ -82,4 +114,11 @@ struct nf_conntrack_protocol nf_conntrack_generic_protocol =
.print_conntrack = generic_print_conntrack,
.packet = packet,
.new = new,
+#ifdef CONFIG_SYSCTL
+ .ctl_table_header = &generic_sysctl_header,
+ .ctl_table = generic_sysctl_table,
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+ .ctl_compat_table = generic_compat_sysctl_table,
+#endif
+#endif
};
diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c
new file mode 100644
index 000000000000..ac193ce70249
--- /dev/null
+++ b/net/netfilter/nf_conntrack_proto_gre.c
@@ -0,0 +1,305 @@
+/*
+ * ip_conntrack_proto_gre.c - Version 3.0
+ *
+ * Connection tracking protocol helper module for GRE.
+ *
+ * GRE is a generic encapsulation protocol, which is generally not very
+ * suited for NAT, as it has no protocol-specific part as port numbers.
+ *
+ * It has an optional key field, which may help us distinguishing two
+ * connections between the same two hosts.
+ *
+ * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784
+ *
+ * PPTP is built on top of a modified version of GRE, and has a mandatory
+ * field called "CallID", which serves us for the same purpose as the key
+ * field in plain GRE.
+ *
+ * Documentation about PPTP can be found in RFC 2637
+ *
+ * (C) 2000-2005 by Harald Welte <laforge@gnumonks.org>
+ *
+ * Development of this code funded by Astaro AG (http://www.astaro.com/)
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/seq_file.h>
+#include <linux/in.h>
+#include <linux/skbuff.h>
+
+#include <net/netfilter/nf_conntrack_l4proto.h>
+#include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_conntrack_core.h>
+#include <linux/netfilter/nf_conntrack_proto_gre.h>
+#include <linux/netfilter/nf_conntrack_pptp.h>
+
+#define GRE_TIMEOUT (30 * HZ)
+#define GRE_STREAM_TIMEOUT (180 * HZ)
+
+#if 0
+#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, __FUNCTION__, ## args)
+#else
+#define DEBUGP(x, args...)
+#endif
+
+static DEFINE_RWLOCK(nf_ct_gre_lock);
+static LIST_HEAD(gre_keymap_list);
+
+void nf_ct_gre_keymap_flush(void)
+{
+ struct list_head *pos, *n;
+
+ write_lock_bh(&nf_ct_gre_lock);
+ list_for_each_safe(pos, n, &gre_keymap_list) {
+ list_del(pos);
+ kfree(pos);
+ }
+ write_unlock_bh(&nf_ct_gre_lock);
+}
+EXPORT_SYMBOL(nf_ct_gre_keymap_flush);
+
+static inline int gre_key_cmpfn(const struct nf_ct_gre_keymap *km,
+ const struct nf_conntrack_tuple *t)
+{
+ return km->tuple.src.l3num == t->src.l3num &&
+ !memcmp(&km->tuple.src.u3, &t->src.u3, sizeof(t->src.u3)) &&
+ !memcmp(&km->tuple.dst.u3, &t->dst.u3, sizeof(t->dst.u3)) &&
+ km->tuple.dst.protonum == t->dst.protonum &&
+ km->tuple.dst.u.all == t->dst.u.all;
+}
+
+/* look up the source key for a given tuple */
+static __be16 gre_keymap_lookup(struct nf_conntrack_tuple *t)
+{
+ struct nf_ct_gre_keymap *km;
+ __be16 key = 0;
+
+ read_lock_bh(&nf_ct_gre_lock);
+ list_for_each_entry(km, &gre_keymap_list, list) {
+ if (gre_key_cmpfn(km, t)) {
+ key = km->tuple.src.u.gre.key;
+ break;
+ }
+ }
+ read_unlock_bh(&nf_ct_gre_lock);
+
+ DEBUGP("lookup src key 0x%x for ", key);
+ NF_CT_DUMP_TUPLE(t);
+
+ return key;
+}
+
+/* add a single keymap entry, associate with specified master ct */
+int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir,
+ struct nf_conntrack_tuple *t)
+{
+ struct nf_conn_help *help = nfct_help(ct);
+ struct nf_ct_gre_keymap **kmp, *km;
+
+ BUG_ON(strcmp(help->helper->name, "pptp"));
+ kmp = &help->help.ct_pptp_info.keymap[dir];
+ if (*kmp) {
+ /* check whether it's a retransmission */
+ list_for_each_entry(km, &gre_keymap_list, list) {
+ if (gre_key_cmpfn(km, t) && km == *kmp)
+ return 0;
+ }
+ DEBUGP("trying to override keymap_%s for ct %p\n",
+ dir == IP_CT_DIR_REPLY ? "reply" : "orig", ct);
+ return -EEXIST;
+ }
+
+ km = kmalloc(sizeof(*km), GFP_ATOMIC);
+ if (!km)
+ return -ENOMEM;
+ memcpy(&km->tuple, t, sizeof(*t));
+ *kmp = km;
+
+ DEBUGP("adding new entry %p: ", km);
+ NF_CT_DUMP_TUPLE(&km->tuple);
+
+ write_lock_bh(&nf_ct_gre_lock);
+ list_add_tail(&km->list, &gre_keymap_list);
+ write_unlock_bh(&nf_ct_gre_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(nf_ct_gre_keymap_add);
+
+/* destroy the keymap entries associated with specified master ct */
+void nf_ct_gre_keymap_destroy(struct nf_conn *ct)
+{
+ struct nf_conn_help *help = nfct_help(ct);
+ enum ip_conntrack_dir dir;
+
+ DEBUGP("entering for ct %p\n", ct);
+ BUG_ON(strcmp(help->helper->name, "pptp"));
+
+ write_lock_bh(&nf_ct_gre_lock);
+ for (dir = IP_CT_DIR_ORIGINAL; dir < IP_CT_DIR_MAX; dir++) {
+ if (help->help.ct_pptp_info.keymap[dir]) {
+ DEBUGP("removing %p from list\n",
+ help->help.ct_pptp_info.keymap[dir]);
+ list_del(&help->help.ct_pptp_info.keymap[dir]->list);
+ kfree(help->help.ct_pptp_info.keymap[dir]);
+ help->help.ct_pptp_info.keymap[dir] = NULL;
+ }
+ }
+ write_unlock_bh(&nf_ct_gre_lock);
+}
+EXPORT_SYMBOL_GPL(nf_ct_gre_keymap_destroy);
+
+/* PUBLIC CONNTRACK PROTO HELPER FUNCTIONS */
+
+/* invert gre part of tuple */
+static int gre_invert_tuple(struct nf_conntrack_tuple *tuple,
+ const struct nf_conntrack_tuple *orig)
+{
+ tuple->dst.u.gre.key = orig->src.u.gre.key;
+ tuple->src.u.gre.key = orig->dst.u.gre.key;
+ return 1;
+}
+
+/* gre hdr info to tuple */
+static int gre_pkt_to_tuple(const struct sk_buff *skb,
+ unsigned int dataoff,
+ struct nf_conntrack_tuple *tuple)
+{
+ struct gre_hdr_pptp _pgrehdr, *pgrehdr;
+ __be16 srckey;
+ struct gre_hdr _grehdr, *grehdr;
+
+ /* first only delinearize old RFC1701 GRE header */
+ grehdr = skb_header_pointer(skb, dataoff, sizeof(_grehdr), &_grehdr);
+ if (!grehdr || grehdr->version != GRE_VERSION_PPTP) {
+ /* try to behave like "nf_conntrack_proto_generic" */
+ tuple->src.u.all = 0;
+ tuple->dst.u.all = 0;
+ return 1;
+ }
+
+ /* PPTP header is variable length, only need up to the call_id field */
+ pgrehdr = skb_header_pointer(skb, dataoff, 8, &_pgrehdr);
+ if (!pgrehdr)
+ return 1;
+
+ if (ntohs(grehdr->protocol) != GRE_PROTOCOL_PPTP) {
+ DEBUGP("GRE_VERSION_PPTP but unknown proto\n");
+ return 0;
+ }
+
+ tuple->dst.u.gre.key = pgrehdr->call_id;
+ srckey = gre_keymap_lookup(tuple);
+ tuple->src.u.gre.key = srckey;
+
+ return 1;
+}
+
+/* print gre part of tuple */
+static int gre_print_tuple(struct seq_file *s,
+ const struct nf_conntrack_tuple *tuple)
+{
+ return seq_printf(s, "srckey=0x%x dstkey=0x%x ",
+ ntohs(tuple->src.u.gre.key),
+ ntohs(tuple->dst.u.gre.key));
+}
+
+/* print private data for conntrack */
+static int gre_print_conntrack(struct seq_file *s,
+ const struct nf_conn *ct)
+{
+ return seq_printf(s, "timeout=%u, stream_timeout=%u ",
+ (ct->proto.gre.timeout / HZ),
+ (ct->proto.gre.stream_timeout / HZ));
+}
+
+/* Returns verdict for packet, and may modify conntrack */
+static int gre_packet(struct nf_conn *ct,
+ const struct sk_buff *skb,
+ unsigned int dataoff,
+ enum ip_conntrack_info ctinfo,
+ int pf,
+ unsigned int hooknum)
+{
+ /* If we've seen traffic both ways, this is a GRE connection.
+ * Extend timeout. */
+ if (ct->status & IPS_SEEN_REPLY) {
+ nf_ct_refresh_acct(ct, ctinfo, skb,
+ ct->proto.gre.stream_timeout);
+ /* Also, more likely to be important, and not a probe. */
+ set_bit(IPS_ASSURED_BIT, &ct->status);
+ nf_conntrack_event_cache(IPCT_STATUS, skb);
+ } else
+ nf_ct_refresh_acct(ct, ctinfo, skb,
+ ct->proto.gre.timeout);
+
+ return NF_ACCEPT;
+}
+
+/* Called when a new connection for this protocol found. */
+static int gre_new(struct nf_conn *ct, const struct sk_buff *skb,
+ unsigned int dataoff)
+{
+ DEBUGP(": ");
+ NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+
+ /* initialize to sane value. Ideally a conntrack helper
+ * (e.g. in case of pptp) is increasing them */
+ ct->proto.gre.stream_timeout = GRE_STREAM_TIMEOUT;
+ ct->proto.gre.timeout = GRE_TIMEOUT;
+
+ return 1;
+}
+
+/* Called when a conntrack entry has already been removed from the hashes
+ * and is about to be deleted from memory */
+static void gre_destroy(struct nf_conn *ct)
+{
+ struct nf_conn *master = ct->master;
+ DEBUGP(" entering\n");
+
+ if (!master)
+ DEBUGP("no master !?!\n");
+ else
+ nf_ct_gre_keymap_destroy(master);
+}
+
+/* protocol helper struct */
+static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 = {
+ .l3proto = AF_INET,
+ .l4proto = IPPROTO_GRE,
+ .name = "gre",
+ .pkt_to_tuple = gre_pkt_to_tuple,
+ .invert_tuple = gre_invert_tuple,
+ .print_tuple = gre_print_tuple,
+ .print_conntrack = gre_print_conntrack,
+ .packet = gre_packet,
+ .new = gre_new,
+ .destroy = gre_destroy,
+ .me = THIS_MODULE,
+#if defined(CONFIG_NF_CONNTRACK_NETLINK) || \
+ defined(CONFIG_NF_CONNTRACK_NETLINK_MODULE)
+ .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
+ .nfattr_to_tuple = nf_ct_port_nfattr_to_tuple,
+#endif
+};
+
+static int __init nf_ct_proto_gre_init(void)
+{
+ return nf_conntrack_l4proto_register(&nf_conntrack_l4proto_gre4);
+}
+
+static void nf_ct_proto_gre_fini(void)
+{
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_gre4);
+ nf_ct_gre_keymap_flush();
+}
+
+module_init(nf_ct_proto_gre_init);
+module_exit(nf_ct_proto_gre_fini);
+
+MODULE_LICENSE("GPL");
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index af568777372b..76e263668222 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -32,7 +32,8 @@
#include <linux/interrupt.h>
#include <net/netfilter/nf_conntrack.h>
-#include <net/netfilter/nf_conntrack_protocol.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
+#include <net/netfilter/nf_conntrack_ecache.h>
#if 0
#define DEBUGP(format, ...) printk(format, ## __VA_ARGS__)
@@ -216,7 +217,7 @@ static int sctp_print_conntrack(struct seq_file *s,
for (offset = dataoff + sizeof(sctp_sctphdr_t), count = 0; \
offset < skb->len && \
(sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch)); \
- offset += (htons(sch->length) + 3) & ~3, count++)
+ offset += (ntohs(sch->length) + 3) & ~3, count++)
/* Some validity checks to make sure the chunks are fine */
static int do_basic_checks(struct nf_conn *conntrack,
@@ -508,36 +509,10 @@ static int sctp_new(struct nf_conn *conntrack, const struct sk_buff *skb,
return 1;
}
-struct nf_conntrack_protocol nf_conntrack_protocol_sctp4 = {
- .l3proto = PF_INET,
- .proto = IPPROTO_SCTP,
- .name = "sctp",
- .pkt_to_tuple = sctp_pkt_to_tuple,
- .invert_tuple = sctp_invert_tuple,
- .print_tuple = sctp_print_tuple,
- .print_conntrack = sctp_print_conntrack,
- .packet = sctp_packet,
- .new = sctp_new,
- .destroy = NULL,
- .me = THIS_MODULE
-};
-
-struct nf_conntrack_protocol nf_conntrack_protocol_sctp6 = {
- .l3proto = PF_INET6,
- .proto = IPPROTO_SCTP,
- .name = "sctp",
- .pkt_to_tuple = sctp_pkt_to_tuple,
- .invert_tuple = sctp_invert_tuple,
- .print_tuple = sctp_print_tuple,
- .print_conntrack = sctp_print_conntrack,
- .packet = sctp_packet,
- .new = sctp_new,
- .destroy = NULL,
- .me = THIS_MODULE
-};
-
#ifdef CONFIG_SYSCTL
-static ctl_table nf_ct_sysctl_table[] = {
+static unsigned int sctp_sysctl_table_users;
+static struct ctl_table_header *sctp_sysctl_header;
+static struct ctl_table sctp_sysctl_table[] = {
{
.ctl_name = NET_NF_CONNTRACK_SCTP_TIMEOUT_CLOSED,
.procname = "nf_conntrack_sctp_timeout_closed",
@@ -594,63 +569,134 @@ static ctl_table nf_ct_sysctl_table[] = {
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
- { .ctl_name = 0 }
+ {
+ .ctl_name = 0
+ }
};
-static ctl_table nf_ct_netfilter_table[] = {
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+static struct ctl_table sctp_compat_sysctl_table[] = {
{
- .ctl_name = NET_NETFILTER,
- .procname = "netfilter",
- .mode = 0555,
- .child = nf_ct_sysctl_table,
+ .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_CLOSED,
+ .procname = "ip_conntrack_sctp_timeout_closed",
+ .data = &nf_ct_sctp_timeout_closed,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_WAIT,
+ .procname = "ip_conntrack_sctp_timeout_cookie_wait",
+ .data = &nf_ct_sctp_timeout_cookie_wait,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_ECHOED,
+ .procname = "ip_conntrack_sctp_timeout_cookie_echoed",
+ .data = &nf_ct_sctp_timeout_cookie_echoed,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_ESTABLISHED,
+ .procname = "ip_conntrack_sctp_timeout_established",
+ .data = &nf_ct_sctp_timeout_established,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_SENT,
+ .procname = "ip_conntrack_sctp_timeout_shutdown_sent",
+ .data = &nf_ct_sctp_timeout_shutdown_sent,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_RECD,
+ .procname = "ip_conntrack_sctp_timeout_shutdown_recd",
+ .data = &nf_ct_sctp_timeout_shutdown_recd,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
},
- { .ctl_name = 0 }
-};
-
-static ctl_table nf_ct_net_table[] = {
{
- .ctl_name = CTL_NET,
- .procname = "net",
- .mode = 0555,
- .child = nf_ct_netfilter_table,
+ .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_ACK_SENT,
+ .procname = "ip_conntrack_sctp_timeout_shutdown_ack_sent",
+ .data = &nf_ct_sctp_timeout_shutdown_ack_sent,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
},
- { .ctl_name = 0 }
+ {
+ .ctl_name = 0
+ }
+};
+#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
+#endif
+
+struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 = {
+ .l3proto = PF_INET,
+ .l4proto = IPPROTO_SCTP,
+ .name = "sctp",
+ .pkt_to_tuple = sctp_pkt_to_tuple,
+ .invert_tuple = sctp_invert_tuple,
+ .print_tuple = sctp_print_tuple,
+ .print_conntrack = sctp_print_conntrack,
+ .packet = sctp_packet,
+ .new = sctp_new,
+ .me = THIS_MODULE,
+#ifdef CONFIG_SYSCTL
+ .ctl_table_users = &sctp_sysctl_table_users,
+ .ctl_table_header = &sctp_sysctl_header,
+ .ctl_table = sctp_sysctl_table,
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+ .ctl_compat_table = sctp_compat_sysctl_table,
+#endif
+#endif
};
-static struct ctl_table_header *nf_ct_sysctl_header;
+struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 = {
+ .l3proto = PF_INET6,
+ .l4proto = IPPROTO_SCTP,
+ .name = "sctp",
+ .pkt_to_tuple = sctp_pkt_to_tuple,
+ .invert_tuple = sctp_invert_tuple,
+ .print_tuple = sctp_print_tuple,
+ .print_conntrack = sctp_print_conntrack,
+ .packet = sctp_packet,
+ .new = sctp_new,
+ .me = THIS_MODULE,
+#ifdef CONFIG_SYSCTL
+ .ctl_table_users = &sctp_sysctl_table_users,
+ .ctl_table_header = &sctp_sysctl_header,
+ .ctl_table = sctp_sysctl_table,
#endif
+};
int __init nf_conntrack_proto_sctp_init(void)
{
int ret;
- ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_sctp4);
+ ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_sctp4);
if (ret) {
- printk("nf_conntrack_proto_sctp4: protocol register failed\n");
+ printk("nf_conntrack_l4proto_sctp4: protocol register failed\n");
goto out;
}
- ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_sctp6);
+ ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_sctp6);
if (ret) {
- printk("nf_conntrack_proto_sctp6: protocol register failed\n");
+ printk("nf_conntrack_l4proto_sctp6: protocol register failed\n");
goto cleanup_sctp4;
}
-#ifdef CONFIG_SYSCTL
- nf_ct_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
- if (nf_ct_sysctl_header == NULL) {
- printk("nf_conntrack_proto_sctp: can't register to sysctl.\n");
- goto cleanup;
- }
-#endif
-
return ret;
-#ifdef CONFIG_SYSCTL
- cleanup:
- nf_conntrack_protocol_unregister(&nf_conntrack_protocol_sctp6);
-#endif
cleanup_sctp4:
- nf_conntrack_protocol_unregister(&nf_conntrack_protocol_sctp4);
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
out:
DEBUGP("SCTP conntrack module loading %s\n",
ret ? "failed": "succeeded");
@@ -659,11 +705,8 @@ int __init nf_conntrack_proto_sctp_init(void)
void __exit nf_conntrack_proto_sctp_fini(void)
{
- nf_conntrack_protocol_unregister(&nf_conntrack_protocol_sctp6);
- nf_conntrack_protocol_unregister(&nf_conntrack_protocol_sctp4);
-#ifdef CONFIG_SYSCTL
- unregister_sysctl_table(nf_ct_sysctl_header);
-#endif
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp6);
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
DEBUGP("SCTP conntrack module unloaded\n");
}
@@ -673,3 +716,4 @@ module_exit(nf_conntrack_proto_sctp_fini);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Kiran Kumar Immidi");
MODULE_DESCRIPTION("Netfilter connection tracking protocol helper for SCTP");
+MODULE_ALIAS("ip_conntrack_proto_sctp");
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 238bbb5b72ef..626b0011dd89 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -42,7 +42,8 @@
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_ipv6.h>
#include <net/netfilter/nf_conntrack.h>
-#include <net/netfilter/nf_conntrack_protocol.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
+#include <net/netfilter/nf_conntrack_ecache.h>
#if 0
#define DEBUGP printk
@@ -92,22 +93,22 @@ static const char *tcp_conntrack_names[] = {
#define HOURS * 60 MINS
#define DAYS * 24 HOURS
-unsigned int nf_ct_tcp_timeout_syn_sent __read_mostly = 2 MINS;
-unsigned int nf_ct_tcp_timeout_syn_recv __read_mostly = 60 SECS;
-unsigned int nf_ct_tcp_timeout_established __read_mostly = 5 DAYS;
-unsigned int nf_ct_tcp_timeout_fin_wait __read_mostly = 2 MINS;
-unsigned int nf_ct_tcp_timeout_close_wait __read_mostly = 60 SECS;
-unsigned int nf_ct_tcp_timeout_last_ack __read_mostly = 30 SECS;
-unsigned int nf_ct_tcp_timeout_time_wait __read_mostly = 2 MINS;
-unsigned int nf_ct_tcp_timeout_close __read_mostly = 10 SECS;
+static unsigned int nf_ct_tcp_timeout_syn_sent __read_mostly = 2 MINS;
+static unsigned int nf_ct_tcp_timeout_syn_recv __read_mostly = 60 SECS;
+static unsigned int nf_ct_tcp_timeout_established __read_mostly = 5 DAYS;
+static unsigned int nf_ct_tcp_timeout_fin_wait __read_mostly = 2 MINS;
+static unsigned int nf_ct_tcp_timeout_close_wait __read_mostly = 60 SECS;
+static unsigned int nf_ct_tcp_timeout_last_ack __read_mostly = 30 SECS;
+static unsigned int nf_ct_tcp_timeout_time_wait __read_mostly = 2 MINS;
+static unsigned int nf_ct_tcp_timeout_close __read_mostly = 10 SECS;
/* RFC1122 says the R2 limit should be at least 100 seconds.
Linux uses 15 packets as limit, which corresponds
to ~13-30min depending on RTO. */
-unsigned int nf_ct_tcp_timeout_max_retrans __read_mostly = 5 MINS;
+static unsigned int nf_ct_tcp_timeout_max_retrans __read_mostly = 5 MINS;
-static unsigned int * tcp_timeouts[]
-= { NULL, /* TCP_CONNTRACK_NONE */
+static unsigned int * tcp_timeouts[] = {
+ NULL, /* TCP_CONNTRACK_NONE */
&nf_ct_tcp_timeout_syn_sent, /* TCP_CONNTRACK_SYN_SENT, */
&nf_ct_tcp_timeout_syn_recv, /* TCP_CONNTRACK_SYN_RECV, */
&nf_ct_tcp_timeout_established, /* TCP_CONNTRACK_ESTABLISHED, */
@@ -473,8 +474,8 @@ static void tcp_sack(const struct sk_buff *skb, unsigned int dataoff,
/* Fast path for timestamp-only option */
if (length == TCPOLEN_TSTAMP_ALIGNED*4
- && *(__u32 *)ptr ==
- __constant_ntohl((TCPOPT_NOP << 24)
+ && *(__be32 *)ptr ==
+ __constant_htonl((TCPOPT_NOP << 24)
| (TCPOPT_NOP << 16)
| (TCPOPT_TIMESTAMP << 8)
| TCPOLEN_TIMESTAMP))
@@ -505,9 +506,7 @@ static void tcp_sack(const struct sk_buff *skb, unsigned int dataoff,
for (i = 0;
i < (opsize - TCPOLEN_SACK_BASE);
i += TCPOLEN_SACK_PERBLOCK) {
- memcpy(&tmp, (__u32 *)(ptr + i) + 1,
- sizeof(__u32));
- tmp = ntohl(tmp);
+ tmp = ntohl(*((__be32 *)(ptr+i)+1));
if (after(tmp, *sack))
*sack = tmp;
@@ -731,7 +730,7 @@ static int tcp_in_window(struct ip_ct_tcp *state,
return res;
}
-#ifdef CONFIG_IP_NF_NAT_NEEDED
+#ifdef CONFIG_NF_NAT_NEEDED
/* Update sender->td_end after NAT successfully mangled the packet */
/* Caller must linearize skb at tcp header. */
void nf_conntrack_tcp_update(struct sk_buff *skb,
@@ -763,7 +762,7 @@ void nf_conntrack_tcp_update(struct sk_buff *skb,
receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
receiver->td_scale);
}
-
+EXPORT_SYMBOL_GPL(nf_conntrack_tcp_update);
#endif
#define TH_FIN 0x01
@@ -1167,11 +1166,221 @@ static int nfattr_to_tcp(struct nfattr *cda[], struct nf_conn *ct)
return 0;
}
#endif
-
-struct nf_conntrack_protocol nf_conntrack_protocol_tcp4 =
+
+#ifdef CONFIG_SYSCTL
+static unsigned int tcp_sysctl_table_users;
+static struct ctl_table_header *tcp_sysctl_header;
+static struct ctl_table tcp_sysctl_table[] = {
+ {
+ .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT,
+ .procname = "nf_conntrack_tcp_timeout_syn_sent",
+ .data = &nf_ct_tcp_timeout_syn_sent,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV,
+ .procname = "nf_conntrack_tcp_timeout_syn_recv",
+ .data = &nf_ct_tcp_timeout_syn_recv,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED,
+ .procname = "nf_conntrack_tcp_timeout_established",
+ .data = &nf_ct_tcp_timeout_established,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT,
+ .procname = "nf_conntrack_tcp_timeout_fin_wait",
+ .data = &nf_ct_tcp_timeout_fin_wait,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT,
+ .procname = "nf_conntrack_tcp_timeout_close_wait",
+ .data = &nf_ct_tcp_timeout_close_wait,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK,
+ .procname = "nf_conntrack_tcp_timeout_last_ack",
+ .data = &nf_ct_tcp_timeout_last_ack,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT,
+ .procname = "nf_conntrack_tcp_timeout_time_wait",
+ .data = &nf_ct_tcp_timeout_time_wait,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_CLOSE,
+ .procname = "nf_conntrack_tcp_timeout_close",
+ .data = &nf_ct_tcp_timeout_close,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_MAX_RETRANS,
+ .procname = "nf_conntrack_tcp_timeout_max_retrans",
+ .data = &nf_ct_tcp_timeout_max_retrans,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_NF_CONNTRACK_TCP_LOOSE,
+ .procname = "nf_conntrack_tcp_loose",
+ .data = &nf_ct_tcp_loose,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
+ {
+ .ctl_name = NET_NF_CONNTRACK_TCP_BE_LIBERAL,
+ .procname = "nf_conntrack_tcp_be_liberal",
+ .data = &nf_ct_tcp_be_liberal,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
+ {
+ .ctl_name = NET_NF_CONNTRACK_TCP_MAX_RETRANS,
+ .procname = "nf_conntrack_tcp_max_retrans",
+ .data = &nf_ct_tcp_max_retrans,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
+ {
+ .ctl_name = 0
+ }
+};
+
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+static struct ctl_table tcp_compat_sysctl_table[] = {
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT,
+ .procname = "ip_conntrack_tcp_timeout_syn_sent",
+ .data = &nf_ct_tcp_timeout_syn_sent,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV,
+ .procname = "ip_conntrack_tcp_timeout_syn_recv",
+ .data = &nf_ct_tcp_timeout_syn_recv,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED,
+ .procname = "ip_conntrack_tcp_timeout_established",
+ .data = &nf_ct_tcp_timeout_established,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT,
+ .procname = "ip_conntrack_tcp_timeout_fin_wait",
+ .data = &nf_ct_tcp_timeout_fin_wait,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT,
+ .procname = "ip_conntrack_tcp_timeout_close_wait",
+ .data = &nf_ct_tcp_timeout_close_wait,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK,
+ .procname = "ip_conntrack_tcp_timeout_last_ack",
+ .data = &nf_ct_tcp_timeout_last_ack,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT,
+ .procname = "ip_conntrack_tcp_timeout_time_wait",
+ .data = &nf_ct_tcp_timeout_time_wait,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE,
+ .procname = "ip_conntrack_tcp_timeout_close",
+ .data = &nf_ct_tcp_timeout_close,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_MAX_RETRANS,
+ .procname = "ip_conntrack_tcp_timeout_max_retrans",
+ .data = &nf_ct_tcp_timeout_max_retrans,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_LOOSE,
+ .procname = "ip_conntrack_tcp_loose",
+ .data = &nf_ct_tcp_loose,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_BE_LIBERAL,
+ .procname = "ip_conntrack_tcp_be_liberal",
+ .data = &nf_ct_tcp_be_liberal,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_MAX_RETRANS,
+ .procname = "ip_conntrack_tcp_max_retrans",
+ .data = &nf_ct_tcp_max_retrans,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
+ {
+ .ctl_name = 0
+ }
+};
+#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
+#endif /* CONFIG_SYSCTL */
+
+struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 =
{
.l3proto = PF_INET,
- .proto = IPPROTO_TCP,
+ .l4proto = IPPROTO_TCP,
.name = "tcp",
.pkt_to_tuple = tcp_pkt_to_tuple,
.invert_tuple = tcp_invert_tuple,
@@ -1187,12 +1396,21 @@ struct nf_conntrack_protocol nf_conntrack_protocol_tcp4 =
.tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
.nfattr_to_tuple = nf_ct_port_nfattr_to_tuple,
#endif
+#ifdef CONFIG_SYSCTL
+ .ctl_table_users = &tcp_sysctl_table_users,
+ .ctl_table_header = &tcp_sysctl_header,
+ .ctl_table = tcp_sysctl_table,
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+ .ctl_compat_table = tcp_compat_sysctl_table,
+#endif
+#endif
};
+EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_tcp4);
-struct nf_conntrack_protocol nf_conntrack_protocol_tcp6 =
+struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 =
{
.l3proto = PF_INET6,
- .proto = IPPROTO_TCP,
+ .l4proto = IPPROTO_TCP,
.name = "tcp",
.pkt_to_tuple = tcp_pkt_to_tuple,
.invert_tuple = tcp_invert_tuple,
@@ -1208,7 +1426,10 @@ struct nf_conntrack_protocol nf_conntrack_protocol_tcp6 =
.tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
.nfattr_to_tuple = nf_ct_port_nfattr_to_tuple,
#endif
+#ifdef CONFIG_SYSCTL
+ .ctl_table_users = &tcp_sysctl_table_users,
+ .ctl_table_header = &tcp_sysctl_header,
+ .ctl_table = tcp_sysctl_table,
+#endif
};
-
-EXPORT_SYMBOL(nf_conntrack_protocol_tcp4);
-EXPORT_SYMBOL(nf_conntrack_protocol_tcp6);
+EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_tcp6);
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c
index d28981cf9af5..e49cd25998c4 100644
--- a/net/netfilter/nf_conntrack_proto_udp.c
+++ b/net/netfilter/nf_conntrack_proto_udp.c
@@ -22,13 +22,15 @@
#include <linux/ipv6.h>
#include <net/ip6_checksum.h>
#include <net/checksum.h>
+
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_ipv6.h>
-#include <net/netfilter/nf_conntrack_protocol.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
+#include <net/netfilter/nf_conntrack_ecache.h>
-unsigned int nf_ct_udp_timeout __read_mostly = 30*HZ;
-unsigned int nf_ct_udp_timeout_stream __read_mostly = 180*HZ;
+static unsigned int nf_ct_udp_timeout __read_mostly = 30*HZ;
+static unsigned int nf_ct_udp_timeout_stream __read_mostly = 180*HZ;
static int udp_pkt_to_tuple(const struct sk_buff *skb,
unsigned int dataoff,
@@ -146,10 +148,59 @@ static int udp_error(struct sk_buff *skb, unsigned int dataoff,
return NF_ACCEPT;
}
-struct nf_conntrack_protocol nf_conntrack_protocol_udp4 =
+#ifdef CONFIG_SYSCTL
+static unsigned int udp_sysctl_table_users;
+static struct ctl_table_header *udp_sysctl_header;
+static struct ctl_table udp_sysctl_table[] = {
+ {
+ .ctl_name = NET_NF_CONNTRACK_UDP_TIMEOUT,
+ .procname = "nf_conntrack_udp_timeout",
+ .data = &nf_ct_udp_timeout,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_NF_CONNTRACK_UDP_TIMEOUT_STREAM,
+ .procname = "nf_conntrack_udp_timeout_stream",
+ .data = &nf_ct_udp_timeout_stream,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = 0
+ }
+};
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+static struct ctl_table udp_compat_sysctl_table[] = {
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT,
+ .procname = "ip_conntrack_udp_timeout",
+ .data = &nf_ct_udp_timeout,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT_STREAM,
+ .procname = "ip_conntrack_udp_timeout_stream",
+ .data = &nf_ct_udp_timeout_stream,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = 0
+ }
+};
+#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
+#endif /* CONFIG_SYSCTL */
+
+struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 =
{
.l3proto = PF_INET,
- .proto = IPPROTO_UDP,
+ .l4proto = IPPROTO_UDP,
.name = "udp",
.pkt_to_tuple = udp_pkt_to_tuple,
.invert_tuple = udp_invert_tuple,
@@ -163,12 +214,21 @@ struct nf_conntrack_protocol nf_conntrack_protocol_udp4 =
.tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
.nfattr_to_tuple = nf_ct_port_nfattr_to_tuple,
#endif
+#ifdef CONFIG_SYSCTL
+ .ctl_table_users = &udp_sysctl_table_users,
+ .ctl_table_header = &udp_sysctl_header,
+ .ctl_table = udp_sysctl_table,
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+ .ctl_compat_table = udp_compat_sysctl_table,
+#endif
+#endif
};
+EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp4);
-struct nf_conntrack_protocol nf_conntrack_protocol_udp6 =
+struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 =
{
.l3proto = PF_INET6,
- .proto = IPPROTO_UDP,
+ .l4proto = IPPROTO_UDP,
.name = "udp",
.pkt_to_tuple = udp_pkt_to_tuple,
.invert_tuple = udp_invert_tuple,
@@ -182,7 +242,10 @@ struct nf_conntrack_protocol nf_conntrack_protocol_udp6 =
.tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
.nfattr_to_tuple = nf_ct_port_nfattr_to_tuple,
#endif
+#ifdef CONFIG_SYSCTL
+ .ctl_table_users = &udp_sysctl_table_users,
+ .ctl_table_header = &udp_sysctl_header,
+ .ctl_table = udp_sysctl_table,
+#endif
};
-
-EXPORT_SYMBOL(nf_conntrack_protocol_udp4);
-EXPORT_SYMBOL(nf_conntrack_protocol_udp6);
+EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp6);
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
new file mode 100644
index 000000000000..eb2a2411f97b
--- /dev/null
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -0,0 +1,531 @@
+/* SIP extension for IP connection tracking.
+ *
+ * (C) 2005 by Christian Hentschel <chentschel@arnet.com.ar>
+ * based on RR's ip_conntrack_ftp.c and other modules.
+ *
+ * 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/ctype.h>
+#include <linux/skbuff.h>
+#include <linux/inet.h>
+#include <linux/in.h>
+#include <linux/udp.h>
+#include <linux/netfilter.h>
+
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_expect.h>
+#include <net/netfilter/nf_conntrack_helper.h>
+#include <linux/netfilter/nf_conntrack_sip.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com.ar>");
+MODULE_DESCRIPTION("SIP connection tracking helper");
+MODULE_ALIAS("ip_conntrack_sip");
+
+#define MAX_PORTS 8
+static unsigned short ports[MAX_PORTS];
+static int ports_c;
+module_param_array(ports, ushort, &ports_c, 0400);
+MODULE_PARM_DESC(ports, "port numbers of SIP servers");
+
+static unsigned int sip_timeout __read_mostly = SIP_TIMEOUT;
+module_param(sip_timeout, uint, 0600);
+MODULE_PARM_DESC(sip_timeout, "timeout for the master SIP session");
+
+unsigned int (*nf_nat_sip_hook)(struct sk_buff **pskb,
+ enum ip_conntrack_info ctinfo,
+ struct nf_conn *ct,
+ const char **dptr) __read_mostly;
+EXPORT_SYMBOL_GPL(nf_nat_sip_hook);
+
+unsigned int (*nf_nat_sdp_hook)(struct sk_buff **pskb,
+ enum ip_conntrack_info ctinfo,
+ struct nf_conntrack_expect *exp,
+ const char *dptr) __read_mostly;
+EXPORT_SYMBOL_GPL(nf_nat_sdp_hook);
+
+static int digits_len(struct nf_conn *, const char *, const char *, int *);
+static int epaddr_len(struct nf_conn *, const char *, const char *, int *);
+static int skp_digits_len(struct nf_conn *, const char *, const char *, int *);
+static int skp_epaddr_len(struct nf_conn *, const char *, const char *, int *);
+
+struct sip_header_nfo {
+ const char *lname;
+ const char *sname;
+ const char *ln_str;
+ size_t lnlen;
+ size_t snlen;
+ size_t ln_strlen;
+ int case_sensitive;
+ int (*match_len)(struct nf_conn *, const char *,
+ const char *, int *);
+};
+
+static const struct sip_header_nfo ct_sip_hdrs[] = {
+ [POS_REG_REQ_URI] = { /* SIP REGISTER request URI */
+ .lname = "sip:",
+ .lnlen = sizeof("sip:") - 1,
+ .ln_str = ":",
+ .ln_strlen = sizeof(":") - 1,
+ .match_len = epaddr_len,
+ },
+ [POS_REQ_URI] = { /* SIP request URI */
+ .lname = "sip:",
+ .lnlen = sizeof("sip:") - 1,
+ .ln_str = "@",
+ .ln_strlen = sizeof("@") - 1,
+ .match_len = epaddr_len,
+ },
+ [POS_FROM] = { /* SIP From header */
+ .lname = "From:",
+ .lnlen = sizeof("From:") - 1,
+ .sname = "\r\nf:",
+ .snlen = sizeof("\r\nf:") - 1,
+ .ln_str = "sip:",
+ .ln_strlen = sizeof("sip:") - 1,
+ .match_len = skp_epaddr_len,
+ },
+ [POS_TO] = { /* SIP To header */
+ .lname = "To:",
+ .lnlen = sizeof("To:") - 1,
+ .sname = "\r\nt:",
+ .snlen = sizeof("\r\nt:") - 1,
+ .ln_str = "sip:",
+ .ln_strlen = sizeof("sip:") - 1,
+ .match_len = skp_epaddr_len
+ },
+ [POS_VIA] = { /* SIP Via header */
+ .lname = "Via:",
+ .lnlen = sizeof("Via:") - 1,
+ .sname = "\r\nv:",
+ .snlen = sizeof("\r\nv:") - 1, /* rfc3261 "\r\n" */
+ .ln_str = "UDP ",
+ .ln_strlen = sizeof("UDP ") - 1,
+ .match_len = epaddr_len,
+ },
+ [POS_CONTACT] = { /* SIP Contact header */
+ .lname = "Contact:",
+ .lnlen = sizeof("Contact:") - 1,
+ .sname = "\r\nm:",
+ .snlen = sizeof("\r\nm:") - 1,
+ .ln_str = "sip:",
+ .ln_strlen = sizeof("sip:") - 1,
+ .match_len = skp_epaddr_len
+ },
+ [POS_CONTENT] = { /* SIP Content length header */
+ .lname = "Content-Length:",
+ .lnlen = sizeof("Content-Length:") - 1,
+ .sname = "\r\nl:",
+ .snlen = sizeof("\r\nl:") - 1,
+ .ln_str = ":",
+ .ln_strlen = sizeof(":") - 1,
+ .match_len = skp_digits_len
+ },
+ [POS_MEDIA] = { /* SDP media info */
+ .case_sensitive = 1,
+ .lname = "\nm=",
+ .lnlen = sizeof("\nm=") - 1,
+ .sname = "\rm=",
+ .snlen = sizeof("\rm=") - 1,
+ .ln_str = "audio ",
+ .ln_strlen = sizeof("audio ") - 1,
+ .match_len = digits_len
+ },
+ [POS_OWNER_IP4] = { /* SDP owner address*/
+ .case_sensitive = 1,
+ .lname = "\no=",
+ .lnlen = sizeof("\no=") - 1,
+ .sname = "\ro=",
+ .snlen = sizeof("\ro=") - 1,
+ .ln_str = "IN IP4 ",
+ .ln_strlen = sizeof("IN IP4 ") - 1,
+ .match_len = epaddr_len
+ },
+ [POS_CONNECTION_IP4] = {/* SDP connection info */
+ .case_sensitive = 1,
+ .lname = "\nc=",
+ .lnlen = sizeof("\nc=") - 1,
+ .sname = "\rc=",
+ .snlen = sizeof("\rc=") - 1,
+ .ln_str = "IN IP4 ",
+ .ln_strlen = sizeof("IN IP4 ") - 1,
+ .match_len = epaddr_len
+ },
+ [POS_OWNER_IP6] = { /* SDP owner address*/
+ .case_sensitive = 1,
+ .lname = "\no=",
+ .lnlen = sizeof("\no=") - 1,
+ .sname = "\ro=",
+ .snlen = sizeof("\ro=") - 1,
+ .ln_str = "IN IP6 ",
+ .ln_strlen = sizeof("IN IP6 ") - 1,
+ .match_len = epaddr_len
+ },
+ [POS_CONNECTION_IP6] = {/* SDP connection info */
+ .case_sensitive = 1,
+ .lname = "\nc=",
+ .lnlen = sizeof("\nc=") - 1,
+ .sname = "\rc=",
+ .snlen = sizeof("\rc=") - 1,
+ .ln_str = "IN IP6 ",
+ .ln_strlen = sizeof("IN IP6 ") - 1,
+ .match_len = epaddr_len
+ },
+ [POS_SDP_HEADER] = { /* SDP version header */
+ .case_sensitive = 1,
+ .lname = "\nv=",
+ .lnlen = sizeof("\nv=") - 1,
+ .sname = "\rv=",
+ .snlen = sizeof("\rv=") - 1,
+ .ln_str = "=",
+ .ln_strlen = sizeof("=") - 1,
+ .match_len = digits_len
+ }
+};
+
+/* get line lenght until first CR or LF seen. */
+int ct_sip_lnlen(const char *line, const char *limit)
+{
+ const char *k = line;
+
+ while ((line <= limit) && (*line == '\r' || *line == '\n'))
+ line++;
+
+ while (line <= limit) {
+ if (*line == '\r' || *line == '\n')
+ break;
+ line++;
+ }
+ return line - k;
+}
+EXPORT_SYMBOL_GPL(ct_sip_lnlen);
+
+/* Linear string search, case sensitive. */
+const char *ct_sip_search(const char *needle, const char *haystack,
+ size_t needle_len, size_t haystack_len,
+ int case_sensitive)
+{
+ const char *limit = haystack + (haystack_len - needle_len);
+
+ while (haystack <= limit) {
+ if (case_sensitive) {
+ if (strncmp(haystack, needle, needle_len) == 0)
+ return haystack;
+ } else {
+ if (strnicmp(haystack, needle, needle_len) == 0)
+ return haystack;
+ }
+ haystack++;
+ }
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(ct_sip_search);
+
+static int digits_len(struct nf_conn *ct, const char *dptr,
+ const char *limit, int *shift)
+{
+ int len = 0;
+ while (dptr <= limit && isdigit(*dptr)) {
+ dptr++;
+ len++;
+ }
+ return len;
+}
+
+/* get digits lenght, skiping blank spaces. */
+static int skp_digits_len(struct nf_conn *ct, const char *dptr,
+ const char *limit, int *shift)
+{
+ for (; dptr <= limit && *dptr == ' '; dptr++)
+ (*shift)++;
+
+ return digits_len(ct, dptr, limit, shift);
+}
+
+static int parse_addr(struct nf_conn *ct, const char *cp, const char **endp,
+ union nf_conntrack_address *addr, const char *limit)
+{
+ const char *end;
+ int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
+ int ret = 0;
+
+ switch (family) {
+ case AF_INET:
+ ret = in4_pton(cp, limit - cp, (u8 *)&addr->ip, -1, &end);
+ break;
+ case AF_INET6:
+ ret = in6_pton(cp, limit - cp, (u8 *)&addr->ip6, -1, &end);
+ break;
+ default:
+ BUG();
+ }
+
+ if (ret == 0 || end == cp)
+ return 0;
+ if (endp)
+ *endp = end;
+ return 1;
+}
+
+/* skip ip address. returns its length. */
+static int epaddr_len(struct nf_conn *ct, const char *dptr,
+ const char *limit, int *shift)
+{
+ union nf_conntrack_address addr;
+ const char *aux = dptr;
+
+ if (!parse_addr(ct, dptr, &dptr, &addr, limit)) {
+ DEBUGP("ip: %s parse failed.!\n", dptr);
+ return 0;
+ }
+
+ /* Port number */
+ if (*dptr == ':') {
+ dptr++;
+ dptr += digits_len(ct, dptr, limit, shift);
+ }
+ return dptr - aux;
+}
+
+/* get address length, skiping user info. */
+static int skp_epaddr_len(struct nf_conn *ct, const char *dptr,
+ const char *limit, int *shift)
+{
+ int s = *shift;
+
+ for (; dptr <= limit && *dptr != '@'; dptr++)
+ (*shift)++;
+
+ if (*dptr == '@') {
+ dptr++;
+ (*shift)++;
+ } else
+ *shift = s;
+
+ return epaddr_len(ct, dptr, limit, shift);
+}
+
+/* Returns 0 if not found, -1 error parsing. */
+int ct_sip_get_info(struct nf_conn *ct,
+ const char *dptr, size_t dlen,
+ unsigned int *matchoff,
+ unsigned int *matchlen,
+ enum sip_header_pos pos)
+{
+ const struct sip_header_nfo *hnfo = &ct_sip_hdrs[pos];
+ const char *limit, *aux, *k = dptr;
+ int shift = 0;
+
+ limit = dptr + (dlen - hnfo->lnlen);
+
+ while (dptr <= limit) {
+ if ((strncmp(dptr, hnfo->lname, hnfo->lnlen) != 0) &&
+ (strncmp(dptr, hnfo->sname, hnfo->snlen) != 0)) {
+ dptr++;
+ continue;
+ }
+ aux = ct_sip_search(hnfo->ln_str, dptr, hnfo->ln_strlen,
+ ct_sip_lnlen(dptr, limit),
+ hnfo->case_sensitive);
+ if (!aux) {
+ DEBUGP("'%s' not found in '%s'.\n", hnfo->ln_str,
+ hnfo->lname);
+ return -1;
+ }
+ aux += hnfo->ln_strlen;
+
+ *matchlen = hnfo->match_len(ct, aux, limit, &shift);
+ if (!*matchlen)
+ return -1;
+
+ *matchoff = (aux - k) + shift;
+
+ DEBUGP("%s match succeeded! - len: %u\n", hnfo->lname,
+ *matchlen);
+ return 1;
+ }
+ DEBUGP("%s header not found.\n", hnfo->lname);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ct_sip_get_info);
+
+static int set_expected_rtp(struct sk_buff **pskb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ union nf_conntrack_address *addr,
+ __be16 port,
+ const char *dptr)
+{
+ struct nf_conntrack_expect *exp;
+ enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+ int family = ct->tuplehash[!dir].tuple.src.l3num;
+ int ret;
+ typeof(nf_nat_sdp_hook) nf_nat_sdp;
+
+ exp = nf_conntrack_expect_alloc(ct);
+ if (exp == NULL)
+ return NF_DROP;
+ nf_conntrack_expect_init(exp, family,
+ &ct->tuplehash[!dir].tuple.src.u3, addr,
+ IPPROTO_UDP, NULL, &port);
+
+ nf_nat_sdp = rcu_dereference(nf_nat_sdp_hook);
+ if (nf_nat_sdp && ct->status & IPS_NAT_MASK)
+ ret = nf_nat_sdp(pskb, ctinfo, exp, dptr);
+ else {
+ if (nf_conntrack_expect_related(exp) != 0)
+ ret = NF_DROP;
+ else
+ ret = NF_ACCEPT;
+ }
+ nf_conntrack_expect_put(exp);
+
+ return ret;
+}
+
+static int sip_help(struct sk_buff **pskb,
+ unsigned int protoff,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo)
+{
+ int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
+ union nf_conntrack_address addr;
+ unsigned int dataoff, datalen;
+ const char *dptr;
+ int ret = NF_ACCEPT;
+ int matchoff, matchlen;
+ u_int16_t port;
+ enum sip_header_pos pos;
+ typeof(nf_nat_sip_hook) nf_nat_sip;
+
+ /* No Data ? */
+ dataoff = protoff + sizeof(struct udphdr);
+ if (dataoff >= (*pskb)->len)
+ return NF_ACCEPT;
+
+ nf_ct_refresh(ct, *pskb, sip_timeout * HZ);
+
+ if (!skb_is_nonlinear(*pskb))
+ dptr = (*pskb)->data + dataoff;
+ else {
+ DEBUGP("Copy of skbuff not supported yet.\n");
+ goto out;
+ }
+
+ nf_nat_sip = rcu_dereference(nf_nat_sip_hook);
+ if (nf_nat_sip && ct->status & IPS_NAT_MASK) {
+ if (!nf_nat_sip(pskb, ctinfo, ct, &dptr)) {
+ ret = NF_DROP;
+ goto out;
+ }
+ }
+
+ datalen = (*pskb)->len - dataoff;
+ if (datalen < sizeof("SIP/2.0 200") - 1)
+ goto out;
+
+ /* RTP info only in some SDP pkts */
+ if (memcmp(dptr, "INVITE", sizeof("INVITE") - 1) != 0 &&
+ memcmp(dptr, "SIP/2.0 200", sizeof("SIP/2.0 200") - 1) != 0) {
+ goto out;
+ }
+ /* Get address and port from SDP packet. */
+ pos = family == AF_INET ? POS_CONNECTION_IP4 : POS_CONNECTION_IP6;
+ if (ct_sip_get_info(ct, dptr, datalen, &matchoff, &matchlen, pos) > 0) {
+
+ /* We'll drop only if there are parse problems. */
+ if (!parse_addr(ct, dptr + matchoff, NULL, &addr,
+ dptr + datalen)) {
+ ret = NF_DROP;
+ goto out;
+ }
+ if (ct_sip_get_info(ct, dptr, datalen, &matchoff, &matchlen,
+ POS_MEDIA) > 0) {
+
+ port = simple_strtoul(dptr + matchoff, NULL, 10);
+ if (port < 1024) {
+ ret = NF_DROP;
+ goto out;
+ }
+ ret = set_expected_rtp(pskb, ct, ctinfo, &addr,
+ htons(port), dptr);
+ }
+ }
+out:
+ return ret;
+}
+
+static struct nf_conntrack_helper sip[MAX_PORTS][2] __read_mostly;
+static char sip_names[MAX_PORTS][2][sizeof("sip-65535")] __read_mostly;
+
+static void nf_conntrack_sip_fini(void)
+{
+ int i, j;
+
+ for (i = 0; i < ports_c; i++) {
+ for (j = 0; j < 2; j++) {
+ if (sip[i][j].me == NULL)
+ continue;
+ nf_conntrack_helper_unregister(&sip[i][j]);
+ }
+ }
+}
+
+static int __init nf_conntrack_sip_init(void)
+{
+ int i, j, ret;
+ char *tmpname;
+
+ if (ports_c == 0)
+ ports[ports_c++] = SIP_PORT;
+
+ for (i = 0; i < ports_c; i++) {
+ memset(&sip[i], 0, sizeof(sip[i]));
+
+ sip[i][0].tuple.src.l3num = AF_INET;
+ sip[i][1].tuple.src.l3num = AF_INET6;
+ for (j = 0; j < 2; j++) {
+ sip[i][j].tuple.dst.protonum = IPPROTO_UDP;
+ sip[i][j].tuple.src.u.udp.port = htons(ports[i]);
+ sip[i][j].mask.src.l3num = 0xFFFF;
+ sip[i][j].mask.src.u.udp.port = htons(0xFFFF);
+ sip[i][j].mask.dst.protonum = 0xFF;
+ sip[i][j].max_expected = 2;
+ sip[i][j].timeout = 3 * 60; /* 3 minutes */
+ sip[i][j].me = THIS_MODULE;
+ sip[i][j].help = sip_help;
+
+ tmpname = &sip_names[i][j][0];
+ if (ports[i] == SIP_PORT)
+ sprintf(tmpname, "sip");
+ else
+ sprintf(tmpname, "sip-%u", i);
+ sip[i][j].name = tmpname;
+
+ DEBUGP("port #%u: %u\n", i, ports[i]);
+
+ ret = nf_conntrack_helper_register(&sip[i][j]);
+ if (ret) {
+ printk("nf_ct_sip: failed to register helper "
+ "for pf: %u port: %u\n",
+ sip[i][j].tuple.src.l3num, ports[i]);
+ nf_conntrack_sip_fini();
+ return ret;
+ }
+ }
+ }
+ return 0;
+}
+
+module_init(nf_conntrack_sip_init);
+module_exit(nf_conntrack_sip_fini);
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 5954f6773810..f1cb60ff9319 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -29,13 +29,11 @@
#include <linux/sysctl.h>
#endif
-#define ASSERT_READ_LOCK(x)
-#define ASSERT_WRITE_LOCK(x)
-
#include <net/netfilter/nf_conntrack.h>
-#include <net/netfilter/nf_conntrack_l3proto.h>
-#include <net/netfilter/nf_conntrack_protocol.h>
#include <net/netfilter/nf_conntrack_core.h>
+#include <net/netfilter/nf_conntrack_l3proto.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
+#include <net/netfilter/nf_conntrack_expect.h>
#include <net/netfilter/nf_conntrack_helper.h>
#if 0
@@ -46,33 +44,15 @@
MODULE_LICENSE("GPL");
-extern atomic_t nf_conntrack_count;
-DECLARE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat);
-
-static int kill_l3proto(struct nf_conn *i, void *data)
-{
- return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num ==
- ((struct nf_conntrack_l3proto *)data)->l3proto);
-}
-
-static int kill_proto(struct nf_conn *i, void *data)
-{
- struct nf_conntrack_protocol *proto;
- proto = (struct nf_conntrack_protocol *)data;
- return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum ==
- proto->proto) &&
- (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num ==
- proto->l3proto);
-}
-
#ifdef CONFIG_PROC_FS
-static int
+int
print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple,
struct nf_conntrack_l3proto *l3proto,
- struct nf_conntrack_protocol *proto)
+ struct nf_conntrack_l4proto *l4proto)
{
- return l3proto->print_tuple(s, tuple) || proto->print_tuple(s, tuple);
+ return l3proto->print_tuple(s, tuple) || l4proto->print_tuple(s, tuple);
}
+EXPORT_SYMBOL_GPL(print_tuple);
#ifdef CONFIG_NF_CT_ACCT
static unsigned int
@@ -150,9 +130,8 @@ static int ct_seq_show(struct seq_file *s, void *v)
const struct nf_conntrack_tuple_hash *hash = v;
const struct nf_conn *conntrack = nf_ct_tuplehash_to_ctrack(hash);
struct nf_conntrack_l3proto *l3proto;
- struct nf_conntrack_protocol *proto;
+ struct nf_conntrack_l4proto *l4proto;
- ASSERT_READ_LOCK(&nf_conntrack_lock);
NF_CT_ASSERT(conntrack);
/* we only want to print DIR_ORIGINAL */
@@ -163,16 +142,16 @@ static int ct_seq_show(struct seq_file *s, void *v)
.tuple.src.l3num);
NF_CT_ASSERT(l3proto);
- proto = __nf_ct_proto_find(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
+ l4proto = __nf_ct_l4proto_find(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
.tuple.src.l3num,
conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
.tuple.dst.protonum);
- NF_CT_ASSERT(proto);
+ NF_CT_ASSERT(l4proto);
if (seq_printf(s, "%-8s %u %-8s %u %ld ",
l3proto->name,
conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num,
- proto->name,
+ l4proto->name,
conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum,
timer_pending(&conntrack->timeout)
? (long)(conntrack->timeout.expires - jiffies)/HZ : 0) != 0)
@@ -181,11 +160,11 @@ static int ct_seq_show(struct seq_file *s, void *v)
if (l3proto->print_conntrack(s, conntrack))
return -ENOSPC;
- if (proto->print_conntrack(s, conntrack))
+ if (l4proto->print_conntrack(s, conntrack))
return -ENOSPC;
if (print_tuple(s, &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
- l3proto, proto))
+ l3proto, l4proto))
return -ENOSPC;
if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_ORIGINAL]))
@@ -196,7 +175,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
return -ENOSPC;
if (print_tuple(s, &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple,
- l3proto, proto))
+ l3proto, l4proto))
return -ENOSPC;
if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_REPLY]))
@@ -258,84 +237,6 @@ static struct file_operations ct_file_ops = {
.release = seq_release_private,
};
-/* expects */
-static void *exp_seq_start(struct seq_file *s, loff_t *pos)
-{
- struct list_head *e = &nf_conntrack_expect_list;
- loff_t i;
-
- /* strange seq_file api calls stop even if we fail,
- * thus we need to grab lock since stop unlocks */
- read_lock_bh(&nf_conntrack_lock);
-
- if (list_empty(e))
- return NULL;
-
- for (i = 0; i <= *pos; i++) {
- e = e->next;
- if (e == &nf_conntrack_expect_list)
- return NULL;
- }
- return e;
-}
-
-static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos)
-{
- struct list_head *e = v;
-
- ++*pos;
- e = e->next;
-
- if (e == &nf_conntrack_expect_list)
- return NULL;
-
- return e;
-}
-
-static void exp_seq_stop(struct seq_file *s, void *v)
-{
- read_unlock_bh(&nf_conntrack_lock);
-}
-
-static int exp_seq_show(struct seq_file *s, void *v)
-{
- struct nf_conntrack_expect *expect = v;
-
- if (expect->timeout.function)
- seq_printf(s, "%ld ", timer_pending(&expect->timeout)
- ? (long)(expect->timeout.expires - jiffies)/HZ : 0);
- else
- seq_printf(s, "- ");
- seq_printf(s, "l3proto = %u proto=%u ",
- expect->tuple.src.l3num,
- expect->tuple.dst.protonum);
- print_tuple(s, &expect->tuple,
- __nf_ct_l3proto_find(expect->tuple.src.l3num),
- __nf_ct_proto_find(expect->tuple.src.l3num,
- expect->tuple.dst.protonum));
- return seq_putc(s, '\n');
-}
-
-static struct seq_operations exp_seq_ops = {
- .start = exp_seq_start,
- .next = exp_seq_next,
- .stop = exp_seq_stop,
- .show = exp_seq_show
-};
-
-static int exp_open(struct inode *inode, struct file *file)
-{
- return seq_open(file, &exp_seq_ops);
-}
-
-static struct file_operations exp_file_ops = {
- .owner = THIS_MODULE,
- .open = exp_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = seq_release
-};
-
static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos)
{
int cpu;
@@ -428,34 +329,9 @@ static struct file_operations ct_cpu_seq_fops = {
/* Sysctl support */
int nf_conntrack_checksum __read_mostly = 1;
+EXPORT_SYMBOL_GPL(nf_conntrack_checksum);
#ifdef CONFIG_SYSCTL
-
-/* From nf_conntrack_core.c */
-extern int nf_conntrack_max;
-extern unsigned int nf_conntrack_htable_size;
-
-/* From nf_conntrack_proto_tcp.c */
-extern unsigned int nf_ct_tcp_timeout_syn_sent;
-extern unsigned int nf_ct_tcp_timeout_syn_recv;
-extern unsigned int nf_ct_tcp_timeout_established;
-extern unsigned int nf_ct_tcp_timeout_fin_wait;
-extern unsigned int nf_ct_tcp_timeout_close_wait;
-extern unsigned int nf_ct_tcp_timeout_last_ack;
-extern unsigned int nf_ct_tcp_timeout_time_wait;
-extern unsigned int nf_ct_tcp_timeout_close;
-extern unsigned int nf_ct_tcp_timeout_max_retrans;
-extern int nf_ct_tcp_loose;
-extern int nf_ct_tcp_be_liberal;
-extern int nf_ct_tcp_max_retrans;
-
-/* From nf_conntrack_proto_udp.c */
-extern unsigned int nf_ct_udp_timeout;
-extern unsigned int nf_ct_udp_timeout_stream;
-
-/* From nf_conntrack_proto_generic.c */
-extern unsigned int nf_ct_generic_timeout;
-
/* Log invalid packets of a given protocol */
static int log_invalid_proto_min = 0;
static int log_invalid_proto_max = 255;
@@ -496,94 +372,6 @@ static ctl_table nf_ct_sysctl_table[] = {
.proc_handler = &proc_dointvec,
},
{
- .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT,
- .procname = "nf_conntrack_tcp_timeout_syn_sent",
- .data = &nf_ct_tcp_timeout_syn_sent,
- .maxlen = sizeof(unsigned int),
- .mode = 0644,
- .proc_handler = &proc_dointvec_jiffies,
- },
- {
- .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV,
- .procname = "nf_conntrack_tcp_timeout_syn_recv",
- .data = &nf_ct_tcp_timeout_syn_recv,
- .maxlen = sizeof(unsigned int),
- .mode = 0644,
- .proc_handler = &proc_dointvec_jiffies,
- },
- {
- .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED,
- .procname = "nf_conntrack_tcp_timeout_established",
- .data = &nf_ct_tcp_timeout_established,
- .maxlen = sizeof(unsigned int),
- .mode = 0644,
- .proc_handler = &proc_dointvec_jiffies,
- },
- {
- .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT,
- .procname = "nf_conntrack_tcp_timeout_fin_wait",
- .data = &nf_ct_tcp_timeout_fin_wait,
- .maxlen = sizeof(unsigned int),
- .mode = 0644,
- .proc_handler = &proc_dointvec_jiffies,
- },
- {
- .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT,
- .procname = "nf_conntrack_tcp_timeout_close_wait",
- .data = &nf_ct_tcp_timeout_close_wait,
- .maxlen = sizeof(unsigned int),
- .mode = 0644,
- .proc_handler = &proc_dointvec_jiffies,
- },
- {
- .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK,
- .procname = "nf_conntrack_tcp_timeout_last_ack",
- .data = &nf_ct_tcp_timeout_last_ack,
- .maxlen = sizeof(unsigned int),
- .mode = 0644,
- .proc_handler = &proc_dointvec_jiffies,
- },
- {
- .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT,
- .procname = "nf_conntrack_tcp_timeout_time_wait",
- .data = &nf_ct_tcp_timeout_time_wait,
- .maxlen = sizeof(unsigned int),
- .mode = 0644,
- .proc_handler = &proc_dointvec_jiffies,
- },
- {
- .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_CLOSE,
- .procname = "nf_conntrack_tcp_timeout_close",
- .data = &nf_ct_tcp_timeout_close,
- .maxlen = sizeof(unsigned int),
- .mode = 0644,
- .proc_handler = &proc_dointvec_jiffies,
- },
- {
- .ctl_name = NET_NF_CONNTRACK_UDP_TIMEOUT,
- .procname = "nf_conntrack_udp_timeout",
- .data = &nf_ct_udp_timeout,
- .maxlen = sizeof(unsigned int),
- .mode = 0644,
- .proc_handler = &proc_dointvec_jiffies,
- },
- {
- .ctl_name = NET_NF_CONNTRACK_UDP_TIMEOUT_STREAM,
- .procname = "nf_conntrack_udp_timeout_stream",
- .data = &nf_ct_udp_timeout_stream,
- .maxlen = sizeof(unsigned int),
- .mode = 0644,
- .proc_handler = &proc_dointvec_jiffies,
- },
- {
- .ctl_name = NET_NF_CONNTRACK_GENERIC_TIMEOUT,
- .procname = "nf_conntrack_generic_timeout",
- .data = &nf_ct_generic_timeout,
- .maxlen = sizeof(unsigned int),
- .mode = 0644,
- .proc_handler = &proc_dointvec_jiffies,
- },
- {
.ctl_name = NET_NF_CONNTRACK_LOG_INVALID,
.procname = "nf_conntrack_log_invalid",
.data = &nf_ct_log_invalid,
@@ -594,38 +382,6 @@ static ctl_table nf_ct_sysctl_table[] = {
.extra1 = &log_invalid_proto_min,
.extra2 = &log_invalid_proto_max,
},
- {
- .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_MAX_RETRANS,
- .procname = "nf_conntrack_tcp_timeout_max_retrans",
- .data = &nf_ct_tcp_timeout_max_retrans,
- .maxlen = sizeof(unsigned int),
- .mode = 0644,
- .proc_handler = &proc_dointvec_jiffies,
- },
- {
- .ctl_name = NET_NF_CONNTRACK_TCP_LOOSE,
- .procname = "nf_conntrack_tcp_loose",
- .data = &nf_ct_tcp_loose,
- .maxlen = sizeof(unsigned int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_NF_CONNTRACK_TCP_BE_LIBERAL,
- .procname = "nf_conntrack_tcp_be_liberal",
- .data = &nf_ct_tcp_be_liberal,
- .maxlen = sizeof(unsigned int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_NF_CONNTRACK_TCP_MAX_RETRANS,
- .procname = "nf_conntrack_tcp_max_retrans",
- .data = &nf_ct_tcp_max_retrans,
- .maxlen = sizeof(unsigned int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
{ .ctl_name = 0 }
};
@@ -659,109 +415,9 @@ static ctl_table nf_ct_net_table[] = {
},
{ .ctl_name = 0 }
};
-EXPORT_SYMBOL(nf_ct_log_invalid);
+EXPORT_SYMBOL_GPL(nf_ct_log_invalid);
#endif /* CONFIG_SYSCTL */
-int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto)
-{
- int ret = 0;
-
- write_lock_bh(&nf_conntrack_lock);
- if (nf_ct_l3protos[proto->l3proto] != &nf_conntrack_generic_l3proto) {
- ret = -EBUSY;
- goto out;
- }
- nf_ct_l3protos[proto->l3proto] = proto;
-out:
- write_unlock_bh(&nf_conntrack_lock);
-
- return ret;
-}
-
-void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto)
-{
- write_lock_bh(&nf_conntrack_lock);
- nf_ct_l3protos[proto->l3proto] = &nf_conntrack_generic_l3proto;
- write_unlock_bh(&nf_conntrack_lock);
-
- /* Somebody could be still looking at the proto in bh. */
- synchronize_net();
-
- /* Remove all contrack entries for this protocol */
- nf_ct_iterate_cleanup(kill_l3proto, proto);
-}
-
-/* FIXME: Allow NULL functions and sub in pointers to generic for
- them. --RR */
-int nf_conntrack_protocol_register(struct nf_conntrack_protocol *proto)
-{
- int ret = 0;
-
-retry:
- write_lock_bh(&nf_conntrack_lock);
- if (nf_ct_protos[proto->l3proto]) {
- if (nf_ct_protos[proto->l3proto][proto->proto]
- != &nf_conntrack_generic_protocol) {
- ret = -EBUSY;
- goto out_unlock;
- }
- } else {
- /* l3proto may be loaded latter. */
- struct nf_conntrack_protocol **proto_array;
- int i;
-
- write_unlock_bh(&nf_conntrack_lock);
-
- proto_array = (struct nf_conntrack_protocol **)
- kmalloc(MAX_NF_CT_PROTO *
- sizeof(struct nf_conntrack_protocol *),
- GFP_KERNEL);
- if (proto_array == NULL) {
- ret = -ENOMEM;
- goto out;
- }
- for (i = 0; i < MAX_NF_CT_PROTO; i++)
- proto_array[i] = &nf_conntrack_generic_protocol;
-
- write_lock_bh(&nf_conntrack_lock);
- if (nf_ct_protos[proto->l3proto]) {
- /* bad timing, but no problem */
- write_unlock_bh(&nf_conntrack_lock);
- kfree(proto_array);
- } else {
- nf_ct_protos[proto->l3proto] = proto_array;
- write_unlock_bh(&nf_conntrack_lock);
- }
-
- /*
- * Just once because array is never freed until unloading
- * nf_conntrack.ko
- */
- goto retry;
- }
-
- nf_ct_protos[proto->l3proto][proto->proto] = proto;
-
-out_unlock:
- write_unlock_bh(&nf_conntrack_lock);
-out:
- return ret;
-}
-
-void nf_conntrack_protocol_unregister(struct nf_conntrack_protocol *proto)
-{
- write_lock_bh(&nf_conntrack_lock);
- nf_ct_protos[proto->l3proto][proto->proto]
- = &nf_conntrack_generic_protocol;
- write_unlock_bh(&nf_conntrack_lock);
-
- /* Somebody could be still looking at the proto in bh. */
- synchronize_net();
-
- /* Remove all contrack entries for this protocol */
- nf_ct_iterate_cleanup(kill_proto, proto);
-}
-
static int __init nf_conntrack_standalone_init(void)
{
#ifdef CONFIG_PROC_FS
@@ -834,70 +490,4 @@ module_exit(nf_conntrack_standalone_fini);
void need_conntrack(void)
{
}
-
-#ifdef CONFIG_NF_CONNTRACK_EVENTS
-EXPORT_SYMBOL_GPL(nf_conntrack_chain);
-EXPORT_SYMBOL_GPL(nf_conntrack_expect_chain);
-EXPORT_SYMBOL_GPL(nf_conntrack_register_notifier);
-EXPORT_SYMBOL_GPL(nf_conntrack_unregister_notifier);
-EXPORT_SYMBOL_GPL(__nf_ct_event_cache_init);
-EXPORT_PER_CPU_SYMBOL_GPL(nf_conntrack_ecache);
-EXPORT_SYMBOL_GPL(nf_ct_deliver_cached_events);
-#endif
-EXPORT_SYMBOL(nf_ct_l3proto_try_module_get);
-EXPORT_SYMBOL(nf_ct_l3proto_module_put);
-EXPORT_SYMBOL(nf_conntrack_l3proto_register);
-EXPORT_SYMBOL(nf_conntrack_l3proto_unregister);
-EXPORT_SYMBOL(nf_conntrack_protocol_register);
-EXPORT_SYMBOL(nf_conntrack_protocol_unregister);
-EXPORT_SYMBOL(nf_ct_invert_tuplepr);
-EXPORT_SYMBOL(nf_conntrack_destroyed);
-EXPORT_SYMBOL(need_conntrack);
-EXPORT_SYMBOL(nf_conntrack_helper_register);
-EXPORT_SYMBOL(nf_conntrack_helper_unregister);
-EXPORT_SYMBOL(nf_ct_iterate_cleanup);
-EXPORT_SYMBOL(__nf_ct_refresh_acct);
-EXPORT_SYMBOL(nf_ct_protos);
-EXPORT_SYMBOL(__nf_ct_proto_find);
-EXPORT_SYMBOL(nf_ct_proto_find_get);
-EXPORT_SYMBOL(nf_ct_proto_put);
-EXPORT_SYMBOL(nf_ct_l3proto_find_get);
-EXPORT_SYMBOL(nf_ct_l3proto_put);
-EXPORT_SYMBOL(nf_ct_l3protos);
-EXPORT_SYMBOL_GPL(nf_conntrack_checksum);
-EXPORT_SYMBOL(nf_conntrack_expect_alloc);
-EXPORT_SYMBOL(nf_conntrack_expect_put);
-EXPORT_SYMBOL(nf_conntrack_expect_related);
-EXPORT_SYMBOL(nf_conntrack_unexpect_related);
-EXPORT_SYMBOL(nf_conntrack_tuple_taken);
-EXPORT_SYMBOL(nf_conntrack_htable_size);
-EXPORT_SYMBOL(nf_conntrack_lock);
-EXPORT_SYMBOL(nf_conntrack_hash);
-EXPORT_SYMBOL(nf_conntrack_untracked);
-EXPORT_SYMBOL_GPL(nf_conntrack_find_get);
-#ifdef CONFIG_IP_NF_NAT_NEEDED
-EXPORT_SYMBOL(nf_conntrack_tcp_update);
-#endif
-EXPORT_SYMBOL(__nf_conntrack_confirm);
-EXPORT_SYMBOL(nf_ct_get_tuple);
-EXPORT_SYMBOL(nf_ct_invert_tuple);
-EXPORT_SYMBOL(nf_conntrack_in);
-EXPORT_SYMBOL(__nf_conntrack_attach);
-EXPORT_SYMBOL(nf_conntrack_alloc);
-EXPORT_SYMBOL(nf_conntrack_free);
-EXPORT_SYMBOL(nf_conntrack_flush);
-EXPORT_SYMBOL(nf_ct_remove_expectations);
-EXPORT_SYMBOL(nf_ct_helper_find_get);
-EXPORT_SYMBOL(nf_ct_helper_put);
-EXPORT_SYMBOL(__nf_conntrack_helper_find_byname);
-EXPORT_SYMBOL(__nf_conntrack_find);
-EXPORT_SYMBOL(nf_ct_unlink_expect);
-EXPORT_SYMBOL(nf_conntrack_hash_insert);
-EXPORT_SYMBOL(__nf_conntrack_expect_find);
-EXPORT_SYMBOL(nf_conntrack_expect_find);
-EXPORT_SYMBOL(nf_conntrack_expect_list);
-#if defined(CONFIG_NF_CT_NETLINK) || \
- defined(CONFIG_NF_CT_NETLINK_MODULE)
-EXPORT_SYMBOL(nf_ct_port_tuple_to_nfattr);
-EXPORT_SYMBOL(nf_ct_port_nfattr_to_tuple);
-#endif
+EXPORT_SYMBOL_GPL(need_conntrack);
diff --git a/net/netfilter/nf_conntrack_tftp.c b/net/netfilter/nf_conntrack_tftp.c
new file mode 100644
index 000000000000..f5bffe24b0a5
--- /dev/null
+++ b/net/netfilter/nf_conntrack_tftp.c
@@ -0,0 +1,160 @@
+/* (C) 2001-2002 Magnus Boden <mb@ozaba.mine.nu>
+ *
+ * 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/moduleparam.h>
+#include <linux/in.h>
+#include <linux/udp.h>
+#include <linux/netfilter.h>
+
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_tuple.h>
+#include <net/netfilter/nf_conntrack_expect.h>
+#include <net/netfilter/nf_conntrack_ecache.h>
+#include <net/netfilter/nf_conntrack_helper.h>
+#include <linux/netfilter/nf_conntrack_tftp.h>
+
+MODULE_AUTHOR("Magnus Boden <mb@ozaba.mine.nu>");
+MODULE_DESCRIPTION("TFTP connection tracking helper");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ip_conntrack_tftp");
+
+#define MAX_PORTS 8
+static unsigned short ports[MAX_PORTS];
+static int ports_c;
+module_param_array(ports, ushort, &ports_c, 0400);
+MODULE_PARM_DESC(ports, "Port numbers of TFTP servers");
+
+#if 0
+#define DEBUGP(format, args...) printk("%s:%s:" format, \
+ __FILE__, __FUNCTION__ , ## args)
+#else
+#define DEBUGP(format, args...)
+#endif
+
+unsigned int (*nf_nat_tftp_hook)(struct sk_buff **pskb,
+ enum ip_conntrack_info ctinfo,
+ struct nf_conntrack_expect *exp) __read_mostly;
+EXPORT_SYMBOL_GPL(nf_nat_tftp_hook);
+
+static int tftp_help(struct sk_buff **pskb,
+ unsigned int protoff,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo)
+{
+ struct tftphdr _tftph, *tfh;
+ struct nf_conntrack_expect *exp;
+ struct nf_conntrack_tuple *tuple;
+ unsigned int ret = NF_ACCEPT;
+ int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
+ typeof(nf_nat_tftp_hook) nf_nat_tftp;
+
+ tfh = skb_header_pointer(*pskb, protoff + sizeof(struct udphdr),
+ sizeof(_tftph), &_tftph);
+ if (tfh == NULL)
+ return NF_ACCEPT;
+
+ switch (ntohs(tfh->opcode)) {
+ case TFTP_OPCODE_READ:
+ case TFTP_OPCODE_WRITE:
+ /* RRQ and WRQ works the same way */
+ DEBUGP("");
+ NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+ NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
+
+ exp = nf_conntrack_expect_alloc(ct);
+ if (exp == NULL)
+ return NF_DROP;
+ tuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
+ nf_conntrack_expect_init(exp, family,
+ &tuple->src.u3, &tuple->dst.u3,
+ IPPROTO_UDP,
+ NULL, &tuple->dst.u.udp.port);
+
+ DEBUGP("expect: ");
+ NF_CT_DUMP_TUPLE(&exp->tuple);
+ NF_CT_DUMP_TUPLE(&exp->mask);
+
+ nf_nat_tftp = rcu_dereference(nf_nat_tftp_hook);
+ if (nf_nat_tftp && ct->status & IPS_NAT_MASK)
+ ret = nf_nat_tftp(pskb, ctinfo, exp);
+ else if (nf_conntrack_expect_related(exp) != 0)
+ ret = NF_DROP;
+ nf_conntrack_expect_put(exp);
+ break;
+ case TFTP_OPCODE_DATA:
+ case TFTP_OPCODE_ACK:
+ DEBUGP("Data/ACK opcode\n");
+ break;
+ case TFTP_OPCODE_ERROR:
+ DEBUGP("Error opcode\n");
+ break;
+ default:
+ DEBUGP("Unknown opcode\n");
+ }
+ return ret;
+}
+
+static struct nf_conntrack_helper tftp[MAX_PORTS][2] __read_mostly;
+static char tftp_names[MAX_PORTS][2][sizeof("tftp-65535")] __read_mostly;
+
+static void nf_conntrack_tftp_fini(void)
+{
+ int i, j;
+
+ for (i = 0; i < ports_c; i++) {
+ for (j = 0; j < 2; j++)
+ nf_conntrack_helper_unregister(&tftp[i][j]);
+ }
+}
+
+static int __init nf_conntrack_tftp_init(void)
+{
+ int i, j, ret;
+ char *tmpname;
+
+ if (ports_c == 0)
+ ports[ports_c++] = TFTP_PORT;
+
+ for (i = 0; i < ports_c; i++) {
+ memset(&tftp[i], 0, sizeof(tftp[i]));
+
+ tftp[i][0].tuple.src.l3num = AF_INET;
+ tftp[i][1].tuple.src.l3num = AF_INET6;
+ for (j = 0; j < 2; j++) {
+ tftp[i][j].tuple.dst.protonum = IPPROTO_UDP;
+ tftp[i][j].tuple.src.u.udp.port = htons(ports[i]);
+ tftp[i][j].mask.src.l3num = 0xFFFF;
+ tftp[i][j].mask.dst.protonum = 0xFF;
+ tftp[i][j].mask.src.u.udp.port = htons(0xFFFF);
+ tftp[i][j].max_expected = 1;
+ tftp[i][j].timeout = 5 * 60; /* 5 minutes */
+ tftp[i][j].me = THIS_MODULE;
+ tftp[i][j].help = tftp_help;
+
+ tmpname = &tftp_names[i][j][0];
+ if (ports[i] == TFTP_PORT)
+ sprintf(tmpname, "tftp");
+ else
+ sprintf(tmpname, "tftp-%u", i);
+ tftp[i][j].name = tmpname;
+
+ ret = nf_conntrack_helper_register(&tftp[i][j]);
+ if (ret) {
+ printk("nf_ct_tftp: failed to register helper "
+ "for pf: %u port: %u\n",
+ tftp[i][j].tuple.src.l3num, ports[i]);
+ nf_conntrack_tftp_fini();
+ return ret;
+ }
+ }
+ }
+ return 0;
+}
+
+module_init(nf_conntrack_tftp_init);
+module_exit(nf_conntrack_tftp_fini);
diff --git a/net/netfilter/nf_sysctl.c b/net/netfilter/nf_sysctl.c
new file mode 100644
index 000000000000..06ddddb2911f
--- /dev/null
+++ b/net/netfilter/nf_sysctl.c
@@ -0,0 +1,134 @@
+/* nf_sysctl.c netfilter sysctl registration/unregistation
+ *
+ * Copyright (c) 2006 Patrick McHardy <kaber@trash.net>
+ */
+#include <linux/module.h>
+#include <linux/sysctl.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+static void
+path_free(struct ctl_table *path, struct ctl_table *table)
+{
+ struct ctl_table *t, *next;
+
+ for (t = path; t != NULL && t != table; t = next) {
+ next = t->child;
+ kfree(t);
+ }
+}
+
+static struct ctl_table *
+path_dup(struct ctl_table *path, struct ctl_table *table)
+{
+ struct ctl_table *t, *last = NULL, *tmp;
+
+ for (t = path; t != NULL; t = t->child) {
+ /* twice the size since path elements are terminated by an
+ * empty element */
+ tmp = kmemdup(t, 2 * sizeof(*t), GFP_KERNEL);
+ if (tmp == NULL) {
+ if (last != NULL)
+ path_free(path, table);
+ return NULL;
+ }
+
+ if (last != NULL)
+ last->child = tmp;
+ else
+ path = tmp;
+ last = tmp;
+ }
+
+ if (last != NULL)
+ last->child = table;
+ else
+ path = table;
+
+ return path;
+}
+
+struct ctl_table_header *
+nf_register_sysctl_table(struct ctl_table *path, struct ctl_table *table)
+{
+ struct ctl_table_header *header;
+
+ path = path_dup(path, table);
+ if (path == NULL)
+ return NULL;
+ header = register_sysctl_table(path, 0);
+ if (header == NULL)
+ path_free(path, table);
+ return header;
+}
+EXPORT_SYMBOL_GPL(nf_register_sysctl_table);
+
+void
+nf_unregister_sysctl_table(struct ctl_table_header *header,
+ struct ctl_table *table)
+{
+ struct ctl_table *path = header->ctl_table;
+
+ unregister_sysctl_table(header);
+ path_free(path, table);
+}
+EXPORT_SYMBOL_GPL(nf_unregister_sysctl_table);
+
+/* net/netfilter */
+static struct ctl_table nf_net_netfilter_table[] = {
+ {
+ .ctl_name = NET_NETFILTER,
+ .procname = "netfilter",
+ .mode = 0555,
+ },
+ {
+ .ctl_name = 0
+ }
+};
+struct ctl_table nf_net_netfilter_sysctl_path[] = {
+ {
+ .ctl_name = CTL_NET,
+ .procname = "net",
+ .mode = 0555,
+ .child = nf_net_netfilter_table,
+ },
+ {
+ .ctl_name = 0
+ }
+};
+EXPORT_SYMBOL_GPL(nf_net_netfilter_sysctl_path);
+
+/* net/ipv4/netfilter */
+static struct ctl_table nf_net_ipv4_netfilter_table[] = {
+ {
+ .ctl_name = NET_IPV4_NETFILTER,
+ .procname = "netfilter",
+ .mode = 0555,
+ },
+ {
+ .ctl_name = 0
+ }
+};
+static struct ctl_table nf_net_ipv4_table[] = {
+ {
+ .ctl_name = NET_IPV4,
+ .procname = "ipv4",
+ .mode = 0555,
+ .child = nf_net_ipv4_netfilter_table,
+ },
+ {
+ .ctl_name = 0
+ }
+};
+struct ctl_table nf_net_ipv4_netfilter_sysctl_path[] = {
+ {
+ .ctl_name = CTL_NET,
+ .procname = "net",
+ .mode = 0555,
+ .child = nf_net_ipv4_table,
+ },
+ {
+ .ctl_name = 0
+ }
+};
+EXPORT_SYMBOL_GPL(nf_net_ipv4_netfilter_sysctl_path);
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index 1e5207b80fe5..d1505dd25c66 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -408,13 +408,13 @@ __build_packet_message(struct nfulnl_instance *inst,
const struct net_device *indev,
const struct net_device *outdev,
const struct nf_loginfo *li,
- const char *prefix)
+ const char *prefix, unsigned int plen)
{
unsigned char *old_tail;
struct nfulnl_msg_packet_hdr pmsg;
struct nlmsghdr *nlh;
struct nfgenmsg *nfmsg;
- u_int32_t tmp_uint;
+ __be32 tmp_uint;
UDEBUG("entered\n");
@@ -432,12 +432,8 @@ __build_packet_message(struct nfulnl_instance *inst,
NFA_PUT(inst->skb, NFULA_PACKET_HDR, sizeof(pmsg), &pmsg);
- if (prefix) {
- int slen = strlen(prefix);
- if (slen > NFULNL_PREFIXLEN)
- slen = NFULNL_PREFIXLEN;
- NFA_PUT(inst->skb, NFULA_PREFIX, slen, prefix);
- }
+ if (prefix)
+ NFA_PUT(inst->skb, NFULA_PREFIX, plen, prefix);
if (indev) {
tmp_uint = htonl(indev->ifindex);
@@ -501,18 +497,16 @@ __build_packet_message(struct nfulnl_instance *inst,
#endif
}
- if (skb->nfmark) {
- tmp_uint = htonl(skb->nfmark);
+ if (skb->mark) {
+ tmp_uint = htonl(skb->mark);
NFA_PUT(inst->skb, NFULA_MARK, sizeof(tmp_uint), &tmp_uint);
}
if (indev && skb->dev && skb->dev->hard_header_parse) {
struct nfulnl_msg_packet_hw phw;
-
- phw.hw_addrlen =
- skb->dev->hard_header_parse((struct sk_buff *)skb,
+ int len = skb->dev->hard_header_parse((struct sk_buff *)skb,
phw.hw_addr);
- phw.hw_addrlen = htons(phw.hw_addrlen);
+ phw.hw_addrlen = htons(len);
NFA_PUT(inst->skb, NFULA_HWADDR, sizeof(phw), &phw);
}
@@ -529,7 +523,7 @@ __build_packet_message(struct nfulnl_instance *inst,
if (skb->sk) {
read_lock_bh(&skb->sk->sk_callback_lock);
if (skb->sk->sk_socket && skb->sk->sk_socket->file) {
- u_int32_t uid = htonl(skb->sk->sk_socket->file->f_uid);
+ __be32 uid = htonl(skb->sk->sk_socket->file->f_uid);
/* need to unlock here since NFA_PUT may goto */
read_unlock_bh(&skb->sk->sk_callback_lock);
NFA_PUT(inst->skb, NFULA_UID, sizeof(uid), &uid);
@@ -603,6 +597,7 @@ nfulnl_log_packet(unsigned int pf,
const struct nf_loginfo *li;
unsigned int qthreshold;
unsigned int nlbufsiz;
+ unsigned int plen;
if (li_user && li_user->type == NF_LOG_TYPE_ULOG)
li = li_user;
@@ -618,6 +613,10 @@ nfulnl_log_packet(unsigned int pf,
return;
}
+ plen = 0;
+ if (prefix)
+ plen = strlen(prefix);
+
/* all macros expand to constant values at compile time */
/* FIXME: do we want to make the size calculation conditional based on
* what is actually present? way more branches and checks, but more
@@ -632,7 +631,7 @@ nfulnl_log_packet(unsigned int pf,
#endif
+ NFA_SPACE(sizeof(u_int32_t)) /* mark */
+ NFA_SPACE(sizeof(u_int32_t)) /* uid */
- + NFA_SPACE(NFULNL_PREFIXLEN) /* prefix */
+ + NFA_SPACE(plen) /* prefix */
+ NFA_SPACE(sizeof(struct nfulnl_msg_packet_hw))
+ NFA_SPACE(sizeof(struct nfulnl_msg_packet_timestamp));
@@ -703,7 +702,7 @@ nfulnl_log_packet(unsigned int pf,
inst->qlen++;
__build_packet_message(inst, skb, data_len, pf,
- hooknum, in, out, li, prefix);
+ hooknum, in, out, li, prefix, plen);
/* timer_pending always called within inst->lock, so there
* is no chance of a race here */
@@ -882,15 +881,15 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
}
if (nfula[NFULA_CFG_TIMEOUT-1]) {
- u_int32_t timeout =
- *(u_int32_t *)NFA_DATA(nfula[NFULA_CFG_TIMEOUT-1]);
+ __be32 timeout =
+ *(__be32 *)NFA_DATA(nfula[NFULA_CFG_TIMEOUT-1]);
nfulnl_set_timeout(inst, ntohl(timeout));
}
if (nfula[NFULA_CFG_NLBUFSIZ-1]) {
- u_int32_t nlbufsiz =
- *(u_int32_t *)NFA_DATA(nfula[NFULA_CFG_NLBUFSIZ-1]);
+ __be32 nlbufsiz =
+ *(__be32 *)NFA_DATA(nfula[NFULA_CFG_NLBUFSIZ-1]);
nfulnl_set_nlbufsiz(inst, ntohl(nlbufsiz));
}
@@ -903,8 +902,8 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
}
if (nfula[NFULA_CFG_FLAGS-1]) {
- u_int16_t flags =
- *(u_int16_t *)NFA_DATA(nfula[NFULA_CFG_FLAGS-1]);
+ __be16 flags =
+ *(__be16 *)NFA_DATA(nfula[NFULA_CFG_FLAGS-1]);
nfulnl_set_flags(inst, ntohs(flags));
}
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index e815a9aa6e95..a88a017da22c 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -349,7 +349,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
struct sk_buff *entskb = entry->skb;
struct net_device *indev;
struct net_device *outdev;
- unsigned int tmp_uint;
+ __be32 tmp_uint;
QDEBUG("entered\n");
@@ -480,8 +480,8 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
#endif
}
- if (entskb->nfmark) {
- tmp_uint = htonl(entskb->nfmark);
+ if (entskb->mark) {
+ tmp_uint = htonl(entskb->mark);
NFA_PUT(skb, NFQA_MARK, sizeof(u_int32_t), &tmp_uint);
}
@@ -489,10 +489,9 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
&& entskb->dev->hard_header_parse) {
struct nfqnl_msg_packet_hw phw;
- phw.hw_addrlen =
- entskb->dev->hard_header_parse(entskb,
+ int len = entskb->dev->hard_header_parse(entskb,
phw.hw_addr);
- phw.hw_addrlen = htons(phw.hw_addrlen);
+ phw.hw_addrlen = htons(len);
NFA_PUT(skb, NFQA_HWADDR, sizeof(phw), &phw);
}
@@ -835,8 +834,8 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
}
if (nfqa[NFQA_MARK-1])
- entry->skb->nfmark = ntohl(*(u_int32_t *)
- NFA_DATA(nfqa[NFQA_MARK-1]));
+ entry->skb->mark = ntohl(*(__be32 *)
+ NFA_DATA(nfqa[NFQA_MARK-1]));
issue_verdict(entry, verdict);
instance_put(queue);
@@ -948,6 +947,14 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
ntohl(params->copy_range));
}
+ if (nfqa[NFQA_CFG_QUEUE_MAXLEN-1]) {
+ __be32 *queue_maxlen;
+ queue_maxlen = NFA_DATA(nfqa[NFQA_CFG_QUEUE_MAXLEN-1]);
+ spin_lock_bh(&queue->lock);
+ queue->queue_maxlen = ntohl(*queue_maxlen);
+ spin_unlock_bh(&queue->lock);
+ }
+
out_put:
instance_put(queue);
return ret;
diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c
index c01524f817f0..b5548239d412 100644
--- a/net/netfilter/xt_CONNMARK.c
+++ b/net/netfilter/xt_CONNMARK.c
@@ -31,6 +31,9 @@ MODULE_ALIAS("ipt_CONNMARK");
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_CONNMARK.h>
#include <net/netfilter/nf_conntrack_compat.h>
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+#include <net/netfilter/nf_conntrack_ecache.h>
+#endif
static unsigned int
target(struct sk_buff **pskb,
@@ -42,7 +45,7 @@ target(struct sk_buff **pskb,
{
const struct xt_connmark_target_info *markinfo = targinfo;
u_int32_t diff;
- u_int32_t nfmark;
+ u_int32_t mark;
u_int32_t newmark;
u_int32_t ctinfo;
u_int32_t *ctmark = nf_ct_get_mark(*pskb, &ctinfo);
@@ -62,7 +65,7 @@ target(struct sk_buff **pskb,
break;
case XT_CONNMARK_SAVE:
newmark = (*ctmark & ~markinfo->mask) |
- ((*pskb)->nfmark & markinfo->mask);
+ ((*pskb)->mark & markinfo->mask);
if (*ctmark != newmark) {
*ctmark = newmark;
#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
@@ -73,10 +76,10 @@ target(struct sk_buff **pskb,
}
break;
case XT_CONNMARK_RESTORE:
- nfmark = (*pskb)->nfmark;
- diff = (*ctmark ^ nfmark) & markinfo->mask;
+ mark = (*pskb)->mark;
+ diff = (*ctmark ^ mark) & markinfo->mask;
if (diff != 0)
- (*pskb)->nfmark = nfmark ^ diff;
+ (*pskb)->mark = mark ^ diff;
break;
}
}
diff --git a/net/netfilter/xt_MARK.c b/net/netfilter/xt_MARK.c
index c6e860a7114f..0b48547e8d64 100644
--- a/net/netfilter/xt_MARK.c
+++ b/net/netfilter/xt_MARK.c
@@ -31,8 +31,8 @@ target_v0(struct sk_buff **pskb,
{
const struct xt_mark_target_info *markinfo = targinfo;
- if((*pskb)->nfmark != markinfo->mark)
- (*pskb)->nfmark = markinfo->mark;
+ if((*pskb)->mark != markinfo->mark)
+ (*pskb)->mark = markinfo->mark;
return XT_CONTINUE;
}
@@ -54,16 +54,16 @@ target_v1(struct sk_buff **pskb,
break;
case XT_MARK_AND:
- mark = (*pskb)->nfmark & markinfo->mark;
+ mark = (*pskb)->mark & markinfo->mark;
break;
case XT_MARK_OR:
- mark = (*pskb)->nfmark | markinfo->mark;
+ mark = (*pskb)->mark | markinfo->mark;
break;
}
- if((*pskb)->nfmark != mark)
- (*pskb)->nfmark = mark;
+ if((*pskb)->mark != mark)
+ (*pskb)->mark = mark;
return XT_CONTINUE;
}
diff --git a/net/netfilter/xt_NFLOG.c b/net/netfilter/xt_NFLOG.c
new file mode 100644
index 000000000000..901ed7abaa1b
--- /dev/null
+++ b/net/netfilter/xt_NFLOG.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2006 Patrick McHardy <kaber@trash.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_NFLOG.h>
+
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_DESCRIPTION("x_tables NFLOG target");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_NFLOG");
+MODULE_ALIAS("ip6t_NFLOG");
+
+static unsigned int
+nflog_target(struct sk_buff **pskb,
+ const struct net_device *in, const struct net_device *out,
+ unsigned int hooknum, const struct xt_target *target,
+ const void *targinfo)
+{
+ const struct xt_nflog_info *info = targinfo;
+ struct nf_loginfo li;
+
+ li.type = NF_LOG_TYPE_ULOG;
+ li.u.ulog.copy_len = info->len;
+ li.u.ulog.group = info->group;
+ li.u.ulog.qthreshold = info->threshold;
+
+ nf_log_packet(target->family, hooknum, *pskb, in, out, &li,
+ "%s", info->prefix);
+ return XT_CONTINUE;
+}
+
+static int
+nflog_checkentry(const char *tablename, const void *entry,
+ const struct xt_target *target, void *targetinfo,
+ unsigned int hookmask)
+{
+ struct xt_nflog_info *info = targetinfo;
+
+ if (info->flags & ~XT_NFLOG_MASK)
+ return 0;
+ if (info->prefix[sizeof(info->prefix) - 1] != '\0')
+ return 0;
+ return 1;
+}
+
+static struct xt_target xt_nflog_target[] = {
+ {
+ .name = "NFLOG",
+ .family = AF_INET,
+ .checkentry = nflog_checkentry,
+ .target = nflog_target,
+ .targetsize = sizeof(struct xt_nflog_info),
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "NFLOG",
+ .family = AF_INET6,
+ .checkentry = nflog_checkentry,
+ .target = nflog_target,
+ .targetsize = sizeof(struct xt_nflog_info),
+ .me = THIS_MODULE,
+ },
+};
+
+static int __init xt_nflog_init(void)
+{
+ return xt_register_targets(xt_nflog_target,
+ ARRAY_SIZE(xt_nflog_target));
+}
+
+static void __exit xt_nflog_fini(void)
+{
+ xt_unregister_targets(xt_nflog_target, ARRAY_SIZE(xt_nflog_target));
+}
+
+module_init(xt_nflog_init);
+module_exit(xt_nflog_fini);
diff --git a/net/ipv4/netfilter/ipt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index 33ccdbf8e794..501c564e247f 100644
--- a/net/ipv4/netfilter/ipt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -6,23 +6,8 @@
* $Id: ipt_hashlimit.c 3244 2004-10-20 16:24:29Z laforge@netfilter.org $
*
* Development of this code was funded by Astaro AG, http://www.astaro.com/
- *
- * based on ipt_limit.c by:
- * Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr>
- * Hervé Eychenne <eychenne@info.enserb.u-bordeaux.fr>
- * Rusty Russell <rusty@rustcorp.com.au>
- *
- * The general idea is to create a hash table for every dstip and have a
- * seperate limit counter per tuple. This way you can do something like 'limit
- * the number of syn packets for each of my internal addresses.
- *
- * Ideally this would just be implemented as a general 'hash' match, which would
- * allow us to attach any iptables target to it's hash buckets. But this is
- * not possible in the current iptables architecture. As always, pkttables for
- * 2.7.x will help ;)
*/
#include <linux/module.h>
-#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/random.h>
#include <linux/jhash.h>
@@ -31,28 +16,40 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/list.h>
+#include <linux/skbuff.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_hashlimit.h>
-
-/* FIXME: this is just for IP_NF_ASSERRT */
-#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter/xt_hashlimit.h>
#include <linux/mutex.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
MODULE_DESCRIPTION("iptables match for limiting per hash-bucket");
+MODULE_ALIAS("ipt_hashlimit");
+MODULE_ALIAS("ip6t_hashlimit");
/* need to declare this at the top */
-static struct proc_dir_entry *hashlimit_procdir;
+static struct proc_dir_entry *hashlimit_procdir4;
+static struct proc_dir_entry *hashlimit_procdir6;
static struct file_operations dl_file_ops;
/* hash table crap */
-
struct dsthash_dst {
- __be32 src_ip;
- __be32 dst_ip;
- /* ports have to be consecutive !!! */
+ union {
+ struct {
+ __be32 src;
+ __be32 dst;
+ } ip;
+ struct {
+ __be32 src[4];
+ __be32 dst[4];
+ } ip6;
+ } addr;
__be16 src_port;
__be16 dst_port;
};
@@ -71,9 +68,10 @@ struct dsthash_ent {
} rateinfo;
};
-struct ipt_hashlimit_htable {
+struct xt_hashlimit_htable {
struct hlist_node node; /* global list of all htables */
atomic_t use;
+ int family;
struct hashlimit_cfg cfg; /* config */
@@ -81,8 +79,8 @@ struct ipt_hashlimit_htable {
spinlock_t lock; /* lock for list_head */
u_int32_t rnd; /* random seed for hash */
int rnd_initialized;
+ unsigned int count; /* number entries in table */
struct timer_list timer; /* timer for gc */
- atomic_t count; /* number entries in table */
/* seq_file stuff */
struct proc_dir_entry *pde;
@@ -97,41 +95,33 @@ static kmem_cache_t *hashlimit_cachep __read_mostly;
static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
{
- return (ent->dst.dst_ip == b->dst_ip
- && ent->dst.dst_port == b->dst_port
- && ent->dst.src_port == b->src_port
- && ent->dst.src_ip == b->src_ip);
+ return !memcmp(&ent->dst, b, sizeof(ent->dst));
}
-static inline u_int32_t
-hash_dst(const struct ipt_hashlimit_htable *ht, const struct dsthash_dst *dst)
+static u_int32_t
+hash_dst(const struct xt_hashlimit_htable *ht, const struct dsthash_dst *dst)
{
- return (jhash_3words((__force u32)dst->dst_ip,
- ((__force u32)dst->dst_port<<16 |
- (__force u32)dst->src_port),
- (__force u32)dst->src_ip, ht->rnd) % ht->cfg.size);
+ return jhash(dst, sizeof(*dst), ht->rnd) % ht->cfg.size;
}
-static inline struct dsthash_ent *
-__dsthash_find(const struct ipt_hashlimit_htable *ht, struct dsthash_dst *dst)
+static struct dsthash_ent *
+dsthash_find(const struct xt_hashlimit_htable *ht, struct dsthash_dst *dst)
{
struct dsthash_ent *ent;
struct hlist_node *pos;
u_int32_t hash = hash_dst(ht, dst);
- if (!hlist_empty(&ht->hash[hash]))
- hlist_for_each_entry(ent, pos, &ht->hash[hash], node) {
- if (dst_cmp(ent, dst)) {
+ if (!hlist_empty(&ht->hash[hash])) {
+ hlist_for_each_entry(ent, pos, &ht->hash[hash], node)
+ if (dst_cmp(ent, dst))
return ent;
- }
- }
-
+ }
return NULL;
}
/* allocate dsthash_ent, initialize dst, put in htable and lock it */
static struct dsthash_ent *
-__dsthash_alloc_init(struct ipt_hashlimit_htable *ht, struct dsthash_dst *dst)
+dsthash_alloc_init(struct xt_hashlimit_htable *ht, struct dsthash_dst *dst)
{
struct dsthash_ent *ent;
@@ -142,12 +132,11 @@ __dsthash_alloc_init(struct ipt_hashlimit_htable *ht, struct dsthash_dst *dst)
ht->rnd_initialized = 1;
}
- if (ht->cfg.max &&
- atomic_read(&ht->count) >= ht->cfg.max) {
+ if (ht->cfg.max && ht->count >= ht->cfg.max) {
/* FIXME: do something. question is what.. */
if (net_ratelimit())
- printk(KERN_WARNING
- "ipt_hashlimit: max count of %u reached\n",
+ printk(KERN_WARNING
+ "xt_hashlimit: max count of %u reached\n",
ht->cfg.max);
return NULL;
}
@@ -155,53 +144,47 @@ __dsthash_alloc_init(struct ipt_hashlimit_htable *ht, struct dsthash_dst *dst)
ent = kmem_cache_alloc(hashlimit_cachep, GFP_ATOMIC);
if (!ent) {
if (net_ratelimit())
- printk(KERN_ERR
- "ipt_hashlimit: can't allocate dsthash_ent\n");
+ printk(KERN_ERR
+ "xt_hashlimit: can't allocate dsthash_ent\n");
return NULL;
}
-
- atomic_inc(&ht->count);
-
- ent->dst.dst_ip = dst->dst_ip;
- ent->dst.dst_port = dst->dst_port;
- ent->dst.src_ip = dst->src_ip;
- ent->dst.src_port = dst->src_port;
+ memcpy(&ent->dst, dst, sizeof(ent->dst));
hlist_add_head(&ent->node, &ht->hash[hash_dst(ht, dst)]);
-
+ ht->count++;
return ent;
}
-static inline void
-__dsthash_free(struct ipt_hashlimit_htable *ht, struct dsthash_ent *ent)
+static inline void
+dsthash_free(struct xt_hashlimit_htable *ht, struct dsthash_ent *ent)
{
hlist_del(&ent->node);
kmem_cache_free(hashlimit_cachep, ent);
- atomic_dec(&ht->count);
+ ht->count--;
}
static void htable_gc(unsigned long htlong);
-static int htable_create(struct ipt_hashlimit_info *minfo)
+static int htable_create(struct xt_hashlimit_info *minfo, int family)
{
- int i;
+ struct xt_hashlimit_htable *hinfo;
unsigned int size;
- struct ipt_hashlimit_htable *hinfo;
+ unsigned int i;
if (minfo->cfg.size)
size = minfo->cfg.size;
else {
- size = (((num_physpages << PAGE_SHIFT) / 16384)
- / sizeof(struct list_head));
+ size = ((num_physpages << PAGE_SHIFT) / 16384) /
+ sizeof(struct list_head);
if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
size = 8192;
if (size < 16)
size = 16;
}
/* FIXME: don't use vmalloc() here or anywhere else -HW */
- hinfo = vmalloc(sizeof(struct ipt_hashlimit_htable)
- + (sizeof(struct list_head) * size));
+ hinfo = vmalloc(sizeof(struct xt_hashlimit_htable) +
+ sizeof(struct list_head) * size);
if (!hinfo) {
- printk(KERN_ERR "ipt_hashlimit: Unable to create hashtable\n");
+ printk(KERN_ERR "xt_hashlimit: unable to create hashtable\n");
return -1;
}
minfo->hinfo = hinfo;
@@ -217,11 +200,14 @@ static int htable_create(struct ipt_hashlimit_info *minfo)
for (i = 0; i < hinfo->cfg.size; i++)
INIT_HLIST_HEAD(&hinfo->hash[i]);
- atomic_set(&hinfo->count, 0);
atomic_set(&hinfo->use, 1);
+ hinfo->count = 0;
+ hinfo->family = family;
hinfo->rnd_initialized = 0;
spin_lock_init(&hinfo->lock);
- hinfo->pde = create_proc_entry(minfo->name, 0, hashlimit_procdir);
+ hinfo->pde = create_proc_entry(minfo->name, 0,
+ family == AF_INET ? hashlimit_procdir4 :
+ hashlimit_procdir6);
if (!hinfo->pde) {
vfree(hinfo);
return -1;
@@ -242,23 +228,21 @@ static int htable_create(struct ipt_hashlimit_info *minfo)
return 0;
}
-static int select_all(struct ipt_hashlimit_htable *ht, struct dsthash_ent *he)
+static int select_all(struct xt_hashlimit_htable *ht, struct dsthash_ent *he)
{
return 1;
}
-static int select_gc(struct ipt_hashlimit_htable *ht, struct dsthash_ent *he)
+static int select_gc(struct xt_hashlimit_htable *ht, struct dsthash_ent *he)
{
return (jiffies >= he->expires);
}
-static void htable_selective_cleanup(struct ipt_hashlimit_htable *ht,
- int (*select)(struct ipt_hashlimit_htable *ht,
+static void htable_selective_cleanup(struct xt_hashlimit_htable *ht,
+ int (*select)(struct xt_hashlimit_htable *ht,
struct dsthash_ent *he))
{
- int i;
-
- IP_NF_ASSERT(ht->cfg.size && ht->cfg.max);
+ unsigned int i;
/* lock hash table and iterate over it */
spin_lock_bh(&ht->lock);
@@ -267,7 +251,7 @@ static void htable_selective_cleanup(struct ipt_hashlimit_htable *ht,
struct hlist_node *pos, *n;
hlist_for_each_entry_safe(dh, pos, n, &ht->hash[i], node) {
if ((*select)(ht, dh))
- __dsthash_free(ht, dh);
+ dsthash_free(ht, dh);
}
}
spin_unlock_bh(&ht->lock);
@@ -276,7 +260,7 @@ static void htable_selective_cleanup(struct ipt_hashlimit_htable *ht,
/* hash table garbage collector, run by timer */
static void htable_gc(unsigned long htlong)
{
- struct ipt_hashlimit_htable *ht = (struct ipt_hashlimit_htable *)htlong;
+ struct xt_hashlimit_htable *ht = (struct xt_hashlimit_htable *)htlong;
htable_selective_cleanup(ht, select_gc);
@@ -285,38 +269,39 @@ static void htable_gc(unsigned long htlong)
add_timer(&ht->timer);
}
-static void htable_destroy(struct ipt_hashlimit_htable *hinfo)
+static void htable_destroy(struct xt_hashlimit_htable *hinfo)
{
/* remove timer, if it is pending */
if (timer_pending(&hinfo->timer))
del_timer(&hinfo->timer);
/* remove proc entry */
- remove_proc_entry(hinfo->pde->name, hashlimit_procdir);
-
+ remove_proc_entry(hinfo->pde->name,
+ hinfo->family == AF_INET ? hashlimit_procdir4 :
+ hashlimit_procdir6);
htable_selective_cleanup(hinfo, select_all);
vfree(hinfo);
}
-static struct ipt_hashlimit_htable *htable_find_get(char *name)
+static struct xt_hashlimit_htable *htable_find_get(char *name, int family)
{
- struct ipt_hashlimit_htable *hinfo;
+ struct xt_hashlimit_htable *hinfo;
struct hlist_node *pos;
spin_lock_bh(&hashlimit_lock);
hlist_for_each_entry(hinfo, pos, &hashlimit_htables, node) {
- if (!strcmp(name, hinfo->pde->name)) {
+ if (!strcmp(name, hinfo->pde->name) &&
+ hinfo->family == family) {
atomic_inc(&hinfo->use);
spin_unlock_bh(&hashlimit_lock);
return hinfo;
}
}
spin_unlock_bh(&hashlimit_lock);
-
return NULL;
}
-static void htable_put(struct ipt_hashlimit_htable *hinfo)
+static void htable_put(struct xt_hashlimit_htable *hinfo)
{
if (atomic_dec_and_test(&hinfo->use)) {
spin_lock_bh(&hashlimit_lock);
@@ -326,7 +311,6 @@ static void htable_put(struct ipt_hashlimit_htable *hinfo)
}
}
-
/* The algorithm used is the Simple Token Bucket Filter (TBF)
* see net/sched/sch_tbf.c in the linux source tree
*/
@@ -370,17 +354,82 @@ user2credits(u_int32_t user)
/* If multiplying would overflow... */
if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
/* Divide first. */
- return (user / IPT_HASHLIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
+ return (user / XT_HASHLIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
- return (user * HZ * CREDITS_PER_JIFFY) / IPT_HASHLIMIT_SCALE;
+ return (user * HZ * CREDITS_PER_JIFFY) / XT_HASHLIMIT_SCALE;
}
static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
{
- dh->rateinfo.credit += (now - xchg(&dh->rateinfo.prev, now))
- * CREDITS_PER_JIFFY;
+ dh->rateinfo.credit += (now - dh->rateinfo.prev) * CREDITS_PER_JIFFY;
if (dh->rateinfo.credit > dh->rateinfo.credit_cap)
dh->rateinfo.credit = dh->rateinfo.credit_cap;
+ dh->rateinfo.prev = now;
+}
+
+static int
+hashlimit_init_dst(struct xt_hashlimit_htable *hinfo, struct dsthash_dst *dst,
+ const struct sk_buff *skb, unsigned int protoff)
+{
+ __be16 _ports[2], *ports;
+ int nexthdr;
+
+ memset(dst, 0, sizeof(*dst));
+
+ switch (hinfo->family) {
+ case AF_INET:
+ if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_DIP)
+ dst->addr.ip.dst = skb->nh.iph->daddr;
+ if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_SIP)
+ dst->addr.ip.src = skb->nh.iph->saddr;
+
+ if (!(hinfo->cfg.mode &
+ (XT_HASHLIMIT_HASH_DPT | XT_HASHLIMIT_HASH_SPT)))
+ return 0;
+ nexthdr = skb->nh.iph->protocol;
+ break;
+#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
+ case AF_INET6:
+ if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_DIP)
+ memcpy(&dst->addr.ip6.dst, &skb->nh.ipv6h->daddr,
+ sizeof(dst->addr.ip6.dst));
+ if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_SIP)
+ memcpy(&dst->addr.ip6.src, &skb->nh.ipv6h->saddr,
+ sizeof(dst->addr.ip6.src));
+
+ if (!(hinfo->cfg.mode &
+ (XT_HASHLIMIT_HASH_DPT | XT_HASHLIMIT_HASH_SPT)))
+ return 0;
+ nexthdr = ipv6_find_hdr(skb, &protoff, -1, NULL);
+ if (nexthdr < 0)
+ return -1;
+ break;
+#endif
+ default:
+ BUG();
+ return 0;
+ }
+
+ switch (nexthdr) {
+ case IPPROTO_TCP:
+ case IPPROTO_UDP:
+ case IPPROTO_SCTP:
+ case IPPROTO_DCCP:
+ ports = skb_header_pointer(skb, protoff, sizeof(_ports),
+ &_ports);
+ break;
+ default:
+ _ports[0] = _ports[1] = 0;
+ ports = _ports;
+ break;
+ }
+ if (!ports)
+ return -1;
+ if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_SPT)
+ dst->src_port = ports[0];
+ if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_DPT)
+ dst->dst_port = ports[1];
+ return 0;
}
static int
@@ -393,68 +442,31 @@ hashlimit_match(const struct sk_buff *skb,
unsigned int protoff,
int *hotdrop)
{
- struct ipt_hashlimit_info *r =
- ((struct ipt_hashlimit_info *)matchinfo)->u.master;
- struct ipt_hashlimit_htable *hinfo = r->hinfo;
+ struct xt_hashlimit_info *r =
+ ((struct xt_hashlimit_info *)matchinfo)->u.master;
+ struct xt_hashlimit_htable *hinfo = r->hinfo;
unsigned long now = jiffies;
struct dsthash_ent *dh;
struct dsthash_dst dst;
- /* build 'dst' according to hinfo->cfg and current packet */
- memset(&dst, 0, sizeof(dst));
- if (hinfo->cfg.mode & IPT_HASHLIMIT_HASH_DIP)
- dst.dst_ip = skb->nh.iph->daddr;
- if (hinfo->cfg.mode & IPT_HASHLIMIT_HASH_SIP)
- dst.src_ip = skb->nh.iph->saddr;
- if (hinfo->cfg.mode & IPT_HASHLIMIT_HASH_DPT
- ||hinfo->cfg.mode & IPT_HASHLIMIT_HASH_SPT) {
- __be16 _ports[2], *ports;
-
- switch (skb->nh.iph->protocol) {
- case IPPROTO_TCP:
- case IPPROTO_UDP:
- case IPPROTO_SCTP:
- case IPPROTO_DCCP:
- ports = skb_header_pointer(skb, skb->nh.iph->ihl*4,
- sizeof(_ports), &_ports);
- break;
- default:
- _ports[0] = _ports[1] = 0;
- ports = _ports;
- break;
- }
- if (!ports) {
- /* We've been asked to examine this packet, and we
- can't. Hence, no choice but to drop. */
- *hotdrop = 1;
- return 0;
- }
- if (hinfo->cfg.mode & IPT_HASHLIMIT_HASH_SPT)
- dst.src_port = ports[0];
- if (hinfo->cfg.mode & IPT_HASHLIMIT_HASH_DPT)
- dst.dst_port = ports[1];
- }
+ if (hashlimit_init_dst(hinfo, &dst, skb, protoff) < 0)
+ goto hotdrop;
spin_lock_bh(&hinfo->lock);
- dh = __dsthash_find(hinfo, &dst);
+ dh = dsthash_find(hinfo, &dst);
if (!dh) {
- dh = __dsthash_alloc_init(hinfo, &dst);
-
+ dh = dsthash_alloc_init(hinfo, &dst);
if (!dh) {
- /* enomem... don't match == DROP */
- if (net_ratelimit())
- printk(KERN_ERR "%s: ENOMEM\n", __FUNCTION__);
spin_unlock_bh(&hinfo->lock);
- return 0;
+ goto hotdrop;
}
dh->expires = jiffies + msecs_to_jiffies(hinfo->cfg.expire);
-
dh->rateinfo.prev = jiffies;
- dh->rateinfo.credit = user2credits(hinfo->cfg.avg *
- hinfo->cfg.burst);
- dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg *
- hinfo->cfg.burst);
+ dh->rateinfo.credit = user2credits(hinfo->cfg.avg *
+ hinfo->cfg.burst);
+ dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg *
+ hinfo->cfg.burst);
dh->rateinfo.cost = user2credits(hinfo->cfg.avg);
} else {
/* update expiration timeout */
@@ -473,6 +485,10 @@ hashlimit_match(const struct sk_buff *skb,
/* default case: we're overlimit, thus don't match */
return 0;
+
+hotdrop:
+ *hotdrop = 1;
+ return 0;
}
static int
@@ -482,42 +498,37 @@ hashlimit_checkentry(const char *tablename,
void *matchinfo,
unsigned int hook_mask)
{
- struct ipt_hashlimit_info *r = matchinfo;
+ struct xt_hashlimit_info *r = matchinfo;
/* Check for overflow. */
- if (r->cfg.burst == 0
- || user2credits(r->cfg.avg * r->cfg.burst) <
- user2credits(r->cfg.avg)) {
- printk(KERN_ERR "ipt_hashlimit: Overflow, try lower: %u/%u\n",
+ if (r->cfg.burst == 0 ||
+ user2credits(r->cfg.avg * r->cfg.burst) < user2credits(r->cfg.avg)) {
+ printk(KERN_ERR "xt_hashlimit: overflow, try lower: %u/%u\n",
r->cfg.avg, r->cfg.burst);
return 0;
}
-
- if (r->cfg.mode == 0
- || r->cfg.mode > (IPT_HASHLIMIT_HASH_DPT
- |IPT_HASHLIMIT_HASH_DIP
- |IPT_HASHLIMIT_HASH_SIP
- |IPT_HASHLIMIT_HASH_SPT))
+ if (r->cfg.mode == 0 ||
+ r->cfg.mode > (XT_HASHLIMIT_HASH_DPT |
+ XT_HASHLIMIT_HASH_DIP |
+ XT_HASHLIMIT_HASH_SIP |
+ XT_HASHLIMIT_HASH_SPT))
return 0;
-
if (!r->cfg.gc_interval)
return 0;
-
if (!r->cfg.expire)
return 0;
-
if (r->name[sizeof(r->name) - 1] != '\0')
return 0;
/* This is the best we've got: We cannot release and re-grab lock,
- * since checkentry() is called before ip_tables.c grabs ipt_mutex.
- * We also cannot grab the hashtable spinlock, since htable_create will
+ * since checkentry() is called before x_tables.c grabs xt_mutex.
+ * We also cannot grab the hashtable spinlock, since htable_create will
* call vmalloc, and that can sleep. And we cannot just re-search
* the list of htable's in htable_create(), since then we would
* create duplicate proc files. -HW */
mutex_lock(&hlimit_mutex);
- r->hinfo = htable_find_get(r->name);
- if (!r->hinfo && (htable_create(r) != 0)) {
+ r->hinfo = htable_find_get(r->name, match->family);
+ if (!r->hinfo && htable_create(r, match->family) != 0) {
mutex_unlock(&hlimit_mutex);
return 0;
}
@@ -525,20 +536,19 @@ hashlimit_checkentry(const char *tablename,
/* Ugly hack: For SMP, we only want to use one set */
r->u.master = r;
-
return 1;
}
static void
hashlimit_destroy(const struct xt_match *match, void *matchinfo)
{
- struct ipt_hashlimit_info *r = matchinfo;
+ struct xt_hashlimit_info *r = matchinfo;
htable_put(r->hinfo);
}
#ifdef CONFIG_COMPAT
-struct compat_ipt_hashlimit_info {
+struct compat_xt_hashlimit_info {
char name[IFNAMSIZ];
struct hashlimit_cfg cfg;
compat_uptr_t hinfo;
@@ -547,40 +557,56 @@ struct compat_ipt_hashlimit_info {
static void compat_from_user(void *dst, void *src)
{
- int off = offsetof(struct compat_ipt_hashlimit_info, hinfo);
+ int off = offsetof(struct compat_xt_hashlimit_info, hinfo);
memcpy(dst, src, off);
- memset(dst + off, 0, sizeof(struct compat_ipt_hashlimit_info) - off);
+ memset(dst + off, 0, sizeof(struct compat_xt_hashlimit_info) - off);
}
static int compat_to_user(void __user *dst, void *src)
{
- int off = offsetof(struct compat_ipt_hashlimit_info, hinfo);
+ int off = offsetof(struct compat_xt_hashlimit_info, hinfo);
return copy_to_user(dst, src, off) ? -EFAULT : 0;
}
#endif
-static struct ipt_match ipt_hashlimit = {
- .name = "hashlimit",
- .match = hashlimit_match,
- .matchsize = sizeof(struct ipt_hashlimit_info),
+static struct xt_match xt_hashlimit[] = {
+ {
+ .name = "hashlimit",
+ .family = AF_INET,
+ .match = hashlimit_match,
+ .matchsize = sizeof(struct xt_hashlimit_info),
+#ifdef CONFIG_COMPAT
+ .compatsize = sizeof(struct compat_xt_hashlimit_info),
+ .compat_from_user = compat_from_user,
+ .compat_to_user = compat_to_user,
+#endif
+ .checkentry = hashlimit_checkentry,
+ .destroy = hashlimit_destroy,
+ .me = THIS_MODULE
+ },
+ {
+ .name = "hashlimit",
+ .family = AF_INET6,
+ .match = hashlimit_match,
+ .matchsize = sizeof(struct xt_hashlimit_info),
#ifdef CONFIG_COMPAT
- .compatsize = sizeof(struct compat_ipt_hashlimit_info),
- .compat_from_user = compat_from_user,
- .compat_to_user = compat_to_user,
+ .compatsize = sizeof(struct compat_xt_hashlimit_info),
+ .compat_from_user = compat_from_user,
+ .compat_to_user = compat_to_user,
#endif
- .checkentry = hashlimit_checkentry,
- .destroy = hashlimit_destroy,
- .me = THIS_MODULE
+ .checkentry = hashlimit_checkentry,
+ .destroy = hashlimit_destroy,
+ .me = THIS_MODULE
+ },
};
/* PROC stuff */
-
static void *dl_seq_start(struct seq_file *s, loff_t *pos)
{
struct proc_dir_entry *pde = s->private;
- struct ipt_hashlimit_htable *htable = pde->data;
+ struct xt_hashlimit_htable *htable = pde->data;
unsigned int *bucket;
spin_lock_bh(&htable->lock);
@@ -598,7 +624,7 @@ static void *dl_seq_start(struct seq_file *s, loff_t *pos)
static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos)
{
struct proc_dir_entry *pde = s->private;
- struct ipt_hashlimit_htable *htable = pde->data;
+ struct xt_hashlimit_htable *htable = pde->data;
unsigned int *bucket = (unsigned int *)v;
*pos = ++(*bucket);
@@ -612,43 +638,59 @@ static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos)
static void dl_seq_stop(struct seq_file *s, void *v)
{
struct proc_dir_entry *pde = s->private;
- struct ipt_hashlimit_htable *htable = pde->data;
+ struct xt_hashlimit_htable *htable = pde->data;
unsigned int *bucket = (unsigned int *)v;
kfree(bucket);
-
spin_unlock_bh(&htable->lock);
}
-static inline int dl_seq_real_show(struct dsthash_ent *ent, struct seq_file *s)
+static int dl_seq_real_show(struct dsthash_ent *ent, int family,
+ struct seq_file *s)
{
/* recalculate to show accurate numbers */
rateinfo_recalc(ent, jiffies);
- return seq_printf(s, "%ld %u.%u.%u.%u:%u->%u.%u.%u.%u:%u %u %u %u\n",
- (long)(ent->expires - jiffies)/HZ,
- NIPQUAD(ent->dst.src_ip), ntohs(ent->dst.src_port),
- NIPQUAD(ent->dst.dst_ip), ntohs(ent->dst.dst_port),
- ent->rateinfo.credit, ent->rateinfo.credit_cap,
- ent->rateinfo.cost);
+ switch (family) {
+ case AF_INET:
+ return seq_printf(s, "%ld %u.%u.%u.%u:%u->"
+ "%u.%u.%u.%u:%u %u %u %u\n",
+ (long)(ent->expires - jiffies)/HZ,
+ NIPQUAD(ent->dst.addr.ip.src),
+ ntohs(ent->dst.src_port),
+ NIPQUAD(ent->dst.addr.ip.dst),
+ ntohs(ent->dst.dst_port),
+ ent->rateinfo.credit, ent->rateinfo.credit_cap,
+ ent->rateinfo.cost);
+ case AF_INET6:
+ return seq_printf(s, "%ld " NIP6_FMT ":%u->"
+ NIP6_FMT ":%u %u %u %u\n",
+ (long)(ent->expires - jiffies)/HZ,
+ NIP6(*(struct in6_addr *)&ent->dst.addr.ip6.src),
+ ntohs(ent->dst.src_port),
+ NIP6(*(struct in6_addr *)&ent->dst.addr.ip6.dst),
+ ntohs(ent->dst.dst_port),
+ ent->rateinfo.credit, ent->rateinfo.credit_cap,
+ ent->rateinfo.cost);
+ default:
+ BUG();
+ return 0;
+ }
}
static int dl_seq_show(struct seq_file *s, void *v)
{
struct proc_dir_entry *pde = s->private;
- struct ipt_hashlimit_htable *htable = pde->data;
+ struct xt_hashlimit_htable *htable = pde->data;
unsigned int *bucket = (unsigned int *)v;
struct dsthash_ent *ent;
struct hlist_node *pos;
- if (!hlist_empty(&htable->hash[*bucket]))
- hlist_for_each_entry(ent, pos, &htable->hash[*bucket], node) {
- if (dl_seq_real_show(ent, s)) {
- /* buffer was filled and unable to print that tuple */
+ if (!hlist_empty(&htable->hash[*bucket])) {
+ hlist_for_each_entry(ent, pos, &htable->hash[*bucket], node)
+ if (dl_seq_real_show(ent, htable->family, s))
return 1;
- }
- }
-
+ }
return 0;
}
@@ -678,56 +720,53 @@ static struct file_operations dl_file_ops = {
.release = seq_release
};
-static int init_or_fini(int fini)
+static int __init xt_hashlimit_init(void)
{
- int ret = 0;
-
- if (fini)
- goto cleanup;
+ int err;
- if (ipt_register_match(&ipt_hashlimit)) {
- ret = -EINVAL;
- goto cleanup_nothing;
- }
+ err = xt_register_matches(xt_hashlimit, ARRAY_SIZE(xt_hashlimit));
+ if (err < 0)
+ goto err1;
- hashlimit_cachep = kmem_cache_create("ipt_hashlimit",
- sizeof(struct dsthash_ent), 0,
- 0, NULL, NULL);
+ err = -ENOMEM;
+ hashlimit_cachep = kmem_cache_create("xt_hashlimit",
+ sizeof(struct dsthash_ent), 0, 0,
+ NULL, NULL);
if (!hashlimit_cachep) {
- printk(KERN_ERR "Unable to create ipt_hashlimit slab cache\n");
- ret = -ENOMEM;
- goto cleanup_unreg_match;
+ printk(KERN_ERR "xt_hashlimit: unable to create slab cache\n");
+ goto err2;
}
-
- hashlimit_procdir = proc_mkdir("ipt_hashlimit", proc_net);
- if (!hashlimit_procdir) {
- printk(KERN_ERR "Unable to create proc dir entry\n");
- ret = -ENOMEM;
- goto cleanup_free_slab;
+ hashlimit_procdir4 = proc_mkdir("ipt_hashlimit", proc_net);
+ if (!hashlimit_procdir4) {
+ printk(KERN_ERR "xt_hashlimit: unable to create proc dir "
+ "entry\n");
+ goto err3;
}
-
- return ret;
-
-cleanup:
+ hashlimit_procdir6 = proc_mkdir("ip6t_hashlimit", proc_net);
+ if (!hashlimit_procdir6) {
+ printk(KERN_ERR "xt_hashlimit: tnable to create proc dir "
+ "entry\n");
+ goto err4;
+ }
+ return 0;
+err4:
remove_proc_entry("ipt_hashlimit", proc_net);
-cleanup_free_slab:
+err3:
kmem_cache_destroy(hashlimit_cachep);
-cleanup_unreg_match:
- ipt_unregister_match(&ipt_hashlimit);
-cleanup_nothing:
- return ret;
-
-}
+err2:
+ xt_unregister_matches(xt_hashlimit, ARRAY_SIZE(xt_hashlimit));
+err1:
+ return err;
-static int __init ipt_hashlimit_init(void)
-{
- return init_or_fini(0);
}
-static void __exit ipt_hashlimit_fini(void)
+static void __exit xt_hashlimit_fini(void)
{
- init_or_fini(1);
+ remove_proc_entry("ipt_hashlimit", proc_net);
+ remove_proc_entry("ip6t_hashlimit", proc_net);
+ kmem_cache_destroy(hashlimit_cachep);
+ xt_unregister_matches(xt_hashlimit, ARRAY_SIZE(xt_hashlimit));
}
-module_init(ipt_hashlimit_init);
-module_exit(ipt_hashlimit_fini);
+module_init(xt_hashlimit_init);
+module_exit(xt_hashlimit_fini);
diff --git a/net/netfilter/xt_mark.c b/net/netfilter/xt_mark.c
index 934dddfbcd23..dfa1ee6914c0 100644
--- a/net/netfilter/xt_mark.c
+++ b/net/netfilter/xt_mark.c
@@ -31,7 +31,7 @@ match(const struct sk_buff *skb,
{
const struct xt_mark_info *info = matchinfo;
- return ((skb->nfmark & info->mask) == info->mark) ^ info->invert;
+ return ((skb->mark & info->mask) == info->mark) ^ info->invert;
}
static int
diff --git a/net/netfilter/xt_multiport.c b/net/netfilter/xt_multiport.c
index d3aefd380930..1602086c7fd6 100644
--- a/net/netfilter/xt_multiport.c
+++ b/net/netfilter/xt_multiport.c
@@ -1,5 +1,5 @@
-/* Kernel module to match one of a list of TCP/UDP/SCTP/DCCP ports: ports are in
- the same place so we can treat them as equal. */
+/* Kernel module to match one of a list of TCP/UDP(-Lite)/SCTP/DCCP 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>
@@ -104,7 +104,7 @@ match(const struct sk_buff *skb,
unsigned int protoff,
int *hotdrop)
{
- u16 _ports[2], *pptr;
+ __be16 _ports[2], *pptr;
const struct xt_multiport *multiinfo = matchinfo;
if (offset)
@@ -135,7 +135,7 @@ match_v1(const struct sk_buff *skb,
unsigned int protoff,
int *hotdrop)
{
- u16 _ports[2], *pptr;
+ __be16 _ports[2], *pptr;
const struct xt_multiport_v1 *multiinfo = matchinfo;
if (offset)
@@ -162,6 +162,7 @@ check(u_int16_t proto,
{
/* Must specify supported protocol, no unknown flags or bad count */
return (proto == IPPROTO_TCP || proto == IPPROTO_UDP
+ || proto == IPPROTO_UDPLITE
|| proto == IPPROTO_SCTP || proto == IPPROTO_DCCP)
&& !(ip_invflags & XT_INV_PROTO)
&& (match_flags == XT_MULTIPORT_SOURCE
diff --git a/net/netfilter/xt_sctp.c b/net/netfilter/xt_sctp.c
index 7956acaaa24b..71bf036f833c 100644
--- a/net/netfilter/xt_sctp.c
+++ b/net/netfilter/xt_sctp.c
@@ -71,7 +71,7 @@ match_packet(const struct sk_buff *skb,
duprintf("Chunk num: %d\toffset: %d\ttype: %d\tlength: %d\tflags: %x\n",
++i, offset, sch->type, htons(sch->length), sch->flags);
- offset += (htons(sch->length) + 3) & ~3;
+ offset += (ntohs(sch->length) + 3) & ~3;
duprintf("skb->len: %d\toffset: %d\n", skb->len, offset);
diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c
index e76a68e0bc66..46414b562a19 100644
--- a/net/netfilter/xt_tcpudp.c
+++ b/net/netfilter/xt_tcpudp.c
@@ -10,7 +10,7 @@
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv6/ip6_tables.h>
-MODULE_DESCRIPTION("x_tables match for TCP and UDP, supports IPv4 and IPv6");
+MODULE_DESCRIPTION("x_tables match for TCP and UDP(-Lite), supports IPv4 and IPv6");
MODULE_LICENSE("GPL");
MODULE_ALIAS("xt_tcp");
MODULE_ALIAS("xt_udp");
@@ -234,6 +234,24 @@ static struct xt_match xt_tcpudp_match[] = {
.proto = IPPROTO_UDP,
.me = THIS_MODULE,
},
+ {
+ .name = "udplite",
+ .family = AF_INET,
+ .checkentry = udp_checkentry,
+ .match = udp_match,
+ .matchsize = sizeof(struct xt_udp),
+ .proto = IPPROTO_UDPLITE,
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "udplite",
+ .family = AF_INET6,
+ .checkentry = udp_checkentry,
+ .match = udp_match,
+ .matchsize = sizeof(struct xt_udp),
+ .proto = IPPROTO_UDPLITE,
+ .me = THIS_MODULE,
+ },
};
static int __init xt_tcpudp_init(void)
diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c
index a6ce1d6d5c59..743b05734a49 100644
--- a/net/netlabel/netlabel_cipso_v4.c
+++ b/net/netlabel/netlabel_cipso_v4.c
@@ -407,12 +407,14 @@ static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info)
audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_ADD,
&audit_info);
- audit_log_format(audit_buf,
- " cipso_doi=%u cipso_type=%s res=%u",
- doi,
- type_str,
- ret_val == 0 ? 1 : 0);
- audit_log_end(audit_buf);
+ if (audit_buf != NULL) {
+ audit_log_format(audit_buf,
+ " cipso_doi=%u cipso_type=%s res=%u",
+ doi,
+ type_str,
+ ret_val == 0 ? 1 : 0);
+ audit_log_end(audit_buf);
+ }
return ret_val;
}
@@ -452,17 +454,13 @@ static int netlbl_cipsov4_list(struct sk_buff *skb, struct genl_info *info)
}
list_start:
- ans_skb = nlmsg_new(NLMSG_GOODSIZE * nlsze_mult, GFP_KERNEL);
+ ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE * nlsze_mult, GFP_KERNEL);
if (ans_skb == NULL) {
ret_val = -ENOMEM;
goto list_failure;
}
- data = netlbl_netlink_hdr_put(ans_skb,
- info->snd_pid,
- info->snd_seq,
- netlbl_cipsov4_gnl_family.id,
- 0,
- NLBL_CIPSOV4_C_LIST);
+ data = genlmsg_put_reply(ans_skb, info, &netlbl_cipsov4_gnl_family,
+ 0, NLBL_CIPSOV4_C_LIST);
if (data == NULL) {
ret_val = -ENOMEM;
goto list_failure;
@@ -568,7 +566,7 @@ list_start:
genlmsg_end(ans_skb, data);
- ret_val = genlmsg_unicast(ans_skb, info->snd_pid);
+ ret_val = genlmsg_reply(ans_skb, info);
if (ret_val != 0)
goto list_failure;
@@ -607,12 +605,9 @@ static int netlbl_cipsov4_listall_cb(struct cipso_v4_doi *doi_def, void *arg)
struct netlbl_cipsov4_doiwalk_arg *cb_arg = arg;
void *data;
- data = netlbl_netlink_hdr_put(cb_arg->skb,
- NETLINK_CB(cb_arg->nl_cb->skb).pid,
- cb_arg->seq,
- netlbl_cipsov4_gnl_family.id,
- NLM_F_MULTI,
- NLBL_CIPSOV4_C_LISTALL);
+ data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).pid,
+ cb_arg->seq, &netlbl_cipsov4_gnl_family,
+ NLM_F_MULTI, NLBL_CIPSOV4_C_LISTALL);
if (data == NULL)
goto listall_cb_failure;
@@ -687,11 +682,13 @@ static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info)
audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_DEL,
&audit_info);
- audit_log_format(audit_buf,
- " cipso_doi=%u res=%u",
- doi,
- ret_val == 0 ? 1 : 0);
- audit_log_end(audit_buf);
+ if (audit_buf != NULL) {
+ audit_log_format(audit_buf,
+ " cipso_doi=%u res=%u",
+ doi,
+ ret_val == 0 ? 1 : 0);
+ audit_log_end(audit_buf);
+ }
return ret_val;
}
diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c
index af4371d3b459..f46a0aeec44f 100644
--- a/net/netlabel/netlabel_domainhash.c
+++ b/net/netlabel/netlabel_domainhash.c
@@ -202,7 +202,6 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry,
int ret_val;
u32 bkt;
struct audit_buffer *audit_buf;
- char *audit_domain;
switch (entry->type) {
case NETLBL_NLTYPE_UNLABELED:
@@ -243,24 +242,24 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry,
} else
ret_val = -EINVAL;
- if (entry->domain != NULL)
- audit_domain = entry->domain;
- else
- audit_domain = "(default)";
audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_ADD, audit_info);
- audit_log_format(audit_buf, " nlbl_domain=%s", audit_domain);
- switch (entry->type) {
- case NETLBL_NLTYPE_UNLABELED:
- audit_log_format(audit_buf, " nlbl_protocol=unlbl");
- break;
- case NETLBL_NLTYPE_CIPSOV4:
+ if (audit_buf != NULL) {
audit_log_format(audit_buf,
- " nlbl_protocol=cipsov4 cipso_doi=%u",
- entry->type_def.cipsov4->doi);
- break;
+ " nlbl_domain=%s",
+ entry->domain ? entry->domain : "(default)");
+ switch (entry->type) {
+ case NETLBL_NLTYPE_UNLABELED:
+ audit_log_format(audit_buf, " nlbl_protocol=unlbl");
+ break;
+ case NETLBL_NLTYPE_CIPSOV4:
+ audit_log_format(audit_buf,
+ " nlbl_protocol=cipsov4 cipso_doi=%u",
+ entry->type_def.cipsov4->doi);
+ break;
+ }
+ audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0);
+ audit_log_end(audit_buf);
}
- audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0);
- audit_log_end(audit_buf);
rcu_read_unlock();
@@ -310,7 +309,6 @@ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info)
int ret_val = -ENOENT;
struct netlbl_dom_map *entry;
struct audit_buffer *audit_buf;
- char *audit_domain;
rcu_read_lock();
if (domain != NULL)
@@ -348,16 +346,14 @@ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info)
spin_unlock(&netlbl_domhsh_def_lock);
}
- if (entry->domain != NULL)
- audit_domain = entry->domain;
- else
- audit_domain = "(default)";
audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_DEL, audit_info);
- audit_log_format(audit_buf,
- " nlbl_domain=%s res=%u",
- audit_domain,
- ret_val == 0 ? 1 : 0);
- audit_log_end(audit_buf);
+ if (audit_buf != NULL) {
+ audit_log_format(audit_buf,
+ " nlbl_domain=%s res=%u",
+ entry->domain ? entry->domain : "(default)",
+ ret_val == 0 ? 1 : 0);
+ audit_log_end(audit_buf);
+ }
if (ret_val == 0)
call_rcu(&entry->rcu, netlbl_domhsh_free_entry);
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c
index ff971103fd0c..e03a3282c551 100644
--- a/net/netlabel/netlabel_kapi.c
+++ b/net/netlabel/netlabel_kapi.c
@@ -40,6 +40,207 @@
#include "netlabel_user.h"
/*
+ * Security Attribute Functions
+ */
+
+/**
+ * netlbl_secattr_catmap_walk - Walk a LSM secattr catmap looking for a bit
+ * @catmap: the category bitmap
+ * @offset: the offset to start searching at, in bits
+ *
+ * Description:
+ * This function walks a LSM secattr category bitmap starting at @offset and
+ * returns the spot of the first set bit or -ENOENT if no bits are set.
+ *
+ */
+int netlbl_secattr_catmap_walk(struct netlbl_lsm_secattr_catmap *catmap,
+ u32 offset)
+{
+ struct netlbl_lsm_secattr_catmap *iter = catmap;
+ u32 node_idx;
+ u32 node_bit;
+ NETLBL_CATMAP_MAPTYPE bitmap;
+
+ if (offset > iter->startbit) {
+ while (offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) {
+ iter = iter->next;
+ if (iter == NULL)
+ return -ENOENT;
+ }
+ node_idx = (offset - iter->startbit) / NETLBL_CATMAP_MAPSIZE;
+ node_bit = offset - iter->startbit -
+ (NETLBL_CATMAP_MAPSIZE * node_idx);
+ } else {
+ node_idx = 0;
+ node_bit = 0;
+ }
+ bitmap = iter->bitmap[node_idx] >> node_bit;
+
+ for (;;) {
+ if (bitmap != 0) {
+ while ((bitmap & NETLBL_CATMAP_BIT) == 0) {
+ bitmap >>= 1;
+ node_bit++;
+ }
+ return iter->startbit +
+ (NETLBL_CATMAP_MAPSIZE * node_idx) + node_bit;
+ }
+ if (++node_idx >= NETLBL_CATMAP_MAPCNT) {
+ if (iter->next != NULL) {
+ iter = iter->next;
+ node_idx = 0;
+ } else
+ return -ENOENT;
+ }
+ bitmap = iter->bitmap[node_idx];
+ node_bit = 0;
+ }
+
+ return -ENOENT;
+}
+
+/**
+ * netlbl_secattr_catmap_walk_rng - Find the end of a string of set bits
+ * @catmap: the category bitmap
+ * @offset: the offset to start searching at, in bits
+ *
+ * Description:
+ * This function walks a LSM secattr category bitmap starting at @offset and
+ * returns the spot of the first cleared bit or -ENOENT if the offset is past
+ * the end of the bitmap.
+ *
+ */
+int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap *catmap,
+ u32 offset)
+{
+ struct netlbl_lsm_secattr_catmap *iter = catmap;
+ u32 node_idx;
+ u32 node_bit;
+ NETLBL_CATMAP_MAPTYPE bitmask;
+ NETLBL_CATMAP_MAPTYPE bitmap;
+
+ if (offset > iter->startbit) {
+ while (offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) {
+ iter = iter->next;
+ if (iter == NULL)
+ return -ENOENT;
+ }
+ node_idx = (offset - iter->startbit) / NETLBL_CATMAP_MAPSIZE;
+ node_bit = offset - iter->startbit -
+ (NETLBL_CATMAP_MAPSIZE * node_idx);
+ } else {
+ node_idx = 0;
+ node_bit = 0;
+ }
+ bitmask = NETLBL_CATMAP_BIT << node_bit;
+
+ for (;;) {
+ bitmap = iter->bitmap[node_idx];
+ while (bitmask != 0 && (bitmap & bitmask) != 0) {
+ bitmask <<= 1;
+ node_bit++;
+ }
+
+ if (bitmask != 0)
+ return iter->startbit +
+ (NETLBL_CATMAP_MAPSIZE * node_idx) +
+ node_bit - 1;
+ else if (++node_idx >= NETLBL_CATMAP_MAPCNT) {
+ if (iter->next == NULL)
+ return iter->startbit + NETLBL_CATMAP_SIZE - 1;
+ iter = iter->next;
+ node_idx = 0;
+ }
+ bitmask = NETLBL_CATMAP_BIT;
+ node_bit = 0;
+ }
+
+ return -ENOENT;
+}
+
+/**
+ * netlbl_secattr_catmap_setbit - Set a bit in a LSM secattr catmap
+ * @catmap: the category bitmap
+ * @bit: the bit to set
+ * @flags: memory allocation flags
+ *
+ * Description:
+ * Set the bit specified by @bit in @catmap. Returns zero on success,
+ * negative values on failure.
+ *
+ */
+int netlbl_secattr_catmap_setbit(struct netlbl_lsm_secattr_catmap *catmap,
+ u32 bit,
+ gfp_t flags)
+{
+ struct netlbl_lsm_secattr_catmap *iter = catmap;
+ u32 node_bit;
+ u32 node_idx;
+
+ while (iter->next != NULL &&
+ bit >= (iter->startbit + NETLBL_CATMAP_SIZE))
+ iter = iter->next;
+ if (bit >= (iter->startbit + NETLBL_CATMAP_SIZE)) {
+ iter->next = netlbl_secattr_catmap_alloc(flags);
+ if (iter->next == NULL)
+ return -ENOMEM;
+ iter = iter->next;
+ iter->startbit = bit & ~(NETLBL_CATMAP_SIZE - 1);
+ }
+
+ /* gcc always rounds to zero when doing integer division */
+ node_idx = (bit - iter->startbit) / NETLBL_CATMAP_MAPSIZE;
+ node_bit = bit - iter->startbit - (NETLBL_CATMAP_MAPSIZE * node_idx);
+ iter->bitmap[node_idx] |= NETLBL_CATMAP_BIT << node_bit;
+
+ return 0;
+}
+
+/**
+ * netlbl_secattr_catmap_setrng - Set a range of bits in a LSM secattr catmap
+ * @catmap: the category bitmap
+ * @start: the starting bit
+ * @end: the last bit in the string
+ * @flags: memory allocation flags
+ *
+ * Description:
+ * Set a range of bits, starting at @start and ending with @end. Returns zero
+ * on success, negative values on failure.
+ *
+ */
+int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap,
+ u32 start,
+ u32 end,
+ gfp_t flags)
+{
+ int ret_val = 0;
+ struct netlbl_lsm_secattr_catmap *iter = catmap;
+ u32 iter_max_spot;
+ u32 spot;
+
+ /* XXX - This could probably be made a bit faster by combining writes
+ * to the catmap instead of setting a single bit each time, but for
+ * right now skipping to the start of the range in the catmap should
+ * be a nice improvement over calling the individual setbit function
+ * repeatedly from a loop. */
+
+ while (iter->next != NULL &&
+ start >= (iter->startbit + NETLBL_CATMAP_SIZE))
+ iter = iter->next;
+ iter_max_spot = iter->startbit + NETLBL_CATMAP_SIZE;
+
+ for (spot = start; spot <= end && ret_val == 0; spot++) {
+ if (spot >= iter_max_spot && iter->next != NULL) {
+ iter = iter->next;
+ iter_max_spot = iter->startbit + NETLBL_CATMAP_SIZE;
+ }
+ ret_val = netlbl_secattr_catmap_setbit(iter, spot, GFP_ATOMIC);
+ }
+
+ return ret_val;
+}
+
+/*
* LSM Functions
*/
@@ -62,6 +263,9 @@ int netlbl_socket_setattr(const struct socket *sock,
int ret_val = -ENOENT;
struct netlbl_dom_map *dom_entry;
+ if ((secattr->flags & NETLBL_SECATTR_DOMAIN) == 0)
+ return -ENOENT;
+
rcu_read_lock();
dom_entry = netlbl_domhsh_getentry(secattr->domain);
if (dom_entry == NULL)
@@ -146,10 +350,8 @@ int netlbl_socket_getattr(const struct socket *sock,
int netlbl_skbuff_getattr(const struct sk_buff *skb,
struct netlbl_lsm_secattr *secattr)
{
- int ret_val;
-
- ret_val = cipso_v4_skbuff_getattr(skb, secattr);
- if (ret_val == 0)
+ if (CIPSO_V4_OPTEXIST(skb) &&
+ cipso_v4_skbuff_getattr(skb, secattr) == 0)
return 0;
return netlbl_unlabel_getattr(secattr);
@@ -200,7 +402,7 @@ void netlbl_cache_invalidate(void)
int netlbl_cache_add(const struct sk_buff *skb,
const struct netlbl_lsm_secattr *secattr)
{
- if (secattr->cache == NULL)
+ if ((secattr->flags & NETLBL_SECATTR_CACHE) == 0)
return -ENOMSG;
if (CIPSO_V4_OPTEXIST(skb))
diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c
index 53c9079ad2c3..e8c80f33f3d7 100644
--- a/net/netlabel/netlabel_mgmt.c
+++ b/net/netlabel/netlabel_mgmt.c
@@ -188,12 +188,9 @@ static int netlbl_mgmt_listall_cb(struct netlbl_dom_map *entry, void *arg)
struct netlbl_domhsh_walk_arg *cb_arg = arg;
void *data;
- data = netlbl_netlink_hdr_put(cb_arg->skb,
- NETLINK_CB(cb_arg->nl_cb->skb).pid,
- cb_arg->seq,
- netlbl_mgmt_gnl_family.id,
- NLM_F_MULTI,
- NLBL_MGMT_C_LISTALL);
+ data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).pid,
+ cb_arg->seq, &netlbl_mgmt_gnl_family,
+ NLM_F_MULTI, NLBL_MGMT_C_LISTALL);
if (data == NULL)
goto listall_cb_failure;
@@ -356,15 +353,11 @@ static int netlbl_mgmt_listdef(struct sk_buff *skb, struct genl_info *info)
void *data;
struct netlbl_dom_map *entry;
- ans_skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+ ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (ans_skb == NULL)
return -ENOMEM;
- data = netlbl_netlink_hdr_put(ans_skb,
- info->snd_pid,
- info->snd_seq,
- netlbl_mgmt_gnl_family.id,
- 0,
- NLBL_MGMT_C_LISTDEF);
+ data = genlmsg_put_reply(ans_skb, info, &netlbl_mgmt_gnl_family,
+ 0, NLBL_MGMT_C_LISTDEF);
if (data == NULL)
goto listdef_failure;
@@ -390,7 +383,7 @@ static int netlbl_mgmt_listdef(struct sk_buff *skb, struct genl_info *info)
genlmsg_end(ans_skb, data);
- ret_val = genlmsg_unicast(ans_skb, info->snd_pid);
+ ret_val = genlmsg_reply(ans_skb, info);
if (ret_val != 0)
goto listdef_failure;
return 0;
@@ -422,12 +415,9 @@ static int netlbl_mgmt_protocols_cb(struct sk_buff *skb,
int ret_val = -ENOMEM;
void *data;
- data = netlbl_netlink_hdr_put(skb,
- NETLINK_CB(cb->skb).pid,
- cb->nlh->nlmsg_seq,
- netlbl_mgmt_gnl_family.id,
- NLM_F_MULTI,
- NLBL_MGMT_C_PROTOCOLS);
+ data = genlmsg_put(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq,
+ &netlbl_mgmt_gnl_family, NLM_F_MULTI,
+ NLBL_MGMT_C_PROTOCOLS);
if (data == NULL)
goto protocols_cb_failure;
@@ -492,15 +482,11 @@ static int netlbl_mgmt_version(struct sk_buff *skb, struct genl_info *info)
struct sk_buff *ans_skb = NULL;
void *data;
- ans_skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+ ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (ans_skb == NULL)
return -ENOMEM;
- data = netlbl_netlink_hdr_put(ans_skb,
- info->snd_pid,
- info->snd_seq,
- netlbl_mgmt_gnl_family.id,
- 0,
- NLBL_MGMT_C_VERSION);
+ data = genlmsg_put_reply(ans_skb, info, &netlbl_mgmt_gnl_family,
+ 0, NLBL_MGMT_C_VERSION);
if (data == NULL)
goto version_failure;
@@ -512,7 +498,7 @@ static int netlbl_mgmt_version(struct sk_buff *skb, struct genl_info *info)
genlmsg_end(ans_skb, data);
- ret_val = genlmsg_unicast(ans_skb, info->snd_pid);
+ ret_val = genlmsg_reply(ans_skb, info);
if (ret_val != 0)
goto version_failure;
return 0;
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index 1833ad233b39..5bc37181662e 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -35,6 +35,7 @@
#include <linux/socket.h>
#include <linux/string.h>
#include <linux/skbuff.h>
+#include <linux/audit.h>
#include <net/sock.h>
#include <net/netlink.h>
#include <net/genetlink.h>
@@ -47,7 +48,8 @@
#include "netlabel_unlabeled.h"
/* Accept unlabeled packets flag */
-static atomic_t netlabel_unlabel_accept_flg = ATOMIC_INIT(0);
+static DEFINE_SPINLOCK(netlabel_unlabel_acceptflg_lock);
+static u8 netlabel_unlabel_acceptflg = 0;
/* NetLabel Generic NETLINK CIPSOv4 family */
static struct genl_family netlbl_unlabel_gnl_family = {
@@ -82,13 +84,20 @@ static void netlbl_unlabel_acceptflg_set(u8 value,
struct audit_buffer *audit_buf;
u8 old_val;
- old_val = atomic_read(&netlabel_unlabel_accept_flg);
- atomic_set(&netlabel_unlabel_accept_flg, value);
+ rcu_read_lock();
+ old_val = netlabel_unlabel_acceptflg;
+ spin_lock(&netlabel_unlabel_acceptflg_lock);
+ netlabel_unlabel_acceptflg = value;
+ spin_unlock(&netlabel_unlabel_acceptflg_lock);
+ rcu_read_unlock();
audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_ALLOW,
audit_info);
- audit_log_format(audit_buf, " unlbl_accept=%u old=%u", value, old_val);
- audit_log_end(audit_buf);
+ if (audit_buf != NULL) {
+ audit_log_format(audit_buf,
+ " unlbl_accept=%u old=%u", value, old_val);
+ audit_log_end(audit_buf);
+ }
}
/*
@@ -138,29 +147,27 @@ static int netlbl_unlabel_list(struct sk_buff *skb, struct genl_info *info)
struct sk_buff *ans_skb;
void *data;
- ans_skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+ ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (ans_skb == NULL)
goto list_failure;
- data = netlbl_netlink_hdr_put(ans_skb,
- info->snd_pid,
- info->snd_seq,
- netlbl_unlabel_gnl_family.id,
- 0,
- NLBL_UNLABEL_C_LIST);
+ data = genlmsg_put_reply(ans_skb, info, &netlbl_unlabel_gnl_family,
+ 0, NLBL_UNLABEL_C_LIST);
if (data == NULL) {
ret_val = -ENOMEM;
goto list_failure;
}
+ rcu_read_lock();
ret_val = nla_put_u8(ans_skb,
NLBL_UNLABEL_A_ACPTFLG,
- atomic_read(&netlabel_unlabel_accept_flg));
+ netlabel_unlabel_acceptflg);
+ rcu_read_unlock();
if (ret_val != 0)
goto list_failure;
genlmsg_end(ans_skb, data);
- ret_val = genlmsg_unicast(ans_skb, info->snd_pid);
+ ret_val = genlmsg_reply(ans_skb, info);
if (ret_val != 0)
goto list_failure;
return 0;
@@ -240,10 +247,17 @@ int netlbl_unlabel_genl_init(void)
*/
int netlbl_unlabel_getattr(struct netlbl_lsm_secattr *secattr)
{
- if (atomic_read(&netlabel_unlabel_accept_flg) == 1)
- return netlbl_secattr_init(secattr);
+ int ret_val;
- return -ENOMSG;
+ rcu_read_lock();
+ if (netlabel_unlabel_acceptflg == 1) {
+ netlbl_secattr_init(secattr);
+ ret_val = 0;
+ } else
+ ret_val = -ENOMSG;
+ rcu_read_unlock();
+
+ return ret_val;
}
/**
diff --git a/net/netlabel/netlabel_user.c b/net/netlabel/netlabel_user.c
index 98a416381e61..42f12bd65964 100644
--- a/net/netlabel/netlabel_user.c
+++ b/net/netlabel/netlabel_user.c
@@ -46,6 +46,10 @@
#include "netlabel_cipso_v4.h"
#include "netlabel_user.h"
+/* do not do any auditing if audit_enabled == 0, see kernel/audit.c for
+ * details */
+extern int audit_enabled;
+
/*
* NetLabel NETLINK Setup Functions
*/
@@ -101,6 +105,9 @@ struct audit_buffer *netlbl_audit_start_common(int type,
char *secctx;
u32 secctx_len;
+ if (audit_enabled == 0)
+ return NULL;
+
audit_buf = audit_log_start(audit_ctx, GFP_ATOMIC, type);
if (audit_buf == NULL)
return NULL;
diff --git a/net/netlabel/netlabel_user.h b/net/netlabel/netlabel_user.h
index 47967ef32964..6d7f4ab46c2b 100644
--- a/net/netlabel/netlabel_user.h
+++ b/net/netlabel/netlabel_user.h
@@ -42,37 +42,6 @@
/* NetLabel NETLINK helper functions */
/**
- * netlbl_netlink_hdr_put - Write the NETLINK buffers into a sk_buff
- * @skb: the packet
- * @pid: the PID of the receipient
- * @seq: the sequence number
- * @type: the generic NETLINK message family type
- * @cmd: command
- *
- * Description:
- * Write both a NETLINK nlmsghdr structure and a Generic NETLINK genlmsghdr
- * struct to the packet. Returns a pointer to the start of the payload buffer
- * on success or NULL on failure.
- *
- */
-static inline void *netlbl_netlink_hdr_put(struct sk_buff *skb,
- u32 pid,
- u32 seq,
- int type,
- int flags,
- u8 cmd)
-{
- return genlmsg_put(skb,
- pid,
- seq,
- type,
- 0,
- flags,
- cmd,
- NETLBL_PROTO_VERSION);
-}
-
-/**
* netlbl_netlink_auditinfo - Fetch the audit information from a NETLINK msg
* @skb: the packet
* @audit_info: NetLabel audit information
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index d527c8977b1f..3baafb10f8f3 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1148,12 +1148,11 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
if (len > sk->sk_sndbuf - 32)
goto out;
err = -ENOBUFS;
- skb = nlmsg_new(len, GFP_KERNEL);
+ skb = alloc_skb(len, GFP_KERNEL);
if (skb==NULL)
goto out;
NETLINK_CB(skb).pid = nlk->pid;
- NETLINK_CB(skb).dst_pid = dst_pid;
NETLINK_CB(skb).dst_group = dst_group;
NETLINK_CB(skb).loginuid = audit_get_loginuid(current->audit_context);
selinux_get_task_sid(current, &(NETLINK_CB(skb).sid));
@@ -1435,14 +1434,13 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err)
struct sk_buff *skb;
struct nlmsghdr *rep;
struct nlmsgerr *errmsg;
- int size;
+ size_t payload = sizeof(*errmsg);
- if (err == 0)
- size = nlmsg_total_size(sizeof(*errmsg));
- else
- size = nlmsg_total_size(sizeof(*errmsg) + nlmsg_len(nlh));
+ /* error messages get the original request appened */
+ if (err)
+ payload += nlmsg_len(nlh);
- skb = nlmsg_new(size, GFP_KERNEL);
+ skb = nlmsg_new(payload, GFP_KERNEL);
if (!skb) {
struct sock *sk;
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 49bc2db7982b..b9b03747c1f3 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -331,7 +331,7 @@ static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
}
*errp = err = netlink_dump_start(genl_sock, skb, nlh,
- ops->dumpit, NULL);
+ ops->dumpit, ops->done);
if (err == 0)
skb_pull(skb, min(NLMSG_ALIGN(nlh->nlmsg_len),
skb->len));
@@ -384,16 +384,19 @@ static void genl_rcv(struct sock *sk, int len)
* Controller
**************************************************************************/
+static struct genl_family genl_ctrl = {
+ .id = GENL_ID_CTRL,
+ .name = "nlctrl",
+ .version = 0x1,
+ .maxattr = CTRL_ATTR_MAX,
+};
+
static int ctrl_fill_info(struct genl_family *family, u32 pid, u32 seq,
u32 flags, struct sk_buff *skb, u8 cmd)
{
- struct nlattr *nla_ops;
- struct genl_ops *ops;
void *hdr;
- int idx = 1;
- hdr = genlmsg_put(skb, pid, seq, GENL_ID_CTRL, 0, flags, cmd,
- family->version);
+ hdr = genlmsg_put(skb, pid, seq, &genl_ctrl, flags, cmd);
if (hdr == NULL)
return -1;
@@ -403,33 +406,39 @@ static int ctrl_fill_info(struct genl_family *family, u32 pid, u32 seq,
NLA_PUT_U32(skb, CTRL_ATTR_HDRSIZE, family->hdrsize);
NLA_PUT_U32(skb, CTRL_ATTR_MAXATTR, family->maxattr);
- nla_ops = nla_nest_start(skb, CTRL_ATTR_OPS);
- if (nla_ops == NULL)
- goto nla_put_failure;
-
- list_for_each_entry(ops, &family->ops_list, ops_list) {
- struct nlattr *nest;
+ if (!list_empty(&family->ops_list)) {
+ struct nlattr *nla_ops;
+ struct genl_ops *ops;
+ int idx = 1;
- nest = nla_nest_start(skb, idx++);
- if (nest == NULL)
+ nla_ops = nla_nest_start(skb, CTRL_ATTR_OPS);
+ if (nla_ops == NULL)
goto nla_put_failure;
- NLA_PUT_U32(skb, CTRL_ATTR_OP_ID, ops->cmd);
- NLA_PUT_U32(skb, CTRL_ATTR_OP_FLAGS, ops->flags);
+ list_for_each_entry(ops, &family->ops_list, ops_list) {
+ struct nlattr *nest;
- if (ops->policy)
- NLA_PUT_FLAG(skb, CTRL_ATTR_OP_POLICY);
+ nest = nla_nest_start(skb, idx++);
+ if (nest == NULL)
+ goto nla_put_failure;
- if (ops->doit)
- NLA_PUT_FLAG(skb, CTRL_ATTR_OP_DOIT);
+ NLA_PUT_U32(skb, CTRL_ATTR_OP_ID, ops->cmd);
+ NLA_PUT_U32(skb, CTRL_ATTR_OP_FLAGS, ops->flags);
- if (ops->dumpit)
- NLA_PUT_FLAG(skb, CTRL_ATTR_OP_DUMPIT);
+ if (ops->policy)
+ NLA_PUT_FLAG(skb, CTRL_ATTR_OP_POLICY);
- nla_nest_end(skb, nest);
- }
+ if (ops->doit)
+ NLA_PUT_FLAG(skb, CTRL_ATTR_OP_DOIT);
- nla_nest_end(skb, nla_ops);
+ if (ops->dumpit)
+ NLA_PUT_FLAG(skb, CTRL_ATTR_OP_DUMPIT);
+
+ nla_nest_end(skb, nest);
+ }
+
+ nla_nest_end(skb, nla_ops);
+ }
return genlmsg_end(skb, hdr);
@@ -480,7 +489,7 @@ static struct sk_buff *ctrl_build_msg(struct genl_family *family, u32 pid,
struct sk_buff *skb;
int err;
- skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+ skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (skb == NULL)
return ERR_PTR(-ENOBUFS);
@@ -529,7 +538,7 @@ static int ctrl_getfamily(struct sk_buff *skb, struct genl_info *info)
goto errout;
}
- err = genlmsg_unicast(msg, info->snd_pid);
+ err = genlmsg_reply(msg, info);
errout:
return err;
}
@@ -562,13 +571,6 @@ static struct genl_ops genl_ctrl_ops = {
.policy = ctrl_policy,
};
-static struct genl_family genl_ctrl = {
- .id = GENL_ID_CTRL,
- .name = "nlctrl",
- .version = 0x1,
- .maxattr = CTRL_ATTR_MAX,
-};
-
static int __init genl_init(void)
{
int i, err;
diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c
index c11737f472d6..0096105bcd47 100644
--- a/net/netrom/nr_route.c
+++ b/net/netrom/nr_route.c
@@ -155,14 +155,15 @@ static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax2
atomic_set(&nr_neigh->refcount, 1);
if (ax25_digi != NULL && ax25_digi->ndigi > 0) {
- if ((nr_neigh->digipeat = kmalloc(sizeof(*ax25_digi), GFP_KERNEL)) == NULL) {
+ nr_neigh->digipeat = kmemdup(ax25_digi,
+ sizeof(*ax25_digi),
+ GFP_KERNEL);
+ if (nr_neigh->digipeat == NULL) {
kfree(nr_neigh);
if (nr_node)
nr_node_put(nr_node);
return -ENOMEM;
}
- memcpy(nr_neigh->digipeat, ax25_digi,
- sizeof(*ax25_digi));
}
spin_lock_bh(&nr_neigh_list_lock);
@@ -432,11 +433,12 @@ static int nr_add_neigh(ax25_address *callsign, ax25_digi *ax25_digi, struct net
atomic_set(&nr_neigh->refcount, 1);
if (ax25_digi != NULL && ax25_digi->ndigi > 0) {
- if ((nr_neigh->digipeat = kmalloc(sizeof(*ax25_digi), GFP_KERNEL)) == NULL) {
+ nr_neigh->digipeat = kmemdup(ax25_digi, sizeof(*ax25_digi),
+ GFP_KERNEL);
+ if (nr_neigh->digipeat == NULL) {
kfree(nr_neigh);
return -ENOMEM;
}
- memcpy(nr_neigh->digipeat, ax25_digi, sizeof(*ax25_digi));
}
spin_lock_bh(&nr_neigh_list_lock);
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index f4ccb90e6739..271d2eed0699 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -201,7 +201,7 @@ struct packet_sock {
spinlock_t bind_lock;
char running; /* prot_hook is attached*/
int ifindex; /* bound device */
- unsigned short num;
+ __be16 num;
#ifdef CONFIG_PACKET_MULTICAST
struct packet_mclist *mclist;
#endif
@@ -331,7 +331,7 @@ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock,
struct sockaddr_pkt *saddr=(struct sockaddr_pkt *)msg->msg_name;
struct sk_buff *skb;
struct net_device *dev;
- unsigned short proto=0;
+ __be16 proto=0;
int err;
/*
@@ -704,7 +704,7 @@ static int packet_sendmsg(struct kiocb *iocb, struct socket *sock,
struct sockaddr_ll *saddr=(struct sockaddr_ll *)msg->msg_name;
struct sk_buff *skb;
struct net_device *dev;
- unsigned short proto;
+ __be16 proto;
unsigned char *addr;
int ifindex, err, reserve = 0;
@@ -858,7 +858,7 @@ static int packet_release(struct socket *sock)
* Attach a packet hook.
*/
-static int packet_do_bind(struct sock *sk, struct net_device *dev, int protocol)
+static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 protocol)
{
struct packet_sock *po = pkt_sk(sk);
/*
@@ -983,6 +983,7 @@ static int packet_create(struct socket *sock, int protocol)
{
struct sock *sk;
struct packet_sock *po;
+ __be16 proto = (__force __be16)protocol; /* weird, but documented */
int err;
if (!capable(CAP_NET_RAW))
@@ -1010,7 +1011,7 @@ static int packet_create(struct socket *sock, int protocol)
po = pkt_sk(sk);
sk->sk_family = PF_PACKET;
- po->num = protocol;
+ po->num = proto;
sk->sk_destruct = packet_sock_destruct;
atomic_inc(&packet_socks_nr);
@@ -1027,8 +1028,8 @@ static int packet_create(struct socket *sock, int protocol)
#endif
po->prot_hook.af_packet_priv = sk;
- if (protocol) {
- po->prot_hook.type = protocol;
+ if (proto) {
+ po->prot_hook.type = proto;
dev_add_pack(&po->prot_hook);
sock_hold(sk);
po->running = 1;
@@ -1624,7 +1625,8 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing
{
char **pg_vec = NULL;
struct packet_sock *po = pkt_sk(sk);
- int was_running, num, order = 0;
+ int was_running, order = 0;
+ __be16 num;
int err = 0;
if (req->tp_block_nr) {
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
index a22542fa1bc8..7252344779a0 100644
--- a/net/rose/rose_route.c
+++ b/net/rose/rose_route.c
@@ -396,7 +396,7 @@ int rose_add_loopback_neigh(void)
int rose_add_loopback_node(rose_address *address)
{
struct rose_node *rose_node;
- unsigned int err = 0;
+ int err = 0;
spin_lock_bh(&rose_node_list_lock);
@@ -432,7 +432,7 @@ int rose_add_loopback_node(rose_address *address)
out:
spin_unlock_bh(&rose_node_list_lock);
- return 0;
+ return err;
}
/*
diff --git a/net/rxrpc/transport.c b/net/rxrpc/transport.c
index 94b2e2fe6fdb..4268b38d92d2 100644
--- a/net/rxrpc/transport.c
+++ b/net/rxrpc/transport.c
@@ -31,7 +31,6 @@
#endif
#include <linux/errqueue.h>
#include <asm/uaccess.h>
-#include <asm/checksum.h>
#include "internal.h"
struct errormsg {
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index 8298ea9ffe19..f4544dd86476 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -6,6 +6,7 @@ menu "QoS and/or fair queueing"
config NET_SCHED
bool "QoS and/or fair queueing"
+ select NET_SCH_FIFO
---help---
When the kernel has several packets to send out over a network
device, it has to decide which ones to send first, which ones to
@@ -40,6 +41,9 @@ config NET_SCHED
The available schedulers are listed in the following questions; you
can say Y to as many as you like. If unsure, say N now.
+config NET_SCH_FIFO
+ bool
+
if NET_SCHED
choice
@@ -320,7 +324,7 @@ config CLS_U32_PERF
config CLS_U32_MARK
bool "Netfilter marks support"
- depends on NET_CLS_U32 && NETFILTER
+ depends on NET_CLS_U32
---help---
Say Y here to be able to use netfilter marks as u32 key.
diff --git a/net/sched/Makefile b/net/sched/Makefile
index 0f06aec66094..ff2d6e5e282c 100644
--- a/net/sched/Makefile
+++ b/net/sched/Makefile
@@ -4,7 +4,7 @@
obj-y := sch_generic.o
-obj-$(CONFIG_NET_SCHED) += sch_api.o sch_fifo.o sch_blackhole.o
+obj-$(CONFIG_NET_SCHED) += sch_api.o sch_blackhole.o
obj-$(CONFIG_NET_CLS) += cls_api.o
obj-$(CONFIG_NET_CLS_ACT) += act_api.o
obj-$(CONFIG_NET_ACT_POLICE) += act_police.o
@@ -14,6 +14,7 @@ obj-$(CONFIG_NET_ACT_MIRRED) += act_mirred.o
obj-$(CONFIG_NET_ACT_IPT) += act_ipt.o
obj-$(CONFIG_NET_ACT_PEDIT) += act_pedit.o
obj-$(CONFIG_NET_ACT_SIMP) += act_simple.o
+obj-$(CONFIG_NET_SCH_FIFO) += sch_fifo.o
obj-$(CONFIG_NET_SCH_CBQ) += sch_cbq.o
obj-$(CONFIG_NET_SCH_HTB) += sch_htb.o
obj-$(CONFIG_NET_SCH_HPFQ) += sch_hpfq.o
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index 6cff56696a81..85de7efd5fea 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -48,14 +48,14 @@ static struct tcf_hashinfo gact_hash_info = {
#ifdef CONFIG_GACT_PROB
static int gact_net_rand(struct tcf_gact *gact)
{
- if (net_random() % gact->tcfg_pval)
+ if (!gact->tcfg_pval || net_random() % gact->tcfg_pval)
return gact->tcf_action;
return gact->tcfg_paction;
}
static int gact_determ(struct tcf_gact *gact)
{
- if (gact->tcf_bstats.packets % gact->tcfg_pval)
+ if (!gact->tcfg_pval || gact->tcf_bstats.packets % gact->tcfg_pval)
return gact->tcf_action;
return gact->tcfg_paction;
}
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index d8c9310da6e5..a9608064a4c3 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -156,10 +156,9 @@ static int tcf_ipt_init(struct rtattr *rta, struct rtattr *est,
rtattr_strlcpy(tname, tb[TCA_IPT_TABLE-1], IFNAMSIZ) >= IFNAMSIZ)
strcpy(tname, "mangle");
- t = kmalloc(td->u.target_size, GFP_KERNEL);
+ t = kmemdup(td, td->u.target_size, GFP_KERNEL);
if (unlikely(!t))
goto err2;
- memcpy(t, td, td->u.target_size);
if ((err = ipt_init_target(t, tname, hook)) < 0)
goto err3;
@@ -256,13 +255,12 @@ static int tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int
** for foolproof you need to not assume this
*/
- t = kmalloc(ipt->tcfi_t->u.user.target_size, GFP_ATOMIC);
+ t = kmemdup(ipt->tcfi_t, ipt->tcfi_t->u.user.target_size, GFP_ATOMIC);
if (unlikely(!t))
goto rtattr_failure;
c.bindcnt = ipt->tcf_bindcnt - bind;
c.refcnt = ipt->tcf_refcnt - ref;
- memcpy(t, ipt->tcfi_t, ipt->tcfi_t->u.user.target_size);
strcpy(t->u.user.name, ipt->tcfi_t->u.kernel.target->name);
RTA_PUT(skb, TCA_IPT_TARG, ipt->tcfi_t->u.user.target_size, t);
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index fed47b658837..af68e1e83251 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -46,6 +46,18 @@ static struct tcf_hashinfo police_hash_info = {
.lock = &police_lock,
};
+/* old policer structure from before tc actions */
+struct tc_police_compat
+{
+ u32 index;
+ int action;
+ u32 limit;
+ u32 burst;
+ u32 mtu;
+ struct tc_ratespec rate;
+ struct tc_ratespec peakrate;
+};
+
/* Each policer is serialized by its individual spinlock */
#ifdef CONFIG_NET_CLS_ACT
@@ -131,12 +143,15 @@ static int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est,
struct tc_police *parm;
struct tcf_police *police;
struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL;
+ int size;
if (rta == NULL || rtattr_parse_nested(tb, TCA_POLICE_MAX, rta) < 0)
return -EINVAL;
- if (tb[TCA_POLICE_TBF-1] == NULL ||
- RTA_PAYLOAD(tb[TCA_POLICE_TBF-1]) != sizeof(*parm))
+ if (tb[TCA_POLICE_TBF-1] == NULL)
+ return -EINVAL;
+ size = RTA_PAYLOAD(tb[TCA_POLICE_TBF-1]);
+ if (size != sizeof(*parm) && size != sizeof(struct tc_police_compat))
return -EINVAL;
parm = RTA_DATA(tb[TCA_POLICE_TBF-1]);
@@ -415,12 +430,15 @@ struct tcf_police *tcf_police_locate(struct rtattr *rta, struct rtattr *est)
struct tcf_police *police;
struct rtattr *tb[TCA_POLICE_MAX];
struct tc_police *parm;
+ int size;
if (rtattr_parse_nested(tb, TCA_POLICE_MAX, rta) < 0)
return NULL;
- if (tb[TCA_POLICE_TBF-1] == NULL ||
- RTA_PAYLOAD(tb[TCA_POLICE_TBF-1]) != sizeof(*parm))
+ if (tb[TCA_POLICE_TBF-1] == NULL)
+ return NULL;
+ size = RTA_PAYLOAD(tb[TCA_POLICE_TBF-1]);
+ if (size != sizeof(*parm) && size != sizeof(struct tc_police_compat))
return NULL;
parm = RTA_DATA(tb[TCA_POLICE_TBF-1]);
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c
index 901571a67707..5fe80854ca91 100644
--- a/net/sched/act_simple.c
+++ b/net/sched/act_simple.c
@@ -71,11 +71,10 @@ static int tcf_simp_release(struct tcf_defact *d, int bind)
static int alloc_defdata(struct tcf_defact *d, u32 datalen, void *defdata)
{
- d->tcfd_defdata = kmalloc(datalen, GFP_KERNEL);
+ d->tcfd_defdata = kmemdup(defdata, datalen, GFP_KERNEL);
if (unlikely(!d->tcfd_defdata))
return -ENOMEM;
d->tcfd_datalen = datalen;
- memcpy(d->tcfd_defdata, defdata, datalen);
return 0;
}
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 37a184021647..edb8fc97ae11 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -217,7 +217,7 @@ replay:
/* Create new proto tcf */
err = -ENOBUFS;
- if ((tp = kmalloc(sizeof(*tp), GFP_KERNEL)) == NULL)
+ if ((tp = kzalloc(sizeof(*tp), GFP_KERNEL)) == NULL)
goto errout;
err = -EINVAL;
tp_ops = tcf_proto_lookup_ops(tca[TCA_KIND-1]);
@@ -247,7 +247,6 @@ replay:
kfree(tp);
goto errout;
}
- memset(tp, 0, sizeof(*tp));
tp->ops = tp_ops;
tp->protocol = protocol;
tp->prio = nprio ? : tcf_auto_prio(*back);
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index e54acc6bcccd..f59a2c4aa039 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -101,11 +101,7 @@ static int fw_classify(struct sk_buff *skb, struct tcf_proto *tp,
struct fw_head *head = (struct fw_head*)tp->root;
struct fw_filter *f;
int r;
-#ifdef CONFIG_NETFILTER
- u32 id = skb->nfmark & head->mask;
-#else
- u32 id = 0;
-#endif
+ u32 id = skb->mark & head->mask;
if (head != NULL) {
for (f=head->ht[fw_hash(id)]; f; f=f->next) {
diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h
index 6e230ecfba05..587b9adab38c 100644
--- a/net/sched/cls_rsvp.h
+++ b/net/sched/cls_rsvp.h
@@ -77,7 +77,7 @@ struct rsvp_head
struct rsvp_session
{
struct rsvp_session *next;
- u32 dst[RSVP_DST_LEN];
+ __be32 dst[RSVP_DST_LEN];
struct tc_rsvp_gpi dpi;
u8 protocol;
u8 tunnelid;
@@ -89,7 +89,7 @@ struct rsvp_session
struct rsvp_filter
{
struct rsvp_filter *next;
- u32 src[RSVP_DST_LEN];
+ __be32 src[RSVP_DST_LEN];
struct tc_rsvp_gpi spi;
u8 tunnelhdr;
@@ -100,17 +100,17 @@ struct rsvp_filter
struct rsvp_session *sess;
};
-static __inline__ unsigned hash_dst(u32 *dst, u8 protocol, u8 tunnelid)
+static __inline__ unsigned hash_dst(__be32 *dst, u8 protocol, u8 tunnelid)
{
- unsigned h = dst[RSVP_DST_LEN-1];
+ unsigned h = (__force __u32)dst[RSVP_DST_LEN-1];
h ^= h>>16;
h ^= h>>8;
return (h ^ protocol ^ tunnelid) & 0xFF;
}
-static __inline__ unsigned hash_src(u32 *src)
+static __inline__ unsigned hash_src(__be32 *src)
{
- unsigned h = src[RSVP_DST_LEN-1];
+ unsigned h = (__force __u32)src[RSVP_DST_LEN-1];
h ^= h>>16;
h ^= h>>8;
h ^= h>>4;
@@ -138,7 +138,7 @@ static int rsvp_classify(struct sk_buff *skb, struct tcf_proto *tp,
struct rsvp_session *s;
struct rsvp_filter *f;
unsigned h1, h2;
- u32 *dst, *src;
+ __be32 *dst, *src;
u8 protocol;
u8 tunnelid = 0;
u8 *xprt;
@@ -410,7 +410,7 @@ static int rsvp_change(struct tcf_proto *tp, unsigned long base,
struct rtattr *tb[TCA_RSVP_MAX];
struct tcf_exts e;
unsigned h1, h2;
- u32 *dst;
+ __be32 *dst;
int err;
if (opt == NULL)
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 0a6cfa0005be..8b5194801995 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -143,7 +143,7 @@ next_knode:
#endif
#ifdef CONFIG_CLS_U32_MARK
- if ((skb->nfmark & n->mark.mask) != n->mark.val) {
+ if ((skb->mark & n->mark.mask) != n->mark.val) {
n = n->next;
goto next_knode;
} else {
diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c
index 61e3b740ab1a..45d47d37155e 100644
--- a/net/sched/em_meta.c
+++ b/net/sched/em_meta.c
@@ -208,13 +208,9 @@ META_COLLECTOR(int_maclen)
* Netfilter
**************************************************************************/
-META_COLLECTOR(int_nfmark)
+META_COLLECTOR(int_mark)
{
-#ifdef CONFIG_NETFILTER
- dst->value = skb->nfmark;
-#else
- dst->value = 0;
-#endif
+ dst->value = skb->mark;
}
/**************************************************************************
@@ -490,7 +486,7 @@ static struct meta_ops __meta_ops[TCF_META_TYPE_MAX+1][TCF_META_ID_MAX+1] = {
[META_ID(PKTLEN)] = META_FUNC(int_pktlen),
[META_ID(DATALEN)] = META_FUNC(int_datalen),
[META_ID(MACLEN)] = META_FUNC(int_maclen),
- [META_ID(NFMARK)] = META_FUNC(int_nfmark),
+ [META_ID(NFMARK)] = META_FUNC(int_mark),
[META_ID(TCINDEX)] = META_FUNC(int_tcindex),
[META_ID(RTCLASSID)] = META_FUNC(int_rtclassid),
[META_ID(RTIIF)] = META_FUNC(int_rtiif),
@@ -550,10 +546,9 @@ static int meta_var_change(struct meta_value *dst, struct rtattr *rta)
{
int len = RTA_PAYLOAD(rta);
- dst->val = (unsigned long) kmalloc(len, GFP_KERNEL);
+ dst->val = (unsigned long)kmemdup(RTA_DATA(rta), len, GFP_KERNEL);
if (dst->val == 0UL)
return -ENOMEM;
- memcpy((void *) dst->val, RTA_DATA(rta), len);
dst->len = len;
return 0;
}
diff --git a/net/sched/em_nbyte.c b/net/sched/em_nbyte.c
index cc80babfd79f..005db409be64 100644
--- a/net/sched/em_nbyte.c
+++ b/net/sched/em_nbyte.c
@@ -34,12 +34,10 @@ static int em_nbyte_change(struct tcf_proto *tp, void *data, int data_len,
return -EINVAL;
em->datalen = sizeof(*nbyte) + nbyte->len;
- em->data = (unsigned long) kmalloc(em->datalen, GFP_KERNEL);
+ em->data = (unsigned long)kmemdup(data, em->datalen, GFP_KERNEL);
if (em->data == 0UL)
return -ENOBUFS;
- memcpy((void *) em->data, data, em->datalen);
-
return 0;
}
diff --git a/net/sched/ematch.c b/net/sched/ematch.c
index 0fd0768a17c6..8f8a16da72a8 100644
--- a/net/sched/ematch.c
+++ b/net/sched/ematch.c
@@ -251,12 +251,11 @@ static int tcf_em_validate(struct tcf_proto *tp,
goto errout;
em->data = *(u32 *) data;
} else {
- void *v = kmalloc(data_len, GFP_KERNEL);
+ void *v = kmemdup(data, data_len, GFP_KERNEL);
if (v == NULL) {
err = -ENOBUFS;
goto errout;
}
- memcpy(v, data, data_len);
em->data = (unsigned long) v;
}
}
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 0b6489291140..65825f4409d9 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -191,21 +191,27 @@ int unregister_qdisc(struct Qdisc_ops *qops)
(root qdisc, all its children, children of children etc.)
*/
-struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle)
+static struct Qdisc *__qdisc_lookup(struct net_device *dev, u32 handle)
{
struct Qdisc *q;
- read_lock(&qdisc_tree_lock);
list_for_each_entry(q, &dev->qdisc_list, list) {
- if (q->handle == handle) {
- read_unlock(&qdisc_tree_lock);
+ if (q->handle == handle)
return q;
- }
}
- read_unlock(&qdisc_tree_lock);
return NULL;
}
+struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle)
+{
+ struct Qdisc *q;
+
+ read_lock(&qdisc_tree_lock);
+ q = __qdisc_lookup(dev, handle);
+ read_unlock(&qdisc_tree_lock);
+ return q;
+}
+
static struct Qdisc *qdisc_leaf(struct Qdisc *p, u32 classid)
{
unsigned long cl;
@@ -348,6 +354,26 @@ dev_graft_qdisc(struct net_device *dev, struct Qdisc *qdisc)
return oqdisc;
}
+void qdisc_tree_decrease_qlen(struct Qdisc *sch, unsigned int n)
+{
+ struct Qdisc_class_ops *cops;
+ unsigned long cl;
+ u32 parentid;
+
+ if (n == 0)
+ return;
+ while ((parentid = sch->parent)) {
+ sch = __qdisc_lookup(sch->dev, TC_H_MAJ(parentid));
+ cops = sch->ops->cl_ops;
+ if (cops->qlen_notify) {
+ cl = cops->get(sch, parentid);
+ cops->qlen_notify(sch, cl);
+ cops->put(sch, cl);
+ }
+ sch->q.qlen -= n;
+ }
+}
+EXPORT_SYMBOL(qdisc_tree_decrease_qlen);
/* Graft qdisc "new" to class "classid" of qdisc "parent" or
to device "dev".
@@ -1112,7 +1138,7 @@ int tc_classify(struct sk_buff *skb, struct tcf_proto *tp,
struct tcf_result *res)
{
int err = 0;
- u32 protocol = skb->protocol;
+ __be16 protocol = skb->protocol;
#ifdef CONFIG_NET_CLS_ACT
struct tcf_proto *otp = tp;
reclassify:
@@ -1277,7 +1303,6 @@ static int __init pktsched_init(void)
subsys_initcall(pktsched_init);
-EXPORT_SYMBOL(qdisc_lookup);
EXPORT_SYMBOL(qdisc_get_rtab);
EXPORT_SYMBOL(qdisc_put_rtab);
EXPORT_SYMBOL(register_qdisc);
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index dbf44da0912f..edc7bb0b9c8b 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -316,7 +316,7 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
}
memset(flow,0,sizeof(*flow));
flow->filter_list = NULL;
- if (!(flow->q = qdisc_create_dflt(sch->dev,&pfifo_qdisc_ops)))
+ if (!(flow->q = qdisc_create_dflt(sch->dev,&pfifo_qdisc_ops,classid)))
flow->q = &noop_qdisc;
DPRINTK("atm_tc_change: qdisc %p\n",flow->q);
flow->sock = sock;
@@ -576,7 +576,8 @@ static int atm_tc_init(struct Qdisc *sch,struct rtattr *opt)
DPRINTK("atm_tc_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt);
p->flows = &p->link;
- if(!(p->link.q = qdisc_create_dflt(sch->dev,&pfifo_qdisc_ops)))
+ if(!(p->link.q = qdisc_create_dflt(sch->dev,&pfifo_qdisc_ops,
+ sch->handle)))
p->link.q = &noop_qdisc;
DPRINTK("atm_tc_init: link (%p) qdisc %p\n",&p->link,p->link.q);
p->link.filter_list = NULL;
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index bac881bfe362..ba82dfab6043 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -1429,7 +1429,8 @@ static int cbq_init(struct Qdisc *sch, struct rtattr *opt)
q->link.sibling = &q->link;
q->link.classid = sch->handle;
q->link.qdisc = sch;
- if (!(q->link.q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops)))
+ if (!(q->link.q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops,
+ sch->handle)))
q->link.q = &noop_qdisc;
q->link.priority = TC_CBQ_MAXPRIO-1;
@@ -1674,7 +1675,8 @@ static int cbq_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
if (cl) {
if (new == NULL) {
- if ((new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops)) == NULL)
+ if ((new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops,
+ cl->classid)) == NULL)
return -ENOBUFS;
} else {
#ifdef CONFIG_NET_CLS_POLICE
@@ -1685,7 +1687,7 @@ static int cbq_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
sch_tree_lock(sch);
*old = cl->q;
cl->q = new;
- sch->q.qlen -= (*old)->q.qlen;
+ qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
qdisc_reset(*old);
sch_tree_unlock(sch);
@@ -1932,7 +1934,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t
cl->R_tab = rtab;
rtab = NULL;
cl->refcnt = 1;
- if (!(cl->q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops)))
+ if (!(cl->q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, classid)))
cl->q = &noop_qdisc;
cl->classid = classid;
cl->tparent = parent;
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c
index 11c8a2119b96..d5421816f007 100644
--- a/net/sched/sch_dsmark.c
+++ b/net/sched/sch_dsmark.c
@@ -88,15 +88,16 @@ static int dsmark_graft(struct Qdisc *sch, unsigned long arg,
sch, p, new, old);
if (new == NULL) {
- new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
+ new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops,
+ sch->handle);
if (new == NULL)
new = &noop_qdisc;
}
sch_tree_lock(sch);
*old = xchg(&p->q, new);
+ qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
qdisc_reset(*old);
- sch->q.qlen = 0;
sch_tree_unlock(sch);
return 0;
@@ -307,7 +308,7 @@ static struct sk_buff *dsmark_dequeue(struct Qdisc *sch)
if (p->mask[index] != 0xff || p->value[index])
printk(KERN_WARNING "dsmark_dequeue: "
"unsupported protocol %d\n",
- htons(skb->protocol));
+ ntohs(skb->protocol));
break;
};
@@ -387,7 +388,7 @@ static int dsmark_init(struct Qdisc *sch, struct rtattr *opt)
p->default_index = default_index;
p->set_tc_index = RTA_GET_FLAG(tb[TCA_DSMARK_SET_TC_INDEX-1]);
- p->q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
+ p->q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, sch->handle);
if (p->q == NULL)
p->q = &noop_qdisc;
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 88c6a99ce53c..bc116bd6937c 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -450,13 +450,15 @@ errout:
return ERR_PTR(-err);
}
-struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops)
+struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops,
+ unsigned int parentid)
{
struct Qdisc *sch;
sch = qdisc_alloc(dev, ops);
if (IS_ERR(sch))
goto errout;
+ sch->parent = parentid;
if (!ops->init || ops->init(sch, NULL) == 0)
return sch;
@@ -520,7 +522,8 @@ void dev_activate(struct net_device *dev)
if (dev->qdisc_sleeping == &noop_qdisc) {
struct Qdisc *qdisc;
if (dev->tx_queue_len) {
- qdisc = qdisc_create_dflt(dev, &pfifo_fast_ops);
+ qdisc = qdisc_create_dflt(dev, &pfifo_fast_ops,
+ TC_H_ROOT);
if (qdisc == NULL) {
printk(KERN_INFO "%s: activation failed\n", dev->name);
return;
@@ -606,13 +609,10 @@ void dev_shutdown(struct net_device *dev)
qdisc_unlock_tree(dev);
}
-EXPORT_SYMBOL(__netdev_watchdog_up);
EXPORT_SYMBOL(netif_carrier_on);
EXPORT_SYMBOL(netif_carrier_off);
EXPORT_SYMBOL(noop_qdisc);
-EXPORT_SYMBOL(noop_qdisc_ops);
EXPORT_SYMBOL(qdisc_create_dflt);
-EXPORT_SYMBOL(qdisc_alloc);
EXPORT_SYMBOL(qdisc_destroy);
EXPORT_SYMBOL(qdisc_reset);
EXPORT_SYMBOL(qdisc_lock_tree);
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index 6a6735a2ed35..6eefa6995777 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -946,6 +946,7 @@ qdisc_peek_len(struct Qdisc *sch)
if (unlikely(sch->ops->requeue(skb, sch) != NET_XMIT_SUCCESS)) {
if (net_ratelimit())
printk("qdisc_peek_len: failed to requeue\n");
+ qdisc_tree_decrease_qlen(sch, 1);
return 0;
}
return len;
@@ -957,11 +958,7 @@ hfsc_purge_queue(struct Qdisc *sch, struct hfsc_class *cl)
unsigned int len = cl->qdisc->q.qlen;
qdisc_reset(cl->qdisc);
- if (len > 0) {
- update_vf(cl, 0, 0);
- set_passive(cl);
- sch->q.qlen -= len;
- }
+ qdisc_tree_decrease_qlen(cl->qdisc, len);
}
static void
@@ -1138,7 +1135,7 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
cl->classid = classid;
cl->sched = q;
cl->cl_parent = parent;
- cl->qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
+ cl->qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, classid);
if (cl->qdisc == NULL)
cl->qdisc = &noop_qdisc;
cl->stats_lock = &sch->dev->queue_lock;
@@ -1271,7 +1268,8 @@ hfsc_graft_class(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
if (cl->level > 0)
return -EINVAL;
if (new == NULL) {
- new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
+ new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops,
+ cl->classid);
if (new == NULL)
new = &noop_qdisc;
}
@@ -1294,6 +1292,17 @@ hfsc_class_leaf(struct Qdisc *sch, unsigned long arg)
return NULL;
}
+static void
+hfsc_qlen_notify(struct Qdisc *sch, unsigned long arg)
+{
+ struct hfsc_class *cl = (struct hfsc_class *)arg;
+
+ if (cl->qdisc->q.qlen == 0) {
+ update_vf(cl, 0, 0);
+ set_passive(cl);
+ }
+}
+
static unsigned long
hfsc_get_class(struct Qdisc *sch, u32 classid)
{
@@ -1514,7 +1523,8 @@ hfsc_init_qdisc(struct Qdisc *sch, struct rtattr *opt)
q->root.refcnt = 1;
q->root.classid = sch->handle;
q->root.sched = q;
- q->root.qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
+ q->root.qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops,
+ sch->handle);
if (q->root.qdisc == NULL)
q->root.qdisc = &noop_qdisc;
q->root.stats_lock = &sch->dev->queue_lock;
@@ -1777,6 +1787,7 @@ static struct Qdisc_class_ops hfsc_class_ops = {
.delete = hfsc_delete_class,
.graft = hfsc_graft_class,
.leaf = hfsc_class_leaf,
+ .qlen_notify = hfsc_qlen_notify,
.get = hfsc_get_class,
.put = hfsc_put_class,
.bind_tcf = hfsc_bind_tcf,
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 4b52fa78935a..215e68c2b615 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -1223,17 +1223,14 @@ static int htb_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
struct htb_class *cl = (struct htb_class *)arg;
if (cl && !cl->level) {
- if (new == NULL && (new = qdisc_create_dflt(sch->dev,
- &pfifo_qdisc_ops))
+ if (new == NULL &&
+ (new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops,
+ cl->classid))
== NULL)
return -ENOBUFS;
sch_tree_lock(sch);
if ((*old = xchg(&cl->un.leaf.q, new)) != NULL) {
- if (cl->prio_activity)
- htb_deactivate(qdisc_priv(sch), cl);
-
- /* TODO: is it correct ? Why CBQ doesn't do it ? */
- sch->q.qlen -= (*old)->q.qlen;
+ qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
qdisc_reset(*old);
}
sch_tree_unlock(sch);
@@ -1248,6 +1245,14 @@ static struct Qdisc *htb_leaf(struct Qdisc *sch, unsigned long arg)
return (cl && !cl->level) ? cl->un.leaf.q : NULL;
}
+static void htb_qlen_notify(struct Qdisc *sch, unsigned long arg)
+{
+ struct htb_class *cl = (struct htb_class *)arg;
+
+ if (cl->un.leaf.q->q.qlen == 0)
+ htb_deactivate(qdisc_priv(sch), cl);
+}
+
static unsigned long htb_get(struct Qdisc *sch, u32 classid)
{
struct htb_class *cl = htb_find(classid, sch);
@@ -1269,9 +1274,9 @@ static void htb_destroy_filters(struct tcf_proto **fl)
static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl)
{
struct htb_sched *q = qdisc_priv(sch);
+
if (!cl->level) {
BUG_TRAP(cl->un.leaf.q);
- sch->q.qlen -= cl->un.leaf.q->q.qlen;
qdisc_destroy(cl->un.leaf.q);
}
qdisc_put_rtab(cl->rate);
@@ -1322,6 +1327,7 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg)
{
struct htb_sched *q = qdisc_priv(sch);
struct htb_class *cl = (struct htb_class *)arg;
+ unsigned int qlen;
// TODO: why don't allow to delete subtree ? references ? does
// tc subsys quarantee us that in htb_destroy it holds no class
@@ -1334,6 +1340,12 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg)
/* delete from hash and active; remainder in destroy_class */
hlist_del_init(&cl->hlist);
+ if (!cl->level) {
+ qlen = cl->un.leaf.q->q.qlen;
+ qdisc_reset(cl->un.leaf.q);
+ qdisc_tree_decrease_qlen(cl->un.leaf.q, qlen);
+ }
+
if (cl->prio_activity)
htb_deactivate(q, cl);
@@ -1410,11 +1422,14 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
/* create leaf qdisc early because it uses kmalloc(GFP_KERNEL)
so that can't be used inside of sch_tree_lock
-- thanks to Karlis Peisenieks */
- new_q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
+ new_q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, classid);
sch_tree_lock(sch);
if (parent && !parent->level) {
+ unsigned int qlen = parent->un.leaf.q->q.qlen;
+
/* turn parent into inner node */
- sch->q.qlen -= parent->un.leaf.q->q.qlen;
+ qdisc_reset(parent->un.leaf.q);
+ qdisc_tree_decrease_qlen(parent->un.leaf.q, qlen);
qdisc_destroy(parent->un.leaf.q);
if (parent->prio_activity)
htb_deactivate(q, parent);
@@ -1562,6 +1577,7 @@ static void htb_walk(struct Qdisc *sch, struct qdisc_walker *arg)
static struct Qdisc_class_ops htb_class_ops = {
.graft = htb_graft,
.leaf = htb_leaf,
+ .qlen_notify = htb_qlen_notify,
.get = htb_get,
.put = htb_put,
.change = htb_change_class,
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 0441876aa1e7..79542af9dab1 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -287,13 +287,10 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch)
psched_tdiff_t delay = PSCHED_TDIFF(cb->time_to_send, now);
if (q->qdisc->ops->requeue(skb, q->qdisc) != NET_XMIT_SUCCESS) {
+ qdisc_tree_decrease_qlen(q->qdisc, 1);
sch->qstats.drops++;
-
- /* After this qlen is confused */
printk(KERN_ERR "netem: queue discpline %s could not requeue\n",
q->qdisc->ops->id);
-
- sch->q.qlen--;
}
mod_timer(&q->timer, jiffies + PSCHED_US2JIFFIE(delay));
@@ -574,7 +571,8 @@ static int netem_init(struct Qdisc *sch, struct rtattr *opt)
q->timer.function = netem_watchdog;
q->timer.data = (unsigned long) sch;
- q->qdisc = qdisc_create_dflt(sch->dev, &tfifo_qdisc_ops);
+ q->qdisc = qdisc_create_dflt(sch->dev, &tfifo_qdisc_ops,
+ TC_H_MAKE(sch->handle, 1));
if (!q->qdisc) {
pr_debug("netem: qdisc create failed\n");
return -ENOMEM;
@@ -661,8 +659,8 @@ static int netem_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
sch_tree_lock(sch);
*old = xchg(&q->qdisc, new);
+ qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
qdisc_reset(*old);
- sch->q.qlen = 0;
sch_tree_unlock(sch);
return 0;
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c
index a5fa03c0c19b..2567b4c96c1e 100644
--- a/net/sched/sch_prio.c
+++ b/net/sched/sch_prio.c
@@ -222,21 +222,27 @@ static int prio_tune(struct Qdisc *sch, struct rtattr *opt)
for (i=q->bands; i<TCQ_PRIO_BANDS; i++) {
struct Qdisc *child = xchg(&q->queues[i], &noop_qdisc);
- if (child != &noop_qdisc)
+ if (child != &noop_qdisc) {
+ qdisc_tree_decrease_qlen(child, child->q.qlen);
qdisc_destroy(child);
+ }
}
sch_tree_unlock(sch);
for (i=0; i<q->bands; i++) {
if (q->queues[i] == &noop_qdisc) {
struct Qdisc *child;
- child = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
+ child = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops,
+ TC_H_MAKE(sch->handle, i + 1));
if (child) {
sch_tree_lock(sch);
child = xchg(&q->queues[i], child);
- if (child != &noop_qdisc)
+ if (child != &noop_qdisc) {
+ qdisc_tree_decrease_qlen(child,
+ child->q.qlen);
qdisc_destroy(child);
+ }
sch_tree_unlock(sch);
}
}
@@ -294,7 +300,7 @@ static int prio_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
sch_tree_lock(sch);
*old = q->queues[band];
q->queues[band] = new;
- sch->q.qlen -= (*old)->q.qlen;
+ qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
qdisc_reset(*old);
sch_tree_unlock(sch);
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c
index d65cadddea69..acddad08850f 100644
--- a/net/sched/sch_red.c
+++ b/net/sched/sch_red.c
@@ -175,12 +175,14 @@ static void red_destroy(struct Qdisc *sch)
qdisc_destroy(q->qdisc);
}
-static struct Qdisc *red_create_dflt(struct net_device *dev, u32 limit)
+static struct Qdisc *red_create_dflt(struct Qdisc *sch, u32 limit)
{
- struct Qdisc *q = qdisc_create_dflt(dev, &bfifo_qdisc_ops);
+ struct Qdisc *q;
struct rtattr *rta;
int ret;
+ q = qdisc_create_dflt(sch->dev, &bfifo_qdisc_ops,
+ TC_H_MAKE(sch->handle, 1));
if (q) {
rta = kmalloc(RTA_LENGTH(sizeof(struct tc_fifo_qopt)),
GFP_KERNEL);
@@ -219,7 +221,7 @@ static int red_change(struct Qdisc *sch, struct rtattr *opt)
ctl = RTA_DATA(tb[TCA_RED_PARMS-1]);
if (ctl->limit > 0) {
- child = red_create_dflt(sch->dev, ctl->limit);
+ child = red_create_dflt(sch, ctl->limit);
if (child == NULL)
return -ENOMEM;
}
@@ -227,8 +229,10 @@ static int red_change(struct Qdisc *sch, struct rtattr *opt)
sch_tree_lock(sch);
q->flags = ctl->flags;
q->limit = ctl->limit;
- if (child)
+ if (child) {
+ qdisc_tree_decrease_qlen(q->qdisc, q->qdisc->q.qlen);
qdisc_destroy(xchg(&q->qdisc, child));
+ }
red_set_parms(&q->parms, ctl->qth_min, ctl->qth_max, ctl->Wlog,
ctl->Plog, ctl->Scell_log,
@@ -306,8 +310,8 @@ static int red_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
sch_tree_lock(sch);
*old = xchg(&q->qdisc, new);
+ qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
qdisc_reset(*old);
- sch->q.qlen = 0;
sch_tree_unlock(sch);
return 0;
}
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index d0d6e595a78c..459cda258a5c 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -393,6 +393,7 @@ static int sfq_change(struct Qdisc *sch, struct rtattr *opt)
{
struct sfq_sched_data *q = qdisc_priv(sch);
struct tc_sfq_qopt *ctl = RTA_DATA(opt);
+ unsigned int qlen;
if (opt->rta_len < RTA_LENGTH(sizeof(*ctl)))
return -EINVAL;
@@ -403,8 +404,10 @@ static int sfq_change(struct Qdisc *sch, struct rtattr *opt)
if (ctl->limit)
q->limit = min_t(u32, ctl->limit, SFQ_DEPTH);
+ qlen = sch->q.qlen;
while (sch->q.qlen >= q->limit-1)
sfq_drop(sch);
+ qdisc_tree_decrease_qlen(sch, qlen - sch->q.qlen);
del_timer(&q->perturb_timer);
if (q->perturb_period) {
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index d9a5d298d755..ed9b6d938540 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -250,7 +250,7 @@ static struct sk_buff *tbf_dequeue(struct Qdisc* sch)
if (q->qdisc->ops->requeue(skb, q->qdisc) != NET_XMIT_SUCCESS) {
/* When requeue fails skb is dropped */
- sch->q.qlen--;
+ qdisc_tree_decrease_qlen(q->qdisc, 1);
sch->qstats.drops++;
}
@@ -273,12 +273,14 @@ static void tbf_reset(struct Qdisc* sch)
del_timer(&q->wd_timer);
}
-static struct Qdisc *tbf_create_dflt_qdisc(struct net_device *dev, u32 limit)
+static struct Qdisc *tbf_create_dflt_qdisc(struct Qdisc *sch, u32 limit)
{
- struct Qdisc *q = qdisc_create_dflt(dev, &bfifo_qdisc_ops);
+ struct Qdisc *q;
struct rtattr *rta;
int ret;
+ q = qdisc_create_dflt(sch->dev, &bfifo_qdisc_ops,
+ TC_H_MAKE(sch->handle, 1));
if (q) {
rta = kmalloc(RTA_LENGTH(sizeof(struct tc_fifo_qopt)), GFP_KERNEL);
if (rta) {
@@ -341,13 +343,15 @@ static int tbf_change(struct Qdisc* sch, struct rtattr *opt)
goto done;
if (qopt->limit > 0) {
- if ((child = tbf_create_dflt_qdisc(sch->dev, qopt->limit)) == NULL)
+ if ((child = tbf_create_dflt_qdisc(sch, qopt->limit)) == NULL)
goto done;
}
sch_tree_lock(sch);
- if (child)
+ if (child) {
+ qdisc_tree_decrease_qlen(q->qdisc, q->qdisc->q.qlen);
qdisc_destroy(xchg(&q->qdisc, child));
+ }
q->limit = qopt->limit;
q->mtu = qopt->mtu;
q->max_size = max_size;
@@ -449,8 +453,8 @@ static int tbf_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
sch_tree_lock(sch);
*old = xchg(&q->qdisc, new);
+ qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
qdisc_reset(*old);
- sch->q.qlen = 0;
sch_tree_unlock(sch);
return 0;
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 88124696ba60..ad0057db0f91 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -486,7 +486,7 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc,
" port: %d\n",
asoc,
(&peer->ipaddr),
- peer->ipaddr.v4.sin_port);
+ ntohs(peer->ipaddr.v4.sin_port));
/* If we are to remove the current retran_path, update it
* to the next peer before removing this peer from the list.
@@ -535,13 +535,13 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
sp = sctp_sk(asoc->base.sk);
/* AF_INET and AF_INET6 share common port field. */
- port = addr->v4.sin_port;
+ port = ntohs(addr->v4.sin_port);
SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_add_peer:association %p addr: ",
" port: %d state:%d\n",
asoc,
addr,
- addr->v4.sin_port,
+ port,
peer_state);
/* Set the port if it has not been set yet. */
@@ -707,6 +707,7 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
struct sctp_transport *first;
struct sctp_transport *second;
struct sctp_ulpevent *event;
+ struct sockaddr_storage addr;
struct list_head *pos;
int spc_state = 0;
@@ -729,8 +730,9 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
/* Generate and send a SCTP_PEER_ADDR_CHANGE notification to the
* user.
*/
- event = sctp_ulpevent_make_peer_addr_change(asoc,
- (struct sockaddr_storage *) &transport->ipaddr,
+ memset(&addr, 0, sizeof(struct sockaddr_storage));
+ memcpy(&addr, &transport->ipaddr, transport->af_specific->sockaddr_len);
+ event = sctp_ulpevent_make_peer_addr_change(asoc, &addr,
0, spc_state, error, GFP_ATOMIC);
if (event)
sctp_ulpq_tail_event(&asoc->ulpq, event);
@@ -866,7 +868,7 @@ struct sctp_transport *sctp_assoc_lookup_tsn(struct sctp_association *asoc,
struct list_head *entry, *pos;
struct sctp_transport *transport;
struct sctp_chunk *chunk;
- __u32 key = htonl(tsn);
+ __be32 key = htonl(tsn);
match = NULL;
@@ -924,8 +926,8 @@ struct sctp_transport *sctp_assoc_is_match(struct sctp_association *asoc,
sctp_read_lock(&asoc->base.addr_lock);
- if ((asoc->base.bind_addr.port == laddr->v4.sin_port) &&
- (asoc->peer.port == paddr->v4.sin_port)) {
+ if ((htons(asoc->base.bind_addr.port) == laddr->v4.sin_port) &&
+ (htons(asoc->peer.port) == paddr->v4.sin_port)) {
transport = sctp_assoc_lookup_paddr(asoc, paddr);
if (!transport)
goto out;
@@ -1136,7 +1138,7 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc)
" port: %d\n",
asoc,
(&t->ipaddr),
- t->ipaddr.v4.sin_port);
+ ntohs(t->ipaddr.v4.sin_port));
}
/* Choose the transport for sending a INIT packet. */
@@ -1161,7 +1163,7 @@ struct sctp_transport *sctp_assoc_choose_init_transport(
" port: %d\n",
asoc,
(&t->ipaddr),
- t->ipaddr.v4.sin_port);
+ ntohs(t->ipaddr.v4.sin_port));
return t;
}
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
index 2b9c12a170e5..00994158e496 100644
--- a/net/sctp/bind_addr.c
+++ b/net/sctp/bind_addr.c
@@ -161,7 +161,7 @@ int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new,
* Both v4 and v6 have the port at the same offset.
*/
if (!addr->a.v4.sin_port)
- addr->a.v4.sin_port = bp->port;
+ addr->a.v4.sin_port = htons(bp->port);
addr->use_as_src = use_as_src;
@@ -275,7 +275,7 @@ int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw_addr_list,
break;
}
- af->from_addr_param(&addr, rawaddr, port, 0);
+ af->from_addr_param(&addr, rawaddr, htons(port), 0);
retval = sctp_add_bind_addr(bp, &addr, 1, gfp);
if (retval) {
/* Can't finish building the list, clean up. */
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index a2b553721514..129756908da4 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -72,6 +72,10 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
{
memset(ep, 0, sizeof(struct sctp_endpoint));
+ ep->digest = kzalloc(SCTP_SIGNATURE_SIZE, gfp);
+ if (!ep->digest)
+ return NULL;
+
/* Initialize the base structure. */
/* What type of endpoint are we? */
ep->base.type = SCTP_EP_TYPE_SOCKET;
@@ -181,6 +185,9 @@ static void sctp_endpoint_destroy(struct sctp_endpoint *ep)
/* Free up the HMAC transform. */
crypto_free_hash(sctp_sk(ep->base.sk)->hmac);
+ /* Free the digest buffer */
+ kfree(ep->digest);
+
/* Cleanup. */
sctp_inq_free(&ep->base.inqueue);
sctp_bind_addr_free(&ep->base.bind_addr);
@@ -222,7 +229,7 @@ struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *ep,
struct sctp_endpoint *retval;
sctp_read_lock(&ep->base.addr_lock);
- if (ep->base.bind_addr.port == laddr->v4.sin_port) {
+ if (htons(ep->base.bind_addr.port) == laddr->v4.sin_port) {
if (sctp_bind_addr_match(&ep->base.bind_addr, laddr,
sctp_sk(ep->base.sk))) {
retval = ep;
@@ -250,7 +257,7 @@ static struct sctp_association *__sctp_endpoint_lookup_assoc(
struct sctp_association *asoc;
struct list_head *pos;
- rport = paddr->v4.sin_port;
+ rport = ntohs(paddr->v4.sin_port);
list_for_each(pos, &ep->asocs) {
asoc = list_entry(pos, struct sctp_association, asocs);
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 6d82f400d13c..33111873a488 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -726,7 +726,7 @@ static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *l
struct sctp_endpoint *ep;
int hash;
- hash = sctp_ep_hashfn(laddr->v4.sin_port);
+ hash = sctp_ep_hashfn(ntohs(laddr->v4.sin_port));
head = &sctp_ep_hashtable[hash];
read_lock(&head->lock);
for (epb = head->chain; epb; epb = epb->next) {
@@ -830,7 +830,7 @@ static struct sctp_association *__sctp_lookup_association(
/* Optimize here for direct hit, only listening connections can
* have wildcards anyways.
*/
- hash = sctp_assoc_hashfn(local->v4.sin_port, peer->v4.sin_port);
+ hash = sctp_assoc_hashfn(ntohs(local->v4.sin_port), ntohs(peer->v4.sin_port));
head = &sctp_assoc_hashtable[hash];
read_lock(&head->lock);
for (epb = head->chain; epb; epb = epb->next) {
@@ -957,7 +957,7 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,
if (!af)
continue;
- af->from_addr_param(paddr, params.addr, ntohs(sh->source), 0);
+ af->from_addr_param(paddr, params.addr, sh->source, 0);
asoc = __sctp_lookup_association(laddr, paddr, &transport);
if (asoc)
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index 78071c6e6cf1..3c3e560087ca 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -84,7 +84,7 @@ static struct notifier_block sctp_inet6addr_notifier = {
/* ICMP error handler. */
SCTP_STATIC void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
- int type, int code, int offset, __u32 info)
+ int type, int code, int offset, __be32 info)
{
struct inet6_dev *idev;
struct ipv6hdr *iph = (struct ipv6hdr *)skb->data;
@@ -170,8 +170,6 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport,
fl.oif = transport->saddr.v6.sin6_scope_id;
else
fl.oif = sk->sk_bound_dev_if;
- fl.fl_ip_sport = inet_sk(sk)->sport;
- fl.fl_ip_dport = transport->ipaddr.v6.sin6_port;
if (np->opt && np->opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
@@ -239,7 +237,7 @@ static inline int sctp_v6_addr_match_len(union sctp_addr *s1,
int i, j;
for (i = 0; i < 4 ; i++) {
- __u32 a1xora2;
+ __be32 a1xora2;
a1xora2 = a1->s6_addr32[i] ^ a2->s6_addr32[i];
@@ -350,7 +348,7 @@ static void sctp_v6_from_skb(union sctp_addr *addr,struct sk_buff *skb,
int is_saddr)
{
void *from;
- __u16 *port;
+ __be16 *port;
struct sctphdr *sh;
port = &addr->v6.sin6_port;
@@ -360,10 +358,10 @@ static void sctp_v6_from_skb(union sctp_addr *addr,struct sk_buff *skb,
sh = (struct sctphdr *) skb->h.raw;
if (is_saddr) {
- *port = ntohs(sh->source);
+ *port = sh->source;
from = &skb->nh.ipv6h->saddr;
} else {
- *port = ntohs(sh->dest);
+ *port = sh->dest;
from = &skb->nh.ipv6h->daddr;
}
ipv6_addr_copy(&addr->v6.sin6_addr, from);
@@ -373,7 +371,7 @@ static void sctp_v6_from_skb(union sctp_addr *addr,struct sk_buff *skb,
static void sctp_v6_from_sk(union sctp_addr *addr, struct sock *sk)
{
addr->v6.sin6_family = AF_INET6;
- addr->v6.sin6_port = inet_sk(sk)->num;
+ addr->v6.sin6_port = 0;
addr->v6.sin6_addr = inet6_sk(sk)->rcv_saddr;
}
@@ -407,7 +405,7 @@ static void sctp_v6_to_sk_daddr(union sctp_addr *addr, struct sock *sk)
/* Initialize a sctp_addr from an address parameter. */
static void sctp_v6_from_addr_param(union sctp_addr *addr,
union sctp_addr_param *param,
- __u16 port, int iif)
+ __be16 port, int iif)
{
addr->v6.sin6_family = AF_INET6;
addr->v6.sin6_port = port;
@@ -425,7 +423,7 @@ static int sctp_v6_to_addr_param(const union sctp_addr *addr,
int length = sizeof(sctp_ipv6addr_param_t);
param->v6.param_hdr.type = SCTP_PARAM_IPV6_ADDRESS;
- param->v6.param_hdr.length = ntohs(length);
+ param->v6.param_hdr.length = htons(length);
ipv6_addr_copy(&param->v6.addr, &addr->v6.sin6_addr);
return length;
@@ -433,7 +431,7 @@ static int sctp_v6_to_addr_param(const union sctp_addr *addr,
/* Initialize a sctp_addr from a dst_entry. */
static void sctp_v6_dst_saddr(union sctp_addr *addr, struct dst_entry *dst,
- unsigned short port)
+ __be16 port)
{
struct rt6_info *rt = (struct rt6_info *)dst;
addr->sa.sa_family = AF_INET6;
@@ -480,7 +478,7 @@ static int sctp_v6_cmp_addr(const union sctp_addr *addr1,
}
/* Initialize addr struct to INADDR_ANY. */
-static void sctp_v6_inaddr_any(union sctp_addr *addr, unsigned short port)
+static void sctp_v6_inaddr_any(union sctp_addr *addr, __be16 port)
{
memset(addr, 0x00, sizeof(union sctp_addr));
addr->v6.sin6_family = AF_INET6;
@@ -855,7 +853,7 @@ static int sctp_inet6_send_verify(struct sctp_sock *opt, union sctp_addr *addr)
* Returns number of addresses supported.
*/
static int sctp_inet6_supported_addrs(const struct sctp_sock *opt,
- __u16 *types)
+ __be16 *types)
{
types[0] = SCTP_PARAM_IPV4_ADDRESS;
types[1] = SCTP_PARAM_IPV6_ADDRESS;
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 739582415bf6..fba567a7cb64 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -1065,7 +1065,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
* A) Initialize the cacc_saw_newack to 0 for all destination
* addresses.
*/
- if (sack->num_gap_ack_blocks > 0 &&
+ if (sack->num_gap_ack_blocks &&
primary->cacc.changeover_active) {
list_for_each(pos, transport_list) {
transport = list_entry(pos, struct sctp_transport,
@@ -1632,7 +1632,7 @@ pass:
}
static inline int sctp_get_skip_pos(struct sctp_fwdtsn_skip *skiplist,
- int nskips, __u16 stream)
+ int nskips, __be16 stream)
{
int i;
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index 7f49e769080e..b3493bdbcacb 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -160,7 +160,7 @@ static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_commo
list_for_each(pos, &epb->bind_addr.address_list) {
laddr = list_entry(pos, struct sctp_sockaddr_entry, list);
- addr = (union sctp_addr *)&laddr->a;
+ addr = &laddr->a;
af = sctp_get_af_specific(addr->sa.sa_family);
if (primary && af->cmp_addr(addr, primary)) {
seq_printf(seq, "*");
@@ -177,10 +177,10 @@ static void sctp_seq_dump_remote_addrs(struct seq_file *seq, struct sctp_associa
union sctp_addr *addr, *primary;
struct sctp_af *af;
- primary = &(assoc->peer.primary_addr);
+ primary = &assoc->peer.primary_addr;
list_for_each(pos, &assoc->peer.transport_addr_list) {
transport = list_entry(pos, struct sctp_transport, transports);
- addr = (union sctp_addr *)&transport->ipaddr;
+ addr = &transport->ipaddr;
af = sctp_get_af_specific(addr->sa.sa_family);
if (af->cmp_addr(addr, primary)) {
seq_printf(seq, "*");
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 5b4f82fd98f8..11f3b549f4a4 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -251,7 +251,7 @@ static void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb,
int is_saddr)
{
void *from;
- __u16 *port;
+ __be16 *port;
struct sctphdr *sh;
port = &addr->v4.sin_port;
@@ -259,10 +259,10 @@ static void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb,
sh = (struct sctphdr *) skb->h.raw;
if (is_saddr) {
- *port = ntohs(sh->source);
+ *port = sh->source;
from = &skb->nh.iph->saddr;
} else {
- *port = ntohs(sh->dest);
+ *port = sh->dest;
from = &skb->nh.iph->daddr;
}
memcpy(&addr->v4.sin_addr.s_addr, from, sizeof(struct in_addr));
@@ -272,7 +272,7 @@ static void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb,
static void sctp_v4_from_sk(union sctp_addr *addr, struct sock *sk)
{
addr->v4.sin_family = AF_INET;
- addr->v4.sin_port = inet_sk(sk)->num;
+ addr->v4.sin_port = 0;
addr->v4.sin_addr.s_addr = inet_sk(sk)->rcv_saddr;
}
@@ -291,7 +291,7 @@ static void sctp_v4_to_sk_daddr(union sctp_addr *addr, struct sock *sk)
/* Initialize a sctp_addr from an address parameter. */
static void sctp_v4_from_addr_param(union sctp_addr *addr,
union sctp_addr_param *param,
- __u16 port, int iif)
+ __be16 port, int iif)
{
addr->v4.sin_family = AF_INET;
addr->v4.sin_port = port;
@@ -307,7 +307,7 @@ static int sctp_v4_to_addr_param(const union sctp_addr *addr,
int length = sizeof(sctp_ipv4addr_param_t);
param->v4.param_hdr.type = SCTP_PARAM_IPV4_ADDRESS;
- param->v4.param_hdr.length = ntohs(length);
+ param->v4.param_hdr.length = htons(length);
param->v4.addr.s_addr = addr->v4.sin_addr.s_addr;
return length;
@@ -315,7 +315,7 @@ static int sctp_v4_to_addr_param(const union sctp_addr *addr,
/* Initialize a sctp_addr from a dst_entry. */
static void sctp_v4_dst_saddr(union sctp_addr *saddr, struct dst_entry *dst,
- unsigned short port)
+ __be16 port)
{
struct rtable *rt = (struct rtable *)dst;
saddr->v4.sin_family = AF_INET;
@@ -338,7 +338,7 @@ static int sctp_v4_cmp_addr(const union sctp_addr *addr1,
}
/* Initialize addr struct to INADDR_ANY. */
-static void sctp_v4_inaddr_any(union sctp_addr *addr, unsigned short port)
+static void sctp_v4_inaddr_any(union sctp_addr *addr, __be16 port)
{
addr->v4.sin_family = AF_INET;
addr->v4.sin_addr.s_addr = INADDR_ANY;
@@ -481,7 +481,7 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc,
list);
if (!laddr->use_as_src)
continue;
- sctp_v4_dst_saddr(&dst_saddr, dst, bp->port);
+ sctp_v4_dst_saddr(&dst_saddr, dst, htons(bp->port));
if (sctp_v4_cmp_addr(&dst_saddr, &laddr->a))
goto out_unlock;
}
@@ -538,7 +538,7 @@ static void sctp_v4_get_saddr(struct sctp_association *asoc,
if (rt) {
saddr->v4.sin_family = AF_INET;
- saddr->v4.sin_port = asoc->base.bind_addr.port;
+ saddr->v4.sin_port = htons(asoc->base.bind_addr.port);
saddr->v4.sin_addr.s_addr = rt->rt_src;
}
}
@@ -791,7 +791,7 @@ static int sctp_inet_send_verify(struct sctp_sock *opt, union sctp_addr *addr)
* chunks. Returns number of addresses supported.
*/
static int sctp_inet_supported_addrs(const struct sctp_sock *opt,
- __u16 *types)
+ __be16 *types)
{
types[0] = SCTP_PARAM_IPV4_ADDRESS;
return 1;
@@ -808,7 +808,7 @@ static inline int sctp_v4_xmit(struct sk_buff *skb,
NIPQUAD(((struct rtable *)skb->dst)->rt_dst));
SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS);
- return ip_queue_xmit(skb, ipfragok);
+ return ip_queue_xmit(skb, skb->sk, ipfragok);
}
static struct sctp_af sctp_ipv4_specific;
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 507dff72c585..04954e5f6846 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -111,7 +111,7 @@ static const struct sctp_paramhdr prsctp_param = {
* provided chunk, as most cause codes will be embedded inside an
* abort chunk.
*/
-void sctp_init_cause(struct sctp_chunk *chunk, __u16 cause_code,
+void sctp_init_cause(struct sctp_chunk *chunk, __be16 cause_code,
const void *payload, size_t paylen)
{
sctp_errhdr_t err;
@@ -183,7 +183,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
int num_types, addrs_len = 0;
struct sctp_sock *sp;
sctp_supported_addrs_param_t sat;
- __u16 types[2];
+ __be16 types[2];
sctp_adaption_ind_param_t aiparam;
/* RFC 2960 3.3.2 Initiation (INIT) (1)
@@ -775,7 +775,7 @@ struct sctp_chunk *sctp_make_abort_no_data(
const struct sctp_chunk *chunk, __u32 tsn)
{
struct sctp_chunk *retval;
- __u32 payload;
+ __be32 payload;
retval = sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t)
+ sizeof(tsn));
@@ -951,7 +951,7 @@ nodata:
/* Create an Operation Error chunk. */
struct sctp_chunk *sctp_make_op_error(const struct sctp_association *asoc,
const struct sctp_chunk *chunk,
- __u16 cause_code, const void *payload,
+ __be16 cause_code, const void *payload,
size_t paylen)
{
struct sctp_chunk *retval;
@@ -1190,15 +1190,14 @@ void sctp_chunk_assign_ssn(struct sctp_chunk *chunk)
if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) {
ssn = 0;
} else {
- sid = htons(chunk->subh.data_hdr->stream);
+ sid = ntohs(chunk->subh.data_hdr->stream);
if (chunk->chunk_hdr->flags & SCTP_DATA_LAST_FRAG)
ssn = sctp_ssn_next(&chunk->asoc->ssnmap->out, sid);
else
ssn = sctp_ssn_peek(&chunk->asoc->ssnmap->out, sid);
- ssn = htons(ssn);
}
- chunk->subh.data_hdr->ssn = ssn;
+ chunk->subh.data_hdr->ssn = htons(ssn);
chunk->has_ssn = 1;
}
@@ -1280,15 +1279,13 @@ static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep,
- (bodysize % SCTP_COOKIE_MULTIPLE);
*cookie_len = headersize + bodysize;
- retval = kmalloc(*cookie_len, GFP_ATOMIC);
-
- if (!retval)
- goto nodata;
-
/* Clear this memory since we are sending this data structure
* out on the network.
*/
- memset(retval, 0x00, *cookie_len);
+ retval = kzalloc(*cookie_len, GFP_ATOMIC);
+ if (!retval)
+ goto nodata;
+
cookie = (struct sctp_signed_cookie *) retval->body;
/* Set up the parameter header. */
@@ -1438,7 +1435,7 @@ no_hmac:
goto fail;
}
- if (ntohs(chunk->sctp_hdr->source) != bear_cookie->peer_addr.v4.sin_port ||
+ if (chunk->sctp_hdr->source != bear_cookie->peer_addr.v4.sin_port ||
ntohs(chunk->sctp_hdr->dest) != bear_cookie->my_port) {
*error = -SCTP_IERROR_BAD_PORTS;
goto fail;
@@ -1473,10 +1470,10 @@ no_hmac:
suseconds_t usecs = (tv.tv_sec -
bear_cookie->expiration.tv_sec) * 1000000L +
tv.tv_usec - bear_cookie->expiration.tv_usec;
+ __be32 n = htonl(usecs);
- usecs = htonl(usecs);
sctp_init_cause(*errp, SCTP_ERROR_STALE_COOKIE,
- &usecs, sizeof(usecs));
+ &n, sizeof(n));
*error = -SCTP_IERROR_STALE_COOKIE;
} else
*error = -SCTP_IERROR_NOMEM;
@@ -1539,8 +1536,8 @@ malformed:
********************************************************************/
struct __sctp_missing {
- __u32 num_missing;
- __u16 type;
+ __be32 num_missing;
+ __be16 type;
} __attribute__((packed));
/*
@@ -1852,9 +1849,10 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid,
* added as the primary transport. The source address seems to
* be a a better choice than any of the embedded addresses.
*/
- if (peer_addr)
+ if (peer_addr) {
if(!sctp_assoc_add_peer(asoc, peer_addr, gfp, SCTP_ACTIVE))
goto nomem;
+ }
/* Process the initialization parameters. */
@@ -1910,10 +1908,9 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid,
/* Copy cookie in case we need to resend COOKIE-ECHO. */
cookie = asoc->peer.cookie;
if (cookie) {
- asoc->peer.cookie = kmalloc(asoc->peer.cookie_len, gfp);
+ asoc->peer.cookie = kmemdup(cookie, asoc->peer.cookie_len, gfp);
if (!asoc->peer.cookie)
goto clean_up;
- memcpy(asoc->peer.cookie, cookie, asoc->peer.cookie_len);
}
/* RFC 2960 7.2.1 The initial value of ssthresh MAY be arbitrarily
@@ -2027,7 +2024,7 @@ static int sctp_process_param(struct sctp_association *asoc,
/* Fall through. */
case SCTP_PARAM_IPV4_ADDRESS:
af = sctp_get_af_specific(param_type2af(param.p->type));
- af->from_addr_param(&addr, param.addr, asoc->peer.port, 0);
+ af->from_addr_param(&addr, param.addr, htons(asoc->peer.port), 0);
scope = sctp_scope(peer_addr);
if (sctp_in_scope(&addr, scope))
if (!sctp_assoc_add_peer(asoc, &addr, gfp, SCTP_UNCONFIRMED))
@@ -2230,7 +2227,7 @@ struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *asoc,
union sctp_addr *laddr,
struct sockaddr *addrs,
int addrcnt,
- __u16 flags)
+ __be16 flags)
{
sctp_addip_param_t param;
struct sctp_chunk *retval;
@@ -2363,14 +2360,14 @@ static struct sctp_chunk *sctp_make_asconf_ack(const struct sctp_association *as
}
/* Add response parameters to an ASCONF_ACK chunk. */
-static void sctp_add_asconf_response(struct sctp_chunk *chunk, __u32 crr_id,
- __u16 err_code, sctp_addip_param_t *asconf_param)
+static void sctp_add_asconf_response(struct sctp_chunk *chunk, __be32 crr_id,
+ __be16 err_code, sctp_addip_param_t *asconf_param)
{
sctp_addip_param_t ack_param;
sctp_errhdr_t err_param;
int asconf_param_len = 0;
int err_param_len = 0;
- __u16 response_type;
+ __be16 response_type;
if (SCTP_ERROR_NO_ERROR == err_code) {
response_type = SCTP_PARAM_SUCCESS_REPORT;
@@ -2404,7 +2401,7 @@ static void sctp_add_asconf_response(struct sctp_chunk *chunk, __u32 crr_id,
}
/* Process a asconf parameter. */
-static __u16 sctp_process_asconf_param(struct sctp_association *asoc,
+static __be16 sctp_process_asconf_param(struct sctp_association *asoc,
struct sctp_chunk *asconf,
sctp_addip_param_t *asconf_param)
{
@@ -2413,7 +2410,7 @@ static __u16 sctp_process_asconf_param(struct sctp_association *asoc,
union sctp_addr addr;
struct list_head *pos;
union sctp_addr_param *addr_param;
-
+
addr_param = (union sctp_addr_param *)
((void *)asconf_param + sizeof(sctp_addip_param_t));
@@ -2421,7 +2418,7 @@ static __u16 sctp_process_asconf_param(struct sctp_association *asoc,
if (unlikely(!af))
return SCTP_ERROR_INV_PARAM;
- af->from_addr_param(&addr, addr_param, asoc->peer.port, 0);
+ af->from_addr_param(&addr, addr_param, htons(asoc->peer.port), 0);
switch (asconf_param->param_hdr.type) {
case SCTP_PARAM_ADD_IP:
/* ADDIP 4.3 D9) If an endpoint receives an ADD IP address
@@ -2487,7 +2484,7 @@ struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
sctp_addip_param_t *asconf_param;
struct sctp_chunk *asconf_ack;
- __u16 err_code;
+ __be16 err_code;
int length = 0;
int chunk_len = asconf->skb->len;
__u32 serial;
@@ -2586,7 +2583,7 @@ static int sctp_asconf_param_success(struct sctp_association *asoc,
/* We have checked the packet before, so we do not check again. */
af = sctp_get_af_specific(param_type2af(addr_param->v4.param_hdr.type));
- af->from_addr_param(&addr, addr_param, bp->port, 0);
+ af->from_addr_param(&addr, addr_param, htons(bp->port), 0);
switch (asconf_param->param_hdr.type) {
case SCTP_PARAM_ADD_IP:
@@ -2630,7 +2627,7 @@ static int sctp_asconf_param_success(struct sctp_association *asoc,
* All TLVs after the failed response are considered unsuccessful unless a
* specific success indication is present for the parameter.
*/
-static __u16 sctp_get_asconf_response(struct sctp_chunk *asconf_ack,
+static __be16 sctp_get_asconf_response(struct sctp_chunk *asconf_ack,
sctp_addip_param_t *asconf_param,
int no_err)
{
@@ -2638,7 +2635,7 @@ static __u16 sctp_get_asconf_response(struct sctp_chunk *asconf_ack,
sctp_errhdr_t *err_param;
int length;
int asconf_ack_len = asconf_ack->skb->len;
- __u16 err_code;
+ __be16 err_code;
if (no_err)
err_code = SCTP_ERROR_NO_ERROR;
@@ -2694,7 +2691,7 @@ int sctp_process_asconf_ack(struct sctp_association *asoc,
int all_param_pass = 0;
int no_err = 1;
int retval = 0;
- __u16 err_code = SCTP_ERROR_NO_ERROR;
+ __be16 err_code = SCTP_ERROR_NO_ERROR;
/* Skip the chunkhdr and addiphdr from the last asconf sent and store
* a pointer to address parameter.
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 9c10bdec1afe..7bbc6156e455 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -442,7 +442,7 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc,
" transport IP: port:%d failed.\n",
asoc,
(&transport->ipaddr),
- transport->ipaddr.v4.sin_port);
+ ntohs(transport->ipaddr.v4.sin_port));
sctp_assoc_control_transport(asoc, transport,
SCTP_TRANSPORT_DOWN,
SCTP_FAILED_THRESHOLD);
@@ -1360,12 +1360,12 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
break;
case SCTP_CMD_INIT_FAILED:
- sctp_cmd_init_failed(commands, asoc, cmd->obj.u32);
+ sctp_cmd_init_failed(commands, asoc, cmd->obj.err);
break;
case SCTP_CMD_ASSOC_FAILED:
sctp_cmd_assoc_failed(commands, asoc, event_type,
- subtype, chunk, cmd->obj.u32);
+ subtype, chunk, cmd->obj.err);
break;
case SCTP_CMD_INIT_COUNTER_INC:
@@ -1420,7 +1420,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
case SCTP_CMD_PROCESS_CTSN:
/* Dummy up a SACK for processing. */
- sackh.cum_tsn_ack = cmd->obj.u32;
+ sackh.cum_tsn_ack = cmd->obj.be32;
sackh.a_rwnd = 0;
sackh.num_gap_ack_blocks = 0;
sackh.num_dup_tsns = 0;
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 1c42fe983a5b..27cc444aaf11 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -93,7 +93,7 @@ static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep,
static struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk);
static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,
- __u16 error, int sk_err,
+ __be16 error, int sk_err,
const struct sctp_association *asoc,
struct sctp_transport *transport);
@@ -443,7 +443,7 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
__u32 init_tag;
struct sctp_chunk *err_chunk;
struct sctp_packet *packet;
- __u16 error;
+ sctp_error_t error;
if (!sctp_vtag_verify(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
@@ -886,7 +886,7 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const struct sctp_endpoint *ep,
SCTP_ERROR(ETIMEDOUT));
/* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
- SCTP_U32(SCTP_ERROR_NO_ERROR));
+ SCTP_PERR(SCTP_ERROR_NO_ERROR));
SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
return SCTP_DISPOSITION_DELETE_TCB;
@@ -2138,7 +2138,7 @@ static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
SCTP_ERROR(ETIMEDOUT));
sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
- SCTP_U32(SCTP_ERROR_STALE_COOKIE));
+ SCTP_PERR(SCTP_ERROR_STALE_COOKIE));
return SCTP_DISPOSITION_DELETE_TCB;
}
@@ -2158,7 +2158,7 @@ static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep,
* to give ample time to retransmit the new cookie and thus
* yield a higher probability of success on the reattempt.
*/
- stale = ntohl(*(suseconds_t *)((u8 *)err + sizeof(sctp_errhdr_t)));
+ stale = ntohl(*(__be32 *)((u8 *)err + sizeof(sctp_errhdr_t)));
stale = (stale * 2) / 1000;
bht.param_hdr.type = SCTP_PARAM_COOKIE_PRESERVATIVE;
@@ -2250,7 +2250,7 @@ sctp_disposition_t sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep,
{
struct sctp_chunk *chunk = arg;
unsigned len;
- __u16 error = SCTP_ERROR_NO_ERROR;
+ __be16 error = SCTP_ERROR_NO_ERROR;
if (!sctp_vtag_verify_either(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
@@ -2275,7 +2275,7 @@ sctp_disposition_t sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNRESET));
/* ASSOC_FAILED will DELETE_TCB. */
- sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_U32(error));
+ sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_PERR(error));
SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
@@ -2295,7 +2295,7 @@ sctp_disposition_t sctp_sf_cookie_wait_abort(const struct sctp_endpoint *ep,
{
struct sctp_chunk *chunk = arg;
unsigned len;
- __u16 error = SCTP_ERROR_NO_ERROR;
+ __be16 error = SCTP_ERROR_NO_ERROR;
if (!sctp_vtag_verify_either(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
@@ -2357,7 +2357,7 @@ sctp_disposition_t sctp_sf_cookie_echoed_abort(const struct sctp_endpoint *ep,
* This is common code called by several sctp_sf_*_abort() functions above.
*/
static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,
- __u16 error, int sk_err,
+ __be16 error, int sk_err,
const struct sctp_association *asoc,
struct sctp_transport *transport)
{
@@ -2370,7 +2370,7 @@ static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,
sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(sk_err));
/* CMD_INIT_FAILED will DELETE_TCB. */
sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
- SCTP_U32(error));
+ SCTP_PERR(error));
return SCTP_DISPOSITION_ABORT;
}
@@ -2466,7 +2466,7 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const struct sctp_endpoint *ep,
* received by the SHUTDOWN sender.
*/
sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_CTSN,
- SCTP_U32(chunk->subh.shutdown_hdr->cum_tsn_ack));
+ SCTP_BE32(chunk->subh.shutdown_hdr->cum_tsn_ack));
out:
return disposition;
@@ -2545,6 +2545,7 @@ sctp_disposition_t sctp_sf_do_ecn_cwr(const struct sctp_endpoint *ep,
{
sctp_cwrhdr_t *cwr;
struct sctp_chunk *chunk = arg;
+ u32 lowest_tsn;
if (!sctp_vtag_verify(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
@@ -2556,14 +2557,14 @@ sctp_disposition_t sctp_sf_do_ecn_cwr(const struct sctp_endpoint *ep,
cwr = (sctp_cwrhdr_t *) chunk->skb->data;
skb_pull(chunk->skb, sizeof(sctp_cwrhdr_t));
- cwr->lowest_tsn = ntohl(cwr->lowest_tsn);
+ lowest_tsn = ntohl(cwr->lowest_tsn);
/* Does this CWR ack the last sent congestion notification? */
- if (TSN_lte(asoc->last_ecne_tsn, cwr->lowest_tsn)) {
+ if (TSN_lte(asoc->last_ecne_tsn, lowest_tsn)) {
/* Stop sending ECNE. */
sctp_add_cmd_sf(commands,
SCTP_CMD_ECN_CWR,
- SCTP_U32(cwr->lowest_tsn));
+ SCTP_U32(lowest_tsn));
}
return SCTP_DISPOSITION_CONSUME;
}
@@ -3360,7 +3361,7 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
SCTP_ERROR(ECONNABORTED));
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
- SCTP_U32(SCTP_ERROR_ASCONF_ACK));
+ SCTP_PERR(SCTP_ERROR_ASCONF_ACK));
SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
return SCTP_DISPOSITION_ABORT;
@@ -3388,7 +3389,7 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
SCTP_ERROR(ECONNABORTED));
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
- SCTP_U32(SCTP_ERROR_ASCONF_ACK));
+ SCTP_PERR(SCTP_ERROR_ASCONF_ACK));
SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
return SCTP_DISPOSITION_ABORT;
@@ -3743,12 +3744,12 @@ static sctp_disposition_t sctp_sf_violation_chunklen(
sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
SCTP_ERROR(ECONNREFUSED));
sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
- SCTP_U32(SCTP_ERROR_PROTO_VIOLATION));
+ SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION));
} else {
sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
SCTP_ERROR(ECONNABORTED));
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
- SCTP_U32(SCTP_ERROR_PROTO_VIOLATION));
+ SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION));
SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
}
@@ -4062,7 +4063,7 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort(
SCTP_ERROR(ECONNABORTED));
/* Delete the established association. */
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
- SCTP_U32(SCTP_ERROR_USER_ABORT));
+ SCTP_PERR(SCTP_ERROR_USER_ABORT));
SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
@@ -4199,7 +4200,7 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort(
SCTP_ERROR(ECONNREFUSED));
/* Delete the established association. */
sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
- SCTP_U32(SCTP_ERROR_USER_ABORT));
+ SCTP_PERR(SCTP_ERROR_USER_ABORT));
return retval;
}
@@ -4571,7 +4572,7 @@ sctp_disposition_t sctp_sf_do_6_3_3_rtx(const struct sctp_endpoint *ep,
SCTP_ERROR(ETIMEDOUT));
/* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
- SCTP_U32(SCTP_ERROR_NO_ERROR));
+ SCTP_PERR(SCTP_ERROR_NO_ERROR));
SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
return SCTP_DISPOSITION_DELETE_TCB;
@@ -4693,7 +4694,7 @@ sctp_disposition_t sctp_sf_t1_init_timer_expire(const struct sctp_endpoint *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
SCTP_ERROR(ETIMEDOUT));
sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
- SCTP_U32(SCTP_ERROR_NO_ERROR));
+ SCTP_PERR(SCTP_ERROR_NO_ERROR));
return SCTP_DISPOSITION_DELETE_TCB;
}
@@ -4745,7 +4746,7 @@ sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep
sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
SCTP_ERROR(ETIMEDOUT));
sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
- SCTP_U32(SCTP_ERROR_NO_ERROR));
+ SCTP_PERR(SCTP_ERROR_NO_ERROR));
return SCTP_DISPOSITION_DELETE_TCB;
}
@@ -4781,7 +4782,7 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const struct sctp_endpoint *ep,
SCTP_ERROR(ETIMEDOUT));
/* Note: CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
- SCTP_U32(SCTP_ERROR_NO_ERROR));
+ SCTP_PERR(SCTP_ERROR_NO_ERROR));
SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
return SCTP_DISPOSITION_DELETE_TCB;
@@ -4859,7 +4860,7 @@ sctp_disposition_t sctp_sf_t4_timer_expire(
sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
SCTP_ERROR(ETIMEDOUT));
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
- SCTP_U32(SCTP_ERROR_NO_ERROR));
+ SCTP_PERR(SCTP_ERROR_NO_ERROR));
SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
SCTP_INC_STATS(SCTP_MIB_CURRESTAB);
return SCTP_DISPOSITION_ABORT;
@@ -4915,7 +4916,7 @@ sctp_disposition_t sctp_sf_t5_timer_expire(const struct sctp_endpoint *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
SCTP_ERROR(ETIMEDOUT));
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
- SCTP_U32(SCTP_ERROR_NO_ERROR));
+ SCTP_PERR(SCTP_ERROR_NO_ERROR));
return SCTP_DISPOSITION_DELETE_TCB;
nomem:
@@ -5365,7 +5366,7 @@ static int sctp_eat_data(const struct sctp_association *asoc,
sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
SCTP_ERROR(ECONNABORTED));
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
- SCTP_U32(SCTP_ERROR_NO_DATA));
+ SCTP_PERR(SCTP_ERROR_NO_DATA));
SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
return SCTP_IERROR_NO_DATA;
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c
index 8bcca5676151..733dd87b3a7d 100644
--- a/net/sctp/sm_statetable.c
+++ b/net/sctp/sm_statetable.c
@@ -104,325 +104,322 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
};
}
+#define TYPE_SCTP_FUNC(func) {.fn = func, .name = #func}
+
#define TYPE_SCTP_DATA { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
+ TYPE_SCTP_FUNC(sctp_sf_ootb), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_tabort_8_4_8, .name = "sctp_sf_tabort_8_4_8"}, \
+ TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_eat_data_6_2, .name = "sctp_sf_eat_data_6_2"}, \
+ TYPE_SCTP_FUNC(sctp_sf_eat_data_6_2), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_eat_data_6_2, .name = "sctp_sf_eat_data_6_2"}, \
+ TYPE_SCTP_FUNC(sctp_sf_eat_data_6_2), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_eat_data_fast_4_4, .name = "sctp_sf_eat_data_fast_4_4"}, \
+ TYPE_SCTP_FUNC(sctp_sf_eat_data_fast_4_4), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
} /* TYPE_SCTP_DATA */
#define TYPE_SCTP_INIT { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ TYPE_SCTP_FUNC(sctp_sf_bug), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_do_5_1B_init, .name = "sctp_sf_do_5_1B_init"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_5_1B_init), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_do_5_2_1_siminit, .name = "sctp_sf_do_5_2_1_siminit"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_5_2_1_siminit), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_do_5_2_1_siminit, .name = "sctp_sf_do_5_2_1_siminit"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_5_2_1_siminit), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_do_5_2_2_dupinit, .name = "sctp_sf_do_5_2_2_dupinit"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_5_2_2_dupinit), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_do_5_2_2_dupinit, .name = "sctp_sf_do_5_2_2_dupinit"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_5_2_2_dupinit), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_do_5_2_2_dupinit, .name = "sctp_sf_do_5_2_2_dupinit"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_5_2_2_dupinit), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_do_5_2_2_dupinit, .name = "sctp_sf_do_5_2_2_dupinit"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_5_2_2_dupinit), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_do_9_2_reshutack, .name = "sctp_sf_do_9_2_reshutack"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_9_2_reshutack), \
} /* TYPE_SCTP_INIT */
#define TYPE_SCTP_INIT_ACK { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
+ TYPE_SCTP_FUNC(sctp_sf_ootb), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_do_5_1C_ack, .name = "sctp_sf_do_5_1C_ack"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_5_1C_ack), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
} /* TYPE_SCTP_INIT_ACK */
#define TYPE_SCTP_SACK { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
+ TYPE_SCTP_FUNC(sctp_sf_ootb), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_tabort_8_4_8, .name = "sctp_sf_tabort_8_4_8"}, \
+ TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_eat_sack_6_2, .name = "sctp_sf_eat_sack_6_2"}, \
+ TYPE_SCTP_FUNC(sctp_sf_eat_sack_6_2), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_eat_sack_6_2, .name = "sctp_sf_eat_sack_6_2"}, \
+ TYPE_SCTP_FUNC(sctp_sf_eat_sack_6_2), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_eat_sack_6_2, .name = "sctp_sf_eat_sack_6_2"}, \
+ TYPE_SCTP_FUNC(sctp_sf_eat_sack_6_2), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_eat_sack_6_2, .name = "sctp_sf_eat_sack_6_2"}, \
+ TYPE_SCTP_FUNC(sctp_sf_eat_sack_6_2), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
} /* TYPE_SCTP_SACK */
#define TYPE_SCTP_HEARTBEAT { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
+ TYPE_SCTP_FUNC(sctp_sf_ootb), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_tabort_8_4_8, .name = "sctp_sf_tabort_8_4_8"}, \
+ TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_beat_8_3, .name = "sctp_sf_beat_8_3"}, \
+ TYPE_SCTP_FUNC(sctp_sf_beat_8_3), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_beat_8_3, .name = "sctp_sf_beat_8_3"}, \
+ TYPE_SCTP_FUNC(sctp_sf_beat_8_3), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_beat_8_3, .name = "sctp_sf_beat_8_3"}, \
+ TYPE_SCTP_FUNC(sctp_sf_beat_8_3), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_beat_8_3, .name = "sctp_sf_beat_8_3"}, \
+ TYPE_SCTP_FUNC(sctp_sf_beat_8_3), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_beat_8_3, .name = "sctp_sf_beat_8_3"}, \
+ TYPE_SCTP_FUNC(sctp_sf_beat_8_3), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
/* This should not happen, but we are nice. */ \
- {.fn = sctp_sf_beat_8_3, .name = "sctp_sf_beat_8_3"}, \
+ TYPE_SCTP_FUNC(sctp_sf_beat_8_3), \
} /* TYPE_SCTP_HEARTBEAT */
#define TYPE_SCTP_HEARTBEAT_ACK { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
+ TYPE_SCTP_FUNC(sctp_sf_ootb), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_tabort_8_4_8, .name = "sctp_sf_tabort_8_4_8"}, \
+ TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_violation, .name = "sctp_sf_violation"}, \
+ TYPE_SCTP_FUNC(sctp_sf_violation), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_backbeat_8_3, .name = "sctp_sf_backbeat_8_3"}, \
+ TYPE_SCTP_FUNC(sctp_sf_backbeat_8_3), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_backbeat_8_3, .name = "sctp_sf_backbeat_8_3"}, \
+ TYPE_SCTP_FUNC(sctp_sf_backbeat_8_3), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_backbeat_8_3, .name = "sctp_sf_backbeat_8_3"}, \
+ TYPE_SCTP_FUNC(sctp_sf_backbeat_8_3), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_backbeat_8_3, .name = "sctp_sf_backbeat_8_3"}, \
+ TYPE_SCTP_FUNC(sctp_sf_backbeat_8_3), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
} /* TYPE_SCTP_HEARTBEAT_ACK */
#define TYPE_SCTP_ABORT { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
+ TYPE_SCTP_FUNC(sctp_sf_ootb), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_pdiscard, .name = "sctp_sf_pdiscard"}, \
+ TYPE_SCTP_FUNC(sctp_sf_pdiscard), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_cookie_wait_abort, .name = "sctp_sf_cookie_wait_abort"}, \
+ TYPE_SCTP_FUNC(sctp_sf_cookie_wait_abort), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_cookie_echoed_abort, \
- .name = "sctp_sf_cookie_echoed_abort"}, \
+ TYPE_SCTP_FUNC(sctp_sf_cookie_echoed_abort), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_do_9_1_abort, .name = "sctp_sf_do_9_1_abort"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_9_1_abort), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_shutdown_pending_abort, \
- .name = "sctp_sf_shutdown_pending_abort"}, \
+ TYPE_SCTP_FUNC(sctp_sf_shutdown_pending_abort), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_shutdown_sent_abort, \
- .name = "sctp_sf_shutdown_sent_abort"}, \
+ TYPE_SCTP_FUNC(sctp_sf_shutdown_sent_abort), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_do_9_1_abort, .name = "sctp_sf_do_9_1_abort"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_9_1_abort), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_shutdown_ack_sent_abort, \
- .name = "sctp_sf_shutdown_ack_sent_abort"}, \
+ TYPE_SCTP_FUNC(sctp_sf_shutdown_ack_sent_abort), \
} /* TYPE_SCTP_ABORT */
#define TYPE_SCTP_SHUTDOWN { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
+ TYPE_SCTP_FUNC(sctp_sf_ootb), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_tabort_8_4_8, .name = "sctp_sf_tabort_8_4_8"}, \
+ TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_do_9_2_shutdown, .name = "sctp_sf_do_9_2_shutdown"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_9_2_shutdown), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_do_9_2_shutdown_ack, \
- .name = "sctp_sf_do_9_2_shutdown_ack"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_9_2_shutdown_ack), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
} /* TYPE_SCTP_SHUTDOWN */
#define TYPE_SCTP_SHUTDOWN_ACK { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
+ TYPE_SCTP_FUNC(sctp_sf_ootb), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
+ TYPE_SCTP_FUNC(sctp_sf_ootb), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_do_8_5_1_E_sa, .name = "sctp_sf_do_8_5_1_E_sa"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_8_5_1_E_sa), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_do_8_5_1_E_sa, .name = "sctp_sf_do_8_5_1_E_sa"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_8_5_1_E_sa), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_violation, .name = "sctp_sf_violation"}, \
+ TYPE_SCTP_FUNC(sctp_sf_violation), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_violation, .name = "sctp_sf_violation"}, \
+ TYPE_SCTP_FUNC(sctp_sf_violation), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_do_9_2_final, .name = "sctp_sf_do_9_2_final"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_9_2_final), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_violation, .name = "sctp_sf_violation"}, \
+ TYPE_SCTP_FUNC(sctp_sf_violation), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_do_9_2_final, .name = "sctp_sf_do_9_2_final"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_9_2_final), \
} /* TYPE_SCTP_SHUTDOWN_ACK */
#define TYPE_SCTP_ERROR { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
+ TYPE_SCTP_FUNC(sctp_sf_ootb), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_tabort_8_4_8, .name = "sctp_sf_tabort_8_4_8"}, \
+ TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_cookie_echoed_err, .name = "sctp_sf_cookie_echoed_err"}, \
+ TYPE_SCTP_FUNC(sctp_sf_cookie_echoed_err), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_operr_notify, .name = "sctp_sf_operr_notify"}, \
+ TYPE_SCTP_FUNC(sctp_sf_operr_notify), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_operr_notify, .name = "sctp_sf_operr_notify"}, \
+ TYPE_SCTP_FUNC(sctp_sf_operr_notify), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_operr_notify, .name = "sctp_sf_operr_notify"}, \
+ TYPE_SCTP_FUNC(sctp_sf_operr_notify), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
} /* TYPE_SCTP_ERROR */
#define TYPE_SCTP_COOKIE_ECHO { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ TYPE_SCTP_FUNC(sctp_sf_bug), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_do_5_1D_ce, .name = "sctp_sf_do_5_1D_ce"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_5_1D_ce), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_do_5_2_4_dupcook, .name = "sctp_sf_do_5_2_4_dupcook"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_5_2_4_dupcook), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_do_5_2_4_dupcook, .name = "sctp_sf_do_5_2_4_dupcook"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_5_2_4_dupcook), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_do_5_2_4_dupcook, .name = "sctp_sf_do_5_2_4_dupcook"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_5_2_4_dupcook), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_do_5_2_4_dupcook, .name = "sctp_sf_do_5_2_4_dupcook"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_5_2_4_dupcook), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_do_5_2_4_dupcook, .name = "sctp_sf_do_5_2_4_dupcook"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_5_2_4_dupcook), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_do_5_2_4_dupcook, .name = "sctp_sf_do_5_2_4_dupcook"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_5_2_4_dupcook), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_do_5_2_4_dupcook, .name = "sctp_sf_do_5_2_4_dupcook"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_5_2_4_dupcook), \
} /* TYPE_SCTP_COOKIE_ECHO */
#define TYPE_SCTP_COOKIE_ACK { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
+ TYPE_SCTP_FUNC(sctp_sf_ootb), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_do_5_1E_ca, .name = "sctp_sf_do_5_1E_ca"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_5_1E_ca), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
} /* TYPE_SCTP_COOKIE_ACK */
#define TYPE_SCTP_ECN_ECNE { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
+ TYPE_SCTP_FUNC(sctp_sf_ootb), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_do_ecne, .name = "sctp_sf_do_ecne"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_ecne), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_do_ecne, .name = "sctp_sf_do_ecne"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_ecne), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_do_ecne, .name = "sctp_sf_do_ecne"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_ecne), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_do_ecne, .name = "sctp_sf_do_ecne"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_ecne), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_do_ecne, .name = "sctp_sf_do_ecne"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_ecne), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
} /* TYPE_SCTP_ECN_ECNE */
#define TYPE_SCTP_ECN_CWR { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
+ TYPE_SCTP_FUNC(sctp_sf_ootb), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_do_ecn_cwr, .name = "sctp_sf_do_ecn_cwr"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_ecn_cwr), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_do_ecn_cwr, .name = "sctp_sf_do_ecn_cwr"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_ecn_cwr), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_do_ecn_cwr, .name = "sctp_sf_do_ecn_cwr"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_ecn_cwr), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
} /* TYPE_SCTP_ECN_CWR */
#define TYPE_SCTP_SHUTDOWN_COMPLETE { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
+ TYPE_SCTP_FUNC(sctp_sf_ootb), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_do_4_C, .name = "sctp_sf_do_4_C"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_4_C), \
} /* TYPE_SCTP_SHUTDOWN_COMPLETE */
/* The primary index for this table is the chunk type.
@@ -450,44 +447,44 @@ static const sctp_sm_table_entry_t chunk_event_table[SCTP_NUM_BASE_CHUNK_TYPES][
#define TYPE_SCTP_ASCONF { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
+ TYPE_SCTP_FUNC(sctp_sf_ootb), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_do_asconf, .name = "sctp_sf_do_asconf"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_asconf), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
} /* TYPE_SCTP_ASCONF */
#define TYPE_SCTP_ASCONF_ACK { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
+ TYPE_SCTP_FUNC(sctp_sf_ootb), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_do_asconf_ack, .name = "sctp_sf_do_asconf_ack"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_asconf_ack), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
} /* TYPE_SCTP_ASCONF_ACK */
/* The primary index for this table is the chunk type.
@@ -500,23 +497,23 @@ static const sctp_sm_table_entry_t addip_chunk_event_table[SCTP_NUM_ADDIP_CHUNK_
#define TYPE_SCTP_FWD_TSN { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
+ TYPE_SCTP_FUNC(sctp_sf_ootb), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_tabort_8_4_8, .name = "sctp_sf_tabort_8_4_8"}, \
+ TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_eat_fwd_tsn, .name = "sctp_sf_eat_fwd_tsn"}, \
+ TYPE_SCTP_FUNC(sctp_sf_eat_fwd_tsn), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_eat_fwd_tsn, .name = "sctp_sf_eat_fwd_tsn"}, \
+ TYPE_SCTP_FUNC(sctp_sf_eat_fwd_tsn), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_eat_fwd_tsn_fast, .name = "sctp_sf_eat_fwd_tsn_fast"}, \
+ TYPE_SCTP_FUNC(sctp_sf_eat_fwd_tsn_fast), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
} /* TYPE_SCTP_FWD_TSN */
/* The primary index for this table is the chunk type.
@@ -529,167 +526,150 @@ static const sctp_sm_table_entry_t prsctp_chunk_event_table[SCTP_NUM_PRSCTP_CHUN
static const sctp_sm_table_entry_t
chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = {
/* SCTP_STATE_EMPTY */
- {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"},
+ TYPE_SCTP_FUNC(sctp_sf_ootb),
/* SCTP_STATE_CLOSED */
- {.fn = sctp_sf_tabort_8_4_8, .name = "sctp_sf_tabort_8_4_8"},
+ TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8),
/* SCTP_STATE_COOKIE_WAIT */
- {.fn = sctp_sf_unk_chunk, .name = "sctp_sf_unk_chunk"},
+ TYPE_SCTP_FUNC(sctp_sf_unk_chunk),
/* SCTP_STATE_COOKIE_ECHOED */
- {.fn = sctp_sf_unk_chunk, .name = "sctp_sf_unk_chunk"},
+ TYPE_SCTP_FUNC(sctp_sf_unk_chunk),
/* SCTP_STATE_ESTABLISHED */
- {.fn = sctp_sf_unk_chunk, .name = "sctp_sf_unk_chunk"},
+ TYPE_SCTP_FUNC(sctp_sf_unk_chunk),
/* SCTP_STATE_SHUTDOWN_PENDING */
- {.fn = sctp_sf_unk_chunk, .name = "sctp_sf_unk_chunk"},
+ TYPE_SCTP_FUNC(sctp_sf_unk_chunk),
/* SCTP_STATE_SHUTDOWN_SENT */
- {.fn = sctp_sf_unk_chunk, .name = "sctp_sf_unk_chunk"},
+ TYPE_SCTP_FUNC(sctp_sf_unk_chunk),
/* SCTP_STATE_SHUTDOWN_RECEIVED */
- {.fn = sctp_sf_unk_chunk, .name = "sctp_sf_unk_chunk"},
+ TYPE_SCTP_FUNC(sctp_sf_unk_chunk),
/* SCTP_STATE_SHUTDOWN_ACK_SENT */
- {.fn = sctp_sf_unk_chunk, .name = "sctp_sf_unk_chunk"},
+ TYPE_SCTP_FUNC(sctp_sf_unk_chunk),
}; /* chunk unknown */
#define TYPE_SCTP_PRIMITIVE_ASSOCIATE { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ TYPE_SCTP_FUNC(sctp_sf_bug), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_do_prm_asoc, .name = "sctp_sf_do_prm_asoc"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_prm_asoc), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
+ TYPE_SCTP_FUNC(sctp_sf_not_impl), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
+ TYPE_SCTP_FUNC(sctp_sf_not_impl), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
+ TYPE_SCTP_FUNC(sctp_sf_not_impl), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
+ TYPE_SCTP_FUNC(sctp_sf_not_impl), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
+ TYPE_SCTP_FUNC(sctp_sf_not_impl), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
+ TYPE_SCTP_FUNC(sctp_sf_not_impl), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
+ TYPE_SCTP_FUNC(sctp_sf_not_impl), \
} /* TYPE_SCTP_PRIMITIVE_ASSOCIATE */
#define TYPE_SCTP_PRIMITIVE_SHUTDOWN { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ TYPE_SCTP_FUNC(sctp_sf_bug), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_error_closed, .name = "sctp_sf_error_closed"}, \
+ TYPE_SCTP_FUNC(sctp_sf_error_closed), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_cookie_wait_prm_shutdown, \
- .name = "sctp_sf_cookie_wait_prm_shutdown"}, \
+ TYPE_SCTP_FUNC(sctp_sf_cookie_wait_prm_shutdown), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_cookie_echoed_prm_shutdown, \
- .name = "sctp_sf_cookie_echoed_prm_shutdown"},\
+ TYPE_SCTP_FUNC(sctp_sf_cookie_echoed_prm_shutdown),\
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_do_9_2_prm_shutdown, \
- .name = "sctp_sf_do_9_2_prm_shutdown"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_9_2_prm_shutdown), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_ignore_primitive, .name = "sctp_sf_ignore_primitive"}, \
+ TYPE_SCTP_FUNC(sctp_sf_ignore_primitive), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_ignore_primitive, .name = "sctp_sf_ignore_primitive"}, \
+ TYPE_SCTP_FUNC(sctp_sf_ignore_primitive), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_ignore_primitive, .name = "sctp_sf_ignore_primitive"}, \
+ TYPE_SCTP_FUNC(sctp_sf_ignore_primitive), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_ignore_primitive, .name = "sctp_sf_ignore_primitive"}, \
+ TYPE_SCTP_FUNC(sctp_sf_ignore_primitive), \
} /* TYPE_SCTP_PRIMITIVE_SHUTDOWN */
#define TYPE_SCTP_PRIMITIVE_ABORT { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ TYPE_SCTP_FUNC(sctp_sf_bug), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_error_closed, .name = "sctp_sf_error_closed"}, \
+ TYPE_SCTP_FUNC(sctp_sf_error_closed), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_cookie_wait_prm_abort, \
- .name = "sctp_sf_cookie_wait_prm_abort"}, \
+ TYPE_SCTP_FUNC(sctp_sf_cookie_wait_prm_abort), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_cookie_echoed_prm_abort, \
- .name = "sctp_sf_cookie_echoed_prm_abort"}, \
+ TYPE_SCTP_FUNC(sctp_sf_cookie_echoed_prm_abort), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_do_9_1_prm_abort, \
- .name = "sctp_sf_do_9_1_prm_abort"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_9_1_prm_abort), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_shutdown_pending_prm_abort, \
- .name = "sctp_sf_shutdown_pending_prm_abort"}, \
+ TYPE_SCTP_FUNC(sctp_sf_shutdown_pending_prm_abort), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_shutdown_sent_prm_abort, \
- .name = "sctp_sf_shutdown_sent_prm_abort"}, \
+ TYPE_SCTP_FUNC(sctp_sf_shutdown_sent_prm_abort), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_do_9_1_prm_abort, \
- .name = "sctp_sf_do_9_1_prm_abort"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_9_1_prm_abort), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_shutdown_ack_sent_prm_abort, \
- .name = "sctp_sf_shutdown_ack_sent_prm_abort"}, \
+ TYPE_SCTP_FUNC(sctp_sf_shutdown_ack_sent_prm_abort), \
} /* TYPE_SCTP_PRIMITIVE_ABORT */
#define TYPE_SCTP_PRIMITIVE_SEND { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ TYPE_SCTP_FUNC(sctp_sf_bug), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_error_closed, .name = "sctp_sf_error_closed"}, \
+ TYPE_SCTP_FUNC(sctp_sf_error_closed), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_do_prm_send, .name = "sctp_sf_do_prm_send"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_prm_send), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_do_prm_send, .name = "sctp_sf_do_prm_send"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_prm_send), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_do_prm_send, .name = "sctp_sf_do_prm_send"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_prm_send), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_error_shutdown, .name = "sctp_sf_error_shutdown"}, \
+ TYPE_SCTP_FUNC(sctp_sf_error_shutdown), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_error_shutdown, .name = "sctp_sf_error_shutdown"}, \
+ TYPE_SCTP_FUNC(sctp_sf_error_shutdown), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_error_shutdown, .name = "sctp_sf_error_shutdown"}, \
+ TYPE_SCTP_FUNC(sctp_sf_error_shutdown), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_error_shutdown, .name = "sctp_sf_error_shutdown"}, \
+ TYPE_SCTP_FUNC(sctp_sf_error_shutdown), \
} /* TYPE_SCTP_PRIMITIVE_SEND */
#define TYPE_SCTP_PRIMITIVE_REQUESTHEARTBEAT { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ TYPE_SCTP_FUNC(sctp_sf_bug), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_error_closed, .name = "sctp_sf_error_closed"}, \
+ TYPE_SCTP_FUNC(sctp_sf_error_closed), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_do_prm_requestheartbeat, \
- .name = "sctp_sf_do_prm_requestheartbeat"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_prm_requestheartbeat), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_do_prm_requestheartbeat, \
- .name = "sctp_sf_do_prm_requestheartbeat"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_prm_requestheartbeat), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_do_prm_requestheartbeat, \
- .name = "sctp_sf_do_prm_requestheartbeat"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_prm_requestheartbeat), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_do_prm_requestheartbeat, \
- .name = "sctp_sf_do_prm_requestheartbeat"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_prm_requestheartbeat), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_do_prm_requestheartbeat, \
- .name = "sctp_sf_do_prm_requestheartbeat"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_prm_requestheartbeat), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_do_prm_requestheartbeat, \
- .name = "sctp_sf_do_prm_requestheartbeat"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_prm_requestheartbeat), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_do_prm_requestheartbeat, \
- .name = "sctp_sf_do_prm_requestheartbeat"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_prm_requestheartbeat), \
} /* TYPE_SCTP_PRIMITIVE_REQUESTHEARTBEAT */
#define TYPE_SCTP_PRIMITIVE_ASCONF { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ TYPE_SCTP_FUNC(sctp_sf_bug), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_error_closed, .name = "sctp_sf_error_closed"}, \
+ TYPE_SCTP_FUNC(sctp_sf_error_closed), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_error_closed, .name = "sctp_sf_error_closed"}, \
+ TYPE_SCTP_FUNC(sctp_sf_error_closed), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_error_closed, .name = "sctp_sf_error_closed"}, \
+ TYPE_SCTP_FUNC(sctp_sf_error_closed), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_do_prm_asconf, .name = "sctp_sf_do_prm_asconf"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_prm_asconf), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_error_shutdown, .name = "sctp_sf_error_shutdown"}, \
+ TYPE_SCTP_FUNC(sctp_sf_error_shutdown), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_error_shutdown, .name = "sctp_sf_error_shutdown"}, \
+ TYPE_SCTP_FUNC(sctp_sf_error_shutdown), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_error_shutdown, .name = "sctp_sf_error_shutdown"}, \
+ TYPE_SCTP_FUNC(sctp_sf_error_shutdown), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_error_shutdown, .name = "sctp_sf_error_shutdown"}, \
+ TYPE_SCTP_FUNC(sctp_sf_error_shutdown), \
} /* TYPE_SCTP_PRIMITIVE_REQUESTHEARTBEAT */
/* The primary index for this table is the primitive type.
@@ -706,47 +686,44 @@ static const sctp_sm_table_entry_t primitive_event_table[SCTP_NUM_PRIMITIVE_TYPE
#define TYPE_SCTP_OTHER_NO_PENDING_TSN { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ TYPE_SCTP_FUNC(sctp_sf_bug), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
+ TYPE_SCTP_FUNC(sctp_sf_ignore_other), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
+ TYPE_SCTP_FUNC(sctp_sf_ignore_other), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
+ TYPE_SCTP_FUNC(sctp_sf_ignore_other), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
+ TYPE_SCTP_FUNC(sctp_sf_ignore_other), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_do_9_2_start_shutdown, \
- .name = "sctp_do_9_2_start_shutdown"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_9_2_start_shutdown), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
+ TYPE_SCTP_FUNC(sctp_sf_ignore_other), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_do_9_2_shutdown_ack, \
- .name = "sctp_sf_do_9_2_shutdown_ack"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_9_2_shutdown_ack), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
+ TYPE_SCTP_FUNC(sctp_sf_ignore_other), \
}
#define TYPE_SCTP_OTHER_ICMP_PROTO_UNREACH { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ TYPE_SCTP_FUNC(sctp_sf_bug), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
+ TYPE_SCTP_FUNC(sctp_sf_ignore_other), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_cookie_wait_icmp_abort, \
- .name = "sctp_sf_cookie_wait_icmp_abort"}, \
+ TYPE_SCTP_FUNC(sctp_sf_cookie_wait_icmp_abort), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
+ TYPE_SCTP_FUNC(sctp_sf_ignore_other), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
+ TYPE_SCTP_FUNC(sctp_sf_ignore_other), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
+ TYPE_SCTP_FUNC(sctp_sf_ignore_other), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
+ TYPE_SCTP_FUNC(sctp_sf_ignore_other), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
+ TYPE_SCTP_FUNC(sctp_sf_ignore_other), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
+ TYPE_SCTP_FUNC(sctp_sf_ignore_other), \
}
static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_STATE_NUM_STATES] = {
@@ -756,215 +733,212 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_
#define TYPE_SCTP_EVENT_TIMEOUT_NONE { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ TYPE_SCTP_FUNC(sctp_sf_bug), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ TYPE_SCTP_FUNC(sctp_sf_bug), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ TYPE_SCTP_FUNC(sctp_sf_bug), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ TYPE_SCTP_FUNC(sctp_sf_bug), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ TYPE_SCTP_FUNC(sctp_sf_bug), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ TYPE_SCTP_FUNC(sctp_sf_bug), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ TYPE_SCTP_FUNC(sctp_sf_bug), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ TYPE_SCTP_FUNC(sctp_sf_bug), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ TYPE_SCTP_FUNC(sctp_sf_bug), \
}
#define TYPE_SCTP_EVENT_TIMEOUT_T1_COOKIE { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ TYPE_SCTP_FUNC(sctp_sf_bug), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ TYPE_SCTP_FUNC(sctp_sf_bug), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_t1_cookie_timer_expire, \
- .name = "sctp_sf_t1_cookie_timer_expire"}, \
+ TYPE_SCTP_FUNC(sctp_sf_t1_cookie_timer_expire), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
}
#define TYPE_SCTP_EVENT_TIMEOUT_T1_INIT { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ TYPE_SCTP_FUNC(sctp_sf_bug), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_t1_init_timer_expire, \
- .name = "sctp_sf_t1_init_timer_expire"}, \
+ TYPE_SCTP_FUNC(sctp_sf_t1_init_timer_expire), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
}
#define TYPE_SCTP_EVENT_TIMEOUT_T2_SHUTDOWN { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ TYPE_SCTP_FUNC(sctp_sf_bug), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_t2_timer_expire, .name = "sctp_sf_t2_timer_expire"}, \
+ TYPE_SCTP_FUNC(sctp_sf_t2_timer_expire), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_t2_timer_expire, .name = "sctp_sf_t2_timer_expire"}, \
+ TYPE_SCTP_FUNC(sctp_sf_t2_timer_expire), \
}
#define TYPE_SCTP_EVENT_TIMEOUT_T3_RTX { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ TYPE_SCTP_FUNC(sctp_sf_bug), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_do_6_3_3_rtx, .name = "sctp_sf_do_6_3_3_rtx"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_6_3_3_rtx), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_do_6_3_3_rtx, .name = "sctp_sf_do_6_3_3_rtx"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_6_3_3_rtx), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_do_6_3_3_rtx, .name = "sctp_sf_do_6_3_3_rtx"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_6_3_3_rtx), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_do_6_3_3_rtx, .name = "sctp_sf_do_6_3_3_rtx"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_6_3_3_rtx), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
}
#define TYPE_SCTP_EVENT_TIMEOUT_T4_RTO { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ TYPE_SCTP_FUNC(sctp_sf_bug), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_t4_timer_expire, .name = "sctp_sf_t4_timer_expire"}, \
+ TYPE_SCTP_FUNC(sctp_sf_t4_timer_expire), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
}
#define TYPE_SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ TYPE_SCTP_FUNC(sctp_sf_bug), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_t5_timer_expire, .name = "sctp_sf_t5_timer_expire"}, \
+ TYPE_SCTP_FUNC(sctp_sf_t5_timer_expire), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_t5_timer_expire, .name = "sctp_sf_t5_timer_expire"}, \
+ TYPE_SCTP_FUNC(sctp_sf_t5_timer_expire), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
}
#define TYPE_SCTP_EVENT_TIMEOUT_HEARTBEAT { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ TYPE_SCTP_FUNC(sctp_sf_bug), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_sendbeat_8_3, .name = "sctp_sf_sendbeat_8_3"}, \
+ TYPE_SCTP_FUNC(sctp_sf_sendbeat_8_3), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_sendbeat_8_3, .name = "sctp_sf_sendbeat_8_3"}, \
+ TYPE_SCTP_FUNC(sctp_sf_sendbeat_8_3), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_sendbeat_8_3, .name = "sctp_sf_sendbeat_8_3"}, \
+ TYPE_SCTP_FUNC(sctp_sf_sendbeat_8_3), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
}
#define TYPE_SCTP_EVENT_TIMEOUT_SACK { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ TYPE_SCTP_FUNC(sctp_sf_bug), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_do_6_2_sack, .name = "sctp_sf_do_6_2_sack"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_6_2_sack), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_do_6_2_sack, .name = "sctp_sf_do_6_2_sack"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_6_2_sack), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_do_6_2_sack, .name = "sctp_sf_do_6_2_sack"}, \
+ TYPE_SCTP_FUNC(sctp_sf_do_6_2_sack), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
}
#define TYPE_SCTP_EVENT_TIMEOUT_AUTOCLOSE { \
/* SCTP_STATE_EMPTY */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_ESTABLISHED */ \
- {.fn = sctp_sf_autoclose_timer_expire, \
- .name = "sctp_sf_autoclose_timer_expire"}, \
+ TYPE_SCTP_FUNC(sctp_sf_autoclose_timer_expire), \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_SHUTDOWN_SENT */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \
}
static const sctp_sm_table_entry_t timeout_event_table[SCTP_NUM_TIMEOUT_TYPES][SCTP_STATE_NUM_STATES] = {
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 935bc9187fd8..02b27145b279 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -229,11 +229,9 @@ static struct sctp_transport *sctp_addr_id2transport(struct sock *sk,
struct sctp_transport *transport;
union sctp_addr *laddr = (union sctp_addr *)addr;
- laddr->v4.sin_port = ntohs(laddr->v4.sin_port);
addr_asoc = sctp_endpoint_lookup_assoc(sctp_sk(sk)->ep,
- (union sctp_addr *)addr,
+ laddr,
&transport);
- laddr->v4.sin_port = htons(laddr->v4.sin_port);
if (!addr_asoc)
return NULL;
@@ -368,9 +366,7 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
sctp_write_lock(&ep->base.addr_lock);
/* Use GFP_ATOMIC since BHs are disabled. */
- addr->v4.sin_port = ntohs(addr->v4.sin_port);
ret = sctp_add_bind_addr(bp, addr, 1, GFP_ATOMIC);
- addr->v4.sin_port = htons(addr->v4.sin_port);
sctp_write_unlock(&ep->base.addr_lock);
sctp_local_bh_enable();
@@ -572,7 +568,6 @@ static int sctp_send_asconf_add_ip(struct sock *sk,
addr = (union sctp_addr *)addr_buf;
af = sctp_get_af_specific(addr->v4.sin_family);
memcpy(&saveaddr, addr, af->sockaddr_len);
- saveaddr.v4.sin_port = ntohs(saveaddr.v4.sin_port);
retval = sctp_add_bind_addr(bp, &saveaddr, 0,
GFP_ATOMIC);
addr_buf += af->sockaddr_len;
@@ -607,9 +602,8 @@ int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt)
int cnt;
struct sctp_bind_addr *bp = &ep->base.bind_addr;
int retval = 0;
- union sctp_addr saveaddr;
void *addr_buf;
- struct sockaddr *sa_addr;
+ union sctp_addr *sa_addr;
struct sctp_af *af;
SCTP_DEBUG_PRINTK("sctp_bindx_rem (sk: %p, addrs: %p, addrcnt: %d)\n",
@@ -627,19 +621,13 @@ int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt)
goto err_bindx_rem;
}
- /* The list may contain either IPv4 or IPv6 address;
- * determine the address length to copy the address to
- * saveaddr.
- */
- sa_addr = (struct sockaddr *)addr_buf;
- af = sctp_get_af_specific(sa_addr->sa_family);
+ sa_addr = (union sctp_addr *)addr_buf;
+ af = sctp_get_af_specific(sa_addr->sa.sa_family);
if (!af) {
retval = -EINVAL;
goto err_bindx_rem;
}
- memcpy(&saveaddr, sa_addr, af->sockaddr_len);
- saveaddr.v4.sin_port = ntohs(saveaddr.v4.sin_port);
- if (saveaddr.v4.sin_port != bp->port) {
+ if (sa_addr->v4.sin_port != htons(bp->port)) {
retval = -EINVAL;
goto err_bindx_rem;
}
@@ -654,7 +642,7 @@ int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt)
sctp_local_bh_disable();
sctp_write_lock(&ep->base.addr_lock);
- retval = sctp_del_bind_addr(bp, &saveaddr);
+ retval = sctp_del_bind_addr(bp, sa_addr);
sctp_write_unlock(&ep->base.addr_lock);
sctp_local_bh_enable();
@@ -693,7 +681,6 @@ static int sctp_send_asconf_del_ip(struct sock *sk,
struct sctp_bind_addr *bp;
struct sctp_chunk *chunk;
union sctp_addr *laddr;
- union sctp_addr saveaddr;
void *addr_buf;
struct sctp_af *af;
struct list_head *pos, *pos1;
@@ -773,13 +760,11 @@ static int sctp_send_asconf_del_ip(struct sock *sk,
for (i = 0; i < addrcnt; i++) {
laddr = (union sctp_addr *)addr_buf;
af = sctp_get_af_specific(laddr->v4.sin_family);
- memcpy(&saveaddr, laddr, af->sockaddr_len);
- saveaddr.v4.sin_port = ntohs(saveaddr.v4.sin_port);
list_for_each(pos1, &bp->address_list) {
saddr = list_entry(pos1,
struct sctp_sockaddr_entry,
list);
- if (sctp_cmp_addr_exact(&saddr->a, &saveaddr))
+ if (sctp_cmp_addr_exact(&saddr->a, laddr))
saddr->use_as_src = 0;
}
addr_buf += af->sockaddr_len;
@@ -979,7 +964,7 @@ static int __sctp_connect(struct sock* sk,
int err = 0;
int addrcnt = 0;
int walk_size = 0;
- struct sockaddr *sa_addr;
+ union sctp_addr *sa_addr;
void *addr_buf;
sp = sctp_sk(sk);
@@ -999,8 +984,8 @@ static int __sctp_connect(struct sock* sk,
/* Walk through the addrs buffer and count the number of addresses. */
addr_buf = kaddrs;
while (walk_size < addrs_size) {
- sa_addr = (struct sockaddr *)addr_buf;
- af = sctp_get_af_specific(sa_addr->sa_family);
+ sa_addr = (union sctp_addr *)addr_buf;
+ af = sctp_get_af_specific(sa_addr->sa.sa_family);
/* If the address family is not supported or if this address
* causes the address buffer to overflow return EINVAL.
@@ -1010,18 +995,16 @@ static int __sctp_connect(struct sock* sk,
goto out_free;
}
- err = sctp_verify_addr(sk, (union sctp_addr *)sa_addr,
- af->sockaddr_len);
+ err = sctp_verify_addr(sk, sa_addr, af->sockaddr_len);
if (err)
goto out_free;
memcpy(&to, sa_addr, af->sockaddr_len);
- to.v4.sin_port = ntohs(to.v4.sin_port);
/* Check if there already is a matching association on the
* endpoint (other than the one created here).
*/
- asoc2 = sctp_endpoint_lookup_assoc(ep, &to, &transport);
+ asoc2 = sctp_endpoint_lookup_assoc(ep, sa_addr, &transport);
if (asoc2 && asoc2 != asoc) {
if (asoc2->state >= SCTP_STATE_ESTABLISHED)
err = -EISCONN;
@@ -1034,7 +1017,7 @@ static int __sctp_connect(struct sock* sk,
* make sure that there is no peeled-off association matching
* the peer address even on another socket.
*/
- if (sctp_endpoint_is_peeled_off(ep, &to)) {
+ if (sctp_endpoint_is_peeled_off(ep, sa_addr)) {
err = -EADDRNOTAVAIL;
goto out_free;
}
@@ -1065,7 +1048,7 @@ static int __sctp_connect(struct sock* sk,
}
}
- scope = sctp_scope(&to);
+ scope = sctp_scope(sa_addr);
asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL);
if (!asoc) {
err = -ENOMEM;
@@ -1074,7 +1057,7 @@ static int __sctp_connect(struct sock* sk,
}
/* Prime the peer's transport structures. */
- transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL,
+ transport = sctp_assoc_add_peer(asoc, sa_addr, GFP_KERNEL,
SCTP_UNKNOWN);
if (!transport) {
err = -ENOMEM;
@@ -1427,11 +1410,6 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
if (msg_namelen > sizeof(to))
msg_namelen = sizeof(to);
memcpy(&to, msg->msg_name, msg_namelen);
- SCTP_DEBUG_PRINTK("Just memcpy'd. msg_name is "
- "0x%x:%u.\n",
- to.v4.sin_addr.s_addr, to.v4.sin_port);
-
- to.v4.sin_port = ntohs(to.v4.sin_port);
msg_name = msg->msg_name;
}
@@ -3217,8 +3195,8 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len,
status.sstat_outstrms = asoc->c.sinit_num_ostreams;
status.sstat_fragmentation_point = asoc->frag_point;
status.sstat_primary.spinfo_assoc_id = sctp_assoc2id(transport->asoc);
- memcpy(&status.sstat_primary.spinfo_address,
- &(transport->ipaddr), sizeof(union sctp_addr));
+ memcpy(&status.sstat_primary.spinfo_address, &transport->ipaddr,
+ transport->af_specific->sockaddr_len);
/* Map ipv4 address into v4-mapped-on-v6 address. */
sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk),
(union sctp_addr *)&status.sstat_primary.spinfo_address);
@@ -3770,7 +3748,6 @@ static int sctp_getsockopt_peer_addrs_old(struct sock *sk, int len,
memcpy(&temp, &from->ipaddr, sizeof(temp));
sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp);
addrlen = sctp_get_af_specific(sk->sk_family)->sockaddr_len;
- temp.v4.sin_port = htons(temp.v4.sin_port);
if (copy_to_user(to, &temp, addrlen))
return -EFAULT;
to += addrlen ;
@@ -3821,7 +3798,6 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len,
addrlen = sctp_get_af_specific(sk->sk_family)->sockaddr_len;
if(space_left < addrlen)
return -ENOMEM;
- temp.v4.sin_port = htons(temp.v4.sin_port);
if (copy_to_user(to, &temp, addrlen))
return -EFAULT;
to += addrlen;
@@ -3889,7 +3865,7 @@ static int sctp_getsockopt_local_addrs_num_old(struct sock *sk, int len,
struct sctp_sockaddr_entry,
list);
if ((PF_INET == sk->sk_family) &&
- (AF_INET6 == addr->a.sa.sa_family))
+ (AF_INET6 == addr->a.sa.sa_family))
continue;
cnt++;
}
@@ -3933,7 +3909,6 @@ static int sctp_copy_laddrs_to_user_old(struct sock *sk, __u16 port, int max_add
sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk),
&temp);
addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
- temp.v4.sin_port = htons(port);
if (copy_to_user(to, &temp, addrlen)) {
sctp_spin_unlock_irqrestore(&sctp_local_addr_lock,
flags);
@@ -3970,7 +3945,6 @@ static int sctp_copy_laddrs_to_user(struct sock *sk, __u16 port,
addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
if(space_left<addrlen)
return -ENOMEM;
- temp.v4.sin_port = htons(port);
if (copy_to_user(*to, &temp, addrlen)) {
sctp_spin_unlock_irqrestore(&sctp_local_addr_lock,
flags);
@@ -4055,7 +4029,6 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len,
memcpy(&temp, &addr->a, sizeof(temp));
sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp);
addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
- temp.v4.sin_port = htons(temp.v4.sin_port);
if (copy_to_user(to, &temp, addrlen)) {
err = -EFAULT;
goto unlock;
@@ -4146,7 +4119,6 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
if(space_left < addrlen)
return -ENOMEM; /*fixme: right error?*/
- temp.v4.sin_port = htons(temp.v4.sin_port);
if (copy_to_user(to, &temp, addrlen)) {
err = -EFAULT;
goto unlock;
@@ -4194,12 +4166,8 @@ static int sctp_getsockopt_primary_addr(struct sock *sk, int len,
if (!asoc->peer.primary_path)
return -ENOTCONN;
- asoc->peer.primary_path->ipaddr.v4.sin_port =
- htons(asoc->peer.primary_path->ipaddr.v4.sin_port);
memcpy(&prim.ssp_addr, &asoc->peer.primary_path->ipaddr,
- sizeof(union sctp_addr));
- asoc->peer.primary_path->ipaddr.v4.sin_port =
- ntohs(asoc->peer.primary_path->ipaddr.v4.sin_port);
+ asoc->peer.primary_path->af_specific->sockaddr_len);
sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp,
(union sctp_addr *)&prim.ssp_addr);
@@ -4645,9 +4613,7 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
unsigned short snum;
int ret;
- /* NOTE: Remember to put this back to net order. */
- addr->v4.sin_port = ntohs(addr->v4.sin_port);
- snum = addr->v4.sin_port;
+ snum = ntohs(addr->v4.sin_port);
SCTP_DEBUG_PRINTK("sctp_get_port() begins, snum=%d\n", snum);
sctp_local_bh_disable();
@@ -4784,7 +4750,6 @@ fail_unlock:
fail:
sctp_local_bh_enable();
- addr->v4.sin_port = htons(addr->v4.sin_port);
return ret;
}
@@ -5083,7 +5048,7 @@ static int sctp_autobind(struct sock *sk)
{
union sctp_addr autoaddr;
struct sctp_af *af;
- unsigned short port;
+ __be16 port;
/* Initialize a local sockaddr structure to INADDR_ANY. */
af = sctp_sk(sk)->pf->af;
diff --git a/net/sctp/tsnmap.c b/net/sctp/tsnmap.c
index ac4fae161bc7..42d9498c64fa 100644
--- a/net/sctp/tsnmap.c
+++ b/net/sctp/tsnmap.c
@@ -401,13 +401,14 @@ __u16 sctp_tsnmap_num_gabs(struct sctp_tsnmap *map)
/* Refresh the gap ack information. */
if (sctp_tsnmap_has_gap(map)) {
+ __u16 start, end;
sctp_tsnmap_iter_init(map, &iter);
while (sctp_tsnmap_next_gap_ack(map, &iter,
- &map->gabs[gabs].start,
- &map->gabs[gabs].end)) {
+ &start,
+ &end)) {
- map->gabs[gabs].start = htons(map->gabs[gabs].start);
- map->gabs[gabs].end = htons(map->gabs[gabs].end);
+ map->gabs[gabs].start = htons(start);
+ map->gabs[gabs].end = htons(end);
gabs++;
if (gabs >= SCTP_MAX_GABS)
break;
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index a015283a9087..e255a709f1b7 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -351,7 +351,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_remote_error(
struct sctp_remote_error *sre;
struct sk_buff *skb;
sctp_errhdr_t *ch;
- __u16 cause;
+ __be16 cause;
int elen;
ch = (sctp_errhdr_t *)(chunk->skb->data);
diff --git a/net/socket.c b/net/socket.c
index 6c9b9b326d76..e8db54702a69 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -77,7 +77,6 @@
#include <linux/cache.h>
#include <linux/module.h>
#include <linux/highmem.h>
-#include <linux/divert.h>
#include <linux/mount.h>
#include <linux/security.h>
#include <linux/syscalls.h>
@@ -852,11 +851,6 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
err = vlan_ioctl_hook(argp);
mutex_unlock(&vlan_ioctl_mutex);
break;
- case SIOCGIFDIVERT:
- case SIOCSIFDIVERT:
- /* Convert this to call through a hook */
- err = divert_ioctl(cmd, argp);
- break;
case SIOCADDDLCI:
case SIOCDELDLCI:
err = -ENOPKG;
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index b36b9463f5a4..e5a84a482e57 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -198,11 +198,10 @@ simple_get_netobj(const void *p, const void *end, struct xdr_netobj *dest)
q = (const void *)((const char *)p + len);
if (unlikely(q > end || q < p))
return ERR_PTR(-EFAULT);
- dest->data = kmalloc(len, GFP_KERNEL);
+ dest->data = kmemdup(p, len, GFP_KERNEL);
if (unlikely(dest->data == NULL))
return ERR_PTR(-ENOMEM);
dest->len = len;
- memcpy(dest->data, p, len);
return q;
}
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 325e72e4fd31..754b8cd6439f 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -70,10 +70,9 @@ simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res)
q = (const void *)((const char *)p + len);
if (unlikely(q > end || q < p))
return ERR_PTR(-EFAULT);
- res->data = kmalloc(len, GFP_KERNEL);
+ res->data = kmemdup(p, len, GFP_KERNEL);
if (unlikely(res->data == NULL))
return ERR_PTR(-ENOMEM);
- memcpy(res->data, p, len);
res->len = len;
return q;
}
diff --git a/net/sunrpc/auth_gss/gss_spkm3_mech.c b/net/sunrpc/auth_gss/gss_spkm3_mech.c
index bdedf456bc17..d57f60838895 100644
--- a/net/sunrpc/auth_gss/gss_spkm3_mech.c
+++ b/net/sunrpc/auth_gss/gss_spkm3_mech.c
@@ -76,10 +76,9 @@ simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res)
q = (const void *)((const char *)p + len);
if (unlikely(q > end || q < p))
return ERR_PTR(-EFAULT);
- res->data = kmalloc(len, GFP_KERNEL);
+ res->data = kmemdup(p, len, GFP_KERNEL);
if (unlikely(res->data == NULL))
return ERR_PTR(-ENOMEM);
- memcpy(res->data, p, len);
return q;
}
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 1f0f079ffa65..700353b330fd 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -113,9 +113,7 @@ static int rsi_match(struct cache_head *a, struct cache_head *b)
static int dup_to_netobj(struct xdr_netobj *dst, char *src, int len)
{
dst->len = len;
- dst->data = (len ? kmalloc(len, GFP_KERNEL) : NULL);
- if (dst->data)
- memcpy(dst->data, src, len);
+ dst->data = (len ? kmemdup(src, len, GFP_KERNEL) : NULL);
if (len && !dst->data)
return -ENOMEM;
return 0;
@@ -756,10 +754,9 @@ svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name)
if (!new)
goto out;
kref_init(&new->h.ref);
- new->h.name = kmalloc(strlen(name) + 1, GFP_KERNEL);
+ new->h.name = kstrdup(name, GFP_KERNEL);
if (!new->h.name)
goto out_free_dom;
- strcpy(new->h.name, name);
new->h.flavour = &svcauthops_gss;
new->pseudoflavor = pseudoflavor;
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 78696f2dc7d6..dfeea4fea95a 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -253,10 +253,9 @@ rpc_clone_client(struct rpc_clnt *clnt)
{
struct rpc_clnt *new;
- new = kmalloc(sizeof(*new), GFP_KERNEL);
+ new = kmemdup(clnt, sizeof(*new), GFP_KERNEL);
if (!new)
goto out_no_clnt;
- memcpy(new, clnt, sizeof(*new));
atomic_set(&new->cl_count, 1);
atomic_set(&new->cl_users, 0);
new->cl_parent = clnt;
diff --git a/net/sunrpc/socklib.c b/net/sunrpc/socklib.c
index 6f17527b9e69..2635c543ba06 100644
--- a/net/sunrpc/socklib.c
+++ b/net/sunrpc/socklib.c
@@ -45,7 +45,8 @@ static size_t skb_read_bits(skb_reader_t *desc, void *to, size_t len)
*/
static size_t skb_read_and_csum_bits(skb_reader_t *desc, void *to, size_t len)
{
- unsigned int csum2, pos;
+ unsigned int pos;
+ __wsum csum2;
if (len > desc->count)
len = desc->count;
@@ -160,13 +161,13 @@ int csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb)
if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_and_csum_bits) < 0)
return -1;
if (desc.offset != skb->len) {
- unsigned int csum2;
+ __wsum csum2;
csum2 = skb_checksum(skb, desc.offset, skb->len - desc.offset, 0);
desc.csum = csum_block_add(desc.csum, csum2, desc.offset);
}
if (desc.count)
return -1;
- if ((unsigned short)csum_fold(desc.csum))
+ if (csum_fold(desc.csum))
return -1;
if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE))
netdev_rx_csum_fault(skb->dev);
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index e1bd933629fe..a0a953a430c2 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -101,9 +101,9 @@ static void ip_map_put(struct kref *kref)
* IP addresses in reverse-endian (i.e. on a little-endian machine).
* So use a trivial but reliable hash instead
*/
-static inline int hash_ip(unsigned long ip)
+static inline int hash_ip(__be32 ip)
{
- int hash = ip ^ (ip>>16);
+ int hash = (__force u32)ip ^ ((__force u32)ip>>16);
return (hash ^ (hash>>8)) & 0xff;
}
#endif
@@ -284,7 +284,7 @@ static struct ip_map *ip_map_lookup(char *class, struct in_addr addr)
ip.m_addr = addr;
ch = sunrpc_cache_lookup(&ip_map_cache, &ip.h,
hash_str(class, IP_HASHBITS) ^
- hash_ip((unsigned long)addr.s_addr));
+ hash_ip(addr.s_addr));
if (ch)
return container_of(ch, struct ip_map, h);
@@ -313,7 +313,7 @@ static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t ex
ch = sunrpc_cache_update(&ip_map_cache,
&ip.h, &ipm->h,
hash_str(ipm->m_class, IP_HASHBITS) ^
- hash_ip((unsigned long)ipm->m_addr.s_addr));
+ hash_ip(ipm->m_addr.s_addr));
if (!ch)
return -ENOMEM;
cache_put(ch, &ip_map_cache);
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index 1bb75703f384..730c5c47ed8d 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -774,8 +774,8 @@ int tipc_bclink_set_queue_limits(u32 limit)
int tipc_bclink_init(void)
{
- bcbearer = kmalloc(sizeof(*bcbearer), GFP_ATOMIC);
- bclink = kmalloc(sizeof(*bclink), GFP_ATOMIC);
+ bcbearer = kzalloc(sizeof(*bcbearer), GFP_ATOMIC);
+ bclink = kzalloc(sizeof(*bclink), GFP_ATOMIC);
if (!bcbearer || !bclink) {
nomem:
warn("Multicast link creation failed, no memory\n");
@@ -786,14 +786,12 @@ int tipc_bclink_init(void)
return -ENOMEM;
}
- memset(bcbearer, 0, sizeof(struct bcbearer));
INIT_LIST_HEAD(&bcbearer->bearer.cong_links);
bcbearer->bearer.media = &bcbearer->media;
bcbearer->media.send_msg = tipc_bcbearer_send;
sprintf(bcbearer->media.name, "tipc-multicast");
bcl = &bclink->link;
- memset(bclink, 0, sizeof(struct bclink));
INIT_LIST_HEAD(&bcl->waiting_ports);
bcl->next_out_no = 1;
spin_lock_init(&bclink->node.lock);
diff --git a/net/tipc/config.c b/net/tipc/config.c
index ed1351ed05e1..458a2c46cef3 100644
--- a/net/tipc/config.c
+++ b/net/tipc/config.c
@@ -107,7 +107,7 @@ int tipc_cfg_append_tlv(struct sk_buff *buf, int tlv_type,
struct sk_buff *tipc_cfg_reply_unsigned_type(u16 tlv_type, u32 value)
{
struct sk_buff *buf;
- u32 value_net;
+ __be32 value_net;
buf = tipc_cfg_reply_alloc(TLV_SPACE(sizeof(value)));
if (buf) {
@@ -284,8 +284,7 @@ static struct sk_buff *cfg_set_own_addr(void)
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
- addr = *(u32 *)TLV_DATA(req_tlv_area);
- addr = ntohl(addr);
+ addr = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
if (addr == tipc_own_addr)
return tipc_cfg_reply_none();
if (!tipc_addr_node_valid(addr))
@@ -319,8 +318,7 @@ static struct sk_buff *cfg_set_remote_mng(void)
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
- value = *(u32 *)TLV_DATA(req_tlv_area);
- value = ntohl(value);
+ value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
tipc_remote_management = (value != 0);
return tipc_cfg_reply_none();
}
@@ -332,8 +330,7 @@ static struct sk_buff *cfg_set_max_publications(void)
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
- value = *(u32 *)TLV_DATA(req_tlv_area);
- value = ntohl(value);
+ value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
if (value != delimit(value, 1, 65535))
return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
" (max publications must be 1-65535)");
@@ -348,8 +345,7 @@ static struct sk_buff *cfg_set_max_subscriptions(void)
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
- value = *(u32 *)TLV_DATA(req_tlv_area);
- value = ntohl(value);
+ value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
if (value != delimit(value, 1, 65535))
return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
" (max subscriptions must be 1-65535");
@@ -363,8 +359,7 @@ static struct sk_buff *cfg_set_max_ports(void)
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
- value = *(u32 *)TLV_DATA(req_tlv_area);
- value = ntohl(value);
+ value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
if (value == tipc_max_ports)
return tipc_cfg_reply_none();
if (value != delimit(value, 127, 65535))
@@ -383,8 +378,7 @@ static struct sk_buff *cfg_set_max_zones(void)
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
- value = *(u32 *)TLV_DATA(req_tlv_area);
- value = ntohl(value);
+ value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
if (value == tipc_max_zones)
return tipc_cfg_reply_none();
if (value != delimit(value, 1, 255))
@@ -403,8 +397,7 @@ static struct sk_buff *cfg_set_max_clusters(void)
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
- value = *(u32 *)TLV_DATA(req_tlv_area);
- value = ntohl(value);
+ value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
if (value != delimit(value, 1, 1))
return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
" (max clusters fixed at 1)");
@@ -417,8 +410,7 @@ static struct sk_buff *cfg_set_max_nodes(void)
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
- value = *(u32 *)TLV_DATA(req_tlv_area);
- value = ntohl(value);
+ value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
if (value == tipc_max_nodes)
return tipc_cfg_reply_none();
if (value != delimit(value, 8, 2047))
@@ -437,8 +429,7 @@ static struct sk_buff *cfg_set_max_slaves(void)
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
- value = *(u32 *)TLV_DATA(req_tlv_area);
- value = ntohl(value);
+ value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
if (value != 0)
return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
" (max secondary nodes fixed at 0)");
@@ -451,8 +442,7 @@ static struct sk_buff *cfg_set_netid(void)
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
- value = *(u32 *)TLV_DATA(req_tlv_area);
- value = ntohl(value);
+ value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
if (value == tipc_net_id)
return tipc_cfg_reply_none();
if (value != delimit(value, 1, 9999))
diff --git a/net/tipc/dbg.c b/net/tipc/dbg.c
index d8af4c28695d..627f99b7afdf 100644
--- a/net/tipc/dbg.c
+++ b/net/tipc/dbg.c
@@ -393,8 +393,7 @@ struct sk_buff *tipc_log_resize(const void *req_tlv_area, int req_tlv_space)
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
- value = *(u32 *)TLV_DATA(req_tlv_area);
- value = ntohl(value);
+ value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
if (value != delimit(value, 0, 32768))
return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
" (log size must be 0-32768)");
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c
index 03bd659c43ca..7bf87cb26ef3 100644
--- a/net/tipc/name_distr.c
+++ b/net/tipc/name_distr.c
@@ -66,11 +66,11 @@
*/
struct distr_item {
- u32 type;
- u32 lower;
- u32 upper;
- u32 ref;
- u32 key;
+ __be32 type;
+ __be32 lower;
+ __be32 upper;
+ __be32 ref;
+ __be32 key;
};
/**
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 886bda5e88db..4111a31def79 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -60,7 +60,7 @@ struct node *tipc_node_create(u32 addr)
struct node *n_ptr;
struct node **curr_node;
- n_ptr = kmalloc(sizeof(*n_ptr),GFP_ATOMIC);
+ n_ptr = kzalloc(sizeof(*n_ptr),GFP_ATOMIC);
if (!n_ptr) {
warn("Node creation failed, no memory\n");
return NULL;
@@ -75,7 +75,6 @@ struct node *tipc_node_create(u32 addr)
return NULL;
}
- memset(n_ptr, 0, sizeof(*n_ptr));
n_ptr->addr = addr;
spin_lock_init(&n_ptr->lock);
INIT_LIST_HEAD(&n_ptr->nsub);
@@ -597,8 +596,7 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
- domain = *(u32 *)TLV_DATA(req_tlv_area);
- domain = ntohl(domain);
+ domain = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
if (!tipc_addr_domain_valid(domain))
return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
" (network address)");
@@ -642,8 +640,7 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
- domain = *(u32 *)TLV_DATA(req_tlv_area);
- domain = ntohl(domain);
+ domain = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
if (!tipc_addr_domain_valid(domain))
return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
" (network address)");
@@ -664,8 +661,7 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
/* Add TLV for broadcast link */
- link_info.dest = tipc_own_addr & 0xfffff00;
- link_info.dest = htonl(link_info.dest);
+ link_info.dest = htonl(tipc_own_addr & 0xfffff00);
link_info.up = htonl(1);
sprintf(link_info.str, tipc_bclink_name);
tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info));
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c
index 7a918f12a5df..ddade7388aa0 100644
--- a/net/tipc/subscr.c
+++ b/net/tipc/subscr.c
@@ -350,7 +350,7 @@ static void subscr_subscribe(struct tipc_subscr *s,
/* Allocate subscription object */
- sub = kmalloc(sizeof(*sub), GFP_ATOMIC);
+ sub = kzalloc(sizeof(*sub), GFP_ATOMIC);
if (!sub) {
warn("Subscription rejected, no memory\n");
subscr_terminate(subscriber);
@@ -359,7 +359,6 @@ static void subscr_subscribe(struct tipc_subscr *s,
/* Initialize subscription object */
- memset(sub, 0, sizeof(*sub));
sub->seq.type = htohl(s->seq.type, subscriber->swap);
sub->seq.lower = htohl(s->seq.lower, subscriber->swap);
sub->seq.upper = htohl(s->seq.upper, subscriber->swap);
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index b43a27828df5..2f208c7f4d43 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -151,8 +151,9 @@ static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
* each socket state is protected by separate rwlock.
*/
-static inline unsigned unix_hash_fold(unsigned hash)
+static inline unsigned unix_hash_fold(__wsum n)
{
+ unsigned hash = (__force unsigned)n;
hash ^= hash>>16;
hash ^= hash>>8;
return hash&(UNIX_HASH_SIZE-1);
diff --git a/net/wanrouter/af_wanpipe.c b/net/wanrouter/af_wanpipe.c
index 6f39faa15832..c2059733e15a 100644
--- a/net/wanrouter/af_wanpipe.c
+++ b/net/wanrouter/af_wanpipe.c
@@ -13,7 +13,7 @@
* Due Credit:
* Wanpipe socket layer is based on Packet and
* the X25 socket layers. The above sockets were
-* used for the specific use of Sangoma Technoloiges
+* used for the specific use of Sangoma Technologies
* API programs.
* Packet socket Authors: Ross Biro, Fred N. van Kempen and
* Alan Cox.
@@ -23,7 +23,7 @@
* Apr 25, 2000 Nenad Corbic o Added the ability to send zero length packets.
* Mar 13, 2000 Nenad Corbic o Added a tx buffer check via ioctl call.
* Mar 06, 2000 Nenad Corbic o Fixed the corrupt sock lcn problem.
-* Server and client applicaton can run
+* Server and client application can run
* simultaneously without conflicts.
* Feb 29, 2000 Nenad Corbic o Added support for PVC protocols, such as
* CHDLC, Frame Relay and HDLC API.
diff --git a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c
index 9479659277ae..316211d9f17d 100644
--- a/net/wanrouter/wanmain.c
+++ b/net/wanrouter/wanmain.c
@@ -3,7 +3,7 @@
*
* This module is completely hardware-independent and provides
* the following common services for the WAN Link Drivers:
-* o WAN device managenment (registering, unregistering)
+* o WAN device management (registering, unregistering)
* o Network interface management
* o Physical connection management (dial-up, incoming calls)
* o Logical connection management (switched virtual circuits)
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index ba924d40df7d..f6c77bd36fdd 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -50,6 +50,40 @@ static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo);
static struct xfrm_policy_afinfo *xfrm_policy_lock_afinfo(unsigned int family);
static void xfrm_policy_unlock_afinfo(struct xfrm_policy_afinfo *afinfo);
+static inline int
+__xfrm4_selector_match(struct xfrm_selector *sel, struct flowi *fl)
+{
+ return addr_match(&fl->fl4_dst, &sel->daddr, sel->prefixlen_d) &&
+ addr_match(&fl->fl4_src, &sel->saddr, sel->prefixlen_s) &&
+ !((xfrm_flowi_dport(fl) ^ sel->dport) & sel->dport_mask) &&
+ !((xfrm_flowi_sport(fl) ^ sel->sport) & sel->sport_mask) &&
+ (fl->proto == sel->proto || !sel->proto) &&
+ (fl->oif == sel->ifindex || !sel->ifindex);
+}
+
+static inline int
+__xfrm6_selector_match(struct xfrm_selector *sel, struct flowi *fl)
+{
+ return addr_match(&fl->fl6_dst, &sel->daddr, sel->prefixlen_d) &&
+ addr_match(&fl->fl6_src, &sel->saddr, sel->prefixlen_s) &&
+ !((xfrm_flowi_dport(fl) ^ sel->dport) & sel->dport_mask) &&
+ !((xfrm_flowi_sport(fl) ^ sel->sport) & sel->sport_mask) &&
+ (fl->proto == sel->proto || !sel->proto) &&
+ (fl->oif == sel->ifindex || !sel->ifindex);
+}
+
+int xfrm_selector_match(struct xfrm_selector *sel, struct flowi *fl,
+ unsigned short family)
+{
+ switch (family) {
+ case AF_INET:
+ return __xfrm4_selector_match(sel, fl);
+ case AF_INET6:
+ return __xfrm6_selector_match(sel, fl);
+ }
+ return 0;
+}
+
int xfrm_register_type(struct xfrm_type *type, unsigned short family)
{
struct xfrm_policy_afinfo *afinfo = xfrm_policy_lock_afinfo(family);
@@ -1177,6 +1211,7 @@ xfrm_tmpl_resolve_one(struct xfrm_policy *policy, struct flowi *fl,
if (tmpl->mode == XFRM_MODE_TUNNEL) {
remote = &tmpl->id.daddr;
local = &tmpl->saddr;
+ family = tmpl->encap_family;
if (xfrm_addr_any(local, family)) {
error = xfrm_get_saddr(&tmp, remote, family);
if (error)
@@ -1894,7 +1929,8 @@ int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first,
if (fl && !xfrm_selector_match(&dst->xfrm->sel, fl, family))
return 0;
- if (fl && !security_xfrm_flow_state_match(fl, dst->xfrm, pol))
+ if (fl && pol &&
+ !security_xfrm_state_pol_flow_match(dst->xfrm, pol, fl))
return 0;
if (dst->xfrm->km.state != XFRM_STATE_VALID)
return 0;
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 40c527179843..da54a64ccfa3 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -1304,7 +1304,7 @@ int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol)
}
EXPORT_SYMBOL(km_query);
-int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport)
+int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport)
{
int err = -EINVAL;
struct xfrm_mgr *km;
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index c4cde57d9216..6f97665983d2 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -244,11 +244,10 @@ static int attach_one_algo(struct xfrm_algo **algpp, u8 *props,
*props = algo->desc.sadb_alg_id;
len = sizeof(*ualg) + (ualg->alg_key_len + 7U) / 8;
- p = kmalloc(len, GFP_KERNEL);
+ p = kmemdup(ualg, len, GFP_KERNEL);
if (!p)
return -ENOMEM;
- memcpy(p, ualg, len);
strcpy(p->alg_name, algo->name);
*algpp = p;
return 0;
@@ -263,11 +262,10 @@ static int attach_encap_tmpl(struct xfrm_encap_tmpl **encapp, struct rtattr *u_a
return 0;
uencap = RTA_DATA(rta);
- p = kmalloc(sizeof(*p), GFP_KERNEL);
+ p = kmemdup(uencap, sizeof(*p), GFP_KERNEL);
if (!p)
return -ENOMEM;
- memcpy(p, uencap, sizeof(*p));
*encapp = p;
return 0;
}
@@ -305,11 +303,10 @@ static int attach_one_addr(xfrm_address_t **addrpp, struct rtattr *u_arg)
return 0;
uaddrp = RTA_DATA(rta);
- p = kmalloc(sizeof(*p), GFP_KERNEL);
+ p = kmemdup(uaddrp, sizeof(*p), GFP_KERNEL);
if (!p)
return -ENOMEM;
- memcpy(p, uaddrp, sizeof(*p));
*addrpp = p;
return 0;
}
@@ -495,6 +492,7 @@ static struct xfrm_state *xfrm_user_state_lookup(struct xfrm_usersa_id *p,
goto out;
}
+ err = -ESRCH;
x = xfrm_state_lookup_byaddr(&p->daddr, saddr, p->proto,
p->family);
}
@@ -652,7 +650,6 @@ static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb,
if (!skb)
return ERR_PTR(-ENOMEM);
- NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
info.in_skb = in_skb;
info.out_skb = skb;
info.nlmsg_seq = seq;
@@ -772,7 +769,7 @@ out_noput:
return err;
}
-static int verify_policy_dir(__u8 dir)
+static int verify_policy_dir(u8 dir)
{
switch (dir) {
case XFRM_POLICY_IN:
@@ -787,7 +784,7 @@ static int verify_policy_dir(__u8 dir)
return 0;
}
-static int verify_policy_type(__u8 type)
+static int verify_policy_type(u8 type)
{
switch (type) {
case XFRM_POLICY_TYPE_MAIN:
@@ -861,6 +858,7 @@ static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut,
int i;
xp->xfrm_nr = nr;
+ xp->family = ut->family;
for (i = 0; i < nr; i++, ut++) {
struct xfrm_tmpl *t = &xp->xfrm_vec[i];
@@ -874,6 +872,7 @@ static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut,
t->aalgos = ut->aalgos;
t->ealgos = ut->ealgos;
t->calgos = ut->calgos;
+ t->encap_family = ut->family;
}
}
@@ -900,7 +899,7 @@ static int copy_from_user_policy_type(u8 *tp, struct rtattr **xfrma)
{
struct rtattr *rt = xfrma[XFRMA_POLICY_TYPE-1];
struct xfrm_userpolicy_type *upt;
- __u8 type = XFRM_POLICY_TYPE_MAIN;
+ u8 type = XFRM_POLICY_TYPE_MAIN;
int err;
if (rt) {
@@ -1027,7 +1026,7 @@ static int copy_to_user_tmpl(struct xfrm_policy *xp, struct sk_buff *skb)
struct xfrm_tmpl *kp = &xp->xfrm_vec[i];
memcpy(&up->id, &kp->id, sizeof(up->id));
- up->family = xp->family;
+ up->family = kp->encap_family;
memcpy(&up->saddr, &kp->saddr, sizeof(up->saddr));
up->reqid = kp->reqid;
up->mode = kp->mode;
@@ -1082,12 +1081,12 @@ static inline int copy_to_user_sec_ctx(struct xfrm_policy *xp, struct sk_buff *s
}
#ifdef CONFIG_XFRM_SUB_POLICY
-static int copy_to_user_policy_type(struct xfrm_policy *xp, struct sk_buff *skb)
+static int copy_to_user_policy_type(u8 type, struct sk_buff *skb)
{
struct xfrm_userpolicy_type upt;
memset(&upt, 0, sizeof(upt));
- upt.type = xp->type;
+ upt.type = type;
RTA_PUT(skb, XFRMA_POLICY_TYPE, sizeof(upt), &upt);
@@ -1098,7 +1097,7 @@ rtattr_failure:
}
#else
-static inline int copy_to_user_policy_type(struct xfrm_policy *xp, struct sk_buff *skb)
+static inline int copy_to_user_policy_type(u8 type, struct sk_buff *skb)
{
return 0;
}
@@ -1127,7 +1126,7 @@ static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr
goto nlmsg_failure;
if (copy_to_user_sec_ctx(xp, skb))
goto nlmsg_failure;
- if (copy_to_user_policy_type(xp, skb) < 0)
+ if (copy_to_user_policy_type(xp->type, skb) < 0)
goto nlmsg_failure;
nlh->nlmsg_len = skb->tail - b;
@@ -1170,7 +1169,6 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb,
if (!skb)
return ERR_PTR(-ENOMEM);
- NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
info.in_skb = in_skb;
info.out_skb = skb;
info.nlmsg_seq = seq;
@@ -1189,7 +1187,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
{
struct xfrm_policy *xp;
struct xfrm_userpolicy_id *p;
- __u8 type = XFRM_POLICY_TYPE_MAIN;
+ u8 type = XFRM_POLICY_TYPE_MAIN;
int err;
struct km_event c;
int delete;
@@ -1283,10 +1281,12 @@ static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, struct km_eve
id = NLMSG_DATA(nlh);
nlh->nlmsg_flags = 0;
- id->sa_id.daddr = x->id.daddr;
+ memcpy(&id->sa_id.daddr, &x->id.daddr,sizeof(x->id.daddr));
id->sa_id.spi = x->id.spi;
id->sa_id.family = x->props.family;
id->sa_id.proto = x->id.proto;
+ memcpy(&id->saddr, &x->props.saddr,sizeof(x->props.saddr));
+ id->reqid = x->props.reqid;
id->flags = c->data.aevent;
RTA_PUT(skb, XFRMA_REPLAY_VAL, sizeof(x->replay), &x->replay);
@@ -1407,7 +1407,7 @@ out:
static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
{
struct km_event c;
- __u8 type = XFRM_POLICY_TYPE_MAIN;
+ u8 type = XFRM_POLICY_TYPE_MAIN;
int err;
err = copy_from_user_policy_type(&type, (struct rtattr **)xfrma);
@@ -1428,7 +1428,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, void *
struct xfrm_policy *xp;
struct xfrm_user_polexpire *up = NLMSG_DATA(nlh);
struct xfrm_userpolicy_info *p = &up->pol;
- __u8 type = XFRM_POLICY_TYPE_MAIN;
+ u8 type = XFRM_POLICY_TYPE_MAIN;
int err = -ENOENT;
err = copy_from_user_policy_type(&type, (struct rtattr **)xfrma);
@@ -1907,7 +1907,7 @@ static int build_acquire(struct sk_buff *skb, struct xfrm_state *x,
goto nlmsg_failure;
if (copy_to_user_state_sec_ctx(x, skb))
goto nlmsg_failure;
- if (copy_to_user_policy_type(xp, skb) < 0)
+ if (copy_to_user_policy_type(xp->type, skb) < 0)
goto nlmsg_failure;
nlh->nlmsg_len = skb->tail - b;
@@ -2017,7 +2017,7 @@ static int build_polexpire(struct sk_buff *skb, struct xfrm_policy *xp,
goto nlmsg_failure;
if (copy_to_user_sec_ctx(xp, skb))
goto nlmsg_failure;
- if (copy_to_user_policy_type(xp, skb) < 0)
+ if (copy_to_user_policy_type(xp->type, skb) < 0)
goto nlmsg_failure;
upe->hard = !!hard;
@@ -2096,7 +2096,7 @@ static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *
copy_to_user_policy(xp, p, dir);
if (copy_to_user_tmpl(xp, skb) < 0)
goto nlmsg_failure;
- if (copy_to_user_policy_type(xp, skb) < 0)
+ if (copy_to_user_policy_type(xp->type, skb) < 0)
goto nlmsg_failure;
nlh->nlmsg_len = skb->tail - b;
@@ -2117,7 +2117,6 @@ static int xfrm_notify_policy_flush(struct km_event *c)
unsigned char *b;
int len = 0;
#ifdef CONFIG_XFRM_SUB_POLICY
- struct xfrm_userpolicy_type upt;
len += RTA_SPACE(sizeof(struct xfrm_userpolicy_type));
#endif
len += NLMSG_LENGTH(0);
@@ -2130,12 +2129,8 @@ static int xfrm_notify_policy_flush(struct km_event *c)
nlh = NLMSG_PUT(skb, c->pid, c->seq, XFRM_MSG_FLUSHPOLICY, 0);
nlh->nlmsg_flags = 0;
-
-#ifdef CONFIG_XFRM_SUB_POLICY
- memset(&upt, 0, sizeof(upt));
- upt.type = c->data.type;
- RTA_PUT(skb, XFRMA_POLICY_TYPE, sizeof(upt), &upt);
-#endif
+ if (copy_to_user_policy_type(c->data.type, skb) < 0)
+ goto nlmsg_failure;
nlh->nlmsg_len = skb->tail - b;
@@ -2143,9 +2138,6 @@ static int xfrm_notify_policy_flush(struct km_event *c)
return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC);
nlmsg_failure:
-#ifdef CONFIG_XFRM_SUB_POLICY
-rtattr_failure:
-#endif
kfree_skb(skb);
return -1;
}
diff --git a/scripts/gen_initramfs_list.sh b/scripts/gen_initramfs_list.sh
index 331c079f029b..4c723fd18648 100644
--- a/scripts/gen_initramfs_list.sh
+++ b/scripts/gen_initramfs_list.sh
@@ -158,7 +158,7 @@ unknown_option() {
}
list_header() {
- echo "deps_initramfs := \\"
+ :
}
header() {
@@ -227,6 +227,7 @@ arg="$1"
case "$arg" in
"-l") # files included in initramfs - used by kbuild
dep_list="list_"
+ echo "deps_initramfs := \\"
shift
;;
"-o") # generate gzipped cpio image named $1
diff --git a/scripts/kconfig/lxdialog/util.c b/scripts/kconfig/lxdialog/util.c
index ebc781b493d7..d54440fc166c 100644
--- a/scripts/kconfig/lxdialog/util.c
+++ b/scripts/kconfig/lxdialog/util.c
@@ -221,16 +221,14 @@ static void init_dialog_colors(void)
*/
static void color_setup(const char *theme)
{
- if (set_theme(theme)) {
- if (has_colors()) { /* Terminal supports color? */
- start_color();
- init_dialog_colors();
- }
- }
- else
- {
+ int use_color;
+
+ use_color = set_theme(theme);
+ if (use_color && has_colors()) {
+ start_color();
+ init_dialog_colors();
+ } else
set_mono_theme();
- }
}
/*
diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc
index 393f3749f330..338bdea96541 100644
--- a/scripts/kconfig/qconf.cc
+++ b/scripts/kconfig/qconf.cc
@@ -1259,6 +1259,7 @@ void ConfigSearchWindow::search(void)
* Construct the complete config widget
*/
ConfigMainWindow::ConfigMainWindow(void)
+ : searchWindow(0)
{
QMenuBar* menu;
bool ok;
diff --git a/security/dummy.c b/security/dummy.c
index 43874c1e6e23..558795b237d6 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -828,6 +828,11 @@ static inline void dummy_inet_csk_clone(struct sock *newsk,
{
}
+static inline void dummy_inet_conn_established(struct sock *sk,
+ struct sk_buff *skb)
+{
+}
+
static inline void dummy_req_classify_flow(const struct request_sock *req,
struct flowi *fl)
{
@@ -836,7 +841,7 @@ static inline void dummy_req_classify_flow(const struct request_sock *req,
#ifdef CONFIG_SECURITY_NETWORK_XFRM
static int dummy_xfrm_policy_alloc_security(struct xfrm_policy *xp,
- struct xfrm_user_sec_ctx *sec_ctx, struct sock *sk)
+ struct xfrm_user_sec_ctx *sec_ctx)
{
return 0;
}
@@ -856,7 +861,7 @@ static int dummy_xfrm_policy_delete_security(struct xfrm_policy *xp)
}
static int dummy_xfrm_state_alloc_security(struct xfrm_state *x,
- struct xfrm_user_sec_ctx *sec_ctx, struct xfrm_sec_ctx *pol, u32 secid)
+ struct xfrm_user_sec_ctx *sec_ctx, u32 secid)
{
return 0;
}
@@ -881,12 +886,6 @@ static int dummy_xfrm_state_pol_flow_match(struct xfrm_state *x,
return 1;
}
-static int dummy_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm,
- struct xfrm_policy *xp)
-{
- return 1;
-}
-
static int dummy_xfrm_decode_session(struct sk_buff *skb, u32 *fl, int ckall)
{
return 0;
@@ -1108,6 +1107,7 @@ void security_fixup_ops (struct security_operations *ops)
set_to_dummy_if_null(ops, sock_graft);
set_to_dummy_if_null(ops, inet_conn_request);
set_to_dummy_if_null(ops, inet_csk_clone);
+ set_to_dummy_if_null(ops, inet_conn_established);
set_to_dummy_if_null(ops, req_classify_flow);
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -1120,7 +1120,6 @@ void security_fixup_ops (struct security_operations *ops)
set_to_dummy_if_null(ops, xfrm_state_delete_security);
set_to_dummy_if_null(ops, xfrm_policy_lookup);
set_to_dummy_if_null(ops, xfrm_state_pol_flow_match);
- set_to_dummy_if_null(ops, xfrm_flow_state_match);
set_to_dummy_if_null(ops, xfrm_decode_session);
#endif /* CONFIG_SECURITY_NETWORK_XFRM */
#ifdef CONFIG_KEYS
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index a300702da527..74c0319c417e 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -32,12 +32,7 @@
#include "avc.h"
#include "avc_ss.h"
-static const struct av_perm_to_string
-{
- u16 tclass;
- u32 value;
- const char *name;
-} av_perm_to_string[] = {
+static const struct av_perm_to_string av_perm_to_string[] = {
#define S_(c, v, s) { c, v, s },
#include "av_perm_to_string.h"
#undef S_
@@ -57,17 +52,21 @@ static const char *class_to_string[] = {
#undef TE_
#undef S_
-static const struct av_inherit
-{
- u16 tclass;
- const char **common_pts;
- u32 common_base;
-} av_inherit[] = {
+static const struct av_inherit av_inherit[] = {
#define S_(c, i, b) { c, common_##i##_perm_to_string, b },
#include "av_inherit.h"
#undef S_
};
+const struct selinux_class_perm selinux_class_perm = {
+ av_perm_to_string,
+ ARRAY_SIZE(av_perm_to_string),
+ class_to_string,
+ ARRAY_SIZE(class_to_string),
+ av_inherit,
+ ARRAY_SIZE(av_inherit)
+};
+
#define AVC_CACHE_SLOTS 512
#define AVC_DEF_CACHE_THRESHOLD 512
#define AVC_CACHE_RECLAIM 16
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 8ab5679a37a3..a29d78d3f44c 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -58,6 +58,7 @@
#include <linux/netlink.h>
#include <linux/tcp.h>
#include <linux/udp.h>
+#include <linux/dccp.h>
#include <linux/quota.h>
#include <linux/un.h> /* for Unix socket types */
#include <net/af_unix.h> /* for Unix socket types */
@@ -751,6 +752,8 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc
return SECCLASS_UDP_SOCKET;
else
return SECCLASS_RAWIP_SOCKET;
+ case SOCK_DCCP:
+ return SECCLASS_DCCP_SOCKET;
default:
return SECCLASS_RAWIP_SOCKET;
}
@@ -1754,7 +1757,8 @@ static inline void flush_unauthorized_files(struct files_struct * files)
get_file(devnull);
} else {
devnull = dentry_open(dget(selinux_null), mntget(selinuxfs_mount), O_RDWR);
- if (!devnull) {
+ if (IS_ERR(devnull)) {
+ devnull = NULL;
put_unused_fd(fd);
fput(file);
continue;
@@ -2888,7 +2892,8 @@ static void selinux_task_to_inode(struct task_struct *p,
}
/* Returns error only if unable to parse addresses */
-static int selinux_parse_skb_ipv4(struct sk_buff *skb, struct avc_audit_data *ad)
+static int selinux_parse_skb_ipv4(struct sk_buff *skb,
+ struct avc_audit_data *ad, u8 *proto)
{
int offset, ihlen, ret = -EINVAL;
struct iphdr _iph, *ih;
@@ -2906,6 +2911,9 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb, struct avc_audit_data *ad
ad->u.net.v4info.daddr = ih->daddr;
ret = 0;
+ if (proto)
+ *proto = ih->protocol;
+
switch (ih->protocol) {
case IPPROTO_TCP: {
struct tcphdr _tcph, *th;
@@ -2939,6 +2947,22 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb, struct avc_audit_data *ad
break;
}
+ case IPPROTO_DCCP: {
+ struct dccp_hdr _dccph, *dh;
+
+ if (ntohs(ih->frag_off) & IP_OFFSET)
+ break;
+
+ offset += ihlen;
+ dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
+ if (dh == NULL)
+ break;
+
+ ad->u.net.sport = dh->dccph_sport;
+ ad->u.net.dport = dh->dccph_dport;
+ break;
+ }
+
default:
break;
}
@@ -2949,7 +2973,8 @@ out:
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
/* Returns error only if unable to parse addresses */
-static int selinux_parse_skb_ipv6(struct sk_buff *skb, struct avc_audit_data *ad)
+static int selinux_parse_skb_ipv6(struct sk_buff *skb,
+ struct avc_audit_data *ad, u8 *proto)
{
u8 nexthdr;
int ret = -EINVAL, offset;
@@ -2970,6 +2995,9 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb, struct avc_audit_data *ad
if (offset < 0)
goto out;
+ if (proto)
+ *proto = nexthdr;
+
switch (nexthdr) {
case IPPROTO_TCP: {
struct tcphdr _tcph, *th;
@@ -2995,6 +3023,18 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb, struct avc_audit_data *ad
break;
}
+ case IPPROTO_DCCP: {
+ struct dccp_hdr _dccph, *dh;
+
+ dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
+ if (dh == NULL)
+ break;
+
+ ad->u.net.sport = dh->dccph_sport;
+ ad->u.net.dport = dh->dccph_dport;
+ break;
+ }
+
/* includes fragments */
default:
break;
@@ -3006,13 +3046,13 @@ out:
#endif /* IPV6 */
static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
- char **addrp, int *len, int src)
+ char **addrp, int *len, int src, u8 *proto)
{
int ret = 0;
switch (ad->u.net.family) {
case PF_INET:
- ret = selinux_parse_skb_ipv4(skb, ad);
+ ret = selinux_parse_skb_ipv4(skb, ad, proto);
if (ret || !addrp)
break;
*len = 4;
@@ -3022,7 +3062,7 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
case PF_INET6:
- ret = selinux_parse_skb_ipv6(skb, ad);
+ ret = selinux_parse_skb_ipv6(skb, ad, proto);
if (ret || !addrp)
break;
*len = 16;
@@ -3100,9 +3140,7 @@ static int selinux_socket_post_create(struct socket *sock, int family,
if (sock->sk) {
sksec = sock->sk->sk_security;
sksec->sid = isec->sid;
- err = selinux_netlbl_socket_post_create(sock,
- family,
- isec->sid);
+ err = selinux_netlbl_socket_post_create(sock);
}
return err;
@@ -3179,7 +3217,11 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
case SECCLASS_UDP_SOCKET:
node_perm = UDP_SOCKET__NODE_BIND;
break;
-
+
+ case SECCLASS_DCCP_SOCKET:
+ node_perm = DCCP_SOCKET__NODE_BIND;
+ break;
+
default:
node_perm = RAWIP_SOCKET__NODE_BIND;
break;
@@ -3217,16 +3259,17 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
return err;
/*
- * If a TCP socket, check name_connect permission for the port.
+ * If a TCP or DCCP socket, check name_connect permission for the port.
*/
isec = SOCK_INODE(sock)->i_security;
- if (isec->sclass == SECCLASS_TCP_SOCKET) {
+ if (isec->sclass == SECCLASS_TCP_SOCKET ||
+ isec->sclass == SECCLASS_DCCP_SOCKET) {
struct sock *sk = sock->sk;
struct avc_audit_data ad;
struct sockaddr_in *addr4 = NULL;
struct sockaddr_in6 *addr6 = NULL;
unsigned short snum;
- u32 sid;
+ u32 sid, perm;
if (sk->sk_family == PF_INET) {
addr4 = (struct sockaddr_in *)address;
@@ -3245,11 +3288,13 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
if (err)
goto out;
+ perm = (isec->sclass == SECCLASS_TCP_SOCKET) ?
+ TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
+
AVC_AUDIT_DATA_INIT(&ad,NET);
ad.u.net.dport = htons(snum);
ad.u.net.family = sk->sk_family;
- err = avc_has_perm(isec->sid, sid, isec->sclass,
- TCP_SOCKET__NAME_CONNECT, &ad);
+ err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad);
if (err)
goto out;
}
@@ -3437,7 +3482,13 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
node_perm = NODE__TCP_RECV;
recv_perm = TCP_SOCKET__RECV_MSG;
break;
-
+
+ case SECCLASS_DCCP_SOCKET:
+ netif_perm = NETIF__DCCP_RECV;
+ node_perm = NODE__DCCP_RECV;
+ recv_perm = DCCP_SOCKET__RECV_MSG;
+ break;
+
default:
netif_perm = NETIF__RAWIP_RECV;
node_perm = NODE__RAWIP_RECV;
@@ -3493,7 +3544,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]";
ad.u.net.family = family;
- err = selinux_parse_skb(skb, &ad, &addrp, &len, 1);
+ err = selinux_parse_skb(skb, &ad, &addrp, &len, 1, NULL);
if (err)
goto out;
@@ -3523,25 +3574,16 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op
u32 scontext_len;
struct sk_security_struct *ssec;
struct inode_security_struct *isec;
- u32 peer_sid = 0;
+ u32 peer_sid = SECSID_NULL;
isec = SOCK_INODE(sock)->i_security;
- /* if UNIX_STREAM check peer_sid, if TCP check dst for labelled sa */
- if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET) {
+ if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
+ isec->sclass == SECCLASS_TCP_SOCKET) {
ssec = sock->sk->sk_security;
peer_sid = ssec->peer_sid;
}
- else if (isec->sclass == SECCLASS_TCP_SOCKET) {
- peer_sid = selinux_netlbl_socket_getpeersec_stream(sock);
- if (peer_sid == SECSID_NULL)
- peer_sid = selinux_socket_getpeer_stream(sock->sk);
- if (peer_sid == SECSID_NULL) {
- err = -ENOPROTOOPT;
- goto out;
- }
- }
- else {
+ if (peer_sid == SECSID_NULL) {
err = -ENOPROTOOPT;
goto out;
}
@@ -3573,13 +3615,12 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *
u32 peer_secid = SECSID_NULL;
int err = 0;
- if (sock && (sock->sk->sk_family == PF_UNIX))
+ if (sock && sock->sk->sk_family == PF_UNIX)
selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid);
- else if (skb) {
- peer_secid = selinux_netlbl_socket_getpeersec_dgram(skb);
- if (peer_secid == SECSID_NULL)
- peer_secid = selinux_socket_getpeer_dgram(skb);
- }
+ else if (skb)
+ security_skb_extlbl_sid(skb,
+ SECINITSID_UNLABELED,
+ &peer_secid);
if (peer_secid == SECSID_NULL)
err = -EINVAL;
@@ -3606,7 +3647,7 @@ static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
newssec->sid = ssec->sid;
newssec->peer_sid = ssec->peer_sid;
- selinux_netlbl_sk_clone_security(ssec, newssec);
+ selinux_netlbl_sk_security_clone(ssec, newssec);
}
static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
@@ -3640,17 +3681,10 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
u32 newsid;
u32 peersid;
- newsid = selinux_netlbl_inet_conn_request(skb, sksec->sid);
- if (newsid != SECSID_NULL) {
- req->secid = newsid;
- return 0;
- }
-
- err = selinux_xfrm_decode_session(skb, &peersid, 0);
- BUG_ON(err);
-
+ security_skb_extlbl_sid(skb, SECINITSID_UNLABELED, &peersid);
if (peersid == SECSID_NULL) {
req->secid = sksec->sid;
+ req->peer_secid = SECSID_NULL;
return 0;
}
@@ -3659,6 +3693,7 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
return err;
req->secid = newsid;
+ req->peer_secid = peersid;
return 0;
}
@@ -3668,12 +3703,23 @@ static void selinux_inet_csk_clone(struct sock *newsk,
struct sk_security_struct *newsksec = newsk->sk_security;
newsksec->sid = req->secid;
+ newsksec->peer_sid = req->peer_secid;
/* NOTE: Ideally, we should also get the isec->sid for the
new socket in sync, but we don't have the isec available yet.
So we will wait until sock_graft to do it, by which
time it will have been created and available. */
- selinux_netlbl_sk_security_init(newsksec, req->rsk_ops->family);
+ /* We don't need to take any sort of lock here as we are the only
+ * thread with access to newsksec */
+ selinux_netlbl_sk_security_reset(newsksec, req->rsk_ops->family);
+}
+
+static void selinux_inet_conn_established(struct sock *sk,
+ struct sk_buff *skb)
+{
+ struct sk_security_struct *sksec = sk->sk_security;
+
+ security_skb_extlbl_sid(skb, SECINITSID_UNLABELED, &sksec->peer_sid);
}
static void selinux_req_classify_flow(const struct request_sock *req,
@@ -3756,7 +3802,13 @@ static int selinux_ip_postroute_last_compat(struct sock *sk, struct net_device *
node_perm = NODE__TCP_SEND;
send_perm = TCP_SOCKET__SEND_MSG;
break;
-
+
+ case SECCLASS_DCCP_SOCKET:
+ netif_perm = NETIF__DCCP_SEND;
+ node_perm = NODE__DCCP_SEND;
+ send_perm = DCCP_SOCKET__SEND_MSG;
+ break;
+
default:
netif_perm = NETIF__RAWIP_SEND;
node_perm = NODE__RAWIP_SEND;
@@ -3807,6 +3859,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
struct avc_audit_data ad;
struct net_device *dev = (struct net_device *)out;
struct sk_security_struct *sksec;
+ u8 proto;
sk = skb->sk;
if (!sk)
@@ -3818,7 +3871,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
ad.u.net.netif = dev->name;
ad.u.net.family = family;
- err = selinux_parse_skb(skb, &ad, &addrp, &len, 0);
+ err = selinux_parse_skb(skb, &ad, &addrp, &len, 0, &proto);
if (err)
goto out;
@@ -3832,7 +3885,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
if (err)
goto out;
- err = selinux_xfrm_postroute_last(sksec->sid, skb, &ad);
+ err = selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto);
out:
return err ? NF_DROP : NF_ACCEPT;
}
@@ -4738,6 +4791,7 @@ static struct security_operations selinux_ops = {
.sock_graft = selinux_sock_graft,
.inet_conn_request = selinux_inet_conn_request,
.inet_csk_clone = selinux_inet_csk_clone,
+ .inet_conn_established = selinux_inet_conn_established,
.req_classify_flow = selinux_req_classify_flow,
#ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -4750,7 +4804,6 @@ static struct security_operations selinux_ops = {
.xfrm_state_delete_security = selinux_xfrm_state_delete,
.xfrm_policy_lookup = selinux_xfrm_policy_lookup,
.xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match,
- .xfrm_flow_state_match = selinux_xfrm_flow_state_match,
.xfrm_decode_session = selinux_xfrm_decode_session,
#endif
diff --git a/security/selinux/include/av_inherit.h b/security/selinux/include/av_inherit.h
index a68fdd55597f..8377a4ba3b95 100644
--- a/security/selinux/include/av_inherit.h
+++ b/security/selinux/include/av_inherit.h
@@ -30,3 +30,4 @@
S_(SECCLASS_NETLINK_DNRT_SOCKET, socket, 0x00400000UL)
S_(SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET, socket, 0x00400000UL)
S_(SECCLASS_APPLETALK_SOCKET, socket, 0x00400000UL)
+ S_(SECCLASS_DCCP_SOCKET, socket, 0x00400000UL)
diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
index 09fc8a2345eb..ad9fb2d69b50 100644
--- a/security/selinux/include/av_perm_to_string.h
+++ b/security/selinux/include/av_perm_to_string.h
@@ -35,12 +35,16 @@
S_(SECCLASS_NODE, NODE__RAWIP_RECV, "rawip_recv")
S_(SECCLASS_NODE, NODE__RAWIP_SEND, "rawip_send")
S_(SECCLASS_NODE, NODE__ENFORCE_DEST, "enforce_dest")
+ S_(SECCLASS_NODE, NODE__DCCP_RECV, "dccp_recv")
+ S_(SECCLASS_NODE, NODE__DCCP_SEND, "dccp_send")
S_(SECCLASS_NETIF, NETIF__TCP_RECV, "tcp_recv")
S_(SECCLASS_NETIF, NETIF__TCP_SEND, "tcp_send")
S_(SECCLASS_NETIF, NETIF__UDP_RECV, "udp_recv")
S_(SECCLASS_NETIF, NETIF__UDP_SEND, "udp_send")
S_(SECCLASS_NETIF, NETIF__RAWIP_RECV, "rawip_recv")
S_(SECCLASS_NETIF, NETIF__RAWIP_SEND, "rawip_send")
+ S_(SECCLASS_NETIF, NETIF__DCCP_RECV, "dccp_recv")
+ S_(SECCLASS_NETIF, NETIF__DCCP_SEND, "dccp_send")
S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__CONNECTTO, "connectto")
S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__NEWCONN, "newconn")
S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__ACCEPTFROM, "acceptfrom")
@@ -252,3 +256,7 @@
S_(SECCLASS_KEY, KEY__LINK, "link")
S_(SECCLASS_KEY, KEY__SETATTR, "setattr")
S_(SECCLASS_KEY, KEY__CREATE, "create")
+ S_(SECCLASS_CONTEXT, CONTEXT__TRANSLATE, "translate")
+ S_(SECCLASS_CONTEXT, CONTEXT__CONTAINS, "contains")
+ S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NODE_BIND, "node_bind")
+ S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NAME_CONNECT, "name_connect")
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
index 81f4f526c8b1..2de4b5fe3aa1 100644
--- a/security/selinux/include/av_permissions.h
+++ b/security/selinux/include/av_permissions.h
@@ -312,6 +312,8 @@
#define NODE__RAWIP_RECV 0x00000010UL
#define NODE__RAWIP_SEND 0x00000020UL
#define NODE__ENFORCE_DEST 0x00000040UL
+#define NODE__DCCP_RECV 0x00000080UL
+#define NODE__DCCP_SEND 0x00000100UL
#define NETIF__TCP_RECV 0x00000001UL
#define NETIF__TCP_SEND 0x00000002UL
@@ -319,6 +321,8 @@
#define NETIF__UDP_SEND 0x00000008UL
#define NETIF__RAWIP_RECV 0x00000010UL
#define NETIF__RAWIP_SEND 0x00000020UL
+#define NETIF__DCCP_RECV 0x00000040UL
+#define NETIF__DCCP_SEND 0x00000080UL
#define NETLINK_SOCKET__IOCTL 0x00000001UL
#define NETLINK_SOCKET__READ 0x00000002UL
@@ -970,3 +974,31 @@
#define KEY__LINK 0x00000010UL
#define KEY__SETATTR 0x00000020UL
#define KEY__CREATE 0x00000040UL
+
+#define CONTEXT__TRANSLATE 0x00000001UL
+#define CONTEXT__CONTAINS 0x00000002UL
+
+#define DCCP_SOCKET__IOCTL 0x00000001UL
+#define DCCP_SOCKET__READ 0x00000002UL
+#define DCCP_SOCKET__WRITE 0x00000004UL
+#define DCCP_SOCKET__CREATE 0x00000008UL
+#define DCCP_SOCKET__GETATTR 0x00000010UL
+#define DCCP_SOCKET__SETATTR 0x00000020UL
+#define DCCP_SOCKET__LOCK 0x00000040UL
+#define DCCP_SOCKET__RELABELFROM 0x00000080UL
+#define DCCP_SOCKET__RELABELTO 0x00000100UL
+#define DCCP_SOCKET__APPEND 0x00000200UL
+#define DCCP_SOCKET__BIND 0x00000400UL
+#define DCCP_SOCKET__CONNECT 0x00000800UL
+#define DCCP_SOCKET__LISTEN 0x00001000UL
+#define DCCP_SOCKET__ACCEPT 0x00002000UL
+#define DCCP_SOCKET__GETOPT 0x00004000UL
+#define DCCP_SOCKET__SETOPT 0x00008000UL
+#define DCCP_SOCKET__SHUTDOWN 0x00010000UL
+#define DCCP_SOCKET__RECVFROM 0x00020000UL
+#define DCCP_SOCKET__SENDTO 0x00040000UL
+#define DCCP_SOCKET__RECV_MSG 0x00080000UL
+#define DCCP_SOCKET__SEND_MSG 0x00100000UL
+#define DCCP_SOCKET__NAME_BIND 0x00200000UL
+#define DCCP_SOCKET__NODE_BIND 0x00400000UL
+#define DCCP_SOCKET__NAME_CONNECT 0x00800000UL
diff --git a/security/selinux/include/avc_ss.h b/security/selinux/include/avc_ss.h
index 450a2831e2e3..ff869e8b6f4a 100644
--- a/security/selinux/include/avc_ss.h
+++ b/security/selinux/include/avc_ss.h
@@ -10,5 +10,29 @@
int avc_ss_reset(u32 seqno);
+struct av_perm_to_string
+{
+ u16 tclass;
+ u32 value;
+ const char *name;
+};
+
+struct av_inherit
+{
+ u16 tclass;
+ const char **common_pts;
+ u32 common_base;
+};
+
+struct selinux_class_perm
+{
+ const struct av_perm_to_string *av_perm_to_string;
+ u32 av_pts_len;
+ const char **class_to_string;
+ u32 cts_len;
+ const struct av_inherit *av_inherit;
+ u32 av_inherit_len;
+};
+
#endif /* _SELINUX_AVC_SS_H_ */
diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h
index 24303b61309f..9f3ebb1bfae6 100644
--- a/security/selinux/include/class_to_string.h
+++ b/security/selinux/include/class_to_string.h
@@ -61,3 +61,5 @@
S_("appletalk_socket")
S_("packet")
S_("key")
+ S_("context")
+ S_("dccp_socket")
diff --git a/security/selinux/include/flask.h b/security/selinux/include/flask.h
index 95887aed2a68..67cef371ee00 100644
--- a/security/selinux/include/flask.h
+++ b/security/selinux/include/flask.h
@@ -63,6 +63,8 @@
#define SECCLASS_APPLETALK_SOCKET 56
#define SECCLASS_PACKET 57
#define SECCLASS_KEY 58
+#define SECCLASS_CONTEXT 59
+#define SECCLASS_DCCP_SOCKET 60
/*
* Security identifier indices for initial entities
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index ef2267fea8bd..91b88f0ba20c 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -23,6 +23,7 @@
#include <linux/fs.h>
#include <linux/binfmts.h>
#include <linux/in.h>
+#include <linux/spinlock.h>
#include "flask.h"
#include "avc.h"
@@ -108,6 +109,7 @@ struct sk_security_struct {
NLBL_REQUIRE,
NLBL_LABELED,
} nlbl_state;
+ spinlock_t nlbl_lock; /* protects nlbl_state */
#endif
};
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 1ef79172cc8c..210eec77e7ff 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -34,6 +34,8 @@
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_RANGETRANS
#endif
+struct sk_buff;
+
extern int selinux_enabled;
extern int selinux_mls_enabled;
@@ -80,6 +82,8 @@ int security_netif_sid(char *name, u32 *if_sid,
int security_node_sid(u16 domain, void *addr, u32 addrlen,
u32 *out_sid);
+void security_skb_extlbl_sid(struct sk_buff *skb, u32 base_sid, u32 *sid);
+
int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
u16 tclass);
diff --git a/security/selinux/include/selinux_netlabel.h b/security/selinux/include/selinux_netlabel.h
index 9de10cc2cef2..2a732c9033e3 100644
--- a/security/selinux/include/selinux_netlabel.h
+++ b/security/selinux/include/selinux_netlabel.h
@@ -38,19 +38,17 @@
#ifdef CONFIG_NETLABEL
void selinux_netlbl_cache_invalidate(void);
-int selinux_netlbl_socket_post_create(struct socket *sock,
- int sock_family,
- u32 sid);
+int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u32 base_sid, u32 *sid);
+int selinux_netlbl_socket_post_create(struct socket *sock);
void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock);
-u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb, u32 sock_sid);
int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
struct sk_buff *skb,
struct avc_audit_data *ad);
-u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock);
-u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb);
+void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec,
+ int family);
void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec,
int family);
-void selinux_netlbl_sk_clone_security(struct sk_security_struct *ssec,
+void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec,
struct sk_security_struct *newssec);
int selinux_netlbl_inode_permission(struct inode *inode, int mask);
int selinux_netlbl_socket_setsockopt(struct socket *sock,
@@ -62,23 +60,23 @@ static inline void selinux_netlbl_cache_invalidate(void)
return;
}
-static inline int selinux_netlbl_socket_post_create(struct socket *sock,
- int sock_family,
- u32 sid)
+static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
+ u32 base_sid,
+ u32 *sid)
{
+ *sid = SECSID_NULL;
return 0;
}
-static inline void selinux_netlbl_sock_graft(struct sock *sk,
- struct socket *sock)
+static inline int selinux_netlbl_socket_post_create(struct socket *sock)
{
- return;
+ return 0;
}
-static inline u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb,
- u32 sock_sid)
+static inline void selinux_netlbl_sock_graft(struct sock *sk,
+ struct socket *sock)
{
- return SECSID_NULL;
+ return;
}
static inline int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
@@ -88,14 +86,11 @@ static inline int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
return 0;
}
-static inline u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock)
-{
- return SECSID_NULL;
-}
-
-static inline u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb)
+static inline void selinux_netlbl_sk_security_reset(
+ struct sk_security_struct *ssec,
+ int family)
{
- return SECSID_NULL;
+ return;
}
static inline void selinux_netlbl_sk_security_init(
@@ -105,7 +100,7 @@ static inline void selinux_netlbl_sk_security_init(
return;
}
-static inline void selinux_netlbl_sk_clone_security(
+static inline void selinux_netlbl_sk_security_clone(
struct sk_security_struct *ssec,
struct sk_security_struct *newssec)
{
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
index 526b28019aca..161eb571c82d 100644
--- a/security/selinux/include/xfrm.h
+++ b/security/selinux/include/xfrm.h
@@ -8,20 +8,17 @@
#define _SELINUX_XFRM_H_
int selinux_xfrm_policy_alloc(struct xfrm_policy *xp,
- struct xfrm_user_sec_ctx *sec_ctx, struct sock *sk);
+ struct xfrm_user_sec_ctx *sec_ctx);
int selinux_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new);
void selinux_xfrm_policy_free(struct xfrm_policy *xp);
int selinux_xfrm_policy_delete(struct xfrm_policy *xp);
int selinux_xfrm_state_alloc(struct xfrm_state *x,
- struct xfrm_user_sec_ctx *sec_ctx, struct xfrm_sec_ctx *pol, u32 secid);
+ struct xfrm_user_sec_ctx *sec_ctx, u32 secid);
void selinux_xfrm_state_free(struct xfrm_state *x);
int selinux_xfrm_state_delete(struct xfrm_state *x);
int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir);
int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
struct xfrm_policy *xp, struct flowi *fl);
-int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm,
- struct xfrm_policy *xp);
-
/*
* Extract the security blob from the sock (it's actually on the socket)
@@ -38,9 +35,7 @@ static inline struct inode_security_struct *get_sock_isec(struct sock *sk)
int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb,
struct avc_audit_data *ad);
int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
- struct avc_audit_data *ad);
-u32 selinux_socket_getpeer_stream(struct sock *sk);
-u32 selinux_socket_getpeer_dgram(struct sk_buff *skb);
+ struct avc_audit_data *ad, u8 proto);
int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall);
#else
static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
@@ -50,20 +45,11 @@ static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
}
static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
- struct avc_audit_data *ad)
+ struct avc_audit_data *ad, u8 proto)
{
return 0;
}
-static inline int selinux_socket_getpeer_stream(struct sock *sk)
-{
- return SECSID_NULL;
-}
-
-static inline int selinux_socket_getpeer_dgram(struct sk_buff *skb)
-{
- return SECSID_NULL;
-}
static inline int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
{
*sid = SECSID_NULL;
@@ -71,4 +57,10 @@ static inline int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int
}
#endif
+static inline void selinux_skb_xfrm_sid(struct sk_buff *skb, u32 *sid)
+{
+ int err = selinux_xfrm_decode_session(skb, sid, 0);
+ BUG_ON(err);
+}
+
#endif /* _SELINUX_XFRM_H_ */
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c
index b8f4d25cf335..ccfe8755735e 100644
--- a/security/selinux/nlmsgtab.c
+++ b/security/selinux/nlmsgtab.c
@@ -60,7 +60,6 @@ static struct nlmsg_perm nlmsg_route_perms[] =
{ RTM_DELACTION, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
{ RTM_GETACTION, NETLINK_ROUTE_SOCKET__NLMSG_READ },
{ RTM_NEWPREFIX, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
- { RTM_GETPREFIX, NETLINK_ROUTE_SOCKET__NLMSG_READ },
{ RTM_GETMULTICAST, NETLINK_ROUTE_SOCKET__NLMSG_READ },
{ RTM_GETANYCAST, NETLINK_ROUTE_SOCKET__NLMSG_READ },
{ RTM_GETNEIGHTBL, NETLINK_ROUTE_SOCKET__NLMSG_READ },
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c
index d539346ab3a2..ce492a6b38ed 100644
--- a/security/selinux/ss/ebitmap.c
+++ b/security/selinux/ss/ebitmap.c
@@ -6,7 +6,7 @@
/*
* Updated: Hewlett-Packard <paul.moore@hp.com>
*
- * Added ebitmap_export() and ebitmap_import()
+ * Added support to import/export the NetLabel category bitmap
*
* (c) Copyright Hewlett-Packard Development Company, L.P., 2006
*/
@@ -14,6 +14,7 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/errno.h>
+#include <net/netlabel.h>
#include "ebitmap.h"
#include "policydb.h"
@@ -67,141 +68,120 @@ int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src)
return 0;
}
+#ifdef CONFIG_NETLABEL
/**
- * ebitmap_export - Export an ebitmap to a unsigned char bitmap string
- * @src: the ebitmap to export
- * @dst: the resulting bitmap string
- * @dst_len: length of dst in bytes
+ * ebitmap_netlbl_export - Export an ebitmap into a NetLabel category bitmap
+ * @ebmap: the ebitmap to export
+ * @catmap: the NetLabel category bitmap
*
* Description:
- * Allocate a buffer at least src->highbit bits long and export the extensible
- * bitmap into the buffer. The bitmap string will be in little endian format,
- * i.e. LSB first. The value returned in dst_len may not the true size of the
- * buffer as the length of the buffer is rounded up to a multiple of MAPTYPE.
- * The caller must free the buffer when finished. Returns zero on success,
- * negative values on failure.
+ * Export a SELinux extensibile bitmap into a NetLabel category bitmap.
+ * Returns zero on success, negative values on error.
*
*/
-int ebitmap_export(const struct ebitmap *src,
- unsigned char **dst,
- size_t *dst_len)
+int ebitmap_netlbl_export(struct ebitmap *ebmap,
+ struct netlbl_lsm_secattr_catmap **catmap)
{
- size_t bitmap_len;
- unsigned char *bitmap;
- struct ebitmap_node *iter_node;
- MAPTYPE node_val;
- size_t bitmap_byte;
- unsigned char bitmask;
-
- if (src->highbit == 0) {
- *dst = NULL;
- *dst_len = 0;
+ struct ebitmap_node *e_iter = ebmap->node;
+ struct netlbl_lsm_secattr_catmap *c_iter;
+ u32 cmap_idx;
+
+ /* This function is a much simpler because SELinux's MAPTYPE happens
+ * to be the same as NetLabel's NETLBL_CATMAP_MAPTYPE, if MAPTYPE is
+ * changed from a u64 this function will most likely need to be changed
+ * as well. It's not ideal but I think the tradeoff in terms of
+ * neatness and speed is worth it. */
+
+ if (e_iter == NULL) {
+ *catmap = NULL;
return 0;
}
- bitmap_len = src->highbit / 8;
- if (src->highbit % 7)
- bitmap_len += 1;
-
- bitmap = kzalloc((bitmap_len & ~(sizeof(MAPTYPE) - 1)) +
- sizeof(MAPTYPE),
- GFP_ATOMIC);
- if (bitmap == NULL)
+ c_iter = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
+ if (c_iter == NULL)
return -ENOMEM;
+ *catmap = c_iter;
+ c_iter->startbit = e_iter->startbit & ~(NETLBL_CATMAP_SIZE - 1);
+
+ while (e_iter != NULL) {
+ if (e_iter->startbit >=
+ (c_iter->startbit + NETLBL_CATMAP_SIZE)) {
+ c_iter->next = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
+ if (c_iter->next == NULL)
+ goto netlbl_export_failure;
+ c_iter = c_iter->next;
+ c_iter->startbit = e_iter->startbit &
+ ~(NETLBL_CATMAP_SIZE - 1);
+ }
+ cmap_idx = (e_iter->startbit - c_iter->startbit) /
+ NETLBL_CATMAP_MAPSIZE;
+ c_iter->bitmap[cmap_idx] = e_iter->map;
+ e_iter = e_iter->next;
+ }
- iter_node = src->node;
- do {
- bitmap_byte = iter_node->startbit / 8;
- bitmask = 0x80;
- node_val = iter_node->map;
- do {
- if (bitmask == 0) {
- bitmap_byte++;
- bitmask = 0x80;
- }
- if (node_val & (MAPTYPE)0x01)
- bitmap[bitmap_byte] |= bitmask;
- node_val >>= 1;
- bitmask >>= 1;
- } while (node_val > 0);
- iter_node = iter_node->next;
- } while (iter_node);
-
- *dst = bitmap;
- *dst_len = bitmap_len;
return 0;
+
+netlbl_export_failure:
+ netlbl_secattr_catmap_free(*catmap);
+ return -ENOMEM;
}
/**
- * ebitmap_import - Import an unsigned char bitmap string into an ebitmap
- * @src: the bitmap string
- * @src_len: the bitmap length in bytes
- * @dst: the empty ebitmap
+ * ebitmap_netlbl_import - Import a NetLabel category bitmap into an ebitmap
+ * @ebmap: the ebitmap to export
+ * @catmap: the NetLabel category bitmap
*
* Description:
- * This function takes a little endian bitmap string in src and imports it into
- * the ebitmap pointed to by dst. Returns zero on success, negative values on
- * failure.
+ * Import a NetLabel category bitmap into a SELinux extensibile bitmap.
+ * Returns zero on success, negative values on error.
*
*/
-int ebitmap_import(const unsigned char *src,
- size_t src_len,
- struct ebitmap *dst)
+int ebitmap_netlbl_import(struct ebitmap *ebmap,
+ struct netlbl_lsm_secattr_catmap *catmap)
{
- size_t src_off = 0;
- size_t node_limit;
- struct ebitmap_node *node_new;
- struct ebitmap_node *node_last = NULL;
- u32 i_byte;
- u32 i_bit;
- unsigned char src_byte;
-
- while (src_off < src_len) {
- if (src_len - src_off >= sizeof(MAPTYPE)) {
- if (*(MAPTYPE *)&src[src_off] == 0) {
- src_off += sizeof(MAPTYPE);
- continue;
- }
- node_limit = sizeof(MAPTYPE);
- } else {
- for (src_byte = 0, i_byte = src_off;
- i_byte < src_len && src_byte == 0;
- i_byte++)
- src_byte |= src[i_byte];
- if (src_byte == 0)
- break;
- node_limit = src_len - src_off;
- }
+ struct ebitmap_node *e_iter = NULL;
+ struct ebitmap_node *emap_prev = NULL;
+ struct netlbl_lsm_secattr_catmap *c_iter = catmap;
+ u32 c_idx;
- node_new = kzalloc(sizeof(*node_new), GFP_ATOMIC);
- if (unlikely(node_new == NULL)) {
- ebitmap_destroy(dst);
- return -ENOMEM;
- }
- node_new->startbit = src_off * 8;
- for (i_byte = 0; i_byte < node_limit; i_byte++) {
- src_byte = src[src_off++];
- for (i_bit = i_byte * 8; src_byte != 0; i_bit++) {
- if (src_byte & 0x80)
- node_new->map |= MAPBIT << i_bit;
- src_byte <<= 1;
- }
- }
+ /* This function is a much simpler because SELinux's MAPTYPE happens
+ * to be the same as NetLabel's NETLBL_CATMAP_MAPTYPE, if MAPTYPE is
+ * changed from a u64 this function will most likely need to be changed
+ * as well. It's not ideal but I think the tradeoff in terms of
+ * neatness and speed is worth it. */
- if (node_last != NULL)
- node_last->next = node_new;
- else
- dst->node = node_new;
- node_last = node_new;
- }
+ do {
+ for (c_idx = 0; c_idx < NETLBL_CATMAP_MAPCNT; c_idx++) {
+ if (c_iter->bitmap[c_idx] == 0)
+ continue;
+
+ e_iter = kzalloc(sizeof(*e_iter), GFP_ATOMIC);
+ if (e_iter == NULL)
+ goto netlbl_import_failure;
+ if (emap_prev == NULL)
+ ebmap->node = e_iter;
+ else
+ emap_prev->next = e_iter;
+ emap_prev = e_iter;
- if (likely(node_last != NULL))
- dst->highbit = node_last->startbit + MAPSIZE;
+ e_iter->startbit = c_iter->startbit +
+ NETLBL_CATMAP_MAPSIZE * c_idx;
+ e_iter->map = c_iter->bitmap[c_idx];
+ }
+ c_iter = c_iter->next;
+ } while (c_iter != NULL);
+ if (e_iter != NULL)
+ ebmap->highbit = e_iter->startbit + MAPSIZE;
else
- ebitmap_init(dst);
+ ebitmap_destroy(ebmap);
return 0;
+
+netlbl_import_failure:
+ ebitmap_destroy(ebmap);
+ return -ENOMEM;
}
+#endif /* CONFIG_NETLABEL */
int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2)
{
diff --git a/security/selinux/ss/ebitmap.h b/security/selinux/ss/ebitmap.h
index da2d4651b10d..1270e34b61c1 100644
--- a/security/selinux/ss/ebitmap.h
+++ b/security/selinux/ss/ebitmap.h
@@ -14,6 +14,8 @@
#ifndef _SS_EBITMAP_H_
#define _SS_EBITMAP_H_
+#include <net/netlabel.h>
+
#define MAPTYPE u64 /* portion of bitmap in each node */
#define MAPSIZE (sizeof(MAPTYPE) * 8) /* number of bits in node bitmap */
#define MAPBIT 1ULL /* a bit in the node bitmap */
@@ -69,16 +71,28 @@ static inline int ebitmap_node_get_bit(struct ebitmap_node * n,
int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2);
int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src);
-int ebitmap_export(const struct ebitmap *src,
- unsigned char **dst,
- size_t *dst_len);
-int ebitmap_import(const unsigned char *src,
- size_t src_len,
- struct ebitmap *dst);
int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2);
int ebitmap_get_bit(struct ebitmap *e, unsigned long bit);
int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value);
void ebitmap_destroy(struct ebitmap *e);
int ebitmap_read(struct ebitmap *e, void *fp);
+#ifdef CONFIG_NETLABEL
+int ebitmap_netlbl_export(struct ebitmap *ebmap,
+ struct netlbl_lsm_secattr_catmap **catmap);
+int ebitmap_netlbl_import(struct ebitmap *ebmap,
+ struct netlbl_lsm_secattr_catmap *catmap);
+#else
+static inline int ebitmap_netlbl_export(struct ebitmap *ebmap,
+ struct netlbl_lsm_secattr_catmap **catmap)
+{
+ return -ENOMEM;
+}
+static inline int ebitmap_netlbl_import(struct ebitmap *ebmap,
+ struct netlbl_lsm_secattr_catmap *catmap)
+{
+ return -ENOMEM;
+}
+#endif
+
#endif /* _SS_EBITMAP_H_ */
diff --git a/security/selinux/ss/hashtab.c b/security/selinux/ss/hashtab.c
index 24e5ec957630..77b530c3bbce 100644
--- a/security/selinux/ss/hashtab.c
+++ b/security/selinux/ss/hashtab.c
@@ -8,8 +8,8 @@
#include <linux/errno.h>
#include "hashtab.h"
-struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, void *key),
- int (*keycmp)(struct hashtab *h, void *key1, void *key2),
+struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, const void *key),
+ int (*keycmp)(struct hashtab *h, const void *key1, const void *key2),
u32 size)
{
struct hashtab *p;
@@ -71,7 +71,7 @@ int hashtab_insert(struct hashtab *h, void *key, void *datum)
return 0;
}
-void *hashtab_search(struct hashtab *h, void *key)
+void *hashtab_search(struct hashtab *h, const void *key)
{
u32 hvalue;
struct hashtab_node *cur;
diff --git a/security/selinux/ss/hashtab.h b/security/selinux/ss/hashtab.h
index 4cc85816a718..7e2ff3e3c6d2 100644
--- a/security/selinux/ss/hashtab.h
+++ b/security/selinux/ss/hashtab.h
@@ -22,9 +22,9 @@ struct hashtab {
struct hashtab_node **htable; /* hash table */
u32 size; /* number of slots in hash table */
u32 nel; /* number of elements in hash table */
- u32 (*hash_value)(struct hashtab *h, void *key);
+ u32 (*hash_value)(struct hashtab *h, const void *key);
/* hash function */
- int (*keycmp)(struct hashtab *h, void *key1, void *key2);
+ int (*keycmp)(struct hashtab *h, const void *key1, const void *key2);
/* key comparison function */
};
@@ -39,8 +39,8 @@ struct hashtab_info {
* Returns NULL if insufficent space is available or
* the new hash table otherwise.
*/
-struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, void *key),
- int (*keycmp)(struct hashtab *h, void *key1, void *key2),
+struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, const void *key),
+ int (*keycmp)(struct hashtab *h, const void *key1, const void *key2),
u32 size);
/*
@@ -59,7 +59,7 @@ int hashtab_insert(struct hashtab *h, void *k, void *d);
* Returns NULL if no entry has the specified key or
* the datum of the entry otherwise.
*/
-void *hashtab_search(struct hashtab *h, void *k);
+void *hashtab_search(struct hashtab *h, const void *k);
/*
* Destroys the specified hash table.
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index 2cca8e251624..b4f682dc13ff 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -13,7 +13,7 @@
/*
* Updated: Hewlett-Packard <paul.moore@hp.com>
*
- * Added support to import/export the MLS label
+ * Added support to import/export the MLS label from NetLabel
*
* (c) Copyright Hewlett-Packard Development Company, L.P., 2006
*/
@@ -22,6 +22,7 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/errno.h>
+#include <net/netlabel.h>
#include "sidtab.h"
#include "mls.h"
#include "policydb.h"
@@ -571,163 +572,108 @@ int mls_compute_sid(struct context *scontext,
return -EINVAL;
}
+#ifdef CONFIG_NETLABEL
/**
- * mls_export_lvl - Export the MLS sensitivity levels
+ * mls_export_netlbl_lvl - Export the MLS sensitivity levels to NetLabel
* @context: the security context
- * @low: the low sensitivity level
- * @high: the high sensitivity level
+ * @secattr: the NetLabel security attributes
*
* Description:
- * Given the security context copy the low MLS sensitivity level into lvl_low
- * and the high sensitivity level in lvl_high. The MLS levels are only
- * exported if the pointers are not NULL, if they are NULL then that level is
- * not exported.
+ * Given the security context copy the low MLS sensitivity level into the
+ * NetLabel MLS sensitivity level field.
*
*/
-void mls_export_lvl(const struct context *context, u32 *low, u32 *high)
+void mls_export_netlbl_lvl(struct context *context,
+ struct netlbl_lsm_secattr *secattr)
{
if (!selinux_mls_enabled)
return;
- if (low != NULL)
- *low = context->range.level[0].sens - 1;
- if (high != NULL)
- *high = context->range.level[1].sens - 1;
+ secattr->mls_lvl = context->range.level[0].sens - 1;
+ secattr->flags |= NETLBL_SECATTR_MLS_LVL;
}
/**
- * mls_import_lvl - Import the MLS sensitivity levels
+ * mls_import_netlbl_lvl - Import the NetLabel MLS sensitivity levels
* @context: the security context
- * @low: the low sensitivity level
- * @high: the high sensitivity level
+ * @secattr: the NetLabel security attributes
*
* Description:
- * Given the security context and the two sensitivty levels, set the MLS levels
- * in the context according the two given as parameters. Returns zero on
- * success, negative values on failure.
+ * Given the security context and the NetLabel security attributes, copy the
+ * NetLabel MLS sensitivity level into the context.
*
*/
-void mls_import_lvl(struct context *context, u32 low, u32 high)
+void mls_import_netlbl_lvl(struct context *context,
+ struct netlbl_lsm_secattr *secattr)
{
if (!selinux_mls_enabled)
return;
- context->range.level[0].sens = low + 1;
- context->range.level[1].sens = high + 1;
+ context->range.level[0].sens = secattr->mls_lvl + 1;
+ context->range.level[1].sens = context->range.level[0].sens;
}
/**
- * mls_export_cat - Export the MLS categories
+ * mls_export_netlbl_cat - Export the MLS categories to NetLabel
* @context: the security context
- * @low: the low category
- * @low_len: length of the cat_low bitmap in bytes
- * @high: the high category
- * @high_len: length of the cat_high bitmap in bytes
+ * @secattr: the NetLabel security attributes
*
* Description:
- * Given the security context export the low MLS category bitmap into cat_low
- * and the high category bitmap into cat_high. The MLS categories are only
- * exported if the pointers are not NULL, if they are NULL then that level is
- * not exported. The caller is responsibile for freeing the memory when
- * finished. Returns zero on success, negative values on failure.
+ * Given the security context copy the low MLS categories into the NetLabel
+ * MLS category field. Returns zero on success, negative values on failure.
*
*/
-int mls_export_cat(const struct context *context,
- unsigned char **low,
- size_t *low_len,
- unsigned char **high,
- size_t *high_len)
+int mls_export_netlbl_cat(struct context *context,
+ struct netlbl_lsm_secattr *secattr)
{
- int rc = -EPERM;
+ int rc;
- if (!selinux_mls_enabled) {
- *low = NULL;
- *low_len = 0;
- *high = NULL;
- *high_len = 0;
+ if (!selinux_mls_enabled)
return 0;
- }
- if (low != NULL) {
- rc = ebitmap_export(&context->range.level[0].cat,
- low,
- low_len);
- if (rc != 0)
- goto export_cat_failure;
- }
- if (high != NULL) {
- rc = ebitmap_export(&context->range.level[1].cat,
- high,
- high_len);
- if (rc != 0)
- goto export_cat_failure;
- }
-
- return 0;
+ rc = ebitmap_netlbl_export(&context->range.level[0].cat,
+ &secattr->mls_cat);
+ if (rc == 0 && secattr->mls_cat != NULL)
+ secattr->flags |= NETLBL_SECATTR_MLS_CAT;
-export_cat_failure:
- if (low != NULL) {
- kfree(*low);
- *low = NULL;
- *low_len = 0;
- }
- if (high != NULL) {
- kfree(*high);
- *high = NULL;
- *high_len = 0;
- }
return rc;
}
/**
- * mls_import_cat - Import the MLS categories
+ * mls_import_netlbl_cat - Import the MLS categories from NetLabel
* @context: the security context
- * @low: the low category
- * @low_len: length of the cat_low bitmap in bytes
- * @high: the high category
- * @high_len: length of the cat_high bitmap in bytes
+ * @secattr: the NetLabel security attributes
*
* Description:
- * Given the security context and the two category bitmap strings import the
- * categories into the security context. The MLS categories are only imported
- * if the pointers are not NULL, if they are NULL they are skipped. Returns
- * zero on success, negative values on failure.
+ * Copy the NetLabel security attributes into the SELinux context; since the
+ * NetLabel security attribute only contains a single MLS category use it for
+ * both the low and high categories of the context. Returns zero on success,
+ * negative values on failure.
*
*/
-int mls_import_cat(struct context *context,
- const unsigned char *low,
- size_t low_len,
- const unsigned char *high,
- size_t high_len)
+int mls_import_netlbl_cat(struct context *context,
+ struct netlbl_lsm_secattr *secattr)
{
- int rc = -EPERM;
+ int rc;
if (!selinux_mls_enabled)
return 0;
- if (low != NULL) {
- rc = ebitmap_import(low,
- low_len,
- &context->range.level[0].cat);
- if (rc != 0)
- goto import_cat_failure;
- }
- if (high != NULL) {
- if (high == low)
- rc = ebitmap_cpy(&context->range.level[1].cat,
- &context->range.level[0].cat);
- else
- rc = ebitmap_import(high,
- high_len,
- &context->range.level[1].cat);
- if (rc != 0)
- goto import_cat_failure;
- }
+ rc = ebitmap_netlbl_import(&context->range.level[0].cat,
+ secattr->mls_cat);
+ if (rc != 0)
+ goto import_netlbl_cat_failure;
+
+ rc = ebitmap_cpy(&context->range.level[1].cat,
+ &context->range.level[0].cat);
+ if (rc != 0)
+ goto import_netlbl_cat_failure;
return 0;
-import_cat_failure:
+import_netlbl_cat_failure:
ebitmap_destroy(&context->range.level[0].cat);
ebitmap_destroy(&context->range.level[1].cat);
return rc;
}
+#endif /* CONFIG_NETLABEL */
diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h
index df6032c6d492..661d6fc76966 100644
--- a/security/selinux/ss/mls.h
+++ b/security/selinux/ss/mls.h
@@ -13,7 +13,7 @@
/*
* Updated: Hewlett-Packard <paul.moore@hp.com>
*
- * Added support to import/export the MLS label
+ * Added support to import/export the MLS label from NetLabel
*
* (c) Copyright Hewlett-Packard Development Company, L.P., 2006
*/
@@ -69,19 +69,37 @@ int mls_compute_sid(struct context *scontext,
int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
struct context *usercon);
-void mls_export_lvl(const struct context *context, u32 *low, u32 *high);
-void mls_import_lvl(struct context *context, u32 low, u32 high);
-
-int mls_export_cat(const struct context *context,
- unsigned char **low,
- size_t *low_len,
- unsigned char **high,
- size_t *high_len);
-int mls_import_cat(struct context *context,
- const unsigned char *low,
- size_t low_len,
- const unsigned char *high,
- size_t high_len);
+#ifdef CONFIG_NETLABEL
+void mls_export_netlbl_lvl(struct context *context,
+ struct netlbl_lsm_secattr *secattr);
+void mls_import_netlbl_lvl(struct context *context,
+ struct netlbl_lsm_secattr *secattr);
+int mls_export_netlbl_cat(struct context *context,
+ struct netlbl_lsm_secattr *secattr);
+int mls_import_netlbl_cat(struct context *context,
+ struct netlbl_lsm_secattr *secattr);
+#else
+static inline void mls_export_netlbl_lvl(struct context *context,
+ struct netlbl_lsm_secattr *secattr)
+{
+ return;
+}
+static inline void mls_import_netlbl_lvl(struct context *context,
+ struct netlbl_lsm_secattr *secattr)
+{
+ return;
+}
+static inline int mls_export_netlbl_cat(struct context *context,
+ struct netlbl_lsm_secattr *secattr)
+{
+ return -ENOMEM;
+}
+static inline int mls_import_netlbl_cat(struct context *context,
+ struct netlbl_lsm_secattr *secattr)
+{
+ return -ENOMEM;
+}
+#endif
#endif /* _SS_MLS_H */
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index ba48961f9d05..cd79c6338aa0 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -468,7 +468,7 @@ static int common_destroy(void *key, void *datum, void *p)
return 0;
}
-static int class_destroy(void *key, void *datum, void *p)
+static int cls_destroy(void *key, void *datum, void *p)
{
struct class_datum *cladatum;
struct constraint_node *constraint, *ctemp;
@@ -566,7 +566,7 @@ static int cat_destroy(void *key, void *datum, void *p)
static int (*destroy_f[SYM_NUM]) (void *key, void *datum, void *datap) =
{
common_destroy,
- class_destroy,
+ cls_destroy,
role_destroy,
type_destroy,
user_destroy,
@@ -1124,7 +1124,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
out:
return rc;
bad:
- class_destroy(key, cladatum, NULL);
+ cls_destroy(key, cladatum, NULL);
goto out;
}
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index bfe122764c98..bdb7070dd3dc 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -17,9 +17,13 @@
*
* Added support for NetLabel
*
+ * Updated: Chad Sellers <csellers@tresys.com>
+ *
+ * Added validation of kernel classes and permissions
+ *
* Copyright (C) 2006 Hewlett-Packard Development Company, L.P.
* Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
- * Copyright (C) 2003 - 2004 Tresys Technology, LLC
+ * Copyright (C) 2003 - 2004, 2006 Tresys Technology, LLC
* Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -29,6 +33,7 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/spinlock.h>
+#include <linux/rcupdate.h>
#include <linux/errno.h>
#include <linux/in.h>
#include <linux/sched.h>
@@ -49,10 +54,17 @@
#include "mls.h"
#include "objsec.h"
#include "selinux_netlabel.h"
+#include "xfrm.h"
+#include "ebitmap.h"
extern void selnl_notify_policyload(u32 seqno);
unsigned int policydb_loaded_version;
+/*
+ * This is declared in avc.c
+ */
+extern const struct selinux_class_perm selinux_class_perm;
+
static DEFINE_RWLOCK(policy_rwlock);
#define POLICY_RDLOCK read_lock(&policy_rwlock)
#define POLICY_WRLOCK write_lock_irq(&policy_rwlock)
@@ -1019,86 +1031,112 @@ int security_change_sid(u32 ssid,
}
/*
- * Verify that each permission that is defined under the
- * existing policy is still defined with the same value
- * in the new policy.
- */
-static int validate_perm(void *key, void *datum, void *p)
-{
- struct hashtab *h;
- struct perm_datum *perdatum, *perdatum2;
- int rc = 0;
-
-
- h = p;
- perdatum = datum;
-
- perdatum2 = hashtab_search(h, key);
- if (!perdatum2) {
- printk(KERN_ERR "security: permission %s disappeared",
- (char *)key);
- rc = -ENOENT;
- goto out;
- }
- if (perdatum->value != perdatum2->value) {
- printk(KERN_ERR "security: the value of permission %s changed",
- (char *)key);
- rc = -EINVAL;
- }
-out:
- return rc;
-}
-
-/*
- * Verify that each class that is defined under the
- * existing policy is still defined with the same
- * attributes in the new policy.
+ * Verify that each kernel class that is defined in the
+ * policy is correct
*/
-static int validate_class(void *key, void *datum, void *p)
+static int validate_classes(struct policydb *p)
{
- struct policydb *newp;
- struct class_datum *cladatum, *cladatum2;
- int rc;
-
- newp = p;
- cladatum = datum;
-
- cladatum2 = hashtab_search(newp->p_classes.table, key);
- if (!cladatum2) {
- printk(KERN_ERR "security: class %s disappeared\n",
- (char *)key);
- rc = -ENOENT;
- goto out;
- }
- if (cladatum->value != cladatum2->value) {
- printk(KERN_ERR "security: the value of class %s changed\n",
- (char *)key);
- rc = -EINVAL;
- goto out;
+ int i, j;
+ struct class_datum *cladatum;
+ struct perm_datum *perdatum;
+ u32 nprim, tmp, common_pts_len, perm_val, pol_val;
+ u16 class_val;
+ const struct selinux_class_perm *kdefs = &selinux_class_perm;
+ const char *def_class, *def_perm, *pol_class;
+ struct symtab *perms;
+
+ for (i = 1; i < kdefs->cts_len; i++) {
+ def_class = kdefs->class_to_string[i];
+ if (i > p->p_classes.nprim) {
+ printk(KERN_INFO
+ "security: class %s not defined in policy\n",
+ def_class);
+ continue;
+ }
+ pol_class = p->p_class_val_to_name[i-1];
+ if (strcmp(pol_class, def_class)) {
+ printk(KERN_ERR
+ "security: class %d is incorrect, found %s but should be %s\n",
+ i, pol_class, def_class);
+ return -EINVAL;
+ }
}
- if ((cladatum->comdatum && !cladatum2->comdatum) ||
- (!cladatum->comdatum && cladatum2->comdatum)) {
- printk(KERN_ERR "security: the inherits clause for the access "
- "vector definition for class %s changed\n", (char *)key);
- rc = -EINVAL;
- goto out;
+ for (i = 0; i < kdefs->av_pts_len; i++) {
+ class_val = kdefs->av_perm_to_string[i].tclass;
+ perm_val = kdefs->av_perm_to_string[i].value;
+ def_perm = kdefs->av_perm_to_string[i].name;
+ if (class_val > p->p_classes.nprim)
+ continue;
+ pol_class = p->p_class_val_to_name[class_val-1];
+ cladatum = hashtab_search(p->p_classes.table, pol_class);
+ BUG_ON(!cladatum);
+ perms = &cladatum->permissions;
+ nprim = 1 << (perms->nprim - 1);
+ if (perm_val > nprim) {
+ printk(KERN_INFO
+ "security: permission %s in class %s not defined in policy\n",
+ def_perm, pol_class);
+ continue;
+ }
+ perdatum = hashtab_search(perms->table, def_perm);
+ if (perdatum == NULL) {
+ printk(KERN_ERR
+ "security: permission %s in class %s not found in policy\n",
+ def_perm, pol_class);
+ return -EINVAL;
+ }
+ pol_val = 1 << (perdatum->value - 1);
+ if (pol_val != perm_val) {
+ printk(KERN_ERR
+ "security: permission %s in class %s has incorrect value\n",
+ def_perm, pol_class);
+ return -EINVAL;
+ }
}
- if (cladatum->comdatum) {
- rc = hashtab_map(cladatum->comdatum->permissions.table, validate_perm,
- cladatum2->comdatum->permissions.table);
- if (rc) {
- printk(" in the access vector definition for class "
- "%s\n", (char *)key);
- goto out;
+ for (i = 0; i < kdefs->av_inherit_len; i++) {
+ class_val = kdefs->av_inherit[i].tclass;
+ if (class_val > p->p_classes.nprim)
+ continue;
+ pol_class = p->p_class_val_to_name[class_val-1];
+ cladatum = hashtab_search(p->p_classes.table, pol_class);
+ BUG_ON(!cladatum);
+ if (!cladatum->comdatum) {
+ printk(KERN_ERR
+ "security: class %s should have an inherits clause but does not\n",
+ pol_class);
+ return -EINVAL;
+ }
+ tmp = kdefs->av_inherit[i].common_base;
+ common_pts_len = 0;
+ while (!(tmp & 0x01)) {
+ common_pts_len++;
+ tmp >>= 1;
+ }
+ perms = &cladatum->comdatum->permissions;
+ for (j = 0; j < common_pts_len; j++) {
+ def_perm = kdefs->av_inherit[i].common_pts[j];
+ if (j >= perms->nprim) {
+ printk(KERN_INFO
+ "security: permission %s in class %s not defined in policy\n",
+ def_perm, pol_class);
+ continue;
+ }
+ perdatum = hashtab_search(perms->table, def_perm);
+ if (perdatum == NULL) {
+ printk(KERN_ERR
+ "security: permission %s in class %s not found in policy\n",
+ def_perm, pol_class);
+ return -EINVAL;
+ }
+ if (perdatum->value != j + 1) {
+ printk(KERN_ERR
+ "security: permission %s in class %s has incorrect value\n",
+ def_perm, pol_class);
+ return -EINVAL;
+ }
}
}
- rc = hashtab_map(cladatum->permissions.table, validate_perm,
- cladatum2->permissions.table);
- if (rc)
- printk(" in access vector definition for class %s\n",
- (char *)key);
-out:
- return rc;
+ return 0;
}
/* Clone the SID into the new SID table. */
@@ -1243,6 +1281,16 @@ int security_load_policy(void *data, size_t len)
avtab_cache_destroy();
return -EINVAL;
}
+ /* Verify that the kernel defined classes are correct. */
+ if (validate_classes(&policydb)) {
+ printk(KERN_ERR
+ "security: the definition of a class is incorrect\n");
+ LOAD_UNLOCK;
+ sidtab_destroy(&sidtab);
+ policydb_destroy(&policydb);
+ avtab_cache_destroy();
+ return -EINVAL;
+ }
policydb_loaded_version = policydb.policyvers;
ss_initialized = 1;
seqno = ++latest_granting;
@@ -1265,10 +1313,10 @@ int security_load_policy(void *data, size_t len)
sidtab_init(&newsidtab);
- /* Verify that the existing classes did not change. */
- if (hashtab_map(policydb.p_classes.table, validate_class, &newpolicydb)) {
- printk(KERN_ERR "security: the definition of an existing "
- "class changed\n");
+ /* Verify that the kernel defined classes are correct. */
+ if (validate_classes(&newpolicydb)) {
+ printk(KERN_ERR
+ "security: the definition of a class is incorrect\n");
rc = -EINVAL;
goto err;
}
@@ -2145,6 +2193,32 @@ void selinux_audit_set_callback(int (*callback)(void))
aurule_callback = callback;
}
+/**
+ * security_skb_extlbl_sid - Determine the external label of a packet
+ * @skb: the packet
+ * @base_sid: the SELinux SID to use as a context for MLS only external labels
+ * @sid: the packet's SID
+ *
+ * Description:
+ * Check the various different forms of external packet labeling and determine
+ * the external SID for the packet.
+ *
+ */
+void security_skb_extlbl_sid(struct sk_buff *skb, u32 base_sid, u32 *sid)
+{
+ u32 xfrm_sid;
+ u32 nlbl_sid;
+
+ selinux_skb_xfrm_sid(skb, &xfrm_sid);
+ if (selinux_netlbl_skbuff_getsid(skb,
+ (xfrm_sid == SECSID_NULL ?
+ base_sid : xfrm_sid),
+ &nlbl_sid) != 0)
+ nlbl_sid = SECSID_NULL;
+
+ *sid = (nlbl_sid == SECSID_NULL ? xfrm_sid : nlbl_sid);
+}
+
#ifdef CONFIG_NETLABEL
/*
* This is the structure we store inside the NetLabel cache block.
@@ -2209,8 +2283,6 @@ static void selinux_netlbl_cache_add(struct sk_buff *skb, struct context *ctx)
cache = kzalloc(sizeof(*cache), GFP_ATOMIC);
if (cache == NULL)
goto netlbl_cache_add_return;
- secattr.cache->free = selinux_netlbl_cache_free;
- secattr.cache->data = (void *)cache;
cache->type = NETLBL_CACHE_T_MLS;
if (ebitmap_cpy(&cache->data.mls_label.level[0].cat,
@@ -2223,6 +2295,10 @@ static void selinux_netlbl_cache_add(struct sk_buff *skb, struct context *ctx)
cache->data.mls_label.level[0].sens = ctx->range.level[0].sens;
cache->data.mls_label.level[1].sens = ctx->range.level[0].sens;
+ secattr.cache->free = selinux_netlbl_cache_free;
+ secattr.cache->data = (void *)cache;
+ secattr.flags = NETLBL_SECATTR_CACHE;
+
netlbl_cache_add(skb, &secattr);
netlbl_cache_add_return:
@@ -2268,7 +2344,7 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb,
POLICY_RDLOCK;
- if (secattr->cache) {
+ if (secattr->flags & NETLBL_SECATTR_CACHE) {
cache = NETLBL_CACHE(secattr->cache->data);
switch (cache->type) {
case NETLBL_CACHE_T_SID:
@@ -2301,7 +2377,7 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb,
default:
goto netlbl_secattr_to_sid_return;
}
- } else if (secattr->mls_lvl_vld) {
+ } else if (secattr->flags & NETLBL_SECATTR_MLS_LVL) {
ctx = sidtab_search(&sidtab, base_sid);
if (ctx == NULL)
goto netlbl_secattr_to_sid_return;
@@ -2309,13 +2385,10 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb,
ctx_new.user = ctx->user;
ctx_new.role = ctx->role;
ctx_new.type = ctx->type;
- mls_import_lvl(&ctx_new, secattr->mls_lvl, secattr->mls_lvl);
- if (secattr->mls_cat) {
- if (mls_import_cat(&ctx_new,
- secattr->mls_cat,
- secattr->mls_cat_len,
- NULL,
- 0) != 0)
+ mls_import_netlbl_lvl(&ctx_new, secattr);
+ if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
+ if (ebitmap_netlbl_import(&ctx_new.range.level[0].cat,
+ secattr->mls_cat) != 0)
goto netlbl_secattr_to_sid_return;
ctx_new.range.level[1].cat.highbit =
ctx_new.range.level[0].cat.highbit;
@@ -2360,20 +2433,20 @@ netlbl_secattr_to_sid_return_cleanup:
* assign to the packet. Returns zero on success, negative values on failure.
*
*/
-static int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
- u32 base_sid,
- u32 *sid)
+int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u32 base_sid, u32 *sid)
{
int rc;
struct netlbl_lsm_secattr secattr;
netlbl_secattr_init(&secattr);
rc = netlbl_skbuff_getattr(skb, &secattr);
- if (rc == 0)
+ if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
rc = selinux_netlbl_secattr_to_sid(skb,
&secattr,
base_sid,
sid);
+ else
+ *sid = SECSID_NULL;
netlbl_secattr_destroy(&secattr);
return rc;
@@ -2386,7 +2459,9 @@ static int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
*
* Description:
* Attempt to label a socket using the NetLabel mechanism using the given
- * SID. Returns zero values on success, negative values on failure.
+ * SID. Returns zero values on success, negative values on failure. The
+ * caller is responsibile for calling rcu_read_lock() before calling this
+ * this function and rcu_read_unlock() after this function returns.
*
*/
static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid)
@@ -2409,19 +2484,18 @@ static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid)
secattr.domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1],
GFP_ATOMIC);
- mls_export_lvl(ctx, &secattr.mls_lvl, NULL);
- secattr.mls_lvl_vld = 1;
- rc = mls_export_cat(ctx,
- &secattr.mls_cat,
- &secattr.mls_cat_len,
- NULL,
- NULL);
+ secattr.flags |= NETLBL_SECATTR_DOMAIN;
+ mls_export_netlbl_lvl(ctx, &secattr);
+ rc = mls_export_netlbl_cat(ctx, &secattr);
if (rc != 0)
goto netlbl_socket_setsid_return;
rc = netlbl_socket_setattr(sock, &secattr);
- if (rc == 0)
+ if (rc == 0) {
+ spin_lock(&sksec->nlbl_lock);
sksec->nlbl_state = NLBL_LABELED;
+ spin_unlock(&sksec->nlbl_lock);
+ }
netlbl_socket_setsid_return:
POLICY_RDUNLOCK;
@@ -2430,6 +2504,25 @@ netlbl_socket_setsid_return:
}
/**
+ * selinux_netlbl_sk_security_reset - Reset the NetLabel fields
+ * @ssec: the sk_security_struct
+ * @family: the socket family
+ *
+ * Description:
+ * Called when the NetLabel state of a sk_security_struct needs to be reset.
+ * The caller is responsibile for all the NetLabel sk_security_struct locking.
+ *
+ */
+void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec,
+ int family)
+{
+ if (family == PF_INET)
+ ssec->nlbl_state = NLBL_REQUIRE;
+ else
+ ssec->nlbl_state = NLBL_UNSET;
+}
+
+/**
* selinux_netlbl_sk_security_init - Setup the NetLabel fields
* @ssec: the sk_security_struct
* @family: the socket family
@@ -2442,14 +2535,13 @@ netlbl_socket_setsid_return:
void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec,
int family)
{
- if (family == PF_INET)
- ssec->nlbl_state = NLBL_REQUIRE;
- else
- ssec->nlbl_state = NLBL_UNSET;
+ /* No locking needed, we are the only one who has access to ssec */
+ selinux_netlbl_sk_security_reset(ssec, family);
+ spin_lock_init(&ssec->nlbl_lock);
}
/**
- * selinux_netlbl_sk_clone_security - Copy the NetLabel fields
+ * selinux_netlbl_sk_security_clone - Copy the NetLabel fields
* @ssec: the original sk_security_struct
* @newssec: the cloned sk_security_struct
*
@@ -2458,41 +2550,41 @@ void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec,
* @newssec.
*
*/
-void selinux_netlbl_sk_clone_security(struct sk_security_struct *ssec,
+void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec,
struct sk_security_struct *newssec)
{
+ /* We don't need to take newssec->nlbl_lock because we are the only
+ * thread with access to newssec, but we do need to take the RCU read
+ * lock as other threads could have access to ssec */
+ rcu_read_lock();
+ selinux_netlbl_sk_security_reset(newssec, ssec->sk->sk_family);
newssec->sclass = ssec->sclass;
- if (ssec->nlbl_state != NLBL_UNSET)
- newssec->nlbl_state = NLBL_REQUIRE;
- else
- newssec->nlbl_state = NLBL_UNSET;
+ rcu_read_unlock();
}
/**
* selinux_netlbl_socket_post_create - Label a socket using NetLabel
* @sock: the socket to label
- * @sock_family: the socket family
- * @sid: the SID to use
*
* Description:
* Attempt to label a socket using the NetLabel mechanism using the given
* SID. Returns zero values on success, negative values on failure.
*
*/
-int selinux_netlbl_socket_post_create(struct socket *sock,
- int sock_family,
- u32 sid)
+int selinux_netlbl_socket_post_create(struct socket *sock)
{
+ int rc = 0;
struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
struct sk_security_struct *sksec = sock->sk->sk_security;
sksec->sclass = isec->sclass;
- if (sock_family != PF_INET)
- return 0;
+ rcu_read_lock();
+ if (sksec->nlbl_state == NLBL_REQUIRE)
+ rc = selinux_netlbl_socket_setsid(sock, sksec->sid);
+ rcu_read_unlock();
- sksec->nlbl_state = NLBL_REQUIRE;
- return selinux_netlbl_socket_setsid(sock, sid);
+ return rc;
}
/**
@@ -2514,11 +2606,16 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
sksec->sclass = isec->sclass;
- if (sk->sk_family != PF_INET)
+ rcu_read_lock();
+
+ if (sksec->nlbl_state != NLBL_REQUIRE) {
+ rcu_read_unlock();
return;
+ }
netlbl_secattr_init(&secattr);
if (netlbl_sock_getattr(sk, &secattr) == 0 &&
+ secattr.flags != NETLBL_SECATTR_NONE &&
selinux_netlbl_secattr_to_sid(NULL,
&secattr,
SECINITSID_UNLABELED,
@@ -2526,35 +2623,12 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
sksec->peer_sid = nlbl_peer_sid;
netlbl_secattr_destroy(&secattr);
- sksec->nlbl_state = NLBL_REQUIRE;
-
/* Try to set the NetLabel on the socket to save time later, if we fail
* here we will pick up the pieces in later calls to
* selinux_netlbl_inode_permission(). */
selinux_netlbl_socket_setsid(sock, sksec->sid);
-}
-
-/**
- * selinux_netlbl_inet_conn_request - Handle a new connection request
- * @skb: the packet
- * @sock_sid: the SID of the parent socket
- *
- * Description:
- * If present, use the security attributes of the packet in @skb and the
- * parent sock's SID to arrive at a SID for the new child sock. Returns the
- * SID of the connection or SECSID_NULL on failure.
- *
- */
-u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb, u32 sock_sid)
-{
- int rc;
- u32 peer_sid;
-
- rc = selinux_netlbl_skbuff_getsid(skb, sock_sid, &peer_sid);
- if (rc != 0)
- return SECSID_NULL;
- return peer_sid;
+ rcu_read_unlock();
}
/**
@@ -2572,25 +2646,24 @@ u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb, u32 sock_sid)
int selinux_netlbl_inode_permission(struct inode *inode, int mask)
{
int rc;
- struct inode_security_struct *isec;
struct sk_security_struct *sksec;
struct socket *sock;
- if (!S_ISSOCK(inode->i_mode))
+ if (!S_ISSOCK(inode->i_mode) ||
+ ((mask & (MAY_WRITE | MAY_APPEND)) == 0))
return 0;
-
sock = SOCKET_I(inode);
- isec = inode->i_security;
sksec = sock->sk->sk_security;
- mutex_lock(&isec->lock);
- if (unlikely(sksec->nlbl_state == NLBL_REQUIRE &&
- (mask & (MAY_WRITE | MAY_APPEND)))) {
- lock_sock(sock->sk);
- rc = selinux_netlbl_socket_setsid(sock, sksec->sid);
- release_sock(sock->sk);
- } else
- rc = 0;
- mutex_unlock(&isec->lock);
+
+ rcu_read_lock();
+ if (sksec->nlbl_state != NLBL_REQUIRE) {
+ rcu_read_unlock();
+ return 0;
+ }
+ lock_sock(sock->sk);
+ rc = selinux_netlbl_socket_setsid(sock, sksec->sid);
+ release_sock(sock->sk);
+ rcu_read_unlock();
return rc;
}
@@ -2648,42 +2721,6 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
}
/**
- * selinux_netlbl_socket_getpeersec_stream - Return the connected peer's SID
- * @sock: the socket
- *
- * Description:
- * Examine @sock to find the connected peer's SID. Returns the SID on success
- * or SECSID_NULL on error.
- *
- */
-u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock)
-{
- struct sk_security_struct *sksec = sock->sk->sk_security;
- return sksec->peer_sid;
-}
-
-/**
- * selinux_netlbl_socket_getpeersec_dgram - Return the SID of a NetLabel packet
- * @skb: the packet
- *
- * Description:
- * Examine @skb to find the SID assigned to it by NetLabel. Returns the SID on
- * success, SECSID_NULL on error.
- *
- */
-u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb)
-{
- int peer_sid;
-
- if (selinux_netlbl_skbuff_getsid(skb,
- SECINITSID_UNLABELED,
- &peer_sid) != 0)
- return SECSID_NULL;
-
- return peer_sid;
-}
-
-/**
* selinux_netlbl_socket_setsockopt - Do not allow users to remove a NetLabel
* @sock: the socket
* @level: the socket level or protocol
@@ -2701,21 +2738,19 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
int optname)
{
int rc = 0;
- struct inode *inode = SOCK_INODE(sock);
struct sk_security_struct *sksec = sock->sk->sk_security;
- struct inode_security_struct *isec = inode->i_security;
struct netlbl_lsm_secattr secattr;
- mutex_lock(&isec->lock);
+ rcu_read_lock();
if (level == IPPROTO_IP && optname == IP_OPTIONS &&
sksec->nlbl_state == NLBL_LABELED) {
netlbl_secattr_init(&secattr);
rc = netlbl_socket_getattr(sock, &secattr);
- if (rc == 0 && (secattr.cache || secattr.mls_lvl_vld))
+ if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
rc = -EACCES;
netlbl_secattr_destroy(&secattr);
}
- mutex_unlock(&isec->lock);
+ rcu_read_unlock();
return rc;
}
diff --git a/security/selinux/ss/symtab.c b/security/selinux/ss/symtab.c
index 24a10d36d3b6..837658a98a54 100644
--- a/security/selinux/ss/symtab.c
+++ b/security/selinux/ss/symtab.c
@@ -9,9 +9,9 @@
#include <linux/errno.h>
#include "symtab.h"
-static unsigned int symhash(struct hashtab *h, void *key)
+static unsigned int symhash(struct hashtab *h, const void *key)
{
- char *p, *keyp;
+ const char *p, *keyp;
unsigned int size;
unsigned int val;
@@ -23,9 +23,9 @@ static unsigned int symhash(struct hashtab *h, void *key)
return val & (h->size - 1);
}
-static int symcmp(struct hashtab *h, void *key1, void *key2)
+static int symcmp(struct hashtab *h, const void *key1, const void *key2)
{
- char *keyp1, *keyp2;
+ const char *keyp1, *keyp2;
keyp1 = key1;
keyp2 = key2;
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index 675b995a67c3..bd8d1ef40a90 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -115,76 +115,46 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *
struct flowi *fl)
{
u32 state_sid;
- u32 pol_sid;
- int err;
+ int rc;
- if (xp->security) {
- if (!x->security)
- /* unlabeled SA and labeled policy can't match */
- return 0;
- else
- state_sid = x->security->ctx_sid;
- pol_sid = xp->security->ctx_sid;
- } else
+ if (!xp->security)
if (x->security)
/* unlabeled policy and labeled SA can't match */
return 0;
else
/* unlabeled policy and unlabeled SA match all flows */
return 1;
-
- err = avc_has_perm(state_sid, pol_sid, SECCLASS_ASSOCIATION,
- ASSOCIATION__POLMATCH,
- NULL);
-
- if (err)
- return 0;
-
- err = avc_has_perm(fl->secid, state_sid, SECCLASS_ASSOCIATION,
- ASSOCIATION__SENDTO,
- NULL)? 0:1;
-
- return err;
-}
-
-/*
- * LSM hook implementation that authorizes that a particular outgoing flow
- * can use a given security association.
- */
-
-int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm,
- struct xfrm_policy *xp)
-{
- int rc = 0;
- u32 sel_sid = SECINITSID_UNLABELED;
- struct xfrm_sec_ctx *ctx;
-
- if (!xp->security)
- if (!xfrm->security)
- return 1;
- else
- return 0;
else
- if (!xfrm->security)
+ if (!x->security)
+ /* unlabeled SA and labeled policy can't match */
return 0;
+ else
+ if (!selinux_authorizable_xfrm(x))
+ /* Not a SELinux-labeled SA */
+ return 0;
- /* Context sid is either set to label or ANY_ASSOC */
- if ((ctx = xfrm->security)) {
- if (!selinux_authorizable_ctx(ctx))
- return 0;
+ state_sid = x->security->ctx_sid;
- sel_sid = ctx->ctx_sid;
- }
+ if (fl->secid != state_sid)
+ return 0;
- rc = avc_has_perm(fl->secid, sel_sid, SECCLASS_ASSOCIATION,
+ rc = avc_has_perm(fl->secid, state_sid, SECCLASS_ASSOCIATION,
ASSOCIATION__SENDTO,
NULL)? 0:1;
+ /*
+ * We don't need a separate SA Vs. policy polmatch check
+ * since the SA is now of the same label as the flow and
+ * a flow Vs. policy polmatch check had already happened
+ * in selinux_xfrm_policy_lookup() above.
+ */
+
return rc;
}
/*
- * LSM hook implementation that determines the sid for the session.
+ * LSM hook implementation that checks and/or returns the xfrm sid for the
+ * incoming packet.
*/
int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
@@ -226,16 +196,15 @@ int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
* CTX does not have a meaningful value on input
*/
static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp,
- struct xfrm_user_sec_ctx *uctx, struct xfrm_sec_ctx *pol, u32 sid)
+ struct xfrm_user_sec_ctx *uctx, u32 sid)
{
int rc = 0;
struct task_security_struct *tsec = current->security;
struct xfrm_sec_ctx *ctx = NULL;
char *ctx_str = NULL;
u32 str_len;
- u32 ctx_sid;
- BUG_ON(uctx && pol);
+ BUG_ON(uctx && sid);
if (!uctx)
goto not_from_user;
@@ -279,15 +248,7 @@ static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp,
return rc;
not_from_user:
- if (pol) {
- rc = security_sid_mls_copy(pol->ctx_sid, sid, &ctx_sid);
- if (rc)
- goto out;
- }
- else
- ctx_sid = sid;
-
- rc = security_sid_to_context(ctx_sid, &ctx_str, &str_len);
+ rc = security_sid_to_context(sid, &ctx_str, &str_len);
if (rc)
goto out;
@@ -302,7 +263,7 @@ not_from_user:
ctx->ctx_doi = XFRM_SC_DOI_LSM;
ctx->ctx_alg = XFRM_SC_ALG_SELINUX;
- ctx->ctx_sid = ctx_sid;
+ ctx->ctx_sid = sid;
ctx->ctx_len = str_len;
memcpy(ctx->ctx_str,
ctx_str,
@@ -323,22 +284,14 @@ out2:
* xfrm_policy.
*/
int selinux_xfrm_policy_alloc(struct xfrm_policy *xp,
- struct xfrm_user_sec_ctx *uctx, struct sock *sk)
+ struct xfrm_user_sec_ctx *uctx)
{
int err;
- u32 sid;
BUG_ON(!xp);
- BUG_ON(uctx && sk);
-
- if (sk) {
- struct sk_security_struct *ssec = sk->sk_security;
- sid = ssec->sid;
- }
- else
- sid = SECSID_NULL;
+ BUG_ON(!uctx);
- err = selinux_xfrm_sec_ctx_alloc(&xp->security, uctx, NULL, sid);
+ err = selinux_xfrm_sec_ctx_alloc(&xp->security, uctx, 0);
return err;
}
@@ -399,13 +352,13 @@ int selinux_xfrm_policy_delete(struct xfrm_policy *xp)
* xfrm_state.
*/
int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *uctx,
- struct xfrm_sec_ctx *pol, u32 secid)
+ u32 secid)
{
int err;
BUG_ON(!x);
- err = selinux_xfrm_sec_ctx_alloc(&x->security, uctx, pol, secid);
+ err = selinux_xfrm_sec_ctx_alloc(&x->security, uctx, secid);
return err;
}
@@ -419,74 +372,6 @@ void selinux_xfrm_state_free(struct xfrm_state *x)
kfree(ctx);
}
-/*
- * SELinux internal function to retrieve the context of a connected
- * (sk->sk_state == TCP_ESTABLISHED) TCP socket based on its security
- * association used to connect to the remote socket.
- *
- * Retrieve via getsockopt SO_PEERSEC.
- */
-u32 selinux_socket_getpeer_stream(struct sock *sk)
-{
- struct dst_entry *dst, *dst_test;
- u32 peer_sid = SECSID_NULL;
-
- if (sk->sk_state != TCP_ESTABLISHED)
- goto out;
-
- dst = sk_dst_get(sk);
- if (!dst)
- goto out;
-
- for (dst_test = dst; dst_test != 0;
- dst_test = dst_test->child) {
- struct xfrm_state *x = dst_test->xfrm;
-
- if (x && selinux_authorizable_xfrm(x)) {
- struct xfrm_sec_ctx *ctx = x->security;
- peer_sid = ctx->ctx_sid;
- break;
- }
- }
- dst_release(dst);
-
-out:
- return peer_sid;
-}
-
-/*
- * SELinux internal function to retrieve the context of a UDP packet
- * based on its security association used to connect to the remote socket.
- *
- * Retrieve via setsockopt IP_PASSSEC and recvmsg with control message
- * type SCM_SECURITY.
- */
-u32 selinux_socket_getpeer_dgram(struct sk_buff *skb)
-{
- struct sec_path *sp;
-
- if (skb == NULL)
- return SECSID_NULL;
-
- if (skb->sk->sk_protocol != IPPROTO_UDP)
- return SECSID_NULL;
-
- sp = skb->sp;
- if (sp) {
- int i;
-
- for (i = sp->len-1; i >= 0; i--) {
- struct xfrm_state *x = sp->xvec[i];
- if (selinux_authorizable_xfrm(x)) {
- struct xfrm_sec_ctx *ctx = x->security;
- return ctx->ctx_sid;
- }
- }
- }
-
- return SECSID_NULL;
-}
-
/*
* LSM hook implementation that authorizes deletion of labeled SAs.
*/
@@ -532,6 +417,13 @@ int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
}
}
+ /*
+ * This check even when there's no association involved is
+ * intended, according to Trent Jaeger, to make sure a
+ * process can't engage in non-ipsec communication unless
+ * explicitly allowed by policy.
+ */
+
rc = avc_has_perm(isec_sid, sel_sid, SECCLASS_ASSOCIATION,
ASSOCIATION__RECVFROM, ad);
@@ -543,10 +435,10 @@ int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
* If we have no security association, then we need to determine
* whether the socket is allowed to send to an unlabelled destination.
* If we do have a authorizable security association, then it has already been
- * checked in xfrm_policy_lookup hook.
+ * checked in the selinux_xfrm_state_pol_flow_match hook above.
*/
int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
- struct avc_audit_data *ad)
+ struct avc_audit_data *ad, u8 proto)
{
struct dst_entry *dst;
int rc = 0;
@@ -565,6 +457,27 @@ int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
}
}
+ switch (proto) {
+ case IPPROTO_AH:
+ case IPPROTO_ESP:
+ case IPPROTO_COMP:
+ /*
+ * We should have already seen this packet once before
+ * it underwent xfrm(s). No need to subject it to the
+ * unlabeled check.
+ */
+ goto out;
+ default:
+ break;
+ }
+
+ /*
+ * This check even when there's no association involved is
+ * intended, according to Trent Jaeger, to make sure a
+ * process can't engage in non-ipsec communication unless
+ * explicitly allowed by policy.
+ */
+
rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION,
ASSOCIATION__SENDTO, ad);
out:
diff --git a/sound/Kconfig b/sound/Kconfig
index e0d791a98452..95949b6806ac 100644
--- a/sound/Kconfig
+++ b/sound/Kconfig
@@ -64,11 +64,11 @@ source "sound/arm/Kconfig"
source "sound/mips/Kconfig"
-# the following will depenend on the order of config.
+# the following will depend on the order of config.
# here assuming USB is defined before ALSA
source "sound/usb/Kconfig"
-# the following will depenend on the order of config.
+# the following will depend on the order of config.
# here assuming PCMCIA is defined before ALSA
source "sound/pcmcia/Kconfig"
diff --git a/sound/aoa/codecs/snd-aoa-codec-tas.c b/sound/aoa/codecs/snd-aoa-codec-tas.c
index 2ef55a17917c..9de8485ba3f5 100644
--- a/sound/aoa/codecs/snd-aoa-codec-tas.c
+++ b/sound/aoa/codecs/snd-aoa-codec-tas.c
@@ -514,9 +514,15 @@ static int tas_snd_capture_source_put(struct snd_kcontrol *kcontrol,
mutex_lock(&tas->mtx);
oldacr = tas->acr;
- tas->acr &= ~TAS_ACR_INPUT_B;
+ /*
+ * Despite what the data sheet says in one place, the
+ * TAS_ACR_B_MONAUREAL bit forces mono output even when
+ * input A (line in) is selected.
+ */
+ tas->acr &= ~(TAS_ACR_INPUT_B | TAS_ACR_B_MONAUREAL);
if (ucontrol->value.enumerated.item[0])
- tas->acr |= TAS_ACR_INPUT_B;
+ tas->acr |= TAS_ACR_INPUT_B | TAS_ACR_B_MONAUREAL |
+ TAS_ACR_B_MON_SEL_RIGHT;
if (oldacr == tas->acr) {
mutex_unlock(&tas->mtx);
return 0;
@@ -686,8 +692,7 @@ static int tas_reset_init(struct tas *tas)
if (tas_write_reg(tas, TAS_REG_MCS, 1, &tmp))
goto outerr;
- tas->acr |= TAS_ACR_ANALOG_PDOWN | TAS_ACR_B_MONAUREAL |
- TAS_ACR_B_MON_SEL_RIGHT;
+ tas->acr |= TAS_ACR_ANALOG_PDOWN;
if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr))
goto outerr;
diff --git a/sound/core/init.c b/sound/core/init.c
index 3058d626a90a..6152a7554dfd 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -361,6 +361,8 @@ static int snd_card_do_free(struct snd_card *card)
snd_printk(KERN_WARNING "unable to free card info\n");
/* Not fatal error */
}
+ if (card->dev)
+ device_unregister(card->dev);
kfree(card);
return 0;
}
@@ -495,6 +497,12 @@ int snd_card_register(struct snd_card *card)
int err;
snd_assert(card != NULL, return -EINVAL);
+ if (!card->dev) {
+ card->dev = device_create(sound_class, card->parent, 0,
+ "card%i", card->number);
+ if (IS_ERR(card->dev))
+ card->dev = NULL;
+ }
if ((err = snd_device_register_all(card)) < 0)
return err;
mutex_lock(&snd_card_mutex);
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 505b23ec4058..e0821eb3d851 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -2359,7 +2359,8 @@ static int snd_pcm_oss_release(struct inode *inode, struct file *file)
substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
snd_assert(substream != NULL, return -ENXIO);
pcm = substream->pcm;
- snd_pcm_oss_sync(pcm_oss_file);
+ if (!pcm->card->shutdown)
+ snd_pcm_oss_sync(pcm_oss_file);
mutex_lock(&pcm->open_mutex);
snd_pcm_oss_release_file(pcm_oss_file);
mutex_unlock(&pcm->open_mutex);
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index fbbbcd20c4cc..5ac6e19ccb41 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -910,7 +910,8 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
substream->pstr->substream_opened--;
}
-static ssize_t show_pcm_class(struct class_device *class_device, char *buf)
+static ssize_t show_pcm_class(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct snd_pcm *pcm;
const char *str;
@@ -921,7 +922,7 @@ static ssize_t show_pcm_class(struct class_device *class_device, char *buf)
[SNDRV_PCM_CLASS_DIGITIZER] = "digitizer",
};
- if (! (pcm = class_get_devdata(class_device)) ||
+ if (! (pcm = dev_get_drvdata(dev)) ||
pcm->dev_class > SNDRV_PCM_CLASS_LAST)
str = "none";
else
@@ -929,7 +930,7 @@ static ssize_t show_pcm_class(struct class_device *class_device, char *buf)
return snprintf(buf, PAGE_SIZE, "%s\n", str);
}
-static struct class_device_attribute pcm_attrs =
+static struct device_attribute pcm_attrs =
__ATTR(pcm_class, S_IRUGO, show_pcm_class, NULL);
static int snd_pcm_dev_register(struct snd_device *device)
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 37b4b10850ae..66e24b5da469 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -1310,7 +1310,8 @@ static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream,
int f_flags)
{
struct snd_pcm_runtime *runtime = substream->runtime;
- if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
+ if (runtime->status->state == SNDRV_PCM_STATE_OPEN ||
+ runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED)
return -EBADFD;
if (snd_pcm_running(substream))
return -EBUSY;
@@ -1568,7 +1569,8 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream)
runtime = substream->runtime;
card = substream->pcm->card;
- if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
+ if (runtime->status->state == SNDRV_PCM_STATE_OPEN ||
+ runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED)
return -EBADFD;
snd_power_lock(card);
diff --git a/sound/core/rtctimer.c b/sound/core/rtctimer.c
index 412dd62b654e..9f7b32e1ccde 100644
--- a/sound/core/rtctimer.c
+++ b/sound/core/rtctimer.c
@@ -22,13 +22,10 @@
#include <sound/driver.h>
#include <linux/init.h>
-#include <linux/time.h>
-#include <linux/threads.h>
#include <linux/interrupt.h>
#include <linux/moduleparam.h>
#include <sound/core.h>
#include <sound/timer.h>
-#include <sound/info.h>
#if defined(CONFIG_RTC) || defined(CONFIG_RTC_MODULE)
@@ -50,7 +47,9 @@ static int rtctimer_stop(struct snd_timer *t);
* The hardware dependent description for this timer.
*/
static struct snd_timer_hardware rtc_hw = {
- .flags = SNDRV_TIMER_HW_FIRST|SNDRV_TIMER_HW_AUTO,
+ .flags = SNDRV_TIMER_HW_AUTO |
+ SNDRV_TIMER_HW_FIRST |
+ SNDRV_TIMER_HW_TASKLET,
.ticks = 100000000L, /* FIXME: XXX */
.open = rtctimer_open,
.close = rtctimer_close,
@@ -60,6 +59,7 @@ static struct snd_timer_hardware rtc_hw = {
static int rtctimer_freq = RTC_FREQ; /* frequency */
static struct snd_timer *rtctimer;
+static struct tasklet_struct rtc_tasklet;
static rtc_task_t rtc_task;
@@ -81,6 +81,7 @@ rtctimer_close(struct snd_timer *t)
rtc_task_t *rtc = t->private_data;
if (rtc) {
rtc_unregister(rtc);
+ tasklet_kill(&rtc_tasklet);
t->private_data = NULL;
}
return 0;
@@ -105,12 +106,17 @@ rtctimer_stop(struct snd_timer *timer)
return 0;
}
+static void rtctimer_tasklet(unsigned long data)
+{
+ snd_timer_interrupt((struct snd_timer *)data, 1);
+}
+
/*
* interrupt
*/
static void rtctimer_interrupt(void *private_data)
{
- snd_timer_interrupt(private_data, 1);
+ tasklet_hi_schedule(private_data);
}
@@ -139,9 +145,11 @@ static int __init rtctimer_init(void)
timer->hw = rtc_hw;
timer->hw.resolution = NANO_SEC / rtctimer_freq;
+ tasklet_init(&rtc_tasklet, rtctimer_tasklet, (unsigned long)timer);
+
/* set up RTC callback */
rtc_task.func = rtctimer_interrupt;
- rtc_task.private_data = timer;
+ rtc_task.private_data = &rtc_tasklet;
err = snd_timer_global_register(timer);
if (err < 0) {
diff --git a/sound/core/sound.c b/sound/core/sound.c
index efa476c5210a..282742022de6 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -61,9 +61,6 @@ EXPORT_SYMBOL(snd_ecards_limit);
static struct snd_minor *snd_minors[SNDRV_OS_MINORS];
static DEFINE_MUTEX(sound_mutex);
-extern struct class *sound_class;
-
-
#ifdef CONFIG_KMOD
/**
@@ -268,11 +265,10 @@ int snd_register_device(int type, struct snd_card *card, int dev,
snd_minors[minor] = preg;
if (card)
device = card->dev;
- preg->class_dev = class_device_create(sound_class, NULL,
- MKDEV(major, minor),
- device, "%s", name);
- if (preg->class_dev)
- class_set_devdata(preg->class_dev, private_data);
+ preg->dev = device_create(sound_class, device, MKDEV(major, minor),
+ "%s", name);
+ if (preg->dev)
+ dev_set_drvdata(preg->dev, private_data);
mutex_unlock(&sound_mutex);
return 0;
@@ -320,7 +316,7 @@ int snd_unregister_device(int type, struct snd_card *card, int dev)
return -EINVAL;
}
- class_device_destroy(sound_class, MKDEV(major, minor));
+ device_destroy(sound_class, MKDEV(major, minor));
kfree(snd_minors[minor]);
snd_minors[minor] = NULL;
@@ -331,15 +327,15 @@ int snd_unregister_device(int type, struct snd_card *card, int dev)
EXPORT_SYMBOL(snd_unregister_device);
int snd_add_device_sysfs_file(int type, struct snd_card *card, int dev,
- const struct class_device_attribute *attr)
+ struct device_attribute *attr)
{
int minor, ret = -EINVAL;
- struct class_device *cdev;
+ struct device *d;
mutex_lock(&sound_mutex);
minor = find_snd_minor(type, card, dev);
- if (minor >= 0 && (cdev = snd_minors[minor]->class_dev) != NULL)
- ret = class_device_create_file(cdev, attr);
+ if (minor >= 0 && (d = snd_minors[minor]->dev) != NULL)
+ ret = device_create_file(d, attr);
mutex_unlock(&sound_mutex);
return ret;
diff --git a/sound/oss/cs46xx.c b/sound/oss/cs46xx.c
index 6e3c41f530e6..b1c5d8286e40 100644
--- a/sound/oss/cs46xx.c
+++ b/sound/oss/cs46xx.c
@@ -779,7 +779,7 @@ static unsigned int cs_set_adc_rate(struct cs_state *state, unsigned int rate)
rate = 48000 / 9;
/*
- * We can not capture at at rate greater than the Input Rate (48000).
+ * We cannot capture at at rate greater than the Input Rate (48000).
* Return an error if an attempt is made to stray outside that limit.
*/
if (rate > 48000)
@@ -4754,8 +4754,8 @@ static int cs_hardware_init(struct cs_card *card)
mdelay(5 * cs_laptop_wait); /* Shouldnt be needed ?? */
/*
-* If we are resuming under 2.2.x then we can not schedule a timeout.
-* so, just spin the CPU.
+* If we are resuming under 2.2.x then we cannot schedule a timeout,
+* so just spin the CPU.
*/
if (card->pm.flags & CS46XX_PM_IDLE) {
/*
diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c
index 2344d09c7114..75c5e745705f 100644
--- a/sound/oss/soundcard.c
+++ b/sound/oss/soundcard.c
@@ -557,17 +557,17 @@ static int __init oss_init(void)
sound_dmap_flag = (dmabuf > 0 ? 1 : 0);
for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) {
- class_device_create(sound_class, NULL,
- MKDEV(SOUND_MAJOR, dev_list[i].minor),
- NULL, "%s", dev_list[i].name);
+ device_create(sound_class, NULL,
+ MKDEV(SOUND_MAJOR, dev_list[i].minor),
+ "%s", dev_list[i].name);
if (!dev_list[i].num)
continue;
for (j = 1; j < *dev_list[i].num; j++)
- class_device_create(sound_class, NULL,
- MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)),
- NULL, "%s%d", dev_list[i].name, j);
+ device_create(sound_class, NULL,
+ MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)),
+ "%s%d", dev_list[i].name, j);
}
if (sound_nblocks >= 1024)
@@ -581,11 +581,11 @@ static void __exit oss_cleanup(void)
int i, j;
for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) {
- class_device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor));
+ device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor));
if (!dev_list[i].num)
continue;
for (j = 1; j < *dev_list[i].num; j++)
- class_device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)));
+ device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)));
}
unregister_sound_special(1);
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index 8058059c56e9..8bc4ffa6220d 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -956,6 +956,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
.ca0151_chip = 1,
.spk71 = 1,
.spdif_bug = 1,
+ .adc_1361t = 1, /* 24 bit capture instead of 16bit. Fixes ALSA bug#324 */
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004, .revision = 0x04,
.driver = "Audigy2", .name = "Audigy 2 [Unknown]",
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 0d728c6f697c..fb961448db19 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -5870,7 +5870,7 @@ static struct hda_board_config alc262_cfg_tbl[] = {
{ .pci_subvendor = 0x10cf, .pci_subdevice = 0x1397,
.config = ALC262_FUJITSU },
{ .modelname = "hp-bpc", .config = ALC262_HP_BPC },
- { .pci_subvendor = 0x103c, .pci_subdevice = 0x208c,
+ { .pci_subvendor = 0x103c, .pci_subdevice = 0x280c,
.config = ALC262_HP_BPC }, /* xw4400 */
{ .pci_subvendor = 0x103c, .pci_subdevice = 0x3014,
.config = ALC262_HP_BPC }, /* xw6400 */
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 731b7b97ee71..fe51ef3e49d2 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -336,6 +336,13 @@ static struct hda_board_config stac9200_cfg_tbl[] = {
.pci_subvendor = PCI_VENDOR_ID_INTEL,
.pci_subdevice = 0x2668, /* DFI LanParty */
.config = STAC_REF },
+ /* Dell laptops have BIOS problem */
+ { .pci_subvendor = PCI_VENDOR_ID_DELL, .pci_subdevice = 0x01b5,
+ .config = STAC_REF }, /* Dell Inspiron 630m */
+ { .pci_subvendor = PCI_VENDOR_ID_DELL, .pci_subdevice = 0x01c2,
+ .config = STAC_REF }, /* Dell Latitude D620 */
+ { .pci_subvendor = PCI_VENDOR_ID_DELL, .pci_subdevice = 0x01cb,
+ .config = STAC_REF }, /* Dell Latitude 120L */
{} /* terminator */
};
@@ -591,13 +598,6 @@ static struct hda_board_config stac9205_cfg_tbl[] = {
.pci_subvendor = PCI_VENDOR_ID_INTEL,
.pci_subdevice = 0x2668, /* DFI LanParty */
.config = STAC_REF }, /* SigmaTel reference board */
- /* Dell laptops have BIOS problem */
- { .pci_subvendor = PCI_VENDOR_ID_DELL, .pci_subdevice = 0x01b5,
- .config = STAC_REF }, /* Dell Inspiron 630m */
- { .pci_subvendor = PCI_VENDOR_ID_DELL, .pci_subdevice = 0x01c2,
- .config = STAC_REF }, /* Dell Latitude D620 */
- { .pci_subvendor = PCI_VENDOR_ID_DELL, .pci_subdevice = 0x01cb,
- .config = STAC_REF }, /* Dell Latitude 120L */
{} /* terminator */
};
diff --git a/sound/sound_core.c b/sound/sound_core.c
index 5322c50c9617..8f1ced4ab34c 100644
--- a/sound/sound_core.c
+++ b/sound/sound_core.c
@@ -170,8 +170,8 @@ static int sound_insert_unit(struct sound_unit **list, const struct file_operati
else
sprintf(s->name, "sound/%s%d", name, r / SOUND_STEP);
- class_device_create(sound_class, NULL, MKDEV(SOUND_MAJOR, s->unit_minor),
- dev, s->name+6);
+ device_create(sound_class, dev, MKDEV(SOUND_MAJOR, s->unit_minor),
+ s->name+6);
return r;
fail:
@@ -193,7 +193,7 @@ static void sound_remove_unit(struct sound_unit **list, int unit)
p = __sound_remove_unit(list, unit);
spin_unlock(&sound_loader_lock);
if (p) {
- class_device_destroy(sound_class, MKDEV(SOUND_MAJOR, p->unit_minor));
+ device_destroy(sound_class, MKDEV(SOUND_MAJOR, p->unit_minor));
kfree(p);
}
}
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index c82b01c7ad3a..67202b9eeb77 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -1469,7 +1469,8 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)
subs->cur_audiofmt = NULL;
subs->cur_rate = 0;
subs->period_bytes = 0;
- release_substream_urbs(subs, 0);
+ if (!subs->stream->chip->shutdown)
+ release_substream_urbs(subs, 0);
return snd_pcm_free_vmalloc_buffer(substream);
}
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
index b7c5e59b2299..24f5a26c5f0c 100644
--- a/sound/usb/usbmidi.c
+++ b/sound/usb/usbmidi.c
@@ -981,7 +981,7 @@ void snd_usbmidi_disconnect(struct list_head* p)
if (umidi->usb_protocol_ops->finish_out_endpoint)
umidi->usb_protocol_ops->finish_out_endpoint(ep->out);
}
- if (ep->in && ep->in->urb)
+ if (ep->in)
usb_kill_urb(ep->in->urb);
}
}
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index 1024c178f5c0..e74eb1bc8d87 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -1620,8 +1620,7 @@ static void snd_usb_mixer_free(struct usb_mixer_interface *mixer)
kfree(mixer->urb->transfer_buffer);
usb_free_urb(mixer->urb);
}
- if (mixer->rc_urb)
- usb_free_urb(mixer->rc_urb);
+ usb_free_urb(mixer->rc_urb);
kfree(mixer->rc_setup_packet);
kfree(mixer);
}
@@ -2056,8 +2055,6 @@ void snd_usb_mixer_disconnect(struct list_head *p)
struct usb_mixer_interface *mixer;
mixer = list_entry(p, struct usb_mixer_interface, list);
- if (mixer->urb)
- usb_kill_urb(mixer->urb);
- if (mixer->rc_urb)
- usb_kill_urb(mixer->rc_urb);
+ usb_kill_urb(mixer->urb);
+ usb_kill_urb(mixer->rc_urb);
}
diff --git a/usr/Makefile b/usr/Makefile
index e338e7bedb29..382702ad663b 100644
--- a/usr/Makefile
+++ b/usr/Makefile
@@ -20,7 +20,7 @@ $(obj)/initramfs_data.o: $(obj)/initramfs_data.cpio.gz FORCE
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)
+ $(shell echo $(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))