aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/SubmittingDrivers2
-rw-r--r--Documentation/SubmittingPatches3
-rw-r--r--Documentation/feature-removal-schedule.txt9
-rw-r--r--Documentation/filesystems/tmpfs.txt12
-rw-r--r--Documentation/kernel-parameters.txt14
-rw-r--r--Documentation/scsi/aacraid.txt108
-rw-r--r--Documentation/spi/butterfly57
-rw-r--r--Documentation/spi/spi-summary457
-rw-r--r--MAINTAINERS35
-rw-r--r--arch/arm/Kconfig39
-rw-r--r--arch/arm/Makefile7
-rw-r--r--arch/arm/common/Kconfig7
-rw-r--r--arch/arm/common/Makefile1
-rw-r--r--arch/arm/common/locomo.c4
-rw-r--r--arch/arm/common/sa1111.c4
-rw-r--r--arch/arm/common/vic.c92
-rw-r--r--arch/arm/kernel/Makefile1
-rw-r--r--arch/arm/kernel/armksyms.c22
-rw-r--r--arch/arm/kernel/calls.S59
-rw-r--r--arch/arm/kernel/ecard.c14
-rw-r--r--arch/arm/kernel/entry-armv.S24
-rw-r--r--arch/arm/kernel/entry-common.S146
-rw-r--r--arch/arm/kernel/entry-header.S1
-rw-r--r--arch/arm/kernel/head.S7
-rw-r--r--arch/arm/kernel/ptrace.c15
-rw-r--r--arch/arm/kernel/semaphore.c17
-rw-r--r--arch/arm/kernel/sys_arm.c2
-rw-r--r--arch/arm/kernel/sys_oabi-compat.c339
-rw-r--r--arch/arm/kernel/traps.c2
-rw-r--r--arch/arm/lib/ashldi3.S1
-rw-r--r--arch/arm/lib/ashrdi3.S1
-rw-r--r--arch/arm/lib/lib1funcs.S27
-rw-r--r--arch/arm/lib/lshrdi3.S1
-rw-r--r--arch/arm/lib/muldi3.S1
-rw-r--r--arch/arm/lib/ucmpdi2.S14
-rw-r--r--arch/arm/mach-aaec2000/aaed2000.c1
-rw-r--r--arch/arm/mach-at91rm9200/board-csb337.c1
-rw-r--r--arch/arm/mach-at91rm9200/board-csb637.c1
-rw-r--r--arch/arm/mach-at91rm9200/board-dk.c1
-rw-r--r--arch/arm/mach-at91rm9200/board-ek.c1
-rw-r--r--arch/arm/mach-clps711x/autcpu12.c1
-rw-r--r--arch/arm/mach-clps711x/cdb89712.c1
-rw-r--r--arch/arm/mach-clps711x/ceiva.c1
-rw-r--r--arch/arm/mach-clps711x/clep7312.c1
-rw-r--r--arch/arm/mach-clps711x/edb7211-arch.c1
-rw-r--r--arch/arm/mach-clps711x/fortunet.c1
-rw-r--r--arch/arm/mach-clps711x/p720t.c1
-rw-r--r--arch/arm/mach-clps7500/core.c1
-rw-r--r--arch/arm/mach-ebsa110/core.c1
-rw-r--r--arch/arm/mach-footbridge/cats-hw.c1
-rw-r--r--arch/arm/mach-footbridge/co285.c1
-rw-r--r--arch/arm/mach-footbridge/ebsa285.c1
-rw-r--r--arch/arm/mach-footbridge/netwinder-hw.c1
-rw-r--r--arch/arm/mach-footbridge/personal.c1
-rw-r--r--arch/arm/mach-h720x/h7201-eval.c1
-rw-r--r--arch/arm/mach-h720x/h7202-eval.c1
-rw-r--r--arch/arm/mach-imx/mx1ads.c1
-rw-r--r--arch/arm/mach-integrator/integrator_ap.c1
-rw-r--r--arch/arm/mach-integrator/integrator_cp.c1
-rw-r--r--arch/arm/mach-integrator/lm.c36
-rw-r--r--arch/arm/mach-iop3xx/iop321-setup.c2
-rw-r--r--arch/arm/mach-iop3xx/iop331-setup.c2
-rw-r--r--arch/arm/mach-ixp2000/core.c10
-rw-r--r--arch/arm/mach-ixp2000/enp2611.c1
-rw-r--r--arch/arm/mach-ixp2000/ixdp2400.c1
-rw-r--r--arch/arm/mach-ixp2000/ixdp2800.c1
-rw-r--r--arch/arm/mach-ixp2000/ixdp2x01.c2
-rw-r--r--arch/arm/mach-ixp4xx/coyote-setup.c2
-rw-r--r--arch/arm/mach-ixp4xx/gtwx5715-setup.c1
-rw-r--r--arch/arm/mach-ixp4xx/ixdp425-setup.c4
-rw-r--r--arch/arm/mach-ixp4xx/nas100d-setup.c1
-rw-r--r--arch/arm/mach-ixp4xx/nslu2-setup.c1
-rw-r--r--arch/arm/mach-l7200/core.c1
-rw-r--r--arch/arm/mach-lh7a40x/arch-kev7a400.c1
-rw-r--r--arch/arm/mach-lh7a40x/arch-lpd7a40x.c2
-rw-r--r--arch/arm/mach-omap1/board-generic.c1
-rw-r--r--arch/arm/mach-omap1/board-h2.c1
-rw-r--r--arch/arm/mach-omap1/board-h3.c1
-rw-r--r--arch/arm/mach-omap1/board-innovator.c1
-rw-r--r--arch/arm/mach-omap1/board-netstar.c1
-rw-r--r--arch/arm/mach-omap1/board-osk.c1
-rw-r--r--arch/arm/mach-omap1/board-palmte.c1
-rw-r--r--arch/arm/mach-omap1/board-perseus2.c1
-rw-r--r--arch/arm/mach-omap1/board-voiceblue.c1
-rw-r--r--arch/arm/mach-omap2/board-generic.c1
-rw-r--r--arch/arm/mach-omap2/board-h4.c1
-rw-r--r--arch/arm/mach-pxa/corgi.c3
-rw-r--r--arch/arm/mach-pxa/idp.c1
-rw-r--r--arch/arm/mach-pxa/lubbock.c1
-rw-r--r--arch/arm/mach-pxa/mainstone.c1
-rw-r--r--arch/arm/mach-pxa/poodle.c1
-rw-r--r--arch/arm/mach-pxa/spitz.c3
-rw-r--r--arch/arm/mach-pxa/tosa.c1
-rw-r--r--arch/arm/mach-realview/Kconfig1
-rw-r--r--arch/arm/mach-realview/realview_eb.c1
-rw-r--r--arch/arm/mach-rpc/riscpc.c1
-rw-r--r--arch/arm/mach-s3c2410/mach-anubis.c1
-rw-r--r--arch/arm/mach-s3c2410/mach-bast.c1
-rw-r--r--arch/arm/mach-s3c2410/mach-h1940.c1
-rw-r--r--arch/arm/mach-s3c2410/mach-n30.c1
-rw-r--r--arch/arm/mach-s3c2410/mach-nexcoder.c1
-rw-r--r--arch/arm/mach-s3c2410/mach-otom.c1
-rw-r--r--arch/arm/mach-s3c2410/mach-rx3715.c1
-rw-r--r--arch/arm/mach-s3c2410/mach-smdk2410.c1
-rw-r--r--arch/arm/mach-s3c2410/mach-smdk2440.c1
-rw-r--r--arch/arm/mach-s3c2410/mach-vr1000.c1
-rw-r--r--arch/arm/mach-sa1100/assabet.c1
-rw-r--r--arch/arm/mach-sa1100/badge4.c1
-rw-r--r--arch/arm/mach-sa1100/cerf.c1
-rw-r--r--arch/arm/mach-sa1100/collie.c1
-rw-r--r--arch/arm/mach-sa1100/h3600.c3
-rw-r--r--arch/arm/mach-sa1100/hackkit.c1
-rw-r--r--arch/arm/mach-sa1100/jornada720.c1
-rw-r--r--arch/arm/mach-sa1100/lart.c1
-rw-r--r--arch/arm/mach-sa1100/pleb.c1
-rw-r--r--arch/arm/mach-sa1100/shannon.c1
-rw-r--r--arch/arm/mach-sa1100/simpad.c1
-rw-r--r--arch/arm/mach-shark/core.c1
-rw-r--r--arch/arm/mach-versatile/Kconfig1
-rw-r--r--arch/arm/mach-versatile/core.c58
-rw-r--r--arch/arm/mach-versatile/versatile_ab.c1
-rw-r--r--arch/arm/mach-versatile/versatile_pb.c1
-rw-r--r--arch/arm/nwfpe/fpa11.h4
-rw-r--r--arch/arm/plat-omap/Kconfig3
-rw-r--r--arch/i386/Kconfig18
-rw-r--r--arch/i386/Makefile6
-rw-r--r--arch/i386/kernel/traps.c57
-rw-r--r--arch/i386/pci/fixup.c16
-rw-r--r--arch/ia64/configs/gensparse_defconfig2
-rw-r--r--arch/ia64/configs/sn2_defconfig2
-rw-r--r--arch/ia64/hp/sim/simserial.c11
-rw-r--r--arch/ia64/kernel/fsys.S1
-rw-r--r--arch/ia64/kernel/jprobes.S27
-rw-r--r--arch/ia64/kernel/kprobes.c57
-rw-r--r--arch/ia64/kernel/mca_asm.S2
-rw-r--r--arch/ia64/kernel/salinfo.c170
-rw-r--r--arch/ia64/kernel/traps.c26
-rw-r--r--arch/ia64/mm/tlb.c2
-rw-r--r--arch/ia64/sn/include/xtalk/hubdev.h16
-rw-r--r--arch/ia64/sn/kernel/bte_error.c58
-rw-r--r--arch/ia64/sn/kernel/huberror.c9
-rw-r--r--arch/ia64/sn/kernel/io_init.c94
-rw-r--r--arch/ia64/sn/kernel/tiocx.c16
-rw-r--r--arch/ia64/sn/kernel/xpc_channel.c24
-rw-r--r--arch/ia64/sn/kernel/xpc_main.c189
-rw-r--r--arch/ia64/sn/kernel/xpc_partition.c10
-rw-r--r--arch/ia64/sn/pci/pcibr/pcibr_dma.c34
-rw-r--r--arch/ia64/sn/pci/pcibr/pcibr_provider.c20
-rw-r--r--arch/parisc/kernel/drivers.c4
-rw-r--r--arch/powerpc/Makefile7
-rw-r--r--arch/powerpc/boot/Makefile49
-rw-r--r--arch/powerpc/boot/crt0.S21
-rw-r--r--arch/powerpc/boot/hack-coff.c84
-rw-r--r--arch/powerpc/boot/main.c46
-rw-r--r--arch/powerpc/boot/prom.c538
-rw-r--r--arch/powerpc/boot/prom.h36
-rw-r--r--arch/powerpc/boot/rs6000.h243
-rw-r--r--arch/powerpc/boot/stdio.c325
-rw-r--r--arch/powerpc/boot/stdio.h6
-rw-r--r--arch/powerpc/boot/string.S20
-rw-r--r--arch/powerpc/boot/zImage.coff.lds46
-rw-r--r--arch/powerpc/configs/mpc834x_sys_defconfig911
-rw-r--r--arch/powerpc/kernel/asm-offsets.c2
-rw-r--r--arch/powerpc/kernel/cpu_setup_power4.S4
-rw-r--r--arch/powerpc/kernel/cputable.c224
-rw-r--r--arch/powerpc/kernel/entry_32.S2
-rw-r--r--arch/powerpc/kernel/entry_64.S15
-rw-r--r--arch/powerpc/kernel/fpu.S10
-rw-r--r--arch/powerpc/kernel/head_64.S112
-rw-r--r--arch/powerpc/kernel/idle_power4.S8
-rw-r--r--arch/powerpc/kernel/irq.c12
-rw-r--r--arch/powerpc/kernel/lparcfg.c13
-rw-r--r--arch/powerpc/kernel/misc_32.S4
-rw-r--r--arch/powerpc/kernel/misc_64.S10
-rw-r--r--arch/powerpc/kernel/of_device.c4
-rw-r--r--arch/powerpc/kernel/paca.c36
-rw-r--r--arch/powerpc/kernel/ppc_ksyms.c3
-rw-r--r--arch/powerpc/kernel/prom.c109
-rw-r--r--arch/powerpc/kernel/prom_parse.c3
-rw-r--r--arch/powerpc/kernel/rtas.c96
-rw-r--r--arch/powerpc/kernel/setup-common.c9
-rw-r--r--arch/powerpc/kernel/time.c2
-rw-r--r--arch/powerpc/kernel/vio.c8
-rw-r--r--arch/powerpc/lib/locks.c8
-rw-r--r--arch/powerpc/oprofile/common.c8
-rw-r--r--arch/powerpc/platforms/83xx/Kconfig1
-rw-r--r--arch/powerpc/platforms/83xx/mpc834x_sys.c243
-rw-r--r--arch/powerpc/platforms/83xx/mpc834x_sys.h23
-rw-r--r--arch/powerpc/platforms/83xx/mpc83xx.h14
-rw-r--r--arch/powerpc/platforms/83xx/pci.c99
-rw-r--r--arch/powerpc/platforms/chrp/pci.c27
-rw-r--r--arch/powerpc/platforms/chrp/setup.c7
-rw-r--r--arch/powerpc/platforms/chrp/time.c7
-rw-r--r--arch/powerpc/platforms/iseries/irq.c6
-rw-r--r--arch/powerpc/platforms/iseries/misc.S3
-rw-r--r--arch/powerpc/platforms/iseries/setup.c8
-rw-r--r--arch/powerpc/platforms/iseries/smp.c2
-rw-r--r--arch/powerpc/platforms/pseries/lpar.c4
-rw-r--r--arch/powerpc/platforms/pseries/reconfig.c100
-rw-r--r--arch/powerpc/platforms/pseries/setup.c20
-rw-r--r--arch/powerpc/sysdev/Makefile1
-rw-r--r--arch/powerpc/sysdev/fsl_soc.c317
-rw-r--r--arch/powerpc/sysdev/fsl_soc.h8
-rw-r--r--arch/ppc/4xx_io/serial_sicc.c1
-rw-r--r--arch/ppc/kernel/head_8xx.S77
-rw-r--r--arch/ppc/kernel/ppc_ksyms.c1
-rw-r--r--arch/ppc/platforms/83xx/mpc834x_sys.c10
-rw-r--r--arch/ppc/platforms/85xx/mpc8540_ads.c14
-rw-r--r--arch/ppc/platforms/85xx/mpc8560_ads.c11
-rw-r--r--arch/ppc/platforms/85xx/mpc85xx_cds_common.c16
-rw-r--r--arch/ppc/platforms/85xx/sbc8560.c10
-rw-r--r--arch/ppc/platforms/85xx/stx_gp3.c10
-rw-r--r--arch/ppc/platforms/85xx/tqm85xx.c16
-rw-r--r--arch/ppc/syslib/mpc83xx_devices.c10
-rw-r--r--arch/ppc/syslib/mpc85xx_devices.c10
-rw-r--r--arch/ppc/syslib/ocp.c4
-rw-r--r--arch/s390/crypto/aes_s390.c60
-rw-r--r--arch/s390/crypto/des_s390.c360
-rw-r--r--arch/s390/crypto/sha256_s390.c29
-rw-r--r--arch/s390/kernel/process.c14
-rw-r--r--arch/s390/kernel/setup.c11
-rw-r--r--arch/s390/kernel/time.c2
-rw-r--r--arch/s390/kernel/vtime.c27
-rw-r--r--arch/s390/lib/Makefile3
-rw-r--r--arch/s390/lib/spinlock.c7
-rw-r--r--arch/sh/kernel/cpu/bus.c34
-rw-r--r--arch/um/Makefile3
-rw-r--r--block/genhd.c106
-rw-r--r--drivers/Kconfig2
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/acpi/ec.c2
-rw-r--r--drivers/base/dd.c12
-rw-r--r--drivers/base/driver.c5
-rw-r--r--drivers/base/firmware_class.c2
-rw-r--r--drivers/base/platform.c2
-rw-r--r--drivers/base/power/shutdown.c9
-rw-r--r--drivers/block/loop.c2
-rw-r--r--drivers/block/pktcdvd.c4
-rw-r--r--drivers/bluetooth/hci_bcsp.c2
-rw-r--r--drivers/char/amiserial.c1
-rw-r--r--drivers/char/drm/r128_state.c2
-rw-r--r--drivers/char/esp.c1
-rw-r--r--drivers/char/generic_serial.c1
-rw-r--r--drivers/char/riscom8.c1
-rw-r--r--drivers/char/serial167.c1
-rw-r--r--drivers/char/specialix.c3
-rw-r--r--drivers/char/synclink.c1
-rw-r--r--drivers/char/watchdog/Kconfig26
-rw-r--r--drivers/char/watchdog/Makefile2
-rw-r--r--drivers/char/watchdog/mpc83xx_wdt.c229
-rw-r--r--drivers/char/watchdog/sbc_epx_c3.c216
-rw-r--r--drivers/cpufreq/cpufreq.c7
-rw-r--r--drivers/dio/dio-driver.c4
-rw-r--r--drivers/firmware/dell_rbu.c26
-rw-r--r--drivers/i2c/i2c-core.c20
-rw-r--r--drivers/ide/ide-cd.c18
-rw-r--r--drivers/ide/ide-disk.c24
-rw-r--r--drivers/ide/ide-floppy.c14
-rw-r--r--drivers/ide/ide-tape.c18
-rw-r--r--drivers/ide/ide-taskfile.c2
-rw-r--r--drivers/ide/ide.c31
-rw-r--r--drivers/infiniband/core/cm.c33
-rw-r--r--drivers/infiniband/core/device.c23
-rw-r--r--drivers/infiniband/core/sysfs.c22
-rw-r--r--drivers/infiniband/core/ucm.c23
-rw-r--r--drivers/infiniband/core/uverbs.h5
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c152
-rw-r--r--drivers/infiniband/core/uverbs_main.c8
-rw-r--r--drivers/infiniband/hw/mthca/mthca_av.c10
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cmd.c7
-rw-r--r--drivers/infiniband/hw/mthca/mthca_dev.h1
-rw-r--r--drivers/infiniband/hw/mthca/mthca_eq.c28
-rw-r--r--drivers/infiniband/hw/mthca/mthca_provider.c132
-rw-r--r--drivers/infiniband/hw/mthca/mthca_qp.c2
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h6
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c31
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c12
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c105
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_verbs.c8
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_vlan.c10
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c23
-rw-r--r--drivers/input/gameport/gameport.c12
-rw-r--r--drivers/input/input.c55
-rw-r--r--drivers/input/mouse/alps.c38
-rw-r--r--drivers/input/mouse/logips2pp.c2
-rw-r--r--drivers/input/mouse/psmouse-base.c316
-rw-r--r--drivers/input/mouse/psmouse.h9
-rw-r--r--drivers/input/mouse/synaptics.c2
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h7
-rw-r--r--drivers/input/serio/serio.c12
-rw-r--r--drivers/input/touchscreen/Kconfig13
-rw-r--r--drivers/input/touchscreen/Makefile1
-rw-r--r--drivers/input/touchscreen/ads7846.c625
-rw-r--r--drivers/isdn/hisax/avm_pci.c2
-rw-r--r--drivers/isdn/hisax/diva.c2
-rw-r--r--drivers/isdn/hisax/hscx_irq.c4
-rw-r--r--drivers/isdn/hisax/jade_irq.c2
-rw-r--r--drivers/macintosh/macio-adb.c13
-rw-r--r--drivers/macintosh/macio_asic.c6
-rw-r--r--drivers/md/bitmap.c2
-rw-r--r--drivers/md/dm-crypt.c2
-rw-r--r--drivers/md/dm-ioctl.c4
-rw-r--r--drivers/md/dm-snap.c2
-rw-r--r--drivers/md/dm.c2
-rw-r--r--drivers/md/raid1.c4
-rw-r--r--drivers/md/raid10.c4
-rw-r--r--drivers/md/raid5.c10
-rw-r--r--drivers/md/raid6main.c8
-rw-r--r--drivers/media/dvb/bt8xx/dvb-bt8xx.c23
-rw-r--r--drivers/media/video/bttv-gpio.c24
-rw-r--r--drivers/media/video/bttv.h2
-rw-r--r--drivers/media/video/tvp5150.c2
-rw-r--r--drivers/message/fusion/Kconfig1
-rw-r--r--drivers/message/fusion/lsi/mpi.h10
-rw-r--r--drivers/message/fusion/lsi/mpi_cnfg.h158
-rw-r--r--drivers/message/fusion/lsi/mpi_history.txt77
-rw-r--r--drivers/message/fusion/lsi/mpi_init.h8
-rw-r--r--drivers/message/fusion/lsi/mpi_ioc.h122
-rw-r--r--drivers/message/fusion/lsi/mpi_log_fc.h89
-rw-r--r--drivers/message/fusion/lsi/mpi_log_sas.h162
-rw-r--r--drivers/message/fusion/lsi/mpi_sas.h30
-rw-r--r--drivers/message/fusion/mptbase.c48
-rw-r--r--drivers/message/fusion/mptbase.h34
-rw-r--r--drivers/message/fusion/mptctl.c12
-rw-r--r--drivers/message/fusion/mptfc.c579
-rw-r--r--drivers/message/fusion/mptlan.c18
-rw-r--r--drivers/message/fusion/mptsas.c404
-rw-r--r--drivers/message/fusion/mptscsih.c34
-rw-r--r--drivers/message/fusion/mptspi.c26
-rw-r--r--drivers/message/i2o/pci.c10
-rw-r--r--drivers/mfd/mcp-core.c4
-rw-r--r--drivers/mmc/mmc_sysfs.c26
-rw-r--r--drivers/mtd/devices/Kconfig16
-rw-r--r--drivers/mtd/devices/Makefile2
-rw-r--r--drivers/mtd/devices/doc2000.c2
-rw-r--r--drivers/mtd/devices/doc2001.c2
-rw-r--r--drivers/mtd/devices/doc2001plus.c2
-rw-r--r--drivers/mtd/devices/m25p80.c582
-rw-r--r--drivers/mtd/devices/mtd_dataflash.c629
-rw-r--r--drivers/mtd/nand/diskonchip.c2
-rw-r--r--drivers/net/Kconfig2
-rw-r--r--drivers/net/cs89x0.c74
-rw-r--r--drivers/net/e100.c18
-rw-r--r--drivers/net/sb1000.c4
-rw-r--r--drivers/net/wireless/hostap/hostap_80211_rx.c10
-rw-r--r--drivers/net/wireless/hostap/hostap_hw.c8
-rw-r--r--drivers/net/wireless/ipw2100.c26
-rw-r--r--drivers/net/wireless/ipw2200.c42
-rw-r--r--drivers/net/wireless/wavelan.c38
-rw-r--r--drivers/pci/pci-driver.c4
-rw-r--r--drivers/pcmcia/ds.c4
-rw-r--r--drivers/pnp/driver.c4
-rw-r--r--drivers/rapidio/rio-driver.c6
-rw-r--r--drivers/s390/block/dasd.c2
-rw-r--r--drivers/s390/cio/airq.c4
-rw-r--r--drivers/s390/cio/blacklist.c4
-rw-r--r--drivers/s390/cio/ccwgroup.c20
-rw-r--r--drivers/s390/cio/chsc.c4
-rw-r--r--drivers/s390/cio/cio.c4
-rw-r--r--drivers/s390/cio/css.c40
-rw-r--r--drivers/s390/cio/css.h6
-rw-r--r--drivers/s390/cio/device.c54
-rw-r--r--drivers/s390/cio/device_fsm.c2
-rw-r--r--drivers/s390/cio/device_id.c2
-rw-r--r--drivers/s390/cio/device_ops.c4
-rw-r--r--drivers/s390/cio/device_pgid.c2
-rw-r--r--drivers/s390/cio/device_status.c2
-rw-r--r--drivers/s390/cio/qdio.c4
-rw-r--r--drivers/s390/net/ctcmain.c8
-rw-r--r--drivers/s390/net/cu3088.c4
-rw-r--r--drivers/s390/net/netiucv.c9
-rw-r--r--drivers/s390/s390_rdev.c4
-rw-r--r--drivers/s390/scsi/zfcp_aux.c2
-rw-r--r--drivers/s390/scsi/zfcp_def.h4
-rw-r--r--drivers/s390/scsi/zfcp_erp.c2
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c84
-rw-r--r--drivers/s390/scsi/zfcp_fsf.h13
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c188
-rw-r--r--drivers/s390/scsi/zfcp_sysfs_adapter.c15
-rw-r--r--drivers/s390/scsi/zfcp_sysfs_port.c4
-rw-r--r--drivers/s390/scsi/zfcp_sysfs_unit.c2
-rw-r--r--drivers/sbus/char/aurora.c1
-rw-r--r--drivers/scsi/3w-9xxx.c7
-rw-r--r--drivers/scsi/3w-9xxx.h2
-rw-r--r--drivers/scsi/3w-xxxx.c7
-rw-r--r--drivers/scsi/3w-xxxx.h2
-rw-r--r--drivers/scsi/BusLogic.c3
-rw-r--r--drivers/scsi/Makefile2
-rw-r--r--drivers/scsi/aacraid/README74
-rw-r--r--drivers/scsi/aacraid/aacraid.h7
-rw-r--r--drivers/scsi/aacraid/commctrl.c4
-rw-r--r--drivers/scsi/aacraid/linit.c35
-rw-r--r--drivers/scsi/aic7xxx/Kconfig.aic7xxx4
-rw-r--r--drivers/scsi/aic7xxx/aic79xx.h39
-rw-r--r--drivers/scsi/aic7xxx/aic79xx.reg60
-rw-r--r--drivers/scsi/aic7xxx/aic79xx.seq241
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_core.c771
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_inline.h38
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.c62
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.h2
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_pci.c24
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_pci.h5
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_reg.h_shipped646
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped507
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_seq.h_shipped1250
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.c28
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.h25
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_pci.c24
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_pci.h1
-rw-r--r--drivers/scsi/aic7xxx_old.c4
-rw-r--r--drivers/scsi/ch.c33
-rw-r--r--drivers/scsi/dpt_i2o.c45
-rw-r--r--drivers/scsi/hosts.c8
-rw-r--r--drivers/scsi/ips.c3
-rw-r--r--drivers/scsi/iscsi_tcp.c305
-rw-r--r--drivers/scsi/iscsi_tcp.h6
-rw-r--r--drivers/scsi/libata-core.c2
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c2
-rw-r--r--drivers/scsi/megaraid.c6
-rw-r--r--drivers/scsi/megaraid.h4
-rw-r--r--drivers/scsi/megaraid/megaraid_mbox.c10
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.c25
-rw-r--r--drivers/scsi/qla2xxx/Kconfig24
-rw-r--r--drivers/scsi/qla2xxx/Makefile2
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c4
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.c105
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.h4
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h6
-rw-r--r--drivers/scsi/qla2xxx/qla_gs.c8
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c24
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c14
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c107
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c6
-rw-r--r--drivers/scsi/qla2xxx/qla_sup.c3
-rw-r--r--drivers/scsi/qla2xxx/qla_version.h4
-rw-r--r--drivers/scsi/raid_class.c2
-rw-r--r--drivers/scsi/scsi.c13
-rw-r--r--drivers/scsi/scsi_debug.c4
-rw-r--r--drivers/scsi/scsi_lib.c16
-rw-r--r--drivers/scsi/scsi_priv.h6
-rw-r--r--drivers/scsi/scsi_proc.c17
-rw-r--r--drivers/scsi/scsi_scan.c32
-rw-r--r--drivers/scsi/scsi_sysfs.c9
-rw-r--r--drivers/scsi/scsi_transport_fc.c26
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c859
-rw-r--r--drivers/scsi/scsi_transport_sas.c58
-rw-r--r--drivers/scsi/scsi_transport_spi.c12
-rw-r--r--drivers/scsi/sd.c63
-rw-r--r--drivers/scsi/sr.c45
-rw-r--r--drivers/scsi/sr_ioctl.c202
-rw-r--r--drivers/scsi/st.c42
-rw-r--r--drivers/serial/68328serial.c1
-rw-r--r--drivers/serial/Kconfig9
-rw-r--r--drivers/serial/Makefile1
-rw-r--r--drivers/serial/imx.c2
-rw-r--r--drivers/serial/ioc3_serial.c2197
-rw-r--r--drivers/sh/superhyway/superhyway.c4
-rw-r--r--drivers/sn/Kconfig14
-rw-r--r--drivers/sn/Makefile1
-rw-r--r--drivers/sn/ioc3.c851
-rw-r--r--drivers/spi/Kconfig109
-rw-r--r--drivers/spi/Makefile25
-rw-r--r--drivers/spi/spi.c642
-rw-r--r--drivers/spi/spi_bitbang.c472
-rw-r--r--drivers/spi/spi_butterfly.c423
-rw-r--r--drivers/usb/atm/usbatm.c4
-rw-r--r--drivers/usb/gadget/ether.c3
-rw-r--r--drivers/usb/gadget/inode.c3
-rw-r--r--drivers/usb/gadget/serial.c3
-rw-r--r--drivers/usb/gadget/zero.c3
-rw-r--r--drivers/usb/input/Kconfig10
-rw-r--r--drivers/usb/input/hid-core.c30
-rw-r--r--drivers/usb/input/hid-input.c179
-rw-r--r--drivers/usb/input/hid.h30
-rw-r--r--drivers/usb/input/pid.c2
-rw-r--r--drivers/usb/input/wacom.c14
-rw-r--r--drivers/usb/serial/bus.c15
-rw-r--r--drivers/usb/serial/pl2303.c2
-rw-r--r--drivers/video/68328fb.c6
-rw-r--r--drivers/video/acornfb.c2
-rw-r--r--drivers/video/amba-clcd.c2
-rw-r--r--drivers/video/amifb.c9
-rw-r--r--drivers/video/arcfb.c5
-rw-r--r--drivers/video/atafb.c3
-rw-r--r--drivers/video/aty/aty128fb.c6
-rw-r--r--drivers/video/aty/atyfb_base.c10
-rw-r--r--drivers/video/aty/radeon_base.c4
-rw-r--r--drivers/video/au1100fb.c2
-rw-r--r--drivers/video/bw2.c10
-rw-r--r--drivers/video/cg14.c10
-rw-r--r--drivers/video/cg3.c10
-rw-r--r--drivers/video/cg6.c10
-rw-r--r--drivers/video/controlfb.c4
-rw-r--r--drivers/video/fbmem.c6
-rw-r--r--drivers/video/ffb.c10
-rw-r--r--drivers/video/gbefb.c3
-rw-r--r--drivers/video/geode/gx1fb_core.c11
-rw-r--r--drivers/video/igafb.c2
-rw-r--r--drivers/video/imsttfb.c3
-rw-r--r--drivers/video/intelfb/intelfbdrv.c8
-rw-r--r--drivers/video/kyro/fbdev.c5
-rw-r--r--drivers/video/leo.c10
-rw-r--r--drivers/video/matrox/matroxfb_base.c5
-rw-r--r--drivers/video/matrox/matroxfb_crtc2.c9
-rw-r--r--drivers/video/matrox/matroxfb_maven.c2
-rw-r--r--drivers/video/neofb.c2
-rw-r--r--drivers/video/p9100.c11
-rw-r--r--drivers/video/pm3fb.c8
-rw-r--r--drivers/video/pmag-aa-fb.c3
-rw-r--r--drivers/video/pxafb.c2
-rw-r--r--drivers/video/radeonfb.c4
-rw-r--r--drivers/video/sa1100fb.c2
-rw-r--r--drivers/video/sgivwfb.c5
-rw-r--r--drivers/video/sis/sis_main.c28
-rw-r--r--drivers/video/sis/sis_main.h5
-rw-r--r--drivers/video/sstfb.c3
-rw-r--r--drivers/video/tcx.c11
-rw-r--r--drivers/video/vfb.c4
-rw-r--r--drivers/zorro/zorro-driver.c4
-rw-r--r--fs/9p/conv.c32
-rw-r--r--fs/autofs4/root.c2
-rw-r--r--fs/binfmt_elf.c4
-rw-r--r--fs/binfmt_misc.c2
-rw-r--r--fs/bio.c4
-rw-r--r--fs/buffer.c6
-rw-r--r--fs/char_dev.c96
-rw-r--r--fs/compat.c4
-rw-r--r--fs/dcache.c2
-rw-r--r--fs/exec.c6
-rw-r--r--fs/ext2/namei.c5
-rw-r--r--fs/ext3/namei.c5
-rw-r--r--fs/fcntl.c2
-rw-r--r--fs/hugetlbfs/inode.c2
-rw-r--r--fs/isofs/namei.c5
-rw-r--r--fs/jffs2/build.c2
-rw-r--r--fs/jffs2/nodelist.c4
-rw-r--r--fs/lockd/xdr.c6
-rw-r--r--fs/mbcache.c6
-rw-r--r--fs/namei.c16
-rw-r--r--fs/ncpfs/inode.c19
-rw-r--r--fs/ncpfs/ioctl.c20
-rw-r--r--fs/nfsd/nfsxdr.c4
-rw-r--r--fs/pipe.c4
-rw-r--r--fs/proc/proc_devtree.c24
-rw-r--r--fs/proc/proc_misc.c160
-rw-r--r--fs/quota_v2.c3
-rw-r--r--fs/reiserfs/namei.c6
-rw-r--r--fs/smbfs/Makefile1
-rw-r--r--fs/smbfs/inode.c32
-rw-r--r--fs/smbfs/request.c13
-rw-r--r--fs/ufs/balloc.c19
-rw-r--r--fs/ufs/ialloc.c4
-rw-r--r--fs/ufs/inode.c11
-rw-r--r--fs/ufs/super.c57
-rw-r--r--fs/ufs/util.h28
-rw-r--r--include/asm-arm/arch-ixp2000/ixp2000-regs.h10
-rw-r--r--include/asm-arm/arch-versatile/entry-macro.S1
-rw-r--r--include/asm-arm/arch-versatile/platform.h23
-rw-r--r--include/asm-arm/hardware/vic.h45
-rw-r--r--include/asm-arm/mach/arch.h2
-rw-r--r--include/asm-arm/page.h7
-rw-r--r--include/asm-arm/processor.h7
-rw-r--r--include/asm-arm/ptrace.h11
-rw-r--r--include/asm-arm/stat.h11
-rw-r--r--include/asm-arm/statfs.h38
-rw-r--r--include/asm-arm/unistd.h65
-rw-r--r--include/asm-i386/bitops.h2
-rw-r--r--include/asm-i386/current.h2
-rw-r--r--include/asm-i386/string.h8
-rw-r--r--include/asm-i386/uaccess.h8
-rw-r--r--include/asm-ia64/kprobes.h6
-rw-r--r--include/asm-ia64/sn/ioc3.h241
-rw-r--r--include/asm-ia64/sn/sn_sal.h5
-rw-r--r--include/asm-ia64/sn/xp.h4
-rw-r--r--include/asm-ia64/sn/xpc.h (renamed from arch/ia64/sn/kernel/xpc.h)11
-rw-r--r--include/asm-ia64/thread_info.h4
-rw-r--r--include/asm-powerpc/atomic.h46
-rw-r--r--include/asm-powerpc/bitops.h6
-rw-r--r--include/asm-powerpc/cputable.h14
-rw-r--r--include/asm-powerpc/elf.h16
-rw-r--r--include/asm-powerpc/futex.h2
-rw-r--r--include/asm-powerpc/hvcall.h5
-rw-r--r--include/asm-powerpc/lppaca.h6
-rw-r--r--include/asm-powerpc/paca.h14
-rw-r--r--include/asm-powerpc/ppc_asm.h76
-rw-r--r--include/asm-powerpc/prom.h8
-rw-r--r--include/asm-powerpc/spinlock.h21
-rw-r--r--include/asm-powerpc/synch.h23
-rw-r--r--include/asm-powerpc/system.h8
-rw-r--r--include/asm-powerpc/time.h5
-rw-r--r--include/asm-s390/s390_rdev.h2
-rw-r--r--include/asm-s390/sigcontext.h2
-rw-r--r--include/asm-s390/system.h5
-rw-r--r--include/asm-x86_64/fixmap.h2
-rw-r--r--include/asm-x86_64/uaccess.h6
-rw-r--r--include/linux/auxvec.h2
-rw-r--r--include/linux/compiler-gcc3.h1
-rw-r--r--include/linux/compiler-gcc4.h11
-rw-r--r--include/linux/cpuset.h6
-rw-r--r--include/linux/device.h3
-rw-r--r--include/linux/fb.h10
-rw-r--r--include/linux/fs.h11
-rw-r--r--include/linux/hardirq.h4
-rw-r--r--include/linux/ide.h5
-rw-r--r--include/linux/ioc3.h93
-rw-r--r--include/linux/kernel.h2
-rw-r--r--include/linux/mempolicy.h11
-rw-r--r--include/linux/mm.h2
-rw-r--r--include/linux/ncp_fs.h28
-rw-r--r--include/linux/netfilter/nf_conntrack_common.h3
-rw-r--r--include/linux/netfilter/x_tables.h224
-rw-r--r--include/linux/netfilter/xt_CLASSIFY.h8
-rw-r--r--include/linux/netfilter/xt_CONNMARK.h25
-rw-r--r--include/linux/netfilter/xt_MARK.h21
-rw-r--r--include/linux/netfilter/xt_NFQUEUE.h16
-rw-r--r--include/linux/netfilter/xt_comment.h10
-rw-r--r--include/linux/netfilter/xt_connbytes.h25
-rw-r--r--include/linux/netfilter/xt_connmark.h18
-rw-r--r--include/linux/netfilter/xt_conntrack.h63
-rw-r--r--include/linux/netfilter/xt_dccp.h23
-rw-r--r--include/linux/netfilter/xt_helper.h8
-rw-r--r--include/linux/netfilter/xt_length.h9
-rw-r--r--include/linux/netfilter/xt_limit.h21
-rw-r--r--include/linux/netfilter/xt_mac.h8
-rw-r--r--include/linux/netfilter/xt_mark.h9
-rw-r--r--include/linux/netfilter/xt_physdev.h24
-rw-r--r--include/linux/netfilter/xt_pkttype.h8
-rw-r--r--include/linux/netfilter/xt_realm.h10
-rw-r--r--include/linux/netfilter/xt_sctp.h107
-rw-r--r--include/linux/netfilter/xt_state.h13
-rw-r--r--include/linux/netfilter/xt_string.h18
-rw-r--r--include/linux/netfilter/xt_tcpmss.h9
-rw-r--r--include/linux/netfilter/xt_tcpudp.h36
-rw-r--r--include/linux/netfilter_arp/arp_tables.h123
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack.h3
-rw-r--r--include/linux/netfilter_ipv4/ip_tables.h217
-rw-r--r--include/linux/netfilter_ipv4/ipt_CLASSIFY.h5
-rw-r--r--include/linux/netfilter_ipv4/ipt_CONNMARK.h16
-rw-r--r--include/linux/netfilter_ipv4/ipt_MARK.h22
-rw-r--r--include/linux/netfilter_ipv4/ipt_NFQUEUE.h8
-rw-r--r--include/linux/netfilter_ipv4/ipt_comment.h8
-rw-r--r--include/linux/netfilter_ipv4/ipt_connbytes.h31
-rw-r--r--include/linux/netfilter_ipv4/ipt_connmark.h15
-rw-r--r--include/linux/netfilter_ipv4/ipt_conntrack.h66
-rw-r--r--include/linux/netfilter_ipv4/ipt_dccp.h22
-rw-r--r--include/linux/netfilter_ipv4/ipt_helper.h7
-rw-r--r--include/linux/netfilter_ipv4/ipt_length.h6
-rw-r--r--include/linux/netfilter_ipv4/ipt_limit.h19
-rw-r--r--include/linux/netfilter_ipv4/ipt_mac.h7
-rw-r--r--include/linux/netfilter_ipv4/ipt_mark.h8
-rw-r--r--include/linux/netfilter_ipv4/ipt_physdev.h27
-rw-r--r--include/linux/netfilter_ipv4/ipt_pkttype.h7
-rw-r--r--include/linux/netfilter_ipv4/ipt_realm.h7
-rw-r--r--include/linux/netfilter_ipv4/ipt_state.h16
-rw-r--r--include/linux/netfilter_ipv4/ipt_string.h16
-rw-r--r--include/linux/netfilter_ipv4/ipt_tcpmss.h6
-rw-r--r--include/linux/netfilter_ipv6/ip6_tables.h208
-rw-r--r--include/linux/netfilter_ipv6/ip6t_MARK.h9
-rw-r--r--include/linux/netfilter_ipv6/ip6t_length.h6
-rw-r--r--include/linux/netfilter_ipv6/ip6t_limit.h21
-rw-r--r--include/linux/netfilter_ipv6/ip6t_mac.h9
-rw-r--r--include/linux/netfilter_ipv6/ip6t_mark.h8
-rw-r--r--include/linux/netfilter_ipv6/ip6t_physdev.h27
-rw-r--r--include/linux/pci_ids.h1
-rw-r--r--include/linux/proc_fs.h5
-rw-r--r--include/linux/raid_class.h2
-rw-r--r--include/linux/sched.h7
-rw-r--r--include/linux/shmem_fs.h2
-rw-r--r--include/linux/smb_fs.h47
-rw-r--r--include/linux/socket.h3
-rw-r--r--include/linux/spi/ads7846.h18
-rw-r--r--include/linux/spi/flash.h31
-rw-r--r--include/linux/spi/spi.h668
-rw-r--r--include/linux/spi/spi_bitbang.h135
-rw-r--r--include/linux/swap.h5
-rw-r--r--include/linux/tipc.h212
-rw-r--r--include/linux/tipc_config.h407
-rw-r--r--include/net/genetlink.h1
-rw-r--r--include/net/netfilter/ipv4/nf_conntrack_ipv4.h3
-rw-r--r--include/net/netfilter/nf_conntrack.h3
-rw-r--r--include/net/netfilter/nf_conntrack_tuple.h2
-rw-r--r--include/net/sctp/sctp.h4
-rw-r--r--include/net/tipc/tipc.h257
-rw-r--r--include/net/tipc/tipc_bearer.h121
-rw-r--r--include/net/tipc/tipc_msg.h223
-rw-r--r--include/net/tipc/tipc_port.h108
-rw-r--r--include/rdma/ib_verbs.h2
-rw-r--r--include/scsi/iscsi_if.h6
-rw-r--r--include/scsi/scsi.h6
-rw-r--r--include/scsi/scsi_cmnd.h1
-rw-r--r--include/scsi/scsi_host.h3
-rw-r--r--include/scsi/scsi_transport.h7
-rw-r--r--include/scsi/scsi_transport_fc.h4
-rw-r--r--include/scsi/scsi_transport_iscsi.h75
-rw-r--r--include/scsi/scsi_transport_spi.h2
-rw-r--r--init/main.c16
-rw-r--r--ipc/mqueue.c59
-rw-r--r--kernel/cpuset.c35
-rw-r--r--kernel/exit.c14
-rw-r--r--kernel/posix-timers.c8
-rw-r--r--kernel/sched.c64
-rw-r--r--kernel/signal.c4
-rw-r--r--kernel/sysctl.c2
-rw-r--r--kernel/workqueue.c2
-rw-r--r--lib/Kconfig.debug14
-rw-r--r--mm/mempolicy.c24
-rw-r--r--mm/oom_kill.c3
-rw-r--r--mm/shmem.c39
-rw-r--r--net/Kconfig1
-rw-r--r--net/Makefile1
-rw-r--r--net/bridge/netfilter/ebt_log.c1
-rw-r--r--net/core/filter.c10
-rw-r--r--net/ieee80211/ieee80211_module.c4
-rw-r--r--net/ieee80211/ieee80211_rx.c14
-rw-r--r--net/ieee80211/ieee80211_tx.c4
-rw-r--r--net/ieee80211/ieee80211_wx.c2
-rw-r--r--net/ipv4/netfilter/Kconfig250
-rw-r--r--net/ipv4/netfilter/Makefile21
-rw-r--r--net/ipv4/netfilter/arp_tables.c444
-rw-r--r--net/ipv4/netfilter/arpt_mangle.c7
-rw-r--r--net/ipv4/netfilter/arptable_filter.c1
-rw-r--r--net/ipv4/netfilter/ip_conntrack_standalone.c4
-rw-r--r--net/ipv4/netfilter/ip_nat_rule.c5
-rw-r--r--net/ipv4/netfilter/ip_nat_standalone.c2
-rw-r--r--net/ipv4/netfilter/ip_tables.c842
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c3
-rw-r--r--net/ipv4/netfilter/ipt_DSCP.c2
-rw-r--r--net/ipv4/netfilter/ipt_ECN.c3
-rw-r--r--net/ipv4/netfilter/ipt_LOG.c2
-rw-r--r--net/ipv4/netfilter/ipt_MASQUERADE.c2
-rw-r--r--net/ipv4/netfilter/ipt_NETMAP.c2
-rw-r--r--net/ipv4/netfilter/ipt_NFQUEUE.c70
-rw-r--r--net/ipv4/netfilter/ipt_REDIRECT.c2
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c3
-rw-r--r--net/ipv4/netfilter/ipt_SAME.c2
-rw-r--r--net/ipv4/netfilter/ipt_TCPMSS.c3
-rw-r--r--net/ipv4/netfilter/ipt_TOS.c2
-rw-r--r--net/ipv4/netfilter/ipt_TTL.c2
-rw-r--r--net/ipv4/netfilter/ipt_ULOG.c2
-rw-r--r--net/ipv4/netfilter/ipt_addrtype.c4
-rw-r--r--net/ipv4/netfilter/ipt_ah.c6
-rw-r--r--net/ipv4/netfilter/ipt_dscp.c4
-rw-r--r--net/ipv4/netfilter/ipt_ecn.c5
-rw-r--r--net/ipv4/netfilter/ipt_esp.c6
-rw-r--r--net/ipv4/netfilter/ipt_hashlimit.c3
-rw-r--r--net/ipv4/netfilter/ipt_iprange.c4
-rw-r--r--net/ipv4/netfilter/ipt_length.c64
-rw-r--r--net/ipv4/netfilter/ipt_multiport.c10
-rw-r--r--net/ipv4/netfilter/ipt_owner.c3
-rw-r--r--net/ipv4/netfilter/ipt_physdev.c135
-rw-r--r--net/ipv4/netfilter/ipt_recent.c6
-rw-r--r--net/ipv4/netfilter/ipt_tos.c3
-rw-r--r--net/ipv4/netfilter/ipt_ttl.c4
-rw-r--r--net/ipv4/netfilter/iptable_filter.c3
-rw-r--r--net/ipv4/netfilter/iptable_mangle.c1
-rw-r--r--net/ipv4/netfilter/iptable_raw.c3
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c7
-rw-r--r--net/ipv4/xfrm4_state.c15
-rw-r--r--net/ipv6/addrconf.c2
-rw-r--r--net/ipv6/ah6.c3
-rw-r--r--net/ipv6/anycast.c4
-rw-r--r--net/ipv6/esp6.c3
-rw-r--r--net/ipv6/icmp.c2
-rw-r--r--net/ipv6/ip6_flowlabel.c8
-rw-r--r--net/ipv6/ipcomp6.c3
-rw-r--r--net/ipv6/mcast.c9
-rw-r--r--net/ipv6/ndisc.c2
-rw-r--r--net/ipv6/netfilter/Kconfig72
-rw-r--r--net/ipv6/netfilter/Makefile6
-rw-r--r--net/ipv6/netfilter/ip6_tables.c828
-rw-r--r--net/ipv6/netfilter/ip6t_HL.c2
-rw-r--r--net/ipv6/netfilter/ip6t_LOG.c7
-rw-r--r--net/ipv6/netfilter/ip6t_MARK.c81
-rw-r--r--net/ipv6/netfilter/ip6t_NFQUEUE.c70
-rw-r--r--net/ipv6/netfilter/ip6t_REJECT.c3
-rw-r--r--net/ipv6/netfilter/ip6t_ah.c2
-rw-r--r--net/ipv6/netfilter/ip6t_dst.c2
-rw-r--r--net/ipv6/netfilter/ip6t_esp.c2
-rw-r--r--net/ipv6/netfilter/ip6t_eui64.c2
-rw-r--r--net/ipv6/netfilter/ip6t_frag.c2
-rw-r--r--net/ipv6/netfilter/ip6t_hbh.c2
-rw-r--r--net/ipv6/netfilter/ip6t_hl.c2
-rw-r--r--net/ipv6/netfilter/ip6t_ipv6header.c2
-rw-r--r--net/ipv6/netfilter/ip6t_length.c66
-rw-r--r--net/ipv6/netfilter/ip6t_limit.c147
-rw-r--r--net/ipv6/netfilter/ip6t_mac.c81
-rw-r--r--net/ipv6/netfilter/ip6t_mark.c66
-rw-r--r--net/ipv6/netfilter/ip6t_multiport.c3
-rw-r--r--net/ipv6/netfilter/ip6t_owner.c2
-rw-r--r--net/ipv6/netfilter/ip6t_rt.c2
-rw-r--r--net/ipv6/netfilter/ip6table_filter.c1
-rw-r--r--net/ipv6/netfilter/ip6table_mangle.c1
-rw-r--r--net/ipv6/netfilter/ip6table_raw.c5
-rw-r--r--net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c10
-rw-r--r--net/ipv6/netfilter/nf_conntrack_reasm.c45
-rw-r--r--net/ipv6/xfrm6_state.c17
-rw-r--r--net/ipv6/xfrm6_tunnel.c8
-rw-r--r--net/netfilter/Kconfig258
-rw-r--r--net/netfilter/Makefile37
-rw-r--r--net/netfilter/nf_conntrack_ftp.c4
-rw-r--r--net/netfilter/nf_conntrack_standalone.c4
-rw-r--r--net/netfilter/nfnetlink.c2
-rw-r--r--net/netfilter/x_tables.c624
-rw-r--r--net/netfilter/xt_CLASSIFY.c (renamed from net/ipv4/netfilter/ipt_CLASSIFY.c)41
-rw-r--r--net/netfilter/xt_CONNMARK.c (renamed from net/ipv4/netfilter/ipt_CONNMARK.c)51
-rw-r--r--net/netfilter/xt_MARK.c (renamed from net/ipv4/netfilter/ipt_MARK.c)79
-rw-r--r--net/netfilter/xt_NFQUEUE.c107
-rw-r--r--net/netfilter/xt_NOTRACK.c (renamed from net/ipv4/netfilter/ipt_NOTRACK.c)38
-rw-r--r--net/netfilter/xt_comment.c (renamed from net/ipv4/netfilter/ipt_comment.c)35
-rw-r--r--net/netfilter/xt_connbytes.c (renamed from net/ipv4/netfilter/ipt_connbytes.c)73
-rw-r--r--net/netfilter/xt_connmark.c (renamed from net/ipv4/netfilter/ipt_connmark.c)41
-rw-r--r--net/netfilter/xt_conntrack.c (renamed from net/ipv4/netfilter/ipt_conntrack.c)110
-rw-r--r--net/netfilter/xt_dccp.c (renamed from net/ipv4/netfilter/ipt_dccp.c)105
-rw-r--r--net/netfilter/xt_helper.c (renamed from net/ipv4/netfilter/ipt_helper.c)56
-rw-r--r--net/netfilter/xt_length.c99
-rw-r--r--net/netfilter/xt_limit.c (renamed from net/ipv4/netfilter/ipt_limit.c)48
-rw-r--r--net/netfilter/xt_mac.c (renamed from net/ipv4/netfilter/ipt_mac.c)38
-rw-r--r--net/netfilter/xt_mark.c (renamed from net/ipv4/netfilter/ipt_mark.c)38
-rw-r--r--net/netfilter/xt_physdev.c (renamed from net/ipv6/netfilter/ip6t_physdev.c)82
-rw-r--r--net/netfilter/xt_pkttype.c (renamed from net/ipv4/netfilter/ipt_pkttype.c)46
-rw-r--r--net/netfilter/xt_realm.c (renamed from net/ipv4/netfilter/ipt_realm.c)25
-rw-r--r--net/netfilter/xt_sctp.c (renamed from net/ipv4/netfilter/ipt_sctp.c)109
-rw-r--r--net/netfilter/xt_state.c (renamed from net/ipv4/netfilter/ipt_state.c)50
-rw-r--r--net/netfilter/xt_string.c (renamed from net/ipv4/netfilter/ipt_string.c)40
-rw-r--r--net/netfilter/xt_tcpmss.c (renamed from net/ipv4/netfilter/ipt_tcpmss.c)69
-rw-r--r--net/netfilter/xt_tcpudp.c334
-rw-r--r--net/netlink/genetlink.c7
-rw-r--r--net/sched/Kconfig2
-rw-r--r--net/sched/act_ipt.c2
-rw-r--r--net/sctp/ipv6.c24
-rw-r--r--net/sctp/sm_statefuns.c4
-rw-r--r--net/tipc/Kconfig112
-rw-r--r--net/tipc/Makefile13
-rw-r--r--net/tipc/addr.c94
-rw-r--r--net/tipc/addr.h128
-rw-r--r--net/tipc/bcast.c806
-rw-r--r--net/tipc/bcast.h223
-rw-r--r--net/tipc/bearer.c692
-rw-r--r--net/tipc/bearer.h172
-rw-r--r--net/tipc/cluster.c576
-rw-r--r--net/tipc/cluster.h92
-rw-r--r--net/tipc/config.c718
-rw-r--r--net/tipc/config.h80
-rw-r--r--net/tipc/core.c285
-rw-r--r--net/tipc/core.h316
-rw-r--r--net/tipc/dbg.c395
-rw-r--r--net/tipc/dbg.h59
-rw-r--r--net/tipc/discover.c318
-rw-r--r--net/tipc/discover.h58
-rw-r--r--net/tipc/eth_media.c299
-rw-r--r--net/tipc/handler.c132
-rw-r--r--net/tipc/link.c3167
-rw-r--r--net/tipc/link.h296
-rw-r--r--net/tipc/msg.c334
-rw-r--r--net/tipc/msg.h818
-rw-r--r--net/tipc/name_distr.c309
-rw-r--r--net/tipc/name_distr.h48
-rw-r--r--net/tipc/name_table.c1079
-rw-r--r--net/tipc/name_table.h108
-rw-r--r--net/tipc/net.c311
-rw-r--r--net/tipc/net.h66
-rw-r--r--net/tipc/netlink.c112
-rw-r--r--net/tipc/node.c679
-rw-r--r--net/tipc/node.h144
-rw-r--r--net/tipc/node_subscr.c79
-rw-r--r--net/tipc/node_subscr.h63
-rw-r--r--net/tipc/port.c1708
-rw-r--r--net/tipc/port.h209
-rw-r--r--net/tipc/ref.c189
-rw-r--r--net/tipc/ref.h131
-rw-r--r--net/tipc/socket.c1726
-rw-r--r--net/tipc/subscr.c527
-rw-r--r--net/tipc/subscr.h80
-rw-r--r--net/tipc/user_reg.c265
-rw-r--r--net/tipc/user_reg.h48
-rw-r--r--net/tipc/zone.c169
-rw-r--r--net/tipc/zone.h71
-rw-r--r--security/selinux/avc.c5
-rw-r--r--security/selinux/hooks.c2
-rw-r--r--sound/oss/esssolo1.c2
-rw-r--r--sound/pci/es1968.c4
881 files changed, 44950 insertions, 10635 deletions
diff --git a/Documentation/SubmittingDrivers b/Documentation/SubmittingDrivers
index dd311cff1cc3..6bd30fdd0786 100644
--- a/Documentation/SubmittingDrivers
+++ b/Documentation/SubmittingDrivers
@@ -143,7 +143,7 @@ KernelNewbies:
143 http://kernelnewbies.org/ 143 http://kernelnewbies.org/
144 144
145Linux USB project: 145Linux USB project:
146 http://linux-usb.sourceforge.net/ 146 http://www.linux-usb.org/
147 147
148How to NOT write kernel driver by arjanv@redhat.com 148How to NOT write kernel driver by arjanv@redhat.com
149 http://people.redhat.com/arjanv/olspaper.pdf 149 http://people.redhat.com/arjanv/olspaper.pdf
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index 6198e5ebcf65..c2c85bcb3d43 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -478,10 +478,11 @@ Andrew Morton, "The perfect patch" (tpp).
478Jeff Garzik, "Linux kernel patch submission format." 478Jeff Garzik, "Linux kernel patch submission format."
479 <http://linux.yyz.us/patch-format.html> 479 <http://linux.yyz.us/patch-format.html>
480 480
481Greg Kroah, "How to piss off a kernel subsystem maintainer". 481Greg Kroah-Hartman "How to piss off a kernel subsystem maintainer".
482 <http://www.kroah.com/log/2005/03/31/> 482 <http://www.kroah.com/log/2005/03/31/>
483 <http://www.kroah.com/log/2005/07/08/> 483 <http://www.kroah.com/log/2005/07/08/>
484 <http://www.kroah.com/log/2005/10/19/> 484 <http://www.kroah.com/log/2005/10/19/>
485 <http://www.kroah.com/log/2006/01/11/>
485 486
486NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!. 487NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!.
487 <http://marc.theaimsgroup.com/?l=linux-kernel&m=112112749912944&w=2> 488 <http://marc.theaimsgroup.com/?l=linux-kernel&m=112112749912944&w=2>
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 9474501dd6cc..b4a1ea762698 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -123,6 +123,15 @@ Who: Christoph Hellwig <hch@lst.de>
123 123
124--------------------------- 124---------------------------
125 125
126What: CONFIG_FORCED_INLINING
127When: June 2006
128Why: Config option is there to see if gcc is good enough. (in january
129 2006). If it is, the behavior should just be the default. If it's not,
130 the option should just go away entirely.
131Who: Arjan van de Ven
132
133---------------------------
134
126What: START_ARRAY ioctl for md 135What: START_ARRAY ioctl for md
127When: July 2006 136When: July 2006
128Files: drivers/md/md.c 137Files: drivers/md/md.c
diff --git a/Documentation/filesystems/tmpfs.txt b/Documentation/filesystems/tmpfs.txt
index 0d783c504ead..dbe4d87d2615 100644
--- a/Documentation/filesystems/tmpfs.txt
+++ b/Documentation/filesystems/tmpfs.txt
@@ -78,6 +78,18 @@ use up all the memory on the machine; but enhances the scalability of
78that instance in a system with many cpus making intensive use of it. 78that instance in a system with many cpus making intensive use of it.
79 79
80 80
81tmpfs has a mount option to set the NUMA memory allocation policy for
82all files in that instance:
83mpol=interleave prefers to allocate memory from each node in turn
84mpol=default prefers to allocate memory from the local node
85mpol=bind prefers to allocate from mpol_nodelist
86mpol=preferred prefers to allocate from first node in mpol_nodelist
87
88The following mount option is used in conjunction with mpol=interleave,
89mpol=bind or mpol=preferred:
90mpol_nodelist: nodelist suitable for parsing with nodelist_parse.
91
92
81To specify the initial root directory you can use the following mount 93To specify the initial root directory you can use the following mount
82options: 94options:
83 95
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index fe11fccf7e41..1cbcf65b764b 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -471,7 +471,7 @@ running once the system is up.
471 arch/i386/kernel/cpu/cpufreq/elanfreq.c. 471 arch/i386/kernel/cpu/cpufreq/elanfreq.c.
472 472
473 elevator= [IOSCHED] 473 elevator= [IOSCHED]
474 Format: {"as" | "cfq" | "deadline" | "noop"} 474 Format: {"anticipatory" | "cfq" | "deadline" | "noop"}
475 See Documentation/block/as-iosched.txt and 475 See Documentation/block/as-iosched.txt and
476 Documentation/block/deadline-iosched.txt for details. 476 Documentation/block/deadline-iosched.txt for details.
477 477
@@ -712,9 +712,17 @@ running once the system is up.
712 load_ramdisk= [RAM] List of ramdisks to load from floppy 712 load_ramdisk= [RAM] List of ramdisks to load from floppy
713 See Documentation/ramdisk.txt. 713 See Documentation/ramdisk.txt.
714 714
715 lockd.udpport= [NFS] 715 lockd.nlm_grace_period=P [NFS] Assign grace period.
716 Format: <integer>
717
718 lockd.nlm_tcpport=N [NFS] Assign TCP port.
719 Format: <integer>
716 720
717 lockd.tcpport= [NFS] 721 lockd.nlm_timeout=T [NFS] Assign timeout value.
722 Format: <integer>
723
724 lockd.nlm_udpport=M [NFS] Assign UDP port.
725 Format: <integer>
718 726
719 logibm.irq= [HW,MOUSE] Logitech Bus Mouse Driver 727 logibm.irq= [HW,MOUSE] Logitech Bus Mouse Driver
720 Format: <irq> 728 Format: <irq>
diff --git a/Documentation/scsi/aacraid.txt b/Documentation/scsi/aacraid.txt
new file mode 100644
index 000000000000..820fd0793502
--- /dev/null
+++ b/Documentation/scsi/aacraid.txt
@@ -0,0 +1,108 @@
1AACRAID Driver for Linux (take two)
2
3Introduction
4-------------------------
5The aacraid driver adds support for Adaptec (http://www.adaptec.com)
6RAID controllers. This is a major rewrite from the original
7Adaptec supplied driver. It has signficantly cleaned up both the code
8and the running binary size (the module is less than half the size of
9the original).
10
11Supported Cards/Chipsets
12-------------------------
13 PCI ID (pci.ids) OEM Product
14 9005:0285:9005:028a Adaptec 2020ZCR (Skyhawk)
15 9005:0285:9005:028e Adaptec 2020SA (Skyhawk)
16 9005:0285:9005:028b Adaptec 2025ZCR (Terminator)
17 9005:0285:9005:028f Adaptec 2025SA (Terminator)
18 9005:0285:9005:0286 Adaptec 2120S (Crusader)
19 9005:0286:9005:028d Adaptec 2130S (Lancer)
20 9005:0285:9005:0285 Adaptec 2200S (Vulcan)
21 9005:0285:9005:0287 Adaptec 2200S (Vulcan-2m)
22 9005:0286:9005:028c Adaptec 2230S (Lancer)
23 9005:0286:9005:028c Adaptec 2230SLP (Lancer)
24 9005:0285:9005:0296 Adaptec 2240S (SabreExpress)
25 9005:0285:9005:0290 Adaptec 2410SA (Jaguar)
26 9005:0285:9005:0293 Adaptec 21610SA (Corsair-16)
27 9005:0285:103c:3227 Adaptec 2610SA (Bearcat)
28 9005:0285:9005:0292 Adaptec 2810SA (Corsair-8)
29 9005:0285:9005:0294 Adaptec Prowler
30 9005:0286:9005:029d Adaptec 2420SA (Intruder)
31 9005:0286:9005:029c Adaptec 2620SA (Intruder)
32 9005:0286:9005:029b Adaptec 2820SA (Intruder)
33 9005:0286:9005:02a7 Adaptec 2830SA (Skyray)
34 9005:0286:9005:02a8 Adaptec 2430SA (Skyray)
35 9005:0285:9005:0288 Adaptec 3230S (Harrier)
36 9005:0285:9005:0289 Adaptec 3240S (Tornado)
37 9005:0285:9005:0298 Adaptec 4000SAS (BlackBird)
38 9005:0285:9005:0297 Adaptec 4005SAS (AvonPark)
39 9005:0285:9005:0299 Adaptec 4800SAS (Marauder-X)
40 9005:0285:9005:029a Adaptec 4805SAS (Marauder-E)
41 9005:0286:9005:02a2 Adaptec 4810SAS (Hurricane)
42 1011:0046:9005:0364 Adaptec 5400S (Mustang)
43 1011:0046:9005:0365 Adaptec 5400S (Mustang)
44 9005:0283:9005:0283 Adaptec Catapult (3210S with arc firmware)
45 9005:0284:9005:0284 Adaptec Tomcat (3410S with arc firmware)
46 9005:0287:9005:0800 Adaptec Themisto (Jupiter)
47 9005:0200:9005:0200 Adaptec Themisto (Jupiter)
48 9005:0286:9005:0800 Adaptec Callisto (Jupiter)
49 1011:0046:9005:1364 Dell PERC 2/QC (Quad Channel, Mustang)
50 1028:0001:1028:0001 Dell PERC 2/Si (Iguana)
51 1028:0003:1028:0003 Dell PERC 3/Si (SlimFast)
52 1028:0002:1028:0002 Dell PERC 3/Di (Opal)
53 1028:0004:1028:0004 Dell PERC 3/DiF (Iguana)
54 1028:0002:1028:00d1 Dell PERC 3/DiV (Viper)
55 1028:0002:1028:00d9 Dell PERC 3/DiL (Lexus)
56 1028:000a:1028:0106 Dell PERC 3/DiJ (Jaguar)
57 1028:000a:1028:011b Dell PERC 3/DiD (Dagger)
58 1028:000a:1028:0121 Dell PERC 3/DiB (Boxster)
59 9005:0285:1028:0287 Dell PERC 320/DC (Vulcan)
60 9005:0285:1028:0291 Dell CERC 2 (DellCorsair)
61 1011:0046:103c:10c2 HP NetRAID-4M (Mustang)
62 9005:0285:17aa:0286 Legend S220 (Crusader)
63 9005:0285:17aa:0287 Legend S230 (Vulcan)
64 9005:0285:9005:0290 IBM ServeRAID 7t (Jaguar)
65 9005:0285:1014:02F2 IBM ServeRAID 8i (AvonPark)
66 9005:0285:1014:0312 IBM ServeRAID 8i (AvonParkLite)
67 9005:0286:1014:9580 IBM ServeRAID 8k/8k-l8 (Aurora)
68 9005:0286:1014:9540 IBM ServeRAID 8k/8k-l4 (AuroraLite)
69 9005:0286:9005:029f ICP ICP9014R0 (Lancer)
70 9005:0286:9005:029e ICP ICP9024R0 (Lancer)
71 9005:0286:9005:02a0 ICP ICP9047MA (Lancer)
72 9005:0286:9005:02a1 ICP ICP9087MA (Lancer)
73 9005:0286:9005:02a4 ICP ICP9085LI (Marauder-X)
74 9005:0286:9005:02a5 ICP ICP5085BR (Marauder-E)
75 9005:0286:9005:02a3 ICP ICP5085AU (Hurricane)
76 9005:0286:9005:02a6 ICP ICP9067MA (Intruder-6)
77 9005:0286:9005:02a9 ICP ICP5087AU (Skyray)
78 9005:0286:9005:02aa ICP ICP5047AU (Skyray)
79
80People
81-------------------------
82Alan Cox <alan@redhat.com>
83Christoph Hellwig <hch@infradead.org> (updates for new-style PCI probing and SCSI host registration,
84 small cleanups/fixes)
85Matt Domsch <matt_domsch@dell.com> (revision ioctl, adapter messages)
86Deanna Bonds (non-DASD support, PAE fibs and 64 bit, added new adaptec controllers
87 added new ioctls, changed scsi interface to use new error handler,
88 increased the number of fibs and outstanding commands to a container)
89
90 (fixed 64bit and 64G memory model, changed confusing naming convention
91 where fibs that go to the hardware are consistently called hw_fibs and
92 not just fibs like the name of the driver tracking structure)
93Mark Salyzyn <Mark_Salyzyn@adaptec.com> Fixed panic issues and added some new product ids for upcoming hbas. Performance tuning, card failover and bug mitigations.
94
95Original Driver
96-------------------------
97Adaptec Unix OEM Product Group
98
99Mailing List
100-------------------------
101linux-scsi@vger.kernel.org (Interested parties troll here)
102Also note this is very different to Brian's original driver
103so don't expect him to support it.
104Adaptec does support this driver. Contact Adaptec tech support or
105aacraid@adaptec.com
106
107Original by Brian Boerner February 2001
108Rewritten by Alan Cox, November 2001
diff --git a/Documentation/spi/butterfly b/Documentation/spi/butterfly
new file mode 100644
index 000000000000..a2e8c8d90e35
--- /dev/null
+++ b/Documentation/spi/butterfly
@@ -0,0 +1,57 @@
1spi_butterfly - parport-to-butterfly adapter driver
2===================================================
3
4This is a hardware and software project that includes building and using
5a parallel port adapter cable, together with an "AVR Butterfly" to run
6firmware for user interfacing and/or sensors. A Butterfly is a $US20
7battery powered card with an AVR microcontroller and lots of goodies:
8sensors, LCD, flash, toggle stick, and more. You can use AVR-GCC to
9develop firmware for this, and flash it using this adapter cable.
10
11You can make this adapter from an old printer cable and solder things
12directly to the Butterfly. Or (if you have the parts and skills) you
13can come up with something fancier, providing ciruit protection to the
14Butterfly and the printer port, or with a better power supply than two
15signal pins from the printer port.
16
17
18The first cable connections will hook Linux up to one SPI bus, with the
19AVR and a DataFlash chip; and to the AVR reset line. This is all you
20need to reflash the firmware, and the pins are the standard Atmel "ISP"
21connector pins (used also on non-Butterfly AVR boards).
22
23 Signal Butterfly Parport (DB-25)
24 ------ --------- ---------------
25 SCK = J403.PB1/SCK = pin 2/D0
26 RESET = J403.nRST = pin 3/D1
27 VCC = J403.VCC_EXT = pin 8/D6
28 MOSI = J403.PB2/MOSI = pin 9/D7
29 MISO = J403.PB3/MISO = pin 11/S7,nBUSY
30 GND = J403.GND = pin 23/GND
31
32Then to let Linux master that bus to talk to the DataFlash chip, you must
33(a) flash new firmware that disables SPI (set PRR.2, and disable pullups
34by clearing PORTB.[0-3]); (b) configure the mtd_dataflash driver; and
35(c) cable in the chipselect.
36
37 Signal Butterfly Parport (DB-25)
38 ------ --------- ---------------
39 VCC = J400.VCC_EXT = pin 7/D5
40 SELECT = J400.PB0/nSS = pin 17/C3,nSELECT
41 GND = J400.GND = pin 24/GND
42
43The "USI" controller, using J405, can be used for a second SPI bus. That
44would let you talk to the AVR over SPI, running firmware that makes it act
45as an SPI slave, while letting either Linux or the AVR use the DataFlash.
46There are plenty of spare parport pins to wire this one up, such as:
47
48 Signal Butterfly Parport (DB-25)
49 ------ --------- ---------------
50 SCK = J403.PE4/USCK = pin 5/D3
51 MOSI = J403.PE5/DI = pin 6/D4
52 MISO = J403.PE6/DO = pin 12/S5,nPAPEROUT
53 GND = J403.GND = pin 22/GND
54
55 IRQ = J402.PF4 = pin 10/S6,ACK
56 GND = J402.GND(P2) = pin 25/GND
57
diff --git a/Documentation/spi/spi-summary b/Documentation/spi/spi-summary
new file mode 100644
index 000000000000..a5ffba33a351
--- /dev/null
+++ b/Documentation/spi/spi-summary
@@ -0,0 +1,457 @@
1Overview of Linux kernel SPI support
2====================================
3
402-Dec-2005
5
6What is SPI?
7------------
8The "Serial Peripheral Interface" (SPI) is a synchronous four wire serial
9link used to connect microcontrollers to sensors, memory, and peripherals.
10
11The three signal wires hold a clock (SCLK, often on the order of 10 MHz),
12and parallel data lines with "Master Out, Slave In" (MOSI) or "Master In,
13Slave Out" (MISO) signals. (Other names are also used.) There are four
14clocking modes through which data is exchanged; mode-0 and mode-3 are most
15commonly used. Each clock cycle shifts data out and data in; the clock
16doesn't cycle except when there is data to shift.
17
18SPI masters may use a "chip select" line to activate a given SPI slave
19device, so those three signal wires may be connected to several chips
20in parallel. All SPI slaves support chipselects. Some devices have
21other signals, often including an interrupt to the master.
22
23Unlike serial busses like USB or SMBUS, even low level protocols for
24SPI slave functions are usually not interoperable between vendors
25(except for cases like SPI memory chips).
26
27 - SPI may be used for request/response style device protocols, as with
28 touchscreen sensors and memory chips.
29
30 - It may also be used to stream data in either direction (half duplex),
31 or both of them at the same time (full duplex).
32
33 - Some devices may use eight bit words. Others may different word
34 lengths, such as streams of 12-bit or 20-bit digital samples.
35
36In the same way, SPI slaves will only rarely support any kind of automatic
37discovery/enumeration protocol. The tree of slave devices accessible from
38a given SPI master will normally be set up manually, with configuration
39tables.
40
41SPI is only one of the names used by such four-wire protocols, and
42most controllers have no problem handling "MicroWire" (think of it as
43half-duplex SPI, for request/response protocols), SSP ("Synchronous
44Serial Protocol"), PSP ("Programmable Serial Protocol"), and other
45related protocols.
46
47Microcontrollers often support both master and slave sides of the SPI
48protocol. This document (and Linux) currently only supports the master
49side of SPI interactions.
50
51
52Who uses it? On what kinds of systems?
53---------------------------------------
54Linux developers using SPI are probably writing device drivers for embedded
55systems boards. SPI is used to control external chips, and it is also a
56protocol supported by every MMC or SD memory card. (The older "DataFlash"
57cards, predating MMC cards but using the same connectors and card shape,
58support only SPI.) Some PC hardware uses SPI flash for BIOS code.
59
60SPI slave chips range from digital/analog converters used for analog
61sensors and codecs, to memory, to peripherals like USB controllers
62or Ethernet adapters; and more.
63
64Most systems using SPI will integrate a few devices on a mainboard.
65Some provide SPI links on expansion connectors; in cases where no
66dedicated SPI controller exists, GPIO pins can be used to create a
67low speed "bitbanging" adapter. Very few systems will "hotplug" an SPI
68controller; the reasons to use SPI focus on low cost and simple operation,
69and if dynamic reconfiguration is important, USB will often be a more
70appropriate low-pincount peripheral bus.
71
72Many microcontrollers that can run Linux integrate one or more I/O
73interfaces with SPI modes. Given SPI support, they could use MMC or SD
74cards without needing a special purpose MMC/SD/SDIO controller.
75
76
77How do these driver programming interfaces work?
78------------------------------------------------
79The <linux/spi/spi.h> header file includes kerneldoc, as does the
80main source code, and you should certainly read that. This is just
81an overview, so you get the big picture before the details.
82
83SPI requests always go into I/O queues. Requests for a given SPI device
84are always executed in FIFO order, and complete asynchronously through
85completion callbacks. There are also some simple synchronous wrappers
86for those calls, including ones for common transaction types like writing
87a command and then reading its response.
88
89There are two types of SPI driver, here called:
90
91 Controller drivers ... these are often built in to System-On-Chip
92 processors, and often support both Master and Slave roles.
93 These drivers touch hardware registers and may use DMA.
94 Or they can be PIO bitbangers, needing just GPIO pins.
95
96 Protocol drivers ... these pass messages through the controller
97 driver to communicate with a Slave or Master device on the
98 other side of an SPI link.
99
100So for example one protocol driver might talk to the MTD layer to export
101data to filesystems stored on SPI flash like DataFlash; and others might
102control audio interfaces, present touchscreen sensors as input interfaces,
103or monitor temperature and voltage levels during industrial processing.
104And those might all be sharing the same controller driver.
105
106A "struct spi_device" encapsulates the master-side interface between
107those two types of driver. At this writing, Linux has no slave side
108programming interface.
109
110There is a minimal core of SPI programming interfaces, focussing on
111using driver model to connect controller and protocol drivers using
112device tables provided by board specific initialization code. SPI
113shows up in sysfs in several locations:
114
115 /sys/devices/.../CTLR/spiB.C ... spi_device for on bus "B",
116 chipselect C, accessed through CTLR.
117
118 /sys/devices/.../CTLR/spiB.C/modalias ... identifies the driver
119 that should be used with this device (for hotplug/coldplug)
120
121 /sys/bus/spi/devices/spiB.C ... symlink to the physical
122 spiB-C device
123
124 /sys/bus/spi/drivers/D ... driver for one or more spi*.* devices
125
126 /sys/class/spi_master/spiB ... class device for the controller
127 managing bus "B". All the spiB.* devices share the same
128 physical SPI bus segment, with SCLK, MOSI, and MISO.
129
130
131How does board-specific init code declare SPI devices?
132------------------------------------------------------
133Linux needs several kinds of information to properly configure SPI devices.
134That information is normally provided by board-specific code, even for
135chips that do support some of automated discovery/enumeration.
136
137DECLARE CONTROLLERS
138
139The first kind of information is a list of what SPI controllers exist.
140For System-on-Chip (SOC) based boards, these will usually be platform
141devices, and the controller may need some platform_data in order to
142operate properly. The "struct platform_device" will include resources
143like the physical address of the controller's first register and its IRQ.
144
145Platforms will often abstract the "register SPI controller" operation,
146maybe coupling it with code to initialize pin configurations, so that
147the arch/.../mach-*/board-*.c files for several boards can all share the
148same basic controller setup code. This is because most SOCs have several
149SPI-capable controllers, and only the ones actually usable on a given
150board should normally be set up and registered.
151
152So for example arch/.../mach-*/board-*.c files might have code like:
153
154 #include <asm/arch/spi.h> /* for mysoc_spi_data */
155
156 /* if your mach-* infrastructure doesn't support kernels that can
157 * run on multiple boards, pdata wouldn't benefit from "__init".
158 */
159 static struct mysoc_spi_data __init pdata = { ... };
160
161 static __init board_init(void)
162 {
163 ...
164 /* this board only uses SPI controller #2 */
165 mysoc_register_spi(2, &pdata);
166 ...
167 }
168
169And SOC-specific utility code might look something like:
170
171 #include <asm/arch/spi.h>
172
173 static struct platform_device spi2 = { ... };
174
175 void mysoc_register_spi(unsigned n, struct mysoc_spi_data *pdata)
176 {
177 struct mysoc_spi_data *pdata2;
178
179 pdata2 = kmalloc(sizeof *pdata2, GFP_KERNEL);
180 *pdata2 = pdata;
181 ...
182 if (n == 2) {
183 spi2->dev.platform_data = pdata2;
184 register_platform_device(&spi2);
185
186 /* also: set up pin modes so the spi2 signals are
187 * visible on the relevant pins ... bootloaders on
188 * production boards may already have done this, but
189 * developer boards will often need Linux to do it.
190 */
191 }
192 ...
193 }
194
195Notice how the platform_data for boards may be different, even if the
196same SOC controller is used. For example, on one board SPI might use
197an external clock, where another derives the SPI clock from current
198settings of some master clock.
199
200
201DECLARE SLAVE DEVICES
202
203The second kind of information is a list of what SPI slave devices exist
204on the target board, often with some board-specific data needed for the
205driver to work correctly.
206
207Normally your arch/.../mach-*/board-*.c files would provide a small table
208listing the SPI devices on each board. (This would typically be only a
209small handful.) That might look like:
210
211 static struct ads7846_platform_data ads_info = {
212 .vref_delay_usecs = 100,
213 .x_plate_ohms = 580,
214 .y_plate_ohms = 410,
215 };
216
217 static struct spi_board_info spi_board_info[] __initdata = {
218 {
219 .modalias = "ads7846",
220 .platform_data = &ads_info,
221 .mode = SPI_MODE_0,
222 .irq = GPIO_IRQ(31),
223 .max_speed_hz = 120000 /* max sample rate at 3V */ * 16,
224 .bus_num = 1,
225 .chip_select = 0,
226 },
227 };
228
229Again, notice how board-specific information is provided; each chip may need
230several types. This example shows generic constraints like the fastest SPI
231clock to allow (a function of board voltage in this case) or how an IRQ pin
232is wired, plus chip-specific constraints like an important delay that's
233changed by the capacitance at one pin.
234
235(There's also "controller_data", information that may be useful to the
236controller driver. An example would be peripheral-specific DMA tuning
237data or chipselect callbacks. This is stored in spi_device later.)
238
239The board_info should provide enough information to let the system work
240without the chip's driver being loaded. The most troublesome aspect of
241that is likely the SPI_CS_HIGH bit in the spi_device.mode field, since
242sharing a bus with a device that interprets chipselect "backwards" is
243not possible.
244
245Then your board initialization code would register that table with the SPI
246infrastructure, so that it's available later when the SPI master controller
247driver is registered:
248
249 spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
250
251Like with other static board-specific setup, you won't unregister those.
252
253The widely used "card" style computers bundle memory, cpu, and little else
254onto a card that's maybe just thirty square centimeters. On such systems,
255your arch/.../mach-.../board-*.c file would primarily provide information
256about the devices on the mainboard into which such a card is plugged. That
257certainly includes SPI devices hooked up through the card connectors!
258
259
260NON-STATIC CONFIGURATIONS
261
262Developer boards often play by different rules than product boards, and one
263example is the potential need to hotplug SPI devices and/or controllers.
264
265For those cases you might need to use use spi_busnum_to_master() to look
266up the spi bus master, and will likely need spi_new_device() to provide the
267board info based on the board that was hotplugged. Of course, you'd later
268call at least spi_unregister_device() when that board is removed.
269
270When Linux includes support for MMC/SD/SDIO/DataFlash cards through SPI, those
271configurations will also be dynamic. Fortunately, those devices all support
272basic device identification probes, so that support should hotplug normally.
273
274
275How do I write an "SPI Protocol Driver"?
276----------------------------------------
277All SPI drivers are currently kernel drivers. A userspace driver API
278would just be another kernel driver, probably offering some lowlevel
279access through aio_read(), aio_write(), and ioctl() calls and using the
280standard userspace sysfs mechanisms to bind to a given SPI device.
281
282SPI protocol drivers somewhat resemble platform device drivers:
283
284 static struct spi_driver CHIP_driver = {
285 .driver = {
286 .name = "CHIP",
287 .bus = &spi_bus_type,
288 .owner = THIS_MODULE,
289 },
290
291 .probe = CHIP_probe,
292 .remove = __devexit_p(CHIP_remove),
293 .suspend = CHIP_suspend,
294 .resume = CHIP_resume,
295 };
296
297The driver core will autmatically attempt to bind this driver to any SPI
298device whose board_info gave a modalias of "CHIP". Your probe() code
299might look like this unless you're creating a class_device:
300
301 static int __devinit CHIP_probe(struct spi_device *spi)
302 {
303 struct CHIP *chip;
304 struct CHIP_platform_data *pdata;
305
306 /* assuming the driver requires board-specific data: */
307 pdata = &spi->dev.platform_data;
308 if (!pdata)
309 return -ENODEV;
310
311 /* get memory for driver's per-chip state */
312 chip = kzalloc(sizeof *chip, GFP_KERNEL);
313 if (!chip)
314 return -ENOMEM;
315 dev_set_drvdata(&spi->dev, chip);
316
317 ... etc
318 return 0;
319 }
320
321As soon as it enters probe(), the driver may issue I/O requests to
322the SPI device using "struct spi_message". When remove() returns,
323the driver guarantees that it won't submit any more such messages.
324
325 - An spi_message is a sequence of of protocol operations, executed
326 as one atomic sequence. SPI driver controls include:
327
328 + when bidirectional reads and writes start ... by how its
329 sequence of spi_transfer requests is arranged;
330
331 + optionally defining short delays after transfers ... using
332 the spi_transfer.delay_usecs setting;
333
334 + whether the chipselect becomes inactive after a transfer and
335 any delay ... by using the spi_transfer.cs_change flag;
336
337 + hinting whether the next message is likely to go to this same
338 device ... using the spi_transfer.cs_change flag on the last
339 transfer in that atomic group, and potentially saving costs
340 for chip deselect and select operations.
341
342 - Follow standard kernel rules, and provide DMA-safe buffers in
343 your messages. That way controller drivers using DMA aren't forced
344 to make extra copies unless the hardware requires it (e.g. working
345 around hardware errata that force the use of bounce buffering).
346
347 If standard dma_map_single() handling of these buffers is inappropriate,
348 you can use spi_message.is_dma_mapped to tell the controller driver
349 that you've already provided the relevant DMA addresses.
350
351 - The basic I/O primitive is spi_async(). Async requests may be
352 issued in any context (irq handler, task, etc) and completion
353 is reported using a callback provided with the message.
354 After any detected error, the chip is deselected and processing
355 of that spi_message is aborted.
356
357 - There are also synchronous wrappers like spi_sync(), and wrappers
358 like spi_read(), spi_write(), and spi_write_then_read(). These
359 may be issued only in contexts that may sleep, and they're all
360 clean (and small, and "optional") layers over spi_async().
361
362 - The spi_write_then_read() call, and convenience wrappers around
363 it, should only be used with small amounts of data where the
364 cost of an extra copy may be ignored. It's designed to support
365 common RPC-style requests, such as writing an eight bit command
366 and reading a sixteen bit response -- spi_w8r16() being one its
367 wrappers, doing exactly that.
368
369Some drivers may need to modify spi_device characteristics like the
370transfer mode, wordsize, or clock rate. This is done with spi_setup(),
371which would normally be called from probe() before the first I/O is
372done to the device.
373
374While "spi_device" would be the bottom boundary of the driver, the
375upper boundaries might include sysfs (especially for sensor readings),
376the input layer, ALSA, networking, MTD, the character device framework,
377or other Linux subsystems.
378
379Note that there are two types of memory your driver must manage as part
380of interacting with SPI devices.
381
382 - I/O buffers use the usual Linux rules, and must be DMA-safe.
383 You'd normally allocate them from the heap or free page pool.
384 Don't use the stack, or anything that's declared "static".
385
386 - The spi_message and spi_transfer metadata used to glue those
387 I/O buffers into a group of protocol transactions. These can
388 be allocated anywhere it's convenient, including as part of
389 other allocate-once driver data structures. Zero-init these.
390
391If you like, spi_message_alloc() and spi_message_free() convenience
392routines are available to allocate and zero-initialize an spi_message
393with several transfers.
394
395
396How do I write an "SPI Master Controller Driver"?
397-------------------------------------------------
398An SPI controller will probably be registered on the platform_bus; write
399a driver to bind to the device, whichever bus is involved.
400
401The main task of this type of driver is to provide an "spi_master".
402Use spi_alloc_master() to allocate the master, and class_get_devdata()
403to get the driver-private data allocated for that device.
404
405 struct spi_master *master;
406 struct CONTROLLER *c;
407
408 master = spi_alloc_master(dev, sizeof *c);
409 if (!master)
410 return -ENODEV;
411
412 c = class_get_devdata(&master->cdev);
413
414The driver will initialize the fields of that spi_master, including the
415bus number (maybe the same as the platform device ID) and three methods
416used to interact with the SPI core and SPI protocol drivers. It will
417also initialize its own internal state.
418
419 master->setup(struct spi_device *spi)
420 This sets up the device clock rate, SPI mode, and word sizes.
421 Drivers may change the defaults provided by board_info, and then
422 call spi_setup(spi) to invoke this routine. It may sleep.
423
424 master->transfer(struct spi_device *spi, struct spi_message *message)
425 This must not sleep. Its responsibility is arrange that the
426 transfer happens and its complete() callback is issued; the two
427 will normally happen later, after other transfers complete.
428
429 master->cleanup(struct spi_device *spi)
430 Your controller driver may use spi_device.controller_state to hold
431 state it dynamically associates with that device. If you do that,
432 be sure to provide the cleanup() method to free that state.
433
434The bulk of the driver will be managing the I/O queue fed by transfer().
435
436That queue could be purely conceptual. For example, a driver used only
437for low-frequency sensor acess might be fine using synchronous PIO.
438
439But the queue will probably be very real, using message->queue, PIO,
440often DMA (especially if the root filesystem is in SPI flash), and
441execution contexts like IRQ handlers, tasklets, or workqueues (such
442as keventd). Your driver can be as fancy, or as simple, as you need.
443
444
445THANKS TO
446---------
447Contributors to Linux-SPI discussions include (in alphabetical order,
448by last name):
449
450David Brownell
451Russell King
452Dmitry Pervushin
453Stephen Street
454Mark Underwood
455Andrew Victor
456Vitaly Wool
457
diff --git a/MAINTAINERS b/MAINTAINERS
index 0db72a36e245..513f3b6c35b9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1300,6 +1300,12 @@ M: ttb@tentacle.dhs.org and rml@novell.com
1300L: linux-kernel@vger.kernel.org 1300L: linux-kernel@vger.kernel.org
1301S: Maintained 1301S: Maintained
1302 1302
1303INTEL FRAMEBUFFER DRIVER (excluding 810 and 815)
1304P: Sylvain Meyer
1305M: sylvain.meyer@worldonline.fr
1306L: linux-fbdev-devel@lists.sourceforge.net
1307S: Maintained
1308
1303INTEL 810/815 FRAMEBUFFER DRIVER 1309INTEL 810/815 FRAMEBUFFER DRIVER
1304P: Antonino Daplas 1310P: Antonino Daplas
1305M: adaplas@pol.net 1311M: adaplas@pol.net
@@ -1889,11 +1895,11 @@ W: http://linux-ntfs.sf.net/
1889T: git kernel.org:/pub/scm/linux/kernel/git/aia21/ntfs-2.6.git 1895T: git kernel.org:/pub/scm/linux/kernel/git/aia21/ntfs-2.6.git
1890S: Maintained 1896S: Maintained
1891 1897
1892NVIDIA (RIVA) FRAMEBUFFER DRIVER 1898NVIDIA (rivafb and nvidiafb) FRAMEBUFFER DRIVER
1893P: Ani Joshi 1899P: Antonino Daplas
1894M: ajoshi@shell.unixbox.com 1900M: adaplas@pol.net
1895L: linux-nvidia@lists.surfsouth.com 1901L: linux-fbdev-devel@lists.sourceforge.net
1896S: Maintained 1902S: Maintained
1897 1903
1898ORACLE CLUSTER FILESYSTEM 2 (OCFS2) 1904ORACLE CLUSTER FILESYSTEM 2 (OCFS2)
1899P: Mark Fasheh 1905P: Mark Fasheh
@@ -2188,6 +2194,12 @@ L: rtl@rtlinux.org
2188W: www.rtlinux.org 2194W: www.rtlinux.org
2189S: Maintained 2195S: Maintained
2190 2196
2197S3 SAVAGE FRAMEBUFFER DRIVER
2198P: Antonino Daplas
2199M: adaplas@pol.net
2200L: linux-fbdev-devel@lists.sourceforge.net
2201S: Maintained
2202
2191S390 2203S390
2192P: Martin Schwidefsky 2204P: Martin Schwidefsky
2193M: schwidefsky@de.ibm.com 2205M: schwidefsky@de.ibm.com
@@ -2519,6 +2531,19 @@ P: Romain Lievin
2519M: roms@lpg.ticalc.org 2531M: roms@lpg.ticalc.org
2520S: Maintained 2532S: Maintained
2521 2533
2534TIPC NETWORK LAYER
2535P: Per Liden
2536M: per.liden@nospam.ericsson.com
2537P: Jon Maloy
2538M: jon.maloy@nospam.ericsson.com
2539P: Allan Stephens
2540M: allan.stephens@nospam.windriver.com
2541L: tipc-discussion@lists.sourceforge.net
2542W: http://tipc.sourceforge.net/
2543W: http://tipc.cslab.ericsson.net/
2544T: git tipc.cslab.ericsson.net:/pub/git/tipc.git
2545S: Maintained
2546
2522TLAN NETWORK DRIVER 2547TLAN NETWORK DRIVER
2523P: Samuel Chessman 2548P: Samuel Chessman
2524M: chessman@tux.org 2549M: chessman@tux.org
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 50b9afa8ae6d..5959e36c3b4c 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -180,6 +180,7 @@ config ARCH_OMAP
180config ARCH_VERSATILE 180config ARCH_VERSATILE
181 bool "Versatile" 181 bool "Versatile"
182 select ARM_AMBA 182 select ARM_AMBA
183 select ARM_VIC
183 select ICST307 184 select ICST307
184 help 185 help
185 This enables support for ARM Ltd Versatile board. 186 This enables support for ARM Ltd Versatile board.
@@ -400,6 +401,38 @@ config NO_IDLE_HZ
400 Currently at least OMAP, PXA2xx and SA11x0 platforms are known 401 Currently at least OMAP, PXA2xx and SA11x0 platforms are known
401 to have accurate timekeeping with dynamic tick. 402 to have accurate timekeeping with dynamic tick.
402 403
404config AEABI
405 bool "Use the ARM EABI to compile the kernel"
406 help
407 This option allows for the kernel to be compiled using the latest
408 ARM ABI (aka EABI). This is only useful if you are using a user
409 space environment that is also compiled with EABI.
410
411 Since there are major incompatibilities between the legacy ABI and
412 EABI, especially with regard to structure member alignment, this
413 option also changes the kernel syscall calling convention to
414 disambiguate both ABIs and allow for backward compatibility support
415 (selected with CONFIG_OABI_COMPAT).
416
417 To use this you need GCC version 4.0.0 or later.
418
419config OABI_COMPAT
420 bool "Allow old ABI binaries to run with this kernel"
421 depends on AEABI
422 default y
423 help
424 This option preserves the old syscall interface along with the
425 new (ARM EABI) one. It also provides a compatibility layer to
426 intercept syscalls that have structure arguments which layout
427 in memory differs between the legacy ABI and the new ARM EABI
428 (only for non "thumb" binaries). This option adds a tiny
429 overhead to all syscalls and produces a slightly larger kernel.
430 If you know you'll be using only pure EABI user space then you
431 can say N here. If this option is not selected and you attempt
432 to execute a legacy ABI binary then the result will be
433 UNPREDICTABLE (in fact it can be predicted that it won't work
434 at all). If in doubt say Y.
435
403config ARCH_DISCONTIGMEM_ENABLE 436config ARCH_DISCONTIGMEM_ENABLE
404 bool 437 bool
405 default (ARCH_LH7A40X && !LH7A40X_CONTIGMEM) 438 default (ARCH_LH7A40X && !LH7A40X_CONTIGMEM)
@@ -586,6 +619,7 @@ comment "At least one emulation must be selected"
586 619
587config FPE_NWFPE 620config FPE_NWFPE
588 bool "NWFPE math emulation" 621 bool "NWFPE math emulation"
622 depends on !AEABI || OABI_COMPAT
589 ---help--- 623 ---help---
590 Say Y to include the NWFPE floating point emulator in the kernel. 624 Say Y to include the NWFPE floating point emulator in the kernel.
591 This is necessary to run most binaries. Linux does not currently 625 This is necessary to run most binaries. Linux does not currently
@@ -609,7 +643,7 @@ config FPE_NWFPE_XP
609 643
610config FPE_FASTFPE 644config FPE_FASTFPE
611 bool "FastFPE math emulation (EXPERIMENTAL)" 645 bool "FastFPE math emulation (EXPERIMENTAL)"
612 depends on !CPU_32v3 && EXPERIMENTAL 646 depends on (!AEABI || OABI_COMPAT) && !CPU_32v3 && EXPERIMENTAL
613 ---help--- 647 ---help---
614 Say Y here to include the FAST floating point emulator in the kernel. 648 Say Y here to include the FAST floating point emulator in the kernel.
615 This is an experimental much faster emulator which now also has full 649 This is an experimental much faster emulator which now also has full
@@ -641,6 +675,7 @@ source "fs/Kconfig.binfmt"
641 675
642config ARTHUR 676config ARTHUR
643 tristate "RISC OS personality" 677 tristate "RISC OS personality"
678 depends on !AEABI
644 help 679 help
645 Say Y here to include the kernel code necessary if you want to run 680 Say Y here to include the kernel code necessary if you want to run
646 Acorn RISC OS/Arthur binaries under Linux. This code is still very 681 Acorn RISC OS/Arthur binaries under Linux. This code is still very
@@ -729,6 +764,8 @@ source "drivers/char/Kconfig"
729 764
730source "drivers/i2c/Kconfig" 765source "drivers/i2c/Kconfig"
731 766
767source "drivers/spi/Kconfig"
768
732source "drivers/hwmon/Kconfig" 769source "drivers/hwmon/Kconfig"
733 770
734#source "drivers/l3/Kconfig" 771#source "drivers/l3/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 1fa2a1011584..fbfc14a56b96 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -56,8 +56,13 @@ tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100
56tune-$(CONFIG_CPU_XSCALE) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale 56tune-$(CONFIG_CPU_XSCALE) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale
57tune-$(CONFIG_CPU_V6) :=$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm) 57tune-$(CONFIG_CPU_V6) :=$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm)
58 58
59# Need -Uarm for gcc < 3.x 59ifeq ($(CONFIG_AEABI),y)
60CFLAGS_ABI :=-mabi=aapcs -mno-thumb-interwork
61else
60CFLAGS_ABI :=$(call cc-option,-mapcs-32,-mabi=apcs-gnu) $(call cc-option,-mno-thumb-interwork,) 62CFLAGS_ABI :=$(call cc-option,-mapcs-32,-mabi=apcs-gnu) $(call cc-option,-mno-thumb-interwork,)
63endif
64
65# Need -Uarm for gcc < 3.x
61CFLAGS +=$(CFLAGS_ABI) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm 66CFLAGS +=$(CFLAGS_ABI) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm
62AFLAGS +=$(CFLAGS_ABI) $(arch-y) $(tune-y) -msoft-float 67AFLAGS +=$(CFLAGS_ABI) $(arch-y) $(tune-y) -msoft-float
63 68
diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
index d7509c7a3c5e..5e34ca6d38b6 100644
--- a/arch/arm/common/Kconfig
+++ b/arch/arm/common/Kconfig
@@ -1,7 +1,10 @@
1config ICST525 1config ARM_GIC
2 bool 2 bool
3 3
4config ARM_GIC 4config ARM_VIC
5 bool
6
7config ICST525
5 bool 8 bool
6 9
7config ICST307 10config ICST307
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
index ec8d17c96906..c81a2ff6b5be 100644
--- a/arch/arm/common/Makefile
+++ b/arch/arm/common/Makefile
@@ -4,6 +4,7 @@
4 4
5obj-y += rtctime.o 5obj-y += rtctime.o
6obj-$(CONFIG_ARM_GIC) += gic.o 6obj-$(CONFIG_ARM_GIC) += gic.o
7obj-$(CONFIG_ARM_VIC) += vic.o
7obj-$(CONFIG_ICST525) += icst525.o 8obj-$(CONFIG_ICST525) += icst525.o
8obj-$(CONFIG_ICST307) += icst307.o 9obj-$(CONFIG_ICST307) += icst307.o
9obj-$(CONFIG_SA1111) += sa1111.o 10obj-$(CONFIG_SA1111) += sa1111.o
diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c
index 1b7eaab02b9e..159ad7ed7a40 100644
--- a/arch/arm/common/locomo.c
+++ b/arch/arm/common/locomo.c
@@ -1103,14 +1103,14 @@ static int locomo_bus_remove(struct device *dev)
1103struct bus_type locomo_bus_type = { 1103struct bus_type locomo_bus_type = {
1104 .name = "locomo-bus", 1104 .name = "locomo-bus",
1105 .match = locomo_match, 1105 .match = locomo_match,
1106 .probe = locomo_bus_probe,
1107 .remove = locomo_bus_remove,
1106 .suspend = locomo_bus_suspend, 1108 .suspend = locomo_bus_suspend,
1107 .resume = locomo_bus_resume, 1109 .resume = locomo_bus_resume,
1108}; 1110};
1109 1111
1110int locomo_driver_register(struct locomo_driver *driver) 1112int locomo_driver_register(struct locomo_driver *driver)
1111{ 1113{
1112 driver->drv.probe = locomo_bus_probe;
1113 driver->drv.remove = locomo_bus_remove;
1114 driver->drv.bus = &locomo_bus_type; 1114 driver->drv.bus = &locomo_bus_type;
1115 return driver_register(&driver->drv); 1115 return driver_register(&driver->drv);
1116} 1116}
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index d0d6e6d2d649..1475089f9b42 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -1247,14 +1247,14 @@ static int sa1111_bus_remove(struct device *dev)
1247struct bus_type sa1111_bus_type = { 1247struct bus_type sa1111_bus_type = {
1248 .name = "sa1111-rab", 1248 .name = "sa1111-rab",
1249 .match = sa1111_match, 1249 .match = sa1111_match,
1250 .probe = sa1111_bus_probe,
1251 .remove = sa1111_bus_remove,
1250 .suspend = sa1111_bus_suspend, 1252 .suspend = sa1111_bus_suspend,
1251 .resume = sa1111_bus_resume, 1253 .resume = sa1111_bus_resume,
1252}; 1254};
1253 1255
1254int sa1111_driver_register(struct sa1111_driver *driver) 1256int sa1111_driver_register(struct sa1111_driver *driver)
1255{ 1257{
1256 driver->drv.probe = sa1111_bus_probe;
1257 driver->drv.remove = sa1111_bus_remove;
1258 driver->drv.bus = &sa1111_bus_type; 1258 driver->drv.bus = &sa1111_bus_type;
1259 return driver_register(&driver->drv); 1259 return driver_register(&driver->drv);
1260} 1260}
diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c
new file mode 100644
index 000000000000..a45ed1687a59
--- /dev/null
+++ b/arch/arm/common/vic.c
@@ -0,0 +1,92 @@
1/*
2 * linux/arch/arm/common/vic.c
3 *
4 * Copyright (C) 1999 - 2003 ARM Limited
5 * Copyright (C) 2000 Deep Blue Solutions Ltd
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21#include <linux/init.h>
22#include <linux/list.h>
23
24#include <asm/io.h>
25#include <asm/irq.h>
26#include <asm/mach/irq.h>
27#include <asm/hardware/vic.h>
28
29static void __iomem *vic_base;
30
31static void vic_mask_irq(unsigned int irq)
32{
33 irq -= IRQ_VIC_START;
34 writel(1 << irq, vic_base + VIC_INT_ENABLE_CLEAR);
35}
36
37static void vic_unmask_irq(unsigned int irq)
38{
39 irq -= IRQ_VIC_START;
40 writel(1 << irq, vic_base + VIC_INT_ENABLE);
41}
42
43static struct irqchip vic_chip = {
44 .ack = vic_mask_irq,
45 .mask = vic_mask_irq,
46 .unmask = vic_unmask_irq,
47};
48
49void __init vic_init(void __iomem *base, u32 vic_sources)
50{
51 unsigned int i;
52
53 vic_base = base;
54
55 /* Disable all interrupts initially. */
56
57 writel(0, vic_base + VIC_INT_SELECT);
58 writel(0, vic_base + VIC_INT_ENABLE);
59 writel(~0, vic_base + VIC_INT_ENABLE_CLEAR);
60 writel(0, vic_base + VIC_IRQ_STATUS);
61 writel(0, vic_base + VIC_ITCR);
62 writel(~0, vic_base + VIC_INT_SOFT_CLEAR);
63
64 /*
65 * Make sure we clear all existing interrupts
66 */
67 writel(0, vic_base + VIC_VECT_ADDR);
68 for (i = 0; i < 19; i++) {
69 unsigned int value;
70
71 value = readl(vic_base + VIC_VECT_ADDR);
72 writel(value, vic_base + VIC_VECT_ADDR);
73 }
74
75 for (i = 0; i < 16; i++) {
76 void __iomem *reg = vic_base + VIC_VECT_CNTL0 + (i * 4);
77 writel(VIC_VECT_CNTL_ENABLE | i, reg);
78 }
79
80 writel(32, vic_base + VIC_DEF_VECT_ADDR);
81
82 for (i = 0; i < 32; i++) {
83 unsigned int irq = IRQ_VIC_START + i;
84
85 set_irq_chip(irq, &vic_chip);
86
87 if (vic_sources & (1 << i)) {
88 set_irq_handler(irq, do_level_IRQ);
89 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
90 }
91 }
92}
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index de94b0f3ee2a..2ce0e3a27a45 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_ARTHUR) += arthur.o
20obj-$(CONFIG_ISA_DMA) += dma-isa.o 20obj-$(CONFIG_ISA_DMA) += dma-isa.o
21obj-$(CONFIG_PCI) += bios32.o 21obj-$(CONFIG_PCI) += bios32.o
22obj-$(CONFIG_SMP) += smp.o 22obj-$(CONFIG_SMP) += smp.o
23obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o
23 24
24obj-$(CONFIG_IWMMXT) += iwmmxt.o 25obj-$(CONFIG_IWMMXT) += iwmmxt.o
25AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt 26AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index 9997098009a9..1574941ebfe1 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -35,6 +35,16 @@ extern void __udivsi3(void);
35extern void __umodsi3(void); 35extern void __umodsi3(void);
36extern void __do_div64(void); 36extern void __do_div64(void);
37 37
38extern void __aeabi_idiv(void);
39extern void __aeabi_idivmod(void);
40extern void __aeabi_lasr(void);
41extern void __aeabi_llsl(void);
42extern void __aeabi_llsr(void);
43extern void __aeabi_lmul(void);
44extern void __aeabi_uidiv(void);
45extern void __aeabi_uidivmod(void);
46extern void __aeabi_ulcmp(void);
47
38extern void fpundefinstr(void); 48extern void fpundefinstr(void);
39extern void fp_enter(void); 49extern void fp_enter(void);
40 50
@@ -141,6 +151,18 @@ EXPORT_SYMBOL(__udivsi3);
141EXPORT_SYMBOL(__umodsi3); 151EXPORT_SYMBOL(__umodsi3);
142EXPORT_SYMBOL(__do_div64); 152EXPORT_SYMBOL(__do_div64);
143 153
154#ifdef CONFIG_AEABI
155EXPORT_SYMBOL(__aeabi_idiv);
156EXPORT_SYMBOL(__aeabi_idivmod);
157EXPORT_SYMBOL(__aeabi_lasr);
158EXPORT_SYMBOL(__aeabi_llsl);
159EXPORT_SYMBOL(__aeabi_llsr);
160EXPORT_SYMBOL(__aeabi_lmul);
161EXPORT_SYMBOL(__aeabi_uidiv);
162EXPORT_SYMBOL(__aeabi_uidivmod);
163EXPORT_SYMBOL(__aeabi_ulcmp);
164#endif
165
144 /* bitops */ 166 /* bitops */
145EXPORT_SYMBOL(_set_bit_le); 167EXPORT_SYMBOL(_set_bit_le);
146EXPORT_SYMBOL(_test_and_set_bit_le); 168EXPORT_SYMBOL(_test_and_set_bit_le);
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index 55076a75e5bf..75e6f9a94713 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -13,7 +13,7 @@
13#define NR_syscalls 328 13#define NR_syscalls 328
14#else 14#else
15 15
16__syscall_start: 16100:
17/* 0 */ .long sys_restart_syscall 17/* 0 */ .long sys_restart_syscall
18 .long sys_exit 18 .long sys_exit
19 .long sys_fork_wrapper 19 .long sys_fork_wrapper
@@ -27,7 +27,7 @@ __syscall_start:
27/* 10 */ .long sys_unlink 27/* 10 */ .long sys_unlink
28 .long sys_execve_wrapper 28 .long sys_execve_wrapper
29 .long sys_chdir 29 .long sys_chdir
30 .long sys_time /* used by libc4 */ 30 .long OBSOLETE(sys_time) /* used by libc4 */
31 .long sys_mknod 31 .long sys_mknod
32/* 15 */ .long sys_chmod 32/* 15 */ .long sys_chmod
33 .long sys_lchown16 33 .long sys_lchown16
@@ -36,15 +36,15 @@ __syscall_start:
36 .long sys_lseek 36 .long sys_lseek
37/* 20 */ .long sys_getpid 37/* 20 */ .long sys_getpid
38 .long sys_mount 38 .long sys_mount
39 .long sys_oldumount /* used by libc4 */ 39 .long OBSOLETE(sys_oldumount) /* used by libc4 */
40 .long sys_setuid16 40 .long sys_setuid16
41 .long sys_getuid16 41 .long sys_getuid16
42/* 25 */ .long sys_stime 42/* 25 */ .long OBSOLETE(sys_stime)
43 .long sys_ptrace 43 .long sys_ptrace
44 .long sys_alarm /* used by libc4 */ 44 .long OBSOLETE(sys_alarm) /* used by libc4 */
45 .long sys_ni_syscall /* was sys_fstat */ 45 .long sys_ni_syscall /* was sys_fstat */
46 .long sys_pause 46 .long sys_pause
47/* 30 */ .long sys_utime /* used by libc4 */ 47/* 30 */ .long OBSOLETE(sys_utime) /* used by libc4 */
48 .long sys_ni_syscall /* was sys_stty */ 48 .long sys_ni_syscall /* was sys_stty */
49 .long sys_ni_syscall /* was sys_getty */ 49 .long sys_ni_syscall /* was sys_getty */
50 .long sys_access 50 .long sys_access
@@ -90,21 +90,21 @@ __syscall_start:
90 .long sys_sigpending 90 .long sys_sigpending
91 .long sys_sethostname 91 .long sys_sethostname
92/* 75 */ .long sys_setrlimit 92/* 75 */ .long sys_setrlimit
93 .long sys_old_getrlimit /* used by libc4 */ 93 .long OBSOLETE(sys_old_getrlimit) /* used by libc4 */
94 .long sys_getrusage 94 .long sys_getrusage
95 .long sys_gettimeofday 95 .long sys_gettimeofday
96 .long sys_settimeofday 96 .long sys_settimeofday
97/* 80 */ .long sys_getgroups16 97/* 80 */ .long sys_getgroups16
98 .long sys_setgroups16 98 .long sys_setgroups16
99 .long old_select /* used by libc4 */ 99 .long OBSOLETE(old_select) /* used by libc4 */
100 .long sys_symlink 100 .long sys_symlink
101 .long sys_ni_syscall /* was sys_lstat */ 101 .long sys_ni_syscall /* was sys_lstat */
102/* 85 */ .long sys_readlink 102/* 85 */ .long sys_readlink
103 .long sys_uselib 103 .long sys_uselib
104 .long sys_swapon 104 .long sys_swapon
105 .long sys_reboot 105 .long sys_reboot
106 .long old_readdir /* used by libc4 */ 106 .long OBSOLETE(old_readdir) /* used by libc4 */
107/* 90 */ .long old_mmap /* used by libc4 */ 107/* 90 */ .long OBSOLETE(old_mmap) /* used by libc4 */
108 .long sys_munmap 108 .long sys_munmap
109 .long sys_truncate 109 .long sys_truncate
110 .long sys_ftruncate 110 .long sys_ftruncate
@@ -116,7 +116,7 @@ __syscall_start:
116 .long sys_statfs 116 .long sys_statfs
117/* 100 */ .long sys_fstatfs 117/* 100 */ .long sys_fstatfs
118 .long sys_ni_syscall 118 .long sys_ni_syscall
119 .long sys_socketcall 119 .long OBSOLETE(sys_socketcall)
120 .long sys_syslog 120 .long sys_syslog
121 .long sys_setitimer 121 .long sys_setitimer
122/* 105 */ .long sys_getitimer 122/* 105 */ .long sys_getitimer
@@ -127,11 +127,11 @@ __syscall_start:
127/* 110 */ .long sys_ni_syscall /* was sys_iopl */ 127/* 110 */ .long sys_ni_syscall /* was sys_iopl */
128 .long sys_vhangup 128 .long sys_vhangup
129 .long sys_ni_syscall 129 .long sys_ni_syscall
130 .long sys_syscall /* call a syscall */ 130 .long OBSOLETE(sys_syscall) /* call a syscall */
131 .long sys_wait4 131 .long sys_wait4
132/* 115 */ .long sys_swapoff 132/* 115 */ .long sys_swapoff
133 .long sys_sysinfo 133 .long sys_sysinfo
134 .long sys_ipc 134 .long OBSOLETE(ABI(sys_ipc, sys_oabi_ipc))
135 .long sys_fsync 135 .long sys_fsync
136 .long sys_sigreturn_wrapper 136 .long sys_sigreturn_wrapper
137/* 120 */ .long sys_clone_wrapper 137/* 120 */ .long sys_clone_wrapper
@@ -194,8 +194,8 @@ __syscall_start:
194 .long sys_rt_sigtimedwait 194 .long sys_rt_sigtimedwait
195 .long sys_rt_sigqueueinfo 195 .long sys_rt_sigqueueinfo
196 .long sys_rt_sigsuspend_wrapper 196 .long sys_rt_sigsuspend_wrapper
197/* 180 */ .long sys_pread64 197/* 180 */ .long ABI(sys_pread64, sys_oabi_pread64)
198 .long sys_pwrite64 198 .long ABI(sys_pwrite64, sys_oabi_pwrite64)
199 .long sys_chown16 199 .long sys_chown16
200 .long sys_getcwd 200 .long sys_getcwd
201 .long sys_capget 201 .long sys_capget
@@ -207,11 +207,11 @@ __syscall_start:
207/* 190 */ .long sys_vfork_wrapper 207/* 190 */ .long sys_vfork_wrapper
208 .long sys_getrlimit 208 .long sys_getrlimit
209 .long sys_mmap2 209 .long sys_mmap2
210 .long sys_truncate64 210 .long ABI(sys_truncate64, sys_oabi_truncate64)
211 .long sys_ftruncate64 211 .long ABI(sys_ftruncate64, sys_oabi_ftruncate64)
212/* 195 */ .long sys_stat64 212/* 195 */ .long ABI(sys_stat64, sys_oabi_stat64)
213 .long sys_lstat64 213 .long ABI(sys_lstat64, sys_oabi_lstat64)
214 .long sys_fstat64 214 .long ABI(sys_fstat64, sys_oabi_fstat64)
215 .long sys_lchown 215 .long sys_lchown
216 .long sys_getuid 216 .long sys_getuid
217/* 200 */ .long sys_getgid 217/* 200 */ .long sys_getgid
@@ -235,11 +235,11 @@ __syscall_start:
235 .long sys_pivot_root 235 .long sys_pivot_root
236 .long sys_mincore 236 .long sys_mincore
237/* 220 */ .long sys_madvise 237/* 220 */ .long sys_madvise
238 .long sys_fcntl64 238 .long ABI(sys_fcntl64, sys_oabi_fcntl64)
239 .long sys_ni_syscall /* TUX */ 239 .long sys_ni_syscall /* TUX */
240 .long sys_ni_syscall 240 .long sys_ni_syscall
241 .long sys_gettid 241 .long sys_gettid
242/* 225 */ .long sys_readahead 242/* 225 */ .long ABI(sys_readahead, sys_oabi_readahead)
243 .long sys_setxattr 243 .long sys_setxattr
244 .long sys_lsetxattr 244 .long sys_lsetxattr
245 .long sys_fsetxattr 245 .long sys_fsetxattr
@@ -265,8 +265,8 @@ __syscall_start:
265 .long sys_exit_group 265 .long sys_exit_group
266 .long sys_lookup_dcookie 266 .long sys_lookup_dcookie
267/* 250 */ .long sys_epoll_create 267/* 250 */ .long sys_epoll_create
268 .long sys_epoll_ctl 268 .long ABI(sys_epoll_ctl, sys_oabi_epoll_ctl)
269 .long sys_epoll_wait 269 .long ABI(sys_epoll_wait, sys_oabi_epoll_wait)
270 .long sys_remap_file_pages 270 .long sys_remap_file_pages
271 .long sys_ni_syscall /* sys_set_thread_area */ 271 .long sys_ni_syscall /* sys_set_thread_area */
272/* 255 */ .long sys_ni_syscall /* sys_get_thread_area */ 272/* 255 */ .long sys_ni_syscall /* sys_get_thread_area */
@@ -280,8 +280,8 @@ __syscall_start:
280 .long sys_clock_gettime 280 .long sys_clock_gettime
281 .long sys_clock_getres 281 .long sys_clock_getres
282/* 265 */ .long sys_clock_nanosleep 282/* 265 */ .long sys_clock_nanosleep
283 .long sys_statfs64 283 .long sys_statfs64_wrapper
284 .long sys_fstatfs64 284 .long sys_fstatfs64_wrapper
285 .long sys_tgkill 285 .long sys_tgkill
286 .long sys_utimes 286 .long sys_utimes
287/* 270 */ .long sys_arm_fadvise64_64 287/* 270 */ .long sys_arm_fadvise64_64
@@ -312,7 +312,7 @@ __syscall_start:
312/* 295 */ .long sys_getsockopt 312/* 295 */ .long sys_getsockopt
313 .long sys_sendmsg 313 .long sys_sendmsg
314 .long sys_recvmsg 314 .long sys_recvmsg
315 .long sys_semop 315 .long ABI(sys_semop, sys_oabi_semop)
316 .long sys_semget 316 .long sys_semget
317/* 300 */ .long sys_semctl 317/* 300 */ .long sys_semctl
318 .long sys_msgsnd 318 .long sys_msgsnd
@@ -326,7 +326,7 @@ __syscall_start:
326 .long sys_add_key 326 .long sys_add_key
327/* 310 */ .long sys_request_key 327/* 310 */ .long sys_request_key
328 .long sys_keyctl 328 .long sys_keyctl
329 .long sys_semtimedop 329 .long ABI(sys_semtimedop, sys_oabi_semtimedop)
330/* vserver */ .long sys_ni_syscall 330/* vserver */ .long sys_ni_syscall
331 .long sys_ioprio_set 331 .long sys_ioprio_set
332/* 315 */ .long sys_ioprio_get 332/* 315 */ .long sys_ioprio_get
@@ -336,9 +336,8 @@ __syscall_start:
336 .long sys_mbind 336 .long sys_mbind
337/* 320 */ .long sys_get_mempolicy 337/* 320 */ .long sys_get_mempolicy
338 .long sys_set_mempolicy 338 .long sys_set_mempolicy
339__syscall_end:
340 339
341 .rept NR_syscalls - (__syscall_end - __syscall_start) / 4 340 .rept NR_syscalls - (. - 100b) / 4
342 .long sys_ni_syscall 341 .long sys_ni_syscall
343 .endr 342 .endr
344#endif 343#endif
diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
index 96fd91926c9b..74ea29c3205e 100644
--- a/arch/arm/kernel/ecard.c
+++ b/arch/arm/kernel/ecard.c
@@ -1147,9 +1147,11 @@ static void ecard_drv_shutdown(struct device *dev)
1147 struct ecard_driver *drv = ECARD_DRV(dev->driver); 1147 struct ecard_driver *drv = ECARD_DRV(dev->driver);
1148 struct ecard_request req; 1148 struct ecard_request req;
1149 1149
1150 if (drv->shutdown) 1150 if (dev->driver) {
1151 drv->shutdown(ec); 1151 if (drv->shutdown)
1152 ecard_release(ec); 1152 drv->shutdown(ec);
1153 ecard_release(ec);
1154 }
1153 1155
1154 /* 1156 /*
1155 * If this card has a loader, call the reset handler. 1157 * If this card has a loader, call the reset handler.
@@ -1164,9 +1166,6 @@ static void ecard_drv_shutdown(struct device *dev)
1164int ecard_register_driver(struct ecard_driver *drv) 1166int ecard_register_driver(struct ecard_driver *drv)
1165{ 1167{
1166 drv->drv.bus = &ecard_bus_type; 1168 drv->drv.bus = &ecard_bus_type;
1167 drv->drv.probe = ecard_drv_probe;
1168 drv->drv.remove = ecard_drv_remove;
1169 drv->drv.shutdown = ecard_drv_shutdown;
1170 1169
1171 return driver_register(&drv->drv); 1170 return driver_register(&drv->drv);
1172} 1171}
@@ -1195,6 +1194,9 @@ struct bus_type ecard_bus_type = {
1195 .name = "ecard", 1194 .name = "ecard",
1196 .dev_attrs = ecard_dev_attrs, 1195 .dev_attrs = ecard_dev_attrs,
1197 .match = ecard_match, 1196 .match = ecard_match,
1197 .probe = ecard_drv_probe,
1198 .remove = ecard_drv_remove,
1199 .shutdown = ecard_drv_shutdown,
1198}; 1200};
1199 1201
1200static int ecard_bus_init(void) 1202static int ecard_bus_init(void)
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index a52baedf6262..874e6bb79405 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -3,6 +3,7 @@
3 * 3 *
4 * Copyright (C) 1996,1997,1998 Russell King. 4 * Copyright (C) 1996,1997,1998 Russell King.
5 * ARM700 fix by Matthew Godbolt (linux-user@willothewisp.demon.co.uk) 5 * ARM700 fix by Matthew Godbolt (linux-user@willothewisp.demon.co.uk)
6 * nommu support by Hyok S. Choi (hyok.choi@samsung.com)
6 * 7 *
7 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 9 * it under the terms of the GNU General Public License version 2 as
@@ -104,14 +105,24 @@ common_invalid:
104/* 105/*
105 * SVC mode handlers 106 * SVC mode handlers
106 */ 107 */
108
109#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5)
110#define SPFIX(code...) code
111#else
112#define SPFIX(code...)
113#endif
114
107 .macro svc_entry 115 .macro svc_entry
108 sub sp, sp, #S_FRAME_SIZE 116 sub sp, sp, #S_FRAME_SIZE
117 SPFIX( tst sp, #4 )
118 SPFIX( bicne sp, sp, #4 )
109 stmib sp, {r1 - r12} 119 stmib sp, {r1 - r12}
110 120
111 ldmia r0, {r1 - r3} 121 ldmia r0, {r1 - r3}
112 add r5, sp, #S_SP @ here for interlock avoidance 122 add r5, sp, #S_SP @ here for interlock avoidance
113 mov r4, #-1 @ "" "" "" "" 123 mov r4, #-1 @ "" "" "" ""
114 add r0, sp, #S_FRAME_SIZE @ "" "" "" "" 124 add r0, sp, #S_FRAME_SIZE @ "" "" "" ""
125 SPFIX( addne r0, r0, #4 )
115 str r1, [sp] @ save the "real" r0 copied 126 str r1, [sp] @ save the "real" r0 copied
116 @ from the exception stack 127 @ from the exception stack
117 128
@@ -302,7 +313,14 @@ __pabt_svc:
302 313
303/* 314/*
304 * User mode handlers 315 * User mode handlers
316 *
317 * EABI note: sp_svc is always 64-bit aligned here, so should S_FRAME_SIZE
305 */ 318 */
319
320#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) && (S_FRAME_SIZE & 7)
321#error "sizeof(struct pt_regs) must be a multiple of 8"
322#endif
323
306 .macro usr_entry 324 .macro usr_entry
307 sub sp, sp, #S_FRAME_SIZE 325 sub sp, sp, #S_FRAME_SIZE
308 stmib sp, {r1 - r12} 326 stmib sp, {r1 - r12}
@@ -538,7 +556,11 @@ ENTRY(__switch_to)
538 add ip, r1, #TI_CPU_SAVE 556 add ip, r1, #TI_CPU_SAVE
539 ldr r3, [r2, #TI_TP_VALUE] 557 ldr r3, [r2, #TI_TP_VALUE]
540 stmia ip!, {r4 - sl, fp, sp, lr} @ Store most regs on stack 558 stmia ip!, {r4 - sl, fp, sp, lr} @ Store most regs on stack
559#ifndef CONFIG_MMU
560 add r2, r2, #TI_CPU_DOMAIN
561#else
541 ldr r6, [r2, #TI_CPU_DOMAIN]! 562 ldr r6, [r2, #TI_CPU_DOMAIN]!
563#endif
542#if __LINUX_ARM_ARCH__ >= 6 564#if __LINUX_ARM_ARCH__ >= 6
543#ifdef CONFIG_CPU_MPCORE 565#ifdef CONFIG_CPU_MPCORE
544 clrex 566 clrex
@@ -556,7 +578,9 @@ ENTRY(__switch_to)
556 mov r4, #0xffff0fff 578 mov r4, #0xffff0fff
557 str r3, [r4, #-15] @ TLS val at 0xffff0ff0 579 str r3, [r4, #-15] @ TLS val at 0xffff0ff0
558#endif 580#endif
581#ifdef CONFIG_MMU
559 mcr p15, 0, r6, c3, c0, 0 @ Set domain register 582 mcr p15, 0, r6, c3, c0, 0 @ Set domain register
583#endif
560#ifdef CONFIG_VFP 584#ifdef CONFIG_VFP
561 @ Always disable VFP so we can lazily save/restore the old 585 @ Always disable VFP so we can lazily save/restore the old
562 @ state. This occurs in the context of the previous thread. 586 @ state. This occurs in the context of the previous thread.
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index e2b42997ad33..2b92ce85f97f 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -98,20 +98,14 @@ ENTRY(ret_from_fork)
98 run on an ARM7 and we can save a couple of instructions. 98 run on an ARM7 and we can save a couple of instructions.
99 --pb */ 99 --pb */
100#ifdef CONFIG_CPU_ARM710 100#ifdef CONFIG_CPU_ARM710
101 .macro arm710_bug_check, instr, temp 101#define A710(code...) code
102 and \temp, \instr, #0x0f000000 @ check for SWI 102.Larm710bug:
103 teq \temp, #0x0f000000
104 bne .Larm700bug
105 .endm
106
107.Larm700bug:
108 ldmia sp, {r0 - lr}^ @ Get calling r0 - lr 103 ldmia sp, {r0 - lr}^ @ Get calling r0 - lr
109 mov r0, r0 104 mov r0, r0
110 add sp, sp, #S_FRAME_SIZE 105 add sp, sp, #S_FRAME_SIZE
111 subs pc, lr, #4 106 subs pc, lr, #4
112#else 107#else
113 .macro arm710_bug_check, instr, temp 108#define A710(code...)
114 .endm
115#endif 109#endif
116 110
117 .align 5 111 .align 5
@@ -129,14 +123,50 @@ ENTRY(vector_swi)
129 /* 123 /*
130 * Get the system call number. 124 * Get the system call number.
131 */ 125 */
126
127#if defined(CONFIG_OABI_COMPAT)
128
129 /*
130 * If we have CONFIG_OABI_COMPAT then we need to look at the swi
131 * value to determine if it is an EABI or an old ABI call.
132 */
132#ifdef CONFIG_ARM_THUMB 133#ifdef CONFIG_ARM_THUMB
134 tst r8, #PSR_T_BIT
135 movne r10, #0 @ no thumb OABI emulation
136 ldreq r10, [lr, #-4] @ get SWI instruction
137#else
138 ldr r10, [lr, #-4] @ get SWI instruction
139 A710( and ip, r10, #0x0f000000 @ check for SWI )
140 A710( teq ip, #0x0f000000 )
141 A710( bne .Larm710bug )
142#endif
143
144#elif defined(CONFIG_AEABI)
145
146 /*
147 * Pure EABI user space always put syscall number into scno (r7).
148 */
149 A710( ldr ip, [lr, #-4] @ get SWI instruction )
150 A710( and ip, ip, #0x0f000000 @ check for SWI )
151 A710( teq ip, #0x0f000000 )
152 A710( bne .Larm710bug )
153
154#elif defined(CONFIG_ARM_THUMB)
155
156 /* Legacy ABI only, possibly thumb mode. */
133 tst r8, #PSR_T_BIT @ this is SPSR from save_user_regs 157 tst r8, #PSR_T_BIT @ this is SPSR from save_user_regs
134 addne scno, r7, #__NR_SYSCALL_BASE @ put OS number in 158 addne scno, r7, #__NR_SYSCALL_BASE @ put OS number in
135 ldreq scno, [lr, #-4] 159 ldreq scno, [lr, #-4]
160
136#else 161#else
162
163 /* Legacy ABI only. */
137 ldr scno, [lr, #-4] @ get SWI instruction 164 ldr scno, [lr, #-4] @ get SWI instruction
165 A710( and ip, scno, #0x0f000000 @ check for SWI )
166 A710( teq ip, #0x0f000000 )
167 A710( bne .Larm710bug )
168
138#endif 169#endif
139 arm710_bug_check scno, ip
140 170
141#ifdef CONFIG_ALIGNMENT_TRAP 171#ifdef CONFIG_ALIGNMENT_TRAP
142 ldr ip, __cr_alignment 172 ldr ip, __cr_alignment
@@ -145,18 +175,31 @@ ENTRY(vector_swi)
145#endif 175#endif
146 enable_irq 176 enable_irq
147 177
148 stmdb sp!, {r4, r5} @ push fifth and sixth args
149
150 get_thread_info tsk 178 get_thread_info tsk
179 adr tbl, sys_call_table @ load syscall table pointer
151 ldr ip, [tsk, #TI_FLAGS] @ check for syscall tracing 180 ldr ip, [tsk, #TI_FLAGS] @ check for syscall tracing
181
182#if defined(CONFIG_OABI_COMPAT)
183 /*
184 * If the swi argument is zero, this is an EABI call and we do nothing.
185 *
186 * If this is an old ABI call, get the syscall number into scno and
187 * get the old ABI syscall table address.
188 */
189 bics r10, r10, #0xff000000
190 eorne scno, r10, #__NR_OABI_SYSCALL_BASE
191 ldrne tbl, =sys_oabi_call_table
192#elif !defined(CONFIG_AEABI)
152 bic scno, scno, #0xff000000 @ mask off SWI op-code 193 bic scno, scno, #0xff000000 @ mask off SWI op-code
153 eor scno, scno, #__NR_SYSCALL_BASE @ check OS number 194 eor scno, scno, #__NR_SYSCALL_BASE @ check OS number
154 adr tbl, sys_call_table @ load syscall table pointer 195#endif
196
197 stmdb sp!, {r4, r5} @ push fifth and sixth args
155 tst ip, #_TIF_SYSCALL_TRACE @ are we tracing syscalls? 198 tst ip, #_TIF_SYSCALL_TRACE @ are we tracing syscalls?
156 bne __sys_trace 199 bne __sys_trace
157 200
158 adr lr, ret_fast_syscall @ return address
159 cmp scno, #NR_syscalls @ check upper syscall limit 201 cmp scno, #NR_syscalls @ check upper syscall limit
202 adr lr, ret_fast_syscall @ return address
160 ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine 203 ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine
161 204
162 add r1, sp, #S_OFF 205 add r1, sp, #S_OFF
@@ -171,11 +214,13 @@ ENTRY(vector_swi)
171 * context switches, and waiting for our parent to respond. 214 * context switches, and waiting for our parent to respond.
172 */ 215 */
173__sys_trace: 216__sys_trace:
217 mov r2, scno
174 add r1, sp, #S_OFF 218 add r1, sp, #S_OFF
175 mov r0, #0 @ trace entry [IP = 0] 219 mov r0, #0 @ trace entry [IP = 0]
176 bl syscall_trace 220 bl syscall_trace
177 221
178 adr lr, __sys_trace_return @ return address 222 adr lr, __sys_trace_return @ return address
223 mov scno, r0 @ syscall number (possibly new)
179 add r1, sp, #S_R0 + S_OFF @ pointer to regs 224 add r1, sp, #S_R0 + S_OFF @ pointer to regs
180 cmp scno, #NR_syscalls @ check upper syscall limit 225 cmp scno, #NR_syscalls @ check upper syscall limit
181 ldmccia r1, {r0 - r3} @ have to reload r0 - r3 226 ldmccia r1, {r0 - r3} @ have to reload r0 - r3
@@ -184,6 +229,7 @@ __sys_trace:
184 229
185__sys_trace_return: 230__sys_trace_return:
186 str r0, [sp, #S_R0 + S_OFF]! @ save returned r0 231 str r0, [sp, #S_R0 + S_OFF]! @ save returned r0
232 mov r2, scno
187 mov r1, sp 233 mov r1, sp
188 mov r0, #1 @ trace exit [IP = 1] 234 mov r0, #1 @ trace exit [IP = 1]
189 bl syscall_trace 235 bl syscall_trace
@@ -195,10 +241,24 @@ __sys_trace_return:
195__cr_alignment: 241__cr_alignment:
196 .word cr_alignment 242 .word cr_alignment
197#endif 243#endif
244 .ltorg
245
246/*
247 * This is the syscall table declaration for native ABI syscalls.
248 * With EABI a couple syscalls are obsolete and defined as sys_ni_syscall.
249 */
250#define ABI(native, compat) native
251#ifdef CONFIG_AEABI
252#define OBSOLETE(syscall) sys_ni_syscall
253#else
254#define OBSOLETE(syscall) syscall
255#endif
198 256
199 .type sys_call_table, #object 257 .type sys_call_table, #object
200ENTRY(sys_call_table) 258ENTRY(sys_call_table)
201#include "calls.S" 259#include "calls.S"
260#undef ABI
261#undef OBSOLETE
202 262
203/*============================================================================ 263/*============================================================================
204 * Special system call wrappers 264 * Special system call wrappers
@@ -207,7 +267,7 @@ ENTRY(sys_call_table)
207@ r8 = syscall table 267@ r8 = syscall table
208 .type sys_syscall, #function 268 .type sys_syscall, #function
209sys_syscall: 269sys_syscall:
210 eor scno, r0, #__NR_SYSCALL_BASE 270 eor scno, r0, #__NR_OABI_SYSCALL_BASE
211 cmp scno, #__NR_syscall - __NR_SYSCALL_BASE 271 cmp scno, #__NR_syscall - __NR_SYSCALL_BASE
212 cmpne scno, #NR_syscalls @ check range 272 cmpne scno, #NR_syscalls @ check range
213 stmloia sp, {r5, r6} @ shuffle args 273 stmloia sp, {r5, r6} @ shuffle args
@@ -255,6 +315,16 @@ sys_sigaltstack_wrapper:
255 ldr r2, [sp, #S_OFF + S_SP] 315 ldr r2, [sp, #S_OFF + S_SP]
256 b do_sigaltstack 316 b do_sigaltstack
257 317
318sys_statfs64_wrapper:
319 teq r1, #88
320 moveq r1, #84
321 b sys_statfs64
322
323sys_fstatfs64_wrapper:
324 teq r1, #88
325 moveq r1, #84
326 b sys_fstatfs64
327
258/* 328/*
259 * Note: off_4k (r5) is always units of 4K. If we can't do the requested 329 * Note: off_4k (r5) is always units of 4K. If we can't do the requested
260 * offset, we return EINVAL. 330 * offset, we return EINVAL.
@@ -271,3 +341,49 @@ sys_mmap2:
271 str r5, [sp, #4] 341 str r5, [sp, #4]
272 b do_mmap2 342 b do_mmap2
273#endif 343#endif
344
345#ifdef CONFIG_OABI_COMPAT
346
347/*
348 * These are syscalls with argument register differences
349 */
350
351sys_oabi_pread64:
352 stmia sp, {r3, r4}
353 b sys_pread64
354
355sys_oabi_pwrite64:
356 stmia sp, {r3, r4}
357 b sys_pwrite64
358
359sys_oabi_truncate64:
360 mov r3, r2
361 mov r2, r1
362 b sys_truncate64
363
364sys_oabi_ftruncate64:
365 mov r3, r2
366 mov r2, r1
367 b sys_ftruncate64
368
369sys_oabi_readahead:
370 str r3, [sp]
371 mov r3, r2
372 mov r2, r1
373 b sys_readahead
374
375/*
376 * Let's declare a second syscall table for old ABI binaries
377 * using the compatibility syscall entries.
378 */
379#define ABI(native, compat) compat
380#define OBSOLETE(syscall) syscall
381
382 .type sys_oabi_call_table, #object
383ENTRY(sys_oabi_call_table)
384#include "calls.S"
385#undef ABI
386#undef OBSOLETE
387
388#endif
389
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
index 648cfff93138..55c99cdab7d6 100644
--- a/arch/arm/kernel/entry-header.S
+++ b/arch/arm/kernel/entry-header.S
@@ -19,6 +19,7 @@
19@ 19@
20@ Most of the stack format comes from struct pt_regs, but with 20@ Most of the stack format comes from struct pt_regs, but with
21@ the addition of 8 bytes for storing syscall args 5 and 6. 21@ the addition of 8 bytes for storing syscall args 5 and 6.
22@ This _must_ remain a multiple of 8 for EABI.
22@ 23@
23#define S_OFF 8 24#define S_OFF 8
24 25
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 1e985f2cd70f..1aca1775b28f 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -251,12 +251,11 @@ __turn_mmu_on:
251 * r10 = procinfo 251 * r10 = procinfo
252 * 252 *
253 * Returns: 253 * Returns:
254 * r0, r3, r5, r6, r7 corrupted 254 * r0, r3, r6, r7 corrupted
255 * r4 = physical page table address 255 * r4 = physical page table address
256 */ 256 */
257 .type __create_page_tables, %function 257 .type __create_page_tables, %function
258__create_page_tables: 258__create_page_tables:
259 ldr r5, [r8, #MACHINFO_PHYSRAM] @ physram
260 pgtbl r4 @ page table address 259 pgtbl r4 @ page table address
261 260
262 /* 261 /*
@@ -303,7 +302,7 @@ __create_page_tables:
303 * Then map first 1MB of ram in case it contains our boot params. 302 * Then map first 1MB of ram in case it contains our boot params.
304 */ 303 */
305 add r0, r4, #PAGE_OFFSET >> 18 304 add r0, r4, #PAGE_OFFSET >> 18
306 orr r6, r5, r7 305 orr r6, r7, #PHYS_OFFSET
307 str r6, [r0] 306 str r6, [r0]
308 307
309#ifdef CONFIG_XIP_KERNEL 308#ifdef CONFIG_XIP_KERNEL
@@ -311,7 +310,7 @@ __create_page_tables:
311 * Map some ram to cover our .data and .bss areas. 310 * Map some ram to cover our .data and .bss areas.
312 * Mapping 3MB should be plenty. 311 * Mapping 3MB should be plenty.
313 */ 312 */
314 sub r3, r4, r5 313 sub r3, r4, #PHYS_OFFSET
315 mov r3, r3, lsr #20 314 mov r3, r3, lsr #20
316 add r0, r0, r3, lsl #2 315 add r0, r0, r3, lsl #2
317 add r6, r6, r3, lsl #20 316 add r6, r6, r3, lsl #20
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index e591f72bcdeb..7b6256bb590e 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -766,6 +766,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
766 (unsigned long __user *) data); 766 (unsigned long __user *) data);
767 break; 767 break;
768 768
769 case PTRACE_SET_SYSCALL:
770 ret = 0;
771 child->ptrace_message = data;
772 break;
773
769 default: 774 default:
770 ret = ptrace_request(child, request, addr, data); 775 ret = ptrace_request(child, request, addr, data);
771 break; 776 break;
@@ -774,14 +779,14 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
774 return ret; 779 return ret;
775} 780}
776 781
777asmlinkage void syscall_trace(int why, struct pt_regs *regs) 782asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
778{ 783{
779 unsigned long ip; 784 unsigned long ip;
780 785
781 if (!test_thread_flag(TIF_SYSCALL_TRACE)) 786 if (!test_thread_flag(TIF_SYSCALL_TRACE))
782 return; 787 return scno;
783 if (!(current->ptrace & PT_PTRACED)) 788 if (!(current->ptrace & PT_PTRACED))
784 return; 789 return scno;
785 790
786 /* 791 /*
787 * Save IP. IP is used to denote syscall entry/exit: 792 * Save IP. IP is used to denote syscall entry/exit:
@@ -790,6 +795,8 @@ asmlinkage void syscall_trace(int why, struct pt_regs *regs)
790 ip = regs->ARM_ip; 795 ip = regs->ARM_ip;
791 regs->ARM_ip = why; 796 regs->ARM_ip = why;
792 797
798 current->ptrace_message = scno;
799
793 /* the 0x80 provides a way for the tracing parent to distinguish 800 /* the 0x80 provides a way for the tracing parent to distinguish
794 between a syscall stop and SIGTRAP delivery */ 801 between a syscall stop and SIGTRAP delivery */
795 ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) 802 ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
@@ -804,4 +811,6 @@ asmlinkage void syscall_trace(int why, struct pt_regs *regs)
804 current->exit_code = 0; 811 current->exit_code = 0;
805 } 812 }
806 regs->ARM_ip = ip; 813 regs->ARM_ip = ip;
814
815 return current->ptrace_message;
807} 816}
diff --git a/arch/arm/kernel/semaphore.c b/arch/arm/kernel/semaphore.c
index 4c31f2923055..981fe5c6ccbe 100644
--- a/arch/arm/kernel/semaphore.c
+++ b/arch/arm/kernel/semaphore.c
@@ -177,41 +177,42 @@ int __down_trylock(struct semaphore * sem)
177 * ip contains the semaphore pointer on entry. Save the C-clobbered 177 * ip contains the semaphore pointer on entry. Save the C-clobbered
178 * registers (r0 to r3 and lr), but not ip, as we use it as a return 178 * registers (r0 to r3 and lr), but not ip, as we use it as a return
179 * value in some cases.. 179 * value in some cases..
180 * To remain AAPCS compliant (64-bit stack align) we save r4 as well.
180 */ 181 */
181asm(" .section .sched.text,\"ax\",%progbits \n\ 182asm(" .section .sched.text,\"ax\",%progbits \n\
182 .align 5 \n\ 183 .align 5 \n\
183 .globl __down_failed \n\ 184 .globl __down_failed \n\
184__down_failed: \n\ 185__down_failed: \n\
185 stmfd sp!, {r0 - r3, lr} \n\ 186 stmfd sp!, {r0 - r4, lr} \n\
186 mov r0, ip \n\ 187 mov r0, ip \n\
187 bl __down \n\ 188 bl __down \n\
188 ldmfd sp!, {r0 - r3, pc} \n\ 189 ldmfd sp!, {r0 - r4, pc} \n\
189 \n\ 190 \n\
190 .align 5 \n\ 191 .align 5 \n\
191 .globl __down_interruptible_failed \n\ 192 .globl __down_interruptible_failed \n\
192__down_interruptible_failed: \n\ 193__down_interruptible_failed: \n\
193 stmfd sp!, {r0 - r3, lr} \n\ 194 stmfd sp!, {r0 - r4, lr} \n\
194 mov r0, ip \n\ 195 mov r0, ip \n\
195 bl __down_interruptible \n\ 196 bl __down_interruptible \n\
196 mov ip, r0 \n\ 197 mov ip, r0 \n\
197 ldmfd sp!, {r0 - r3, pc} \n\ 198 ldmfd sp!, {r0 - r4, pc} \n\
198 \n\ 199 \n\
199 .align 5 \n\ 200 .align 5 \n\
200 .globl __down_trylock_failed \n\ 201 .globl __down_trylock_failed \n\
201__down_trylock_failed: \n\ 202__down_trylock_failed: \n\
202 stmfd sp!, {r0 - r3, lr} \n\ 203 stmfd sp!, {r0 - r4, lr} \n\
203 mov r0, ip \n\ 204 mov r0, ip \n\
204 bl __down_trylock \n\ 205 bl __down_trylock \n\
205 mov ip, r0 \n\ 206 mov ip, r0 \n\
206 ldmfd sp!, {r0 - r3, pc} \n\ 207 ldmfd sp!, {r0 - r4, pc} \n\
207 \n\ 208 \n\
208 .align 5 \n\ 209 .align 5 \n\
209 .globl __up_wakeup \n\ 210 .globl __up_wakeup \n\
210__up_wakeup: \n\ 211__up_wakeup: \n\
211 stmfd sp!, {r0 - r3, lr} \n\ 212 stmfd sp!, {r0 - r4, lr} \n\
212 mov r0, ip \n\ 213 mov r0, ip \n\
213 bl __up \n\ 214 bl __up \n\
214 ldmfd sp!, {r0 - r3, pc} \n\ 215 ldmfd sp!, {r0 - r4, pc} \n\
215 "); 216 ");
216 217
217EXPORT_SYMBOL(__down_failed); 218EXPORT_SYMBOL(__down_failed);
diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c
index ea569ba482b1..a491de2d9024 100644
--- a/arch/arm/kernel/sys_arm.c
+++ b/arch/arm/kernel/sys_arm.c
@@ -147,6 +147,7 @@ asmlinkage int old_select(struct sel_arg_struct __user *arg)
147 return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp); 147 return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
148} 148}
149 149
150#if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT)
150/* 151/*
151 * sys_ipc() is the de-multiplexer for the SysV IPC calls.. 152 * sys_ipc() is the de-multiplexer for the SysV IPC calls..
152 * 153 *
@@ -226,6 +227,7 @@ asmlinkage int sys_ipc(uint call, int first, int second, int third,
226 return -ENOSYS; 227 return -ENOSYS;
227 } 228 }
228} 229}
230#endif
229 231
230/* Fork a new task - this creates a new program thread. 232/* Fork a new task - this creates a new program thread.
231 * This is called indirectly via a small wrapper 233 * This is called indirectly via a small wrapper
diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c
new file mode 100644
index 000000000000..eafa8e5284af
--- /dev/null
+++ b/arch/arm/kernel/sys_oabi-compat.c
@@ -0,0 +1,339 @@
1/*
2 * arch/arm/kernel/sys_oabi-compat.c
3 *
4 * Compatibility wrappers for syscalls that are used from
5 * old ABI user space binaries with an EABI kernel.
6 *
7 * Author: Nicolas Pitre
8 * Created: Oct 7, 2005
9 * Copyright: MontaVista Software, Inc.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 */
15
16/*
17 * The legacy ABI and the new ARM EABI have different rules making some
18 * syscalls incompatible especially with structure arguments.
19 * Most notably, Eabi says 64-bit members should be 64-bit aligned instead of
20 * simply word aligned. EABI also pads structures to the size of the largest
21 * member it contains instead of the invariant 32-bit.
22 *
23 * The following syscalls are affected:
24 *
25 * sys_stat64:
26 * sys_lstat64:
27 * sys_fstat64:
28 *
29 * struct stat64 has different sizes and some members are shifted
30 * Compatibility wrappers are needed for them and provided below.
31 *
32 * sys_fcntl64:
33 *
34 * struct flock64 has different sizes and some members are shifted
35 * A compatibility wrapper is needed and provided below.
36 *
37 * sys_statfs64:
38 * sys_fstatfs64:
39 *
40 * struct statfs64 has extra padding with EABI growing its size from
41 * 84 to 88. This struct is now __attribute__((packed,aligned(4)))
42 * with a small assembly wrapper to force the sz argument to 84 if it is 88
43 * to avoid copying the extra padding over user space unexpecting it.
44 *
45 * sys_newuname:
46 *
47 * struct new_utsname has no padding with EABI. No problem there.
48 *
49 * sys_epoll_ctl:
50 * sys_epoll_wait:
51 *
52 * struct epoll_event has its second member shifted also affecting the
53 * structure size. Compatibility wrappers are needed and provided below.
54 *
55 * sys_ipc:
56 * sys_semop:
57 * sys_semtimedop:
58 *
59 * struct sembuf loses its padding with EABI. Since arrays of them are
60 * used they have to be copyed to remove the padding. Compatibility wrappers
61 * provided below.
62 */
63
64#include <linux/syscalls.h>
65#include <linux/errno.h>
66#include <linux/fs.h>
67#include <linux/fcntl.h>
68#include <linux/eventpoll.h>
69#include <linux/sem.h>
70#include <asm/ipc.h>
71#include <asm/uaccess.h>
72
73struct oldabi_stat64 {
74 unsigned long long st_dev;
75 unsigned int __pad1;
76 unsigned long __st_ino;
77 unsigned int st_mode;
78 unsigned int st_nlink;
79
80 unsigned long st_uid;
81 unsigned long st_gid;
82
83 unsigned long long st_rdev;
84 unsigned int __pad2;
85
86 long long st_size;
87 unsigned long st_blksize;
88 unsigned long long st_blocks;
89
90 unsigned long st_atime;
91 unsigned long st_atime_nsec;
92
93 unsigned long st_mtime;
94 unsigned long st_mtime_nsec;
95
96 unsigned long st_ctime;
97 unsigned long st_ctime_nsec;
98
99 unsigned long long st_ino;
100} __attribute__ ((packed,aligned(4)));
101
102static long cp_oldabi_stat64(struct kstat *stat,
103 struct oldabi_stat64 __user *statbuf)
104{
105 struct oldabi_stat64 tmp;
106
107 tmp.st_dev = huge_encode_dev(stat->dev);
108 tmp.__pad1 = 0;
109 tmp.__st_ino = stat->ino;
110 tmp.st_mode = stat->mode;
111 tmp.st_nlink = stat->nlink;
112 tmp.st_uid = stat->uid;
113 tmp.st_gid = stat->gid;
114 tmp.st_rdev = huge_encode_dev(stat->rdev);
115 tmp.st_size = stat->size;
116 tmp.st_blocks = stat->blocks;
117 tmp.__pad2 = 0;
118 tmp.st_blksize = stat->blksize;
119 tmp.st_atime = stat->atime.tv_sec;
120 tmp.st_atime_nsec = stat->atime.tv_nsec;
121 tmp.st_mtime = stat->mtime.tv_sec;
122 tmp.st_mtime_nsec = stat->mtime.tv_nsec;
123 tmp.st_ctime = stat->ctime.tv_sec;
124 tmp.st_ctime_nsec = stat->ctime.tv_nsec;
125 tmp.st_ino = stat->ino;
126 return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
127}
128
129asmlinkage long sys_oabi_stat64(char __user * filename,
130 struct oldabi_stat64 __user * statbuf)
131{
132 struct kstat stat;
133 int error = vfs_stat(filename, &stat);
134 if (!error)
135 error = cp_oldabi_stat64(&stat, statbuf);
136 return error;
137}
138
139asmlinkage long sys_oabi_lstat64(char __user * filename,
140 struct oldabi_stat64 __user * statbuf)
141{
142 struct kstat stat;
143 int error = vfs_lstat(filename, &stat);
144 if (!error)
145 error = cp_oldabi_stat64(&stat, statbuf);
146 return error;
147}
148
149asmlinkage long sys_oabi_fstat64(unsigned long fd,
150 struct oldabi_stat64 __user * statbuf)
151{
152 struct kstat stat;
153 int error = vfs_fstat(fd, &stat);
154 if (!error)
155 error = cp_oldabi_stat64(&stat, statbuf);
156 return error;
157}
158
159struct oabi_flock64 {
160 short l_type;
161 short l_whence;
162 loff_t l_start;
163 loff_t l_len;
164 pid_t l_pid;
165} __attribute__ ((packed,aligned(4)));
166
167asmlinkage long sys_oabi_fcntl64(unsigned int fd, unsigned int cmd,
168 unsigned long arg)
169{
170 struct oabi_flock64 user;
171 struct flock64 kernel;
172 mm_segment_t fs = USER_DS; /* initialized to kill a warning */
173 unsigned long local_arg = arg;
174 int ret;
175
176 switch (cmd) {
177 case F_GETLK64:
178 case F_SETLK64:
179 case F_SETLKW64:
180 if (copy_from_user(&user, (struct oabi_flock64 __user *)arg,
181 sizeof(user)))
182 return -EFAULT;
183 kernel.l_type = user.l_type;
184 kernel.l_whence = user.l_whence;
185 kernel.l_start = user.l_start;
186 kernel.l_len = user.l_len;
187 kernel.l_pid = user.l_pid;
188 local_arg = (unsigned long)&kernel;
189 fs = get_fs();
190 set_fs(KERNEL_DS);
191 }
192
193 ret = sys_fcntl64(fd, cmd, local_arg);
194
195 switch (cmd) {
196 case F_GETLK64:
197 if (!ret) {
198 user.l_type = kernel.l_type;
199 user.l_whence = kernel.l_whence;
200 user.l_start = kernel.l_start;
201 user.l_len = kernel.l_len;
202 user.l_pid = kernel.l_pid;
203 if (copy_to_user((struct oabi_flock64 __user *)arg,
204 &user, sizeof(user)))
205 ret = -EFAULT;
206 }
207 case F_SETLK64:
208 case F_SETLKW64:
209 set_fs(fs);
210 }
211
212 return ret;
213}
214
215struct oabi_epoll_event {
216 __u32 events;
217 __u64 data;
218} __attribute__ ((packed,aligned(4)));
219
220asmlinkage long sys_oabi_epoll_ctl(int epfd, int op, int fd,
221 struct oabi_epoll_event __user *event)
222{
223 struct oabi_epoll_event user;
224 struct epoll_event kernel;
225 mm_segment_t fs;
226 long ret;
227
228 if (op == EPOLL_CTL_DEL)
229 return sys_epoll_ctl(epfd, op, fd, NULL);
230 if (copy_from_user(&user, event, sizeof(user)))
231 return -EFAULT;
232 kernel.events = user.events;
233 kernel.data = user.data;
234 fs = get_fs();
235 set_fs(KERNEL_DS);
236 ret = sys_epoll_ctl(epfd, op, fd, &kernel);
237 set_fs(fs);
238 return ret;
239}
240
241asmlinkage long sys_oabi_epoll_wait(int epfd,
242 struct oabi_epoll_event __user *events,
243 int maxevents, int timeout)
244{
245 struct epoll_event *kbuf;
246 mm_segment_t fs;
247 long ret, err, i;
248
249 if (maxevents <= 0 || maxevents > (INT_MAX/sizeof(struct epoll_event)))
250 return -EINVAL;
251 kbuf = kmalloc(sizeof(*kbuf) * maxevents, GFP_KERNEL);
252 if (!kbuf)
253 return -ENOMEM;
254 fs = get_fs();
255 set_fs(KERNEL_DS);
256 ret = sys_epoll_wait(epfd, kbuf, maxevents, timeout);
257 set_fs(fs);
258 err = 0;
259 for (i = 0; i < ret; i++) {
260 __put_user_error(kbuf[i].events, &events->events, err);
261 __put_user_error(kbuf[i].data, &events->data, err);
262 events++;
263 }
264 kfree(kbuf);
265 return err ? -EFAULT : ret;
266}
267
268struct oabi_sembuf {
269 unsigned short sem_num;
270 short sem_op;
271 short sem_flg;
272 unsigned short __pad;
273};
274
275asmlinkage long sys_oabi_semtimedop(int semid,
276 struct oabi_sembuf __user *tsops,
277 unsigned nsops,
278 const struct timespec __user *timeout)
279{
280 struct sembuf *sops;
281 struct timespec local_timeout;
282 long err;
283 int i;
284
285 if (nsops < 1)
286 return -EINVAL;
287 sops = kmalloc(sizeof(*sops) * nsops, GFP_KERNEL);
288 if (!sops)
289 return -ENOMEM;
290 err = 0;
291 for (i = 0; i < nsops; i++) {
292 __get_user_error(sops[i].sem_num, &tsops->sem_num, err);
293 __get_user_error(sops[i].sem_op, &tsops->sem_op, err);
294 __get_user_error(sops[i].sem_flg, &tsops->sem_flg, err);
295 tsops++;
296 }
297 if (timeout) {
298 /* copy this as well before changing domain protection */
299 err |= copy_from_user(&local_timeout, timeout, sizeof(*timeout));
300 timeout = &local_timeout;
301 }
302 if (err) {
303 err = -EFAULT;
304 } else {
305 mm_segment_t fs = get_fs();
306 set_fs(KERNEL_DS);
307 err = sys_semtimedop(semid, sops, nsops, timeout);
308 set_fs(fs);
309 }
310 kfree(sops);
311 return err;
312}
313
314asmlinkage long sys_oabi_semop(int semid, struct oabi_sembuf __user *tsops,
315 unsigned nsops)
316{
317 return sys_oabi_semtimedop(semid, tsops, nsops, NULL);
318}
319
320extern asmlinkage int sys_ipc(uint call, int first, int second, int third,
321 void __user *ptr, long fifth);
322
323asmlinkage int sys_oabi_ipc(uint call, int first, int second, int third,
324 void __user *ptr, long fifth)
325{
326 switch (call & 0xffff) {
327 case SEMOP:
328 return sys_oabi_semtimedop(first,
329 (struct oabi_sembuf __user *)ptr,
330 second, NULL);
331 case SEMTIMEDOP:
332 return sys_oabi_semtimedop(first,
333 (struct oabi_sembuf __user *)ptr,
334 second,
335 (const struct timespec __user *)fifth);
336 default:
337 return sys_ipc(call, first, second, third, ptr, fifth);
338 }
339}
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 93cfd3ffcc72..10235b01582e 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -404,7 +404,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
404 struct thread_info *thread = current_thread_info(); 404 struct thread_info *thread = current_thread_info();
405 siginfo_t info; 405 siginfo_t info;
406 406
407 if ((no >> 16) != 0x9f) 407 if ((no >> 16) != (__ARM_NR_BASE>> 16))
408 return bad_syscall(no, regs); 408 return bad_syscall(no, regs);
409 409
410 switch (no & 0xffff) { 410 switch (no & 0xffff) {
diff --git a/arch/arm/lib/ashldi3.S b/arch/arm/lib/ashldi3.S
index 561e20717b30..55e57a1c2e6d 100644
--- a/arch/arm/lib/ashldi3.S
+++ b/arch/arm/lib/ashldi3.S
@@ -37,6 +37,7 @@ Boston, MA 02110-1301, USA. */
37#endif 37#endif
38 38
39ENTRY(__ashldi3) 39ENTRY(__ashldi3)
40ENTRY(__aeabi_llsl)
40 41
41 subs r3, r2, #32 42 subs r3, r2, #32
42 rsb ip, r2, #32 43 rsb ip, r2, #32
diff --git a/arch/arm/lib/ashrdi3.S b/arch/arm/lib/ashrdi3.S
index 86fb2a90c301..0b31398f89b2 100644
--- a/arch/arm/lib/ashrdi3.S
+++ b/arch/arm/lib/ashrdi3.S
@@ -37,6 +37,7 @@ Boston, MA 02110-1301, USA. */
37#endif 37#endif
38 38
39ENTRY(__ashrdi3) 39ENTRY(__ashrdi3)
40ENTRY(__aeabi_lasr)
40 41
41 subs r3, r2, #32 42 subs r3, r2, #32
42 rsb ip, r2, #32 43 rsb ip, r2, #32
diff --git a/arch/arm/lib/lib1funcs.S b/arch/arm/lib/lib1funcs.S
index 59026029d017..4e492f4b3f0e 100644
--- a/arch/arm/lib/lib1funcs.S
+++ b/arch/arm/lib/lib1funcs.S
@@ -206,6 +206,7 @@ Boston, MA 02111-1307, USA. */
206 206
207 207
208ENTRY(__udivsi3) 208ENTRY(__udivsi3)
209ENTRY(__aeabi_uidiv)
209 210
210 subs r2, r1, #1 211 subs r2, r1, #1
211 moveq pc, lr 212 moveq pc, lr
@@ -246,6 +247,7 @@ ENTRY(__umodsi3)
246 247
247 248
248ENTRY(__divsi3) 249ENTRY(__divsi3)
250ENTRY(__aeabi_idiv)
249 251
250 cmp r1, #0 252 cmp r1, #0
251 eor ip, r0, r1 @ save the sign of the result. 253 eor ip, r0, r1 @ save the sign of the result.
@@ -303,12 +305,33 @@ ENTRY(__modsi3)
303 rsbmi r0, r0, #0 305 rsbmi r0, r0, #0
304 mov pc, lr 306 mov pc, lr
305 307
308#ifdef CONFIG_AEABI
309
310ENTRY(__aeabi_uidivmod)
311
312 stmfd sp!, {r0, r1, ip, lr}
313 bl __aeabi_uidiv
314 ldmfd sp!, {r1, r2, ip, lr}
315 mul r3, r0, r2
316 sub r1, r1, r3
317 mov pc, lr
318
319ENTRY(__aeabi_idivmod)
320
321 stmfd sp!, {r0, r1, ip, lr}
322 bl __aeabi_idiv
323 ldmfd sp!, {r1, r2, ip, lr}
324 mul r3, r0, r2
325 sub r1, r1, r3
326 mov pc, lr
327
328#endif
306 329
307Ldiv0: 330Ldiv0:
308 331
309 str lr, [sp, #-4]! 332 str lr, [sp, #-8]!
310 bl __div0 333 bl __div0
311 mov r0, #0 @ About as wrong as it could be. 334 mov r0, #0 @ About as wrong as it could be.
312 ldr pc, [sp], #4 335 ldr pc, [sp], #8
313 336
314 337
diff --git a/arch/arm/lib/lshrdi3.S b/arch/arm/lib/lshrdi3.S
index 46c2ed19ec95..a86dbdd59cc4 100644
--- a/arch/arm/lib/lshrdi3.S
+++ b/arch/arm/lib/lshrdi3.S
@@ -37,6 +37,7 @@ Boston, MA 02110-1301, USA. */
37#endif 37#endif
38 38
39ENTRY(__lshrdi3) 39ENTRY(__lshrdi3)
40ENTRY(__aeabi_llsr)
40 41
41 subs r3, r2, #32 42 subs r3, r2, #32
42 rsb ip, r2, #32 43 rsb ip, r2, #32
diff --git a/arch/arm/lib/muldi3.S b/arch/arm/lib/muldi3.S
index c7fbdf005319..72d594184b8a 100644
--- a/arch/arm/lib/muldi3.S
+++ b/arch/arm/lib/muldi3.S
@@ -25,6 +25,7 @@
25#endif 25#endif
26 26
27ENTRY(__muldi3) 27ENTRY(__muldi3)
28ENTRY(__aeabi_lmul)
28 29
29 mul xh, yl, xh 30 mul xh, yl, xh
30 mla xh, xl, yh, xh 31 mla xh, xl, yh, xh
diff --git a/arch/arm/lib/ucmpdi2.S b/arch/arm/lib/ucmpdi2.S
index 112630f93e5d..d847a62834cb 100644
--- a/arch/arm/lib/ucmpdi2.S
+++ b/arch/arm/lib/ucmpdi2.S
@@ -10,6 +10,7 @@
10 * published by the Free Software Foundation. 10 * published by the Free Software Foundation.
11 */ 11 */
12 12
13#include <linux/config.h>
13#include <linux/linkage.h> 14#include <linux/linkage.h>
14 15
15#ifdef __ARMEB__ 16#ifdef __ARMEB__
@@ -33,3 +34,16 @@ ENTRY(__ucmpdi2)
33 movhi r0, #2 34 movhi r0, #2
34 mov pc, lr 35 mov pc, lr
35 36
37#ifdef CONFIG_AEABI
38
39ENTRY(__aeabi_ulcmp)
40
41 cmp xh, yh
42 cmpeq xl, yl
43 movlo r0, #-1
44 moveq r0, #0
45 movhi r0, #1
46 mov pc, lr
47
48#endif
49
diff --git a/arch/arm/mach-aaec2000/aaed2000.c b/arch/arm/mach-aaec2000/aaed2000.c
index f5ef69702296..dc5fa8e5ebef 100644
--- a/arch/arm/mach-aaec2000/aaed2000.c
+++ b/arch/arm/mach-aaec2000/aaed2000.c
@@ -90,7 +90,6 @@ static void __init aaed2000_map_io(void)
90 90
91MACHINE_START(AAED2000, "Agilent AAED-2000 Development Platform") 91MACHINE_START(AAED2000, "Agilent AAED-2000 Development Platform")
92 /* Maintainer: Nicolas Bellido Y Ortega */ 92 /* Maintainer: Nicolas Bellido Y Ortega */
93 .phys_ram = 0xf0000000,
94 .phys_io = PIO_BASE, 93 .phys_io = PIO_BASE,
95 .io_pg_offst = ((VIO_BASE) >> 18) & 0xfffc, 94 .io_pg_offst = ((VIO_BASE) >> 18) & 0xfffc,
96 .map_io = aaed2000_map_io, 95 .map_io = aaed2000_map_io,
diff --git a/arch/arm/mach-at91rm9200/board-csb337.c b/arch/arm/mach-at91rm9200/board-csb337.c
index 4aec834ee47f..54022e58d50d 100644
--- a/arch/arm/mach-at91rm9200/board-csb337.c
+++ b/arch/arm/mach-at91rm9200/board-csb337.c
@@ -132,7 +132,6 @@ static void __init csb337_board_init(void)
132 132
133MACHINE_START(CSB337, "Cogent CSB337") 133MACHINE_START(CSB337, "Cogent CSB337")
134 /* Maintainer: Bill Gatliff */ 134 /* Maintainer: Bill Gatliff */
135 .phys_ram = AT91_SDRAM_BASE,
136 .phys_io = AT91_BASE_SYS, 135 .phys_io = AT91_BASE_SYS,
137 .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, 136 .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
138 .boot_params = AT91_SDRAM_BASE + 0x100, 137 .boot_params = AT91_SDRAM_BASE + 0x100,
diff --git a/arch/arm/mach-at91rm9200/board-csb637.c b/arch/arm/mach-at91rm9200/board-csb637.c
index 23e4cc21481a..8195f9d919ea 100644
--- a/arch/arm/mach-at91rm9200/board-csb637.c
+++ b/arch/arm/mach-at91rm9200/board-csb637.c
@@ -105,7 +105,6 @@ static void __init csb637_board_init(void)
105 105
106MACHINE_START(CSB637, "Cogent CSB637") 106MACHINE_START(CSB637, "Cogent CSB637")
107 /* Maintainer: Bill Gatliff */ 107 /* Maintainer: Bill Gatliff */
108 .phys_ram = AT91_SDRAM_BASE,
109 .phys_io = AT91_BASE_SYS, 108 .phys_io = AT91_BASE_SYS,
110 .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, 109 .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
111 .boot_params = AT91_SDRAM_BASE + 0x100, 110 .boot_params = AT91_SDRAM_BASE + 0x100,
diff --git a/arch/arm/mach-at91rm9200/board-dk.c b/arch/arm/mach-at91rm9200/board-dk.c
index 8c747a31b95a..8a783368366e 100644
--- a/arch/arm/mach-at91rm9200/board-dk.c
+++ b/arch/arm/mach-at91rm9200/board-dk.c
@@ -127,7 +127,6 @@ static void __init dk_board_init(void)
127 127
128MACHINE_START(AT91RM9200DK, "Atmel AT91RM9200-DK") 128MACHINE_START(AT91RM9200DK, "Atmel AT91RM9200-DK")
129 /* Maintainer: SAN People/Atmel */ 129 /* Maintainer: SAN People/Atmel */
130 .phys_ram = AT91_SDRAM_BASE,
131 .phys_io = AT91_BASE_SYS, 130 .phys_io = AT91_BASE_SYS,
132 .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, 131 .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
133 .boot_params = AT91_SDRAM_BASE + 0x100, 132 .boot_params = AT91_SDRAM_BASE + 0x100,
diff --git a/arch/arm/mach-at91rm9200/board-ek.c b/arch/arm/mach-at91rm9200/board-ek.c
index d140645711be..fd0752eba897 100644
--- a/arch/arm/mach-at91rm9200/board-ek.c
+++ b/arch/arm/mach-at91rm9200/board-ek.c
@@ -120,7 +120,6 @@ static void __init ek_board_init(void)
120 120
121MACHINE_START(AT91RM9200EK, "Atmel AT91RM9200-EK") 121MACHINE_START(AT91RM9200EK, "Atmel AT91RM9200-EK")
122 /* Maintainer: SAN People/Atmel */ 122 /* Maintainer: SAN People/Atmel */
123 .phys_ram = AT91_SDRAM_BASE,
124 .phys_io = AT91_BASE_SYS, 123 .phys_io = AT91_BASE_SYS,
125 .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, 124 .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
126 .boot_params = AT91_SDRAM_BASE + 0x100, 125 .boot_params = AT91_SDRAM_BASE + 0x100,
diff --git a/arch/arm/mach-clps711x/autcpu12.c b/arch/arm/mach-clps711x/autcpu12.c
index 43b9423d1440..c13ca6c56baa 100644
--- a/arch/arm/mach-clps711x/autcpu12.c
+++ b/arch/arm/mach-clps711x/autcpu12.c
@@ -64,7 +64,6 @@ void __init autcpu12_map_io(void)
64 64
65MACHINE_START(AUTCPU12, "autronix autcpu12") 65MACHINE_START(AUTCPU12, "autronix autcpu12")
66 /* Maintainer: Thomas Gleixner */ 66 /* Maintainer: Thomas Gleixner */
67 .phys_ram = 0xc0000000,
68 .phys_io = 0x80000000, 67 .phys_io = 0x80000000,
69 .io_pg_offst = ((0xff000000) >> 18) & 0xfffc, 68 .io_pg_offst = ((0xff000000) >> 18) & 0xfffc,
70 .boot_params = 0xc0020000, 69 .boot_params = 0xc0020000,
diff --git a/arch/arm/mach-clps711x/cdb89712.c b/arch/arm/mach-clps711x/cdb89712.c
index cba7be5a06c3..831df007f6c7 100644
--- a/arch/arm/mach-clps711x/cdb89712.c
+++ b/arch/arm/mach-clps711x/cdb89712.c
@@ -55,7 +55,6 @@ static void __init cdb89712_map_io(void)
55 55
56MACHINE_START(CDB89712, "Cirrus-CDB89712") 56MACHINE_START(CDB89712, "Cirrus-CDB89712")
57 /* Maintainer: Ray Lehtiniemi */ 57 /* Maintainer: Ray Lehtiniemi */
58 .phys_ram = 0xc0000000,
59 .phys_io = 0x80000000, 58 .phys_io = 0x80000000,
60 .io_pg_offst = ((0xff000000) >> 18) & 0xfffc, 59 .io_pg_offst = ((0xff000000) >> 18) & 0xfffc,
61 .boot_params = 0xc0000100, 60 .boot_params = 0xc0000100,
diff --git a/arch/arm/mach-clps711x/ceiva.c b/arch/arm/mach-clps711x/ceiva.c
index 35d51a759b59..e2b2c5ac8a83 100644
--- a/arch/arm/mach-clps711x/ceiva.c
+++ b/arch/arm/mach-clps711x/ceiva.c
@@ -56,7 +56,6 @@ static void __init ceiva_map_io(void)
56 56
57MACHINE_START(CEIVA, "CEIVA/Polaroid Photo MAX Digital Picture Frame") 57MACHINE_START(CEIVA, "CEIVA/Polaroid Photo MAX Digital Picture Frame")
58 /* Maintainer: Rob Scott */ 58 /* Maintainer: Rob Scott */
59 .phys_ram = 0xc0000000,
60 .phys_io = 0x80000000, 59 .phys_io = 0x80000000,
61 .io_pg_offst = ((0xff000000) >> 18) & 0xfffc, 60 .io_pg_offst = ((0xff000000) >> 18) & 0xfffc,
62 .boot_params = 0xc0000100, 61 .boot_params = 0xc0000100,
diff --git a/arch/arm/mach-clps711x/clep7312.c b/arch/arm/mach-clps711x/clep7312.c
index c83f3fd68fcd..09fb57e45213 100644
--- a/arch/arm/mach-clps711x/clep7312.c
+++ b/arch/arm/mach-clps711x/clep7312.c
@@ -38,7 +38,6 @@ fixup_clep7312(struct machine_desc *desc, struct tag *tags,
38 38
39MACHINE_START(CLEP7212, "Cirrus Logic 7212/7312") 39MACHINE_START(CLEP7212, "Cirrus Logic 7212/7312")
40 /* Maintainer: Nobody */ 40 /* Maintainer: Nobody */
41 .phys_ram = 0xc0000000,
42 .phys_io = 0x80000000, 41 .phys_io = 0x80000000,
43 .io_pg_offst = ((0xff000000) >> 18) & 0xfffc, 42 .io_pg_offst = ((0xff000000) >> 18) & 0xfffc,
44 .boot_params = 0xc0000100, 43 .boot_params = 0xc0000100,
diff --git a/arch/arm/mach-clps711x/edb7211-arch.c b/arch/arm/mach-clps711x/edb7211-arch.c
index 255c98b63e15..dc81cc68595d 100644
--- a/arch/arm/mach-clps711x/edb7211-arch.c
+++ b/arch/arm/mach-clps711x/edb7211-arch.c
@@ -52,7 +52,6 @@ fixup_edb7211(struct machine_desc *desc, struct tag *tags,
52 52
53MACHINE_START(EDB7211, "CL-EDB7211 (EP7211 eval board)") 53MACHINE_START(EDB7211, "CL-EDB7211 (EP7211 eval board)")
54 /* Maintainer: Jon McClintock */ 54 /* Maintainer: Jon McClintock */
55 .phys_ram = 0xc0000000,
56 .phys_io = 0x80000000, 55 .phys_io = 0x80000000,
57 .io_pg_offst = ((0xff000000) >> 18) & 0xfffc, 56 .io_pg_offst = ((0xff000000) >> 18) & 0xfffc,
58 .boot_params = 0xc0020100, /* 0xc0000000 - 0xc001ffff can be video RAM */ 57 .boot_params = 0xc0020100, /* 0xc0000000 - 0xc001ffff can be video RAM */
diff --git a/arch/arm/mach-clps711x/fortunet.c b/arch/arm/mach-clps711x/fortunet.c
index 3d88da0c287b..ff26a85aa4ba 100644
--- a/arch/arm/mach-clps711x/fortunet.c
+++ b/arch/arm/mach-clps711x/fortunet.c
@@ -78,7 +78,6 @@ fortunet_fixup(struct machine_desc *desc, struct tag *tags,
78 78
79MACHINE_START(FORTUNET, "ARM-FortuNet") 79MACHINE_START(FORTUNET, "ARM-FortuNet")
80 /* Maintainer: FortuNet Inc. */ 80 /* Maintainer: FortuNet Inc. */
81 .phys_ram = 0xc0000000,
82 .phys_io = 0x80000000, 81 .phys_io = 0x80000000,
83 .io_pg_offst = ((0xf0000000) >> 18) & 0xfffc, 82 .io_pg_offst = ((0xf0000000) >> 18) & 0xfffc,
84 .boot_params = 0x00000000, 83 .boot_params = 0x00000000,
diff --git a/arch/arm/mach-clps711x/p720t.c b/arch/arm/mach-clps711x/p720t.c
index a1acb945fb51..9ba45f4d5a7e 100644
--- a/arch/arm/mach-clps711x/p720t.c
+++ b/arch/arm/mach-clps711x/p720t.c
@@ -90,7 +90,6 @@ static void __init p720t_map_io(void)
90 90
91MACHINE_START(P720T, "ARM-Prospector720T") 91MACHINE_START(P720T, "ARM-Prospector720T")
92 /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ 92 /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
93 .phys_ram = 0xc0000000,
94 .phys_io = 0x80000000, 93 .phys_io = 0x80000000,
95 .io_pg_offst = ((0xff000000) >> 18) & 0xfffc, 94 .io_pg_offst = ((0xff000000) >> 18) & 0xfffc,
96 .boot_params = 0xc0000100, 95 .boot_params = 0xc0000100,
diff --git a/arch/arm/mach-clps7500/core.c b/arch/arm/mach-clps7500/core.c
index d869af0023f8..5b12cab0e691 100644
--- a/arch/arm/mach-clps7500/core.c
+++ b/arch/arm/mach-clps7500/core.c
@@ -384,7 +384,6 @@ static void __init clps7500_init(void)
384 384
385MACHINE_START(CLPS7500, "CL-PS7500") 385MACHINE_START(CLPS7500, "CL-PS7500")
386 /* Maintainer: Philip Blundell */ 386 /* Maintainer: Philip Blundell */
387 .phys_ram = 0x10000000,
388 .phys_io = 0x03000000, 387 .phys_io = 0x03000000,
389 .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc, 388 .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc,
390 .map_io = clps7500_map_io, 389 .map_io = clps7500_map_io,
diff --git a/arch/arm/mach-ebsa110/core.c b/arch/arm/mach-ebsa110/core.c
index ed4614983adb..6d620d8268cc 100644
--- a/arch/arm/mach-ebsa110/core.c
+++ b/arch/arm/mach-ebsa110/core.c
@@ -284,7 +284,6 @@ arch_initcall(ebsa110_init);
284 284
285MACHINE_START(EBSA110, "EBSA110") 285MACHINE_START(EBSA110, "EBSA110")
286 /* Maintainer: Russell King */ 286 /* Maintainer: Russell King */
287 .phys_ram = 0x00000000,
288 .phys_io = 0xe0000000, 287 .phys_io = 0xe0000000,
289 .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc, 288 .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc,
290 .boot_params = 0x00000400, 289 .boot_params = 0x00000400,
diff --git a/arch/arm/mach-footbridge/cats-hw.c b/arch/arm/mach-footbridge/cats-hw.c
index 49b898af0032..5b64d5c5b967 100644
--- a/arch/arm/mach-footbridge/cats-hw.c
+++ b/arch/arm/mach-footbridge/cats-hw.c
@@ -85,7 +85,6 @@ fixup_cats(struct machine_desc *desc, struct tag *tags,
85 85
86MACHINE_START(CATS, "Chalice-CATS") 86MACHINE_START(CATS, "Chalice-CATS")
87 /* Maintainer: Philip Blundell */ 87 /* Maintainer: Philip Blundell */
88 .phys_ram = 0x00000000,
89 .phys_io = DC21285_ARMCSR_BASE, 88 .phys_io = DC21285_ARMCSR_BASE,
90 .io_pg_offst = ((0xfe000000) >> 18) & 0xfffc, 89 .io_pg_offst = ((0xfe000000) >> 18) & 0xfffc,
91 .boot_params = 0x00000100, 90 .boot_params = 0x00000100,
diff --git a/arch/arm/mach-footbridge/co285.c b/arch/arm/mach-footbridge/co285.c
index 548a79081688..4545576ad8d9 100644
--- a/arch/arm/mach-footbridge/co285.c
+++ b/arch/arm/mach-footbridge/co285.c
@@ -29,7 +29,6 @@ fixup_coebsa285(struct machine_desc *desc, struct tag *tags,
29 29
30MACHINE_START(CO285, "co-EBSA285") 30MACHINE_START(CO285, "co-EBSA285")
31 /* Maintainer: Mark van Doesburg */ 31 /* Maintainer: Mark van Doesburg */
32 .phys_ram = 0x00000000,
33 .phys_io = DC21285_ARMCSR_BASE, 32 .phys_io = DC21285_ARMCSR_BASE,
34 .io_pg_offst = ((0x7cf00000) >> 18) & 0xfffc, 33 .io_pg_offst = ((0x7cf00000) >> 18) & 0xfffc,
35 .fixup = fixup_coebsa285, 34 .fixup = fixup_coebsa285,
diff --git a/arch/arm/mach-footbridge/ebsa285.c b/arch/arm/mach-footbridge/ebsa285.c
index 1c37605268d5..b1d3bf20a41e 100644
--- a/arch/arm/mach-footbridge/ebsa285.c
+++ b/arch/arm/mach-footbridge/ebsa285.c
@@ -14,7 +14,6 @@
14 14
15MACHINE_START(EBSA285, "EBSA285") 15MACHINE_START(EBSA285, "EBSA285")
16 /* Maintainer: Russell King */ 16 /* Maintainer: Russell King */
17 .phys_ram = 0x00000000,
18 .phys_io = DC21285_ARMCSR_BASE, 17 .phys_io = DC21285_ARMCSR_BASE,
19 .io_pg_offst = ((0xfe000000) >> 18) & 0xfffc, 18 .io_pg_offst = ((0xfe000000) >> 18) & 0xfffc,
20 .boot_params = 0x00000100, 19 .boot_params = 0x00000100,
diff --git a/arch/arm/mach-footbridge/netwinder-hw.c b/arch/arm/mach-footbridge/netwinder-hw.c
index 9e563de465b5..229bf0585e40 100644
--- a/arch/arm/mach-footbridge/netwinder-hw.c
+++ b/arch/arm/mach-footbridge/netwinder-hw.c
@@ -649,7 +649,6 @@ fixup_netwinder(struct machine_desc *desc, struct tag *tags,
649 649
650MACHINE_START(NETWINDER, "Rebel-NetWinder") 650MACHINE_START(NETWINDER, "Rebel-NetWinder")
651 /* Maintainer: Russell King/Rebel.com */ 651 /* Maintainer: Russell King/Rebel.com */
652 .phys_ram = 0x00000000,
653 .phys_io = DC21285_ARMCSR_BASE, 652 .phys_io = DC21285_ARMCSR_BASE,
654 .io_pg_offst = ((0xfe000000) >> 18) & 0xfffc, 653 .io_pg_offst = ((0xfe000000) >> 18) & 0xfffc,
655 .boot_params = 0x00000100, 654 .boot_params = 0x00000100,
diff --git a/arch/arm/mach-footbridge/personal.c b/arch/arm/mach-footbridge/personal.c
index 0146b8bb59da..c4f843fc099d 100644
--- a/arch/arm/mach-footbridge/personal.c
+++ b/arch/arm/mach-footbridge/personal.c
@@ -14,7 +14,6 @@
14 14
15MACHINE_START(PERSONAL_SERVER, "Compaq-PersonalServer") 15MACHINE_START(PERSONAL_SERVER, "Compaq-PersonalServer")
16 /* Maintainer: Jamey Hicks / George France */ 16 /* Maintainer: Jamey Hicks / George France */
17 .phys_ram = 0x00000000,
18 .phys_io = DC21285_ARMCSR_BASE, 17 .phys_io = DC21285_ARMCSR_BASE,
19 .io_pg_offst = ((0xfe000000) >> 18) & 0xfffc, 18 .io_pg_offst = ((0xfe000000) >> 18) & 0xfffc,
20 .boot_params = 0x00000100, 19 .boot_params = 0x00000100,
diff --git a/arch/arm/mach-h720x/h7201-eval.c b/arch/arm/mach-h720x/h7201-eval.c
index fa59e9e2a5c8..193f968edac3 100644
--- a/arch/arm/mach-h720x/h7201-eval.c
+++ b/arch/arm/mach-h720x/h7201-eval.c
@@ -31,7 +31,6 @@
31 31
32MACHINE_START(H7201, "Hynix GMS30C7201") 32MACHINE_START(H7201, "Hynix GMS30C7201")
33 /* Maintainer: Robert Schwebel, Pengutronix */ 33 /* Maintainer: Robert Schwebel, Pengutronix */
34 .phys_ram = 0x40000000,
35 .phys_io = 0x80000000, 34 .phys_io = 0x80000000,
36 .io_pg_offst = ((0xf0000000) >> 18) & 0xfffc, 35 .io_pg_offst = ((0xf0000000) >> 18) & 0xfffc,
37 .boot_params = 0xc0001000, 36 .boot_params = 0xc0001000,
diff --git a/arch/arm/mach-h720x/h7202-eval.c b/arch/arm/mach-h720x/h7202-eval.c
index d75c8221d2a5..36266896979c 100644
--- a/arch/arm/mach-h720x/h7202-eval.c
+++ b/arch/arm/mach-h720x/h7202-eval.c
@@ -72,7 +72,6 @@ static void __init init_eval_h7202(void)
72 72
73MACHINE_START(H7202, "Hynix HMS30C7202") 73MACHINE_START(H7202, "Hynix HMS30C7202")
74 /* Maintainer: Robert Schwebel, Pengutronix */ 74 /* Maintainer: Robert Schwebel, Pengutronix */
75 .phys_ram = 0x40000000,
76 .phys_io = 0x80000000, 75 .phys_io = 0x80000000,
77 .io_pg_offst = ((0xf0000000) >> 18) & 0xfffc, 76 .io_pg_offst = ((0xf0000000) >> 18) & 0xfffc,
78 .boot_params = 0x40000100, 77 .boot_params = 0x40000100,
diff --git a/arch/arm/mach-imx/mx1ads.c b/arch/arm/mach-imx/mx1ads.c
index c9e0cd8ed016..dc31e3fd6c57 100644
--- a/arch/arm/mach-imx/mx1ads.c
+++ b/arch/arm/mach-imx/mx1ads.c
@@ -69,7 +69,6 @@ mx1ads_map_io(void)
69 69
70MACHINE_START(MX1ADS, "Motorola MX1ADS") 70MACHINE_START(MX1ADS, "Motorola MX1ADS")
71 /* Maintainer: Sascha Hauer, Pengutronix */ 71 /* Maintainer: Sascha Hauer, Pengutronix */
72 .phys_ram = 0x08000000,
73 .phys_io = 0x00200000, 72 .phys_io = 0x00200000,
74 .io_pg_offst = ((0xe0200000) >> 18) & 0xfffc, 73 .io_pg_offst = ((0xe0200000) >> 18) & 0xfffc,
75 .boot_params = 0x08000100, 74 .boot_params = 0x08000100,
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c
index 3afedeb56a6e..d8d3c2a5a97e 100644
--- a/arch/arm/mach-integrator/integrator_ap.c
+++ b/arch/arm/mach-integrator/integrator_ap.c
@@ -347,7 +347,6 @@ static struct sys_timer ap_timer = {
347 347
348MACHINE_START(INTEGRATOR, "ARM-Integrator") 348MACHINE_START(INTEGRATOR, "ARM-Integrator")
349 /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ 349 /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
350 .phys_ram = 0x00000000,
351 .phys_io = 0x16000000, 350 .phys_io = 0x16000000,
352 .io_pg_offst = ((0xf1600000) >> 18) & 0xfffc, 351 .io_pg_offst = ((0xf1600000) >> 18) & 0xfffc,
353 .boot_params = 0x00000100, 352 .boot_params = 0x00000100,
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index 16cf2482a3e9..31820170f306 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -578,7 +578,6 @@ static struct sys_timer cp_timer = {
578 578
579MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP") 579MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP")
580 /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ 580 /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
581 .phys_ram = 0x00000000,
582 .phys_io = 0x16000000, 581 .phys_io = 0x16000000,
583 .io_pg_offst = ((0xf1600000) >> 18) & 0xfffc, 582 .io_pg_offst = ((0xf1600000) >> 18) & 0xfffc,
584 .boot_params = 0x00000100, 583 .boot_params = 0x00000100,
diff --git a/arch/arm/mach-integrator/lm.c b/arch/arm/mach-integrator/lm.c
index 5b41e3a724e1..622cdc4212dd 100644
--- a/arch/arm/mach-integrator/lm.c
+++ b/arch/arm/mach-integrator/lm.c
@@ -22,20 +22,6 @@ static int lm_match(struct device *dev, struct device_driver *drv)
22 return 1; 22 return 1;
23} 23}
24 24
25static struct bus_type lm_bustype = {
26 .name = "logicmodule",
27 .match = lm_match,
28// .suspend = lm_suspend,
29// .resume = lm_resume,
30};
31
32static int __init lm_init(void)
33{
34 return bus_register(&lm_bustype);
35}
36
37postcore_initcall(lm_init);
38
39static int lm_bus_probe(struct device *dev) 25static int lm_bus_probe(struct device *dev)
40{ 26{
41 struct lm_device *lmdev = to_lm_device(dev); 27 struct lm_device *lmdev = to_lm_device(dev);
@@ -49,16 +35,30 @@ static int lm_bus_remove(struct device *dev)
49 struct lm_device *lmdev = to_lm_device(dev); 35 struct lm_device *lmdev = to_lm_device(dev);
50 struct lm_driver *lmdrv = to_lm_driver(dev->driver); 36 struct lm_driver *lmdrv = to_lm_driver(dev->driver);
51 37
52 lmdrv->remove(lmdev); 38 if (lmdrv->remove)
39 lmdrv->remove(lmdev);
53 return 0; 40 return 0;
54} 41}
55 42
43static struct bus_type lm_bustype = {
44 .name = "logicmodule",
45 .match = lm_match,
46 .probe = lm_bus_probe,
47 .remove = lm_bus_remove,
48// .suspend = lm_bus_suspend,
49// .resume = lm_bus_resume,
50};
51
52static int __init lm_init(void)
53{
54 return bus_register(&lm_bustype);
55}
56
57postcore_initcall(lm_init);
58
56int lm_driver_register(struct lm_driver *drv) 59int lm_driver_register(struct lm_driver *drv)
57{ 60{
58 drv->drv.bus = &lm_bustype; 61 drv->drv.bus = &lm_bustype;
59 drv->drv.probe = lm_bus_probe;
60 drv->drv.remove = lm_bus_remove;
61
62 return driver_register(&drv->drv); 62 return driver_register(&drv->drv);
63} 63}
64 64
diff --git a/arch/arm/mach-iop3xx/iop321-setup.c b/arch/arm/mach-iop3xx/iop321-setup.c
index 80770233b8d4..e4f4c52d93d4 100644
--- a/arch/arm/mach-iop3xx/iop321-setup.c
+++ b/arch/arm/mach-iop3xx/iop321-setup.c
@@ -151,7 +151,6 @@ extern void iop321_init_time(void);
151#if defined(CONFIG_ARCH_IQ80321) 151#if defined(CONFIG_ARCH_IQ80321)
152MACHINE_START(IQ80321, "Intel IQ80321") 152MACHINE_START(IQ80321, "Intel IQ80321")
153 /* Maintainer: Intel Corporation */ 153 /* Maintainer: Intel Corporation */
154 .phys_ram = PHYS_OFFSET,
155 .phys_io = IQ80321_UART, 154 .phys_io = IQ80321_UART,
156 .io_pg_offst = ((IQ80321_UART) >> 18) & 0xfffc, 155 .io_pg_offst = ((IQ80321_UART) >> 18) & 0xfffc,
157 .map_io = iq80321_map_io, 156 .map_io = iq80321_map_io,
@@ -163,7 +162,6 @@ MACHINE_END
163#elif defined(CONFIG_ARCH_IQ31244) 162#elif defined(CONFIG_ARCH_IQ31244)
164MACHINE_START(IQ31244, "Intel IQ31244") 163MACHINE_START(IQ31244, "Intel IQ31244")
165 /* Maintainer: Intel Corp. */ 164 /* Maintainer: Intel Corp. */
166 .phys_ram = PHYS_OFFSET,
167 .phys_io = IQ31244_UART, 165 .phys_io = IQ31244_UART,
168 .io_pg_offst = ((IQ31244_UART) >> 18) & 0xfffc, 166 .io_pg_offst = ((IQ31244_UART) >> 18) & 0xfffc,
169 .map_io = iq31244_map_io, 167 .map_io = iq31244_map_io,
diff --git a/arch/arm/mach-iop3xx/iop331-setup.c b/arch/arm/mach-iop3xx/iop331-setup.c
index e6ea1cba6a17..63585485123e 100644
--- a/arch/arm/mach-iop3xx/iop331-setup.c
+++ b/arch/arm/mach-iop3xx/iop331-setup.c
@@ -195,7 +195,6 @@ extern void iq80332_map_io(void);
195#if defined(CONFIG_ARCH_IQ80331) 195#if defined(CONFIG_ARCH_IQ80331)
196MACHINE_START(IQ80331, "Intel IQ80331") 196MACHINE_START(IQ80331, "Intel IQ80331")
197 /* Maintainer: Intel Corp. */ 197 /* Maintainer: Intel Corp. */
198 .phys_ram = PHYS_OFFSET,
199 .phys_io = 0xfefff000, 198 .phys_io = 0xfefff000,
200 .io_pg_offst = ((0xfffff000) >> 18) & 0xfffc, // virtual, physical 199 .io_pg_offst = ((0xfffff000) >> 18) & 0xfffc, // virtual, physical
201 .map_io = iq80331_map_io, 200 .map_io = iq80331_map_io,
@@ -208,7 +207,6 @@ MACHINE_END
208#elif defined(CONFIG_MACH_IQ80332) 207#elif defined(CONFIG_MACH_IQ80332)
209MACHINE_START(IQ80332, "Intel IQ80332") 208MACHINE_START(IQ80332, "Intel IQ80332")
210 /* Maintainer: Intel Corp. */ 209 /* Maintainer: Intel Corp. */
211 .phys_ram = PHYS_OFFSET,
212 .phys_io = 0xfefff000, 210 .phys_io = 0xfefff000,
213 .io_pg_offst = ((0xfffff000) >> 18) & 0xfffc, // virtual, physical 211 .io_pg_offst = ((0xfffff000) >> 18) & 0xfffc, // virtual, physical
214 .map_io = iq80332_map_io, 212 .map_io = iq80332_map_io,
diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c
index 6851abaf5524..cfd5bef3190b 100644
--- a/arch/arm/mach-ixp2000/core.c
+++ b/arch/arm/mach-ixp2000/core.c
@@ -106,6 +106,16 @@ static struct map_desc ixp2000_io_desc[] __initdata = {
106 .length = IXP2000_MSF_SIZE, 106 .length = IXP2000_MSF_SIZE,
107 .type = MT_IXP2000_DEVICE, 107 .type = MT_IXP2000_DEVICE,
108 }, { 108 }, {
109 .virtual = IXP2000_SCRATCH_RING_VIRT_BASE,
110 .pfn = __phys_to_pfn(IXP2000_SCRATCH_RING_PHYS_BASE),
111 .length = IXP2000_SCRATCH_RING_SIZE,
112 .type = MT_IXP2000_DEVICE,
113 }, {
114 .virtual = IXP2000_SRAM0_VIRT_BASE,
115 .pfn = __phys_to_pfn(IXP2000_SRAM0_PHYS_BASE),
116 .length = IXP2000_SRAM0_SIZE,
117 .type = MT_IXP2000_DEVICE,
118 }, {
109 .virtual = IXP2000_PCI_IO_VIRT_BASE, 119 .virtual = IXP2000_PCI_IO_VIRT_BASE,
110 .pfn = __phys_to_pfn(IXP2000_PCI_IO_PHYS_BASE), 120 .pfn = __phys_to_pfn(IXP2000_PCI_IO_PHYS_BASE),
111 .length = IXP2000_PCI_IO_SIZE, 121 .length = IXP2000_PCI_IO_SIZE,
diff --git a/arch/arm/mach-ixp2000/enp2611.c b/arch/arm/mach-ixp2000/enp2611.c
index 61f6006241bd..9e5a13bb39d0 100644
--- a/arch/arm/mach-ixp2000/enp2611.c
+++ b/arch/arm/mach-ixp2000/enp2611.c
@@ -254,7 +254,6 @@ static void __init enp2611_init_machine(void)
254 254
255MACHINE_START(ENP2611, "Radisys ENP-2611 PCI network processor board") 255MACHINE_START(ENP2611, "Radisys ENP-2611 PCI network processor board")
256 /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */ 256 /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
257 .phys_ram = 0x00000000,
258 .phys_io = IXP2000_UART_PHYS_BASE, 257 .phys_io = IXP2000_UART_PHYS_BASE,
259 .io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc, 258 .io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc,
260 .boot_params = 0x00000100, 259 .boot_params = 0x00000100,
diff --git a/arch/arm/mach-ixp2000/ixdp2400.c b/arch/arm/mach-ixp2000/ixdp2400.c
index fd280a93637e..7c782403042a 100644
--- a/arch/arm/mach-ixp2000/ixdp2400.c
+++ b/arch/arm/mach-ixp2000/ixdp2400.c
@@ -169,7 +169,6 @@ void ixdp2400_init_irq(void)
169 169
170MACHINE_START(IXDP2400, "Intel IXDP2400 Development Platform") 170MACHINE_START(IXDP2400, "Intel IXDP2400 Development Platform")
171 /* Maintainer: MontaVista Software, Inc. */ 171 /* Maintainer: MontaVista Software, Inc. */
172 .phys_ram = 0x00000000,
173 .phys_io = IXP2000_UART_PHYS_BASE, 172 .phys_io = IXP2000_UART_PHYS_BASE,
174 .io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc, 173 .io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc,
175 .boot_params = 0x00000100, 174 .boot_params = 0x00000100,
diff --git a/arch/arm/mach-ixp2000/ixdp2800.c b/arch/arm/mach-ixp2000/ixdp2800.c
index f9073aa28615..076e3f8acc96 100644
--- a/arch/arm/mach-ixp2000/ixdp2800.c
+++ b/arch/arm/mach-ixp2000/ixdp2800.c
@@ -285,7 +285,6 @@ void ixdp2800_init_irq(void)
285 285
286MACHINE_START(IXDP2800, "Intel IXDP2800 Development Platform") 286MACHINE_START(IXDP2800, "Intel IXDP2800 Development Platform")
287 /* Maintainer: MontaVista Software, Inc. */ 287 /* Maintainer: MontaVista Software, Inc. */
288 .phys_ram = 0x00000000,
289 .phys_io = IXP2000_UART_PHYS_BASE, 288 .phys_io = IXP2000_UART_PHYS_BASE,
290 .io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc, 289 .io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc,
291 .boot_params = 0x00000100, 290 .boot_params = 0x00000100,
diff --git a/arch/arm/mach-ixp2000/ixdp2x01.c b/arch/arm/mach-ixp2000/ixdp2x01.c
index e6a882f35da2..10f06606d460 100644
--- a/arch/arm/mach-ixp2000/ixdp2x01.c
+++ b/arch/arm/mach-ixp2000/ixdp2x01.c
@@ -376,7 +376,6 @@ static void __init ixdp2x01_init_machine(void)
376#ifdef CONFIG_ARCH_IXDP2401 376#ifdef CONFIG_ARCH_IXDP2401
377MACHINE_START(IXDP2401, "Intel IXDP2401 Development Platform") 377MACHINE_START(IXDP2401, "Intel IXDP2401 Development Platform")
378 /* Maintainer: MontaVista Software, Inc. */ 378 /* Maintainer: MontaVista Software, Inc. */
379 .phys_ram = 0x00000000,
380 .phys_io = IXP2000_UART_PHYS_BASE, 379 .phys_io = IXP2000_UART_PHYS_BASE,
381 .io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc, 380 .io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc,
382 .boot_params = 0x00000100, 381 .boot_params = 0x00000100,
@@ -390,7 +389,6 @@ MACHINE_END
390#ifdef CONFIG_ARCH_IXDP2801 389#ifdef CONFIG_ARCH_IXDP2801
391MACHINE_START(IXDP2801, "Intel IXDP2801 Development Platform") 390MACHINE_START(IXDP2801, "Intel IXDP2801 Development Platform")
392 /* Maintainer: MontaVista Software, Inc. */ 391 /* Maintainer: MontaVista Software, Inc. */
393 .phys_ram = 0x00000000,
394 .phys_io = IXP2000_UART_PHYS_BASE, 392 .phys_io = IXP2000_UART_PHYS_BASE,
395 .io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc, 393 .io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc,
396 .boot_params = 0x00000100, 394 .boot_params = 0x00000100,
diff --git a/arch/arm/mach-ixp4xx/coyote-setup.c b/arch/arm/mach-ixp4xx/coyote-setup.c
index 679594a73981..13f8a7ac3ba9 100644
--- a/arch/arm/mach-ixp4xx/coyote-setup.c
+++ b/arch/arm/mach-ixp4xx/coyote-setup.c
@@ -101,7 +101,6 @@ static void __init coyote_init(void)
101#ifdef CONFIG_ARCH_ADI_COYOTE 101#ifdef CONFIG_ARCH_ADI_COYOTE
102MACHINE_START(ADI_COYOTE, "ADI Engineering Coyote") 102MACHINE_START(ADI_COYOTE, "ADI Engineering Coyote")
103 /* Maintainer: MontaVista Software, Inc. */ 103 /* Maintainer: MontaVista Software, Inc. */
104 .phys_ram = PHYS_OFFSET,
105 .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, 104 .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
106 .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, 105 .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
107 .map_io = ixp4xx_map_io, 106 .map_io = ixp4xx_map_io,
@@ -119,7 +118,6 @@ MACHINE_END
119#ifdef CONFIG_MACH_IXDPG425 118#ifdef CONFIG_MACH_IXDPG425
120MACHINE_START(IXDPG425, "Intel IXDPG425") 119MACHINE_START(IXDPG425, "Intel IXDPG425")
121 /* Maintainer: MontaVista Software, Inc. */ 120 /* Maintainer: MontaVista Software, Inc. */
122 .phys_ram = PHYS_OFFSET,
123 .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, 121 .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
124 .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, 122 .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
125 .map_io = ixp4xx_map_io, 123 .map_io = ixp4xx_map_io,
diff --git a/arch/arm/mach-ixp4xx/gtwx5715-setup.c b/arch/arm/mach-ixp4xx/gtwx5715-setup.c
index 038670489970..654e2eed81fb 100644
--- a/arch/arm/mach-ixp4xx/gtwx5715-setup.c
+++ b/arch/arm/mach-ixp4xx/gtwx5715-setup.c
@@ -142,7 +142,6 @@ static void __init gtwx5715_init(void)
142 142
143MACHINE_START(GTWX5715, "Gemtek GTWX5715 (Linksys WRV54G)") 143MACHINE_START(GTWX5715, "Gemtek GTWX5715 (Linksys WRV54G)")
144 /* Maintainer: George Joseph */ 144 /* Maintainer: George Joseph */
145 .phys_ram = PHYS_OFFSET,
146 .phys_io = IXP4XX_UART2_BASE_PHYS, 145 .phys_io = IXP4XX_UART2_BASE_PHYS,
147 .io_pg_offst = ((IXP4XX_UART2_BASE_VIRT) >> 18) & 0xfffc, 146 .io_pg_offst = ((IXP4XX_UART2_BASE_VIRT) >> 18) & 0xfffc,
148 .map_io = ixp4xx_map_io, 147 .map_io = ixp4xx_map_io,
diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c
index c2e105c89c95..da72383ee301 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-setup.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c
@@ -121,7 +121,6 @@ static void __init ixdp425_init(void)
121#ifdef CONFIG_ARCH_IXDP425 121#ifdef CONFIG_ARCH_IXDP425
122MACHINE_START(IXDP425, "Intel IXDP425 Development Platform") 122MACHINE_START(IXDP425, "Intel IXDP425 Development Platform")
123 /* Maintainer: MontaVista Software, Inc. */ 123 /* Maintainer: MontaVista Software, Inc. */
124 .phys_ram = PHYS_OFFSET,
125 .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, 124 .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
126 .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, 125 .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
127 .map_io = ixp4xx_map_io, 126 .map_io = ixp4xx_map_io,
@@ -135,7 +134,6 @@ MACHINE_END
135#ifdef CONFIG_MACH_IXDP465 134#ifdef CONFIG_MACH_IXDP465
136MACHINE_START(IXDP465, "Intel IXDP465 Development Platform") 135MACHINE_START(IXDP465, "Intel IXDP465 Development Platform")
137 /* Maintainer: MontaVista Software, Inc. */ 136 /* Maintainer: MontaVista Software, Inc. */
138 .phys_ram = PHYS_OFFSET,
139 .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, 137 .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
140 .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, 138 .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
141 .map_io = ixp4xx_map_io, 139 .map_io = ixp4xx_map_io,
@@ -149,7 +147,6 @@ MACHINE_END
149#ifdef CONFIG_ARCH_PRPMC1100 147#ifdef CONFIG_ARCH_PRPMC1100
150MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform") 148MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform")
151 /* Maintainer: MontaVista Software, Inc. */ 149 /* Maintainer: MontaVista Software, Inc. */
152 .phys_ram = PHYS_OFFSET,
153 .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, 150 .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
154 .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, 151 .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
155 .map_io = ixp4xx_map_io, 152 .map_io = ixp4xx_map_io,
@@ -169,7 +166,6 @@ MACHINE_END
169#ifdef CONFIG_ARCH_AVILA 166#ifdef CONFIG_ARCH_AVILA
170MACHINE_START(AVILA, "Gateworks Avila Network Platform") 167MACHINE_START(AVILA, "Gateworks Avila Network Platform")
171 /* Maintainer: Deepak Saxena <dsaxena@plexity.net> */ 168 /* Maintainer: Deepak Saxena <dsaxena@plexity.net> */
172 .phys_ram = PHYS_OFFSET,
173 .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, 169 .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
174 .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, 170 .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
175 .map_io = ixp4xx_map_io, 171 .map_io = ixp4xx_map_io,
diff --git a/arch/arm/mach-ixp4xx/nas100d-setup.c b/arch/arm/mach-ixp4xx/nas100d-setup.c
index 49998a8bd4e8..856d56f3b2ae 100644
--- a/arch/arm/mach-ixp4xx/nas100d-setup.c
+++ b/arch/arm/mach-ixp4xx/nas100d-setup.c
@@ -124,7 +124,6 @@ static void __init nas100d_init(void)
124 124
125MACHINE_START(NAS100D, "Iomega NAS 100d") 125MACHINE_START(NAS100D, "Iomega NAS 100d")
126 /* Maintainer: www.nslu2-linux.org */ 126 /* Maintainer: www.nslu2-linux.org */
127 .phys_ram = PHYS_OFFSET,
128 .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, 127 .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
129 .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC, 128 .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC,
130 .boot_params = 0x00000100, 129 .boot_params = 0x00000100,
diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c
index 289e94cb65c2..da9340a53434 100644
--- a/arch/arm/mach-ixp4xx/nslu2-setup.c
+++ b/arch/arm/mach-ixp4xx/nslu2-setup.c
@@ -123,7 +123,6 @@ static void __init nslu2_init(void)
123 123
124MACHINE_START(NSLU2, "Linksys NSLU2") 124MACHINE_START(NSLU2, "Linksys NSLU2")
125 /* Maintainer: www.nslu2-linux.org */ 125 /* Maintainer: www.nslu2-linux.org */
126 .phys_ram = PHYS_OFFSET,
127 .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, 126 .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
128 .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC, 127 .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC,
129 .boot_params = 0x00000100, 128 .boot_params = 0x00000100,
diff --git a/arch/arm/mach-l7200/core.c b/arch/arm/mach-l7200/core.c
index 03ed742ae2be..ac626436e96f 100644
--- a/arch/arm/mach-l7200/core.c
+++ b/arch/arm/mach-l7200/core.c
@@ -91,7 +91,6 @@ static void __init l7200_map_io(void)
91 91
92MACHINE_START(L7200, "LinkUp Systems L7200") 92MACHINE_START(L7200, "LinkUp Systems L7200")
93 /* Maintainer: Steve Hill / Scott McConnell */ 93 /* Maintainer: Steve Hill / Scott McConnell */
94 .phys_ram = 0xf0000000,
95 .phys_io = 0x80040000, 94 .phys_io = 0x80040000,
96 .io_pg_offst = ((0xd0000000) >> 18) & 0xfffc, 95 .io_pg_offst = ((0xd0000000) >> 18) & 0xfffc,
97 .map_io = l7200_map_io, 96 .map_io = l7200_map_io,
diff --git a/arch/arm/mach-lh7a40x/arch-kev7a400.c b/arch/arm/mach-lh7a40x/arch-kev7a400.c
index 19f2fa2244c4..2cccc27c62e4 100644
--- a/arch/arm/mach-lh7a40x/arch-kev7a400.c
+++ b/arch/arm/mach-lh7a40x/arch-kev7a400.c
@@ -112,7 +112,6 @@ void __init lh7a40x_init_board_irq (void)
112 112
113MACHINE_START (KEV7A400, "Sharp KEV7a400") 113MACHINE_START (KEV7A400, "Sharp KEV7a400")
114 /* Maintainer: Marc Singer */ 114 /* Maintainer: Marc Singer */
115 .phys_ram = 0xc0000000,
116 .phys_io = 0x80000000, 115 .phys_io = 0x80000000,
117 .io_pg_offst = ((io_p2v (0x80000000))>>18) & 0xfffc, 116 .io_pg_offst = ((io_p2v (0x80000000))>>18) & 0xfffc,
118 .boot_params = 0xc0000100, 117 .boot_params = 0xc0000100,
diff --git a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
index 4eb962fdb3a8..12e23277c5ea 100644
--- a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
+++ b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
@@ -317,7 +317,6 @@ lpd7a400_map_io(void)
317 317
318MACHINE_START (LPD7A400, "Logic Product Development LPD7A400-10") 318MACHINE_START (LPD7A400, "Logic Product Development LPD7A400-10")
319 /* Maintainer: Marc Singer */ 319 /* Maintainer: Marc Singer */
320 .phys_ram = 0xc0000000,
321 .phys_io = 0x80000000, 320 .phys_io = 0x80000000,
322 .io_pg_offst = ((io_p2v (0x80000000))>>18) & 0xfffc, 321 .io_pg_offst = ((io_p2v (0x80000000))>>18) & 0xfffc,
323 .boot_params = 0xc0000100, 322 .boot_params = 0xc0000100,
@@ -333,7 +332,6 @@ MACHINE_END
333 332
334MACHINE_START (LPD7A404, "Logic Product Development LPD7A404-10") 333MACHINE_START (LPD7A404, "Logic Product Development LPD7A404-10")
335 /* Maintainer: Marc Singer */ 334 /* Maintainer: Marc Singer */
336 .phys_ram = 0xc0000000,
337 .phys_io = 0x80000000, 335 .phys_io = 0x80000000,
338 .io_pg_offst = ((io_p2v (0x80000000))>>18) & 0xfffc, 336 .io_pg_offst = ((io_p2v (0x80000000))>>18) & 0xfffc,
339 .boot_params = 0xc0000100, 337 .boot_params = 0xc0000100,
diff --git a/arch/arm/mach-omap1/board-generic.c b/arch/arm/mach-omap1/board-generic.c
index 4b292e93fbe2..bdc20b51b076 100644
--- a/arch/arm/mach-omap1/board-generic.c
+++ b/arch/arm/mach-omap1/board-generic.c
@@ -109,7 +109,6 @@ static void __init omap_generic_map_io(void)
109 109
110MACHINE_START(OMAP_GENERIC, "Generic OMAP1510/1610/1710") 110MACHINE_START(OMAP_GENERIC, "Generic OMAP1510/1610/1710")
111 /* Maintainer: Tony Lindgren <tony@atomide.com> */ 111 /* Maintainer: Tony Lindgren <tony@atomide.com> */
112 .phys_ram = 0x10000000,
113 .phys_io = 0xfff00000, 112 .phys_io = 0xfff00000,
114 .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, 113 .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
115 .boot_params = 0x10000100, 114 .boot_params = 0x10000100,
diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c
index a07e2c9307fa..9533c36a92df 100644
--- a/arch/arm/mach-omap1/board-h2.c
+++ b/arch/arm/mach-omap1/board-h2.c
@@ -199,7 +199,6 @@ static void __init h2_map_io(void)
199 199
200MACHINE_START(OMAP_H2, "TI-H2") 200MACHINE_START(OMAP_H2, "TI-H2")
201 /* Maintainer: Imre Deak <imre.deak@nokia.com> */ 201 /* Maintainer: Imre Deak <imre.deak@nokia.com> */
202 .phys_ram = 0x10000000,
203 .phys_io = 0xfff00000, 202 .phys_io = 0xfff00000,
204 .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, 203 .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
205 .boot_params = 0x10000100, 204 .boot_params = 0x10000100,
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c
index 668e278433c2..d665efc1c344 100644
--- a/arch/arm/mach-omap1/board-h3.c
+++ b/arch/arm/mach-omap1/board-h3.c
@@ -215,7 +215,6 @@ static void __init h3_map_io(void)
215 215
216MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board") 216MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board")
217 /* Maintainer: Texas Instruments, Inc. */ 217 /* Maintainer: Texas Instruments, Inc. */
218 .phys_ram = 0x10000000,
219 .phys_io = 0xfff00000, 218 .phys_io = 0xfff00000,
220 .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, 219 .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
221 .boot_params = 0x10000100, 220 .boot_params = 0x10000100,
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c
index 95f1ff36cdcb..652f37c7f906 100644
--- a/arch/arm/mach-omap1/board-innovator.c
+++ b/arch/arm/mach-omap1/board-innovator.c
@@ -303,7 +303,6 @@ static void __init innovator_map_io(void)
303 303
304MACHINE_START(OMAP_INNOVATOR, "TI-Innovator") 304MACHINE_START(OMAP_INNOVATOR, "TI-Innovator")
305 /* Maintainer: MontaVista Software, Inc. */ 305 /* Maintainer: MontaVista Software, Inc. */
306 .phys_ram = 0x10000000,
307 .phys_io = 0xfff00000, 306 .phys_io = 0xfff00000,
308 .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, 307 .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
309 .boot_params = 0x10000100, 308 .boot_params = 0x10000100,
diff --git a/arch/arm/mach-omap1/board-netstar.c b/arch/arm/mach-omap1/board-netstar.c
index 0448fa7de8a4..58f783930d45 100644
--- a/arch/arm/mach-omap1/board-netstar.c
+++ b/arch/arm/mach-omap1/board-netstar.c
@@ -149,7 +149,6 @@ postcore_initcall(netstar_late_init);
149 149
150MACHINE_START(NETSTAR, "NetStar OMAP5910") 150MACHINE_START(NETSTAR, "NetStar OMAP5910")
151 /* Maintainer: Ladislav Michl <michl@2n.cz> */ 151 /* Maintainer: Ladislav Michl <michl@2n.cz> */
152 .phys_ram = 0x10000000,
153 .phys_io = 0xfff00000, 152 .phys_io = 0xfff00000,
154 .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, 153 .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
155 .boot_params = 0x10000100, 154 .boot_params = 0x10000100,
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
index e990e1bc1669..e5d126e8f276 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -274,7 +274,6 @@ static void __init osk_map_io(void)
274 274
275MACHINE_START(OMAP_OSK, "TI-OSK") 275MACHINE_START(OMAP_OSK, "TI-OSK")
276 /* Maintainer: Dirk Behme <dirk.behme@de.bosch.com> */ 276 /* Maintainer: Dirk Behme <dirk.behme@de.bosch.com> */
277 .phys_ram = 0x10000000,
278 .phys_io = 0xfff00000, 277 .phys_io = 0xfff00000,
279 .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, 278 .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
280 .boot_params = 0x10000100, 279 .boot_params = 0x10000100,
diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c
index 5c975eb5c34b..67fada207622 100644
--- a/arch/arm/mach-omap1/board-palmte.c
+++ b/arch/arm/mach-omap1/board-palmte.c
@@ -76,7 +76,6 @@ static void __init omap_generic_map_io(void)
76} 76}
77 77
78MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E") 78MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E")
79 .phys_ram = 0x10000000,
80 .phys_io = 0xfff00000, 79 .phys_io = 0xfff00000,
81 .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, 80 .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
82 .boot_params = 0x10000100, 81 .boot_params = 0x10000100,
diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c
index 92ff5dc07351..88708a0c52a2 100644
--- a/arch/arm/mach-omap1/board-perseus2.c
+++ b/arch/arm/mach-omap1/board-perseus2.c
@@ -199,7 +199,6 @@ static void __init omap_perseus2_map_io(void)
199 199
200MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2") 200MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2")
201 /* Maintainer: Kevin Hilman <kjh@hilman.org> */ 201 /* Maintainer: Kevin Hilman <kjh@hilman.org> */
202 .phys_ram = 0x10000000,
203 .phys_io = 0xfff00000, 202 .phys_io = 0xfff00000,
204 .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, 203 .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
205 .boot_params = 0x10000100, 204 .boot_params = 0x10000100,
diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c
index 6f9a6220e78a..959b4b847c87 100644
--- a/arch/arm/mach-omap1/board-voiceblue.c
+++ b/arch/arm/mach-omap1/board-voiceblue.c
@@ -281,7 +281,6 @@ EXPORT_SYMBOL(voiceblue_wdt_ping);
281 281
282MACHINE_START(VOICEBLUE, "VoiceBlue OMAP5910") 282MACHINE_START(VOICEBLUE, "VoiceBlue OMAP5910")
283 /* Maintainer: Ladislav Michl <michl@2n.cz> */ 283 /* Maintainer: Ladislav Michl <michl@2n.cz> */
284 .phys_ram = 0x10000000,
285 .phys_io = 0xfff00000, 284 .phys_io = 0xfff00000,
286 .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, 285 .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
287 .boot_params = 0x10000100, 286 .boot_params = 0x10000100,
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index c602e7a3d93e..b937123e5c65 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -69,7 +69,6 @@ static void __init omap_generic_map_io(void)
69 69
70MACHINE_START(OMAP_GENERIC, "Generic OMAP24xx") 70MACHINE_START(OMAP_GENERIC, "Generic OMAP24xx")
71 /* Maintainer: Paul Mundt <paul.mundt@nokia.com> */ 71 /* Maintainer: Paul Mundt <paul.mundt@nokia.com> */
72 .phys_ram = 0x80000000,
73 .phys_io = 0x48000000, 72 .phys_io = 0x48000000,
74 .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, 73 .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc,
75 .boot_params = 0x80000100, 74 .boot_params = 0x80000100,
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index f2554469a76a..c3c35d40378a 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -186,7 +186,6 @@ static void __init omap_h4_map_io(void)
186 186
187MACHINE_START(OMAP_H4, "OMAP2420 H4 board") 187MACHINE_START(OMAP_H4, "OMAP2420 H4 board")
188 /* Maintainer: Paul Mundt <paul.mundt@nokia.com> */ 188 /* Maintainer: Paul Mundt <paul.mundt@nokia.com> */
189 .phys_ram = 0x80000000,
190 .phys_io = 0x48000000, 189 .phys_io = 0x48000000,
191 .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, 190 .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc,
192 .boot_params = 0x80000100, 191 .boot_params = 0x80000100,
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index 5a7b873f29b3..7ffd2de8f2f3 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -342,7 +342,6 @@ static void __init fixup_corgi(struct machine_desc *desc,
342 342
343#ifdef CONFIG_MACH_CORGI 343#ifdef CONFIG_MACH_CORGI
344MACHINE_START(CORGI, "SHARP Corgi") 344MACHINE_START(CORGI, "SHARP Corgi")
345 .phys_ram = 0xa0000000,
346 .phys_io = 0x40000000, 345 .phys_io = 0x40000000,
347 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, 346 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
348 .fixup = fixup_corgi, 347 .fixup = fixup_corgi,
@@ -355,7 +354,6 @@ MACHINE_END
355 354
356#ifdef CONFIG_MACH_SHEPHERD 355#ifdef CONFIG_MACH_SHEPHERD
357MACHINE_START(SHEPHERD, "SHARP Shepherd") 356MACHINE_START(SHEPHERD, "SHARP Shepherd")
358 .phys_ram = 0xa0000000,
359 .phys_io = 0x40000000, 357 .phys_io = 0x40000000,
360 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, 358 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
361 .fixup = fixup_corgi, 359 .fixup = fixup_corgi,
@@ -368,7 +366,6 @@ MACHINE_END
368 366
369#ifdef CONFIG_MACH_HUSKY 367#ifdef CONFIG_MACH_HUSKY
370MACHINE_START(HUSKY, "SHARP Husky") 368MACHINE_START(HUSKY, "SHARP Husky")
371 .phys_ram = 0xa0000000,
372 .phys_io = 0x40000000, 369 .phys_io = 0x40000000,
373 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, 370 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
374 .fixup = fixup_corgi, 371 .fixup = fixup_corgi,
diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
index 7de159e2ab42..347b9dea24c6 100644
--- a/arch/arm/mach-pxa/idp.c
+++ b/arch/arm/mach-pxa/idp.c
@@ -183,7 +183,6 @@ static void __init idp_map_io(void)
183 183
184MACHINE_START(PXA_IDP, "Vibren PXA255 IDP") 184MACHINE_START(PXA_IDP, "Vibren PXA255 IDP")
185 /* Maintainer: Vibren Technologies */ 185 /* Maintainer: Vibren Technologies */
186 .phys_ram = 0xa0000000,
187 .phys_io = 0x40000000, 186 .phys_io = 0x40000000,
188 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, 187 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
189 .map_io = idp_map_io, 188 .map_io = idp_map_io,
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index b464bc88ff93..3e26d7ce5bb2 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -437,7 +437,6 @@ static void __init lubbock_map_io(void)
437 437
438MACHINE_START(LUBBOCK, "Intel DBPXA250 Development Platform (aka Lubbock)") 438MACHINE_START(LUBBOCK, "Intel DBPXA250 Development Platform (aka Lubbock)")
439 /* Maintainer: MontaVista Software Inc. */ 439 /* Maintainer: MontaVista Software Inc. */
440 .phys_ram = 0xa0000000,
441 .phys_io = 0x40000000, 440 .phys_io = 0x40000000,
442 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, 441 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
443 .map_io = lubbock_map_io, 442 .map_io = lubbock_map_io,
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index 8da9d3efe9a0..d5bda60209ec 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -489,7 +489,6 @@ static void __init mainstone_map_io(void)
489 489
490MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)") 490MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)")
491 /* Maintainer: MontaVista Software Inc. */ 491 /* Maintainer: MontaVista Software Inc. */
492 .phys_ram = 0xa0000000,
493 .phys_io = 0x40000000, 492 .phys_io = 0x40000000,
494 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, 493 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
495 .map_io = mainstone_map_io, 494 .map_io = mainstone_map_io,
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index 663c95005985..911e6ff5a9bd 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -311,7 +311,6 @@ static void __init fixup_poodle(struct machine_desc *desc,
311} 311}
312 312
313MACHINE_START(POODLE, "SHARP Poodle") 313MACHINE_START(POODLE, "SHARP Poodle")
314 .phys_ram = 0xa0000000,
315 .phys_io = 0x40000000, 314 .phys_io = 0x40000000,
316 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, 315 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
317 .fixup = fixup_poodle, 316 .fixup = fixup_poodle,
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index a9eacc06555f..c094d99ebf56 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -497,7 +497,6 @@ static void __init fixup_spitz(struct machine_desc *desc,
497 497
498#ifdef CONFIG_MACH_SPITZ 498#ifdef CONFIG_MACH_SPITZ
499MACHINE_START(SPITZ, "SHARP Spitz") 499MACHINE_START(SPITZ, "SHARP Spitz")
500 .phys_ram = 0xa0000000,
501 .phys_io = 0x40000000, 500 .phys_io = 0x40000000,
502 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, 501 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
503 .fixup = fixup_spitz, 502 .fixup = fixup_spitz,
@@ -510,7 +509,6 @@ MACHINE_END
510 509
511#ifdef CONFIG_MACH_BORZOI 510#ifdef CONFIG_MACH_BORZOI
512MACHINE_START(BORZOI, "SHARP Borzoi") 511MACHINE_START(BORZOI, "SHARP Borzoi")
513 .phys_ram = 0xa0000000,
514 .phys_io = 0x40000000, 512 .phys_io = 0x40000000,
515 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, 513 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
516 .fixup = fixup_spitz, 514 .fixup = fixup_spitz,
@@ -523,7 +521,6 @@ MACHINE_END
523 521
524#ifdef CONFIG_MACH_AKITA 522#ifdef CONFIG_MACH_AKITA
525MACHINE_START(AKITA, "SHARP Akita") 523MACHINE_START(AKITA, "SHARP Akita")
526 .phys_ram = 0xa0000000,
527 .phys_io = 0x40000000, 524 .phys_io = 0x40000000,
528 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, 525 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
529 .fixup = fixup_spitz, 526 .fixup = fixup_spitz,
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index e4f92efc616e..d168286ed470 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -295,7 +295,6 @@ static void __init fixup_tosa(struct machine_desc *desc,
295} 295}
296 296
297MACHINE_START(TOSA, "SHARP Tosa") 297MACHINE_START(TOSA, "SHARP Tosa")
298 .phys_ram = 0xa0000000,
299 .phys_io = 0x40000000, 298 .phys_io = 0x40000000,
300 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, 299 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
301 .fixup = fixup_tosa, 300 .fixup = fixup_tosa,
diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig
index 129976866d47..17f5f4439fe7 100644
--- a/arch/arm/mach-realview/Kconfig
+++ b/arch/arm/mach-realview/Kconfig
@@ -3,7 +3,6 @@ menu "RealView platform type"
3 3
4config MACH_REALVIEW_EB 4config MACH_REALVIEW_EB
5 bool "Support RealView/EB platform" 5 bool "Support RealView/EB platform"
6 default n
7 select ARM_GIC 6 select ARM_GIC
8 help 7 help
9 Include support for the ARM(R) RealView Emulation Baseboard platform. 8 Include support for the ARM(R) RealView Emulation Baseboard platform.
diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
index 112f7592aca9..d4a586e38d5b 100644
--- a/arch/arm/mach-realview/realview_eb.c
+++ b/arch/arm/mach-realview/realview_eb.c
@@ -166,7 +166,6 @@ static void __init realview_eb_init(void)
166 166
167MACHINE_START(REALVIEW_EB, "ARM-RealView EB") 167MACHINE_START(REALVIEW_EB, "ARM-RealView EB")
168 /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ 168 /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
169 .phys_ram = 0x00000000,
170 .phys_io = REALVIEW_UART0_BASE, 169 .phys_io = REALVIEW_UART0_BASE,
171 .io_pg_offst = (IO_ADDRESS(REALVIEW_UART0_BASE) >> 18) & 0xfffc, 170 .io_pg_offst = (IO_ADDRESS(REALVIEW_UART0_BASE) >> 18) & 0xfffc,
172 .boot_params = 0x00000100, 171 .boot_params = 0x00000100,
diff --git a/arch/arm/mach-rpc/riscpc.c b/arch/arm/mach-rpc/riscpc.c
index 5c4ac1c008a6..208a2b5dba1b 100644
--- a/arch/arm/mach-rpc/riscpc.c
+++ b/arch/arm/mach-rpc/riscpc.c
@@ -177,7 +177,6 @@ extern struct sys_timer ioc_timer;
177 177
178MACHINE_START(RISCPC, "Acorn-RiscPC") 178MACHINE_START(RISCPC, "Acorn-RiscPC")
179 /* Maintainer: Russell King */ 179 /* Maintainer: Russell King */
180 .phys_ram = 0x10000000,
181 .phys_io = 0x03000000, 180 .phys_io = 0x03000000,
182 .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc, 181 .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc,
183 .boot_params = 0x10000100, 182 .boot_params = 0x10000100,
diff --git a/arch/arm/mach-s3c2410/mach-anubis.c b/arch/arm/mach-s3c2410/mach-anubis.c
index 0f81fc0c2f7f..3e327b8e46be 100644
--- a/arch/arm/mach-s3c2410/mach-anubis.c
+++ b/arch/arm/mach-s3c2410/mach-anubis.c
@@ -294,7 +294,6 @@ static void __init anubis_map_io(void)
294 294
295MACHINE_START(ANUBIS, "Simtec-Anubis") 295MACHINE_START(ANUBIS, "Simtec-Anubis")
296 /* Maintainer: Ben Dooks <ben@simtec.co.uk> */ 296 /* Maintainer: Ben Dooks <ben@simtec.co.uk> */
297 .phys_ram = S3C2410_SDRAM_PA,
298 .phys_io = S3C2410_PA_UART, 297 .phys_io = S3C2410_PA_UART,
299 .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, 298 .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
300 .boot_params = S3C2410_SDRAM_PA + 0x100, 299 .boot_params = S3C2410_SDRAM_PA + 0x100,
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index 4d962717fdf7..995bb8add331 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -527,7 +527,6 @@ static void __init bast_init(void)
527 527
528MACHINE_START(BAST, "Simtec-BAST") 528MACHINE_START(BAST, "Simtec-BAST")
529 /* Maintainer: Ben Dooks <ben@simtec.co.uk> */ 529 /* Maintainer: Ben Dooks <ben@simtec.co.uk> */
530 .phys_ram = S3C2410_SDRAM_PA,
531 .phys_io = S3C2410_PA_UART, 530 .phys_io = S3C2410_PA_UART,
532 .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, 531 .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
533 .boot_params = S3C2410_SDRAM_PA + 0x100, 532 .boot_params = S3C2410_SDRAM_PA + 0x100,
diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
index 0aa8760598f7..1c316f14ed94 100644
--- a/arch/arm/mach-s3c2410/mach-h1940.c
+++ b/arch/arm/mach-s3c2410/mach-h1940.c
@@ -171,7 +171,6 @@ static void __init h1940_init(void)
171 171
172MACHINE_START(H1940, "IPAQ-H1940") 172MACHINE_START(H1940, "IPAQ-H1940")
173 /* Maintainer: Ben Dooks <ben@fluff.org> */ 173 /* Maintainer: Ben Dooks <ben@fluff.org> */
174 .phys_ram = S3C2410_SDRAM_PA,
175 .phys_io = S3C2410_PA_UART, 174 .phys_io = S3C2410_PA_UART,
176 .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, 175 .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
177 .boot_params = S3C2410_SDRAM_PA + 0x100, 176 .boot_params = S3C2410_SDRAM_PA + 0x100,
diff --git a/arch/arm/mach-s3c2410/mach-n30.c b/arch/arm/mach-s3c2410/mach-n30.c
index 378d640ab00b..116ac3169966 100644
--- a/arch/arm/mach-s3c2410/mach-n30.c
+++ b/arch/arm/mach-s3c2410/mach-n30.c
@@ -128,7 +128,6 @@ MACHINE_START(N30, "Acer-N30")
128 /* Maintainer: Christer Weinigel <christer@weinigel.se>, 128 /* Maintainer: Christer Weinigel <christer@weinigel.se>,
129 Ben Dooks <ben-linux@fluff.org> 129 Ben Dooks <ben-linux@fluff.org>
130 */ 130 */
131 .phys_ram = S3C2410_SDRAM_PA,
132 .phys_io = S3C2410_PA_UART, 131 .phys_io = S3C2410_PA_UART,
133 .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, 132 .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
134 .boot_params = S3C2410_SDRAM_PA + 0x100, 133 .boot_params = S3C2410_SDRAM_PA + 0x100,
diff --git a/arch/arm/mach-s3c2410/mach-nexcoder.c b/arch/arm/mach-s3c2410/mach-nexcoder.c
index 42b0eeff2e0f..07d09509a626 100644
--- a/arch/arm/mach-s3c2410/mach-nexcoder.c
+++ b/arch/arm/mach-s3c2410/mach-nexcoder.c
@@ -148,7 +148,6 @@ static void __init nexcoder_map_io(void)
148 148
149MACHINE_START(NEXCODER_2440, "NexVision - Nexcoder 2440") 149MACHINE_START(NEXCODER_2440, "NexVision - Nexcoder 2440")
150 /* Maintainer: Guillaume GOURAT <guillaume.gourat@nexvision.tv> */ 150 /* Maintainer: Guillaume GOURAT <guillaume.gourat@nexvision.tv> */
151 .phys_ram = S3C2410_SDRAM_PA,
152 .phys_io = S3C2410_PA_UART, 151 .phys_io = S3C2410_PA_UART,
153 .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, 152 .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
154 .boot_params = S3C2410_SDRAM_PA + 0x100, 153 .boot_params = S3C2410_SDRAM_PA + 0x100,
diff --git a/arch/arm/mach-s3c2410/mach-otom.c b/arch/arm/mach-s3c2410/mach-otom.c
index a2eb9ed48fcd..b39daedf93ca 100644
--- a/arch/arm/mach-s3c2410/mach-otom.c
+++ b/arch/arm/mach-s3c2410/mach-otom.c
@@ -116,7 +116,6 @@ static void __init otom11_map_io(void)
116 116
117MACHINE_START(OTOM, "Nex Vision - Otom 1.1") 117MACHINE_START(OTOM, "Nex Vision - Otom 1.1")
118 /* Maintainer: Guillaume GOURAT <guillaume.gourat@nexvision.tv> */ 118 /* Maintainer: Guillaume GOURAT <guillaume.gourat@nexvision.tv> */
119 .phys_ram = S3C2410_SDRAM_PA,
120 .phys_io = S3C2410_PA_UART, 119 .phys_io = S3C2410_PA_UART,
121 .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, 120 .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
122 .boot_params = S3C2410_SDRAM_PA + 0x100, 121 .boot_params = S3C2410_SDRAM_PA + 0x100,
diff --git a/arch/arm/mach-s3c2410/mach-rx3715.c b/arch/arm/mach-s3c2410/mach-rx3715.c
index f8d86d1e16b6..0260ed5ab946 100644
--- a/arch/arm/mach-s3c2410/mach-rx3715.c
+++ b/arch/arm/mach-s3c2410/mach-rx3715.c
@@ -205,7 +205,6 @@ static void __init rx3715_init_machine(void)
205 205
206MACHINE_START(RX3715, "IPAQ-RX3715") 206MACHINE_START(RX3715, "IPAQ-RX3715")
207 /* Maintainer: Ben Dooks <ben@fluff.org> */ 207 /* Maintainer: Ben Dooks <ben@fluff.org> */
208 .phys_ram = S3C2410_SDRAM_PA,
209 .phys_io = S3C2410_PA_UART, 208 .phys_io = S3C2410_PA_UART,
210 .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, 209 .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
211 .boot_params = S3C2410_SDRAM_PA + 0x100, 210 .boot_params = S3C2410_SDRAM_PA + 0x100,
diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c
index 2c91965ee1c8..1e76e1fdfcea 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2410.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2410.c
@@ -115,7 +115,6 @@ static void __init smdk2410_init_irq(void)
115MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch 115MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch
116 * to SMDK2410 */ 116 * to SMDK2410 */
117 /* Maintainer: Jonas Dietsche */ 117 /* Maintainer: Jonas Dietsche */
118 .phys_ram = S3C2410_SDRAM_PA,
119 .phys_io = S3C2410_PA_UART, 118 .phys_io = S3C2410_PA_UART,
120 .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, 119 .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
121 .boot_params = S3C2410_SDRAM_PA + 0x100, 120 .boot_params = S3C2410_SDRAM_PA + 0x100,
diff --git a/arch/arm/mach-s3c2410/mach-smdk2440.c b/arch/arm/mach-s3c2410/mach-smdk2440.c
index 4e31118533e6..f4315721c3b8 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2440.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2440.c
@@ -216,7 +216,6 @@ static void __init smdk2440_machine_init(void)
216 216
217MACHINE_START(S3C2440, "SMDK2440") 217MACHINE_START(S3C2440, "SMDK2440")
218 /* Maintainer: Ben Dooks <ben@fluff.org> */ 218 /* Maintainer: Ben Dooks <ben@fluff.org> */
219 .phys_ram = S3C2410_SDRAM_PA,
220 .phys_io = S3C2410_PA_UART, 219 .phys_io = S3C2410_PA_UART,
221 .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, 220 .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
222 .boot_params = S3C2410_SDRAM_PA + 0x100, 221 .boot_params = S3C2410_SDRAM_PA + 0x100,
diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c
index ae7e099bf6c8..785fc9cdcf7c 100644
--- a/arch/arm/mach-s3c2410/mach-vr1000.c
+++ b/arch/arm/mach-s3c2410/mach-vr1000.c
@@ -395,7 +395,6 @@ static void __init vr1000_map_io(void)
395 395
396MACHINE_START(VR1000, "Thorcom-VR1000") 396MACHINE_START(VR1000, "Thorcom-VR1000")
397 /* Maintainer: Ben Dooks <ben@simtec.co.uk> */ 397 /* Maintainer: Ben Dooks <ben@simtec.co.uk> */
398 .phys_ram = S3C2410_SDRAM_PA,
399 .phys_io = S3C2410_PA_UART, 398 .phys_io = S3C2410_PA_UART,
400 .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, 399 .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
401 .boot_params = S3C2410_SDRAM_PA + 0x100, 400 .boot_params = S3C2410_SDRAM_PA + 0x100,
diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c
index a66ac61233a2..a599bb0d4ab8 100644
--- a/arch/arm/mach-sa1100/assabet.c
+++ b/arch/arm/mach-sa1100/assabet.c
@@ -447,7 +447,6 @@ static void __init assabet_map_io(void)
447 447
448 448
449MACHINE_START(ASSABET, "Intel-Assabet") 449MACHINE_START(ASSABET, "Intel-Assabet")
450 .phys_ram = 0xc0000000,
451 .phys_io = 0x80000000, 450 .phys_io = 0x80000000,
452 .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, 451 .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
453 .boot_params = 0xc0000100, 452 .boot_params = 0xc0000100,
diff --git a/arch/arm/mach-sa1100/badge4.c b/arch/arm/mach-sa1100/badge4.c
index edccd5eb06be..f60b7a66dfa0 100644
--- a/arch/arm/mach-sa1100/badge4.c
+++ b/arch/arm/mach-sa1100/badge4.c
@@ -297,7 +297,6 @@ static void __init badge4_map_io(void)
297} 297}
298 298
299MACHINE_START(BADGE4, "Hewlett-Packard Laboratories BadgePAD 4") 299MACHINE_START(BADGE4, "Hewlett-Packard Laboratories BadgePAD 4")
300 .phys_ram = 0xc0000000,
301 .phys_io = 0x80000000, 300 .phys_io = 0x80000000,
302 .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, 301 .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
303 .boot_params = 0xc0000100, 302 .boot_params = 0xc0000100,
diff --git a/arch/arm/mach-sa1100/cerf.c b/arch/arm/mach-sa1100/cerf.c
index 508593722bc7..8269a9ef9afe 100644
--- a/arch/arm/mach-sa1100/cerf.c
+++ b/arch/arm/mach-sa1100/cerf.c
@@ -135,7 +135,6 @@ static void __init cerf_init(void)
135 135
136MACHINE_START(CERF, "Intrinsyc CerfBoard/CerfCube") 136MACHINE_START(CERF, "Intrinsyc CerfBoard/CerfCube")
137 /* Maintainer: support@intrinsyc.com */ 137 /* Maintainer: support@intrinsyc.com */
138 .phys_ram = 0xc0000000,
139 .phys_io = 0x80000000, 138 .phys_io = 0x80000000,
140 .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, 139 .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
141 .map_io = cerf_map_io, 140 .map_io = cerf_map_io,
diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c
index 522abc036d3a..6888816a1935 100644
--- a/arch/arm/mach-sa1100/collie.c
+++ b/arch/arm/mach-sa1100/collie.c
@@ -191,7 +191,6 @@ static void __init collie_map_io(void)
191} 191}
192 192
193MACHINE_START(COLLIE, "Sharp-Collie") 193MACHINE_START(COLLIE, "Sharp-Collie")
194 .phys_ram = 0xc0000000,
195 .phys_io = 0x80000000, 194 .phys_io = 0x80000000,
196 .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, 195 .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
197 .map_io = collie_map_io, 196 .map_io = collie_map_io,
diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c
index e8352b7f74b0..b04d92271020 100644
--- a/arch/arm/mach-sa1100/h3600.c
+++ b/arch/arm/mach-sa1100/h3600.c
@@ -392,7 +392,6 @@ static void __init h3100_map_io(void)
392} 392}
393 393
394MACHINE_START(H3100, "Compaq iPAQ H3100") 394MACHINE_START(H3100, "Compaq iPAQ H3100")
395 .phys_ram = 0xc0000000,
396 .phys_io = 0x80000000, 395 .phys_io = 0x80000000,
397 .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, 396 .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
398 .boot_params = 0xc0000100, 397 .boot_params = 0xc0000100,
@@ -510,7 +509,6 @@ static void __init h3600_map_io(void)
510} 509}
511 510
512MACHINE_START(H3600, "Compaq iPAQ H3600") 511MACHINE_START(H3600, "Compaq iPAQ H3600")
513 .phys_ram = 0xc0000000,
514 .phys_io = 0x80000000, 512 .phys_io = 0x80000000,
515 .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, 513 .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
516 .boot_params = 0xc0000100, 514 .boot_params = 0xc0000100,
@@ -897,7 +895,6 @@ static void __init h3800_map_io(void)
897} 895}
898 896
899MACHINE_START(H3800, "Compaq iPAQ H3800") 897MACHINE_START(H3800, "Compaq iPAQ H3800")
900 .phys_ram = 0xc0000000,
901 .phys_io = 0x80000000, 898 .phys_io = 0x80000000,
902 .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, 899 .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
903 .boot_params = 0xc0000100, 900 .boot_params = 0xc0000100,
diff --git a/arch/arm/mach-sa1100/hackkit.c b/arch/arm/mach-sa1100/hackkit.c
index c922e043c424..046b213efd5b 100644
--- a/arch/arm/mach-sa1100/hackkit.c
+++ b/arch/arm/mach-sa1100/hackkit.c
@@ -195,7 +195,6 @@ static void __init hackkit_init(void)
195 */ 195 */
196 196
197MACHINE_START(HACKKIT, "HackKit Cpu Board") 197MACHINE_START(HACKKIT, "HackKit Cpu Board")
198 .phys_ram = 0xc0000000,
199 .phys_io = 0x80000000, 198 .phys_io = 0x80000000,
200 .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, 199 .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
201 .boot_params = 0xc0000100, 200 .boot_params = 0xc0000100,
diff --git a/arch/arm/mach-sa1100/jornada720.c b/arch/arm/mach-sa1100/jornada720.c
index 2f671cc3cb99..17f5a43acdb7 100644
--- a/arch/arm/mach-sa1100/jornada720.c
+++ b/arch/arm/mach-sa1100/jornada720.c
@@ -173,7 +173,6 @@ static void __init jornada720_mach_init(void)
173 173
174MACHINE_START(JORNADA720, "HP Jornada 720") 174MACHINE_START(JORNADA720, "HP Jornada 720")
175 /* Maintainer: Michael Gernoth <michael@gernoth.net> */ 175 /* Maintainer: Michael Gernoth <michael@gernoth.net> */
176 .phys_ram = 0xc0000000,
177 .phys_io = 0x80000000, 176 .phys_io = 0x80000000,
178 .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, 177 .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
179 .boot_params = 0xc0000100, 178 .boot_params = 0xc0000100,
diff --git a/arch/arm/mach-sa1100/lart.c b/arch/arm/mach-sa1100/lart.c
index 8c9e3dd52942..07d3a696ae7f 100644
--- a/arch/arm/mach-sa1100/lart.c
+++ b/arch/arm/mach-sa1100/lart.c
@@ -60,7 +60,6 @@ static void __init lart_map_io(void)
60} 60}
61 61
62MACHINE_START(LART, "LART") 62MACHINE_START(LART, "LART")
63 .phys_ram = 0xc0000000,
64 .phys_io = 0x80000000, 63 .phys_io = 0x80000000,
65 .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, 64 .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
66 .boot_params = 0xc0000100, 65 .boot_params = 0xc0000100,
diff --git a/arch/arm/mach-sa1100/pleb.c b/arch/arm/mach-sa1100/pleb.c
index 58c18f9e9b7b..0709ebab531c 100644
--- a/arch/arm/mach-sa1100/pleb.c
+++ b/arch/arm/mach-sa1100/pleb.c
@@ -146,7 +146,6 @@ static void __init pleb_map_io(void)
146} 146}
147 147
148MACHINE_START(PLEB, "PLEB") 148MACHINE_START(PLEB, "PLEB")
149 .phys_ram = 0xc0000000,
150 .phys_io = 0x80000000, 149 .phys_io = 0x80000000,
151 .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, 150 .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
152 .map_io = pleb_map_io, 151 .map_io = pleb_map_io,
diff --git a/arch/arm/mach-sa1100/shannon.c b/arch/arm/mach-sa1100/shannon.c
index 7482288278d9..5aafe0b56992 100644
--- a/arch/arm/mach-sa1100/shannon.c
+++ b/arch/arm/mach-sa1100/shannon.c
@@ -83,7 +83,6 @@ static void __init shannon_map_io(void)
83} 83}
84 84
85MACHINE_START(SHANNON, "Shannon (AKA: Tuxscreen)") 85MACHINE_START(SHANNON, "Shannon (AKA: Tuxscreen)")
86 .phys_ram = 0xc0000000,
87 .phys_io = 0x80000000, 86 .phys_io = 0x80000000,
88 .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, 87 .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
89 .boot_params = 0xc0000100, 88 .boot_params = 0xc0000100,
diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c
index 439ddc9b06d6..d2c23b2c34d1 100644
--- a/arch/arm/mach-sa1100/simpad.c
+++ b/arch/arm/mach-sa1100/simpad.c
@@ -229,7 +229,6 @@ arch_initcall(simpad_init);
229 229
230MACHINE_START(SIMPAD, "Simpad") 230MACHINE_START(SIMPAD, "Simpad")
231 /* Maintainer: Holger Freyther */ 231 /* Maintainer: Holger Freyther */
232 .phys_ram = 0xc0000000,
233 .phys_io = 0x80000000, 232 .phys_io = 0x80000000,
234 .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, 233 .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
235 .boot_params = 0xc0000100, 234 .boot_params = 0xc0000100,
diff --git a/arch/arm/mach-shark/core.c b/arch/arm/mach-shark/core.c
index 2d428b6dbb58..877600e212dd 100644
--- a/arch/arm/mach-shark/core.c
+++ b/arch/arm/mach-shark/core.c
@@ -111,7 +111,6 @@ static struct sys_timer shark_timer = {
111 111
112MACHINE_START(SHARK, "Shark") 112MACHINE_START(SHARK, "Shark")
113 /* Maintainer: Alexander Schulz */ 113 /* Maintainer: Alexander Schulz */
114 .phys_ram = 0x08000000,
115 .phys_io = 0x40000000, 114 .phys_io = 0x40000000,
116 .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc, 115 .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc,
117 .boot_params = 0x08003000, 116 .boot_params = 0x08003000,
diff --git a/arch/arm/mach-versatile/Kconfig b/arch/arm/mach-versatile/Kconfig
index 8d787f4c78e6..95096afd5271 100644
--- a/arch/arm/mach-versatile/Kconfig
+++ b/arch/arm/mach-versatile/Kconfig
@@ -9,7 +9,6 @@ config ARCH_VERSATILE_PB
9 9
10config MACH_VERSATILE_AB 10config MACH_VERSATILE_AB
11 bool "Support Versatile/AB platform" 11 bool "Support Versatile/AB platform"
12 default n
13 help 12 help
14 Include support for the ARM(R) Versatile/AP platform. 13 Include support for the ARM(R) Versatile/AP platform.
15 14
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index 90023745b23a..9ebbe808b41d 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -35,6 +35,7 @@
35#include <asm/leds.h> 35#include <asm/leds.h>
36#include <asm/hardware/arm_timer.h> 36#include <asm/hardware/arm_timer.h>
37#include <asm/hardware/icst307.h> 37#include <asm/hardware/icst307.h>
38#include <asm/hardware/vic.h>
38 39
39#include <asm/mach/arch.h> 40#include <asm/mach/arch.h>
40#include <asm/mach/flash.h> 41#include <asm/mach/flash.h>
@@ -56,24 +57,6 @@
56#define VA_VIC_BASE __io_address(VERSATILE_VIC_BASE) 57#define VA_VIC_BASE __io_address(VERSATILE_VIC_BASE)
57#define VA_SIC_BASE __io_address(VERSATILE_SIC_BASE) 58#define VA_SIC_BASE __io_address(VERSATILE_SIC_BASE)
58 59
59static void vic_mask_irq(unsigned int irq)
60{
61 irq -= IRQ_VIC_START;
62 writel(1 << irq, VA_VIC_BASE + VIC_IRQ_ENABLE_CLEAR);
63}
64
65static void vic_unmask_irq(unsigned int irq)
66{
67 irq -= IRQ_VIC_START;
68 writel(1 << irq, VA_VIC_BASE + VIC_IRQ_ENABLE);
69}
70
71static struct irqchip vic_chip = {
72 .ack = vic_mask_irq,
73 .mask = vic_mask_irq,
74 .unmask = vic_unmask_irq,
75};
76
77static void sic_mask_irq(unsigned int irq) 60static void sic_mask_irq(unsigned int irq)
78{ 61{
79 irq -= IRQ_SIC_START; 62 irq -= IRQ_SIC_START;
@@ -127,43 +110,12 @@ sic_handle_irq(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
127 110
128void __init versatile_init_irq(void) 111void __init versatile_init_irq(void)
129{ 112{
130 unsigned int i, value; 113 unsigned int i;
131
132 /* Disable all interrupts initially. */
133 114
134 writel(0, VA_VIC_BASE + VIC_INT_SELECT); 115 vic_init(VA_VIC_BASE, ~(1 << 31));
135 writel(0, VA_VIC_BASE + VIC_IRQ_ENABLE);
136 writel(~0, VA_VIC_BASE + VIC_IRQ_ENABLE_CLEAR);
137 writel(0, VA_VIC_BASE + VIC_IRQ_STATUS);
138 writel(0, VA_VIC_BASE + VIC_ITCR);
139 writel(~0, VA_VIC_BASE + VIC_IRQ_SOFT_CLEAR);
140
141 /*
142 * Make sure we clear all existing interrupts
143 */
144 writel(0, VA_VIC_BASE + VIC_VECT_ADDR);
145 for (i = 0; i < 19; i++) {
146 value = readl(VA_VIC_BASE + VIC_VECT_ADDR);
147 writel(value, VA_VIC_BASE + VIC_VECT_ADDR);
148 }
149
150 for (i = 0; i < 16; i++) {
151 value = readl(VA_VIC_BASE + VIC_VECT_CNTL0 + (i * 4));
152 writel(value | VICVectCntl_Enable | i, VA_VIC_BASE + VIC_VECT_CNTL0 + (i * 4));
153 }
154
155 writel(32, VA_VIC_BASE + VIC_DEF_VECT_ADDR);
156
157 for (i = IRQ_VIC_START; i <= IRQ_VIC_END; i++) {
158 if (i != IRQ_VICSOURCE31) {
159 set_irq_chip(i, &vic_chip);
160 set_irq_handler(i, do_level_IRQ);
161 set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
162 }
163 }
164 116
165 set_irq_handler(IRQ_VICSOURCE31, sic_handle_irq); 117 set_irq_handler(IRQ_VICSOURCE31, sic_handle_irq);
166 vic_unmask_irq(IRQ_VICSOURCE31); 118 enable_irq(IRQ_VICSOURCE31);
167 119
168 /* Do second interrupt controller */ 120 /* Do second interrupt controller */
169 writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR); 121 writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR);
@@ -877,7 +829,7 @@ static unsigned long versatile_gettimeoffset(void)
877 ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff; 829 ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
878 do { 830 do {
879 ticks1 = ticks2; 831 ticks1 = ticks2;
880 status = __raw_readl(VA_IC_BASE + VIC_IRQ_RAW_STATUS); 832 status = __raw_readl(VA_IC_BASE + VIC_RAW_STATUS);
881 ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff; 833 ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
882 } while (ticks2 > ticks1); 834 } while (ticks2 > ticks1);
883 835
diff --git a/arch/arm/mach-versatile/versatile_ab.c b/arch/arm/mach-versatile/versatile_ab.c
index e74c8a2fbb95..1eb596782078 100644
--- a/arch/arm/mach-versatile/versatile_ab.c
+++ b/arch/arm/mach-versatile/versatile_ab.c
@@ -36,7 +36,6 @@
36 36
37MACHINE_START(VERSATILE_AB, "ARM-Versatile AB") 37MACHINE_START(VERSATILE_AB, "ARM-Versatile AB")
38 /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ 38 /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
39 .phys_ram = 0x00000000,
40 .phys_io = 0x101f1000, 39 .phys_io = 0x101f1000,
41 .io_pg_offst = ((0xf11f1000) >> 18) & 0xfffc, 40 .io_pg_offst = ((0xf11f1000) >> 18) & 0xfffc,
42 .boot_params = 0x00000100, 41 .boot_params = 0x00000100,
diff --git a/arch/arm/mach-versatile/versatile_pb.c b/arch/arm/mach-versatile/versatile_pb.c
index 22d5ca07f75d..f17ab4fb548a 100644
--- a/arch/arm/mach-versatile/versatile_pb.c
+++ b/arch/arm/mach-versatile/versatile_pb.c
@@ -100,7 +100,6 @@ arch_initcall(versatile_pb_init);
100 100
101MACHINE_START(VERSATILE_PB, "ARM-Versatile PB") 101MACHINE_START(VERSATILE_PB, "ARM-Versatile PB")
102 /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ 102 /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
103 .phys_ram = 0x00000000,
104 .phys_io = 0x101f1000, 103 .phys_io = 0x101f1000,
105 .io_pg_offst = ((0xf11f1000) >> 18) & 0xfffc, 104 .io_pg_offst = ((0xf11f1000) >> 18) & 0xfffc,
106 .boot_params = 0x00000100, 105 .boot_params = 0x00000100,
diff --git a/arch/arm/nwfpe/fpa11.h b/arch/arm/nwfpe/fpa11.h
index da4c616b6c49..28cd79a451d3 100644
--- a/arch/arm/nwfpe/fpa11.h
+++ b/arch/arm/nwfpe/fpa11.h
@@ -62,7 +62,7 @@ typedef union tagFPREG {
62#else 62#else
63 u32 padding[3]; 63 u32 padding[3];
64#endif 64#endif
65} FPREG; 65} __attribute__ ((packed,aligned(4))) FPREG;
66 66
67/* 67/*
68 * FPA11 device model. 68 * FPA11 device model.
@@ -89,7 +89,7 @@ typedef struct tagFPA11 {
89 so we can use it to detect whether this 89 so we can use it to detect whether this
90 instance of the emulator needs to be 90 instance of the emulator needs to be
91 initialised. */ 91 initialised. */
92} FPA11; 92} __attribute__ ((packed,aligned(4))) FPA11;
93 93
94extern int8 SetRoundingMode(const unsigned int); 94extern int8 SetRoundingMode(const unsigned int);
95extern int8 SetRoundingPrecision(const unsigned int); 95extern int8 SetRoundingPrecision(const unsigned int);
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index 9693e9b4ffd1..0887bb2a2551 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -22,7 +22,6 @@ comment "OMAP Feature Selections"
22config OMAP_RESET_CLOCKS 22config OMAP_RESET_CLOCKS
23 bool "Reset unused clocks during boot" 23 bool "Reset unused clocks during boot"
24 depends on ARCH_OMAP 24 depends on ARCH_OMAP
25 default n
26 help 25 help
27 Say Y if you want to reset unused clocks during boot. 26 Say Y if you want to reset unused clocks during boot.
28 This option saves power, but assumes all drivers are 27 This option saves power, but assumes all drivers are
@@ -44,7 +43,6 @@ config OMAP_MUX
44config OMAP_MUX_DEBUG 43config OMAP_MUX_DEBUG
45 bool "Multiplexing debug output" 44 bool "Multiplexing debug output"
46 depends on OMAP_MUX 45 depends on OMAP_MUX
47 default n
48 help 46 help
49 Makes the multiplexing functions print out a lot of debug info. 47 Makes the multiplexing functions print out a lot of debug info.
50 This is useful if you want to find out the correct values of the 48 This is useful if you want to find out the correct values of the
@@ -93,7 +91,6 @@ config OMAP_32K_TIMER_HZ
93 91
94config OMAP_DM_TIMER 92config OMAP_DM_TIMER
95 bool "Use dual-mode timer" 93 bool "Use dual-mode timer"
96 default n
97 depends on ARCH_OMAP16XX 94 depends on ARCH_OMAP16XX
98 help 95 help
99 Select this option if you want to use OMAP Dual-Mode timers. 96 Select this option if you want to use OMAP Dual-Mode timers.
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index d5d0df7f04fc..cbde675bc95c 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -702,6 +702,15 @@ config PHYSICAL_START
702 702
703 Don't change this unless you know what you are doing. 703 Don't change this unless you know what you are doing.
704 704
705config HOTPLUG_CPU
706 bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"
707 depends on SMP && HOTPLUG && EXPERIMENTAL
708 ---help---
709 Say Y here to experiment with turning CPUs off and on. CPUs
710 can be controlled through /sys/devices/system/cpu.
711
712 Say N.
713
705endmenu 714endmenu
706 715
707 716
@@ -988,15 +997,6 @@ config SCx200
988 This support is also available as a module. If compiled as a 997 This support is also available as a module. If compiled as a
989 module, it will be called scx200. 998 module, it will be called scx200.
990 999
991config HOTPLUG_CPU
992 bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"
993 depends on SMP && HOTPLUG && EXPERIMENTAL
994 ---help---
995 Say Y here to experiment with turning CPUs off and on. CPUs
996 can be controlled through /sys/devices/system/cpu.
997
998 Say N.
999
1000source "drivers/pcmcia/Kconfig" 1000source "drivers/pcmcia/Kconfig"
1001 1001
1002source "drivers/pci/hotplug/Kconfig" 1002source "drivers/pci/hotplug/Kconfig"
diff --git a/arch/i386/Makefile b/arch/i386/Makefile
index d3c0409d201c..bd2d53a9dd2b 100644
--- a/arch/i386/Makefile
+++ b/arch/i386/Makefile
@@ -42,9 +42,9 @@ include $(srctree)/arch/i386/Makefile.cpu
42cflags-$(CONFIG_REGPARM) += $(shell if [ $(call cc-version) -ge 0300 ] ; then \ 42cflags-$(CONFIG_REGPARM) += $(shell if [ $(call cc-version) -ge 0300 ] ; then \
43 echo "-mregparm=3"; fi ;) 43 echo "-mregparm=3"; fi ;)
44 44
45# Disable unit-at-a-time mode, it makes gcc use a lot more stack 45# Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use
46# due to the lack of sharing of stacklots. 46# a lot more stack due to the lack of sharing of stacklots:
47CFLAGS += $(call cc-option,-fno-unit-at-a-time) 47CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then echo $(call cc-option,-fno-unit-at-a-time); fi ;)
48 48
49CFLAGS += $(cflags-y) 49CFLAGS += $(cflags-y)
50 50
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index b9f0030a2ebb..0aaebf3e1cfa 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -112,33 +112,38 @@ static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
112 p < (void *)tinfo + THREAD_SIZE - 3; 112 p < (void *)tinfo + THREAD_SIZE - 3;
113} 113}
114 114
115static void print_addr_and_symbol(unsigned long addr, char *log_lvl)
116{
117 printk(log_lvl);
118 printk(" [<%08lx>] ", addr);
119 print_symbol("%s", addr);
120 printk("\n");
121}
122
115static inline unsigned long print_context_stack(struct thread_info *tinfo, 123static inline unsigned long print_context_stack(struct thread_info *tinfo,
116 unsigned long *stack, unsigned long ebp) 124 unsigned long *stack, unsigned long ebp,
125 char *log_lvl)
117{ 126{
118 unsigned long addr; 127 unsigned long addr;
119 128
120#ifdef CONFIG_FRAME_POINTER 129#ifdef CONFIG_FRAME_POINTER
121 while (valid_stack_ptr(tinfo, (void *)ebp)) { 130 while (valid_stack_ptr(tinfo, (void *)ebp)) {
122 addr = *(unsigned long *)(ebp + 4); 131 addr = *(unsigned long *)(ebp + 4);
123 printk(KERN_EMERG " [<%08lx>] ", addr); 132 print_addr_and_symbol(addr, log_lvl);
124 print_symbol("%s", addr);
125 printk("\n");
126 ebp = *(unsigned long *)ebp; 133 ebp = *(unsigned long *)ebp;
127 } 134 }
128#else 135#else
129 while (valid_stack_ptr(tinfo, stack)) { 136 while (valid_stack_ptr(tinfo, stack)) {
130 addr = *stack++; 137 addr = *stack++;
131 if (__kernel_text_address(addr)) { 138 if (__kernel_text_address(addr))
132 printk(KERN_EMERG " [<%08lx>]", addr); 139 print_addr_and_symbol(addr, log_lvl);
133 print_symbol(" %s", addr);
134 printk("\n");
135 }
136 } 140 }
137#endif 141#endif
138 return ebp; 142 return ebp;
139} 143}
140 144
141void show_trace(struct task_struct *task, unsigned long * stack) 145static void show_trace_log_lvl(struct task_struct *task,
146 unsigned long *stack, char *log_lvl)
142{ 147{
143 unsigned long ebp; 148 unsigned long ebp;
144 149
@@ -157,7 +162,7 @@ void show_trace(struct task_struct *task, unsigned long * stack)
157 struct thread_info *context; 162 struct thread_info *context;
158 context = (struct thread_info *) 163 context = (struct thread_info *)
159 ((unsigned long)stack & (~(THREAD_SIZE - 1))); 164 ((unsigned long)stack & (~(THREAD_SIZE - 1)));
160 ebp = print_context_stack(context, stack, ebp); 165 ebp = print_context_stack(context, stack, ebp, log_lvl);
161 stack = (unsigned long*)context->previous_esp; 166 stack = (unsigned long*)context->previous_esp;
162 if (!stack) 167 if (!stack)
163 break; 168 break;
@@ -165,7 +170,13 @@ void show_trace(struct task_struct *task, unsigned long * stack)
165 } 170 }
166} 171}
167 172
168void show_stack(struct task_struct *task, unsigned long *esp) 173void show_trace(struct task_struct *task, unsigned long * stack)
174{
175 show_trace_log_lvl(task, stack, "");
176}
177
178static void show_stack_log_lvl(struct task_struct *task, unsigned long *esp,
179 char *log_lvl)
169{ 180{
170 unsigned long *stack; 181 unsigned long *stack;
171 int i; 182 int i;
@@ -178,16 +189,26 @@ void show_stack(struct task_struct *task, unsigned long *esp)
178 } 189 }
179 190
180 stack = esp; 191 stack = esp;
181 printk(KERN_EMERG); 192 printk(log_lvl);
182 for(i = 0; i < kstack_depth_to_print; i++) { 193 for(i = 0; i < kstack_depth_to_print; i++) {
183 if (kstack_end(stack)) 194 if (kstack_end(stack))
184 break; 195 break;
185 if (i && ((i % 8) == 0)) 196 if (i && ((i % 8) == 0)) {
186 printk("\n" KERN_EMERG " "); 197 printk("\n");
198 printk(log_lvl);
199 printk(" ");
200 }
187 printk("%08lx ", *stack++); 201 printk("%08lx ", *stack++);
188 } 202 }
189 printk("\n" KERN_EMERG "Call Trace:\n"); 203 printk("\n");
190 show_trace(task, esp); 204 printk(log_lvl);
205 printk("Call Trace:\n");
206 show_trace_log_lvl(task, esp, log_lvl);
207}
208
209void show_stack(struct task_struct *task, unsigned long *esp)
210{
211 show_stack_log_lvl(task, esp, "");
191} 212}
192 213
193/* 214/*
@@ -238,7 +259,7 @@ void show_registers(struct pt_regs *regs)
238 u8 __user *eip; 259 u8 __user *eip;
239 260
240 printk("\n" KERN_EMERG "Stack: "); 261 printk("\n" KERN_EMERG "Stack: ");
241 show_stack(NULL, (unsigned long*)esp); 262 show_stack_log_lvl(NULL, (unsigned long *)esp, KERN_EMERG);
242 263
243 printk(KERN_EMERG "Code: "); 264 printk(KERN_EMERG "Code: ");
244 265
diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c
index 65f67070db64..83c3645ccc43 100644
--- a/arch/i386/pci/fixup.c
+++ b/arch/i386/pci/fixup.c
@@ -449,3 +449,19 @@ static void __devinit pci_post_fixup_toshiba_ohci1394(struct pci_dev *dev)
449} 449}
450DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_TI, 0x8032, 450DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_TI, 0x8032,
451 pci_post_fixup_toshiba_ohci1394); 451 pci_post_fixup_toshiba_ohci1394);
452
453
454/*
455 * Prevent the BIOS trapping accesses to the Cyrix CS5530A video device
456 * configuration space.
457 */
458static void __devinit pci_early_fixup_cyrix_5530(struct pci_dev *dev)
459{
460 u8 r;
461 /* clear 'F4 Video Configuration Trap' bit */
462 pci_read_config_byte(dev, 0x42, &r);
463 r &= 0xfd;
464 pci_write_config_byte(dev, 0x42, r);
465}
466DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY,
467 pci_early_fixup_cyrix_5530);
diff --git a/arch/ia64/configs/gensparse_defconfig b/arch/ia64/configs/gensparse_defconfig
index 80f8663bc6d9..1d07d8072ec2 100644
--- a/arch/ia64/configs/gensparse_defconfig
+++ b/arch/ia64/configs/gensparse_defconfig
@@ -701,6 +701,7 @@ CONFIG_SERIAL_CORE_CONSOLE=y
701CONFIG_SERIAL_SGI_L1_CONSOLE=y 701CONFIG_SERIAL_SGI_L1_CONSOLE=y
702# CONFIG_SERIAL_JSM is not set 702# CONFIG_SERIAL_JSM is not set
703CONFIG_SERIAL_SGI_IOC4=y 703CONFIG_SERIAL_SGI_IOC4=y
704CONFIG_SERIAL_SGI_IOC3=y
704CONFIG_UNIX98_PTYS=y 705CONFIG_UNIX98_PTYS=y
705CONFIG_LEGACY_PTYS=y 706CONFIG_LEGACY_PTYS=y
706CONFIG_LEGACY_PTY_COUNT=256 707CONFIG_LEGACY_PTY_COUNT=256
@@ -1046,6 +1047,7 @@ CONFIG_INFINIBAND_IPOIB=m
1046# SN Devices 1047# SN Devices
1047# 1048#
1048CONFIG_SGI_IOC4=y 1049CONFIG_SGI_IOC4=y
1050CONFIG_SGI_IOC3=y
1049 1051
1050# 1052#
1051# File systems 1053# File systems
diff --git a/arch/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig
index ff8bb3770c9d..3cb503b659e6 100644
--- a/arch/ia64/configs/sn2_defconfig
+++ b/arch/ia64/configs/sn2_defconfig
@@ -659,6 +659,7 @@ CONFIG_SERIAL_CORE_CONSOLE=y
659CONFIG_SERIAL_SGI_L1_CONSOLE=y 659CONFIG_SERIAL_SGI_L1_CONSOLE=y
660# CONFIG_SERIAL_JSM is not set 660# CONFIG_SERIAL_JSM is not set
661CONFIG_SERIAL_SGI_IOC4=y 661CONFIG_SERIAL_SGI_IOC4=y
662CONFIG_SERIAL_SGI_IOC3=y
662CONFIG_UNIX98_PTYS=y 663CONFIG_UNIX98_PTYS=y
663CONFIG_LEGACY_PTYS=y 664CONFIG_LEGACY_PTYS=y
664CONFIG_LEGACY_PTY_COUNT=256 665CONFIG_LEGACY_PTY_COUNT=256
@@ -899,6 +900,7 @@ CONFIG_INFINIBAND_SRP=m
899# SN Devices 900# SN Devices
900# 901#
901CONFIG_SGI_IOC4=y 902CONFIG_SGI_IOC4=y
903CONFIG_SGI_IOC3=y
902 904
903# 905#
904# File systems 906# File systems
diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c
index a346e1833bf2..626cdc83668b 100644
--- a/arch/ia64/hp/sim/simserial.c
+++ b/arch/ia64/hp/sim/simserial.c
@@ -108,7 +108,6 @@ static struct async_struct *IRQ_ports[NR_IRQS];
108static struct console *console; 108static struct console *console;
109 109
110static unsigned char *tmp_buf; 110static unsigned char *tmp_buf;
111static DECLARE_MUTEX(tmp_buf_sem);
112 111
113extern struct console *console_drivers; /* from kernel/printk.c */ 112extern struct console *console_drivers; /* from kernel/printk.c */
114 113
@@ -167,15 +166,9 @@ static void receive_chars(struct tty_struct *tty, struct pt_regs *regs)
167 } 166 }
168 } 167 }
169 seen_esc = 0; 168 seen_esc = 0;
170 if (tty->flip.count >= TTY_FLIPBUF_SIZE) break;
171 169
172 *tty->flip.char_buf_ptr = ch; 170 if (tty_insert_flip_char(tty, ch, TTY_NORMAL) == 0)
173 171 break;
174 *tty->flip.flag_buf_ptr = 0;
175
176 tty->flip.flag_buf_ptr++;
177 tty->flip.char_buf_ptr++;
178 tty->flip.count++;
179 } 172 }
180 tty_flip_buffer_push(tty); 173 tty_flip_buffer_push(tty);
181} 174}
diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S
index 2ddbac6f4999..ce423910ca97 100644
--- a/arch/ia64/kernel/fsys.S
+++ b/arch/ia64/kernel/fsys.S
@@ -903,5 +903,6 @@ fsyscall_table:
903 data8 0 903 data8 0
904 data8 0 904 data8 0
905 data8 0 905 data8 0
906 data8 0 // 1280
906 907
907 .org fsyscall_table + 8*NR_syscalls // guard against failures to increase NR_syscalls 908 .org fsyscall_table + 8*NR_syscalls // guard against failures to increase NR_syscalls
diff --git a/arch/ia64/kernel/jprobes.S b/arch/ia64/kernel/jprobes.S
index 2323377e3695..5cd6226f44f2 100644
--- a/arch/ia64/kernel/jprobes.S
+++ b/arch/ia64/kernel/jprobes.S
@@ -60,3 +60,30 @@ END(jprobe_break)
60GLOBAL_ENTRY(jprobe_inst_return) 60GLOBAL_ENTRY(jprobe_inst_return)
61 br.call.sptk.many b0=jprobe_break 61 br.call.sptk.many b0=jprobe_break
62END(jprobe_inst_return) 62END(jprobe_inst_return)
63
64GLOBAL_ENTRY(invalidate_stacked_regs)
65 movl r16=invalidate_restore_cfm
66 ;;
67 mov b6=r16
68 ;;
69 br.ret.sptk.many b6
70 ;;
71invalidate_restore_cfm:
72 mov r16=ar.rsc
73 ;;
74 mov ar.rsc=r0
75 ;;
76 loadrs
77 ;;
78 mov ar.rsc=r16
79 ;;
80 br.cond.sptk.many rp
81END(invalidate_stacked_regs)
82
83GLOBAL_ENTRY(flush_register_stack)
84 // flush dirty regs to backing store (must be first in insn group)
85 flushrs
86 ;;
87 br.ret.sptk.many rp
88END(flush_register_stack)
89
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index 346fedf9ea47..50ae8c7d453d 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -766,11 +766,56 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
766 return ret; 766 return ret;
767} 767}
768 768
769struct param_bsp_cfm {
770 unsigned long ip;
771 unsigned long *bsp;
772 unsigned long cfm;
773};
774
775static void ia64_get_bsp_cfm(struct unw_frame_info *info, void *arg)
776{
777 unsigned long ip;
778 struct param_bsp_cfm *lp = arg;
779
780 do {
781 unw_get_ip(info, &ip);
782 if (ip == 0)
783 break;
784 if (ip == lp->ip) {
785 unw_get_bsp(info, (unsigned long*)&lp->bsp);
786 unw_get_cfm(info, (unsigned long*)&lp->cfm);
787 return;
788 }
789 } while (unw_unwind(info) >= 0);
790 lp->bsp = 0;
791 lp->cfm = 0;
792 return;
793}
794
769int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) 795int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
770{ 796{
771 struct jprobe *jp = container_of(p, struct jprobe, kp); 797 struct jprobe *jp = container_of(p, struct jprobe, kp);
772 unsigned long addr = ((struct fnptr *)(jp->entry))->ip; 798 unsigned long addr = ((struct fnptr *)(jp->entry))->ip;
773 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); 799 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
800 struct param_bsp_cfm pa;
801 int bytes;
802
803 /*
804 * Callee owns the argument space and could overwrite it, eg
805 * tail call optimization. So to be absolutely safe
806 * we save the argument space before transfering the control
807 * to instrumented jprobe function which runs in
808 * the process context
809 */
810 pa.ip = regs->cr_iip;
811 unw_init_running(ia64_get_bsp_cfm, &pa);
812 bytes = (char *)ia64_rse_skip_regs(pa.bsp, pa.cfm & 0x3f)
813 - (char *)pa.bsp;
814 memcpy( kcb->jprobes_saved_stacked_regs,
815 pa.bsp,
816 bytes );
817 kcb->bsp = pa.bsp;
818 kcb->cfm = pa.cfm;
774 819
775 /* save architectural state */ 820 /* save architectural state */
776 kcb->jprobe_saved_regs = *regs; 821 kcb->jprobe_saved_regs = *regs;
@@ -792,8 +837,20 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
792int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) 837int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
793{ 838{
794 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); 839 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
840 int bytes;
795 841
842 /* restoring architectural state */
796 *regs = kcb->jprobe_saved_regs; 843 *regs = kcb->jprobe_saved_regs;
844
845 /* restoring the original argument space */
846 flush_register_stack();
847 bytes = (char *)ia64_rse_skip_regs(kcb->bsp, kcb->cfm & 0x3f)
848 - (char *)kcb->bsp;
849 memcpy( kcb->bsp,
850 kcb->jprobes_saved_stacked_regs,
851 bytes );
852 invalidate_stacked_regs();
853
797 preempt_enable_no_resched(); 854 preempt_enable_no_resched();
798 return 1; 855 return 1;
799} 856}
diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S
index db32fc1d3935..403a80a58c13 100644
--- a/arch/ia64/kernel/mca_asm.S
+++ b/arch/ia64/kernel/mca_asm.S
@@ -847,7 +847,7 @@ ia64_state_restore:
847 ;; 847 ;;
848 mov cr.iim=temp3 848 mov cr.iim=temp3
849 mov cr.iha=temp4 849 mov cr.iha=temp4
850 dep r22=0,r22,62,2 // pal_min_state, physical, uncached 850 dep r22=0,r22,62,1 // pal_min_state, physical, uncached
851 mov IA64_KR(CURRENT)=r21 851 mov IA64_KR(CURRENT)=r21
852 ld8 r8=[temp1] // os_status 852 ld8 r8=[temp1] // os_status
853 ld8 r10=[temp2] // context 853 ld8 r10=[temp2] // context
diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c
index a87a162a3086..9d5a823479a3 100644
--- a/arch/ia64/kernel/salinfo.c
+++ b/arch/ia64/kernel/salinfo.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Creates entries in /proc/sal for various system features. 4 * Creates entries in /proc/sal for various system features.
5 * 5 *
6 * Copyright (c) 2003 Silicon Graphics, Inc. All rights reserved. 6 * Copyright (c) 2003, 2006 Silicon Graphics, Inc. All rights reserved.
7 * Copyright (c) 2003 Hewlett-Packard Co 7 * Copyright (c) 2003 Hewlett-Packard Co
8 * Bjorn Helgaas <bjorn.helgaas@hp.com> 8 * Bjorn Helgaas <bjorn.helgaas@hp.com>
9 * 9 *
@@ -27,9 +27,17 @@
27 * mca.c may not pass a buffer, a NULL buffer just indicates that a new 27 * mca.c may not pass a buffer, a NULL buffer just indicates that a new
28 * record is available in SAL. 28 * record is available in SAL.
29 * Replace some NR_CPUS by cpus_online, for hotplug cpu. 29 * Replace some NR_CPUS by cpus_online, for hotplug cpu.
30 *
31 * Jan 5 2006 kaos@sgi.com
32 * Handle hotplug cpus coming online.
33 * Handle hotplug cpus going offline while they still have outstanding records.
34 * Use the cpu_* macros consistently.
35 * Replace the counting semaphore with a mutex and a test if the cpumask is non-empty.
36 * Modify the locking to make the test for "work to do" an atomic operation.
30 */ 37 */
31 38
32#include <linux/capability.h> 39#include <linux/capability.h>
40#include <linux/cpu.h>
33#include <linux/types.h> 41#include <linux/types.h>
34#include <linux/proc_fs.h> 42#include <linux/proc_fs.h>
35#include <linux/module.h> 43#include <linux/module.h>
@@ -132,8 +140,8 @@ enum salinfo_state {
132}; 140};
133 141
134struct salinfo_data { 142struct salinfo_data {
135 volatile cpumask_t cpu_event; /* which cpus have outstanding events */ 143 cpumask_t cpu_event; /* which cpus have outstanding events */
136 struct semaphore sem; /* count of cpus with outstanding events (bits set in cpu_event) */ 144 struct semaphore mutex;
137 u8 *log_buffer; 145 u8 *log_buffer;
138 u64 log_size; 146 u64 log_size;
139 u8 *oemdata; /* decoded oem data */ 147 u8 *oemdata; /* decoded oem data */
@@ -174,6 +182,21 @@ struct salinfo_platform_oemdata_parms {
174 int ret; 182 int ret;
175}; 183};
176 184
185/* Kick the mutex that tells user space that there is work to do. Instead of
186 * trying to track the state of the mutex across multiple cpus, in user
187 * context, interrupt context, non-maskable interrupt context and hotplug cpu,
188 * it is far easier just to grab the mutex if it is free then release it.
189 *
190 * This routine must be called with data_saved_lock held, to make the down/up
191 * operation atomic.
192 */
193static void
194salinfo_work_to_do(struct salinfo_data *data)
195{
196 down_trylock(&data->mutex);
197 up(&data->mutex);
198}
199
177static void 200static void
178salinfo_platform_oemdata_cpu(void *context) 201salinfo_platform_oemdata_cpu(void *context)
179{ 202{
@@ -212,9 +235,9 @@ salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe)
212 235
213 BUG_ON(type >= ARRAY_SIZE(salinfo_log_name)); 236 BUG_ON(type >= ARRAY_SIZE(salinfo_log_name));
214 237
238 if (irqsafe)
239 spin_lock_irqsave(&data_saved_lock, flags);
215 if (buffer) { 240 if (buffer) {
216 if (irqsafe)
217 spin_lock_irqsave(&data_saved_lock, flags);
218 for (i = 0, data_saved = data->data_saved; i < saved_size; ++i, ++data_saved) { 241 for (i = 0, data_saved = data->data_saved; i < saved_size; ++i, ++data_saved) {
219 if (!data_saved->buffer) 242 if (!data_saved->buffer)
220 break; 243 break;
@@ -232,13 +255,11 @@ salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe)
232 data_saved->size = size; 255 data_saved->size = size;
233 data_saved->buffer = buffer; 256 data_saved->buffer = buffer;
234 } 257 }
235 if (irqsafe)
236 spin_unlock_irqrestore(&data_saved_lock, flags);
237 } 258 }
238 259 cpu_set(smp_processor_id(), data->cpu_event);
239 if (!test_and_set_bit(smp_processor_id(), &data->cpu_event)) { 260 if (irqsafe) {
240 if (irqsafe) 261 salinfo_work_to_do(data);
241 up(&data->sem); 262 spin_unlock_irqrestore(&data_saved_lock, flags);
242 } 263 }
243} 264}
244 265
@@ -249,20 +270,17 @@ static struct timer_list salinfo_timer;
249static void 270static void
250salinfo_timeout_check(struct salinfo_data *data) 271salinfo_timeout_check(struct salinfo_data *data)
251{ 272{
252 int i; 273 unsigned long flags;
253 if (!data->open) 274 if (!data->open)
254 return; 275 return;
255 for_each_online_cpu(i) { 276 if (!cpus_empty(data->cpu_event)) {
256 if (test_bit(i, &data->cpu_event)) { 277 spin_lock_irqsave(&data_saved_lock, flags);
257 /* double up() is not a problem, user space will see no 278 salinfo_work_to_do(data);
258 * records for the additional "events". 279 spin_unlock_irqrestore(&data_saved_lock, flags);
259 */
260 up(&data->sem);
261 }
262 } 280 }
263} 281}
264 282
265static void 283static void
266salinfo_timeout (unsigned long arg) 284salinfo_timeout (unsigned long arg)
267{ 285{
268 salinfo_timeout_check(salinfo_data + SAL_INFO_TYPE_MCA); 286 salinfo_timeout_check(salinfo_data + SAL_INFO_TYPE_MCA);
@@ -290,16 +308,20 @@ salinfo_event_read(struct file *file, char __user *buffer, size_t count, loff_t
290 int i, n, cpu = -1; 308 int i, n, cpu = -1;
291 309
292retry: 310retry:
293 if (down_trylock(&data->sem)) { 311 if (cpus_empty(data->cpu_event) && down_trylock(&data->mutex)) {
294 if (file->f_flags & O_NONBLOCK) 312 if (file->f_flags & O_NONBLOCK)
295 return -EAGAIN; 313 return -EAGAIN;
296 if (down_interruptible(&data->sem)) 314 if (down_interruptible(&data->mutex))
297 return -EINTR; 315 return -EINTR;
298 } 316 }
299 317
300 n = data->cpu_check; 318 n = data->cpu_check;
301 for (i = 0; i < NR_CPUS; i++) { 319 for (i = 0; i < NR_CPUS; i++) {
302 if (test_bit(n, &data->cpu_event) && cpu_online(n)) { 320 if (cpu_isset(n, data->cpu_event)) {
321 if (!cpu_online(n)) {
322 cpu_clear(n, data->cpu_event);
323 continue;
324 }
303 cpu = n; 325 cpu = n;
304 break; 326 break;
305 } 327 }
@@ -310,9 +332,6 @@ retry:
310 if (cpu == -1) 332 if (cpu == -1)
311 goto retry; 333 goto retry;
312 334
313 /* events are sticky until the user says "clear" */
314 up(&data->sem);
315
316 /* for next read, start checking at next CPU */ 335 /* for next read, start checking at next CPU */
317 data->cpu_check = cpu; 336 data->cpu_check = cpu;
318 if (++data->cpu_check == NR_CPUS) 337 if (++data->cpu_check == NR_CPUS)
@@ -381,10 +400,8 @@ salinfo_log_release(struct inode *inode, struct file *file)
381static void 400static void
382call_on_cpu(int cpu, void (*fn)(void *), void *arg) 401call_on_cpu(int cpu, void (*fn)(void *), void *arg)
383{ 402{
384 cpumask_t save_cpus_allowed, new_cpus_allowed; 403 cpumask_t save_cpus_allowed = current->cpus_allowed;
385 memcpy(&save_cpus_allowed, &current->cpus_allowed, sizeof(save_cpus_allowed)); 404 cpumask_t new_cpus_allowed = cpumask_of_cpu(cpu);
386 memset(&new_cpus_allowed, 0, sizeof(new_cpus_allowed));
387 set_bit(cpu, &new_cpus_allowed);
388 set_cpus_allowed(current, new_cpus_allowed); 405 set_cpus_allowed(current, new_cpus_allowed);
389 (*fn)(arg); 406 (*fn)(arg);
390 set_cpus_allowed(current, save_cpus_allowed); 407 set_cpus_allowed(current, save_cpus_allowed);
@@ -433,10 +450,10 @@ retry:
433 if (!data->saved_num) 450 if (!data->saved_num)
434 call_on_cpu(cpu, salinfo_log_read_cpu, data); 451 call_on_cpu(cpu, salinfo_log_read_cpu, data);
435 if (!data->log_size) { 452 if (!data->log_size) {
436 data->state = STATE_NO_DATA; 453 data->state = STATE_NO_DATA;
437 clear_bit(cpu, &data->cpu_event); 454 cpu_clear(cpu, data->cpu_event);
438 } else { 455 } else {
439 data->state = STATE_LOG_RECORD; 456 data->state = STATE_LOG_RECORD;
440 } 457 }
441} 458}
442 459
@@ -473,27 +490,31 @@ static int
473salinfo_log_clear(struct salinfo_data *data, int cpu) 490salinfo_log_clear(struct salinfo_data *data, int cpu)
474{ 491{
475 sal_log_record_header_t *rh; 492 sal_log_record_header_t *rh;
493 unsigned long flags;
494 spin_lock_irqsave(&data_saved_lock, flags);
476 data->state = STATE_NO_DATA; 495 data->state = STATE_NO_DATA;
477 if (!test_bit(cpu, &data->cpu_event)) 496 if (!cpu_isset(cpu, data->cpu_event)) {
497 spin_unlock_irqrestore(&data_saved_lock, flags);
478 return 0; 498 return 0;
479 down(&data->sem); 499 }
480 clear_bit(cpu, &data->cpu_event); 500 cpu_clear(cpu, data->cpu_event);
481 if (data->saved_num) { 501 if (data->saved_num) {
482 unsigned long flags; 502 shift1_data_saved(data, data->saved_num - 1);
483 spin_lock_irqsave(&data_saved_lock, flags);
484 shift1_data_saved(data, data->saved_num - 1 );
485 data->saved_num = 0; 503 data->saved_num = 0;
486 spin_unlock_irqrestore(&data_saved_lock, flags);
487 } 504 }
505 spin_unlock_irqrestore(&data_saved_lock, flags);
488 rh = (sal_log_record_header_t *)(data->log_buffer); 506 rh = (sal_log_record_header_t *)(data->log_buffer);
489 /* Corrected errors have already been cleared from SAL */ 507 /* Corrected errors have already been cleared from SAL */
490 if (rh->severity != sal_log_severity_corrected) 508 if (rh->severity != sal_log_severity_corrected)
491 call_on_cpu(cpu, salinfo_log_clear_cpu, data); 509 call_on_cpu(cpu, salinfo_log_clear_cpu, data);
492 /* clearing a record may make a new record visible */ 510 /* clearing a record may make a new record visible */
493 salinfo_log_new_read(cpu, data); 511 salinfo_log_new_read(cpu, data);
494 if (data->state == STATE_LOG_RECORD && 512 if (data->state == STATE_LOG_RECORD) {
495 !test_and_set_bit(cpu, &data->cpu_event)) 513 spin_lock_irqsave(&data_saved_lock, flags);
496 up(&data->sem); 514 cpu_set(cpu, data->cpu_event);
515 salinfo_work_to_do(data);
516 spin_unlock_irqrestore(&data_saved_lock, flags);
517 }
497 return 0; 518 return 0;
498} 519}
499 520
@@ -550,6 +571,53 @@ static struct file_operations salinfo_data_fops = {
550 .write = salinfo_log_write, 571 .write = salinfo_log_write,
551}; 572};
552 573
574#ifdef CONFIG_HOTPLUG_CPU
575static int __devinit
576salinfo_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
577{
578 unsigned int i, cpu = (unsigned long)hcpu;
579 unsigned long flags;
580 struct salinfo_data *data;
581 switch (action) {
582 case CPU_ONLINE:
583 spin_lock_irqsave(&data_saved_lock, flags);
584 for (i = 0, data = salinfo_data;
585 i < ARRAY_SIZE(salinfo_data);
586 ++i, ++data) {
587 cpu_set(cpu, data->cpu_event);
588 salinfo_work_to_do(data);
589 }
590 spin_unlock_irqrestore(&data_saved_lock, flags);
591 break;
592 case CPU_DEAD:
593 spin_lock_irqsave(&data_saved_lock, flags);
594 for (i = 0, data = salinfo_data;
595 i < ARRAY_SIZE(salinfo_data);
596 ++i, ++data) {
597 struct salinfo_data_saved *data_saved;
598 int j;
599 for (j = ARRAY_SIZE(data->data_saved) - 1, data_saved = data->data_saved + j;
600 j >= 0;
601 --j, --data_saved) {
602 if (data_saved->buffer && data_saved->cpu == cpu) {
603 shift1_data_saved(data, j);
604 }
605 }
606 cpu_clear(cpu, data->cpu_event);
607 }
608 spin_unlock_irqrestore(&data_saved_lock, flags);
609 break;
610 }
611 return NOTIFY_OK;
612}
613
614static struct notifier_block salinfo_cpu_notifier =
615{
616 .notifier_call = salinfo_cpu_callback,
617 .priority = 0,
618};
619#endif /* CONFIG_HOTPLUG_CPU */
620
553static int __init 621static int __init
554salinfo_init(void) 622salinfo_init(void)
555{ 623{
@@ -557,7 +625,7 @@ salinfo_init(void)
557 struct proc_dir_entry **sdir = salinfo_proc_entries; /* keeps track of every entry */ 625 struct proc_dir_entry **sdir = salinfo_proc_entries; /* keeps track of every entry */
558 struct proc_dir_entry *dir, *entry; 626 struct proc_dir_entry *dir, *entry;
559 struct salinfo_data *data; 627 struct salinfo_data *data;
560 int i, j, online; 628 int i, j;
561 629
562 salinfo_dir = proc_mkdir("sal", NULL); 630 salinfo_dir = proc_mkdir("sal", NULL);
563 if (!salinfo_dir) 631 if (!salinfo_dir)
@@ -572,7 +640,7 @@ salinfo_init(void)
572 for (i = 0; i < ARRAY_SIZE(salinfo_log_name); i++) { 640 for (i = 0; i < ARRAY_SIZE(salinfo_log_name); i++) {
573 data = salinfo_data + i; 641 data = salinfo_data + i;
574 data->type = i; 642 data->type = i;
575 sema_init(&data->sem, 0); 643 init_MUTEX(&data->mutex);
576 dir = proc_mkdir(salinfo_log_name[i], salinfo_dir); 644 dir = proc_mkdir(salinfo_log_name[i], salinfo_dir);
577 if (!dir) 645 if (!dir)
578 continue; 646 continue;
@@ -592,12 +660,8 @@ salinfo_init(void)
592 *sdir++ = entry; 660 *sdir++ = entry;
593 661
594 /* we missed any events before now */ 662 /* we missed any events before now */
595 online = 0; 663 for_each_online_cpu(j)
596 for_each_online_cpu(j) { 664 cpu_set(j, data->cpu_event);
597 set_bit(j, &data->cpu_event);
598 ++online;
599 }
600 sema_init(&data->sem, online);
601 665
602 *sdir++ = dir; 666 *sdir++ = dir;
603 } 667 }
@@ -609,6 +673,10 @@ salinfo_init(void)
609 salinfo_timer.function = &salinfo_timeout; 673 salinfo_timer.function = &salinfo_timeout;
610 add_timer(&salinfo_timer); 674 add_timer(&salinfo_timer);
611 675
676#ifdef CONFIG_HOTPLUG_CPU
677 register_cpu_notifier(&salinfo_cpu_notifier);
678#endif
679
612 return 0; 680 return 0;
613} 681}
614 682
diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c
index d3e0ecb56d62..55391901b013 100644
--- a/arch/ia64/kernel/traps.c
+++ b/arch/ia64/kernel/traps.c
@@ -530,12 +530,15 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
530 if (fsys_mode(current, &regs)) { 530 if (fsys_mode(current, &regs)) {
531 extern char __kernel_syscall_via_break[]; 531 extern char __kernel_syscall_via_break[];
532 /* 532 /*
533 * Got a trap in fsys-mode: Taken Branch Trap and Single Step trap 533 * Got a trap in fsys-mode: Taken Branch Trap
534 * need special handling; Debug trap is not supposed to happen. 534 * and Single Step trap need special handling;
535 * Debug trap is ignored (we disable it here
536 * and re-enable it in the lower-privilege trap).
535 */ 537 */
536 if (unlikely(vector == 29)) { 538 if (unlikely(vector == 29)) {
537 die("Got debug trap in fsys-mode---not supposed to happen!", 539 set_thread_flag(TIF_DB_DISABLED);
538 &regs, 0); 540 ia64_psr(&regs)->db = 0;
541 ia64_psr(&regs)->lp = 1;
539 return; 542 return;
540 } 543 }
541 /* re-do the system call via break 0x100000: */ 544 /* re-do the system call via break 0x100000: */
@@ -589,10 +592,19 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
589 case 34: 592 case 34:
590 if (isr & 0x2) { 593 if (isr & 0x2) {
591 /* Lower-Privilege Transfer Trap */ 594 /* Lower-Privilege Transfer Trap */
595
596 /* If we disabled debug traps during an fsyscall,
597 * re-enable them here.
598 */
599 if (test_thread_flag(TIF_DB_DISABLED)) {
600 clear_thread_flag(TIF_DB_DISABLED);
601 ia64_psr(&regs)->db = 1;
602 }
603
592 /* 604 /*
593 * Just clear PSR.lp and then return immediately: all the 605 * Just clear PSR.lp and then return immediately:
594 * interesting work (e.g., signal delivery is done in the kernel 606 * all the interesting work (e.g., signal delivery)
595 * exit path). 607 * is done in the kernel exit path.
596 */ 608 */
597 ia64_psr(&regs)->lp = 0; 609 ia64_psr(&regs)->lp = 0;
598 return; 610 return;
diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c
index 41105d454423..6a4eec9113e8 100644
--- a/arch/ia64/mm/tlb.c
+++ b/arch/ia64/mm/tlb.c
@@ -90,7 +90,7 @@ ia64_global_tlb_purge (struct mm_struct *mm, unsigned long start,
90{ 90{
91 static DEFINE_SPINLOCK(ptcg_lock); 91 static DEFINE_SPINLOCK(ptcg_lock);
92 92
93 if (mm != current->active_mm) { 93 if (mm != current->active_mm || !current->mm) {
94 flush_tlb_all(); 94 flush_tlb_all();
95 return; 95 return;
96 } 96 }
diff --git a/arch/ia64/sn/include/xtalk/hubdev.h b/arch/ia64/sn/include/xtalk/hubdev.h
index 71c2b271b4c6..4d417c301201 100644
--- a/arch/ia64/sn/include/xtalk/hubdev.h
+++ b/arch/ia64/sn/include/xtalk/hubdev.h
@@ -26,11 +26,14 @@
26#define IIO_NUM_ITTES 7 26#define IIO_NUM_ITTES 7
27#define HUB_NUM_BIG_WINDOW (IIO_NUM_ITTES - 1) 27#define HUB_NUM_BIG_WINDOW (IIO_NUM_ITTES - 1)
28 28
29struct sn_flush_device_list { 29/* This struct is shared between the PROM and the kernel.
30 * Changes to this struct will require corresponding changes to the kernel.
31 */
32struct sn_flush_device_common {
30 int sfdl_bus; 33 int sfdl_bus;
31 int sfdl_slot; 34 int sfdl_slot;
32 int sfdl_pin; 35 int sfdl_pin;
33 struct bar_list { 36 struct common_bar_list {
34 unsigned long start; 37 unsigned long start;
35 unsigned long end; 38 unsigned long end;
36 } sfdl_bar_list[6]; 39 } sfdl_bar_list[6];
@@ -40,14 +43,19 @@ struct sn_flush_device_list {
40 uint32_t sfdl_persistent_busnum; 43 uint32_t sfdl_persistent_busnum;
41 uint32_t sfdl_persistent_segment; 44 uint32_t sfdl_persistent_segment;
42 struct pcibus_info *sfdl_pcibus_info; 45 struct pcibus_info *sfdl_pcibus_info;
46};
47
48/* This struct is kernel only and is not used by the PROM */
49struct sn_flush_device_kernel {
43 spinlock_t sfdl_flush_lock; 50 spinlock_t sfdl_flush_lock;
51 struct sn_flush_device_common *common;
44}; 52};
45 53
46/* 54/*
47 * **widget_p - Used as an array[wid_num][device] of sn_flush_device_list. 55 * **widget_p - Used as an array[wid_num][device] of sn_flush_device_kernel.
48 */ 56 */
49struct sn_flush_nasid_entry { 57struct sn_flush_nasid_entry {
50 struct sn_flush_device_list **widget_p; /* Used as a array of wid_num */ 58 struct sn_flush_device_kernel **widget_p; // Used as an array of wid_num
51 uint64_t iio_itte[8]; 59 uint64_t iio_itte[8];
52}; 60};
53 61
diff --git a/arch/ia64/sn/kernel/bte_error.c b/arch/ia64/sn/kernel/bte_error.c
index fcbc748ae433..f1ec1370b3e3 100644
--- a/arch/ia64/sn/kernel/bte_error.c
+++ b/arch/ia64/sn/kernel/bte_error.c
@@ -33,7 +33,7 @@ void bte_error_handler(unsigned long);
33 * Wait until all BTE related CRBs are completed 33 * Wait until all BTE related CRBs are completed
34 * and then reset the interfaces. 34 * and then reset the interfaces.
35 */ 35 */
36void shub1_bte_error_handler(unsigned long _nodepda) 36int shub1_bte_error_handler(unsigned long _nodepda)
37{ 37{
38 struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda; 38 struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda;
39 struct timer_list *recovery_timer = &err_nodepda->bte_recovery_timer; 39 struct timer_list *recovery_timer = &err_nodepda->bte_recovery_timer;
@@ -53,7 +53,7 @@ void shub1_bte_error_handler(unsigned long _nodepda)
53 (err_nodepda->bte_if[1].bh_error == BTE_SUCCESS)) { 53 (err_nodepda->bte_if[1].bh_error == BTE_SUCCESS)) {
54 BTE_PRINTK(("eh:%p:%d Nothing to do.\n", err_nodepda, 54 BTE_PRINTK(("eh:%p:%d Nothing to do.\n", err_nodepda,
55 smp_processor_id())); 55 smp_processor_id()));
56 return; 56 return 1;
57 } 57 }
58 58
59 /* Determine information about our hub */ 59 /* Determine information about our hub */
@@ -81,7 +81,7 @@ void shub1_bte_error_handler(unsigned long _nodepda)
81 mod_timer(recovery_timer, HZ * 5); 81 mod_timer(recovery_timer, HZ * 5);
82 BTE_PRINTK(("eh:%p:%d Marked Giving up\n", err_nodepda, 82 BTE_PRINTK(("eh:%p:%d Marked Giving up\n", err_nodepda,
83 smp_processor_id())); 83 smp_processor_id()));
84 return; 84 return 1;
85 } 85 }
86 if (icmr.ii_icmr_fld_s.i_crb_vld != 0) { 86 if (icmr.ii_icmr_fld_s.i_crb_vld != 0) {
87 87
@@ -99,7 +99,7 @@ void shub1_bte_error_handler(unsigned long _nodepda)
99 BTE_PRINTK(("eh:%p:%d Valid %d, Giving up\n", 99 BTE_PRINTK(("eh:%p:%d Valid %d, Giving up\n",
100 err_nodepda, smp_processor_id(), 100 err_nodepda, smp_processor_id(),
101 i)); 101 i));
102 return; 102 return 1;
103 } 103 }
104 } 104 }
105 } 105 }
@@ -124,6 +124,42 @@ void shub1_bte_error_handler(unsigned long _nodepda)
124 REMOTE_HUB_S(nasid, IIO_IBCR, ibcr.ii_ibcr_regval); 124 REMOTE_HUB_S(nasid, IIO_IBCR, ibcr.ii_ibcr_regval);
125 125
126 del_timer(recovery_timer); 126 del_timer(recovery_timer);
127 return 0;
128}
129
130/*
131 * Wait until all BTE related CRBs are completed
132 * and then reset the interfaces.
133 */
134int shub2_bte_error_handler(unsigned long _nodepda)
135{
136 struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda;
137 struct timer_list *recovery_timer = &err_nodepda->bte_recovery_timer;
138 struct bteinfo_s *bte;
139 nasid_t nasid;
140 u64 status;
141 int i;
142
143 nasid = cnodeid_to_nasid(err_nodepda->bte_if[0].bte_cnode);
144
145 /*
146 * Verify that all the BTEs are complete
147 */
148 for (i = 0; i < BTES_PER_NODE; i++) {
149 bte = &err_nodepda->bte_if[i];
150 status = BTE_LNSTAT_LOAD(bte);
151 if ((status & IBLS_ERROR) || !(status & IBLS_BUSY))
152 continue;
153 mod_timer(recovery_timer, HZ * 5);
154 BTE_PRINTK(("eh:%p:%d Marked Giving up\n", err_nodepda,
155 smp_processor_id()));
156 return 1;
157 }
158 if (ia64_sn_bte_recovery(nasid))
159 panic("bte_error_handler(): Fatal BTE Error");
160
161 del_timer(recovery_timer);
162 return 0;
127} 163}
128 164
129/* 165/*
@@ -135,7 +171,6 @@ void bte_error_handler(unsigned long _nodepda)
135 struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda; 171 struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda;
136 spinlock_t *recovery_lock = &err_nodepda->bte_recovery_lock; 172 spinlock_t *recovery_lock = &err_nodepda->bte_recovery_lock;
137 int i; 173 int i;
138 nasid_t nasid;
139 unsigned long irq_flags; 174 unsigned long irq_flags;
140 volatile u64 *notify; 175 volatile u64 *notify;
141 bte_result_t bh_error; 176 bte_result_t bh_error;
@@ -160,12 +195,15 @@ void bte_error_handler(unsigned long _nodepda)
160 } 195 }
161 196
162 if (is_shub1()) { 197 if (is_shub1()) {
163 shub1_bte_error_handler(_nodepda); 198 if (shub1_bte_error_handler(_nodepda)) {
199 spin_unlock_irqrestore(recovery_lock, irq_flags);
200 return;
201 }
164 } else { 202 } else {
165 nasid = cnodeid_to_nasid(err_nodepda->bte_if[0].bte_cnode); 203 if (shub2_bte_error_handler(_nodepda)) {
166 204 spin_unlock_irqrestore(recovery_lock, irq_flags);
167 if (ia64_sn_bte_recovery(nasid)) 205 return;
168 panic("bte_error_handler(): Fatal BTE Error"); 206 }
169 } 207 }
170 208
171 for (i = 0; i < BTES_PER_NODE; i++) { 209 for (i = 0; i < BTES_PER_NODE; i++) {
diff --git a/arch/ia64/sn/kernel/huberror.c b/arch/ia64/sn/kernel/huberror.c
index 5c5eb01c50f0..56ab6bae00ee 100644
--- a/arch/ia64/sn/kernel/huberror.c
+++ b/arch/ia64/sn/kernel/huberror.c
@@ -32,13 +32,14 @@ static irqreturn_t hub_eint_handler(int irq, void *arg, struct pt_regs *ep)
32 ret_stuff.v0 = 0; 32 ret_stuff.v0 = 0;
33 hubdev_info = (struct hubdev_info *)arg; 33 hubdev_info = (struct hubdev_info *)arg;
34 nasid = hubdev_info->hdi_nasid; 34 nasid = hubdev_info->hdi_nasid;
35 SAL_CALL_NOLOCK(ret_stuff, SN_SAL_HUB_ERROR_INTERRUPT, 35
36 if (is_shub1()) {
37 SAL_CALL_NOLOCK(ret_stuff, SN_SAL_HUB_ERROR_INTERRUPT,
36 (u64) nasid, 0, 0, 0, 0, 0, 0); 38 (u64) nasid, 0, 0, 0, 0, 0, 0);
37 39
38 if ((int)ret_stuff.v0) 40 if ((int)ret_stuff.v0)
39 panic("hubii_eint_handler(): Fatal TIO Error"); 41 panic("hubii_eint_handler(): Fatal TIO Error");
40 42
41 if (is_shub1()) {
42 if (!(nasid & 1)) /* Not a TIO, handle CRB errors */ 43 if (!(nasid & 1)) /* Not a TIO, handle CRB errors */
43 (void)hubiio_crb_error_handler(hubdev_info); 44 (void)hubiio_crb_error_handler(hubdev_info);
44 } else 45 } else
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c
index 318087e35b66..258d9d7aff98 100644
--- a/arch/ia64/sn/kernel/io_init.c
+++ b/arch/ia64/sn/kernel/io_init.c
@@ -76,11 +76,12 @@ static struct sn_pcibus_provider sn_pci_default_provider = {
76}; 76};
77 77
78/* 78/*
79 * Retrieve the DMA Flush List given nasid. This list is needed 79 * Retrieve the DMA Flush List given nasid, widget, and device.
80 * to implement the WAR - Flush DMA data on PIO Reads. 80 * This list is needed to implement the WAR - Flush DMA data on PIO Reads.
81 */ 81 */
82static inline uint64_t 82static inline u64
83sal_get_widget_dmaflush_list(u64 nasid, u64 widget_num, u64 address) 83sal_get_device_dmaflush_list(u64 nasid, u64 widget_num, u64 device_num,
84 u64 address)
84{ 85{
85 86
86 struct ia64_sal_retval ret_stuff; 87 struct ia64_sal_retval ret_stuff;
@@ -88,17 +89,17 @@ sal_get_widget_dmaflush_list(u64 nasid, u64 widget_num, u64 address)
88 ret_stuff.v0 = 0; 89 ret_stuff.v0 = 0;
89 90
90 SAL_CALL_NOLOCK(ret_stuff, 91 SAL_CALL_NOLOCK(ret_stuff,
91 (u64) SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST, 92 (u64) SN_SAL_IOIF_GET_DEVICE_DMAFLUSH_LIST,
92 (u64) nasid, (u64) widget_num, (u64) address, 0, 0, 0, 93 (u64) nasid, (u64) widget_num,
93 0); 94 (u64) device_num, (u64) address, 0, 0, 0);
94 return ret_stuff.v0; 95 return ret_stuff.status;
95 96
96} 97}
97 98
98/* 99/*
99 * Retrieve the hub device info structure for the given nasid. 100 * Retrieve the hub device info structure for the given nasid.
100 */ 101 */
101static inline uint64_t sal_get_hubdev_info(u64 handle, u64 address) 102static inline u64 sal_get_hubdev_info(u64 handle, u64 address)
102{ 103{
103 104
104 struct ia64_sal_retval ret_stuff; 105 struct ia64_sal_retval ret_stuff;
@@ -114,7 +115,7 @@ static inline uint64_t sal_get_hubdev_info(u64 handle, u64 address)
114/* 115/*
115 * Retrieve the pci bus information given the bus number. 116 * Retrieve the pci bus information given the bus number.
116 */ 117 */
117static inline uint64_t sal_get_pcibus_info(u64 segment, u64 busnum, u64 address) 118static inline u64 sal_get_pcibus_info(u64 segment, u64 busnum, u64 address)
118{ 119{
119 120
120 struct ia64_sal_retval ret_stuff; 121 struct ia64_sal_retval ret_stuff;
@@ -130,7 +131,7 @@ static inline uint64_t sal_get_pcibus_info(u64 segment, u64 busnum, u64 address)
130/* 131/*
131 * Retrieve the pci device information given the bus and device|function number. 132 * Retrieve the pci device information given the bus and device|function number.
132 */ 133 */
133static inline uint64_t 134static inline u64
134sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev, 135sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev,
135 u64 sn_irq_info) 136 u64 sn_irq_info)
136{ 137{
@@ -170,12 +171,12 @@ sn_pcidev_info_get(struct pci_dev *dev)
170 */ 171 */
171static void sn_fixup_ionodes(void) 172static void sn_fixup_ionodes(void)
172{ 173{
173 174 struct sn_flush_device_kernel *sn_flush_device_kernel;
174 struct sn_flush_device_list *sn_flush_device_list; 175 struct sn_flush_device_kernel *dev_entry;
175 struct hubdev_info *hubdev; 176 struct hubdev_info *hubdev;
176 uint64_t status; 177 u64 status;
177 uint64_t nasid; 178 u64 nasid;
178 int i, widget; 179 int i, widget, device;
179 180
180 /* 181 /*
181 * Get SGI Specific HUB chipset information. 182 * Get SGI Specific HUB chipset information.
@@ -186,7 +187,7 @@ static void sn_fixup_ionodes(void)
186 nasid = cnodeid_to_nasid(i); 187 nasid = cnodeid_to_nasid(i);
187 hubdev->max_segment_number = 0xffffffff; 188 hubdev->max_segment_number = 0xffffffff;
188 hubdev->max_pcibus_number = 0xff; 189 hubdev->max_pcibus_number = 0xff;
189 status = sal_get_hubdev_info(nasid, (uint64_t) __pa(hubdev)); 190 status = sal_get_hubdev_info(nasid, (u64) __pa(hubdev));
190 if (status) 191 if (status)
191 continue; 192 continue;
192 193
@@ -213,38 +214,49 @@ static void sn_fixup_ionodes(void)
213 214
214 hubdev->hdi_flush_nasid_list.widget_p = 215 hubdev->hdi_flush_nasid_list.widget_p =
215 kmalloc((HUB_WIDGET_ID_MAX + 1) * 216 kmalloc((HUB_WIDGET_ID_MAX + 1) *
216 sizeof(struct sn_flush_device_list *), GFP_KERNEL); 217 sizeof(struct sn_flush_device_kernel *),
217 218 GFP_KERNEL);
218 memset(hubdev->hdi_flush_nasid_list.widget_p, 0x0, 219 memset(hubdev->hdi_flush_nasid_list.widget_p, 0x0,
219 (HUB_WIDGET_ID_MAX + 1) * 220 (HUB_WIDGET_ID_MAX + 1) *
220 sizeof(struct sn_flush_device_list *)); 221 sizeof(struct sn_flush_device_kernel *));
221 222
222 for (widget = 0; widget <= HUB_WIDGET_ID_MAX; widget++) { 223 for (widget = 0; widget <= HUB_WIDGET_ID_MAX; widget++) {
223 sn_flush_device_list = kmalloc(DEV_PER_WIDGET * 224 sn_flush_device_kernel = kmalloc(DEV_PER_WIDGET *
224 sizeof(struct 225 sizeof(struct
225 sn_flush_device_list), 226 sn_flush_device_kernel),
226 GFP_KERNEL); 227 GFP_KERNEL);
227 memset(sn_flush_device_list, 0x0, 228 if (!sn_flush_device_kernel)
229 BUG();
230 memset(sn_flush_device_kernel, 0x0,
228 DEV_PER_WIDGET * 231 DEV_PER_WIDGET *
229 sizeof(struct sn_flush_device_list)); 232 sizeof(struct sn_flush_device_kernel));
230 233
231 status = 234 dev_entry = sn_flush_device_kernel;
232 sal_get_widget_dmaflush_list(nasid, widget, 235 for (device = 0; device < DEV_PER_WIDGET;
233 (uint64_t) 236 device++,dev_entry++) {
234 __pa 237 dev_entry->common = kmalloc(sizeof(struct
235 (sn_flush_device_list)); 238 sn_flush_device_common),
236 if (status) { 239 GFP_KERNEL);
237 kfree(sn_flush_device_list); 240 if (!dev_entry->common)
238 continue; 241 BUG();
242 memset(dev_entry->common, 0x0, sizeof(struct
243 sn_flush_device_common));
244
245 status = sal_get_device_dmaflush_list(nasid,
246 widget,
247 device,
248 (u64)(dev_entry->common));
249 if (status)
250 BUG();
251
252 spin_lock_init(&dev_entry->sfdl_flush_lock);
239 } 253 }
240 254
241 spin_lock_init(&sn_flush_device_list->sfdl_flush_lock); 255 if (sn_flush_device_kernel)
242 hubdev->hdi_flush_nasid_list.widget_p[widget] = 256 hubdev->hdi_flush_nasid_list.widget_p[widget] =
243 sn_flush_device_list; 257 sn_flush_device_kernel;
244 } 258 }
245
246 } 259 }
247
248} 260}
249 261
250/* 262/*
diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c
index 493fb3f38dc3..6a7939b16a1c 100644
--- a/arch/ia64/sn/kernel/tiocx.c
+++ b/arch/ia64/sn/kernel/tiocx.c
@@ -77,12 +77,6 @@ static void tiocx_bus_release(struct device *dev)
77 kfree(to_cx_dev(dev)); 77 kfree(to_cx_dev(dev));
78} 78}
79 79
80struct bus_type tiocx_bus_type = {
81 .name = "tiocx",
82 .match = tiocx_match,
83 .uevent = tiocx_uevent,
84};
85
86/** 80/**
87 * cx_device_match - Find cx_device in the id table. 81 * cx_device_match - Find cx_device in the id table.
88 * @ids: id table from driver 82 * @ids: id table from driver
@@ -149,6 +143,14 @@ static int cx_driver_remove(struct device *dev)
149 return 0; 143 return 0;
150} 144}
151 145
146struct bus_type tiocx_bus_type = {
147 .name = "tiocx",
148 .match = tiocx_match,
149 .uevent = tiocx_uevent,
150 .probe = cx_device_probe,
151 .remove = cx_driver_remove,
152};
153
152/** 154/**
153 * cx_driver_register - Register the driver. 155 * cx_driver_register - Register the driver.
154 * @cx_driver: driver table (cx_drv struct) from driver 156 * @cx_driver: driver table (cx_drv struct) from driver
@@ -162,8 +164,6 @@ int cx_driver_register(struct cx_drv *cx_driver)
162{ 164{
163 cx_driver->driver.name = cx_driver->name; 165 cx_driver->driver.name = cx_driver->name;
164 cx_driver->driver.bus = &tiocx_bus_type; 166 cx_driver->driver.bus = &tiocx_bus_type;
165 cx_driver->driver.probe = cx_device_probe;
166 cx_driver->driver.remove = cx_driver_remove;
167 167
168 return driver_register(&cx_driver->driver); 168 return driver_register(&cx_driver->driver);
169} 169}
diff --git a/arch/ia64/sn/kernel/xpc_channel.c b/arch/ia64/sn/kernel/xpc_channel.c
index abf4fc2a87bb..0c0a68902409 100644
--- a/arch/ia64/sn/kernel/xpc_channel.c
+++ b/arch/ia64/sn/kernel/xpc_channel.c
@@ -3,7 +3,7 @@
3 * License. See the file "COPYING" in the main directory of this archive 3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details. 4 * for more details.
5 * 5 *
6 * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved. 6 * Copyright (c) 2004-2006 Silicon Graphics, Inc. All Rights Reserved.
7 */ 7 */
8 8
9 9
@@ -24,7 +24,7 @@
24#include <linux/slab.h> 24#include <linux/slab.h>
25#include <asm/sn/bte.h> 25#include <asm/sn/bte.h>
26#include <asm/sn/sn_sal.h> 26#include <asm/sn/sn_sal.h>
27#include "xpc.h" 27#include <asm/sn/xpc.h>
28 28
29 29
30/* 30/*
@@ -779,6 +779,12 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)
779 779
780 /* both sides are disconnected now */ 780 /* both sides are disconnected now */
781 781
782 if (ch->flags & XPC_C_CONNECTCALLOUT) {
783 spin_unlock_irqrestore(&ch->lock, *irq_flags);
784 xpc_disconnect_callout(ch, xpcDisconnected);
785 spin_lock_irqsave(&ch->lock, *irq_flags);
786 }
787
782 /* it's now safe to free the channel's message queues */ 788 /* it's now safe to free the channel's message queues */
783 xpc_free_msgqueues(ch); 789 xpc_free_msgqueues(ch);
784 790
@@ -1645,7 +1651,7 @@ xpc_disconnect_channel(const int line, struct xpc_channel *ch,
1645 1651
1646 1652
1647void 1653void
1648xpc_disconnecting_callout(struct xpc_channel *ch) 1654xpc_disconnect_callout(struct xpc_channel *ch, enum xpc_retval reason)
1649{ 1655{
1650 /* 1656 /*
1651 * Let the channel's registerer know that the channel is being 1657 * Let the channel's registerer know that the channel is being
@@ -1654,15 +1660,13 @@ xpc_disconnecting_callout(struct xpc_channel *ch)
1654 */ 1660 */
1655 1661
1656 if (ch->func != NULL) { 1662 if (ch->func != NULL) {
1657 dev_dbg(xpc_chan, "ch->func() called, reason=xpcDisconnecting," 1663 dev_dbg(xpc_chan, "ch->func() called, reason=%d, partid=%d, "
1658 " partid=%d, channel=%d\n", ch->partid, ch->number); 1664 "channel=%d\n", reason, ch->partid, ch->number);
1659 1665
1660 ch->func(xpcDisconnecting, ch->partid, ch->number, NULL, 1666 ch->func(reason, ch->partid, ch->number, NULL, ch->key);
1661 ch->key);
1662 1667
1663 dev_dbg(xpc_chan, "ch->func() returned, reason=" 1668 dev_dbg(xpc_chan, "ch->func() returned, reason=%d, partid=%d, "
1664 "xpcDisconnecting, partid=%d, channel=%d\n", 1669 "channel=%d\n", reason, ch->partid, ch->number);
1665 ch->partid, ch->number);
1666 } 1670 }
1667} 1671}
1668 1672
diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c
index b617236524c6..8930586e0eb4 100644
--- a/arch/ia64/sn/kernel/xpc_main.c
+++ b/arch/ia64/sn/kernel/xpc_main.c
@@ -3,7 +3,7 @@
3 * License. See the file "COPYING" in the main directory of this archive 3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details. 4 * for more details.
5 * 5 *
6 * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved. 6 * Copyright (c) 2004-2006 Silicon Graphics, Inc. All Rights Reserved.
7 */ 7 */
8 8
9 9
@@ -59,7 +59,7 @@
59#include <asm/sn/sn_sal.h> 59#include <asm/sn/sn_sal.h>
60#include <asm/kdebug.h> 60#include <asm/kdebug.h>
61#include <asm/uaccess.h> 61#include <asm/uaccess.h>
62#include "xpc.h" 62#include <asm/sn/xpc.h>
63 63
64 64
65/* define two XPC debug device structures to be used with dev_dbg() et al */ 65/* define two XPC debug device structures to be used with dev_dbg() et al */
@@ -82,6 +82,9 @@ struct device *xpc_part = &xpc_part_dbg_subname;
82struct device *xpc_chan = &xpc_chan_dbg_subname; 82struct device *xpc_chan = &xpc_chan_dbg_subname;
83 83
84 84
85static int xpc_kdebug_ignore;
86
87
85/* systune related variables for /proc/sys directories */ 88/* systune related variables for /proc/sys directories */
86 89
87static int xpc_hb_interval = XPC_HB_DEFAULT_INTERVAL; 90static int xpc_hb_interval = XPC_HB_DEFAULT_INTERVAL;
@@ -162,6 +165,8 @@ static ctl_table xpc_sys_dir[] = {
162}; 165};
163static struct ctl_table_header *xpc_sysctl; 166static struct ctl_table_header *xpc_sysctl;
164 167
168/* non-zero if any remote partition disengage request was timed out */
169int xpc_disengage_request_timedout;
165 170
166/* #of IRQs received */ 171/* #of IRQs received */
167static atomic_t xpc_act_IRQ_rcvd; 172static atomic_t xpc_act_IRQ_rcvd;
@@ -773,7 +778,7 @@ xpc_daemonize_kthread(void *args)
773 ch->flags |= XPC_C_DISCONNECTCALLOUT; 778 ch->flags |= XPC_C_DISCONNECTCALLOUT;
774 spin_unlock_irqrestore(&ch->lock, irq_flags); 779 spin_unlock_irqrestore(&ch->lock, irq_flags);
775 780
776 xpc_disconnecting_callout(ch); 781 xpc_disconnect_callout(ch, xpcDisconnecting);
777 } else { 782 } else {
778 spin_unlock_irqrestore(&ch->lock, irq_flags); 783 spin_unlock_irqrestore(&ch->lock, irq_flags);
779 } 784 }
@@ -921,9 +926,9 @@ static void
921xpc_do_exit(enum xpc_retval reason) 926xpc_do_exit(enum xpc_retval reason)
922{ 927{
923 partid_t partid; 928 partid_t partid;
924 int active_part_count; 929 int active_part_count, printed_waiting_msg = 0;
925 struct xpc_partition *part; 930 struct xpc_partition *part;
926 unsigned long printmsg_time; 931 unsigned long printmsg_time, disengage_request_timeout = 0;
927 932
928 933
929 /* a 'rmmod XPC' and a 'reboot' cannot both end up here together */ 934 /* a 'rmmod XPC' and a 'reboot' cannot both end up here together */
@@ -953,7 +958,8 @@ xpc_do_exit(enum xpc_retval reason)
953 958
954 /* wait for all partitions to become inactive */ 959 /* wait for all partitions to become inactive */
955 960
956 printmsg_time = jiffies; 961 printmsg_time = jiffies + (XPC_DISENGAGE_PRINTMSG_INTERVAL * HZ);
962 xpc_disengage_request_timedout = 0;
957 963
958 do { 964 do {
959 active_part_count = 0; 965 active_part_count = 0;
@@ -969,20 +975,39 @@ xpc_do_exit(enum xpc_retval reason)
969 active_part_count++; 975 active_part_count++;
970 976
971 XPC_DEACTIVATE_PARTITION(part, reason); 977 XPC_DEACTIVATE_PARTITION(part, reason);
972 }
973 978
974 if (active_part_count == 0) { 979 if (part->disengage_request_timeout >
975 break; 980 disengage_request_timeout) {
981 disengage_request_timeout =
982 part->disengage_request_timeout;
983 }
976 } 984 }
977 985
978 if (jiffies >= printmsg_time) { 986 if (xpc_partition_engaged(-1UL)) {
979 dev_info(xpc_part, "waiting for partitions to " 987 if (time_after(jiffies, printmsg_time)) {
980 "deactivate/disengage, active count=%d, remote " 988 dev_info(xpc_part, "waiting for remote "
981 "engaged=0x%lx\n", active_part_count, 989 "partitions to disengage, timeout in "
982 xpc_partition_engaged(1UL << partid)); 990 "%ld seconds\n",
983 991 (disengage_request_timeout - jiffies)
984 printmsg_time = jiffies + 992 / HZ);
993 printmsg_time = jiffies +
985 (XPC_DISENGAGE_PRINTMSG_INTERVAL * HZ); 994 (XPC_DISENGAGE_PRINTMSG_INTERVAL * HZ);
995 printed_waiting_msg = 1;
996 }
997
998 } else if (active_part_count > 0) {
999 if (printed_waiting_msg) {
1000 dev_info(xpc_part, "waiting for local partition"
1001 " to disengage\n");
1002 printed_waiting_msg = 0;
1003 }
1004
1005 } else {
1006 if (!xpc_disengage_request_timedout) {
1007 dev_info(xpc_part, "all partitions have "
1008 "disengaged\n");
1009 }
1010 break;
986 } 1011 }
987 1012
988 /* sleep for a 1/3 of a second or so */ 1013 /* sleep for a 1/3 of a second or so */
@@ -1000,11 +1025,13 @@ xpc_do_exit(enum xpc_retval reason)
1000 del_timer_sync(&xpc_hb_timer); 1025 del_timer_sync(&xpc_hb_timer);
1001 DBUG_ON(xpc_vars->heartbeating_to_mask != 0); 1026 DBUG_ON(xpc_vars->heartbeating_to_mask != 0);
1002 1027
1003 /* take ourselves off of the reboot_notifier_list */ 1028 if (reason == xpcUnloading) {
1004 (void) unregister_reboot_notifier(&xpc_reboot_notifier); 1029 /* take ourselves off of the reboot_notifier_list */
1030 (void) unregister_reboot_notifier(&xpc_reboot_notifier);
1005 1031
1006 /* take ourselves off of the die_notifier list */ 1032 /* take ourselves off of the die_notifier list */
1007 (void) unregister_die_notifier(&xpc_die_notifier); 1033 (void) unregister_die_notifier(&xpc_die_notifier);
1034 }
1008 1035
1009 /* close down protections for IPI operations */ 1036 /* close down protections for IPI operations */
1010 xpc_restrict_IPI_ops(); 1037 xpc_restrict_IPI_ops();
@@ -1020,7 +1047,35 @@ xpc_do_exit(enum xpc_retval reason)
1020 1047
1021 1048
1022/* 1049/*
1023 * Called when the system is about to be either restarted or halted. 1050 * This function is called when the system is being rebooted.
1051 */
1052static int
1053xpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused)
1054{
1055 enum xpc_retval reason;
1056
1057
1058 switch (event) {
1059 case SYS_RESTART:
1060 reason = xpcSystemReboot;
1061 break;
1062 case SYS_HALT:
1063 reason = xpcSystemHalt;
1064 break;
1065 case SYS_POWER_OFF:
1066 reason = xpcSystemPoweroff;
1067 break;
1068 default:
1069 reason = xpcSystemGoingDown;
1070 }
1071
1072 xpc_do_exit(reason);
1073 return NOTIFY_DONE;
1074}
1075
1076
1077/*
1078 * Notify other partitions to disengage from all references to our memory.
1024 */ 1079 */
1025static void 1080static void
1026xpc_die_disengage(void) 1081xpc_die_disengage(void)
@@ -1028,7 +1083,7 @@ xpc_die_disengage(void)
1028 struct xpc_partition *part; 1083 struct xpc_partition *part;
1029 partid_t partid; 1084 partid_t partid;
1030 unsigned long engaged; 1085 unsigned long engaged;
1031 long time, print_time, disengage_request_timeout; 1086 long time, printmsg_time, disengage_request_timeout;
1032 1087
1033 1088
1034 /* keep xpc_hb_checker thread from doing anything (just in case) */ 1089 /* keep xpc_hb_checker thread from doing anything (just in case) */
@@ -1055,57 +1110,53 @@ xpc_die_disengage(void)
1055 } 1110 }
1056 } 1111 }
1057 1112
1058 print_time = rtc_time(); 1113 time = rtc_time();
1059 disengage_request_timeout = print_time + 1114 printmsg_time = time +
1115 (XPC_DISENGAGE_PRINTMSG_INTERVAL * sn_rtc_cycles_per_second);
1116 disengage_request_timeout = time +
1060 (xpc_disengage_request_timelimit * sn_rtc_cycles_per_second); 1117 (xpc_disengage_request_timelimit * sn_rtc_cycles_per_second);
1061 1118
1062 /* wait for all other partitions to disengage from us */ 1119 /* wait for all other partitions to disengage from us */
1063 1120
1064 while ((engaged = xpc_partition_engaged(-1UL)) && 1121 while (1) {
1065 (time = rtc_time()) < disengage_request_timeout) { 1122 engaged = xpc_partition_engaged(-1UL);
1123 if (!engaged) {
1124 dev_info(xpc_part, "all partitions have disengaged\n");
1125 break;
1126 }
1066 1127
1067 if (time >= print_time) { 1128 time = rtc_time();
1129 if (time >= disengage_request_timeout) {
1130 for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
1131 if (engaged & (1UL << partid)) {
1132 dev_info(xpc_part, "disengage from "
1133 "remote partition %d timed "
1134 "out\n", partid);
1135 }
1136 }
1137 break;
1138 }
1139
1140 if (time >= printmsg_time) {
1068 dev_info(xpc_part, "waiting for remote partitions to " 1141 dev_info(xpc_part, "waiting for remote partitions to "
1069 "disengage, engaged=0x%lx\n", engaged); 1142 "disengage, timeout in %ld seconds\n",
1070 print_time = time + (XPC_DISENGAGE_PRINTMSG_INTERVAL * 1143 (disengage_request_timeout - time) /
1144 sn_rtc_cycles_per_second);
1145 printmsg_time = time +
1146 (XPC_DISENGAGE_PRINTMSG_INTERVAL *
1071 sn_rtc_cycles_per_second); 1147 sn_rtc_cycles_per_second);
1072 } 1148 }
1073 } 1149 }
1074 dev_info(xpc_part, "finished waiting for remote partitions to "
1075 "disengage, engaged=0x%lx\n", engaged);
1076}
1077
1078
1079/*
1080 * This function is called when the system is being rebooted.
1081 */
1082static int
1083xpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused)
1084{
1085 enum xpc_retval reason;
1086
1087
1088 switch (event) {
1089 case SYS_RESTART:
1090 reason = xpcSystemReboot;
1091 break;
1092 case SYS_HALT:
1093 reason = xpcSystemHalt;
1094 break;
1095 case SYS_POWER_OFF:
1096 reason = xpcSystemPoweroff;
1097 break;
1098 default:
1099 reason = xpcSystemGoingDown;
1100 }
1101
1102 xpc_do_exit(reason);
1103 return NOTIFY_DONE;
1104} 1150}
1105 1151
1106 1152
1107/* 1153/*
1108 * This function is called when the system is being rebooted. 1154 * This function is called when the system is being restarted or halted due
1155 * to some sort of system failure. If this is the case we need to notify the
1156 * other partitions to disengage from all references to our memory.
1157 * This function can also be called when our heartbeater could be offlined
1158 * for a time. In this case we need to notify other partitions to not worry
1159 * about the lack of a heartbeat.
1109 */ 1160 */
1110static int 1161static int
1111xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused) 1162xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused)
@@ -1115,11 +1166,25 @@ xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused)
1115 case DIE_MACHINE_HALT: 1166 case DIE_MACHINE_HALT:
1116 xpc_die_disengage(); 1167 xpc_die_disengage();
1117 break; 1168 break;
1169
1170 case DIE_KDEBUG_ENTER:
1171 /* Should lack of heartbeat be ignored by other partitions? */
1172 if (!xpc_kdebug_ignore) {
1173 break;
1174 }
1175 /* fall through */
1118 case DIE_MCA_MONARCH_ENTER: 1176 case DIE_MCA_MONARCH_ENTER:
1119 case DIE_INIT_MONARCH_ENTER: 1177 case DIE_INIT_MONARCH_ENTER:
1120 xpc_vars->heartbeat++; 1178 xpc_vars->heartbeat++;
1121 xpc_vars->heartbeat_offline = 1; 1179 xpc_vars->heartbeat_offline = 1;
1122 break; 1180 break;
1181
1182 case DIE_KDEBUG_LEAVE:
1183 /* Is lack of heartbeat being ignored by other partitions? */
1184 if (!xpc_kdebug_ignore) {
1185 break;
1186 }
1187 /* fall through */
1123 case DIE_MCA_MONARCH_LEAVE: 1188 case DIE_MCA_MONARCH_LEAVE:
1124 case DIE_INIT_MONARCH_LEAVE: 1189 case DIE_INIT_MONARCH_LEAVE:
1125 xpc_vars->heartbeat++; 1190 xpc_vars->heartbeat++;
@@ -1344,3 +1409,7 @@ module_param(xpc_disengage_request_timelimit, int, 0);
1344MODULE_PARM_DESC(xpc_disengage_request_timelimit, "Number of seconds to wait " 1409MODULE_PARM_DESC(xpc_disengage_request_timelimit, "Number of seconds to wait "
1345 "for disengage request to complete."); 1410 "for disengage request to complete.");
1346 1411
1412module_param(xpc_kdebug_ignore, int, 0);
1413MODULE_PARM_DESC(xpc_kdebug_ignore, "Should lack of heartbeat be ignored by "
1414 "other partitions when dropping into kdebug.");
1415
diff --git a/arch/ia64/sn/kernel/xpc_partition.c b/arch/ia64/sn/kernel/xpc_partition.c
index cdd6431853a1..88a730e6cfdb 100644
--- a/arch/ia64/sn/kernel/xpc_partition.c
+++ b/arch/ia64/sn/kernel/xpc_partition.c
@@ -3,7 +3,7 @@
3 * License. See the file "COPYING" in the main directory of this archive 3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details. 4 * for more details.
5 * 5 *
6 * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved. 6 * Copyright (c) 2004-2006 Silicon Graphics, Inc. All Rights Reserved.
7 */ 7 */
8 8
9 9
@@ -28,7 +28,7 @@
28#include <asm/sn/sn_sal.h> 28#include <asm/sn/sn_sal.h>
29#include <asm/sn/nodepda.h> 29#include <asm/sn/nodepda.h>
30#include <asm/sn/addrs.h> 30#include <asm/sn/addrs.h>
31#include "xpc.h" 31#include <asm/sn/xpc.h>
32 32
33 33
34/* XPC is exiting flag */ 34/* XPC is exiting flag */
@@ -771,7 +771,8 @@ xpc_identify_act_IRQ_req(int nasid)
771 } 771 }
772 } 772 }
773 773
774 if (!xpc_partition_disengaged(part)) { 774 if (part->disengage_request_timeout > 0 &&
775 !xpc_partition_disengaged(part)) {
775 /* still waiting on other side to disengage from us */ 776 /* still waiting on other side to disengage from us */
776 return; 777 return;
777 } 778 }
@@ -873,6 +874,9 @@ xpc_partition_disengaged(struct xpc_partition *part)
873 * request in a timely fashion, so assume it's dead. 874 * request in a timely fashion, so assume it's dead.
874 */ 875 */
875 876
877 dev_info(xpc_part, "disengage from remote partition %d "
878 "timed out\n", partid);
879 xpc_disengage_request_timedout = 1;
876 xpc_clear_partition_engaged(1UL << partid); 880 xpc_clear_partition_engaged(1UL << partid);
877 disengaged = 1; 881 disengaged = 1;
878 } 882 }
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_dma.c b/arch/ia64/sn/pci/pcibr/pcibr_dma.c
index 34093476e965..e68332d93171 100644
--- a/arch/ia64/sn/pci/pcibr/pcibr_dma.c
+++ b/arch/ia64/sn/pci/pcibr/pcibr_dma.c
@@ -218,7 +218,9 @@ void sn_dma_flush(uint64_t addr)
218 uint64_t flags; 218 uint64_t flags;
219 uint64_t itte; 219 uint64_t itte;
220 struct hubdev_info *hubinfo; 220 struct hubdev_info *hubinfo;
221 volatile struct sn_flush_device_list *p; 221 volatile struct sn_flush_device_kernel *p;
222 volatile struct sn_flush_device_common *common;
223
222 struct sn_flush_nasid_entry *flush_nasid_list; 224 struct sn_flush_nasid_entry *flush_nasid_list;
223 225
224 if (!sn_ioif_inited) 226 if (!sn_ioif_inited)
@@ -268,17 +270,17 @@ void sn_dma_flush(uint64_t addr)
268 p = &flush_nasid_list->widget_p[wid_num][0]; 270 p = &flush_nasid_list->widget_p[wid_num][0];
269 271
270 /* find a matching BAR */ 272 /* find a matching BAR */
271 for (i = 0; i < DEV_PER_WIDGET; i++) { 273 for (i = 0; i < DEV_PER_WIDGET; i++,p++) {
274 common = p->common;
272 for (j = 0; j < PCI_ROM_RESOURCE; j++) { 275 for (j = 0; j < PCI_ROM_RESOURCE; j++) {
273 if (p->sfdl_bar_list[j].start == 0) 276 if (common->sfdl_bar_list[j].start == 0)
274 break; 277 break;
275 if (addr >= p->sfdl_bar_list[j].start 278 if (addr >= common->sfdl_bar_list[j].start
276 && addr <= p->sfdl_bar_list[j].end) 279 && addr <= common->sfdl_bar_list[j].end)
277 break; 280 break;
278 } 281 }
279 if (j < PCI_ROM_RESOURCE && p->sfdl_bar_list[j].start != 0) 282 if (j < PCI_ROM_RESOURCE && common->sfdl_bar_list[j].start != 0)
280 break; 283 break;
281 p++;
282 } 284 }
283 285
284 /* if no matching BAR, return without doing anything. */ 286 /* if no matching BAR, return without doing anything. */
@@ -304,24 +306,24 @@ void sn_dma_flush(uint64_t addr)
304 if ((1 << XWIDGET_PART_REV_NUM_REV(revnum)) & PV907516) { 306 if ((1 << XWIDGET_PART_REV_NUM_REV(revnum)) & PV907516) {
305 return; 307 return;
306 } else { 308 } else {
307 pcireg_wrb_flush_get(p->sfdl_pcibus_info, 309 pcireg_wrb_flush_get(common->sfdl_pcibus_info,
308 (p->sfdl_slot - 1)); 310 (common->sfdl_slot - 1));
309 } 311 }
310 } else { 312 } else {
311 spin_lock_irqsave(&((struct sn_flush_device_list *)p)-> 313 spin_lock_irqsave((spinlock_t *)&p->sfdl_flush_lock,
312 sfdl_flush_lock, flags); 314 flags);
313 315 *common->sfdl_flush_addr = 0;
314 *p->sfdl_flush_addr = 0;
315 316
316 /* force an interrupt. */ 317 /* force an interrupt. */
317 *(volatile uint32_t *)(p->sfdl_force_int_addr) = 1; 318 *(volatile uint32_t *)(common->sfdl_force_int_addr) = 1;
318 319
319 /* wait for the interrupt to come back. */ 320 /* wait for the interrupt to come back. */
320 while (*(p->sfdl_flush_addr) != 0x10f) 321 while (*(common->sfdl_flush_addr) != 0x10f)
321 cpu_relax(); 322 cpu_relax();
322 323
323 /* okay, everything is synched up. */ 324 /* okay, everything is synched up. */
324 spin_unlock_irqrestore((spinlock_t *)&p->sfdl_flush_lock, flags); 325 spin_unlock_irqrestore((spinlock_t *)&p->sfdl_flush_lock,
326 flags);
325 } 327 }
326 return; 328 return;
327} 329}
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c
index 1f500c81002c..e328e948175d 100644
--- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c
+++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c
@@ -92,7 +92,8 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
92 cnodeid_t near_cnode; 92 cnodeid_t near_cnode;
93 struct hubdev_info *hubdev_info; 93 struct hubdev_info *hubdev_info;
94 struct pcibus_info *soft; 94 struct pcibus_info *soft;
95 struct sn_flush_device_list *sn_flush_device_list; 95 struct sn_flush_device_kernel *sn_flush_device_kernel;
96 struct sn_flush_device_common *common;
96 97
97 if (! IS_PCI_BRIDGE_ASIC(prom_bussoft->bs_asic_type)) { 98 if (! IS_PCI_BRIDGE_ASIC(prom_bussoft->bs_asic_type)) {
98 return NULL; 99 return NULL;
@@ -137,20 +138,19 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
137 hubdev_info = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo); 138 hubdev_info = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo);
138 139
139 if (hubdev_info->hdi_flush_nasid_list.widget_p) { 140 if (hubdev_info->hdi_flush_nasid_list.widget_p) {
140 sn_flush_device_list = hubdev_info->hdi_flush_nasid_list. 141 sn_flush_device_kernel = hubdev_info->hdi_flush_nasid_list.
141 widget_p[(int)soft->pbi_buscommon.bs_xid]; 142 widget_p[(int)soft->pbi_buscommon.bs_xid];
142 if (sn_flush_device_list) { 143 if (sn_flush_device_kernel) {
143 for (j = 0; j < DEV_PER_WIDGET; 144 for (j = 0; j < DEV_PER_WIDGET;
144 j++, sn_flush_device_list++) { 145 j++, sn_flush_device_kernel++) {
145 if (sn_flush_device_list->sfdl_slot == -1) 146 common = sn_flush_device_kernel->common;
147 if (common->sfdl_slot == -1)
146 continue; 148 continue;
147 if ((sn_flush_device_list-> 149 if ((common->sfdl_persistent_segment ==
148 sfdl_persistent_segment ==
149 soft->pbi_buscommon.bs_persist_segment) && 150 soft->pbi_buscommon.bs_persist_segment) &&
150 (sn_flush_device_list-> 151 (common->sfdl_persistent_busnum ==
151 sfdl_persistent_busnum ==
152 soft->pbi_buscommon.bs_persist_busnum)) 152 soft->pbi_buscommon.bs_persist_busnum))
153 sn_flush_device_list->sfdl_pcibus_info = 153 common->sfdl_pcibus_info =
154 soft; 154 soft;
155 } 155 }
156 } 156 }
diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c
index 1eaa0d37f677..2d804e2d16d1 100644
--- a/arch/parisc/kernel/drivers.c
+++ b/arch/parisc/kernel/drivers.c
@@ -173,8 +173,6 @@ int register_parisc_driver(struct parisc_driver *driver)
173 WARN_ON(driver->drv.probe != NULL); 173 WARN_ON(driver->drv.probe != NULL);
174 WARN_ON(driver->drv.remove != NULL); 174 WARN_ON(driver->drv.remove != NULL);
175 175
176 driver->drv.probe = parisc_driver_probe;
177 driver->drv.remove = parisc_driver_remove;
178 driver->drv.name = driver->name; 176 driver->drv.name = driver->name;
179 177
180 return driver_register(&driver->drv); 178 return driver_register(&driver->drv);
@@ -575,6 +573,8 @@ struct bus_type parisc_bus_type = {
575 .name = "parisc", 573 .name = "parisc",
576 .match = parisc_generic_match, 574 .match = parisc_generic_match,
577 .dev_attrs = parisc_device_attrs, 575 .dev_attrs = parisc_device_attrs,
576 .probe = parisc_driver_probe,
577 .remove = parisc_driver_remove,
578}; 578};
579 579
580/** 580/**
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index d3654a264ef7..44dd82b791d1 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -139,17 +139,14 @@ drivers-$(CONFIG_CPM2) += arch/ppc/8260_io/
139 139
140drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/ 140drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/
141 141
142defaultimage-$(CONFIG_PPC32) := zImage 142# Default to zImage, override when needed
143defaultimage-y := zImage
143defaultimage-$(CONFIG_PPC_ISERIES) := vmlinux 144defaultimage-$(CONFIG_PPC_ISERIES) := vmlinux
144defaultimage-$(CONFIG_PPC_PSERIES) := zImage
145KBUILD_IMAGE := $(defaultimage-y) 145KBUILD_IMAGE := $(defaultimage-y)
146all: $(KBUILD_IMAGE) 146all: $(KBUILD_IMAGE)
147 147
148CPPFLAGS_vmlinux.lds := -Upowerpc 148CPPFLAGS_vmlinux.lds := -Upowerpc
149 149
150# All the instructions talk about "make bzImage".
151bzImage: zImage
152
153BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm uImage 150BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm uImage
154 151
155.PHONY: $(BOOT_TARGETS) 152.PHONY: $(BOOT_TARGETS)
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index b53d677f6742..788dec4c7ef3 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -25,8 +25,8 @@ HOSTCC := gcc
25BOOTCFLAGS := $(HOSTCFLAGS) -fno-builtin -nostdinc -isystem \ 25BOOTCFLAGS := $(HOSTCFLAGS) -fno-builtin -nostdinc -isystem \
26 $(shell $(CROSS32CC) -print-file-name=include) -fPIC 26 $(shell $(CROSS32CC) -print-file-name=include) -fPIC
27BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc 27BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc
28BOOTLFLAGS := -T $(srctree)/$(src)/zImage.lds
29OBJCOPYFLAGS := contents,alloc,load,readonly,data 28OBJCOPYFLAGS := contents,alloc,load,readonly,data
29OBJCOPY_COFF_ARGS := -O aixcoff-rs6000 --set-start 0x500000
30 30
31zlib := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c 31zlib := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c
32zlibheader := infblock.h infcodes.h inffast.h inftrees.h infutil.h 32zlibheader := infblock.h infcodes.h inffast.h inftrees.h infutil.h
@@ -35,7 +35,7 @@ zliblinuxheader := zlib.h zconf.h zutil.h
35$(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader)) 35$(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
36#$(addprefix $(obj)/,main.o): $(addprefix $(obj)/,zlib.h) 36#$(addprefix $(obj)/,main.o): $(addprefix $(obj)/,zlib.h)
37 37
38src-boot := string.S prom.c main.c div64.S crt0.S 38src-boot := crt0.S string.S prom.c stdio.c main.c div64.S
39src-boot += $(zlib) 39src-boot += $(zlib)
40src-boot := $(addprefix $(obj)/, $(src-boot)) 40src-boot := $(addprefix $(obj)/, $(src-boot))
41obj-boot := $(addsuffix .o, $(basename $(src-boot))) 41obj-boot := $(addsuffix .o, $(basename $(src-boot)))
@@ -70,7 +70,7 @@ quiet_cmd_bootas = BOOTAS $@
70 cmd_bootas = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTAFLAGS) -c -o $@ $< 70 cmd_bootas = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTAFLAGS) -c -o $@ $<
71 71
72quiet_cmd_bootld = BOOTLD $@ 72quiet_cmd_bootld = BOOTLD $@
73 cmd_bootld = $(CROSS32LD) $(BOOTLFLAGS) -o $@ $(2) 73 cmd_bootld = $(CROSS32LD) -T $(srctree)/$(src)/$(3) -o $@ $(2)
74 74
75$(patsubst %.c,%.o, $(filter %.c, $(src-boot))): %.o: %.c 75$(patsubst %.c,%.o, $(filter %.c, $(src-boot))): %.o: %.c
76 $(call if_changed_dep,bootcc) 76 $(call if_changed_dep,bootcc)
@@ -87,12 +87,14 @@ obj-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.o, $(section)))
87src-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.c, $(section))) 87src-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.c, $(section)))
88gz-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.gz, $(section))) 88gz-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.gz, $(section)))
89 89
90hostprogs-y := addnote addRamDisk 90hostprogs-y := addnote addRamDisk hack-coff
91targets += zImage.vmode zImage.initrd.vmode zImage zImage.initrd \ 91
92 $(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \ 92targets += zImage.vmode zImage.initrd.vmode zImage zImage.initrd \
93 $(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \ 93 zImage.coff zImage.initrd.coff \
94 $(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \ 94 $(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \
95 vmlinux.initrd 95 $(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \
96 $(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \
97 vmlinux.initrd
96extra-y := initrd.o 98extra-y := initrd.o
97 99
98quiet_cmd_ramdisk = RAMDISK $@ 100quiet_cmd_ramdisk = RAMDISK $@
@@ -114,6 +116,10 @@ quiet_cmd_addsection = ADDSEC $@
114quiet_cmd_addnote = ADDNOTE $@ 116quiet_cmd_addnote = ADDNOTE $@
115 cmd_addnote = $(obj)/addnote $@ 117 cmd_addnote = $(obj)/addnote $@
116 118
119quiet_cmd_gencoff = COFF $@
120 cmd_gencoff = $(OBJCOPY) $(OBJCOPY_COFF_ARGS) $@ && \
121 $(obj)/hack-coff $@
122
117$(call gz-sec, $(required)): $(obj)/kernel-%.gz: % 123$(call gz-sec, $(required)): $(obj)/kernel-%.gz: %
118 $(call if_changed,gzip) 124 $(call if_changed,gzip)
119 125
@@ -127,22 +133,35 @@ $(call obj-sec, $(required) $(initrd)): $(obj)/kernel-%.o: $(obj)/kernel-%.c
127 $(call if_changed_dep,bootcc) 133 $(call if_changed_dep,bootcc)
128 $(call cmd,addsection) 134 $(call cmd,addsection)
129 135
130$(obj)/zImage.vmode: obj-boot += $(call obj-sec, $(required)) 136$(obj)/zImage.vmode $(obj)/zImage.coff: obj-boot += $(call obj-sec, $(required))
131$(obj)/zImage.vmode: $(call obj-sec, $(required)) $(obj-boot) $(srctree)/$(src)/zImage.lds 137$(obj)/zImage.vmode: $(call obj-sec, $(required)) $(obj-boot) $(srctree)/$(src)/zImage.lds
132 $(call cmd,bootld,$(obj-boot)) 138 $(call cmd,bootld,$(obj-boot),zImage.lds)
133 139
134$(obj)/zImage.initrd.vmode: obj-boot += $(call obj-sec, $(required) $(initrd)) 140$(obj)/zImage.initrd.vmode $(obj)/zImage.initrd.coff: obj-boot += $(call obj-sec, $(required) $(initrd))
135$(obj)/zImage.initrd.vmode: $(call obj-sec, $(required) $(initrd)) $(obj-boot) $(srctree)/$(src)/zImage.lds 141$(obj)/zImage.initrd.vmode: $(call obj-sec, $(required) $(initrd)) $(obj-boot) $(srctree)/$(src)/zImage.lds
136 $(call cmd,bootld,$(obj-boot)) 142 $(call cmd,bootld,$(obj-boot),zImage.lds)
143
144# For 32-bit powermacs, build the COFF images as well as the ELF images.
145coffimage-$(CONFIG_PPC_PMAC)-$(CONFIG_PPC32) := $(obj)/zImage.coff
146coffrdimg-$(CONFIG_PPC_PMAC)-$(CONFIG_PPC32) := $(obj)/zImage.initrd.coff
137 147
138$(obj)/zImage: $(obj)/zImage.vmode $(obj)/addnote 148$(obj)/zImage: $(obj)/zImage.vmode $(obj)/addnote $(coffimage-y-y)
139 @cp -f $< $@ 149 @cp -f $< $@
140 $(call if_changed,addnote) 150 $(call if_changed,addnote)
141 151
142$(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/addnote 152$(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/addnote $(coffrdimg-y-y)
143 @cp -f $< $@ 153 @cp -f $< $@
144 $(call if_changed,addnote) 154 $(call if_changed,addnote)
145 155
156$(obj)/zImage.coff: $(call obj-sec, $(required)) $(obj-boot) $(srctree)/$(src)/zImage.coff.lds $(obj)/hack-coff
157 $(call cmd,bootld,$(obj-boot),zImage.coff.lds)
158 $(call cmd,gencoff)
159
160$(obj)/zImage.initrd.coff: $(call obj-sec, $(required) $(initrd)) $(obj-boot) \
161 $(srctree)/$(src)/zImage.coff.lds $(obj)/hack-coff
162 $(call cmd,bootld,$(obj-boot),zImage.coff.lds)
163 $(call cmd,gencoff)
164
146#----------------------------------------------------------- 165#-----------------------------------------------------------
147# build u-boot images 166# build u-boot images
148#----------------------------------------------------------- 167#-----------------------------------------------------------
diff --git a/arch/powerpc/boot/crt0.S b/arch/powerpc/boot/crt0.S
index d2f2ace56cd3..e0192c26037b 100644
--- a/arch/powerpc/boot/crt0.S
+++ b/arch/powerpc/boot/crt0.S
@@ -12,17 +12,23 @@
12#include "ppc_asm.h" 12#include "ppc_asm.h"
13 13
14 .text 14 .text
15 /* a procedure descriptor used when booting this as a COFF file */
16_zimage_start_opd:
17 .long _zimage_start, 0, 0, 0
18
15 .globl _zimage_start 19 .globl _zimage_start
16_zimage_start: 20_zimage_start:
21 /* Work out the offset between the address we were linked at
22 and the address where we're running. */
17 bl 1f 23 bl 1f
18 241: mflr r0
191:
20 mflr r0
21 lis r9,1b@ha 25 lis r9,1b@ha
22 addi r9,r9,1b@l 26 addi r9,r9,1b@l
23 subf. r0,r9,r0 27 subf. r0,r9,r0
24 beq 3f 28 beq 3f /* if running at same address as linked */
25 29
30 /* The .got2 section contains a list of addresses, so add
31 the address offset onto each entry. */
26 lis r9,__got2_start@ha 32 lis r9,__got2_start@ha
27 addi r9,r9,__got2_start@l 33 addi r9,r9,__got2_start@l
28 lis r8,__got2_end@ha 34 lis r8,__got2_end@ha
@@ -32,15 +38,14 @@ _zimage_start:
32 srwi. r8,r8,2 38 srwi. r8,r8,2
33 mtctr r8 39 mtctr r8
34 add r9,r0,r9 40 add r9,r0,r9
352: 412: lwz r8,0(r9)
36 lwz r8,0(r9)
37 add r8,r8,r0 42 add r8,r8,r0
38 stw r8,0(r9) 43 stw r8,0(r9)
39 addi r9,r9,4 44 addi r9,r9,4
40 bdnz 2b 45 bdnz 2b
41 46
423: 47 /* Do a cache flush for our text, in case OF didn't */
43 lis r9,_start@h 483: lis r9,_start@h
44 add r9,r0,r9 49 add r9,r0,r9
45 lis r8,_etext@ha 50 lis r8,_etext@ha
46 addi r8,r8,_etext@l 51 addi r8,r8,_etext@l
diff --git a/arch/powerpc/boot/hack-coff.c b/arch/powerpc/boot/hack-coff.c
new file mode 100644
index 000000000000..5e5a6573a1ef
--- /dev/null
+++ b/arch/powerpc/boot/hack-coff.c
@@ -0,0 +1,84 @@
1/*
2 * hack-coff.c - hack the header of an xcoff file to fill in
3 * a few fields needed by the Open Firmware xcoff loader on
4 * Power Macs but not initialized by objcopy.
5 *
6 * Copyright (C) Paul Mackerras 1997.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 */
13#include <stdio.h>
14#include <stdlib.h>
15#include <unistd.h>
16#include <fcntl.h>
17#include <string.h>
18#include "rs6000.h"
19
20#define AOUT_MAGIC 0x010b
21
22#define get_16be(x) ((((unsigned char *)(x))[0] << 8) \
23 + ((unsigned char *)(x))[1])
24#define put_16be(x, v) (((unsigned char *)(x))[0] = (v) >> 8, \
25 ((unsigned char *)(x))[1] = (v) & 0xff)
26#define get_32be(x) ((((unsigned char *)(x))[0] << 24) \
27 + (((unsigned char *)(x))[1] << 16) \
28 + (((unsigned char *)(x))[2] << 8) \
29 + ((unsigned char *)(x))[3])
30
31int
32main(int ac, char **av)
33{
34 int fd;
35 int i, nsect;
36 int aoutsz;
37 struct external_filehdr fhdr;
38 AOUTHDR aout;
39 struct external_scnhdr shdr;
40
41 if (ac != 2) {
42 fprintf(stderr, "Usage: hack-coff coff-file\n");
43 exit(1);
44 }
45 if ((fd = open(av[1], 2)) == -1) {
46 perror(av[2]);
47 exit(1);
48 }
49 if (read(fd, &fhdr, sizeof(fhdr)) != sizeof(fhdr))
50 goto readerr;
51 i = get_16be(fhdr.f_magic);
52 if (i != U802TOCMAGIC && i != U802WRMAGIC && i != U802ROMAGIC) {
53 fprintf(stderr, "%s: not an xcoff file\n", av[1]);
54 exit(1);
55 }
56 aoutsz = get_16be(fhdr.f_opthdr);
57 if (read(fd, &aout, aoutsz) != aoutsz)
58 goto readerr;
59 nsect = get_16be(fhdr.f_nscns);
60 for (i = 0; i < nsect; ++i) {
61 if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr))
62 goto readerr;
63 if (strcmp(shdr.s_name, ".text") == 0) {
64 put_16be(aout.o_snentry, i+1);
65 put_16be(aout.o_sntext, i+1);
66 } else if (strcmp(shdr.s_name, ".data") == 0) {
67 put_16be(aout.o_sndata, i+1);
68 } else if (strcmp(shdr.s_name, ".bss") == 0) {
69 put_16be(aout.o_snbss, i+1);
70 }
71 }
72 put_16be(aout.magic, AOUT_MAGIC);
73 if (lseek(fd, (long) sizeof(struct external_filehdr), 0) == -1
74 || write(fd, &aout, aoutsz) != aoutsz) {
75 fprintf(stderr, "%s: write error\n", av[1]);
76 exit(1);
77 }
78 close(fd);
79 exit(0);
80
81readerr:
82 fprintf(stderr, "%s: read error or file too short\n", av[1]);
83 exit(1);
84}
diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c
index 64ec93116fa6..55ec59867250 100644
--- a/arch/powerpc/boot/main.c
+++ b/arch/powerpc/boot/main.c
@@ -21,8 +21,8 @@ extern void flush_cache(void *, unsigned long);
21 21
22 22
23/* Value picked to match that used by yaboot */ 23/* Value picked to match that used by yaboot */
24#define PROG_START 0x01400000 24#define PROG_START 0x01400000 /* only used on 64-bit systems */
25#define RAM_END (512<<20) // Fixme: use OF */ 25#define RAM_END (512<<20) /* Fixme: use OF */
26#define ONE_MB 0x100000 26#define ONE_MB 0x100000
27 27
28extern char _start[]; 28extern char _start[];
@@ -160,6 +160,17 @@ static int is_elf64(void *hdr)
160 elfoffset = (unsigned long)elf64ph->p_offset; 160 elfoffset = (unsigned long)elf64ph->p_offset;
161 vmlinux.size = (unsigned long)elf64ph->p_filesz + elfoffset; 161 vmlinux.size = (unsigned long)elf64ph->p_filesz + elfoffset;
162 vmlinux.memsize = (unsigned long)elf64ph->p_memsz + elfoffset; 162 vmlinux.memsize = (unsigned long)elf64ph->p_memsz + elfoffset;
163
164#if defined(PROG_START)
165 /*
166 * Maintain a "magic" minimum address. This keeps some older
167 * firmware platforms running.
168 */
169
170 if (claim_base < PROG_START)
171 claim_base = PROG_START;
172#endif
173
163 return 1; 174 return 1;
164} 175}
165 176
@@ -206,12 +217,18 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
206 exit(); 217 exit();
207 if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4) 218 if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4)
208 exit(); 219 exit();
209 stderr = stdout;
210 if (getprop(chosen_handle, "stdin", &stdin, sizeof(stdin)) != 4)
211 exit();
212 220
213 printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start, sp); 221 printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start, sp);
214 222
223 /*
224 * The first available claim_base must be above the end of the
225 * the loaded kernel wrapper file (_start to _end includes the
226 * initrd image if it is present) and rounded up to a nice
227 * 1 MB boundary for good measure.
228 */
229
230 claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB);
231
215 vmlinuz.addr = (unsigned long)_vmlinux_start; 232 vmlinuz.addr = (unsigned long)_vmlinux_start;
216 vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start); 233 vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start);
217 234
@@ -228,25 +245,6 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
228 exit(); 245 exit();
229 } 246 }
230 247
231 /*
232 * The first available claim_base must be above the end of the
233 * the loaded kernel wrapper file (_start to _end includes the
234 * initrd image if it is present) and rounded up to a nice
235 * 1 MB boundary for good measure.
236 */
237
238 claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB);
239
240#if defined(PROG_START)
241 /*
242 * Maintain a "magic" minimum address. This keeps some older
243 * firmware platforms running.
244 */
245
246 if (claim_base < PROG_START)
247 claim_base = PROG_START;
248#endif
249
250 /* We need to claim the memsize plus the file offset since gzip 248 /* We need to claim the memsize plus the file offset since gzip
251 * will expand the header (file offset), then the kernel, then 249 * will expand the header (file offset), then the kernel, then
252 * possible rubbish we don't care about. But the kernel bss must 250 * possible rubbish we don't care about. But the kernel bss must
diff --git a/arch/powerpc/boot/prom.c b/arch/powerpc/boot/prom.c
index 4bea2f4dcb06..fa0057736f6b 100644
--- a/arch/powerpc/boot/prom.c
+++ b/arch/powerpc/boot/prom.c
@@ -13,487 +13,153 @@
13#include "prom.h" 13#include "prom.h"
14 14
15int (*prom)(void *); 15int (*prom)(void *);
16phandle chosen_handle;
17ihandle stdout;
16 18
17void *chosen_handle; 19int call_prom(const char *service, int nargs, int nret, ...)
18
19void *stdin;
20void *stdout;
21void *stderr;
22
23
24int
25write(void *handle, void *ptr, int nb)
26{
27 struct prom_args {
28 char *service;
29 int nargs;
30 int nret;
31 void *ihandle;
32 void *addr;
33 int len;
34 int actual;
35 } args;
36
37 args.service = "write";
38 args.nargs = 3;
39 args.nret = 1;
40 args.ihandle = handle;
41 args.addr = ptr;
42 args.len = nb;
43 args.actual = -1;
44 (*prom)(&args);
45 return args.actual;
46}
47
48int
49read(void *handle, void *ptr, int nb)
50{ 20{
21 int i;
51 struct prom_args { 22 struct prom_args {
52 char *service; 23 const char *service;
53 int nargs; 24 int nargs;
54 int nret; 25 int nret;
55 void *ihandle; 26 unsigned int args[12];
56 void *addr;
57 int len;
58 int actual;
59 } args;
60
61 args.service = "read";
62 args.nargs = 3;
63 args.nret = 1;
64 args.ihandle = handle;
65 args.addr = ptr;
66 args.len = nb;
67 args.actual = -1;
68 (*prom)(&args);
69 return args.actual;
70}
71
72void
73exit()
74{
75 struct prom_args {
76 char *service;
77 } args;
78
79 for (;;) {
80 args.service = "exit";
81 (*prom)(&args);
82 }
83}
84
85void
86pause(void)
87{
88 struct prom_args {
89 char *service;
90 } args; 27 } args;
28 va_list list;
91 29
92 args.service = "enter"; 30 args.service = service;
93 (*prom)(&args); 31 args.nargs = nargs;
94} 32 args.nret = nret;
95 33
96void * 34 va_start(list, nret);
97finddevice(const char *name) 35 for (i = 0; i < nargs; i++)
98{ 36 args.args[i] = va_arg(list, unsigned int);
99 struct prom_args { 37 va_end(list);
100 char *service;
101 int nargs;
102 int nret;
103 const char *devspec;
104 void *phandle;
105 } args;
106 38
107 args.service = "finddevice"; 39 for (i = 0; i < nret; i++)
108 args.nargs = 1; 40 args.args[nargs+i] = 0;
109 args.nret = 1;
110 args.devspec = name;
111 args.phandle = (void *) -1;
112 (*prom)(&args);
113 return args.phandle;
114}
115 41
116void * 42 if (prom(&args) < 0)
117claim(unsigned long virt, unsigned long size, unsigned long align) 43 return -1;
118{
119 struct prom_args {
120 char *service;
121 int nargs;
122 int nret;
123 unsigned int virt;
124 unsigned int size;
125 unsigned int align;
126 void *ret;
127 } args;
128 44
129 args.service = "claim"; 45 return (nret > 0)? args.args[nargs]: 0;
130 args.nargs = 3;
131 args.nret = 1;
132 args.virt = virt;
133 args.size = size;
134 args.align = align;
135 (*prom)(&args);
136 return args.ret;
137} 46}
138 47
139int 48int call_prom_ret(const char *service, int nargs, int nret,
140getprop(void *phandle, const char *name, void *buf, int buflen) 49 unsigned int *rets, ...)
141{ 50{
51 int i;
142 struct prom_args { 52 struct prom_args {
143 char *service; 53 const char *service;
144 int nargs; 54 int nargs;
145 int nret; 55 int nret;
146 void *phandle; 56 unsigned int args[12];
147 const char *name;
148 void *buf;
149 int buflen;
150 int size;
151 } args; 57 } args;
58 va_list list;
152 59
153 args.service = "getprop"; 60 args.service = service;
154 args.nargs = 4; 61 args.nargs = nargs;
155 args.nret = 1; 62 args.nret = nret;
156 args.phandle = phandle;
157 args.name = name;
158 args.buf = buf;
159 args.buflen = buflen;
160 args.size = -1;
161 (*prom)(&args);
162 return args.size;
163}
164 63
165int 64 va_start(list, rets);
166putc(int c, void *f) 65 for (i = 0; i < nargs; i++)
167{ 66 args.args[i] = va_arg(list, unsigned int);
168 char ch = c; 67 va_end(list);
169 68
170 if (c == '\n') 69 for (i = 0; i < nret; i++)
171 putc('\r', f); 70 args.args[nargs+i] = 0;
172 return write(f, &ch, 1) == 1? c: -1;
173}
174 71
175int 72 if (prom(&args) < 0)
176putchar(int c) 73 return -1;
177{
178 return putc(c, stdout);
179}
180 74
181int 75 if (rets != (void *) 0)
182fputs(char *str, void *f) 76 for (i = 1; i < nret; ++i)
183{ 77 rets[i-1] = args.args[nargs+i];
184 int n = strlen(str);
185 78
186 return write(f, str, n) == n? 0: -1; 79 return (nret > 0)? args.args[nargs]: 0;
187} 80}
188 81
189size_t strnlen(const char * s, size_t count) 82int write(void *handle, void *ptr, int nb)
190{ 83{
191 const char *sc; 84 return call_prom("write", 3, 1, handle, ptr, nb);
192
193 for (sc = s; count-- && *sc != '\0'; ++sc)
194 /* nothing */;
195 return sc - s;
196} 85}
197 86
198extern unsigned int __div64_32(unsigned long long *dividend, 87/*
199 unsigned int divisor); 88 * Older OF's require that when claiming a specific range of addresses,
200 89 * we claim the physical space in the /memory node and the virtual
201/* The unnecessary pointer compare is there 90 * space in the chosen mmu node, and then do a map operation to
202 * to check for type safety (n must be 64bit) 91 * map virtual to physical.
203 */ 92 */
204# define do_div(n,base) ({ \ 93static int need_map = -1;
205 unsigned int __base = (base); \ 94static ihandle chosen_mmu;
206 unsigned int __rem; \ 95static phandle memory;
207 (void)(((typeof((n)) *)0) == ((unsigned long long *)0)); \
208 if (((n) >> 32) == 0) { \
209 __rem = (unsigned int)(n) % __base; \
210 (n) = (unsigned int)(n) / __base; \
211 } else \
212 __rem = __div64_32(&(n), __base); \
213 __rem; \
214 })
215 96
216static int skip_atoi(const char **s) 97/* returns true if s2 is a prefix of s1 */
98static int string_match(const char *s1, const char *s2)
217{ 99{
218 int i, c; 100 for (; *s2; ++s2)
219 101 if (*s1++ != *s2)
220 for (i = 0; '0' <= (c = **s) && c <= '9'; ++*s) 102 return 0;
221 i = i*10 + c - '0'; 103 return 1;
222 return i;
223} 104}
224 105
225#define ZEROPAD 1 /* pad with zero */ 106static int check_of_version(void)
226#define SIGN 2 /* unsigned/signed long */
227#define PLUS 4 /* show plus */
228#define SPACE 8 /* space if plus */
229#define LEFT 16 /* left justified */
230#define SPECIAL 32 /* 0x */
231#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
232
233static char * number(char * str, unsigned long long num, int base, int size, int precision, int type)
234{ 107{
235 char c,sign,tmp[66]; 108 phandle oprom, chosen;
236 const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; 109 char version[64];
237 int i;
238 110
239 if (type & LARGE) 111 oprom = finddevice("/openprom");
240 digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 112 if (oprom == (phandle) -1)
241 if (type & LEFT)
242 type &= ~ZEROPAD;
243 if (base < 2 || base > 36)
244 return 0; 113 return 0;
245 c = (type & ZEROPAD) ? '0' : ' '; 114 if (getprop(oprom, "model", version, sizeof(version)) <= 0)
246 sign = 0; 115 return 0;
247 if (type & SIGN) { 116 version[sizeof(version)-1] = 0;
248 if ((signed long long)num < 0) { 117 printf("OF version = '%s'\r\n", version);
249 sign = '-'; 118 if (!string_match(version, "Open Firmware, 1.")
250 num = - (signed long long)num; 119 && !string_match(version, "FirmWorks,3."))
251 size--; 120 return 0;
252 } else if (type & PLUS) { 121 chosen = finddevice("/chosen");
253 sign = '+'; 122 if (chosen == (phandle) -1) {
254 size--; 123 chosen = finddevice("/chosen@0");
255 } else if (type & SPACE) { 124 if (chosen == (phandle) -1) {
256 sign = ' '; 125 printf("no chosen\n");
257 size--; 126 return 0;
258 } 127 }
259 } 128 }
260 if (type & SPECIAL) { 129 if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) {
261 if (base == 16) 130 printf("no mmu\n");
262 size -= 2; 131 return 0;
263 else if (base == 8)
264 size--;
265 }
266 i = 0;
267 if (num == 0)
268 tmp[i++]='0';
269 else while (num != 0) {
270 tmp[i++] = digits[do_div(num, base)];
271 } 132 }
272 if (i > precision) 133 memory = (ihandle) call_prom("open", 1, 1, "/memory");
273 precision = i; 134 if (memory == (ihandle) -1) {
274 size -= precision; 135 memory = (ihandle) call_prom("open", 1, 1, "/memory@0");
275 if (!(type&(ZEROPAD+LEFT))) 136 if (memory == (ihandle) -1) {
276 while(size-->0) 137 printf("no memory node\n");
277 *str++ = ' '; 138 return 0;
278 if (sign)
279 *str++ = sign;
280 if (type & SPECIAL) {
281 if (base==8)
282 *str++ = '0';
283 else if (base==16) {
284 *str++ = '0';
285 *str++ = digits[33];
286 } 139 }
287 } 140 }
288 if (!(type & LEFT)) 141 printf("old OF detected\r\n");
289 while (size-- > 0) 142 return 1;
290 *str++ = c;
291 while (i < precision--)
292 *str++ = '0';
293 while (i-- > 0)
294 *str++ = tmp[i];
295 while (size-- > 0)
296 *str++ = ' ';
297 return str;
298} 143}
299 144
300int vsprintf(char *buf, const char *fmt, va_list args) 145void *claim(unsigned long virt, unsigned long size, unsigned long align)
301{ 146{
302 int len; 147 int ret;
303 unsigned long long num; 148 unsigned int result;
304 int i, base;
305 char * str;
306 const char *s;
307
308 int flags; /* flags to number() */
309
310 int field_width; /* width of output field */
311 int precision; /* min. # of digits for integers; max
312 number of chars for from string */
313 int qualifier; /* 'h', 'l', or 'L' for integer fields */
314 /* 'z' support added 23/7/1999 S.H. */
315 /* 'z' changed to 'Z' --davidm 1/25/99 */
316 149
150 if (need_map < 0)
151 need_map = check_of_version();
152 if (align || !need_map)
153 return (void *) call_prom("claim", 3, 1, virt, size, align);
317 154
318 for (str=buf ; *fmt ; ++fmt) { 155 ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory,
319 if (*fmt != '%') { 156 align, size, virt);
320 *str++ = *fmt; 157 if (ret != 0 || result == -1)
321 continue; 158 return (void *) -1;
322 } 159 ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu,
323 160 align, size, virt);
324 /* process flags */ 161 /* 0x12 == coherent + read/write */
325 flags = 0; 162 ret = call_prom("call-method", 6, 1, "map", chosen_mmu,
326 repeat: 163 0x12, size, virt, virt);
327 ++fmt; /* this also skips first '%' */ 164 return (void *) virt;
328 switch (*fmt) {
329 case '-': flags |= LEFT; goto repeat;
330 case '+': flags |= PLUS; goto repeat;
331 case ' ': flags |= SPACE; goto repeat;
332 case '#': flags |= SPECIAL; goto repeat;
333 case '0': flags |= ZEROPAD; goto repeat;
334 }
335
336 /* get field width */
337 field_width = -1;
338 if ('0' <= *fmt && *fmt <= '9')
339 field_width = skip_atoi(&fmt);
340 else if (*fmt == '*') {
341 ++fmt;
342 /* it's the next argument */
343 field_width = va_arg(args, int);
344 if (field_width < 0) {
345 field_width = -field_width;
346 flags |= LEFT;
347 }
348 }
349
350 /* get the precision */
351 precision = -1;
352 if (*fmt == '.') {
353 ++fmt;
354 if ('0' <= *fmt && *fmt <= '9')
355 precision = skip_atoi(&fmt);
356 else if (*fmt == '*') {
357 ++fmt;
358 /* it's the next argument */
359 precision = va_arg(args, int);
360 }
361 if (precision < 0)
362 precision = 0;
363 }
364
365 /* get the conversion qualifier */
366 qualifier = -1;
367 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') {
368 qualifier = *fmt;
369 ++fmt;
370 }
371
372 /* default base */
373 base = 10;
374
375 switch (*fmt) {
376 case 'c':
377 if (!(flags & LEFT))
378 while (--field_width > 0)
379 *str++ = ' ';
380 *str++ = (unsigned char) va_arg(args, int);
381 while (--field_width > 0)
382 *str++ = ' ';
383 continue;
384
385 case 's':
386 s = va_arg(args, char *);
387 if (!s)
388 s = "<NULL>";
389
390 len = strnlen(s, precision);
391
392 if (!(flags & LEFT))
393 while (len < field_width--)
394 *str++ = ' ';
395 for (i = 0; i < len; ++i)
396 *str++ = *s++;
397 while (len < field_width--)
398 *str++ = ' ';
399 continue;
400
401 case 'p':
402 if (field_width == -1) {
403 field_width = 2*sizeof(void *);
404 flags |= ZEROPAD;
405 }
406 str = number(str,
407 (unsigned long) va_arg(args, void *), 16,
408 field_width, precision, flags);
409 continue;
410
411
412 case 'n':
413 if (qualifier == 'l') {
414 long * ip = va_arg(args, long *);
415 *ip = (str - buf);
416 } else if (qualifier == 'Z') {
417 size_t * ip = va_arg(args, size_t *);
418 *ip = (str - buf);
419 } else {
420 int * ip = va_arg(args, int *);
421 *ip = (str - buf);
422 }
423 continue;
424
425 case '%':
426 *str++ = '%';
427 continue;
428
429 /* integer number formats - set up the flags and "break" */
430 case 'o':
431 base = 8;
432 break;
433
434 case 'X':
435 flags |= LARGE;
436 case 'x':
437 base = 16;
438 break;
439
440 case 'd':
441 case 'i':
442 flags |= SIGN;
443 case 'u':
444 break;
445
446 default:
447 *str++ = '%';
448 if (*fmt)
449 *str++ = *fmt;
450 else
451 --fmt;
452 continue;
453 }
454 if (qualifier == 'l') {
455 num = va_arg(args, unsigned long);
456 if (flags & SIGN)
457 num = (signed long) num;
458 } else if (qualifier == 'Z') {
459 num = va_arg(args, size_t);
460 } else if (qualifier == 'h') {
461 num = (unsigned short) va_arg(args, int);
462 if (flags & SIGN)
463 num = (signed short) num;
464 } else {
465 num = va_arg(args, unsigned int);
466 if (flags & SIGN)
467 num = (signed int) num;
468 }
469 str = number(str, num, base, field_width, precision, flags);
470 }
471 *str = '\0';
472 return str-buf;
473}
474
475int sprintf(char * buf, const char *fmt, ...)
476{
477 va_list args;
478 int i;
479
480 va_start(args, fmt);
481 i=vsprintf(buf,fmt,args);
482 va_end(args);
483 return i;
484}
485
486static char sprint_buf[1024];
487
488int
489printf(const char *fmt, ...)
490{
491 va_list args;
492 int n;
493
494 va_start(args, fmt);
495 n = vsprintf(sprint_buf, fmt, args);
496 va_end(args);
497 write(stdout, sprint_buf, n);
498 return n;
499} 165}
diff --git a/arch/powerpc/boot/prom.h b/arch/powerpc/boot/prom.h
index 96ab5aec740c..3e2ddd4a5a81 100644
--- a/arch/powerpc/boot/prom.h
+++ b/arch/powerpc/boot/prom.h
@@ -1,18 +1,34 @@
1#ifndef _PPC_BOOT_PROM_H_ 1#ifndef _PPC_BOOT_PROM_H_
2#define _PPC_BOOT_PROM_H_ 2#define _PPC_BOOT_PROM_H_
3 3
4typedef void *phandle;
5typedef void *ihandle;
6
4extern int (*prom) (void *); 7extern int (*prom) (void *);
5extern void *chosen_handle; 8extern phandle chosen_handle;
9extern ihandle stdout;
6 10
7extern void *stdin; 11int call_prom(const char *service, int nargs, int nret, ...);
8extern void *stdout; 12int call_prom_ret(const char *service, int nargs, int nret,
9extern void *stderr; 13 unsigned int *rets, ...);
10 14
11extern int write(void *handle, void *ptr, int nb); 15extern int write(void *handle, void *ptr, int nb);
12extern int read(void *handle, void *ptr, int nb); 16extern void *claim(unsigned long virt, unsigned long size, unsigned long aln);
13extern void exit(void); 17
14extern void pause(void); 18static inline void exit(void)
15extern void *finddevice(const char *); 19{
16extern void *claim(unsigned long virt, unsigned long size, unsigned long align); 20 call_prom("exit", 0, 0);
17extern int getprop(void *phandle, const char *name, void *buf, int buflen); 21}
22
23static inline phandle finddevice(const char *name)
24{
25 return (phandle) call_prom("finddevice", 1, 1, name);
26}
27
28static inline int getprop(void *phandle, const char *name,
29 void *buf, int buflen)
30{
31 return call_prom("getprop", 4, 1, phandle, name, buf, buflen);
32}
33
18#endif /* _PPC_BOOT_PROM_H_ */ 34#endif /* _PPC_BOOT_PROM_H_ */
diff --git a/arch/powerpc/boot/rs6000.h b/arch/powerpc/boot/rs6000.h
new file mode 100644
index 000000000000..433f45084e41
--- /dev/null
+++ b/arch/powerpc/boot/rs6000.h
@@ -0,0 +1,243 @@
1/* IBM RS/6000 "XCOFF" file definitions for BFD.
2 Copyright (C) 1990, 1991 Free Software Foundation, Inc.
3 FIXME: Can someone provide a transliteration of this name into ASCII?
4 Using the following chars caused a compiler warning on HIUX (so I replaced
5 them with octal escapes), and isn't useful without an understanding of what
6 character set it is.
7 Written by Mimi Ph\373\364ng-Th\345o V\365 of IBM
8 and John Gilmore of Cygnus Support. */
9
10/********************** FILE HEADER **********************/
11
12struct external_filehdr {
13 char f_magic[2]; /* magic number */
14 char f_nscns[2]; /* number of sections */
15 char f_timdat[4]; /* time & date stamp */
16 char f_symptr[4]; /* file pointer to symtab */
17 char f_nsyms[4]; /* number of symtab entries */
18 char f_opthdr[2]; /* sizeof(optional hdr) */
19 char f_flags[2]; /* flags */
20};
21
22 /* IBM RS/6000 */
23#define U802WRMAGIC 0730 /* writeable text segments **chh** */
24#define U802ROMAGIC 0735 /* readonly sharable text segments */
25#define U802TOCMAGIC 0737 /* readonly text segments and TOC */
26
27#define BADMAG(x) \
28 ((x).f_magic != U802ROMAGIC && (x).f_magic != U802WRMAGIC && \
29 (x).f_magic != U802TOCMAGIC)
30
31#define FILHDR struct external_filehdr
32#define FILHSZ 20
33
34
35/********************** AOUT "OPTIONAL HEADER" **********************/
36
37
38typedef struct
39{
40 unsigned char magic[2]; /* type of file */
41 unsigned char vstamp[2]; /* version stamp */
42 unsigned char tsize[4]; /* text size in bytes, padded to FW bdry */
43 unsigned char dsize[4]; /* initialized data " " */
44 unsigned char bsize[4]; /* uninitialized data " " */
45 unsigned char entry[4]; /* entry pt. */
46 unsigned char text_start[4]; /* base of text used for this file */
47 unsigned char data_start[4]; /* base of data used for this file */
48 unsigned char o_toc[4]; /* address of TOC */
49 unsigned char o_snentry[2]; /* section number of entry point */
50 unsigned char o_sntext[2]; /* section number of .text section */
51 unsigned char o_sndata[2]; /* section number of .data section */
52 unsigned char o_sntoc[2]; /* section number of TOC */
53 unsigned char o_snloader[2]; /* section number of .loader section */
54 unsigned char o_snbss[2]; /* section number of .bss section */
55 unsigned char o_algntext[2]; /* .text alignment */
56 unsigned char o_algndata[2]; /* .data alignment */
57 unsigned char o_modtype[2]; /* module type (??) */
58 unsigned char o_cputype[2]; /* cpu type */
59 unsigned char o_maxstack[4]; /* max stack size (??) */
60 unsigned char o_maxdata[4]; /* max data size (??) */
61 unsigned char o_resv2[12]; /* reserved */
62}
63AOUTHDR;
64
65#define AOUTSZ 72
66#define SMALL_AOUTSZ (28)
67#define AOUTHDRSZ 72
68
69#define RS6K_AOUTHDR_OMAGIC 0x0107 /* old: text & data writeable */
70#define RS6K_AOUTHDR_NMAGIC 0x0108 /* new: text r/o, data r/w */
71#define RS6K_AOUTHDR_ZMAGIC 0x010B /* paged: text r/o, both page-aligned */
72
73
74/********************** SECTION HEADER **********************/
75
76
77struct external_scnhdr {
78 char s_name[8]; /* section name */
79 char s_paddr[4]; /* physical address, aliased s_nlib */
80 char s_vaddr[4]; /* virtual address */
81 char s_size[4]; /* section size */
82 char s_scnptr[4]; /* file ptr to raw data for section */
83 char s_relptr[4]; /* file ptr to relocation */
84 char s_lnnoptr[4]; /* file ptr to line numbers */
85 char s_nreloc[2]; /* number of relocation entries */
86 char s_nlnno[2]; /* number of line number entries*/
87 char s_flags[4]; /* flags */
88};
89
90/*
91 * names of "special" sections
92 */
93#define _TEXT ".text"
94#define _DATA ".data"
95#define _BSS ".bss"
96#define _PAD ".pad"
97#define _LOADER ".loader"
98
99#define SCNHDR struct external_scnhdr
100#define SCNHSZ 40
101
102/* XCOFF uses a special .loader section with type STYP_LOADER. */
103#define STYP_LOADER 0x1000
104
105/* XCOFF uses a special .debug section with type STYP_DEBUG. */
106#define STYP_DEBUG 0x2000
107
108/* XCOFF handles line number or relocation overflow by creating
109 another section header with STYP_OVRFLO set. */
110#define STYP_OVRFLO 0x8000
111
112/********************** LINE NUMBERS **********************/
113
114/* 1 line number entry for every "breakpointable" source line in a section.
115 * Line numbers are grouped on a per function basis; first entry in a function
116 * grouping will have l_lnno = 0 and in place of physical address will be the
117 * symbol table index of the function name.
118 */
119struct external_lineno {
120 union {
121 char l_symndx[4]; /* function name symbol index, iff l_lnno == 0*/
122 char l_paddr[4]; /* (physical) address of line number */
123 } l_addr;
124 char l_lnno[2]; /* line number */
125};
126
127
128#define LINENO struct external_lineno
129#define LINESZ 6
130
131
132/********************** SYMBOLS **********************/
133
134#define E_SYMNMLEN 8 /* # characters in a symbol name */
135#define E_FILNMLEN 14 /* # characters in a file name */
136#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */
137
138struct external_syment
139{
140 union {
141 char e_name[E_SYMNMLEN];
142 struct {
143 char e_zeroes[4];
144 char e_offset[4];
145 } e;
146 } e;
147 char e_value[4];
148 char e_scnum[2];
149 char e_type[2];
150 char e_sclass[1];
151 char e_numaux[1];
152};
153
154
155
156#define N_BTMASK (017)
157#define N_TMASK (060)
158#define N_BTSHFT (4)
159#define N_TSHIFT (2)
160
161
162union external_auxent {
163 struct {
164 char x_tagndx[4]; /* str, un, or enum tag indx */
165 union {
166 struct {
167 char x_lnno[2]; /* declaration line number */
168 char x_size[2]; /* str/union/array size */
169 } x_lnsz;
170 char x_fsize[4]; /* size of function */
171 } x_misc;
172 union {
173 struct { /* if ISFCN, tag, or .bb */
174 char x_lnnoptr[4]; /* ptr to fcn line # */
175 char x_endndx[4]; /* entry ndx past block end */
176 } x_fcn;
177 struct { /* if ISARY, up to 4 dimen. */
178 char x_dimen[E_DIMNUM][2];
179 } x_ary;
180 } x_fcnary;
181 char x_tvndx[2]; /* tv index */
182 } x_sym;
183
184 union {
185 char x_fname[E_FILNMLEN];
186 struct {
187 char x_zeroes[4];
188 char x_offset[4];
189 } x_n;
190 } x_file;
191
192 struct {
193 char x_scnlen[4]; /* section length */
194 char x_nreloc[2]; /* # relocation entries */
195 char x_nlinno[2]; /* # line numbers */
196 } x_scn;
197
198 struct {
199 char x_tvfill[4]; /* tv fill value */
200 char x_tvlen[2]; /* length of .tv */
201 char x_tvran[2][2]; /* tv range */
202 } x_tv; /* info about .tv section (in auxent of symbol .tv)) */
203
204 struct {
205 unsigned char x_scnlen[4];
206 unsigned char x_parmhash[4];
207 unsigned char x_snhash[2];
208 unsigned char x_smtyp[1];
209 unsigned char x_smclas[1];
210 unsigned char x_stab[4];
211 unsigned char x_snstab[2];
212 } x_csect;
213
214};
215
216#define SYMENT struct external_syment
217#define SYMESZ 18
218#define AUXENT union external_auxent
219#define AUXESZ 18
220#define DBXMASK 0x80 /* for dbx storage mask */
221#define SYMNAME_IN_DEBUG(symptr) ((symptr)->n_sclass & DBXMASK)
222
223
224
225/********************** RELOCATION DIRECTIVES **********************/
226
227
228struct external_reloc {
229 char r_vaddr[4];
230 char r_symndx[4];
231 char r_size[1];
232 char r_type[1];
233};
234
235
236#define RELOC struct external_reloc
237#define RELSZ 10
238
239#define DEFAULT_DATA_SECTION_ALIGNMENT 4
240#define DEFAULT_BSS_SECTION_ALIGNMENT 4
241#define DEFAULT_TEXT_SECTION_ALIGNMENT 4
242/* For new sections we havn't heard of before */
243#define DEFAULT_SECTION_ALIGNMENT 4
diff --git a/arch/powerpc/boot/stdio.c b/arch/powerpc/boot/stdio.c
new file mode 100644
index 000000000000..b5aa522f8b77
--- /dev/null
+++ b/arch/powerpc/boot/stdio.c
@@ -0,0 +1,325 @@
1/*
2 * Copyright (C) Paul Mackerras 1997.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9#include <stdarg.h>
10#include <stddef.h>
11#include "string.h"
12#include "stdio.h"
13#include "prom.h"
14
15size_t strnlen(const char * s, size_t count)
16{
17 const char *sc;
18
19 for (sc = s; count-- && *sc != '\0'; ++sc)
20 /* nothing */;
21 return sc - s;
22}
23
24extern unsigned int __div64_32(unsigned long long *dividend,
25 unsigned int divisor);
26
27/* The unnecessary pointer compare is there
28 * to check for type safety (n must be 64bit)
29 */
30# define do_div(n,base) ({ \
31 unsigned int __base = (base); \
32 unsigned int __rem; \
33 (void)(((typeof((n)) *)0) == ((unsigned long long *)0)); \
34 if (((n) >> 32) == 0) { \
35 __rem = (unsigned int)(n) % __base; \
36 (n) = (unsigned int)(n) / __base; \
37 } else \
38 __rem = __div64_32(&(n), __base); \
39 __rem; \
40 })
41
42static int skip_atoi(const char **s)
43{
44 int i, c;
45
46 for (i = 0; '0' <= (c = **s) && c <= '9'; ++*s)
47 i = i*10 + c - '0';
48 return i;
49}
50
51#define ZEROPAD 1 /* pad with zero */
52#define SIGN 2 /* unsigned/signed long */
53#define PLUS 4 /* show plus */
54#define SPACE 8 /* space if plus */
55#define LEFT 16 /* left justified */
56#define SPECIAL 32 /* 0x */
57#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
58
59static char * number(char * str, unsigned long long num, int base, int size, int precision, int type)
60{
61 char c,sign,tmp[66];
62 const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
63 int i;
64
65 if (type & LARGE)
66 digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
67 if (type & LEFT)
68 type &= ~ZEROPAD;
69 if (base < 2 || base > 36)
70 return 0;
71 c = (type & ZEROPAD) ? '0' : ' ';
72 sign = 0;
73 if (type & SIGN) {
74 if ((signed long long)num < 0) {
75 sign = '-';
76 num = - (signed long long)num;
77 size--;
78 } else if (type & PLUS) {
79 sign = '+';
80 size--;
81 } else if (type & SPACE) {
82 sign = ' ';
83 size--;
84 }
85 }
86 if (type & SPECIAL) {
87 if (base == 16)
88 size -= 2;
89 else if (base == 8)
90 size--;
91 }
92 i = 0;
93 if (num == 0)
94 tmp[i++]='0';
95 else while (num != 0) {
96 tmp[i++] = digits[do_div(num, base)];
97 }
98 if (i > precision)
99 precision = i;
100 size -= precision;
101 if (!(type&(ZEROPAD+LEFT)))
102 while(size-->0)
103 *str++ = ' ';
104 if (sign)
105 *str++ = sign;
106 if (type & SPECIAL) {
107 if (base==8)
108 *str++ = '0';
109 else if (base==16) {
110 *str++ = '0';
111 *str++ = digits[33];
112 }
113 }
114 if (!(type & LEFT))
115 while (size-- > 0)
116 *str++ = c;
117 while (i < precision--)
118 *str++ = '0';
119 while (i-- > 0)
120 *str++ = tmp[i];
121 while (size-- > 0)
122 *str++ = ' ';
123 return str;
124}
125
126int vsprintf(char *buf, const char *fmt, va_list args)
127{
128 int len;
129 unsigned long long num;
130 int i, base;
131 char * str;
132 const char *s;
133
134 int flags; /* flags to number() */
135
136 int field_width; /* width of output field */
137 int precision; /* min. # of digits for integers; max
138 number of chars for from string */
139 int qualifier; /* 'h', 'l', or 'L' for integer fields */
140 /* 'z' support added 23/7/1999 S.H. */
141 /* 'z' changed to 'Z' --davidm 1/25/99 */
142
143
144 for (str=buf ; *fmt ; ++fmt) {
145 if (*fmt != '%') {
146 *str++ = *fmt;
147 continue;
148 }
149
150 /* process flags */
151 flags = 0;
152 repeat:
153 ++fmt; /* this also skips first '%' */
154 switch (*fmt) {
155 case '-': flags |= LEFT; goto repeat;
156 case '+': flags |= PLUS; goto repeat;
157 case ' ': flags |= SPACE; goto repeat;
158 case '#': flags |= SPECIAL; goto repeat;
159 case '0': flags |= ZEROPAD; goto repeat;
160 }
161
162 /* get field width */
163 field_width = -1;
164 if ('0' <= *fmt && *fmt <= '9')
165 field_width = skip_atoi(&fmt);
166 else if (*fmt == '*') {
167 ++fmt;
168 /* it's the next argument */
169 field_width = va_arg(args, int);
170 if (field_width < 0) {
171 field_width = -field_width;
172 flags |= LEFT;
173 }
174 }
175
176 /* get the precision */
177 precision = -1;
178 if (*fmt == '.') {
179 ++fmt;
180 if ('0' <= *fmt && *fmt <= '9')
181 precision = skip_atoi(&fmt);
182 else if (*fmt == '*') {
183 ++fmt;
184 /* it's the next argument */
185 precision = va_arg(args, int);
186 }
187 if (precision < 0)
188 precision = 0;
189 }
190
191 /* get the conversion qualifier */
192 qualifier = -1;
193 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') {
194 qualifier = *fmt;
195 ++fmt;
196 }
197
198 /* default base */
199 base = 10;
200
201 switch (*fmt) {
202 case 'c':
203 if (!(flags & LEFT))
204 while (--field_width > 0)
205 *str++ = ' ';
206 *str++ = (unsigned char) va_arg(args, int);
207 while (--field_width > 0)
208 *str++ = ' ';
209 continue;
210
211 case 's':
212 s = va_arg(args, char *);
213 if (!s)
214 s = "<NULL>";
215
216 len = strnlen(s, precision);
217
218 if (!(flags & LEFT))
219 while (len < field_width--)
220 *str++ = ' ';
221 for (i = 0; i < len; ++i)
222 *str++ = *s++;
223 while (len < field_width--)
224 *str++ = ' ';
225 continue;
226
227 case 'p':
228 if (field_width == -1) {
229 field_width = 2*sizeof(void *);
230 flags |= ZEROPAD;
231 }
232 str = number(str,
233 (unsigned long) va_arg(args, void *), 16,
234 field_width, precision, flags);
235 continue;
236
237
238 case 'n':
239 if (qualifier == 'l') {
240 long * ip = va_arg(args, long *);
241 *ip = (str - buf);
242 } else if (qualifier == 'Z') {
243 size_t * ip = va_arg(args, size_t *);
244 *ip = (str - buf);
245 } else {
246 int * ip = va_arg(args, int *);
247 *ip = (str - buf);
248 }
249 continue;
250
251 case '%':
252 *str++ = '%';
253 continue;
254
255 /* integer number formats - set up the flags and "break" */
256 case 'o':
257 base = 8;
258 break;
259
260 case 'X':
261 flags |= LARGE;
262 case 'x':
263 base = 16;
264 break;
265
266 case 'd':
267 case 'i':
268 flags |= SIGN;
269 case 'u':
270 break;
271
272 default:
273 *str++ = '%';
274 if (*fmt)
275 *str++ = *fmt;
276 else
277 --fmt;
278 continue;
279 }
280 if (qualifier == 'l') {
281 num = va_arg(args, unsigned long);
282 if (flags & SIGN)
283 num = (signed long) num;
284 } else if (qualifier == 'Z') {
285 num = va_arg(args, size_t);
286 } else if (qualifier == 'h') {
287 num = (unsigned short) va_arg(args, int);
288 if (flags & SIGN)
289 num = (signed short) num;
290 } else {
291 num = va_arg(args, unsigned int);
292 if (flags & SIGN)
293 num = (signed int) num;
294 }
295 str = number(str, num, base, field_width, precision, flags);
296 }
297 *str = '\0';
298 return str-buf;
299}
300
301int sprintf(char * buf, const char *fmt, ...)
302{
303 va_list args;
304 int i;
305
306 va_start(args, fmt);
307 i=vsprintf(buf,fmt,args);
308 va_end(args);
309 return i;
310}
311
312static char sprint_buf[1024];
313
314int
315printf(const char *fmt, ...)
316{
317 va_list args;
318 int n;
319
320 va_start(args, fmt);
321 n = vsprintf(sprint_buf, fmt, args);
322 va_end(args);
323 write(stdout, sprint_buf, n);
324 return n;
325}
diff --git a/arch/powerpc/boot/stdio.h b/arch/powerpc/boot/stdio.h
index 24bd3a8dee94..eb9e16c87aef 100644
--- a/arch/powerpc/boot/stdio.h
+++ b/arch/powerpc/boot/stdio.h
@@ -7,10 +7,4 @@ extern int sprintf(char *buf, const char *fmt, ...);
7 7
8extern int vsprintf(char *buf, const char *fmt, va_list args); 8extern int vsprintf(char *buf, const char *fmt, va_list args);
9 9
10extern int putc(int c, void *f);
11extern int putchar(int c);
12extern int getchar(void);
13
14extern int fputs(char *str, void *f);
15
16#endif /* _PPC_BOOT_STDIO_H_ */ 10#endif /* _PPC_BOOT_STDIO_H_ */
diff --git a/arch/powerpc/boot/string.S b/arch/powerpc/boot/string.S
index b1eeaed7db17..ac3d43b6a324 100644
--- a/arch/powerpc/boot/string.S
+++ b/arch/powerpc/boot/string.S
@@ -107,10 +107,12 @@ memcpy:
107 rlwinm. r7,r5,32-3,3,31 /* r7 = r5 >> 3 */ 107 rlwinm. r7,r5,32-3,3,31 /* r7 = r5 >> 3 */
108 addi r6,r3,-4 108 addi r6,r3,-4
109 addi r4,r4,-4 109 addi r4,r4,-4
110 beq 2f /* if less than 8 bytes to do */ 110 beq 3f /* if less than 8 bytes to do */
111 andi. r0,r6,3 /* get dest word aligned */ 111 andi. r0,r6,3 /* get dest word aligned */
112 mtctr r7 112 mtctr r7
113 bne 5f 113 bne 5f
114 andi. r0,r4,3 /* check src word aligned too */
115 bne 3f
1141: lwz r7,4(r4) 1161: lwz r7,4(r4)
115 lwzu r8,8(r4) 117 lwzu r8,8(r4)
116 stw r7,4(r6) 118 stw r7,4(r6)
@@ -132,6 +134,11 @@ memcpy:
132 bdnz 4b 134 bdnz 4b
133 blr 135 blr
1345: subfic r0,r0,4 1365: subfic r0,r0,4
137 cmpw cr1,r0,r5
138 add r7,r0,r4
139 andi. r7,r7,3 /* will source be word-aligned too? */
140 ble cr1,3b
141 bne 3b /* do byte-by-byte if not */
135 mtctr r0 142 mtctr r0
1366: lbz r7,4(r4) 1436: lbz r7,4(r4)
137 addi r4,r4,1 144 addi r4,r4,1
@@ -149,10 +156,12 @@ backwards_memcpy:
149 rlwinm. r7,r5,32-3,3,31 /* r7 = r5 >> 3 */ 156 rlwinm. r7,r5,32-3,3,31 /* r7 = r5 >> 3 */
150 add r6,r3,r5 157 add r6,r3,r5
151 add r4,r4,r5 158 add r4,r4,r5
152 beq 2f 159 beq 3f
153 andi. r0,r6,3 160 andi. r0,r6,3
154 mtctr r7 161 mtctr r7
155 bne 5f 162 bne 5f
163 andi. r0,r4,3
164 bne 3f
1561: lwz r7,-4(r4) 1651: lwz r7,-4(r4)
157 lwzu r8,-8(r4) 166 lwzu r8,-8(r4)
158 stw r7,-4(r6) 167 stw r7,-4(r6)
@@ -171,7 +180,12 @@ backwards_memcpy:
171 stbu r0,-1(r6) 180 stbu r0,-1(r6)
172 bdnz 4b 181 bdnz 4b
173 blr 182 blr
1745: mtctr r0 1835: cmpw cr1,r0,r5
184 subf r7,r0,r4
185 andi. r7,r7,3
186 ble cr1,3b
187 bne 3b
188 mtctr r0
1756: lbzu r7,-1(r4) 1896: lbzu r7,-1(r4)
176 stbu r7,-1(r6) 190 stbu r7,-1(r6)
177 bdnz 6b 191 bdnz 6b
diff --git a/arch/powerpc/boot/zImage.coff.lds b/arch/powerpc/boot/zImage.coff.lds
new file mode 100644
index 000000000000..6016251a1a2c
--- /dev/null
+++ b/arch/powerpc/boot/zImage.coff.lds
@@ -0,0 +1,46 @@
1OUTPUT_ARCH(powerpc:common)
2ENTRY(_start)
3SECTIONS
4{
5 . = (5*1024*1024);
6 _start = .;
7 .text :
8 {
9 *(.text)
10 *(.fixup)
11 }
12 _etext = .;
13 . = ALIGN(4096);
14 .data :
15 {
16 *(.rodata*)
17 *(.data*)
18 *(.sdata*)
19 __got2_start = .;
20 *(.got2)
21 __got2_end = .;
22
23 _vmlinux_start = .;
24 *(.kernel:vmlinux.strip)
25 _vmlinux_end = .;
26
27 _initrd_start = .;
28 *(.kernel:initrd)
29 _initrd_end = .;
30 }
31
32 . = ALIGN(4096);
33 _edata = .;
34 __bss_start = .;
35 .bss :
36 {
37 *(.sbss)
38 *(.bss)
39 }
40 _end = . ;
41
42 /DISCARD/ :
43 {
44 *(.comment)
45 }
46}
diff --git a/arch/powerpc/configs/mpc834x_sys_defconfig b/arch/powerpc/configs/mpc834x_sys_defconfig
new file mode 100644
index 000000000000..3bff761965c2
--- /dev/null
+++ b/arch/powerpc/configs/mpc834x_sys_defconfig
@@ -0,0 +1,911 @@
1#
2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.15-g461d4edf-dirty
4# Fri Jan 13 11:01:47 2006
5#
6# CONFIG_PPC64 is not set
7CONFIG_PPC32=y
8CONFIG_PPC_MERGE=y
9CONFIG_MMU=y
10CONFIG_GENERIC_HARDIRQS=y
11CONFIG_RWSEM_XCHGADD_ALGORITHM=y
12CONFIG_GENERIC_CALIBRATE_DELAY=y
13CONFIG_PPC=y
14CONFIG_EARLY_PRINTK=y
15CONFIG_GENERIC_NVRAM=y
16CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
17CONFIG_ARCH_MAY_HAVE_PC_FDC=y
18CONFIG_PPC_OF=y
19CONFIG_PPC_UDBG_16550=y
20# CONFIG_GENERIC_TBSYNC is not set
21CONFIG_DEFAULT_UIMAGE=y
22
23#
24# Processor support
25#
26# CONFIG_CLASSIC32 is not set
27# CONFIG_PPC_52xx is not set
28# CONFIG_PPC_82xx is not set
29CONFIG_PPC_83xx=y
30# CONFIG_40x is not set
31# CONFIG_44x is not set
32# CONFIG_8xx is not set
33# CONFIG_E200 is not set
34# CONFIG_E500 is not set
35CONFIG_6xx=y
36CONFIG_83xx=y
37CONFIG_PPC_FPU=y
38CONFIG_PPC_STD_MMU=y
39CONFIG_PPC_STD_MMU_32=y
40# CONFIG_SMP is not set
41
42#
43# Code maturity level options
44#
45CONFIG_EXPERIMENTAL=y
46CONFIG_CLEAN_COMPILE=y
47CONFIG_BROKEN_ON_SMP=y
48CONFIG_INIT_ENV_ARG_LIMIT=32
49
50#
51# General setup
52#
53CONFIG_LOCALVERSION=""
54CONFIG_LOCALVERSION_AUTO=y
55CONFIG_SWAP=y
56CONFIG_SYSVIPC=y
57# CONFIG_POSIX_MQUEUE is not set
58# CONFIG_BSD_PROCESS_ACCT is not set
59CONFIG_SYSCTL=y
60# CONFIG_AUDIT is not set
61# CONFIG_IKCONFIG is not set
62CONFIG_INITRAMFS_SOURCE=""
63# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
64CONFIG_EMBEDDED=y
65# CONFIG_KALLSYMS is not set
66CONFIG_HOTPLUG=y
67CONFIG_PRINTK=y
68CONFIG_BUG=y
69CONFIG_ELF_CORE=y
70CONFIG_BASE_FULL=y
71CONFIG_FUTEX=y
72# CONFIG_EPOLL is not set
73CONFIG_SHMEM=y
74CONFIG_CC_ALIGN_FUNCTIONS=0
75CONFIG_CC_ALIGN_LABELS=0
76CONFIG_CC_ALIGN_LOOPS=0
77CONFIG_CC_ALIGN_JUMPS=0
78CONFIG_SLAB=y
79# CONFIG_TINY_SHMEM is not set
80CONFIG_BASE_SMALL=0
81# CONFIG_SLOB is not set
82
83#
84# Loadable module support
85#
86CONFIG_MODULES=y
87CONFIG_MODULE_UNLOAD=y
88# CONFIG_MODULE_FORCE_UNLOAD is not set
89CONFIG_OBSOLETE_MODPARM=y
90# CONFIG_MODVERSIONS is not set
91# CONFIG_MODULE_SRCVERSION_ALL is not set
92# CONFIG_KMOD is not set
93
94#
95# Block layer
96#
97# CONFIG_LBD is not set
98
99#
100# IO Schedulers
101#
102CONFIG_IOSCHED_NOOP=y
103CONFIG_IOSCHED_AS=y
104CONFIG_IOSCHED_DEADLINE=y
105CONFIG_IOSCHED_CFQ=y
106CONFIG_DEFAULT_AS=y
107# CONFIG_DEFAULT_DEADLINE is not set
108# CONFIG_DEFAULT_CFQ is not set
109# CONFIG_DEFAULT_NOOP is not set
110CONFIG_DEFAULT_IOSCHED="anticipatory"
111CONFIG_PPC_GEN550=y
112# CONFIG_WANT_EARLY_SERIAL is not set
113
114#
115# Platform support
116#
117CONFIG_MPC834x_SYS=y
118CONFIG_MPC834x=y
119
120#
121# Kernel options
122#
123# CONFIG_HIGHMEM is not set
124# CONFIG_HZ_100 is not set
125CONFIG_HZ_250=y
126# CONFIG_HZ_1000 is not set
127CONFIG_HZ=250
128CONFIG_PREEMPT_NONE=y
129# CONFIG_PREEMPT_VOLUNTARY is not set
130# CONFIG_PREEMPT is not set
131CONFIG_BINFMT_ELF=y
132# CONFIG_BINFMT_MISC is not set
133CONFIG_ARCH_FLATMEM_ENABLE=y
134CONFIG_SELECT_MEMORY_MODEL=y
135CONFIG_FLATMEM_MANUAL=y
136# CONFIG_DISCONTIGMEM_MANUAL is not set
137# CONFIG_SPARSEMEM_MANUAL is not set
138CONFIG_FLATMEM=y
139CONFIG_FLAT_NODE_MEM_MAP=y
140# CONFIG_SPARSEMEM_STATIC is not set
141CONFIG_SPLIT_PTLOCK_CPUS=4
142CONFIG_PROC_DEVICETREE=y
143# CONFIG_CMDLINE_BOOL is not set
144# CONFIG_PM is not set
145# CONFIG_SOFTWARE_SUSPEND is not set
146CONFIG_SECCOMP=y
147CONFIG_ISA_DMA_API=y
148
149#
150# Bus options
151#
152CONFIG_GENERIC_ISA_DMA=y
153# CONFIG_PPC_I8259 is not set
154CONFIG_PPC_INDIRECT_PCI=y
155CONFIG_FSL_SOC=y
156CONFIG_PCI=y
157CONFIG_PCI_DOMAINS=y
158# CONFIG_PCI_LEGACY_PROC is not set
159
160#
161# PCCARD (PCMCIA/CardBus) support
162#
163# CONFIG_PCCARD is not set
164
165#
166# PCI Hotplug Support
167#
168# CONFIG_HOTPLUG_PCI is not set
169
170#
171# Advanced setup
172#
173# CONFIG_ADVANCED_OPTIONS is not set
174
175#
176# Default settings for advanced configuration options are used
177#
178CONFIG_HIGHMEM_START=0xfe000000
179CONFIG_LOWMEM_SIZE=0x30000000
180CONFIG_KERNEL_START=0xc0000000
181CONFIG_TASK_SIZE=0x80000000
182CONFIG_BOOT_LOAD=0x00800000
183
184#
185# Networking
186#
187CONFIG_NET=y
188
189#
190# Networking options
191#
192CONFIG_PACKET=y
193# CONFIG_PACKET_MMAP is not set
194CONFIG_UNIX=y
195# CONFIG_NET_KEY is not set
196CONFIG_INET=y
197CONFIG_IP_MULTICAST=y
198# CONFIG_IP_ADVANCED_ROUTER is not set
199CONFIG_IP_FIB_HASH=y
200CONFIG_IP_PNP=y
201CONFIG_IP_PNP_DHCP=y
202CONFIG_IP_PNP_BOOTP=y
203# CONFIG_IP_PNP_RARP is not set
204# CONFIG_NET_IPIP is not set
205# CONFIG_NET_IPGRE is not set
206# CONFIG_IP_MROUTE is not set
207# CONFIG_ARPD is not set
208CONFIG_SYN_COOKIES=y
209# CONFIG_INET_AH is not set
210# CONFIG_INET_ESP is not set
211# CONFIG_INET_IPCOMP is not set
212# CONFIG_INET_TUNNEL is not set
213CONFIG_INET_DIAG=y
214CONFIG_INET_TCP_DIAG=y
215# CONFIG_TCP_CONG_ADVANCED is not set
216CONFIG_TCP_CONG_BIC=y
217# CONFIG_IPV6 is not set
218# CONFIG_NETFILTER is not set
219
220#
221# DCCP Configuration (EXPERIMENTAL)
222#
223# CONFIG_IP_DCCP is not set
224
225#
226# SCTP Configuration (EXPERIMENTAL)
227#
228# CONFIG_IP_SCTP is not set
229# CONFIG_ATM is not set
230# CONFIG_BRIDGE is not set
231# CONFIG_VLAN_8021Q is not set
232# CONFIG_DECNET is not set
233# CONFIG_LLC2 is not set
234# CONFIG_IPX is not set
235# CONFIG_ATALK is not set
236# CONFIG_X25 is not set
237# CONFIG_LAPB is not set
238# CONFIG_NET_DIVERT is not set
239# CONFIG_ECONET is not set
240# CONFIG_WAN_ROUTER is not set
241
242#
243# QoS and/or fair queueing
244#
245# CONFIG_NET_SCHED is not set
246
247#
248# Network testing
249#
250# CONFIG_NET_PKTGEN is not set
251# CONFIG_HAMRADIO is not set
252# CONFIG_IRDA is not set
253# CONFIG_BT is not set
254# CONFIG_IEEE80211 is not set
255
256#
257# Device Drivers
258#
259
260#
261# Generic Driver Options
262#
263CONFIG_STANDALONE=y
264CONFIG_PREVENT_FIRMWARE_BUILD=y
265# CONFIG_FW_LOADER is not set
266
267#
268# Connector - unified userspace <-> kernelspace linker
269#
270# CONFIG_CONNECTOR is not set
271
272#
273# Memory Technology Devices (MTD)
274#
275# CONFIG_MTD is not set
276
277#
278# Parallel port support
279#
280# CONFIG_PARPORT is not set
281
282#
283# Plug and Play support
284#
285
286#
287# Block devices
288#
289# CONFIG_BLK_DEV_FD is not set
290# CONFIG_BLK_CPQ_DA is not set
291# CONFIG_BLK_CPQ_CISS_DA is not set
292# CONFIG_BLK_DEV_DAC960 is not set
293# CONFIG_BLK_DEV_UMEM is not set
294# CONFIG_BLK_DEV_COW_COMMON is not set
295CONFIG_BLK_DEV_LOOP=y
296# CONFIG_BLK_DEV_CRYPTOLOOP is not set
297# CONFIG_BLK_DEV_NBD is not set
298# CONFIG_BLK_DEV_SX8 is not set
299CONFIG_BLK_DEV_RAM=y
300CONFIG_BLK_DEV_RAM_COUNT=16
301CONFIG_BLK_DEV_RAM_SIZE=32768
302CONFIG_BLK_DEV_INITRD=y
303# CONFIG_CDROM_PKTCDVD is not set
304# CONFIG_ATA_OVER_ETH is not set
305
306#
307# ATA/ATAPI/MFM/RLL support
308#
309# CONFIG_IDE is not set
310
311#
312# SCSI device support
313#
314# CONFIG_RAID_ATTRS is not set
315# CONFIG_SCSI is not set
316
317#
318# Multi-device support (RAID and LVM)
319#
320# CONFIG_MD is not set
321
322#
323# Fusion MPT device support
324#
325# CONFIG_FUSION is not set
326
327#
328# IEEE 1394 (FireWire) support
329#
330# CONFIG_IEEE1394 is not set
331
332#
333# I2O device support
334#
335# CONFIG_I2O is not set
336
337#
338# Macintosh device drivers
339#
340# CONFIG_WINDFARM is not set
341
342#
343# Network device support
344#
345CONFIG_NETDEVICES=y
346# CONFIG_DUMMY is not set
347# CONFIG_BONDING is not set
348# CONFIG_EQUALIZER is not set
349# CONFIG_TUN is not set
350
351#
352# ARCnet devices
353#
354# CONFIG_ARCNET is not set
355
356#
357# PHY device support
358#
359CONFIG_PHYLIB=y
360
361#
362# MII PHY device drivers
363#
364CONFIG_MARVELL_PHY=y
365# CONFIG_DAVICOM_PHY is not set
366# CONFIG_QSEMI_PHY is not set
367# CONFIG_LXT_PHY is not set
368# CONFIG_CICADA_PHY is not set
369
370#
371# Ethernet (10 or 100Mbit)
372#
373CONFIG_NET_ETHERNET=y
374CONFIG_MII=y
375# CONFIG_HAPPYMEAL is not set
376# CONFIG_SUNGEM is not set
377# CONFIG_CASSINI is not set
378# CONFIG_NET_VENDOR_3COM is not set
379
380#
381# Tulip family network device support
382#
383# CONFIG_NET_TULIP is not set
384# CONFIG_HP100 is not set
385CONFIG_NET_PCI=y
386# CONFIG_PCNET32 is not set
387# CONFIG_AMD8111_ETH is not set
388# CONFIG_ADAPTEC_STARFIRE is not set
389# CONFIG_B44 is not set
390# CONFIG_FORCEDETH is not set
391# CONFIG_DGRS is not set
392# CONFIG_EEPRO100 is not set
393CONFIG_E100=y
394# CONFIG_FEALNX is not set
395# CONFIG_NATSEMI is not set
396# CONFIG_NE2K_PCI is not set
397# CONFIG_8139CP is not set
398# CONFIG_8139TOO is not set
399# CONFIG_SIS900 is not set
400# CONFIG_EPIC100 is not set
401# CONFIG_SUNDANCE is not set
402# CONFIG_TLAN is not set
403# CONFIG_VIA_RHINE is not set
404
405#
406# Ethernet (1000 Mbit)
407#
408# CONFIG_ACENIC is not set
409# CONFIG_DL2K is not set
410# CONFIG_E1000 is not set
411# CONFIG_NS83820 is not set
412# CONFIG_HAMACHI is not set
413# CONFIG_YELLOWFIN is not set
414# CONFIG_R8169 is not set
415# CONFIG_SIS190 is not set
416# CONFIG_SKGE is not set
417# CONFIG_SKY2 is not set
418# CONFIG_SK98LIN is not set
419# CONFIG_VIA_VELOCITY is not set
420# CONFIG_TIGON3 is not set
421# CONFIG_BNX2 is not set
422CONFIG_GIANFAR=y
423# CONFIG_GFAR_NAPI is not set
424
425#
426# Ethernet (10000 Mbit)
427#
428# CONFIG_CHELSIO_T1 is not set
429# CONFIG_IXGB is not set
430# CONFIG_S2IO is not set
431
432#
433# Token Ring devices
434#
435# CONFIG_TR is not set
436
437#
438# Wireless LAN (non-hamradio)
439#
440# CONFIG_NET_RADIO is not set
441
442#
443# Wan interfaces
444#
445# CONFIG_WAN is not set
446# CONFIG_FDDI is not set
447# CONFIG_HIPPI is not set
448# CONFIG_PPP is not set
449# CONFIG_SLIP is not set
450# CONFIG_SHAPER is not set
451# CONFIG_NETCONSOLE is not set
452# CONFIG_NETPOLL is not set
453# CONFIG_NET_POLL_CONTROLLER is not set
454
455#
456# ISDN subsystem
457#
458# CONFIG_ISDN is not set
459
460#
461# Telephony Support
462#
463# CONFIG_PHONE is not set
464
465#
466# Input device support
467#
468CONFIG_INPUT=y
469
470#
471# Userland interfaces
472#
473# CONFIG_INPUT_MOUSEDEV is not set
474# CONFIG_INPUT_JOYDEV is not set
475# CONFIG_INPUT_TSDEV is not set
476# CONFIG_INPUT_EVDEV is not set
477# CONFIG_INPUT_EVBUG is not set
478
479#
480# Input Device Drivers
481#
482# CONFIG_INPUT_KEYBOARD is not set
483# CONFIG_INPUT_MOUSE is not set
484# CONFIG_INPUT_JOYSTICK is not set
485# CONFIG_INPUT_TOUCHSCREEN is not set
486# CONFIG_INPUT_MISC is not set
487
488#
489# Hardware I/O ports
490#
491# CONFIG_SERIO is not set
492# CONFIG_GAMEPORT is not set
493
494#
495# Character devices
496#
497# CONFIG_VT is not set
498# CONFIG_SERIAL_NONSTANDARD is not set
499
500#
501# Serial drivers
502#
503CONFIG_SERIAL_8250=y
504CONFIG_SERIAL_8250_CONSOLE=y
505CONFIG_SERIAL_8250_NR_UARTS=4
506CONFIG_SERIAL_8250_RUNTIME_UARTS=4
507# CONFIG_SERIAL_8250_EXTENDED is not set
508
509#
510# Non-8250 serial port support
511#
512CONFIG_SERIAL_CORE=y
513CONFIG_SERIAL_CORE_CONSOLE=y
514CONFIG_UNIX98_PTYS=y
515CONFIG_LEGACY_PTYS=y
516CONFIG_LEGACY_PTY_COUNT=256
517
518#
519# IPMI
520#
521# CONFIG_IPMI_HANDLER is not set
522
523#
524# Watchdog Cards
525#
526CONFIG_WATCHDOG=y
527# CONFIG_WATCHDOG_NOWAYOUT is not set
528
529#
530# Watchdog Device Drivers
531#
532# CONFIG_SOFT_WATCHDOG is not set
533CONFIG_83xx_WDT=y
534
535#
536# PCI-based Watchdog Cards
537#
538# CONFIG_PCIPCWATCHDOG is not set
539# CONFIG_WDTPCI is not set
540# CONFIG_NVRAM is not set
541CONFIG_GEN_RTC=y
542# CONFIG_GEN_RTC_X is not set
543# CONFIG_DTLK is not set
544# CONFIG_R3964 is not set
545# CONFIG_APPLICOM is not set
546
547#
548# Ftape, the floppy tape device driver
549#
550# CONFIG_AGP is not set
551# CONFIG_DRM is not set
552# CONFIG_RAW_DRIVER is not set
553
554#
555# TPM devices
556#
557# CONFIG_TCG_TPM is not set
558# CONFIG_TELCLOCK is not set
559
560#
561# I2C support
562#
563CONFIG_I2C=y
564CONFIG_I2C_CHARDEV=y
565
566#
567# I2C Algorithms
568#
569# CONFIG_I2C_ALGOBIT is not set
570# CONFIG_I2C_ALGOPCF is not set
571# CONFIG_I2C_ALGOPCA is not set
572
573#
574# I2C Hardware Bus support
575#
576# CONFIG_I2C_ALI1535 is not set
577# CONFIG_I2C_ALI1563 is not set
578# CONFIG_I2C_ALI15X3 is not set
579# CONFIG_I2C_AMD756 is not set
580# CONFIG_I2C_AMD8111 is not set
581# CONFIG_I2C_I801 is not set
582# CONFIG_I2C_I810 is not set
583# CONFIG_I2C_PIIX4 is not set
584CONFIG_I2C_MPC=y
585# CONFIG_I2C_NFORCE2 is not set
586# CONFIG_I2C_PARPORT_LIGHT is not set
587# CONFIG_I2C_PROSAVAGE is not set
588# CONFIG_I2C_SAVAGE4 is not set
589# CONFIG_SCx200_ACB is not set
590# CONFIG_I2C_SIS5595 is not set
591# CONFIG_I2C_SIS630 is not set
592# CONFIG_I2C_SIS96X is not set
593# CONFIG_I2C_STUB is not set
594# CONFIG_I2C_VIA is not set
595# CONFIG_I2C_VIAPRO is not set
596# CONFIG_I2C_VOODOO3 is not set
597# CONFIG_I2C_PCA_ISA is not set
598
599#
600# Miscellaneous I2C Chip support
601#
602# CONFIG_SENSORS_DS1337 is not set
603# CONFIG_SENSORS_DS1374 is not set
604# CONFIG_SENSORS_EEPROM is not set
605# CONFIG_SENSORS_PCF8574 is not set
606# CONFIG_SENSORS_PCA9539 is not set
607# CONFIG_SENSORS_PCF8591 is not set
608# CONFIG_SENSORS_RTC8564 is not set
609# CONFIG_SENSORS_M41T00 is not set
610# CONFIG_SENSORS_MAX6875 is not set
611# CONFIG_RTC_X1205_I2C is not set
612# CONFIG_I2C_DEBUG_CORE is not set
613# CONFIG_I2C_DEBUG_ALGO is not set
614# CONFIG_I2C_DEBUG_BUS is not set
615# CONFIG_I2C_DEBUG_CHIP is not set
616
617#
618# Dallas's 1-wire bus
619#
620# CONFIG_W1 is not set
621
622#
623# Hardware Monitoring support
624#
625CONFIG_HWMON=y
626# CONFIG_HWMON_VID is not set
627# CONFIG_SENSORS_ADM1021 is not set
628# CONFIG_SENSORS_ADM1025 is not set
629# CONFIG_SENSORS_ADM1026 is not set
630# CONFIG_SENSORS_ADM1031 is not set
631# CONFIG_SENSORS_ADM9240 is not set
632# CONFIG_SENSORS_ASB100 is not set
633# CONFIG_SENSORS_ATXP1 is not set
634# CONFIG_SENSORS_DS1621 is not set
635# CONFIG_SENSORS_FSCHER is not set
636# CONFIG_SENSORS_FSCPOS is not set
637# CONFIG_SENSORS_GL518SM is not set
638# CONFIG_SENSORS_GL520SM is not set
639# CONFIG_SENSORS_IT87 is not set
640# CONFIG_SENSORS_LM63 is not set
641# CONFIG_SENSORS_LM75 is not set
642# CONFIG_SENSORS_LM77 is not set
643# CONFIG_SENSORS_LM78 is not set
644# CONFIG_SENSORS_LM80 is not set
645# CONFIG_SENSORS_LM83 is not set
646# CONFIG_SENSORS_LM85 is not set
647# CONFIG_SENSORS_LM87 is not set
648# CONFIG_SENSORS_LM90 is not set
649# CONFIG_SENSORS_LM92 is not set
650# CONFIG_SENSORS_MAX1619 is not set
651# CONFIG_SENSORS_PC87360 is not set
652# CONFIG_SENSORS_SIS5595 is not set
653# CONFIG_SENSORS_SMSC47M1 is not set
654# CONFIG_SENSORS_SMSC47B397 is not set
655# CONFIG_SENSORS_VIA686A is not set
656# CONFIG_SENSORS_VT8231 is not set
657# CONFIG_SENSORS_W83781D is not set
658# CONFIG_SENSORS_W83792D is not set
659# CONFIG_SENSORS_W83L785TS is not set
660# CONFIG_SENSORS_W83627HF is not set
661# CONFIG_SENSORS_W83627EHF is not set
662# CONFIG_HWMON_DEBUG_CHIP is not set
663
664#
665# Misc devices
666#
667
668#
669# Multimedia Capabilities Port drivers
670#
671
672#
673# Multimedia devices
674#
675# CONFIG_VIDEO_DEV is not set
676
677#
678# Digital Video Broadcasting Devices
679#
680# CONFIG_DVB is not set
681
682#
683# Graphics support
684#
685# CONFIG_FB is not set
686
687#
688# Sound
689#
690# CONFIG_SOUND is not set
691
692#
693# USB support
694#
695CONFIG_USB_ARCH_HAS_HCD=y
696CONFIG_USB_ARCH_HAS_OHCI=y
697# CONFIG_USB is not set
698
699#
700# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
701#
702
703#
704# USB Gadget Support
705#
706# CONFIG_USB_GADGET is not set
707
708#
709# MMC/SD Card support
710#
711# CONFIG_MMC is not set
712
713#
714# InfiniBand support
715#
716# CONFIG_INFINIBAND is not set
717
718#
719# SN Devices
720#
721
722#
723# File systems
724#
725CONFIG_EXT2_FS=y
726# CONFIG_EXT2_FS_XATTR is not set
727# CONFIG_EXT2_FS_XIP is not set
728CONFIG_EXT3_FS=y
729CONFIG_EXT3_FS_XATTR=y
730# CONFIG_EXT3_FS_POSIX_ACL is not set
731# CONFIG_EXT3_FS_SECURITY is not set
732CONFIG_JBD=y
733# CONFIG_JBD_DEBUG is not set
734CONFIG_FS_MBCACHE=y
735# CONFIG_REISERFS_FS is not set
736# CONFIG_JFS_FS is not set
737# CONFIG_FS_POSIX_ACL is not set
738# CONFIG_XFS_FS is not set
739# CONFIG_OCFS2_FS is not set
740# CONFIG_MINIX_FS is not set
741# CONFIG_ROMFS_FS is not set
742CONFIG_INOTIFY=y
743# CONFIG_QUOTA is not set
744CONFIG_DNOTIFY=y
745# CONFIG_AUTOFS_FS is not set
746# CONFIG_AUTOFS4_FS is not set
747# CONFIG_FUSE_FS is not set
748
749#
750# CD-ROM/DVD Filesystems
751#
752# CONFIG_ISO9660_FS is not set
753# CONFIG_UDF_FS is not set
754
755#
756# DOS/FAT/NT Filesystems
757#
758# CONFIG_MSDOS_FS is not set
759# CONFIG_VFAT_FS is not set
760# CONFIG_NTFS_FS is not set
761
762#
763# Pseudo filesystems
764#
765CONFIG_PROC_FS=y
766CONFIG_PROC_KCORE=y
767CONFIG_SYSFS=y
768CONFIG_TMPFS=y
769# CONFIG_HUGETLB_PAGE is not set
770CONFIG_RAMFS=y
771# CONFIG_RELAYFS_FS is not set
772# CONFIG_CONFIGFS_FS is not set
773
774#
775# Miscellaneous filesystems
776#
777# CONFIG_ADFS_FS is not set
778# CONFIG_AFFS_FS is not set
779# CONFIG_HFS_FS is not set
780# CONFIG_HFSPLUS_FS is not set
781# CONFIG_BEFS_FS is not set
782# CONFIG_BFS_FS is not set
783# CONFIG_EFS_FS is not set
784# CONFIG_CRAMFS is not set
785# CONFIG_VXFS_FS is not set
786# CONFIG_HPFS_FS is not set
787# CONFIG_QNX4FS_FS is not set
788# CONFIG_SYSV_FS is not set
789# CONFIG_UFS_FS is not set
790
791#
792# Network File Systems
793#
794CONFIG_NFS_FS=y
795CONFIG_NFS_V3=y
796# CONFIG_NFS_V3_ACL is not set
797CONFIG_NFS_V4=y
798# CONFIG_NFS_DIRECTIO is not set
799# CONFIG_NFSD is not set
800CONFIG_ROOT_NFS=y
801CONFIG_LOCKD=y
802CONFIG_LOCKD_V4=y
803CONFIG_NFS_COMMON=y
804CONFIG_SUNRPC=y
805CONFIG_SUNRPC_GSS=y
806CONFIG_RPCSEC_GSS_KRB5=y
807# CONFIG_RPCSEC_GSS_SPKM3 is not set
808# CONFIG_SMB_FS is not set
809# CONFIG_CIFS is not set
810# CONFIG_NCP_FS is not set
811# CONFIG_CODA_FS is not set
812# CONFIG_AFS_FS is not set
813# CONFIG_9P_FS is not set
814
815#
816# Partition Types
817#
818CONFIG_PARTITION_ADVANCED=y
819# CONFIG_ACORN_PARTITION is not set
820# CONFIG_OSF_PARTITION is not set
821# CONFIG_AMIGA_PARTITION is not set
822# CONFIG_ATARI_PARTITION is not set
823# CONFIG_MAC_PARTITION is not set
824# CONFIG_MSDOS_PARTITION is not set
825# CONFIG_LDM_PARTITION is not set
826# CONFIG_SGI_PARTITION is not set
827# CONFIG_ULTRIX_PARTITION is not set
828# CONFIG_SUN_PARTITION is not set
829# CONFIG_EFI_PARTITION is not set
830
831#
832# Native Language Support
833#
834# CONFIG_NLS is not set
835
836#
837# Library routines
838#
839# CONFIG_CRC_CCITT is not set
840# CONFIG_CRC16 is not set
841CONFIG_CRC32=y
842# CONFIG_LIBCRC32C is not set
843
844#
845# Instrumentation Support
846#
847# CONFIG_PROFILING is not set
848
849#
850# Kernel hacking
851#
852# CONFIG_PRINTK_TIME is not set
853# CONFIG_MAGIC_SYSRQ is not set
854# CONFIG_DEBUG_KERNEL is not set
855CONFIG_LOG_BUF_SHIFT=14
856# CONFIG_BOOTX_TEXT is not set
857# CONFIG_SERIAL_TEXT_DEBUG is not set
858# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
859# CONFIG_PPC_EARLY_DEBUG_G5 is not set
860# CONFIG_PPC_EARLY_DEBUG_RTAS is not set
861# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
862# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
863
864#
865# Security options
866#
867# CONFIG_KEYS is not set
868# CONFIG_SECURITY is not set
869
870#
871# Cryptographic options
872#
873CONFIG_CRYPTO=y
874# CONFIG_CRYPTO_HMAC is not set
875# CONFIG_CRYPTO_NULL is not set
876# CONFIG_CRYPTO_MD4 is not set
877CONFIG_CRYPTO_MD5=y
878# CONFIG_CRYPTO_SHA1 is not set
879# CONFIG_CRYPTO_SHA256 is not set
880# CONFIG_CRYPTO_SHA512 is not set
881# CONFIG_CRYPTO_WP512 is not set
882# CONFIG_CRYPTO_TGR192 is not set
883CONFIG_CRYPTO_DES=y
884# CONFIG_CRYPTO_BLOWFISH is not set
885# CONFIG_CRYPTO_TWOFISH is not set
886# CONFIG_CRYPTO_SERPENT is not set
887# CONFIG_CRYPTO_AES is not set
888# CONFIG_CRYPTO_CAST5 is not set
889# CONFIG_CRYPTO_CAST6 is not set
890# CONFIG_CRYPTO_TEA is not set
891# CONFIG_CRYPTO_ARC4 is not set
892# CONFIG_CRYPTO_KHAZAD is not set
893# CONFIG_CRYPTO_ANUBIS is not set
894# CONFIG_CRYPTO_DEFLATE is not set
895# CONFIG_CRYPTO_MICHAEL_MIC is not set
896# CONFIG_CRYPTO_CRC32C is not set
897# CONFIG_CRYPTO_TEST is not set
898
899#
900# Hardware crypto devices
901#
902
903#
904# SEC2.x Options
905#
906CONFIG_MPC8349E_SEC2x=y
907
908#
909# SEC2.x Test Options
910#
911CONFIG_MPC8349E_SEC2xTEST=y
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 56399c5c931a..840aad43a98b 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -135,7 +135,7 @@ int main(void)
135 DEFINE(PACA_EXMC, offsetof(struct paca_struct, exmc)); 135 DEFINE(PACA_EXMC, offsetof(struct paca_struct, exmc));
136 DEFINE(PACA_EXSLB, offsetof(struct paca_struct, exslb)); 136 DEFINE(PACA_EXSLB, offsetof(struct paca_struct, exslb));
137 DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp)); 137 DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp));
138 DEFINE(PACALPPACA, offsetof(struct paca_struct, lppaca)); 138 DEFINE(PACALPPACAPTR, offsetof(struct paca_struct, lppaca_ptr));
139 DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); 139 DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id));
140 140
141 DEFINE(LPPACASRR0, offsetof(struct lppaca, saved_srr0)); 141 DEFINE(LPPACASRR0, offsetof(struct lppaca, saved_srr0));
diff --git a/arch/powerpc/kernel/cpu_setup_power4.S b/arch/powerpc/kernel/cpu_setup_power4.S
index cca942fe6115..b61d86e7ceb6 100644
--- a/arch/powerpc/kernel/cpu_setup_power4.S
+++ b/arch/powerpc/kernel/cpu_setup_power4.S
@@ -130,7 +130,7 @@ _GLOBAL(__save_cpu_setup)
130 mfcr r7 130 mfcr r7
131 131
132 /* Get storage ptr */ 132 /* Get storage ptr */
133 LOADADDR(r5,cpu_state_storage) 133 LOAD_REG_IMMEDIATE(r5,cpu_state_storage)
134 134
135 /* We only deal with 970 for now */ 135 /* We only deal with 970 for now */
136 mfspr r0,SPRN_PVR 136 mfspr r0,SPRN_PVR
@@ -164,7 +164,7 @@ _GLOBAL(__restore_cpu_setup)
164 /* Get storage ptr (FIXME when using anton reloc as we 164 /* Get storage ptr (FIXME when using anton reloc as we
165 * are running with translation disabled here 165 * are running with translation disabled here
166 */ 166 */
167 LOADADDR(r5,cpu_state_storage) 167 LOAD_REG_IMMEDIATE(r5,cpu_state_storage)
168 168
169 /* We only deal with 970 for now */ 169 /* We only deal with 970 for now */
170 mfspr r0,SPRN_PVR 170 mfspr r0,SPRN_PVR
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 43c74a6b07b1..10696456a4c6 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -55,7 +55,8 @@ extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec);
55#define COMMON_USER_POWER4 (COMMON_USER_PPC64 | PPC_FEATURE_POWER4) 55#define COMMON_USER_POWER4 (COMMON_USER_PPC64 | PPC_FEATURE_POWER4)
56#define COMMON_USER_POWER5 (COMMON_USER_PPC64 | PPC_FEATURE_POWER5) 56#define COMMON_USER_POWER5 (COMMON_USER_PPC64 | PPC_FEATURE_POWER5)
57#define COMMON_USER_POWER5_PLUS (COMMON_USER_PPC64 | PPC_FEATURE_POWER5_PLUS) 57#define COMMON_USER_POWER5_PLUS (COMMON_USER_PPC64 | PPC_FEATURE_POWER5_PLUS)
58 58#define COMMON_USER_BOOKE (PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | \
59 PPC_FEATURE_BOOKE)
59 60
60/* We only set the spe features if the kernel was compiled with 61/* We only set the spe features if the kernel was compiled with
61 * spe support 62 * spe support
@@ -79,7 +80,8 @@ struct cpu_spec cpu_specs[] = {
79 .num_pmcs = 8, 80 .num_pmcs = 8,
80 .cpu_setup = __setup_cpu_power3, 81 .cpu_setup = __setup_cpu_power3,
81 .oprofile_cpu_type = "ppc64/power3", 82 .oprofile_cpu_type = "ppc64/power3",
82 .oprofile_type = RS64, 83 .oprofile_type = PPC_OPROFILE_RS64,
84 .platform = "power3",
83 }, 85 },
84 { /* Power3+ */ 86 { /* Power3+ */
85 .pvr_mask = 0xffff0000, 87 .pvr_mask = 0xffff0000,
@@ -92,7 +94,8 @@ struct cpu_spec cpu_specs[] = {
92 .num_pmcs = 8, 94 .num_pmcs = 8,
93 .cpu_setup = __setup_cpu_power3, 95 .cpu_setup = __setup_cpu_power3,
94 .oprofile_cpu_type = "ppc64/power3", 96 .oprofile_cpu_type = "ppc64/power3",
95 .oprofile_type = RS64, 97 .oprofile_type = PPC_OPROFILE_RS64,
98 .platform = "power3",
96 }, 99 },
97 { /* Northstar */ 100 { /* Northstar */
98 .pvr_mask = 0xffff0000, 101 .pvr_mask = 0xffff0000,
@@ -105,7 +108,8 @@ struct cpu_spec cpu_specs[] = {
105 .num_pmcs = 8, 108 .num_pmcs = 8,
106 .cpu_setup = __setup_cpu_power3, 109 .cpu_setup = __setup_cpu_power3,
107 .oprofile_cpu_type = "ppc64/rs64", 110 .oprofile_cpu_type = "ppc64/rs64",
108 .oprofile_type = RS64, 111 .oprofile_type = PPC_OPROFILE_RS64,
112 .platform = "rs64",
109 }, 113 },
110 { /* Pulsar */ 114 { /* Pulsar */
111 .pvr_mask = 0xffff0000, 115 .pvr_mask = 0xffff0000,
@@ -118,7 +122,8 @@ struct cpu_spec cpu_specs[] = {
118 .num_pmcs = 8, 122 .num_pmcs = 8,
119 .cpu_setup = __setup_cpu_power3, 123 .cpu_setup = __setup_cpu_power3,
120 .oprofile_cpu_type = "ppc64/rs64", 124 .oprofile_cpu_type = "ppc64/rs64",
121 .oprofile_type = RS64, 125 .oprofile_type = PPC_OPROFILE_RS64,
126 .platform = "rs64",
122 }, 127 },
123 { /* I-star */ 128 { /* I-star */
124 .pvr_mask = 0xffff0000, 129 .pvr_mask = 0xffff0000,
@@ -131,7 +136,8 @@ struct cpu_spec cpu_specs[] = {
131 .num_pmcs = 8, 136 .num_pmcs = 8,
132 .cpu_setup = __setup_cpu_power3, 137 .cpu_setup = __setup_cpu_power3,
133 .oprofile_cpu_type = "ppc64/rs64", 138 .oprofile_cpu_type = "ppc64/rs64",
134 .oprofile_type = RS64, 139 .oprofile_type = PPC_OPROFILE_RS64,
140 .platform = "rs64",
135 }, 141 },
136 { /* S-star */ 142 { /* S-star */
137 .pvr_mask = 0xffff0000, 143 .pvr_mask = 0xffff0000,
@@ -144,7 +150,8 @@ struct cpu_spec cpu_specs[] = {
144 .num_pmcs = 8, 150 .num_pmcs = 8,
145 .cpu_setup = __setup_cpu_power3, 151 .cpu_setup = __setup_cpu_power3,
146 .oprofile_cpu_type = "ppc64/rs64", 152 .oprofile_cpu_type = "ppc64/rs64",
147 .oprofile_type = RS64, 153 .oprofile_type = PPC_OPROFILE_RS64,
154 .platform = "rs64",
148 }, 155 },
149 { /* Power4 */ 156 { /* Power4 */
150 .pvr_mask = 0xffff0000, 157 .pvr_mask = 0xffff0000,
@@ -157,7 +164,8 @@ struct cpu_spec cpu_specs[] = {
157 .num_pmcs = 8, 164 .num_pmcs = 8,
158 .cpu_setup = __setup_cpu_power4, 165 .cpu_setup = __setup_cpu_power4,
159 .oprofile_cpu_type = "ppc64/power4", 166 .oprofile_cpu_type = "ppc64/power4",
160 .oprofile_type = POWER4, 167 .oprofile_type = PPC_OPROFILE_POWER4,
168 .platform = "power4",
161 }, 169 },
162 { /* Power4+ */ 170 { /* Power4+ */
163 .pvr_mask = 0xffff0000, 171 .pvr_mask = 0xffff0000,
@@ -170,7 +178,8 @@ struct cpu_spec cpu_specs[] = {
170 .num_pmcs = 8, 178 .num_pmcs = 8,
171 .cpu_setup = __setup_cpu_power4, 179 .cpu_setup = __setup_cpu_power4,
172 .oprofile_cpu_type = "ppc64/power4", 180 .oprofile_cpu_type = "ppc64/power4",
173 .oprofile_type = POWER4, 181 .oprofile_type = PPC_OPROFILE_POWER4,
182 .platform = "power4",
174 }, 183 },
175 { /* PPC970 */ 184 { /* PPC970 */
176 .pvr_mask = 0xffff0000, 185 .pvr_mask = 0xffff0000,
@@ -184,7 +193,8 @@ struct cpu_spec cpu_specs[] = {
184 .num_pmcs = 8, 193 .num_pmcs = 8,
185 .cpu_setup = __setup_cpu_ppc970, 194 .cpu_setup = __setup_cpu_ppc970,
186 .oprofile_cpu_type = "ppc64/970", 195 .oprofile_cpu_type = "ppc64/970",
187 .oprofile_type = POWER4, 196 .oprofile_type = PPC_OPROFILE_POWER4,
197 .platform = "ppc970",
188 }, 198 },
189#endif /* CONFIG_PPC64 */ 199#endif /* CONFIG_PPC64 */
190#if defined(CONFIG_PPC64) || defined(CONFIG_POWER4) 200#if defined(CONFIG_PPC64) || defined(CONFIG_POWER4)
@@ -204,7 +214,8 @@ struct cpu_spec cpu_specs[] = {
204 .num_pmcs = 8, 214 .num_pmcs = 8,
205 .cpu_setup = __setup_cpu_ppc970, 215 .cpu_setup = __setup_cpu_ppc970,
206 .oprofile_cpu_type = "ppc64/970", 216 .oprofile_cpu_type = "ppc64/970",
207 .oprofile_type = POWER4, 217 .oprofile_type = PPC_OPROFILE_POWER4,
218 .platform = "ppc970",
208 }, 219 },
209#endif /* defined(CONFIG_PPC64) || defined(CONFIG_POWER4) */ 220#endif /* defined(CONFIG_PPC64) || defined(CONFIG_POWER4) */
210#ifdef CONFIG_PPC64 221#ifdef CONFIG_PPC64
@@ -219,7 +230,8 @@ struct cpu_spec cpu_specs[] = {
219 .dcache_bsize = 128, 230 .dcache_bsize = 128,
220 .cpu_setup = __setup_cpu_ppc970, 231 .cpu_setup = __setup_cpu_ppc970,
221 .oprofile_cpu_type = "ppc64/970", 232 .oprofile_cpu_type = "ppc64/970",
222 .oprofile_type = POWER4, 233 .oprofile_type = PPC_OPROFILE_POWER4,
234 .platform = "ppc970",
223 }, 235 },
224 { /* Power5 GR */ 236 { /* Power5 GR */
225 .pvr_mask = 0xffff0000, 237 .pvr_mask = 0xffff0000,
@@ -232,7 +244,8 @@ struct cpu_spec cpu_specs[] = {
232 .num_pmcs = 6, 244 .num_pmcs = 6,
233 .cpu_setup = __setup_cpu_power4, 245 .cpu_setup = __setup_cpu_power4,
234 .oprofile_cpu_type = "ppc64/power5", 246 .oprofile_cpu_type = "ppc64/power5",
235 .oprofile_type = POWER4, 247 .oprofile_type = PPC_OPROFILE_POWER4,
248 .platform = "power5",
236 }, 249 },
237 { /* Power5 GS */ 250 { /* Power5 GS */
238 .pvr_mask = 0xffff0000, 251 .pvr_mask = 0xffff0000,
@@ -245,7 +258,8 @@ struct cpu_spec cpu_specs[] = {
245 .num_pmcs = 6, 258 .num_pmcs = 6,
246 .cpu_setup = __setup_cpu_power4, 259 .cpu_setup = __setup_cpu_power4,
247 .oprofile_cpu_type = "ppc64/power5+", 260 .oprofile_cpu_type = "ppc64/power5+",
248 .oprofile_type = POWER4, 261 .oprofile_type = PPC_OPROFILE_POWER4,
262 .platform = "power5+",
249 }, 263 },
250 { /* Cell Broadband Engine */ 264 { /* Cell Broadband Engine */
251 .pvr_mask = 0xffff0000, 265 .pvr_mask = 0xffff0000,
@@ -257,6 +271,7 @@ struct cpu_spec cpu_specs[] = {
257 .icache_bsize = 128, 271 .icache_bsize = 128,
258 .dcache_bsize = 128, 272 .dcache_bsize = 128,
259 .cpu_setup = __setup_cpu_be, 273 .cpu_setup = __setup_cpu_be,
274 .platform = "ppc-cell-be",
260 }, 275 },
261 { /* default match */ 276 { /* default match */
262 .pvr_mask = 0x00000000, 277 .pvr_mask = 0x00000000,
@@ -268,6 +283,7 @@ struct cpu_spec cpu_specs[] = {
268 .dcache_bsize = 128, 283 .dcache_bsize = 128,
269 .num_pmcs = 6, 284 .num_pmcs = 6,
270 .cpu_setup = __setup_cpu_power4, 285 .cpu_setup = __setup_cpu_power4,
286 .platform = "power4",
271 } 287 }
272#endif /* CONFIG_PPC64 */ 288#endif /* CONFIG_PPC64 */
273#ifdef CONFIG_PPC32 289#ifdef CONFIG_PPC32
@@ -281,6 +297,7 @@ struct cpu_spec cpu_specs[] = {
281 PPC_FEATURE_UNIFIED_CACHE | PPC_FEATURE_NO_TB, 297 PPC_FEATURE_UNIFIED_CACHE | PPC_FEATURE_NO_TB,
282 .icache_bsize = 32, 298 .icache_bsize = 32,
283 .dcache_bsize = 32, 299 .dcache_bsize = 32,
300 .platform = "ppc601",
284 }, 301 },
285 { /* 603 */ 302 { /* 603 */
286 .pvr_mask = 0xffff0000, 303 .pvr_mask = 0xffff0000,
@@ -290,7 +307,8 @@ struct cpu_spec cpu_specs[] = {
290 .cpu_user_features = COMMON_USER, 307 .cpu_user_features = COMMON_USER,
291 .icache_bsize = 32, 308 .icache_bsize = 32,
292 .dcache_bsize = 32, 309 .dcache_bsize = 32,
293 .cpu_setup = __setup_cpu_603 310 .cpu_setup = __setup_cpu_603,
311 .platform = "ppc603",
294 }, 312 },
295 { /* 603e */ 313 { /* 603e */
296 .pvr_mask = 0xffff0000, 314 .pvr_mask = 0xffff0000,
@@ -300,7 +318,8 @@ struct cpu_spec cpu_specs[] = {
300 .cpu_user_features = COMMON_USER, 318 .cpu_user_features = COMMON_USER,
301 .icache_bsize = 32, 319 .icache_bsize = 32,
302 .dcache_bsize = 32, 320 .dcache_bsize = 32,
303 .cpu_setup = __setup_cpu_603 321 .cpu_setup = __setup_cpu_603,
322 .platform = "ppc603",
304 }, 323 },
305 { /* 603ev */ 324 { /* 603ev */
306 .pvr_mask = 0xffff0000, 325 .pvr_mask = 0xffff0000,
@@ -310,7 +329,8 @@ struct cpu_spec cpu_specs[] = {
310 .cpu_user_features = COMMON_USER, 329 .cpu_user_features = COMMON_USER,
311 .icache_bsize = 32, 330 .icache_bsize = 32,
312 .dcache_bsize = 32, 331 .dcache_bsize = 32,
313 .cpu_setup = __setup_cpu_603 332 .cpu_setup = __setup_cpu_603,
333 .platform = "ppc603",
314 }, 334 },
315 { /* 604 */ 335 { /* 604 */
316 .pvr_mask = 0xffff0000, 336 .pvr_mask = 0xffff0000,
@@ -321,7 +341,8 @@ struct cpu_spec cpu_specs[] = {
321 .icache_bsize = 32, 341 .icache_bsize = 32,
322 .dcache_bsize = 32, 342 .dcache_bsize = 32,
323 .num_pmcs = 2, 343 .num_pmcs = 2,
324 .cpu_setup = __setup_cpu_604 344 .cpu_setup = __setup_cpu_604,
345 .platform = "ppc604",
325 }, 346 },
326 { /* 604e */ 347 { /* 604e */
327 .pvr_mask = 0xfffff000, 348 .pvr_mask = 0xfffff000,
@@ -332,7 +353,8 @@ struct cpu_spec cpu_specs[] = {
332 .icache_bsize = 32, 353 .icache_bsize = 32,
333 .dcache_bsize = 32, 354 .dcache_bsize = 32,
334 .num_pmcs = 4, 355 .num_pmcs = 4,
335 .cpu_setup = __setup_cpu_604 356 .cpu_setup = __setup_cpu_604,
357 .platform = "ppc604",
336 }, 358 },
337 { /* 604r */ 359 { /* 604r */
338 .pvr_mask = 0xffff0000, 360 .pvr_mask = 0xffff0000,
@@ -343,7 +365,8 @@ struct cpu_spec cpu_specs[] = {
343 .icache_bsize = 32, 365 .icache_bsize = 32,
344 .dcache_bsize = 32, 366 .dcache_bsize = 32,
345 .num_pmcs = 4, 367 .num_pmcs = 4,
346 .cpu_setup = __setup_cpu_604 368 .cpu_setup = __setup_cpu_604,
369 .platform = "ppc604",
347 }, 370 },
348 { /* 604ev */ 371 { /* 604ev */
349 .pvr_mask = 0xffff0000, 372 .pvr_mask = 0xffff0000,
@@ -354,7 +377,8 @@ struct cpu_spec cpu_specs[] = {
354 .icache_bsize = 32, 377 .icache_bsize = 32,
355 .dcache_bsize = 32, 378 .dcache_bsize = 32,
356 .num_pmcs = 4, 379 .num_pmcs = 4,
357 .cpu_setup = __setup_cpu_604 380 .cpu_setup = __setup_cpu_604,
381 .platform = "ppc604",
358 }, 382 },
359 { /* 740/750 (0x4202, don't support TAU ?) */ 383 { /* 740/750 (0x4202, don't support TAU ?) */
360 .pvr_mask = 0xffffffff, 384 .pvr_mask = 0xffffffff,
@@ -365,7 +389,8 @@ struct cpu_spec cpu_specs[] = {
365 .icache_bsize = 32, 389 .icache_bsize = 32,
366 .dcache_bsize = 32, 390 .dcache_bsize = 32,
367 .num_pmcs = 4, 391 .num_pmcs = 4,
368 .cpu_setup = __setup_cpu_750 392 .cpu_setup = __setup_cpu_750,
393 .platform = "ppc750",
369 }, 394 },
370 { /* 750CX (80100 and 8010x?) */ 395 { /* 750CX (80100 and 8010x?) */
371 .pvr_mask = 0xfffffff0, 396 .pvr_mask = 0xfffffff0,
@@ -376,7 +401,8 @@ struct cpu_spec cpu_specs[] = {
376 .icache_bsize = 32, 401 .icache_bsize = 32,
377 .dcache_bsize = 32, 402 .dcache_bsize = 32,
378 .num_pmcs = 4, 403 .num_pmcs = 4,
379 .cpu_setup = __setup_cpu_750cx 404 .cpu_setup = __setup_cpu_750cx,
405 .platform = "ppc750",
380 }, 406 },
381 { /* 750CX (82201 and 82202) */ 407 { /* 750CX (82201 and 82202) */
382 .pvr_mask = 0xfffffff0, 408 .pvr_mask = 0xfffffff0,
@@ -387,7 +413,8 @@ struct cpu_spec cpu_specs[] = {
387 .icache_bsize = 32, 413 .icache_bsize = 32,
388 .dcache_bsize = 32, 414 .dcache_bsize = 32,
389 .num_pmcs = 4, 415 .num_pmcs = 4,
390 .cpu_setup = __setup_cpu_750cx 416 .cpu_setup = __setup_cpu_750cx,
417 .platform = "ppc750",
391 }, 418 },
392 { /* 750CXe (82214) */ 419 { /* 750CXe (82214) */
393 .pvr_mask = 0xfffffff0, 420 .pvr_mask = 0xfffffff0,
@@ -398,7 +425,8 @@ struct cpu_spec cpu_specs[] = {
398 .icache_bsize = 32, 425 .icache_bsize = 32,
399 .dcache_bsize = 32, 426 .dcache_bsize = 32,
400 .num_pmcs = 4, 427 .num_pmcs = 4,
401 .cpu_setup = __setup_cpu_750cx 428 .cpu_setup = __setup_cpu_750cx,
429 .platform = "ppc750",
402 }, 430 },
403 { /* 750CXe "Gekko" (83214) */ 431 { /* 750CXe "Gekko" (83214) */
404 .pvr_mask = 0xffffffff, 432 .pvr_mask = 0xffffffff,
@@ -409,7 +437,8 @@ struct cpu_spec cpu_specs[] = {
409 .icache_bsize = 32, 437 .icache_bsize = 32,
410 .dcache_bsize = 32, 438 .dcache_bsize = 32,
411 .num_pmcs = 4, 439 .num_pmcs = 4,
412 .cpu_setup = __setup_cpu_750cx 440 .cpu_setup = __setup_cpu_750cx,
441 .platform = "ppc750",
413 }, 442 },
414 { /* 745/755 */ 443 { /* 745/755 */
415 .pvr_mask = 0xfffff000, 444 .pvr_mask = 0xfffff000,
@@ -420,7 +449,8 @@ struct cpu_spec cpu_specs[] = {
420 .icache_bsize = 32, 449 .icache_bsize = 32,
421 .dcache_bsize = 32, 450 .dcache_bsize = 32,
422 .num_pmcs = 4, 451 .num_pmcs = 4,
423 .cpu_setup = __setup_cpu_750 452 .cpu_setup = __setup_cpu_750,
453 .platform = "ppc750",
424 }, 454 },
425 { /* 750FX rev 1.x */ 455 { /* 750FX rev 1.x */
426 .pvr_mask = 0xffffff00, 456 .pvr_mask = 0xffffff00,
@@ -431,7 +461,8 @@ struct cpu_spec cpu_specs[] = {
431 .icache_bsize = 32, 461 .icache_bsize = 32,
432 .dcache_bsize = 32, 462 .dcache_bsize = 32,
433 .num_pmcs = 4, 463 .num_pmcs = 4,
434 .cpu_setup = __setup_cpu_750 464 .cpu_setup = __setup_cpu_750,
465 .platform = "ppc750",
435 }, 466 },
436 { /* 750FX rev 2.0 must disable HID0[DPM] */ 467 { /* 750FX rev 2.0 must disable HID0[DPM] */
437 .pvr_mask = 0xffffffff, 468 .pvr_mask = 0xffffffff,
@@ -442,7 +473,8 @@ struct cpu_spec cpu_specs[] = {
442 .icache_bsize = 32, 473 .icache_bsize = 32,
443 .dcache_bsize = 32, 474 .dcache_bsize = 32,
444 .num_pmcs = 4, 475 .num_pmcs = 4,
445 .cpu_setup = __setup_cpu_750 476 .cpu_setup = __setup_cpu_750,
477 .platform = "ppc750",
446 }, 478 },
447 { /* 750FX (All revs except 2.0) */ 479 { /* 750FX (All revs except 2.0) */
448 .pvr_mask = 0xffff0000, 480 .pvr_mask = 0xffff0000,
@@ -453,7 +485,8 @@ struct cpu_spec cpu_specs[] = {
453 .icache_bsize = 32, 485 .icache_bsize = 32,
454 .dcache_bsize = 32, 486 .dcache_bsize = 32,
455 .num_pmcs = 4, 487 .num_pmcs = 4,
456 .cpu_setup = __setup_cpu_750fx 488 .cpu_setup = __setup_cpu_750fx,
489 .platform = "ppc750",
457 }, 490 },
458 { /* 750GX */ 491 { /* 750GX */
459 .pvr_mask = 0xffff0000, 492 .pvr_mask = 0xffff0000,
@@ -464,7 +497,8 @@ struct cpu_spec cpu_specs[] = {
464 .icache_bsize = 32, 497 .icache_bsize = 32,
465 .dcache_bsize = 32, 498 .dcache_bsize = 32,
466 .num_pmcs = 4, 499 .num_pmcs = 4,
467 .cpu_setup = __setup_cpu_750fx 500 .cpu_setup = __setup_cpu_750fx,
501 .platform = "ppc750",
468 }, 502 },
469 { /* 740/750 (L2CR bit need fixup for 740) */ 503 { /* 740/750 (L2CR bit need fixup for 740) */
470 .pvr_mask = 0xffff0000, 504 .pvr_mask = 0xffff0000,
@@ -475,7 +509,8 @@ struct cpu_spec cpu_specs[] = {
475 .icache_bsize = 32, 509 .icache_bsize = 32,
476 .dcache_bsize = 32, 510 .dcache_bsize = 32,
477 .num_pmcs = 4, 511 .num_pmcs = 4,
478 .cpu_setup = __setup_cpu_750 512 .cpu_setup = __setup_cpu_750,
513 .platform = "ppc750",
479 }, 514 },
480 { /* 7400 rev 1.1 ? (no TAU) */ 515 { /* 7400 rev 1.1 ? (no TAU) */
481 .pvr_mask = 0xffffffff, 516 .pvr_mask = 0xffffffff,
@@ -486,7 +521,8 @@ struct cpu_spec cpu_specs[] = {
486 .icache_bsize = 32, 521 .icache_bsize = 32,
487 .dcache_bsize = 32, 522 .dcache_bsize = 32,
488 .num_pmcs = 4, 523 .num_pmcs = 4,
489 .cpu_setup = __setup_cpu_7400 524 .cpu_setup = __setup_cpu_7400,
525 .platform = "ppc7400",
490 }, 526 },
491 { /* 7400 */ 527 { /* 7400 */
492 .pvr_mask = 0xffff0000, 528 .pvr_mask = 0xffff0000,
@@ -497,7 +533,8 @@ struct cpu_spec cpu_specs[] = {
497 .icache_bsize = 32, 533 .icache_bsize = 32,
498 .dcache_bsize = 32, 534 .dcache_bsize = 32,
499 .num_pmcs = 4, 535 .num_pmcs = 4,
500 .cpu_setup = __setup_cpu_7400 536 .cpu_setup = __setup_cpu_7400,
537 .platform = "ppc7400",
501 }, 538 },
502 { /* 7410 */ 539 { /* 7410 */
503 .pvr_mask = 0xffff0000, 540 .pvr_mask = 0xffff0000,
@@ -508,7 +545,8 @@ struct cpu_spec cpu_specs[] = {
508 .icache_bsize = 32, 545 .icache_bsize = 32,
509 .dcache_bsize = 32, 546 .dcache_bsize = 32,
510 .num_pmcs = 4, 547 .num_pmcs = 4,
511 .cpu_setup = __setup_cpu_7410 548 .cpu_setup = __setup_cpu_7410,
549 .platform = "ppc7400",
512 }, 550 },
513 { /* 7450 2.0 - no doze/nap */ 551 { /* 7450 2.0 - no doze/nap */
514 .pvr_mask = 0xffffffff, 552 .pvr_mask = 0xffffffff,
@@ -521,7 +559,8 @@ struct cpu_spec cpu_specs[] = {
521 .num_pmcs = 6, 559 .num_pmcs = 6,
522 .cpu_setup = __setup_cpu_745x, 560 .cpu_setup = __setup_cpu_745x,
523 .oprofile_cpu_type = "ppc/7450", 561 .oprofile_cpu_type = "ppc/7450",
524 .oprofile_type = G4, 562 .oprofile_type = PPC_OPROFILE_G4,
563 .platform = "ppc7450",
525 }, 564 },
526 { /* 7450 2.1 */ 565 { /* 7450 2.1 */
527 .pvr_mask = 0xffffffff, 566 .pvr_mask = 0xffffffff,
@@ -534,7 +573,8 @@ struct cpu_spec cpu_specs[] = {
534 .num_pmcs = 6, 573 .num_pmcs = 6,
535 .cpu_setup = __setup_cpu_745x, 574 .cpu_setup = __setup_cpu_745x,
536 .oprofile_cpu_type = "ppc/7450", 575 .oprofile_cpu_type = "ppc/7450",
537 .oprofile_type = G4, 576 .oprofile_type = PPC_OPROFILE_G4,
577 .platform = "ppc7450",
538 }, 578 },
539 { /* 7450 2.3 and newer */ 579 { /* 7450 2.3 and newer */
540 .pvr_mask = 0xffff0000, 580 .pvr_mask = 0xffff0000,
@@ -547,7 +587,8 @@ struct cpu_spec cpu_specs[] = {
547 .num_pmcs = 6, 587 .num_pmcs = 6,
548 .cpu_setup = __setup_cpu_745x, 588 .cpu_setup = __setup_cpu_745x,
549 .oprofile_cpu_type = "ppc/7450", 589 .oprofile_cpu_type = "ppc/7450",
550 .oprofile_type = G4, 590 .oprofile_type = PPC_OPROFILE_G4,
591 .platform = "ppc7450",
551 }, 592 },
552 { /* 7455 rev 1.x */ 593 { /* 7455 rev 1.x */
553 .pvr_mask = 0xffffff00, 594 .pvr_mask = 0xffffff00,
@@ -560,7 +601,8 @@ struct cpu_spec cpu_specs[] = {
560 .num_pmcs = 6, 601 .num_pmcs = 6,
561 .cpu_setup = __setup_cpu_745x, 602 .cpu_setup = __setup_cpu_745x,
562 .oprofile_cpu_type = "ppc/7450", 603 .oprofile_cpu_type = "ppc/7450",
563 .oprofile_type = G4, 604 .oprofile_type = PPC_OPROFILE_G4,
605 .platform = "ppc7450",
564 }, 606 },
565 { /* 7455 rev 2.0 */ 607 { /* 7455 rev 2.0 */
566 .pvr_mask = 0xffffffff, 608 .pvr_mask = 0xffffffff,
@@ -573,7 +615,8 @@ struct cpu_spec cpu_specs[] = {
573 .num_pmcs = 6, 615 .num_pmcs = 6,
574 .cpu_setup = __setup_cpu_745x, 616 .cpu_setup = __setup_cpu_745x,
575 .oprofile_cpu_type = "ppc/7450", 617 .oprofile_cpu_type = "ppc/7450",
576 .oprofile_type = G4, 618 .oprofile_type = PPC_OPROFILE_G4,
619 .platform = "ppc7450",
577 }, 620 },
578 { /* 7455 others */ 621 { /* 7455 others */
579 .pvr_mask = 0xffff0000, 622 .pvr_mask = 0xffff0000,
@@ -586,7 +629,8 @@ struct cpu_spec cpu_specs[] = {
586 .num_pmcs = 6, 629 .num_pmcs = 6,
587 .cpu_setup = __setup_cpu_745x, 630 .cpu_setup = __setup_cpu_745x,
588 .oprofile_cpu_type = "ppc/7450", 631 .oprofile_cpu_type = "ppc/7450",
589 .oprofile_type = G4, 632 .oprofile_type = PPC_OPROFILE_G4,
633 .platform = "ppc7450",
590 }, 634 },
591 { /* 7447/7457 Rev 1.0 */ 635 { /* 7447/7457 Rev 1.0 */
592 .pvr_mask = 0xffffffff, 636 .pvr_mask = 0xffffffff,
@@ -599,7 +643,8 @@ struct cpu_spec cpu_specs[] = {
599 .num_pmcs = 6, 643 .num_pmcs = 6,
600 .cpu_setup = __setup_cpu_745x, 644 .cpu_setup = __setup_cpu_745x,
601 .oprofile_cpu_type = "ppc/7450", 645 .oprofile_cpu_type = "ppc/7450",
602 .oprofile_type = G4, 646 .oprofile_type = PPC_OPROFILE_G4,
647 .platform = "ppc7450",
603 }, 648 },
604 { /* 7447/7457 Rev 1.1 */ 649 { /* 7447/7457 Rev 1.1 */
605 .pvr_mask = 0xffffffff, 650 .pvr_mask = 0xffffffff,
@@ -612,7 +657,8 @@ struct cpu_spec cpu_specs[] = {
612 .num_pmcs = 6, 657 .num_pmcs = 6,
613 .cpu_setup = __setup_cpu_745x, 658 .cpu_setup = __setup_cpu_745x,
614 .oprofile_cpu_type = "ppc/7450", 659 .oprofile_cpu_type = "ppc/7450",
615 .oprofile_type = G4, 660 .oprofile_type = PPC_OPROFILE_G4,
661 .platform = "ppc7450",
616 }, 662 },
617 { /* 7447/7457 Rev 1.2 and later */ 663 { /* 7447/7457 Rev 1.2 and later */
618 .pvr_mask = 0xffff0000, 664 .pvr_mask = 0xffff0000,
@@ -625,7 +671,8 @@ struct cpu_spec cpu_specs[] = {
625 .num_pmcs = 6, 671 .num_pmcs = 6,
626 .cpu_setup = __setup_cpu_745x, 672 .cpu_setup = __setup_cpu_745x,
627 .oprofile_cpu_type = "ppc/7450", 673 .oprofile_cpu_type = "ppc/7450",
628 .oprofile_type = G4, 674 .oprofile_type = PPC_OPROFILE_G4,
675 .platform = "ppc7450",
629 }, 676 },
630 { /* 7447A */ 677 { /* 7447A */
631 .pvr_mask = 0xffff0000, 678 .pvr_mask = 0xffff0000,
@@ -638,7 +685,8 @@ struct cpu_spec cpu_specs[] = {
638 .num_pmcs = 6, 685 .num_pmcs = 6,
639 .cpu_setup = __setup_cpu_745x, 686 .cpu_setup = __setup_cpu_745x,
640 .oprofile_cpu_type = "ppc/7450", 687 .oprofile_cpu_type = "ppc/7450",
641 .oprofile_type = G4, 688 .oprofile_type = PPC_OPROFILE_G4,
689 .platform = "ppc7450",
642 }, 690 },
643 { /* 7448 */ 691 { /* 7448 */
644 .pvr_mask = 0xffff0000, 692 .pvr_mask = 0xffff0000,
@@ -651,7 +699,8 @@ struct cpu_spec cpu_specs[] = {
651 .num_pmcs = 6, 699 .num_pmcs = 6,
652 .cpu_setup = __setup_cpu_745x, 700 .cpu_setup = __setup_cpu_745x,
653 .oprofile_cpu_type = "ppc/7450", 701 .oprofile_cpu_type = "ppc/7450",
654 .oprofile_type = G4, 702 .oprofile_type = PPC_OPROFILE_G4,
703 .platform = "ppc7450",
655 }, 704 },
656 { /* 82xx (8240, 8245, 8260 are all 603e cores) */ 705 { /* 82xx (8240, 8245, 8260 are all 603e cores) */
657 .pvr_mask = 0x7fff0000, 706 .pvr_mask = 0x7fff0000,
@@ -661,7 +710,8 @@ struct cpu_spec cpu_specs[] = {
661 .cpu_user_features = COMMON_USER, 710 .cpu_user_features = COMMON_USER,
662 .icache_bsize = 32, 711 .icache_bsize = 32,
663 .dcache_bsize = 32, 712 .dcache_bsize = 32,
664 .cpu_setup = __setup_cpu_603 713 .cpu_setup = __setup_cpu_603,
714 .platform = "ppc603",
665 }, 715 },
666 { /* All G2_LE (603e core, plus some) have the same pvr */ 716 { /* All G2_LE (603e core, plus some) have the same pvr */
667 .pvr_mask = 0x7fff0000, 717 .pvr_mask = 0x7fff0000,
@@ -671,7 +721,8 @@ struct cpu_spec cpu_specs[] = {
671 .cpu_user_features = COMMON_USER, 721 .cpu_user_features = COMMON_USER,
672 .icache_bsize = 32, 722 .icache_bsize = 32,
673 .dcache_bsize = 32, 723 .dcache_bsize = 32,
674 .cpu_setup = __setup_cpu_603 724 .cpu_setup = __setup_cpu_603,
725 .platform = "ppc603",
675 }, 726 },
676 { /* e300 (a 603e core, plus some) on 83xx */ 727 { /* e300 (a 603e core, plus some) on 83xx */
677 .pvr_mask = 0x7fff0000, 728 .pvr_mask = 0x7fff0000,
@@ -681,7 +732,8 @@ struct cpu_spec cpu_specs[] = {
681 .cpu_user_features = COMMON_USER, 732 .cpu_user_features = COMMON_USER,
682 .icache_bsize = 32, 733 .icache_bsize = 32,
683 .dcache_bsize = 32, 734 .dcache_bsize = 32,
684 .cpu_setup = __setup_cpu_603 735 .cpu_setup = __setup_cpu_603,
736 .platform = "ppc603",
685 }, 737 },
686 { /* default match, we assume split I/D cache & TB (non-601)... */ 738 { /* default match, we assume split I/D cache & TB (non-601)... */
687 .pvr_mask = 0x00000000, 739 .pvr_mask = 0x00000000,
@@ -691,6 +743,7 @@ struct cpu_spec cpu_specs[] = {
691 .cpu_user_features = COMMON_USER, 743 .cpu_user_features = COMMON_USER,
692 .icache_bsize = 32, 744 .icache_bsize = 32,
693 .dcache_bsize = 32, 745 .dcache_bsize = 32,
746 .platform = "ppc603",
694 }, 747 },
695#endif /* CLASSIC_PPC */ 748#endif /* CLASSIC_PPC */
696#ifdef CONFIG_8xx 749#ifdef CONFIG_8xx
@@ -704,6 +757,7 @@ struct cpu_spec cpu_specs[] = {
704 .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, 757 .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
705 .icache_bsize = 16, 758 .icache_bsize = 16,
706 .dcache_bsize = 16, 759 .dcache_bsize = 16,
760 .platform = "ppc823",
707 }, 761 },
708#endif /* CONFIG_8xx */ 762#endif /* CONFIG_8xx */
709#ifdef CONFIG_40x 763#ifdef CONFIG_40x
@@ -715,6 +769,7 @@ struct cpu_spec cpu_specs[] = {
715 .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, 769 .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
716 .icache_bsize = 16, 770 .icache_bsize = 16,
717 .dcache_bsize = 16, 771 .dcache_bsize = 16,
772 .platform = "ppc403",
718 }, 773 },
719 { /* 403GCX */ 774 { /* 403GCX */
720 .pvr_mask = 0xffffff00, 775 .pvr_mask = 0xffffff00,
@@ -725,6 +780,7 @@ struct cpu_spec cpu_specs[] = {
725 PPC_FEATURE_HAS_MMU | PPC_FEATURE_NO_TB, 780 PPC_FEATURE_HAS_MMU | PPC_FEATURE_NO_TB,
726 .icache_bsize = 16, 781 .icache_bsize = 16,
727 .dcache_bsize = 16, 782 .dcache_bsize = 16,
783 .platform = "ppc403",
728 }, 784 },
729 { /* 403G ?? */ 785 { /* 403G ?? */
730 .pvr_mask = 0xffff0000, 786 .pvr_mask = 0xffff0000,
@@ -734,6 +790,7 @@ struct cpu_spec cpu_specs[] = {
734 .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, 790 .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
735 .icache_bsize = 16, 791 .icache_bsize = 16,
736 .dcache_bsize = 16, 792 .dcache_bsize = 16,
793 .platform = "ppc403",
737 }, 794 },
738 { /* 405GP */ 795 { /* 405GP */
739 .pvr_mask = 0xffff0000, 796 .pvr_mask = 0xffff0000,
@@ -744,6 +801,7 @@ struct cpu_spec cpu_specs[] = {
744 PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, 801 PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
745 .icache_bsize = 32, 802 .icache_bsize = 32,
746 .dcache_bsize = 32, 803 .dcache_bsize = 32,
804 .platform = "ppc405",
747 }, 805 },
748 { /* STB 03xxx */ 806 { /* STB 03xxx */
749 .pvr_mask = 0xffff0000, 807 .pvr_mask = 0xffff0000,
@@ -754,6 +812,7 @@ struct cpu_spec cpu_specs[] = {
754 PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, 812 PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
755 .icache_bsize = 32, 813 .icache_bsize = 32,
756 .dcache_bsize = 32, 814 .dcache_bsize = 32,
815 .platform = "ppc405",
757 }, 816 },
758 { /* STB 04xxx */ 817 { /* STB 04xxx */
759 .pvr_mask = 0xffff0000, 818 .pvr_mask = 0xffff0000,
@@ -764,6 +823,7 @@ struct cpu_spec cpu_specs[] = {
764 PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, 823 PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
765 .icache_bsize = 32, 824 .icache_bsize = 32,
766 .dcache_bsize = 32, 825 .dcache_bsize = 32,
826 .platform = "ppc405",
767 }, 827 },
768 { /* NP405L */ 828 { /* NP405L */
769 .pvr_mask = 0xffff0000, 829 .pvr_mask = 0xffff0000,
@@ -774,6 +834,7 @@ struct cpu_spec cpu_specs[] = {
774 PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, 834 PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
775 .icache_bsize = 32, 835 .icache_bsize = 32,
776 .dcache_bsize = 32, 836 .dcache_bsize = 32,
837 .platform = "ppc405",
777 }, 838 },
778 { /* NP4GS3 */ 839 { /* NP4GS3 */
779 .pvr_mask = 0xffff0000, 840 .pvr_mask = 0xffff0000,
@@ -784,6 +845,7 @@ struct cpu_spec cpu_specs[] = {
784 PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, 845 PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
785 .icache_bsize = 32, 846 .icache_bsize = 32,
786 .dcache_bsize = 32, 847 .dcache_bsize = 32,
848 .platform = "ppc405",
787 }, 849 },
788 { /* NP405H */ 850 { /* NP405H */
789 .pvr_mask = 0xffff0000, 851 .pvr_mask = 0xffff0000,
@@ -794,6 +856,7 @@ struct cpu_spec cpu_specs[] = {
794 PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, 856 PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
795 .icache_bsize = 32, 857 .icache_bsize = 32,
796 .dcache_bsize = 32, 858 .dcache_bsize = 32,
859 .platform = "ppc405",
797 }, 860 },
798 { /* 405GPr */ 861 { /* 405GPr */
799 .pvr_mask = 0xffff0000, 862 .pvr_mask = 0xffff0000,
@@ -804,6 +867,7 @@ struct cpu_spec cpu_specs[] = {
804 PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, 867 PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
805 .icache_bsize = 32, 868 .icache_bsize = 32,
806 .dcache_bsize = 32, 869 .dcache_bsize = 32,
870 .platform = "ppc405",
807 }, 871 },
808 { /* STBx25xx */ 872 { /* STBx25xx */
809 .pvr_mask = 0xffff0000, 873 .pvr_mask = 0xffff0000,
@@ -814,6 +878,7 @@ struct cpu_spec cpu_specs[] = {
814 PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, 878 PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
815 .icache_bsize = 32, 879 .icache_bsize = 32,
816 .dcache_bsize = 32, 880 .dcache_bsize = 32,
881 .platform = "ppc405",
817 }, 882 },
818 { /* 405LP */ 883 { /* 405LP */
819 .pvr_mask = 0xffff0000, 884 .pvr_mask = 0xffff0000,
@@ -823,6 +888,7 @@ struct cpu_spec cpu_specs[] = {
823 .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, 888 .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
824 .icache_bsize = 32, 889 .icache_bsize = 32,
825 .dcache_bsize = 32, 890 .dcache_bsize = 32,
891 .platform = "ppc405",
826 }, 892 },
827 { /* Xilinx Virtex-II Pro */ 893 { /* Xilinx Virtex-II Pro */
828 .pvr_mask = 0xffff0000, 894 .pvr_mask = 0xffff0000,
@@ -833,6 +899,7 @@ struct cpu_spec cpu_specs[] = {
833 PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, 899 PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
834 .icache_bsize = 32, 900 .icache_bsize = 32,
835 .dcache_bsize = 32, 901 .dcache_bsize = 32,
902 .platform = "ppc405",
836 }, 903 },
837 { /* 405EP */ 904 { /* 405EP */
838 .pvr_mask = 0xffff0000, 905 .pvr_mask = 0xffff0000,
@@ -843,6 +910,7 @@ struct cpu_spec cpu_specs[] = {
843 PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, 910 PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
844 .icache_bsize = 32, 911 .icache_bsize = 32,
845 .dcache_bsize = 32, 912 .dcache_bsize = 32,
913 .platform = "ppc405",
846 }, 914 },
847 915
848#endif /* CONFIG_40x */ 916#endif /* CONFIG_40x */
@@ -852,81 +920,90 @@ struct cpu_spec cpu_specs[] = {
852 .pvr_value = 0x40000850, 920 .pvr_value = 0x40000850,
853 .cpu_name = "440EP Rev. A", 921 .cpu_name = "440EP Rev. A",
854 .cpu_features = CPU_FTRS_44X, 922 .cpu_features = CPU_FTRS_44X,
855 .cpu_user_features = COMMON_USER, /* 440EP has an FPU */ 923 .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
856 .icache_bsize = 32, 924 .icache_bsize = 32,
857 .dcache_bsize = 32, 925 .dcache_bsize = 32,
926 .platform = "ppc440",
858 }, 927 },
859 { 928 {
860 .pvr_mask = 0xf0000fff, 929 .pvr_mask = 0xf0000fff,
861 .pvr_value = 0x400008d3, 930 .pvr_value = 0x400008d3,
862 .cpu_name = "440EP Rev. B", 931 .cpu_name = "440EP Rev. B",
863 .cpu_features = CPU_FTRS_44X, 932 .cpu_features = CPU_FTRS_44X,
864 .cpu_user_features = COMMON_USER, /* 440EP has an FPU */ 933 .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
865 .icache_bsize = 32, 934 .icache_bsize = 32,
866 .dcache_bsize = 32, 935 .dcache_bsize = 32,
936 .platform = "ppc440",
867 }, 937 },
868 { /* 440GP Rev. B */ 938 { /* 440GP Rev. B */
869 .pvr_mask = 0xf0000fff, 939 .pvr_mask = 0xf0000fff,
870 .pvr_value = 0x40000440, 940 .pvr_value = 0x40000440,
871 .cpu_name = "440GP Rev. B", 941 .cpu_name = "440GP Rev. B",
872 .cpu_features = CPU_FTRS_44X, 942 .cpu_features = CPU_FTRS_44X,
873 .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, 943 .cpu_user_features = COMMON_USER_BOOKE,
874 .icache_bsize = 32, 944 .icache_bsize = 32,
875 .dcache_bsize = 32, 945 .dcache_bsize = 32,
946 .platform = "ppc440gp",
876 }, 947 },
877 { /* 440GP Rev. C */ 948 { /* 440GP Rev. C */
878 .pvr_mask = 0xf0000fff, 949 .pvr_mask = 0xf0000fff,
879 .pvr_value = 0x40000481, 950 .pvr_value = 0x40000481,
880 .cpu_name = "440GP Rev. C", 951 .cpu_name = "440GP Rev. C",
881 .cpu_features = CPU_FTRS_44X, 952 .cpu_features = CPU_FTRS_44X,
882 .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, 953 .cpu_user_features = COMMON_USER_BOOKE,
883 .icache_bsize = 32, 954 .icache_bsize = 32,
884 .dcache_bsize = 32, 955 .dcache_bsize = 32,
956 .platform = "ppc440gp",
885 }, 957 },
886 { /* 440GX Rev. A */ 958 { /* 440GX Rev. A */
887 .pvr_mask = 0xf0000fff, 959 .pvr_mask = 0xf0000fff,
888 .pvr_value = 0x50000850, 960 .pvr_value = 0x50000850,
889 .cpu_name = "440GX Rev. A", 961 .cpu_name = "440GX Rev. A",
890 .cpu_features = CPU_FTRS_44X, 962 .cpu_features = CPU_FTRS_44X,
891 .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, 963 .cpu_user_features = COMMON_USER_BOOKE,
892 .icache_bsize = 32, 964 .icache_bsize = 32,
893 .dcache_bsize = 32, 965 .dcache_bsize = 32,
966 .platform = "ppc440",
894 }, 967 },
895 { /* 440GX Rev. B */ 968 { /* 440GX Rev. B */
896 .pvr_mask = 0xf0000fff, 969 .pvr_mask = 0xf0000fff,
897 .pvr_value = 0x50000851, 970 .pvr_value = 0x50000851,
898 .cpu_name = "440GX Rev. B", 971 .cpu_name = "440GX Rev. B",
899 .cpu_features = CPU_FTRS_44X, 972 .cpu_features = CPU_FTRS_44X,
900 .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, 973 .cpu_user_features = COMMON_USER_BOOKE,
901 .icache_bsize = 32, 974 .icache_bsize = 32,
902 .dcache_bsize = 32, 975 .dcache_bsize = 32,
976 .platform = "ppc440",
903 }, 977 },
904 { /* 440GX Rev. C */ 978 { /* 440GX Rev. C */
905 .pvr_mask = 0xf0000fff, 979 .pvr_mask = 0xf0000fff,
906 .pvr_value = 0x50000892, 980 .pvr_value = 0x50000892,
907 .cpu_name = "440GX Rev. C", 981 .cpu_name = "440GX Rev. C",
908 .cpu_features = CPU_FTRS_44X, 982 .cpu_features = CPU_FTRS_44X,
909 .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, 983 .cpu_user_features = COMMON_USER_BOOKE,
910 .icache_bsize = 32, 984 .icache_bsize = 32,
911 .dcache_bsize = 32, 985 .dcache_bsize = 32,
986 .platform = "ppc440",
912 }, 987 },
913 { /* 440GX Rev. F */ 988 { /* 440GX Rev. F */
914 .pvr_mask = 0xf0000fff, 989 .pvr_mask = 0xf0000fff,
915 .pvr_value = 0x50000894, 990 .pvr_value = 0x50000894,
916 .cpu_name = "440GX Rev. F", 991 .cpu_name = "440GX Rev. F",
917 .cpu_features = CPU_FTRS_44X, 992 .cpu_features = CPU_FTRS_44X,
918 .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, 993 .cpu_user_features = COMMON_USER_BOOKE,
919 .icache_bsize = 32, 994 .icache_bsize = 32,
920 .dcache_bsize = 32, 995 .dcache_bsize = 32,
996 .platform = "ppc440",
921 }, 997 },
922 { /* 440SP Rev. A */ 998 { /* 440SP Rev. A */
923 .pvr_mask = 0xff000fff, 999 .pvr_mask = 0xff000fff,
924 .pvr_value = 0x53000891, 1000 .pvr_value = 0x53000891,
925 .cpu_name = "440SP Rev. A", 1001 .cpu_name = "440SP Rev. A",
926 .cpu_features = CPU_FTRS_44X, 1002 .cpu_features = CPU_FTRS_44X,
927 .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, 1003 .cpu_user_features = COMMON_USER_BOOKE,
928 .icache_bsize = 32, 1004 .icache_bsize = 32,
929 .dcache_bsize = 32, 1005 .dcache_bsize = 32,
1006 .platform = "ppc440",
930 }, 1007 },
931 { /* 440SPe Rev. A */ 1008 { /* 440SPe Rev. A */
932 .pvr_mask = 0xff000fff, 1009 .pvr_mask = 0xff000fff,
@@ -934,9 +1011,10 @@ struct cpu_spec cpu_specs[] = {
934 .cpu_name = "440SPe Rev. A", 1011 .cpu_name = "440SPe Rev. A",
935 .cpu_features = CPU_FTR_SPLIT_ID_CACHE | 1012 .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
936 CPU_FTR_USE_TB, 1013 CPU_FTR_USE_TB,
937 .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, 1014 .cpu_user_features = COMMON_USER_BOOKE,
938 .icache_bsize = 32, 1015 .icache_bsize = 32,
939 .dcache_bsize = 32, 1016 .dcache_bsize = 32,
1017 .platform = "ppc440",
940 }, 1018 },
941#endif /* CONFIG_44x */ 1019#endif /* CONFIG_44x */
942#ifdef CONFIG_FSL_BOOKE 1020#ifdef CONFIG_FSL_BOOKE
@@ -946,10 +1024,11 @@ struct cpu_spec cpu_specs[] = {
946 .cpu_name = "e200z5", 1024 .cpu_name = "e200z5",
947 /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ 1025 /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */
948 .cpu_features = CPU_FTRS_E200, 1026 .cpu_features = CPU_FTRS_E200,
949 .cpu_user_features = PPC_FEATURE_32 | 1027 .cpu_user_features = COMMON_USER_BOOKE |
950 PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_EFP_SINGLE | 1028 PPC_FEATURE_HAS_EFP_SINGLE |
951 PPC_FEATURE_UNIFIED_CACHE, 1029 PPC_FEATURE_UNIFIED_CACHE,
952 .dcache_bsize = 32, 1030 .dcache_bsize = 32,
1031 .platform = "ppc5554",
953 }, 1032 },
954 { /* e200z6 */ 1033 { /* e200z6 */
955 .pvr_mask = 0xfff00000, 1034 .pvr_mask = 0xfff00000,
@@ -957,11 +1036,12 @@ struct cpu_spec cpu_specs[] = {
957 .cpu_name = "e200z6", 1036 .cpu_name = "e200z6",
958 /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ 1037 /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */
959 .cpu_features = CPU_FTRS_E200, 1038 .cpu_features = CPU_FTRS_E200,
960 .cpu_user_features = PPC_FEATURE_32 | 1039 .cpu_user_features = COMMON_USER_BOOKE |
961 PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP | 1040 PPC_FEATURE_SPE_COMP |
962 PPC_FEATURE_HAS_EFP_SINGLE | 1041 PPC_FEATURE_HAS_EFP_SINGLE |
963 PPC_FEATURE_UNIFIED_CACHE, 1042 PPC_FEATURE_UNIFIED_CACHE,
964 .dcache_bsize = 32, 1043 .dcache_bsize = 32,
1044 .platform = "ppc5554",
965 }, 1045 },
966 { /* e500 */ 1046 { /* e500 */
967 .pvr_mask = 0xffff0000, 1047 .pvr_mask = 0xffff0000,
@@ -969,14 +1049,15 @@ struct cpu_spec cpu_specs[] = {
969 .cpu_name = "e500", 1049 .cpu_name = "e500",
970 /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ 1050 /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */
971 .cpu_features = CPU_FTRS_E500, 1051 .cpu_features = CPU_FTRS_E500,
972 .cpu_user_features = PPC_FEATURE_32 | 1052 .cpu_user_features = COMMON_USER_BOOKE |
973 PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP | 1053 PPC_FEATURE_SPE_COMP |
974 PPC_FEATURE_HAS_EFP_SINGLE, 1054 PPC_FEATURE_HAS_EFP_SINGLE,
975 .icache_bsize = 32, 1055 .icache_bsize = 32,
976 .dcache_bsize = 32, 1056 .dcache_bsize = 32,
977 .num_pmcs = 4, 1057 .num_pmcs = 4,
978 .oprofile_cpu_type = "ppc/e500", 1058 .oprofile_cpu_type = "ppc/e500",
979 .oprofile_type = BOOKE, 1059 .oprofile_type = PPC_OPROFILE_BOOKE,
1060 .platform = "ppc8540",
980 }, 1061 },
981 { /* e500v2 */ 1062 { /* e500v2 */
982 .pvr_mask = 0xffff0000, 1063 .pvr_mask = 0xffff0000,
@@ -984,14 +1065,16 @@ struct cpu_spec cpu_specs[] = {
984 .cpu_name = "e500v2", 1065 .cpu_name = "e500v2",
985 /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ 1066 /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */
986 .cpu_features = CPU_FTRS_E500_2, 1067 .cpu_features = CPU_FTRS_E500_2,
987 .cpu_user_features = PPC_FEATURE_32 | 1068 .cpu_user_features = COMMON_USER_BOOKE |
988 PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP | 1069 PPC_FEATURE_SPE_COMP |
989 PPC_FEATURE_HAS_EFP_SINGLE | PPC_FEATURE_HAS_EFP_DOUBLE, 1070 PPC_FEATURE_HAS_EFP_SINGLE |
1071 PPC_FEATURE_HAS_EFP_DOUBLE,
990 .icache_bsize = 32, 1072 .icache_bsize = 32,
991 .dcache_bsize = 32, 1073 .dcache_bsize = 32,
992 .num_pmcs = 4, 1074 .num_pmcs = 4,
993 .oprofile_cpu_type = "ppc/e500", 1075 .oprofile_cpu_type = "ppc/e500",
994 .oprofile_type = BOOKE, 1076 .oprofile_type = PPC_OPROFILE_BOOKE,
1077 .platform = "ppc8548",
995 }, 1078 },
996#endif 1079#endif
997#if !CLASSIC_PPC 1080#if !CLASSIC_PPC
@@ -1003,6 +1086,7 @@ struct cpu_spec cpu_specs[] = {
1003 .cpu_user_features = PPC_FEATURE_32, 1086 .cpu_user_features = PPC_FEATURE_32,
1004 .icache_bsize = 32, 1087 .icache_bsize = 32,
1005 .dcache_bsize = 32, 1088 .dcache_bsize = 32,
1089 .platform = "powerpc",
1006 } 1090 }
1007#endif /* !CLASSIC_PPC */ 1091#endif /* !CLASSIC_PPC */
1008#endif /* CONFIG_PPC32 */ 1092#endif /* CONFIG_PPC32 */
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index 036b71d2adfc..d8da2a35c0a4 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -988,7 +988,7 @@ _GLOBAL(enter_rtas)
988 stwu r1,-INT_FRAME_SIZE(r1) 988 stwu r1,-INT_FRAME_SIZE(r1)
989 mflr r0 989 mflr r0
990 stw r0,INT_FRAME_SIZE+4(r1) 990 stw r0,INT_FRAME_SIZE+4(r1)
991 LOADADDR(r4, rtas) 991 LOAD_REG_ADDR(r4, rtas)
992 lis r6,1f@ha /* physical return address for rtas */ 992 lis r6,1f@ha /* physical return address for rtas */
993 addi r6,r6,1f@l 993 addi r6,r6,1f@l
994 tophys(r6,r6) 994 tophys(r6,r6)
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index aacebb33e98a..542036318866 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -511,7 +511,8 @@ restore:
511 cmpdi 0,r5,0 511 cmpdi 0,r5,0
512 beq 4f 512 beq 4f
513 /* Check for pending interrupts (iSeries) */ 513 /* Check for pending interrupts (iSeries) */
514 ld r3,PACALPPACA+LPPACAANYINT(r13) 514 ld r3,PACALPPACAPTR(r13)
515 ld r3,LPPACAANYINT(r3)
515 cmpdi r3,0 516 cmpdi r3,0
516 beq+ 4f /* skip do_IRQ if no interrupts */ 517 beq+ 4f /* skip do_IRQ if no interrupts */
517 518
@@ -689,9 +690,8 @@ _GLOBAL(enter_rtas)
689 std r6,PACASAVEDMSR(r13) 690 std r6,PACASAVEDMSR(r13)
690 691
691 /* Setup our real return addr */ 692 /* Setup our real return addr */
692 SET_REG_TO_LABEL(r4,.rtas_return_loc) 693 LOAD_REG_ADDR(r4,.rtas_return_loc)
693 SET_REG_TO_CONST(r9,PAGE_OFFSET) 694 clrldi r4,r4,2 /* convert to realmode address */
694 sub r4,r4,r9
695 mtlr r4 695 mtlr r4
696 696
697 li r0,0 697 li r0,0
@@ -706,7 +706,7 @@ _GLOBAL(enter_rtas)
706 sync /* disable interrupts so SRR0/1 */ 706 sync /* disable interrupts so SRR0/1 */
707 mtmsrd r0 /* don't get trashed */ 707 mtmsrd r0 /* don't get trashed */
708 708
709 SET_REG_TO_LABEL(r4,rtas) 709 LOAD_REG_ADDR(r4, rtas)
710 ld r5,RTASENTRY(r4) /* get the rtas->entry value */ 710 ld r5,RTASENTRY(r4) /* get the rtas->entry value */
711 ld r4,RTASBASE(r4) /* get the rtas->base value */ 711 ld r4,RTASBASE(r4) /* get the rtas->base value */
712 712
@@ -718,8 +718,7 @@ _GLOBAL(enter_rtas)
718_STATIC(rtas_return_loc) 718_STATIC(rtas_return_loc)
719 /* relocation is off at this point */ 719 /* relocation is off at this point */
720 mfspr r4,SPRN_SPRG3 /* Get PACA */ 720 mfspr r4,SPRN_SPRG3 /* Get PACA */
721 SET_REG_TO_CONST(r5, PAGE_OFFSET) 721 clrldi r4,r4,2 /* convert to realmode address */
722 sub r4,r4,r5 /* RELOC the PACA base pointer */
723 722
724 mfmsr r6 723 mfmsr r6
725 li r0,MSR_RI 724 li r0,MSR_RI
@@ -728,7 +727,7 @@ _STATIC(rtas_return_loc)
728 mtmsrd r6 727 mtmsrd r6
729 728
730 ld r1,PACAR1(r4) /* Restore our SP */ 729 ld r1,PACAR1(r4) /* Restore our SP */
731 LOADADDR(r3,.rtas_restore_regs) 730 LOAD_REG_IMMEDIATE(r3,.rtas_restore_regs)
732 ld r4,PACASAVEDMSR(r4) /* Restore our MSR */ 731 ld r4,PACASAVEDMSR(r4) /* Restore our MSR */
733 732
734 mtspr SPRN_SRR0,r3 733 mtspr SPRN_SRR0,r3
diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S
index b780b42c95fc..e4362dfa37fb 100644
--- a/arch/powerpc/kernel/fpu.S
+++ b/arch/powerpc/kernel/fpu.S
@@ -39,9 +39,9 @@ _GLOBAL(load_up_fpu)
39 * to another. Instead we call giveup_fpu in switch_to. 39 * to another. Instead we call giveup_fpu in switch_to.
40 */ 40 */
41#ifndef CONFIG_SMP 41#ifndef CONFIG_SMP
42 LOADBASE(r3, last_task_used_math) 42 LOAD_REG_ADDRBASE(r3, last_task_used_math)
43 toreal(r3) 43 toreal(r3)
44 PPC_LL r4,OFF(last_task_used_math)(r3) 44 PPC_LL r4,ADDROFF(last_task_used_math)(r3)
45 PPC_LCMPI 0,r4,0 45 PPC_LCMPI 0,r4,0
46 beq 1f 46 beq 1f
47 toreal(r4) 47 toreal(r4)
@@ -77,7 +77,7 @@ _GLOBAL(load_up_fpu)
77#ifndef CONFIG_SMP 77#ifndef CONFIG_SMP
78 subi r4,r5,THREAD 78 subi r4,r5,THREAD
79 fromreal(r4) 79 fromreal(r4)
80 PPC_STL r4,OFF(last_task_used_math)(r3) 80 PPC_STL r4,ADDROFF(last_task_used_math)(r3)
81#endif /* CONFIG_SMP */ 81#endif /* CONFIG_SMP */
82 /* restore registers and return */ 82 /* restore registers and return */
83 /* we haven't used ctr or xer or lr */ 83 /* we haven't used ctr or xer or lr */
@@ -113,8 +113,8 @@ _GLOBAL(giveup_fpu)
1131: 1131:
114#ifndef CONFIG_SMP 114#ifndef CONFIG_SMP
115 li r5,0 115 li r5,0
116 LOADBASE(r4,last_task_used_math) 116 LOAD_REG_ADDRBASE(r4,last_task_used_math)
117 PPC_STL r5,OFF(last_task_used_math)(r4) 117 PPC_STL r5,ADDROFF(last_task_used_math)(r4)
118#endif /* CONFIG_SMP */ 118#endif /* CONFIG_SMP */
119 blr 119 blr
120 120
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 1c066d125375..308268466342 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -154,12 +154,12 @@ _GLOBAL(__secondary_hold)
154 bne 100b 154 bne 100b
155 155
156#ifdef CONFIG_HMT 156#ifdef CONFIG_HMT
157 LOADADDR(r4, .hmt_init) 157 SET_REG_IMMEDIATE(r4, .hmt_init)
158 mtctr r4 158 mtctr r4
159 bctr 159 bctr
160#else 160#else
161#ifdef CONFIG_SMP 161#ifdef CONFIG_SMP
162 LOADADDR(r4, .pSeries_secondary_smp_init) 162 LOAD_REG_IMMEDIATE(r4, .pSeries_secondary_smp_init)
163 mtctr r4 163 mtctr r4
164 mr r3,r24 164 mr r3,r24
165 bctr 165 bctr
@@ -205,9 +205,10 @@ exception_marker:
205#define EX_LR 72 205#define EX_LR 72
206 206
207/* 207/*
208 * We're short on space and time in the exception prolog, so we can't use 208 * We're short on space and time in the exception prolog, so we can't
209 * the normal LOADADDR macro. Normally we just need the low halfword of the 209 * use the normal SET_REG_IMMEDIATE macro. Normally we just need the
210 * address, but for Kdump we need the whole low word. 210 * low halfword of the address, but for Kdump we need the whole low
211 * word.
211 */ 212 */
212#ifdef CONFIG_CRASH_DUMP 213#ifdef CONFIG_CRASH_DUMP
213#define LOAD_HANDLER(reg, label) \ 214#define LOAD_HANDLER(reg, label) \
@@ -254,8 +255,9 @@ exception_marker:
254 255
255#define EXCEPTION_PROLOG_ISERIES_2 \ 256#define EXCEPTION_PROLOG_ISERIES_2 \
256 mfmsr r10; \ 257 mfmsr r10; \
257 ld r11,PACALPPACA+LPPACASRR0(r13); \ 258 ld r12,PACALPPACAPTR(r13); \
258 ld r12,PACALPPACA+LPPACASRR1(r13); \ 259 ld r11,LPPACASRR0(r12); \
260 ld r12,LPPACASRR1(r12); \
259 ori r10,r10,MSR_RI; \ 261 ori r10,r10,MSR_RI; \
260 mtmsrd r10,1 262 mtmsrd r10,1
261 263
@@ -634,7 +636,8 @@ data_access_slb_iSeries:
634 std r12,PACA_EXSLB+EX_R12(r13) 636 std r12,PACA_EXSLB+EX_R12(r13)
635 mfspr r10,SPRN_SPRG1 637 mfspr r10,SPRN_SPRG1
636 std r10,PACA_EXSLB+EX_R13(r13) 638 std r10,PACA_EXSLB+EX_R13(r13)
637 ld r12,PACALPPACA+LPPACASRR1(r13); 639 ld r12,PACALPPACAPTR(r13)
640 ld r12,LPPACASRR1(r12)
638 b .slb_miss_realmode 641 b .slb_miss_realmode
639 642
640 STD_EXCEPTION_ISERIES(0x400, instruction_access, PACA_EXGEN) 643 STD_EXCEPTION_ISERIES(0x400, instruction_access, PACA_EXGEN)
@@ -644,7 +647,8 @@ instruction_access_slb_iSeries:
644 mtspr SPRN_SPRG1,r13 /* save r13 */ 647 mtspr SPRN_SPRG1,r13 /* save r13 */
645 mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ 648 mfspr r13,SPRN_SPRG3 /* get paca address into r13 */
646 std r3,PACA_EXSLB+EX_R3(r13) 649 std r3,PACA_EXSLB+EX_R3(r13)
647 ld r3,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */ 650 ld r3,PACALPPACAPTR(r13)
651 ld r3,LPPACASRR0(r3) /* get SRR0 value */
648 std r9,PACA_EXSLB+EX_R9(r13) 652 std r9,PACA_EXSLB+EX_R9(r13)
649 mfcr r9 653 mfcr r9
650#ifdef __DISABLED__ 654#ifdef __DISABLED__
@@ -656,7 +660,8 @@ instruction_access_slb_iSeries:
656 std r12,PACA_EXSLB+EX_R12(r13) 660 std r12,PACA_EXSLB+EX_R12(r13)
657 mfspr r10,SPRN_SPRG1 661 mfspr r10,SPRN_SPRG1
658 std r10,PACA_EXSLB+EX_R13(r13) 662 std r10,PACA_EXSLB+EX_R13(r13)
659 ld r12,PACALPPACA+LPPACASRR1(r13); 663 ld r12,PACALPPACAPTR(r13)
664 ld r12,LPPACASRR1(r12)
660 b .slb_miss_realmode 665 b .slb_miss_realmode
661 666
662#ifdef __DISABLED__ 667#ifdef __DISABLED__
@@ -713,7 +718,7 @@ system_reset_iSeries:
713 lbz r23,PACAPROCSTART(r13) /* Test if this processor 718 lbz r23,PACAPROCSTART(r13) /* Test if this processor
714 * should start */ 719 * should start */
715 sync 720 sync
716 LOADADDR(r3,current_set) 721 LOAD_REG_IMMEDIATE(r3,current_set)
717 sldi r28,r24,3 /* get current_set[cpu#] */ 722 sldi r28,r24,3 /* get current_set[cpu#] */
718 ldx r3,r3,r28 723 ldx r3,r3,r28
719 addi r1,r3,THREAD_SIZE 724 addi r1,r3,THREAD_SIZE
@@ -745,17 +750,19 @@ iSeries_secondary_smp_loop:
745 .globl decrementer_iSeries_masked 750 .globl decrementer_iSeries_masked
746decrementer_iSeries_masked: 751decrementer_iSeries_masked:
747 li r11,1 752 li r11,1
748 stb r11,PACALPPACA+LPPACADECRINT(r13) 753 ld r12,PACALPPACAPTR(r13)
749 LOADBASE(r12,tb_ticks_per_jiffy) 754 stb r11,LPPACADECRINT(r12)
750 lwz r12,OFF(tb_ticks_per_jiffy)(r12) 755 LOAD_REG_ADDRBASE(r12,tb_ticks_per_jiffy)
756 lwz r12,ADDROFF(tb_ticks_per_jiffy)(r12)
751 mtspr SPRN_DEC,r12 757 mtspr SPRN_DEC,r12
752 /* fall through */ 758 /* fall through */
753 759
754 .globl hardware_interrupt_iSeries_masked 760 .globl hardware_interrupt_iSeries_masked
755hardware_interrupt_iSeries_masked: 761hardware_interrupt_iSeries_masked:
756 mtcrf 0x80,r9 /* Restore regs */ 762 mtcrf 0x80,r9 /* Restore regs */
757 ld r11,PACALPPACA+LPPACASRR0(r13) 763 ld r12,PACALPPACAPTR(r13)
758 ld r12,PACALPPACA+LPPACASRR1(r13) 764 ld r11,LPPACASRR0(r12)
765 ld r12,LPPACASRR1(r12)
759 mtspr SPRN_SRR0,r11 766 mtspr SPRN_SRR0,r11
760 mtspr SPRN_SRR1,r12 767 mtspr SPRN_SRR1,r12
761 ld r9,PACA_EXGEN+EX_R9(r13) 768 ld r9,PACA_EXGEN+EX_R9(r13)
@@ -994,7 +1001,8 @@ _GLOBAL(slb_miss_realmode)
994 ld r3,PACA_EXSLB+EX_R3(r13) 1001 ld r3,PACA_EXSLB+EX_R3(r13)
995 lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ 1002 lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */
996#ifdef CONFIG_PPC_ISERIES 1003#ifdef CONFIG_PPC_ISERIES
997 ld r11,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */ 1004 ld r11,PACALPPACAPTR(r13)
1005 ld r11,LPPACASRR0(r11) /* get SRR0 value */
998#endif /* CONFIG_PPC_ISERIES */ 1006#endif /* CONFIG_PPC_ISERIES */
999 1007
1000 mtlr r10 1008 mtlr r10
@@ -1412,7 +1420,7 @@ _GLOBAL(pSeries_secondary_smp_init)
1412 * physical cpu id in r24, we need to search the pacas to find 1420 * physical cpu id in r24, we need to search the pacas to find
1413 * which logical id maps to our physical one. 1421 * which logical id maps to our physical one.
1414 */ 1422 */
1415 LOADADDR(r13, paca) /* Get base vaddr of paca array */ 1423 LOAD_REG_IMMEDIATE(r13, paca) /* Get base vaddr of paca array */
1416 li r5,0 /* logical cpu id */ 1424 li r5,0 /* logical cpu id */
14171: lhz r6,PACAHWCPUID(r13) /* Load HW procid from paca */ 14251: lhz r6,PACAHWCPUID(r13) /* Load HW procid from paca */
1418 cmpw r6,r24 /* Compare to our id */ 1426 cmpw r6,r24 /* Compare to our id */
@@ -1446,8 +1454,8 @@ _GLOBAL(pSeries_secondary_smp_init)
1446#ifdef CONFIG_PPC_ISERIES 1454#ifdef CONFIG_PPC_ISERIES
1447_STATIC(__start_initialization_iSeries) 1455_STATIC(__start_initialization_iSeries)
1448 /* Clear out the BSS */ 1456 /* Clear out the BSS */
1449 LOADADDR(r11,__bss_stop) 1457 LOAD_REG_IMMEDIATE(r11,__bss_stop)
1450 LOADADDR(r8,__bss_start) 1458 LOAD_REG_IMMEDIATE(r8,__bss_start)
1451 sub r11,r11,r8 /* bss size */ 1459 sub r11,r11,r8 /* bss size */
1452 addi r11,r11,7 /* round up to an even double word */ 1460 addi r11,r11,7 /* round up to an even double word */
1453 rldicl. r11,r11,61,3 /* shift right by 3 */ 1461 rldicl. r11,r11,61,3 /* shift right by 3 */
@@ -1458,17 +1466,17 @@ _STATIC(__start_initialization_iSeries)
14583: stdu r0,8(r8) 14663: stdu r0,8(r8)
1459 bdnz 3b 1467 bdnz 3b
14604: 14684:
1461 LOADADDR(r1,init_thread_union) 1469 LOAD_REG_IMMEDIATE(r1,init_thread_union)
1462 addi r1,r1,THREAD_SIZE 1470 addi r1,r1,THREAD_SIZE
1463 li r0,0 1471 li r0,0
1464 stdu r0,-STACK_FRAME_OVERHEAD(r1) 1472 stdu r0,-STACK_FRAME_OVERHEAD(r1)
1465 1473
1466 LOADADDR(r3,cpu_specs) 1474 LOAD_REG_IMMEDIATE(r3,cpu_specs)
1467 LOADADDR(r4,cur_cpu_spec) 1475 LOAD_REG_IMMEDIATE(r4,cur_cpu_spec)
1468 li r5,0 1476 li r5,0
1469 bl .identify_cpu 1477 bl .identify_cpu
1470 1478
1471 LOADADDR(r2,__toc_start) 1479 LOAD_REG_IMMEDIATE(r2,__toc_start)
1472 addi r2,r2,0x4000 1480 addi r2,r2,0x4000
1473 addi r2,r2,0x4000 1481 addi r2,r2,0x4000
1474 1482
@@ -1528,7 +1536,7 @@ _GLOBAL(__start_initialization_multiplatform)
1528 li r24,0 1536 li r24,0
1529 1537
1530 /* Switch off MMU if not already */ 1538 /* Switch off MMU if not already */
1531 LOADADDR(r4, .__after_prom_start - KERNELBASE) 1539 LOAD_REG_IMMEDIATE(r4, .__after_prom_start - KERNELBASE)
1532 add r4,r4,r30 1540 add r4,r4,r30
1533 bl .__mmu_off 1541 bl .__mmu_off
1534 b .__after_prom_start 1542 b .__after_prom_start
@@ -1548,7 +1556,7 @@ _STATIC(__boot_from_prom)
1548 /* put a relocation offset into r3 */ 1556 /* put a relocation offset into r3 */
1549 bl .reloc_offset 1557 bl .reloc_offset
1550 1558
1551 LOADADDR(r2,__toc_start) 1559 LOAD_REG_IMMEDIATE(r2,__toc_start)
1552 addi r2,r2,0x4000 1560 addi r2,r2,0x4000
1553 addi r2,r2,0x4000 1561 addi r2,r2,0x4000
1554 1562
@@ -1588,9 +1596,9 @@ _STATIC(__after_prom_start)
1588 */ 1596 */
1589 bl .reloc_offset 1597 bl .reloc_offset
1590 mr r26,r3 1598 mr r26,r3
1591 SET_REG_TO_CONST(r27,KERNELBASE) 1599 LOAD_REG_IMMEDIATE(r27, KERNELBASE)
1592 1600
1593 LOADADDR(r3, PHYSICAL_START) /* target addr */ 1601 LOAD_REG_IMMEDIATE(r3, PHYSICAL_START) /* target addr */
1594 1602
1595 // XXX FIXME: Use phys returned by OF (r30) 1603 // XXX FIXME: Use phys returned by OF (r30)
1596 add r4,r27,r26 /* source addr */ 1604 add r4,r27,r26 /* source addr */
@@ -1598,7 +1606,7 @@ _STATIC(__after_prom_start)
1598 /* i.e. where we are running */ 1606 /* i.e. where we are running */
1599 /* the source addr */ 1607 /* the source addr */
1600 1608
1601 LOADADDR(r5,copy_to_here) /* # bytes of memory to copy */ 1609 LOAD_REG_IMMEDIATE(r5,copy_to_here) /* # bytes of memory to copy */
1602 sub r5,r5,r27 1610 sub r5,r5,r27
1603 1611
1604 li r6,0x100 /* Start offset, the first 0x100 */ 1612 li r6,0x100 /* Start offset, the first 0x100 */
@@ -1608,11 +1616,11 @@ _STATIC(__after_prom_start)
1608 /* this includes the code being */ 1616 /* this includes the code being */
1609 /* executed here. */ 1617 /* executed here. */
1610 1618
1611 LOADADDR(r0, 4f) /* Jump to the copy of this code */ 1619 LOAD_REG_IMMEDIATE(r0, 4f) /* Jump to the copy of this code */
1612 mtctr r0 /* that we just made/relocated */ 1620 mtctr r0 /* that we just made/relocated */
1613 bctr 1621 bctr
1614 1622
16154: LOADADDR(r5,klimit) 16234: LOAD_REG_IMMEDIATE(r5,klimit)
1616 add r5,r5,r26 1624 add r5,r5,r26
1617 ld r5,0(r5) /* get the value of klimit */ 1625 ld r5,0(r5) /* get the value of klimit */
1618 sub r5,r5,r27 1626 sub r5,r5,r27
@@ -1694,7 +1702,7 @@ _GLOBAL(pmac_secondary_start)
1694 mtmsrd r3 /* RI on */ 1702 mtmsrd r3 /* RI on */
1695 1703
1696 /* Set up a paca value for this processor. */ 1704 /* Set up a paca value for this processor. */
1697 LOADADDR(r4, paca) /* Get base vaddr of paca array */ 1705 LOAD_REG_IMMEDIATE(r4, paca) /* Get base vaddr of paca array */
1698 mulli r13,r24,PACA_SIZE /* Calculate vaddr of right paca */ 1706 mulli r13,r24,PACA_SIZE /* Calculate vaddr of right paca */
1699 add r13,r13,r4 /* for this processor. */ 1707 add r13,r13,r4 /* for this processor. */
1700 mtspr SPRN_SPRG3,r13 /* Save vaddr of paca in SPRG3 */ 1708 mtspr SPRN_SPRG3,r13 /* Save vaddr of paca in SPRG3 */
@@ -1731,7 +1739,7 @@ _GLOBAL(__secondary_start)
1731 bl .early_setup_secondary 1739 bl .early_setup_secondary
1732 1740
1733 /* Initialize the kernel stack. Just a repeat for iSeries. */ 1741 /* Initialize the kernel stack. Just a repeat for iSeries. */
1734 LOADADDR(r3,current_set) 1742 LOAD_REG_ADDR(r3, current_set)
1735 sldi r28,r24,3 /* get current_set[cpu#] */ 1743 sldi r28,r24,3 /* get current_set[cpu#] */
1736 ldx r1,r3,r28 1744 ldx r1,r3,r28
1737 addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD 1745 addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD
@@ -1742,8 +1750,8 @@ _GLOBAL(__secondary_start)
1742 mtlr r7 1750 mtlr r7
1743 1751
1744 /* enable MMU and jump to start_secondary */ 1752 /* enable MMU and jump to start_secondary */
1745 LOADADDR(r3,.start_secondary_prolog) 1753 LOAD_REG_ADDR(r3, .start_secondary_prolog)
1746 SET_REG_TO_CONST(r4, MSR_KERNEL) 1754 LOAD_REG_IMMEDIATE(r4, MSR_KERNEL)
1747#ifdef DO_SOFT_DISABLE 1755#ifdef DO_SOFT_DISABLE
1748 ori r4,r4,MSR_EE 1756 ori r4,r4,MSR_EE
1749#endif 1757#endif
@@ -1792,8 +1800,8 @@ _STATIC(start_here_multiplatform)
1792 * be detached from the kernel completely. Besides, we need 1800 * be detached from the kernel completely. Besides, we need
1793 * to clear it now for kexec-style entry. 1801 * to clear it now for kexec-style entry.
1794 */ 1802 */
1795 LOADADDR(r11,__bss_stop) 1803 LOAD_REG_IMMEDIATE(r11,__bss_stop)
1796 LOADADDR(r8,__bss_start) 1804 LOAD_REG_IMMEDIATE(r8,__bss_start)
1797 sub r11,r11,r8 /* bss size */ 1805 sub r11,r11,r8 /* bss size */
1798 addi r11,r11,7 /* round up to an even double word */ 1806 addi r11,r11,7 /* round up to an even double word */
1799 rldicl. r11,r11,61,3 /* shift right by 3 */ 1807 rldicl. r11,r11,61,3 /* shift right by 3 */
@@ -1831,7 +1839,7 @@ _STATIC(start_here_multiplatform)
1831 /* up the htab. This is done because we have relocated the */ 1839 /* up the htab. This is done because we have relocated the */
1832 /* kernel but are still running in real mode. */ 1840 /* kernel but are still running in real mode. */
1833 1841
1834 LOADADDR(r3,init_thread_union) 1842 LOAD_REG_IMMEDIATE(r3,init_thread_union)
1835 add r3,r3,r26 1843 add r3,r3,r26
1836 1844
1837 /* set up a stack pointer (physical address) */ 1845 /* set up a stack pointer (physical address) */
@@ -1840,14 +1848,14 @@ _STATIC(start_here_multiplatform)
1840 stdu r0,-STACK_FRAME_OVERHEAD(r1) 1848 stdu r0,-STACK_FRAME_OVERHEAD(r1)
1841 1849
1842 /* set up the TOC (physical address) */ 1850 /* set up the TOC (physical address) */
1843 LOADADDR(r2,__toc_start) 1851 LOAD_REG_IMMEDIATE(r2,__toc_start)
1844 addi r2,r2,0x4000 1852 addi r2,r2,0x4000
1845 addi r2,r2,0x4000 1853 addi r2,r2,0x4000
1846 add r2,r2,r26 1854 add r2,r2,r26
1847 1855
1848 LOADADDR(r3,cpu_specs) 1856 LOAD_REG_IMMEDIATE(r3, cpu_specs)
1849 add r3,r3,r26 1857 add r3,r3,r26
1850 LOADADDR(r4,cur_cpu_spec) 1858 LOAD_REG_IMMEDIATE(r4,cur_cpu_spec)
1851 add r4,r4,r26 1859 add r4,r4,r26
1852 mr r5,r26 1860 mr r5,r26
1853 bl .identify_cpu 1861 bl .identify_cpu
@@ -1863,11 +1871,11 @@ _STATIC(start_here_multiplatform)
1863 * nowhere it can be initialized differently before we reach this 1871 * nowhere it can be initialized differently before we reach this
1864 * code 1872 * code
1865 */ 1873 */
1866 LOADADDR(r27, boot_cpuid) 1874 LOAD_REG_IMMEDIATE(r27, boot_cpuid)
1867 add r27,r27,r26 1875 add r27,r27,r26
1868 lwz r27,0(r27) 1876 lwz r27,0(r27)
1869 1877
1870 LOADADDR(r24, paca) /* Get base vaddr of paca array */ 1878 LOAD_REG_IMMEDIATE(r24, paca) /* Get base vaddr of paca array */
1871 mulli r13,r27,PACA_SIZE /* Calculate vaddr of right paca */ 1879 mulli r13,r27,PACA_SIZE /* Calculate vaddr of right paca */
1872 add r13,r13,r24 /* for this processor. */ 1880 add r13,r13,r24 /* for this processor. */
1873 add r13,r13,r26 /* convert to physical addr */ 1881 add r13,r13,r26 /* convert to physical addr */
@@ -1880,8 +1888,8 @@ _STATIC(start_here_multiplatform)
1880 mr r3,r31 1888 mr r3,r31
1881 bl .early_setup 1889 bl .early_setup
1882 1890
1883 LOADADDR(r3,.start_here_common) 1891 LOAD_REG_IMMEDIATE(r3, .start_here_common)
1884 SET_REG_TO_CONST(r4, MSR_KERNEL) 1892 LOAD_REG_IMMEDIATE(r4, MSR_KERNEL)
1885 mtspr SPRN_SRR0,r3 1893 mtspr SPRN_SRR0,r3
1886 mtspr SPRN_SRR1,r4 1894 mtspr SPRN_SRR1,r4
1887 rfid 1895 rfid
@@ -1895,7 +1903,7 @@ _STATIC(start_here_common)
1895 /* The following code sets up the SP and TOC now that we are */ 1903 /* The following code sets up the SP and TOC now that we are */
1896 /* running with translation enabled. */ 1904 /* running with translation enabled. */
1897 1905
1898 LOADADDR(r3,init_thread_union) 1906 LOAD_REG_IMMEDIATE(r3,init_thread_union)
1899 1907
1900 /* set up the stack */ 1908 /* set up the stack */
1901 addi r1,r3,THREAD_SIZE 1909 addi r1,r3,THREAD_SIZE
@@ -1908,16 +1916,16 @@ _STATIC(start_here_common)
1908 li r3,0 1916 li r3,0
1909 bl .do_cpu_ftr_fixups 1917 bl .do_cpu_ftr_fixups
1910 1918
1911 LOADADDR(r26, boot_cpuid) 1919 LOAD_REG_IMMEDIATE(r26, boot_cpuid)
1912 lwz r26,0(r26) 1920 lwz r26,0(r26)
1913 1921
1914 LOADADDR(r24, paca) /* Get base vaddr of paca array */ 1922 LOAD_REG_IMMEDIATE(r24, paca) /* Get base vaddr of paca array */
1915 mulli r13,r26,PACA_SIZE /* Calculate vaddr of right paca */ 1923 mulli r13,r26,PACA_SIZE /* Calculate vaddr of right paca */
1916 add r13,r13,r24 /* for this processor. */ 1924 add r13,r13,r24 /* for this processor. */
1917 mtspr SPRN_SPRG3,r13 1925 mtspr SPRN_SPRG3,r13
1918 1926
1919 /* ptr to current */ 1927 /* ptr to current */
1920 LOADADDR(r4,init_task) 1928 LOAD_REG_IMMEDIATE(r4, init_task)
1921 std r4,PACACURRENT(r13) 1929 std r4,PACACURRENT(r13)
1922 1930
1923 /* Load the TOC */ 1931 /* Load the TOC */
@@ -1940,7 +1948,7 @@ _STATIC(start_here_common)
1940 1948
1941_GLOBAL(hmt_init) 1949_GLOBAL(hmt_init)
1942#ifdef CONFIG_HMT 1950#ifdef CONFIG_HMT
1943 LOADADDR(r5, hmt_thread_data) 1951 LOAD_REG_IMMEDIATE(r5, hmt_thread_data)
1944 mfspr r7,SPRN_PVR 1952 mfspr r7,SPRN_PVR
1945 srwi r7,r7,16 1953 srwi r7,r7,16
1946 cmpwi r7,0x34 /* Pulsar */ 1954 cmpwi r7,0x34 /* Pulsar */
@@ -1961,7 +1969,7 @@ _GLOBAL(hmt_init)
1961 b 101f 1969 b 101f
1962 1970
1963__hmt_secondary_hold: 1971__hmt_secondary_hold:
1964 LOADADDR(r5, hmt_thread_data) 1972 LOAD_REG_IMMEDIATE(r5, hmt_thread_data)
1965 clrldi r5,r5,4 1973 clrldi r5,r5,4
1966 li r7,0 1974 li r7,0
1967 mfspr r6,SPRN_PIR 1975 mfspr r6,SPRN_PIR
@@ -1989,7 +1997,7 @@ __hmt_secondary_hold:
1989 1997
1990#ifdef CONFIG_HMT 1998#ifdef CONFIG_HMT
1991_GLOBAL(hmt_start_secondary) 1999_GLOBAL(hmt_start_secondary)
1992 LOADADDR(r4,__hmt_secondary_hold) 2000 LOAD_REG_IMMEDIATE(r4,__hmt_secondary_hold)
1993 clrldi r4,r4,4 2001 clrldi r4,r4,4
1994 mtspr SPRN_NIADORM, r4 2002 mtspr SPRN_NIADORM, r4
1995 mfspr r4, SPRN_MSRDORM 2003 mfspr r4, SPRN_MSRDORM
diff --git a/arch/powerpc/kernel/idle_power4.S b/arch/powerpc/kernel/idle_power4.S
index 1494e2f177f7..c16b4afab582 100644
--- a/arch/powerpc/kernel/idle_power4.S
+++ b/arch/powerpc/kernel/idle_power4.S
@@ -38,14 +38,14 @@ END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
38 /* We must dynamically check for the NAP feature as it 38 /* We must dynamically check for the NAP feature as it
39 * can be cleared by CPU init after the fixups are done 39 * can be cleared by CPU init after the fixups are done
40 */ 40 */
41 LOADBASE(r3,cur_cpu_spec) 41 LOAD_REG_ADDRBASE(r3,cur_cpu_spec)
42 ld r4,OFF(cur_cpu_spec)(r3) 42 ld r4,ADDROFF(cur_cpu_spec)(r3)
43 ld r4,CPU_SPEC_FEATURES(r4) 43 ld r4,CPU_SPEC_FEATURES(r4)
44 andi. r0,r4,CPU_FTR_CAN_NAP 44 andi. r0,r4,CPU_FTR_CAN_NAP
45 beqlr 45 beqlr
46 /* Now check if user or arch enabled NAP mode */ 46 /* Now check if user or arch enabled NAP mode */
47 LOADBASE(r3,powersave_nap) 47 LOAD_REG_ADDRBASE(r3,powersave_nap)
48 lwz r4,OFF(powersave_nap)(r3) 48 lwz r4,ADDROFF(powersave_nap)(r3)
49 cmpwi 0,r4,0 49 cmpwi 0,r4,0
50 beqlr 50 beqlr
51 51
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 5651032d8706..d1fffce86df9 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -238,14 +238,10 @@ void do_IRQ(struct pt_regs *regs)
238 irq_exit(); 238 irq_exit();
239 239
240#ifdef CONFIG_PPC_ISERIES 240#ifdef CONFIG_PPC_ISERIES
241 { 241 if (get_lppaca()->int_dword.fields.decr_int) {
242 struct paca_struct *lpaca = get_paca(); 242 get_lppaca()->int_dword.fields.decr_int = 0;
243 243 /* Signal a fake decrementer interrupt */
244 if (lpaca->lppaca.int_dword.fields.decr_int) { 244 timer_interrupt(regs);
245 lpaca->lppaca.int_dword.fields.decr_int = 0;
246 /* Signal a fake decrementer interrupt */
247 timer_interrupt(regs);
248 }
249 } 245 }
250#endif 246#endif
251} 247}
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c
index 9dda16ccde78..1ae96a8ed7e2 100644
--- a/arch/powerpc/kernel/lparcfg.c
+++ b/arch/powerpc/kernel/lparcfg.c
@@ -55,15 +55,13 @@ static unsigned long get_purr(void)
55{ 55{
56 unsigned long sum_purr = 0; 56 unsigned long sum_purr = 0;
57 int cpu; 57 int cpu;
58 struct paca_struct *lpaca;
59 58
60 for_each_cpu(cpu) { 59 for_each_cpu(cpu) {
61 lpaca = paca + cpu; 60 sum_purr += lppaca[cpu].emulated_time_base;
62 sum_purr += lpaca->lppaca.emulated_time_base;
63 61
64#ifdef PURR_DEBUG 62#ifdef PURR_DEBUG
65 printk(KERN_INFO "get_purr for cpu (%d) has value (%ld) \n", 63 printk(KERN_INFO "get_purr for cpu (%d) has value (%ld) \n",
66 cpu, lpaca->lppaca.emulated_time_base); 64 cpu, lppaca[cpu].emulated_time_base);
67#endif 65#endif
68 } 66 }
69 return sum_purr; 67 return sum_purr;
@@ -79,12 +77,11 @@ static int lparcfg_data(struct seq_file *m, void *v)
79 unsigned long pool_id, lp_index; 77 unsigned long pool_id, lp_index;
80 int shared, entitled_capacity, max_entitled_capacity; 78 int shared, entitled_capacity, max_entitled_capacity;
81 int processors, max_processors; 79 int processors, max_processors;
82 struct paca_struct *lpaca = get_paca();
83 unsigned long purr = get_purr(); 80 unsigned long purr = get_purr();
84 81
85 seq_printf(m, "%s %s \n", MODULE_NAME, MODULE_VERS); 82 seq_printf(m, "%s %s \n", MODULE_NAME, MODULE_VERS);
86 83
87 shared = (int)(lpaca->lppaca_ptr->shared_proc); 84 shared = (int)(get_lppaca()->shared_proc);
88 seq_printf(m, "serial_number=%c%c%c%c%c%c%c\n", 85 seq_printf(m, "serial_number=%c%c%c%c%c%c%c\n",
89 e2a(xItExtVpdPanel.mfgID[2]), 86 e2a(xItExtVpdPanel.mfgID[2]),
90 e2a(xItExtVpdPanel.mfgID[3]), 87 e2a(xItExtVpdPanel.mfgID[3]),
@@ -402,7 +399,7 @@ static int lparcfg_data(struct seq_file *m, void *v)
402 (h_resource >> 0 * 8) & 0xffff); 399 (h_resource >> 0 * 8) & 0xffff);
403 400
404 /* pool related entries are apropriate for shared configs */ 401 /* pool related entries are apropriate for shared configs */
405 if (paca[0].lppaca.shared_proc) { 402 if (lppaca[0].shared_proc) {
406 403
407 h_pic(&pool_idle_time, &pool_procs); 404 h_pic(&pool_idle_time, &pool_procs);
408 405
@@ -451,7 +448,7 @@ static int lparcfg_data(struct seq_file *m, void *v)
451 seq_printf(m, "partition_potential_processors=%d\n", 448 seq_printf(m, "partition_potential_processors=%d\n",
452 partition_potential_processors); 449 partition_potential_processors);
453 450
454 seq_printf(m, "shared_processor_mode=%d\n", paca[0].lppaca.shared_proc); 451 seq_printf(m, "shared_processor_mode=%d\n", lppaca[0].shared_proc);
455 452
456 return 0; 453 return 0;
457} 454}
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index 01d0d97a16e1..be982023409e 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -68,7 +68,7 @@ _GLOBAL(reloc_offset)
68 mflr r0 68 mflr r0
69 bl 1f 69 bl 1f
701: mflr r3 701: mflr r3
71 LOADADDR(r4,1b) 71 LOAD_REG_IMMEDIATE(r4,1b)
72 subf r3,r4,r3 72 subf r3,r4,r3
73 mtlr r0 73 mtlr r0
74 blr 74 blr
@@ -80,7 +80,7 @@ _GLOBAL(add_reloc_offset)
80 mflr r0 80 mflr r0
81 bl 1f 81 bl 1f
821: mflr r5 821: mflr r5
83 LOADADDR(r4,1b) 83 LOAD_REG_IMMEDIATE(r4,1b)
84 subf r5,r4,r5 84 subf r5,r4,r5
85 add r3,r3,r5 85 add r3,r3,r5
86 mtlr r0 86 mtlr r0
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S
index ae48a002f81a..2778cce058e2 100644
--- a/arch/powerpc/kernel/misc_64.S
+++ b/arch/powerpc/kernel/misc_64.S
@@ -39,7 +39,7 @@ _GLOBAL(reloc_offset)
39 mflr r0 39 mflr r0
40 bl 1f 40 bl 1f
411: mflr r3 411: mflr r3
42 LOADADDR(r4,1b) 42 LOAD_REG_IMMEDIATE(r4,1b)
43 subf r3,r4,r3 43 subf r3,r4,r3
44 mtlr r0 44 mtlr r0
45 blr 45 blr
@@ -51,7 +51,7 @@ _GLOBAL(add_reloc_offset)
51 mflr r0 51 mflr r0
52 bl 1f 52 bl 1f
531: mflr r5 531: mflr r5
54 LOADADDR(r4,1b) 54 LOAD_REG_IMMEDIATE(r4,1b)
55 subf r5,r4,r5 55 subf r5,r4,r5
56 add r3,r3,r5 56 add r3,r3,r5
57 mtlr r0 57 mtlr r0
@@ -498,15 +498,15 @@ _GLOBAL(identify_cpu)
498 */ 498 */
499_GLOBAL(do_cpu_ftr_fixups) 499_GLOBAL(do_cpu_ftr_fixups)
500 /* Get CPU 0 features */ 500 /* Get CPU 0 features */
501 LOADADDR(r6,cur_cpu_spec) 501 LOAD_REG_IMMEDIATE(r6,cur_cpu_spec)
502 sub r6,r6,r3 502 sub r6,r6,r3
503 ld r4,0(r6) 503 ld r4,0(r6)
504 sub r4,r4,r3 504 sub r4,r4,r3
505 ld r4,CPU_SPEC_FEATURES(r4) 505 ld r4,CPU_SPEC_FEATURES(r4)
506 /* Get the fixup table */ 506 /* Get the fixup table */
507 LOADADDR(r6,__start___ftr_fixup) 507 LOAD_REG_IMMEDIATE(r6,__start___ftr_fixup)
508 sub r6,r6,r3 508 sub r6,r6,r3
509 LOADADDR(r7,__stop___ftr_fixup) 509 LOAD_REG_IMMEDIATE(r7,__stop___ftr_fixup)
510 sub r7,r7,r3 510 sub r7,r7,r3
511 /* Do the fixup */ 511 /* Do the fixup */
5121: cmpld r6,r7 5121: cmpld r6,r7
diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c
index 7065e40e2f42..22d83d4d1af5 100644
--- a/arch/powerpc/kernel/of_device.c
+++ b/arch/powerpc/kernel/of_device.c
@@ -132,6 +132,8 @@ static int of_device_resume(struct device * dev)
132struct bus_type of_platform_bus_type = { 132struct bus_type of_platform_bus_type = {
133 .name = "of_platform", 133 .name = "of_platform",
134 .match = of_platform_bus_match, 134 .match = of_platform_bus_match,
135 .probe = of_device_probe,
136 .remove = of_device_remove,
135 .suspend = of_device_suspend, 137 .suspend = of_device_suspend,
136 .resume = of_device_resume, 138 .resume = of_device_resume,
137}; 139};
@@ -150,8 +152,6 @@ int of_register_driver(struct of_platform_driver *drv)
150 /* initialize common driver fields */ 152 /* initialize common driver fields */
151 drv->driver.name = drv->name; 153 drv->driver.name = drv->name;
152 drv->driver.bus = &of_platform_bus_type; 154 drv->driver.bus = &of_platform_bus_type;
153 drv->driver.probe = of_device_probe;
154 drv->driver.remove = of_device_remove;
155 155
156 /* register with core */ 156 /* register with core */
157 count = driver_register(&drv->driver); 157 count = driver_register(&drv->driver);
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index 999bdd816769..5d1b708086bd 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -25,6 +25,28 @@
25 * field correctly */ 25 * field correctly */
26extern unsigned long __toc_start; 26extern unsigned long __toc_start;
27 27
28/*
29 * iSeries structure which the hypervisor knows about - this structure
30 * should not cross a page boundary. The vpa_init/register_vpa call
31 * is now known to fail if the lppaca structure crosses a page
32 * boundary. The lppaca is also used on POWER5 pSeries boxes. The
33 * lppaca is 640 bytes long, and cannot readily change since the
34 * hypervisor knows its layout, so a 1kB alignment will suffice to
35 * ensure that it doesn't cross a page boundary.
36 */
37struct lppaca lppaca[] = {
38 [0 ... (NR_CPUS-1)] = {
39 .desc = 0xd397d781, /* "LpPa" */
40 .size = sizeof(struct lppaca),
41 .dyn_proc_status = 2,
42 .decr_val = 0x00ff0000,
43 .fpregs_in_use = 1,
44 .end_of_quantum = 0xfffffffffffffffful,
45 .slb_count = 64,
46 .vmxregs_in_use = 0,
47 },
48};
49
28/* The Paca is an array with one entry per processor. Each contains an 50/* The Paca is an array with one entry per processor. Each contains an
29 * lppaca, which contains the information shared between the 51 * lppaca, which contains the information shared between the
30 * hypervisor and Linux. 52 * hypervisor and Linux.
@@ -35,27 +57,17 @@ extern unsigned long __toc_start;
35 * processor (not thread). 57 * processor (not thread).
36 */ 58 */
37#define PACA_INIT_COMMON(number, start, asrr, asrv) \ 59#define PACA_INIT_COMMON(number, start, asrr, asrv) \
60 .lppaca_ptr = &lppaca[number], \
38 .lock_token = 0x8000, \ 61 .lock_token = 0x8000, \
39 .paca_index = (number), /* Paca Index */ \ 62 .paca_index = (number), /* Paca Index */ \
40 .kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL, \ 63 .kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL, \
41 .stab_real = (asrr), /* Real pointer to segment table */ \ 64 .stab_real = (asrr), /* Real pointer to segment table */ \
42 .stab_addr = (asrv), /* Virt pointer to segment table */ \ 65 .stab_addr = (asrv), /* Virt pointer to segment table */ \
43 .cpu_start = (start), /* Processor start */ \ 66 .cpu_start = (start), /* Processor start */ \
44 .hw_cpu_id = 0xffff, \ 67 .hw_cpu_id = 0xffff,
45 .lppaca = { \
46 .desc = 0xd397d781, /* "LpPa" */ \
47 .size = sizeof(struct lppaca), \
48 .dyn_proc_status = 2, \
49 .decr_val = 0x00ff0000, \
50 .fpregs_in_use = 1, \
51 .end_of_quantum = 0xfffffffffffffffful, \
52 .slb_count = 64, \
53 .vmxregs_in_use = 0, \
54 }, \
55 68
56#ifdef CONFIG_PPC_ISERIES 69#ifdef CONFIG_PPC_ISERIES
57#define PACA_INIT_ISERIES(number) \ 70#define PACA_INIT_ISERIES(number) \
58 .lppaca_ptr = &paca[number].lppaca, \
59 .reg_save_ptr = &iseries_reg_save[number], 71 .reg_save_ptr = &iseries_reg_save[number],
60 72
61#define PACA_INIT(number) \ 73#define PACA_INIT(number) \
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index 16d9a904f3cb..d9a459c144d8 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -230,8 +230,7 @@ EXPORT_SYMBOL(__down_interruptible);
230EXPORT_SYMBOL(cpm_install_handler); 230EXPORT_SYMBOL(cpm_install_handler);
231EXPORT_SYMBOL(cpm_free_handler); 231EXPORT_SYMBOL(cpm_free_handler);
232#endif /* CONFIG_8xx */ 232#endif /* CONFIG_8xx */
233#if defined(CONFIG_8xx) || defined(CONFIG_40x) || defined(CONFIG_85xx) ||\ 233#if defined(CONFIG_8xx) || defined(CONFIG_40x)
234 defined(CONFIG_83xx)
235EXPORT_SYMBOL(__res); 234EXPORT_SYMBOL(__res);
236#endif 235#endif
237 236
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 02e2115323e4..d50c8df0183e 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -1627,6 +1627,11 @@ static void of_node_release(struct kref *kref)
1627 kfree(prop->value); 1627 kfree(prop->value);
1628 kfree(prop); 1628 kfree(prop);
1629 prop = next; 1629 prop = next;
1630
1631 if (!prop) {
1632 prop = node->deadprops;
1633 node->deadprops = NULL;
1634 }
1630 } 1635 }
1631 kfree(node->intrs); 1636 kfree(node->intrs);
1632 kfree(node->full_name); 1637 kfree(node->full_name);
@@ -1774,22 +1779,32 @@ static int __init prom_reconfig_setup(void)
1774__initcall(prom_reconfig_setup); 1779__initcall(prom_reconfig_setup);
1775#endif 1780#endif
1776 1781
1777/* 1782struct property *of_find_property(struct device_node *np, const char *name,
1778 * Find a property with a given name for a given node 1783 int *lenp)
1779 * and return the value.
1780 */
1781unsigned char *get_property(struct device_node *np, const char *name,
1782 int *lenp)
1783{ 1784{
1784 struct property *pp; 1785 struct property *pp;
1785 1786
1787 read_lock(&devtree_lock);
1786 for (pp = np->properties; pp != 0; pp = pp->next) 1788 for (pp = np->properties; pp != 0; pp = pp->next)
1787 if (strcmp(pp->name, name) == 0) { 1789 if (strcmp(pp->name, name) == 0) {
1788 if (lenp != 0) 1790 if (lenp != 0)
1789 *lenp = pp->length; 1791 *lenp = pp->length;
1790 return pp->value; 1792 break;
1791 } 1793 }
1792 return NULL; 1794 read_unlock(&devtree_lock);
1795
1796 return pp;
1797}
1798
1799/*
1800 * Find a property with a given name for a given node
1801 * and return the value.
1802 */
1803unsigned char *get_property(struct device_node *np, const char *name,
1804 int *lenp)
1805{
1806 struct property *pp = of_find_property(np,name,lenp);
1807 return pp ? pp->value : NULL;
1793} 1808}
1794EXPORT_SYMBOL(get_property); 1809EXPORT_SYMBOL(get_property);
1795 1810
@@ -1823,4 +1838,82 @@ int prom_add_property(struct device_node* np, struct property* prop)
1823 return 0; 1838 return 0;
1824} 1839}
1825 1840
1841/*
1842 * Remove a property from a node. Note that we don't actually
1843 * remove it, since we have given out who-knows-how-many pointers
1844 * to the data using get-property. Instead we just move the property
1845 * to the "dead properties" list, so it won't be found any more.
1846 */
1847int prom_remove_property(struct device_node *np, struct property *prop)
1848{
1849 struct property **next;
1850 int found = 0;
1826 1851
1852 write_lock(&devtree_lock);
1853 next = &np->properties;
1854 while (*next) {
1855 if (*next == prop) {
1856 /* found the node */
1857 *next = prop->next;
1858 prop->next = np->deadprops;
1859 np->deadprops = prop;
1860 found = 1;
1861 break;
1862 }
1863 next = &(*next)->next;
1864 }
1865 write_unlock(&devtree_lock);
1866
1867 if (!found)
1868 return -ENODEV;
1869
1870#ifdef CONFIG_PROC_DEVICETREE
1871 /* try to remove the proc node as well */
1872 if (np->pde)
1873 proc_device_tree_remove_prop(np->pde, prop);
1874#endif /* CONFIG_PROC_DEVICETREE */
1875
1876 return 0;
1877}
1878
1879/*
1880 * Update a property in a node. Note that we don't actually
1881 * remove it, since we have given out who-knows-how-many pointers
1882 * to the data using get-property. Instead we just move the property
1883 * to the "dead properties" list, and add the new property to the
1884 * property list
1885 */
1886int prom_update_property(struct device_node *np,
1887 struct property *newprop,
1888 struct property *oldprop)
1889{
1890 struct property **next;
1891 int found = 0;
1892
1893 write_lock(&devtree_lock);
1894 next = &np->properties;
1895 while (*next) {
1896 if (*next == oldprop) {
1897 /* found the node */
1898 newprop->next = oldprop->next;
1899 *next = newprop;
1900 oldprop->next = np->deadprops;
1901 np->deadprops = oldprop;
1902 found = 1;
1903 break;
1904 }
1905 next = &(*next)->next;
1906 }
1907 write_unlock(&devtree_lock);
1908
1909 if (!found)
1910 return -ENODEV;
1911
1912#ifdef CONFIG_PROC_DEVICETREE
1913 /* try to add to proc as well if it was initialized */
1914 if (np->pde)
1915 proc_device_tree_update_prop(np->pde, newprop, oldprop);
1916#endif /* CONFIG_PROC_DEVICETREE */
1917
1918 return 0;
1919}
diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c
index 309ae1d5fa77..a8099c806150 100644
--- a/arch/powerpc/kernel/prom_parse.c
+++ b/arch/powerpc/kernel/prom_parse.c
@@ -113,7 +113,8 @@ static unsigned int of_bus_default_get_flags(u32 *addr)
113 113
114static int of_bus_pci_match(struct device_node *np) 114static int of_bus_pci_match(struct device_node *np)
115{ 115{
116 return !strcmp(np->type, "pci"); 116 /* "vci" is for the /chaos bridge on 1st-gen PCI powermacs */
117 return !strcmp(np->type, "pci") || !strcmp(np->type, "vci");
117} 118}
118 119
119static void of_bus_pci_count_cells(struct device_node *np, 120static void of_bus_pci_count_cells(struct device_node *np,
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 4b9cfe4637b1..7fe4a5c944c9 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -36,6 +36,11 @@ struct rtas_t rtas = {
36 .lock = SPIN_LOCK_UNLOCKED 36 .lock = SPIN_LOCK_UNLOCKED
37}; 37};
38 38
39struct rtas_suspend_me_data {
40 long waiting;
41 struct rtas_args *args;
42};
43
39EXPORT_SYMBOL(rtas); 44EXPORT_SYMBOL(rtas);
40 45
41DEFINE_SPINLOCK(rtas_data_buf_lock); 46DEFINE_SPINLOCK(rtas_data_buf_lock);
@@ -556,6 +561,80 @@ void rtas_os_term(char *str)
556 } while (status == RTAS_BUSY); 561 } while (status == RTAS_BUSY);
557} 562}
558 563
564static int ibm_suspend_me_token = RTAS_UNKNOWN_SERVICE;
565#ifdef CONFIG_PPC_PSERIES
566static void rtas_percpu_suspend_me(void *info)
567{
568 long rc;
569 long flags;
570 struct rtas_suspend_me_data *data =
571 (struct rtas_suspend_me_data *)info;
572
573 /*
574 * We use "waiting" to indicate our state. As long
575 * as it is >0, we are still trying to all join up.
576 * If it goes to 0, we have successfully joined up and
577 * one thread got H_Continue. If any error happens,
578 * we set it to <0.
579 */
580 local_irq_save(flags);
581 do {
582 rc = plpar_hcall_norets(H_JOIN);
583 smp_rmb();
584 } while (rc == H_Success && data->waiting > 0);
585 if (rc == H_Success)
586 goto out;
587
588 if (rc == H_Continue) {
589 data->waiting = 0;
590 rtas_call(ibm_suspend_me_token, 0, 1,
591 data->args->args);
592 } else {
593 data->waiting = -EBUSY;
594 printk(KERN_ERR "Error on H_Join hypervisor call\n");
595 }
596
597out:
598 /* before we restore interrupts, make sure we don't
599 * generate a spurious soft lockup errors
600 */
601 touch_softlockup_watchdog();
602 local_irq_restore(flags);
603 return;
604}
605
606static int rtas_ibm_suspend_me(struct rtas_args *args)
607{
608 int i;
609
610 struct rtas_suspend_me_data data;
611
612 data.waiting = 1;
613 data.args = args;
614
615 /* Call function on all CPUs. One of us will make the
616 * rtas call
617 */
618 if (on_each_cpu(rtas_percpu_suspend_me, &data, 1, 0))
619 data.waiting = -EINVAL;
620
621 if (data.waiting != 0)
622 printk(KERN_ERR "Error doing global join\n");
623
624 /* Prod each CPU. This won't hurt, and will wake
625 * anyone we successfully put to sleep with H_Join
626 */
627 for_each_cpu(i)
628 plpar_hcall_norets(H_PROD, i);
629
630 return data.waiting;
631}
632#else /* CONFIG_PPC_PSERIES */
633static int rtas_ibm_suspend_me(struct rtas_args *args)
634{
635 return -ENOSYS;
636}
637#endif
559 638
560asmlinkage int ppc_rtas(struct rtas_args __user *uargs) 639asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
561{ 640{
@@ -563,6 +642,7 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
563 unsigned long flags; 642 unsigned long flags;
564 char *buff_copy, *errbuf = NULL; 643 char *buff_copy, *errbuf = NULL;
565 int nargs; 644 int nargs;
645 int rc;
566 646
567 if (!capable(CAP_SYS_ADMIN)) 647 if (!capable(CAP_SYS_ADMIN))
568 return -EPERM; 648 return -EPERM;
@@ -581,6 +661,17 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
581 nargs * sizeof(rtas_arg_t)) != 0) 661 nargs * sizeof(rtas_arg_t)) != 0)
582 return -EFAULT; 662 return -EFAULT;
583 663
664 if (args.token == RTAS_UNKNOWN_SERVICE)
665 return -EINVAL;
666
667 /* Need to handle ibm,suspend_me call specially */
668 if (args.token == ibm_suspend_me_token) {
669 rc = rtas_ibm_suspend_me(&args);
670 if (rc)
671 return rc;
672 goto copy_return;
673 }
674
584 buff_copy = get_errorlog_buffer(); 675 buff_copy = get_errorlog_buffer();
585 676
586 spin_lock_irqsave(&rtas.lock, flags); 677 spin_lock_irqsave(&rtas.lock, flags);
@@ -604,6 +695,7 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
604 kfree(buff_copy); 695 kfree(buff_copy);
605 } 696 }
606 697
698 copy_return:
607 /* Copy out args. */ 699 /* Copy out args. */
608 if (copy_to_user(uargs->args + nargs, 700 if (copy_to_user(uargs->args + nargs,
609 args.args + nargs, 701 args.args + nargs,
@@ -675,8 +767,10 @@ void __init rtas_initialize(void)
675 * the stop-self token if any 767 * the stop-self token if any
676 */ 768 */
677#ifdef CONFIG_PPC64 769#ifdef CONFIG_PPC64
678 if (_machine == PLATFORM_PSERIES_LPAR) 770 if (_machine == PLATFORM_PSERIES_LPAR) {
679 rtas_region = min(lmb.rmo_size, RTAS_INSTANTIATE_MAX); 771 rtas_region = min(lmb.rmo_size, RTAS_INSTANTIATE_MAX);
772 ibm_suspend_me_token = rtas_token("ibm,suspend-me");
773 }
680#endif 774#endif
681 rtas_rmo_buf = lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE, rtas_region); 775 rtas_rmo_buf = lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE, rtas_region);
682 776
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index d5c52fae023a..be12041c0fc5 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -100,7 +100,8 @@ void machine_shutdown(void)
100void machine_restart(char *cmd) 100void machine_restart(char *cmd)
101{ 101{
102 machine_shutdown(); 102 machine_shutdown();
103 ppc_md.restart(cmd); 103 if (ppc_md.restart)
104 ppc_md.restart(cmd);
104#ifdef CONFIG_SMP 105#ifdef CONFIG_SMP
105 smp_send_stop(); 106 smp_send_stop();
106#endif 107#endif
@@ -112,7 +113,8 @@ void machine_restart(char *cmd)
112void machine_power_off(void) 113void machine_power_off(void)
113{ 114{
114 machine_shutdown(); 115 machine_shutdown();
115 ppc_md.power_off(); 116 if (ppc_md.power_off)
117 ppc_md.power_off();
116#ifdef CONFIG_SMP 118#ifdef CONFIG_SMP
117 smp_send_stop(); 119 smp_send_stop();
118#endif 120#endif
@@ -129,7 +131,8 @@ EXPORT_SYMBOL_GPL(pm_power_off);
129void machine_halt(void) 131void machine_halt(void)
130{ 132{
131 machine_shutdown(); 133 machine_shutdown();
132 ppc_md.halt(); 134 if (ppc_md.halt)
135 ppc_md.halt();
133#ifdef CONFIG_SMP 136#ifdef CONFIG_SMP
134 smp_send_stop(); 137 smp_send_stop();
135#endif 138#endif
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 56f50e91bddb..c4a294d657b9 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -431,7 +431,7 @@ void timer_interrupt(struct pt_regs * regs)
431 profile_tick(CPU_PROFILING, regs); 431 profile_tick(CPU_PROFILING, regs);
432 432
433#ifdef CONFIG_PPC_ISERIES 433#ifdef CONFIG_PPC_ISERIES
434 get_paca()->lppaca.int_dword.fields.decr_int = 0; 434 get_lppaca()->int_dword.fields.decr_int = 0;
435#endif 435#endif
436 436
437 while ((ticks = tb_ticks_since(per_cpu(last_jiffy, cpu))) 437 while ((ticks = tb_ticks_since(per_cpu(last_jiffy, cpu)))
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index 13c41495fe06..13c655ba2841 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -76,7 +76,7 @@ static void vio_bus_shutdown(struct device *dev)
76 struct vio_dev *viodev = to_vio_dev(dev); 76 struct vio_dev *viodev = to_vio_dev(dev);
77 struct vio_driver *viodrv = to_vio_driver(dev->driver); 77 struct vio_driver *viodrv = to_vio_driver(dev->driver);
78 78
79 if (viodrv->shutdown) 79 if (dev->driver && viodrv->shutdown)
80 viodrv->shutdown(viodev); 80 viodrv->shutdown(viodev);
81} 81}
82 82
@@ -91,9 +91,6 @@ int vio_register_driver(struct vio_driver *viodrv)
91 91
92 /* fill in 'struct driver' fields */ 92 /* fill in 'struct driver' fields */
93 viodrv->driver.bus = &vio_bus_type; 93 viodrv->driver.bus = &vio_bus_type;
94 viodrv->driver.probe = vio_bus_probe;
95 viodrv->driver.remove = vio_bus_remove;
96 viodrv->driver.shutdown = vio_bus_shutdown;
97 94
98 return driver_register(&viodrv->driver); 95 return driver_register(&viodrv->driver);
99} 96}
@@ -295,4 +292,7 @@ struct bus_type vio_bus_type = {
295 .name = "vio", 292 .name = "vio",
296 .uevent = vio_hotplug, 293 .uevent = vio_hotplug,
297 .match = vio_bus_match, 294 .match = vio_bus_match,
295 .probe = vio_bus_probe,
296 .remove = vio_bus_remove,
297 .shutdown = vio_bus_shutdown,
298}; 298};
diff --git a/arch/powerpc/lib/locks.c b/arch/powerpc/lib/locks.c
index 35bd03c41dd1..8362fa272ca5 100644
--- a/arch/powerpc/lib/locks.c
+++ b/arch/powerpc/lib/locks.c
@@ -28,15 +28,13 @@
28void __spin_yield(raw_spinlock_t *lock) 28void __spin_yield(raw_spinlock_t *lock)
29{ 29{
30 unsigned int lock_value, holder_cpu, yield_count; 30 unsigned int lock_value, holder_cpu, yield_count;
31 struct paca_struct *holder_paca;
32 31
33 lock_value = lock->slock; 32 lock_value = lock->slock;
34 if (lock_value == 0) 33 if (lock_value == 0)
35 return; 34 return;
36 holder_cpu = lock_value & 0xffff; 35 holder_cpu = lock_value & 0xffff;
37 BUG_ON(holder_cpu >= NR_CPUS); 36 BUG_ON(holder_cpu >= NR_CPUS);
38 holder_paca = &paca[holder_cpu]; 37 yield_count = lppaca[holder_cpu].yield_count;
39 yield_count = holder_paca->lppaca.yield_count;
40 if ((yield_count & 1) == 0) 38 if ((yield_count & 1) == 0)
41 return; /* virtual cpu is currently running */ 39 return; /* virtual cpu is currently running */
42 rmb(); 40 rmb();
@@ -60,15 +58,13 @@ void __rw_yield(raw_rwlock_t *rw)
60{ 58{
61 int lock_value; 59 int lock_value;
62 unsigned int holder_cpu, yield_count; 60 unsigned int holder_cpu, yield_count;
63 struct paca_struct *holder_paca;
64 61
65 lock_value = rw->lock; 62 lock_value = rw->lock;
66 if (lock_value >= 0) 63 if (lock_value >= 0)
67 return; /* no write lock at present */ 64 return; /* no write lock at present */
68 holder_cpu = lock_value & 0xffff; 65 holder_cpu = lock_value & 0xffff;
69 BUG_ON(holder_cpu >= NR_CPUS); 66 BUG_ON(holder_cpu >= NR_CPUS);
70 holder_paca = &paca[holder_cpu]; 67 yield_count = lppaca[holder_cpu].yield_count;
71 yield_count = holder_paca->lppaca.yield_count;
72 if ((yield_count & 1) == 0) 68 if ((yield_count & 1) == 0)
73 return; /* virtual cpu is currently running */ 69 return; /* virtual cpu is currently running */
74 rmb(); 70 rmb();
diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c
index 71615eb70b2b..cc2535be3a73 100644
--- a/arch/powerpc/oprofile/common.c
+++ b/arch/powerpc/oprofile/common.c
@@ -140,19 +140,19 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
140 140
141 switch (cur_cpu_spec->oprofile_type) { 141 switch (cur_cpu_spec->oprofile_type) {
142#ifdef CONFIG_PPC64 142#ifdef CONFIG_PPC64
143 case RS64: 143 case PPC_OPROFILE_RS64:
144 model = &op_model_rs64; 144 model = &op_model_rs64;
145 break; 145 break;
146 case POWER4: 146 case PPC_OPROFILE_POWER4:
147 model = &op_model_power4; 147 model = &op_model_power4;
148 break; 148 break;
149#else 149#else
150 case G4: 150 case PPC_OPROFILE_G4:
151 model = &op_model_7450; 151 model = &op_model_7450;
152 break; 152 break;
153#endif 153#endif
154#ifdef CONFIG_FSL_BOOKE 154#ifdef CONFIG_FSL_BOOKE
155 case BOOKE: 155 case PPC_OPROFILE_BOOKE:
156 model = &op_model_fsl_booke; 156 model = &op_model_fsl_booke;
157 break; 157 break;
158#endif 158#endif
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig
index b20812d460e6..7675e675dce1 100644
--- a/arch/powerpc/platforms/83xx/Kconfig
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -7,6 +7,7 @@ choice
7 7
8config MPC834x_SYS 8config MPC834x_SYS
9 bool "Freescale MPC834x SYS" 9 bool "Freescale MPC834x SYS"
10 select DEFAULT_UIMAGE
10 help 11 help
11 This option enables support for the MPC 834x SYS evaluation board. 12 This option enables support for the MPC 834x SYS evaluation board.
12 13
diff --git a/arch/powerpc/platforms/83xx/mpc834x_sys.c b/arch/powerpc/platforms/83xx/mpc834x_sys.c
new file mode 100644
index 000000000000..2098dd05a773
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/mpc834x_sys.c
@@ -0,0 +1,243 @@
1/*
2 * arch/powerpc/platforms/83xx/mpc834x_sys.c
3 *
4 * MPC834x SYS board specific routines
5 *
6 * Maintainer: Kumar Gala <galak@kernel.crashing.org>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
13
14#include <linux/config.h>
15#include <linux/stddef.h>
16#include <linux/kernel.h>
17#include <linux/init.h>
18#include <linux/errno.h>
19#include <linux/reboot.h>
20#include <linux/pci.h>
21#include <linux/kdev_t.h>
22#include <linux/major.h>
23#include <linux/console.h>
24#include <linux/delay.h>
25#include <linux/seq_file.h>
26#include <linux/root_dev.h>
27#include <linux/module.h>
28#include <linux/fsl_devices.h>
29
30#include <asm/system.h>
31#include <asm/pgtable.h>
32#include <asm/page.h>
33#include <asm/atomic.h>
34#include <asm/time.h>
35#include <asm/io.h>
36#include <asm/machdep.h>
37#include <asm/ipic.h>
38#include <asm/bootinfo.h>
39#include <asm/pci-bridge.h>
40#include <asm/mpc83xx.h>
41#include <asm/irq.h>
42#include <mm/mmu_decl.h>
43#include <asm/prom.h>
44#include <asm/udbg.h>
45#include <sysdev/fsl_soc.h>
46
47#include "mpc83xx.h"
48
49#ifndef CONFIG_PCI
50unsigned long isa_io_base = 0;
51unsigned long isa_mem_base = 0;
52#endif
53
54#ifdef CONFIG_PCI
55extern int mpc83xx_pci2_busno;
56
57static int
58mpc83xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
59{
60 static char pci_irq_table[][4] =
61 /*
62 * PCI IDSEL/INTPIN->INTLINE
63 * A B C D
64 */
65 {
66 {PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x11 */
67 {PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x12 */
68 {PIRQD, PIRQA, PIRQB, PIRQC}, /* idsel 0x13 */
69 {0, 0, 0, 0},
70 {PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x15 */
71 {PIRQD, PIRQA, PIRQB, PIRQC}, /* idsel 0x16 */
72 {PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x17 */
73 {PIRQB, PIRQC, PIRQD, PIRQA}, /* idsel 0x18 */
74 {0, 0, 0, 0}, /* idsel 0x19 */
75 {0, 0, 0, 0}, /* idsel 0x20 */
76 };
77
78 const long min_idsel = 0x11, max_idsel = 0x20, irqs_per_slot = 4;
79 return PCI_IRQ_TABLE_LOOKUP;
80}
81
82static int
83mpc83xx_exclude_device(u_char bus, u_char devfn)
84{
85 if (bus == 0 && PCI_SLOT(devfn) == 0)
86 return PCIBIOS_DEVICE_NOT_FOUND;
87 if (mpc83xx_pci2_busno)
88 if (bus == (mpc83xx_pci2_busno) && PCI_SLOT(devfn) == 0)
89 return PCIBIOS_DEVICE_NOT_FOUND;
90 return PCIBIOS_SUCCESSFUL;
91}
92#endif /* CONFIG_PCI */
93
94/* ************************************************************************
95 *
96 * Setup the architecture
97 *
98 */
99static void __init
100mpc834x_sys_setup_arch(void)
101{
102 struct device_node *np;
103
104 if (ppc_md.progress)
105 ppc_md.progress("mpc834x_sys_setup_arch()", 0);
106
107 np = of_find_node_by_type(NULL, "cpu");
108 if (np != 0) {
109 unsigned int *fp = (int *) get_property(np, "clock-frequency", NULL);
110 if (fp != 0)
111 loops_per_jiffy = *fp / HZ;
112 else
113 loops_per_jiffy = 50000000 / HZ;
114 of_node_put(np);
115 }
116
117#ifdef CONFIG_PCI
118 for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
119 add_bridge(np);
120
121 ppc_md.pci_swizzle = common_swizzle;
122 ppc_md.pci_map_irq = mpc83xx_map_irq;
123 ppc_md.pci_exclude_device = mpc83xx_exclude_device;
124#endif
125
126#ifdef CONFIG_ROOT_NFS
127 ROOT_DEV = Root_NFS;
128#else
129 ROOT_DEV = Root_HDA1;
130#endif
131}
132
133void __init
134mpc834x_sys_init_IRQ(void)
135{
136 u8 senses[8] = {
137 0, /* EXT 0 */
138 IRQ_SENSE_LEVEL, /* EXT 1 */
139 IRQ_SENSE_LEVEL, /* EXT 2 */
140 0, /* EXT 3 */
141#ifdef CONFIG_PCI
142 IRQ_SENSE_LEVEL, /* EXT 4 */
143 IRQ_SENSE_LEVEL, /* EXT 5 */
144 IRQ_SENSE_LEVEL, /* EXT 6 */
145 IRQ_SENSE_LEVEL, /* EXT 7 */
146#else
147 0, /* EXT 4 */
148 0, /* EXT 5 */
149 0, /* EXT 6 */
150 0, /* EXT 7 */
151#endif
152 };
153
154 ipic_init(get_immrbase() + 0x00700, 0, 0, senses, 8);
155
156 /* Initialize the default interrupt mapping priorities,
157 * in case the boot rom changed something on us.
158 */
159 ipic_set_default_priority();
160}
161
162#if defined(CONFIG_I2C_MPC) && defined(CONFIG_SENSORS_DS1374)
163extern ulong ds1374_get_rtc_time(void);
164extern int ds1374_set_rtc_time(ulong);
165
166static int __init
167mpc834x_rtc_hookup(void)
168{
169 struct timespec tv;
170
171 ppc_md.get_rtc_time = ds1374_get_rtc_time;
172 ppc_md.set_rtc_time = ds1374_set_rtc_time;
173
174 tv.tv_nsec = 0;
175 tv.tv_sec = (ppc_md.get_rtc_time)();
176 do_settimeofday(&tv);
177
178 return 0;
179}
180late_initcall(mpc834x_rtc_hookup);
181#endif
182
183static void
184mpc83xx_restart(char *cmd)
185{
186#define RST_OFFSET 0x00000900
187#define RST_PROT_REG 0x00000018
188#define RST_CTRL_REG 0x0000001c
189 __be32 __iomem *reg;
190
191 // map reset register space
192 reg = ioremap(get_immrbase() + 0x900, 0xff);
193
194 local_irq_disable();
195
196 /* enable software reset "RSTE" */
197 out_be32(reg + (RST_PROT_REG >> 2), 0x52535445);
198
199 /* set software hard reset */
200 out_be32(reg + (RST_CTRL_REG >> 2), 0x52535445);
201 for(;;);
202}
203
204static long __init
205mpc83xx_time_init(void)
206{
207#define SPCR_OFFSET 0x00000110
208#define SPCR_TBEN 0x00400000
209 __be32 __iomem *spcr = ioremap(get_immrbase() + SPCR_OFFSET, 4);
210 __be32 tmp;
211
212 tmp = in_be32(spcr);
213 out_be32(spcr, tmp|SPCR_TBEN);
214
215 iounmap(spcr);
216
217 return 0;
218}
219void __init
220platform_init(void)
221{
222 /* setup the PowerPC module struct */
223 ppc_md.setup_arch = mpc834x_sys_setup_arch;
224
225 ppc_md.init_IRQ = mpc834x_sys_init_IRQ;
226 ppc_md.get_irq = ipic_get_irq;
227
228 ppc_md.restart = mpc83xx_restart;
229
230 ppc_md.time_init = mpc83xx_time_init;
231 ppc_md.set_rtc_time = NULL;
232 ppc_md.get_rtc_time = NULL;
233 ppc_md.calibrate_decr = generic_calibrate_decr;
234
235 ppc_md.progress = udbg_progress;
236
237 if (ppc_md.progress)
238 ppc_md.progress("mpc834x_sys_init(): exit", 0);
239
240 return;
241}
242
243
diff --git a/arch/powerpc/platforms/83xx/mpc834x_sys.h b/arch/powerpc/platforms/83xx/mpc834x_sys.h
new file mode 100644
index 000000000000..e4ca39f6a862
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/mpc834x_sys.h
@@ -0,0 +1,23 @@
1/*
2 * arch/powerppc/platforms/83xx/mpc834x_sys.h
3 *
4 * MPC834X SYS common board definitions
5 *
6 * Maintainer: Kumar Gala <galak@kernel.crashing.org>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 */
14
15#ifndef __MACH_MPC83XX_SYS_H__
16#define __MACH_MPC83XX_SYS_H__
17
18#define PIRQA MPC83xx_IRQ_EXT4
19#define PIRQB MPC83xx_IRQ_EXT5
20#define PIRQC MPC83xx_IRQ_EXT6
21#define PIRQD MPC83xx_IRQ_EXT7
22
23#endif /* __MACH_MPC83XX_SYS_H__ */
diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h
new file mode 100644
index 000000000000..ce9e66abef24
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/mpc83xx.h
@@ -0,0 +1,14 @@
1#ifndef __MPC83XX_H__
2#define __MPC83XX_H__
3
4#include <linux/init.h>
5#include <linux/device.h>
6
7/*
8 * Declaration for the various functions exported by the
9 * mpc83xx_* files. Mostly for use by mpc83xx_setup
10 */
11
12extern int add_bridge(struct device_node *dev);
13
14#endif /* __MPC83XX_H__ */
diff --git a/arch/powerpc/platforms/83xx/pci.c b/arch/powerpc/platforms/83xx/pci.c
new file mode 100644
index 000000000000..469cdacc5bd4
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/pci.c
@@ -0,0 +1,99 @@
1/*
2 * FSL SoC setup code
3 *
4 * Maintained by Kumar Gala (see MAINTAINERS for contact information)
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 */
11
12#include <linux/config.h>
13#include <linux/stddef.h>
14#include <linux/kernel.h>
15#include <linux/init.h>
16#include <linux/errno.h>
17#include <linux/pci.h>
18#include <linux/delay.h>
19#include <linux/irq.h>
20#include <linux/module.h>
21
22#include <asm/system.h>
23#include <asm/atomic.h>
24#include <asm/io.h>
25#include <asm/pci-bridge.h>
26#include <asm/prom.h>
27#include <sysdev/fsl_soc.h>
28
29#undef DEBUG
30
31#ifdef DEBUG
32#define DBG(x...) printk(x)
33#else
34#define DBG(x...)
35#endif
36
37int mpc83xx_pci2_busno;
38
39#ifdef CONFIG_PCI
40int __init add_bridge(struct device_node *dev)
41{
42 int len;
43 struct pci_controller *hose;
44 struct resource rsrc;
45 int *bus_range;
46 int primary = 1, has_address = 0;
47 phys_addr_t immr = get_immrbase();
48
49 DBG("Adding PCI host bridge %s\n", dev->full_name);
50
51 /* Fetch host bridge registers address */
52 has_address = (of_address_to_resource(dev, 0, &rsrc) == 0);
53
54 /* Get bus range if any */
55 bus_range = (int *) get_property(dev, "bus-range", &len);
56 if (bus_range == NULL || len < 2 * sizeof(int)) {
57 printk(KERN_WARNING "Can't get bus-range for %s, assume"
58 " bus 0\n", dev->full_name);
59 }
60
61 hose = pcibios_alloc_controller();
62 if (!hose)
63 return -ENOMEM;
64 hose->arch_data = dev;
65 hose->set_cfg_type = 1;
66
67 hose->first_busno = bus_range ? bus_range[0] : 0;
68 hose->last_busno = bus_range ? bus_range[1] : 0xff;
69
70 /* MPC83xx supports up to two host controllers one at 0x8500 from immrbar
71 * the other at 0x8600, we consider the 0x8500 the primary controller
72 */
73 /* PCI 1 */
74 if ((rsrc.start & 0xfffff) == 0x8500) {
75 setup_indirect_pci(hose, immr + 0x8300, immr + 0x8304);
76 }
77 /* PCI 2*/
78 if ((rsrc.start & 0xfffff) == 0x8600) {
79 setup_indirect_pci(hose, immr + 0x8380, immr + 0x8384);
80 primary = 0;
81 hose->bus_offset = hose->first_busno;
82 mpc83xx_pci2_busno = hose->first_busno;
83 }
84
85 printk(KERN_INFO "Found MPC83xx PCI host bridge at 0x%08lx. "
86 "Firmware bus number: %d->%d\n",
87 rsrc.start, hose->first_busno, hose->last_busno);
88
89 DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n",
90 hose, hose->cfg_addr, hose->cfg_data);
91
92 /* Interpret the "ranges" property */
93 /* This also maps the I/O region and sets isa_io/mem_base */
94 pci_process_bridge_OF_ranges(hose, dev, primary);
95
96 return 0;
97}
98
99#endif
diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c
index 82c429d487f3..00c52f27ef4f 100644
--- a/arch/powerpc/platforms/chrp/pci.c
+++ b/arch/powerpc/platforms/chrp/pci.c
@@ -135,12 +135,13 @@ int __init
135hydra_init(void) 135hydra_init(void)
136{ 136{
137 struct device_node *np; 137 struct device_node *np;
138 struct resource r;
138 139
139 np = find_devices("mac-io"); 140 np = find_devices("mac-io");
140 if (np == NULL || np->n_addrs == 0) 141 if (np == NULL || of_address_to_resource(np, 0, &r))
141 return 0; 142 return 0;
142 Hydra = ioremap(np->addrs[0].address, np->addrs[0].size); 143 Hydra = ioremap(r.start, r.end-r.start);
143 printk("Hydra Mac I/O at %lx\n", np->addrs[0].address); 144 printk("Hydra Mac I/O at %lx\n", r.start);
144 printk("Hydra Feature_Control was %x", 145 printk("Hydra Feature_Control was %x",
145 in_le32(&Hydra->Feature_Control)); 146 in_le32(&Hydra->Feature_Control));
146 out_le32(&Hydra->Feature_Control, (HYDRA_FC_SCC_CELL_EN | 147 out_le32(&Hydra->Feature_Control, (HYDRA_FC_SCC_CELL_EN |
@@ -177,18 +178,24 @@ setup_python(struct pci_controller *hose, struct device_node *dev)
177{ 178{
178 u32 __iomem *reg; 179 u32 __iomem *reg;
179 u32 val; 180 u32 val;
180 unsigned long addr = dev->addrs[0].address; 181 struct resource r;
181 182
182 setup_indirect_pci(hose, addr + 0xf8000, addr + 0xf8010); 183 if (of_address_to_resource(dev, 0, &r)) {
184 printk(KERN_ERR "No address for Python PCI controller\n");
185 return;
186 }
183 187
184 /* Clear the magic go-slow bit */ 188 /* Clear the magic go-slow bit */
185 reg = ioremap(dev->addrs[0].address + 0xf6000, 0x40); 189 reg = ioremap(r.start + 0xf6000, 0x40);
190 BUG_ON(!reg);
186 val = in_be32(&reg[12]); 191 val = in_be32(&reg[12]);
187 if (val & PRG_CL_RESET_VALID) { 192 if (val & PRG_CL_RESET_VALID) {
188 out_be32(&reg[12], val & ~PRG_CL_RESET_VALID); 193 out_be32(&reg[12], val & ~PRG_CL_RESET_VALID);
189 in_be32(&reg[12]); 194 in_be32(&reg[12]);
190 } 195 }
191 iounmap(reg); 196 iounmap(reg);
197
198 setup_indirect_pci(hose, r.start + 0xf8000, r.start + 0xf8010);
192} 199}
193 200
194/* Marvell Discovery II based Pegasos 2 */ 201/* Marvell Discovery II based Pegasos 2 */
@@ -218,7 +225,7 @@ chrp_find_bridges(void)
218 char *model, *machine; 225 char *model, *machine;
219 int is_longtrail = 0, is_mot = 0, is_pegasos = 0; 226 int is_longtrail = 0, is_mot = 0, is_pegasos = 0;
220 struct device_node *root = find_path_device("/"); 227 struct device_node *root = find_path_device("/");
221 228 struct resource r;
222 /* 229 /*
223 * The PCI host bridge nodes on some machines don't have 230 * The PCI host bridge nodes on some machines don't have
224 * properties to adequately identify them, so we have to 231 * properties to adequately identify them, so we have to
@@ -238,7 +245,7 @@ chrp_find_bridges(void)
238 continue; 245 continue;
239 ++index; 246 ++index;
240 /* The GG2 bridge on the LongTrail doesn't have an address */ 247 /* The GG2 bridge on the LongTrail doesn't have an address */
241 if (dev->n_addrs < 1 && !is_longtrail) { 248 if (of_address_to_resource(dev, 0, &r) && !is_longtrail) {
242 printk(KERN_WARNING "Can't use %s: no address\n", 249 printk(KERN_WARNING "Can't use %s: no address\n",
243 dev->full_name); 250 dev->full_name);
244 continue; 251 continue;
@@ -255,8 +262,8 @@ chrp_find_bridges(void)
255 printk(KERN_INFO "PCI buses %d..%d", 262 printk(KERN_INFO "PCI buses %d..%d",
256 bus_range[0], bus_range[1]); 263 bus_range[0], bus_range[1]);
257 printk(" controlled by %s", dev->type); 264 printk(" controlled by %s", dev->type);
258 if (dev->n_addrs > 0) 265 if (!is_longtrail)
259 printk(" at %lx", dev->addrs[0].address); 266 printk(" at %lx", r.start);
260 printk("\n"); 267 printk("\n");
261 268
262 hose = pcibios_alloc_controller(); 269 hose = pcibios_alloc_controller();
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index 4ec8ba737e7d..2dc87aa5962f 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -352,9 +352,10 @@ static void __init chrp_find_openpic(void)
352 opaddr = opprop[na-1]; /* assume 32-bit */ 352 opaddr = opprop[na-1]; /* assume 32-bit */
353 oplen /= na * sizeof(unsigned int); 353 oplen /= na * sizeof(unsigned int);
354 } else { 354 } else {
355 if (np->n_addrs == 0) 355 struct resource r;
356 if (of_address_to_resource(np, 0, &r))
356 return; 357 return;
357 opaddr = np->addrs[0].address; 358 opaddr = r.start;
358 oplen = 0; 359 oplen = 0;
359 } 360 }
360 361
@@ -377,7 +378,7 @@ static void __init chrp_find_openpic(void)
377 */ 378 */
378 if (oplen < len) { 379 if (oplen < len) {
379 printk(KERN_ERR "Insufficient addresses for distributed" 380 printk(KERN_ERR "Insufficient addresses for distributed"
380 " OpenPIC (%d < %d)\n", np->n_addrs, len); 381 " OpenPIC (%d < %d)\n", oplen, len);
381 len = oplen; 382 len = oplen;
382 } 383 }
383 384
diff --git a/arch/powerpc/platforms/chrp/time.c b/arch/powerpc/platforms/chrp/time.c
index 737ee5d9f0aa..36a0f97bb7b1 100644
--- a/arch/powerpc/platforms/chrp/time.c
+++ b/arch/powerpc/platforms/chrp/time.c
@@ -21,6 +21,7 @@
21#include <linux/mc146818rtc.h> 21#include <linux/mc146818rtc.h>
22#include <linux/init.h> 22#include <linux/init.h>
23#include <linux/bcd.h> 23#include <linux/bcd.h>
24#include <linux/ioport.h>
24 25
25#include <asm/io.h> 26#include <asm/io.h>
26#include <asm/nvram.h> 27#include <asm/nvram.h>
@@ -37,14 +38,16 @@ static int nvram_data = NVRAM_DATA;
37long __init chrp_time_init(void) 38long __init chrp_time_init(void)
38{ 39{
39 struct device_node *rtcs; 40 struct device_node *rtcs;
41 struct resource r;
40 int base; 42 int base;
41 43
42 rtcs = find_compatible_devices("rtc", "pnpPNP,b00"); 44 rtcs = find_compatible_devices("rtc", "pnpPNP,b00");
43 if (rtcs == NULL) 45 if (rtcs == NULL)
44 rtcs = find_compatible_devices("rtc", "ds1385-rtc"); 46 rtcs = find_compatible_devices("rtc", "ds1385-rtc");
45 if (rtcs == NULL || rtcs->addrs == NULL) 47 if (rtcs == NULL || of_address_to_resource(rtcs, 0, &r))
46 return 0; 48 return 0;
47 base = rtcs->addrs[0].address; 49
50 base = r.start;
48 nvram_as1 = 0; 51 nvram_as1 = 0;
49 nvram_as0 = base; 52 nvram_as0 = base;
50 nvram_data = base + 1; 53 nvram_data = base + 1;
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c
index 83442ea77476..be3fbfc24e6c 100644
--- a/arch/powerpc/platforms/iseries/irq.c
+++ b/arch/powerpc/platforms/iseries/irq.c
@@ -334,14 +334,12 @@ int __init iSeries_allocate_IRQ(HvBusNumber bus,
334 */ 334 */
335int iSeries_get_irq(struct pt_regs *regs) 335int iSeries_get_irq(struct pt_regs *regs)
336{ 336{
337 struct paca_struct *lpaca;
338 /* -2 means ignore this interrupt */ 337 /* -2 means ignore this interrupt */
339 int irq = -2; 338 int irq = -2;
340 339
341 lpaca = get_paca();
342#ifdef CONFIG_SMP 340#ifdef CONFIG_SMP
343 if (lpaca->lppaca.int_dword.fields.ipi_cnt) { 341 if (get_lppaca()->int_dword.fields.ipi_cnt) {
344 lpaca->lppaca.int_dword.fields.ipi_cnt = 0; 342 get_lppaca()->int_dword.fields.ipi_cnt = 0;
345 iSeries_smp_message_recv(regs); 343 iSeries_smp_message_recv(regs);
346 } 344 }
347#endif /* CONFIG_SMP */ 345#endif /* CONFIG_SMP */
diff --git a/arch/powerpc/platforms/iseries/misc.S b/arch/powerpc/platforms/iseries/misc.S
index dfe7aa1ba098..7641fc7e550a 100644
--- a/arch/powerpc/platforms/iseries/misc.S
+++ b/arch/powerpc/platforms/iseries/misc.S
@@ -44,7 +44,8 @@ _GLOBAL(local_irq_restore)
44 /* Check pending interrupts */ 44 /* Check pending interrupts */
45 /* A decrementer, IPI or PMC interrupt may have occurred 45 /* A decrementer, IPI or PMC interrupt may have occurred
46 * while we were in the hypervisor (which enables) */ 46 * while we were in the hypervisor (which enables) */
47 ld r4,PACALPPACA+LPPACAANYINT(r13) 47 ld r4,PACALPPACAPTR(r13)
48 ld r4,LPPACAANYINT(r4)
48 cmpdi r4,0 49 cmpdi r4,0
49 beqlr 50 beqlr
50 51
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index c6bbe5c25107..3f8790146b00 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -538,7 +538,7 @@ static unsigned long __init build_iSeries_Memory_Map(void)
538 */ 538 */
539static void __init iSeries_setup_arch(void) 539static void __init iSeries_setup_arch(void)
540{ 540{
541 if (get_paca()->lppaca.shared_proc) { 541 if (get_lppaca()->shared_proc) {
542 ppc_md.idle_loop = iseries_shared_idle; 542 ppc_md.idle_loop = iseries_shared_idle;
543 printk(KERN_INFO "Using shared processor idle loop\n"); 543 printk(KERN_INFO "Using shared processor idle loop\n");
544 } else { 544 } else {
@@ -647,7 +647,7 @@ static void yield_shared_processor(void)
647 * The decrementer stops during the yield. Force a fake decrementer 647 * The decrementer stops during the yield. Force a fake decrementer
648 * here and let the timer_interrupt code sort out the actual time. 648 * here and let the timer_interrupt code sort out the actual time.
649 */ 649 */
650 get_paca()->lppaca.int_dword.fields.decr_int = 1; 650 get_lppaca()->int_dword.fields.decr_int = 1;
651 process_iSeries_events(); 651 process_iSeries_events();
652} 652}
653 653
@@ -883,7 +883,7 @@ void dt_cpus(struct iseries_flat_dt *dt)
883 pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE); 883 pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE);
884 884
885 for (i = 0; i < NR_CPUS; i++) { 885 for (i = 0; i < NR_CPUS; i++) {
886 if (paca[i].lppaca.dyn_proc_status >= 2) 886 if (lppaca[i].dyn_proc_status >= 2)
887 continue; 887 continue;
888 888
889 snprintf(p, 32 - (p - buf), "@%d", i); 889 snprintf(p, 32 - (p - buf), "@%d", i);
@@ -891,7 +891,7 @@ void dt_cpus(struct iseries_flat_dt *dt)
891 891
892 dt_prop_str(dt, "device_type", "cpu"); 892 dt_prop_str(dt, "device_type", "cpu");
893 893
894 index = paca[i].lppaca.dyn_hv_phys_proc_index; 894 index = lppaca[i].dyn_hv_phys_proc_index;
895 d = &xIoHriProcessorVpd[index]; 895 d = &xIoHriProcessorVpd[index];
896 896
897 dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024); 897 dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024);
diff --git a/arch/powerpc/platforms/iseries/smp.c b/arch/powerpc/platforms/iseries/smp.c
index fcb094ec6aec..6f9d407a709f 100644
--- a/arch/powerpc/platforms/iseries/smp.c
+++ b/arch/powerpc/platforms/iseries/smp.c
@@ -91,7 +91,7 @@ static void smp_iSeries_kick_cpu(int nr)
91 BUG_ON((nr < 0) || (nr >= NR_CPUS)); 91 BUG_ON((nr < 0) || (nr >= NR_CPUS));
92 92
93 /* Verify that our partition has a processor nr */ 93 /* Verify that our partition has a processor nr */
94 if (paca[nr].lppaca.dyn_proc_status >= 2) 94 if (lppaca[nr].dyn_proc_status >= 2)
95 return; 95 return;
96 96
97 /* The processor is currently spinning, waiting 97 /* The processor is currently spinning, waiting
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index 1fe445ab78a6..8952528d31ac 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -254,11 +254,11 @@ out:
254void vpa_init(int cpu) 254void vpa_init(int cpu)
255{ 255{
256 int hwcpu = get_hard_smp_processor_id(cpu); 256 int hwcpu = get_hard_smp_processor_id(cpu);
257 unsigned long vpa = __pa(&paca[cpu].lppaca); 257 unsigned long vpa = __pa(&lppaca[cpu]);
258 long ret; 258 long ret;
259 259
260 if (cpu_has_feature(CPU_FTR_ALTIVEC)) 260 if (cpu_has_feature(CPU_FTR_ALTIVEC))
261 paca[cpu].lppaca.vmxregs_in_use = 1; 261 lppaca[cpu].vmxregs_in_use = 1;
262 262
263 ret = register_vpa(hwcpu, vpa); 263 ret = register_vpa(hwcpu, vpa);
264 264
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index d8864164dbe8..86cfa6ecdcf3 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -350,6 +350,100 @@ static int do_remove_node(char *buf)
350 return rv; 350 return rv;
351} 351}
352 352
353static char *parse_node(char *buf, size_t bufsize, struct device_node **npp)
354{
355 char *handle_str;
356 phandle handle;
357 *npp = NULL;
358
359 handle_str = buf;
360
361 buf = strchr(buf, ' ');
362 if (!buf)
363 return NULL;
364 *buf = '\0';
365 buf++;
366
367 handle = simple_strtoul(handle_str, NULL, 10);
368
369 *npp = of_find_node_by_phandle(handle);
370 return buf;
371}
372
373static int do_add_property(char *buf, size_t bufsize)
374{
375 struct property *prop = NULL;
376 struct device_node *np;
377 unsigned char *value;
378 char *name, *end;
379 int length;
380 end = buf + bufsize;
381 buf = parse_node(buf, bufsize, &np);
382
383 if (!np)
384 return -ENODEV;
385
386 if (parse_next_property(buf, end, &name, &length, &value) == NULL)
387 return -EINVAL;
388
389 prop = new_property(name, length, value, NULL);
390 if (!prop)
391 return -ENOMEM;
392
393 prom_add_property(np, prop);
394
395 return 0;
396}
397
398static int do_remove_property(char *buf, size_t bufsize)
399{
400 struct device_node *np;
401 char *tmp;
402 struct property *prop;
403 buf = parse_node(buf, bufsize, &np);
404
405 if (!np)
406 return -ENODEV;
407
408 tmp = strchr(buf,' ');
409 if (tmp)
410 *tmp = '\0';
411
412 if (strlen(buf) == 0)
413 return -EINVAL;
414
415 prop = of_find_property(np, buf, NULL);
416
417 return prom_remove_property(np, prop);
418}
419
420static int do_update_property(char *buf, size_t bufsize)
421{
422 struct device_node *np;
423 unsigned char *value;
424 char *name, *end;
425 int length;
426 struct property *newprop, *oldprop;
427 buf = parse_node(buf, bufsize, &np);
428 end = buf + bufsize;
429
430 if (!np)
431 return -ENODEV;
432
433 if (parse_next_property(buf, end, &name, &length, &value) == NULL)
434 return -EINVAL;
435
436 newprop = new_property(name, length, value, NULL);
437 if (!newprop)
438 return -ENOMEM;
439
440 oldprop = of_find_property(np, name,NULL);
441 if (!oldprop)
442 return -ENODEV;
443
444 return prom_update_property(np, newprop, oldprop);
445}
446
353/** 447/**
354 * ofdt_write - perform operations on the Open Firmware device tree 448 * ofdt_write - perform operations on the Open Firmware device tree
355 * 449 *
@@ -392,6 +486,12 @@ static ssize_t ofdt_write(struct file *file, const char __user *buf, size_t coun
392 rv = do_add_node(tmp, count - (tmp - kbuf)); 486 rv = do_add_node(tmp, count - (tmp - kbuf));
393 else if (!strcmp(kbuf, "remove_node")) 487 else if (!strcmp(kbuf, "remove_node"))
394 rv = do_remove_node(tmp); 488 rv = do_remove_node(tmp);
489 else if (!strcmp(kbuf, "add_property"))
490 rv = do_add_property(tmp, count - (tmp - kbuf));
491 else if (!strcmp(kbuf, "remove_property"))
492 rv = do_remove_property(tmp, count - (tmp - kbuf));
493 else if (!strcmp(kbuf, "update_property"))
494 rv = do_update_property(tmp, count - (tmp - kbuf));
395 else 495 else
396 rv = -EINVAL; 496 rv = -EINVAL;
397out: 497out:
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 68b7f086d63d..da6cebaf72cd 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -190,7 +190,7 @@ static void pseries_lpar_enable_pmcs(void)
190 190
191 /* instruct hypervisor to maintain PMCs */ 191 /* instruct hypervisor to maintain PMCs */
192 if (firmware_has_feature(FW_FEATURE_SPLPAR)) 192 if (firmware_has_feature(FW_FEATURE_SPLPAR))
193 get_paca()->lppaca.pmcregs_in_use = 1; 193 get_lppaca()->pmcregs_in_use = 1;
194} 194}
195 195
196static void __init pSeries_setup_arch(void) 196static void __init pSeries_setup_arch(void)
@@ -234,7 +234,7 @@ static void __init pSeries_setup_arch(void)
234 /* Choose an idle loop */ 234 /* Choose an idle loop */
235 if (firmware_has_feature(FW_FEATURE_SPLPAR)) { 235 if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
236 vpa_init(boot_cpuid); 236 vpa_init(boot_cpuid);
237 if (get_paca()->lppaca.shared_proc) { 237 if (get_lppaca()->shared_proc) {
238 printk(KERN_INFO "Using shared processor idle loop\n"); 238 printk(KERN_INFO "Using shared processor idle loop\n");
239 ppc_md.idle_loop = pseries_shared_idle; 239 ppc_md.idle_loop = pseries_shared_idle;
240 } else { 240 } else {
@@ -444,10 +444,10 @@ DECLARE_PER_CPU(unsigned long, smt_snooze_delay);
444 444
445static inline void dedicated_idle_sleep(unsigned int cpu) 445static inline void dedicated_idle_sleep(unsigned int cpu)
446{ 446{
447 struct paca_struct *ppaca = &paca[cpu ^ 1]; 447 struct lppaca *plppaca = &lppaca[cpu ^ 1];
448 448
449 /* Only sleep if the other thread is not idle */ 449 /* Only sleep if the other thread is not idle */
450 if (!(ppaca->lppaca.idle)) { 450 if (!(plppaca->idle)) {
451 local_irq_disable(); 451 local_irq_disable();
452 452
453 /* 453 /*
@@ -480,7 +480,6 @@ static inline void dedicated_idle_sleep(unsigned int cpu)
480 480
481static void pseries_dedicated_idle(void) 481static void pseries_dedicated_idle(void)
482{ 482{
483 struct paca_struct *lpaca = get_paca();
484 unsigned int cpu = smp_processor_id(); 483 unsigned int cpu = smp_processor_id();
485 unsigned long start_snooze; 484 unsigned long start_snooze;
486 unsigned long *smt_snooze_delay = &__get_cpu_var(smt_snooze_delay); 485 unsigned long *smt_snooze_delay = &__get_cpu_var(smt_snooze_delay);
@@ -491,7 +490,7 @@ static void pseries_dedicated_idle(void)
491 * Indicate to the HV that we are idle. Now would be 490 * Indicate to the HV that we are idle. Now would be
492 * a good time to find other work to dispatch. 491 * a good time to find other work to dispatch.
493 */ 492 */
494 lpaca->lppaca.idle = 1; 493 get_lppaca()->idle = 1;
495 494
496 if (!need_resched()) { 495 if (!need_resched()) {
497 start_snooze = get_tb() + 496 start_snooze = get_tb() +
@@ -518,7 +517,7 @@ static void pseries_dedicated_idle(void)
518 HMT_medium(); 517 HMT_medium();
519 } 518 }
520 519
521 lpaca->lppaca.idle = 0; 520 get_lppaca()->idle = 0;
522 ppc64_runlatch_on(); 521 ppc64_runlatch_on();
523 522
524 preempt_enable_no_resched(); 523 preempt_enable_no_resched();
@@ -532,7 +531,6 @@ static void pseries_dedicated_idle(void)
532 531
533static void pseries_shared_idle(void) 532static void pseries_shared_idle(void)
534{ 533{
535 struct paca_struct *lpaca = get_paca();
536 unsigned int cpu = smp_processor_id(); 534 unsigned int cpu = smp_processor_id();
537 535
538 while (1) { 536 while (1) {
@@ -540,7 +538,7 @@ static void pseries_shared_idle(void)
540 * Indicate to the HV that we are idle. Now would be 538 * Indicate to the HV that we are idle. Now would be
541 * a good time to find other work to dispatch. 539 * a good time to find other work to dispatch.
542 */ 540 */
543 lpaca->lppaca.idle = 1; 541 get_lppaca()->idle = 1;
544 542
545 while (!need_resched() && !cpu_is_offline(cpu)) { 543 while (!need_resched() && !cpu_is_offline(cpu)) {
546 local_irq_disable(); 544 local_irq_disable();
@@ -564,7 +562,7 @@ static void pseries_shared_idle(void)
564 HMT_medium(); 562 HMT_medium();
565 } 563 }
566 564
567 lpaca->lppaca.idle = 0; 565 get_lppaca()->idle = 0;
568 ppc64_runlatch_on(); 566 ppc64_runlatch_on();
569 567
570 preempt_enable_no_resched(); 568 preempt_enable_no_resched();
@@ -588,7 +586,7 @@ static void pseries_kexec_cpu_down(int crash_shutdown, int secondary)
588{ 586{
589 /* Don't risk a hypervisor call if we're crashing */ 587 /* Don't risk a hypervisor call if we're crashing */
590 if (!crash_shutdown) { 588 if (!crash_shutdown) {
591 unsigned long vpa = __pa(&get_paca()->lppaca); 589 unsigned long vpa = __pa(get_lppaca());
592 590
593 if (unregister_vpa(hard_smp_processor_id(), vpa)) { 591 if (unregister_vpa(hard_smp_processor_id(), vpa)) {
594 printk("VPA deregistration of cpu %u (hw_cpu_id %d) " 592 printk("VPA deregistration of cpu %u (hw_cpu_id %d) "
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 0ae841347a09..4c2b356774ea 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_40x) += dcr.o
7obj-$(CONFIG_U3_DART) += dart_iommu.o 7obj-$(CONFIG_U3_DART) += dart_iommu.o
8obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o 8obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o
9obj-$(CONFIG_PPC_83xx) += ipic.o 9obj-$(CONFIG_PPC_83xx) += ipic.o
10obj-$(CONFIG_FSL_SOC) += fsl_soc.o
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
new file mode 100644
index 000000000000..064c9de47732
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -0,0 +1,317 @@
1/*
2 * FSL SoC setup code
3 *
4 * Maintained by Kumar Gala (see MAINTAINERS for contact information)
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 */
11
12#include <linux/config.h>
13#include <linux/stddef.h>
14#include <linux/kernel.h>
15#include <linux/init.h>
16#include <linux/errno.h>
17#include <linux/major.h>
18#include <linux/delay.h>
19#include <linux/irq.h>
20#include <linux/module.h>
21#include <linux/device.h>
22#include <linux/platform_device.h>
23#include <linux/fsl_devices.h>
24
25#include <asm/system.h>
26#include <asm/atomic.h>
27#include <asm/io.h>
28#include <asm/irq.h>
29#include <asm/prom.h>
30#include <sysdev/fsl_soc.h>
31#include <mm/mmu_decl.h>
32
33static phys_addr_t immrbase = -1;
34
35phys_addr_t get_immrbase(void)
36{
37 struct device_node *soc;
38
39 if (immrbase != -1)
40 return immrbase;
41
42 soc = of_find_node_by_type(NULL, "soc");
43 if (soc != 0) {
44 unsigned int size;
45 void *prop = get_property(soc, "reg", &size);
46 immrbase = of_translate_address(soc, prop);
47 of_node_put(soc);
48 };
49
50 return immrbase;
51}
52EXPORT_SYMBOL(get_immrbase);
53
54static const char * gfar_tx_intr = "tx";
55static const char * gfar_rx_intr = "rx";
56static const char * gfar_err_intr = "error";
57
58static int __init gfar_of_init(void)
59{
60 struct device_node *np;
61 unsigned int i;
62 struct platform_device *mdio_dev, *gfar_dev;
63 struct resource res;
64 int ret;
65
66 for (np = NULL, i = 0; (np = of_find_compatible_node(np, "mdio", "gianfar")) != NULL; i++) {
67 int k;
68 struct device_node *child = NULL;
69 struct gianfar_mdio_data mdio_data;
70
71 memset(&res, 0, sizeof(res));
72 memset(&mdio_data, 0, sizeof(mdio_data));
73
74 ret = of_address_to_resource(np, 0, &res);
75 if (ret)
76 goto mdio_err;
77
78 mdio_dev = platform_device_register_simple("fsl-gianfar_mdio", res.start, &res, 1);
79 if (IS_ERR(mdio_dev)) {
80 ret = PTR_ERR(mdio_dev);
81 goto mdio_err;
82 }
83
84 for (k = 0; k < 32; k++)
85 mdio_data.irq[k] = -1;
86
87 while ((child = of_get_next_child(np, child)) != NULL) {
88 if (child->n_intrs) {
89 u32 *id = (u32 *) get_property(child, "reg", NULL);
90 mdio_data.irq[*id] = child->intrs[0].line;
91 }
92 }
93
94 ret = platform_device_add_data(mdio_dev, &mdio_data, sizeof(struct gianfar_mdio_data));
95 if (ret)
96 goto mdio_unreg;
97 }
98
99 for (np = NULL, i = 0; (np = of_find_compatible_node(np, "network", "gianfar")) != NULL; i++) {
100 struct resource r[4];
101 struct device_node *phy, *mdio;
102 struct gianfar_platform_data gfar_data;
103 unsigned int *id;
104 char *model;
105 void *mac_addr;
106 phandle *ph;
107
108 memset(r, 0, sizeof(r));
109 memset(&gfar_data, 0, sizeof(gfar_data));
110
111 ret = of_address_to_resource(np, 0, &r[0]);
112 if (ret)
113 goto gfar_err;
114
115 r[1].start = np->intrs[0].line;
116 r[1].end = np->intrs[0].line;
117 r[1].flags = IORESOURCE_IRQ;
118
119 model = get_property(np, "model", NULL);
120
121 /* If we aren't the FEC we have multiple interrupts */
122 if (model && strcasecmp(model, "FEC")) {
123 r[1].name = gfar_tx_intr;
124
125 r[2].name = gfar_rx_intr;
126 r[2].start = np->intrs[1].line;
127 r[2].end = np->intrs[1].line;
128 r[2].flags = IORESOURCE_IRQ;
129
130 r[3].name = gfar_err_intr;
131 r[3].start = np->intrs[2].line;
132 r[3].end = np->intrs[2].line;
133 r[3].flags = IORESOURCE_IRQ;
134 }
135
136 gfar_dev = platform_device_register_simple("fsl-gianfar", i, &r[0], np->n_intrs + 1);
137
138 if (IS_ERR(gfar_dev)) {
139 ret = PTR_ERR(gfar_dev);
140 goto gfar_err;
141 }
142
143 mac_addr = get_property(np, "address", NULL);
144 memcpy(gfar_data.mac_addr, mac_addr, 6);
145
146 if (model && !strcasecmp(model, "TSEC"))
147 gfar_data.device_flags =
148 FSL_GIANFAR_DEV_HAS_GIGABIT |
149 FSL_GIANFAR_DEV_HAS_COALESCE |
150 FSL_GIANFAR_DEV_HAS_RMON |
151 FSL_GIANFAR_DEV_HAS_MULTI_INTR;
152 if (model && !strcasecmp(model, "eTSEC"))
153 gfar_data.device_flags =
154 FSL_GIANFAR_DEV_HAS_GIGABIT |
155 FSL_GIANFAR_DEV_HAS_COALESCE |
156 FSL_GIANFAR_DEV_HAS_RMON |
157 FSL_GIANFAR_DEV_HAS_MULTI_INTR |
158 FSL_GIANFAR_DEV_HAS_CSUM |
159 FSL_GIANFAR_DEV_HAS_VLAN |
160 FSL_GIANFAR_DEV_HAS_EXTENDED_HASH;
161
162 ph = (phandle *) get_property(np, "phy-handle", NULL);
163 phy = of_find_node_by_phandle(*ph);
164
165 if (phy == NULL) {
166 ret = -ENODEV;
167 goto gfar_unreg;
168 }
169
170 mdio = of_get_parent(phy);
171
172 id = (u32 *) get_property(phy, "reg", NULL);
173 ret = of_address_to_resource(mdio, 0, &res);
174 if (ret) {
175 of_node_put(phy);
176 of_node_put(mdio);
177 goto gfar_unreg;
178 }
179
180 gfar_data.phy_id = *id;
181 gfar_data.bus_id = res.start;
182
183 of_node_put(phy);
184 of_node_put(mdio);
185
186 ret = platform_device_add_data(gfar_dev, &gfar_data, sizeof(struct gianfar_platform_data));
187 if (ret)
188 goto gfar_unreg;
189 }
190
191 return 0;
192
193mdio_unreg:
194 platform_device_unregister(mdio_dev);
195mdio_err:
196 return ret;
197
198gfar_unreg:
199 platform_device_unregister(gfar_dev);
200gfar_err:
201 return ret;
202}
203arch_initcall(gfar_of_init);
204
205static int __init fsl_i2c_of_init(void)
206{
207 struct device_node *np;
208 unsigned int i;
209 struct platform_device *i2c_dev;
210 int ret;
211
212 for (np = NULL, i = 0; (np = of_find_compatible_node(np, "i2c", "fsl-i2c")) != NULL; i++) {
213 struct resource r[2];
214 struct fsl_i2c_platform_data i2c_data;
215 unsigned char * flags = NULL;
216
217 memset(&r, 0, sizeof(r));
218 memset(&i2c_data, 0, sizeof(i2c_data));
219
220 ret = of_address_to_resource(np, 0, &r[0]);
221 if (ret)
222 goto i2c_err;
223
224 r[1].start = np->intrs[0].line;
225 r[1].end = np->intrs[0].line;
226 r[1].flags = IORESOURCE_IRQ;
227
228 i2c_dev = platform_device_register_simple("fsl-i2c", i, r, 2);
229 if (IS_ERR(i2c_dev)) {
230 ret = PTR_ERR(i2c_dev);
231 goto i2c_err;
232 }
233
234 i2c_data.device_flags = 0;
235 flags = get_property(np, "dfsrr", NULL);
236 if (flags)
237 i2c_data.device_flags |= FSL_I2C_DEV_SEPARATE_DFSRR;
238
239 flags = get_property(np, "fsl5200-clocking", NULL);
240 if (flags)
241 i2c_data.device_flags |= FSL_I2C_DEV_CLOCK_5200;
242
243 ret = platform_device_add_data(i2c_dev, &i2c_data, sizeof(struct fsl_i2c_platform_data));
244 if (ret)
245 goto i2c_unreg;
246 }
247
248 return 0;
249
250i2c_unreg:
251 platform_device_unregister(i2c_dev);
252i2c_err:
253 return ret;
254}
255arch_initcall(fsl_i2c_of_init);
256
257#ifdef CONFIG_PPC_83xx
258static int __init mpc83xx_wdt_init(void)
259{
260 struct resource r;
261 struct device_node *soc, *np;
262 struct platform_device *dev;
263 unsigned int *freq;
264 int ret;
265
266 np = of_find_compatible_node(NULL, "watchdog", "mpc83xx_wdt");
267
268 if (!np) {
269 ret = -ENODEV;
270 goto mpc83xx_wdt_nodev;
271 }
272
273 soc = of_find_node_by_type(NULL, "soc");
274
275 if (!soc) {
276 ret = -ENODEV;
277 goto mpc83xx_wdt_nosoc;
278 }
279
280 freq = (unsigned int *)get_property(soc, "bus-frequency", NULL);
281 if (!freq) {
282 ret = -ENODEV;
283 goto mpc83xx_wdt_err;
284 }
285
286 memset(&r, 0, sizeof(r));
287
288 ret = of_address_to_resource(np, 0, &r);
289 if (ret)
290 goto mpc83xx_wdt_err;
291
292 dev = platform_device_register_simple("mpc83xx_wdt", 0, &r, 1);
293 if (IS_ERR(dev)) {
294 ret = PTR_ERR(dev);
295 goto mpc83xx_wdt_err;
296 }
297
298 ret = platform_device_add_data(dev, freq, sizeof(int));
299 if (ret)
300 goto mpc83xx_wdt_unreg;
301
302 of_node_put(soc);
303 of_node_put(np);
304
305 return 0;
306
307mpc83xx_wdt_unreg:
308 platform_device_unregister(dev);
309mpc83xx_wdt_err:
310 of_node_put(soc);
311mpc83xx_wdt_nosoc:
312 of_node_put(np);
313mpc83xx_wdt_nodev:
314 return ret;
315}
316arch_initcall(mpc83xx_wdt_init);
317#endif
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h
new file mode 100644
index 000000000000..c433d3f39edd
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_soc.h
@@ -0,0 +1,8 @@
1#ifndef __PPC_FSL_SOC_H
2#define __PPC_FSL_SOC_H
3#ifdef __KERNEL__
4
5extern phys_addr_t get_immrbase(void);
6
7#endif
8#endif
diff --git a/arch/ppc/4xx_io/serial_sicc.c b/arch/ppc/4xx_io/serial_sicc.c
index ebc4db8fcc63..8ace2a1f3b48 100644
--- a/arch/ppc/4xx_io/serial_sicc.c
+++ b/arch/ppc/4xx_io/serial_sicc.c
@@ -215,7 +215,6 @@ static struct tty_driver *siccnormal_driver;
215 * memory if large numbers of serial ports are open. 215 * memory if large numbers of serial ports are open.
216 */ 216 */
217static u_char *tmp_buf; 217static u_char *tmp_buf;
218static DECLARE_MUTEX(tmp_buf_sem);
219 218
220#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) 219#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
221 220
diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S
index de0978742221..3e6ca7f5843f 100644
--- a/arch/ppc/kernel/head_8xx.S
+++ b/arch/ppc/kernel/head_8xx.S
@@ -375,6 +375,8 @@ DataStoreTLBMiss:
375 lis r11, swapper_pg_dir@h 375 lis r11, swapper_pg_dir@h
376 ori r11, r11, swapper_pg_dir@l 376 ori r11, r11, swapper_pg_dir@l
377 rlwimi r10, r11, 0, 2, 19 377 rlwimi r10, r11, 0, 2, 19
378 stw r12, 16(r0)
379 b LoadLargeDTLB
3783: 3803:
379 lwz r11, 0(r10) /* Get the level 1 entry */ 381 lwz r11, 0(r10) /* Get the level 1 entry */
380 rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */ 382 rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */
@@ -430,6 +432,81 @@ DataStoreTLBMiss:
430InstructionTLBError: 432InstructionTLBError:
431 b InstructionAccess 433 b InstructionAccess
432 434
435LoadLargeDTLB:
436 li r12, 0
437 lwz r11, 0(r10) /* Get the level 1 entry */
438 rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */
439 beq 3f /* If zero, don't try to find a pte */
440
441 /* We have a pte table, so load fetch the pte from the table.
442 */
443 ori r11, r11, 1 /* Set valid bit in physical L2 page */
444 DO_8xx_CPU6(0x3b80, r3)
445 mtspr SPRN_MD_TWC, r11 /* Load pte table base address */
446 mfspr r10, SPRN_MD_TWC /* ....and get the pte address */
447 lwz r10, 0(r10) /* Get the pte */
448
449 /* Insert the Guarded flag into the TWC from the Linux PTE.
450 * It is bit 27 of both the Linux PTE and the TWC (at least
451 * I got that right :-). It will be better when we can put
452 * this into the Linux pgd/pmd and load it in the operation
453 * above.
454 */
455 rlwimi r11, r10, 0, 27, 27
456
457 rlwimi r12, r10, 0, 0, 9 /* extract phys. addr */
458 mfspr r3, SPRN_MD_EPN
459 rlwinm r3, r3, 0, 0, 9 /* extract virtual address */
460 tophys(r3, r3)
461 cmpw r3, r12 /* only use 8M page if it is a direct
462 kernel mapping */
463 bne 1f
464 ori r11, r11, MD_PS8MEG
465 li r12, 1
466 b 2f
4671:
468 li r12, 0 /* can't use 8MB TLB, so zero r12. */
4692:
470 DO_8xx_CPU6(0x3b80, r3)
471 mtspr SPRN_MD_TWC, r11
472
473 /* The Linux PTE won't go exactly into the MMU TLB.
474 * Software indicator bits 21, 22 and 28 must be clear.
475 * Software indicator bits 24, 25, 26, and 27 must be
476 * set. All other Linux PTE bits control the behavior
477 * of the MMU.
478 */
4793: li r11, 0x00f0
480 rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */
481 cmpwi r12, 1
482 bne 4f
483 ori r10, r10, 0x8
484
485 mfspr r12, SPRN_MD_EPN
486 lis r3, 0xff80 /* 10-19 must be clear for 8MB TLB */
487 ori r3, r3, 0x0fff
488 and r12, r3, r12
489 DO_8xx_CPU6(0x3780, r3)
490 mtspr SPRN_MD_EPN, r12
491
492 lis r3, 0xff80 /* 10-19 must be clear for 8MB TLB */
493 ori r3, r3, 0x0fff
494 and r10, r3, r10
4954:
496 DO_8xx_CPU6(0x3d80, r3)
497 mtspr SPRN_MD_RPN, r10 /* Update TLB entry */
498
499 mfspr r10, SPRN_M_TW /* Restore registers */
500 lwz r11, 0(r0)
501 mtcr r11
502 lwz r11, 4(r0)
503
504 lwz r12, 16(r0)
505#ifdef CONFIG_8xx_CPU6
506 lwz r3, 8(r0)
507#endif
508 rfi
509
433/* This is the data TLB error on the MPC8xx. This could be due to 510/* This is the data TLB error on the MPC8xx. This could be due to
434 * many reasons, including a dirty update to a pte. We can catch that 511 * many reasons, including a dirty update to a pte. We can catch that
435 * one here, but anything else is an error. First, we track down the 512 * one here, but anything else is an error. First, we track down the
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index 95075f99a6d4..fb0da7c209db 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -270,7 +270,6 @@ EXPORT_SYMBOL(__delay);
270EXPORT_SYMBOL(timer_interrupt); 270EXPORT_SYMBOL(timer_interrupt);
271EXPORT_SYMBOL(irq_desc); 271EXPORT_SYMBOL(irq_desc);
272EXPORT_SYMBOL(tb_ticks_per_jiffy); 272EXPORT_SYMBOL(tb_ticks_per_jiffy);
273EXPORT_SYMBOL(get_wchan);
274EXPORT_SYMBOL(console_drivers); 273EXPORT_SYMBOL(console_drivers);
275#ifdef CONFIG_XMON 274#ifdef CONFIG_XMON
276EXPORT_SYMBOL(xmon); 275EXPORT_SYMBOL(xmon);
diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.c b/arch/ppc/platforms/83xx/mpc834x_sys.c
index 04bdc39bf47b..012e1e652c03 100644
--- a/arch/ppc/platforms/83xx/mpc834x_sys.c
+++ b/arch/ppc/platforms/83xx/mpc834x_sys.c
@@ -51,9 +51,6 @@
51 51
52#include <syslib/ppc83xx_setup.h> 52#include <syslib/ppc83xx_setup.h>
53 53
54static const char *GFAR_PHY_0 = "phy0:0";
55static const char *GFAR_PHY_1 = "phy0:1";
56
57#ifndef CONFIG_PCI 54#ifndef CONFIG_PCI
58unsigned long isa_io_base = 0; 55unsigned long isa_io_base = 0;
59unsigned long isa_mem_base = 0; 56unsigned long isa_mem_base = 0;
@@ -129,20 +126,21 @@ mpc834x_sys_setup_arch(void)
129 mdata->irq[1] = MPC83xx_IRQ_EXT2; 126 mdata->irq[1] = MPC83xx_IRQ_EXT2;
130 mdata->irq[2] = -1; 127 mdata->irq[2] = -1;
131 mdata->irq[31] = -1; 128 mdata->irq[31] = -1;
132 mdata->paddr += binfo->bi_immr_base;
133 129
134 /* setup the board related information for the enet controllers */ 130 /* setup the board related information for the enet controllers */
135 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC1); 131 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC1);
136 if (pdata) { 132 if (pdata) {
137 pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; 133 pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
138 pdata->bus_id = GFAR_PHY_0; 134 pdata->bus_id = 0;
135 pdata->phy_id = 0;
139 memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); 136 memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
140 } 137 }
141 138
142 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC2); 139 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC2);
143 if (pdata) { 140 if (pdata) {
144 pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; 141 pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
145 pdata->bus_id = GFAR_PHY_1; 142 pdata->bus_id = 0;
143 pdata->phy_id = 1;
146 memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); 144 memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
147 } 145 }
148 146
diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.c b/arch/ppc/platforms/85xx/mpc8540_ads.c
index c5cde97c6ef0..2eceb1e6f4eb 100644
--- a/arch/ppc/platforms/85xx/mpc8540_ads.c
+++ b/arch/ppc/platforms/85xx/mpc8540_ads.c
@@ -52,10 +52,6 @@
52 52
53#include <syslib/ppc85xx_setup.h> 53#include <syslib/ppc85xx_setup.h>
54 54
55static const char *GFAR_PHY_0 = "phy0:0";
56static const char *GFAR_PHY_1 = "phy0:1";
57static const char *GFAR_PHY_3 = "phy0:3";
58
59/* ************************************************************************ 55/* ************************************************************************
60 * 56 *
61 * Setup the architecture 57 * Setup the architecture
@@ -102,27 +98,29 @@ mpc8540ads_setup_arch(void)
102 mdata->irq[2] = -1; 98 mdata->irq[2] = -1;
103 mdata->irq[3] = MPC85xx_IRQ_EXT5; 99 mdata->irq[3] = MPC85xx_IRQ_EXT5;
104 mdata->irq[31] = -1; 100 mdata->irq[31] = -1;
105 mdata->paddr += binfo->bi_immr_base;
106 101
107 /* setup the board related information for the enet controllers */ 102 /* setup the board related information for the enet controllers */
108 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); 103 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
109 if (pdata) { 104 if (pdata) {
110 pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; 105 pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
111 pdata->bus_id = GFAR_PHY_0; 106 pdata->bus_id = 0;
107 pdata->phy_id = 0;
112 memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); 108 memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
113 } 109 }
114 110
115 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); 111 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
116 if (pdata) { 112 if (pdata) {
117 pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; 113 pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
118 pdata->bus_id = GFAR_PHY_1; 114 pdata->bus_id = 0;
115 pdata->phy_id = 1;
119 memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); 116 memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
120 } 117 }
121 118
122 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_FEC); 119 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_FEC);
123 if (pdata) { 120 if (pdata) {
124 pdata->board_flags = 0; 121 pdata->board_flags = 0;
125 pdata->bus_id = GFAR_PHY_3; 122 pdata->bus_id = 0;
123 pdata->phy_id = 3;
126 memcpy(pdata->mac_addr, binfo->bi_enet2addr, 6); 124 memcpy(pdata->mac_addr, binfo->bi_enet2addr, 6);
127 } 125 }
128 126
diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.c b/arch/ppc/platforms/85xx/mpc8560_ads.c
index 8e39a5517092..442c7ff195d3 100644
--- a/arch/ppc/platforms/85xx/mpc8560_ads.c
+++ b/arch/ppc/platforms/85xx/mpc8560_ads.c
@@ -56,10 +56,6 @@
56#include <syslib/ppc85xx_setup.h> 56#include <syslib/ppc85xx_setup.h>
57 57
58 58
59static const char *GFAR_PHY_0 = "phy0:0";
60static const char *GFAR_PHY_1 = "phy0:1";
61static const char *GFAR_PHY_3 = "phy0:3";
62
63/* ************************************************************************ 59/* ************************************************************************
64 * 60 *
65 * Setup the architecture 61 * Setup the architecture
@@ -99,20 +95,21 @@ mpc8560ads_setup_arch(void)
99 mdata->irq[2] = -1; 95 mdata->irq[2] = -1;
100 mdata->irq[3] = MPC85xx_IRQ_EXT5; 96 mdata->irq[3] = MPC85xx_IRQ_EXT5;
101 mdata->irq[31] = -1; 97 mdata->irq[31] = -1;
102 mdata->paddr += binfo->bi_immr_base;
103 98
104 /* setup the board related information for the enet controllers */ 99 /* setup the board related information for the enet controllers */
105 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); 100 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
106 if (pdata) { 101 if (pdata) {
107 pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; 102 pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
108 pdata->bus_id = GFAR_PHY_0; 103 pdata->bus_id = 0;
104 pdata->phy_id = 0;
109 memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); 105 memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
110 } 106 }
111 107
112 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); 108 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
113 if (pdata) { 109 if (pdata) {
114 pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; 110 pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
115 pdata->bus_id = GFAR_PHY_1; 111 pdata->bus_id = 0;
112 pdata->phy_id = 1;
116 memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); 113 memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
117 } 114 }
118 115
diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
index 2959e3c4083d..b332ebae6bd3 100644
--- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
+++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
@@ -395,9 +395,6 @@ mpc85xx_cds_pcibios_fixup(void)
395 395
396TODC_ALLOC(); 396TODC_ALLOC();
397 397
398static const char *GFAR_PHY_0 = "phy0:0";
399static const char *GFAR_PHY_1 = "phy0:1";
400
401/* ************************************************************************ 398/* ************************************************************************
402 * 399 *
403 * Setup the architecture 400 * Setup the architecture
@@ -461,34 +458,37 @@ mpc85xx_cds_setup_arch(void)
461 mdata->irq[2] = -1; 458 mdata->irq[2] = -1;
462 mdata->irq[3] = -1; 459 mdata->irq[3] = -1;
463 mdata->irq[31] = -1; 460 mdata->irq[31] = -1;
464 mdata->paddr += binfo->bi_immr_base;
465 461
466 /* setup the board related information for the enet controllers */ 462 /* setup the board related information for the enet controllers */
467 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); 463 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
468 if (pdata) { 464 if (pdata) {
469 pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; 465 pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
470 pdata->bus_id = GFAR_PHY_0; 466 pdata->bus_id = 0;
467 pdata->phy_id = 0;
471 memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); 468 memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
472 } 469 }
473 470
474 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); 471 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
475 if (pdata) { 472 if (pdata) {
476 pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; 473 pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
477 pdata->bus_id = GFAR_PHY_1; 474 pdata->bus_id = 0;
475 pdata->phy_id = 1;
478 memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); 476 memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
479 } 477 }
480 478
481 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_eTSEC1); 479 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_eTSEC1);
482 if (pdata) { 480 if (pdata) {
483 pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; 481 pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
484 pdata->bus_id = GFAR_PHY_0; 482 pdata->bus_id = 0;
483 pdata->phy_id = 0;
485 memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); 484 memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
486 } 485 }
487 486
488 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_eTSEC2); 487 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_eTSEC2);
489 if (pdata) { 488 if (pdata) {
490 pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; 489 pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
491 pdata->bus_id = GFAR_PHY_1; 490 pdata->bus_id = 0;
491 pdata->phy_id = 1;
492 memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); 492 memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
493 } 493 }
494 494
diff --git a/arch/ppc/platforms/85xx/sbc8560.c b/arch/ppc/platforms/85xx/sbc8560.c
index 45a5b81b4ed1..e777ba824aa9 100644
--- a/arch/ppc/platforms/85xx/sbc8560.c
+++ b/arch/ppc/platforms/85xx/sbc8560.c
@@ -91,9 +91,6 @@ sbc8560_early_serial_map(void)
91} 91}
92#endif 92#endif
93 93
94static const char *GFAR_PHY_25 = "phy0:25";
95static const char *GFAR_PHY_26 = "phy0:26";
96
97/* ************************************************************************ 94/* ************************************************************************
98 * 95 *
99 * Setup the architecture 96 * Setup the architecture
@@ -136,20 +133,21 @@ sbc8560_setup_arch(void)
136 mdata->irq[25] = MPC85xx_IRQ_EXT6; 133 mdata->irq[25] = MPC85xx_IRQ_EXT6;
137 mdata->irq[26] = MPC85xx_IRQ_EXT7; 134 mdata->irq[26] = MPC85xx_IRQ_EXT7;
138 mdata->irq[31] = -1; 135 mdata->irq[31] = -1;
139 mdata->paddr += binfo->bi_immr_base;
140 136
141 /* setup the board related information for the enet controllers */ 137 /* setup the board related information for the enet controllers */
142 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); 138 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
143 if (pdata) { 139 if (pdata) {
144 pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; 140 pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
145 pdata->bus_id = GFAR_PHY_25; 141 pdata->bus_id = 0;
142 pdata->phy_id = 25;
146 memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); 143 memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
147 } 144 }
148 145
149 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); 146 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
150 if (pdata) { 147 if (pdata) {
151 pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; 148 pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
152 pdata->bus_id = GFAR_PHY_26; 149 pdata->bus_id = 0;
150 pdata->phy_id = 26;
153 memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); 151 memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
154 } 152 }
155 153
diff --git a/arch/ppc/platforms/85xx/stx_gp3.c b/arch/ppc/platforms/85xx/stx_gp3.c
index 15ce9d070634..061bb7cf2d9a 100644
--- a/arch/ppc/platforms/85xx/stx_gp3.c
+++ b/arch/ppc/platforms/85xx/stx_gp3.c
@@ -93,9 +93,6 @@ static u8 gp3_openpic_initsenses[] __initdata = {
93 0x0, /* External 11: */ 93 0x0, /* External 11: */
94}; 94};
95 95
96static const char *GFAR_PHY_2 = "phy0:2";
97static const char *GFAR_PHY_4 = "phy0:4";
98
99/* 96/*
100 * Setup the architecture 97 * Setup the architecture
101 */ 98 */
@@ -130,20 +127,21 @@ gp3_setup_arch(void)
130 mdata->irq[2] = MPC85xx_IRQ_EXT5; 127 mdata->irq[2] = MPC85xx_IRQ_EXT5;
131 mdata->irq[4] = MPC85xx_IRQ_EXT5; 128 mdata->irq[4] = MPC85xx_IRQ_EXT5;
132 mdata->irq[31] = -1; 129 mdata->irq[31] = -1;
133 mdata->paddr += binfo->bi_immr_base;
134 130
135 /* setup the board related information for the enet controllers */ 131 /* setup the board related information for the enet controllers */
136 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); 132 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
137 if (pdata) { 133 if (pdata) {
138 /* pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; */ 134 /* pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; */
139 pdata->bus_id = GFAR_PHY_2; 135 pdata->bus_id = 0;
136 pdata->phy_id = 2;
140 memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); 137 memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
141 } 138 }
142 139
143 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); 140 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
144 if (pdata) { 141 if (pdata) {
145 /* pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; */ 142 /* pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; */
146 pdata->bus_id = GFAR_PHY_4; 143 pdata->bus_id = 0;
144 pdata->phy_id = 4;
147 memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); 145 memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
148 } 146 }
149 147
diff --git a/arch/ppc/platforms/85xx/tqm85xx.c b/arch/ppc/platforms/85xx/tqm85xx.c
index c6dfd8f0f9df..b436f4d0a3fa 100644
--- a/arch/ppc/platforms/85xx/tqm85xx.c
+++ b/arch/ppc/platforms/85xx/tqm85xx.c
@@ -91,12 +91,6 @@ static u_char tqm85xx_openpic_initsenses[] __initdata = {
91 0x0, /* External 11: */ 91 0x0, /* External 11: */
92}; 92};
93 93
94static const char *GFAR_PHY_0 = "phy0:2";
95static const char *GFAR_PHY_1 = "phy0:1";
96#ifdef CONFIG_MPC8540
97static const char *GFAR_PHY_3 = "phy0:3";
98#endif
99
100/* ************************************************************************ 94/* ************************************************************************
101 * 95 *
102 * Setup the architecture 96 * Setup the architecture
@@ -149,20 +143,21 @@ tqm85xx_setup_arch(void)
149 mdata->irq[2] = -1; 143 mdata->irq[2] = -1;
150 mdata->irq[3] = MPC85xx_IRQ_EXT8; 144 mdata->irq[3] = MPC85xx_IRQ_EXT8;
151 mdata->irq[31] = -1; 145 mdata->irq[31] = -1;
152 mdata->paddr += binfo->bi_immr_base;
153 146
154 /* setup the board related information for the enet controllers */ 147 /* setup the board related information for the enet controllers */
155 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); 148 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
156 if (pdata) { 149 if (pdata) {
157 pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; 150 pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
158 pdata->bus_id = GFAR_PHY_0; 151 pdata->bus_id = 0;
152 pdata->phy_id = 2;
159 memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); 153 memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
160 } 154 }
161 155
162 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); 156 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
163 if (pdata) { 157 if (pdata) {
164 pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; 158 pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
165 pdata->bus_id = GFAR_PHY_1; 159 pdata->bus_id = 0;
160 pdata->phy_id = 1;
166 memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); 161 memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
167 } 162 }
168 163
@@ -170,7 +165,8 @@ tqm85xx_setup_arch(void)
170 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_FEC); 165 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_FEC);
171 if (pdata) { 166 if (pdata) {
172 pdata->board_flags = 0; 167 pdata->board_flags = 0;
173 pdata->bus_id = GFAR_PHY_3; 168 pdata->bus_id = 0;
169 pdata->phy_id = 3;
174 memcpy(pdata->mac_addr, binfo->bi_enet2addr, 6); 170 memcpy(pdata->mac_addr, binfo->bi_enet2addr, 6);
175 } 171 }
176#endif 172#endif
diff --git a/arch/ppc/syslib/mpc83xx_devices.c b/arch/ppc/syslib/mpc83xx_devices.c
index 847df4409982..f9b95de70e23 100644
--- a/arch/ppc/syslib/mpc83xx_devices.c
+++ b/arch/ppc/syslib/mpc83xx_devices.c
@@ -28,7 +28,6 @@
28 */ 28 */
29 29
30struct gianfar_mdio_data mpc83xx_mdio_pdata = { 30struct gianfar_mdio_data mpc83xx_mdio_pdata = {
31 .paddr = 0x24520,
32}; 31};
33 32
34static struct gianfar_platform_data mpc83xx_tsec1_pdata = { 33static struct gianfar_platform_data mpc83xx_tsec1_pdata = {
@@ -226,7 +225,14 @@ struct platform_device ppc_sys_platform_devices[] = {
226 .name = "fsl-gianfar_mdio", 225 .name = "fsl-gianfar_mdio",
227 .id = 0, 226 .id = 0,
228 .dev.platform_data = &mpc83xx_mdio_pdata, 227 .dev.platform_data = &mpc83xx_mdio_pdata,
229 .num_resources = 0, 228 .num_resources = 1,
229 .resource = (struct resource[]) {
230 {
231 .start = 0x24520,
232 .end = 0x2453f,
233 .flags = IORESOURCE_MEM,
234 },
235 },
230 }, 236 },
231}; 237};
232 238
diff --git a/arch/ppc/syslib/mpc85xx_devices.c b/arch/ppc/syslib/mpc85xx_devices.c
index 69949d255658..00e9b6ff2f6e 100644
--- a/arch/ppc/syslib/mpc85xx_devices.c
+++ b/arch/ppc/syslib/mpc85xx_devices.c
@@ -26,7 +26,6 @@
26 * what CCSRBAR is, will get fixed up by mach_mpc85xx_fixup 26 * what CCSRBAR is, will get fixed up by mach_mpc85xx_fixup
27 */ 27 */
28struct gianfar_mdio_data mpc85xx_mdio_pdata = { 28struct gianfar_mdio_data mpc85xx_mdio_pdata = {
29 .paddr = MPC85xx_MIIM_OFFSET,
30}; 29};
31 30
32static struct gianfar_platform_data mpc85xx_tsec1_pdata = { 31static struct gianfar_platform_data mpc85xx_tsec1_pdata = {
@@ -720,7 +719,14 @@ struct platform_device ppc_sys_platform_devices[] = {
720 .name = "fsl-gianfar_mdio", 719 .name = "fsl-gianfar_mdio",
721 .id = 0, 720 .id = 0,
722 .dev.platform_data = &mpc85xx_mdio_pdata, 721 .dev.platform_data = &mpc85xx_mdio_pdata,
723 .num_resources = 0, 722 .num_resources = 1,
723 .resource = (struct resource[]) {
724 {
725 .start = 0x24520,
726 .end = 0x2453f,
727 .flags = IORESOURCE_MEM,
728 },
729 },
724 }, 730 },
725}; 731};
726 732
diff --git a/arch/ppc/syslib/ocp.c b/arch/ppc/syslib/ocp.c
index 9ccce438bd7a..ab34b1d6072f 100644
--- a/arch/ppc/syslib/ocp.c
+++ b/arch/ppc/syslib/ocp.c
@@ -189,6 +189,8 @@ ocp_device_resume(struct device *dev)
189struct bus_type ocp_bus_type = { 189struct bus_type ocp_bus_type = {
190 .name = "ocp", 190 .name = "ocp",
191 .match = ocp_device_match, 191 .match = ocp_device_match,
192 .probe = ocp_driver_probe,
193 .remove = ocp_driver_remove,
192 .suspend = ocp_device_suspend, 194 .suspend = ocp_device_suspend,
193 .resume = ocp_device_resume, 195 .resume = ocp_device_resume,
194}; 196};
@@ -210,8 +212,6 @@ ocp_register_driver(struct ocp_driver *drv)
210 /* initialize common driver fields */ 212 /* initialize common driver fields */
211 drv->driver.name = drv->name; 213 drv->driver.name = drv->name;
212 drv->driver.bus = &ocp_bus_type; 214 drv->driver.bus = &ocp_bus_type;
213 drv->driver.probe = ocp_device_probe;
214 drv->driver.remove = ocp_device_remove;
215 215
216 /* register with core */ 216 /* register with core */
217 return driver_register(&drv->driver); 217 return driver_register(&drv->driver);
diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c
index 7a1033d8e00f..c5ca2dc5d428 100644
--- a/arch/s390/crypto/aes_s390.c
+++ b/arch/s390/crypto/aes_s390.c
@@ -114,80 +114,108 @@ static unsigned int aes_encrypt_ecb(const struct cipher_desc *desc, u8 *out,
114 const u8 *in, unsigned int nbytes) 114 const u8 *in, unsigned int nbytes)
115{ 115{
116 struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm); 116 struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm);
117 int ret;
118
119 /* only use complete blocks */
120 nbytes &= ~(AES_BLOCK_SIZE - 1);
117 121
118 switch (sctx->key_len) { 122 switch (sctx->key_len) {
119 case 16: 123 case 16:
120 crypt_s390_km(KM_AES_128_ENCRYPT, &sctx->key, out, in, nbytes); 124 ret = crypt_s390_km(KM_AES_128_ENCRYPT, &sctx->key, out, in, nbytes);
125 BUG_ON((ret < 0) || (ret != nbytes));
121 break; 126 break;
122 case 24: 127 case 24:
123 crypt_s390_km(KM_AES_192_ENCRYPT, &sctx->key, out, in, nbytes); 128 ret = crypt_s390_km(KM_AES_192_ENCRYPT, &sctx->key, out, in, nbytes);
129 BUG_ON((ret < 0) || (ret != nbytes));
124 break; 130 break;
125 case 32: 131 case 32:
126 crypt_s390_km(KM_AES_256_ENCRYPT, &sctx->key, out, in, nbytes); 132 ret = crypt_s390_km(KM_AES_256_ENCRYPT, &sctx->key, out, in, nbytes);
133 BUG_ON((ret < 0) || (ret != nbytes));
127 break; 134 break;
128 } 135 }
129 return nbytes & ~(AES_BLOCK_SIZE - 1); 136 return nbytes;
130} 137}
131 138
132static unsigned int aes_decrypt_ecb(const struct cipher_desc *desc, u8 *out, 139static unsigned int aes_decrypt_ecb(const struct cipher_desc *desc, u8 *out,
133 const u8 *in, unsigned int nbytes) 140 const u8 *in, unsigned int nbytes)
134{ 141{
135 struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm); 142 struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm);
143 int ret;
144
145 /* only use complete blocks */
146 nbytes &= ~(AES_BLOCK_SIZE - 1);
136 147
137 switch (sctx->key_len) { 148 switch (sctx->key_len) {
138 case 16: 149 case 16:
139 crypt_s390_km(KM_AES_128_DECRYPT, &sctx->key, out, in, nbytes); 150 ret = crypt_s390_km(KM_AES_128_DECRYPT, &sctx->key, out, in, nbytes);
151 BUG_ON((ret < 0) || (ret != nbytes));
140 break; 152 break;
141 case 24: 153 case 24:
142 crypt_s390_km(KM_AES_192_DECRYPT, &sctx->key, out, in, nbytes); 154 ret = crypt_s390_km(KM_AES_192_DECRYPT, &sctx->key, out, in, nbytes);
155 BUG_ON((ret < 0) || (ret != nbytes));
143 break; 156 break;
144 case 32: 157 case 32:
145 crypt_s390_km(KM_AES_256_DECRYPT, &sctx->key, out, in, nbytes); 158 ret = crypt_s390_km(KM_AES_256_DECRYPT, &sctx->key, out, in, nbytes);
159 BUG_ON((ret < 0) || (ret != nbytes));
146 break; 160 break;
147 } 161 }
148 return nbytes & ~(AES_BLOCK_SIZE - 1); 162 return nbytes;
149} 163}
150 164
151static unsigned int aes_encrypt_cbc(const struct cipher_desc *desc, u8 *out, 165static unsigned int aes_encrypt_cbc(const struct cipher_desc *desc, u8 *out,
152 const u8 *in, unsigned int nbytes) 166 const u8 *in, unsigned int nbytes)
153{ 167{
154 struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm); 168 struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm);
169 int ret;
170
171 /* only use complete blocks */
172 nbytes &= ~(AES_BLOCK_SIZE - 1);
155 173
156 memcpy(&sctx->iv, desc->info, AES_BLOCK_SIZE); 174 memcpy(&sctx->iv, desc->info, AES_BLOCK_SIZE);
157 switch (sctx->key_len) { 175 switch (sctx->key_len) {
158 case 16: 176 case 16:
159 crypt_s390_kmc(KMC_AES_128_ENCRYPT, &sctx->iv, out, in, nbytes); 177 ret = crypt_s390_kmc(KMC_AES_128_ENCRYPT, &sctx->iv, out, in, nbytes);
178 BUG_ON((ret < 0) || (ret != nbytes));
160 break; 179 break;
161 case 24: 180 case 24:
162 crypt_s390_kmc(KMC_AES_192_ENCRYPT, &sctx->iv, out, in, nbytes); 181 ret = crypt_s390_kmc(KMC_AES_192_ENCRYPT, &sctx->iv, out, in, nbytes);
182 BUG_ON((ret < 0) || (ret != nbytes));
163 break; 183 break;
164 case 32: 184 case 32:
165 crypt_s390_kmc(KMC_AES_256_ENCRYPT, &sctx->iv, out, in, nbytes); 185 ret = crypt_s390_kmc(KMC_AES_256_ENCRYPT, &sctx->iv, out, in, nbytes);
186 BUG_ON((ret < 0) || (ret != nbytes));
166 break; 187 break;
167 } 188 }
168 memcpy(desc->info, &sctx->iv, AES_BLOCK_SIZE); 189 memcpy(desc->info, &sctx->iv, AES_BLOCK_SIZE);
169 190
170 return nbytes & ~(AES_BLOCK_SIZE - 1); 191 return nbytes;
171} 192}
172 193
173static unsigned int aes_decrypt_cbc(const struct cipher_desc *desc, u8 *out, 194static unsigned int aes_decrypt_cbc(const struct cipher_desc *desc, u8 *out,
174 const u8 *in, unsigned int nbytes) 195 const u8 *in, unsigned int nbytes)
175{ 196{
176 struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm); 197 struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm);
198 int ret;
199
200 /* only use complete blocks */
201 nbytes &= ~(AES_BLOCK_SIZE - 1);
177 202
178 memcpy(&sctx->iv, desc->info, AES_BLOCK_SIZE); 203 memcpy(&sctx->iv, desc->info, AES_BLOCK_SIZE);
179 switch (sctx->key_len) { 204 switch (sctx->key_len) {
180 case 16: 205 case 16:
181 crypt_s390_kmc(KMC_AES_128_DECRYPT, &sctx->iv, out, in, nbytes); 206 ret = crypt_s390_kmc(KMC_AES_128_DECRYPT, &sctx->iv, out, in, nbytes);
207 BUG_ON((ret < 0) || (ret != nbytes));
182 break; 208 break;
183 case 24: 209 case 24:
184 crypt_s390_kmc(KMC_AES_192_DECRYPT, &sctx->iv, out, in, nbytes); 210 ret = crypt_s390_kmc(KMC_AES_192_DECRYPT, &sctx->iv, out, in, nbytes);
211 BUG_ON((ret < 0) || (ret != nbytes));
185 break; 212 break;
186 case 32: 213 case 32:
187 crypt_s390_kmc(KMC_AES_256_DECRYPT, &sctx->iv, out, in, nbytes); 214 ret = crypt_s390_kmc(KMC_AES_256_DECRYPT, &sctx->iv, out, in, nbytes);
215 BUG_ON((ret < 0) || (ret != nbytes));
188 break; 216 break;
189 } 217 }
190 return nbytes & ~(AES_BLOCK_SIZE - 1); 218 return nbytes;
191} 219}
192 220
193 221
diff --git a/arch/s390/crypto/des_s390.c b/arch/s390/crypto/des_s390.c
index a38bb2a3eef6..e3c37aa0a199 100644
--- a/arch/s390/crypto/des_s390.c
+++ b/arch/s390/crypto/des_s390.c
@@ -15,10 +15,8 @@
15 */ 15 */
16#include <linux/init.h> 16#include <linux/init.h>
17#include <linux/module.h> 17#include <linux/module.h>
18#include <linux/mm.h>
19#include <linux/errno.h>
20#include <asm/scatterlist.h>
21#include <linux/crypto.h> 18#include <linux/crypto.h>
19
22#include "crypt_s390.h" 20#include "crypt_s390.h"
23#include "crypto_des.h" 21#include "crypto_des.h"
24 22
@@ -46,38 +44,92 @@ struct crypt_s390_des3_192_ctx {
46 u8 key[DES3_192_KEY_SIZE]; 44 u8 key[DES3_192_KEY_SIZE];
47}; 45};
48 46
49static int 47static int des_setkey(void *ctx, const u8 *key, unsigned int keylen,
50des_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) 48 u32 *flags)
51{ 49{
52 struct crypt_s390_des_ctx *dctx; 50 struct crypt_s390_des_ctx *dctx = ctx;
53 int ret; 51 int ret;
54 52
55 dctx = ctx; 53 /* test if key is valid (not a weak key) */
56 //test if key is valid (not a weak key)
57 ret = crypto_des_check_key(key, keylen, flags); 54 ret = crypto_des_check_key(key, keylen, flags);
58 if (ret == 0){ 55 if (ret == 0)
59 memcpy(dctx->key, key, keylen); 56 memcpy(dctx->key, key, keylen);
60 }
61 return ret; 57 return ret;
62} 58}
63 59
60static void des_encrypt(void *ctx, u8 *out, const u8 *in)
61{
62 struct crypt_s390_des_ctx *dctx = ctx;
63
64 crypt_s390_km(KM_DEA_ENCRYPT, dctx->key, out, in, DES_BLOCK_SIZE);
65}
66
67static void des_decrypt(void *ctx, u8 *out, const u8 *in)
68{
69 struct crypt_s390_des_ctx *dctx = ctx;
70
71 crypt_s390_km(KM_DEA_DECRYPT, dctx->key, out, in, DES_BLOCK_SIZE);
72}
73
74static unsigned int des_encrypt_ecb(const struct cipher_desc *desc, u8 *out,
75 const u8 *in, unsigned int nbytes)
76{
77 struct crypt_s390_des_ctx *sctx = crypto_tfm_ctx(desc->tfm);
78 int ret;
79
80 /* only use complete blocks */
81 nbytes &= ~(DES_BLOCK_SIZE - 1);
82 ret = crypt_s390_km(KM_DEA_ENCRYPT, sctx->key, out, in, nbytes);
83 BUG_ON((ret < 0) || (ret != nbytes));
84
85 return nbytes;
86}
64 87
65static void 88static unsigned int des_decrypt_ecb(const struct cipher_desc *desc, u8 *out,
66des_encrypt(void *ctx, u8 *dst, const u8 *src) 89 const u8 *in, unsigned int nbytes)
67{ 90{
68 struct crypt_s390_des_ctx *dctx; 91 struct crypt_s390_des_ctx *sctx = crypto_tfm_ctx(desc->tfm);
92 int ret;
93
94 /* only use complete blocks */
95 nbytes &= ~(DES_BLOCK_SIZE - 1);
96 ret = crypt_s390_km(KM_DEA_DECRYPT, sctx->key, out, in, nbytes);
97 BUG_ON((ret < 0) || (ret != nbytes));
69 98
70 dctx = ctx; 99 return nbytes;
71 crypt_s390_km(KM_DEA_ENCRYPT, dctx->key, dst, src, DES_BLOCK_SIZE);
72} 100}
73 101
74static void 102static unsigned int des_encrypt_cbc(const struct cipher_desc *desc, u8 *out,
75des_decrypt(void *ctx, u8 *dst, const u8 *src) 103 const u8 *in, unsigned int nbytes)
76{ 104{
77 struct crypt_s390_des_ctx *dctx; 105 struct crypt_s390_des_ctx *sctx = crypto_tfm_ctx(desc->tfm);
106 int ret;
78 107
79 dctx = ctx; 108 /* only use complete blocks */
80 crypt_s390_km(KM_DEA_DECRYPT, dctx->key, dst, src, DES_BLOCK_SIZE); 109 nbytes &= ~(DES_BLOCK_SIZE - 1);
110
111 memcpy(sctx->iv, desc->info, DES_BLOCK_SIZE);
112 ret = crypt_s390_kmc(KMC_DEA_ENCRYPT, &sctx->iv, out, in, nbytes);
113 BUG_ON((ret < 0) || (ret != nbytes));
114
115 memcpy(desc->info, sctx->iv, DES_BLOCK_SIZE);
116 return nbytes;
117}
118
119static unsigned int des_decrypt_cbc(const struct cipher_desc *desc, u8 *out,
120 const u8 *in, unsigned int nbytes)
121{
122 struct crypt_s390_des_ctx *sctx = crypto_tfm_ctx(desc->tfm);
123 int ret;
124
125 /* only use complete blocks */
126 nbytes &= ~(DES_BLOCK_SIZE - 1);
127
128 memcpy(&sctx->iv, desc->info, DES_BLOCK_SIZE);
129 ret = crypt_s390_kmc(KMC_DEA_DECRYPT, &sctx->iv, out, in, nbytes);
130 BUG_ON((ret < 0) || (ret != nbytes));
131
132 return nbytes;
81} 133}
82 134
83static struct crypto_alg des_alg = { 135static struct crypto_alg des_alg = {
@@ -87,12 +139,19 @@ static struct crypto_alg des_alg = {
87 .cra_ctxsize = sizeof(struct crypt_s390_des_ctx), 139 .cra_ctxsize = sizeof(struct crypt_s390_des_ctx),
88 .cra_module = THIS_MODULE, 140 .cra_module = THIS_MODULE,
89 .cra_list = LIST_HEAD_INIT(des_alg.cra_list), 141 .cra_list = LIST_HEAD_INIT(des_alg.cra_list),
90 .cra_u = { .cipher = { 142 .cra_u = {
91 .cia_min_keysize = DES_KEY_SIZE, 143 .cipher = {
92 .cia_max_keysize = DES_KEY_SIZE, 144 .cia_min_keysize = DES_KEY_SIZE,
93 .cia_setkey = des_setkey, 145 .cia_max_keysize = DES_KEY_SIZE,
94 .cia_encrypt = des_encrypt, 146 .cia_setkey = des_setkey,
95 .cia_decrypt = des_decrypt } } 147 .cia_encrypt = des_encrypt,
148 .cia_decrypt = des_decrypt,
149 .cia_encrypt_ecb = des_encrypt_ecb,
150 .cia_decrypt_ecb = des_decrypt_ecb,
151 .cia_encrypt_cbc = des_encrypt_cbc,
152 .cia_decrypt_cbc = des_decrypt_cbc,
153 }
154 }
96}; 155};
97 156
98/* 157/*
@@ -107,20 +166,18 @@ static struct crypto_alg des_alg = {
107 * Implementers MUST reject keys that exhibit this property. 166 * Implementers MUST reject keys that exhibit this property.
108 * 167 *
109 */ 168 */
110static int 169static int des3_128_setkey(void *ctx, const u8 *key, unsigned int keylen,
111des3_128_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) 170 u32 *flags)
112{ 171{
113 int i, ret; 172 int i, ret;
114 struct crypt_s390_des3_128_ctx *dctx; 173 struct crypt_s390_des3_128_ctx *dctx = ctx;
115 const u8* temp_key = key; 174 const u8* temp_key = key;
116 175
117 dctx = ctx;
118 if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE))) { 176 if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE))) {
119
120 *flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED; 177 *flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED;
121 return -EINVAL; 178 return -EINVAL;
122 } 179 }
123 for (i = 0; i < 2; i++, temp_key += DES_KEY_SIZE) { 180 for (i = 0; i < 2; i++, temp_key += DES_KEY_SIZE) {
124 ret = crypto_des_check_key(temp_key, DES_KEY_SIZE, flags); 181 ret = crypto_des_check_key(temp_key, DES_KEY_SIZE, flags);
125 if (ret < 0) 182 if (ret < 0)
126 return ret; 183 return ret;
@@ -129,24 +186,85 @@ des3_128_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags)
129 return 0; 186 return 0;
130} 187}
131 188
132static void 189static void des3_128_encrypt(void *ctx, u8 *dst, const u8 *src)
133des3_128_encrypt(void *ctx, u8 *dst, const u8 *src)
134{ 190{
135 struct crypt_s390_des3_128_ctx *dctx; 191 struct crypt_s390_des3_128_ctx *dctx = ctx;
136 192
137 dctx = ctx;
138 crypt_s390_km(KM_TDEA_128_ENCRYPT, dctx->key, dst, (void*)src, 193 crypt_s390_km(KM_TDEA_128_ENCRYPT, dctx->key, dst, (void*)src,
139 DES3_128_BLOCK_SIZE); 194 DES3_128_BLOCK_SIZE);
140} 195}
141 196
142static void 197static void des3_128_decrypt(void *ctx, u8 *dst, const u8 *src)
143des3_128_decrypt(void *ctx, u8 *dst, const u8 *src)
144{ 198{
145 struct crypt_s390_des3_128_ctx *dctx; 199 struct crypt_s390_des3_128_ctx *dctx = ctx;
146 200
147 dctx = ctx;
148 crypt_s390_km(KM_TDEA_128_DECRYPT, dctx->key, dst, (void*)src, 201 crypt_s390_km(KM_TDEA_128_DECRYPT, dctx->key, dst, (void*)src,
149 DES3_128_BLOCK_SIZE); 202 DES3_128_BLOCK_SIZE);
203}
204
205static unsigned int des3_128_encrypt_ecb(const struct cipher_desc *desc,
206 u8 *out, const u8 *in,
207 unsigned int nbytes)
208{
209 struct crypt_s390_des3_128_ctx *sctx = crypto_tfm_ctx(desc->tfm);
210 int ret;
211
212 /* only use complete blocks */
213 nbytes &= ~(DES3_128_BLOCK_SIZE - 1);
214 ret = crypt_s390_km(KM_TDEA_128_ENCRYPT, sctx->key, out, in, nbytes);
215 BUG_ON((ret < 0) || (ret != nbytes));
216
217 return nbytes;
218}
219
220static unsigned int des3_128_decrypt_ecb(const struct cipher_desc *desc,
221 u8 *out, const u8 *in,
222 unsigned int nbytes)
223{
224 struct crypt_s390_des3_128_ctx *sctx = crypto_tfm_ctx(desc->tfm);
225 int ret;
226
227 /* only use complete blocks */
228 nbytes &= ~(DES3_128_BLOCK_SIZE - 1);
229 ret = crypt_s390_km(KM_TDEA_128_DECRYPT, sctx->key, out, in, nbytes);
230 BUG_ON((ret < 0) || (ret != nbytes));
231
232 return nbytes;
233}
234
235static unsigned int des3_128_encrypt_cbc(const struct cipher_desc *desc,
236 u8 *out, const u8 *in,
237 unsigned int nbytes)
238{
239 struct crypt_s390_des3_128_ctx *sctx = crypto_tfm_ctx(desc->tfm);
240 int ret;
241
242 /* only use complete blocks */
243 nbytes &= ~(DES3_128_BLOCK_SIZE - 1);
244
245 memcpy(sctx->iv, desc->info, DES3_128_BLOCK_SIZE);
246 ret = crypt_s390_kmc(KMC_TDEA_128_ENCRYPT, &sctx->iv, out, in, nbytes);
247 BUG_ON((ret < 0) || (ret != nbytes));
248
249 memcpy(desc->info, sctx->iv, DES3_128_BLOCK_SIZE);
250 return nbytes;
251}
252
253static unsigned int des3_128_decrypt_cbc(const struct cipher_desc *desc,
254 u8 *out, const u8 *in,
255 unsigned int nbytes)
256{
257 struct crypt_s390_des3_128_ctx *sctx = crypto_tfm_ctx(desc->tfm);
258 int ret;
259
260 /* only use complete blocks */
261 nbytes &= ~(DES3_128_BLOCK_SIZE - 1);
262
263 memcpy(&sctx->iv, desc->info, DES3_128_BLOCK_SIZE);
264 ret = crypt_s390_kmc(KMC_TDEA_128_DECRYPT, &sctx->iv, out, in, nbytes);
265 BUG_ON((ret < 0) || (ret != nbytes));
266
267 return nbytes;
150} 268}
151 269
152static struct crypto_alg des3_128_alg = { 270static struct crypto_alg des3_128_alg = {
@@ -156,12 +274,19 @@ static struct crypto_alg des3_128_alg = {
156 .cra_ctxsize = sizeof(struct crypt_s390_des3_128_ctx), 274 .cra_ctxsize = sizeof(struct crypt_s390_des3_128_ctx),
157 .cra_module = THIS_MODULE, 275 .cra_module = THIS_MODULE,
158 .cra_list = LIST_HEAD_INIT(des3_128_alg.cra_list), 276 .cra_list = LIST_HEAD_INIT(des3_128_alg.cra_list),
159 .cra_u = { .cipher = { 277 .cra_u = {
160 .cia_min_keysize = DES3_128_KEY_SIZE, 278 .cipher = {
161 .cia_max_keysize = DES3_128_KEY_SIZE, 279 .cia_min_keysize = DES3_128_KEY_SIZE,
162 .cia_setkey = des3_128_setkey, 280 .cia_max_keysize = DES3_128_KEY_SIZE,
163 .cia_encrypt = des3_128_encrypt, 281 .cia_setkey = des3_128_setkey,
164 .cia_decrypt = des3_128_decrypt } } 282 .cia_encrypt = des3_128_encrypt,
283 .cia_decrypt = des3_128_decrypt,
284 .cia_encrypt_ecb = des3_128_encrypt_ecb,
285 .cia_decrypt_ecb = des3_128_decrypt_ecb,
286 .cia_encrypt_cbc = des3_128_encrypt_cbc,
287 .cia_decrypt_cbc = des3_128_decrypt_cbc,
288 }
289 }
165}; 290};
166 291
167/* 292/*
@@ -177,50 +302,108 @@ static struct crypto_alg des3_128_alg = {
177 * property. 302 * property.
178 * 303 *
179 */ 304 */
180static int 305static int des3_192_setkey(void *ctx, const u8 *key, unsigned int keylen,
181des3_192_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) 306 u32 *flags)
182{ 307{
183 int i, ret; 308 int i, ret;
184 struct crypt_s390_des3_192_ctx *dctx; 309 struct crypt_s390_des3_192_ctx *dctx = ctx;
185 const u8* temp_key; 310 const u8* temp_key = key;
186 311
187 dctx = ctx;
188 temp_key = key;
189 if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE) && 312 if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE) &&
190 memcmp(&key[DES_KEY_SIZE], &key[DES_KEY_SIZE * 2], 313 memcmp(&key[DES_KEY_SIZE], &key[DES_KEY_SIZE * 2],
191 DES_KEY_SIZE))) { 314 DES_KEY_SIZE))) {
192 315
193 *flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED; 316 *flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED;
194 return -EINVAL; 317 return -EINVAL;
195 } 318 }
196 for (i = 0; i < 3; i++, temp_key += DES_KEY_SIZE) { 319 for (i = 0; i < 3; i++, temp_key += DES_KEY_SIZE) {
197 ret = crypto_des_check_key(temp_key, DES_KEY_SIZE, flags); 320 ret = crypto_des_check_key(temp_key, DES_KEY_SIZE, flags);
198 if (ret < 0){ 321 if (ret < 0)
199 return ret; 322 return ret;
200 }
201 } 323 }
202 memcpy(dctx->key, key, keylen); 324 memcpy(dctx->key, key, keylen);
203 return 0; 325 return 0;
204} 326}
205 327
206static void 328static void des3_192_encrypt(void *ctx, u8 *dst, const u8 *src)
207des3_192_encrypt(void *ctx, u8 *dst, const u8 *src)
208{ 329{
209 struct crypt_s390_des3_192_ctx *dctx; 330 struct crypt_s390_des3_192_ctx *dctx = ctx;
210 331
211 dctx = ctx;
212 crypt_s390_km(KM_TDEA_192_ENCRYPT, dctx->key, dst, (void*)src, 332 crypt_s390_km(KM_TDEA_192_ENCRYPT, dctx->key, dst, (void*)src,
213 DES3_192_BLOCK_SIZE); 333 DES3_192_BLOCK_SIZE);
214} 334}
215 335
216static void 336static void des3_192_decrypt(void *ctx, u8 *dst, const u8 *src)
217des3_192_decrypt(void *ctx, u8 *dst, const u8 *src)
218{ 337{
219 struct crypt_s390_des3_192_ctx *dctx; 338 struct crypt_s390_des3_192_ctx *dctx = ctx;
220 339
221 dctx = ctx;
222 crypt_s390_km(KM_TDEA_192_DECRYPT, dctx->key, dst, (void*)src, 340 crypt_s390_km(KM_TDEA_192_DECRYPT, dctx->key, dst, (void*)src,
223 DES3_192_BLOCK_SIZE); 341 DES3_192_BLOCK_SIZE);
342}
343
344static unsigned int des3_192_encrypt_ecb(const struct cipher_desc *desc,
345 u8 *out, const u8 *in,
346 unsigned int nbytes)
347{
348 struct crypt_s390_des3_192_ctx *sctx = crypto_tfm_ctx(desc->tfm);
349 int ret;
350
351 /* only use complete blocks */
352 nbytes &= ~(DES3_192_BLOCK_SIZE - 1);
353 ret = crypt_s390_km(KM_TDEA_192_ENCRYPT, sctx->key, out, in, nbytes);
354 BUG_ON((ret < 0) || (ret != nbytes));
355
356 return nbytes;
357}
358
359static unsigned int des3_192_decrypt_ecb(const struct cipher_desc *desc,
360 u8 *out, const u8 *in,
361 unsigned int nbytes)
362{
363 struct crypt_s390_des3_192_ctx *sctx = crypto_tfm_ctx(desc->tfm);
364 int ret;
365
366 /* only use complete blocks */
367 nbytes &= ~(DES3_192_BLOCK_SIZE - 1);
368 ret = crypt_s390_km(KM_TDEA_192_DECRYPT, sctx->key, out, in, nbytes);
369 BUG_ON((ret < 0) || (ret != nbytes));
370
371 return nbytes;
372}
373
374static unsigned int des3_192_encrypt_cbc(const struct cipher_desc *desc,
375 u8 *out, const u8 *in,
376 unsigned int nbytes)
377{
378 struct crypt_s390_des3_192_ctx *sctx = crypto_tfm_ctx(desc->tfm);
379 int ret;
380
381 /* only use complete blocks */
382 nbytes &= ~(DES3_192_BLOCK_SIZE - 1);
383
384 memcpy(sctx->iv, desc->info, DES3_192_BLOCK_SIZE);
385 ret = crypt_s390_kmc(KMC_TDEA_192_ENCRYPT, &sctx->iv, out, in, nbytes);
386 BUG_ON((ret < 0) || (ret != nbytes));
387
388 memcpy(desc->info, sctx->iv, DES3_192_BLOCK_SIZE);
389 return nbytes;
390}
391
392static unsigned int des3_192_decrypt_cbc(const struct cipher_desc *desc,
393 u8 *out, const u8 *in,
394 unsigned int nbytes)
395{
396 struct crypt_s390_des3_192_ctx *sctx = crypto_tfm_ctx(desc->tfm);
397 int ret;
398
399 /* only use complete blocks */
400 nbytes &= ~(DES3_192_BLOCK_SIZE - 1);
401
402 memcpy(&sctx->iv, desc->info, DES3_192_BLOCK_SIZE);
403 ret = crypt_s390_kmc(KMC_TDEA_192_DECRYPT, &sctx->iv, out, in, nbytes);
404 BUG_ON((ret < 0) || (ret != nbytes));
405
406 return nbytes;
224} 407}
225 408
226static struct crypto_alg des3_192_alg = { 409static struct crypto_alg des3_192_alg = {
@@ -230,44 +413,43 @@ static struct crypto_alg des3_192_alg = {
230 .cra_ctxsize = sizeof(struct crypt_s390_des3_192_ctx), 413 .cra_ctxsize = sizeof(struct crypt_s390_des3_192_ctx),
231 .cra_module = THIS_MODULE, 414 .cra_module = THIS_MODULE,
232 .cra_list = LIST_HEAD_INIT(des3_192_alg.cra_list), 415 .cra_list = LIST_HEAD_INIT(des3_192_alg.cra_list),
233 .cra_u = { .cipher = { 416 .cra_u = {
234 .cia_min_keysize = DES3_192_KEY_SIZE, 417 .cipher = {
235 .cia_max_keysize = DES3_192_KEY_SIZE, 418 .cia_min_keysize = DES3_192_KEY_SIZE,
236 .cia_setkey = des3_192_setkey, 419 .cia_max_keysize = DES3_192_KEY_SIZE,
237 .cia_encrypt = des3_192_encrypt, 420 .cia_setkey = des3_192_setkey,
238 .cia_decrypt = des3_192_decrypt } } 421 .cia_encrypt = des3_192_encrypt,
422 .cia_decrypt = des3_192_decrypt,
423 .cia_encrypt_ecb = des3_192_encrypt_ecb,
424 .cia_decrypt_ecb = des3_192_decrypt_ecb,
425 .cia_encrypt_cbc = des3_192_encrypt_cbc,
426 .cia_decrypt_cbc = des3_192_decrypt_cbc,
427 }
428 }
239}; 429};
240 430
241 431static int init(void)
242
243static int
244init(void)
245{ 432{
246 int ret; 433 int ret = 0;
247 434
248 if (!crypt_s390_func_available(KM_DEA_ENCRYPT) || 435 if (!crypt_s390_func_available(KM_DEA_ENCRYPT) ||
249 !crypt_s390_func_available(KM_TDEA_128_ENCRYPT) || 436 !crypt_s390_func_available(KM_TDEA_128_ENCRYPT) ||
250 !crypt_s390_func_available(KM_TDEA_192_ENCRYPT)){ 437 !crypt_s390_func_available(KM_TDEA_192_ENCRYPT))
251 return -ENOSYS; 438 return -ENOSYS;
252 }
253 439
254 ret = 0; 440 ret |= (crypto_register_alg(&des_alg) == 0) ? 0:1;
255 ret |= (crypto_register_alg(&des_alg) == 0)? 0:1; 441 ret |= (crypto_register_alg(&des3_128_alg) == 0) ? 0:2;
256 ret |= (crypto_register_alg(&des3_128_alg) == 0)? 0:2; 442 ret |= (crypto_register_alg(&des3_192_alg) == 0) ? 0:4;
257 ret |= (crypto_register_alg(&des3_192_alg) == 0)? 0:4; 443 if (ret) {
258 if (ret){
259 crypto_unregister_alg(&des3_192_alg); 444 crypto_unregister_alg(&des3_192_alg);
260 crypto_unregister_alg(&des3_128_alg); 445 crypto_unregister_alg(&des3_128_alg);
261 crypto_unregister_alg(&des_alg); 446 crypto_unregister_alg(&des_alg);
262 return -EEXIST; 447 return -EEXIST;
263 } 448 }
264
265 printk(KERN_INFO "crypt_s390: des_s390 loaded.\n");
266 return 0; 449 return 0;
267} 450}
268 451
269static void __exit 452static void __exit fini(void)
270fini(void)
271{ 453{
272 crypto_unregister_alg(&des3_192_alg); 454 crypto_unregister_alg(&des3_192_alg);
273 crypto_unregister_alg(&des3_128_alg); 455 crypto_unregister_alg(&des3_128_alg);
diff --git a/arch/s390/crypto/sha256_s390.c b/arch/s390/crypto/sha256_s390.c
index b75bdbd476c7..1ec5e92b3454 100644
--- a/arch/s390/crypto/sha256_s390.c
+++ b/arch/s390/crypto/sha256_s390.c
@@ -51,6 +51,7 @@ static void sha256_update(void *ctx, const u8 *data, unsigned int len)
51{ 51{
52 struct s390_sha256_ctx *sctx = ctx; 52 struct s390_sha256_ctx *sctx = ctx;
53 unsigned int index; 53 unsigned int index;
54 int ret;
54 55
55 /* how much is already in the buffer? */ 56 /* how much is already in the buffer? */
56 index = sctx->count / 8 & 0x3f; 57 index = sctx->count / 8 & 0x3f;
@@ -58,15 +59,29 @@ static void sha256_update(void *ctx, const u8 *data, unsigned int len)
58 /* update message bit length */ 59 /* update message bit length */
59 sctx->count += len * 8; 60 sctx->count += len * 8;
60 61
61 /* process one block */ 62 if ((index + len) < SHA256_BLOCK_SIZE)
62 if ((index + len) >= SHA256_BLOCK_SIZE) { 63 goto store;
64
65 /* process one stored block */
66 if (index) {
63 memcpy(sctx->buf + index, data, SHA256_BLOCK_SIZE - index); 67 memcpy(sctx->buf + index, data, SHA256_BLOCK_SIZE - index);
64 crypt_s390_kimd(KIMD_SHA_256, sctx->state, sctx->buf, 68 ret = crypt_s390_kimd(KIMD_SHA_256, sctx->state, sctx->buf,
65 SHA256_BLOCK_SIZE); 69 SHA256_BLOCK_SIZE);
70 BUG_ON(ret != SHA256_BLOCK_SIZE);
66 data += SHA256_BLOCK_SIZE - index; 71 data += SHA256_BLOCK_SIZE - index;
67 len -= SHA256_BLOCK_SIZE - index; 72 len -= SHA256_BLOCK_SIZE - index;
68 } 73 }
69 74
75 /* process as many blocks as possible */
76 if (len >= SHA256_BLOCK_SIZE) {
77 ret = crypt_s390_kimd(KIMD_SHA_256, sctx->state, data,
78 len & ~(SHA256_BLOCK_SIZE - 1));
79 BUG_ON(ret != (len & ~(SHA256_BLOCK_SIZE - 1)));
80 data += ret;
81 len -= ret;
82 }
83
84store:
70 /* anything left? */ 85 /* anything left? */
71 if (len) 86 if (len)
72 memcpy(sctx->buf + index , data, len); 87 memcpy(sctx->buf + index , data, len);
@@ -119,9 +134,9 @@ static struct crypto_alg alg = {
119 .cra_list = LIST_HEAD_INIT(alg.cra_list), 134 .cra_list = LIST_HEAD_INIT(alg.cra_list),
120 .cra_u = { .digest = { 135 .cra_u = { .digest = {
121 .dia_digestsize = SHA256_DIGEST_SIZE, 136 .dia_digestsize = SHA256_DIGEST_SIZE,
122 .dia_init = sha256_init, 137 .dia_init = sha256_init,
123 .dia_update = sha256_update, 138 .dia_update = sha256_update,
124 .dia_final = sha256_final } } 139 .dia_final = sha256_final } }
125}; 140};
126 141
127static int init(void) 142static int init(void)
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 2ff90a1a1056..008c74526fd3 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -58,10 +58,18 @@ asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
58 */ 58 */
59unsigned long thread_saved_pc(struct task_struct *tsk) 59unsigned long thread_saved_pc(struct task_struct *tsk)
60{ 60{
61 struct stack_frame *sf; 61 struct stack_frame *sf, *low, *high;
62 62
63 sf = (struct stack_frame *) tsk->thread.ksp; 63 if (!tsk || !task_stack_page(tsk))
64 sf = (struct stack_frame *) sf->back_chain; 64 return 0;
65 low = task_stack_page(tsk);
66 high = (struct stack_frame *) task_pt_regs(tsk);
67 sf = (struct stack_frame *) (tsk->thread.ksp & PSW_ADDR_INSN);
68 if (sf <= low || sf > high)
69 return 0;
70 sf = (struct stack_frame *) (sf->back_chain & PSW_ADDR_INSN);
71 if (sf <= low || sf > high)
72 return 0;
65 return sf->gprs[8]; 73 return sf->gprs[8];
66} 74}
67 75
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index b03847d100d9..de8784267473 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -268,7 +268,7 @@ static void do_machine_restart_nonsmp(char * __unused)
268 reipl_diag(); 268 reipl_diag();
269 269
270 if (MACHINE_IS_VM) 270 if (MACHINE_IS_VM)
271 cpcmd ("IPL", NULL, 0); 271 cpcmd ("IPL", NULL, 0, NULL);
272 else 272 else
273 reipl (0x10000 | S390_lowcore.ipl_device); 273 reipl (0x10000 | S390_lowcore.ipl_device);
274} 274}
@@ -276,14 +276,14 @@ static void do_machine_restart_nonsmp(char * __unused)
276static void do_machine_halt_nonsmp(void) 276static void do_machine_halt_nonsmp(void)
277{ 277{
278 if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0) 278 if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0)
279 cpcmd(vmhalt_cmd, NULL, 0); 279 cpcmd(vmhalt_cmd, NULL, 0, NULL);
280 signal_processor(smp_processor_id(), sigp_stop_and_store_status); 280 signal_processor(smp_processor_id(), sigp_stop_and_store_status);
281} 281}
282 282
283static void do_machine_power_off_nonsmp(void) 283static void do_machine_power_off_nonsmp(void)
284{ 284{
285 if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0) 285 if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0)
286 cpcmd(vmpoff_cmd, NULL, 0); 286 cpcmd(vmpoff_cmd, NULL, 0, NULL);
287 signal_processor(smp_processor_id(), sigp_stop_and_store_status); 287 signal_processor(smp_processor_id(), sigp_stop_and_store_status);
288} 288}
289 289
@@ -315,6 +315,11 @@ void machine_power_off(void)
315 _machine_power_off(); 315 _machine_power_off();
316} 316}
317 317
318/*
319 * Dummy power off function.
320 */
321void (*pm_power_off)(void) = machine_power_off;
322
318static void __init 323static void __init
319add_memory_hole(unsigned long start, unsigned long end) 324add_memory_hole(unsigned long start, unsigned long end)
320{ 325{
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index b0d8ca8e5eeb..7c0fe152a111 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -214,7 +214,7 @@ void account_ticks(struct pt_regs *regs)
214#endif 214#endif
215 215
216#ifdef CONFIG_VIRT_CPU_ACCOUNTING 216#ifdef CONFIG_VIRT_CPU_ACCOUNTING
217 account_user_vtime(current); 217 account_tick_vtime(current);
218#else 218#else
219 while (ticks--) 219 while (ticks--)
220 update_process_times(user_mode(regs)); 220 update_process_times(user_mode(regs));
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index 22a895ecb7a4..dfe6f0856617 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -32,7 +32,7 @@ DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer);
32 * Update process times based on virtual cpu times stored by entry.S 32 * Update process times based on virtual cpu times stored by entry.S
33 * to the lowcore fields user_timer, system_timer & steal_clock. 33 * to the lowcore fields user_timer, system_timer & steal_clock.
34 */ 34 */
35void account_user_vtime(struct task_struct *tsk) 35void account_tick_vtime(struct task_struct *tsk)
36{ 36{
37 cputime_t cputime; 37 cputime_t cputime;
38 __u64 timer, clock; 38 __u64 timer, clock;
@@ -76,6 +76,31 @@ void account_user_vtime(struct task_struct *tsk)
76 * Update process times based on virtual cpu times stored by entry.S 76 * Update process times based on virtual cpu times stored by entry.S
77 * to the lowcore fields user_timer, system_timer & steal_clock. 77 * to the lowcore fields user_timer, system_timer & steal_clock.
78 */ 78 */
79void account_vtime(struct task_struct *tsk)
80{
81 cputime_t cputime;
82 __u64 timer;
83
84 timer = S390_lowcore.last_update_timer;
85 asm volatile (" STPT %0" /* Store current cpu timer value */
86 : "=m" (S390_lowcore.last_update_timer) );
87 S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer;
88
89 cputime = S390_lowcore.user_timer >> 12;
90 S390_lowcore.user_timer -= cputime << 12;
91 S390_lowcore.steal_clock -= cputime << 12;
92 account_user_time(tsk, cputime);
93
94 cputime = S390_lowcore.system_timer >> 12;
95 S390_lowcore.system_timer -= cputime << 12;
96 S390_lowcore.steal_clock -= cputime << 12;
97 account_system_time(tsk, 0, cputime);
98}
99
100/*
101 * Update process times based on virtual cpu times stored by entry.S
102 * to the lowcore fields user_timer, system_timer & steal_clock.
103 */
79void account_system_vtime(struct task_struct *tsk) 104void account_system_vtime(struct task_struct *tsk)
80{ 105{
81 cputime_t cputime; 106 cputime_t cputime;
diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile
index d9b97b3c597f..f20b51ff1d86 100644
--- a/arch/s390/lib/Makefile
+++ b/arch/s390/lib/Makefile
@@ -4,5 +4,6 @@
4 4
5EXTRA_AFLAGS := -traditional 5EXTRA_AFLAGS := -traditional
6 6
7lib-y += delay.o string.o spinlock.o 7lib-y += delay.o string.o
8lib-y += $(if $(CONFIG_64BIT),uaccess64.o,uaccess.o) 8lib-y += $(if $(CONFIG_64BIT),uaccess64.o,uaccess.o)
9lib-$(CONFIG_SMP) += spinlock.o \ No newline at end of file
diff --git a/arch/s390/lib/spinlock.c b/arch/s390/lib/spinlock.c
index 68d79c502081..60f80a4eed4e 100644
--- a/arch/s390/lib/spinlock.c
+++ b/arch/s390/lib/spinlock.c
@@ -13,7 +13,6 @@
13#include <linux/init.h> 13#include <linux/init.h>
14#include <asm/io.h> 14#include <asm/io.h>
15 15
16atomic_t spin_retry_counter;
17int spin_retry = 1000; 16int spin_retry = 1000;
18 17
19/** 18/**
@@ -45,7 +44,6 @@ _raw_spin_lock_wait(raw_spinlock_t *lp, unsigned int pc)
45 _diag44(); 44 _diag44();
46 count = spin_retry; 45 count = spin_retry;
47 } 46 }
48 atomic_inc(&spin_retry_counter);
49 if (_raw_compare_and_swap(&lp->lock, 0, pc) == 0) 47 if (_raw_compare_and_swap(&lp->lock, 0, pc) == 0)
50 return; 48 return;
51 } 49 }
@@ -58,7 +56,6 @@ _raw_spin_trylock_retry(raw_spinlock_t *lp, unsigned int pc)
58 int count = spin_retry; 56 int count = spin_retry;
59 57
60 while (count-- > 0) { 58 while (count-- > 0) {
61 atomic_inc(&spin_retry_counter);
62 if (_raw_compare_and_swap(&lp->lock, 0, pc) == 0) 59 if (_raw_compare_and_swap(&lp->lock, 0, pc) == 0)
63 return 1; 60 return 1;
64 } 61 }
@@ -77,7 +74,6 @@ _raw_read_lock_wait(raw_rwlock_t *rw)
77 _diag44(); 74 _diag44();
78 count = spin_retry; 75 count = spin_retry;
79 } 76 }
80 atomic_inc(&spin_retry_counter);
81 old = rw->lock & 0x7fffffffU; 77 old = rw->lock & 0x7fffffffU;
82 if (_raw_compare_and_swap(&rw->lock, old, old + 1) == old) 78 if (_raw_compare_and_swap(&rw->lock, old, old + 1) == old)
83 return; 79 return;
@@ -92,7 +88,6 @@ _raw_read_trylock_retry(raw_rwlock_t *rw)
92 int count = spin_retry; 88 int count = spin_retry;
93 89
94 while (count-- > 0) { 90 while (count-- > 0) {
95 atomic_inc(&spin_retry_counter);
96 old = rw->lock & 0x7fffffffU; 91 old = rw->lock & 0x7fffffffU;
97 if (_raw_compare_and_swap(&rw->lock, old, old + 1) == old) 92 if (_raw_compare_and_swap(&rw->lock, old, old + 1) == old)
98 return 1; 93 return 1;
@@ -111,7 +106,6 @@ _raw_write_lock_wait(raw_rwlock_t *rw)
111 _diag44(); 106 _diag44();
112 count = spin_retry; 107 count = spin_retry;
113 } 108 }
114 atomic_inc(&spin_retry_counter);
115 if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0) 109 if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0)
116 return; 110 return;
117 } 111 }
@@ -124,7 +118,6 @@ _raw_write_trylock_retry(raw_rwlock_t *rw)
124 int count = spin_retry; 118 int count = spin_retry;
125 119
126 while (count-- > 0) { 120 while (count-- > 0) {
127 atomic_inc(&spin_retry_counter);
128 if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0) 121 if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0)
129 return 1; 122 return 1;
130 } 123 }
diff --git a/arch/sh/kernel/cpu/bus.c b/arch/sh/kernel/cpu/bus.c
index d4fee2a79373..3278d234bb1b 100644
--- a/arch/sh/kernel/cpu/bus.c
+++ b/arch/sh/kernel/cpu/bus.c
@@ -53,21 +53,6 @@ static int sh_bus_resume(struct device *dev)
53 return 0; 53 return 0;
54} 54}
55 55
56static struct device sh_bus_devices[SH_NR_BUSES] = {
57 {
58 .bus_id = SH_BUS_NAME_VIRT,
59 },
60};
61
62struct bus_type sh_bus_types[SH_NR_BUSES] = {
63 {
64 .name = SH_BUS_NAME_VIRT,
65 .match = sh_bus_match,
66 .suspend = sh_bus_suspend,
67 .resume = sh_bus_resume,
68 },
69};
70
71static int sh_device_probe(struct device *dev) 56static int sh_device_probe(struct device *dev)
72{ 57{
73 struct sh_dev *shdev = to_sh_dev(dev); 58 struct sh_dev *shdev = to_sh_dev(dev);
@@ -90,6 +75,23 @@ static int sh_device_remove(struct device *dev)
90 return 0; 75 return 0;
91} 76}
92 77
78static struct device sh_bus_devices[SH_NR_BUSES] = {
79 {
80 .bus_id = SH_BUS_NAME_VIRT,
81 },
82};
83
84struct bus_type sh_bus_types[SH_NR_BUSES] = {
85 {
86 .name = SH_BUS_NAME_VIRT,
87 .match = sh_bus_match,
88 .probe = sh_bus_probe,
89 .remove = sh_bus_remove,
90 .suspend = sh_bus_suspend,
91 .resume = sh_bus_resume,
92 },
93};
94
93int sh_device_register(struct sh_dev *dev) 95int sh_device_register(struct sh_dev *dev)
94{ 96{
95 if (!dev) 97 if (!dev)
@@ -133,8 +135,6 @@ int sh_driver_register(struct sh_driver *drv)
133 return -EINVAL; 135 return -EINVAL;
134 } 136 }
135 137
136 drv->drv.probe = sh_device_probe;
137 drv->drv.remove = sh_device_remove;
138 drv->drv.bus = &sh_bus_types[drv->bus_id]; 138 drv->drv.bus = &sh_bus_types[drv->bus_id];
139 139
140 return driver_register(&drv->drv); 140 return driver_register(&drv->drv);
diff --git a/arch/um/Makefile b/arch/um/Makefile
index 322972fd064e..45435ff589c1 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -67,7 +67,8 @@ USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) $(ARCH_INCLUDE) \
67# in CFLAGS. Otherwise, it would cause ld to complain about the two different 67# in CFLAGS. Otherwise, it would cause ld to complain about the two different
68# errnos. 68# errnos.
69 69
70CFLAGS += -Derrno=kernel_errno -Dsigprocmask=kernel_sigprocmask 70CFLAGS += -Derrno=kernel_errno -Dsigprocmask=kernel_sigprocmask \
71 -Dmktime=kernel_mktime
71CFLAGS += $(call cc-option,-fno-unit-at-a-time,) 72CFLAGS += $(call cc-option,-fno-unit-at-a-time,)
72 73
73include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH) 74include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH)
diff --git a/block/genhd.c b/block/genhd.c
index f1ed83f3f083..db57546a709d 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -38,34 +38,100 @@ static inline int major_to_index(int major)
38 return major % MAX_PROBE_HASH; 38 return major % MAX_PROBE_HASH;
39} 39}
40 40
41#ifdef CONFIG_PROC_FS 41struct blkdev_info {
42/* get block device names in somewhat random order */ 42 int index;
43int get_blkdev_list(char *p, int used) 43 struct blk_major_name *bd;
44};
45
46/*
47 * iterate over a list of blkdev_info structures. allows
48 * the major_names array to be iterated over from outside this file
49 * must be called with the block_subsys_sem held
50 */
51void *get_next_blkdev(void *dev)
52{
53 struct blkdev_info *info;
54
55 if (dev == NULL) {
56 info = kmalloc(sizeof(*info), GFP_KERNEL);
57 if (!info)
58 goto out;
59 info->index=0;
60 info->bd = major_names[info->index];
61 if (info->bd)
62 goto out;
63 } else {
64 info = dev;
65 }
66
67 while (info->index < ARRAY_SIZE(major_names)) {
68 if (info->bd)
69 info->bd = info->bd->next;
70 if (info->bd)
71 goto out;
72 /*
73 * No devices on this chain, move to the next
74 */
75 info->index++;
76 info->bd = (info->index < ARRAY_SIZE(major_names)) ?
77 major_names[info->index] : NULL;
78 if (info->bd)
79 goto out;
80 }
81
82out:
83 return info;
84}
85
86void *acquire_blkdev_list(void)
87{
88 down(&block_subsys_sem);
89 return get_next_blkdev(NULL);
90}
91
92void release_blkdev_list(void *dev)
93{
94 up(&block_subsys_sem);
95 kfree(dev);
96}
97
98
99/*
100 * Count the number of records in the blkdev_list.
101 * must be called with the block_subsys_sem held
102 */
103int count_blkdev_list(void)
44{ 104{
45 struct blk_major_name *n; 105 struct blk_major_name *n;
46 int i, len; 106 int i, count;
47 107
48 len = snprintf(p, (PAGE_SIZE-used), "\nBlock devices:\n"); 108 count = 0;
49 109
50 down(&block_subsys_sem);
51 for (i = 0; i < ARRAY_SIZE(major_names); i++) { 110 for (i = 0; i < ARRAY_SIZE(major_names); i++) {
52 for (n = major_names[i]; n; n = n->next) { 111 for (n = major_names[i]; n; n = n->next)
53 /* 112 count++;
54 * If the curent string plus the 5 extra characters
55 * in the line would run us off the page, then we're done
56 */
57 if ((len + used + strlen(n->name) + 5) >= PAGE_SIZE)
58 goto page_full;
59 len += sprintf(p+len, "%3d %s\n",
60 n->major, n->name);
61 }
62 } 113 }
63page_full:
64 up(&block_subsys_sem);
65 114
66 return len; 115 return count;
67} 116}
68#endif 117
118/*
119 * extract the major and name values from a blkdev_info struct
120 * passed in as a void to *dev. Must be called with
121 * block_subsys_sem held
122 */
123int get_blkdev_info(void *dev, int *major, char **name)
124{
125 struct blkdev_info *info = dev;
126
127 if (info->bd == NULL)
128 return 1;
129
130 *major = info->bd->major;
131 *name = info->bd->name;
132 return 0;
133}
134
69 135
70int register_blkdev(unsigned int major, const char *name) 136int register_blkdev(unsigned int major, const char *name)
71{ 137{
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 48f446d3c671..283c089537bc 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -44,6 +44,8 @@ source "drivers/char/Kconfig"
44 44
45source "drivers/i2c/Kconfig" 45source "drivers/i2c/Kconfig"
46 46
47source "drivers/spi/Kconfig"
48
47source "drivers/w1/Kconfig" 49source "drivers/w1/Kconfig"
48 50
49source "drivers/hwmon/Kconfig" 51source "drivers/hwmon/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 7fc3f0f08b29..7c45050ecd03 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -41,6 +41,7 @@ obj-$(CONFIG_FUSION) += message/
41obj-$(CONFIG_IEEE1394) += ieee1394/ 41obj-$(CONFIG_IEEE1394) += ieee1394/
42obj-y += cdrom/ 42obj-y += cdrom/
43obj-$(CONFIG_MTD) += mtd/ 43obj-$(CONFIG_MTD) += mtd/
44obj-$(CONFIG_SPI) += spi/
44obj-$(CONFIG_PCCARD) += pcmcia/ 45obj-$(CONFIG_PCCARD) += pcmcia/
45obj-$(CONFIG_DIO) += dio/ 46obj-$(CONFIG_DIO) += dio/
46obj-$(CONFIG_SBUS) += sbus/ 47obj-$(CONFIG_SBUS) += sbus/
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 7e1a445955bc..3758b558d2b5 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -153,7 +153,7 @@ static int acpi_ec_polling_mode = EC_POLLING;
153 Transaction Management 153 Transaction Management
154 -------------------------------------------------------------------------- */ 154 -------------------------------------------------------------------------- */
155 155
156static inline u32 acpi_ec_read_status(union acpi_ec *ec) 156static u32 acpi_ec_read_status(union acpi_ec *ec)
157{ 157{
158 u32 status = 0; 158 u32 status = 0;
159 159
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 2b905016664d..730a9ce0a14a 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -78,7 +78,13 @@ int driver_probe_device(struct device_driver * drv, struct device * dev)
78 pr_debug("%s: Matched Device %s with Driver %s\n", 78 pr_debug("%s: Matched Device %s with Driver %s\n",
79 drv->bus->name, dev->bus_id, drv->name); 79 drv->bus->name, dev->bus_id, drv->name);
80 dev->driver = drv; 80 dev->driver = drv;
81 if (drv->probe) { 81 if (dev->bus->probe) {
82 ret = dev->bus->probe(dev);
83 if (ret) {
84 dev->driver = NULL;
85 goto ProbeFailed;
86 }
87 } else if (drv->probe) {
82 ret = drv->probe(dev); 88 ret = drv->probe(dev);
83 if (ret) { 89 if (ret) {
84 dev->driver = NULL; 90 dev->driver = NULL;
@@ -203,7 +209,9 @@ static void __device_release_driver(struct device * dev)
203 sysfs_remove_link(&dev->kobj, "driver"); 209 sysfs_remove_link(&dev->kobj, "driver");
204 klist_remove(&dev->knode_driver); 210 klist_remove(&dev->knode_driver);
205 211
206 if (drv->remove) 212 if (dev->bus->remove)
213 dev->bus->remove(dev);
214 else if (drv->remove)
207 drv->remove(dev); 215 drv->remove(dev);
208 dev->driver = NULL; 216 dev->driver = NULL;
209 put_driver(drv); 217 put_driver(drv);
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 161f3a390d90..b400314e1c62 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -171,6 +171,11 @@ static void klist_devices_put(struct klist_node *n)
171 */ 171 */
172int driver_register(struct device_driver * drv) 172int driver_register(struct device_driver * drv)
173{ 173{
174 if ((drv->bus->probe && drv->probe) ||
175 (drv->bus->remove && drv->remove) ||
176 (drv->bus->shutdown && drv->shutdown)) {
177 printk(KERN_WARNING "Driver '%s' needs updating - please use bus_type methods\n", drv->name);
178 }
174 klist_init(&drv->klist_devices, klist_devices_get, klist_devices_put); 179 klist_init(&drv->klist_devices, klist_devices_get, klist_devices_put);
175 init_completion(&drv->unloaded); 180 init_completion(&drv->unloaded);
176 return bus_add_driver(drv); 181 return bus_add_driver(drv);
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 3d384e3d34de..e97e911ebf7a 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -48,7 +48,7 @@ struct firmware_priv {
48 struct timer_list timeout; 48 struct timer_list timeout;
49}; 49};
50 50
51static inline void 51static void
52fw_load_abort(struct firmware_priv *fw_priv) 52fw_load_abort(struct firmware_priv *fw_priv)
53{ 53{
54 set_bit(FW_STATUS_ABORT, &fw_priv->status); 54 set_bit(FW_STATUS_ABORT, &fw_priv->status);
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 0f81731bdfa8..461554a02517 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -327,7 +327,7 @@ EXPORT_SYMBOL_GPL(platform_device_register);
327 * @pdev: platform device we're unregistering 327 * @pdev: platform device we're unregistering
328 * 328 *
329 * Unregistration is done in 2 steps. Fisrt we release all resources 329 * Unregistration is done in 2 steps. Fisrt we release all resources
330 * and remove it from the sybsystem, then we drop reference count by 330 * and remove it from the subsystem, then we drop reference count by
331 * calling platform_device_put(). 331 * calling platform_device_put().
332 */ 332 */
333void platform_device_unregister(struct platform_device * pdev) 333void platform_device_unregister(struct platform_device * pdev)
diff --git a/drivers/base/power/shutdown.c b/drivers/base/power/shutdown.c
index f50a08be424b..c2475f3134ea 100644
--- a/drivers/base/power/shutdown.c
+++ b/drivers/base/power/shutdown.c
@@ -35,12 +35,15 @@ extern int sysdev_shutdown(void);
35 */ 35 */
36void device_shutdown(void) 36void device_shutdown(void)
37{ 37{
38 struct device * dev; 38 struct device * dev, *devn;
39 39
40 down_write(&devices_subsys.rwsem); 40 down_write(&devices_subsys.rwsem);
41 list_for_each_entry_reverse(dev, &devices_subsys.kset.list, 41 list_for_each_entry_safe_reverse(dev, devn, &devices_subsys.kset.list,
42 kobj.entry) { 42 kobj.entry) {
43 if (dev->driver && dev->driver->shutdown) { 43 if (dev->bus && dev->bus->shutdown) {
44 dev_dbg(dev, "shutdown\n");
45 dev->bus->shutdown(dev);
46 } else if (dev->driver && dev->driver->shutdown) {
44 dev_dbg(dev, "shutdown\n"); 47 dev_dbg(dev, "shutdown\n");
45 dev->driver->shutdown(dev); 48 dev->driver->shutdown(dev);
46 } 49 }
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 864729046e22..5f6d1a5cce11 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -294,7 +294,7 @@ fail:
294 * This helper just factors out common code between do_lo_send_direct_write() 294 * This helper just factors out common code between do_lo_send_direct_write()
295 * and do_lo_send_write(). 295 * and do_lo_send_write().
296 */ 296 */
297static inline int __do_lo_send_write(struct file *file, 297static int __do_lo_send_write(struct file *file,
298 u8 __user *buf, const int len, loff_t pos) 298 u8 __user *buf, const int len, loff_t pos)
299{ 299{
300 ssize_t bw; 300 ssize_t bw;
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 51b7a5c5b77a..93affeeef7bd 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -247,7 +247,7 @@ static inline struct pkt_rb_node *pkt_rbtree_next(struct pkt_rb_node *node)
247 return rb_entry(n, struct pkt_rb_node, rb_node); 247 return rb_entry(n, struct pkt_rb_node, rb_node);
248} 248}
249 249
250static inline void pkt_rbtree_erase(struct pktcdvd_device *pd, struct pkt_rb_node *node) 250static void pkt_rbtree_erase(struct pktcdvd_device *pd, struct pkt_rb_node *node)
251{ 251{
252 rb_erase(&node->rb_node, &pd->bio_queue); 252 rb_erase(&node->rb_node, &pd->bio_queue);
253 mempool_free(node, pd->rb_pool); 253 mempool_free(node, pd->rb_pool);
@@ -315,7 +315,7 @@ static void pkt_rbtree_insert(struct pktcdvd_device *pd, struct pkt_rb_node *nod
315/* 315/*
316 * Add a bio to a single linked list defined by its head and tail pointers. 316 * Add a bio to a single linked list defined by its head and tail pointers.
317 */ 317 */
318static inline void pkt_add_list_last(struct bio *bio, struct bio **list_head, struct bio **list_tail) 318static void pkt_add_list_last(struct bio *bio, struct bio **list_head, struct bio **list_tail)
319{ 319{
320 bio->bi_next = NULL; 320 bio->bi_next = NULL;
321 if (*list_tail) { 321 if (*list_tail) {
diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c
index 8fddfdfd0fbd..7bd4ef904115 100644
--- a/drivers/bluetooth/hci_bcsp.c
+++ b/drivers/bluetooth/hci_bcsp.c
@@ -494,7 +494,7 @@ static inline void bcsp_unslip_one_byte(struct bcsp_struct *bcsp, unsigned char
494 } 494 }
495} 495}
496 496
497static inline void bcsp_complete_rx_pkt(struct hci_uart *hu) 497static void bcsp_complete_rx_pkt(struct hci_uart *hu)
498{ 498{
499 struct bcsp_struct *bcsp = hu->priv; 499 struct bcsp_struct *bcsp = hu->priv;
500 int pass_up; 500 int pass_up;
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index 667a21c72edb..7ac365b5d9ec 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -129,7 +129,6 @@ static struct serial_state rs_table[1];
129 * memory if large numbers of serial ports are open. 129 * memory if large numbers of serial ports are open.
130 */ 130 */
131static unsigned char *tmp_buf; 131static unsigned char *tmp_buf;
132static DECLARE_MUTEX(tmp_buf_sem);
133 132
134#include <asm/uaccess.h> 133#include <asm/uaccess.h>
135 134
diff --git a/drivers/char/drm/r128_state.c b/drivers/char/drm/r128_state.c
index caeecc2c36da..a080cdd6081e 100644
--- a/drivers/char/drm/r128_state.c
+++ b/drivers/char/drm/r128_state.c
@@ -220,7 +220,7 @@ static __inline__ void r128_emit_tex1(drm_r128_private_t * dev_priv)
220 ADVANCE_RING(); 220 ADVANCE_RING();
221} 221}
222 222
223static __inline__ void r128_emit_state(drm_r128_private_t * dev_priv) 223static void r128_emit_state(drm_r128_private_t * dev_priv)
224{ 224{
225 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; 225 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
226 unsigned int dirty = sarea_priv->dirty; 226 unsigned int dirty = sarea_priv->dirty;
diff --git a/drivers/char/esp.c b/drivers/char/esp.c
index e469f641c728..dd5dc8fa490d 100644
--- a/drivers/char/esp.c
+++ b/drivers/char/esp.c
@@ -160,7 +160,6 @@ static void rs_wait_until_sent(struct tty_struct *, int);
160 * memory if large numbers of serial ports are open. 160 * memory if large numbers of serial ports are open.
161 */ 161 */
162static unsigned char *tmp_buf; 162static unsigned char *tmp_buf;
163static DECLARE_MUTEX(tmp_buf_sem);
164 163
165static inline int serial_paranoia_check(struct esp_struct *info, 164static inline int serial_paranoia_check(struct esp_struct *info,
166 char *name, const char *routine) 165 char *name, const char *routine)
diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c
index 204a7302a4a9..e38a5f0e07bb 100644
--- a/drivers/char/generic_serial.c
+++ b/drivers/char/generic_serial.c
@@ -34,7 +34,6 @@
34#define DEBUG 34#define DEBUG
35 35
36static char * tmp_buf; 36static char * tmp_buf;
37static DECLARE_MUTEX(tmp_buf_sem);
38 37
39static int gs_debug; 38static int gs_debug;
40 39
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c
index 050e70ee5920..119e629656b7 100644
--- a/drivers/char/riscom8.c
+++ b/drivers/char/riscom8.c
@@ -82,7 +82,6 @@
82static struct riscom_board * IRQ_to_board[16]; 82static struct riscom_board * IRQ_to_board[16];
83static struct tty_driver *riscom_driver; 83static struct tty_driver *riscom_driver;
84static unsigned char * tmp_buf; 84static unsigned char * tmp_buf;
85static DECLARE_MUTEX(tmp_buf_sem);
86 85
87static unsigned long baud_table[] = { 86static unsigned long baud_table[] = {
88 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 87 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c
index f36342ae8e7e..037c940ac71b 100644
--- a/drivers/char/serial167.c
+++ b/drivers/char/serial167.c
@@ -129,7 +129,6 @@ struct cyclades_port cy_port[] = {
129 * memory if large numbers of serial ports are open. 129 * memory if large numbers of serial ports are open.
130 */ 130 */
131static unsigned char *tmp_buf = 0; 131static unsigned char *tmp_buf = 0;
132DECLARE_MUTEX(tmp_buf_sem);
133 132
134/* 133/*
135 * This is used to look up the divisor speeds and the timeouts 134 * This is used to look up the divisor speeds and the timeouts
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index 0a574bdbce36..5343e9fc6ab7 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -184,7 +184,6 @@ static int sx_poll = HZ;
184 184
185static struct tty_driver *specialix_driver; 185static struct tty_driver *specialix_driver;
186static unsigned char * tmp_buf; 186static unsigned char * tmp_buf;
187static DECLARE_MUTEX(tmp_buf_sem);
188 187
189static unsigned long baud_table[] = { 188static unsigned long baud_table[] = {
190 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 189 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
@@ -2556,8 +2555,6 @@ static int __init specialix_init_module(void)
2556 2555
2557 func_enter(); 2556 func_enter();
2558 2557
2559 init_MUTEX(&tmp_buf_sem); /* Init de the semaphore - pvdl */
2560
2561 if (iobase[0] || iobase[1] || iobase[2] || iobase[3]) { 2558 if (iobase[0] || iobase[1] || iobase[2] || iobase[3]) {
2562 for(i = 0; i < SX_NBOARD; i++) { 2559 for(i = 0; i < SX_NBOARD; i++) {
2563 sx_board[i].base = iobase[i]; 2560 sx_board[i].base = iobase[i];
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index 9f1b466c4f84..ede688a4e141 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -951,7 +951,6 @@ static void* mgsl_get_text_ptr(void)
951 * memory if large numbers of serial ports are open. 951 * memory if large numbers of serial ports are open.
952 */ 952 */
953static unsigned char *tmp_buf; 953static unsigned char *tmp_buf;
954static DECLARE_MUTEX(tmp_buf_sem);
955 954
956static inline int mgsl_paranoia_check(struct mgsl_struct *info, 955static inline int mgsl_paranoia_check(struct mgsl_struct *info,
957 char *name, const char *routine) 956 char *name, const char *routine)
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index a6544790af60..c0dfcf273f0a 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -395,12 +395,38 @@ config MACHZ_WDT
395 To compile this driver as a module, choose M here: the 395 To compile this driver as a module, choose M here: the
396 module will be called machzwd. 396 module will be called machzwd.
397 397
398config SBC_EPX_C3_WATCHDOG
399 tristate "Winsystems SBC EPX-C3 watchdog"
400 depends on WATCHDOG && X86
401 ---help---
402 This is the driver for the built-in watchdog timer on the EPX-C3
403 Single-board computer made by Winsystems, Inc.
404
405 *Note*: This hardware watchdog is not probeable and thus there
406 is no way to know if writing to its IO address will corrupt
407 your system or have any real effect. The only way to be sure
408 that this driver does what you want is to make sure you
409 are runnning it on an EPX-C3 from Winsystems with the watchdog
410 timer at IO address 0x1ee and 0x1ef. It will write to both those
411 IO ports. Basically, the assumption is made that if you compile
412 this driver into your kernel and/or load it as a module, that you
413 know what you are doing and that you are in fact running on an
414 EPX-C3 board!
415
416 To compile this driver as a module, choose M here: the
417 module will be called sbc_epx_c3.
418
419
398# PowerPC Architecture 420# PowerPC Architecture
399 421
400config 8xx_WDT 422config 8xx_WDT
401 tristate "MPC8xx Watchdog Timer" 423 tristate "MPC8xx Watchdog Timer"
402 depends on WATCHDOG && 8xx 424 depends on WATCHDOG && 8xx
403 425
426config 83xx_WDT
427 tristate "MPC83xx Watchdog Timer"
428 depends on WATCHDOG && PPC_83xx
429
404config MV64X60_WDT 430config MV64X60_WDT
405 tristate "MV64X60 (Marvell Discovery) Watchdog Timer" 431 tristate "MV64X60 (Marvell Discovery) Watchdog Timer"
406 depends on WATCHDOG && MV64X60 432 depends on WATCHDOG && MV64X60
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
index cfd0a3987710..36c0b282b8ba 100644
--- a/drivers/char/watchdog/Makefile
+++ b/drivers/char/watchdog/Makefile
@@ -52,9 +52,11 @@ obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o
52obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o 52obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o
53obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o 53obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o
54obj-$(CONFIG_MACHZ_WDT) += machzwd.o 54obj-$(CONFIG_MACHZ_WDT) += machzwd.o
55obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o
55 56
56# PowerPC Architecture 57# PowerPC Architecture
57obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o 58obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o
59obj-$(CONFIG_83xx_WDT) += mpc83xx_wdt.o
58obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o 60obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o
59obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o 61obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o
60 62
diff --git a/drivers/char/watchdog/mpc83xx_wdt.c b/drivers/char/watchdog/mpc83xx_wdt.c
new file mode 100644
index 000000000000..5d6f5061603a
--- /dev/null
+++ b/drivers/char/watchdog/mpc83xx_wdt.c
@@ -0,0 +1,229 @@
1/*
2 * mpc83xx_wdt.c - MPC83xx watchdog userspace interface
3 *
4 * Authors: Dave Updegraff <dave@cray.org>
5 * Kumar Gala <galak@kernel.crashing.org>
6 * Attribution: from 83xx_wst: Florian Schirmer <jolt@tuxbox.org>
7 * ..and from sc520_wdt
8 *
9 * Note: it appears that you can only actually ENABLE or DISABLE the thing
10 * once after POR. Once enabled, you cannot disable, and vice versa.
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version.
16 */
17
18#include <linux/config.h>
19#include <linux/fs.h>
20#include <linux/init.h>
21#include <linux/kernel.h>
22#include <linux/miscdevice.h>
23#include <linux/platform_device.h>
24#include <linux/module.h>
25#include <linux/watchdog.h>
26#include <asm/io.h>
27#include <asm/uaccess.h>
28
29struct mpc83xx_wdt {
30 __be32 res0;
31 __be32 swcrr; /* System watchdog control register */
32#define SWCRR_SWTC 0xFFFF0000 /* Software Watchdog Time Count. */
33#define SWCRR_SWEN 0x00000004 /* Watchdog Enable bit. */
34#define SWCRR_SWRI 0x00000002 /* Software Watchdog Reset/Interrupt Select bit.*/
35#define SWCRR_SWPR 0x00000001 /* Software Watchdog Counter Prescale bit. */
36 __be32 swcnr; /* System watchdog count register */
37 u8 res1[2];
38 __be16 swsrr; /* System watchdog service register */
39 u8 res2[0xF0];
40};
41
42static struct mpc83xx_wdt __iomem *wd_base;
43
44static u16 timeout = 0xffff;
45module_param(timeout, ushort, 0);
46MODULE_PARM_DESC(timeout, "Watchdog timeout in ticks. (0<timeout<65536, default=65535");
47
48static int reset = 1;
49module_param(reset, bool, 0);
50MODULE_PARM_DESC(reset, "Watchdog Interrupt/Reset Mode. 0 = interrupt, 1 = reset");
51
52/*
53 * We always prescale, but if someone really doesn't want to they can set this
54 * to 0
55 */
56static int prescale = 1;
57static unsigned int timeout_sec;
58
59static unsigned long wdt_is_open;
60static spinlock_t wdt_spinlock;
61
62static void mpc83xx_wdt_keepalive(void)
63{
64 /* Ping the WDT */
65 spin_lock(&wdt_spinlock);
66 out_be16(&wd_base->swsrr, 0x556c);
67 out_be16(&wd_base->swsrr, 0xaa39);
68 spin_unlock(&wdt_spinlock);
69}
70
71static ssize_t mpc83xx_wdt_write(struct file *file, const char __user *buf,
72 size_t count, loff_t *ppos)
73{
74 if (count)
75 mpc83xx_wdt_keepalive();
76 return count;
77}
78
79static int mpc83xx_wdt_open(struct inode *inode, struct file *file)
80{
81 u32 tmp = SWCRR_SWEN;
82 if (test_and_set_bit(0, &wdt_is_open))
83 return -EBUSY;
84
85 /* Once we start the watchdog we can't stop it */
86 __module_get(THIS_MODULE);
87
88 /* Good, fire up the show */
89 if (prescale)
90 tmp |= SWCRR_SWPR;
91 if (reset)
92 tmp |= SWCRR_SWRI;
93
94 tmp |= timeout << 16;
95
96 out_be32(&wd_base->swcrr, tmp);
97
98 return nonseekable_open(inode, file);
99}
100
101static int mpc83xx_wdt_release(struct inode *inode, struct file *file)
102{
103 printk(KERN_CRIT "Unexpected close, not stopping watchdog!\n");
104 mpc83xx_wdt_keepalive();
105 clear_bit(0, &wdt_is_open);
106 return 0;
107}
108
109static int mpc83xx_wdt_ioctl(struct inode *inode, struct file *file,
110 unsigned int cmd, unsigned long arg)
111{
112 void __user *argp = (void __user *)arg;
113 int __user *p = argp;
114 static struct watchdog_info ident = {
115 .options = WDIOF_KEEPALIVEPING,
116 .firmware_version = 1,
117 .identity = "MPC83xx",
118 };
119
120 switch (cmd) {
121 case WDIOC_GETSUPPORT:
122 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
123 case WDIOC_KEEPALIVE:
124 mpc83xx_wdt_keepalive();
125 return 0;
126 case WDIOC_GETTIMEOUT:
127 return put_user(timeout_sec, p);
128 default:
129 return -ENOIOCTLCMD;
130 }
131}
132
133static struct file_operations mpc83xx_wdt_fops = {
134 .owner = THIS_MODULE,
135 .llseek = no_llseek,
136 .write = mpc83xx_wdt_write,
137 .ioctl = mpc83xx_wdt_ioctl,
138 .open = mpc83xx_wdt_open,
139 .release = mpc83xx_wdt_release,
140};
141
142static struct miscdevice mpc83xx_wdt_miscdev = {
143 .minor = WATCHDOG_MINOR,
144 .name = "watchdog",
145 .fops = &mpc83xx_wdt_fops,
146};
147
148static int __devinit mpc83xx_wdt_probe(struct platform_device *dev)
149{
150 struct resource *r;
151 int ret;
152 unsigned int *freq = dev->dev.platform_data;
153
154 /* get a pointer to the register memory */
155 r = platform_get_resource(dev, IORESOURCE_MEM, 0);
156
157 if (!r) {
158 ret = -ENODEV;
159 goto err_out;
160 }
161
162 wd_base = ioremap(r->start, sizeof (struct mpc83xx_wdt));
163
164 if (wd_base == NULL) {
165 ret = -ENOMEM;
166 goto err_out;
167 }
168
169 ret = misc_register(&mpc83xx_wdt_miscdev);
170 if (ret) {
171 printk(KERN_ERR "cannot register miscdev on minor=%d "
172 "(err=%d)\n",
173 WATCHDOG_MINOR, ret);
174 goto err_unmap;
175 }
176
177 /* Calculate the timeout in seconds */
178 if (prescale)
179 timeout_sec = (timeout * 0x10000) / (*freq);
180 else
181 timeout_sec = timeout / (*freq);
182
183 printk(KERN_INFO "WDT driver for MPC83xx initialized. "
184 "mode:%s timeout=%d (%d seconds)\n",
185 reset ? "reset":"interrupt", timeout, timeout_sec);
186
187 spin_lock_init(&wdt_spinlock);
188
189 return 0;
190
191err_unmap:
192 iounmap(wd_base);
193err_out:
194 return ret;
195}
196
197static int __devexit mpc83xx_wdt_remove(struct platform_device *dev)
198{
199 misc_deregister(&mpc83xx_wdt_miscdev);
200 iounmap(wd_base);
201
202 return 0;
203}
204
205static struct platform_driver mpc83xx_wdt_driver = {
206 .probe = mpc83xx_wdt_probe,
207 .remove = __devexit_p(mpc83xx_wdt_remove),
208 .driver = {
209 .name = "mpc83xx_wdt",
210 },
211};
212
213static int __init mpc83xx_wdt_init(void)
214{
215 return platform_driver_register(&mpc83xx_wdt_driver);
216}
217
218static void __exit mpc83xx_wdt_exit(void)
219{
220 platform_driver_unregister(&mpc83xx_wdt_driver);
221}
222
223module_init(mpc83xx_wdt_init);
224module_exit(mpc83xx_wdt_exit);
225
226MODULE_AUTHOR("Dave Updegraff, Kumar Gala");
227MODULE_DESCRIPTION("Driver for watchdog timer in MPC83xx uProcessor");
228MODULE_LICENSE("GPL");
229MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/sbc_epx_c3.c b/drivers/char/watchdog/sbc_epx_c3.c
new file mode 100644
index 000000000000..951764614ebf
--- /dev/null
+++ b/drivers/char/watchdog/sbc_epx_c3.c
@@ -0,0 +1,216 @@
1/*
2 * SBC EPX C3 0.1 A Hardware Watchdog Device for the Winsystems EPX-C3
3 * single board computer
4 *
5 * (c) Copyright 2006 Calin A. Culianu <calin@ajvar.org>, All Rights
6 * Reserved.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 *
13 * based on softdog.c by Alan Cox <alan@redhat.com>
14 */
15
16#include <linux/module.h>
17#include <linux/moduleparam.h>
18#include <linux/config.h>
19#include <linux/types.h>
20#include <linux/kernel.h>
21#include <linux/fs.h>
22#include <linux/mm.h>
23#include <linux/miscdevice.h>
24#include <linux/watchdog.h>
25#include <linux/notifier.h>
26#include <linux/reboot.h>
27#include <linux/init.h>
28#include <asm/uaccess.h>
29#include <asm/io.h>
30
31#define PFX "epx_c3: "
32static int epx_c3_alive;
33
34#define WATCHDOG_TIMEOUT 1 /* 1 sec default timeout */
35
36static int nowayout = WATCHDOG_NOWAYOUT;
37module_param(nowayout, int, 0);
38MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
39
40#define EPXC3_WATCHDOG_CTL_REG 0x1ee /* write 1 to enable, 0 to disable */
41#define EPXC3_WATCHDOG_PET_REG 0x1ef /* write anything to pet once enabled */
42
43static void epx_c3_start(void)
44{
45 outb(1, EPXC3_WATCHDOG_CTL_REG);
46}
47
48static void epx_c3_stop(void)
49{
50
51 outb(0, EPXC3_WATCHDOG_CTL_REG);
52
53 printk(KERN_INFO PFX "Stopped watchdog timer.\n");
54}
55
56static void epx_c3_pet(void)
57{
58 outb(1, EPXC3_WATCHDOG_PET_REG);
59}
60
61/*
62 * Allow only one person to hold it open
63 */
64static int epx_c3_open(struct inode *inode, struct file *file)
65{
66 if (epx_c3_alive)
67 return -EBUSY;
68
69 if (nowayout)
70 __module_get(THIS_MODULE);
71
72 /* Activate timer */
73 epx_c3_start();
74 epx_c3_pet();
75
76 epx_c3_alive = 1;
77 printk(KERN_INFO "Started watchdog timer.\n");
78
79 return nonseekable_open(inode, file);
80}
81
82static int epx_c3_release(struct inode *inode, struct file *file)
83{
84 /* Shut off the timer.
85 * Lock it in if it's a module and we defined ...NOWAYOUT */
86 if (!nowayout)
87 epx_c3_stop(); /* Turn the WDT off */
88
89 epx_c3_alive = 0;
90
91 return 0;
92}
93
94static ssize_t epx_c3_write(struct file *file, const char *data,
95 size_t len, loff_t *ppos)
96{
97 /* Refresh the timer. */
98 if (len)
99 epx_c3_pet();
100 return len;
101}
102
103static int epx_c3_ioctl(struct inode *inode, struct file *file,
104 unsigned int cmd, unsigned long arg)
105{
106 int options, retval = -EINVAL;
107 static struct watchdog_info ident = {
108 .options = WDIOF_KEEPALIVEPING |
109 WDIOF_MAGICCLOSE,
110 .firmware_version = 0,
111 .identity = "Winsystems EPX-C3 H/W Watchdog",
112 };
113
114 switch (cmd) {
115 case WDIOC_GETSUPPORT:
116 if (copy_to_user((struct watchdog_info *)arg,
117 &ident, sizeof(ident)))
118 return -EFAULT;
119 return 0;
120 case WDIOC_GETSTATUS:
121 case WDIOC_GETBOOTSTATUS:
122 return put_user(0,(int *)arg);
123 case WDIOC_KEEPALIVE:
124 epx_c3_pet();
125 return 0;
126 case WDIOC_GETTIMEOUT:
127 return put_user(WATCHDOG_TIMEOUT,(int *)arg);
128 case WDIOC_SETOPTIONS: {
129 if (get_user(options, (int *)arg))
130 return -EFAULT;
131
132 if (options & WDIOS_DISABLECARD) {
133 epx_c3_stop();
134 retval = 0;
135 }
136
137 if (options & WDIOS_ENABLECARD) {
138 epx_c3_start();
139 retval = 0;
140 }
141
142 return retval;
143 }
144 default:
145 return -ENOIOCTLCMD;
146 }
147}
148
149static int epx_c3_notify_sys(struct notifier_block *this, unsigned long code,
150 void *unused)
151{
152 if (code == SYS_DOWN || code == SYS_HALT)
153 epx_c3_stop(); /* Turn the WDT off */
154
155 return NOTIFY_DONE;
156}
157
158static struct file_operations epx_c3_fops = {
159 .owner = THIS_MODULE,
160 .llseek = no_llseek,
161 .write = epx_c3_write,
162 .ioctl = epx_c3_ioctl,
163 .open = epx_c3_open,
164 .release = epx_c3_release,
165};
166
167static struct miscdevice epx_c3_miscdev = {
168 .minor = WATCHDOG_MINOR,
169 .name = "watchdog",
170 .fops = &epx_c3_fops,
171};
172
173static struct notifier_block epx_c3_notifier = {
174 .notifier_call = epx_c3_notify_sys,
175};
176
177static const char banner[] __initdata =
178 KERN_INFO PFX "Hardware Watchdog Timer for Winsystems EPX-C3 SBC: 0.1\n";
179
180static int __init watchdog_init(void)
181{
182 int ret;
183
184 ret = register_reboot_notifier(&epx_c3_notifier);
185 if (ret) {
186 printk(KERN_ERR PFX "cannot register reboot notifier "
187 "(err=%d)\n", ret);
188 return ret;
189 }
190
191 ret = misc_register(&epx_c3_miscdev);
192 if (ret) {
193 printk(KERN_ERR PFX "cannot register miscdev on minor=%d "
194 "(err=%d)\n", WATCHDOG_MINOR, ret);
195 unregister_reboot_notifier(&epx_c3_notifier);
196 return ret;
197 }
198
199 printk(banner);
200
201 return 0;
202}
203
204static void __exit watchdog_exit(void)
205{
206 misc_deregister(&epx_c3_miscdev);
207 unregister_reboot_notifier(&epx_c3_notifier);
208}
209
210module_init(watchdog_init);
211module_exit(watchdog_exit);
212
213MODULE_AUTHOR("Calin A. Culianu <calin@ajvar.org>");
214MODULE_DESCRIPTION("Hardware Watchdog Device for Winsystems EPX-C3 SBC. Note that there is no way to probe for this device -- so only use it if you are *sure* you are runnning on this specific SBC system from Winsystems! It writes to IO ports 0x1ee and 0x1ef!");
215MODULE_LICENSE("GPL");
216MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index a9163d02983a..277a843a87a6 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -41,7 +41,6 @@ static DEFINE_SPINLOCK(cpufreq_driver_lock);
41/* internal prototypes */ 41/* internal prototypes */
42static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event); 42static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event);
43static void handle_update(void *data); 43static void handle_update(void *data);
44static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci);
45 44
46/** 45/**
47 * Two notifier lists: the "policy" list is involved in the 46 * Two notifier lists: the "policy" list is involved in the
@@ -127,7 +126,7 @@ static unsigned int debug_ratelimit = 1;
127static unsigned int disable_ratelimit = 1; 126static unsigned int disable_ratelimit = 1;
128static DEFINE_SPINLOCK(disable_ratelimit_lock); 127static DEFINE_SPINLOCK(disable_ratelimit_lock);
129 128
130static inline void cpufreq_debug_enable_ratelimit(void) 129static void cpufreq_debug_enable_ratelimit(void)
131{ 130{
132 unsigned long flags; 131 unsigned long flags;
133 132
@@ -137,7 +136,7 @@ static inline void cpufreq_debug_enable_ratelimit(void)
137 spin_unlock_irqrestore(&disable_ratelimit_lock, flags); 136 spin_unlock_irqrestore(&disable_ratelimit_lock, flags);
138} 137}
139 138
140static inline void cpufreq_debug_disable_ratelimit(void) 139static void cpufreq_debug_disable_ratelimit(void)
141{ 140{
142 unsigned long flags; 141 unsigned long flags;
143 142
@@ -206,7 +205,7 @@ static inline void cpufreq_debug_disable_ratelimit(void) { return; }
206static unsigned long l_p_j_ref; 205static unsigned long l_p_j_ref;
207static unsigned int l_p_j_ref_freq; 206static unsigned int l_p_j_ref_freq;
208 207
209static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) 208static void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
210{ 209{
211 if (ci->flags & CPUFREQ_CONST_LOOPS) 210 if (ci->flags & CPUFREQ_CONST_LOOPS)
212 return; 211 return;
diff --git a/drivers/dio/dio-driver.c b/drivers/dio/dio-driver.c
index ffe6f44ac76f..ca8e69d2f64d 100644
--- a/drivers/dio/dio-driver.c
+++ b/drivers/dio/dio-driver.c
@@ -83,7 +83,6 @@ int dio_register_driver(struct dio_driver *drv)
83 /* initialize common driver fields */ 83 /* initialize common driver fields */
84 drv->driver.name = drv->name; 84 drv->driver.name = drv->name;
85 drv->driver.bus = &dio_bus_type; 85 drv->driver.bus = &dio_bus_type;
86 drv->driver.probe = dio_device_probe;
87 86
88 /* register with core */ 87 /* register with core */
89 count = driver_register(&drv->driver); 88 count = driver_register(&drv->driver);
@@ -145,7 +144,8 @@ static int dio_bus_match(struct device *dev, struct device_driver *drv)
145 144
146struct bus_type dio_bus_type = { 145struct bus_type dio_bus_type = {
147 .name = "dio", 146 .name = "dio",
148 .match = dio_bus_match 147 .match = dio_bus_match,
148 .probe = dio_device_probe,
149}; 149};
150 150
151 151
diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c
index dfedb777d8c9..fdb8b042e64d 100644
--- a/drivers/firmware/dell_rbu.c
+++ b/drivers/firmware/dell_rbu.c
@@ -49,7 +49,7 @@
49MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>"); 49MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>");
50MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems"); 50MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems");
51MODULE_LICENSE("GPL"); 51MODULE_LICENSE("GPL");
52MODULE_VERSION("3.1"); 52MODULE_VERSION("3.2");
53 53
54#define BIOS_SCAN_LIMIT 0xffffffff 54#define BIOS_SCAN_LIMIT 0xffffffff
55#define MAX_IMAGE_LENGTH 16 55#define MAX_IMAGE_LENGTH 16
@@ -564,12 +564,10 @@ static ssize_t read_rbu_data(struct kobject *kobj, char *buffer,
564 564
565static void callbackfn_rbu(const struct firmware *fw, void *context) 565static void callbackfn_rbu(const struct firmware *fw, void *context)
566{ 566{
567 int rc = 0; 567 rbu_data.entry_created = 0;
568 568
569 if (!fw || !fw->size) { 569 if (!fw || !fw->size)
570 rbu_data.entry_created = 0;
571 return; 570 return;
572 }
573 571
574 spin_lock(&rbu_data.lock); 572 spin_lock(&rbu_data.lock);
575 if (!strcmp(image_type, "mono")) { 573 if (!strcmp(image_type, "mono")) {
@@ -592,15 +590,6 @@ static void callbackfn_rbu(const struct firmware *fw, void *context)
592 } else 590 } else
593 pr_debug("invalid image type specified.\n"); 591 pr_debug("invalid image type specified.\n");
594 spin_unlock(&rbu_data.lock); 592 spin_unlock(&rbu_data.lock);
595
596 rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
597 "dell_rbu", &rbu_device->dev, &context, callbackfn_rbu);
598 if (rc)
599 printk(KERN_ERR
600 "dell_rbu:%s request_firmware_nowait failed"
601 " %d\n", __FUNCTION__, rc);
602 else
603 rbu_data.entry_created = 1;
604} 593}
605 594
606static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer, 595static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer,
@@ -735,14 +724,7 @@ static int __init dcdrbu_init(void)
735 sysfs_create_bin_file(&rbu_device->dev.kobj, 724 sysfs_create_bin_file(&rbu_device->dev.kobj,
736 &rbu_packet_size_attr); 725 &rbu_packet_size_attr);
737 726
738 rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, 727 rbu_data.entry_created = 0;
739 "dell_rbu", &rbu_device->dev, &context, callbackfn_rbu);
740 if (rc)
741 printk(KERN_ERR "dell_rbu:%s:request_firmware_nowait"
742 " failed %d\n", __FUNCTION__, rc);
743 else
744 rbu_data.entry_created = 1;
745
746 return rc; 728 return rc;
747 729
748} 730}
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 52b77477df57..0ce58b506046 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -63,13 +63,6 @@ static int i2c_bus_resume(struct device * dev)
63 return rc; 63 return rc;
64} 64}
65 65
66struct bus_type i2c_bus_type = {
67 .name = "i2c",
68 .match = i2c_device_match,
69 .suspend = i2c_bus_suspend,
70 .resume = i2c_bus_resume,
71};
72
73static int i2c_device_probe(struct device *dev) 66static int i2c_device_probe(struct device *dev)
74{ 67{
75 return -ENODEV; 68 return -ENODEV;
@@ -80,6 +73,15 @@ static int i2c_device_remove(struct device *dev)
80 return 0; 73 return 0;
81} 74}
82 75
76struct bus_type i2c_bus_type = {
77 .name = "i2c",
78 .match = i2c_device_match,
79 .probe = i2c_device_probe,
80 .remove = i2c_device_remove,
81 .suspend = i2c_bus_suspend,
82 .resume = i2c_bus_resume,
83};
84
83void i2c_adapter_dev_release(struct device *dev) 85void i2c_adapter_dev_release(struct device *dev)
84{ 86{
85 struct i2c_adapter *adap = dev_to_i2c_adapter(dev); 87 struct i2c_adapter *adap = dev_to_i2c_adapter(dev);
@@ -90,8 +92,6 @@ struct device_driver i2c_adapter_driver = {
90 .owner = THIS_MODULE, 92 .owner = THIS_MODULE,
91 .name = "i2c_adapter", 93 .name = "i2c_adapter",
92 .bus = &i2c_bus_type, 94 .bus = &i2c_bus_type,
93 .probe = i2c_device_probe,
94 .remove = i2c_device_remove,
95}; 95};
96 96
97static void i2c_adapter_class_dev_release(struct class_device *dev) 97static void i2c_adapter_class_dev_release(struct class_device *dev)
@@ -294,8 +294,6 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
294 /* add the driver to the list of i2c drivers in the driver core */ 294 /* add the driver to the list of i2c drivers in the driver core */
295 driver->driver.owner = owner; 295 driver->driver.owner = owner;
296 driver->driver.bus = &i2c_bus_type; 296 driver->driver.bus = &i2c_bus_type;
297 driver->driver.probe = i2c_device_probe;
298 driver->driver.remove = i2c_device_remove;
299 297
300 res = driver_register(&driver->driver); 298 res = driver_register(&driver->driver);
301 if (res) 299 if (res)
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 9b2ebd219ad0..3325660f7248 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -980,7 +980,7 @@ static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector,
980 * and attempt to recover if there are problems. Returns 0 if everything's 980 * and attempt to recover if there are problems. Returns 0 if everything's
981 * ok; nonzero if the request has been terminated. 981 * ok; nonzero if the request has been terminated.
982 */ 982 */
983static inline 983static
984int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason) 984int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason)
985{ 985{
986 if (ireason == 2) 986 if (ireason == 2)
@@ -1539,7 +1539,7 @@ int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq)
1539/* 1539/*
1540 * Write handling 1540 * Write handling
1541 */ 1541 */
1542static inline int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ireason) 1542static int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ireason)
1543{ 1543{
1544 /* Two notes about IDE interrupt reason here - 0 means that 1544 /* Two notes about IDE interrupt reason here - 0 means that
1545 * the drive wants to receive data from us, 2 means that 1545 * the drive wants to receive data from us, 2 means that
@@ -3256,9 +3256,8 @@ sector_t ide_cdrom_capacity (ide_drive_t *drive)
3256} 3256}
3257#endif 3257#endif
3258 3258
3259static int ide_cd_remove(struct device *dev) 3259static void ide_cd_remove(ide_drive_t *drive)
3260{ 3260{
3261 ide_drive_t *drive = to_ide_device(dev);
3262 struct cdrom_info *info = drive->driver_data; 3261 struct cdrom_info *info = drive->driver_data;
3263 3262
3264 ide_unregister_subdriver(drive, info->driver); 3263 ide_unregister_subdriver(drive, info->driver);
@@ -3266,8 +3265,6 @@ static int ide_cd_remove(struct device *dev)
3266 del_gendisk(info->disk); 3265 del_gendisk(info->disk);
3267 3266
3268 ide_cd_put(info); 3267 ide_cd_put(info);
3269
3270 return 0;
3271} 3268}
3272 3269
3273static void ide_cd_release(struct kref *kref) 3270static void ide_cd_release(struct kref *kref)
@@ -3291,7 +3288,7 @@ static void ide_cd_release(struct kref *kref)
3291 kfree(info); 3288 kfree(info);
3292} 3289}
3293 3290
3294static int ide_cd_probe(struct device *); 3291static int ide_cd_probe(ide_drive_t *);
3295 3292
3296#ifdef CONFIG_PROC_FS 3293#ifdef CONFIG_PROC_FS
3297static int proc_idecd_read_capacity 3294static int proc_idecd_read_capacity
@@ -3317,9 +3314,9 @@ static ide_driver_t ide_cdrom_driver = {
3317 .owner = THIS_MODULE, 3314 .owner = THIS_MODULE,
3318 .name = "ide-cdrom", 3315 .name = "ide-cdrom",
3319 .bus = &ide_bus_type, 3316 .bus = &ide_bus_type,
3320 .probe = ide_cd_probe,
3321 .remove = ide_cd_remove,
3322 }, 3317 },
3318 .probe = ide_cd_probe,
3319 .remove = ide_cd_remove,
3323 .version = IDECD_VERSION, 3320 .version = IDECD_VERSION,
3324 .media = ide_cdrom, 3321 .media = ide_cdrom,
3325 .supports_dsc_overlap = 1, 3322 .supports_dsc_overlap = 1,
@@ -3413,9 +3410,8 @@ static char *ignore = NULL;
3413module_param(ignore, charp, 0400); 3410module_param(ignore, charp, 0400);
3414MODULE_DESCRIPTION("ATAPI CD-ROM Driver"); 3411MODULE_DESCRIPTION("ATAPI CD-ROM Driver");
3415 3412
3416static int ide_cd_probe(struct device *dev) 3413static int ide_cd_probe(ide_drive_t *drive)
3417{ 3414{
3418 ide_drive_t *drive = to_ide_device(dev);
3419 struct cdrom_info *info; 3415 struct cdrom_info *info;
3420 struct gendisk *g; 3416 struct gendisk *g;
3421 struct request_sense sense; 3417 struct request_sense sense;
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index cab362ea0336..ca25f9e3d0f4 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -477,7 +477,7 @@ static inline int idedisk_supports_lba48(const struct hd_driveid *id)
477 && id->lba_capacity_2; 477 && id->lba_capacity_2;
478} 478}
479 479
480static inline void idedisk_check_hpa(ide_drive_t *drive) 480static void idedisk_check_hpa(ide_drive_t *drive)
481{ 481{
482 unsigned long long capacity, set_max; 482 unsigned long long capacity, set_max;
483 int lba48 = idedisk_supports_lba48(drive->id); 483 int lba48 = idedisk_supports_lba48(drive->id);
@@ -997,9 +997,8 @@ static void ide_cacheflush_p(ide_drive_t *drive)
997 printk(KERN_INFO "%s: wcache flush failed!\n", drive->name); 997 printk(KERN_INFO "%s: wcache flush failed!\n", drive->name);
998} 998}
999 999
1000static int ide_disk_remove(struct device *dev) 1000static void ide_disk_remove(ide_drive_t *drive)
1001{ 1001{
1002 ide_drive_t *drive = to_ide_device(dev);
1003 struct ide_disk_obj *idkp = drive->driver_data; 1002 struct ide_disk_obj *idkp = drive->driver_data;
1004 struct gendisk *g = idkp->disk; 1003 struct gendisk *g = idkp->disk;
1005 1004
@@ -1010,8 +1009,6 @@ static int ide_disk_remove(struct device *dev)
1010 ide_cacheflush_p(drive); 1009 ide_cacheflush_p(drive);
1011 1010
1012 ide_disk_put(idkp); 1011 ide_disk_put(idkp);
1013
1014 return 0;
1015} 1012}
1016 1013
1017static void ide_disk_release(struct kref *kref) 1014static void ide_disk_release(struct kref *kref)
@@ -1027,12 +1024,10 @@ static void ide_disk_release(struct kref *kref)
1027 kfree(idkp); 1024 kfree(idkp);
1028} 1025}
1029 1026
1030static int ide_disk_probe(struct device *dev); 1027static int ide_disk_probe(ide_drive_t *drive);
1031 1028
1032static void ide_device_shutdown(struct device *dev) 1029static void ide_device_shutdown(ide_drive_t *drive)
1033{ 1030{
1034 ide_drive_t *drive = container_of(dev, ide_drive_t, gendev);
1035
1036#ifdef CONFIG_ALPHA 1031#ifdef CONFIG_ALPHA
1037 /* On Alpha, halt(8) doesn't actually turn the machine off, 1032 /* On Alpha, halt(8) doesn't actually turn the machine off,
1038 it puts you into the sort of firmware monitor. Typically, 1033 it puts you into the sort of firmware monitor. Typically,
@@ -1054,7 +1049,7 @@ static void ide_device_shutdown(struct device *dev)
1054 } 1049 }
1055 1050
1056 printk("Shutdown: %s\n", drive->name); 1051 printk("Shutdown: %s\n", drive->name);
1057 dev->bus->suspend(dev, PMSG_SUSPEND); 1052 drive->gendev.bus->suspend(&drive->gendev, PMSG_SUSPEND);
1058} 1053}
1059 1054
1060static ide_driver_t idedisk_driver = { 1055static ide_driver_t idedisk_driver = {
@@ -1062,10 +1057,10 @@ static ide_driver_t idedisk_driver = {
1062 .owner = THIS_MODULE, 1057 .owner = THIS_MODULE,
1063 .name = "ide-disk", 1058 .name = "ide-disk",
1064 .bus = &ide_bus_type, 1059 .bus = &ide_bus_type,
1065 .probe = ide_disk_probe,
1066 .remove = ide_disk_remove,
1067 .shutdown = ide_device_shutdown,
1068 }, 1060 },
1061 .probe = ide_disk_probe,
1062 .remove = ide_disk_remove,
1063 .shutdown = ide_device_shutdown,
1069 .version = IDEDISK_VERSION, 1064 .version = IDEDISK_VERSION,
1070 .media = ide_disk, 1065 .media = ide_disk,
1071 .supports_dsc_overlap = 0, 1066 .supports_dsc_overlap = 0,
@@ -1182,9 +1177,8 @@ static struct block_device_operations idedisk_ops = {
1182 1177
1183MODULE_DESCRIPTION("ATA DISK Driver"); 1178MODULE_DESCRIPTION("ATA DISK Driver");
1184 1179
1185static int ide_disk_probe(struct device *dev) 1180static int ide_disk_probe(ide_drive_t *drive)
1186{ 1181{
1187 ide_drive_t *drive = to_ide_device(dev);
1188 struct ide_disk_obj *idkp; 1182 struct ide_disk_obj *idkp;
1189 struct gendisk *g; 1183 struct gendisk *g;
1190 1184
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index 5945f551aaaa..1f8db9ac05d1 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -1871,9 +1871,8 @@ static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy)
1871 idefloppy_add_settings(drive); 1871 idefloppy_add_settings(drive);
1872} 1872}
1873 1873
1874static int ide_floppy_remove(struct device *dev) 1874static void ide_floppy_remove(ide_drive_t *drive)
1875{ 1875{
1876 ide_drive_t *drive = to_ide_device(dev);
1877 idefloppy_floppy_t *floppy = drive->driver_data; 1876 idefloppy_floppy_t *floppy = drive->driver_data;
1878 struct gendisk *g = floppy->disk; 1877 struct gendisk *g = floppy->disk;
1879 1878
@@ -1882,8 +1881,6 @@ static int ide_floppy_remove(struct device *dev)
1882 del_gendisk(g); 1881 del_gendisk(g);
1883 1882
1884 ide_floppy_put(floppy); 1883 ide_floppy_put(floppy);
1885
1886 return 0;
1887} 1884}
1888 1885
1889static void ide_floppy_release(struct kref *kref) 1886static void ide_floppy_release(struct kref *kref)
@@ -1922,16 +1919,16 @@ static ide_proc_entry_t idefloppy_proc[] = {
1922 1919
1923#endif /* CONFIG_PROC_FS */ 1920#endif /* CONFIG_PROC_FS */
1924 1921
1925static int ide_floppy_probe(struct device *); 1922static int ide_floppy_probe(ide_drive_t *);
1926 1923
1927static ide_driver_t idefloppy_driver = { 1924static ide_driver_t idefloppy_driver = {
1928 .gen_driver = { 1925 .gen_driver = {
1929 .owner = THIS_MODULE, 1926 .owner = THIS_MODULE,
1930 .name = "ide-floppy", 1927 .name = "ide-floppy",
1931 .bus = &ide_bus_type, 1928 .bus = &ide_bus_type,
1932 .probe = ide_floppy_probe,
1933 .remove = ide_floppy_remove,
1934 }, 1929 },
1930 .probe = ide_floppy_probe,
1931 .remove = ide_floppy_remove,
1935 .version = IDEFLOPPY_VERSION, 1932 .version = IDEFLOPPY_VERSION,
1936 .media = ide_floppy, 1933 .media = ide_floppy,
1937 .supports_dsc_overlap = 0, 1934 .supports_dsc_overlap = 0,
@@ -2136,9 +2133,8 @@ static struct block_device_operations idefloppy_ops = {
2136 .revalidate_disk= idefloppy_revalidate_disk 2133 .revalidate_disk= idefloppy_revalidate_disk
2137}; 2134};
2138 2135
2139static int ide_floppy_probe(struct device *dev) 2136static int ide_floppy_probe(ide_drive_t *drive)
2140{ 2137{
2141 ide_drive_t *drive = to_ide_device(dev);
2142 idefloppy_floppy_t *floppy; 2138 idefloppy_floppy_t *floppy;
2143 struct gendisk *g; 2139 struct gendisk *g;
2144 2140
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index fab9b2b02504..0101d0def7c5 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -4682,9 +4682,8 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
4682 idetape_add_settings(drive); 4682 idetape_add_settings(drive);
4683} 4683}
4684 4684
4685static int ide_tape_remove(struct device *dev) 4685static void ide_tape_remove(ide_drive_t *drive)
4686{ 4686{
4687 ide_drive_t *drive = to_ide_device(dev);
4688 idetape_tape_t *tape = drive->driver_data; 4687 idetape_tape_t *tape = drive->driver_data;
4689 4688
4690 ide_unregister_subdriver(drive, tape->driver); 4689 ide_unregister_subdriver(drive, tape->driver);
@@ -4692,8 +4691,6 @@ static int ide_tape_remove(struct device *dev)
4692 ide_unregister_region(tape->disk); 4691 ide_unregister_region(tape->disk);
4693 4692
4694 ide_tape_put(tape); 4693 ide_tape_put(tape);
4695
4696 return 0;
4697} 4694}
4698 4695
4699static void ide_tape_release(struct kref *kref) 4696static void ide_tape_release(struct kref *kref)
@@ -4745,16 +4742,16 @@ static ide_proc_entry_t idetape_proc[] = {
4745 4742
4746#endif 4743#endif
4747 4744
4748static int ide_tape_probe(struct device *); 4745static int ide_tape_probe(ide_drive_t *);
4749 4746
4750static ide_driver_t idetape_driver = { 4747static ide_driver_t idetape_driver = {
4751 .gen_driver = { 4748 .gen_driver = {
4752 .owner = THIS_MODULE, 4749 .owner = THIS_MODULE,
4753 .name = "ide-tape", 4750 .name = "ide-tape",
4754 .bus = &ide_bus_type, 4751 .bus = &ide_bus_type,
4755 .probe = ide_tape_probe,
4756 .remove = ide_tape_remove,
4757 }, 4752 },
4753 .probe = ide_tape_probe,
4754 .remove = ide_tape_remove,
4758 .version = IDETAPE_VERSION, 4755 .version = IDETAPE_VERSION,
4759 .media = ide_tape, 4756 .media = ide_tape,
4760 .supports_dsc_overlap = 1, 4757 .supports_dsc_overlap = 1,
@@ -4825,9 +4822,8 @@ static struct block_device_operations idetape_block_ops = {
4825 .ioctl = idetape_ioctl, 4822 .ioctl = idetape_ioctl,
4826}; 4823};
4827 4824
4828static int ide_tape_probe(struct device *dev) 4825static int ide_tape_probe(ide_drive_t *drive)
4829{ 4826{
4830 ide_drive_t *drive = to_ide_device(dev);
4831 idetape_tape_t *tape; 4827 idetape_tape_t *tape;
4832 struct gendisk *g; 4828 struct gendisk *g;
4833 int minor; 4829 int minor;
@@ -4883,9 +4879,9 @@ static int ide_tape_probe(struct device *dev)
4883 idetape_setup(drive, tape, minor); 4879 idetape_setup(drive, tape, minor);
4884 4880
4885 class_device_create(idetape_sysfs_class, NULL, 4881 class_device_create(idetape_sysfs_class, NULL,
4886 MKDEV(IDETAPE_MAJOR, minor), dev, "%s", tape->name); 4882 MKDEV(IDETAPE_MAJOR, minor), &drive->gendev, "%s", tape->name);
4887 class_device_create(idetape_sysfs_class, NULL, 4883 class_device_create(idetape_sysfs_class, NULL,
4888 MKDEV(IDETAPE_MAJOR, minor + 128), dev, "n%s", tape->name); 4884 MKDEV(IDETAPE_MAJOR, minor + 128), &drive->gendev, "n%s", tape->name);
4889 4885
4890 devfs_mk_cdev(MKDEV(HWIF(drive)->major, minor), 4886 devfs_mk_cdev(MKDEV(HWIF(drive)->major, minor),
4891 S_IFCHR | S_IRUGO | S_IWUGO, 4887 S_IFCHR | S_IRUGO | S_IWUGO,
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index 62ebefd6394a..9834dce4e20f 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -308,7 +308,7 @@ static void ide_pio_multi(ide_drive_t *drive, unsigned int write)
308 ide_pio_sector(drive, write); 308 ide_pio_sector(drive, write);
309} 309}
310 310
311static inline void ide_pio_datablock(ide_drive_t *drive, struct request *rq, 311static void ide_pio_datablock(ide_drive_t *drive, struct request *rq,
312 unsigned int write) 312 unsigned int write)
313{ 313{
314 if (rq->bio) /* fs request */ 314 if (rq->bio) /* fs request */
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index ec5a4cb173b0..afeb02bbb722 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -1949,10 +1949,41 @@ static int ide_uevent(struct device *dev, char **envp, int num_envp,
1949 return 0; 1949 return 0;
1950} 1950}
1951 1951
1952static int generic_ide_probe(struct device *dev)
1953{
1954 ide_drive_t *drive = to_ide_device(dev);
1955 ide_driver_t *drv = to_ide_driver(dev->driver);
1956
1957 return drv->probe ? drv->probe(drive) : -ENODEV;
1958}
1959
1960static int generic_ide_remove(struct device *dev)
1961{
1962 ide_drive_t *drive = to_ide_device(dev);
1963 ide_driver_t *drv = to_ide_driver(dev->driver);
1964
1965 if (drv->remove)
1966 drv->remove(drive);
1967
1968 return 0;
1969}
1970
1971static void generic_ide_shutdown(struct device *dev)
1972{
1973 ide_drive_t *drive = to_ide_device(dev);
1974 ide_driver_t *drv = to_ide_driver(dev->driver);
1975
1976 if (dev->driver && drv->shutdown)
1977 drv->shutdown(drive);
1978}
1979
1952struct bus_type ide_bus_type = { 1980struct bus_type ide_bus_type = {
1953 .name = "ide", 1981 .name = "ide",
1954 .match = ide_bus_match, 1982 .match = ide_bus_match,
1955 .uevent = ide_uevent, 1983 .uevent = ide_uevent,
1984 .probe = generic_ide_probe,
1985 .remove = generic_ide_remove,
1986 .shutdown = generic_ide_shutdown,
1956 .dev_attrs = ide_dev_attrs, 1987 .dev_attrs = ide_dev_attrs,
1957 .suspend = generic_ide_suspend, 1988 .suspend = generic_ide_suspend,
1958 .resume = generic_ide_resume, 1989 .resume = generic_ide_resume,
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 3a611fe5497e..2514de3480d8 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -856,7 +856,7 @@ static void cm_format_req(struct cm_req_msg *req_msg,
856 param->private_data_len); 856 param->private_data_len);
857} 857}
858 858
859static inline int cm_validate_req_param(struct ib_cm_req_param *param) 859static int cm_validate_req_param(struct ib_cm_req_param *param)
860{ 860{
861 /* peer-to-peer not supported */ 861 /* peer-to-peer not supported */
862 if (param->peer_to_peer) 862 if (param->peer_to_peer)
@@ -1005,7 +1005,7 @@ static inline int cm_is_active_peer(__be64 local_ca_guid, __be64 remote_ca_guid,
1005 (be32_to_cpu(local_qpn) > be32_to_cpu(remote_qpn)))); 1005 (be32_to_cpu(local_qpn) > be32_to_cpu(remote_qpn))));
1006} 1006}
1007 1007
1008static inline void cm_format_paths_from_req(struct cm_req_msg *req_msg, 1008static void cm_format_paths_from_req(struct cm_req_msg *req_msg,
1009 struct ib_sa_path_rec *primary_path, 1009 struct ib_sa_path_rec *primary_path,
1010 struct ib_sa_path_rec *alt_path) 1010 struct ib_sa_path_rec *alt_path)
1011{ 1011{
@@ -3163,22 +3163,6 @@ int ib_cm_init_qp_attr(struct ib_cm_id *cm_id,
3163} 3163}
3164EXPORT_SYMBOL(ib_cm_init_qp_attr); 3164EXPORT_SYMBOL(ib_cm_init_qp_attr);
3165 3165
3166static __be64 cm_get_ca_guid(struct ib_device *device)
3167{
3168 struct ib_device_attr *device_attr;
3169 __be64 guid;
3170 int ret;
3171
3172 device_attr = kmalloc(sizeof *device_attr, GFP_KERNEL);
3173 if (!device_attr)
3174 return 0;
3175
3176 ret = ib_query_device(device, device_attr);
3177 guid = ret ? 0 : device_attr->node_guid;
3178 kfree(device_attr);
3179 return guid;
3180}
3181
3182static void cm_add_one(struct ib_device *device) 3166static void cm_add_one(struct ib_device *device)
3183{ 3167{
3184 struct cm_device *cm_dev; 3168 struct cm_device *cm_dev;
@@ -3200,9 +3184,7 @@ static void cm_add_one(struct ib_device *device)
3200 return; 3184 return;
3201 3185
3202 cm_dev->device = device; 3186 cm_dev->device = device;
3203 cm_dev->ca_guid = cm_get_ca_guid(device); 3187 cm_dev->ca_guid = device->node_guid;
3204 if (!cm_dev->ca_guid)
3205 goto error1;
3206 3188
3207 set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask); 3189 set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask);
3208 for (i = 1; i <= device->phys_port_cnt; i++) { 3190 for (i = 1; i <= device->phys_port_cnt; i++) {
@@ -3217,11 +3199,11 @@ static void cm_add_one(struct ib_device *device)
3217 cm_recv_handler, 3199 cm_recv_handler,
3218 port); 3200 port);
3219 if (IS_ERR(port->mad_agent)) 3201 if (IS_ERR(port->mad_agent))
3220 goto error2; 3202 goto error1;
3221 3203
3222 ret = ib_modify_port(device, i, 0, &port_modify); 3204 ret = ib_modify_port(device, i, 0, &port_modify);
3223 if (ret) 3205 if (ret)
3224 goto error3; 3206 goto error2;
3225 } 3207 }
3226 ib_set_client_data(device, &cm_client, cm_dev); 3208 ib_set_client_data(device, &cm_client, cm_dev);
3227 3209
@@ -3230,9 +3212,9 @@ static void cm_add_one(struct ib_device *device)
3230 write_unlock_irqrestore(&cm.device_lock, flags); 3212 write_unlock_irqrestore(&cm.device_lock, flags);
3231 return; 3213 return;
3232 3214
3233error3:
3234 ib_unregister_mad_agent(port->mad_agent);
3235error2: 3215error2:
3216 ib_unregister_mad_agent(port->mad_agent);
3217error1:
3236 port_modify.set_port_cap_mask = 0; 3218 port_modify.set_port_cap_mask = 0;
3237 port_modify.clr_port_cap_mask = IB_PORT_CM_SUP; 3219 port_modify.clr_port_cap_mask = IB_PORT_CM_SUP;
3238 while (--i) { 3220 while (--i) {
@@ -3240,7 +3222,6 @@ error2:
3240 ib_modify_port(device, port->port_num, 0, &port_modify); 3222 ib_modify_port(device, port->port_num, 0, &port_modify);
3241 ib_unregister_mad_agent(port->mad_agent); 3223 ib_unregister_mad_agent(port->mad_agent);
3242 } 3224 }
3243error1:
3244 kfree(cm_dev); 3225 kfree(cm_dev);
3245} 3226}
3246 3227
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index e169e798354b..b2f3cb91d9bc 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -38,8 +38,7 @@
38#include <linux/errno.h> 38#include <linux/errno.h>
39#include <linux/slab.h> 39#include <linux/slab.h>
40#include <linux/init.h> 40#include <linux/init.h>
41 41#include <linux/mutex.h>
42#include <asm/semaphore.h>
43 42
44#include "core_priv.h" 43#include "core_priv.h"
45 44
@@ -57,13 +56,13 @@ static LIST_HEAD(device_list);
57static LIST_HEAD(client_list); 56static LIST_HEAD(client_list);
58 57
59/* 58/*
60 * device_sem protects access to both device_list and client_list. 59 * device_mutex protects access to both device_list and client_list.
61 * There's no real point to using multiple locks or something fancier 60 * There's no real point to using multiple locks or something fancier
62 * like an rwsem: we always access both lists, and we're always 61 * like an rwsem: we always access both lists, and we're always
63 * modifying one list or the other list. In any case this is not a 62 * modifying one list or the other list. In any case this is not a
64 * hot path so there's no point in trying to optimize. 63 * hot path so there's no point in trying to optimize.
65 */ 64 */
66static DECLARE_MUTEX(device_sem); 65static DEFINE_MUTEX(device_mutex);
67 66
68static int ib_device_check_mandatory(struct ib_device *device) 67static int ib_device_check_mandatory(struct ib_device *device)
69{ 68{
@@ -221,7 +220,7 @@ int ib_register_device(struct ib_device *device)
221{ 220{
222 int ret; 221 int ret;
223 222
224 down(&device_sem); 223 mutex_lock(&device_mutex);
225 224
226 if (strchr(device->name, '%')) { 225 if (strchr(device->name, '%')) {
227 ret = alloc_name(device->name); 226 ret = alloc_name(device->name);
@@ -259,7 +258,7 @@ int ib_register_device(struct ib_device *device)
259 } 258 }
260 259
261 out: 260 out:
262 up(&device_sem); 261 mutex_unlock(&device_mutex);
263 return ret; 262 return ret;
264} 263}
265EXPORT_SYMBOL(ib_register_device); 264EXPORT_SYMBOL(ib_register_device);
@@ -276,7 +275,7 @@ void ib_unregister_device(struct ib_device *device)
276 struct ib_client_data *context, *tmp; 275 struct ib_client_data *context, *tmp;
277 unsigned long flags; 276 unsigned long flags;
278 277
279 down(&device_sem); 278 mutex_lock(&device_mutex);
280 279
281 list_for_each_entry_reverse(client, &client_list, list) 280 list_for_each_entry_reverse(client, &client_list, list)
282 if (client->remove) 281 if (client->remove)
@@ -284,7 +283,7 @@ void ib_unregister_device(struct ib_device *device)
284 283
285 list_del(&device->core_list); 284 list_del(&device->core_list);
286 285
287 up(&device_sem); 286 mutex_unlock(&device_mutex);
288 287
289 spin_lock_irqsave(&device->client_data_lock, flags); 288 spin_lock_irqsave(&device->client_data_lock, flags);
290 list_for_each_entry_safe(context, tmp, &device->client_data_list, list) 289 list_for_each_entry_safe(context, tmp, &device->client_data_list, list)
@@ -312,14 +311,14 @@ int ib_register_client(struct ib_client *client)
312{ 311{
313 struct ib_device *device; 312 struct ib_device *device;
314 313
315 down(&device_sem); 314 mutex_lock(&device_mutex);
316 315
317 list_add_tail(&client->list, &client_list); 316 list_add_tail(&client->list, &client_list);
318 list_for_each_entry(device, &device_list, core_list) 317 list_for_each_entry(device, &device_list, core_list)
319 if (client->add && !add_client_context(device, client)) 318 if (client->add && !add_client_context(device, client))
320 client->add(device); 319 client->add(device);
321 320
322 up(&device_sem); 321 mutex_unlock(&device_mutex);
323 322
324 return 0; 323 return 0;
325} 324}
@@ -339,7 +338,7 @@ void ib_unregister_client(struct ib_client *client)
339 struct ib_device *device; 338 struct ib_device *device;
340 unsigned long flags; 339 unsigned long flags;
341 340
342 down(&device_sem); 341 mutex_lock(&device_mutex);
343 342
344 list_for_each_entry(device, &device_list, core_list) { 343 list_for_each_entry(device, &device_list, core_list) {
345 if (client->remove) 344 if (client->remove)
@@ -355,7 +354,7 @@ void ib_unregister_client(struct ib_client *client)
355 } 354 }
356 list_del(&client->list); 355 list_del(&client->list);
357 356
358 up(&device_sem); 357 mutex_unlock(&device_mutex);
359} 358}
360EXPORT_SYMBOL(ib_unregister_client); 359EXPORT_SYMBOL(ib_unregister_client);
361 360
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index 1f1743c5c9a3..5982d687a000 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -445,13 +445,7 @@ static int ib_device_uevent(struct class_device *cdev, char **envp,
445 return -ENOMEM; 445 return -ENOMEM;
446 446
447 /* 447 /*
448 * It might be nice to pass the node GUID with the event, but 448 * It would be nice to pass the node GUID with the event...
449 * right now the only way to get it is to query the device
450 * provider, and this can crash during device removal because
451 * we are will be running after driver removal has started.
452 * We could add a node_guid field to struct ib_device, or we
453 * could just let userspace read the node GUID from sysfs when
454 * devices are added.
455 */ 449 */
456 450
457 envp[i] = NULL; 451 envp[i] = NULL;
@@ -623,21 +617,15 @@ static ssize_t show_sys_image_guid(struct class_device *cdev, char *buf)
623static ssize_t show_node_guid(struct class_device *cdev, char *buf) 617static ssize_t show_node_guid(struct class_device *cdev, char *buf)
624{ 618{
625 struct ib_device *dev = container_of(cdev, struct ib_device, class_dev); 619 struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);
626 struct ib_device_attr attr;
627 ssize_t ret;
628 620
629 if (!ibdev_is_alive(dev)) 621 if (!ibdev_is_alive(dev))
630 return -ENODEV; 622 return -ENODEV;
631 623
632 ret = ib_query_device(dev, &attr);
633 if (ret)
634 return ret;
635
636 return sprintf(buf, "%04x:%04x:%04x:%04x\n", 624 return sprintf(buf, "%04x:%04x:%04x:%04x\n",
637 be16_to_cpu(((__be16 *) &attr.node_guid)[0]), 625 be16_to_cpu(((__be16 *) &dev->node_guid)[0]),
638 be16_to_cpu(((__be16 *) &attr.node_guid)[1]), 626 be16_to_cpu(((__be16 *) &dev->node_guid)[1]),
639 be16_to_cpu(((__be16 *) &attr.node_guid)[2]), 627 be16_to_cpu(((__be16 *) &dev->node_guid)[2]),
640 be16_to_cpu(((__be16 *) &attr.node_guid)[3])); 628 be16_to_cpu(((__be16 *) &dev->node_guid)[3]));
641} 629}
642 630
643static CLASS_DEVICE_ATTR(node_type, S_IRUGO, show_node_type, NULL); 631static CLASS_DEVICE_ATTR(node_type, S_IRUGO, show_node_type, NULL);
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
index 6e15787d1de1..e95c4293a496 100644
--- a/drivers/infiniband/core/ucm.c
+++ b/drivers/infiniband/core/ucm.c
@@ -42,6 +42,7 @@
42#include <linux/mount.h> 42#include <linux/mount.h>
43#include <linux/cdev.h> 43#include <linux/cdev.h>
44#include <linux/idr.h> 44#include <linux/idr.h>
45#include <linux/mutex.h>
45 46
46#include <asm/uaccess.h> 47#include <asm/uaccess.h>
47 48
@@ -113,7 +114,7 @@ static struct ib_client ucm_client = {
113 .remove = ib_ucm_remove_one 114 .remove = ib_ucm_remove_one
114}; 115};
115 116
116static DECLARE_MUTEX(ctx_id_mutex); 117static DEFINE_MUTEX(ctx_id_mutex);
117static DEFINE_IDR(ctx_id_table); 118static DEFINE_IDR(ctx_id_table);
118static DECLARE_BITMAP(dev_map, IB_UCM_MAX_DEVICES); 119static DECLARE_BITMAP(dev_map, IB_UCM_MAX_DEVICES);
119 120
@@ -121,7 +122,7 @@ static struct ib_ucm_context *ib_ucm_ctx_get(struct ib_ucm_file *file, int id)
121{ 122{
122 struct ib_ucm_context *ctx; 123 struct ib_ucm_context *ctx;
123 124
124 down(&ctx_id_mutex); 125 mutex_lock(&ctx_id_mutex);
125 ctx = idr_find(&ctx_id_table, id); 126 ctx = idr_find(&ctx_id_table, id);
126 if (!ctx) 127 if (!ctx)
127 ctx = ERR_PTR(-ENOENT); 128 ctx = ERR_PTR(-ENOENT);
@@ -129,7 +130,7 @@ static struct ib_ucm_context *ib_ucm_ctx_get(struct ib_ucm_file *file, int id)
129 ctx = ERR_PTR(-EINVAL); 130 ctx = ERR_PTR(-EINVAL);
130 else 131 else
131 atomic_inc(&ctx->ref); 132 atomic_inc(&ctx->ref);
132 up(&ctx_id_mutex); 133 mutex_unlock(&ctx_id_mutex);
133 134
134 return ctx; 135 return ctx;
135} 136}
@@ -186,9 +187,9 @@ static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file)
186 if (!result) 187 if (!result)
187 goto error; 188 goto error;
188 189
189 down(&ctx_id_mutex); 190 mutex_lock(&ctx_id_mutex);
190 result = idr_get_new(&ctx_id_table, ctx, &ctx->id); 191 result = idr_get_new(&ctx_id_table, ctx, &ctx->id);
191 up(&ctx_id_mutex); 192 mutex_unlock(&ctx_id_mutex);
192 } while (result == -EAGAIN); 193 } while (result == -EAGAIN);
193 194
194 if (result) 195 if (result)
@@ -550,9 +551,9 @@ static ssize_t ib_ucm_create_id(struct ib_ucm_file *file,
550err2: 551err2:
551 ib_destroy_cm_id(ctx->cm_id); 552 ib_destroy_cm_id(ctx->cm_id);
552err1: 553err1:
553 down(&ctx_id_mutex); 554 mutex_lock(&ctx_id_mutex);
554 idr_remove(&ctx_id_table, ctx->id); 555 idr_remove(&ctx_id_table, ctx->id);
555 up(&ctx_id_mutex); 556 mutex_unlock(&ctx_id_mutex);
556 kfree(ctx); 557 kfree(ctx);
557 return result; 558 return result;
558} 559}
@@ -572,7 +573,7 @@ static ssize_t ib_ucm_destroy_id(struct ib_ucm_file *file,
572 if (copy_from_user(&cmd, inbuf, sizeof(cmd))) 573 if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
573 return -EFAULT; 574 return -EFAULT;
574 575
575 down(&ctx_id_mutex); 576 mutex_lock(&ctx_id_mutex);
576 ctx = idr_find(&ctx_id_table, cmd.id); 577 ctx = idr_find(&ctx_id_table, cmd.id);
577 if (!ctx) 578 if (!ctx)
578 ctx = ERR_PTR(-ENOENT); 579 ctx = ERR_PTR(-ENOENT);
@@ -580,7 +581,7 @@ static ssize_t ib_ucm_destroy_id(struct ib_ucm_file *file,
580 ctx = ERR_PTR(-EINVAL); 581 ctx = ERR_PTR(-EINVAL);
581 else 582 else
582 idr_remove(&ctx_id_table, ctx->id); 583 idr_remove(&ctx_id_table, ctx->id);
583 up(&ctx_id_mutex); 584 mutex_unlock(&ctx_id_mutex);
584 585
585 if (IS_ERR(ctx)) 586 if (IS_ERR(ctx))
586 return PTR_ERR(ctx); 587 return PTR_ERR(ctx);
@@ -1280,9 +1281,9 @@ static int ib_ucm_close(struct inode *inode, struct file *filp)
1280 struct ib_ucm_context, file_list); 1281 struct ib_ucm_context, file_list);
1281 up(&file->mutex); 1282 up(&file->mutex);
1282 1283
1283 down(&ctx_id_mutex); 1284 mutex_lock(&ctx_id_mutex);
1284 idr_remove(&ctx_id_table, ctx->id); 1285 idr_remove(&ctx_id_table, ctx->id);
1285 up(&ctx_id_mutex); 1286 mutex_unlock(&ctx_id_mutex);
1286 1287
1287 ib_destroy_cm_id(ctx->cm_id); 1288 ib_destroy_cm_id(ctx->cm_id);
1288 ib_ucm_cleanup_events(ctx); 1289 ib_ucm_cleanup_events(ctx);
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index 7114e3fbab00..f7eecbc6af6c 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -41,6 +41,7 @@
41 41
42#include <linux/kref.h> 42#include <linux/kref.h>
43#include <linux/idr.h> 43#include <linux/idr.h>
44#include <linux/mutex.h>
44 45
45#include <rdma/ib_verbs.h> 46#include <rdma/ib_verbs.h>
46#include <rdma/ib_user_verbs.h> 47#include <rdma/ib_user_verbs.h>
@@ -88,7 +89,7 @@ struct ib_uverbs_event_file {
88 89
89struct ib_uverbs_file { 90struct ib_uverbs_file {
90 struct kref ref; 91 struct kref ref;
91 struct semaphore mutex; 92 struct mutex mutex;
92 struct ib_uverbs_device *device; 93 struct ib_uverbs_device *device;
93 struct ib_ucontext *ucontext; 94 struct ib_ucontext *ucontext;
94 struct ib_event_handler event_handler; 95 struct ib_event_handler event_handler;
@@ -131,7 +132,7 @@ struct ib_ucq_object {
131 u32 async_events_reported; 132 u32 async_events_reported;
132}; 133};
133 134
134extern struct semaphore ib_uverbs_idr_mutex; 135extern struct mutex ib_uverbs_idr_mutex;
135extern struct idr ib_uverbs_pd_idr; 136extern struct idr ib_uverbs_pd_idr;
136extern struct idr ib_uverbs_mr_idr; 137extern struct idr ib_uverbs_mr_idr;
137extern struct idr ib_uverbs_mw_idr; 138extern struct idr ib_uverbs_mw_idr;
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index a02c5a05c984..407b6284d7d5 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -67,7 +67,7 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
67 if (copy_from_user(&cmd, buf, sizeof cmd)) 67 if (copy_from_user(&cmd, buf, sizeof cmd))
68 return -EFAULT; 68 return -EFAULT;
69 69
70 down(&file->mutex); 70 mutex_lock(&file->mutex);
71 71
72 if (file->ucontext) { 72 if (file->ucontext) {
73 ret = -EINVAL; 73 ret = -EINVAL;
@@ -119,7 +119,7 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
119 119
120 fd_install(resp.async_fd, filp); 120 fd_install(resp.async_fd, filp);
121 121
122 up(&file->mutex); 122 mutex_unlock(&file->mutex);
123 123
124 return in_len; 124 return in_len;
125 125
@@ -131,7 +131,7 @@ err_free:
131 ibdev->dealloc_ucontext(ucontext); 131 ibdev->dealloc_ucontext(ucontext);
132 132
133err: 133err:
134 up(&file->mutex); 134 mutex_unlock(&file->mutex);
135 return ret; 135 return ret;
136} 136}
137 137
@@ -157,7 +157,7 @@ ssize_t ib_uverbs_query_device(struct ib_uverbs_file *file,
157 memset(&resp, 0, sizeof resp); 157 memset(&resp, 0, sizeof resp);
158 158
159 resp.fw_ver = attr.fw_ver; 159 resp.fw_ver = attr.fw_ver;
160 resp.node_guid = attr.node_guid; 160 resp.node_guid = file->device->ib_dev->node_guid;
161 resp.sys_image_guid = attr.sys_image_guid; 161 resp.sys_image_guid = attr.sys_image_guid;
162 resp.max_mr_size = attr.max_mr_size; 162 resp.max_mr_size = attr.max_mr_size;
163 resp.page_size_cap = attr.page_size_cap; 163 resp.page_size_cap = attr.page_size_cap;
@@ -290,7 +290,7 @@ ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file,
290 pd->uobject = uobj; 290 pd->uobject = uobj;
291 atomic_set(&pd->usecnt, 0); 291 atomic_set(&pd->usecnt, 0);
292 292
293 down(&ib_uverbs_idr_mutex); 293 mutex_lock(&ib_uverbs_idr_mutex);
294 294
295retry: 295retry:
296 if (!idr_pre_get(&ib_uverbs_pd_idr, GFP_KERNEL)) { 296 if (!idr_pre_get(&ib_uverbs_pd_idr, GFP_KERNEL)) {
@@ -314,11 +314,11 @@ retry:
314 goto err_idr; 314 goto err_idr;
315 } 315 }
316 316
317 down(&file->mutex); 317 mutex_lock(&file->mutex);
318 list_add_tail(&uobj->list, &file->ucontext->pd_list); 318 list_add_tail(&uobj->list, &file->ucontext->pd_list);
319 up(&file->mutex); 319 mutex_unlock(&file->mutex);
320 320
321 up(&ib_uverbs_idr_mutex); 321 mutex_unlock(&ib_uverbs_idr_mutex);
322 322
323 return in_len; 323 return in_len;
324 324
@@ -326,7 +326,7 @@ err_idr:
326 idr_remove(&ib_uverbs_pd_idr, uobj->id); 326 idr_remove(&ib_uverbs_pd_idr, uobj->id);
327 327
328err_up: 328err_up:
329 up(&ib_uverbs_idr_mutex); 329 mutex_unlock(&ib_uverbs_idr_mutex);
330 ib_dealloc_pd(pd); 330 ib_dealloc_pd(pd);
331 331
332err: 332err:
@@ -346,7 +346,7 @@ ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file,
346 if (copy_from_user(&cmd, buf, sizeof cmd)) 346 if (copy_from_user(&cmd, buf, sizeof cmd))
347 return -EFAULT; 347 return -EFAULT;
348 348
349 down(&ib_uverbs_idr_mutex); 349 mutex_lock(&ib_uverbs_idr_mutex);
350 350
351 pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); 351 pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
352 if (!pd || pd->uobject->context != file->ucontext) 352 if (!pd || pd->uobject->context != file->ucontext)
@@ -360,14 +360,14 @@ ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file,
360 360
361 idr_remove(&ib_uverbs_pd_idr, cmd.pd_handle); 361 idr_remove(&ib_uverbs_pd_idr, cmd.pd_handle);
362 362
363 down(&file->mutex); 363 mutex_lock(&file->mutex);
364 list_del(&uobj->list); 364 list_del(&uobj->list);
365 up(&file->mutex); 365 mutex_unlock(&file->mutex);
366 366
367 kfree(uobj); 367 kfree(uobj);
368 368
369out: 369out:
370 up(&ib_uverbs_idr_mutex); 370 mutex_unlock(&ib_uverbs_idr_mutex);
371 371
372 return ret ? ret : in_len; 372 return ret ? ret : in_len;
373} 373}
@@ -426,7 +426,7 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
426 426
427 obj->umem.virt_base = cmd.hca_va; 427 obj->umem.virt_base = cmd.hca_va;
428 428
429 down(&ib_uverbs_idr_mutex); 429 mutex_lock(&ib_uverbs_idr_mutex);
430 430
431 pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); 431 pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
432 if (!pd || pd->uobject->context != file->ucontext) { 432 if (!pd || pd->uobject->context != file->ucontext) {
@@ -476,11 +476,11 @@ retry:
476 goto err_idr; 476 goto err_idr;
477 } 477 }
478 478
479 down(&file->mutex); 479 mutex_lock(&file->mutex);
480 list_add_tail(&obj->uobject.list, &file->ucontext->mr_list); 480 list_add_tail(&obj->uobject.list, &file->ucontext->mr_list);
481 up(&file->mutex); 481 mutex_unlock(&file->mutex);
482 482
483 up(&ib_uverbs_idr_mutex); 483 mutex_unlock(&ib_uverbs_idr_mutex);
484 484
485 return in_len; 485 return in_len;
486 486
@@ -492,7 +492,7 @@ err_unreg:
492 atomic_dec(&pd->usecnt); 492 atomic_dec(&pd->usecnt);
493 493
494err_up: 494err_up:
495 up(&ib_uverbs_idr_mutex); 495 mutex_unlock(&ib_uverbs_idr_mutex);
496 496
497 ib_umem_release(file->device->ib_dev, &obj->umem); 497 ib_umem_release(file->device->ib_dev, &obj->umem);
498 498
@@ -513,7 +513,7 @@ ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file,
513 if (copy_from_user(&cmd, buf, sizeof cmd)) 513 if (copy_from_user(&cmd, buf, sizeof cmd))
514 return -EFAULT; 514 return -EFAULT;
515 515
516 down(&ib_uverbs_idr_mutex); 516 mutex_lock(&ib_uverbs_idr_mutex);
517 517
518 mr = idr_find(&ib_uverbs_mr_idr, cmd.mr_handle); 518 mr = idr_find(&ib_uverbs_mr_idr, cmd.mr_handle);
519 if (!mr || mr->uobject->context != file->ucontext) 519 if (!mr || mr->uobject->context != file->ucontext)
@@ -527,15 +527,15 @@ ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file,
527 527
528 idr_remove(&ib_uverbs_mr_idr, cmd.mr_handle); 528 idr_remove(&ib_uverbs_mr_idr, cmd.mr_handle);
529 529
530 down(&file->mutex); 530 mutex_lock(&file->mutex);
531 list_del(&memobj->uobject.list); 531 list_del(&memobj->uobject.list);
532 up(&file->mutex); 532 mutex_unlock(&file->mutex);
533 533
534 ib_umem_release(file->device->ib_dev, &memobj->umem); 534 ib_umem_release(file->device->ib_dev, &memobj->umem);
535 kfree(memobj); 535 kfree(memobj);
536 536
537out: 537out:
538 up(&ib_uverbs_idr_mutex); 538 mutex_unlock(&ib_uverbs_idr_mutex);
539 539
540 return ret ? ret : in_len; 540 return ret ? ret : in_len;
541} 541}
@@ -628,7 +628,7 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
628 cq->cq_context = ev_file; 628 cq->cq_context = ev_file;
629 atomic_set(&cq->usecnt, 0); 629 atomic_set(&cq->usecnt, 0);
630 630
631 down(&ib_uverbs_idr_mutex); 631 mutex_lock(&ib_uverbs_idr_mutex);
632 632
633retry: 633retry:
634 if (!idr_pre_get(&ib_uverbs_cq_idr, GFP_KERNEL)) { 634 if (!idr_pre_get(&ib_uverbs_cq_idr, GFP_KERNEL)) {
@@ -653,11 +653,11 @@ retry:
653 goto err_idr; 653 goto err_idr;
654 } 654 }
655 655
656 down(&file->mutex); 656 mutex_lock(&file->mutex);
657 list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list); 657 list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list);
658 up(&file->mutex); 658 mutex_unlock(&file->mutex);
659 659
660 up(&ib_uverbs_idr_mutex); 660 mutex_unlock(&ib_uverbs_idr_mutex);
661 661
662 return in_len; 662 return in_len;
663 663
@@ -665,7 +665,7 @@ err_idr:
665 idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id); 665 idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id);
666 666
667err_up: 667err_up:
668 up(&ib_uverbs_idr_mutex); 668 mutex_unlock(&ib_uverbs_idr_mutex);
669 ib_destroy_cq(cq); 669 ib_destroy_cq(cq);
670 670
671err: 671err:
@@ -701,7 +701,7 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,
701 goto out_wc; 701 goto out_wc;
702 } 702 }
703 703
704 down(&ib_uverbs_idr_mutex); 704 mutex_lock(&ib_uverbs_idr_mutex);
705 cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); 705 cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle);
706 if (!cq || cq->uobject->context != file->ucontext) { 706 if (!cq || cq->uobject->context != file->ucontext) {
707 ret = -EINVAL; 707 ret = -EINVAL;
@@ -731,7 +731,7 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,
731 ret = -EFAULT; 731 ret = -EFAULT;
732 732
733out: 733out:
734 up(&ib_uverbs_idr_mutex); 734 mutex_unlock(&ib_uverbs_idr_mutex);
735 kfree(resp); 735 kfree(resp);
736 736
737out_wc: 737out_wc:
@@ -750,14 +750,14 @@ ssize_t ib_uverbs_req_notify_cq(struct ib_uverbs_file *file,
750 if (copy_from_user(&cmd, buf, sizeof cmd)) 750 if (copy_from_user(&cmd, buf, sizeof cmd))
751 return -EFAULT; 751 return -EFAULT;
752 752
753 down(&ib_uverbs_idr_mutex); 753 mutex_lock(&ib_uverbs_idr_mutex);
754 cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); 754 cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle);
755 if (cq && cq->uobject->context == file->ucontext) { 755 if (cq && cq->uobject->context == file->ucontext) {
756 ib_req_notify_cq(cq, cmd.solicited_only ? 756 ib_req_notify_cq(cq, cmd.solicited_only ?
757 IB_CQ_SOLICITED : IB_CQ_NEXT_COMP); 757 IB_CQ_SOLICITED : IB_CQ_NEXT_COMP);
758 ret = in_len; 758 ret = in_len;
759 } 759 }
760 up(&ib_uverbs_idr_mutex); 760 mutex_unlock(&ib_uverbs_idr_mutex);
761 761
762 return ret; 762 return ret;
763} 763}
@@ -779,7 +779,7 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
779 779
780 memset(&resp, 0, sizeof resp); 780 memset(&resp, 0, sizeof resp);
781 781
782 down(&ib_uverbs_idr_mutex); 782 mutex_lock(&ib_uverbs_idr_mutex);
783 783
784 cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); 784 cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle);
785 if (!cq || cq->uobject->context != file->ucontext) 785 if (!cq || cq->uobject->context != file->ucontext)
@@ -795,9 +795,9 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
795 795
796 idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle); 796 idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle);
797 797
798 down(&file->mutex); 798 mutex_lock(&file->mutex);
799 list_del(&uobj->uobject.list); 799 list_del(&uobj->uobject.list);
800 up(&file->mutex); 800 mutex_unlock(&file->mutex);
801 801
802 ib_uverbs_release_ucq(file, ev_file, uobj); 802 ib_uverbs_release_ucq(file, ev_file, uobj);
803 803
@@ -811,7 +811,7 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
811 ret = -EFAULT; 811 ret = -EFAULT;
812 812
813out: 813out:
814 up(&ib_uverbs_idr_mutex); 814 mutex_unlock(&ib_uverbs_idr_mutex);
815 815
816 return ret ? ret : in_len; 816 return ret ? ret : in_len;
817} 817}
@@ -845,7 +845,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
845 if (!uobj) 845 if (!uobj)
846 return -ENOMEM; 846 return -ENOMEM;
847 847
848 down(&ib_uverbs_idr_mutex); 848 mutex_lock(&ib_uverbs_idr_mutex);
849 849
850 pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); 850 pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
851 scq = idr_find(&ib_uverbs_cq_idr, cmd.send_cq_handle); 851 scq = idr_find(&ib_uverbs_cq_idr, cmd.send_cq_handle);
@@ -930,11 +930,11 @@ retry:
930 goto err_idr; 930 goto err_idr;
931 } 931 }
932 932
933 down(&file->mutex); 933 mutex_lock(&file->mutex);
934 list_add_tail(&uobj->uevent.uobject.list, &file->ucontext->qp_list); 934 list_add_tail(&uobj->uevent.uobject.list, &file->ucontext->qp_list);
935 up(&file->mutex); 935 mutex_unlock(&file->mutex);
936 936
937 up(&ib_uverbs_idr_mutex); 937 mutex_unlock(&ib_uverbs_idr_mutex);
938 938
939 return in_len; 939 return in_len;
940 940
@@ -950,7 +950,7 @@ err_destroy:
950 atomic_dec(&attr.srq->usecnt); 950 atomic_dec(&attr.srq->usecnt);
951 951
952err_up: 952err_up:
953 up(&ib_uverbs_idr_mutex); 953 mutex_unlock(&ib_uverbs_idr_mutex);
954 954
955 kfree(uobj); 955 kfree(uobj);
956 return ret; 956 return ret;
@@ -972,7 +972,7 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
972 if (!attr) 972 if (!attr)
973 return -ENOMEM; 973 return -ENOMEM;
974 974
975 down(&ib_uverbs_idr_mutex); 975 mutex_lock(&ib_uverbs_idr_mutex);
976 976
977 qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); 977 qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
978 if (!qp || qp->uobject->context != file->ucontext) { 978 if (!qp || qp->uobject->context != file->ucontext) {
@@ -1033,7 +1033,7 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
1033 ret = in_len; 1033 ret = in_len;
1034 1034
1035out: 1035out:
1036 up(&ib_uverbs_idr_mutex); 1036 mutex_unlock(&ib_uverbs_idr_mutex);
1037 kfree(attr); 1037 kfree(attr);
1038 1038
1039 return ret; 1039 return ret;
@@ -1054,7 +1054,7 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
1054 1054
1055 memset(&resp, 0, sizeof resp); 1055 memset(&resp, 0, sizeof resp);
1056 1056
1057 down(&ib_uverbs_idr_mutex); 1057 mutex_lock(&ib_uverbs_idr_mutex);
1058 1058
1059 qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); 1059 qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
1060 if (!qp || qp->uobject->context != file->ucontext) 1060 if (!qp || qp->uobject->context != file->ucontext)
@@ -1073,9 +1073,9 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
1073 1073
1074 idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle); 1074 idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle);
1075 1075
1076 down(&file->mutex); 1076 mutex_lock(&file->mutex);
1077 list_del(&uobj->uevent.uobject.list); 1077 list_del(&uobj->uevent.uobject.list);
1078 up(&file->mutex); 1078 mutex_unlock(&file->mutex);
1079 1079
1080 ib_uverbs_release_uevent(file, &uobj->uevent); 1080 ib_uverbs_release_uevent(file, &uobj->uevent);
1081 1081
@@ -1088,7 +1088,7 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
1088 ret = -EFAULT; 1088 ret = -EFAULT;
1089 1089
1090out: 1090out:
1091 up(&ib_uverbs_idr_mutex); 1091 mutex_unlock(&ib_uverbs_idr_mutex);
1092 1092
1093 return ret ? ret : in_len; 1093 return ret ? ret : in_len;
1094} 1094}
@@ -1119,7 +1119,7 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
1119 if (!user_wr) 1119 if (!user_wr)
1120 return -ENOMEM; 1120 return -ENOMEM;
1121 1121
1122 down(&ib_uverbs_idr_mutex); 1122 mutex_lock(&ib_uverbs_idr_mutex);
1123 1123
1124 qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); 1124 qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
1125 if (!qp || qp->uobject->context != file->ucontext) 1125 if (!qp || qp->uobject->context != file->ucontext)
@@ -1224,7 +1224,7 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
1224 ret = -EFAULT; 1224 ret = -EFAULT;
1225 1225
1226out: 1226out:
1227 up(&ib_uverbs_idr_mutex); 1227 mutex_unlock(&ib_uverbs_idr_mutex);
1228 1228
1229 while (wr) { 1229 while (wr) {
1230 next = wr->next; 1230 next = wr->next;
@@ -1341,7 +1341,7 @@ ssize_t ib_uverbs_post_recv(struct ib_uverbs_file *file,
1341 if (IS_ERR(wr)) 1341 if (IS_ERR(wr))
1342 return PTR_ERR(wr); 1342 return PTR_ERR(wr);
1343 1343
1344 down(&ib_uverbs_idr_mutex); 1344 mutex_lock(&ib_uverbs_idr_mutex);
1345 1345
1346 qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); 1346 qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
1347 if (!qp || qp->uobject->context != file->ucontext) 1347 if (!qp || qp->uobject->context != file->ucontext)
@@ -1362,7 +1362,7 @@ ssize_t ib_uverbs_post_recv(struct ib_uverbs_file *file,
1362 ret = -EFAULT; 1362 ret = -EFAULT;
1363 1363
1364out: 1364out:
1365 up(&ib_uverbs_idr_mutex); 1365 mutex_unlock(&ib_uverbs_idr_mutex);
1366 1366
1367 while (wr) { 1367 while (wr) {
1368 next = wr->next; 1368 next = wr->next;
@@ -1392,7 +1392,7 @@ ssize_t ib_uverbs_post_srq_recv(struct ib_uverbs_file *file,
1392 if (IS_ERR(wr)) 1392 if (IS_ERR(wr))
1393 return PTR_ERR(wr); 1393 return PTR_ERR(wr);
1394 1394
1395 down(&ib_uverbs_idr_mutex); 1395 mutex_lock(&ib_uverbs_idr_mutex);
1396 1396
1397 srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); 1397 srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
1398 if (!srq || srq->uobject->context != file->ucontext) 1398 if (!srq || srq->uobject->context != file->ucontext)
@@ -1413,7 +1413,7 @@ ssize_t ib_uverbs_post_srq_recv(struct ib_uverbs_file *file,
1413 ret = -EFAULT; 1413 ret = -EFAULT;
1414 1414
1415out: 1415out:
1416 up(&ib_uverbs_idr_mutex); 1416 mutex_unlock(&ib_uverbs_idr_mutex);
1417 1417
1418 while (wr) { 1418 while (wr) {
1419 next = wr->next; 1419 next = wr->next;
@@ -1446,7 +1446,7 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file,
1446 if (!uobj) 1446 if (!uobj)
1447 return -ENOMEM; 1447 return -ENOMEM;
1448 1448
1449 down(&ib_uverbs_idr_mutex); 1449 mutex_lock(&ib_uverbs_idr_mutex);
1450 1450
1451 pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); 1451 pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
1452 if (!pd || pd->uobject->context != file->ucontext) { 1452 if (!pd || pd->uobject->context != file->ucontext) {
@@ -1498,11 +1498,11 @@ retry:
1498 goto err_idr; 1498 goto err_idr;
1499 } 1499 }
1500 1500
1501 down(&file->mutex); 1501 mutex_lock(&file->mutex);
1502 list_add_tail(&uobj->list, &file->ucontext->ah_list); 1502 list_add_tail(&uobj->list, &file->ucontext->ah_list);
1503 up(&file->mutex); 1503 mutex_unlock(&file->mutex);
1504 1504
1505 up(&ib_uverbs_idr_mutex); 1505 mutex_unlock(&ib_uverbs_idr_mutex);
1506 1506
1507 return in_len; 1507 return in_len;
1508 1508
@@ -1513,7 +1513,7 @@ err_destroy:
1513 ib_destroy_ah(ah); 1513 ib_destroy_ah(ah);
1514 1514
1515err_up: 1515err_up:
1516 up(&ib_uverbs_idr_mutex); 1516 mutex_unlock(&ib_uverbs_idr_mutex);
1517 1517
1518 kfree(uobj); 1518 kfree(uobj);
1519 return ret; 1519 return ret;
@@ -1530,7 +1530,7 @@ ssize_t ib_uverbs_destroy_ah(struct ib_uverbs_file *file,
1530 if (copy_from_user(&cmd, buf, sizeof cmd)) 1530 if (copy_from_user(&cmd, buf, sizeof cmd))
1531 return -EFAULT; 1531 return -EFAULT;
1532 1532
1533 down(&ib_uverbs_idr_mutex); 1533 mutex_lock(&ib_uverbs_idr_mutex);
1534 1534
1535 ah = idr_find(&ib_uverbs_ah_idr, cmd.ah_handle); 1535 ah = idr_find(&ib_uverbs_ah_idr, cmd.ah_handle);
1536 if (!ah || ah->uobject->context != file->ucontext) 1536 if (!ah || ah->uobject->context != file->ucontext)
@@ -1544,14 +1544,14 @@ ssize_t ib_uverbs_destroy_ah(struct ib_uverbs_file *file,
1544 1544
1545 idr_remove(&ib_uverbs_ah_idr, cmd.ah_handle); 1545 idr_remove(&ib_uverbs_ah_idr, cmd.ah_handle);
1546 1546
1547 down(&file->mutex); 1547 mutex_lock(&file->mutex);
1548 list_del(&uobj->list); 1548 list_del(&uobj->list);
1549 up(&file->mutex); 1549 mutex_unlock(&file->mutex);
1550 1550
1551 kfree(uobj); 1551 kfree(uobj);
1552 1552
1553out: 1553out:
1554 up(&ib_uverbs_idr_mutex); 1554 mutex_unlock(&ib_uverbs_idr_mutex);
1555 1555
1556 return ret ? ret : in_len; 1556 return ret ? ret : in_len;
1557} 1557}
@@ -1569,7 +1569,7 @@ ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file,
1569 if (copy_from_user(&cmd, buf, sizeof cmd)) 1569 if (copy_from_user(&cmd, buf, sizeof cmd))
1570 return -EFAULT; 1570 return -EFAULT;
1571 1571
1572 down(&ib_uverbs_idr_mutex); 1572 mutex_lock(&ib_uverbs_idr_mutex);
1573 1573
1574 qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); 1574 qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
1575 if (!qp || qp->uobject->context != file->ucontext) 1575 if (!qp || qp->uobject->context != file->ucontext)
@@ -1602,7 +1602,7 @@ ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file,
1602 kfree(mcast); 1602 kfree(mcast);
1603 1603
1604out: 1604out:
1605 up(&ib_uverbs_idr_mutex); 1605 mutex_unlock(&ib_uverbs_idr_mutex);
1606 1606
1607 return ret ? ret : in_len; 1607 return ret ? ret : in_len;
1608} 1608}
@@ -1620,7 +1620,7 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file,
1620 if (copy_from_user(&cmd, buf, sizeof cmd)) 1620 if (copy_from_user(&cmd, buf, sizeof cmd))
1621 return -EFAULT; 1621 return -EFAULT;
1622 1622
1623 down(&ib_uverbs_idr_mutex); 1623 mutex_lock(&ib_uverbs_idr_mutex);
1624 1624
1625 qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); 1625 qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
1626 if (!qp || qp->uobject->context != file->ucontext) 1626 if (!qp || qp->uobject->context != file->ucontext)
@@ -1641,7 +1641,7 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file,
1641 } 1641 }
1642 1642
1643out: 1643out:
1644 up(&ib_uverbs_idr_mutex); 1644 mutex_unlock(&ib_uverbs_idr_mutex);
1645 1645
1646 return ret ? ret : in_len; 1646 return ret ? ret : in_len;
1647} 1647}
@@ -1673,7 +1673,7 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
1673 if (!uobj) 1673 if (!uobj)
1674 return -ENOMEM; 1674 return -ENOMEM;
1675 1675
1676 down(&ib_uverbs_idr_mutex); 1676 mutex_lock(&ib_uverbs_idr_mutex);
1677 1677
1678 pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); 1678 pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
1679 1679
@@ -1730,11 +1730,11 @@ retry:
1730 goto err_idr; 1730 goto err_idr;
1731 } 1731 }
1732 1732
1733 down(&file->mutex); 1733 mutex_lock(&file->mutex);
1734 list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list); 1734 list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list);
1735 up(&file->mutex); 1735 mutex_unlock(&file->mutex);
1736 1736
1737 up(&ib_uverbs_idr_mutex); 1737 mutex_unlock(&ib_uverbs_idr_mutex);
1738 1738
1739 return in_len; 1739 return in_len;
1740 1740
@@ -1746,7 +1746,7 @@ err_destroy:
1746 atomic_dec(&pd->usecnt); 1746 atomic_dec(&pd->usecnt);
1747 1747
1748err_up: 1748err_up:
1749 up(&ib_uverbs_idr_mutex); 1749 mutex_unlock(&ib_uverbs_idr_mutex);
1750 1750
1751 kfree(uobj); 1751 kfree(uobj);
1752 return ret; 1752 return ret;
@@ -1764,7 +1764,7 @@ ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file,
1764 if (copy_from_user(&cmd, buf, sizeof cmd)) 1764 if (copy_from_user(&cmd, buf, sizeof cmd))
1765 return -EFAULT; 1765 return -EFAULT;
1766 1766
1767 down(&ib_uverbs_idr_mutex); 1767 mutex_lock(&ib_uverbs_idr_mutex);
1768 1768
1769 srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); 1769 srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
1770 if (!srq || srq->uobject->context != file->ucontext) { 1770 if (!srq || srq->uobject->context != file->ucontext) {
@@ -1778,7 +1778,7 @@ ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file,
1778 ret = ib_modify_srq(srq, &attr, cmd.attr_mask); 1778 ret = ib_modify_srq(srq, &attr, cmd.attr_mask);
1779 1779
1780out: 1780out:
1781 up(&ib_uverbs_idr_mutex); 1781 mutex_unlock(&ib_uverbs_idr_mutex);
1782 1782
1783 return ret ? ret : in_len; 1783 return ret ? ret : in_len;
1784} 1784}
@@ -1796,7 +1796,7 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
1796 if (copy_from_user(&cmd, buf, sizeof cmd)) 1796 if (copy_from_user(&cmd, buf, sizeof cmd))
1797 return -EFAULT; 1797 return -EFAULT;
1798 1798
1799 down(&ib_uverbs_idr_mutex); 1799 mutex_lock(&ib_uverbs_idr_mutex);
1800 1800
1801 memset(&resp, 0, sizeof resp); 1801 memset(&resp, 0, sizeof resp);
1802 1802
@@ -1812,9 +1812,9 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
1812 1812
1813 idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle); 1813 idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle);
1814 1814
1815 down(&file->mutex); 1815 mutex_lock(&file->mutex);
1816 list_del(&uobj->uobject.list); 1816 list_del(&uobj->uobject.list);
1817 up(&file->mutex); 1817 mutex_unlock(&file->mutex);
1818 1818
1819 ib_uverbs_release_uevent(file, uobj); 1819 ib_uverbs_release_uevent(file, uobj);
1820 1820
@@ -1827,7 +1827,7 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
1827 ret = -EFAULT; 1827 ret = -EFAULT;
1828 1828
1829out: 1829out:
1830 up(&ib_uverbs_idr_mutex); 1830 mutex_unlock(&ib_uverbs_idr_mutex);
1831 1831
1832 return ret ? ret : in_len; 1832 return ret ? ret : in_len;
1833} 1833}
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 81737bd6faea..96ea79b63df7 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -66,7 +66,7 @@ enum {
66 66
67static struct class *uverbs_class; 67static struct class *uverbs_class;
68 68
69DECLARE_MUTEX(ib_uverbs_idr_mutex); 69DEFINE_MUTEX(ib_uverbs_idr_mutex);
70DEFINE_IDR(ib_uverbs_pd_idr); 70DEFINE_IDR(ib_uverbs_pd_idr);
71DEFINE_IDR(ib_uverbs_mr_idr); 71DEFINE_IDR(ib_uverbs_mr_idr);
72DEFINE_IDR(ib_uverbs_mw_idr); 72DEFINE_IDR(ib_uverbs_mw_idr);
@@ -180,7 +180,7 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
180 if (!context) 180 if (!context)
181 return 0; 181 return 0;
182 182
183 down(&ib_uverbs_idr_mutex); 183 mutex_lock(&ib_uverbs_idr_mutex);
184 184
185 list_for_each_entry_safe(uobj, tmp, &context->ah_list, list) { 185 list_for_each_entry_safe(uobj, tmp, &context->ah_list, list) {
186 struct ib_ah *ah = idr_find(&ib_uverbs_ah_idr, uobj->id); 186 struct ib_ah *ah = idr_find(&ib_uverbs_ah_idr, uobj->id);
@@ -250,7 +250,7 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
250 kfree(uobj); 250 kfree(uobj);
251 } 251 }
252 252
253 up(&ib_uverbs_idr_mutex); 253 mutex_unlock(&ib_uverbs_idr_mutex);
254 254
255 return context->device->dealloc_ucontext(context); 255 return context->device->dealloc_ucontext(context);
256} 256}
@@ -653,7 +653,7 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
653 file->ucontext = NULL; 653 file->ucontext = NULL;
654 file->async_file = NULL; 654 file->async_file = NULL;
655 kref_init(&file->ref); 655 kref_init(&file->ref);
656 init_MUTEX(&file->mutex); 656 mutex_init(&file->mutex);
657 657
658 filp->private_data = file; 658 filp->private_data = file;
659 659
diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c
index 22fdc446f25c..a14eed08a0fc 100644
--- a/drivers/infiniband/hw/mthca/mthca_av.c
+++ b/drivers/infiniband/hw/mthca/mthca_av.c
@@ -163,6 +163,11 @@ int mthca_destroy_ah(struct mthca_dev *dev, struct mthca_ah *ah)
163 return 0; 163 return 0;
164} 164}
165 165
166int mthca_ah_grh_present(struct mthca_ah *ah)
167{
168 return !!(ah->av->g_slid & 0x80);
169}
170
166int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah, 171int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah,
167 struct ib_ud_header *header) 172 struct ib_ud_header *header)
168{ 173{
@@ -172,8 +177,7 @@ int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah,
172 header->lrh.service_level = be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 28; 177 header->lrh.service_level = be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 28;
173 header->lrh.destination_lid = ah->av->dlid; 178 header->lrh.destination_lid = ah->av->dlid;
174 header->lrh.source_lid = cpu_to_be16(ah->av->g_slid & 0x7f); 179 header->lrh.source_lid = cpu_to_be16(ah->av->g_slid & 0x7f);
175 if (ah->av->g_slid & 0x80) { 180 if (mthca_ah_grh_present(ah)) {
176 header->grh_present = 1;
177 header->grh.traffic_class = 181 header->grh.traffic_class =
178 (be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 20) & 0xff; 182 (be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 20) & 0xff;
179 header->grh.flow_label = 183 header->grh.flow_label =
@@ -184,8 +188,6 @@ int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah,
184 &header->grh.source_gid); 188 &header->grh.source_gid);
185 memcpy(header->grh.destination_gid.raw, 189 memcpy(header->grh.destination_gid.raw,
186 ah->av->dgid, 16); 190 ah->av->dgid, 16);
187 } else {
188 header->grh_present = 0;
189 } 191 }
190 192
191 return 0; 193 return 0;
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c
index 22ac72bc20c3..be1791be627b 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -606,7 +606,7 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm,
606 err = -EINVAL; 606 err = -EINVAL;
607 goto out; 607 goto out;
608 } 608 }
609 for (i = 0; i < mthca_icm_size(&iter) / (1 << lg); ++i) { 609 for (i = 0; i < mthca_icm_size(&iter) >> lg; ++i) {
610 if (virt != -1) { 610 if (virt != -1) {
611 pages[nent * 2] = cpu_to_be64(virt); 611 pages[nent * 2] = cpu_to_be64(virt);
612 virt += 1 << lg; 612 virt += 1 << lg;
@@ -727,8 +727,8 @@ int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status)
727 * system pages needed. 727 * system pages needed.
728 */ 728 */
729 dev->fw.arbel.fw_pages = 729 dev->fw.arbel.fw_pages =
730 (dev->fw.arbel.fw_pages + (1 << (PAGE_SHIFT - 12)) - 1) >> 730 ALIGN(dev->fw.arbel.fw_pages, PAGE_SIZE >> 12) >>
731 (PAGE_SHIFT - 12); 731 (PAGE_SHIFT - 12);
732 732
733 mthca_dbg(dev, "Clear int @ %llx, EQ arm @ %llx, EQ set CI @ %llx\n", 733 mthca_dbg(dev, "Clear int @ %llx, EQ arm @ %llx, EQ set CI @ %llx\n",
734 (unsigned long long) dev->fw.arbel.clr_int_base, 734 (unsigned long long) dev->fw.arbel.clr_int_base,
@@ -1445,6 +1445,7 @@ int mthca_SET_ICM_SIZE(struct mthca_dev *dev, u64 icm_size, u64 *aux_pages,
1445 * pages needed. 1445 * pages needed.
1446 */ 1446 */
1447 *aux_pages = (*aux_pages + (1 << (PAGE_SHIFT - 12)) - 1) >> (PAGE_SHIFT - 12); 1447 *aux_pages = (*aux_pages + (1 << (PAGE_SHIFT - 12)) - 1) >> (PAGE_SHIFT - 12);
1448 *aux_pages = ALIGN(*aux_pages, PAGE_SIZE >> 12) >> (PAGE_SHIFT - 12);
1448 1449
1449 return 0; 1450 return 0;
1450} 1451}
diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h
index 795b379260bf..a104ab041ea3 100644
--- a/drivers/infiniband/hw/mthca/mthca_dev.h
+++ b/drivers/infiniband/hw/mthca/mthca_dev.h
@@ -520,6 +520,7 @@ int mthca_create_ah(struct mthca_dev *dev,
520int mthca_destroy_ah(struct mthca_dev *dev, struct mthca_ah *ah); 520int mthca_destroy_ah(struct mthca_dev *dev, struct mthca_ah *ah);
521int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah, 521int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah,
522 struct ib_ud_header *header); 522 struct ib_ud_header *header);
523int mthca_ah_grh_present(struct mthca_ah *ah);
523 524
524int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid); 525int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid);
525int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid); 526int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid);
diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c
index e8a948f087c0..2eabb27804cd 100644
--- a/drivers/infiniband/hw/mthca/mthca_eq.c
+++ b/drivers/infiniband/hw/mthca/mthca_eq.c
@@ -45,6 +45,7 @@
45enum { 45enum {
46 MTHCA_NUM_ASYNC_EQE = 0x80, 46 MTHCA_NUM_ASYNC_EQE = 0x80,
47 MTHCA_NUM_CMD_EQE = 0x80, 47 MTHCA_NUM_CMD_EQE = 0x80,
48 MTHCA_NUM_SPARE_EQE = 0x80,
48 MTHCA_EQ_ENTRY_SIZE = 0x20 49 MTHCA_EQ_ENTRY_SIZE = 0x20
49}; 50};
50 51
@@ -277,11 +278,10 @@ static int mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq)
277{ 278{
278 struct mthca_eqe *eqe; 279 struct mthca_eqe *eqe;
279 int disarm_cqn; 280 int disarm_cqn;
280 int eqes_found = 0; 281 int eqes_found = 0;
282 int set_ci = 0;
281 283
282 while ((eqe = next_eqe_sw(eq))) { 284 while ((eqe = next_eqe_sw(eq))) {
283 int set_ci = 0;
284
285 /* 285 /*
286 * Make sure we read EQ entry contents after we've 286 * Make sure we read EQ entry contents after we've
287 * checked the ownership bit. 287 * checked the ownership bit.
@@ -345,12 +345,6 @@ static int mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq)
345 be16_to_cpu(eqe->event.cmd.token), 345 be16_to_cpu(eqe->event.cmd.token),
346 eqe->event.cmd.status, 346 eqe->event.cmd.status,
347 be64_to_cpu(eqe->event.cmd.out_param)); 347 be64_to_cpu(eqe->event.cmd.out_param));
348 /*
349 * cmd_event() may add more commands.
350 * The card will think the queue has overflowed if
351 * we don't tell it we've been processing events.
352 */
353 set_ci = 1;
354 break; 348 break;
355 349
356 case MTHCA_EVENT_TYPE_PORT_CHANGE: 350 case MTHCA_EVENT_TYPE_PORT_CHANGE:
@@ -385,8 +379,16 @@ static int mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq)
385 set_eqe_hw(eqe); 379 set_eqe_hw(eqe);
386 ++eq->cons_index; 380 ++eq->cons_index;
387 eqes_found = 1; 381 eqes_found = 1;
382 ++set_ci;
388 383
389 if (unlikely(set_ci)) { 384 /*
385 * The HCA will think the queue has overflowed if we
386 * don't tell it we've been processing events. We
387 * create our EQs with MTHCA_NUM_SPARE_EQE extra
388 * entries, so we must update our consumer index at
389 * least that often.
390 */
391 if (unlikely(set_ci >= MTHCA_NUM_SPARE_EQE)) {
390 /* 392 /*
391 * Conditional on hca_type is OK here because 393 * Conditional on hca_type is OK here because
392 * this is a rare case, not the fast path. 394 * this is a rare case, not the fast path.
@@ -862,19 +864,19 @@ int __devinit mthca_init_eq_table(struct mthca_dev *dev)
862 intr = (dev->mthca_flags & MTHCA_FLAG_MSI) ? 864 intr = (dev->mthca_flags & MTHCA_FLAG_MSI) ?
863 128 : dev->eq_table.inta_pin; 865 128 : dev->eq_table.inta_pin;
864 866
865 err = mthca_create_eq(dev, dev->limits.num_cqs, 867 err = mthca_create_eq(dev, dev->limits.num_cqs + MTHCA_NUM_SPARE_EQE,
866 (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 128 : intr, 868 (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 128 : intr,
867 &dev->eq_table.eq[MTHCA_EQ_COMP]); 869 &dev->eq_table.eq[MTHCA_EQ_COMP]);
868 if (err) 870 if (err)
869 goto err_out_unmap; 871 goto err_out_unmap;
870 872
871 err = mthca_create_eq(dev, MTHCA_NUM_ASYNC_EQE, 873 err = mthca_create_eq(dev, MTHCA_NUM_ASYNC_EQE + MTHCA_NUM_SPARE_EQE,
872 (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 129 : intr, 874 (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 129 : intr,
873 &dev->eq_table.eq[MTHCA_EQ_ASYNC]); 875 &dev->eq_table.eq[MTHCA_EQ_ASYNC]);
874 if (err) 876 if (err)
875 goto err_out_comp; 877 goto err_out_comp;
876 878
877 err = mthca_create_eq(dev, MTHCA_NUM_CMD_EQE, 879 err = mthca_create_eq(dev, MTHCA_NUM_CMD_EQE + MTHCA_NUM_SPARE_EQE,
878 (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 130 : intr, 880 (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 130 : intr,
879 &dev->eq_table.eq[MTHCA_EQ_CMD]); 881 &dev->eq_table.eq[MTHCA_EQ_CMD]);
880 if (err) 882 if (err)
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index 4cc7e2846df1..484a7e6b7f8c 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -33,7 +33,7 @@
33 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 33 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
34 * SOFTWARE. 34 * SOFTWARE.
35 * 35 *
36 * $Id: mthca_provider.c 1397 2004-12-28 05:09:00Z roland $ 36 * $Id: mthca_provider.c 4859 2006-01-09 21:55:10Z roland $
37 */ 37 */
38 38
39#include <rdma/ib_smi.h> 39#include <rdma/ib_smi.h>
@@ -45,6 +45,14 @@
45#include "mthca_user.h" 45#include "mthca_user.h"
46#include "mthca_memfree.h" 46#include "mthca_memfree.h"
47 47
48static void init_query_mad(struct ib_smp *mad)
49{
50 mad->base_version = 1;
51 mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
52 mad->class_version = 1;
53 mad->method = IB_MGMT_METHOD_GET;
54}
55
48static int mthca_query_device(struct ib_device *ibdev, 56static int mthca_query_device(struct ib_device *ibdev,
49 struct ib_device_attr *props) 57 struct ib_device_attr *props)
50{ 58{
@@ -55,7 +63,7 @@ static int mthca_query_device(struct ib_device *ibdev,
55 63
56 u8 status; 64 u8 status;
57 65
58 in_mad = kmalloc(sizeof *in_mad, GFP_KERNEL); 66 in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL);
59 out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); 67 out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
60 if (!in_mad || !out_mad) 68 if (!in_mad || !out_mad)
61 goto out; 69 goto out;
@@ -64,12 +72,8 @@ static int mthca_query_device(struct ib_device *ibdev,
64 72
65 props->fw_ver = mdev->fw_ver; 73 props->fw_ver = mdev->fw_ver;
66 74
67 memset(in_mad, 0, sizeof *in_mad); 75 init_query_mad(in_mad);
68 in_mad->base_version = 1; 76 in_mad->attr_id = IB_SMP_ATTR_NODE_INFO;
69 in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
70 in_mad->class_version = 1;
71 in_mad->method = IB_MGMT_METHOD_GET;
72 in_mad->attr_id = IB_SMP_ATTR_NODE_INFO;
73 77
74 err = mthca_MAD_IFC(mdev, 1, 1, 78 err = mthca_MAD_IFC(mdev, 1, 1,
75 1, NULL, NULL, in_mad, out_mad, 79 1, NULL, NULL, in_mad, out_mad,
@@ -87,7 +91,6 @@ static int mthca_query_device(struct ib_device *ibdev,
87 props->vendor_part_id = be16_to_cpup((__be16 *) (out_mad->data + 30)); 91 props->vendor_part_id = be16_to_cpup((__be16 *) (out_mad->data + 30));
88 props->hw_ver = be32_to_cpup((__be32 *) (out_mad->data + 32)); 92 props->hw_ver = be32_to_cpup((__be32 *) (out_mad->data + 32));
89 memcpy(&props->sys_image_guid, out_mad->data + 4, 8); 93 memcpy(&props->sys_image_guid, out_mad->data + 4, 8);
90 memcpy(&props->node_guid, out_mad->data + 12, 8);
91 94
92 props->max_mr_size = ~0ull; 95 props->max_mr_size = ~0ull;
93 props->page_size_cap = mdev->limits.page_size_cap; 96 props->page_size_cap = mdev->limits.page_size_cap;
@@ -128,20 +131,16 @@ static int mthca_query_port(struct ib_device *ibdev,
128 int err = -ENOMEM; 131 int err = -ENOMEM;
129 u8 status; 132 u8 status;
130 133
131 in_mad = kmalloc(sizeof *in_mad, GFP_KERNEL); 134 in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL);
132 out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); 135 out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
133 if (!in_mad || !out_mad) 136 if (!in_mad || !out_mad)
134 goto out; 137 goto out;
135 138
136 memset(props, 0, sizeof *props); 139 memset(props, 0, sizeof *props);
137 140
138 memset(in_mad, 0, sizeof *in_mad); 141 init_query_mad(in_mad);
139 in_mad->base_version = 1; 142 in_mad->attr_id = IB_SMP_ATTR_PORT_INFO;
140 in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; 143 in_mad->attr_mod = cpu_to_be32(port);
141 in_mad->class_version = 1;
142 in_mad->method = IB_MGMT_METHOD_GET;
143 in_mad->attr_id = IB_SMP_ATTR_PORT_INFO;
144 in_mad->attr_mod = cpu_to_be32(port);
145 144
146 err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1, 145 err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1,
147 port, NULL, NULL, in_mad, out_mad, 146 port, NULL, NULL, in_mad, out_mad,
@@ -220,18 +219,14 @@ static int mthca_query_pkey(struct ib_device *ibdev,
220 int err = -ENOMEM; 219 int err = -ENOMEM;
221 u8 status; 220 u8 status;
222 221
223 in_mad = kmalloc(sizeof *in_mad, GFP_KERNEL); 222 in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL);
224 out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); 223 out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
225 if (!in_mad || !out_mad) 224 if (!in_mad || !out_mad)
226 goto out; 225 goto out;
227 226
228 memset(in_mad, 0, sizeof *in_mad); 227 init_query_mad(in_mad);
229 in_mad->base_version = 1; 228 in_mad->attr_id = IB_SMP_ATTR_PKEY_TABLE;
230 in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; 229 in_mad->attr_mod = cpu_to_be32(index / 32);
231 in_mad->class_version = 1;
232 in_mad->method = IB_MGMT_METHOD_GET;
233 in_mad->attr_id = IB_SMP_ATTR_PKEY_TABLE;
234 in_mad->attr_mod = cpu_to_be32(index / 32);
235 230
236 err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1, 231 err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1,
237 port, NULL, NULL, in_mad, out_mad, 232 port, NULL, NULL, in_mad, out_mad,
@@ -259,18 +254,14 @@ static int mthca_query_gid(struct ib_device *ibdev, u8 port,
259 int err = -ENOMEM; 254 int err = -ENOMEM;
260 u8 status; 255 u8 status;
261 256
262 in_mad = kmalloc(sizeof *in_mad, GFP_KERNEL); 257 in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL);
263 out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); 258 out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
264 if (!in_mad || !out_mad) 259 if (!in_mad || !out_mad)
265 goto out; 260 goto out;
266 261
267 memset(in_mad, 0, sizeof *in_mad); 262 init_query_mad(in_mad);
268 in_mad->base_version = 1; 263 in_mad->attr_id = IB_SMP_ATTR_PORT_INFO;
269 in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; 264 in_mad->attr_mod = cpu_to_be32(port);
270 in_mad->class_version = 1;
271 in_mad->method = IB_MGMT_METHOD_GET;
272 in_mad->attr_id = IB_SMP_ATTR_PORT_INFO;
273 in_mad->attr_mod = cpu_to_be32(port);
274 265
275 err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1, 266 err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1,
276 port, NULL, NULL, in_mad, out_mad, 267 port, NULL, NULL, in_mad, out_mad,
@@ -284,13 +275,9 @@ static int mthca_query_gid(struct ib_device *ibdev, u8 port,
284 275
285 memcpy(gid->raw, out_mad->data + 8, 8); 276 memcpy(gid->raw, out_mad->data + 8, 8);
286 277
287 memset(in_mad, 0, sizeof *in_mad); 278 init_query_mad(in_mad);
288 in_mad->base_version = 1; 279 in_mad->attr_id = IB_SMP_ATTR_GUID_INFO;
289 in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; 280 in_mad->attr_mod = cpu_to_be32(index / 8);
290 in_mad->class_version = 1;
291 in_mad->method = IB_MGMT_METHOD_GET;
292 in_mad->attr_id = IB_SMP_ATTR_GUID_INFO;
293 in_mad->attr_mod = cpu_to_be32(index / 8);
294 281
295 err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1, 282 err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1,
296 port, NULL, NULL, in_mad, out_mad, 283 port, NULL, NULL, in_mad, out_mad,
@@ -458,8 +445,10 @@ static struct ib_srq *mthca_create_srq(struct ib_pd *pd,
458 if (pd->uobject) { 445 if (pd->uobject) {
459 context = to_mucontext(pd->uobject->context); 446 context = to_mucontext(pd->uobject->context);
460 447
461 if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) 448 if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) {
462 return ERR_PTR(-EFAULT); 449 err = -EFAULT;
450 goto err_free;
451 }
463 452
464 err = mthca_map_user_db(to_mdev(pd->device), &context->uar, 453 err = mthca_map_user_db(to_mdev(pd->device), &context->uar,
465 context->db_tab, ucmd.db_index, 454 context->db_tab, ucmd.db_index,
@@ -535,8 +524,10 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
535 if (pd->uobject) { 524 if (pd->uobject) {
536 context = to_mucontext(pd->uobject->context); 525 context = to_mucontext(pd->uobject->context);
537 526
538 if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) 527 if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) {
528 kfree(qp);
539 return ERR_PTR(-EFAULT); 529 return ERR_PTR(-EFAULT);
530 }
540 531
541 err = mthca_map_user_db(to_mdev(pd->device), &context->uar, 532 err = mthca_map_user_db(to_mdev(pd->device), &context->uar,
542 context->db_tab, 533 context->db_tab,
@@ -783,24 +774,20 @@ static struct ib_mr *mthca_reg_phys_mr(struct ib_pd *pd,
783 if ((*iova_start & ~PAGE_MASK) != (buffer_list[0].addr & ~PAGE_MASK)) 774 if ((*iova_start & ~PAGE_MASK) != (buffer_list[0].addr & ~PAGE_MASK))
784 return ERR_PTR(-EINVAL); 775 return ERR_PTR(-EINVAL);
785 776
786 if (num_phys_buf > 1 &&
787 ((buffer_list[0].addr + buffer_list[0].size) & ~PAGE_MASK))
788 return ERR_PTR(-EINVAL);
789
790 mask = 0; 777 mask = 0;
791 total_size = 0; 778 total_size = 0;
792 for (i = 0; i < num_phys_buf; ++i) { 779 for (i = 0; i < num_phys_buf; ++i) {
793 if (i != 0 && buffer_list[i].addr & ~PAGE_MASK) 780 if (i != 0)
794 return ERR_PTR(-EINVAL); 781 mask |= buffer_list[i].addr;
795 if (i != 0 && i != num_phys_buf - 1 && 782 if (i != num_phys_buf - 1)
796 (buffer_list[i].size & ~PAGE_MASK)) 783 mask |= buffer_list[i].addr + buffer_list[i].size;
797 return ERR_PTR(-EINVAL);
798 784
799 total_size += buffer_list[i].size; 785 total_size += buffer_list[i].size;
800 if (i > 0)
801 mask |= buffer_list[i].addr;
802 } 786 }
803 787
788 if (mask & ~PAGE_MASK)
789 return ERR_PTR(-EINVAL);
790
804 /* Find largest page shift we can use to cover buffers */ 791 /* Find largest page shift we can use to cover buffers */
805 for (shift = PAGE_SHIFT; shift < 31; ++shift) 792 for (shift = PAGE_SHIFT; shift < 31; ++shift)
806 if (num_phys_buf > 1) { 793 if (num_phys_buf > 1) {
@@ -1070,11 +1057,48 @@ static struct class_device_attribute *mthca_class_attributes[] = {
1070 &class_device_attr_board_id 1057 &class_device_attr_board_id
1071}; 1058};
1072 1059
1060static int mthca_init_node_data(struct mthca_dev *dev)
1061{
1062 struct ib_smp *in_mad = NULL;
1063 struct ib_smp *out_mad = NULL;
1064 int err = -ENOMEM;
1065 u8 status;
1066
1067 in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL);
1068 out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
1069 if (!in_mad || !out_mad)
1070 goto out;
1071
1072 init_query_mad(in_mad);
1073 in_mad->attr_id = IB_SMP_ATTR_NODE_INFO;
1074
1075 err = mthca_MAD_IFC(dev, 1, 1,
1076 1, NULL, NULL, in_mad, out_mad,
1077 &status);
1078 if (err)
1079 goto out;
1080 if (status) {
1081 err = -EINVAL;
1082 goto out;
1083 }
1084
1085 memcpy(&dev->ib_dev.node_guid, out_mad->data + 12, 8);
1086
1087out:
1088 kfree(in_mad);
1089 kfree(out_mad);
1090 return err;
1091}
1092
1073int mthca_register_device(struct mthca_dev *dev) 1093int mthca_register_device(struct mthca_dev *dev)
1074{ 1094{
1075 int ret; 1095 int ret;
1076 int i; 1096 int i;
1077 1097
1098 ret = mthca_init_node_data(dev);
1099 if (ret)
1100 return ret;
1101
1078 strlcpy(dev->ib_dev.name, "mthca%d", IB_DEVICE_NAME_MAX); 1102 strlcpy(dev->ib_dev.name, "mthca%d", IB_DEVICE_NAME_MAX);
1079 dev->ib_dev.owner = THIS_MODULE; 1103 dev->ib_dev.owner = THIS_MODULE;
1080 1104
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index 564b6d51c394..fba608ed7df2 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -1434,7 +1434,7 @@ static int build_mlx_header(struct mthca_dev *dev, struct mthca_sqp *sqp,
1434 u16 pkey; 1434 u16 pkey;
1435 1435
1436 ib_ud_header_init(256, /* assume a MAD */ 1436 ib_ud_header_init(256, /* assume a MAD */
1437 sqp->ud_header.grh_present, 1437 mthca_ah_grh_present(to_mah(wr->wr.ud.ah)),
1438 &sqp->ud_header); 1438 &sqp->ud_header);
1439 1439
1440 err = mthca_read_ah(dev, to_mah(wr->wr.ud.ah), &sqp->ud_header); 1440 err = mthca_read_ah(dev, to_mah(wr->wr.ud.ah), &sqp->ud_header);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 9923a15a9996..e0a5412b7e68 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -45,11 +45,11 @@
45#include <linux/config.h> 45#include <linux/config.h>
46#include <linux/kref.h> 46#include <linux/kref.h>
47#include <linux/if_infiniband.h> 47#include <linux/if_infiniband.h>
48#include <linux/mutex.h>
48 49
49#include <net/neighbour.h> 50#include <net/neighbour.h>
50 51
51#include <asm/atomic.h> 52#include <asm/atomic.h>
52#include <asm/semaphore.h>
53 53
54#include <rdma/ib_verbs.h> 54#include <rdma/ib_verbs.h>
55#include <rdma/ib_pack.h> 55#include <rdma/ib_pack.h>
@@ -123,8 +123,8 @@ struct ipoib_dev_priv {
123 123
124 unsigned long flags; 124 unsigned long flags;
125 125
126 struct semaphore mcast_mutex; 126 struct mutex mcast_mutex;
127 struct semaphore vlan_mutex; 127 struct mutex vlan_mutex;
128 128
129 struct rb_root path_tree; 129 struct rb_root path_tree;
130 struct list_head path_list; 130 struct list_head path_list;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index 23885801b6d2..86bcdd72a107 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -52,7 +52,7 @@ MODULE_PARM_DESC(data_debug_level,
52 52
53#define IPOIB_OP_RECV (1ul << 31) 53#define IPOIB_OP_RECV (1ul << 31)
54 54
55static DECLARE_MUTEX(pkey_sem); 55static DEFINE_MUTEX(pkey_mutex);
56 56
57struct ipoib_ah *ipoib_create_ah(struct net_device *dev, 57struct ipoib_ah *ipoib_create_ah(struct net_device *dev,
58 struct ib_pd *pd, struct ib_ah_attr *attr) 58 struct ib_pd *pd, struct ib_ah_attr *attr)
@@ -445,25 +445,16 @@ int ipoib_ib_dev_down(struct net_device *dev)
445 445
446 /* Shutdown the P_Key thread if still active */ 446 /* Shutdown the P_Key thread if still active */
447 if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) { 447 if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) {
448 down(&pkey_sem); 448 mutex_lock(&pkey_mutex);
449 set_bit(IPOIB_PKEY_STOP, &priv->flags); 449 set_bit(IPOIB_PKEY_STOP, &priv->flags);
450 cancel_delayed_work(&priv->pkey_task); 450 cancel_delayed_work(&priv->pkey_task);
451 up(&pkey_sem); 451 mutex_unlock(&pkey_mutex);
452 flush_workqueue(ipoib_workqueue); 452 flush_workqueue(ipoib_workqueue);
453 } 453 }
454 454
455 ipoib_mcast_stop_thread(dev, 1); 455 ipoib_mcast_stop_thread(dev, 1);
456
457 /*
458 * Flush the multicast groups first so we stop any multicast joins. The
459 * completion thread may have already died and we may deadlock waiting
460 * for the completion thread to finish some multicast joins.
461 */
462 ipoib_mcast_dev_flush(dev); 456 ipoib_mcast_dev_flush(dev);
463 457
464 /* Delete broadcast and local addresses since they will be recreated */
465 ipoib_mcast_dev_down(dev);
466
467 ipoib_flush_paths(dev); 458 ipoib_flush_paths(dev);
468 459
469 return 0; 460 return 0;
@@ -608,13 +599,13 @@ void ipoib_ib_dev_flush(void *_dev)
608 if (test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) 599 if (test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags))
609 ipoib_ib_dev_up(dev); 600 ipoib_ib_dev_up(dev);
610 601
611 down(&priv->vlan_mutex); 602 mutex_lock(&priv->vlan_mutex);
612 603
613 /* Flush any child interfaces too */ 604 /* Flush any child interfaces too */
614 list_for_each_entry(cpriv, &priv->child_intfs, list) 605 list_for_each_entry(cpriv, &priv->child_intfs, list)
615 ipoib_ib_dev_flush(&cpriv->dev); 606 ipoib_ib_dev_flush(&cpriv->dev);
616 607
617 up(&priv->vlan_mutex); 608 mutex_unlock(&priv->vlan_mutex);
618} 609}
619 610
620void ipoib_ib_dev_cleanup(struct net_device *dev) 611void ipoib_ib_dev_cleanup(struct net_device *dev)
@@ -624,9 +615,7 @@ void ipoib_ib_dev_cleanup(struct net_device *dev)
624 ipoib_dbg(priv, "cleaning up ib_dev\n"); 615 ipoib_dbg(priv, "cleaning up ib_dev\n");
625 616
626 ipoib_mcast_stop_thread(dev, 1); 617 ipoib_mcast_stop_thread(dev, 1);
627 618 ipoib_mcast_dev_flush(dev);
628 /* Delete the broadcast address and the local address */
629 ipoib_mcast_dev_down(dev);
630 619
631 ipoib_transport_dev_cleanup(dev); 620 ipoib_transport_dev_cleanup(dev);
632} 621}
@@ -662,12 +651,12 @@ void ipoib_pkey_poll(void *dev_ptr)
662 if (test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) 651 if (test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags))
663 ipoib_open(dev); 652 ipoib_open(dev);
664 else { 653 else {
665 down(&pkey_sem); 654 mutex_lock(&pkey_mutex);
666 if (!test_bit(IPOIB_PKEY_STOP, &priv->flags)) 655 if (!test_bit(IPOIB_PKEY_STOP, &priv->flags))
667 queue_delayed_work(ipoib_workqueue, 656 queue_delayed_work(ipoib_workqueue,
668 &priv->pkey_task, 657 &priv->pkey_task,
669 HZ); 658 HZ);
670 up(&pkey_sem); 659 mutex_unlock(&pkey_mutex);
671 } 660 }
672} 661}
673 662
@@ -681,12 +670,12 @@ int ipoib_pkey_dev_delay_open(struct net_device *dev)
681 670
682 /* P_Key value not assigned yet - start polling */ 671 /* P_Key value not assigned yet - start polling */
683 if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) { 672 if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) {
684 down(&pkey_sem); 673 mutex_lock(&pkey_mutex);
685 clear_bit(IPOIB_PKEY_STOP, &priv->flags); 674 clear_bit(IPOIB_PKEY_STOP, &priv->flags);
686 queue_delayed_work(ipoib_workqueue, 675 queue_delayed_work(ipoib_workqueue,
687 &priv->pkey_task, 676 &priv->pkey_task,
688 HZ); 677 HZ);
689 up(&pkey_sem); 678 mutex_unlock(&pkey_mutex);
690 return 1; 679 return 1;
691 } 680 }
692 681
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 780009c7eaa6..fd3f5c862a5d 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -105,7 +105,7 @@ int ipoib_open(struct net_device *dev)
105 struct ipoib_dev_priv *cpriv; 105 struct ipoib_dev_priv *cpriv;
106 106
107 /* Bring up any child interfaces too */ 107 /* Bring up any child interfaces too */
108 down(&priv->vlan_mutex); 108 mutex_lock(&priv->vlan_mutex);
109 list_for_each_entry(cpriv, &priv->child_intfs, list) { 109 list_for_each_entry(cpriv, &priv->child_intfs, list) {
110 int flags; 110 int flags;
111 111
@@ -115,7 +115,7 @@ int ipoib_open(struct net_device *dev)
115 115
116 dev_change_flags(cpriv->dev, flags | IFF_UP); 116 dev_change_flags(cpriv->dev, flags | IFF_UP);
117 } 117 }
118 up(&priv->vlan_mutex); 118 mutex_unlock(&priv->vlan_mutex);
119 } 119 }
120 120
121 netif_start_queue(dev); 121 netif_start_queue(dev);
@@ -140,7 +140,7 @@ static int ipoib_stop(struct net_device *dev)
140 struct ipoib_dev_priv *cpriv; 140 struct ipoib_dev_priv *cpriv;
141 141
142 /* Bring down any child interfaces too */ 142 /* Bring down any child interfaces too */
143 down(&priv->vlan_mutex); 143 mutex_lock(&priv->vlan_mutex);
144 list_for_each_entry(cpriv, &priv->child_intfs, list) { 144 list_for_each_entry(cpriv, &priv->child_intfs, list) {
145 int flags; 145 int flags;
146 146
@@ -150,7 +150,7 @@ static int ipoib_stop(struct net_device *dev)
150 150
151 dev_change_flags(cpriv->dev, flags & ~IFF_UP); 151 dev_change_flags(cpriv->dev, flags & ~IFF_UP);
152 } 152 }
153 up(&priv->vlan_mutex); 153 mutex_unlock(&priv->vlan_mutex);
154 } 154 }
155 155
156 return 0; 156 return 0;
@@ -892,8 +892,8 @@ static void ipoib_setup(struct net_device *dev)
892 spin_lock_init(&priv->lock); 892 spin_lock_init(&priv->lock);
893 spin_lock_init(&priv->tx_lock); 893 spin_lock_init(&priv->tx_lock);
894 894
895 init_MUTEX(&priv->mcast_mutex); 895 mutex_init(&priv->mcast_mutex);
896 init_MUTEX(&priv->vlan_mutex); 896 mutex_init(&priv->vlan_mutex);
897 897
898 INIT_LIST_HEAD(&priv->path_list); 898 INIT_LIST_HEAD(&priv->path_list);
899 INIT_LIST_HEAD(&priv->child_intfs); 899 INIT_LIST_HEAD(&priv->child_intfs);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index ed0c2ead8bc1..98039da0caf0 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -55,7 +55,7 @@ MODULE_PARM_DESC(mcast_debug_level,
55 "Enable multicast debug tracing if > 0"); 55 "Enable multicast debug tracing if > 0");
56#endif 56#endif
57 57
58static DECLARE_MUTEX(mcast_mutex); 58static DEFINE_MUTEX(mcast_mutex);
59 59
60/* Used for all multicast joins (broadcast, IPv4 mcast and IPv6 mcast) */ 60/* Used for all multicast joins (broadcast, IPv4 mcast and IPv6 mcast) */
61struct ipoib_mcast { 61struct ipoib_mcast {
@@ -97,8 +97,6 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast)
97 struct ipoib_dev_priv *priv = netdev_priv(dev); 97 struct ipoib_dev_priv *priv = netdev_priv(dev);
98 struct ipoib_neigh *neigh, *tmp; 98 struct ipoib_neigh *neigh, *tmp;
99 unsigned long flags; 99 unsigned long flags;
100 LIST_HEAD(ah_list);
101 struct ipoib_ah *ah, *tah;
102 100
103 ipoib_dbg_mcast(netdev_priv(dev), 101 ipoib_dbg_mcast(netdev_priv(dev),
104 "deleting multicast group " IPOIB_GID_FMT "\n", 102 "deleting multicast group " IPOIB_GID_FMT "\n",
@@ -107,8 +105,14 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast)
107 spin_lock_irqsave(&priv->lock, flags); 105 spin_lock_irqsave(&priv->lock, flags);
108 106
109 list_for_each_entry_safe(neigh, tmp, &mcast->neigh_list, list) { 107 list_for_each_entry_safe(neigh, tmp, &mcast->neigh_list, list) {
108 /*
109 * It's safe to call ipoib_put_ah() inside priv->lock
110 * here, because we know that mcast->ah will always
111 * hold one more reference, so ipoib_put_ah() will
112 * never do more than decrement the ref count.
113 */
110 if (neigh->ah) 114 if (neigh->ah)
111 list_add_tail(&neigh->ah->list, &ah_list); 115 ipoib_put_ah(neigh->ah);
112 *to_ipoib_neigh(neigh->neighbour) = NULL; 116 *to_ipoib_neigh(neigh->neighbour) = NULL;
113 neigh->neighbour->ops->destructor = NULL; 117 neigh->neighbour->ops->destructor = NULL;
114 kfree(neigh); 118 kfree(neigh);
@@ -116,9 +120,6 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast)
116 120
117 spin_unlock_irqrestore(&priv->lock, flags); 121 spin_unlock_irqrestore(&priv->lock, flags);
118 122
119 list_for_each_entry_safe(ah, tah, &ah_list, list)
120 ipoib_put_ah(ah);
121
122 if (mcast->ah) 123 if (mcast->ah)
123 ipoib_put_ah(mcast->ah); 124 ipoib_put_ah(mcast->ah);
124 125
@@ -384,10 +385,10 @@ static void ipoib_mcast_join_complete(int status,
384 385
385 if (!status && !ipoib_mcast_join_finish(mcast, mcmember)) { 386 if (!status && !ipoib_mcast_join_finish(mcast, mcmember)) {
386 mcast->backoff = 1; 387 mcast->backoff = 1;
387 down(&mcast_mutex); 388 mutex_lock(&mcast_mutex);
388 if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) 389 if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
389 queue_work(ipoib_workqueue, &priv->mcast_task); 390 queue_work(ipoib_workqueue, &priv->mcast_task);
390 up(&mcast_mutex); 391 mutex_unlock(&mcast_mutex);
391 complete(&mcast->done); 392 complete(&mcast->done);
392 return; 393 return;
393 } 394 }
@@ -417,7 +418,7 @@ static void ipoib_mcast_join_complete(int status,
417 418
418 mcast->query = NULL; 419 mcast->query = NULL;
419 420
420 down(&mcast_mutex); 421 mutex_lock(&mcast_mutex);
421 if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) { 422 if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) {
422 if (status == -ETIMEDOUT) 423 if (status == -ETIMEDOUT)
423 queue_work(ipoib_workqueue, &priv->mcast_task); 424 queue_work(ipoib_workqueue, &priv->mcast_task);
@@ -426,7 +427,7 @@ static void ipoib_mcast_join_complete(int status,
426 mcast->backoff * HZ); 427 mcast->backoff * HZ);
427 } else 428 } else
428 complete(&mcast->done); 429 complete(&mcast->done);
429 up(&mcast_mutex); 430 mutex_unlock(&mcast_mutex);
430 431
431 return; 432 return;
432} 433}
@@ -481,12 +482,12 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast,
481 if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS) 482 if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS)
482 mcast->backoff = IPOIB_MAX_BACKOFF_SECONDS; 483 mcast->backoff = IPOIB_MAX_BACKOFF_SECONDS;
483 484
484 down(&mcast_mutex); 485 mutex_lock(&mcast_mutex);
485 if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) 486 if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
486 queue_delayed_work(ipoib_workqueue, 487 queue_delayed_work(ipoib_workqueue,
487 &priv->mcast_task, 488 &priv->mcast_task,
488 mcast->backoff * HZ); 489 mcast->backoff * HZ);
489 up(&mcast_mutex); 490 mutex_unlock(&mcast_mutex);
490 } else 491 } else
491 mcast->query_id = ret; 492 mcast->query_id = ret;
492} 493}
@@ -519,11 +520,11 @@ void ipoib_mcast_join_task(void *dev_ptr)
519 priv->broadcast = ipoib_mcast_alloc(dev, 1); 520 priv->broadcast = ipoib_mcast_alloc(dev, 1);
520 if (!priv->broadcast) { 521 if (!priv->broadcast) {
521 ipoib_warn(priv, "failed to allocate broadcast group\n"); 522 ipoib_warn(priv, "failed to allocate broadcast group\n");
522 down(&mcast_mutex); 523 mutex_lock(&mcast_mutex);
523 if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) 524 if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
524 queue_delayed_work(ipoib_workqueue, 525 queue_delayed_work(ipoib_workqueue,
525 &priv->mcast_task, HZ); 526 &priv->mcast_task, HZ);
526 up(&mcast_mutex); 527 mutex_unlock(&mcast_mutex);
527 return; 528 return;
528 } 529 }
529 530
@@ -579,10 +580,10 @@ int ipoib_mcast_start_thread(struct net_device *dev)
579 580
580 ipoib_dbg_mcast(priv, "starting multicast thread\n"); 581 ipoib_dbg_mcast(priv, "starting multicast thread\n");
581 582
582 down(&mcast_mutex); 583 mutex_lock(&mcast_mutex);
583 if (!test_and_set_bit(IPOIB_MCAST_RUN, &priv->flags)) 584 if (!test_and_set_bit(IPOIB_MCAST_RUN, &priv->flags))
584 queue_work(ipoib_workqueue, &priv->mcast_task); 585 queue_work(ipoib_workqueue, &priv->mcast_task);
585 up(&mcast_mutex); 586 mutex_unlock(&mcast_mutex);
586 587
587 return 0; 588 return 0;
588} 589}
@@ -594,10 +595,10 @@ int ipoib_mcast_stop_thread(struct net_device *dev, int flush)
594 595
595 ipoib_dbg_mcast(priv, "stopping multicast thread\n"); 596 ipoib_dbg_mcast(priv, "stopping multicast thread\n");
596 597
597 down(&mcast_mutex); 598 mutex_lock(&mcast_mutex);
598 clear_bit(IPOIB_MCAST_RUN, &priv->flags); 599 clear_bit(IPOIB_MCAST_RUN, &priv->flags);
599 cancel_delayed_work(&priv->mcast_task); 600 cancel_delayed_work(&priv->mcast_task);
600 up(&mcast_mutex); 601 mutex_unlock(&mcast_mutex);
601 602
602 if (flush) 603 if (flush)
603 flush_workqueue(ipoib_workqueue); 604 flush_workqueue(ipoib_workqueue);
@@ -741,48 +742,23 @@ void ipoib_mcast_dev_flush(struct net_device *dev)
741{ 742{
742 struct ipoib_dev_priv *priv = netdev_priv(dev); 743 struct ipoib_dev_priv *priv = netdev_priv(dev);
743 LIST_HEAD(remove_list); 744 LIST_HEAD(remove_list);
744 struct ipoib_mcast *mcast, *tmcast, *nmcast; 745 struct ipoib_mcast *mcast, *tmcast;
745 unsigned long flags; 746 unsigned long flags;
746 747
747 ipoib_dbg_mcast(priv, "flushing multicast list\n"); 748 ipoib_dbg_mcast(priv, "flushing multicast list\n");
748 749
749 spin_lock_irqsave(&priv->lock, flags); 750 spin_lock_irqsave(&priv->lock, flags);
750 list_for_each_entry_safe(mcast, tmcast, &priv->multicast_list, list) {
751 nmcast = ipoib_mcast_alloc(dev, 0);
752 if (nmcast) {
753 nmcast->flags =
754 mcast->flags & (1 << IPOIB_MCAST_FLAG_SENDONLY);
755 751
756 nmcast->mcmember.mgid = mcast->mcmember.mgid; 752 list_for_each_entry_safe(mcast, tmcast, &priv->multicast_list, list) {
757 753 list_del(&mcast->list);
758 /* Add the new group in before the to-be-destroyed group */ 754 rb_erase(&mcast->rb_node, &priv->multicast_tree);
759 list_add_tail(&nmcast->list, &mcast->list); 755 list_add_tail(&mcast->list, &remove_list);
760 list_del_init(&mcast->list);
761
762 rb_replace_node(&mcast->rb_node, &nmcast->rb_node,
763 &priv->multicast_tree);
764
765 list_add_tail(&mcast->list, &remove_list);
766 } else {
767 ipoib_warn(priv, "could not reallocate multicast group "
768 IPOIB_GID_FMT "\n",
769 IPOIB_GID_ARG(mcast->mcmember.mgid));
770 }
771 } 756 }
772 757
773 if (priv->broadcast) { 758 if (priv->broadcast) {
774 nmcast = ipoib_mcast_alloc(dev, 0); 759 rb_erase(&priv->broadcast->rb_node, &priv->multicast_tree);
775 if (nmcast) { 760 list_add_tail(&priv->broadcast->list, &remove_list);
776 nmcast->mcmember.mgid = priv->broadcast->mcmember.mgid; 761 priv->broadcast = NULL;
777
778 rb_replace_node(&priv->broadcast->rb_node,
779 &nmcast->rb_node,
780 &priv->multicast_tree);
781
782 list_add_tail(&priv->broadcast->list, &remove_list);
783 }
784
785 priv->broadcast = nmcast;
786 } 762 }
787 763
788 spin_unlock_irqrestore(&priv->lock, flags); 764 spin_unlock_irqrestore(&priv->lock, flags);
@@ -793,24 +769,6 @@ void ipoib_mcast_dev_flush(struct net_device *dev)
793 } 769 }
794} 770}
795 771
796void ipoib_mcast_dev_down(struct net_device *dev)
797{
798 struct ipoib_dev_priv *priv = netdev_priv(dev);
799 unsigned long flags;
800
801 /* Delete broadcast since it will be recreated */
802 if (priv->broadcast) {
803 ipoib_dbg_mcast(priv, "deleting broadcast group\n");
804
805 spin_lock_irqsave(&priv->lock, flags);
806 rb_erase(&priv->broadcast->rb_node, &priv->multicast_tree);
807 spin_unlock_irqrestore(&priv->lock, flags);
808 ipoib_mcast_leave(dev, priv->broadcast);
809 ipoib_mcast_free(priv->broadcast);
810 priv->broadcast = NULL;
811 }
812}
813
814void ipoib_mcast_restart_task(void *dev_ptr) 772void ipoib_mcast_restart_task(void *dev_ptr)
815{ 773{
816 struct net_device *dev = dev_ptr; 774 struct net_device *dev = dev_ptr;
@@ -824,7 +782,8 @@ void ipoib_mcast_restart_task(void *dev_ptr)
824 782
825 ipoib_mcast_stop_thread(dev, 0); 783 ipoib_mcast_stop_thread(dev, 0);
826 784
827 spin_lock_irqsave(&priv->lock, flags); 785 spin_lock_irqsave(&dev->xmit_lock, flags);
786 spin_lock(&priv->lock);
828 787
829 /* 788 /*
830 * Unfortunately, the networking core only gives us a list of all of 789 * Unfortunately, the networking core only gives us a list of all of
@@ -896,7 +855,9 @@ void ipoib_mcast_restart_task(void *dev_ptr)
896 list_add_tail(&mcast->list, &remove_list); 855 list_add_tail(&mcast->list, &remove_list);
897 } 856 }
898 } 857 }
899 spin_unlock_irqrestore(&priv->lock, flags); 858
859 spin_unlock(&priv->lock);
860 spin_unlock_irqrestore(&dev->xmit_lock, flags);
900 861
901 /* We have to cancel outside of the spinlock */ 862 /* We have to cancel outside of the spinlock */
902 list_for_each_entry_safe(mcast, tmcast, &remove_list, list) { 863 list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
index e829e10400e3..faaf10e5fc7b 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
@@ -65,9 +65,9 @@ int ipoib_mcast_attach(struct net_device *dev, u16 mlid, union ib_gid *mgid)
65 } 65 }
66 66
67 /* attach QP to multicast group */ 67 /* attach QP to multicast group */
68 down(&priv->mcast_mutex); 68 mutex_lock(&priv->mcast_mutex);
69 ret = ib_attach_mcast(priv->qp, mgid, mlid); 69 ret = ib_attach_mcast(priv->qp, mgid, mlid);
70 up(&priv->mcast_mutex); 70 mutex_unlock(&priv->mcast_mutex);
71 if (ret) 71 if (ret)
72 ipoib_warn(priv, "failed to attach to multicast group, ret = %d\n", ret); 72 ipoib_warn(priv, "failed to attach to multicast group, ret = %d\n", ret);
73 73
@@ -81,9 +81,9 @@ int ipoib_mcast_detach(struct net_device *dev, u16 mlid, union ib_gid *mgid)
81 struct ipoib_dev_priv *priv = netdev_priv(dev); 81 struct ipoib_dev_priv *priv = netdev_priv(dev);
82 int ret; 82 int ret;
83 83
84 down(&priv->mcast_mutex); 84 mutex_lock(&priv->mcast_mutex);
85 ret = ib_detach_mcast(priv->qp, mgid, mlid); 85 ret = ib_detach_mcast(priv->qp, mgid, mlid);
86 up(&priv->mcast_mutex); 86 mutex_unlock(&priv->mcast_mutex);
87 if (ret) 87 if (ret)
88 ipoib_warn(priv, "ib_detach_mcast failed (result = %d)\n", ret); 88 ipoib_warn(priv, "ib_detach_mcast failed (result = %d)\n", ret);
89 89
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
index d280b341a37f..4ca175553f9f 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
@@ -63,7 +63,7 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
63 63
64 ppriv = netdev_priv(pdev); 64 ppriv = netdev_priv(pdev);
65 65
66 down(&ppriv->vlan_mutex); 66 mutex_lock(&ppriv->vlan_mutex);
67 67
68 /* 68 /*
69 * First ensure this isn't a duplicate. We check the parent device and 69 * First ensure this isn't a duplicate. We check the parent device and
@@ -124,7 +124,7 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
124 124
125 list_add_tail(&priv->list, &ppriv->child_intfs); 125 list_add_tail(&priv->list, &ppriv->child_intfs);
126 126
127 up(&ppriv->vlan_mutex); 127 mutex_unlock(&ppriv->vlan_mutex);
128 128
129 return 0; 129 return 0;
130 130
@@ -139,7 +139,7 @@ device_init_failed:
139 free_netdev(priv->dev); 139 free_netdev(priv->dev);
140 140
141err: 141err:
142 up(&ppriv->vlan_mutex); 142 mutex_unlock(&ppriv->vlan_mutex);
143 return result; 143 return result;
144} 144}
145 145
@@ -153,7 +153,7 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey)
153 153
154 ppriv = netdev_priv(pdev); 154 ppriv = netdev_priv(pdev);
155 155
156 down(&ppriv->vlan_mutex); 156 mutex_lock(&ppriv->vlan_mutex);
157 list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) { 157 list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) {
158 if (priv->pkey == pkey) { 158 if (priv->pkey == pkey) {
159 unregister_netdev(priv->dev); 159 unregister_netdev(priv->dev);
@@ -167,7 +167,7 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey)
167 break; 167 break;
168 } 168 }
169 } 169 }
170 up(&ppriv->vlan_mutex); 170 mutex_unlock(&ppriv->vlan_mutex);
171 171
172 return ret; 172 return ret;
173} 173}
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index dd488d3cffa9..31207e664148 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -1516,8 +1516,7 @@ static ssize_t show_port(struct class_device *class_dev, char *buf)
1516 1516
1517static CLASS_DEVICE_ATTR(port, S_IRUGO, show_port, NULL); 1517static CLASS_DEVICE_ATTR(port, S_IRUGO, show_port, NULL);
1518 1518
1519static struct srp_host *srp_add_port(struct ib_device *device, 1519static struct srp_host *srp_add_port(struct ib_device *device, u8 port)
1520 __be64 node_guid, u8 port)
1521{ 1520{
1522 struct srp_host *host; 1521 struct srp_host *host;
1523 1522
@@ -1532,7 +1531,7 @@ static struct srp_host *srp_add_port(struct ib_device *device,
1532 host->port = port; 1531 host->port = port;
1533 1532
1534 host->initiator_port_id[7] = port; 1533 host->initiator_port_id[7] = port;
1535 memcpy(host->initiator_port_id + 8, &node_guid, 8); 1534 memcpy(host->initiator_port_id + 8, &device->node_guid, 8);
1536 1535
1537 host->pd = ib_alloc_pd(device); 1536 host->pd = ib_alloc_pd(device);
1538 if (IS_ERR(host->pd)) 1537 if (IS_ERR(host->pd))
@@ -1580,22 +1579,11 @@ static void srp_add_one(struct ib_device *device)
1580{ 1579{
1581 struct list_head *dev_list; 1580 struct list_head *dev_list;
1582 struct srp_host *host; 1581 struct srp_host *host;
1583 struct ib_device_attr *dev_attr;
1584 int s, e, p; 1582 int s, e, p;
1585 1583
1586 dev_attr = kmalloc(sizeof *dev_attr, GFP_KERNEL);
1587 if (!dev_attr)
1588 return;
1589
1590 if (ib_query_device(device, dev_attr)) {
1591 printk(KERN_WARNING PFX "Couldn't query node GUID for %s.\n",
1592 device->name);
1593 goto out;
1594 }
1595
1596 dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL); 1584 dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL);
1597 if (!dev_list) 1585 if (!dev_list)
1598 goto out; 1586 return;
1599 1587
1600 INIT_LIST_HEAD(dev_list); 1588 INIT_LIST_HEAD(dev_list);
1601 1589
@@ -1608,15 +1596,12 @@ static void srp_add_one(struct ib_device *device)
1608 } 1596 }
1609 1597
1610 for (p = s; p <= e; ++p) { 1598 for (p = s; p <= e; ++p) {
1611 host = srp_add_port(device, dev_attr->node_guid, p); 1599 host = srp_add_port(device, p);
1612 if (host) 1600 if (host)
1613 list_add_tail(&host->list, dev_list); 1601 list_add_tail(&host->list, dev_list);
1614 } 1602 }
1615 1603
1616 ib_set_client_data(device, &srp_client, dev_list); 1604 ib_set_client_data(device, &srp_client, dev_list);
1617
1618out:
1619 kfree(dev_attr);
1620} 1605}
1621 1606
1622static void srp_remove_one(struct ib_device *device) 1607static void srp_remove_one(struct ib_device *device)
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index caac6d63d46f..b765a155c008 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -50,9 +50,7 @@ static DECLARE_MUTEX(gameport_sem);
50 50
51static LIST_HEAD(gameport_list); 51static LIST_HEAD(gameport_list);
52 52
53static struct bus_type gameport_bus = { 53static struct bus_type gameport_bus;
54 .name = "gameport",
55};
56 54
57static void gameport_add_port(struct gameport *gameport); 55static void gameport_add_port(struct gameport *gameport);
58static void gameport_destroy_port(struct gameport *gameport); 56static void gameport_destroy_port(struct gameport *gameport);
@@ -703,11 +701,15 @@ static int gameport_driver_remove(struct device *dev)
703 return 0; 701 return 0;
704} 702}
705 703
704static struct bus_type gameport_bus = {
705 .name = "gameport",
706 .probe = gameport_driver_probe,
707 .remove = gameport_driver_remove,
708};
709
706void __gameport_register_driver(struct gameport_driver *drv, struct module *owner) 710void __gameport_register_driver(struct gameport_driver *drv, struct module *owner)
707{ 711{
708 drv->driver.bus = &gameport_bus; 712 drv->driver.bus = &gameport_bus;
709 drv->driver.probe = gameport_driver_probe;
710 drv->driver.remove = gameport_driver_remove;
711 gameport_queue_event(drv, owner, GAMEPORT_REGISTER_DRIVER); 713 gameport_queue_event(drv, owner, GAMEPORT_REGISTER_DRIVER);
712} 714}
713 715
diff --git a/drivers/input/input.c b/drivers/input/input.c
index fe33ff334e27..4fe3da3c667a 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -528,40 +528,56 @@ INPUT_DEV_STRING_ATTR_SHOW(name);
528INPUT_DEV_STRING_ATTR_SHOW(phys); 528INPUT_DEV_STRING_ATTR_SHOW(phys);
529INPUT_DEV_STRING_ATTR_SHOW(uniq); 529INPUT_DEV_STRING_ATTR_SHOW(uniq);
530 530
531static int print_modalias_bits(char *buf, char prefix, unsigned long *arr, 531static int print_modalias_bits(char *buf, int size, char prefix, unsigned long *arr,
532 unsigned int min, unsigned int max) 532 unsigned int min, unsigned int max)
533{ 533{
534 int len, i; 534 int len, i;
535 535
536 len = sprintf(buf, "%c", prefix); 536 len = snprintf(buf, size, "%c", prefix);
537 for (i = min; i < max; i++) 537 for (i = min; i < max; i++)
538 if (arr[LONG(i)] & BIT(i)) 538 if (arr[LONG(i)] & BIT(i))
539 len += sprintf(buf+len, "%X,", i); 539 len += snprintf(buf + len, size - len, "%X,", i);
540 return len; 540 return len;
541} 541}
542 542
543static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf) 543static int print_modalias(char *buf, int size, struct input_dev *id)
544{ 544{
545 struct input_dev *id = to_input_dev(dev); 545 int len;
546 ssize_t len = 0;
547 546
548 len += sprintf(buf+len, "input:b%04Xv%04Xp%04Xe%04X-", 547 len = snprintf(buf, size, "input:b%04Xv%04Xp%04Xe%04X-",
549 id->id.bustype, 548 id->id.bustype,
550 id->id.vendor, 549 id->id.vendor,
551 id->id.product, 550 id->id.product,
552 id->id.version); 551 id->id.version);
553 552
554 len += print_modalias_bits(buf+len, 'e', id->evbit, 0, EV_MAX); 553 len += print_modalias_bits(buf + len, size - len, 'e', id->evbit,
555 len += print_modalias_bits(buf+len, 'k', id->keybit, 554 0, EV_MAX);
555 len += print_modalias_bits(buf + len, size - len, 'k', id->keybit,
556 KEY_MIN_INTERESTING, KEY_MAX); 556 KEY_MIN_INTERESTING, KEY_MAX);
557 len += print_modalias_bits(buf+len, 'r', id->relbit, 0, REL_MAX); 557 len += print_modalias_bits(buf + len, size - len, 'r', id->relbit,
558 len += print_modalias_bits(buf+len, 'a', id->absbit, 0, ABS_MAX); 558 0, REL_MAX);
559 len += print_modalias_bits(buf+len, 'm', id->mscbit, 0, MSC_MAX); 559 len += print_modalias_bits(buf + len, size - len, 'a', id->absbit,
560 len += print_modalias_bits(buf+len, 'l', id->ledbit, 0, LED_MAX); 560 0, ABS_MAX);
561 len += print_modalias_bits(buf+len, 's', id->sndbit, 0, SND_MAX); 561 len += print_modalias_bits(buf + len, size - len, 'm', id->mscbit,
562 len += print_modalias_bits(buf+len, 'f', id->ffbit, 0, FF_MAX); 562 0, MSC_MAX);
563 len += print_modalias_bits(buf+len, 'w', id->swbit, 0, SW_MAX); 563 len += print_modalias_bits(buf + len, size - len, 'l', id->ledbit,
564 len += sprintf(buf+len, "\n"); 564 0, LED_MAX);
565 len += print_modalias_bits(buf + len, size - len, 's', id->sndbit,
566 0, SND_MAX);
567 len += print_modalias_bits(buf + len, size - len, 'f', id->ffbit,
568 0, FF_MAX);
569 len += print_modalias_bits(buf + len, size - len, 'w', id->swbit,
570 0, SW_MAX);
571 return len;
572}
573
574static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf)
575{
576 struct input_dev *id = to_input_dev(dev);
577 ssize_t len;
578
579 len = print_modalias(buf, PAGE_SIZE, id);
580 len += snprintf(buf + len, PAGE_SIZE-len, "\n");
565 return len; 581 return len;
566} 582}
567static CLASS_DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL); 583static CLASS_DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL);
@@ -728,8 +744,11 @@ static int input_dev_uevent(struct class_device *cdev, char **envp,
728 if (test_bit(EV_SW, dev->evbit)) 744 if (test_bit(EV_SW, dev->evbit))
729 INPUT_ADD_HOTPLUG_BM_VAR("SW=", dev->swbit, SW_MAX); 745 INPUT_ADD_HOTPLUG_BM_VAR("SW=", dev->swbit, SW_MAX);
730 746
731 envp[i] = NULL; 747 envp[i++] = buffer + len;
748 len += snprintf(buffer + len, buffer_size - len, "MODALIAS=");
749 len += print_modalias(buffer + len, buffer_size - len, dev) + 1;
732 750
751 envp[i] = NULL;
733 return 0; 752 return 0;
734} 753}
735 754
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 24474335dfd1..2141501e9f2e 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -348,6 +348,40 @@ static int alps_tap_mode(struct psmouse *psmouse, int enable)
348 return 0; 348 return 0;
349} 349}
350 350
351/*
352 * alps_poll() - poll the touchpad for current motion packet.
353 * Used in resync.
354 */
355static int alps_poll(struct psmouse *psmouse)
356{
357 struct alps_data *priv = psmouse->private;
358 unsigned char buf[6];
359 int poll_failed;
360
361 if (priv->i->flags & ALPS_PASS)
362 alps_passthrough_mode(psmouse, 1);
363
364 poll_failed = ps2_command(&psmouse->ps2dev, buf,
365 PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0;
366
367 if (priv->i->flags & ALPS_PASS)
368 alps_passthrough_mode(psmouse, 0);
369
370 if (poll_failed || (buf[0] & priv->i->mask0) != priv->i->byte0)
371 return -1;
372
373 if ((psmouse->badbyte & 0xc8) == 0x08) {
374/*
375 * Poll the track stick ...
376 */
377 if (ps2_command(&psmouse->ps2dev, buf, PSMOUSE_CMD_POLL | (3 << 8)))
378 return -1;
379 }
380
381 memcpy(psmouse->packet, buf, sizeof(buf));
382 return 0;
383}
384
351static int alps_reconnect(struct psmouse *psmouse) 385static int alps_reconnect(struct psmouse *psmouse)
352{ 386{
353 struct alps_data *priv = psmouse->private; 387 struct alps_data *priv = psmouse->private;
@@ -451,10 +485,14 @@ int alps_init(struct psmouse *psmouse)
451 input_register_device(priv->dev2); 485 input_register_device(priv->dev2);
452 486
453 psmouse->protocol_handler = alps_process_byte; 487 psmouse->protocol_handler = alps_process_byte;
488 psmouse->poll = alps_poll;
454 psmouse->disconnect = alps_disconnect; 489 psmouse->disconnect = alps_disconnect;
455 psmouse->reconnect = alps_reconnect; 490 psmouse->reconnect = alps_reconnect;
456 psmouse->pktsize = 6; 491 psmouse->pktsize = 6;
457 492
493 /* We are having trouble resyncing ALPS touchpads so disable it for now */
494 psmouse->resync_time = 0;
495
458 return 0; 496 return 0;
459 497
460init_fail: 498init_fail:
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
index 025a71de5404..c88520d3d13c 100644
--- a/drivers/input/mouse/logips2pp.c
+++ b/drivers/input/mouse/logips2pp.c
@@ -117,7 +117,7 @@ static int ps2pp_cmd(struct psmouse *psmouse, unsigned char *param, unsigned cha
117 if (psmouse_sliced_command(psmouse, command)) 117 if (psmouse_sliced_command(psmouse, command))
118 return -1; 118 return -1;
119 119
120 if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_POLL)) 120 if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_POLL | 0x0300))
121 return -1; 121 return -1;
122 122
123 return 0; 123 return 0;
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index 4d5ecc04c5b6..7665fd9ce559 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -54,10 +54,14 @@ static unsigned int psmouse_smartscroll = 1;
54module_param_named(smartscroll, psmouse_smartscroll, bool, 0644); 54module_param_named(smartscroll, psmouse_smartscroll, bool, 0644);
55MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled."); 55MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled.");
56 56
57static unsigned int psmouse_resetafter; 57static unsigned int psmouse_resetafter = 5;
58module_param_named(resetafter, psmouse_resetafter, uint, 0644); 58module_param_named(resetafter, psmouse_resetafter, uint, 0644);
59MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never)."); 59MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never).");
60 60
61static unsigned int psmouse_resync_time = 5;
62module_param_named(resync_time, psmouse_resync_time, uint, 0644);
63MODULE_PARM_DESC(resync_time, "How long can mouse stay idle before forcing resync (in seconds, 0 = never).");
64
61PSMOUSE_DEFINE_ATTR(protocol, S_IWUSR | S_IRUGO, 65PSMOUSE_DEFINE_ATTR(protocol, S_IWUSR | S_IRUGO,
62 NULL, 66 NULL,
63 psmouse_attr_show_protocol, psmouse_attr_set_protocol); 67 psmouse_attr_show_protocol, psmouse_attr_set_protocol);
@@ -70,12 +74,16 @@ PSMOUSE_DEFINE_ATTR(resolution, S_IWUSR | S_IRUGO,
70PSMOUSE_DEFINE_ATTR(resetafter, S_IWUSR | S_IRUGO, 74PSMOUSE_DEFINE_ATTR(resetafter, S_IWUSR | S_IRUGO,
71 (void *) offsetof(struct psmouse, resetafter), 75 (void *) offsetof(struct psmouse, resetafter),
72 psmouse_show_int_attr, psmouse_set_int_attr); 76 psmouse_show_int_attr, psmouse_set_int_attr);
77PSMOUSE_DEFINE_ATTR(resync_time, S_IWUSR | S_IRUGO,
78 (void *) offsetof(struct psmouse, resync_time),
79 psmouse_show_int_attr, psmouse_set_int_attr);
73 80
74static struct attribute *psmouse_attributes[] = { 81static struct attribute *psmouse_attributes[] = {
75 &psmouse_attr_protocol.dattr.attr, 82 &psmouse_attr_protocol.dattr.attr,
76 &psmouse_attr_rate.dattr.attr, 83 &psmouse_attr_rate.dattr.attr,
77 &psmouse_attr_resolution.dattr.attr, 84 &psmouse_attr_resolution.dattr.attr,
78 &psmouse_attr_resetafter.dattr.attr, 85 &psmouse_attr_resetafter.dattr.attr,
86 &psmouse_attr_resync_time.dattr.attr,
79 NULL 87 NULL
80}; 88};
81 89
@@ -98,6 +106,8 @@ __obsolete_setup("psmouse_rate=");
98 */ 106 */
99static DECLARE_MUTEX(psmouse_sem); 107static DECLARE_MUTEX(psmouse_sem);
100 108
109static struct workqueue_struct *kpsmoused_wq;
110
101struct psmouse_protocol { 111struct psmouse_protocol {
102 enum psmouse_type type; 112 enum psmouse_type type;
103 char *name; 113 char *name;
@@ -178,15 +188,79 @@ static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse, struct pt_reg
178} 188}
179 189
180/* 190/*
181 * psmouse_interrupt() handles incoming characters, either gathering them into 191 * __psmouse_set_state() sets new psmouse state and resets all flags.
182 * packets or passing them to the command routine as command output. 192 */
193
194static inline void __psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state)
195{
196 psmouse->state = new_state;
197 psmouse->pktcnt = psmouse->out_of_sync = 0;
198 psmouse->ps2dev.flags = 0;
199 psmouse->last = jiffies;
200}
201
202
203/*
204 * psmouse_set_state() sets new psmouse state and resets all flags and
205 * counters while holding serio lock so fighting with interrupt handler
206 * is not a concern.
207 */
208
209static void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state)
210{
211 serio_pause_rx(psmouse->ps2dev.serio);
212 __psmouse_set_state(psmouse, new_state);
213 serio_continue_rx(psmouse->ps2dev.serio);
214}
215
216/*
217 * psmouse_handle_byte() processes one byte of the input data stream
218 * by calling corresponding protocol handler.
219 */
220
221static int psmouse_handle_byte(struct psmouse *psmouse, struct pt_regs *regs)
222{
223 psmouse_ret_t rc = psmouse->protocol_handler(psmouse, regs);
224
225 switch (rc) {
226 case PSMOUSE_BAD_DATA:
227 if (psmouse->state == PSMOUSE_ACTIVATED) {
228 printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n",
229 psmouse->name, psmouse->phys, psmouse->pktcnt);
230 if (++psmouse->out_of_sync == psmouse->resetafter) {
231 __psmouse_set_state(psmouse, PSMOUSE_IGNORE);
232 printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n");
233 serio_reconnect(psmouse->ps2dev.serio);
234 return -1;
235 }
236 }
237 psmouse->pktcnt = 0;
238 break;
239
240 case PSMOUSE_FULL_PACKET:
241 psmouse->pktcnt = 0;
242 if (psmouse->out_of_sync) {
243 psmouse->out_of_sync = 0;
244 printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n",
245 psmouse->name, psmouse->phys);
246 }
247 break;
248
249 case PSMOUSE_GOOD_DATA:
250 break;
251 }
252 return 0;
253}
254
255/*
256 * psmouse_interrupt() handles incoming characters, either passing them
257 * for normal processing or gathering them as command response.
183 */ 258 */
184 259
185static irqreturn_t psmouse_interrupt(struct serio *serio, 260static irqreturn_t psmouse_interrupt(struct serio *serio,
186 unsigned char data, unsigned int flags, struct pt_regs *regs) 261 unsigned char data, unsigned int flags, struct pt_regs *regs)
187{ 262{
188 struct psmouse *psmouse = serio_get_drvdata(serio); 263 struct psmouse *psmouse = serio_get_drvdata(serio);
189 psmouse_ret_t rc;
190 264
191 if (psmouse->state == PSMOUSE_IGNORE) 265 if (psmouse->state == PSMOUSE_IGNORE)
192 goto out; 266 goto out;
@@ -208,67 +282,58 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
208 if (ps2_handle_response(&psmouse->ps2dev, data)) 282 if (ps2_handle_response(&psmouse->ps2dev, data))
209 goto out; 283 goto out;
210 284
211 if (psmouse->state == PSMOUSE_INITIALIZING) 285 if (psmouse->state <= PSMOUSE_RESYNCING)
212 goto out; 286 goto out;
213 287
214 if (psmouse->state == PSMOUSE_ACTIVATED && 288 if (psmouse->state == PSMOUSE_ACTIVATED &&
215 psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) { 289 psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) {
216 printk(KERN_WARNING "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n", 290 printk(KERN_INFO "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n",
217 psmouse->name, psmouse->phys, psmouse->pktcnt); 291 psmouse->name, psmouse->phys, psmouse->pktcnt);
218 psmouse->pktcnt = 0; 292 psmouse->badbyte = psmouse->packet[0];
293 __psmouse_set_state(psmouse, PSMOUSE_RESYNCING);
294 queue_work(kpsmoused_wq, &psmouse->resync_work);
295 goto out;
219 } 296 }
220 297
221 psmouse->last = jiffies;
222 psmouse->packet[psmouse->pktcnt++] = data; 298 psmouse->packet[psmouse->pktcnt++] = data;
223 299/*
224 if (psmouse->packet[0] == PSMOUSE_RET_BAT) { 300 * Check if this is a new device announcement (0xAA 0x00)
301 */
302 if (unlikely(psmouse->packet[0] == PSMOUSE_RET_BAT && psmouse->pktcnt <= 2)) {
225 if (psmouse->pktcnt == 1) 303 if (psmouse->pktcnt == 1)
226 goto out; 304 goto out;
227 305
228 if (psmouse->pktcnt == 2) { 306 if (psmouse->packet[1] == PSMOUSE_RET_ID) {
229 if (psmouse->packet[1] == PSMOUSE_RET_ID) { 307 __psmouse_set_state(psmouse, PSMOUSE_IGNORE);
230 psmouse->state = PSMOUSE_IGNORE; 308 serio_reconnect(serio);
231 serio_reconnect(serio); 309 goto out;
232 goto out;
233 }
234 if (psmouse->type == PSMOUSE_SYNAPTICS) {
235 /* neither 0xAA nor 0x00 are valid first bytes
236 * for a packet in absolute mode
237 */
238 psmouse->pktcnt = 0;
239 goto out;
240 }
241 } 310 }
242 } 311/*
243 312 * Not a new device, try processing first byte normally
244 rc = psmouse->protocol_handler(psmouse, regs); 313 */
314 psmouse->pktcnt = 1;
315 if (psmouse_handle_byte(psmouse, regs))
316 goto out;
245 317
246 switch (rc) { 318 psmouse->packet[psmouse->pktcnt++] = data;
247 case PSMOUSE_BAD_DATA: 319 }
248 printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n",
249 psmouse->name, psmouse->phys, psmouse->pktcnt);
250 psmouse->pktcnt = 0;
251 320
252 if (++psmouse->out_of_sync == psmouse->resetafter) { 321/*
253 psmouse->state = PSMOUSE_IGNORE; 322 * See if we need to force resync because mouse was idle for too long
254 printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n"); 323 */
255 serio_reconnect(psmouse->ps2dev.serio); 324 if (psmouse->state == PSMOUSE_ACTIVATED &&
256 } 325 psmouse->pktcnt == 1 && psmouse->resync_time &&
257 break; 326 time_after(jiffies, psmouse->last + psmouse->resync_time * HZ)) {
327 psmouse->badbyte = psmouse->packet[0];
328 __psmouse_set_state(psmouse, PSMOUSE_RESYNCING);
329 queue_work(kpsmoused_wq, &psmouse->resync_work);
330 goto out;
331 }
258 332
259 case PSMOUSE_FULL_PACKET: 333 psmouse->last = jiffies;
260 psmouse->pktcnt = 0; 334 psmouse_handle_byte(psmouse, regs);
261 if (psmouse->out_of_sync) {
262 psmouse->out_of_sync = 0;
263 printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n",
264 psmouse->name, psmouse->phys);
265 }
266 break;
267 335
268 case PSMOUSE_GOOD_DATA: 336 out:
269 break;
270 }
271out:
272 return IRQ_HANDLED; 337 return IRQ_HANDLED;
273} 338}
274 339
@@ -752,21 +817,6 @@ static void psmouse_initialize(struct psmouse *psmouse)
752} 817}
753 818
754/* 819/*
755 * psmouse_set_state() sets new psmouse state and resets all flags and
756 * counters while holding serio lock so fighting with interrupt handler
757 * is not a concern.
758 */
759
760static void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state)
761{
762 serio_pause_rx(psmouse->ps2dev.serio);
763 psmouse->state = new_state;
764 psmouse->pktcnt = psmouse->out_of_sync = 0;
765 psmouse->ps2dev.flags = 0;
766 serio_continue_rx(psmouse->ps2dev.serio);
767}
768
769/*
770 * psmouse_activate() enables the mouse so that we get motion reports from it. 820 * psmouse_activate() enables the mouse so that we get motion reports from it.
771 */ 821 */
772 822
@@ -794,6 +844,111 @@ static void psmouse_deactivate(struct psmouse *psmouse)
794 psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); 844 psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
795} 845}
796 846
847/*
848 * psmouse_poll() - default poll hanlder. Everyone except for ALPS uses it.
849 */
850
851static int psmouse_poll(struct psmouse *psmouse)
852{
853 return ps2_command(&psmouse->ps2dev, psmouse->packet,
854 PSMOUSE_CMD_POLL | (psmouse->pktsize << 8));
855}
856
857
858/*
859 * psmouse_resync() attempts to re-validate current protocol.
860 */
861
862static void psmouse_resync(void *p)
863{
864 struct psmouse *psmouse = p, *parent = NULL;
865 struct serio *serio = psmouse->ps2dev.serio;
866 psmouse_ret_t rc = PSMOUSE_GOOD_DATA;
867 int failed = 0, enabled = 0;
868 int i;
869
870 down(&psmouse_sem);
871
872 if (psmouse->state != PSMOUSE_RESYNCING)
873 goto out;
874
875 if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
876 parent = serio_get_drvdata(serio->parent);
877 psmouse_deactivate(parent);
878 }
879
880/*
881 * Some mice don't ACK commands sent while they are in the middle of
882 * transmitting motion packet. To avoid delay we use ps2_sendbyte()
883 * instead of ps2_command() which would wait for 200ms for an ACK
884 * that may never come.
885 * As an additional quirk ALPS touchpads may not only forget to ACK
886 * disable command but will stop reporting taps, so if we see that
887 * mouse at least once ACKs disable we will do full reconnect if ACK
888 * is missing.
889 */
890 psmouse->num_resyncs++;
891
892 if (ps2_sendbyte(&psmouse->ps2dev, PSMOUSE_CMD_DISABLE, 20)) {
893 if (psmouse->num_resyncs < 3 || psmouse->acks_disable_command)
894 failed = 1;
895 } else
896 psmouse->acks_disable_command = 1;
897
898/*
899 * Poll the mouse. If it was reset the packet will be shorter than
900 * psmouse->pktsize and ps2_command will fail. We do not expect and
901 * do not handle scenario when mouse "upgrades" its protocol while
902 * disconnected since it would require additional delay. If we ever
903 * see a mouse that does it we'll adjust the code.
904 */
905 if (!failed) {
906 if (psmouse->poll(psmouse))
907 failed = 1;
908 else {
909 psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
910 for (i = 0; i < psmouse->pktsize; i++) {
911 psmouse->pktcnt++;
912 rc = psmouse->protocol_handler(psmouse, NULL);
913 if (rc != PSMOUSE_GOOD_DATA)
914 break;
915 }
916 if (rc != PSMOUSE_FULL_PACKET)
917 failed = 1;
918 psmouse_set_state(psmouse, PSMOUSE_RESYNCING);
919 }
920 }
921/*
922 * Now try to enable mouse. We try to do that even if poll failed and also
923 * repeat our attempts 5 times, otherwise we may be left out with disabled
924 * mouse.
925 */
926 for (i = 0; i < 5; i++) {
927 if (!ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE)) {
928 enabled = 1;
929 break;
930 }
931 msleep(200);
932 }
933
934 if (!enabled) {
935 printk(KERN_WARNING "psmouse.c: failed to re-enable mouse on %s\n",
936 psmouse->ps2dev.serio->phys);
937 failed = 1;
938 }
939
940 if (failed) {
941 psmouse_set_state(psmouse, PSMOUSE_IGNORE);
942 printk(KERN_INFO "psmouse.c: resync failed, issuing reconnect request\n");
943 serio_reconnect(serio);
944 } else
945 psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
946
947 if (parent)
948 psmouse_activate(parent);
949 out:
950 up(&psmouse_sem);
951}
797 952
798/* 953/*
799 * psmouse_cleanup() resets the mouse into power-on state. 954 * psmouse_cleanup() resets the mouse into power-on state.
@@ -822,6 +977,11 @@ static void psmouse_disconnect(struct serio *serio)
822 977
823 psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); 978 psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
824 979
980 /* make sure we don't have a resync in progress */
981 up(&psmouse_sem);
982 flush_workqueue(kpsmoused_wq);
983 down(&psmouse_sem);
984
825 if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { 985 if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
826 parent = serio_get_drvdata(serio->parent); 986 parent = serio_get_drvdata(serio->parent);
827 psmouse_deactivate(parent); 987 psmouse_deactivate(parent);
@@ -859,6 +1019,7 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_proto
859 1019
860 psmouse->set_rate = psmouse_set_rate; 1020 psmouse->set_rate = psmouse_set_rate;
861 psmouse->set_resolution = psmouse_set_resolution; 1021 psmouse->set_resolution = psmouse_set_resolution;
1022 psmouse->poll = psmouse_poll;
862 psmouse->protocol_handler = psmouse_process_byte; 1023 psmouse->protocol_handler = psmouse_process_byte;
863 psmouse->pktsize = 3; 1024 psmouse->pktsize = 3;
864 1025
@@ -874,6 +1035,23 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_proto
874 else 1035 else
875 psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1); 1036 psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1);
876 1037
1038 /*
1039 * If mouse's packet size is 3 there is no point in polling the
1040 * device in hopes to detect protocol reset - we won't get less
1041 * than 3 bytes response anyhow.
1042 */
1043 if (psmouse->pktsize == 3)
1044 psmouse->resync_time = 0;
1045
1046 /*
1047 * Some smart KVMs fake response to POLL command returning just
1048 * 3 bytes and messing up our resync logic, so if initial poll
1049 * fails we won't try polling the device anymore. Hopefully
1050 * such KVM will maintain initially selected protocol.
1051 */
1052 if (psmouse->resync_time && psmouse->poll(psmouse))
1053 psmouse->resync_time = 0;
1054
877 sprintf(psmouse->devname, "%s %s %s", 1055 sprintf(psmouse->devname, "%s %s %s",
878 psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name); 1056 psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name);
879 1057
@@ -914,6 +1092,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
914 goto out; 1092 goto out;
915 1093
916 ps2_init(&psmouse->ps2dev, serio); 1094 ps2_init(&psmouse->ps2dev, serio);
1095 INIT_WORK(&psmouse->resync_work, psmouse_resync, psmouse);
917 psmouse->dev = input_dev; 1096 psmouse->dev = input_dev;
918 sprintf(psmouse->phys, "%s/input0", serio->phys); 1097 sprintf(psmouse->phys, "%s/input0", serio->phys);
919 1098
@@ -934,6 +1113,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
934 psmouse->rate = psmouse_rate; 1113 psmouse->rate = psmouse_rate;
935 psmouse->resolution = psmouse_resolution; 1114 psmouse->resolution = psmouse_resolution;
936 psmouse->resetafter = psmouse_resetafter; 1115 psmouse->resetafter = psmouse_resetafter;
1116 psmouse->resync_time = parent ? 0 : psmouse_resync_time;
937 psmouse->smartscroll = psmouse_smartscroll; 1117 psmouse->smartscroll = psmouse_smartscroll;
938 1118
939 psmouse_switch_protocol(psmouse, NULL); 1119 psmouse_switch_protocol(psmouse, NULL);
@@ -1278,13 +1458,21 @@ static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp)
1278 1458
1279static int __init psmouse_init(void) 1459static int __init psmouse_init(void)
1280{ 1460{
1461 kpsmoused_wq = create_singlethread_workqueue("kpsmoused");
1462 if (!kpsmoused_wq) {
1463 printk(KERN_ERR "psmouse: failed to create kpsmoused workqueue\n");
1464 return -ENOMEM;
1465 }
1466
1281 serio_register_driver(&psmouse_drv); 1467 serio_register_driver(&psmouse_drv);
1468
1282 return 0; 1469 return 0;
1283} 1470}
1284 1471
1285static void __exit psmouse_exit(void) 1472static void __exit psmouse_exit(void)
1286{ 1473{
1287 serio_unregister_driver(&psmouse_drv); 1474 serio_unregister_driver(&psmouse_drv);
1475 destroy_workqueue(kpsmoused_wq);
1288} 1476}
1289 1477
1290module_init(psmouse_init); 1478module_init(psmouse_init);
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index 7c4192bd1279..4d9107fba6a1 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -7,7 +7,7 @@
7#define PSMOUSE_CMD_GETINFO 0x03e9 7#define PSMOUSE_CMD_GETINFO 0x03e9
8#define PSMOUSE_CMD_SETSTREAM 0x00ea 8#define PSMOUSE_CMD_SETSTREAM 0x00ea
9#define PSMOUSE_CMD_SETPOLL 0x00f0 9#define PSMOUSE_CMD_SETPOLL 0x00f0
10#define PSMOUSE_CMD_POLL 0x03eb 10#define PSMOUSE_CMD_POLL 0x00eb /* caller sets number of bytes to receive */
11#define PSMOUSE_CMD_GETID 0x02f2 11#define PSMOUSE_CMD_GETID 0x02f2
12#define PSMOUSE_CMD_SETRATE 0x10f3 12#define PSMOUSE_CMD_SETRATE 0x10f3
13#define PSMOUSE_CMD_ENABLE 0x00f4 13#define PSMOUSE_CMD_ENABLE 0x00f4
@@ -23,6 +23,7 @@
23enum psmouse_state { 23enum psmouse_state {
24 PSMOUSE_IGNORE, 24 PSMOUSE_IGNORE,
25 PSMOUSE_INITIALIZING, 25 PSMOUSE_INITIALIZING,
26 PSMOUSE_RESYNCING,
26 PSMOUSE_CMD_MODE, 27 PSMOUSE_CMD_MODE,
27 PSMOUSE_ACTIVATED, 28 PSMOUSE_ACTIVATED,
28}; 29};
@@ -38,15 +39,19 @@ struct psmouse {
38 void *private; 39 void *private;
39 struct input_dev *dev; 40 struct input_dev *dev;
40 struct ps2dev ps2dev; 41 struct ps2dev ps2dev;
42 struct work_struct resync_work;
41 char *vendor; 43 char *vendor;
42 char *name; 44 char *name;
43 unsigned char packet[8]; 45 unsigned char packet[8];
46 unsigned char badbyte;
44 unsigned char pktcnt; 47 unsigned char pktcnt;
45 unsigned char pktsize; 48 unsigned char pktsize;
46 unsigned char type; 49 unsigned char type;
50 unsigned char acks_disable_command;
47 unsigned int model; 51 unsigned int model;
48 unsigned long last; 52 unsigned long last;
49 unsigned long out_of_sync; 53 unsigned long out_of_sync;
54 unsigned long num_resyncs;
50 enum psmouse_state state; 55 enum psmouse_state state;
51 char devname[64]; 56 char devname[64];
52 char phys[32]; 57 char phys[32];
@@ -54,6 +59,7 @@ struct psmouse {
54 unsigned int rate; 59 unsigned int rate;
55 unsigned int resolution; 60 unsigned int resolution;
56 unsigned int resetafter; 61 unsigned int resetafter;
62 unsigned int resync_time;
57 unsigned int smartscroll; /* Logitech only */ 63 unsigned int smartscroll; /* Logitech only */
58 64
59 psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse, struct pt_regs *regs); 65 psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse, struct pt_regs *regs);
@@ -62,6 +68,7 @@ struct psmouse {
62 68
63 int (*reconnect)(struct psmouse *psmouse); 69 int (*reconnect)(struct psmouse *psmouse);
64 void (*disconnect)(struct psmouse *psmouse); 70 void (*disconnect)(struct psmouse *psmouse);
71 int (*poll)(struct psmouse *psmouse);
65 72
66 void (*pt_activate)(struct psmouse *psmouse); 73 void (*pt_activate)(struct psmouse *psmouse);
67 void (*pt_deactivate)(struct psmouse *psmouse); 74 void (*pt_deactivate)(struct psmouse *psmouse);
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 97cdfd6acaca..2051bec2c394 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -652,6 +652,8 @@ int synaptics_init(struct psmouse *psmouse)
652 psmouse->disconnect = synaptics_disconnect; 652 psmouse->disconnect = synaptics_disconnect;
653 psmouse->reconnect = synaptics_reconnect; 653 psmouse->reconnect = synaptics_reconnect;
654 psmouse->pktsize = 6; 654 psmouse->pktsize = 6;
655 /* Synaptics can usually stay in sync without extra help */
656 psmouse->resync_time = 0;
655 657
656 if (SYN_CAP_PASS_THROUGH(priv->capabilities)) 658 if (SYN_CAP_PASS_THROUGH(priv->capabilities))
657 synaptics_pt_create(psmouse); 659 synaptics_pt_create(psmouse);
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index 2d2f9fb3aded..a4c6f3522723 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -173,6 +173,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
173 DMI_MATCH(DMI_PRODUCT_NAME, "PC-MM20 Series"), 173 DMI_MATCH(DMI_PRODUCT_NAME, "PC-MM20 Series"),
174 }, 174 },
175 }, 175 },
176 {
177 .ident = "Sony Vaio FS-115b",
178 .matches = {
179 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
180 DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FS115B"),
181 },
182 },
176 { } 183 { }
177}; 184};
178 185
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index 8e530cc970e1..2f76813c3a64 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -59,9 +59,7 @@ static DECLARE_MUTEX(serio_sem);
59 59
60static LIST_HEAD(serio_list); 60static LIST_HEAD(serio_list);
61 61
62static struct bus_type serio_bus = { 62static struct bus_type serio_bus;
63 .name = "serio",
64};
65 63
66static void serio_add_port(struct serio *serio); 64static void serio_add_port(struct serio *serio);
67static void serio_destroy_port(struct serio *serio); 65static void serio_destroy_port(struct serio *serio);
@@ -750,11 +748,15 @@ static int serio_driver_remove(struct device *dev)
750 return 0; 748 return 0;
751} 749}
752 750
751static struct bus_type serio_bus = {
752 .name = "serio",
753 .probe = serio_driver_probe,
754 .remove = serio_driver_remove,
755};
756
753void __serio_register_driver(struct serio_driver *drv, struct module *owner) 757void __serio_register_driver(struct serio_driver *drv, struct module *owner)
754{ 758{
755 drv->driver.bus = &serio_bus; 759 drv->driver.bus = &serio_bus;
756 drv->driver.probe = serio_driver_probe;
757 drv->driver.remove = serio_driver_remove;
758 760
759 serio_queue_event(drv, owner, SERIO_REGISTER_DRIVER); 761 serio_queue_event(drv, owner, SERIO_REGISTER_DRIVER);
760} 762}
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 21d55ed4b88a..2c674023a6ac 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -11,6 +11,19 @@ menuconfig INPUT_TOUCHSCREEN
11 11
12if INPUT_TOUCHSCREEN 12if INPUT_TOUCHSCREEN
13 13
14config TOUCHSCREEN_ADS7846
15 tristate "ADS 7846 based touchscreens"
16 depends on SPI_MASTER
17 help
18 Say Y here if you have a touchscreen interface using the
19 ADS7846 controller, and your board-specific initialization
20 code includes that in its table of SPI devices.
21
22 If unsure, say N (but it's safe to say "Y").
23
24 To compile this driver as a module, choose M here: the
25 module will be called ads7846.
26
14config TOUCHSCREEN_BITSY 27config TOUCHSCREEN_BITSY
15 tristate "Compaq iPAQ H3600 (Bitsy) touchscreen" 28 tristate "Compaq iPAQ H3600 (Bitsy) touchscreen"
16 depends on SA1100_BITSY 29 depends on SA1100_BITSY
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 6842869c9a26..5e5557c43121 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -4,6 +4,7 @@
4 4
5# Each configuration option enables a list of files. 5# Each configuration option enables a list of files.
6 6
7obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o
7obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o 8obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o
8obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o 9obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o
9obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o 10obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
new file mode 100644
index 000000000000..dd8c6a9ffc76
--- /dev/null
+++ b/drivers/input/touchscreen/ads7846.c
@@ -0,0 +1,625 @@
1/*
2 * ADS7846 based touchscreen and sensor driver
3 *
4 * Copyright (c) 2005 David Brownell
5 *
6 * Using code from:
7 * - corgi_ts.c
8 * Copyright (C) 2004-2005 Richard Purdie
9 * - omap_ts.[hc], ads7846.h, ts_osk.c
10 * Copyright (C) 2002 MontaVista Software
11 * Copyright (C) 2004 Texas Instruments
12 * Copyright (C) 2005 Dirk Behme
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2 as
16 * published by the Free Software Foundation.
17 */
18#include <linux/device.h>
19#include <linux/init.h>
20#include <linux/delay.h>
21#include <linux/input.h>
22#include <linux/interrupt.h>
23#include <linux/slab.h>
24#include <linux/spi/spi.h>
25#include <linux/spi/ads7846.h>
26
27#ifdef CONFIG_ARM
28#include <asm/mach-types.h>
29#ifdef CONFIG_ARCH_OMAP
30#include <asm/arch/gpio.h>
31#endif
32
33#else
34#define set_irq_type(irq,type) do{}while(0)
35#endif
36
37
38/*
39 * This code has been lightly tested on an ads7846.
40 * Support for ads7843 and ads7845 has only been stubbed in.
41 *
42 * Not yet done: investigate the values reported. Are x/y/pressure
43 * event values sane enough for X11? How accurate are the temperature
44 * and voltage readings? (System-specific calibration should support
45 * accuracy of 0.3 degrees C; otherwise it's 2.0 degrees.)
46 *
47 * app note sbaa036 talks in more detail about accurate sampling...
48 * that ought to help in situations like LCDs inducing noise (which
49 * can also be helped by using synch signals) and more generally.
50 */
51
52#define TS_POLL_PERIOD msecs_to_jiffies(10)
53
54struct ts_event {
55 /* For portability, we can't read 12 bit values using SPI (which
56 * would make the controller deliver them as native byteorder u16
57 * with msbs zeroed). Instead, we read them as two 8-byte values,
58 * which need byteswapping then range adjustment.
59 */
60 __be16 x;
61 __be16 y;
62 __be16 z1, z2;
63};
64
65struct ads7846 {
66 struct input_dev input;
67 char phys[32];
68
69 struct spi_device *spi;
70 u16 model;
71 u16 vref_delay_usecs;
72 u16 x_plate_ohms;
73
74 struct ts_event tc;
75
76 struct spi_transfer xfer[8];
77 struct spi_message msg;
78
79 spinlock_t lock;
80 struct timer_list timer; /* P: lock */
81 unsigned pendown:1; /* P: lock */
82 unsigned pending:1; /* P: lock */
83// FIXME remove "irq_disabled"
84 unsigned irq_disabled:1; /* P: lock */
85};
86
87/* leave chip selected when we're done, for quicker re-select? */
88#if 0
89#define CS_CHANGE(xfer) ((xfer).cs_change = 1)
90#else
91#define CS_CHANGE(xfer) ((xfer).cs_change = 0)
92#endif
93
94/*--------------------------------------------------------------------------*/
95
96/* The ADS7846 has touchscreen and other sensors.
97 * Earlier ads784x chips are somewhat compatible.
98 */
99#define ADS_START (1 << 7)
100#define ADS_A2A1A0_d_y (1 << 4) /* differential */
101#define ADS_A2A1A0_d_z1 (3 << 4) /* differential */
102#define ADS_A2A1A0_d_z2 (4 << 4) /* differential */
103#define ADS_A2A1A0_d_x (5 << 4) /* differential */
104#define ADS_A2A1A0_temp0 (0 << 4) /* non-differential */
105#define ADS_A2A1A0_vbatt (2 << 4) /* non-differential */
106#define ADS_A2A1A0_vaux (6 << 4) /* non-differential */
107#define ADS_A2A1A0_temp1 (7 << 4) /* non-differential */
108#define ADS_8_BIT (1 << 3)
109#define ADS_12_BIT (0 << 3)
110#define ADS_SER (1 << 2) /* non-differential */
111#define ADS_DFR (0 << 2) /* differential */
112#define ADS_PD10_PDOWN (0 << 0) /* lowpower mode + penirq */
113#define ADS_PD10_ADC_ON (1 << 0) /* ADC on */
114#define ADS_PD10_REF_ON (2 << 0) /* vREF on + penirq */
115#define ADS_PD10_ALL_ON (3 << 0) /* ADC + vREF on */
116
117#define MAX_12BIT ((1<<12)-1)
118
119/* leave ADC powered up (disables penirq) between differential samples */
120#define READ_12BIT_DFR(x) (ADS_START | ADS_A2A1A0_d_ ## x \
121 | ADS_12_BIT | ADS_DFR)
122
123static const u8 read_y = READ_12BIT_DFR(y) | ADS_PD10_ADC_ON;
124static const u8 read_z1 = READ_12BIT_DFR(z1) | ADS_PD10_ADC_ON;
125static const u8 read_z2 = READ_12BIT_DFR(z2) | ADS_PD10_ADC_ON;
126static const u8 read_x = READ_12BIT_DFR(x) | ADS_PD10_PDOWN; /* LAST */
127
128/* single-ended samples need to first power up reference voltage;
129 * we leave both ADC and VREF powered
130 */
131#define READ_12BIT_SER(x) (ADS_START | ADS_A2A1A0_ ## x \
132 | ADS_12_BIT | ADS_SER)
133
134static const u8 ref_on = READ_12BIT_DFR(x) | ADS_PD10_ALL_ON;
135static const u8 ref_off = READ_12BIT_DFR(y) | ADS_PD10_PDOWN;
136
137/*--------------------------------------------------------------------------*/
138
139/*
140 * Non-touchscreen sensors only use single-ended conversions.
141 */
142
143struct ser_req {
144 u8 command;
145 u16 scratch;
146 __be16 sample;
147 struct spi_message msg;
148 struct spi_transfer xfer[6];
149};
150
151static int ads7846_read12_ser(struct device *dev, unsigned command)
152{
153 struct spi_device *spi = to_spi_device(dev);
154 struct ads7846 *ts = dev_get_drvdata(dev);
155 struct ser_req *req = kzalloc(sizeof *req, SLAB_KERNEL);
156 int status;
157 int sample;
158 int i;
159
160 if (!req)
161 return -ENOMEM;
162
163 INIT_LIST_HEAD(&req->msg.transfers);
164
165 /* activate reference, so it has time to settle; */
166 req->xfer[0].tx_buf = &ref_on;
167 req->xfer[0].len = 1;
168 req->xfer[1].rx_buf = &req->scratch;
169 req->xfer[1].len = 2;
170
171 /*
172 * for external VREF, 0 usec (and assume it's always on);
173 * for 1uF, use 800 usec;
174 * no cap, 100 usec.
175 */
176 req->xfer[1].delay_usecs = ts->vref_delay_usecs;
177
178 /* take sample */
179 req->command = (u8) command;
180 req->xfer[2].tx_buf = &req->command;
181 req->xfer[2].len = 1;
182 req->xfer[3].rx_buf = &req->sample;
183 req->xfer[3].len = 2;
184
185 /* REVISIT: take a few more samples, and compare ... */
186
187 /* turn off reference */
188 req->xfer[4].tx_buf = &ref_off;
189 req->xfer[4].len = 1;
190 req->xfer[5].rx_buf = &req->scratch;
191 req->xfer[5].len = 2;
192
193 CS_CHANGE(req->xfer[5]);
194
195 /* group all the transfers together, so we can't interfere with
196 * reading touchscreen state; disable penirq while sampling
197 */
198 for (i = 0; i < 6; i++)
199 spi_message_add_tail(&req->xfer[i], &req->msg);
200
201 disable_irq(spi->irq);
202 status = spi_sync(spi, &req->msg);
203 enable_irq(spi->irq);
204
205 if (req->msg.status)
206 status = req->msg.status;
207 sample = be16_to_cpu(req->sample);
208 sample = sample >> 4;
209 kfree(req);
210
211 return status ? status : sample;
212}
213
214#define SHOW(name) static ssize_t \
215name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \
216{ \
217 ssize_t v = ads7846_read12_ser(dev, \
218 READ_12BIT_SER(name) | ADS_PD10_ALL_ON); \
219 if (v < 0) \
220 return v; \
221 return sprintf(buf, "%u\n", (unsigned) v); \
222} \
223static DEVICE_ATTR(name, S_IRUGO, name ## _show, NULL);
224
225SHOW(temp0)
226SHOW(temp1)
227SHOW(vaux)
228SHOW(vbatt)
229
230/*--------------------------------------------------------------------------*/
231
232/*
233 * PENIRQ only kicks the timer. The timer only reissues the SPI transfer,
234 * to retrieve touchscreen status.
235 *
236 * The SPI transfer completion callback does the real work. It reports
237 * touchscreen events and reactivates the timer (or IRQ) as appropriate.
238 */
239
240static void ads7846_rx(void *ads)
241{
242 struct ads7846 *ts = ads;
243 unsigned Rt;
244 unsigned sync = 0;
245 u16 x, y, z1, z2;
246 unsigned long flags;
247
248 /* adjust: 12 bit samples (left aligned), built from
249 * two 8 bit values writen msb-first.
250 */
251 x = be16_to_cpu(ts->tc.x) >> 4;
252 y = be16_to_cpu(ts->tc.y) >> 4;
253 z1 = be16_to_cpu(ts->tc.z1) >> 4;
254 z2 = be16_to_cpu(ts->tc.z2) >> 4;
255
256 /* range filtering */
257 if (x == MAX_12BIT)
258 x = 0;
259
260 if (x && z1 && ts->spi->dev.power.power_state.event == PM_EVENT_ON) {
261 /* compute touch pressure resistance using equation #2 */
262 Rt = z2;
263 Rt -= z1;
264 Rt *= x;
265 Rt *= ts->x_plate_ohms;
266 Rt /= z1;
267 Rt = (Rt + 2047) >> 12;
268 } else
269 Rt = 0;
270
271 /* NOTE: "pendown" is inferred from pressure; we don't rely on
272 * being able to check nPENIRQ status, or "friendly" trigger modes
273 * (both-edges is much better than just-falling or low-level).
274 *
275 * REVISIT: some boards may require reading nPENIRQ; it's
276 * needed on 7843. and 7845 reads pressure differently...
277 *
278 * REVISIT: the touchscreen might not be connected; this code
279 * won't notice that, even if nPENIRQ never fires ...
280 */
281 if (!ts->pendown && Rt != 0) {
282 input_report_key(&ts->input, BTN_TOUCH, 1);
283 sync = 1;
284 } else if (ts->pendown && Rt == 0) {
285 input_report_key(&ts->input, BTN_TOUCH, 0);
286 sync = 1;
287 }
288
289 if (Rt) {
290 input_report_abs(&ts->input, ABS_X, x);
291 input_report_abs(&ts->input, ABS_Y, y);
292 input_report_abs(&ts->input, ABS_PRESSURE, Rt);
293 sync = 1;
294 }
295 if (sync)
296 input_sync(&ts->input);
297
298#ifdef VERBOSE
299 if (Rt || ts->pendown)
300 pr_debug("%s: %d/%d/%d%s\n", ts->spi->dev.bus_id,
301 x, y, Rt, Rt ? "" : " UP");
302#endif
303
304 /* don't retrigger while we're suspended */
305 spin_lock_irqsave(&ts->lock, flags);
306
307 ts->pendown = (Rt != 0);
308 ts->pending = 0;
309
310 if (ts->spi->dev.power.power_state.event == PM_EVENT_ON) {
311 if (ts->pendown)
312 mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD);
313 else if (ts->irq_disabled) {
314 ts->irq_disabled = 0;
315 enable_irq(ts->spi->irq);
316 }
317 }
318
319 spin_unlock_irqrestore(&ts->lock, flags);
320}
321
322static void ads7846_timer(unsigned long handle)
323{
324 struct ads7846 *ts = (void *)handle;
325 int status = 0;
326 unsigned long flags;
327
328 spin_lock_irqsave(&ts->lock, flags);
329 if (!ts->pending) {
330 ts->pending = 1;
331 if (!ts->irq_disabled) {
332 ts->irq_disabled = 1;
333 disable_irq(ts->spi->irq);
334 }
335 status = spi_async(ts->spi, &ts->msg);
336 if (status)
337 dev_err(&ts->spi->dev, "spi_async --> %d\n",
338 status);
339 }
340 spin_unlock_irqrestore(&ts->lock, flags);
341}
342
343static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs)
344{
345 ads7846_timer((unsigned long) handle);
346 return IRQ_HANDLED;
347}
348
349/*--------------------------------------------------------------------------*/
350
351static int
352ads7846_suspend(struct spi_device *spi, pm_message_t message)
353{
354 struct ads7846 *ts = dev_get_drvdata(&spi->dev);
355 unsigned long flags;
356
357 spin_lock_irqsave(&ts->lock, flags);
358
359 spi->dev.power.power_state = message;
360
361 /* are we waiting for IRQ, or polling? */
362 if (!ts->pendown) {
363 if (!ts->irq_disabled) {
364 ts->irq_disabled = 1;
365 disable_irq(ts->spi->irq);
366 }
367 } else {
368 /* polling; force a final SPI completion;
369 * that will clean things up neatly
370 */
371 if (!ts->pending)
372 mod_timer(&ts->timer, jiffies);
373
374 while (ts->pendown || ts->pending) {
375 spin_unlock_irqrestore(&ts->lock, flags);
376 udelay(10);
377 spin_lock_irqsave(&ts->lock, flags);
378 }
379 }
380
381 /* we know the chip's in lowpower mode since we always
382 * leave it that way after every request
383 */
384
385 spin_unlock_irqrestore(&ts->lock, flags);
386 return 0;
387}
388
389static int ads7846_resume(struct spi_device *spi)
390{
391 struct ads7846 *ts = dev_get_drvdata(&spi->dev);
392
393 ts->irq_disabled = 0;
394 enable_irq(ts->spi->irq);
395 spi->dev.power.power_state = PMSG_ON;
396 return 0;
397}
398
399static int __devinit ads7846_probe(struct spi_device *spi)
400{
401 struct ads7846 *ts;
402 struct ads7846_platform_data *pdata = spi->dev.platform_data;
403 struct spi_transfer *x;
404 int i;
405
406 if (!spi->irq) {
407 dev_dbg(&spi->dev, "no IRQ?\n");
408 return -ENODEV;
409 }
410
411 if (!pdata) {
412 dev_dbg(&spi->dev, "no platform data?\n");
413 return -ENODEV;
414 }
415
416 /* don't exceed max specified sample rate */
417 if (spi->max_speed_hz > (125000 * 16)) {
418 dev_dbg(&spi->dev, "f(sample) %d KHz?\n",
419 (spi->max_speed_hz/16)/1000);
420 return -EINVAL;
421 }
422
423 /* We'd set the wordsize to 12 bits ... except that some controllers
424 * will then treat the 8 bit command words as 12 bits (and drop the
425 * four MSBs of the 12 bit result). Result: inputs must be shifted
426 * to discard the four garbage LSBs.
427 */
428
429 if (!(ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL)))
430 return -ENOMEM;
431
432 dev_set_drvdata(&spi->dev, ts);
433
434 ts->spi = spi;
435 spi->dev.power.power_state = PMSG_ON;
436
437 init_timer(&ts->timer);
438 ts->timer.data = (unsigned long) ts;
439 ts->timer.function = ads7846_timer;
440
441 ts->model = pdata->model ? : 7846;
442 ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100;
443 ts->x_plate_ohms = pdata->x_plate_ohms ? : 400;
444
445 init_input_dev(&ts->input);
446
447 ts->input.dev = &spi->dev;
448 ts->input.name = "ADS784x Touchscreen";
449 snprintf(ts->phys, sizeof ts->phys, "%s/input0", spi->dev.bus_id);
450 ts->input.phys = ts->phys;
451
452 ts->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
453 ts->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
454 input_set_abs_params(&ts->input, ABS_X,
455 pdata->x_min ? : 0,
456 pdata->x_max ? : MAX_12BIT,
457 0, 0);
458 input_set_abs_params(&ts->input, ABS_Y,
459 pdata->y_min ? : 0,
460 pdata->y_max ? : MAX_12BIT,
461 0, 0);
462 input_set_abs_params(&ts->input, ABS_PRESSURE,
463 pdata->pressure_min, pdata->pressure_max, 0, 0);
464
465 input_register_device(&ts->input);
466
467 /* set up the transfers to read touchscreen state; this assumes we
468 * use formula #2 for pressure, not #3.
469 */
470 x = ts->xfer;
471
472 /* y- still on; turn on only y+ (and ADC) */
473 x->tx_buf = &read_y;
474 x->len = 1;
475 x++;
476 x->rx_buf = &ts->tc.y;
477 x->len = 2;
478 x++;
479
480 /* turn y+ off, x- on; we'll use formula #2 */
481 if (ts->model == 7846) {
482 x->tx_buf = &read_z1;
483 x->len = 1;
484 x++;
485 x->rx_buf = &ts->tc.z1;
486 x->len = 2;
487 x++;
488
489 x->tx_buf = &read_z2;
490 x->len = 1;
491 x++;
492 x->rx_buf = &ts->tc.z2;
493 x->len = 2;
494 x++;
495 }
496
497 /* turn y- off, x+ on, then leave in lowpower */
498 x->tx_buf = &read_x;
499 x->len = 1;
500 x++;
501 x->rx_buf = &ts->tc.x;
502 x->len = 2;
503 x++;
504
505 CS_CHANGE(x[-1]);
506
507 for (i = 0; i < x - ts->xfer; i++)
508 spi_message_add_tail(&ts->xfer[i], &ts->msg);
509 ts->msg.complete = ads7846_rx;
510 ts->msg.context = ts;
511
512 if (request_irq(spi->irq, ads7846_irq, SA_SAMPLE_RANDOM,
513 spi->dev.bus_id, ts)) {
514 dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq);
515 input_unregister_device(&ts->input);
516 kfree(ts);
517 return -EBUSY;
518 }
519 set_irq_type(spi->irq, IRQT_FALLING);
520
521 dev_info(&spi->dev, "touchscreen, irq %d\n", spi->irq);
522
523 /* take a first sample, leaving nPENIRQ active; avoid
524 * the touchscreen, in case it's not connected.
525 */
526 (void) ads7846_read12_ser(&spi->dev,
527 READ_12BIT_SER(vaux) | ADS_PD10_ALL_ON);
528
529 /* ads7843/7845 don't have temperature sensors, and
530 * use the other sensors a bit differently too
531 */
532 if (ts->model == 7846) {
533 device_create_file(&spi->dev, &dev_attr_temp0);
534 device_create_file(&spi->dev, &dev_attr_temp1);
535 }
536 if (ts->model != 7845)
537 device_create_file(&spi->dev, &dev_attr_vbatt);
538 device_create_file(&spi->dev, &dev_attr_vaux);
539
540 return 0;
541}
542
543static int __devexit ads7846_remove(struct spi_device *spi)
544{
545 struct ads7846 *ts = dev_get_drvdata(&spi->dev);
546
547 ads7846_suspend(spi, PMSG_SUSPEND);
548 free_irq(ts->spi->irq, ts);
549 if (ts->irq_disabled)
550 enable_irq(ts->spi->irq);
551
552 if (ts->model == 7846) {
553 device_remove_file(&spi->dev, &dev_attr_temp0);
554 device_remove_file(&spi->dev, &dev_attr_temp1);
555 }
556 if (ts->model != 7845)
557 device_remove_file(&spi->dev, &dev_attr_vbatt);
558 device_remove_file(&spi->dev, &dev_attr_vaux);
559
560 input_unregister_device(&ts->input);
561 kfree(ts);
562
563 dev_dbg(&spi->dev, "unregistered touchscreen\n");
564 return 0;
565}
566
567static struct spi_driver ads7846_driver = {
568 .driver = {
569 .name = "ads7846",
570 .bus = &spi_bus_type,
571 .owner = THIS_MODULE,
572 },
573 .probe = ads7846_probe,
574 .remove = __devexit_p(ads7846_remove),
575 .suspend = ads7846_suspend,
576 .resume = ads7846_resume,
577};
578
579static int __init ads7846_init(void)
580{
581 /* grr, board-specific init should stay out of drivers!! */
582
583#ifdef CONFIG_ARCH_OMAP
584 if (machine_is_omap_osk()) {
585 /* GPIO4 = PENIRQ; GPIO6 = BUSY */
586 omap_request_gpio(4);
587 omap_set_gpio_direction(4, 1);
588 omap_request_gpio(6);
589 omap_set_gpio_direction(6, 1);
590 }
591 // also TI 1510 Innovator, bitbanging through FPGA
592 // also Nokia 770
593 // also Palm Tungsten T2
594#endif
595
596 // PXA:
597 // also Dell Axim X50
598 // also HP iPaq H191x/H192x/H415x/H435x
599 // also Intel Lubbock (additional to UCB1400; as temperature sensor)
600 // also Sharp Zaurus C7xx, C8xx (corgi/sheperd/husky)
601
602 // Atmel at91sam9261-EK uses ads7843
603
604 // also various AMD Au1x00 devel boards
605
606 return spi_register_driver(&ads7846_driver);
607}
608module_init(ads7846_init);
609
610static void __exit ads7846_exit(void)
611{
612 spi_unregister_driver(&ads7846_driver);
613
614#ifdef CONFIG_ARCH_OMAP
615 if (machine_is_omap_osk()) {
616 omap_free_gpio(4);
617 omap_free_gpio(6);
618 }
619#endif
620
621}
622module_exit(ads7846_exit);
623
624MODULE_DESCRIPTION("ADS7846 TouchScreen Driver");
625MODULE_LICENSE("GPL");
diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c
index 5d8ee7368f7b..4abe5ff10e72 100644
--- a/drivers/isdn/hisax/avm_pci.c
+++ b/drivers/isdn/hisax/avm_pci.c
@@ -358,7 +358,7 @@ hdlc_fill_fifo(struct BCState *bcs)
358 } 358 }
359} 359}
360 360
361static inline void 361static void
362HDLC_irq(struct BCState *bcs, u_int stat) { 362HDLC_irq(struct BCState *bcs, u_int stat) {
363 int len; 363 int len;
364 struct sk_buff *skb; 364 struct sk_buff *skb;
diff --git a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c
index b62d6b30b72b..b0ff1cc97d7c 100644
--- a/drivers/isdn/hisax/diva.c
+++ b/drivers/isdn/hisax/diva.c
@@ -476,7 +476,7 @@ Memhscx_fill_fifo(struct BCState *bcs)
476 } 476 }
477} 477}
478 478
479static inline void 479static void
480Memhscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) 480Memhscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
481{ 481{
482 u_char r; 482 u_char r;
diff --git a/drivers/isdn/hisax/hscx_irq.c b/drivers/isdn/hisax/hscx_irq.c
index 5fe9d42d03a3..7b1ad5e4ecda 100644
--- a/drivers/isdn/hisax/hscx_irq.c
+++ b/drivers/isdn/hisax/hscx_irq.c
@@ -119,7 +119,7 @@ hscx_fill_fifo(struct BCState *bcs)
119 } 119 }
120} 120}
121 121
122static inline void 122static void
123hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) 123hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
124{ 124{
125 u_char r; 125 u_char r;
@@ -221,7 +221,7 @@ hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
221 } 221 }
222} 222}
223 223
224static inline void 224static void
225hscx_int_main(struct IsdnCardState *cs, u_char val) 225hscx_int_main(struct IsdnCardState *cs, u_char val)
226{ 226{
227 227
diff --git a/drivers/isdn/hisax/jade_irq.c b/drivers/isdn/hisax/jade_irq.c
index 08563400e4fd..1f201af15a0f 100644
--- a/drivers/isdn/hisax/jade_irq.c
+++ b/drivers/isdn/hisax/jade_irq.c
@@ -110,7 +110,7 @@ jade_fill_fifo(struct BCState *bcs)
110} 110}
111 111
112 112
113static inline void 113static void
114jade_interrupt(struct IsdnCardState *cs, u_char val, u_char jade) 114jade_interrupt(struct IsdnCardState *cs, u_char val, u_char jade)
115{ 115{
116 u_char r; 116 u_char r;
diff --git a/drivers/macintosh/macio-adb.c b/drivers/macintosh/macio-adb.c
index cf6a6f2248ac..314fc0830d90 100644
--- a/drivers/macintosh/macio-adb.c
+++ b/drivers/macintosh/macio-adb.c
@@ -17,6 +17,7 @@
17#include <asm/irq.h> 17#include <asm/irq.h>
18#include <asm/system.h> 18#include <asm/system.h>
19#include <linux/init.h> 19#include <linux/init.h>
20#include <linux/ioport.h>
20 21
21struct preg { 22struct preg {
22 unsigned char r; 23 unsigned char r;
@@ -88,24 +89,26 @@ int macio_probe(void)
88int macio_init(void) 89int macio_init(void)
89{ 90{
90 struct device_node *adbs; 91 struct device_node *adbs;
92 struct resource r;
91 93
92 adbs = find_compatible_devices("adb", "chrp,adb0"); 94 adbs = find_compatible_devices("adb", "chrp,adb0");
93 if (adbs == 0) 95 if (adbs == 0)
94 return -ENXIO; 96 return -ENXIO;
95 97
96#if 0 98#if 0
97 { int i; 99 { int i = 0;
98 100
99 printk("macio_adb_init: node = %p, addrs =", adbs->node); 101 printk("macio_adb_init: node = %p, addrs =", adbs->node);
100 for (i = 0; i < adbs->n_addrs; ++i) 102 while(!of_address_to_resource(adbs, i, &r))
101 printk(" %x(%x)", adbs->addrs[i].address, adbs->addrs[i].size); 103 printk(" %x(%x)", r.start, r.end - r.start);
102 printk(", intrs ="); 104 printk(", intrs =");
103 for (i = 0; i < adbs->n_intrs; ++i) 105 for (i = 0; i < adbs->n_intrs; ++i)
104 printk(" %x", adbs->intrs[i].line); 106 printk(" %x", adbs->intrs[i].line);
105 printk("\n"); } 107 printk("\n"); }
106#endif 108#endif
107 109 if (of_address_to_resource(adbs, 0, &r))
108 adb = ioremap(adbs->addrs->address, sizeof(struct adb_regs)); 110 return -ENXIO;
111 adb = ioremap(r.start, sizeof(struct adb_regs));
109 112
110 out_8(&adb->ctrl.r, 0); 113 out_8(&adb->ctrl.r, 0);
111 out_8(&adb->intr.r, 0); 114 out_8(&adb->intr.r, 0);
diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c
index 2a545ceb523b..ed6d3174d660 100644
--- a/drivers/macintosh/macio_asic.c
+++ b/drivers/macintosh/macio_asic.c
@@ -211,6 +211,9 @@ struct bus_type macio_bus_type = {
211 .name = "macio", 211 .name = "macio",
212 .match = macio_bus_match, 212 .match = macio_bus_match,
213 .uevent = macio_uevent, 213 .uevent = macio_uevent,
214 .probe = macio_device_probe,
215 .remove = macio_device_remove,
216 .shutdown = macio_device_shutdown,
214 .suspend = macio_device_suspend, 217 .suspend = macio_device_suspend,
215 .resume = macio_device_resume, 218 .resume = macio_device_resume,
216 .dev_attrs = macio_dev_attrs, 219 .dev_attrs = macio_dev_attrs,
@@ -528,9 +531,6 @@ int macio_register_driver(struct macio_driver *drv)
528 /* initialize common driver fields */ 531 /* initialize common driver fields */
529 drv->driver.name = drv->name; 532 drv->driver.name = drv->name;
530 drv->driver.bus = &macio_bus_type; 533 drv->driver.bus = &macio_bus_type;
531 drv->driver.probe = macio_device_probe;
532 drv->driver.remove = macio_device_remove;
533 drv->driver.shutdown = macio_device_shutdown;
534 534
535 /* register with core */ 535 /* register with core */
536 count = driver_register(&drv->driver); 536 count = driver_register(&drv->driver);
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 76a189ceb529..eae4473eadde 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -200,7 +200,7 @@ out:
200/* if page is completely empty, put it back on the free list, or dealloc it */ 200/* if page is completely empty, put it back on the free list, or dealloc it */
201/* if page was hijacked, unmark the flag so it might get alloced next time */ 201/* if page was hijacked, unmark the flag so it might get alloced next time */
202/* Note: lock should be held when calling this */ 202/* Note: lock should be held when calling this */
203static inline void bitmap_checkfree(struct bitmap *bitmap, unsigned long page) 203static void bitmap_checkfree(struct bitmap *bitmap, unsigned long page)
204{ 204{
205 char *ptr; 205 char *ptr;
206 206
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index a601a427885c..e7a650f9ca07 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -228,7 +228,7 @@ static struct crypt_iv_operations crypt_iv_essiv_ops = {
228}; 228};
229 229
230 230
231static inline int 231static int
232crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist *out, 232crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist *out,
233 struct scatterlist *in, unsigned int length, 233 struct scatterlist *in, unsigned int length,
234 int write, sector_t sector) 234 int write, sector_t sector)
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 561bda5011e0..1235135b384b 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -598,7 +598,7 @@ static int dev_create(struct dm_ioctl *param, size_t param_size)
598/* 598/*
599 * Always use UUID for lookups if it's present, otherwise use name or dev. 599 * Always use UUID for lookups if it's present, otherwise use name or dev.
600 */ 600 */
601static inline struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param) 601static struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param)
602{ 602{
603 if (*param->uuid) 603 if (*param->uuid)
604 return __get_uuid_cell(param->uuid); 604 return __get_uuid_cell(param->uuid);
@@ -608,7 +608,7 @@ static inline struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param)
608 return dm_get_mdptr(huge_decode_dev(param->dev)); 608 return dm_get_mdptr(huge_decode_dev(param->dev));
609} 609}
610 610
611static inline struct mapped_device *find_device(struct dm_ioctl *param) 611static struct mapped_device *find_device(struct dm_ioctl *param)
612{ 612{
613 struct hash_cell *hc; 613 struct hash_cell *hc;
614 struct mapped_device *md = NULL; 614 struct mapped_device *md = NULL;
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 4b9dd8fb1e5c..87727d84dbba 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -691,7 +691,7 @@ static void copy_callback(int read_err, unsigned int write_err, void *context)
691/* 691/*
692 * Dispatches the copy operation to kcopyd. 692 * Dispatches the copy operation to kcopyd.
693 */ 693 */
694static inline void start_copy(struct pending_exception *pe) 694static void start_copy(struct pending_exception *pe)
695{ 695{
696 struct dm_snapshot *s = pe->snap; 696 struct dm_snapshot *s = pe->snap;
697 struct io_region src, dest; 697 struct io_region src, dest;
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 097d1e540090..8c16359f8b01 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -293,7 +293,7 @@ struct dm_table *dm_get_table(struct mapped_device *md)
293 * Decrements the number of outstanding ios that a bio has been 293 * Decrements the number of outstanding ios that a bio has been
294 * cloned into, completing the original io if necc. 294 * cloned into, completing the original io if necc.
295 */ 295 */
296static inline void dec_pending(struct dm_io *io, int error) 296static void dec_pending(struct dm_io *io, int error)
297{ 297{
298 if (error) 298 if (error)
299 io->error = error; 299 io->error = error;
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index a06ff91f27e2..d39f584cd8b3 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -176,7 +176,7 @@ static void put_all_bios(conf_t *conf, r1bio_t *r1_bio)
176 } 176 }
177} 177}
178 178
179static inline void free_r1bio(r1bio_t *r1_bio) 179static void free_r1bio(r1bio_t *r1_bio)
180{ 180{
181 conf_t *conf = mddev_to_conf(r1_bio->mddev); 181 conf_t *conf = mddev_to_conf(r1_bio->mddev);
182 182
@@ -190,7 +190,7 @@ static inline void free_r1bio(r1bio_t *r1_bio)
190 mempool_free(r1_bio, conf->r1bio_pool); 190 mempool_free(r1_bio, conf->r1bio_pool);
191} 191}
192 192
193static inline void put_buf(r1bio_t *r1_bio) 193static void put_buf(r1bio_t *r1_bio)
194{ 194{
195 conf_t *conf = mddev_to_conf(r1_bio->mddev); 195 conf_t *conf = mddev_to_conf(r1_bio->mddev);
196 int i; 196 int i;
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 9e658e519a27..9130d051b474 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -176,7 +176,7 @@ static void put_all_bios(conf_t *conf, r10bio_t *r10_bio)
176 } 176 }
177} 177}
178 178
179static inline void free_r10bio(r10bio_t *r10_bio) 179static void free_r10bio(r10bio_t *r10_bio)
180{ 180{
181 conf_t *conf = mddev_to_conf(r10_bio->mddev); 181 conf_t *conf = mddev_to_conf(r10_bio->mddev);
182 182
@@ -190,7 +190,7 @@ static inline void free_r10bio(r10bio_t *r10_bio)
190 mempool_free(r10_bio, conf->r10bio_pool); 190 mempool_free(r10_bio, conf->r10bio_pool);
191} 191}
192 192
193static inline void put_buf(r10bio_t *r10_bio) 193static void put_buf(r10bio_t *r10_bio)
194{ 194{
195 conf_t *conf = mddev_to_conf(r10_bio->mddev); 195 conf_t *conf = mddev_to_conf(r10_bio->mddev);
196 196
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 54f4a9847e38..25976bfb6f9c 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -69,7 +69,7 @@
69 69
70static void print_raid5_conf (raid5_conf_t *conf); 70static void print_raid5_conf (raid5_conf_t *conf);
71 71
72static inline void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh) 72static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
73{ 73{
74 if (atomic_dec_and_test(&sh->count)) { 74 if (atomic_dec_and_test(&sh->count)) {
75 if (!list_empty(&sh->lru)) 75 if (!list_empty(&sh->lru))
@@ -118,7 +118,7 @@ static inline void remove_hash(struct stripe_head *sh)
118 hlist_del_init(&sh->hash); 118 hlist_del_init(&sh->hash);
119} 119}
120 120
121static inline void insert_hash(raid5_conf_t *conf, struct stripe_head *sh) 121static void insert_hash(raid5_conf_t *conf, struct stripe_head *sh)
122{ 122{
123 struct hlist_head *hp = stripe_hash(conf, sh->sector); 123 struct hlist_head *hp = stripe_hash(conf, sh->sector);
124 124
@@ -178,7 +178,7 @@ static int grow_buffers(struct stripe_head *sh, int num)
178 178
179static void raid5_build_block (struct stripe_head *sh, int i); 179static void raid5_build_block (struct stripe_head *sh, int i);
180 180
181static inline void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx) 181static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx)
182{ 182{
183 raid5_conf_t *conf = sh->raid_conf; 183 raid5_conf_t *conf = sh->raid_conf;
184 int disks = conf->raid_disks, i; 184 int disks = conf->raid_disks, i;
@@ -1415,7 +1415,7 @@ static void handle_stripe(struct stripe_head *sh)
1415 } 1415 }
1416} 1416}
1417 1417
1418static inline void raid5_activate_delayed(raid5_conf_t *conf) 1418static void raid5_activate_delayed(raid5_conf_t *conf)
1419{ 1419{
1420 if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) { 1420 if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) {
1421 while (!list_empty(&conf->delayed_list)) { 1421 while (!list_empty(&conf->delayed_list)) {
@@ -1431,7 +1431,7 @@ static inline void raid5_activate_delayed(raid5_conf_t *conf)
1431 } 1431 }
1432} 1432}
1433 1433
1434static inline void activate_bit_delay(raid5_conf_t *conf) 1434static void activate_bit_delay(raid5_conf_t *conf)
1435{ 1435{
1436 /* device_lock is held */ 1436 /* device_lock is held */
1437 struct list_head head; 1437 struct list_head head;
diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
index 8c823d686a60..f618a53b98be 100644
--- a/drivers/md/raid6main.c
+++ b/drivers/md/raid6main.c
@@ -88,7 +88,7 @@ static inline int raid6_next_disk(int disk, int raid_disks)
88 88
89static void print_raid6_conf (raid6_conf_t *conf); 89static void print_raid6_conf (raid6_conf_t *conf);
90 90
91static inline void __release_stripe(raid6_conf_t *conf, struct stripe_head *sh) 91static void __release_stripe(raid6_conf_t *conf, struct stripe_head *sh)
92{ 92{
93 if (atomic_dec_and_test(&sh->count)) { 93 if (atomic_dec_and_test(&sh->count)) {
94 if (!list_empty(&sh->lru)) 94 if (!list_empty(&sh->lru))
@@ -197,7 +197,7 @@ static int grow_buffers(struct stripe_head *sh, int num)
197 197
198static void raid6_build_block (struct stripe_head *sh, int i); 198static void raid6_build_block (struct stripe_head *sh, int i);
199 199
200static inline void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx) 200static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx)
201{ 201{
202 raid6_conf_t *conf = sh->raid_conf; 202 raid6_conf_t *conf = sh->raid_conf;
203 int disks = conf->raid_disks, i; 203 int disks = conf->raid_disks, i;
@@ -1577,7 +1577,7 @@ static void handle_stripe(struct stripe_head *sh, struct page *tmp_page)
1577 } 1577 }
1578} 1578}
1579 1579
1580static inline void raid6_activate_delayed(raid6_conf_t *conf) 1580static void raid6_activate_delayed(raid6_conf_t *conf)
1581{ 1581{
1582 if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) { 1582 if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) {
1583 while (!list_empty(&conf->delayed_list)) { 1583 while (!list_empty(&conf->delayed_list)) {
@@ -1593,7 +1593,7 @@ static inline void raid6_activate_delayed(raid6_conf_t *conf)
1593 } 1593 }
1594} 1594}
1595 1595
1596static inline void activate_bit_delay(raid6_conf_t *conf) 1596static void activate_bit_delay(raid6_conf_t *conf)
1597{ 1597{
1598 /* device_lock is held */ 1598 /* device_lock is held */
1599 struct list_head head; 1599 struct list_head head;
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
index f65f64b00ff3..44fcbe77c8f9 100644
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c
+++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
@@ -779,9 +779,8 @@ static int __init dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
779 return 0; 779 return 0;
780} 780}
781 781
782static int dvb_bt8xx_probe(struct device *dev) 782static int dvb_bt8xx_probe(struct bttv_sub_device *sub)
783{ 783{
784 struct bttv_sub_device *sub = to_bttv_sub_dev(dev);
785 struct dvb_bt8xx_card *card; 784 struct dvb_bt8xx_card *card;
786 struct pci_dev* bttv_pci_dev; 785 struct pci_dev* bttv_pci_dev;
787 int ret; 786 int ret;
@@ -890,13 +889,13 @@ static int dvb_bt8xx_probe(struct device *dev)
890 return ret; 889 return ret;
891 } 890 }
892 891
893 dev_set_drvdata(dev, card); 892 dev_set_drvdata(&sub->dev, card);
894 return 0; 893 return 0;
895} 894}
896 895
897static int dvb_bt8xx_remove(struct device *dev) 896static int dvb_bt8xx_remove(struct bttv_sub_device *sub)
898{ 897{
899 struct dvb_bt8xx_card *card = dev_get_drvdata(dev); 898 struct dvb_bt8xx_card *card = dev_get_drvdata(&sub->dev);
900 899
901 dprintk("dvb_bt8xx: unloading card%d\n", card->bttv_nr); 900 dprintk("dvb_bt8xx: unloading card%d\n", card->bttv_nr);
902 901
@@ -919,14 +918,14 @@ static int dvb_bt8xx_remove(struct device *dev)
919static struct bttv_sub_driver driver = { 918static struct bttv_sub_driver driver = {
920 .drv = { 919 .drv = {
921 .name = "dvb-bt8xx", 920 .name = "dvb-bt8xx",
922 .probe = dvb_bt8xx_probe,
923 .remove = dvb_bt8xx_remove,
924 /* FIXME:
925 * .shutdown = dvb_bt8xx_shutdown,
926 * .suspend = dvb_bt8xx_suspend,
927 * .resume = dvb_bt8xx_resume,
928 */
929 }, 921 },
922 .probe = dvb_bt8xx_probe,
923 .remove = dvb_bt8xx_remove,
924 /* FIXME:
925 * .shutdown = dvb_bt8xx_shutdown,
926 * .suspend = dvb_bt8xx_suspend,
927 * .resume = dvb_bt8xx_resume,
928 */
930}; 929};
931 930
932static int __init dvb_bt8xx_init(void) 931static int __init dvb_bt8xx_init(void)
diff --git a/drivers/media/video/bttv-gpio.c b/drivers/media/video/bttv-gpio.c
index d64accc17b0e..c4d5e2b70c28 100644
--- a/drivers/media/video/bttv-gpio.c
+++ b/drivers/media/video/bttv-gpio.c
@@ -47,9 +47,29 @@ static int bttv_sub_bus_match(struct device *dev, struct device_driver *drv)
47 return 0; 47 return 0;
48} 48}
49 49
50static int bttv_sub_probe(struct device *dev)
51{
52 struct bttv_sub_device *sdev = to_bttv_sub_dev(dev);
53 struct bttv_sub_driver *sub = to_bttv_sub_drv(dev->driver);
54
55 return sub->probe ? sub->probe(sdev) : -ENODEV;
56}
57
58static int bttv_sub_remove(struct device *dev)
59{
60 struct bttv_sub_device *sdev = to_bttv_sub_dev(dev);
61 struct bttv_sub_driver *sub = to_bttv_sub_drv(dev->driver);
62
63 if (sub->remove)
64 sub->remove(sdev);
65 return 0;
66}
67
50struct bus_type bttv_sub_bus_type = { 68struct bus_type bttv_sub_bus_type = {
51 .name = "bttv-sub", 69 .name = "bttv-sub",
52 .match = &bttv_sub_bus_match, 70 .match = &bttv_sub_bus_match,
71 .probe = bttv_sub_probe,
72 .remove = bttv_sub_remove,
53}; 73};
54EXPORT_SYMBOL(bttv_sub_bus_type); 74EXPORT_SYMBOL(bttv_sub_bus_type);
55 75
diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h
index e370d74f2a1b..9908c8e0c951 100644
--- a/drivers/media/video/bttv.h
+++ b/drivers/media/video/bttv.h
@@ -365,6 +365,8 @@ struct bttv_sub_device {
365struct bttv_sub_driver { 365struct bttv_sub_driver {
366 struct device_driver drv; 366 struct device_driver drv;
367 char wanted[BUS_ID_SIZE]; 367 char wanted[BUS_ID_SIZE];
368 int (*probe)(struct bttv_sub_device *sub);
369 void (*remove)(struct bttv_sub_device *sub);
368 void (*gpio_irq)(struct bttv_sub_device *sub); 370 void (*gpio_irq)(struct bttv_sub_device *sub);
369}; 371};
370#define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv) 372#define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv)
diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c
index e86b522938fd..9094fa9f2ecb 100644
--- a/drivers/media/video/tvp5150.c
+++ b/drivers/media/video/tvp5150.c
@@ -93,7 +93,7 @@ struct tvp5150 {
93 int sat; 93 int sat;
94}; 94};
95 95
96static inline int tvp5150_read(struct i2c_client *c, unsigned char addr) 96static int tvp5150_read(struct i2c_client *c, unsigned char addr)
97{ 97{
98 unsigned char buffer[1]; 98 unsigned char buffer[1];
99 int rc; 99 int rc;
diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig
index 1883d22cffeb..e67cf15e9c39 100644
--- a/drivers/message/fusion/Kconfig
+++ b/drivers/message/fusion/Kconfig
@@ -23,6 +23,7 @@ config FUSION_FC
23 tristate "Fusion MPT ScsiHost drivers for FC" 23 tristate "Fusion MPT ScsiHost drivers for FC"
24 depends on PCI && SCSI 24 depends on PCI && SCSI
25 select FUSION 25 select FUSION
26 select SCSI_FC_ATTRS
26 ---help--- 27 ---help---
27 SCSI HOST support for a Fiber Channel host adapters. 28 SCSI HOST support for a Fiber Channel host adapters.
28 29
diff --git a/drivers/message/fusion/lsi/mpi.h b/drivers/message/fusion/lsi/mpi.h
index b61e3d175070..02cdc840a06b 100644
--- a/drivers/message/fusion/lsi/mpi.h
+++ b/drivers/message/fusion/lsi/mpi.h
@@ -6,7 +6,7 @@
6 * Title: MPI Message independent structures and definitions 6 * Title: MPI Message independent structures and definitions
7 * Creation Date: July 27, 2000 7 * Creation Date: July 27, 2000
8 * 8 *
9 * mpi.h Version: 01.05.08 9 * mpi.h Version: 01.05.10
10 * 10 *
11 * Version History 11 * Version History
12 * --------------- 12 * ---------------
@@ -74,6 +74,8 @@
74 * 06-24-05 01.05.08 Added function codes for SCSI IO 32 and 74 * 06-24-05 01.05.08 Added function codes for SCSI IO 32 and
75 * TargetAssistExtended requests. 75 * TargetAssistExtended requests.
76 * Added EEDP IOCStatus codes. 76 * Added EEDP IOCStatus codes.
77 * 08-03-05 01.05.09 Bumped MPI_HEADER_VERSION_UNIT.
78 * 08-30-05 01.05.10 Added 2 new IOCStatus codes for Target.
77 * -------------------------------------------------------------------------- 79 * --------------------------------------------------------------------------
78 */ 80 */
79 81
@@ -104,7 +106,7 @@
104/* Note: The major versions of 0xe0 through 0xff are reserved */ 106/* Note: The major versions of 0xe0 through 0xff are reserved */
105 107
106/* versioning for this MPI header set */ 108/* versioning for this MPI header set */
107#define MPI_HEADER_VERSION_UNIT (0x0A) 109#define MPI_HEADER_VERSION_UNIT (0x0C)
108#define MPI_HEADER_VERSION_DEV (0x00) 110#define MPI_HEADER_VERSION_DEV (0x00)
109#define MPI_HEADER_VERSION_UNIT_MASK (0xFF00) 111#define MPI_HEADER_VERSION_UNIT_MASK (0xFF00)
110#define MPI_HEADER_VERSION_UNIT_SHIFT (8) 112#define MPI_HEADER_VERSION_UNIT_SHIFT (8)
@@ -711,6 +713,8 @@ typedef struct _MSG_DEFAULT_REPLY
711#define MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR (0x006D) 713#define MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR (0x006D)
712#define MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA (0x006E) 714#define MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA (0x006E)
713#define MPI_IOCSTATUS_TARGET_IU_TOO_SHORT (0x006F) 715#define MPI_IOCSTATUS_TARGET_IU_TOO_SHORT (0x006F)
716#define MPI_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT (0x0070)
717#define MPI_IOCSTATUS_TARGET_NAK_RECEIVED (0x0071)
714 718
715/****************************************************************************/ 719/****************************************************************************/
716/* Additional FCP target values (obsolete) */ 720/* Additional FCP target values (obsolete) */
@@ -745,7 +749,7 @@ typedef struct _MSG_DEFAULT_REPLY
745#define MPI_IOCSTATUS_LAN_CANCELED (0x0087) 749#define MPI_IOCSTATUS_LAN_CANCELED (0x0087)
746 750
747/****************************************************************************/ 751/****************************************************************************/
748/* Serial Attached SCSI values */ 752/* Serial Attached SCSI values */
749/****************************************************************************/ 753/****************************************************************************/
750 754
751#define MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED (0x0090) 755#define MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED (0x0090)
diff --git a/drivers/message/fusion/lsi/mpi_cnfg.h b/drivers/message/fusion/lsi/mpi_cnfg.h
index d8339896f734..b1becec27e1b 100644
--- a/drivers/message/fusion/lsi/mpi_cnfg.h
+++ b/drivers/message/fusion/lsi/mpi_cnfg.h
@@ -6,7 +6,7 @@
6 * Title: MPI Config message, structures, and Pages 6 * Title: MPI Config message, structures, and Pages
7 * Creation Date: July 27, 2000 7 * Creation Date: July 27, 2000
8 * 8 *
9 * mpi_cnfg.h Version: 01.05.09 9 * mpi_cnfg.h Version: 01.05.11
10 * 10 *
11 * Version History 11 * Version History
12 * --------------- 12 * ---------------
@@ -249,6 +249,23 @@
249 * Added OwnerDevHandle and Flags field to SAS PHY Page 0. 249 * Added OwnerDevHandle and Flags field to SAS PHY Page 0.
250 * Added IOC GPIO Flags define to SAS Enclosure Page 0. 250 * Added IOC GPIO Flags define to SAS Enclosure Page 0.
251 * Fixed the value for MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT. 251 * Fixed the value for MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT.
252 * 08-03-05 01.05.10 Removed ISDataScrubRate and ISResyncRate from
253 * Manufacturing Page 4.
254 * Added MPI_IOUNITPAGE1_SATA_WRITE_CACHE_DISABLE bit.
255 * Added NumDevsPerEnclosure field to SAS IO Unit page 2.
256 * Added MPI_SAS_IOUNIT2_FLAGS_HOST_ASSIGNED_PHYS_MAP
257 * define.
258 * Added EnclosureHandle field to SAS Expander page 0.
259 * Removed redundant NumTableEntriesProg field from SAS
260 * Expander Page 1.
261 * 08-30-05 01.05.11 Added DeviceID for FC949E and changed the DeviceID for
262 * SAS1078.
263 * Added more defines for Manufacturing Page 4 Flags field.
264 * Added more defines for IOCSettings and added
265 * ExpanderSpinup field to Bios Page 1.
266 * Added postpone SATA Init bit to SAS IO Unit Page 1
267 * ControlFlags.
268 * Changed LogEntry format for Log Page 0.
252 * -------------------------------------------------------------------------- 269 * --------------------------------------------------------------------------
253 */ 270 */
254 271
@@ -494,7 +511,7 @@ typedef struct _MSG_CONFIG_REPLY
494#define MPI_MANUFACTPAGE_DEVICEID_FC929X (0x0626) 511#define MPI_MANUFACTPAGE_DEVICEID_FC929X (0x0626)
495#define MPI_MANUFACTPAGE_DEVICEID_FC939X (0x0642) 512#define MPI_MANUFACTPAGE_DEVICEID_FC939X (0x0642)
496#define MPI_MANUFACTPAGE_DEVICEID_FC949X (0x0640) 513#define MPI_MANUFACTPAGE_DEVICEID_FC949X (0x0640)
497#define MPI_MANUFACTPAGE_DEVICEID_FC949ES (0x0646) 514#define MPI_MANUFACTPAGE_DEVICEID_FC949E (0x0646)
498/* SCSI */ 515/* SCSI */
499#define MPI_MANUFACTPAGE_DEVID_53C1030 (0x0030) 516#define MPI_MANUFACTPAGE_DEVID_53C1030 (0x0030)
500#define MPI_MANUFACTPAGE_DEVID_53C1030ZC (0x0031) 517#define MPI_MANUFACTPAGE_DEVID_53C1030ZC (0x0031)
@@ -510,7 +527,7 @@ typedef struct _MSG_CONFIG_REPLY
510#define MPI_MANUFACTPAGE_DEVID_SAS1066E (0x005A) 527#define MPI_MANUFACTPAGE_DEVID_SAS1066E (0x005A)
511#define MPI_MANUFACTPAGE_DEVID_SAS1068 (0x0054) 528#define MPI_MANUFACTPAGE_DEVID_SAS1068 (0x0054)
512#define MPI_MANUFACTPAGE_DEVID_SAS1068E (0x0058) 529#define MPI_MANUFACTPAGE_DEVID_SAS1068E (0x0058)
513#define MPI_MANUFACTPAGE_DEVID_SAS1078 (0x0060) 530#define MPI_MANUFACTPAGE_DEVID_SAS1078 (0x0062)
514 531
515 532
516typedef struct _CONFIG_PAGE_MANUFACTURING_0 533typedef struct _CONFIG_PAGE_MANUFACTURING_0
@@ -602,9 +619,7 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_4
602 U32 IMVolumeSettings; /* 50h */ 619 U32 IMVolumeSettings; /* 50h */
603 U32 Reserved3; /* 54h */ 620 U32 Reserved3; /* 54h */
604 U32 Reserved4; /* 58h */ 621 U32 Reserved4; /* 58h */
605 U8 ISDataScrubRate; /* 5Ch */ 622 U32 Reserved5; /* 5Ch */
606 U8 ISResyncRate; /* 5Dh */
607 U16 Reserved5; /* 5Eh */
608 U8 IMEDataScrubRate; /* 60h */ 623 U8 IMEDataScrubRate; /* 60h */
609 U8 IMEResyncRate; /* 61h */ 624 U8 IMEResyncRate; /* 61h */
610 U16 Reserved6; /* 62h */ 625 U16 Reserved6; /* 62h */
@@ -616,9 +631,14 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_4
616} CONFIG_PAGE_MANUFACTURING_4, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_4, 631} CONFIG_PAGE_MANUFACTURING_4, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_4,
617 ManufacturingPage4_t, MPI_POINTER pManufacturingPage4_t; 632 ManufacturingPage4_t, MPI_POINTER pManufacturingPage4_t;
618 633
619#define MPI_MANUFACTURING4_PAGEVERSION (0x02) 634#define MPI_MANUFACTURING4_PAGEVERSION (0x03)
620 635
621/* defines for the Flags field */ 636/* defines for the Flags field */
637#define MPI_MANPAGE4_IME_DISABLE (0x20)
638#define MPI_MANPAGE4_IM_DISABLE (0x10)
639#define MPI_MANPAGE4_IS_DISABLE (0x08)
640#define MPI_MANPAGE4_IR_MODEPAGE8_DISABLE (0x04)
641#define MPI_MANPAGE4_IM_RESYNC_CACHE_ENABLE (0x02)
622#define MPI_MANPAGE4_IR_NO_MIX_SAS_SATA (0x01) 642#define MPI_MANPAGE4_IR_NO_MIX_SAS_SATA (0x01)
623 643
624 644
@@ -669,7 +689,7 @@ typedef struct _CONFIG_PAGE_IO_UNIT_1
669} CONFIG_PAGE_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_1, 689} CONFIG_PAGE_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_1,
670 IOUnitPage1_t, MPI_POINTER pIOUnitPage1_t; 690 IOUnitPage1_t, MPI_POINTER pIOUnitPage1_t;
671 691
672#define MPI_IOUNITPAGE1_PAGEVERSION (0x01) 692#define MPI_IOUNITPAGE1_PAGEVERSION (0x02)
673 693
674/* IO Unit Page 1 Flags defines */ 694/* IO Unit Page 1 Flags defines */
675#define MPI_IOUNITPAGE1_MULTI_FUNCTION (0x00000000) 695#define MPI_IOUNITPAGE1_MULTI_FUNCTION (0x00000000)
@@ -681,7 +701,7 @@ typedef struct _CONFIG_PAGE_IO_UNIT_1
681#define MPI_IOUNITPAGE1_DISABLE_IR (0x00000040) 701#define MPI_IOUNITPAGE1_DISABLE_IR (0x00000040)
682#define MPI_IOUNITPAGE1_FORCE_32 (0x00000080) 702#define MPI_IOUNITPAGE1_FORCE_32 (0x00000080)
683#define MPI_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE (0x00000100) 703#define MPI_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE (0x00000100)
684 704#define MPI_IOUNITPAGE1_SATA_WRITE_CACHE_DISABLE (0x00000200)
685 705
686typedef struct _MPI_ADAPTER_INFO 706typedef struct _MPI_ADAPTER_INFO
687{ 707{
@@ -968,7 +988,8 @@ typedef struct _CONFIG_PAGE_BIOS_1
968 U32 Reserved1; /* 0Ch */ 988 U32 Reserved1; /* 0Ch */
969 U32 DeviceSettings; /* 10h */ 989 U32 DeviceSettings; /* 10h */
970 U16 NumberOfDevices; /* 14h */ 990 U16 NumberOfDevices; /* 14h */
971 U16 Reserved2; /* 16h */ 991 U8 ExpanderSpinup; /* 16h */
992 U8 Reserved2; /* 17h */
972 U16 IOTimeoutBlockDevicesNonRM; /* 18h */ 993 U16 IOTimeoutBlockDevicesNonRM; /* 18h */
973 U16 IOTimeoutSequential; /* 1Ah */ 994 U16 IOTimeoutSequential; /* 1Ah */
974 U16 IOTimeoutOther; /* 1Ch */ 995 U16 IOTimeoutOther; /* 1Ch */
@@ -976,7 +997,7 @@ typedef struct _CONFIG_PAGE_BIOS_1
976} CONFIG_PAGE_BIOS_1, MPI_POINTER PTR_CONFIG_PAGE_BIOS_1, 997} CONFIG_PAGE_BIOS_1, MPI_POINTER PTR_CONFIG_PAGE_BIOS_1,
977 BIOSPage1_t, MPI_POINTER pBIOSPage1_t; 998 BIOSPage1_t, MPI_POINTER pBIOSPage1_t;
978 999
979#define MPI_BIOSPAGE1_PAGEVERSION (0x02) 1000#define MPI_BIOSPAGE1_PAGEVERSION (0x03)
980 1001
981/* values for the BiosOptions field */ 1002/* values for the BiosOptions field */
982#define MPI_BIOSPAGE1_OPTIONS_SPI_ENABLE (0x00000400) 1003#define MPI_BIOSPAGE1_OPTIONS_SPI_ENABLE (0x00000400)
@@ -985,8 +1006,15 @@ typedef struct _CONFIG_PAGE_BIOS_1
985#define MPI_BIOSPAGE1_OPTIONS_DISABLE_BIOS (0x00000001) 1006#define MPI_BIOSPAGE1_OPTIONS_DISABLE_BIOS (0x00000001)
986 1007
987/* values for the IOCSettings field */ 1008/* values for the IOCSettings field */
1009#define MPI_BIOSPAGE1_IOCSET_MASK_INITIAL_SPINUP_DELAY (0x0F000000)
1010#define MPI_BIOSPAGE1_IOCSET_SHIFT_INITIAL_SPINUP_DELAY (24)
1011
988#define MPI_BIOSPAGE1_IOCSET_MASK_PORT_ENABLE_DELAY (0x00F00000) 1012#define MPI_BIOSPAGE1_IOCSET_MASK_PORT_ENABLE_DELAY (0x00F00000)
989#define MPI_BIOSPAGE1_IOCSET_SHIFT_PORT_ENABLE_DELAY (20) 1013#define MPI_BIOSPAGE1_IOCSET_SHIFT_PORT_ENABLE_DELAY (20)
1014
1015#define MPI_BIOSPAGE1_IOCSET_AUTO_PORT_ENABLE (0x00080000)
1016#define MPI_BIOSPAGE1_IOCSET_DIRECT_ATTACH_SPINUP_MODE (0x00040000)
1017
990#define MPI_BIOSPAGE1_IOCSET_MASK_BOOT_PREFERENCE (0x00030000) 1018#define MPI_BIOSPAGE1_IOCSET_MASK_BOOT_PREFERENCE (0x00030000)
991#define MPI_BIOSPAGE1_IOCSET_ENCLOSURE_SLOT_BOOT (0x00000000) 1019#define MPI_BIOSPAGE1_IOCSET_ENCLOSURE_SLOT_BOOT (0x00000000)
992#define MPI_BIOSPAGE1_IOCSET_SAS_ADDRESS_BOOT (0x00010000) 1020#define MPI_BIOSPAGE1_IOCSET_SAS_ADDRESS_BOOT (0x00010000)
@@ -1016,6 +1044,11 @@ typedef struct _CONFIG_PAGE_BIOS_1
1016#define MPI_BIOSPAGE1_DEVSET_DISABLE_NON_RM_LUN (0x00000002) 1044#define MPI_BIOSPAGE1_DEVSET_DISABLE_NON_RM_LUN (0x00000002)
1017#define MPI_BIOSPAGE1_DEVSET_DISABLE_OTHER_LUN (0x00000001) 1045#define MPI_BIOSPAGE1_DEVSET_DISABLE_OTHER_LUN (0x00000001)
1018 1046
1047/* defines for the ExpanderSpinup field */
1048#define MPI_BIOSPAGE1_EXPSPINUP_MASK_MAX_TARGET (0xF0)
1049#define MPI_BIOSPAGE1_EXPSPINUP_SHIFT_MAX_TARGET (4)
1050#define MPI_BIOSPAGE1_EXPSPINUP_MASK_DELAY (0x0F)
1051
1019typedef struct _MPI_BOOT_DEVICE_ADAPTER_ORDER 1052typedef struct _MPI_BOOT_DEVICE_ADAPTER_ORDER
1020{ 1053{
1021 U32 Reserved1; /* 00h */ 1054 U32 Reserved1; /* 00h */
@@ -1233,13 +1266,13 @@ typedef struct _CONFIG_PAGE_SCSI_PORT_0
1233 1266
1234#define MPI_SCSIPORTPAGE0_CAP_SHIFT_MIN_SYNC_PERIOD (8) 1267#define MPI_SCSIPORTPAGE0_CAP_SHIFT_MIN_SYNC_PERIOD (8)
1235#define MPI_SCSIPORTPAGE0_CAP_GET_MIN_SYNC_PERIOD(Cap) \ 1268#define MPI_SCSIPORTPAGE0_CAP_GET_MIN_SYNC_PERIOD(Cap) \
1236 ( ((Cap) & MPI_SCSIPORTPAGE0_CAP_MASK_MIN_SYNC_PERIOD) \ 1269 ( ((Cap) & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK) \
1237 >> MPI_SCSIPORTPAGE0_CAP_SHIFT_MIN_SYNC_PERIOD \ 1270 >> MPI_SCSIPORTPAGE0_CAP_SHIFT_MIN_SYNC_PERIOD \
1238 ) 1271 )
1239#define MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK (0x00FF0000) 1272#define MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK (0x00FF0000)
1240#define MPI_SCSIPORTPAGE0_CAP_SHIFT_MAX_SYNC_OFFSET (16) 1273#define MPI_SCSIPORTPAGE0_CAP_SHIFT_MAX_SYNC_OFFSET (16)
1241#define MPI_SCSIPORTPAGE0_CAP_GET_MAX_SYNC_OFFSET(Cap) \ 1274#define MPI_SCSIPORTPAGE0_CAP_GET_MAX_SYNC_OFFSET(Cap) \
1242 ( ((Cap) & MPI_SCSIPORTPAGE0_CAP_MASK_MAX_SYNC_OFFSET) \ 1275 ( ((Cap) & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK) \
1243 >> MPI_SCSIPORTPAGE0_CAP_SHIFT_MAX_SYNC_OFFSET \ 1276 >> MPI_SCSIPORTPAGE0_CAP_SHIFT_MAX_SYNC_OFFSET \
1244 ) 1277 )
1245#define MPI_SCSIPORTPAGE0_CAP_IDP (0x08000000) 1278#define MPI_SCSIPORTPAGE0_CAP_IDP (0x08000000)
@@ -2370,47 +2403,48 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_1
2370} CONFIG_PAGE_SAS_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_1, 2403} CONFIG_PAGE_SAS_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_1,
2371 SasIOUnitPage1_t, MPI_POINTER pSasIOUnitPage1_t; 2404 SasIOUnitPage1_t, MPI_POINTER pSasIOUnitPage1_t;
2372 2405
2373#define MPI_SASIOUNITPAGE1_PAGEVERSION (0x04) 2406#define MPI_SASIOUNITPAGE1_PAGEVERSION (0x05)
2374 2407
2375/* values for SAS IO Unit Page 1 ControlFlags */ 2408/* values for SAS IO Unit Page 1 ControlFlags */
2376#define MPI_SAS_IOUNIT1_CONTROL_DEVICE_SELF_TEST (0x8000) 2409#define MPI_SAS_IOUNIT1_CONTROL_DEVICE_SELF_TEST (0x8000)
2377#define MPI_SAS_IOUNIT1_CONTROL_SATA_3_0_MAX (0x4000) 2410#define MPI_SAS_IOUNIT1_CONTROL_SATA_3_0_MAX (0x4000)
2378#define MPI_SAS_IOUNIT1_CONTROL_SATA_1_5_MAX (0x2000) 2411#define MPI_SAS_IOUNIT1_CONTROL_SATA_1_5_MAX (0x2000)
2379#define MPI_SAS_IOUNIT1_CONTROL_SATA_SW_PRESERVE (0x1000) 2412#define MPI_SAS_IOUNIT1_CONTROL_SATA_SW_PRESERVE (0x1000)
2380#define MPI_SAS_IOUNIT1_CONTROL_DISABLE_SAS_HASH (0x0800) 2413#define MPI_SAS_IOUNIT1_CONTROL_DISABLE_SAS_HASH (0x0800)
2381 2414
2382#define MPI_SAS_IOUNIT1_CONTROL_MASK_DEV_SUPPORT (0x0600) 2415#define MPI_SAS_IOUNIT1_CONTROL_MASK_DEV_SUPPORT (0x0600)
2383#define MPI_SAS_IOUNIT1_CONTROL_SHIFT_DEV_SUPPORT (9) 2416#define MPI_SAS_IOUNIT1_CONTROL_SHIFT_DEV_SUPPORT (9)
2384#define MPI_SAS_IOUNIT1_CONTROL_DEV_SUPPORT_BOTH (0x00) 2417#define MPI_SAS_IOUNIT1_CONTROL_DEV_SUPPORT_BOTH (0x00)
2385#define MPI_SAS_IOUNIT1_CONTROL_DEV_SAS_SUPPORT (0x01) 2418#define MPI_SAS_IOUNIT1_CONTROL_DEV_SAS_SUPPORT (0x01)
2386#define MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT (0x02) 2419#define MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT (0x02)
2387 2420
2388#define MPI_SAS_IOUNIT1_CONTROL_SATA_48BIT_LBA_REQUIRED (0x0080) 2421#define MPI_SAS_IOUNIT1_CONTROL_POSTPONE_SATA_INIT (0x0100)
2389#define MPI_SAS_IOUNIT1_CONTROL_SATA_SMART_REQUIRED (0x0040) 2422#define MPI_SAS_IOUNIT1_CONTROL_SATA_48BIT_LBA_REQUIRED (0x0080)
2390#define MPI_SAS_IOUNIT1_CONTROL_SATA_NCQ_REQUIRED (0x0020) 2423#define MPI_SAS_IOUNIT1_CONTROL_SATA_SMART_REQUIRED (0x0040)
2391#define MPI_SAS_IOUNIT1_CONTROL_SATA_FUA_REQUIRED (0x0010) 2424#define MPI_SAS_IOUNIT1_CONTROL_SATA_NCQ_REQUIRED (0x0020)
2392#define MPI_SAS_IOUNIT1_CONTROL_PHY_ENABLE_ORDER_HIGH (0x0008) 2425#define MPI_SAS_IOUNIT1_CONTROL_SATA_FUA_REQUIRED (0x0010)
2393#define MPI_SAS_IOUNIT1_CONTROL_SUBTRACTIVE_ILLEGAL (0x0004) 2426#define MPI_SAS_IOUNIT1_CONTROL_PHY_ENABLE_ORDER_HIGH (0x0008)
2394#define MPI_SAS_IOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY (0x0002) 2427#define MPI_SAS_IOUNIT1_CONTROL_SUBTRACTIVE_ILLEGAL (0x0004)
2395#define MPI_SAS_IOUNIT1_CONTROL_CLEAR_AFFILIATION (0x0001) 2428#define MPI_SAS_IOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY (0x0002)
2429#define MPI_SAS_IOUNIT1_CONTROL_CLEAR_AFFILIATION (0x0001)
2396 2430
2397/* values for SAS IO Unit Page 1 PortFlags */ 2431/* values for SAS IO Unit Page 1 PortFlags */
2398#define MPI_SAS_IOUNIT1_PORT_FLAGS_0_TARGET_IOC_NUM (0x00) 2432#define MPI_SAS_IOUNIT1_PORT_FLAGS_0_TARGET_IOC_NUM (0x00)
2399#define MPI_SAS_IOUNIT1_PORT_FLAGS_1_TARGET_IOC_NUM (0x04) 2433#define MPI_SAS_IOUNIT1_PORT_FLAGS_1_TARGET_IOC_NUM (0x04)
2400#define MPI_SAS_IOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG (0x01) 2434#define MPI_SAS_IOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG (0x01)
2401 2435
2402/* values for SAS IO Unit Page 0 PhyFlags */ 2436/* values for SAS IO Unit Page 0 PhyFlags */
2403#define MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE (0x04) 2437#define MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE (0x04)
2404#define MPI_SAS_IOUNIT1_PHY_FLAGS_TX_INVERT (0x02) 2438#define MPI_SAS_IOUNIT1_PHY_FLAGS_TX_INVERT (0x02)
2405#define MPI_SAS_IOUNIT1_PHY_FLAGS_RX_INVERT (0x01) 2439#define MPI_SAS_IOUNIT1_PHY_FLAGS_RX_INVERT (0x01)
2406 2440
2407/* values for SAS IO Unit Page 0 MaxMinLinkRate */ 2441/* values for SAS IO Unit Page 0 MaxMinLinkRate */
2408#define MPI_SAS_IOUNIT1_MAX_RATE_MASK (0xF0) 2442#define MPI_SAS_IOUNIT1_MAX_RATE_MASK (0xF0)
2409#define MPI_SAS_IOUNIT1_MAX_RATE_1_5 (0x80) 2443#define MPI_SAS_IOUNIT1_MAX_RATE_1_5 (0x80)
2410#define MPI_SAS_IOUNIT1_MAX_RATE_3_0 (0x90) 2444#define MPI_SAS_IOUNIT1_MAX_RATE_3_0 (0x90)
2411#define MPI_SAS_IOUNIT1_MIN_RATE_MASK (0x0F) 2445#define MPI_SAS_IOUNIT1_MIN_RATE_MASK (0x0F)
2412#define MPI_SAS_IOUNIT1_MIN_RATE_1_5 (0x08) 2446#define MPI_SAS_IOUNIT1_MIN_RATE_1_5 (0x08)
2413#define MPI_SAS_IOUNIT1_MIN_RATE_3_0 (0x09) 2447#define MPI_SAS_IOUNIT1_MIN_RATE_3_0 (0x09)
2414 2448
2415/* see mpi_sas.h for values for SAS IO Unit Page 1 ControllerPhyDeviceInfo values */ 2449/* see mpi_sas.h for values for SAS IO Unit Page 1 ControllerPhyDeviceInfo values */
2416 2450
@@ -2418,16 +2452,18 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_1
2418typedef struct _CONFIG_PAGE_SAS_IO_UNIT_2 2452typedef struct _CONFIG_PAGE_SAS_IO_UNIT_2
2419{ 2453{
2420 CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ 2454 CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
2421 U32 Reserved1; /* 08h */ 2455 U8 NumDevsPerEnclosure; /* 08h */
2456 U8 Reserved1; /* 09h */
2457 U16 Reserved2; /* 0Ah */
2422 U16 MaxPersistentIDs; /* 0Ch */ 2458 U16 MaxPersistentIDs; /* 0Ch */
2423 U16 NumPersistentIDsUsed; /* 0Eh */ 2459 U16 NumPersistentIDsUsed; /* 0Eh */
2424 U8 Status; /* 10h */ 2460 U8 Status; /* 10h */
2425 U8 Flags; /* 11h */ 2461 U8 Flags; /* 11h */
2426 U16 MaxNumPhysicalMappedIDs;/* 12h */ /* 12h */ 2462 U16 MaxNumPhysicalMappedIDs;/* 12h */
2427} CONFIG_PAGE_SAS_IO_UNIT_2, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_2, 2463} CONFIG_PAGE_SAS_IO_UNIT_2, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_2,
2428 SasIOUnitPage2_t, MPI_POINTER pSasIOUnitPage2_t; 2464 SasIOUnitPage2_t, MPI_POINTER pSasIOUnitPage2_t;
2429 2465
2430#define MPI_SASIOUNITPAGE2_PAGEVERSION (0x04) 2466#define MPI_SASIOUNITPAGE2_PAGEVERSION (0x05)
2431 2467
2432/* values for SAS IO Unit Page 2 Status field */ 2468/* values for SAS IO Unit Page 2 Status field */
2433#define MPI_SAS_IOUNIT2_STATUS_DISABLED_PERSISTENT_MAPPINGS (0x02) 2469#define MPI_SAS_IOUNIT2_STATUS_DISABLED_PERSISTENT_MAPPINGS (0x02)
@@ -2441,6 +2477,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_2
2441#define MPI_SAS_IOUNIT2_FLAGS_NO_PHYS_MAP (0x00) 2477#define MPI_SAS_IOUNIT2_FLAGS_NO_PHYS_MAP (0x00)
2442#define MPI_SAS_IOUNIT2_FLAGS_DIRECT_ATTACH_PHYS_MAP (0x01) 2478#define MPI_SAS_IOUNIT2_FLAGS_DIRECT_ATTACH_PHYS_MAP (0x01)
2443#define MPI_SAS_IOUNIT2_FLAGS_ENCLOSURE_SLOT_PHYS_MAP (0x02) 2479#define MPI_SAS_IOUNIT2_FLAGS_ENCLOSURE_SLOT_PHYS_MAP (0x02)
2480#define MPI_SAS_IOUNIT2_FLAGS_HOST_ASSIGNED_PHYS_MAP (0x07)
2444 2481
2445#define MPI_SAS_IOUNIT2_FLAGS_RESERVE_ID_0_FOR_BOOT (0x10) 2482#define MPI_SAS_IOUNIT2_FLAGS_RESERVE_ID_0_FOR_BOOT (0x10)
2446#define MPI_SAS_IOUNIT2_FLAGS_DA_STARTING_SLOT (0x20) 2483#define MPI_SAS_IOUNIT2_FLAGS_DA_STARTING_SLOT (0x20)
@@ -2473,7 +2510,7 @@ typedef struct _CONFIG_PAGE_SAS_EXPANDER_0
2473 CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ 2510 CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
2474 U8 PhysicalPort; /* 08h */ 2511 U8 PhysicalPort; /* 08h */
2475 U8 Reserved1; /* 09h */ 2512 U8 Reserved1; /* 09h */
2476 U16 Reserved2; /* 0Ah */ 2513 U16 EnclosureHandle; /* 0Ah */
2477 U64 SASAddress; /* 0Ch */ 2514 U64 SASAddress; /* 0Ch */
2478 U32 DiscoveryStatus; /* 14h */ 2515 U32 DiscoveryStatus; /* 14h */
2479 U16 DevHandle; /* 18h */ 2516 U16 DevHandle; /* 18h */
@@ -2487,7 +2524,7 @@ typedef struct _CONFIG_PAGE_SAS_EXPANDER_0
2487} CONFIG_PAGE_SAS_EXPANDER_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_EXPANDER_0, 2524} CONFIG_PAGE_SAS_EXPANDER_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_EXPANDER_0,
2488 SasExpanderPage0_t, MPI_POINTER pSasExpanderPage0_t; 2525 SasExpanderPage0_t, MPI_POINTER pSasExpanderPage0_t;
2489 2526
2490#define MPI_SASEXPANDER0_PAGEVERSION (0x02) 2527#define MPI_SASEXPANDER0_PAGEVERSION (0x03)
2491 2528
2492/* values for SAS Expander Page 0 DiscoveryStatus field */ 2529/* values for SAS Expander Page 0 DiscoveryStatus field */
2493#define MPI_SAS_EXPANDER0_DS_LOOP_DETECTED (0x00000001) 2530#define MPI_SAS_EXPANDER0_DS_LOOP_DETECTED (0x00000001)
@@ -2527,9 +2564,9 @@ typedef struct _CONFIG_PAGE_SAS_EXPANDER_1
2527 U8 NegotiatedLinkRate; /* 1Fh */ 2564 U8 NegotiatedLinkRate; /* 1Fh */
2528 U8 PhyIdentifier; /* 20h */ 2565 U8 PhyIdentifier; /* 20h */
2529 U8 AttachedPhyIdentifier; /* 21h */ 2566 U8 AttachedPhyIdentifier; /* 21h */
2530 U8 NumTableEntriesProg; /* 22h */ 2567 U8 Reserved3; /* 22h */
2531 U8 DiscoveryInfo; /* 23h */ 2568 U8 DiscoveryInfo; /* 23h */
2532 U32 Reserved3; /* 24h */ 2569 U32 Reserved4; /* 24h */
2533} CONFIG_PAGE_SAS_EXPANDER_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_EXPANDER_1, 2570} CONFIG_PAGE_SAS_EXPANDER_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_EXPANDER_1,
2534 SasExpanderPage1_t, MPI_POINTER pSasExpanderPage1_t; 2571 SasExpanderPage1_t, MPI_POINTER pSasExpanderPage1_t;
2535 2572
@@ -2766,16 +2803,15 @@ typedef struct _CONFIG_PAGE_SAS_ENCLOSURE_0
2766#define MPI_LOG_0_NUM_LOG_ENTRIES (1) 2803#define MPI_LOG_0_NUM_LOG_ENTRIES (1)
2767#endif 2804#endif
2768 2805
2769#define MPI_LOG_0_LOG_DATA_LENGTH (20) 2806#define MPI_LOG_0_LOG_DATA_LENGTH (0x1C)
2770 2807
2771typedef struct _MPI_LOG_0_ENTRY 2808typedef struct _MPI_LOG_0_ENTRY
2772{ 2809{
2773 U64 WWID; /* 00h */ 2810 U32 TimeStamp; /* 00h */
2774 U32 TimeStamp; /* 08h */ 2811 U32 Reserved1; /* 04h */
2775 U32 Reserved1; /* 0Ch */ 2812 U16 LogSequence; /* 08h */
2776 U16 LogSequence; /* 10h */ 2813 U16 LogEntryQualifier; /* 0Ah */
2777 U16 LogEntryQualifier; /* 12h */ 2814 U8 LogData[MPI_LOG_0_LOG_DATA_LENGTH]; /* 0Ch */
2778 U8 LogData[MPI_LOG_0_LOG_DATA_LENGTH]; /* 14h */
2779} MPI_LOG_0_ENTRY, MPI_POINTER PTR_MPI_LOG_0_ENTRY, 2815} MPI_LOG_0_ENTRY, MPI_POINTER PTR_MPI_LOG_0_ENTRY,
2780 MpiLog0Entry_t, MPI_POINTER pMpiLog0Entry_t; 2816 MpiLog0Entry_t, MPI_POINTER pMpiLog0Entry_t;
2781 2817
@@ -2794,7 +2830,7 @@ typedef struct _CONFIG_PAGE_LOG_0
2794} CONFIG_PAGE_LOG_0, MPI_POINTER PTR_CONFIG_PAGE_LOG_0, 2830} CONFIG_PAGE_LOG_0, MPI_POINTER PTR_CONFIG_PAGE_LOG_0,
2795 LogPage0_t, MPI_POINTER pLogPage0_t; 2831 LogPage0_t, MPI_POINTER pLogPage0_t;
2796 2832
2797#define MPI_LOG_0_PAGEVERSION (0x00) 2833#define MPI_LOG_0_PAGEVERSION (0x01)
2798 2834
2799 2835
2800#endif 2836#endif
diff --git a/drivers/message/fusion/lsi/mpi_history.txt b/drivers/message/fusion/lsi/mpi_history.txt
index 1a30ef16adb4..4a5f8dd1d766 100644
--- a/drivers/message/fusion/lsi/mpi_history.txt
+++ b/drivers/message/fusion/lsi/mpi_history.txt
@@ -6,25 +6,25 @@
6 Copyright (c) 2000-2005 LSI Logic Corporation. 6 Copyright (c) 2000-2005 LSI Logic Corporation.
7 7
8 --------------------------------------- 8 ---------------------------------------
9 Header Set Release Version: 01.05.10 9 Header Set Release Version: 01.05.12
10 Header Set Release Date: 03-11-05 10 Header Set Release Date: 08-30-05
11 --------------------------------------- 11 ---------------------------------------
12 12
13 Filename Current version Prior version 13 Filename Current version Prior version
14 ---------- --------------- ------------- 14 ---------- --------------- -------------
15 mpi.h 01.05.08 01.05.07 15 mpi.h 01.05.10 01.05.09
16 mpi_ioc.h 01.05.09 01.05.08 16 mpi_ioc.h 01.05.10 01.05.09
17 mpi_cnfg.h 01.05.09 01.05.08 17 mpi_cnfg.h 01.05.11 01.05.10
18 mpi_init.h 01.05.05 01.05.04 18 mpi_init.h 01.05.06 01.05.06
19 mpi_targ.h 01.05.05 01.05.04 19 mpi_targ.h 01.05.05 01.05.05
20 mpi_fc.h 01.05.01 01.05.01 20 mpi_fc.h 01.05.01 01.05.01
21 mpi_lan.h 01.05.01 01.05.01 21 mpi_lan.h 01.05.01 01.05.01
22 mpi_raid.h 01.05.02 01.05.02 22 mpi_raid.h 01.05.02 01.05.02
23 mpi_tool.h 01.05.03 01.05.03 23 mpi_tool.h 01.05.03 01.05.03
24 mpi_inb.h 01.05.01 01.05.01 24 mpi_inb.h 01.05.01 01.05.01
25 mpi_sas.h 01.05.01 01.05.01 25 mpi_sas.h 01.05.02 01.05.01
26 mpi_type.h 01.05.01 01.05.01 26 mpi_type.h 01.05.02 01.05.01
27 mpi_history.txt 01.05.09 01.05.09 27 mpi_history.txt 01.05.12 01.05.11
28 28
29 29
30 * Date Version Description 30 * Date Version Description
@@ -91,6 +91,8 @@ mpi.h
91 * 06-24-05 01.05.08 Added function codes for SCSI IO 32 and 91 * 06-24-05 01.05.08 Added function codes for SCSI IO 32 and
92 * TargetAssistExtended requests. 92 * TargetAssistExtended requests.
93 * Added EEDP IOCStatus codes. 93 * Added EEDP IOCStatus codes.
94 * 08-03-05 01.05.09 Bumped MPI_HEADER_VERSION_UNIT.
95 * 08-30-05 01.05.10 Added 2 new IOCStatus codes for Target.
94 * -------------------------------------------------------------------------- 96 * --------------------------------------------------------------------------
95 97
96mpi_ioc.h 98mpi_ioc.h
@@ -164,6 +166,10 @@ mpi_ioc.h
164 * Removed IOCFacts Reply EEDP Capability bit. 166 * Removed IOCFacts Reply EEDP Capability bit.
165 * 06-24-05 01.05.09 Added 5 new IOCFacts Reply IOCCapabilities bits. 167 * 06-24-05 01.05.09 Added 5 new IOCFacts Reply IOCCapabilities bits.
166 * Added Max SATA Targets to SAS Discovery Error event. 168 * Added Max SATA Targets to SAS Discovery Error event.
169 * 08-30-05 01.05.10 Added 4 new events and their event data structures.
170 * Added new ReasonCode value for SAS Device Status Change
171 * event.
172 * Added new family code for FC949E.
167 * -------------------------------------------------------------------------- 173 * --------------------------------------------------------------------------
168 174
169mpi_cnfg.h 175mpi_cnfg.h
@@ -402,6 +408,23 @@ mpi_cnfg.h
402 * Added OwnerDevHandle and Flags field to SAS PHY Page 0. 408 * Added OwnerDevHandle and Flags field to SAS PHY Page 0.
403 * Added IOC GPIO Flags define to SAS Enclosure Page 0. 409 * Added IOC GPIO Flags define to SAS Enclosure Page 0.
404 * Fixed the value for MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT. 410 * Fixed the value for MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT.
411 * 08-03-05 01.05.10 Removed ISDataScrubRate and ISResyncRate from
412 * Manufacturing Page 4.
413 * Added MPI_IOUNITPAGE1_SATA_WRITE_CACHE_DISABLE bit.
414 * Added NumDevsPerEnclosure field to SAS IO Unit page 2.
415 * Added MPI_SAS_IOUNIT2_FLAGS_HOST_ASSIGNED_PHYS_MAP
416 * define.
417 * Added EnclosureHandle field to SAS Expander page 0.
418 * Removed redundant NumTableEntriesProg field from SAS
419 * Expander Page 1.
420 * 08-30-05 01.05.11 Added DeviceID for FC949E and changed the DeviceID for
421 * SAS1078.
422 * Added more defines for Manufacturing Page 4 Flags field.
423 * Added more defines for IOCSettings and added
424 * ExpanderSpinup field to Bios Page 1.
425 * Added postpone SATA Init bit to SAS IO Unit Page 1
426 * ControlFlags.
427 * Changed LogEntry format for Log Page 0.
405 * -------------------------------------------------------------------------- 428 * --------------------------------------------------------------------------
406 429
407mpi_init.h 430mpi_init.h
@@ -442,6 +465,8 @@ mpi_init.h
442 * addressing. 465 * addressing.
443 * 06-24-05 01.05.05 Added SCSI IO 32 structures and defines. 466 * 06-24-05 01.05.05 Added SCSI IO 32 structures and defines.
444 * Added four new defines for SEP SlotStatus. 467 * Added four new defines for SEP SlotStatus.
468 * 08-03-05 01.05.06 Fixed some MPI_SCSIIO32_MSGFLGS_ defines to make them
469 * unique in the first 32 characters.
445 * -------------------------------------------------------------------------- 470 * --------------------------------------------------------------------------
446 471
447mpi_targ.h 472mpi_targ.h
@@ -582,6 +607,9 @@ mpi_inb.h
582 607
583mpi_sas.h 608mpi_sas.h
584 * 08-19-04 01.05.01 Original release. 609 * 08-19-04 01.05.01 Original release.
610 * 08-30-05 01.05.02 Added DeviceInfo bit for SEP.
611 * Added PrimFlags and Primitive field to SAS IO Unit
612 * Control request, and added a new operation code.
585 * -------------------------------------------------------------------------- 613 * --------------------------------------------------------------------------
586 614
587mpi_type.h 615mpi_type.h
@@ -592,24 +620,25 @@ mpi_type.h
592 * 08-08-01 01.02.01 Original release for v1.2 work. 620 * 08-08-01 01.02.01 Original release for v1.2 work.
593 * 05-11-04 01.03.01 Original release for MPI v1.3. 621 * 05-11-04 01.03.01 Original release for MPI v1.3.
594 * 08-19-04 01.05.01 Original release for MPI v1.5. 622 * 08-19-04 01.05.01 Original release for MPI v1.5.
623 * 08-30-05 01.05.02 Added PowerPC option to #ifdef's.
595 * -------------------------------------------------------------------------- 624 * --------------------------------------------------------------------------
596 625
597mpi_history.txt Parts list history 626mpi_history.txt Parts list history
598 627
599Filename 01.05.10 01.05.09 628Filename 01.05.12 01.05.11 01.05.10 01.05.09
600---------- -------- -------- 629---------- -------- -------- -------- --------
601mpi.h 01.05.08 01.05.07 630mpi.h 01.05.10 01.05.09 01.05.08 01.05.07
602mpi_ioc.h 01.05.09 01.05.08 631mpi_ioc.h 01.05.10 01.05.09 01.05.09 01.05.08
603mpi_cnfg.h 01.05.09 01.05.08 632mpi_cnfg.h 01.05.11 01.05.10 01.05.09 01.05.08
604mpi_init.h 01.05.05 01.05.04 633mpi_init.h 01.05.06 01.05.06 01.05.05 01.05.04
605mpi_targ.h 01.05.05 01.05.04 634mpi_targ.h 01.05.05 01.05.05 01.05.05 01.05.04
606mpi_fc.h 01.05.01 01.05.01 635mpi_fc.h 01.05.01 01.05.01 01.05.01 01.05.01
607mpi_lan.h 01.05.01 01.05.01 636mpi_lan.h 01.05.01 01.05.01 01.05.01 01.05.01
608mpi_raid.h 01.05.02 01.05.02 637mpi_raid.h 01.05.02 01.05.02 01.05.02 01.05.02
609mpi_tool.h 01.05.03 01.05.03 638mpi_tool.h 01.05.03 01.05.03 01.05.03 01.05.03
610mpi_inb.h 01.05.01 01.05.01 639mpi_inb.h 01.05.01 01.05.01 01.05.01 01.05.01
611mpi_sas.h 01.05.01 01.05.01 640mpi_sas.h 01.05.02 01.05.01 01.05.01 01.05.01
612mpi_type.h 01.05.01 01.05.01 641mpi_type.h 01.05.02 01.05.01 01.05.01 01.05.01
613 642
614Filename 01.05.08 01.05.07 01.05.06 01.05.05 01.05.04 01.05.03 643Filename 01.05.08 01.05.07 01.05.06 01.05.05 01.05.04 01.05.03
615---------- -------- -------- -------- -------- -------- -------- 644---------- -------- -------- -------- -------- -------- --------
diff --git a/drivers/message/fusion/lsi/mpi_init.h b/drivers/message/fusion/lsi/mpi_init.h
index d5af75afbd94..68941f459ca3 100644
--- a/drivers/message/fusion/lsi/mpi_init.h
+++ b/drivers/message/fusion/lsi/mpi_init.h
@@ -6,7 +6,7 @@
6 * Title: MPI initiator mode messages and structures 6 * Title: MPI initiator mode messages and structures
7 * Creation Date: June 8, 2000 7 * Creation Date: June 8, 2000
8 * 8 *
9 * mpi_init.h Version: 01.05.05 9 * mpi_init.h Version: 01.05.06
10 * 10 *
11 * Version History 11 * Version History
12 * --------------- 12 * ---------------
@@ -50,6 +50,8 @@
50 * addressing. 50 * addressing.
51 * 06-24-05 01.05.05 Added SCSI IO 32 structures and defines. 51 * 06-24-05 01.05.05 Added SCSI IO 32 structures and defines.
52 * Added four new defines for SEP SlotStatus. 52 * Added four new defines for SEP SlotStatus.
53 * 08-03-05 01.05.06 Fixed some MPI_SCSIIO32_MSGFLGS_ defines to make them
54 * unique in the first 32 characters.
53 * -------------------------------------------------------------------------- 55 * --------------------------------------------------------------------------
54 */ 56 */
55 57
@@ -290,8 +292,8 @@ typedef struct _MSG_SCSI_IO32_REQUEST
290 292
291/* SCSI IO 32 MsgFlags bits */ 293/* SCSI IO 32 MsgFlags bits */
292#define MPI_SCSIIO32_MSGFLGS_SENSE_WIDTH (0x01) 294#define MPI_SCSIIO32_MSGFLGS_SENSE_WIDTH (0x01)
293#define MPI_SCSIIO32_MSGFLGS_SENSE_WIDTH_32 (0x00) 295#define MPI_SCSIIO32_MSGFLGS_32_SENSE_WIDTH (0x00)
294#define MPI_SCSIIO32_MSGFLGS_SENSE_WIDTH_64 (0x01) 296#define MPI_SCSIIO32_MSGFLGS_64_SENSE_WIDTH (0x01)
295 297
296#define MPI_SCSIIO32_MSGFLGS_SENSE_LOCATION (0x02) 298#define MPI_SCSIIO32_MSGFLGS_SENSE_LOCATION (0x02)
297#define MPI_SCSIIO32_MSGFLGS_SENSE_LOC_HOST (0x00) 299#define MPI_SCSIIO32_MSGFLGS_SENSE_LOC_HOST (0x00)
diff --git a/drivers/message/fusion/lsi/mpi_ioc.h b/drivers/message/fusion/lsi/mpi_ioc.h
index 93b70e2b4266..2c5f43fa7c73 100644
--- a/drivers/message/fusion/lsi/mpi_ioc.h
+++ b/drivers/message/fusion/lsi/mpi_ioc.h
@@ -6,7 +6,7 @@
6 * Title: MPI IOC, Port, Event, FW Download, and FW Upload messages 6 * Title: MPI IOC, Port, Event, FW Download, and FW Upload messages
7 * Creation Date: August 11, 2000 7 * Creation Date: August 11, 2000
8 * 8 *
9 * mpi_ioc.h Version: 01.05.09 9 * mpi_ioc.h Version: 01.05.10
10 * 10 *
11 * Version History 11 * Version History
12 * --------------- 12 * ---------------
@@ -83,6 +83,10 @@
83 * Removed IOCFacts Reply EEDP Capability bit. 83 * Removed IOCFacts Reply EEDP Capability bit.
84 * 06-24-05 01.05.09 Added 5 new IOCFacts Reply IOCCapabilities bits. 84 * 06-24-05 01.05.09 Added 5 new IOCFacts Reply IOCCapabilities bits.
85 * Added Max SATA Targets to SAS Discovery Error event. 85 * Added Max SATA Targets to SAS Discovery Error event.
86 * 08-30-05 01.05.10 Added 4 new events and their event data structures.
87 * Added new ReasonCode value for SAS Device Status Change
88 * event.
89 * Added new family code for FC949E.
86 * -------------------------------------------------------------------------- 90 * --------------------------------------------------------------------------
87 */ 91 */
88 92
@@ -464,6 +468,10 @@ typedef struct _MSG_EVENT_ACK_REPLY
464#define MPI_EVENT_PERSISTENT_TABLE_FULL (0x00000011) 468#define MPI_EVENT_PERSISTENT_TABLE_FULL (0x00000011)
465#define MPI_EVENT_SAS_PHY_LINK_STATUS (0x00000012) 469#define MPI_EVENT_SAS_PHY_LINK_STATUS (0x00000012)
466#define MPI_EVENT_SAS_DISCOVERY_ERROR (0x00000013) 470#define MPI_EVENT_SAS_DISCOVERY_ERROR (0x00000013)
471#define MPI_EVENT_IR_RESYNC_UPDATE (0x00000014)
472#define MPI_EVENT_IR2 (0x00000015)
473#define MPI_EVENT_SAS_DISCOVERY (0x00000016)
474#define MPI_EVENT_LOG_ENTRY_ADDED (0x00000021)
467 475
468/* AckRequired field values */ 476/* AckRequired field values */
469 477
@@ -480,6 +488,29 @@ typedef struct _EVENT_DATA_EVENT_CHANGE
480} EVENT_DATA_EVENT_CHANGE, MPI_POINTER PTR_EVENT_DATA_EVENT_CHANGE, 488} EVENT_DATA_EVENT_CHANGE, MPI_POINTER PTR_EVENT_DATA_EVENT_CHANGE,
481 EventDataEventChange_t, MPI_POINTER pEventDataEventChange_t; 489 EventDataEventChange_t, MPI_POINTER pEventDataEventChange_t;
482 490
491/* LogEntryAdded Event data */
492
493/* this structure matches MPI_LOG_0_ENTRY in mpi_cnfg.h */
494#define MPI_EVENT_DATA_LOG_ENTRY_DATA_LENGTH (0x1C)
495typedef struct _EVENT_DATA_LOG_ENTRY
496{
497 U32 TimeStamp; /* 00h */
498 U32 Reserved1; /* 04h */
499 U16 LogSequence; /* 08h */
500 U16 LogEntryQualifier; /* 0Ah */
501 U8 LogData[MPI_EVENT_DATA_LOG_ENTRY_DATA_LENGTH]; /* 0Ch */
502} EVENT_DATA_LOG_ENTRY, MPI_POINTER PTR_EVENT_DATA_LOG_ENTRY,
503 MpiEventDataLogEntry_t, MPI_POINTER pMpiEventDataLogEntry_t;
504
505typedef struct _EVENT_DATA_LOG_ENTRY_ADDED
506{
507 U16 LogSequence; /* 00h */
508 U16 Reserved1; /* 02h */
509 U32 Reserved2; /* 04h */
510 EVENT_DATA_LOG_ENTRY LogEntry; /* 08h */
511} EVENT_DATA_LOG_ENTRY_ADDED, MPI_POINTER PTR_EVENT_DATA_LOG_ENTRY_ADDED,
512 MpiEventDataLogEntryAdded_t, MPI_POINTER pMpiEventDataLogEntryAdded_t;
513
483/* SCSI Event data for Port, Bus and Device forms */ 514/* SCSI Event data for Port, Bus and Device forms */
484 515
485typedef struct _EVENT_DATA_SCSI 516typedef struct _EVENT_DATA_SCSI
@@ -538,6 +569,7 @@ typedef struct _EVENT_DATA_SAS_DEVICE_STATUS_CHANGE
538#define MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA (0x05) 569#define MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA (0x05)
539#define MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED (0x06) 570#define MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED (0x06)
540#define MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED (0x07) 571#define MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED (0x07)
572#define MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET (0x08)
541 573
542 574
543/* SCSI Event data for Queue Full event */ 575/* SCSI Event data for Queue Full event */
@@ -579,6 +611,79 @@ typedef struct _EVENT_DATA_RAID
579#define MPI_EVENT_RAID_RC_SMART_DATA (0x0A) 611#define MPI_EVENT_RAID_RC_SMART_DATA (0x0A)
580#define MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED (0x0B) 612#define MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED (0x0B)
581 613
614
615/* MPI Integrated RAID Resync Update Event data */
616
617typedef struct _MPI_EVENT_DATA_IR_RESYNC_UPDATE
618{
619 U8 VolumeID; /* 00h */
620 U8 VolumeBus; /* 01h */
621 U8 ResyncComplete; /* 02h */
622 U8 Reserved1; /* 03h */
623 U32 Reserved2; /* 04h */
624} MPI_EVENT_DATA_IR_RESYNC_UPDATE,
625 MPI_POINTER PTR_MPI_EVENT_DATA_IR_RESYNC_UPDATE,
626 MpiEventDataIrResyncUpdate_t, MPI_POINTER pMpiEventDataIrResyncUpdate_t;
627
628/* MPI IR2 Event data */
629
630/* MPI_LD_STATE or MPI_PD_STATE */
631typedef struct _IR2_STATE_CHANGED
632{
633 U16 PreviousState; /* 00h */
634 U16 NewState; /* 02h */
635} IR2_STATE_CHANGED, MPI_POINTER PTR_IR2_STATE_CHANGED;
636
637typedef struct _IR2_PD_INFO
638{
639 U16 DeviceHandle; /* 00h */
640 U8 TruncEnclosureHandle; /* 02h */
641 U8 TruncatedSlot; /* 03h */
642} IR2_PD_INFO, MPI_POINTER PTR_IR2_PD_INFO;
643
644typedef union _MPI_IR2_RC_EVENT_DATA
645{
646 IR2_STATE_CHANGED StateChanged;
647 U32 Lba;
648 IR2_PD_INFO PdInfo;
649} MPI_IR2_RC_EVENT_DATA, MPI_POINTER PTR_MPI_IR2_RC_EVENT_DATA;
650
651typedef struct _MPI_EVENT_DATA_IR2
652{
653 U8 TargetID; /* 00h */
654 U8 Bus; /* 01h */
655 U8 ReasonCode; /* 02h */
656 U8 PhysDiskNum; /* 03h */
657 MPI_IR2_RC_EVENT_DATA IR2EventData; /* 04h */
658} MPI_EVENT_DATA_IR2, MPI_POINTER PTR_MPI_EVENT_DATA_IR2,
659 MpiEventDataIR2_t, MPI_POINTER pMpiEventDataIR2_t;
660
661/* MPI IR2 Event data ReasonCode values */
662#define MPI_EVENT_IR2_RC_LD_STATE_CHANGED (0x01)
663#define MPI_EVENT_IR2_RC_PD_STATE_CHANGED (0x02)
664#define MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL (0x03)
665#define MPI_EVENT_IR2_RC_PD_INSERTED (0x04)
666#define MPI_EVENT_IR2_RC_PD_REMOVED (0x05)
667#define MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED (0x06)
668#define MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR (0x07)
669
670/* defines for logical disk states */
671#define MPI_LD_STATE_OPTIMAL (0x00)
672#define MPI_LD_STATE_DEGRADED (0x01)
673#define MPI_LD_STATE_FAILED (0x02)
674#define MPI_LD_STATE_MISSING (0x03)
675#define MPI_LD_STATE_OFFLINE (0x04)
676
677/* defines for physical disk states */
678#define MPI_PD_STATE_ONLINE (0x00)
679#define MPI_PD_STATE_MISSING (0x01)
680#define MPI_PD_STATE_NOT_COMPATIBLE (0x02)
681#define MPI_PD_STATE_FAILED (0x03)
682#define MPI_PD_STATE_INITIALIZING (0x04)
683#define MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST (0x05)
684#define MPI_PD_STATE_FAILED_AT_HOST_REQUEST (0x06)
685#define MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON (0xFF)
686
582/* MPI Link Status Change Event data */ 687/* MPI Link Status Change Event data */
583 688
584typedef struct _EVENT_DATA_LINK_STATUS 689typedef struct _EVENT_DATA_LINK_STATUS
@@ -660,6 +765,20 @@ typedef struct _EVENT_DATA_SAS_PHY_LINK_STATUS
660#define MPI_EVENT_SAS_PLS_LR_RATE_1_5 (0x08) 765#define MPI_EVENT_SAS_PLS_LR_RATE_1_5 (0x08)
661#define MPI_EVENT_SAS_PLS_LR_RATE_3_0 (0x09) 766#define MPI_EVENT_SAS_PLS_LR_RATE_3_0 (0x09)
662 767
768/* SAS Discovery Event data */
769
770typedef struct _EVENT_DATA_SAS_DISCOVERY
771{
772 U32 DiscoveryStatus; /* 00h */
773 U32 Reserved1; /* 04h */
774} EVENT_DATA_SAS_DISCOVERY, MPI_POINTER PTR_EVENT_DATA_SAS_DISCOVERY,
775 EventDataSasDiscovery_t, MPI_POINTER pEventDataSasDiscovery_t;
776
777#define MPI_EVENT_SAS_DSCVRY_COMPLETE (0x00000000)
778#define MPI_EVENT_SAS_DSCVRY_IN_PROGRESS (0x00000001)
779#define MPI_EVENT_SAS_DSCVRY_PHY_BITS_MASK (0xFFFF0000)
780#define MPI_EVENT_SAS_DSCVRY_PHY_BITS_SHIFT (16)
781
663/* SAS Discovery Errror Event data */ 782/* SAS Discovery Errror Event data */
664 783
665typedef struct _EVENT_DATA_DISCOVERY_ERROR 784typedef struct _EVENT_DATA_DISCOVERY_ERROR
@@ -869,6 +988,7 @@ typedef struct _MPI_FW_HEADER
869#define MPI_FW_HEADER_PID_FAMILY_919XL_FC (0x0003) /* 919XL and 929XL */ 988#define MPI_FW_HEADER_PID_FAMILY_919XL_FC (0x0003) /* 919XL and 929XL */
870#define MPI_FW_HEADER_PID_FAMILY_939X_FC (0x0004) /* 939X and 949X */ 989#define MPI_FW_HEADER_PID_FAMILY_939X_FC (0x0004) /* 939X and 949X */
871#define MPI_FW_HEADER_PID_FAMILY_959_FC (0x0005) 990#define MPI_FW_HEADER_PID_FAMILY_959_FC (0x0005)
991#define MPI_FW_HEADER_PID_FAMILY_949E_FC (0x0006)
872/* SAS */ 992/* SAS */
873#define MPI_FW_HEADER_PID_FAMILY_1064_SAS (0x0001) 993#define MPI_FW_HEADER_PID_FAMILY_1064_SAS (0x0001)
874#define MPI_FW_HEADER_PID_FAMILY_1068_SAS (0x0002) 994#define MPI_FW_HEADER_PID_FAMILY_1068_SAS (0x0002)
diff --git a/drivers/message/fusion/lsi/mpi_log_fc.h b/drivers/message/fusion/lsi/mpi_log_fc.h
new file mode 100644
index 000000000000..dc98d46f9071
--- /dev/null
+++ b/drivers/message/fusion/lsi/mpi_log_fc.h
@@ -0,0 +1,89 @@
1/*
2 * Copyright (c) 2000-2001 LSI Logic Corporation. All rights reserved.
3 *
4 * NAME: fc_log.h
5 * SUMMARY: MPI IocLogInfo definitions for the SYMFC9xx chips
6 * DESCRIPTION: Contains the enumerated list of values that may be returned
7 * in the IOCLogInfo field of a MPI Default Reply Message.
8 *
9 * CREATION DATE: 6/02/2000
10 * ID: $Id: fc_log.h,v 4.6 2001/07/26 14:41:33 sschremm Exp $
11 */
12
13
14/*
15 * MpiIocLogInfo_t enum
16 *
17 * These 32 bit values are used in the IOCLogInfo field of the MPI reply
18 * messages.
19 * The value is 0xabcccccc where
20 * a = The type of log info as per the MPI spec. Since these codes are
21 * all for Fibre Channel this value will always be 2.
22 * b = Specifies a subclass of the firmware where
23 * 0 = FCP Initiator
24 * 1 = FCP Target
25 * 2 = LAN
26 * 3 = MPI Message Layer
27 * 4 = FC Link
28 * 5 = Context Manager
29 * 6 = Invalid Field Offset
30 * 7 = State Change Info
31 * all others are reserved for future use
32 * c = A specific value within the subclass.
33 *
34 * NOTE: Any new values should be added to the end of each subclass so that the
35 * codes remain consistent across firmware releases.
36 */
37typedef enum _MpiIocLogInfoFc
38{
39 MPI_IOCLOGINFO_FC_INIT_BASE = 0x20000000,
40 MPI_IOCLOGINFO_FC_INIT_ERROR_OUT_OF_ORDER_FRAME = 0x20000001, /* received an out of order frame - unsupported */
41 MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_START_OF_FRAME = 0x20000002, /* Bad Rx Frame, bad start of frame primative */
42 MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_END_OF_FRAME = 0x20000003, /* Bad Rx Frame, bad end of frame primative */
43 MPI_IOCLOGINFO_FC_INIT_ERROR_OVER_RUN = 0x20000004, /* Bad Rx Frame, overrun */
44 MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OTHER = 0x20000005, /* Other errors caught by IOC which require retries */
45 MPI_IOCLOGINFO_FC_INIT_ERROR_SUBPROC_DEAD = 0x20000006, /* Main processor could not initialize sub-processor */
46 MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OVERRUN = 0x20000007, /* Scatter Gather overrun */
47 MPI_IOCLOGINFO_FC_INIT_ERROR_RX_BAD_STATUS = 0x20000008, /* Receiver detected context mismatch via invalid header */
48 MPI_IOCLOGINFO_FC_INIT_ERROR_RX_UNEXPECTED_FRAME= 0x20000009, /* CtxMgr detected unsupported frame type */
49 MPI_IOCLOGINFO_FC_INIT_ERROR_LINK_FAILURE = 0x2000000A, /* Link failure occurred */
50 MPI_IOCLOGINFO_FC_INIT_ERROR_TX_TIMEOUT = 0x2000000B, /* Transmitter timeout error */
51
52 MPI_IOCLOGINFO_FC_TARGET_BASE = 0x21000000,
53 MPI_IOCLOGINFO_FC_TARGET_NO_PDISC = 0x21000001, /* not sent because we are waiting for a PDISC from the initiator */
54 MPI_IOCLOGINFO_FC_TARGET_NO_LOGIN = 0x21000002, /* not sent because we are not logged in to the remote node */
55 MPI_IOCLOGINFO_FC_TARGET_DOAR_KILLED_BY_LIP = 0x21000003, /* Data Out, Auto Response, not sent due to a LIP */
56 MPI_IOCLOGINFO_FC_TARGET_DIAR_KILLED_BY_LIP = 0x21000004, /* Data In, Auto Response, not sent due to a LIP */
57 MPI_IOCLOGINFO_FC_TARGET_DIAR_MISSING_DATA = 0x21000005, /* Data In, Auto Response, missing data frames */
58 MPI_IOCLOGINFO_FC_TARGET_DONR_KILLED_BY_LIP = 0x21000006, /* Data Out, No Response, not sent due to a LIP */
59 MPI_IOCLOGINFO_FC_TARGET_WRSP_KILLED_BY_LIP = 0x21000007, /* Auto-response after a write not sent due to a LIP */
60 MPI_IOCLOGINFO_FC_TARGET_DINR_KILLED_BY_LIP = 0x21000008, /* Data In, No Response, not completed due to a LIP */
61 MPI_IOCLOGINFO_FC_TARGET_DINR_MISSING_DATA = 0x21000009, /* Data In, No Response, missing data frames */
62 MPI_IOCLOGINFO_FC_TARGET_MRSP_KILLED_BY_LIP = 0x2100000a, /* Manual Response not sent due to a LIP */
63 MPI_IOCLOGINFO_FC_TARGET_NO_CLASS_3 = 0x2100000b, /* not sent because remote node does not support Class 3 */
64 MPI_IOCLOGINFO_FC_TARGET_LOGIN_NOT_VALID = 0x2100000c, /* not sent because login to remote node not validated */
65 MPI_IOCLOGINFO_FC_TARGET_FROM_OUTBOUND = 0x2100000e, /* cleared from the outbound queue after a logout */
66 MPI_IOCLOGINFO_FC_TARGET_WAITING_FOR_DATA_IN = 0x2100000f, /* cleared waiting for data after a logout */
67
68 MPI_IOCLOGINFO_FC_LAN_BASE = 0x22000000,
69 MPI_IOCLOGINFO_FC_LAN_TRANS_SGL_MISSING = 0x22000001, /* Transaction Context Sgl Missing */
70 MPI_IOCLOGINFO_FC_LAN_TRANS_WRONG_PLACE = 0x22000002, /* Transaction Context found before an EOB */
71 MPI_IOCLOGINFO_FC_LAN_TRANS_RES_BITS_SET = 0x22000003, /* Transaction Context value has reserved bits set */
72 MPI_IOCLOGINFO_FC_LAN_WRONG_SGL_FLAG = 0x22000004, /* Invalid SGL Flags */
73
74 MPI_IOCLOGINFO_FC_MSG_BASE = 0x23000000,
75
76 MPI_IOCLOGINFO_FC_LINK_BASE = 0x24000000,
77 MPI_IOCLOGINFO_FC_LINK_LOOP_INIT_TIMEOUT = 0x24000001, /* Loop initialization timed out */
78 MPI_IOCLOGINFO_FC_LINK_ALREADY_INITIALIZED = 0x24000002, /* Another system controller already initialized the loop */
79 MPI_IOCLOGINFO_FC_LINK_LINK_NOT_ESTABLISHED = 0x24000003, /* Not synchronized to signal or still negotiating (possible cable problem) */
80 MPI_IOCLOGINFO_FC_LINK_CRC_ERROR = 0x24000004, /* CRC check detected error on received frame */
81
82 MPI_IOCLOGINFO_FC_CTX_BASE = 0x25000000,
83
84 MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET = 0x26000000, /* The lower 24 bits give the byte offset of the field in the request message that is invalid */
85 MPI_IOCLOGINFO_FC_INVALID_FIELD_MAX_OFFSET = 0x26ffffff,
86
87 MPI_IOCLOGINFO_FC_STATE_CHANGE = 0x27000000 /* The lower 24 bits give additional information concerning state change */
88
89} MpiIocLogInfoFc_t;
diff --git a/drivers/message/fusion/lsi/mpi_log_sas.h b/drivers/message/fusion/lsi/mpi_log_sas.h
new file mode 100644
index 000000000000..9259d1ad6e6e
--- /dev/null
+++ b/drivers/message/fusion/lsi/mpi_log_sas.h
@@ -0,0 +1,162 @@
1
2/***************************************************************************
3 * *
4 * Copyright 2003 LSI Logic Corporation. All rights reserved. *
5 * *
6 * This file is confidential and a trade secret of LSI Logic. The *
7 * receipt of or possession of this file does not convey any rights to *
8 * reproduce or disclose its contents or to manufacture, use, or sell *
9 * anything it may describe, in whole, or in part, without the specific *
10 * written consent of LSI Logic Corporation. *
11 * *
12 ***************************************************************************
13 *
14 * Name: iopiIocLogInfo.h
15 * Title: SAS Firmware IOP Interface IOC Log Info Definitions
16 * Programmer: Guy Kendall
17 * Creation Date: September 24, 2003
18 *
19 * Version History
20 * ---------------
21 *
22 * Last Updated
23 * -------------
24 * Version %version: 22 %
25 * Date Updated %date_modified: %
26 * Programmer %created_by: nperucca %
27 *
28 * Date Who Description
29 * -------- --- -------------------------------------------------------
30 * 09/24/03 GWK Initial version
31 *
32 *
33 * Description
34 * ------------
35 * This include file contains SAS firmware interface IOC Log Info codes
36 *
37 *-------------------------------------------------------------------------
38 */
39
40#ifndef IOPI_IOCLOGINFO_H_INCLUDED
41#define IOPI_IOCLOGINFO_H_INCLUDED
42
43
44/****************************************************************************/
45/* IOC LOGINFO defines, 0x00000000 - 0x0FFFFFFF */
46/* Format: */
47/* Bits 31-28: MPI_IOCLOGINFO_TYPE_SAS (3) */
48/* Bits 27-24: IOC_LOGINFO_ORIGINATOR: 0=IOP, 1=PL, 2=IR */
49/* Bits 23-16: LOGINFO_CODE */
50/* Bits 15-0: LOGINFO_CODE Specific */
51/****************************************************************************/
52
53/****************************************************************************/
54/* IOC_LOGINFO_ORIGINATOR defines */
55/****************************************************************************/
56#define IOC_LOGINFO_ORIGINATOR_IOP (0x00000000)
57#define IOC_LOGINFO_ORIGINATOR_PL (0x01000000)
58#define IOC_LOGINFO_ORIGINATOR_IR (0x02000000)
59
60/****************************************************************************/
61/* LOGINFO_CODE defines */
62/****************************************************************************/
63#define IOC_LOGINFO_CODE_MASK (0x00FF0000)
64#define IOC_LOGINFO_CODE_SHIFT (16)
65
66/****************************************************************************/
67/* IOP LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = IOP */
68/****************************************************************************/
69#define IOP_LOGINFO_CODE_INVALID_SAS_ADDRESS (0x00010000)
70#define IOP_LOGINFO_CODE_UNUSED2 (0x00020000)
71#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE (0x00030000)
72#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_RT (0x00030100) /* Route Table Entry not found */
73#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PN (0x00030200) /* Invalid Page Number */
74#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM (0x00030300) /* Invalid FORM */
75#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT (0x00030400) /* Invalid Page Type */
76#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DNM (0x00030500) /* Device Not Mapped */
77#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PERSIST (0x00030600) /* Persistent Page not found */
78#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DEFAULT (0x00030700) /* Default Page not found */
79#define IOP_LOGINFO_CODE_TASK_TERMINATED (0x00050000)
80
81
82/****************************************************************************/
83/* PL LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = PL */
84/****************************************************************************/
85#define PL_LOGINFO_CODE_OPEN_FAILURE (0x00010000)
86#define PL_LOGINFO_CODE_INVALID_SGL (0x00020000)
87#define PL_LOGINFO_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00030000)
88#define PL_LOGINFO_CODE_FRAME_XFER_ERROR (0x00040000)
89#define PL_LOGINFO_CODE_TX_FM_CONNECTED_LOW (0x00050000)
90#define PL_LOGINFO_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET (0x00060000)
91#define PL_LOGINFO_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR (0x00070000)
92#define PL_LOGINFO_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR (0x00080000)
93#define PL_LOGINFO_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS (0x00090000)
94#define PL_LOGINFO_CODE_RX_FM_INVALID_MESSAGE (0x000A0000)
95#define PL_LOGINFO_CODE_RX_CTX_MESSAGE_VALID_ERROR (0x000B0000)
96#define PL_LOGINFO_CODE_RX_FM_CURRENT_FRAME_ERROR (0x000C0000)
97#define PL_LOGINFO_CODE_SATA_LINK_DOWN (0x000D0000)
98#define PL_LOGINFO_CODE_DISCOVERY_SATA_INIT_W_IOS (0x000E0000)
99#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE (0x000F0000)
100#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT (0x000F0100) /* Invalid Page Type */
101#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NUM_PHYS (0x000F0200) /* Invalid Number of Phys */
102#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NOT_IMP (0x000F0300) /* Case Not Handled */
103#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_DEV (0x000F0400) /* No Device Found */
104#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM (0x000F0500) /* Invalid FORM */
105#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PHY (0x000F0600) /* Invalid Phy */
106#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_OWNER (0x000F0700) /* No Owner Found */
107#define PL_LOGINFO_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00100000)
108#define PL_LOGINFO_CODE_RESET (0x00110000)
109#define PL_LOGINFO_CODE_ABORT (0x00120000)
110#define PL_LOGINFO_CODE_IO_NOT_YET_EXECUTED (0x00130000)
111#define PL_LOGINFO_CODE_IO_EXECUTED (0x00140000)
112#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE (0x00000100)
113#define PL_LOGINFO_SUB_CODE_INVALID_SGL (0x00000200)
114#define PL_LOGINFO_SUB_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00000300)
115#define PL_LOGINFO_SUB_CODE_FRAME_XFER_ERROR (0x00000400)
116#define PL_LOGINFO_SUB_CODE_TX_FM_CONNECTED_LOW (0x00000500)
117#define PL_LOGINFO_SUB_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET (0x00000600)
118#define PL_LOGINFO_SUB_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR (0x00000700)
119#define PL_LOGINFO_SUB_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR (0x00000800)
120#define PL_LOGINFO_SUB_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS (0x00000900)
121#define PL_LOGINFO_SUB_CODE_RX_FM_INVALID_MESSAGE (0x00000A00)
122#define PL_LOGINFO_SUB_CODE_RX_CTX_MESSAGE_VALID_ERROR (0x00000B00)
123#define PL_LOGINFO_SUB_CODE_RX_FM_CURRENT_FRAME_ERROR (0x00000C00)
124#define PL_LOGINFO_SUB_CODE_SATA_LINK_DOWN (0x00000D00)
125#define PL_LOGINFO_SUB_CODE_DISCOVERY_SATA_INIT_W_IOS (0x00000E00)
126#define PL_LOGINFO_SUB_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00001000)
127
128
129#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_FAILURE (0x00200000) /* Can't get SMP Frame */
130#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR (0x00200001) /* Error occured on SMP Read */
131#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_WRITE_ERROR (0x00200002) /* Error occured on SMP Write */
132#define PL_LOGINFO_CODE_ENCL_MGMT_NOT_SUPPORTED_ON_ENCL (0x00200004) /* Encl Mgmt services not available for this WWID */
133#define PL_LOGINFO_CODE_ENCL_MGMT_ADDR_MODE_NOT_SUPPORTED (0x00200005) /* Address Mode not suppored */
134#define PL_LOGINFO_CODE_ENCL_MGMT_BAD_SLOT_NUM (0x00200006) /* Invalid Slot Number in SEP Msg */
135#define PL_LOGINFO_CODE_ENCL_MGMT_SGPIO_NOT_PRESENT (0x00200007) /* SGPIO not present/enabled */
136
137#define PL_LOGINFO_DA_SEP_NOT_PRESENT (0x00200100) /* SEP not present when msg received */
138#define PL_LOGINFO_DA_SEP_SINGLE_THREAD_ERROR (0x00200101) /* Can only accept 1 msg at a time */
139#define PL_LOGINFO_DA_SEP_ISTWI_INTR_IN_IDLE_STATE (0x00200102) /* ISTWI interrupt recvd. while IDLE */
140#define PL_LOGINFO_DA_SEP_RECEIVED_NACK_FROM_SLAVE (0x00200103) /* SEP NACK'd, it is busy */
141#define PL_LOGINFO_DA_SEP_BAD_STATUS_HDR_CHKSUM (0x00200104) /* SEP stopped or sent bad chksum in Hdr */
142#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_1 (0x00200105) /* SEP returned unknown scsi status */
143#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_2 (0x00200106) /* SEP returned unknown scsi status */
144#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP (0x00200107) /* SEP returned bad chksum after STOP */
145#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP_GETDATA (0x00200108) /* SEP returned bad chksum after STOP while gettin data*/
146
147
148/****************************************************************************/
149/* IR LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = IR */
150/****************************************************************************/
151#define IR_LOGINFO_CODE_UNUSED1 (0x00010000)
152#define IR_LOGINFO_CODE_UNUSED2 (0x00020000)
153
154/****************************************************************************/
155/* Defines for convienence */
156/****************************************************************************/
157#define IOC_LOGINFO_PREFIX_IOP ((MPI_IOCLOGINFO_TYPE_SAS << MPI_IOCLOGINFO_TYPE_SHIFT) | IOC_LOGINFO_ORIGINATOR_IOP)
158#define IOC_LOGINFO_PREFIX_PL ((MPI_IOCLOGINFO_TYPE_SAS << MPI_IOCLOGINFO_TYPE_SHIFT) | IOC_LOGINFO_ORIGINATOR_PL)
159#define IOC_LOGINFO_PREFIX_IR ((MPI_IOCLOGINFO_TYPE_SAS << MPI_IOCLOGINFO_TYPE_SHIFT) | IOC_LOGINFO_ORIGINATOR_IR)
160
161#endif /* end of file */
162
diff --git a/drivers/message/fusion/lsi/mpi_sas.h b/drivers/message/fusion/lsi/mpi_sas.h
index 230fa69b5353..70514867bddf 100644
--- a/drivers/message/fusion/lsi/mpi_sas.h
+++ b/drivers/message/fusion/lsi/mpi_sas.h
@@ -6,7 +6,7 @@
6 * Title: MPI Serial Attached SCSI structures and definitions 6 * Title: MPI Serial Attached SCSI structures and definitions
7 * Creation Date: August 19, 2004 7 * Creation Date: August 19, 2004
8 * 8 *
9 * mpi_sas.h Version: 01.05.01 9 * mpi_sas.h Version: 01.05.02
10 * 10 *
11 * Version History 11 * Version History
12 * --------------- 12 * ---------------
@@ -14,6 +14,9 @@
14 * Date Version Description 14 * Date Version Description
15 * -------- -------- ------------------------------------------------------ 15 * -------- -------- ------------------------------------------------------
16 * 08-19-04 01.05.01 Original release. 16 * 08-19-04 01.05.01 Original release.
17 * 08-30-05 01.05.02 Added DeviceInfo bit for SEP.
18 * Added PrimFlags and Primitive field to SAS IO Unit
19 * Control request, and added a new operation code.
17 * -------------------------------------------------------------------------- 20 * --------------------------------------------------------------------------
18 */ 21 */
19 22
@@ -51,6 +54,7 @@
51 * Values for the SAS DeviceInfo field used in SAS Device Status Change Event 54 * Values for the SAS DeviceInfo field used in SAS Device Status Change Event
52 * data and SAS IO Unit Configuration pages. 55 * data and SAS IO Unit Configuration pages.
53 */ 56 */
57#define MPI_SAS_DEVICE_INFO_SEP (0x00004000)
54#define MPI_SAS_DEVICE_INFO_ATAPI_DEVICE (0x00002000) 58#define MPI_SAS_DEVICE_INFO_ATAPI_DEVICE (0x00002000)
55#define MPI_SAS_DEVICE_INFO_LSI_DEVICE (0x00001000) 59#define MPI_SAS_DEVICE_INFO_LSI_DEVICE (0x00001000)
56#define MPI_SAS_DEVICE_INFO_DIRECT_ATTACH (0x00000800) 60#define MPI_SAS_DEVICE_INFO_DIRECT_ATTACH (0x00000800)
@@ -212,20 +216,26 @@ typedef struct _MSG_SAS_IOUNIT_CONTROL_REQUEST
212 U8 TargetID; /* 0Ch */ 216 U8 TargetID; /* 0Ch */
213 U8 Bus; /* 0Dh */ 217 U8 Bus; /* 0Dh */
214 U8 PhyNum; /* 0Eh */ 218 U8 PhyNum; /* 0Eh */
215 U8 Reserved4; /* 0Fh */ 219 U8 PrimFlags; /* 0Fh */
216 U32 Reserved5; /* 10h */ 220 U32 Primitive; /* 10h */
217 U64 SASAddress; /* 14h */ 221 U64 SASAddress; /* 14h */
218 U32 Reserved6; /* 1Ch */ 222 U32 Reserved4; /* 1Ch */
219} MSG_SAS_IOUNIT_CONTROL_REQUEST, MPI_POINTER PTR_MSG_SAS_IOUNIT_CONTROL_REQUEST, 223} MSG_SAS_IOUNIT_CONTROL_REQUEST, MPI_POINTER PTR_MSG_SAS_IOUNIT_CONTROL_REQUEST,
220 SasIoUnitControlRequest_t, MPI_POINTER pSasIoUnitControlRequest_t; 224 SasIoUnitControlRequest_t, MPI_POINTER pSasIoUnitControlRequest_t;
221 225
222/* values for the Operation field */ 226/* values for the Operation field */
223#define MPI_SAS_OP_CLEAR_NOT_PRESENT (0x01) 227#define MPI_SAS_OP_CLEAR_NOT_PRESENT (0x01)
224#define MPI_SAS_OP_CLEAR_ALL_PERSISTENT (0x02) 228#define MPI_SAS_OP_CLEAR_ALL_PERSISTENT (0x02)
225#define MPI_SAS_OP_PHY_LINK_RESET (0x06) 229#define MPI_SAS_OP_PHY_LINK_RESET (0x06)
226#define MPI_SAS_OP_PHY_HARD_RESET (0x07) 230#define MPI_SAS_OP_PHY_HARD_RESET (0x07)
227#define MPI_SAS_OP_PHY_CLEAR_ERROR_LOG (0x08) 231#define MPI_SAS_OP_PHY_CLEAR_ERROR_LOG (0x08)
228#define MPI_SAS_OP_MAP_CURRENT (0x09) 232#define MPI_SAS_OP_MAP_CURRENT (0x09)
233#define MPI_SAS_OP_SEND_PRIMITIVE (0x0A)
234
235/* values for the PrimFlags field */
236#define MPI_SAS_PRIMFLAGS_SINGLE (0x08)
237#define MPI_SAS_PRIMFLAGS_TRIPLE (0x02)
238#define MPI_SAS_PRIMFLAGS_REDUNDANT (0x01)
229 239
230 240
231/* SAS IO Unit Control Reply */ 241/* SAS IO Unit Control Reply */
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 537836068c49..d890b2b8a93e 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -148,7 +148,6 @@ static int WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
148static int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag); 148static int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
149static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag); 149static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
150static int GetLanConfigPages(MPT_ADAPTER *ioc); 150static int GetLanConfigPages(MPT_ADAPTER *ioc);
151static int GetFcPortPage0(MPT_ADAPTER *ioc, int portnum);
152static int GetIoUnitPage2(MPT_ADAPTER *ioc); 151static int GetIoUnitPage2(MPT_ADAPTER *ioc);
153int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); 152int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
154static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum); 153static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);
@@ -1232,12 +1231,11 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
1232 dprintk((KERN_INFO MYNAM 1231 dprintk((KERN_INFO MYNAM
1233 ": Not using 64 bit consistent mask\n")); 1232 ": Not using 64 bit consistent mask\n"));
1234 1233
1235 ioc = kmalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC); 1234 ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
1236 if (ioc == NULL) { 1235 if (ioc == NULL) {
1237 printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n"); 1236 printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
1238 return -ENOMEM; 1237 return -ENOMEM;
1239 } 1238 }
1240 memset(ioc, 0, sizeof(MPT_ADAPTER));
1241 ioc->alloc_total = sizeof(MPT_ADAPTER); 1239 ioc->alloc_total = sizeof(MPT_ADAPTER);
1242 ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */ 1240 ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */
1243 ioc->reply_sz = MPT_REPLY_FRAME_SIZE; 1241 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
@@ -1245,6 +1243,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
1245 ioc->pcidev = pdev; 1243 ioc->pcidev = pdev;
1246 ioc->diagPending = 0; 1244 ioc->diagPending = 0;
1247 spin_lock_init(&ioc->diagLock); 1245 spin_lock_init(&ioc->diagLock);
1246 spin_lock_init(&ioc->fc_rescan_work_lock);
1247 spin_lock_init(&ioc->fc_rport_lock);
1248 spin_lock_init(&ioc->initializing_hba_lock); 1248 spin_lock_init(&ioc->initializing_hba_lock);
1249 1249
1250 /* Initialize the event logging. 1250 /* Initialize the event logging.
@@ -1268,6 +1268,10 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
1268 */ 1268 */
1269 INIT_LIST_HEAD(&ioc->configQ); 1269 INIT_LIST_HEAD(&ioc->configQ);
1270 1270
1271 /* Initialize the fc rport list head.
1272 */
1273 INIT_LIST_HEAD(&ioc->fc_rports);
1274
1271 /* Find lookup slot. */ 1275 /* Find lookup slot. */
1272 INIT_LIST_HEAD(&ioc->list); 1276 INIT_LIST_HEAD(&ioc->list);
1273 ioc->id = mpt_ids++; 1277 ioc->id = mpt_ids++;
@@ -1374,6 +1378,10 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
1374 ioc->bus_type = FC; 1378 ioc->bus_type = FC;
1375 ioc->errata_flag_1064 = 1; 1379 ioc->errata_flag_1064 = 1;
1376 } 1380 }
1381 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949E) {
1382 ioc->prod_name = "LSIFC949E";
1383 ioc->bus_type = FC;
1384 }
1377 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) { 1385 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) {
1378 ioc->prod_name = "LSI53C1030"; 1386 ioc->prod_name = "LSI53C1030";
1379 ioc->bus_type = SPI; 1387 ioc->bus_type = SPI;
@@ -1622,7 +1630,7 @@ mpt_resume(struct pci_dev *pdev)
1622 pci_enable_device(pdev); 1630 pci_enable_device(pdev);
1623 1631
1624 /* enable interrupts */ 1632 /* enable interrupts */
1625 CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM)); 1633 CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
1626 ioc->active = 1; 1634 ioc->active = 1;
1627 1635
1628 /* F/W not running */ 1636 /* F/W not running */
@@ -1715,7 +1723,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
1715 /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */ 1723 /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
1716 dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n", 1724 dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
1717 ioc->alt_ioc->name)); 1725 ioc->alt_ioc->name));
1718 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM)); 1726 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
1719 ioc->alt_ioc->active = 1; 1727 ioc->alt_ioc->active = 1;
1720 } 1728 }
1721 1729
@@ -1831,7 +1839,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
1831 1839
1832 if (ret == 0) { 1840 if (ret == 0) {
1833 /* Enable! (reply interrupt) */ 1841 /* Enable! (reply interrupt) */
1834 CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM)); 1842 CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
1835 ioc->active = 1; 1843 ioc->active = 1;
1836 } 1844 }
1837 1845
@@ -1839,7 +1847,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
1839 /* (re)Enable alt-IOC! (reply interrupt) */ 1847 /* (re)Enable alt-IOC! (reply interrupt) */
1840 dinitprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n", 1848 dinitprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
1841 ioc->alt_ioc->name)); 1849 ioc->alt_ioc->name));
1842 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM)); 1850 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
1843 ioc->alt_ioc->active = 1; 1851 ioc->alt_ioc->active = 1;
1844 } 1852 }
1845 1853
@@ -1880,7 +1888,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
1880 * (FCPortPage0_t stuff) 1888 * (FCPortPage0_t stuff)
1881 */ 1889 */
1882 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { 1890 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1883 (void) GetFcPortPage0(ioc, ii); 1891 (void) mptbase_GetFcPortPage0(ioc, ii);
1884 } 1892 }
1885 1893
1886 if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) && 1894 if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
@@ -4199,7 +4207,7 @@ GetLanConfigPages(MPT_ADAPTER *ioc)
4199 4207
4200/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 4208/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4201/* 4209/*
4202 * GetFcPortPage0 - Fetch FCPort config Page0. 4210 * mptbase_GetFcPortPage0 - Fetch FCPort config Page0.
4203 * @ioc: Pointer to MPT_ADAPTER structure 4211 * @ioc: Pointer to MPT_ADAPTER structure
4204 * @portnum: IOC Port number 4212 * @portnum: IOC Port number
4205 * 4213 *
@@ -4209,8 +4217,8 @@ GetLanConfigPages(MPT_ADAPTER *ioc)
4209 * -EAGAIN if no msg frames currently available 4217 * -EAGAIN if no msg frames currently available
4210 * -EFAULT for non-successful reply or no reply (timeout) 4218 * -EFAULT for non-successful reply or no reply (timeout)
4211 */ 4219 */
4212static int 4220int
4213GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) 4221mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
4214{ 4222{
4215 ConfigPageHeader_t hdr; 4223 ConfigPageHeader_t hdr;
4216 CONFIGPARMS cfg; 4224 CONFIGPARMS cfg;
@@ -4220,6 +4228,8 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
4220 int data_sz; 4228 int data_sz;
4221 int copy_sz; 4229 int copy_sz;
4222 int rc; 4230 int rc;
4231 int count = 400;
4232
4223 4233
4224 /* Get FCPort Page 0 header */ 4234 /* Get FCPort Page 0 header */
4225 hdr.PageVersion = 0; 4235 hdr.PageVersion = 0;
@@ -4243,6 +4253,8 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
4243 rc = -ENOMEM; 4253 rc = -ENOMEM;
4244 ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma); 4254 ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
4245 if (ppage0_alloc) { 4255 if (ppage0_alloc) {
4256
4257 try_again:
4246 memset((u8 *)ppage0_alloc, 0, data_sz); 4258 memset((u8 *)ppage0_alloc, 0, data_sz);
4247 cfg.physAddr = page0_dma; 4259 cfg.physAddr = page0_dma;
4248 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; 4260 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
@@ -4274,6 +4286,19 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
4274 pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount); 4286 pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);
4275 pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators); 4287 pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);
4276 4288
4289 /*
4290 * if still doing discovery,
4291 * hang loose a while until finished
4292 */
4293 if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) {
4294 if (count-- > 0) {
4295 msleep_interruptible(100);
4296 goto try_again;
4297 }
4298 printk(MYIOC_s_INFO_FMT "Firmware discovery not"
4299 " complete.\n",
4300 ioc->name);
4301 }
4277 } 4302 }
4278 4303
4279 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma); 4304 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
@@ -6358,6 +6383,7 @@ EXPORT_SYMBOL(mpt_alloc_fw_memory);
6358EXPORT_SYMBOL(mpt_free_fw_memory); 6383EXPORT_SYMBOL(mpt_free_fw_memory);
6359EXPORT_SYMBOL(mptbase_sas_persist_operation); 6384EXPORT_SYMBOL(mptbase_sas_persist_operation);
6360EXPORT_SYMBOL(mpt_alt_ioc_wait); 6385EXPORT_SYMBOL(mpt_alt_ioc_wait);
6386EXPORT_SYMBOL(mptbase_GetFcPortPage0);
6361 6387
6362 6388
6363/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 6389/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index 6c48d1f54ac9..47053ac65068 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -76,8 +76,8 @@
76#define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR 76#define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR
77#endif 77#endif
78 78
79#define MPT_LINUX_VERSION_COMMON "3.03.05" 79#define MPT_LINUX_VERSION_COMMON "3.03.06"
80#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.05" 80#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.06"
81#define WHAT_MAGIC_STRING "@" "(" "#" ")" 81#define WHAT_MAGIC_STRING "@" "(" "#" ")"
82 82
83#define show_mptmod_ver(s,ver) \ 83#define show_mptmod_ver(s,ver) \
@@ -413,7 +413,7 @@ typedef struct _MPT_IOCTL {
413 u8 status; /* current command status */ 413 u8 status; /* current command status */
414 u8 reset; /* 1 if bus reset allowed */ 414 u8 reset; /* 1 if bus reset allowed */
415 u8 target; /* target for reset */ 415 u8 target; /* target for reset */
416 struct semaphore sem_ioc; 416 struct mutex ioctl_mutex;
417} MPT_IOCTL; 417} MPT_IOCTL;
418 418
419#define MPT_SAS_MGMT_STATUS_RF_VALID 0x02 /* The Reply Frame is VALID */ 419#define MPT_SAS_MGMT_STATUS_RF_VALID 0x02 /* The Reply Frame is VALID */
@@ -421,7 +421,7 @@ typedef struct _MPT_IOCTL {
421#define MPT_SAS_MGMT_STATUS_TM_FAILED 0x40 /* User TM request failed */ 421#define MPT_SAS_MGMT_STATUS_TM_FAILED 0x40 /* User TM request failed */
422 422
423typedef struct _MPT_SAS_MGMT { 423typedef struct _MPT_SAS_MGMT {
424 struct semaphore mutex; 424 struct mutex mutex;
425 struct completion done; 425 struct completion done;
426 u8 reply[MPT_DEFAULT_FRAME_SIZE]; /* reply frame data */ 426 u8 reply[MPT_DEFAULT_FRAME_SIZE]; /* reply frame data */
427 u8 status; /* current command status */ 427 u8 status; /* current command status */
@@ -499,6 +499,22 @@ typedef struct _RaidCfgData {
499 int isRaid; /* bit field, 1 if RAID */ 499 int isRaid; /* bit field, 1 if RAID */
500}RaidCfgData; 500}RaidCfgData;
501 501
502#define MPT_RPORT_INFO_FLAGS_REGISTERED 0x01 /* rport registered */
503#define MPT_RPORT_INFO_FLAGS_MISSING 0x02 /* missing from DevPage0 scan */
504#define MPT_RPORT_INFO_FLAGS_MAPPED_VDEV 0x04 /* target mapped in vdev */
505
506/*
507 * data allocated for each fc rport device
508 */
509struct mptfc_rport_info
510{
511 struct list_head list;
512 struct fc_rport *rport;
513 VirtDevice *vdev;
514 FCDevicePage0_t pg0;
515 u8 flags;
516};
517
502/* 518/*
503 * Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS 519 * Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS
504 */ 520 */
@@ -612,7 +628,16 @@ typedef struct _MPT_ADAPTER
612 struct list_head list; 628 struct list_head list;
613 struct net_device *netdev; 629 struct net_device *netdev;
614 struct list_head sas_topology; 630 struct list_head sas_topology;
631 struct mutex sas_topology_mutex;
615 MPT_SAS_MGMT sas_mgmt; 632 MPT_SAS_MGMT sas_mgmt;
633 int num_ports;
634
635 struct list_head fc_rports;
636 spinlock_t fc_rport_lock; /* list and ri flags */
637 spinlock_t fc_rescan_work_lock;
638 int fc_rescan_work_count;
639 struct work_struct fc_rescan_work;
640
616} MPT_ADAPTER; 641} MPT_ADAPTER;
617 642
618/* 643/*
@@ -999,6 +1024,7 @@ extern void mpt_free_fw_memory(MPT_ADAPTER *ioc);
999extern int mpt_findImVolumes(MPT_ADAPTER *ioc); 1024extern int mpt_findImVolumes(MPT_ADAPTER *ioc);
1000extern int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc); 1025extern int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
1001extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); 1026extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
1027extern int mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum);
1002extern int mpt_alt_ioc_wait(MPT_ADAPTER *ioc); 1028extern int mpt_alt_ioc_wait(MPT_ADAPTER *ioc);
1003 1029
1004/* 1030/*
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index 7c340240a50e..bdf709987982 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -177,10 +177,10 @@ mptctl_syscall_down(MPT_ADAPTER *ioc, int nonblock)
177 dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down(%p,%d) called\n", ioc, nonblock)); 177 dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down(%p,%d) called\n", ioc, nonblock));
178 178
179 if (nonblock) { 179 if (nonblock) {
180 if (down_trylock(&ioc->ioctl->sem_ioc)) 180 if (!mutex_trylock(&ioc->ioctl->ioctl_mutex))
181 rc = -EAGAIN; 181 rc = -EAGAIN;
182 } else { 182 } else {
183 if (down_interruptible(&ioc->ioctl->sem_ioc)) 183 if (mutex_lock_interruptible(&ioc->ioctl->ioctl_mutex))
184 rc = -ERESTARTSYS; 184 rc = -ERESTARTSYS;
185 } 185 }
186 dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down return %d\n", rc)); 186 dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down return %d\n", rc));
@@ -557,7 +557,7 @@ __mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
557 else 557 else
558 ret = -EINVAL; 558 ret = -EINVAL;
559 559
560 up(&iocp->ioctl->sem_ioc); 560 mutex_unlock(&iocp->ioctl->ioctl_mutex);
561 561
562 return ret; 562 return ret;
563} 563}
@@ -2619,7 +2619,7 @@ compat_mptfwxfer_ioctl(struct file *filp, unsigned int cmd,
2619 2619
2620 ret = mptctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen); 2620 ret = mptctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen);
2621 2621
2622 up(&iocp->ioctl->sem_ioc); 2622 mutex_unlock(&iocp->ioctl->ioctl_mutex);
2623 2623
2624 return ret; 2624 return ret;
2625} 2625}
@@ -2673,7 +2673,7 @@ compat_mpt_command(struct file *filp, unsigned int cmd,
2673 */ 2673 */
2674 ret = mptctl_do_mpt_command (karg, &uarg->MF); 2674 ret = mptctl_do_mpt_command (karg, &uarg->MF);
2675 2675
2676 up(&iocp->ioctl->sem_ioc); 2676 mutex_unlock(&iocp->ioctl->ioctl_mutex);
2677 2677
2678 return ret; 2678 return ret;
2679} 2679}
@@ -2743,7 +2743,7 @@ mptctl_probe(struct pci_dev *pdev, const struct pci_device_id *id)
2743 memset(mem, 0, sz); 2743 memset(mem, 0, sz);
2744 ioc->ioctl = (MPT_IOCTL *) mem; 2744 ioc->ioctl = (MPT_IOCTL *) mem;
2745 ioc->ioctl->ioc = ioc; 2745 ioc->ioctl->ioc = ioc;
2746 sema_init(&ioc->ioctl->sem_ioc, 1); 2746 mutex_init(&ioc->ioctl->ioctl_mutex);
2747 return 0; 2747 return 0;
2748 2748
2749out_fail: 2749out_fail:
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index ba61e1828858..b102c7666d0e 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -55,12 +55,14 @@
55#include <linux/reboot.h> /* notifier code */ 55#include <linux/reboot.h> /* notifier code */
56#include <linux/sched.h> 56#include <linux/sched.h>
57#include <linux/workqueue.h> 57#include <linux/workqueue.h>
58#include <linux/sort.h>
58 59
59#include <scsi/scsi.h> 60#include <scsi/scsi.h>
60#include <scsi/scsi_cmnd.h> 61#include <scsi/scsi_cmnd.h>
61#include <scsi/scsi_device.h> 62#include <scsi/scsi_device.h>
62#include <scsi/scsi_host.h> 63#include <scsi/scsi_host.h>
63#include <scsi/scsi_tcq.h> 64#include <scsi/scsi_tcq.h>
65#include <scsi/scsi_transport_fc.h>
64 66
65#include "mptbase.h" 67#include "mptbase.h"
66#include "mptscsih.h" 68#include "mptscsih.h"
@@ -79,19 +81,34 @@ static int mpt_pq_filter = 0;
79module_param(mpt_pq_filter, int, 0); 81module_param(mpt_pq_filter, int, 0);
80MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)"); 82MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)");
81 83
84#define MPTFC_DEV_LOSS_TMO (60)
85static int mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO; /* reasonable default */
86module_param(mptfc_dev_loss_tmo, int, 0);
87MODULE_PARM_DESC(mptfc_dev_loss_tmo, " Initial time the driver programs the "
88 " transport to wait for an rport to "
89 " return following a device loss event."
90 " Default=60.");
91
82static int mptfcDoneCtx = -1; 92static int mptfcDoneCtx = -1;
83static int mptfcTaskCtx = -1; 93static int mptfcTaskCtx = -1;
84static int mptfcInternalCtx = -1; /* Used only for internal commands */ 94static int mptfcInternalCtx = -1; /* Used only for internal commands */
85 95
96int mptfc_slave_alloc(struct scsi_device *device);
97static int mptfc_qcmd(struct scsi_cmnd *SCpnt,
98 void (*done)(struct scsi_cmnd *));
99
100static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout);
101static void __devexit mptfc_remove(struct pci_dev *pdev);
102
86static struct scsi_host_template mptfc_driver_template = { 103static struct scsi_host_template mptfc_driver_template = {
87 .module = THIS_MODULE, 104 .module = THIS_MODULE,
88 .proc_name = "mptfc", 105 .proc_name = "mptfc",
89 .proc_info = mptscsih_proc_info, 106 .proc_info = mptscsih_proc_info,
90 .name = "MPT FC Host", 107 .name = "MPT FC Host",
91 .info = mptscsih_info, 108 .info = mptscsih_info,
92 .queuecommand = mptscsih_qcmd, 109 .queuecommand = mptfc_qcmd,
93 .target_alloc = mptscsih_target_alloc, 110 .target_alloc = mptscsih_target_alloc,
94 .slave_alloc = mptscsih_slave_alloc, 111 .slave_alloc = mptfc_slave_alloc,
95 .slave_configure = mptscsih_slave_configure, 112 .slave_configure = mptscsih_slave_configure,
96 .target_destroy = mptscsih_target_destroy, 113 .target_destroy = mptscsih_target_destroy,
97 .slave_destroy = mptscsih_slave_destroy, 114 .slave_destroy = mptscsih_slave_destroy,
@@ -128,19 +145,478 @@ static struct pci_device_id mptfc_pci_table[] = {
128 PCI_ANY_ID, PCI_ANY_ID }, 145 PCI_ANY_ID, PCI_ANY_ID },
129 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949X, 146 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949X,
130 PCI_ANY_ID, PCI_ANY_ID }, 147 PCI_ANY_ID, PCI_ANY_ID },
148 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949ES,
149 PCI_ANY_ID, PCI_ANY_ID },
131 {0} /* Terminating entry */ 150 {0} /* Terminating entry */
132}; 151};
133MODULE_DEVICE_TABLE(pci, mptfc_pci_table); 152MODULE_DEVICE_TABLE(pci, mptfc_pci_table);
134 153
135/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 154static struct scsi_transport_template *mptfc_transport_template = NULL;
136/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 155
156struct fc_function_template mptfc_transport_functions = {
157 .dd_fcrport_size = 8,
158 .show_host_node_name = 1,
159 .show_host_port_name = 1,
160 .show_host_supported_classes = 1,
161 .show_host_port_id = 1,
162 .show_rport_supported_classes = 1,
163 .show_starget_node_name = 1,
164 .show_starget_port_name = 1,
165 .show_starget_port_id = 1,
166 .set_rport_dev_loss_tmo = mptfc_set_rport_loss_tmo,
167 .show_rport_dev_loss_tmo = 1,
168
169};
170
171/* FIXME! values controlling firmware RESCAN event
172 * need to be set low to allow dev_loss_tmo to
173 * work as expected. Currently, firmware doesn't
174 * notify driver of RESCAN event until some number
175 * of seconds elapse. This value can be set via
176 * lsiutil.
177 */
178static void
179mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
180{
181 if (timeout > 0)
182 rport->dev_loss_tmo = timeout;
183 else
184 rport->dev_loss_tmo = mptfc_dev_loss_tmo;
185}
186
187static int
188mptfc_FcDevPage0_cmp_func(const void *a, const void *b)
189{
190 FCDevicePage0_t **aa = (FCDevicePage0_t **)a;
191 FCDevicePage0_t **bb = (FCDevicePage0_t **)b;
192
193 if ((*aa)->CurrentBus == (*bb)->CurrentBus) {
194 if ((*aa)->CurrentTargetID == (*bb)->CurrentTargetID)
195 return 0;
196 if ((*aa)->CurrentTargetID < (*bb)->CurrentTargetID)
197 return -1;
198 return 1;
199 }
200 if ((*aa)->CurrentBus < (*bb)->CurrentBus)
201 return -1;
202 return 1;
203}
204
205static int
206mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, int ioc_port,
207 void(*func)(MPT_ADAPTER *ioc,int channel, FCDevicePage0_t *arg))
208{
209 ConfigPageHeader_t hdr;
210 CONFIGPARMS cfg;
211 FCDevicePage0_t *ppage0_alloc, *fc;
212 dma_addr_t page0_dma;
213 int data_sz;
214 int ii;
215
216 FCDevicePage0_t *p0_array=NULL, *p_p0;
217 FCDevicePage0_t **pp0_array=NULL, **p_pp0;
218
219 int rc = -ENOMEM;
220 U32 port_id = 0xffffff;
221 int num_targ = 0;
222 int max_bus = ioc->facts.MaxBuses;
223 int max_targ = ioc->facts.MaxDevices;
224
225 if (max_bus == 0 || max_targ == 0)
226 goto out;
227
228 data_sz = sizeof(FCDevicePage0_t) * max_bus * max_targ;
229 p_p0 = p0_array = kzalloc(data_sz, GFP_KERNEL);
230 if (!p0_array)
231 goto out;
232
233 data_sz = sizeof(FCDevicePage0_t *) * max_bus * max_targ;
234 p_pp0 = pp0_array = kzalloc(data_sz, GFP_KERNEL);
235 if (!pp0_array)
236 goto out;
237
238 do {
239 /* Get FC Device Page 0 header */
240 hdr.PageVersion = 0;
241 hdr.PageLength = 0;
242 hdr.PageNumber = 0;
243 hdr.PageType = MPI_CONFIG_PAGETYPE_FC_DEVICE;
244 cfg.cfghdr.hdr = &hdr;
245 cfg.physAddr = -1;
246 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
247 cfg.dir = 0;
248 cfg.pageAddr = port_id;
249 cfg.timeout = 0;
250
251 if ((rc = mpt_config(ioc, &cfg)) != 0)
252 break;
253
254 if (hdr.PageLength <= 0)
255 break;
256
257 data_sz = hdr.PageLength * 4;
258 ppage0_alloc = pci_alloc_consistent(ioc->pcidev, data_sz,
259 &page0_dma);
260 rc = -ENOMEM;
261 if (!ppage0_alloc)
262 break;
263
264 cfg.physAddr = page0_dma;
265 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
266
267 if ((rc = mpt_config(ioc, &cfg)) == 0) {
268 ppage0_alloc->PortIdentifier =
269 le32_to_cpu(ppage0_alloc->PortIdentifier);
270
271 ppage0_alloc->WWNN.Low =
272 le32_to_cpu(ppage0_alloc->WWNN.Low);
273
274 ppage0_alloc->WWNN.High =
275 le32_to_cpu(ppage0_alloc->WWNN.High);
276
277 ppage0_alloc->WWPN.Low =
278 le32_to_cpu(ppage0_alloc->WWPN.Low);
279
280 ppage0_alloc->WWPN.High =
281 le32_to_cpu(ppage0_alloc->WWPN.High);
282
283 ppage0_alloc->BBCredit =
284 le16_to_cpu(ppage0_alloc->BBCredit);
285
286 ppage0_alloc->MaxRxFrameSize =
287 le16_to_cpu(ppage0_alloc->MaxRxFrameSize);
288
289 port_id = ppage0_alloc->PortIdentifier;
290 num_targ++;
291 *p_p0 = *ppage0_alloc; /* save data */
292 *p_pp0++ = p_p0++; /* save addr */
293 }
294 pci_free_consistent(ioc->pcidev, data_sz,
295 (u8 *) ppage0_alloc, page0_dma);
296 if (rc != 0)
297 break;
298
299 } while (port_id <= 0xff0000);
300
301 if (num_targ) {
302 /* sort array */
303 if (num_targ > 1)
304 sort (pp0_array, num_targ, sizeof(FCDevicePage0_t *),
305 mptfc_FcDevPage0_cmp_func, NULL);
306 /* call caller's func for each targ */
307 for (ii = 0; ii < num_targ; ii++) {
308 fc = *(pp0_array+ii);
309 func(ioc, ioc_port, fc);
310 }
311 }
312
313 out:
314 if (pp0_array)
315 kfree(pp0_array);
316 if (p0_array)
317 kfree(p0_array);
318 return rc;
319}
320
321static int
322mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid)
323{
324 /* not currently usable */
325 if (pg0->Flags & (MPI_FC_DEVICE_PAGE0_FLAGS_PLOGI_INVALID |
326 MPI_FC_DEVICE_PAGE0_FLAGS_PRLI_INVALID))
327 return -1;
328
329 if (!(pg0->Flags & MPI_FC_DEVICE_PAGE0_FLAGS_TARGETID_BUS_VALID))
330 return -1;
331
332 if (!(pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_TARGET))
333 return -1;
334
335 /*
336 * board data structure already normalized to platform endianness
337 * shifted to avoid unaligned access on 64 bit architecture
338 */
339 rid->node_name = ((u64)pg0->WWNN.High) << 32 | (u64)pg0->WWNN.Low;
340 rid->port_name = ((u64)pg0->WWPN.High) << 32 | (u64)pg0->WWPN.Low;
341 rid->port_id = pg0->PortIdentifier;
342 rid->roles = FC_RPORT_ROLE_UNKNOWN;
343 rid->roles |= FC_RPORT_ROLE_FCP_TARGET;
344 if (pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR)
345 rid->roles |= FC_RPORT_ROLE_FCP_INITIATOR;
346
347 return 0;
348}
349
350static void
351mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
352{
353 struct fc_rport_identifiers rport_ids;
354 struct fc_rport *rport;
355 struct mptfc_rport_info *ri;
356 int match = 0;
357 u64 port_name;
358 unsigned long flags;
359
360 if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0)
361 return;
362
363 /* scan list looking for a match */
364 spin_lock_irqsave(&ioc->fc_rport_lock, flags);
365 list_for_each_entry(ri, &ioc->fc_rports, list) {
366 port_name = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
367 if (port_name == rport_ids.port_name) { /* match */
368 list_move_tail(&ri->list, &ioc->fc_rports);
369 match = 1;
370 break;
371 }
372 }
373 if (!match) { /* allocate one */
374 spin_unlock_irqrestore(&ioc->fc_rport_lock, flags);
375 ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL);
376 if (!ri)
377 return;
378 spin_lock_irqsave(&ioc->fc_rport_lock, flags);
379 list_add_tail(&ri->list, &ioc->fc_rports);
380 }
381
382 ri->pg0 = *pg0; /* add/update pg0 data */
383 ri->flags &= ~MPT_RPORT_INFO_FLAGS_MISSING;
384
385 if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) {
386 ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED;
387 spin_unlock_irqrestore(&ioc->fc_rport_lock, flags);
388 rport = fc_remote_port_add(ioc->sh,channel, &rport_ids);
389 spin_lock_irqsave(&ioc->fc_rport_lock, flags);
390 if (rport) {
391 if (*((struct mptfc_rport_info **)rport->dd_data) != ri) {
392 ri->flags &= ~MPT_RPORT_INFO_FLAGS_MAPPED_VDEV;
393 ri->vdev = NULL;
394 ri->rport = rport;
395 *((struct mptfc_rport_info **)rport->dd_data) = ri;
396 }
397 rport->dev_loss_tmo = mptfc_dev_loss_tmo;
398 /*
399 * if already mapped, remap here. If not mapped,
400 * slave_alloc will allocate vdev and map
401 */
402 if (ri->flags & MPT_RPORT_INFO_FLAGS_MAPPED_VDEV) {
403 ri->vdev->target_id = ri->pg0.CurrentTargetID;
404 ri->vdev->bus_id = ri->pg0.CurrentBus;
405 ri->vdev->vtarget->target_id = ri->vdev->target_id;
406 ri->vdev->vtarget->bus_id = ri->vdev->bus_id;
407 }
408 #ifdef MPT_DEBUG
409 printk ("mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, "
410 "rport tid %d, tmo %d\n",
411 ioc->sh->host_no,
412 pg0->PortIdentifier,
413 pg0->WWNN,
414 pg0->WWPN,
415 pg0->CurrentTargetID,
416 ri->rport->scsi_target_id,
417 ri->rport->dev_loss_tmo);
418 #endif
419 } else {
420 list_del(&ri->list);
421 kfree(ri);
422 ri = NULL;
423 }
424 }
425 spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
426
427}
428
137/* 429/*
138 * mptfc_probe - Installs scsi devices per bus. 430 * OS entry point to allow host driver to alloc memory
139 * @pdev: Pointer to pci_dev structure 431 * for each scsi device. Called once per device the bus scan.
140 * 432 * Return non-zero if allocation fails.
141 * Returns 0 for success, non-zero for failure. 433 * Init memory once per LUN.
142 *
143 */ 434 */
435int
436mptfc_slave_alloc(struct scsi_device *sdev)
437{
438 MPT_SCSI_HOST *hd;
439 VirtTarget *vtarget;
440 VirtDevice *vdev;
441 struct scsi_target *starget;
442 struct fc_rport *rport;
443 struct mptfc_rport_info *ri;
444 unsigned long flags;
445
446
447 rport = starget_to_rport(scsi_target(sdev));
448
449 if (!rport || fc_remote_port_chkready(rport))
450 return -ENXIO;
451
452 hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
453
454 vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL);
455 if (!vdev) {
456 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
457 hd->ioc->name, sizeof(VirtDevice));
458 return -ENOMEM;
459 }
460 memset(vdev, 0, sizeof(VirtDevice));
461
462 spin_lock_irqsave(&hd->ioc->fc_rport_lock,flags);
463
464 if (!(ri = *((struct mptfc_rport_info **)rport->dd_data))) {
465 spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags);
466 kfree(vdev);
467 return -ENODEV;
468 }
469
470 sdev->hostdata = vdev;
471 starget = scsi_target(sdev);
472 vtarget = starget->hostdata;
473 if (vtarget->num_luns == 0) {
474 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES |
475 MPT_TARGET_FLAGS_VALID_INQUIRY;
476 hd->Targets[sdev->id] = vtarget;
477 }
478
479 vtarget->target_id = vdev->target_id;
480 vtarget->bus_id = vdev->bus_id;
481
482 vdev->vtarget = vtarget;
483 vdev->ioc_id = hd->ioc->id;
484 vdev->lun = sdev->lun;
485 vdev->target_id = ri->pg0.CurrentTargetID;
486 vdev->bus_id = ri->pg0.CurrentBus;
487
488 ri->flags |= MPT_RPORT_INFO_FLAGS_MAPPED_VDEV;
489 ri->vdev = vdev;
490
491 spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags);
492
493 vtarget->num_luns++;
494
495#ifdef MPT_DEBUG
496 printk ("mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "
497 "CurrentTargetID %d, %x %llx %llx\n",
498 sdev->host->host_no,
499 vtarget->num_luns,
500 sdev->id, ri->pg0.CurrentTargetID,
501 ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN);
502#endif
503
504 return 0;
505}
506
507static int
508mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
509{
510 struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device));
511 int err;
512
513 err = fc_remote_port_chkready(rport);
514 if (unlikely(err)) {
515 SCpnt->result = err;
516 done(SCpnt);
517 return 0;
518 }
519 return mptscsih_qcmd(SCpnt,done);
520}
521
522static void
523mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum)
524{
525 unsigned class = 0, cos = 0;
526
527 /* don't know what to do as only one scsi (fc) host was allocated */
528 if (portnum != 0)
529 return;
530
531 class = ioc->fc_port_page0[portnum].SupportedServiceClass;
532 if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_1)
533 cos |= FC_COS_CLASS1;
534 if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_2)
535 cos |= FC_COS_CLASS2;
536 if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_3)
537 cos |= FC_COS_CLASS3;
538
539 fc_host_node_name(ioc->sh) =
540 (u64)ioc->fc_port_page0[portnum].WWNN.High << 32
541 | (u64)ioc->fc_port_page0[portnum].WWNN.Low;
542
543 fc_host_port_name(ioc->sh) =
544 (u64)ioc->fc_port_page0[portnum].WWPN.High << 32
545 | (u64)ioc->fc_port_page0[portnum].WWPN.Low;
546
547 fc_host_port_id(ioc->sh) = ioc->fc_port_page0[portnum].PortIdentifier;
548
549 fc_host_supported_classes(ioc->sh) = cos;
550
551 fc_host_tgtid_bind_type(ioc->sh) = FC_TGTID_BIND_BY_WWPN;
552}
553
554static void
555mptfc_rescan_devices(void *arg)
556{
557 MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
558 int ii;
559 int work_to_do;
560 unsigned long flags;
561 struct mptfc_rport_info *ri;
562
563 do {
564 /* start by tagging all ports as missing */
565 spin_lock_irqsave(&ioc->fc_rport_lock,flags);
566 list_for_each_entry(ri, &ioc->fc_rports, list) {
567 if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
568 ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING;
569 }
570 }
571 spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
572
573 /*
574 * now rescan devices known to adapter,
575 * will reregister existing rports
576 */
577 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
578 (void) mptbase_GetFcPortPage0(ioc, ii);
579 mptfc_init_host_attr(ioc,ii); /* refresh */
580 mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev);
581 }
582
583 /* delete devices still missing */
584 spin_lock_irqsave(&ioc->fc_rport_lock, flags);
585 list_for_each_entry(ri, &ioc->fc_rports, list) {
586 /* if newly missing, delete it */
587 if ((ri->flags & (MPT_RPORT_INFO_FLAGS_REGISTERED |
588 MPT_RPORT_INFO_FLAGS_MISSING))
589 == (MPT_RPORT_INFO_FLAGS_REGISTERED |
590 MPT_RPORT_INFO_FLAGS_MISSING)) {
591
592 ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|
593 MPT_RPORT_INFO_FLAGS_MISSING);
594 fc_remote_port_delete(ri->rport);
595 /*
596 * remote port not really deleted 'cause
597 * binding is by WWPN and driver only
598 * registers FCP_TARGETs
599 */
600 #ifdef MPT_DEBUG
601 printk ("mptfc_rescan.%d: %llx deleted\n",
602 ioc->sh->host_no, ri->pg0.WWPN);
603 #endif
604 }
605 }
606 spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
607
608 /*
609 * allow multiple passes as target state
610 * might have changed during scan
611 */
612 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
613 if (ioc->fc_rescan_work_count > 2) /* only need one more */
614 ioc->fc_rescan_work_count = 2;
615 work_to_do = --ioc->fc_rescan_work_count;
616 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
617 } while (work_to_do);
618}
619
144static int 620static int
145mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) 621mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
146{ 622{
@@ -148,17 +624,16 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
148 MPT_SCSI_HOST *hd; 624 MPT_SCSI_HOST *hd;
149 MPT_ADAPTER *ioc; 625 MPT_ADAPTER *ioc;
150 unsigned long flags; 626 unsigned long flags;
151 int sz, ii; 627 int ii;
152 int numSGE = 0; 628 int numSGE = 0;
153 int scale; 629 int scale;
154 int ioc_cap; 630 int ioc_cap;
155 u8 *mem;
156 int error=0; 631 int error=0;
157 int r; 632 int r;
158 633
159 if ((r = mpt_attach(pdev,id)) != 0) 634 if ((r = mpt_attach(pdev,id)) != 0)
160 return r; 635 return r;
161 636
162 ioc = pci_get_drvdata(pdev); 637 ioc = pci_get_drvdata(pdev);
163 ioc->DoneCtx = mptfcDoneCtx; 638 ioc->DoneCtx = mptfcDoneCtx;
164 ioc->TaskCtx = mptfcTaskCtx; 639 ioc->TaskCtx = mptfcTaskCtx;
@@ -194,7 +669,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
194 printk(MYIOC_s_WARN_FMT 669 printk(MYIOC_s_WARN_FMT
195 "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n", 670 "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
196 ioc->name, ioc); 671 ioc->name, ioc);
197 return 0; 672 return -ENODEV;
198 } 673 }
199 674
200 sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST)); 675 sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));
@@ -207,6 +682,8 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
207 goto out_mptfc_probe; 682 goto out_mptfc_probe;
208 } 683 }
209 684
685 INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices,(void *)ioc);
686
210 spin_lock_irqsave(&ioc->FreeQlock, flags); 687 spin_lock_irqsave(&ioc->FreeQlock, flags);
211 688
212 /* Attach the SCSI Host to the IOC structure 689 /* Attach the SCSI Host to the IOC structure
@@ -268,36 +745,27 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
268 /* SCSI needs scsi_cmnd lookup table! 745 /* SCSI needs scsi_cmnd lookup table!
269 * (with size equal to req_depth*PtrSz!) 746 * (with size equal to req_depth*PtrSz!)
270 */ 747 */
271 sz = ioc->req_depth * sizeof(void *); 748 hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
272 mem = kmalloc(sz, GFP_ATOMIC); 749 if (!hd->ScsiLookup) {
273 if (mem == NULL) {
274 error = -ENOMEM; 750 error = -ENOMEM;
275 goto out_mptfc_probe; 751 goto out_mptfc_probe;
276 } 752 }
277 753
278 memset(mem, 0, sz); 754 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
279 hd->ScsiLookup = (struct scsi_cmnd **) mem; 755 ioc->name, hd->ScsiLookup));
280
281 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
282 ioc->name, hd->ScsiLookup, sz));
283 756
284 /* Allocate memory for the device structures. 757 /* Allocate memory for the device structures.
285 * A non-Null pointer at an offset 758 * A non-Null pointer at an offset
286 * indicates a device exists. 759 * indicates a device exists.
287 * max_id = 1 + maximum id (hosts.h) 760 * max_id = 1 + maximum id (hosts.h)
288 */ 761 */
289 sz = sh->max_id * sizeof(void *); 762 hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
290 mem = kmalloc(sz, GFP_ATOMIC); 763 if (!hd->Targets) {
291 if (mem == NULL) {
292 error = -ENOMEM; 764 error = -ENOMEM;
293 goto out_mptfc_probe; 765 goto out_mptfc_probe;
294 } 766 }
295 767
296 memset(mem, 0, sz); 768 dprintk((KERN_INFO " vdev @ %p\n", hd->Targets));
297 hd->Targets = (VirtTarget **) mem;
298
299 dprintk((KERN_INFO
300 " vdev @ %p, sz=%d\n", hd->Targets, sz));
301 769
302 /* Clear the TM flags 770 /* Clear the TM flags
303 */ 771 */
@@ -332,6 +800,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
332 hd->scandv_wait_done = 0; 800 hd->scandv_wait_done = 0;
333 hd->last_queue_full = 0; 801 hd->last_queue_full = 0;
334 802
803 sh->transportt = mptfc_transport_template;
335 error = scsi_add_host (sh, &ioc->pcidev->dev); 804 error = scsi_add_host (sh, &ioc->pcidev->dev);
336 if(error) { 805 if(error) {
337 dprintk((KERN_ERR MYNAM 806 dprintk((KERN_ERR MYNAM
@@ -339,7 +808,11 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
339 goto out_mptfc_probe; 808 goto out_mptfc_probe;
340 } 809 }
341 810
342 scsi_scan_host(sh); 811 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
812 mptfc_init_host_attr(ioc,ii);
813 mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev);
814 }
815
343 return 0; 816 return 0;
344 817
345out_mptfc_probe: 818out_mptfc_probe:
@@ -352,7 +825,7 @@ static struct pci_driver mptfc_driver = {
352 .name = "mptfc", 825 .name = "mptfc",
353 .id_table = mptfc_pci_table, 826 .id_table = mptfc_pci_table,
354 .probe = mptfc_probe, 827 .probe = mptfc_probe,
355 .remove = __devexit_p(mptscsih_remove), 828 .remove = __devexit_p(mptfc_remove),
356 .shutdown = mptscsih_shutdown, 829 .shutdown = mptscsih_shutdown,
357#ifdef CONFIG_PM 830#ifdef CONFIG_PM
358 .suspend = mptscsih_suspend, 831 .suspend = mptscsih_suspend,
@@ -370,9 +843,20 @@ static struct pci_driver mptfc_driver = {
370static int __init 843static int __init
371mptfc_init(void) 844mptfc_init(void)
372{ 845{
846 int error;
373 847
374 show_mptmod_ver(my_NAME, my_VERSION); 848 show_mptmod_ver(my_NAME, my_VERSION);
375 849
850 /* sanity check module parameter */
851 if (mptfc_dev_loss_tmo == 0)
852 mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;
853
854 mptfc_transport_template =
855 fc_attach_transport(&mptfc_transport_functions);
856
857 if (!mptfc_transport_template)
858 return -ENODEV;
859
376 mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER); 860 mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER);
377 mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER); 861 mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER);
378 mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER); 862 mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER);
@@ -387,7 +871,33 @@ mptfc_init(void)
387 ": Registered for IOC reset notifications\n")); 871 ": Registered for IOC reset notifications\n"));
388 } 872 }
389 873
390 return pci_register_driver(&mptfc_driver); 874 error = pci_register_driver(&mptfc_driver);
875 if (error) {
876 fc_release_transport(mptfc_transport_template);
877 }
878
879 return error;
880}
881
882/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
883/**
884 * mptfc_remove - Removed fc infrastructure for devices
885 * @pdev: Pointer to pci_dev structure
886 *
887 */
888static void __devexit mptfc_remove(struct pci_dev *pdev)
889{
890 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
891 struct mptfc_rport_info *p, *n;
892
893 fc_remove_host(ioc->sh);
894
895 list_for_each_entry_safe(p, n, &ioc->fc_rports, list) {
896 list_del(&p->list);
897 kfree(p);
898 }
899
900 mptscsih_remove(pdev);
391} 901}
392 902
393/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 903/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -400,7 +910,8 @@ static void __exit
400mptfc_exit(void) 910mptfc_exit(void)
401{ 911{
402 pci_unregister_driver(&mptfc_driver); 912 pci_unregister_driver(&mptfc_driver);
403 913 fc_release_transport(mptfc_transport_template);
914
404 mpt_reset_deregister(mptfcDoneCtx); 915 mpt_reset_deregister(mptfcDoneCtx);
405 dprintk((KERN_INFO MYNAM 916 dprintk((KERN_INFO MYNAM
406 ": Deregistered for IOC reset notifications\n")); 917 ": Deregistered for IOC reset notifications\n"));
diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c
index 014085d8ec85..73f59528212a 100644
--- a/drivers/message/fusion/mptlan.c
+++ b/drivers/message/fusion/mptlan.c
@@ -411,14 +411,12 @@ mpt_lan_open(struct net_device *dev)
411 goto out; 411 goto out;
412 priv->mpt_txfidx_tail = -1; 412 priv->mpt_txfidx_tail = -1;
413 413
414 priv->SendCtl = kmalloc(priv->tx_max_out * sizeof(struct BufferControl), 414 priv->SendCtl = kcalloc(priv->tx_max_out, sizeof(struct BufferControl),
415 GFP_KERNEL); 415 GFP_KERNEL);
416 if (priv->SendCtl == NULL) 416 if (priv->SendCtl == NULL)
417 goto out_mpt_txfidx; 417 goto out_mpt_txfidx;
418 for (i = 0; i < priv->tx_max_out; i++) { 418 for (i = 0; i < priv->tx_max_out; i++)
419 memset(&priv->SendCtl[i], 0, sizeof(struct BufferControl));
420 priv->mpt_txfidx[++priv->mpt_txfidx_tail] = i; 419 priv->mpt_txfidx[++priv->mpt_txfidx_tail] = i;
421 }
422 420
423 dlprintk((KERN_INFO MYNAM "@lo: Finished initializing SendCtl\n")); 421 dlprintk((KERN_INFO MYNAM "@lo: Finished initializing SendCtl\n"));
424 422
@@ -428,15 +426,13 @@ mpt_lan_open(struct net_device *dev)
428 goto out_SendCtl; 426 goto out_SendCtl;
429 priv->mpt_rxfidx_tail = -1; 427 priv->mpt_rxfidx_tail = -1;
430 428
431 priv->RcvCtl = kmalloc(priv->max_buckets_out * 429 priv->RcvCtl = kcalloc(priv->max_buckets_out,
432 sizeof(struct BufferControl), 430 sizeof(struct BufferControl),
433 GFP_KERNEL); 431 GFP_KERNEL);
434 if (priv->RcvCtl == NULL) 432 if (priv->RcvCtl == NULL)
435 goto out_mpt_rxfidx; 433 goto out_mpt_rxfidx;
436 for (i = 0; i < priv->max_buckets_out; i++) { 434 for (i = 0; i < priv->max_buckets_out; i++)
437 memset(&priv->RcvCtl[i], 0, sizeof(struct BufferControl));
438 priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = i; 435 priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = i;
439 }
440 436
441/**/ dlprintk((KERN_INFO MYNAM "/lo: txfidx contains - ")); 437/**/ dlprintk((KERN_INFO MYNAM "/lo: txfidx contains - "));
442/**/ for (i = 0; i < priv->tx_max_out; i++) 438/**/ for (i = 0; i < priv->tx_max_out; i++)
@@ -848,7 +844,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, struct net_device *dev)
848} 844}
849 845
850/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 846/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
851static inline void 847static void
852mpt_lan_wake_post_buckets_task(struct net_device *dev, int priority) 848mpt_lan_wake_post_buckets_task(struct net_device *dev, int priority)
853/* 849/*
854 * @priority: 0 = put it on the timer queue, 1 = put it on the immediate queue 850 * @priority: 0 = put it on the timer queue, 1 = put it on the immediate queue
@@ -870,7 +866,7 @@ mpt_lan_wake_post_buckets_task(struct net_device *dev, int priority)
870} 866}
871 867
872/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 868/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
873static inline int 869static int
874mpt_lan_receive_skb(struct net_device *dev, struct sk_buff *skb) 870mpt_lan_receive_skb(struct net_device *dev, struct sk_buff *skb)
875{ 871{
876 struct mpt_lan_priv *priv = dev->priv; 872 struct mpt_lan_priv *priv = dev->priv;
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 17e9757e728b..5a06d8d8694e 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -5,7 +5,7 @@
5 * 5 *
6 * Copyright (c) 1999-2005 LSI Logic Corporation 6 * Copyright (c) 1999-2005 LSI Logic Corporation
7 * (mailto:mpt_linux_developer@lsil.com) 7 * (mailto:mpt_linux_developer@lsil.com)
8 * Copyright (c) 2005 Dell 8 * Copyright (c) 2005-2006 Dell
9 */ 9 */
10/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 10/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11/* 11/*
@@ -86,6 +86,24 @@ static int mptsasInternalCtx = -1; /* Used only for internal commands */
86static int mptsasMgmtCtx = -1; 86static int mptsasMgmtCtx = -1;
87 87
88 88
89enum mptsas_hotplug_action {
90 MPTSAS_ADD_DEVICE,
91 MPTSAS_DEL_DEVICE,
92};
93
94struct mptsas_hotplug_event {
95 struct work_struct work;
96 MPT_ADAPTER *ioc;
97 enum mptsas_hotplug_action event_type;
98 u64 sas_address;
99 u32 channel;
100 u32 id;
101 u32 device_info;
102 u16 handle;
103 u16 parent_handle;
104 u8 phy_id;
105};
106
89/* 107/*
90 * SAS topology structures 108 * SAS topology structures
91 * 109 *
@@ -99,8 +117,8 @@ struct mptsas_devinfo {
99 u8 phy_id; /* phy number of parent device */ 117 u8 phy_id; /* phy number of parent device */
100 u8 port_id; /* sas physical port this device 118 u8 port_id; /* sas physical port this device
101 is assoc'd with */ 119 is assoc'd with */
102 u8 target; /* logical target id of this device */ 120 u8 id; /* logical target id of this device */
103 u8 bus; /* logical bus number of this device */ 121 u8 channel; /* logical bus number of this device */
104 u64 sas_address; /* WWN of this device, 122 u64 sas_address; /* WWN of this device,
105 SATA is assigned by HBA,expander */ 123 SATA is assigned by HBA,expander */
106 u32 device_info; /* bitfield detailed info about this device */ 124 u32 device_info; /* bitfield detailed info about this device */
@@ -114,6 +132,7 @@ struct mptsas_phyinfo {
114 u8 programmed_link_rate; /* programmed max/min phy link rate */ 132 u8 programmed_link_rate; /* programmed max/min phy link rate */
115 struct mptsas_devinfo identify; /* point to phy device info */ 133 struct mptsas_devinfo identify; /* point to phy device info */
116 struct mptsas_devinfo attached; /* point to attached device info */ 134 struct mptsas_devinfo attached; /* point to attached device info */
135 struct sas_phy *phy;
117 struct sas_rphy *rphy; 136 struct sas_rphy *rphy;
118}; 137};
119 138
@@ -239,13 +258,12 @@ mptsas_slave_alloc(struct scsi_device *sdev)
239 struct scsi_target *starget; 258 struct scsi_target *starget;
240 int i; 259 int i;
241 260
242 vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL); 261 vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
243 if (!vdev) { 262 if (!vdev) {
244 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n", 263 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
245 hd->ioc->name, sizeof(VirtDevice)); 264 hd->ioc->name, sizeof(VirtDevice));
246 return -ENOMEM; 265 return -ENOMEM;
247 } 266 }
248 memset(vdev, 0, sizeof(VirtDevice));
249 vdev->ioc_id = hd->ioc->id; 267 vdev->ioc_id = hd->ioc->id;
250 sdev->hostdata = vdev; 268 sdev->hostdata = vdev;
251 starget = scsi_target(sdev); 269 starget = scsi_target(sdev);
@@ -256,19 +274,32 @@ mptsas_slave_alloc(struct scsi_device *sdev)
256 hd->Targets[sdev->id] = vtarget; 274 hd->Targets[sdev->id] = vtarget;
257 } 275 }
258 276
277 /*
278 RAID volumes placed beyond the last expected port.
279 */
280 if (sdev->channel == hd->ioc->num_ports) {
281 vdev->target_id = sdev->id;
282 vdev->bus_id = 0;
283 vdev->lun = 0;
284 goto out;
285 }
286
259 rphy = dev_to_rphy(sdev->sdev_target->dev.parent); 287 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
288 mutex_lock(&hd->ioc->sas_topology_mutex);
260 list_for_each_entry(p, &hd->ioc->sas_topology, list) { 289 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
261 for (i = 0; i < p->num_phys; i++) { 290 for (i = 0; i < p->num_phys; i++) {
262 if (p->phy_info[i].attached.sas_address == 291 if (p->phy_info[i].attached.sas_address ==
263 rphy->identify.sas_address) { 292 rphy->identify.sas_address) {
264 vdev->target_id = 293 vdev->target_id =
265 p->phy_info[i].attached.target; 294 p->phy_info[i].attached.id;
266 vdev->bus_id = p->phy_info[i].attached.bus; 295 vdev->bus_id = p->phy_info[i].attached.channel;
267 vdev->lun = sdev->lun; 296 vdev->lun = sdev->lun;
297 mutex_unlock(&hd->ioc->sas_topology_mutex);
268 goto out; 298 goto out;
269 } 299 }
270 } 300 }
271 } 301 }
302 mutex_unlock(&hd->ioc->sas_topology_mutex);
272 303
273 printk("No matching SAS device found!!\n"); 304 printk("No matching SAS device found!!\n");
274 kfree(vdev); 305 kfree(vdev);
@@ -282,6 +313,42 @@ mptsas_slave_alloc(struct scsi_device *sdev)
282 return 0; 313 return 0;
283} 314}
284 315
316static void
317mptsas_slave_destroy(struct scsi_device *sdev)
318{
319 struct Scsi_Host *host = sdev->host;
320 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
321 struct sas_rphy *rphy;
322 struct mptsas_portinfo *p;
323 int i;
324
325 /*
326 * Handle hotplug removal case.
327 * We need to clear out attached data structure.
328 */
329 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
330
331 mutex_lock(&hd->ioc->sas_topology_mutex);
332 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
333 for (i = 0; i < p->num_phys; i++) {
334 if (p->phy_info[i].attached.sas_address ==
335 rphy->identify.sas_address) {
336 memset(&p->phy_info[i].attached, 0,
337 sizeof(struct mptsas_devinfo));
338 p->phy_info[i].rphy = NULL;
339 goto out;
340 }
341 }
342 }
343
344 out:
345 mutex_unlock(&hd->ioc->sas_topology_mutex);
346 /*
347 * TODO: Issue target reset to flush firmware outstanding commands.
348 */
349 mptscsih_slave_destroy(sdev);
350}
351
285static struct scsi_host_template mptsas_driver_template = { 352static struct scsi_host_template mptsas_driver_template = {
286 .module = THIS_MODULE, 353 .module = THIS_MODULE,
287 .proc_name = "mptsas", 354 .proc_name = "mptsas",
@@ -293,7 +360,7 @@ static struct scsi_host_template mptsas_driver_template = {
293 .slave_alloc = mptsas_slave_alloc, 360 .slave_alloc = mptsas_slave_alloc,
294 .slave_configure = mptscsih_slave_configure, 361 .slave_configure = mptscsih_slave_configure,
295 .target_destroy = mptscsih_target_destroy, 362 .target_destroy = mptscsih_target_destroy,
296 .slave_destroy = mptscsih_slave_destroy, 363 .slave_destroy = mptsas_slave_destroy,
297 .change_queue_depth = mptscsih_change_queue_depth, 364 .change_queue_depth = mptscsih_change_queue_depth,
298 .eh_abort_handler = mptscsih_abort, 365 .eh_abort_handler = mptscsih_abort,
299 .eh_device_reset_handler = mptscsih_dev_reset, 366 .eh_device_reset_handler = mptscsih_dev_reset,
@@ -399,7 +466,7 @@ static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
399 if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP) 466 if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
400 return -ENXIO; 467 return -ENXIO;
401 468
402 if (down_interruptible(&ioc->sas_mgmt.mutex)) 469 if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
403 goto out; 470 goto out;
404 471
405 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc); 472 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
@@ -450,7 +517,7 @@ static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
450 error = 0; 517 error = 0;
451 518
452 out_unlock: 519 out_unlock:
453 up(&ioc->sas_mgmt.mutex); 520 mutex_unlock(&ioc->sas_mgmt.mutex);
454 out: 521 out:
455 return error; 522 return error;
456} 523}
@@ -649,8 +716,8 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
649 device_info->handle = le16_to_cpu(buffer->DevHandle); 716 device_info->handle = le16_to_cpu(buffer->DevHandle);
650 device_info->phy_id = buffer->PhyNum; 717 device_info->phy_id = buffer->PhyNum;
651 device_info->port_id = buffer->PhysicalPort; 718 device_info->port_id = buffer->PhysicalPort;
652 device_info->target = buffer->TargetID; 719 device_info->id = buffer->TargetID;
653 device_info->bus = buffer->Bus; 720 device_info->channel = buffer->Bus;
654 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64)); 721 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
655 device_info->sas_address = le64_to_cpu(sas_address); 722 device_info->sas_address = le64_to_cpu(sas_address);
656 device_info->device_info = 723 device_info->device_info =
@@ -858,36 +925,36 @@ mptsas_parse_device_info(struct sas_identify *identify,
858static int mptsas_probe_one_phy(struct device *dev, 925static int mptsas_probe_one_phy(struct device *dev,
859 struct mptsas_phyinfo *phy_info, int index, int local) 926 struct mptsas_phyinfo *phy_info, int index, int local)
860{ 927{
861 struct sas_phy *port; 928 struct sas_phy *phy;
862 int error; 929 int error;
863 930
864 port = sas_phy_alloc(dev, index); 931 phy = sas_phy_alloc(dev, index);
865 if (!port) 932 if (!phy)
866 return -ENOMEM; 933 return -ENOMEM;
867 934
868 port->port_identifier = phy_info->port_id; 935 phy->port_identifier = phy_info->port_id;
869 mptsas_parse_device_info(&port->identify, &phy_info->identify); 936 mptsas_parse_device_info(&phy->identify, &phy_info->identify);
870 937
871 /* 938 /*
872 * Set Negotiated link rate. 939 * Set Negotiated link rate.
873 */ 940 */
874 switch (phy_info->negotiated_link_rate) { 941 switch (phy_info->negotiated_link_rate) {
875 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED: 942 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
876 port->negotiated_linkrate = SAS_PHY_DISABLED; 943 phy->negotiated_linkrate = SAS_PHY_DISABLED;
877 break; 944 break;
878 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION: 945 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
879 port->negotiated_linkrate = SAS_LINK_RATE_FAILED; 946 phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
880 break; 947 break;
881 case MPI_SAS_IOUNIT0_RATE_1_5: 948 case MPI_SAS_IOUNIT0_RATE_1_5:
882 port->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS; 949 phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
883 break; 950 break;
884 case MPI_SAS_IOUNIT0_RATE_3_0: 951 case MPI_SAS_IOUNIT0_RATE_3_0:
885 port->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS; 952 phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
886 break; 953 break;
887 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE: 954 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
888 case MPI_SAS_IOUNIT0_RATE_UNKNOWN: 955 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
889 default: 956 default:
890 port->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN; 957 phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
891 break; 958 break;
892 } 959 }
893 960
@@ -896,10 +963,10 @@ static int mptsas_probe_one_phy(struct device *dev,
896 */ 963 */
897 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) { 964 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
898 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5: 965 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
899 port->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS; 966 phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
900 break; 967 break;
901 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0: 968 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
902 port->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS; 969 phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
903 break; 970 break;
904 default: 971 default:
905 break; 972 break;
@@ -911,10 +978,10 @@ static int mptsas_probe_one_phy(struct device *dev,
911 switch (phy_info->programmed_link_rate & 978 switch (phy_info->programmed_link_rate &
912 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) { 979 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
913 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5: 980 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
914 port->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS; 981 phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
915 break; 982 break;
916 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0: 983 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
917 port->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS; 984 phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
918 break; 985 break;
919 default: 986 default:
920 break; 987 break;
@@ -925,10 +992,10 @@ static int mptsas_probe_one_phy(struct device *dev,
925 */ 992 */
926 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) { 993 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
927 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5: 994 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
928 port->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS; 995 phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
929 break; 996 break;
930 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0: 997 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
931 port->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS; 998 phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
932 break; 999 break;
933 default: 1000 default:
934 break; 1001 break;
@@ -940,28 +1007,29 @@ static int mptsas_probe_one_phy(struct device *dev,
940 switch (phy_info->programmed_link_rate & 1007 switch (phy_info->programmed_link_rate &
941 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) { 1008 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
942 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5: 1009 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
943 port->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS; 1010 phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
944 break; 1011 break;
945 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0: 1012 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
946 port->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS; 1013 phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
947 break; 1014 break;
948 default: 1015 default:
949 break; 1016 break;
950 } 1017 }
951 1018
952 if (local) 1019 if (local)
953 port->local_attached = 1; 1020 phy->local_attached = 1;
954 1021
955 error = sas_phy_add(port); 1022 error = sas_phy_add(phy);
956 if (error) { 1023 if (error) {
957 sas_phy_free(port); 1024 sas_phy_free(phy);
958 return error; 1025 return error;
959 } 1026 }
1027 phy_info->phy = phy;
960 1028
961 if (phy_info->attached.handle) { 1029 if (phy_info->attached.handle) {
962 struct sas_rphy *rphy; 1030 struct sas_rphy *rphy;
963 1031
964 rphy = sas_rphy_alloc(port); 1032 rphy = sas_rphy_alloc(phy);
965 if (!rphy) 1033 if (!rphy)
966 return 0; /* non-fatal: an rphy can be added later */ 1034 return 0; /* non-fatal: an rphy can be added later */
967 1035
@@ -985,16 +1053,19 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index)
985 u32 handle = 0xFFFF; 1053 u32 handle = 0xFFFF;
986 int error = -ENOMEM, i; 1054 int error = -ENOMEM, i;
987 1055
988 port_info = kmalloc(sizeof(*port_info), GFP_KERNEL); 1056 port_info = kzalloc(sizeof(*port_info), GFP_KERNEL);
989 if (!port_info) 1057 if (!port_info)
990 goto out; 1058 goto out;
991 memset(port_info, 0, sizeof(*port_info));
992 1059
993 error = mptsas_sas_io_unit_pg0(ioc, port_info); 1060 error = mptsas_sas_io_unit_pg0(ioc, port_info);
994 if (error) 1061 if (error)
995 goto out_free_port_info; 1062 goto out_free_port_info;
996 1063
1064 ioc->num_ports = port_info->num_phys;
1065 mutex_lock(&ioc->sas_topology_mutex);
997 list_add_tail(&port_info->list, &ioc->sas_topology); 1066 list_add_tail(&port_info->list, &ioc->sas_topology);
1067 mutex_unlock(&ioc->sas_topology_mutex);
1068
998 for (i = 0; i < port_info->num_phys; i++) { 1069 for (i = 0; i < port_info->num_phys; i++) {
999 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i], 1070 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
1000 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER << 1071 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
@@ -1034,10 +1105,9 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
1034 struct mptsas_portinfo *port_info, *p; 1105 struct mptsas_portinfo *port_info, *p;
1035 int error = -ENOMEM, i, j; 1106 int error = -ENOMEM, i, j;
1036 1107
1037 port_info = kmalloc(sizeof(*port_info), GFP_KERNEL); 1108 port_info = kzalloc(sizeof(*port_info), GFP_KERNEL);
1038 if (!port_info) 1109 if (!port_info)
1039 goto out; 1110 goto out;
1040 memset(port_info, 0, sizeof(*port_info));
1041 1111
1042 error = mptsas_sas_expander_pg0(ioc, port_info, 1112 error = mptsas_sas_expander_pg0(ioc, port_info,
1043 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE << 1113 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
@@ -1047,7 +1117,10 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
1047 1117
1048 *handle = port_info->handle; 1118 *handle = port_info->handle;
1049 1119
1120 mutex_lock(&ioc->sas_topology_mutex);
1050 list_add_tail(&port_info->list, &ioc->sas_topology); 1121 list_add_tail(&port_info->list, &ioc->sas_topology);
1122 mutex_unlock(&ioc->sas_topology_mutex);
1123
1051 for (i = 0; i < port_info->num_phys; i++) { 1124 for (i = 0; i < port_info->num_phys; i++) {
1052 struct device *parent; 1125 struct device *parent;
1053 1126
@@ -1079,6 +1152,7 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
1079 * HBA phys. 1152 * HBA phys.
1080 */ 1153 */
1081 parent = &ioc->sh->shost_gendev; 1154 parent = &ioc->sh->shost_gendev;
1155 mutex_lock(&ioc->sas_topology_mutex);
1082 list_for_each_entry(p, &ioc->sas_topology, list) { 1156 list_for_each_entry(p, &ioc->sas_topology, list) {
1083 for (j = 0; j < p->num_phys; j++) { 1157 for (j = 0; j < p->num_phys; j++) {
1084 if (port_info->phy_info[i].identify.handle == 1158 if (port_info->phy_info[i].identify.handle ==
@@ -1086,6 +1160,7 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
1086 parent = &p->phy_info[j].rphy->dev; 1160 parent = &p->phy_info[j].rphy->dev;
1087 } 1161 }
1088 } 1162 }
1163 mutex_unlock(&ioc->sas_topology_mutex);
1089 1164
1090 mptsas_probe_one_phy(parent, &port_info->phy_info[i], 1165 mptsas_probe_one_phy(parent, &port_info->phy_info[i],
1091 *index, 0); 1166 *index, 0);
@@ -1111,6 +1186,211 @@ mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
1111 ; 1186 ;
1112} 1187}
1113 1188
1189static struct mptsas_phyinfo *
1190mptsas_find_phyinfo_by_parent(MPT_ADAPTER *ioc, u16 parent_handle, u8 phy_id)
1191{
1192 struct mptsas_portinfo *port_info;
1193 struct mptsas_devinfo device_info;
1194 struct mptsas_phyinfo *phy_info = NULL;
1195 int i, error;
1196
1197 /*
1198 * Retrieve the parent sas_address
1199 */
1200 error = mptsas_sas_device_pg0(ioc, &device_info,
1201 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1202 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1203 parent_handle);
1204 if (error) {
1205 printk("mptsas: failed to retrieve device page\n");
1206 return NULL;
1207 }
1208
1209 /*
1210 * The phy_info structures are never deallocated during lifetime of
1211 * a host, so the code below is safe without additional refcounting.
1212 */
1213 mutex_lock(&ioc->sas_topology_mutex);
1214 list_for_each_entry(port_info, &ioc->sas_topology, list) {
1215 for (i = 0; i < port_info->num_phys; i++) {
1216 if (port_info->phy_info[i].identify.sas_address ==
1217 device_info.sas_address &&
1218 port_info->phy_info[i].phy_id == phy_id) {
1219 phy_info = &port_info->phy_info[i];
1220 break;
1221 }
1222 }
1223 }
1224 mutex_unlock(&ioc->sas_topology_mutex);
1225
1226 return phy_info;
1227}
1228
1229static struct mptsas_phyinfo *
1230mptsas_find_phyinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
1231{
1232 struct mptsas_portinfo *port_info;
1233 struct mptsas_phyinfo *phy_info = NULL;
1234 int i;
1235
1236 /*
1237 * The phy_info structures are never deallocated during lifetime of
1238 * a host, so the code below is safe without additional refcounting.
1239 */
1240 mutex_lock(&ioc->sas_topology_mutex);
1241 list_for_each_entry(port_info, &ioc->sas_topology, list) {
1242 for (i = 0; i < port_info->num_phys; i++) {
1243 if (port_info->phy_info[i].attached.handle == handle) {
1244 phy_info = &port_info->phy_info[i];
1245 break;
1246 }
1247 }
1248 }
1249 mutex_unlock(&ioc->sas_topology_mutex);
1250
1251 return phy_info;
1252}
1253
1254static void
1255mptsas_hotplug_work(void *arg)
1256{
1257 struct mptsas_hotplug_event *ev = arg;
1258 MPT_ADAPTER *ioc = ev->ioc;
1259 struct mptsas_phyinfo *phy_info;
1260 struct sas_rphy *rphy;
1261 char *ds = NULL;
1262
1263 if (ev->device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1264 ds = "ssp";
1265 if (ev->device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
1266 ds = "stp";
1267 if (ev->device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1268 ds = "sata";
1269
1270 switch (ev->event_type) {
1271 case MPTSAS_DEL_DEVICE:
1272 printk(MYIOC_s_INFO_FMT
1273 "removing %s device, channel %d, id %d, phy %d\n",
1274 ioc->name, ds, ev->channel, ev->id, ev->phy_id);
1275
1276 phy_info = mptsas_find_phyinfo_by_handle(ioc, ev->handle);
1277 if (!phy_info) {
1278 printk("mptsas: remove event for non-existant PHY.\n");
1279 break;
1280 }
1281
1282 if (phy_info->rphy) {
1283 sas_rphy_delete(phy_info->rphy);
1284 phy_info->rphy = NULL;
1285 }
1286 break;
1287 case MPTSAS_ADD_DEVICE:
1288 printk(MYIOC_s_INFO_FMT
1289 "attaching %s device, channel %d, id %d, phy %d\n",
1290 ioc->name, ds, ev->channel, ev->id, ev->phy_id);
1291
1292 phy_info = mptsas_find_phyinfo_by_parent(ioc,
1293 ev->parent_handle, ev->phy_id);
1294 if (!phy_info) {
1295 printk("mptsas: add event for non-existant PHY.\n");
1296 break;
1297 }
1298
1299 if (phy_info->rphy) {
1300 printk("mptsas: trying to add existing device.\n");
1301 break;
1302 }
1303
1304 /* fill attached info */
1305 phy_info->attached.handle = ev->handle;
1306 phy_info->attached.phy_id = ev->phy_id;
1307 phy_info->attached.port_id = phy_info->identify.port_id;
1308 phy_info->attached.id = ev->id;
1309 phy_info->attached.channel = ev->channel;
1310 phy_info->attached.sas_address = ev->sas_address;
1311 phy_info->attached.device_info = ev->device_info;
1312
1313 rphy = sas_rphy_alloc(phy_info->phy);
1314 if (!rphy)
1315 break; /* non-fatal: an rphy can be added later */
1316
1317 mptsas_parse_device_info(&rphy->identify, &phy_info->attached);
1318 if (sas_rphy_add(rphy)) {
1319 sas_rphy_free(rphy);
1320 break;
1321 }
1322
1323 phy_info->rphy = rphy;
1324 break;
1325 }
1326
1327 kfree(ev);
1328}
1329
1330static void
1331mptscsih_send_sas_event(MPT_ADAPTER *ioc,
1332 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
1333{
1334 struct mptsas_hotplug_event *ev;
1335 u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
1336 __le64 sas_address;
1337
1338 if ((device_info &
1339 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
1340 MPI_SAS_DEVICE_INFO_STP_TARGET |
1341 MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)
1342 return;
1343
1344 if ((sas_event_data->ReasonCode &
1345 (MPI_EVENT_SAS_DEV_STAT_RC_ADDED |
1346 MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING)) == 0)
1347 return;
1348
1349 ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
1350 if (!ev) {
1351 printk(KERN_WARNING "mptsas: lost hotplug event\n");
1352 return;
1353 }
1354
1355
1356 INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
1357 ev->ioc = ioc;
1358 ev->handle = le16_to_cpu(sas_event_data->DevHandle);
1359 ev->parent_handle = le16_to_cpu(sas_event_data->ParentDevHandle);
1360 ev->channel = sas_event_data->Bus;
1361 ev->id = sas_event_data->TargetID;
1362 ev->phy_id = sas_event_data->PhyNum;
1363 memcpy(&sas_address, &sas_event_data->SASAddress, sizeof(__le64));
1364 ev->sas_address = le64_to_cpu(sas_address);
1365 ev->device_info = device_info;
1366
1367 if (sas_event_data->ReasonCode & MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
1368 ev->event_type = MPTSAS_ADD_DEVICE;
1369 else
1370 ev->event_type = MPTSAS_DEL_DEVICE;
1371
1372 schedule_work(&ev->work);
1373}
1374
1375static int
1376mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
1377{
1378 u8 event = le32_to_cpu(reply->Event) & 0xFF;
1379
1380 if (!ioc->sh)
1381 return 1;
1382
1383 switch (event) {
1384 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
1385 mptscsih_send_sas_event(ioc,
1386 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
1387 return 1; /* currently means nothing really */
1388
1389 default:
1390 return mptscsih_event_process(ioc, reply);
1391 }
1392}
1393
1114static int 1394static int
1115mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) 1395mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1116{ 1396{
@@ -1118,11 +1398,10 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1118 MPT_SCSI_HOST *hd; 1398 MPT_SCSI_HOST *hd;
1119 MPT_ADAPTER *ioc; 1399 MPT_ADAPTER *ioc;
1120 unsigned long flags; 1400 unsigned long flags;
1121 int sz, ii; 1401 int ii;
1122 int numSGE = 0; 1402 int numSGE = 0;
1123 int scale; 1403 int scale;
1124 int ioc_cap; 1404 int ioc_cap;
1125 u8 *mem;
1126 int error=0; 1405 int error=0;
1127 int r; 1406 int r;
1128 1407
@@ -1203,7 +1482,9 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1203 sh->unique_id = ioc->id; 1482 sh->unique_id = ioc->id;
1204 1483
1205 INIT_LIST_HEAD(&ioc->sas_topology); 1484 INIT_LIST_HEAD(&ioc->sas_topology);
1206 init_MUTEX(&ioc->sas_mgmt.mutex); 1485 mutex_init(&ioc->sas_topology_mutex);
1486
1487 mutex_init(&ioc->sas_mgmt.mutex);
1207 init_completion(&ioc->sas_mgmt.done); 1488 init_completion(&ioc->sas_mgmt.done);
1208 1489
1209 /* Verify that we won't exceed the maximum 1490 /* Verify that we won't exceed the maximum
@@ -1244,36 +1525,27 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1244 /* SCSI needs scsi_cmnd lookup table! 1525 /* SCSI needs scsi_cmnd lookup table!
1245 * (with size equal to req_depth*PtrSz!) 1526 * (with size equal to req_depth*PtrSz!)
1246 */ 1527 */
1247 sz = ioc->req_depth * sizeof(void *); 1528 hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
1248 mem = kmalloc(sz, GFP_ATOMIC); 1529 if (!hd->ScsiLookup) {
1249 if (mem == NULL) {
1250 error = -ENOMEM; 1530 error = -ENOMEM;
1251 goto out_mptsas_probe; 1531 goto out_mptsas_probe;
1252 } 1532 }
1253 1533
1254 memset(mem, 0, sz); 1534 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
1255 hd->ScsiLookup = (struct scsi_cmnd **) mem; 1535 ioc->name, hd->ScsiLookup));
1256
1257 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
1258 ioc->name, hd->ScsiLookup, sz));
1259 1536
1260 /* Allocate memory for the device structures. 1537 /* Allocate memory for the device structures.
1261 * A non-Null pointer at an offset 1538 * A non-Null pointer at an offset
1262 * indicates a device exists. 1539 * indicates a device exists.
1263 * max_id = 1 + maximum id (hosts.h) 1540 * max_id = 1 + maximum id (hosts.h)
1264 */ 1541 */
1265 sz = sh->max_id * sizeof(void *); 1542 hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
1266 mem = kmalloc(sz, GFP_ATOMIC); 1543 if (!hd->Targets) {
1267 if (mem == NULL) {
1268 error = -ENOMEM; 1544 error = -ENOMEM;
1269 goto out_mptsas_probe; 1545 goto out_mptsas_probe;
1270 } 1546 }
1271 1547
1272 memset(mem, 0, sz); 1548 dprintk((KERN_INFO " vtarget @ %p\n", hd->Targets));
1273 hd->Targets = (VirtTarget **) mem;
1274
1275 dprintk((KERN_INFO
1276 " vtarget @ %p, sz=%d\n", hd->Targets, sz));
1277 1549
1278 /* Clear the TM flags 1550 /* Clear the TM flags
1279 */ 1551 */
@@ -1324,6 +1596,20 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1324 1596
1325 mptsas_scan_sas_topology(ioc); 1597 mptsas_scan_sas_topology(ioc);
1326 1598
1599 /*
1600 Reporting RAID volumes.
1601 */
1602 if (!ioc->raid_data.pIocPg2)
1603 return 0;
1604 if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
1605 return 0;
1606 for (ii=0;ii<ioc->raid_data.pIocPg2->NumActiveVolumes;ii++) {
1607 scsi_add_device(sh,
1608 ioc->num_ports,
1609 ioc->raid_data.pIocPg2->RaidVolume[ii].VolumeID,
1610 0);
1611 }
1612
1327 return 0; 1613 return 0;
1328 1614
1329out_mptsas_probe: 1615out_mptsas_probe:
@@ -1339,10 +1625,12 @@ static void __devexit mptsas_remove(struct pci_dev *pdev)
1339 1625
1340 sas_remove_host(ioc->sh); 1626 sas_remove_host(ioc->sh);
1341 1627
1628 mutex_lock(&ioc->sas_topology_mutex);
1342 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) { 1629 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
1343 list_del(&p->list); 1630 list_del(&p->list);
1344 kfree(p); 1631 kfree(p);
1345 } 1632 }
1633 mutex_unlock(&ioc->sas_topology_mutex);
1346 1634
1347 mptscsih_remove(pdev); 1635 mptscsih_remove(pdev);
1348} 1636}
@@ -1393,7 +1681,7 @@ mptsas_init(void)
1393 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER); 1681 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
1394 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER); 1682 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
1395 1683
1396 if (mpt_event_register(mptsasDoneCtx, mptscsih_event_process) == 0) { 1684 if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) {
1397 devtprintk((KERN_INFO MYNAM 1685 devtprintk((KERN_INFO MYNAM
1398 ": Registered for IOC event notifications\n")); 1686 ": Registered for IOC event notifications\n"));
1399 } 1687 }
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 93a16fa3c4ba..cdac5578fdf2 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -893,6 +893,7 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
893 * when a lun is disable by mid-layer. 893 * when a lun is disable by mid-layer.
894 * Do NOT access the referenced scsi_cmnd structure or 894 * Do NOT access the referenced scsi_cmnd structure or
895 * members. Will cause either a paging or NULL ptr error. 895 * members. Will cause either a paging or NULL ptr error.
896 * (BUT, BUT, BUT, the code does reference it! - mdr)
896 * @hd: Pointer to a SCSI HOST structure 897 * @hd: Pointer to a SCSI HOST structure
897 * @vdevice: per device private data 898 * @vdevice: per device private data
898 * 899 *
@@ -2162,10 +2163,9 @@ mptscsih_target_alloc(struct scsi_target *starget)
2162{ 2163{
2163 VirtTarget *vtarget; 2164 VirtTarget *vtarget;
2164 2165
2165 vtarget = kmalloc(sizeof(VirtTarget), GFP_KERNEL); 2166 vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
2166 if (!vtarget) 2167 if (!vtarget)
2167 return -ENOMEM; 2168 return -ENOMEM;
2168 memset(vtarget, 0, sizeof(VirtTarget));
2169 starget->hostdata = vtarget; 2169 starget->hostdata = vtarget;
2170 return 0; 2170 return 0;
2171} 2171}
@@ -2185,14 +2185,13 @@ mptscsih_slave_alloc(struct scsi_device *sdev)
2185 VirtDevice *vdev; 2185 VirtDevice *vdev;
2186 struct scsi_target *starget; 2186 struct scsi_target *starget;
2187 2187
2188 vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL); 2188 vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
2189 if (!vdev) { 2189 if (!vdev) {
2190 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n", 2190 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
2191 hd->ioc->name, sizeof(VirtDevice)); 2191 hd->ioc->name, sizeof(VirtDevice));
2192 return -ENOMEM; 2192 return -ENOMEM;
2193 } 2193 }
2194 2194
2195 memset(vdev, 0, sizeof(VirtDevice));
2196 vdev->ioc_id = hd->ioc->id; 2195 vdev->ioc_id = hd->ioc->id;
2197 vdev->target_id = sdev->id; 2196 vdev->target_id = sdev->id;
2198 vdev->bus_id = sdev->channel; 2197 vdev->bus_id = sdev->channel;
@@ -2559,13 +2558,25 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
2559 hd->cmdPtr = NULL; 2558 hd->cmdPtr = NULL;
2560 } 2559 }
2561 2560
2562 /* 7. Set flag to force DV and re-read IOC Page 3 2561 /* 7. SPI: Set flag to force DV and re-read IOC Page 3
2563 */ 2562 */
2564 if (ioc->bus_type == SPI) { 2563 if (ioc->bus_type == SPI) {
2565 ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3; 2564 ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
2566 ddvtprintk(("Set reload IOC Pg3 Flag\n")); 2565 ddvtprintk(("Set reload IOC Pg3 Flag\n"));
2567 } 2566 }
2568 2567
2568 /* 7. FC: Rescan for blocked rports which might have returned.
2569 */
2570 else if (ioc->bus_type == FC) {
2571 int work_count;
2572 unsigned long flags;
2573
2574 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
2575 work_count = ++ioc->fc_rescan_work_count;
2576 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
2577 if (work_count == 1)
2578 schedule_work(&ioc->fc_rescan_work);
2579 }
2569 dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name)); 2580 dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
2570 2581
2571 } 2582 }
@@ -2589,6 +2600,8 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
2589{ 2600{
2590 MPT_SCSI_HOST *hd; 2601 MPT_SCSI_HOST *hd;
2591 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF; 2602 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
2603 int work_count;
2604 unsigned long flags;
2592 2605
2593 devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", 2606 devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
2594 ioc->name, event)); 2607 ioc->name, event));
@@ -2610,11 +2623,18 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
2610 /* FIXME! */ 2623 /* FIXME! */
2611 break; 2624 break;
2612 2625
2626 case MPI_EVENT_RESCAN: /* 06 */
2627 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
2628 work_count = ++ioc->fc_rescan_work_count;
2629 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
2630 if (work_count == 1)
2631 schedule_work(&ioc->fc_rescan_work);
2632 break;
2633
2613 /* 2634 /*
2614 * CHECKME! Don't think we need to do 2635 * CHECKME! Don't think we need to do
2615 * anything for these, but... 2636 * anything for these, but...
2616 */ 2637 */
2617 case MPI_EVENT_RESCAN: /* 06 */
2618 case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */ 2638 case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */
2619 case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */ 2639 case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */
2620 /* 2640 /*
@@ -3954,8 +3974,6 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
3954 3974
3955/* Search IOC page 3 to determine if this is hidden physical disk 3975/* Search IOC page 3 to determine if this is hidden physical disk
3956 */ 3976 */
3957/* Search IOC page 3 to determine if this is hidden physical disk
3958 */
3959static int 3977static int
3960mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id) 3978mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
3961{ 3979{
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index ce332a6085e5..7dce29277cb7 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -158,11 +158,10 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
158 MPT_SCSI_HOST *hd; 158 MPT_SCSI_HOST *hd;
159 MPT_ADAPTER *ioc; 159 MPT_ADAPTER *ioc;
160 unsigned long flags; 160 unsigned long flags;
161 int sz, ii; 161 int ii;
162 int numSGE = 0; 162 int numSGE = 0;
163 int scale; 163 int scale;
164 int ioc_cap; 164 int ioc_cap;
165 u8 *mem;
166 int error=0; 165 int error=0;
167 int r; 166 int r;
168 167
@@ -288,36 +287,27 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
288 /* SCSI needs scsi_cmnd lookup table! 287 /* SCSI needs scsi_cmnd lookup table!
289 * (with size equal to req_depth*PtrSz!) 288 * (with size equal to req_depth*PtrSz!)
290 */ 289 */
291 sz = ioc->req_depth * sizeof(void *); 290 hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
292 mem = kmalloc(sz, GFP_ATOMIC); 291 if (!hd->ScsiLookup) {
293 if (mem == NULL) {
294 error = -ENOMEM; 292 error = -ENOMEM;
295 goto out_mptspi_probe; 293 goto out_mptspi_probe;
296 } 294 }
297 295
298 memset(mem, 0, sz); 296 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
299 hd->ScsiLookup = (struct scsi_cmnd **) mem; 297 ioc->name, hd->ScsiLookup));
300
301 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
302 ioc->name, hd->ScsiLookup, sz));
303 298
304 /* Allocate memory for the device structures. 299 /* Allocate memory for the device structures.
305 * A non-Null pointer at an offset 300 * A non-Null pointer at an offset
306 * indicates a device exists. 301 * indicates a device exists.
307 * max_id = 1 + maximum id (hosts.h) 302 * max_id = 1 + maximum id (hosts.h)
308 */ 303 */
309 sz = sh->max_id * sizeof(void *); 304 hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
310 mem = kmalloc(sz, GFP_ATOMIC); 305 if (!hd->Targets) {
311 if (mem == NULL) {
312 error = -ENOMEM; 306 error = -ENOMEM;
313 goto out_mptspi_probe; 307 goto out_mptspi_probe;
314 } 308 }
315 309
316 memset(mem, 0, sz); 310 dprintk((KERN_INFO " vdev @ %p\n", hd->Targets));
317 hd->Targets = (VirtTarget **) mem;
318
319 dprintk((KERN_INFO
320 " vdev @ %p, sz=%d\n", hd->Targets, sz));
321 311
322 /* Clear the TM flags 312 /* Clear the TM flags
323 */ 313 */
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c
index c5b656cdea7c..d698d7709c31 100644
--- a/drivers/message/i2o/pci.c
+++ b/drivers/message/i2o/pci.c
@@ -88,11 +88,6 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c)
88 struct device *dev = &pdev->dev; 88 struct device *dev = &pdev->dev;
89 int i; 89 int i;
90 90
91 if (pci_request_regions(pdev, OSM_DESCRIPTION)) {
92 printk(KERN_ERR "%s: device already claimed\n", c->name);
93 return -ENODEV;
94 }
95
96 for (i = 0; i < 6; i++) { 91 for (i = 0; i < 6; i++) {
97 /* Skip I/O spaces */ 92 /* Skip I/O spaces */
98 if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO)) { 93 if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO)) {
@@ -319,6 +314,11 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
319 return rc; 314 return rc;
320 } 315 }
321 316
317 if (pci_request_regions(pdev, OSM_DESCRIPTION)) {
318 printk(KERN_ERR "i2o: device already claimed\n");
319 return -ENODEV;
320 }
321
322 if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { 322 if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
323 printk(KERN_WARNING "i2o: no suitable DMA found for %s\n", 323 printk(KERN_WARNING "i2o: no suitable DMA found for %s\n",
324 pci_name(pdev)); 324 pci_name(pdev));
diff --git a/drivers/mfd/mcp-core.c b/drivers/mfd/mcp-core.c
index 55ba23075c90..75f401d52fda 100644
--- a/drivers/mfd/mcp-core.c
+++ b/drivers/mfd/mcp-core.c
@@ -77,6 +77,8 @@ static int mcp_bus_resume(struct device *dev)
77static struct bus_type mcp_bus_type = { 77static struct bus_type mcp_bus_type = {
78 .name = "mcp", 78 .name = "mcp",
79 .match = mcp_bus_match, 79 .match = mcp_bus_match,
80 .probe = mcp_bus_probe,
81 .remove = mcp_bus_remove,
80 .suspend = mcp_bus_suspend, 82 .suspend = mcp_bus_suspend,
81 .resume = mcp_bus_resume, 83 .resume = mcp_bus_resume,
82}; 84};
@@ -227,8 +229,6 @@ EXPORT_SYMBOL(mcp_host_unregister);
227int mcp_driver_register(struct mcp_driver *mcpdrv) 229int mcp_driver_register(struct mcp_driver *mcpdrv)
228{ 230{
229 mcpdrv->drv.bus = &mcp_bus_type; 231 mcpdrv->drv.bus = &mcp_bus_type;
230 mcpdrv->drv.probe = mcp_bus_probe;
231 mcpdrv->drv.remove = mcp_bus_remove;
232 return driver_register(&mcpdrv->drv); 232 return driver_register(&mcpdrv->drv);
233} 233}
234EXPORT_SYMBOL(mcp_driver_register); 234EXPORT_SYMBOL(mcp_driver_register);
diff --git a/drivers/mmc/mmc_sysfs.c b/drivers/mmc/mmc_sysfs.c
index ec701667abfc..a2a35fd946ee 100644
--- a/drivers/mmc/mmc_sysfs.c
+++ b/drivers/mmc/mmc_sysfs.c
@@ -136,17 +136,7 @@ static int mmc_bus_resume(struct device *dev)
136 return ret; 136 return ret;
137} 137}
138 138
139static struct bus_type mmc_bus_type = { 139static int mmc_bus_probe(struct device *dev)
140 .name = "mmc",
141 .dev_attrs = mmc_dev_attrs,
142 .match = mmc_bus_match,
143 .uevent = mmc_bus_uevent,
144 .suspend = mmc_bus_suspend,
145 .resume = mmc_bus_resume,
146};
147
148
149static int mmc_drv_probe(struct device *dev)
150{ 140{
151 struct mmc_driver *drv = to_mmc_driver(dev->driver); 141 struct mmc_driver *drv = to_mmc_driver(dev->driver);
152 struct mmc_card *card = dev_to_mmc_card(dev); 142 struct mmc_card *card = dev_to_mmc_card(dev);
@@ -154,7 +144,7 @@ static int mmc_drv_probe(struct device *dev)
154 return drv->probe(card); 144 return drv->probe(card);
155} 145}
156 146
157static int mmc_drv_remove(struct device *dev) 147static int mmc_bus_remove(struct device *dev)
158{ 148{
159 struct mmc_driver *drv = to_mmc_driver(dev->driver); 149 struct mmc_driver *drv = to_mmc_driver(dev->driver);
160 struct mmc_card *card = dev_to_mmc_card(dev); 150 struct mmc_card *card = dev_to_mmc_card(dev);
@@ -164,6 +154,16 @@ static int mmc_drv_remove(struct device *dev)
164 return 0; 154 return 0;
165} 155}
166 156
157static struct bus_type mmc_bus_type = {
158 .name = "mmc",
159 .dev_attrs = mmc_dev_attrs,
160 .match = mmc_bus_match,
161 .uevent = mmc_bus_uevent,
162 .probe = mmc_bus_probe,
163 .remove = mmc_bus_remove,
164 .suspend = mmc_bus_suspend,
165 .resume = mmc_bus_resume,
166};
167 167
168/** 168/**
169 * mmc_register_driver - register a media driver 169 * mmc_register_driver - register a media driver
@@ -172,8 +172,6 @@ static int mmc_drv_remove(struct device *dev)
172int mmc_register_driver(struct mmc_driver *drv) 172int mmc_register_driver(struct mmc_driver *drv)
173{ 173{
174 drv->drv.bus = &mmc_bus_type; 174 drv->drv.bus = &mmc_bus_type;
175 drv->drv.probe = mmc_drv_probe;
176 drv->drv.remove = mmc_drv_remove;
177 return driver_register(&drv->drv); 175 return driver_register(&drv->drv);
178} 176}
179 177
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 9a2aa4033c6a..5038e90ceb12 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -47,6 +47,22 @@ config MTD_MS02NV
47 accelerator. Say Y here if you have a DECstation 5000/2x0 or a 47 accelerator. Say Y here if you have a DECstation 5000/2x0 or a
48 DECsystem 5900 equipped with such a module. 48 DECsystem 5900 equipped with such a module.
49 49
50config MTD_DATAFLASH
51 tristate "Support for AT45xxx DataFlash"
52 depends on MTD && SPI_MASTER && EXPERIMENTAL
53 help
54 This enables access to AT45xxx DataFlash chips, using SPI.
55 Sometimes DataFlash chips are packaged inside MMC-format
56 cards; at this writing, the MMC stack won't handle those.
57
58config MTD_M25P80
59 tristate "Support for M25 SPI Flash"
60 depends on MTD && SPI_MASTER && EXPERIMENTAL
61 help
62 This enables access to ST M25P80 and similar SPI flash chips,
63 used for program and data storage. Set up your spi devices
64 with the right board-specific platform data.
65
50config MTD_SLRAM 66config MTD_SLRAM
51 tristate "Uncached system RAM" 67 tristate "Uncached system RAM"
52 depends on MTD 68 depends on MTD
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index e38db348057d..7c5ed2178380 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -23,3 +23,5 @@ obj-$(CONFIG_MTD_MTDRAM) += mtdram.o
23obj-$(CONFIG_MTD_LART) += lart.o 23obj-$(CONFIG_MTD_LART) += lart.o
24obj-$(CONFIG_MTD_BLKMTD) += blkmtd.o 24obj-$(CONFIG_MTD_BLKMTD) += blkmtd.o
25obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o 25obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o
26obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o
27obj-$(CONFIG_MTD_M25P80) += m25p80.o
diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c
index be5e88b3888d..e4345cf744a2 100644
--- a/drivers/mtd/devices/doc2000.c
+++ b/drivers/mtd/devices/doc2000.c
@@ -138,7 +138,7 @@ static inline int DoC_WaitReady(struct DiskOnChip *doc)
138 bypass the internal pipeline. Each of 4 delay cycles (read from the NOP register) is 138 bypass the internal pipeline. Each of 4 delay cycles (read from the NOP register) is
139 required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */ 139 required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */
140 140
141static inline int DoC_Command(struct DiskOnChip *doc, unsigned char command, 141static int DoC_Command(struct DiskOnChip *doc, unsigned char command,
142 unsigned char xtraflags) 142 unsigned char xtraflags)
143{ 143{
144 void __iomem *docptr = doc->virtadr; 144 void __iomem *docptr = doc->virtadr;
diff --git a/drivers/mtd/devices/doc2001.c b/drivers/mtd/devices/doc2001.c
index fcb28a6fd89f..681a9c73a2a3 100644
--- a/drivers/mtd/devices/doc2001.c
+++ b/drivers/mtd/devices/doc2001.c
@@ -103,7 +103,7 @@ static inline int DoC_WaitReady(void __iomem * docptr)
103 with the internal pipeline. Each of 4 delay cycles (read from the NOP register) is 103 with the internal pipeline. Each of 4 delay cycles (read from the NOP register) is
104 required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */ 104 required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */
105 105
106static inline void DoC_Command(void __iomem * docptr, unsigned char command, 106static void DoC_Command(void __iomem * docptr, unsigned char command,
107 unsigned char xtraflags) 107 unsigned char xtraflags)
108{ 108{
109 /* Assert the CLE (Command Latch Enable) line to the flash chip */ 109 /* Assert the CLE (Command Latch Enable) line to the flash chip */
diff --git a/drivers/mtd/devices/doc2001plus.c b/drivers/mtd/devices/doc2001plus.c
index 0595cc7324b2..5f57f29efee4 100644
--- a/drivers/mtd/devices/doc2001plus.c
+++ b/drivers/mtd/devices/doc2001plus.c
@@ -118,7 +118,7 @@ static inline void DoC_CheckASIC(void __iomem * docptr)
118/* DoC_Command: Send a flash command to the flash chip through the Flash 118/* DoC_Command: Send a flash command to the flash chip through the Flash
119 * command register. Need 2 Write Pipeline Terminates to complete send. 119 * command register. Need 2 Write Pipeline Terminates to complete send.
120 */ 120 */
121static inline void DoC_Command(void __iomem * docptr, unsigned char command, 121static void DoC_Command(void __iomem * docptr, unsigned char command,
122 unsigned char xtraflags) 122 unsigned char xtraflags)
123{ 123{
124 WriteDOC(command, docptr, Mplus_FlashCmd); 124 WriteDOC(command, docptr, Mplus_FlashCmd);
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
new file mode 100644
index 000000000000..d5f24089be71
--- /dev/null
+++ b/drivers/mtd/devices/m25p80.c
@@ -0,0 +1,582 @@
1/*
2 * MTD SPI driver for ST M25Pxx flash chips
3 *
4 * Author: Mike Lavender, mike@steroidmicros.com
5 *
6 * Copyright (c) 2005, Intec Automation Inc.
7 *
8 * Some parts are based on lart.c by Abraham Van Der Merwe
9 *
10 * Cleaned up and generalized based on mtd_dataflash.c
11 *
12 * This code is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 *
16 */
17
18#include <linux/init.h>
19#include <linux/module.h>
20#include <linux/device.h>
21#include <linux/interrupt.h>
22#include <linux/interrupt.h>
23#include <linux/mtd/mtd.h>
24#include <linux/mtd/partitions.h>
25#include <linux/spi/spi.h>
26#include <linux/spi/flash.h>
27
28#include <asm/semaphore.h>
29
30
31/* NOTE: AT 25F and SST 25LF series are very similar,
32 * but commands for sector erase and chip id differ...
33 */
34
35#define FLASH_PAGESIZE 256
36
37/* Flash opcodes. */
38#define OPCODE_WREN 6 /* Write enable */
39#define OPCODE_RDSR 5 /* Read status register */
40#define OPCODE_READ 3 /* Read data bytes */
41#define OPCODE_PP 2 /* Page program */
42#define OPCODE_SE 0xd8 /* Sector erase */
43#define OPCODE_RES 0xab /* Read Electronic Signature */
44#define OPCODE_RDID 0x9f /* Read JEDEC ID */
45
46/* Status Register bits. */
47#define SR_WIP 1 /* Write in progress */
48#define SR_WEL 2 /* Write enable latch */
49#define SR_BP0 4 /* Block protect 0 */
50#define SR_BP1 8 /* Block protect 1 */
51#define SR_BP2 0x10 /* Block protect 2 */
52#define SR_SRWD 0x80 /* SR write protect */
53
54/* Define max times to check status register before we give up. */
55#define MAX_READY_WAIT_COUNT 100000
56
57
58#ifdef CONFIG_MTD_PARTITIONS
59#define mtd_has_partitions() (1)
60#else
61#define mtd_has_partitions() (0)
62#endif
63
64/****************************************************************************/
65
66struct m25p {
67 struct spi_device *spi;
68 struct semaphore lock;
69 struct mtd_info mtd;
70 unsigned partitioned;
71 u8 command[4];
72};
73
74static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd)
75{
76 return container_of(mtd, struct m25p, mtd);
77}
78
79/****************************************************************************/
80
81/*
82 * Internal helper functions
83 */
84
85/*
86 * Read the status register, returning its value in the location
87 * Return the status register value.
88 * Returns negative if error occurred.
89 */
90static int read_sr(struct m25p *flash)
91{
92 ssize_t retval;
93 u8 code = OPCODE_RDSR;
94 u8 val;
95
96 retval = spi_write_then_read(flash->spi, &code, 1, &val, 1);
97
98 if (retval < 0) {
99 dev_err(&flash->spi->dev, "error %d reading SR\n",
100 (int) retval);
101 return retval;
102 }
103
104 return val;
105}
106
107
108/*
109 * Set write enable latch with Write Enable command.
110 * Returns negative if error occurred.
111 */
112static inline int write_enable(struct m25p *flash)
113{
114 u8 code = OPCODE_WREN;
115
116 return spi_write_then_read(flash->spi, &code, 1, NULL, 0);
117}
118
119
120/*
121 * Service routine to read status register until ready, or timeout occurs.
122 * Returns non-zero if error.
123 */
124static int wait_till_ready(struct m25p *flash)
125{
126 int count;
127 int sr;
128
129 /* one chip guarantees max 5 msec wait here after page writes,
130 * but potentially three seconds (!) after page erase.
131 */
132 for (count = 0; count < MAX_READY_WAIT_COUNT; count++) {
133 if ((sr = read_sr(flash)) < 0)
134 break;
135 else if (!(sr & SR_WIP))
136 return 0;
137
138 /* REVISIT sometimes sleeping would be best */
139 }
140
141 return 1;
142}
143
144
145/*
146 * Erase one sector of flash memory at offset ``offset'' which is any
147 * address within the sector which should be erased.
148 *
149 * Returns 0 if successful, non-zero otherwise.
150 */
151static int erase_sector(struct m25p *flash, u32 offset)
152{
153 DEBUG(MTD_DEBUG_LEVEL3, "%s: %s at 0x%08x\n", flash->spi->dev.bus_id,
154 __FUNCTION__, offset);
155
156 /* Wait until finished previous write command. */
157 if (wait_till_ready(flash))
158 return 1;
159
160 /* Send write enable, then erase commands. */
161 write_enable(flash);
162
163 /* Set up command buffer. */
164 flash->command[0] = OPCODE_SE;
165 flash->command[1] = offset >> 16;
166 flash->command[2] = offset >> 8;
167 flash->command[3] = offset;
168
169 spi_write(flash->spi, flash->command, sizeof(flash->command));
170
171 return 0;
172}
173
174/****************************************************************************/
175
176/*
177 * MTD implementation
178 */
179
180/*
181 * Erase an address range on the flash chip. The address range may extend
182 * one or more erase sectors. Return an error is there is a problem erasing.
183 */
184static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
185{
186 struct m25p *flash = mtd_to_m25p(mtd);
187 u32 addr,len;
188
189 DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
190 flash->spi->dev.bus_id, __FUNCTION__, "at",
191 (u32)instr->addr, instr->len);
192
193 /* sanity checks */
194 if (instr->addr + instr->len > flash->mtd.size)
195 return -EINVAL;
196 if ((instr->addr % mtd->erasesize) != 0
197 || (instr->len % mtd->erasesize) != 0) {
198 return -EINVAL;
199 }
200
201 addr = instr->addr;
202 len = instr->len;
203
204 down(&flash->lock);
205
206 /* now erase those sectors */
207 while (len) {
208 if (erase_sector(flash, addr)) {
209 instr->state = MTD_ERASE_FAILED;
210 up(&flash->lock);
211 return -EIO;
212 }
213
214 addr += mtd->erasesize;
215 len -= mtd->erasesize;
216 }
217
218 up(&flash->lock);
219
220 instr->state = MTD_ERASE_DONE;
221 mtd_erase_callback(instr);
222
223 return 0;
224}
225
226/*
227 * Read an address range from the flash chip. The address range
228 * may be any size provided it is within the physical boundaries.
229 */
230static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
231 size_t *retlen, u_char *buf)
232{
233 struct m25p *flash = mtd_to_m25p(mtd);
234 struct spi_transfer t[2];
235 struct spi_message m;
236
237 DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
238 flash->spi->dev.bus_id, __FUNCTION__, "from",
239 (u32)from, len);
240
241 /* sanity checks */
242 if (!len)
243 return 0;
244
245 if (from + len > flash->mtd.size)
246 return -EINVAL;
247
248 spi_message_init(&m);
249 memset(t, 0, (sizeof t));
250
251 t[0].tx_buf = flash->command;
252 t[0].len = sizeof(flash->command);
253 spi_message_add_tail(&t[0], &m);
254
255 t[1].rx_buf = buf;
256 t[1].len = len;
257 spi_message_add_tail(&t[1], &m);
258
259 /* Byte count starts at zero. */
260 if (retlen)
261 *retlen = 0;
262
263 down(&flash->lock);
264
265 /* Wait till previous write/erase is done. */
266 if (wait_till_ready(flash)) {
267 /* REVISIT status return?? */
268 up(&flash->lock);
269 return 1;
270 }
271
272 /* NOTE: OPCODE_FAST_READ (if available) is faster... */
273
274 /* Set up the write data buffer. */
275 flash->command[0] = OPCODE_READ;
276 flash->command[1] = from >> 16;
277 flash->command[2] = from >> 8;
278 flash->command[3] = from;
279
280 spi_sync(flash->spi, &m);
281
282 *retlen = m.actual_length - sizeof(flash->command);
283
284 up(&flash->lock);
285
286 return 0;
287}
288
289/*
290 * Write an address range to the flash chip. Data must be written in
291 * FLASH_PAGESIZE chunks. The address range may be any size provided
292 * it is within the physical boundaries.
293 */
294static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
295 size_t *retlen, const u_char *buf)
296{
297 struct m25p *flash = mtd_to_m25p(mtd);
298 u32 page_offset, page_size;
299 struct spi_transfer t[2];
300 struct spi_message m;
301
302 DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
303 flash->spi->dev.bus_id, __FUNCTION__, "to",
304 (u32)to, len);
305
306 if (retlen)
307 *retlen = 0;
308
309 /* sanity checks */
310 if (!len)
311 return(0);
312
313 if (to + len > flash->mtd.size)
314 return -EINVAL;
315
316 spi_message_init(&m);
317 memset(t, 0, (sizeof t));
318
319 t[0].tx_buf = flash->command;
320 t[0].len = sizeof(flash->command);
321 spi_message_add_tail(&t[0], &m);
322
323 t[1].tx_buf = buf;
324 spi_message_add_tail(&t[1], &m);
325
326 down(&flash->lock);
327
328 /* Wait until finished previous write command. */
329 if (wait_till_ready(flash))
330 return 1;
331
332 write_enable(flash);
333
334 /* Set up the opcode in the write buffer. */
335 flash->command[0] = OPCODE_PP;
336 flash->command[1] = to >> 16;
337 flash->command[2] = to >> 8;
338 flash->command[3] = to;
339
340 /* what page do we start with? */
341 page_offset = to % FLASH_PAGESIZE;
342
343 /* do all the bytes fit onto one page? */
344 if (page_offset + len <= FLASH_PAGESIZE) {
345 t[1].len = len;
346
347 spi_sync(flash->spi, &m);
348
349 *retlen = m.actual_length - sizeof(flash->command);
350 } else {
351 u32 i;
352
353 /* the size of data remaining on the first page */
354 page_size = FLASH_PAGESIZE - page_offset;
355
356 t[1].len = page_size;
357 spi_sync(flash->spi, &m);
358
359 *retlen = m.actual_length - sizeof(flash->command);
360
361 /* write everything in PAGESIZE chunks */
362 for (i = page_size; i < len; i += page_size) {
363 page_size = len - i;
364 if (page_size > FLASH_PAGESIZE)
365 page_size = FLASH_PAGESIZE;
366
367 /* write the next page to flash */
368 flash->command[1] = (to + i) >> 16;
369 flash->command[2] = (to + i) >> 8;
370 flash->command[3] = (to + i);
371
372 t[1].tx_buf = buf + i;
373 t[1].len = page_size;
374
375 wait_till_ready(flash);
376
377 write_enable(flash);
378
379 spi_sync(flash->spi, &m);
380
381 if (retlen)
382 *retlen += m.actual_length
383 - sizeof(flash->command);
384 }
385 }
386
387 up(&flash->lock);
388
389 return 0;
390}
391
392
393/****************************************************************************/
394
395/*
396 * SPI device driver setup and teardown
397 */
398
399struct flash_info {
400 char *name;
401 u8 id;
402 u16 jedec_id;
403 unsigned sector_size;
404 unsigned n_sectors;
405};
406
407static struct flash_info __devinitdata m25p_data [] = {
408 /* REVISIT: fill in JEDEC ids, for parts that have them */
409 { "m25p05", 0x05, 0x0000, 32 * 1024, 2 },
410 { "m25p10", 0x10, 0x0000, 32 * 1024, 4 },
411 { "m25p20", 0x11, 0x0000, 64 * 1024, 4 },
412 { "m25p40", 0x12, 0x0000, 64 * 1024, 8 },
413 { "m25p80", 0x13, 0x0000, 64 * 1024, 16 },
414 { "m25p16", 0x14, 0x0000, 64 * 1024, 32 },
415 { "m25p32", 0x15, 0x0000, 64 * 1024, 64 },
416 { "m25p64", 0x16, 0x2017, 64 * 1024, 128 },
417};
418
419/*
420 * board specific setup should have ensured the SPI clock used here
421 * matches what the READ command supports, at least until this driver
422 * understands FAST_READ (for clocks over 25 MHz).
423 */
424static int __devinit m25p_probe(struct spi_device *spi)
425{
426 struct flash_platform_data *data;
427 struct m25p *flash;
428 struct flash_info *info;
429 unsigned i;
430
431 /* Platform data helps sort out which chip type we have, as
432 * well as how this board partitions it.
433 */
434 data = spi->dev.platform_data;
435 if (!data || !data->type) {
436 /* FIXME some chips can identify themselves with RES
437 * or JEDEC get-id commands. Try them ...
438 */
439 DEBUG(MTD_DEBUG_LEVEL1, "%s: no chip id\n",
440 flash->spi->dev.bus_id);
441 return -ENODEV;
442 }
443
444 for (i = 0, info = m25p_data; i < ARRAY_SIZE(m25p_data); i++, info++) {
445 if (strcmp(data->type, info->name) == 0)
446 break;
447 }
448 if (i == ARRAY_SIZE(m25p_data)) {
449 DEBUG(MTD_DEBUG_LEVEL1, "%s: unrecognized id %s\n",
450 flash->spi->dev.bus_id, data->type);
451 return -ENODEV;
452 }
453
454 flash = kzalloc(sizeof *flash, SLAB_KERNEL);
455 if (!flash)
456 return -ENOMEM;
457
458 flash->spi = spi;
459 init_MUTEX(&flash->lock);
460 dev_set_drvdata(&spi->dev, flash);
461
462 if (data->name)
463 flash->mtd.name = data->name;
464 else
465 flash->mtd.name = spi->dev.bus_id;
466
467 flash->mtd.type = MTD_NORFLASH;
468 flash->mtd.flags = MTD_CAP_NORFLASH;
469 flash->mtd.size = info->sector_size * info->n_sectors;
470 flash->mtd.erasesize = info->sector_size;
471 flash->mtd.erase = m25p80_erase;
472 flash->mtd.read = m25p80_read;
473 flash->mtd.write = m25p80_write;
474
475 dev_info(&spi->dev, "%s (%d Kbytes)\n", info->name,
476 flash->mtd.size / 1024);
477
478 DEBUG(MTD_DEBUG_LEVEL2,
479 "mtd .name = %s, .size = 0x%.8x (%uM) "
480 ".erasesize = 0x%.8x (%uK) .numeraseregions = %d\n",
481 flash->mtd.name,
482 flash->mtd.size, flash->mtd.size / (1024*1024),
483 flash->mtd.erasesize, flash->mtd.erasesize / 1024,
484 flash->mtd.numeraseregions);
485
486 if (flash->mtd.numeraseregions)
487 for (i = 0; i < flash->mtd.numeraseregions; i++)
488 DEBUG(MTD_DEBUG_LEVEL2,
489 "mtd.eraseregions[%d] = { .offset = 0x%.8x, "
490 ".erasesize = 0x%.8x (%uK), "
491 ".numblocks = %d }\n",
492 i, flash->mtd.eraseregions[i].offset,
493 flash->mtd.eraseregions[i].erasesize,
494 flash->mtd.eraseregions[i].erasesize / 1024,
495 flash->mtd.eraseregions[i].numblocks);
496
497
498 /* partitions should match sector boundaries; and it may be good to
499 * use readonly partitions for writeprotected sectors (BP2..BP0).
500 */
501 if (mtd_has_partitions()) {
502 struct mtd_partition *parts = NULL;
503 int nr_parts = 0;
504
505#ifdef CONFIG_MTD_CMDLINE_PARTS
506 static const char *part_probes[] = { "cmdlinepart", NULL, };
507
508 nr_parts = parse_mtd_partitions(&flash->mtd,
509 part_probes, &parts, 0);
510#endif
511
512 if (nr_parts <= 0 && data && data->parts) {
513 parts = data->parts;
514 nr_parts = data->nr_parts;
515 }
516
517 if (nr_parts > 0) {
518 for (i = 0; i < data->nr_parts; i++) {
519 DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
520 "{.name = %s, .offset = 0x%.8x, "
521 ".size = 0x%.8x (%uK) }\n",
522 i, data->parts[i].name,
523 data->parts[i].offset,
524 data->parts[i].size,
525 data->parts[i].size / 1024);
526 }
527 flash->partitioned = 1;
528 return add_mtd_partitions(&flash->mtd, parts, nr_parts);
529 }
530 } else if (data->nr_parts)
531 dev_warn(&spi->dev, "ignoring %d default partitions on %s\n",
532 data->nr_parts, data->name);
533
534 return add_mtd_device(&flash->mtd) == 1 ? -ENODEV : 0;
535}
536
537
538static int __devexit m25p_remove(struct spi_device *spi)
539{
540 struct m25p *flash = dev_get_drvdata(&spi->dev);
541 int status;
542
543 /* Clean up MTD stuff. */
544 if (mtd_has_partitions() && flash->partitioned)
545 status = del_mtd_partitions(&flash->mtd);
546 else
547 status = del_mtd_device(&flash->mtd);
548 if (status == 0)
549 kfree(flash);
550 return 0;
551}
552
553
554static struct spi_driver m25p80_driver = {
555 .driver = {
556 .name = "m25p80",
557 .bus = &spi_bus_type,
558 .owner = THIS_MODULE,
559 },
560 .probe = m25p_probe,
561 .remove = __devexit_p(m25p_remove),
562};
563
564
565static int m25p80_init(void)
566{
567 return spi_register_driver(&m25p80_driver);
568}
569
570
571static void m25p80_exit(void)
572{
573 spi_unregister_driver(&m25p80_driver);
574}
575
576
577module_init(m25p80_init);
578module_exit(m25p80_exit);
579
580MODULE_LICENSE("GPL");
581MODULE_AUTHOR("Mike Lavender");
582MODULE_DESCRIPTION("MTD SPI driver for ST M25Pxx flash chips");
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
new file mode 100644
index 000000000000..155737e7483f
--- /dev/null
+++ b/drivers/mtd/devices/mtd_dataflash.c
@@ -0,0 +1,629 @@
1/*
2 * Atmel AT45xxx DataFlash MTD driver for lightweight SPI framework
3 *
4 * Largely derived from at91_dataflash.c:
5 * Copyright (C) 2003-2005 SAN People (Pty) Ltd
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11*/
12#include <linux/config.h>
13#include <linux/module.h>
14#include <linux/init.h>
15#include <linux/slab.h>
16#include <linux/delay.h>
17#include <linux/device.h>
18#include <linux/spi/spi.h>
19#include <linux/spi/flash.h>
20
21#include <linux/mtd/mtd.h>
22#include <linux/mtd/partitions.h>
23
24
25/*
26 * DataFlash is a kind of SPI flash. Most AT45 chips have two buffers in
27 * each chip, which may be used for double buffered I/O; but this driver
28 * doesn't (yet) use these for any kind of i/o overlap or prefetching.
29 *
30 * Sometimes DataFlash is packaged in MMC-format cards, although the
31 * MMC stack can't use SPI (yet), or distinguish between MMC and DataFlash
32 * protocols during enumeration.
33 */
34
35#define CONFIG_DATAFLASH_WRITE_VERIFY
36
37/* reads can bypass the buffers */
38#define OP_READ_CONTINUOUS 0xE8
39#define OP_READ_PAGE 0xD2
40
41/* group B requests can run even while status reports "busy" */
42#define OP_READ_STATUS 0xD7 /* group B */
43
44/* move data between host and buffer */
45#define OP_READ_BUFFER1 0xD4 /* group B */
46#define OP_READ_BUFFER2 0xD6 /* group B */
47#define OP_WRITE_BUFFER1 0x84 /* group B */
48#define OP_WRITE_BUFFER2 0x87 /* group B */
49
50/* erasing flash */
51#define OP_ERASE_PAGE 0x81
52#define OP_ERASE_BLOCK 0x50
53
54/* move data between buffer and flash */
55#define OP_TRANSFER_BUF1 0x53
56#define OP_TRANSFER_BUF2 0x55
57#define OP_MREAD_BUFFER1 0xD4
58#define OP_MREAD_BUFFER2 0xD6
59#define OP_MWERASE_BUFFER1 0x83
60#define OP_MWERASE_BUFFER2 0x86
61#define OP_MWRITE_BUFFER1 0x88 /* sector must be pre-erased */
62#define OP_MWRITE_BUFFER2 0x89 /* sector must be pre-erased */
63
64/* write to buffer, then write-erase to flash */
65#define OP_PROGRAM_VIA_BUF1 0x82
66#define OP_PROGRAM_VIA_BUF2 0x85
67
68/* compare buffer to flash */
69#define OP_COMPARE_BUF1 0x60
70#define OP_COMPARE_BUF2 0x61
71
72/* read flash to buffer, then write-erase to flash */
73#define OP_REWRITE_VIA_BUF1 0x58
74#define OP_REWRITE_VIA_BUF2 0x59
75
76/* newer chips report JEDEC manufacturer and device IDs; chip
77 * serial number and OTP bits; and per-sector writeprotect.
78 */
79#define OP_READ_ID 0x9F
80#define OP_READ_SECURITY 0x77
81#define OP_WRITE_SECURITY 0x9A /* OTP bits */
82
83
84struct dataflash {
85 u8 command[4];
86 char name[24];
87
88 unsigned partitioned:1;
89
90 unsigned short page_offset; /* offset in flash address */
91 unsigned int page_size; /* of bytes per page */
92
93 struct semaphore lock;
94 struct spi_device *spi;
95
96 struct mtd_info mtd;
97};
98
99#ifdef CONFIG_MTD_PARTITIONS
100#define mtd_has_partitions() (1)
101#else
102#define mtd_has_partitions() (0)
103#endif
104
105/* ......................................................................... */
106
107/*
108 * Return the status of the DataFlash device.
109 */
110static inline int dataflash_status(struct spi_device *spi)
111{
112 /* NOTE: at45db321c over 25 MHz wants to write
113 * a dummy byte after the opcode...
114 */
115 return spi_w8r8(spi, OP_READ_STATUS);
116}
117
118/*
119 * Poll the DataFlash device until it is READY.
120 * This usually takes 5-20 msec or so; more for sector erase.
121 */
122static int dataflash_waitready(struct spi_device *spi)
123{
124 int status;
125
126 for (;;) {
127 status = dataflash_status(spi);
128 if (status < 0) {
129 DEBUG(MTD_DEBUG_LEVEL1, "%s: status %d?\n",
130 spi->dev.bus_id, status);
131 status = 0;
132 }
133
134 if (status & (1 << 7)) /* RDY/nBSY */
135 return status;
136
137 msleep(3);
138 }
139}
140
141/* ......................................................................... */
142
143/*
144 * Erase pages of flash.
145 */
146static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
147{
148 struct dataflash *priv = (struct dataflash *)mtd->priv;
149 struct spi_device *spi = priv->spi;
150 struct spi_transfer x = { .tx_dma = 0, };
151 struct spi_message msg;
152 unsigned blocksize = priv->page_size << 3;
153 u8 *command;
154
155 DEBUG(MTD_DEBUG_LEVEL2, "%s: erase addr=0x%x len 0x%x\n",
156 spi->dev.bus_id,
157 instr->addr, instr->len);
158
159 /* Sanity checks */
160 if ((instr->addr + instr->len) > mtd->size
161 || (instr->len % priv->page_size) != 0
162 || (instr->addr % priv->page_size) != 0)
163 return -EINVAL;
164
165 spi_message_init(&msg);
166
167 x.tx_buf = command = priv->command;
168 x.len = 4;
169 spi_message_add_tail(&x, &msg);
170
171 down(&priv->lock);
172 while (instr->len > 0) {
173 unsigned int pageaddr;
174 int status;
175 int do_block;
176
177 /* Calculate flash page address; use block erase (for speed) if
178 * we're at a block boundary and need to erase the whole block.
179 */
180 pageaddr = instr->addr / priv->page_size;
181 do_block = (pageaddr & 0x7) == 0 && instr->len <= blocksize;
182 pageaddr = pageaddr << priv->page_offset;
183
184 command[0] = do_block ? OP_ERASE_BLOCK : OP_ERASE_PAGE;
185 command[1] = (u8)(pageaddr >> 16);
186 command[2] = (u8)(pageaddr >> 8);
187 command[3] = 0;
188
189 DEBUG(MTD_DEBUG_LEVEL3, "ERASE %s: (%x) %x %x %x [%i]\n",
190 do_block ? "block" : "page",
191 command[0], command[1], command[2], command[3],
192 pageaddr);
193
194 status = spi_sync(spi, &msg);
195 (void) dataflash_waitready(spi);
196
197 if (status < 0) {
198 printk(KERN_ERR "%s: erase %x, err %d\n",
199 spi->dev.bus_id, pageaddr, status);
200 /* REVISIT: can retry instr->retries times; or
201 * giveup and instr->fail_addr = instr->addr;
202 */
203 continue;
204 }
205
206 if (do_block) {
207 instr->addr += blocksize;
208 instr->len -= blocksize;
209 } else {
210 instr->addr += priv->page_size;
211 instr->len -= priv->page_size;
212 }
213 }
214 up(&priv->lock);
215
216 /* Inform MTD subsystem that erase is complete */
217 instr->state = MTD_ERASE_DONE;
218 mtd_erase_callback(instr);
219
220 return 0;
221}
222
223/*
224 * Read from the DataFlash device.
225 * from : Start offset in flash device
226 * len : Amount to read
227 * retlen : About of data actually read
228 * buf : Buffer containing the data
229 */
230static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len,
231 size_t *retlen, u_char *buf)
232{
233 struct dataflash *priv = (struct dataflash *)mtd->priv;
234 struct spi_transfer x[2] = { { .tx_dma = 0, }, };
235 struct spi_message msg;
236 unsigned int addr;
237 u8 *command;
238 int status;
239
240 DEBUG(MTD_DEBUG_LEVEL2, "%s: read 0x%x..0x%x\n",
241 priv->spi->dev.bus_id, (unsigned)from, (unsigned)(from + len));
242
243 *retlen = 0;
244
245 /* Sanity checks */
246 if (!len)
247 return 0;
248 if (from + len > mtd->size)
249 return -EINVAL;
250
251 /* Calculate flash page/byte address */
252 addr = (((unsigned)from / priv->page_size) << priv->page_offset)
253 + ((unsigned)from % priv->page_size);
254
255 command = priv->command;
256
257 DEBUG(MTD_DEBUG_LEVEL3, "READ: (%x) %x %x %x\n",
258 command[0], command[1], command[2], command[3]);
259
260 spi_message_init(&msg);
261
262 x[0].tx_buf = command;
263 x[0].len = 8;
264 spi_message_add_tail(&x[0], &msg);
265
266 x[1].rx_buf = buf;
267 x[1].len = len;
268 spi_message_add_tail(&x[1], &msg);
269
270 down(&priv->lock);
271
272 /* Continuous read, max clock = f(car) which may be less than
273 * the peak rate available. Some chips support commands with
274 * fewer "don't care" bytes. Both buffers stay unchanged.
275 */
276 command[0] = OP_READ_CONTINUOUS;
277 command[1] = (u8)(addr >> 16);
278 command[2] = (u8)(addr >> 8);
279 command[3] = (u8)(addr >> 0);
280 /* plus 4 "don't care" bytes */
281
282 status = spi_sync(priv->spi, &msg);
283 up(&priv->lock);
284
285 if (status >= 0) {
286 *retlen = msg.actual_length - 8;
287 status = 0;
288 } else
289 DEBUG(MTD_DEBUG_LEVEL1, "%s: read %x..%x --> %d\n",
290 priv->spi->dev.bus_id,
291 (unsigned)from, (unsigned)(from + len),
292 status);
293 return status;
294}
295
296/*
297 * Write to the DataFlash device.
298 * to : Start offset in flash device
299 * len : Amount to write
300 * retlen : Amount of data actually written
301 * buf : Buffer containing the data
302 */
303static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
304 size_t * retlen, const u_char * buf)
305{
306 struct dataflash *priv = (struct dataflash *)mtd->priv;
307 struct spi_device *spi = priv->spi;
308 struct spi_transfer x[2] = { { .tx_dma = 0, }, };
309 struct spi_message msg;
310 unsigned int pageaddr, addr, offset, writelen;
311 size_t remaining = len;
312 u_char *writebuf = (u_char *) buf;
313 int status = -EINVAL;
314 u8 *command;
315
316 DEBUG(MTD_DEBUG_LEVEL2, "%s: write 0x%x..0x%x\n",
317 spi->dev.bus_id, (unsigned)to, (unsigned)(to + len));
318
319 *retlen = 0;
320
321 /* Sanity checks */
322 if (!len)
323 return 0;
324 if ((to + len) > mtd->size)
325 return -EINVAL;
326
327 spi_message_init(&msg);
328
329 x[0].tx_buf = command = priv->command;
330 x[0].len = 4;
331 spi_message_add_tail(&x[0], &msg);
332
333 pageaddr = ((unsigned)to / priv->page_size);
334 offset = ((unsigned)to % priv->page_size);
335 if (offset + len > priv->page_size)
336 writelen = priv->page_size - offset;
337 else
338 writelen = len;
339
340 down(&priv->lock);
341 while (remaining > 0) {
342 DEBUG(MTD_DEBUG_LEVEL3, "write @ %i:%i len=%i\n",
343 pageaddr, offset, writelen);
344
345 /* REVISIT:
346 * (a) each page in a sector must be rewritten at least
347 * once every 10K sibling erase/program operations.
348 * (b) for pages that are already erased, we could
349 * use WRITE+MWRITE not PROGRAM for ~30% speedup.
350 * (c) WRITE to buffer could be done while waiting for
351 * a previous MWRITE/MWERASE to complete ...
352 * (d) error handling here seems to be mostly missing.
353 *
354 * Two persistent bits per page, plus a per-sector counter,
355 * could support (a) and (b) ... we might consider using
356 * the second half of sector zero, which is just one block,
357 * to track that state. (On AT91, that sector should also
358 * support boot-from-DataFlash.)
359 */
360
361 addr = pageaddr << priv->page_offset;
362
363 /* (1) Maybe transfer partial page to Buffer1 */
364 if (writelen != priv->page_size) {
365 command[0] = OP_TRANSFER_BUF1;
366 command[1] = (addr & 0x00FF0000) >> 16;
367 command[2] = (addr & 0x0000FF00) >> 8;
368 command[3] = 0;
369
370 DEBUG(MTD_DEBUG_LEVEL3, "TRANSFER: (%x) %x %x %x\n",
371 command[0], command[1], command[2], command[3]);
372
373 status = spi_sync(spi, &msg);
374 if (status < 0)
375 DEBUG(MTD_DEBUG_LEVEL1, "%s: xfer %u -> %d \n",
376 spi->dev.bus_id, addr, status);
377
378 (void) dataflash_waitready(priv->spi);
379 }
380
381 /* (2) Program full page via Buffer1 */
382 addr += offset;
383 command[0] = OP_PROGRAM_VIA_BUF1;
384 command[1] = (addr & 0x00FF0000) >> 16;
385 command[2] = (addr & 0x0000FF00) >> 8;
386 command[3] = (addr & 0x000000FF);
387
388 DEBUG(MTD_DEBUG_LEVEL3, "PROGRAM: (%x) %x %x %x\n",
389 command[0], command[1], command[2], command[3]);
390
391 x[1].tx_buf = writebuf;
392 x[1].len = writelen;
393 spi_message_add_tail(x + 1, &msg);
394 status = spi_sync(spi, &msg);
395 spi_transfer_del(x + 1);
396 if (status < 0)
397 DEBUG(MTD_DEBUG_LEVEL1, "%s: pgm %u/%u -> %d \n",
398 spi->dev.bus_id, addr, writelen, status);
399
400 (void) dataflash_waitready(priv->spi);
401
402
403#ifdef CONFIG_DATAFLASH_WRITE_VERIFY
404
405 /* (3) Compare to Buffer1 */
406 addr = pageaddr << priv->page_offset;
407 command[0] = OP_COMPARE_BUF1;
408 command[1] = (addr & 0x00FF0000) >> 16;
409 command[2] = (addr & 0x0000FF00) >> 8;
410 command[3] = 0;
411
412 DEBUG(MTD_DEBUG_LEVEL3, "COMPARE: (%x) %x %x %x\n",
413 command[0], command[1], command[2], command[3]);
414
415 status = spi_sync(spi, &msg);
416 if (status < 0)
417 DEBUG(MTD_DEBUG_LEVEL1, "%s: compare %u -> %d \n",
418 spi->dev.bus_id, addr, status);
419
420 status = dataflash_waitready(priv->spi);
421
422 /* Check result of the compare operation */
423 if ((status & (1 << 6)) == 1) {
424 printk(KERN_ERR "%s: compare page %u, err %d\n",
425 spi->dev.bus_id, pageaddr, status);
426 remaining = 0;
427 status = -EIO;
428 break;
429 } else
430 status = 0;
431
432#endif /* CONFIG_DATAFLASH_WRITE_VERIFY */
433
434 remaining = remaining - writelen;
435 pageaddr++;
436 offset = 0;
437 writebuf += writelen;
438 *retlen += writelen;
439
440 if (remaining > priv->page_size)
441 writelen = priv->page_size;
442 else
443 writelen = remaining;
444 }
445 up(&priv->lock);
446
447 return status;
448}
449
450/* ......................................................................... */
451
452/*
453 * Register DataFlash device with MTD subsystem.
454 */
455static int __devinit
456add_dataflash(struct spi_device *spi, char *name,
457 int nr_pages, int pagesize, int pageoffset)
458{
459 struct dataflash *priv;
460 struct mtd_info *device;
461 struct flash_platform_data *pdata = spi->dev.platform_data;
462
463 priv = (struct dataflash *) kzalloc(sizeof *priv, GFP_KERNEL);
464 if (!priv)
465 return -ENOMEM;
466
467 init_MUTEX(&priv->lock);
468 priv->spi = spi;
469 priv->page_size = pagesize;
470 priv->page_offset = pageoffset;
471
472 /* name must be usable with cmdlinepart */
473 sprintf(priv->name, "spi%d.%d-%s",
474 spi->master->bus_num, spi->chip_select,
475 name);
476
477 device = &priv->mtd;
478 device->name = (pdata && pdata->name) ? pdata->name : priv->name;
479 device->size = nr_pages * pagesize;
480 device->erasesize = pagesize;
481 device->owner = THIS_MODULE;
482 device->type = MTD_DATAFLASH;
483 device->flags = MTD_CAP_NORFLASH;
484 device->erase = dataflash_erase;
485 device->read = dataflash_read;
486 device->write = dataflash_write;
487 device->priv = priv;
488
489 dev_info(&spi->dev, "%s (%d KBytes)\n", name, device->size/1024);
490 dev_set_drvdata(&spi->dev, priv);
491
492 if (mtd_has_partitions()) {
493 struct mtd_partition *parts;
494 int nr_parts = 0;
495
496#ifdef CONFIG_MTD_CMDLINE_PARTS
497 static const char *part_probes[] = { "cmdlinepart", NULL, };
498
499 nr_parts = parse_mtd_partitions(device, part_probes, &parts, 0);
500#endif
501
502 if (nr_parts <= 0 && pdata && pdata->parts) {
503 parts = pdata->parts;
504 nr_parts = pdata->nr_parts;
505 }
506
507 if (nr_parts > 0) {
508 priv->partitioned = 1;
509 return add_mtd_partitions(device, parts, nr_parts);
510 }
511 } else if (pdata && pdata->nr_parts)
512 dev_warn(&spi->dev, "ignoring %d default partitions on %s\n",
513 pdata->nr_parts, device->name);
514
515 return add_mtd_device(device) == 1 ? -ENODEV : 0;
516}
517
518/*
519 * Detect and initialize DataFlash device:
520 *
521 * Device Density ID code #Pages PageSize Offset
522 * AT45DB011B 1Mbit (128K) xx0011xx (0x0c) 512 264 9
523 * AT45DB021B 2Mbit (256K) xx0101xx (0x14) 1025 264 9
524 * AT45DB041B 4Mbit (512K) xx0111xx (0x1c) 2048 264 9
525 * AT45DB081B 8Mbit (1M) xx1001xx (0x24) 4096 264 9
526 * AT45DB0161B 16Mbit (2M) xx1011xx (0x2c) 4096 528 10
527 * AT45DB0321B 32Mbit (4M) xx1101xx (0x34) 8192 528 10
528 * AT45DB0642 64Mbit (8M) xx111xxx (0x3c) 8192 1056 11
529 * AT45DB1282 128Mbit (16M) xx0100xx (0x10) 16384 1056 11
530 */
531static int __devinit dataflash_probe(struct spi_device *spi)
532{
533 int status;
534
535 status = dataflash_status(spi);
536 if (status <= 0 || status == 0xff) {
537 DEBUG(MTD_DEBUG_LEVEL1, "%s: status error %d\n",
538 spi->dev.bus_id, status);
539 if (status == 0xff)
540 status = -ENODEV;
541 return status;
542 }
543
544 /* if there's a device there, assume it's dataflash.
545 * board setup should have set spi->max_speed_max to
546 * match f(car) for continuous reads, mode 0 or 3.
547 */
548 switch (status & 0x3c) {
549 case 0x0c: /* 0 0 1 1 x x */
550 status = add_dataflash(spi, "AT45DB011B", 512, 264, 9);
551 break;
552 case 0x14: /* 0 1 0 1 x x */
553 status = add_dataflash(spi, "AT45DB021B", 1025, 264, 9);
554 break;
555 case 0x1c: /* 0 1 1 1 x x */
556 status = add_dataflash(spi, "AT45DB041x", 2048, 264, 9);
557 break;
558 case 0x24: /* 1 0 0 1 x x */
559 status = add_dataflash(spi, "AT45DB081B", 4096, 264, 9);
560 break;
561 case 0x2c: /* 1 0 1 1 x x */
562 status = add_dataflash(spi, "AT45DB161x", 4096, 528, 10);
563 break;
564 case 0x34: /* 1 1 0 1 x x */
565 status = add_dataflash(spi, "AT45DB321x", 8192, 528, 10);
566 break;
567 case 0x38: /* 1 1 1 x x x */
568 case 0x3c:
569 status = add_dataflash(spi, "AT45DB642x", 8192, 1056, 11);
570 break;
571 /* obsolete AT45DB1282 not (yet?) supported */
572 default:
573 DEBUG(MTD_DEBUG_LEVEL1, "%s: unsupported device (%x)\n",
574 spi->dev.bus_id, status & 0x3c);
575 status = -ENODEV;
576 }
577
578 if (status < 0)
579 DEBUG(MTD_DEBUG_LEVEL1, "%s: add_dataflash --> %d\n",
580 spi->dev.bus_id, status);
581
582 return status;
583}
584
585static int __devexit dataflash_remove(struct spi_device *spi)
586{
587 struct dataflash *flash = dev_get_drvdata(&spi->dev);
588 int status;
589
590 DEBUG(MTD_DEBUG_LEVEL1, "%s: remove\n", spi->dev.bus_id);
591
592 if (mtd_has_partitions() && flash->partitioned)
593 status = del_mtd_partitions(&flash->mtd);
594 else
595 status = del_mtd_device(&flash->mtd);
596 if (status == 0)
597 kfree(flash);
598 return status;
599}
600
601static struct spi_driver dataflash_driver = {
602 .driver = {
603 .name = "mtd_dataflash",
604 .bus = &spi_bus_type,
605 .owner = THIS_MODULE,
606 },
607
608 .probe = dataflash_probe,
609 .remove = __devexit_p(dataflash_remove),
610
611 /* FIXME: investigate suspend and resume... */
612};
613
614static int __init dataflash_init(void)
615{
616 return spi_register_driver(&dataflash_driver);
617}
618module_init(dataflash_init);
619
620static void __exit dataflash_exit(void)
621{
622 spi_unregister_driver(&dataflash_driver);
623}
624module_exit(dataflash_exit);
625
626
627MODULE_LICENSE("GPL");
628MODULE_AUTHOR("Andrew Victor, David Brownell");
629MODULE_DESCRIPTION("MTD DataFlash driver");
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index 21d4e8f4b7af..ec5e45e4e4ef 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -1506,7 +1506,7 @@ static inline int __init doc2001plus_init(struct mtd_info *mtd)
1506 return 1; 1506 return 1;
1507} 1507}
1508 1508
1509static inline int __init doc_probe(unsigned long physadr) 1509static int __init doc_probe(unsigned long physadr)
1510{ 1510{
1511 unsigned char ChipID; 1511 unsigned char ChipID;
1512 struct mtd_info *mtd; 1512 struct mtd_info *mtd;
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 5c15f3e9ea07..171999e67eec 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1387,7 +1387,7 @@ config FORCEDETH
1387 1387
1388config CS89x0 1388config CS89x0
1389 tristate "CS89x0 support" 1389 tristate "CS89x0 support"
1390 depends on NET_PCI && (ISA || ARCH_IXDP2X01 || ARCH_PNX010X) 1390 depends on NET_PCI && (ISA || MACH_IXDP2351 || ARCH_IXDP2X01 || ARCH_PNX010X)
1391 ---help--- 1391 ---help---
1392 Support for CS89x0 chipset based Ethernet cards. If you have a 1392 Support for CS89x0 chipset based Ethernet cards. If you have a
1393 network (Ethernet) card of this type, say Y and read the 1393 network (Ethernet) card of this type, say Y and read the
diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c
index e2cfde7e31ec..fab6586d87e9 100644
--- a/drivers/net/cs89x0.c
+++ b/drivers/net/cs89x0.c
@@ -87,6 +87,12 @@
87 Deepak Saxena : dsaxena@plexity.net 87 Deepak Saxena : dsaxena@plexity.net
88 : Intel IXDP2x01 (XScale ixp2x00 NPU) platform support 88 : Intel IXDP2x01 (XScale ixp2x00 NPU) platform support
89 89
90 Dmitry Pervushin : dpervushin@ru.mvista.com
91 : PNX010X platform support
92
93 Deepak Saxena : dsaxena@plexity.net
94 : Intel IXDP2351 platform support
95
90*/ 96*/
91 97
92/* Always include 'config.h' first in case the user wants to turn on 98/* Always include 'config.h' first in case the user wants to turn on
@@ -171,6 +177,10 @@ static unsigned int cs8900_irq_map[] = {12,0,0,0};
171static unsigned int netcard_portlist[] __initdata = 177static unsigned int netcard_portlist[] __initdata =
172 { 0x0300, 0}; 178 { 0x0300, 0};
173static unsigned int cs8900_irq_map[] = {1,0,0,0}; 179static unsigned int cs8900_irq_map[] = {1,0,0,0};
180#elif defined(CONFIG_MACH_IXDP2351)
181static unsigned int netcard_portlist[] __initdata = {IXDP2351_VIRT_CS8900_BASE, 0};
182static unsigned int cs8900_irq_map[] = {IRQ_IXDP2351_CS8900, 0, 0, 0};
183#include <asm/irq.h>
174#elif defined(CONFIG_ARCH_IXDP2X01) 184#elif defined(CONFIG_ARCH_IXDP2X01)
175#include <asm/irq.h> 185#include <asm/irq.h>
176static unsigned int netcard_portlist[] __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0}; 186static unsigned int netcard_portlist[] __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0};
@@ -338,45 +348,55 @@ out:
338} 348}
339#endif 349#endif
340 350
341#if defined(CONFIG_ARCH_IXDP2X01) 351#if defined(CONFIG_MACH_IXDP2351)
342static int 352static u16
343readword(unsigned long base_addr, int portno) 353readword(unsigned long base_addr, int portno)
344{ 354{
345 return (u16)__raw_readl(base_addr + (portno << 1)); 355 return __raw_readw(base_addr + (portno << 1));
346} 356}
347 357
348static void 358static void
349writeword(unsigned long base_addr, int portno, int value) 359writeword(unsigned long base_addr, int portno, u16 value)
350{ 360{
351 __raw_writel((u16)value, base_addr + (portno << 1)); 361 __raw_writew(value, base_addr + (portno << 1));
352} 362}
353#else 363#elif defined(CONFIG_ARCH_IXDP2X01)
354#if defined(CONFIG_ARCH_PNX010X) 364static u16
355static int 365readword(unsigned long base_addr, int portno)
366{
367 return __raw_readl(base_addr + (portno << 1));
368}
369
370static void
371writeword(unsigned long base_addr, int portno, u16 value)
372{
373 __raw_writel(value, base_addr + (portno << 1));
374}
375#elif defined(CONFIG_ARCH_PNX010X)
376static u16
356readword(unsigned long base_addr, int portno) 377readword(unsigned long base_addr, int portno)
357{ 378{
358 return inw(base_addr + (portno << 1)); 379 return inw(base_addr + (portno << 1));
359} 380}
360 381
361static void 382static void
362writeword(unsigned long base_addr, int portno, int value) 383writeword(unsigned long base_addr, int portno, u16 value)
363{ 384{
364 outw(value, base_addr + (portno << 1)); 385 outw(value, base_addr + (portno << 1));
365} 386}
366#else 387#else
367static int 388static u16
368readword(unsigned long base_addr, int portno) 389readword(unsigned long base_addr, int portno)
369{ 390{
370 return inw(base_addr + portno); 391 return inw(base_addr + portno);
371} 392}
372 393
373static void 394static void
374writeword(unsigned long base_addr, int portno, int value) 395writeword(unsigned long base_addr, int portno, u16 value)
375{ 396{
376 outw(value, base_addr + portno); 397 outw(value, base_addr + portno);
377} 398}
378#endif 399#endif
379#endif
380 400
381static void 401static void
382readwords(unsigned long base_addr, int portno, void *buf, int length) 402readwords(unsigned long base_addr, int portno, void *buf, int length)
@@ -384,11 +404,11 @@ readwords(unsigned long base_addr, int portno, void *buf, int length)
384 u8 *buf8 = (u8 *)buf; 404 u8 *buf8 = (u8 *)buf;
385 405
386 do { 406 do {
387 u32 tmp32; 407 u16 tmp16;
388 408
389 tmp32 = readword(base_addr, portno); 409 tmp16 = readword(base_addr, portno);
390 *buf8++ = (u8)tmp32; 410 *buf8++ = (u8)tmp16;
391 *buf8++ = (u8)(tmp32 >> 8); 411 *buf8++ = (u8)(tmp16 >> 8);
392 } while (--length); 412 } while (--length);
393} 413}
394 414
@@ -398,23 +418,23 @@ writewords(unsigned long base_addr, int portno, void *buf, int length)
398 u8 *buf8 = (u8 *)buf; 418 u8 *buf8 = (u8 *)buf;
399 419
400 do { 420 do {
401 u32 tmp32; 421 u16 tmp16;
402 422
403 tmp32 = *buf8++; 423 tmp16 = *buf8++;
404 tmp32 |= (*buf8++) << 8; 424 tmp16 |= (*buf8++) << 8;
405 writeword(base_addr, portno, tmp32); 425 writeword(base_addr, portno, tmp16);
406 } while (--length); 426 } while (--length);
407} 427}
408 428
409static int 429static u16
410readreg(struct net_device *dev, int regno) 430readreg(struct net_device *dev, u16 regno)
411{ 431{
412 writeword(dev->base_addr, ADD_PORT, regno); 432 writeword(dev->base_addr, ADD_PORT, regno);
413 return readword(dev->base_addr, DATA_PORT); 433 return readword(dev->base_addr, DATA_PORT);
414} 434}
415 435
416static void 436static void
417writereg(struct net_device *dev, int regno, int value) 437writereg(struct net_device *dev, u16 regno, u16 value)
418{ 438{
419 writeword(dev->base_addr, ADD_PORT, regno); 439 writeword(dev->base_addr, ADD_PORT, regno);
420 writeword(dev->base_addr, DATA_PORT, value); 440 writeword(dev->base_addr, DATA_PORT, value);
@@ -780,7 +800,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
780 } else { 800 } else {
781 i = lp->isa_config & INT_NO_MASK; 801 i = lp->isa_config & INT_NO_MASK;
782 if (lp->chip_type == CS8900) { 802 if (lp->chip_type == CS8900) {
783#if defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX010X) 803#if defined(CONFIG_MACH_IXDP2351) || defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX010X)
784 i = cs8900_irq_map[0]; 804 i = cs8900_irq_map[0];
785#else 805#else
786 /* Translate the IRQ using the IRQ mapping table. */ 806 /* Translate the IRQ using the IRQ mapping table. */
@@ -1012,7 +1032,7 @@ skip_this_frame:
1012 1032
1013void __init reset_chip(struct net_device *dev) 1033void __init reset_chip(struct net_device *dev)
1014{ 1034{
1015#ifndef CONFIG_ARCH_IXDP2X01 1035#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01)
1016 struct net_local *lp = netdev_priv(dev); 1036 struct net_local *lp = netdev_priv(dev);
1017 int ioaddr = dev->base_addr; 1037 int ioaddr = dev->base_addr;
1018#endif 1038#endif
@@ -1023,7 +1043,7 @@ void __init reset_chip(struct net_device *dev)
1023 /* wait 30 ms */ 1043 /* wait 30 ms */
1024 msleep(30); 1044 msleep(30);
1025 1045
1026#ifndef CONFIG_ARCH_IXDP2X01 1046#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01)
1027 if (lp->chip_type != CS8900) { 1047 if (lp->chip_type != CS8900) {
1028 /* Hardware problem requires PNP registers to be reconfigured after a reset */ 1048 /* Hardware problem requires PNP registers to be reconfigured after a reset */
1029 writeword(ioaddr, ADD_PORT, PP_CS8920_ISAINT); 1049 writeword(ioaddr, ADD_PORT, PP_CS8920_ISAINT);
@@ -1287,7 +1307,7 @@ net_open(struct net_device *dev)
1287 else 1307 else
1288#endif 1308#endif
1289 { 1309 {
1290#if !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX010X) 1310#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX010X)
1291 if (((1 << dev->irq) & lp->irq_map) == 0) { 1311 if (((1 << dev->irq) & lp->irq_map) == 0) {
1292 printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n", 1312 printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n",
1293 dev->name, dev->irq, lp->irq_map); 1313 dev->name, dev->irq, lp->irq_map);
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 23de22631c64..4726722a0635 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -592,7 +592,7 @@ static inline void e100_write_flush(struct nic *nic)
592 (void)readb(&nic->csr->scb.status); 592 (void)readb(&nic->csr->scb.status);
593} 593}
594 594
595static inline void e100_enable_irq(struct nic *nic) 595static void e100_enable_irq(struct nic *nic)
596{ 596{
597 unsigned long flags; 597 unsigned long flags;
598 598
@@ -602,7 +602,7 @@ static inline void e100_enable_irq(struct nic *nic)
602 e100_write_flush(nic); 602 e100_write_flush(nic);
603} 603}
604 604
605static inline void e100_disable_irq(struct nic *nic) 605static void e100_disable_irq(struct nic *nic)
606{ 606{
607 unsigned long flags; 607 unsigned long flags;
608 608
@@ -791,7 +791,7 @@ static int e100_eeprom_save(struct nic *nic, u16 start, u16 count)
791 791
792#define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */ 792#define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */
793#define E100_WAIT_SCB_FAST 20 /* delay like the old code */ 793#define E100_WAIT_SCB_FAST 20 /* delay like the old code */
794static inline int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) 794static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr)
795{ 795{
796 unsigned long flags; 796 unsigned long flags;
797 unsigned int i; 797 unsigned int i;
@@ -822,7 +822,7 @@ err_unlock:
822 return err; 822 return err;
823} 823}
824 824
825static inline int e100_exec_cb(struct nic *nic, struct sk_buff *skb, 825static int e100_exec_cb(struct nic *nic, struct sk_buff *skb,
826 void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) 826 void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *))
827{ 827{
828 struct cb *cb; 828 struct cb *cb;
@@ -1567,7 +1567,7 @@ static void e100_watchdog(unsigned long data)
1567 mod_timer(&nic->watchdog, jiffies + E100_WATCHDOG_PERIOD); 1567 mod_timer(&nic->watchdog, jiffies + E100_WATCHDOG_PERIOD);
1568} 1568}
1569 1569
1570static inline void e100_xmit_prepare(struct nic *nic, struct cb *cb, 1570static void e100_xmit_prepare(struct nic *nic, struct cb *cb,
1571 struct sk_buff *skb) 1571 struct sk_buff *skb)
1572{ 1572{
1573 cb->command = nic->tx_command; 1573 cb->command = nic->tx_command;
@@ -1617,7 +1617,7 @@ static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
1617 return 0; 1617 return 0;
1618} 1618}
1619 1619
1620static inline int e100_tx_clean(struct nic *nic) 1620static int e100_tx_clean(struct nic *nic)
1621{ 1621{
1622 struct cb *cb; 1622 struct cb *cb;
1623 int tx_cleaned = 0; 1623 int tx_cleaned = 0;
@@ -1728,7 +1728,7 @@ static inline void e100_start_receiver(struct nic *nic, struct rx *rx)
1728} 1728}
1729 1729
1730#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) 1730#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN)
1731static inline int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) 1731static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx)
1732{ 1732{
1733 if(!(rx->skb = dev_alloc_skb(RFD_BUF_LEN + NET_IP_ALIGN))) 1733 if(!(rx->skb = dev_alloc_skb(RFD_BUF_LEN + NET_IP_ALIGN)))
1734 return -ENOMEM; 1734 return -ENOMEM;
@@ -1762,7 +1762,7 @@ static inline int e100_rx_alloc_skb(struct nic *nic, struct rx *rx)
1762 return 0; 1762 return 0;
1763} 1763}
1764 1764
1765static inline int e100_rx_indicate(struct nic *nic, struct rx *rx, 1765static int e100_rx_indicate(struct nic *nic, struct rx *rx,
1766 unsigned int *work_done, unsigned int work_to_do) 1766 unsigned int *work_done, unsigned int work_to_do)
1767{ 1767{
1768 struct sk_buff *skb = rx->skb; 1768 struct sk_buff *skb = rx->skb;
@@ -1822,7 +1822,7 @@ static inline int e100_rx_indicate(struct nic *nic, struct rx *rx,
1822 return 0; 1822 return 0;
1823} 1823}
1824 1824
1825static inline void e100_rx_clean(struct nic *nic, unsigned int *work_done, 1825static void e100_rx_clean(struct nic *nic, unsigned int *work_done,
1826 unsigned int work_to_do) 1826 unsigned int work_to_do)
1827{ 1827{
1828 struct rx *rx; 1828 struct rx *rx;
diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c
index d6388e1533f0..76139478c3df 100644
--- a/drivers/net/sb1000.c
+++ b/drivers/net/sb1000.c
@@ -94,7 +94,7 @@ static inline int card_wait_for_busy_clear(const int ioaddr[],
94 const char* name); 94 const char* name);
95static inline int card_wait_for_ready(const int ioaddr[], const char* name, 95static inline int card_wait_for_ready(const int ioaddr[], const char* name,
96 unsigned char in[]); 96 unsigned char in[]);
97static inline int card_send_command(const int ioaddr[], const char* name, 97static int card_send_command(const int ioaddr[], const char* name,
98 const unsigned char out[], unsigned char in[]); 98 const unsigned char out[], unsigned char in[]);
99 99
100/* SB1000 hardware routines to be used during frame rx interrupt */ 100/* SB1000 hardware routines to be used during frame rx interrupt */
@@ -309,7 +309,7 @@ card_wait_for_ready(const int ioaddr[], const char* name, unsigned char in[])
309} 309}
310 310
311/* Card Send Command (cannot be used during an interrupt) */ 311/* Card Send Command (cannot be used during an interrupt) */
312static inline int 312static int
313card_send_command(const int ioaddr[], const char* name, 313card_send_command(const int ioaddr[], const char* name,
314 const unsigned char out[], unsigned char in[]) 314 const unsigned char out[], unsigned char in[])
315{ 315{
diff --git a/drivers/net/wireless/hostap/hostap_80211_rx.c b/drivers/net/wireless/hostap/hostap_80211_rx.c
index ffac50899454..4b13b76425c1 100644
--- a/drivers/net/wireless/hostap/hostap_80211_rx.c
+++ b/drivers/net/wireless/hostap/hostap_80211_rx.c
@@ -435,7 +435,7 @@ static void hostap_rx_sta_beacon(local_info_t *local, struct sk_buff *skb,
435} 435}
436 436
437 437
438static inline int 438static int
439hostap_rx_frame_mgmt(local_info_t *local, struct sk_buff *skb, 439hostap_rx_frame_mgmt(local_info_t *local, struct sk_buff *skb,
440 struct hostap_80211_rx_status *rx_stats, u16 type, 440 struct hostap_80211_rx_status *rx_stats, u16 type,
441 u16 stype) 441 u16 stype)
@@ -499,7 +499,7 @@ hostap_rx_frame_mgmt(local_info_t *local, struct sk_buff *skb,
499 499
500 500
501/* Called only as a tasklet (software IRQ) */ 501/* Called only as a tasklet (software IRQ) */
502static inline struct net_device *prism2_rx_get_wds(local_info_t *local, 502static struct net_device *prism2_rx_get_wds(local_info_t *local,
503 u8 *addr) 503 u8 *addr)
504{ 504{
505 struct hostap_interface *iface = NULL; 505 struct hostap_interface *iface = NULL;
@@ -519,7 +519,7 @@ static inline struct net_device *prism2_rx_get_wds(local_info_t *local,
519} 519}
520 520
521 521
522static inline int 522static int
523hostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr_4addr *hdr, 523hostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr_4addr *hdr,
524 u16 fc, struct net_device **wds) 524 u16 fc, struct net_device **wds)
525{ 525{
@@ -615,7 +615,7 @@ static int hostap_is_eapol_frame(local_info_t *local, struct sk_buff *skb)
615 615
616 616
617/* Called only as a tasklet (software IRQ) */ 617/* Called only as a tasklet (software IRQ) */
618static inline int 618static int
619hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb, 619hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb,
620 struct ieee80211_crypt_data *crypt) 620 struct ieee80211_crypt_data *crypt)
621{ 621{
@@ -654,7 +654,7 @@ hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb,
654 654
655 655
656/* Called only as a tasklet (software IRQ) */ 656/* Called only as a tasklet (software IRQ) */
657static inline int 657static int
658hostap_rx_frame_decrypt_msdu(local_info_t *local, struct sk_buff *skb, 658hostap_rx_frame_decrypt_msdu(local_info_t *local, struct sk_buff *skb,
659 int keyidx, struct ieee80211_crypt_data *crypt) 659 int keyidx, struct ieee80211_crypt_data *crypt)
660{ 660{
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
index abfae7fedebc..b1f142d9e232 100644
--- a/drivers/net/wireless/hostap/hostap_hw.c
+++ b/drivers/net/wireless/hostap/hostap_hw.c
@@ -253,7 +253,7 @@ static void prism2_clear_cmd_queue(local_info_t *local)
253 * @dev: pointer to net_device 253 * @dev: pointer to net_device
254 * @entry: Prism2 command queue entry to be issued 254 * @entry: Prism2 command queue entry to be issued
255 */ 255 */
256static inline int hfa384x_cmd_issue(struct net_device *dev, 256static int hfa384x_cmd_issue(struct net_device *dev,
257 struct hostap_cmd_queue *entry) 257 struct hostap_cmd_queue *entry)
258{ 258{
259 struct hostap_interface *iface; 259 struct hostap_interface *iface;
@@ -743,7 +743,7 @@ static void prism2_cmd_ev(struct net_device *dev)
743} 743}
744 744
745 745
746static inline int hfa384x_wait_offset(struct net_device *dev, u16 o_off) 746static int hfa384x_wait_offset(struct net_device *dev, u16 o_off)
747{ 747{
748 int tries = HFA384X_BAP_BUSY_TIMEOUT; 748 int tries = HFA384X_BAP_BUSY_TIMEOUT;
749 int res = HFA384X_INW(o_off) & HFA384X_OFFSET_BUSY; 749 int res = HFA384X_INW(o_off) & HFA384X_OFFSET_BUSY;
@@ -1904,7 +1904,7 @@ fail:
1904 * and will try to get the correct fid eventually. */ 1904 * and will try to get the correct fid eventually. */
1905#define EXTRA_FID_READ_TESTS 1905#define EXTRA_FID_READ_TESTS
1906 1906
1907static inline u16 prism2_read_fid_reg(struct net_device *dev, u16 reg) 1907static u16 prism2_read_fid_reg(struct net_device *dev, u16 reg)
1908{ 1908{
1909#ifdef EXTRA_FID_READ_TESTS 1909#ifdef EXTRA_FID_READ_TESTS
1910 u16 val, val2, val3; 1910 u16 val, val2, val3;
@@ -2581,7 +2581,7 @@ static void prism2_ev_tick(struct net_device *dev)
2581 2581
2582 2582
2583/* Called only from hardware IRQ */ 2583/* Called only from hardware IRQ */
2584static inline void prism2_check_magic(local_info_t *local) 2584static void prism2_check_magic(local_info_t *local)
2585{ 2585{
2586 /* at least PCI Prism2.5 with bus mastering seems to sometimes 2586 /* at least PCI Prism2.5 with bus mastering seems to sometimes
2587 * return 0x0000 in SWSUPPORT0 for unknown reason, but re-reading the 2587 * return 0x0000 in SWSUPPORT0 for unknown reason, but re-reading the
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index cf05661fb1bd..7518384f34d9 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -411,7 +411,7 @@ static inline void write_nic_dword_auto_inc(struct net_device *dev, u32 val)
411 write_register(dev, IPW_REG_AUTOINCREMENT_DATA, val); 411 write_register(dev, IPW_REG_AUTOINCREMENT_DATA, val);
412} 412}
413 413
414static inline void write_nic_memory(struct net_device *dev, u32 addr, u32 len, 414static void write_nic_memory(struct net_device *dev, u32 addr, u32 len,
415 const u8 * buf) 415 const u8 * buf)
416{ 416{
417 u32 aligned_addr; 417 u32 aligned_addr;
@@ -449,7 +449,7 @@ static inline void write_nic_memory(struct net_device *dev, u32 addr, u32 len,
449 *buf); 449 *buf);
450} 450}
451 451
452static inline void read_nic_memory(struct net_device *dev, u32 addr, u32 len, 452static void read_nic_memory(struct net_device *dev, u32 addr, u32 len,
453 u8 * buf) 453 u8 * buf)
454{ 454{
455 u32 aligned_addr; 455 u32 aligned_addr;
@@ -657,7 +657,7 @@ static void printk_buf(int level, const u8 * data, u32 len)
657 657
658#define MAX_RESET_BACKOFF 10 658#define MAX_RESET_BACKOFF 10
659 659
660static inline void schedule_reset(struct ipw2100_priv *priv) 660static void schedule_reset(struct ipw2100_priv *priv)
661{ 661{
662 unsigned long now = get_seconds(); 662 unsigned long now = get_seconds();
663 663
@@ -1130,7 +1130,7 @@ static inline void ipw2100_hw_set_gpio(struct ipw2100_priv *priv)
1130 write_register(priv->net_dev, IPW_REG_GPIO, reg); 1130 write_register(priv->net_dev, IPW_REG_GPIO, reg);
1131} 1131}
1132 1132
1133static inline int rf_kill_active(struct ipw2100_priv *priv) 1133static int rf_kill_active(struct ipw2100_priv *priv)
1134{ 1134{
1135#define MAX_RF_KILL_CHECKS 5 1135#define MAX_RF_KILL_CHECKS 5
1136#define RF_KILL_CHECK_DELAY 40 1136#define RF_KILL_CHECK_DELAY 40
@@ -2177,7 +2177,7 @@ static const char *frame_types[] = {
2177}; 2177};
2178#endif 2178#endif
2179 2179
2180static inline int ipw2100_alloc_skb(struct ipw2100_priv *priv, 2180static int ipw2100_alloc_skb(struct ipw2100_priv *priv,
2181 struct ipw2100_rx_packet *packet) 2181 struct ipw2100_rx_packet *packet)
2182{ 2182{
2183 packet->skb = dev_alloc_skb(sizeof(struct ipw2100_rx)); 2183 packet->skb = dev_alloc_skb(sizeof(struct ipw2100_rx));
@@ -2201,7 +2201,7 @@ static inline int ipw2100_alloc_skb(struct ipw2100_priv *priv,
2201#define SEARCH_SNAPSHOT 1 2201#define SEARCH_SNAPSHOT 1
2202 2202
2203#define SNAPSHOT_ADDR(ofs) (priv->snapshot[((ofs) >> 12) & 0xff] + ((ofs) & 0xfff)) 2203#define SNAPSHOT_ADDR(ofs) (priv->snapshot[((ofs) >> 12) & 0xff] + ((ofs) & 0xfff))
2204static inline int ipw2100_snapshot_alloc(struct ipw2100_priv *priv) 2204static int ipw2100_snapshot_alloc(struct ipw2100_priv *priv)
2205{ 2205{
2206 int i; 2206 int i;
2207 if (priv->snapshot[0]) 2207 if (priv->snapshot[0])
@@ -2221,7 +2221,7 @@ static inline int ipw2100_snapshot_alloc(struct ipw2100_priv *priv)
2221 return 1; 2221 return 1;
2222} 2222}
2223 2223
2224static inline void ipw2100_snapshot_free(struct ipw2100_priv *priv) 2224static void ipw2100_snapshot_free(struct ipw2100_priv *priv)
2225{ 2225{
2226 int i; 2226 int i;
2227 if (!priv->snapshot[0]) 2227 if (!priv->snapshot[0])
@@ -2231,7 +2231,7 @@ static inline void ipw2100_snapshot_free(struct ipw2100_priv *priv)
2231 priv->snapshot[0] = NULL; 2231 priv->snapshot[0] = NULL;
2232} 2232}
2233 2233
2234static inline u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 * in_buf, 2234static u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 * in_buf,
2235 size_t len, int mode) 2235 size_t len, int mode)
2236{ 2236{
2237 u32 i, j; 2237 u32 i, j;
@@ -2288,7 +2288,7 @@ static inline u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 * in_buf,
2288static u8 packet_data[IPW_RX_NIC_BUFFER_LENGTH]; 2288static u8 packet_data[IPW_RX_NIC_BUFFER_LENGTH];
2289#endif 2289#endif
2290 2290
2291static inline void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i) 2291static void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i)
2292{ 2292{
2293#ifdef CONFIG_IPW2100_DEBUG_C3 2293#ifdef CONFIG_IPW2100_DEBUG_C3
2294 struct ipw2100_status *status = &priv->status_queue.drv[i]; 2294 struct ipw2100_status *status = &priv->status_queue.drv[i];
@@ -2346,7 +2346,7 @@ static inline void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i)
2346 schedule_reset(priv); 2346 schedule_reset(priv);
2347} 2347}
2348 2348
2349static inline void isr_rx(struct ipw2100_priv *priv, int i, 2349static void isr_rx(struct ipw2100_priv *priv, int i,
2350 struct ieee80211_rx_stats *stats) 2350 struct ieee80211_rx_stats *stats)
2351{ 2351{
2352 struct ipw2100_status *status = &priv->status_queue.drv[i]; 2352 struct ipw2100_status *status = &priv->status_queue.drv[i];
@@ -2425,7 +2425,7 @@ static inline void isr_rx(struct ipw2100_priv *priv, int i,
2425 priv->rx_queue.drv[i].host_addr = packet->dma_addr; 2425 priv->rx_queue.drv[i].host_addr = packet->dma_addr;
2426} 2426}
2427 2427
2428static inline int ipw2100_corruption_check(struct ipw2100_priv *priv, int i) 2428static int ipw2100_corruption_check(struct ipw2100_priv *priv, int i)
2429{ 2429{
2430 struct ipw2100_status *status = &priv->status_queue.drv[i]; 2430 struct ipw2100_status *status = &priv->status_queue.drv[i];
2431 struct ipw2100_rx *u = priv->rx_buffers[i].rxp; 2431 struct ipw2100_rx *u = priv->rx_buffers[i].rxp;
@@ -2481,7 +2481,7 @@ static inline int ipw2100_corruption_check(struct ipw2100_priv *priv, int i)
2481 * The WRITE index is cached in the variable 'priv->rx_queue.next'. 2481 * The WRITE index is cached in the variable 'priv->rx_queue.next'.
2482 * 2482 *
2483 */ 2483 */
2484static inline void __ipw2100_rx_process(struct ipw2100_priv *priv) 2484static void __ipw2100_rx_process(struct ipw2100_priv *priv)
2485{ 2485{
2486 struct ipw2100_bd_queue *rxq = &priv->rx_queue; 2486 struct ipw2100_bd_queue *rxq = &priv->rx_queue;
2487 struct ipw2100_status_queue *sq = &priv->status_queue; 2487 struct ipw2100_status_queue *sq = &priv->status_queue;
@@ -2634,7 +2634,7 @@ static inline void __ipw2100_rx_process(struct ipw2100_priv *priv)
2634 * for use by future command and data packets. 2634 * for use by future command and data packets.
2635 * 2635 *
2636 */ 2636 */
2637static inline int __ipw2100_tx_process(struct ipw2100_priv *priv) 2637static int __ipw2100_tx_process(struct ipw2100_priv *priv)
2638{ 2638{
2639 struct ipw2100_bd_queue *txq = &priv->tx_queue; 2639 struct ipw2100_bd_queue *txq = &priv->tx_queue;
2640 struct ipw2100_bd *tbd; 2640 struct ipw2100_bd *tbd;
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index cdfe50207757..819be2b6b7df 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -813,7 +813,7 @@ static void ipw_bg_led_link_off(void *data)
813 up(&priv->sem); 813 up(&priv->sem);
814} 814}
815 815
816static inline void __ipw_led_activity_on(struct ipw_priv *priv) 816static void __ipw_led_activity_on(struct ipw_priv *priv)
817{ 817{
818 u32 led; 818 u32 led;
819 819
@@ -1508,7 +1508,7 @@ static ssize_t store_direct_dword(struct device *d,
1508static DEVICE_ATTR(direct_dword, S_IWUSR | S_IRUGO, 1508static DEVICE_ATTR(direct_dword, S_IWUSR | S_IRUGO,
1509 show_direct_dword, store_direct_dword); 1509 show_direct_dword, store_direct_dword);
1510 1510
1511static inline int rf_kill_active(struct ipw_priv *priv) 1511static int rf_kill_active(struct ipw_priv *priv)
1512{ 1512{
1513 if (0 == (ipw_read32(priv, 0x30) & 0x10000)) 1513 if (0 == (ipw_read32(priv, 0x30) & 0x10000))
1514 priv->status |= STATUS_RF_KILL_HW; 1514 priv->status |= STATUS_RF_KILL_HW;
@@ -2359,7 +2359,7 @@ static inline void eeprom_write_reg(struct ipw_priv *p, u32 data)
2359} 2359}
2360 2360
2361/* perform a chip select operation */ 2361/* perform a chip select operation */
2362static inline void eeprom_cs(struct ipw_priv *priv) 2362static void eeprom_cs(struct ipw_priv *priv)
2363{ 2363{
2364 eeprom_write_reg(priv, 0); 2364 eeprom_write_reg(priv, 0);
2365 eeprom_write_reg(priv, EEPROM_BIT_CS); 2365 eeprom_write_reg(priv, EEPROM_BIT_CS);
@@ -2368,7 +2368,7 @@ static inline void eeprom_cs(struct ipw_priv *priv)
2368} 2368}
2369 2369
2370/* perform a chip select operation */ 2370/* perform a chip select operation */
2371static inline void eeprom_disable_cs(struct ipw_priv *priv) 2371static void eeprom_disable_cs(struct ipw_priv *priv)
2372{ 2372{
2373 eeprom_write_reg(priv, EEPROM_BIT_CS); 2373 eeprom_write_reg(priv, EEPROM_BIT_CS);
2374 eeprom_write_reg(priv, 0); 2374 eeprom_write_reg(priv, 0);
@@ -2475,7 +2475,7 @@ static void ipw_eeprom_init_sram(struct ipw_priv *priv)
2475 IPW_DEBUG_TRACE("<<\n"); 2475 IPW_DEBUG_TRACE("<<\n");
2476} 2476}
2477 2477
2478static inline void ipw_zero_memory(struct ipw_priv *priv, u32 start, u32 count) 2478static void ipw_zero_memory(struct ipw_priv *priv, u32 start, u32 count)
2479{ 2479{
2480 count >>= 2; 2480 count >>= 2;
2481 if (!count) 2481 if (!count)
@@ -2772,7 +2772,7 @@ static inline int ipw_alive(struct ipw_priv *priv)
2772 return ipw_read32(priv, 0x90) == 0xd55555d5; 2772 return ipw_read32(priv, 0x90) == 0xd55555d5;
2773} 2773}
2774 2774
2775static inline int ipw_poll_bit(struct ipw_priv *priv, u32 addr, u32 mask, 2775static int ipw_poll_bit(struct ipw_priv *priv, u32 addr, u32 mask,
2776 int timeout) 2776 int timeout)
2777{ 2777{
2778 int i = 0; 2778 int i = 0;
@@ -3150,7 +3150,7 @@ static int ipw_get_fw(struct ipw_priv *priv,
3150 3150
3151#define IPW_RX_BUF_SIZE (3000) 3151#define IPW_RX_BUF_SIZE (3000)
3152 3152
3153static inline void ipw_rx_queue_reset(struct ipw_priv *priv, 3153static void ipw_rx_queue_reset(struct ipw_priv *priv,
3154 struct ipw_rx_queue *rxq) 3154 struct ipw_rx_queue *rxq)
3155{ 3155{
3156 unsigned long flags; 3156 unsigned long flags;
@@ -3608,7 +3608,7 @@ static void ipw_tx_queue_free(struct ipw_priv *priv)
3608 ipw_queue_tx_free(priv, &priv->txq[3]); 3608 ipw_queue_tx_free(priv, &priv->txq[3]);
3609} 3609}
3610 3610
3611static inline void ipw_create_bssid(struct ipw_priv *priv, u8 * bssid) 3611static void ipw_create_bssid(struct ipw_priv *priv, u8 * bssid)
3612{ 3612{
3613 /* First 3 bytes are manufacturer */ 3613 /* First 3 bytes are manufacturer */
3614 bssid[0] = priv->mac_addr[0]; 3614 bssid[0] = priv->mac_addr[0];
@@ -3622,7 +3622,7 @@ static inline void ipw_create_bssid(struct ipw_priv *priv, u8 * bssid)
3622 bssid[0] |= 0x02; /* set local assignment bit (IEEE802) */ 3622 bssid[0] |= 0x02; /* set local assignment bit (IEEE802) */
3623} 3623}
3624 3624
3625static inline u8 ipw_add_station(struct ipw_priv *priv, u8 * bssid) 3625static u8 ipw_add_station(struct ipw_priv *priv, u8 * bssid)
3626{ 3626{
3627 struct ipw_station_entry entry; 3627 struct ipw_station_entry entry;
3628 int i; 3628 int i;
@@ -3655,7 +3655,7 @@ static inline u8 ipw_add_station(struct ipw_priv *priv, u8 * bssid)
3655 return i; 3655 return i;
3656} 3656}
3657 3657
3658static inline u8 ipw_find_station(struct ipw_priv *priv, u8 * bssid) 3658static u8 ipw_find_station(struct ipw_priv *priv, u8 * bssid)
3659{ 3659{
3660 int i; 3660 int i;
3661 3661
@@ -3794,7 +3794,7 @@ static void inline average_init(struct average *avg)
3794 memset(avg, 0, sizeof(*avg)); 3794 memset(avg, 0, sizeof(*avg));
3795} 3795}
3796 3796
3797static void inline average_add(struct average *avg, s16 val) 3797static void average_add(struct average *avg, s16 val)
3798{ 3798{
3799 avg->sum -= avg->entries[avg->pos]; 3799 avg->sum -= avg->entries[avg->pos];
3800 avg->sum += val; 3800 avg->sum += val;
@@ -3805,7 +3805,7 @@ static void inline average_add(struct average *avg, s16 val)
3805 } 3805 }
3806} 3806}
3807 3807
3808static s16 inline average_value(struct average *avg) 3808static s16 average_value(struct average *avg)
3809{ 3809{
3810 if (!unlikely(avg->init)) { 3810 if (!unlikely(avg->init)) {
3811 if (avg->pos) 3811 if (avg->pos)
@@ -3847,7 +3847,7 @@ static void ipw_reset_stats(struct ipw_priv *priv)
3847 3847
3848} 3848}
3849 3849
3850static inline u32 ipw_get_max_rate(struct ipw_priv *priv) 3850static u32 ipw_get_max_rate(struct ipw_priv *priv)
3851{ 3851{
3852 u32 i = 0x80000000; 3852 u32 i = 0x80000000;
3853 u32 mask = priv->rates_mask; 3853 u32 mask = priv->rates_mask;
@@ -4087,7 +4087,7 @@ static void ipw_bg_gather_stats(void *data)
4087 * roaming_threshold -> disassociate_threshold, scan and roam for better signal. 4087 * roaming_threshold -> disassociate_threshold, scan and roam for better signal.
4088 * Above disassociate threshold, give up and stop scanning. 4088 * Above disassociate threshold, give up and stop scanning.
4089 * Roaming is disabled if disassociate_threshold <= roaming_threshold */ 4089 * Roaming is disabled if disassociate_threshold <= roaming_threshold */
4090static inline void ipw_handle_missed_beacon(struct ipw_priv *priv, 4090static void ipw_handle_missed_beacon(struct ipw_priv *priv,
4091 int missed_count) 4091 int missed_count)
4092{ 4092{
4093 priv->notif_missed_beacons = missed_count; 4093 priv->notif_missed_beacons = missed_count;
@@ -4157,7 +4157,7 @@ static inline void ipw_handle_missed_beacon(struct ipw_priv *priv,
4157 * Handle host notification packet. 4157 * Handle host notification packet.
4158 * Called from interrupt routine 4158 * Called from interrupt routine
4159 */ 4159 */
4160static inline void ipw_rx_notification(struct ipw_priv *priv, 4160static void ipw_rx_notification(struct ipw_priv *priv,
4161 struct ipw_rx_notification *notif) 4161 struct ipw_rx_notification *notif)
4162{ 4162{
4163 notif->size = le16_to_cpu(notif->size); 4163 notif->size = le16_to_cpu(notif->size);
@@ -5095,7 +5095,7 @@ static int ipw_compatible_rates(struct ipw_priv *priv,
5095 return 1; 5095 return 1;
5096} 5096}
5097 5097
5098static inline void ipw_copy_rates(struct ipw_supported_rates *dest, 5098static void ipw_copy_rates(struct ipw_supported_rates *dest,
5099 const struct ipw_supported_rates *src) 5099 const struct ipw_supported_rates *src)
5100{ 5100{
5101 u8 i; 5101 u8 i;
@@ -5856,7 +5856,7 @@ static void ipw_debug_config(struct ipw_priv *priv)
5856#define ipw_debug_config(x) do {} while (0) 5856#define ipw_debug_config(x) do {} while (0)
5857#endif 5857#endif
5858 5858
5859static inline void ipw_set_fixed_rate(struct ipw_priv *priv, int mode) 5859static void ipw_set_fixed_rate(struct ipw_priv *priv, int mode)
5860{ 5860{
5861 /* TODO: Verify that this works... */ 5861 /* TODO: Verify that this works... */
5862 struct ipw_fixed_rate fr = { 5862 struct ipw_fixed_rate fr = {
@@ -7634,7 +7634,7 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv,
7634} 7634}
7635#endif 7635#endif
7636 7636
7637static inline int is_network_packet(struct ipw_priv *priv, 7637static int is_network_packet(struct ipw_priv *priv,
7638 struct ieee80211_hdr_4addr *header) 7638 struct ieee80211_hdr_4addr *header)
7639{ 7639{
7640 /* Filter incoming packets to determine if they are targetted toward 7640 /* Filter incoming packets to determine if they are targetted toward
@@ -7672,7 +7672,7 @@ static inline int is_network_packet(struct ipw_priv *priv,
7672 7672
7673#define IPW_PACKET_RETRY_TIME HZ 7673#define IPW_PACKET_RETRY_TIME HZ
7674 7674
7675static inline int is_duplicate_packet(struct ipw_priv *priv, 7675static int is_duplicate_packet(struct ipw_priv *priv,
7676 struct ieee80211_hdr_4addr *header) 7676 struct ieee80211_hdr_4addr *header)
7677{ 7677{
7678 u16 sc = le16_to_cpu(header->seq_ctl); 7678 u16 sc = le16_to_cpu(header->seq_ctl);
@@ -9581,7 +9581,7 @@ static struct iw_statistics *ipw_get_wireless_stats(struct net_device *dev)
9581 9581
9582/* net device stuff */ 9582/* net device stuff */
9583 9583
9584static inline void init_sys_config(struct ipw_sys_config *sys_config) 9584static void init_sys_config(struct ipw_sys_config *sys_config)
9585{ 9585{
9586 memset(sys_config, 0, sizeof(struct ipw_sys_config)); 9586 memset(sys_config, 0, sizeof(struct ipw_sys_config));
9587 sys_config->bt_coexistence = 1; /* We may need to look into prvStaBtConfig */ 9587 sys_config->bt_coexistence = 1; /* We may need to look into prvStaBtConfig */
@@ -9627,7 +9627,7 @@ modify to send one tfd per fragment instead of using chunking. otherwise
9627we need to heavily modify the ieee80211_skb_to_txb. 9627we need to heavily modify the ieee80211_skb_to_txb.
9628*/ 9628*/
9629 9629
9630static inline int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, 9630static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
9631 int pri) 9631 int pri)
9632{ 9632{
9633 struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *) 9633 struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)
diff --git a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c
index b0d8b5b03152..ff192e96268a 100644
--- a/drivers/net/wireless/wavelan.c
+++ b/drivers/net/wireless/wavelan.c
@@ -102,7 +102,7 @@ static inline void hacr_write(unsigned long ioaddr, u16 hacr)
102 * Write to card's Host Adapter Command Register. Include a delay for 102 * Write to card's Host Adapter Command Register. Include a delay for
103 * those times when it is needed. 103 * those times when it is needed.
104 */ 104 */
105static inline void hacr_write_slow(unsigned long ioaddr, u16 hacr) 105static void hacr_write_slow(unsigned long ioaddr, u16 hacr)
106{ 106{
107 hacr_write(ioaddr, hacr); 107 hacr_write(ioaddr, hacr);
108 /* delay might only be needed sometimes */ 108 /* delay might only be needed sometimes */
@@ -242,7 +242,7 @@ static void psa_write(unsigned long ioaddr, u16 hacr, int o, /* Offset in PSA */
242 * The Windows drivers don't use the CRC, but the AP and the PtP tool 242 * The Windows drivers don't use the CRC, but the AP and the PtP tool
243 * depend on it. 243 * depend on it.
244 */ 244 */
245static inline u16 psa_crc(u8 * psa, /* The PSA */ 245static u16 psa_crc(u8 * psa, /* The PSA */
246 int size) 246 int size)
247{ /* Number of short for CRC */ 247{ /* Number of short for CRC */
248 int byte_cnt; /* Loop on the PSA */ 248 int byte_cnt; /* Loop on the PSA */
@@ -310,7 +310,7 @@ static void update_psa_checksum(struct net_device * dev, unsigned long ioaddr, u
310/* 310/*
311 * Write 1 byte to the MMC. 311 * Write 1 byte to the MMC.
312 */ 312 */
313static inline void mmc_out(unsigned long ioaddr, u16 o, u8 d) 313static void mmc_out(unsigned long ioaddr, u16 o, u8 d)
314{ 314{
315 int count = 0; 315 int count = 0;
316 316
@@ -326,7 +326,7 @@ static inline void mmc_out(unsigned long ioaddr, u16 o, u8 d)
326 * Routine to write bytes to the Modem Management Controller. 326 * Routine to write bytes to the Modem Management Controller.
327 * We start at the end because it is the way it should be! 327 * We start at the end because it is the way it should be!
328 */ 328 */
329static inline void mmc_write(unsigned long ioaddr, u8 o, u8 * b, int n) 329static void mmc_write(unsigned long ioaddr, u8 o, u8 * b, int n)
330{ 330{
331 o += n; 331 o += n;
332 b += n; 332 b += n;
@@ -340,7 +340,7 @@ static inline void mmc_write(unsigned long ioaddr, u8 o, u8 * b, int n)
340 * Read a byte from the MMC. 340 * Read a byte from the MMC.
341 * Optimised version for 1 byte, avoid using memory. 341 * Optimised version for 1 byte, avoid using memory.
342 */ 342 */
343static inline u8 mmc_in(unsigned long ioaddr, u16 o) 343static u8 mmc_in(unsigned long ioaddr, u16 o)
344{ 344{
345 int count = 0; 345 int count = 0;
346 346
@@ -587,7 +587,7 @@ static void wv_ack(struct net_device * dev)
587 * Set channel attention bit and busy wait until command has 587 * Set channel attention bit and busy wait until command has
588 * completed, then acknowledge completion of the command. 588 * completed, then acknowledge completion of the command.
589 */ 589 */
590static inline int wv_synchronous_cmd(struct net_device * dev, const char *str) 590static int wv_synchronous_cmd(struct net_device * dev, const char *str)
591{ 591{
592 net_local *lp = (net_local *) dev->priv; 592 net_local *lp = (net_local *) dev->priv;
593 unsigned long ioaddr = dev->base_addr; 593 unsigned long ioaddr = dev->base_addr;
@@ -633,7 +633,7 @@ static inline int wv_synchronous_cmd(struct net_device * dev, const char *str)
633 * Configuration commands completion interrupt. 633 * Configuration commands completion interrupt.
634 * Check if done, and if OK. 634 * Check if done, and if OK.
635 */ 635 */
636static inline int 636static int
637wv_config_complete(struct net_device * dev, unsigned long ioaddr, net_local * lp) 637wv_config_complete(struct net_device * dev, unsigned long ioaddr, net_local * lp)
638{ 638{
639 unsigned short mcs_addr; 639 unsigned short mcs_addr;
@@ -843,7 +843,7 @@ if (lp->tx_n_in_use > 0)
843 * wavelan_interrupt is not an option), so you may experience 843 * wavelan_interrupt is not an option), so you may experience
844 * delays sometimes. 844 * delays sometimes.
845 */ 845 */
846static inline void wv_82586_reconfig(struct net_device * dev) 846static void wv_82586_reconfig(struct net_device * dev)
847{ 847{
848 net_local *lp = (net_local *) dev->priv; 848 net_local *lp = (net_local *) dev->priv;
849 unsigned long flags; 849 unsigned long flags;
@@ -1281,7 +1281,7 @@ static inline void wv_packet_info(u8 * p, /* Packet to dump */
1281 * This is the information which is displayed by the driver at startup. 1281 * This is the information which is displayed by the driver at startup.
1282 * There are lots of flags for configuring it to your liking. 1282 * There are lots of flags for configuring it to your liking.
1283 */ 1283 */
1284static inline void wv_init_info(struct net_device * dev) 1284static void wv_init_info(struct net_device * dev)
1285{ 1285{
1286 short ioaddr = dev->base_addr; 1286 short ioaddr = dev->base_addr;
1287 net_local *lp = (net_local *) dev->priv; 1287 net_local *lp = (net_local *) dev->priv;
@@ -1502,7 +1502,7 @@ static int wavelan_set_mac_address(struct net_device * dev, void *addr)
1502 * It's a bit complicated and you don't really want to look into it. 1502 * It's a bit complicated and you don't really want to look into it.
1503 * (called in wavelan_ioctl) 1503 * (called in wavelan_ioctl)
1504 */ 1504 */
1505static inline int wv_set_frequency(unsigned long ioaddr, /* I/O port of the card */ 1505static int wv_set_frequency(unsigned long ioaddr, /* I/O port of the card */
1506 iw_freq * frequency) 1506 iw_freq * frequency)
1507{ 1507{
1508 const int BAND_NUM = 10; /* Number of bands */ 1508 const int BAND_NUM = 10; /* Number of bands */
@@ -1677,7 +1677,7 @@ static inline int wv_set_frequency(unsigned long ioaddr, /* I/O port of the card
1677/* 1677/*
1678 * Give the list of available frequencies. 1678 * Give the list of available frequencies.
1679 */ 1679 */
1680static inline int wv_frequency_list(unsigned long ioaddr, /* I/O port of the card */ 1680static int wv_frequency_list(unsigned long ioaddr, /* I/O port of the card */
1681 iw_freq * list, /* List of frequencies to fill */ 1681 iw_freq * list, /* List of frequencies to fill */
1682 int max) 1682 int max)
1683{ /* Maximum number of frequencies */ 1683{ /* Maximum number of frequencies */
@@ -2489,7 +2489,7 @@ static iw_stats *wavelan_get_wireless_stats(struct net_device * dev)
2489 * Note: if any errors occur, the packet is "dropped on the floor". 2489 * Note: if any errors occur, the packet is "dropped on the floor".
2490 * (called by wv_packet_rcv()) 2490 * (called by wv_packet_rcv())
2491 */ 2491 */
2492static inline void 2492static void
2493wv_packet_read(struct net_device * dev, u16 buf_off, int sksize) 2493wv_packet_read(struct net_device * dev, u16 buf_off, int sksize)
2494{ 2494{
2495 net_local *lp = (net_local *) dev->priv; 2495 net_local *lp = (net_local *) dev->priv;
@@ -2585,7 +2585,7 @@ wv_packet_read(struct net_device * dev, u16 buf_off, int sksize)
2585 * (called in wavelan_interrupt()). 2585 * (called in wavelan_interrupt()).
2586 * Note : the spinlock is already grabbed for us. 2586 * Note : the spinlock is already grabbed for us.
2587 */ 2587 */
2588static inline void wv_receive(struct net_device * dev) 2588static void wv_receive(struct net_device * dev)
2589{ 2589{
2590 unsigned long ioaddr = dev->base_addr; 2590 unsigned long ioaddr = dev->base_addr;
2591 net_local *lp = (net_local *) dev->priv; 2591 net_local *lp = (net_local *) dev->priv;
@@ -2768,7 +2768,7 @@ static inline void wv_receive(struct net_device * dev)
2768 * 2768 *
2769 * (called in wavelan_packet_xmit()) 2769 * (called in wavelan_packet_xmit())
2770 */ 2770 */
2771static inline int wv_packet_write(struct net_device * dev, void *buf, short length) 2771static int wv_packet_write(struct net_device * dev, void *buf, short length)
2772{ 2772{
2773 net_local *lp = (net_local *) dev->priv; 2773 net_local *lp = (net_local *) dev->priv;
2774 unsigned long ioaddr = dev->base_addr; 2774 unsigned long ioaddr = dev->base_addr;
@@ -2964,7 +2964,7 @@ static int wavelan_packet_xmit(struct sk_buff *skb, struct net_device * dev)
2964 * Routine to initialize the Modem Management Controller. 2964 * Routine to initialize the Modem Management Controller.
2965 * (called by wv_hw_reset()) 2965 * (called by wv_hw_reset())
2966 */ 2966 */
2967static inline int wv_mmc_init(struct net_device * dev) 2967static int wv_mmc_init(struct net_device * dev)
2968{ 2968{
2969 unsigned long ioaddr = dev->base_addr; 2969 unsigned long ioaddr = dev->base_addr;
2970 net_local *lp = (net_local *) dev->priv; 2970 net_local *lp = (net_local *) dev->priv;
@@ -3136,7 +3136,7 @@ static inline int wv_mmc_init(struct net_device * dev)
3136 * Start the receive unit. 3136 * Start the receive unit.
3137 * (called by wv_hw_reset()) 3137 * (called by wv_hw_reset())
3138 */ 3138 */
3139static inline int wv_ru_start(struct net_device * dev) 3139static int wv_ru_start(struct net_device * dev)
3140{ 3140{
3141 net_local *lp = (net_local *) dev->priv; 3141 net_local *lp = (net_local *) dev->priv;
3142 unsigned long ioaddr = dev->base_addr; 3142 unsigned long ioaddr = dev->base_addr;
@@ -3228,7 +3228,7 @@ static inline int wv_ru_start(struct net_device * dev)
3228 * 3228 *
3229 * (called by wv_hw_reset()) 3229 * (called by wv_hw_reset())
3230 */ 3230 */
3231static inline int wv_cu_start(struct net_device * dev) 3231static int wv_cu_start(struct net_device * dev)
3232{ 3232{
3233 net_local *lp = (net_local *) dev->priv; 3233 net_local *lp = (net_local *) dev->priv;
3234 unsigned long ioaddr = dev->base_addr; 3234 unsigned long ioaddr = dev->base_addr;
@@ -3329,7 +3329,7 @@ static inline int wv_cu_start(struct net_device * dev)
3329 * 3329 *
3330 * (called by wv_hw_reset()) 3330 * (called by wv_hw_reset())
3331 */ 3331 */
3332static inline int wv_82586_start(struct net_device * dev) 3332static int wv_82586_start(struct net_device * dev)
3333{ 3333{
3334 net_local *lp = (net_local *) dev->priv; 3334 net_local *lp = (net_local *) dev->priv;
3335 unsigned long ioaddr = dev->base_addr; 3335 unsigned long ioaddr = dev->base_addr;
@@ -3641,7 +3641,7 @@ static void wv_82586_config(struct net_device * dev)
3641 * WaveLAN controller (i82586). 3641 * WaveLAN controller (i82586).
3642 * (called by wavelan_close()) 3642 * (called by wavelan_close())
3643 */ 3643 */
3644static inline void wv_82586_stop(struct net_device * dev) 3644static void wv_82586_stop(struct net_device * dev)
3645{ 3645{
3646 net_local *lp = (net_local *) dev->priv; 3646 net_local *lp = (net_local *) dev->priv;
3647 unsigned long ioaddr = dev->base_addr; 3647 unsigned long ioaddr = dev->base_addr;
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 7146b69b812c..0aa14c92b570 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -380,8 +380,6 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner)
380 /* initialize common driver fields */ 380 /* initialize common driver fields */
381 drv->driver.name = drv->name; 381 drv->driver.name = drv->name;
382 drv->driver.bus = &pci_bus_type; 382 drv->driver.bus = &pci_bus_type;
383 drv->driver.probe = pci_device_probe;
384 drv->driver.remove = pci_device_remove;
385 /* FIXME, once all of the existing PCI drivers have been fixed to set 383 /* FIXME, once all of the existing PCI drivers have been fixed to set
386 * the pci shutdown function, this test can go away. */ 384 * the pci shutdown function, this test can go away. */
387 if (!drv->driver.shutdown) 385 if (!drv->driver.shutdown)
@@ -513,6 +511,8 @@ struct bus_type pci_bus_type = {
513 .name = "pci", 511 .name = "pci",
514 .match = pci_bus_match, 512 .match = pci_bus_match,
515 .uevent = pci_uevent, 513 .uevent = pci_uevent,
514 .probe = pci_device_probe,
515 .remove = pci_device_remove,
516 .suspend = pci_device_suspend, 516 .suspend = pci_device_suspend,
517 .resume = pci_device_resume, 517 .resume = pci_device_resume,
518 .dev_attrs = pci_dev_attrs, 518 .dev_attrs = pci_dev_attrs,
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 621ec459d27a..0a424a4e8187 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -311,8 +311,6 @@ int pcmcia_register_driver(struct pcmcia_driver *driver)
311 /* initialize common fields */ 311 /* initialize common fields */
312 driver->drv.bus = &pcmcia_bus_type; 312 driver->drv.bus = &pcmcia_bus_type;
313 driver->drv.owner = driver->owner; 313 driver->drv.owner = driver->owner;
314 driver->drv.probe = pcmcia_device_probe;
315 driver->drv.remove = pcmcia_device_remove;
316 314
317 return driver_register(&driver->drv); 315 return driver_register(&driver->drv);
318} 316}
@@ -1200,6 +1198,8 @@ struct bus_type pcmcia_bus_type = {
1200 .uevent = pcmcia_bus_uevent, 1198 .uevent = pcmcia_bus_uevent,
1201 .match = pcmcia_bus_match, 1199 .match = pcmcia_bus_match,
1202 .dev_attrs = pcmcia_dev_attrs, 1200 .dev_attrs = pcmcia_dev_attrs,
1201 .probe = pcmcia_device_probe,
1202 .remove = pcmcia_device_remove,
1203 .suspend = pcmcia_dev_suspend, 1203 .suspend = pcmcia_dev_suspend,
1204 .resume = pcmcia_dev_resume, 1204 .resume = pcmcia_dev_resume,
1205}; 1205};
diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c
index 15fb758a9e52..7cafacdd12b0 100644
--- a/drivers/pnp/driver.c
+++ b/drivers/pnp/driver.c
@@ -195,6 +195,8 @@ static int pnp_bus_resume(struct device *dev)
195struct bus_type pnp_bus_type = { 195struct bus_type pnp_bus_type = {
196 .name = "pnp", 196 .name = "pnp",
197 .match = pnp_bus_match, 197 .match = pnp_bus_match,
198 .probe = pnp_device_probe,
199 .remove = pnp_device_remove,
198 .suspend = pnp_bus_suspend, 200 .suspend = pnp_bus_suspend,
199 .resume = pnp_bus_resume, 201 .resume = pnp_bus_resume,
200}; 202};
@@ -215,8 +217,6 @@ int pnp_register_driver(struct pnp_driver *drv)
215 217
216 drv->driver.name = drv->name; 218 drv->driver.name = drv->name;
217 drv->driver.bus = &pnp_bus_type; 219 drv->driver.bus = &pnp_bus_type;
218 drv->driver.probe = pnp_device_probe;
219 drv->driver.remove = pnp_device_remove;
220 220
221 count = driver_register(&drv->driver); 221 count = driver_register(&drv->driver);
222 222
diff --git a/drivers/rapidio/rio-driver.c b/drivers/rapidio/rio-driver.c
index dc749609699a..5480119ff9d3 100644
--- a/drivers/rapidio/rio-driver.c
+++ b/drivers/rapidio/rio-driver.c
@@ -147,8 +147,6 @@ int rio_register_driver(struct rio_driver *rdrv)
147 /* initialize common driver fields */ 147 /* initialize common driver fields */
148 rdrv->driver.name = rdrv->name; 148 rdrv->driver.name = rdrv->name;
149 rdrv->driver.bus = &rio_bus_type; 149 rdrv->driver.bus = &rio_bus_type;
150 rdrv->driver.probe = rio_device_probe;
151 rdrv->driver.remove = rio_device_remove;
152 150
153 /* register with core */ 151 /* register with core */
154 return driver_register(&rdrv->driver); 152 return driver_register(&rdrv->driver);
@@ -204,7 +202,9 @@ static struct device rio_bus = {
204struct bus_type rio_bus_type = { 202struct bus_type rio_bus_type = {
205 .name = "rapidio", 203 .name = "rapidio",
206 .match = rio_match_bus, 204 .match = rio_match_bus,
207 .dev_attrs = rio_dev_attrs 205 .dev_attrs = rio_dev_attrs,
206 .probe = rio_device_probe,
207 .remove = rio_device_remove,
208}; 208};
209 209
210/** 210/**
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 9c25654b1e75..ef4c687e7c01 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -1635,7 +1635,7 @@ dasd_setup_queue(struct dasd_device * device)
1635 blk_queue_max_hw_segments(device->request_queue, -1L); 1635 blk_queue_max_hw_segments(device->request_queue, -1L);
1636 blk_queue_max_segment_size(device->request_queue, -1L); 1636 blk_queue_max_segment_size(device->request_queue, -1L);
1637 blk_queue_segment_boundary(device->request_queue, -1L); 1637 blk_queue_segment_boundary(device->request_queue, -1L);
1638 blk_queue_ordered(device->request_queue, 1); 1638 blk_queue_ordered(device->request_queue, QUEUE_ORDERED_TAG, NULL);
1639} 1639}
1640 1640
1641/* 1641/*
diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c
index 83e6a060668e..cd2cc28e16a7 100644
--- a/drivers/s390/cio/airq.c
+++ b/drivers/s390/cio/airq.c
@@ -2,12 +2,12 @@
2 * drivers/s390/cio/airq.c 2 * drivers/s390/cio/airq.c
3 * S/390 common I/O routines -- support for adapter interruptions 3 * S/390 common I/O routines -- support for adapter interruptions
4 * 4 *
5 * $Revision: 1.12 $ 5 * $Revision: 1.15 $
6 * 6 *
7 * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, 7 * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
8 * IBM Corporation 8 * IBM Corporation
9 * Author(s): Ingo Adlung (adlung@de.ibm.com) 9 * Author(s): Ingo Adlung (adlung@de.ibm.com)
10 * Cornelia Huck (cohuck@de.ibm.com) 10 * Cornelia Huck (cornelia.huck@de.ibm.com)
11 * Arnd Bergmann (arndb@de.ibm.com) 11 * Arnd Bergmann (arndb@de.ibm.com)
12 */ 12 */
13 13
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index daf21e03b21d..72f27c151c09 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -1,12 +1,12 @@
1/* 1/*
2 * drivers/s390/cio/blacklist.c 2 * drivers/s390/cio/blacklist.c
3 * S/390 common I/O routines -- blacklisting of specific devices 3 * S/390 common I/O routines -- blacklisting of specific devices
4 * $Revision: 1.39 $ 4 * $Revision: 1.42 $
5 * 5 *
6 * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, 6 * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
7 * IBM Corporation 7 * IBM Corporation
8 * Author(s): Ingo Adlung (adlung@de.ibm.com) 8 * Author(s): Ingo Adlung (adlung@de.ibm.com)
9 * Cornelia Huck (cohuck@de.ibm.com) 9 * Cornelia Huck (cornelia.huck@de.ibm.com)
10 * Arnd Bergmann (arndb@de.ibm.com) 10 * Arnd Bergmann (arndb@de.ibm.com)
11 */ 11 */
12 12
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index e849289d4f3c..6c077ad71edc 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -1,12 +1,12 @@
1/* 1/*
2 * drivers/s390/cio/ccwgroup.c 2 * drivers/s390/cio/ccwgroup.c
3 * bus driver for ccwgroup 3 * bus driver for ccwgroup
4 * $Revision: 1.33 $ 4 * $Revision: 1.35 $
5 * 5 *
6 * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, 6 * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
7 * IBM Corporation 7 * IBM Corporation
8 * Author(s): Arnd Bergmann (arndb@de.ibm.com) 8 * Author(s): Arnd Bergmann (arndb@de.ibm.com)
9 * Cornelia Huck (cohuck@de.ibm.com) 9 * Cornelia Huck (cornelia.huck@de.ibm.com)
10 */ 10 */
11#include <linux/module.h> 11#include <linux/module.h>
12#include <linux/errno.h> 12#include <linux/errno.h>
@@ -52,11 +52,7 @@ ccwgroup_uevent (struct device *dev, char **envp, int num_envp, char *buffer,
52 return 0; 52 return 0;
53} 53}
54 54
55static struct bus_type ccwgroup_bus_type = { 55static struct bus_type ccwgroup_bus_type;
56 .name = "ccwgroup",
57 .match = ccwgroup_bus_match,
58 .uevent = ccwgroup_uevent,
59};
60 56
61static inline void 57static inline void
62__ccwgroup_remove_symlinks(struct ccwgroup_device *gdev) 58__ccwgroup_remove_symlinks(struct ccwgroup_device *gdev)
@@ -389,6 +385,14 @@ ccwgroup_remove (struct device *dev)
389 return 0; 385 return 0;
390} 386}
391 387
388static struct bus_type ccwgroup_bus_type = {
389 .name = "ccwgroup",
390 .match = ccwgroup_bus_match,
391 .uevent = ccwgroup_uevent,
392 .probe = ccwgroup_probe,
393 .remove = ccwgroup_remove,
394};
395
392int 396int
393ccwgroup_driver_register (struct ccwgroup_driver *cdriver) 397ccwgroup_driver_register (struct ccwgroup_driver *cdriver)
394{ 398{
@@ -396,8 +400,6 @@ ccwgroup_driver_register (struct ccwgroup_driver *cdriver)
396 cdriver->driver = (struct device_driver) { 400 cdriver->driver = (struct device_driver) {
397 .bus = &ccwgroup_bus_type, 401 .bus = &ccwgroup_bus_type,
398 .name = cdriver->name, 402 .name = cdriver->name,
399 .probe = ccwgroup_probe,
400 .remove = ccwgroup_remove,
401 }; 403 };
402 404
403 return driver_register(&cdriver->driver); 405 return driver_register(&cdriver->driver);
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index 7270808c02d1..2cbb724791a8 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -1,12 +1,12 @@
1/* 1/*
2 * drivers/s390/cio/chsc.c 2 * drivers/s390/cio/chsc.c
3 * S/390 common I/O routines -- channel subsystem call 3 * S/390 common I/O routines -- channel subsystem call
4 * $Revision: 1.126 $ 4 * $Revision: 1.128 $
5 * 5 *
6 * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, 6 * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
7 * IBM Corporation 7 * IBM Corporation
8 * Author(s): Ingo Adlung (adlung@de.ibm.com) 8 * Author(s): Ingo Adlung (adlung@de.ibm.com)
9 * Cornelia Huck (cohuck@de.ibm.com) 9 * Cornelia Huck (cornelia.huck@de.ibm.com)
10 * Arnd Bergmann (arndb@de.ibm.com) 10 * Arnd Bergmann (arndb@de.ibm.com)
11 */ 11 */
12 12
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 7376bc87206d..6223b06d27d5 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -1,12 +1,12 @@
1/* 1/*
2 * drivers/s390/cio/cio.c 2 * drivers/s390/cio/cio.c
3 * S/390 common I/O routines -- low level i/o calls 3 * S/390 common I/O routines -- low level i/o calls
4 * $Revision: 1.138 $ 4 * $Revision: 1.140 $
5 * 5 *
6 * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, 6 * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
7 * IBM Corporation 7 * IBM Corporation
8 * Author(s): Ingo Adlung (adlung@de.ibm.com) 8 * Author(s): Ingo Adlung (adlung@de.ibm.com)
9 * Cornelia Huck (cohuck@de.ibm.com) 9 * Cornelia Huck (cornelia.huck@de.ibm.com)
10 * Arnd Bergmann (arndb@de.ibm.com) 10 * Arnd Bergmann (arndb@de.ibm.com)
11 * Martin Schwidefsky (schwidefsky@de.ibm.com) 11 * Martin Schwidefsky (schwidefsky@de.ibm.com)
12 */ 12 */
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index e565193650c7..516108779f60 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -1,12 +1,12 @@
1/* 1/*
2 * drivers/s390/cio/css.c 2 * drivers/s390/cio/css.c
3 * driver for channel subsystem 3 * driver for channel subsystem
4 * $Revision: 1.93 $ 4 * $Revision: 1.96 $
5 * 5 *
6 * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, 6 * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
7 * IBM Corporation 7 * IBM Corporation
8 * Author(s): Arnd Bergmann (arndb@de.ibm.com) 8 * Author(s): Arnd Bergmann (arndb@de.ibm.com)
9 * Cornelia Huck (cohuck@de.ibm.com) 9 * Cornelia Huck (cornelia.huck@de.ibm.com)
10 */ 10 */
11#include <linux/module.h> 11#include <linux/module.h>
12#include <linux/init.h> 12#include <linux/init.h>
@@ -542,9 +542,41 @@ css_bus_match (struct device *dev, struct device_driver *drv)
542 return 0; 542 return 0;
543} 543}
544 544
545static int
546css_probe (struct device *dev)
547{
548 struct subchannel *sch;
549
550 sch = to_subchannel(dev);
551 sch->driver = container_of (dev->driver, struct css_driver, drv);
552 return (sch->driver->probe ? sch->driver->probe(sch) : 0);
553}
554
555static int
556css_remove (struct device *dev)
557{
558 struct subchannel *sch;
559
560 sch = to_subchannel(dev);
561 return (sch->driver->remove ? sch->driver->remove(sch) : 0);
562}
563
564static void
565css_shutdown (struct device *dev)
566{
567 struct subchannel *sch;
568
569 sch = to_subchannel(dev);
570 if (sch->driver->shutdown)
571 sch->driver->shutdown(sch);
572}
573
545struct bus_type css_bus_type = { 574struct bus_type css_bus_type = {
546 .name = "css", 575 .name = "css",
547 .match = &css_bus_match, 576 .match = css_bus_match,
577 .probe = css_probe,
578 .remove = css_remove,
579 .shutdown = css_shutdown,
548}; 580};
549 581
550subsys_initcall(init_channel_subsystem); 582subsys_initcall(init_channel_subsystem);
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
index 251ebd7a7d3a..b6375861cb37 100644
--- a/drivers/s390/cio/css.h
+++ b/drivers/s390/cio/css.h
@@ -115,6 +115,7 @@ struct ccw_device_private {
115 * Currently, we only care about I/O subchannels (type 0), these 115 * Currently, we only care about I/O subchannels (type 0), these
116 * have a ccw_device connected to them. 116 * have a ccw_device connected to them.
117 */ 117 */
118struct subchannel;
118struct css_driver { 119struct css_driver {
119 unsigned int subchannel_type; 120 unsigned int subchannel_type;
120 struct device_driver drv; 121 struct device_driver drv;
@@ -122,6 +123,9 @@ struct css_driver {
122 int (*notify)(struct device *, int); 123 int (*notify)(struct device *, int);
123 void (*verify)(struct device *); 124 void (*verify)(struct device *);
124 void (*termination)(struct device *); 125 void (*termination)(struct device *);
126 int (*probe)(struct subchannel *);
127 int (*remove)(struct subchannel *);
128 void (*shutdown)(struct subchannel *);
125}; 129};
126 130
127/* 131/*
@@ -143,7 +147,7 @@ extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *);
143struct channel_subsystem { 147struct channel_subsystem {
144 u8 cssid; 148 u8 cssid;
145 int valid; 149 int valid;
146 struct channel_path *chps[__MAX_CHPID]; 150 struct channel_path *chps[__MAX_CHPID + 1];
147 struct device device; 151 struct device device;
148 struct pgid global_pgid; 152 struct pgid global_pgid;
149}; 153};
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index fa3e4c0a2536..a67e7e60e330 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -1,12 +1,12 @@
1/* 1/*
2 * drivers/s390/cio/device.c 2 * drivers/s390/cio/device.c
3 * bus driver for ccw devices 3 * bus driver for ccw devices
4 * $Revision: 1.137 $ 4 * $Revision: 1.140 $
5 * 5 *
6 * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, 6 * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
7 * IBM Corporation 7 * IBM Corporation
8 * Author(s): Arnd Bergmann (arndb@de.ibm.com) 8 * Author(s): Arnd Bergmann (arndb@de.ibm.com)
9 * Cornelia Huck (cohuck@de.ibm.com) 9 * Cornelia Huck (cornelia.huck@de.ibm.com)
10 * Martin Schwidefsky (schwidefsky@de.ibm.com) 10 * Martin Schwidefsky (schwidefsky@de.ibm.com)
11 */ 11 */
12#include <linux/config.h> 12#include <linux/config.h>
@@ -107,33 +107,29 @@ ccw_uevent (struct device *dev, char **envp, int num_envp,
107 return 0; 107 return 0;
108} 108}
109 109
110struct bus_type ccw_bus_type = { 110struct bus_type ccw_bus_type;
111 .name = "ccw",
112 .match = &ccw_bus_match,
113 .uevent = &ccw_uevent,
114};
115 111
116static int io_subchannel_probe (struct device *); 112static int io_subchannel_probe (struct subchannel *);
117static int io_subchannel_remove (struct device *); 113static int io_subchannel_remove (struct subchannel *);
118void io_subchannel_irq (struct device *); 114void io_subchannel_irq (struct device *);
119static int io_subchannel_notify(struct device *, int); 115static int io_subchannel_notify(struct device *, int);
120static void io_subchannel_verify(struct device *); 116static void io_subchannel_verify(struct device *);
121static void io_subchannel_ioterm(struct device *); 117static void io_subchannel_ioterm(struct device *);
122static void io_subchannel_shutdown(struct device *); 118static void io_subchannel_shutdown(struct subchannel *);
123 119
124struct css_driver io_subchannel_driver = { 120struct css_driver io_subchannel_driver = {
125 .subchannel_type = SUBCHANNEL_TYPE_IO, 121 .subchannel_type = SUBCHANNEL_TYPE_IO,
126 .drv = { 122 .drv = {
127 .name = "io_subchannel", 123 .name = "io_subchannel",
128 .bus = &css_bus_type, 124 .bus = &css_bus_type,
129 .probe = &io_subchannel_probe,
130 .remove = &io_subchannel_remove,
131 .shutdown = &io_subchannel_shutdown,
132 }, 125 },
133 .irq = io_subchannel_irq, 126 .irq = io_subchannel_irq,
134 .notify = io_subchannel_notify, 127 .notify = io_subchannel_notify,
135 .verify = io_subchannel_verify, 128 .verify = io_subchannel_verify,
136 .termination = io_subchannel_ioterm, 129 .termination = io_subchannel_ioterm,
130 .probe = io_subchannel_probe,
131 .remove = io_subchannel_remove,
132 .shutdown = io_subchannel_shutdown,
137}; 133};
138 134
139struct workqueue_struct *ccw_device_work; 135struct workqueue_struct *ccw_device_work;
@@ -803,14 +799,12 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch)
803} 799}
804 800
805static int 801static int
806io_subchannel_probe (struct device *pdev) 802io_subchannel_probe (struct subchannel *sch)
807{ 803{
808 struct subchannel *sch;
809 struct ccw_device *cdev; 804 struct ccw_device *cdev;
810 int rc; 805 int rc;
811 unsigned long flags; 806 unsigned long flags;
812 807
813 sch = to_subchannel(pdev);
814 if (sch->dev.driver_data) { 808 if (sch->dev.driver_data) {
815 /* 809 /*
816 * This subchannel already has an associated ccw_device. 810 * This subchannel already has an associated ccw_device.
@@ -846,7 +840,7 @@ io_subchannel_probe (struct device *pdev)
846 memset(cdev->private, 0, sizeof(struct ccw_device_private)); 840 memset(cdev->private, 0, sizeof(struct ccw_device_private));
847 atomic_set(&cdev->private->onoff, 0); 841 atomic_set(&cdev->private->onoff, 0);
848 cdev->dev = (struct device) { 842 cdev->dev = (struct device) {
849 .parent = pdev, 843 .parent = &sch->dev,
850 .release = ccw_device_release, 844 .release = ccw_device_release,
851 }; 845 };
852 INIT_LIST_HEAD(&cdev->private->kick_work.entry); 846 INIT_LIST_HEAD(&cdev->private->kick_work.entry);
@@ -859,7 +853,7 @@ io_subchannel_probe (struct device *pdev)
859 return -ENODEV; 853 return -ENODEV;
860 } 854 }
861 855
862 rc = io_subchannel_recog(cdev, to_subchannel(pdev)); 856 rc = io_subchannel_recog(cdev, sch);
863 if (rc) { 857 if (rc) {
864 spin_lock_irqsave(&sch->lock, flags); 858 spin_lock_irqsave(&sch->lock, flags);
865 sch->dev.driver_data = NULL; 859 sch->dev.driver_data = NULL;
@@ -883,17 +877,17 @@ ccw_device_unregister(void *data)
883} 877}
884 878
885static int 879static int
886io_subchannel_remove (struct device *dev) 880io_subchannel_remove (struct subchannel *sch)
887{ 881{
888 struct ccw_device *cdev; 882 struct ccw_device *cdev;
889 unsigned long flags; 883 unsigned long flags;
890 884
891 if (!dev->driver_data) 885 if (!sch->dev.driver_data)
892 return 0; 886 return 0;
893 cdev = dev->driver_data; 887 cdev = sch->dev.driver_data;
894 /* Set ccw device to not operational and drop reference. */ 888 /* Set ccw device to not operational and drop reference. */
895 spin_lock_irqsave(cdev->ccwlock, flags); 889 spin_lock_irqsave(cdev->ccwlock, flags);
896 dev->driver_data = NULL; 890 sch->dev.driver_data = NULL;
897 cdev->private->state = DEV_STATE_NOT_OPER; 891 cdev->private->state = DEV_STATE_NOT_OPER;
898 spin_unlock_irqrestore(cdev->ccwlock, flags); 892 spin_unlock_irqrestore(cdev->ccwlock, flags);
899 /* 893 /*
@@ -948,14 +942,12 @@ io_subchannel_ioterm(struct device *dev)
948} 942}
949 943
950static void 944static void
951io_subchannel_shutdown(struct device *dev) 945io_subchannel_shutdown(struct subchannel *sch)
952{ 946{
953 struct subchannel *sch;
954 struct ccw_device *cdev; 947 struct ccw_device *cdev;
955 int ret; 948 int ret;
956 949
957 sch = to_subchannel(dev); 950 cdev = sch->dev.driver_data;
958 cdev = dev->driver_data;
959 951
960 if (cio_is_console(sch->schid)) 952 if (cio_is_console(sch->schid))
961 return; 953 return;
@@ -1129,6 +1121,14 @@ ccw_device_remove (struct device *dev)
1129 return 0; 1121 return 0;
1130} 1122}
1131 1123
1124struct bus_type ccw_bus_type = {
1125 .name = "ccw",
1126 .match = ccw_bus_match,
1127 .uevent = ccw_uevent,
1128 .probe = ccw_device_probe,
1129 .remove = ccw_device_remove,
1130};
1131
1132int 1132int
1133ccw_driver_register (struct ccw_driver *cdriver) 1133ccw_driver_register (struct ccw_driver *cdriver)
1134{ 1134{
@@ -1136,8 +1136,6 @@ ccw_driver_register (struct ccw_driver *cdriver)
1136 1136
1137 drv->bus = &ccw_bus_type; 1137 drv->bus = &ccw_bus_type;
1138 drv->name = cdriver->name; 1138 drv->name = cdriver->name;
1139 drv->probe = ccw_device_probe;
1140 drv->remove = ccw_device_remove;
1141 1139
1142 return driver_register(drv); 1140 return driver_register(drv);
1143} 1141}
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 23d12b65e5fa..b302779e7cff 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -4,7 +4,7 @@
4 * 4 *
5 * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, 5 * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
6 * IBM Corporation 6 * IBM Corporation
7 * Author(s): Cornelia Huck(cohuck@de.ibm.com) 7 * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com)
8 * Martin Schwidefsky (schwidefsky@de.ibm.com) 8 * Martin Schwidefsky (schwidefsky@de.ibm.com)
9 */ 9 */
10 10
diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c
index 04ceba343db8..e60b2d8103b8 100644
--- a/drivers/s390/cio/device_id.c
+++ b/drivers/s390/cio/device_id.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, 4 * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
5 * IBM Corporation 5 * IBM Corporation
6 * Author(s): Cornelia Huck(cohuck@de.ibm.com) 6 * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com)
7 * Martin Schwidefsky (schwidefsky@de.ibm.com) 7 * Martin Schwidefsky (schwidefsky@de.ibm.com)
8 * 8 *
9 * Sense ID functions. 9 * Sense ID functions.
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index 143b6c25a4e6..8b0218949b62 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -1,12 +1,12 @@
1/* 1/*
2 * drivers/s390/cio/device_ops.c 2 * drivers/s390/cio/device_ops.c
3 * 3 *
4 * $Revision: 1.58 $ 4 * $Revision: 1.61 $
5 * 5 *
6 * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, 6 * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
7 * IBM Corporation 7 * IBM Corporation
8 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) 8 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
9 * Cornelia Huck (cohuck@de.ibm.com) 9 * Cornelia Huck (cornelia.huck@de.ibm.com)
10 */ 10 */
11#include <linux/config.h> 11#include <linux/config.h>
12#include <linux/module.h> 12#include <linux/module.h>
diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c
index 052832d03d38..d2a5b04d7cba 100644
--- a/drivers/s390/cio/device_pgid.c
+++ b/drivers/s390/cio/device_pgid.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, 4 * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
5 * IBM Corporation 5 * IBM Corporation
6 * Author(s): Cornelia Huck(cohuck@de.ibm.com) 6 * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com)
7 * Martin Schwidefsky (schwidefsky@de.ibm.com) 7 * Martin Schwidefsky (schwidefsky@de.ibm.com)
8 * 8 *
9 * Path Group ID functions. 9 * Path Group ID functions.
diff --git a/drivers/s390/cio/device_status.c b/drivers/s390/cio/device_status.c
index db09c209098b..dad4dd9887c9 100644
--- a/drivers/s390/cio/device_status.c
+++ b/drivers/s390/cio/device_status.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, 4 * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
5 * IBM Corporation 5 * IBM Corporation
6 * Author(s): Cornelia Huck(cohuck@de.ibm.com) 6 * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com)
7 * Martin Schwidefsky (schwidefsky@de.ibm.com) 7 * Martin Schwidefsky (schwidefsky@de.ibm.com)
8 * 8 *
9 * Status accumulation and basic sense functions. 9 * Status accumulation and basic sense functions.
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index 30a836ffc31f..77be2c39bfe4 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -7,7 +7,7 @@
7 * 7 *
8 * Copyright 2000,2002 IBM Corporation 8 * Copyright 2000,2002 IBM Corporation
9 * Author(s): Utz Bacher <utz.bacher@de.ibm.com> 9 * Author(s): Utz Bacher <utz.bacher@de.ibm.com>
10 * 2.6 cio integration by Cornelia Huck <cohuck@de.ibm.com> 10 * 2.6 cio integration by Cornelia Huck <cornelia.huck@de.ibm.com>
11 * 11 *
12 * Restriction: only 63 iqdio subchannels would have its own indicator, 12 * Restriction: only 63 iqdio subchannels would have its own indicator,
13 * after that, subsequent subchannels share one indicator 13 * after that, subsequent subchannels share one indicator
@@ -56,7 +56,7 @@
56#include "ioasm.h" 56#include "ioasm.h"
57#include "chsc.h" 57#include "chsc.h"
58 58
59#define VERSION_QDIO_C "$Revision: 1.114 $" 59#define VERSION_QDIO_C "$Revision: 1.117 $"
60 60
61/****************** MODULE PARAMETER VARIABLES ********************/ 61/****************** MODULE PARAMETER VARIABLES ********************/
62MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>"); 62MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c
index 0db4f57a6a95..1901feef07d9 100644
--- a/drivers/s390/net/ctcmain.c
+++ b/drivers/s390/net/ctcmain.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: ctcmain.c,v 1.78 2005/09/07 12:18:02 pavlic Exp $ 2 * $Id: ctcmain.c,v 1.79 2006/01/11 11:32:18 cohuck Exp $
3 * 3 *
4 * CTC / ESCON network driver 4 * CTC / ESCON network driver
5 * 5 *
@@ -8,7 +8,7 @@
8 * Fixes by : Jochen Röhrig (roehrig@de.ibm.com) 8 * Fixes by : Jochen Röhrig (roehrig@de.ibm.com)
9 * Arnaldo Carvalho de Melo <acme@conectiva.com.br> 9 * Arnaldo Carvalho de Melo <acme@conectiva.com.br>
10 Peter Tiedemann (ptiedem@de.ibm.com) 10 Peter Tiedemann (ptiedem@de.ibm.com)
11 * Driver Model stuff by : Cornelia Huck <cohuck@de.ibm.com> 11 * Driver Model stuff by : Cornelia Huck <huckc@de.ibm.com>
12 * 12 *
13 * Documentation used: 13 * Documentation used:
14 * - Principles of Operation (IBM doc#: SA22-7201-06) 14 * - Principles of Operation (IBM doc#: SA22-7201-06)
@@ -37,7 +37,7 @@
37 * along with this program; if not, write to the Free Software 37 * along with this program; if not, write to the Free Software
38 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 38 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
39 * 39 *
40 * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.78 $ 40 * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.79 $
41 * 41 *
42 */ 42 */
43#undef DEBUG 43#undef DEBUG
@@ -248,7 +248,7 @@ static void
248print_banner(void) 248print_banner(void)
249{ 249{
250 static int printed = 0; 250 static int printed = 0;
251 char vbuf[] = "$Revision: 1.78 $"; 251 char vbuf[] = "$Revision: 1.79 $";
252 char *version = vbuf; 252 char *version = vbuf;
253 253
254 if (printed) 254 if (printed)
diff --git a/drivers/s390/net/cu3088.c b/drivers/s390/net/cu3088.c
index 77dacb465732..2014fb7a4881 100644
--- a/drivers/s390/net/cu3088.c
+++ b/drivers/s390/net/cu3088.c
@@ -1,11 +1,11 @@
1/* 1/*
2 * $Id: cu3088.c,v 1.36 2005/10/25 14:37:17 cohuck Exp $ 2 * $Id: cu3088.c,v 1.38 2006/01/12 14:33:09 cohuck Exp $
3 * 3 *
4 * CTC / LCS ccw_device driver 4 * CTC / LCS ccw_device driver
5 * 5 *
6 * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation 6 * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
7 * Author(s): Arnd Bergmann <arndb@de.ibm.com> 7 * Author(s): Arnd Bergmann <arndb@de.ibm.com>
8 * Cornelia Huck <cohuck@de.ibm.com> 8 * Cornelia Huck <cornelia.huck@de.ibm.com>
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by 11 * it under the terms of the GNU General Public License as published by
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index 69425a7a6e98..ac4c4b83fe17 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -1,12 +1,13 @@
1/* 1/*
2 * $Id: netiucv.c,v 1.66 2005/05/11 08:10:17 holzheu Exp $ 2 * $Id: netiucv.c,v 1.69 2006/01/12 14:33:09 cohuck Exp $
3 * 3 *
4 * IUCV network driver 4 * IUCV network driver
5 * 5 *
6 * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation 6 * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
7 * Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com) 7 * Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
8 * 8 *
9 * Driverfs integration and all bugs therein by Cornelia Huck(cohuck@de.ibm.com) 9 * Sysfs integration and all bugs therein by Cornelia Huck
10 * (cornelia.huck@de.ibm.com)
10 * 11 *
11 * Documentation used: 12 * Documentation used:
12 * the source of the original IUCV driver by: 13 * the source of the original IUCV driver by:
@@ -30,7 +31,7 @@
30 * along with this program; if not, write to the Free Software 31 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 32 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32 * 33 *
33 * RELEASE-TAG: IUCV network driver $Revision: 1.66 $ 34 * RELEASE-TAG: IUCV network driver $Revision: 1.69 $
34 * 35 *
35 */ 36 */
36 37
@@ -2076,7 +2077,7 @@ DRIVER_ATTR(remove, 0200, NULL, remove_write);
2076static void 2077static void
2077netiucv_banner(void) 2078netiucv_banner(void)
2078{ 2079{
2079 char vbuf[] = "$Revision: 1.66 $"; 2080 char vbuf[] = "$Revision: 1.69 $";
2080 char *version = vbuf; 2081 char *version = vbuf;
2081 2082
2082 if ((version = strchr(version, ':'))) { 2083 if ((version = strchr(version, ':'))) {
diff --git a/drivers/s390/s390_rdev.c b/drivers/s390/s390_rdev.c
index 566cc3d185b6..206518c7d332 100644
--- a/drivers/s390/s390_rdev.c
+++ b/drivers/s390/s390_rdev.c
@@ -1,11 +1,11 @@
1/* 1/*
2 * drivers/s390/s390_rdev.c 2 * drivers/s390/s390_rdev.c
3 * s390 root device 3 * s390 root device
4 * $Revision: 1.2 $ 4 * $Revision: 1.4 $
5 * 5 *
6 * Copyright (C) 2002, 2005 IBM Deutschland Entwicklung GmbH, 6 * Copyright (C) 2002, 2005 IBM Deutschland Entwicklung GmbH,
7 * IBM Corporation 7 * IBM Corporation
8 * Author(s): Cornelia Huck (cohuck@de.ibm.com) 8 * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com)
9 * Carsten Otte (cotte@de.ibm.com) 9 * Carsten Otte (cotte@de.ibm.com)
10 */ 10 */
11 11
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 5e84c5aa7779..167fef39d8a7 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -1125,6 +1125,8 @@ zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
1125 zfcp_free_low_mem_buffers(adapter); 1125 zfcp_free_low_mem_buffers(adapter);
1126 /* free memory of adapter data structure and queues */ 1126 /* free memory of adapter data structure and queues */
1127 zfcp_qdio_free_queues(adapter); 1127 zfcp_qdio_free_queues(adapter);
1128 kfree(adapter->fc_stats);
1129 kfree(adapter->stats_reset_data);
1128 ZFCP_LOG_TRACE("freeing adapter structure\n"); 1130 ZFCP_LOG_TRACE("freeing adapter structure\n");
1129 kfree(adapter); 1131 kfree(adapter);
1130 out: 1132 out:
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index d81b737d68cc..9bb511083a26 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -921,7 +921,6 @@ struct zfcp_adapter {
921 u32 physical_s_id; /* local FC port ID */ 921 u32 physical_s_id; /* local FC port ID */
922 struct ccw_device *ccw_device; /* S/390 ccw device */ 922 struct ccw_device *ccw_device; /* S/390 ccw device */
923 u8 fc_service_class; 923 u8 fc_service_class;
924 u32 fc_topology; /* FC topology */
925 u32 hydra_version; /* Hydra version */ 924 u32 hydra_version; /* Hydra version */
926 u32 fsf_lic_version; 925 u32 fsf_lic_version;
927 u32 adapter_features; /* FCP channel features */ 926 u32 adapter_features; /* FCP channel features */
@@ -978,6 +977,9 @@ struct zfcp_adapter {
978 struct zfcp_adapter_mempool pool; /* Adapter memory pools */ 977 struct zfcp_adapter_mempool pool; /* Adapter memory pools */
979 struct qdio_initialize qdio_init_data; /* for qdio_establish */ 978 struct qdio_initialize qdio_init_data; /* for qdio_establish */
980 struct device generic_services; /* directory for WKA ports */ 979 struct device generic_services; /* directory for WKA ports */
980 struct fc_host_statistics *fc_stats;
981 struct fsf_qtcb_bottom_port *stats_reset_data;
982 unsigned long stats_reset;
981}; 983};
982 984
983/* 985/*
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index ee7314d8c2da..7bdb00b5aeb2 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -2613,7 +2613,7 @@ zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action)
2613 case ZFCP_ERP_STEP_UNINITIALIZED: 2613 case ZFCP_ERP_STEP_UNINITIALIZED:
2614 case ZFCP_ERP_STEP_PHYS_PORT_CLOSING: 2614 case ZFCP_ERP_STEP_PHYS_PORT_CLOSING:
2615 case ZFCP_ERP_STEP_PORT_CLOSING: 2615 case ZFCP_ERP_STEP_PORT_CLOSING:
2616 if (adapter->fc_topology == FSF_TOPO_P2P) { 2616 if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP) {
2617 if (port->wwpn != adapter->peer_wwpn) { 2617 if (port->wwpn != adapter->peer_wwpn) {
2618 ZFCP_LOG_NORMAL("Failed to open port 0x%016Lx " 2618 ZFCP_LOG_NORMAL("Failed to open port 0x%016Lx "
2619 "on adapter %s.\nPeer WWPN " 2619 "on adapter %s.\nPeer WWPN "
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 59587951c847..cbfab09899c8 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -964,6 +964,40 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
964 | ZFCP_STATUS_COMMON_ERP_FAILED); 964 | ZFCP_STATUS_COMMON_ERP_FAILED);
965 break; 965 break;
966 966
967 case FSF_STATUS_READ_NOTIFICATION_LOST:
968 ZFCP_LOG_NORMAL("Unsolicited status notification(s) lost: "
969 "adapter %s%s%s%s%s%s%s%s%s\n",
970 zfcp_get_busid_by_adapter(adapter),
971 (status_buffer->status_subtype &
972 FSF_STATUS_READ_SUB_INCOMING_ELS) ?
973 ", incoming ELS" : "",
974 (status_buffer->status_subtype &
975 FSF_STATUS_READ_SUB_SENSE_DATA) ?
976 ", sense data" : "",
977 (status_buffer->status_subtype &
978 FSF_STATUS_READ_SUB_LINK_STATUS) ?
979 ", link status change" : "",
980 (status_buffer->status_subtype &
981 FSF_STATUS_READ_SUB_PORT_CLOSED) ?
982 ", port close" : "",
983 (status_buffer->status_subtype &
984 FSF_STATUS_READ_SUB_BIT_ERROR_THRESHOLD) ?
985 ", bit error exception" : "",
986 (status_buffer->status_subtype &
987 FSF_STATUS_READ_SUB_ACT_UPDATED) ?
988 ", ACT update" : "",
989 (status_buffer->status_subtype &
990 FSF_STATUS_READ_SUB_ACT_HARDENED) ?
991 ", ACT hardening" : "",
992 (status_buffer->status_subtype &
993 FSF_STATUS_READ_SUB_FEATURE_UPDATE_ALERT) ?
994 ", adapter feature change" : "");
995
996 if (status_buffer->status_subtype &
997 FSF_STATUS_READ_SUB_ACT_UPDATED)
998 zfcp_erp_adapter_access_changed(adapter);
999 break;
1000
967 case FSF_STATUS_READ_CFDC_UPDATED: 1001 case FSF_STATUS_READ_CFDC_UPDATED:
968 ZFCP_LOG_NORMAL("CFDC has been updated on the adapter %s\n", 1002 ZFCP_LOG_NORMAL("CFDC has been updated on the adapter %s\n",
969 zfcp_get_busid_by_adapter(adapter)); 1003 zfcp_get_busid_by_adapter(adapter));
@@ -1954,6 +1988,7 @@ zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
1954 erp_action->fsf_req->qtcb->bottom.config.feature_selection = 1988 erp_action->fsf_req->qtcb->bottom.config.feature_selection =
1955 FSF_FEATURE_CFDC | 1989 FSF_FEATURE_CFDC |
1956 FSF_FEATURE_LUN_SHARING | 1990 FSF_FEATURE_LUN_SHARING |
1991 FSF_FEATURE_NOTIFICATION_LOST |
1957 FSF_FEATURE_UPDATE_ALERT; 1992 FSF_FEATURE_UPDATE_ALERT;
1958 1993
1959 /* start QDIO request for this FSF request */ 1994 /* start QDIO request for this FSF request */
@@ -2008,27 +2043,30 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
2008 fc_host_port_id(shost) = bottom->s_id & ZFCP_DID_MASK; 2043 fc_host_port_id(shost) = bottom->s_id & ZFCP_DID_MASK;
2009 fc_host_speed(shost) = bottom->fc_link_speed; 2044 fc_host_speed(shost) = bottom->fc_link_speed;
2010 fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3; 2045 fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3;
2011 adapter->fc_topology = bottom->fc_topology;
2012 adapter->hydra_version = bottom->adapter_type; 2046 adapter->hydra_version = bottom->adapter_type;
2013 if (adapter->physical_wwpn == 0) 2047 if (fc_host_permanent_port_name(shost) == -1)
2014 adapter->physical_wwpn = fc_host_port_name(shost); 2048 fc_host_permanent_port_name(shost) =
2015 if (adapter->physical_s_id == 0) 2049 fc_host_port_name(shost);
2016 adapter->physical_s_id = fc_host_port_id(shost); 2050 if (bottom->fc_topology == FSF_TOPO_P2P) {
2051 adapter->peer_d_id = bottom->peer_d_id & ZFCP_DID_MASK;
2052 adapter->peer_wwpn = bottom->plogi_payload.wwpn;
2053 adapter->peer_wwnn = bottom->plogi_payload.wwnn;
2054 fc_host_port_type(shost) = FC_PORTTYPE_PTP;
2055 } else if (bottom->fc_topology == FSF_TOPO_FABRIC)
2056 fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
2057 else if (bottom->fc_topology == FSF_TOPO_AL)
2058 fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
2059 else
2060 fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
2017 } else { 2061 } else {
2018 fc_host_node_name(shost) = 0; 2062 fc_host_node_name(shost) = 0;
2019 fc_host_port_name(shost) = 0; 2063 fc_host_port_name(shost) = 0;
2020 fc_host_port_id(shost) = 0; 2064 fc_host_port_id(shost) = 0;
2021 fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; 2065 fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
2022 adapter->fc_topology = 0; 2066 fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
2023 adapter->hydra_version = 0; 2067 adapter->hydra_version = 0;
2024 } 2068 }
2025 2069
2026 if (adapter->fc_topology == FSF_TOPO_P2P) {
2027 adapter->peer_d_id = bottom->peer_d_id & ZFCP_DID_MASK;
2028 adapter->peer_wwpn = bottom->plogi_payload.wwpn;
2029 adapter->peer_wwnn = bottom->plogi_payload.wwnn;
2030 }
2031
2032 if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT) { 2070 if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT) {
2033 adapter->hardware_version = bottom->hardware_version; 2071 adapter->hardware_version = bottom->hardware_version;
2034 memcpy(fc_host_serial_number(shost), bottom->serial_number, 2072 memcpy(fc_host_serial_number(shost), bottom->serial_number,
@@ -2097,8 +2135,8 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
2097 if (zfcp_fsf_exchange_config_evaluate(fsf_req, 1)) 2135 if (zfcp_fsf_exchange_config_evaluate(fsf_req, 1))
2098 return -EIO; 2136 return -EIO;
2099 2137
2100 switch (adapter->fc_topology) { 2138 switch (fc_host_port_type(adapter->scsi_host)) {
2101 case FSF_TOPO_P2P: 2139 case FC_PORTTYPE_PTP:
2102 ZFCP_LOG_NORMAL("Point-to-Point fibrechannel " 2140 ZFCP_LOG_NORMAL("Point-to-Point fibrechannel "
2103 "configuration detected at adapter %s\n" 2141 "configuration detected at adapter %s\n"
2104 "Peer WWNN 0x%016llx, " 2142 "Peer WWNN 0x%016llx, "
@@ -2111,7 +2149,7 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
2111 debug_text_event(fsf_req->adapter->erp_dbf, 0, 2149 debug_text_event(fsf_req->adapter->erp_dbf, 0,
2112 "top-p-to-p"); 2150 "top-p-to-p");
2113 break; 2151 break;
2114 case FSF_TOPO_AL: 2152 case FC_PORTTYPE_NLPORT:
2115 ZFCP_LOG_NORMAL("error: Arbitrated loop fibrechannel " 2153 ZFCP_LOG_NORMAL("error: Arbitrated loop fibrechannel "
2116 "topology detected at adapter %s " 2154 "topology detected at adapter %s "
2117 "unsupported, shutting down adapter\n", 2155 "unsupported, shutting down adapter\n",
@@ -2120,7 +2158,7 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
2120 "top-al"); 2158 "top-al");
2121 zfcp_erp_adapter_shutdown(adapter, 0); 2159 zfcp_erp_adapter_shutdown(adapter, 0);
2122 return -EIO; 2160 return -EIO;
2123 case FSF_TOPO_FABRIC: 2161 case FC_PORTTYPE_NPORT:
2124 ZFCP_LOG_NORMAL("Switched fabric fibrechannel " 2162 ZFCP_LOG_NORMAL("Switched fabric fibrechannel "
2125 "network detected at adapter %s.\n", 2163 "network detected at adapter %s.\n",
2126 zfcp_get_busid_by_adapter(adapter)); 2164 zfcp_get_busid_by_adapter(adapter));
@@ -2133,7 +2171,6 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
2133 "of a type known to the zfcp " 2171 "of a type known to the zfcp "
2134 "driver, shutting down adapter\n", 2172 "driver, shutting down adapter\n",
2135 zfcp_get_busid_by_adapter(adapter)); 2173 zfcp_get_busid_by_adapter(adapter));
2136 adapter->fc_topology = FSF_TOPO_ERROR;
2137 debug_text_exception(fsf_req->adapter->erp_dbf, 0, 2174 debug_text_exception(fsf_req->adapter->erp_dbf, 0,
2138 "unknown-topo"); 2175 "unknown-topo");
2139 zfcp_erp_adapter_shutdown(adapter, 0); 2176 zfcp_erp_adapter_shutdown(adapter, 0);
@@ -2293,14 +2330,13 @@ zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req)
2293 data = (struct fsf_qtcb_bottom_port*) fsf_req->data; 2330 data = (struct fsf_qtcb_bottom_port*) fsf_req->data;
2294 if (data) 2331 if (data)
2295 memcpy(data, bottom, sizeof(struct fsf_qtcb_bottom_port)); 2332 memcpy(data, bottom, sizeof(struct fsf_qtcb_bottom_port));
2296 if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) { 2333 if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
2297 adapter->physical_wwpn = bottom->wwpn; 2334 fc_host_permanent_port_name(shost) = bottom->wwpn;
2298 adapter->physical_s_id = bottom->fc_port_id; 2335 else
2299 } else { 2336 fc_host_permanent_port_name(shost) =
2300 adapter->physical_wwpn = fc_host_port_name(shost); 2337 fc_host_port_name(shost);
2301 adapter->physical_s_id = fc_host_port_id(shost);
2302 }
2303 fc_host_maxframe_size(shost) = bottom->maximum_frame_size; 2338 fc_host_maxframe_size(shost) = bottom->maximum_frame_size;
2339 fc_host_supported_speeds(shost) = bottom->supported_speed;
2304 break; 2340 break;
2305 2341
2306 case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE: 2342 case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h
index 48719f055952..e734415cae6d 100644
--- a/drivers/s390/scsi/zfcp_fsf.h
+++ b/drivers/s390/scsi/zfcp_fsf.h
@@ -166,6 +166,7 @@
166#define FSF_STATUS_READ_BIT_ERROR_THRESHOLD 0x00000004 166#define FSF_STATUS_READ_BIT_ERROR_THRESHOLD 0x00000004
167#define FSF_STATUS_READ_LINK_DOWN 0x00000005 167#define FSF_STATUS_READ_LINK_DOWN 0x00000005
168#define FSF_STATUS_READ_LINK_UP 0x00000006 168#define FSF_STATUS_READ_LINK_UP 0x00000006
169#define FSF_STATUS_READ_NOTIFICATION_LOST 0x00000009
169#define FSF_STATUS_READ_CFDC_UPDATED 0x0000000A 170#define FSF_STATUS_READ_CFDC_UPDATED 0x0000000A
170#define FSF_STATUS_READ_CFDC_HARDENED 0x0000000B 171#define FSF_STATUS_READ_CFDC_HARDENED 0x0000000B
171#define FSF_STATUS_READ_FEATURE_UPDATE_ALERT 0x0000000C 172#define FSF_STATUS_READ_FEATURE_UPDATE_ALERT 0x0000000C
@@ -179,6 +180,16 @@
179#define FSF_STATUS_READ_SUB_FDISC_FAILED 0x00000001 180#define FSF_STATUS_READ_SUB_FDISC_FAILED 0x00000001
180#define FSF_STATUS_READ_SUB_FIRMWARE_UPDATE 0x00000002 181#define FSF_STATUS_READ_SUB_FIRMWARE_UPDATE 0x00000002
181 182
183/* status subtypes for unsolicited status notification lost */
184#define FSF_STATUS_READ_SUB_INCOMING_ELS 0x00000001
185#define FSF_STATUS_READ_SUB_SENSE_DATA 0x00000002
186#define FSF_STATUS_READ_SUB_LINK_STATUS 0x00000004
187#define FSF_STATUS_READ_SUB_PORT_CLOSED 0x00000008
188#define FSF_STATUS_READ_SUB_BIT_ERROR_THRESHOLD 0x00000010
189#define FSF_STATUS_READ_SUB_ACT_UPDATED 0x00000020
190#define FSF_STATUS_READ_SUB_ACT_HARDENED 0x00000040
191#define FSF_STATUS_READ_SUB_FEATURE_UPDATE_ALERT 0x00000080
192
182/* status subtypes for CFDC */ 193/* status subtypes for CFDC */
183#define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE 0x00000002 194#define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE 0x00000002
184#define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2 0x0000000F 195#define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2 0x0000000F
@@ -188,7 +199,6 @@
188#define FSF_TOPO_P2P 0x00000001 199#define FSF_TOPO_P2P 0x00000001
189#define FSF_TOPO_FABRIC 0x00000002 200#define FSF_TOPO_FABRIC 0x00000002
190#define FSF_TOPO_AL 0x00000003 201#define FSF_TOPO_AL 0x00000003
191#define FSF_TOPO_FABRIC_VIRT 0x00000004
192 202
193/* data direction for FCP commands */ 203/* data direction for FCP commands */
194#define FSF_DATADIR_WRITE 0x00000001 204#define FSF_DATADIR_WRITE 0x00000001
@@ -211,6 +221,7 @@
211/* channel features */ 221/* channel features */
212#define FSF_FEATURE_CFDC 0x00000002 222#define FSF_FEATURE_CFDC 0x00000002
213#define FSF_FEATURE_LUN_SHARING 0x00000004 223#define FSF_FEATURE_LUN_SHARING 0x00000004
224#define FSF_FEATURE_NOTIFICATION_LOST 0x00000008
214#define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010 225#define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010
215#define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020 226#define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020
216#define FSF_FEATURE_UPDATE_ALERT 0x00000100 227#define FSF_FEATURE_UPDATE_ALERT 0x00000100
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 66608d13a634..3c2cbcccbf54 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -49,8 +49,6 @@ static int zfcp_task_management_function(struct zfcp_unit *, u8,
49 49
50static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int, scsi_id_t, 50static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int, scsi_id_t,
51 scsi_lun_t); 51 scsi_lun_t);
52static struct zfcp_port *zfcp_port_lookup(struct zfcp_adapter *, int,
53 scsi_id_t);
54 52
55static struct device_attribute *zfcp_sysfs_sdev_attrs[]; 53static struct device_attribute *zfcp_sysfs_sdev_attrs[];
56 54
@@ -406,18 +404,6 @@ zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id,
406 return retval; 404 return retval;
407} 405}
408 406
409static struct zfcp_port *
410zfcp_port_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id)
411{
412 struct zfcp_port *port;
413
414 list_for_each_entry(port, &adapter->port_list_head, list) {
415 if (port->rport && (id == port->rport->scsi_target_id))
416 return port;
417 }
418 return (struct zfcp_port *) NULL;
419}
420
421/** 407/**
422 * zfcp_scsi_eh_abort_handler - abort the specified SCSI command 408 * zfcp_scsi_eh_abort_handler - abort the specified SCSI command
423 * @scpnt: pointer to scsi_cmnd to be aborted 409 * @scpnt: pointer to scsi_cmnd to be aborted
@@ -731,70 +717,164 @@ zfcp_fsf_start_scsi_er_timer(struct zfcp_adapter *adapter)
731/* 717/*
732 * Support functions for FC transport class 718 * Support functions for FC transport class
733 */ 719 */
734static void 720static struct fc_host_statistics*
735zfcp_get_port_id(struct scsi_target *starget) 721zfcp_init_fc_host_stats(struct zfcp_adapter *adapter)
736{ 722{
737 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 723 struct fc_host_statistics *fc_stats;
738 struct zfcp_adapter *adapter = (struct zfcp_adapter *)shost->hostdata[0];
739 struct zfcp_port *port;
740 unsigned long flags;
741 724
742 read_lock_irqsave(&zfcp_data.config_lock, flags); 725 if (!adapter->fc_stats) {
743 port = zfcp_port_lookup(adapter, starget->channel, starget->id); 726 fc_stats = kmalloc(sizeof(*fc_stats), GFP_KERNEL);
744 if (port) 727 if (!fc_stats)
745 fc_starget_port_id(starget) = port->d_id; 728 return NULL;
746 else 729 adapter->fc_stats = fc_stats; /* freed in adater_dequeue */
747 fc_starget_port_id(starget) = -1; 730 }
748 read_unlock_irqrestore(&zfcp_data.config_lock, flags); 731 memset(adapter->fc_stats, 0, sizeof(*adapter->fc_stats));
732 return adapter->fc_stats;
749} 733}
750 734
751static void 735static void
752zfcp_get_port_name(struct scsi_target *starget) 736zfcp_adjust_fc_host_stats(struct fc_host_statistics *fc_stats,
737 struct fsf_qtcb_bottom_port *data,
738 struct fsf_qtcb_bottom_port *old)
753{ 739{
754 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 740 fc_stats->seconds_since_last_reset = data->seconds_since_last_reset -
755 struct zfcp_adapter *adapter = (struct zfcp_adapter *)shost->hostdata[0]; 741 old->seconds_since_last_reset;
756 struct zfcp_port *port; 742 fc_stats->tx_frames = data->tx_frames - old->tx_frames;
757 unsigned long flags; 743 fc_stats->tx_words = data->tx_words - old->tx_words;
744 fc_stats->rx_frames = data->rx_frames - old->rx_frames;
745 fc_stats->rx_words = data->rx_words - old->rx_words;
746 fc_stats->lip_count = data->lip - old->lip;
747 fc_stats->nos_count = data->nos - old->nos;
748 fc_stats->error_frames = data->error_frames - old->error_frames;
749 fc_stats->dumped_frames = data->dumped_frames - old->dumped_frames;
750 fc_stats->link_failure_count = data->link_failure - old->link_failure;
751 fc_stats->loss_of_sync_count = data->loss_of_sync - old->loss_of_sync;
752 fc_stats->loss_of_signal_count = data->loss_of_signal -
753 old->loss_of_signal;
754 fc_stats->prim_seq_protocol_err_count = data->psp_error_counts -
755 old->psp_error_counts;
756 fc_stats->invalid_tx_word_count = data->invalid_tx_words -
757 old->invalid_tx_words;
758 fc_stats->invalid_crc_count = data->invalid_crcs - old->invalid_crcs;
759 fc_stats->fcp_input_requests = data->input_requests -
760 old->input_requests;
761 fc_stats->fcp_output_requests = data->output_requests -
762 old->output_requests;
763 fc_stats->fcp_control_requests = data->control_requests -
764 old->control_requests;
765 fc_stats->fcp_input_megabytes = data->input_mb - old->input_mb;
766 fc_stats->fcp_output_megabytes = data->output_mb - old->output_mb;
767}
758 768
759 read_lock_irqsave(&zfcp_data.config_lock, flags); 769static void
760 port = zfcp_port_lookup(adapter, starget->channel, starget->id); 770zfcp_set_fc_host_stats(struct fc_host_statistics *fc_stats,
761 if (port) 771 struct fsf_qtcb_bottom_port *data)
762 fc_starget_port_name(starget) = port->wwpn; 772{
763 else 773 fc_stats->seconds_since_last_reset = data->seconds_since_last_reset;
764 fc_starget_port_name(starget) = -1; 774 fc_stats->tx_frames = data->tx_frames;
765 read_unlock_irqrestore(&zfcp_data.config_lock, flags); 775 fc_stats->tx_words = data->tx_words;
776 fc_stats->rx_frames = data->rx_frames;
777 fc_stats->rx_words = data->rx_words;
778 fc_stats->lip_count = data->lip;
779 fc_stats->nos_count = data->nos;
780 fc_stats->error_frames = data->error_frames;
781 fc_stats->dumped_frames = data->dumped_frames;
782 fc_stats->link_failure_count = data->link_failure;
783 fc_stats->loss_of_sync_count = data->loss_of_sync;
784 fc_stats->loss_of_signal_count = data->loss_of_signal;
785 fc_stats->prim_seq_protocol_err_count = data->psp_error_counts;
786 fc_stats->invalid_tx_word_count = data->invalid_tx_words;
787 fc_stats->invalid_crc_count = data->invalid_crcs;
788 fc_stats->fcp_input_requests = data->input_requests;
789 fc_stats->fcp_output_requests = data->output_requests;
790 fc_stats->fcp_control_requests = data->control_requests;
791 fc_stats->fcp_input_megabytes = data->input_mb;
792 fc_stats->fcp_output_megabytes = data->output_mb;
793}
794
795/**
796 * zfcp_get_fc_host_stats - provide fc_host_statistics for scsi_transport_fc
797 *
798 * assumption: scsi_transport_fc synchronizes calls of
799 * get_fc_host_stats and reset_fc_host_stats
800 * (XXX to be checked otherwise introduce locking)
801 */
802static struct fc_host_statistics *
803zfcp_get_fc_host_stats(struct Scsi_Host *shost)
804{
805 struct zfcp_adapter *adapter;
806 struct fc_host_statistics *fc_stats;
807 struct fsf_qtcb_bottom_port *data;
808 int ret;
809
810 adapter = (struct zfcp_adapter *)shost->hostdata[0];
811 fc_stats = zfcp_init_fc_host_stats(adapter);
812 if (!fc_stats)
813 return NULL;
814
815 data = kmalloc(sizeof(*data), GFP_KERNEL);
816 if (!data)
817 return NULL;
818 memset(data, 0, sizeof(*data));
819
820 ret = zfcp_fsf_exchange_port_data(NULL, adapter, data);
821 if (ret) {
822 kfree(data);
823 return NULL; /* XXX return zeroed fc_stats? */
824 }
825
826 if (adapter->stats_reset &&
827 ((jiffies/HZ - adapter->stats_reset) <
828 data->seconds_since_last_reset)) {
829 zfcp_adjust_fc_host_stats(fc_stats, data,
830 adapter->stats_reset_data);
831 } else
832 zfcp_set_fc_host_stats(fc_stats, data);
833
834 kfree(data);
835 return fc_stats;
766} 836}
767 837
768static void 838static void
769zfcp_get_node_name(struct scsi_target *starget) 839zfcp_reset_fc_host_stats(struct Scsi_Host *shost)
770{ 840{
771 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 841 struct zfcp_adapter *adapter;
772 struct zfcp_adapter *adapter = (struct zfcp_adapter *)shost->hostdata[0]; 842 struct fsf_qtcb_bottom_port *data, *old_data;
773 struct zfcp_port *port; 843 int ret;
774 unsigned long flags;
775 844
776 read_lock_irqsave(&zfcp_data.config_lock, flags); 845 adapter = (struct zfcp_adapter *)shost->hostdata[0];
777 port = zfcp_port_lookup(adapter, starget->channel, starget->id); 846 data = kmalloc(sizeof(*data), GFP_KERNEL);
778 if (port) 847 if (!data)
779 fc_starget_node_name(starget) = port->wwnn; 848 return;
780 else 849 memset(data, 0, sizeof(*data));
781 fc_starget_node_name(starget) = -1; 850
782 read_unlock_irqrestore(&zfcp_data.config_lock, flags); 851 ret = zfcp_fsf_exchange_port_data(NULL, adapter, data);
852 if (ret == 0) {
853 adapter->stats_reset = jiffies/HZ;
854 old_data = adapter->stats_reset_data;
855 adapter->stats_reset_data = data; /* finally freed in
856 adater_dequeue */
857 kfree(old_data);
858 }
783} 859}
784 860
785struct fc_function_template zfcp_transport_functions = { 861struct fc_function_template zfcp_transport_functions = {
786 .get_starget_port_id = zfcp_get_port_id,
787 .get_starget_port_name = zfcp_get_port_name,
788 .get_starget_node_name = zfcp_get_node_name,
789 .show_starget_port_id = 1, 862 .show_starget_port_id = 1,
790 .show_starget_port_name = 1, 863 .show_starget_port_name = 1,
791 .show_starget_node_name = 1, 864 .show_starget_node_name = 1,
792 .show_rport_supported_classes = 1, 865 .show_rport_supported_classes = 1,
793 .show_host_node_name = 1, 866 .show_host_node_name = 1,
794 .show_host_port_name = 1, 867 .show_host_port_name = 1,
868 .show_host_permanent_port_name = 1,
795 .show_host_supported_classes = 1, 869 .show_host_supported_classes = 1,
870 .show_host_supported_speeds = 1,
796 .show_host_maxframe_size = 1, 871 .show_host_maxframe_size = 1,
797 .show_host_serial_number = 1, 872 .show_host_serial_number = 1,
873 .get_fc_host_stats = zfcp_get_fc_host_stats,
874 .reset_fc_host_stats = zfcp_reset_fc_host_stats,
875 /* no functions registered for following dynamic attributes but
876 directly set by LLDD */
877 .show_host_port_type = 1,
798 .show_host_speed = 1, 878 .show_host_speed = 1,
799 .show_host_port_id = 1, 879 .show_host_port_id = 1,
800}; 880};
diff --git a/drivers/s390/scsi/zfcp_sysfs_adapter.c b/drivers/s390/scsi/zfcp_sysfs_adapter.c
index 0cd435280e7d..9f262250043a 100644
--- a/drivers/s390/scsi/zfcp_sysfs_adapter.c
+++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c
@@ -33,14 +33,6 @@
33 33
34#define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG 34#define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG
35 35
36static const char fc_topologies[5][25] = {
37 "<error>",
38 "point-to-point",
39 "fabric",
40 "arbitrated loop",
41 "fabric (virt. adapter)"
42};
43
44/** 36/**
45 * ZFCP_DEFINE_ADAPTER_ATTR 37 * ZFCP_DEFINE_ADAPTER_ATTR
46 * @_name: name of show attribute 38 * @_name: name of show attribute
@@ -69,12 +61,8 @@ ZFCP_DEFINE_ADAPTER_ATTR(physical_wwpn, "0x%016llx\n", adapter->physical_wwpn);
69ZFCP_DEFINE_ADAPTER_ATTR(physical_s_id, "0x%06x\n", adapter->physical_s_id); 61ZFCP_DEFINE_ADAPTER_ATTR(physical_s_id, "0x%06x\n", adapter->physical_s_id);
70ZFCP_DEFINE_ADAPTER_ATTR(card_version, "0x%04x\n", adapter->hydra_version); 62ZFCP_DEFINE_ADAPTER_ATTR(card_version, "0x%04x\n", adapter->hydra_version);
71ZFCP_DEFINE_ADAPTER_ATTR(lic_version, "0x%08x\n", adapter->fsf_lic_version); 63ZFCP_DEFINE_ADAPTER_ATTR(lic_version, "0x%08x\n", adapter->fsf_lic_version);
72ZFCP_DEFINE_ADAPTER_ATTR(fc_service_class, "%d\n", adapter->fc_service_class);
73ZFCP_DEFINE_ADAPTER_ATTR(fc_topology, "%s\n",
74 fc_topologies[adapter->fc_topology]);
75ZFCP_DEFINE_ADAPTER_ATTR(hardware_version, "0x%08x\n", 64ZFCP_DEFINE_ADAPTER_ATTR(hardware_version, "0x%08x\n",
76 adapter->hardware_version); 65 adapter->hardware_version);
77ZFCP_DEFINE_ADAPTER_ATTR(scsi_host_no, "0x%x\n", adapter->scsi_host_no);
78ZFCP_DEFINE_ADAPTER_ATTR(in_recovery, "%d\n", atomic_test_mask 66ZFCP_DEFINE_ADAPTER_ATTR(in_recovery, "%d\n", atomic_test_mask
79 (ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status)); 67 (ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status));
80 68
@@ -259,9 +247,6 @@ static struct attribute *zfcp_adapter_attrs[] = {
259 &dev_attr_physical_s_id.attr, 247 &dev_attr_physical_s_id.attr,
260 &dev_attr_card_version.attr, 248 &dev_attr_card_version.attr,
261 &dev_attr_lic_version.attr, 249 &dev_attr_lic_version.attr,
262 &dev_attr_fc_service_class.attr,
263 &dev_attr_fc_topology.attr,
264 &dev_attr_scsi_host_no.attr,
265 &dev_attr_status.attr, 250 &dev_attr_status.attr,
266 &dev_attr_hardware_version.attr, 251 &dev_attr_hardware_version.attr,
267 NULL 252 NULL
diff --git a/drivers/s390/scsi/zfcp_sysfs_port.c b/drivers/s390/scsi/zfcp_sysfs_port.c
index c55e82d91deb..3924eb38805c 100644
--- a/drivers/s390/scsi/zfcp_sysfs_port.c
+++ b/drivers/s390/scsi/zfcp_sysfs_port.c
@@ -65,8 +65,6 @@ static ssize_t zfcp_sysfs_port_##_name##_show(struct device *dev, struct device_
65static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_port_##_name##_show, NULL); 65static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_port_##_name##_show, NULL);
66 66
67ZFCP_DEFINE_PORT_ATTR(status, "0x%08x\n", atomic_read(&port->status)); 67ZFCP_DEFINE_PORT_ATTR(status, "0x%08x\n", atomic_read(&port->status));
68ZFCP_DEFINE_PORT_ATTR(wwnn, "0x%016llx\n", port->wwnn);
69ZFCP_DEFINE_PORT_ATTR(d_id, "0x%06x\n", port->d_id);
70ZFCP_DEFINE_PORT_ATTR(in_recovery, "%d\n", atomic_test_mask 68ZFCP_DEFINE_PORT_ATTR(in_recovery, "%d\n", atomic_test_mask
71 (ZFCP_STATUS_COMMON_ERP_INUSE, &port->status)); 69 (ZFCP_STATUS_COMMON_ERP_INUSE, &port->status));
72ZFCP_DEFINE_PORT_ATTR(access_denied, "%d\n", atomic_test_mask 70ZFCP_DEFINE_PORT_ATTR(access_denied, "%d\n", atomic_test_mask
@@ -245,8 +243,6 @@ static struct attribute *zfcp_port_common_attrs[] = {
245 &dev_attr_failed.attr, 243 &dev_attr_failed.attr,
246 &dev_attr_in_recovery.attr, 244 &dev_attr_in_recovery.attr,
247 &dev_attr_status.attr, 245 &dev_attr_status.attr,
248 &dev_attr_wwnn.attr,
249 &dev_attr_d_id.attr,
250 &dev_attr_access_denied.attr, 246 &dev_attr_access_denied.attr,
251 NULL 247 NULL
252}; 248};
diff --git a/drivers/s390/scsi/zfcp_sysfs_unit.c b/drivers/s390/scsi/zfcp_sysfs_unit.c
index 0556642c9e1d..2f50815f65c7 100644
--- a/drivers/s390/scsi/zfcp_sysfs_unit.c
+++ b/drivers/s390/scsi/zfcp_sysfs_unit.c
@@ -65,7 +65,6 @@ static ssize_t zfcp_sysfs_unit_##_name##_show(struct device *dev, struct device_
65static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_unit_##_name##_show, NULL); 65static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_unit_##_name##_show, NULL);
66 66
67ZFCP_DEFINE_UNIT_ATTR(status, "0x%08x\n", atomic_read(&unit->status)); 67ZFCP_DEFINE_UNIT_ATTR(status, "0x%08x\n", atomic_read(&unit->status));
68ZFCP_DEFINE_UNIT_ATTR(scsi_lun, "0x%x\n", unit->scsi_lun);
69ZFCP_DEFINE_UNIT_ATTR(in_recovery, "%d\n", atomic_test_mask 68ZFCP_DEFINE_UNIT_ATTR(in_recovery, "%d\n", atomic_test_mask
70 (ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status)); 69 (ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status));
71ZFCP_DEFINE_UNIT_ATTR(access_denied, "%d\n", atomic_test_mask 70ZFCP_DEFINE_UNIT_ATTR(access_denied, "%d\n", atomic_test_mask
@@ -138,7 +137,6 @@ static DEVICE_ATTR(failed, S_IWUSR | S_IRUGO, zfcp_sysfs_unit_failed_show,
138 zfcp_sysfs_unit_failed_store); 137 zfcp_sysfs_unit_failed_store);
139 138
140static struct attribute *zfcp_unit_attrs[] = { 139static struct attribute *zfcp_unit_attrs[] = {
141 &dev_attr_scsi_lun.attr,
142 &dev_attr_failed.attr, 140 &dev_attr_failed.attr,
143 &dev_attr_in_recovery.attr, 141 &dev_attr_in_recovery.attr,
144 &dev_attr_status.attr, 142 &dev_attr_status.attr,
diff --git a/drivers/sbus/char/aurora.c b/drivers/sbus/char/aurora.c
index 92e6c5639dd3..015db40ad8a4 100644
--- a/drivers/sbus/char/aurora.c
+++ b/drivers/sbus/char/aurora.c
@@ -92,7 +92,6 @@ static struct Aurora_port aurora_port[AURORA_TNPORTS] = {
92 92
93/* no longer used. static struct Aurora_board * IRQ_to_board[16] = { NULL, } ;*/ 93/* no longer used. static struct Aurora_board * IRQ_to_board[16] = { NULL, } ;*/
94static unsigned char * tmp_buf = NULL; 94static unsigned char * tmp_buf = NULL;
95static DECLARE_MUTEX(tmp_buf_sem);
96 95
97DECLARE_TASK_QUEUE(tq_aurora); 96DECLARE_TASK_QUEUE(tq_aurora);
98 97
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index 3ff74f472249..31c497542272 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -73,6 +73,7 @@
73#include <linux/delay.h> 73#include <linux/delay.h>
74#include <linux/pci.h> 74#include <linux/pci.h>
75#include <linux/time.h> 75#include <linux/time.h>
76#include <linux/mutex.h>
76#include <asm/io.h> 77#include <asm/io.h>
77#include <asm/irq.h> 78#include <asm/irq.h>
78#include <asm/uaccess.h> 79#include <asm/uaccess.h>
@@ -615,7 +616,7 @@ static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int
615 void __user *argp = (void __user *)arg; 616 void __user *argp = (void __user *)arg;
616 617
617 /* Only let one of these through at a time */ 618 /* Only let one of these through at a time */
618 if (down_interruptible(&tw_dev->ioctl_sem)) { 619 if (mutex_lock_interruptible(&tw_dev->ioctl_lock)) {
619 retval = TW_IOCTL_ERROR_OS_EINTR; 620 retval = TW_IOCTL_ERROR_OS_EINTR;
620 goto out; 621 goto out;
621 } 622 }
@@ -852,7 +853,7 @@ out3:
852 /* Now free ioctl buf memory */ 853 /* Now free ioctl buf memory */
853 dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_Ioctl_Buf_Apache) - 1, cpu_addr, dma_handle); 854 dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_Ioctl_Buf_Apache) - 1, cpu_addr, dma_handle);
854out2: 855out2:
855 up(&tw_dev->ioctl_sem); 856 mutex_unlock(&tw_dev->ioctl_lock);
856out: 857out:
857 return retval; 858 return retval;
858} /* End twa_chrdev_ioctl() */ 859} /* End twa_chrdev_ioctl() */
@@ -1182,7 +1183,7 @@ static int twa_initialize_device_extension(TW_Device_Extension *tw_dev)
1182 tw_dev->error_sequence_id = 1; 1183 tw_dev->error_sequence_id = 1;
1183 tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE; 1184 tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
1184 1185
1185 init_MUTEX(&tw_dev->ioctl_sem); 1186 mutex_init(&tw_dev->ioctl_lock);
1186 init_waitqueue_head(&tw_dev->ioctl_wqueue); 1187 init_waitqueue_head(&tw_dev->ioctl_wqueue);
1187 1188
1188 retval = 0; 1189 retval = 0;
diff --git a/drivers/scsi/3w-9xxx.h b/drivers/scsi/3w-9xxx.h
index 46f22cdc8298..1b16d57f0314 100644
--- a/drivers/scsi/3w-9xxx.h
+++ b/drivers/scsi/3w-9xxx.h
@@ -672,7 +672,7 @@ typedef struct TAG_TW_Device_Extension {
672 u32 ioctl_msec; 672 u32 ioctl_msec;
673 int chrdev_request_id; 673 int chrdev_request_id;
674 wait_queue_head_t ioctl_wqueue; 674 wait_queue_head_t ioctl_wqueue;
675 struct semaphore ioctl_sem; 675 struct mutex ioctl_lock;
676 char aen_clobber; 676 char aen_clobber;
677 unsigned short working_srl; 677 unsigned short working_srl;
678 unsigned short working_branch; 678 unsigned short working_branch;
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index 283f6d25892b..25f678d0780b 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -203,6 +203,7 @@
203#include <linux/delay.h> 203#include <linux/delay.h>
204#include <linux/pci.h> 204#include <linux/pci.h>
205#include <linux/time.h> 205#include <linux/time.h>
206#include <linux/mutex.h>
206#include <asm/io.h> 207#include <asm/io.h>
207#include <asm/irq.h> 208#include <asm/irq.h>
208#include <asm/uaccess.h> 209#include <asm/uaccess.h>
@@ -888,7 +889,7 @@ static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int
888 dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl()\n"); 889 dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl()\n");
889 890
890 /* Only let one of these through at a time */ 891 /* Only let one of these through at a time */
891 if (down_interruptible(&tw_dev->ioctl_sem)) 892 if (mutex_lock_interruptible(&tw_dev->ioctl_lock))
892 return -EINTR; 893 return -EINTR;
893 894
894 /* First copy down the buffer length */ 895 /* First copy down the buffer length */
@@ -1029,7 +1030,7 @@ out2:
1029 /* Now free ioctl buf memory */ 1030 /* Now free ioctl buf memory */
1030 dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, cpu_addr, dma_handle); 1031 dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, cpu_addr, dma_handle);
1031out: 1032out:
1032 up(&tw_dev->ioctl_sem); 1033 mutex_unlock(&tw_dev->ioctl_lock);
1033 return retval; 1034 return retval;
1034} /* End tw_chrdev_ioctl() */ 1035} /* End tw_chrdev_ioctl() */
1035 1036
@@ -1270,7 +1271,7 @@ static int tw_initialize_device_extension(TW_Device_Extension *tw_dev)
1270 tw_dev->pending_tail = TW_Q_START; 1271 tw_dev->pending_tail = TW_Q_START;
1271 tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE; 1272 tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
1272 1273
1273 init_MUTEX(&tw_dev->ioctl_sem); 1274 mutex_init(&tw_dev->ioctl_lock);
1274 init_waitqueue_head(&tw_dev->ioctl_wqueue); 1275 init_waitqueue_head(&tw_dev->ioctl_wqueue);
1275 1276
1276 return 0; 1277 return 0;
diff --git a/drivers/scsi/3w-xxxx.h b/drivers/scsi/3w-xxxx.h
index 4f81fc39ec57..31fe5ea15920 100644
--- a/drivers/scsi/3w-xxxx.h
+++ b/drivers/scsi/3w-xxxx.h
@@ -420,7 +420,7 @@ typedef struct TAG_TW_Device_Extension {
420 u32 max_sector_count; 420 u32 max_sector_count;
421 u32 aen_count; 421 u32 aen_count;
422 struct Scsi_Host *host; 422 struct Scsi_Host *host;
423 struct semaphore ioctl_sem; 423 struct mutex ioctl_lock;
424 unsigned short aen_queue[TW_Q_LENGTH]; 424 unsigned short aen_queue[TW_Q_LENGTH];
425 unsigned char aen_head; 425 unsigned char aen_head;
426 unsigned char aen_tail; 426 unsigned char aen_tail;
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
index 9d6040bfa064..1c459343292b 100644
--- a/drivers/scsi/BusLogic.c
+++ b/drivers/scsi/BusLogic.c
@@ -2216,6 +2216,7 @@ static int __init BusLogic_init(void)
2216 HostAdapter->PCI_Address = ProbeInfo->PCI_Address; 2216 HostAdapter->PCI_Address = ProbeInfo->PCI_Address;
2217 HostAdapter->Bus = ProbeInfo->Bus; 2217 HostAdapter->Bus = ProbeInfo->Bus;
2218 HostAdapter->Device = ProbeInfo->Device; 2218 HostAdapter->Device = ProbeInfo->Device;
2219 HostAdapter->PCI_Device = ProbeInfo->PCI_Device;
2219 HostAdapter->IRQ_Channel = ProbeInfo->IRQ_Channel; 2220 HostAdapter->IRQ_Channel = ProbeInfo->IRQ_Channel;
2220 HostAdapter->AddressCount = BusLogic_HostAdapterAddressCount[HostAdapter->HostAdapterType]; 2221 HostAdapter->AddressCount = BusLogic_HostAdapterAddressCount[HostAdapter->HostAdapterType];
2221 /* 2222 /*
@@ -2296,7 +2297,7 @@ static int __init BusLogic_init(void)
2296 scsi_host_put(Host); 2297 scsi_host_put(Host);
2297 } else { 2298 } else {
2298 BusLogic_InitializeHostStructure(HostAdapter, Host); 2299 BusLogic_InitializeHostStructure(HostAdapter, Host);
2299 scsi_add_host(Host, NULL); 2300 scsi_add_host(Host, HostAdapter->PCI_Device ? &HostAdapter->PCI_Device->dev : NULL);
2300 scsi_scan_host(Host); 2301 scsi_scan_host(Host);
2301 BusLogicHostAdapterCount++; 2302 BusLogicHostAdapterCount++;
2302 } 2303 }
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 6e0c059df6a5..320e765fa0cd 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -80,7 +80,7 @@ obj-$(CONFIG_SCSI_QLOGIC_FAS) += qlogicfas408.o qlogicfas.o
80obj-$(CONFIG_PCMCIA_QLOGIC) += qlogicfas408.o 80obj-$(CONFIG_PCMCIA_QLOGIC) += qlogicfas408.o
81obj-$(CONFIG_SCSI_QLOGIC_FC) += qlogicfc.o 81obj-$(CONFIG_SCSI_QLOGIC_FC) += qlogicfc.o
82obj-$(CONFIG_SCSI_QLOGIC_1280) += qla1280.o 82obj-$(CONFIG_SCSI_QLOGIC_1280) += qla1280.o
83obj-$(CONFIG_SCSI_QLA2XXX) += qla2xxx/ 83obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx/
84obj-$(CONFIG_SCSI_LPFC) += lpfc/ 84obj-$(CONFIG_SCSI_LPFC) += lpfc/
85obj-$(CONFIG_SCSI_PAS16) += pas16.o 85obj-$(CONFIG_SCSI_PAS16) += pas16.o
86obj-$(CONFIG_SCSI_SEAGATE) += seagate.o 86obj-$(CONFIG_SCSI_SEAGATE) += seagate.o
diff --git a/drivers/scsi/aacraid/README b/drivers/scsi/aacraid/README
deleted file mode 100644
index 4193865d419c..000000000000
--- a/drivers/scsi/aacraid/README
+++ /dev/null
@@ -1,74 +0,0 @@
1AACRAID Driver for Linux (take two)
2
3Introduction
4-------------------------
5The aacraid driver adds support for Adaptec (http://www.adaptec.com)
6RAID controllers. This is a major rewrite from the original
7Adaptec supplied driver. It has signficantly cleaned up both the code
8and the running binary size (the module is less than half the size of
9the original).
10
11Supported Cards/Chipsets
12-------------------------
13 Adaptec 2020S
14 Adaptec 2025S
15 Adaptec 2120S
16 Adaptec 2130S
17 Adaptec 2200S
18 Adaptec 2230S
19 Adaptec 2240S
20 Adaptec 2410SA
21 Adaptec 2610SA
22 Adaptec 2810SA
23 Adaptec 21610SA
24 Adaptec 3230S
25 Adaptec 3240S
26 Adaptec 4000SAS
27 Adaptec 4005SAS
28 Adaptec 4800SAS
29 Adaptec 4805SAS
30 Adaptec 5400S
31 Dell PERC 2 Quad Channel
32 Dell PERC 2/Si
33 Dell PERC 3/Si
34 Dell PERC 3/Di
35 Dell CERC 2
36 HP NetRAID-4M
37 Legend S220
38 Legend S230
39 IBM ServeRAID 8i
40 ICP 9014R0
41 ICP 9024R0
42 ICP 9047MA
43 ICP 9087MA
44 ICP 9085LI
45 ICP 5085AU
46
47People
48-------------------------
49Alan Cox <alan@redhat.com>
50Christoph Hellwig <hch@infradead.org> (updates for new-style PCI probing and SCSI host registration,
51 small cleanups/fixes)
52Matt Domsch <matt_domsch@dell.com> (revision ioctl, adapter messages)
53Deanna Bonds (non-DASD support, PAE fibs and 64 bit, added new adaptec controllers
54 added new ioctls, changed scsi interface to use new error handler,
55 increased the number of fibs and outstanding commands to a container)
56
57 (fixed 64bit and 64G memory model, changed confusing naming convention
58 where fibs that go to the hardware are consistently called hw_fibs and
59 not just fibs like the name of the driver tracking structure)
60Mark Salyzyn <Mark_Salyzyn@adaptec.com> Fixed panic issues and added some new product ids for upcoming hbas. Performance tuning, card failover and bug mitigations.
61
62Original Driver
63-------------------------
64Adaptec Unix OEM Product Group
65
66Mailing List
67-------------------------
68linux-scsi@vger.kernel.org (Interested parties troll here)
69Also note this is very different to Brian's original driver
70so don't expect him to support it.
71Adaptec does support this driver. Contact either tech support or Mark Salyzyn.
72
73Original by Brian Boerner February 2001
74Rewritten by Alan Cox, November 2001
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 30fd8d6e3f31..66dbb6d2c506 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -532,6 +532,13 @@ struct aac_driver_ident
532#define AAC_QUIRK_MASTER 0x0008 532#define AAC_QUIRK_MASTER 0x0008
533 533
534/* 534/*
535 * Some adapter firmware perform poorly when it must split up scatter gathers
536 * in order to deal with the limits of the underlying CHIM. This limit in this
537 * class of adapters is 17 scatter gather elements.
538 */
539#define AAC_QUIRK_17SG 0x0010
540
541/*
535 * The adapter interface specs all queues to be located in the same 542 * The adapter interface specs all queues to be located in the same
536 * physically contigous block. The host structure that defines the 543 * physically contigous block. The host structure that defines the
537 * commuication queues will assume they are each a separate physically 544 * commuication queues will assume they are each a separate physically
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index ef623bd965f5..4fe79cd7c957 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -85,6 +85,10 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
85 if (size < le16_to_cpu(kfib->header.SenderSize)) 85 if (size < le16_to_cpu(kfib->header.SenderSize))
86 size = le16_to_cpu(kfib->header.SenderSize); 86 size = le16_to_cpu(kfib->header.SenderSize);
87 if (size > dev->max_fib_size) { 87 if (size > dev->max_fib_size) {
88 if (size > 2048) {
89 retval = -EINVAL;
90 goto cleanup;
91 }
88 /* Highjack the hw_fib */ 92 /* Highjack the hw_fib */
89 hw_fib = fibptr->hw_fib; 93 hw_fib = fibptr->hw_fib;
90 hw_fib_pa = fibptr->hw_fib_pa; 94 hw_fib_pa = fibptr->hw_fib_pa;
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 9b9062f02462..0bf5f9a943e8 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -200,10 +200,10 @@ static struct aac_driver_ident aac_drivers[] = {
200 { aac_rkt_init, "aacraid", "ADAPTEC ", "Callisto ", 2, AAC_QUIRK_MASTER }, /* Jupiter Platform */ 200 { aac_rkt_init, "aacraid", "ADAPTEC ", "Callisto ", 2, AAC_QUIRK_MASTER }, /* Jupiter Platform */
201 { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2020SA ", 1 }, /* ASR-2020SA SATA PCI-X ZCR (Skyhawk) */ 201 { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2020SA ", 1 }, /* ASR-2020SA SATA PCI-X ZCR (Skyhawk) */
202 { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2025SA ", 1 }, /* ASR-2025SA SATA SO-DIMM PCI-X ZCR (Terminator) */ 202 { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2025SA ", 1 }, /* ASR-2025SA SATA SO-DIMM PCI-X ZCR (Terminator) */
203 { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2410SA SATA ", 1 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */ 203 { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2410SA SATA ", 1, AAC_QUIRK_17SG }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */
204 { aac_rx_init, "aacraid", "DELL ", "CERC SR2 ", 1 }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */ 204 { aac_rx_init, "aacraid", "DELL ", "CERC SR2 ", 1, AAC_QUIRK_17SG }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */
205 { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2810SA SATA ", 1 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */ 205 { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2810SA SATA ", 1, AAC_QUIRK_17SG }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */
206 { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-21610SA SATA", 1 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */ 206 { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-21610SA SATA", 1, AAC_QUIRK_17SG }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */
207 { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2026ZCR ", 1 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */ 207 { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2026ZCR ", 1 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */
208 { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2610SA ", 1 }, /* SATA 6Ch (Bearcat) */ 208 { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2610SA ", 1 }, /* SATA 6Ch (Bearcat) */
209 { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2240S ", 1 }, /* ASR-2240S (SabreExpress) */ 209 { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2240S ", 1 }, /* ASR-2240S (SabreExpress) */
@@ -574,7 +574,15 @@ static ssize_t aac_show_model(struct class_device *class_dev,
574 struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata; 574 struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
575 int len; 575 int len;
576 576
577 len = snprintf(buf, PAGE_SIZE, "%s\n", 577 if (dev->supplement_adapter_info.AdapterTypeText[0]) {
578 char * cp = dev->supplement_adapter_info.AdapterTypeText;
579 while (*cp && *cp != ' ')
580 ++cp;
581 while (*cp == ' ')
582 ++cp;
583 len = snprintf(buf, PAGE_SIZE, "%s\n", cp);
584 } else
585 len = snprintf(buf, PAGE_SIZE, "%s\n",
578 aac_drivers[dev->cardtype].model); 586 aac_drivers[dev->cardtype].model);
579 return len; 587 return len;
580} 588}
@@ -585,7 +593,15 @@ static ssize_t aac_show_vendor(struct class_device *class_dev,
585 struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata; 593 struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
586 int len; 594 int len;
587 595
588 len = snprintf(buf, PAGE_SIZE, "%s\n", 596 if (dev->supplement_adapter_info.AdapterTypeText[0]) {
597 char * cp = dev->supplement_adapter_info.AdapterTypeText;
598 while (*cp && *cp != ' ')
599 ++cp;
600 len = snprintf(buf, PAGE_SIZE, "%.*s\n",
601 (int)(cp - (char *)dev->supplement_adapter_info.AdapterTypeText),
602 dev->supplement_adapter_info.AdapterTypeText);
603 } else
604 len = snprintf(buf, PAGE_SIZE, "%s\n",
589 aac_drivers[dev->cardtype].vname); 605 aac_drivers[dev->cardtype].vname);
590 return len; 606 return len;
591} 607}
@@ -837,6 +853,13 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
837 = (aac->scsi_host_ptr->sg_tablesize * 8) + 112; 853 = (aac->scsi_host_ptr->sg_tablesize * 8) + 112;
838 } 854 }
839 855
856 if ((aac_drivers[index].quirks & AAC_QUIRK_17SG) &&
857 (aac->scsi_host_ptr->sg_tablesize > 17)) {
858 aac->scsi_host_ptr->sg_tablesize = 17;
859 aac->scsi_host_ptr->max_sectors
860 = (aac->scsi_host_ptr->sg_tablesize * 8) + 112;
861 }
862
840 /* 863 /*
841 * Firware printf works only with older firmware. 864 * Firware printf works only with older firmware.
842 */ 865 */
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic7xxx b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
index ac8de03c9fa2..6c2c395554ff 100644
--- a/drivers/scsi/aic7xxx/Kconfig.aic7xxx
+++ b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
@@ -42,13 +42,13 @@ config AIC7XXX_CMDS_PER_DEVICE
42config AIC7XXX_RESET_DELAY_MS 42config AIC7XXX_RESET_DELAY_MS
43 int "Initial bus reset delay in milli-seconds" 43 int "Initial bus reset delay in milli-seconds"
44 depends on SCSI_AIC7XXX 44 depends on SCSI_AIC7XXX
45 default "15000" 45 default "5000"
46 ---help--- 46 ---help---
47 The number of milliseconds to delay after an initial bus reset. 47 The number of milliseconds to delay after an initial bus reset.
48 The bus settle delay following all error recovery actions is 48 The bus settle delay following all error recovery actions is
49 dictated by the SCSI layer and is not affected by this value. 49 dictated by the SCSI layer and is not affected by this value.
50 50
51 Default: 15000 (15 seconds) 51 Default: 5000 (5 seconds)
52 52
53config AIC7XXX_PROBE_EISA_VL 53config AIC7XXX_PROBE_EISA_VL
54 bool "Probe for EISA and VL AIC7XXX Adapters" 54 bool "Probe for EISA and VL AIC7XXX Adapters"
diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h
index 653fb0b42aea..2cfdbef447db 100644
--- a/drivers/scsi/aic7xxx/aic79xx.h
+++ b/drivers/scsi/aic7xxx/aic79xx.h
@@ -37,7 +37,7 @@
37 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGES. 38 * POSSIBILITY OF SUCH DAMAGES.
39 * 39 *
40 * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#95 $ 40 * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#108 $
41 * 41 *
42 * $FreeBSD$ 42 * $FreeBSD$
43 */ 43 */
@@ -75,8 +75,7 @@ struct scb_platform_data;
75#define INITIATOR_WILDCARD (~0) 75#define INITIATOR_WILDCARD (~0)
76#define SCB_LIST_NULL 0xFF00 76#define SCB_LIST_NULL 0xFF00
77#define SCB_LIST_NULL_LE (ahd_htole16(SCB_LIST_NULL)) 77#define SCB_LIST_NULL_LE (ahd_htole16(SCB_LIST_NULL))
78#define QOUTFIFO_ENTRY_VALID 0x8000 78#define QOUTFIFO_ENTRY_VALID 0x80
79#define QOUTFIFO_ENTRY_VALID_LE (ahd_htole16(0x8000))
80#define SCBID_IS_NULL(scbid) (((scbid) & 0xFF00 ) == SCB_LIST_NULL) 79#define SCBID_IS_NULL(scbid) (((scbid) & 0xFF00 ) == SCB_LIST_NULL)
81 80
82#define SCSIID_TARGET(ahd, scsiid) \ 81#define SCSIID_TARGET(ahd, scsiid) \
@@ -1053,6 +1052,13 @@ typedef uint8_t ahd_mode_state;
1053 1052
1054typedef void ahd_callback_t (void *); 1053typedef void ahd_callback_t (void *);
1055 1054
1055struct ahd_completion
1056{
1057 uint16_t tag;
1058 uint8_t sg_status;
1059 uint8_t valid_tag;
1060};
1061
1056struct ahd_softc { 1062struct ahd_softc {
1057 bus_space_tag_t tags[2]; 1063 bus_space_tag_t tags[2];
1058 bus_space_handle_t bshs[2]; 1064 bus_space_handle_t bshs[2];
@@ -1062,6 +1068,7 @@ struct ahd_softc {
1062 struct scb_data scb_data; 1068 struct scb_data scb_data;
1063 1069
1064 struct hardware_scb *next_queued_hscb; 1070 struct hardware_scb *next_queued_hscb;
1071 struct map_node *next_queued_hscb_map;
1065 1072
1066 /* 1073 /*
1067 * SCBs that have been sent to the controller 1074 * SCBs that have been sent to the controller
@@ -1140,16 +1147,23 @@ struct ahd_softc {
1140 ahd_flag flags; 1147 ahd_flag flags;
1141 struct seeprom_config *seep_config; 1148 struct seeprom_config *seep_config;
1142 1149
1143 /* Values to store in the SEQCTL register for pause and unpause */
1144 uint8_t unpause;
1145 uint8_t pause;
1146
1147 /* Command Queues */ 1150 /* Command Queues */
1151 struct ahd_completion *qoutfifo;
1148 uint16_t qoutfifonext; 1152 uint16_t qoutfifonext;
1149 uint16_t qoutfifonext_valid_tag; 1153 uint16_t qoutfifonext_valid_tag;
1150 uint16_t qinfifonext; 1154 uint16_t qinfifonext;
1151 uint16_t qinfifo[AHD_SCB_MAX]; 1155 uint16_t qinfifo[AHD_SCB_MAX];
1152 uint16_t *qoutfifo; 1156
1157 /*
1158 * Our qfreeze count. The sequencer compares
1159 * this value with its own counter to determine
1160 * whether to allow selections to occur.
1161 */
1162 uint16_t qfreeze_cnt;
1163
1164 /* Values to store in the SEQCTL register for pause and unpause */
1165 uint8_t unpause;
1166 uint8_t pause;
1153 1167
1154 /* Critical Section Data */ 1168 /* Critical Section Data */
1155 struct cs *critical_sections; 1169 struct cs *critical_sections;
@@ -1197,8 +1211,7 @@ struct ahd_softc {
1197 */ 1211 */
1198 bus_dma_tag_t parent_dmat; 1212 bus_dma_tag_t parent_dmat;
1199 bus_dma_tag_t shared_data_dmat; 1213 bus_dma_tag_t shared_data_dmat;
1200 bus_dmamap_t shared_data_dmamap; 1214 struct map_node shared_data_map;
1201 dma_addr_t shared_data_busaddr;
1202 1215
1203 /* Information saved through suspend/resume cycles */ 1216 /* Information saved through suspend/resume cycles */
1204 struct ahd_suspend_state suspend_state; 1217 struct ahd_suspend_state suspend_state;
@@ -1296,9 +1309,9 @@ struct ahd_devinfo {
1296}; 1309};
1297 1310
1298/****************************** PCI Structures ********************************/ 1311/****************************** PCI Structures ********************************/
1299#define AHD_PCI_IOADDR0 PCIR_MAPS /* I/O BAR*/ 1312#define AHD_PCI_IOADDR0 PCIR_BAR(0) /* I/O BAR*/
1300#define AHD_PCI_MEMADDR (PCIR_MAPS + 4) /* Memory BAR */ 1313#define AHD_PCI_MEMADDR PCIR_BAR(1) /* Memory BAR */
1301#define AHD_PCI_IOADDR1 (PCIR_MAPS + 12)/* Second I/O BAR */ 1314#define AHD_PCI_IOADDR1 PCIR_BAR(3) /* Second I/O BAR */
1302 1315
1303typedef int (ahd_device_setup_t)(struct ahd_softc *); 1316typedef int (ahd_device_setup_t)(struct ahd_softc *);
1304 1317
diff --git a/drivers/scsi/aic7xxx/aic79xx.reg b/drivers/scsi/aic7xxx/aic79xx.reg
index cca58edc8648..3a3204703b15 100644
--- a/drivers/scsi/aic7xxx/aic79xx.reg
+++ b/drivers/scsi/aic7xxx/aic79xx.reg
@@ -39,7 +39,7 @@
39 * 39 *
40 * $FreeBSD$ 40 * $FreeBSD$
41 */ 41 */
42VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $" 42VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#76 $"
43 43
44/* 44/*
45 * This file is processed by the aic7xxx_asm utility for use in assembling 45 * This file is processed by the aic7xxx_asm utility for use in assembling
@@ -65,13 +65,6 @@ VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $"
65 mvi MODE_PTR, MK_MODE(src, dst); \ 65 mvi MODE_PTR, MK_MODE(src, dst); \
66 } 66 }
67 67
68#define TOGGLE_DFF_MODE \
69 if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) { \
70 call toggle_dff_mode_work_around; \
71 } else { \
72 xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1); \
73 }
74
75#define RESTORE_MODE(mode) \ 68#define RESTORE_MODE(mode) \
76 if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) { \ 69 if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) { \
77 mov mode call set_mode_work_around; \ 70 mov mode call set_mode_work_around; \
@@ -1199,7 +1192,7 @@ register TARGPCISTAT {
1199 1192
1200/* 1193/*
1201 * LQ Packet In 1194 * LQ Packet In
1202 * The last LQ Packet received 1195 * The last LQ Packet recieved
1203 */ 1196 */
1204register LQIN { 1197register LQIN {
1205 address 0x020 1198 address 0x020
@@ -3542,10 +3535,34 @@ scratch_ram {
3542 COMPLETE_DMA_SCB_HEAD { 3535 COMPLETE_DMA_SCB_HEAD {
3543 size 2 3536 size 2
3544 } 3537 }
3545 /* Counting semaphore to prevent new select-outs */ 3538 /*
3539 * tail of list of SCBs that have
3540 * completed but need to be uploaded
3541 * to the host prior to being completed.
3542 */
3543 COMPLETE_DMA_SCB_TAIL {
3544 size 2
3545 }
3546 /*
3547 * head of list of SCBs that have
3548 * been uploaded to the host, but cannot
3549 * be completed until the QFREEZE is in
3550 * full effect (i.e. no selections pending).
3551 */
3552 COMPLETE_ON_QFREEZE_HEAD {
3553 size 2
3554 }
3555 /*
3556 * Counting semaphore to prevent new select-outs
3557 * The queue is frozen so long as the sequencer
3558 * and kernel freeze counts differ.
3559 */
3546 QFREEZE_COUNT { 3560 QFREEZE_COUNT {
3547 size 2 3561 size 2
3548 } 3562 }
3563 KERNEL_QFREEZE_COUNT {
3564 size 2
3565 }
3549 /* 3566 /*
3550 * Mode to restore on legacy idle loop exit. 3567 * Mode to restore on legacy idle loop exit.
3551 */ 3568 */
@@ -3625,6 +3642,17 @@ scratch_ram {
3625 size 1 3642 size 1
3626 } 3643 }
3627 /* 3644 /*
3645 * Kernel and sequencer offsets into the queue of
3646 * incoming target mode command descriptors. The
3647 * queue is full when the KERNEL_TQINPOS == TQINPOS.
3648 */
3649 KERNEL_TQINPOS {
3650 size 1
3651 }
3652 TQINPOS {
3653 size 1
3654 }
3655 /*
3628 * Base address of our shared data with the kernel driver in host 3656 * Base address of our shared data with the kernel driver in host
3629 * memory. This includes the qoutfifo and target mode 3657 * memory. This includes the qoutfifo and target mode
3630 * incoming command queue. 3658 * incoming command queue.
@@ -3639,17 +3667,6 @@ scratch_ram {
3639 QOUTFIFO_NEXT_ADDR { 3667 QOUTFIFO_NEXT_ADDR {
3640 size 4 3668 size 4
3641 } 3669 }
3642 /*
3643 * Kernel and sequencer offsets into the queue of
3644 * incoming target mode command descriptors. The
3645 * queue is full when the KERNEL_TQINPOS == TQINPOS.
3646 */
3647 KERNEL_TQINPOS {
3648 size 1
3649 }
3650 TQINPOS {
3651 size 1
3652 }
3653 ARG_1 { 3670 ARG_1 {
3654 size 1 3671 size 1
3655 mask SEND_MSG 0x80 3672 mask SEND_MSG 0x80
@@ -3951,6 +3968,7 @@ const SG_PREFETCH_ADDR_MASK download
3951const SG_SIZEOF download 3968const SG_SIZEOF download
3952const PKT_OVERRUN_BUFOFFSET download 3969const PKT_OVERRUN_BUFOFFSET download
3953const SCB_TRANSFER_SIZE download 3970const SCB_TRANSFER_SIZE download
3971const CACHELINE_MASK download
3954 3972
3955/* 3973/*
3956 * BIOS SCB offsets 3974 * BIOS SCB offsets
diff --git a/drivers/scsi/aic7xxx/aic79xx.seq b/drivers/scsi/aic7xxx/aic79xx.seq
index 65339bc1ca99..bef1f9d369b6 100644
--- a/drivers/scsi/aic7xxx/aic79xx.seq
+++ b/drivers/scsi/aic7xxx/aic79xx.seq
@@ -40,7 +40,7 @@
40 * $FreeBSD$ 40 * $FreeBSD$
41 */ 41 */
42 42
43VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#99 $" 43VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#119 $"
44PATCH_ARG_LIST = "struct ahd_softc *ahd" 44PATCH_ARG_LIST = "struct ahd_softc *ahd"
45PREFIX = "ahd_" 45PREFIX = "ahd_"
46 46
@@ -68,13 +68,47 @@ no_error_set:
68 } 68 }
69 SET_MODE(M_SCSI, M_SCSI) 69 SET_MODE(M_SCSI, M_SCSI)
70 test SCSISEQ0, ENSELO|ENARBO jnz idle_loop_checkbus; 70 test SCSISEQ0, ENSELO|ENARBO jnz idle_loop_checkbus;
71 test SEQ_FLAGS2, SELECTOUT_QFROZEN jnz idle_loop_checkbus; 71 test SEQ_FLAGS2, SELECTOUT_QFROZEN jz check_waiting_list;
72 /*
73 * If the kernel has caught up with us, thaw the queue.
74 */
75 mov A, KERNEL_QFREEZE_COUNT;
76 cmp QFREEZE_COUNT, A jne check_frozen_completions;
77 mov A, KERNEL_QFREEZE_COUNT[1];
78 cmp QFREEZE_COUNT[1], A jne check_frozen_completions;
79 and SEQ_FLAGS2, ~SELECTOUT_QFROZEN;
80 jmp check_waiting_list;
81check_frozen_completions:
82 test SSTAT0, SELDO|SELINGO jnz idle_loop_checkbus;
83BEGIN_CRITICAL;
84 /*
85 * If we have completions stalled waiting for the qfreeze
86 * to take effect, move them over to the complete_scb list
87 * now that no selections are pending.
88 */
89 cmp COMPLETE_ON_QFREEZE_HEAD[1],SCB_LIST_NULL je idle_loop_checkbus;
90 /*
91 * Find the end of the qfreeze list. The first element has
92 * to be treated specially.
93 */
94 bmov SCBPTR, COMPLETE_ON_QFREEZE_HEAD, 2;
95 cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL je join_lists;
96 /*
97 * Now the normal loop.
98 */
99 bmov SCBPTR, SCB_NEXT_COMPLETE, 2;
100 cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL jne . - 1;
101join_lists:
102 bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2;
103 bmov COMPLETE_SCB_HEAD, COMPLETE_ON_QFREEZE_HEAD, 2;
104 mvi COMPLETE_ON_QFREEZE_HEAD[1], SCB_LIST_NULL;
105 jmp idle_loop_checkbus;
106check_waiting_list:
72 cmp WAITING_TID_HEAD[1], SCB_LIST_NULL je idle_loop_checkbus; 107 cmp WAITING_TID_HEAD[1], SCB_LIST_NULL je idle_loop_checkbus;
73 /* 108 /*
74 * ENSELO is cleared by a SELDO, so we must test for SELDO 109 * ENSELO is cleared by a SELDO, so we must test for SELDO
75 * one last time. 110 * one last time.
76 */ 111 */
77BEGIN_CRITICAL;
78 test SSTAT0, SELDO jnz select_out; 112 test SSTAT0, SELDO jnz select_out;
79END_CRITICAL; 113END_CRITICAL;
80 call start_selection; 114 call start_selection;
@@ -90,6 +124,13 @@ idle_loop_check_nonpackreq:
90 test SSTAT2, NONPACKREQ jz . + 2; 124 test SSTAT2, NONPACKREQ jz . + 2;
91 call unexpected_nonpkt_phase_find_ctxt; 125 call unexpected_nonpkt_phase_find_ctxt;
92 if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) { 126 if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) {
127 /*
128 * On Rev A. hardware, the busy LED is only
129 * turned on automaically during selections
130 * and re-selections. Make the LED status
131 * more useful by forcing it to be on so
132 * long as one of our data FIFOs is active.
133 */
93 and A, FIFO0FREE|FIFO1FREE, DFFSTAT; 134 and A, FIFO0FREE|FIFO1FREE, DFFSTAT;
94 cmp A, FIFO0FREE|FIFO1FREE jne . + 3; 135 cmp A, FIFO0FREE|FIFO1FREE jne . + 3;
95 and SBLKCTL, ~DIAGLEDEN|DIAGLEDON; 136 and SBLKCTL, ~DIAGLEDEN|DIAGLEDON;
@@ -101,9 +142,9 @@ idle_loop_check_nonpackreq:
101 call idle_loop_cchan; 142 call idle_loop_cchan;
102 jmp idle_loop; 143 jmp idle_loop;
103 144
104BEGIN_CRITICAL;
105idle_loop_gsfifo: 145idle_loop_gsfifo:
106 SET_MODE(M_SCSI, M_SCSI) 146 SET_MODE(M_SCSI, M_SCSI)
147BEGIN_CRITICAL;
107idle_loop_gsfifo_in_scsi_mode: 148idle_loop_gsfifo_in_scsi_mode:
108 test LQISTAT2, LQIGSAVAIL jz return; 149 test LQISTAT2, LQIGSAVAIL jz return;
109 /* 150 /*
@@ -152,11 +193,15 @@ END_CRITICAL;
152 193
153idle_loop_service_fifos: 194idle_loop_service_fifos:
154 SET_MODE(M_DFF0, M_DFF0) 195 SET_MODE(M_DFF0, M_DFF0)
196BEGIN_CRITICAL;
155 test LONGJMP_ADDR[1], INVALID_ADDR jnz idle_loop_next_fifo; 197 test LONGJMP_ADDR[1], INVALID_ADDR jnz idle_loop_next_fifo;
156 call longjmp; 198 call longjmp;
199END_CRITICAL;
157idle_loop_next_fifo: 200idle_loop_next_fifo:
158 SET_MODE(M_DFF1, M_DFF1) 201 SET_MODE(M_DFF1, M_DFF1)
202BEGIN_CRITICAL;
159 test LONGJMP_ADDR[1], INVALID_ADDR jz longjmp; 203 test LONGJMP_ADDR[1], INVALID_ADDR jz longjmp;
204END_CRITICAL;
160return: 205return:
161 ret; 206 ret;
162 207
@@ -170,7 +215,6 @@ BEGIN_CRITICAL;
170 test CCSCBCTL, CCARREN|CCSCBEN jz scbdma_idle; 215 test CCSCBCTL, CCARREN|CCSCBEN jz scbdma_idle;
171 test CCSCBCTL, CCSCBDIR jnz fetch_new_scb_inprog; 216 test CCSCBCTL, CCSCBDIR jnz fetch_new_scb_inprog;
172 test CCSCBCTL, CCSCBDONE jz return; 217 test CCSCBCTL, CCSCBDONE jz return;
173END_CRITICAL;
174 /* FALLTHROUGH */ 218 /* FALLTHROUGH */
175scbdma_tohost_done: 219scbdma_tohost_done:
176 test CCSCBCTL, CCARREN jz fill_qoutfifo_dmadone; 220 test CCSCBCTL, CCARREN jz fill_qoutfifo_dmadone;
@@ -180,26 +224,18 @@ scbdma_tohost_done:
180 * bad SCSI status (currently only for underruns), we 224 * bad SCSI status (currently only for underruns), we
181 * queue the SCB for normal completion. Otherwise, we 225 * queue the SCB for normal completion. Otherwise, we
182 * wait until any select-out activity has halted, and 226 * wait until any select-out activity has halted, and
183 * then notify the host so that the transaction can be 227 * then queue the completion.
184 * dealt with.
185 */ 228 */
186 test SCB_SCSI_STATUS, 0xff jnz scbdma_notify_host;
187 and CCSCBCTL, ~(CCARREN|CCSCBEN); 229 and CCSCBCTL, ~(CCARREN|CCSCBEN);
188 bmov COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2; 230 bmov COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2;
231 cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL jne . + 2;
232 mvi COMPLETE_DMA_SCB_TAIL[1], SCB_LIST_NULL;
233 test SCB_SCSI_STATUS, 0xff jz scbdma_queue_completion;
234 bmov SCB_NEXT_COMPLETE, COMPLETE_ON_QFREEZE_HEAD, 2;
235 bmov COMPLETE_ON_QFREEZE_HEAD, SCBPTR, 2 ret;
236scbdma_queue_completion:
189 bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2; 237 bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2;
190 bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret; 238 bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret;
191scbdma_notify_host:
192 SET_MODE(M_SCSI, M_SCSI)
193 test SCSISEQ0, ENSELO jnz return;
194 test SSTAT0, (SELDO|SELINGO) jnz return;
195 SET_MODE(M_CCHAN, M_CCHAN)
196 /*
197 * Remove SCB and notify host.
198 */
199 and CCSCBCTL, ~(CCARREN|CCSCBEN);
200 bmov COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2;
201 SET_SEQINTCODE(BAD_SCB_STATUS)
202 ret;
203fill_qoutfifo_dmadone: 239fill_qoutfifo_dmadone:
204 and CCSCBCTL, ~(CCARREN|CCSCBEN); 240 and CCSCBCTL, ~(CCARREN|CCSCBEN);
205 call qoutfifo_updated; 241 call qoutfifo_updated;
@@ -208,6 +244,7 @@ fill_qoutfifo_dmadone:
208 test QOFF_CTLSTA, SDSCB_ROLLOVR jz return; 244 test QOFF_CTLSTA, SDSCB_ROLLOVR jz return;
209 bmov QOUTFIFO_NEXT_ADDR, SHARED_DATA_ADDR, 4; 245 bmov QOUTFIFO_NEXT_ADDR, SHARED_DATA_ADDR, 4;
210 xor QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID_TOGGLE ret; 246 xor QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID_TOGGLE ret;
247END_CRITICAL;
211 248
212qoutfifo_updated: 249qoutfifo_updated:
213 /* 250 /*
@@ -324,14 +361,15 @@ fill_qoutfifo:
324 * Keep track of the SCBs we are dmaing just 361 * Keep track of the SCBs we are dmaing just
325 * in case the DMA fails or is aborted. 362 * in case the DMA fails or is aborted.
326 */ 363 */
327 mov A, QOUTFIFO_ENTRY_VALID_TAG;
328 bmov COMPLETE_SCB_DMAINPROG_HEAD, COMPLETE_SCB_HEAD, 2; 364 bmov COMPLETE_SCB_DMAINPROG_HEAD, COMPLETE_SCB_HEAD, 2;
329 mvi CCSCBCTL, CCSCBRESET; 365 mvi CCSCBCTL, CCSCBRESET;
330 bmov SCBHADDR, QOUTFIFO_NEXT_ADDR, 4; 366 bmov SCBHADDR, QOUTFIFO_NEXT_ADDR, 4;
367 mov A, QOUTFIFO_NEXT_ADDR;
331 bmov SCBPTR, COMPLETE_SCB_HEAD, 2; 368 bmov SCBPTR, COMPLETE_SCB_HEAD, 2;
332fill_qoutfifo_loop: 369fill_qoutfifo_loop:
333 mov CCSCBRAM, SCBPTR; 370 bmov CCSCBRAM, SCBPTR, 2;
334 or CCSCBRAM, A, SCBPTR[1]; 371 mov CCSCBRAM, SCB_SGPTR[0];
372 mov CCSCBRAM, QOUTFIFO_ENTRY_VALID_TAG;
335 mov NONE, SDSCB_QOFF; 373 mov NONE, SDSCB_QOFF;
336 inc INT_COALESCING_CMDCOUNT; 374 inc INT_COALESCING_CMDCOUNT;
337 add CMDS_PENDING, -1; 375 add CMDS_PENDING, -1;
@@ -339,6 +377,18 @@ fill_qoutfifo_loop:
339 cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL je fill_qoutfifo_done; 377 cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL je fill_qoutfifo_done;
340 cmp CCSCBADDR, CCSCBADDR_MAX je fill_qoutfifo_done; 378 cmp CCSCBADDR, CCSCBADDR_MAX je fill_qoutfifo_done;
341 test QOFF_CTLSTA, SDSCB_ROLLOVR jnz fill_qoutfifo_done; 379 test QOFF_CTLSTA, SDSCB_ROLLOVR jnz fill_qoutfifo_done;
380 /*
381 * Don't cross an ADB or Cachline boundary when DMA'ing
382 * completion entries. In PCI mode, at least in 32/33
383 * configurations, the SCB DMA engine may lose its place
384 * in the data-stream should the target force a retry on
385 * something other than an 8byte aligned boundary. In
386 * PCI-X mode, we do this to avoid split transactions since
387 * many chipsets seem to be unable to format proper split
388 * completions to continue the data transfer.
389 */
390 add SINDEX, A, CCSCBADDR;
391 test SINDEX, CACHELINE_MASK jz fill_qoutfifo_done;
342 bmov SCBPTR, SCB_NEXT_COMPLETE, 2; 392 bmov SCBPTR, SCB_NEXT_COMPLETE, 2;
343 jmp fill_qoutfifo_loop; 393 jmp fill_qoutfifo_loop;
344fill_qoutfifo_done: 394fill_qoutfifo_done:
@@ -354,7 +404,6 @@ dma_complete_scb:
354 bmov SCBPTR, COMPLETE_DMA_SCB_HEAD, 2; 404 bmov SCBPTR, COMPLETE_DMA_SCB_HEAD, 2;
355 bmov SCBHADDR, SCB_BUSADDR, 4; 405 bmov SCBHADDR, SCB_BUSADDR, 4;
356 mvi CCARREN|CCSCBEN|CCSCBRESET jmp dma_scb; 406 mvi CCARREN|CCSCBEN|CCSCBRESET jmp dma_scb;
357END_CRITICAL;
358 407
359/* 408/*
360 * Either post or fetch an SCB from host memory. The caller 409 * Either post or fetch an SCB from host memory. The caller
@@ -371,9 +420,19 @@ dma_scb:
371 mvi SCBHCNT, SCB_TRANSFER_SIZE; 420 mvi SCBHCNT, SCB_TRANSFER_SIZE;
372 mov CCSCBCTL, SINDEX ret; 421 mov CCSCBCTL, SINDEX ret;
373 422
374BEGIN_CRITICAL;
375setjmp: 423setjmp:
376 bmov LONGJMP_ADDR, STACK, 2 ret; 424 /*
425 * At least on the A, a return in the same
426 * instruction as the bmov results in a return
427 * to the caller, not to the new address at the
428 * top of the stack. Since we want the latter
429 * (we use setjmp to register a handler from an
430 * interrupt context but not invoke that handler
431 * until we return to our idle loop), use a
432 * separate ret instruction.
433 */
434 bmov LONGJMP_ADDR, STACK, 2;
435 ret;
377setjmp_inline: 436setjmp_inline:
378 bmov LONGJMP_ADDR, STACK, 2; 437 bmov LONGJMP_ADDR, STACK, 2;
379longjmp: 438longjmp:
@@ -392,11 +451,6 @@ set_mode_work_around:
392 mvi SEQINTCTL, INTVEC1DSL; 451 mvi SEQINTCTL, INTVEC1DSL;
393 mov MODE_PTR, SINDEX; 452 mov MODE_PTR, SINDEX;
394 clr SEQINTCTL ret; 453 clr SEQINTCTL ret;
395
396toggle_dff_mode_work_around:
397 mvi SEQINTCTL, INTVEC1DSL;
398 xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1);
399 clr SEQINTCTL ret;
400} 454}
401 455
402 456
@@ -490,6 +544,21 @@ allocate_fifo1:
490SET_SRC_MODE M_SCSI; 544SET_SRC_MODE M_SCSI;
491SET_DST_MODE M_SCSI; 545SET_DST_MODE M_SCSI;
492select_in: 546select_in:
547 if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) {
548 /*
549 * On Rev A. hardware, the busy LED is only
550 * turned on automaically during selections
551 * and re-selections. Make the LED status
552 * more useful by forcing it to be on from
553 * the point of selection until our idle
554 * loop determines that neither of our FIFOs
555 * are busy. This handles the non-packetized
556 * case nicely as we will not return to the
557 * idle loop until the busfree at the end of
558 * each transaction.
559 */
560 or SBLKCTL, DIAGLEDEN|DIAGLEDON;
561 }
493 if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) { 562 if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) {
494 /* 563 /*
495 * Test to ensure that the bus has not 564 * Test to ensure that the bus has not
@@ -528,6 +597,21 @@ SET_SRC_MODE M_SCSI;
528SET_DST_MODE M_SCSI; 597SET_DST_MODE M_SCSI;
529select_out: 598select_out:
530BEGIN_CRITICAL; 599BEGIN_CRITICAL;
600 if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) {
601 /*
602 * On Rev A. hardware, the busy LED is only
603 * turned on automaically during selections
604 * and re-selections. Make the LED status
605 * more useful by forcing it to be on from
606 * the point of re-selection until our idle
607 * loop determines that neither of our FIFOs
608 * are busy. This handles the non-packetized
609 * case nicely as we will not return to the
610 * idle loop until the busfree at the end of
611 * each transaction.
612 */
613 or SBLKCTL, DIAGLEDEN|DIAGLEDON;
614 }
531 /* Clear out all SCBs that have been successfully sent. */ 615 /* Clear out all SCBs that have been successfully sent. */
532 if ((ahd->bugs & AHD_SENT_SCB_UPDATE_BUG) != 0) { 616 if ((ahd->bugs & AHD_SENT_SCB_UPDATE_BUG) != 0) {
533 /* 617 /*
@@ -1000,15 +1084,9 @@ not_found_ITloop:
1000/* 1084/*
1001 * We received a "command complete" message. Put the SCB on the complete 1085 * We received a "command complete" message. Put the SCB on the complete
1002 * queue and trigger a completion interrupt via the idle loop. Before doing 1086 * queue and trigger a completion interrupt via the idle loop. Before doing
1003 * so, check to see if there 1087 * so, check to see if there is a residual or the status byte is something
1004 * is a residual or the status byte is something other than STATUS_GOOD (0). 1088 * other than STATUS_GOOD (0). In either of these conditions, we upload the
1005 * In either of these conditions, we upload the SCB back to the host so it can 1089 * SCB back to the host so it can process this information.
1006 * process this information. In the case of a non zero status byte, we
1007 * additionally interrupt the kernel driver synchronously, allowing it to
1008 * decide if sense should be retrieved. If the kernel driver wishes to request
1009 * sense, it will fill the kernel SCB with a request sense command, requeue
1010 * it to the QINFIFO and tell us not to post to the QOUTFIFO by setting
1011 * RETURN_1 to SEND_SENSE.
1012 */ 1090 */
1013mesgin_complete: 1091mesgin_complete:
1014 1092
@@ -1053,6 +1131,7 @@ complete_nomsg:
1053 call queue_scb_completion; 1131 call queue_scb_completion;
1054 jmp await_busfree; 1132 jmp await_busfree;
1055 1133
1134BEGIN_CRITICAL;
1056freeze_queue: 1135freeze_queue:
1057 /* Cancel any pending select-out. */ 1136 /* Cancel any pending select-out. */
1058 test SSTAT0, SELDO|SELINGO jnz . + 2; 1137 test SSTAT0, SELDO|SELINGO jnz . + 2;
@@ -1063,6 +1142,7 @@ freeze_queue:
1063 adc QFREEZE_COUNT[1], A; 1142 adc QFREEZE_COUNT[1], A;
1064 or SEQ_FLAGS2, SELECTOUT_QFROZEN; 1143 or SEQ_FLAGS2, SELECTOUT_QFROZEN;
1065 mov A, ACCUM_SAVE ret; 1144 mov A, ACCUM_SAVE ret;
1145END_CRITICAL;
1066 1146
1067/* 1147/*
1068 * Complete the current FIFO's SCB if data for this same 1148 * Complete the current FIFO's SCB if data for this same
@@ -1085,8 +1165,10 @@ queue_scb_completion:
1085 test SCB_SGPTR, SG_FULL_RESID jnz upload_scb;/* Never xfered */ 1165 test SCB_SGPTR, SG_FULL_RESID jnz upload_scb;/* Never xfered */
1086 test SCB_RESIDUAL_SGPTR, SG_LIST_NULL jz upload_scb; 1166 test SCB_RESIDUAL_SGPTR, SG_LIST_NULL jz upload_scb;
1087complete: 1167complete:
1168BEGIN_CRITICAL;
1088 bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2; 1169 bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2;
1089 bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret; 1170 bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret;
1171END_CRITICAL;
1090bad_status: 1172bad_status:
1091 cmp SCB_SCSI_STATUS, STATUS_PKT_SENSE je upload_scb; 1173 cmp SCB_SCSI_STATUS, STATUS_PKT_SENSE je upload_scb;
1092 call freeze_queue; 1174 call freeze_queue;
@@ -1097,9 +1179,18 @@ upload_scb:
1097 * it on the host. 1179 * it on the host.
1098 */ 1180 */
1099 bmov SCB_TAG, SCBPTR, 2; 1181 bmov SCB_TAG, SCBPTR, 2;
1100 bmov SCB_NEXT_COMPLETE, COMPLETE_DMA_SCB_HEAD, 2; 1182BEGIN_CRITICAL;
1183 or SCB_SGPTR, SG_STATUS_VALID;
1184 mvi SCB_NEXT_COMPLETE[1], SCB_LIST_NULL;
1185 cmp COMPLETE_DMA_SCB_HEAD[1], SCB_LIST_NULL jne add_dma_scb_tail;
1101 bmov COMPLETE_DMA_SCB_HEAD, SCBPTR, 2; 1186 bmov COMPLETE_DMA_SCB_HEAD, SCBPTR, 2;
1102 or SCB_SGPTR, SG_STATUS_VALID ret; 1187 bmov COMPLETE_DMA_SCB_TAIL, SCBPTR, 2 ret;
1188add_dma_scb_tail:
1189 bmov REG0, SCBPTR, 2;
1190 bmov SCBPTR, COMPLETE_DMA_SCB_TAIL, 2;
1191 bmov SCB_NEXT_COMPLETE, REG0, 2;
1192 bmov COMPLETE_DMA_SCB_TAIL, REG0, 2 ret;
1193END_CRITICAL;
1103 1194
1104/* 1195/*
1105 * Is it a disconnect message? Set a flag in the SCB to remind us 1196 * Is it a disconnect message? Set a flag in the SCB to remind us
@@ -1146,8 +1237,18 @@ SET_DST_MODE M_DFF1;
1146await_busfree_clrchn: 1237await_busfree_clrchn:
1147 mvi DFFSXFRCTL, CLRCHN; 1238 mvi DFFSXFRCTL, CLRCHN;
1148await_busfree_not_m_dff: 1239await_busfree_not_m_dff:
1149 call clear_target_state; 1240 /* clear target specific flags */
1241 mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT;
1150 test SSTAT1,REQINIT|BUSFREE jz .; 1242 test SSTAT1,REQINIT|BUSFREE jz .;
1243 /*
1244 * We only set BUSFREE status once either a new
1245 * phase has been detected or we are really
1246 * BUSFREE. This allows the driver to know
1247 * that we are active on the bus even though
1248 * no identified transaction exists should a
1249 * timeout occur while awaiting busfree.
1250 */
1251 mvi LASTPHASE, P_BUSFREE;
1151 test SSTAT1, BUSFREE jnz idle_loop; 1252 test SSTAT1, BUSFREE jnz idle_loop;
1152 SET_SEQINTCODE(MISSED_BUSFREE) 1253 SET_SEQINTCODE(MISSED_BUSFREE)
1153 1254
@@ -1202,11 +1303,6 @@ msgin_rdptrs_get_fifo:
1202 call allocate_fifo; 1303 call allocate_fifo;
1203 jmp mesgin_done; 1304 jmp mesgin_done;
1204 1305
1205clear_target_state:
1206 mvi LASTPHASE, P_BUSFREE;
1207 /* clear target specific flags */
1208 mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT ret;
1209
1210phase_lock: 1306phase_lock:
1211 if ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0) { 1307 if ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0) {
1212 /* 1308 /*
@@ -1298,6 +1394,47 @@ service_fifo:
1298 test CCSGCTL, CCSGENACK jnz return; 1394 test CCSGCTL, CCSGENACK jnz return;
1299 1395
1300 /* 1396 /*
1397 * Should the other FIFO get the S/G cache first? If
1398 * both FIFOs have been allocated since we last checked
1399 * any FIFO, it is important that we service a FIFO
1400 * that is not actively on the bus first. This guarantees
1401 * that a FIFO will be freed to handle snapshot requests for
1402 * any FIFO that is still on the bus. Chips with RTI do not
1403 * perform snapshots, so don't bother with this test there.
1404 */
1405 if ((ahd->features & AHD_RTI) == 0) {
1406 /*
1407 * If we're not still receiving SCSI data,
1408 * it is safe to allocate the S/G cache to
1409 * this FIFO.
1410 */
1411 test DFCNTRL, SCSIEN jz idle_sgfetch_start;
1412
1413 /*
1414 * Switch to the other FIFO. Non-RTI chips
1415 * also have the "set mode" bug, so we must
1416 * disable interrupts during the switch.
1417 */
1418 mvi SEQINTCTL, INTVEC1DSL;
1419 xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1);
1420
1421 /*
1422 * If the other FIFO needs loading, then it
1423 * must not have claimed the S/G cache yet
1424 * (SG_CACHE_AVAIL would have been cleared in
1425 * the orginal FIFO mode and we test this above).
1426 * Return to the idle loop so we can process the
1427 * FIFO not currently on the bus first.
1428 */
1429 test SG_STATE, LOADING_NEEDED jz idle_sgfetch_okay;
1430 clr SEQINTCTL ret;
1431idle_sgfetch_okay:
1432 xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1);
1433 clr SEQINTCTL;
1434 }
1435
1436idle_sgfetch_start:
1437 /*
1301 * We fetch a "cacheline aligned" and sized amount of data 1438 * We fetch a "cacheline aligned" and sized amount of data
1302 * so we don't end up referencing a non-existant page. 1439 * so we don't end up referencing a non-existant page.
1303 * Cacheline aligned is in quotes because the kernel will 1440 * Cacheline aligned is in quotes because the kernel will
@@ -1308,7 +1445,7 @@ service_fifo:
1308 mvi SGHCNT, SG_PREFETCH_CNT; 1445 mvi SGHCNT, SG_PREFETCH_CNT;
1309 if ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0) { 1446 if ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0) {
1310 /* 1447 /*
1311 * Need two instruction between "touches" of SGHADDR. 1448 * Need two instructions between "touches" of SGHADDR.
1312 */ 1449 */
1313 nop; 1450 nop;
1314 } 1451 }
@@ -1658,7 +1795,7 @@ export seq_isr:
1658 * savepointer in the current FIFO. We do this so that 1795 * savepointer in the current FIFO. We do this so that
1659 * a pending CTXTDONE or SAVEPTR is visible in the active 1796 * a pending CTXTDONE or SAVEPTR is visible in the active
1660 * FIFO. This status is the only way we can detect if we 1797 * FIFO. This status is the only way we can detect if we
1661 * have lost the race (e.g. host paused us) and our attepts 1798 * have lost the race (e.g. host paused us) and our attempts
1662 * to disable the channel occurred after all REQs were 1799 * to disable the channel occurred after all REQs were
1663 * already seen and acked (REQINIT never comes true). 1800 * already seen and acked (REQINIT never comes true).
1664 */ 1801 */
@@ -1667,7 +1804,7 @@ export seq_isr:
1667 test DFCNTRL, DIRECTION jz interrupt_return; 1804 test DFCNTRL, DIRECTION jz interrupt_return;
1668 and DFCNTRL, ~SCSIEN; 1805 and DFCNTRL, ~SCSIEN;
1669snapshot_wait_data_valid: 1806snapshot_wait_data_valid:
1670 test SEQINTSRC, (CTXTDONE|SAVEPTRS) jnz snapshot_data_valid; 1807 test SEQINTSRC, (CTXTDONE|SAVEPTRS) jnz interrupt_return;
1671 test SSTAT1, REQINIT jz snapshot_wait_data_valid; 1808 test SSTAT1, REQINIT jz snapshot_wait_data_valid;
1672snapshot_data_valid: 1809snapshot_data_valid:
1673 or DFCNTRL, SCSIEN; 1810 or DFCNTRL, SCSIEN;
@@ -1834,7 +1971,6 @@ pkt_saveptrs_check_status:
1834 dec SCB_FIFO_USE_COUNT; 1971 dec SCB_FIFO_USE_COUNT;
1835 test SCB_CONTROL, STATUS_RCVD jnz pkt_complete_scb_if_fifos_idle; 1972 test SCB_CONTROL, STATUS_RCVD jnz pkt_complete_scb_if_fifos_idle;
1836 mvi DFFSXFRCTL, CLRCHN ret; 1973 mvi DFFSXFRCTL, CLRCHN ret;
1837END_CRITICAL;
1838 1974
1839/* 1975/*
1840 * LAST_SEG_DONE status has been seen in the current FIFO. 1976 * LAST_SEG_DONE status has been seen in the current FIFO.
@@ -1843,7 +1979,6 @@ END_CRITICAL;
1843 * Check for overrun and see if we can complete this command. 1979 * Check for overrun and see if we can complete this command.
1844 */ 1980 */
1845pkt_last_seg_done: 1981pkt_last_seg_done:
1846BEGIN_CRITICAL;
1847 /* 1982 /*
1848 * Mark transfer as completed. 1983 * Mark transfer as completed.
1849 */ 1984 */
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c
index 4e8f00df978d..db8f5ce99ee3 100644
--- a/drivers/scsi/aic7xxx/aic79xx_core.c
+++ b/drivers/scsi/aic7xxx/aic79xx_core.c
@@ -37,9 +37,7 @@
37 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGES. 38 * POSSIBILITY OF SUCH DAMAGES.
39 * 39 *
40 * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#202 $ 40 * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#247 $
41 *
42 * $FreeBSD$
43 */ 41 */
44 42
45#ifdef __linux__ 43#ifdef __linux__
@@ -332,6 +330,14 @@ ahd_restart(struct ahd_softc *ahd)
332 ahd_outb(ahd, SCSISEQ1, 330 ahd_outb(ahd, SCSISEQ1,
333 ahd_inb(ahd, SCSISEQ_TEMPLATE) & (ENSELI|ENRSELI|ENAUTOATNP)); 331 ahd_inb(ahd, SCSISEQ_TEMPLATE) & (ENSELI|ENRSELI|ENAUTOATNP));
334 ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN); 332 ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
333
334 /*
335 * Clear any pending sequencer interrupt. It is no
336 * longer relevant since we're resetting the Program
337 * Counter.
338 */
339 ahd_outb(ahd, CLRINT, CLRSEQINT);
340
335 ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET); 341 ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET);
336 ahd_unpause(ahd); 342 ahd_unpause(ahd);
337} 343}
@@ -373,13 +379,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
373 saved_modes = ahd_save_modes(ahd); 379 saved_modes = ahd_save_modes(ahd);
374 380
375 /* 381 /*
376 * Complete any SCBs that just finished being 382 * Flush the good status FIFO for completed packetized commands.
377 * DMA'ed into the qoutfifo.
378 */
379 ahd_run_qoutfifo(ahd);
380
381 /*
382 * Flush the good status FIFO for compelted packetized commands.
383 */ 383 */
384 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); 384 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
385 saved_scbptr = ahd_get_scbptr(ahd); 385 saved_scbptr = ahd_get_scbptr(ahd);
@@ -387,8 +387,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
387 u_int fifo_mode; 387 u_int fifo_mode;
388 u_int i; 388 u_int i;
389 389
390 scbid = (ahd_inb(ahd, GSFIFO+1) << 8) 390 scbid = ahd_inw(ahd, GSFIFO);
391 | ahd_inb(ahd, GSFIFO);
392 scb = ahd_lookup_scb(ahd, scbid); 391 scb = ahd_lookup_scb(ahd, scbid);
393 if (scb == NULL) { 392 if (scb == NULL) {
394 printf("%s: Warning - GSFIFO SCB %d invalid\n", 393 printf("%s: Warning - GSFIFO SCB %d invalid\n",
@@ -401,22 +400,33 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
401 * the host before completing the command. 400 * the host before completing the command.
402 */ 401 */
403 fifo_mode = 0; 402 fifo_mode = 0;
403rescan_fifos:
404 for (i = 0; i < 2; i++) { 404 for (i = 0; i < 2; i++) {
405 /* Toggle to the other mode. */ 405 /* Toggle to the other mode. */
406 fifo_mode ^= 1; 406 fifo_mode ^= 1;
407 ahd_set_modes(ahd, fifo_mode, fifo_mode); 407 ahd_set_modes(ahd, fifo_mode, fifo_mode);
408
408 if (ahd_scb_active_in_fifo(ahd, scb) == 0) 409 if (ahd_scb_active_in_fifo(ahd, scb) == 0)
409 continue; 410 continue;
410 411
411 ahd_run_data_fifo(ahd, scb); 412 ahd_run_data_fifo(ahd, scb);
412 413
413 /* 414 /*
414 * Clearing this transaction in this FIFO may 415 * Running this FIFO may cause a CFG4DATA for
415 * cause a CFG4DATA for this same transaction 416 * this same transaction to assert in the other
416 * to assert in the other FIFO. Make sure we 417 * FIFO or a new snapshot SAVEPTRS interrupt
417 * loop one more time and check the other FIFO. 418 * in this FIFO. Even running a FIFO may not
419 * clear the transaction if we are still waiting
420 * for data to drain to the host. We must loop
421 * until the transaction is not active in either
422 * FIFO just to be sure. Reset our loop counter
423 * so we will visit both FIFOs again before
424 * declaring this transaction finished. We
425 * also delay a bit so that status has a chance
426 * to change before we look at this FIFO again.
418 */ 427 */
419 i = 0; 428 ahd_delay(200);
429 goto rescan_fifos;
420 } 430 }
421 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); 431 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
422 ahd_set_scbptr(ahd, scbid); 432 ahd_set_scbptr(ahd, scbid);
@@ -429,19 +439,28 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
429 /* 439 /*
430 * The transfer completed with a residual. 440 * The transfer completed with a residual.
431 * Place this SCB on the complete DMA list 441 * Place this SCB on the complete DMA list
432 * so that we Update our in-core copy of the 442 * so that we update our in-core copy of the
433 * SCB before completing the command. 443 * SCB before completing the command.
434 */ 444 */
435 ahd_outb(ahd, SCB_SCSI_STATUS, 0); 445 ahd_outb(ahd, SCB_SCSI_STATUS, 0);
436 ahd_outb(ahd, SCB_SGPTR, 446 ahd_outb(ahd, SCB_SGPTR,
437 ahd_inb_scbram(ahd, SCB_SGPTR) 447 ahd_inb_scbram(ahd, SCB_SGPTR)
438 | SG_STATUS_VALID); 448 | SG_STATUS_VALID);
439 ahd_outw(ahd, SCB_TAG, SCB_GET_TAG(scb)); 449 ahd_outw(ahd, SCB_TAG, scbid);
450 ahd_outw(ahd, SCB_NEXT_COMPLETE, SCB_LIST_NULL);
440 comp_head = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD); 451 comp_head = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD);
441 ahd_outw(ahd, SCB_NEXT_COMPLETE, comp_head); 452 if (SCBID_IS_NULL(comp_head)) {
442 if (SCBID_IS_NULL(comp_head)) 453 ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, scbid);
443 ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, 454 ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, scbid);
444 SCB_GET_TAG(scb)); 455 } else {
456 u_int tail;
457
458 tail = ahd_inw(ahd, COMPLETE_DMA_SCB_TAIL);
459 ahd_set_scbptr(ahd, tail);
460 ahd_outw(ahd, SCB_NEXT_COMPLETE, scbid);
461 ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, scbid);
462 ahd_set_scbptr(ahd, scbid);
463 }
445 } else 464 } else
446 ahd_complete_scb(ahd, scb); 465 ahd_complete_scb(ahd, scb);
447 } 466 }
@@ -465,9 +484,22 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
465 break; 484 break;
466 ahd_delay(200); 485 ahd_delay(200);
467 } 486 }
468 if ((ccscbctl & CCSCBDIR) != 0) 487 /*
488 * We leave the sequencer to cleanup in the case of DMA's to
489 * update the qoutfifo. In all other cases (DMA's to the
490 * chip or a push of an SCB from the COMPLETE_DMA_SCB list),
491 * we disable the DMA engine so that the sequencer will not
492 * attempt to handle the DMA completion.
493 */
494 if ((ccscbctl & CCSCBDIR) != 0 || (ccscbctl & ARRDONE) != 0)
469 ahd_outb(ahd, CCSCBCTL, ccscbctl & ~(CCARREN|CCSCBEN)); 495 ahd_outb(ahd, CCSCBCTL, ccscbctl & ~(CCARREN|CCSCBEN));
470 496
497 /*
498 * Complete any SCBs that just finished
499 * being DMA'ed into the qoutfifo.
500 */
501 ahd_run_qoutfifo(ahd);
502
471 saved_scbptr = ahd_get_scbptr(ahd); 503 saved_scbptr = ahd_get_scbptr(ahd);
472 /* 504 /*
473 * Manually update/complete any completed SCBs that are waiting to be 505 * Manually update/complete any completed SCBs that are waiting to be
@@ -494,6 +526,24 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
494 scbid = next_scbid; 526 scbid = next_scbid;
495 } 527 }
496 ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL); 528 ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL);
529 ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, SCB_LIST_NULL);
530
531 scbid = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD);
532 while (!SCBID_IS_NULL(scbid)) {
533
534 ahd_set_scbptr(ahd, scbid);
535 next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
536 scb = ahd_lookup_scb(ahd, scbid);
537 if (scb == NULL) {
538 printf("%s: Warning - Complete Qfrz SCB %d invalid\n",
539 ahd_name(ahd), scbid);
540 continue;
541 }
542
543 ahd_complete_scb(ahd, scb);
544 scbid = next_scbid;
545 }
546 ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD, SCB_LIST_NULL);
497 547
498 scbid = ahd_inw(ahd, COMPLETE_SCB_HEAD); 548 scbid = ahd_inw(ahd, COMPLETE_SCB_HEAD);
499 while (!SCBID_IS_NULL(scbid)) { 549 while (!SCBID_IS_NULL(scbid)) {
@@ -558,150 +608,146 @@ ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb)
558{ 608{
559 u_int seqintsrc; 609 u_int seqintsrc;
560 610
561 while (1) { 611 seqintsrc = ahd_inb(ahd, SEQINTSRC);
562 seqintsrc = ahd_inb(ahd, SEQINTSRC); 612 if ((seqintsrc & CFG4DATA) != 0) {
563 if ((seqintsrc & CFG4DATA) != 0) { 613 uint32_t datacnt;
564 uint32_t datacnt; 614 uint32_t sgptr;
565 uint32_t sgptr;
566
567 /*
568 * Clear full residual flag.
569 */
570 sgptr = ahd_inl_scbram(ahd, SCB_SGPTR) & ~SG_FULL_RESID;
571 ahd_outb(ahd, SCB_SGPTR, sgptr);
572 615
573 /* 616 /*
574 * Load datacnt and address. 617 * Clear full residual flag.
575 */ 618 */
576 datacnt = ahd_inl_scbram(ahd, SCB_DATACNT); 619 sgptr = ahd_inl_scbram(ahd, SCB_SGPTR) & ~SG_FULL_RESID;
577 if ((datacnt & AHD_DMA_LAST_SEG) != 0) { 620 ahd_outb(ahd, SCB_SGPTR, sgptr);
578 sgptr |= LAST_SEG;
579 ahd_outb(ahd, SG_STATE, 0);
580 } else
581 ahd_outb(ahd, SG_STATE, LOADING_NEEDED);
582 ahd_outq(ahd, HADDR, ahd_inq_scbram(ahd, SCB_DATAPTR));
583 ahd_outl(ahd, HCNT, datacnt & AHD_SG_LEN_MASK);
584 ahd_outb(ahd, SG_CACHE_PRE, sgptr);
585 ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN);
586 621
587 /* 622 /*
588 * Initialize Residual Fields. 623 * Load datacnt and address.
589 */ 624 */
590 ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, datacnt >> 24); 625 datacnt = ahd_inl_scbram(ahd, SCB_DATACNT);
591 ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr & SG_PTR_MASK); 626 if ((datacnt & AHD_DMA_LAST_SEG) != 0) {
627 sgptr |= LAST_SEG;
628 ahd_outb(ahd, SG_STATE, 0);
629 } else
630 ahd_outb(ahd, SG_STATE, LOADING_NEEDED);
631 ahd_outq(ahd, HADDR, ahd_inq_scbram(ahd, SCB_DATAPTR));
632 ahd_outl(ahd, HCNT, datacnt & AHD_SG_LEN_MASK);
633 ahd_outb(ahd, SG_CACHE_PRE, sgptr);
634 ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN);
592 635
593 /* 636 /*
594 * Mark the SCB as having a FIFO in use. 637 * Initialize Residual Fields.
595 */ 638 */
596 ahd_outb(ahd, SCB_FIFO_USE_COUNT, 639 ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, datacnt >> 24);
597 ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) + 1); 640 ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr & SG_PTR_MASK);
598 641
599 /* 642 /*
600 * Install a "fake" handler for this FIFO. 643 * Mark the SCB as having a FIFO in use.
601 */ 644 */
602 ahd_outw(ahd, LONGJMP_ADDR, 0); 645 ahd_outb(ahd, SCB_FIFO_USE_COUNT,
646 ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) + 1);
603 647
604 /* 648 /*
605 * Notify the hardware that we have satisfied 649 * Install a "fake" handler for this FIFO.
606 * this sequencer interrupt. 650 */
607 */ 651 ahd_outw(ahd, LONGJMP_ADDR, 0);
608 ahd_outb(ahd, CLRSEQINTSRC, CLRCFG4DATA);
609 } else if ((seqintsrc & SAVEPTRS) != 0) {
610 uint32_t sgptr;
611 uint32_t resid;
612 652
613 if ((ahd_inb(ahd, LONGJMP_ADDR+1)&INVALID_ADDR) != 0) { 653 /*
614 /* 654 * Notify the hardware that we have satisfied
615 * Snapshot Save Pointers. Clear 655 * this sequencer interrupt.
616 * the snapshot and continue. 656 */
617 */ 657 ahd_outb(ahd, CLRSEQINTSRC, CLRCFG4DATA);
618 ahd_outb(ahd, DFFSXFRCTL, CLRCHN); 658 } else if ((seqintsrc & SAVEPTRS) != 0) {
619 continue; 659 uint32_t sgptr;
620 } 660 uint32_t resid;
621 661
662 if ((ahd_inb(ahd, LONGJMP_ADDR+1)&INVALID_ADDR) != 0) {
622 /* 663 /*
623 * Disable S/G fetch so the DMA engine 664 * Snapshot Save Pointers. All that
624 * is available to future users. 665 * is necessary to clear the snapshot
666 * is a CLRCHN.
625 */ 667 */
626 if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) 668 goto clrchn;
627 ahd_outb(ahd, CCSGCTL, 0); 669 }
628 ahd_outb(ahd, SG_STATE, 0);
629 670
630 /* 671 /*
631 * Flush the data FIFO. Strickly only 672 * Disable S/G fetch so the DMA engine
632 * necessary for Rev A parts. 673 * is available to future users.
633 */ 674 */
634 ahd_outb(ahd, DFCNTRL, 675 if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0)
635 ahd_inb(ahd, DFCNTRL) | FIFOFLUSH); 676 ahd_outb(ahd, CCSGCTL, 0);
677 ahd_outb(ahd, SG_STATE, 0);
636 678
637 /* 679 /*
638 * Calculate residual. 680 * Flush the data FIFO. Strickly only
639 */ 681 * necessary for Rev A parts.
640 sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR); 682 */
641 resid = ahd_inl(ahd, SHCNT); 683 ahd_outb(ahd, DFCNTRL, ahd_inb(ahd, DFCNTRL) | FIFOFLUSH);
642 resid |=
643 ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT+3) << 24;
644 ahd_outl(ahd, SCB_RESIDUAL_DATACNT, resid);
645 if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG) == 0) {
646 /*
647 * Must back up to the correct S/G element.
648 * Typically this just means resetting our
649 * low byte to the offset in the SG_CACHE,
650 * but if we wrapped, we have to correct
651 * the other bytes of the sgptr too.
652 */
653 if ((ahd_inb(ahd, SG_CACHE_SHADOW) & 0x80) != 0
654 && (sgptr & 0x80) == 0)
655 sgptr -= 0x100;
656 sgptr &= ~0xFF;
657 sgptr |= ahd_inb(ahd, SG_CACHE_SHADOW)
658 & SG_ADDR_MASK;
659 ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);
660 ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 3, 0);
661 } else if ((resid & AHD_SG_LEN_MASK) == 0) {
662 ahd_outb(ahd, SCB_RESIDUAL_SGPTR,
663 sgptr | SG_LIST_NULL);
664 }
665 /*
666 * Save Pointers.
667 */
668 ahd_outq(ahd, SCB_DATAPTR, ahd_inq(ahd, SHADDR));
669 ahd_outl(ahd, SCB_DATACNT, resid);
670 ahd_outl(ahd, SCB_SGPTR, sgptr);
671 ahd_outb(ahd, CLRSEQINTSRC, CLRSAVEPTRS);
672 ahd_outb(ahd, SEQIMODE,
673 ahd_inb(ahd, SEQIMODE) | ENSAVEPTRS);
674 /*
675 * If the data is to the SCSI bus, we are
676 * done, otherwise wait for FIFOEMP.
677 */
678 if ((ahd_inb(ahd, DFCNTRL) & DIRECTION) != 0)
679 break;
680 } else if ((ahd_inb(ahd, SG_STATE) & LOADING_NEEDED) != 0) {
681 uint32_t sgptr;
682 uint64_t data_addr;
683 uint32_t data_len;
684 u_int dfcntrl;
685 684
685 /*
686 * Calculate residual.
687 */
688 sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
689 resid = ahd_inl(ahd, SHCNT);
690 resid |= ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT+3) << 24;
691 ahd_outl(ahd, SCB_RESIDUAL_DATACNT, resid);
692 if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG) == 0) {
686 /* 693 /*
687 * Disable S/G fetch so the DMA engine 694 * Must back up to the correct S/G element.
688 * is available to future users. 695 * Typically this just means resetting our
696 * low byte to the offset in the SG_CACHE,
697 * but if we wrapped, we have to correct
698 * the other bytes of the sgptr too.
689 */ 699 */
690 if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) { 700 if ((ahd_inb(ahd, SG_CACHE_SHADOW) & 0x80) != 0
691 ahd_outb(ahd, CCSGCTL, 0); 701 && (sgptr & 0x80) == 0)
692 ahd_outb(ahd, SG_STATE, LOADING_NEEDED); 702 sgptr -= 0x100;
693 } 703 sgptr &= ~0xFF;
704 sgptr |= ahd_inb(ahd, SG_CACHE_SHADOW)
705 & SG_ADDR_MASK;
706 ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);
707 ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 3, 0);
708 } else if ((resid & AHD_SG_LEN_MASK) == 0) {
709 ahd_outb(ahd, SCB_RESIDUAL_SGPTR,
710 sgptr | SG_LIST_NULL);
711 }
712 /*
713 * Save Pointers.
714 */
715 ahd_outq(ahd, SCB_DATAPTR, ahd_inq(ahd, SHADDR));
716 ahd_outl(ahd, SCB_DATACNT, resid);
717 ahd_outl(ahd, SCB_SGPTR, sgptr);
718 ahd_outb(ahd, CLRSEQINTSRC, CLRSAVEPTRS);
719 ahd_outb(ahd, SEQIMODE,
720 ahd_inb(ahd, SEQIMODE) | ENSAVEPTRS);
721 /*
722 * If the data is to the SCSI bus, we are
723 * done, otherwise wait for FIFOEMP.
724 */
725 if ((ahd_inb(ahd, DFCNTRL) & DIRECTION) != 0)
726 goto clrchn;
727 } else if ((ahd_inb(ahd, SG_STATE) & LOADING_NEEDED) != 0) {
728 uint32_t sgptr;
729 uint64_t data_addr;
730 uint32_t data_len;
731 u_int dfcntrl;
694 732
695 /* 733 /*
696 * Wait for the DMA engine to notice that the 734 * Disable S/G fetch so the DMA engine
697 * host transfer is enabled and that there is 735 * is available to future users. We won't
698 * space in the S/G FIFO for new segments before 736 * be using the DMA engine to load segments.
699 * loading more segments. 737 */
700 */ 738 if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) {
701 if ((ahd_inb(ahd, DFSTATUS) & PRELOAD_AVAIL) == 0) 739 ahd_outb(ahd, CCSGCTL, 0);
702 continue; 740 ahd_outb(ahd, SG_STATE, LOADING_NEEDED);
703 if ((ahd_inb(ahd, DFCNTRL) & HDMAENACK) == 0) 741 }
704 continue; 742
743 /*
744 * Wait for the DMA engine to notice that the
745 * host transfer is enabled and that there is
746 * space in the S/G FIFO for new segments before
747 * loading more segments.
748 */
749 if ((ahd_inb(ahd, DFSTATUS) & PRELOAD_AVAIL) != 0
750 && (ahd_inb(ahd, DFCNTRL) & HDMAENACK) != 0) {
705 751
706 /* 752 /*
707 * Determine the offset of the next S/G 753 * Determine the offset of the next S/G
@@ -748,7 +794,7 @@ ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb)
748 * Advertise the segment to the hardware. 794 * Advertise the segment to the hardware.
749 */ 795 */
750 dfcntrl = ahd_inb(ahd, DFCNTRL)|PRELOADEN|HDMAEN; 796 dfcntrl = ahd_inb(ahd, DFCNTRL)|PRELOADEN|HDMAEN;
751 if ((ahd->features & AHD_NEW_DFCNTRL_OPTS)!=0) { 797 if ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0) {
752 /* 798 /*
753 * Use SCSIENWRDIS so that SCSIEN 799 * Use SCSIENWRDIS so that SCSIEN
754 * is never modified by this 800 * is never modified by this
@@ -757,35 +803,44 @@ ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb)
757 dfcntrl |= SCSIENWRDIS; 803 dfcntrl |= SCSIENWRDIS;
758 } 804 }
759 ahd_outb(ahd, DFCNTRL, dfcntrl); 805 ahd_outb(ahd, DFCNTRL, dfcntrl);
760 } else if ((ahd_inb(ahd, SG_CACHE_SHADOW)
761 & LAST_SEG_DONE) != 0) {
762
763 /*
764 * Transfer completed to the end of SG list
765 * and has flushed to the host.
766 */
767 ahd_outb(ahd, SCB_SGPTR,
768 ahd_inb_scbram(ahd, SCB_SGPTR) | SG_LIST_NULL);
769 break;
770 } else if ((ahd_inb(ahd, DFSTATUS) & FIFOEMP) != 0) {
771 break;
772 } 806 }
773 ahd_delay(200); 807 } else if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG_DONE) != 0) {
808
809 /*
810 * Transfer completed to the end of SG list
811 * and has flushed to the host.
812 */
813 ahd_outb(ahd, SCB_SGPTR,
814 ahd_inb_scbram(ahd, SCB_SGPTR) | SG_LIST_NULL);
815 goto clrchn;
816 } else if ((ahd_inb(ahd, DFSTATUS) & FIFOEMP) != 0) {
817clrchn:
818 /*
819 * Clear any handler for this FIFO, decrement
820 * the FIFO use count for the SCB, and release
821 * the FIFO.
822 */
823 ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR);
824 ahd_outb(ahd, SCB_FIFO_USE_COUNT,
825 ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) - 1);
826 ahd_outb(ahd, DFFSXFRCTL, CLRCHN);
774 } 827 }
775 /*
776 * Clear any handler for this FIFO, decrement
777 * the FIFO use count for the SCB, and release
778 * the FIFO.
779 */
780 ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR);
781 ahd_outb(ahd, SCB_FIFO_USE_COUNT,
782 ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) - 1);
783 ahd_outb(ahd, DFFSXFRCTL, CLRCHN);
784} 828}
785 829
830/*
831 * Look for entries in the QoutFIFO that have completed.
832 * The valid_tag completion field indicates the validity
833 * of the entry - the valid value toggles each time through
834 * the queue. We use the sg_status field in the completion
835 * entry to avoid referencing the hscb if the completion
836 * occurred with no errors and no residual. sg_status is
837 * a copy of the first byte (little endian) of the sgptr
838 * hscb field.
839 */
786void 840void
787ahd_run_qoutfifo(struct ahd_softc *ahd) 841ahd_run_qoutfifo(struct ahd_softc *ahd)
788{ 842{
843 struct ahd_completion *completion;
789 struct scb *scb; 844 struct scb *scb;
790 u_int scb_index; 845 u_int scb_index;
791 846
@@ -793,11 +848,13 @@ ahd_run_qoutfifo(struct ahd_softc *ahd)
793 panic("ahd_run_qoutfifo recursion"); 848 panic("ahd_run_qoutfifo recursion");
794 ahd->flags |= AHD_RUNNING_QOUTFIFO; 849 ahd->flags |= AHD_RUNNING_QOUTFIFO;
795 ahd_sync_qoutfifo(ahd, BUS_DMASYNC_POSTREAD); 850 ahd_sync_qoutfifo(ahd, BUS_DMASYNC_POSTREAD);
796 while ((ahd->qoutfifo[ahd->qoutfifonext] 851 for (;;) {
797 & QOUTFIFO_ENTRY_VALID_LE) == ahd->qoutfifonext_valid_tag) { 852 completion = &ahd->qoutfifo[ahd->qoutfifonext];
798 853
799 scb_index = ahd_le16toh(ahd->qoutfifo[ahd->qoutfifonext] 854 if (completion->valid_tag != ahd->qoutfifonext_valid_tag)
800 & ~QOUTFIFO_ENTRY_VALID_LE); 855 break;
856
857 scb_index = ahd_le16toh(completion->tag);
801 scb = ahd_lookup_scb(ahd, scb_index); 858 scb = ahd_lookup_scb(ahd, scb_index);
802 if (scb == NULL) { 859 if (scb == NULL) {
803 printf("%s: WARNING no command for scb %d " 860 printf("%s: WARNING no command for scb %d "
@@ -805,12 +862,15 @@ ahd_run_qoutfifo(struct ahd_softc *ahd)
805 ahd_name(ahd), scb_index, 862 ahd_name(ahd), scb_index,
806 ahd->qoutfifonext); 863 ahd->qoutfifonext);
807 ahd_dump_card_state(ahd); 864 ahd_dump_card_state(ahd);
808 } else 865 } else if ((completion->sg_status & SG_STATUS_VALID) != 0) {
809 ahd_complete_scb(ahd, scb); 866 ahd_handle_scb_status(ahd, scb);
867 } else {
868 ahd_done(ahd, scb);
869 }
810 870
811 ahd->qoutfifonext = (ahd->qoutfifonext+1) & (AHD_QOUT_SIZE-1); 871 ahd->qoutfifonext = (ahd->qoutfifonext+1) & (AHD_QOUT_SIZE-1);
812 if (ahd->qoutfifonext == 0) 872 if (ahd->qoutfifonext == 0)
813 ahd->qoutfifonext_valid_tag ^= QOUTFIFO_ENTRY_VALID_LE; 873 ahd->qoutfifonext_valid_tag ^= QOUTFIFO_ENTRY_VALID;
814 } 874 }
815 ahd->flags &= ~AHD_RUNNING_QOUTFIFO; 875 ahd->flags &= ~AHD_RUNNING_QOUTFIFO;
816} 876}
@@ -876,26 +936,6 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
876 ahd_name(ahd), seqintcode); 936 ahd_name(ahd), seqintcode);
877#endif 937#endif
878 switch (seqintcode) { 938 switch (seqintcode) {
879 case BAD_SCB_STATUS:
880 {
881 struct scb *scb;
882 u_int scbid;
883 int cmds_pending;
884
885 scbid = ahd_get_scbptr(ahd);
886 scb = ahd_lookup_scb(ahd, scbid);
887 if (scb != NULL) {
888 ahd_complete_scb(ahd, scb);
889 } else {
890 printf("%s: WARNING no command for scb %d "
891 "(bad status)\n", ahd_name(ahd), scbid);
892 ahd_dump_card_state(ahd);
893 }
894 cmds_pending = ahd_inw(ahd, CMDS_PENDING);
895 if (cmds_pending > 0)
896 ahd_outw(ahd, CMDS_PENDING, cmds_pending - 1);
897 break;
898 }
899 case ENTERING_NONPACK: 939 case ENTERING_NONPACK:
900 { 940 {
901 struct scb *scb; 941 struct scb *scb;
@@ -1060,7 +1100,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
1060 ahd_outb(ahd, SAVED_LUN, 0); 1100 ahd_outb(ahd, SAVED_LUN, 0);
1061 ahd_outb(ahd, SEQ_FLAGS, 0); 1101 ahd_outb(ahd, SEQ_FLAGS, 0);
1062 ahd_assert_atn(ahd); 1102 ahd_assert_atn(ahd);
1063 scb->flags &= ~(SCB_PACKETIZED); 1103 scb->flags &= ~SCB_PACKETIZED;
1064 scb->flags |= SCB_ABORT|SCB_CMDPHASE_ABORT; 1104 scb->flags |= SCB_ABORT|SCB_CMDPHASE_ABORT;
1065 ahd_freeze_devq(ahd, scb); 1105 ahd_freeze_devq(ahd, scb);
1066 ahd_set_transaction_status(scb, CAM_REQUEUE_REQ); 1106 ahd_set_transaction_status(scb, CAM_REQUEUE_REQ);
@@ -1503,9 +1543,6 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
1503 && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) != 0) 1543 && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) != 0)
1504 scb = NULL; 1544 scb = NULL;
1505 1545
1506 /* Make sure the sequencer is in a safe location. */
1507 ahd_clear_critical_section(ahd);
1508
1509 if ((status0 & IOERR) != 0) { 1546 if ((status0 & IOERR) != 0) {
1510 u_int now_lvd; 1547 u_int now_lvd;
1511 1548
@@ -1521,26 +1558,35 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
1521 ahd_setup_iocell_workaround(ahd); 1558 ahd_setup_iocell_workaround(ahd);
1522 ahd_unpause(ahd); 1559 ahd_unpause(ahd);
1523 } else if ((status0 & OVERRUN) != 0) { 1560 } else if ((status0 & OVERRUN) != 0) {
1561
1524 printf("%s: SCSI offset overrun detected. Resetting bus.\n", 1562 printf("%s: SCSI offset overrun detected. Resetting bus.\n",
1525 ahd_name(ahd)); 1563 ahd_name(ahd));
1526 ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE); 1564 ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
1527 } else if ((status & SCSIRSTI) != 0) { 1565 } else if ((status & SCSIRSTI) != 0) {
1566
1528 printf("%s: Someone reset channel A\n", ahd_name(ahd)); 1567 printf("%s: Someone reset channel A\n", ahd_name(ahd));
1529 ahd_reset_channel(ahd, 'A', /*Initiate Reset*/FALSE); 1568 ahd_reset_channel(ahd, 'A', /*Initiate Reset*/FALSE);
1530 } else if ((status & SCSIPERR) != 0) { 1569 } else if ((status & SCSIPERR) != 0) {
1570
1571 /* Make sure the sequencer is in a safe location. */
1572 ahd_clear_critical_section(ahd);
1573
1531 ahd_handle_transmission_error(ahd); 1574 ahd_handle_transmission_error(ahd);
1532 } else if (lqostat0 != 0) { 1575 } else if (lqostat0 != 0) {
1576
1533 printf("%s: lqostat0 == 0x%x!\n", ahd_name(ahd), lqostat0); 1577 printf("%s: lqostat0 == 0x%x!\n", ahd_name(ahd), lqostat0);
1534 ahd_outb(ahd, CLRLQOINT0, lqostat0); 1578 ahd_outb(ahd, CLRLQOINT0, lqostat0);
1535 if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) { 1579 if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0)
1536 ahd_outb(ahd, CLRLQOINT1, 0); 1580 ahd_outb(ahd, CLRLQOINT1, 0);
1537 }
1538 } else if ((status & SELTO) != 0) { 1581 } else if ((status & SELTO) != 0) {
1539 u_int scbid; 1582 u_int scbid;
1540 1583
1541 /* Stop the selection */ 1584 /* Stop the selection */
1542 ahd_outb(ahd, SCSISEQ0, 0); 1585 ahd_outb(ahd, SCSISEQ0, 0);
1543 1586
1587 /* Make sure the sequencer is in a safe location. */
1588 ahd_clear_critical_section(ahd);
1589
1544 /* No more pending messages */ 1590 /* No more pending messages */
1545 ahd_clear_msg_state(ahd); 1591 ahd_clear_msg_state(ahd);
1546 1592
@@ -1573,24 +1619,27 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
1573 scbid); 1619 scbid);
1574 } 1620 }
1575#endif 1621#endif
1576 /*
1577 * Force a renegotiation with this target just in
1578 * case the cable was pulled and will later be
1579 * re-attached. The target may forget its negotiation
1580 * settings with us should it attempt to reselect
1581 * during the interruption. The target will not issue
1582 * a unit attention in this case, so we must always
1583 * renegotiate.
1584 */
1585 ahd_scb_devinfo(ahd, &devinfo, scb); 1622 ahd_scb_devinfo(ahd, &devinfo, scb);
1586 ahd_force_renegotiation(ahd, &devinfo);
1587 ahd_set_transaction_status(scb, CAM_SEL_TIMEOUT); 1623 ahd_set_transaction_status(scb, CAM_SEL_TIMEOUT);
1588 ahd_freeze_devq(ahd, scb); 1624 ahd_freeze_devq(ahd, scb);
1625
1626 /*
1627 * Cancel any pending transactions on the device
1628 * now that it seems to be missing. This will
1629 * also revert us to async/narrow transfers until
1630 * we can renegotiate with the device.
1631 */
1632 ahd_handle_devreset(ahd, &devinfo,
1633 CAM_LUN_WILDCARD,
1634 CAM_SEL_TIMEOUT,
1635 "Selection Timeout",
1636 /*verbose_level*/1);
1589 } 1637 }
1590 ahd_outb(ahd, CLRINT, CLRSCSIINT); 1638 ahd_outb(ahd, CLRINT, CLRSCSIINT);
1591 ahd_iocell_first_selection(ahd); 1639 ahd_iocell_first_selection(ahd);
1592 ahd_unpause(ahd); 1640 ahd_unpause(ahd);
1593 } else if ((status0 & (SELDI|SELDO)) != 0) { 1641 } else if ((status0 & (SELDI|SELDO)) != 0) {
1642
1594 ahd_iocell_first_selection(ahd); 1643 ahd_iocell_first_selection(ahd);
1595 ahd_unpause(ahd); 1644 ahd_unpause(ahd);
1596 } else if (status3 != 0) { 1645 } else if (status3 != 0) {
@@ -1598,6 +1647,10 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
1598 ahd_name(ahd), status3); 1647 ahd_name(ahd), status3);
1599 ahd_outb(ahd, CLRSINT3, status3); 1648 ahd_outb(ahd, CLRSINT3, status3);
1600 } else if ((lqistat1 & (LQIPHASE_LQ|LQIPHASE_NLQ)) != 0) { 1649 } else if ((lqistat1 & (LQIPHASE_LQ|LQIPHASE_NLQ)) != 0) {
1650
1651 /* Make sure the sequencer is in a safe location. */
1652 ahd_clear_critical_section(ahd);
1653
1601 ahd_handle_lqiphase_error(ahd, lqistat1); 1654 ahd_handle_lqiphase_error(ahd, lqistat1);
1602 } else if ((lqistat1 & LQICRCI_NLQ) != 0) { 1655 } else if ((lqistat1 & LQICRCI_NLQ) != 0) {
1603 /* 1656 /*
@@ -1622,6 +1675,9 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
1622 */ 1675 */
1623 ahd_outb(ahd, SCSISEQ0, 0); 1676 ahd_outb(ahd, SCSISEQ0, 0);
1624 1677
1678 /* Make sure the sequencer is in a safe location. */
1679 ahd_clear_critical_section(ahd);
1680
1625 /* 1681 /*
1626 * Determine what we were up to at the time of 1682 * Determine what we were up to at the time of
1627 * the busfree. 1683 * the busfree.
@@ -1659,7 +1715,16 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
1659 clear_fifo = 0; 1715 clear_fifo = 0;
1660 packetized = (lqostat1 & LQOBUSFREE) != 0; 1716 packetized = (lqostat1 & LQOBUSFREE) != 0;
1661 if (!packetized 1717 if (!packetized
1662 && ahd_inb(ahd, LASTPHASE) == P_BUSFREE) 1718 && ahd_inb(ahd, LASTPHASE) == P_BUSFREE
1719 && (ahd_inb(ahd, SSTAT0) & SELDI) == 0
1720 && ((ahd_inb(ahd, SSTAT0) & SELDO) == 0
1721 || (ahd_inb(ahd, SCSISEQ0) & ENSELO) == 0))
1722 /*
1723 * Assume packetized if we are not
1724 * on the bus in a non-packetized
1725 * capacity and any pending selection
1726 * was a packetized selection.
1727 */
1663 packetized = 1; 1728 packetized = 1;
1664 break; 1729 break;
1665 } 1730 }
@@ -2310,8 +2375,7 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd)
2310 "PRGMCNT == 0x%x\n", 2375 "PRGMCNT == 0x%x\n",
2311 ahd_lookup_phase_entry(lastphase)->phasemsg, 2376 ahd_lookup_phase_entry(lastphase)->phasemsg,
2312 aborted, 2377 aborted,
2313 ahd_inb(ahd, PRGMCNT) 2378 ahd_inw(ahd, PRGMCNT));
2314 | (ahd_inb(ahd, PRGMCNT+1) << 8));
2315 ahd_dump_card_state(ahd); 2379 ahd_dump_card_state(ahd);
2316 } 2380 }
2317 /* Always restart the sequencer. */ 2381 /* Always restart the sequencer. */
@@ -2474,8 +2538,7 @@ ahd_clear_critical_section(struct ahd_softc *ahd)
2474 u_int i; 2538 u_int i;
2475 2539
2476 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); 2540 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
2477 seqaddr = ahd_inb(ahd, CURADDR) 2541 seqaddr = ahd_inw(ahd, CURADDR);
2478 | (ahd_inb(ahd, CURADDR+1) << 8);
2479 2542
2480 cs = ahd->critical_sections; 2543 cs = ahd->critical_sections;
2481 for (i = 0; i < ahd->num_critical_sections; i++, cs++) { 2544 for (i = 0; i < ahd->num_critical_sections; i++, cs++) {
@@ -3196,14 +3259,25 @@ ahd_update_neg_table(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
3196 iocell_opts[AHD_PRECOMP_SLEW_INDEX] &= ~AHD_PRECOMP_MASK; 3259 iocell_opts[AHD_PRECOMP_SLEW_INDEX] &= ~AHD_PRECOMP_MASK;
3197 3260
3198 if ((ahd->features & AHD_NEW_IOCELL_OPTS) != 0 3261 if ((ahd->features & AHD_NEW_IOCELL_OPTS) != 0
3199 && (ppr_opts & MSG_EXT_PPR_DT_REQ) != 0) { 3262 && (ppr_opts & MSG_EXT_PPR_DT_REQ) != 0
3263 && (ppr_opts & MSG_EXT_PPR_IU_REQ) == 0) {
3200 /* 3264 /*
3201 * Slow down our CRC interval to be 3265 * Slow down our CRC interval to be
3202 * compatible with devices that can't 3266 * compatible with non-packetized
3203 * handle a CRC at full speed. 3267 * U160 devices that can't handle a
3268 * CRC at full speed.
3204 */ 3269 */
3205 con_opts |= ENSLOWCRC; 3270 con_opts |= ENSLOWCRC;
3206 } 3271 }
3272
3273 if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0) {
3274 /*
3275 * On H2A4, revert to a slower slewrate
3276 * on non-paced transfers.
3277 */
3278 iocell_opts[AHD_PRECOMP_SLEW_INDEX] &=
3279 ~AHD_SLEWRATE_MASK;
3280 }
3207 } 3281 }
3208 3282
3209 ahd_outb(ahd, ANNEXCOL, AHD_ANNEXCOL_PRECOMP_SLEW); 3283 ahd_outb(ahd, ANNEXCOL, AHD_ANNEXCOL_PRECOMP_SLEW);
@@ -3292,11 +3366,15 @@ ahd_update_pending_scbs(struct ahd_softc *ahd)
3292 * Force the sequencer to reinitialize the selection for 3366 * Force the sequencer to reinitialize the selection for
3293 * the command at the head of the execution queue if it 3367 * the command at the head of the execution queue if it
3294 * has already been setup. The negotiation changes may 3368 * has already been setup. The negotiation changes may
3295 * effect whether we select-out with ATN. 3369 * effect whether we select-out with ATN. It is only
3370 * safe to clear ENSELO when the bus is not free and no
3371 * selection is in progres or completed.
3296 */ 3372 */
3297 saved_modes = ahd_save_modes(ahd); 3373 saved_modes = ahd_save_modes(ahd);
3298 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); 3374 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
3299 ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO); 3375 if ((ahd_inb(ahd, SCSISIGI) & BSYI) != 0
3376 && (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) == 0)
3377 ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
3300 saved_scbptr = ahd_get_scbptr(ahd); 3378 saved_scbptr = ahd_get_scbptr(ahd);
3301 /* Ensure that the hscbs down on the card match the new information */ 3379 /* Ensure that the hscbs down on the card match the new information */
3302 for (scb_tag = 0; scb_tag < ahd->scb_data.maxhscbs; scb_tag++) { 3380 for (scb_tag = 0; scb_tag < ahd->scb_data.maxhscbs; scb_tag++) {
@@ -4909,10 +4987,7 @@ ahd_reinitialize_dataptrs(struct ahd_softc *ahd)
4909 * Determine initial values for data_addr and data_cnt 4987 * Determine initial values for data_addr and data_cnt
4910 * for resuming the data phase. 4988 * for resuming the data phase.
4911 */ 4989 */
4912 sgptr = (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 3) << 24) 4990 sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
4913 | (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 2) << 16)
4914 | (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 1) << 8)
4915 | ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR);
4916 sgptr &= SG_PTR_MASK; 4991 sgptr &= SG_PTR_MASK;
4917 4992
4918 resid = (ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT + 2) << 16) 4993 resid = (ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT + 2) << 16)
@@ -4930,10 +5005,7 @@ ahd_reinitialize_dataptrs(struct ahd_softc *ahd)
4930 dataptr = ahd_le64toh(sg->addr) 5005 dataptr = ahd_le64toh(sg->addr)
4931 + (ahd_le32toh(sg->len) & AHD_SG_LEN_MASK) 5006 + (ahd_le32toh(sg->len) & AHD_SG_LEN_MASK)
4932 - resid; 5007 - resid;
4933 ahd_outb(ahd, HADDR + 7, dataptr >> 56); 5008 ahd_outl(ahd, HADDR + 4, dataptr >> 32);
4934 ahd_outb(ahd, HADDR + 6, dataptr >> 48);
4935 ahd_outb(ahd, HADDR + 5, dataptr >> 40);
4936 ahd_outb(ahd, HADDR + 4, dataptr >> 32);
4937 } else { 5009 } else {
4938 struct ahd_dma_seg *sg; 5010 struct ahd_dma_seg *sg;
4939 5011
@@ -4948,10 +5020,7 @@ ahd_reinitialize_dataptrs(struct ahd_softc *ahd)
4948 ahd_outb(ahd, HADDR + 4, 5020 ahd_outb(ahd, HADDR + 4,
4949 (ahd_le32toh(sg->len) & ~AHD_SG_LEN_MASK) >> 24); 5021 (ahd_le32toh(sg->len) & ~AHD_SG_LEN_MASK) >> 24);
4950 } 5022 }
4951 ahd_outb(ahd, HADDR + 3, dataptr >> 24); 5023 ahd_outl(ahd, HADDR, dataptr);
4952 ahd_outb(ahd, HADDR + 2, dataptr >> 16);
4953 ahd_outb(ahd, HADDR + 1, dataptr >> 8);
4954 ahd_outb(ahd, HADDR, dataptr);
4955 ahd_outb(ahd, HCNT + 2, resid >> 16); 5024 ahd_outb(ahd, HCNT + 2, resid >> 16);
4956 ahd_outb(ahd, HCNT + 1, resid >> 8); 5025 ahd_outb(ahd, HCNT + 1, resid >> 8);
4957 ahd_outb(ahd, HCNT, resid); 5026 ahd_outb(ahd, HCNT, resid);
@@ -5011,13 +5080,14 @@ ahd_handle_devreset(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
5011 ahd_set_width(ahd, devinfo, MSG_EXT_WDTR_BUS_8_BIT, 5080 ahd_set_width(ahd, devinfo, MSG_EXT_WDTR_BUS_8_BIT,
5012 AHD_TRANS_CUR, /*paused*/TRUE); 5081 AHD_TRANS_CUR, /*paused*/TRUE);
5013 ahd_set_syncrate(ahd, devinfo, /*period*/0, /*offset*/0, 5082 ahd_set_syncrate(ahd, devinfo, /*period*/0, /*offset*/0,
5014 /*ppr_options*/0, AHD_TRANS_CUR, /*paused*/TRUE); 5083 /*ppr_options*/0, AHD_TRANS_CUR,
5084 /*paused*/TRUE);
5015 5085
5016 ahd_send_async(ahd, devinfo->channel, devinfo->target, 5086 if (status != CAM_SEL_TIMEOUT)
5017 lun, AC_SENT_BDR, NULL); 5087 ahd_send_async(ahd, devinfo->channel, devinfo->target,
5088 CAM_LUN_WILDCARD, AC_SENT_BDR, NULL);
5018 5089
5019 if (message != NULL 5090 if (message != NULL && bootverbose)
5020 && (verbose_level <= bootverbose))
5021 printf("%s: %s on %c:%d. %d SCBs aborted\n", ahd_name(ahd), 5091 printf("%s: %s on %c:%d. %d SCBs aborted\n", ahd_name(ahd),
5022 message, devinfo->channel, devinfo->target, found); 5092 message, devinfo->channel, devinfo->target, found);
5023} 5093}
@@ -5203,13 +5273,13 @@ ahd_free(struct ahd_softc *ahd)
5203 /* FALLTHROUGH */ 5273 /* FALLTHROUGH */
5204 case 4: 5274 case 4:
5205 ahd_dmamap_unload(ahd, ahd->shared_data_dmat, 5275 ahd_dmamap_unload(ahd, ahd->shared_data_dmat,
5206 ahd->shared_data_dmamap); 5276 ahd->shared_data_map.dmamap);
5207 /* FALLTHROUGH */ 5277 /* FALLTHROUGH */
5208 case 3: 5278 case 3:
5209 ahd_dmamem_free(ahd, ahd->shared_data_dmat, ahd->qoutfifo, 5279 ahd_dmamem_free(ahd, ahd->shared_data_dmat, ahd->qoutfifo,
5210 ahd->shared_data_dmamap); 5280 ahd->shared_data_map.dmamap);
5211 ahd_dmamap_destroy(ahd, ahd->shared_data_dmat, 5281 ahd_dmamap_destroy(ahd, ahd->shared_data_dmat,
5212 ahd->shared_data_dmamap); 5282 ahd->shared_data_map.dmamap);
5213 /* FALLTHROUGH */ 5283 /* FALLTHROUGH */
5214 case 2: 5284 case 2:
5215 ahd_dma_tag_destroy(ahd, ahd->shared_data_dmat); 5285 ahd_dma_tag_destroy(ahd, ahd->shared_data_dmat);
@@ -5975,16 +6045,13 @@ ahd_alloc_scbs(struct ahd_softc *ahd)
5975 newcount = MIN(scb_data->sense_left, scb_data->scbs_left); 6045 newcount = MIN(scb_data->sense_left, scb_data->scbs_left);
5976 newcount = MIN(newcount, scb_data->sgs_left); 6046 newcount = MIN(newcount, scb_data->sgs_left);
5977 newcount = MIN(newcount, (AHD_SCB_MAX_ALLOC - scb_data->numscbs)); 6047 newcount = MIN(newcount, (AHD_SCB_MAX_ALLOC - scb_data->numscbs));
5978 scb_data->sense_left -= newcount;
5979 scb_data->scbs_left -= newcount;
5980 scb_data->sgs_left -= newcount;
5981 for (i = 0; i < newcount; i++) { 6048 for (i = 0; i < newcount; i++) {
5982 u_int col_tag;
5983
5984 struct scb_platform_data *pdata; 6049 struct scb_platform_data *pdata;
6050 u_int col_tag;
5985#ifndef __linux__ 6051#ifndef __linux__
5986 int error; 6052 int error;
5987#endif 6053#endif
6054
5988 next_scb = (struct scb *)malloc(sizeof(*next_scb), 6055 next_scb = (struct scb *)malloc(sizeof(*next_scb),
5989 M_DEVBUF, M_NOWAIT); 6056 M_DEVBUF, M_NOWAIT);
5990 if (next_scb == NULL) 6057 if (next_scb == NULL)
@@ -6041,6 +6108,9 @@ ahd_alloc_scbs(struct ahd_softc *ahd)
6041 sense_data += AHD_SENSE_BUFSIZE; 6108 sense_data += AHD_SENSE_BUFSIZE;
6042 sense_busaddr += AHD_SENSE_BUFSIZE; 6109 sense_busaddr += AHD_SENSE_BUFSIZE;
6043 scb_data->numscbs++; 6110 scb_data->numscbs++;
6111 scb_data->sense_left--;
6112 scb_data->scbs_left--;
6113 scb_data->sgs_left--;
6044 } 6114 }
6045} 6115}
6046 6116
@@ -6088,7 +6158,6 @@ static const char *termstat_strings[] = {
6088int 6158int
6089ahd_init(struct ahd_softc *ahd) 6159ahd_init(struct ahd_softc *ahd)
6090{ 6160{
6091 uint8_t *base_vaddr;
6092 uint8_t *next_vaddr; 6161 uint8_t *next_vaddr;
6093 dma_addr_t next_baddr; 6162 dma_addr_t next_baddr;
6094 size_t driver_data_size; 6163 size_t driver_data_size;
@@ -6156,7 +6225,7 @@ ahd_init(struct ahd_softc *ahd)
6156 * for the target mode role, we must additionally provide space for 6225 * for the target mode role, we must additionally provide space for
6157 * the incoming target command fifo. 6226 * the incoming target command fifo.
6158 */ 6227 */
6159 driver_data_size = AHD_SCB_MAX * sizeof(uint16_t) 6228 driver_data_size = AHD_SCB_MAX * sizeof(*ahd->qoutfifo)
6160 + sizeof(struct hardware_scb); 6229 + sizeof(struct hardware_scb);
6161 if ((ahd->features & AHD_TARGETMODE) != 0) 6230 if ((ahd->features & AHD_TARGETMODE) != 0)
6162 driver_data_size += AHD_TMODE_CMDS * sizeof(struct target_cmd); 6231 driver_data_size += AHD_TMODE_CMDS * sizeof(struct target_cmd);
@@ -6178,20 +6247,23 @@ ahd_init(struct ahd_softc *ahd)
6178 6247
6179 /* Allocation of driver data */ 6248 /* Allocation of driver data */
6180 if (ahd_dmamem_alloc(ahd, ahd->shared_data_dmat, 6249 if (ahd_dmamem_alloc(ahd, ahd->shared_data_dmat,
6181 (void **)&base_vaddr, 6250 (void **)&ahd->shared_data_map.vaddr,
6182 BUS_DMA_NOWAIT, &ahd->shared_data_dmamap) != 0) { 6251 BUS_DMA_NOWAIT,
6252 &ahd->shared_data_map.dmamap) != 0) {
6183 return (ENOMEM); 6253 return (ENOMEM);
6184 } 6254 }
6185 6255
6186 ahd->init_level++; 6256 ahd->init_level++;
6187 6257
6188 /* And permanently map it in */ 6258 /* And permanently map it in */
6189 ahd_dmamap_load(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap, 6259 ahd_dmamap_load(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
6190 base_vaddr, driver_data_size, ahd_dmamap_cb, 6260 ahd->shared_data_map.vaddr, driver_data_size,
6191 &ahd->shared_data_busaddr, /*flags*/0); 6261 ahd_dmamap_cb, &ahd->shared_data_map.physaddr,
6192 ahd->qoutfifo = (uint16_t *)base_vaddr; 6262 /*flags*/0);
6263 ahd->qoutfifo = (struct ahd_completion *)ahd->shared_data_map.vaddr;
6193 next_vaddr = (uint8_t *)&ahd->qoutfifo[AHD_QOUT_SIZE]; 6264 next_vaddr = (uint8_t *)&ahd->qoutfifo[AHD_QOUT_SIZE];
6194 next_baddr = ahd->shared_data_busaddr + AHD_QOUT_SIZE*sizeof(uint16_t); 6265 next_baddr = ahd->shared_data_map.physaddr
6266 + AHD_QOUT_SIZE*sizeof(struct ahd_completion);
6195 if ((ahd->features & AHD_TARGETMODE) != 0) { 6267 if ((ahd->features & AHD_TARGETMODE) != 0) {
6196 ahd->targetcmds = (struct target_cmd *)next_vaddr; 6268 ahd->targetcmds = (struct target_cmd *)next_vaddr;
6197 next_vaddr += AHD_TMODE_CMDS * sizeof(struct target_cmd); 6269 next_vaddr += AHD_TMODE_CMDS * sizeof(struct target_cmd);
@@ -6212,6 +6284,7 @@ ahd_init(struct ahd_softc *ahd)
6212 * specially from the DMA safe memory chunk used for the QOUTFIFO. 6284 * specially from the DMA safe memory chunk used for the QOUTFIFO.
6213 */ 6285 */
6214 ahd->next_queued_hscb = (struct hardware_scb *)next_vaddr; 6286 ahd->next_queued_hscb = (struct hardware_scb *)next_vaddr;
6287 ahd->next_queued_hscb_map = &ahd->shared_data_map;
6215 ahd->next_queued_hscb->hscb_busaddr = ahd_htole32(next_baddr); 6288 ahd->next_queued_hscb->hscb_busaddr = ahd_htole32(next_baddr);
6216 6289
6217 ahd->init_level++; 6290 ahd->init_level++;
@@ -6517,10 +6590,10 @@ ahd_chip_init(struct ahd_softc *ahd)
6517 6590
6518 /* All of our queues are empty */ 6591 /* All of our queues are empty */
6519 ahd->qoutfifonext = 0; 6592 ahd->qoutfifonext = 0;
6520 ahd->qoutfifonext_valid_tag = QOUTFIFO_ENTRY_VALID_LE; 6593 ahd->qoutfifonext_valid_tag = QOUTFIFO_ENTRY_VALID;
6521 ahd_outb(ahd, QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID >> 8); 6594 ahd_outb(ahd, QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID);
6522 for (i = 0; i < AHD_QOUT_SIZE; i++) 6595 for (i = 0; i < AHD_QOUT_SIZE; i++)
6523 ahd->qoutfifo[i] = 0; 6596 ahd->qoutfifo[i].valid_tag = 0;
6524 ahd_sync_qoutfifo(ahd, BUS_DMASYNC_PREREAD); 6597 ahd_sync_qoutfifo(ahd, BUS_DMASYNC_PREREAD);
6525 6598
6526 ahd->qinfifonext = 0; 6599 ahd->qinfifonext = 0;
@@ -6553,24 +6626,22 @@ ahd_chip_init(struct ahd_softc *ahd)
6553 ahd_outw(ahd, COMPLETE_SCB_HEAD, SCB_LIST_NULL); 6626 ahd_outw(ahd, COMPLETE_SCB_HEAD, SCB_LIST_NULL);
6554 ahd_outw(ahd, COMPLETE_SCB_DMAINPROG_HEAD, SCB_LIST_NULL); 6627 ahd_outw(ahd, COMPLETE_SCB_DMAINPROG_HEAD, SCB_LIST_NULL);
6555 ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL); 6628 ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL);
6629 ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, SCB_LIST_NULL);
6630 ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD, SCB_LIST_NULL);
6556 6631
6557 /* 6632 /*
6558 * The Freeze Count is 0. 6633 * The Freeze Count is 0.
6559 */ 6634 */
6635 ahd->qfreeze_cnt = 0;
6560 ahd_outw(ahd, QFREEZE_COUNT, 0); 6636 ahd_outw(ahd, QFREEZE_COUNT, 0);
6637 ahd_outw(ahd, KERNEL_QFREEZE_COUNT, 0);
6561 6638
6562 /* 6639 /*
6563 * Tell the sequencer where it can find our arrays in memory. 6640 * Tell the sequencer where it can find our arrays in memory.
6564 */ 6641 */
6565 busaddr = ahd->shared_data_busaddr; 6642 busaddr = ahd->shared_data_map.physaddr;
6566 ahd_outb(ahd, SHARED_DATA_ADDR, busaddr & 0xFF); 6643 ahd_outl(ahd, SHARED_DATA_ADDR, busaddr);
6567 ahd_outb(ahd, SHARED_DATA_ADDR + 1, (busaddr >> 8) & 0xFF); 6644 ahd_outl(ahd, QOUTFIFO_NEXT_ADDR, busaddr);
6568 ahd_outb(ahd, SHARED_DATA_ADDR + 2, (busaddr >> 16) & 0xFF);
6569 ahd_outb(ahd, SHARED_DATA_ADDR + 3, (busaddr >> 24) & 0xFF);
6570 ahd_outb(ahd, QOUTFIFO_NEXT_ADDR, busaddr & 0xFF);
6571 ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 1, (busaddr >> 8) & 0xFF);
6572 ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 2, (busaddr >> 16) & 0xFF);
6573 ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 3, (busaddr >> 24) & 0xFF);
6574 6645
6575 /* 6646 /*
6576 * Setup the allowed SCSI Sequences based on operational mode. 6647 * Setup the allowed SCSI Sequences based on operational mode.
@@ -6619,10 +6690,7 @@ ahd_chip_init(struct ahd_softc *ahd)
6619 * Tell the sequencer which SCB will be the next one it receives. 6690 * Tell the sequencer which SCB will be the next one it receives.
6620 */ 6691 */
6621 busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr); 6692 busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr);
6622 ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF); 6693 ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr);
6623 ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF);
6624 ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF);
6625 ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF);
6626 6694
6627 /* 6695 /*
6628 * Default to coalescing disabled. 6696 * Default to coalescing disabled.
@@ -6926,43 +6994,34 @@ ahd_pause_and_flushwork(struct ahd_softc *ahd)
6926{ 6994{
6927 u_int intstat; 6995 u_int intstat;
6928 u_int maxloops; 6996 u_int maxloops;
6929 u_int qfreeze_cnt;
6930 6997
6931 maxloops = 1000; 6998 maxloops = 1000;
6932 ahd->flags |= AHD_ALL_INTERRUPTS; 6999 ahd->flags |= AHD_ALL_INTERRUPTS;
6933 ahd_pause(ahd); 7000 ahd_pause(ahd);
6934 /* 7001 /*
6935 * Increment the QFreeze Count so that the sequencer 7002 * Freeze the outgoing selections. We do this only
6936 * will not start new selections. We do this only
6937 * until we are safely paused without further selections 7003 * until we are safely paused without further selections
6938 * pending. 7004 * pending.
6939 */ 7005 */
6940 ahd_outw(ahd, QFREEZE_COUNT, ahd_inw(ahd, QFREEZE_COUNT) + 1); 7006 ahd->qfreeze_cnt--;
7007 ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt);
6941 ahd_outb(ahd, SEQ_FLAGS2, ahd_inb(ahd, SEQ_FLAGS2) | SELECTOUT_QFROZEN); 7008 ahd_outb(ahd, SEQ_FLAGS2, ahd_inb(ahd, SEQ_FLAGS2) | SELECTOUT_QFROZEN);
6942 do { 7009 do {
6943 struct scb *waiting_scb;
6944 7010
6945 ahd_unpause(ahd); 7011 ahd_unpause(ahd);
7012 /*
7013 * Give the sequencer some time to service
7014 * any active selections.
7015 */
7016 ahd_delay(500);
7017
6946 ahd_intr(ahd); 7018 ahd_intr(ahd);
6947 ahd_pause(ahd); 7019 ahd_pause(ahd);
6948 ahd_clear_critical_section(ahd);
6949 intstat = ahd_inb(ahd, INTSTAT); 7020 intstat = ahd_inb(ahd, INTSTAT);
6950 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); 7021 if ((intstat & INT_PEND) == 0) {
6951 if ((ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) == 0) 7022 ahd_clear_critical_section(ahd);
6952 ahd_outb(ahd, SCSISEQ0, 7023 intstat = ahd_inb(ahd, INTSTAT);
6953 ahd_inb(ahd, SCSISEQ0) & ~ENSELO); 7024 }
6954 /*
6955 * In the non-packetized case, the sequencer (for Rev A),
6956 * relies on ENSELO remaining set after SELDO. The hardware
6957 * auto-clears ENSELO in the packetized case.
6958 */
6959 waiting_scb = ahd_lookup_scb(ahd,
6960 ahd_inw(ahd, WAITING_TID_HEAD));
6961 if (waiting_scb != NULL
6962 && (waiting_scb->flags & SCB_PACKETIZED) == 0
6963 && (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) != 0)
6964 ahd_outb(ahd, SCSISEQ0,
6965 ahd_inb(ahd, SCSISEQ0) | ENSELO);
6966 } while (--maxloops 7025 } while (--maxloops
6967 && (intstat != 0xFF || (ahd->features & AHD_REMOVABLE) == 0) 7026 && (intstat != 0xFF || (ahd->features & AHD_REMOVABLE) == 0)
6968 && ((intstat & INT_PEND) != 0 7027 && ((intstat & INT_PEND) != 0
@@ -6973,17 +7032,8 @@ ahd_pause_and_flushwork(struct ahd_softc *ahd)
6973 printf("Infinite interrupt loop, INTSTAT = %x", 7032 printf("Infinite interrupt loop, INTSTAT = %x",
6974 ahd_inb(ahd, INTSTAT)); 7033 ahd_inb(ahd, INTSTAT));
6975 } 7034 }
6976 qfreeze_cnt = ahd_inw(ahd, QFREEZE_COUNT); 7035 ahd->qfreeze_cnt++;
6977 if (qfreeze_cnt == 0) { 7036 ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt);
6978 printf("%s: ahd_pause_and_flushwork with 0 qfreeze count!\n",
6979 ahd_name(ahd));
6980 } else {
6981 qfreeze_cnt--;
6982 }
6983 ahd_outw(ahd, QFREEZE_COUNT, qfreeze_cnt);
6984 if (qfreeze_cnt == 0)
6985 ahd_outb(ahd, SEQ_FLAGS2,
6986 ahd_inb(ahd, SEQ_FLAGS2) & ~SELECTOUT_QFROZEN);
6987 7037
6988 ahd_flush_qoutfifo(ahd); 7038 ahd_flush_qoutfifo(ahd);
6989 7039
@@ -7155,10 +7205,7 @@ ahd_qinfifo_requeue(struct ahd_softc *ahd, struct scb *prev_scb,
7155 uint32_t busaddr; 7205 uint32_t busaddr;
7156 7206
7157 busaddr = ahd_le32toh(scb->hscb->hscb_busaddr); 7207 busaddr = ahd_le32toh(scb->hscb->hscb_busaddr);
7158 ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF); 7208 ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr);
7159 ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF);
7160 ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF);
7161 ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF);
7162 } else { 7209 } else {
7163 prev_scb->hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr; 7210 prev_scb->hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr;
7164 ahd_sync_scb(ahd, prev_scb, 7211 ahd_sync_scb(ahd, prev_scb,
@@ -7265,10 +7312,7 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel,
7265 */ 7312 */
7266 ahd->qinfifonext = qinstart; 7313 ahd->qinfifonext = qinstart;
7267 busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr); 7314 busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr);
7268 ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF); 7315 ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr);
7269 ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF);
7270 ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF);
7271 ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF);
7272 7316
7273 while (qinpos != qintail) { 7317 while (qinpos != qintail) {
7274 scb = ahd_lookup_scb(ahd, ahd->qinfifo[qinpos]); 7318 scb = ahd_lookup_scb(ahd, ahd->qinfifo[qinpos]);
@@ -7330,6 +7374,7 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel,
7330 * appropriate, traverse the SCBs of each "their id" 7374 * appropriate, traverse the SCBs of each "their id"
7331 * looking for matches. 7375 * looking for matches.
7332 */ 7376 */
7377 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
7333 savedscbptr = ahd_get_scbptr(ahd); 7378 savedscbptr = ahd_get_scbptr(ahd);
7334 tid_next = ahd_inw(ahd, WAITING_TID_HEAD); 7379 tid_next = ahd_inw(ahd, WAITING_TID_HEAD);
7335 tid_prev = SCB_LIST_NULL; 7380 tid_prev = SCB_LIST_NULL;
@@ -7399,7 +7444,7 @@ ahd_search_scb_list(struct ahd_softc *ahd, int target, char channel,
7399 u_int prev; 7444 u_int prev;
7400 int found; 7445 int found;
7401 7446
7402 AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); 7447 AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
7403 found = 0; 7448 found = 0;
7404 prev = SCB_LIST_NULL; 7449 prev = SCB_LIST_NULL;
7405 next = *list_head; 7450 next = *list_head;
@@ -7466,7 +7511,7 @@ static void
7466ahd_stitch_tid_list(struct ahd_softc *ahd, u_int tid_prev, 7511ahd_stitch_tid_list(struct ahd_softc *ahd, u_int tid_prev,
7467 u_int tid_cur, u_int tid_next) 7512 u_int tid_cur, u_int tid_next)
7468{ 7513{
7469 AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); 7514 AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
7470 7515
7471 if (SCBID_IS_NULL(tid_cur)) { 7516 if (SCBID_IS_NULL(tid_cur)) {
7472 7517
@@ -7506,7 +7551,7 @@ ahd_rem_wscb(struct ahd_softc *ahd, u_int scbid,
7506{ 7551{
7507 u_int tail_offset; 7552 u_int tail_offset;
7508 7553
7509 AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); 7554 AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
7510 if (!SCBID_IS_NULL(prev)) { 7555 if (!SCBID_IS_NULL(prev)) {
7511 ahd_set_scbptr(ahd, prev); 7556 ahd_set_scbptr(ahd, prev);
7512 ahd_outw(ahd, SCB_NEXT, next); 7557 ahd_outw(ahd, SCB_NEXT, next);
@@ -7739,7 +7784,7 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
7739 */ 7784 */
7740 ahd_clear_msg_state(ahd); 7785 ahd_clear_msg_state(ahd);
7741 ahd_outb(ahd, SIMODE1, 7786 ahd_outb(ahd, SIMODE1,
7742 ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST|ENBUSFREE)); 7787 ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST));
7743 7788
7744 if (initiate_reset) 7789 if (initiate_reset)
7745 ahd_reset_current_bus(ahd); 7790 ahd_reset_current_bus(ahd);
@@ -7910,30 +7955,35 @@ ahd_handle_scb_status(struct ahd_softc *ahd, struct scb *scb)
7910void 7955void
7911ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) 7956ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb)
7912{ 7957{
7913 struct hardware_scb *hscb; 7958 struct hardware_scb *hscb;
7914 u_int qfreeze_cnt; 7959 int paused;
7915 7960
7916 /* 7961 /*
7917 * The sequencer freezes its select-out queue 7962 * The sequencer freezes its select-out queue
7918 * anytime a SCSI status error occurs. We must 7963 * anytime a SCSI status error occurs. We must
7919 * handle the error and decrement the QFREEZE count 7964 * handle the error and increment our qfreeze count
7920 * to allow the sequencer to continue. 7965 * to allow the sequencer to continue. We don't
7966 * bother clearing critical sections here since all
7967 * operations are on data structures that the sequencer
7968 * is not touching once the queue is frozen.
7921 */ 7969 */
7922 hscb = scb->hscb; 7970 hscb = scb->hscb;
7923 7971
7972 if (ahd_is_paused(ahd)) {
7973 paused = 1;
7974 } else {
7975 paused = 0;
7976 ahd_pause(ahd);
7977 }
7978
7924 /* Freeze the queue until the client sees the error. */ 7979 /* Freeze the queue until the client sees the error. */
7925 ahd_freeze_devq(ahd, scb); 7980 ahd_freeze_devq(ahd, scb);
7926 ahd_freeze_scb(scb); 7981 ahd_freeze_scb(scb);
7927 qfreeze_cnt = ahd_inw(ahd, QFREEZE_COUNT); 7982 ahd->qfreeze_cnt++;
7928 if (qfreeze_cnt == 0) { 7983 ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt);
7929 printf("%s: Bad status with 0 qfreeze count!\n", ahd_name(ahd)); 7984
7930 } else { 7985 if (paused == 0)
7931 qfreeze_cnt--; 7986 ahd_unpause(ahd);
7932 ahd_outw(ahd, QFREEZE_COUNT, qfreeze_cnt);
7933 }
7934 if (qfreeze_cnt == 0)
7935 ahd_outb(ahd, SEQ_FLAGS2,
7936 ahd_inb(ahd, SEQ_FLAGS2) & ~SELECTOUT_QFROZEN);
7937 7987
7938 /* Don't want to clobber the original sense code */ 7988 /* Don't want to clobber the original sense code */
7939 if ((scb->flags & SCB_SENSE) != 0) { 7989 if ((scb->flags & SCB_SENSE) != 0) {
@@ -8317,8 +8367,7 @@ ahd_dumpseq(struct ahd_softc* ahd)
8317 max_prog = 2048; 8367 max_prog = 2048;
8318 8368
8319 ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM); 8369 ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM);
8320 ahd_outb(ahd, PRGMCNT, 0); 8370 ahd_outw(ahd, PRGMCNT, 0);
8321 ahd_outb(ahd, PRGMCNT+1, 0);
8322 for (i = 0; i < max_prog; i++) { 8371 for (i = 0; i < max_prog; i++) {
8323 uint8_t ins_bytes[4]; 8372 uint8_t ins_bytes[4];
8324 8373
@@ -8347,13 +8396,14 @@ ahd_loadseq(struct ahd_softc *ahd)
8347 u_int sg_prefetch_cnt_limit; 8396 u_int sg_prefetch_cnt_limit;
8348 u_int sg_prefetch_align; 8397 u_int sg_prefetch_align;
8349 u_int sg_size; 8398 u_int sg_size;
8399 u_int cacheline_mask;
8350 uint8_t download_consts[DOWNLOAD_CONST_COUNT]; 8400 uint8_t download_consts[DOWNLOAD_CONST_COUNT];
8351 8401
8352 if (bootverbose) 8402 if (bootverbose)
8353 printf("%s: Downloading Sequencer Program...", 8403 printf("%s: Downloading Sequencer Program...",
8354 ahd_name(ahd)); 8404 ahd_name(ahd));
8355 8405
8356#if DOWNLOAD_CONST_COUNT != 7 8406#if DOWNLOAD_CONST_COUNT != 8
8357#error "Download Const Mismatch" 8407#error "Download Const Mismatch"
8358#endif 8408#endif
8359 /* 8409 /*
@@ -8389,6 +8439,9 @@ ahd_loadseq(struct ahd_softc *ahd)
8389 /* Round down to the nearest power of 2. */ 8439 /* Round down to the nearest power of 2. */
8390 while (powerof2(sg_prefetch_align) == 0) 8440 while (powerof2(sg_prefetch_align) == 0)
8391 sg_prefetch_align--; 8441 sg_prefetch_align--;
8442
8443 cacheline_mask = sg_prefetch_align - 1;
8444
8392 /* 8445 /*
8393 * If the cacheline boundary is greater than half our prefetch RAM 8446 * If the cacheline boundary is greater than half our prefetch RAM
8394 * we risk not being able to fetch even a single complete S/G 8447 * we risk not being able to fetch even a single complete S/G
@@ -8429,12 +8482,12 @@ ahd_loadseq(struct ahd_softc *ahd)
8429 download_consts[PKT_OVERRUN_BUFOFFSET] = 8482 download_consts[PKT_OVERRUN_BUFOFFSET] =
8430 (ahd->overrun_buf - (uint8_t *)ahd->qoutfifo) / 256; 8483 (ahd->overrun_buf - (uint8_t *)ahd->qoutfifo) / 256;
8431 download_consts[SCB_TRANSFER_SIZE] = SCB_TRANSFER_SIZE_1BYTE_LUN; 8484 download_consts[SCB_TRANSFER_SIZE] = SCB_TRANSFER_SIZE_1BYTE_LUN;
8485 download_consts[CACHELINE_MASK] = cacheline_mask;
8432 cur_patch = patches; 8486 cur_patch = patches;
8433 downloaded = 0; 8487 downloaded = 0;
8434 skip_addr = 0; 8488 skip_addr = 0;
8435 ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM); 8489 ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM);
8436 ahd_outb(ahd, PRGMCNT, 0); 8490 ahd_outw(ahd, PRGMCNT, 0);
8437 ahd_outb(ahd, PRGMCNT+1, 0);
8438 8491
8439 for (i = 0; i < sizeof(seqprog)/4; i++) { 8492 for (i = 0; i < sizeof(seqprog)/4; i++) {
8440 if (ahd_check_patch(ahd, &cur_patch, i, &skip_addr) == 0) { 8493 if (ahd_check_patch(ahd, &cur_patch, i, &skip_addr) == 0) {
@@ -8727,7 +8780,7 @@ ahd_dump_card_state(struct ahd_softc *ahd)
8727 printf(">>>>>>>>>>>>>>>>>> Dump Card State Begins <<<<<<<<<<<<<<<<<\n" 8780 printf(">>>>>>>>>>>>>>>>>> Dump Card State Begins <<<<<<<<<<<<<<<<<\n"
8728 "%s: Dumping Card State at program address 0x%x Mode 0x%x\n", 8781 "%s: Dumping Card State at program address 0x%x Mode 0x%x\n",
8729 ahd_name(ahd), 8782 ahd_name(ahd),
8730 ahd_inb(ahd, CURADDR) | (ahd_inb(ahd, CURADDR+1) << 8), 8783 ahd_inw(ahd, CURADDR),
8731 ahd_build_mode_state(ahd, ahd->saved_src_mode, 8784 ahd_build_mode_state(ahd, ahd->saved_src_mode,
8732 ahd->saved_dst_mode)); 8785 ahd->saved_dst_mode));
8733 if (paused) 8786 if (paused)
@@ -8843,6 +8896,15 @@ ahd_dump_card_state(struct ahd_softc *ahd)
8843 scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE); 8896 scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
8844 } 8897 }
8845 printf("\n"); 8898 printf("\n");
8899 printf("Sequencer On QFreeze and Complete list: ");
8900 scb_index = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD);
8901 i = 0;
8902 while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {
8903 ahd_set_scbptr(ahd, scb_index);
8904 printf("%d ", scb_index);
8905 scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
8906 }
8907 printf("\n");
8846 ahd_set_scbptr(ahd, saved_scb_index); 8908 ahd_set_scbptr(ahd, saved_scb_index);
8847 dffstat = ahd_inb(ahd, DFFSTAT); 8909 dffstat = ahd_inb(ahd, DFFSTAT);
8848 for (i = 0; i < 2; i++) { 8910 for (i = 0; i < 2; i++) {
@@ -9077,7 +9139,7 @@ ahd_wait_seeprom(struct ahd_softc *ahd)
9077{ 9139{
9078 int cnt; 9140 int cnt;
9079 9141
9080 cnt = 20; 9142 cnt = 5000;
9081 while ((ahd_inb(ahd, SEESTAT) & (SEEARBACK|SEEBUSY)) != 0 && --cnt) 9143 while ((ahd_inb(ahd, SEESTAT) & (SEEARBACK|SEEBUSY)) != 0 && --cnt)
9082 ahd_delay(5); 9144 ahd_delay(5);
9083 9145
@@ -9423,13 +9485,9 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
9423 if ((ahd->features & AHD_MULTI_TID) != 0) { 9485 if ((ahd->features & AHD_MULTI_TID) != 0) {
9424 u_int targid_mask; 9486 u_int targid_mask;
9425 9487
9426 targid_mask = ahd_inb(ahd, TARGID) 9488 targid_mask = ahd_inw(ahd, TARGID);
9427 | (ahd_inb(ahd, TARGID + 1) << 8);
9428
9429 targid_mask |= target_mask; 9489 targid_mask |= target_mask;
9430 ahd_outb(ahd, TARGID, targid_mask); 9490 ahd_outw(ahd, TARGID, targid_mask);
9431 ahd_outb(ahd, TARGID+1, (targid_mask >> 8));
9432
9433 ahd_update_scsiid(ahd, targid_mask); 9491 ahd_update_scsiid(ahd, targid_mask);
9434 } else { 9492 } else {
9435 u_int our_id; 9493 u_int our_id;
@@ -9543,14 +9601,9 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
9543 if (ahd->features & AHD_MULTI_TID) { 9601 if (ahd->features & AHD_MULTI_TID) {
9544 u_int targid_mask; 9602 u_int targid_mask;
9545 9603
9546 targid_mask = ahd_inb(ahd, TARGID) 9604 targid_mask = ahd_inw(ahd, TARGID);
9547 | (ahd_inb(ahd, TARGID + 1)
9548 << 8);
9549
9550 targid_mask &= ~target_mask; 9605 targid_mask &= ~target_mask;
9551 ahd_outb(ahd, TARGID, targid_mask); 9606 ahd_outw(ahd, TARGID, targid_mask);
9552 ahd_outb(ahd, TARGID+1,
9553 (targid_mask >> 8));
9554 ahd_update_scsiid(ahd, targid_mask); 9607 ahd_update_scsiid(ahd, targid_mask);
9555 } 9608 }
9556 } 9609 }
@@ -9651,7 +9704,7 @@ ahd_run_tqinfifo(struct ahd_softc *ahd, int paused)
9651 9704
9652 cmd->cmd_valid = 0; 9705 cmd->cmd_valid = 0;
9653 ahd_dmamap_sync(ahd, ahd->shared_data_dmat, 9706 ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
9654 ahd->shared_data_dmamap, 9707 ahd->shared_data_map.dmamap,
9655 ahd_targetcmd_offset(ahd, ahd->tqinfifonext), 9708 ahd_targetcmd_offset(ahd, ahd->tqinfifonext),
9656 sizeof(struct target_cmd), 9709 sizeof(struct target_cmd),
9657 BUS_DMASYNC_PREREAD); 9710 BUS_DMASYNC_PREREAD);
diff --git a/drivers/scsi/aic7xxx/aic79xx_inline.h b/drivers/scsi/aic7xxx/aic79xx_inline.h
index d80bc5161fb1..91c4f7f484b1 100644
--- a/drivers/scsi/aic7xxx/aic79xx_inline.h
+++ b/drivers/scsi/aic7xxx/aic79xx_inline.h
@@ -37,7 +37,7 @@
37 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGES. 38 * POSSIBILITY OF SUCH DAMAGES.
39 * 39 *
40 * $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#51 $ 40 * $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#58 $
41 * 41 *
42 * $FreeBSD$ 42 * $FreeBSD$
43 */ 43 */
@@ -522,12 +522,21 @@ do { \
522static __inline uint16_t 522static __inline uint16_t
523ahd_inw(struct ahd_softc *ahd, u_int port) 523ahd_inw(struct ahd_softc *ahd, u_int port)
524{ 524{
525 /*
526 * Read high byte first as some registers increment
527 * or have other side effects when the low byte is
528 * read.
529 */
525 return ((ahd_inb(ahd, port+1) << 8) | ahd_inb(ahd, port)); 530 return ((ahd_inb(ahd, port+1) << 8) | ahd_inb(ahd, port));
526} 531}
527 532
528static __inline void 533static __inline void
529ahd_outw(struct ahd_softc *ahd, u_int port, u_int value) 534ahd_outw(struct ahd_softc *ahd, u_int port, u_int value)
530{ 535{
536 /*
537 * Write low byte first to accomodate registers
538 * such as PRGMCNT where the order maters.
539 */
531 ahd_outb(ahd, port, value & 0xFF); 540 ahd_outb(ahd, port, value & 0xFF);
532 ahd_outb(ahd, port+1, (value >> 8) & 0xFF); 541 ahd_outb(ahd, port+1, (value >> 8) & 0xFF);
533} 542}
@@ -684,7 +693,7 @@ ahd_inb_scbram(struct ahd_softc *ahd, u_int offset)
684 * Razor #528 693 * Razor #528
685 */ 694 */
686 value = ahd_inb(ahd, offset); 695 value = ahd_inb(ahd, offset);
687 if ((ahd->flags & AHD_PCIX_SCBRAM_RD_BUG) != 0) 696 if ((ahd->bugs & AHD_PCIX_SCBRAM_RD_BUG) != 0)
688 ahd_inb(ahd, MODE_PTR); 697 ahd_inb(ahd, MODE_PTR);
689 return (value); 698 return (value);
690} 699}
@@ -727,7 +736,8 @@ ahd_lookup_scb(struct ahd_softc *ahd, u_int tag)
727static __inline void 736static __inline void
728ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb) 737ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb)
729{ 738{
730 struct hardware_scb *q_hscb; 739 struct hardware_scb *q_hscb;
740 struct map_node *q_hscb_map;
731 uint32_t saved_hscb_busaddr; 741 uint32_t saved_hscb_busaddr;
732 742
733 /* 743 /*
@@ -743,6 +753,7 @@ ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb)
743 * locate the correct SCB by SCB_TAG. 753 * locate the correct SCB by SCB_TAG.
744 */ 754 */
745 q_hscb = ahd->next_queued_hscb; 755 q_hscb = ahd->next_queued_hscb;
756 q_hscb_map = ahd->next_queued_hscb_map;
746 saved_hscb_busaddr = q_hscb->hscb_busaddr; 757 saved_hscb_busaddr = q_hscb->hscb_busaddr;
747 memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb)); 758 memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb));
748 q_hscb->hscb_busaddr = saved_hscb_busaddr; 759 q_hscb->hscb_busaddr = saved_hscb_busaddr;
@@ -750,7 +761,9 @@ ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb)
750 761
751 /* Now swap HSCB pointers. */ 762 /* Now swap HSCB pointers. */
752 ahd->next_queued_hscb = scb->hscb; 763 ahd->next_queued_hscb = scb->hscb;
764 ahd->next_queued_hscb_map = scb->hscb_map;
753 scb->hscb = q_hscb; 765 scb->hscb = q_hscb;
766 scb->hscb_map = q_hscb_map;
754 767
755 /* Now define the mapping from tag to SCB in the scbindex */ 768 /* Now define the mapping from tag to SCB in the scbindex */
756 ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb; 769 ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb;
@@ -824,8 +837,9 @@ static __inline int ahd_intr(struct ahd_softc *ahd);
824static __inline void 837static __inline void
825ahd_sync_qoutfifo(struct ahd_softc *ahd, int op) 838ahd_sync_qoutfifo(struct ahd_softc *ahd, int op)
826{ 839{
827 ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap, 840 ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
828 /*offset*/0, /*len*/AHC_SCB_MAX * sizeof(uint16_t), op); 841 /*offset*/0,
842 /*len*/AHD_SCB_MAX * sizeof(struct ahd_completion), op);
829} 843}
830 844
831static __inline void 845static __inline void
@@ -834,7 +848,7 @@ ahd_sync_tqinfifo(struct ahd_softc *ahd, int op)
834#ifdef AHD_TARGET_MODE 848#ifdef AHD_TARGET_MODE
835 if ((ahd->flags & AHD_TARGETROLE) != 0) { 849 if ((ahd->flags & AHD_TARGETROLE) != 0) {
836 ahd_dmamap_sync(ahd, ahd->shared_data_dmat, 850 ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
837 ahd->shared_data_dmamap, 851 ahd->shared_data_map.dmamap,
838 ahd_targetcmd_offset(ahd, 0), 852 ahd_targetcmd_offset(ahd, 0),
839 sizeof(struct target_cmd) * AHD_TMODE_CMDS, 853 sizeof(struct target_cmd) * AHD_TMODE_CMDS,
840 op); 854 op);
@@ -854,17 +868,17 @@ ahd_check_cmdcmpltqueues(struct ahd_softc *ahd)
854 u_int retval; 868 u_int retval;
855 869
856 retval = 0; 870 retval = 0;
857 ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap, 871 ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
858 /*offset*/ahd->qoutfifonext, /*len*/2, 872 /*offset*/ahd->qoutfifonext * sizeof(*ahd->qoutfifo),
859 BUS_DMASYNC_POSTREAD); 873 /*len*/sizeof(*ahd->qoutfifo), BUS_DMASYNC_POSTREAD);
860 if ((ahd->qoutfifo[ahd->qoutfifonext] 874 if (ahd->qoutfifo[ahd->qoutfifonext].valid_tag
861 & QOUTFIFO_ENTRY_VALID_LE) == ahd->qoutfifonext_valid_tag) 875 == ahd->qoutfifonext_valid_tag)
862 retval |= AHD_RUN_QOUTFIFO; 876 retval |= AHD_RUN_QOUTFIFO;
863#ifdef AHD_TARGET_MODE 877#ifdef AHD_TARGET_MODE
864 if ((ahd->flags & AHD_TARGETROLE) != 0 878 if ((ahd->flags & AHD_TARGETROLE) != 0
865 && (ahd->flags & AHD_TQINFIFO_BLOCKED) == 0) { 879 && (ahd->flags & AHD_TQINFIFO_BLOCKED) == 0) {
866 ahd_dmamap_sync(ahd, ahd->shared_data_dmat, 880 ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
867 ahd->shared_data_dmamap, 881 ahd->shared_data_map.dmamap,
868 ahd_targetcmd_offset(ahd, ahd->tqinfifofnext), 882 ahd_targetcmd_offset(ahd, ahd->tqinfifofnext),
869 /*len*/sizeof(struct target_cmd), 883 /*len*/sizeof(struct target_cmd),
870 BUS_DMASYNC_POSTREAD); 884 BUS_DMASYNC_POSTREAD);
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 1c8f872e2dd4..2567e29960bd 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -1468,6 +1468,30 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev,
1468 if ((tstate->auto_negotiate & mask) != 0) { 1468 if ((tstate->auto_negotiate & mask) != 0) {
1469 scb->flags |= SCB_AUTO_NEGOTIATE; 1469 scb->flags |= SCB_AUTO_NEGOTIATE;
1470 scb->hscb->control |= MK_MESSAGE; 1470 scb->hscb->control |= MK_MESSAGE;
1471 } else if (cmd->cmnd[0] == INQUIRY
1472 && (tinfo->curr.offset != 0
1473 || tinfo->curr.width != MSG_EXT_WDTR_BUS_8_BIT
1474 || tinfo->curr.ppr_options != 0)
1475 && (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ)==0) {
1476 /*
1477 * The SCSI spec requires inquiry
1478 * commands to complete without
1479 * reporting unit attention conditions.
1480 * Because of this, an inquiry command
1481 * that occurs just after a device is
1482 * reset will result in a data phase
1483 * with mismatched negotiated rates.
1484 * The core already forces a renegotiation
1485 * for reset events that are visible to
1486 * our controller or that we initiate,
1487 * but a third party device reset or a
1488 * hot-plug insertion can still cause this
1489 * issue. Therefore, we force a re-negotiation
1490 * for every inquiry command unless we
1491 * are async.
1492 */
1493 scb->flags |= SCB_NEGOTIATE;
1494 scb->hscb->control |= MK_MESSAGE;
1471 } 1495 }
1472 1496
1473 if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) { 1497 if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) {
@@ -2058,6 +2082,7 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
2058 int paused; 2082 int paused;
2059 int wait; 2083 int wait;
2060 int disconnected; 2084 int disconnected;
2085 int found;
2061 ahd_mode_state saved_modes; 2086 ahd_mode_state saved_modes;
2062 unsigned long flags; 2087 unsigned long flags;
2063 2088
@@ -2176,7 +2201,8 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
2176 last_phase = ahd_inb(ahd, LASTPHASE); 2201 last_phase = ahd_inb(ahd, LASTPHASE);
2177 saved_scbptr = ahd_get_scbptr(ahd); 2202 saved_scbptr = ahd_get_scbptr(ahd);
2178 active_scbptr = saved_scbptr; 2203 active_scbptr = saved_scbptr;
2179 if (disconnected && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0) { 2204 if (disconnected && ((last_phase != P_BUSFREE) ||
2205 (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0)) {
2180 struct scb *bus_scb; 2206 struct scb *bus_scb;
2181 2207
2182 bus_scb = ahd_lookup_scb(ahd, active_scbptr); 2208 bus_scb = ahd_lookup_scb(ahd, active_scbptr);
@@ -2194,28 +2220,41 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
2194 * bus or is in the disconnected state. 2220 * bus or is in the disconnected state.
2195 */ 2221 */
2196 saved_scsiid = ahd_inb(ahd, SAVED_SCSIID); 2222 saved_scsiid = ahd_inb(ahd, SAVED_SCSIID);
2197 if (last_phase != P_BUSFREE 2223 if (SCB_GET_TAG(pending_scb) == active_scbptr
2198 && (SCB_GET_TAG(pending_scb) == active_scbptr
2199 || (flag == SCB_DEVICE_RESET 2224 || (flag == SCB_DEVICE_RESET
2200 && SCSIID_TARGET(ahd, saved_scsiid) == scmd_id(cmd)))) { 2225 && SCSIID_TARGET(ahd, saved_scsiid) == scmd_id(cmd))) {
2201 2226
2202 /* 2227 /*
2203 * We're active on the bus, so assert ATN 2228 * We're active on the bus, so assert ATN
2204 * and hope that the target responds. 2229 * and hope that the target responds.
2205 */ 2230 */
2206 pending_scb = ahd_lookup_scb(ahd, active_scbptr); 2231 pending_scb = ahd_lookup_scb(ahd, active_scbptr);
2207 pending_scb->flags |= SCB_RECOVERY_SCB|flag; 2232 pending_scb->flags |= SCB_RECOVERY_SCB|SCB_DEVICE_RESET;
2208 ahd_outb(ahd, MSG_OUT, HOST_MSG); 2233 ahd_outb(ahd, MSG_OUT, HOST_MSG);
2209 ahd_outb(ahd, SCSISIGO, last_phase|ATNO); 2234 ahd_outb(ahd, SCSISIGO, last_phase|ATNO);
2210 scmd_printk(KERN_INFO, cmd, "Device is active, asserting ATN\n"); 2235 scmd_printk(KERN_INFO, cmd, "BDR message in message buffer\n");
2211 wait = TRUE; 2236 wait = TRUE;
2237 } else if (last_phase != P_BUSFREE
2238 && ahd_inb(ahd, SCSIPHASE) == 0) {
2239 /*
2240 * SCB is not identified, there
2241 * is no pending REQ, and the sequencer
2242 * has not seen a busfree. Looks like
2243 * a stuck connection waiting to
2244 * go busfree. Reset the bus.
2245 */
2246 found = ahd_reset_channel(ahd, cmd->device->channel + 'A',
2247 /*Initiate Reset*/TRUE);
2248 printf("%s: Issued Channel %c Bus Reset. "
2249 "%d SCBs aborted\n", ahd_name(ahd),
2250 cmd->device->channel + 'A', found);
2212 } else if (disconnected) { 2251 } else if (disconnected) {
2213 2252
2214 /* 2253 /*
2215 * Actually re-queue this SCB in an attempt 2254 * Actually re-queue this SCB in an attempt
2216 * to select the device before it reconnects. 2255 * to select the device before it reconnects.
2217 */ 2256 */
2218 pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT; 2257 pending_scb->flags |= SCB_RECOVERY_SCB|flag;
2219 ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb)); 2258 ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb));
2220 pending_scb->hscb->cdb_len = 0; 2259 pending_scb->hscb->cdb_len = 0;
2221 pending_scb->hscb->task_attribute = 0; 2260 pending_scb->hscb->task_attribute = 0;
@@ -2296,16 +2335,17 @@ done:
2296 timer.expires = jiffies + (5 * HZ); 2335 timer.expires = jiffies + (5 * HZ);
2297 timer.function = ahd_linux_sem_timeout; 2336 timer.function = ahd_linux_sem_timeout;
2298 add_timer(&timer); 2337 add_timer(&timer);
2299 printf("Recovery code sleeping\n"); 2338 printf("%s: Recovery code sleeping\n", ahd_name(ahd));
2300 down(&ahd->platform_data->eh_sem); 2339 down(&ahd->platform_data->eh_sem);
2301 printf("Recovery code awake\n"); 2340 printf("%s: Recovery code awake\n", ahd_name(ahd));
2302 ret = del_timer_sync(&timer); 2341 ret = del_timer_sync(&timer);
2303 if (ret == 0) { 2342 if (ret == 0) {
2304 printf("Timer Expired\n"); 2343 printf("%s: Timer Expired (active %d)\n",
2344 ahd_name(ahd), dev->active);
2305 retval = FAILED; 2345 retval = FAILED;
2306 } 2346 }
2307 } 2347 }
2308 ahd_unlock(ahd, &flags); 2348 ahd_unlock(ahd, &flags);
2309 return (retval); 2349 return (retval);
2310} 2350}
2311 2351
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h
index bc44222d6cc3..cb74fccc8100 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.h
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.h
@@ -252,7 +252,7 @@ ahd_scb_timer_reset(struct scb *scb, u_int usec)
252/***************************** SMP support ************************************/ 252/***************************** SMP support ************************************/
253#include <linux/spinlock.h> 253#include <linux/spinlock.h>
254 254
255#define AIC79XX_DRIVER_VERSION "1.3.11" 255#define AIC79XX_DRIVER_VERSION "3.0"
256 256
257/*************************** Device Data Structures ***************************/ 257/*************************** Device Data Structures ***************************/
258/* 258/*
diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c
index 2131db60018a..196a6344b037 100644
--- a/drivers/scsi/aic7xxx/aic79xx_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_pci.c
@@ -38,9 +38,7 @@
38 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 38 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39 * POSSIBILITY OF SUCH DAMAGES. 39 * POSSIBILITY OF SUCH DAMAGES.
40 * 40 *
41 * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#77 $ 41 * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#89 $
42 *
43 * $FreeBSD$
44 */ 42 */
45 43
46#ifdef __linux__ 44#ifdef __linux__
@@ -114,6 +112,13 @@ struct ahd_pci_identity ahd_pci_ident_table [] =
114 "Adaptec 29320ALP Ultra320 SCSI adapter", 112 "Adaptec 29320ALP Ultra320 SCSI adapter",
115 ahd_aic7901_setup 113 ahd_aic7901_setup
116 }, 114 },
115 /* aic7901A based controllers */
116 {
117 ID_AHA_29320LP,
118 ID_ALL_MASK,
119 "Adaptec 29320LP Ultra320 SCSI adapter",
120 ahd_aic7901A_setup
121 },
117 /* aic7902 based controllers */ 122 /* aic7902 based controllers */
118 { 123 {
119 ID_AHA_29320, 124 ID_AHA_29320,
@@ -128,12 +133,6 @@ struct ahd_pci_identity ahd_pci_ident_table [] =
128 ahd_aic7902_setup 133 ahd_aic7902_setup
129 }, 134 },
130 { 135 {
131 ID_AHA_29320LP,
132 ID_ALL_MASK,
133 "Adaptec 29320LP Ultra320 SCSI adapter",
134 ahd_aic7901A_setup
135 },
136 {
137 ID_AHA_39320, 136 ID_AHA_39320,
138 ID_ALL_MASK, 137 ID_ALL_MASK,
139 "Adaptec 39320 Ultra320 SCSI adapter", 138 "Adaptec 39320 Ultra320 SCSI adapter",
@@ -146,6 +145,12 @@ struct ahd_pci_identity ahd_pci_ident_table [] =
146 ahd_aic7902_setup 145 ahd_aic7902_setup
147 }, 146 },
148 { 147 {
148 ID_AHA_39320_B_DELL,
149 ID_ALL_MASK,
150 "Adaptec (Dell OEM) 39320 Ultra320 SCSI adapter",
151 ahd_aic7902_setup
152 },
153 {
149 ID_AHA_39320A, 154 ID_AHA_39320A,
150 ID_ALL_MASK, 155 ID_ALL_MASK,
151 "Adaptec 39320A Ultra320 SCSI adapter", 156 "Adaptec 39320A Ultra320 SCSI adapter",
@@ -668,6 +673,7 @@ ahd_configure_termination(struct ahd_softc *ahd, u_int adapter_control)
668 * Now set the termination based on what we found. 673 * Now set the termination based on what we found.
669 */ 674 */
670 sxfrctl1 = ahd_inb(ahd, SXFRCTL1) & ~STPWEN; 675 sxfrctl1 = ahd_inb(ahd, SXFRCTL1) & ~STPWEN;
676 ahd->flags &= ~AHD_TERM_ENB_A;
671 if ((termctl & FLX_TERMCTL_ENPRILOW) != 0) { 677 if ((termctl & FLX_TERMCTL_ENPRILOW) != 0) {
672 ahd->flags |= AHD_TERM_ENB_A; 678 ahd->flags |= AHD_TERM_ENB_A;
673 sxfrctl1 |= STPWEN; 679 sxfrctl1 |= STPWEN;
diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.h b/drivers/scsi/aic7xxx/aic79xx_pci.h
index b5cfeabdfecf..da45153668c7 100644
--- a/drivers/scsi/aic7xxx/aic79xx_pci.h
+++ b/drivers/scsi/aic7xxx/aic79xx_pci.h
@@ -53,14 +53,15 @@
53#define ID_AHA_29320ALP 0x8017900500449005ull 53#define ID_AHA_29320ALP 0x8017900500449005ull
54 54
55#define ID_AIC7901A 0x801E9005FFFF9005ull 55#define ID_AIC7901A 0x801E9005FFFF9005ull
56#define ID_AHA_29320 0x8012900500429005ull
57#define ID_AHA_29320B 0x8013900500439005ull
58#define ID_AHA_29320LP 0x8014900500449005ull 56#define ID_AHA_29320LP 0x8014900500449005ull
59 57
60#define ID_AIC7902 0x801F9005FFFF9005ull 58#define ID_AIC7902 0x801F9005FFFF9005ull
61#define ID_AIC7902_B 0x801D9005FFFF9005ull 59#define ID_AIC7902_B 0x801D9005FFFF9005ull
62#define ID_AHA_39320 0x8010900500409005ull 60#define ID_AHA_39320 0x8010900500409005ull
61#define ID_AHA_29320 0x8012900500429005ull
62#define ID_AHA_29320B 0x8013900500439005ull
63#define ID_AHA_39320_B 0x8015900500409005ull 63#define ID_AHA_39320_B 0x8015900500409005ull
64#define ID_AHA_39320_B_DELL 0x8015900501681028ull
64#define ID_AHA_39320A 0x8016900500409005ull 65#define ID_AHA_39320A 0x8016900500409005ull
65#define ID_AHA_39320D 0x8011900500419005ull 66#define ID_AHA_39320D 0x8011900500419005ull
66#define ID_AHA_39320D_B 0x801C900500419005ull 67#define ID_AHA_39320D_B 0x801C900500419005ull
diff --git a/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped b/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped
index c01ac39090d9..8763b158856b 100644
--- a/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped
+++ b/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped
@@ -2,8 +2,8 @@
2 * DO NOT EDIT - This file is automatically generated 2 * DO NOT EDIT - This file is automatically generated
3 * from the following source files: 3 * from the following source files:
4 * 4 *
5 * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#94 $ 5 * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#119 $
6 * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $ 6 * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#76 $
7 */ 7 */
8typedef int (ahd_reg_print_t)(u_int, u_int *, u_int); 8typedef int (ahd_reg_print_t)(u_int, u_int *, u_int);
9typedef struct ahd_reg_parse_entry { 9typedef struct ahd_reg_parse_entry {
@@ -83,17 +83,17 @@ ahd_reg_print_t ahd_hs_mailbox_print;
83#endif 83#endif
84 84
85#if AIC_DEBUG_REGISTERS 85#if AIC_DEBUG_REGISTERS
86ahd_reg_print_t ahd_clrseqintstat_print; 86ahd_reg_print_t ahd_seqintstat_print;
87#else 87#else
88#define ahd_clrseqintstat_print(regvalue, cur_col, wrap) \ 88#define ahd_seqintstat_print(regvalue, cur_col, wrap) \
89 ahd_print_register(NULL, 0, "CLRSEQINTSTAT", 0x0c, regvalue, cur_col, wrap) 89 ahd_print_register(NULL, 0, "SEQINTSTAT", 0x0c, regvalue, cur_col, wrap)
90#endif 90#endif
91 91
92#if AIC_DEBUG_REGISTERS 92#if AIC_DEBUG_REGISTERS
93ahd_reg_print_t ahd_seqintstat_print; 93ahd_reg_print_t ahd_clrseqintstat_print;
94#else 94#else
95#define ahd_seqintstat_print(regvalue, cur_col, wrap) \ 95#define ahd_clrseqintstat_print(regvalue, cur_col, wrap) \
96 ahd_print_register(NULL, 0, "SEQINTSTAT", 0x0c, regvalue, cur_col, wrap) 96 ahd_print_register(NULL, 0, "CLRSEQINTSTAT", 0x0c, regvalue, cur_col, wrap)
97#endif 97#endif
98 98
99#if AIC_DEBUG_REGISTERS 99#if AIC_DEBUG_REGISTERS
@@ -412,17 +412,17 @@ ahd_reg_print_t ahd_sxfrctl0_print;
412#endif 412#endif
413 413
414#if AIC_DEBUG_REGISTERS 414#if AIC_DEBUG_REGISTERS
415ahd_reg_print_t ahd_businitid_print; 415ahd_reg_print_t ahd_dlcount_print;
416#else 416#else
417#define ahd_businitid_print(regvalue, cur_col, wrap) \ 417#define ahd_dlcount_print(regvalue, cur_col, wrap) \
418 ahd_print_register(NULL, 0, "BUSINITID", 0x3c, regvalue, cur_col, wrap) 418 ahd_print_register(NULL, 0, "DLCOUNT", 0x3c, regvalue, cur_col, wrap)
419#endif 419#endif
420 420
421#if AIC_DEBUG_REGISTERS 421#if AIC_DEBUG_REGISTERS
422ahd_reg_print_t ahd_dlcount_print; 422ahd_reg_print_t ahd_businitid_print;
423#else 423#else
424#define ahd_dlcount_print(regvalue, cur_col, wrap) \ 424#define ahd_businitid_print(regvalue, cur_col, wrap) \
425 ahd_print_register(NULL, 0, "DLCOUNT", 0x3c, regvalue, cur_col, wrap) 425 ahd_print_register(NULL, 0, "BUSINITID", 0x3c, regvalue, cur_col, wrap)
426#endif 426#endif
427 427
428#if AIC_DEBUG_REGISTERS 428#if AIC_DEBUG_REGISTERS
@@ -517,13 +517,6 @@ ahd_reg_print_t ahd_selid_print;
517#endif 517#endif
518 518
519#if AIC_DEBUG_REGISTERS 519#if AIC_DEBUG_REGISTERS
520ahd_reg_print_t ahd_sblkctl_print;
521#else
522#define ahd_sblkctl_print(regvalue, cur_col, wrap) \
523 ahd_print_register(NULL, 0, "SBLKCTL", 0x4a, regvalue, cur_col, wrap)
524#endif
525
526#if AIC_DEBUG_REGISTERS
527ahd_reg_print_t ahd_optionmode_print; 520ahd_reg_print_t ahd_optionmode_print;
528#else 521#else
529#define ahd_optionmode_print(regvalue, cur_col, wrap) \ 522#define ahd_optionmode_print(regvalue, cur_col, wrap) \
@@ -531,10 +524,10 @@ ahd_reg_print_t ahd_optionmode_print;
531#endif 524#endif
532 525
533#if AIC_DEBUG_REGISTERS 526#if AIC_DEBUG_REGISTERS
534ahd_reg_print_t ahd_sstat0_print; 527ahd_reg_print_t ahd_sblkctl_print;
535#else 528#else
536#define ahd_sstat0_print(regvalue, cur_col, wrap) \ 529#define ahd_sblkctl_print(regvalue, cur_col, wrap) \
537 ahd_print_register(NULL, 0, "SSTAT0", 0x4b, regvalue, cur_col, wrap) 530 ahd_print_register(NULL, 0, "SBLKCTL", 0x4a, regvalue, cur_col, wrap)
538#endif 531#endif
539 532
540#if AIC_DEBUG_REGISTERS 533#if AIC_DEBUG_REGISTERS
@@ -545,6 +538,13 @@ ahd_reg_print_t ahd_clrsint0_print;
545#endif 538#endif
546 539
547#if AIC_DEBUG_REGISTERS 540#if AIC_DEBUG_REGISTERS
541ahd_reg_print_t ahd_sstat0_print;
542#else
543#define ahd_sstat0_print(regvalue, cur_col, wrap) \
544 ahd_print_register(NULL, 0, "SSTAT0", 0x4b, regvalue, cur_col, wrap)
545#endif
546
547#if AIC_DEBUG_REGISTERS
548ahd_reg_print_t ahd_simode0_print; 548ahd_reg_print_t ahd_simode0_print;
549#else 549#else
550#define ahd_simode0_print(regvalue, cur_col, wrap) \ 550#define ahd_simode0_print(regvalue, cur_col, wrap) \
@@ -573,17 +573,17 @@ ahd_reg_print_t ahd_sstat2_print;
573#endif 573#endif
574 574
575#if AIC_DEBUG_REGISTERS 575#if AIC_DEBUG_REGISTERS
576ahd_reg_print_t ahd_clrsint2_print; 576ahd_reg_print_t ahd_simode2_print;
577#else 577#else
578#define ahd_clrsint2_print(regvalue, cur_col, wrap) \ 578#define ahd_simode2_print(regvalue, cur_col, wrap) \
579 ahd_print_register(NULL, 0, "CLRSINT2", 0x4d, regvalue, cur_col, wrap) 579 ahd_print_register(NULL, 0, "SIMODE2", 0x4d, regvalue, cur_col, wrap)
580#endif 580#endif
581 581
582#if AIC_DEBUG_REGISTERS 582#if AIC_DEBUG_REGISTERS
583ahd_reg_print_t ahd_simode2_print; 583ahd_reg_print_t ahd_clrsint2_print;
584#else 584#else
585#define ahd_simode2_print(regvalue, cur_col, wrap) \ 585#define ahd_clrsint2_print(regvalue, cur_col, wrap) \
586 ahd_print_register(NULL, 0, "SIMODE2", 0x4d, regvalue, cur_col, wrap) 586 ahd_print_register(NULL, 0, "CLRSINT2", 0x4d, regvalue, cur_col, wrap)
587#endif 587#endif
588 588
589#if AIC_DEBUG_REGISTERS 589#if AIC_DEBUG_REGISTERS
@@ -685,13 +685,6 @@ ahd_reg_print_t ahd_clrsint3_print;
685#endif 685#endif
686 686
687#if AIC_DEBUG_REGISTERS 687#if AIC_DEBUG_REGISTERS
688ahd_reg_print_t ahd_lqomode0_print;
689#else
690#define ahd_lqomode0_print(regvalue, cur_col, wrap) \
691 ahd_print_register(NULL, 0, "LQOMODE0", 0x54, regvalue, cur_col, wrap)
692#endif
693
694#if AIC_DEBUG_REGISTERS
695ahd_reg_print_t ahd_lqostat0_print; 688ahd_reg_print_t ahd_lqostat0_print;
696#else 689#else
697#define ahd_lqostat0_print(regvalue, cur_col, wrap) \ 690#define ahd_lqostat0_print(regvalue, cur_col, wrap) \
@@ -706,6 +699,20 @@ ahd_reg_print_t ahd_clrlqoint0_print;
706#endif 699#endif
707 700
708#if AIC_DEBUG_REGISTERS 701#if AIC_DEBUG_REGISTERS
702ahd_reg_print_t ahd_lqomode0_print;
703#else
704#define ahd_lqomode0_print(regvalue, cur_col, wrap) \
705 ahd_print_register(NULL, 0, "LQOMODE0", 0x54, regvalue, cur_col, wrap)
706#endif
707
708#if AIC_DEBUG_REGISTERS
709ahd_reg_print_t ahd_lqomode1_print;
710#else
711#define ahd_lqomode1_print(regvalue, cur_col, wrap) \
712 ahd_print_register(NULL, 0, "LQOMODE1", 0x55, regvalue, cur_col, wrap)
713#endif
714
715#if AIC_DEBUG_REGISTERS
709ahd_reg_print_t ahd_lqostat1_print; 716ahd_reg_print_t ahd_lqostat1_print;
710#else 717#else
711#define ahd_lqostat1_print(regvalue, cur_col, wrap) \ 718#define ahd_lqostat1_print(regvalue, cur_col, wrap) \
@@ -720,13 +727,6 @@ ahd_reg_print_t ahd_clrlqoint1_print;
720#endif 727#endif
721 728
722#if AIC_DEBUG_REGISTERS 729#if AIC_DEBUG_REGISTERS
723ahd_reg_print_t ahd_lqomode1_print;
724#else
725#define ahd_lqomode1_print(regvalue, cur_col, wrap) \
726 ahd_print_register(NULL, 0, "LQOMODE1", 0x55, regvalue, cur_col, wrap)
727#endif
728
729#if AIC_DEBUG_REGISTERS
730ahd_reg_print_t ahd_lqostat2_print; 730ahd_reg_print_t ahd_lqostat2_print;
731#else 731#else
732#define ahd_lqostat2_print(regvalue, cur_col, wrap) \ 732#define ahd_lqostat2_print(regvalue, cur_col, wrap) \
@@ -909,17 +909,17 @@ ahd_reg_print_t ahd_annexcol_print;
909#endif 909#endif
910 910
911#if AIC_DEBUG_REGISTERS 911#if AIC_DEBUG_REGISTERS
912ahd_reg_print_t ahd_scschkn_print; 912ahd_reg_print_t ahd_annexdat_print;
913#else 913#else
914#define ahd_scschkn_print(regvalue, cur_col, wrap) \ 914#define ahd_annexdat_print(regvalue, cur_col, wrap) \
915 ahd_print_register(NULL, 0, "SCSCHKN", 0x66, regvalue, cur_col, wrap) 915 ahd_print_register(NULL, 0, "ANNEXDAT", 0x66, regvalue, cur_col, wrap)
916#endif 916#endif
917 917
918#if AIC_DEBUG_REGISTERS 918#if AIC_DEBUG_REGISTERS
919ahd_reg_print_t ahd_annexdat_print; 919ahd_reg_print_t ahd_scschkn_print;
920#else 920#else
921#define ahd_annexdat_print(regvalue, cur_col, wrap) \ 921#define ahd_scschkn_print(regvalue, cur_col, wrap) \
922 ahd_print_register(NULL, 0, "ANNEXDAT", 0x66, regvalue, cur_col, wrap) 922 ahd_print_register(NULL, 0, "SCSCHKN", 0x66, regvalue, cur_col, wrap)
923#endif 923#endif
924 924
925#if AIC_DEBUG_REGISTERS 925#if AIC_DEBUG_REGISTERS
@@ -1000,17 +1000,17 @@ ahd_reg_print_t ahd_pll400ctl1_print;
1000#endif 1000#endif
1001 1001
1002#if AIC_DEBUG_REGISTERS 1002#if AIC_DEBUG_REGISTERS
1003ahd_reg_print_t ahd_pll400cnt0_print; 1003ahd_reg_print_t ahd_unfairness_print;
1004#else 1004#else
1005#define ahd_pll400cnt0_print(regvalue, cur_col, wrap) \ 1005#define ahd_unfairness_print(regvalue, cur_col, wrap) \
1006 ahd_print_register(NULL, 0, "PLL400CNT0", 0x6e, regvalue, cur_col, wrap) 1006 ahd_print_register(NULL, 0, "UNFAIRNESS", 0x6e, regvalue, cur_col, wrap)
1007#endif 1007#endif
1008 1008
1009#if AIC_DEBUG_REGISTERS 1009#if AIC_DEBUG_REGISTERS
1010ahd_reg_print_t ahd_unfairness_print; 1010ahd_reg_print_t ahd_pll400cnt0_print;
1011#else 1011#else
1012#define ahd_unfairness_print(regvalue, cur_col, wrap) \ 1012#define ahd_pll400cnt0_print(regvalue, cur_col, wrap) \
1013 ahd_print_register(NULL, 0, "UNFAIRNESS", 0x6e, regvalue, cur_col, wrap) 1013 ahd_print_register(NULL, 0, "PLL400CNT0", 0x6e, regvalue, cur_col, wrap)
1014#endif 1014#endif
1015 1015
1016#if AIC_DEBUG_REGISTERS 1016#if AIC_DEBUG_REGISTERS
@@ -1056,13 +1056,6 @@ ahd_reg_print_t ahd_hodmaen_print;
1056#endif 1056#endif
1057 1057
1058#if AIC_DEBUG_REGISTERS 1058#if AIC_DEBUG_REGISTERS
1059ahd_reg_print_t ahd_sghaddr_print;
1060#else
1061#define ahd_sghaddr_print(regvalue, cur_col, wrap) \
1062 ahd_print_register(NULL, 0, "SGHADDR", 0x7c, regvalue, cur_col, wrap)
1063#endif
1064
1065#if AIC_DEBUG_REGISTERS
1066ahd_reg_print_t ahd_scbhaddr_print; 1059ahd_reg_print_t ahd_scbhaddr_print;
1067#else 1060#else
1068#define ahd_scbhaddr_print(regvalue, cur_col, wrap) \ 1061#define ahd_scbhaddr_print(regvalue, cur_col, wrap) \
@@ -1070,10 +1063,10 @@ ahd_reg_print_t ahd_scbhaddr_print;
1070#endif 1063#endif
1071 1064
1072#if AIC_DEBUG_REGISTERS 1065#if AIC_DEBUG_REGISTERS
1073ahd_reg_print_t ahd_sghcnt_print; 1066ahd_reg_print_t ahd_sghaddr_print;
1074#else 1067#else
1075#define ahd_sghcnt_print(regvalue, cur_col, wrap) \ 1068#define ahd_sghaddr_print(regvalue, cur_col, wrap) \
1076 ahd_print_register(NULL, 0, "SGHCNT", 0x84, regvalue, cur_col, wrap) 1069 ahd_print_register(NULL, 0, "SGHADDR", 0x7c, regvalue, cur_col, wrap)
1077#endif 1070#endif
1078 1071
1079#if AIC_DEBUG_REGISTERS 1072#if AIC_DEBUG_REGISTERS
@@ -1084,6 +1077,13 @@ ahd_reg_print_t ahd_scbhcnt_print;
1084#endif 1077#endif
1085 1078
1086#if AIC_DEBUG_REGISTERS 1079#if AIC_DEBUG_REGISTERS
1080ahd_reg_print_t ahd_sghcnt_print;
1081#else
1082#define ahd_sghcnt_print(regvalue, cur_col, wrap) \
1083 ahd_print_register(NULL, 0, "SGHCNT", 0x84, regvalue, cur_col, wrap)
1084#endif
1085
1086#if AIC_DEBUG_REGISTERS
1087ahd_reg_print_t ahd_dff_thrsh_print; 1087ahd_reg_print_t ahd_dff_thrsh_print;
1088#else 1088#else
1089#define ahd_dff_thrsh_print(regvalue, cur_col, wrap) \ 1089#define ahd_dff_thrsh_print(regvalue, cur_col, wrap) \
@@ -1154,13 +1154,6 @@ ahd_reg_print_t ahd_nsenable_print;
1154#endif 1154#endif
1155 1155
1156#if AIC_DEBUG_REGISTERS 1156#if AIC_DEBUG_REGISTERS
1157ahd_reg_print_t ahd_dchrxmsg1_print;
1158#else
1159#define ahd_dchrxmsg1_print(regvalue, cur_col, wrap) \
1160 ahd_print_register(NULL, 0, "DCHRXMSG1", 0x91, regvalue, cur_col, wrap)
1161#endif
1162
1163#if AIC_DEBUG_REGISTERS
1164ahd_reg_print_t ahd_cmcrxmsg1_print; 1157ahd_reg_print_t ahd_cmcrxmsg1_print;
1165#else 1158#else
1166#define ahd_cmcrxmsg1_print(regvalue, cur_col, wrap) \ 1159#define ahd_cmcrxmsg1_print(regvalue, cur_col, wrap) \
@@ -1168,17 +1161,17 @@ ahd_reg_print_t ahd_cmcrxmsg1_print;
1168#endif 1161#endif
1169 1162
1170#if AIC_DEBUG_REGISTERS 1163#if AIC_DEBUG_REGISTERS
1171ahd_reg_print_t ahd_dchrxmsg2_print; 1164ahd_reg_print_t ahd_dchrxmsg1_print;
1172#else 1165#else
1173#define ahd_dchrxmsg2_print(regvalue, cur_col, wrap) \ 1166#define ahd_dchrxmsg1_print(regvalue, cur_col, wrap) \
1174 ahd_print_register(NULL, 0, "DCHRXMSG2", 0x92, regvalue, cur_col, wrap) 1167 ahd_print_register(NULL, 0, "DCHRXMSG1", 0x91, regvalue, cur_col, wrap)
1175#endif 1168#endif
1176 1169
1177#if AIC_DEBUG_REGISTERS 1170#if AIC_DEBUG_REGISTERS
1178ahd_reg_print_t ahd_ovlyrxmsg2_print; 1171ahd_reg_print_t ahd_dchrxmsg2_print;
1179#else 1172#else
1180#define ahd_ovlyrxmsg2_print(regvalue, cur_col, wrap) \ 1173#define ahd_dchrxmsg2_print(regvalue, cur_col, wrap) \
1181 ahd_print_register(NULL, 0, "OVLYRXMSG2", 0x92, regvalue, cur_col, wrap) 1174 ahd_print_register(NULL, 0, "DCHRXMSG2", 0x92, regvalue, cur_col, wrap)
1182#endif 1175#endif
1183 1176
1184#if AIC_DEBUG_REGISTERS 1177#if AIC_DEBUG_REGISTERS
@@ -1196,6 +1189,13 @@ ahd_reg_print_t ahd_ost_print;
1196#endif 1189#endif
1197 1190
1198#if AIC_DEBUG_REGISTERS 1191#if AIC_DEBUG_REGISTERS
1192ahd_reg_print_t ahd_ovlyrxmsg2_print;
1193#else
1194#define ahd_ovlyrxmsg2_print(regvalue, cur_col, wrap) \
1195 ahd_print_register(NULL, 0, "OVLYRXMSG2", 0x92, regvalue, cur_col, wrap)
1196#endif
1197
1198#if AIC_DEBUG_REGISTERS
1199ahd_reg_print_t ahd_dchrxmsg3_print; 1199ahd_reg_print_t ahd_dchrxmsg3_print;
1200#else 1200#else
1201#define ahd_dchrxmsg3_print(regvalue, cur_col, wrap) \ 1201#define ahd_dchrxmsg3_print(regvalue, cur_col, wrap) \
@@ -1203,6 +1203,13 @@ ahd_reg_print_t ahd_dchrxmsg3_print;
1203#endif 1203#endif
1204 1204
1205#if AIC_DEBUG_REGISTERS 1205#if AIC_DEBUG_REGISTERS
1206ahd_reg_print_t ahd_ovlyrxmsg3_print;
1207#else
1208#define ahd_ovlyrxmsg3_print(regvalue, cur_col, wrap) \
1209 ahd_print_register(NULL, 0, "OVLYRXMSG3", 0x93, regvalue, cur_col, wrap)
1210#endif
1211
1212#if AIC_DEBUG_REGISTERS
1206ahd_reg_print_t ahd_cmcrxmsg3_print; 1213ahd_reg_print_t ahd_cmcrxmsg3_print;
1207#else 1214#else
1208#define ahd_cmcrxmsg3_print(regvalue, cur_col, wrap) \ 1215#define ahd_cmcrxmsg3_print(regvalue, cur_col, wrap) \
@@ -1217,13 +1224,6 @@ ahd_reg_print_t ahd_pcixctl_print;
1217#endif 1224#endif
1218 1225
1219#if AIC_DEBUG_REGISTERS 1226#if AIC_DEBUG_REGISTERS
1220ahd_reg_print_t ahd_ovlyrxmsg3_print;
1221#else
1222#define ahd_ovlyrxmsg3_print(regvalue, cur_col, wrap) \
1223 ahd_print_register(NULL, 0, "OVLYRXMSG3", 0x93, regvalue, cur_col, wrap)
1224#endif
1225
1226#if AIC_DEBUG_REGISTERS
1227ahd_reg_print_t ahd_ovlyseqbcnt_print; 1227ahd_reg_print_t ahd_ovlyseqbcnt_print;
1228#else 1228#else
1229#define ahd_ovlyseqbcnt_print(regvalue, cur_col, wrap) \ 1229#define ahd_ovlyseqbcnt_print(regvalue, cur_col, wrap) \
@@ -1231,13 +1231,6 @@ ahd_reg_print_t ahd_ovlyseqbcnt_print;
1231#endif 1231#endif
1232 1232
1233#if AIC_DEBUG_REGISTERS 1233#if AIC_DEBUG_REGISTERS
1234ahd_reg_print_t ahd_cmcseqbcnt_print;
1235#else
1236#define ahd_cmcseqbcnt_print(regvalue, cur_col, wrap) \
1237 ahd_print_register(NULL, 0, "CMCSEQBCNT", 0x94, regvalue, cur_col, wrap)
1238#endif
1239
1240#if AIC_DEBUG_REGISTERS
1241ahd_reg_print_t ahd_dchseqbcnt_print; 1234ahd_reg_print_t ahd_dchseqbcnt_print;
1242#else 1235#else
1243#define ahd_dchseqbcnt_print(regvalue, cur_col, wrap) \ 1236#define ahd_dchseqbcnt_print(regvalue, cur_col, wrap) \
@@ -1245,17 +1238,17 @@ ahd_reg_print_t ahd_dchseqbcnt_print;
1245#endif 1238#endif
1246 1239
1247#if AIC_DEBUG_REGISTERS 1240#if AIC_DEBUG_REGISTERS
1248ahd_reg_print_t ahd_cmcspltstat0_print; 1241ahd_reg_print_t ahd_cmcseqbcnt_print;
1249#else 1242#else
1250#define ahd_cmcspltstat0_print(regvalue, cur_col, wrap) \ 1243#define ahd_cmcseqbcnt_print(regvalue, cur_col, wrap) \
1251 ahd_print_register(NULL, 0, "CMCSPLTSTAT0", 0x96, regvalue, cur_col, wrap) 1244 ahd_print_register(NULL, 0, "CMCSEQBCNT", 0x94, regvalue, cur_col, wrap)
1252#endif 1245#endif
1253 1246
1254#if AIC_DEBUG_REGISTERS 1247#if AIC_DEBUG_REGISTERS
1255ahd_reg_print_t ahd_ovlyspltstat0_print; 1248ahd_reg_print_t ahd_cmcspltstat0_print;
1256#else 1249#else
1257#define ahd_ovlyspltstat0_print(regvalue, cur_col, wrap) \ 1250#define ahd_cmcspltstat0_print(regvalue, cur_col, wrap) \
1258 ahd_print_register(NULL, 0, "OVLYSPLTSTAT0", 0x96, regvalue, cur_col, wrap) 1251 ahd_print_register(NULL, 0, "CMCSPLTSTAT0", 0x96, regvalue, cur_col, wrap)
1259#endif 1252#endif
1260 1253
1261#if AIC_DEBUG_REGISTERS 1254#if AIC_DEBUG_REGISTERS
@@ -1266,10 +1259,10 @@ ahd_reg_print_t ahd_dchspltstat0_print;
1266#endif 1259#endif
1267 1260
1268#if AIC_DEBUG_REGISTERS 1261#if AIC_DEBUG_REGISTERS
1269ahd_reg_print_t ahd_dchspltstat1_print; 1262ahd_reg_print_t ahd_ovlyspltstat0_print;
1270#else 1263#else
1271#define ahd_dchspltstat1_print(regvalue, cur_col, wrap) \ 1264#define ahd_ovlyspltstat0_print(regvalue, cur_col, wrap) \
1272 ahd_print_register(NULL, 0, "DCHSPLTSTAT1", 0x97, regvalue, cur_col, wrap) 1265 ahd_print_register(NULL, 0, "OVLYSPLTSTAT0", 0x96, regvalue, cur_col, wrap)
1273#endif 1266#endif
1274 1267
1275#if AIC_DEBUG_REGISTERS 1268#if AIC_DEBUG_REGISTERS
@@ -1287,6 +1280,13 @@ ahd_reg_print_t ahd_ovlyspltstat1_print;
1287#endif 1280#endif
1288 1281
1289#if AIC_DEBUG_REGISTERS 1282#if AIC_DEBUG_REGISTERS
1283ahd_reg_print_t ahd_dchspltstat1_print;
1284#else
1285#define ahd_dchspltstat1_print(regvalue, cur_col, wrap) \
1286 ahd_print_register(NULL, 0, "DCHSPLTSTAT1", 0x97, regvalue, cur_col, wrap)
1287#endif
1288
1289#if AIC_DEBUG_REGISTERS
1290ahd_reg_print_t ahd_sgrxmsg0_print; 1290ahd_reg_print_t ahd_sgrxmsg0_print;
1291#else 1291#else
1292#define ahd_sgrxmsg0_print(regvalue, cur_col, wrap) \ 1292#define ahd_sgrxmsg0_print(regvalue, cur_col, wrap) \
@@ -1378,17 +1378,17 @@ ahd_reg_print_t ahd_sgspltstat0_print;
1378#endif 1378#endif
1379 1379
1380#if AIC_DEBUG_REGISTERS 1380#if AIC_DEBUG_REGISTERS
1381ahd_reg_print_t ahd_sfunct_print; 1381ahd_reg_print_t ahd_sgspltstat1_print;
1382#else 1382#else
1383#define ahd_sfunct_print(regvalue, cur_col, wrap) \ 1383#define ahd_sgspltstat1_print(regvalue, cur_col, wrap) \
1384 ahd_print_register(NULL, 0, "SFUNCT", 0x9f, regvalue, cur_col, wrap) 1384 ahd_print_register(NULL, 0, "SGSPLTSTAT1", 0x9f, regvalue, cur_col, wrap)
1385#endif 1385#endif
1386 1386
1387#if AIC_DEBUG_REGISTERS 1387#if AIC_DEBUG_REGISTERS
1388ahd_reg_print_t ahd_sgspltstat1_print; 1388ahd_reg_print_t ahd_sfunct_print;
1389#else 1389#else
1390#define ahd_sgspltstat1_print(regvalue, cur_col, wrap) \ 1390#define ahd_sfunct_print(regvalue, cur_col, wrap) \
1391 ahd_print_register(NULL, 0, "SGSPLTSTAT1", 0x9f, regvalue, cur_col, wrap) 1391 ahd_print_register(NULL, 0, "SFUNCT", 0x9f, regvalue, cur_col, wrap)
1392#endif 1392#endif
1393 1393
1394#if AIC_DEBUG_REGISTERS 1394#if AIC_DEBUG_REGISTERS
@@ -1504,17 +1504,17 @@ ahd_reg_print_t ahd_ccsgaddr_print;
1504#endif 1504#endif
1505 1505
1506#if AIC_DEBUG_REGISTERS 1506#if AIC_DEBUG_REGISTERS
1507ahd_reg_print_t ahd_ccscbaddr_print; 1507ahd_reg_print_t ahd_ccscbadr_bk_print;
1508#else 1508#else
1509#define ahd_ccscbaddr_print(regvalue, cur_col, wrap) \ 1509#define ahd_ccscbadr_bk_print(regvalue, cur_col, wrap) \
1510 ahd_print_register(NULL, 0, "CCSCBADDR", 0xac, regvalue, cur_col, wrap) 1510 ahd_print_register(NULL, 0, "CCSCBADR_BK", 0xac, regvalue, cur_col, wrap)
1511#endif 1511#endif
1512 1512
1513#if AIC_DEBUG_REGISTERS 1513#if AIC_DEBUG_REGISTERS
1514ahd_reg_print_t ahd_ccscbadr_bk_print; 1514ahd_reg_print_t ahd_ccscbaddr_print;
1515#else 1515#else
1516#define ahd_ccscbadr_bk_print(regvalue, cur_col, wrap) \ 1516#define ahd_ccscbaddr_print(regvalue, cur_col, wrap) \
1517 ahd_print_register(NULL, 0, "CCSCBADR_BK", 0xac, regvalue, cur_col, wrap) 1517 ahd_print_register(NULL, 0, "CCSCBADDR", 0xac, regvalue, cur_col, wrap)
1518#endif 1518#endif
1519 1519
1520#if AIC_DEBUG_REGISTERS 1520#if AIC_DEBUG_REGISTERS
@@ -1525,17 +1525,17 @@ ahd_reg_print_t ahd_cmc_rambist_print;
1525#endif 1525#endif
1526 1526
1527#if AIC_DEBUG_REGISTERS 1527#if AIC_DEBUG_REGISTERS
1528ahd_reg_print_t ahd_ccsgctl_print; 1528ahd_reg_print_t ahd_ccscbctl_print;
1529#else 1529#else
1530#define ahd_ccsgctl_print(regvalue, cur_col, wrap) \ 1530#define ahd_ccscbctl_print(regvalue, cur_col, wrap) \
1531 ahd_print_register(NULL, 0, "CCSGCTL", 0xad, regvalue, cur_col, wrap) 1531 ahd_print_register(NULL, 0, "CCSCBCTL", 0xad, regvalue, cur_col, wrap)
1532#endif 1532#endif
1533 1533
1534#if AIC_DEBUG_REGISTERS 1534#if AIC_DEBUG_REGISTERS
1535ahd_reg_print_t ahd_ccscbctl_print; 1535ahd_reg_print_t ahd_ccsgctl_print;
1536#else 1536#else
1537#define ahd_ccscbctl_print(regvalue, cur_col, wrap) \ 1537#define ahd_ccsgctl_print(regvalue, cur_col, wrap) \
1538 ahd_print_register(NULL, 0, "CCSCBCTL", 0xad, regvalue, cur_col, wrap) 1538 ahd_print_register(NULL, 0, "CCSGCTL", 0xad, regvalue, cur_col, wrap)
1539#endif 1539#endif
1540 1540
1541#if AIC_DEBUG_REGISTERS 1541#if AIC_DEBUG_REGISTERS
@@ -1707,13 +1707,6 @@ ahd_reg_print_t ahd_wrtbiascalc_print;
1707#endif 1707#endif
1708 1708
1709#if AIC_DEBUG_REGISTERS 1709#if AIC_DEBUG_REGISTERS
1710ahd_reg_print_t ahd_dfptrs_print;
1711#else
1712#define ahd_dfptrs_print(regvalue, cur_col, wrap) \
1713 ahd_print_register(NULL, 0, "DFPTRS", 0xc8, regvalue, cur_col, wrap)
1714#endif
1715
1716#if AIC_DEBUG_REGISTERS
1717ahd_reg_print_t ahd_rcvrbiascalc_print; 1710ahd_reg_print_t ahd_rcvrbiascalc_print;
1718#else 1711#else
1719#define ahd_rcvrbiascalc_print(regvalue, cur_col, wrap) \ 1712#define ahd_rcvrbiascalc_print(regvalue, cur_col, wrap) \
@@ -1721,10 +1714,10 @@ ahd_reg_print_t ahd_rcvrbiascalc_print;
1721#endif 1714#endif
1722 1715
1723#if AIC_DEBUG_REGISTERS 1716#if AIC_DEBUG_REGISTERS
1724ahd_reg_print_t ahd_dfbkptr_print; 1717ahd_reg_print_t ahd_dfptrs_print;
1725#else 1718#else
1726#define ahd_dfbkptr_print(regvalue, cur_col, wrap) \ 1719#define ahd_dfptrs_print(regvalue, cur_col, wrap) \
1727 ahd_print_register(NULL, 0, "DFBKPTR", 0xc9, regvalue, cur_col, wrap) 1720 ahd_print_register(NULL, 0, "DFPTRS", 0xc8, regvalue, cur_col, wrap)
1728#endif 1721#endif
1729 1722
1730#if AIC_DEBUG_REGISTERS 1723#if AIC_DEBUG_REGISTERS
@@ -1735,6 +1728,13 @@ ahd_reg_print_t ahd_skewcalc_print;
1735#endif 1728#endif
1736 1729
1737#if AIC_DEBUG_REGISTERS 1730#if AIC_DEBUG_REGISTERS
1731ahd_reg_print_t ahd_dfbkptr_print;
1732#else
1733#define ahd_dfbkptr_print(regvalue, cur_col, wrap) \
1734 ahd_print_register(NULL, 0, "DFBKPTR", 0xc9, regvalue, cur_col, wrap)
1735#endif
1736
1737#if AIC_DEBUG_REGISTERS
1738ahd_reg_print_t ahd_dfdbctl_print; 1738ahd_reg_print_t ahd_dfdbctl_print;
1739#else 1739#else
1740#define ahd_dfdbctl_print(regvalue, cur_col, wrap) \ 1740#define ahd_dfdbctl_print(regvalue, cur_col, wrap) \
@@ -1826,17 +1826,17 @@ ahd_reg_print_t ahd_dindex_print;
1826#endif 1826#endif
1827 1827
1828#if AIC_DEBUG_REGISTERS 1828#if AIC_DEBUG_REGISTERS
1829ahd_reg_print_t ahd_brkaddr1_print; 1829ahd_reg_print_t ahd_brkaddr0_print;
1830#else 1830#else
1831#define ahd_brkaddr1_print(regvalue, cur_col, wrap) \ 1831#define ahd_brkaddr0_print(regvalue, cur_col, wrap) \
1832 ahd_print_register(NULL, 0, "BRKADDR1", 0xe6, regvalue, cur_col, wrap) 1832 ahd_print_register(NULL, 0, "BRKADDR0", 0xe6, regvalue, cur_col, wrap)
1833#endif 1833#endif
1834 1834
1835#if AIC_DEBUG_REGISTERS 1835#if AIC_DEBUG_REGISTERS
1836ahd_reg_print_t ahd_brkaddr0_print; 1836ahd_reg_print_t ahd_brkaddr1_print;
1837#else 1837#else
1838#define ahd_brkaddr0_print(regvalue, cur_col, wrap) \ 1838#define ahd_brkaddr1_print(regvalue, cur_col, wrap) \
1839 ahd_print_register(NULL, 0, "BRKADDR0", 0xe6, regvalue, cur_col, wrap) 1839 ahd_print_register(NULL, 0, "BRKADDR1", 0xe6, regvalue, cur_col, wrap)
1840#endif 1840#endif
1841 1841
1842#if AIC_DEBUG_REGISTERS 1842#if AIC_DEBUG_REGISTERS
@@ -1889,13 +1889,6 @@ ahd_reg_print_t ahd_stack_print;
1889#endif 1889#endif
1890 1890
1891#if AIC_DEBUG_REGISTERS 1891#if AIC_DEBUG_REGISTERS
1892ahd_reg_print_t ahd_curaddr_print;
1893#else
1894#define ahd_curaddr_print(regvalue, cur_col, wrap) \
1895 ahd_print_register(NULL, 0, "CURADDR", 0xf4, regvalue, cur_col, wrap)
1896#endif
1897
1898#if AIC_DEBUG_REGISTERS
1899ahd_reg_print_t ahd_intvec1_addr_print; 1892ahd_reg_print_t ahd_intvec1_addr_print;
1900#else 1893#else
1901#define ahd_intvec1_addr_print(regvalue, cur_col, wrap) \ 1894#define ahd_intvec1_addr_print(regvalue, cur_col, wrap) \
@@ -1903,10 +1896,10 @@ ahd_reg_print_t ahd_intvec1_addr_print;
1903#endif 1896#endif
1904 1897
1905#if AIC_DEBUG_REGISTERS 1898#if AIC_DEBUG_REGISTERS
1906ahd_reg_print_t ahd_intvec2_addr_print; 1899ahd_reg_print_t ahd_curaddr_print;
1907#else 1900#else
1908#define ahd_intvec2_addr_print(regvalue, cur_col, wrap) \ 1901#define ahd_curaddr_print(regvalue, cur_col, wrap) \
1909 ahd_print_register(NULL, 0, "INTVEC2_ADDR", 0xf6, regvalue, cur_col, wrap) 1902 ahd_print_register(NULL, 0, "CURADDR", 0xf4, regvalue, cur_col, wrap)
1910#endif 1903#endif
1911 1904
1912#if AIC_DEBUG_REGISTERS 1905#if AIC_DEBUG_REGISTERS
@@ -1917,6 +1910,13 @@ ahd_reg_print_t ahd_lastaddr_print;
1917#endif 1910#endif
1918 1911
1919#if AIC_DEBUG_REGISTERS 1912#if AIC_DEBUG_REGISTERS
1913ahd_reg_print_t ahd_intvec2_addr_print;
1914#else
1915#define ahd_intvec2_addr_print(regvalue, cur_col, wrap) \
1916 ahd_print_register(NULL, 0, "INTVEC2_ADDR", 0xf6, regvalue, cur_col, wrap)
1917#endif
1918
1919#if AIC_DEBUG_REGISTERS
1920ahd_reg_print_t ahd_longjmp_addr_print; 1920ahd_reg_print_t ahd_longjmp_addr_print;
1921#else 1921#else
1922#define ahd_longjmp_addr_print(regvalue, cur_col, wrap) \ 1922#define ahd_longjmp_addr_print(regvalue, cur_col, wrap) \
@@ -1994,192 +1994,213 @@ ahd_reg_print_t ahd_complete_dma_scb_head_print;
1994#endif 1994#endif
1995 1995
1996#if AIC_DEBUG_REGISTERS 1996#if AIC_DEBUG_REGISTERS
1997ahd_reg_print_t ahd_complete_dma_scb_tail_print;
1998#else
1999#define ahd_complete_dma_scb_tail_print(regvalue, cur_col, wrap) \
2000 ahd_print_register(NULL, 0, "COMPLETE_DMA_SCB_TAIL", 0x12e, regvalue, cur_col, wrap)
2001#endif
2002
2003#if AIC_DEBUG_REGISTERS
2004ahd_reg_print_t ahd_complete_on_qfreeze_head_print;
2005#else
2006#define ahd_complete_on_qfreeze_head_print(regvalue, cur_col, wrap) \
2007 ahd_print_register(NULL, 0, "COMPLETE_ON_QFREEZE_HEAD", 0x130, regvalue, cur_col, wrap)
2008#endif
2009
2010#if AIC_DEBUG_REGISTERS
1997ahd_reg_print_t ahd_qfreeze_count_print; 2011ahd_reg_print_t ahd_qfreeze_count_print;
1998#else 2012#else
1999#define ahd_qfreeze_count_print(regvalue, cur_col, wrap) \ 2013#define ahd_qfreeze_count_print(regvalue, cur_col, wrap) \
2000 ahd_print_register(NULL, 0, "QFREEZE_COUNT", 0x12e, regvalue, cur_col, wrap) 2014 ahd_print_register(NULL, 0, "QFREEZE_COUNT", 0x132, regvalue, cur_col, wrap)
2015#endif
2016
2017#if AIC_DEBUG_REGISTERS
2018ahd_reg_print_t ahd_kernel_qfreeze_count_print;
2019#else
2020#define ahd_kernel_qfreeze_count_print(regvalue, cur_col, wrap) \
2021 ahd_print_register(NULL, 0, "KERNEL_QFREEZE_COUNT", 0x134, regvalue, cur_col, wrap)
2001#endif 2022#endif
2002 2023
2003#if AIC_DEBUG_REGISTERS 2024#if AIC_DEBUG_REGISTERS
2004ahd_reg_print_t ahd_saved_mode_print; 2025ahd_reg_print_t ahd_saved_mode_print;
2005#else 2026#else
2006#define ahd_saved_mode_print(regvalue, cur_col, wrap) \ 2027#define ahd_saved_mode_print(regvalue, cur_col, wrap) \
2007 ahd_print_register(NULL, 0, "SAVED_MODE", 0x130, regvalue, cur_col, wrap) 2028 ahd_print_register(NULL, 0, "SAVED_MODE", 0x136, regvalue, cur_col, wrap)
2008#endif 2029#endif
2009 2030
2010#if AIC_DEBUG_REGISTERS 2031#if AIC_DEBUG_REGISTERS
2011ahd_reg_print_t ahd_msg_out_print; 2032ahd_reg_print_t ahd_msg_out_print;
2012#else 2033#else
2013#define ahd_msg_out_print(regvalue, cur_col, wrap) \ 2034#define ahd_msg_out_print(regvalue, cur_col, wrap) \
2014 ahd_print_register(NULL, 0, "MSG_OUT", 0x131, regvalue, cur_col, wrap) 2035 ahd_print_register(NULL, 0, "MSG_OUT", 0x137, regvalue, cur_col, wrap)
2015#endif 2036#endif
2016 2037
2017#if AIC_DEBUG_REGISTERS 2038#if AIC_DEBUG_REGISTERS
2018ahd_reg_print_t ahd_dmaparams_print; 2039ahd_reg_print_t ahd_dmaparams_print;
2019#else 2040#else
2020#define ahd_dmaparams_print(regvalue, cur_col, wrap) \ 2041#define ahd_dmaparams_print(regvalue, cur_col, wrap) \
2021 ahd_print_register(NULL, 0, "DMAPARAMS", 0x132, regvalue, cur_col, wrap) 2042 ahd_print_register(NULL, 0, "DMAPARAMS", 0x138, regvalue, cur_col, wrap)
2022#endif 2043#endif
2023 2044
2024#if AIC_DEBUG_REGISTERS 2045#if AIC_DEBUG_REGISTERS
2025ahd_reg_print_t ahd_seq_flags_print; 2046ahd_reg_print_t ahd_seq_flags_print;
2026#else 2047#else
2027#define ahd_seq_flags_print(regvalue, cur_col, wrap) \ 2048#define ahd_seq_flags_print(regvalue, cur_col, wrap) \
2028 ahd_print_register(NULL, 0, "SEQ_FLAGS", 0x133, regvalue, cur_col, wrap) 2049 ahd_print_register(NULL, 0, "SEQ_FLAGS", 0x139, regvalue, cur_col, wrap)
2029#endif 2050#endif
2030 2051
2031#if AIC_DEBUG_REGISTERS 2052#if AIC_DEBUG_REGISTERS
2032ahd_reg_print_t ahd_saved_scsiid_print; 2053ahd_reg_print_t ahd_saved_scsiid_print;
2033#else 2054#else
2034#define ahd_saved_scsiid_print(regvalue, cur_col, wrap) \ 2055#define ahd_saved_scsiid_print(regvalue, cur_col, wrap) \
2035 ahd_print_register(NULL, 0, "SAVED_SCSIID", 0x134, regvalue, cur_col, wrap) 2056 ahd_print_register(NULL, 0, "SAVED_SCSIID", 0x13a, regvalue, cur_col, wrap)
2036#endif 2057#endif
2037 2058
2038#if AIC_DEBUG_REGISTERS 2059#if AIC_DEBUG_REGISTERS
2039ahd_reg_print_t ahd_saved_lun_print; 2060ahd_reg_print_t ahd_saved_lun_print;
2040#else 2061#else
2041#define ahd_saved_lun_print(regvalue, cur_col, wrap) \ 2062#define ahd_saved_lun_print(regvalue, cur_col, wrap) \
2042 ahd_print_register(NULL, 0, "SAVED_LUN", 0x135, regvalue, cur_col, wrap) 2063 ahd_print_register(NULL, 0, "SAVED_LUN", 0x13b, regvalue, cur_col, wrap)
2043#endif 2064#endif
2044 2065
2045#if AIC_DEBUG_REGISTERS 2066#if AIC_DEBUG_REGISTERS
2046ahd_reg_print_t ahd_lastphase_print; 2067ahd_reg_print_t ahd_lastphase_print;
2047#else 2068#else
2048#define ahd_lastphase_print(regvalue, cur_col, wrap) \ 2069#define ahd_lastphase_print(regvalue, cur_col, wrap) \
2049 ahd_print_register(NULL, 0, "LASTPHASE", 0x136, regvalue, cur_col, wrap) 2070 ahd_print_register(NULL, 0, "LASTPHASE", 0x13c, regvalue, cur_col, wrap)
2050#endif 2071#endif
2051 2072
2052#if AIC_DEBUG_REGISTERS 2073#if AIC_DEBUG_REGISTERS
2053ahd_reg_print_t ahd_qoutfifo_entry_valid_tag_print; 2074ahd_reg_print_t ahd_qoutfifo_entry_valid_tag_print;
2054#else 2075#else
2055#define ahd_qoutfifo_entry_valid_tag_print(regvalue, cur_col, wrap) \ 2076#define ahd_qoutfifo_entry_valid_tag_print(regvalue, cur_col, wrap) \
2056 ahd_print_register(NULL, 0, "QOUTFIFO_ENTRY_VALID_TAG", 0x137, regvalue, cur_col, wrap) 2077 ahd_print_register(NULL, 0, "QOUTFIFO_ENTRY_VALID_TAG", 0x13d, regvalue, cur_col, wrap)
2057#endif 2078#endif
2058 2079
2059#if AIC_DEBUG_REGISTERS 2080#if AIC_DEBUG_REGISTERS
2060ahd_reg_print_t ahd_shared_data_addr_print; 2081ahd_reg_print_t ahd_kernel_tqinpos_print;
2061#else 2082#else
2062#define ahd_shared_data_addr_print(regvalue, cur_col, wrap) \ 2083#define ahd_kernel_tqinpos_print(regvalue, cur_col, wrap) \
2063 ahd_print_register(NULL, 0, "SHARED_DATA_ADDR", 0x138, regvalue, cur_col, wrap) 2084 ahd_print_register(NULL, 0, "KERNEL_TQINPOS", 0x13e, regvalue, cur_col, wrap)
2064#endif 2085#endif
2065 2086
2066#if AIC_DEBUG_REGISTERS 2087#if AIC_DEBUG_REGISTERS
2067ahd_reg_print_t ahd_qoutfifo_next_addr_print; 2088ahd_reg_print_t ahd_tqinpos_print;
2068#else 2089#else
2069#define ahd_qoutfifo_next_addr_print(regvalue, cur_col, wrap) \ 2090#define ahd_tqinpos_print(regvalue, cur_col, wrap) \
2070 ahd_print_register(NULL, 0, "QOUTFIFO_NEXT_ADDR", 0x13c, regvalue, cur_col, wrap) 2091 ahd_print_register(NULL, 0, "TQINPOS", 0x13f, regvalue, cur_col, wrap)
2071#endif 2092#endif
2072 2093
2073#if AIC_DEBUG_REGISTERS 2094#if AIC_DEBUG_REGISTERS
2074ahd_reg_print_t ahd_kernel_tqinpos_print; 2095ahd_reg_print_t ahd_shared_data_addr_print;
2075#else 2096#else
2076#define ahd_kernel_tqinpos_print(regvalue, cur_col, wrap) \ 2097#define ahd_shared_data_addr_print(regvalue, cur_col, wrap) \
2077 ahd_print_register(NULL, 0, "KERNEL_TQINPOS", 0x140, regvalue, cur_col, wrap) 2098 ahd_print_register(NULL, 0, "SHARED_DATA_ADDR", 0x140, regvalue, cur_col, wrap)
2078#endif 2099#endif
2079 2100
2080#if AIC_DEBUG_REGISTERS 2101#if AIC_DEBUG_REGISTERS
2081ahd_reg_print_t ahd_tqinpos_print; 2102ahd_reg_print_t ahd_qoutfifo_next_addr_print;
2082#else 2103#else
2083#define ahd_tqinpos_print(regvalue, cur_col, wrap) \ 2104#define ahd_qoutfifo_next_addr_print(regvalue, cur_col, wrap) \
2084 ahd_print_register(NULL, 0, "TQINPOS", 0x141, regvalue, cur_col, wrap) 2105 ahd_print_register(NULL, 0, "QOUTFIFO_NEXT_ADDR", 0x144, regvalue, cur_col, wrap)
2085#endif 2106#endif
2086 2107
2087#if AIC_DEBUG_REGISTERS 2108#if AIC_DEBUG_REGISTERS
2088ahd_reg_print_t ahd_arg_1_print; 2109ahd_reg_print_t ahd_arg_1_print;
2089#else 2110#else
2090#define ahd_arg_1_print(regvalue, cur_col, wrap) \ 2111#define ahd_arg_1_print(regvalue, cur_col, wrap) \
2091 ahd_print_register(NULL, 0, "ARG_1", 0x142, regvalue, cur_col, wrap) 2112 ahd_print_register(NULL, 0, "ARG_1", 0x148, regvalue, cur_col, wrap)
2092#endif 2113#endif
2093 2114
2094#if AIC_DEBUG_REGISTERS 2115#if AIC_DEBUG_REGISTERS
2095ahd_reg_print_t ahd_arg_2_print; 2116ahd_reg_print_t ahd_arg_2_print;
2096#else 2117#else
2097#define ahd_arg_2_print(regvalue, cur_col, wrap) \ 2118#define ahd_arg_2_print(regvalue, cur_col, wrap) \
2098 ahd_print_register(NULL, 0, "ARG_2", 0x143, regvalue, cur_col, wrap) 2119 ahd_print_register(NULL, 0, "ARG_2", 0x149, regvalue, cur_col, wrap)
2099#endif 2120#endif
2100 2121
2101#if AIC_DEBUG_REGISTERS 2122#if AIC_DEBUG_REGISTERS
2102ahd_reg_print_t ahd_last_msg_print; 2123ahd_reg_print_t ahd_last_msg_print;
2103#else 2124#else
2104#define ahd_last_msg_print(regvalue, cur_col, wrap) \ 2125#define ahd_last_msg_print(regvalue, cur_col, wrap) \
2105 ahd_print_register(NULL, 0, "LAST_MSG", 0x144, regvalue, cur_col, wrap) 2126 ahd_print_register(NULL, 0, "LAST_MSG", 0x14a, regvalue, cur_col, wrap)
2106#endif 2127#endif
2107 2128
2108#if AIC_DEBUG_REGISTERS 2129#if AIC_DEBUG_REGISTERS
2109ahd_reg_print_t ahd_scsiseq_template_print; 2130ahd_reg_print_t ahd_scsiseq_template_print;
2110#else 2131#else
2111#define ahd_scsiseq_template_print(regvalue, cur_col, wrap) \ 2132#define ahd_scsiseq_template_print(regvalue, cur_col, wrap) \
2112 ahd_print_register(NULL, 0, "SCSISEQ_TEMPLATE", 0x145, regvalue, cur_col, wrap) 2133 ahd_print_register(NULL, 0, "SCSISEQ_TEMPLATE", 0x14b, regvalue, cur_col, wrap)
2113#endif 2134#endif
2114 2135
2115#if AIC_DEBUG_REGISTERS 2136#if AIC_DEBUG_REGISTERS
2116ahd_reg_print_t ahd_initiator_tag_print; 2137ahd_reg_print_t ahd_initiator_tag_print;
2117#else 2138#else
2118#define ahd_initiator_tag_print(regvalue, cur_col, wrap) \ 2139#define ahd_initiator_tag_print(regvalue, cur_col, wrap) \
2119 ahd_print_register(NULL, 0, "INITIATOR_TAG", 0x146, regvalue, cur_col, wrap) 2140 ahd_print_register(NULL, 0, "INITIATOR_TAG", 0x14c, regvalue, cur_col, wrap)
2120#endif 2141#endif
2121 2142
2122#if AIC_DEBUG_REGISTERS 2143#if AIC_DEBUG_REGISTERS
2123ahd_reg_print_t ahd_seq_flags2_print; 2144ahd_reg_print_t ahd_seq_flags2_print;
2124#else 2145#else
2125#define ahd_seq_flags2_print(regvalue, cur_col, wrap) \ 2146#define ahd_seq_flags2_print(regvalue, cur_col, wrap) \
2126 ahd_print_register(NULL, 0, "SEQ_FLAGS2", 0x147, regvalue, cur_col, wrap) 2147 ahd_print_register(NULL, 0, "SEQ_FLAGS2", 0x14d, regvalue, cur_col, wrap)
2127#endif 2148#endif
2128 2149
2129#if AIC_DEBUG_REGISTERS 2150#if AIC_DEBUG_REGISTERS
2130ahd_reg_print_t ahd_allocfifo_scbptr_print; 2151ahd_reg_print_t ahd_allocfifo_scbptr_print;
2131#else 2152#else
2132#define ahd_allocfifo_scbptr_print(regvalue, cur_col, wrap) \ 2153#define ahd_allocfifo_scbptr_print(regvalue, cur_col, wrap) \
2133 ahd_print_register(NULL, 0, "ALLOCFIFO_SCBPTR", 0x148, regvalue, cur_col, wrap) 2154 ahd_print_register(NULL, 0, "ALLOCFIFO_SCBPTR", 0x14e, regvalue, cur_col, wrap)
2134#endif 2155#endif
2135 2156
2136#if AIC_DEBUG_REGISTERS 2157#if AIC_DEBUG_REGISTERS
2137ahd_reg_print_t ahd_int_coalescing_timer_print; 2158ahd_reg_print_t ahd_int_coalescing_timer_print;
2138#else 2159#else
2139#define ahd_int_coalescing_timer_print(regvalue, cur_col, wrap) \ 2160#define ahd_int_coalescing_timer_print(regvalue, cur_col, wrap) \
2140 ahd_print_register(NULL, 0, "INT_COALESCING_TIMER", 0x14a, regvalue, cur_col, wrap) 2161 ahd_print_register(NULL, 0, "INT_COALESCING_TIMER", 0x150, regvalue, cur_col, wrap)
2141#endif 2162#endif
2142 2163
2143#if AIC_DEBUG_REGISTERS 2164#if AIC_DEBUG_REGISTERS
2144ahd_reg_print_t ahd_int_coalescing_maxcmds_print; 2165ahd_reg_print_t ahd_int_coalescing_maxcmds_print;
2145#else 2166#else
2146#define ahd_int_coalescing_maxcmds_print(regvalue, cur_col, wrap) \ 2167#define ahd_int_coalescing_maxcmds_print(regvalue, cur_col, wrap) \
2147 ahd_print_register(NULL, 0, "INT_COALESCING_MAXCMDS", 0x14c, regvalue, cur_col, wrap) 2168 ahd_print_register(NULL, 0, "INT_COALESCING_MAXCMDS", 0x152, regvalue, cur_col, wrap)
2148#endif 2169#endif
2149 2170
2150#if AIC_DEBUG_REGISTERS 2171#if AIC_DEBUG_REGISTERS
2151ahd_reg_print_t ahd_int_coalescing_mincmds_print; 2172ahd_reg_print_t ahd_int_coalescing_mincmds_print;
2152#else 2173#else
2153#define ahd_int_coalescing_mincmds_print(regvalue, cur_col, wrap) \ 2174#define ahd_int_coalescing_mincmds_print(regvalue, cur_col, wrap) \
2154 ahd_print_register(NULL, 0, "INT_COALESCING_MINCMDS", 0x14d, regvalue, cur_col, wrap) 2175 ahd_print_register(NULL, 0, "INT_COALESCING_MINCMDS", 0x153, regvalue, cur_col, wrap)
2155#endif 2176#endif
2156 2177
2157#if AIC_DEBUG_REGISTERS 2178#if AIC_DEBUG_REGISTERS
2158ahd_reg_print_t ahd_cmds_pending_print; 2179ahd_reg_print_t ahd_cmds_pending_print;
2159#else 2180#else
2160#define ahd_cmds_pending_print(regvalue, cur_col, wrap) \ 2181#define ahd_cmds_pending_print(regvalue, cur_col, wrap) \
2161 ahd_print_register(NULL, 0, "CMDS_PENDING", 0x14e, regvalue, cur_col, wrap) 2182 ahd_print_register(NULL, 0, "CMDS_PENDING", 0x154, regvalue, cur_col, wrap)
2162#endif 2183#endif
2163 2184
2164#if AIC_DEBUG_REGISTERS 2185#if AIC_DEBUG_REGISTERS
2165ahd_reg_print_t ahd_int_coalescing_cmdcount_print; 2186ahd_reg_print_t ahd_int_coalescing_cmdcount_print;
2166#else 2187#else
2167#define ahd_int_coalescing_cmdcount_print(regvalue, cur_col, wrap) \ 2188#define ahd_int_coalescing_cmdcount_print(regvalue, cur_col, wrap) \
2168 ahd_print_register(NULL, 0, "INT_COALESCING_CMDCOUNT", 0x150, regvalue, cur_col, wrap) 2189 ahd_print_register(NULL, 0, "INT_COALESCING_CMDCOUNT", 0x156, regvalue, cur_col, wrap)
2169#endif 2190#endif
2170 2191
2171#if AIC_DEBUG_REGISTERS 2192#if AIC_DEBUG_REGISTERS
2172ahd_reg_print_t ahd_local_hs_mailbox_print; 2193ahd_reg_print_t ahd_local_hs_mailbox_print;
2173#else 2194#else
2174#define ahd_local_hs_mailbox_print(regvalue, cur_col, wrap) \ 2195#define ahd_local_hs_mailbox_print(regvalue, cur_col, wrap) \
2175 ahd_print_register(NULL, 0, "LOCAL_HS_MAILBOX", 0x151, regvalue, cur_col, wrap) 2196 ahd_print_register(NULL, 0, "LOCAL_HS_MAILBOX", 0x157, regvalue, cur_col, wrap)
2176#endif 2197#endif
2177 2198
2178#if AIC_DEBUG_REGISTERS 2199#if AIC_DEBUG_REGISTERS
2179ahd_reg_print_t ahd_cmdsize_table_print; 2200ahd_reg_print_t ahd_cmdsize_table_print;
2180#else 2201#else
2181#define ahd_cmdsize_table_print(regvalue, cur_col, wrap) \ 2202#define ahd_cmdsize_table_print(regvalue, cur_col, wrap) \
2182 ahd_print_register(NULL, 0, "CMDSIZE_TABLE", 0x152, regvalue, cur_col, wrap) 2203 ahd_print_register(NULL, 0, "CMDSIZE_TABLE", 0x158, regvalue, cur_col, wrap)
2183#endif 2204#endif
2184 2205
2185#if AIC_DEBUG_REGISTERS 2206#if AIC_DEBUG_REGISTERS
@@ -2434,13 +2455,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
2434#define HOST_TQINPOS 0x80 2455#define HOST_TQINPOS 0x80
2435#define ENINT_COALESCE 0x40 2456#define ENINT_COALESCE 0x40
2436 2457
2437#define CLRSEQINTSTAT 0x0c
2438#define CLRSEQ_SWTMRTO 0x10
2439#define CLRSEQ_SEQINT 0x08
2440#define CLRSEQ_SCSIINT 0x04
2441#define CLRSEQ_PCIINT 0x02
2442#define CLRSEQ_SPLTINT 0x01
2443
2444#define SEQINTSTAT 0x0c 2458#define SEQINTSTAT 0x0c
2445#define SEQ_SWTMRTO 0x10 2459#define SEQ_SWTMRTO 0x10
2446#define SEQ_SEQINT 0x08 2460#define SEQ_SEQINT 0x08
@@ -2448,6 +2462,13 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
2448#define SEQ_PCIINT 0x02 2462#define SEQ_PCIINT 0x02
2449#define SEQ_SPLTINT 0x01 2463#define SEQ_SPLTINT 0x01
2450 2464
2465#define CLRSEQINTSTAT 0x0c
2466#define CLRSEQ_SWTMRTO 0x10
2467#define CLRSEQ_SEQINT 0x08
2468#define CLRSEQ_SCSIINT 0x04
2469#define CLRSEQ_PCIINT 0x02
2470#define CLRSEQ_SPLTINT 0x01
2471
2451#define SWTIMER 0x0e 2472#define SWTIMER 0x0e
2452 2473
2453#define SNSCB_QOFF 0x10 2474#define SNSCB_QOFF 0x10
@@ -2623,10 +2644,10 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
2623#define BIOSCANCELEN 0x10 2644#define BIOSCANCELEN 0x10
2624#define SPIOEN 0x08 2645#define SPIOEN 0x08
2625 2646
2626#define BUSINITID 0x3c
2627
2628#define DLCOUNT 0x3c 2647#define DLCOUNT 0x3c
2629 2648
2649#define BUSINITID 0x3c
2650
2630#define SXFRCTL1 0x3d 2651#define SXFRCTL1 0x3d
2631#define BITBUCKET 0x80 2652#define BITBUCKET 0x80
2632#define ENSACHK 0x40 2653#define ENSACHK 0x40
@@ -2693,13 +2714,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
2693#define SELID_MASK 0xf0 2714#define SELID_MASK 0xf0
2694#define ONEBIT 0x08 2715#define ONEBIT 0x08
2695 2716
2696#define SBLKCTL 0x4a
2697#define DIAGLEDEN 0x80
2698#define DIAGLEDON 0x40
2699#define ENAB40 0x08
2700#define ENAB20 0x04
2701#define SELWIDE 0x02
2702
2703#define OPTIONMODE 0x4a 2717#define OPTIONMODE 0x4a
2704#define OPTIONMODE_DEFAULTS 0x02 2718#define OPTIONMODE_DEFAULTS 0x02
2705#define BIOSCANCTL 0x80 2719#define BIOSCANCTL 0x80
@@ -2709,15 +2723,12 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
2709#define ENDGFORMCHK 0x04 2723#define ENDGFORMCHK 0x04
2710#define AUTO_MSGOUT_DE 0x02 2724#define AUTO_MSGOUT_DE 0x02
2711 2725
2712#define SSTAT0 0x4b 2726#define SBLKCTL 0x4a
2713#define TARGET 0x80 2727#define DIAGLEDEN 0x80
2714#define SELDO 0x40 2728#define DIAGLEDON 0x40
2715#define SELDI 0x20 2729#define ENAB40 0x08
2716#define SELINGO 0x10 2730#define ENAB20 0x04
2717#define IOERR 0x08 2731#define SELWIDE 0x02
2718#define OVERRUN 0x04
2719#define SPIORDY 0x02
2720#define ARBDO 0x01
2721 2732
2722#define CLRSINT0 0x4b 2733#define CLRSINT0 0x4b
2723#define CLRSELDO 0x40 2734#define CLRSELDO 0x40
@@ -2728,6 +2739,16 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
2728#define CLRSPIORDY 0x02 2739#define CLRSPIORDY 0x02
2729#define CLRARBDO 0x01 2740#define CLRARBDO 0x01
2730 2741
2742#define SSTAT0 0x4b
2743#define TARGET 0x80
2744#define SELDO 0x40
2745#define SELDI 0x20
2746#define SELINGO 0x10
2747#define IOERR 0x08
2748#define OVERRUN 0x04
2749#define SPIORDY 0x02
2750#define ARBDO 0x01
2751
2731#define SIMODE0 0x4b 2752#define SIMODE0 0x4b
2732#define ENSELDO 0x40 2753#define ENSELDO 0x40
2733#define ENSELDI 0x20 2754#define ENSELDI 0x20
@@ -2768,17 +2789,17 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
2768#define BUSFREE_DFF0 0x80 2789#define BUSFREE_DFF0 0x80
2769#define BUSFREE_LQO 0x40 2790#define BUSFREE_LQO 0x40
2770 2791
2792#define SIMODE2 0x4d
2793#define ENWIDE_RES 0x04
2794#define ENSDONE 0x02
2795#define ENDMADONE 0x01
2796
2771#define CLRSINT2 0x4d 2797#define CLRSINT2 0x4d
2772#define CLRNONPACKREQ 0x20 2798#define CLRNONPACKREQ 0x20
2773#define CLRWIDE_RES 0x04 2799#define CLRWIDE_RES 0x04
2774#define CLRSDONE 0x02 2800#define CLRSDONE 0x02
2775#define CLRDMADONE 0x01 2801#define CLRDMADONE 0x01
2776 2802
2777#define SIMODE2 0x4d
2778#define ENWIDE_RES 0x04
2779#define ENSDONE 0x02
2780#define ENDMADONE 0x01
2781
2782#define PERRDIAG 0x4e 2803#define PERRDIAG 0x4e
2783#define HIZERO 0x80 2804#define HIZERO 0x80
2784#define HIPERR 0x40 2805#define HIPERR 0x40
@@ -2871,13 +2892,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
2871#define CLRNTRAMPERR 0x02 2892#define CLRNTRAMPERR 0x02
2872#define CLROSRAMPERR 0x01 2893#define CLROSRAMPERR 0x01
2873 2894
2874#define LQOMODE0 0x54
2875#define ENLQOTARGSCBPERR 0x10
2876#define ENLQOSTOPT2 0x08
2877#define ENLQOATNLQ 0x04
2878#define ENLQOATNPKT 0x02
2879#define ENLQOTCRC 0x01
2880
2881#define LQOSTAT0 0x54 2895#define LQOSTAT0 0x54
2882#define LQOTARGSCBPERR 0x10 2896#define LQOTARGSCBPERR 0x10
2883#define LQOSTOPT2 0x08 2897#define LQOSTOPT2 0x08
@@ -2892,6 +2906,20 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
2892#define CLRLQOATNPKT 0x02 2906#define CLRLQOATNPKT 0x02
2893#define CLRLQOTCRC 0x01 2907#define CLRLQOTCRC 0x01
2894 2908
2909#define LQOMODE0 0x54
2910#define ENLQOTARGSCBPERR 0x10
2911#define ENLQOSTOPT2 0x08
2912#define ENLQOATNLQ 0x04
2913#define ENLQOATNPKT 0x02
2914#define ENLQOTCRC 0x01
2915
2916#define LQOMODE1 0x55
2917#define ENLQOINITSCBPERR 0x10
2918#define ENLQOSTOPI2 0x08
2919#define ENLQOBADQAS 0x04
2920#define ENLQOBUSFREE 0x02
2921#define ENLQOPHACHGINPKT 0x01
2922
2895#define LQOSTAT1 0x55 2923#define LQOSTAT1 0x55
2896#define LQOINITSCBPERR 0x10 2924#define LQOINITSCBPERR 0x10
2897#define LQOSTOPI2 0x08 2925#define LQOSTOPI2 0x08
@@ -2906,13 +2934,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
2906#define CLRLQOBUSFREE 0x02 2934#define CLRLQOBUSFREE 0x02
2907#define CLRLQOPHACHGINPKT 0x01 2935#define CLRLQOPHACHGINPKT 0x01
2908 2936
2909#define LQOMODE1 0x55
2910#define ENLQOINITSCBPERR 0x10
2911#define ENLQOSTOPI2 0x08
2912#define ENLQOBADQAS 0x04
2913#define ENLQOBUSFREE 0x02
2914#define ENLQOPHACHGINPKT 0x01
2915
2916#define LQOSTAT2 0x56 2937#define LQOSTAT2 0x56
2917#define LQOPKT 0xe0 2938#define LQOPKT 0xe0
2918#define LQOWAITFIFO 0x10 2939#define LQOWAITFIFO 0x10
@@ -3028,6 +3049,8 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
3028 3049
3029#define ANNEXCOL 0x65 3050#define ANNEXCOL 0x65
3030 3051
3052#define ANNEXDAT 0x66
3053
3031#define SCSCHKN 0x66 3054#define SCSCHKN 0x66
3032#define STSELSKIDDIS 0x40 3055#define STSELSKIDDIS 0x40
3033#define CURRFIFODEF 0x20 3056#define CURRFIFODEF 0x20
@@ -3037,8 +3060,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
3037#define SHVALIDSTDIS 0x02 3060#define SHVALIDSTDIS 0x02
3038#define LSTSGCLRDIS 0x01 3061#define LSTSGCLRDIS 0x01
3039 3062
3040#define ANNEXDAT 0x66
3041
3042#define IOWNID 0x67 3063#define IOWNID 0x67
3043 3064
3044#define PLL960CTL0 0x68 3065#define PLL960CTL0 0x68
@@ -3071,10 +3092,10 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
3071#define PLL_CNTCLR 0x40 3092#define PLL_CNTCLR 0x40
3072#define PLL_RST 0x01 3093#define PLL_RST 0x01
3073 3094
3074#define PLL400CNT0 0x6e
3075
3076#define UNFAIRNESS 0x6e 3095#define UNFAIRNESS 0x6e
3077 3096
3097#define PLL400CNT0 0x6e
3098
3078#define HADDR 0x70 3099#define HADDR 0x70
3079 3100
3080#define PLLDELAY 0x70 3101#define PLLDELAY 0x70
@@ -3088,14 +3109,14 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
3088 3109
3089#define HODMAEN 0x7a 3110#define HODMAEN 0x7a
3090 3111
3091#define SGHADDR 0x7c
3092
3093#define SCBHADDR 0x7c 3112#define SCBHADDR 0x7c
3094 3113
3095#define SGHCNT 0x84 3114#define SGHADDR 0x7c
3096 3115
3097#define SCBHCNT 0x84 3116#define SCBHCNT 0x84
3098 3117
3118#define SGHCNT 0x84
3119
3099#define DFF_THRSH 0x88 3120#define DFF_THRSH 0x88
3100#define WR_DFTHRSH 0x70 3121#define WR_DFTHRSH 0x70
3101#define RD_DFTHRSH 0x07 3122#define RD_DFTHRSH 0x07
@@ -3113,8 +3134,8 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
3113#define RD_DFTHRSH_63 0x03 3134#define RD_DFTHRSH_63 0x03
3114#define RD_DFTHRSH_50 0x02 3135#define RD_DFTHRSH_50 0x02
3115#define RD_DFTHRSH_25 0x01 3136#define RD_DFTHRSH_25 0x01
3116#define WR_DFTHRSH_MIN 0x00
3117#define RD_DFTHRSH_MIN 0x00 3137#define RD_DFTHRSH_MIN 0x00
3138#define WR_DFTHRSH_MIN 0x00
3118 3139
3119#define ROMADDR 0x8a 3140#define ROMADDR 0x8a
3120 3141
@@ -3150,20 +3171,22 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
3150#define DCH1NSEN 0x02 3171#define DCH1NSEN 0x02
3151#define DCH0NSEN 0x01 3172#define DCH0NSEN 0x01
3152 3173
3153#define DCHRXMSG1 0x91
3154
3155#define CMCRXMSG1 0x91 3174#define CMCRXMSG1 0x91
3156 3175
3157#define DCHRXMSG2 0x92 3176#define DCHRXMSG1 0x91
3158 3177
3159#define OVLYRXMSG2 0x92 3178#define DCHRXMSG2 0x92
3160 3179
3161#define CMCRXMSG2 0x92 3180#define CMCRXMSG2 0x92
3162 3181
3163#define OST 0x92 3182#define OST 0x92
3164 3183
3184#define OVLYRXMSG2 0x92
3185
3165#define DCHRXMSG3 0x93 3186#define DCHRXMSG3 0x93
3166 3187
3188#define OVLYRXMSG3 0x93
3189
3167#define CMCRXMSG3 0x93 3190#define CMCRXMSG3 0x93
3168 3191
3169#define PCIXCTL 0x93 3192#define PCIXCTL 0x93
@@ -3175,26 +3198,24 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
3175#define TSCSERREN 0x02 3198#define TSCSERREN 0x02
3176#define CMPABCDIS 0x01 3199#define CMPABCDIS 0x01
3177 3200
3178#define OVLYRXMSG3 0x93
3179
3180#define OVLYSEQBCNT 0x94 3201#define OVLYSEQBCNT 0x94
3181 3202
3182#define CMCSEQBCNT 0x94
3183
3184#define DCHSEQBCNT 0x94 3203#define DCHSEQBCNT 0x94
3185 3204
3186#define CMCSPLTSTAT0 0x96 3205#define CMCSEQBCNT 0x94
3187 3206
3188#define OVLYSPLTSTAT0 0x96 3207#define CMCSPLTSTAT0 0x96
3189 3208
3190#define DCHSPLTSTAT0 0x96 3209#define DCHSPLTSTAT0 0x96
3191 3210
3192#define DCHSPLTSTAT1 0x97 3211#define OVLYSPLTSTAT0 0x96
3193 3212
3194#define CMCSPLTSTAT1 0x97 3213#define CMCSPLTSTAT1 0x97
3195 3214
3196#define OVLYSPLTSTAT1 0x97 3215#define OVLYSPLTSTAT1 0x97
3197 3216
3217#define DCHSPLTSTAT1 0x97
3218
3198#define SGRXMSG0 0x98 3219#define SGRXMSG0 0x98
3199#define CDNUM 0xf8 3220#define CDNUM 0xf8
3200#define CFNUM 0x07 3221#define CFNUM 0x07
@@ -3244,13 +3265,13 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
3244#define RXSCEMSG 0x02 3265#define RXSCEMSG 0x02
3245#define RXSPLTRSP 0x01 3266#define RXSPLTRSP 0x01
3246 3267
3268#define SGSPLTSTAT1 0x9f
3269#define RXDATABUCKET 0x01
3270
3247#define SFUNCT 0x9f 3271#define SFUNCT 0x9f
3248#define TEST_GROUP 0xf0 3272#define TEST_GROUP 0xf0
3249#define TEST_NUM 0x0f 3273#define TEST_NUM 0x0f
3250 3274
3251#define SGSPLTSTAT1 0x9f
3252#define RXDATABUCKET 0x01
3253
3254#define DF0PCISTAT 0xa0 3275#define DF0PCISTAT 0xa0
3255 3276
3256#define REG0 0xa0 3277#define REG0 0xa0
@@ -3299,10 +3320,10 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
3299 3320
3300#define CCSGADDR 0xac 3321#define CCSGADDR 0xac
3301 3322
3302#define CCSCBADDR 0xac
3303
3304#define CCSCBADR_BK 0xac 3323#define CCSCBADR_BK 0xac
3305 3324
3325#define CCSCBADDR 0xac
3326
3306#define CMC_RAMBIST 0xad 3327#define CMC_RAMBIST 0xad
3307#define SG_ELEMENT_SIZE 0x80 3328#define SG_ELEMENT_SIZE 0x80
3308#define SCBRAMBIST_FAIL 0x40 3329#define SCBRAMBIST_FAIL 0x40
@@ -3311,14 +3332,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
3311#define CMC_BUFFER_BIST_FAIL 0x02 3332#define CMC_BUFFER_BIST_FAIL 0x02
3312#define CMC_BUFFER_BIST_EN 0x01 3333#define CMC_BUFFER_BIST_EN 0x01
3313 3334
3314#define CCSGCTL 0xad
3315#define CCSGEN 0x0c
3316#define CCSGDONE 0x80
3317#define SG_CACHE_AVAIL 0x10
3318#define CCSGENACK 0x08
3319#define SG_FETCH_REQ 0x02
3320#define CCSGRESET 0x01
3321
3322#define CCSCBCTL 0xad 3335#define CCSCBCTL 0xad
3323#define CCSCBDONE 0x80 3336#define CCSCBDONE 0x80
3324#define ARRDONE 0x40 3337#define ARRDONE 0x40
@@ -3327,6 +3340,14 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
3327#define CCSCBDIR 0x04 3340#define CCSCBDIR 0x04
3328#define CCSCBRESET 0x01 3341#define CCSCBRESET 0x01
3329 3342
3343#define CCSGCTL 0xad
3344#define CCSGEN 0x0c
3345#define CCSGDONE 0x80
3346#define SG_CACHE_AVAIL 0x10
3347#define CCSGENACK 0x08
3348#define SG_FETCH_REQ 0x02
3349#define CCSGRESET 0x01
3350
3330#define CCSGRAM 0xb0 3351#define CCSGRAM 0xb0
3331 3352
3332#define FLEXADR 0xb0 3353#define FLEXADR 0xb0
@@ -3356,8 +3377,8 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
3356#define SEEDAT 0xbc 3377#define SEEDAT 0xbc
3357 3378
3358#define SEECTL 0xbe 3379#define SEECTL 0xbe
3359#define SEEOP_EWEN 0x40
3360#define SEEOP_WALL 0x40 3380#define SEEOP_WALL 0x40
3381#define SEEOP_EWEN 0x40
3361#define SEEOP_EWDS 0x40 3382#define SEEOP_EWDS 0x40
3362#define SEEOPCODE 0x70 3383#define SEEOPCODE 0x70
3363#define SEERST 0x02 3384#define SEERST 0x02
@@ -3414,14 +3435,14 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
3414 3435
3415#define WRTBIASCALC 0xc7 3436#define WRTBIASCALC 0xc7
3416 3437
3417#define DFPTRS 0xc8
3418
3419#define RCVRBIASCALC 0xc8 3438#define RCVRBIASCALC 0xc8
3420 3439
3421#define DFBKPTR 0xc9 3440#define DFPTRS 0xc8
3422 3441
3423#define SKEWCALC 0xc9 3442#define SKEWCALC 0xc9
3424 3443
3444#define DFBKPTR 0xc9
3445
3425#define DFDBCTL 0xcb 3446#define DFDBCTL 0xcb
3426#define DFF_CIO_WR_RDY 0x20 3447#define DFF_CIO_WR_RDY 0x20
3427#define DFF_CIO_RD_RDY 0x10 3448#define DFF_CIO_RD_RDY 0x10
@@ -3475,11 +3496,11 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
3475 3496
3476#define DINDEX 0xe4 3497#define DINDEX 0xe4
3477 3498
3499#define BRKADDR0 0xe6
3500
3478#define BRKADDR1 0xe6 3501#define BRKADDR1 0xe6
3479#define BRKDIS 0x80 3502#define BRKDIS 0x80
3480 3503
3481#define BRKADDR0 0xe6
3482
3483#define ALLONES 0xe8 3504#define ALLONES 0xe8
3484 3505
3485#define ALLZEROS 0xea 3506#define ALLZEROS 0xea
@@ -3494,14 +3515,14 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
3494 3515
3495#define STACK 0xf2 3516#define STACK 0xf2
3496 3517
3497#define CURADDR 0xf4
3498
3499#define INTVEC1_ADDR 0xf4 3518#define INTVEC1_ADDR 0xf4
3500 3519
3501#define INTVEC2_ADDR 0xf6 3520#define CURADDR 0xf4
3502 3521
3503#define LASTADDR 0xf6 3522#define LASTADDR 0xf6
3504 3523
3524#define INTVEC2_ADDR 0xf6
3525
3505#define LONGJMP_ADDR 0xf8 3526#define LONGJMP_ADDR 0xf8
3506 3527
3507#define ACCUM_SAVE 0xfa 3528#define ACCUM_SAVE 0xfa
@@ -3524,25 +3545,31 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
3524 3545
3525#define COMPLETE_DMA_SCB_HEAD 0x12c 3546#define COMPLETE_DMA_SCB_HEAD 0x12c
3526 3547
3527#define QFREEZE_COUNT 0x12e 3548#define COMPLETE_DMA_SCB_TAIL 0x12e
3549
3550#define COMPLETE_ON_QFREEZE_HEAD 0x130
3551
3552#define QFREEZE_COUNT 0x132
3528 3553
3529#define SAVED_MODE 0x130 3554#define KERNEL_QFREEZE_COUNT 0x134
3530 3555
3531#define MSG_OUT 0x131 3556#define SAVED_MODE 0x136
3532 3557
3533#define DMAPARAMS 0x132 3558#define MSG_OUT 0x137
3559
3560#define DMAPARAMS 0x138
3534#define PRELOADEN 0x80 3561#define PRELOADEN 0x80
3535#define WIDEODD 0x40 3562#define WIDEODD 0x40
3536#define SCSIEN 0x20 3563#define SCSIEN 0x20
3537#define SDMAEN 0x10 3564#define SDMAEN 0x10
3538#define SDMAENACK 0x10 3565#define SDMAENACK 0x10
3539#define HDMAENACK 0x08
3540#define HDMAEN 0x08 3566#define HDMAEN 0x08
3567#define HDMAENACK 0x08
3541#define DIRECTION 0x04 3568#define DIRECTION 0x04
3542#define FIFOFLUSH 0x02 3569#define FIFOFLUSH 0x02
3543#define FIFORESET 0x01 3570#define FIFORESET 0x01
3544 3571
3545#define SEQ_FLAGS 0x133 3572#define SEQ_FLAGS 0x139
3546#define NOT_IDENTIFIED 0x80 3573#define NOT_IDENTIFIED 0x80
3547#define NO_CDB_SENT 0x40 3574#define NO_CDB_SENT 0x40
3548#define TARGET_CMD_IS_TAGGED 0x40 3575#define TARGET_CMD_IS_TAGGED 0x40
@@ -3553,11 +3580,11 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
3553#define SPHASE_PENDING 0x02 3580#define SPHASE_PENDING 0x02
3554#define NO_DISCONNECT 0x01 3581#define NO_DISCONNECT 0x01
3555 3582
3556#define SAVED_SCSIID 0x134 3583#define SAVED_SCSIID 0x13a
3557 3584
3558#define SAVED_LUN 0x135 3585#define SAVED_LUN 0x13b
3559 3586
3560#define LASTPHASE 0x136 3587#define LASTPHASE 0x13c
3561#define PHASE_MASK 0xe0 3588#define PHASE_MASK 0xe0
3562#define CDI 0x80 3589#define CDI 0x80
3563#define IOI 0x40 3590#define IOI 0x40
@@ -3572,18 +3599,18 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
3572#define P_DATAOUT_DT 0x20 3599#define P_DATAOUT_DT 0x20
3573#define P_DATAOUT 0x00 3600#define P_DATAOUT 0x00
3574 3601
3575#define QOUTFIFO_ENTRY_VALID_TAG 0x137 3602#define QOUTFIFO_ENTRY_VALID_TAG 0x13d
3576 3603
3577#define SHARED_DATA_ADDR 0x138 3604#define KERNEL_TQINPOS 0x13e
3578 3605
3579#define QOUTFIFO_NEXT_ADDR 0x13c 3606#define TQINPOS 0x13f
3580 3607
3581#define KERNEL_TQINPOS 0x140 3608#define SHARED_DATA_ADDR 0x140
3582 3609
3583#define TQINPOS 0x141 3610#define QOUTFIFO_NEXT_ADDR 0x144
3584 3611
3585#define ARG_1 0x142 3612#define ARG_1 0x148
3586#define RETURN_1 0x142 3613#define RETURN_1 0x148
3587#define SEND_MSG 0x80 3614#define SEND_MSG 0x80
3588#define SEND_SENSE 0x40 3615#define SEND_SENSE 0x40
3589#define SEND_REJ 0x20 3616#define SEND_REJ 0x20
@@ -3593,12 +3620,12 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
3593#define CONT_MSG_LOOP_READ 0x03 3620#define CONT_MSG_LOOP_READ 0x03
3594#define CONT_MSG_LOOP_TARG 0x02 3621#define CONT_MSG_LOOP_TARG 0x02
3595 3622
3596#define ARG_2 0x143 3623#define ARG_2 0x149
3597#define RETURN_2 0x143 3624#define RETURN_2 0x149
3598 3625
3599#define LAST_MSG 0x144 3626#define LAST_MSG 0x14a
3600 3627
3601#define SCSISEQ_TEMPLATE 0x145 3628#define SCSISEQ_TEMPLATE 0x14b
3602#define MANUALCTL 0x40 3629#define MANUALCTL 0x40
3603#define ENSELI 0x20 3630#define ENSELI 0x20
3604#define ENRSELI 0x10 3631#define ENRSELI 0x10
@@ -3606,27 +3633,27 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
3606#define ENAUTOATNP 0x02 3633#define ENAUTOATNP 0x02
3607#define ALTSTIM 0x01 3634#define ALTSTIM 0x01
3608 3635
3609#define INITIATOR_TAG 0x146 3636#define INITIATOR_TAG 0x14c
3610 3637
3611#define SEQ_FLAGS2 0x147 3638#define SEQ_FLAGS2 0x14d
3612#define SELECTOUT_QFROZEN 0x04 3639#define SELECTOUT_QFROZEN 0x04
3613#define TARGET_MSG_PENDING 0x02 3640#define TARGET_MSG_PENDING 0x02
3614 3641
3615#define ALLOCFIFO_SCBPTR 0x148 3642#define ALLOCFIFO_SCBPTR 0x14e
3616 3643
3617#define INT_COALESCING_TIMER 0x14a 3644#define INT_COALESCING_TIMER 0x150
3618 3645
3619#define INT_COALESCING_MAXCMDS 0x14c 3646#define INT_COALESCING_MAXCMDS 0x152
3620 3647
3621#define INT_COALESCING_MINCMDS 0x14d 3648#define INT_COALESCING_MINCMDS 0x153
3622 3649
3623#define CMDS_PENDING 0x14e 3650#define CMDS_PENDING 0x154
3624 3651
3625#define INT_COALESCING_CMDCOUNT 0x150 3652#define INT_COALESCING_CMDCOUNT 0x156
3626 3653
3627#define LOCAL_HS_MAILBOX 0x151 3654#define LOCAL_HS_MAILBOX 0x157
3628 3655
3629#define CMDSIZE_TABLE 0x152 3656#define CMDSIZE_TABLE 0x158
3630 3657
3631#define SCB_BASE 0x180 3658#define SCB_BASE 0x180
3632 3659
@@ -3701,6 +3728,16 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
3701#define SCB_DISCONNECTED_LISTS 0x1b8 3728#define SCB_DISCONNECTED_LISTS 0x1b8
3702 3729
3703 3730
3731#define AHD_TIMER_MAX_US 0x18ffe7
3732#define AHD_TIMER_MAX_TICKS 0xffff
3733#define AHD_SENSE_BUFSIZE 0x100
3734#define BUS_8_BIT 0x00
3735#define TARGET_CMD_CMPLT 0xfe
3736#define SEEOP_WRAL_ADDR 0x40
3737#define AHD_AMPLITUDE_DEF 0x07
3738#define AHD_PRECOMP_CUTBACK_37 0x07
3739#define AHD_PRECOMP_SHIFT 0x00
3740#define AHD_ANNEXCOL_PRECOMP_SLEW 0x04
3704#define AHD_TIMER_US_PER_TICK 0x19 3741#define AHD_TIMER_US_PER_TICK 0x19
3705#define SCB_TRANSFER_SIZE_FULL_LUN 0x38 3742#define SCB_TRANSFER_SIZE_FULL_LUN 0x38
3706#define STATUS_QUEUE_FULL 0x28 3743#define STATUS_QUEUE_FULL 0x28
@@ -3724,28 +3761,18 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
3724#define B_CURRFIFO_0 0x02 3761#define B_CURRFIFO_0 0x02
3725#define LUNLEN_SINGLE_LEVEL_LUN 0x0f 3762#define LUNLEN_SINGLE_LEVEL_LUN 0x0f
3726#define NVRAM_SCB_OFFSET 0x2c 3763#define NVRAM_SCB_OFFSET 0x2c
3727#define AHD_TIMER_MAX_US 0x18ffe7
3728#define AHD_TIMER_MAX_TICKS 0xffff
3729#define STATUS_PKT_SENSE 0xff 3764#define STATUS_PKT_SENSE 0xff
3730#define CMD_GROUP_CODE_SHIFT 0x05 3765#define CMD_GROUP_CODE_SHIFT 0x05
3731#define AHD_SENSE_BUFSIZE 0x100
3732#define MAX_OFFSET_PACED_BUG 0x7f 3766#define MAX_OFFSET_PACED_BUG 0x7f
3733#define BUS_8_BIT 0x00
3734#define STIMESEL_BUG_ADJ 0x08 3767#define STIMESEL_BUG_ADJ 0x08
3735#define STIMESEL_MIN 0x18 3768#define STIMESEL_MIN 0x18
3736#define STIMESEL_SHIFT 0x03 3769#define STIMESEL_SHIFT 0x03
3737#define CCSGRAM_MAXSEGS 0x10 3770#define CCSGRAM_MAXSEGS 0x10
3738#define INVALID_ADDR 0x80 3771#define INVALID_ADDR 0x80
3739#define TARGET_CMD_CMPLT 0xfe
3740#define SEEOP_WRAL_ADDR 0x40
3741#define SEEOP_ERAL_ADDR 0x80 3772#define SEEOP_ERAL_ADDR 0x80
3742#define AHD_AMPLITUDE_DEF 0x07
3743#define AHD_SLEWRATE_DEF_REVB 0x08 3773#define AHD_SLEWRATE_DEF_REVB 0x08
3744#define AHD_PRECOMP_CUTBACK_37 0x07
3745#define AHD_PRECOMP_CUTBACK_17 0x04 3774#define AHD_PRECOMP_CUTBACK_17 0x04
3746#define AHD_PRECOMP_SHIFT 0x00
3747#define AHD_PRECOMP_MASK 0x07 3775#define AHD_PRECOMP_MASK 0x07
3748#define AHD_ANNEXCOL_PRECOMP_SLEW 0x04
3749#define SRC_MODE_SHIFT 0x00 3776#define SRC_MODE_SHIFT 0x00
3750#define PKT_OVERRUN_BUFSIZE 0x200 3777#define PKT_OVERRUN_BUFSIZE 0x200
3751#define SCB_TRANSFER_SIZE_1BYTE_LUN 0x30 3778#define SCB_TRANSFER_SIZE_1BYTE_LUN 0x30
@@ -3761,6 +3788,7 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
3761 3788
3762 3789
3763/* Downloaded Constant Definitions */ 3790/* Downloaded Constant Definitions */
3791#define CACHELINE_MASK 0x07
3764#define SCB_TRANSFER_SIZE 0x06 3792#define SCB_TRANSFER_SIZE 0x06
3765#define PKT_OVERRUN_BUFOFFSET 0x05 3793#define PKT_OVERRUN_BUFOFFSET 0x05
3766#define SG_SIZEOF 0x04 3794#define SG_SIZEOF 0x04
@@ -3768,9 +3796,9 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
3768#define SG_PREFETCH_ALIGN_MASK 0x02 3796#define SG_PREFETCH_ALIGN_MASK 0x02
3769#define SG_PREFETCH_CNT_LIMIT 0x01 3797#define SG_PREFETCH_CNT_LIMIT 0x01
3770#define SG_PREFETCH_CNT 0x00 3798#define SG_PREFETCH_CNT 0x00
3771#define DOWNLOAD_CONST_COUNT 0x07 3799#define DOWNLOAD_CONST_COUNT 0x08
3772 3800
3773 3801
3774/* Exported Labels */ 3802/* Exported Labels */
3775#define LABEL_seq_isr 0x269 3803#define LABEL_seq_isr 0x285
3776#define LABEL_timer_isr 0x265 3804#define LABEL_timer_isr 0x281
diff --git a/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped b/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped
index 3098a757e3d7..a4137c985376 100644
--- a/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped
+++ b/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped
@@ -2,8 +2,8 @@
2 * DO NOT EDIT - This file is automatically generated 2 * DO NOT EDIT - This file is automatically generated
3 * from the following source files: 3 * from the following source files:
4 * 4 *
5 * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#94 $ 5 * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#118 $
6 * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $ 6 * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#75 $
7 */ 7 */
8 8
9#include "aic79xx_osm.h" 9#include "aic79xx_osm.h"
@@ -172,21 +172,6 @@ ahd_hs_mailbox_print(u_int regvalue, u_int *cur_col, u_int wrap)
172 0x0b, regvalue, cur_col, wrap)); 172 0x0b, regvalue, cur_col, wrap));
173} 173}
174 174
175static ahd_reg_parse_entry_t CLRSEQINTSTAT_parse_table[] = {
176 { "CLRSEQ_SPLTINT", 0x01, 0x01 },
177 { "CLRSEQ_PCIINT", 0x02, 0x02 },
178 { "CLRSEQ_SCSIINT", 0x04, 0x04 },
179 { "CLRSEQ_SEQINT", 0x08, 0x08 },
180 { "CLRSEQ_SWTMRTO", 0x10, 0x10 }
181};
182
183int
184ahd_clrseqintstat_print(u_int regvalue, u_int *cur_col, u_int wrap)
185{
186 return (ahd_print_register(CLRSEQINTSTAT_parse_table, 5, "CLRSEQINTSTAT",
187 0x0c, regvalue, cur_col, wrap));
188}
189
190static ahd_reg_parse_entry_t SEQINTSTAT_parse_table[] = { 175static ahd_reg_parse_entry_t SEQINTSTAT_parse_table[] = {
191 { "SEQ_SPLTINT", 0x01, 0x01 }, 176 { "SEQ_SPLTINT", 0x01, 0x01 },
192 { "SEQ_PCIINT", 0x02, 0x02 }, 177 { "SEQ_PCIINT", 0x02, 0x02 },
@@ -202,6 +187,21 @@ ahd_seqintstat_print(u_int regvalue, u_int *cur_col, u_int wrap)
202 0x0c, regvalue, cur_col, wrap)); 187 0x0c, regvalue, cur_col, wrap));
203} 188}
204 189
190static ahd_reg_parse_entry_t CLRSEQINTSTAT_parse_table[] = {
191 { "CLRSEQ_SPLTINT", 0x01, 0x01 },
192 { "CLRSEQ_PCIINT", 0x02, 0x02 },
193 { "CLRSEQ_SCSIINT", 0x04, 0x04 },
194 { "CLRSEQ_SEQINT", 0x08, 0x08 },
195 { "CLRSEQ_SWTMRTO", 0x10, 0x10 }
196};
197
198int
199ahd_clrseqintstat_print(u_int regvalue, u_int *cur_col, u_int wrap)
200{
201 return (ahd_print_register(CLRSEQINTSTAT_parse_table, 5, "CLRSEQINTSTAT",
202 0x0c, regvalue, cur_col, wrap));
203}
204
205int 205int
206ahd_swtimer_print(u_int regvalue, u_int *cur_col, u_int wrap) 206ahd_swtimer_print(u_int regvalue, u_int *cur_col, u_int wrap)
207{ 207{
@@ -670,16 +670,16 @@ ahd_sxfrctl0_print(u_int regvalue, u_int *cur_col, u_int wrap)
670} 670}
671 671
672int 672int
673ahd_businitid_print(u_int regvalue, u_int *cur_col, u_int wrap) 673ahd_dlcount_print(u_int regvalue, u_int *cur_col, u_int wrap)
674{ 674{
675 return (ahd_print_register(NULL, 0, "BUSINITID", 675 return (ahd_print_register(NULL, 0, "DLCOUNT",
676 0x3c, regvalue, cur_col, wrap)); 676 0x3c, regvalue, cur_col, wrap));
677} 677}
678 678
679int 679int
680ahd_dlcount_print(u_int regvalue, u_int *cur_col, u_int wrap) 680ahd_businitid_print(u_int regvalue, u_int *cur_col, u_int wrap)
681{ 681{
682 return (ahd_print_register(NULL, 0, "DLCOUNT", 682 return (ahd_print_register(NULL, 0, "BUSINITID",
683 0x3c, regvalue, cur_col, wrap)); 683 0x3c, regvalue, cur_col, wrap));
684} 684}
685 685
@@ -859,21 +859,6 @@ ahd_selid_print(u_int regvalue, u_int *cur_col, u_int wrap)
859 0x49, regvalue, cur_col, wrap)); 859 0x49, regvalue, cur_col, wrap));
860} 860}
861 861
862static ahd_reg_parse_entry_t SBLKCTL_parse_table[] = {
863 { "SELWIDE", 0x02, 0x02 },
864 { "ENAB20", 0x04, 0x04 },
865 { "ENAB40", 0x08, 0x08 },
866 { "DIAGLEDON", 0x40, 0x40 },
867 { "DIAGLEDEN", 0x80, 0x80 }
868};
869
870int
871ahd_sblkctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
872{
873 return (ahd_print_register(SBLKCTL_parse_table, 5, "SBLKCTL",
874 0x4a, regvalue, cur_col, wrap));
875}
876
877static ahd_reg_parse_entry_t OPTIONMODE_parse_table[] = { 862static ahd_reg_parse_entry_t OPTIONMODE_parse_table[] = {
878 { "AUTO_MSGOUT_DE", 0x02, 0x02 }, 863 { "AUTO_MSGOUT_DE", 0x02, 0x02 },
879 { "ENDGFORMCHK", 0x04, 0x04 }, 864 { "ENDGFORMCHK", 0x04, 0x04 },
@@ -891,22 +876,19 @@ ahd_optionmode_print(u_int regvalue, u_int *cur_col, u_int wrap)
891 0x4a, regvalue, cur_col, wrap)); 876 0x4a, regvalue, cur_col, wrap));
892} 877}
893 878
894static ahd_reg_parse_entry_t SSTAT0_parse_table[] = { 879static ahd_reg_parse_entry_t SBLKCTL_parse_table[] = {
895 { "ARBDO", 0x01, 0x01 }, 880 { "SELWIDE", 0x02, 0x02 },
896 { "SPIORDY", 0x02, 0x02 }, 881 { "ENAB20", 0x04, 0x04 },
897 { "OVERRUN", 0x04, 0x04 }, 882 { "ENAB40", 0x08, 0x08 },
898 { "IOERR", 0x08, 0x08 }, 883 { "DIAGLEDON", 0x40, 0x40 },
899 { "SELINGO", 0x10, 0x10 }, 884 { "DIAGLEDEN", 0x80, 0x80 }
900 { "SELDI", 0x20, 0x20 },
901 { "SELDO", 0x40, 0x40 },
902 { "TARGET", 0x80, 0x80 }
903}; 885};
904 886
905int 887int
906ahd_sstat0_print(u_int regvalue, u_int *cur_col, u_int wrap) 888ahd_sblkctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
907{ 889{
908 return (ahd_print_register(SSTAT0_parse_table, 8, "SSTAT0", 890 return (ahd_print_register(SBLKCTL_parse_table, 5, "SBLKCTL",
909 0x4b, regvalue, cur_col, wrap)); 891 0x4a, regvalue, cur_col, wrap));
910} 892}
911 893
912static ahd_reg_parse_entry_t CLRSINT0_parse_table[] = { 894static ahd_reg_parse_entry_t CLRSINT0_parse_table[] = {
@@ -926,6 +908,24 @@ ahd_clrsint0_print(u_int regvalue, u_int *cur_col, u_int wrap)
926 0x4b, regvalue, cur_col, wrap)); 908 0x4b, regvalue, cur_col, wrap));
927} 909}
928 910
911static ahd_reg_parse_entry_t SSTAT0_parse_table[] = {
912 { "ARBDO", 0x01, 0x01 },
913 { "SPIORDY", 0x02, 0x02 },
914 { "OVERRUN", 0x04, 0x04 },
915 { "IOERR", 0x08, 0x08 },
916 { "SELINGO", 0x10, 0x10 },
917 { "SELDI", 0x20, 0x20 },
918 { "SELDO", 0x40, 0x40 },
919 { "TARGET", 0x80, 0x80 }
920};
921
922int
923ahd_sstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
924{
925 return (ahd_print_register(SSTAT0_parse_table, 8, "SSTAT0",
926 0x4b, regvalue, cur_col, wrap));
927}
928
929static ahd_reg_parse_entry_t SIMODE0_parse_table[] = { 929static ahd_reg_parse_entry_t SIMODE0_parse_table[] = {
930 { "ENARBDO", 0x01, 0x01 }, 930 { "ENARBDO", 0x01, 0x01 },
931 { "ENSPIORDY", 0x02, 0x02 }, 931 { "ENSPIORDY", 0x02, 0x02 },
@@ -998,30 +998,30 @@ ahd_sstat2_print(u_int regvalue, u_int *cur_col, u_int wrap)
998 0x4d, regvalue, cur_col, wrap)); 998 0x4d, regvalue, cur_col, wrap));
999} 999}
1000 1000
1001static ahd_reg_parse_entry_t CLRSINT2_parse_table[] = { 1001static ahd_reg_parse_entry_t SIMODE2_parse_table[] = {
1002 { "CLRDMADONE", 0x01, 0x01 }, 1002 { "ENDMADONE", 0x01, 0x01 },
1003 { "CLRSDONE", 0x02, 0x02 }, 1003 { "ENSDONE", 0x02, 0x02 },
1004 { "CLRWIDE_RES", 0x04, 0x04 }, 1004 { "ENWIDE_RES", 0x04, 0x04 }
1005 { "CLRNONPACKREQ", 0x20, 0x20 }
1006}; 1005};
1007 1006
1008int 1007int
1009ahd_clrsint2_print(u_int regvalue, u_int *cur_col, u_int wrap) 1008ahd_simode2_print(u_int regvalue, u_int *cur_col, u_int wrap)
1010{ 1009{
1011 return (ahd_print_register(CLRSINT2_parse_table, 4, "CLRSINT2", 1010 return (ahd_print_register(SIMODE2_parse_table, 3, "SIMODE2",
1012 0x4d, regvalue, cur_col, wrap)); 1011 0x4d, regvalue, cur_col, wrap));
1013} 1012}
1014 1013
1015static ahd_reg_parse_entry_t SIMODE2_parse_table[] = { 1014static ahd_reg_parse_entry_t CLRSINT2_parse_table[] = {
1016 { "ENDMADONE", 0x01, 0x01 }, 1015 { "CLRDMADONE", 0x01, 0x01 },
1017 { "ENSDONE", 0x02, 0x02 }, 1016 { "CLRSDONE", 0x02, 0x02 },
1018 { "ENWIDE_RES", 0x04, 0x04 } 1017 { "CLRWIDE_RES", 0x04, 0x04 },
1018 { "CLRNONPACKREQ", 0x20, 0x20 }
1019}; 1019};
1020 1020
1021int 1021int
1022ahd_simode2_print(u_int regvalue, u_int *cur_col, u_int wrap) 1022ahd_clrsint2_print(u_int regvalue, u_int *cur_col, u_int wrap)
1023{ 1023{
1024 return (ahd_print_register(SIMODE2_parse_table, 3, "SIMODE2", 1024 return (ahd_print_register(CLRSINT2_parse_table, 4, "CLRSINT2",
1025 0x4d, regvalue, cur_col, wrap)); 1025 0x4d, regvalue, cur_col, wrap));
1026} 1026}
1027 1027
@@ -1220,21 +1220,6 @@ ahd_clrsint3_print(u_int regvalue, u_int *cur_col, u_int wrap)
1220 0x53, regvalue, cur_col, wrap)); 1220 0x53, regvalue, cur_col, wrap));
1221} 1221}
1222 1222
1223static ahd_reg_parse_entry_t LQOMODE0_parse_table[] = {
1224 { "ENLQOTCRC", 0x01, 0x01 },
1225 { "ENLQOATNPKT", 0x02, 0x02 },
1226 { "ENLQOATNLQ", 0x04, 0x04 },
1227 { "ENLQOSTOPT2", 0x08, 0x08 },
1228 { "ENLQOTARGSCBPERR", 0x10, 0x10 }
1229};
1230
1231int
1232ahd_lqomode0_print(u_int regvalue, u_int *cur_col, u_int wrap)
1233{
1234 return (ahd_print_register(LQOMODE0_parse_table, 5, "LQOMODE0",
1235 0x54, regvalue, cur_col, wrap));
1236}
1237
1238static ahd_reg_parse_entry_t LQOSTAT0_parse_table[] = { 1223static ahd_reg_parse_entry_t LQOSTAT0_parse_table[] = {
1239 { "LQOTCRC", 0x01, 0x01 }, 1224 { "LQOTCRC", 0x01, 0x01 },
1240 { "LQOATNPKT", 0x02, 0x02 }, 1225 { "LQOATNPKT", 0x02, 0x02 },
@@ -1265,6 +1250,36 @@ ahd_clrlqoint0_print(u_int regvalue, u_int *cur_col, u_int wrap)
1265 0x54, regvalue, cur_col, wrap)); 1250 0x54, regvalue, cur_col, wrap));
1266} 1251}
1267 1252
1253static ahd_reg_parse_entry_t LQOMODE0_parse_table[] = {
1254 { "ENLQOTCRC", 0x01, 0x01 },
1255 { "ENLQOATNPKT", 0x02, 0x02 },
1256 { "ENLQOATNLQ", 0x04, 0x04 },
1257 { "ENLQOSTOPT2", 0x08, 0x08 },
1258 { "ENLQOTARGSCBPERR", 0x10, 0x10 }
1259};
1260
1261int
1262ahd_lqomode0_print(u_int regvalue, u_int *cur_col, u_int wrap)
1263{
1264 return (ahd_print_register(LQOMODE0_parse_table, 5, "LQOMODE0",
1265 0x54, regvalue, cur_col, wrap));
1266}
1267
1268static ahd_reg_parse_entry_t LQOMODE1_parse_table[] = {
1269 { "ENLQOPHACHGINPKT", 0x01, 0x01 },
1270 { "ENLQOBUSFREE", 0x02, 0x02 },
1271 { "ENLQOBADQAS", 0x04, 0x04 },
1272 { "ENLQOSTOPI2", 0x08, 0x08 },
1273 { "ENLQOINITSCBPERR", 0x10, 0x10 }
1274};
1275
1276int
1277ahd_lqomode1_print(u_int regvalue, u_int *cur_col, u_int wrap)
1278{
1279 return (ahd_print_register(LQOMODE1_parse_table, 5, "LQOMODE1",
1280 0x55, regvalue, cur_col, wrap));
1281}
1282
1268static ahd_reg_parse_entry_t LQOSTAT1_parse_table[] = { 1283static ahd_reg_parse_entry_t LQOSTAT1_parse_table[] = {
1269 { "LQOPHACHGINPKT", 0x01, 0x01 }, 1284 { "LQOPHACHGINPKT", 0x01, 0x01 },
1270 { "LQOBUSFREE", 0x02, 0x02 }, 1285 { "LQOBUSFREE", 0x02, 0x02 },
@@ -1295,21 +1310,6 @@ ahd_clrlqoint1_print(u_int regvalue, u_int *cur_col, u_int wrap)
1295 0x55, regvalue, cur_col, wrap)); 1310 0x55, regvalue, cur_col, wrap));
1296} 1311}
1297 1312
1298static ahd_reg_parse_entry_t LQOMODE1_parse_table[] = {
1299 { "ENLQOPHACHGINPKT", 0x01, 0x01 },
1300 { "ENLQOBUSFREE", 0x02, 0x02 },
1301 { "ENLQOBADQAS", 0x04, 0x04 },
1302 { "ENLQOSTOPI2", 0x08, 0x08 },
1303 { "ENLQOINITSCBPERR", 0x10, 0x10 }
1304};
1305
1306int
1307ahd_lqomode1_print(u_int regvalue, u_int *cur_col, u_int wrap)
1308{
1309 return (ahd_print_register(LQOMODE1_parse_table, 5, "LQOMODE1",
1310 0x55, regvalue, cur_col, wrap));
1311}
1312
1313static ahd_reg_parse_entry_t LQOSTAT2_parse_table[] = { 1313static ahd_reg_parse_entry_t LQOSTAT2_parse_table[] = {
1314 { "LQOSTOP0", 0x01, 0x01 }, 1314 { "LQOSTOP0", 0x01, 0x01 },
1315 { "LQOPHACHGOUTPKT", 0x02, 0x02 }, 1315 { "LQOPHACHGOUTPKT", 0x02, 0x02 },
@@ -1594,6 +1594,13 @@ ahd_annexcol_print(u_int regvalue, u_int *cur_col, u_int wrap)
1594 0x65, regvalue, cur_col, wrap)); 1594 0x65, regvalue, cur_col, wrap));
1595} 1595}
1596 1596
1597int
1598ahd_annexdat_print(u_int regvalue, u_int *cur_col, u_int wrap)
1599{
1600 return (ahd_print_register(NULL, 0, "ANNEXDAT",
1601 0x66, regvalue, cur_col, wrap));
1602}
1603
1597static ahd_reg_parse_entry_t SCSCHKN_parse_table[] = { 1604static ahd_reg_parse_entry_t SCSCHKN_parse_table[] = {
1598 { "LSTSGCLRDIS", 0x01, 0x01 }, 1605 { "LSTSGCLRDIS", 0x01, 0x01 },
1599 { "SHVALIDSTDIS", 0x02, 0x02 }, 1606 { "SHVALIDSTDIS", 0x02, 0x02 },
@@ -1612,13 +1619,6 @@ ahd_scschkn_print(u_int regvalue, u_int *cur_col, u_int wrap)
1612} 1619}
1613 1620
1614int 1621int
1615ahd_annexdat_print(u_int regvalue, u_int *cur_col, u_int wrap)
1616{
1617 return (ahd_print_register(NULL, 0, "ANNEXDAT",
1618 0x66, regvalue, cur_col, wrap));
1619}
1620
1621int
1622ahd_iownid_print(u_int regvalue, u_int *cur_col, u_int wrap) 1622ahd_iownid_print(u_int regvalue, u_int *cur_col, u_int wrap)
1623{ 1623{
1624 return (ahd_print_register(NULL, 0, "IOWNID", 1624 return (ahd_print_register(NULL, 0, "IOWNID",
@@ -1728,16 +1728,16 @@ ahd_pll400ctl1_print(u_int regvalue, u_int *cur_col, u_int wrap)
1728} 1728}
1729 1729
1730int 1730int
1731ahd_pll400cnt0_print(u_int regvalue, u_int *cur_col, u_int wrap) 1731ahd_unfairness_print(u_int regvalue, u_int *cur_col, u_int wrap)
1732{ 1732{
1733 return (ahd_print_register(NULL, 0, "PLL400CNT0", 1733 return (ahd_print_register(NULL, 0, "UNFAIRNESS",
1734 0x6e, regvalue, cur_col, wrap)); 1734 0x6e, regvalue, cur_col, wrap));
1735} 1735}
1736 1736
1737int 1737int
1738ahd_unfairness_print(u_int regvalue, u_int *cur_col, u_int wrap) 1738ahd_pll400cnt0_print(u_int regvalue, u_int *cur_col, u_int wrap)
1739{ 1739{
1740 return (ahd_print_register(NULL, 0, "UNFAIRNESS", 1740 return (ahd_print_register(NULL, 0, "PLL400CNT0",
1741 0x6e, regvalue, cur_col, wrap)); 1741 0x6e, regvalue, cur_col, wrap));
1742} 1742}
1743 1743
@@ -1788,30 +1788,30 @@ ahd_hodmaen_print(u_int regvalue, u_int *cur_col, u_int wrap)
1788} 1788}
1789 1789
1790int 1790int
1791ahd_sghaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) 1791ahd_scbhaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
1792{ 1792{
1793 return (ahd_print_register(NULL, 0, "SGHADDR", 1793 return (ahd_print_register(NULL, 0, "SCBHADDR",
1794 0x7c, regvalue, cur_col, wrap)); 1794 0x7c, regvalue, cur_col, wrap));
1795} 1795}
1796 1796
1797int 1797int
1798ahd_scbhaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) 1798ahd_sghaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
1799{ 1799{
1800 return (ahd_print_register(NULL, 0, "SCBHADDR", 1800 return (ahd_print_register(NULL, 0, "SGHADDR",
1801 0x7c, regvalue, cur_col, wrap)); 1801 0x7c, regvalue, cur_col, wrap));
1802} 1802}
1803 1803
1804int 1804int
1805ahd_sghcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) 1805ahd_scbhcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
1806{ 1806{
1807 return (ahd_print_register(NULL, 0, "SGHCNT", 1807 return (ahd_print_register(NULL, 0, "SCBHCNT",
1808 0x84, regvalue, cur_col, wrap)); 1808 0x84, regvalue, cur_col, wrap));
1809} 1809}
1810 1810
1811int 1811int
1812ahd_scbhcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) 1812ahd_sghcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
1813{ 1813{
1814 return (ahd_print_register(NULL, 0, "SCBHCNT", 1814 return (ahd_print_register(NULL, 0, "SGHCNT",
1815 0x84, regvalue, cur_col, wrap)); 1815 0x84, regvalue, cur_col, wrap));
1816} 1816}
1817 1817
@@ -1950,25 +1950,25 @@ ahd_nsenable_print(u_int regvalue, u_int *cur_col, u_int wrap)
1950 0x91, regvalue, cur_col, wrap)); 1950 0x91, regvalue, cur_col, wrap));
1951} 1951}
1952 1952
1953static ahd_reg_parse_entry_t DCHRXMSG1_parse_table[] = { 1953static ahd_reg_parse_entry_t CMCRXMSG1_parse_table[] = {
1954 { "CBNUM", 0xff, 0xff } 1954 { "CBNUM", 0xff, 0xff }
1955}; 1955};
1956 1956
1957int 1957int
1958ahd_dchrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap) 1958ahd_cmcrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap)
1959{ 1959{
1960 return (ahd_print_register(DCHRXMSG1_parse_table, 1, "DCHRXMSG1", 1960 return (ahd_print_register(CMCRXMSG1_parse_table, 1, "CMCRXMSG1",
1961 0x91, regvalue, cur_col, wrap)); 1961 0x91, regvalue, cur_col, wrap));
1962} 1962}
1963 1963
1964static ahd_reg_parse_entry_t CMCRXMSG1_parse_table[] = { 1964static ahd_reg_parse_entry_t DCHRXMSG1_parse_table[] = {
1965 { "CBNUM", 0xff, 0xff } 1965 { "CBNUM", 0xff, 0xff }
1966}; 1966};
1967 1967
1968int 1968int
1969ahd_cmcrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap) 1969ahd_dchrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap)
1970{ 1970{
1971 return (ahd_print_register(CMCRXMSG1_parse_table, 1, "CMCRXMSG1", 1971 return (ahd_print_register(DCHRXMSG1_parse_table, 1, "DCHRXMSG1",
1972 0x91, regvalue, cur_col, wrap)); 1972 0x91, regvalue, cur_col, wrap));
1973} 1973}
1974 1974
@@ -1983,17 +1983,6 @@ ahd_dchrxmsg2_print(u_int regvalue, u_int *cur_col, u_int wrap)
1983 0x92, regvalue, cur_col, wrap)); 1983 0x92, regvalue, cur_col, wrap));
1984} 1984}
1985 1985
1986static ahd_reg_parse_entry_t OVLYRXMSG2_parse_table[] = {
1987 { "MINDEX", 0xff, 0xff }
1988};
1989
1990int
1991ahd_ovlyrxmsg2_print(u_int regvalue, u_int *cur_col, u_int wrap)
1992{
1993 return (ahd_print_register(OVLYRXMSG2_parse_table, 1, "OVLYRXMSG2",
1994 0x92, regvalue, cur_col, wrap));
1995}
1996
1997static ahd_reg_parse_entry_t CMCRXMSG2_parse_table[] = { 1986static ahd_reg_parse_entry_t CMCRXMSG2_parse_table[] = {
1998 { "MINDEX", 0xff, 0xff } 1987 { "MINDEX", 0xff, 0xff }
1999}; 1988};
@@ -2012,6 +2001,17 @@ ahd_ost_print(u_int regvalue, u_int *cur_col, u_int wrap)
2012 0x92, regvalue, cur_col, wrap)); 2001 0x92, regvalue, cur_col, wrap));
2013} 2002}
2014 2003
2004static ahd_reg_parse_entry_t OVLYRXMSG2_parse_table[] = {
2005 { "MINDEX", 0xff, 0xff }
2006};
2007
2008int
2009ahd_ovlyrxmsg2_print(u_int regvalue, u_int *cur_col, u_int wrap)
2010{
2011 return (ahd_print_register(OVLYRXMSG2_parse_table, 1, "OVLYRXMSG2",
2012 0x92, regvalue, cur_col, wrap));
2013}
2014
2015static ahd_reg_parse_entry_t DCHRXMSG3_parse_table[] = { 2015static ahd_reg_parse_entry_t DCHRXMSG3_parse_table[] = {
2016 { "MCLASS", 0x0f, 0x0f } 2016 { "MCLASS", 0x0f, 0x0f }
2017}; 2017};
@@ -2023,6 +2023,17 @@ ahd_dchrxmsg3_print(u_int regvalue, u_int *cur_col, u_int wrap)
2023 0x93, regvalue, cur_col, wrap)); 2023 0x93, regvalue, cur_col, wrap));
2024} 2024}
2025 2025
2026static ahd_reg_parse_entry_t OVLYRXMSG3_parse_table[] = {
2027 { "MCLASS", 0x0f, 0x0f }
2028};
2029
2030int
2031ahd_ovlyrxmsg3_print(u_int regvalue, u_int *cur_col, u_int wrap)
2032{
2033 return (ahd_print_register(OVLYRXMSG3_parse_table, 1, "OVLYRXMSG3",
2034 0x93, regvalue, cur_col, wrap));
2035}
2036
2026static ahd_reg_parse_entry_t CMCRXMSG3_parse_table[] = { 2037static ahd_reg_parse_entry_t CMCRXMSG3_parse_table[] = {
2027 { "MCLASS", 0x0f, 0x0f } 2038 { "MCLASS", 0x0f, 0x0f }
2028}; 2039};
@@ -2051,17 +2062,6 @@ ahd_pcixctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
2051 0x93, regvalue, cur_col, wrap)); 2062 0x93, regvalue, cur_col, wrap));
2052} 2063}
2053 2064
2054static ahd_reg_parse_entry_t OVLYRXMSG3_parse_table[] = {
2055 { "MCLASS", 0x0f, 0x0f }
2056};
2057
2058int
2059ahd_ovlyrxmsg3_print(u_int regvalue, u_int *cur_col, u_int wrap)
2060{
2061 return (ahd_print_register(OVLYRXMSG3_parse_table, 1, "OVLYRXMSG3",
2062 0x93, regvalue, cur_col, wrap));
2063}
2064
2065int 2065int
2066ahd_ovlyseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) 2066ahd_ovlyseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
2067{ 2067{
@@ -2070,16 +2070,16 @@ ahd_ovlyseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
2070} 2070}
2071 2071
2072int 2072int
2073ahd_cmcseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) 2073ahd_dchseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
2074{ 2074{
2075 return (ahd_print_register(NULL, 0, "CMCSEQBCNT", 2075 return (ahd_print_register(NULL, 0, "DCHSEQBCNT",
2076 0x94, regvalue, cur_col, wrap)); 2076 0x94, regvalue, cur_col, wrap));
2077} 2077}
2078 2078
2079int 2079int
2080ahd_dchseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) 2080ahd_cmcseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
2081{ 2081{
2082 return (ahd_print_register(NULL, 0, "DCHSEQBCNT", 2082 return (ahd_print_register(NULL, 0, "CMCSEQBCNT",
2083 0x94, regvalue, cur_col, wrap)); 2083 0x94, regvalue, cur_col, wrap));
2084} 2084}
2085 2085
@@ -2101,7 +2101,7 @@ ahd_cmcspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
2101 0x96, regvalue, cur_col, wrap)); 2101 0x96, regvalue, cur_col, wrap));
2102} 2102}
2103 2103
2104static ahd_reg_parse_entry_t OVLYSPLTSTAT0_parse_table[] = { 2104static ahd_reg_parse_entry_t DCHSPLTSTAT0_parse_table[] = {
2105 { "RXSPLTRSP", 0x01, 0x01 }, 2105 { "RXSPLTRSP", 0x01, 0x01 },
2106 { "RXSCEMSG", 0x02, 0x02 }, 2106 { "RXSCEMSG", 0x02, 0x02 },
2107 { "RXOVRUN", 0x04, 0x04 }, 2107 { "RXOVRUN", 0x04, 0x04 },
@@ -2113,13 +2113,13 @@ static ahd_reg_parse_entry_t OVLYSPLTSTAT0_parse_table[] = {
2113}; 2113};
2114 2114
2115int 2115int
2116ahd_ovlyspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap) 2116ahd_dchspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
2117{ 2117{
2118 return (ahd_print_register(OVLYSPLTSTAT0_parse_table, 8, "OVLYSPLTSTAT0", 2118 return (ahd_print_register(DCHSPLTSTAT0_parse_table, 8, "DCHSPLTSTAT0",
2119 0x96, regvalue, cur_col, wrap)); 2119 0x96, regvalue, cur_col, wrap));
2120} 2120}
2121 2121
2122static ahd_reg_parse_entry_t DCHSPLTSTAT0_parse_table[] = { 2122static ahd_reg_parse_entry_t OVLYSPLTSTAT0_parse_table[] = {
2123 { "RXSPLTRSP", 0x01, 0x01 }, 2123 { "RXSPLTRSP", 0x01, 0x01 },
2124 { "RXSCEMSG", 0x02, 0x02 }, 2124 { "RXSCEMSG", 0x02, 0x02 },
2125 { "RXOVRUN", 0x04, 0x04 }, 2125 { "RXOVRUN", 0x04, 0x04 },
@@ -2131,42 +2131,42 @@ static ahd_reg_parse_entry_t DCHSPLTSTAT0_parse_table[] = {
2131}; 2131};
2132 2132
2133int 2133int
2134ahd_dchspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap) 2134ahd_ovlyspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
2135{ 2135{
2136 return (ahd_print_register(DCHSPLTSTAT0_parse_table, 8, "DCHSPLTSTAT0", 2136 return (ahd_print_register(OVLYSPLTSTAT0_parse_table, 8, "OVLYSPLTSTAT0",
2137 0x96, regvalue, cur_col, wrap)); 2137 0x96, regvalue, cur_col, wrap));
2138} 2138}
2139 2139
2140static ahd_reg_parse_entry_t DCHSPLTSTAT1_parse_table[] = { 2140static ahd_reg_parse_entry_t CMCSPLTSTAT1_parse_table[] = {
2141 { "RXDATABUCKET", 0x01, 0x01 } 2141 { "RXDATABUCKET", 0x01, 0x01 }
2142}; 2142};
2143 2143
2144int 2144int
2145ahd_dchspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) 2145ahd_cmcspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
2146{ 2146{
2147 return (ahd_print_register(DCHSPLTSTAT1_parse_table, 1, "DCHSPLTSTAT1", 2147 return (ahd_print_register(CMCSPLTSTAT1_parse_table, 1, "CMCSPLTSTAT1",
2148 0x97, regvalue, cur_col, wrap)); 2148 0x97, regvalue, cur_col, wrap));
2149} 2149}
2150 2150
2151static ahd_reg_parse_entry_t CMCSPLTSTAT1_parse_table[] = { 2151static ahd_reg_parse_entry_t OVLYSPLTSTAT1_parse_table[] = {
2152 { "RXDATABUCKET", 0x01, 0x01 } 2152 { "RXDATABUCKET", 0x01, 0x01 }
2153}; 2153};
2154 2154
2155int 2155int
2156ahd_cmcspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) 2156ahd_ovlyspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
2157{ 2157{
2158 return (ahd_print_register(CMCSPLTSTAT1_parse_table, 1, "CMCSPLTSTAT1", 2158 return (ahd_print_register(OVLYSPLTSTAT1_parse_table, 1, "OVLYSPLTSTAT1",
2159 0x97, regvalue, cur_col, wrap)); 2159 0x97, regvalue, cur_col, wrap));
2160} 2160}
2161 2161
2162static ahd_reg_parse_entry_t OVLYSPLTSTAT1_parse_table[] = { 2162static ahd_reg_parse_entry_t DCHSPLTSTAT1_parse_table[] = {
2163 { "RXDATABUCKET", 0x01, 0x01 } 2163 { "RXDATABUCKET", 0x01, 0x01 }
2164}; 2164};
2165 2165
2166int 2166int
2167ahd_ovlyspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) 2167ahd_dchspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
2168{ 2168{
2169 return (ahd_print_register(OVLYSPLTSTAT1_parse_table, 1, "OVLYSPLTSTAT1", 2169 return (ahd_print_register(DCHSPLTSTAT1_parse_table, 1, "DCHSPLTSTAT1",
2170 0x97, regvalue, cur_col, wrap)); 2170 0x97, regvalue, cur_col, wrap));
2171} 2171}
2172 2172
@@ -2320,26 +2320,26 @@ ahd_sgspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
2320 0x9e, regvalue, cur_col, wrap)); 2320 0x9e, regvalue, cur_col, wrap));
2321} 2321}
2322 2322
2323static ahd_reg_parse_entry_t SFUNCT_parse_table[] = { 2323static ahd_reg_parse_entry_t SGSPLTSTAT1_parse_table[] = {
2324 { "TEST_NUM", 0x0f, 0x0f }, 2324 { "RXDATABUCKET", 0x01, 0x01 }
2325 { "TEST_GROUP", 0xf0, 0xf0 }
2326}; 2325};
2327 2326
2328int 2327int
2329ahd_sfunct_print(u_int regvalue, u_int *cur_col, u_int wrap) 2328ahd_sgspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
2330{ 2329{
2331 return (ahd_print_register(SFUNCT_parse_table, 2, "SFUNCT", 2330 return (ahd_print_register(SGSPLTSTAT1_parse_table, 1, "SGSPLTSTAT1",
2332 0x9f, regvalue, cur_col, wrap)); 2331 0x9f, regvalue, cur_col, wrap));
2333} 2332}
2334 2333
2335static ahd_reg_parse_entry_t SGSPLTSTAT1_parse_table[] = { 2334static ahd_reg_parse_entry_t SFUNCT_parse_table[] = {
2336 { "RXDATABUCKET", 0x01, 0x01 } 2335 { "TEST_NUM", 0x0f, 0x0f },
2336 { "TEST_GROUP", 0xf0, 0xf0 }
2337}; 2337};
2338 2338
2339int 2339int
2340ahd_sgspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) 2340ahd_sfunct_print(u_int regvalue, u_int *cur_col, u_int wrap)
2341{ 2341{
2342 return (ahd_print_register(SGSPLTSTAT1_parse_table, 1, "SGSPLTSTAT1", 2342 return (ahd_print_register(SFUNCT_parse_table, 2, "SFUNCT",
2343 0x9f, regvalue, cur_col, wrap)); 2343 0x9f, regvalue, cur_col, wrap));
2344} 2344}
2345 2345
@@ -2537,16 +2537,16 @@ ahd_ccsgaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
2537} 2537}
2538 2538
2539int 2539int
2540ahd_ccscbaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) 2540ahd_ccscbadr_bk_print(u_int regvalue, u_int *cur_col, u_int wrap)
2541{ 2541{
2542 return (ahd_print_register(NULL, 0, "CCSCBADDR", 2542 return (ahd_print_register(NULL, 0, "CCSCBADR_BK",
2543 0xac, regvalue, cur_col, wrap)); 2543 0xac, regvalue, cur_col, wrap));
2544} 2544}
2545 2545
2546int 2546int
2547ahd_ccscbadr_bk_print(u_int regvalue, u_int *cur_col, u_int wrap) 2547ahd_ccscbaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
2548{ 2548{
2549 return (ahd_print_register(NULL, 0, "CCSCBADR_BK", 2549 return (ahd_print_register(NULL, 0, "CCSCBADDR",
2550 0xac, regvalue, cur_col, wrap)); 2550 0xac, regvalue, cur_col, wrap));
2551} 2551}
2552 2552
@@ -2566,22 +2566,6 @@ ahd_cmc_rambist_print(u_int regvalue, u_int *cur_col, u_int wrap)
2566 0xad, regvalue, cur_col, wrap)); 2566 0xad, regvalue, cur_col, wrap));
2567} 2567}
2568 2568
2569static ahd_reg_parse_entry_t CCSGCTL_parse_table[] = {
2570 { "CCSGRESET", 0x01, 0x01 },
2571 { "SG_FETCH_REQ", 0x02, 0x02 },
2572 { "CCSGENACK", 0x08, 0x08 },
2573 { "SG_CACHE_AVAIL", 0x10, 0x10 },
2574 { "CCSGDONE", 0x80, 0x80 },
2575 { "CCSGEN", 0x0c, 0x0c }
2576};
2577
2578int
2579ahd_ccsgctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
2580{
2581 return (ahd_print_register(CCSGCTL_parse_table, 6, "CCSGCTL",
2582 0xad, regvalue, cur_col, wrap));
2583}
2584
2585static ahd_reg_parse_entry_t CCSCBCTL_parse_table[] = { 2569static ahd_reg_parse_entry_t CCSCBCTL_parse_table[] = {
2586 { "CCSCBRESET", 0x01, 0x01 }, 2570 { "CCSCBRESET", 0x01, 0x01 },
2587 { "CCSCBDIR", 0x04, 0x04 }, 2571 { "CCSCBDIR", 0x04, 0x04 },
@@ -2598,6 +2582,22 @@ ahd_ccscbctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
2598 0xad, regvalue, cur_col, wrap)); 2582 0xad, regvalue, cur_col, wrap));
2599} 2583}
2600 2584
2585static ahd_reg_parse_entry_t CCSGCTL_parse_table[] = {
2586 { "CCSGRESET", 0x01, 0x01 },
2587 { "SG_FETCH_REQ", 0x02, 0x02 },
2588 { "CCSGENACK", 0x08, 0x08 },
2589 { "SG_CACHE_AVAIL", 0x10, 0x10 },
2590 { "CCSGDONE", 0x80, 0x80 },
2591 { "CCSGEN", 0x0c, 0x0c }
2592};
2593
2594int
2595ahd_ccsgctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
2596{
2597 return (ahd_print_register(CCSGCTL_parse_table, 6, "CCSGCTL",
2598 0xad, regvalue, cur_col, wrap));
2599}
2600
2601int 2601int
2602ahd_ccsgram_print(u_int regvalue, u_int *cur_col, u_int wrap) 2602ahd_ccsgram_print(u_int regvalue, u_int *cur_col, u_int wrap)
2603{ 2603{
@@ -2841,30 +2841,30 @@ ahd_wrtbiascalc_print(u_int regvalue, u_int *cur_col, u_int wrap)
2841} 2841}
2842 2842
2843int 2843int
2844ahd_dfptrs_print(u_int regvalue, u_int *cur_col, u_int wrap) 2844ahd_rcvrbiascalc_print(u_int regvalue, u_int *cur_col, u_int wrap)
2845{ 2845{
2846 return (ahd_print_register(NULL, 0, "DFPTRS", 2846 return (ahd_print_register(NULL, 0, "RCVRBIASCALC",
2847 0xc8, regvalue, cur_col, wrap)); 2847 0xc8, regvalue, cur_col, wrap));
2848} 2848}
2849 2849
2850int 2850int
2851ahd_rcvrbiascalc_print(u_int regvalue, u_int *cur_col, u_int wrap) 2851ahd_dfptrs_print(u_int regvalue, u_int *cur_col, u_int wrap)
2852{ 2852{
2853 return (ahd_print_register(NULL, 0, "RCVRBIASCALC", 2853 return (ahd_print_register(NULL, 0, "DFPTRS",
2854 0xc8, regvalue, cur_col, wrap)); 2854 0xc8, regvalue, cur_col, wrap));
2855} 2855}
2856 2856
2857int 2857int
2858ahd_dfbkptr_print(u_int regvalue, u_int *cur_col, u_int wrap) 2858ahd_skewcalc_print(u_int regvalue, u_int *cur_col, u_int wrap)
2859{ 2859{
2860 return (ahd_print_register(NULL, 0, "DFBKPTR", 2860 return (ahd_print_register(NULL, 0, "SKEWCALC",
2861 0xc9, regvalue, cur_col, wrap)); 2861 0xc9, regvalue, cur_col, wrap));
2862} 2862}
2863 2863
2864int 2864int
2865ahd_skewcalc_print(u_int regvalue, u_int *cur_col, u_int wrap) 2865ahd_dfbkptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
2866{ 2866{
2867 return (ahd_print_register(NULL, 0, "SKEWCALC", 2867 return (ahd_print_register(NULL, 0, "DFBKPTR",
2868 0xc9, regvalue, cur_col, wrap)); 2868 0xc9, regvalue, cur_col, wrap));
2869} 2869}
2870 2870
@@ -3001,6 +3001,13 @@ ahd_dindex_print(u_int regvalue, u_int *cur_col, u_int wrap)
3001 0xe4, regvalue, cur_col, wrap)); 3001 0xe4, regvalue, cur_col, wrap));
3002} 3002}
3003 3003
3004int
3005ahd_brkaddr0_print(u_int regvalue, u_int *cur_col, u_int wrap)
3006{
3007 return (ahd_print_register(NULL, 0, "BRKADDR0",
3008 0xe6, regvalue, cur_col, wrap));
3009}
3010
3004static ahd_reg_parse_entry_t BRKADDR1_parse_table[] = { 3011static ahd_reg_parse_entry_t BRKADDR1_parse_table[] = {
3005 { "BRKDIS", 0x80, 0x80 } 3012 { "BRKDIS", 0x80, 0x80 }
3006}; 3013};
@@ -3013,13 +3020,6 @@ ahd_brkaddr1_print(u_int regvalue, u_int *cur_col, u_int wrap)
3013} 3020}
3014 3021
3015int 3022int
3016ahd_brkaddr0_print(u_int regvalue, u_int *cur_col, u_int wrap)
3017{
3018 return (ahd_print_register(NULL, 0, "BRKADDR0",
3019 0xe6, regvalue, cur_col, wrap));
3020}
3021
3022int
3023ahd_allones_print(u_int regvalue, u_int *cur_col, u_int wrap) 3023ahd_allones_print(u_int regvalue, u_int *cur_col, u_int wrap)
3024{ 3024{
3025 return (ahd_print_register(NULL, 0, "ALLONES", 3025 return (ahd_print_register(NULL, 0, "ALLONES",
@@ -3069,30 +3069,30 @@ ahd_stack_print(u_int regvalue, u_int *cur_col, u_int wrap)
3069} 3069}
3070 3070
3071int 3071int
3072ahd_curaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) 3072ahd_intvec1_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
3073{ 3073{
3074 return (ahd_print_register(NULL, 0, "CURADDR", 3074 return (ahd_print_register(NULL, 0, "INTVEC1_ADDR",
3075 0xf4, regvalue, cur_col, wrap)); 3075 0xf4, regvalue, cur_col, wrap));
3076} 3076}
3077 3077
3078int 3078int
3079ahd_intvec1_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) 3079ahd_curaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
3080{ 3080{
3081 return (ahd_print_register(NULL, 0, "INTVEC1_ADDR", 3081 return (ahd_print_register(NULL, 0, "CURADDR",
3082 0xf4, regvalue, cur_col, wrap)); 3082 0xf4, regvalue, cur_col, wrap));
3083} 3083}
3084 3084
3085int 3085int
3086ahd_intvec2_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) 3086ahd_lastaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
3087{ 3087{
3088 return (ahd_print_register(NULL, 0, "INTVEC2_ADDR", 3088 return (ahd_print_register(NULL, 0, "LASTADDR",
3089 0xf6, regvalue, cur_col, wrap)); 3089 0xf6, regvalue, cur_col, wrap));
3090} 3090}
3091 3091
3092int 3092int
3093ahd_lastaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) 3093ahd_intvec2_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
3094{ 3094{
3095 return (ahd_print_register(NULL, 0, "LASTADDR", 3095 return (ahd_print_register(NULL, 0, "INTVEC2_ADDR",
3096 0xf6, regvalue, cur_col, wrap)); 3096 0xf6, regvalue, cur_col, wrap));
3097} 3097}
3098 3098
@@ -3174,24 +3174,45 @@ ahd_complete_dma_scb_head_print(u_int regvalue, u_int *cur_col, u_int wrap)
3174} 3174}
3175 3175
3176int 3176int
3177ahd_complete_dma_scb_tail_print(u_int regvalue, u_int *cur_col, u_int wrap)
3178{
3179 return (ahd_print_register(NULL, 0, "COMPLETE_DMA_SCB_TAIL",
3180 0x12e, regvalue, cur_col, wrap));
3181}
3182
3183int
3184ahd_complete_on_qfreeze_head_print(u_int regvalue, u_int *cur_col, u_int wrap)
3185{
3186 return (ahd_print_register(NULL, 0, "COMPLETE_ON_QFREEZE_HEAD",
3187 0x130, regvalue, cur_col, wrap));
3188}
3189
3190int
3177ahd_qfreeze_count_print(u_int regvalue, u_int *cur_col, u_int wrap) 3191ahd_qfreeze_count_print(u_int regvalue, u_int *cur_col, u_int wrap)
3178{ 3192{
3179 return (ahd_print_register(NULL, 0, "QFREEZE_COUNT", 3193 return (ahd_print_register(NULL, 0, "QFREEZE_COUNT",
3180 0x12e, regvalue, cur_col, wrap)); 3194 0x132, regvalue, cur_col, wrap));
3195}
3196
3197int
3198ahd_kernel_qfreeze_count_print(u_int regvalue, u_int *cur_col, u_int wrap)
3199{
3200 return (ahd_print_register(NULL, 0, "KERNEL_QFREEZE_COUNT",
3201 0x134, regvalue, cur_col, wrap));
3181} 3202}
3182 3203
3183int 3204int
3184ahd_saved_mode_print(u_int regvalue, u_int *cur_col, u_int wrap) 3205ahd_saved_mode_print(u_int regvalue, u_int *cur_col, u_int wrap)
3185{ 3206{
3186 return (ahd_print_register(NULL, 0, "SAVED_MODE", 3207 return (ahd_print_register(NULL, 0, "SAVED_MODE",
3187 0x130, regvalue, cur_col, wrap)); 3208 0x136, regvalue, cur_col, wrap));
3188} 3209}
3189 3210
3190int 3211int
3191ahd_msg_out_print(u_int regvalue, u_int *cur_col, u_int wrap) 3212ahd_msg_out_print(u_int regvalue, u_int *cur_col, u_int wrap)
3192{ 3213{
3193 return (ahd_print_register(NULL, 0, "MSG_OUT", 3214 return (ahd_print_register(NULL, 0, "MSG_OUT",
3194 0x131, regvalue, cur_col, wrap)); 3215 0x137, regvalue, cur_col, wrap));
3195} 3216}
3196 3217
3197static ahd_reg_parse_entry_t DMAPARAMS_parse_table[] = { 3218static ahd_reg_parse_entry_t DMAPARAMS_parse_table[] = {
@@ -3211,7 +3232,7 @@ int
3211ahd_dmaparams_print(u_int regvalue, u_int *cur_col, u_int wrap) 3232ahd_dmaparams_print(u_int regvalue, u_int *cur_col, u_int wrap)
3212{ 3233{
3213 return (ahd_print_register(DMAPARAMS_parse_table, 10, "DMAPARAMS", 3234 return (ahd_print_register(DMAPARAMS_parse_table, 10, "DMAPARAMS",
3214 0x132, regvalue, cur_col, wrap)); 3235 0x138, regvalue, cur_col, wrap));
3215} 3236}
3216 3237
3217static ahd_reg_parse_entry_t SEQ_FLAGS_parse_table[] = { 3238static ahd_reg_parse_entry_t SEQ_FLAGS_parse_table[] = {
@@ -3230,21 +3251,21 @@ int
3230ahd_seq_flags_print(u_int regvalue, u_int *cur_col, u_int wrap) 3251ahd_seq_flags_print(u_int regvalue, u_int *cur_col, u_int wrap)
3231{ 3252{
3232 return (ahd_print_register(SEQ_FLAGS_parse_table, 9, "SEQ_FLAGS", 3253 return (ahd_print_register(SEQ_FLAGS_parse_table, 9, "SEQ_FLAGS",
3233 0x133, regvalue, cur_col, wrap)); 3254 0x139, regvalue, cur_col, wrap));
3234} 3255}
3235 3256
3236int 3257int
3237ahd_saved_scsiid_print(u_int regvalue, u_int *cur_col, u_int wrap) 3258ahd_saved_scsiid_print(u_int regvalue, u_int *cur_col, u_int wrap)
3238{ 3259{
3239 return (ahd_print_register(NULL, 0, "SAVED_SCSIID", 3260 return (ahd_print_register(NULL, 0, "SAVED_SCSIID",
3240 0x134, regvalue, cur_col, wrap)); 3261 0x13a, regvalue, cur_col, wrap));
3241} 3262}
3242 3263
3243int 3264int
3244ahd_saved_lun_print(u_int regvalue, u_int *cur_col, u_int wrap) 3265ahd_saved_lun_print(u_int regvalue, u_int *cur_col, u_int wrap)
3245{ 3266{
3246 return (ahd_print_register(NULL, 0, "SAVED_LUN", 3267 return (ahd_print_register(NULL, 0, "SAVED_LUN",
3247 0x135, regvalue, cur_col, wrap)); 3268 0x13b, regvalue, cur_col, wrap));
3248} 3269}
3249 3270
3250static ahd_reg_parse_entry_t LASTPHASE_parse_table[] = { 3271static ahd_reg_parse_entry_t LASTPHASE_parse_table[] = {
@@ -3267,42 +3288,42 @@ int
3267ahd_lastphase_print(u_int regvalue, u_int *cur_col, u_int wrap) 3288ahd_lastphase_print(u_int regvalue, u_int *cur_col, u_int wrap)
3268{ 3289{
3269 return (ahd_print_register(LASTPHASE_parse_table, 13, "LASTPHASE", 3290 return (ahd_print_register(LASTPHASE_parse_table, 13, "LASTPHASE",
3270 0x136, regvalue, cur_col, wrap)); 3291 0x13c, regvalue, cur_col, wrap));
3271} 3292}
3272 3293
3273int 3294int
3274ahd_qoutfifo_entry_valid_tag_print(u_int regvalue, u_int *cur_col, u_int wrap) 3295ahd_qoutfifo_entry_valid_tag_print(u_int regvalue, u_int *cur_col, u_int wrap)
3275{ 3296{
3276 return (ahd_print_register(NULL, 0, "QOUTFIFO_ENTRY_VALID_TAG", 3297 return (ahd_print_register(NULL, 0, "QOUTFIFO_ENTRY_VALID_TAG",
3277 0x137, regvalue, cur_col, wrap)); 3298 0x13d, regvalue, cur_col, wrap));
3278} 3299}
3279 3300
3280int 3301int
3281ahd_shared_data_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) 3302ahd_kernel_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap)
3282{ 3303{
3283 return (ahd_print_register(NULL, 0, "SHARED_DATA_ADDR", 3304 return (ahd_print_register(NULL, 0, "KERNEL_TQINPOS",
3284 0x138, regvalue, cur_col, wrap)); 3305 0x13e, regvalue, cur_col, wrap));
3285} 3306}
3286 3307
3287int 3308int
3288ahd_qoutfifo_next_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) 3309ahd_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap)
3289{ 3310{
3290 return (ahd_print_register(NULL, 0, "QOUTFIFO_NEXT_ADDR", 3311 return (ahd_print_register(NULL, 0, "TQINPOS",
3291 0x13c, regvalue, cur_col, wrap)); 3312 0x13f, regvalue, cur_col, wrap));
3292} 3313}
3293 3314
3294int 3315int
3295ahd_kernel_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap) 3316ahd_shared_data_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
3296{ 3317{
3297 return (ahd_print_register(NULL, 0, "KERNEL_TQINPOS", 3318 return (ahd_print_register(NULL, 0, "SHARED_DATA_ADDR",
3298 0x140, regvalue, cur_col, wrap)); 3319 0x140, regvalue, cur_col, wrap));
3299} 3320}
3300 3321
3301int 3322int
3302ahd_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap) 3323ahd_qoutfifo_next_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
3303{ 3324{
3304 return (ahd_print_register(NULL, 0, "TQINPOS", 3325 return (ahd_print_register(NULL, 0, "QOUTFIFO_NEXT_ADDR",
3305 0x141, regvalue, cur_col, wrap)); 3326 0x144, regvalue, cur_col, wrap));
3306} 3327}
3307 3328
3308static ahd_reg_parse_entry_t ARG_1_parse_table[] = { 3329static ahd_reg_parse_entry_t ARG_1_parse_table[] = {
@@ -3320,21 +3341,21 @@ int
3320ahd_arg_1_print(u_int regvalue, u_int *cur_col, u_int wrap) 3341ahd_arg_1_print(u_int regvalue, u_int *cur_col, u_int wrap)
3321{ 3342{
3322 return (ahd_print_register(ARG_1_parse_table, 8, "ARG_1", 3343 return (ahd_print_register(ARG_1_parse_table, 8, "ARG_1",
3323 0x142, regvalue, cur_col, wrap)); 3344 0x148, regvalue, cur_col, wrap));
3324} 3345}
3325 3346
3326int 3347int
3327ahd_arg_2_print(u_int regvalue, u_int *cur_col, u_int wrap) 3348ahd_arg_2_print(u_int regvalue, u_int *cur_col, u_int wrap)
3328{ 3349{
3329 return (ahd_print_register(NULL, 0, "ARG_2", 3350 return (ahd_print_register(NULL, 0, "ARG_2",
3330 0x143, regvalue, cur_col, wrap)); 3351 0x149, regvalue, cur_col, wrap));
3331} 3352}
3332 3353
3333int 3354int
3334ahd_last_msg_print(u_int regvalue, u_int *cur_col, u_int wrap) 3355ahd_last_msg_print(u_int regvalue, u_int *cur_col, u_int wrap)
3335{ 3356{
3336 return (ahd_print_register(NULL, 0, "LAST_MSG", 3357 return (ahd_print_register(NULL, 0, "LAST_MSG",
3337 0x144, regvalue, cur_col, wrap)); 3358 0x14a, regvalue, cur_col, wrap));
3338} 3359}
3339 3360
3340static ahd_reg_parse_entry_t SCSISEQ_TEMPLATE_parse_table[] = { 3361static ahd_reg_parse_entry_t SCSISEQ_TEMPLATE_parse_table[] = {
@@ -3350,14 +3371,14 @@ int
3350ahd_scsiseq_template_print(u_int regvalue, u_int *cur_col, u_int wrap) 3371ahd_scsiseq_template_print(u_int regvalue, u_int *cur_col, u_int wrap)
3351{ 3372{
3352 return (ahd_print_register(SCSISEQ_TEMPLATE_parse_table, 6, "SCSISEQ_TEMPLATE", 3373 return (ahd_print_register(SCSISEQ_TEMPLATE_parse_table, 6, "SCSISEQ_TEMPLATE",
3353 0x145, regvalue, cur_col, wrap)); 3374 0x14b, regvalue, cur_col, wrap));
3354} 3375}
3355 3376
3356int 3377int
3357ahd_initiator_tag_print(u_int regvalue, u_int *cur_col, u_int wrap) 3378ahd_initiator_tag_print(u_int regvalue, u_int *cur_col, u_int wrap)
3358{ 3379{
3359 return (ahd_print_register(NULL, 0, "INITIATOR_TAG", 3380 return (ahd_print_register(NULL, 0, "INITIATOR_TAG",
3360 0x146, regvalue, cur_col, wrap)); 3381 0x14c, regvalue, cur_col, wrap));
3361} 3382}
3362 3383
3363static ahd_reg_parse_entry_t SEQ_FLAGS2_parse_table[] = { 3384static ahd_reg_parse_entry_t SEQ_FLAGS2_parse_table[] = {
@@ -3369,63 +3390,63 @@ int
3369ahd_seq_flags2_print(u_int regvalue, u_int *cur_col, u_int wrap) 3390ahd_seq_flags2_print(u_int regvalue, u_int *cur_col, u_int wrap)
3370{ 3391{
3371 return (ahd_print_register(SEQ_FLAGS2_parse_table, 2, "SEQ_FLAGS2", 3392 return (ahd_print_register(SEQ_FLAGS2_parse_table, 2, "SEQ_FLAGS2",
3372 0x147, regvalue, cur_col, wrap)); 3393 0x14d, regvalue, cur_col, wrap));
3373} 3394}
3374 3395
3375int 3396int
3376ahd_allocfifo_scbptr_print(u_int regvalue, u_int *cur_col, u_int wrap) 3397ahd_allocfifo_scbptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
3377{ 3398{
3378 return (ahd_print_register(NULL, 0, "ALLOCFIFO_SCBPTR", 3399 return (ahd_print_register(NULL, 0, "ALLOCFIFO_SCBPTR",
3379 0x148, regvalue, cur_col, wrap)); 3400 0x14e, regvalue, cur_col, wrap));
3380} 3401}
3381 3402
3382int 3403int
3383ahd_int_coalescing_timer_print(u_int regvalue, u_int *cur_col, u_int wrap) 3404ahd_int_coalescing_timer_print(u_int regvalue, u_int *cur_col, u_int wrap)
3384{ 3405{
3385 return (ahd_print_register(NULL, 0, "INT_COALESCING_TIMER", 3406 return (ahd_print_register(NULL, 0, "INT_COALESCING_TIMER",
3386 0x14a, regvalue, cur_col, wrap)); 3407 0x150, regvalue, cur_col, wrap));
3387} 3408}
3388 3409
3389int 3410int
3390ahd_int_coalescing_maxcmds_print(u_int regvalue, u_int *cur_col, u_int wrap) 3411ahd_int_coalescing_maxcmds_print(u_int regvalue, u_int *cur_col, u_int wrap)
3391{ 3412{
3392 return (ahd_print_register(NULL, 0, "INT_COALESCING_MAXCMDS", 3413 return (ahd_print_register(NULL, 0, "INT_COALESCING_MAXCMDS",
3393 0x14c, regvalue, cur_col, wrap)); 3414 0x152, regvalue, cur_col, wrap));
3394} 3415}
3395 3416
3396int 3417int
3397ahd_int_coalescing_mincmds_print(u_int regvalue, u_int *cur_col, u_int wrap) 3418ahd_int_coalescing_mincmds_print(u_int regvalue, u_int *cur_col, u_int wrap)
3398{ 3419{
3399 return (ahd_print_register(NULL, 0, "INT_COALESCING_MINCMDS", 3420 return (ahd_print_register(NULL, 0, "INT_COALESCING_MINCMDS",
3400 0x14d, regvalue, cur_col, wrap)); 3421 0x153, regvalue, cur_col, wrap));
3401} 3422}
3402 3423
3403int 3424int
3404ahd_cmds_pending_print(u_int regvalue, u_int *cur_col, u_int wrap) 3425ahd_cmds_pending_print(u_int regvalue, u_int *cur_col, u_int wrap)
3405{ 3426{
3406 return (ahd_print_register(NULL, 0, "CMDS_PENDING", 3427 return (ahd_print_register(NULL, 0, "CMDS_PENDING",
3407 0x14e, regvalue, cur_col, wrap)); 3428 0x154, regvalue, cur_col, wrap));
3408} 3429}
3409 3430
3410int 3431int
3411ahd_int_coalescing_cmdcount_print(u_int regvalue, u_int *cur_col, u_int wrap) 3432ahd_int_coalescing_cmdcount_print(u_int regvalue, u_int *cur_col, u_int wrap)
3412{ 3433{
3413 return (ahd_print_register(NULL, 0, "INT_COALESCING_CMDCOUNT", 3434 return (ahd_print_register(NULL, 0, "INT_COALESCING_CMDCOUNT",
3414 0x150, regvalue, cur_col, wrap)); 3435 0x156, regvalue, cur_col, wrap));
3415} 3436}
3416 3437
3417int 3438int
3418ahd_local_hs_mailbox_print(u_int regvalue, u_int *cur_col, u_int wrap) 3439ahd_local_hs_mailbox_print(u_int regvalue, u_int *cur_col, u_int wrap)
3419{ 3440{
3420 return (ahd_print_register(NULL, 0, "LOCAL_HS_MAILBOX", 3441 return (ahd_print_register(NULL, 0, "LOCAL_HS_MAILBOX",
3421 0x151, regvalue, cur_col, wrap)); 3442 0x157, regvalue, cur_col, wrap));
3422} 3443}
3423 3444
3424int 3445int
3425ahd_cmdsize_table_print(u_int regvalue, u_int *cur_col, u_int wrap) 3446ahd_cmdsize_table_print(u_int regvalue, u_int *cur_col, u_int wrap)
3426{ 3447{
3427 return (ahd_print_register(NULL, 0, "CMDSIZE_TABLE", 3448 return (ahd_print_register(NULL, 0, "CMDSIZE_TABLE",
3428 0x152, regvalue, cur_col, wrap)); 3449 0x158, regvalue, cur_col, wrap));
3429} 3450}
3430 3451
3431int 3452int
diff --git a/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped b/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped
index 77c471f934e0..b1e5365be230 100644
--- a/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped
+++ b/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped
@@ -2,215 +2,228 @@
2 * DO NOT EDIT - This file is automatically generated 2 * DO NOT EDIT - This file is automatically generated
3 * from the following source files: 3 * from the following source files:
4 * 4 *
5 * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#94 $ 5 * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#119 $
6 * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $ 6 * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#76 $
7 */ 7 */
8static uint8_t seqprog[] = { 8static uint8_t seqprog[] = {
9 0xff, 0x02, 0x06, 0x78, 9 0xff, 0x02, 0x06, 0x78,
10 0x00, 0xea, 0x50, 0x59, 10 0x00, 0xea, 0x64, 0x59,
11 0x01, 0xea, 0x04, 0x30, 11 0x01, 0xea, 0x04, 0x30,
12 0xff, 0x04, 0x0c, 0x78, 12 0xff, 0x04, 0x0c, 0x78,
13 0x19, 0xea, 0x50, 0x59, 13 0x19, 0xea, 0x64, 0x59,
14 0x19, 0xea, 0x04, 0x00, 14 0x19, 0xea, 0x04, 0x00,
15 0x33, 0xea, 0x44, 0x59, 15 0x33, 0xea, 0x5e, 0x59,
16 0x33, 0xea, 0x00, 0x00, 16 0x33, 0xea, 0x00, 0x00,
17 0x60, 0x3a, 0x1a, 0x68, 17 0x60, 0x3a, 0x3a, 0x68,
18 0x04, 0x47, 0x1b, 0x68, 18 0x04, 0x4d, 0x35, 0x78,
19 0xff, 0x21, 0x1b, 0x70, 19 0x01, 0x34, 0xc1, 0x31,
20 0x40, 0x4b, 0x92, 0x69, 20 0x00, 0x32, 0x21, 0x60,
21 0x00, 0xe2, 0x54, 0x59, 21 0x01, 0x35, 0xc1, 0x31,
22 0x40, 0x4b, 0x92, 0x69, 22 0x00, 0x33, 0x21, 0x60,
23 0x20, 0x4b, 0x82, 0x69, 23 0xfb, 0x4d, 0x9b, 0x0a,
24 0xfc, 0x42, 0x24, 0x78, 24 0x00, 0xe2, 0x34, 0x40,
25 0x10, 0x40, 0x24, 0x78, 25 0x50, 0x4b, 0x3a, 0x68,
26 0x00, 0xe2, 0xc4, 0x5d, 26 0xff, 0x31, 0x3b, 0x70,
27 0x20, 0x4d, 0x28, 0x78, 27 0x02, 0x30, 0x51, 0x31,
28 0x00, 0xe2, 0xc4, 0x5d, 28 0xff, 0x8d, 0x2d, 0x70,
29 0x02, 0x8c, 0x51, 0x31,
30 0xff, 0x8d, 0x29, 0x60,
31 0x02, 0x28, 0x19, 0x33,
32 0x02, 0x30, 0x51, 0x32,
33 0xff, 0xea, 0x62, 0x02,
34 0x00, 0xe2, 0x3a, 0x40,
35 0xff, 0x21, 0x3b, 0x70,
36 0x40, 0x4b, 0xaa, 0x69,
37 0x00, 0xe2, 0x68, 0x59,
38 0x40, 0x4b, 0xaa, 0x69,
39 0x20, 0x4b, 0x96, 0x69,
40 0xfc, 0x42, 0x44, 0x78,
41 0x10, 0x40, 0x44, 0x78,
42 0x00, 0xe2, 0xfc, 0x5d,
43 0x20, 0x4d, 0x48, 0x78,
44 0x00, 0xe2, 0xfc, 0x5d,
29 0x30, 0x3f, 0xc0, 0x09, 45 0x30, 0x3f, 0xc0, 0x09,
30 0x30, 0xe0, 0x30, 0x60, 46 0x30, 0xe0, 0x50, 0x60,
31 0x7f, 0x4a, 0x94, 0x08, 47 0x7f, 0x4a, 0x94, 0x08,
32 0x00, 0xe2, 0x32, 0x40, 48 0x00, 0xe2, 0x52, 0x40,
33 0xc0, 0x4a, 0x94, 0x00, 49 0xc0, 0x4a, 0x94, 0x00,
34 0x00, 0xe2, 0x3e, 0x58, 50 0x00, 0xe2, 0x5e, 0x58,
35 0x00, 0xe2, 0x56, 0x58, 51 0x00, 0xe2, 0x76, 0x58,
36 0x00, 0xe2, 0x66, 0x58, 52 0x00, 0xe2, 0x86, 0x58,
37 0x00, 0xe2, 0x06, 0x40, 53 0x00, 0xe2, 0x06, 0x40,
38 0x33, 0xea, 0x44, 0x59, 54 0x33, 0xea, 0x5e, 0x59,
39 0x33, 0xea, 0x00, 0x00, 55 0x33, 0xea, 0x00, 0x00,
40 0x01, 0x52, 0x64, 0x78, 56 0x01, 0x52, 0x84, 0x78,
41 0x02, 0x58, 0x50, 0x31, 57 0x02, 0x58, 0x50, 0x31,
42 0xff, 0xea, 0x10, 0x0b, 58 0xff, 0xea, 0x10, 0x0b,
43 0xff, 0x97, 0x4f, 0x78, 59 0xff, 0x97, 0x6f, 0x78,
44 0x50, 0x4b, 0x4a, 0x68, 60 0x50, 0x4b, 0x6a, 0x68,
45 0xbf, 0x3a, 0x74, 0x08, 61 0xbf, 0x3a, 0x74, 0x08,
46 0x14, 0xea, 0x50, 0x59, 62 0x14, 0xea, 0x64, 0x59,
47 0x14, 0xea, 0x04, 0x00, 63 0x14, 0xea, 0x04, 0x00,
48 0x08, 0x92, 0x25, 0x03, 64 0x08, 0x92, 0x25, 0x03,
49 0xff, 0x90, 0x3f, 0x68, 65 0xff, 0x90, 0x5f, 0x68,
50 0x00, 0xe2, 0x56, 0x5b, 66 0x00, 0xe2, 0x76, 0x5b,
51 0x00, 0xe2, 0x3e, 0x40, 67 0x00, 0xe2, 0x5e, 0x40,
52 0x00, 0xea, 0x44, 0x59, 68 0x00, 0xea, 0x5e, 0x59,
53 0x01, 0xea, 0x00, 0x30, 69 0x01, 0xea, 0x00, 0x30,
54 0x80, 0xf9, 0x5e, 0x68, 70 0x80, 0xf9, 0x7e, 0x68,
55 0x00, 0xe2, 0x42, 0x59, 71 0x00, 0xe2, 0x5c, 0x59,
56 0x11, 0xea, 0x44, 0x59, 72 0x11, 0xea, 0x5e, 0x59,
57 0x11, 0xea, 0x00, 0x00, 73 0x11, 0xea, 0x00, 0x00,
58 0x80, 0xf9, 0x42, 0x79, 74 0x80, 0xf9, 0x5c, 0x79,
59 0xff, 0xea, 0xd4, 0x0d, 75 0xff, 0xea, 0xd4, 0x0d,
60 0x22, 0xea, 0x44, 0x59, 76 0x22, 0xea, 0x5e, 0x59,
61 0x22, 0xea, 0x00, 0x00, 77 0x22, 0xea, 0x00, 0x00,
62 0x10, 0x16, 0x70, 0x78, 78 0x10, 0x16, 0x90, 0x78,
63 0x01, 0x0b, 0xa2, 0x32,
64 0x10, 0x16, 0x2c, 0x00, 79 0x10, 0x16, 0x2c, 0x00,
65 0x18, 0xad, 0x00, 0x79, 80 0x01, 0x0b, 0xae, 0x32,
66 0x04, 0xad, 0xca, 0x68, 81 0x18, 0xad, 0x12, 0x79,
67 0x80, 0xad, 0x64, 0x78, 82 0x04, 0xad, 0xdc, 0x68,
68 0x10, 0xad, 0x98, 0x78, 83 0x80, 0xad, 0x84, 0x78,
69 0xff, 0x88, 0x83, 0x68, 84 0x10, 0xad, 0xaa, 0x78,
70 0xe7, 0xad, 0x5a, 0x09, 85 0xe7, 0xad, 0x5a, 0x09,
71 0x02, 0x8c, 0x59, 0x32, 86 0x02, 0x8c, 0x59, 0x32,
87 0xff, 0x8d, 0xa1, 0x60,
88 0xff, 0xea, 0x5e, 0x02,
89 0xff, 0x88, 0xa7, 0x78,
90 0x02, 0x30, 0x19, 0x33,
91 0x02, 0xa8, 0x60, 0x36,
72 0x02, 0x28, 0x19, 0x33, 92 0x02, 0x28, 0x19, 0x33,
73 0x02, 0xa8, 0x50, 0x36, 93 0x02, 0xa8, 0x50, 0x36,
74 0x33, 0xea, 0x44, 0x59,
75 0x33, 0xea, 0x00, 0x00,
76 0x40, 0x3a, 0x64, 0x68,
77 0x50, 0x4b, 0x64, 0x68,
78 0x22, 0xea, 0x44, 0x59,
79 0x22, 0xea, 0x00, 0x00,
80 0xe7, 0xad, 0x5a, 0x09,
81 0x02, 0x8c, 0x59, 0x32,
82 0x1a, 0xea, 0x50, 0x59,
83 0x1a, 0xea, 0x04, 0x00,
84 0xff, 0xea, 0xd4, 0x0d,
85 0xe7, 0xad, 0x5a, 0x09, 94 0xe7, 0xad, 0x5a, 0x09,
86 0x00, 0xe2, 0xa6, 0x58, 95 0x00, 0xe2, 0xb8, 0x58,
87 0xff, 0xea, 0x56, 0x02, 96 0xff, 0xea, 0x56, 0x02,
88 0x04, 0x7c, 0x78, 0x32, 97 0x04, 0x7c, 0x88, 0x32,
89 0x20, 0x16, 0x64, 0x78, 98 0x20, 0x16, 0x84, 0x78,
90 0x04, 0x38, 0x79, 0x32, 99 0x04, 0x40, 0x89, 0x32,
91 0x80, 0x37, 0x6f, 0x16, 100 0x80, 0x3d, 0x7b, 0x16,
92 0xff, 0x2d, 0xb5, 0x60, 101 0xff, 0x2d, 0xc7, 0x60,
93 0xff, 0x29, 0xb5, 0x60, 102 0xff, 0x29, 0xc7, 0x60,
94 0x40, 0x51, 0xc5, 0x78, 103 0x40, 0x57, 0xd7, 0x78,
95 0xff, 0x4f, 0xb5, 0x68, 104 0xff, 0x55, 0xc7, 0x68,
96 0xff, 0x4d, 0xc1, 0x19, 105 0xff, 0x53, 0xc1, 0x19,
97 0x00, 0x4e, 0xd5, 0x19, 106 0x00, 0x54, 0xd5, 0x19,
98 0x00, 0xe2, 0xc4, 0x50, 107 0x00, 0xe2, 0xd6, 0x50,
99 0x01, 0x4c, 0xc1, 0x31, 108 0x01, 0x52, 0xc1, 0x31,
100 0x00, 0x50, 0xd5, 0x19, 109 0x00, 0x56, 0xd5, 0x19,
101 0x00, 0xe2, 0xc4, 0x48, 110 0x00, 0xe2, 0xd6, 0x48,
102 0x80, 0x18, 0x64, 0x78, 111 0x80, 0x18, 0x84, 0x78,
103 0x02, 0x4a, 0x1d, 0x30, 112 0x02, 0x50, 0x1d, 0x30,
104 0x10, 0xea, 0x18, 0x00, 113 0x10, 0xea, 0x18, 0x00,
105 0x60, 0x18, 0x30, 0x00, 114 0x60, 0x18, 0x30, 0x00,
106 0x7f, 0x18, 0x30, 0x0c, 115 0x7f, 0x18, 0x30, 0x0c,
107 0x02, 0xea, 0x02, 0x00, 116 0x02, 0xea, 0x02, 0x00,
108 0xff, 0xea, 0xa0, 0x0a, 117 0xff, 0xea, 0xac, 0x0a,
109 0x80, 0x18, 0x30, 0x04, 118 0x80, 0x18, 0x30, 0x04,
110 0x40, 0xad, 0x64, 0x78, 119 0x40, 0xad, 0x84, 0x78,
111 0xe7, 0xad, 0x5a, 0x09, 120 0xe7, 0xad, 0x5a, 0x09,
112 0x02, 0xa8, 0x40, 0x31, 121 0x02, 0xa8, 0x40, 0x31,
113 0xff, 0xea, 0xc0, 0x09, 122 0xff, 0xea, 0xc0, 0x09,
114 0x01, 0x4e, 0x9d, 0x1a, 123 0x01, 0x54, 0xa9, 0x1a,
115 0x00, 0x4f, 0x9f, 0x22, 124 0x00, 0x55, 0xab, 0x22,
116 0x01, 0x94, 0x6d, 0x33, 125 0x01, 0x94, 0x6d, 0x33,
117 0x01, 0xea, 0x20, 0x33, 126 0xff, 0xea, 0x20, 0x0b,
118 0x04, 0xac, 0x49, 0x32, 127 0x04, 0xac, 0x49, 0x32,
119 0xff, 0xea, 0x5a, 0x03, 128 0xff, 0xea, 0x5a, 0x03,
120 0xff, 0xea, 0x5e, 0x03, 129 0xff, 0xea, 0x5e, 0x03,
121 0x01, 0x10, 0xd4, 0x31, 130 0x01, 0x10, 0xd4, 0x31,
122 0x10, 0x92, 0xf5, 0x68, 131 0x10, 0x92, 0x07, 0x69,
123 0x3d, 0x93, 0xc5, 0x29, 132 0x3d, 0x93, 0xc5, 0x29,
124 0xfe, 0xe2, 0xc4, 0x09, 133 0xfe, 0xe2, 0xc4, 0x09,
125 0x01, 0xea, 0xc6, 0x01, 134 0x01, 0xea, 0xc6, 0x01,
126 0x02, 0xe2, 0xc8, 0x31, 135 0x02, 0xe2, 0xc8, 0x31,
127 0x02, 0xec, 0x50, 0x31, 136 0x02, 0xec, 0x50, 0x31,
128 0x02, 0xa0, 0xda, 0x31, 137 0x02, 0xa0, 0xda, 0x31,
129 0xff, 0xa9, 0xf4, 0x70, 138 0xff, 0xa9, 0x06, 0x71,
130 0x02, 0xa0, 0x58, 0x37, 139 0x02, 0xa0, 0x58, 0x37,
131 0xff, 0x21, 0xfd, 0x70, 140 0xff, 0x21, 0x0f, 0x71,
132 0x02, 0x22, 0x51, 0x31, 141 0x02, 0x22, 0x51, 0x31,
133 0x02, 0xa0, 0x5c, 0x33, 142 0x02, 0xa0, 0x5c, 0x33,
134 0x02, 0xa0, 0x44, 0x36, 143 0x02, 0xa0, 0x44, 0x36,
135 0x02, 0xa0, 0x40, 0x32, 144 0x02, 0xa0, 0x40, 0x32,
136 0x02, 0xa0, 0x44, 0x36, 145 0x02, 0xa0, 0x44, 0x36,
137 0x04, 0x47, 0x05, 0x69, 146 0x04, 0x4d, 0x17, 0x69,
138 0x40, 0x16, 0x30, 0x69, 147 0x40, 0x16, 0x48, 0x69,
139 0xff, 0x2d, 0x35, 0x61, 148 0xff, 0x2d, 0x4d, 0x61,
140 0xff, 0x29, 0x65, 0x70, 149 0xff, 0x29, 0x85, 0x70,
141 0x01, 0x37, 0xc1, 0x31,
142 0x02, 0x28, 0x55, 0x32, 150 0x02, 0x28, 0x55, 0x32,
143 0x01, 0xea, 0x5a, 0x01, 151 0x01, 0xea, 0x5a, 0x01,
144 0x04, 0x3c, 0xf9, 0x30, 152 0x04, 0x44, 0xf9, 0x30,
153 0x01, 0x44, 0xc1, 0x31,
145 0x02, 0x28, 0x51, 0x31, 154 0x02, 0x28, 0x51, 0x31,
146 0x01, 0xa8, 0x60, 0x31, 155 0x02, 0xa8, 0x60, 0x31,
147 0x00, 0xa9, 0x60, 0x01, 156 0x01, 0xa4, 0x61, 0x31,
157 0x01, 0x3d, 0x61, 0x31,
148 0x01, 0x14, 0xd4, 0x31, 158 0x01, 0x14, 0xd4, 0x31,
149 0x01, 0x50, 0xa1, 0x1a, 159 0x01, 0x56, 0xad, 0x1a,
150 0xff, 0x4e, 0x9d, 0x1a, 160 0xff, 0x54, 0xa9, 0x1a,
151 0xff, 0x4f, 0x9f, 0x22, 161 0xff, 0x55, 0xab, 0x22,
152 0xff, 0x8d, 0x29, 0x71, 162 0xff, 0x8d, 0x41, 0x71,
153 0x80, 0xac, 0x28, 0x71, 163 0x80, 0xac, 0x40, 0x71,
154 0x20, 0x16, 0x28, 0x69, 164 0x20, 0x16, 0x40, 0x69,
165 0x00, 0xac, 0xc4, 0x19,
166 0x07, 0xe2, 0x40, 0xf9,
155 0x02, 0x8c, 0x51, 0x31, 167 0x02, 0x8c, 0x51, 0x31,
156 0x00, 0xe2, 0x12, 0x41, 168 0x00, 0xe2, 0x24, 0x41,
157 0x01, 0xac, 0x08, 0x31, 169 0x01, 0xac, 0x08, 0x31,
158 0x09, 0xea, 0x5a, 0x01, 170 0x09, 0xea, 0x5a, 0x01,
159 0x02, 0x8c, 0x51, 0x32, 171 0x02, 0x8c, 0x51, 0x32,
160 0xff, 0xea, 0x1a, 0x07, 172 0xff, 0xea, 0x1a, 0x07,
161 0x04, 0x24, 0xf9, 0x30, 173 0x04, 0x24, 0xf9, 0x30,
162 0x1d, 0xea, 0x3a, 0x41, 174 0x1d, 0xea, 0x52, 0x41,
163 0x02, 0x2c, 0x51, 0x31, 175 0x02, 0x2c, 0x51, 0x31,
164 0x04, 0xa8, 0xf9, 0x30, 176 0x04, 0xa8, 0xf9, 0x30,
165 0x19, 0xea, 0x3a, 0x41, 177 0x19, 0xea, 0x52, 0x41,
166 0x06, 0xea, 0x08, 0x81, 178 0x06, 0xea, 0x08, 0x81,
167 0x01, 0xe2, 0x5a, 0x35, 179 0x01, 0xe2, 0x5a, 0x35,
168 0x02, 0xf2, 0xf0, 0x35, 180 0x02, 0xf2, 0xf0, 0x31,
181 0xff, 0xea, 0xd4, 0x0d,
169 0x02, 0xf2, 0xf0, 0x31, 182 0x02, 0xf2, 0xf0, 0x31,
170 0x02, 0xf8, 0xe4, 0x35, 183 0x02, 0xf8, 0xe4, 0x35,
171 0x80, 0xea, 0xb2, 0x01, 184 0x80, 0xea, 0xb2, 0x01,
172 0x01, 0xe2, 0x00, 0x30, 185 0x01, 0xe2, 0x00, 0x30,
173 0xff, 0xea, 0xb2, 0x0d, 186 0xff, 0xea, 0xb2, 0x0d,
174 0x80, 0xea, 0xb2, 0x01,
175 0x11, 0x00, 0x00, 0x10,
176 0xff, 0xea, 0xb2, 0x0d,
177 0x01, 0xe2, 0x04, 0x30, 187 0x01, 0xe2, 0x04, 0x30,
178 0x01, 0xea, 0x04, 0x34, 188 0x01, 0xea, 0x04, 0x34,
179 0x02, 0x20, 0xbd, 0x30, 189 0x02, 0x20, 0xbd, 0x30,
180 0x02, 0x20, 0xb9, 0x30, 190 0x02, 0x20, 0xb9, 0x30,
181 0x02, 0x20, 0x51, 0x31, 191 0x02, 0x20, 0x51, 0x31,
182 0x4c, 0x93, 0xd7, 0x28, 192 0x4c, 0x93, 0xd7, 0x28,
183 0x10, 0x92, 0x63, 0x79, 193 0x10, 0x92, 0x77, 0x79,
184 0x01, 0x6b, 0xc0, 0x30, 194 0x01, 0x6b, 0xc0, 0x30,
185 0x02, 0x64, 0xc8, 0x00, 195 0x02, 0x64, 0xc8, 0x00,
186 0x40, 0x3a, 0x74, 0x04, 196 0x40, 0x3a, 0x74, 0x04,
187 0x00, 0xe2, 0x56, 0x58, 197 0x00, 0xe2, 0x76, 0x58,
188 0x33, 0xea, 0x44, 0x59, 198 0x33, 0xea, 0x5e, 0x59,
189 0x33, 0xea, 0x00, 0x00, 199 0x33, 0xea, 0x00, 0x00,
190 0x30, 0x3f, 0xc0, 0x09, 200 0x30, 0x3f, 0xc0, 0x09,
191 0x30, 0xe0, 0x64, 0x61, 201 0x30, 0xe0, 0x78, 0x61,
192 0x20, 0x3f, 0x7a, 0x69, 202 0x20, 0x3f, 0x8e, 0x69,
193 0x10, 0x3f, 0x64, 0x79, 203 0x10, 0x3f, 0x78, 0x79,
194 0x02, 0xea, 0x7e, 0x00, 204 0x02, 0xea, 0x7e, 0x00,
195 0x00, 0xea, 0x44, 0x59, 205 0x00, 0xea, 0x5e, 0x59,
196 0x01, 0xea, 0x00, 0x30, 206 0x01, 0xea, 0x00, 0x30,
197 0x02, 0x48, 0x51, 0x35, 207 0x02, 0x4e, 0x51, 0x35,
198 0x01, 0xea, 0x7e, 0x00, 208 0x01, 0xea, 0x7e, 0x00,
199 0x11, 0xea, 0x44, 0x59, 209 0x11, 0xea, 0x5e, 0x59,
200 0x11, 0xea, 0x00, 0x00, 210 0x11, 0xea, 0x00, 0x00,
201 0x02, 0x48, 0x51, 0x35, 211 0x02, 0x4e, 0x51, 0x35,
212 0xc0, 0x4a, 0x94, 0x00,
213 0x04, 0x41, 0x9c, 0x79,
202 0x08, 0xea, 0x98, 0x00, 214 0x08, 0xea, 0x98, 0x00,
203 0x08, 0x57, 0xae, 0x00, 215 0x08, 0x57, 0xae, 0x00,
204 0x08, 0x3c, 0x78, 0x00, 216 0x08, 0x3c, 0x78, 0x00,
205 0xf0, 0x49, 0x68, 0x0a, 217 0xf0, 0x49, 0x74, 0x0a,
206 0x0f, 0x67, 0xc0, 0x09, 218 0x0f, 0x67, 0xc0, 0x09,
207 0x00, 0x34, 0x69, 0x02, 219 0x00, 0x3a, 0x75, 0x02,
208 0x20, 0xea, 0x96, 0x00, 220 0x20, 0xea, 0x96, 0x00,
209 0x00, 0xe2, 0xf8, 0x41, 221 0x00, 0xe2, 0x14, 0x42,
210 0x40, 0x3a, 0xae, 0x69, 222 0xc0, 0x4a, 0x94, 0x00,
223 0x40, 0x3a, 0xc8, 0x69,
211 0x02, 0x55, 0x06, 0x68, 224 0x02, 0x55, 0x06, 0x68,
212 0x02, 0x56, 0xae, 0x69, 225 0x02, 0x56, 0xc8, 0x69,
213 0xff, 0x5b, 0xae, 0x61, 226 0xff, 0x5b, 0xc8, 0x61,
214 0x02, 0x20, 0x51, 0x31, 227 0x02, 0x20, 0x51, 0x31,
215 0x80, 0xea, 0xb2, 0x01, 228 0x80, 0xea, 0xb2, 0x01,
216 0x44, 0xea, 0x00, 0x00, 229 0x44, 0xea, 0x00, 0x00,
@@ -218,237 +231,246 @@ static uint8_t seqprog[] = {
218 0x33, 0xea, 0x00, 0x00, 231 0x33, 0xea, 0x00, 0x00,
219 0xff, 0xea, 0xb2, 0x09, 232 0xff, 0xea, 0xb2, 0x09,
220 0xff, 0xe0, 0xc0, 0x19, 233 0xff, 0xe0, 0xc0, 0x19,
221 0xff, 0xe0, 0xb0, 0x79, 234 0xff, 0xe0, 0xca, 0x79,
222 0x02, 0xac, 0x51, 0x31, 235 0x02, 0xac, 0x51, 0x31,
223 0x00, 0xe2, 0xa6, 0x41, 236 0x00, 0xe2, 0xc0, 0x41,
224 0x02, 0x5e, 0x50, 0x31, 237 0x02, 0x5e, 0x50, 0x31,
225 0x02, 0xa8, 0xb8, 0x30, 238 0x02, 0xa8, 0xb8, 0x30,
226 0x02, 0x5c, 0x50, 0x31, 239 0x02, 0x5c, 0x50, 0x31,
227 0xff, 0xad, 0xc1, 0x71, 240 0xff, 0xad, 0xdb, 0x71,
228 0x02, 0xac, 0x41, 0x31, 241 0x02, 0xac, 0x41, 0x31,
229 0x02, 0x22, 0x51, 0x31, 242 0x02, 0x22, 0x51, 0x31,
230 0x02, 0xa0, 0x5c, 0x33, 243 0x02, 0xa0, 0x5c, 0x33,
231 0x02, 0xa0, 0x44, 0x32, 244 0x02, 0xa0, 0x44, 0x32,
232 0x00, 0xe2, 0xca, 0x41, 245 0x00, 0xe2, 0xe4, 0x41,
233 0x10, 0x92, 0xcb, 0x69, 246 0x10, 0x92, 0xe5, 0x69,
234 0x3d, 0x93, 0xc9, 0x29, 247 0x3d, 0x93, 0xc9, 0x29,
235 0x01, 0xe4, 0xc8, 0x01, 248 0x01, 0xe4, 0xc8, 0x01,
236 0x01, 0xea, 0xca, 0x01, 249 0x01, 0xea, 0xca, 0x01,
237 0xff, 0xea, 0xda, 0x01, 250 0xff, 0xea, 0xda, 0x01,
238 0x02, 0x20, 0x51, 0x31, 251 0x02, 0x20, 0x51, 0x31,
239 0x02, 0xae, 0x41, 0x32, 252 0x02, 0xae, 0x41, 0x32,
240 0xff, 0x21, 0xd3, 0x61, 253 0xff, 0x21, 0xed, 0x61,
241 0xff, 0xea, 0x46, 0x02, 254 0xff, 0xea, 0x46, 0x02,
242 0x02, 0x5c, 0x50, 0x31, 255 0x02, 0x5c, 0x50, 0x31,
243 0x40, 0xea, 0x96, 0x00, 256 0x40, 0xea, 0x96, 0x00,
244 0x02, 0x56, 0xcc, 0x6d, 257 0x02, 0x56, 0x04, 0x6e,
245 0x01, 0x55, 0xcc, 0x6d, 258 0x01, 0x55, 0x04, 0x6e,
246 0x10, 0x92, 0xdf, 0x79, 259 0x10, 0x92, 0xf9, 0x79,
247 0x10, 0x40, 0xe8, 0x69, 260 0x10, 0x40, 0x02, 0x6a,
248 0x01, 0x56, 0xe8, 0x79, 261 0x01, 0x56, 0x02, 0x7a,
249 0xff, 0x97, 0x07, 0x78, 262 0xff, 0x97, 0x07, 0x78,
250 0x13, 0xea, 0x50, 0x59, 263 0x13, 0xea, 0x64, 0x59,
251 0x13, 0xea, 0x04, 0x00, 264 0x13, 0xea, 0x04, 0x00,
252 0x00, 0xe2, 0x06, 0x40, 265 0x00, 0xe2, 0x06, 0x40,
253 0xbf, 0x3a, 0x74, 0x08, 266 0xbf, 0x3a, 0x74, 0x08,
267 0x04, 0x41, 0x08, 0x7a,
254 0x08, 0xea, 0x98, 0x00, 268 0x08, 0xea, 0x98, 0x00,
255 0x08, 0x57, 0xae, 0x00, 269 0x08, 0x57, 0xae, 0x00,
256 0x01, 0x93, 0x69, 0x32, 270 0x01, 0x93, 0x75, 0x32,
257 0x01, 0x94, 0x6b, 0x32, 271 0x01, 0x94, 0x77, 0x32,
258 0x40, 0xea, 0x66, 0x02, 272 0x40, 0xea, 0x72, 0x02,
259 0x08, 0x3c, 0x78, 0x00, 273 0x08, 0x3c, 0x78, 0x00,
260 0x80, 0xea, 0x62, 0x02, 274 0x80, 0xea, 0x6e, 0x02,
261 0x00, 0xe2, 0xb8, 0x5b, 275 0x00, 0xe2, 0xe2, 0x5b,
262 0x01, 0x36, 0xc1, 0x31, 276 0x01, 0x3c, 0xc1, 0x31,
263 0x9f, 0xe0, 0x4c, 0x7c, 277 0x9f, 0xe0, 0x84, 0x7c,
264 0x80, 0xe0, 0x0c, 0x72, 278 0x80, 0xe0, 0x28, 0x72,
265 0xa0, 0xe0, 0x44, 0x72, 279 0xa0, 0xe0, 0x64, 0x72,
266 0xc0, 0xe0, 0x3a, 0x72, 280 0xc0, 0xe0, 0x5a, 0x72,
267 0xe0, 0xe0, 0x74, 0x72, 281 0xe0, 0xe0, 0x94, 0x72,
268 0x01, 0xea, 0x50, 0x59, 282 0x01, 0xea, 0x64, 0x59,
269 0x01, 0xea, 0x04, 0x00, 283 0x01, 0xea, 0x04, 0x00,
270 0x00, 0xe2, 0xf8, 0x41, 284 0x00, 0xe2, 0x14, 0x42,
271 0x80, 0x33, 0x13, 0x7a, 285 0x80, 0x39, 0x2f, 0x7a,
272 0x03, 0xea, 0x50, 0x59, 286 0x03, 0xea, 0x64, 0x59,
273 0x03, 0xea, 0x04, 0x00, 287 0x03, 0xea, 0x04, 0x00,
274 0xee, 0x00, 0x1a, 0x6a, 288 0xee, 0x00, 0x36, 0x6a,
275 0x05, 0xea, 0xb4, 0x00, 289 0x05, 0xea, 0xb4, 0x00,
276 0x33, 0xea, 0x44, 0x59, 290 0x33, 0xea, 0x5e, 0x59,
277 0x33, 0xea, 0x00, 0x00, 291 0x33, 0xea, 0x00, 0x00,
278 0x02, 0xa8, 0x90, 0x32, 292 0x02, 0xa8, 0x9c, 0x32,
279 0x00, 0xe2, 0x6a, 0x59, 293 0x00, 0xe2, 0x7e, 0x59,
280 0xef, 0x96, 0xd5, 0x19, 294 0xef, 0x96, 0xd5, 0x19,
281 0x00, 0xe2, 0x2a, 0x52, 295 0x00, 0xe2, 0x46, 0x52,
282 0x09, 0x80, 0xe1, 0x30, 296 0x09, 0x80, 0xe1, 0x30,
283 0x02, 0xea, 0x36, 0x00, 297 0x02, 0xea, 0x36, 0x00,
284 0xa8, 0xea, 0x32, 0x00, 298 0xa8, 0xea, 0x32, 0x00,
285 0x00, 0xe2, 0x30, 0x42, 299 0x00, 0xe2, 0x4c, 0x42,
286 0x01, 0x96, 0xd1, 0x30, 300 0x01, 0x96, 0xd1, 0x30,
287 0x10, 0x80, 0x89, 0x31, 301 0x10, 0x80, 0x89, 0x31,
288 0x20, 0xea, 0x32, 0x00, 302 0x20, 0xea, 0x32, 0x00,
289 0xbf, 0x33, 0x67, 0x0a, 303 0xbf, 0x39, 0x73, 0x0a,
290 0x20, 0x19, 0x32, 0x6a, 304 0x10, 0x4c, 0x56, 0x6a,
291 0x02, 0x4d, 0xf8, 0x69, 305 0x20, 0x19, 0x4e, 0x6a,
292 0x40, 0x33, 0x67, 0x02, 306 0x20, 0x19, 0x52, 0x6a,
293 0x00, 0xe2, 0xf8, 0x41, 307 0x02, 0x4d, 0x14, 0x6a,
294 0x80, 0x33, 0xb5, 0x6a, 308 0x40, 0x39, 0x73, 0x02,
309 0x00, 0xe2, 0x14, 0x42,
310 0x80, 0x39, 0xd5, 0x6a,
295 0x01, 0x44, 0x10, 0x33, 311 0x01, 0x44, 0x10, 0x33,
296 0x08, 0x92, 0x25, 0x03, 312 0x08, 0x92, 0x25, 0x03,
297 0x00, 0xe2, 0xf8, 0x41, 313 0x00, 0xe2, 0x14, 0x42,
298 0x10, 0xea, 0x80, 0x00, 314 0x10, 0xea, 0x80, 0x00,
299 0x01, 0x31, 0xc5, 0x31, 315 0x01, 0x37, 0xc5, 0x31,
300 0x80, 0xe2, 0x60, 0x62, 316 0x80, 0xe2, 0x80, 0x62,
301 0x10, 0x92, 0x85, 0x6a, 317 0x10, 0x92, 0xa5, 0x6a,
302 0xc0, 0x94, 0xc5, 0x01, 318 0xc0, 0x94, 0xc5, 0x01,
303 0x40, 0x92, 0x51, 0x6a, 319 0x40, 0x92, 0x71, 0x6a,
304 0xbf, 0xe2, 0xc4, 0x09, 320 0xbf, 0xe2, 0xc4, 0x09,
305 0x20, 0x92, 0x65, 0x7a, 321 0x20, 0x92, 0x85, 0x7a,
306 0x01, 0xe2, 0x88, 0x30, 322 0x01, 0xe2, 0x88, 0x30,
307 0x00, 0xe2, 0xb8, 0x5b, 323 0x00, 0xe2, 0xe2, 0x5b,
308 0xa0, 0x36, 0x6d, 0x62, 324 0xa0, 0x3c, 0x8d, 0x62,
309 0x23, 0x92, 0x89, 0x08, 325 0x23, 0x92, 0x89, 0x08,
310 0x00, 0xe2, 0xb8, 0x5b, 326 0x00, 0xe2, 0xe2, 0x5b,
311 0xa0, 0x36, 0x6d, 0x62, 327 0xa0, 0x3c, 0x8d, 0x62,
312 0x00, 0xa8, 0x64, 0x42, 328 0x00, 0xa8, 0x84, 0x42,
313 0xff, 0xe2, 0x64, 0x62, 329 0xff, 0xe2, 0x84, 0x62,
314 0x00, 0xe2, 0x84, 0x42, 330 0x00, 0xe2, 0xa4, 0x42,
315 0x40, 0xea, 0x98, 0x00, 331 0x40, 0xea, 0x98, 0x00,
316 0x01, 0xe2, 0x88, 0x30, 332 0x01, 0xe2, 0x88, 0x30,
317 0x00, 0xe2, 0xb8, 0x5b, 333 0x00, 0xe2, 0xe2, 0x5b,
318 0xa0, 0x36, 0x43, 0x72, 334 0xa0, 0x3c, 0x63, 0x72,
319 0x40, 0xea, 0x98, 0x00, 335 0x40, 0xea, 0x98, 0x00,
320 0x01, 0x31, 0x89, 0x32, 336 0x01, 0x37, 0x95, 0x32,
321 0x08, 0xea, 0x62, 0x02, 337 0x08, 0xea, 0x6e, 0x02,
322 0x00, 0xe2, 0xf8, 0x41, 338 0x00, 0xe2, 0x14, 0x42,
323 0xe0, 0xea, 0xd4, 0x5b, 339 0xe0, 0xea, 0xfe, 0x5b,
324 0x80, 0xe0, 0xc0, 0x6a, 340 0x80, 0xe0, 0xe0, 0x6a,
325 0x04, 0xe0, 0x66, 0x73, 341 0x04, 0xe0, 0x92, 0x73,
326 0x02, 0xe0, 0x96, 0x73, 342 0x02, 0xe0, 0xc4, 0x73,
327 0x00, 0xea, 0x1e, 0x73, 343 0x00, 0xea, 0x3e, 0x73,
328 0x03, 0xe0, 0xa6, 0x73, 344 0x03, 0xe0, 0xd4, 0x73,
329 0x23, 0xe0, 0x96, 0x72, 345 0x23, 0xe0, 0xb6, 0x72,
330 0x08, 0xe0, 0xbc, 0x72, 346 0x08, 0xe0, 0xdc, 0x72,
331 0x00, 0xe2, 0xb8, 0x5b, 347 0x00, 0xe2, 0xe2, 0x5b,
332 0x07, 0xea, 0x50, 0x59, 348 0x07, 0xea, 0x64, 0x59,
333 0x07, 0xea, 0x04, 0x00, 349 0x07, 0xea, 0x04, 0x00,
334 0x08, 0x42, 0xf9, 0x71, 350 0x08, 0x48, 0x15, 0x72,
335 0x04, 0x42, 0x93, 0x62, 351 0x04, 0x48, 0xb3, 0x62,
336 0x01, 0x43, 0x89, 0x30, 352 0x01, 0x49, 0x89, 0x30,
337 0x00, 0xe2, 0x84, 0x42, 353 0x00, 0xe2, 0xa4, 0x42,
338 0x01, 0x44, 0xd4, 0x31, 354 0x01, 0x44, 0xd4, 0x31,
339 0x00, 0xe2, 0x84, 0x42, 355 0x00, 0xe2, 0xa4, 0x42,
340 0x01, 0x00, 0x60, 0x32, 356 0x01, 0x00, 0x6c, 0x32,
341 0x33, 0xea, 0x44, 0x59, 357 0x33, 0xea, 0x5e, 0x59,
342 0x33, 0xea, 0x00, 0x00, 358 0x33, 0xea, 0x00, 0x00,
343 0x4c, 0x34, 0xc1, 0x28, 359 0x4c, 0x3a, 0xc1, 0x28,
344 0x01, 0x64, 0xc0, 0x31, 360 0x01, 0x64, 0xc0, 0x31,
345 0x00, 0x30, 0x45, 0x59, 361 0x00, 0x36, 0x5f, 0x59,
346 0x01, 0x30, 0x01, 0x30, 362 0x01, 0x36, 0x01, 0x30,
347 0x01, 0xe0, 0xba, 0x7a, 363 0x01, 0xe0, 0xda, 0x7a,
348 0xa0, 0xea, 0xca, 0x5b, 364 0xa0, 0xea, 0xf4, 0x5b,
349 0x01, 0xa0, 0xba, 0x62, 365 0x01, 0xa0, 0xda, 0x62,
350 0x01, 0x84, 0xaf, 0x7a, 366 0x01, 0x84, 0xcf, 0x7a,
351 0x01, 0x95, 0xbd, 0x6a, 367 0x01, 0x95, 0xdd, 0x6a,
352 0x05, 0xea, 0x50, 0x59, 368 0x05, 0xea, 0x64, 0x59,
353 0x05, 0xea, 0x04, 0x00, 369 0x05, 0xea, 0x04, 0x00,
354 0x00, 0xe2, 0xbc, 0x42, 370 0x00, 0xe2, 0xdc, 0x42,
355 0x03, 0xea, 0x50, 0x59, 371 0x03, 0xea, 0x64, 0x59,
356 0x03, 0xea, 0x04, 0x00, 372 0x03, 0xea, 0x04, 0x00,
357 0x00, 0xe2, 0xbc, 0x42, 373 0x00, 0xe2, 0xdc, 0x42,
358 0x07, 0xea, 0xdc, 0x5b, 374 0x07, 0xea, 0x06, 0x5c,
359 0x01, 0x44, 0xd4, 0x31, 375 0x01, 0x44, 0xd4, 0x31,
360 0x00, 0xe2, 0xf8, 0x41, 376 0x00, 0xe2, 0x14, 0x42,
361 0x3f, 0xe0, 0x6a, 0x0a, 377 0x3f, 0xe0, 0x76, 0x0a,
362 0xc0, 0x34, 0xc1, 0x09, 378 0xc0, 0x3a, 0xc1, 0x09,
363 0x00, 0x35, 0x51, 0x01, 379 0x00, 0x3b, 0x51, 0x01,
364 0xff, 0xea, 0x52, 0x09, 380 0xff, 0xea, 0x52, 0x09,
365 0x30, 0x34, 0xc5, 0x09, 381 0x30, 0x3a, 0xc5, 0x09,
366 0x3d, 0xe2, 0xc4, 0x29, 382 0x3d, 0xe2, 0xc4, 0x29,
367 0xb8, 0xe2, 0xc4, 0x19, 383 0xb8, 0xe2, 0xc4, 0x19,
368 0x01, 0xea, 0xc6, 0x01, 384 0x01, 0xea, 0xc6, 0x01,
369 0x02, 0xe2, 0xc8, 0x31, 385 0x02, 0xe2, 0xc8, 0x31,
370 0x02, 0xec, 0x40, 0x31, 386 0x02, 0xec, 0x40, 0x31,
371 0xff, 0xa1, 0xdc, 0x72, 387 0xff, 0xa1, 0xfc, 0x72,
372 0x02, 0xe8, 0xda, 0x31, 388 0x02, 0xe8, 0xda, 0x31,
373 0x02, 0xa0, 0x50, 0x31, 389 0x02, 0xa0, 0x50, 0x31,
374 0x00, 0xe2, 0xfe, 0x42, 390 0x00, 0xe2, 0x1e, 0x43,
375 0x80, 0x33, 0x67, 0x02, 391 0x80, 0x39, 0x73, 0x02,
376 0x01, 0x44, 0xd4, 0x31, 392 0x01, 0x44, 0xd4, 0x31,
377 0x00, 0xe2, 0xb8, 0x5b, 393 0x00, 0xe2, 0xe2, 0x5b,
378 0x01, 0x33, 0x67, 0x02, 394 0x01, 0x39, 0x73, 0x02,
379 0xe0, 0x36, 0x19, 0x63, 395 0xe0, 0x3c, 0x39, 0x63,
380 0x02, 0x33, 0x67, 0x02, 396 0x02, 0x39, 0x73, 0x02,
381 0x20, 0x46, 0x12, 0x63, 397 0x20, 0x46, 0x32, 0x63,
382 0xff, 0xea, 0x52, 0x09, 398 0xff, 0xea, 0x52, 0x09,
383 0xa8, 0xea, 0xca, 0x5b, 399 0xa8, 0xea, 0xf4, 0x5b,
384 0x04, 0x92, 0xf9, 0x7a, 400 0x04, 0x92, 0x19, 0x7b,
385 0x01, 0x34, 0xc1, 0x31, 401 0x01, 0x3a, 0xc1, 0x31,
386 0x00, 0x93, 0xf9, 0x62, 402 0x00, 0x93, 0x19, 0x63,
387 0x01, 0x35, 0xc1, 0x31, 403 0x01, 0x3b, 0xc1, 0x31,
388 0x00, 0x94, 0x03, 0x73, 404 0x00, 0x94, 0x23, 0x73,
389 0x01, 0xa9, 0x52, 0x11, 405 0x01, 0xa9, 0x52, 0x11,
390 0xff, 0xa9, 0xee, 0x6a, 406 0xff, 0xa9, 0x0e, 0x6b,
391 0x00, 0xe2, 0x12, 0x43, 407 0x00, 0xe2, 0x32, 0x43,
392 0x10, 0x33, 0x67, 0x02, 408 0x10, 0x39, 0x73, 0x02,
393 0x04, 0x92, 0x13, 0x7b, 409 0x04, 0x92, 0x33, 0x7b,
394 0xfb, 0x92, 0x25, 0x0b, 410 0xfb, 0x92, 0x25, 0x0b,
395 0xff, 0xea, 0x66, 0x0a, 411 0xff, 0xea, 0x72, 0x0a,
396 0x01, 0xa4, 0x0d, 0x6b, 412 0x01, 0xa4, 0x2d, 0x6b,
397 0x02, 0xa8, 0x90, 0x32, 413 0x02, 0xa8, 0x9c, 0x32,
398 0x00, 0xe2, 0x6a, 0x59, 414 0x00, 0xe2, 0x7e, 0x59,
399 0x10, 0x92, 0xbd, 0x7a, 415 0x10, 0x92, 0xdd, 0x7a,
400 0xff, 0xea, 0xdc, 0x5b, 416 0xff, 0xea, 0x06, 0x5c,
401 0x00, 0xe2, 0xbc, 0x42, 417 0x00, 0xe2, 0xdc, 0x42,
402 0x04, 0xea, 0x50, 0x59, 418 0x04, 0xea, 0x64, 0x59,
403 0x04, 0xea, 0x04, 0x00, 419 0x04, 0xea, 0x04, 0x00,
404 0x00, 0xe2, 0xbc, 0x42, 420 0x00, 0xe2, 0xdc, 0x42,
405 0x04, 0xea, 0x50, 0x59, 421 0x04, 0xea, 0x64, 0x59,
406 0x04, 0xea, 0x04, 0x00, 422 0x04, 0xea, 0x04, 0x00,
407 0x00, 0xe2, 0xf8, 0x41, 423 0x00, 0xe2, 0x14, 0x42,
408 0x08, 0x92, 0xb5, 0x7a, 424 0x08, 0x92, 0xd5, 0x7a,
409 0xc0, 0x33, 0x29, 0x7b, 425 0xc0, 0x39, 0x49, 0x7b,
410 0x80, 0x33, 0xb5, 0x6a, 426 0x80, 0x39, 0xd5, 0x6a,
411 0xff, 0x88, 0x29, 0x6b, 427 0xff, 0x88, 0x49, 0x6b,
412 0x40, 0x33, 0xb5, 0x6a, 428 0x40, 0x39, 0xd5, 0x6a,
413 0x10, 0x92, 0x2f, 0x7b, 429 0x10, 0x92, 0x4f, 0x7b,
414 0x0a, 0xea, 0x50, 0x59, 430 0x0a, 0xea, 0x64, 0x59,
415 0x0a, 0xea, 0x04, 0x00, 431 0x0a, 0xea, 0x04, 0x00,
416 0x00, 0xe2, 0x4e, 0x5b, 432 0x00, 0xe2, 0x6e, 0x5b,
417 0x00, 0xe2, 0x82, 0x43, 433 0x00, 0xe2, 0xae, 0x43,
418 0x50, 0x4b, 0x36, 0x6b, 434 0x50, 0x4b, 0x56, 0x6b,
419 0xbf, 0x3a, 0x74, 0x08, 435 0xbf, 0x3a, 0x74, 0x08,
420 0x01, 0xe0, 0xf4, 0x31, 436 0x01, 0xe0, 0xf4, 0x31,
421 0xff, 0xea, 0xc0, 0x09, 437 0xff, 0xea, 0xc0, 0x09,
422 0x01, 0x2e, 0x5d, 0x1a, 438 0x01, 0x32, 0x65, 0x1a,
423 0x00, 0x2f, 0x5f, 0x22, 439 0x00, 0x33, 0x67, 0x22,
424 0x04, 0x47, 0x8f, 0x02, 440 0x04, 0x4d, 0x9b, 0x02,
425 0x01, 0xfa, 0xc0, 0x35, 441 0x01, 0xfa, 0xc0, 0x35,
426 0x02, 0xa8, 0x84, 0x32, 442 0x02, 0xa8, 0x90, 0x32,
427 0x02, 0xea, 0xb4, 0x00, 443 0x02, 0xea, 0xb4, 0x00,
428 0x33, 0xea, 0x44, 0x59, 444 0x33, 0xea, 0x5e, 0x59,
429 0x33, 0xea, 0x00, 0x00, 445 0x33, 0xea, 0x00, 0x00,
430 0x02, 0x42, 0x51, 0x31, 446 0x02, 0x48, 0x51, 0x31,
431 0xff, 0x90, 0x65, 0x68, 447 0xff, 0x90, 0x85, 0x68,
432 0xff, 0x88, 0x5b, 0x6b, 448 0xff, 0x88, 0x7b, 0x6b,
433 0x01, 0xa4, 0x57, 0x6b, 449 0x01, 0xa4, 0x77, 0x6b,
434 0x02, 0xa4, 0x5f, 0x6b, 450 0x02, 0xa4, 0x7f, 0x6b,
435 0x01, 0x84, 0x5f, 0x7b, 451 0x01, 0x84, 0x7f, 0x7b,
436 0x02, 0x28, 0x19, 0x33, 452 0x02, 0x28, 0x19, 0x33,
437 0x02, 0xa8, 0x50, 0x36, 453 0x02, 0xa8, 0x50, 0x36,
438 0xff, 0x88, 0x5f, 0x73, 454 0xff, 0x88, 0x7f, 0x73,
439 0x00, 0xe2, 0x32, 0x5b, 455 0x00, 0xe2, 0x52, 0x5b,
440 0x02, 0xa8, 0x20, 0x33, 456 0x02, 0xa8, 0x20, 0x33,
441 0x02, 0x2c, 0x19, 0x33, 457 0x04, 0xa4, 0x49, 0x03,
458 0xff, 0xea, 0x1a, 0x03,
459 0xff, 0x2d, 0x8b, 0x63,
442 0x02, 0xa8, 0x58, 0x32, 460 0x02, 0xa8, 0x58, 0x32,
443 0x04, 0xa4, 0x49, 0x07, 461 0x02, 0xa8, 0x5c, 0x36,
444 0xc0, 0x33, 0xb5, 0x6a, 462 0x02, 0xa8, 0x40, 0x31,
463 0x02, 0x2e, 0x51, 0x31,
464 0x02, 0xa0, 0x18, 0x33,
465 0x02, 0xa0, 0x5c, 0x36,
466 0xc0, 0x39, 0xd5, 0x6a,
445 0x04, 0x92, 0x25, 0x03, 467 0x04, 0x92, 0x25, 0x03,
446 0x20, 0x92, 0x83, 0x6b, 468 0x20, 0x92, 0xaf, 0x6b,
447 0x02, 0xa8, 0x40, 0x31, 469 0x02, 0xa8, 0x40, 0x31,
448 0xc0, 0x34, 0xc1, 0x09, 470 0xc0, 0x3a, 0xc1, 0x09,
449 0x00, 0x35, 0x51, 0x01, 471 0x00, 0x3b, 0x51, 0x01,
450 0xff, 0xea, 0x52, 0x09, 472 0xff, 0xea, 0x52, 0x09,
451 0x30, 0x34, 0xc5, 0x09, 473 0x30, 0x3a, 0xc5, 0x09,
452 0x3d, 0xe2, 0xc4, 0x29, 474 0x3d, 0xe2, 0xc4, 0x29,
453 0xb8, 0xe2, 0xc4, 0x19, 475 0xb8, 0xe2, 0xc4, 0x19,
454 0x01, 0xea, 0xc6, 0x01, 476 0x01, 0xea, 0xc6, 0x01,
@@ -458,69 +480,75 @@ static uint8_t seqprog[] = {
458 0xf7, 0x57, 0xae, 0x08, 480 0xf7, 0x57, 0xae, 0x08,
459 0x08, 0xea, 0x98, 0x00, 481 0x08, 0xea, 0x98, 0x00,
460 0x01, 0x44, 0xd4, 0x31, 482 0x01, 0x44, 0xd4, 0x31,
461 0xee, 0x00, 0x8c, 0x6b, 483 0xee, 0x00, 0xb8, 0x6b,
462 0x02, 0xea, 0xb4, 0x00, 484 0x02, 0xea, 0xb4, 0x00,
463 0x00, 0xe2, 0xb4, 0x5b, 485 0xc0, 0xea, 0x72, 0x02,
464 0x09, 0x4c, 0x8e, 0x7b, 486 0x09, 0x4c, 0xba, 0x7b,
487 0x01, 0xea, 0x78, 0x02,
465 0x08, 0x4c, 0x06, 0x68, 488 0x08, 0x4c, 0x06, 0x68,
466 0x0b, 0xea, 0x50, 0x59, 489 0x0b, 0xea, 0x64, 0x59,
467 0x0b, 0xea, 0x04, 0x00, 490 0x0b, 0xea, 0x04, 0x00,
468 0x01, 0x44, 0xd4, 0x31, 491 0x01, 0x44, 0xd4, 0x31,
469 0x20, 0x33, 0xf9, 0x79, 492 0x20, 0x39, 0x15, 0x7a,
470 0x00, 0xe2, 0x9e, 0x5b, 493 0x00, 0xe2, 0xcc, 0x5b,
471 0x00, 0xe2, 0xf8, 0x41, 494 0x00, 0xe2, 0x14, 0x42,
472 0x01, 0x84, 0xa3, 0x7b, 495 0x01, 0x84, 0xd1, 0x7b,
473 0x01, 0xa4, 0x49, 0x07, 496 0x01, 0xa4, 0x49, 0x07,
474 0x08, 0x60, 0x30, 0x33, 497 0x08, 0x60, 0x30, 0x33,
475 0x08, 0x80, 0x41, 0x37, 498 0x08, 0x80, 0x41, 0x37,
476 0xdf, 0x33, 0x67, 0x0a, 499 0xdf, 0x39, 0x73, 0x0a,
477 0xee, 0x00, 0xb0, 0x6b, 500 0xee, 0x00, 0xde, 0x6b,
478 0x05, 0xea, 0xb4, 0x00, 501 0x05, 0xea, 0xb4, 0x00,
479 0x33, 0xea, 0x44, 0x59, 502 0x33, 0xea, 0x5e, 0x59,
480 0x33, 0xea, 0x00, 0x00, 503 0x33, 0xea, 0x00, 0x00,
481 0x00, 0xe2, 0x6a, 0x59, 504 0x00, 0xe2, 0x7e, 0x59,
482 0x00, 0xe2, 0xbc, 0x42, 505 0x00, 0xe2, 0xdc, 0x42,
483 0x01, 0xea, 0x6c, 0x02, 506 0xff, 0x42, 0xee, 0x6b,
484 0xc0, 0xea, 0x66, 0x06, 507 0x01, 0x41, 0xe2, 0x6b,
485 0xff, 0x42, 0xc4, 0x6b, 508 0x02, 0x41, 0xe2, 0x7b,
486 0x01, 0x41, 0xb8, 0x6b, 509 0xff, 0x42, 0xee, 0x6b,
487 0x02, 0x41, 0xb8, 0x7b, 510 0x01, 0x41, 0xe2, 0x6b,
488 0xff, 0x42, 0xc4, 0x6b, 511 0x02, 0x41, 0xe2, 0x7b,
489 0x01, 0x41, 0xb8, 0x6b, 512 0xff, 0x42, 0xee, 0x7b,
490 0x02, 0x41, 0xb8, 0x7b, 513 0x04, 0x4c, 0xe2, 0x6b,
491 0xff, 0x42, 0xc4, 0x7b, 514 0xe0, 0x41, 0x78, 0x0e,
492 0x04, 0x4c, 0xb8, 0x6b,
493 0xe0, 0x41, 0x6c, 0x0e,
494 0x01, 0x44, 0xd4, 0x31, 515 0x01, 0x44, 0xd4, 0x31,
495 0xff, 0x42, 0xcc, 0x7b, 516 0xff, 0x42, 0xf6, 0x7b,
496 0x04, 0x4c, 0xcc, 0x6b, 517 0x04, 0x4c, 0xf6, 0x6b,
497 0xe0, 0x41, 0x6c, 0x0a, 518 0xe0, 0x41, 0x78, 0x0a,
498 0xe0, 0x36, 0xf9, 0x61, 519 0xe0, 0x3c, 0x15, 0x62,
499 0xff, 0xea, 0xca, 0x09, 520 0xff, 0xea, 0xca, 0x09,
500 0x01, 0xe2, 0xc8, 0x31, 521 0x01, 0xe2, 0xc8, 0x31,
501 0x01, 0x46, 0xda, 0x35, 522 0x01, 0x46, 0xda, 0x35,
502 0x01, 0x44, 0xd4, 0x35, 523 0x01, 0x44, 0xd4, 0x35,
503 0x10, 0xea, 0x80, 0x00, 524 0x10, 0xea, 0x80, 0x00,
504 0x01, 0xe2, 0x62, 0x36, 525 0x01, 0xe2, 0x6e, 0x36,
505 0x04, 0xa6, 0xe4, 0x7b, 526 0x04, 0xa6, 0x0e, 0x7c,
506 0xff, 0xea, 0x5a, 0x09, 527 0xff, 0xea, 0x5a, 0x09,
507 0xff, 0xea, 0x4c, 0x0d, 528 0xff, 0xea, 0x4c, 0x0d,
508 0x01, 0xa6, 0x02, 0x6c, 529 0x01, 0xa6, 0x3a, 0x6c,
509 0x10, 0xad, 0x64, 0x78, 530 0x10, 0xad, 0x84, 0x78,
510 0x80, 0xad, 0xfa, 0x6b, 531 0x80, 0xad, 0x32, 0x6c,
511 0x08, 0xad, 0x64, 0x68, 532 0x08, 0xad, 0x84, 0x68,
533 0x20, 0x19, 0x26, 0x7c,
534 0x80, 0xea, 0xb2, 0x01,
535 0x11, 0x00, 0x00, 0x10,
536 0x02, 0xa6, 0x22, 0x7c,
537 0xff, 0xea, 0xb2, 0x0d,
538 0x11, 0x00, 0x00, 0x10,
539 0xff, 0xea, 0xb2, 0x09,
512 0x04, 0x84, 0xf9, 0x30, 540 0x04, 0x84, 0xf9, 0x30,
513 0x00, 0xea, 0x08, 0x81, 541 0x00, 0xea, 0x08, 0x81,
514 0xff, 0xea, 0xd4, 0x09, 542 0xff, 0xea, 0xd4, 0x09,
515 0x02, 0x84, 0xf9, 0x88, 543 0x02, 0x84, 0xf9, 0x88,
516 0x0d, 0xea, 0x5a, 0x01, 544 0x0d, 0xea, 0x5a, 0x01,
517 0x04, 0xa6, 0x4c, 0x05, 545 0x04, 0xa6, 0x4c, 0x05,
518 0x04, 0xa6, 0x64, 0x78, 546 0x04, 0xa6, 0x84, 0x78,
519 0xff, 0xea, 0x5a, 0x09, 547 0xff, 0xea, 0x5a, 0x09,
520 0x03, 0x84, 0x59, 0x89, 548 0x03, 0x84, 0x59, 0x89,
521 0x03, 0xea, 0x4c, 0x01, 549 0x03, 0xea, 0x4c, 0x01,
522 0x80, 0x1a, 0x64, 0x78, 550 0x80, 0x1a, 0x84, 0x78,
523 0x08, 0x19, 0x64, 0x78, 551 0x08, 0x19, 0x84, 0x78,
524 0x08, 0xb0, 0xe0, 0x30, 552 0x08, 0xb0, 0xe0, 0x30,
525 0x04, 0xb0, 0xe0, 0x30, 553 0x04, 0xb0, 0xe0, 0x30,
526 0x03, 0xb0, 0xf0, 0x30, 554 0x03, 0xb0, 0xf0, 0x30,
@@ -533,259 +561,259 @@ static uint8_t seqprog[] = {
533 0x00, 0x86, 0x0d, 0x23, 561 0x00, 0x86, 0x0d, 0x23,
534 0x00, 0x87, 0x0f, 0x23, 562 0x00, 0x87, 0x0f, 0x23,
535 0x01, 0x84, 0xc5, 0x31, 563 0x01, 0x84, 0xc5, 0x31,
536 0x80, 0x83, 0x25, 0x7c, 564 0x80, 0x83, 0x5d, 0x7c,
537 0x02, 0xe2, 0xc4, 0x01, 565 0x02, 0xe2, 0xc4, 0x01,
538 0xff, 0xea, 0x4c, 0x09, 566 0xff, 0xea, 0x4c, 0x09,
539 0x01, 0xe2, 0x36, 0x30, 567 0x01, 0xe2, 0x36, 0x30,
540 0xc8, 0x19, 0x32, 0x00, 568 0xc8, 0x19, 0x32, 0x00,
541 0x88, 0x19, 0x32, 0x00, 569 0x88, 0x19, 0x32, 0x00,
542 0x01, 0xac, 0xd4, 0x99, 570 0x01, 0xac, 0xd4, 0x99,
543 0x00, 0xe2, 0x64, 0x50, 571 0x00, 0xe2, 0x84, 0x50,
544 0xfe, 0xa6, 0x4c, 0x0d, 572 0xfe, 0xa6, 0x4c, 0x0d,
545 0x0b, 0x98, 0xe1, 0x30, 573 0x0b, 0x98, 0xe1, 0x30,
546 0xfd, 0xa4, 0x49, 0x09, 574 0xfd, 0xa4, 0x49, 0x09,
547 0x80, 0xa3, 0x39, 0x7c, 575 0x80, 0xa3, 0x71, 0x7c,
548 0x02, 0xa4, 0x48, 0x01, 576 0x02, 0xa4, 0x48, 0x01,
549 0x01, 0xa4, 0x36, 0x30, 577 0x01, 0xa4, 0x36, 0x30,
550 0xa8, 0xea, 0x32, 0x00, 578 0xa8, 0xea, 0x32, 0x00,
551 0xfd, 0xa4, 0x49, 0x0b, 579 0xfd, 0xa4, 0x49, 0x0b,
552 0x05, 0xa3, 0x07, 0x33, 580 0x05, 0xa3, 0x07, 0x33,
553 0x80, 0x83, 0x45, 0x6c, 581 0x80, 0x83, 0x7d, 0x6c,
554 0x02, 0xea, 0x4c, 0x05, 582 0x02, 0xea, 0x4c, 0x05,
555 0xff, 0xea, 0x4c, 0x0d, 583 0xff, 0xea, 0x4c, 0x0d,
556 0x00, 0xe2, 0x3e, 0x59, 584 0x00, 0xe2, 0x56, 0x59,
557 0x02, 0xa6, 0xe6, 0x6b, 585 0x02, 0xa6, 0x10, 0x6c,
558 0x80, 0xf9, 0xf2, 0x05, 586 0x80, 0xf9, 0xf2, 0x05,
559 0xc0, 0x33, 0x53, 0x7c, 587 0xc0, 0x39, 0x8b, 0x7c,
560 0x03, 0xea, 0x50, 0x59, 588 0x03, 0xea, 0x64, 0x59,
561 0x03, 0xea, 0x04, 0x00, 589 0x03, 0xea, 0x04, 0x00,
562 0x20, 0x33, 0x77, 0x7c, 590 0x20, 0x39, 0xaf, 0x7c,
563 0x01, 0x84, 0x5d, 0x6c, 591 0x01, 0x84, 0x95, 0x6c,
564 0x06, 0xea, 0x50, 0x59, 592 0x06, 0xea, 0x64, 0x59,
565 0x06, 0xea, 0x04, 0x00, 593 0x06, 0xea, 0x04, 0x00,
566 0x00, 0xe2, 0x7a, 0x44, 594 0x00, 0xe2, 0xb2, 0x44,
567 0x01, 0x00, 0x60, 0x32, 595 0x01, 0x00, 0x6c, 0x32,
568 0xee, 0x00, 0x66, 0x6c, 596 0xee, 0x00, 0x9e, 0x6c,
569 0x05, 0xea, 0xb4, 0x00, 597 0x05, 0xea, 0xb4, 0x00,
570 0x33, 0xea, 0x44, 0x59, 598 0x33, 0xea, 0x5e, 0x59,
571 0x33, 0xea, 0x00, 0x00, 599 0x33, 0xea, 0x00, 0x00,
572 0x80, 0x3d, 0x7a, 0x00, 600 0x80, 0x3d, 0x7a, 0x00,
573 0xfc, 0x42, 0x68, 0x7c, 601 0xfc, 0x42, 0xa0, 0x7c,
574 0x7f, 0x3d, 0x7a, 0x08, 602 0x7f, 0x3d, 0x7a, 0x08,
575 0x00, 0x30, 0x45, 0x59, 603 0x00, 0x36, 0x5f, 0x59,
576 0x01, 0x30, 0x01, 0x30, 604 0x01, 0x36, 0x01, 0x30,
577 0x09, 0xea, 0x50, 0x59, 605 0x09, 0xea, 0x64, 0x59,
578 0x09, 0xea, 0x04, 0x00, 606 0x09, 0xea, 0x04, 0x00,
579 0x00, 0xe2, 0xf8, 0x41, 607 0x00, 0xe2, 0x14, 0x42,
580 0x01, 0xa4, 0x5d, 0x6c, 608 0x01, 0xa4, 0x95, 0x6c,
581 0x00, 0xe2, 0x30, 0x5c, 609 0x00, 0xe2, 0x68, 0x5c,
582 0x20, 0x33, 0x67, 0x02, 610 0x20, 0x39, 0x73, 0x02,
583 0x01, 0x00, 0x60, 0x32, 611 0x01, 0x00, 0x6c, 0x32,
584 0x02, 0xa6, 0x82, 0x7c, 612 0x02, 0xa6, 0xba, 0x7c,
585 0x00, 0xe2, 0x46, 0x5c, 613 0x00, 0xe2, 0x7e, 0x5c,
586 0x00, 0xe2, 0x56, 0x58, 614 0x00, 0xe2, 0x76, 0x58,
587 0x00, 0xe2, 0x66, 0x58, 615 0x00, 0xe2, 0x86, 0x58,
588 0x00, 0xe2, 0x3a, 0x58, 616 0x00, 0xe2, 0x5a, 0x58,
589 0x00, 0x30, 0x45, 0x59, 617 0x00, 0x36, 0x5f, 0x59,
590 0x01, 0x30, 0x01, 0x30, 618 0x01, 0x36, 0x01, 0x30,
591 0x20, 0x19, 0x82, 0x6c, 619 0x20, 0x19, 0xba, 0x6c,
592 0x00, 0xe2, 0xb2, 0x5c, 620 0x00, 0xe2, 0xea, 0x5c,
593 0x04, 0x19, 0x9c, 0x6c, 621 0x04, 0x19, 0xd4, 0x6c,
594 0x02, 0x19, 0x32, 0x00, 622 0x02, 0x19, 0x32, 0x00,
595 0x01, 0x84, 0x9d, 0x7c, 623 0x01, 0x84, 0xd5, 0x7c,
596 0x01, 0x1b, 0x96, 0x7c, 624 0x01, 0x1b, 0xce, 0x7c,
597 0x01, 0x1a, 0x9c, 0x6c, 625 0x01, 0x1a, 0xd4, 0x6c,
598 0x00, 0xe2, 0x4c, 0x44, 626 0x00, 0xe2, 0x84, 0x44,
599 0x80, 0x4b, 0xa2, 0x6c, 627 0x80, 0x4b, 0xda, 0x6c,
600 0x01, 0x4c, 0x9e, 0x7c, 628 0x01, 0x4c, 0xd6, 0x7c,
601 0x03, 0x42, 0x4c, 0x6c, 629 0x03, 0x42, 0x84, 0x6c,
602 0x00, 0xe2, 0xe0, 0x5b, 630 0x00, 0xe2, 0x0a, 0x5c,
603 0x80, 0xf9, 0xf2, 0x01, 631 0x80, 0xf9, 0xf2, 0x01,
604 0x04, 0x33, 0xf9, 0x79, 632 0x04, 0x39, 0x15, 0x7a,
605 0x00, 0xe2, 0xf8, 0x41, 633 0x00, 0xe2, 0x14, 0x42,
606 0x08, 0x5d, 0xba, 0x6c, 634 0x08, 0x5d, 0xf2, 0x6c,
607 0x00, 0xe2, 0x56, 0x58, 635 0x00, 0xe2, 0x76, 0x58,
608 0x00, 0x30, 0x45, 0x59, 636 0x00, 0x36, 0x5f, 0x59,
609 0x01, 0x30, 0x01, 0x30, 637 0x01, 0x36, 0x01, 0x30,
610 0x02, 0x1b, 0xaa, 0x7c, 638 0x02, 0x1b, 0xe2, 0x7c,
611 0x08, 0x5d, 0xb8, 0x7c, 639 0x08, 0x5d, 0xf0, 0x7c,
612 0x03, 0x68, 0x00, 0x37, 640 0x03, 0x68, 0x00, 0x37,
613 0x01, 0x84, 0x09, 0x07, 641 0x01, 0x84, 0x09, 0x07,
614 0x80, 0x1b, 0xc4, 0x7c, 642 0x80, 0x1b, 0xfc, 0x7c,
615 0x80, 0x84, 0xc5, 0x6c, 643 0x80, 0x84, 0xfd, 0x6c,
616 0xff, 0x85, 0x0b, 0x1b, 644 0xff, 0x85, 0x0b, 0x1b,
617 0xff, 0x86, 0x0d, 0x23, 645 0xff, 0x86, 0x0d, 0x23,
618 0xff, 0x87, 0x0f, 0x23, 646 0xff, 0x87, 0x0f, 0x23,
619 0xf8, 0x1b, 0x08, 0x0b, 647 0xf8, 0x1b, 0x08, 0x0b,
620 0xff, 0xea, 0x06, 0x0b, 648 0xff, 0xea, 0x06, 0x0b,
621 0x03, 0x68, 0x00, 0x37, 649 0x03, 0x68, 0x00, 0x37,
622 0x00, 0xe2, 0xc4, 0x58, 650 0x00, 0xe2, 0xd6, 0x58,
623 0x10, 0xea, 0x18, 0x00, 651 0x10, 0xea, 0x18, 0x00,
624 0xf9, 0xd9, 0xb2, 0x0d, 652 0xf9, 0xd9, 0xb2, 0x0d,
625 0x01, 0xd9, 0xb2, 0x05, 653 0x01, 0xd9, 0xb2, 0x05,
626 0x01, 0x52, 0x48, 0x31, 654 0x01, 0x52, 0x48, 0x31,
627 0x20, 0xa4, 0xee, 0x7c, 655 0x20, 0xa4, 0x26, 0x7d,
628 0x20, 0x5b, 0xee, 0x7c, 656 0x20, 0x5b, 0x26, 0x7d,
629 0x80, 0xf9, 0xfc, 0x7c, 657 0x80, 0xf9, 0x34, 0x7d,
630 0x02, 0xea, 0xb4, 0x00, 658 0x02, 0xea, 0xb4, 0x00,
631 0x11, 0x00, 0x00, 0x10, 659 0x11, 0x00, 0x00, 0x10,
632 0x04, 0x19, 0x08, 0x7d, 660 0x04, 0x19, 0x40, 0x7d,
633 0xdf, 0x19, 0x32, 0x08, 661 0xdf, 0x19, 0x32, 0x08,
634 0x60, 0x5b, 0xe6, 0x6c, 662 0x60, 0x5b, 0x40, 0x6d,
635 0x01, 0x4c, 0xe2, 0x7c, 663 0x01, 0x4c, 0x1a, 0x7d,
636 0x20, 0x19, 0x32, 0x00, 664 0x20, 0x19, 0x32, 0x00,
637 0x01, 0xd9, 0xb2, 0x05, 665 0x01, 0xd9, 0xb2, 0x05,
638 0x02, 0xea, 0xb4, 0x00, 666 0x02, 0xea, 0xb4, 0x00,
639 0x01, 0xd9, 0xb2, 0x05, 667 0x01, 0xd9, 0xb2, 0x05,
640 0x10, 0x5b, 0x00, 0x6d, 668 0x10, 0x5b, 0x38, 0x6d,
641 0x08, 0x5b, 0x0a, 0x6d, 669 0x08, 0x5b, 0x42, 0x6d,
642 0x20, 0x5b, 0xfa, 0x6c, 670 0x20, 0x5b, 0x32, 0x6d,
643 0x02, 0x5b, 0x2a, 0x6d, 671 0x02, 0x5b, 0x62, 0x6d,
644 0x0e, 0xea, 0x50, 0x59, 672 0x0e, 0xea, 0x64, 0x59,
645 0x0e, 0xea, 0x04, 0x00, 673 0x0e, 0xea, 0x04, 0x00,
646 0x80, 0xf9, 0xea, 0x6c, 674 0x80, 0xf9, 0x22, 0x6d,
647 0xdf, 0x5c, 0xb8, 0x08, 675 0xdf, 0x5c, 0xb8, 0x08,
648 0x01, 0xd9, 0xb2, 0x05, 676 0x01, 0xd9, 0xb2, 0x05,
649 0x01, 0xa4, 0xe5, 0x6d, 677 0x01, 0xa4, 0x1d, 0x6e,
650 0x00, 0xe2, 0x30, 0x5c, 678 0x00, 0xe2, 0x68, 0x5c,
651 0x00, 0xe2, 0x34, 0x5d, 679 0x00, 0xe2, 0x6c, 0x5d,
652 0x01, 0x90, 0x21, 0x1b, 680 0x01, 0x90, 0x21, 0x1b,
653 0x01, 0xd9, 0xb2, 0x05, 681 0x01, 0xd9, 0xb2, 0x05,
654 0x00, 0xe2, 0x32, 0x5b, 682 0x00, 0xe2, 0x52, 0x5b,
655 0xf3, 0x96, 0xd5, 0x19, 683 0xf3, 0x96, 0xd5, 0x19,
656 0x00, 0xe2, 0x18, 0x55, 684 0x00, 0xe2, 0x50, 0x55,
657 0x80, 0x96, 0x19, 0x6d, 685 0x80, 0x96, 0x51, 0x6d,
658 0x0f, 0xea, 0x50, 0x59, 686 0x0f, 0xea, 0x64, 0x59,
659 0x0f, 0xea, 0x04, 0x00, 687 0x0f, 0xea, 0x04, 0x00,
660 0x00, 0xe2, 0x20, 0x45, 688 0x00, 0xe2, 0x58, 0x45,
661 0x04, 0x8c, 0xe1, 0x30, 689 0x04, 0x8c, 0xe1, 0x30,
662 0x01, 0xea, 0xf2, 0x00, 690 0x01, 0xea, 0xf2, 0x00,
663 0x02, 0xea, 0x36, 0x00, 691 0x02, 0xea, 0x36, 0x00,
664 0xa8, 0xea, 0x32, 0x00, 692 0xa8, 0xea, 0x32, 0x00,
665 0xff, 0x97, 0x27, 0x7d, 693 0xff, 0x97, 0x5f, 0x7d,
666 0x14, 0xea, 0x50, 0x59, 694 0x14, 0xea, 0x64, 0x59,
667 0x14, 0xea, 0x04, 0x00, 695 0x14, 0xea, 0x04, 0x00,
668 0x00, 0xe2, 0x96, 0x5d, 696 0x00, 0xe2, 0xce, 0x5d,
669 0x01, 0xd9, 0xb2, 0x05, 697 0x01, 0xd9, 0xb2, 0x05,
670 0x09, 0x80, 0xe1, 0x30, 698 0x09, 0x80, 0xe1, 0x30,
671 0x02, 0xea, 0x36, 0x00, 699 0x02, 0xea, 0x36, 0x00,
672 0xa8, 0xea, 0x32, 0x00, 700 0xa8, 0xea, 0x32, 0x00,
673 0x00, 0xe2, 0x8e, 0x5d, 701 0x00, 0xe2, 0xc6, 0x5d,
674 0x01, 0xd9, 0xb2, 0x05, 702 0x01, 0xd9, 0xb2, 0x05,
675 0x02, 0xa6, 0x44, 0x7d, 703 0x02, 0xa6, 0x7c, 0x7d,
676 0x00, 0xe2, 0x3e, 0x59, 704 0x00, 0xe2, 0x56, 0x59,
677 0x20, 0x5b, 0x52, 0x6d, 705 0x20, 0x5b, 0x8a, 0x6d,
678 0xfc, 0x42, 0x3e, 0x7d, 706 0xfc, 0x42, 0x76, 0x7d,
679 0x10, 0x40, 0x40, 0x6d, 707 0x10, 0x40, 0x78, 0x6d,
680 0x20, 0x4d, 0x42, 0x7d, 708 0x20, 0x4d, 0x7a, 0x7d,
681 0x08, 0x5d, 0x52, 0x6d, 709 0x08, 0x5d, 0x8a, 0x6d,
682 0x02, 0xa6, 0xe6, 0x6b, 710 0x02, 0xa6, 0x10, 0x6c,
683 0x00, 0xe2, 0x3e, 0x59, 711 0x00, 0xe2, 0x56, 0x59,
684 0x20, 0x5b, 0x52, 0x6d, 712 0x20, 0x5b, 0x8a, 0x6d,
685 0x01, 0x1b, 0x72, 0x6d, 713 0x01, 0x1b, 0xaa, 0x6d,
686 0xfc, 0x42, 0x4e, 0x7d, 714 0xfc, 0x42, 0x86, 0x7d,
687 0x10, 0x40, 0x50, 0x6d, 715 0x10, 0x40, 0x88, 0x6d,
688 0x20, 0x4d, 0x64, 0x78, 716 0x20, 0x4d, 0x84, 0x78,
689 0x08, 0x5d, 0x64, 0x78, 717 0x08, 0x5d, 0x84, 0x78,
690 0x02, 0x19, 0x32, 0x00, 718 0x02, 0x19, 0x32, 0x00,
691 0x01, 0x5b, 0x40, 0x31, 719 0x01, 0x5b, 0x40, 0x31,
692 0x00, 0xe2, 0xb2, 0x5c, 720 0x00, 0xe2, 0xea, 0x5c,
693 0x00, 0xe2, 0x9e, 0x5b, 721 0x00, 0xe2, 0xcc, 0x5b,
694 0x20, 0xea, 0xb6, 0x00, 722 0x20, 0xea, 0xb6, 0x00,
695 0x00, 0xe2, 0xe0, 0x5b, 723 0x00, 0xe2, 0x0a, 0x5c,
696 0x20, 0x5c, 0xb8, 0x00, 724 0x20, 0x5c, 0xb8, 0x00,
697 0x04, 0x19, 0x68, 0x6d, 725 0x04, 0x19, 0xa0, 0x6d,
698 0x01, 0x1a, 0x68, 0x6d, 726 0x01, 0x1a, 0xa0, 0x6d,
699 0x00, 0xe2, 0x3e, 0x59, 727 0x00, 0xe2, 0x56, 0x59,
700 0x01, 0x1a, 0x64, 0x78, 728 0x01, 0x1a, 0x84, 0x78,
701 0x80, 0xf9, 0xf2, 0x01, 729 0x80, 0xf9, 0xf2, 0x01,
702 0x20, 0xa0, 0xcc, 0x7d, 730 0x20, 0xa0, 0x04, 0x7e,
703 0xff, 0x90, 0x21, 0x1b, 731 0xff, 0x90, 0x21, 0x1b,
704 0x08, 0x92, 0x43, 0x6b, 732 0x08, 0x92, 0x63, 0x6b,
705 0x02, 0xea, 0xb4, 0x04, 733 0x02, 0xea, 0xb4, 0x04,
706 0x01, 0xa4, 0x49, 0x03, 734 0x01, 0xa4, 0x49, 0x03,
707 0x40, 0x5b, 0x82, 0x6d, 735 0x40, 0x5b, 0xba, 0x6d,
708 0x00, 0xe2, 0x3e, 0x59, 736 0x00, 0xe2, 0x56, 0x59,
709 0x40, 0x5b, 0x82, 0x6d, 737 0x40, 0x5b, 0xba, 0x6d,
710 0x04, 0x5d, 0xe6, 0x7d, 738 0x04, 0x5d, 0x1e, 0x7e,
711 0x01, 0x1a, 0xe6, 0x7d, 739 0x01, 0x1a, 0x1e, 0x7e,
712 0x20, 0x4d, 0x64, 0x78, 740 0x20, 0x4d, 0x84, 0x78,
713 0x40, 0x5b, 0xcc, 0x7d, 741 0x40, 0x5b, 0x04, 0x7e,
714 0x04, 0x5d, 0xe6, 0x7d, 742 0x04, 0x5d, 0x1e, 0x7e,
715 0x01, 0x1a, 0xe6, 0x7d, 743 0x01, 0x1a, 0x1e, 0x7e,
716 0x80, 0xf9, 0xf2, 0x01, 744 0x80, 0xf9, 0xf2, 0x01,
717 0xff, 0x90, 0x21, 0x1b, 745 0xff, 0x90, 0x21, 0x1b,
718 0x08, 0x92, 0x43, 0x6b, 746 0x08, 0x92, 0x63, 0x6b,
719 0x02, 0xea, 0xb4, 0x04, 747 0x02, 0xea, 0xb4, 0x04,
720 0x00, 0xe2, 0x3e, 0x59, 748 0x00, 0xe2, 0x56, 0x59,
721 0x01, 0x1b, 0x64, 0x78, 749 0x01, 0x1b, 0x84, 0x78,
722 0x80, 0xf9, 0xf2, 0x01, 750 0x80, 0xf9, 0xf2, 0x01,
723 0x02, 0xea, 0xb4, 0x04, 751 0x02, 0xea, 0xb4, 0x04,
724 0x00, 0xe2, 0x3e, 0x59, 752 0x00, 0xe2, 0x56, 0x59,
725 0x01, 0x1b, 0xaa, 0x6d, 753 0x01, 0x1b, 0xe2, 0x6d,
726 0x40, 0x5b, 0xb8, 0x7d, 754 0x40, 0x5b, 0xf0, 0x7d,
727 0x01, 0x1b, 0xaa, 0x6d, 755 0x01, 0x1b, 0xe2, 0x6d,
728 0x02, 0x19, 0x32, 0x00, 756 0x02, 0x19, 0x32, 0x00,
729 0x01, 0x1a, 0x64, 0x78, 757 0x01, 0x1a, 0x84, 0x78,
730 0x80, 0xf9, 0xf2, 0x01, 758 0x80, 0xf9, 0xf2, 0x01,
731 0xff, 0xea, 0x10, 0x03, 759 0xff, 0xea, 0x10, 0x03,
732 0x08, 0x92, 0x25, 0x03, 760 0x08, 0x92, 0x25, 0x03,
733 0x00, 0xe2, 0x42, 0x43, 761 0x00, 0xe2, 0x62, 0x43,
734 0x01, 0x1a, 0xb4, 0x7d, 762 0x01, 0x1a, 0xec, 0x7d,
735 0x40, 0x5b, 0xb0, 0x7d, 763 0x40, 0x5b, 0xe8, 0x7d,
736 0x01, 0x1a, 0x9e, 0x6d, 764 0x01, 0x1a, 0xd6, 0x6d,
737 0xfc, 0x42, 0x64, 0x78, 765 0xfc, 0x42, 0x84, 0x78,
738 0x01, 0x1a, 0xb8, 0x6d, 766 0x01, 0x1a, 0xf0, 0x6d,
739 0x10, 0xea, 0x50, 0x59, 767 0x10, 0xea, 0x64, 0x59,
740 0x10, 0xea, 0x04, 0x00, 768 0x10, 0xea, 0x04, 0x00,
741 0xfc, 0x42, 0x64, 0x78, 769 0xfc, 0x42, 0x84, 0x78,
742 0x10, 0x40, 0xbe, 0x6d, 770 0x10, 0x40, 0xf6, 0x6d,
743 0x20, 0x4d, 0x64, 0x78, 771 0x20, 0x4d, 0x84, 0x78,
744 0x40, 0x5b, 0x9e, 0x6d, 772 0x40, 0x5b, 0xd6, 0x6d,
745 0x01, 0x1a, 0x64, 0x78, 773 0x01, 0x1a, 0x84, 0x78,
746 0x01, 0x90, 0x21, 0x1b, 774 0x01, 0x90, 0x21, 0x1b,
747 0x30, 0x3f, 0xc0, 0x09, 775 0x30, 0x3f, 0xc0, 0x09,
748 0x30, 0xe0, 0x64, 0x60, 776 0x30, 0xe0, 0x84, 0x60,
749 0x40, 0x4b, 0x64, 0x68, 777 0x40, 0x4b, 0x84, 0x68,
750 0xff, 0xea, 0x52, 0x01, 778 0xff, 0xea, 0x52, 0x01,
751 0xee, 0x00, 0xd2, 0x6d, 779 0xee, 0x00, 0x0c, 0x6e,
752 0x80, 0xf9, 0xf2, 0x01, 780 0x80, 0xf9, 0xf2, 0x01,
753 0xff, 0x90, 0x21, 0x1b, 781 0xff, 0x90, 0x21, 0x1b,
754 0x02, 0xea, 0xb4, 0x00, 782 0x02, 0xea, 0xb4, 0x00,
755 0x20, 0xea, 0x9a, 0x00, 783 0x20, 0xea, 0x9a, 0x00,
756 0xf3, 0x42, 0xde, 0x6d, 784 0xf3, 0x42, 0x16, 0x6e,
757 0x12, 0xea, 0x50, 0x59, 785 0x12, 0xea, 0x64, 0x59,
758 0x12, 0xea, 0x04, 0x00, 786 0x12, 0xea, 0x04, 0x00,
759 0x00, 0xe2, 0xf8, 0x41, 787 0x00, 0xe2, 0x14, 0x42,
760 0x0d, 0xea, 0x50, 0x59, 788 0x0d, 0xea, 0x64, 0x59,
761 0x0d, 0xea, 0x04, 0x00, 789 0x0d, 0xea, 0x04, 0x00,
762 0x00, 0xe2, 0xf8, 0x41, 790 0x00, 0xe2, 0x14, 0x42,
763 0x01, 0x90, 0x21, 0x1b, 791 0x01, 0x90, 0x21, 0x1b,
764 0x11, 0xea, 0x50, 0x59, 792 0x11, 0xea, 0x64, 0x59,
765 0x11, 0xea, 0x04, 0x00, 793 0x11, 0xea, 0x04, 0x00,
766 0x00, 0xe2, 0x32, 0x5b, 794 0x00, 0xe2, 0x52, 0x5b,
767 0x08, 0x5a, 0xb4, 0x00, 795 0x08, 0x5a, 0xb4, 0x00,
768 0x00, 0xe2, 0x0c, 0x5e, 796 0x00, 0xe2, 0x44, 0x5e,
769 0xa8, 0xea, 0x32, 0x00, 797 0xa8, 0xea, 0x32, 0x00,
770 0x00, 0xe2, 0x3e, 0x59, 798 0x00, 0xe2, 0x56, 0x59,
771 0x80, 0x1a, 0xfa, 0x7d, 799 0x80, 0x1a, 0x32, 0x7e,
772 0x00, 0xe2, 0x0c, 0x5e, 800 0x00, 0xe2, 0x44, 0x5e,
773 0x80, 0x19, 0x32, 0x00, 801 0x80, 0x19, 0x32, 0x00,
774 0x40, 0x5b, 0x00, 0x6e, 802 0x40, 0x5b, 0x38, 0x6e,
775 0x08, 0x5a, 0x00, 0x7e, 803 0x08, 0x5a, 0x38, 0x7e,
776 0x20, 0x4d, 0x64, 0x78, 804 0x20, 0x4d, 0x84, 0x78,
777 0x02, 0x84, 0x09, 0x03, 805 0x02, 0x84, 0x09, 0x03,
778 0x40, 0x5b, 0xcc, 0x7d, 806 0x40, 0x5b, 0x04, 0x7e,
779 0xff, 0x90, 0x21, 0x1b, 807 0xff, 0x90, 0x21, 0x1b,
780 0x80, 0xf9, 0xf2, 0x01, 808 0x80, 0xf9, 0xf2, 0x01,
781 0x08, 0x92, 0x43, 0x6b, 809 0x08, 0x92, 0x63, 0x6b,
782 0x02, 0xea, 0xb4, 0x04, 810 0x02, 0xea, 0xb4, 0x04,
783 0x01, 0x38, 0xe1, 0x30, 811 0x01, 0x40, 0xe1, 0x30,
784 0x05, 0x39, 0xe3, 0x98, 812 0x05, 0x41, 0xe3, 0x98,
785 0x01, 0xe0, 0xf4, 0x31, 813 0x01, 0xe0, 0xf4, 0x31,
786 0xff, 0xea, 0xc0, 0x09, 814 0xff, 0xea, 0xc0, 0x09,
787 0x00, 0x3a, 0xe5, 0x20, 815 0x00, 0x42, 0xe5, 0x20,
788 0x00, 0x3b, 0xe7, 0x20, 816 0x00, 0x43, 0xe7, 0x20,
789 0x01, 0xfa, 0xc0, 0x31, 817 0x01, 0xfa, 0xc0, 0x31,
790 0x04, 0xea, 0xe8, 0x30, 818 0x04, 0xea, 0xe8, 0x30,
791 0xff, 0xea, 0xf0, 0x08, 819 0xff, 0xea, 0xf0, 0x08,
@@ -794,12 +822,20 @@ static uint8_t seqprog[] = {
794}; 822};
795 823
796typedef int ahd_patch_func_t (struct ahd_softc *ahd); 824typedef int ahd_patch_func_t (struct ahd_softc *ahd);
825static ahd_patch_func_t ahd_patch23_func;
826
827static int
828ahd_patch23_func(struct ahd_softc *ahd)
829{
830 return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0);
831}
832
797static ahd_patch_func_t ahd_patch22_func; 833static ahd_patch_func_t ahd_patch22_func;
798 834
799static int 835static int
800ahd_patch22_func(struct ahd_softc *ahd) 836ahd_patch22_func(struct ahd_softc *ahd)
801{ 837{
802 return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0); 838 return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) == 0);
803} 839}
804 840
805static ahd_patch_func_t ahd_patch21_func; 841static ahd_patch_func_t ahd_patch21_func;
@@ -807,7 +843,7 @@ static ahd_patch_func_t ahd_patch21_func;
807static int 843static int
808ahd_patch21_func(struct ahd_softc *ahd) 844ahd_patch21_func(struct ahd_softc *ahd)
809{ 845{
810 return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) == 0); 846 return ((ahd->flags & AHD_INITIATORROLE) != 0);
811} 847}
812 848
813static ahd_patch_func_t ahd_patch20_func; 849static ahd_patch_func_t ahd_patch20_func;
@@ -815,7 +851,7 @@ static ahd_patch_func_t ahd_patch20_func;
815static int 851static int
816ahd_patch20_func(struct ahd_softc *ahd) 852ahd_patch20_func(struct ahd_softc *ahd)
817{ 853{
818 return ((ahd->features & AHD_RTI) == 0); 854 return ((ahd->flags & AHD_TARGETROLE) != 0);
819} 855}
820 856
821static ahd_patch_func_t ahd_patch19_func; 857static ahd_patch_func_t ahd_patch19_func;
@@ -823,7 +859,7 @@ static ahd_patch_func_t ahd_patch19_func;
823static int 859static int
824ahd_patch19_func(struct ahd_softc *ahd) 860ahd_patch19_func(struct ahd_softc *ahd)
825{ 861{
826 return ((ahd->flags & AHD_INITIATORROLE) != 0); 862 return ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0);
827} 863}
828 864
829static ahd_patch_func_t ahd_patch18_func; 865static ahd_patch_func_t ahd_patch18_func;
@@ -831,7 +867,7 @@ static ahd_patch_func_t ahd_patch18_func;
831static int 867static int
832ahd_patch18_func(struct ahd_softc *ahd) 868ahd_patch18_func(struct ahd_softc *ahd)
833{ 869{
834 return ((ahd->flags & AHD_TARGETROLE) != 0); 870 return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0);
835} 871}
836 872
837static ahd_patch_func_t ahd_patch17_func; 873static ahd_patch_func_t ahd_patch17_func;
@@ -839,7 +875,7 @@ static ahd_patch_func_t ahd_patch17_func;
839static int 875static int
840ahd_patch17_func(struct ahd_softc *ahd) 876ahd_patch17_func(struct ahd_softc *ahd)
841{ 877{
842 return ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0); 878 return ((ahd->flags & AHD_39BIT_ADDRESSING) != 0);
843} 879}
844 880
845static ahd_patch_func_t ahd_patch16_func; 881static ahd_patch_func_t ahd_patch16_func;
@@ -847,7 +883,7 @@ static ahd_patch_func_t ahd_patch16_func;
847static int 883static int
848ahd_patch16_func(struct ahd_softc *ahd) 884ahd_patch16_func(struct ahd_softc *ahd)
849{ 885{
850 return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0); 886 return ((ahd->flags & AHD_64BIT_ADDRESSING) != 0);
851} 887}
852 888
853static ahd_patch_func_t ahd_patch15_func; 889static ahd_patch_func_t ahd_patch15_func;
@@ -855,7 +891,7 @@ static ahd_patch_func_t ahd_patch15_func;
855static int 891static int
856ahd_patch15_func(struct ahd_softc *ahd) 892ahd_patch15_func(struct ahd_softc *ahd)
857{ 893{
858 return ((ahd->flags & AHD_39BIT_ADDRESSING) != 0); 894 return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) == 0);
859} 895}
860 896
861static ahd_patch_func_t ahd_patch14_func; 897static ahd_patch_func_t ahd_patch14_func;
@@ -863,7 +899,7 @@ static ahd_patch_func_t ahd_patch14_func;
863static int 899static int
864ahd_patch14_func(struct ahd_softc *ahd) 900ahd_patch14_func(struct ahd_softc *ahd)
865{ 901{
866 return ((ahd->flags & AHD_64BIT_ADDRESSING) != 0); 902 return ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0);
867} 903}
868 904
869static ahd_patch_func_t ahd_patch13_func; 905static ahd_patch_func_t ahd_patch13_func;
@@ -871,7 +907,7 @@ static ahd_patch_func_t ahd_patch13_func;
871static int 907static int
872ahd_patch13_func(struct ahd_softc *ahd) 908ahd_patch13_func(struct ahd_softc *ahd)
873{ 909{
874 return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) == 0); 910 return ((ahd->features & AHD_RTI) == 0);
875} 911}
876 912
877static ahd_patch_func_t ahd_patch12_func; 913static ahd_patch_func_t ahd_patch12_func;
@@ -879,7 +915,7 @@ static ahd_patch_func_t ahd_patch12_func;
879static int 915static int
880ahd_patch12_func(struct ahd_softc *ahd) 916ahd_patch12_func(struct ahd_softc *ahd)
881{ 917{
882 return ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0); 918 return ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0);
883} 919}
884 920
885static ahd_patch_func_t ahd_patch11_func; 921static ahd_patch_func_t ahd_patch11_func;
@@ -887,7 +923,7 @@ static ahd_patch_func_t ahd_patch11_func;
887static int 923static int
888ahd_patch11_func(struct ahd_softc *ahd) 924ahd_patch11_func(struct ahd_softc *ahd)
889{ 925{
890 return ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0); 926 return ((ahd->bugs & AHD_BUSFREEREV_BUG) == 0);
891} 927}
892 928
893static ahd_patch_func_t ahd_patch10_func; 929static ahd_patch_func_t ahd_patch10_func;
@@ -895,7 +931,7 @@ static ahd_patch_func_t ahd_patch10_func;
895static int 931static int
896ahd_patch10_func(struct ahd_softc *ahd) 932ahd_patch10_func(struct ahd_softc *ahd)
897{ 933{
898 return ((ahd->bugs & AHD_BUSFREEREV_BUG) == 0); 934 return ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0);
899} 935}
900 936
901static ahd_patch_func_t ahd_patch9_func; 937static ahd_patch_func_t ahd_patch9_func;
@@ -903,7 +939,7 @@ static ahd_patch_func_t ahd_patch9_func;
903static int 939static int
904ahd_patch9_func(struct ahd_softc *ahd) 940ahd_patch9_func(struct ahd_softc *ahd)
905{ 941{
906 return ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0); 942 return ((ahd->features & AHD_FAST_CDB_DELIVERY) != 0);
907} 943}
908 944
909static ahd_patch_func_t ahd_patch8_func; 945static ahd_patch_func_t ahd_patch8_func;
@@ -992,147 +1028,149 @@ static struct patch {
992 { ahd_patch0_func, 5, 1, 1 }, 1028 { ahd_patch0_func, 5, 1, 1 },
993 { ahd_patch2_func, 6, 1, 2 }, 1029 { ahd_patch2_func, 6, 1, 2 },
994 { ahd_patch0_func, 7, 1, 1 }, 1030 { ahd_patch0_func, 7, 1, 1 },
995 { ahd_patch3_func, 20, 5, 1 }, 1031 { ahd_patch3_func, 36, 5, 1 },
996 { ahd_patch2_func, 29, 1, 2 }, 1032 { ahd_patch2_func, 45, 1, 2 },
997 { ahd_patch0_func, 30, 1, 1 }, 1033 { ahd_patch0_func, 46, 1, 1 },
998 { ahd_patch1_func, 37, 1, 2 }, 1034 { ahd_patch1_func, 53, 1, 2 },
999 { ahd_patch0_func, 38, 1, 1 }, 1035 { ahd_patch0_func, 54, 1, 1 },
1000 { ahd_patch2_func, 43, 1, 2 }, 1036 { ahd_patch2_func, 59, 1, 2 },
1001 { ahd_patch0_func, 44, 1, 1 }, 1037 { ahd_patch0_func, 60, 1, 1 },
1002 { ahd_patch2_func, 47, 1, 2 }, 1038 { ahd_patch2_func, 63, 1, 2 },
1003 { ahd_patch0_func, 48, 1, 1 }, 1039 { ahd_patch0_func, 64, 1, 1 },
1004 { ahd_patch2_func, 51, 1, 2 }, 1040 { ahd_patch2_func, 67, 1, 2 },
1005 { ahd_patch0_func, 52, 1, 1 }, 1041 { ahd_patch0_func, 68, 1, 1 },
1006 { ahd_patch2_func, 65, 1, 2 }, 1042 { ahd_patch4_func, 116, 1, 1 },
1007 { ahd_patch0_func, 66, 1, 1 }, 1043 { ahd_patch2_func, 175, 3, 1 },
1008 { ahd_patch2_func, 69, 1, 2 }, 1044 { ahd_patch1_func, 178, 2, 1 },
1009 { ahd_patch0_func, 70, 1, 1 }, 1045 { ahd_patch5_func, 180, 1, 1 },
1010 { ahd_patch1_func, 73, 1, 2 }, 1046 { ahd_patch2_func, 189, 1, 2 },
1011 { ahd_patch0_func, 74, 1, 1 }, 1047 { ahd_patch0_func, 190, 1, 1 },
1012 { ahd_patch4_func, 107, 1, 1 }, 1048 { ahd_patch6_func, 191, 2, 2 },
1013 { ahd_patch2_func, 162, 6, 1 }, 1049 { ahd_patch0_func, 193, 6, 3 },
1014 { ahd_patch1_func, 168, 2, 1 }, 1050 { ahd_patch2_func, 196, 1, 2 },
1015 { ahd_patch5_func, 170, 1, 1 }, 1051 { ahd_patch0_func, 197, 1, 1 },
1016 { ahd_patch2_func, 179, 1, 2 }, 1052 { ahd_patch2_func, 200, 1, 2 },
1017 { ahd_patch0_func, 180, 1, 1 }, 1053 { ahd_patch0_func, 201, 1, 1 },
1018 { ahd_patch6_func, 181, 2, 2 }, 1054 { ahd_patch3_func, 203, 1, 1 },
1019 { ahd_patch0_func, 183, 6, 3 }, 1055 { ahd_patch7_func, 204, 3, 1 },
1020 { ahd_patch2_func, 186, 1, 2 }, 1056 { ahd_patch3_func, 213, 1, 1 },
1021 { ahd_patch0_func, 187, 1, 1 }, 1057 { ahd_patch5_func, 214, 16, 2 },
1022 { ahd_patch2_func, 190, 1, 2 }, 1058 { ahd_patch0_func, 230, 1, 1 },
1023 { ahd_patch0_func, 191, 1, 1 }, 1059 { ahd_patch8_func, 250, 2, 1 },
1024 { ahd_patch7_func, 193, 2, 1 }, 1060 { ahd_patch1_func, 254, 1, 2 },
1025 { ahd_patch5_func, 201, 16, 2 }, 1061 { ahd_patch0_func, 255, 1, 1 },
1026 { ahd_patch0_func, 217, 1, 1 }, 1062 { ahd_patch7_func, 258, 3, 1 },
1027 { ahd_patch8_func, 237, 2, 1 }, 1063 { ahd_patch1_func, 273, 1, 2 },
1028 { ahd_patch1_func, 241, 1, 2 }, 1064 { ahd_patch0_func, 274, 1, 1 },
1029 { ahd_patch0_func, 242, 1, 1 }, 1065 { ahd_patch1_func, 277, 1, 2 },
1030 { ahd_patch7_func, 245, 2, 1 }, 1066 { ahd_patch0_func, 278, 1, 1 },
1031 { ahd_patch1_func, 259, 1, 2 }, 1067 { ahd_patch2_func, 281, 1, 2 },
1032 { ahd_patch0_func, 260, 1, 1 }, 1068 { ahd_patch0_func, 282, 1, 1 },
1033 { ahd_patch1_func, 263, 1, 2 }, 1069 { ahd_patch9_func, 295, 2, 2 },
1034 { ahd_patch0_func, 264, 1, 1 }, 1070 { ahd_patch0_func, 297, 1, 1 },
1035 { ahd_patch2_func, 267, 1, 2 }, 1071 { ahd_patch1_func, 339, 1, 2 },
1036 { ahd_patch0_func, 268, 1, 1 }, 1072 { ahd_patch0_func, 340, 1, 1 },
1037 { ahd_patch1_func, 323, 1, 2 }, 1073 { ahd_patch2_func, 348, 1, 2 },
1038 { ahd_patch0_func, 324, 1, 1 }, 1074 { ahd_patch0_func, 349, 1, 1 },
1039 { ahd_patch2_func, 332, 1, 2 }, 1075 { ahd_patch2_func, 352, 1, 2 },
1040 { ahd_patch0_func, 333, 1, 1 }, 1076 { ahd_patch0_func, 353, 1, 1 },
1041 { ahd_patch2_func, 336, 1, 2 }, 1077 { ahd_patch1_func, 359, 1, 2 },
1042 { ahd_patch0_func, 337, 1, 1 }, 1078 { ahd_patch0_func, 360, 1, 1 },
1043 { ahd_patch1_func, 343, 1, 2 }, 1079 { ahd_patch1_func, 362, 1, 2 },
1044 { ahd_patch0_func, 344, 1, 1 }, 1080 { ahd_patch0_func, 363, 1, 1 },
1045 { ahd_patch1_func, 346, 1, 2 }, 1081 { ahd_patch10_func, 382, 1, 1 },
1046 { ahd_patch0_func, 347, 1, 1 }, 1082 { ahd_patch10_func, 385, 1, 1 },
1047 { ahd_patch9_func, 366, 1, 1 }, 1083 { ahd_patch10_func, 387, 1, 1 },
1048 { ahd_patch9_func, 369, 1, 1 }, 1084 { ahd_patch10_func, 399, 1, 1 },
1049 { ahd_patch9_func, 371, 1, 1 }, 1085 { ahd_patch1_func, 409, 1, 2 },
1050 { ahd_patch9_func, 383, 1, 1 }, 1086 { ahd_patch0_func, 410, 1, 1 },
1051 { ahd_patch1_func, 393, 1, 2 }, 1087 { ahd_patch1_func, 412, 1, 2 },
1052 { ahd_patch0_func, 394, 1, 1 }, 1088 { ahd_patch0_func, 413, 1, 1 },
1053 { ahd_patch1_func, 396, 1, 2 }, 1089 { ahd_patch1_func, 421, 1, 2 },
1054 { ahd_patch0_func, 397, 1, 1 }, 1090 { ahd_patch0_func, 422, 1, 1 },
1055 { ahd_patch1_func, 405, 1, 2 }, 1091 { ahd_patch2_func, 435, 1, 2 },
1056 { ahd_patch0_func, 406, 1, 1 }, 1092 { ahd_patch0_func, 436, 1, 1 },
1057 { ahd_patch2_func, 419, 1, 2 }, 1093 { ahd_patch11_func, 472, 1, 1 },
1058 { ahd_patch0_func, 420, 1, 1 }, 1094 { ahd_patch1_func, 480, 1, 2 },
1059 { ahd_patch10_func, 450, 1, 1 }, 1095 { ahd_patch0_func, 481, 1, 1 },
1060 { ahd_patch1_func, 457, 1, 2 }, 1096 { ahd_patch2_func, 493, 1, 2 },
1061 { ahd_patch0_func, 458, 1, 1 }, 1097 { ahd_patch0_func, 494, 1, 1 },
1062 { ahd_patch2_func, 470, 1, 2 }, 1098 { ahd_patch12_func, 497, 6, 2 },
1063 { ahd_patch0_func, 471, 1, 1 }, 1099 { ahd_patch0_func, 503, 1, 1 },
1064 { ahd_patch11_func, 476, 6, 2 }, 1100 { ahd_patch13_func, 524, 7, 1 },
1065 { ahd_patch0_func, 482, 1, 1 }, 1101 { ahd_patch14_func, 533, 1, 1 },
1066 { ahd_patch12_func, 505, 1, 1 }, 1102 { ahd_patch15_func, 542, 1, 1 },
1067 { ahd_patch13_func, 514, 1, 1 }, 1103 { ahd_patch16_func, 543, 1, 2 },
1068 { ahd_patch14_func, 515, 1, 2 }, 1104 { ahd_patch0_func, 544, 1, 1 },
1069 { ahd_patch0_func, 516, 1, 1 }, 1105 { ahd_patch17_func, 547, 1, 1 },
1070 { ahd_patch15_func, 519, 1, 1 }, 1106 { ahd_patch16_func, 548, 1, 1 },
1071 { ahd_patch14_func, 520, 1, 1 }, 1107 { ahd_patch18_func, 559, 1, 2 },
1072 { ahd_patch16_func, 531, 1, 2 }, 1108 { ahd_patch0_func, 560, 1, 1 },
1073 { ahd_patch0_func, 532, 1, 1 }, 1109 { ahd_patch1_func, 579, 1, 2 },
1074 { ahd_patch1_func, 551, 1, 2 }, 1110 { ahd_patch0_func, 580, 1, 1 },
1075 { ahd_patch0_func, 552, 1, 1 }, 1111 { ahd_patch1_func, 583, 1, 2 },
1076 { ahd_patch1_func, 555, 1, 2 }, 1112 { ahd_patch0_func, 584, 1, 1 },
1077 { ahd_patch0_func, 556, 1, 1 }, 1113 { ahd_patch2_func, 589, 1, 2 },
1078 { ahd_patch2_func, 561, 1, 2 }, 1114 { ahd_patch0_func, 590, 1, 1 },
1079 { ahd_patch0_func, 562, 1, 1 }, 1115 { ahd_patch2_func, 594, 1, 2 },
1080 { ahd_patch2_func, 566, 1, 2 }, 1116 { ahd_patch0_func, 595, 1, 1 },
1081 { ahd_patch0_func, 567, 1, 1 }, 1117 { ahd_patch1_func, 596, 1, 2 },
1082 { ahd_patch1_func, 568, 1, 2 }, 1118 { ahd_patch0_func, 597, 1, 1 },
1083 { ahd_patch0_func, 569, 1, 1 }, 1119 { ahd_patch2_func, 608, 1, 2 },
1084 { ahd_patch2_func, 580, 1, 2 }, 1120 { ahd_patch0_func, 609, 1, 1 },
1085 { ahd_patch0_func, 581, 1, 1 }, 1121 { ahd_patch19_func, 613, 1, 1 },
1086 { ahd_patch17_func, 585, 1, 1 }, 1122 { ahd_patch20_func, 618, 1, 1 },
1087 { ahd_patch18_func, 590, 1, 1 }, 1123 { ahd_patch21_func, 619, 2, 1 },
1088 { ahd_patch19_func, 591, 2, 1 }, 1124 { ahd_patch20_func, 623, 1, 2 },
1089 { ahd_patch18_func, 595, 1, 2 }, 1125 { ahd_patch0_func, 624, 1, 1 },
1090 { ahd_patch0_func, 596, 1, 1 }, 1126 { ahd_patch2_func, 627, 1, 2 },
1091 { ahd_patch2_func, 599, 1, 2 }, 1127 { ahd_patch0_func, 628, 1, 1 },
1092 { ahd_patch0_func, 600, 1, 1 }, 1128 { ahd_patch2_func, 643, 1, 2 },
1093 { ahd_patch2_func, 615, 1, 2 }, 1129 { ahd_patch0_func, 644, 1, 1 },
1094 { ahd_patch0_func, 616, 1, 1 }, 1130 { ahd_patch13_func, 645, 14, 1 },
1095 { ahd_patch20_func, 617, 14, 1 }, 1131 { ahd_patch1_func, 663, 1, 2 },
1096 { ahd_patch1_func, 635, 1, 2 }, 1132 { ahd_patch0_func, 664, 1, 1 },
1097 { ahd_patch0_func, 636, 1, 1 }, 1133 { ahd_patch13_func, 665, 1, 1 },
1098 { ahd_patch20_func, 637, 1, 1 }, 1134 { ahd_patch1_func, 677, 1, 2 },
1099 { ahd_patch1_func, 649, 1, 2 }, 1135 { ahd_patch0_func, 678, 1, 1 },
1100 { ahd_patch0_func, 650, 1, 1 }, 1136 { ahd_patch1_func, 685, 1, 2 },
1101 { ahd_patch1_func, 657, 1, 2 }, 1137 { ahd_patch0_func, 686, 1, 1 },
1102 { ahd_patch0_func, 658, 1, 1 }, 1138 { ahd_patch19_func, 709, 1, 1 },
1103 { ahd_patch17_func, 681, 1, 1 }, 1139 { ahd_patch19_func, 747, 1, 1 },
1104 { ahd_patch17_func, 719, 1, 1 }, 1140 { ahd_patch1_func, 758, 1, 2 },
1105 { ahd_patch1_func, 730, 1, 2 }, 1141 { ahd_patch0_func, 759, 1, 1 },
1106 { ahd_patch0_func, 731, 1, 1 }, 1142 { ahd_patch1_func, 776, 1, 2 },
1107 { ahd_patch1_func, 748, 1, 2 }, 1143 { ahd_patch0_func, 777, 1, 1 },
1108 { ahd_patch0_func, 749, 1, 1 }, 1144 { ahd_patch1_func, 779, 1, 2 },
1109 { ahd_patch1_func, 751, 1, 2 }, 1145 { ahd_patch0_func, 780, 1, 1 },
1110 { ahd_patch0_func, 752, 1, 1 }, 1146 { ahd_patch1_func, 783, 1, 2 },
1111 { ahd_patch1_func, 755, 1, 2 }, 1147 { ahd_patch0_func, 784, 1, 1 },
1112 { ahd_patch0_func, 756, 1, 1 }, 1148 { ahd_patch22_func, 786, 1, 2 },
1113 { ahd_patch21_func, 758, 1, 2 }, 1149 { ahd_patch0_func, 787, 2, 1 },
1114 { ahd_patch0_func, 759, 2, 1 }, 1150 { ahd_patch23_func, 790, 4, 2 },
1115 { ahd_patch22_func, 762, 4, 2 }, 1151 { ahd_patch0_func, 794, 1, 1 },
1116 { ahd_patch0_func, 766, 1, 1 }, 1152 { ahd_patch23_func, 802, 11, 1 }
1117 { ahd_patch22_func, 774, 11, 1 }
1118}; 1153};
1119 1154
1120static struct cs { 1155static struct cs {
1121 uint16_t begin; 1156 uint16_t begin;
1122 uint16_t end; 1157 uint16_t end;
1123} critical_sections[] = { 1158} critical_sections[] = {
1124 { 11, 12 }, 1159 { 17, 28 },
1125 { 13, 14 }, 1160 { 29, 30 },
1126 { 29, 42 }, 1161 { 47, 58 },
1127 { 56, 59 }, 1162 { 61, 63 },
1128 { 101, 128 }, 1163 { 65, 66 },
1129 { 129, 157 }, 1164 { 72, 92 },
1130 { 159, 162 }, 1165 { 110, 137 },
1131 { 170, 178 }, 1166 { 138, 175 },
1132 { 201, 250 }, 1167 { 180, 188 },
1133 { 681, 697 }, 1168 { 213, 264 },
1134 { 697, 711 }, 1169 { 425, 433 },
1135 { 721, 725 } 1170 { 443, 445 },
1171 { 448, 457 },
1172 { 709, 739 },
1173 { 749, 753 }
1136}; 1174};
1137 1175
1138static const int num_critical_sections = sizeof(critical_sections) 1176static const int num_critical_sections = sizeof(critical_sections)
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index fd389e9f9460..051970efba68 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -375,7 +375,7 @@ static void ahc_linux_queue_cmd_complete(struct ahc_softc *ahc,
375 struct scsi_cmnd *cmd); 375 struct scsi_cmnd *cmd);
376static void ahc_linux_sem_timeout(u_long arg); 376static void ahc_linux_sem_timeout(u_long arg);
377static void ahc_linux_freeze_simq(struct ahc_softc *ahc); 377static void ahc_linux_freeze_simq(struct ahc_softc *ahc);
378static void ahc_linux_release_simq(u_long arg); 378static void ahc_linux_release_simq(struct ahc_softc *ahc);
379static int ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag); 379static int ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag);
380static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc); 380static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc);
381static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc, 381static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc,
@@ -1073,7 +1073,6 @@ ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *templa
1073 return (ENOMEM); 1073 return (ENOMEM);
1074 1074
1075 *((struct ahc_softc **)host->hostdata) = ahc; 1075 *((struct ahc_softc **)host->hostdata) = ahc;
1076 ahc_lock(ahc, &s);
1077 ahc->platform_data->host = host; 1076 ahc->platform_data->host = host;
1078 host->can_queue = AHC_MAX_QUEUE; 1077 host->can_queue = AHC_MAX_QUEUE;
1079 host->cmd_per_lun = 2; 1078 host->cmd_per_lun = 2;
@@ -1084,7 +1083,9 @@ ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *templa
1084 host->max_lun = AHC_NUM_LUNS; 1083 host->max_lun = AHC_NUM_LUNS;
1085 host->max_channel = (ahc->features & AHC_TWIN) ? 1 : 0; 1084 host->max_channel = (ahc->features & AHC_TWIN) ? 1 : 0;
1086 host->sg_tablesize = AHC_NSEG; 1085 host->sg_tablesize = AHC_NSEG;
1086 ahc_lock(ahc, &s);
1087 ahc_set_unit(ahc, ahc_linux_unit++); 1087 ahc_set_unit(ahc, ahc_linux_unit++);
1088 ahc_unlock(ahc, &s);
1088 sprintf(buf, "scsi%d", host->host_no); 1089 sprintf(buf, "scsi%d", host->host_no);
1089 new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT); 1090 new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
1090 if (new_name != NULL) { 1091 if (new_name != NULL) {
@@ -1094,7 +1095,6 @@ ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *templa
1094 host->unique_id = ahc->unit; 1095 host->unique_id = ahc->unit;
1095 ahc_linux_initialize_scsi_bus(ahc); 1096 ahc_linux_initialize_scsi_bus(ahc);
1096 ahc_intr_enable(ahc, TRUE); 1097 ahc_intr_enable(ahc, TRUE);
1097 ahc_unlock(ahc, &s);
1098 1098
1099 host->transportt = ahc_linux_transport_template; 1099 host->transportt = ahc_linux_transport_template;
1100 1100
@@ -1120,10 +1120,13 @@ ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc)
1120{ 1120{
1121 int i; 1121 int i;
1122 int numtarg; 1122 int numtarg;
1123 unsigned long s;
1123 1124
1124 i = 0; 1125 i = 0;
1125 numtarg = 0; 1126 numtarg = 0;
1126 1127
1128 ahc_lock(ahc, &s);
1129
1127 if (aic7xxx_no_reset != 0) 1130 if (aic7xxx_no_reset != 0)
1128 ahc->flags &= ~(AHC_RESET_BUS_A|AHC_RESET_BUS_B); 1131 ahc->flags &= ~(AHC_RESET_BUS_A|AHC_RESET_BUS_B);
1129 1132
@@ -1170,16 +1173,12 @@ ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc)
1170 ahc_update_neg_request(ahc, &devinfo, tstate, 1173 ahc_update_neg_request(ahc, &devinfo, tstate,
1171 tinfo, AHC_NEG_ALWAYS); 1174 tinfo, AHC_NEG_ALWAYS);
1172 } 1175 }
1176 ahc_unlock(ahc, &s);
1173 /* Give the bus some time to recover */ 1177 /* Give the bus some time to recover */
1174 if ((ahc->flags & (AHC_RESET_BUS_A|AHC_RESET_BUS_B)) != 0) { 1178 if ((ahc->flags & (AHC_RESET_BUS_A|AHC_RESET_BUS_B)) != 0) {
1175 ahc_linux_freeze_simq(ahc); 1179 ahc_linux_freeze_simq(ahc);
1176 init_timer(&ahc->platform_data->reset_timer); 1180 msleep(AIC7XXX_RESET_DELAY);
1177 ahc->platform_data->reset_timer.data = (u_long)ahc; 1181 ahc_linux_release_simq(ahc);
1178 ahc->platform_data->reset_timer.expires =
1179 jiffies + (AIC7XXX_RESET_DELAY * HZ)/1000;
1180 ahc->platform_data->reset_timer.function =
1181 ahc_linux_release_simq;
1182 add_timer(&ahc->platform_data->reset_timer);
1183 } 1182 }
1184} 1183}
1185 1184
@@ -2059,6 +2058,9 @@ ahc_linux_sem_timeout(u_long arg)
2059static void 2058static void
2060ahc_linux_freeze_simq(struct ahc_softc *ahc) 2059ahc_linux_freeze_simq(struct ahc_softc *ahc)
2061{ 2060{
2061 unsigned long s;
2062
2063 ahc_lock(ahc, &s);
2062 ahc->platform_data->qfrozen++; 2064 ahc->platform_data->qfrozen++;
2063 if (ahc->platform_data->qfrozen == 1) { 2065 if (ahc->platform_data->qfrozen == 1) {
2064 scsi_block_requests(ahc->platform_data->host); 2066 scsi_block_requests(ahc->platform_data->host);
@@ -2068,17 +2070,15 @@ ahc_linux_freeze_simq(struct ahc_softc *ahc)
2068 CAM_LUN_WILDCARD, SCB_LIST_NULL, 2070 CAM_LUN_WILDCARD, SCB_LIST_NULL,
2069 ROLE_INITIATOR, CAM_REQUEUE_REQ); 2071 ROLE_INITIATOR, CAM_REQUEUE_REQ);
2070 } 2072 }
2073 ahc_unlock(ahc, &s);
2071} 2074}
2072 2075
2073static void 2076static void
2074ahc_linux_release_simq(u_long arg) 2077ahc_linux_release_simq(struct ahc_softc *ahc)
2075{ 2078{
2076 struct ahc_softc *ahc;
2077 u_long s; 2079 u_long s;
2078 int unblock_reqs; 2080 int unblock_reqs;
2079 2081
2080 ahc = (struct ahc_softc *)arg;
2081
2082 unblock_reqs = 0; 2082 unblock_reqs = 0;
2083 ahc_lock(ahc, &s); 2083 ahc_lock(ahc, &s);
2084 if (ahc->platform_data->qfrozen > 0) 2084 if (ahc->platform_data->qfrozen > 0)
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h
index f2a95447142c..e0edacae895f 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.h
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h
@@ -223,9 +223,6 @@ int ahc_dmamap_unload(struct ahc_softc *, bus_dma_tag_t, bus_dmamap_t);
223 */ 223 */
224#define ahc_dmamap_sync(ahc, dma_tag, dmamap, offset, len, op) 224#define ahc_dmamap_sync(ahc, dma_tag, dmamap, offset, len, op)
225 225
226/************************** Timer DataStructures ******************************/
227typedef struct timer_list ahc_timer_t;
228
229/********************************** Includes **********************************/ 226/********************************** Includes **********************************/
230#ifdef CONFIG_AIC7XXX_REG_PRETTY_PRINT 227#ifdef CONFIG_AIC7XXX_REG_PRETTY_PRINT
231#define AIC_DEBUG_REGISTERS 1 228#define AIC_DEBUG_REGISTERS 1
@@ -235,30 +232,9 @@ typedef struct timer_list ahc_timer_t;
235#include "aic7xxx.h" 232#include "aic7xxx.h"
236 233
237/***************************** Timer Facilities *******************************/ 234/***************************** Timer Facilities *******************************/
238#define ahc_timer_init init_timer
239#define ahc_timer_stop del_timer_sync
240typedef void ahc_linux_callback_t (u_long);
241static __inline void ahc_timer_reset(ahc_timer_t *timer, int usec,
242 ahc_callback_t *func, void *arg);
243static __inline void ahc_scb_timer_reset(struct scb *scb, u_int usec);
244
245static __inline void
246ahc_timer_reset(ahc_timer_t *timer, int usec, ahc_callback_t *func, void *arg)
247{
248 struct ahc_softc *ahc;
249
250 ahc = (struct ahc_softc *)arg;
251 del_timer(timer);
252 timer->data = (u_long)arg;
253 timer->expires = jiffies + (usec * HZ)/1000000;
254 timer->function = (ahc_linux_callback_t*)func;
255 add_timer(timer);
256}
257
258static __inline void 235static __inline void
259ahc_scb_timer_reset(struct scb *scb, u_int usec) 236ahc_scb_timer_reset(struct scb *scb, u_int usec)
260{ 237{
261 mod_timer(&scb->io_ctx->eh_timeout, jiffies + (usec * HZ)/1000000);
262} 238}
263 239
264/***************************** SMP support ************************************/ 240/***************************** SMP support ************************************/
@@ -393,7 +369,6 @@ struct ahc_platform_data {
393 369
394 spinlock_t spin_lock; 370 spinlock_t spin_lock;
395 u_int qfrozen; 371 u_int qfrozen;
396 struct timer_list reset_timer;
397 struct semaphore eh_sem; 372 struct semaphore eh_sem;
398 struct Scsi_Host *host; /* pointer to scsi host */ 373 struct Scsi_Host *host; /* pointer to scsi host */
399#define AHC_LINUX_NOIRQ ((uint32_t)~0) 374#define AHC_LINUX_NOIRQ ((uint32_t)~0)
diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c
index b3b2e2237eb3..5f586140e057 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_pci.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c
@@ -39,9 +39,7 @@
39 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 39 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
40 * POSSIBILITY OF SUCH DAMAGES. 40 * POSSIBILITY OF SUCH DAMAGES.
41 * 41 *
42 * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#69 $ 42 * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#79 $
43 *
44 * $FreeBSD$
45 */ 43 */
46 44
47#ifdef __linux__ 45#ifdef __linux__
@@ -393,6 +391,12 @@ struct ahc_pci_identity ahc_pci_ident_table [] =
393 "Adaptec aic7892 Ultra160 SCSI adapter (ARO)", 391 "Adaptec aic7892 Ultra160 SCSI adapter (ARO)",
394 ahc_aic7892_setup 392 ahc_aic7892_setup
395 }, 393 },
394 {
395 ID_AHA_2915_30LP,
396 ID_ALL_MASK,
397 "Adaptec 2915/30LP Ultra160 SCSI adapter",
398 ahc_aic7892_setup
399 },
396 /* aic7895 based controllers */ 400 /* aic7895 based controllers */
397 { 401 {
398 ID_AHA_2940U_DUAL, 402 ID_AHA_2940U_DUAL,
@@ -1193,9 +1197,19 @@ ahc_pci_test_register_access(struct ahc_softc *ahc)
1193 * use for this test. 1197 * use for this test.
1194 */ 1198 */
1195 hcntrl = ahc_inb(ahc, HCNTRL); 1199 hcntrl = ahc_inb(ahc, HCNTRL);
1200
1196 if (hcntrl == 0xFF) 1201 if (hcntrl == 0xFF)
1197 goto fail; 1202 goto fail;
1198 1203
1204 if ((hcntrl & CHIPRST) != 0) {
1205 /*
1206 * The chip has not been initialized since
1207 * PCI/EISA/VLB bus reset. Don't trust
1208 * "left over BIOS data".
1209 */
1210 ahc->flags |= AHC_NO_BIOS_INIT;
1211 }
1212
1199 /* 1213 /*
1200 * Next create a situation where write combining 1214 * Next create a situation where write combining
1201 * or read prefetching could be initiated by the 1215 * or read prefetching could be initiated by the
@@ -1307,6 +1321,10 @@ check_extport(struct ahc_softc *ahc, u_int *sxfrctl1)
1307 sd.sd_chip = C56_66; 1321 sd.sd_chip = C56_66;
1308 } 1322 }
1309 ahc_release_seeprom(&sd); 1323 ahc_release_seeprom(&sd);
1324
1325 /* Remember the SEEPROM type for later */
1326 if (sd.sd_chip == C56_66)
1327 ahc->flags |= AHC_LARGE_SEEPROM;
1310 } 1328 }
1311 1329
1312 if (!have_seeprom) { 1330 if (!have_seeprom) {
diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.h b/drivers/scsi/aic7xxx/aic7xxx_pci.h
index be27fcb20346..263f85da405e 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_pci.h
+++ b/drivers/scsi/aic7xxx/aic7xxx_pci.h
@@ -105,6 +105,7 @@
105#define ID_AHA_29160C 0x0080900562209005ull 105#define ID_AHA_29160C 0x0080900562209005ull
106#define ID_AHA_29160B 0x00809005E2209005ull 106#define ID_AHA_29160B 0x00809005E2209005ull
107#define ID_AHA_19160B 0x0081900562A19005ull 107#define ID_AHA_19160B 0x0081900562A19005ull
108#define ID_AHA_2915_30LP 0x0082900502109005ull
108 109
109#define ID_AIC7896 0x005F9005FFFF9005ull 110#define ID_AIC7896 0x005F9005FFFF9005ull
110#define ID_AIC7896_ARO 0x00539005FFFF9005ull 111#define ID_AIC7896_ARO 0x00539005FFFF9005ull
diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
index 33d56c344944..770f1647e4d6 100644
--- a/drivers/scsi/aic7xxx_old.c
+++ b/drivers/scsi/aic7xxx_old.c
@@ -1290,7 +1290,7 @@ static void aic7xxx_check_scbs(struct aic7xxx_host *p, char *buffer);
1290 * 1290 *
1291 ***************************************************************************/ 1291 ***************************************************************************/
1292 1292
1293static inline unsigned char 1293static unsigned char
1294aic_inb(struct aic7xxx_host *p, long port) 1294aic_inb(struct aic7xxx_host *p, long port)
1295{ 1295{
1296#ifdef MMAPIO 1296#ifdef MMAPIO
@@ -1309,7 +1309,7 @@ aic_inb(struct aic7xxx_host *p, long port)
1309#endif 1309#endif
1310} 1310}
1311 1311
1312static inline void 1312static void
1313aic_outb(struct aic7xxx_host *p, unsigned char val, long port) 1313aic_outb(struct aic7xxx_host *p, unsigned char val, long port)
1314{ 1314{
1315#ifdef MMAPIO 1315#ifdef MMAPIO
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index 4299fabca554..c3f27285db1b 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -22,6 +22,7 @@
22#include <linux/completion.h> 22#include <linux/completion.h>
23#include <linux/compat.h> 23#include <linux/compat.h>
24#include <linux/chio.h> /* here are all the ioctls */ 24#include <linux/chio.h> /* here are all the ioctls */
25#include <linux/mutex.h>
25 26
26#include <scsi/scsi.h> 27#include <scsi/scsi.h>
27#include <scsi/scsi_cmnd.h> 28#include <scsi/scsi_cmnd.h>
@@ -111,7 +112,7 @@ typedef struct {
111 u_int counts[CH_TYPES]; 112 u_int counts[CH_TYPES];
112 u_int unit_attention; 113 u_int unit_attention;
113 u_int voltags; 114 u_int voltags;
114 struct semaphore lock; 115 struct mutex lock;
115} scsi_changer; 116} scsi_changer;
116 117
117static LIST_HEAD(ch_devlist); 118static LIST_HEAD(ch_devlist);
@@ -565,7 +566,7 @@ static int ch_gstatus(scsi_changer *ch, int type, unsigned char __user *dest)
565 u_char data[16]; 566 u_char data[16];
566 unsigned int i; 567 unsigned int i;
567 568
568 down(&ch->lock); 569 mutex_lock(&ch->lock);
569 for (i = 0; i < ch->counts[type]; i++) { 570 for (i = 0; i < ch->counts[type]; i++) {
570 if (0 != ch_read_element_status 571 if (0 != ch_read_element_status
571 (ch, ch->firsts[type]+i,data)) { 572 (ch, ch->firsts[type]+i,data)) {
@@ -582,7 +583,7 @@ static int ch_gstatus(scsi_changer *ch, int type, unsigned char __user *dest)
582 if (0 != retval) 583 if (0 != retval)
583 break; 584 break;
584 } 585 }
585 up(&ch->lock); 586 mutex_unlock(&ch->lock);
586 return retval; 587 return retval;
587} 588}
588 589
@@ -687,11 +688,11 @@ static int ch_ioctl(struct inode * inode, struct file * file,
687 dprintk("CHIOPOSITION: invalid parameter\n"); 688 dprintk("CHIOPOSITION: invalid parameter\n");
688 return -EBADSLT; 689 return -EBADSLT;
689 } 690 }
690 down(&ch->lock); 691 mutex_lock(&ch->lock);
691 retval = ch_position(ch,0, 692 retval = ch_position(ch,0,
692 ch->firsts[pos.cp_type] + pos.cp_unit, 693 ch->firsts[pos.cp_type] + pos.cp_unit,
693 pos.cp_flags & CP_INVERT); 694 pos.cp_flags & CP_INVERT);
694 up(&ch->lock); 695 mutex_unlock(&ch->lock);
695 return retval; 696 return retval;
696 } 697 }
697 698
@@ -708,12 +709,12 @@ static int ch_ioctl(struct inode * inode, struct file * file,
708 return -EBADSLT; 709 return -EBADSLT;
709 } 710 }
710 711
711 down(&ch->lock); 712 mutex_lock(&ch->lock);
712 retval = ch_move(ch,0, 713 retval = ch_move(ch,0,
713 ch->firsts[mv.cm_fromtype] + mv.cm_fromunit, 714 ch->firsts[mv.cm_fromtype] + mv.cm_fromunit,
714 ch->firsts[mv.cm_totype] + mv.cm_tounit, 715 ch->firsts[mv.cm_totype] + mv.cm_tounit,
715 mv.cm_flags & CM_INVERT); 716 mv.cm_flags & CM_INVERT);
716 up(&ch->lock); 717 mutex_unlock(&ch->lock);
717 return retval; 718 return retval;
718 } 719 }
719 720
@@ -731,14 +732,14 @@ static int ch_ioctl(struct inode * inode, struct file * file,
731 return -EBADSLT; 732 return -EBADSLT;
732 } 733 }
733 734
734 down(&ch->lock); 735 mutex_lock(&ch->lock);
735 retval = ch_exchange 736 retval = ch_exchange
736 (ch,0, 737 (ch,0,
737 ch->firsts[mv.ce_srctype] + mv.ce_srcunit, 738 ch->firsts[mv.ce_srctype] + mv.ce_srcunit,
738 ch->firsts[mv.ce_fdsttype] + mv.ce_fdstunit, 739 ch->firsts[mv.ce_fdsttype] + mv.ce_fdstunit,
739 ch->firsts[mv.ce_sdsttype] + mv.ce_sdstunit, 740 ch->firsts[mv.ce_sdsttype] + mv.ce_sdstunit,
740 mv.ce_flags & CE_INVERT1, mv.ce_flags & CE_INVERT2); 741 mv.ce_flags & CE_INVERT1, mv.ce_flags & CE_INVERT2);
741 up(&ch->lock); 742 mutex_unlock(&ch->lock);
742 return retval; 743 return retval;
743 } 744 }
744 745
@@ -772,7 +773,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
772 buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); 773 buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
773 if (!buffer) 774 if (!buffer)
774 return -ENOMEM; 775 return -ENOMEM;
775 down(&ch->lock); 776 mutex_lock(&ch->lock);
776 777
777 voltag_retry: 778 voltag_retry:
778 memset(cmd,0,sizeof(cmd)); 779 memset(cmd,0,sizeof(cmd));
@@ -823,7 +824,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
823 goto voltag_retry; 824 goto voltag_retry;
824 } 825 }
825 kfree(buffer); 826 kfree(buffer);
826 up(&ch->lock); 827 mutex_unlock(&ch->lock);
827 828
828 if (copy_to_user(argp, &cge, sizeof (cge))) 829 if (copy_to_user(argp, &cge, sizeof (cge)))
829 return -EFAULT; 830 return -EFAULT;
@@ -832,9 +833,9 @@ static int ch_ioctl(struct inode * inode, struct file * file,
832 833
833 case CHIOINITELEM: 834 case CHIOINITELEM:
834 { 835 {
835 down(&ch->lock); 836 mutex_lock(&ch->lock);
836 retval = ch_init_elem(ch); 837 retval = ch_init_elem(ch);
837 up(&ch->lock); 838 mutex_unlock(&ch->lock);
838 return retval; 839 return retval;
839 } 840 }
840 841
@@ -851,12 +852,12 @@ static int ch_ioctl(struct inode * inode, struct file * file,
851 return -EBADSLT; 852 return -EBADSLT;
852 } 853 }
853 elem = ch->firsts[csv.csv_type] + csv.csv_unit; 854 elem = ch->firsts[csv.csv_type] + csv.csv_unit;
854 down(&ch->lock); 855 mutex_lock(&ch->lock);
855 retval = ch_set_voltag(ch, elem, 856 retval = ch_set_voltag(ch, elem,
856 csv.csv_flags & CSV_AVOLTAG, 857 csv.csv_flags & CSV_AVOLTAG,
857 csv.csv_flags & CSV_CLEARTAG, 858 csv.csv_flags & CSV_CLEARTAG,
858 csv.csv_voltag); 859 csv.csv_voltag);
859 up(&ch->lock); 860 mutex_unlock(&ch->lock);
860 return retval; 861 return retval;
861 } 862 }
862 863
@@ -929,7 +930,7 @@ static int ch_probe(struct device *dev)
929 memset(ch,0,sizeof(*ch)); 930 memset(ch,0,sizeof(*ch));
930 ch->minor = ch_devcount; 931 ch->minor = ch_devcount;
931 sprintf(ch->name,"ch%d",ch->minor); 932 sprintf(ch->name,"ch%d",ch->minor);
932 init_MUTEX(&ch->lock); 933 mutex_init(&ch->lock);
933 ch->device = sd; 934 ch->device = sd;
934 ch_readconfig(ch); 935 ch_readconfig(ch);
935 if (init) 936 if (init)
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index 6252b9ddc01e..6e6b293dcb28 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -61,6 +61,7 @@ MODULE_DESCRIPTION("Adaptec I2O RAID Driver");
61#include <linux/timer.h> 61#include <linux/timer.h>
62#include <linux/string.h> 62#include <linux/string.h>
63#include <linux/ioport.h> 63#include <linux/ioport.h>
64#include <linux/mutex.h>
64 65
65#include <asm/processor.h> /* for boot_cpu_data */ 66#include <asm/processor.h> /* for boot_cpu_data */
66#include <asm/pgtable.h> 67#include <asm/pgtable.h>
@@ -106,7 +107,7 @@ static dpt_sig_S DPTI_sig = {
106 *============================================================================ 107 *============================================================================
107 */ 108 */
108 109
109static DECLARE_MUTEX(adpt_configuration_lock); 110static DEFINE_MUTEX(adpt_configuration_lock);
110 111
111static struct i2o_sys_tbl *sys_tbl = NULL; 112static struct i2o_sys_tbl *sys_tbl = NULL;
112static int sys_tbl_ind = 0; 113static int sys_tbl_ind = 0;
@@ -537,13 +538,13 @@ static int adpt_proc_info(struct Scsi_Host *host, char *buffer, char **start, of
537 */ 538 */
538 539
539 // Find HBA (host bus adapter) we are looking for 540 // Find HBA (host bus adapter) we are looking for
540 down(&adpt_configuration_lock); 541 mutex_lock(&adpt_configuration_lock);
541 for (pHba = hba_chain; pHba; pHba = pHba->next) { 542 for (pHba = hba_chain; pHba; pHba = pHba->next) {
542 if (pHba->host == host) { 543 if (pHba->host == host) {
543 break; /* found adapter */ 544 break; /* found adapter */
544 } 545 }
545 } 546 }
546 up(&adpt_configuration_lock); 547 mutex_unlock(&adpt_configuration_lock);
547 if (pHba == NULL) { 548 if (pHba == NULL) {
548 return 0; 549 return 0;
549 } 550 }
@@ -898,6 +899,12 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
898 if(pci_enable_device(pDev)) { 899 if(pci_enable_device(pDev)) {
899 return -EINVAL; 900 return -EINVAL;
900 } 901 }
902
903 if (pci_request_regions(pDev, "dpt_i2o")) {
904 PERROR("dpti: adpt_config_hba: pci request region failed\n");
905 return -EINVAL;
906 }
907
901 pci_set_master(pDev); 908 pci_set_master(pDev);
902 if (pci_set_dma_mask(pDev, 0xffffffffffffffffULL) && 909 if (pci_set_dma_mask(pDev, 0xffffffffffffffffULL) &&
903 pci_set_dma_mask(pDev, 0xffffffffULL)) 910 pci_set_dma_mask(pDev, 0xffffffffULL))
@@ -923,10 +930,6 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
923 raptorFlag = TRUE; 930 raptorFlag = TRUE;
924 } 931 }
925 932
926 if (pci_request_regions(pDev, "dpt_i2o")) {
927 PERROR("dpti: adpt_config_hba: pci request region failed\n");
928 return -EINVAL;
929 }
930 base_addr_virt = ioremap(base_addr0_phys,hba_map0_area_size); 933 base_addr_virt = ioremap(base_addr0_phys,hba_map0_area_size);
931 if (!base_addr_virt) { 934 if (!base_addr_virt) {
932 pci_release_regions(pDev); 935 pci_release_regions(pDev);
@@ -958,7 +961,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
958 } 961 }
959 memset(pHba, 0, sizeof(adpt_hba)); 962 memset(pHba, 0, sizeof(adpt_hba));
960 963
961 down(&adpt_configuration_lock); 964 mutex_lock(&adpt_configuration_lock);
962 965
963 if(hba_chain != NULL){ 966 if(hba_chain != NULL){
964 for(p = hba_chain; p->next; p = p->next); 967 for(p = hba_chain; p->next; p = p->next);
@@ -971,7 +974,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
971 sprintf(pHba->name, "dpti%d", hba_count); 974 sprintf(pHba->name, "dpti%d", hba_count);
972 hba_count++; 975 hba_count++;
973 976
974 up(&adpt_configuration_lock); 977 mutex_unlock(&adpt_configuration_lock);
975 978
976 pHba->pDev = pDev; 979 pHba->pDev = pDev;
977 pHba->base_addr_phys = base_addr0_phys; 980 pHba->base_addr_phys = base_addr0_phys;
@@ -1027,7 +1030,7 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba)
1027 struct adpt_device* pNext; 1030 struct adpt_device* pNext;
1028 1031
1029 1032
1030 down(&adpt_configuration_lock); 1033 mutex_lock(&adpt_configuration_lock);
1031 // scsi_unregister calls our adpt_release which 1034 // scsi_unregister calls our adpt_release which
1032 // does a quiese 1035 // does a quiese
1033 if(pHba->host){ 1036 if(pHba->host){
@@ -1046,7 +1049,7 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba)
1046 } 1049 }
1047 1050
1048 hba_count--; 1051 hba_count--;
1049 up(&adpt_configuration_lock); 1052 mutex_unlock(&adpt_configuration_lock);
1050 1053
1051 iounmap(pHba->base_addr_virt); 1054 iounmap(pHba->base_addr_virt);
1052 pci_release_regions(pHba->pDev); 1055 pci_release_regions(pHba->pDev);
@@ -1549,7 +1552,7 @@ static int adpt_i2o_parse_lct(adpt_hba* pHba)
1549 1552
1550static int adpt_i2o_install_device(adpt_hba* pHba, struct i2o_device *d) 1553static int adpt_i2o_install_device(adpt_hba* pHba, struct i2o_device *d)
1551{ 1554{
1552 down(&adpt_configuration_lock); 1555 mutex_lock(&adpt_configuration_lock);
1553 d->controller=pHba; 1556 d->controller=pHba;
1554 d->owner=NULL; 1557 d->owner=NULL;
1555 d->next=pHba->devices; 1558 d->next=pHba->devices;
@@ -1560,7 +1563,7 @@ static int adpt_i2o_install_device(adpt_hba* pHba, struct i2o_device *d)
1560 pHba->devices=d; 1563 pHba->devices=d;
1561 *d->dev_name = 0; 1564 *d->dev_name = 0;
1562 1565
1563 up(&adpt_configuration_lock); 1566 mutex_unlock(&adpt_configuration_lock);
1564 return 0; 1567 return 0;
1565} 1568}
1566 1569
@@ -1575,24 +1578,24 @@ static int adpt_open(struct inode *inode, struct file *file)
1575 if (minor >= hba_count) { 1578 if (minor >= hba_count) {
1576 return -ENXIO; 1579 return -ENXIO;
1577 } 1580 }
1578 down(&adpt_configuration_lock); 1581 mutex_lock(&adpt_configuration_lock);
1579 for (pHba = hba_chain; pHba; pHba = pHba->next) { 1582 for (pHba = hba_chain; pHba; pHba = pHba->next) {
1580 if (pHba->unit == minor) { 1583 if (pHba->unit == minor) {
1581 break; /* found adapter */ 1584 break; /* found adapter */
1582 } 1585 }
1583 } 1586 }
1584 if (pHba == NULL) { 1587 if (pHba == NULL) {
1585 up(&adpt_configuration_lock); 1588 mutex_unlock(&adpt_configuration_lock);
1586 return -ENXIO; 1589 return -ENXIO;
1587 } 1590 }
1588 1591
1589// if(pHba->in_use){ 1592// if(pHba->in_use){
1590 // up(&adpt_configuration_lock); 1593 // mutex_unlock(&adpt_configuration_lock);
1591// return -EBUSY; 1594// return -EBUSY;
1592// } 1595// }
1593 1596
1594 pHba->in_use = 1; 1597 pHba->in_use = 1;
1595 up(&adpt_configuration_lock); 1598 mutex_unlock(&adpt_configuration_lock);
1596 1599
1597 return 0; 1600 return 0;
1598} 1601}
@@ -1606,13 +1609,13 @@ static int adpt_close(struct inode *inode, struct file *file)
1606 if (minor >= hba_count) { 1609 if (minor >= hba_count) {
1607 return -ENXIO; 1610 return -ENXIO;
1608 } 1611 }
1609 down(&adpt_configuration_lock); 1612 mutex_lock(&adpt_configuration_lock);
1610 for (pHba = hba_chain; pHba; pHba = pHba->next) { 1613 for (pHba = hba_chain; pHba; pHba = pHba->next) {
1611 if (pHba->unit == minor) { 1614 if (pHba->unit == minor) {
1612 break; /* found adapter */ 1615 break; /* found adapter */
1613 } 1616 }
1614 } 1617 }
1615 up(&adpt_configuration_lock); 1618 mutex_unlock(&adpt_configuration_lock);
1616 if (pHba == NULL) { 1619 if (pHba == NULL) {
1617 return -ENXIO; 1620 return -ENXIO;
1618 } 1621 }
@@ -1910,13 +1913,13 @@ static int adpt_ioctl(struct inode *inode, struct file *file, uint cmd,
1910 if (minor >= DPTI_MAX_HBA){ 1913 if (minor >= DPTI_MAX_HBA){
1911 return -ENXIO; 1914 return -ENXIO;
1912 } 1915 }
1913 down(&adpt_configuration_lock); 1916 mutex_lock(&adpt_configuration_lock);
1914 for (pHba = hba_chain; pHba; pHba = pHba->next) { 1917 for (pHba = hba_chain; pHba; pHba = pHba->next) {
1915 if (pHba->unit == minor) { 1918 if (pHba->unit == minor) {
1916 break; /* found adapter */ 1919 break; /* found adapter */
1917 } 1920 }
1918 } 1921 }
1919 up(&adpt_configuration_lock); 1922 mutex_unlock(&adpt_configuration_lock);
1920 if(pHba == NULL){ 1923 if(pHba == NULL){
1921 return -ENXIO; 1924 return -ENXIO;
1922 } 1925 }
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 66783c860a19..588107923499 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -156,16 +156,16 @@ EXPORT_SYMBOL(scsi_host_set_state);
156void scsi_remove_host(struct Scsi_Host *shost) 156void scsi_remove_host(struct Scsi_Host *shost)
157{ 157{
158 unsigned long flags; 158 unsigned long flags;
159 down(&shost->scan_mutex); 159 mutex_lock(&shost->scan_mutex);
160 spin_lock_irqsave(shost->host_lock, flags); 160 spin_lock_irqsave(shost->host_lock, flags);
161 if (scsi_host_set_state(shost, SHOST_CANCEL)) 161 if (scsi_host_set_state(shost, SHOST_CANCEL))
162 if (scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY)) { 162 if (scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY)) {
163 spin_unlock_irqrestore(shost->host_lock, flags); 163 spin_unlock_irqrestore(shost->host_lock, flags);
164 up(&shost->scan_mutex); 164 mutex_unlock(&shost->scan_mutex);
165 return; 165 return;
166 } 166 }
167 spin_unlock_irqrestore(shost->host_lock, flags); 167 spin_unlock_irqrestore(shost->host_lock, flags);
168 up(&shost->scan_mutex); 168 mutex_unlock(&shost->scan_mutex);
169 scsi_forget_host(shost); 169 scsi_forget_host(shost);
170 scsi_proc_host_rm(shost); 170 scsi_proc_host_rm(shost);
171 171
@@ -320,7 +320,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
320 INIT_LIST_HEAD(&shost->starved_list); 320 INIT_LIST_HEAD(&shost->starved_list);
321 init_waitqueue_head(&shost->host_wait); 321 init_waitqueue_head(&shost->host_wait);
322 322
323 init_MUTEX(&shost->scan_mutex); 323 mutex_init(&shost->scan_mutex);
324 324
325 shost->host_no = scsi_host_next_hn++; /* XXX(hch): still racy */ 325 shost->host_no = scsi_host_next_hn++; /* XXX(hch): still racy */
326 shost->dma_channel = 0xff; 326 shost->dma_channel = 0xff;
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index 3882d48a42bf..e5e1ca44e1ee 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -1319,6 +1319,9 @@ ips_slave_configure(struct scsi_device * SDptr)
1319 min = ha->max_cmds - 1; 1319 min = ha->max_cmds - 1;
1320 scsi_adjust_queue_depth(SDptr, MSG_ORDERED_TAG, min); 1320 scsi_adjust_queue_depth(SDptr, MSG_ORDERED_TAG, min);
1321 } 1321 }
1322
1323 SDptr->skip_ms_page_8 = 1;
1324 SDptr->skip_ms_page_3f = 1;
1322 return 0; 1325 return 0;
1323} 1326}
1324#endif 1327#endif
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 10bcf42cb65c..780bfcc67096 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -33,6 +33,7 @@
33#include <linux/delay.h> 33#include <linux/delay.h>
34#include <linux/kfifo.h> 34#include <linux/kfifo.h>
35#include <linux/scatterlist.h> 35#include <linux/scatterlist.h>
36#include <linux/mutex.h>
36#include <net/tcp.h> 37#include <net/tcp.h>
37#include <scsi/scsi_cmnd.h> 38#include <scsi/scsi_cmnd.h>
38#include <scsi/scsi_device.h> 39#include <scsi/scsi_device.h>
@@ -86,35 +87,32 @@ iscsi_buf_init_virt(struct iscsi_buf *ibuf, char *vbuf, int size)
86{ 87{
87 sg_init_one(&ibuf->sg, (u8 *)vbuf, size); 88 sg_init_one(&ibuf->sg, (u8 *)vbuf, size);
88 ibuf->sent = 0; 89 ibuf->sent = 0;
90 ibuf->use_sendmsg = 0;
89} 91}
90 92
91static inline void 93static inline void
92iscsi_buf_init_iov(struct iscsi_buf *ibuf, char *vbuf, int size) 94iscsi_buf_init_iov(struct iscsi_buf *ibuf, char *vbuf, int size)
93{ 95{
94 ibuf->sg.page = (void*)vbuf; 96 ibuf->sg.page = virt_to_page(vbuf);
95 ibuf->sg.offset = (unsigned int)-1; 97 ibuf->sg.offset = offset_in_page(vbuf);
96 ibuf->sg.length = size; 98 ibuf->sg.length = size;
97 ibuf->sent = 0; 99 ibuf->sent = 0;
98} 100 ibuf->use_sendmsg = 1;
99
100static inline void*
101iscsi_buf_iov_base(struct iscsi_buf *ibuf)
102{
103 return (char*)ibuf->sg.page + ibuf->sent;
104} 101}
105 102
106static inline void 103static inline void
107iscsi_buf_init_sg(struct iscsi_buf *ibuf, struct scatterlist *sg) 104iscsi_buf_init_sg(struct iscsi_buf *ibuf, struct scatterlist *sg)
108{ 105{
106 ibuf->sg.page = sg->page;
107 ibuf->sg.offset = sg->offset;
108 ibuf->sg.length = sg->length;
109 /* 109 /*
110 * Fastpath: sg element fits into single page 110 * Fastpath: sg element fits into single page
111 */ 111 */
112 if (sg->length + sg->offset <= PAGE_SIZE && page_count(sg->page) >= 2) { 112 if (sg->length + sg->offset <= PAGE_SIZE && !PageSlab(sg->page))
113 ibuf->sg.page = sg->page; 113 ibuf->use_sendmsg = 0;
114 ibuf->sg.offset = sg->offset; 114 else
115 ibuf->sg.length = sg->length; 115 ibuf->use_sendmsg = 1;
116 } else
117 iscsi_buf_init_iov(ibuf, page_address(sg->page), sg->length);
118 ibuf->sent = 0; 116 ibuf->sent = 0;
119} 117}
120 118
@@ -356,7 +354,7 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
356 struct scsi_cmnd *sc = ctask->sc; 354 struct scsi_cmnd *sc = ctask->sc;
357 355
358 conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1; 356 conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1;
359 if (rhdr->flags & ISCSI_FLAG_CMD_UNDERFLOW) { 357 if (rhdr->flags & ISCSI_FLAG_DATA_UNDERFLOW) {
360 int res_count = be32_to_cpu(rhdr->residual_count); 358 int res_count = be32_to_cpu(rhdr->residual_count);
361 359
362 if (res_count > 0 && 360 if (res_count > 0 &&
@@ -366,9 +364,7 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
366 } else 364 } else
367 sc->result = (DID_BAD_TARGET << 16) | 365 sc->result = (DID_BAD_TARGET << 16) |
368 rhdr->cmd_status; 366 rhdr->cmd_status;
369 } else if (rhdr->flags & ISCSI_FLAG_CMD_BIDI_UNDERFLOW) 367 } else if (rhdr->flags & ISCSI_FLAG_DATA_OVERFLOW) {
370 sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
371 else if (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW) {
372 sc->resid = be32_to_cpu(rhdr->residual_count); 368 sc->resid = be32_to_cpu(rhdr->residual_count);
373 sc->result = (DID_OK << 16) | rhdr->cmd_status; 369 sc->result = (DID_OK << 16) | rhdr->cmd_status;
374 } else 370 } else
@@ -529,7 +525,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
529 __kfifo_put(ctask->r2tqueue, (void*)&r2t, sizeof(void*)); 525 __kfifo_put(ctask->r2tqueue, (void*)&r2t, sizeof(void*));
530 __kfifo_put(conn->writequeue, (void*)&ctask, sizeof(void*)); 526 __kfifo_put(conn->writequeue, (void*)&ctask, sizeof(void*));
531 527
532 schedule_work(&conn->xmitwork); 528 scsi_queue_work(session->host, &conn->xmitwork);
533 conn->r2t_pdus_cnt++; 529 conn->r2t_pdus_cnt++;
534 spin_unlock(&session->lock); 530 spin_unlock(&session->lock);
535 531
@@ -686,7 +682,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
686 switch(conn->in.opcode) { 682 switch(conn->in.opcode) {
687 case ISCSI_OP_LOGIN_RSP: 683 case ISCSI_OP_LOGIN_RSP:
688 case ISCSI_OP_TEXT_RSP: 684 case ISCSI_OP_TEXT_RSP:
689 case ISCSI_OP_LOGOUT_RSP: 685 case ISCSI_OP_LOGOUT_RSP:
690 rc = iscsi_check_assign_cmdsn(session, 686 rc = iscsi_check_assign_cmdsn(session,
691 (struct iscsi_nopin*)hdr); 687 (struct iscsi_nopin*)hdr);
692 if (rc) 688 if (rc)
@@ -727,12 +723,12 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
727 } 723 }
728 spin_unlock(&session->lock); 724 spin_unlock(&session->lock);
729 break; 725 break;
730 case ISCSI_OP_NOOP_IN: 726 case ISCSI_OP_NOOP_IN:
731 if (hdr->ttt != ISCSI_RESERVED_TAG) { 727 if (hdr->ttt != ISCSI_RESERVED_TAG) {
732 rc = ISCSI_ERR_PROTO; 728 rc = ISCSI_ERR_PROTO;
733 break; 729 break;
734 } 730 }
735 rc = iscsi_check_assign_cmdsn(session, 731 rc = iscsi_check_assign_cmdsn(session,
736 (struct iscsi_nopin*)hdr); 732 (struct iscsi_nopin*)hdr);
737 if (rc) 733 if (rc)
738 break; 734 break;
@@ -767,7 +763,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
767 if (!rc && hdr->ttt != ISCSI_RESERVED_TAG) 763 if (!rc && hdr->ttt != ISCSI_RESERVED_TAG)
768 rc = iscsi_recv_pdu(iscsi_handle(conn), 764 rc = iscsi_recv_pdu(iscsi_handle(conn),
769 hdr, NULL, 0); 765 hdr, NULL, 0);
770 } else 766 } else
771 rc = ISCSI_ERR_PROTO; 767 rc = ISCSI_ERR_PROTO;
772 break; 768 break;
773 case ISCSI_OP_REJECT: 769 case ISCSI_OP_REJECT:
@@ -929,7 +925,7 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn)
929 sc->request_bufflen, ctask->data_offset); 925 sc->request_bufflen, ctask->data_offset);
930 if (rc == -EAGAIN) 926 if (rc == -EAGAIN)
931 return rc; 927 return rc;
932 if (conn->datadgst_en) 928 if (conn->datadgst_en)
933 iscsi_recv_digest_update(conn, sc->request_buffer, i); 929 iscsi_recv_digest_update(conn, sc->request_buffer, i);
934 rc = 0; 930 rc = 0;
935 goto done; 931 goto done;
@@ -1024,7 +1020,7 @@ iscsi_data_recv(struct iscsi_conn *conn)
1024 conn->in.hdr = &conn->hdr; 1020 conn->in.hdr = &conn->hdr;
1025 conn->senselen = (conn->data[0] << 8) | conn->data[1]; 1021 conn->senselen = (conn->data[0] << 8) | conn->data[1];
1026 rc = iscsi_cmd_rsp(conn, conn->in.ctask); 1022 rc = iscsi_cmd_rsp(conn, conn->in.ctask);
1027 if (!rc && conn->datadgst_en) 1023 if (!rc && conn->datadgst_en)
1028 iscsi_recv_digest_update(conn, conn->data, 1024 iscsi_recv_digest_update(conn, conn->data,
1029 conn->in.datalen); 1025 conn->in.datalen);
1030 } 1026 }
@@ -1051,7 +1047,7 @@ iscsi_data_recv(struct iscsi_conn *conn)
1051 rc = iscsi_recv_pdu(iscsi_handle(conn), conn->in.hdr, 1047 rc = iscsi_recv_pdu(iscsi_handle(conn), conn->in.hdr,
1052 conn->data, conn->in.datalen); 1048 conn->data, conn->in.datalen);
1053 1049
1054 if (!rc && conn->datadgst_en && 1050 if (!rc && conn->datadgst_en &&
1055 conn->in.opcode != ISCSI_OP_LOGIN_RSP) 1051 conn->in.opcode != ISCSI_OP_LOGIN_RSP)
1056 iscsi_recv_digest_update(conn, conn->data, 1052 iscsi_recv_digest_update(conn, conn->data,
1057 conn->in.datalen); 1053 conn->in.datalen);
@@ -1271,7 +1267,7 @@ iscsi_write_space(struct sock *sk)
1271 conn->old_write_space(sk); 1267 conn->old_write_space(sk);
1272 debug_tcp("iscsi_write_space: cid %d\n", conn->id); 1268 debug_tcp("iscsi_write_space: cid %d\n", conn->id);
1273 clear_bit(SUSPEND_BIT, &conn->suspend_tx); 1269 clear_bit(SUSPEND_BIT, &conn->suspend_tx);
1274 schedule_work(&conn->xmitwork); 1270 scsi_queue_work(conn->session->host, &conn->xmitwork);
1275} 1271}
1276 1272
1277static void 1273static void
@@ -1312,35 +1308,25 @@ iscsi_conn_restore_callbacks(struct iscsi_conn *conn)
1312 * @buf: buffer to write from 1308 * @buf: buffer to write from
1313 * @size: actual size to write 1309 * @size: actual size to write
1314 * @flags: socket's flags 1310 * @flags: socket's flags
1315 *
1316 * Notes:
1317 * depending on buffer will use tcp_sendpage() or tcp_sendmsg().
1318 * buf->sg.offset == -1 tells us that buffer is non S/G and forces
1319 * to use tcp_sendmsg().
1320 */ 1311 */
1321static inline int 1312static inline int
1322iscsi_send(struct socket *sk, struct iscsi_buf *buf, int size, int flags) 1313iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags)
1323{ 1314{
1324 int res; 1315 struct socket *sk = conn->sock;
1325 1316 int offset = buf->sg.offset + buf->sent;
1326 if ((int)buf->sg.offset >= 0) {
1327 int offset = buf->sg.offset + buf->sent;
1328
1329 /* tcp_sendpage */
1330 res = sk->ops->sendpage(sk, buf->sg.page, offset, size, flags);
1331 } else {
1332 struct msghdr msg;
1333
1334 buf->iov.iov_base = iscsi_buf_iov_base(buf);
1335 buf->iov.iov_len = size;
1336
1337 memset(&msg, 0, sizeof(struct msghdr));
1338
1339 /* tcp_sendmsg */
1340 res = kernel_sendmsg(sk, &msg, &buf->iov, 1, size);
1341 }
1342 1317
1343 return res; 1318 /*
1319 * if we got use_sg=0 or are sending something we kmallocd
1320 * then we did not have to do kmap (kmap returns page_address)
1321 *
1322 * if we got use_sg > 0, but had to drop down, we do not
1323 * set clustering so this should only happen for that
1324 * slab case.
1325 */
1326 if (buf->use_sendmsg)
1327 return sock_no_sendpage(sk, buf->sg.page, offset, size, flags);
1328 else
1329 return conn->sendpage(sk, buf->sg.page, offset, size, flags);
1344} 1330}
1345 1331
1346/** 1332/**
@@ -1355,7 +1341,6 @@ iscsi_send(struct socket *sk, struct iscsi_buf *buf, int size, int flags)
1355static inline int 1341static inline int
1356iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen) 1342iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen)
1357{ 1343{
1358 struct socket *sk = conn->sock;
1359 int flags = 0; /* MSG_DONTWAIT; */ 1344 int flags = 0; /* MSG_DONTWAIT; */
1360 int res, size; 1345 int res, size;
1361 1346
@@ -1364,7 +1349,7 @@ iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen)
1364 if (buf->sent + size != buf->sg.length || datalen) 1349 if (buf->sent + size != buf->sg.length || datalen)
1365 flags |= MSG_MORE; 1350 flags |= MSG_MORE;
1366 1351
1367 res = iscsi_send(sk, buf, size, flags); 1352 res = iscsi_send(conn, buf, size, flags);
1368 debug_tcp("sendhdr %d bytes, sent %d res %d\n", size, buf->sent, res); 1353 debug_tcp("sendhdr %d bytes, sent %d res %d\n", size, buf->sent, res);
1369 if (res >= 0) { 1354 if (res >= 0) {
1370 conn->txdata_octets += res; 1355 conn->txdata_octets += res;
@@ -1395,7 +1380,6 @@ static inline int
1395iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf, 1380iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf,
1396 int *count, int *sent) 1381 int *count, int *sent)
1397{ 1382{
1398 struct socket *sk = conn->sock;
1399 int flags = 0; /* MSG_DONTWAIT; */ 1383 int flags = 0; /* MSG_DONTWAIT; */
1400 int res, size; 1384 int res, size;
1401 1385
@@ -1406,7 +1390,7 @@ iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf,
1406 if (buf->sent + size != buf->sg.length || *count != size) 1390 if (buf->sent + size != buf->sg.length || *count != size)
1407 flags |= MSG_MORE; 1391 flags |= MSG_MORE;
1408 1392
1409 res = iscsi_send(sk, buf, size, flags); 1393 res = iscsi_send(conn, buf, size, flags);
1410 debug_tcp("sendpage: %d bytes, sent %d left %d sent %d res %d\n", 1394 debug_tcp("sendpage: %d bytes, sent %d left %d sent %d res %d\n",
1411 size, buf->sent, *count, *sent, res); 1395 size, buf->sent, *count, *sent, res);
1412 if (res >= 0) { 1396 if (res >= 0) {
@@ -1434,20 +1418,7 @@ iscsi_data_digest_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1434 ctask->digest_count = 4; 1418 ctask->digest_count = 4;
1435} 1419}
1436 1420
1437static inline void 1421static int
1438iscsi_buf_data_digest_update(struct iscsi_conn *conn, struct iscsi_buf *buf)
1439{
1440 struct scatterlist sg;
1441
1442 if (buf->sg.offset != -1)
1443 crypto_digest_update(conn->data_tx_tfm, &buf->sg, 1);
1444 else {
1445 sg_init_one(&sg, (char *)buf->sg.page, buf->sg.length);
1446 crypto_digest_update(conn->data_tx_tfm, &sg, 1);
1447 }
1448}
1449
1450static inline int
1451iscsi_digest_final_send(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, 1422iscsi_digest_final_send(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
1452 struct iscsi_buf *buf, uint32_t *digest, int final) 1423 struct iscsi_buf *buf, uint32_t *digest, int final)
1453{ 1424{
@@ -1680,7 +1651,7 @@ iscsi_cmd_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
1680 zero_data(ctask->hdr.dlength); 1651 zero_data(ctask->hdr.dlength);
1681 } 1652 }
1682 1653
1683 iscsi_buf_init_virt(&ctask->headbuf, (char*)&ctask->hdr, 1654 iscsi_buf_init_virt(&ctask->headbuf, (char*)&ctask->hdr,
1684 sizeof(struct iscsi_hdr)); 1655 sizeof(struct iscsi_hdr));
1685 conn->scsicmd_pdus_cnt++; 1656 conn->scsicmd_pdus_cnt++;
1686} 1657}
@@ -1746,7 +1717,7 @@ static inline int
1746handle_xmstate_r_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) 1717handle_xmstate_r_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1747{ 1718{
1748 ctask->xmstate &= ~XMSTATE_R_HDR; 1719 ctask->xmstate &= ~XMSTATE_R_HDR;
1749 if (conn->hdrdgst_en) 1720 if (conn->hdrdgst_en)
1750 iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext); 1721 iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext);
1751 if (!iscsi_sendhdr(conn, &ctask->headbuf, 0)) { 1722 if (!iscsi_sendhdr(conn, &ctask->headbuf, 0)) {
1752 BUG_ON(ctask->xmstate != XMSTATE_IDLE); 1723 BUG_ON(ctask->xmstate != XMSTATE_IDLE);
@@ -1760,7 +1731,7 @@ static inline int
1760handle_xmstate_w_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) 1731handle_xmstate_w_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1761{ 1732{
1762 ctask->xmstate &= ~XMSTATE_W_HDR; 1733 ctask->xmstate &= ~XMSTATE_W_HDR;
1763 if (conn->hdrdgst_en) 1734 if (conn->hdrdgst_en)
1764 iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext); 1735 iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext);
1765 if (iscsi_sendhdr(conn, &ctask->headbuf, ctask->imm_count)) { 1736 if (iscsi_sendhdr(conn, &ctask->headbuf, ctask->imm_count)) {
1766 ctask->xmstate |= XMSTATE_W_HDR; 1737 ctask->xmstate |= XMSTATE_W_HDR;
@@ -1809,7 +1780,8 @@ handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1809 return -EAGAIN; 1780 return -EAGAIN;
1810 } 1781 }
1811 if (conn->datadgst_en) 1782 if (conn->datadgst_en)
1812 iscsi_buf_data_digest_update(conn, &ctask->sendbuf); 1783 crypto_digest_update(conn->data_tx_tfm,
1784 &ctask->sendbuf.sg, 1);
1813 1785
1814 if (!ctask->imm_count) 1786 if (!ctask->imm_count)
1815 break; 1787 break;
@@ -1894,7 +1866,8 @@ handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1894 * so pass it 1866 * so pass it
1895 */ 1867 */
1896 if (conn->datadgst_en && ctask->sent - start > 0) 1868 if (conn->datadgst_en && ctask->sent - start > 0)
1897 iscsi_buf_data_digest_update(conn, &ctask->sendbuf); 1869 crypto_digest_update(conn->data_tx_tfm,
1870 &ctask->sendbuf.sg, 1);
1898 1871
1899 if (!ctask->data_count) 1872 if (!ctask->data_count)
1900 break; 1873 break;
@@ -1972,7 +1945,7 @@ solicit_again:
1972 1945
1973 BUG_ON(r2t->data_count < 0); 1946 BUG_ON(r2t->data_count < 0);
1974 if (conn->datadgst_en) 1947 if (conn->datadgst_en)
1975 iscsi_buf_data_digest_update(conn, &r2t->sendbuf); 1948 crypto_digest_update(conn->data_tx_tfm, &r2t->sendbuf.sg, 1);
1976 1949
1977 if (r2t->data_count) { 1950 if (r2t->data_count) {
1978 BUG_ON(ctask->sc->use_sg == 0); 1951 BUG_ON(ctask->sc->use_sg == 0);
@@ -2054,7 +2027,7 @@ handle_xmstate_w_pad(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
2054 } 2027 }
2055 2028
2056 if (conn->datadgst_en) { 2029 if (conn->datadgst_en) {
2057 iscsi_buf_data_digest_update(conn, &ctask->sendbuf); 2030 crypto_digest_update(conn->data_tx_tfm, &ctask->sendbuf.sg, 1);
2058 /* imm data? */ 2031 /* imm data? */
2059 if (!dtask) { 2032 if (!dtask) {
2060 if (iscsi_digest_final_send(conn, ctask, &ctask->immbuf, 2033 if (iscsi_digest_final_send(conn, ctask, &ctask->immbuf,
@@ -2148,7 +2121,7 @@ unsolicit_head_again:
2148solicit_head_again: 2121solicit_head_again:
2149 r2t = ctask->r2t; 2122 r2t = ctask->r2t;
2150 if (conn->hdrdgst_en) 2123 if (conn->hdrdgst_en)
2151 iscsi_hdr_digest(conn, &r2t->headbuf, 2124 iscsi_hdr_digest(conn, &r2t->headbuf,
2152 (u8*)r2t->dtask->hdrext); 2125 (u8*)r2t->dtask->hdrext);
2153 if (iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count)) { 2126 if (iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count)) {
2154 ctask->xmstate &= ~XMSTATE_SOL_DATA; 2127 ctask->xmstate &= ~XMSTATE_SOL_DATA;
@@ -2300,10 +2273,10 @@ iscsi_xmitworker(void *data)
2300 /* 2273 /*
2301 * serialize Xmit worker on a per-connection basis. 2274 * serialize Xmit worker on a per-connection basis.
2302 */ 2275 */
2303 down(&conn->xmitsema); 2276 mutex_lock(&conn->xmitmutex);
2304 if (iscsi_data_xmit(conn)) 2277 if (iscsi_data_xmit(conn))
2305 schedule_work(&conn->xmitwork); 2278 scsi_queue_work(conn->session->host, &conn->xmitwork);
2306 up(&conn->xmitsema); 2279 mutex_unlock(&conn->xmitmutex);
2307} 2280}
2308 2281
2309#define FAILURE_BAD_HOST 1 2282#define FAILURE_BAD_HOST 1
@@ -2367,15 +2340,7 @@ iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
2367 session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1); 2340 session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
2368 spin_unlock(&session->lock); 2341 spin_unlock(&session->lock);
2369 2342
2370 if (!in_interrupt() && !down_trylock(&conn->xmitsema)) { 2343 scsi_queue_work(host, &conn->xmitwork);
2371 spin_unlock_irq(host->host_lock);
2372 if (iscsi_data_xmit(conn))
2373 schedule_work(&conn->xmitwork);
2374 up(&conn->xmitsema);
2375 spin_lock_irq(host->host_lock);
2376 } else
2377 schedule_work(&conn->xmitwork);
2378
2379 return 0; 2344 return 0;
2380 2345
2381reject: 2346reject:
@@ -2462,17 +2427,20 @@ iscsi_pool_free(struct iscsi_queue *q, void **items)
2462 kfree(items); 2427 kfree(items);
2463} 2428}
2464 2429
2465static iscsi_connh_t 2430static struct iscsi_cls_conn *
2466iscsi_conn_create(iscsi_sessionh_t sessionh, uint32_t conn_idx) 2431iscsi_conn_create(struct Scsi_Host *shost, uint32_t conn_idx)
2467{ 2432{
2468 struct iscsi_session *session = iscsi_ptr(sessionh); 2433 struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
2469 struct iscsi_conn *conn = NULL; 2434 struct iscsi_conn *conn;
2435 struct iscsi_cls_conn *cls_conn;
2470 2436
2471 conn = kmalloc(sizeof(struct iscsi_conn), GFP_KERNEL); 2437 cls_conn = iscsi_create_conn(hostdata_session(shost->hostdata),
2472 if (conn == NULL) 2438 conn_idx);
2473 goto conn_alloc_fail; 2439 if (!cls_conn)
2474 memset(conn, 0, sizeof(struct iscsi_conn)); 2440 return NULL;
2441 conn = cls_conn->dd_data;
2475 2442
2443 memset(conn, 0, sizeof(struct iscsi_conn));
2476 conn->c_stage = ISCSI_CONN_INITIAL_STAGE; 2444 conn->c_stage = ISCSI_CONN_INITIAL_STAGE;
2477 conn->in_progress = IN_PROGRESS_WAIT_HEADER; 2445 conn->in_progress = IN_PROGRESS_WAIT_HEADER;
2478 conn->id = conn_idx; 2446 conn->id = conn_idx;
@@ -2531,10 +2499,10 @@ iscsi_conn_create(iscsi_sessionh_t sessionh, uint32_t conn_idx)
2531 goto max_recv_dlenght_alloc_fail; 2499 goto max_recv_dlenght_alloc_fail;
2532 2500
2533 init_timer(&conn->tmabort_timer); 2501 init_timer(&conn->tmabort_timer);
2534 init_MUTEX(&conn->xmitsema); 2502 mutex_init(&conn->xmitmutex);
2535 init_waitqueue_head(&conn->ehwait); 2503 init_waitqueue_head(&conn->ehwait);
2536 2504
2537 return iscsi_handle(conn); 2505 return cls_conn;
2538 2506
2539max_recv_dlenght_alloc_fail: 2507max_recv_dlenght_alloc_fail:
2540 spin_lock_bh(&session->lock); 2508 spin_lock_bh(&session->lock);
@@ -2550,18 +2518,18 @@ immqueue_alloc_fail:
2550writequeue_alloc_fail: 2518writequeue_alloc_fail:
2551 kfifo_free(conn->xmitqueue); 2519 kfifo_free(conn->xmitqueue);
2552xmitqueue_alloc_fail: 2520xmitqueue_alloc_fail:
2553 kfree(conn); 2521 iscsi_destroy_conn(cls_conn);
2554conn_alloc_fail: 2522 return NULL;
2555 return iscsi_handle(NULL);
2556} 2523}
2557 2524
2558static void 2525static void
2559iscsi_conn_destroy(iscsi_connh_t connh) 2526iscsi_conn_destroy(struct iscsi_cls_conn *cls_conn)
2560{ 2527{
2561 struct iscsi_conn *conn = iscsi_ptr(connh); 2528 struct iscsi_conn *conn = cls_conn->dd_data;
2562 struct iscsi_session *session = conn->session; 2529 struct iscsi_session *session = conn->session;
2530 unsigned long flags;
2563 2531
2564 down(&conn->xmitsema); 2532 mutex_lock(&conn->xmitmutex);
2565 set_bit(SUSPEND_BIT, &conn->suspend_tx); 2533 set_bit(SUSPEND_BIT, &conn->suspend_tx);
2566 if (conn->c_stage == ISCSI_CONN_INITIAL_STAGE && conn->sock) { 2534 if (conn->c_stage == ISCSI_CONN_INITIAL_STAGE && conn->sock) {
2567 struct sock *sk = conn->sock->sk; 2535 struct sock *sk = conn->sock->sk;
@@ -2592,19 +2560,19 @@ iscsi_conn_destroy(iscsi_connh_t connh)
2592 } 2560 }
2593 spin_unlock_bh(&session->lock); 2561 spin_unlock_bh(&session->lock);
2594 2562
2595 up(&conn->xmitsema); 2563 mutex_unlock(&conn->xmitmutex);
2596 2564
2597 /* 2565 /*
2598 * Block until all in-progress commands for this connection 2566 * Block until all in-progress commands for this connection
2599 * time out or fail. 2567 * time out or fail.
2600 */ 2568 */
2601 for (;;) { 2569 for (;;) {
2602 spin_lock_bh(&conn->lock); 2570 spin_lock_irqsave(session->host->host_lock, flags);
2603 if (!session->host->host_busy) { /* OK for ERL == 0 */ 2571 if (!session->host->host_busy) { /* OK for ERL == 0 */
2604 spin_unlock_bh(&conn->lock); 2572 spin_unlock_irqrestore(session->host->host_lock, flags);
2605 break; 2573 break;
2606 } 2574 }
2607 spin_unlock_bh(&conn->lock); 2575 spin_unlock_irqrestore(session->host->host_lock, flags);
2608 msleep_interruptible(500); 2576 msleep_interruptible(500);
2609 printk("conn_destroy(): host_busy %d host_failed %d\n", 2577 printk("conn_destroy(): host_busy %d host_failed %d\n",
2610 session->host->host_busy, session->host->host_failed); 2578 session->host->host_busy, session->host->host_failed);
@@ -2652,7 +2620,8 @@ iscsi_conn_destroy(iscsi_connh_t connh)
2652 kfifo_free(conn->writequeue); 2620 kfifo_free(conn->writequeue);
2653 kfifo_free(conn->immqueue); 2621 kfifo_free(conn->immqueue);
2654 kfifo_free(conn->mgmtqueue); 2622 kfifo_free(conn->mgmtqueue);
2655 kfree(conn); 2623
2624 iscsi_destroy_conn(cls_conn);
2656} 2625}
2657 2626
2658static int 2627static int
@@ -2713,6 +2682,8 @@ iscsi_conn_bind(iscsi_sessionh_t sessionh, iscsi_connh_t connh,
2713 */ 2682 */
2714 iscsi_conn_set_callbacks(conn); 2683 iscsi_conn_set_callbacks(conn);
2715 2684
2685 conn->sendpage = conn->sock->ops->sendpage;
2686
2716 /* 2687 /*
2717 * set receive state machine into initial state 2688 * set receive state machine into initial state
2718 */ 2689 */
@@ -2796,7 +2767,7 @@ iscsi_conn_stop(iscsi_connh_t connh, int flag)
2796 set_bit(SUSPEND_BIT, &conn->suspend_rx); 2767 set_bit(SUSPEND_BIT, &conn->suspend_rx);
2797 write_unlock_bh(&sk->sk_callback_lock); 2768 write_unlock_bh(&sk->sk_callback_lock);
2798 2769
2799 down(&conn->xmitsema); 2770 mutex_lock(&conn->xmitmutex);
2800 2771
2801 spin_lock_irqsave(session->host->host_lock, flags); 2772 spin_lock_irqsave(session->host->host_lock, flags);
2802 spin_lock(&session->lock); 2773 spin_lock(&session->lock);
@@ -2878,7 +2849,7 @@ iscsi_conn_stop(iscsi_connh_t connh, int flag)
2878 conn->datadgst_en = 0; 2849 conn->datadgst_en = 0;
2879 } 2850 }
2880 } 2851 }
2881 up(&conn->xmitsema); 2852 mutex_unlock(&conn->xmitmutex);
2882} 2853}
2883 2854
2884static int 2855static int
@@ -2963,8 +2934,7 @@ iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
2963 else 2934 else
2964 __kfifo_put(conn->mgmtqueue, (void*)&mtask, sizeof(void*)); 2935 __kfifo_put(conn->mgmtqueue, (void*)&mtask, sizeof(void*));
2965 2936
2966 schedule_work(&conn->xmitwork); 2937 scsi_queue_work(session->host, &conn->xmitwork);
2967
2968 return 0; 2938 return 0;
2969} 2939}
2970 2940
@@ -3029,12 +2999,12 @@ iscsi_eh_abort(struct scsi_cmnd *sc)
3029 * 1) connection-level failure; 2999 * 1) connection-level failure;
3030 * 2) recovery due protocol error; 3000 * 2) recovery due protocol error;
3031 */ 3001 */
3032 down(&conn->xmitsema); 3002 mutex_lock(&conn->xmitmutex);
3033 spin_lock_bh(&session->lock); 3003 spin_lock_bh(&session->lock);
3034 if (session->state != ISCSI_STATE_LOGGED_IN) { 3004 if (session->state != ISCSI_STATE_LOGGED_IN) {
3035 if (session->state == ISCSI_STATE_TERMINATE) { 3005 if (session->state == ISCSI_STATE_TERMINATE) {
3036 spin_unlock_bh(&session->lock); 3006 spin_unlock_bh(&session->lock);
3037 up(&conn->xmitsema); 3007 mutex_unlock(&conn->xmitmutex);
3038 goto failed; 3008 goto failed;
3039 } 3009 }
3040 spin_unlock_bh(&session->lock); 3010 spin_unlock_bh(&session->lock);
@@ -3052,7 +3022,7 @@ iscsi_eh_abort(struct scsi_cmnd *sc)
3052 * 2) session was re-open during time out of ctask. 3022 * 2) session was re-open during time out of ctask.
3053 */ 3023 */
3054 spin_unlock_bh(&session->lock); 3024 spin_unlock_bh(&session->lock);
3055 up(&conn->xmitsema); 3025 mutex_unlock(&conn->xmitmutex);
3056 goto success; 3026 goto success;
3057 } 3027 }
3058 conn->tmabort_state = TMABORT_INITIAL; 3028 conn->tmabort_state = TMABORT_INITIAL;
@@ -3107,7 +3077,7 @@ iscsi_eh_abort(struct scsi_cmnd *sc)
3107 conn->tmabort_state == TMABORT_SUCCESS) { 3077 conn->tmabort_state == TMABORT_SUCCESS) {
3108 conn->tmabort_state = TMABORT_INITIAL; 3078 conn->tmabort_state = TMABORT_INITIAL;
3109 spin_unlock_bh(&session->lock); 3079 spin_unlock_bh(&session->lock);
3110 up(&conn->xmitsema); 3080 mutex_unlock(&conn->xmitmutex);
3111 goto success; 3081 goto success;
3112 } 3082 }
3113 conn->tmabort_state = TMABORT_INITIAL; 3083 conn->tmabort_state = TMABORT_INITIAL;
@@ -3116,7 +3086,7 @@ iscsi_eh_abort(struct scsi_cmnd *sc)
3116 spin_unlock_bh(&session->lock); 3086 spin_unlock_bh(&session->lock);
3117 } 3087 }
3118 } 3088 }
3119 up(&conn->xmitsema); 3089 mutex_unlock(&conn->xmitmutex);
3120 3090
3121 3091
3122 /* 3092 /*
@@ -3182,7 +3152,7 @@ failed:
3182exit: 3152exit:
3183 del_timer_sync(&conn->tmabort_timer); 3153 del_timer_sync(&conn->tmabort_timer);
3184 3154
3185 down(&conn->xmitsema); 3155 mutex_lock(&conn->xmitmutex);
3186 if (conn->sock) { 3156 if (conn->sock) {
3187 struct sock *sk = conn->sock->sk; 3157 struct sock *sk = conn->sock->sk;
3188 3158
@@ -3190,7 +3160,7 @@ exit:
3190 iscsi_ctask_cleanup(conn, ctask); 3160 iscsi_ctask_cleanup(conn, ctask);
3191 write_unlock_bh(&sk->sk_callback_lock); 3161 write_unlock_bh(&sk->sk_callback_lock);
3192 } 3162 }
3193 up(&conn->xmitsema); 3163 mutex_unlock(&conn->xmitmutex);
3194 return rc; 3164 return rc;
3195} 3165}
3196 3166
@@ -3281,17 +3251,23 @@ static struct scsi_host_template iscsi_sht = {
3281 .this_id = -1, 3251 .this_id = -1,
3282}; 3252};
3283 3253
3284static iscsi_sessionh_t 3254static struct iscsi_transport iscsi_tcp_transport;
3285iscsi_session_create(uint32_t initial_cmdsn, struct Scsi_Host *host) 3255
3256static struct Scsi_Host *
3257iscsi_session_create(struct scsi_transport_template *scsit,
3258 uint32_t initial_cmdsn)
3286{ 3259{
3287 int cmd_i; 3260 struct Scsi_Host *shost;
3288 struct iscsi_session *session; 3261 struct iscsi_session *session;
3262 int cmd_i;
3289 3263
3290 session = iscsi_hostdata(host->hostdata); 3264 shost = iscsi_transport_create_session(scsit, &iscsi_tcp_transport);
3291 memset(session, 0, sizeof(struct iscsi_session)); 3265 if (!shost)
3266 return NULL;
3292 3267
3293 session->host = host; 3268 session = iscsi_hostdata(shost->hostdata);
3294 session->id = host->host_no; 3269 memset(session, 0, sizeof(struct iscsi_session));
3270 session->host = shost;
3295 session->state = ISCSI_STATE_LOGGED_IN; 3271 session->state = ISCSI_STATE_LOGGED_IN;
3296 session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX; 3272 session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX;
3297 session->cmds_max = ISCSI_XMIT_CMDS_MAX; 3273 session->cmds_max = ISCSI_XMIT_CMDS_MAX;
@@ -3335,7 +3311,7 @@ iscsi_session_create(uint32_t initial_cmdsn, struct Scsi_Host *host)
3335 if (iscsi_r2tpool_alloc(session)) 3311 if (iscsi_r2tpool_alloc(session))
3336 goto r2tpool_alloc_fail; 3312 goto r2tpool_alloc_fail;
3337 3313
3338 return iscsi_handle(session); 3314 return shost;
3339 3315
3340r2tpool_alloc_fail: 3316r2tpool_alloc_fail:
3341 for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) 3317 for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++)
@@ -3345,15 +3321,15 @@ immdata_alloc_fail:
3345mgmtpool_alloc_fail: 3321mgmtpool_alloc_fail:
3346 iscsi_pool_free(&session->cmdpool, (void**)session->cmds); 3322 iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
3347cmdpool_alloc_fail: 3323cmdpool_alloc_fail:
3348 return iscsi_handle(NULL); 3324 return NULL;
3349} 3325}
3350 3326
3351static void 3327static void
3352iscsi_session_destroy(iscsi_sessionh_t sessionh) 3328iscsi_session_destroy(struct Scsi_Host *shost)
3353{ 3329{
3330 struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
3354 int cmd_i; 3331 int cmd_i;
3355 struct iscsi_data_task *dtask, *n; 3332 struct iscsi_data_task *dtask, *n;
3356 struct iscsi_session *session = iscsi_ptr(sessionh);
3357 3333
3358 for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { 3334 for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) {
3359 struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; 3335 struct iscsi_cmd_task *ctask = session->cmds[cmd_i];
@@ -3369,6 +3345,8 @@ iscsi_session_destroy(iscsi_sessionh_t sessionh)
3369 iscsi_r2tpool_free(session); 3345 iscsi_r2tpool_free(session);
3370 iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds); 3346 iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds);
3371 iscsi_pool_free(&session->cmdpool, (void**)session->cmds); 3347 iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
3348
3349 iscsi_transport_destroy_session(shost);
3372} 3350}
3373 3351
3374static int 3352static int
@@ -3467,6 +3445,8 @@ iscsi_conn_set_param(iscsi_connh_t connh, enum iscsi_param param,
3467 if (conn->data_rx_tfm) 3445 if (conn->data_rx_tfm)
3468 crypto_free_tfm(conn->data_rx_tfm); 3446 crypto_free_tfm(conn->data_rx_tfm);
3469 } 3447 }
3448 conn->sendpage = conn->datadgst_en ?
3449 sock_no_sendpage : conn->sock->ops->sendpage;
3470 break; 3450 break;
3471 case ISCSI_PARAM_INITIAL_R2T_EN: 3451 case ISCSI_PARAM_INITIAL_R2T_EN:
3472 session->initial_r2t_en = value; 3452 session->initial_r2t_en = value;
@@ -3515,25 +3495,12 @@ iscsi_conn_set_param(iscsi_connh_t connh, enum iscsi_param param,
3515} 3495}
3516 3496
3517static int 3497static int
3518iscsi_conn_get_param(iscsi_connh_t connh, enum iscsi_param param, 3498iscsi_session_get_param(struct Scsi_Host *shost,
3519 uint32_t *value) 3499 enum iscsi_param param, uint32_t *value)
3520{ 3500{
3521 struct iscsi_conn *conn = iscsi_ptr(connh); 3501 struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
3522 struct iscsi_session *session = conn->session;
3523 3502
3524 switch(param) { 3503 switch(param) {
3525 case ISCSI_PARAM_MAX_RECV_DLENGTH:
3526 *value = conn->max_recv_dlength;
3527 break;
3528 case ISCSI_PARAM_MAX_XMIT_DLENGTH:
3529 *value = conn->max_xmit_dlength;
3530 break;
3531 case ISCSI_PARAM_HDRDGST_EN:
3532 *value = conn->hdrdgst_en;
3533 break;
3534 case ISCSI_PARAM_DATADGST_EN:
3535 *value = conn->datadgst_en;
3536 break;
3537 case ISCSI_PARAM_INITIAL_R2T_EN: 3504 case ISCSI_PARAM_INITIAL_R2T_EN:
3538 *value = session->initial_r2t_en; 3505 *value = session->initial_r2t_en;
3539 break; 3506 break;
@@ -3571,6 +3538,31 @@ iscsi_conn_get_param(iscsi_connh_t connh, enum iscsi_param param,
3571 return 0; 3538 return 0;
3572} 3539}
3573 3540
3541static int
3542iscsi_conn_get_param(void *data, enum iscsi_param param, uint32_t *value)
3543{
3544 struct iscsi_conn *conn = data;
3545
3546 switch(param) {
3547 case ISCSI_PARAM_MAX_RECV_DLENGTH:
3548 *value = conn->max_recv_dlength;
3549 break;
3550 case ISCSI_PARAM_MAX_XMIT_DLENGTH:
3551 *value = conn->max_xmit_dlength;
3552 break;
3553 case ISCSI_PARAM_HDRDGST_EN:
3554 *value = conn->hdrdgst_en;
3555 break;
3556 case ISCSI_PARAM_DATADGST_EN:
3557 *value = conn->datadgst_en;
3558 break;
3559 default:
3560 return ISCSI_ERR_PARAM_NOT_FOUND;
3561 }
3562
3563 return 0;
3564}
3565
3574static void 3566static void
3575iscsi_conn_get_stats(iscsi_connh_t connh, struct iscsi_stats *stats) 3567iscsi_conn_get_stats(iscsi_connh_t connh, struct iscsi_stats *stats)
3576{ 3568{
@@ -3601,9 +3593,9 @@ iscsi_conn_send_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr, char *data,
3601 struct iscsi_conn *conn = iscsi_ptr(connh); 3593 struct iscsi_conn *conn = iscsi_ptr(connh);
3602 int rc; 3594 int rc;
3603 3595
3604 down(&conn->xmitsema); 3596 mutex_lock(&conn->xmitmutex);
3605 rc = iscsi_conn_send_generic(conn, hdr, data, data_size); 3597 rc = iscsi_conn_send_generic(conn, hdr, data, data_size);
3606 up(&conn->xmitsema); 3598 mutex_unlock(&conn->xmitmutex);
3607 3599
3608 return rc; 3600 return rc;
3609} 3601}
@@ -3615,6 +3607,7 @@ static struct iscsi_transport iscsi_tcp_transport = {
3615 | CAP_DATADGST, 3607 | CAP_DATADGST,
3616 .host_template = &iscsi_sht, 3608 .host_template = &iscsi_sht,
3617 .hostdata_size = sizeof(struct iscsi_session), 3609 .hostdata_size = sizeof(struct iscsi_session),
3610 .conndata_size = sizeof(struct iscsi_conn),
3618 .max_conn = 1, 3611 .max_conn = 1,
3619 .max_cmd_len = ISCSI_TCP_MAX_CMD_LEN, 3612 .max_cmd_len = ISCSI_TCP_MAX_CMD_LEN,
3620 .create_session = iscsi_session_create, 3613 .create_session = iscsi_session_create,
@@ -3623,7 +3616,8 @@ static struct iscsi_transport iscsi_tcp_transport = {
3623 .bind_conn = iscsi_conn_bind, 3616 .bind_conn = iscsi_conn_bind,
3624 .destroy_conn = iscsi_conn_destroy, 3617 .destroy_conn = iscsi_conn_destroy,
3625 .set_param = iscsi_conn_set_param, 3618 .set_param = iscsi_conn_set_param,
3626 .get_param = iscsi_conn_get_param, 3619 .get_conn_param = iscsi_conn_get_param,
3620 .get_session_param = iscsi_session_get_param,
3627 .start_conn = iscsi_conn_start, 3621 .start_conn = iscsi_conn_start,
3628 .stop_conn = iscsi_conn_stop, 3622 .stop_conn = iscsi_conn_stop,
3629 .send_pdu = iscsi_conn_send_pdu, 3623 .send_pdu = iscsi_conn_send_pdu,
@@ -3633,8 +3627,6 @@ static struct iscsi_transport iscsi_tcp_transport = {
3633static int __init 3627static int __init
3634iscsi_tcp_init(void) 3628iscsi_tcp_init(void)
3635{ 3629{
3636 int error;
3637
3638 if (iscsi_max_lun < 1) { 3630 if (iscsi_max_lun < 1) {
3639 printk(KERN_ERR "Invalid max_lun value of %u\n", iscsi_max_lun); 3631 printk(KERN_ERR "Invalid max_lun value of %u\n", iscsi_max_lun);
3640 return -EINVAL; 3632 return -EINVAL;
@@ -3647,11 +3639,10 @@ iscsi_tcp_init(void)
3647 if (!taskcache) 3639 if (!taskcache)
3648 return -ENOMEM; 3640 return -ENOMEM;
3649 3641
3650 error = iscsi_register_transport(&iscsi_tcp_transport); 3642 if (!iscsi_register_transport(&iscsi_tcp_transport))
3651 if (error)
3652 kmem_cache_destroy(taskcache); 3643 kmem_cache_destroy(taskcache);
3653 3644
3654 return error; 3645 return 0;
3655} 3646}
3656 3647
3657static void __exit 3648static void __exit
diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
index 855f2dfd18af..f95e61b76f70 100644
--- a/drivers/scsi/iscsi_tcp.h
+++ b/drivers/scsi/iscsi_tcp.h
@@ -158,7 +158,7 @@ struct iscsi_conn {
158 struct kfifo *mgmtqueue; /* mgmt (control) xmit queue */ 158 struct kfifo *mgmtqueue; /* mgmt (control) xmit queue */
159 struct kfifo *xmitqueue; /* data-path cmd queue */ 159 struct kfifo *xmitqueue; /* data-path cmd queue */
160 struct work_struct xmitwork; /* per-conn. xmit workqueue */ 160 struct work_struct xmitwork; /* per-conn. xmit workqueue */
161 struct semaphore xmitsema; /* serializes connection xmit, 161 struct mutex xmitmutex; /* serializes connection xmit,
162 * access to kfifos: * 162 * access to kfifos: *
163 * xmitqueue, writequeue, * 163 * xmitqueue, writequeue, *
164 * immqueue, mgmtqueue */ 164 * immqueue, mgmtqueue */
@@ -191,6 +191,8 @@ struct iscsi_conn {
191 uint32_t sendpage_failures_cnt; 191 uint32_t sendpage_failures_cnt;
192 uint32_t discontiguous_hdr_cnt; 192 uint32_t discontiguous_hdr_cnt;
193 uint32_t eh_abort_cnt; 193 uint32_t eh_abort_cnt;
194
195 ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int);
194}; 196};
195 197
196struct iscsi_session { 198struct iscsi_session {
@@ -240,8 +242,8 @@ struct iscsi_session {
240 242
241struct iscsi_buf { 243struct iscsi_buf {
242 struct scatterlist sg; 244 struct scatterlist sg;
243 struct kvec iov;
244 unsigned int sent; 245 unsigned int sent;
246 char use_sendmsg;
245}; 247};
246 248
247struct iscsi_data_task { 249struct iscsi_data_task {
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index f55b9b3f7b37..99bae8369ab2 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -1747,7 +1747,7 @@ static const struct {
1747 { ATA_SHIFT_PIO, XFER_PIO_0 }, 1747 { ATA_SHIFT_PIO, XFER_PIO_0 },
1748}; 1748};
1749 1749
1750static inline u8 base_from_shift(unsigned int shift) 1750static u8 base_from_shift(unsigned int shift)
1751{ 1751{
1752 int i; 1752 int i;
1753 1753
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 9ee8218404c0..dafabeefc5b3 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -150,7 +150,7 @@ lpfc_new_scsi_buf(struct lpfc_hba * phba)
150 return psb; 150 return psb;
151} 151}
152 152
153struct lpfc_scsi_buf* 153static struct lpfc_scsi_buf*
154lpfc_get_scsi_buf(struct lpfc_hba * phba) 154lpfc_get_scsi_buf(struct lpfc_hba * phba)
155{ 155{
156 struct lpfc_scsi_buf * lpfc_cmd = NULL; 156 struct lpfc_scsi_buf * lpfc_cmd = NULL;
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 4a6feb1e5e3d..d101a8a6f4e8 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -4479,7 +4479,7 @@ mega_internal_command(adapter_t *adapter, megacmd_t *mc, mega_passthru *pthru)
4479 * serialized. This is so because we want to reserve maximum number of 4479 * serialized. This is so because we want to reserve maximum number of
4480 * available command ids for the I/O commands. 4480 * available command ids for the I/O commands.
4481 */ 4481 */
4482 down(&adapter->int_mtx); 4482 mutex_lock(&adapter->int_mtx);
4483 4483
4484 scb = &adapter->int_scb; 4484 scb = &adapter->int_scb;
4485 memset(scb, 0, sizeof(scb_t)); 4485 memset(scb, 0, sizeof(scb_t));
@@ -4527,7 +4527,7 @@ mega_internal_command(adapter_t *adapter, megacmd_t *mc, mega_passthru *pthru)
4527 mc->cmd, mc->opcode, mc->subopcode, scmd->result); 4527 mc->cmd, mc->opcode, mc->subopcode, scmd->result);
4528 } 4528 }
4529 4529
4530 up(&adapter->int_mtx); 4530 mutex_unlock(&adapter->int_mtx);
4531 4531
4532 return rval; 4532 return rval;
4533} 4533}
@@ -4866,7 +4866,7 @@ megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
4866 adapter->has_64bit_addr = 0; 4866 adapter->has_64bit_addr = 0;
4867 } 4867 }
4868 4868
4869 init_MUTEX(&adapter->int_mtx); 4869 mutex_init(&adapter->int_mtx);
4870 init_completion(&adapter->int_waitq); 4870 init_completion(&adapter->int_waitq);
4871 4871
4872 adapter->this_id = DEFAULT_INITIATOR_ID; 4872 adapter->this_id = DEFAULT_INITIATOR_ID;
diff --git a/drivers/scsi/megaraid.h b/drivers/scsi/megaraid.h
index 6f9078025748..4b3e0d6e5afa 100644
--- a/drivers/scsi/megaraid.h
+++ b/drivers/scsi/megaraid.h
@@ -2,7 +2,7 @@
2#define __MEGARAID_H__ 2#define __MEGARAID_H__
3 3
4#include <linux/spinlock.h> 4#include <linux/spinlock.h>
5 5#include <linux/mutex.h>
6 6
7#define MEGARAID_VERSION \ 7#define MEGARAID_VERSION \
8 "v2.00.3 (Release Date: Wed Feb 19 08:51:30 EST 2003)\n" 8 "v2.00.3 (Release Date: Wed Feb 19 08:51:30 EST 2003)\n"
@@ -889,7 +889,7 @@ typedef struct {
889 889
890 scb_t int_scb; 890 scb_t int_scb;
891 Scsi_Cmnd int_scmd; 891 Scsi_Cmnd int_scmd;
892 struct semaphore int_mtx; /* To synchronize the internal 892 struct mutex int_mtx; /* To synchronize the internal
893 commands */ 893 commands */
894 struct completion int_waitq; /* wait queue for internal 894 struct completion int_waitq; /* wait queue for internal
895 cmds */ 895 cmds */
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
index d18a4bc2498c..bf9f7f7ba354 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.c
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -1266,7 +1266,7 @@ megaraid_mbox_teardown_dma_pools(adapter_t *adapter)
1266 * return the scb from the head of the free list. NULL if there are none 1266 * return the scb from the head of the free list. NULL if there are none
1267 * available 1267 * available
1268 **/ 1268 **/
1269static inline scb_t * 1269static scb_t *
1270megaraid_alloc_scb(adapter_t *adapter, struct scsi_cmnd *scp) 1270megaraid_alloc_scb(adapter_t *adapter, struct scsi_cmnd *scp)
1271{ 1271{
1272 struct list_head *head = &adapter->kscb_pool; 1272 struct list_head *head = &adapter->kscb_pool;
@@ -1329,7 +1329,7 @@ megaraid_dealloc_scb(adapter_t *adapter, scb_t *scb)
1329 * 1329 *
1330 * prepare the scatter-gather list 1330 * prepare the scatter-gather list
1331 */ 1331 */
1332static inline int 1332static int
1333megaraid_mbox_mksgl(adapter_t *adapter, scb_t *scb) 1333megaraid_mbox_mksgl(adapter_t *adapter, scb_t *scb)
1334{ 1334{
1335 struct scatterlist *sgl; 1335 struct scatterlist *sgl;
@@ -1402,7 +1402,7 @@ megaraid_mbox_mksgl(adapter_t *adapter, scb_t *scb)
1402 * 1402 *
1403 * post the command to the controller if mailbox is availble. 1403 * post the command to the controller if mailbox is availble.
1404 */ 1404 */
1405static inline int 1405static int
1406mbox_post_cmd(adapter_t *adapter, scb_t *scb) 1406mbox_post_cmd(adapter_t *adapter, scb_t *scb)
1407{ 1407{
1408 mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); 1408 mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter);
@@ -2070,7 +2070,7 @@ megaraid_mbox_prepare_epthru(adapter_t *adapter, scb_t *scb,
2070 * 2070 *
2071 * Returns: 1 if the interrupt is valid, 0 otherwise 2071 * Returns: 1 if the interrupt is valid, 0 otherwise
2072 */ 2072 */
2073static inline int 2073static int
2074megaraid_ack_sequence(adapter_t *adapter) 2074megaraid_ack_sequence(adapter_t *adapter)
2075{ 2075{
2076 mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); 2076 mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter);
@@ -2208,7 +2208,7 @@ megaraid_isr(int irq, void *devp, struct pt_regs *regs)
2208 * 2208 *
2209 * DMA sync if required. 2209 * DMA sync if required.
2210 */ 2210 */
2211static inline void 2211static void
2212megaraid_mbox_sync_scb(adapter_t *adapter, scb_t *scb) 2212megaraid_mbox_sync_scb(adapter_t *adapter, scb_t *scb)
2213{ 2213{
2214 mbox_ccb_t *ccb; 2214 mbox_ccb_t *ccb;
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index 3c32e69afcd9..511ed52a5807 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -35,6 +35,7 @@
35#include <asm/uaccess.h> 35#include <asm/uaccess.h>
36#include <linux/fs.h> 36#include <linux/fs.h>
37#include <linux/compat.h> 37#include <linux/compat.h>
38#include <linux/mutex.h>
38 39
39#include <scsi/scsi.h> 40#include <scsi/scsi.h>
40#include <scsi/scsi_cmnd.h> 41#include <scsi/scsi_cmnd.h>
@@ -72,7 +73,7 @@ MODULE_DEVICE_TABLE(pci, megasas_pci_table);
72static int megasas_mgmt_majorno; 73static int megasas_mgmt_majorno;
73static struct megasas_mgmt_info megasas_mgmt_info; 74static struct megasas_mgmt_info megasas_mgmt_info;
74static struct fasync_struct *megasas_async_queue; 75static struct fasync_struct *megasas_async_queue;
75static DECLARE_MUTEX(megasas_async_queue_mutex); 76static DEFINE_MUTEX(megasas_async_queue_mutex);
76 77
77/** 78/**
78 * megasas_get_cmd - Get a command from the free pool 79 * megasas_get_cmd - Get a command from the free pool
@@ -80,7 +81,7 @@ static DECLARE_MUTEX(megasas_async_queue_mutex);
80 * 81 *
81 * Returns a free command from the pool 82 * Returns a free command from the pool
82 */ 83 */
83static inline struct megasas_cmd *megasas_get_cmd(struct megasas_instance 84static struct megasas_cmd *megasas_get_cmd(struct megasas_instance
84 *instance) 85 *instance)
85{ 86{
86 unsigned long flags; 87 unsigned long flags;
@@ -262,7 +263,7 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance,
262 * If successful, this function returns the number of SG elements. Otherwise, 263 * If successful, this function returns the number of SG elements. Otherwise,
263 * it returnes -1. 264 * it returnes -1.
264 */ 265 */
265static inline int 266static int
266megasas_make_sgl32(struct megasas_instance *instance, struct scsi_cmnd *scp, 267megasas_make_sgl32(struct megasas_instance *instance, struct scsi_cmnd *scp,
267 union megasas_sgl *mfi_sgl) 268 union megasas_sgl *mfi_sgl)
268{ 269{
@@ -310,7 +311,7 @@ megasas_make_sgl32(struct megasas_instance *instance, struct scsi_cmnd *scp,
310 * If successful, this function returns the number of SG elements. Otherwise, 311 * If successful, this function returns the number of SG elements. Otherwise,
311 * it returnes -1. 312 * it returnes -1.
312 */ 313 */
313static inline int 314static int
314megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp, 315megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp,
315 union megasas_sgl *mfi_sgl) 316 union megasas_sgl *mfi_sgl)
316{ 317{
@@ -359,7 +360,7 @@ megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp,
359 * This function prepares CDB commands. These are typcially pass-through 360 * This function prepares CDB commands. These are typcially pass-through
360 * commands to the devices. 361 * commands to the devices.
361 */ 362 */
362static inline int 363static int
363megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, 364megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
364 struct megasas_cmd *cmd) 365 struct megasas_cmd *cmd)
365{ 366{
@@ -440,7 +441,7 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
440 * 441 *
441 * Frames (and accompanying SGLs) for regular SCSI IOs use this function. 442 * Frames (and accompanying SGLs) for regular SCSI IOs use this function.
442 */ 443 */
443static inline int 444static int
444megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, 445megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
445 struct megasas_cmd *cmd) 446 struct megasas_cmd *cmd)
446{ 447{
@@ -562,7 +563,7 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
562 * @scp: SCSI command 563 * @scp: SCSI command
563 * @frame_count: [OUT] Number of frames used to prepare this command 564 * @frame_count: [OUT] Number of frames used to prepare this command
564 */ 565 */
565static inline struct megasas_cmd *megasas_build_cmd(struct megasas_instance 566static struct megasas_cmd *megasas_build_cmd(struct megasas_instance
566 *instance, 567 *instance,
567 struct scsi_cmnd *scp, 568 struct scsi_cmnd *scp,
568 int *frame_count) 569 int *frame_count)
@@ -913,7 +914,7 @@ megasas_complete_abort(struct megasas_instance *instance,
913 * @instance: Adapter soft state 914 * @instance: Adapter soft state
914 * @cmd: Completed command 915 * @cmd: Completed command
915 */ 916 */
916static inline void 917static void
917megasas_unmap_sgbuf(struct megasas_instance *instance, struct megasas_cmd *cmd) 918megasas_unmap_sgbuf(struct megasas_instance *instance, struct megasas_cmd *cmd)
918{ 919{
919 dma_addr_t buf_h; 920 dma_addr_t buf_h;
@@ -957,7 +958,7 @@ megasas_unmap_sgbuf(struct megasas_instance *instance, struct megasas_cmd *cmd)
957 * an alternate status (as in the case of aborted 958 * an alternate status (as in the case of aborted
958 * commands) 959 * commands)
959 */ 960 */
960static inline void 961static void
961megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, 962megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
962 u8 alt_status) 963 u8 alt_status)
963{ 964{
@@ -1104,7 +1105,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
1104 * SCSI mid-layer instead of the status 1105 * SCSI mid-layer instead of the status
1105 * returned by the FW 1106 * returned by the FW
1106 */ 1107 */
1107static inline int 1108static int
1108megasas_deplete_reply_queue(struct megasas_instance *instance, u8 alt_status) 1109megasas_deplete_reply_queue(struct megasas_instance *instance, u8 alt_status)
1109{ 1110{
1110 u32 status; 1111 u32 status;
@@ -2362,11 +2363,11 @@ static int megasas_mgmt_fasync(int fd, struct file *filep, int mode)
2362{ 2363{
2363 int rc; 2364 int rc;
2364 2365
2365 down(&megasas_async_queue_mutex); 2366 mutex_lock(&megasas_async_queue_mutex);
2366 2367
2367 rc = fasync_helper(fd, filep, mode, &megasas_async_queue); 2368 rc = fasync_helper(fd, filep, mode, &megasas_async_queue);
2368 2369
2369 up(&megasas_async_queue_mutex); 2370 mutex_unlock(&megasas_async_queue_mutex);
2370 2371
2371 if (rc >= 0) { 2372 if (rc >= 0) {
2372 /* For sanity check when we get ioctl */ 2373 /* For sanity check when we get ioctl */
diff --git a/drivers/scsi/qla2xxx/Kconfig b/drivers/scsi/qla2xxx/Kconfig
index 5205c4e7d6ff..5758b2566d7f 100644
--- a/drivers/scsi/qla2xxx/Kconfig
+++ b/drivers/scsi/qla2xxx/Kconfig
@@ -1,4 +1,4 @@
1config SCSI_QLA2XXX 1config SCSI_QLA_FC
2 tristate "QLogic QLA2XXX Fibre Channel Support" 2 tristate "QLogic QLA2XXX Fibre Channel Support"
3 depends on PCI && SCSI 3 depends on PCI && SCSI
4 select SCSI_FC_ATTRS 4 select SCSI_FC_ATTRS
@@ -22,49 +22,57 @@ config SCSI_QLA2XXX
22 Upon request, the driver caches the firmware image until 22 Upon request, the driver caches the firmware image until
23 the driver is unloaded. 23 the driver is unloaded.
24 24
25 Firmware images can be retrieved from:
26
27 ftp://ftp.qlogic.com/outgoing/linux/firmware/
28
25 NOTE: The original method of building firmware-loader 29 NOTE: The original method of building firmware-loader
26 modules has been deprecated as the firmware-images will 30 modules has been deprecated as the firmware-images will
27 be removed from the kernel sources. 31 be removed from the kernel sources.
28 32
29config SCSI_QLA2XXX_EMBEDDED_FIRMWARE 33config SCSI_QLA2XXX_EMBEDDED_FIRMWARE
30 bool " Use firmware-loader modules (DEPRECATED)" 34 bool " Use firmware-loader modules (DEPRECATED)"
31 depends on SCSI_QLA2XXX 35 depends on SCSI_QLA_FC
36 help
37 This option offers you the deprecated firmware-loader
38 modules that have been obsoleted by the usage of the
39 Firmware Loader interface in the qla2xxx driver.
32 40
33config SCSI_QLA21XX 41config SCSI_QLA21XX
34 tristate " Build QLogic ISP2100 firmware-module" 42 tristate " Build QLogic ISP2100 firmware-module"
35 depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE 43 depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE
36 ---help--- 44 ---help---
37 This driver supports the QLogic 21xx (ISP2100) host adapter family. 45 This driver supports the QLogic 21xx (ISP2100) host adapter family.
38 46
39config SCSI_QLA22XX 47config SCSI_QLA22XX
40 tristate " Build QLogic ISP2200 firmware-module" 48 tristate " Build QLogic ISP2200 firmware-module"
41 depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE 49 depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE
42 ---help--- 50 ---help---
43 This driver supports the QLogic 22xx (ISP2200) host adapter family. 51 This driver supports the QLogic 22xx (ISP2200) host adapter family.
44 52
45config SCSI_QLA2300 53config SCSI_QLA2300
46 tristate " Build QLogic ISP2300 firmware-module" 54 tristate " Build QLogic ISP2300 firmware-module"
47 depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE 55 depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE
48 ---help--- 56 ---help---
49 This driver supports the QLogic 2300 (ISP2300 and ISP2312) host 57 This driver supports the QLogic 2300 (ISP2300 and ISP2312) host
50 adapter family. 58 adapter family.
51 59
52config SCSI_QLA2322 60config SCSI_QLA2322
53 tristate " Build QLogic ISP2322 firmware-module" 61 tristate " Build QLogic ISP2322 firmware-module"
54 depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE 62 depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE
55 ---help--- 63 ---help---
56 This driver supports the QLogic 2322 (ISP2322) host adapter family. 64 This driver supports the QLogic 2322 (ISP2322) host adapter family.
57 65
58config SCSI_QLA6312 66config SCSI_QLA6312
59 tristate " Build QLogic ISP63xx firmware-module" 67 tristate " Build QLogic ISP63xx firmware-module"
60 depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE 68 depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE
61 ---help--- 69 ---help---
62 This driver supports the QLogic 63xx (ISP6312 and ISP6322) host 70 This driver supports the QLogic 63xx (ISP6312 and ISP6322) host
63 adapter family. 71 adapter family.
64 72
65config SCSI_QLA24XX 73config SCSI_QLA24XX
66 tristate " Build QLogic ISP24xx firmware-module" 74 tristate " Build QLogic ISP24xx firmware-module"
67 depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE 75 depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE
68 ---help--- 76 ---help---
69 This driver supports the QLogic 24xx (ISP2422 and ISP2432) host 77 This driver supports the QLogic 24xx (ISP2422 and ISP2432) host
70 adapter family. 78 adapter family.
diff --git a/drivers/scsi/qla2xxx/Makefile b/drivers/scsi/qla2xxx/Makefile
index 40c0de125889..d028bc50ccf7 100644
--- a/drivers/scsi/qla2xxx/Makefile
+++ b/drivers/scsi/qla2xxx/Makefile
@@ -3,7 +3,7 @@ EXTRA_CFLAGS += -DUNIQUE_FW_NAME
3qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \ 3qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \
4 qla_dbg.o qla_sup.o qla_rscn.o qla_attr.o 4 qla_dbg.o qla_sup.o qla_rscn.o qla_attr.o
5 5
6obj-$(CONFIG_SCSI_QLA2XXX) += qla2xxx.o 6obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o
7 7
8qla2100-y := ql2100.o ql2100_fw.o 8qla2100-y := ql2100.o ql2100_fw.o
9qla2200-y := ql2200.o ql2200_fw.o 9qla2200-y := ql2200.o ql2200_fw.o
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 2efca52dff50..b17ee62dd1a9 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -541,7 +541,7 @@ struct fc_function_template qla2xxx_transport_functions = {
541void 541void
542qla2x00_init_host_attr(scsi_qla_host_t *ha) 542qla2x00_init_host_attr(scsi_qla_host_t *ha)
543{ 543{
544 fc_host_node_name(ha->host) = wwn_to_u64(ha->init_cb->node_name); 544 fc_host_node_name(ha->host) = wwn_to_u64(ha->node_name);
545 fc_host_port_name(ha->host) = wwn_to_u64(ha->init_cb->port_name); 545 fc_host_port_name(ha->host) = wwn_to_u64(ha->port_name);
546 fc_host_supported_classes(ha->host) = FC_COS_CLASS3; 546 fc_host_supported_classes(ha->host) = FC_COS_CLASS3;
547} 547}
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index 5c5d2315cfab..2d9b12ffe09c 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -1003,10 +1003,10 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
1003 fw = (struct qla24xx_fw_dump *) ha->fw_dump24; 1003 fw = (struct qla24xx_fw_dump *) ha->fw_dump24;
1004 1004
1005 rval = QLA_SUCCESS; 1005 rval = QLA_SUCCESS;
1006 fw->hccr = RD_REG_DWORD(&reg->hccr); 1006 fw->host_status = RD_REG_DWORD(&reg->host_status);
1007 1007
1008 /* Pause RISC. */ 1008 /* Pause RISC. */
1009 if ((fw->hccr & HCCRX_RISC_PAUSE) == 0) { 1009 if ((RD_REG_DWORD(&reg->hccr) & HCCRX_RISC_PAUSE) == 0) {
1010 WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_RESET | 1010 WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_RESET |
1011 HCCRX_CLR_HOST_INT); 1011 HCCRX_CLR_HOST_INT);
1012 RD_REG_DWORD(&reg->hccr); /* PCI Posting. */ 1012 RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
@@ -1021,16 +1021,54 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
1021 } 1021 }
1022 } 1022 }
1023 1023
1024 /* Disable interrupts. */
1025 WRT_REG_DWORD(&reg->ictrl, 0);
1026 RD_REG_DWORD(&reg->ictrl);
1027
1028 if (rval == QLA_SUCCESS) { 1024 if (rval == QLA_SUCCESS) {
1029 /* Host interface registers. */ 1025 /* Host interface registers. */
1030 dmp_reg = (uint32_t __iomem *)(reg + 0); 1026 dmp_reg = (uint32_t __iomem *)(reg + 0);
1031 for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++) 1027 for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++)
1032 fw->host_reg[cnt] = RD_REG_DWORD(dmp_reg++); 1028 fw->host_reg[cnt] = RD_REG_DWORD(dmp_reg++);
1033 1029
1030 /* Disable interrupts. */
1031 WRT_REG_DWORD(&reg->ictrl, 0);
1032 RD_REG_DWORD(&reg->ictrl);
1033
1034 /* Shadow registers. */
1035 WRT_REG_DWORD(&reg->iobase_addr, 0x0F70);
1036 RD_REG_DWORD(&reg->iobase_addr);
1037 dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
1038 WRT_REG_DWORD(dmp_reg, 0xB0000000);
1039 dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
1040 fw->shadow_reg[0] = RD_REG_DWORD(dmp_reg);
1041
1042 dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
1043 WRT_REG_DWORD(dmp_reg, 0xB0100000);
1044 dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
1045 fw->shadow_reg[1] = RD_REG_DWORD(dmp_reg);
1046
1047 dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
1048 WRT_REG_DWORD(dmp_reg, 0xB0200000);
1049 dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
1050 fw->shadow_reg[2] = RD_REG_DWORD(dmp_reg);
1051
1052 dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
1053 WRT_REG_DWORD(dmp_reg, 0xB0300000);
1054 dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
1055 fw->shadow_reg[3] = RD_REG_DWORD(dmp_reg);
1056
1057 dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
1058 WRT_REG_DWORD(dmp_reg, 0xB0400000);
1059 dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
1060 fw->shadow_reg[4] = RD_REG_DWORD(dmp_reg);
1061
1062 dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
1063 WRT_REG_DWORD(dmp_reg, 0xB0500000);
1064 dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
1065 fw->shadow_reg[5] = RD_REG_DWORD(dmp_reg);
1066
1067 dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
1068 WRT_REG_DWORD(dmp_reg, 0xB0600000);
1069 dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
1070 fw->shadow_reg[6] = RD_REG_DWORD(dmp_reg);
1071
1034 /* Mailbox registers. */ 1072 /* Mailbox registers. */
1035 mbx_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); 1073 mbx_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
1036 for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) 1074 for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++)
@@ -1308,43 +1346,6 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
1308 for (cnt = 0; cnt < 16; cnt++) 1346 for (cnt = 0; cnt < 16; cnt++)
1309 *iter_reg++ = RD_REG_DWORD(dmp_reg++); 1347 *iter_reg++ = RD_REG_DWORD(dmp_reg++);
1310 1348
1311 WRT_REG_DWORD(&reg->iobase_addr, 0x0F70);
1312 RD_REG_DWORD(&reg->iobase_addr);
1313 dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
1314 WRT_REG_DWORD(dmp_reg, 0xB0000000);
1315 dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
1316 fw->shadow_reg[0] = RD_REG_DWORD(dmp_reg);
1317
1318 dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
1319 WRT_REG_DWORD(dmp_reg, 0xB0100000);
1320 dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
1321 fw->shadow_reg[1] = RD_REG_DWORD(dmp_reg);
1322
1323 dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
1324 WRT_REG_DWORD(dmp_reg, 0xB0200000);
1325 dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
1326 fw->shadow_reg[2] = RD_REG_DWORD(dmp_reg);
1327
1328 dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
1329 WRT_REG_DWORD(dmp_reg, 0xB0300000);
1330 dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
1331 fw->shadow_reg[3] = RD_REG_DWORD(dmp_reg);
1332
1333 dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
1334 WRT_REG_DWORD(dmp_reg, 0xB0400000);
1335 dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
1336 fw->shadow_reg[4] = RD_REG_DWORD(dmp_reg);
1337
1338 dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
1339 WRT_REG_DWORD(dmp_reg, 0xB0500000);
1340 dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
1341 fw->shadow_reg[5] = RD_REG_DWORD(dmp_reg);
1342
1343 dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
1344 WRT_REG_DWORD(dmp_reg, 0xB0600000);
1345 dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
1346 fw->shadow_reg[6] = RD_REG_DWORD(dmp_reg);
1347
1348 /* Local memory controller registers. */ 1349 /* Local memory controller registers. */
1349 iter_reg = fw->lmc_reg; 1350 iter_reg = fw->lmc_reg;
1350 WRT_REG_DWORD(&reg->iobase_addr, 0x3000); 1351 WRT_REG_DWORD(&reg->iobase_addr, 0x3000);
@@ -1677,7 +1678,7 @@ qla24xx_ascii_fw_dump(scsi_qla_host_t *ha)
1677 ha->fw_major_version, ha->fw_minor_version, 1678 ha->fw_major_version, ha->fw_minor_version,
1678 ha->fw_subminor_version, ha->fw_attributes); 1679 ha->fw_subminor_version, ha->fw_attributes);
1679 1680
1680 qla_uprintf(&uiter, "\nHCCR Register\n%04x\n", fw->hccr); 1681 qla_uprintf(&uiter, "\nR2H Status Register\n%04x\n", fw->host_status);
1681 1682
1682 qla_uprintf(&uiter, "\nHost Interface Registers"); 1683 qla_uprintf(&uiter, "\nHost Interface Registers");
1683 for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++) { 1684 for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++) {
@@ -1687,6 +1688,14 @@ qla24xx_ascii_fw_dump(scsi_qla_host_t *ha)
1687 qla_uprintf(&uiter, "%08x ", fw->host_reg[cnt]); 1688 qla_uprintf(&uiter, "%08x ", fw->host_reg[cnt]);
1688 } 1689 }
1689 1690
1691 qla_uprintf(&uiter, "\n\nShadow Registers");
1692 for (cnt = 0; cnt < sizeof(fw->shadow_reg) / 4; cnt++) {
1693 if (cnt % 8 == 0)
1694 qla_uprintf(&uiter, "\n");
1695
1696 qla_uprintf(&uiter, "%08x ", fw->shadow_reg[cnt]);
1697 }
1698
1690 qla_uprintf(&uiter, "\n\nMailbox Registers"); 1699 qla_uprintf(&uiter, "\n\nMailbox Registers");
1691 for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) { 1700 for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) {
1692 if (cnt % 8 == 0) 1701 if (cnt % 8 == 0)
@@ -1855,14 +1864,6 @@ qla24xx_ascii_fw_dump(scsi_qla_host_t *ha)
1855 qla_uprintf(&uiter, "%08x ", fw->risc_gp_reg[cnt]); 1864 qla_uprintf(&uiter, "%08x ", fw->risc_gp_reg[cnt]);
1856 } 1865 }
1857 1866
1858 qla_uprintf(&uiter, "\n\nShadow Registers");
1859 for (cnt = 0; cnt < sizeof(fw->shadow_reg) / 4; cnt++) {
1860 if (cnt % 8 == 0)
1861 qla_uprintf(&uiter, "\n");
1862
1863 qla_uprintf(&uiter, "%08x ", fw->shadow_reg[cnt]);
1864 }
1865
1866 qla_uprintf(&uiter, "\n\nLMC Registers"); 1867 qla_uprintf(&uiter, "\n\nLMC Registers");
1867 for (cnt = 0; cnt < sizeof(fw->lmc_reg) / 4; cnt++) { 1868 for (cnt = 0; cnt < sizeof(fw->lmc_reg) / 4; cnt++) {
1868 if (cnt % 8 == 0) 1869 if (cnt % 8 == 0)
diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h
index 935a59a8c054..ab6afeaa2f2c 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.h
+++ b/drivers/scsi/qla2xxx/qla_dbg.h
@@ -227,8 +227,9 @@ struct qla2100_fw_dump {
227#define FW_DUMP_SIZE_24XX 0x2B0000 227#define FW_DUMP_SIZE_24XX 0x2B0000
228 228
229struct qla24xx_fw_dump { 229struct qla24xx_fw_dump {
230 uint32_t hccr; 230 uint32_t host_status;
231 uint32_t host_reg[32]; 231 uint32_t host_reg[32];
232 uint32_t shadow_reg[7];
232 uint16_t mailbox_reg[32]; 233 uint16_t mailbox_reg[32];
233 uint32_t xseq_gp_reg[128]; 234 uint32_t xseq_gp_reg[128];
234 uint32_t xseq_0_reg[16]; 235 uint32_t xseq_0_reg[16];
@@ -250,7 +251,6 @@ struct qla24xx_fw_dump {
250 uint32_t rcvt0_data_dma_reg[32]; 251 uint32_t rcvt0_data_dma_reg[32];
251 uint32_t rcvt1_data_dma_reg[32]; 252 uint32_t rcvt1_data_dma_reg[32];
252 uint32_t risc_gp_reg[128]; 253 uint32_t risc_gp_reg[128];
253 uint32_t shadow_reg[7];
254 uint32_t lmc_reg[112]; 254 uint32_t lmc_reg[112];
255 uint32_t fpm_hdw_reg[192]; 255 uint32_t fpm_hdw_reg[192];
256 uint32_t fb_hdw_reg[176]; 256 uint32_t fb_hdw_reg[176];
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index bec81adcf4fd..32be4c14cccb 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -62,6 +62,7 @@ extern int qlport_down_retry;
62extern int ql2xplogiabsentdevice; 62extern int ql2xplogiabsentdevice;
63extern int ql2xloginretrycount; 63extern int ql2xloginretrycount;
64extern int ql2xfdmienable; 64extern int ql2xfdmienable;
65extern int ql2xprocessrscn;
65 66
66extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *); 67extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *);
67 68
@@ -96,10 +97,7 @@ int __qla2x00_marker(scsi_qla_host_t *, uint16_t, uint16_t, uint8_t);
96 * Global Function Prototypes in qla_mbx.c source file. 97 * Global Function Prototypes in qla_mbx.c source file.
97 */ 98 */
98extern int 99extern int
99qla2x00_load_ram(scsi_qla_host_t *, dma_addr_t, uint16_t, uint16_t); 100qla2x00_load_ram(scsi_qla_host_t *, dma_addr_t, uint32_t, uint32_t);
100
101extern int
102qla2x00_load_ram_ext(scsi_qla_host_t *, dma_addr_t, uint32_t, uint32_t);
103 101
104extern int 102extern int
105qla2x00_execute_fw(scsi_qla_host_t *, uint32_t); 103qla2x00_execute_fw(scsi_qla_host_t *, uint32_t);
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index cd6f7c3cfe68..d620a8e8a614 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -538,6 +538,7 @@ qla2x00_rff_id(scsi_qla_host_t *ha)
538 ct_req->req.rff_id.port_id[1] = ha->d_id.b.area; 538 ct_req->req.rff_id.port_id[1] = ha->d_id.b.area;
539 ct_req->req.rff_id.port_id[2] = ha->d_id.b.al_pa; 539 ct_req->req.rff_id.port_id[2] = ha->d_id.b.al_pa;
540 540
541 ct_req->req.rff_id.fc4_feature = BIT_1;
541 ct_req->req.rff_id.fc4_type = 0x08; /* SCSI - FCP */ 542 ct_req->req.rff_id.fc4_type = 0x08; /* SCSI - FCP */
542 543
543 /* Execute MS IOCB */ 544 /* Execute MS IOCB */
@@ -1529,9 +1530,9 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha)
1529 eiter->type = __constant_cpu_to_be16(FDMI_PORT_SUPPORT_SPEED); 1530 eiter->type = __constant_cpu_to_be16(FDMI_PORT_SUPPORT_SPEED);
1530 eiter->len = __constant_cpu_to_be16(4 + 4); 1531 eiter->len = __constant_cpu_to_be16(4 + 4);
1531 if (IS_QLA25XX(ha)) 1532 if (IS_QLA25XX(ha))
1532 eiter->a.sup_speed = __constant_cpu_to_be32(4);
1533 else if (IS_QLA24XX(ha))
1534 eiter->a.sup_speed = __constant_cpu_to_be32(8); 1533 eiter->a.sup_speed = __constant_cpu_to_be32(8);
1534 else if (IS_QLA24XX(ha))
1535 eiter->a.sup_speed = __constant_cpu_to_be32(4);
1535 else if (IS_QLA23XX(ha)) 1536 else if (IS_QLA23XX(ha))
1536 eiter->a.sup_speed = __constant_cpu_to_be32(2); 1537 eiter->a.sup_speed = __constant_cpu_to_be32(2);
1537 else 1538 else
@@ -1553,9 +1554,6 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha)
1553 eiter->a.cur_speed = __constant_cpu_to_be32(2); 1554 eiter->a.cur_speed = __constant_cpu_to_be32(2);
1554 break; 1555 break;
1555 case 3: 1556 case 3:
1556 eiter->a.cur_speed = __constant_cpu_to_be32(8);
1557 break;
1558 case 4:
1559 eiter->a.cur_speed = __constant_cpu_to_be32(4); 1557 eiter->a.cur_speed = __constant_cpu_to_be32(4);
1560 break; 1558 break;
1561 } 1559 }
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 7d973bd9022b..a91fea69ad63 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1014,11 +1014,13 @@ qla24xx_update_fw_options(scsi_qla_host_t *ha)
1014 int rval; 1014 int rval;
1015 1015
1016 /* Update Serial Link options. */ 1016 /* Update Serial Link options. */
1017 if ((ha->fw_seriallink_options24[0] & BIT_0) == 0) 1017 if ((le16_to_cpu(ha->fw_seriallink_options24[0]) & BIT_0) == 0)
1018 return; 1018 return;
1019 1019
1020 rval = qla2x00_set_serdes_params(ha, ha->fw_seriallink_options24[1], 1020 rval = qla2x00_set_serdes_params(ha,
1021 ha->fw_seriallink_options24[2], ha->fw_seriallink_options24[3]); 1021 le16_to_cpu(ha->fw_seriallink_options24[1]),
1022 le16_to_cpu(ha->fw_seriallink_options24[2]),
1023 le16_to_cpu(ha->fw_seriallink_options24[3]));
1022 if (rval != QLA_SUCCESS) { 1024 if (rval != QLA_SUCCESS) {
1023 qla_printk(KERN_WARNING, ha, 1025 qla_printk(KERN_WARNING, ha,
1024 "Unable to update Serial Link options (%x).\n", rval); 1026 "Unable to update Serial Link options (%x).\n", rval);
@@ -1939,6 +1941,9 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha)
1939 "information -- get_port_database=%x, " 1941 "information -- get_port_database=%x, "
1940 "loop_id=0x%04x\n", 1942 "loop_id=0x%04x\n",
1941 ha->host_no, rval2, new_fcport->loop_id)); 1943 ha->host_no, rval2, new_fcport->loop_id));
1944 DEBUG2(printk("scsi(%ld): Scheduling resync...\n",
1945 ha->host_no));
1946 set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
1942 continue; 1947 continue;
1943 } 1948 }
1944 1949
@@ -2648,7 +2653,8 @@ qla2x00_device_resync(scsi_qla_host_t *ha)
2648 2653
2649 switch (format) { 2654 switch (format) {
2650 case 0: 2655 case 0:
2651 if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && 2656 if (ql2xprocessrscn &&
2657 !IS_QLA2100(ha) && !IS_QLA2200(ha) &&
2652 !IS_QLA6312(ha) && !IS_QLA6322(ha) && 2658 !IS_QLA6312(ha) && !IS_QLA6322(ha) &&
2653 !IS_QLA24XX(ha) && !IS_QLA25XX(ha) && 2659 !IS_QLA24XX(ha) && !IS_QLA25XX(ha) &&
2654 ha->flags.init_done) { 2660 ha->flags.init_done) {
@@ -3402,6 +3408,8 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
3402 ha->node_name = icb->node_name; 3408 ha->node_name = icb->node_name;
3403 ha->port_name = icb->port_name; 3409 ha->port_name = icb->port_name;
3404 3410
3411 icb->execution_throttle = __constant_cpu_to_le16(0xFFFF);
3412
3405 ha->retry_count = le16_to_cpu(nv->login_retry_count); 3413 ha->retry_count = le16_to_cpu(nv->login_retry_count);
3406 3414
3407 /* Set minimum login_timeout to 4 seconds. */ 3415 /* Set minimum login_timeout to 4 seconds. */
@@ -3667,8 +3675,8 @@ qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr)
3667 for (i = 0; i < dlen; i++) 3675 for (i = 0; i < dlen; i++)
3668 dcode[i] = swab32(dcode[i]); 3676 dcode[i] = swab32(dcode[i]);
3669 3677
3670 rval = qla2x00_load_ram_ext(ha, ha->request_dma, 3678 rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr,
3671 risc_addr, dlen); 3679 dlen);
3672 if (rval) { 3680 if (rval) {
3673 DEBUG(printk("scsi(%ld):[ERROR] Failed to load " 3681 DEBUG(printk("scsi(%ld):[ERROR] Failed to load "
3674 "segment %d of firmware\n", ha->host_no, 3682 "segment %d of firmware\n", ha->host_no,
@@ -3868,8 +3876,8 @@ qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
3868 for (i = 0; i < dlen; i++) 3876 for (i = 0; i < dlen; i++)
3869 dcode[i] = swab32(fwcode[i]); 3877 dcode[i] = swab32(fwcode[i]);
3870 3878
3871 rval = qla2x00_load_ram_ext(ha, ha->request_dma, 3879 rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr,
3872 risc_addr, dlen); 3880 dlen);
3873 if (rval) { 3881 if (rval) {
3874 DEBUG(printk("scsi(%ld):[ERROR] Failed to load " 3882 DEBUG(printk("scsi(%ld):[ERROR] Failed to load "
3875 "segment %d of firmware\n", ha->host_no, 3883 "segment %d of firmware\n", ha->host_no,
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 5181d966fecb..f63af081d4ff 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -519,7 +519,8 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
519 * us, create a new entry in our rscn fcports list and handle 519 * us, create a new entry in our rscn fcports list and handle
520 * the event like an RSCN. 520 * the event like an RSCN.
521 */ 521 */
522 if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA6312(ha) && 522 if (ql2xprocessrscn &&
523 !IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA6312(ha) &&
523 !IS_QLA6322(ha) && !IS_QLA24XX(ha) && !IS_QLA25XX(ha) && 524 !IS_QLA6322(ha) && !IS_QLA24XX(ha) && !IS_QLA25XX(ha) &&
524 ha->flags.init_done && mb[1] != 0xffff && 525 ha->flags.init_done && mb[1] != 0xffff &&
525 ((ha->operating_mode == P2P && mb[1] != 0) || 526 ((ha->operating_mode == P2P && mb[1] != 0) ||
@@ -963,15 +964,16 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
963 break; 964 break;
964 965
965 case CS_DATA_UNDERRUN: 966 case CS_DATA_UNDERRUN:
966 DEBUG2(printk(KERN_INFO
967 "scsi(%ld:%d:%d) UNDERRUN status detected 0x%x-0x%x.\n",
968 ha->host_no, cp->device->id, cp->device->lun, comp_status,
969 scsi_status));
970
971 resid = resid_len; 967 resid = resid_len;
972 if (scsi_status & SS_RESIDUAL_UNDER) { 968 if (scsi_status & SS_RESIDUAL_UNDER) {
973 cp->resid = resid; 969 cp->resid = resid;
974 CMD_RESID_LEN(cp) = resid; 970 CMD_RESID_LEN(cp) = resid;
971 } else {
972 DEBUG2(printk(KERN_INFO
973 "scsi(%ld:%d:%d) UNDERRUN status detected "
974 "0x%x-0x%x.\n", ha->host_no, cp->device->id,
975 cp->device->lun, comp_status, scsi_status));
976
975 } 977 }
976 978
977 /* 979 /*
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 9746cd1e664b..3099b379de9d 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -196,7 +196,9 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
196 /* Check for pending interrupts. */ 196 /* Check for pending interrupts. */
197 qla2x00_poll(ha); 197 qla2x00_poll(ha);
198 198
199 udelay(10); /* v4.27 */ 199 if (command != MBC_LOAD_RISC_RAM_EXTENDED &&
200 !ha->flags.mbox_int)
201 msleep(10);
200 } /* while */ 202 } /* while */
201 } 203 }
202 204
@@ -325,113 +327,30 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
325 return rval; 327 return rval;
326} 328}
327 329
328/*
329 * qla2x00_load_ram
330 * Load adapter RAM using DMA.
331 *
332 * Input:
333 * ha = adapter block pointer.
334 *
335 * Returns:
336 * qla2x00 local function return status code.
337 *
338 * Context:
339 * Kernel context.
340 */
341int 330int
342qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint16_t risc_addr, 331qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t risc_addr,
343 uint16_t risc_code_size) 332 uint32_t risc_code_size)
344{ 333{
345 int rval; 334 int rval;
346 mbx_cmd_t mc; 335 mbx_cmd_t mc;
347 mbx_cmd_t *mcp = &mc; 336 mbx_cmd_t *mcp = &mc;
348 uint32_t req_len;
349 dma_addr_t nml_dma;
350 uint32_t nml_len;
351 uint32_t normalized;
352
353 DEBUG11(printk("qla2x00_load_ram(%ld): entered.\n",
354 ha->host_no);)
355 337
356 req_len = risc_code_size; 338 DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
357 nml_dma = 0;
358 nml_len = 0;
359
360 normalized = qla2x00_normalize_dma_addr(&req_dma, &req_len, &nml_dma,
361 &nml_len);
362
363 /* Load first segment */
364 mcp->mb[0] = MBC_LOAD_RISC_RAM;
365 mcp->mb[1] = risc_addr;
366 mcp->mb[2] = MSW(req_dma);
367 mcp->mb[3] = LSW(req_dma);
368 mcp->mb[4] = (uint16_t)req_len;
369 mcp->mb[6] = MSW(MSD(req_dma));
370 mcp->mb[7] = LSW(MSD(req_dma));
371 mcp->out_mb = MBX_7|MBX_6|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
372 mcp->in_mb = MBX_0;
373 mcp->tov = 30;
374 mcp->flags = 0;
375 rval = qla2x00_mailbox_command(ha, mcp);
376
377 /* Load second segment - if necessary */
378 if (normalized && (rval == QLA_SUCCESS)) {
379 mcp->mb[0] = MBC_LOAD_RISC_RAM;
380 mcp->mb[1] = risc_addr + (uint16_t)req_len;
381 mcp->mb[2] = MSW(nml_dma);
382 mcp->mb[3] = LSW(nml_dma);
383 mcp->mb[4] = (uint16_t)nml_len;
384 mcp->mb[6] = MSW(MSD(nml_dma));
385 mcp->mb[7] = LSW(MSD(nml_dma));
386 mcp->out_mb = MBX_7|MBX_6|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
387 mcp->in_mb = MBX_0;
388 mcp->tov = 30;
389 mcp->flags = 0;
390 rval = qla2x00_mailbox_command(ha, mcp);
391 }
392 339
393 if (rval == QLA_SUCCESS) { 340 if (MSW(risc_addr) || IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
394 /* Empty */ 341 mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED;
395 DEBUG11(printk("qla2x00_load_ram(%ld): done.\n", ha->host_no);) 342 mcp->mb[8] = MSW(risc_addr);
343 mcp->out_mb = MBX_8|MBX_0;
396 } else { 344 } else {
397 /* Empty */ 345 mcp->mb[0] = MBC_LOAD_RISC_RAM;
398 DEBUG2_3_11(printk("qla2x00_load_ram(%ld): failed. rval=%x " 346 mcp->out_mb = MBX_0;
399 "mb[0]=%x.\n", ha->host_no, rval, mcp->mb[0]);)
400 } 347 }
401 return rval;
402}
403
404/*
405 * qla2x00_load_ram_ext
406 * Load adapter extended RAM using DMA.
407 *
408 * Input:
409 * ha = adapter block pointer.
410 *
411 * Returns:
412 * qla2x00 local function return status code.
413 *
414 * Context:
415 * Kernel context.
416 */
417int
418qla2x00_load_ram_ext(scsi_qla_host_t *ha, dma_addr_t req_dma,
419 uint32_t risc_addr, uint32_t risc_code_size)
420{
421 int rval;
422 mbx_cmd_t mc;
423 mbx_cmd_t *mcp = &mc;
424
425 DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
426
427 mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED;
428 mcp->mb[1] = LSW(risc_addr); 348 mcp->mb[1] = LSW(risc_addr);
429 mcp->mb[2] = MSW(req_dma); 349 mcp->mb[2] = MSW(req_dma);
430 mcp->mb[3] = LSW(req_dma); 350 mcp->mb[3] = LSW(req_dma);
431 mcp->mb[6] = MSW(MSD(req_dma)); 351 mcp->mb[6] = MSW(MSD(req_dma));
432 mcp->mb[7] = LSW(MSD(req_dma)); 352 mcp->mb[7] = LSW(MSD(req_dma));
433 mcp->mb[8] = MSW(risc_addr); 353 mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_1;
434 mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
435 if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { 354 if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
436 mcp->mb[4] = MSW(risc_code_size); 355 mcp->mb[4] = MSW(risc_code_size);
437 mcp->mb[5] = LSW(risc_code_size); 356 mcp->mb[5] = LSW(risc_code_size);
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 24304300d7b5..4916847d84ec 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -71,6 +71,12 @@ MODULE_PARM_DESC(ql2xfdmienable,
71 "Enables FDMI registratons " 71 "Enables FDMI registratons "
72 "Default is 0 - no FDMI. 1 - perfom FDMI."); 72 "Default is 0 - no FDMI. 1 - perfom FDMI.");
73 73
74int ql2xprocessrscn;
75module_param(ql2xprocessrscn, int, S_IRUGO|S_IRUSR);
76MODULE_PARM_DESC(ql2xprocessrscn,
77 "Option to enable port RSCN handling via a series of less"
78 "fabric intrusive ADISCs and PLOGIs.");
79
74/* 80/*
75 * SCSI host template entry points 81 * SCSI host template entry points
76 */ 82 */
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index d54d2a99c3d3..f4d755a643e4 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -573,6 +573,9 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
573 } 573 }
574 } while (0); 574 } while (0);
575 575
576 /* Enable flash write-protection. */
577 qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0x9c);
578
576 /* Disable flash write. */ 579 /* Disable flash write. */
577 WRT_REG_DWORD(&reg->ctrl_status, 580 WRT_REG_DWORD(&reg->ctrl_status,
578 RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE); 581 RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index f7937f7f9c68..d537192a1edb 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -7,9 +7,9 @@
7/* 7/*
8 * Driver version 8 * Driver version
9 */ 9 */
10#define QLA2XXX_VERSION "8.01.03-k" 10#define QLA2XXX_VERSION "8.01.04-k"
11 11
12#define QLA_DRIVER_MAJOR_VER 8 12#define QLA_DRIVER_MAJOR_VER 8
13#define QLA_DRIVER_MINOR_VER 1 13#define QLA_DRIVER_MINOR_VER 1
14#define QLA_DRIVER_PATCH_VER 3 14#define QLA_DRIVER_PATCH_VER 4
15#define QLA_DRIVER_BETA_VER 0 15#define QLA_DRIVER_BETA_VER 0
diff --git a/drivers/scsi/raid_class.c b/drivers/scsi/raid_class.c
index 5ec5f44602ac..50c398aab557 100644
--- a/drivers/scsi/raid_class.c
+++ b/drivers/scsi/raid_class.c
@@ -148,9 +148,11 @@ static struct {
148 { RAID_LEVEL_LINEAR, "linear" }, 148 { RAID_LEVEL_LINEAR, "linear" },
149 { RAID_LEVEL_0, "raid0" }, 149 { RAID_LEVEL_0, "raid0" },
150 { RAID_LEVEL_1, "raid1" }, 150 { RAID_LEVEL_1, "raid1" },
151 { RAID_LEVEL_10, "raid10" },
151 { RAID_LEVEL_3, "raid3" }, 152 { RAID_LEVEL_3, "raid3" },
152 { RAID_LEVEL_4, "raid4" }, 153 { RAID_LEVEL_4, "raid4" },
153 { RAID_LEVEL_5, "raid5" }, 154 { RAID_LEVEL_5, "raid5" },
155 { RAID_LEVEL_50, "raid50" },
154 { RAID_LEVEL_6, "raid6" }, 156 { RAID_LEVEL_6, "raid6" },
155}; 157};
156 158
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index ee5f4dfdab14..245ca99a641e 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -55,6 +55,7 @@
55#include <linux/interrupt.h> 55#include <linux/interrupt.h>
56#include <linux/notifier.h> 56#include <linux/notifier.h>
57#include <linux/cpu.h> 57#include <linux/cpu.h>
58#include <linux/mutex.h>
58 59
59#include <scsi/scsi.h> 60#include <scsi/scsi.h>
60#include <scsi/scsi_cmnd.h> 61#include <scsi/scsi_cmnd.h>
@@ -209,7 +210,7 @@ static struct scsi_host_cmd_pool scsi_cmd_dma_pool = {
209 .gfp_mask = __GFP_DMA, 210 .gfp_mask = __GFP_DMA,
210}; 211};
211 212
212static DECLARE_MUTEX(host_cmd_pool_mutex); 213static DEFINE_MUTEX(host_cmd_pool_mutex);
213 214
214static struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, 215static struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost,
215 gfp_t gfp_mask) 216 gfp_t gfp_mask)
@@ -330,7 +331,7 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost)
330 * Select a command slab for this host and create it if not 331 * Select a command slab for this host and create it if not
331 * yet existant. 332 * yet existant.
332 */ 333 */
333 down(&host_cmd_pool_mutex); 334 mutex_lock(&host_cmd_pool_mutex);
334 pool = (shost->unchecked_isa_dma ? &scsi_cmd_dma_pool : &scsi_cmd_pool); 335 pool = (shost->unchecked_isa_dma ? &scsi_cmd_dma_pool : &scsi_cmd_pool);
335 if (!pool->users) { 336 if (!pool->users) {
336 pool->slab = kmem_cache_create(pool->name, 337 pool->slab = kmem_cache_create(pool->name,
@@ -342,7 +343,7 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost)
342 343
343 pool->users++; 344 pool->users++;
344 shost->cmd_pool = pool; 345 shost->cmd_pool = pool;
345 up(&host_cmd_pool_mutex); 346 mutex_unlock(&host_cmd_pool_mutex);
346 347
347 /* 348 /*
348 * Get one backup command for this host. 349 * Get one backup command for this host.
@@ -359,7 +360,7 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost)
359 kmem_cache_destroy(pool->slab); 360 kmem_cache_destroy(pool->slab);
360 return -ENOMEM; 361 return -ENOMEM;
361 fail: 362 fail:
362 up(&host_cmd_pool_mutex); 363 mutex_unlock(&host_cmd_pool_mutex);
363 return -ENOMEM; 364 return -ENOMEM;
364 365
365} 366}
@@ -381,10 +382,10 @@ void scsi_destroy_command_freelist(struct Scsi_Host *shost)
381 kmem_cache_free(shost->cmd_pool->slab, cmd); 382 kmem_cache_free(shost->cmd_pool->slab, cmd);
382 } 383 }
383 384
384 down(&host_cmd_pool_mutex); 385 mutex_lock(&host_cmd_pool_mutex);
385 if (!--shost->cmd_pool->users) 386 if (!--shost->cmd_pool->users)
386 kmem_cache_destroy(shost->cmd_pool->slab); 387 kmem_cache_destroy(shost->cmd_pool->slab);
387 up(&host_cmd_pool_mutex); 388 mutex_unlock(&host_cmd_pool_mutex);
388} 389}
389 390
390#ifdef CONFIG_SCSI_LOGGING 391#ifdef CONFIG_SCSI_LOGGING
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 3ded9daaf4a0..0e529f8171c4 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -221,8 +221,6 @@ static struct bus_type pseudo_lld_bus;
221static struct device_driver sdebug_driverfs_driver = { 221static struct device_driver sdebug_driverfs_driver = {
222 .name = sdebug_proc_name, 222 .name = sdebug_proc_name,
223 .bus = &pseudo_lld_bus, 223 .bus = &pseudo_lld_bus,
224 .probe = sdebug_driver_probe,
225 .remove = sdebug_driver_remove,
226}; 224};
227 225
228static const int check_condition_result = 226static const int check_condition_result =
@@ -1796,6 +1794,8 @@ static int pseudo_lld_bus_match(struct device *dev,
1796static struct bus_type pseudo_lld_bus = { 1794static struct bus_type pseudo_lld_bus = {
1797 .name = "pseudo", 1795 .name = "pseudo",
1798 .match = pseudo_lld_bus_match, 1796 .match = pseudo_lld_bus_match,
1797 .probe = sdebug_driver_probe,
1798 .remove = sdebug_driver_remove,
1799}; 1799};
1800 1800
1801static void sdebug_release_adapter(struct device * dev) 1801static void sdebug_release_adapter(struct device * dev)
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 00c9bf383e23..3574ba935af8 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1212,7 +1212,7 @@ static int scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk,
1212 return -EOPNOTSUPP; 1212 return -EOPNOTSUPP;
1213} 1213}
1214 1214
1215static void scsi_generic_done(struct scsi_cmnd *cmd) 1215static void scsi_blk_pc_done(struct scsi_cmnd *cmd)
1216{ 1216{
1217 BUG_ON(!blk_pc_request(cmd->request)); 1217 BUG_ON(!blk_pc_request(cmd->request));
1218 /* 1218 /*
@@ -1224,7 +1224,7 @@ static void scsi_generic_done(struct scsi_cmnd *cmd)
1224 scsi_io_completion(cmd, cmd->bufflen, 0); 1224 scsi_io_completion(cmd, cmd->bufflen, 0);
1225} 1225}
1226 1226
1227void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd) 1227static void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd)
1228{ 1228{
1229 struct request *req = cmd->request; 1229 struct request *req = cmd->request;
1230 1230
@@ -1241,8 +1241,8 @@ void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd)
1241 cmd->transfersize = req->data_len; 1241 cmd->transfersize = req->data_len;
1242 cmd->allowed = req->retries; 1242 cmd->allowed = req->retries;
1243 cmd->timeout_per_command = req->timeout; 1243 cmd->timeout_per_command = req->timeout;
1244 cmd->done = scsi_blk_pc_done;
1244} 1245}
1245EXPORT_SYMBOL_GPL(scsi_setup_blk_pc_cmnd);
1246 1246
1247static int scsi_prep_fn(struct request_queue *q, struct request *req) 1247static int scsi_prep_fn(struct request_queue *q, struct request *req)
1248{ 1248{
@@ -1339,7 +1339,6 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
1339 * happening now. 1339 * happening now.
1340 */ 1340 */
1341 if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) { 1341 if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) {
1342 struct scsi_driver *drv;
1343 int ret; 1342 int ret;
1344 1343
1345 /* 1344 /*
@@ -1371,16 +1370,17 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
1371 /* 1370 /*
1372 * Initialize the actual SCSI command for this request. 1371 * Initialize the actual SCSI command for this request.
1373 */ 1372 */
1374 if (req->rq_disk) { 1373 if (req->flags & REQ_BLOCK_PC) {
1374 scsi_setup_blk_pc_cmnd(cmd);
1375 } else if (req->rq_disk) {
1376 struct scsi_driver *drv;
1377
1375 drv = *(struct scsi_driver **)req->rq_disk->private_data; 1378 drv = *(struct scsi_driver **)req->rq_disk->private_data;
1376 if (unlikely(!drv->init_command(cmd))) { 1379 if (unlikely(!drv->init_command(cmd))) {
1377 scsi_release_buffers(cmd); 1380 scsi_release_buffers(cmd);
1378 scsi_put_command(cmd); 1381 scsi_put_command(cmd);
1379 goto kill; 1382 goto kill;
1380 } 1383 }
1381 } else {
1382 scsi_setup_blk_pc_cmnd(cmd);
1383 cmd->done = scsi_generic_done;
1384 } 1384 }
1385 } 1385 }
1386 1386
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index 14a6198cb8d2..27c48274e8cb 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -26,12 +26,6 @@ struct Scsi_Host;
26#define SCSI_SENSE_VALID(scmd) \ 26#define SCSI_SENSE_VALID(scmd) \
27 (((scmd)->sense_buffer[0] & 0x70) == 0x70) 27 (((scmd)->sense_buffer[0] & 0x70) == 0x70)
28 28
29/*
30 * Special value for scanning to specify scanning or rescanning of all
31 * possible channels, (target) ids, or luns on a given shost.
32 */
33#define SCAN_WILD_CARD ~0
34
35/* hosts.c */ 29/* hosts.c */
36extern int scsi_init_hosts(void); 30extern int scsi_init_hosts(void);
37extern void scsi_exit_hosts(void); 31extern void scsi_exit_hosts(void);
diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c
index a50958b1b6ee..07be62bbaaea 100644
--- a/drivers/scsi/scsi_proc.c
+++ b/drivers/scsi/scsi_proc.c
@@ -25,11 +25,13 @@
25#include <linux/errno.h> 25#include <linux/errno.h>
26#include <linux/blkdev.h> 26#include <linux/blkdev.h>
27#include <linux/seq_file.h> 27#include <linux/seq_file.h>
28#include <linux/mutex.h>
28#include <asm/uaccess.h> 29#include <asm/uaccess.h>
29 30
30#include <scsi/scsi.h> 31#include <scsi/scsi.h>
31#include <scsi/scsi_device.h> 32#include <scsi/scsi_device.h>
32#include <scsi/scsi_host.h> 33#include <scsi/scsi_host.h>
34#include <scsi/scsi_transport.h>
33 35
34#include "scsi_priv.h" 36#include "scsi_priv.h"
35#include "scsi_logging.h" 37#include "scsi_logging.h"
@@ -41,7 +43,7 @@
41static struct proc_dir_entry *proc_scsi; 43static struct proc_dir_entry *proc_scsi;
42 44
43/* Protect sht->present and sht->proc_dir */ 45/* Protect sht->present and sht->proc_dir */
44static DECLARE_MUTEX(global_host_template_sem); 46static DEFINE_MUTEX(global_host_template_mutex);
45 47
46static int proc_scsi_read(char *buffer, char **start, off_t offset, 48static int proc_scsi_read(char *buffer, char **start, off_t offset,
47 int length, int *eof, void *data) 49 int length, int *eof, void *data)
@@ -83,7 +85,7 @@ void scsi_proc_hostdir_add(struct scsi_host_template *sht)
83 if (!sht->proc_info) 85 if (!sht->proc_info)
84 return; 86 return;
85 87
86 down(&global_host_template_sem); 88 mutex_lock(&global_host_template_mutex);
87 if (!sht->present++) { 89 if (!sht->present++) {
88 sht->proc_dir = proc_mkdir(sht->proc_name, proc_scsi); 90 sht->proc_dir = proc_mkdir(sht->proc_name, proc_scsi);
89 if (!sht->proc_dir) 91 if (!sht->proc_dir)
@@ -92,7 +94,7 @@ void scsi_proc_hostdir_add(struct scsi_host_template *sht)
92 else 94 else
93 sht->proc_dir->owner = sht->module; 95 sht->proc_dir->owner = sht->module;
94 } 96 }
95 up(&global_host_template_sem); 97 mutex_unlock(&global_host_template_mutex);
96} 98}
97 99
98void scsi_proc_hostdir_rm(struct scsi_host_template *sht) 100void scsi_proc_hostdir_rm(struct scsi_host_template *sht)
@@ -100,12 +102,12 @@ void scsi_proc_hostdir_rm(struct scsi_host_template *sht)
100 if (!sht->proc_info) 102 if (!sht->proc_info)
101 return; 103 return;
102 104
103 down(&global_host_template_sem); 105 mutex_lock(&global_host_template_mutex);
104 if (!--sht->present && sht->proc_dir) { 106 if (!--sht->present && sht->proc_dir) {
105 remove_proc_entry(sht->proc_name, proc_scsi); 107 remove_proc_entry(sht->proc_name, proc_scsi);
106 sht->proc_dir = NULL; 108 sht->proc_dir = NULL;
107 } 109 }
108 up(&global_host_template_sem); 110 mutex_unlock(&global_host_template_mutex);
109} 111}
110 112
111void scsi_proc_host_add(struct Scsi_Host *shost) 113void scsi_proc_host_add(struct Scsi_Host *shost)
@@ -199,7 +201,10 @@ static int scsi_add_single_device(uint host, uint channel, uint id, uint lun)
199 if (IS_ERR(shost)) 201 if (IS_ERR(shost))
200 return PTR_ERR(shost); 202 return PTR_ERR(shost);
201 203
202 error = scsi_scan_host_selected(shost, channel, id, lun, 1); 204 if (shost->transportt->user_scan)
205 error = shost->transportt->user_scan(shost, channel, id, lun);
206 else
207 error = scsi_scan_host_selected(shost, channel, id, lun, 1);
203 scsi_host_put(shost); 208 scsi_host_put(shost);
204 return error; 209 return error;
205} 210}
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 05ebb9cef961..752fb5da3de4 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -334,19 +334,6 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
334 struct scsi_target *starget; 334 struct scsi_target *starget;
335 struct scsi_target *found_target; 335 struct scsi_target *found_target;
336 336
337 /*
338 * Obtain the real parent from the transport. The transport
339 * is allowed to fail (no error) if there is nothing at that
340 * target id.
341 */
342 if (shost->transportt->target_parent) {
343 spin_lock_irqsave(shost->host_lock, flags);
344 parent = shost->transportt->target_parent(shost, channel, id);
345 spin_unlock_irqrestore(shost->host_lock, flags);
346 if (!parent)
347 return NULL;
348 }
349
350 starget = kmalloc(size, GFP_KERNEL); 337 starget = kmalloc(size, GFP_KERNEL);
351 if (!starget) { 338 if (!starget) {
352 printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__); 339 printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__);
@@ -1283,20 +1270,21 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
1283 struct scsi_device *sdev; 1270 struct scsi_device *sdev;
1284 struct device *parent = &shost->shost_gendev; 1271 struct device *parent = &shost->shost_gendev;
1285 int res; 1272 int res;
1286 struct scsi_target *starget = scsi_alloc_target(parent, channel, id); 1273 struct scsi_target *starget;
1287 1274
1275 starget = scsi_alloc_target(parent, channel, id);
1288 if (!starget) 1276 if (!starget)
1289 return ERR_PTR(-ENOMEM); 1277 return ERR_PTR(-ENOMEM);
1290 1278
1291 get_device(&starget->dev); 1279 get_device(&starget->dev);
1292 down(&shost->scan_mutex); 1280 mutex_lock(&shost->scan_mutex);
1293 if (scsi_host_scan_allowed(shost)) { 1281 if (scsi_host_scan_allowed(shost)) {
1294 res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, 1282 res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1,
1295 hostdata); 1283 hostdata);
1296 if (res != SCSI_SCAN_LUN_PRESENT) 1284 if (res != SCSI_SCAN_LUN_PRESENT)
1297 sdev = ERR_PTR(-ENODEV); 1285 sdev = ERR_PTR(-ENODEV);
1298 } 1286 }
1299 up(&shost->scan_mutex); 1287 mutex_unlock(&shost->scan_mutex);
1300 scsi_target_reap(starget); 1288 scsi_target_reap(starget);
1301 put_device(&starget->dev); 1289 put_device(&starget->dev);
1302 1290
@@ -1404,10 +1392,10 @@ void scsi_scan_target(struct device *parent, unsigned int channel,
1404{ 1392{
1405 struct Scsi_Host *shost = dev_to_shost(parent); 1393 struct Scsi_Host *shost = dev_to_shost(parent);
1406 1394
1407 down(&shost->scan_mutex); 1395 mutex_lock(&shost->scan_mutex);
1408 if (scsi_host_scan_allowed(shost)) 1396 if (scsi_host_scan_allowed(shost))
1409 __scsi_scan_target(parent, channel, id, lun, rescan); 1397 __scsi_scan_target(parent, channel, id, lun, rescan);
1410 up(&shost->scan_mutex); 1398 mutex_unlock(&shost->scan_mutex);
1411} 1399}
1412EXPORT_SYMBOL(scsi_scan_target); 1400EXPORT_SYMBOL(scsi_scan_target);
1413 1401
@@ -1454,7 +1442,7 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
1454 ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun))) 1442 ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun)))
1455 return -EINVAL; 1443 return -EINVAL;
1456 1444
1457 down(&shost->scan_mutex); 1445 mutex_lock(&shost->scan_mutex);
1458 if (scsi_host_scan_allowed(shost)) { 1446 if (scsi_host_scan_allowed(shost)) {
1459 if (channel == SCAN_WILD_CARD) 1447 if (channel == SCAN_WILD_CARD)
1460 for (channel = 0; channel <= shost->max_channel; 1448 for (channel = 0; channel <= shost->max_channel;
@@ -1464,7 +1452,7 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
1464 else 1452 else
1465 scsi_scan_channel(shost, channel, id, lun, rescan); 1453 scsi_scan_channel(shost, channel, id, lun, rescan);
1466 } 1454 }
1467 up(&shost->scan_mutex); 1455 mutex_unlock(&shost->scan_mutex);
1468 1456
1469 return 0; 1457 return 0;
1470} 1458}
@@ -1522,7 +1510,7 @@ struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost)
1522 struct scsi_device *sdev = NULL; 1510 struct scsi_device *sdev = NULL;
1523 struct scsi_target *starget; 1511 struct scsi_target *starget;
1524 1512
1525 down(&shost->scan_mutex); 1513 mutex_lock(&shost->scan_mutex);
1526 if (!scsi_host_scan_allowed(shost)) 1514 if (!scsi_host_scan_allowed(shost))
1527 goto out; 1515 goto out;
1528 starget = scsi_alloc_target(&shost->shost_gendev, 0, shost->this_id); 1516 starget = scsi_alloc_target(&shost->shost_gendev, 0, shost->this_id);
@@ -1536,7 +1524,7 @@ struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost)
1536 } 1524 }
1537 put_device(&starget->dev); 1525 put_device(&starget->dev);
1538 out: 1526 out:
1539 up(&shost->scan_mutex); 1527 mutex_unlock(&shost->scan_mutex);
1540 return sdev; 1528 return sdev;
1541} 1529}
1542EXPORT_SYMBOL(scsi_get_host_dev); 1530EXPORT_SYMBOL(scsi_get_host_dev);
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index ea7f3a433572..a77b32deaf8f 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -106,7 +106,10 @@ static int scsi_scan(struct Scsi_Host *shost, const char *str)
106 return -EINVAL; 106 return -EINVAL;
107 if (check_set(&lun, s3)) 107 if (check_set(&lun, s3))
108 return -EINVAL; 108 return -EINVAL;
109 res = scsi_scan_host_selected(shost, channel, id, lun, 1); 109 if (shost->transportt->user_scan)
110 res = shost->transportt->user_scan(shost, channel, id, lun);
111 else
112 res = scsi_scan_host_selected(shost, channel, id, lun, 1);
110 return res; 113 return res;
111} 114}
112 115
@@ -745,9 +748,9 @@ void scsi_remove_device(struct scsi_device *sdev)
745{ 748{
746 struct Scsi_Host *shost = sdev->host; 749 struct Scsi_Host *shost = sdev->host;
747 750
748 down(&shost->scan_mutex); 751 mutex_lock(&shost->scan_mutex);
749 __scsi_remove_device(sdev); 752 __scsi_remove_device(sdev);
750 up(&shost->scan_mutex); 753 mutex_unlock(&shost->scan_mutex);
751} 754}
752EXPORT_SYMBOL(scsi_remove_device); 755EXPORT_SYMBOL(scsi_remove_device);
753 756
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 685b997306cf..f2c9acf11bd0 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -295,6 +295,7 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev,
295 */ 295 */
296 fc_host_node_name(shost) = -1; 296 fc_host_node_name(shost) = -1;
297 fc_host_port_name(shost) = -1; 297 fc_host_port_name(shost) = -1;
298 fc_host_permanent_port_name(shost) = -1;
298 fc_host_supported_classes(shost) = FC_COS_UNSPECIFIED; 299 fc_host_supported_classes(shost) = FC_COS_UNSPECIFIED;
299 memset(fc_host_supported_fc4s(shost), 0, 300 memset(fc_host_supported_fc4s(shost), 0,
300 sizeof(fc_host_supported_fc4s(shost))); 301 sizeof(fc_host_supported_fc4s(shost)));
@@ -795,6 +796,8 @@ static FC_CLASS_DEVICE_ATTR(host, supported_speeds, S_IRUGO,
795 796
796fc_private_host_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long); 797fc_private_host_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long);
797fc_private_host_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long); 798fc_private_host_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long);
799fc_private_host_rd_attr_cast(permanent_port_name, "0x%llx\n", 20,
800 unsigned long long);
798fc_private_host_rd_attr(symbolic_name, "%s\n", (FC_SYMBOLIC_NAME_SIZE +1)); 801fc_private_host_rd_attr(symbolic_name, "%s\n", (FC_SYMBOLIC_NAME_SIZE +1));
799fc_private_host_rd_attr(maxframe_size, "%u bytes\n", 20); 802fc_private_host_rd_attr(maxframe_size, "%u bytes\n", 20);
800fc_private_host_rd_attr(serial_number, "%s\n", (FC_SERIAL_NUMBER_SIZE +1)); 803fc_private_host_rd_attr(serial_number, "%s\n", (FC_SERIAL_NUMBER_SIZE +1));
@@ -1090,17 +1093,23 @@ static int fc_rport_match(struct attribute_container *cont,
1090/* 1093/*
1091 * Must be called with shost->host_lock held 1094 * Must be called with shost->host_lock held
1092 */ 1095 */
1093static struct device *fc_target_parent(struct Scsi_Host *shost, 1096static int fc_user_scan(struct Scsi_Host *shost, uint channel,
1094 int channel, uint id) 1097 uint id, uint lun)
1095{ 1098{
1096 struct fc_rport *rport; 1099 struct fc_rport *rport;
1097 1100
1098 list_for_each_entry(rport, &fc_host_rports(shost), peers) 1101 list_for_each_entry(rport, &fc_host_rports(shost), peers) {
1099 if ((rport->channel == channel) && 1102 if (rport->scsi_target_id == -1)
1100 (rport->scsi_target_id == id)) 1103 continue;
1101 return &rport->dev;
1102 1104
1103 return NULL; 1105 if ((channel == SCAN_WILD_CARD || channel == rport->channel) &&
1106 (id == SCAN_WILD_CARD || id == rport->scsi_target_id)) {
1107 scsi_scan_target(&rport->dev, rport->channel,
1108 rport->scsi_target_id, lun, 1);
1109 }
1110 }
1111
1112 return 0;
1104} 1113}
1105 1114
1106struct scsi_transport_template * 1115struct scsi_transport_template *
@@ -1139,7 +1148,7 @@ fc_attach_transport(struct fc_function_template *ft)
1139 /* Transport uses the shost workq for scsi scanning */ 1148 /* Transport uses the shost workq for scsi scanning */
1140 i->t.create_work_queue = 1; 1149 i->t.create_work_queue = 1;
1141 1150
1142 i->t.target_parent = fc_target_parent; 1151 i->t.user_scan = fc_user_scan;
1143 1152
1144 /* 1153 /*
1145 * Setup SCSI Target Attributes. 1154 * Setup SCSI Target Attributes.
@@ -1160,6 +1169,7 @@ fc_attach_transport(struct fc_function_template *ft)
1160 count=0; 1169 count=0;
1161 SETUP_HOST_ATTRIBUTE_RD(node_name); 1170 SETUP_HOST_ATTRIBUTE_RD(node_name);
1162 SETUP_HOST_ATTRIBUTE_RD(port_name); 1171 SETUP_HOST_ATTRIBUTE_RD(port_name);
1172 SETUP_HOST_ATTRIBUTE_RD(permanent_port_name);
1163 SETUP_HOST_ATTRIBUTE_RD(supported_classes); 1173 SETUP_HOST_ATTRIBUTE_RD(supported_classes);
1164 SETUP_HOST_ATTRIBUTE_RD(supported_fc4s); 1174 SETUP_HOST_ATTRIBUTE_RD(supported_fc4s);
1165 SETUP_HOST_ATTRIBUTE_RD(symbolic_name); 1175 SETUP_HOST_ATTRIBUTE_RD(symbolic_name);
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index e08462d50c97..59a1c9d9d3bd 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -21,11 +21,9 @@
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */ 22 */
23#include <linux/module.h> 23#include <linux/module.h>
24#include <linux/string.h>
25#include <linux/slab.h>
26#include <linux/mempool.h> 24#include <linux/mempool.h>
25#include <linux/mutex.h>
27#include <net/tcp.h> 26#include <net/tcp.h>
28
29#include <scsi/scsi.h> 27#include <scsi/scsi.h>
30#include <scsi/scsi_host.h> 28#include <scsi/scsi_host.h>
31#include <scsi/scsi_device.h> 29#include <scsi/scsi_device.h>
@@ -45,11 +43,6 @@ struct iscsi_internal {
45 */ 43 */
46 struct list_head sessions; 44 struct list_head sessions;
47 /* 45 /*
48 * lock to serialize access to the sessions list which must
49 * be taken after the rx_queue_sema
50 */
51 spinlock_t session_lock;
52 /*
53 * based on transport capabilities, at register time we set these 46 * based on transport capabilities, at register time we set these
54 * bits to tell the transport class it wants attributes displayed 47 * bits to tell the transport class it wants attributes displayed
55 * in sysfs or that it can support different iSCSI Data-Path 48 * in sysfs or that it can support different iSCSI Data-Path
@@ -70,7 +63,7 @@ struct iscsi_internal {
70/* 63/*
71 * list of registered transports and lock that must 64 * list of registered transports and lock that must
72 * be held while accessing list. The iscsi_transport_lock must 65 * be held while accessing list. The iscsi_transport_lock must
73 * be acquired after the rx_queue_sema. 66 * be acquired after the rx_queue_mutex.
74 */ 67 */
75static LIST_HEAD(iscsi_transports); 68static LIST_HEAD(iscsi_transports);
76static DEFINE_SPINLOCK(iscsi_transport_lock); 69static DEFINE_SPINLOCK(iscsi_transport_lock);
@@ -145,7 +138,7 @@ static DECLARE_TRANSPORT_CLASS(iscsi_connection_class,
145 138
146static struct sock *nls; 139static struct sock *nls;
147static int daemon_pid; 140static int daemon_pid;
148static DECLARE_MUTEX(rx_queue_sema); 141static DEFINE_MUTEX(rx_queue_mutex);
149 142
150struct mempool_zone { 143struct mempool_zone {
151 mempool_t *pool; 144 mempool_t *pool;
@@ -156,7 +149,7 @@ struct mempool_zone {
156 spinlock_t freelock; 149 spinlock_t freelock;
157}; 150};
158 151
159static struct mempool_zone z_reply; 152static struct mempool_zone *z_reply;
160 153
161/* 154/*
162 * Z_MAX_* - actual mempool size allocated at the mempool_zone_init() time 155 * Z_MAX_* - actual mempool size allocated at the mempool_zone_init() time
@@ -171,50 +164,271 @@ static struct mempool_zone z_reply;
171#define Z_MAX_ERROR 16 164#define Z_MAX_ERROR 16
172#define Z_HIWAT_ERROR 12 165#define Z_HIWAT_ERROR 12
173 166
174struct iscsi_if_conn { 167static LIST_HEAD(connlist);
175 struct list_head conn_list; /* item in connlist */ 168static DEFINE_SPINLOCK(connlock);
176 struct list_head session_list; /* item in session->connections */
177 iscsi_connh_t connh;
178 int active; /* must be accessed with the connlock */
179 struct Scsi_Host *host; /* originated shost */
180 struct device dev; /* sysfs transport/container device */
181 struct iscsi_transport *transport;
182 struct mempool_zone z_error;
183 struct mempool_zone z_pdu;
184 struct list_head freequeue;
185};
186 169
187#define iscsi_dev_to_if_conn(_dev) \ 170/*
188 container_of(_dev, struct iscsi_if_conn, dev) 171 * The following functions can be used by LLDs that allocate
172 * their own scsi_hosts or by software iscsi LLDs
173 */
174static void iscsi_session_release(struct device *dev)
175{
176 struct iscsi_cls_session *session = iscsi_dev_to_session(dev);
177 struct iscsi_transport *transport = session->transport;
178 struct Scsi_Host *shost;
189 179
190#define iscsi_cdev_to_if_conn(_cdev) \ 180 shost = iscsi_session_to_shost(session);
191 iscsi_dev_to_if_conn(_cdev->dev) 181 scsi_host_put(shost);
182 kfree(session);
183 module_put(transport->owner);
184}
192 185
193static LIST_HEAD(connlist); 186static int iscsi_is_session_dev(const struct device *dev)
194static DEFINE_SPINLOCK(connlock); 187{
188 return dev->release == iscsi_session_release;
189}
195 190
196struct iscsi_if_session { 191/**
197 struct list_head list; /* item in session_list */ 192 * iscsi_create_session - create iscsi class session
198 struct list_head connections; 193 * @shost: scsi host
199 iscsi_sessionh_t sessionh; 194 * @transport: iscsi transport
200 struct iscsi_transport *transport; 195 *
201 struct device dev; /* sysfs transport/container device */ 196 * This can be called from a LLD or iscsi_transport
202}; 197 **/
198struct iscsi_cls_session *
199iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport)
200{
201 struct iscsi_cls_session *session;
202 int err;
203
204 if (!try_module_get(transport->owner))
205 return NULL;
206
207 session = kzalloc(sizeof(*session), GFP_KERNEL);
208 if (!session)
209 goto module_put;
210 session->transport = transport;
211
212 /* this is released in the dev's release function */
213 scsi_host_get(shost);
214 snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", shost->host_no);
215 session->dev.parent = &shost->shost_gendev;
216 session->dev.release = iscsi_session_release;
217 err = device_register(&session->dev);
218 if (err) {
219 dev_printk(KERN_ERR, &session->dev, "iscsi: could not "
220 "register session's dev\n");
221 goto free_session;
222 }
223 transport_register_device(&session->dev);
224
225 return session;
226
227free_session:
228 kfree(session);
229module_put:
230 module_put(transport->owner);
231 return NULL;
232}
233
234EXPORT_SYMBOL_GPL(iscsi_create_session);
235
236/**
237 * iscsi_destroy_session - destroy iscsi session
238 * @session: iscsi_session
239 *
240 * Can be called by a LLD or iscsi_transport. There must not be
241 * any running connections.
242 **/
243int iscsi_destroy_session(struct iscsi_cls_session *session)
244{
245 transport_unregister_device(&session->dev);
246 device_unregister(&session->dev);
247 return 0;
248}
249
250EXPORT_SYMBOL_GPL(iscsi_destroy_session);
251
252static void iscsi_conn_release(struct device *dev)
253{
254 struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev);
255 struct device *parent = conn->dev.parent;
256
257 kfree(conn);
258 put_device(parent);
259}
260
261static int iscsi_is_conn_dev(const struct device *dev)
262{
263 return dev->release == iscsi_conn_release;
264}
265
266/**
267 * iscsi_create_conn - create iscsi class connection
268 * @session: iscsi cls session
269 * @cid: connection id
270 *
271 * This can be called from a LLD or iscsi_transport. The connection
272 * is child of the session so cid must be unique for all connections
273 * on the session.
274 **/
275struct iscsi_cls_conn *
276iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid)
277{
278 struct iscsi_transport *transport = session->transport;
279 struct Scsi_Host *shost = iscsi_session_to_shost(session);
280 struct iscsi_cls_conn *conn;
281 int err;
282
283 conn = kzalloc(sizeof(*conn) + transport->conndata_size, GFP_KERNEL);
284 if (!conn)
285 return NULL;
286
287 if (transport->conndata_size)
288 conn->dd_data = &conn[1];
289
290 INIT_LIST_HEAD(&conn->conn_list);
291 conn->transport = transport;
292
293 /* this is released in the dev's release function */
294 if (!get_device(&session->dev))
295 goto free_conn;
296 snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u",
297 shost->host_no, cid);
298 conn->dev.parent = &session->dev;
299 conn->dev.release = iscsi_conn_release;
300 err = device_register(&conn->dev);
301 if (err) {
302 dev_printk(KERN_ERR, &conn->dev, "iscsi: could not register "
303 "connection's dev\n");
304 goto release_parent_ref;
305 }
306 transport_register_device(&conn->dev);
307 return conn;
308
309release_parent_ref:
310 put_device(&session->dev);
311free_conn:
312 kfree(conn);
313 return NULL;
314}
315
316EXPORT_SYMBOL_GPL(iscsi_create_conn);
317
318/**
319 * iscsi_destroy_conn - destroy iscsi class connection
320 * @session: iscsi cls session
321 *
322 * This can be called from a LLD or iscsi_transport.
323 **/
324int iscsi_destroy_conn(struct iscsi_cls_conn *conn)
325{
326 transport_unregister_device(&conn->dev);
327 device_unregister(&conn->dev);
328 return 0;
329}
330
331EXPORT_SYMBOL_GPL(iscsi_destroy_conn);
332
333/*
334 * These functions are used only by software iscsi_transports
335 * which do not allocate and more their scsi_hosts since this
336 * is initiated from userspace.
337 */
338
339/*
340 * iSCSI Session's hostdata organization:
341 *
342 * *------------------* <== hostdata_session(host->hostdata)
343 * | ptr to class sess|
344 * |------------------| <== iscsi_hostdata(host->hostdata)
345 * | transport's data |
346 * *------------------*
347 */
348
349#define hostdata_privsize(_t) (sizeof(unsigned long) + _t->hostdata_size + \
350 _t->hostdata_size % sizeof(unsigned long))
351
352#define hostdata_session(_hostdata) (iscsi_ptr(*(unsigned long *)_hostdata))
353
354/**
355 * iscsi_transport_create_session - create iscsi cls session and host
356 * scsit: scsi transport template
357 * transport: iscsi transport template
358 *
359 * This can be used by software iscsi_transports that allocate
360 * a session per scsi host.
361 **/
362struct Scsi_Host *
363iscsi_transport_create_session(struct scsi_transport_template *scsit,
364 struct iscsi_transport *transport)
365{
366 struct iscsi_cls_session *session;
367 struct Scsi_Host *shost;
368
369 shost = scsi_host_alloc(transport->host_template,
370 hostdata_privsize(transport));
371 if (!shost) {
372 printk(KERN_ERR "iscsi: can not allocate SCSI host for "
373 "session\n");
374 return NULL;
375 }
376
377 shost->max_id = 1;
378 shost->max_channel = 0;
379 shost->max_lun = transport->max_lun;
380 shost->max_cmd_len = transport->max_cmd_len;
381 shost->transportt = scsit;
382 shost->transportt->create_work_queue = 1;
383
384 if (scsi_add_host(shost, NULL))
385 goto free_host;
386
387 session = iscsi_create_session(shost, transport);
388 if (!session)
389 goto remove_host;
203 390
204#define iscsi_dev_to_if_session(_dev) \ 391 *(unsigned long*)shost->hostdata = (unsigned long)session;
205 container_of(_dev, struct iscsi_if_session, dev) 392 return shost;
393
394remove_host:
395 scsi_remove_host(shost);
396free_host:
397 scsi_host_put(shost);
398 return NULL;
399}
206 400
207#define iscsi_cdev_to_if_session(_cdev) \ 401EXPORT_SYMBOL_GPL(iscsi_transport_create_session);
208 iscsi_dev_to_if_session(_cdev->dev)
209 402
210#define iscsi_if_session_to_shost(_session) \ 403/**
211 dev_to_shost(_session->dev.parent) 404 * iscsi_transport_destroy_session - destroy session and scsi host
405 * shost: scsi host
406 *
407 * This can be used by software iscsi_transports that allocate
408 * a session per scsi host.
409 **/
410int iscsi_transport_destroy_session(struct Scsi_Host *shost)
411{
412 struct iscsi_cls_session *session;
212 413
213static struct iscsi_if_conn* 414 scsi_remove_host(shost);
415 session = hostdata_session(shost->hostdata);
416 iscsi_destroy_session(session);
417 /* ref from host alloc */
418 scsi_host_put(shost);
419 return 0;
420}
421
422EXPORT_SYMBOL_GPL(iscsi_transport_destroy_session);
423
424/*
425 * iscsi interface functions
426 */
427static struct iscsi_cls_conn*
214iscsi_if_find_conn(uint64_t key) 428iscsi_if_find_conn(uint64_t key)
215{ 429{
216 unsigned long flags; 430 unsigned long flags;
217 struct iscsi_if_conn *conn; 431 struct iscsi_cls_conn *conn;
218 432
219 spin_lock_irqsave(&connlock, flags); 433 spin_lock_irqsave(&connlock, flags);
220 list_for_each_entry(conn, &connlist, conn_list) 434 list_for_each_entry(conn, &connlist, conn_list)
@@ -249,7 +463,7 @@ static inline struct list_head *skb_to_lh(struct sk_buff *skb)
249} 463}
250 464
251static void* 465static void*
252mempool_zone_alloc_skb(gfp_t gfp_mask, void *pool_data) 466mempool_zone_alloc_skb(unsigned int gfp_mask, void *pool_data)
253{ 467{
254 struct mempool_zone *zone = pool_data; 468 struct mempool_zone *zone = pool_data;
255 469
@@ -281,14 +495,21 @@ mempool_zone_complete(struct mempool_zone *zone)
281 spin_unlock_irqrestore(&zone->freelock, flags); 495 spin_unlock_irqrestore(&zone->freelock, flags);
282} 496}
283 497
284static int 498static struct mempool_zone *
285mempool_zone_init(struct mempool_zone *zp, unsigned max, unsigned size, 499mempool_zone_init(unsigned max, unsigned size, unsigned hiwat)
286 unsigned hiwat)
287{ 500{
501 struct mempool_zone *zp;
502
503 zp = kzalloc(sizeof(*zp), GFP_KERNEL);
504 if (!zp)
505 return NULL;
506
288 zp->pool = mempool_create(max, mempool_zone_alloc_skb, 507 zp->pool = mempool_create(max, mempool_zone_alloc_skb,
289 mempool_zone_free_skb, zp); 508 mempool_zone_free_skb, zp);
290 if (!zp->pool) 509 if (!zp->pool) {
291 return -ENOMEM; 510 kfree(zp);
511 return NULL;
512 }
292 513
293 zp->size = size; 514 zp->size = size;
294 zp->hiwat = hiwat; 515 zp->hiwat = hiwat;
@@ -297,9 +518,14 @@ mempool_zone_init(struct mempool_zone *zp, unsigned max, unsigned size,
297 spin_lock_init(&zp->freelock); 518 spin_lock_init(&zp->freelock);
298 atomic_set(&zp->allocated, 0); 519 atomic_set(&zp->allocated, 0);
299 520
300 return 0; 521 return zp;
301} 522}
302 523
524static void mempool_zone_destroy(struct mempool_zone *zp)
525{
526 mempool_destroy(zp->pool);
527 kfree(zp);
528}
303 529
304static struct sk_buff* 530static struct sk_buff*
305mempool_zone_get_skb(struct mempool_zone *zone) 531mempool_zone_get_skb(struct mempool_zone *zone)
@@ -339,7 +565,7 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr,
339 struct nlmsghdr *nlh; 565 struct nlmsghdr *nlh;
340 struct sk_buff *skb; 566 struct sk_buff *skb;
341 struct iscsi_uevent *ev; 567 struct iscsi_uevent *ev;
342 struct iscsi_if_conn *conn; 568 struct iscsi_cls_conn *conn;
343 char *pdu; 569 char *pdu;
344 int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) + 570 int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) +
345 data_size); 571 data_size);
@@ -347,13 +573,13 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr,
347 conn = iscsi_if_find_conn(connh); 573 conn = iscsi_if_find_conn(connh);
348 BUG_ON(!conn); 574 BUG_ON(!conn);
349 575
350 mempool_zone_complete(&conn->z_pdu); 576 mempool_zone_complete(conn->z_pdu);
351 577
352 skb = mempool_zone_get_skb(&conn->z_pdu); 578 skb = mempool_zone_get_skb(conn->z_pdu);
353 if (!skb) { 579 if (!skb) {
354 iscsi_conn_error(connh, ISCSI_ERR_CONN_FAILED); 580 iscsi_conn_error(connh, ISCSI_ERR_CONN_FAILED);
355 printk(KERN_ERR "iscsi%d: can not deliver control PDU: OOM\n", 581 dev_printk(KERN_ERR, &conn->dev, "iscsi: can not deliver "
356 conn->host->host_no); 582 "control PDU: OOM\n");
357 return -ENOMEM; 583 return -ENOMEM;
358 } 584 }
359 585
@@ -362,14 +588,14 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr,
362 memset(ev, 0, sizeof(*ev)); 588 memset(ev, 0, sizeof(*ev));
363 ev->transport_handle = iscsi_handle(conn->transport); 589 ev->transport_handle = iscsi_handle(conn->transport);
364 ev->type = ISCSI_KEVENT_RECV_PDU; 590 ev->type = ISCSI_KEVENT_RECV_PDU;
365 if (atomic_read(&conn->z_pdu.allocated) >= conn->z_pdu.hiwat) 591 if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat)
366 ev->iferror = -ENOMEM; 592 ev->iferror = -ENOMEM;
367 ev->r.recv_req.conn_handle = connh; 593 ev->r.recv_req.conn_handle = connh;
368 pdu = (char*)ev + sizeof(*ev); 594 pdu = (char*)ev + sizeof(*ev);
369 memcpy(pdu, hdr, sizeof(struct iscsi_hdr)); 595 memcpy(pdu, hdr, sizeof(struct iscsi_hdr));
370 memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size); 596 memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size);
371 597
372 return iscsi_unicast_skb(&conn->z_pdu, skb); 598 return iscsi_unicast_skb(conn->z_pdu, skb);
373} 599}
374EXPORT_SYMBOL_GPL(iscsi_recv_pdu); 600EXPORT_SYMBOL_GPL(iscsi_recv_pdu);
375 601
@@ -378,18 +604,18 @@ void iscsi_conn_error(iscsi_connh_t connh, enum iscsi_err error)
378 struct nlmsghdr *nlh; 604 struct nlmsghdr *nlh;
379 struct sk_buff *skb; 605 struct sk_buff *skb;
380 struct iscsi_uevent *ev; 606 struct iscsi_uevent *ev;
381 struct iscsi_if_conn *conn; 607 struct iscsi_cls_conn *conn;
382 int len = NLMSG_SPACE(sizeof(*ev)); 608 int len = NLMSG_SPACE(sizeof(*ev));
383 609
384 conn = iscsi_if_find_conn(connh); 610 conn = iscsi_if_find_conn(connh);
385 BUG_ON(!conn); 611 BUG_ON(!conn);
386 612
387 mempool_zone_complete(&conn->z_error); 613 mempool_zone_complete(conn->z_error);
388 614
389 skb = mempool_zone_get_skb(&conn->z_error); 615 skb = mempool_zone_get_skb(conn->z_error);
390 if (!skb) { 616 if (!skb) {
391 printk(KERN_ERR "iscsi%d: gracefully ignored conn error (%d)\n", 617 dev_printk(KERN_ERR, &conn->dev, "iscsi: gracefully ignored "
392 conn->host->host_no, error); 618 "conn error (%d)\n", error);
393 return; 619 return;
394 } 620 }
395 621
@@ -397,15 +623,15 @@ void iscsi_conn_error(iscsi_connh_t connh, enum iscsi_err error)
397 ev = NLMSG_DATA(nlh); 623 ev = NLMSG_DATA(nlh);
398 ev->transport_handle = iscsi_handle(conn->transport); 624 ev->transport_handle = iscsi_handle(conn->transport);
399 ev->type = ISCSI_KEVENT_CONN_ERROR; 625 ev->type = ISCSI_KEVENT_CONN_ERROR;
400 if (atomic_read(&conn->z_error.allocated) >= conn->z_error.hiwat) 626 if (atomic_read(&conn->z_error->allocated) >= conn->z_error->hiwat)
401 ev->iferror = -ENOMEM; 627 ev->iferror = -ENOMEM;
402 ev->r.connerror.error = error; 628 ev->r.connerror.error = error;
403 ev->r.connerror.conn_handle = connh; 629 ev->r.connerror.conn_handle = connh;
404 630
405 iscsi_unicast_skb(&conn->z_error, skb); 631 iscsi_unicast_skb(conn->z_error, skb);
406 632
407 printk(KERN_INFO "iscsi%d: detected conn error (%d)\n", 633 dev_printk(KERN_INFO, &conn->dev, "iscsi: detected conn error (%d)\n",
408 conn->host->host_no, error); 634 error);
409} 635}
410EXPORT_SYMBOL_GPL(iscsi_conn_error); 636EXPORT_SYMBOL_GPL(iscsi_conn_error);
411 637
@@ -419,9 +645,9 @@ iscsi_if_send_reply(int pid, int seq, int type, int done, int multi,
419 int flags = multi ? NLM_F_MULTI : 0; 645 int flags = multi ? NLM_F_MULTI : 0;
420 int t = done ? NLMSG_DONE : type; 646 int t = done ? NLMSG_DONE : type;
421 647
422 mempool_zone_complete(&z_reply); 648 mempool_zone_complete(z_reply);
423 649
424 skb = mempool_zone_get_skb(&z_reply); 650 skb = mempool_zone_get_skb(z_reply);
425 /* 651 /*
426 * FIXME: 652 * FIXME:
427 * user is supposed to react on iferror == -ENOMEM; 653 * user is supposed to react on iferror == -ENOMEM;
@@ -432,366 +658,197 @@ iscsi_if_send_reply(int pid, int seq, int type, int done, int multi,
432 nlh = __nlmsg_put(skb, pid, seq, t, (len - sizeof(*nlh)), 0); 658 nlh = __nlmsg_put(skb, pid, seq, t, (len - sizeof(*nlh)), 0);
433 nlh->nlmsg_flags = flags; 659 nlh->nlmsg_flags = flags;
434 memcpy(NLMSG_DATA(nlh), payload, size); 660 memcpy(NLMSG_DATA(nlh), payload, size);
435 return iscsi_unicast_skb(&z_reply, skb); 661 return iscsi_unicast_skb(z_reply, skb);
436} 662}
437 663
438/* 664static int
439 * iSCSI Session's hostdata organization: 665iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb,
440 * 666 struct nlmsghdr *nlh)
441 * *------------------* <== host->hostdata 667{
442 * | transport | 668 struct iscsi_uevent *ev = NLMSG_DATA(nlh);
443 * |------------------| <== iscsi_hostdata(host->hostdata) 669 struct iscsi_stats *stats;
444 * | transport's data | 670 struct sk_buff *skbstat;
445 * |------------------| <== hostdata_session(host->hostdata) 671 struct iscsi_cls_conn *conn;
446 * | interface's data | 672 struct nlmsghdr *nlhstat;
447 * *------------------* 673 struct iscsi_uevent *evstat;
448 */ 674 int len = NLMSG_SPACE(sizeof(*ev) +
675 sizeof(struct iscsi_stats) +
676 sizeof(struct iscsi_stats_custom) *
677 ISCSI_STATS_CUSTOM_MAX);
678 int err = 0;
449 679
450#define hostdata_privsize(_t) (sizeof(unsigned long) + _t->hostdata_size + \ 680 conn = iscsi_if_find_conn(ev->u.get_stats.conn_handle);
451 _t->hostdata_size % sizeof(unsigned long) + \ 681 if (!conn)
452 sizeof(struct iscsi_if_session)) 682 return -EEXIST;
453 683
454#define hostdata_session(_hostdata) ((void*)_hostdata + sizeof(unsigned long) + \ 684 do {
455 ((struct iscsi_transport *) \ 685 int actual_size;
456 iscsi_ptr(*(uint64_t *)_hostdata))->hostdata_size)
457 686
458static void iscsi_if_session_dev_release(struct device *dev) 687 mempool_zone_complete(conn->z_pdu);
459{
460 struct iscsi_if_session *session = iscsi_dev_to_if_session(dev);
461 struct iscsi_transport *transport = session->transport;
462 struct Scsi_Host *shost = iscsi_if_session_to_shost(session);
463 struct iscsi_if_conn *conn, *tmp;
464 unsigned long flags;
465 688
466 /* now free connections */ 689 skbstat = mempool_zone_get_skb(conn->z_pdu);
467 spin_lock_irqsave(&connlock, flags); 690 if (!skbstat) {
468 list_for_each_entry_safe(conn, tmp, &session->connections, 691 dev_printk(KERN_ERR, &conn->dev, "iscsi: can not "
469 session_list) { 692 "deliver stats: OOM\n");
470 list_del(&conn->session_list); 693 return -ENOMEM;
471 mempool_destroy(conn->z_pdu.pool); 694 }
472 mempool_destroy(conn->z_error.pool); 695
473 kfree(conn); 696 nlhstat = __nlmsg_put(skbstat, daemon_pid, 0, 0,
474 } 697 (len - sizeof(*nlhstat)), 0);
475 spin_unlock_irqrestore(&connlock, flags); 698 evstat = NLMSG_DATA(nlhstat);
476 scsi_host_put(shost); 699 memset(evstat, 0, sizeof(*evstat));
477 module_put(transport->owner); 700 evstat->transport_handle = iscsi_handle(conn->transport);
701 evstat->type = nlh->nlmsg_type;
702 if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat)
703 evstat->iferror = -ENOMEM;
704 evstat->u.get_stats.conn_handle =
705 ev->u.get_stats.conn_handle;
706 stats = (struct iscsi_stats *)
707 ((char*)evstat + sizeof(*evstat));
708 memset(stats, 0, sizeof(*stats));
709
710 transport->get_stats(ev->u.get_stats.conn_handle, stats);
711 actual_size = NLMSG_SPACE(sizeof(struct iscsi_uevent) +
712 sizeof(struct iscsi_stats) +
713 sizeof(struct iscsi_stats_custom) *
714 stats->custom_length);
715 actual_size -= sizeof(*nlhstat);
716 actual_size = NLMSG_LENGTH(actual_size);
717 skb_trim(skb, NLMSG_ALIGN(actual_size));
718 nlhstat->nlmsg_len = actual_size;
719
720 err = iscsi_unicast_skb(conn->z_pdu, skbstat);
721 } while (err < 0 && err != -ECONNREFUSED);
722
723 return err;
478} 724}
479 725
480static int 726static int
481iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev) 727iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
482{ 728{
483 struct iscsi_transport *transport = priv->iscsi_transport; 729 struct iscsi_transport *transport = priv->iscsi_transport;
484 struct iscsi_if_session *session;
485 struct Scsi_Host *shost; 730 struct Scsi_Host *shost;
486 unsigned long flags;
487 int error;
488
489 if (!try_module_get(transport->owner))
490 return -EPERM;
491 731
492 shost = scsi_host_alloc(transport->host_template, 732 if (!transport->create_session)
493 hostdata_privsize(transport)); 733 return -EINVAL;
494 if (!shost) {
495 ev->r.c_session_ret.session_handle = iscsi_handle(NULL);
496 printk(KERN_ERR "iscsi: can not allocate SCSI host for "
497 "session\n");
498 error = -ENOMEM;
499 goto out_module_put;
500 }
501 shost->max_id = 1;
502 shost->max_channel = 0;
503 shost->max_lun = transport->max_lun;
504 shost->max_cmd_len = transport->max_cmd_len;
505 shost->transportt = &priv->t;
506
507 /* store struct iscsi_transport in hostdata */
508 *(uint64_t*)shost->hostdata = ev->transport_handle;
509 734
510 ev->r.c_session_ret.session_handle = transport->create_session( 735 shost = transport->create_session(&priv->t,
511 ev->u.c_session.initial_cmdsn, shost); 736 ev->u.c_session.initial_cmdsn);
512 if (ev->r.c_session_ret.session_handle == iscsi_handle(NULL)) { 737 if (!shost)
513 error = 0; 738 return -ENOMEM;
514 goto out_host_put;
515 }
516 739
517 /* host_no becomes assigned SID */ 740 ev->r.c_session_ret.session_handle = iscsi_handle(iscsi_hostdata(shost->hostdata));
518 ev->r.c_session_ret.sid = shost->host_no; 741 ev->r.c_session_ret.sid = shost->host_no;
519 /* initialize session */
520 session = hostdata_session(shost->hostdata);
521 INIT_LIST_HEAD(&session->connections);
522 INIT_LIST_HEAD(&session->list);
523 session->sessionh = ev->r.c_session_ret.session_handle;
524 session->transport = transport;
525
526 error = scsi_add_host(shost, NULL);
527 if (error)
528 goto out_destroy_session;
529
530 /*
531 * this is released in the dev's release function)
532 */
533 scsi_host_get(shost);
534 snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", shost->host_no);
535 session->dev.parent = &shost->shost_gendev;
536 session->dev.release = iscsi_if_session_dev_release;
537 error = device_register(&session->dev);
538 if (error) {
539 printk(KERN_ERR "iscsi: could not register session%d's dev\n",
540 shost->host_no);
541 goto out_remove_host;
542 }
543 transport_register_device(&session->dev);
544
545 /* add this session to the list of active sessions */
546 spin_lock_irqsave(&priv->session_lock, flags);
547 list_add(&session->list, &priv->sessions);
548 spin_unlock_irqrestore(&priv->session_lock, flags);
549
550 return 0; 742 return 0;
551
552out_remove_host:
553 scsi_remove_host(shost);
554out_destroy_session:
555 transport->destroy_session(ev->r.c_session_ret.session_handle);
556 ev->r.c_session_ret.session_handle = iscsi_handle(NULL);
557out_host_put:
558 scsi_host_put(shost);
559out_module_put:
560 module_put(transport->owner);
561 return error;
562} 743}
563 744
564static int 745static int
565iscsi_if_destroy_session(struct iscsi_internal *priv, struct iscsi_uevent *ev) 746iscsi_if_destroy_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
566{ 747{
567 struct iscsi_transport *transport = priv->iscsi_transport; 748 struct iscsi_transport *transport = priv->iscsi_transport;
749
568 struct Scsi_Host *shost; 750 struct Scsi_Host *shost;
569 struct iscsi_if_session *session; 751
570 unsigned long flags; 752 if (!transport->destroy_session)
571 struct iscsi_if_conn *conn; 753 return -EINVAL;
572 int error = 0;
573 754
574 shost = scsi_host_lookup(ev->u.d_session.sid); 755 shost = scsi_host_lookup(ev->u.d_session.sid);
575 if (shost == ERR_PTR(-ENXIO)) 756 if (shost == ERR_PTR(-ENXIO))
576 return -EEXIST; 757 return -EEXIST;
577 session = hostdata_session(shost->hostdata);
578 758
579 /* check if we have active connections */ 759 if (transport->destroy_session)
580 spin_lock_irqsave(&connlock, flags); 760 transport->destroy_session(shost);
581 list_for_each_entry(conn, &session->connections, session_list) { 761 /* ref from host lookup */
582 if (conn->active) { 762 scsi_host_put(shost);
583 printk(KERN_ERR "iscsi%d: can not destroy session: " 763 return 0;
584 "has active connection (%p)\n",
585 shost->host_no, iscsi_ptr(conn->connh));
586 spin_unlock_irqrestore(&connlock, flags);
587 error = EIO;
588 goto out_release_ref;
589 }
590 }
591 spin_unlock_irqrestore(&connlock, flags);
592
593 scsi_remove_host(shost);
594 transport->destroy_session(ev->u.d_session.session_handle);
595 transport_unregister_device(&session->dev);
596 device_unregister(&session->dev);
597
598 /* remove this session from the list of active sessions */
599 spin_lock_irqsave(&priv->session_lock, flags);
600 list_del(&session->list);
601 spin_unlock_irqrestore(&priv->session_lock, flags);
602
603 /* ref from host alloc */
604 scsi_host_put(shost);
605out_release_ref:
606 /* ref from host lookup */
607 scsi_host_put(shost);
608 return error;
609}
610
611static void iscsi_if_conn_dev_release(struct device *dev)
612{
613 struct iscsi_if_conn *conn = iscsi_dev_to_if_conn(dev);
614 struct Scsi_Host *shost = conn->host;
615
616 scsi_host_put(shost);
617} 764}
618 765
619static int 766static int
620iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev) 767iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev){
621{
622 struct iscsi_if_session *session;
623 struct Scsi_Host *shost; 768 struct Scsi_Host *shost;
624 struct iscsi_if_conn *conn; 769 struct iscsi_cls_conn *conn;
625 unsigned long flags; 770 unsigned long flags;
626 int error; 771
772 if (!transport->create_conn)
773 return -EINVAL;
627 774
628 shost = scsi_host_lookup(ev->u.c_conn.sid); 775 shost = scsi_host_lookup(ev->u.c_conn.sid);
629 if (shost == ERR_PTR(-ENXIO)) 776 if (shost == ERR_PTR(-ENXIO))
630 return -EEXIST; 777 return -EEXIST;
631 session = hostdata_session(shost->hostdata);
632 778
633 conn = kmalloc(sizeof(struct iscsi_if_conn), GFP_KERNEL); 779 conn = transport->create_conn(shost, ev->u.c_conn.cid);
634 if (!conn) { 780 if (!conn)
635 error = -ENOMEM; 781 goto release_ref;
636 goto out_release_ref;
637 }
638 memset(conn, 0, sizeof(struct iscsi_if_conn));
639 INIT_LIST_HEAD(&conn->session_list);
640 INIT_LIST_HEAD(&conn->conn_list);
641 conn->host = shost;
642 conn->transport = transport;
643 782
644 error = mempool_zone_init(&conn->z_pdu, Z_MAX_PDU, 783 conn->z_pdu = mempool_zone_init(Z_MAX_PDU,
645 NLMSG_SPACE(sizeof(struct iscsi_uevent) + 784 NLMSG_SPACE(sizeof(struct iscsi_uevent) +
646 sizeof(struct iscsi_hdr) + 785 sizeof(struct iscsi_hdr) +
647 DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH), 786 DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH),
648 Z_HIWAT_PDU); 787 Z_HIWAT_PDU);
649 if (error) { 788 if (!conn->z_pdu) {
650 printk(KERN_ERR "iscsi%d: can not allocate pdu zone for new " 789 dev_printk(KERN_ERR, &conn->dev, "iscsi: can not allocate "
651 "conn\n", shost->host_no); 790 "pdu zone for new conn\n");
652 goto out_free_conn; 791 goto destroy_conn;
653 } 792 }
654 error = mempool_zone_init(&conn->z_error, Z_MAX_ERROR, 793
794 conn->z_error = mempool_zone_init(Z_MAX_ERROR,
655 NLMSG_SPACE(sizeof(struct iscsi_uevent)), 795 NLMSG_SPACE(sizeof(struct iscsi_uevent)),
656 Z_HIWAT_ERROR); 796 Z_HIWAT_ERROR);
657 if (error) { 797 if (!conn->z_error) {
658 printk(KERN_ERR "iscsi%d: can not allocate error zone for " 798 dev_printk(KERN_ERR, &conn->dev, "iscsi: can not allocate "
659 "new conn\n", shost->host_no); 799 "error zone for new conn\n");
660 goto out_free_pdu_pool; 800 goto free_pdu_pool;
661 }
662
663 ev->r.handle = transport->create_conn(ev->u.c_conn.session_handle,
664 ev->u.c_conn.cid);
665 if (!ev->r.handle) {
666 error = -ENODEV;
667 goto out_free_error_pool;
668 } 801 }
669 802
670 conn->connh = ev->r.handle; 803 ev->r.handle = conn->connh = iscsi_handle(conn->dd_data);
671
672 /*
673 * this is released in the dev's release function
674 */
675 if (!scsi_host_get(shost))
676 goto out_destroy_conn;
677 snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u",
678 shost->host_no, ev->u.c_conn.cid);
679 conn->dev.parent = &session->dev;
680 conn->dev.release = iscsi_if_conn_dev_release;
681 error = device_register(&conn->dev);
682 if (error) {
683 printk(KERN_ERR "iscsi%d: could not register connections%u "
684 "dev\n", shost->host_no, ev->u.c_conn.cid);
685 goto out_release_parent_ref;
686 }
687 transport_register_device(&conn->dev);
688 804
689 spin_lock_irqsave(&connlock, flags); 805 spin_lock_irqsave(&connlock, flags);
690 list_add(&conn->conn_list, &connlist); 806 list_add(&conn->conn_list, &connlist);
691 list_add(&conn->session_list, &session->connections);
692 conn->active = 1; 807 conn->active = 1;
693 spin_unlock_irqrestore(&connlock, flags); 808 spin_unlock_irqrestore(&connlock, flags);
694 809
695 scsi_host_put(shost); 810 scsi_host_put(shost);
696 return 0; 811 return 0;
697 812
698out_release_parent_ref: 813free_pdu_pool:
814 mempool_zone_destroy(conn->z_pdu);
815destroy_conn:
816 if (transport->destroy_conn)
817 transport->destroy_conn(conn->dd_data);
818release_ref:
699 scsi_host_put(shost); 819 scsi_host_put(shost);
700out_destroy_conn: 820 return -ENOMEM;
701 transport->destroy_conn(ev->r.handle);
702out_free_error_pool:
703 mempool_destroy(conn->z_error.pool);
704out_free_pdu_pool:
705 mempool_destroy(conn->z_pdu.pool);
706out_free_conn:
707 kfree(conn);
708out_release_ref:
709 scsi_host_put(shost);
710 return error;
711} 821}
712 822
713static int 823static int
714iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev) 824iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
715{ 825{
716 unsigned long flags; 826 unsigned long flags;
717 struct iscsi_if_conn *conn; 827 struct iscsi_cls_conn *conn;
828 struct mempool_zone *z_error, *z_pdu;
718 829
719 conn = iscsi_if_find_conn(ev->u.d_conn.conn_handle); 830 conn = iscsi_if_find_conn(ev->u.d_conn.conn_handle);
720 if (!conn) 831 if (!conn)
721 return -EEXIST; 832 return -EEXIST;
722 833
723 transport->destroy_conn(ev->u.d_conn.conn_handle); 834 if (!transport->destroy_conn)
835 return -EINVAL;
724 836
725 spin_lock_irqsave(&connlock, flags); 837 spin_lock_irqsave(&connlock, flags);
726 conn->active = 0; 838 conn->active = 0;
727 list_del(&conn->conn_list); 839 list_del(&conn->conn_list);
728 spin_unlock_irqrestore(&connlock, flags); 840 spin_unlock_irqrestore(&connlock, flags);
729 841
730 transport_unregister_device(&conn->dev); 842 z_pdu = conn->z_pdu;
731 device_unregister(&conn->dev); 843 z_error = conn->z_error;
732 return 0;
733}
734
735static int
736iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb,
737 struct nlmsghdr *nlh)
738{
739 struct iscsi_uevent *ev = NLMSG_DATA(nlh);
740 struct iscsi_stats *stats;
741 struct sk_buff *skbstat;
742 struct iscsi_if_conn *conn;
743 struct nlmsghdr *nlhstat;
744 struct iscsi_uevent *evstat;
745 int len = NLMSG_SPACE(sizeof(*ev) +
746 sizeof(struct iscsi_stats) +
747 sizeof(struct iscsi_stats_custom) *
748 ISCSI_STATS_CUSTOM_MAX);
749 int err = 0;
750
751 conn = iscsi_if_find_conn(ev->u.get_stats.conn_handle);
752 if (!conn)
753 return -EEXIST;
754
755 do {
756 int actual_size;
757
758 mempool_zone_complete(&conn->z_pdu);
759
760 skbstat = mempool_zone_get_skb(&conn->z_pdu);
761 if (!skbstat) {
762 printk(KERN_ERR "iscsi%d: can not deliver stats: OOM\n",
763 conn->host->host_no);
764 return -ENOMEM;
765 }
766
767 nlhstat = __nlmsg_put(skbstat, daemon_pid, 0, 0,
768 (len - sizeof(*nlhstat)), 0);
769 evstat = NLMSG_DATA(nlhstat);
770 memset(evstat, 0, sizeof(*evstat));
771 evstat->transport_handle = iscsi_handle(conn->transport);
772 evstat->type = nlh->nlmsg_type;
773 if (atomic_read(&conn->z_pdu.allocated) >= conn->z_pdu.hiwat)
774 evstat->iferror = -ENOMEM;
775 evstat->u.get_stats.conn_handle =
776 ev->u.get_stats.conn_handle;
777 stats = (struct iscsi_stats *)
778 ((char*)evstat + sizeof(*evstat));
779 memset(stats, 0, sizeof(*stats));
780 844
781 transport->get_stats(ev->u.get_stats.conn_handle, stats); 845 if (transport->destroy_conn)
782 actual_size = NLMSG_SPACE(sizeof(struct iscsi_uevent) + 846 transport->destroy_conn(conn);
783 sizeof(struct iscsi_stats) +
784 sizeof(struct iscsi_stats_custom) *
785 stats->custom_length);
786 actual_size -= sizeof(*nlhstat);
787 actual_size = NLMSG_LENGTH(actual_size);
788 skb_trim(skb, NLMSG_ALIGN(actual_size));
789 nlhstat->nlmsg_len = actual_size;
790 847
791 err = iscsi_unicast_skb(&conn->z_pdu, skbstat); 848 mempool_zone_destroy(z_pdu);
792 } while (err < 0 && err != -ECONNREFUSED); 849 mempool_zone_destroy(z_error);
793 850
794 return err; 851 return 0;
795} 852}
796 853
797static int 854static int
@@ -881,7 +938,7 @@ iscsi_if_rx(struct sock *sk, int len)
881{ 938{
882 struct sk_buff *skb; 939 struct sk_buff *skb;
883 940
884 down(&rx_queue_sema); 941 mutex_lock(&rx_queue_mutex);
885 while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) { 942 while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
886 while (skb->len >= NLMSG_SPACE(0)) { 943 while (skb->len >= NLMSG_SPACE(0)) {
887 int err; 944 int err;
@@ -915,17 +972,20 @@ iscsi_if_rx(struct sock *sk, int len)
915 err = iscsi_if_send_reply( 972 err = iscsi_if_send_reply(
916 NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq, 973 NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq,
917 nlh->nlmsg_type, 0, 0, ev, sizeof(*ev)); 974 nlh->nlmsg_type, 0, 0, ev, sizeof(*ev));
918 if (atomic_read(&z_reply.allocated) >= 975 if (atomic_read(&z_reply->allocated) >=
919 z_reply.hiwat) 976 z_reply->hiwat)
920 ev->iferror = -ENOMEM; 977 ev->iferror = -ENOMEM;
921 } while (err < 0 && err != -ECONNREFUSED); 978 } while (err < 0 && err != -ECONNREFUSED);
922 skb_pull(skb, rlen); 979 skb_pull(skb, rlen);
923 } 980 }
924 kfree_skb(skb); 981 kfree_skb(skb);
925 } 982 }
926 up(&rx_queue_sema); 983 mutex_unlock(&rx_queue_mutex);
927} 984}
928 985
986#define iscsi_cdev_to_conn(_cdev) \
987 iscsi_dev_to_conn(_cdev->dev)
988
929/* 989/*
930 * iSCSI connection attrs 990 * iSCSI connection attrs
931 */ 991 */
@@ -934,12 +994,10 @@ static ssize_t \
934show_conn_int_param_##param(struct class_device *cdev, char *buf) \ 994show_conn_int_param_##param(struct class_device *cdev, char *buf) \
935{ \ 995{ \
936 uint32_t value = 0; \ 996 uint32_t value = 0; \
937 struct iscsi_if_conn *conn = iscsi_cdev_to_if_conn(cdev); \ 997 struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev); \
938 struct iscsi_internal *priv; \ 998 struct iscsi_transport *t = conn->transport; \
939 \ 999 \
940 priv = to_iscsi_internal(conn->host->transportt); \ 1000 t->get_conn_param(conn->dd_data, param, &value); \
941 if (priv->param_mask & (1 << param)) \
942 priv->iscsi_transport->get_param(conn->connh, param, &value); \
943 return snprintf(buf, 20, format"\n", value); \ 1001 return snprintf(buf, 20, format"\n", value); \
944} 1002}
945 1003
@@ -954,6 +1012,9 @@ iscsi_conn_int_attr(data_digest, ISCSI_PARAM_DATADGST_EN, "%d");
954iscsi_conn_int_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN, "%d"); 1012iscsi_conn_int_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN, "%d");
955iscsi_conn_int_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN, "%d"); 1013iscsi_conn_int_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN, "%d");
956 1014
1015#define iscsi_cdev_to_session(_cdev) \
1016 iscsi_dev_to_session(_cdev->dev)
1017
957/* 1018/*
958 * iSCSI session attrs 1019 * iSCSI session attrs
959 */ 1020 */
@@ -962,20 +1023,11 @@ static ssize_t \
962show_session_int_param_##param(struct class_device *cdev, char *buf) \ 1023show_session_int_param_##param(struct class_device *cdev, char *buf) \
963{ \ 1024{ \
964 uint32_t value = 0; \ 1025 uint32_t value = 0; \
965 struct iscsi_if_session *session = iscsi_cdev_to_if_session(cdev); \ 1026 struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \
966 struct Scsi_Host *shost = iscsi_if_session_to_shost(session); \ 1027 struct Scsi_Host *shost = iscsi_session_to_shost(session); \
967 struct iscsi_internal *priv = to_iscsi_internal(shost->transportt); \ 1028 struct iscsi_transport *t = session->transport; \
968 struct iscsi_if_conn *conn = NULL; \
969 unsigned long flags; \
970 \
971 spin_lock_irqsave(&connlock, flags); \
972 if (!list_empty(&session->connections)) \
973 conn = list_entry(session->connections.next, \
974 struct iscsi_if_conn, session_list); \
975 spin_unlock_irqrestore(&connlock, flags); \
976 \ 1029 \
977 if (conn && (priv->param_mask & (1 << param))) \ 1030 t->get_session_param(shost, param, &value); \
978 priv->iscsi_transport->get_param(conn->connh, param, &value);\
979 return snprintf(buf, 20, format"\n", value); \ 1031 return snprintf(buf, 20, format"\n", value); \
980} 1032}
981 1033
@@ -1004,23 +1056,18 @@ iscsi_session_int_attr(erl, ISCSI_PARAM_ERL, "%d");
1004 count++; \ 1056 count++; \
1005 } 1057 }
1006 1058
1007static int iscsi_is_session_dev(const struct device *dev)
1008{
1009 return dev->release == iscsi_if_session_dev_release;
1010}
1011
1012static int iscsi_session_match(struct attribute_container *cont, 1059static int iscsi_session_match(struct attribute_container *cont,
1013 struct device *dev) 1060 struct device *dev)
1014{ 1061{
1015 struct iscsi_if_session *session; 1062 struct iscsi_cls_session *session;
1016 struct Scsi_Host *shost; 1063 struct Scsi_Host *shost;
1017 struct iscsi_internal *priv; 1064 struct iscsi_internal *priv;
1018 1065
1019 if (!iscsi_is_session_dev(dev)) 1066 if (!iscsi_is_session_dev(dev))
1020 return 0; 1067 return 0;
1021 1068
1022 session = iscsi_dev_to_if_session(dev); 1069 session = iscsi_dev_to_session(dev);
1023 shost = iscsi_if_session_to_shost(session); 1070 shost = iscsi_session_to_shost(session);
1024 if (!shost->transportt) 1071 if (!shost->transportt)
1025 return 0; 1072 return 0;
1026 1073
@@ -1031,23 +1078,21 @@ static int iscsi_session_match(struct attribute_container *cont,
1031 return &priv->session_cont.ac == cont; 1078 return &priv->session_cont.ac == cont;
1032} 1079}
1033 1080
1034static int iscsi_is_conn_dev(const struct device *dev)
1035{
1036 return dev->release == iscsi_if_conn_dev_release;
1037}
1038
1039static int iscsi_conn_match(struct attribute_container *cont, 1081static int iscsi_conn_match(struct attribute_container *cont,
1040 struct device *dev) 1082 struct device *dev)
1041{ 1083{
1042 struct iscsi_if_conn *conn; 1084 struct iscsi_cls_session *session;
1085 struct iscsi_cls_conn *conn;
1043 struct Scsi_Host *shost; 1086 struct Scsi_Host *shost;
1044 struct iscsi_internal *priv; 1087 struct iscsi_internal *priv;
1045 1088
1046 if (!iscsi_is_conn_dev(dev)) 1089 if (!iscsi_is_conn_dev(dev))
1047 return 0; 1090 return 0;
1048 1091
1049 conn = iscsi_dev_to_if_conn(dev); 1092 conn = iscsi_dev_to_conn(dev);
1050 shost = conn->host; 1093 session = iscsi_dev_to_session(conn->dev.parent);
1094 shost = iscsi_session_to_shost(session);
1095
1051 if (!shost->transportt) 1096 if (!shost->transportt)
1052 return 0; 1097 return 0;
1053 1098
@@ -1058,7 +1103,8 @@ static int iscsi_conn_match(struct attribute_container *cont,
1058 return &priv->conn_cont.ac == cont; 1103 return &priv->conn_cont.ac == cont;
1059} 1104}
1060 1105
1061int iscsi_register_transport(struct iscsi_transport *tt) 1106struct scsi_transport_template *
1107iscsi_register_transport(struct iscsi_transport *tt)
1062{ 1108{
1063 struct iscsi_internal *priv; 1109 struct iscsi_internal *priv;
1064 unsigned long flags; 1110 unsigned long flags;
@@ -1068,15 +1114,14 @@ int iscsi_register_transport(struct iscsi_transport *tt)
1068 1114
1069 priv = iscsi_if_transport_lookup(tt); 1115 priv = iscsi_if_transport_lookup(tt);
1070 if (priv) 1116 if (priv)
1071 return -EEXIST; 1117 return NULL;
1072 1118
1073 priv = kmalloc(sizeof(*priv), GFP_KERNEL); 1119 priv = kmalloc(sizeof(*priv), GFP_KERNEL);
1074 if (!priv) 1120 if (!priv)
1075 return -ENOMEM; 1121 return NULL;
1076 memset(priv, 0, sizeof(*priv)); 1122 memset(priv, 0, sizeof(*priv));
1077 INIT_LIST_HEAD(&priv->list); 1123 INIT_LIST_HEAD(&priv->list);
1078 INIT_LIST_HEAD(&priv->sessions); 1124 INIT_LIST_HEAD(&priv->sessions);
1079 spin_lock_init(&priv->session_lock);
1080 priv->iscsi_transport = tt; 1125 priv->iscsi_transport = tt;
1081 1126
1082 priv->cdev.class = &iscsi_transport_class; 1127 priv->cdev.class = &iscsi_transport_class;
@@ -1142,13 +1187,13 @@ int iscsi_register_transport(struct iscsi_transport *tt)
1142 spin_unlock_irqrestore(&iscsi_transport_lock, flags); 1187 spin_unlock_irqrestore(&iscsi_transport_lock, flags);
1143 1188
1144 printk(KERN_NOTICE "iscsi: registered transport (%s)\n", tt->name); 1189 printk(KERN_NOTICE "iscsi: registered transport (%s)\n", tt->name);
1145 return 0; 1190 return &priv->t;
1146 1191
1147unregister_cdev: 1192unregister_cdev:
1148 class_device_unregister(&priv->cdev); 1193 class_device_unregister(&priv->cdev);
1149free_priv: 1194free_priv:
1150 kfree(priv); 1195 kfree(priv);
1151 return err; 1196 return NULL;
1152} 1197}
1153EXPORT_SYMBOL_GPL(iscsi_register_transport); 1198EXPORT_SYMBOL_GPL(iscsi_register_transport);
1154 1199
@@ -1159,19 +1204,11 @@ int iscsi_unregister_transport(struct iscsi_transport *tt)
1159 1204
1160 BUG_ON(!tt); 1205 BUG_ON(!tt);
1161 1206
1162 down(&rx_queue_sema); 1207 mutex_lock(&rx_queue_mutex);
1163 1208
1164 priv = iscsi_if_transport_lookup(tt); 1209 priv = iscsi_if_transport_lookup(tt);
1165 BUG_ON (!priv); 1210 BUG_ON (!priv);
1166 1211
1167 spin_lock_irqsave(&priv->session_lock, flags);
1168 if (!list_empty(&priv->sessions)) {
1169 spin_unlock_irqrestore(&priv->session_lock, flags);
1170 up(&rx_queue_sema);
1171 return -EPERM;
1172 }
1173 spin_unlock_irqrestore(&priv->session_lock, flags);
1174
1175 spin_lock_irqsave(&iscsi_transport_lock, flags); 1212 spin_lock_irqsave(&iscsi_transport_lock, flags);
1176 list_del(&priv->list); 1213 list_del(&priv->list);
1177 spin_unlock_irqrestore(&iscsi_transport_lock, flags); 1214 spin_unlock_irqrestore(&iscsi_transport_lock, flags);
@@ -1181,7 +1218,7 @@ int iscsi_unregister_transport(struct iscsi_transport *tt)
1181 1218
1182 sysfs_remove_group(&priv->cdev.kobj, &iscsi_transport_group); 1219 sysfs_remove_group(&priv->cdev.kobj, &iscsi_transport_group);
1183 class_device_unregister(&priv->cdev); 1220 class_device_unregister(&priv->cdev);
1184 up(&rx_queue_sema); 1221 mutex_unlock(&rx_queue_mutex);
1185 1222
1186 return 0; 1223 return 0;
1187} 1224}
@@ -1194,14 +1231,14 @@ iscsi_rcv_nl_event(struct notifier_block *this, unsigned long event, void *ptr)
1194 1231
1195 if (event == NETLINK_URELEASE && 1232 if (event == NETLINK_URELEASE &&
1196 n->protocol == NETLINK_ISCSI && n->pid) { 1233 n->protocol == NETLINK_ISCSI && n->pid) {
1197 struct iscsi_if_conn *conn; 1234 struct iscsi_cls_conn *conn;
1198 unsigned long flags; 1235 unsigned long flags;
1199 1236
1200 mempool_zone_complete(&z_reply); 1237 mempool_zone_complete(z_reply);
1201 spin_lock_irqsave(&connlock, flags); 1238 spin_lock_irqsave(&connlock, flags);
1202 list_for_each_entry(conn, &connlist, conn_list) { 1239 list_for_each_entry(conn, &connlist, conn_list) {
1203 mempool_zone_complete(&conn->z_error); 1240 mempool_zone_complete(conn->z_error);
1204 mempool_zone_complete(&conn->z_pdu); 1241 mempool_zone_complete(conn->z_pdu);
1205 } 1242 }
1206 spin_unlock_irqrestore(&connlock, flags); 1243 spin_unlock_irqrestore(&connlock, flags);
1207 } 1244 }
@@ -1234,15 +1271,15 @@ static __init int iscsi_transport_init(void)
1234 goto unregister_session_class; 1271 goto unregister_session_class;
1235 1272
1236 nls = netlink_kernel_create(NETLINK_ISCSI, 1, iscsi_if_rx, 1273 nls = netlink_kernel_create(NETLINK_ISCSI, 1, iscsi_if_rx,
1237 THIS_MODULE); 1274 THIS_MODULE);
1238 if (!nls) { 1275 if (!nls) {
1239 err = -ENOBUFS; 1276 err = -ENOBUFS;
1240 goto unregister_notifier; 1277 goto unregister_notifier;
1241 } 1278 }
1242 1279
1243 err = mempool_zone_init(&z_reply, Z_MAX_REPLY, 1280 z_reply = mempool_zone_init(Z_MAX_REPLY,
1244 NLMSG_SPACE(sizeof(struct iscsi_uevent)), Z_HIWAT_REPLY); 1281 NLMSG_SPACE(sizeof(struct iscsi_uevent)), Z_HIWAT_REPLY);
1245 if (!err) 1282 if (z_reply)
1246 return 0; 1283 return 0;
1247 1284
1248 sock_release(nls->sk_socket); 1285 sock_release(nls->sk_socket);
@@ -1259,7 +1296,7 @@ unregister_transport_class:
1259 1296
1260static void __exit iscsi_transport_exit(void) 1297static void __exit iscsi_transport_exit(void)
1261{ 1298{
1262 mempool_destroy(z_reply.pool); 1299 mempool_zone_destroy(z_reply);
1263 sock_release(nls->sk_socket); 1300 sock_release(nls->sk_socket);
1264 netlink_unregister_notifier(&iscsi_nl_notifier); 1301 netlink_unregister_notifier(&iscsi_nl_notifier);
1265 transport_class_unregister(&iscsi_connection_class); 1302 transport_class_unregister(&iscsi_connection_class);
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index edabbd05d258..a3e0b7bc2d7b 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -29,6 +29,7 @@
29#include <linux/slab.h> 29#include <linux/slab.h>
30#include <linux/string.h> 30#include <linux/string.h>
31 31
32#include <scsi/scsi.h>
32#include <scsi/scsi_device.h> 33#include <scsi/scsi_device.h>
33#include <scsi/scsi_host.h> 34#include <scsi/scsi_host.h>
34#include <scsi/scsi_transport.h> 35#include <scsi/scsi_transport.h>
@@ -62,7 +63,7 @@ struct sas_internal {
62 63
63struct sas_host_attrs { 64struct sas_host_attrs {
64 struct list_head rphy_list; 65 struct list_head rphy_list;
65 spinlock_t lock; 66 struct mutex lock;
66 u32 next_target_id; 67 u32 next_target_id;
67}; 68};
68#define to_sas_host_attrs(host) ((struct sas_host_attrs *)(host)->shost_data) 69#define to_sas_host_attrs(host) ((struct sas_host_attrs *)(host)->shost_data)
@@ -165,7 +166,7 @@ static int sas_host_setup(struct transport_container *tc, struct device *dev,
165 struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 166 struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
166 167
167 INIT_LIST_HEAD(&sas_host->rphy_list); 168 INIT_LIST_HEAD(&sas_host->rphy_list);
168 spin_lock_init(&sas_host->lock); 169 mutex_init(&sas_host->lock);
169 sas_host->next_target_id = 0; 170 sas_host->next_target_id = 0;
170 return 0; 171 return 0;
171} 172}
@@ -626,7 +627,7 @@ int sas_rphy_add(struct sas_rphy *rphy)
626 transport_add_device(&rphy->dev); 627 transport_add_device(&rphy->dev);
627 transport_configure_device(&rphy->dev); 628 transport_configure_device(&rphy->dev);
628 629
629 spin_lock(&sas_host->lock); 630 mutex_lock(&sas_host->lock);
630 list_add_tail(&rphy->list, &sas_host->rphy_list); 631 list_add_tail(&rphy->list, &sas_host->rphy_list);
631 if (identify->device_type == SAS_END_DEVICE && 632 if (identify->device_type == SAS_END_DEVICE &&
632 (identify->target_port_protocols & 633 (identify->target_port_protocols &
@@ -634,10 +635,10 @@ int sas_rphy_add(struct sas_rphy *rphy)
634 rphy->scsi_target_id = sas_host->next_target_id++; 635 rphy->scsi_target_id = sas_host->next_target_id++;
635 else 636 else
636 rphy->scsi_target_id = -1; 637 rphy->scsi_target_id = -1;
637 spin_unlock(&sas_host->lock); 638 mutex_unlock(&sas_host->lock);
638 639
639 if (rphy->scsi_target_id != -1) { 640 if (rphy->scsi_target_id != -1) {
640 scsi_scan_target(&rphy->dev, parent->number, 641 scsi_scan_target(&rphy->dev, parent->port_identifier,
641 rphy->scsi_target_id, ~0, 0); 642 rphy->scsi_target_id, ~0, 0);
642 } 643 }
643 644
@@ -661,9 +662,9 @@ void sas_rphy_free(struct sas_rphy *rphy)
661 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent); 662 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
662 struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 663 struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
663 664
664 spin_lock(&sas_host->lock); 665 mutex_lock(&sas_host->lock);
665 list_del(&rphy->list); 666 list_del(&rphy->list);
666 spin_unlock(&sas_host->lock); 667 mutex_unlock(&sas_host->lock);
667 668
668 transport_destroy_device(&rphy->dev); 669 transport_destroy_device(&rphy->dev);
669 put_device(rphy->dev.parent); 670 put_device(rphy->dev.parent);
@@ -687,15 +688,27 @@ sas_rphy_delete(struct sas_rphy *rphy)
687 struct Scsi_Host *shost = dev_to_shost(parent->dev.parent); 688 struct Scsi_Host *shost = dev_to_shost(parent->dev.parent);
688 struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 689 struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
689 690
690 scsi_remove_target(dev); 691 switch (rphy->identify.device_type) {
692 case SAS_END_DEVICE:
693 scsi_remove_target(dev);
694 break;
695 case SAS_EDGE_EXPANDER_DEVICE:
696 case SAS_FANOUT_EXPANDER_DEVICE:
697 device_for_each_child(dev, NULL, do_sas_phy_delete);
698 break;
699 default:
700 break;
701 }
691 702
692 transport_remove_device(dev); 703 transport_remove_device(dev);
693 device_del(dev); 704 device_del(dev);
694 transport_destroy_device(dev); 705 transport_destroy_device(dev);
695 706
696 spin_lock(&sas_host->lock); 707 mutex_lock(&sas_host->lock);
697 list_del(&rphy->list); 708 list_del(&rphy->list);
698 spin_unlock(&sas_host->lock); 709 mutex_unlock(&sas_host->lock);
710
711 parent->rphy = NULL;
699 712
700 put_device(&parent->dev); 713 put_device(&parent->dev);
701} 714}
@@ -719,23 +732,28 @@ EXPORT_SYMBOL(scsi_is_sas_rphy);
719 * SCSI scan helper 732 * SCSI scan helper
720 */ 733 */
721 734
722static struct device *sas_target_parent(struct Scsi_Host *shost, 735static int sas_user_scan(struct Scsi_Host *shost, uint channel,
723 int channel, uint id) 736 uint id, uint lun)
724{ 737{
725 struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 738 struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
726 struct sas_rphy *rphy; 739 struct sas_rphy *rphy;
727 struct device *dev = NULL;
728 740
729 spin_lock(&sas_host->lock); 741 mutex_lock(&sas_host->lock);
730 list_for_each_entry(rphy, &sas_host->rphy_list, list) { 742 list_for_each_entry(rphy, &sas_host->rphy_list, list) {
731 struct sas_phy *parent = dev_to_phy(rphy->dev.parent); 743 struct sas_phy *parent = dev_to_phy(rphy->dev.parent);
732 if (parent->number == channel && 744
733 rphy->scsi_target_id == id) 745 if (rphy->scsi_target_id == -1)
734 dev = &rphy->dev; 746 continue;
747
748 if ((channel == SCAN_WILD_CARD || channel == parent->port_identifier) &&
749 (id == SCAN_WILD_CARD || id == rphy->scsi_target_id)) {
750 scsi_scan_target(&rphy->dev, parent->port_identifier,
751 rphy->scsi_target_id, lun, 1);
752 }
735 } 753 }
736 spin_unlock(&sas_host->lock); 754 mutex_unlock(&sas_host->lock);
737 755
738 return dev; 756 return 0;
739} 757}
740 758
741 759
@@ -780,7 +798,7 @@ sas_attach_transport(struct sas_function_template *ft)
780 return NULL; 798 return NULL;
781 memset(i, 0, sizeof(struct sas_internal)); 799 memset(i, 0, sizeof(struct sas_internal));
782 800
783 i->t.target_parent = sas_target_parent; 801 i->t.user_scan = sas_user_scan;
784 802
785 i->t.host_attrs.ac.attrs = &i->host_attrs[0]; 803 i->t.host_attrs.ac.attrs = &i->host_attrs[0];
786 i->t.host_attrs.ac.class = &sas_host_class.class; 804 i->t.host_attrs.ac.class = &sas_host_class.class;
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
index 46da6fe10ad5..7ee95eb83dda 100644
--- a/drivers/scsi/scsi_transport_spi.c
+++ b/drivers/scsi/scsi_transport_spi.c
@@ -24,7 +24,7 @@
24#include <linux/module.h> 24#include <linux/module.h>
25#include <linux/workqueue.h> 25#include <linux/workqueue.h>
26#include <linux/blkdev.h> 26#include <linux/blkdev.h>
27#include <asm/semaphore.h> 27#include <linux/mutex.h>
28#include <scsi/scsi.h> 28#include <scsi/scsi.h>
29#include "scsi_priv.h" 29#include "scsi_priv.h"
30#include <scsi/scsi_device.h> 30#include <scsi/scsi_device.h>
@@ -48,7 +48,7 @@
48 48
49/* Private data accessors (keep these out of the header file) */ 49/* Private data accessors (keep these out of the header file) */
50#define spi_dv_pending(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_pending) 50#define spi_dv_pending(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_pending)
51#define spi_dv_sem(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_sem) 51#define spi_dv_mutex(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_mutex)
52 52
53struct spi_internal { 53struct spi_internal {
54 struct scsi_transport_template t; 54 struct scsi_transport_template t;
@@ -242,7 +242,7 @@ static int spi_setup_transport_attrs(struct transport_container *tc,
242 spi_hold_mcs(starget) = 0; 242 spi_hold_mcs(starget) = 0;
243 spi_dv_pending(starget) = 0; 243 spi_dv_pending(starget) = 0;
244 spi_initial_dv(starget) = 0; 244 spi_initial_dv(starget) = 0;
245 init_MUTEX(&spi_dv_sem(starget)); 245 mutex_init(&spi_dv_mutex(starget));
246 246
247 return 0; 247 return 0;
248} 248}
@@ -915,7 +915,7 @@ spi_dv_device(struct scsi_device *sdev)
915 scsi_target_quiesce(starget); 915 scsi_target_quiesce(starget);
916 916
917 spi_dv_pending(starget) = 1; 917 spi_dv_pending(starget) = 1;
918 down(&spi_dv_sem(starget)); 918 mutex_lock(&spi_dv_mutex(starget));
919 919
920 starget_printk(KERN_INFO, starget, "Beginning Domain Validation\n"); 920 starget_printk(KERN_INFO, starget, "Beginning Domain Validation\n");
921 921
@@ -923,7 +923,7 @@ spi_dv_device(struct scsi_device *sdev)
923 923
924 starget_printk(KERN_INFO, starget, "Ending Domain Validation\n"); 924 starget_printk(KERN_INFO, starget, "Ending Domain Validation\n");
925 925
926 up(&spi_dv_sem(starget)); 926 mutex_unlock(&spi_dv_mutex(starget));
927 spi_dv_pending(starget) = 0; 927 spi_dv_pending(starget) = 0;
928 928
929 scsi_target_resume(starget); 929 scsi_target_resume(starget);
@@ -1075,7 +1075,7 @@ static const char * const extended_msgs[] = {
1075/* 0x04 */ "Parallel Protocol Request" 1075/* 0x04 */ "Parallel Protocol Request"
1076}; 1076};
1077 1077
1078void print_nego(const unsigned char *msg, int per, int off, int width) 1078static void print_nego(const unsigned char *msg, int per, int off, int width)
1079{ 1079{
1080 if (per) { 1080 if (per) {
1081 char buf[20]; 1081 char buf[20];
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 4c5127ed379c..930db398d107 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -49,6 +49,7 @@
49#include <linux/blkpg.h> 49#include <linux/blkpg.h>
50#include <linux/kref.h> 50#include <linux/kref.h>
51#include <linux/delay.h> 51#include <linux/delay.h>
52#include <linux/mutex.h>
52#include <asm/uaccess.h> 53#include <asm/uaccess.h>
53 54
54#include <scsi/scsi.h> 55#include <scsi/scsi.h>
@@ -111,7 +112,7 @@ static DEFINE_SPINLOCK(sd_index_lock);
111/* This semaphore is used to mediate the 0->1 reference get in the 112/* This semaphore is used to mediate the 0->1 reference get in the
112 * face of object destruction (i.e. we can't allow a get on an 113 * face of object destruction (i.e. we can't allow a get on an
113 * object after last put) */ 114 * object after last put) */
114static DECLARE_MUTEX(sd_ref_sem); 115static DEFINE_MUTEX(sd_ref_mutex);
115 116
116static int sd_revalidate_disk(struct gendisk *disk); 117static int sd_revalidate_disk(struct gendisk *disk);
117static void sd_rw_intr(struct scsi_cmnd * SCpnt); 118static void sd_rw_intr(struct scsi_cmnd * SCpnt);
@@ -193,9 +194,9 @@ static struct scsi_disk *scsi_disk_get(struct gendisk *disk)
193{ 194{
194 struct scsi_disk *sdkp; 195 struct scsi_disk *sdkp;
195 196
196 down(&sd_ref_sem); 197 mutex_lock(&sd_ref_mutex);
197 sdkp = __scsi_disk_get(disk); 198 sdkp = __scsi_disk_get(disk);
198 up(&sd_ref_sem); 199 mutex_unlock(&sd_ref_mutex);
199 return sdkp; 200 return sdkp;
200} 201}
201 202
@@ -203,11 +204,11 @@ static struct scsi_disk *scsi_disk_get_from_dev(struct device *dev)
203{ 204{
204 struct scsi_disk *sdkp; 205 struct scsi_disk *sdkp;
205 206
206 down(&sd_ref_sem); 207 mutex_lock(&sd_ref_mutex);
207 sdkp = dev_get_drvdata(dev); 208 sdkp = dev_get_drvdata(dev);
208 if (sdkp) 209 if (sdkp)
209 sdkp = __scsi_disk_get(sdkp->disk); 210 sdkp = __scsi_disk_get(sdkp->disk);
210 up(&sd_ref_sem); 211 mutex_unlock(&sd_ref_mutex);
211 return sdkp; 212 return sdkp;
212} 213}
213 214
@@ -215,10 +216,10 @@ static void scsi_disk_put(struct scsi_disk *sdkp)
215{ 216{
216 struct scsi_device *sdev = sdkp->device; 217 struct scsi_device *sdev = sdkp->device;
217 218
218 down(&sd_ref_sem); 219 mutex_lock(&sd_ref_mutex);
219 kref_put(&sdkp->kref, scsi_disk_release); 220 kref_put(&sdkp->kref, scsi_disk_release);
220 scsi_device_put(sdev); 221 scsi_device_put(sdev);
221 up(&sd_ref_sem); 222 mutex_unlock(&sd_ref_mutex);
222} 223}
223 224
224/** 225/**
@@ -231,34 +232,12 @@ static void scsi_disk_put(struct scsi_disk *sdkp)
231 **/ 232 **/
232static int sd_init_command(struct scsi_cmnd * SCpnt) 233static int sd_init_command(struct scsi_cmnd * SCpnt)
233{ 234{
234 unsigned int this_count, timeout;
235 struct gendisk *disk;
236 sector_t block;
237 struct scsi_device *sdp = SCpnt->device; 235 struct scsi_device *sdp = SCpnt->device;
238 struct request *rq = SCpnt->request; 236 struct request *rq = SCpnt->request;
239 237 struct gendisk *disk = rq->rq_disk;
240 timeout = sdp->timeout; 238 sector_t block = rq->sector;
241 239 unsigned int this_count = SCpnt->request_bufflen >> 9;
242 /* 240 unsigned int timeout = sdp->timeout;
243 * SG_IO from block layer already setup, just copy cdb basically
244 */
245 if (blk_pc_request(rq)) {
246 scsi_setup_blk_pc_cmnd(SCpnt);
247 if (rq->timeout)
248 timeout = rq->timeout;
249
250 goto queue;
251 }
252
253 /*
254 * we only do REQ_CMD and REQ_BLOCK_PC
255 */
256 if (!blk_fs_request(rq))
257 return 0;
258
259 disk = rq->rq_disk;
260 block = rq->sector;
261 this_count = SCpnt->request_bufflen >> 9;
262 241
263 SCSI_LOG_HLQUEUE(1, printk("sd_init_command: disk=%s, block=%llu, " 242 SCSI_LOG_HLQUEUE(1, printk("sd_init_command: disk=%s, block=%llu, "
264 "count=%d\n", disk->disk_name, 243 "count=%d\n", disk->disk_name,
@@ -401,8 +380,6 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
401 SCpnt->transfersize = sdp->sector_size; 380 SCpnt->transfersize = sdp->sector_size;
402 SCpnt->underflow = this_count << 9; 381 SCpnt->underflow = this_count << 9;
403 SCpnt->allowed = SD_MAX_RETRIES; 382 SCpnt->allowed = SD_MAX_RETRIES;
404
405queue:
406 SCpnt->timeout_per_command = timeout; 383 SCpnt->timeout_per_command = timeout;
407 384
408 /* 385 /*
@@ -836,15 +813,7 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt)
836 relatively rare error condition, no care is taken to avoid 813 relatively rare error condition, no care is taken to avoid
837 unnecessary additional work such as memcpy's that could be avoided. 814 unnecessary additional work such as memcpy's that could be avoided.
838 */ 815 */
839 816 if (driver_byte(result) != 0 &&
840 /*
841 * If SG_IO from block layer then set good_bytes to stop retries;
842 * else if errors, check them, and if necessary prepare for
843 * (partial) retries.
844 */
845 if (blk_pc_request(SCpnt->request))
846 good_bytes = this_count;
847 else if (driver_byte(result) != 0 &&
848 sense_valid && !sense_deferred) { 817 sense_valid && !sense_deferred) {
849 switch (sshdr.sense_key) { 818 switch (sshdr.sense_key) {
850 case MEDIUM_ERROR: 819 case MEDIUM_ERROR:
@@ -1635,10 +1604,10 @@ static int sd_remove(struct device *dev)
1635 del_gendisk(sdkp->disk); 1604 del_gendisk(sdkp->disk);
1636 sd_shutdown(dev); 1605 sd_shutdown(dev);
1637 1606
1638 down(&sd_ref_sem); 1607 mutex_lock(&sd_ref_mutex);
1639 dev_set_drvdata(dev, NULL); 1608 dev_set_drvdata(dev, NULL);
1640 kref_put(&sdkp->kref, scsi_disk_release); 1609 kref_put(&sdkp->kref, scsi_disk_release);
1641 up(&sd_ref_sem); 1610 mutex_unlock(&sd_ref_mutex);
1642 1611
1643 return 0; 1612 return 0;
1644} 1613}
@@ -1647,7 +1616,7 @@ static int sd_remove(struct device *dev)
1647 * scsi_disk_release - Called to free the scsi_disk structure 1616 * scsi_disk_release - Called to free the scsi_disk structure
1648 * @kref: pointer to embedded kref 1617 * @kref: pointer to embedded kref
1649 * 1618 *
1650 * sd_ref_sem must be held entering this routine. Because it is 1619 * sd_ref_mutex must be held entering this routine. Because it is
1651 * called on last put, you should always use the scsi_disk_get() 1620 * called on last put, you should always use the scsi_disk_get()
1652 * scsi_disk_put() helpers which manipulate the semaphore directly 1621 * scsi_disk_put() helpers which manipulate the semaphore directly
1653 * and never do a direct kref_put(). 1622 * and never do a direct kref_put().
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index a4d9be7c6874..997f8e30509b 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -44,6 +44,7 @@
44#include <linux/interrupt.h> 44#include <linux/interrupt.h>
45#include <linux/init.h> 45#include <linux/init.h>
46#include <linux/blkdev.h> 46#include <linux/blkdev.h>
47#include <linux/mutex.h>
47#include <asm/uaccess.h> 48#include <asm/uaccess.h>
48 49
49#include <scsi/scsi.h> 50#include <scsi/scsi.h>
@@ -90,7 +91,7 @@ static DEFINE_SPINLOCK(sr_index_lock);
90/* This semaphore is used to mediate the 0->1 reference get in the 91/* This semaphore is used to mediate the 0->1 reference get in the
91 * face of object destruction (i.e. we can't allow a get on an 92 * face of object destruction (i.e. we can't allow a get on an
92 * object after last put) */ 93 * object after last put) */
93static DECLARE_MUTEX(sr_ref_sem); 94static DEFINE_MUTEX(sr_ref_mutex);
94 95
95static int sr_open(struct cdrom_device_info *, int); 96static int sr_open(struct cdrom_device_info *, int);
96static void sr_release(struct cdrom_device_info *); 97static void sr_release(struct cdrom_device_info *);
@@ -133,7 +134,7 @@ static inline struct scsi_cd *scsi_cd_get(struct gendisk *disk)
133{ 134{
134 struct scsi_cd *cd = NULL; 135 struct scsi_cd *cd = NULL;
135 136
136 down(&sr_ref_sem); 137 mutex_lock(&sr_ref_mutex);
137 if (disk->private_data == NULL) 138 if (disk->private_data == NULL)
138 goto out; 139 goto out;
139 cd = scsi_cd(disk); 140 cd = scsi_cd(disk);
@@ -146,18 +147,18 @@ static inline struct scsi_cd *scsi_cd_get(struct gendisk *disk)
146 kref_put(&cd->kref, sr_kref_release); 147 kref_put(&cd->kref, sr_kref_release);
147 cd = NULL; 148 cd = NULL;
148 out: 149 out:
149 up(&sr_ref_sem); 150 mutex_unlock(&sr_ref_mutex);
150 return cd; 151 return cd;
151} 152}
152 153
153static inline void scsi_cd_put(struct scsi_cd *cd) 154static void scsi_cd_put(struct scsi_cd *cd)
154{ 155{
155 struct scsi_device *sdev = cd->device; 156 struct scsi_device *sdev = cd->device;
156 157
157 down(&sr_ref_sem); 158 mutex_lock(&sr_ref_mutex);
158 kref_put(&cd->kref, sr_kref_release); 159 kref_put(&cd->kref, sr_kref_release);
159 scsi_device_put(sdev); 160 scsi_device_put(sdev);
160 up(&sr_ref_sem); 161 mutex_unlock(&sr_ref_mutex);
161} 162}
162 163
163/* 164/*
@@ -237,8 +238,6 @@ static void rw_intr(struct scsi_cmnd * SCpnt)
237 case ILLEGAL_REQUEST: 238 case ILLEGAL_REQUEST:
238 if (!(SCpnt->sense_buffer[0] & 0x90)) 239 if (!(SCpnt->sense_buffer[0] & 0x90))
239 break; 240 break;
240 if (!blk_fs_request(SCpnt->request))
241 break;
242 error_sector = (SCpnt->sense_buffer[3] << 24) | 241 error_sector = (SCpnt->sense_buffer[3] << 24) |
243 (SCpnt->sense_buffer[4] << 16) | 242 (SCpnt->sense_buffer[4] << 16) |
244 (SCpnt->sense_buffer[5] << 8) | 243 (SCpnt->sense_buffer[5] << 8) |
@@ -317,23 +316,6 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
317 } 316 }
318 317
319 /* 318 /*
320 * these are already setup, just copy cdb basically
321 */
322 if (SCpnt->request->flags & REQ_BLOCK_PC) {
323 scsi_setup_blk_pc_cmnd(SCpnt);
324
325 if (SCpnt->timeout_per_command)
326 timeout = SCpnt->timeout_per_command;
327
328 goto queue;
329 }
330
331 if (!(SCpnt->request->flags & REQ_CMD)) {
332 blk_dump_rq_flags(SCpnt->request, "sr unsup command");
333 return 0;
334 }
335
336 /*
337 * we do lazy blocksize switching (when reading XA sectors, 319 * we do lazy blocksize switching (when reading XA sectors,
338 * see CDROMREADMODE2 ioctl) 320 * see CDROMREADMODE2 ioctl)
339 */ 321 */
@@ -421,8 +403,6 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
421 */ 403 */
422 SCpnt->transfersize = cd->device->sector_size; 404 SCpnt->transfersize = cd->device->sector_size;
423 SCpnt->underflow = this_count << 9; 405 SCpnt->underflow = this_count << 9;
424
425queue:
426 SCpnt->allowed = MAX_RETRIES; 406 SCpnt->allowed = MAX_RETRIES;
427 SCpnt->timeout_per_command = timeout; 407 SCpnt->timeout_per_command = timeout;
428 408
@@ -762,8 +742,9 @@ static void get_capabilities(struct scsi_cd *cd)
762 /* failed, drive doesn't have capabilities mode page */ 742 /* failed, drive doesn't have capabilities mode page */
763 cd->cdi.speed = 1; 743 cd->cdi.speed = 1;
764 cd->cdi.mask |= (CDC_CD_R | CDC_CD_RW | CDC_DVD_R | 744 cd->cdi.mask |= (CDC_CD_R | CDC_CD_RW | CDC_DVD_R |
765 CDC_DVD | CDC_DVD_RAM | 745 CDC_DVD | CDC_DVD_RAM |
766 CDC_SELECT_DISC | CDC_SELECT_SPEED); 746 CDC_SELECT_DISC | CDC_SELECT_SPEED |
747 CDC_MRW | CDC_MRW_W | CDC_RAM);
767 kfree(buffer); 748 kfree(buffer);
768 printk("%s: scsi-1 drive\n", cd->cdi.name); 749 printk("%s: scsi-1 drive\n", cd->cdi.name);
769 return; 750 return;
@@ -845,7 +826,7 @@ static int sr_packet(struct cdrom_device_info *cdi,
845 * sr_kref_release - Called to free the scsi_cd structure 826 * sr_kref_release - Called to free the scsi_cd structure
846 * @kref: pointer to embedded kref 827 * @kref: pointer to embedded kref
847 * 828 *
848 * sr_ref_sem must be held entering this routine. Because it is 829 * sr_ref_mutex must be held entering this routine. Because it is
849 * called on last put, you should always use the scsi_cd_get() 830 * called on last put, you should always use the scsi_cd_get()
850 * scsi_cd_put() helpers which manipulate the semaphore directly 831 * scsi_cd_put() helpers which manipulate the semaphore directly
851 * and never do a direct kref_put(). 832 * and never do a direct kref_put().
@@ -874,9 +855,9 @@ static int sr_remove(struct device *dev)
874 855
875 del_gendisk(cd->disk); 856 del_gendisk(cd->disk);
876 857
877 down(&sr_ref_sem); 858 mutex_lock(&sr_ref_mutex);
878 kref_put(&cd->kref, sr_kref_release); 859 kref_put(&cd->kref, sr_kref_release);
879 up(&sr_ref_sem); 860 mutex_unlock(&sr_ref_mutex);
880 861
881 return 0; 862 return 0;
882} 863}
diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c
index 6e45ac3c43c5..5d02ff4db6cc 100644
--- a/drivers/scsi/sr_ioctl.c
+++ b/drivers/scsi/sr_ioctl.c
@@ -31,6 +31,79 @@ static int xa_test = 0;
31 31
32module_param(xa_test, int, S_IRUGO | S_IWUSR); 32module_param(xa_test, int, S_IRUGO | S_IWUSR);
33 33
34/* primitive to determine whether we need to have GFP_DMA set based on
35 * the status of the unchecked_isa_dma flag in the host structure */
36#define SR_GFP_DMA(cd) (((cd)->device->host->unchecked_isa_dma) ? GFP_DMA : 0)
37
38
39static int sr_read_tochdr(struct cdrom_device_info *cdi,
40 struct cdrom_tochdr *tochdr)
41{
42 struct scsi_cd *cd = cdi->handle;
43 struct packet_command cgc;
44 int result;
45 unsigned char *buffer;
46
47 buffer = kmalloc(32, GFP_KERNEL | SR_GFP_DMA(cd));
48 if (!buffer)
49 return -ENOMEM;
50
51 memset(&cgc, 0, sizeof(struct packet_command));
52 cgc.timeout = IOCTL_TIMEOUT;
53 cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
54 cgc.cmd[8] = 12; /* LSB of length */
55 cgc.buffer = buffer;
56 cgc.buflen = 12;
57 cgc.quiet = 1;
58 cgc.data_direction = DMA_FROM_DEVICE;
59
60 result = sr_do_ioctl(cd, &cgc);
61
62 tochdr->cdth_trk0 = buffer[2];
63 tochdr->cdth_trk1 = buffer[3];
64
65 kfree(buffer);
66 return result;
67}
68
69static int sr_read_tocentry(struct cdrom_device_info *cdi,
70 struct cdrom_tocentry *tocentry)
71{
72 struct scsi_cd *cd = cdi->handle;
73 struct packet_command cgc;
74 int result;
75 unsigned char *buffer;
76
77 buffer = kmalloc(32, GFP_KERNEL | SR_GFP_DMA(cd));
78 if (!buffer)
79 return -ENOMEM;
80
81 memset(&cgc, 0, sizeof(struct packet_command));
82 cgc.timeout = IOCTL_TIMEOUT;
83 cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
84 cgc.cmd[1] |= (tocentry->cdte_format == CDROM_MSF) ? 0x02 : 0;
85 cgc.cmd[6] = tocentry->cdte_track;
86 cgc.cmd[8] = 12; /* LSB of length */
87 cgc.buffer = buffer;
88 cgc.buflen = 12;
89 cgc.data_direction = DMA_FROM_DEVICE;
90
91 result = sr_do_ioctl(cd, &cgc);
92
93 tocentry->cdte_ctrl = buffer[5] & 0xf;
94 tocentry->cdte_adr = buffer[5] >> 4;
95 tocentry->cdte_datamode = (tocentry->cdte_ctrl & 0x04) ? 1 : 0;
96 if (tocentry->cdte_format == CDROM_MSF) {
97 tocentry->cdte_addr.msf.minute = buffer[9];
98 tocentry->cdte_addr.msf.second = buffer[10];
99 tocentry->cdte_addr.msf.frame = buffer[11];
100 } else
101 tocentry->cdte_addr.lba = (((((buffer[8] << 8) + buffer[9]) << 8)
102 + buffer[10]) << 8) + buffer[11];
103
104 kfree(buffer);
105 return result;
106}
34 107
35#define IOCTL_RETRIES 3 108#define IOCTL_RETRIES 3
36 109
@@ -45,7 +118,8 @@ static int sr_fake_playtrkind(struct cdrom_device_info *cdi, struct cdrom_ti *ti
45 struct packet_command cgc; 118 struct packet_command cgc;
46 int ntracks, ret; 119 int ntracks, ret;
47 120
48 if ((ret = sr_audio_ioctl(cdi, CDROMREADTOCHDR, &tochdr))) 121 ret = sr_read_tochdr(cdi, &tochdr);
122 if (ret)
49 return ret; 123 return ret;
50 124
51 ntracks = tochdr.cdth_trk1 - tochdr.cdth_trk0 + 1; 125 ntracks = tochdr.cdth_trk1 - tochdr.cdth_trk0 + 1;
@@ -60,9 +134,11 @@ static int sr_fake_playtrkind(struct cdrom_device_info *cdi, struct cdrom_ti *ti
60 trk1_te.cdte_track = ti->cdti_trk1; 134 trk1_te.cdte_track = ti->cdti_trk1;
61 trk1_te.cdte_format = CDROM_MSF; 135 trk1_te.cdte_format = CDROM_MSF;
62 136
63 if ((ret = sr_audio_ioctl(cdi, CDROMREADTOCENTRY, &trk0_te))) 137 ret = sr_read_tocentry(cdi, &trk0_te);
138 if (ret)
64 return ret; 139 return ret;
65 if ((ret = sr_audio_ioctl(cdi, CDROMREADTOCENTRY, &trk1_te))) 140 ret = sr_read_tocentry(cdi, &trk1_te);
141 if (ret)
66 return ret; 142 return ret;
67 143
68 memset(&cgc, 0, sizeof(struct packet_command)); 144 memset(&cgc, 0, sizeof(struct packet_command));
@@ -78,6 +154,30 @@ static int sr_fake_playtrkind(struct cdrom_device_info *cdi, struct cdrom_ti *ti
78 return sr_do_ioctl(cdi->handle, &cgc); 154 return sr_do_ioctl(cdi->handle, &cgc);
79} 155}
80 156
157static int sr_play_trkind(struct cdrom_device_info *cdi,
158 struct cdrom_ti *ti)
159
160{
161 struct scsi_cd *cd = cdi->handle;
162 struct packet_command cgc;
163 int result;
164
165 memset(&cgc, 0, sizeof(struct packet_command));
166 cgc.timeout = IOCTL_TIMEOUT;
167 cgc.cmd[0] = GPCMD_PLAYAUDIO_TI;
168 cgc.cmd[4] = ti->cdti_trk0;
169 cgc.cmd[5] = ti->cdti_ind0;
170 cgc.cmd[7] = ti->cdti_trk1;
171 cgc.cmd[8] = ti->cdti_ind1;
172 cgc.data_direction = DMA_NONE;
173
174 result = sr_do_ioctl(cd, &cgc);
175 if (result == -EDRIVE_CANT_DO_THIS)
176 result = sr_fake_playtrkind(cdi, ti);
177
178 return result;
179}
180
81/* We do our own retries because we want to know what the specific 181/* We do our own retries because we want to know what the specific
82 error code is. Normally the UNIT_ATTENTION code will automatically 182 error code is. Normally the UNIT_ATTENTION code will automatically
83 clear after one error */ 183 clear after one error */
@@ -229,13 +329,14 @@ int sr_disk_status(struct cdrom_device_info *cdi)
229 int i, rc, have_datatracks = 0; 329 int i, rc, have_datatracks = 0;
230 330
231 /* look for data tracks */ 331 /* look for data tracks */
232 if (0 != (rc = sr_audio_ioctl(cdi, CDROMREADTOCHDR, &toc_h))) 332 rc = sr_read_tochdr(cdi, &toc_h);
333 if (rc)
233 return (rc == -ENOMEDIUM) ? CDS_NO_DISC : CDS_NO_INFO; 334 return (rc == -ENOMEDIUM) ? CDS_NO_DISC : CDS_NO_INFO;
234 335
235 for (i = toc_h.cdth_trk0; i <= toc_h.cdth_trk1; i++) { 336 for (i = toc_h.cdth_trk0; i <= toc_h.cdth_trk1; i++) {
236 toc_e.cdte_track = i; 337 toc_e.cdte_track = i;
237 toc_e.cdte_format = CDROM_LBA; 338 toc_e.cdte_format = CDROM_LBA;
238 if (sr_audio_ioctl(cdi, CDROMREADTOCENTRY, &toc_e)) 339 if (sr_read_tocentry(cdi, &toc_e))
239 return CDS_NO_INFO; 340 return CDS_NO_INFO;
240 if (toc_e.cdte_ctrl & CDROM_DATA_TRACK) { 341 if (toc_e.cdte_ctrl & CDROM_DATA_TRACK) {
241 have_datatracks = 1; 342 have_datatracks = 1;
@@ -262,10 +363,6 @@ int sr_get_last_session(struct cdrom_device_info *cdi,
262 return 0; 363 return 0;
263} 364}
264 365
265/* primitive to determine whether we need to have GFP_DMA set based on
266 * the status of the unchecked_isa_dma flag in the host structure */
267#define SR_GFP_DMA(cd) (((cd)->device->host->unchecked_isa_dma) ? GFP_DMA : 0)
268
269int sr_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn) 366int sr_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
270{ 367{
271 Scsi_CD *cd = cdi->handle; 368 Scsi_CD *cd = cdi->handle;
@@ -329,93 +426,16 @@ int sr_select_speed(struct cdrom_device_info *cdi, int speed)
329 426
330int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg) 427int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg)
331{ 428{
332 Scsi_CD *cd = cdi->handle;
333 struct packet_command cgc;
334 int result;
335 unsigned char *buffer = kmalloc(32, GFP_KERNEL | SR_GFP_DMA(cd));
336
337 if (!buffer)
338 return -ENOMEM;
339
340 memset(&cgc, 0, sizeof(struct packet_command));
341 cgc.timeout = IOCTL_TIMEOUT;
342
343 switch (cmd) { 429 switch (cmd) {
344 case CDROMREADTOCHDR: 430 case CDROMREADTOCHDR:
345 { 431 return sr_read_tochdr(cdi, arg);
346 struct cdrom_tochdr *tochdr = (struct cdrom_tochdr *) arg;
347
348 cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
349 cgc.cmd[8] = 12; /* LSB of length */
350 cgc.buffer = buffer;
351 cgc.buflen = 12;
352 cgc.quiet = 1;
353 cgc.data_direction = DMA_FROM_DEVICE;
354
355 result = sr_do_ioctl(cd, &cgc);
356
357 tochdr->cdth_trk0 = buffer[2];
358 tochdr->cdth_trk1 = buffer[3];
359
360 break;
361 }
362
363 case CDROMREADTOCENTRY: 432 case CDROMREADTOCENTRY:
364 { 433 return sr_read_tocentry(cdi, arg);
365 struct cdrom_tocentry *tocentry = (struct cdrom_tocentry *) arg; 434 case CDROMPLAYTRKIND:
366 435 return sr_play_trkind(cdi, arg);
367 cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
368 cgc.cmd[1] |= (tocentry->cdte_format == CDROM_MSF) ? 0x02 : 0;
369 cgc.cmd[6] = tocentry->cdte_track;
370 cgc.cmd[8] = 12; /* LSB of length */
371 cgc.buffer = buffer;
372 cgc.buflen = 12;
373 cgc.data_direction = DMA_FROM_DEVICE;
374
375 result = sr_do_ioctl(cd, &cgc);
376
377 tocentry->cdte_ctrl = buffer[5] & 0xf;
378 tocentry->cdte_adr = buffer[5] >> 4;
379 tocentry->cdte_datamode = (tocentry->cdte_ctrl & 0x04) ? 1 : 0;
380 if (tocentry->cdte_format == CDROM_MSF) {
381 tocentry->cdte_addr.msf.minute = buffer[9];
382 tocentry->cdte_addr.msf.second = buffer[10];
383 tocentry->cdte_addr.msf.frame = buffer[11];
384 } else
385 tocentry->cdte_addr.lba = (((((buffer[8] << 8) + buffer[9]) << 8)
386 + buffer[10]) << 8) + buffer[11];
387
388 break;
389 }
390
391 case CDROMPLAYTRKIND: {
392 struct cdrom_ti* ti = (struct cdrom_ti*)arg;
393
394 cgc.cmd[0] = GPCMD_PLAYAUDIO_TI;
395 cgc.cmd[4] = ti->cdti_trk0;
396 cgc.cmd[5] = ti->cdti_ind0;
397 cgc.cmd[7] = ti->cdti_trk1;
398 cgc.cmd[8] = ti->cdti_ind1;
399 cgc.data_direction = DMA_NONE;
400
401 result = sr_do_ioctl(cd, &cgc);
402 if (result == -EDRIVE_CANT_DO_THIS)
403 result = sr_fake_playtrkind(cdi, ti);
404
405 break;
406 }
407
408 default: 436 default:
409 result = -EINVAL; 437 return -EINVAL;
410 } 438 }
411
412#if 0
413 if (result)
414 printk("DEBUG: sr_audio: result for ioctl %x: %x\n", cmd, result);
415#endif
416
417 kfree(buffer);
418 return result;
419} 439}
420 440
421/* ----------------------------------------------------------------------- 441/* -----------------------------------------------------------------------
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index c4aade8f5345..13b1d3aac265 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -38,6 +38,7 @@ static const char *verstr = "20050830";
38#include <linux/devfs_fs_kernel.h> 38#include <linux/devfs_fs_kernel.h>
39#include <linux/cdev.h> 39#include <linux/cdev.h>
40#include <linux/delay.h> 40#include <linux/delay.h>
41#include <linux/mutex.h>
41 42
42#include <asm/uaccess.h> 43#include <asm/uaccess.h>
43#include <asm/dma.h> 44#include <asm/dma.h>
@@ -193,7 +194,6 @@ static int sgl_unmap_user_pages(struct scatterlist *, const unsigned int, int);
193 194
194static int st_probe(struct device *); 195static int st_probe(struct device *);
195static int st_remove(struct device *); 196static int st_remove(struct device *);
196static int st_init_command(struct scsi_cmnd *);
197 197
198static void do_create_driverfs_files(void); 198static void do_create_driverfs_files(void);
199static void do_remove_driverfs_files(void); 199static void do_remove_driverfs_files(void);
@@ -206,7 +206,6 @@ static struct scsi_driver st_template = {
206 .probe = st_probe, 206 .probe = st_probe,
207 .remove = st_remove, 207 .remove = st_remove,
208 }, 208 },
209 .init_command = st_init_command,
210}; 209};
211 210
212static int st_compression(struct scsi_tape *, int); 211static int st_compression(struct scsi_tape *, int);
@@ -220,7 +219,7 @@ static void scsi_tape_release(struct kref *);
220 219
221#define to_scsi_tape(obj) container_of(obj, struct scsi_tape, kref) 220#define to_scsi_tape(obj) container_of(obj, struct scsi_tape, kref)
222 221
223static DECLARE_MUTEX(st_ref_sem); 222static DEFINE_MUTEX(st_ref_mutex);
224 223
225 224
226#include "osst_detect.h" 225#include "osst_detect.h"
@@ -237,7 +236,7 @@ static struct scsi_tape *scsi_tape_get(int dev)
237{ 236{
238 struct scsi_tape *STp = NULL; 237 struct scsi_tape *STp = NULL;
239 238
240 down(&st_ref_sem); 239 mutex_lock(&st_ref_mutex);
241 write_lock(&st_dev_arr_lock); 240 write_lock(&st_dev_arr_lock);
242 241
243 if (dev < st_dev_max && scsi_tapes != NULL) 242 if (dev < st_dev_max && scsi_tapes != NULL)
@@ -259,7 +258,7 @@ out_put:
259 STp = NULL; 258 STp = NULL;
260out: 259out:
261 write_unlock(&st_dev_arr_lock); 260 write_unlock(&st_dev_arr_lock);
262 up(&st_ref_sem); 261 mutex_unlock(&st_ref_mutex);
263 return STp; 262 return STp;
264} 263}
265 264
@@ -267,10 +266,10 @@ static void scsi_tape_put(struct scsi_tape *STp)
267{ 266{
268 struct scsi_device *sdev = STp->device; 267 struct scsi_device *sdev = STp->device;
269 268
270 down(&st_ref_sem); 269 mutex_lock(&st_ref_mutex);
271 kref_put(&STp->kref, scsi_tape_release); 270 kref_put(&STp->kref, scsi_tape_release);
272 scsi_device_put(sdev); 271 scsi_device_put(sdev);
273 up(&st_ref_sem); 272 mutex_unlock(&st_ref_mutex);
274} 273}
275 274
276struct st_reject_data { 275struct st_reject_data {
@@ -4141,9 +4140,9 @@ static int st_remove(struct device *dev)
4141 } 4140 }
4142 } 4141 }
4143 4142
4144 down(&st_ref_sem); 4143 mutex_lock(&st_ref_mutex);
4145 kref_put(&tpnt->kref, scsi_tape_release); 4144 kref_put(&tpnt->kref, scsi_tape_release);
4146 up(&st_ref_sem); 4145 mutex_unlock(&st_ref_mutex);
4147 return 0; 4146 return 0;
4148 } 4147 }
4149 } 4148 }
@@ -4156,7 +4155,7 @@ static int st_remove(struct device *dev)
4156 * scsi_tape_release - Called to free the Scsi_Tape structure 4155 * scsi_tape_release - Called to free the Scsi_Tape structure
4157 * @kref: pointer to embedded kref 4156 * @kref: pointer to embedded kref
4158 * 4157 *
4159 * st_ref_sem must be held entering this routine. Because it is 4158 * st_ref_mutex must be held entering this routine. Because it is
4160 * called on last put, you should always use the scsi_tape_get() 4159 * called on last put, you should always use the scsi_tape_get()
4161 * scsi_tape_put() helpers which manipulate the semaphore directly 4160 * scsi_tape_put() helpers which manipulate the semaphore directly
4162 * and never do a direct kref_put(). 4161 * and never do a direct kref_put().
@@ -4180,29 +4179,6 @@ static void scsi_tape_release(struct kref *kref)
4180 return; 4179 return;
4181} 4180}
4182 4181
4183static void st_intr(struct scsi_cmnd *SCpnt)
4184{
4185 /*
4186 * The caller should be checking the request's errors
4187 * value.
4188 */
4189 scsi_io_completion(SCpnt, SCpnt->bufflen, 0);
4190}
4191
4192/*
4193 * st_init_command: only called via the scsi_cmd_ioctl (block SG_IO)
4194 * interface for REQ_BLOCK_PC commands.
4195 */
4196static int st_init_command(struct scsi_cmnd *SCpnt)
4197{
4198 if (!(SCpnt->request->flags & REQ_BLOCK_PC))
4199 return 0;
4200
4201 scsi_setup_blk_pc_cmnd(SCpnt);
4202 SCpnt->done = st_intr;
4203 return 1;
4204}
4205
4206static int __init init_st(void) 4182static int __init init_st(void)
4207{ 4183{
4208 validate_options(); 4184 validate_options();
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c
index 4dd5c3f98167..8cbf0fc5a225 100644
--- a/drivers/serial/68328serial.c
+++ b/drivers/serial/68328serial.c
@@ -143,7 +143,6 @@ static int m68328_console_cbaud = DEFAULT_CBAUD;
143 * memory if large numbers of serial ports are open. 143 * memory if large numbers of serial ports are open.
144 */ 144 */
145static unsigned char tmp_buf[SERIAL_XMIT_SIZE]; /* This is cheating */ 145static unsigned char tmp_buf[SERIAL_XMIT_SIZE]; /* This is cheating */
146DECLARE_MUTEX(tmp_buf_sem);
147 146
148static inline int serial_paranoia_check(struct m68k_serial *info, 147static inline int serial_paranoia_check(struct m68k_serial *info,
149 char *name, const char *routine) 148 char *name, const char *routine)
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 843717275d49..e0685a520514 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -190,7 +190,6 @@ config SERIAL_8250_BOCA
190 To compile this driver as a module, choose M here: the module 190 To compile this driver as a module, choose M here: the module
191 will be called 8250_boca. 191 will be called 8250_boca.
192 192
193
194config SERIAL_8250_HUB6 193config SERIAL_8250_HUB6
195 tristate "Support Hub6 cards" 194 tristate "Support Hub6 cards"
196 depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS 195 depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
@@ -917,4 +916,12 @@ config SERIAL_SGI_IOC4
917 and wish to use the serial ports on this card, say Y. 916 and wish to use the serial ports on this card, say Y.
918 Otherwise, say N. 917 Otherwise, say N.
919 918
919config SERIAL_SGI_IOC3
920 tristate "SGI Altix IOC3 serial support"
921 depends on (IA64_GENERIC || IA64_SGI_SN2) && SGI_IOC3
922 select SERIAL_CORE
923 help
924 If you have an SGI Altix with an IOC3 serial card,
925 say Y or M. Otherwise, say N.
926
920endmenu 927endmenu
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 24a583e482bb..eaf8e01db198 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -56,4 +56,5 @@ obj-$(CONFIG_SERIAL_JSM) += jsm/
56obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o 56obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o
57obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o 57obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o
58obj-$(CONFIG_SERIAL_SGI_IOC4) += ioc4_serial.o 58obj-$(CONFIG_SERIAL_SGI_IOC4) += ioc4_serial.o
59obj-$(CONFIG_SERIAL_SGI_IOC3) += ioc3_serial.o
59obj-$(CONFIG_SERIAL_AT91) += at91_serial.o 60obj-$(CONFIG_SERIAL_AT91) += at91_serial.o
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index 5c098be9346b..587cc6a95114 100644
--- a/drivers/serial/imx.c
+++ b/drivers/serial/imx.c
@@ -499,7 +499,7 @@ imx_set_termios(struct uart_port *port, struct termios *termios,
499 ucr2 |= UCR2_STPB; 499 ucr2 |= UCR2_STPB;
500 if (termios->c_cflag & PARENB) { 500 if (termios->c_cflag & PARENB) {
501 ucr2 |= UCR2_PREN; 501 ucr2 |= UCR2_PREN;
502 if (!(termios->c_cflag & PARODD)) 502 if (termios->c_cflag & PARODD)
503 ucr2 |= UCR2_PROE; 503 ucr2 |= UCR2_PROE;
504 } 504 }
505 505
diff --git a/drivers/serial/ioc3_serial.c b/drivers/serial/ioc3_serial.c
new file mode 100644
index 000000000000..8097cd91f16b
--- /dev/null
+++ b/drivers/serial/ioc3_serial.c
@@ -0,0 +1,2197 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2005 Silicon Graphics, Inc. All Rights Reserved.
7 */
8
9/*
10 * This file contains a module version of the ioc3 serial driver. This
11 * includes all the support functions needed (support functions, etc.)
12 * and the serial driver itself.
13 */
14#include <linux/errno.h>
15#include <linux/tty.h>
16#include <linux/serial.h>
17#include <linux/circ_buf.h>
18#include <linux/serial_reg.h>
19#include <linux/module.h>
20#include <linux/pci.h>
21#include <linux/serial_core.h>
22#include <linux/ioc3.h>
23
24/*
25 * Interesting things about the ioc3
26 */
27
28#define LOGICAL_PORTS 2 /* rs232(0) and rs422(1) */
29#define PORTS_PER_CARD 2
30#define LOGICAL_PORTS_PER_CARD (PORTS_PER_CARD * LOGICAL_PORTS)
31#define MAX_CARDS 8
32#define MAX_LOGICAL_PORTS (LOGICAL_PORTS_PER_CARD * MAX_CARDS)
33
34/* determine given the sio_ir what port it applies to */
35#define GET_PORT_FROM_SIO_IR(_x) (_x & SIO_IR_SA) ? 0 : 1
36
37
38/*
39 * we have 2 logical ports (rs232, rs422) for each physical port
40 * evens are rs232, odds are rs422
41 */
42#define GET_PHYSICAL_PORT(_x) ((_x) >> 1)
43#define GET_LOGICAL_PORT(_x) ((_x) & 1)
44#define IS_PHYSICAL_PORT(_x) !((_x) & 1)
45#define IS_RS232(_x) !((_x) & 1)
46
47static unsigned int Num_of_ioc3_cards;
48static unsigned int Submodule_slot;
49
50/* defining this will get you LOTS of great debug info */
51//#define DEBUG_INTERRUPTS
52#define DPRINT_CONFIG(_x...) ;
53//#define DPRINT_CONFIG(_x...) printk _x
54#define NOT_PROGRESS() ;
55//#define NOT_PROGRESS() printk("%s : fails %d\n", __FUNCTION__, __LINE__)
56
57/* number of characters we want to transmit to the lower level at a time */
58#define MAX_CHARS 256
59#define FIFO_SIZE (MAX_CHARS-1) /* it's a uchar */
60
61/* Device name we're using */
62#define DEVICE_NAME "ttySIOC"
63#define DEVICE_MAJOR 204
64#define DEVICE_MINOR 116
65
66/* flags for next_char_state */
67#define NCS_BREAK 0x1
68#define NCS_PARITY 0x2
69#define NCS_FRAMING 0x4
70#define NCS_OVERRUN 0x8
71
72/* cause we need SOME parameters ... */
73#define MIN_BAUD_SUPPORTED 1200
74#define MAX_BAUD_SUPPORTED 115200
75
76/* protocol types supported */
77#define PROTO_RS232 0
78#define PROTO_RS422 1
79
80/* Notification types */
81#define N_DATA_READY 0x01
82#define N_OUTPUT_LOWAT 0x02
83#define N_BREAK 0x04
84#define N_PARITY_ERROR 0x08
85#define N_FRAMING_ERROR 0x10
86#define N_OVERRUN_ERROR 0x20
87#define N_DDCD 0x40
88#define N_DCTS 0x80
89
90#define N_ALL_INPUT (N_DATA_READY | N_BREAK \
91 | N_PARITY_ERROR | N_FRAMING_ERROR \
92 | N_OVERRUN_ERROR | N_DDCD | N_DCTS)
93
94#define N_ALL_OUTPUT N_OUTPUT_LOWAT
95
96#define N_ALL_ERRORS (N_PARITY_ERROR | N_FRAMING_ERROR \
97 | N_OVERRUN_ERROR)
98
99#define N_ALL (N_DATA_READY | N_OUTPUT_LOWAT | N_BREAK \
100 | N_PARITY_ERROR | N_FRAMING_ERROR \
101 | N_OVERRUN_ERROR | N_DDCD | N_DCTS)
102
103#define SER_CLK_SPEED(prediv) ((22000000 << 1) / prediv)
104#define SER_DIVISOR(x, clk) (((clk) + (x) * 8) / ((x) * 16))
105#define DIVISOR_TO_BAUD(div, clk) ((clk) / 16 / (div))
106
107/* Some masks */
108#define LCR_MASK_BITS_CHAR (UART_LCR_WLEN5 | UART_LCR_WLEN6 \
109 | UART_LCR_WLEN7 | UART_LCR_WLEN8)
110#define LCR_MASK_STOP_BITS (UART_LCR_STOP)
111
112#define PENDING(_a, _p) (readl(&(_p)->vma->sio_ir) & (_a)->ic_enable)
113
114#define RING_BUF_SIZE 4096
115#define BUF_SIZE_BIT SBBR_L_SIZE
116#define PROD_CONS_MASK PROD_CONS_PTR_4K
117
118#define TOTAL_RING_BUF_SIZE (RING_BUF_SIZE * 4)
119
120/* driver specific - one per card */
121struct ioc3_card {
122 struct {
123 /* uart ports are allocated here */
124 struct uart_port icp_uart_port[LOGICAL_PORTS];
125 /* the ioc3_port used for this port */
126 struct ioc3_port *icp_port;
127 } ic_port[PORTS_PER_CARD];
128 /* currently enabled interrupts */
129 uint32_t ic_enable;
130};
131
132/* Local port info for each IOC3 serial port */
133struct ioc3_port {
134 /* handy reference material */
135 struct uart_port *ip_port;
136 struct ioc3_card *ip_card;
137 struct ioc3_driver_data *ip_idd;
138 struct ioc3_submodule *ip_is;
139
140 /* pci mem addresses for this port */
141 struct ioc3_serialregs __iomem *ip_serial_regs;
142 struct ioc3_uartregs __iomem *ip_uart_regs;
143
144 /* Ring buffer page for this port */
145 dma_addr_t ip_dma_ringbuf;
146 /* vaddr of ring buffer */
147 struct ring_buffer *ip_cpu_ringbuf;
148
149 /* Rings for this port */
150 struct ring *ip_inring;
151 struct ring *ip_outring;
152
153 /* Hook to port specific values */
154 struct port_hooks *ip_hooks;
155
156 spinlock_t ip_lock;
157
158 /* Various rx/tx parameters */
159 int ip_baud;
160 int ip_tx_lowat;
161 int ip_rx_timeout;
162
163 /* Copy of notification bits */
164 int ip_notify;
165
166 /* Shadow copies of various registers so we don't need to PIO
167 * read them constantly
168 */
169 uint32_t ip_sscr;
170 uint32_t ip_tx_prod;
171 uint32_t ip_rx_cons;
172 unsigned char ip_flags;
173};
174
175/* tx low water mark. We need to notify the driver whenever tx is getting
176 * close to empty so it can refill the tx buffer and keep things going.
177 * Let's assume that if we interrupt 1 ms before the tx goes idle, we'll
178 * have no trouble getting in more chars in time (I certainly hope so).
179 */
180#define TX_LOWAT_LATENCY 1000
181#define TX_LOWAT_HZ (1000000 / TX_LOWAT_LATENCY)
182#define TX_LOWAT_CHARS(baud) (baud / 10 / TX_LOWAT_HZ)
183
184/* Flags per port */
185#define INPUT_HIGH 0x01
186 /* used to signify that we have turned off the rx_high
187 * temporarily - we need to drain the fifo and don't
188 * want to get blasted with interrupts.
189 */
190#define DCD_ON 0x02
191 /* DCD state is on */
192#define LOWAT_WRITTEN 0x04
193#define READ_ABORTED 0x08
194 /* the read was aborted - used to avaoid infinate looping
195 * in the interrupt handler
196 */
197#define INPUT_ENABLE 0x10
198
199/* Since each port has different register offsets and bitmasks
200 * for everything, we'll store those that we need in tables so we
201 * don't have to be constantly checking the port we are dealing with.
202 */
203struct port_hooks {
204 uint32_t intr_delta_dcd;
205 uint32_t intr_delta_cts;
206 uint32_t intr_tx_mt;
207 uint32_t intr_rx_timer;
208 uint32_t intr_rx_high;
209 uint32_t intr_tx_explicit;
210 uint32_t intr_clear;
211 uint32_t intr_all;
212 char rs422_select_pin;
213};
214
215static struct port_hooks hooks_array[PORTS_PER_CARD] = {
216 /* values for port A */
217 {
218 .intr_delta_dcd = SIO_IR_SA_DELTA_DCD,
219 .intr_delta_cts = SIO_IR_SA_DELTA_CTS,
220 .intr_tx_mt = SIO_IR_SA_TX_MT,
221 .intr_rx_timer = SIO_IR_SA_RX_TIMER,
222 .intr_rx_high = SIO_IR_SA_RX_HIGH,
223 .intr_tx_explicit = SIO_IR_SA_TX_EXPLICIT,
224 .intr_clear = (SIO_IR_SA_TX_MT | SIO_IR_SA_RX_FULL
225 | SIO_IR_SA_RX_HIGH
226 | SIO_IR_SA_RX_TIMER
227 | SIO_IR_SA_DELTA_DCD
228 | SIO_IR_SA_DELTA_CTS
229 | SIO_IR_SA_INT
230 | SIO_IR_SA_TX_EXPLICIT
231 | SIO_IR_SA_MEMERR),
232 .intr_all = SIO_IR_SA,
233 .rs422_select_pin = GPPR_UARTA_MODESEL_PIN,
234 },
235
236 /* values for port B */
237 {
238 .intr_delta_dcd = SIO_IR_SB_DELTA_DCD,
239 .intr_delta_cts = SIO_IR_SB_DELTA_CTS,
240 .intr_tx_mt = SIO_IR_SB_TX_MT,
241 .intr_rx_timer = SIO_IR_SB_RX_TIMER,
242 .intr_rx_high = SIO_IR_SB_RX_HIGH,
243 .intr_tx_explicit = SIO_IR_SB_TX_EXPLICIT,
244 .intr_clear = (SIO_IR_SB_TX_MT | SIO_IR_SB_RX_FULL
245 | SIO_IR_SB_RX_HIGH
246 | SIO_IR_SB_RX_TIMER
247 | SIO_IR_SB_DELTA_DCD
248 | SIO_IR_SB_DELTA_CTS
249 | SIO_IR_SB_INT
250 | SIO_IR_SB_TX_EXPLICIT
251 | SIO_IR_SB_MEMERR),
252 .intr_all = SIO_IR_SB,
253 .rs422_select_pin = GPPR_UARTB_MODESEL_PIN,
254 }
255};
256
257struct ring_entry {
258 union {
259 struct {
260 uint32_t alldata;
261 uint32_t allsc;
262 } all;
263 struct {
264 char data[4]; /* data bytes */
265 char sc[4]; /* status/control */
266 } s;
267 } u;
268};
269
270/* Test the valid bits in any of the 4 sc chars using "allsc" member */
271#define RING_ANY_VALID \
272 ((uint32_t)(RXSB_MODEM_VALID | RXSB_DATA_VALID) * 0x01010101)
273
274#define ring_sc u.s.sc
275#define ring_data u.s.data
276#define ring_allsc u.all.allsc
277
278/* Number of entries per ring buffer. */
279#define ENTRIES_PER_RING (RING_BUF_SIZE / (int) sizeof(struct ring_entry))
280
281/* An individual ring */
282struct ring {
283 struct ring_entry entries[ENTRIES_PER_RING];
284};
285
286/* The whole enchilada */
287struct ring_buffer {
288 struct ring TX_A;
289 struct ring RX_A;
290 struct ring TX_B;
291 struct ring RX_B;
292};
293
294/* Get a ring from a port struct */
295#define RING(_p, _wh) &(((struct ring_buffer *)((_p)->ip_cpu_ringbuf))->_wh)
296
297/* for Infinite loop detection */
298#define MAXITER 10000000
299
300
301/**
302 * set_baud - Baud rate setting code
303 * @port: port to set
304 * @baud: baud rate to use
305 */
306static int set_baud(struct ioc3_port *port, int baud)
307{
308 int divisor;
309 int actual_baud;
310 int diff;
311 int lcr, prediv;
312 struct ioc3_uartregs __iomem *uart;
313
314 for (prediv = 6; prediv < 64; prediv++) {
315 divisor = SER_DIVISOR(baud, SER_CLK_SPEED(prediv));
316 if (!divisor)
317 continue; /* invalid divisor */
318 actual_baud = DIVISOR_TO_BAUD(divisor, SER_CLK_SPEED(prediv));
319
320 diff = actual_baud - baud;
321 if (diff < 0)
322 diff = -diff;
323
324 /* if we're within 1% we've found a match */
325 if (diff * 100 <= actual_baud)
326 break;
327 }
328
329 /* if the above loop completed, we didn't match
330 * the baud rate. give up.
331 */
332 if (prediv == 64) {
333 NOT_PROGRESS();
334 return 1;
335 }
336
337 uart = port->ip_uart_regs;
338 lcr = readb(&uart->iu_lcr);
339
340 writeb(lcr | UART_LCR_DLAB, &uart->iu_lcr);
341 writeb((unsigned char)divisor, &uart->iu_dll);
342 writeb((unsigned char)(divisor >> 8), &uart->iu_dlm);
343 writeb((unsigned char)prediv, &uart->iu_scr);
344 writeb((unsigned char)lcr, &uart->iu_lcr);
345
346 return 0;
347}
348
349/**
350 * get_ioc3_port - given a uart port, return the control structure
351 * @the_port: uart port to find
352 */
353static struct ioc3_port *get_ioc3_port(struct uart_port *the_port)
354{
355 struct ioc3_driver_data *idd = dev_get_drvdata(the_port->dev);
356 struct ioc3_card *card_ptr = idd->data[Submodule_slot];
357 int ii, jj;
358
359 if (!card_ptr) {
360 NOT_PROGRESS();
361 return NULL;
362 }
363 for (ii = 0; ii < PORTS_PER_CARD; ii++) {
364 for (jj = 0; jj < LOGICAL_PORTS; jj++) {
365 if (the_port == &card_ptr->ic_port[ii].icp_uart_port[jj])
366 return card_ptr->ic_port[ii].icp_port;
367 }
368 }
369 NOT_PROGRESS();
370 return NULL;
371}
372
373/**
374 * port_init - Initialize the sio and ioc3 hardware for a given port
375 * called per port from attach...
376 * @port: port to initialize
377 */
378static int inline port_init(struct ioc3_port *port)
379{
380 uint32_t sio_cr;
381 struct port_hooks *hooks = port->ip_hooks;
382 struct ioc3_uartregs __iomem *uart;
383 int reset_loop_counter = 0xfffff;
384 struct ioc3_driver_data *idd = port->ip_idd;
385
386 /* Idle the IOC3 serial interface */
387 writel(SSCR_RESET, &port->ip_serial_regs->sscr);
388
389 /* Wait until any pending bus activity for this port has ceased */
390 do {
391 sio_cr = readl(&idd->vma->sio_cr);
392 if (reset_loop_counter-- <= 0) {
393 printk(KERN_WARNING
394 "IOC3 unable to come out of reset"
395 " scr 0x%x\n", sio_cr);
396 return -1;
397 }
398 } while (!(sio_cr & SIO_CR_ARB_DIAG_IDLE) &&
399 (((sio_cr &= SIO_CR_ARB_DIAG) == SIO_CR_ARB_DIAG_TXA)
400 || sio_cr == SIO_CR_ARB_DIAG_TXB
401 || sio_cr == SIO_CR_ARB_DIAG_RXA
402 || sio_cr == SIO_CR_ARB_DIAG_RXB));
403
404 /* Finish reset sequence */
405 writel(0, &port->ip_serial_regs->sscr);
406
407 /* Once RESET is done, reload cached tx_prod and rx_cons values
408 * and set rings to empty by making prod == cons
409 */
410 port->ip_tx_prod = readl(&port->ip_serial_regs->stcir) & PROD_CONS_MASK;
411 writel(port->ip_tx_prod, &port->ip_serial_regs->stpir);
412 port->ip_rx_cons = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK;
413 writel(port->ip_rx_cons | SRCIR_ARM, &port->ip_serial_regs->srcir);
414
415 /* Disable interrupts for this 16550 */
416 uart = port->ip_uart_regs;
417 writeb(0, &uart->iu_lcr);
418 writeb(0, &uart->iu_ier);
419
420 /* Set the default baud */
421 set_baud(port, port->ip_baud);
422
423 /* Set line control to 8 bits no parity */
424 writeb(UART_LCR_WLEN8 | 0, &uart->iu_lcr);
425 /* UART_LCR_STOP == 1 stop */
426
427 /* Enable the FIFOs */
428 writeb(UART_FCR_ENABLE_FIFO, &uart->iu_fcr);
429 /* then reset 16550 FIFOs */
430 writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
431 &uart->iu_fcr);
432
433 /* Clear modem control register */
434 writeb(0, &uart->iu_mcr);
435
436 /* Clear deltas in modem status register */
437 writel(0, &port->ip_serial_regs->shadow);
438
439 /* Only do this once per port pair */
440 if (port->ip_hooks == &hooks_array[0]) {
441 unsigned long ring_pci_addr;
442 uint32_t __iomem *sbbr_l, *sbbr_h;
443
444 sbbr_l = &idd->vma->sbbr_l;
445 sbbr_h = &idd->vma->sbbr_h;
446 ring_pci_addr = (unsigned long __iomem)port->ip_dma_ringbuf;
447 DPRINT_CONFIG(("%s: ring_pci_addr 0x%p\n",
448 __FUNCTION__, (void *)ring_pci_addr));
449
450 writel((unsigned int)((uint64_t) ring_pci_addr >> 32), sbbr_h);
451 writel((unsigned int)ring_pci_addr | BUF_SIZE_BIT, sbbr_l);
452 }
453
454 /* Set the receive timeout value to 10 msec */
455 writel(SRTR_HZ / 100, &port->ip_serial_regs->srtr);
456
457 /* Set rx threshold, enable DMA */
458 /* Set high water mark at 3/4 of full ring */
459 port->ip_sscr = (ENTRIES_PER_RING * 3 / 4);
460
461 /* uart experiences pauses at high baud rate reducing actual
462 * throughput by 10% or so unless we enable high speed polling
463 * XXX when this hardware bug is resolved we should revert to
464 * normal polling speed
465 */
466 port->ip_sscr |= SSCR_HIGH_SPD;
467
468 writel(port->ip_sscr, &port->ip_serial_regs->sscr);
469
470 /* Disable and clear all serial related interrupt bits */
471 port->ip_card->ic_enable &= ~hooks->intr_clear;
472 ioc3_disable(port->ip_is, idd, hooks->intr_clear);
473 ioc3_ack(port->ip_is, idd, hooks->intr_clear);
474 return 0;
475}
476
477/**
478 * enable_intrs - enable interrupts
479 * @port: port to enable
480 * @mask: mask to use
481 */
482static void enable_intrs(struct ioc3_port *port, uint32_t mask)
483{
484 if ((port->ip_card->ic_enable & mask) != mask) {
485 port->ip_card->ic_enable |= mask;
486 ioc3_enable(port->ip_is, port->ip_idd, mask);
487 }
488}
489
490/**
491 * local_open - local open a port
492 * @port: port to open
493 */
494static inline int local_open(struct ioc3_port *port)
495{
496 int spiniter = 0;
497
498 port->ip_flags = INPUT_ENABLE;
499
500 /* Pause the DMA interface if necessary */
501 if (port->ip_sscr & SSCR_DMA_EN) {
502 writel(port->ip_sscr | SSCR_DMA_PAUSE,
503 &port->ip_serial_regs->sscr);
504 while ((readl(&port->ip_serial_regs->sscr)
505 & SSCR_PAUSE_STATE) == 0) {
506 spiniter++;
507 if (spiniter > MAXITER) {
508 NOT_PROGRESS();
509 return -1;
510 }
511 }
512 }
513
514 /* Reset the input fifo. If the uart received chars while the port
515 * was closed and DMA is not enabled, the uart may have a bunch of
516 * chars hanging around in its rx fifo which will not be discarded
517 * by rclr in the upper layer. We must get rid of them here.
518 */
519 writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR,
520 &port->ip_uart_regs->iu_fcr);
521
522 writeb(UART_LCR_WLEN8, &port->ip_uart_regs->iu_lcr);
523 /* UART_LCR_STOP == 1 stop */
524
525 /* Re-enable DMA, set default threshold to intr whenever there is
526 * data available.
527 */
528 port->ip_sscr &= ~SSCR_RX_THRESHOLD;
529 port->ip_sscr |= 1; /* default threshold */
530
531 /* Plug in the new sscr. This implicitly clears the DMA_PAUSE
532 * flag if it was set above
533 */
534 writel(port->ip_sscr, &port->ip_serial_regs->sscr);
535 port->ip_tx_lowat = 1;
536 return 0;
537}
538
539/**
540 * set_rx_timeout - Set rx timeout and threshold values.
541 * @port: port to use
542 * @timeout: timeout value in ticks
543 */
544static inline int set_rx_timeout(struct ioc3_port *port, int timeout)
545{
546 int threshold;
547
548 port->ip_rx_timeout = timeout;
549
550 /* Timeout is in ticks. Let's figure out how many chars we
551 * can receive at the current baud rate in that interval
552 * and set the rx threshold to that amount. There are 4 chars
553 * per ring entry, so we'll divide the number of chars that will
554 * arrive in timeout by 4.
555 * So .... timeout * baud / 10 / HZ / 4, with HZ = 100.
556 */
557 threshold = timeout * port->ip_baud / 4000;
558 if (threshold == 0)
559 threshold = 1; /* otherwise we'll intr all the time! */
560
561 if ((unsigned)threshold > (unsigned)SSCR_RX_THRESHOLD)
562 return 1;
563
564 port->ip_sscr &= ~SSCR_RX_THRESHOLD;
565 port->ip_sscr |= threshold;
566 writel(port->ip_sscr, &port->ip_serial_regs->sscr);
567
568 /* Now set the rx timeout to the given value
569 * again timeout * SRTR_HZ / HZ
570 */
571 timeout = timeout * SRTR_HZ / 100;
572 if (timeout > SRTR_CNT)
573 timeout = SRTR_CNT;
574 writel(timeout, &port->ip_serial_regs->srtr);
575 return 0;
576}
577
578/**
579 * config_port - config the hardware
580 * @port: port to config
581 * @baud: baud rate for the port
582 * @byte_size: data size
583 * @stop_bits: number of stop bits
584 * @parenb: parity enable ?
585 * @parodd: odd parity ?
586 */
587static inline int
588config_port(struct ioc3_port *port,
589 int baud, int byte_size, int stop_bits, int parenb, int parodd)
590{
591 char lcr, sizebits;
592 int spiniter = 0;
593
594 DPRINT_CONFIG(("%s: line %d baud %d byte_size %d stop %d parenb %d "
595 "parodd %d\n",
596 __FUNCTION__, ((struct uart_port *)port->ip_port)->line,
597 baud, byte_size, stop_bits, parenb, parodd));
598
599 if (set_baud(port, baud))
600 return 1;
601
602 switch (byte_size) {
603 case 5:
604 sizebits = UART_LCR_WLEN5;
605 break;
606 case 6:
607 sizebits = UART_LCR_WLEN6;
608 break;
609 case 7:
610 sizebits = UART_LCR_WLEN7;
611 break;
612 case 8:
613 sizebits = UART_LCR_WLEN8;
614 break;
615 default:
616 return 1;
617 }
618
619 /* Pause the DMA interface if necessary */
620 if (port->ip_sscr & SSCR_DMA_EN) {
621 writel(port->ip_sscr | SSCR_DMA_PAUSE,
622 &port->ip_serial_regs->sscr);
623 while ((readl(&port->ip_serial_regs->sscr)
624 & SSCR_PAUSE_STATE) == 0) {
625 spiniter++;
626 if (spiniter > MAXITER)
627 return -1;
628 }
629 }
630
631 /* Clear relevant fields in lcr */
632 lcr = readb(&port->ip_uart_regs->iu_lcr);
633 lcr &= ~(LCR_MASK_BITS_CHAR | UART_LCR_EPAR |
634 UART_LCR_PARITY | LCR_MASK_STOP_BITS);
635
636 /* Set byte size in lcr */
637 lcr |= sizebits;
638
639 /* Set parity */
640 if (parenb) {
641 lcr |= UART_LCR_PARITY;
642 if (!parodd)
643 lcr |= UART_LCR_EPAR;
644 }
645
646 /* Set stop bits */
647 if (stop_bits)
648 lcr |= UART_LCR_STOP /* 2 stop bits */ ;
649
650 writeb(lcr, &port->ip_uart_regs->iu_lcr);
651
652 /* Re-enable the DMA interface if necessary */
653 if (port->ip_sscr & SSCR_DMA_EN) {
654 writel(port->ip_sscr, &port->ip_serial_regs->sscr);
655 }
656 port->ip_baud = baud;
657
658 /* When we get within this number of ring entries of filling the
659 * entire ring on tx, place an EXPLICIT intr to generate a lowat
660 * notification when output has drained.
661 */
662 port->ip_tx_lowat = (TX_LOWAT_CHARS(baud) + 3) / 4;
663 if (port->ip_tx_lowat == 0)
664 port->ip_tx_lowat = 1;
665
666 set_rx_timeout(port, 2);
667 return 0;
668}
669
670/**
671 * do_write - Write bytes to the port. Returns the number of bytes
672 * actually written. Called from transmit_chars
673 * @port: port to use
674 * @buf: the stuff to write
675 * @len: how many bytes in 'buf'
676 */
677static inline int do_write(struct ioc3_port *port, char *buf, int len)
678{
679 int prod_ptr, cons_ptr, total = 0;
680 struct ring *outring;
681 struct ring_entry *entry;
682 struct port_hooks *hooks = port->ip_hooks;
683
684 BUG_ON(!(len >= 0));
685
686 prod_ptr = port->ip_tx_prod;
687 cons_ptr = readl(&port->ip_serial_regs->stcir) & PROD_CONS_MASK;
688 outring = port->ip_outring;
689
690 /* Maintain a 1-entry red-zone. The ring buffer is full when
691 * (cons - prod) % ring_size is 1. Rather than do this subtraction
692 * in the body of the loop, I'll do it now.
693 */
694 cons_ptr = (cons_ptr - (int)sizeof(struct ring_entry)) & PROD_CONS_MASK;
695
696 /* Stuff the bytes into the output */
697 while ((prod_ptr != cons_ptr) && (len > 0)) {
698 int xx;
699
700 /* Get 4 bytes (one ring entry) at a time */
701 entry = (struct ring_entry *)((caddr_t) outring + prod_ptr);
702
703 /* Invalidate all entries */
704 entry->ring_allsc = 0;
705
706 /* Copy in some bytes */
707 for (xx = 0; (xx < 4) && (len > 0); xx++) {
708 entry->ring_data[xx] = *buf++;
709 entry->ring_sc[xx] = TXCB_VALID;
710 len--;
711 total++;
712 }
713
714 /* If we are within some small threshold of filling up the
715 * entire ring buffer, we must place an EXPLICIT intr here
716 * to generate a lowat interrupt in case we subsequently
717 * really do fill up the ring and the caller goes to sleep.
718 * No need to place more than one though.
719 */
720 if (!(port->ip_flags & LOWAT_WRITTEN) &&
721 ((cons_ptr - prod_ptr) & PROD_CONS_MASK)
722 <= port->ip_tx_lowat * (int)sizeof(struct ring_entry)) {
723 port->ip_flags |= LOWAT_WRITTEN;
724 entry->ring_sc[0] |= TXCB_INT_WHEN_DONE;
725 }
726
727 /* Go on to next entry */
728 prod_ptr += sizeof(struct ring_entry);
729 prod_ptr &= PROD_CONS_MASK;
730 }
731
732 /* If we sent something, start DMA if necessary */
733 if (total > 0 && !(port->ip_sscr & SSCR_DMA_EN)) {
734 port->ip_sscr |= SSCR_DMA_EN;
735 writel(port->ip_sscr, &port->ip_serial_regs->sscr);
736 }
737
738 /* Store the new producer pointer. If tx is disabled, we stuff the
739 * data into the ring buffer, but we don't actually start tx.
740 */
741 if (!uart_tx_stopped(port->ip_port)) {
742 writel(prod_ptr, &port->ip_serial_regs->stpir);
743
744 /* If we are now transmitting, enable tx_mt interrupt so we
745 * can disable DMA if necessary when the tx finishes.
746 */
747 if (total > 0)
748 enable_intrs(port, hooks->intr_tx_mt);
749 }
750 port->ip_tx_prod = prod_ptr;
751
752 return total;
753}
754
755/**
756 * disable_intrs - disable interrupts
757 * @port: port to enable
758 * @mask: mask to use
759 */
760static inline void disable_intrs(struct ioc3_port *port, uint32_t mask)
761{
762 if (port->ip_card->ic_enable & mask) {
763 ioc3_disable(port->ip_is, port->ip_idd, mask);
764 port->ip_card->ic_enable &= ~mask;
765 }
766}
767
768/**
769 * set_notification - Modify event notification
770 * @port: port to use
771 * @mask: events mask
772 * @set_on: set ?
773 */
774static int set_notification(struct ioc3_port *port, int mask, int set_on)
775{
776 struct port_hooks *hooks = port->ip_hooks;
777 uint32_t intrbits, sscrbits;
778
779 BUG_ON(!mask);
780
781 intrbits = sscrbits = 0;
782
783 if (mask & N_DATA_READY)
784 intrbits |= (hooks->intr_rx_timer | hooks->intr_rx_high);
785 if (mask & N_OUTPUT_LOWAT)
786 intrbits |= hooks->intr_tx_explicit;
787 if (mask & N_DDCD) {
788 intrbits |= hooks->intr_delta_dcd;
789 sscrbits |= SSCR_RX_RING_DCD;
790 }
791 if (mask & N_DCTS)
792 intrbits |= hooks->intr_delta_cts;
793
794 if (set_on) {
795 enable_intrs(port, intrbits);
796 port->ip_notify |= mask;
797 port->ip_sscr |= sscrbits;
798 } else {
799 disable_intrs(port, intrbits);
800 port->ip_notify &= ~mask;
801 port->ip_sscr &= ~sscrbits;
802 }
803
804 /* We require DMA if either DATA_READY or DDCD notification is
805 * currently requested. If neither of these is requested and
806 * there is currently no tx in progress, DMA may be disabled.
807 */
808 if (port->ip_notify & (N_DATA_READY | N_DDCD))
809 port->ip_sscr |= SSCR_DMA_EN;
810 else if (!(port->ip_card->ic_enable & hooks->intr_tx_mt))
811 port->ip_sscr &= ~SSCR_DMA_EN;
812
813 writel(port->ip_sscr, &port->ip_serial_regs->sscr);
814 return 0;
815}
816
817/**
818 * set_mcr - set the master control reg
819 * @the_port: port to use
820 * @mask1: mcr mask
821 * @mask2: shadow mask
822 */
823static inline int set_mcr(struct uart_port *the_port,
824 int mask1, int mask2)
825{
826 struct ioc3_port *port = get_ioc3_port(the_port);
827 uint32_t shadow;
828 int spiniter = 0;
829 char mcr;
830
831 if (!port)
832 return -1;
833
834 /* Pause the DMA interface if necessary */
835 if (port->ip_sscr & SSCR_DMA_EN) {
836 writel(port->ip_sscr | SSCR_DMA_PAUSE,
837 &port->ip_serial_regs->sscr);
838 while ((readl(&port->ip_serial_regs->sscr)
839 & SSCR_PAUSE_STATE) == 0) {
840 spiniter++;
841 if (spiniter > MAXITER)
842 return -1;
843 }
844 }
845 shadow = readl(&port->ip_serial_regs->shadow);
846 mcr = (shadow & 0xff000000) >> 24;
847
848 /* Set new value */
849 mcr |= mask1;
850 shadow |= mask2;
851 writeb(mcr, &port->ip_uart_regs->iu_mcr);
852 writel(shadow, &port->ip_serial_regs->shadow);
853
854 /* Re-enable the DMA interface if necessary */
855 if (port->ip_sscr & SSCR_DMA_EN) {
856 writel(port->ip_sscr, &port->ip_serial_regs->sscr);
857 }
858 return 0;
859}
860
861/**
862 * ioc3_set_proto - set the protocol for the port
863 * @port: port to use
864 * @proto: protocol to use
865 */
866static int ioc3_set_proto(struct ioc3_port *port, int proto)
867{
868 struct port_hooks *hooks = port->ip_hooks;
869
870 switch (proto) {
871 default:
872 case PROTO_RS232:
873 /* Clear the appropriate GIO pin */
874 DPRINT_CONFIG(("%s: rs232\n", __FUNCTION__));
875 writel(0, (&port->ip_idd->vma->gppr[0]
876 + hooks->rs422_select_pin));
877 break;
878
879 case PROTO_RS422:
880 /* Set the appropriate GIO pin */
881 DPRINT_CONFIG(("%s: rs422\n", __FUNCTION__));
882 writel(1, (&port->ip_idd->vma->gppr[0]
883 + hooks->rs422_select_pin));
884 break;
885 }
886 return 0;
887}
888
889/**
890 * transmit_chars - upper level write, called with the_port->lock
891 * @the_port: port to write
892 */
893static void transmit_chars(struct uart_port *the_port)
894{
895 int xmit_count, tail, head;
896 int result;
897 char *start;
898 struct tty_struct *tty;
899 struct ioc3_port *port = get_ioc3_port(the_port);
900 struct uart_info *info;
901
902 if (!the_port)
903 return;
904 if (!port)
905 return;
906
907 info = the_port->info;
908 tty = info->tty;
909
910 if (uart_circ_empty(&info->xmit) || uart_tx_stopped(the_port)) {
911 /* Nothing to do or hw stopped */
912 set_notification(port, N_ALL_OUTPUT, 0);
913 return;
914 }
915
916 head = info->xmit.head;
917 tail = info->xmit.tail;
918 start = (char *)&info->xmit.buf[tail];
919
920 /* write out all the data or until the end of the buffer */
921 xmit_count = (head < tail) ? (UART_XMIT_SIZE - tail) : (head - tail);
922 if (xmit_count > 0) {
923 result = do_write(port, start, xmit_count);
924 if (result > 0) {
925 /* booking */
926 xmit_count -= result;
927 the_port->icount.tx += result;
928 /* advance the pointers */
929 tail += result;
930 tail &= UART_XMIT_SIZE - 1;
931 info->xmit.tail = tail;
932 start = (char *)&info->xmit.buf[tail];
933 }
934 }
935 if (uart_circ_chars_pending(&info->xmit) < WAKEUP_CHARS)
936 uart_write_wakeup(the_port);
937
938 if (uart_circ_empty(&info->xmit)) {
939 set_notification(port, N_OUTPUT_LOWAT, 0);
940 } else {
941 set_notification(port, N_OUTPUT_LOWAT, 1);
942 }
943}
944
945/**
946 * ioc3_change_speed - change the speed of the port
947 * @the_port: port to change
948 * @new_termios: new termios settings
949 * @old_termios: old termios settings
950 */
951static void
952ioc3_change_speed(struct uart_port *the_port,
953 struct termios *new_termios, struct termios *old_termios)
954{
955 struct ioc3_port *port = get_ioc3_port(the_port);
956 unsigned int cflag;
957 int baud;
958 int new_parity = 0, new_parity_enable = 0, new_stop = 0, new_data = 8;
959 struct uart_info *info = the_port->info;
960
961 cflag = new_termios->c_cflag;
962
963 switch (cflag & CSIZE) {
964 case CS5:
965 new_data = 5;
966 break;
967 case CS6:
968 new_data = 6;
969 break;
970 case CS7:
971 new_data = 7;
972 break;
973 case CS8:
974 new_data = 8;
975 break;
976 default:
977 /* cuz we always need a default ... */
978 new_data = 5;
979 break;
980 }
981 if (cflag & CSTOPB) {
982 new_stop = 1;
983 }
984 if (cflag & PARENB) {
985 new_parity_enable = 1;
986 if (cflag & PARODD)
987 new_parity = 1;
988 }
989 baud = uart_get_baud_rate(the_port, new_termios, old_termios,
990 MIN_BAUD_SUPPORTED, MAX_BAUD_SUPPORTED);
991 DPRINT_CONFIG(("%s: returned baud %d for line %d\n", __FUNCTION__, baud,
992 the_port->line));
993
994 if (!the_port->fifosize)
995 the_port->fifosize = FIFO_SIZE;
996 uart_update_timeout(the_port, cflag, baud);
997
998 the_port->ignore_status_mask = N_ALL_INPUT;
999
1000 info->tty->low_latency = 1;
1001
1002 if (I_IGNPAR(info->tty))
1003 the_port->ignore_status_mask &= ~(N_PARITY_ERROR
1004 | N_FRAMING_ERROR);
1005 if (I_IGNBRK(info->tty)) {
1006 the_port->ignore_status_mask &= ~N_BREAK;
1007 if (I_IGNPAR(info->tty))
1008 the_port->ignore_status_mask &= ~N_OVERRUN_ERROR;
1009 }
1010 if (!(cflag & CREAD)) {
1011 /* ignore everything */
1012 the_port->ignore_status_mask &= ~N_DATA_READY;
1013 }
1014
1015 if (cflag & CRTSCTS) {
1016 /* enable hardware flow control */
1017 port->ip_sscr |= SSCR_HFC_EN;
1018 }
1019 else {
1020 /* disable hardware flow control */
1021 port->ip_sscr &= ~SSCR_HFC_EN;
1022 }
1023 writel(port->ip_sscr, &port->ip_serial_regs->sscr);
1024
1025 /* Set the configuration and proper notification call */
1026 DPRINT_CONFIG(("%s : port 0x%p line %d cflag 0%o "
1027 "config_port(baud %d data %d stop %d penable %d "
1028 " parity %d), notification 0x%x\n",
1029 __FUNCTION__, (void *)port, the_port->line, cflag, baud,
1030 new_data, new_stop, new_parity_enable, new_parity,
1031 the_port->ignore_status_mask));
1032
1033 if ((config_port(port, baud, /* baud */
1034 new_data, /* byte size */
1035 new_stop, /* stop bits */
1036 new_parity_enable, /* set parity */
1037 new_parity)) >= 0) { /* parity 1==odd */
1038 set_notification(port, the_port->ignore_status_mask, 1);
1039 }
1040}
1041
1042/**
1043 * ic3_startup_local - Start up the serial port - returns >= 0 if no errors
1044 * @the_port: Port to operate on
1045 */
1046static inline int ic3_startup_local(struct uart_port *the_port)
1047{
1048 struct ioc3_port *port;
1049
1050 if (!the_port) {
1051 NOT_PROGRESS();
1052 return -1;
1053 }
1054
1055 port = get_ioc3_port(the_port);
1056 if (!port) {
1057 NOT_PROGRESS();
1058 return -1;
1059 }
1060
1061 local_open(port);
1062
1063 /* set the protocol */
1064 ioc3_set_proto(port, IS_RS232(the_port->line) ? PROTO_RS232 :
1065 PROTO_RS422);
1066 return 0;
1067}
1068
1069/*
1070 * ioc3_cb_output_lowat - called when the output low water mark is hit
1071 * @port: port to output
1072 */
1073static void ioc3_cb_output_lowat(struct ioc3_port *port)
1074{
1075 unsigned long pflags;
1076
1077 /* the_port->lock is set on the call here */
1078 if (port->ip_port) {
1079 spin_lock_irqsave(&port->ip_port->lock, pflags);
1080 transmit_chars(port->ip_port);
1081 spin_unlock_irqrestore(&port->ip_port->lock, pflags);
1082 }
1083}
1084
1085/*
1086 * ioc3_cb_post_ncs - called for some basic errors
1087 * @port: port to use
1088 * @ncs: event
1089 */
1090static void ioc3_cb_post_ncs(struct uart_port *the_port, int ncs)
1091{
1092 struct uart_icount *icount;
1093
1094 icount = &the_port->icount;
1095
1096 if (ncs & NCS_BREAK)
1097 icount->brk++;
1098 if (ncs & NCS_FRAMING)
1099 icount->frame++;
1100 if (ncs & NCS_OVERRUN)
1101 icount->overrun++;
1102 if (ncs & NCS_PARITY)
1103 icount->parity++;
1104}
1105
1106/**
1107 * do_read - Read in bytes from the port. Return the number of bytes
1108 * actually read.
1109 * @the_port: port to use
1110 * @buf: place to put the stuff we read
1111 * @len: how big 'buf' is
1112 */
1113
1114static inline int do_read(struct uart_port *the_port, char *buf, int len)
1115{
1116 int prod_ptr, cons_ptr, total;
1117 struct ioc3_port *port = get_ioc3_port(the_port);
1118 struct ring *inring;
1119 struct ring_entry *entry;
1120 struct port_hooks *hooks = port->ip_hooks;
1121 int byte_num;
1122 char *sc;
1123 int loop_counter;
1124
1125 BUG_ON(!(len >= 0));
1126 BUG_ON(!port);
1127
1128 /* There is a nasty timing issue in the IOC3. When the rx_timer
1129 * expires or the rx_high condition arises, we take an interrupt.
1130 * At some point while servicing the interrupt, we read bytes from
1131 * the ring buffer and re-arm the rx_timer. However the rx_timer is
1132 * not started until the first byte is received *after* it is armed,
1133 * and any bytes pending in the rx construction buffers are not drained
1134 * to memory until either there are 4 bytes available or the rx_timer
1135 * expires. This leads to a potential situation where data is left
1136 * in the construction buffers forever - 1 to 3 bytes were received
1137 * after the interrupt was generated but before the rx_timer was
1138 * re-armed. At that point as long as no subsequent bytes are received
1139 * the timer will never be started and the bytes will remain in the
1140 * construction buffer forever. The solution is to execute a DRAIN
1141 * command after rearming the timer. This way any bytes received before
1142 * the DRAIN will be drained to memory, and any bytes received after
1143 * the DRAIN will start the TIMER and be drained when it expires.
1144 * Luckily, this only needs to be done when the DMA buffer is empty
1145 * since there is no requirement that this function return all
1146 * available data as long as it returns some.
1147 */
1148 /* Re-arm the timer */
1149
1150 writel(port->ip_rx_cons | SRCIR_ARM, &port->ip_serial_regs->srcir);
1151
1152 prod_ptr = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK;
1153 cons_ptr = port->ip_rx_cons;
1154
1155 if (prod_ptr == cons_ptr) {
1156 int reset_dma = 0;
1157
1158 /* Input buffer appears empty, do a flush. */
1159
1160 /* DMA must be enabled for this to work. */
1161 if (!(port->ip_sscr & SSCR_DMA_EN)) {
1162 port->ip_sscr |= SSCR_DMA_EN;
1163 reset_dma = 1;
1164 }
1165
1166 /* Potential race condition: we must reload the srpir after
1167 * issuing the drain command, otherwise we could think the rx
1168 * buffer is empty, then take a very long interrupt, and when
1169 * we come back it's full and we wait forever for the drain to
1170 * complete.
1171 */
1172 writel(port->ip_sscr | SSCR_RX_DRAIN,
1173 &port->ip_serial_regs->sscr);
1174 prod_ptr = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK;
1175
1176 /* We must not wait for the DRAIN to complete unless there are
1177 * at least 8 bytes (2 ring entries) available to receive the
1178 * data otherwise the DRAIN will never complete and we'll
1179 * deadlock here.
1180 * In fact, to make things easier, I'll just ignore the flush if
1181 * there is any data at all now available.
1182 */
1183 if (prod_ptr == cons_ptr) {
1184 loop_counter = 0;
1185 while (readl(&port->ip_serial_regs->sscr) &
1186 SSCR_RX_DRAIN) {
1187 loop_counter++;
1188 if (loop_counter > MAXITER)
1189 return -1;
1190 }
1191
1192 /* SIGH. We have to reload the prod_ptr *again* since
1193 * the drain may have caused it to change
1194 */
1195 prod_ptr = readl(&port->ip_serial_regs->srpir)
1196 & PROD_CONS_MASK;
1197 }
1198 if (reset_dma) {
1199 port->ip_sscr &= ~SSCR_DMA_EN;
1200 writel(port->ip_sscr, &port->ip_serial_regs->sscr);
1201 }
1202 }
1203 inring = port->ip_inring;
1204 port->ip_flags &= ~READ_ABORTED;
1205
1206 total = 0;
1207 loop_counter = 0xfffff; /* to avoid hangs */
1208
1209 /* Grab bytes from the hardware */
1210 while ((prod_ptr != cons_ptr) && (len > 0)) {
1211 entry = (struct ring_entry *)((caddr_t) inring + cons_ptr);
1212
1213 if (loop_counter-- <= 0) {
1214 printk(KERN_WARNING "IOC3 serial: "
1215 "possible hang condition/"
1216 "port stuck on read (line %d).\n",
1217 the_port->line);
1218 break;
1219 }
1220
1221 /* According to the producer pointer, this ring entry
1222 * must contain some data. But if the PIO happened faster
1223 * than the DMA, the data may not be available yet, so let's
1224 * wait until it arrives.
1225 */
1226 if ((entry->ring_allsc & RING_ANY_VALID) == 0) {
1227 /* Indicate the read is aborted so we don't disable
1228 * the interrupt thinking that the consumer is
1229 * congested.
1230 */
1231 port->ip_flags |= READ_ABORTED;
1232 len = 0;
1233 break;
1234 }
1235
1236 /* Load the bytes/status out of the ring entry */
1237 for (byte_num = 0; byte_num < 4 && len > 0; byte_num++) {
1238 sc = &(entry->ring_sc[byte_num]);
1239
1240 /* Check for change in modem state or overrun */
1241 if ((*sc & RXSB_MODEM_VALID)
1242 && (port->ip_notify & N_DDCD)) {
1243 /* Notify upper layer if DCD dropped */
1244 if ((port->ip_flags & DCD_ON)
1245 && !(*sc & RXSB_DCD)) {
1246 /* If we have already copied some data,
1247 * return it. We'll pick up the carrier
1248 * drop on the next pass. That way we
1249 * don't throw away the data that has
1250 * already been copied back to
1251 * the caller's buffer.
1252 */
1253 if (total > 0) {
1254 len = 0;
1255 break;
1256 }
1257 port->ip_flags &= ~DCD_ON;
1258
1259 /* Turn off this notification so the
1260 * carrier drop protocol won't see it
1261 * again when it does a read.
1262 */
1263 *sc &= ~RXSB_MODEM_VALID;
1264
1265 /* To keep things consistent, we need
1266 * to update the consumer pointer so
1267 * the next reader won't come in and
1268 * try to read the same ring entries
1269 * again. This must be done here before
1270 * the dcd change.
1271 */
1272
1273 if ((entry->ring_allsc & RING_ANY_VALID)
1274 == 0) {
1275 cons_ptr += (int)sizeof
1276 (struct ring_entry);
1277 cons_ptr &= PROD_CONS_MASK;
1278 }
1279 writel(cons_ptr,
1280 &port->ip_serial_regs->srcir);
1281 port->ip_rx_cons = cons_ptr;
1282
1283 /* Notify upper layer of carrier drop */
1284 if ((port->ip_notify & N_DDCD)
1285 && port->ip_port) {
1286 uart_handle_dcd_change
1287 (port->ip_port, 0);
1288 wake_up_interruptible
1289 (&the_port->info->
1290 delta_msr_wait);
1291 }
1292
1293 /* If we had any data to return, we
1294 * would have returned it above.
1295 */
1296 return 0;
1297 }
1298 }
1299 if (*sc & RXSB_MODEM_VALID) {
1300 /* Notify that an input overrun occurred */
1301 if ((*sc & RXSB_OVERRUN)
1302 && (port->ip_notify & N_OVERRUN_ERROR)) {
1303 ioc3_cb_post_ncs(the_port, NCS_OVERRUN);
1304 }
1305 /* Don't look at this byte again */
1306 *sc &= ~RXSB_MODEM_VALID;
1307 }
1308
1309 /* Check for valid data or RX errors */
1310 if ((*sc & RXSB_DATA_VALID) &&
1311 ((*sc & (RXSB_PAR_ERR
1312 | RXSB_FRAME_ERR | RXSB_BREAK))
1313 && (port->ip_notify & (N_PARITY_ERROR
1314 | N_FRAMING_ERROR
1315 | N_BREAK)))) {
1316 /* There is an error condition on the next byte.
1317 * If we have already transferred some bytes,
1318 * we'll stop here. Otherwise if this is the
1319 * first byte to be read, we'll just transfer
1320 * it alone after notifying the
1321 * upper layer of its status.
1322 */
1323 if (total > 0) {
1324 len = 0;
1325 break;
1326 } else {
1327 if ((*sc & RXSB_PAR_ERR) &&
1328 (port->
1329 ip_notify & N_PARITY_ERROR)) {
1330 ioc3_cb_post_ncs(the_port,
1331 NCS_PARITY);
1332 }
1333 if ((*sc & RXSB_FRAME_ERR) &&
1334 (port->
1335 ip_notify & N_FRAMING_ERROR)) {
1336 ioc3_cb_post_ncs(the_port,
1337 NCS_FRAMING);
1338 }
1339 if ((*sc & RXSB_BREAK)
1340 && (port->ip_notify & N_BREAK)) {
1341 ioc3_cb_post_ncs
1342 (the_port, NCS_BREAK);
1343 }
1344 len = 1;
1345 }
1346 }
1347 if (*sc & RXSB_DATA_VALID) {
1348 *sc &= ~RXSB_DATA_VALID;
1349 *buf = entry->ring_data[byte_num];
1350 buf++;
1351 len--;
1352 total++;
1353 }
1354 }
1355
1356 /* If we used up this entry entirely, go on to the next one,
1357 * otherwise we must have run out of buffer space, so
1358 * leave the consumer pointer here for the next read in case
1359 * there are still unread bytes in this entry.
1360 */
1361 if ((entry->ring_allsc & RING_ANY_VALID) == 0) {
1362 cons_ptr += (int)sizeof(struct ring_entry);
1363 cons_ptr &= PROD_CONS_MASK;
1364 }
1365 }
1366
1367 /* Update consumer pointer and re-arm rx timer interrupt */
1368 writel(cons_ptr, &port->ip_serial_regs->srcir);
1369 port->ip_rx_cons = cons_ptr;
1370
1371 /* If we have now dipped below the rx high water mark and we have
1372 * rx_high interrupt turned off, we can now turn it back on again.
1373 */
1374 if ((port->ip_flags & INPUT_HIGH) && (((prod_ptr - cons_ptr)
1375 & PROD_CONS_MASK) <
1376 ((port->
1377 ip_sscr &
1378 SSCR_RX_THRESHOLD)
1379 << PROD_CONS_PTR_OFF))) {
1380 port->ip_flags &= ~INPUT_HIGH;
1381 enable_intrs(port, hooks->intr_rx_high);
1382 }
1383 return total;
1384}
1385
1386/**
1387 * receive_chars - upper level read.
1388 * @the_port: port to read from
1389 */
1390static int receive_chars(struct uart_port *the_port)
1391{
1392 struct tty_struct *tty;
1393 unsigned char ch[MAX_CHARS];
1394 int read_count = 0, read_room, flip = 0;
1395 struct uart_info *info = the_port->info;
1396 struct ioc3_port *port = get_ioc3_port(the_port);
1397 unsigned long pflags;
1398
1399 /* Make sure all the pointers are "good" ones */
1400 if (!info)
1401 return 0;
1402 if (!info->tty)
1403 return 0;
1404
1405 if (!(port->ip_flags & INPUT_ENABLE))
1406 return 0;
1407
1408 spin_lock_irqsave(&the_port->lock, pflags);
1409 tty = info->tty;
1410
1411 read_count = do_read(the_port, ch, MAX_CHARS);
1412 if (read_count > 0) {
1413 flip = 1;
1414 read_room = tty_buffer_request_room(tty, read_count);
1415 tty_insert_flip_string(tty, ch, read_room);
1416 the_port->icount.rx += read_count;
1417 }
1418 spin_unlock_irqrestore(&the_port->lock, pflags);
1419
1420 if (flip)
1421 tty_flip_buffer_push(tty);
1422
1423 return read_count;
1424}
1425
1426/**
1427 * ioc3uart_intr_one - lowest level (per port) interrupt handler.
1428 * @is : submodule
1429 * @idd: driver data
1430 * @pending: interrupts to handle
1431 * @regs: pt_regs
1432 */
1433
1434static int inline
1435ioc3uart_intr_one(struct ioc3_submodule *is,
1436 struct ioc3_driver_data *idd,
1437 unsigned int pending, struct pt_regs *regs)
1438{
1439 int port_num = GET_PORT_FROM_SIO_IR(pending);
1440 struct port_hooks *hooks;
1441 unsigned int rx_high_rd_aborted = 0;
1442 unsigned long flags;
1443 struct uart_port *the_port;
1444 struct ioc3_port *port;
1445 int loop_counter;
1446 struct ioc3_card *card_ptr;
1447 unsigned int sio_ir;
1448
1449 card_ptr = idd->data[is->id];
1450 port = card_ptr->ic_port[port_num].icp_port;
1451 hooks = port->ip_hooks;
1452
1453 /* Possible race condition here: The tx_mt interrupt bit may be
1454 * cleared without the intervention of the interrupt handler,
1455 * e.g. by a write. If the top level interrupt handler reads a
1456 * tx_mt, then some other processor does a write, starting up
1457 * output, then we come in here, see the tx_mt and stop DMA, the
1458 * output started by the other processor will hang. Thus we can
1459 * only rely on tx_mt being legitimate if it is read while the
1460 * port lock is held. Therefore this bit must be ignored in the
1461 * passed in interrupt mask which was read by the top level
1462 * interrupt handler since the port lock was not held at the time
1463 * it was read. We can only rely on this bit being accurate if it
1464 * is read while the port lock is held. So we'll clear it for now,
1465 * and reload it later once we have the port lock.
1466 */
1467
1468 sio_ir = pending & ~(hooks->intr_tx_mt);
1469 spin_lock_irqsave(&port->ip_lock, flags);
1470
1471 loop_counter = MAXITER; /* to avoid hangs */
1472
1473 do {
1474 uint32_t shadow;
1475
1476 if (loop_counter-- <= 0) {
1477 printk(KERN_WARNING "IOC3 serial: "
1478 "possible hang condition/"
1479 "port stuck on interrupt (line %d).\n",
1480 ((struct uart_port *)port->ip_port)->line);
1481 break;
1482 }
1483 /* Handle a DCD change */
1484 if (sio_ir & hooks->intr_delta_dcd) {
1485 ioc3_ack(is, idd, hooks->intr_delta_dcd);
1486 shadow = readl(&port->ip_serial_regs->shadow);
1487
1488 if ((port->ip_notify & N_DDCD)
1489 && (shadow & SHADOW_DCD)
1490 && (port->ip_port)) {
1491 the_port = port->ip_port;
1492 uart_handle_dcd_change(the_port,
1493 shadow & SHADOW_DCD);
1494 wake_up_interruptible
1495 (&the_port->info->delta_msr_wait);
1496 } else if ((port->ip_notify & N_DDCD)
1497 && !(shadow & SHADOW_DCD)) {
1498 /* Flag delta DCD/no DCD */
1499 uart_handle_dcd_change(port->ip_port,
1500 shadow & SHADOW_DCD);
1501 port->ip_flags |= DCD_ON;
1502 }
1503 }
1504
1505 /* Handle a CTS change */
1506 if (sio_ir & hooks->intr_delta_cts) {
1507 ioc3_ack(is, idd, hooks->intr_delta_cts);
1508 shadow = readl(&port->ip_serial_regs->shadow);
1509
1510 if ((port->ip_notify & N_DCTS) && (port->ip_port)) {
1511 the_port = port->ip_port;
1512 uart_handle_cts_change(the_port, shadow
1513 & SHADOW_CTS);
1514 wake_up_interruptible
1515 (&the_port->info->delta_msr_wait);
1516 }
1517 }
1518
1519 /* rx timeout interrupt. Must be some data available. Put this
1520 * before the check for rx_high since servicing this condition
1521 * may cause that condition to clear.
1522 */
1523 if (sio_ir & hooks->intr_rx_timer) {
1524 ioc3_ack(is, idd, hooks->intr_rx_timer);
1525 if ((port->ip_notify & N_DATA_READY)
1526 && (port->ip_port)) {
1527 receive_chars(port->ip_port);
1528 }
1529 }
1530
1531 /* rx high interrupt. Must be after rx_timer. */
1532 else if (sio_ir & hooks->intr_rx_high) {
1533 /* Data available, notify upper layer */
1534 if ((port->ip_notify & N_DATA_READY) && port->ip_port) {
1535 receive_chars(port->ip_port);
1536 }
1537
1538 /* We can't ACK this interrupt. If receive_chars didn't
1539 * cause the condition to clear, we'll have to disable
1540 * the interrupt until the data is drained.
1541 * If the read was aborted, don't disable the interrupt
1542 * as this may cause us to hang indefinitely. An
1543 * aborted read generally means that this interrupt
1544 * hasn't been delivered to the cpu yet anyway, even
1545 * though we see it as asserted when we read the sio_ir.
1546 */
1547 if ((sio_ir = PENDING(card_ptr, idd))
1548 & hooks->intr_rx_high) {
1549 if (port->ip_flags & READ_ABORTED) {
1550 rx_high_rd_aborted++;
1551 }
1552 else {
1553 card_ptr->ic_enable &= ~hooks->intr_rx_high;
1554 port->ip_flags |= INPUT_HIGH;
1555 }
1556 }
1557 }
1558
1559 /* We got a low water interrupt: notify upper layer to
1560 * send more data. Must come before tx_mt since servicing
1561 * this condition may cause that condition to clear.
1562 */
1563 if (sio_ir & hooks->intr_tx_explicit) {
1564 port->ip_flags &= ~LOWAT_WRITTEN;
1565 ioc3_ack(is, idd, hooks->intr_tx_explicit);
1566 if (port->ip_notify & N_OUTPUT_LOWAT)
1567 ioc3_cb_output_lowat(port);
1568 }
1569
1570 /* Handle tx_mt. Must come after tx_explicit. */
1571 else if (sio_ir & hooks->intr_tx_mt) {
1572 /* If we are expecting a lowat notification
1573 * and we get to this point it probably means that for
1574 * some reason the tx_explicit didn't work as expected
1575 * (that can legitimately happen if the output buffer is
1576 * filled up in just the right way).
1577 * So send the notification now.
1578 */
1579 if (port->ip_notify & N_OUTPUT_LOWAT) {
1580 ioc3_cb_output_lowat(port);
1581
1582 /* We need to reload the sio_ir since the lowat
1583 * call may have caused another write to occur,
1584 * clearing the tx_mt condition.
1585 */
1586 sio_ir = PENDING(card_ptr, idd);
1587 }
1588
1589 /* If the tx_mt condition still persists even after the
1590 * lowat call, we've got some work to do.
1591 */
1592 if (sio_ir & hooks->intr_tx_mt) {
1593 /* If we are not currently expecting DMA input,
1594 * and the transmitter has just gone idle,
1595 * there is no longer any reason for DMA, so
1596 * disable it.
1597 */
1598 if (!(port->ip_notify
1599 & (N_DATA_READY | N_DDCD))) {
1600 BUG_ON(!(port->ip_sscr
1601 & SSCR_DMA_EN));
1602 port->ip_sscr &= ~SSCR_DMA_EN;
1603 writel(port->ip_sscr,
1604 &port->ip_serial_regs->sscr);
1605 }
1606 /* Prevent infinite tx_mt interrupt */
1607 card_ptr->ic_enable &= ~hooks->intr_tx_mt;
1608 }
1609 }
1610 sio_ir = PENDING(card_ptr, idd);
1611
1612 /* if the read was aborted and only hooks->intr_rx_high,
1613 * clear hooks->intr_rx_high, so we do not loop forever.
1614 */
1615
1616 if (rx_high_rd_aborted && (sio_ir == hooks->intr_rx_high)) {
1617 sio_ir &= ~hooks->intr_rx_high;
1618 }
1619 } while (sio_ir & hooks->intr_all);
1620
1621 spin_unlock_irqrestore(&port->ip_lock, flags);
1622 ioc3_enable(is, idd, card_ptr->ic_enable);
1623 return 0;
1624}
1625
1626/**
1627 * ioc3uart_intr - field all serial interrupts
1628 * @is : submodule
1629 * @idd: driver data
1630 * @pending: interrupts to handle
1631 * @regs: pt_regs
1632 *
1633 */
1634
1635static int ioc3uart_intr(struct ioc3_submodule *is,
1636 struct ioc3_driver_data *idd,
1637 unsigned int pending, struct pt_regs *regs)
1638{
1639 int ret = 0;
1640
1641 /*
1642 * The upper level interrupt handler sends interrupts for both ports
1643 * here. So we need to call for each port with its interrupts.
1644 */
1645
1646 if (pending & SIO_IR_SA)
1647 ret |= ioc3uart_intr_one(is, idd, pending & SIO_IR_SA, regs);
1648 if (pending & SIO_IR_SB)
1649 ret |= ioc3uart_intr_one(is, idd, pending & SIO_IR_SB, regs);
1650
1651 return ret;
1652}
1653
1654/**
1655 * ic3_type
1656 * @port: Port to operate with (we ignore since we only have one port)
1657 *
1658 */
1659static const char *ic3_type(struct uart_port *the_port)
1660{
1661 if (IS_RS232(the_port->line))
1662 return "SGI IOC3 Serial [rs232]";
1663 else
1664 return "SGI IOC3 Serial [rs422]";
1665}
1666
1667/**
1668 * ic3_tx_empty - Is the transmitter empty?
1669 * @port: Port to operate on
1670 *
1671 */
1672static unsigned int ic3_tx_empty(struct uart_port *the_port)
1673{
1674 unsigned int ret = 0;
1675 struct ioc3_port *port = get_ioc3_port(the_port);
1676
1677 if (readl(&port->ip_serial_regs->shadow) & SHADOW_TEMT)
1678 ret = TIOCSER_TEMT;
1679 return ret;
1680}
1681
1682/**
1683 * ic3_stop_tx - stop the transmitter
1684 * @port: Port to operate on
1685 *
1686 */
1687static void ic3_stop_tx(struct uart_port *the_port)
1688{
1689 struct ioc3_port *port = get_ioc3_port(the_port);
1690
1691 if (port)
1692 set_notification(port, N_OUTPUT_LOWAT, 0);
1693}
1694
1695/**
1696 * ic3_stop_rx - stop the receiver
1697 * @port: Port to operate on
1698 *
1699 */
1700static void ic3_stop_rx(struct uart_port *the_port)
1701{
1702 struct ioc3_port *port = get_ioc3_port(the_port);
1703
1704 if (port)
1705 port->ip_flags &= ~INPUT_ENABLE;
1706}
1707
1708/**
1709 * null_void_function
1710 * @port: Port to operate on
1711 *
1712 */
1713static void null_void_function(struct uart_port *the_port)
1714{
1715}
1716
1717/**
1718 * ic3_shutdown - shut down the port - free irq and disable
1719 * @port: port to shut down
1720 *
1721 */
1722static void ic3_shutdown(struct uart_port *the_port)
1723{
1724 unsigned long port_flags;
1725 struct ioc3_port *port;
1726 struct uart_info *info;
1727
1728 port = get_ioc3_port(the_port);
1729 if (!port)
1730 return;
1731
1732 info = the_port->info;
1733 wake_up_interruptible(&info->delta_msr_wait);
1734
1735 spin_lock_irqsave(&the_port->lock, port_flags);
1736 set_notification(port, N_ALL, 0);
1737 spin_unlock_irqrestore(&the_port->lock, port_flags);
1738}
1739
1740/**
1741 * ic3_set_mctrl - set control lines (dtr, rts, etc)
1742 * @port: Port to operate on
1743 * @mctrl: Lines to set/unset
1744 *
1745 */
1746static void ic3_set_mctrl(struct uart_port *the_port, unsigned int mctrl)
1747{
1748 unsigned char mcr = 0;
1749
1750 if (mctrl & TIOCM_RTS)
1751 mcr |= UART_MCR_RTS;
1752 if (mctrl & TIOCM_DTR)
1753 mcr |= UART_MCR_DTR;
1754 if (mctrl & TIOCM_OUT1)
1755 mcr |= UART_MCR_OUT1;
1756 if (mctrl & TIOCM_OUT2)
1757 mcr |= UART_MCR_OUT2;
1758 if (mctrl & TIOCM_LOOP)
1759 mcr |= UART_MCR_LOOP;
1760
1761 set_mcr(the_port, mcr, SHADOW_DTR);
1762}
1763
1764/**
1765 * ic3_get_mctrl - get control line info
1766 * @port: port to operate on
1767 *
1768 */
1769static unsigned int ic3_get_mctrl(struct uart_port *the_port)
1770{
1771 struct ioc3_port *port = get_ioc3_port(the_port);
1772 uint32_t shadow;
1773 unsigned int ret = 0;
1774
1775 if (!port)
1776 return 0;
1777
1778 shadow = readl(&port->ip_serial_regs->shadow);
1779 if (shadow & SHADOW_DCD)
1780 ret |= TIOCM_CD;
1781 if (shadow & SHADOW_DR)
1782 ret |= TIOCM_DSR;
1783 if (shadow & SHADOW_CTS)
1784 ret |= TIOCM_CTS;
1785 return ret;
1786}
1787
1788/**
1789 * ic3_start_tx - Start transmitter. Called with the_port->lock
1790 * @port: Port to operate on
1791 *
1792 */
1793static void ic3_start_tx(struct uart_port *the_port)
1794{
1795 struct ioc3_port *port = get_ioc3_port(the_port);
1796
1797 if (port) {
1798 set_notification(port, N_OUTPUT_LOWAT, 1);
1799 enable_intrs(port, port->ip_hooks->intr_tx_mt);
1800 }
1801}
1802
1803/**
1804 * ic3_break_ctl - handle breaks
1805 * @port: Port to operate on
1806 * @break_state: Break state
1807 *
1808 */
1809static void ic3_break_ctl(struct uart_port *the_port, int break_state)
1810{
1811}
1812
1813/**
1814 * ic3_startup - Start up the serial port - always return 0 (We're always on)
1815 * @port: Port to operate on
1816 *
1817 */
1818static int ic3_startup(struct uart_port *the_port)
1819{
1820 int retval;
1821 struct ioc3_port *port;
1822 struct ioc3_card *card_ptr;
1823 unsigned long port_flags;
1824
1825 if (!the_port) {
1826 NOT_PROGRESS();
1827 return -ENODEV;
1828 }
1829 port = get_ioc3_port(the_port);
1830 if (!port) {
1831 NOT_PROGRESS();
1832 return -ENODEV;
1833 }
1834 card_ptr = port->ip_card;
1835 port->ip_port = the_port;
1836
1837 if (!card_ptr) {
1838 NOT_PROGRESS();
1839 return -ENODEV;
1840 }
1841
1842 /* Start up the serial port */
1843 spin_lock_irqsave(&the_port->lock, port_flags);
1844 retval = ic3_startup_local(the_port);
1845 spin_unlock_irqrestore(&the_port->lock, port_flags);
1846 return retval;
1847}
1848
1849/**
1850 * ic3_set_termios - set termios stuff
1851 * @port: port to operate on
1852 * @termios: New settings
1853 * @termios: Old
1854 *
1855 */
1856static void
1857ic3_set_termios(struct uart_port *the_port,
1858 struct termios *termios, struct termios *old_termios)
1859{
1860 unsigned long port_flags;
1861
1862 spin_lock_irqsave(&the_port->lock, port_flags);
1863 ioc3_change_speed(the_port, termios, old_termios);
1864 spin_unlock_irqrestore(&the_port->lock, port_flags);
1865}
1866
1867/**
1868 * ic3_request_port - allocate resources for port - no op....
1869 * @port: port to operate on
1870 *
1871 */
1872static int ic3_request_port(struct uart_port *port)
1873{
1874 return 0;
1875}
1876
1877/* Associate the uart functions above - given to serial core */
1878static struct uart_ops ioc3_ops = {
1879 .tx_empty = ic3_tx_empty,
1880 .set_mctrl = ic3_set_mctrl,
1881 .get_mctrl = ic3_get_mctrl,
1882 .stop_tx = ic3_stop_tx,
1883 .start_tx = ic3_start_tx,
1884 .stop_rx = ic3_stop_rx,
1885 .enable_ms = null_void_function,
1886 .break_ctl = ic3_break_ctl,
1887 .startup = ic3_startup,
1888 .shutdown = ic3_shutdown,
1889 .set_termios = ic3_set_termios,
1890 .type = ic3_type,
1891 .release_port = null_void_function,
1892 .request_port = ic3_request_port,
1893};
1894
1895/*
1896 * Boot-time initialization code
1897 */
1898
1899static struct uart_driver ioc3_uart = {
1900 .owner = THIS_MODULE,
1901 .driver_name = "ioc3_serial",
1902 .dev_name = DEVICE_NAME,
1903 .major = DEVICE_MAJOR,
1904 .minor = DEVICE_MINOR,
1905 .nr = MAX_LOGICAL_PORTS
1906};
1907
1908/**
1909 * ioc3_serial_core_attach - register with serial core
1910 * This is done during pci probing
1911 * @is: submodule struct for this
1912 * @idd: handle for this card
1913 */
1914static inline int ioc3_serial_core_attach( struct ioc3_submodule *is,
1915 struct ioc3_driver_data *idd)
1916{
1917 struct ioc3_port *port;
1918 struct uart_port *the_port;
1919 struct ioc3_card *card_ptr = idd->data[is->id];
1920 int ii, phys_port;
1921 struct pci_dev *pdev = idd->pdev;
1922
1923 DPRINT_CONFIG(("%s: attach pdev 0x%p - card_ptr 0x%p\n",
1924 __FUNCTION__, pdev, (void *)card_ptr));
1925
1926 if (!card_ptr)
1927 return -ENODEV;
1928
1929 /* once around for each logical port on this card */
1930 for (ii = 0; ii < LOGICAL_PORTS_PER_CARD; ii++) {
1931 phys_port = GET_PHYSICAL_PORT(ii);
1932 the_port = &card_ptr->ic_port[phys_port].
1933 icp_uart_port[GET_LOGICAL_PORT(ii)];
1934 port = card_ptr->ic_port[phys_port].icp_port;
1935 port->ip_port = the_port;
1936
1937 DPRINT_CONFIG(("%s: attach the_port 0x%p / port 0x%p [%d/%d]\n",
1938 __FUNCTION__, (void *)the_port, (void *)port,
1939 phys_port, ii));
1940
1941 /* membase, iobase and mapbase just need to be non-0 */
1942 the_port->membase = (unsigned char __iomem *)1;
1943 the_port->iobase = (pdev->bus->number << 16) | ii;
1944 the_port->line = (Num_of_ioc3_cards << 2) | ii;
1945 the_port->mapbase = 1;
1946 the_port->type = PORT_16550A;
1947 the_port->fifosize = FIFO_SIZE;
1948 the_port->ops = &ioc3_ops;
1949 the_port->irq = idd->irq_io;
1950 the_port->dev = &pdev->dev;
1951
1952 if (uart_add_one_port(&ioc3_uart, the_port) < 0) {
1953 printk(KERN_WARNING
1954 "%s: unable to add port %d bus %d\n",
1955 __FUNCTION__, the_port->line, pdev->bus->number);
1956 } else {
1957 DPRINT_CONFIG(("IOC3 serial port %d irq %d bus %d\n",
1958 the_port->line, the_port->irq, pdev->bus->number));
1959 }
1960
1961 /* all ports are rs232 for now */
1962 if (IS_PHYSICAL_PORT(ii))
1963 ioc3_set_proto(port, PROTO_RS232);
1964 }
1965 return 0;
1966}
1967
1968/**
1969 * ioc3uart_remove - register detach function
1970 * @is: submodule struct for this submodule
1971 * @idd: ioc3 driver data for this submodule
1972 */
1973
1974static int ioc3uart_remove(struct ioc3_submodule *is,
1975 struct ioc3_driver_data *idd)
1976{
1977 struct ioc3_card *card_ptr = idd->data[is->id];
1978 struct uart_port *the_port;
1979 struct ioc3_port *port;
1980 int ii;
1981
1982 if (card_ptr) {
1983 for (ii = 0; ii < LOGICAL_PORTS_PER_CARD; ii++) {
1984 the_port = &card_ptr->ic_port[GET_PHYSICAL_PORT(ii)].
1985 icp_uart_port[GET_LOGICAL_PORT(ii)];
1986 if (the_port)
1987 uart_remove_one_port(&ioc3_uart, the_port);
1988 port = card_ptr->ic_port[GET_PHYSICAL_PORT(ii)].icp_port;
1989 if (port && IS_PHYSICAL_PORT(ii)
1990 && (GET_PHYSICAL_PORT(ii) == 0)) {
1991 pci_free_consistent(port->ip_idd->pdev,
1992 TOTAL_RING_BUF_SIZE,
1993 (void *)port->ip_cpu_ringbuf,
1994 port->ip_dma_ringbuf);
1995 kfree(port);
1996 card_ptr->ic_port[GET_PHYSICAL_PORT(ii)].
1997 icp_port = NULL;
1998 }
1999 }
2000 kfree(card_ptr);
2001 idd->data[is->id] = NULL;
2002 }
2003 return 0;
2004}
2005
2006/**
2007 * ioc3uart_probe - card probe function called from shim driver
2008 * @is: submodule struct for this submodule
2009 * @idd: ioc3 driver data for this card
2010 */
2011
2012static int __devinit
2013ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd)
2014{
2015 struct pci_dev *pdev = idd->pdev;
2016 struct ioc3_card *card_ptr;
2017 int ret = 0;
2018 struct ioc3_port *port;
2019 struct ioc3_port *ports[PORTS_PER_CARD];
2020 int phys_port;
2021
2022 DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __FUNCTION__, is, idd));
2023
2024 card_ptr = kmalloc(sizeof(struct ioc3_card), GFP_KERNEL);
2025 if (!card_ptr) {
2026 printk(KERN_WARNING "ioc3_attach_one"
2027 ": unable to get memory for the IOC3\n");
2028 return -ENOMEM;
2029 }
2030 memset(card_ptr, 0, sizeof(struct ioc3_card));
2031 idd->data[is->id] = card_ptr;
2032 Submodule_slot = is->id;
2033
2034 writel(((UARTA_BASE >> 3) << SIO_CR_SER_A_BASE_SHIFT) |
2035 ((UARTB_BASE >> 3) << SIO_CR_SER_B_BASE_SHIFT) |
2036 (0xf << SIO_CR_CMD_PULSE_SHIFT), &idd->vma->sio_cr);
2037
2038 pci_write_config_dword(pdev, PCI_LAT, 0xff00);
2039
2040 /* Enable serial port mode select generic PIO pins as outputs */
2041 ioc3_gpcr_set(idd, GPCR_UARTA_MODESEL | GPCR_UARTB_MODESEL);
2042
2043 /* Create port structures for each port */
2044 for (phys_port = 0; phys_port < PORTS_PER_CARD; phys_port++) {
2045 port = kmalloc(sizeof(struct ioc3_port), GFP_KERNEL);
2046 if (!port) {
2047 printk(KERN_WARNING
2048 "IOC3 serial memory not available for port\n");
2049 goto out4;
2050 }
2051 memset(port, 0, sizeof(struct ioc3_port));
2052 spin_lock_init(&port->ip_lock);
2053
2054 /* we need to remember the previous ones, to point back to
2055 * them farther down - setting up the ring buffers.
2056 */
2057 ports[phys_port] = port;
2058
2059 /* init to something useful */
2060 card_ptr->ic_port[phys_port].icp_port = port;
2061 port->ip_is = is;
2062 port->ip_idd = idd;
2063 port->ip_baud = 9600;
2064 port->ip_card = card_ptr;
2065 port->ip_hooks = &hooks_array[phys_port];
2066
2067 /* Setup each port */
2068 if (phys_port == 0) {
2069 port->ip_serial_regs = &idd->vma->port_a;
2070 port->ip_uart_regs = &idd->vma->sregs.uarta;
2071
2072 DPRINT_CONFIG(("%s : Port A ip_serial_regs 0x%p "
2073 "ip_uart_regs 0x%p\n",
2074 __FUNCTION__,
2075 (void *)port->ip_serial_regs,
2076 (void *)port->ip_uart_regs));
2077
2078 /* setup ring buffers */
2079 port->ip_cpu_ringbuf = pci_alloc_consistent(pdev,
2080 TOTAL_RING_BUF_SIZE, &port->ip_dma_ringbuf);
2081
2082 BUG_ON(!((((int64_t) port->ip_dma_ringbuf) &
2083 (TOTAL_RING_BUF_SIZE - 1)) == 0));
2084 port->ip_inring = RING(port, RX_A);
2085 port->ip_outring = RING(port, TX_A);
2086 DPRINT_CONFIG(("%s : Port A ip_cpu_ringbuf 0x%p "
2087 "ip_dma_ringbuf 0x%p, ip_inring 0x%p "
2088 "ip_outring 0x%p\n",
2089 __FUNCTION__,
2090 (void *)port->ip_cpu_ringbuf,
2091 (void *)port->ip_dma_ringbuf,
2092 (void *)port->ip_inring,
2093 (void *)port->ip_outring));
2094 }
2095 else {
2096 port->ip_serial_regs = &idd->vma->port_b;
2097 port->ip_uart_regs = &idd->vma->sregs.uartb;
2098
2099 DPRINT_CONFIG(("%s : Port B ip_serial_regs 0x%p "
2100 "ip_uart_regs 0x%p\n",
2101 __FUNCTION__,
2102 (void *)port->ip_serial_regs,
2103 (void *)port->ip_uart_regs));
2104
2105 /* share the ring buffers */
2106 port->ip_dma_ringbuf =
2107 ports[phys_port - 1]->ip_dma_ringbuf;
2108 port->ip_cpu_ringbuf =
2109 ports[phys_port - 1]->ip_cpu_ringbuf;
2110 port->ip_inring = RING(port, RX_B);
2111 port->ip_outring = RING(port, TX_B);
2112 DPRINT_CONFIG(("%s : Port B ip_cpu_ringbuf 0x%p "
2113 "ip_dma_ringbuf 0x%p, ip_inring 0x%p "
2114 "ip_outring 0x%p\n",
2115 __FUNCTION__,
2116 (void *)port->ip_cpu_ringbuf,
2117 (void *)port->ip_dma_ringbuf,
2118 (void *)port->ip_inring,
2119 (void *)port->ip_outring));
2120 }
2121
2122 DPRINT_CONFIG(("%s : port %d [addr 0x%p] card_ptr 0x%p",
2123 __FUNCTION__,
2124 phys_port, (void *)port, (void *)card_ptr));
2125 DPRINT_CONFIG((" ip_serial_regs 0x%p ip_uart_regs 0x%p\n",
2126 (void *)port->ip_serial_regs,
2127 (void *)port->ip_uart_regs));
2128
2129 /* Initialize the hardware for IOC3 */
2130 port_init(port);
2131
2132 DPRINT_CONFIG(("%s: phys_port %d port 0x%p inring 0x%p "
2133 "outring 0x%p\n",
2134 __FUNCTION__,
2135 phys_port, (void *)port,
2136 (void *)port->ip_inring,
2137 (void *)port->ip_outring));
2138
2139 }
2140
2141 /* register port with the serial core */
2142
2143 if ((ret = ioc3_serial_core_attach(is, idd)))
2144 goto out4;
2145
2146 Num_of_ioc3_cards++;
2147
2148 return ret;
2149
2150 /* error exits that give back resources */
2151out4:
2152 kfree(card_ptr);
2153 return ret;
2154}
2155
2156static struct ioc3_submodule ioc3uart_submodule = {
2157 .name = "IOC3uart",
2158 .probe = ioc3uart_probe,
2159 .remove = ioc3uart_remove,
2160 /* call .intr for both ports initially */
2161 .irq_mask = SIO_IR_SA | SIO_IR_SB,
2162 .intr = ioc3uart_intr,
2163 .owner = THIS_MODULE,
2164};
2165
2166/**
2167 * ioc3_detect - module init called,
2168 */
2169static int __devinit ioc3uart_init(void)
2170{
2171 int ret;
2172
2173 /* register with serial core */
2174 if ((ret = uart_register_driver(&ioc3_uart)) < 0) {
2175 printk(KERN_WARNING
2176 "%s: Couldn't register IOC3 uart serial driver\n",
2177 __FUNCTION__);
2178 return ret;
2179 }
2180 ret = ioc3_register_submodule(&ioc3uart_submodule);
2181 if (ret)
2182 uart_unregister_driver(&ioc3_uart);
2183 return ret;
2184}
2185
2186static void __devexit ioc3uart_exit(void)
2187{
2188 ioc3_unregister_submodule(&ioc3uart_submodule);
2189 uart_unregister_driver(&ioc3_uart);
2190}
2191
2192module_init(ioc3uart_init);
2193module_exit(ioc3uart_exit);
2194
2195MODULE_AUTHOR("Pat Gefre - Silicon Graphics Inc. (SGI) <pfg@sgi.com>");
2196MODULE_DESCRIPTION("Serial PCI driver module for SGI IOC3 card");
2197MODULE_LICENSE("GPL");
diff --git a/drivers/sh/superhyway/superhyway.c b/drivers/sh/superhyway/superhyway.c
index 7bdab2a7f59c..94b229031198 100644
--- a/drivers/sh/superhyway/superhyway.c
+++ b/drivers/sh/superhyway/superhyway.c
@@ -175,8 +175,6 @@ int superhyway_register_driver(struct superhyway_driver *drv)
175{ 175{
176 drv->drv.name = drv->name; 176 drv->drv.name = drv->name;
177 drv->drv.bus = &superhyway_bus_type; 177 drv->drv.bus = &superhyway_bus_type;
178 drv->drv.probe = superhyway_device_probe;
179 drv->drv.remove = superhyway_device_remove;
180 178
181 return driver_register(&drv->drv); 179 return driver_register(&drv->drv);
182} 180}
@@ -213,6 +211,8 @@ struct bus_type superhyway_bus_type = {
213#ifdef CONFIG_SYSFS 211#ifdef CONFIG_SYSFS
214 .dev_attrs = superhyway_dev_attrs, 212 .dev_attrs = superhyway_dev_attrs,
215#endif 213#endif
214 .probe = superhyway_device_probe,
215 .remove = superhyway_device_remove,
216}; 216};
217 217
218static int __init superhyway_bus_init(void) 218static int __init superhyway_bus_init(void)
diff --git a/drivers/sn/Kconfig b/drivers/sn/Kconfig
index 13b8d249da5c..d95265b187a3 100644
--- a/drivers/sn/Kconfig
+++ b/drivers/sn/Kconfig
@@ -17,4 +17,18 @@ config SGI_IOC4
17 If you have an SGI Altix with an IOC4-based 17 If you have an SGI Altix with an IOC4-based
18 I/O controller say Y. Otherwise say N. 18 I/O controller say Y. Otherwise say N.
19 19
20config SGI_IOC3
21 tristate "SGI IOC3 Base IO support"
22 depends on (IA64_GENERIC || IA64_SGI_SN2)
23 default m
24 ---help---
25 This option enables basic support for the SGI IOC3-based Base IO
26 controller card. This option does not enable any specific
27 functions on such a card, but provides necessary infrastructure
28 for other drivers to utilize.
29
30 If you have an SGI Altix with an IOC3-based
31 I/O controller or a PCI IOC3 serial card say Y.
32 Otherwise say N.
33
20endmenu 34endmenu
diff --git a/drivers/sn/Makefile b/drivers/sn/Makefile
index c2a284185372..2cda011597c0 100644
--- a/drivers/sn/Makefile
+++ b/drivers/sn/Makefile
@@ -4,3 +4,4 @@
4# 4#
5 5
6obj-$(CONFIG_SGI_IOC4) += ioc4.o 6obj-$(CONFIG_SGI_IOC4) += ioc4.o
7obj-$(CONFIG_SGI_IOC3) += ioc3.o
diff --git a/drivers/sn/ioc3.c b/drivers/sn/ioc3.c
new file mode 100644
index 000000000000..aaa009f4a7bf
--- /dev/null
+++ b/drivers/sn/ioc3.c
@@ -0,0 +1,851 @@
1/*
2 * SGI IOC3 master driver and IRQ demuxer
3 *
4 * Copyright (c) 2005 Stanislaw Skowronek <skylark@linux-mips.org>
5 * Heavily based on similar work by:
6 * Brent Casavant <bcasavan@sgi.com> - IOC4 master driver
7 * Pat Gefre <pfg@sgi.com> - IOC3 serial port IRQ demuxer
8 */
9
10#include <linux/config.h>
11#include <linux/errno.h>
12#include <linux/module.h>
13#include <linux/pci.h>
14#include <linux/interrupt.h>
15#include <linux/spinlock.h>
16#include <linux/delay.h>
17#include <linux/ioc3.h>
18#include <linux/rwsem.h>
19
20#define IOC3_PCI_SIZE 0x100000
21
22static LIST_HEAD(ioc3_devices);
23static int ioc3_counter;
24static DECLARE_RWSEM(ioc3_devices_rwsem);
25
26static struct ioc3_submodule *ioc3_submodules[IOC3_MAX_SUBMODULES];
27static struct ioc3_submodule *ioc3_ethernet;
28static rwlock_t ioc3_submodules_lock = RW_LOCK_UNLOCKED;
29
30/* NIC probing code */
31
32#define GPCR_MLAN_EN 0x00200000 /* enable MCR to pin 8 */
33
34static inline unsigned mcr_pack(unsigned pulse, unsigned sample)
35{
36 return (pulse << 10) | (sample << 2);
37}
38
39static int nic_wait(struct ioc3_driver_data *idd)
40{
41 volatile unsigned mcr;
42
43 do {
44 mcr = (volatile unsigned)idd->vma->mcr;
45 } while (!(mcr & 2));
46
47 return mcr & 1;
48}
49
50static int nic_reset(struct ioc3_driver_data *idd)
51{
52 int presence;
53 unsigned long flags;
54
55 local_irq_save(flags);
56 idd->vma->mcr = mcr_pack(500, 65);
57 presence = nic_wait(idd);
58 local_irq_restore(flags);
59
60 udelay(500);
61
62 return presence;
63}
64
65static inline int nic_read_bit(struct ioc3_driver_data *idd)
66{
67 int result;
68 unsigned long flags;
69
70 local_irq_save(flags);
71 idd->vma->mcr = mcr_pack(6, 13);
72 result = nic_wait(idd);
73 local_irq_restore(flags);
74
75 udelay(500);
76
77 return result;
78}
79
80static inline void nic_write_bit(struct ioc3_driver_data *idd, int bit)
81{
82 if (bit)
83 idd->vma->mcr = mcr_pack(6, 110);
84 else
85 idd->vma->mcr = mcr_pack(80, 30);
86
87 nic_wait(idd);
88}
89
90static unsigned nic_read_byte(struct ioc3_driver_data *idd)
91{
92 unsigned result = 0;
93 int i;
94
95 for (i = 0; i < 8; i++)
96 result = (result >> 1) | (nic_read_bit(idd) << 7);
97
98 return result;
99}
100
101static void nic_write_byte(struct ioc3_driver_data *idd, int byte)
102{
103 int i, bit;
104
105 for (i = 8; i; i--) {
106 bit = byte & 1;
107 byte >>= 1;
108
109 nic_write_bit(idd, bit);
110 }
111}
112
113static unsigned long
114nic_find(struct ioc3_driver_data *idd, int *last, unsigned long addr)
115{
116 int a, b, index, disc;
117
118 nic_reset(idd);
119
120 /* Search ROM. */
121 nic_write_byte(idd, 0xF0);
122
123 /* Algorithm from ``Book of iButton Standards''. */
124 for (index = 0, disc = 0; index < 64; index++) {
125 a = nic_read_bit(idd);
126 b = nic_read_bit(idd);
127
128 if (a && b) {
129 printk(KERN_WARNING "IOC3 NIC search failed.\n");
130 *last = 0;
131 return 0;
132 }
133
134 if (!a && !b) {
135 if (index == *last) {
136 addr |= 1UL << index;
137 } else if (index > *last) {
138 addr &= ~(1UL << index);
139 disc = index;
140 } else if ((addr & (1UL << index)) == 0)
141 disc = index;
142 nic_write_bit(idd, (addr>>index)&1);
143 continue;
144 } else {
145 if (a)
146 addr |= 1UL << index;
147 else
148 addr &= ~(1UL << index);
149 nic_write_bit(idd, a);
150 continue;
151 }
152 }
153 *last = disc;
154 return addr;
155}
156
157static void nic_addr(struct ioc3_driver_data *idd, unsigned long addr)
158{
159 int index;
160
161 nic_reset(idd);
162 nic_write_byte(idd, 0xF0);
163 for (index = 0; index < 64; index++) {
164 nic_read_bit(idd);
165 nic_read_bit(idd);
166 nic_write_bit(idd, (addr>>index)&1);
167 }
168}
169
170static void crc16_byte(unsigned int *crc, unsigned char db)
171{
172 int i;
173
174 for(i=0;i<8;i++) {
175 *crc <<= 1;
176 if((db^(*crc>>16)) & 1)
177 *crc ^= 0x8005;
178 db >>= 1;
179 }
180 *crc &= 0xFFFF;
181}
182
183static unsigned int crc16_area(unsigned char *dbs, int size, unsigned int crc)
184{
185 while(size--)
186 crc16_byte(&crc, *(dbs++));
187 return crc;
188}
189
190static void crc8_byte(unsigned int *crc, unsigned char db)
191{
192 int i,f;
193
194 for(i=0;i<8;i++) {
195 f = (*crc ^ db) & 1;
196 *crc >>= 1;
197 db >>= 1;
198 if(f)
199 *crc ^= 0x8c;
200 }
201 *crc &= 0xff;
202}
203
204static unsigned int crc8_addr(unsigned long addr)
205{
206 int i;
207 unsigned int crc = 0x00;
208
209 for(i=0;i<8;i++)
210 crc8_byte(&crc, addr>>(i<<3));
211 return crc;
212}
213
214static void
215read_redir_page(struct ioc3_driver_data *idd, unsigned long addr, int page,
216 unsigned char *redir, unsigned char *data)
217{
218 int loops = 16, i;
219
220 while(redir[page] != 0xFF) {
221 page = redir[page]^0xFF;
222 loops--;
223 if(loops<0) {
224 printk(KERN_ERR "IOC3: NIC circular redirection\n");
225 return;
226 }
227 }
228 loops = 3;
229 while(loops>0) {
230 nic_addr(idd, addr);
231 nic_write_byte(idd, 0xF0);
232 nic_write_byte(idd, (page << 5) & 0xE0);
233 nic_write_byte(idd, (page >> 3) & 0x1F);
234 for(i=0;i<0x20;i++)
235 data[i] = nic_read_byte(idd);
236 if(crc16_area(data, 0x20, 0x0000) == 0x800d)
237 return;
238 loops--;
239 }
240 printk(KERN_ERR "IOC3: CRC error in data page\n");
241 for(i=0;i<0x20;i++)
242 data[i] = 0x00;
243}
244
245static void
246read_redir_map(struct ioc3_driver_data *idd, unsigned long addr,
247 unsigned char *redir)
248{
249 int i,j,loops = 3,crc_ok;
250 unsigned int crc;
251
252 while(loops>0) {
253 crc_ok = 1;
254 nic_addr(idd, addr);
255 nic_write_byte(idd, 0xAA);
256 nic_write_byte(idd, 0x00);
257 nic_write_byte(idd, 0x01);
258 for(i=0;i<64;i+=8) {
259 for(j=0;j<8;j++)
260 redir[i+j] = nic_read_byte(idd);
261 crc = crc16_area(redir+i, 8, (i==0)?0x8707:0x0000);
262 crc16_byte(&crc, nic_read_byte(idd));
263 crc16_byte(&crc, nic_read_byte(idd));
264 if(crc != 0x800d)
265 crc_ok = 0;
266 }
267 if(crc_ok)
268 return;
269 loops--;
270 }
271 printk(KERN_ERR "IOC3: CRC error in redirection page\n");
272 for(i=0;i<64;i++)
273 redir[i] = 0xFF;
274}
275
276static void read_nic(struct ioc3_driver_data *idd, unsigned long addr)
277{
278 unsigned char redir[64];
279 unsigned char data[64],part[32];
280 int i,j;
281
282 /* read redirections */
283 read_redir_map(idd, addr, redir);
284 /* read data pages */
285 read_redir_page(idd, addr, 0, redir, data);
286 read_redir_page(idd, addr, 1, redir, data+32);
287 /* assemble the part # */
288 j=0;
289 for(i=0;i<19;i++)
290 if(data[i+11] != ' ')
291 part[j++] = data[i+11];
292 for(i=0;i<6;i++)
293 if(data[i+32] != ' ')
294 part[j++] = data[i+32];
295 part[j] = 0;
296 /* skip Octane power supplies */
297 if(!strncmp(part, "060-0035-", 9))
298 return;
299 if(!strncmp(part, "060-0038-", 9))
300 return;
301 strcpy(idd->nic_part, part);
302 /* assemble the serial # */
303 j=0;
304 for(i=0;i<10;i++)
305 if(data[i+1] != ' ')
306 idd->nic_serial[j++] = data[i+1];
307 idd->nic_serial[j] = 0;
308}
309
310static void read_mac(struct ioc3_driver_data *idd, unsigned long addr)
311{
312 int i, loops = 3;
313 unsigned char data[13];
314
315 while(loops>0) {
316 nic_addr(idd, addr);
317 nic_write_byte(idd, 0xF0);
318 nic_write_byte(idd, 0x00);
319 nic_write_byte(idd, 0x00);
320 nic_read_byte(idd);
321 for(i=0;i<13;i++)
322 data[i] = nic_read_byte(idd);
323 if(crc16_area(data, 13, 0x0000) == 0x800d) {
324 for(i=10;i>4;i--)
325 idd->nic_mac[10-i] = data[i];
326 return;
327 }
328 loops--;
329 }
330 printk(KERN_ERR "IOC3: CRC error in MAC address\n");
331 for(i=0;i<6;i++)
332 idd->nic_mac[i] = 0x00;
333}
334
335static void probe_nic(struct ioc3_driver_data *idd)
336{
337 int save = 0, loops = 3;
338 unsigned long first, addr;
339
340 idd->vma->gpcr_s = GPCR_MLAN_EN;
341
342 while(loops>0) {
343 idd->nic_part[0] = 0;
344 idd->nic_serial[0] = 0;
345 addr = first = nic_find(idd, &save, 0);
346 if(!first)
347 return;
348 while(1) {
349 if(crc8_addr(addr))
350 break;
351 else {
352 switch(addr & 0xFF) {
353 case 0x0B:
354 read_nic(idd, addr);
355 break;
356 case 0x09:
357 case 0x89:
358 case 0x91:
359 read_mac(idd, addr);
360 break;
361 }
362 }
363 addr = nic_find(idd, &save, addr);
364 if(addr == first)
365 return;
366 }
367 loops--;
368 }
369 printk(KERN_ERR "IOC3: CRC error in NIC address\n");
370}
371
372/* Interrupts */
373
374static inline void
375write_ireg(struct ioc3_driver_data *idd, uint32_t val, int which)
376{
377 unsigned long flags;
378
379 spin_lock_irqsave(&idd->ir_lock, flags);
380 switch (which) {
381 case IOC3_W_IES:
382 writel(val, &idd->vma->sio_ies);
383 break;
384 case IOC3_W_IEC:
385 writel(val, &idd->vma->sio_iec);
386 break;
387 }
388 spin_unlock_irqrestore(&idd->ir_lock, flags);
389}
390static inline uint32_t get_pending_intrs(struct ioc3_driver_data *idd)
391{
392 unsigned long flag;
393 uint32_t intrs = 0;
394
395 spin_lock_irqsave(&idd->ir_lock, flag);
396 intrs = readl(&idd->vma->sio_ir);
397 intrs &= readl(&idd->vma->sio_ies);
398 spin_unlock_irqrestore(&idd->ir_lock, flag);
399 return intrs;
400}
401
402static irqreturn_t ioc3_intr_io(int irq, void *arg, struct pt_regs *regs)
403{
404 unsigned long flags;
405 struct ioc3_driver_data *idd = (struct ioc3_driver_data *)arg;
406 int handled = 1, id;
407 unsigned int pending;
408
409 read_lock_irqsave(&ioc3_submodules_lock, flags);
410
411 if(idd->dual_irq && idd->vma->eisr) {
412 /* send Ethernet IRQ to the driver */
413 if(ioc3_ethernet && idd->active[ioc3_ethernet->id] &&
414 ioc3_ethernet->intr) {
415 handled = handled && !ioc3_ethernet->intr(ioc3_ethernet,
416 idd, 0, regs);
417 }
418 }
419 pending = get_pending_intrs(idd); /* look at the IO IRQs */
420
421 for(id=0;id<IOC3_MAX_SUBMODULES;id++) {
422 if(idd->active[id] && ioc3_submodules[id]
423 && (pending & ioc3_submodules[id]->irq_mask)
424 && ioc3_submodules[id]->intr) {
425 write_ireg(idd, ioc3_submodules[id]->irq_mask,
426 IOC3_W_IEC);
427 if(!ioc3_submodules[id]->intr(ioc3_submodules[id],
428 idd, pending & ioc3_submodules[id]->irq_mask,
429 regs))
430 pending &= ~ioc3_submodules[id]->irq_mask;
431 if (ioc3_submodules[id]->reset_mask)
432 write_ireg(idd, ioc3_submodules[id]->irq_mask,
433 IOC3_W_IES);
434 }
435 }
436 read_unlock_irqrestore(&ioc3_submodules_lock, flags);
437 if(pending) {
438 printk(KERN_WARNING
439 "IOC3: Pending IRQs 0x%08x discarded and disabled\n",pending);
440 write_ireg(idd, pending, IOC3_W_IEC);
441 handled = 1;
442 }
443 return handled?IRQ_HANDLED:IRQ_NONE;
444}
445
446static irqreturn_t ioc3_intr_eth(int irq, void *arg, struct pt_regs *regs)
447{
448 unsigned long flags;
449 struct ioc3_driver_data *idd = (struct ioc3_driver_data *)arg;
450 int handled = 1;
451
452 if(!idd->dual_irq)
453 return IRQ_NONE;
454 read_lock_irqsave(&ioc3_submodules_lock, flags);
455 if(ioc3_ethernet && idd->active[ioc3_ethernet->id]
456 && ioc3_ethernet->intr)
457 handled = handled && !ioc3_ethernet->intr(ioc3_ethernet, idd, 0,
458 regs);
459 read_unlock_irqrestore(&ioc3_submodules_lock, flags);
460 return handled?IRQ_HANDLED:IRQ_NONE;
461}
462
463void ioc3_enable(struct ioc3_submodule *is,
464 struct ioc3_driver_data *idd, unsigned int irqs)
465{
466 write_ireg(idd, irqs & is->irq_mask, IOC3_W_IES);
467}
468
469void ioc3_ack(struct ioc3_submodule *is, struct ioc3_driver_data *idd,
470 unsigned int irqs)
471{
472 writel(irqs & is->irq_mask, &idd->vma->sio_ir);
473}
474
475void ioc3_disable(struct ioc3_submodule *is,
476 struct ioc3_driver_data *idd, unsigned int irqs)
477{
478 write_ireg(idd, irqs & is->irq_mask, IOC3_W_IEC);
479}
480
481void ioc3_gpcr_set(struct ioc3_driver_data *idd, unsigned int val)
482{
483 unsigned long flags;
484 spin_lock_irqsave(&idd->gpio_lock, flags);
485 writel(val, &idd->vma->gpcr_s);
486 spin_unlock_irqrestore(&idd->gpio_lock, flags);
487}
488
489/* Keep it simple, stupid! */
490static int find_slot(void **tab, int max)
491{
492 int i;
493 for(i=0;i<max;i++)
494 if(!(tab[i]))
495 return i;
496 return -1;
497}
498
499/* Register an IOC3 submodule */
500int ioc3_register_submodule(struct ioc3_submodule *is)
501{
502 struct ioc3_driver_data *idd;
503 int alloc_id;
504 unsigned long flags;
505
506 write_lock_irqsave(&ioc3_submodules_lock, flags);
507 alloc_id = find_slot((void **)ioc3_submodules, IOC3_MAX_SUBMODULES);
508 if(alloc_id != -1) {
509 ioc3_submodules[alloc_id] = is;
510 if(is->ethernet) {
511 if(ioc3_ethernet==NULL)
512 ioc3_ethernet=is;
513 else
514 printk(KERN_WARNING
515 "IOC3 Ethernet module already registered!\n");
516 }
517 }
518 write_unlock_irqrestore(&ioc3_submodules_lock, flags);
519
520 if(alloc_id == -1) {
521 printk(KERN_WARNING "Increase IOC3_MAX_SUBMODULES!\n");
522 return -ENOMEM;
523 }
524
525 is->id=alloc_id;
526
527 /* Initialize submodule for each IOC3 */
528 if (!is->probe)
529 return 0;
530
531 down_read(&ioc3_devices_rwsem);
532 list_for_each_entry(idd, &ioc3_devices, list) {
533 /* set to 1 for IRQs in probe */
534 idd->active[alloc_id] = 1;
535 idd->active[alloc_id] = !is->probe(is, idd);
536 }
537 up_read(&ioc3_devices_rwsem);
538
539 return 0;
540}
541
542/* Unregister an IOC3 submodule */
543void ioc3_unregister_submodule(struct ioc3_submodule *is)
544{
545 struct ioc3_driver_data *idd;
546 unsigned long flags;
547
548 write_lock_irqsave(&ioc3_submodules_lock, flags);
549 if(ioc3_submodules[is->id]==is)
550 ioc3_submodules[is->id]=NULL;
551 else
552 printk(KERN_WARNING
553 "IOC3 submodule %s has wrong ID.\n",is->name);
554 if(ioc3_ethernet==is)
555 ioc3_ethernet = NULL;
556 write_unlock_irqrestore(&ioc3_submodules_lock, flags);
557
558 /* Remove submodule for each IOC3 */
559 down_read(&ioc3_devices_rwsem);
560 list_for_each_entry(idd, &ioc3_devices, list)
561 if(idd->active[is->id]) {
562 if(is->remove)
563 if(is->remove(is, idd))
564 printk(KERN_WARNING
565 "%s: IOC3 submodule %s remove failed "
566 "for pci_dev %s.\n",
567 __FUNCTION__, module_name(is->owner),
568 pci_name(idd->pdev));
569 idd->active[is->id] = 0;
570 if(is->irq_mask)
571 write_ireg(idd, is->irq_mask, IOC3_W_IEC);
572 }
573 up_read(&ioc3_devices_rwsem);
574}
575
576/*********************
577 * Device management *
578 *********************/
579
580static char *
581ioc3_class_names[]={"unknown", "IP27 BaseIO", "IP30 system", "MENET 1/2/3",
582 "MENET 4", "CADduo", "Altix Serial"};
583
584static int ioc3_class(struct ioc3_driver_data *idd)
585{
586 int res = IOC3_CLASS_NONE;
587 /* NIC-based logic */
588 if(!strncmp(idd->nic_part, "030-0891-", 9))
589 res = IOC3_CLASS_BASE_IP30;
590 if(!strncmp(idd->nic_part, "030-1155-", 9))
591 res = IOC3_CLASS_CADDUO;
592 if(!strncmp(idd->nic_part, "030-1657-", 9))
593 res = IOC3_CLASS_SERIAL;
594 if(!strncmp(idd->nic_part, "030-1664-", 9))
595 res = IOC3_CLASS_SERIAL;
596 /* total random heuristics */
597#ifdef CONFIG_SGI_IP27
598 if(!idd->nic_part[0])
599 res = IOC3_CLASS_BASE_IP27;
600#endif
601 /* print educational message */
602 printk(KERN_INFO "IOC3 part: [%s], serial: [%s] => class %s\n",
603 idd->nic_part, idd->nic_serial, ioc3_class_names[res]);
604 return res;
605}
606/* Adds a new instance of an IOC3 card */
607static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
608{
609 struct ioc3_driver_data *idd;
610 uint32_t pcmd;
611 int ret, id;
612
613 /* Enable IOC3 and take ownership of it */
614 if ((ret = pci_enable_device(pdev))) {
615 printk(KERN_WARNING
616 "%s: Failed to enable IOC3 device for pci_dev %s.\n",
617 __FUNCTION__, pci_name(pdev));
618 goto out;
619 }
620 pci_set_master(pdev);
621
622#ifdef USE_64BIT_DMA
623 ret = pci_set_dma_mask(pdev, 0xffffffffffffffffULL);
624 if (!ret) {
625 ret = pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL);
626 if (ret < 0) {
627 printk(KERN_WARNING "%s: Unable to obtain 64 bit DMA "
628 "for consistent allocations\n",
629 __FUNCTION__);
630 }
631 }
632#endif
633
634 /* Set up per-IOC3 data */
635 idd = kmalloc(sizeof(struct ioc3_driver_data), GFP_KERNEL);
636 if (!idd) {
637 printk(KERN_WARNING
638 "%s: Failed to allocate IOC3 data for pci_dev %s.\n",
639 __FUNCTION__, pci_name(pdev));
640 ret = -ENODEV;
641 goto out_idd;
642 }
643 memset(idd, 0, sizeof(struct ioc3_driver_data));
644 spin_lock_init(&idd->ir_lock);
645 spin_lock_init(&idd->gpio_lock);
646 idd->pdev = pdev;
647
648 /* Map all IOC3 registers. These are shared between subdevices
649 * so the main IOC3 module manages them.
650 */
651 idd->pma = pci_resource_start(pdev, 0);
652 if (!idd->pma) {
653 printk(KERN_WARNING
654 "%s: Unable to find IOC3 resource "
655 "for pci_dev %s.\n",
656 __FUNCTION__, pci_name(pdev));
657 ret = -ENODEV;
658 goto out_pci;
659 }
660 if (!request_region(idd->pma, IOC3_PCI_SIZE, "ioc3")) {
661 printk(KERN_WARNING
662 "%s: Unable to request IOC3 region "
663 "for pci_dev %s.\n",
664 __FUNCTION__, pci_name(pdev));
665 ret = -ENODEV;
666 goto out_pci;
667 }
668 idd->vma = ioremap(idd->pma, IOC3_PCI_SIZE);
669 if (!idd->vma) {
670 printk(KERN_WARNING
671 "%s: Unable to remap IOC3 region "
672 "for pci_dev %s.\n",
673 __FUNCTION__, pci_name(pdev));
674 ret = -ENODEV;
675 goto out_misc_region;
676 }
677
678 /* Track PCI-device specific data */
679 pci_set_drvdata(pdev, idd);
680 down_write(&ioc3_devices_rwsem);
681 list_add(&idd->list, &ioc3_devices);
682 idd->id = ioc3_counter++;
683 up_write(&ioc3_devices_rwsem);
684
685 idd->gpdr_shadow = idd->vma->gpdr;
686
687 /* Read IOC3 NIC contents */
688 probe_nic(idd);
689
690 /* Detect IOC3 class */
691 idd->class = ioc3_class(idd);
692
693 /* Initialize IOC3 */
694 pci_read_config_dword(pdev, PCI_COMMAND, &pcmd);
695 pci_write_config_dword(pdev, PCI_COMMAND,
696 pcmd | PCI_COMMAND_MEMORY |
697 PCI_COMMAND_PARITY | PCI_COMMAND_SERR |
698 PCI_SCR_DROP_MODE_EN);
699
700 write_ireg(idd, ~0, IOC3_W_IEC);
701 writel(~0, &idd->vma->sio_ir);
702
703 /* Set up IRQs */
704 if(idd->class == IOC3_CLASS_BASE_IP30
705 || idd->class == IOC3_CLASS_BASE_IP27) {
706 writel(0, &idd->vma->eier);
707 writel(~0, &idd->vma->eisr);
708
709 idd->dual_irq = 1;
710 if (!request_irq(pdev->irq, ioc3_intr_eth, SA_SHIRQ,
711 "ioc3-eth", (void *)idd)) {
712 idd->irq_eth = pdev->irq;
713 } else {
714 printk(KERN_WARNING
715 "%s : request_irq fails for IRQ 0x%x\n ",
716 __FUNCTION__, pdev->irq);
717 }
718 if (!request_irq(pdev->irq+2, ioc3_intr_io, SA_SHIRQ,
719 "ioc3-io", (void *)idd)) {
720 idd->irq_io = pdev->irq+2;
721 } else {
722 printk(KERN_WARNING
723 "%s : request_irq fails for IRQ 0x%x\n ",
724 __FUNCTION__, pdev->irq+2);
725 }
726 } else {
727 if (!request_irq(pdev->irq, ioc3_intr_io, SA_SHIRQ,
728 "ioc3", (void *)idd)) {
729 idd->irq_io = pdev->irq;
730 } else {
731 printk(KERN_WARNING
732 "%s : request_irq fails for IRQ 0x%x\n ",
733 __FUNCTION__, pdev->irq);
734 }
735 }
736
737 /* Add this IOC3 to all submodules */
738 read_lock(&ioc3_submodules_lock);
739 for(id=0;id<IOC3_MAX_SUBMODULES;id++)
740 if(ioc3_submodules[id] && ioc3_submodules[id]->probe) {
741 idd->active[id] = 1;
742 idd->active[id] = !ioc3_submodules[id]->probe
743 (ioc3_submodules[id], idd);
744 }
745 read_unlock(&ioc3_submodules_lock);
746
747 printk(KERN_INFO "IOC3 Master Driver loaded for %s\n", pci_name(pdev));
748
749 return 0;
750
751out_misc_region:
752 release_region(idd->pma, IOC3_PCI_SIZE);
753out_pci:
754 kfree(idd);
755out_idd:
756 pci_disable_device(pdev);
757out:
758 return ret;
759}
760
761/* Removes a particular instance of an IOC3 card. */
762static void ioc3_remove(struct pci_dev *pdev)
763{
764 int id;
765 struct ioc3_driver_data *idd;
766
767 idd = pci_get_drvdata(pdev);
768
769 /* Remove this IOC3 from all submodules */
770 read_lock(&ioc3_submodules_lock);
771 for(id=0;id<IOC3_MAX_SUBMODULES;id++)
772 if(idd->active[id]) {
773 if(ioc3_submodules[id] && ioc3_submodules[id]->remove)
774 if(ioc3_submodules[id]->remove(ioc3_submodules[id],
775 idd))
776 printk(KERN_WARNING
777 "%s: IOC3 submodule 0x%s remove failed "
778 "for pci_dev %s.\n",
779 __FUNCTION__,
780 module_name(ioc3_submodules[id]->owner),
781 pci_name(pdev));
782 idd->active[id] = 0;
783 }
784 read_unlock(&ioc3_submodules_lock);
785
786 /* Clear and disable all IRQs */
787 write_ireg(idd, ~0, IOC3_W_IEC);
788 writel(~0, &idd->vma->sio_ir);
789
790 /* Release resources */
791 free_irq(idd->irq_io, (void *)idd);
792 if(idd->dual_irq)
793 free_irq(idd->irq_eth, (void *)idd);
794 iounmap(idd->vma);
795 release_region(idd->pma, IOC3_PCI_SIZE);
796
797 /* Disable IOC3 and relinquish */
798 pci_disable_device(pdev);
799
800 /* Remove and free driver data */
801 down_write(&ioc3_devices_rwsem);
802 list_del(&idd->list);
803 up_write(&ioc3_devices_rwsem);
804 kfree(idd);
805}
806
807static struct pci_device_id ioc3_id_table[] = {
808 {PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, PCI_ANY_ID, PCI_ANY_ID},
809 {0}
810};
811
812static struct pci_driver ioc3_driver = {
813 .name = "IOC3",
814 .id_table = ioc3_id_table,
815 .probe = ioc3_probe,
816 .remove = ioc3_remove,
817};
818
819MODULE_DEVICE_TABLE(pci, ioc3_id_table);
820
821/*********************
822 * Module management *
823 *********************/
824
825/* Module load */
826static int __devinit ioc3_init(void)
827{
828 if (ia64_platform_is("sn2"))
829 return pci_register_driver(&ioc3_driver);
830 return 0;
831}
832
833/* Module unload */
834static void __devexit ioc3_exit(void)
835{
836 pci_unregister_driver(&ioc3_driver);
837}
838
839module_init(ioc3_init);
840module_exit(ioc3_exit);
841
842MODULE_AUTHOR("Stanislaw Skowronek <skylark@linux-mips.org>");
843MODULE_DESCRIPTION("PCI driver for SGI IOC3");
844MODULE_LICENSE("GPL");
845
846EXPORT_SYMBOL(ioc3_register_submodule);
847EXPORT_SYMBOL(ioc3_unregister_submodule);
848EXPORT_SYMBOL(ioc3_ack);
849EXPORT_SYMBOL(ioc3_gpcr_set);
850EXPORT_SYMBOL(ioc3_disable);
851EXPORT_SYMBOL(ioc3_enable);
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
new file mode 100644
index 000000000000..b77dbd63e596
--- /dev/null
+++ b/drivers/spi/Kconfig
@@ -0,0 +1,109 @@
1#
2# SPI driver configuration
3#
4# NOTE: the reason this doesn't show SPI slave support is mostly that
5# nobody's needed a slave side API yet. The master-role API is not
6# fully appropriate there, so it'd need some thought to do well.
7#
8menu "SPI support"
9
10config SPI
11 bool "SPI support"
12 help
13 The "Serial Peripheral Interface" is a low level synchronous
14 protocol. Chips that support SPI can have data transfer rates
15 up to several tens of Mbit/sec. Chips are addressed with a
16 controller and a chipselect. Most SPI slaves don't support
17 dynamic device discovery; some are even write-only or read-only.
18
19 SPI is widely used by microcontollers to talk with sensors,
20 eeprom and flash memory, codecs and various other controller
21 chips, analog to digital (and d-to-a) converters, and more.
22 MMC and SD cards can be accessed using SPI protocol; and for
23 DataFlash cards used in MMC sockets, SPI must always be used.
24
25 SPI is one of a family of similar protocols using a four wire
26 interface (select, clock, data in, data out) including Microwire
27 (half duplex), SSP, SSI, and PSP. This driver framework should
28 work with most such devices and controllers.
29
30config SPI_DEBUG
31 boolean "Debug support for SPI drivers"
32 depends on SPI && DEBUG_KERNEL
33 help
34 Say "yes" to enable debug messaging (like dev_dbg and pr_debug),
35 sysfs, and debugfs support in SPI controller and protocol drivers.
36
37#
38# MASTER side ... talking to discrete SPI slave chips including microcontrollers
39#
40
41config SPI_MASTER
42# boolean "SPI Master Support"
43 boolean
44 default SPI
45 help
46 If your system has an master-capable SPI controller (which
47 provides the clock and chipselect), you can enable that
48 controller and the protocol drivers for the SPI slave chips
49 that are connected.
50
51comment "SPI Master Controller Drivers"
52 depends on SPI_MASTER
53
54config SPI_BITBANG
55 tristate "Bitbanging SPI master"
56 depends on SPI_MASTER && EXPERIMENTAL
57 help
58 With a few GPIO pins, your system can bitbang the SPI protocol.
59 Select this to get SPI support through I/O pins (GPIO, parallel
60 port, etc). Or, some systems' SPI master controller drivers use
61 this code to manage the per-word or per-transfer accesses to the
62 hardware shift registers.
63
64 This is library code, and is automatically selected by drivers that
65 need it. You only need to select this explicitly to support driver
66 modules that aren't part of this kernel tree.
67
68config SPI_BUTTERFLY
69 tristate "Parallel port adapter for AVR Butterfly (DEVELOPMENT)"
70 depends on SPI_MASTER && PARPORT && EXPERIMENTAL
71 select SPI_BITBANG
72 help
73 This uses a custom parallel port cable to connect to an AVR
74 Butterfly <http://www.atmel.com/products/avr/butterfly>, an
75 inexpensive battery powered microcontroller evaluation board.
76 This same cable can be used to flash new firmware.
77
78config SPI_BUTTERFLY
79 tristate "Parallel port adapter for AVR Butterfly (DEVELOPMENT)"
80 depends on SPI_MASTER && PARPORT && EXPERIMENTAL
81 select SPI_BITBANG
82 help
83 This uses a custom parallel port cable to connect to an AVR
84 Butterfly <http://www.atmel.com/products/avr/butterfly>, an
85 inexpensive battery powered microcontroller evaluation board.
86 This same cable can be used to flash new firmware.
87
88#
89# Add new SPI master controllers in alphabetical order above this line
90#
91
92
93#
94# There are lots of SPI device types, with sensors and memory
95# being probably the most widely used ones.
96#
97comment "SPI Protocol Masters"
98 depends on SPI_MASTER
99
100
101#
102# Add new SPI protocol masters in alphabetical order above this line
103#
104
105
106# (slave support would go here)
107
108endmenu # "SPI support"
109
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
new file mode 100644
index 000000000000..c2c87e845abf
--- /dev/null
+++ b/drivers/spi/Makefile
@@ -0,0 +1,25 @@
1#
2# Makefile for kernel SPI drivers.
3#
4
5ifeq ($(CONFIG_SPI_DEBUG),y)
6EXTRA_CFLAGS += -DDEBUG
7endif
8
9# small core, mostly translating board-specific
10# config declarations into driver model code
11obj-$(CONFIG_SPI_MASTER) += spi.o
12
13# SPI master controller drivers (bus)
14obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o
15obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o
16# ... add above this line ...
17
18# SPI protocol drivers (device/link on bus)
19# ... add above this line ...
20
21# SPI slave controller drivers (upstream link)
22# ... add above this line ...
23
24# SPI slave drivers (protocol for that link)
25# ... add above this line ...
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
new file mode 100644
index 000000000000..791c4dc550ae
--- /dev/null
+++ b/drivers/spi/spi.c
@@ -0,0 +1,642 @@
1/*
2 * spi.c - SPI init/core code
3 *
4 * Copyright (C) 2005 David Brownell
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21#include <linux/autoconf.h>
22#include <linux/kernel.h>
23#include <linux/device.h>
24#include <linux/init.h>
25#include <linux/cache.h>
26#include <linux/spi/spi.h>
27
28
29/* SPI bustype and spi_master class are registered after board init code
30 * provides the SPI device tables, ensuring that both are present by the
31 * time controller driver registration causes spi_devices to "enumerate".
32 */
33static void spidev_release(struct device *dev)
34{
35 const struct spi_device *spi = to_spi_device(dev);
36
37 /* spi masters may cleanup for released devices */
38 if (spi->master->cleanup)
39 spi->master->cleanup(spi);
40
41 spi_master_put(spi->master);
42 kfree(dev);
43}
44
45static ssize_t
46modalias_show(struct device *dev, struct device_attribute *a, char *buf)
47{
48 const struct spi_device *spi = to_spi_device(dev);
49
50 return snprintf(buf, BUS_ID_SIZE + 1, "%s\n", spi->modalias);
51}
52
53static struct device_attribute spi_dev_attrs[] = {
54 __ATTR_RO(modalias),
55 __ATTR_NULL,
56};
57
58/* modalias support makes "modprobe $MODALIAS" new-style hotplug work,
59 * and the sysfs version makes coldplug work too.
60 */
61
62static int spi_match_device(struct device *dev, struct device_driver *drv)
63{
64 const struct spi_device *spi = to_spi_device(dev);
65
66 return strncmp(spi->modalias, drv->name, BUS_ID_SIZE) == 0;
67}
68
69static int spi_uevent(struct device *dev, char **envp, int num_envp,
70 char *buffer, int buffer_size)
71{
72 const struct spi_device *spi = to_spi_device(dev);
73
74 envp[0] = buffer;
75 snprintf(buffer, buffer_size, "MODALIAS=%s", spi->modalias);
76 envp[1] = NULL;
77 return 0;
78}
79
80#ifdef CONFIG_PM
81
82/*
83 * NOTE: the suspend() method for an spi_master controller driver
84 * should verify that all its child devices are marked as suspended;
85 * suspend requests delivered through sysfs power/state files don't
86 * enforce such constraints.
87 */
88static int spi_suspend(struct device *dev, pm_message_t message)
89{
90 int value;
91 struct spi_driver *drv = to_spi_driver(dev->driver);
92
93 if (!drv->suspend)
94 return 0;
95
96 /* suspend will stop irqs and dma; no more i/o */
97 value = drv->suspend(to_spi_device(dev), message);
98 if (value == 0)
99 dev->power.power_state = message;
100 return value;
101}
102
103static int spi_resume(struct device *dev)
104{
105 int value;
106 struct spi_driver *drv = to_spi_driver(dev->driver);
107
108 if (!drv->resume)
109 return 0;
110
111 /* resume may restart the i/o queue */
112 value = drv->resume(to_spi_device(dev));
113 if (value == 0)
114 dev->power.power_state = PMSG_ON;
115 return value;
116}
117
118#else
119#define spi_suspend NULL
120#define spi_resume NULL
121#endif
122
123struct bus_type spi_bus_type = {
124 .name = "spi",
125 .dev_attrs = spi_dev_attrs,
126 .match = spi_match_device,
127 .uevent = spi_uevent,
128 .suspend = spi_suspend,
129 .resume = spi_resume,
130};
131EXPORT_SYMBOL_GPL(spi_bus_type);
132
133
134static int spi_drv_probe(struct device *dev)
135{
136 const struct spi_driver *sdrv = to_spi_driver(dev->driver);
137
138 return sdrv->probe(to_spi_device(dev));
139}
140
141static int spi_drv_remove(struct device *dev)
142{
143 const struct spi_driver *sdrv = to_spi_driver(dev->driver);
144
145 return sdrv->remove(to_spi_device(dev));
146}
147
148static void spi_drv_shutdown(struct device *dev)
149{
150 const struct spi_driver *sdrv = to_spi_driver(dev->driver);
151
152 sdrv->shutdown(to_spi_device(dev));
153}
154
155int spi_register_driver(struct spi_driver *sdrv)
156{
157 sdrv->driver.bus = &spi_bus_type;
158 if (sdrv->probe)
159 sdrv->driver.probe = spi_drv_probe;
160 if (sdrv->remove)
161 sdrv->driver.remove = spi_drv_remove;
162 if (sdrv->shutdown)
163 sdrv->driver.shutdown = spi_drv_shutdown;
164 return driver_register(&sdrv->driver);
165}
166EXPORT_SYMBOL_GPL(spi_register_driver);
167
168/*-------------------------------------------------------------------------*/
169
170/* SPI devices should normally not be created by SPI device drivers; that
171 * would make them board-specific. Similarly with SPI master drivers.
172 * Device registration normally goes into like arch/.../mach.../board-YYY.c
173 * with other readonly (flashable) information about mainboard devices.
174 */
175
176struct boardinfo {
177 struct list_head list;
178 unsigned n_board_info;
179 struct spi_board_info board_info[0];
180};
181
182static LIST_HEAD(board_list);
183static DECLARE_MUTEX(board_lock);
184
185
186/* On typical mainboards, this is purely internal; and it's not needed
187 * after board init creates the hard-wired devices. Some development
188 * platforms may not be able to use spi_register_board_info though, and
189 * this is exported so that for example a USB or parport based adapter
190 * driver could add devices (which it would learn about out-of-band).
191 */
192struct spi_device *__init_or_module
193spi_new_device(struct spi_master *master, struct spi_board_info *chip)
194{
195 struct spi_device *proxy;
196 struct device *dev = master->cdev.dev;
197 int status;
198
199 /* NOTE: caller did any chip->bus_num checks necessary */
200
201 if (!spi_master_get(master))
202 return NULL;
203
204 proxy = kzalloc(sizeof *proxy, GFP_KERNEL);
205 if (!proxy) {
206 dev_err(dev, "can't alloc dev for cs%d\n",
207 chip->chip_select);
208 goto fail;
209 }
210 proxy->master = master;
211 proxy->chip_select = chip->chip_select;
212 proxy->max_speed_hz = chip->max_speed_hz;
213 proxy->irq = chip->irq;
214 proxy->modalias = chip->modalias;
215
216 snprintf(proxy->dev.bus_id, sizeof proxy->dev.bus_id,
217 "%s.%u", master->cdev.class_id,
218 chip->chip_select);
219 proxy->dev.parent = dev;
220 proxy->dev.bus = &spi_bus_type;
221 proxy->dev.platform_data = (void *) chip->platform_data;
222 proxy->controller_data = chip->controller_data;
223 proxy->controller_state = NULL;
224 proxy->dev.release = spidev_release;
225
226 /* drivers may modify this default i/o setup */
227 status = master->setup(proxy);
228 if (status < 0) {
229 dev_dbg(dev, "can't %s %s, status %d\n",
230 "setup", proxy->dev.bus_id, status);
231 goto fail;
232 }
233
234 /* driver core catches callers that misbehave by defining
235 * devices that already exist.
236 */
237 status = device_register(&proxy->dev);
238 if (status < 0) {
239 dev_dbg(dev, "can't %s %s, status %d\n",
240 "add", proxy->dev.bus_id, status);
241 goto fail;
242 }
243 dev_dbg(dev, "registered child %s\n", proxy->dev.bus_id);
244 return proxy;
245
246fail:
247 spi_master_put(master);
248 kfree(proxy);
249 return NULL;
250}
251EXPORT_SYMBOL_GPL(spi_new_device);
252
253/*
254 * Board-specific early init code calls this (probably during arch_initcall)
255 * with segments of the SPI device table. Any device nodes are created later,
256 * after the relevant parent SPI controller (bus_num) is defined. We keep
257 * this table of devices forever, so that reloading a controller driver will
258 * not make Linux forget about these hard-wired devices.
259 *
260 * Other code can also call this, e.g. a particular add-on board might provide
261 * SPI devices through its expansion connector, so code initializing that board
262 * would naturally declare its SPI devices.
263 *
264 * The board info passed can safely be __initdata ... but be careful of
265 * any embedded pointers (platform_data, etc), they're copied as-is.
266 */
267int __init
268spi_register_board_info(struct spi_board_info const *info, unsigned n)
269{
270 struct boardinfo *bi;
271
272 bi = kmalloc(sizeof(*bi) + n * sizeof *info, GFP_KERNEL);
273 if (!bi)
274 return -ENOMEM;
275 bi->n_board_info = n;
276 memcpy(bi->board_info, info, n * sizeof *info);
277
278 down(&board_lock);
279 list_add_tail(&bi->list, &board_list);
280 up(&board_lock);
281 return 0;
282}
283EXPORT_SYMBOL_GPL(spi_register_board_info);
284
285/* FIXME someone should add support for a __setup("spi", ...) that
286 * creates board info from kernel command lines
287 */
288
289static void __init_or_module
290scan_boardinfo(struct spi_master *master)
291{
292 struct boardinfo *bi;
293 struct device *dev = master->cdev.dev;
294
295 down(&board_lock);
296 list_for_each_entry(bi, &board_list, list) {
297 struct spi_board_info *chip = bi->board_info;
298 unsigned n;
299
300 for (n = bi->n_board_info; n > 0; n--, chip++) {
301 if (chip->bus_num != master->bus_num)
302 continue;
303 /* some controllers only have one chip, so they
304 * might not use chipselects. otherwise, the
305 * chipselects are numbered 0..max.
306 */
307 if (chip->chip_select >= master->num_chipselect
308 && master->num_chipselect) {
309 dev_dbg(dev, "cs%d > max %d\n",
310 chip->chip_select,
311 master->num_chipselect);
312 continue;
313 }
314 (void) spi_new_device(master, chip);
315 }
316 }
317 up(&board_lock);
318}
319
320/*-------------------------------------------------------------------------*/
321
322static void spi_master_release(struct class_device *cdev)
323{
324 struct spi_master *master;
325
326 master = container_of(cdev, struct spi_master, cdev);
327 kfree(master);
328}
329
330static struct class spi_master_class = {
331 .name = "spi_master",
332 .owner = THIS_MODULE,
333 .release = spi_master_release,
334};
335
336
337/**
338 * spi_alloc_master - allocate SPI master controller
339 * @dev: the controller, possibly using the platform_bus
340 * @size: how much driver-private data to preallocate; the pointer to this
341 * memory is in the class_data field of the returned class_device,
342 * accessible with spi_master_get_devdata().
343 *
344 * This call is used only by SPI master controller drivers, which are the
345 * only ones directly touching chip registers. It's how they allocate
346 * an spi_master structure, prior to calling spi_add_master().
347 *
348 * This must be called from context that can sleep. It returns the SPI
349 * master structure on success, else NULL.
350 *
351 * The caller is responsible for assigning the bus number and initializing
352 * the master's methods before calling spi_add_master(); and (after errors
353 * adding the device) calling spi_master_put() to prevent a memory leak.
354 */
355struct spi_master * __init_or_module
356spi_alloc_master(struct device *dev, unsigned size)
357{
358 struct spi_master *master;
359
360 if (!dev)
361 return NULL;
362
363 master = kzalloc(size + sizeof *master, SLAB_KERNEL);
364 if (!master)
365 return NULL;
366
367 class_device_initialize(&master->cdev);
368 master->cdev.class = &spi_master_class;
369 master->cdev.dev = get_device(dev);
370 spi_master_set_devdata(master, &master[1]);
371
372 return master;
373}
374EXPORT_SYMBOL_GPL(spi_alloc_master);
375
376/**
377 * spi_register_master - register SPI master controller
378 * @master: initialized master, originally from spi_alloc_master()
379 *
380 * SPI master controllers connect to their drivers using some non-SPI bus,
381 * such as the platform bus. The final stage of probe() in that code
382 * includes calling spi_register_master() to hook up to this SPI bus glue.
383 *
384 * SPI controllers use board specific (often SOC specific) bus numbers,
385 * and board-specific addressing for SPI devices combines those numbers
386 * with chip select numbers. Since SPI does not directly support dynamic
387 * device identification, boards need configuration tables telling which
388 * chip is at which address.
389 *
390 * This must be called from context that can sleep. It returns zero on
391 * success, else a negative error code (dropping the master's refcount).
392 * After a successful return, the caller is responsible for calling
393 * spi_unregister_master().
394 */
395int __init_or_module
396spi_register_master(struct spi_master *master)
397{
398 static atomic_t dyn_bus_id = ATOMIC_INIT(0);
399 struct device *dev = master->cdev.dev;
400 int status = -ENODEV;
401 int dynamic = 0;
402
403 if (!dev)
404 return -ENODEV;
405
406 /* convention: dynamically assigned bus IDs count down from the max */
407 if (master->bus_num == 0) {
408 master->bus_num = atomic_dec_return(&dyn_bus_id);
409 dynamic = 1;
410 }
411
412 /* register the device, then userspace will see it.
413 * registration fails if the bus ID is in use.
414 */
415 snprintf(master->cdev.class_id, sizeof master->cdev.class_id,
416 "spi%u", master->bus_num);
417 status = class_device_add(&master->cdev);
418 if (status < 0)
419 goto done;
420 dev_dbg(dev, "registered master %s%s\n", master->cdev.class_id,
421 dynamic ? " (dynamic)" : "");
422
423 /* populate children from any spi device tables */
424 scan_boardinfo(master);
425 status = 0;
426done:
427 return status;
428}
429EXPORT_SYMBOL_GPL(spi_register_master);
430
431
432static int __unregister(struct device *dev, void *unused)
433{
434 /* note: before about 2.6.14-rc1 this would corrupt memory: */
435 spi_unregister_device(to_spi_device(dev));
436 return 0;
437}
438
439/**
440 * spi_unregister_master - unregister SPI master controller
441 * @master: the master being unregistered
442 *
443 * This call is used only by SPI master controller drivers, which are the
444 * only ones directly touching chip registers.
445 *
446 * This must be called from context that can sleep.
447 */
448void spi_unregister_master(struct spi_master *master)
449{
450 (void) device_for_each_child(master->cdev.dev, NULL, __unregister);
451 class_device_unregister(&master->cdev);
452 master->cdev.dev = NULL;
453}
454EXPORT_SYMBOL_GPL(spi_unregister_master);
455
456/**
457 * spi_busnum_to_master - look up master associated with bus_num
458 * @bus_num: the master's bus number
459 *
460 * This call may be used with devices that are registered after
461 * arch init time. It returns a refcounted pointer to the relevant
462 * spi_master (which the caller must release), or NULL if there is
463 * no such master registered.
464 */
465struct spi_master *spi_busnum_to_master(u16 bus_num)
466{
467 if (bus_num) {
468 char name[8];
469 struct kobject *bus;
470
471 snprintf(name, sizeof name, "spi%u", bus_num);
472 bus = kset_find_obj(&spi_master_class.subsys.kset, name);
473 if (bus)
474 return container_of(bus, struct spi_master, cdev.kobj);
475 }
476 return NULL;
477}
478EXPORT_SYMBOL_GPL(spi_busnum_to_master);
479
480
481/*-------------------------------------------------------------------------*/
482
483static void spi_complete(void *arg)
484{
485 complete(arg);
486}
487
488/**
489 * spi_sync - blocking/synchronous SPI data transfers
490 * @spi: device with which data will be exchanged
491 * @message: describes the data transfers
492 *
493 * This call may only be used from a context that may sleep. The sleep
494 * is non-interruptible, and has no timeout. Low-overhead controller
495 * drivers may DMA directly into and out of the message buffers.
496 *
497 * Note that the SPI device's chip select is active during the message,
498 * and then is normally disabled between messages. Drivers for some
499 * frequently-used devices may want to minimize costs of selecting a chip,
500 * by leaving it selected in anticipation that the next message will go
501 * to the same chip. (That may increase power usage.)
502 *
503 * Also, the caller is guaranteeing that the memory associated with the
504 * message will not be freed before this call returns.
505 *
506 * The return value is a negative error code if the message could not be
507 * submitted, else zero. When the value is zero, then message->status is
508 * also defined: it's the completion code for the transfer, either zero
509 * or a negative error code from the controller driver.
510 */
511int spi_sync(struct spi_device *spi, struct spi_message *message)
512{
513 DECLARE_COMPLETION(done);
514 int status;
515
516 message->complete = spi_complete;
517 message->context = &done;
518 status = spi_async(spi, message);
519 if (status == 0)
520 wait_for_completion(&done);
521 message->context = NULL;
522 return status;
523}
524EXPORT_SYMBOL_GPL(spi_sync);
525
526#define SPI_BUFSIZ (SMP_CACHE_BYTES)
527
528static u8 *buf;
529
530/**
531 * spi_write_then_read - SPI synchronous write followed by read
532 * @spi: device with which data will be exchanged
533 * @txbuf: data to be written (need not be dma-safe)
534 * @n_tx: size of txbuf, in bytes
535 * @rxbuf: buffer into which data will be read
536 * @n_rx: size of rxbuf, in bytes (need not be dma-safe)
537 *
538 * This performs a half duplex MicroWire style transaction with the
539 * device, sending txbuf and then reading rxbuf. The return value
540 * is zero for success, else a negative errno status code.
541 * This call may only be used from a context that may sleep.
542 *
543 * Parameters to this routine are always copied using a small buffer;
544 * performance-sensitive or bulk transfer code should instead use
545 * spi_{async,sync}() calls with dma-safe buffers.
546 */
547int spi_write_then_read(struct spi_device *spi,
548 const u8 *txbuf, unsigned n_tx,
549 u8 *rxbuf, unsigned n_rx)
550{
551 static DECLARE_MUTEX(lock);
552
553 int status;
554 struct spi_message message;
555 struct spi_transfer x[2];
556 u8 *local_buf;
557
558 /* Use preallocated DMA-safe buffer. We can't avoid copying here,
559 * (as a pure convenience thing), but we can keep heap costs
560 * out of the hot path ...
561 */
562 if ((n_tx + n_rx) > SPI_BUFSIZ)
563 return -EINVAL;
564
565 spi_message_init(&message);
566 memset(x, 0, sizeof x);
567 if (n_tx) {
568 x[0].len = n_tx;
569 spi_message_add_tail(&x[0], &message);
570 }
571 if (n_rx) {
572 x[1].len = n_rx;
573 spi_message_add_tail(&x[1], &message);
574 }
575
576 /* ... unless someone else is using the pre-allocated buffer */
577 if (down_trylock(&lock)) {
578 local_buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
579 if (!local_buf)
580 return -ENOMEM;
581 } else
582 local_buf = buf;
583
584 memcpy(local_buf, txbuf, n_tx);
585 x[0].tx_buf = local_buf;
586 x[1].rx_buf = local_buf + n_tx;
587
588 /* do the i/o */
589 status = spi_sync(spi, &message);
590 if (status == 0) {
591 memcpy(rxbuf, x[1].rx_buf, n_rx);
592 status = message.status;
593 }
594
595 if (x[0].tx_buf == buf)
596 up(&lock);
597 else
598 kfree(local_buf);
599
600 return status;
601}
602EXPORT_SYMBOL_GPL(spi_write_then_read);
603
604/*-------------------------------------------------------------------------*/
605
606static int __init spi_init(void)
607{
608 int status;
609
610 buf = kmalloc(SPI_BUFSIZ, SLAB_KERNEL);
611 if (!buf) {
612 status = -ENOMEM;
613 goto err0;
614 }
615
616 status = bus_register(&spi_bus_type);
617 if (status < 0)
618 goto err1;
619
620 status = class_register(&spi_master_class);
621 if (status < 0)
622 goto err2;
623 return 0;
624
625err2:
626 bus_unregister(&spi_bus_type);
627err1:
628 kfree(buf);
629 buf = NULL;
630err0:
631 return status;
632}
633
634/* board_info is normally registered in arch_initcall(),
635 * but even essential drivers wait till later
636 *
637 * REVISIT only boardinfo really needs static linking. the rest (device and
638 * driver registration) _could_ be dynamically linked (modular) ... costs
639 * include needing to have boardinfo data structures be much more public.
640 */
641subsys_initcall(spi_init);
642
diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c
new file mode 100644
index 000000000000..f037e5593269
--- /dev/null
+++ b/drivers/spi/spi_bitbang.c
@@ -0,0 +1,472 @@
1/*
2 * spi_bitbang.c - polling/bitbanging SPI master controller driver utilities
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19#include <linux/config.h>
20#include <linux/init.h>
21#include <linux/spinlock.h>
22#include <linux/workqueue.h>
23#include <linux/interrupt.h>
24#include <linux/delay.h>
25#include <linux/errno.h>
26#include <linux/platform_device.h>
27
28#include <linux/spi/spi.h>
29#include <linux/spi/spi_bitbang.h>
30
31
32/*----------------------------------------------------------------------*/
33
34/*
35 * FIRST PART (OPTIONAL): word-at-a-time spi_transfer support.
36 * Use this for GPIO or shift-register level hardware APIs.
37 *
38 * spi_bitbang_cs is in spi_device->controller_state, which is unavailable
39 * to glue code. These bitbang setup() and cleanup() routines are always
40 * used, though maybe they're called from controller-aware code.
41 *
42 * chipselect() and friends may use use spi_device->controller_data and
43 * controller registers as appropriate.
44 *
45 *
46 * NOTE: SPI controller pins can often be used as GPIO pins instead,
47 * which means you could use a bitbang driver either to get hardware
48 * working quickly, or testing for differences that aren't speed related.
49 */
50
51struct spi_bitbang_cs {
52 unsigned nsecs; /* (clock cycle time)/2 */
53 u32 (*txrx_word)(struct spi_device *spi, unsigned nsecs,
54 u32 word, u8 bits);
55 unsigned (*txrx_bufs)(struct spi_device *,
56 u32 (*txrx_word)(
57 struct spi_device *spi,
58 unsigned nsecs,
59 u32 word, u8 bits),
60 unsigned, struct spi_transfer *);
61};
62
63static unsigned bitbang_txrx_8(
64 struct spi_device *spi,
65 u32 (*txrx_word)(struct spi_device *spi,
66 unsigned nsecs,
67 u32 word, u8 bits),
68 unsigned ns,
69 struct spi_transfer *t
70) {
71 unsigned bits = spi->bits_per_word;
72 unsigned count = t->len;
73 const u8 *tx = t->tx_buf;
74 u8 *rx = t->rx_buf;
75
76 while (likely(count > 0)) {
77 u8 word = 0;
78
79 if (tx)
80 word = *tx++;
81 word = txrx_word(spi, ns, word, bits);
82 if (rx)
83 *rx++ = word;
84 count -= 1;
85 }
86 return t->len - count;
87}
88
89static unsigned bitbang_txrx_16(
90 struct spi_device *spi,
91 u32 (*txrx_word)(struct spi_device *spi,
92 unsigned nsecs,
93 u32 word, u8 bits),
94 unsigned ns,
95 struct spi_transfer *t
96) {
97 unsigned bits = spi->bits_per_word;
98 unsigned count = t->len;
99 const u16 *tx = t->tx_buf;
100 u16 *rx = t->rx_buf;
101
102 while (likely(count > 1)) {
103 u16 word = 0;
104
105 if (tx)
106 word = *tx++;
107 word = txrx_word(spi, ns, word, bits);
108 if (rx)
109 *rx++ = word;
110 count -= 2;
111 }
112 return t->len - count;
113}
114
115static unsigned bitbang_txrx_32(
116 struct spi_device *spi,
117 u32 (*txrx_word)(struct spi_device *spi,
118 unsigned nsecs,
119 u32 word, u8 bits),
120 unsigned ns,
121 struct spi_transfer *t
122) {
123 unsigned bits = spi->bits_per_word;
124 unsigned count = t->len;
125 const u32 *tx = t->tx_buf;
126 u32 *rx = t->rx_buf;
127
128 while (likely(count > 3)) {
129 u32 word = 0;
130
131 if (tx)
132 word = *tx++;
133 word = txrx_word(spi, ns, word, bits);
134 if (rx)
135 *rx++ = word;
136 count -= 4;
137 }
138 return t->len - count;
139}
140
141/**
142 * spi_bitbang_setup - default setup for per-word I/O loops
143 */
144int spi_bitbang_setup(struct spi_device *spi)
145{
146 struct spi_bitbang_cs *cs = spi->controller_state;
147 struct spi_bitbang *bitbang;
148
149 if (!spi->max_speed_hz)
150 return -EINVAL;
151
152 if (!cs) {
153 cs = kzalloc(sizeof *cs, SLAB_KERNEL);
154 if (!cs)
155 return -ENOMEM;
156 spi->controller_state = cs;
157 }
158 bitbang = spi_master_get_devdata(spi->master);
159
160 if (!spi->bits_per_word)
161 spi->bits_per_word = 8;
162
163 /* spi_transfer level calls that work per-word */
164 if (spi->bits_per_word <= 8)
165 cs->txrx_bufs = bitbang_txrx_8;
166 else if (spi->bits_per_word <= 16)
167 cs->txrx_bufs = bitbang_txrx_16;
168 else if (spi->bits_per_word <= 32)
169 cs->txrx_bufs = bitbang_txrx_32;
170 else
171 return -EINVAL;
172
173 /* per-word shift register access, in hardware or bitbanging */
174 cs->txrx_word = bitbang->txrx_word[spi->mode & (SPI_CPOL|SPI_CPHA)];
175 if (!cs->txrx_word)
176 return -EINVAL;
177
178 /* nsecs = (clock period)/2 */
179 cs->nsecs = (1000000000/2) / (spi->max_speed_hz);
180 if (cs->nsecs > MAX_UDELAY_MS * 1000)
181 return -EINVAL;
182
183 dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec\n",
184 __FUNCTION__, spi->mode & (SPI_CPOL | SPI_CPHA),
185 spi->bits_per_word, 2 * cs->nsecs);
186
187 /* NOTE we _need_ to call chipselect() early, ideally with adapter
188 * setup, unless the hardware defaults cooperate to avoid confusion
189 * between normal (active low) and inverted chipselects.
190 */
191
192 /* deselect chip (low or high) */
193 spin_lock(&bitbang->lock);
194 if (!bitbang->busy) {
195 bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
196 ndelay(cs->nsecs);
197 }
198 spin_unlock(&bitbang->lock);
199
200 return 0;
201}
202EXPORT_SYMBOL_GPL(spi_bitbang_setup);
203
204/**
205 * spi_bitbang_cleanup - default cleanup for per-word I/O loops
206 */
207void spi_bitbang_cleanup(const struct spi_device *spi)
208{
209 kfree(spi->controller_state);
210}
211EXPORT_SYMBOL_GPL(spi_bitbang_cleanup);
212
213static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t)
214{
215 struct spi_bitbang_cs *cs = spi->controller_state;
216 unsigned nsecs = cs->nsecs;
217
218 return cs->txrx_bufs(spi, cs->txrx_word, nsecs, t);
219}
220
221/*----------------------------------------------------------------------*/
222
223/*
224 * SECOND PART ... simple transfer queue runner.
225 *
226 * This costs a task context per controller, running the queue by
227 * performing each transfer in sequence. Smarter hardware can queue
228 * several DMA transfers at once, and process several controller queues
229 * in parallel; this driver doesn't match such hardware very well.
230 *
231 * Drivers can provide word-at-a-time i/o primitives, or provide
232 * transfer-at-a-time ones to leverage dma or fifo hardware.
233 */
234static void bitbang_work(void *_bitbang)
235{
236 struct spi_bitbang *bitbang = _bitbang;
237 unsigned long flags;
238
239 spin_lock_irqsave(&bitbang->lock, flags);
240 bitbang->busy = 1;
241 while (!list_empty(&bitbang->queue)) {
242 struct spi_message *m;
243 struct spi_device *spi;
244 unsigned nsecs;
245 struct spi_transfer *t = NULL;
246 unsigned tmp;
247 unsigned cs_change;
248 int status;
249
250 m = container_of(bitbang->queue.next, struct spi_message,
251 queue);
252 list_del_init(&m->queue);
253 spin_unlock_irqrestore(&bitbang->lock, flags);
254
255 /* FIXME this is made-up ... the correct value is known to
256 * word-at-a-time bitbang code, and presumably chipselect()
257 * should enforce these requirements too?
258 */
259 nsecs = 100;
260
261 spi = m->spi;
262 tmp = 0;
263 cs_change = 1;
264 status = 0;
265
266 list_for_each_entry (t, &m->transfers, transfer_list) {
267 if (bitbang->shutdown) {
268 status = -ESHUTDOWN;
269 break;
270 }
271
272 /* set up default clock polarity, and activate chip;
273 * this implicitly updates clock and spi modes as
274 * previously recorded for this device via setup().
275 * (and also deselects any other chip that might be
276 * selected ...)
277 */
278 if (cs_change) {
279 bitbang->chipselect(spi, BITBANG_CS_ACTIVE);
280 ndelay(nsecs);
281 }
282 cs_change = t->cs_change;
283 if (!t->tx_buf && !t->rx_buf && t->len) {
284 status = -EINVAL;
285 break;
286 }
287
288 /* transfer data. the lower level code handles any
289 * new dma mappings it needs. our caller always gave
290 * us dma-safe buffers.
291 */
292 if (t->len) {
293 /* REVISIT dma API still needs a designated
294 * DMA_ADDR_INVALID; ~0 might be better.
295 */
296 if (!m->is_dma_mapped)
297 t->rx_dma = t->tx_dma = 0;
298 status = bitbang->txrx_bufs(spi, t);
299 }
300 if (status != t->len) {
301 if (status > 0)
302 status = -EMSGSIZE;
303 break;
304 }
305 m->actual_length += status;
306 status = 0;
307
308 /* protocol tweaks before next transfer */
309 if (t->delay_usecs)
310 udelay(t->delay_usecs);
311
312 if (!cs_change)
313 continue;
314 if (t->transfer_list.next == &m->transfers)
315 break;
316
317 /* sometimes a short mid-message deselect of the chip
318 * may be needed to terminate a mode or command
319 */
320 ndelay(nsecs);
321 bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
322 ndelay(nsecs);
323 }
324
325 m->status = status;
326 m->complete(m->context);
327
328 /* normally deactivate chipselect ... unless no error and
329 * cs_change has hinted that the next message will probably
330 * be for this chip too.
331 */
332 if (!(status == 0 && cs_change)) {
333 ndelay(nsecs);
334 bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
335 ndelay(nsecs);
336 }
337
338 spin_lock_irqsave(&bitbang->lock, flags);
339 }
340 bitbang->busy = 0;
341 spin_unlock_irqrestore(&bitbang->lock, flags);
342}
343
344/**
345 * spi_bitbang_transfer - default submit to transfer queue
346 */
347int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m)
348{
349 struct spi_bitbang *bitbang;
350 unsigned long flags;
351
352 m->actual_length = 0;
353 m->status = -EINPROGRESS;
354
355 bitbang = spi_master_get_devdata(spi->master);
356 if (bitbang->shutdown)
357 return -ESHUTDOWN;
358
359 spin_lock_irqsave(&bitbang->lock, flags);
360 list_add_tail(&m->queue, &bitbang->queue);
361 queue_work(bitbang->workqueue, &bitbang->work);
362 spin_unlock_irqrestore(&bitbang->lock, flags);
363
364 return 0;
365}
366EXPORT_SYMBOL_GPL(spi_bitbang_transfer);
367
368/*----------------------------------------------------------------------*/
369
370/**
371 * spi_bitbang_start - start up a polled/bitbanging SPI master driver
372 * @bitbang: driver handle
373 *
374 * Caller should have zero-initialized all parts of the structure, and then
375 * provided callbacks for chip selection and I/O loops. If the master has
376 * a transfer method, its final step should call spi_bitbang_transfer; or,
377 * that's the default if the transfer routine is not initialized. It should
378 * also set up the bus number and number of chipselects.
379 *
380 * For i/o loops, provide callbacks either per-word (for bitbanging, or for
381 * hardware that basically exposes a shift register) or per-spi_transfer
382 * (which takes better advantage of hardware like fifos or DMA engines).
383 *
384 * Drivers using per-word I/O loops should use (or call) spi_bitbang_setup and
385 * spi_bitbang_cleanup to handle those spi master methods. Those methods are
386 * the defaults if the bitbang->txrx_bufs routine isn't initialized.
387 *
388 * This routine registers the spi_master, which will process requests in a
389 * dedicated task, keeping IRQs unblocked most of the time. To stop
390 * processing those requests, call spi_bitbang_stop().
391 */
392int spi_bitbang_start(struct spi_bitbang *bitbang)
393{
394 int status;
395
396 if (!bitbang->master || !bitbang->chipselect)
397 return -EINVAL;
398
399 INIT_WORK(&bitbang->work, bitbang_work, bitbang);
400 spin_lock_init(&bitbang->lock);
401 INIT_LIST_HEAD(&bitbang->queue);
402
403 if (!bitbang->master->transfer)
404 bitbang->master->transfer = spi_bitbang_transfer;
405 if (!bitbang->txrx_bufs) {
406 bitbang->use_dma = 0;
407 bitbang->txrx_bufs = spi_bitbang_bufs;
408 if (!bitbang->master->setup) {
409 bitbang->master->setup = spi_bitbang_setup;
410 bitbang->master->cleanup = spi_bitbang_cleanup;
411 }
412 } else if (!bitbang->master->setup)
413 return -EINVAL;
414
415 /* this task is the only thing to touch the SPI bits */
416 bitbang->busy = 0;
417 bitbang->workqueue = create_singlethread_workqueue(
418 bitbang->master->cdev.dev->bus_id);
419 if (bitbang->workqueue == NULL) {
420 status = -EBUSY;
421 goto err1;
422 }
423
424 /* driver may get busy before register() returns, especially
425 * if someone registered boardinfo for devices
426 */
427 status = spi_register_master(bitbang->master);
428 if (status < 0)
429 goto err2;
430
431 return status;
432
433err2:
434 destroy_workqueue(bitbang->workqueue);
435err1:
436 return status;
437}
438EXPORT_SYMBOL_GPL(spi_bitbang_start);
439
440/**
441 * spi_bitbang_stop - stops the task providing spi communication
442 */
443int spi_bitbang_stop(struct spi_bitbang *bitbang)
444{
445 unsigned limit = 500;
446
447 spin_lock_irq(&bitbang->lock);
448 bitbang->shutdown = 0;
449 while (!list_empty(&bitbang->queue) && limit--) {
450 spin_unlock_irq(&bitbang->lock);
451
452 dev_dbg(bitbang->master->cdev.dev, "wait for queue\n");
453 msleep(10);
454
455 spin_lock_irq(&bitbang->lock);
456 }
457 spin_unlock_irq(&bitbang->lock);
458 if (!list_empty(&bitbang->queue)) {
459 dev_err(bitbang->master->cdev.dev, "queue didn't empty\n");
460 return -EBUSY;
461 }
462
463 destroy_workqueue(bitbang->workqueue);
464
465 spi_unregister_master(bitbang->master);
466
467 return 0;
468}
469EXPORT_SYMBOL_GPL(spi_bitbang_stop);
470
471MODULE_LICENSE("GPL");
472
diff --git a/drivers/spi/spi_butterfly.c b/drivers/spi/spi_butterfly.c
new file mode 100644
index 000000000000..79a3c59615ab
--- /dev/null
+++ b/drivers/spi/spi_butterfly.c
@@ -0,0 +1,423 @@
1/*
2 * spi_butterfly.c - parport-to-butterfly adapter
3 *
4 * Copyright (C) 2005 David Brownell
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20#include <linux/config.h>
21#include <linux/kernel.h>
22#include <linux/init.h>
23#include <linux/delay.h>
24#include <linux/platform_device.h>
25#include <linux/parport.h>
26
27#include <linux/spi/spi.h>
28#include <linux/spi/spi_bitbang.h>
29#include <linux/spi/flash.h>
30
31#include <linux/mtd/partitions.h>
32
33
34/*
35 * This uses SPI to talk with an "AVR Butterfly", which is a $US20 card
36 * with a battery powered AVR microcontroller and lots of goodies. You
37 * can use GCC to develop firmware for this.
38 *
39 * See Documentation/spi/butterfly for information about how to build
40 * and use this custom parallel port cable.
41 */
42
43#undef HAVE_USI /* nyet */
44
45
46/* DATA output bits (pins 2..9 == D0..D7) */
47#define butterfly_nreset (1 << 1) /* pin 3 */
48
49#define spi_sck_bit (1 << 0) /* pin 2 */
50#define spi_mosi_bit (1 << 7) /* pin 9 */
51
52#define usi_sck_bit (1 << 3) /* pin 5 */
53#define usi_mosi_bit (1 << 4) /* pin 6 */
54
55#define vcc_bits ((1 << 6) | (1 << 5)) /* pins 7, 8 */
56
57/* STATUS input bits */
58#define spi_miso_bit PARPORT_STATUS_BUSY /* pin 11 */
59
60#define usi_miso_bit PARPORT_STATUS_PAPEROUT /* pin 12 */
61
62/* CONTROL output bits */
63#define spi_cs_bit PARPORT_CONTROL_SELECT /* pin 17 */
64/* USI uses no chipselect */
65
66
67
68static inline struct butterfly *spidev_to_pp(struct spi_device *spi)
69{
70 return spi->controller_data;
71}
72
73static inline int is_usidev(struct spi_device *spi)
74{
75#ifdef HAVE_USI
76 return spi->chip_select != 1;
77#else
78 return 0;
79#endif
80}
81
82
83struct butterfly {
84 /* REVISIT ... for now, this must be first */
85 struct spi_bitbang bitbang;
86
87 struct parport *port;
88 struct pardevice *pd;
89
90 u8 lastbyte;
91
92 struct spi_device *dataflash;
93 struct spi_device *butterfly;
94 struct spi_board_info info[2];
95
96};
97
98/*----------------------------------------------------------------------*/
99
100/*
101 * these routines may be slower than necessary because they're hiding
102 * the fact that there are two different SPI busses on this cable: one
103 * to the DataFlash chip (or AVR SPI controller), the other to the
104 * AVR USI controller.
105 */
106
107static inline void
108setsck(struct spi_device *spi, int is_on)
109{
110 struct butterfly *pp = spidev_to_pp(spi);
111 u8 bit, byte = pp->lastbyte;
112
113 if (is_usidev(spi))
114 bit = usi_sck_bit;
115 else
116 bit = spi_sck_bit;
117
118 if (is_on)
119 byte |= bit;
120 else
121 byte &= ~bit;
122 parport_write_data(pp->port, byte);
123 pp->lastbyte = byte;
124}
125
126static inline void
127setmosi(struct spi_device *spi, int is_on)
128{
129 struct butterfly *pp = spidev_to_pp(spi);
130 u8 bit, byte = pp->lastbyte;
131
132 if (is_usidev(spi))
133 bit = usi_mosi_bit;
134 else
135 bit = spi_mosi_bit;
136
137 if (is_on)
138 byte |= bit;
139 else
140 byte &= ~bit;
141 parport_write_data(pp->port, byte);
142 pp->lastbyte = byte;
143}
144
145static inline int getmiso(struct spi_device *spi)
146{
147 struct butterfly *pp = spidev_to_pp(spi);
148 int value;
149 u8 bit;
150
151 if (is_usidev(spi))
152 bit = usi_miso_bit;
153 else
154 bit = spi_miso_bit;
155
156 /* only STATUS_BUSY is NOT negated */
157 value = !(parport_read_status(pp->port) & bit);
158 return (bit == PARPORT_STATUS_BUSY) ? value : !value;
159}
160
161static void butterfly_chipselect(struct spi_device *spi, int value)
162{
163 struct butterfly *pp = spidev_to_pp(spi);
164
165 /* set default clock polarity */
166 if (value)
167 setsck(spi, spi->mode & SPI_CPOL);
168
169 /* no chipselect on this USI link config */
170 if (is_usidev(spi))
171 return;
172
173 /* here, value == "activate or not" */
174
175 /* most PARPORT_CONTROL_* bits are negated */
176 if (spi_cs_bit == PARPORT_CONTROL_INIT)
177 value = !value;
178
179 /* here, value == "bit value to write in control register" */
180
181 parport_frob_control(pp->port, spi_cs_bit, value ? spi_cs_bit : 0);
182}
183
184
185/* we only needed to implement one mode here, and choose SPI_MODE_0 */
186
187#define spidelay(X) do{}while(0)
188//#define spidelay ndelay
189
190#define EXPAND_BITBANG_TXRX
191#include <linux/spi/spi_bitbang.h>
192
193static u32
194butterfly_txrx_word_mode0(struct spi_device *spi,
195 unsigned nsecs,
196 u32 word, u8 bits)
197{
198 return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits);
199}
200
201/*----------------------------------------------------------------------*/
202
203/* override default partitioning with cmdlinepart */
204static struct mtd_partition partitions[] = { {
205 /* JFFS2 wants partitions of 4*N blocks for this device ... */
206
207 /* sector 0 = 8 pages * 264 bytes/page (1 block)
208 * sector 1 = 248 pages * 264 bytes/page
209 */
210 .name = "bookkeeping", // 66 KB
211 .offset = 0,
212 .size = (8 + 248) * 264,
213// .mask_flags = MTD_WRITEABLE,
214}, {
215 /* sector 2 = 256 pages * 264 bytes/page
216 * sectors 3-5 = 512 pages * 264 bytes/page
217 */
218 .name = "filesystem", // 462 KB
219 .offset = MTDPART_OFS_APPEND,
220 .size = MTDPART_SIZ_FULL,
221} };
222
223static struct flash_platform_data flash = {
224 .name = "butterflash",
225 .parts = partitions,
226 .nr_parts = ARRAY_SIZE(partitions),
227};
228
229
230/* REVISIT remove this ugly global and its "only one" limitation */
231static struct butterfly *butterfly;
232
233static void butterfly_attach(struct parport *p)
234{
235 struct pardevice *pd;
236 int status;
237 struct butterfly *pp;
238 struct spi_master *master;
239 struct platform_device *pdev;
240
241 if (butterfly)
242 return;
243
244 /* REVISIT: this just _assumes_ a butterfly is there ... no probe,
245 * and no way to be selective about what it binds to.
246 */
247
248 /* FIXME where should master->cdev.dev come from?
249 * e.g. /sys/bus/pnp0/00:0b, some PCI thing, etc
250 * setting up a platform device like this is an ugly kluge...
251 */
252 pdev = platform_device_register_simple("butterfly", -1, NULL, 0);
253
254 master = spi_alloc_master(&pdev->dev, sizeof *pp);
255 if (!master) {
256 status = -ENOMEM;
257 goto done;
258 }
259 pp = spi_master_get_devdata(master);
260
261 /*
262 * SPI and bitbang hookup
263 *
264 * use default setup(), cleanup(), and transfer() methods; and
265 * only bother implementing mode 0. Start it later.
266 */
267 master->bus_num = 42;
268 master->num_chipselect = 2;
269
270 pp->bitbang.master = spi_master_get(master);
271 pp->bitbang.chipselect = butterfly_chipselect;
272 pp->bitbang.txrx_word[SPI_MODE_0] = butterfly_txrx_word_mode0;
273
274 /*
275 * parport hookup
276 */
277 pp->port = p;
278 pd = parport_register_device(p, "spi_butterfly",
279 NULL, NULL, NULL,
280 0 /* FLAGS */, pp);
281 if (!pd) {
282 status = -ENOMEM;
283 goto clean0;
284 }
285 pp->pd = pd;
286
287 status = parport_claim(pd);
288 if (status < 0)
289 goto clean1;
290
291 /*
292 * Butterfly reset, powerup, run firmware
293 */
294 pr_debug("%s: powerup/reset Butterfly\n", p->name);
295
296 /* nCS for dataflash (this bit is inverted on output) */
297 parport_frob_control(pp->port, spi_cs_bit, 0);
298
299 /* stabilize power with chip in reset (nRESET), and
300 * both spi_sck_bit and usi_sck_bit clear (CPOL=0)
301 */
302 pp->lastbyte |= vcc_bits;
303 parport_write_data(pp->port, pp->lastbyte);
304 msleep(5);
305
306 /* take it out of reset; assume long reset delay */
307 pp->lastbyte |= butterfly_nreset;
308 parport_write_data(pp->port, pp->lastbyte);
309 msleep(100);
310
311
312 /*
313 * Start SPI ... for now, hide that we're two physical busses.
314 */
315 status = spi_bitbang_start(&pp->bitbang);
316 if (status < 0)
317 goto clean2;
318
319 /* Bus 1 lets us talk to at45db041b (firmware disables AVR)
320 * or AVR (firmware resets at45, acts as spi slave)
321 */
322 pp->info[0].max_speed_hz = 15 * 1000 * 1000;
323 strcpy(pp->info[0].modalias, "mtd_dataflash");
324 pp->info[0].platform_data = &flash;
325 pp->info[0].chip_select = 1;
326 pp->info[0].controller_data = pp;
327 pp->dataflash = spi_new_device(pp->bitbang.master, &pp->info[0]);
328 if (pp->dataflash)
329 pr_debug("%s: dataflash at %s\n", p->name,
330 pp->dataflash->dev.bus_id);
331
332#ifdef HAVE_USI
333 /* even more custom AVR firmware */
334 pp->info[1].max_speed_hz = 10 /* ?? */ * 1000 * 1000;
335 strcpy(pp->info[1].modalias, "butterfly");
336 // pp->info[1].platform_data = ... TBD ... ;
337 pp->info[1].chip_select = 2,
338 pp->info[1].controller_data = pp;
339 pp->butterfly = spi_new_device(pp->bitbang.master, &pp->info[1]);
340 if (pp->butterfly)
341 pr_debug("%s: butterfly at %s\n", p->name,
342 pp->butterfly->dev.bus_id);
343
344 /* FIXME setup ACK for the IRQ line ... */
345#endif
346
347 // dev_info(_what?_, ...)
348 pr_info("%s: AVR Butterfly\n", p->name);
349 butterfly = pp;
350 return;
351
352clean2:
353 /* turn off VCC */
354 parport_write_data(pp->port, 0);
355
356 parport_release(pp->pd);
357clean1:
358 parport_unregister_device(pd);
359clean0:
360 (void) spi_master_put(pp->bitbang.master);
361done:
362 platform_device_unregister(pdev);
363 pr_debug("%s: butterfly probe, fail %d\n", p->name, status);
364}
365
366static void butterfly_detach(struct parport *p)
367{
368 struct butterfly *pp;
369 struct platform_device *pdev;
370 int status;
371
372 /* FIXME this global is ugly ... but, how to quickly get from
373 * the parport to the "struct butterfly" associated with it?
374 * "old school" driver-internal device lists?
375 */
376 if (!butterfly || butterfly->port != p)
377 return;
378 pp = butterfly;
379 butterfly = NULL;
380
381#ifdef HAVE_USI
382 spi_unregister_device(pp->butterfly);
383 pp->butterfly = NULL;
384#endif
385 spi_unregister_device(pp->dataflash);
386 pp->dataflash = NULL;
387
388 status = spi_bitbang_stop(&pp->bitbang);
389
390 /* turn off VCC */
391 parport_write_data(pp->port, 0);
392 msleep(10);
393
394 parport_release(pp->pd);
395 parport_unregister_device(pp->pd);
396
397 pdev = to_platform_device(pp->bitbang.master->cdev.dev);
398
399 (void) spi_master_put(pp->bitbang.master);
400
401 platform_device_unregister(pdev);
402}
403
404static struct parport_driver butterfly_driver = {
405 .name = "spi_butterfly",
406 .attach = butterfly_attach,
407 .detach = butterfly_detach,
408};
409
410
411static int __init butterfly_init(void)
412{
413 return parport_register_driver(&butterfly_driver);
414}
415device_initcall(butterfly_init);
416
417static void __exit butterfly_exit(void)
418{
419 parport_unregister_driver(&butterfly_driver);
420}
421module_exit(butterfly_exit);
422
423MODULE_LICENSE("GPL");
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c
index 9baa6296fc95..7af1883d4bf9 100644
--- a/drivers/usb/atm/usbatm.c
+++ b/drivers/usb/atm/usbatm.c
@@ -207,7 +207,7 @@ static inline void usbatm_pop(struct atm_vcc *vcc, struct sk_buff *skb)
207** urbs ** 207** urbs **
208************/ 208************/
209 209
210static inline struct urb *usbatm_pop_urb(struct usbatm_channel *channel) 210static struct urb *usbatm_pop_urb(struct usbatm_channel *channel)
211{ 211{
212 struct urb *urb; 212 struct urb *urb;
213 213
@@ -224,7 +224,7 @@ static inline struct urb *usbatm_pop_urb(struct usbatm_channel *channel)
224 return urb; 224 return urb;
225} 225}
226 226
227static inline int usbatm_submit_urb(struct urb *urb) 227static int usbatm_submit_urb(struct urb *urb)
228{ 228{
229 struct usbatm_channel *channel = urb->context; 229 struct usbatm_channel *channel = urb->context;
230 int ret; 230 int ret;
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 8f402f85e1ca..afc84cfb61f9 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -2534,9 +2534,6 @@ static struct usb_gadget_driver eth_driver = {
2534 .driver = { 2534 .driver = {
2535 .name = (char *) shortname, 2535 .name = (char *) shortname,
2536 .owner = THIS_MODULE, 2536 .owner = THIS_MODULE,
2537 // .shutdown = ...
2538 // .suspend = ...
2539 // .resume = ...
2540 }, 2537 },
2541}; 2538};
2542 2539
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index c6c279de832e..9a4edc5657aa 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -1738,9 +1738,6 @@ static struct usb_gadget_driver gadgetfs_driver = {
1738 1738
1739 .driver = { 1739 .driver = {
1740 .name = (char *) shortname, 1740 .name = (char *) shortname,
1741 // .shutdown = ...
1742 // .suspend = ...
1743 // .resume = ...
1744 }, 1741 },
1745}; 1742};
1746 1743
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index 2e6926b33455..ba9acd531024 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -374,9 +374,6 @@ static struct usb_gadget_driver gs_gadget_driver = {
374 .disconnect = gs_disconnect, 374 .disconnect = gs_disconnect,
375 .driver = { 375 .driver = {
376 .name = GS_SHORT_NAME, 376 .name = GS_SHORT_NAME,
377 /* .shutdown = ... */
378 /* .suspend = ... */
379 /* .resume = ... */
380 }, 377 },
381}; 378};
382 379
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index 6c58636e914b..2fc110d3ad5a 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -1303,9 +1303,6 @@ static struct usb_gadget_driver zero_driver = {
1303 .driver = { 1303 .driver = {
1304 .name = (char *) shortname, 1304 .name = (char *) shortname,
1305 .owner = THIS_MODULE, 1305 .owner = THIS_MODULE,
1306 // .shutdown = ...
1307 // .suspend = ...
1308 // .resume = ...
1309 }, 1306 },
1310}; 1307};
1311 1308
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig
index 509dd0a04c54..5246b35301de 100644
--- a/drivers/usb/input/Kconfig
+++ b/drivers/usb/input/Kconfig
@@ -37,6 +37,16 @@ config USB_HIDINPUT
37 37
38 If unsure, say Y. 38 If unsure, say Y.
39 39
40config USB_HIDINPUT_POWERBOOK
41 bool "Enable support for iBook/PowerBook special keys"
42 default n
43 depends on USB_HIDINPUT
44 help
45 Say Y here if you want support for the special keys (Fn, Numlock) on
46 Apple iBooks and PowerBooks.
47
48 If unsure, say N.
49
40config HID_FF 50config HID_FF
41 bool "Force feedback support (EXPERIMENTAL)" 51 bool "Force feedback support (EXPERIMENTAL)"
42 depends on USB_HIDINPUT && EXPERIMENTAL 52 depends on USB_HIDINPUT && EXPERIMENTAL
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index 5f52979af1c7..a91e72c41415 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -1450,6 +1450,9 @@ void hid_init_reports(struct hid_device *hid)
1450#define USB_VENDOR_ID_APPLE 0x05ac 1450#define USB_VENDOR_ID_APPLE 0x05ac
1451#define USB_DEVICE_ID_APPLE_POWERMOUSE 0x0304 1451#define USB_DEVICE_ID_APPLE_POWERMOUSE 0x0304
1452 1452
1453#define USB_VENDOR_ID_CHERRY 0x046a
1454#define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023
1455
1453/* 1456/*
1454 * Alphabetically sorted blacklist by quirk type. 1457 * Alphabetically sorted blacklist by quirk type.
1455 */ 1458 */
@@ -1580,6 +1583,16 @@ static const struct hid_blacklist {
1580 { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD }, 1583 { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD },
1581 { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD }, 1584 { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
1582 1585
1586 { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION },
1587
1588 { USB_VENDOR_ID_APPLE, 0x020E, HID_QUIRK_POWERBOOK_HAS_FN },
1589 { USB_VENDOR_ID_APPLE, 0x020F, HID_QUIRK_POWERBOOK_HAS_FN },
1590 { USB_VENDOR_ID_APPLE, 0x0214, HID_QUIRK_POWERBOOK_HAS_FN },
1591 { USB_VENDOR_ID_APPLE, 0x0215, HID_QUIRK_POWERBOOK_HAS_FN },
1592 { USB_VENDOR_ID_APPLE, 0x0216, HID_QUIRK_POWERBOOK_HAS_FN },
1593 { USB_VENDOR_ID_APPLE, 0x030A, HID_QUIRK_POWERBOOK_HAS_FN },
1594 { USB_VENDOR_ID_APPLE, 0x030B, HID_QUIRK_POWERBOOK_HAS_FN },
1595
1583 { 0, 0 } 1596 { 0, 0 }
1584}; 1597};
1585 1598
@@ -1626,6 +1639,20 @@ static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
1626 usb_buffer_free(dev, hid->bufsize, hid->ctrlbuf, hid->ctrlbuf_dma); 1639 usb_buffer_free(dev, hid->bufsize, hid->ctrlbuf, hid->ctrlbuf_dma);
1627} 1640}
1628 1641
1642/*
1643 * Cherry Cymotion keyboard have an invalid HID report descriptor,
1644 * that needs fixing before we can parse it.
1645 */
1646
1647static void hid_fixup_cymotion_descriptor(char *rdesc, int rsize)
1648{
1649 if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
1650 info("Fixing up Cherry Cymotion report descriptor");
1651 rdesc[11] = rdesc[16] = 0xff;
1652 rdesc[12] = rdesc[17] = 0x03;
1653 }
1654}
1655
1629static struct hid_device *usb_hid_configure(struct usb_interface *intf) 1656static struct hid_device *usb_hid_configure(struct usb_interface *intf)
1630{ 1657{
1631 struct usb_host_interface *interface = intf->cur_altsetting; 1658 struct usb_host_interface *interface = intf->cur_altsetting;
@@ -1673,6 +1700,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
1673 return NULL; 1700 return NULL;
1674 } 1701 }
1675 1702
1703 if ((quirks & HID_QUIRK_CYMOTION))
1704 hid_fixup_cymotion_descriptor(rdesc, rsize);
1705
1676#ifdef DEBUG_DATA 1706#ifdef DEBUG_DATA
1677 printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n); 1707 printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n);
1678 for (n = 0; n < rsize; n++) 1708 for (n = 0; n < rsize; n++)
diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c
index 192a03b28971..cb0d80f49252 100644
--- a/drivers/usb/input/hid-input.c
+++ b/drivers/usb/input/hid-input.c
@@ -73,6 +73,160 @@ static const struct {
73#define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0) 73#define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0)
74#define map_ff_effect(c) do { set_bit(c, input->ffbit); } while (0) 74#define map_ff_effect(c) do { set_bit(c, input->ffbit); } while (0)
75 75
76#ifdef CONFIG_USB_HIDINPUT_POWERBOOK
77
78struct hidinput_key_translation {
79 u16 from;
80 u16 to;
81 u8 flags;
82};
83
84#define POWERBOOK_FLAG_FKEY 0x01
85
86static struct hidinput_key_translation powerbook_fn_keys[] = {
87 { KEY_BACKSPACE, KEY_DELETE },
88 { KEY_F1, KEY_BRIGHTNESSDOWN, POWERBOOK_FLAG_FKEY },
89 { KEY_F2, KEY_BRIGHTNESSUP, POWERBOOK_FLAG_FKEY },
90 { KEY_F3, KEY_MUTE, POWERBOOK_FLAG_FKEY },
91 { KEY_F4, KEY_VOLUMEDOWN, POWERBOOK_FLAG_FKEY },
92 { KEY_F5, KEY_VOLUMEUP, POWERBOOK_FLAG_FKEY },
93 { KEY_F6, KEY_NUMLOCK, POWERBOOK_FLAG_FKEY },
94 { KEY_F7, KEY_SWITCHVIDEOMODE, POWERBOOK_FLAG_FKEY },
95 { KEY_F8, KEY_KBDILLUMTOGGLE, POWERBOOK_FLAG_FKEY },
96 { KEY_F9, KEY_KBDILLUMDOWN, POWERBOOK_FLAG_FKEY },
97 { KEY_F10, KEY_KBDILLUMUP, POWERBOOK_FLAG_FKEY },
98 { KEY_UP, KEY_PAGEUP },
99 { KEY_DOWN, KEY_PAGEDOWN },
100 { KEY_LEFT, KEY_HOME },
101 { KEY_RIGHT, KEY_END },
102 { }
103};
104
105static struct hidinput_key_translation powerbook_numlock_keys[] = {
106 { KEY_J, KEY_KP1 },
107 { KEY_K, KEY_KP2 },
108 { KEY_L, KEY_KP3 },
109 { KEY_U, KEY_KP4 },
110 { KEY_I, KEY_KP5 },
111 { KEY_O, KEY_KP6 },
112 { KEY_7, KEY_KP7 },
113 { KEY_8, KEY_KP8 },
114 { KEY_9, KEY_KP9 },
115 { KEY_M, KEY_KP0 },
116 { KEY_DOT, KEY_KPDOT },
117 { KEY_SLASH, KEY_KPPLUS },
118 { KEY_SEMICOLON, KEY_KPMINUS },
119 { KEY_P, KEY_KPASTERISK },
120 { KEY_MINUS, KEY_KPEQUAL },
121 { KEY_0, KEY_KPSLASH },
122 { KEY_F6, KEY_NUMLOCK },
123 { KEY_KPENTER, KEY_KPENTER },
124 { KEY_BACKSPACE, KEY_BACKSPACE },
125 { }
126};
127
128static int usbhid_pb_fnmode = 1;
129module_param_named(pb_fnmode, usbhid_pb_fnmode, int, 0644);
130MODULE_PARM_DESC(pb_fnmode,
131 "Mode of fn key on PowerBooks (0 = disabled, 1 = fkeyslast, 2 = fkeysfirst)");
132
133static struct hidinput_key_translation *find_translation(struct hidinput_key_translation *table, u16 from)
134{
135 struct hidinput_key_translation *trans;
136
137 /* Look for the translation */
138 for (trans = table; trans->from; trans++)
139 if (trans->from == from)
140 return trans;
141
142 return NULL;
143}
144
145static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
146 struct hid_usage *usage, __s32 value)
147{
148 struct hidinput_key_translation *trans;
149
150 if (usage->code == KEY_FN) {
151 if (value) hid->quirks |= HID_QUIRK_POWERBOOK_FN_ON;
152 else hid->quirks &= ~HID_QUIRK_POWERBOOK_FN_ON;
153
154 input_event(input, usage->type, usage->code, value);
155
156 return 1;
157 }
158
159 if (usbhid_pb_fnmode) {
160 int do_translate;
161
162 trans = find_translation(powerbook_fn_keys, usage->code);
163 if (trans) {
164 if (test_bit(usage->code, hid->pb_pressed_fn))
165 do_translate = 1;
166 else if (trans->flags & POWERBOOK_FLAG_FKEY)
167 do_translate =
168 (usbhid_pb_fnmode == 2 && (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON)) ||
169 (usbhid_pb_fnmode == 1 && !(hid->quirks & HID_QUIRK_POWERBOOK_FN_ON));
170 else
171 do_translate = (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON);
172
173 if (do_translate) {
174 if (value)
175 set_bit(usage->code, hid->pb_pressed_fn);
176 else
177 clear_bit(usage->code, hid->pb_pressed_fn);
178
179 input_event(input, usage->type, trans->to, value);
180
181 return 1;
182 }
183 }
184
185 if (test_bit(usage->code, hid->pb_pressed_numlock) ||
186 test_bit(LED_NUML, input->led)) {
187 trans = find_translation(powerbook_numlock_keys, usage->code);
188
189 if (trans) {
190 if (value)
191 set_bit(usage->code, hid->pb_pressed_numlock);
192 else
193 clear_bit(usage->code, hid->pb_pressed_numlock);
194
195 input_event(input, usage->type, trans->to, value);
196 }
197
198 return 1;
199 }
200 }
201
202 return 0;
203}
204
205static void hidinput_pb_setup(struct input_dev *input)
206{
207 struct hidinput_key_translation *trans;
208
209 set_bit(KEY_NUMLOCK, input->keybit);
210
211 /* Enable all needed keys */
212 for (trans = powerbook_fn_keys; trans->from; trans++)
213 set_bit(trans->to, input->keybit);
214
215 for (trans = powerbook_numlock_keys; trans->from; trans++)
216 set_bit(trans->to, input->keybit);
217}
218#else
219static inline int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
220 struct hid_usage *usage, __s32 value)
221{
222 return 0;
223}
224
225static inline void hidinput_pb_setup(struct input_dev *input)
226{
227}
228#endif
229
76static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, 230static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field,
77 struct hid_usage *usage) 231 struct hid_usage *usage)
78{ 232{
@@ -135,8 +289,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
135 case HID_UP_SIMULATION: 289 case HID_UP_SIMULATION:
136 290
137 switch (usage->hid & 0xffff) { 291 switch (usage->hid & 0xffff) {
138 case 0xba: map_abs(ABS_RUDDER); break; 292 case 0xba: map_abs(ABS_RUDDER); break;
139 case 0xbb: map_abs(ABS_THROTTLE); break; 293 case 0xbb: map_abs(ABS_THROTTLE); break;
294 case 0xc4: map_abs(ABS_GAS); break;
295 case 0xc5: map_abs(ABS_BRAKE); break;
296 case 0xc8: map_abs(ABS_WHEEL); break;
140 default: goto ignore; 297 default: goto ignore;
141 } 298 }
142 break; 299 break;
@@ -289,11 +446,19 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
289 case 0x226: map_key_clear(KEY_STOP); break; 446 case 0x226: map_key_clear(KEY_STOP); break;
290 case 0x227: map_key_clear(KEY_REFRESH); break; 447 case 0x227: map_key_clear(KEY_REFRESH); break;
291 case 0x22a: map_key_clear(KEY_BOOKMARKS); break; 448 case 0x22a: map_key_clear(KEY_BOOKMARKS); break;
449 case 0x233: map_key_clear(KEY_SCROLLUP); break;
450 case 0x234: map_key_clear(KEY_SCROLLDOWN); break;
292 case 0x238: map_rel(REL_HWHEEL); break; 451 case 0x238: map_rel(REL_HWHEEL); break;
293 case 0x279: map_key_clear(KEY_REDO); break; 452 case 0x279: map_key_clear(KEY_REDO); break;
294 case 0x289: map_key_clear(KEY_REPLY); break; 453 case 0x289: map_key_clear(KEY_REPLY); break;
295 case 0x28b: map_key_clear(KEY_FORWARDMAIL); break; 454 case 0x28b: map_key_clear(KEY_FORWARDMAIL); break;
296 case 0x28c: map_key_clear(KEY_SEND); break; 455 case 0x28c: map_key_clear(KEY_SEND); break;
456
457 /* Reported on a Cherry Cymotion keyboard */
458 case 0x301: map_key_clear(KEY_PROG1); break;
459 case 0x302: map_key_clear(KEY_PROG2); break;
460 case 0x303: map_key_clear(KEY_PROG3); break;
461
297 default: goto ignore; 462 default: goto ignore;
298 } 463 }
299 break; 464 break;
@@ -325,7 +490,12 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
325 490
326 set_bit(EV_REP, input->evbit); 491 set_bit(EV_REP, input->evbit);
327 switch(usage->hid & HID_USAGE) { 492 switch(usage->hid & HID_USAGE) {
328 case 0x003: map_key_clear(KEY_FN); break; 493 case 0x003:
494 /* The fn key on Apple PowerBooks */
495 map_key_clear(KEY_FN);
496 hidinput_pb_setup(input);
497 break;
498
329 default: goto ignore; 499 default: goto ignore;
330 } 500 }
331 break; 501 break;
@@ -482,6 +652,9 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
482 return; 652 return;
483 } 653 }
484 654
655 if ((hid->quirks & HID_QUIRK_POWERBOOK_HAS_FN) && hidinput_pb_event(hid, input, usage, value))
656 return;
657
485 if (usage->hat_min < usage->hat_max || usage->hat_dir) { 658 if (usage->hat_min < usage->hat_max || usage->hat_dir) {
486 int hat_dir = usage->hat_dir; 659 int hat_dir = usage->hat_dir;
487 if (!hat_dir) 660 if (!hat_dir)
@@ -524,7 +697,7 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
524 return; 697 return;
525 } 698 }
526 699
527 if((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */ 700 if ((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */
528 return; 701 return;
529 702
530 input_event(input, usage->type, usage->code, value); 703 input_event(input, usage->type, usage->code, value);
diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h
index ee48a2276104..8b0d4346ce9c 100644
--- a/drivers/usb/input/hid.h
+++ b/drivers/usb/input/hid.h
@@ -235,17 +235,20 @@ struct hid_item {
235 * HID device quirks. 235 * HID device quirks.
236 */ 236 */
237 237
238#define HID_QUIRK_INVERT 0x001 238#define HID_QUIRK_INVERT 0x00000001
239#define HID_QUIRK_NOTOUCH 0x002 239#define HID_QUIRK_NOTOUCH 0x00000002
240#define HID_QUIRK_IGNORE 0x004 240#define HID_QUIRK_IGNORE 0x00000004
241#define HID_QUIRK_NOGET 0x008 241#define HID_QUIRK_NOGET 0x00000008
242#define HID_QUIRK_HIDDEV 0x010 242#define HID_QUIRK_HIDDEV 0x00000010
243#define HID_QUIRK_BADPAD 0x020 243#define HID_QUIRK_BADPAD 0x00000020
244#define HID_QUIRK_MULTI_INPUT 0x040 244#define HID_QUIRK_MULTI_INPUT 0x00000040
245#define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x080 245#define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x00000080
246#define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x100 246#define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x00000100
247#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x200 247#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x00000200
248#define HID_QUIRK_2WHEEL_POWERMOUSE 0x400 248#define HID_QUIRK_2WHEEL_POWERMOUSE 0x00000400
249#define HID_QUIRK_CYMOTION 0x00000800
250#define HID_QUIRK_POWERBOOK_HAS_FN 0x00001000
251#define HID_QUIRK_POWERBOOK_FN_ON 0x00002000
249 252
250/* 253/*
251 * This is the global environment of the parser. This information is 254 * This is the global environment of the parser. This information is
@@ -431,6 +434,11 @@ struct hid_device { /* device report descriptor */
431 void (*ff_exit)(struct hid_device*); /* Called by hid_exit_ff(hid) */ 434 void (*ff_exit)(struct hid_device*); /* Called by hid_exit_ff(hid) */
432 int (*ff_event)(struct hid_device *hid, struct input_dev *input, 435 int (*ff_event)(struct hid_device *hid, struct input_dev *input,
433 unsigned int type, unsigned int code, int value); 436 unsigned int type, unsigned int code, int value);
437
438#ifdef CONFIG_USB_HIDINPUT_POWERBOOK
439 unsigned long pb_pressed_fn[NBITS(KEY_MAX)];
440 unsigned long pb_pressed_numlock[NBITS(KEY_MAX)];
441#endif
434}; 442};
435 443
436#define HID_GLOBAL_STACK_SIZE 4 444#define HID_GLOBAL_STACK_SIZE 4
diff --git a/drivers/usb/input/pid.c b/drivers/usb/input/pid.c
index 19e015d171aa..d9d9f656b8c9 100644
--- a/drivers/usb/input/pid.c
+++ b/drivers/usb/input/pid.c
@@ -259,7 +259,7 @@ static int hid_pid_upload_effect(struct input_dev *dev,
259int hid_pid_init(struct hid_device *hid) 259int hid_pid_init(struct hid_device *hid)
260{ 260{
261 struct hid_ff_pid *private; 261 struct hid_ff_pid *private;
262 struct hid_input *hidinput = list_entry(&hid->inputs, struct hid_input, list); 262 struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
263 struct input_dev *input_dev = hidinput->input; 263 struct input_dev *input_dev = hidinput->input;
264 264
265 private = hid->ff_private = kzalloc(sizeof(struct hid_ff_pid), GFP_KERNEL); 265 private = hid->ff_private = kzalloc(sizeof(struct hid_ff_pid), GFP_KERNEL);
diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c
index 48df4cfd5a42..d3e15df9e815 100644
--- a/drivers/usb/input/wacom.c
+++ b/drivers/usb/input/wacom.c
@@ -95,7 +95,7 @@ MODULE_LICENSE(DRIVER_LICENSE);
95enum { 95enum {
96 PENPARTNER = 0, 96 PENPARTNER = 0,
97 GRAPHIRE, 97 GRAPHIRE,
98 G4, 98 WACOM_G4,
99 PL, 99 PL,
100 INTUOS, 100 INTUOS,
101 INTUOS3, 101 INTUOS3,
@@ -373,7 +373,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs)
373 373
374 case 2: /* Mouse with wheel */ 374 case 2: /* Mouse with wheel */
375 input_report_key(dev, BTN_MIDDLE, data[1] & 0x04); 375 input_report_key(dev, BTN_MIDDLE, data[1] & 0x04);
376 if (wacom->features->type == G4) { 376 if (wacom->features->type == WACOM_G4) {
377 rw = data[7] & 0x04 ? -(data[7] & 0x03) : (data[7] & 0x03); 377 rw = data[7] & 0x04 ? -(data[7] & 0x03) : (data[7] & 0x03);
378 input_report_rel(dev, REL_WHEEL, rw); 378 input_report_rel(dev, REL_WHEEL, rw);
379 } else 379 } else
@@ -385,7 +385,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs)
385 id = CURSOR_DEVICE_ID; 385 id = CURSOR_DEVICE_ID;
386 input_report_key(dev, BTN_LEFT, data[1] & 0x01); 386 input_report_key(dev, BTN_LEFT, data[1] & 0x01);
387 input_report_key(dev, BTN_RIGHT, data[1] & 0x02); 387 input_report_key(dev, BTN_RIGHT, data[1] & 0x02);
388 if (wacom->features->type == G4) 388 if (wacom->features->type == WACOM_G4)
389 input_report_abs(dev, ABS_DISTANCE, data[6]); 389 input_report_abs(dev, ABS_DISTANCE, data[6]);
390 else 390 else
391 input_report_abs(dev, ABS_DISTANCE, data[7]); 391 input_report_abs(dev, ABS_DISTANCE, data[7]);
@@ -410,7 +410,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs)
410 input_sync(dev); 410 input_sync(dev);
411 411
412 /* send pad data */ 412 /* send pad data */
413 if (wacom->features->type == G4) { 413 if (wacom->features->type == WACOM_G4) {
414 /* fist time sending pad data */ 414 /* fist time sending pad data */
415 if (wacom->tool[1] != BTN_TOOL_FINGER) { 415 if (wacom->tool[1] != BTN_TOOL_FINGER) {
416 wacom->id[1] = 0; 416 wacom->id[1] = 0;
@@ -713,8 +713,8 @@ static struct wacom_features wacom_features[] = {
713 { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32, GRAPHIRE, wacom_graphire_irq }, 713 { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32, GRAPHIRE, wacom_graphire_irq },
714 { "Wacom Graphire3", 8, 10208, 7424, 511, 32, GRAPHIRE, wacom_graphire_irq }, 714 { "Wacom Graphire3", 8, 10208, 7424, 511, 32, GRAPHIRE, wacom_graphire_irq },
715 { "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 32, GRAPHIRE, wacom_graphire_irq }, 715 { "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 32, GRAPHIRE, wacom_graphire_irq },
716 { "Wacom Graphire4 4x5", 8, 10208, 7424, 511, 32, G4, wacom_graphire_irq }, 716 { "Wacom Graphire4 4x5", 8, 10208, 7424, 511, 32, WACOM_G4, wacom_graphire_irq },
717 { "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 32, G4, wacom_graphire_irq }, 717 { "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 32, WACOM_G4, wacom_graphire_irq },
718 { "Wacom Volito", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq }, 718 { "Wacom Volito", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq },
719 { "Wacom PenStation2", 8, 3250, 2320, 255, 32, GRAPHIRE, wacom_graphire_irq }, 719 { "Wacom PenStation2", 8, 3250, 2320, 255, 32, GRAPHIRE, wacom_graphire_irq },
720 { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq }, 720 { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq },
@@ -859,7 +859,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
859 input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom->features->pressure_max, 0, 0); 859 input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom->features->pressure_max, 0, 0);
860 860
861 switch (wacom->features->type) { 861 switch (wacom->features->type) {
862 case G4: 862 case WACOM_G4:
863 input_dev->evbit[0] |= BIT(EV_MSC); 863 input_dev->evbit[0] |= BIT(EV_MSC);
864 input_dev->mscbit[0] |= BIT(MSC_SERIAL); 864 input_dev->mscbit[0] |= BIT(MSC_SERIAL);
865 input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); 865 input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER);
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c
index 664139afcfa9..e9f9f4bafa17 100644
--- a/drivers/usb/serial/bus.c
+++ b/drivers/usb/serial/bus.c
@@ -37,11 +37,6 @@ static int usb_serial_device_match (struct device *dev, struct device_driver *dr
37 return 0; 37 return 0;
38} 38}
39 39
40struct bus_type usb_serial_bus_type = {
41 .name = "usb-serial",
42 .match = usb_serial_device_match,
43};
44
45static int usb_serial_device_probe (struct device *dev) 40static int usb_serial_device_probe (struct device *dev)
46{ 41{
47 struct usb_serial_driver *driver; 42 struct usb_serial_driver *driver;
@@ -109,14 +104,18 @@ exit:
109 return retval; 104 return retval;
110} 105}
111 106
107struct bus_type usb_serial_bus_type = {
108 .name = "usb-serial",
109 .match = usb_serial_device_match,
110 .probe = usb_serial_device_probe,
111 .remove = usb_serial_device_remove,
112};
113
112int usb_serial_bus_register(struct usb_serial_driver *driver) 114int usb_serial_bus_register(struct usb_serial_driver *driver)
113{ 115{
114 int retval; 116 int retval;
115 117
116 driver->driver.bus = &usb_serial_bus_type; 118 driver->driver.bus = &usb_serial_bus_type;
117 driver->driver.probe = usb_serial_device_probe;
118 driver->driver.remove = usb_serial_device_remove;
119
120 retval = driver_register(&driver->driver); 119 retval = driver_register(&driver->driver);
121 120
122 return retval; 121 return retval;
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 9ffff1938239..0eb883f44ada 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -43,8 +43,6 @@ static int debug;
43#define PL2303_BUF_SIZE 1024 43#define PL2303_BUF_SIZE 1024
44#define PL2303_TMP_BUF_SIZE 1024 44#define PL2303_TMP_BUF_SIZE 1024
45 45
46static DECLARE_MUTEX(pl2303_tmp_buf_sem);
47
48struct pl2303_buf { 46struct pl2303_buf {
49 unsigned int buf_size; 47 unsigned int buf_size;
50 char *buf_buf; 48 char *buf_buf;
diff --git a/drivers/video/68328fb.c b/drivers/video/68328fb.c
index 3b0ddc55236b..78488bb41aeb 100644
--- a/drivers/video/68328fb.c
+++ b/drivers/video/68328fb.c
@@ -102,8 +102,7 @@ static int mc68x328fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
102 u_int transp, struct fb_info *info); 102 u_int transp, struct fb_info *info);
103static int mc68x328fb_pan_display(struct fb_var_screeninfo *var, 103static int mc68x328fb_pan_display(struct fb_var_screeninfo *var,
104 struct fb_info *info); 104 struct fb_info *info);
105static int mc68x328fb_mmap(struct fb_info *info, struct file *file, 105static int mc68x328fb_mmap(struct fb_info *info, struct vm_area_struct *vma);
106 struct vm_area_struct *vma);
107 106
108static struct fb_ops mc68x328fb_ops = { 107static struct fb_ops mc68x328fb_ops = {
109 .fb_check_var = mc68x328fb_check_var, 108 .fb_check_var = mc68x328fb_check_var,
@@ -398,8 +397,7 @@ static int mc68x328fb_pan_display(struct fb_var_screeninfo *var,
398 * Most drivers don't need their own mmap function 397 * Most drivers don't need their own mmap function
399 */ 398 */
400 399
401static int mc68x328fb_mmap(struct fb_info *info, struct file *file, 400static int mc68x328fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
402 struct vm_area_struct *vma)
403{ 401{
404#ifndef MMU 402#ifndef MMU
405 /* this is uClinux (no MMU) specific code */ 403 /* this is uClinux (no MMU) specific code */
diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c
index 750cebb18306..b058273527bb 100644
--- a/drivers/video/acornfb.c
+++ b/drivers/video/acornfb.c
@@ -883,7 +883,7 @@ acornfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
883 * Note that we are entered with the kernel locked. 883 * Note that we are entered with the kernel locked.
884 */ 884 */
885static int 885static int
886acornfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) 886acornfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
887{ 887{
888 unsigned long off, start; 888 unsigned long off, start;
889 u32 len; 889 u32 len;
diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c
index 0da4083ba908..b2187175d03f 100644
--- a/drivers/video/amba-clcd.c
+++ b/drivers/video/amba-clcd.c
@@ -307,7 +307,7 @@ static int clcdfb_blank(int blank_mode, struct fb_info *info)
307 return 0; 307 return 0;
308} 308}
309 309
310static int clcdfb_mmap(struct fb_info *info, struct file *file, 310static int clcdfb_mmap(struct fb_info *info,
311 struct vm_area_struct *vma) 311 struct vm_area_struct *vma)
312{ 312{
313 struct clcd_fb *fb = to_clcd(info); 313 struct clcd_fb *fb = to_clcd(info);
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
index 2c42a812655a..3033c72dea20 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -1131,9 +1131,7 @@ static void amifb_copyarea(struct fb_info *info,
1131 const struct fb_copyarea *region); 1131 const struct fb_copyarea *region);
1132static void amifb_imageblit(struct fb_info *info, 1132static void amifb_imageblit(struct fb_info *info,
1133 const struct fb_image *image); 1133 const struct fb_image *image);
1134static int amifb_ioctl(struct inode *inode, struct file *file, 1134static int amifb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg);
1135 unsigned int cmd, unsigned long arg,
1136 struct fb_info *info);
1137 1135
1138 1136
1139 /* 1137 /*
@@ -2172,9 +2170,8 @@ static void amifb_imageblit(struct fb_info *info, const struct fb_image *image)
2172 * Amiga Frame Buffer Specific ioctls 2170 * Amiga Frame Buffer Specific ioctls
2173 */ 2171 */
2174 2172
2175static int amifb_ioctl(struct inode *inode, struct file *file, 2173static int amifb_ioctl(struct fb_info *info,
2176 unsigned int cmd, unsigned long arg, 2174 unsigned int cmd, unsigned long arg)
2177 struct fb_info *info)
2178{ 2175{
2179 union { 2176 union {
2180 struct fb_fix_cursorinfo fix; 2177 struct fb_fix_cursorinfo fix;
diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c
index 89060b2db8e5..df8e5667b348 100644
--- a/drivers/video/arcfb.c
+++ b/drivers/video/arcfb.c
@@ -399,9 +399,8 @@ static void arcfb_imageblit(struct fb_info *info, const struct fb_image *image)
399 image->height); 399 image->height);
400} 400}
401 401
402static int arcfb_ioctl(struct inode *inode, struct file *file, 402static int arcfb_ioctl(struct fb_info *info,
403 unsigned int cmd, unsigned long arg, 403 unsigned int cmd, unsigned long arg)
404 struct fb_info *info)
405{ 404{
406 void __user *argp = (void __user *)arg; 405 void __user *argp = (void __user *)arg;
407 struct arcfb_par *par = info->par; 406 struct arcfb_par *par = info->par;
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c
index 15ec1295bc29..e69ab65f7843 100644
--- a/drivers/video/atafb.c
+++ b/drivers/video/atafb.c
@@ -2571,8 +2571,7 @@ atafb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info)
2571} 2571}
2572 2572
2573static int 2573static int
2574atafb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 2574atafb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
2575 unsigned long arg, int con, struct fb_info *info)
2576{ 2575{
2577 switch (cmd) { 2576 switch (cmd) {
2578#ifdef FBCMD_GET_CURRENTPAR 2577#ifdef FBCMD_GET_CURRENTPAR
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index e686185a076d..bfc8a93b2c73 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -431,8 +431,7 @@ static int aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
431static int aty128fb_pan_display(struct fb_var_screeninfo *var, 431static int aty128fb_pan_display(struct fb_var_screeninfo *var,
432 struct fb_info *fb); 432 struct fb_info *fb);
433static int aty128fb_blank(int blank, struct fb_info *fb); 433static int aty128fb_blank(int blank, struct fb_info *fb);
434static int aty128fb_ioctl(struct inode *inode, struct file *file, u_int cmd, 434static int aty128fb_ioctl(struct fb_info *info, u_int cmd, unsigned long arg);
435 u_long arg, struct fb_info *info);
436static int aty128fb_sync(struct fb_info *info); 435static int aty128fb_sync(struct fb_info *info);
437 436
438 /* 437 /*
@@ -2108,8 +2107,7 @@ static int aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
2108/* in param: u32* backlight value: 0 to 15 */ 2107/* in param: u32* backlight value: 0 to 15 */
2109#define FBIO_ATY128_SET_MIRROR _IOW('@', 2, __u32) 2108#define FBIO_ATY128_SET_MIRROR _IOW('@', 2, __u32)
2110 2109
2111static int aty128fb_ioctl(struct inode *inode, struct file *file, u_int cmd, 2110static int aty128fb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
2112 u_long arg, struct fb_info *info)
2113{ 2111{
2114 struct aty128fb_par *par = info->par; 2112 struct aty128fb_par *par = info->par;
2115 u32 value; 2113 u32 value;
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index ed81005cbdba..485be386a8ff 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -238,13 +238,12 @@ static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
238 u_int transp, struct fb_info *info); 238 u_int transp, struct fb_info *info);
239static int atyfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info); 239static int atyfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
240static int atyfb_blank(int blank, struct fb_info *info); 240static int atyfb_blank(int blank, struct fb_info *info);
241static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd, 241static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg);
242 u_long arg, struct fb_info *info);
243extern void atyfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect); 242extern void atyfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
244extern void atyfb_copyarea(struct fb_info *info, const struct fb_copyarea *area); 243extern void atyfb_copyarea(struct fb_info *info, const struct fb_copyarea *area);
245extern void atyfb_imageblit(struct fb_info *info, const struct fb_image *image); 244extern void atyfb_imageblit(struct fb_info *info, const struct fb_image *image);
246#ifdef __sparc__ 245#ifdef __sparc__
247static int atyfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma); 246static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma);
248#endif 247#endif
249static int atyfb_sync(struct fb_info *info); 248static int atyfb_sync(struct fb_info *info);
250 249
@@ -1739,8 +1738,7 @@ struct atyclk {
1739#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32) 1738#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)
1740#endif 1739#endif
1741 1740
1742static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd, 1741static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
1743 u_long arg, struct fb_info *info)
1744{ 1742{
1745 struct atyfb_par *par = (struct atyfb_par *) info->par; 1743 struct atyfb_par *par = (struct atyfb_par *) info->par;
1746#ifdef __sparc__ 1744#ifdef __sparc__
@@ -1845,7 +1843,7 @@ static int atyfb_sync(struct fb_info *info)
1845} 1843}
1846 1844
1847#ifdef __sparc__ 1845#ifdef __sparc__
1848static int atyfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) 1846static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
1849{ 1847{
1850 struct atyfb_par *par = (struct atyfb_par *) info->par; 1848 struct atyfb_par *par = (struct atyfb_par *) info->par;
1851 unsigned int size, page, map_size = 0; 1849 unsigned int size, page, map_size = 0;
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 156db84cb363..c9f0c5a07e6e 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -864,8 +864,8 @@ static int radeonfb_pan_display (struct fb_var_screeninfo *var,
864} 864}
865 865
866 866
867static int radeonfb_ioctl (struct inode *inode, struct file *file, unsigned int cmd, 867static int radeonfb_ioctl (struct fb_info *info, unsigned int cmd,
868 unsigned long arg, struct fb_info *info) 868 unsigned long arg)
869{ 869{
870 struct radeonfb_info *rinfo = info->par; 870 struct radeonfb_info *rinfo = info->par;
871 unsigned int tmp; 871 unsigned int tmp;
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
index a5129806172f..2406899f1207 100644
--- a/drivers/video/au1100fb.c
+++ b/drivers/video/au1100fb.c
@@ -379,7 +379,7 @@ void au1100fb_fb_rotate(struct fb_info *fbi, int angle)
379 * Map video memory in user space. We don't use the generic fb_mmap method mainly 379 * Map video memory in user space. We don't use the generic fb_mmap method mainly
380 * to allow the use of the TLB streaming flag (CCA=6) 380 * to allow the use of the TLB streaming flag (CCA=6)
381 */ 381 */
382int au1100fb_fb_mmap(struct fb_info *fbi, struct file *file, struct vm_area_struct *vma) 382int au1100fb_fb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
383{ 383{
384 struct au1100fb_device *fbdev = to_au1100fb_device(fbi); 384 struct au1100fb_device *fbdev = to_au1100fb_device(fbi);
385 unsigned int len; 385 unsigned int len;
diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c
index 9248fe1fbb1a..c029db4646f6 100644
--- a/drivers/video/bw2.c
+++ b/drivers/video/bw2.c
@@ -35,9 +35,8 @@
35 35
36static int bw2_blank(int, struct fb_info *); 36static int bw2_blank(int, struct fb_info *);
37 37
38static int bw2_mmap(struct fb_info *, struct file *, struct vm_area_struct *); 38static int bw2_mmap(struct fb_info *, struct vm_area_struct *);
39static int bw2_ioctl(struct inode *, struct file *, unsigned int, 39static int bw2_ioctl(struct fb_info *, unsigned int, unsigned long);
40 unsigned long, struct fb_info *);
41 40
42/* 41/*
43 * Frame buffer operations 42 * Frame buffer operations
@@ -169,7 +168,7 @@ static struct sbus_mmap_map bw2_mmap_map[] = {
169 { .size = 0 } 168 { .size = 0 }
170}; 169};
171 170
172static int bw2_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) 171static int bw2_mmap(struct fb_info *info, struct vm_area_struct *vma)
173{ 172{
174 struct bw2_par *par = (struct bw2_par *)info->par; 173 struct bw2_par *par = (struct bw2_par *)info->par;
175 174
@@ -181,8 +180,7 @@ static int bw2_mmap(struct fb_info *info, struct file *file, struct vm_area_stru
181 vma); 180 vma);
182} 181}
183 182
184static int bw2_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 183static int bw2_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
185 unsigned long arg, struct fb_info *info)
186{ 184{
187 struct bw2_par *par = (struct bw2_par *) info->par; 185 struct bw2_par *par = (struct bw2_par *) info->par;
188 186
diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c
index a56147102abb..63b6c79c8a0a 100644
--- a/drivers/video/cg14.c
+++ b/drivers/video/cg14.c
@@ -31,9 +31,8 @@
31static int cg14_setcolreg(unsigned, unsigned, unsigned, unsigned, 31static int cg14_setcolreg(unsigned, unsigned, unsigned, unsigned,
32 unsigned, struct fb_info *); 32 unsigned, struct fb_info *);
33 33
34static int cg14_mmap(struct fb_info *, struct file *, struct vm_area_struct *); 34static int cg14_mmap(struct fb_info *, struct vm_area_struct *);
35static int cg14_ioctl(struct inode *, struct file *, unsigned int, 35static int cg14_ioctl(struct fb_info *, unsigned int, unsigned long);
36 unsigned long, struct fb_info *);
37static int cg14_pan_display(struct fb_var_screeninfo *, struct fb_info *); 36static int cg14_pan_display(struct fb_var_screeninfo *, struct fb_info *);
38 37
39/* 38/*
@@ -268,7 +267,7 @@ static int cg14_setcolreg(unsigned regno,
268 return 0; 267 return 0;
269} 268}
270 269
271static int cg14_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) 270static int cg14_mmap(struct fb_info *info, struct vm_area_struct *vma)
272{ 271{
273 struct cg14_par *par = (struct cg14_par *) info->par; 272 struct cg14_par *par = (struct cg14_par *) info->par;
274 273
@@ -277,8 +276,7 @@ static int cg14_mmap(struct fb_info *info, struct file *file, struct vm_area_str
277 par->iospace, vma); 276 par->iospace, vma);
278} 277}
279 278
280static int cg14_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 279static int cg14_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
281 unsigned long arg, struct fb_info *info)
282{ 280{
283 struct cg14_par *par = (struct cg14_par *) info->par; 281 struct cg14_par *par = (struct cg14_par *) info->par;
284 struct cg14_regs __iomem *regs = par->regs; 282 struct cg14_regs __iomem *regs = par->regs;
diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c
index 9fcd89608ed7..3de6e1b5ab2f 100644
--- a/drivers/video/cg3.c
+++ b/drivers/video/cg3.c
@@ -33,9 +33,8 @@ static int cg3_setcolreg(unsigned, unsigned, unsigned, unsigned,
33 unsigned, struct fb_info *); 33 unsigned, struct fb_info *);
34static int cg3_blank(int, struct fb_info *); 34static int cg3_blank(int, struct fb_info *);
35 35
36static int cg3_mmap(struct fb_info *, struct file *, struct vm_area_struct *); 36static int cg3_mmap(struct fb_info *, struct vm_area_struct *);
37static int cg3_ioctl(struct inode *, struct file *, unsigned int, 37static int cg3_ioctl(struct fb_info *, unsigned int, unsigned long);
38 unsigned long, struct fb_info *);
39 38
40/* 39/*
41 * Frame buffer operations 40 * Frame buffer operations
@@ -230,7 +229,7 @@ static struct sbus_mmap_map cg3_mmap_map[] = {
230 { .size = 0 } 229 { .size = 0 }
231}; 230};
232 231
233static int cg3_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) 232static int cg3_mmap(struct fb_info *info, struct vm_area_struct *vma)
234{ 233{
235 struct cg3_par *par = (struct cg3_par *)info->par; 234 struct cg3_par *par = (struct cg3_par *)info->par;
236 235
@@ -240,8 +239,7 @@ static int cg3_mmap(struct fb_info *info, struct file *file, struct vm_area_stru
240 vma); 239 vma);
241} 240}
242 241
243static int cg3_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 242static int cg3_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
244 unsigned long arg, struct fb_info *info)
245{ 243{
246 struct cg3_par *par = (struct cg3_par *) info->par; 244 struct cg3_par *par = (struct cg3_par *) info->par;
247 245
diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c
index 050835e39aa3..7aab91ead681 100644
--- a/drivers/video/cg6.c
+++ b/drivers/video/cg6.c
@@ -36,9 +36,8 @@ static int cg6_blank(int, struct fb_info *);
36static void cg6_imageblit(struct fb_info *, const struct fb_image *); 36static void cg6_imageblit(struct fb_info *, const struct fb_image *);
37static void cg6_fillrect(struct fb_info *, const struct fb_fillrect *); 37static void cg6_fillrect(struct fb_info *, const struct fb_fillrect *);
38static int cg6_sync(struct fb_info *); 38static int cg6_sync(struct fb_info *);
39static int cg6_mmap(struct fb_info *, struct file *, struct vm_area_struct *); 39static int cg6_mmap(struct fb_info *, struct vm_area_struct *);
40static int cg6_ioctl(struct inode *, struct file *, unsigned int, 40static int cg6_ioctl(struct fb_info *, unsigned int, unsigned long);
41 unsigned long, struct fb_info *);
42 41
43/* 42/*
44 * Frame buffer operations 43 * Frame buffer operations
@@ -524,7 +523,7 @@ static struct sbus_mmap_map cg6_mmap_map[] = {
524 { .size = 0 } 523 { .size = 0 }
525}; 524};
526 525
527static int cg6_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) 526static int cg6_mmap(struct fb_info *info, struct vm_area_struct *vma)
528{ 527{
529 struct cg6_par *par = (struct cg6_par *)info->par; 528 struct cg6_par *par = (struct cg6_par *)info->par;
530 529
@@ -534,8 +533,7 @@ static int cg6_mmap(struct fb_info *info, struct file *file, struct vm_area_stru
534 vma); 533 vma);
535} 534}
536 535
537static int cg6_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 536static int cg6_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
538 unsigned long arg, struct fb_info *info)
539{ 537{
540 struct cg6_par *par = (struct cg6_par *) info->par; 538 struct cg6_par *par = (struct cg6_par *) info->par;
541 539
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c
index 03798e9c882d..655301a8671c 100644
--- a/drivers/video/controlfb.c
+++ b/drivers/video/controlfb.c
@@ -128,7 +128,7 @@ static int controlfb_pan_display(struct fb_var_screeninfo *var,
128static int controlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, 128static int controlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
129 u_int transp, struct fb_info *info); 129 u_int transp, struct fb_info *info);
130static int controlfb_blank(int blank_mode, struct fb_info *info); 130static int controlfb_blank(int blank_mode, struct fb_info *info);
131static int controlfb_mmap(struct fb_info *info, struct file *file, 131static int controlfb_mmap(struct fb_info *info,
132 struct vm_area_struct *vma); 132 struct vm_area_struct *vma);
133static int controlfb_set_par (struct fb_info *info); 133static int controlfb_set_par (struct fb_info *info);
134static int controlfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info); 134static int controlfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info);
@@ -280,7 +280,7 @@ static int controlfb_pan_display(struct fb_var_screeninfo *var,
280 * for controlfb. 280 * for controlfb.
281 * Note there's no locking in here; it's done in fb_mmap() in fbmem.c. 281 * Note there's no locking in here; it's done in fb_mmap() in fbmem.c.
282 */ 282 */
283static int controlfb_mmap(struct fb_info *info, struct file *file, 283static int controlfb_mmap(struct fb_info *info,
284 struct vm_area_struct *vma) 284 struct vm_area_struct *vma)
285{ 285{
286 unsigned long off, start; 286 unsigned long off, start;
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 32a9b69becc5..d2dede6ed3e5 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -957,7 +957,7 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
957 default: 957 default:
958 if (fb->fb_ioctl == NULL) 958 if (fb->fb_ioctl == NULL)
959 return -EINVAL; 959 return -EINVAL;
960 return fb->fb_ioctl(inode, file, cmd, arg, info); 960 return fb->fb_ioctl(info, cmd, arg);
961 } 961 }
962} 962}
963 963
@@ -1107,7 +1107,7 @@ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1107 1107
1108 default: 1108 default:
1109 if (fb->fb_compat_ioctl) 1109 if (fb->fb_compat_ioctl)
1110 ret = fb->fb_compat_ioctl(file, cmd, arg, info); 1110 ret = fb->fb_compat_ioctl(info, cmd, arg);
1111 break; 1111 break;
1112 } 1112 }
1113 unlock_kernel(); 1113 unlock_kernel();
@@ -1135,7 +1135,7 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
1135 if (fb->fb_mmap) { 1135 if (fb->fb_mmap) {
1136 int res; 1136 int res;
1137 lock_kernel(); 1137 lock_kernel();
1138 res = fb->fb_mmap(info, file, vma); 1138 res = fb->fb_mmap(info, vma);
1139 unlock_kernel(); 1139 unlock_kernel();
1140 return res; 1140 return res;
1141 } 1141 }
diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c
index c4870d559afc..9c9b21d469a1 100644
--- a/drivers/video/ffb.c
+++ b/drivers/video/ffb.c
@@ -37,9 +37,8 @@ static void ffb_imageblit(struct fb_info *, const struct fb_image *);
37static void ffb_fillrect(struct fb_info *, const struct fb_fillrect *); 37static void ffb_fillrect(struct fb_info *, const struct fb_fillrect *);
38static void ffb_copyarea(struct fb_info *, const struct fb_copyarea *); 38static void ffb_copyarea(struct fb_info *, const struct fb_copyarea *);
39static int ffb_sync(struct fb_info *); 39static int ffb_sync(struct fb_info *);
40static int ffb_mmap(struct fb_info *, struct file *, struct vm_area_struct *); 40static int ffb_mmap(struct fb_info *, struct vm_area_struct *);
41static int ffb_ioctl(struct inode *, struct file *, unsigned int, 41static int ffb_ioctl(struct fb_info *, unsigned int, unsigned long);
42 unsigned long, struct fb_info *);
43static int ffb_pan_display(struct fb_var_screeninfo *, struct fb_info *); 42static int ffb_pan_display(struct fb_var_screeninfo *, struct fb_info *);
44 43
45/* 44/*
@@ -839,7 +838,7 @@ static struct sbus_mmap_map ffb_mmap_map[] = {
839 { .size = 0 } 838 { .size = 0 }
840}; 839};
841 840
842static int ffb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) 841static int ffb_mmap(struct fb_info *info, struct vm_area_struct *vma)
843{ 842{
844 struct ffb_par *par = (struct ffb_par *)info->par; 843 struct ffb_par *par = (struct ffb_par *)info->par;
845 844
@@ -848,8 +847,7 @@ static int ffb_mmap(struct fb_info *info, struct file *file, struct vm_area_stru
848 0, vma); 847 0, vma);
849} 848}
850 849
851static int ffb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 850static int ffb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
852 unsigned long arg, struct fb_info *info)
853{ 851{
854 struct ffb_par *par = (struct ffb_par *) info->par; 852 struct ffb_par *par = (struct ffb_par *) info->par;
855 853
diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c
index d744c51807b7..38d22729b129 100644
--- a/drivers/video/gbefb.c
+++ b/drivers/video/gbefb.c
@@ -979,7 +979,7 @@ static int gbefb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
979 return 0; 979 return 0;
980} 980}
981 981
982static int gbefb_mmap(struct fb_info *info, struct file *file, 982static int gbefb_mmap(struct fb_info *info,
983 struct vm_area_struct *vma) 983 struct vm_area_struct *vma)
984{ 984{
985 unsigned long size = vma->vm_end - vma->vm_start; 985 unsigned long size = vma->vm_end - vma->vm_start;
@@ -1000,7 +1000,6 @@ static int gbefb_mmap(struct fb_info *info, struct file *file,
1000 pgprot_fb(pgprot_val(vma->vm_page_prot)); 1000 pgprot_fb(pgprot_val(vma->vm_page_prot));
1001 1001
1002 vma->vm_flags |= VM_IO | VM_RESERVED; 1002 vma->vm_flags |= VM_IO | VM_RESERVED;
1003 vma->vm_file = file;
1004 1003
1005 /* look for the starting tile */ 1004 /* look for the starting tile */
1006 tile = &gbe_tiles.cpu[offset >> TILE_SHIFT]; 1005 tile = &gbe_tiles.cpu[offset >> TILE_SHIFT];
diff --git a/drivers/video/geode/gx1fb_core.c b/drivers/video/geode/gx1fb_core.c
index 8e8da7433994..20e69156d728 100644
--- a/drivers/video/geode/gx1fb_core.c
+++ b/drivers/video/geode/gx1fb_core.c
@@ -215,11 +215,11 @@ static int __init gx1fb_map_video_memory(struct fb_info *info, struct pci_dev *d
215 if (ret < 0) 215 if (ret < 0)
216 return ret; 216 return ret;
217 217
218 ret = pci_request_region(dev, 1, "gx1fb (video)"); 218 ret = pci_request_region(dev, 0, "gx1fb (video)");
219 if (ret < 0) 219 if (ret < 0)
220 return ret; 220 return ret;
221 par->vid_regs = ioremap(pci_resource_start(dev, 1), 221 par->vid_regs = ioremap(pci_resource_start(dev, 0),
222 pci_resource_len(dev, 1)); 222 pci_resource_len(dev, 0));
223 if (!par->vid_regs) 223 if (!par->vid_regs)
224 return -ENOMEM; 224 return -ENOMEM;
225 225
@@ -229,12 +229,9 @@ static int __init gx1fb_map_video_memory(struct fb_info *info, struct pci_dev *d
229 if (!par->dc_regs) 229 if (!par->dc_regs)
230 return -ENOMEM; 230 return -ENOMEM;
231 231
232 ret = pci_request_region(dev, 0, "gx1fb (frame buffer)");
233 if (ret < 0 )
234 return -EBUSY;
235 if ((fb_len = gx1_frame_buffer_size()) < 0) 232 if ((fb_len = gx1_frame_buffer_size()) < 0)
236 return -ENOMEM; 233 return -ENOMEM;
237 info->fix.smem_start = pci_resource_start(dev, 0); 234 info->fix.smem_start = gx_base + 0x800000;
238 info->fix.smem_len = fb_len; 235 info->fix.smem_len = fb_len;
239 info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len); 236 info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
240 if (!info->screen_base) 237 if (!info->screen_base)
diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c
index e326f44f652d..6b88050d21bf 100644
--- a/drivers/video/igafb.c
+++ b/drivers/video/igafb.c
@@ -219,7 +219,7 @@ static void iga_blank_border(struct iga_par *par)
219} 219}
220 220
221#ifdef __sparc__ 221#ifdef __sparc__
222static int igafb_mmap(struct fb_info *info, struct file *file, 222static int igafb_mmap(struct fb_info *info,
223 struct vm_area_struct *vma) 223 struct vm_area_struct *vma)
224{ 224{
225 struct iga_par *par = (struct iga_par *)info->par; 225 struct iga_par *par = (struct iga_par *)info->par;
diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c
index a5d813050db5..ad416ae47596 100644
--- a/drivers/video/imsttfb.c
+++ b/drivers/video/imsttfb.c
@@ -1267,8 +1267,7 @@ imsttfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
1267#define FBIMSTT_GETIDXREG 0x545406 1267#define FBIMSTT_GETIDXREG 0x545406
1268 1268
1269static int 1269static int
1270imsttfb_ioctl(struct inode *inode, struct file *file, u_int cmd, 1270imsttfb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
1271 u_long arg, struct fb_info *info)
1272{ 1271{
1273 struct imstt_par *par = info->par; 1272 struct imstt_par *par = info->par;
1274 void __user *argp = (void __user *)arg; 1273 void __user *argp = (void __user *)arg;
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
index 0090544842f5..6b8bd3cdf9c0 100644
--- a/drivers/video/intelfb/intelfbdrv.c
+++ b/drivers/video/intelfb/intelfbdrv.c
@@ -157,9 +157,8 @@ static int intelfb_cursor(struct fb_info *info,
157 157
158static int intelfb_sync(struct fb_info *info); 158static int intelfb_sync(struct fb_info *info);
159 159
160static int intelfb_ioctl(struct inode *inode, struct file *file, 160static int intelfb_ioctl(struct fb_info *info,
161 unsigned int cmd, unsigned long arg, 161 unsigned int cmd, unsigned long arg);
162 struct fb_info *info);
163 162
164static int __devinit intelfb_pci_register(struct pci_dev *pdev, 163static int __devinit intelfb_pci_register(struct pci_dev *pdev,
165 const struct pci_device_id *ent); 164 const struct pci_device_id *ent);
@@ -1380,8 +1379,7 @@ intelfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
1380 1379
1381/* When/if we have our own ioctls. */ 1380/* When/if we have our own ioctls. */
1382static int 1381static int
1383intelfb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 1382intelfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
1384 unsigned long arg, struct fb_info *info)
1385{ 1383{
1386 int retval = 0; 1384 int retval = 0;
1387 1385
diff --git a/drivers/video/kyro/fbdev.c b/drivers/video/kyro/fbdev.c
index bcd359b6d4ff..477ad297de4e 100644
--- a/drivers/video/kyro/fbdev.c
+++ b/drivers/video/kyro/fbdev.c
@@ -586,9 +586,8 @@ static int __init kyrofb_setup(char *options)
586} 586}
587#endif 587#endif
588 588
589static int kyrofb_ioctl(struct inode *inode, struct file *file, 589static int kyrofb_ioctl(struct fb_info *info,
590 unsigned int cmd, unsigned long arg, 590 unsigned int cmd, unsigned long arg)
591 struct fb_info *info)
592{ 591{
593 overlay_create ol_create; 592 overlay_create ol_create;
594 overlay_viewport_set ol_viewport_set; 593 overlay_viewport_set ol_viewport_set;
diff --git a/drivers/video/leo.c b/drivers/video/leo.c
index 494287f8f8bf..a23cfdb9d826 100644
--- a/drivers/video/leo.c
+++ b/drivers/video/leo.c
@@ -32,9 +32,8 @@ static int leo_setcolreg(unsigned, unsigned, unsigned, unsigned,
32 unsigned, struct fb_info *); 32 unsigned, struct fb_info *);
33static int leo_blank(int, struct fb_info *); 33static int leo_blank(int, struct fb_info *);
34 34
35static int leo_mmap(struct fb_info *, struct file *, struct vm_area_struct *); 35static int leo_mmap(struct fb_info *, struct vm_area_struct *);
36static int leo_ioctl(struct inode *, struct file *, unsigned int, 36static int leo_ioctl(struct fb_info *, unsigned int, unsigned long);
37 unsigned long, struct fb_info *);
38static int leo_pan_display(struct fb_var_screeninfo *, struct fb_info *); 37static int leo_pan_display(struct fb_var_screeninfo *, struct fb_info *);
39 38
40/* 39/*
@@ -363,7 +362,7 @@ static struct sbus_mmap_map leo_mmap_map[] = {
363 { .size = 0 } 362 { .size = 0 }
364}; 363};
365 364
366static int leo_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) 365static int leo_mmap(struct fb_info *info, struct vm_area_struct *vma)
367{ 366{
368 struct leo_par *par = (struct leo_par *)info->par; 367 struct leo_par *par = (struct leo_par *)info->par;
369 368
@@ -373,8 +372,7 @@ static int leo_mmap(struct fb_info *info, struct file *file, struct vm_area_stru
373 vma); 372 vma);
374} 373}
375 374
376static int leo_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 375static int leo_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
377 unsigned long arg, struct fb_info *info)
378{ 376{
379 struct leo_par *par = (struct leo_par *) info->par; 377 struct leo_par *par = (struct leo_par *) info->par;
380 378
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index 1e74f4cca53b..4055ff6f5a81 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -865,9 +865,8 @@ static struct matrox_altout panellink_output = {
865 .name = "Panellink output", 865 .name = "Panellink output",
866}; 866};
867 867
868static int matroxfb_ioctl(struct inode *inode, struct file *file, 868static int matroxfb_ioctl(struct fb_info *info,
869 unsigned int cmd, unsigned long arg, 869 unsigned int cmd, unsigned long arg)
870 struct fb_info *info)
871{ 870{
872 void __user *argp = (void __user *)arg; 871 void __user *argp = (void __user *)arg;
873 MINFO_FROM_INFO(info); 872 MINFO_FROM_INFO(info);
diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c
index d52d7d825c41..27eb4bb4f89f 100644
--- a/drivers/video/matrox/matroxfb_crtc2.c
+++ b/drivers/video/matrox/matroxfb_crtc2.c
@@ -419,11 +419,10 @@ static int matroxfb_dh_get_vblank(const struct matroxfb_dh_fb_info* m2info, stru
419 return 0; 419 return 0;
420} 420}
421 421
422static int matroxfb_dh_ioctl(struct inode* inode, 422static int matroxfb_dh_ioctl(struct fb_info *info,
423 struct file* file,
424 unsigned int cmd, 423 unsigned int cmd,
425 unsigned long arg, 424 unsigned long arg)
426 struct fb_info* info) { 425{
427#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon)) 426#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
428 MINFO_FROM(m2info->primary_dev); 427 MINFO_FROM(m2info->primary_dev);
429 428
@@ -457,7 +456,7 @@ static int matroxfb_dh_ioctl(struct inode* inode,
457 case MATROXFB_GET_OUTPUT_MODE: 456 case MATROXFB_GET_OUTPUT_MODE:
458 case MATROXFB_GET_ALL_OUTPUTS: 457 case MATROXFB_GET_ALL_OUTPUTS:
459 { 458 {
460 return ACCESS_FBINFO(fbcon.fbops)->fb_ioctl(inode, file, cmd, arg, &ACCESS_FBINFO(fbcon)); 459 return ACCESS_FBINFO(fbcon.fbops)->fb_ioctl(&ACCESS_FBINFO(fbcon), cmd, arg);
461 } 460 }
462 case MATROXFB_SET_OUTPUT_CONNECTION: 461 case MATROXFB_SET_OUTPUT_CONNECTION:
463 { 462 {
diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c
index a1f2c5e8fc88..6019710dc298 100644
--- a/drivers/video/matrox/matroxfb_maven.c
+++ b/drivers/video/matrox/matroxfb_maven.c
@@ -968,7 +968,7 @@ static inline int maven_compute_timming(struct maven_data* md,
968 return 0; 968 return 0;
969} 969}
970 970
971static inline int maven_program_timming(struct maven_data* md, 971static int maven_program_timming(struct maven_data* md,
972 const struct mavenregs* m) { 972 const struct mavenregs* m) {
973 struct i2c_client* c = md->client; 973 struct i2c_client* c = md->client;
974 974
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c
index e18c9f98a401..747602aa5615 100644
--- a/drivers/video/neofb.c
+++ b/drivers/video/neofb.c
@@ -853,7 +853,7 @@ static int neofb_set_par(struct fb_info *info)
853 /* If the user did not specify any display devices, then... */ 853 /* If the user did not specify any display devices, then... */
854 if (par->PanelDispCntlReg1 == 0x00) { 854 if (par->PanelDispCntlReg1 == 0x00) {
855 /* Default to internal (i.e., LCD) only. */ 855 /* Default to internal (i.e., LCD) only. */
856 par->PanelDispCntlReg1 |= 0x02; 856 par->PanelDispCntlReg1 = vga_rgfx(NULL, 0x20) & 0x03;
857 } 857 }
858 858
859 /* If we are using a fixed mode, then tell the chip we are. */ 859 /* If we are using a fixed mode, then tell the chip we are. */
diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c
index b251e754e16c..0d1957505359 100644
--- a/drivers/video/p9100.c
+++ b/drivers/video/p9100.c
@@ -31,9 +31,8 @@ static int p9100_setcolreg(unsigned, unsigned, unsigned, unsigned,
31 unsigned, struct fb_info *); 31 unsigned, struct fb_info *);
32static int p9100_blank(int, struct fb_info *); 32static int p9100_blank(int, struct fb_info *);
33 33
34static int p9100_mmap(struct fb_info *, struct file *, struct vm_area_struct *); 34static int p9100_mmap(struct fb_info *, struct vm_area_struct *);
35static int p9100_ioctl(struct inode *, struct file *, unsigned int, 35static int p9100_ioctl(struct fb_info *, unsigned int, unsigned long);
36 unsigned long, struct fb_info *);
37 36
38/* 37/*
39 * Frame buffer operations 38 * Frame buffer operations
@@ -222,7 +221,7 @@ static struct sbus_mmap_map p9100_mmap_map[] = {
222 { 0, 0, 0 } 221 { 0, 0, 0 }
223}; 222};
224 223
225static int p9100_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) 224static int p9100_mmap(struct fb_info *info, struct vm_area_struct *vma)
226{ 225{
227 struct p9100_par *par = (struct p9100_par *)info->par; 226 struct p9100_par *par = (struct p9100_par *)info->par;
228 227
@@ -232,8 +231,8 @@ static int p9100_mmap(struct fb_info *info, struct file *file, struct vm_area_st
232 vma); 231 vma);
233} 232}
234 233
235static int p9100_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 234static int p9100_ioctl(struct fb_info *info, unsigned int cmd,
236 unsigned long arg, struct fb_info *info) 235 unsigned long arg)
237{ 236{
238 struct p9100_par *par = (struct p9100_par *) info->par; 237 struct p9100_par *par = (struct p9100_par *) info->par;
239 238
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c
index 2e11b601c488..0e78ddc81583 100644
--- a/drivers/video/pm3fb.c
+++ b/drivers/video/pm3fb.c
@@ -657,9 +657,7 @@ static void pm3fb_set_disp(const void *par, struct display *disp,
657static void pm3fb_detect(void); 657static void pm3fb_detect(void);
658static int pm3fb_pan_display(const struct fb_var_screeninfo *var, 658static int pm3fb_pan_display(const struct fb_var_screeninfo *var,
659 struct fb_info_gen *info); 659 struct fb_info_gen *info);
660static int pm3fb_ioctl(struct inode *inode, struct file *file, 660static int pm3fb_ioctl(struct fb_info *info, u_int cmd, u_long arg);
661 u_int cmd, u_long arg, int con,
662 struct fb_info *info);
663 661
664 662
665/* the struct that hold them together */ 663/* the struct that hold them together */
@@ -3438,9 +3436,7 @@ static int pm3fb_pan_display(const struct fb_var_screeninfo *var,
3438 return 0; 3436 return 0;
3439} 3437}
3440 3438
3441static int pm3fb_ioctl(struct inode *inode, struct file *file, 3439static int pm3fb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
3442 u_int cmd, u_long arg, int con,
3443 struct fb_info *info)
3444{ 3440{
3445 struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info; 3441 struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info;
3446 u32 cm, i; 3442 u32 cm, i;
diff --git a/drivers/video/pmag-aa-fb.c b/drivers/video/pmag-aa-fb.c
index 28d1fe5fe340..d92f352211ef 100644
--- a/drivers/video/pmag-aa-fb.c
+++ b/drivers/video/pmag-aa-fb.c
@@ -299,8 +299,7 @@ static int aafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
299 return -EINVAL; 299 return -EINVAL;
300} 300}
301 301
302static int aafb_ioctl(struct inode *inode, struct file *file, u32 cmd, 302static int aafb_ioctl(struct fb_info *info, u32 cmd, unsigned long arg)
303 unsigned long arg, int con, struct fb_info *info)
304{ 303{
305 /* TODO: Not yet implemented */ 304 /* TODO: Not yet implemented */
306 return -ENOIOCTLCMD; 305 return -ENOIOCTLCMD;
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 9fc10b9e6f57..53ad61f1038c 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -395,7 +395,7 @@ static int pxafb_blank(int blank, struct fb_info *info)
395 return 0; 395 return 0;
396} 396}
397 397
398static int pxafb_mmap(struct fb_info *info, struct file *file, 398static int pxafb_mmap(struct fb_info *info,
399 struct vm_area_struct *vma) 399 struct vm_area_struct *vma)
400{ 400{
401 struct pxafb_info *fbi = (struct pxafb_info *)info; 401 struct pxafb_info *fbi = (struct pxafb_info *)info;
diff --git a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c
index 600318f708f2..db9fb9074dbc 100644
--- a/drivers/video/radeonfb.c
+++ b/drivers/video/radeonfb.c
@@ -1497,8 +1497,8 @@ static int radeonfb_pan_display (struct fb_var_screeninfo *var,
1497} 1497}
1498 1498
1499 1499
1500static int radeonfb_ioctl (struct inode *inode, struct file *file, unsigned int cmd, 1500static int radeonfb_ioctl (struct fb_info *info, unsigned int cmd,
1501 unsigned long arg, struct fb_info *info) 1501 unsigned long arg)
1502{ 1502{
1503 struct radeonfb_info *rinfo = (struct radeonfb_info *) info; 1503 struct radeonfb_info *rinfo = (struct radeonfb_info *) info;
1504 unsigned int tmp; 1504 unsigned int tmp;
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index 087e58689e4c..8a893ce7040d 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -815,7 +815,7 @@ static int sa1100fb_blank(int blank, struct fb_info *info)
815 return 0; 815 return 0;
816} 816}
817 817
818static int sa1100fb_mmap(struct fb_info *info, struct file *file, 818static int sa1100fb_mmap(struct fb_info *info,
819 struct vm_area_struct *vma) 819 struct vm_area_struct *vma)
820{ 820{
821 struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; 821 struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c
index 7054660767e4..2e6df1fcb2b9 100644
--- a/drivers/video/sgivwfb.c
+++ b/drivers/video/sgivwfb.c
@@ -115,7 +115,7 @@ static int sgivwfb_set_par(struct fb_info *info);
115static int sgivwfb_setcolreg(u_int regno, u_int red, u_int green, 115static int sgivwfb_setcolreg(u_int regno, u_int red, u_int green,
116 u_int blue, u_int transp, 116 u_int blue, u_int transp,
117 struct fb_info *info); 117 struct fb_info *info);
118static int sgivwfb_mmap(struct fb_info *info, struct file *file, 118static int sgivwfb_mmap(struct fb_info *info,
119 struct vm_area_struct *vma); 119 struct vm_area_struct *vma);
120 120
121static struct fb_ops sgivwfb_ops = { 121static struct fb_ops sgivwfb_ops = {
@@ -706,7 +706,7 @@ static int sgivwfb_setcolreg(u_int regno, u_int red, u_int green,
706 return 0; 706 return 0;
707} 707}
708 708
709static int sgivwfb_mmap(struct fb_info *info, struct file *file, 709static int sgivwfb_mmap(struct fb_info *info,
710 struct vm_area_struct *vma) 710 struct vm_area_struct *vma)
711{ 711{
712 unsigned long size = vma->vm_end - vma->vm_start; 712 unsigned long size = vma->vm_end - vma->vm_start;
@@ -723,7 +723,6 @@ static int sgivwfb_mmap(struct fb_info *info, struct file *file,
723 if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT, 723 if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT,
724 size, vma->vm_page_prot)) 724 size, vma->vm_page_prot))
725 return -EAGAIN; 725 return -EAGAIN;
726 vma->vm_file = file;
727 printk(KERN_DEBUG "sgivwfb: mmap framebuffer P(%lx)->V(%lx)\n", 726 printk(KERN_DEBUG "sgivwfb: mmap framebuffer P(%lx)->V(%lx)\n",
728 offset, vma->vm_start); 727 offset, vma->vm_start);
729 return 0; 728 return 0;
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index dea1a46c67c4..8adf5bf91eee 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -1743,13 +1743,14 @@ sisfb_blank(int blank, struct fb_info *info)
1743 1743
1744/* ----------- FBDev related routines for all series ---------- */ 1744/* ----------- FBDev related routines for all series ---------- */
1745 1745
1746static int 1746#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
1747sisfb_ioctl(struct inode *inode, struct file *file, 1747static int sisfb_ioctl(struct fb_info *info, unsigned int cmd,
1748 unsigned int cmd, unsigned long arg, 1748 unsigned long arg)
1749#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) 1749#else
1750 int con, 1750static int sisfb_ioctl(struct inode *inode, struct file *file,
1751 unsigned int cmd, unsigned long arg,
1752 struct fb_info *info)
1751#endif 1753#endif
1752 struct fb_info *info)
1753{ 1754{
1754 struct sis_video_info *ivideo = (struct sis_video_info *)info->par; 1755 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1755 struct sis_memreq sismemreq; 1756 struct sis_memreq sismemreq;
@@ -1924,19 +1925,6 @@ sisfb_ioctl(struct inode *inode, struct file *file,
1924 return 0; 1925 return 0;
1925} 1926}
1926 1927
1927#ifdef SIS_NEW_CONFIG_COMPAT
1928static long
1929sisfb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg, struct fb_info *info)
1930{
1931 int ret;
1932
1933 lock_kernel();
1934 ret = sisfb_ioctl(NULL, f, cmd, arg, info);
1935 unlock_kernel();
1936 return ret;
1937}
1938#endif
1939
1940static int 1928static int
1941sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info) 1929sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
1942{ 1930{
@@ -2007,7 +1995,7 @@ static struct fb_ops sisfb_ops = {
2007#endif 1995#endif
2008 .fb_sync = fbcon_sis_sync, 1996 .fb_sync = fbcon_sis_sync,
2009#ifdef SIS_NEW_CONFIG_COMPAT 1997#ifdef SIS_NEW_CONFIG_COMPAT
2010 .fb_compat_ioctl= sisfb_compat_ioctl, 1998 .fb_compat_ioctl= sisfb_ioctl,
2011#endif 1999#endif
2012 .fb_ioctl = sisfb_ioctl 2000 .fb_ioctl = sisfb_ioctl
2013}; 2001};
diff --git a/drivers/video/sis/sis_main.h b/drivers/video/sis/sis_main.h
index 445bcbba03ae..70b6df371b8e 100644
--- a/drivers/video/sis/sis_main.h
+++ b/drivers/video/sis/sis_main.h
@@ -727,9 +727,14 @@ static int sisfb_ioctl(struct inode *inode, struct file *file,
727#endif 727#endif
728 728
729#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) 729#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
730#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
731static int sisfb_ioctl(struct fb_info *info, unsigned int cmd,
732 unsigned long arg);
733#else
730static int sisfb_ioctl(struct inode *inode, struct file *file, 734static int sisfb_ioctl(struct inode *inode, struct file *file,
731 unsigned int cmd, unsigned long arg, 735 unsigned int cmd, unsigned long arg,
732 struct fb_info *info); 736 struct fb_info *info);
737#endif
733static int sisfb_set_par(struct fb_info *info); 738static int sisfb_set_par(struct fb_info *info);
734static int sisfb_blank(int blank, 739static int sisfb_blank(int blank,
735 struct fb_info *info); 740 struct fb_info *info);
diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c
index 8a5ce210bb27..99921df35474 100644
--- a/drivers/video/sstfb.c
+++ b/drivers/video/sstfb.c
@@ -771,8 +771,7 @@ static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
771 return 0; 771 return 0;
772} 772}
773 773
774static int sstfb_ioctl(struct inode *inode, struct file *file, 774static int sstfb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
775 u_int cmd, u_long arg, struct fb_info *info )
776{ 775{
777 struct sstfb_par *par = info->par; 776 struct sstfb_par *par = info->par;
778 struct pci_dev *sst_dev = par->dev; 777 struct pci_dev *sst_dev = par->dev;
diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c
index 2b27b4474001..95b918229d9b 100644
--- a/drivers/video/tcx.c
+++ b/drivers/video/tcx.c
@@ -33,9 +33,8 @@ static int tcx_setcolreg(unsigned, unsigned, unsigned, unsigned,
33 unsigned, struct fb_info *); 33 unsigned, struct fb_info *);
34static int tcx_blank(int, struct fb_info *); 34static int tcx_blank(int, struct fb_info *);
35 35
36static int tcx_mmap(struct fb_info *, struct file *, struct vm_area_struct *); 36static int tcx_mmap(struct fb_info *, struct vm_area_struct *);
37static int tcx_ioctl(struct inode *, struct file *, unsigned int, 37static int tcx_ioctl(struct fb_info *, unsigned int, unsigned long);
38 unsigned long, struct fb_info *);
39static int tcx_pan_display(struct fb_var_screeninfo *, struct fb_info *); 38static int tcx_pan_display(struct fb_var_screeninfo *, struct fb_info *);
40 39
41/* 40/*
@@ -302,7 +301,7 @@ static struct sbus_mmap_map __tcx_mmap_map[TCX_MMAP_ENTRIES] = {
302 { .size = 0 } 301 { .size = 0 }
303}; 302};
304 303
305static int tcx_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) 304static int tcx_mmap(struct fb_info *info, struct vm_area_struct *vma)
306{ 305{
307 struct tcx_par *par = (struct tcx_par *)info->par; 306 struct tcx_par *par = (struct tcx_par *)info->par;
308 307
@@ -312,8 +311,8 @@ static int tcx_mmap(struct fb_info *info, struct file *file, struct vm_area_stru
312 vma); 311 vma);
313} 312}
314 313
315static int tcx_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 314static int tcx_ioctl(struct fb_info *info, unsigned int cmd,
316 unsigned long arg, struct fb_info *info) 315 unsigned long arg)
317{ 316{
318 struct tcx_par *par = (struct tcx_par *) info->par; 317 struct tcx_par *par = (struct tcx_par *) info->par;
319 318
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c
index ffa1ad474226..53208cb58396 100644
--- a/drivers/video/vfb.c
+++ b/drivers/video/vfb.c
@@ -81,7 +81,7 @@ static int vfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
81 u_int transp, struct fb_info *info); 81 u_int transp, struct fb_info *info);
82static int vfb_pan_display(struct fb_var_screeninfo *var, 82static int vfb_pan_display(struct fb_var_screeninfo *var,
83 struct fb_info *info); 83 struct fb_info *info);
84static int vfb_mmap(struct fb_info *info, struct file *file, 84static int vfb_mmap(struct fb_info *info,
85 struct vm_area_struct *vma); 85 struct vm_area_struct *vma);
86 86
87static struct fb_ops vfb_ops = { 87static struct fb_ops vfb_ops = {
@@ -368,7 +368,7 @@ static int vfb_pan_display(struct fb_var_screeninfo *var,
368 * Most drivers don't need their own mmap function 368 * Most drivers don't need their own mmap function
369 */ 369 */
370 370
371static int vfb_mmap(struct fb_info *info, struct file *file, 371static int vfb_mmap(struct fb_info *info,
372 struct vm_area_struct *vma) 372 struct vm_area_struct *vma)
373{ 373{
374 return -EINVAL; 374 return -EINVAL;
diff --git a/drivers/zorro/zorro-driver.c b/drivers/zorro/zorro-driver.c
index ccba227676f2..fcbee748c592 100644
--- a/drivers/zorro/zorro-driver.c
+++ b/drivers/zorro/zorro-driver.c
@@ -77,7 +77,6 @@ int zorro_register_driver(struct zorro_driver *drv)
77 /* initialize common driver fields */ 77 /* initialize common driver fields */
78 drv->driver.name = drv->name; 78 drv->driver.name = drv->name;
79 drv->driver.bus = &zorro_bus_type; 79 drv->driver.bus = &zorro_bus_type;
80 drv->driver.probe = zorro_device_probe;
81 80
82 /* register with core */ 81 /* register with core */
83 count = driver_register(&drv->driver); 82 count = driver_register(&drv->driver);
@@ -132,7 +131,8 @@ static int zorro_bus_match(struct device *dev, struct device_driver *drv)
132 131
133struct bus_type zorro_bus_type = { 132struct bus_type zorro_bus_type = {
134 .name = "zorro", 133 .name = "zorro",
135 .match = zorro_bus_match 134 .match = zorro_bus_match,
135 .probe = zorro_device_probe,
136}; 136};
137 137
138 138
diff --git a/fs/9p/conv.c b/fs/9p/conv.c
index 55ccfa10ee9e..32a9f99154e2 100644
--- a/fs/9p/conv.c
+++ b/fs/9p/conv.c
@@ -56,7 +56,7 @@ static inline int buf_check_overflow(struct cbuf *buf)
56 return buf->p > buf->ep; 56 return buf->p > buf->ep;
57} 57}
58 58
59static inline int buf_check_size(struct cbuf *buf, int len) 59static int buf_check_size(struct cbuf *buf, int len)
60{ 60{
61 if (buf->p + len > buf->ep) { 61 if (buf->p + len > buf->ep) {
62 if (buf->p < buf->ep) { 62 if (buf->p < buf->ep) {
@@ -72,7 +72,7 @@ static inline int buf_check_size(struct cbuf *buf, int len)
72 return 1; 72 return 1;
73} 73}
74 74
75static inline void *buf_alloc(struct cbuf *buf, int len) 75static void *buf_alloc(struct cbuf *buf, int len)
76{ 76{
77 void *ret = NULL; 77 void *ret = NULL;
78 78
@@ -84,7 +84,7 @@ static inline void *buf_alloc(struct cbuf *buf, int len)
84 return ret; 84 return ret;
85} 85}
86 86
87static inline void buf_put_int8(struct cbuf *buf, u8 val) 87static void buf_put_int8(struct cbuf *buf, u8 val)
88{ 88{
89 if (buf_check_size(buf, 1)) { 89 if (buf_check_size(buf, 1)) {
90 buf->p[0] = val; 90 buf->p[0] = val;
@@ -92,7 +92,7 @@ static inline void buf_put_int8(struct cbuf *buf, u8 val)
92 } 92 }
93} 93}
94 94
95static inline void buf_put_int16(struct cbuf *buf, u16 val) 95static void buf_put_int16(struct cbuf *buf, u16 val)
96{ 96{
97 if (buf_check_size(buf, 2)) { 97 if (buf_check_size(buf, 2)) {
98 *(__le16 *) buf->p = cpu_to_le16(val); 98 *(__le16 *) buf->p = cpu_to_le16(val);
@@ -100,7 +100,7 @@ static inline void buf_put_int16(struct cbuf *buf, u16 val)
100 } 100 }
101} 101}
102 102
103static inline void buf_put_int32(struct cbuf *buf, u32 val) 103static void buf_put_int32(struct cbuf *buf, u32 val)
104{ 104{
105 if (buf_check_size(buf, 4)) { 105 if (buf_check_size(buf, 4)) {
106 *(__le32 *)buf->p = cpu_to_le32(val); 106 *(__le32 *)buf->p = cpu_to_le32(val);
@@ -108,7 +108,7 @@ static inline void buf_put_int32(struct cbuf *buf, u32 val)
108 } 108 }
109} 109}
110 110
111static inline void buf_put_int64(struct cbuf *buf, u64 val) 111static void buf_put_int64(struct cbuf *buf, u64 val)
112{ 112{
113 if (buf_check_size(buf, 8)) { 113 if (buf_check_size(buf, 8)) {
114 *(__le64 *)buf->p = cpu_to_le64(val); 114 *(__le64 *)buf->p = cpu_to_le64(val);
@@ -116,7 +116,7 @@ static inline void buf_put_int64(struct cbuf *buf, u64 val)
116 } 116 }
117} 117}
118 118
119static inline void buf_put_stringn(struct cbuf *buf, const char *s, u16 slen) 119static void buf_put_stringn(struct cbuf *buf, const char *s, u16 slen)
120{ 120{
121 if (buf_check_size(buf, slen + 2)) { 121 if (buf_check_size(buf, slen + 2)) {
122 buf_put_int16(buf, slen); 122 buf_put_int16(buf, slen);
@@ -130,7 +130,7 @@ static inline void buf_put_string(struct cbuf *buf, const char *s)
130 buf_put_stringn(buf, s, strlen(s)); 130 buf_put_stringn(buf, s, strlen(s));
131} 131}
132 132
133static inline u8 buf_get_int8(struct cbuf *buf) 133static u8 buf_get_int8(struct cbuf *buf)
134{ 134{
135 u8 ret = 0; 135 u8 ret = 0;
136 136
@@ -142,7 +142,7 @@ static inline u8 buf_get_int8(struct cbuf *buf)
142 return ret; 142 return ret;
143} 143}
144 144
145static inline u16 buf_get_int16(struct cbuf *buf) 145static u16 buf_get_int16(struct cbuf *buf)
146{ 146{
147 u16 ret = 0; 147 u16 ret = 0;
148 148
@@ -154,7 +154,7 @@ static inline u16 buf_get_int16(struct cbuf *buf)
154 return ret; 154 return ret;
155} 155}
156 156
157static inline u32 buf_get_int32(struct cbuf *buf) 157static u32 buf_get_int32(struct cbuf *buf)
158{ 158{
159 u32 ret = 0; 159 u32 ret = 0;
160 160
@@ -166,7 +166,7 @@ static inline u32 buf_get_int32(struct cbuf *buf)
166 return ret; 166 return ret;
167} 167}
168 168
169static inline u64 buf_get_int64(struct cbuf *buf) 169static u64 buf_get_int64(struct cbuf *buf)
170{ 170{
171 u64 ret = 0; 171 u64 ret = 0;
172 172
@@ -178,7 +178,7 @@ static inline u64 buf_get_int64(struct cbuf *buf)
178 return ret; 178 return ret;
179} 179}
180 180
181static inline void buf_get_str(struct cbuf *buf, struct v9fs_str *vstr) 181static void buf_get_str(struct cbuf *buf, struct v9fs_str *vstr)
182{ 182{
183 vstr->len = buf_get_int16(buf); 183 vstr->len = buf_get_int16(buf);
184 if (!buf_check_overflow(buf) && buf_check_size(buf, vstr->len)) { 184 if (!buf_check_overflow(buf) && buf_check_size(buf, vstr->len)) {
@@ -190,7 +190,7 @@ static inline void buf_get_str(struct cbuf *buf, struct v9fs_str *vstr)
190 } 190 }
191} 191}
192 192
193static inline void buf_get_qid(struct cbuf *bufp, struct v9fs_qid *qid) 193static void buf_get_qid(struct cbuf *bufp, struct v9fs_qid *qid)
194{ 194{
195 qid->type = buf_get_int8(bufp); 195 qid->type = buf_get_int8(bufp);
196 qid->version = buf_get_int32(bufp); 196 qid->version = buf_get_int32(bufp);
@@ -254,7 +254,7 @@ static int v9fs_size_wstat(struct v9fs_wstat *wstat, int extended)
254 * 254 *
255 */ 255 */
256 256
257static inline void 257static void
258buf_get_stat(struct cbuf *bufp, struct v9fs_stat *stat, int extended) 258buf_get_stat(struct cbuf *bufp, struct v9fs_stat *stat, int extended)
259{ 259{
260 stat->size = buf_get_int16(bufp); 260 stat->size = buf_get_int16(bufp);
@@ -427,7 +427,7 @@ static inline void v9fs_put_int64(struct cbuf *bufp, u64 val, u64 * p)
427 buf_put_int64(bufp, val); 427 buf_put_int64(bufp, val);
428} 428}
429 429
430static inline void 430static void
431v9fs_put_str(struct cbuf *bufp, char *data, struct v9fs_str *str) 431v9fs_put_str(struct cbuf *bufp, char *data, struct v9fs_str *str)
432{ 432{
433 if (data) { 433 if (data) {
@@ -441,7 +441,7 @@ v9fs_put_str(struct cbuf *bufp, char *data, struct v9fs_str *str)
441 buf_put_stringn(bufp, data, str->len); 441 buf_put_stringn(bufp, data, str->len);
442} 442}
443 443
444static inline int 444static int
445v9fs_put_user_data(struct cbuf *bufp, const char __user * data, int count, 445v9fs_put_user_data(struct cbuf *bufp, const char __user * data, int count,
446 unsigned char **pdata) 446 unsigned char **pdata)
447{ 447{
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index e93a7ae467c9..62d8d4acb8bb 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -195,6 +195,8 @@ static int autofs4_dir_open(struct inode *inode, struct file *file)
195 if (!empty) 195 if (!empty)
196 d_invalidate(dentry); 196 d_invalidate(dentry);
197 197
198 nd.dentry = dentry;
199 nd.mnt = mnt;
198 nd.flags = LOOKUP_DIRECTORY; 200 nd.flags = LOOKUP_DIRECTORY;
199 status = (dentry->d_op->d_revalidate)(dentry, &nd); 201 status = (dentry->d_op->d_revalidate)(dentry, &nd);
200 202
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index f979ebbce49c..1b117a441298 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1218,7 +1218,7 @@ static int writenote(struct memelfnote *men, struct file *file)
1218 if (!dump_seek(file, (off))) \ 1218 if (!dump_seek(file, (off))) \
1219 goto end_coredump; 1219 goto end_coredump;
1220 1220
1221static inline void fill_elf_header(struct elfhdr *elf, int segs) 1221static void fill_elf_header(struct elfhdr *elf, int segs)
1222{ 1222{
1223 memcpy(elf->e_ident, ELFMAG, SELFMAG); 1223 memcpy(elf->e_ident, ELFMAG, SELFMAG);
1224 elf->e_ident[EI_CLASS] = ELF_CLASS; 1224 elf->e_ident[EI_CLASS] = ELF_CLASS;
@@ -1243,7 +1243,7 @@ static inline void fill_elf_header(struct elfhdr *elf, int segs)
1243 return; 1243 return;
1244} 1244}
1245 1245
1246static inline void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset) 1246static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset)
1247{ 1247{
1248 phdr->p_type = PT_NOTE; 1248 phdr->p_type = PT_NOTE;
1249 phdr->p_offset = offset; 1249 phdr->p_offset = offset;
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index 9ccc7d8275b8..6a7b730c206b 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -264,7 +264,7 @@ static int unquote(char *from)
264 return p - from; 264 return p - from;
265} 265}
266 266
267static inline char * check_special_flags (char * sfs, Node * e) 267static char * check_special_flags (char * sfs, Node * e)
268{ 268{
269 char * p = sfs; 269 char * p = sfs;
270 int cont = 1; 270 int cont = 1;
diff --git a/fs/bio.c b/fs/bio.c
index 7b3069589951..bbc442b8c867 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -123,7 +123,7 @@ static void bio_fs_destructor(struct bio *bio)
123 bio_free(bio, fs_bio_set); 123 bio_free(bio, fs_bio_set);
124} 124}
125 125
126inline void bio_init(struct bio *bio) 126void bio_init(struct bio *bio)
127{ 127{
128 bio->bi_next = NULL; 128 bio->bi_next = NULL;
129 bio->bi_bdev = NULL; 129 bio->bi_bdev = NULL;
@@ -253,7 +253,7 @@ inline int bio_hw_segments(request_queue_t *q, struct bio *bio)
253 * the actual data it points to. Reference count of returned 253 * the actual data it points to. Reference count of returned
254 * bio will be one. 254 * bio will be one.
255 */ 255 */
256inline void __bio_clone(struct bio *bio, struct bio *bio_src) 256void __bio_clone(struct bio *bio, struct bio *bio_src)
257{ 257{
258 request_queue_t *q = bdev_get_queue(bio_src->bi_bdev); 258 request_queue_t *q = bdev_get_queue(bio_src->bi_bdev);
259 259
diff --git a/fs/buffer.c b/fs/buffer.c
index b9bb7ad6897b..7cdf48a9a501 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1165,7 +1165,7 @@ failed:
1165 * some of those buffers may be aliases of filesystem data. 1165 * some of those buffers may be aliases of filesystem data.
1166 * grow_dev_page() will go BUG() if this happens. 1166 * grow_dev_page() will go BUG() if this happens.
1167 */ 1167 */
1168static inline int 1168static int
1169grow_buffers(struct block_device *bdev, sector_t block, int size) 1169grow_buffers(struct block_device *bdev, sector_t block, int size)
1170{ 1170{
1171 struct page *page; 1171 struct page *page;
@@ -1391,7 +1391,7 @@ static void bh_lru_install(struct buffer_head *bh)
1391/* 1391/*
1392 * Look up the bh in this cpu's LRU. If it's there, move it to the head. 1392 * Look up the bh in this cpu's LRU. If it's there, move it to the head.
1393 */ 1393 */
1394static inline struct buffer_head * 1394static struct buffer_head *
1395lookup_bh_lru(struct block_device *bdev, sector_t block, int size) 1395lookup_bh_lru(struct block_device *bdev, sector_t block, int size)
1396{ 1396{
1397 struct buffer_head *ret = NULL; 1397 struct buffer_head *ret = NULL;
@@ -1541,7 +1541,7 @@ EXPORT_SYMBOL(set_bh_page);
1541/* 1541/*
1542 * Called when truncating a buffer on a page completely. 1542 * Called when truncating a buffer on a page completely.
1543 */ 1543 */
1544static inline void discard_buffer(struct buffer_head * bh) 1544static void discard_buffer(struct buffer_head * bh)
1545{ 1545{
1546 lock_buffer(bh); 1546 lock_buffer(bh);
1547 clear_buffer_dirty(bh); 1547 clear_buffer_dirty(bh);
diff --git a/fs/char_dev.c b/fs/char_dev.c
index 3b1b1eefdbb0..21195c481637 100644
--- a/fs/char_dev.c
+++ b/fs/char_dev.c
@@ -35,7 +35,7 @@ static struct char_device_struct {
35 unsigned int major; 35 unsigned int major;
36 unsigned int baseminor; 36 unsigned int baseminor;
37 int minorct; 37 int minorct;
38 const char *name; 38 char name[64];
39 struct file_operations *fops; 39 struct file_operations *fops;
40 struct cdev *cdev; /* will die */ 40 struct cdev *cdev; /* will die */
41} *chrdevs[MAX_PROBE_HASH]; 41} *chrdevs[MAX_PROBE_HASH];
@@ -46,34 +46,84 @@ static inline int major_to_index(int major)
46 return major % MAX_PROBE_HASH; 46 return major % MAX_PROBE_HASH;
47} 47}
48 48
49/* get char device names in somewhat random order */ 49struct chrdev_info {
50int get_chrdev_list(char *page) 50 int index;
51{
52 struct char_device_struct *cd; 51 struct char_device_struct *cd;
53 int i, len; 52};
54 53
55 len = sprintf(page, "Character devices:\n"); 54void *get_next_chrdev(void *dev)
55{
56 struct chrdev_info *info;
56 57
58 if (dev == NULL) {
59 info = kmalloc(sizeof(*info), GFP_KERNEL);
60 if (!info)
61 goto out;
62 info->index=0;
63 info->cd = chrdevs[info->index];
64 if (info->cd)
65 goto out;
66 } else {
67 info = dev;
68 }
69
70 while (info->index < ARRAY_SIZE(chrdevs)) {
71 if (info->cd)
72 info->cd = info->cd->next;
73 if (info->cd)
74 goto out;
75 /*
76 * No devices on this chain, move to the next
77 */
78 info->index++;
79 info->cd = (info->index < ARRAY_SIZE(chrdevs)) ?
80 chrdevs[info->index] : NULL;
81 if (info->cd)
82 goto out;
83 }
84
85out:
86 return info;
87}
88
89void *acquire_chrdev_list(void)
90{
57 down(&chrdevs_lock); 91 down(&chrdevs_lock);
92 return get_next_chrdev(NULL);
93}
94
95void release_chrdev_list(void *dev)
96{
97 up(&chrdevs_lock);
98 kfree(dev);
99}
100
101
102int count_chrdev_list(void)
103{
104 struct char_device_struct *cd;
105 int i, count;
106
107 count = 0;
108
58 for (i = 0; i < ARRAY_SIZE(chrdevs) ; i++) { 109 for (i = 0; i < ARRAY_SIZE(chrdevs) ; i++) {
59 for (cd = chrdevs[i]; cd; cd = cd->next) { 110 for (cd = chrdevs[i]; cd; cd = cd->next)
60 /* 111 count++;
61 * if the current name, plus the 5 extra characters
62 * in the device line for this entry
63 * would run us off the page, we're done
64 */
65 if ((len+strlen(cd->name) + 5) >= PAGE_SIZE)
66 goto page_full;
67
68
69 len += sprintf(page+len, "%3d %s\n",
70 cd->major, cd->name);
71 }
72 } 112 }
73page_full:
74 up(&chrdevs_lock);
75 113
76 return len; 114 return count;
115}
116
117int get_chrdev_info(void *dev, int *major, char **name)
118{
119 struct chrdev_info *info = dev;
120
121 if (info->cd == NULL)
122 return 1;
123
124 *major = info->cd->major;
125 *name = info->cd->name;
126 return 0;
77} 127}
78 128
79/* 129/*
@@ -121,7 +171,7 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor,
121 cd->major = major; 171 cd->major = major;
122 cd->baseminor = baseminor; 172 cd->baseminor = baseminor;
123 cd->minorct = minorct; 173 cd->minorct = minorct;
124 cd->name = name; 174 strncpy(cd->name,name, 64);
125 175
126 i = major_to_index(major); 176 i = major_to_index(major);
127 177
diff --git a/fs/compat.c b/fs/compat.c
index 271b75d1597f..2468ac1df2f0 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1537,7 +1537,7 @@ out_ret:
1537 * Ooo, nasty. We need here to frob 32-bit unsigned longs to 1537 * Ooo, nasty. We need here to frob 32-bit unsigned longs to
1538 * 64-bit unsigned longs. 1538 * 64-bit unsigned longs.
1539 */ 1539 */
1540static inline 1540static
1541int compat_get_fd_set(unsigned long nr, compat_ulong_t __user *ufdset, 1541int compat_get_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
1542 unsigned long *fdset) 1542 unsigned long *fdset)
1543{ 1543{
@@ -1570,7 +1570,7 @@ int compat_get_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
1570 return 0; 1570 return 0;
1571} 1571}
1572 1572
1573static inline 1573static
1574void compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset, 1574void compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
1575 unsigned long *fdset) 1575 unsigned long *fdset)
1576{ 1576{
diff --git a/fs/dcache.c b/fs/dcache.c
index 134d6775183f..86bdb93789c6 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -94,7 +94,7 @@ static void d_free(struct dentry *dentry)
94 * d_iput() operation if defined. 94 * d_iput() operation if defined.
95 * Called with dcache_lock and per dentry lock held, drops both. 95 * Called with dcache_lock and per dentry lock held, drops both.
96 */ 96 */
97static inline void dentry_iput(struct dentry * dentry) 97static void dentry_iput(struct dentry * dentry)
98{ 98{
99 struct inode *inode = dentry->d_inode; 99 struct inode *inode = dentry->d_inode;
100 if (inode) { 100 if (inode) {
diff --git a/fs/exec.c b/fs/exec.c
index b5bcf1aae0ab..62b40af68cc4 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -575,7 +575,7 @@ static int exec_mmap(struct mm_struct *mm)
575 * disturbing other processes. (Other processes might share the signal 575 * disturbing other processes. (Other processes might share the signal
576 * table via the CLONE_SIGHAND option to clone().) 576 * table via the CLONE_SIGHAND option to clone().)
577 */ 577 */
578static inline int de_thread(struct task_struct *tsk) 578static int de_thread(struct task_struct *tsk)
579{ 579{
580 struct signal_struct *sig = tsk->signal; 580 struct signal_struct *sig = tsk->signal;
581 struct sighand_struct *newsighand, *oldsighand = tsk->sighand; 581 struct sighand_struct *newsighand, *oldsighand = tsk->sighand;
@@ -780,7 +780,7 @@ no_thread_group:
780 * so that a new one can be started 780 * so that a new one can be started
781 */ 781 */
782 782
783static inline void flush_old_files(struct files_struct * files) 783static void flush_old_files(struct files_struct * files)
784{ 784{
785 long j = -1; 785 long j = -1;
786 struct fdtable *fdt; 786 struct fdtable *fdt;
@@ -964,7 +964,7 @@ int prepare_binprm(struct linux_binprm *bprm)
964 964
965EXPORT_SYMBOL(prepare_binprm); 965EXPORT_SYMBOL(prepare_binprm);
966 966
967static inline int unsafe_exec(struct task_struct *p) 967static int unsafe_exec(struct task_struct *p)
968{ 968{
969 int unsafe = 0; 969 int unsafe = 0;
970 if (p->ptrace & PT_PTRACED) { 970 if (p->ptrace & PT_PTRACED) {
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index c5513953c825..ad1432a2a62e 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -83,10 +83,7 @@ static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry, str
83 if (!inode) 83 if (!inode)
84 return ERR_PTR(-EACCES); 84 return ERR_PTR(-EACCES);
85 } 85 }
86 if (inode) 86 return d_splice_alias(inode, dentry);
87 return d_splice_alias(inode, dentry);
88 d_add(dentry, inode);
89 return NULL;
90} 87}
91 88
92struct dentry *ext2_get_parent(struct dentry *child) 89struct dentry *ext2_get_parent(struct dentry *child)
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index af193a304ee5..8bd8ac077704 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -1005,10 +1005,7 @@ static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, str
1005 if (!inode) 1005 if (!inode)
1006 return ERR_PTR(-EACCES); 1006 return ERR_PTR(-EACCES);
1007 } 1007 }
1008 if (inode) 1008 return d_splice_alias(inode, dentry);
1009 return d_splice_alias(inode, dentry);
1010 d_add(dentry, inode);
1011 return NULL;
1012} 1009}
1013 1010
1014 1011
diff --git a/fs/fcntl.c b/fs/fcntl.c
index d0767fe58362..5f96786d1c73 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -36,7 +36,7 @@ void fastcall set_close_on_exec(unsigned int fd, int flag)
36 spin_unlock(&files->file_lock); 36 spin_unlock(&files->file_lock);
37} 37}
38 38
39static inline int get_close_on_exec(unsigned int fd) 39static int get_close_on_exec(unsigned int fd)
40{ 40{
41 struct files_struct *files = current->files; 41 struct files_struct *files = current->files;
42 struct fdtable *fdt; 42 struct fdtable *fdt;
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index ab4c3a9d51b8..f568102da1e8 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -402,7 +402,7 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb, uid_t uid,
402 inode->i_mapping->backing_dev_info =&hugetlbfs_backing_dev_info; 402 inode->i_mapping->backing_dev_info =&hugetlbfs_backing_dev_info;
403 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; 403 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
404 info = HUGETLBFS_I(inode); 404 info = HUGETLBFS_I(inode);
405 mpol_shared_policy_init(&info->policy); 405 mpol_shared_policy_init(&info->policy, MPOL_DEFAULT, NULL);
406 switch (mode & S_IFMT) { 406 switch (mode & S_IFMT) {
407 default: 407 default:
408 init_special_inode(inode, mode, dev); 408 init_special_inode(inode, mode, dev);
diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c
index e37e82b7cbf0..e7ba0c30e071 100644
--- a/fs/isofs/namei.c
+++ b/fs/isofs/namei.c
@@ -185,8 +185,5 @@ struct dentry *isofs_lookup(struct inode * dir, struct dentry * dentry, struct n
185 } 185 }
186 } 186 }
187 unlock_kernel(); 187 unlock_kernel();
188 if (inode) 188 return d_splice_alias(inode, dentry);
189 return d_splice_alias(inode, dentry);
190 d_add(dentry, inode);
191 return NULL;
192} 189}
diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c
index fff108bb118b..70f7a896c04a 100644
--- a/fs/jffs2/build.c
+++ b/fs/jffs2/build.c
@@ -47,7 +47,7 @@ next_inode(int *i, struct jffs2_inode_cache *ic, struct jffs2_sb_info *c)
47 ic = next_inode(&i, ic, (c))) 47 ic = next_inode(&i, ic, (c)))
48 48
49 49
50static inline void jffs2_build_inode_pass1(struct jffs2_sb_info *c, 50static void jffs2_build_inode_pass1(struct jffs2_sb_info *c,
51 struct jffs2_inode_cache *ic) 51 struct jffs2_inode_cache *ic)
52{ 52{
53 struct jffs2_full_dirent *fd; 53 struct jffs2_full_dirent *fd;
diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c
index c79eebb8ab32..b635e167a3fa 100644
--- a/fs/jffs2/nodelist.c
+++ b/fs/jffs2/nodelist.c
@@ -134,7 +134,7 @@ static void jffs2_fragtree_insert(struct jffs2_node_frag *newfrag, struct jffs2_
134/* 134/*
135 * Allocate and initializes a new fragment. 135 * Allocate and initializes a new fragment.
136 */ 136 */
137static inline struct jffs2_node_frag * new_fragment(struct jffs2_full_dnode *fn, uint32_t ofs, uint32_t size) 137static struct jffs2_node_frag * new_fragment(struct jffs2_full_dnode *fn, uint32_t ofs, uint32_t size)
138{ 138{
139 struct jffs2_node_frag *newfrag; 139 struct jffs2_node_frag *newfrag;
140 140
@@ -513,7 +513,7 @@ free_out:
513 * 513 *
514 * Checks the node if we are in the checking stage. 514 * Checks the node if we are in the checking stage.
515 */ 515 */
516static inline int check_node(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn) 516static int check_node(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn)
517{ 517{
518 int ret; 518 int ret;
519 519
diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c
index f01e9c0d2677..200fbda2c6d1 100644
--- a/fs/lockd/xdr.c
+++ b/fs/lockd/xdr.c
@@ -44,7 +44,7 @@ loff_t_to_s32(loff_t offset)
44/* 44/*
45 * XDR functions for basic NLM types 45 * XDR functions for basic NLM types
46 */ 46 */
47static inline u32 *nlm_decode_cookie(u32 *p, struct nlm_cookie *c) 47static u32 *nlm_decode_cookie(u32 *p, struct nlm_cookie *c)
48{ 48{
49 unsigned int len; 49 unsigned int len;
50 50
@@ -79,7 +79,7 @@ nlm_encode_cookie(u32 *p, struct nlm_cookie *c)
79 return p; 79 return p;
80} 80}
81 81
82static inline u32 * 82static u32 *
83nlm_decode_fh(u32 *p, struct nfs_fh *f) 83nlm_decode_fh(u32 *p, struct nfs_fh *f)
84{ 84{
85 unsigned int len; 85 unsigned int len;
@@ -119,7 +119,7 @@ nlm_encode_oh(u32 *p, struct xdr_netobj *oh)
119 return xdr_encode_netobj(p, oh); 119 return xdr_encode_netobj(p, oh);
120} 120}
121 121
122static inline u32 * 122static u32 *
123nlm_decode_lock(u32 *p, struct nlm_lock *lock) 123nlm_decode_lock(u32 *p, struct nlm_lock *lock)
124{ 124{
125 struct file_lock *fl = &lock->fl; 125 struct file_lock *fl = &lock->fl;
diff --git a/fs/mbcache.c b/fs/mbcache.c
index 0f1e4530670f..f5bbe4c97c58 100644
--- a/fs/mbcache.c
+++ b/fs/mbcache.c
@@ -126,7 +126,7 @@ __mb_cache_entry_is_hashed(struct mb_cache_entry *ce)
126} 126}
127 127
128 128
129static inline void 129static void
130__mb_cache_entry_unhash(struct mb_cache_entry *ce) 130__mb_cache_entry_unhash(struct mb_cache_entry *ce)
131{ 131{
132 int n; 132 int n;
@@ -139,7 +139,7 @@ __mb_cache_entry_unhash(struct mb_cache_entry *ce)
139} 139}
140 140
141 141
142static inline void 142static void
143__mb_cache_entry_forget(struct mb_cache_entry *ce, gfp_t gfp_mask) 143__mb_cache_entry_forget(struct mb_cache_entry *ce, gfp_t gfp_mask)
144{ 144{
145 struct mb_cache *cache = ce->e_cache; 145 struct mb_cache *cache = ce->e_cache;
@@ -158,7 +158,7 @@ __mb_cache_entry_forget(struct mb_cache_entry *ce, gfp_t gfp_mask)
158} 158}
159 159
160 160
161static inline void 161static void
162__mb_cache_entry_release_unlock(struct mb_cache_entry *ce) 162__mb_cache_entry_release_unlock(struct mb_cache_entry *ce)
163{ 163{
164 /* Wake up all processes queuing for this cache entry. */ 164 /* Wake up all processes queuing for this cache entry. */
diff --git a/fs/namei.c b/fs/namei.c
index 1e5746eb1380..33fb5bd34a81 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -113,7 +113,7 @@
113 * POSIX.1 2.4: an empty pathname is invalid (ENOENT). 113 * POSIX.1 2.4: an empty pathname is invalid (ENOENT).
114 * PATH_MAX includes the nul terminator --RR. 114 * PATH_MAX includes the nul terminator --RR.
115 */ 115 */
116static inline int do_getname(const char __user *filename, char *page) 116static int do_getname(const char __user *filename, char *page)
117{ 117{
118 int retval; 118 int retval;
119 unsigned long len = PATH_MAX; 119 unsigned long len = PATH_MAX;
@@ -396,7 +396,7 @@ static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name,
396 * short-cut DAC fails, then call permission() to do more 396 * short-cut DAC fails, then call permission() to do more
397 * complete permission check. 397 * complete permission check.
398 */ 398 */
399static inline int exec_permission_lite(struct inode *inode, 399static int exec_permission_lite(struct inode *inode,
400 struct nameidata *nd) 400 struct nameidata *nd)
401{ 401{
402 umode_t mode = inode->i_mode; 402 umode_t mode = inode->i_mode;
@@ -486,7 +486,7 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, s
486static int __emul_lookup_dentry(const char *, struct nameidata *); 486static int __emul_lookup_dentry(const char *, struct nameidata *);
487 487
488/* SMP-safe */ 488/* SMP-safe */
489static inline int 489static __always_inline int
490walk_init_root(const char *name, struct nameidata *nd) 490walk_init_root(const char *name, struct nameidata *nd)
491{ 491{
492 read_lock(&current->fs->lock); 492 read_lock(&current->fs->lock);
@@ -504,7 +504,7 @@ walk_init_root(const char *name, struct nameidata *nd)
504 return 1; 504 return 1;
505} 505}
506 506
507static inline int __vfs_follow_link(struct nameidata *nd, const char *link) 507static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *link)
508{ 508{
509 int res = 0; 509 int res = 0;
510 char *name; 510 char *name;
@@ -544,7 +544,7 @@ struct path {
544 struct dentry *dentry; 544 struct dentry *dentry;
545}; 545};
546 546
547static inline int __do_follow_link(struct path *path, struct nameidata *nd) 547static __always_inline int __do_follow_link(struct path *path, struct nameidata *nd)
548{ 548{
549 int error; 549 int error;
550 void *cookie; 550 void *cookie;
@@ -690,7 +690,7 @@ int follow_down(struct vfsmount **mnt, struct dentry **dentry)
690 return 0; 690 return 0;
691} 691}
692 692
693static inline void follow_dotdot(struct nameidata *nd) 693static __always_inline void follow_dotdot(struct nameidata *nd)
694{ 694{
695 while(1) { 695 while(1) {
696 struct vfsmount *parent; 696 struct vfsmount *parent;
@@ -1294,7 +1294,7 @@ static inline int check_sticky(struct inode *dir, struct inode *inode)
1294 * 10. We don't allow removal of NFS sillyrenamed files; it's handled by 1294 * 10. We don't allow removal of NFS sillyrenamed files; it's handled by
1295 * nfs_async_unlink(). 1295 * nfs_async_unlink().
1296 */ 1296 */
1297static inline int may_delete(struct inode *dir,struct dentry *victim,int isdir) 1297static int may_delete(struct inode *dir,struct dentry *victim,int isdir)
1298{ 1298{
1299 int error; 1299 int error;
1300 1300
@@ -2315,7 +2315,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
2315 return error; 2315 return error;
2316} 2316}
2317 2317
2318static inline int do_rename(const char * oldname, const char * newname) 2318static int do_rename(const char * oldname, const char * newname)
2319{ 2319{
2320 int error = 0; 2320 int error = 0;
2321 struct dentry * old_dir, * new_dir; 2321 struct dentry * old_dir, * new_dir;
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
index 8c8839203cd5..d277a58bd128 100644
--- a/fs/ncpfs/inode.c
+++ b/fs/ncpfs/inode.c
@@ -716,10 +716,8 @@ static void ncp_put_super(struct super_block *sb)
716 fput(server->ncp_filp); 716 fput(server->ncp_filp);
717 kill_proc(server->m.wdog_pid, SIGTERM, 1); 717 kill_proc(server->m.wdog_pid, SIGTERM, 1);
718 718
719 if (server->priv.data) 719 kfree(server->priv.data);
720 ncp_kfree_s(server->priv.data, server->priv.len); 720 kfree(server->auth.object_name);
721 if (server->auth.object_name)
722 ncp_kfree_s(server->auth.object_name, server->auth.object_name_len);
723 vfree(server->packet); 721 vfree(server->packet);
724 sb->s_fs_info = NULL; 722 sb->s_fs_info = NULL;
725 kfree(server); 723 kfree(server);
@@ -958,11 +956,6 @@ out:
958 return result; 956 return result;
959} 957}
960 958
961#ifdef DEBUG_NCP_MALLOC
962int ncp_malloced;
963int ncp_current_malloced;
964#endif
965
966static struct super_block *ncp_get_sb(struct file_system_type *fs_type, 959static struct super_block *ncp_get_sb(struct file_system_type *fs_type,
967 int flags, const char *dev_name, void *data) 960 int flags, const char *dev_name, void *data)
968{ 961{
@@ -981,10 +974,6 @@ static int __init init_ncp_fs(void)
981 int err; 974 int err;
982 DPRINTK("ncpfs: init_module called\n"); 975 DPRINTK("ncpfs: init_module called\n");
983 976
984#ifdef DEBUG_NCP_MALLOC
985 ncp_malloced = 0;
986 ncp_current_malloced = 0;
987#endif
988 err = init_inodecache(); 977 err = init_inodecache();
989 if (err) 978 if (err)
990 goto out1; 979 goto out1;
@@ -1003,10 +992,6 @@ static void __exit exit_ncp_fs(void)
1003 DPRINTK("ncpfs: cleanup_module called\n"); 992 DPRINTK("ncpfs: cleanup_module called\n");
1004 unregister_filesystem(&ncp_fs_type); 993 unregister_filesystem(&ncp_fs_type);
1005 destroy_inodecache(); 994 destroy_inodecache();
1006#ifdef DEBUG_NCP_MALLOC
1007 PRINTK("ncp_malloced: %d\n", ncp_malloced);
1008 PRINTK("ncp_current_malloced: %d\n", ncp_current_malloced);
1009#endif
1010} 995}
1011 996
1012module_init(init_ncp_fs) 997module_init(init_ncp_fs)
diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c
index d6e0c089e1b1..eb3813ad136f 100644
--- a/fs/ncpfs/ioctl.c
+++ b/fs/ncpfs/ioctl.c
@@ -518,10 +518,11 @@ outrel:
518 if (user.object_name_len > NCP_OBJECT_NAME_MAX_LEN) 518 if (user.object_name_len > NCP_OBJECT_NAME_MAX_LEN)
519 return -ENOMEM; 519 return -ENOMEM;
520 if (user.object_name_len) { 520 if (user.object_name_len) {
521 newname = ncp_kmalloc(user.object_name_len, GFP_USER); 521 newname = kmalloc(user.object_name_len, GFP_USER);
522 if (!newname) return -ENOMEM; 522 if (!newname)
523 return -ENOMEM;
523 if (copy_from_user(newname, user.object_name, user.object_name_len)) { 524 if (copy_from_user(newname, user.object_name, user.object_name_len)) {
524 ncp_kfree_s(newname, user.object_name_len); 525 kfree(newname);
525 return -EFAULT; 526 return -EFAULT;
526 } 527 }
527 } else { 528 } else {
@@ -540,8 +541,8 @@ outrel:
540 server->priv.len = 0; 541 server->priv.len = 0;
541 server->priv.data = NULL; 542 server->priv.data = NULL;
542 /* leave critical section */ 543 /* leave critical section */
543 if (oldprivate) ncp_kfree_s(oldprivate, oldprivatelen); 544 kfree(oldprivate);
544 if (oldname) ncp_kfree_s(oldname, oldnamelen); 545 kfree(oldname);
545 return 0; 546 return 0;
546 } 547 }
547 case NCP_IOC_GETPRIVATEDATA: 548 case NCP_IOC_GETPRIVATEDATA:
@@ -581,10 +582,11 @@ outrel:
581 if (user.len > NCP_PRIVATE_DATA_MAX_LEN) 582 if (user.len > NCP_PRIVATE_DATA_MAX_LEN)
582 return -ENOMEM; 583 return -ENOMEM;
583 if (user.len) { 584 if (user.len) {
584 new = ncp_kmalloc(user.len, GFP_USER); 585 new = kmalloc(user.len, GFP_USER);
585 if (!new) return -ENOMEM; 586 if (!new)
587 return -ENOMEM;
586 if (copy_from_user(new, user.data, user.len)) { 588 if (copy_from_user(new, user.data, user.len)) {
587 ncp_kfree_s(new, user.len); 589 kfree(new);
588 return -EFAULT; 590 return -EFAULT;
589 } 591 }
590 } else { 592 } else {
@@ -596,7 +598,7 @@ outrel:
596 server->priv.len = user.len; 598 server->priv.len = user.len;
597 server->priv.data = new; 599 server->priv.data = new;
598 /* leave critical section */ 600 /* leave critical section */
599 if (old) ncp_kfree_s(old, oldlen); 601 kfree(old);
600 return 0; 602 return 0;
601 } 603 }
602 604
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index aa7bb41b293d..e3a0797dd56b 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -37,7 +37,7 @@ static u32 nfs_ftypes[] = {
37/* 37/*
38 * XDR functions for basic NFS types 38 * XDR functions for basic NFS types
39 */ 39 */
40static inline u32 * 40static u32 *
41decode_fh(u32 *p, struct svc_fh *fhp) 41decode_fh(u32 *p, struct svc_fh *fhp)
42{ 42{
43 fh_init(fhp, NFS_FHSIZE); 43 fh_init(fhp, NFS_FHSIZE);
@@ -151,7 +151,7 @@ decode_sattr(u32 *p, struct iattr *iap)
151 return p; 151 return p;
152} 152}
153 153
154static inline u32 * 154static u32 *
155encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp, 155encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp,
156 struct kstat *stat) 156 struct kstat *stat)
157{ 157{
diff --git a/fs/pipe.c b/fs/pipe.c
index eef0f29e86ef..d722579df79a 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -50,7 +50,7 @@ void pipe_wait(struct inode * inode)
50 mutex_lock(PIPE_MUTEX(*inode)); 50 mutex_lock(PIPE_MUTEX(*inode));
51} 51}
52 52
53static inline int 53static int
54pipe_iov_copy_from_user(void *to, struct iovec *iov, unsigned long len) 54pipe_iov_copy_from_user(void *to, struct iovec *iov, unsigned long len)
55{ 55{
56 unsigned long copy; 56 unsigned long copy;
@@ -70,7 +70,7 @@ pipe_iov_copy_from_user(void *to, struct iovec *iov, unsigned long len)
70 return 0; 70 return 0;
71} 71}
72 72
73static inline int 73static int
74pipe_iov_copy_to_user(struct iovec *iov, const void *from, unsigned long len) 74pipe_iov_copy_to_user(struct iovec *iov, const void *from, unsigned long len)
75{ 75{
76 unsigned long copy; 76 unsigned long copy;
diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c
index fb117b74809e..9bdd077d6f55 100644
--- a/fs/proc/proc_devtree.c
+++ b/fs/proc/proc_devtree.c
@@ -81,6 +81,30 @@ void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop
81 __proc_device_tree_add_prop(pde, prop); 81 __proc_device_tree_add_prop(pde, prop);
82} 82}
83 83
84void proc_device_tree_remove_prop(struct proc_dir_entry *pde,
85 struct property *prop)
86{
87 remove_proc_entry(prop->name, pde);
88}
89
90void proc_device_tree_update_prop(struct proc_dir_entry *pde,
91 struct property *newprop,
92 struct property *oldprop)
93{
94 struct proc_dir_entry *ent;
95
96 for (ent = pde->subdir; ent != NULL; ent = ent->next)
97 if (ent->data == oldprop)
98 break;
99 if (ent == NULL) {
100 printk(KERN_WARNING "device-tree: property \"%s\" "
101 " does not exist\n", oldprop->name);
102 } else {
103 ent->data = newprop;
104 ent->size = newprop->length;
105 }
106}
107
84/* 108/*
85 * Process a node, adding entries for its children and its properties. 109 * Process a node, adding entries for its children and its properties.
86 */ 110 */
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index 63bf6c00fa0c..8f8014285a34 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -20,6 +20,7 @@
20#include <linux/time.h> 20#include <linux/time.h>
21#include <linux/kernel.h> 21#include <linux/kernel.h>
22#include <linux/kernel_stat.h> 22#include <linux/kernel_stat.h>
23#include <linux/fs.h>
23#include <linux/tty.h> 24#include <linux/tty.h>
24#include <linux/string.h> 25#include <linux/string.h>
25#include <linux/mman.h> 26#include <linux/mman.h>
@@ -62,7 +63,6 @@
62 */ 63 */
63extern int get_hardware_list(char *); 64extern int get_hardware_list(char *);
64extern int get_stram_list(char *); 65extern int get_stram_list(char *);
65extern int get_chrdev_list(char *);
66extern int get_filesystem_list(char *); 66extern int get_filesystem_list(char *);
67extern int get_exec_domain_list(char *); 67extern int get_exec_domain_list(char *);
68extern int get_dma_list(char *); 68extern int get_dma_list(char *);
@@ -248,6 +248,154 @@ static int cpuinfo_open(struct inode *inode, struct file *file)
248{ 248{
249 return seq_open(file, &cpuinfo_op); 249 return seq_open(file, &cpuinfo_op);
250} 250}
251
252enum devinfo_states {
253 CHR_HDR,
254 CHR_LIST,
255 BLK_HDR,
256 BLK_LIST,
257 DEVINFO_DONE
258};
259
260struct devinfo_state {
261 void *chrdev;
262 void *blkdev;
263 unsigned int num_records;
264 unsigned int cur_record;
265 enum devinfo_states state;
266};
267
268static void *devinfo_start(struct seq_file *f, loff_t *pos)
269{
270 struct devinfo_state *info = f->private;
271
272 if (*pos) {
273 if ((info) && (*pos <= info->num_records))
274 return info;
275 return NULL;
276 }
277 info = kmalloc(sizeof(*info), GFP_KERNEL);
278 f->private = info;
279 info->chrdev = acquire_chrdev_list();
280 info->blkdev = acquire_blkdev_list();
281 info->state = CHR_HDR;
282 info->num_records = count_chrdev_list();
283 info->num_records += count_blkdev_list();
284 info->num_records += 2; /* Character and Block headers */
285 *pos = 1;
286 info->cur_record = *pos;
287 return info;
288}
289
290static void *devinfo_next(struct seq_file *f, void *v, loff_t *pos)
291{
292 int idummy;
293 char *ndummy;
294 struct devinfo_state *info = f->private;
295
296 switch (info->state) {
297 case CHR_HDR:
298 info->state = CHR_LIST;
299 (*pos)++;
300 /*fallthrough*/
301 case CHR_LIST:
302 if (get_chrdev_info(info->chrdev,&idummy,&ndummy)) {
303 /*
304 * The character dev list is complete
305 */
306 info->state = BLK_HDR;
307 } else {
308 info->chrdev = get_next_chrdev(info->chrdev);
309 }
310 (*pos)++;
311 break;
312 case BLK_HDR:
313 info->state = BLK_LIST;
314 (*pos)++;
315 break;
316 case BLK_LIST:
317 if (get_blkdev_info(info->blkdev,&idummy,&ndummy)) {
318 /*
319 * The block dev list is complete
320 */
321 info->state = DEVINFO_DONE;
322 } else {
323 info->blkdev = get_next_blkdev(info->blkdev);
324 }
325 (*pos)++;
326 break;
327 case DEVINFO_DONE:
328 (*pos)++;
329 info->cur_record = *pos;
330 info = NULL;
331 break;
332 default:
333 break;
334 }
335 if (info)
336 info->cur_record = *pos;
337 return info;
338}
339
340static void devinfo_stop(struct seq_file *f, void *v)
341{
342 struct devinfo_state *info = f->private;
343
344 if (info) {
345 release_chrdev_list(info->chrdev);
346 release_blkdev_list(info->blkdev);
347 f->private = NULL;
348 kfree(info);
349 }
350}
351
352static int devinfo_show(struct seq_file *f, void *arg)
353{
354 int major;
355 char *name;
356 struct devinfo_state *info = f->private;
357
358 switch(info->state) {
359 case CHR_HDR:
360 seq_printf(f,"Character devices:\n");
361 /* fallthrough */
362 case CHR_LIST:
363 if (!get_chrdev_info(info->chrdev,&major,&name))
364 seq_printf(f,"%3d %s\n",major,name);
365 break;
366 case BLK_HDR:
367 seq_printf(f,"\nBlock devices:\n");
368 /* fallthrough */
369 case BLK_LIST:
370 if (!get_blkdev_info(info->blkdev,&major,&name))
371 seq_printf(f,"%3d %s\n",major,name);
372 break;
373 default:
374 break;
375 }
376
377 return 0;
378}
379
380static struct seq_operations devinfo_op = {
381 .start = devinfo_start,
382 .next = devinfo_next,
383 .stop = devinfo_stop,
384 .show = devinfo_show,
385};
386
387static int devinfo_open(struct inode *inode, struct file *file)
388{
389 return seq_open(file, &devinfo_op);
390}
391
392static struct file_operations proc_devinfo_operations = {
393 .open = devinfo_open,
394 .read = seq_read,
395 .llseek = seq_lseek,
396 .release = seq_release,
397};
398
251static struct file_operations proc_cpuinfo_operations = { 399static struct file_operations proc_cpuinfo_operations = {
252 .open = cpuinfo_open, 400 .open = cpuinfo_open,
253 .read = seq_read, 401 .read = seq_read,
@@ -450,14 +598,6 @@ static struct file_operations proc_stat_operations = {
450 .release = single_release, 598 .release = single_release,
451}; 599};
452 600
453static int devices_read_proc(char *page, char **start, off_t off,
454 int count, int *eof, void *data)
455{
456 int len = get_chrdev_list(page);
457 len += get_blkdev_list(page+len, len);
458 return proc_calc_metrics(page, start, off, count, eof, len);
459}
460
461/* 601/*
462 * /proc/interrupts 602 * /proc/interrupts
463 */ 603 */
@@ -582,7 +722,6 @@ void __init proc_misc_init(void)
582#ifdef CONFIG_STRAM_PROC 722#ifdef CONFIG_STRAM_PROC
583 {"stram", stram_read_proc}, 723 {"stram", stram_read_proc},
584#endif 724#endif
585 {"devices", devices_read_proc},
586 {"filesystems", filesystems_read_proc}, 725 {"filesystems", filesystems_read_proc},
587 {"cmdline", cmdline_read_proc}, 726 {"cmdline", cmdline_read_proc},
588 {"locks", locks_read_proc}, 727 {"locks", locks_read_proc},
@@ -598,6 +737,7 @@ void __init proc_misc_init(void)
598 entry = create_proc_entry("kmsg", S_IRUSR, &proc_root); 737 entry = create_proc_entry("kmsg", S_IRUSR, &proc_root);
599 if (entry) 738 if (entry)
600 entry->proc_fops = &proc_kmsg_operations; 739 entry->proc_fops = &proc_kmsg_operations;
740 create_seq_entry("devices", 0, &proc_devinfo_operations);
601 create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations); 741 create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations);
602 create_seq_entry("partitions", 0, &proc_partitions_operations); 742 create_seq_entry("partitions", 0, &proc_partitions_operations);
603 create_seq_entry("stat", 0, &proc_stat_operations); 743 create_seq_entry("stat", 0, &proc_stat_operations);
diff --git a/fs/quota_v2.c b/fs/quota_v2.c
index 7afcbb1b9376..a4ef91bb4f3b 100644
--- a/fs/quota_v2.c
+++ b/fs/quota_v2.c
@@ -35,7 +35,8 @@ static int v2_check_quota_file(struct super_block *sb, int type)
35 35
36 size = sb->s_op->quota_read(sb, type, (char *)&dqhead, sizeof(struct v2_disk_dqheader), 0); 36 size = sb->s_op->quota_read(sb, type, (char *)&dqhead, sizeof(struct v2_disk_dqheader), 0);
37 if (size != sizeof(struct v2_disk_dqheader)) { 37 if (size != sizeof(struct v2_disk_dqheader)) {
38 printk("failed read\n"); 38 printk("quota_v2: failed read expected=%d got=%d\n",
39 sizeof(struct v2_disk_dqheader), size);
39 return 0; 40 return 0;
40 } 41 }
41 if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] || 42 if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] ||
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index 3549067c42d9..8f8d8d01107c 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -375,11 +375,7 @@ static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry,
375 return ERR_PTR(-EIO); 375 return ERR_PTR(-EIO);
376 } 376 }
377 377
378 if (inode) 378 return d_splice_alias(inode, dentry);
379 return d_splice_alias(inode, dentry);
380
381 d_add(dentry, inode);
382 return NULL;
383} 379}
384 380
385/* 381/*
diff --git a/fs/smbfs/Makefile b/fs/smbfs/Makefile
index 93246b7dd6fb..6673ee82cb4c 100644
--- a/fs/smbfs/Makefile
+++ b/fs/smbfs/Makefile
@@ -13,7 +13,6 @@ smbfs-objs := proc.o dir.o cache.o sock.o inode.o file.o ioctl.o getopt.o \
13EXTRA_CFLAGS += -DSMBFS_PARANOIA 13EXTRA_CFLAGS += -DSMBFS_PARANOIA
14#EXTRA_CFLAGS += -DSMBFS_DEBUG 14#EXTRA_CFLAGS += -DSMBFS_DEBUG
15#EXTRA_CFLAGS += -DSMBFS_DEBUG_VERBOSE 15#EXTRA_CFLAGS += -DSMBFS_DEBUG_VERBOSE
16#EXTRA_CFLAGS += -DDEBUG_SMB_MALLOC
17#EXTRA_CFLAGS += -DDEBUG_SMB_TIMESTAMP 16#EXTRA_CFLAGS += -DDEBUG_SMB_TIMESTAMP
18#EXTRA_CFLAGS += -Werror 17#EXTRA_CFLAGS += -Werror
19 18
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c
index 6ec88bf59b2d..02e3e82d465c 100644
--- a/fs/smbfs/inode.c
+++ b/fs/smbfs/inode.c
@@ -487,11 +487,11 @@ smb_put_super(struct super_block *sb)
487 if (server->conn_pid) 487 if (server->conn_pid)
488 kill_proc(server->conn_pid, SIGTERM, 1); 488 kill_proc(server->conn_pid, SIGTERM, 1);
489 489
490 smb_kfree(server->ops); 490 kfree(server->ops);
491 smb_unload_nls(server); 491 smb_unload_nls(server);
492 sb->s_fs_info = NULL; 492 sb->s_fs_info = NULL;
493 smb_unlock_server(server); 493 smb_unlock_server(server);
494 smb_kfree(server); 494 kfree(server);
495} 495}
496 496
497static int smb_fill_super(struct super_block *sb, void *raw_data, int silent) 497static int smb_fill_super(struct super_block *sb, void *raw_data, int silent)
@@ -519,11 +519,10 @@ static int smb_fill_super(struct super_block *sb, void *raw_data, int silent)
519 sb->s_op = &smb_sops; 519 sb->s_op = &smb_sops;
520 sb->s_time_gran = 100; 520 sb->s_time_gran = 100;
521 521
522 server = smb_kmalloc(sizeof(struct smb_sb_info), GFP_KERNEL); 522 server = kzalloc(sizeof(struct smb_sb_info), GFP_KERNEL);
523 if (!server) 523 if (!server)
524 goto out_no_server; 524 goto out_no_server;
525 sb->s_fs_info = server; 525 sb->s_fs_info = server;
526 memset(server, 0, sizeof(struct smb_sb_info));
527 526
528 server->super_block = sb; 527 server->super_block = sb;
529 server->mnt = NULL; 528 server->mnt = NULL;
@@ -542,8 +541,8 @@ static int smb_fill_super(struct super_block *sb, void *raw_data, int silent)
542 /* FIXME: move these to the smb_sb_info struct */ 541 /* FIXME: move these to the smb_sb_info struct */
543 VERBOSE("alloc chunk = %d\n", sizeof(struct smb_ops) + 542 VERBOSE("alloc chunk = %d\n", sizeof(struct smb_ops) +
544 sizeof(struct smb_mount_data_kernel)); 543 sizeof(struct smb_mount_data_kernel));
545 mem = smb_kmalloc(sizeof(struct smb_ops) + 544 mem = kmalloc(sizeof(struct smb_ops) +
546 sizeof(struct smb_mount_data_kernel), GFP_KERNEL); 545 sizeof(struct smb_mount_data_kernel), GFP_KERNEL);
547 if (!mem) 546 if (!mem)
548 goto out_no_mem; 547 goto out_no_mem;
549 548
@@ -621,12 +620,12 @@ out_no_root:
621out_no_smbiod: 620out_no_smbiod:
622 smb_unload_nls(server); 621 smb_unload_nls(server);
623out_bad_option: 622out_bad_option:
624 smb_kfree(mem); 623 kfree(mem);
625out_no_mem: 624out_no_mem:
626 if (!server->mnt) 625 if (!server->mnt)
627 printk(KERN_ERR "smb_fill_super: allocation failure\n"); 626 printk(KERN_ERR "smb_fill_super: allocation failure\n");
628 sb->s_fs_info = NULL; 627 sb->s_fs_info = NULL;
629 smb_kfree(server); 628 kfree(server);
630 goto out_fail; 629 goto out_fail;
631out_wrong_data: 630out_wrong_data:
632 printk(KERN_ERR "smbfs: mount_data version %d is not supported\n", ver); 631 printk(KERN_ERR "smbfs: mount_data version %d is not supported\n", ver);
@@ -782,12 +781,6 @@ out:
782 return error; 781 return error;
783} 782}
784 783
785#ifdef DEBUG_SMB_MALLOC
786int smb_malloced;
787int smb_current_kmalloced;
788int smb_current_vmalloced;
789#endif
790
791static struct super_block *smb_get_sb(struct file_system_type *fs_type, 784static struct super_block *smb_get_sb(struct file_system_type *fs_type,
792 int flags, const char *dev_name, void *data) 785 int flags, const char *dev_name, void *data)
793{ 786{
@@ -807,12 +800,6 @@ static int __init init_smb_fs(void)
807 int err; 800 int err;
808 DEBUG1("registering ...\n"); 801 DEBUG1("registering ...\n");
809 802
810#ifdef DEBUG_SMB_MALLOC
811 smb_malloced = 0;
812 smb_current_kmalloced = 0;
813 smb_current_vmalloced = 0;
814#endif
815
816 err = init_inodecache(); 803 err = init_inodecache();
817 if (err) 804 if (err)
818 goto out_inode; 805 goto out_inode;
@@ -837,11 +824,6 @@ static void __exit exit_smb_fs(void)
837 unregister_filesystem(&smb_fs_type); 824 unregister_filesystem(&smb_fs_type);
838 smb_destroy_request_cache(); 825 smb_destroy_request_cache();
839 destroy_inodecache(); 826 destroy_inodecache();
840#ifdef DEBUG_SMB_MALLOC
841 printk(KERN_DEBUG "smb_malloced: %d\n", smb_malloced);
842 printk(KERN_DEBUG "smb_current_kmalloced: %d\n",smb_current_kmalloced);
843 printk(KERN_DEBUG "smb_current_vmalloced: %d\n",smb_current_vmalloced);
844#endif
845} 827}
846 828
847module_init(init_smb_fs) 829module_init(init_smb_fs)
diff --git a/fs/smbfs/request.c b/fs/smbfs/request.c
index a0f296d9928a..c71c375863cc 100644
--- a/fs/smbfs/request.c
+++ b/fs/smbfs/request.c
@@ -68,7 +68,7 @@ static struct smb_request *smb_do_alloc_request(struct smb_sb_info *server,
68 goto out; 68 goto out;
69 69
70 if (bufsize > 0) { 70 if (bufsize > 0) {
71 buf = smb_kmalloc(bufsize, GFP_NOFS); 71 buf = kmalloc(bufsize, GFP_NOFS);
72 if (!buf) { 72 if (!buf) {
73 kmem_cache_free(req_cachep, req); 73 kmem_cache_free(req_cachep, req);
74 return NULL; 74 return NULL;
@@ -124,9 +124,8 @@ static void smb_free_request(struct smb_request *req)
124{ 124{
125 atomic_dec(&req->rq_server->nr_requests); 125 atomic_dec(&req->rq_server->nr_requests);
126 if (req->rq_buffer && !(req->rq_flags & SMB_REQ_STATIC)) 126 if (req->rq_buffer && !(req->rq_flags & SMB_REQ_STATIC))
127 smb_kfree(req->rq_buffer); 127 kfree(req->rq_buffer);
128 if (req->rq_trans2buffer) 128 kfree(req->rq_trans2buffer);
129 smb_kfree(req->rq_trans2buffer);
130 kmem_cache_free(req_cachep, req); 129 kmem_cache_free(req_cachep, req);
131} 130}
132 131
@@ -183,8 +182,7 @@ static int smb_setup_request(struct smb_request *req)
183 req->rq_err = 0; 182 req->rq_err = 0;
184 req->rq_errno = 0; 183 req->rq_errno = 0;
185 req->rq_fragment = 0; 184 req->rq_fragment = 0;
186 if (req->rq_trans2buffer) 185 kfree(req->rq_trans2buffer);
187 smb_kfree(req->rq_trans2buffer);
188 186
189 return 0; 187 return 0;
190} 188}
@@ -647,10 +645,9 @@ static int smb_recv_trans2(struct smb_sb_info *server, struct smb_request *req)
647 goto out_too_long; 645 goto out_too_long;
648 646
649 req->rq_trans2bufsize = buf_len; 647 req->rq_trans2bufsize = buf_len;
650 req->rq_trans2buffer = smb_kmalloc(buf_len, GFP_NOFS); 648 req->rq_trans2buffer = kzalloc(buf_len, GFP_NOFS);
651 if (!req->rq_trans2buffer) 649 if (!req->rq_trans2buffer)
652 goto out_no_mem; 650 goto out_no_mem;
653 memset(req->rq_trans2buffer, 0, buf_len);
654 651
655 req->rq_parm = req->rq_trans2buffer; 652 req->rq_parm = req->rq_trans2buffer;
656 req->rq_data = req->rq_trans2buffer + parm_tot; 653 req->rq_data = req->rq_trans2buffer + parm_tot;
diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c
index a9f4421ddb6f..3ada9dcf55b8 100644
--- a/fs/ufs/balloc.c
+++ b/fs/ufs/balloc.c
@@ -49,7 +49,7 @@ void ufs_free_fragments (struct inode * inode, unsigned fragment, unsigned count
49 49
50 sb = inode->i_sb; 50 sb = inode->i_sb;
51 uspi = UFS_SB(sb)->s_uspi; 51 uspi = UFS_SB(sb)->s_uspi;
52 usb1 = ubh_get_usb_first(USPI_UBH); 52 usb1 = ubh_get_usb_first(uspi);
53 53
54 UFSD(("ENTER, fragment %u, count %u\n", fragment, count)) 54 UFSD(("ENTER, fragment %u, count %u\n", fragment, count))
55 55
@@ -81,8 +81,9 @@ void ufs_free_fragments (struct inode * inode, unsigned fragment, unsigned count
81 for (i = bit; i < end_bit; i++) { 81 for (i = bit; i < end_bit; i++) {
82 if (ubh_isclr (UCPI_UBH, ucpi->c_freeoff, i)) 82 if (ubh_isclr (UCPI_UBH, ucpi->c_freeoff, i))
83 ubh_setbit (UCPI_UBH, ucpi->c_freeoff, i); 83 ubh_setbit (UCPI_UBH, ucpi->c_freeoff, i);
84 else ufs_error (sb, "ufs_free_fragments", 84 else
85 "bit already cleared for fragment %u", i); 85 ufs_error (sb, "ufs_free_fragments",
86 "bit already cleared for fragment %u", i);
86 } 87 }
87 88
88 DQUOT_FREE_BLOCK (inode, count); 89 DQUOT_FREE_BLOCK (inode, count);
@@ -143,7 +144,7 @@ void ufs_free_blocks (struct inode * inode, unsigned fragment, unsigned count) {
143 144
144 sb = inode->i_sb; 145 sb = inode->i_sb;
145 uspi = UFS_SB(sb)->s_uspi; 146 uspi = UFS_SB(sb)->s_uspi;
146 usb1 = ubh_get_usb_first(USPI_UBH); 147 usb1 = ubh_get_usb_first(uspi);
147 148
148 UFSD(("ENTER, fragment %u, count %u\n", fragment, count)) 149 UFSD(("ENTER, fragment %u, count %u\n", fragment, count))
149 150
@@ -247,7 +248,7 @@ unsigned ufs_new_fragments (struct inode * inode, __fs32 * p, unsigned fragment,
247 248
248 sb = inode->i_sb; 249 sb = inode->i_sb;
249 uspi = UFS_SB(sb)->s_uspi; 250 uspi = UFS_SB(sb)->s_uspi;
250 usb1 = ubh_get_usb_first(USPI_UBH); 251 usb1 = ubh_get_usb_first(uspi);
251 *err = -ENOSPC; 252 *err = -ENOSPC;
252 253
253 lock_super (sb); 254 lock_super (sb);
@@ -407,7 +408,7 @@ ufs_add_fragments (struct inode * inode, unsigned fragment,
407 408
408 sb = inode->i_sb; 409 sb = inode->i_sb;
409 uspi = UFS_SB(sb)->s_uspi; 410 uspi = UFS_SB(sb)->s_uspi;
410 usb1 = ubh_get_usb_first (USPI_UBH); 411 usb1 = ubh_get_usb_first (uspi);
411 count = newcount - oldcount; 412 count = newcount - oldcount;
412 413
413 cgno = ufs_dtog(fragment); 414 cgno = ufs_dtog(fragment);
@@ -490,7 +491,7 @@ static unsigned ufs_alloc_fragments (struct inode * inode, unsigned cgno,
490 491
491 sb = inode->i_sb; 492 sb = inode->i_sb;
492 uspi = UFS_SB(sb)->s_uspi; 493 uspi = UFS_SB(sb)->s_uspi;
493 usb1 = ubh_get_usb_first(USPI_UBH); 494 usb1 = ubh_get_usb_first(uspi);
494 oldcg = cgno; 495 oldcg = cgno;
495 496
496 /* 497 /*
@@ -606,7 +607,7 @@ static unsigned ufs_alloccg_block (struct inode * inode,
606 607
607 sb = inode->i_sb; 608 sb = inode->i_sb;
608 uspi = UFS_SB(sb)->s_uspi; 609 uspi = UFS_SB(sb)->s_uspi;
609 usb1 = ubh_get_usb_first(USPI_UBH); 610 usb1 = ubh_get_usb_first(uspi);
610 ucg = ubh_get_ucg(UCPI_UBH); 611 ucg = ubh_get_ucg(UCPI_UBH);
611 612
612 if (goal == 0) { 613 if (goal == 0) {
@@ -663,7 +664,7 @@ static unsigned ufs_bitmap_search (struct super_block * sb,
663 UFSD(("ENTER, cg %u, goal %u, count %u\n", ucpi->c_cgx, goal, count)) 664 UFSD(("ENTER, cg %u, goal %u, count %u\n", ucpi->c_cgx, goal, count))
664 665
665 uspi = UFS_SB(sb)->s_uspi; 666 uspi = UFS_SB(sb)->s_uspi;
666 usb1 = ubh_get_usb_first (USPI_UBH); 667 usb1 = ubh_get_usb_first (uspi);
667 ucg = ubh_get_ucg(UCPI_UBH); 668 ucg = ubh_get_ucg(UCPI_UBH);
668 669
669 if (goal) 670 if (goal)
diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c
index 0938945b9cbc..c7a47ed4f430 100644
--- a/fs/ufs/ialloc.c
+++ b/fs/ufs/ialloc.c
@@ -72,7 +72,7 @@ void ufs_free_inode (struct inode * inode)
72 72
73 sb = inode->i_sb; 73 sb = inode->i_sb;
74 uspi = UFS_SB(sb)->s_uspi; 74 uspi = UFS_SB(sb)->s_uspi;
75 usb1 = ubh_get_usb_first(USPI_UBH); 75 usb1 = ubh_get_usb_first(uspi);
76 76
77 ino = inode->i_ino; 77 ino = inode->i_ino;
78 78
@@ -167,7 +167,7 @@ struct inode * ufs_new_inode(struct inode * dir, int mode)
167 ufsi = UFS_I(inode); 167 ufsi = UFS_I(inode);
168 sbi = UFS_SB(sb); 168 sbi = UFS_SB(sb);
169 uspi = sbi->s_uspi; 169 uspi = sbi->s_uspi;
170 usb1 = ubh_get_usb_first(USPI_UBH); 170 usb1 = ubh_get_usb_first(uspi);
171 171
172 lock_super (sb); 172 lock_super (sb);
173 173
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
index 55f4aa16e3fc..e0c04e36a051 100644
--- a/fs/ufs/inode.c
+++ b/fs/ufs/inode.c
@@ -61,7 +61,7 @@ static int ufs_block_to_path(struct inode *inode, sector_t i_block, sector_t off
61 int n = 0; 61 int n = 0;
62 62
63 63
64 UFSD(("ptrs=uspi->s_apb = %d,double_blocks=%d \n",ptrs,double_blocks)); 64 UFSD(("ptrs=uspi->s_apb = %d,double_blocks=%ld \n",ptrs,double_blocks));
65 if (i_block < 0) { 65 if (i_block < 0) {
66 ufs_warning(inode->i_sb, "ufs_block_to_path", "block < 0"); 66 ufs_warning(inode->i_sb, "ufs_block_to_path", "block < 0");
67 } else if (i_block < direct_blocks) { 67 } else if (i_block < direct_blocks) {
@@ -104,7 +104,7 @@ u64 ufs_frag_map(struct inode *inode, sector_t frag)
104 unsigned flags = UFS_SB(sb)->s_flags; 104 unsigned flags = UFS_SB(sb)->s_flags;
105 u64 temp = 0L; 105 u64 temp = 0L;
106 106
107 UFSD((": frag = %lu depth = %d\n",frag,depth)); 107 UFSD((": frag = %llu depth = %d\n", (unsigned long long)frag, depth));
108 UFSD((": uspi->s_fpbshift = %d ,uspi->s_apbmask = %x, mask=%llx\n",uspi->s_fpbshift,uspi->s_apbmask,mask)); 108 UFSD((": uspi->s_fpbshift = %d ,uspi->s_apbmask = %x, mask=%llx\n",uspi->s_fpbshift,uspi->s_apbmask,mask));
109 109
110 if (depth == 0) 110 if (depth == 0)
@@ -365,9 +365,10 @@ repeat:
365 sync_dirty_buffer(bh); 365 sync_dirty_buffer(bh);
366 inode->i_ctime = CURRENT_TIME_SEC; 366 inode->i_ctime = CURRENT_TIME_SEC;
367 mark_inode_dirty(inode); 367 mark_inode_dirty(inode);
368 UFSD(("result %u\n", tmp + blockoff));
368out: 369out:
369 brelse (bh); 370 brelse (bh);
370 UFSD(("EXIT, result %u\n", tmp + blockoff)) 371 UFSD(("EXIT\n"));
371 return result; 372 return result;
372} 373}
373 374
@@ -386,7 +387,7 @@ static int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buf
386 387
387 if (!create) { 388 if (!create) {
388 phys64 = ufs_frag_map(inode, fragment); 389 phys64 = ufs_frag_map(inode, fragment);
389 UFSD(("phys64 = %lu \n",phys64)); 390 UFSD(("phys64 = %llu \n",phys64));
390 if (phys64) 391 if (phys64)
391 map_bh(bh_result, sb, phys64); 392 map_bh(bh_result, sb, phys64);
392 return 0; 393 return 0;
@@ -401,7 +402,7 @@ static int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buf
401 402
402 lock_kernel(); 403 lock_kernel();
403 404
404 UFSD(("ENTER, ino %lu, fragment %u\n", inode->i_ino, fragment)) 405 UFSD(("ENTER, ino %lu, fragment %llu\n", inode->i_ino, (unsigned long long)fragment))
405 if (fragment < 0) 406 if (fragment < 0)
406 goto abort_negative; 407 goto abort_negative;
407 if (fragment > 408 if (fragment >
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index e9a42c711a9e..d4aacee593ff 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -221,7 +221,7 @@ void ufs_error (struct super_block * sb, const char * function,
221 va_list args; 221 va_list args;
222 222
223 uspi = UFS_SB(sb)->s_uspi; 223 uspi = UFS_SB(sb)->s_uspi;
224 usb1 = ubh_get_usb_first(USPI_UBH); 224 usb1 = ubh_get_usb_first(uspi);
225 225
226 if (!(sb->s_flags & MS_RDONLY)) { 226 if (!(sb->s_flags & MS_RDONLY)) {
227 usb1->fs_clean = UFS_FSBAD; 227 usb1->fs_clean = UFS_FSBAD;
@@ -253,7 +253,7 @@ void ufs_panic (struct super_block * sb, const char * function,
253 va_list args; 253 va_list args;
254 254
255 uspi = UFS_SB(sb)->s_uspi; 255 uspi = UFS_SB(sb)->s_uspi;
256 usb1 = ubh_get_usb_first(USPI_UBH); 256 usb1 = ubh_get_usb_first(uspi);
257 257
258 if (!(sb->s_flags & MS_RDONLY)) { 258 if (!(sb->s_flags & MS_RDONLY)) {
259 usb1->fs_clean = UFS_FSBAD; 259 usb1->fs_clean = UFS_FSBAD;
@@ -420,21 +420,18 @@ static int ufs_read_cylinder_structures (struct super_block *sb) {
420 if (i + uspi->s_fpb > blks) 420 if (i + uspi->s_fpb > blks)
421 size = (blks - i) * uspi->s_fsize; 421 size = (blks - i) * uspi->s_fsize;
422 422
423 if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) { 423 if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2)
424 ubh = ubh_bread(sb, 424 ubh = ubh_bread(sb,
425 fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_csaddr) + i, size); 425 fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_csaddr) + i, size);
426 if (!ubh) 426 else
427 goto failed;
428 ubh_ubhcpymem (space, ubh, size);
429 sbi->s_csp[ufs_fragstoblks(i)]=(struct ufs_csum *)space;
430 }
431 else {
432 ubh = ubh_bread(sb, uspi->s_csaddr + i, size); 427 ubh = ubh_bread(sb, uspi->s_csaddr + i, size);
433 if (!ubh) 428
434 goto failed; 429 if (!ubh)
435 ubh_ubhcpymem(space, ubh, size); 430 goto failed;
436 sbi->s_csp[ufs_fragstoblks(i)]=(struct ufs_csum *)space; 431
437 } 432 ubh_ubhcpymem (space, ubh, size);
433 sbi->s_csp[ufs_fragstoblks(i)]=(struct ufs_csum *)space;
434
438 space += size; 435 space += size;
439 ubh_brelse (ubh); 436 ubh_brelse (ubh);
440 ubh = NULL; 437 ubh = NULL;
@@ -539,6 +536,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
539 struct inode *inode; 536 struct inode *inode;
540 unsigned block_size, super_block_size; 537 unsigned block_size, super_block_size;
541 unsigned flags; 538 unsigned flags;
539 unsigned super_block_offset;
542 540
543 uspi = NULL; 541 uspi = NULL;
544 ubh = NULL; 542 ubh = NULL;
@@ -586,10 +584,11 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
586 if (!uspi) 584 if (!uspi)
587 goto failed; 585 goto failed;
588 586
587 super_block_offset=UFS_SBLOCK;
588
589 /* Keep 2Gig file limit. Some UFS variants need to override 589 /* Keep 2Gig file limit. Some UFS variants need to override
590 this but as I don't know which I'll let those in the know loosen 590 this but as I don't know which I'll let those in the know loosen
591 the rules */ 591 the rules */
592
593 switch (sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) { 592 switch (sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) {
594 case UFS_MOUNT_UFSTYPE_44BSD: 593 case UFS_MOUNT_UFSTYPE_44BSD:
595 UFSD(("ufstype=44bsd\n")) 594 UFSD(("ufstype=44bsd\n"))
@@ -601,7 +600,8 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
601 flags |= UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD; 600 flags |= UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD;
602 break; 601 break;
603 case UFS_MOUNT_UFSTYPE_UFS2: 602 case UFS_MOUNT_UFSTYPE_UFS2:
604 UFSD(("ufstype=ufs2\n")) 603 UFSD(("ufstype=ufs2\n"));
604 super_block_offset=SBLOCK_UFS2;
605 uspi->s_fsize = block_size = 512; 605 uspi->s_fsize = block_size = 512;
606 uspi->s_fmask = ~(512 - 1); 606 uspi->s_fmask = ~(512 - 1);
607 uspi->s_fshift = 9; 607 uspi->s_fshift = 9;
@@ -725,19 +725,16 @@ again:
725 /* 725 /*
726 * read ufs super block from device 726 * read ufs super block from device
727 */ 727 */
728 if ( (flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) { 728
729 ubh = ubh_bread_uspi(uspi, sb, uspi->s_sbbase + SBLOCK_UFS2/block_size, super_block_size); 729 ubh = ubh_bread_uspi(uspi, sb, uspi->s_sbbase + super_block_offset/block_size, super_block_size);
730 } 730
731 else {
732 ubh = ubh_bread_uspi(uspi, sb, uspi->s_sbbase + UFS_SBLOCK/block_size, super_block_size);
733 }
734 if (!ubh) 731 if (!ubh)
735 goto failed; 732 goto failed;
736 733
737 734
738 usb1 = ubh_get_usb_first(USPI_UBH); 735 usb1 = ubh_get_usb_first(uspi);
739 usb2 = ubh_get_usb_second(USPI_UBH); 736 usb2 = ubh_get_usb_second(uspi);
740 usb3 = ubh_get_usb_third(USPI_UBH); 737 usb3 = ubh_get_usb_third(uspi);
741 usb = (struct ufs_super_block *) 738 usb = (struct ufs_super_block *)
742 ((struct ufs_buffer_head *)uspi)->bh[0]->b_data ; 739 ((struct ufs_buffer_head *)uspi)->bh[0]->b_data ;
743 740
@@ -1006,8 +1003,8 @@ static void ufs_write_super (struct super_block *sb) {
1006 UFSD(("ENTER\n")) 1003 UFSD(("ENTER\n"))
1007 flags = UFS_SB(sb)->s_flags; 1004 flags = UFS_SB(sb)->s_flags;
1008 uspi = UFS_SB(sb)->s_uspi; 1005 uspi = UFS_SB(sb)->s_uspi;
1009 usb1 = ubh_get_usb_first(USPI_UBH); 1006 usb1 = ubh_get_usb_first(uspi);
1010 usb3 = ubh_get_usb_third(USPI_UBH); 1007 usb3 = ubh_get_usb_third(uspi);
1011 1008
1012 if (!(sb->s_flags & MS_RDONLY)) { 1009 if (!(sb->s_flags & MS_RDONLY)) {
1013 usb1->fs_time = cpu_to_fs32(sb, get_seconds()); 1010 usb1->fs_time = cpu_to_fs32(sb, get_seconds());
@@ -1049,8 +1046,8 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
1049 1046
1050 uspi = UFS_SB(sb)->s_uspi; 1047 uspi = UFS_SB(sb)->s_uspi;
1051 flags = UFS_SB(sb)->s_flags; 1048 flags = UFS_SB(sb)->s_flags;
1052 usb1 = ubh_get_usb_first(USPI_UBH); 1049 usb1 = ubh_get_usb_first(uspi);
1053 usb3 = ubh_get_usb_third(USPI_UBH); 1050 usb3 = ubh_get_usb_third(uspi);
1054 1051
1055 /* 1052 /*
1056 * Allow the "check" option to be passed as a remount option. 1053 * Allow the "check" option to be passed as a remount option.
@@ -1124,7 +1121,7 @@ static int ufs_statfs (struct super_block *sb, struct kstatfs *buf)
1124 lock_kernel(); 1121 lock_kernel();
1125 1122
1126 uspi = UFS_SB(sb)->s_uspi; 1123 uspi = UFS_SB(sb)->s_uspi;
1127 usb1 = ubh_get_usb_first (USPI_UBH); 1124 usb1 = ubh_get_usb_first (uspi);
1128 usb = (struct ufs_super_block *) 1125 usb = (struct ufs_super_block *)
1129 ((struct ufs_buffer_head *)uspi)->bh[0]->b_data ; 1126 ((struct ufs_buffer_head *)uspi)->bh[0]->b_data ;
1130 1127
diff --git a/fs/ufs/util.h b/fs/ufs/util.h
index b2640076679a..48d6d9bcc157 100644
--- a/fs/ufs/util.h
+++ b/fs/ufs/util.h
@@ -249,18 +249,28 @@ extern void _ubh_memcpyubh_(struct ufs_sb_private_info *, struct ufs_buffer_head
249 249
250 250
251/* 251/*
252 * macros to get important structures from ufs_buffer_head 252 * macros and inline function to get important structures from ufs_sb_private_info
253 */ 253 */
254#define ubh_get_usb_first(ubh) \
255 ((struct ufs_super_block_first *)((ubh)->bh[0]->b_data))
256 254
257#define ubh_get_usb_second(ubh) \ 255static inline void *get_usb_offset(struct ufs_sb_private_info *uspi,
258 ((struct ufs_super_block_second *)(ubh)-> \ 256 unsigned int offset)
259 bh[UFS_SECTOR_SIZE >> uspi->s_fshift]->b_data + (UFS_SECTOR_SIZE & ~uspi->s_fmask)) 257{
258 unsigned int index;
259
260 index = offset >> uspi->s_fshift;
261 offset &= ~uspi->s_fmask;
262 return uspi->s_ubh.bh[index]->b_data + offset;
263}
264
265#define ubh_get_usb_first(uspi) \
266 ((struct ufs_super_block_first *)get_usb_offset((uspi), 0))
267
268#define ubh_get_usb_second(uspi) \
269 ((struct ufs_super_block_second *)get_usb_offset((uspi), UFS_SECTOR_SIZE))
270
271#define ubh_get_usb_third(uspi) \
272 ((struct ufs_super_block_third *)get_usb_offset((uspi), 2*UFS_SECTOR_SIZE))
260 273
261#define ubh_get_usb_third(ubh) \
262 ((struct ufs_super_block_third *)((ubh)-> \
263 bh[UFS_SECTOR_SIZE*2 >> uspi->s_fshift]->b_data + (UFS_SECTOR_SIZE*2 & ~uspi->s_fmask)))
264 274
265#define ubh_get_ucg(ubh) \ 275#define ubh_get_ucg(ubh) \
266 ((struct ufs_cylinder_group *)((ubh)->bh[0]->b_data)) 276 ((struct ufs_cylinder_group *)((ubh)->bh[0]->b_data))
diff --git a/include/asm-arm/arch-ixp2000/ixp2000-regs.h b/include/asm-arm/arch-ixp2000/ixp2000-regs.h
index 8cf70ff160af..2b57f91b4ebd 100644
--- a/include/asm-arm/arch-ixp2000/ixp2000-regs.h
+++ b/include/asm-arm/arch-ixp2000/ixp2000-regs.h
@@ -26,6 +26,8 @@
26 * fc000000 da000000 16M PCI CFG0 26 * fc000000 da000000 16M PCI CFG0
27 * fd000000 d8000000 16M PCI I/O 27 * fd000000 d8000000 16M PCI I/O
28 * fe[0-7]00000 8M per-platform mappings 28 * fe[0-7]00000 8M per-platform mappings
29 * fe900000 80000000 1M SRAM #0 (first MB)
30 * fea00000 cb400000 1M SCRATCH ring get/put
29 * feb00000 c8000000 1M MSF 31 * feb00000 c8000000 1M MSF
30 * fec00000 df000000 1M PCI CSRs 32 * fec00000 df000000 1M PCI CSRs
31 * fed00000 de000000 1M PCI CREG 33 * fed00000 de000000 1M PCI CREG
@@ -91,6 +93,14 @@
91#define IXP2000_MSF_VIRT_BASE 0xfeb00000 93#define IXP2000_MSF_VIRT_BASE 0xfeb00000
92#define IXP2000_MSF_SIZE 0x00100000 94#define IXP2000_MSF_SIZE 0x00100000
93 95
96#define IXP2000_SCRATCH_RING_PHYS_BASE 0xcb400000
97#define IXP2000_SCRATCH_RING_VIRT_BASE 0xfea00000
98#define IXP2000_SCRATCH_RING_SIZE 0x00100000
99
100#define IXP2000_SRAM0_PHYS_BASE 0x80000000
101#define IXP2000_SRAM0_VIRT_BASE 0xfe900000
102#define IXP2000_SRAM0_SIZE 0x00100000
103
94#define IXP2000_PCI_IO_PHYS_BASE 0xd8000000 104#define IXP2000_PCI_IO_PHYS_BASE 0xd8000000
95#define IXP2000_PCI_IO_VIRT_BASE 0xfd000000 105#define IXP2000_PCI_IO_VIRT_BASE 0xfd000000
96#define IXP2000_PCI_IO_SIZE 0x01000000 106#define IXP2000_PCI_IO_SIZE 0x01000000
diff --git a/include/asm-arm/arch-versatile/entry-macro.S b/include/asm-arm/arch-versatile/entry-macro.S
index 58f0d71759f6..feff771c0a0a 100644
--- a/include/asm-arm/arch-versatile/entry-macro.S
+++ b/include/asm-arm/arch-versatile/entry-macro.S
@@ -8,6 +8,7 @@
8 * warranty of any kind, whether express or implied. 8 * warranty of any kind, whether express or implied.
9 */ 9 */
10#include <asm/hardware.h> 10#include <asm/hardware.h>
11#include <asm/hardware/vic.h>
11 12
12 .macro disable_fiq 13 .macro disable_fiq
13 .endm 14 .endm
diff --git a/include/asm-arm/arch-versatile/platform.h b/include/asm-arm/arch-versatile/platform.h
index cbdd9fb96332..72ef874567d5 100644
--- a/include/asm-arm/arch-versatile/platform.h
+++ b/include/asm-arm/arch-versatile/platform.h
@@ -293,26 +293,7 @@
293 * VERSATILE_SYS_IC 293 * VERSATILE_SYS_IC
294 * 294 *
295 */ 295 */
296#define VIC_IRQ_STATUS 0 296/* VIC definitions in include/asm-arm/hardware/vic.h */
297#define VIC_FIQ_STATUS 0x04
298#define VIC_IRQ_RAW_STATUS 0x08
299#define VIC_INT_SELECT 0x0C /* 1 = FIQ, 0 = IRQ */
300#define VIC_IRQ_ENABLE 0x10 /* 1 = enable, 0 = disable */
301#define VIC_IRQ_ENABLE_CLEAR 0x14
302#define VIC_IRQ_SOFT 0x18
303#define VIC_IRQ_SOFT_CLEAR 0x1C
304#define VIC_PROTECT 0x20
305#define VIC_VECT_ADDR 0x30
306#define VIC_DEF_VECT_ADDR 0x34
307#define VIC_VECT_ADDR0 0x100 /* 0 to 15 */
308#define VIC_VECT_CNTL0 0x200 /* 0 to 15 */
309#define VIC_ITCR 0x300 /* VIC test control register */
310
311#define VIC_FIQ_RAW_STATUS 0x08
312#define VIC_FIQ_ENABLE 0x10 /* 1 = enable, 0 = disable */
313#define VIC_FIQ_ENABLE_CLEAR 0x14
314#define VIC_FIQ_SOFT 0x18
315#define VIC_FIQ_SOFT_CLEAR 0x1C
316 297
317#define SIC_IRQ_STATUS 0 298#define SIC_IRQ_STATUS 0
318#define SIC_IRQ_RAW_STATUS 0x04 299#define SIC_IRQ_RAW_STATUS 0x04
@@ -325,8 +306,6 @@
325#define SIC_INT_PIC_ENABLES 0x20 /* set interrupt pass through bits */ 306#define SIC_INT_PIC_ENABLES 0x20 /* set interrupt pass through bits */
326#define SIC_INT_PIC_ENABLEC 0x24 /* Clear interrupt pass through bits */ 307#define SIC_INT_PIC_ENABLEC 0x24 /* Clear interrupt pass through bits */
327 308
328#define VICVectCntl_Enable (1 << 5)
329
330/* ------------------------------------------------------------------------ 309/* ------------------------------------------------------------------------
331 * Interrupts - bit assignment (primary) 310 * Interrupts - bit assignment (primary)
332 * ------------------------------------------------------------------------ 311 * ------------------------------------------------------------------------
diff --git a/include/asm-arm/hardware/vic.h b/include/asm-arm/hardware/vic.h
new file mode 100644
index 000000000000..81825eb54c9e
--- /dev/null
+++ b/include/asm-arm/hardware/vic.h
@@ -0,0 +1,45 @@
1/*
2 * linux/include/asm-arm/hardware/vic.h
3 *
4 * Copyright (c) ARM Limited 2003. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#ifndef __ASM_ARM_HARDWARE_VIC_H
21#define __ASM_ARM_HARDWARE_VIC_H
22
23#define VIC_IRQ_STATUS 0x00
24#define VIC_FIQ_STATUS 0x04
25#define VIC_RAW_STATUS 0x08
26#define VIC_INT_SELECT 0x0c /* 1 = FIQ, 0 = IRQ */
27#define VIC_INT_ENABLE 0x10 /* 1 = enable, 0 = disable */
28#define VIC_INT_ENABLE_CLEAR 0x14
29#define VIC_INT_SOFT 0x18
30#define VIC_INT_SOFT_CLEAR 0x1c
31#define VIC_PROTECT 0x20
32#define VIC_VECT_ADDR 0x30
33#define VIC_DEF_VECT_ADDR 0x34
34
35#define VIC_VECT_ADDR0 0x100 /* 0 to 15 */
36#define VIC_VECT_CNTL0 0x200 /* 0 to 15 */
37#define VIC_ITCR 0x300 /* VIC test control register */
38
39#define VIC_VECT_CNTL_ENABLE (1 << 5)
40
41#ifndef __ASSEMBLY__
42void vic_init(void __iomem *base, u32 vic_sources);
43#endif
44
45#endif
diff --git a/include/asm-arm/mach/arch.h b/include/asm-arm/mach/arch.h
index eb262e078c46..8222bf9fc366 100644
--- a/include/asm-arm/mach/arch.h
+++ b/include/asm-arm/mach/arch.h
@@ -20,7 +20,7 @@ struct machine_desc {
20 * by assembler code in head-armv.S 20 * by assembler code in head-armv.S
21 */ 21 */
22 unsigned int nr; /* architecture number */ 22 unsigned int nr; /* architecture number */
23 unsigned int phys_ram; /* start of physical ram */ 23 unsigned int __deprecated phys_ram; /* start of physical ram */
24 unsigned int phys_io; /* start of physical io */ 24 unsigned int phys_io; /* start of physical io */
25 unsigned int io_pg_offst; /* byte offset for io 25 unsigned int io_pg_offst; /* byte offset for io
26 * page tabe entry */ 26 * page tabe entry */
diff --git a/include/asm-arm/page.h b/include/asm-arm/page.h
index 4da1d532cbeb..416320d95419 100644
--- a/include/asm-arm/page.h
+++ b/include/asm-arm/page.h
@@ -170,6 +170,13 @@ extern pmd_t *top_pmd;
170#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ 170#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
171 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) 171 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
172 172
173/*
174 * With EABI on ARMv5 and above we must have 64-bit aligned slab pointers.
175 */
176#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5)
177#define ARCH_SLAB_MINALIGN 8
178#endif
179
173#endif /* __KERNEL__ */ 180#endif /* __KERNEL__ */
174 181
175#include <asm-generic/page.h> 182#include <asm-generic/page.h>
diff --git a/include/asm-arm/processor.h b/include/asm-arm/processor.h
index 31290694648b..04f4d34c6317 100644
--- a/include/asm-arm/processor.h
+++ b/include/asm-arm/processor.h
@@ -49,6 +49,12 @@ struct thread_struct {
49 49
50#define INIT_THREAD { } 50#define INIT_THREAD { }
51 51
52#ifdef CONFIG_MMU
53#define nommu_start_thread(regs) do { } while (0)
54#else
55#define nommu_start_thread(regs) regs->ARM_r10 = current->mm->start_data
56#endif
57
52#define start_thread(regs,pc,sp) \ 58#define start_thread(regs,pc,sp) \
53({ \ 59({ \
54 unsigned long *stack = (unsigned long *)sp; \ 60 unsigned long *stack = (unsigned long *)sp; \
@@ -65,6 +71,7 @@ struct thread_struct {
65 regs->ARM_r2 = stack[2]; /* r2 (envp) */ \ 71 regs->ARM_r2 = stack[2]; /* r2 (envp) */ \
66 regs->ARM_r1 = stack[1]; /* r1 (argv) */ \ 72 regs->ARM_r1 = stack[1]; /* r1 (argv) */ \
67 regs->ARM_r0 = stack[0]; /* r0 (argc) */ \ 73 regs->ARM_r0 = stack[0]; /* r0 (argc) */ \
74 nommu_start_thread(regs); \
68}) 75})
69 76
70/* Forward declaration, a strange C thing */ 77/* Forward declaration, a strange C thing */
diff --git a/include/asm-arm/ptrace.h b/include/asm-arm/ptrace.h
index 4377e22b7e1a..77adb7fa169b 100644
--- a/include/asm-arm/ptrace.h
+++ b/include/asm-arm/ptrace.h
@@ -23,6 +23,9 @@
23#define PTRACE_OLDSETOPTIONS 21 23#define PTRACE_OLDSETOPTIONS 21
24 24
25#define PTRACE_GET_THREAD_AREA 22 25#define PTRACE_GET_THREAD_AREA 22
26
27#define PTRACE_SET_SYSCALL 23
28
26/* 29/*
27 * PSR bits 30 * PSR bits
28 */ 31 */
@@ -60,9 +63,11 @@
60 63
61#ifndef __ASSEMBLY__ 64#ifndef __ASSEMBLY__
62 65
63/* this struct defines the way the registers are stored on the 66/*
64 stack during a system call. */ 67 * This struct defines the way the registers are stored on the
65 68 * stack during a system call. Note that sizeof(struct pt_regs)
69 * has to be a multiple of 8.
70 */
66struct pt_regs { 71struct pt_regs {
67 long uregs[18]; 72 long uregs[18];
68}; 73};
diff --git a/include/asm-arm/stat.h b/include/asm-arm/stat.h
index ec4e2c2e3b47..42c0c13999d5 100644
--- a/include/asm-arm/stat.h
+++ b/include/asm-arm/stat.h
@@ -70,14 +70,7 @@ struct stat64 {
70 70
71 long long st_size; 71 long long st_size;
72 unsigned long st_blksize; 72 unsigned long st_blksize;
73 73 unsigned long long st_blocks; /* Number 512-byte blocks allocated. */
74#if defined(__ARMEB__)
75 unsigned long __pad4; /* Future possible st_blocks hi bits */
76 unsigned long st_blocks; /* Number 512-byte blocks allocated. */
77#else /* Must be little */
78 unsigned long st_blocks; /* Number 512-byte blocks allocated. */
79 unsigned long __pad4; /* Future possible st_blocks hi bits */
80#endif
81 74
82 unsigned long st_atime; 75 unsigned long st_atime;
83 unsigned long st_atime_nsec; 76 unsigned long st_atime_nsec;
@@ -89,6 +82,6 @@ struct stat64 {
89 unsigned long st_ctime_nsec; 82 unsigned long st_ctime_nsec;
90 83
91 unsigned long long st_ino; 84 unsigned long long st_ino;
92} __attribute__((packed)); 85};
93 86
94#endif 87#endif
diff --git a/include/asm-arm/statfs.h b/include/asm-arm/statfs.h
index e81f82783b87..a02e6a8c3d70 100644
--- a/include/asm-arm/statfs.h
+++ b/include/asm-arm/statfs.h
@@ -1,6 +1,42 @@
1#ifndef _ASMARM_STATFS_H 1#ifndef _ASMARM_STATFS_H
2#define _ASMARM_STATFS_H 2#define _ASMARM_STATFS_H
3 3
4#include <asm-generic/statfs.h> 4#ifndef __KERNEL_STRICT_NAMES
5# include <linux/types.h>
6typedef __kernel_fsid_t fsid_t;
7#endif
8
9struct statfs {
10 __u32 f_type;
11 __u32 f_bsize;
12 __u32 f_blocks;
13 __u32 f_bfree;
14 __u32 f_bavail;
15 __u32 f_files;
16 __u32 f_ffree;
17 __kernel_fsid_t f_fsid;
18 __u32 f_namelen;
19 __u32 f_frsize;
20 __u32 f_spare[5];
21};
22
23/*
24 * With EABI there is 4 bytes of padding added to this structure.
25 * Let's pack it so the padding goes away to simplify dual ABI support.
26 * Note that user space does NOT have to pack this structure.
27 */
28struct statfs64 {
29 __u32 f_type;
30 __u32 f_bsize;
31 __u64 f_blocks;
32 __u64 f_bfree;
33 __u64 f_bavail;
34 __u64 f_files;
35 __u64 f_ffree;
36 __kernel_fsid_t f_fsid;
37 __u32 f_namelen;
38 __u32 f_frsize;
39 __u32 f_spare[5];
40} __attribute__ ((packed,aligned(4)));
5 41
6#endif 42#endif
diff --git a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h
index d626e70faded..77430d6178ae 100644
--- a/include/asm-arm/unistd.h
+++ b/include/asm-arm/unistd.h
@@ -15,10 +15,12 @@
15 15
16#include <linux/linkage.h> 16#include <linux/linkage.h>
17 17
18#if defined(__thumb__) 18#define __NR_OABI_SYSCALL_BASE 0x900000
19
20#if defined(__thumb__) || defined(__ARM_EABI__)
19#define __NR_SYSCALL_BASE 0 21#define __NR_SYSCALL_BASE 0
20#else 22#else
21#define __NR_SYSCALL_BASE 0x900000 23#define __NR_SYSCALL_BASE __NR_OABI_SYSCALL_BASE
22#endif 24#endif
23 25
24/* 26/*
@@ -373,13 +375,13 @@
373#define __sys1(x) __sys2(x) 375#define __sys1(x) __sys2(x)
374 376
375#ifndef __syscall 377#ifndef __syscall
376#if defined(__thumb__) 378#if defined(__thumb__) || defined(__ARM_EABI__)
377#define __syscall(name) \ 379#define __SYS_REG(name) register long __sysreg __asm__("r7") = __NR_##name;
378 "push {r7}\n\t" \ 380#define __SYS_REG_LIST(regs...) "r" (__sysreg) , ##regs
379 "mov r7, #" __sys1(__NR_##name) "\n\t" \ 381#define __syscall(name) "swi\t0"
380 "swi 0\n\t" \
381 "pop {r7}"
382#else 382#else
383#define __SYS_REG(name)
384#define __SYS_REG_LIST(regs...) regs
383#define __syscall(name) "swi\t" __sys1(__NR_##name) "" 385#define __syscall(name) "swi\t" __sys1(__NR_##name) ""
384#endif 386#endif
385#endif 387#endif
@@ -395,33 +397,34 @@ do { \
395 397
396#define _syscall0(type,name) \ 398#define _syscall0(type,name) \
397type name(void) { \ 399type name(void) { \
400 __SYS_REG(name) \
398 register long __res_r0 __asm__("r0"); \ 401 register long __res_r0 __asm__("r0"); \
399 long __res; \ 402 long __res; \
400 __asm__ __volatile__ ( \ 403 __asm__ __volatile__ ( \
401 __syscall(name) \ 404 __syscall(name) \
402 : "=r" (__res_r0) \ 405 : "=r" (__res_r0) \
403 : \ 406 : __SYS_REG_LIST() ); \
404 : "lr"); \
405 __res = __res_r0; \ 407 __res = __res_r0; \
406 __syscall_return(type,__res); \ 408 __syscall_return(type,__res); \
407} 409}
408 410
409#define _syscall1(type,name,type1,arg1) \ 411#define _syscall1(type,name,type1,arg1) \
410type name(type1 arg1) { \ 412type name(type1 arg1) { \
413 __SYS_REG(name) \
411 register long __r0 __asm__("r0") = (long)arg1; \ 414 register long __r0 __asm__("r0") = (long)arg1; \
412 register long __res_r0 __asm__("r0"); \ 415 register long __res_r0 __asm__("r0"); \
413 long __res; \ 416 long __res; \
414 __asm__ __volatile__ ( \ 417 __asm__ __volatile__ ( \
415 __syscall(name) \ 418 __syscall(name) \
416 : "=r" (__res_r0) \ 419 : "=r" (__res_r0) \
417 : "r" (__r0) \ 420 : __SYS_REG_LIST( "0" (__r0) ) ); \
418 : "lr"); \
419 __res = __res_r0; \ 421 __res = __res_r0; \
420 __syscall_return(type,__res); \ 422 __syscall_return(type,__res); \
421} 423}
422 424
423#define _syscall2(type,name,type1,arg1,type2,arg2) \ 425#define _syscall2(type,name,type1,arg1,type2,arg2) \
424type name(type1 arg1,type2 arg2) { \ 426type name(type1 arg1,type2 arg2) { \
427 __SYS_REG(name) \
425 register long __r0 __asm__("r0") = (long)arg1; \ 428 register long __r0 __asm__("r0") = (long)arg1; \
426 register long __r1 __asm__("r1") = (long)arg2; \ 429 register long __r1 __asm__("r1") = (long)arg2; \
427 register long __res_r0 __asm__("r0"); \ 430 register long __res_r0 __asm__("r0"); \
@@ -429,8 +432,7 @@ type name(type1 arg1,type2 arg2) { \
429 __asm__ __volatile__ ( \ 432 __asm__ __volatile__ ( \
430 __syscall(name) \ 433 __syscall(name) \
431 : "=r" (__res_r0) \ 434 : "=r" (__res_r0) \
432 : "r" (__r0),"r" (__r1) \ 435 : __SYS_REG_LIST( "0" (__r0), "r" (__r1) ) ); \
433 : "lr"); \
434 __res = __res_r0; \ 436 __res = __res_r0; \
435 __syscall_return(type,__res); \ 437 __syscall_return(type,__res); \
436} 438}
@@ -438,6 +440,7 @@ type name(type1 arg1,type2 arg2) { \
438 440
439#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ 441#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
440type name(type1 arg1,type2 arg2,type3 arg3) { \ 442type name(type1 arg1,type2 arg2,type3 arg3) { \
443 __SYS_REG(name) \
441 register long __r0 __asm__("r0") = (long)arg1; \ 444 register long __r0 __asm__("r0") = (long)arg1; \
442 register long __r1 __asm__("r1") = (long)arg2; \ 445 register long __r1 __asm__("r1") = (long)arg2; \
443 register long __r2 __asm__("r2") = (long)arg3; \ 446 register long __r2 __asm__("r2") = (long)arg3; \
@@ -446,8 +449,7 @@ type name(type1 arg1,type2 arg2,type3 arg3) { \
446 __asm__ __volatile__ ( \ 449 __asm__ __volatile__ ( \
447 __syscall(name) \ 450 __syscall(name) \
448 : "=r" (__res_r0) \ 451 : "=r" (__res_r0) \
449 : "r" (__r0),"r" (__r1),"r" (__r2) \ 452 : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2) ) ); \
450 : "lr"); \
451 __res = __res_r0; \ 453 __res = __res_r0; \
452 __syscall_return(type,__res); \ 454 __syscall_return(type,__res); \
453} 455}
@@ -455,6 +457,7 @@ type name(type1 arg1,type2 arg2,type3 arg3) { \
455 457
456#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4)\ 458#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4)\
457type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ 459type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
460 __SYS_REG(name) \
458 register long __r0 __asm__("r0") = (long)arg1; \ 461 register long __r0 __asm__("r0") = (long)arg1; \
459 register long __r1 __asm__("r1") = (long)arg2; \ 462 register long __r1 __asm__("r1") = (long)arg2; \
460 register long __r2 __asm__("r2") = (long)arg3; \ 463 register long __r2 __asm__("r2") = (long)arg3; \
@@ -464,8 +467,7 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
464 __asm__ __volatile__ ( \ 467 __asm__ __volatile__ ( \
465 __syscall(name) \ 468 __syscall(name) \
466 : "=r" (__res_r0) \ 469 : "=r" (__res_r0) \
467 : "r" (__r0),"r" (__r1),"r" (__r2),"r" (__r3) \ 470 : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2), "r" (__r3) ) ); \
468 : "lr"); \
469 __res = __res_r0; \ 471 __res = __res_r0; \
470 __syscall_return(type,__res); \ 472 __syscall_return(type,__res); \
471} 473}
@@ -473,6 +475,7 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
473 475
474#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \ 476#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \
475type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \ 477type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \
478 __SYS_REG(name) \
476 register long __r0 __asm__("r0") = (long)arg1; \ 479 register long __r0 __asm__("r0") = (long)arg1; \
477 register long __r1 __asm__("r1") = (long)arg2; \ 480 register long __r1 __asm__("r1") = (long)arg2; \
478 register long __r2 __asm__("r2") = (long)arg3; \ 481 register long __r2 __asm__("r2") = (long)arg3; \
@@ -483,14 +486,15 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \
483 __asm__ __volatile__ ( \ 486 __asm__ __volatile__ ( \
484 __syscall(name) \ 487 __syscall(name) \
485 : "=r" (__res_r0) \ 488 : "=r" (__res_r0) \
486 : "r" (__r0),"r" (__r1),"r" (__r2),"r" (__r3),"r" (__r4) \ 489 : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2), \
487 : "lr"); \ 490 "r" (__r3), "r" (__r4) ) ); \
488 __res = __res_r0; \ 491 __res = __res_r0; \
489 __syscall_return(type,__res); \ 492 __syscall_return(type,__res); \
490} 493}
491 494
492#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \ 495#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \
493type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) { \ 496type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) { \
497 __SYS_REG(name) \
494 register long __r0 __asm__("r0") = (long)arg1; \ 498 register long __r0 __asm__("r0") = (long)arg1; \
495 register long __r1 __asm__("r1") = (long)arg2; \ 499 register long __r1 __asm__("r1") = (long)arg2; \
496 register long __r2 __asm__("r2") = (long)arg3; \ 500 register long __r2 __asm__("r2") = (long)arg3; \
@@ -502,30 +506,33 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6
502 __asm__ __volatile__ ( \ 506 __asm__ __volatile__ ( \
503 __syscall(name) \ 507 __syscall(name) \
504 : "=r" (__res_r0) \ 508 : "=r" (__res_r0) \
505 : "r" (__r0),"r" (__r1),"r" (__r2),"r" (__r3), "r" (__r4),"r" (__r5) \ 509 : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2), \
506 : "lr"); \ 510 "r" (__r3), "r" (__r4), "r" (__r5) ) ); \
507 __res = __res_r0; \ 511 __res = __res_r0; \
508 __syscall_return(type,__res); \ 512 __syscall_return(type,__res); \
509} 513}
510 514
511#ifdef __KERNEL__ 515#ifdef __KERNEL__
512#define __ARCH_WANT_IPC_PARSE_VERSION 516#define __ARCH_WANT_IPC_PARSE_VERSION
513#define __ARCH_WANT_OLD_READDIR
514#define __ARCH_WANT_STAT64 517#define __ARCH_WANT_STAT64
515#define __ARCH_WANT_SYS_ALARM
516#define __ARCH_WANT_SYS_GETHOSTNAME 518#define __ARCH_WANT_SYS_GETHOSTNAME
517#define __ARCH_WANT_SYS_PAUSE 519#define __ARCH_WANT_SYS_PAUSE
518#define __ARCH_WANT_SYS_TIME
519#define __ARCH_WANT_SYS_UTIME
520#define __ARCH_WANT_SYS_SOCKETCALL
521#define __ARCH_WANT_SYS_GETPGRP 520#define __ARCH_WANT_SYS_GETPGRP
522#define __ARCH_WANT_SYS_LLSEEK 521#define __ARCH_WANT_SYS_LLSEEK
523#define __ARCH_WANT_SYS_NICE 522#define __ARCH_WANT_SYS_NICE
524#define __ARCH_WANT_SYS_OLD_GETRLIMIT
525#define __ARCH_WANT_SYS_OLDUMOUNT
526#define __ARCH_WANT_SYS_SIGPENDING 523#define __ARCH_WANT_SYS_SIGPENDING
527#define __ARCH_WANT_SYS_SIGPROCMASK 524#define __ARCH_WANT_SYS_SIGPROCMASK
528#define __ARCH_WANT_SYS_RT_SIGACTION 525#define __ARCH_WANT_SYS_RT_SIGACTION
526
527#if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT)
528#define __ARCH_WANT_SYS_TIME
529#define __ARCH_WANT_SYS_OLDUMOUNT
530#define __ARCH_WANT_SYS_ALARM
531#define __ARCH_WANT_SYS_UTIME
532#define __ARCH_WANT_SYS_OLD_GETRLIMIT
533#define __ARCH_WANT_OLD_READDIR
534#define __ARCH_WANT_SYS_SOCKETCALL
535#endif
529#endif 536#endif
530 537
531#ifdef __KERNEL_SYSCALLS__ 538#ifdef __KERNEL_SYSCALLS__
diff --git a/include/asm-i386/bitops.h b/include/asm-i386/bitops.h
index fe0819fe9c64..88e6ca248cd7 100644
--- a/include/asm-i386/bitops.h
+++ b/include/asm-i386/bitops.h
@@ -247,7 +247,7 @@ static inline int test_and_change_bit(int nr, volatile unsigned long* addr)
247static int test_bit(int nr, const volatile void * addr); 247static int test_bit(int nr, const volatile void * addr);
248#endif 248#endif
249 249
250static inline int constant_test_bit(int nr, const volatile unsigned long *addr) 250static __always_inline int constant_test_bit(int nr, const volatile unsigned long *addr)
251{ 251{
252 return ((1UL << (nr & 31)) & (addr[nr >> 5])) != 0; 252 return ((1UL << (nr & 31)) & (addr[nr >> 5])) != 0;
253} 253}
diff --git a/include/asm-i386/current.h b/include/asm-i386/current.h
index d97328951f5f..3cbbecd79016 100644
--- a/include/asm-i386/current.h
+++ b/include/asm-i386/current.h
@@ -5,7 +5,7 @@
5 5
6struct task_struct; 6struct task_struct;
7 7
8static inline struct task_struct * get_current(void) 8static __always_inline struct task_struct * get_current(void)
9{ 9{
10 return current_thread_info()->task; 10 return current_thread_info()->task;
11} 11}
diff --git a/include/asm-i386/string.h b/include/asm-i386/string.h
index 02c8f5d22065..bb5f88a27f7a 100644
--- a/include/asm-i386/string.h
+++ b/include/asm-i386/string.h
@@ -201,7 +201,7 @@ __asm__ __volatile__(
201return __res; 201return __res;
202} 202}
203 203
204static inline void * __memcpy(void * to, const void * from, size_t n) 204static __always_inline void * __memcpy(void * to, const void * from, size_t n)
205{ 205{
206int d0, d1, d2; 206int d0, d1, d2;
207__asm__ __volatile__( 207__asm__ __volatile__(
@@ -223,7 +223,7 @@ return (to);
223 * This looks ugly, but the compiler can optimize it totally, 223 * This looks ugly, but the compiler can optimize it totally,
224 * as the count is constant. 224 * as the count is constant.
225 */ 225 */
226static inline void * __constant_memcpy(void * to, const void * from, size_t n) 226static __always_inline void * __constant_memcpy(void * to, const void * from, size_t n)
227{ 227{
228 long esi, edi; 228 long esi, edi;
229 if (!n) return to; 229 if (!n) return to;
@@ -367,7 +367,7 @@ return s;
367 * things 32 bits at a time even when we don't know the size of the 367 * things 32 bits at a time even when we don't know the size of the
368 * area at compile-time.. 368 * area at compile-time..
369 */ 369 */
370static inline void * __constant_c_memset(void * s, unsigned long c, size_t count) 370static __always_inline void * __constant_c_memset(void * s, unsigned long c, size_t count)
371{ 371{
372int d0, d1; 372int d0, d1;
373__asm__ __volatile__( 373__asm__ __volatile__(
@@ -416,7 +416,7 @@ extern char *strstr(const char *cs, const char *ct);
416 * This looks horribly ugly, but the compiler can optimize it totally, 416 * This looks horribly ugly, but the compiler can optimize it totally,
417 * as we by now know that both pattern and count is constant.. 417 * as we by now know that both pattern and count is constant..
418 */ 418 */
419static inline void * __constant_c_and_count_memset(void * s, unsigned long pattern, size_t count) 419static __always_inline void * __constant_c_and_count_memset(void * s, unsigned long pattern, size_t count)
420{ 420{
421 switch (count) { 421 switch (count) {
422 case 0: 422 case 0:
diff --git a/include/asm-i386/uaccess.h b/include/asm-i386/uaccess.h
index 89ab7e2bc5aa..3f1337c34208 100644
--- a/include/asm-i386/uaccess.h
+++ b/include/asm-i386/uaccess.h
@@ -411,7 +411,7 @@ unsigned long __must_check __copy_from_user_ll(void *to,
411 * Returns number of bytes that could not be copied. 411 * Returns number of bytes that could not be copied.
412 * On success, this will be zero. 412 * On success, this will be zero.
413 */ 413 */
414static inline unsigned long __must_check 414static __always_inline unsigned long __must_check
415__copy_to_user_inatomic(void __user *to, const void *from, unsigned long n) 415__copy_to_user_inatomic(void __user *to, const void *from, unsigned long n)
416{ 416{
417 if (__builtin_constant_p(n)) { 417 if (__builtin_constant_p(n)) {
@@ -432,7 +432,7 @@ __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n)
432 return __copy_to_user_ll(to, from, n); 432 return __copy_to_user_ll(to, from, n);
433} 433}
434 434
435static inline unsigned long __must_check 435static __always_inline unsigned long __must_check
436__copy_to_user(void __user *to, const void *from, unsigned long n) 436__copy_to_user(void __user *to, const void *from, unsigned long n)
437{ 437{
438 might_sleep(); 438 might_sleep();
@@ -456,7 +456,7 @@ __copy_to_user(void __user *to, const void *from, unsigned long n)
456 * If some data could not be copied, this function will pad the copied 456 * If some data could not be copied, this function will pad the copied
457 * data to the requested size using zero bytes. 457 * data to the requested size using zero bytes.
458 */ 458 */
459static inline unsigned long 459static __always_inline unsigned long
460__copy_from_user_inatomic(void *to, const void __user *from, unsigned long n) 460__copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
461{ 461{
462 if (__builtin_constant_p(n)) { 462 if (__builtin_constant_p(n)) {
@@ -477,7 +477,7 @@ __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
477 return __copy_from_user_ll(to, from, n); 477 return __copy_from_user_ll(to, from, n);
478} 478}
479 479
480static inline unsigned long 480static __always_inline unsigned long
481__copy_from_user(void *to, const void __user *from, unsigned long n) 481__copy_from_user(void *to, const void __user *from, unsigned long n)
482{ 482{
483 might_sleep(); 483 might_sleep();
diff --git a/include/asm-ia64/kprobes.h b/include/asm-ia64/kprobes.h
index a74b68104559..8c0fc227f0fb 100644
--- a/include/asm-ia64/kprobes.h
+++ b/include/asm-ia64/kprobes.h
@@ -68,10 +68,14 @@ struct prev_kprobe {
68 unsigned long status; 68 unsigned long status;
69}; 69};
70 70
71#define MAX_PARAM_RSE_SIZE (0x60+0x60/0x3f)
71/* per-cpu kprobe control block */ 72/* per-cpu kprobe control block */
72struct kprobe_ctlblk { 73struct kprobe_ctlblk {
73 unsigned long kprobe_status; 74 unsigned long kprobe_status;
74 struct pt_regs jprobe_saved_regs; 75 struct pt_regs jprobe_saved_regs;
76 unsigned long jprobes_saved_stacked_regs[MAX_PARAM_RSE_SIZE];
77 unsigned long *bsp;
78 unsigned long cfm;
75 struct prev_kprobe prev_kprobe; 79 struct prev_kprobe prev_kprobe;
76}; 80};
77 81
@@ -118,5 +122,7 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
118static inline void jprobe_return(void) 122static inline void jprobe_return(void)
119{ 123{
120} 124}
125extern void invalidate_stacked_regs(void);
126extern void flush_register_stack(void);
121 127
122#endif /* _ASM_KPROBES_H */ 128#endif /* _ASM_KPROBES_H */
diff --git a/include/asm-ia64/sn/ioc3.h b/include/asm-ia64/sn/ioc3.h
new file mode 100644
index 000000000000..95ed6cc83cf1
--- /dev/null
+++ b/include/asm-ia64/sn/ioc3.h
@@ -0,0 +1,241 @@
1/*
2 * Copyright (C) 2005 Silicon Graphics, Inc.
3 */
4#ifndef IA64_SN_IOC3_H
5#define IA64_SN_IOC3_H
6
7/* serial port register map */
8struct ioc3_serialregs {
9 uint32_t sscr;
10 uint32_t stpir;
11 uint32_t stcir;
12 uint32_t srpir;
13 uint32_t srcir;
14 uint32_t srtr;
15 uint32_t shadow;
16};
17
18/* SUPERIO uart register map */
19struct ioc3_uartregs {
20 char iu_lcr;
21 union {
22 char iir; /* read only */
23 char fcr; /* write only */
24 } u3;
25 union {
26 char ier; /* DLAB == 0 */
27 char dlm; /* DLAB == 1 */
28 } u2;
29 union {
30 char rbr; /* read only, DLAB == 0 */
31 char thr; /* write only, DLAB == 0 */
32 char dll; /* DLAB == 1 */
33 } u1;
34 char iu_scr;
35 char iu_msr;
36 char iu_lsr;
37 char iu_mcr;
38};
39
40#define iu_rbr u1.rbr
41#define iu_thr u1.thr
42#define iu_dll u1.dll
43#define iu_ier u2.ier
44#define iu_dlm u2.dlm
45#define iu_iir u3.iir
46#define iu_fcr u3.fcr
47
48struct ioc3_sioregs {
49 char fill[0x170];
50 struct ioc3_uartregs uartb;
51 struct ioc3_uartregs uarta;
52};
53
54/* PCI IO/mem space register map */
55struct ioc3 {
56 uint32_t pci_id;
57 uint32_t pci_scr;
58 uint32_t pci_rev;
59 uint32_t pci_lat;
60 uint32_t pci_addr;
61 uint32_t pci_err_addr_l;
62 uint32_t pci_err_addr_h;
63
64 uint32_t sio_ir;
65 /* these registers are read-only for general kernel code. To
66 * modify them use the functions in ioc3.c
67 */
68 uint32_t sio_ies;
69 uint32_t sio_iec;
70 uint32_t sio_cr;
71 uint32_t int_out;
72 uint32_t mcr;
73 uint32_t gpcr_s;
74 uint32_t gpcr_c;
75 uint32_t gpdr;
76 uint32_t gppr[9];
77 char fill[0x4c];
78
79 /* serial port registers */
80 uint32_t sbbr_h;
81 uint32_t sbbr_l;
82
83 struct ioc3_serialregs port_a;
84 struct ioc3_serialregs port_b;
85 char fill1[0x1ff10];
86 /* superio registers */
87 struct ioc3_sioregs sregs;
88};
89
90/* These don't exist on the ioc3 serial card... */
91#define eier fill1[8]
92#define eisr fill1[4]
93
94#define PCI_LAT 0xc /* Latency Timer */
95#define PCI_SCR_DROP_MODE_EN 0x00008000 /* drop pios on parity err */
96#define UARTA_BASE 0x178
97#define UARTB_BASE 0x170
98
99
100/* bitmasks for serial RX status byte */
101#define RXSB_OVERRUN 0x01 /* char(s) lost */
102#define RXSB_PAR_ERR 0x02 /* parity error */
103#define RXSB_FRAME_ERR 0x04 /* framing error */
104#define RXSB_BREAK 0x08 /* break character */
105#define RXSB_CTS 0x10 /* state of CTS */
106#define RXSB_DCD 0x20 /* state of DCD */
107#define RXSB_MODEM_VALID 0x40 /* DCD, CTS and OVERRUN are valid */
108#define RXSB_DATA_VALID 0x80 /* FRAME_ERR PAR_ERR & BREAK valid */
109
110/* bitmasks for serial TX control byte */
111#define TXCB_INT_WHEN_DONE 0x20 /* interrupt after this byte is sent */
112#define TXCB_INVALID 0x00 /* byte is invalid */
113#define TXCB_VALID 0x40 /* byte is valid */
114#define TXCB_MCR 0x80 /* data<7:0> to modem cntrl register */
115#define TXCB_DELAY 0xc0 /* delay data<7:0> mSec */
116
117/* bitmasks for SBBR_L */
118#define SBBR_L_SIZE 0x00000001 /* 0 1KB rings, 1 4KB rings */
119
120/* bitmasks for SSCR_<A:B> */
121#define SSCR_RX_THRESHOLD 0x000001ff /* hiwater mark */
122#define SSCR_TX_TIMER_BUSY 0x00010000 /* TX timer in progress */
123#define SSCR_HFC_EN 0x00020000 /* h/w flow cntrl enabled */
124#define SSCR_RX_RING_DCD 0x00040000 /* postRX record on delta-DCD */
125#define SSCR_RX_RING_CTS 0x00080000 /* postRX record on delta-CTS */
126#define SSCR_HIGH_SPD 0x00100000 /* 4X speed */
127#define SSCR_DIAG 0x00200000 /* bypass clock divider */
128#define SSCR_RX_DRAIN 0x08000000 /* drain RX buffer to memory */
129#define SSCR_DMA_EN 0x10000000 /* enable ring buffer DMA */
130#define SSCR_DMA_PAUSE 0x20000000 /* pause DMA */
131#define SSCR_PAUSE_STATE 0x40000000 /* set when PAUSE takes effect*/
132#define SSCR_RESET 0x80000000 /* reset DMA channels */
133
134/* all producer/comsumer pointers are the same bitfield */
135#define PROD_CONS_PTR_4K 0x00000ff8 /* for 4K buffers */
136#define PROD_CONS_PTR_1K 0x000003f8 /* for 1K buffers */
137#define PROD_CONS_PTR_OFF 3
138
139/* bitmasks for SRCIR_<A:B> */
140#define SRCIR_ARM 0x80000000 /* arm RX timer */
141
142/* bitmasks for SHADOW_<A:B> */
143#define SHADOW_DR 0x00000001 /* data ready */
144#define SHADOW_OE 0x00000002 /* overrun error */
145#define SHADOW_PE 0x00000004 /* parity error */
146#define SHADOW_FE 0x00000008 /* framing error */
147#define SHADOW_BI 0x00000010 /* break interrupt */
148#define SHADOW_THRE 0x00000020 /* transmit holding reg empty */
149#define SHADOW_TEMT 0x00000040 /* transmit shift reg empty */
150#define SHADOW_RFCE 0x00000080 /* char in RX fifo has error */
151#define SHADOW_DCTS 0x00010000 /* delta clear to send */
152#define SHADOW_DDCD 0x00080000 /* delta data carrier detect */
153#define SHADOW_CTS 0x00100000 /* clear to send */
154#define SHADOW_DCD 0x00800000 /* data carrier detect */
155#define SHADOW_DTR 0x01000000 /* data terminal ready */
156#define SHADOW_RTS 0x02000000 /* request to send */
157#define SHADOW_OUT1 0x04000000 /* 16550 OUT1 bit */
158#define SHADOW_OUT2 0x08000000 /* 16550 OUT2 bit */
159#define SHADOW_LOOP 0x10000000 /* loopback enabled */
160
161/* bitmasks for SRTR_<A:B> */
162#define SRTR_CNT 0x00000fff /* reload value for RX timer */
163#define SRTR_CNT_VAL 0x0fff0000 /* current value of RX timer */
164#define SRTR_CNT_VAL_SHIFT 16
165#define SRTR_HZ 16000 /* SRTR clock frequency */
166
167/* bitmasks for SIO_IR, SIO_IEC and SIO_IES */
168#define SIO_IR_SA_TX_MT 0x00000001 /* Serial port A TX empty */
169#define SIO_IR_SA_RX_FULL 0x00000002 /* port A RX buf full */
170#define SIO_IR_SA_RX_HIGH 0x00000004 /* port A RX hiwat */
171#define SIO_IR_SA_RX_TIMER 0x00000008 /* port A RX timeout */
172#define SIO_IR_SA_DELTA_DCD 0x00000010 /* port A delta DCD */
173#define SIO_IR_SA_DELTA_CTS 0x00000020 /* port A delta CTS */
174#define SIO_IR_SA_INT 0x00000040 /* port A pass-thru intr */
175#define SIO_IR_SA_TX_EXPLICIT 0x00000080 /* port A explicit TX thru */
176#define SIO_IR_SA_MEMERR 0x00000100 /* port A PCI error */
177#define SIO_IR_SB_TX_MT 0x00000200
178#define SIO_IR_SB_RX_FULL 0x00000400
179#define SIO_IR_SB_RX_HIGH 0x00000800
180#define SIO_IR_SB_RX_TIMER 0x00001000
181#define SIO_IR_SB_DELTA_DCD 0x00002000
182#define SIO_IR_SB_DELTA_CTS 0x00004000
183#define SIO_IR_SB_INT 0x00008000
184#define SIO_IR_SB_TX_EXPLICIT 0x00010000
185#define SIO_IR_SB_MEMERR 0x00020000
186#define SIO_IR_PP_INT 0x00040000 /* P port pass-thru intr */
187#define SIO_IR_PP_INTA 0x00080000 /* PP context A thru */
188#define SIO_IR_PP_INTB 0x00100000 /* PP context B thru */
189#define SIO_IR_PP_MEMERR 0x00200000 /* PP PCI error */
190#define SIO_IR_KBD_INT 0x00400000 /* kbd/mouse intr */
191#define SIO_IR_RT_INT 0x08000000 /* RT output pulse */
192#define SIO_IR_GEN_INT1 0x10000000 /* RT input pulse */
193#define SIO_IR_GEN_INT_SHIFT 28
194
195/* per device interrupt masks */
196#define SIO_IR_SA (SIO_IR_SA_TX_MT | \
197 SIO_IR_SA_RX_FULL | \
198 SIO_IR_SA_RX_HIGH | \
199 SIO_IR_SA_RX_TIMER | \
200 SIO_IR_SA_DELTA_DCD | \
201 SIO_IR_SA_DELTA_CTS | \
202 SIO_IR_SA_INT | \
203 SIO_IR_SA_TX_EXPLICIT | \
204 SIO_IR_SA_MEMERR)
205
206#define SIO_IR_SB (SIO_IR_SB_TX_MT | \
207 SIO_IR_SB_RX_FULL | \
208 SIO_IR_SB_RX_HIGH | \
209 SIO_IR_SB_RX_TIMER | \
210 SIO_IR_SB_DELTA_DCD | \
211 SIO_IR_SB_DELTA_CTS | \
212 SIO_IR_SB_INT | \
213 SIO_IR_SB_TX_EXPLICIT | \
214 SIO_IR_SB_MEMERR)
215
216#define SIO_IR_PP (SIO_IR_PP_INT | SIO_IR_PP_INTA | \
217 SIO_IR_PP_INTB | SIO_IR_PP_MEMERR)
218#define SIO_IR_RT (SIO_IR_RT_INT | SIO_IR_GEN_INT1)
219
220/* bitmasks for SIO_CR */
221#define SIO_CR_CMD_PULSE_SHIFT 15
222#define SIO_CR_SER_A_BASE_SHIFT 1
223#define SIO_CR_SER_B_BASE_SHIFT 8
224#define SIO_CR_ARB_DIAG 0x00380000 /* cur !enet PCI requet (ro) */
225#define SIO_CR_ARB_DIAG_TXA 0x00000000
226#define SIO_CR_ARB_DIAG_RXA 0x00080000
227#define SIO_CR_ARB_DIAG_TXB 0x00100000
228#define SIO_CR_ARB_DIAG_RXB 0x00180000
229#define SIO_CR_ARB_DIAG_PP 0x00200000
230#define SIO_CR_ARB_DIAG_IDLE 0x00400000 /* 0 -> active request (ro) */
231
232/* defs for some of the generic I/O pins */
233#define GPCR_PHY_RESET 0x20 /* pin is output to PHY reset */
234#define GPCR_UARTB_MODESEL 0x40 /* pin is output to port B mode sel */
235#define GPCR_UARTA_MODESEL 0x80 /* pin is output to port A mode sel */
236
237#define GPPR_PHY_RESET_PIN 5 /* GIO pin controlling phy reset */
238#define GPPR_UARTB_MODESEL_PIN 6 /* GIO pin cntrling uartb modeselect */
239#define GPPR_UARTA_MODESEL_PIN 7 /* GIO pin cntrling uarta modeselect */
240
241#endif /* IA64_SN_IOC3_H */
diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h
index 2a8b0d92a5d6..8b9e10e7cdba 100644
--- a/include/asm-ia64/sn/sn_sal.h
+++ b/include/asm-ia64/sn/sn_sal.h
@@ -75,7 +75,8 @@
75#define SN_SAL_IOIF_GET_HUBDEV_INFO 0x02000055 75#define SN_SAL_IOIF_GET_HUBDEV_INFO 0x02000055
76#define SN_SAL_IOIF_GET_PCIBUS_INFO 0x02000056 76#define SN_SAL_IOIF_GET_PCIBUS_INFO 0x02000056
77#define SN_SAL_IOIF_GET_PCIDEV_INFO 0x02000057 77#define SN_SAL_IOIF_GET_PCIDEV_INFO 0x02000057
78#define SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST 0x02000058 78#define SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST 0x02000058 // deprecated
79#define SN_SAL_IOIF_GET_DEVICE_DMAFLUSH_LIST 0x0200005a
79 80
80#define SN_SAL_HUB_ERROR_INTERRUPT 0x02000060 81#define SN_SAL_HUB_ERROR_INTERRUPT 0x02000060
81#define SN_SAL_BTE_RECOVER 0x02000061 82#define SN_SAL_BTE_RECOVER 0x02000061
@@ -1100,7 +1101,7 @@ ia64_sn_bte_recovery(nasid_t nasid)
1100 struct ia64_sal_retval rv; 1101 struct ia64_sal_retval rv;
1101 1102
1102 rv.status = 0; 1103 rv.status = 0;
1103 SAL_CALL_NOLOCK(rv, SN_SAL_BTE_RECOVER, 0, 0, 0, 0, 0, 0, 0); 1104 SAL_CALL_NOLOCK(rv, SN_SAL_BTE_RECOVER, (u64)nasid, 0, 0, 0, 0, 0, 0);
1104 if (rv.status == SALRET_NOT_IMPLEMENTED) 1105 if (rv.status == SALRET_NOT_IMPLEMENTED)
1105 return 0; 1106 return 0;
1106 return (int) rv.status; 1107 return (int) rv.status;
diff --git a/include/asm-ia64/sn/xp.h b/include/asm-ia64/sn/xp.h
index 49faf8f26430..203945ae034e 100644
--- a/include/asm-ia64/sn/xp.h
+++ b/include/asm-ia64/sn/xp.h
@@ -227,7 +227,9 @@ enum xpc_retval {
227 227
228 xpcOpenCloseError, /* 50: channel open/close protocol error */ 228 xpcOpenCloseError, /* 50: channel open/close protocol error */
229 229
230 xpcUnknownReason /* 51: unknown reason -- must be last in list */ 230 xpcDisconnected, /* 51: channel disconnected (closed) */
231
232 xpcUnknownReason /* 52: unknown reason -- must be last in list */
231}; 233};
232 234
233 235
diff --git a/arch/ia64/sn/kernel/xpc.h b/include/asm-ia64/sn/xpc.h
index 5483a9f227d4..87e9cd588510 100644
--- a/arch/ia64/sn/kernel/xpc.h
+++ b/include/asm-ia64/sn/xpc.h
@@ -3,7 +3,7 @@
3 * License. See the file "COPYING" in the main directory of this archive 3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details. 4 * for more details.
5 * 5 *
6 * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved. 6 * Copyright (c) 2004-2006 Silicon Graphics, Inc. All Rights Reserved.
7 */ 7 */
8 8
9 9
@@ -11,8 +11,8 @@
11 * Cross Partition Communication (XPC) structures and macros. 11 * Cross Partition Communication (XPC) structures and macros.
12 */ 12 */
13 13
14#ifndef _IA64_SN_KERNEL_XPC_H 14#ifndef _ASM_IA64_SN_XPC_H
15#define _IA64_SN_KERNEL_XPC_H 15#define _ASM_IA64_SN_XPC_H
16 16
17 17
18#include <linux/config.h> 18#include <linux/config.h>
@@ -663,6 +663,7 @@ extern struct xpc_registration xpc_registrations[];
663extern struct device *xpc_part; 663extern struct device *xpc_part;
664extern struct device *xpc_chan; 664extern struct device *xpc_chan;
665extern int xpc_disengage_request_timelimit; 665extern int xpc_disengage_request_timelimit;
666extern int xpc_disengage_request_timedout;
666extern irqreturn_t xpc_notify_IRQ_handler(int, void *, struct pt_regs *); 667extern irqreturn_t xpc_notify_IRQ_handler(int, void *, struct pt_regs *);
667extern void xpc_dropped_IPI_check(struct xpc_partition *); 668extern void xpc_dropped_IPI_check(struct xpc_partition *);
668extern void xpc_activate_partition(struct xpc_partition *); 669extern void xpc_activate_partition(struct xpc_partition *);
@@ -707,7 +708,7 @@ extern void xpc_connected_callout(struct xpc_channel *);
707extern void xpc_deliver_msg(struct xpc_channel *); 708extern void xpc_deliver_msg(struct xpc_channel *);
708extern void xpc_disconnect_channel(const int, struct xpc_channel *, 709extern void xpc_disconnect_channel(const int, struct xpc_channel *,
709 enum xpc_retval, unsigned long *); 710 enum xpc_retval, unsigned long *);
710extern void xpc_disconnecting_callout(struct xpc_channel *); 711extern void xpc_disconnect_callout(struct xpc_channel *, enum xpc_retval);
711extern void xpc_partition_going_down(struct xpc_partition *, enum xpc_retval); 712extern void xpc_partition_going_down(struct xpc_partition *, enum xpc_retval);
712extern void xpc_teardown_infrastructure(struct xpc_partition *); 713extern void xpc_teardown_infrastructure(struct xpc_partition *);
713 714
@@ -1269,5 +1270,5 @@ xpc_check_for_channel_activity(struct xpc_partition *part)
1269} 1270}
1270 1271
1271 1272
1272#endif /* _IA64_SN_KERNEL_XPC_H */ 1273#endif /* _ASM_IA64_SN_XPC_H */
1273 1274
diff --git a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h
index 653bb7f9a753..1d6518fe1f02 100644
--- a/include/asm-ia64/thread_info.h
+++ b/include/asm-ia64/thread_info.h
@@ -93,6 +93,7 @@ struct thread_info {
93#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */ 93#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */
94#define TIF_MEMDIE 17 94#define TIF_MEMDIE 17
95#define TIF_MCA_INIT 18 /* this task is processing MCA or INIT */ 95#define TIF_MCA_INIT 18 /* this task is processing MCA or INIT */
96#define TIF_DB_DISABLED 19 /* debug trap disabled for fsyscall */
96 97
97#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) 98#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
98#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) 99#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
@@ -100,9 +101,10 @@ struct thread_info {
100#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) 101#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
101#define _TIF_SIGPENDING (1 << TIF_SIGPENDING) 102#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
102#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) 103#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
103#define _TIF_SIGDELAYED (1 << TIF_SIGDELAYED) 104#define _TIF_SIGDELAYED (1 << TIF_SIGDELAYED)
104#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) 105#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
105#define _TIF_MCA_INIT (1 << TIF_MCA_INIT) 106#define _TIF_MCA_INIT (1 << TIF_MCA_INIT)
107#define _TIF_DB_DISABLED (1 << TIF_DB_DISABLED)
106 108
107/* "work to do on user-return" bits */ 109/* "work to do on user-return" bits */
108#define TIF_ALLWORK_MASK (_TIF_NOTIFY_RESUME|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SIGDELAYED) 110#define TIF_ALLWORK_MASK (_TIF_NOTIFY_RESUME|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SIGDELAYED)
diff --git a/include/asm-powerpc/atomic.h b/include/asm-powerpc/atomic.h
index 248f9aec959c..147a38dcc766 100644
--- a/include/asm-powerpc/atomic.h
+++ b/include/asm-powerpc/atomic.h
@@ -36,7 +36,7 @@ static __inline__ int atomic_add_return(int a, atomic_t *v)
36 int t; 36 int t;
37 37
38 __asm__ __volatile__( 38 __asm__ __volatile__(
39 EIEIO_ON_SMP 39 LWSYNC_ON_SMP
40"1: lwarx %0,0,%2 # atomic_add_return\n\ 40"1: lwarx %0,0,%2 # atomic_add_return\n\
41 add %0,%1,%0\n" 41 add %0,%1,%0\n"
42 PPC405_ERR77(0,%2) 42 PPC405_ERR77(0,%2)
@@ -72,7 +72,7 @@ static __inline__ int atomic_sub_return(int a, atomic_t *v)
72 int t; 72 int t;
73 73
74 __asm__ __volatile__( 74 __asm__ __volatile__(
75 EIEIO_ON_SMP 75 LWSYNC_ON_SMP
76"1: lwarx %0,0,%2 # atomic_sub_return\n\ 76"1: lwarx %0,0,%2 # atomic_sub_return\n\
77 subf %0,%1,%0\n" 77 subf %0,%1,%0\n"
78 PPC405_ERR77(0,%2) 78 PPC405_ERR77(0,%2)
@@ -106,7 +106,7 @@ static __inline__ int atomic_inc_return(atomic_t *v)
106 int t; 106 int t;
107 107
108 __asm__ __volatile__( 108 __asm__ __volatile__(
109 EIEIO_ON_SMP 109 LWSYNC_ON_SMP
110"1: lwarx %0,0,%1 # atomic_inc_return\n\ 110"1: lwarx %0,0,%1 # atomic_inc_return\n\
111 addic %0,%0,1\n" 111 addic %0,%0,1\n"
112 PPC405_ERR77(0,%1) 112 PPC405_ERR77(0,%1)
@@ -150,7 +150,7 @@ static __inline__ int atomic_dec_return(atomic_t *v)
150 int t; 150 int t;
151 151
152 __asm__ __volatile__( 152 __asm__ __volatile__(
153 EIEIO_ON_SMP 153 LWSYNC_ON_SMP
154"1: lwarx %0,0,%1 # atomic_dec_return\n\ 154"1: lwarx %0,0,%1 # atomic_dec_return\n\
155 addic %0,%0,-1\n" 155 addic %0,%0,-1\n"
156 PPC405_ERR77(0,%1) 156 PPC405_ERR77(0,%1)
@@ -176,19 +176,19 @@ static __inline__ int atomic_dec_return(atomic_t *v)
176 * Atomically adds @a to @v, so long as it was not @u. 176 * Atomically adds @a to @v, so long as it was not @u.
177 * Returns non-zero if @v was not @u, and zero otherwise. 177 * Returns non-zero if @v was not @u, and zero otherwise.
178 */ 178 */
179#define atomic_add_unless(v, a, u) \ 179#define atomic_add_unless(v, a, u) \
180({ \ 180({ \
181 int c, old; \ 181 int c, old; \
182 c = atomic_read(v); \ 182 c = atomic_read(v); \
183 for (;;) { \ 183 for (;;) { \
184 if (unlikely(c == (u))) \ 184 if (unlikely(c == (u))) \
185 break; \ 185 break; \
186 old = atomic_cmpxchg((v), c, c + (a)); \ 186 old = atomic_cmpxchg((v), c, c + (a)); \
187 if (likely(old == c)) \ 187 if (likely(old == c)) \
188 break; \ 188 break; \
189 c = old; \ 189 c = old; \
190 } \ 190 } \
191 c != (u); \ 191 c != (u); \
192}) 192})
193#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) 193#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
194 194
@@ -204,7 +204,7 @@ static __inline__ int atomic_dec_if_positive(atomic_t *v)
204 int t; 204 int t;
205 205
206 __asm__ __volatile__( 206 __asm__ __volatile__(
207 EIEIO_ON_SMP 207 LWSYNC_ON_SMP
208"1: lwarx %0,0,%1 # atomic_dec_if_positive\n\ 208"1: lwarx %0,0,%1 # atomic_dec_if_positive\n\
209 addic. %0,%0,-1\n\ 209 addic. %0,%0,-1\n\
210 blt- 2f\n" 210 blt- 2f\n"
@@ -253,7 +253,7 @@ static __inline__ long atomic64_add_return(long a, atomic64_t *v)
253 long t; 253 long t;
254 254
255 __asm__ __volatile__( 255 __asm__ __volatile__(
256 EIEIO_ON_SMP 256 LWSYNC_ON_SMP
257"1: ldarx %0,0,%2 # atomic64_add_return\n\ 257"1: ldarx %0,0,%2 # atomic64_add_return\n\
258 add %0,%1,%0\n\ 258 add %0,%1,%0\n\
259 stdcx. %0,0,%2 \n\ 259 stdcx. %0,0,%2 \n\
@@ -287,7 +287,7 @@ static __inline__ long atomic64_sub_return(long a, atomic64_t *v)
287 long t; 287 long t;
288 288
289 __asm__ __volatile__( 289 __asm__ __volatile__(
290 EIEIO_ON_SMP 290 LWSYNC_ON_SMP
291"1: ldarx %0,0,%2 # atomic64_sub_return\n\ 291"1: ldarx %0,0,%2 # atomic64_sub_return\n\
292 subf %0,%1,%0\n\ 292 subf %0,%1,%0\n\
293 stdcx. %0,0,%2 \n\ 293 stdcx. %0,0,%2 \n\
@@ -319,7 +319,7 @@ static __inline__ long atomic64_inc_return(atomic64_t *v)
319 long t; 319 long t;
320 320
321 __asm__ __volatile__( 321 __asm__ __volatile__(
322 EIEIO_ON_SMP 322 LWSYNC_ON_SMP
323"1: ldarx %0,0,%1 # atomic64_inc_return\n\ 323"1: ldarx %0,0,%1 # atomic64_inc_return\n\
324 addic %0,%0,1\n\ 324 addic %0,%0,1\n\
325 stdcx. %0,0,%1 \n\ 325 stdcx. %0,0,%1 \n\
@@ -361,7 +361,7 @@ static __inline__ long atomic64_dec_return(atomic64_t *v)
361 long t; 361 long t;
362 362
363 __asm__ __volatile__( 363 __asm__ __volatile__(
364 EIEIO_ON_SMP 364 LWSYNC_ON_SMP
365"1: ldarx %0,0,%1 # atomic64_dec_return\n\ 365"1: ldarx %0,0,%1 # atomic64_dec_return\n\
366 addic %0,%0,-1\n\ 366 addic %0,%0,-1\n\
367 stdcx. %0,0,%1\n\ 367 stdcx. %0,0,%1\n\
@@ -386,7 +386,7 @@ static __inline__ long atomic64_dec_if_positive(atomic64_t *v)
386 long t; 386 long t;
387 387
388 __asm__ __volatile__( 388 __asm__ __volatile__(
389 EIEIO_ON_SMP 389 LWSYNC_ON_SMP
390"1: ldarx %0,0,%1 # atomic64_dec_if_positive\n\ 390"1: ldarx %0,0,%1 # atomic64_dec_if_positive\n\
391 addic. %0,%0,-1\n\ 391 addic. %0,%0,-1\n\
392 blt- 2f\n\ 392 blt- 2f\n\
diff --git a/include/asm-powerpc/bitops.h b/include/asm-powerpc/bitops.h
index 1996eaa8aeae..bf6941a810b8 100644
--- a/include/asm-powerpc/bitops.h
+++ b/include/asm-powerpc/bitops.h
@@ -112,7 +112,7 @@ static __inline__ int test_and_set_bit(unsigned long nr,
112 unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); 112 unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
113 113
114 __asm__ __volatile__( 114 __asm__ __volatile__(
115 EIEIO_ON_SMP 115 LWSYNC_ON_SMP
116"1:" PPC_LLARX "%0,0,%3 # test_and_set_bit\n" 116"1:" PPC_LLARX "%0,0,%3 # test_and_set_bit\n"
117 "or %1,%0,%2 \n" 117 "or %1,%0,%2 \n"
118 PPC405_ERR77(0,%3) 118 PPC405_ERR77(0,%3)
@@ -134,7 +134,7 @@ static __inline__ int test_and_clear_bit(unsigned long nr,
134 unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); 134 unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
135 135
136 __asm__ __volatile__( 136 __asm__ __volatile__(
137 EIEIO_ON_SMP 137 LWSYNC_ON_SMP
138"1:" PPC_LLARX "%0,0,%3 # test_and_clear_bit\n" 138"1:" PPC_LLARX "%0,0,%3 # test_and_clear_bit\n"
139 "andc %1,%0,%2 \n" 139 "andc %1,%0,%2 \n"
140 PPC405_ERR77(0,%3) 140 PPC405_ERR77(0,%3)
@@ -156,7 +156,7 @@ static __inline__ int test_and_change_bit(unsigned long nr,
156 unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); 156 unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
157 157
158 __asm__ __volatile__( 158 __asm__ __volatile__(
159 EIEIO_ON_SMP 159 LWSYNC_ON_SMP
160"1:" PPC_LLARX "%0,0,%3 # test_and_change_bit\n" 160"1:" PPC_LLARX "%0,0,%3 # test_and_change_bit\n"
161 "xor %1,%0,%2 \n" 161 "xor %1,%0,%2 \n"
162 PPC405_ERR77(0,%3) 162 PPC405_ERR77(0,%3)
diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h
index ef6ead34a773..64210549f56b 100644
--- a/include/asm-powerpc/cputable.h
+++ b/include/asm-powerpc/cputable.h
@@ -19,6 +19,7 @@
19#define PPC_FEATURE_POWER5 0x00040000 19#define PPC_FEATURE_POWER5 0x00040000
20#define PPC_FEATURE_POWER5_PLUS 0x00020000 20#define PPC_FEATURE_POWER5_PLUS 0x00020000
21#define PPC_FEATURE_CELL 0x00010000 21#define PPC_FEATURE_CELL 0x00010000
22#define PPC_FEATURE_BOOKE 0x00008000
22 23
23#ifdef __KERNEL__ 24#ifdef __KERNEL__
24#ifndef __ASSEMBLY__ 25#ifndef __ASSEMBLY__
@@ -31,11 +32,11 @@ struct cpu_spec;
31typedef void (*cpu_setup_t)(unsigned long offset, struct cpu_spec* spec); 32typedef void (*cpu_setup_t)(unsigned long offset, struct cpu_spec* spec);
32 33
33enum powerpc_oprofile_type { 34enum powerpc_oprofile_type {
34 INVALID = 0, 35 PPC_OPROFILE_INVALID = 0,
35 RS64 = 1, 36 PPC_OPROFILE_RS64 = 1,
36 POWER4 = 2, 37 PPC_OPROFILE_POWER4 = 2,
37 G4 = 3, 38 PPC_OPROFILE_G4 = 3,
38 BOOKE = 4, 39 PPC_OPROFILE_BOOKE = 4,
39}; 40};
40 41
41struct cpu_spec { 42struct cpu_spec {
@@ -64,6 +65,9 @@ struct cpu_spec {
64 65
65 /* Processor specific oprofile operations */ 66 /* Processor specific oprofile operations */
66 enum powerpc_oprofile_type oprofile_type; 67 enum powerpc_oprofile_type oprofile_type;
68
69 /* Name of processor class, for the ELF AT_PLATFORM entry */
70 char *platform;
67}; 71};
68 72
69extern struct cpu_spec *cur_cpu_spec; 73extern struct cpu_spec *cur_cpu_spec;
diff --git a/include/asm-powerpc/elf.h b/include/asm-powerpc/elf.h
index 45f2af6f89c4..94d228f9c6ac 100644
--- a/include/asm-powerpc/elf.h
+++ b/include/asm-powerpc/elf.h
@@ -221,20 +221,18 @@ extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *);
221 instruction set this cpu supports. This could be done in userspace, 221 instruction set this cpu supports. This could be done in userspace,
222 but it's not easy, and we've already done it here. */ 222 but it's not easy, and we've already done it here. */
223# define ELF_HWCAP (cur_cpu_spec->cpu_user_features) 223# define ELF_HWCAP (cur_cpu_spec->cpu_user_features)
224#ifdef __powerpc64__
225# define ELF_PLAT_INIT(_r, load_addr) do { \
226 _r->gpr[2] = load_addr; \
227} while (0)
228#endif /* __powerpc64__ */
229 224
230/* This yields a string that ld.so will use to load implementation 225/* This yields a string that ld.so will use to load implementation
231 specific libraries for optimization. This is more specific in 226 specific libraries for optimization. This is more specific in
232 intent than poking at uname or /proc/cpuinfo. 227 intent than poking at uname or /proc/cpuinfo. */
233 228
234 For the moment, we have only optimizations for the Intel generations, 229#define ELF_PLATFORM (cur_cpu_spec->platform)
235 but that could change... */
236 230
237#define ELF_PLATFORM (NULL) 231#ifdef __powerpc64__
232# define ELF_PLAT_INIT(_r, load_addr) do { \
233 _r->gpr[2] = load_addr; \
234} while (0)
235#endif /* __powerpc64__ */
238 236
239#ifdef __KERNEL__ 237#ifdef __KERNEL__
240 238
diff --git a/include/asm-powerpc/futex.h b/include/asm-powerpc/futex.h
index f0319d50b129..39e85f320a76 100644
--- a/include/asm-powerpc/futex.h
+++ b/include/asm-powerpc/futex.h
@@ -11,7 +11,7 @@
11 11
12#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ 12#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
13 __asm__ __volatile ( \ 13 __asm__ __volatile ( \
14 SYNC_ON_SMP \ 14 LWSYNC_ON_SMP \
15"1: lwarx %0,0,%2\n" \ 15"1: lwarx %0,0,%2\n" \
16 insn \ 16 insn \
17 PPC405_ERR77(0, %2) \ 17 PPC405_ERR77(0, %2) \
diff --git a/include/asm-powerpc/hvcall.h b/include/asm-powerpc/hvcall.h
index da7af5a720e0..38ca9ad6110d 100644
--- a/include/asm-powerpc/hvcall.h
+++ b/include/asm-powerpc/hvcall.h
@@ -6,7 +6,10 @@
6 6
7#define H_Success 0 7#define H_Success 0
8#define H_Busy 1 /* Hardware busy -- retry later */ 8#define H_Busy 1 /* Hardware busy -- retry later */
9#define H_Closed 2 /* Resource closed */
9#define H_Constrained 4 /* Resource request constrained to max allowed */ 10#define H_Constrained 4 /* Resource request constrained to max allowed */
11#define H_InProgress 14 /* Kind of like busy */
12#define H_Continue 18 /* Returned from H_Join on success */
10#define H_LongBusyStartRange 9900 /* Start of long busy range */ 13#define H_LongBusyStartRange 9900 /* Start of long busy range */
11#define H_LongBusyOrder1msec 9900 /* Long busy, hint that 1msec is a good time to retry */ 14#define H_LongBusyOrder1msec 9900 /* Long busy, hint that 1msec is a good time to retry */
12#define H_LongBusyOrder10msec 9901 /* Long busy, hint that 10msec is a good time to retry */ 15#define H_LongBusyOrder10msec 9901 /* Long busy, hint that 10msec is a good time to retry */
@@ -114,6 +117,8 @@
114#define H_REGISTER_VTERM 0x154 117#define H_REGISTER_VTERM 0x154
115#define H_FREE_VTERM 0x158 118#define H_FREE_VTERM 0x158
116#define H_POLL_PENDING 0x1D8 119#define H_POLL_PENDING 0x1D8
120#define H_JOIN 0x298
121#define H_ENABLE_CRQ 0x2B0
117 122
118#ifndef __ASSEMBLY__ 123#ifndef __ASSEMBLY__
119 124
diff --git a/include/asm-powerpc/lppaca.h b/include/asm-powerpc/lppaca.h
index ff82ea7c4829..cd9f11f1ef14 100644
--- a/include/asm-powerpc/lppaca.h
+++ b/include/asm-powerpc/lppaca.h
@@ -29,7 +29,9 @@
29//---------------------------------------------------------------------------- 29//----------------------------------------------------------------------------
30#include <asm/types.h> 30#include <asm/types.h>
31 31
32struct lppaca { 32/* The Hypervisor barfs if the lppaca crosses a page boundary. A 1k
33 * alignment is sufficient to prevent this */
34struct __attribute__((__aligned__(0x400))) lppaca {
33//============================================================================= 35//=============================================================================
34// CACHE_LINE_1 0x0000 - 0x007F Contains read-only data 36// CACHE_LINE_1 0x0000 - 0x007F Contains read-only data
35// NOTE: The xDynXyz fields are fields that will be dynamically changed by 37// NOTE: The xDynXyz fields are fields that will be dynamically changed by
@@ -129,5 +131,7 @@ struct lppaca {
129 u8 pmc_save_area[256]; // PMC interrupt Area x00-xFF 131 u8 pmc_save_area[256]; // PMC interrupt Area x00-xFF
130}; 132};
131 133
134extern struct lppaca lppaca[];
135
132#endif /* __KERNEL__ */ 136#endif /* __KERNEL__ */
133#endif /* _ASM_POWERPC_LPPACA_H */ 137#endif /* _ASM_POWERPC_LPPACA_H */
diff --git a/include/asm-powerpc/paca.h b/include/asm-powerpc/paca.h
index a64b4d425dab..c9add8f1ad94 100644
--- a/include/asm-powerpc/paca.h
+++ b/include/asm-powerpc/paca.h
@@ -23,6 +23,7 @@
23 23
24register struct paca_struct *local_paca asm("r13"); 24register struct paca_struct *local_paca asm("r13");
25#define get_paca() local_paca 25#define get_paca() local_paca
26#define get_lppaca() (get_paca()->lppaca_ptr)
26 27
27struct task_struct; 28struct task_struct;
28 29
@@ -95,19 +96,6 @@ struct paca_struct {
95 u64 saved_r1; /* r1 save for RTAS calls */ 96 u64 saved_r1; /* r1 save for RTAS calls */
96 u64 saved_msr; /* MSR saved here by enter_rtas */ 97 u64 saved_msr; /* MSR saved here by enter_rtas */
97 u8 proc_enabled; /* irq soft-enable flag */ 98 u8 proc_enabled; /* irq soft-enable flag */
98
99 /*
100 * iSeries structure which the hypervisor knows about -
101 * this structure should not cross a page boundary.
102 * The vpa_init/register_vpa call is now known to fail if the
103 * lppaca structure crosses a page boundary.
104 * The lppaca is also used on POWER5 pSeries boxes.
105 * The lppaca is 640 bytes long, and cannot readily change
106 * since the hypervisor knows its layout, so a 1kB
107 * alignment will suffice to ensure that it doesn't
108 * cross a page boundary.
109 */
110 struct lppaca lppaca __attribute__((__aligned__(0x400)));
111}; 99};
112 100
113extern struct paca_struct paca[]; 101extern struct paca_struct paca[];
diff --git a/include/asm-powerpc/ppc_asm.h b/include/asm-powerpc/ppc_asm.h
index 0dc798d46ea4..ab8688d39024 100644
--- a/include/asm-powerpc/ppc_asm.h
+++ b/include/asm-powerpc/ppc_asm.h
@@ -156,52 +156,56 @@ n:
156#endif 156#endif
157 157
158/* 158/*
159 * LOADADDR( rn, name ) 159 * LOAD_REG_IMMEDIATE(rn, expr)
160 * loads the address of 'name' into 'rn' 160 * Loads the value of the constant expression 'expr' into register 'rn'
161 * using immediate instructions only. Use this when it's important not
162 * to reference other data (i.e. on ppc64 when the TOC pointer is not
163 * valid).
161 * 164 *
162 * LOADBASE( rn, name ) 165 * LOAD_REG_ADDR(rn, name)
163 * loads the address (possibly without the low 16 bits) of 'name' into 'rn' 166 * Loads the address of label 'name' into register 'rn'. Use this when
164 * suitable for base+disp addressing 167 * you don't particularly need immediate instructions only, but you need
168 * the whole address in one register (e.g. it's a structure address and
169 * you want to access various offsets within it). On ppc32 this is
170 * identical to LOAD_REG_IMMEDIATE.
171 *
172 * LOAD_REG_ADDRBASE(rn, name)
173 * ADDROFF(name)
174 * LOAD_REG_ADDRBASE loads part of the address of label 'name' into
175 * register 'rn'. ADDROFF(name) returns the remainder of the address as
176 * a constant expression. ADDROFF(name) is a signed expression < 16 bits
177 * in size, so is suitable for use directly as an offset in load and store
178 * instructions. Use this when loading/storing a single word or less as:
179 * LOAD_REG_ADDRBASE(rX, name)
180 * ld rY,ADDROFF(name)(rX)
165 */ 181 */
166#ifdef __powerpc64__ 182#ifdef __powerpc64__
167#define LOADADDR(rn,name) \ 183#define LOAD_REG_IMMEDIATE(reg,expr) \
168 lis rn,name##@highest; \ 184 lis (reg),(expr)@highest; \
169 ori rn,rn,name##@higher; \ 185 ori (reg),(reg),(expr)@higher; \
170 rldicr rn,rn,32,31; \ 186 rldicr (reg),(reg),32,31; \
171 oris rn,rn,name##@h; \ 187 oris (reg),(reg),(expr)@h; \
172 ori rn,rn,name##@l 188 ori (reg),(reg),(expr)@l;
173 189
174#define LOADBASE(rn,name) \ 190#define LOAD_REG_ADDR(reg,name) \
175 ld rn,name@got(r2) 191 ld (reg),name@got(r2)
176 192
177#define OFF(name) 0 193#define LOAD_REG_ADDRBASE(reg,name) LOAD_REG_ADDR(reg,name)
178 194#define ADDROFF(name) 0
179#define SET_REG_TO_CONST(reg, value) \
180 lis reg,(((value)>>48)&0xFFFF); \
181 ori reg,reg,(((value)>>32)&0xFFFF); \
182 rldicr reg,reg,32,31; \
183 oris reg,reg,(((value)>>16)&0xFFFF); \
184 ori reg,reg,((value)&0xFFFF);
185
186#define SET_REG_TO_LABEL(reg, label) \
187 lis reg,(label)@highest; \
188 ori reg,reg,(label)@higher; \
189 rldicr reg,reg,32,31; \
190 oris reg,reg,(label)@h; \
191 ori reg,reg,(label)@l;
192 195
193/* offsets for stack frame layout */ 196/* offsets for stack frame layout */
194#define LRSAVE 16 197#define LRSAVE 16
195 198
196#else /* 32-bit */ 199#else /* 32-bit */
197#define LOADADDR(rn,name) \
198 lis rn,name@ha; \
199 addi rn,rn,name@l
200 200
201#define LOADBASE(rn,name) \ 201#define LOAD_REG_IMMEDIATE(reg,expr) \
202 lis rn,name@ha 202 lis (reg),(expr)@ha; \
203 addi (reg),(reg),(expr)@l;
204
205#define LOAD_REG_ADDR(reg,name) LOAD_REG_IMMEDIATE(reg, name)
203 206
204#define OFF(name) name@l 207#define LOAD_REG_ADDRBASE(reg, name) lis (reg),name@ha
208#define ADDROFF(name) name@l
205 209
206/* offsets for stack frame layout */ 210/* offsets for stack frame layout */
207#define LRSAVE 4 211#define LRSAVE 4
diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h
index 329e9bf62260..5b2bd4eefb01 100644
--- a/include/asm-powerpc/prom.h
+++ b/include/asm-powerpc/prom.h
@@ -87,6 +87,7 @@ struct device_node {
87 char *full_name; 87 char *full_name;
88 88
89 struct property *properties; 89 struct property *properties;
90 struct property *deadprops; /* removed properties */
90 struct device_node *parent; 91 struct device_node *parent;
91 struct device_node *child; 92 struct device_node *child;
92 struct device_node *sibling; 93 struct device_node *sibling;
@@ -135,6 +136,9 @@ extern struct device_node *of_find_all_nodes(struct device_node *prev);
135extern struct device_node *of_get_parent(const struct device_node *node); 136extern struct device_node *of_get_parent(const struct device_node *node);
136extern struct device_node *of_get_next_child(const struct device_node *node, 137extern struct device_node *of_get_next_child(const struct device_node *node,
137 struct device_node *prev); 138 struct device_node *prev);
139extern struct property *of_find_property(struct device_node *np,
140 const char *name,
141 int *lenp);
138extern struct device_node *of_node_get(struct device_node *node); 142extern struct device_node *of_node_get(struct device_node *node);
139extern void of_node_put(struct device_node *node); 143extern void of_node_put(struct device_node *node);
140 144
@@ -164,6 +168,10 @@ extern int prom_n_size_cells(struct device_node* np);
164extern int prom_n_intr_cells(struct device_node* np); 168extern int prom_n_intr_cells(struct device_node* np);
165extern void prom_get_irq_senses(unsigned char *senses, int off, int max); 169extern void prom_get_irq_senses(unsigned char *senses, int off, int max);
166extern int prom_add_property(struct device_node* np, struct property* prop); 170extern int prom_add_property(struct device_node* np, struct property* prop);
171extern int prom_remove_property(struct device_node *np, struct property *prop);
172extern int prom_update_property(struct device_node *np,
173 struct property *newprop,
174 struct property *oldprop);
167 175
168#ifdef CONFIG_PPC32 176#ifdef CONFIG_PPC32
169/* 177/*
diff --git a/include/asm-powerpc/spinlock.h b/include/asm-powerpc/spinlock.h
index 754900901cd8..895cb6d3a42a 100644
--- a/include/asm-powerpc/spinlock.h
+++ b/include/asm-powerpc/spinlock.h
@@ -46,7 +46,7 @@ static __inline__ unsigned long __spin_trylock(raw_spinlock_t *lock)
46 46
47 token = LOCK_TOKEN; 47 token = LOCK_TOKEN;
48 __asm__ __volatile__( 48 __asm__ __volatile__(
49"1: lwarx %0,0,%2 # __spin_trylock\n\ 49"1: lwarx %0,0,%2\n\
50 cmpwi 0,%0,0\n\ 50 cmpwi 0,%0,0\n\
51 bne- 2f\n\ 51 bne- 2f\n\
52 stwcx. %1,0,%2\n\ 52 stwcx. %1,0,%2\n\
@@ -80,7 +80,7 @@ static int __inline__ __raw_spin_trylock(raw_spinlock_t *lock)
80 80
81#if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES) 81#if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES)
82/* We only yield to the hypervisor if we are in shared processor mode */ 82/* We only yield to the hypervisor if we are in shared processor mode */
83#define SHARED_PROCESSOR (get_paca()->lppaca.shared_proc) 83#define SHARED_PROCESSOR (get_lppaca()->shared_proc)
84extern void __spin_yield(raw_spinlock_t *lock); 84extern void __spin_yield(raw_spinlock_t *lock);
85extern void __rw_yield(raw_rwlock_t *lock); 85extern void __rw_yield(raw_rwlock_t *lock);
86#else /* SPLPAR || ISERIES */ 86#else /* SPLPAR || ISERIES */
@@ -124,8 +124,8 @@ static void __inline__ __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long
124 124
125static __inline__ void __raw_spin_unlock(raw_spinlock_t *lock) 125static __inline__ void __raw_spin_unlock(raw_spinlock_t *lock)
126{ 126{
127 __asm__ __volatile__(SYNC_ON_SMP" # __raw_spin_unlock" 127 __asm__ __volatile__("# __raw_spin_unlock\n\t"
128 : : :"memory"); 128 LWSYNC_ON_SMP: : :"memory");
129 lock->slock = 0; 129 lock->slock = 0;
130} 130}
131 131
@@ -167,7 +167,7 @@ static long __inline__ __read_trylock(raw_rwlock_t *rw)
167 long tmp; 167 long tmp;
168 168
169 __asm__ __volatile__( 169 __asm__ __volatile__(
170"1: lwarx %0,0,%1 # read_trylock\n" 170"1: lwarx %0,0,%1\n"
171 __DO_SIGN_EXTEND 171 __DO_SIGN_EXTEND
172" addic. %0,%0,1\n\ 172" addic. %0,%0,1\n\
173 ble- 2f\n" 173 ble- 2f\n"
@@ -192,7 +192,7 @@ static __inline__ long __write_trylock(raw_rwlock_t *rw)
192 192
193 token = WRLOCK_TOKEN; 193 token = WRLOCK_TOKEN;
194 __asm__ __volatile__( 194 __asm__ __volatile__(
195"1: lwarx %0,0,%2 # write_trylock\n\ 195"1: lwarx %0,0,%2\n\
196 cmpwi 0,%0,0\n\ 196 cmpwi 0,%0,0\n\
197 bne- 2f\n" 197 bne- 2f\n"
198 PPC405_ERR77(0,%1) 198 PPC405_ERR77(0,%1)
@@ -249,8 +249,9 @@ static void __inline__ __raw_read_unlock(raw_rwlock_t *rw)
249 long tmp; 249 long tmp;
250 250
251 __asm__ __volatile__( 251 __asm__ __volatile__(
252 "eieio # read_unlock\n\ 252 "# read_unlock\n\t"
2531: lwarx %0,0,%1\n\ 253 LWSYNC_ON_SMP
254"1: lwarx %0,0,%1\n\
254 addic %0,%0,-1\n" 255 addic %0,%0,-1\n"
255 PPC405_ERR77(0,%1) 256 PPC405_ERR77(0,%1)
256" stwcx. %0,0,%1\n\ 257" stwcx. %0,0,%1\n\
@@ -262,8 +263,8 @@ static void __inline__ __raw_read_unlock(raw_rwlock_t *rw)
262 263
263static __inline__ void __raw_write_unlock(raw_rwlock_t *rw) 264static __inline__ void __raw_write_unlock(raw_rwlock_t *rw)
264{ 265{
265 __asm__ __volatile__(SYNC_ON_SMP" # write_unlock" 266 __asm__ __volatile__("# write_unlock\n\t"
266 : : :"memory"); 267 LWSYNC_ON_SMP: : :"memory");
267 rw->lock = 0; 268 rw->lock = 0;
268} 269}
269 270
diff --git a/include/asm-powerpc/synch.h b/include/asm-powerpc/synch.h
index 794870ab8fd3..c90d9d9aae72 100644
--- a/include/asm-powerpc/synch.h
+++ b/include/asm-powerpc/synch.h
@@ -2,6 +2,8 @@
2#define _ASM_POWERPC_SYNCH_H 2#define _ASM_POWERPC_SYNCH_H
3#ifdef __KERNEL__ 3#ifdef __KERNEL__
4 4
5#include <linux/stringify.h>
6
5#ifdef __powerpc64__ 7#ifdef __powerpc64__
6#define __SUBARCH_HAS_LWSYNC 8#define __SUBARCH_HAS_LWSYNC
7#endif 9#endif
@@ -12,20 +14,12 @@
12# define LWSYNC sync 14# define LWSYNC sync
13#endif 15#endif
14 16
15
16/*
17 * Arguably the bitops and *xchg operations don't imply any memory barrier
18 * or SMP ordering, but in fact a lot of drivers expect them to imply
19 * both, since they do on x86 cpus.
20 */
21#ifdef CONFIG_SMP 17#ifdef CONFIG_SMP
22#define EIEIO_ON_SMP "eieio\n"
23#define ISYNC_ON_SMP "\n\tisync" 18#define ISYNC_ON_SMP "\n\tisync"
24#define SYNC_ON_SMP __stringify(LWSYNC) "\n" 19#define LWSYNC_ON_SMP __stringify(LWSYNC) "\n"
25#else 20#else
26#define EIEIO_ON_SMP
27#define ISYNC_ON_SMP 21#define ISYNC_ON_SMP
28#define SYNC_ON_SMP 22#define LWSYNC_ON_SMP
29#endif 23#endif
30 24
31static inline void eieio(void) 25static inline void eieio(void)
@@ -38,14 +32,5 @@ static inline void isync(void)
38 __asm__ __volatile__ ("isync" : : : "memory"); 32 __asm__ __volatile__ ("isync" : : : "memory");
39} 33}
40 34
41#ifdef CONFIG_SMP
42#define eieio_on_smp() eieio()
43#define isync_on_smp() isync()
44#else
45#define eieio_on_smp() __asm__ __volatile__("": : :"memory")
46#define isync_on_smp() __asm__ __volatile__("": : :"memory")
47#endif
48
49#endif /* __KERNEL__ */ 35#endif /* __KERNEL__ */
50#endif /* _ASM_POWERPC_SYNCH_H */ 36#endif /* _ASM_POWERPC_SYNCH_H */
51
diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h
index 9b822afa7d0e..d9bf53653b10 100644
--- a/include/asm-powerpc/system.h
+++ b/include/asm-powerpc/system.h
@@ -212,7 +212,7 @@ __xchg_u32(volatile void *p, unsigned long val)
212 unsigned long prev; 212 unsigned long prev;
213 213
214 __asm__ __volatile__( 214 __asm__ __volatile__(
215 EIEIO_ON_SMP 215 LWSYNC_ON_SMP
216"1: lwarx %0,0,%2 \n" 216"1: lwarx %0,0,%2 \n"
217 PPC405_ERR77(0,%2) 217 PPC405_ERR77(0,%2)
218" stwcx. %3,0,%2 \n\ 218" stwcx. %3,0,%2 \n\
@@ -232,7 +232,7 @@ __xchg_u64(volatile void *p, unsigned long val)
232 unsigned long prev; 232 unsigned long prev;
233 233
234 __asm__ __volatile__( 234 __asm__ __volatile__(
235 EIEIO_ON_SMP 235 LWSYNC_ON_SMP
236"1: ldarx %0,0,%2 \n" 236"1: ldarx %0,0,%2 \n"
237 PPC405_ERR77(0,%2) 237 PPC405_ERR77(0,%2)
238" stdcx. %3,0,%2 \n\ 238" stdcx. %3,0,%2 \n\
@@ -287,7 +287,7 @@ __cmpxchg_u32(volatile unsigned int *p, unsigned long old, unsigned long new)
287 unsigned int prev; 287 unsigned int prev;
288 288
289 __asm__ __volatile__ ( 289 __asm__ __volatile__ (
290 EIEIO_ON_SMP 290 LWSYNC_ON_SMP
291"1: lwarx %0,0,%2 # __cmpxchg_u32\n\ 291"1: lwarx %0,0,%2 # __cmpxchg_u32\n\
292 cmpw 0,%0,%3\n\ 292 cmpw 0,%0,%3\n\
293 bne- 2f\n" 293 bne- 2f\n"
@@ -311,7 +311,7 @@ __cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new)
311 unsigned long prev; 311 unsigned long prev;
312 312
313 __asm__ __volatile__ ( 313 __asm__ __volatile__ (
314 EIEIO_ON_SMP 314 LWSYNC_ON_SMP
315"1: ldarx %0,0,%2 # __cmpxchg_u64\n\ 315"1: ldarx %0,0,%2 # __cmpxchg_u64\n\
316 cmpd 0,%0,%3\n\ 316 cmpd 0,%0,%3\n\
317 bne- 2f\n\ 317 bne- 2f\n\
diff --git a/include/asm-powerpc/time.h b/include/asm-powerpc/time.h
index d9b86a17271b..baddc9ab57ad 100644
--- a/include/asm-powerpc/time.h
+++ b/include/asm-powerpc/time.h
@@ -175,11 +175,10 @@ static inline void set_dec(int val)
175 set_dec_cpu6(val); 175 set_dec_cpu6(val);
176#else 176#else
177#ifdef CONFIG_PPC_ISERIES 177#ifdef CONFIG_PPC_ISERIES
178 struct paca_struct *lpaca = get_paca();
179 int cur_dec; 178 int cur_dec;
180 179
181 if (lpaca->lppaca.shared_proc) { 180 if (get_lppaca()->shared_proc) {
182 lpaca->lppaca.virtual_decr = val; 181 get_lppaca()->virtual_decr = val;
183 cur_dec = get_dec(); 182 cur_dec = get_dec();
184 if (cur_dec > val) 183 if (cur_dec > val)
185 HvCall_setVirtualDecr(); 184 HvCall_setVirtualDecr();
diff --git a/include/asm-s390/s390_rdev.h b/include/asm-s390/s390_rdev.h
index 3ad78f2b9c48..6fa20442a48c 100644
--- a/include/asm-s390/s390_rdev.h
+++ b/include/asm-s390/s390_rdev.h
@@ -2,7 +2,7 @@
2 * include/asm-s390/ccwdev.h 2 * include/asm-s390/ccwdev.h
3 * 3 *
4 * Copyright (C) 2002,2005 IBM Deutschland Entwicklung GmbH, IBM Corporation 4 * Copyright (C) 2002,2005 IBM Deutschland Entwicklung GmbH, IBM Corporation
5 * Author(s): Cornelia Huck <cohuck@de.ibm.com> 5 * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
6 * Carsten Otte <cotte@de.ibm.com> 6 * Carsten Otte <cotte@de.ibm.com>
7 * 7 *
8 * Interface for s390 root device 8 * Interface for s390 root device
diff --git a/include/asm-s390/sigcontext.h b/include/asm-s390/sigcontext.h
index 803545351dd8..aeb6e0b13329 100644
--- a/include/asm-s390/sigcontext.h
+++ b/include/asm-s390/sigcontext.h
@@ -8,6 +8,8 @@
8#ifndef _ASM_S390_SIGCONTEXT_H 8#ifndef _ASM_S390_SIGCONTEXT_H
9#define _ASM_S390_SIGCONTEXT_H 9#define _ASM_S390_SIGCONTEXT_H
10 10
11#include <linux/compiler.h>
12
11#define __NUM_GPRS 16 13#define __NUM_GPRS 16
12#define __NUM_FPRS 16 14#define __NUM_FPRS 16
13#define __NUM_ACRS 16 15#define __NUM_ACRS 16
diff --git a/include/asm-s390/system.h b/include/asm-s390/system.h
index c7c3a9ad593f..b2e65e8bf812 100644
--- a/include/asm-s390/system.h
+++ b/include/asm-s390/system.h
@@ -115,13 +115,14 @@ static inline void sched_cacheflush(void)
115} 115}
116 116
117#ifdef CONFIG_VIRT_CPU_ACCOUNTING 117#ifdef CONFIG_VIRT_CPU_ACCOUNTING
118extern void account_user_vtime(struct task_struct *); 118extern void account_vtime(struct task_struct *);
119extern void account_tick_vtime(struct task_struct *);
119extern void account_system_vtime(struct task_struct *); 120extern void account_system_vtime(struct task_struct *);
120#endif 121#endif
121 122
122#define finish_arch_switch(prev) do { \ 123#define finish_arch_switch(prev) do { \
123 set_fs(current->thread.mm_segment); \ 124 set_fs(current->thread.mm_segment); \
124 account_system_vtime(prev); \ 125 account_vtime(prev); \
125} while (0) 126} while (0)
126 127
127#define nop() __asm__ __volatile__ ("nop") 128#define nop() __asm__ __volatile__ ("nop")
diff --git a/include/asm-x86_64/fixmap.h b/include/asm-x86_64/fixmap.h
index a582cfcf2231..7b286bd21d1d 100644
--- a/include/asm-x86_64/fixmap.h
+++ b/include/asm-x86_64/fixmap.h
@@ -76,7 +76,7 @@ extern void __this_fixmap_does_not_exist(void);
76 * directly without translation, we catch the bug with a NULL-deference 76 * directly without translation, we catch the bug with a NULL-deference
77 * kernel oops. Illegal ranges of incoming indices are caught too. 77 * kernel oops. Illegal ranges of incoming indices are caught too.
78 */ 78 */
79static inline unsigned long fix_to_virt(const unsigned int idx) 79static __always_inline unsigned long fix_to_virt(const unsigned int idx)
80{ 80{
81 /* 81 /*
82 * this branch gets completely eliminated after inlining, 82 * this branch gets completely eliminated after inlining,
diff --git a/include/asm-x86_64/uaccess.h b/include/asm-x86_64/uaccess.h
index 2892c4b7a28b..bddffcb591b8 100644
--- a/include/asm-x86_64/uaccess.h
+++ b/include/asm-x86_64/uaccess.h
@@ -244,7 +244,7 @@ extern unsigned long copy_to_user(void __user *to, const void *from, unsigned le
244extern unsigned long copy_from_user(void *to, const void __user *from, unsigned len); 244extern unsigned long copy_from_user(void *to, const void __user *from, unsigned len);
245extern unsigned long copy_in_user(void __user *to, const void __user *from, unsigned len); 245extern unsigned long copy_in_user(void __user *to, const void __user *from, unsigned len);
246 246
247static inline int __copy_from_user(void *dst, const void __user *src, unsigned size) 247static __always_inline int __copy_from_user(void *dst, const void __user *src, unsigned size)
248{ 248{
249 int ret = 0; 249 int ret = 0;
250 if (!__builtin_constant_p(size)) 250 if (!__builtin_constant_p(size))
@@ -273,7 +273,7 @@ static inline int __copy_from_user(void *dst, const void __user *src, unsigned s
273 } 273 }
274} 274}
275 275
276static inline int __copy_to_user(void __user *dst, const void *src, unsigned size) 276static __always_inline int __copy_to_user(void __user *dst, const void *src, unsigned size)
277{ 277{
278 int ret = 0; 278 int ret = 0;
279 if (!__builtin_constant_p(size)) 279 if (!__builtin_constant_p(size))
@@ -305,7 +305,7 @@ static inline int __copy_to_user(void __user *dst, const void *src, unsigned siz
305} 305}
306 306
307 307
308static inline int __copy_in_user(void __user *dst, const void __user *src, unsigned size) 308static __always_inline int __copy_in_user(void __user *dst, const void __user *src, unsigned size)
309{ 309{
310 int ret = 0; 310 int ret = 0;
311 if (!__builtin_constant_p(size)) 311 if (!__builtin_constant_p(size))
diff --git a/include/linux/auxvec.h b/include/linux/auxvec.h
index 9a7b374c9fb4..d2bc0d66e65d 100644
--- a/include/linux/auxvec.h
+++ b/include/linux/auxvec.h
@@ -26,6 +26,6 @@
26 26
27#define AT_SECURE 23 /* secure mode boolean */ 27#define AT_SECURE 23 /* secure mode boolean */
28 28
29#define AT_VECTOR_SIZE 42 /* Size of auxiliary table. */ 29#define AT_VECTOR_SIZE 44 /* Size of auxiliary table. */
30 30
31#endif /* _LINUX_AUXVEC_H */ 31#endif /* _LINUX_AUXVEC_H */
diff --git a/include/linux/compiler-gcc3.h b/include/linux/compiler-gcc3.h
index 4209082ee934..1698b845761f 100644
--- a/include/linux/compiler-gcc3.h
+++ b/include/linux/compiler-gcc3.h
@@ -13,3 +13,4 @@
13#define __must_check __attribute__((warn_unused_result)) 13#define __must_check __attribute__((warn_unused_result))
14#endif 14#endif
15 15
16#define __always_inline inline __attribute__((always_inline))
diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h
index e913e9beaf69..6f5cc6f0e7a6 100644
--- a/include/linux/compiler-gcc4.h
+++ b/include/linux/compiler-gcc4.h
@@ -3,7 +3,16 @@
3/* These definitions are for GCC v4.x. */ 3/* These definitions are for GCC v4.x. */
4#include <linux/compiler-gcc.h> 4#include <linux/compiler-gcc.h>
5 5
6#ifdef CONFIG_FORCED_INLINING
7# undef inline
8# undef __inline__
9# undef __inline
10# define inline inline __attribute__((always_inline))
11# define __inline__ __inline__ __attribute__((always_inline))
12# define __inline __inline __attribute__((always_inline))
13#endif
14
6#define __attribute_used__ __attribute__((__used__)) 15#define __attribute_used__ __attribute__((__used__))
7#define __must_check __attribute__((warn_unused_result)) 16#define __must_check __attribute__((warn_unused_result))
8#define __compiler_offsetof(a,b) __builtin_offsetof(a,b) 17#define __compiler_offsetof(a,b) __builtin_offsetof(a,b)
9 18#define __always_inline inline __attribute__((always_inline))
diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
index c472f972bd6d..3bc606927116 100644
--- a/include/linux/cpuset.h
+++ b/include/linux/cpuset.h
@@ -48,6 +48,9 @@ extern void __cpuset_memory_pressure_bump(void);
48extern struct file_operations proc_cpuset_operations; 48extern struct file_operations proc_cpuset_operations;
49extern char *cpuset_task_status_allowed(struct task_struct *task, char *buffer); 49extern char *cpuset_task_status_allowed(struct task_struct *task, char *buffer);
50 50
51extern void cpuset_lock(void);
52extern void cpuset_unlock(void);
53
51#else /* !CONFIG_CPUSETS */ 54#else /* !CONFIG_CPUSETS */
52 55
53static inline int cpuset_init_early(void) { return 0; } 56static inline int cpuset_init_early(void) { return 0; }
@@ -93,6 +96,9 @@ static inline char *cpuset_task_status_allowed(struct task_struct *task,
93 return buffer; 96 return buffer;
94} 97}
95 98
99static inline void cpuset_lock(void) {}
100static inline void cpuset_unlock(void) {}
101
96#endif /* !CONFIG_CPUSETS */ 102#endif /* !CONFIG_CPUSETS */
97 103
98#endif /* _LINUX_CPUSET_H */ 104#endif /* _LINUX_CPUSET_H */
diff --git a/include/linux/device.h b/include/linux/device.h
index 0cdee78e5ce1..58df18d9cd3e 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -49,6 +49,9 @@ struct bus_type {
49 int (*match)(struct device * dev, struct device_driver * drv); 49 int (*match)(struct device * dev, struct device_driver * drv);
50 int (*uevent)(struct device *dev, char **envp, 50 int (*uevent)(struct device *dev, char **envp,
51 int num_envp, char *buffer, int buffer_size); 51 int num_envp, char *buffer, int buffer_size);
52 int (*probe)(struct device * dev);
53 int (*remove)(struct device * dev);
54 void (*shutdown)(struct device * dev);
52 int (*suspend)(struct device * dev, pm_message_t state); 55 int (*suspend)(struct device * dev, pm_message_t state);
53 int (*resume)(struct device * dev); 56 int (*resume)(struct device * dev);
54}; 57};
diff --git a/include/linux/fb.h b/include/linux/fb.h
index a973be2cfe61..2cb19e6503aa 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -608,15 +608,15 @@ struct fb_ops {
608 int (*fb_sync)(struct fb_info *info); 608 int (*fb_sync)(struct fb_info *info);
609 609
610 /* perform fb specific ioctl (optional) */ 610 /* perform fb specific ioctl (optional) */
611 int (*fb_ioctl)(struct inode *inode, struct file *file, unsigned int cmd, 611 int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,
612 unsigned long arg, struct fb_info *info); 612 unsigned long arg);
613 613
614 /* Handle 32bit compat ioctl (optional) */ 614 /* Handle 32bit compat ioctl (optional) */
615 long (*fb_compat_ioctl)(struct file *f, unsigned cmd, unsigned long arg, 615 int (*fb_compat_ioctl)(struct fb_info *info, unsigned cmd,
616 struct fb_info *info); 616 unsigned long arg);
617 617
618 /* perform fb specific mmap */ 618 /* perform fb specific mmap */
619 int (*fb_mmap)(struct fb_info *info, struct file *file, struct vm_area_struct *vma); 619 int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);
620 620
621 /* save current hardware state */ 621 /* save current hardware state */
622 void (*fb_save_state)(struct fb_info *info); 622 void (*fb_save_state)(struct fb_info *info);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index d1e370d25f7b..552cedfa6064 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1383,6 +1383,12 @@ extern int register_chrdev(unsigned int, const char *,
1383extern int unregister_chrdev(unsigned int, const char *); 1383extern int unregister_chrdev(unsigned int, const char *);
1384extern void unregister_chrdev_region(dev_t, unsigned); 1384extern void unregister_chrdev_region(dev_t, unsigned);
1385extern int chrdev_open(struct inode *, struct file *); 1385extern int chrdev_open(struct inode *, struct file *);
1386extern int get_chrdev_list(char *);
1387extern void *acquire_chrdev_list(void);
1388extern int count_chrdev_list(void);
1389extern void *get_next_chrdev(void *);
1390extern int get_chrdev_info(void *, int *, char **);
1391extern void release_chrdev_list(void *);
1386 1392
1387/* fs/block_dev.c */ 1393/* fs/block_dev.c */
1388#define BDEVNAME_SIZE 32 /* Largest string for a blockdev identifier */ 1394#define BDEVNAME_SIZE 32 /* Largest string for a blockdev identifier */
@@ -1391,6 +1397,11 @@ extern const char *bdevname(struct block_device *bdev, char *buffer);
1391extern struct block_device *lookup_bdev(const char *); 1397extern struct block_device *lookup_bdev(const char *);
1392extern struct block_device *open_bdev_excl(const char *, int, void *); 1398extern struct block_device *open_bdev_excl(const char *, int, void *);
1393extern void close_bdev_excl(struct block_device *); 1399extern void close_bdev_excl(struct block_device *);
1400extern void *acquire_blkdev_list(void);
1401extern int count_blkdev_list(void);
1402extern void *get_next_blkdev(void *);
1403extern int get_blkdev_info(void *, int *, char **);
1404extern void release_blkdev_list(void *);
1394 1405
1395extern void init_special_inode(struct inode *, umode_t, dev_t); 1406extern void init_special_inode(struct inode *, umode_t, dev_t);
1396 1407
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
index 71d2b8a723b9..eab537091f2a 100644
--- a/include/linux/hardirq.h
+++ b/include/linux/hardirq.h
@@ -93,10 +93,6 @@ extern void synchronize_irq(unsigned int irq);
93struct task_struct; 93struct task_struct;
94 94
95#ifndef CONFIG_VIRT_CPU_ACCOUNTING 95#ifndef CONFIG_VIRT_CPU_ACCOUNTING
96static inline void account_user_vtime(struct task_struct *tsk)
97{
98}
99
100static inline void account_system_vtime(struct task_struct *tsk) 96static inline void account_system_vtime(struct task_struct *tsk)
101{ 97{
102} 98}
diff --git a/include/linux/ide.h b/include/linux/ide.h
index f2e1b5b22898..110b3cfac021 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -983,8 +983,13 @@ typedef struct ide_driver_s {
983 ide_startstop_t (*abort)(ide_drive_t *, struct request *rq); 983 ide_startstop_t (*abort)(ide_drive_t *, struct request *rq);
984 ide_proc_entry_t *proc; 984 ide_proc_entry_t *proc;
985 struct device_driver gen_driver; 985 struct device_driver gen_driver;
986 int (*probe)(ide_drive_t *);
987 void (*remove)(ide_drive_t *);
988 void (*shutdown)(ide_drive_t *);
986} ide_driver_t; 989} ide_driver_t;
987 990
991#define to_ide_driver(drv) container_of(drv, ide_driver_t, gen_driver)
992
988int generic_ide_ioctl(ide_drive_t *, struct file *, struct block_device *, unsigned, unsigned long); 993int generic_ide_ioctl(ide_drive_t *, struct file *, struct block_device *, unsigned, unsigned long);
989 994
990/* 995/*
diff --git a/include/linux/ioc3.h b/include/linux/ioc3.h
new file mode 100644
index 000000000000..e7906a72a4f1
--- /dev/null
+++ b/include/linux/ioc3.h
@@ -0,0 +1,93 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (c) 2005 Stanislaw Skowronek <skylark@linux-mips.org>
7 */
8
9#ifndef _LINUX_IOC3_H
10#define _LINUX_IOC3_H
11
12#include <asm/sn/ioc3.h>
13
14#define IOC3_MAX_SUBMODULES 32
15
16#define IOC3_CLASS_NONE 0
17#define IOC3_CLASS_BASE_IP27 1
18#define IOC3_CLASS_BASE_IP30 2
19#define IOC3_CLASS_MENET_123 3
20#define IOC3_CLASS_MENET_4 4
21#define IOC3_CLASS_CADDUO 5
22#define IOC3_CLASS_SERIAL 6
23
24/* One of these per IOC3 */
25struct ioc3_driver_data {
26 struct list_head list;
27 int id; /* IOC3 sequence number */
28 /* PCI mapping */
29 unsigned long pma; /* physical address */
30 struct __iomem ioc3 *vma; /* pointer to registers */
31 struct pci_dev *pdev; /* PCI device */
32 /* IRQ stuff */
33 int dual_irq; /* set if separate IRQs are used */
34 int irq_io, irq_eth; /* IRQ numbers */
35 /* GPIO magic */
36 spinlock_t gpio_lock;
37 unsigned int gpdr_shadow;
38 /* NIC identifiers */
39 char nic_part[32];
40 char nic_serial[16];
41 char nic_mac[6];
42 /* submodule set */
43 int class;
44 void *data[IOC3_MAX_SUBMODULES]; /* for submodule use */
45 int active[IOC3_MAX_SUBMODULES]; /* set if probe succeeds */
46 /* is_ir_lock must be held while
47 * modifying sio_ie values, so
48 * we can be sure that sio_ie is
49 * not changing when we read it
50 * along with sio_ir.
51 */
52 spinlock_t ir_lock; /* SIO_IE[SC] mod lock */
53};
54
55/* One per submodule */
56struct ioc3_submodule {
57 char *name; /* descriptive submodule name */
58 struct module *owner; /* owning kernel module */
59 int ethernet; /* set for ethernet drivers */
60 int (*probe) (struct ioc3_submodule *, struct ioc3_driver_data *);
61 int (*remove) (struct ioc3_submodule *, struct ioc3_driver_data *);
62 int id; /* assigned by IOC3, index for the "data" array */
63 /* IRQ stuff */
64 unsigned int irq_mask; /* IOC3 IRQ mask, leave clear for Ethernet */
65 int reset_mask; /* non-zero if you want the ioc3.c module to reset interrupts */
66 int (*intr) (struct ioc3_submodule *, struct ioc3_driver_data *, unsigned int, struct pt_regs *);
67 /* private submodule data */
68 void *data; /* assigned by submodule */
69};
70
71/**********************************
72 * Functions needed by submodules *
73 **********************************/
74
75#define IOC3_W_IES 0
76#define IOC3_W_IEC 1
77
78/* registers a submodule for all existing and future IOC3 chips */
79extern int ioc3_register_submodule(struct ioc3_submodule *);
80/* unregisters a submodule */
81extern void ioc3_unregister_submodule(struct ioc3_submodule *);
82/* enables IRQs indicated by irq_mask for a specified IOC3 chip */
83extern void ioc3_enable(struct ioc3_submodule *, struct ioc3_driver_data *, unsigned int);
84/* ackowledges specified IRQs */
85extern void ioc3_ack(struct ioc3_submodule *, struct ioc3_driver_data *, unsigned int);
86/* disables IRQs indicated by irq_mask for a specified IOC3 chip */
87extern void ioc3_disable(struct ioc3_submodule *, struct ioc3_driver_data *, unsigned int);
88/* atomically sets GPCR bits */
89extern void ioc3_gpcr_set(struct ioc3_driver_data *, unsigned int);
90/* general ireg writer */
91extern void ioc3_write_ireg(struct ioc3_driver_data *idd, uint32_t value, int reg);
92
93#endif
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index e6ee2d95da7a..323924edb26a 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -216,6 +216,7 @@ extern void dump_stack(void);
216 ((unsigned char *)&addr)[1], \ 216 ((unsigned char *)&addr)[1], \
217 ((unsigned char *)&addr)[2], \ 217 ((unsigned char *)&addr)[2], \
218 ((unsigned char *)&addr)[3] 218 ((unsigned char *)&addr)[3]
219#define NIPQUAD_FMT "%u.%u.%u.%u"
219 220
220#define NIP6(addr) \ 221#define NIP6(addr) \
221 ntohs((addr).s6_addr16[0]), \ 222 ntohs((addr).s6_addr16[0]), \
@@ -226,6 +227,7 @@ extern void dump_stack(void);
226 ntohs((addr).s6_addr16[5]), \ 227 ntohs((addr).s6_addr16[5]), \
227 ntohs((addr).s6_addr16[6]), \ 228 ntohs((addr).s6_addr16[6]), \
228 ntohs((addr).s6_addr16[7]) 229 ntohs((addr).s6_addr16[7])
230#define NIP6_FMT "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x"
229 231
230#if defined(__LITTLE_ENDIAN) 232#if defined(__LITTLE_ENDIAN)
231#define HIPQUAD(addr) \ 233#define HIPQUAD(addr) \
diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h
index c7ac77e873b3..d6a53ed6ab6c 100644
--- a/include/linux/mempolicy.h
+++ b/include/linux/mempolicy.h
@@ -132,12 +132,8 @@ struct shared_policy {
132 spinlock_t lock; 132 spinlock_t lock;
133}; 133};
134 134
135static inline void mpol_shared_policy_init(struct shared_policy *info) 135void mpol_shared_policy_init(struct shared_policy *info, int policy,
136{ 136 nodemask_t *nodes);
137 info->root = RB_ROOT;
138 spin_lock_init(&info->lock);
139}
140
141int mpol_set_shared_policy(struct shared_policy *info, 137int mpol_set_shared_policy(struct shared_policy *info,
142 struct vm_area_struct *vma, 138 struct vm_area_struct *vma,
143 struct mempolicy *new); 139 struct mempolicy *new);
@@ -211,7 +207,8 @@ static inline int mpol_set_shared_policy(struct shared_policy *info,
211 return -EINVAL; 207 return -EINVAL;
212} 208}
213 209
214static inline void mpol_shared_policy_init(struct shared_policy *info) 210static inline void mpol_shared_policy_init(struct shared_policy *info,
211 int policy, nodemask_t *nodes)
215{ 212{
216} 213}
217 214
diff --git a/include/linux/mm.h b/include/linux/mm.h
index c643016499a1..85854b867463 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -512,7 +512,7 @@ static inline void set_page_links(struct page *page, unsigned long zone,
512extern struct page *mem_map; 512extern struct page *mem_map;
513#endif 513#endif
514 514
515static inline void *lowmem_page_address(struct page *page) 515static __always_inline void *lowmem_page_address(struct page *page)
516{ 516{
517 return __va(page_to_pfn(page) << PAGE_SHIFT); 517 return __va(page_to_pfn(page) << PAGE_SHIFT);
518} 518}
diff --git a/include/linux/ncp_fs.h b/include/linux/ncp_fs.h
index 7297e4372c0f..e01342568530 100644
--- a/include/linux/ncp_fs.h
+++ b/include/linux/ncp_fs.h
@@ -201,34 +201,6 @@ static inline struct ncp_inode_info *NCP_FINFO(struct inode *inode)
201 return container_of(inode, struct ncp_inode_info, vfs_inode); 201 return container_of(inode, struct ncp_inode_info, vfs_inode);
202} 202}
203 203
204#ifdef DEBUG_NCP_MALLOC
205
206#include <linux/slab.h>
207
208extern int ncp_malloced;
209extern int ncp_current_malloced;
210
211static inline void *
212 ncp_kmalloc(unsigned int size, int priority)
213{
214 ncp_malloced += 1;
215 ncp_current_malloced += 1;
216 return kmalloc(size, priority);
217}
218
219static inline void ncp_kfree_s(void *obj, int size)
220{
221 ncp_current_malloced -= 1;
222 kfree(obj);
223}
224
225#else /* DEBUG_NCP_MALLOC */
226
227#define ncp_kmalloc(s,p) kmalloc(s,p)
228#define ncp_kfree_s(o,s) kfree(o)
229
230#endif /* DEBUG_NCP_MALLOC */
231
232/* linux/fs/ncpfs/inode.c */ 204/* linux/fs/ncpfs/inode.c */
233int ncp_notify_change(struct dentry *, struct iattr *); 205int ncp_notify_change(struct dentry *, struct iattr *);
234struct inode *ncp_iget(struct super_block *, struct ncp_entry_info *); 206struct inode *ncp_iget(struct super_block *, struct ncp_entry_info *);
diff --git a/include/linux/netfilter/nf_conntrack_common.h b/include/linux/netfilter/nf_conntrack_common.h
index 6d39b518486b..3ff88c878308 100644
--- a/include/linux/netfilter/nf_conntrack_common.h
+++ b/include/linux/netfilter/nf_conntrack_common.h
@@ -154,6 +154,9 @@ struct ip_conntrack_stat
154 unsigned int expect_delete; 154 unsigned int expect_delete;
155}; 155};
156 156
157/* call to create an explicit dependency on nf_conntrack. */
158extern void need_conntrack(void);
159
157#endif /* __KERNEL__ */ 160#endif /* __KERNEL__ */
158 161
159#endif /* _NF_CONNTRACK_COMMON_H */ 162#endif /* _NF_CONNTRACK_COMMON_H */
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
new file mode 100644
index 000000000000..472f04834809
--- /dev/null
+++ b/include/linux/netfilter/x_tables.h
@@ -0,0 +1,224 @@
1#ifndef _X_TABLES_H
2#define _X_TABLES_H
3
4#define XT_FUNCTION_MAXNAMELEN 30
5#define XT_TABLE_MAXNAMELEN 32
6
7/* The argument to IPT_SO_GET_REVISION_*. Returns highest revision
8 * kernel supports, if >= revision. */
9struct xt_get_revision
10{
11 char name[XT_FUNCTION_MAXNAMELEN-1];
12
13 u_int8_t revision;
14};
15
16/* CONTINUE verdict for targets */
17#define XT_CONTINUE 0xFFFFFFFF
18
19/* For standard target */
20#define XT_RETURN (-NF_REPEAT - 1)
21
22#define XT_ALIGN(s) (((s) + (__alignof__(void *)-1)) & ~(__alignof__(void *)-1))
23
24/* Standard return verdict, or do jump. */
25#define XT_STANDARD_TARGET ""
26/* Error verdict. */
27#define XT_ERROR_TARGET "ERROR"
28
29/*
30 * New IP firewall options for [gs]etsockopt at the RAW IP level.
31 * Unlike BSD Linux inherits IP options so you don't have to use a raw
32 * socket for this. Instead we check rights in the calls. */
33#define XT_BASE_CTL 64 /* base for firewall socket options */
34
35#define XT_SO_SET_REPLACE (XT_BASE_CTL)
36#define XT_SO_SET_ADD_COUNTERS (XT_BASE_CTL + 1)
37#define XT_SO_SET_MAX XT_SO_SET_ADD_COUNTERS
38
39#define XT_SO_GET_INFO (XT_BASE_CTL)
40#define XT_SO_GET_ENTRIES (XT_BASE_CTL + 1)
41#define XT_SO_GET_REVISION_MATCH (XT_BASE_CTL + 2)
42#define XT_SO_GET_REVISION_TARGET (XT_BASE_CTL + 3)
43#define XT_SO_GET_MAX XT_SO_GET_REVISION_TARGET
44
45#define SET_COUNTER(c,b,p) do { (c).bcnt = (b); (c).pcnt = (p); } while(0)
46#define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0)
47
48struct xt_counters
49{
50 u_int64_t pcnt, bcnt; /* Packet and byte counters */
51};
52
53/* The argument to IPT_SO_ADD_COUNTERS. */
54struct xt_counters_info
55{
56 /* Which table. */
57 char name[XT_TABLE_MAXNAMELEN];
58
59 unsigned int num_counters;
60
61 /* The counters (actually `number' of these). */
62 struct xt_counters counters[0];
63};
64
65#define XT_INV_PROTO 0x40 /* Invert the sense of PROTO. */
66
67#ifdef __KERNEL__
68
69#include <linux/netdevice.h>
70
71#define ASSERT_READ_LOCK(x)
72#define ASSERT_WRITE_LOCK(x)
73#include <linux/netfilter_ipv4/listhelp.h>
74
75struct xt_match
76{
77 struct list_head list;
78
79 const char name[XT_FUNCTION_MAXNAMELEN-1];
80
81 u_int8_t revision;
82
83 /* Return true or false: return FALSE and set *hotdrop = 1 to
84 force immediate packet drop. */
85 /* Arguments changed since 2.6.9, as this must now handle
86 non-linear skb, using skb_header_pointer and
87 skb_ip_make_writable. */
88 int (*match)(const struct sk_buff *skb,
89 const struct net_device *in,
90 const struct net_device *out,
91 const void *matchinfo,
92 int offset,
93 unsigned int protoff,
94 int *hotdrop);
95
96 /* Called when user tries to insert an entry of this type. */
97 /* Should return true or false. */
98 int (*checkentry)(const char *tablename,
99 const void *ip,
100 void *matchinfo,
101 unsigned int matchinfosize,
102 unsigned int hook_mask);
103
104 /* Called when entry of this type deleted. */
105 void (*destroy)(void *matchinfo, unsigned int matchinfosize);
106
107 /* Set this to THIS_MODULE if you are a module, otherwise NULL */
108 struct module *me;
109};
110
111/* Registration hooks for targets. */
112struct xt_target
113{
114 struct list_head list;
115
116 const char name[XT_FUNCTION_MAXNAMELEN-1];
117
118 u_int8_t revision;
119
120 /* Returns verdict. Argument order changed since 2.6.9, as this
121 must now handle non-linear skbs, using skb_copy_bits and
122 skb_ip_make_writable. */
123 unsigned int (*target)(struct sk_buff **pskb,
124 const struct net_device *in,
125 const struct net_device *out,
126 unsigned int hooknum,
127 const void *targinfo,
128 void *userdata);
129
130 /* Called when user tries to insert an entry of this type:
131 hook_mask is a bitmask of hooks from which it can be
132 called. */
133 /* Should return true or false. */
134 int (*checkentry)(const char *tablename,
135 const void *entry,
136 void *targinfo,
137 unsigned int targinfosize,
138 unsigned int hook_mask);
139
140 /* Called when entry of this type deleted. */
141 void (*destroy)(void *targinfo, unsigned int targinfosize);
142
143 /* Set this to THIS_MODULE if you are a module, otherwise NULL */
144 struct module *me;
145};
146
147/* Furniture shopping... */
148struct xt_table
149{
150 struct list_head list;
151
152 /* A unique name... */
153 char name[XT_TABLE_MAXNAMELEN];
154
155 /* What hooks you will enter on */
156 unsigned int valid_hooks;
157
158 /* Lock for the curtain */
159 rwlock_t lock;
160
161 /* Man behind the curtain... */
162 //struct ip6t_table_info *private;
163 void *private;
164
165 /* Set this to THIS_MODULE if you are a module, otherwise NULL */
166 struct module *me;
167
168 int af; /* address/protocol family */
169};
170
171#include <linux/netfilter_ipv4.h>
172
173/* The table itself */
174struct xt_table_info
175{
176 /* Size per table */
177 unsigned int size;
178 /* Number of entries: FIXME. --RR */
179 unsigned int number;
180 /* Initial number of entries. Needed for module usage count */
181 unsigned int initial_entries;
182
183 /* Entry points and underflows */
184 unsigned int hook_entry[NF_IP_NUMHOOKS];
185 unsigned int underflow[NF_IP_NUMHOOKS];
186
187 /* ipt_entry tables: one per CPU */
188 char *entries[NR_CPUS];
189};
190
191extern int xt_register_target(int af, struct xt_target *target);
192extern void xt_unregister_target(int af, struct xt_target *target);
193extern int xt_register_match(int af, struct xt_match *target);
194extern void xt_unregister_match(int af, struct xt_match *target);
195
196extern int xt_register_table(struct xt_table *table,
197 struct xt_table_info *bootstrap,
198 struct xt_table_info *newinfo);
199extern void *xt_unregister_table(struct xt_table *table);
200
201extern struct xt_table_info *xt_replace_table(struct xt_table *table,
202 unsigned int num_counters,
203 struct xt_table_info *newinfo,
204 int *error);
205
206extern struct xt_match *xt_find_match(int af, const char *name, u8 revision);
207extern struct xt_target *xt_find_target(int af, const char *name, u8 revision);
208extern struct xt_target *xt_request_find_target(int af, const char *name,
209 u8 revision);
210extern int xt_find_revision(int af, const char *name, u8 revision, int target,
211 int *err);
212
213extern struct xt_table *xt_find_table_lock(int af, const char *name);
214extern void xt_table_unlock(struct xt_table *t);
215
216extern int xt_proto_init(int af);
217extern void xt_proto_fini(int af);
218
219extern struct xt_table_info *xt_alloc_table_info(unsigned int size);
220extern void xt_free_table_info(struct xt_table_info *info);
221
222#endif /* __KERNEL__ */
223
224#endif /* _X_TABLES_H */
diff --git a/include/linux/netfilter/xt_CLASSIFY.h b/include/linux/netfilter/xt_CLASSIFY.h
new file mode 100644
index 000000000000..58111355255d
--- /dev/null
+++ b/include/linux/netfilter/xt_CLASSIFY.h
@@ -0,0 +1,8 @@
1#ifndef _XT_CLASSIFY_H
2#define _XT_CLASSIFY_H
3
4struct xt_classify_target_info {
5 u_int32_t priority;
6};
7
8#endif /*_XT_CLASSIFY_H */
diff --git a/include/linux/netfilter/xt_CONNMARK.h b/include/linux/netfilter/xt_CONNMARK.h
new file mode 100644
index 000000000000..9f744689fffc
--- /dev/null
+++ b/include/linux/netfilter/xt_CONNMARK.h
@@ -0,0 +1,25 @@
1#ifndef _XT_CONNMARK_H_target
2#define _XT_CONNMARK_H_target
3
4/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
5 * by Henrik Nordstrom <hno@marasystems.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13enum {
14 XT_CONNMARK_SET = 0,
15 XT_CONNMARK_SAVE,
16 XT_CONNMARK_RESTORE
17};
18
19struct xt_connmark_target_info {
20 unsigned long mark;
21 unsigned long mask;
22 u_int8_t mode;
23};
24
25#endif /*_XT_CONNMARK_H_target*/
diff --git a/include/linux/netfilter/xt_MARK.h b/include/linux/netfilter/xt_MARK.h
new file mode 100644
index 000000000000..b021e93ee5d6
--- /dev/null
+++ b/include/linux/netfilter/xt_MARK.h
@@ -0,0 +1,21 @@
1#ifndef _XT_MARK_H_target
2#define _XT_MARK_H_target
3
4/* Version 0 */
5struct xt_mark_target_info {
6 unsigned long mark;
7};
8
9/* Version 1 */
10enum {
11 XT_MARK_SET=0,
12 XT_MARK_AND,
13 XT_MARK_OR,
14};
15
16struct xt_mark_target_info_v1 {
17 unsigned long mark;
18 u_int8_t mode;
19};
20
21#endif /*_XT_MARK_H_target */
diff --git a/include/linux/netfilter/xt_NFQUEUE.h b/include/linux/netfilter/xt_NFQUEUE.h
new file mode 100644
index 000000000000..9a9af79f74d2
--- /dev/null
+++ b/include/linux/netfilter/xt_NFQUEUE.h
@@ -0,0 +1,16 @@
1/* iptables module for using NFQUEUE mechanism
2 *
3 * (C) 2005 Harald Welte <laforge@netfilter.org>
4 *
5 * This software is distributed under GNU GPL v2, 1991
6 *
7*/
8#ifndef _XT_NFQ_TARGET_H
9#define _XT_NFQ_TARGET_H
10
11/* target info */
12struct xt_NFQ_info {
13 u_int16_t queuenum;
14};
15
16#endif /* _XT_NFQ_TARGET_H */
diff --git a/include/linux/netfilter/xt_comment.h b/include/linux/netfilter/xt_comment.h
new file mode 100644
index 000000000000..eacfedc6b5d0
--- /dev/null
+++ b/include/linux/netfilter/xt_comment.h
@@ -0,0 +1,10 @@
1#ifndef _XT_COMMENT_H
2#define _XT_COMMENT_H
3
4#define XT_MAX_COMMENT_LEN 256
5
6struct xt_comment_info {
7 unsigned char comment[XT_MAX_COMMENT_LEN];
8};
9
10#endif /* XT_COMMENT_H */
diff --git a/include/linux/netfilter/xt_connbytes.h b/include/linux/netfilter/xt_connbytes.h
new file mode 100644
index 000000000000..c022c989754d
--- /dev/null
+++ b/include/linux/netfilter/xt_connbytes.h
@@ -0,0 +1,25 @@
1#ifndef _XT_CONNBYTES_H
2#define _XT_CONNBYTES_H
3
4enum xt_connbytes_what {
5 XT_CONNBYTES_PKTS,
6 XT_CONNBYTES_BYTES,
7 XT_CONNBYTES_AVGPKT,
8};
9
10enum xt_connbytes_direction {
11 XT_CONNBYTES_DIR_ORIGINAL,
12 XT_CONNBYTES_DIR_REPLY,
13 XT_CONNBYTES_DIR_BOTH,
14};
15
16struct xt_connbytes_info
17{
18 struct {
19 aligned_u64 from; /* count to be matched */
20 aligned_u64 to; /* count to be matched */
21 } count;
22 u_int8_t what; /* ipt_connbytes_what */
23 u_int8_t direction; /* ipt_connbytes_direction */
24};
25#endif
diff --git a/include/linux/netfilter/xt_connmark.h b/include/linux/netfilter/xt_connmark.h
new file mode 100644
index 000000000000..c592f6ae0883
--- /dev/null
+++ b/include/linux/netfilter/xt_connmark.h
@@ -0,0 +1,18 @@
1#ifndef _XT_CONNMARK_H
2#define _XT_CONNMARK_H
3
4/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
5 * by Henrik Nordstrom <hno@marasystems.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13struct xt_connmark_info {
14 unsigned long mark, mask;
15 u_int8_t invert;
16};
17
18#endif /*_XT_CONNMARK_H*/
diff --git a/include/linux/netfilter/xt_conntrack.h b/include/linux/netfilter/xt_conntrack.h
new file mode 100644
index 000000000000..34f63cf2e293
--- /dev/null
+++ b/include/linux/netfilter/xt_conntrack.h
@@ -0,0 +1,63 @@
1/* Header file for kernel module to match connection tracking information.
2 * GPL (C) 2001 Marc Boucher (marc@mbsi.ca).
3 */
4
5#ifndef _XT_CONNTRACK_H
6#define _XT_CONNTRACK_H
7
8#include <linux/netfilter/nf_conntrack_tuple_common.h>
9#include <linux/in.h>
10
11#define XT_CONNTRACK_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1))
12#define XT_CONNTRACK_STATE_INVALID (1 << 0)
13
14#define XT_CONNTRACK_STATE_SNAT (1 << (IP_CT_NUMBER + 1))
15#define XT_CONNTRACK_STATE_DNAT (1 << (IP_CT_NUMBER + 2))
16#define XT_CONNTRACK_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 3))
17
18/* flags, invflags: */
19#define XT_CONNTRACK_STATE 0x01
20#define XT_CONNTRACK_PROTO 0x02
21#define XT_CONNTRACK_ORIGSRC 0x04
22#define XT_CONNTRACK_ORIGDST 0x08
23#define XT_CONNTRACK_REPLSRC 0x10
24#define XT_CONNTRACK_REPLDST 0x20
25#define XT_CONNTRACK_STATUS 0x40
26#define XT_CONNTRACK_EXPIRES 0x80
27
28/* This is exposed to userspace, so remains frozen in time. */
29struct ip_conntrack_old_tuple
30{
31 struct {
32 __u32 ip;
33 union {
34 __u16 all;
35 } u;
36 } src;
37
38 struct {
39 __u32 ip;
40 union {
41 __u16 all;
42 } u;
43
44 /* The protocol. */
45 u16 protonum;
46 } dst;
47};
48
49struct xt_conntrack_info
50{
51 unsigned int statemask, statusmask;
52
53 struct ip_conntrack_old_tuple tuple[IP_CT_DIR_MAX];
54 struct in_addr sipmsk[IP_CT_DIR_MAX], dipmsk[IP_CT_DIR_MAX];
55
56 unsigned long expires_min, expires_max;
57
58 /* Flags word */
59 u_int8_t flags;
60 /* Inverse flags */
61 u_int8_t invflags;
62};
63#endif /*_XT_CONNTRACK_H*/
diff --git a/include/linux/netfilter/xt_dccp.h b/include/linux/netfilter/xt_dccp.h
new file mode 100644
index 000000000000..e0221b9d32cb
--- /dev/null
+++ b/include/linux/netfilter/xt_dccp.h
@@ -0,0 +1,23 @@
1#ifndef _XT_DCCP_H_
2#define _XT_DCCP_H_
3
4#define XT_DCCP_SRC_PORTS 0x01
5#define XT_DCCP_DEST_PORTS 0x02
6#define XT_DCCP_TYPE 0x04
7#define XT_DCCP_OPTION 0x08
8
9#define XT_DCCP_VALID_FLAGS 0x0f
10
11struct xt_dccp_info {
12 u_int16_t dpts[2]; /* Min, Max */
13 u_int16_t spts[2]; /* Min, Max */
14
15 u_int16_t flags;
16 u_int16_t invflags;
17
18 u_int16_t typemask;
19 u_int8_t option;
20};
21
22#endif /* _XT_DCCP_H_ */
23
diff --git a/include/linux/netfilter/xt_helper.h b/include/linux/netfilter/xt_helper.h
new file mode 100644
index 000000000000..6b42763f999d
--- /dev/null
+++ b/include/linux/netfilter/xt_helper.h
@@ -0,0 +1,8 @@
1#ifndef _XT_HELPER_H
2#define _XT_HELPER_H
3
4struct xt_helper_info {
5 int invert;
6 char name[30];
7};
8#endif /* _XT_HELPER_H */
diff --git a/include/linux/netfilter/xt_length.h b/include/linux/netfilter/xt_length.h
new file mode 100644
index 000000000000..7c2b439f73fe
--- /dev/null
+++ b/include/linux/netfilter/xt_length.h
@@ -0,0 +1,9 @@
1#ifndef _XT_LENGTH_H
2#define _XT_LENGTH_H
3
4struct xt_length_info {
5 u_int16_t min, max;
6 u_int8_t invert;
7};
8
9#endif /*_XT_LENGTH_H*/
diff --git a/include/linux/netfilter/xt_limit.h b/include/linux/netfilter/xt_limit.h
new file mode 100644
index 000000000000..b3ce65375ecb
--- /dev/null
+++ b/include/linux/netfilter/xt_limit.h
@@ -0,0 +1,21 @@
1#ifndef _XT_RATE_H
2#define _XT_RATE_H
3
4/* timings are in milliseconds. */
5#define XT_LIMIT_SCALE 10000
6
7/* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490
8 seconds, or one every 59 hours. */
9struct xt_rateinfo {
10 u_int32_t avg; /* Average secs between packets * scale */
11 u_int32_t burst; /* Period multiplier for upper limit. */
12
13 /* Used internally by the kernel */
14 unsigned long prev;
15 u_int32_t credit;
16 u_int32_t credit_cap, cost;
17
18 /* Ugly, ugly fucker. */
19 struct xt_rateinfo *master;
20};
21#endif /*_XT_RATE_H*/
diff --git a/include/linux/netfilter/xt_mac.h b/include/linux/netfilter/xt_mac.h
new file mode 100644
index 000000000000..b892cdc67e06
--- /dev/null
+++ b/include/linux/netfilter/xt_mac.h
@@ -0,0 +1,8 @@
1#ifndef _XT_MAC_H
2#define _XT_MAC_H
3
4struct xt_mac_info {
5 unsigned char srcaddr[ETH_ALEN];
6 int invert;
7};
8#endif /*_XT_MAC_H*/
diff --git a/include/linux/netfilter/xt_mark.h b/include/linux/netfilter/xt_mark.h
new file mode 100644
index 000000000000..802dd4842caf
--- /dev/null
+++ b/include/linux/netfilter/xt_mark.h
@@ -0,0 +1,9 @@
1#ifndef _XT_MARK_H
2#define _XT_MARK_H
3
4struct xt_mark_info {
5 unsigned long mark, mask;
6 u_int8_t invert;
7};
8
9#endif /*_XT_MARK_H*/
diff --git a/include/linux/netfilter/xt_physdev.h b/include/linux/netfilter/xt_physdev.h
new file mode 100644
index 000000000000..25a7a1815b5b
--- /dev/null
+++ b/include/linux/netfilter/xt_physdev.h
@@ -0,0 +1,24 @@
1#ifndef _XT_PHYSDEV_H
2#define _XT_PHYSDEV_H
3
4#ifdef __KERNEL__
5#include <linux/if.h>
6#endif
7
8#define XT_PHYSDEV_OP_IN 0x01
9#define XT_PHYSDEV_OP_OUT 0x02
10#define XT_PHYSDEV_OP_BRIDGED 0x04
11#define XT_PHYSDEV_OP_ISIN 0x08
12#define XT_PHYSDEV_OP_ISOUT 0x10
13#define XT_PHYSDEV_OP_MASK (0x20 - 1)
14
15struct xt_physdev_info {
16 char physindev[IFNAMSIZ];
17 char in_mask[IFNAMSIZ];
18 char physoutdev[IFNAMSIZ];
19 char out_mask[IFNAMSIZ];
20 u_int8_t invert;
21 u_int8_t bitmask;
22};
23
24#endif /*_XT_PHYSDEV_H*/
diff --git a/include/linux/netfilter/xt_pkttype.h b/include/linux/netfilter/xt_pkttype.h
new file mode 100644
index 000000000000..f265cf52faea
--- /dev/null
+++ b/include/linux/netfilter/xt_pkttype.h
@@ -0,0 +1,8 @@
1#ifndef _XT_PKTTYPE_H
2#define _XT_PKTTYPE_H
3
4struct xt_pkttype_info {
5 int pkttype;
6 int invert;
7};
8#endif /*_XT_PKTTYPE_H*/
diff --git a/include/linux/netfilter/xt_realm.h b/include/linux/netfilter/xt_realm.h
new file mode 100644
index 000000000000..220e87245716
--- /dev/null
+++ b/include/linux/netfilter/xt_realm.h
@@ -0,0 +1,10 @@
1#ifndef _XT_REALM_H
2#define _XT_REALM_H
3
4struct xt_realm_info {
5 u_int32_t id;
6 u_int32_t mask;
7 u_int8_t invert;
8};
9
10#endif /* _XT_REALM_H */
diff --git a/include/linux/netfilter/xt_sctp.h b/include/linux/netfilter/xt_sctp.h
new file mode 100644
index 000000000000..b157897e7792
--- /dev/null
+++ b/include/linux/netfilter/xt_sctp.h
@@ -0,0 +1,107 @@
1#ifndef _XT_SCTP_H_
2#define _XT_SCTP_H_
3
4#define XT_SCTP_SRC_PORTS 0x01
5#define XT_SCTP_DEST_PORTS 0x02
6#define XT_SCTP_CHUNK_TYPES 0x04
7
8#define XT_SCTP_VALID_FLAGS 0x07
9
10#define ELEMCOUNT(x) (sizeof(x)/sizeof(x[0]))
11
12
13struct xt_sctp_flag_info {
14 u_int8_t chunktype;
15 u_int8_t flag;
16 u_int8_t flag_mask;
17};
18
19#define XT_NUM_SCTP_FLAGS 4
20
21struct xt_sctp_info {
22 u_int16_t dpts[2]; /* Min, Max */
23 u_int16_t spts[2]; /* Min, Max */
24
25 u_int32_t chunkmap[256 / sizeof (u_int32_t)]; /* Bit mask of chunks to be matched according to RFC 2960 */
26
27#define SCTP_CHUNK_MATCH_ANY 0x01 /* Match if any of the chunk types are present */
28#define SCTP_CHUNK_MATCH_ALL 0x02 /* Match if all of the chunk types are present */
29#define SCTP_CHUNK_MATCH_ONLY 0x04 /* Match if these are the only chunk types present */
30
31 u_int32_t chunk_match_type;
32 struct xt_sctp_flag_info flag_info[XT_NUM_SCTP_FLAGS];
33 int flag_count;
34
35 u_int32_t flags;
36 u_int32_t invflags;
37};
38
39#define bytes(type) (sizeof(type) * 8)
40
41#define SCTP_CHUNKMAP_SET(chunkmap, type) \
42 do { \
43 chunkmap[type / bytes(u_int32_t)] |= \
44 1 << (type % bytes(u_int32_t)); \
45 } while (0)
46
47#define SCTP_CHUNKMAP_CLEAR(chunkmap, type) \
48 do { \
49 chunkmap[type / bytes(u_int32_t)] &= \
50 ~(1 << (type % bytes(u_int32_t))); \
51 } while (0)
52
53#define SCTP_CHUNKMAP_IS_SET(chunkmap, type) \
54({ \
55 (chunkmap[type / bytes (u_int32_t)] & \
56 (1 << (type % bytes (u_int32_t)))) ? 1: 0; \
57})
58
59#define SCTP_CHUNKMAP_RESET(chunkmap) \
60 do { \
61 int i; \
62 for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
63 chunkmap[i] = 0; \
64 } while (0)
65
66#define SCTP_CHUNKMAP_SET_ALL(chunkmap) \
67 do { \
68 int i; \
69 for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
70 chunkmap[i] = ~0; \
71 } while (0)
72
73#define SCTP_CHUNKMAP_COPY(destmap, srcmap) \
74 do { \
75 int i; \
76 for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
77 destmap[i] = srcmap[i]; \
78 } while (0)
79
80#define SCTP_CHUNKMAP_IS_CLEAR(chunkmap) \
81({ \
82 int i; \
83 int flag = 1; \
84 for (i = 0; i < ELEMCOUNT(chunkmap); i++) { \
85 if (chunkmap[i]) { \
86 flag = 0; \
87 break; \
88 } \
89 } \
90 flag; \
91})
92
93#define SCTP_CHUNKMAP_IS_ALL_SET(chunkmap) \
94({ \
95 int i; \
96 int flag = 1; \
97 for (i = 0; i < ELEMCOUNT(chunkmap); i++) { \
98 if (chunkmap[i] != ~0) { \
99 flag = 0; \
100 break; \
101 } \
102 } \
103 flag; \
104})
105
106#endif /* _XT_SCTP_H_ */
107
diff --git a/include/linux/netfilter/xt_state.h b/include/linux/netfilter/xt_state.h
new file mode 100644
index 000000000000..c06f32edee07
--- /dev/null
+++ b/include/linux/netfilter/xt_state.h
@@ -0,0 +1,13 @@
1#ifndef _XT_STATE_H
2#define _XT_STATE_H
3
4#define XT_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1))
5#define XT_STATE_INVALID (1 << 0)
6
7#define XT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1))
8
9struct xt_state_info
10{
11 unsigned int statemask;
12};
13#endif /*_XT_STATE_H*/
diff --git a/include/linux/netfilter/xt_string.h b/include/linux/netfilter/xt_string.h
new file mode 100644
index 000000000000..3b3419f2637d
--- /dev/null
+++ b/include/linux/netfilter/xt_string.h
@@ -0,0 +1,18 @@
1#ifndef _XT_STRING_H
2#define _XT_STRING_H
3
4#define XT_STRING_MAX_PATTERN_SIZE 128
5#define XT_STRING_MAX_ALGO_NAME_SIZE 16
6
7struct xt_string_info
8{
9 u_int16_t from_offset;
10 u_int16_t to_offset;
11 char algo[XT_STRING_MAX_ALGO_NAME_SIZE];
12 char pattern[XT_STRING_MAX_PATTERN_SIZE];
13 u_int8_t patlen;
14 u_int8_t invert;
15 struct ts_config __attribute__((aligned(8))) *config;
16};
17
18#endif /*_XT_STRING_H*/
diff --git a/include/linux/netfilter/xt_tcpmss.h b/include/linux/netfilter/xt_tcpmss.h
new file mode 100644
index 000000000000..e03274c4c790
--- /dev/null
+++ b/include/linux/netfilter/xt_tcpmss.h
@@ -0,0 +1,9 @@
1#ifndef _XT_TCPMSS_MATCH_H
2#define _XT_TCPMSS_MATCH_H
3
4struct xt_tcpmss_match_info {
5 u_int16_t mss_min, mss_max;
6 u_int8_t invert;
7};
8
9#endif /*_XT_TCPMSS_MATCH_H*/
diff --git a/include/linux/netfilter/xt_tcpudp.h b/include/linux/netfilter/xt_tcpudp.h
new file mode 100644
index 000000000000..78bc65f11adf
--- /dev/null
+++ b/include/linux/netfilter/xt_tcpudp.h
@@ -0,0 +1,36 @@
1#ifndef _XT_TCPUDP_H
2#define _XT_TCPUDP_H
3
4/* TCP matching stuff */
5struct xt_tcp
6{
7 u_int16_t spts[2]; /* Source port range. */
8 u_int16_t dpts[2]; /* Destination port range. */
9 u_int8_t option; /* TCP Option iff non-zero*/
10 u_int8_t flg_mask; /* TCP flags mask byte */
11 u_int8_t flg_cmp; /* TCP flags compare byte */
12 u_int8_t invflags; /* Inverse flags */
13};
14
15/* Values for "inv" field in struct ipt_tcp. */
16#define XT_TCP_INV_SRCPT 0x01 /* Invert the sense of source ports. */
17#define XT_TCP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */
18#define XT_TCP_INV_FLAGS 0x04 /* Invert the sense of TCP flags. */
19#define XT_TCP_INV_OPTION 0x08 /* Invert the sense of option test. */
20#define XT_TCP_INV_MASK 0x0F /* All possible flags. */
21
22/* UDP matching stuff */
23struct xt_udp
24{
25 u_int16_t spts[2]; /* Source port range. */
26 u_int16_t dpts[2]; /* Destination port range. */
27 u_int8_t invflags; /* Inverse flags */
28};
29
30/* Values for "invflags" field in struct ipt_udp. */
31#define XT_UDP_INV_SRCPT 0x01 /* Invert the sense of source ports. */
32#define XT_UDP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */
33#define XT_UDP_INV_MASK 0x03 /* All possible flags. */
34
35
36#endif
diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h
index e98a870a20be..fd21796e5131 100644
--- a/include/linux/netfilter_arp/arp_tables.h
+++ b/include/linux/netfilter_arp/arp_tables.h
@@ -19,8 +19,12 @@
19#include <linux/compiler.h> 19#include <linux/compiler.h>
20#include <linux/netfilter_arp.h> 20#include <linux/netfilter_arp.h>
21 21
22#define ARPT_FUNCTION_MAXNAMELEN 30 22#include <linux/netfilter/x_tables.h>
23#define ARPT_TABLE_MAXNAMELEN 32 23
24#define ARPT_FUNCTION_MAXNAMELEN XT_FUNCTION_MAXNAMELEN
25#define ARPT_TABLE_MAXNAMELEN XT_TABLE_MAXNAMELEN
26#define arpt_target xt_target
27#define arpt_table xt_table
24 28
25#define ARPT_DEV_ADDR_LEN_MAX 16 29#define ARPT_DEV_ADDR_LEN_MAX 16
26 30
@@ -91,11 +95,6 @@ struct arpt_standard_target
91 int verdict; 95 int verdict;
92}; 96};
93 97
94struct arpt_counters
95{
96 u_int64_t pcnt, bcnt; /* Packet and byte counters */
97};
98
99/* Values for "flag" field in struct arpt_ip (general arp structure). 98/* Values for "flag" field in struct arpt_ip (general arp structure).
100 * No flags defined yet. 99 * No flags defined yet.
101 */ 100 */
@@ -130,7 +129,7 @@ struct arpt_entry
130 unsigned int comefrom; 129 unsigned int comefrom;
131 130
132 /* Packet and byte counters. */ 131 /* Packet and byte counters. */
133 struct arpt_counters counters; 132 struct xt_counters counters;
134 133
135 /* The matches (if any), then the target. */ 134 /* The matches (if any), then the target. */
136 unsigned char elems[0]; 135 unsigned char elems[0];
@@ -141,23 +140,24 @@ struct arpt_entry
141 * Unlike BSD Linux inherits IP options so you don't have to use a raw 140 * Unlike BSD Linux inherits IP options so you don't have to use a raw
142 * socket for this. Instead we check rights in the calls. 141 * socket for this. Instead we check rights in the calls.
143 */ 142 */
144#define ARPT_BASE_CTL 96 /* base for firewall socket options */ 143#define ARPT_CTL_OFFSET 32
144#define ARPT_BASE_CTL (XT_BASE_CTL+ARPT_CTL_OFFSET)
145 145
146#define ARPT_SO_SET_REPLACE (ARPT_BASE_CTL) 146#define ARPT_SO_SET_REPLACE (XT_SO_SET_REPLACE+ARPT_CTL_OFFSET)
147#define ARPT_SO_SET_ADD_COUNTERS (ARPT_BASE_CTL + 1) 147#define ARPT_SO_SET_ADD_COUNTERS (XT_SO_SET_ADD_COUNTERS+ARPT_CTL_OFFSET)
148#define ARPT_SO_SET_MAX ARPT_SO_SET_ADD_COUNTERS 148#define ARPT_SO_SET_MAX (XT_SO_SET_MAX+ARPT_CTL_OFFSET)
149 149
150#define ARPT_SO_GET_INFO (ARPT_BASE_CTL) 150#define ARPT_SO_GET_INFO (XT_SO_GET_INFO+ARPT_CTL_OFFSET)
151#define ARPT_SO_GET_ENTRIES (ARPT_BASE_CTL + 1) 151#define ARPT_SO_GET_ENTRIES (XT_SO_GET_ENTRIES+ARPT_CTL_OFFSET)
152/* #define ARPT_SO_GET_REVISION_MATCH (ARPT_BASE_CTL + 2)*/ 152/* #define ARPT_SO_GET_REVISION_MATCH XT_SO_GET_REVISION_MATCH */
153#define ARPT_SO_GET_REVISION_TARGET (ARPT_BASE_CTL + 3) 153#define ARPT_SO_GET_REVISION_TARGET (XT_SO_GET_REVISION_TARGET+ARPT_CTL_OFFSET)
154#define ARPT_SO_GET_MAX ARPT_SO_GET_REVISION_TARGET 154#define ARPT_SO_GET_MAX (XT_SO_GET_REVISION_TARGET+ARPT_CTL_OFFSET)
155 155
156/* CONTINUE verdict for targets */ 156/* CONTINUE verdict for targets */
157#define ARPT_CONTINUE 0xFFFFFFFF 157#define ARPT_CONTINUE XT_CONTINUE
158 158
159/* For standard target */ 159/* For standard target */
160#define ARPT_RETURN (-NF_REPEAT - 1) 160#define ARPT_RETURN XT_RETURN
161 161
162/* The argument to ARPT_SO_GET_INFO */ 162/* The argument to ARPT_SO_GET_INFO */
163struct arpt_getinfo 163struct arpt_getinfo
@@ -208,23 +208,14 @@ struct arpt_replace
208 /* Number of counters (must be equal to current number of entries). */ 208 /* Number of counters (must be equal to current number of entries). */
209 unsigned int num_counters; 209 unsigned int num_counters;
210 /* The old entries' counters. */ 210 /* The old entries' counters. */
211 struct arpt_counters __user *counters; 211 struct xt_counters __user *counters;
212 212
213 /* The entries (hang off end: not really an array). */ 213 /* The entries (hang off end: not really an array). */
214 struct arpt_entry entries[0]; 214 struct arpt_entry entries[0];
215}; 215};
216 216
217/* The argument to ARPT_SO_ADD_COUNTERS. */ 217/* The argument to ARPT_SO_ADD_COUNTERS. */
218struct arpt_counters_info 218#define arpt_counters_info xt_counters_info
219{
220 /* Which table. */
221 char name[ARPT_TABLE_MAXNAMELEN];
222
223 unsigned int num_counters;
224
225 /* The counters (actually `number' of these). */
226 struct arpt_counters counters[0];
227};
228 219
229/* The argument to ARPT_SO_GET_ENTRIES. */ 220/* The argument to ARPT_SO_GET_ENTRIES. */
230struct arpt_get_entries 221struct arpt_get_entries
@@ -239,19 +230,10 @@ struct arpt_get_entries
239 struct arpt_entry entrytable[0]; 230 struct arpt_entry entrytable[0];
240}; 231};
241 232
242/* The argument to ARPT_SO_GET_REVISION_*. Returns highest revision
243 * kernel supports, if >= revision. */
244struct arpt_get_revision
245{
246 char name[ARPT_FUNCTION_MAXNAMELEN-1];
247
248 u_int8_t revision;
249};
250
251/* Standard return verdict, or do jump. */ 233/* Standard return verdict, or do jump. */
252#define ARPT_STANDARD_TARGET "" 234#define ARPT_STANDARD_TARGET XT_STANDARD_TARGET
253/* Error verdict. */ 235/* Error verdict. */
254#define ARPT_ERROR_TARGET "ERROR" 236#define ARPT_ERROR_TARGET XT_ERROR_TARGET
255 237
256/* Helper functions */ 238/* Helper functions */
257static __inline__ struct arpt_entry_target *arpt_get_target(struct arpt_entry *e) 239static __inline__ struct arpt_entry_target *arpt_get_target(struct arpt_entry *e)
@@ -281,63 +263,8 @@ static __inline__ struct arpt_entry_target *arpt_get_target(struct arpt_entry *e
281 */ 263 */
282#ifdef __KERNEL__ 264#ifdef __KERNEL__
283 265
284/* Registration hooks for targets. */ 266#define arpt_register_target(tgt) xt_register_target(NF_ARP, tgt)
285struct arpt_target 267#define arpt_unregister_target(tgt) xt_unregister_target(NF_ARP, tgt)
286{
287 struct list_head list;
288
289 const char name[ARPT_FUNCTION_MAXNAMELEN-1];
290
291 u_int8_t revision;
292
293 /* Returns verdict. */
294 unsigned int (*target)(struct sk_buff **pskb,
295 unsigned int hooknum,
296 const struct net_device *in,
297 const struct net_device *out,
298 const void *targinfo,
299 void *userdata);
300
301 /* Called when user tries to insert an entry of this type:
302 hook_mask is a bitmask of hooks from which it can be
303 called. */
304 /* Should return true or false. */
305 int (*checkentry)(const char *tablename,
306 const struct arpt_entry *e,
307 void *targinfo,
308 unsigned int targinfosize,
309 unsigned int hook_mask);
310
311 /* Called when entry of this type deleted. */
312 void (*destroy)(void *targinfo, unsigned int targinfosize);
313
314 /* Set this to THIS_MODULE if you are a module, otherwise NULL */
315 struct module *me;
316};
317
318extern int arpt_register_target(struct arpt_target *target);
319extern void arpt_unregister_target(struct arpt_target *target);
320
321/* Furniture shopping... */
322struct arpt_table
323{
324 struct list_head list;
325
326 /* A unique name... */
327 char name[ARPT_TABLE_MAXNAMELEN];
328
329 /* What hooks you will enter on */
330 unsigned int valid_hooks;
331
332 /* Lock for the curtain */
333 rwlock_t lock;
334
335 /* Man behind the curtain... */
336 struct arpt_table_info *private;
337
338 /* Set this to THIS_MODULE if you are a module, otherwise NULL */
339 struct module *me;
340};
341 268
342extern int arpt_register_table(struct arpt_table *table, 269extern int arpt_register_table(struct arpt_table *table,
343 const struct arpt_replace *repl); 270 const struct arpt_replace *repl);
diff --git a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h
index b3432ab59a17..215765f043e6 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack.h
@@ -199,9 +199,6 @@ ip_conntrack_put(struct ip_conntrack *ct)
199 nf_conntrack_put(&ct->ct_general); 199 nf_conntrack_put(&ct->ct_general);
200} 200}
201 201
202/* call to create an explicit dependency on ip_conntrack. */
203extern void need_ip_conntrack(void);
204
205extern int invert_tuplepr(struct ip_conntrack_tuple *inverse, 202extern int invert_tuplepr(struct ip_conntrack_tuple *inverse,
206 const struct ip_conntrack_tuple *orig); 203 const struct ip_conntrack_tuple *orig);
207 204
diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h
index d19d65cf4530..76ba24b68515 100644
--- a/include/linux/netfilter_ipv4/ip_tables.h
+++ b/include/linux/netfilter_ipv4/ip_tables.h
@@ -25,8 +25,14 @@
25#include <linux/compiler.h> 25#include <linux/compiler.h>
26#include <linux/netfilter_ipv4.h> 26#include <linux/netfilter_ipv4.h>
27 27
28#define IPT_FUNCTION_MAXNAMELEN 30 28#include <linux/netfilter/x_tables.h>
29#define IPT_TABLE_MAXNAMELEN 32 29
30#define IPT_FUNCTION_MAXNAMELEN XT_FUNCTION_MAXNAMELEN
31#define IPT_TABLE_MAXNAMELEN XT_FUNCTION_MAXNAMELEN
32#define ipt_match xt_match
33#define ipt_target xt_target
34#define ipt_table xt_table
35#define ipt_get_revision xt_get_revision
30 36
31/* Yes, Virginia, you have to zero the padding. */ 37/* Yes, Virginia, you have to zero the padding. */
32struct ipt_ip { 38struct ipt_ip {
@@ -102,10 +108,7 @@ struct ipt_standard_target
102 int verdict; 108 int verdict;
103}; 109};
104 110
105struct ipt_counters 111#define ipt_counters xt_counters
106{
107 u_int64_t pcnt, bcnt; /* Packet and byte counters */
108};
109 112
110/* Values for "flag" field in struct ipt_ip (general ip structure). */ 113/* Values for "flag" field in struct ipt_ip (general ip structure). */
111#define IPT_F_FRAG 0x01 /* Set if rule is a fragment rule */ 114#define IPT_F_FRAG 0x01 /* Set if rule is a fragment rule */
@@ -119,7 +122,7 @@ struct ipt_counters
119#define IPT_INV_SRCIP 0x08 /* Invert the sense of SRC IP. */ 122#define IPT_INV_SRCIP 0x08 /* Invert the sense of SRC IP. */
120#define IPT_INV_DSTIP 0x10 /* Invert the sense of DST OP. */ 123#define IPT_INV_DSTIP 0x10 /* Invert the sense of DST OP. */
121#define IPT_INV_FRAG 0x20 /* Invert the sense of FRAG. */ 124#define IPT_INV_FRAG 0x20 /* Invert the sense of FRAG. */
122#define IPT_INV_PROTO 0x40 /* Invert the sense of PROTO. */ 125#define IPT_INV_PROTO XT_INV_PROTO
123#define IPT_INV_MASK 0x7F /* All possible flag bits mask. */ 126#define IPT_INV_MASK 0x7F /* All possible flag bits mask. */
124 127
125/* This structure defines each of the firewall rules. Consists of 3 128/* This structure defines each of the firewall rules. Consists of 3
@@ -141,7 +144,7 @@ struct ipt_entry
141 unsigned int comefrom; 144 unsigned int comefrom;
142 145
143 /* Packet and byte counters. */ 146 /* Packet and byte counters. */
144 struct ipt_counters counters; 147 struct xt_counters counters;
145 148
146 /* The matches (if any), then the target. */ 149 /* The matches (if any), then the target. */
147 unsigned char elems[0]; 150 unsigned char elems[0];
@@ -151,54 +154,34 @@ struct ipt_entry
151 * New IP firewall options for [gs]etsockopt at the RAW IP level. 154 * New IP firewall options for [gs]etsockopt at the RAW IP level.
152 * Unlike BSD Linux inherits IP options so you don't have to use a raw 155 * Unlike BSD Linux inherits IP options so you don't have to use a raw
153 * socket for this. Instead we check rights in the calls. */ 156 * socket for this. Instead we check rights in the calls. */
154#define IPT_BASE_CTL 64 /* base for firewall socket options */ 157#define IPT_BASE_CTL XT_BASE_CTL
155 158
156#define IPT_SO_SET_REPLACE (IPT_BASE_CTL) 159#define IPT_SO_SET_REPLACE XT_SO_SET_REPLACE
157#define IPT_SO_SET_ADD_COUNTERS (IPT_BASE_CTL + 1) 160#define IPT_SO_SET_ADD_COUNTERS XT_SO_SET_ADD_COUNTERS
158#define IPT_SO_SET_MAX IPT_SO_SET_ADD_COUNTERS 161#define IPT_SO_SET_MAX XT_SO_SET_MAX
159 162
160#define IPT_SO_GET_INFO (IPT_BASE_CTL) 163#define IPT_SO_GET_INFO XT_SO_GET_INFO
161#define IPT_SO_GET_ENTRIES (IPT_BASE_CTL + 1) 164#define IPT_SO_GET_ENTRIES XT_SO_GET_ENTRIES
162#define IPT_SO_GET_REVISION_MATCH (IPT_BASE_CTL + 2) 165#define IPT_SO_GET_REVISION_MATCH XT_SO_GET_REVISION_MATCH
163#define IPT_SO_GET_REVISION_TARGET (IPT_BASE_CTL + 3) 166#define IPT_SO_GET_REVISION_TARGET XT_SO_GET_REVISION_TARGET
164#define IPT_SO_GET_MAX IPT_SO_GET_REVISION_TARGET 167#define IPT_SO_GET_MAX XT_SO_GET_REVISION_TARGET
165 168
166/* CONTINUE verdict for targets */ 169#define IPT_CONTINUE XT_CONTINUE
167#define IPT_CONTINUE 0xFFFFFFFF 170#define IPT_RETURN XT_RETURN
168 171
169/* For standard target */ 172#include <linux/netfilter/xt_tcpudp.h>
170#define IPT_RETURN (-NF_REPEAT - 1) 173#define ipt_udp xt_udp
174#define ipt_tcp xt_tcp
171 175
172/* TCP matching stuff */ 176#define IPT_TCP_INV_SRCPT XT_TCP_INV_SRCPT
173struct ipt_tcp 177#define IPT_TCP_INV_DSTPT XT_TCP_INV_DSTPT
174{ 178#define IPT_TCP_INV_FLAGS XT_TCP_INV_FLAGS
175 u_int16_t spts[2]; /* Source port range. */ 179#define IPT_TCP_INV_OPTION XT_TCP_INV_OPTION
176 u_int16_t dpts[2]; /* Destination port range. */ 180#define IPT_TCP_INV_MASK XT_TCP_INV_MASK
177 u_int8_t option; /* TCP Option iff non-zero*/
178 u_int8_t flg_mask; /* TCP flags mask byte */
179 u_int8_t flg_cmp; /* TCP flags compare byte */
180 u_int8_t invflags; /* Inverse flags */
181};
182
183/* Values for "inv" field in struct ipt_tcp. */
184#define IPT_TCP_INV_SRCPT 0x01 /* Invert the sense of source ports. */
185#define IPT_TCP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */
186#define IPT_TCP_INV_FLAGS 0x04 /* Invert the sense of TCP flags. */
187#define IPT_TCP_INV_OPTION 0x08 /* Invert the sense of option test. */
188#define IPT_TCP_INV_MASK 0x0F /* All possible flags. */
189
190/* UDP matching stuff */
191struct ipt_udp
192{
193 u_int16_t spts[2]; /* Source port range. */
194 u_int16_t dpts[2]; /* Destination port range. */
195 u_int8_t invflags; /* Inverse flags */
196};
197 181
198/* Values for "invflags" field in struct ipt_udp. */ 182#define IPT_UDP_INV_SRCPT XT_UDP_INV_SRCPT
199#define IPT_UDP_INV_SRCPT 0x01 /* Invert the sense of source ports. */ 183#define IPT_UDP_INV_DSTPT XT_UDP_INV_DSTPT
200#define IPT_UDP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */ 184#define IPT_UDP_INV_MASK XT_UDP_INV_MASK
201#define IPT_UDP_INV_MASK 0x03 /* All possible flags. */
202 185
203/* ICMP matching stuff */ 186/* ICMP matching stuff */
204struct ipt_icmp 187struct ipt_icmp
@@ -260,23 +243,14 @@ struct ipt_replace
260 /* Number of counters (must be equal to current number of entries). */ 243 /* Number of counters (must be equal to current number of entries). */
261 unsigned int num_counters; 244 unsigned int num_counters;
262 /* The old entries' counters. */ 245 /* The old entries' counters. */
263 struct ipt_counters __user *counters; 246 struct xt_counters __user *counters;
264 247
265 /* The entries (hang off end: not really an array). */ 248 /* The entries (hang off end: not really an array). */
266 struct ipt_entry entries[0]; 249 struct ipt_entry entries[0];
267}; 250};
268 251
269/* The argument to IPT_SO_ADD_COUNTERS. */ 252/* The argument to IPT_SO_ADD_COUNTERS. */
270struct ipt_counters_info 253#define ipt_counters_info xt_counters_info
271{
272 /* Which table. */
273 char name[IPT_TABLE_MAXNAMELEN];
274
275 unsigned int num_counters;
276
277 /* The counters (actually `number' of these). */
278 struct ipt_counters counters[0];
279};
280 254
281/* The argument to IPT_SO_GET_ENTRIES. */ 255/* The argument to IPT_SO_GET_ENTRIES. */
282struct ipt_get_entries 256struct ipt_get_entries
@@ -291,19 +265,10 @@ struct ipt_get_entries
291 struct ipt_entry entrytable[0]; 265 struct ipt_entry entrytable[0];
292}; 266};
293 267
294/* The argument to IPT_SO_GET_REVISION_*. Returns highest revision
295 * kernel supports, if >= revision. */
296struct ipt_get_revision
297{
298 char name[IPT_FUNCTION_MAXNAMELEN-1];
299
300 u_int8_t revision;
301};
302
303/* Standard return verdict, or do jump. */ 268/* Standard return verdict, or do jump. */
304#define IPT_STANDARD_TARGET "" 269#define IPT_STANDARD_TARGET XT_STANDARD_TARGET
305/* Error verdict. */ 270/* Error verdict. */
306#define IPT_ERROR_TARGET "ERROR" 271#define IPT_ERROR_TARGET XT_ERROR_TARGET
307 272
308/* Helper functions */ 273/* Helper functions */
309static __inline__ struct ipt_entry_target * 274static __inline__ struct ipt_entry_target *
@@ -356,103 +321,18 @@ ipt_get_target(struct ipt_entry *e)
356#include <linux/init.h> 321#include <linux/init.h>
357extern void ipt_init(void) __init; 322extern void ipt_init(void) __init;
358 323
359struct ipt_match 324#define ipt_register_target(tgt) xt_register_target(AF_INET, tgt)
360{ 325#define ipt_unregister_target(tgt) xt_unregister_target(AF_INET, tgt)
361 struct list_head list;
362
363 const char name[IPT_FUNCTION_MAXNAMELEN-1];
364
365 u_int8_t revision;
366
367 /* Return true or false: return FALSE and set *hotdrop = 1 to
368 force immediate packet drop. */
369 /* Arguments changed since 2.4, as this must now handle
370 non-linear skbs, using skb_copy_bits and
371 skb_ip_make_writable. */
372 int (*match)(const struct sk_buff *skb,
373 const struct net_device *in,
374 const struct net_device *out,
375 const void *matchinfo,
376 int offset,
377 int *hotdrop);
378
379 /* Called when user tries to insert an entry of this type. */
380 /* Should return true or false. */
381 int (*checkentry)(const char *tablename,
382 const struct ipt_ip *ip,
383 void *matchinfo,
384 unsigned int matchinfosize,
385 unsigned int hook_mask);
386
387 /* Called when entry of this type deleted. */
388 void (*destroy)(void *matchinfo, unsigned int matchinfosize);
389
390 /* Set this to THIS_MODULE. */
391 struct module *me;
392};
393
394/* Registration hooks for targets. */
395struct ipt_target
396{
397 struct list_head list;
398
399 const char name[IPT_FUNCTION_MAXNAMELEN-1];
400
401 u_int8_t revision;
402
403 /* Called when user tries to insert an entry of this type:
404 hook_mask is a bitmask of hooks from which it can be
405 called. */
406 /* Should return true or false. */
407 int (*checkentry)(const char *tablename,
408 const struct ipt_entry *e,
409 void *targinfo,
410 unsigned int targinfosize,
411 unsigned int hook_mask);
412
413 /* Called when entry of this type deleted. */
414 void (*destroy)(void *targinfo, unsigned int targinfosize);
415
416 /* Returns verdict. Argument order changed since 2.4, as this
417 must now handle non-linear skbs, using skb_copy_bits and
418 skb_ip_make_writable. */
419 unsigned int (*target)(struct sk_buff **pskb,
420 const struct net_device *in,
421 const struct net_device *out,
422 unsigned int hooknum,
423 const void *targinfo,
424 void *userdata);
425
426 /* Set this to THIS_MODULE. */
427 struct module *me;
428};
429 326
430extern int ipt_register_target(struct ipt_target *target); 327#define ipt_register_match(mtch) xt_register_match(AF_INET, mtch)
431extern void ipt_unregister_target(struct ipt_target *target); 328#define ipt_unregister_match(mtch) xt_unregister_match(AF_INET, mtch)
432 329
433extern int ipt_register_match(struct ipt_match *match); 330//#define ipt_register_table(tbl, repl) xt_register_table(AF_INET, tbl, repl)
434extern void ipt_unregister_match(struct ipt_match *match); 331//#define ipt_unregister_table(tbl) xt_unregister_table(AF_INET, tbl)
435 332
436/* Furniture shopping... */ 333extern int ipt_register_table(struct ipt_table *table,
437struct ipt_table 334 const struct ipt_replace *repl);
438{ 335extern void ipt_unregister_table(struct ipt_table *table);
439 struct list_head list;
440
441 /* A unique name... */
442 char name[IPT_TABLE_MAXNAMELEN];
443
444 /* What hooks you will enter on */
445 unsigned int valid_hooks;
446
447 /* Lock for the curtain */
448 rwlock_t lock;
449
450 /* Man behind the curtain... */
451 struct ipt_table_info *private;
452
453 /* Set to THIS_MODULE. */
454 struct module *me;
455};
456 336
457/* net/sched/ipt.c: Gimme access to your targets! Gets target->me. */ 337/* net/sched/ipt.c: Gimme access to your targets! Gets target->me. */
458extern struct ipt_target *ipt_find_target(const char *name, u8 revision); 338extern struct ipt_target *ipt_find_target(const char *name, u8 revision);
@@ -476,9 +356,6 @@ struct ipt_error
476 struct ipt_error_target target; 356 struct ipt_error_target target;
477}; 357};
478 358
479extern int ipt_register_table(struct ipt_table *table,
480 const struct ipt_replace *repl);
481extern void ipt_unregister_table(struct ipt_table *table);
482extern unsigned int ipt_do_table(struct sk_buff **pskb, 359extern unsigned int ipt_do_table(struct sk_buff **pskb,
483 unsigned int hook, 360 unsigned int hook,
484 const struct net_device *in, 361 const struct net_device *in,
@@ -486,6 +363,6 @@ extern unsigned int ipt_do_table(struct sk_buff **pskb,
486 struct ipt_table *table, 363 struct ipt_table *table,
487 void *userdata); 364 void *userdata);
488 365
489#define IPT_ALIGN(s) (((s) + (__alignof__(struct ipt_entry)-1)) & ~(__alignof__(struct ipt_entry)-1)) 366#define IPT_ALIGN(s) XT_ALIGN(s)
490#endif /*__KERNEL__*/ 367#endif /*__KERNEL__*/
491#endif /* _IPTABLES_H */ 368#endif /* _IPTABLES_H */
diff --git a/include/linux/netfilter_ipv4/ipt_CLASSIFY.h b/include/linux/netfilter_ipv4/ipt_CLASSIFY.h
index 7596e3dd00ca..a46d511b5c36 100644
--- a/include/linux/netfilter_ipv4/ipt_CLASSIFY.h
+++ b/include/linux/netfilter_ipv4/ipt_CLASSIFY.h
@@ -1,8 +1,7 @@
1#ifndef _IPT_CLASSIFY_H 1#ifndef _IPT_CLASSIFY_H
2#define _IPT_CLASSIFY_H 2#define _IPT_CLASSIFY_H
3 3
4struct ipt_classify_target_info { 4#include <linux/netfilter/xt_CLASSIFY.h>
5 u_int32_t priority; 5#define ipt_classify_target_info xt_classify_target_info
6};
7 6
8#endif /*_IPT_CLASSIFY_H */ 7#endif /*_IPT_CLASSIFY_H */
diff --git a/include/linux/netfilter_ipv4/ipt_CONNMARK.h b/include/linux/netfilter_ipv4/ipt_CONNMARK.h
index d3c02536fc4c..9ecfee0a9e33 100644
--- a/include/linux/netfilter_ipv4/ipt_CONNMARK.h
+++ b/include/linux/netfilter_ipv4/ipt_CONNMARK.h
@@ -9,17 +9,11 @@
9 * the Free Software Foundation; either version 2 of the License, or 9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version. 10 * (at your option) any later version.
11 */ 11 */
12#include <linux/netfilter/xt_CONNMARK.h>
13#define IPT_CONNMARK_SET XT_CONNMARK_SET
14#define IPT_CONNMARK_SAVE XT_CONNMARK_SAVE
15#define IPT_CONNMARK_RESTORE XT_CONNMARK_RESTORE
12 16
13enum { 17#define ipt_connmark_target_info xt_connmark_target_info
14 IPT_CONNMARK_SET = 0,
15 IPT_CONNMARK_SAVE,
16 IPT_CONNMARK_RESTORE
17};
18
19struct ipt_connmark_target_info {
20 unsigned long mark;
21 unsigned long mask;
22 u_int8_t mode;
23};
24 18
25#endif /*_IPT_CONNMARK_H_target*/ 19#endif /*_IPT_CONNMARK_H_target*/
diff --git a/include/linux/netfilter_ipv4/ipt_MARK.h b/include/linux/netfilter_ipv4/ipt_MARK.h
index f47485790ed4..697a486a96d3 100644
--- a/include/linux/netfilter_ipv4/ipt_MARK.h
+++ b/include/linux/netfilter_ipv4/ipt_MARK.h
@@ -1,20 +1,18 @@
1#ifndef _IPT_MARK_H_target 1#ifndef _IPT_MARK_H_target
2#define _IPT_MARK_H_target 2#define _IPT_MARK_H_target
3 3
4/* Backwards compatibility for old userspace */
5
6#include <linux/netfilter/xt_MARK.h>
7
4/* Version 0 */ 8/* Version 0 */
5struct ipt_mark_target_info { 9#define ipt_mark_target_info xt_mark_target_info
6 unsigned long mark;
7};
8 10
9/* Version 1 */ 11/* Version 1 */
10enum { 12#define IPT_MARK_SET XT_MARK_SET
11 IPT_MARK_SET=0, 13#define IPT_MARK_AND XT_MARK_AND
12 IPT_MARK_AND, 14#define IPT_MARK_OR XT_MARK_OR
13 IPT_MARK_OR 15
14}; 16#define ipt_mark_target_info_v1 xt_mark_target_info_v1
15 17
16struct ipt_mark_target_info_v1 {
17 unsigned long mark;
18 u_int8_t mode;
19};
20#endif /*_IPT_MARK_H_target*/ 18#endif /*_IPT_MARK_H_target*/
diff --git a/include/linux/netfilter_ipv4/ipt_NFQUEUE.h b/include/linux/netfilter_ipv4/ipt_NFQUEUE.h
index b5b2943b0c66..97a2a7557cb9 100644
--- a/include/linux/netfilter_ipv4/ipt_NFQUEUE.h
+++ b/include/linux/netfilter_ipv4/ipt_NFQUEUE.h
@@ -8,9 +8,9 @@
8#ifndef _IPT_NFQ_TARGET_H 8#ifndef _IPT_NFQ_TARGET_H
9#define _IPT_NFQ_TARGET_H 9#define _IPT_NFQ_TARGET_H
10 10
11/* target info */ 11/* Backwards compatibility for old userspace */
12struct ipt_NFQ_info { 12#include <linux/netfilter/xt_NFQUEUE.h>
13 u_int16_t queuenum; 13
14}; 14#define ipt_NFQ_info xt_NFQ_info
15 15
16#endif /* _IPT_DSCP_TARGET_H */ 16#endif /* _IPT_DSCP_TARGET_H */
diff --git a/include/linux/netfilter_ipv4/ipt_comment.h b/include/linux/netfilter_ipv4/ipt_comment.h
index 85c1123c29ce..ae2afc2f7481 100644
--- a/include/linux/netfilter_ipv4/ipt_comment.h
+++ b/include/linux/netfilter_ipv4/ipt_comment.h
@@ -1,10 +1,10 @@
1#ifndef _IPT_COMMENT_H 1#ifndef _IPT_COMMENT_H
2#define _IPT_COMMENT_H 2#define _IPT_COMMENT_H
3 3
4#define IPT_MAX_COMMENT_LEN 256 4#include <linux/netfilter/xt_comment.h>
5 5
6struct ipt_comment_info { 6#define IPT_MAX_COMMENT_LEN XT_MAX_COMMENT_LEN
7 unsigned char comment[IPT_MAX_COMMENT_LEN]; 7
8}; 8#define ipt_comment_info xt_comment_info
9 9
10#endif /* _IPT_COMMENT_H */ 10#endif /* _IPT_COMMENT_H */
diff --git a/include/linux/netfilter_ipv4/ipt_connbytes.h b/include/linux/netfilter_ipv4/ipt_connbytes.h
index 9e5532f8d8ac..b04dfa3083c9 100644
--- a/include/linux/netfilter_ipv4/ipt_connbytes.h
+++ b/include/linux/netfilter_ipv4/ipt_connbytes.h
@@ -1,25 +1,18 @@
1#ifndef _IPT_CONNBYTES_H 1#ifndef _IPT_CONNBYTES_H
2#define _IPT_CONNBYTES_H 2#define _IPT_CONNBYTES_H
3 3
4enum ipt_connbytes_what { 4#include <net/netfilter/xt_connbytes.h>
5 IPT_CONNBYTES_PKTS, 5#define ipt_connbytes_what xt_connbytes_what
6 IPT_CONNBYTES_BYTES,
7 IPT_CONNBYTES_AVGPKT,
8};
9 6
10enum ipt_connbytes_direction { 7#define IPT_CONNBYTES_PKTS XT_CONNBYTES_PACKETS
11 IPT_CONNBYTES_DIR_ORIGINAL, 8#define IPT_CONNBYTES_BYTES XT_CONNBYTES_BYTES
12 IPT_CONNBYTES_DIR_REPLY, 9#define IPT_CONNBYTES_AVGPKT XT_CONNBYTES_AVGPKT
13 IPT_CONNBYTES_DIR_BOTH, 10
14}; 11#define ipt_connbytes_direction xt_connbytes_direction
12#define IPT_CONNBYTES_DIR_ORIGINAL XT_CONNBYTES_DIR_ORIGINAL
13#define IPT_CONNBYTES_DIR_REPLY XT_CONNBYTES_DIR_REPLY
14#define IPT_CONNBYTES_DIR_BOTH XT_CONNBYTES_DIR_BOTH
15
16#define ipt_connbytes_info xt_connbytes_info
15 17
16struct ipt_connbytes_info
17{
18 struct {
19 aligned_u64 from; /* count to be matched */
20 aligned_u64 to; /* count to be matched */
21 } count;
22 u_int8_t what; /* ipt_connbytes_what */
23 u_int8_t direction; /* ipt_connbytes_direction */
24};
25#endif 18#endif
diff --git a/include/linux/netfilter_ipv4/ipt_connmark.h b/include/linux/netfilter_ipv4/ipt_connmark.h
index 46573270d9aa..c7ba6560d44c 100644
--- a/include/linux/netfilter_ipv4/ipt_connmark.h
+++ b/include/linux/netfilter_ipv4/ipt_connmark.h
@@ -1,18 +1,7 @@
1#ifndef _IPT_CONNMARK_H 1#ifndef _IPT_CONNMARK_H
2#define _IPT_CONNMARK_H 2#define _IPT_CONNMARK_H
3 3
4/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com> 4#include <linux/netfilter/xt_connmark.h>
5 * by Henrik Nordstrom <hno@marasystems.com> 5#define ipt_connmark_info xt_connmark_info
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13struct ipt_connmark_info {
14 unsigned long mark, mask;
15 u_int8_t invert;
16};
17 6
18#endif /*_IPT_CONNMARK_H*/ 7#endif /*_IPT_CONNMARK_H*/
diff --git a/include/linux/netfilter_ipv4/ipt_conntrack.h b/include/linux/netfilter_ipv4/ipt_conntrack.h
index 413c5658bd3a..cde6762949c5 100644
--- a/include/linux/netfilter_ipv4/ipt_conntrack.h
+++ b/include/linux/netfilter_ipv4/ipt_conntrack.h
@@ -5,56 +5,24 @@
5#ifndef _IPT_CONNTRACK_H 5#ifndef _IPT_CONNTRACK_H
6#define _IPT_CONNTRACK_H 6#define _IPT_CONNTRACK_H
7 7
8#define IPT_CONNTRACK_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1)) 8#include <linux/netfilter/xt_conntrack.h>
9#define IPT_CONNTRACK_STATE_INVALID (1 << 0)
10 9
11#define IPT_CONNTRACK_STATE_SNAT (1 << (IP_CT_NUMBER + 1)) 10#define IPT_CONNTRACK_STATE_BIT(ctinfo) XT_CONNTRACK_STATE_BIT(ctinfo)
12#define IPT_CONNTRACK_STATE_DNAT (1 << (IP_CT_NUMBER + 2)) 11#define IPT_CONNTRACK_STATE_INVALID XT_CONNTRACK_STATE_INVALID
13#define IPT_CONNTRACK_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 3))
14 12
15/* flags, invflags: */ 13#define IPT_CONNTRACK_STATE_SNAT XT_CONNTRACK_STATE_SNAT
16#define IPT_CONNTRACK_STATE 0x01 14#define IPT_CONNTRACK_STATE_DNAT XT_CONNTRACK_STATE_DNAT
17#define IPT_CONNTRACK_PROTO 0x02 15#define IPT_CONNTRACK_STATE_UNTRACKED XT_CONNTRACK_STATE_UNTRACKED
18#define IPT_CONNTRACK_ORIGSRC 0x04
19#define IPT_CONNTRACK_ORIGDST 0x08
20#define IPT_CONNTRACK_REPLSRC 0x10
21#define IPT_CONNTRACK_REPLDST 0x20
22#define IPT_CONNTRACK_STATUS 0x40
23#define IPT_CONNTRACK_EXPIRES 0x80
24
25/* This is exposed to userspace, so remains frozen in time. */
26struct ip_conntrack_old_tuple
27{
28 struct {
29 __u32 ip;
30 union {
31 __u16 all;
32 } u;
33 } src;
34
35 struct {
36 __u32 ip;
37 union {
38 __u16 all;
39 } u;
40
41 /* The protocol. */
42 u16 protonum;
43 } dst;
44};
45 16
46struct ipt_conntrack_info 17/* flags, invflags: */
47{ 18#define IPT_CONNTRACK_STATE XT_CONNTRACK_STATE
48 unsigned int statemask, statusmask; 19#define IPT_CONNTRACK_PROTO XT_CONNTRACK_PROTO
49 20#define IPT_CONNTRACK_ORIGSRC XT_CONNTRACK_ORIGSRC
50 struct ip_conntrack_old_tuple tuple[IP_CT_DIR_MAX]; 21#define IPT_CONNTRACK_ORIGDST XT_CONNTRACK_ORIGDST
51 struct in_addr sipmsk[IP_CT_DIR_MAX], dipmsk[IP_CT_DIR_MAX]; 22#define IPT_CONNTRACK_REPLSRC XT_CONNTRACK_REPLSRC
52 23#define IPT_CONNTRACK_REPLDST XT_CONNTRACK_REPLDST
53 unsigned long expires_min, expires_max; 24#define IPT_CONNTRACK_STATUS XT_CONNTRACK_STATUS
54 25#define IPT_CONNTRACK_EXPIRES XT_CONNTRACK_EXPIRES
55 /* Flags word */ 26
56 u_int8_t flags; 27#define ipt_conntrack_info xt_conntrack_info
57 /* Inverse flags */
58 u_int8_t invflags;
59};
60#endif /*_IPT_CONNTRACK_H*/ 28#endif /*_IPT_CONNTRACK_H*/
diff --git a/include/linux/netfilter_ipv4/ipt_dccp.h b/include/linux/netfilter_ipv4/ipt_dccp.h
index 3cb3a522e62b..e70d11e1f53c 100644
--- a/include/linux/netfilter_ipv4/ipt_dccp.h
+++ b/include/linux/netfilter_ipv4/ipt_dccp.h
@@ -1,23 +1,15 @@
1#ifndef _IPT_DCCP_H_ 1#ifndef _IPT_DCCP_H_
2#define _IPT_DCCP_H_ 2#define _IPT_DCCP_H_
3 3
4#define IPT_DCCP_SRC_PORTS 0x01 4#include <linux/netfilter/xt_dccp.h>
5#define IPT_DCCP_DEST_PORTS 0x02 5#define IPT_DCCP_SRC_PORTS XT_DCCP_SRC_PORTS
6#define IPT_DCCP_TYPE 0x04 6#define IPT_DCCP_DEST_PORTS XT_DCCP_DEST_PORTS
7#define IPT_DCCP_OPTION 0x08 7#define IPT_DCCP_TYPE XT_DCCP_TYPE
8#define IPT_DCCP_OPTION XT_DCCP_OPTION
8 9
9#define IPT_DCCP_VALID_FLAGS 0x0f 10#define IPT_DCCP_VALID_FLAGS XT_DCCP_VALID_FLAGS
10 11
11struct ipt_dccp_info { 12#define ipt_dccp_info xt_dccp_info
12 u_int16_t dpts[2]; /* Min, Max */
13 u_int16_t spts[2]; /* Min, Max */
14
15 u_int16_t flags;
16 u_int16_t invflags;
17
18 u_int16_t typemask;
19 u_int8_t option;
20};
21 13
22#endif /* _IPT_DCCP_H_ */ 14#endif /* _IPT_DCCP_H_ */
23 15
diff --git a/include/linux/netfilter_ipv4/ipt_helper.h b/include/linux/netfilter_ipv4/ipt_helper.h
index 6f12ecb8c93d..80452c218551 100644
--- a/include/linux/netfilter_ipv4/ipt_helper.h
+++ b/include/linux/netfilter_ipv4/ipt_helper.h
@@ -1,8 +1,7 @@
1#ifndef _IPT_HELPER_H 1#ifndef _IPT_HELPER_H
2#define _IPT_HELPER_H 2#define _IPT_HELPER_H
3 3
4struct ipt_helper_info { 4#include <linux/netfilter/xt_helper.h>
5 int invert; 5#define ipt_helper_info xt_helper_info
6 char name[30]; 6
7};
8#endif /* _IPT_HELPER_H */ 7#endif /* _IPT_HELPER_H */
diff --git a/include/linux/netfilter_ipv4/ipt_length.h b/include/linux/netfilter_ipv4/ipt_length.h
index 6e0885229615..9b45206ffcef 100644
--- a/include/linux/netfilter_ipv4/ipt_length.h
+++ b/include/linux/netfilter_ipv4/ipt_length.h
@@ -1,9 +1,7 @@
1#ifndef _IPT_LENGTH_H 1#ifndef _IPT_LENGTH_H
2#define _IPT_LENGTH_H 2#define _IPT_LENGTH_H
3 3
4struct ipt_length_info { 4#include <linux/netfilter/xt_length.h>
5 u_int16_t min, max; 5#define ipt_length_info xt_length_info
6 u_int8_t invert;
7};
8 6
9#endif /*_IPT_LENGTH_H*/ 7#endif /*_IPT_LENGTH_H*/
diff --git a/include/linux/netfilter_ipv4/ipt_limit.h b/include/linux/netfilter_ipv4/ipt_limit.h
index 256453409e21..92f5cd07bbc4 100644
--- a/include/linux/netfilter_ipv4/ipt_limit.h
+++ b/include/linux/netfilter_ipv4/ipt_limit.h
@@ -1,21 +1,8 @@
1#ifndef _IPT_RATE_H 1#ifndef _IPT_RATE_H
2#define _IPT_RATE_H 2#define _IPT_RATE_H
3 3
4/* timings are in milliseconds. */ 4#include <linux/netfilter/xt_limit.h>
5#define IPT_LIMIT_SCALE 10000 5#define IPT_LIMIT_SCALE XT_LIMIT_SCALE
6#define ipt_rateinfo xt_rateinfo
6 7
7/* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490
8 seconds, or one every 59 hours. */
9struct ipt_rateinfo {
10 u_int32_t avg; /* Average secs between packets * scale */
11 u_int32_t burst; /* Period multiplier for upper limit. */
12
13 /* Used internally by the kernel */
14 unsigned long prev;
15 u_int32_t credit;
16 u_int32_t credit_cap, cost;
17
18 /* Ugly, ugly fucker. */
19 struct ipt_rateinfo *master;
20};
21#endif /*_IPT_RATE_H*/ 8#endif /*_IPT_RATE_H*/
diff --git a/include/linux/netfilter_ipv4/ipt_mac.h b/include/linux/netfilter_ipv4/ipt_mac.h
index f8d5b8e7ccdb..b186008a3c47 100644
--- a/include/linux/netfilter_ipv4/ipt_mac.h
+++ b/include/linux/netfilter_ipv4/ipt_mac.h
@@ -1,8 +1,7 @@
1#ifndef _IPT_MAC_H 1#ifndef _IPT_MAC_H
2#define _IPT_MAC_H 2#define _IPT_MAC_H
3 3
4struct ipt_mac_info { 4#include <linux/netfilter/xt_mac.h>
5 unsigned char srcaddr[ETH_ALEN]; 5#define ipt_mac_info xt_mac_info
6 int invert; 6
7};
8#endif /*_IPT_MAC_H*/ 7#endif /*_IPT_MAC_H*/
diff --git a/include/linux/netfilter_ipv4/ipt_mark.h b/include/linux/netfilter_ipv4/ipt_mark.h
index f3952b563d4c..bfde67c61224 100644
--- a/include/linux/netfilter_ipv4/ipt_mark.h
+++ b/include/linux/netfilter_ipv4/ipt_mark.h
@@ -1,9 +1,9 @@
1#ifndef _IPT_MARK_H 1#ifndef _IPT_MARK_H
2#define _IPT_MARK_H 2#define _IPT_MARK_H
3 3
4struct ipt_mark_info { 4/* Backwards compatibility for old userspace */
5 unsigned long mark, mask; 5#include <linux/netfilter/xt_mark.h>
6 u_int8_t invert; 6
7}; 7#define ipt_mark_info xt_mark_info
8 8
9#endif /*_IPT_MARK_H*/ 9#endif /*_IPT_MARK_H*/
diff --git a/include/linux/netfilter_ipv4/ipt_physdev.h b/include/linux/netfilter_ipv4/ipt_physdev.h
index 7538c8655ec0..2400e7140f26 100644
--- a/include/linux/netfilter_ipv4/ipt_physdev.h
+++ b/include/linux/netfilter_ipv4/ipt_physdev.h
@@ -1,24 +1,17 @@
1#ifndef _IPT_PHYSDEV_H 1#ifndef _IPT_PHYSDEV_H
2#define _IPT_PHYSDEV_H 2#define _IPT_PHYSDEV_H
3 3
4#ifdef __KERNEL__ 4/* Backwards compatibility for old userspace */
5#include <linux/if.h>
6#endif
7 5
8#define IPT_PHYSDEV_OP_IN 0x01 6#include <linux/netfilter/xt_physdev.h>
9#define IPT_PHYSDEV_OP_OUT 0x02
10#define IPT_PHYSDEV_OP_BRIDGED 0x04
11#define IPT_PHYSDEV_OP_ISIN 0x08
12#define IPT_PHYSDEV_OP_ISOUT 0x10
13#define IPT_PHYSDEV_OP_MASK (0x20 - 1)
14 7
15struct ipt_physdev_info { 8#define IPT_PHYSDEV_OP_IN XT_PHYSDEV_OP_IN
16 char physindev[IFNAMSIZ]; 9#define IPT_PHYSDEV_OP_OUT XT_PHYSDEV_OP_OUT
17 char in_mask[IFNAMSIZ]; 10#define IPT_PHYSDEV_OP_BRIDGED XT_PHYSDEV_OP_BRIDGED
18 char physoutdev[IFNAMSIZ]; 11#define IPT_PHYSDEV_OP_ISIN XT_PHYSDEV_OP_ISIN
19 char out_mask[IFNAMSIZ]; 12#define IPT_PHYSDEV_OP_ISOUT XT_PHYSDEV_OP_ISOUT
20 u_int8_t invert; 13#define IPT_PHYSDEV_OP_MASK XT_PHYSDEV_OP_MASK
21 u_int8_t bitmask; 14
22}; 15#define ipt_physdev_info xt_physdev_info
23 16
24#endif /*_IPT_PHYSDEV_H*/ 17#endif /*_IPT_PHYSDEV_H*/
diff --git a/include/linux/netfilter_ipv4/ipt_pkttype.h b/include/linux/netfilter_ipv4/ipt_pkttype.h
index d53a65848683..ff1fbc949a0c 100644
--- a/include/linux/netfilter_ipv4/ipt_pkttype.h
+++ b/include/linux/netfilter_ipv4/ipt_pkttype.h
@@ -1,8 +1,7 @@
1#ifndef _IPT_PKTTYPE_H 1#ifndef _IPT_PKTTYPE_H
2#define _IPT_PKTTYPE_H 2#define _IPT_PKTTYPE_H
3 3
4struct ipt_pkttype_info { 4#include <linux/netfilter/xt_pkttype.h>
5 int pkttype; 5#define ipt_pkttype_info xt_pkttype_info
6 int invert; 6
7};
8#endif /*_IPT_PKTTYPE_H*/ 7#endif /*_IPT_PKTTYPE_H*/
diff --git a/include/linux/netfilter_ipv4/ipt_realm.h b/include/linux/netfilter_ipv4/ipt_realm.h
index a4d6698723ac..b3996eaa0188 100644
--- a/include/linux/netfilter_ipv4/ipt_realm.h
+++ b/include/linux/netfilter_ipv4/ipt_realm.h
@@ -1,10 +1,7 @@
1#ifndef _IPT_REALM_H 1#ifndef _IPT_REALM_H
2#define _IPT_REALM_H 2#define _IPT_REALM_H
3 3
4struct ipt_realm_info { 4#include <linux/netfilter/xt_realm.h>
5 u_int32_t id; 5#define ipt_realm_info xt_realm_info
6 u_int32_t mask;
7 u_int8_t invert;
8};
9 6
10#endif /* _IPT_REALM_H */ 7#endif /* _IPT_REALM_H */
diff --git a/include/linux/netfilter_ipv4/ipt_state.h b/include/linux/netfilter_ipv4/ipt_state.h
index 5df37868933d..a44a99cc28cc 100644
--- a/include/linux/netfilter_ipv4/ipt_state.h
+++ b/include/linux/netfilter_ipv4/ipt_state.h
@@ -1,13 +1,15 @@
1#ifndef _IPT_STATE_H 1#ifndef _IPT_STATE_H
2#define _IPT_STATE_H 2#define _IPT_STATE_H
3 3
4#define IPT_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1)) 4/* Backwards compatibility for old userspace */
5#define IPT_STATE_INVALID (1 << 0)
6 5
7#define IPT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1)) 6#include <linux/netfilter/xt_state.h>
7
8#define IPT_STATE_BIT XT_STATE_BIT
9#define IPT_STATE_INVALID XT_STATE_INVALID
10
11#define IPT_STATE_UNTRACKED XT_STATE_UNTRACKED
12
13#define ipt_state_info xt_state_info
8 14
9struct ipt_state_info
10{
11 unsigned int statemask;
12};
13#endif /*_IPT_STATE_H*/ 15#endif /*_IPT_STATE_H*/
diff --git a/include/linux/netfilter_ipv4/ipt_string.h b/include/linux/netfilter_ipv4/ipt_string.h
index a265f6e44eab..c26de3059903 100644
--- a/include/linux/netfilter_ipv4/ipt_string.h
+++ b/include/linux/netfilter_ipv4/ipt_string.h
@@ -1,18 +1,10 @@
1#ifndef _IPT_STRING_H 1#ifndef _IPT_STRING_H
2#define _IPT_STRING_H 2#define _IPT_STRING_H
3 3
4#define IPT_STRING_MAX_PATTERN_SIZE 128 4#include <linux/netfilter/xt_string.h>
5#define IPT_STRING_MAX_ALGO_NAME_SIZE 16
6 5
7struct ipt_string_info 6#define IPT_STRING_MAX_PATTERN_SIZE XT_STRING_MAX_PATTERN_SIZE
8{ 7#define IPT_STRING_MAX_ALGO_NAME_SIZE XT_STRING_MAX_ALGO_NAME_SIZE
9 u_int16_t from_offset; 8#define ipt_string_info xt_string_info
10 u_int16_t to_offset;
11 char algo[IPT_STRING_MAX_ALGO_NAME_SIZE];
12 char pattern[IPT_STRING_MAX_PATTERN_SIZE];
13 u_int8_t patlen;
14 u_int8_t invert;
15 struct ts_config __attribute__((aligned(8))) *config;
16};
17 9
18#endif /*_IPT_STRING_H*/ 10#endif /*_IPT_STRING_H*/
diff --git a/include/linux/netfilter_ipv4/ipt_tcpmss.h b/include/linux/netfilter_ipv4/ipt_tcpmss.h
index e2b14397f701..18bbc8e8e009 100644
--- a/include/linux/netfilter_ipv4/ipt_tcpmss.h
+++ b/include/linux/netfilter_ipv4/ipt_tcpmss.h
@@ -1,9 +1,7 @@
1#ifndef _IPT_TCPMSS_MATCH_H 1#ifndef _IPT_TCPMSS_MATCH_H
2#define _IPT_TCPMSS_MATCH_H 2#define _IPT_TCPMSS_MATCH_H
3 3
4struct ipt_tcpmss_match_info { 4#include <linux/netfilter/xt_tcpmss.h>
5 u_int16_t mss_min, mss_max; 5#define ipt_tcpmss_match_info xt_tcpmss_match_info
6 u_int8_t invert;
7};
8 6
9#endif /*_IPT_TCPMSS_MATCH_H*/ 7#endif /*_IPT_TCPMSS_MATCH_H*/
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
index c163ba31aab7..f249b574f0fa 100644
--- a/include/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/linux/netfilter_ipv6/ip6_tables.h
@@ -25,8 +25,15 @@
25#include <linux/compiler.h> 25#include <linux/compiler.h>
26#include <linux/netfilter_ipv6.h> 26#include <linux/netfilter_ipv6.h>
27 27
28#define IP6T_FUNCTION_MAXNAMELEN 30 28#include <linux/netfilter/x_tables.h>
29#define IP6T_TABLE_MAXNAMELEN 32 29
30#define IP6T_FUNCTION_MAXNAMELEN XT_FUNCTION_MAXNAMELEN
31#define IP6T_TABLE_MAXNAMELEN XT_TABLE_MAXNAMELEN
32
33#define ip6t_match xt_match
34#define ip6t_target xt_target
35#define ip6t_table xt_table
36#define ip6t_get_revision xt_get_revision
30 37
31/* Yes, Virginia, you have to zero the padding. */ 38/* Yes, Virginia, you have to zero the padding. */
32struct ip6t_ip6 { 39struct ip6t_ip6 {
@@ -104,10 +111,7 @@ struct ip6t_standard_target
104 int verdict; 111 int verdict;
105}; 112};
106 113
107struct ip6t_counters 114#define ip6t_counters xt_counters
108{
109 u_int64_t pcnt, bcnt; /* Packet and byte counters */
110};
111 115
112/* Values for "flag" field in struct ip6t_ip6 (general ip6 structure). */ 116/* Values for "flag" field in struct ip6t_ip6 (general ip6 structure). */
113#define IP6T_F_PROTO 0x01 /* Set if rule cares about upper 117#define IP6T_F_PROTO 0x01 /* Set if rule cares about upper
@@ -123,7 +127,7 @@ struct ip6t_counters
123#define IP6T_INV_SRCIP 0x08 /* Invert the sense of SRC IP. */ 127#define IP6T_INV_SRCIP 0x08 /* Invert the sense of SRC IP. */
124#define IP6T_INV_DSTIP 0x10 /* Invert the sense of DST OP. */ 128#define IP6T_INV_DSTIP 0x10 /* Invert the sense of DST OP. */
125#define IP6T_INV_FRAG 0x20 /* Invert the sense of FRAG. */ 129#define IP6T_INV_FRAG 0x20 /* Invert the sense of FRAG. */
126#define IP6T_INV_PROTO 0x40 /* Invert the sense of PROTO. */ 130#define IP6T_INV_PROTO XT_INV_PROTO
127#define IP6T_INV_MASK 0x7F /* All possible flag bits mask. */ 131#define IP6T_INV_MASK 0x7F /* All possible flag bits mask. */
128 132
129/* This structure defines each of the firewall rules. Consists of 3 133/* This structure defines each of the firewall rules. Consists of 3
@@ -145,7 +149,7 @@ struct ip6t_entry
145 unsigned int comefrom; 149 unsigned int comefrom;
146 150
147 /* Packet and byte counters. */ 151 /* Packet and byte counters. */
148 struct ip6t_counters counters; 152 struct xt_counters counters;
149 153
150 /* The matches (if any), then the target. */ 154 /* The matches (if any), then the target. */
151 unsigned char elems[0]; 155 unsigned char elems[0];
@@ -155,54 +159,41 @@ struct ip6t_entry
155 * New IP firewall options for [gs]etsockopt at the RAW IP level. 159 * New IP firewall options for [gs]etsockopt at the RAW IP level.
156 * Unlike BSD Linux inherits IP options so you don't have to use 160 * Unlike BSD Linux inherits IP options so you don't have to use
157 * a raw socket for this. Instead we check rights in the calls. */ 161 * a raw socket for this. Instead we check rights in the calls. */
158#define IP6T_BASE_CTL 64 /* base for firewall socket options */ 162#define IP6T_BASE_CTL XT_BASE_CTL
159 163
160#define IP6T_SO_SET_REPLACE (IP6T_BASE_CTL) 164#define IP6T_SO_SET_REPLACE XT_SO_SET_REPLACE
161#define IP6T_SO_SET_ADD_COUNTERS (IP6T_BASE_CTL + 1) 165#define IP6T_SO_SET_ADD_COUNTERS XT_SO_SET_ADD_COUNTERS
162#define IP6T_SO_SET_MAX IP6T_SO_SET_ADD_COUNTERS 166#define IP6T_SO_SET_MAX XT_SO_SET_MAX
163 167
164#define IP6T_SO_GET_INFO (IP6T_BASE_CTL) 168#define IP6T_SO_GET_INFO XT_SO_GET_INFO
165#define IP6T_SO_GET_ENTRIES (IP6T_BASE_CTL + 1) 169#define IP6T_SO_GET_ENTRIES XT_SO_GET_ENTRIES
166#define IP6T_SO_GET_REVISION_MATCH (IP6T_BASE_CTL + 2) 170#define IP6T_SO_GET_REVISION_MATCH XT_SO_GET_REVISION_MATCH
167#define IP6T_SO_GET_REVISION_TARGET (IP6T_BASE_CTL + 3) 171#define IP6T_SO_GET_REVISION_TARGET XT_SO_GET_REVISION_TARGET
168#define IP6T_SO_GET_MAX IP6T_SO_GET_REVISION_TARGET 172#define IP6T_SO_GET_MAX XT_SO_GET_REVISION_TARGET
169 173
170/* CONTINUE verdict for targets */ 174/* CONTINUE verdict for targets */
171#define IP6T_CONTINUE 0xFFFFFFFF 175#define IP6T_CONTINUE XT_CONTINUE
172 176
173/* For standard target */ 177/* For standard target */
174#define IP6T_RETURN (-NF_REPEAT - 1) 178#define IP6T_RETURN XT_RETURN
175 179
176/* TCP matching stuff */ 180/* TCP/UDP matching stuff */
177struct ip6t_tcp 181#include <linux/netfilter/xt_tcpudp.h>
178{ 182
179 u_int16_t spts[2]; /* Source port range. */ 183#define ip6t_tcp xt_tcp
180 u_int16_t dpts[2]; /* Destination port range. */ 184#define ip6t_udp xt_udp
181 u_int8_t option; /* TCP Option iff non-zero*/
182 u_int8_t flg_mask; /* TCP flags mask byte */
183 u_int8_t flg_cmp; /* TCP flags compare byte */
184 u_int8_t invflags; /* Inverse flags */
185};
186 185
187/* Values for "inv" field in struct ipt_tcp. */ 186/* Values for "inv" field in struct ipt_tcp. */
188#define IP6T_TCP_INV_SRCPT 0x01 /* Invert the sense of source ports. */ 187#define IP6T_TCP_INV_SRCPT XT_TCP_INV_SRCPT
189#define IP6T_TCP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */ 188#define IP6T_TCP_INV_DSTPT XT_TCP_INV_DSTPT
190#define IP6T_TCP_INV_FLAGS 0x04 /* Invert the sense of TCP flags. */ 189#define IP6T_TCP_INV_FLAGS XT_TCP_INV_FLAGS
191#define IP6T_TCP_INV_OPTION 0x08 /* Invert the sense of option test. */ 190#define IP6T_TCP_INV_OPTION XT_TCP_INV_OPTION
192#define IP6T_TCP_INV_MASK 0x0F /* All possible flags. */ 191#define IP6T_TCP_INV_MASK XT_TCP_INV_MASK
193
194/* UDP matching stuff */
195struct ip6t_udp
196{
197 u_int16_t spts[2]; /* Source port range. */
198 u_int16_t dpts[2]; /* Destination port range. */
199 u_int8_t invflags; /* Inverse flags */
200};
201 192
202/* Values for "invflags" field in struct ipt_udp. */ 193/* Values for "invflags" field in struct ipt_udp. */
203#define IP6T_UDP_INV_SRCPT 0x01 /* Invert the sense of source ports. */ 194#define IP6T_UDP_INV_SRCPT XT_UDP_INV_SRCPT
204#define IP6T_UDP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */ 195#define IP6T_UDP_INV_DSTPT XT_UDP_INV_DSTPT
205#define IP6T_UDP_INV_MASK 0x03 /* All possible flags. */ 196#define IP6T_UDP_INV_MASK XT_UDP_INV_MASK
206 197
207/* ICMP matching stuff */ 198/* ICMP matching stuff */
208struct ip6t_icmp 199struct ip6t_icmp
@@ -264,23 +255,14 @@ struct ip6t_replace
264 /* Number of counters (must be equal to current number of entries). */ 255 /* Number of counters (must be equal to current number of entries). */
265 unsigned int num_counters; 256 unsigned int num_counters;
266 /* The old entries' counters. */ 257 /* The old entries' counters. */
267 struct ip6t_counters __user *counters; 258 struct xt_counters __user *counters;
268 259
269 /* The entries (hang off end: not really an array). */ 260 /* The entries (hang off end: not really an array). */
270 struct ip6t_entry entries[0]; 261 struct ip6t_entry entries[0];
271}; 262};
272 263
273/* The argument to IP6T_SO_ADD_COUNTERS. */ 264/* The argument to IP6T_SO_ADD_COUNTERS. */
274struct ip6t_counters_info 265#define ip6t_counters_info xt_counters_info
275{
276 /* Which table. */
277 char name[IP6T_TABLE_MAXNAMELEN];
278
279 unsigned int num_counters;
280
281 /* The counters (actually `number' of these). */
282 struct ip6t_counters counters[0];
283};
284 266
285/* The argument to IP6T_SO_GET_ENTRIES. */ 267/* The argument to IP6T_SO_GET_ENTRIES. */
286struct ip6t_get_entries 268struct ip6t_get_entries
@@ -295,19 +277,10 @@ struct ip6t_get_entries
295 struct ip6t_entry entrytable[0]; 277 struct ip6t_entry entrytable[0];
296}; 278};
297 279
298/* The argument to IP6T_SO_GET_REVISION_*. Returns highest revision
299 * kernel supports, if >= revision. */
300struct ip6t_get_revision
301{
302 char name[IP6T_FUNCTION_MAXNAMELEN-1];
303
304 u_int8_t revision;
305};
306
307/* Standard return verdict, or do jump. */ 280/* Standard return verdict, or do jump. */
308#define IP6T_STANDARD_TARGET "" 281#define IP6T_STANDARD_TARGET XT_STANDARD_TARGET
309/* Error verdict. */ 282/* Error verdict. */
310#define IP6T_ERROR_TARGET "ERROR" 283#define IP6T_ERROR_TARGET XT_ERROR_TARGET
311 284
312/* Helper functions */ 285/* Helper functions */
313static __inline__ struct ip6t_entry_target * 286static __inline__ struct ip6t_entry_target *
@@ -361,104 +334,11 @@ ip6t_get_target(struct ip6t_entry *e)
361#include <linux/init.h> 334#include <linux/init.h>
362extern void ip6t_init(void) __init; 335extern void ip6t_init(void) __init;
363 336
364struct ip6t_match 337#define ip6t_register_target(tgt) xt_register_target(AF_INET6, tgt)
365{ 338#define ip6t_unregister_target(tgt) xt_unregister_target(AF_INET6, tgt)
366 struct list_head list;
367
368 const char name[IP6T_FUNCTION_MAXNAMELEN-1];
369
370 u_int8_t revision;
371
372 /* Return true or false: return FALSE and set *hotdrop = 1 to
373 force immediate packet drop. */
374 /* Arguments changed since 2.6.9, as this must now handle
375 non-linear skb, using skb_header_pointer and
376 skb_ip_make_writable. */
377 int (*match)(const struct sk_buff *skb,
378 const struct net_device *in,
379 const struct net_device *out,
380 const void *matchinfo,
381 int offset,
382 unsigned int protoff,
383 int *hotdrop);
384
385 /* Called when user tries to insert an entry of this type. */
386 /* Should return true or false. */
387 int (*checkentry)(const char *tablename,
388 const struct ip6t_ip6 *ip,
389 void *matchinfo,
390 unsigned int matchinfosize,
391 unsigned int hook_mask);
392
393 /* Called when entry of this type deleted. */
394 void (*destroy)(void *matchinfo, unsigned int matchinfosize);
395
396 /* Set this to THIS_MODULE if you are a module, otherwise NULL */
397 struct module *me;
398};
399
400/* Registration hooks for targets. */
401struct ip6t_target
402{
403 struct list_head list;
404
405 const char name[IP6T_FUNCTION_MAXNAMELEN-1];
406
407 u_int8_t revision;
408
409 /* Returns verdict. Argument order changed since 2.6.9, as this
410 must now handle non-linear skbs, using skb_copy_bits and
411 skb_ip_make_writable. */
412 unsigned int (*target)(struct sk_buff **pskb,
413 const struct net_device *in,
414 const struct net_device *out,
415 unsigned int hooknum,
416 const void *targinfo,
417 void *userdata);
418
419 /* Called when user tries to insert an entry of this type:
420 hook_mask is a bitmask of hooks from which it can be
421 called. */
422 /* Should return true or false. */
423 int (*checkentry)(const char *tablename,
424 const struct ip6t_entry *e,
425 void *targinfo,
426 unsigned int targinfosize,
427 unsigned int hook_mask);
428
429 /* Called when entry of this type deleted. */
430 void (*destroy)(void *targinfo, unsigned int targinfosize);
431
432 /* Set this to THIS_MODULE if you are a module, otherwise NULL */
433 struct module *me;
434};
435
436extern int ip6t_register_target(struct ip6t_target *target);
437extern void ip6t_unregister_target(struct ip6t_target *target);
438
439extern int ip6t_register_match(struct ip6t_match *match);
440extern void ip6t_unregister_match(struct ip6t_match *match);
441 339
442/* Furniture shopping... */ 340#define ip6t_register_match(match) xt_register_match(AF_INET6, match)
443struct ip6t_table 341#define ip6t_unregister_match(match) xt_unregister_match(AF_INET6, match)
444{
445 struct list_head list;
446
447 /* A unique name... */
448 char name[IP6T_TABLE_MAXNAMELEN];
449
450 /* What hooks you will enter on */
451 unsigned int valid_hooks;
452
453 /* Lock for the curtain */
454 rwlock_t lock;
455
456 /* Man behind the curtain... */
457 struct ip6t_table_info *private;
458
459 /* Set this to THIS_MODULE if you are a module, otherwise NULL */
460 struct module *me;
461};
462 342
463extern int ip6t_register_table(struct ip6t_table *table, 343extern int ip6t_register_table(struct ip6t_table *table,
464 const struct ip6t_replace *repl); 344 const struct ip6t_replace *repl);
diff --git a/include/linux/netfilter_ipv6/ip6t_MARK.h b/include/linux/netfilter_ipv6/ip6t_MARK.h
index 7ade8d8f5246..7cf629a8ab92 100644
--- a/include/linux/netfilter_ipv6/ip6t_MARK.h
+++ b/include/linux/netfilter_ipv6/ip6t_MARK.h
@@ -1,8 +1,9 @@
1#ifndef _IP6T_MARK_H_target 1#ifndef _IP6T_MARK_H_target
2#define _IP6T_MARK_H_target 2#define _IP6T_MARK_H_target
3 3
4struct ip6t_mark_target_info { 4/* Backwards compatibility for old userspace */
5 unsigned long mark; 5#include <linux/netfilter/xt_MARK.h>
6};
7 6
8#endif /*_IPT_MARK_H_target*/ 7#define ip6t_mark_target_info xt_mark_target_info
8
9#endif /*_IP6T_MARK_H_target*/
diff --git a/include/linux/netfilter_ipv6/ip6t_length.h b/include/linux/netfilter_ipv6/ip6t_length.h
index 7fc09f9f9d63..9e9689d03ed7 100644
--- a/include/linux/netfilter_ipv6/ip6t_length.h
+++ b/include/linux/netfilter_ipv6/ip6t_length.h
@@ -1,10 +1,8 @@
1#ifndef _IP6T_LENGTH_H 1#ifndef _IP6T_LENGTH_H
2#define _IP6T_LENGTH_H 2#define _IP6T_LENGTH_H
3 3
4struct ip6t_length_info { 4#include <linux/netfilter/xt_length.h>
5 u_int16_t min, max; 5#define ip6t_length_info xt_length_info
6 u_int8_t invert;
7};
8 6
9#endif /*_IP6T_LENGTH_H*/ 7#endif /*_IP6T_LENGTH_H*/
10 8
diff --git a/include/linux/netfilter_ipv6/ip6t_limit.h b/include/linux/netfilter_ipv6/ip6t_limit.h
index f2866e50f3b4..487e5ea342c6 100644
--- a/include/linux/netfilter_ipv6/ip6t_limit.h
+++ b/include/linux/netfilter_ipv6/ip6t_limit.h
@@ -1,21 +1,8 @@
1#ifndef _IP6T_RATE_H 1#ifndef _IP6T_RATE_H
2#define _IP6T_RATE_H 2#define _IP6T_RATE_H
3 3
4/* timings are in milliseconds. */ 4#include <linux/netfilter/xt_limit.h>
5#define IP6T_LIMIT_SCALE 10000 5#define IP6T_LIMIT_SCALE XT_LIMIT_SCALE
6#define ip6t_rateinfo xt_rateinfo
6 7
7/* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490 8#endif /*_IP6T_RATE_H*/
8 seconds, or one every 59 hours. */
9struct ip6t_rateinfo {
10 u_int32_t avg; /* Average secs between packets * scale */
11 u_int32_t burst; /* Period multiplier for upper limit. */
12
13 /* Used internally by the kernel */
14 unsigned long prev;
15 u_int32_t credit;
16 u_int32_t credit_cap, cost;
17
18 /* Ugly, ugly fucker. */
19 struct ip6t_rateinfo *master;
20};
21#endif /*_IPT_RATE_H*/
diff --git a/include/linux/netfilter_ipv6/ip6t_mac.h b/include/linux/netfilter_ipv6/ip6t_mac.h
index 87c088c21848..ac58e83e9423 100644
--- a/include/linux/netfilter_ipv6/ip6t_mac.h
+++ b/include/linux/netfilter_ipv6/ip6t_mac.h
@@ -1,8 +1,7 @@
1#ifndef _IP6T_MAC_H 1#ifndef _IP6T_MAC_H
2#define _IP6T_MAC_H 2#define _IP6T_MAC_H
3 3
4struct ip6t_mac_info { 4#include <linux/netfilter/xt_mac.h>
5 unsigned char srcaddr[ETH_ALEN]; 5#define ip6t_mac_info xt_mac_info
6 int invert; 6
7}; 7#endif /*_IP6T_MAC_H*/
8#endif /*_IPT_MAC_H*/
diff --git a/include/linux/netfilter_ipv6/ip6t_mark.h b/include/linux/netfilter_ipv6/ip6t_mark.h
index a734441e1c19..ff204951ddc3 100644
--- a/include/linux/netfilter_ipv6/ip6t_mark.h
+++ b/include/linux/netfilter_ipv6/ip6t_mark.h
@@ -1,9 +1,9 @@
1#ifndef _IP6T_MARK_H 1#ifndef _IP6T_MARK_H
2#define _IP6T_MARK_H 2#define _IP6T_MARK_H
3 3
4struct ip6t_mark_info { 4/* Backwards compatibility for old userspace */
5 unsigned long mark, mask; 5#include <linux/netfilter/xt_mark.h>
6 u_int8_t invert; 6
7}; 7#define ip6t_mark_info xt_mark_info
8 8
9#endif /*_IPT_MARK_H*/ 9#endif /*_IPT_MARK_H*/
diff --git a/include/linux/netfilter_ipv6/ip6t_physdev.h b/include/linux/netfilter_ipv6/ip6t_physdev.h
index c234731cd66b..c161c0a81b55 100644
--- a/include/linux/netfilter_ipv6/ip6t_physdev.h
+++ b/include/linux/netfilter_ipv6/ip6t_physdev.h
@@ -1,24 +1,17 @@
1#ifndef _IP6T_PHYSDEV_H 1#ifndef _IP6T_PHYSDEV_H
2#define _IP6T_PHYSDEV_H 2#define _IP6T_PHYSDEV_H
3 3
4#ifdef __KERNEL__ 4/* Backwards compatibility for old userspace */
5#include <linux/if.h>
6#endif
7 5
8#define IP6T_PHYSDEV_OP_IN 0x01 6#include <linux/netfilter/xt_physdev.h>
9#define IP6T_PHYSDEV_OP_OUT 0x02
10#define IP6T_PHYSDEV_OP_BRIDGED 0x04
11#define IP6T_PHYSDEV_OP_ISIN 0x08
12#define IP6T_PHYSDEV_OP_ISOUT 0x10
13#define IP6T_PHYSDEV_OP_MASK (0x20 - 1)
14 7
15struct ip6t_physdev_info { 8#define IP6T_PHYSDEV_OP_IN XT_PHYSDEV_OP_IN
16 char physindev[IFNAMSIZ]; 9#define IP6T_PHYSDEV_OP_OUT XT_PHYSDEV_OP_OUT
17 char in_mask[IFNAMSIZ]; 10#define IP6T_PHYSDEV_OP_BRIDGED XT_PHYSDEV_OP_BRIDGED
18 char physoutdev[IFNAMSIZ]; 11#define IP6T_PHYSDEV_OP_ISIN XT_PHYSDEV_OP_ISIN
19 char out_mask[IFNAMSIZ]; 12#define IP6T_PHYSDEV_OP_ISOUT XT_PHYSDEV_OP_ISOUT
20 u_int8_t invert; 13#define IP6T_PHYSDEV_OP_MASK XT_PHYSDEV_OP_MASK
21 u_int8_t bitmask; 14
22}; 15#define ip6t_physdev_info xt_physdev_info
23 16
24#endif /*_IP6T_PHYSDEV_H*/ 17#endif /*_IP6T_PHYSDEV_H*/
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 7fb397e3f2d3..5403257ae3e7 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -181,6 +181,7 @@
181#define PCI_DEVICE_ID_LSI_FC929X 0x0626 181#define PCI_DEVICE_ID_LSI_FC929X 0x0626
182#define PCI_DEVICE_ID_LSI_FC939X 0x0642 182#define PCI_DEVICE_ID_LSI_FC939X 0x0642
183#define PCI_DEVICE_ID_LSI_FC949X 0x0640 183#define PCI_DEVICE_ID_LSI_FC949X 0x0640
184#define PCI_DEVICE_ID_LSI_FC949ES 0x0646
184#define PCI_DEVICE_ID_LSI_FC919X 0x0628 185#define PCI_DEVICE_ID_LSI_FC919X 0x0628
185#define PCI_DEVICE_ID_NCR_YELLOWFIN 0x0701 186#define PCI_DEVICE_ID_NCR_YELLOWFIN 0x0701
186#define PCI_DEVICE_ID_LSI_61C102 0x0901 187#define PCI_DEVICE_ID_LSI_61C102 0x0901
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 74488e49166d..aa6322d45198 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -146,6 +146,11 @@ struct property;
146extern void proc_device_tree_init(void); 146extern void proc_device_tree_init(void);
147extern void proc_device_tree_add_node(struct device_node *, struct proc_dir_entry *); 147extern void proc_device_tree_add_node(struct device_node *, struct proc_dir_entry *);
148extern void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop); 148extern void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop);
149extern void proc_device_tree_remove_prop(struct proc_dir_entry *pde,
150 struct property *prop);
151extern void proc_device_tree_update_prop(struct proc_dir_entry *pde,
152 struct property *newprop,
153 struct property *oldprop);
149#endif /* CONFIG_PROC_DEVICETREE */ 154#endif /* CONFIG_PROC_DEVICETREE */
150 155
151extern struct proc_dir_entry *proc_symlink(const char *, 156extern struct proc_dir_entry *proc_symlink(const char *,
diff --git a/include/linux/raid_class.h b/include/linux/raid_class.h
index 48831eac2910..d0dd38b3a2fd 100644
--- a/include/linux/raid_class.h
+++ b/include/linux/raid_class.h
@@ -31,9 +31,11 @@ enum raid_level {
31 RAID_LEVEL_LINEAR, 31 RAID_LEVEL_LINEAR,
32 RAID_LEVEL_0, 32 RAID_LEVEL_0,
33 RAID_LEVEL_1, 33 RAID_LEVEL_1,
34 RAID_LEVEL_10,
34 RAID_LEVEL_3, 35 RAID_LEVEL_3,
35 RAID_LEVEL_4, 36 RAID_LEVEL_4,
36 RAID_LEVEL_5, 37 RAID_LEVEL_5,
38 RAID_LEVEL_50,
37 RAID_LEVEL_6, 39 RAID_LEVEL_6,
38}; 40};
39 41
diff --git a/include/linux/sched.h b/include/linux/sched.h
index a72e17135421..2df1a1a2fee5 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -160,6 +160,7 @@ extern unsigned long nr_iowait(void);
160#define SCHED_NORMAL 0 160#define SCHED_NORMAL 0
161#define SCHED_FIFO 1 161#define SCHED_FIFO 1
162#define SCHED_RR 2 162#define SCHED_RR 2
163#define SCHED_BATCH 3
163 164
164struct sched_param { 165struct sched_param {
165 int sched_priority; 166 int sched_priority;
@@ -470,9 +471,9 @@ struct signal_struct {
470 471
471/* 472/*
472 * Priority of a process goes from 0..MAX_PRIO-1, valid RT 473 * Priority of a process goes from 0..MAX_PRIO-1, valid RT
473 * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL tasks are 474 * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH
474 * in the range MAX_RT_PRIO..MAX_PRIO-1. Priority values 475 * tasks are in the range MAX_RT_PRIO..MAX_PRIO-1. Priority
475 * are inverted: lower p->prio value means higher priority. 476 * values are inverted: lower p->prio value means higher priority.
476 * 477 *
477 * The MAX_USER_RT_PRIO value allows the actual maximum 478 * The MAX_USER_RT_PRIO value allows the actual maximum
478 * RT priority to be separate from the value exported to 479 * RT priority to be separate from the value exported to
diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
index c3e598276e78..c057f0b32318 100644
--- a/include/linux/shmem_fs.h
+++ b/include/linux/shmem_fs.h
@@ -26,6 +26,8 @@ struct shmem_sb_info {
26 unsigned long free_blocks; /* How many are left for allocation */ 26 unsigned long free_blocks; /* How many are left for allocation */
27 unsigned long max_inodes; /* How many inodes are allowed */ 27 unsigned long max_inodes; /* How many inodes are allowed */
28 unsigned long free_inodes; /* How many are left for allocation */ 28 unsigned long free_inodes; /* How many are left for allocation */
29 int policy; /* Default NUMA memory alloc policy */
30 nodemask_t policy_nodes; /* nodemask for preferred and bind */
29 spinlock_t stat_lock; 31 spinlock_t stat_lock;
30}; 32};
31 33
diff --git a/include/linux/smb_fs.h b/include/linux/smb_fs.h
index c4153120ade6..621a3d3662f3 100644
--- a/include/linux/smb_fs.h
+++ b/include/linux/smb_fs.h
@@ -58,53 +58,6 @@ static inline struct smb_inode_info *SMB_I(struct inode *inode)
58/* where to find the base of the SMB packet proper */ 58/* where to find the base of the SMB packet proper */
59#define smb_base(buf) ((u8 *)(((u8 *)(buf))+4)) 59#define smb_base(buf) ((u8 *)(((u8 *)(buf))+4))
60 60
61#ifdef DEBUG_SMB_MALLOC
62
63#include <linux/slab.h>
64
65extern int smb_malloced;
66extern int smb_current_vmalloced;
67extern int smb_current_kmalloced;
68
69static inline void *
70smb_vmalloc(unsigned int size)
71{
72 smb_malloced += 1;
73 smb_current_vmalloced += 1;
74 return vmalloc(size);
75}
76
77static inline void
78smb_vfree(void *obj)
79{
80 smb_current_vmalloced -= 1;
81 vfree(obj);
82}
83
84static inline void *
85smb_kmalloc(size_t size, int flags)
86{
87 smb_malloced += 1;
88 smb_current_kmalloced += 1;
89 return kmalloc(size, flags);
90}
91
92static inline void
93smb_kfree(void *obj)
94{
95 smb_current_kmalloced -= 1;
96 kfree(obj);
97}
98
99#else /* DEBUG_SMB_MALLOC */
100
101#define smb_kmalloc(s,p) kmalloc(s,p)
102#define smb_kfree(o) kfree(o)
103#define smb_vmalloc(s) vmalloc(s)
104#define smb_vfree(o) vfree(o)
105
106#endif /* DEBUG_SMB_MALLOC */
107
108/* 61/*
109 * Flags for the in-memory inode 62 * Flags for the in-memory inode
110 */ 63 */
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 9f4019156fd8..b02dda4ee83d 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -186,6 +186,7 @@ struct ucred {
186#define AF_PPPOX 24 /* PPPoX sockets */ 186#define AF_PPPOX 24 /* PPPoX sockets */
187#define AF_WANPIPE 25 /* Wanpipe API Sockets */ 187#define AF_WANPIPE 25 /* Wanpipe API Sockets */
188#define AF_LLC 26 /* Linux LLC */ 188#define AF_LLC 26 /* Linux LLC */
189#define AF_TIPC 30 /* TIPC sockets */
189#define AF_BLUETOOTH 31 /* Bluetooth sockets */ 190#define AF_BLUETOOTH 31 /* Bluetooth sockets */
190#define AF_MAX 32 /* For now.. */ 191#define AF_MAX 32 /* For now.. */
191 192
@@ -218,6 +219,7 @@ struct ucred {
218#define PF_PPPOX AF_PPPOX 219#define PF_PPPOX AF_PPPOX
219#define PF_WANPIPE AF_WANPIPE 220#define PF_WANPIPE AF_WANPIPE
220#define PF_LLC AF_LLC 221#define PF_LLC AF_LLC
222#define PF_TIPC AF_TIPC
221#define PF_BLUETOOTH AF_BLUETOOTH 223#define PF_BLUETOOTH AF_BLUETOOTH
222#define PF_MAX AF_MAX 224#define PF_MAX AF_MAX
223 225
@@ -279,6 +281,7 @@ struct ucred {
279#define SOL_LLC 268 281#define SOL_LLC 268
280#define SOL_DCCP 269 282#define SOL_DCCP 269
281#define SOL_NETLINK 270 283#define SOL_NETLINK 270
284#define SOL_TIPC 271
282 285
283/* IPX options */ 286/* IPX options */
284#define IPX_TYPE 1 287#define IPX_TYPE 1
diff --git a/include/linux/spi/ads7846.h b/include/linux/spi/ads7846.h
new file mode 100644
index 000000000000..72261e0f2ac1
--- /dev/null
+++ b/include/linux/spi/ads7846.h
@@ -0,0 +1,18 @@
1/* linux/spi/ads7846.h */
2
3/* Touchscreen characteristics vary between boards and models. The
4 * platform_data for the device's "struct device" holds this information.
5 *
6 * It's OK if the min/max values are zero.
7 */
8struct ads7846_platform_data {
9 u16 model; /* 7843, 7845, 7846. */
10 u16 vref_delay_usecs; /* 0 for external vref; etc */
11 u16 x_plate_ohms;
12 u16 y_plate_ohms;
13
14 u16 x_min, x_max;
15 u16 y_min, y_max;
16 u16 pressure_min, pressure_max;
17};
18
diff --git a/include/linux/spi/flash.h b/include/linux/spi/flash.h
new file mode 100644
index 000000000000..3f22932e67a4
--- /dev/null
+++ b/include/linux/spi/flash.h
@@ -0,0 +1,31 @@
1#ifndef LINUX_SPI_FLASH_H
2#define LINUX_SPI_FLASH_H
3
4struct mtd_partition;
5
6/**
7 * struct flash_platform_data: board-specific flash data
8 * @name: optional flash device name (eg, as used with mtdparts=)
9 * @parts: optional array of mtd_partitions for static partitioning
10 * @nr_parts: number of mtd_partitions for static partitoning
11 * @type: optional flash device type (e.g. m25p80 vs m25p64), for use
12 * with chips that can't be queried for JEDEC or other IDs
13 *
14 * Board init code (in arch/.../mach-xxx/board-yyy.c files) can
15 * provide information about SPI flash parts (such as DataFlash) to
16 * help set up the device and its appropriate default partitioning.
17 *
18 * Note that for DataFlash, sizes for pages, blocks, and sectors are
19 * rarely powers of two; and partitions should be sector-aligned.
20 */
21struct flash_platform_data {
22 char *name;
23 struct mtd_partition *parts;
24 unsigned int nr_parts;
25
26 char *type;
27
28 /* we'll likely add more ... use JEDEC IDs, etc */
29};
30
31#endif
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
new file mode 100644
index 000000000000..b05f1463a267
--- /dev/null
+++ b/include/linux/spi/spi.h
@@ -0,0 +1,668 @@
1/*
2 * Copyright (C) 2005 David Brownell
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19#ifndef __LINUX_SPI_H
20#define __LINUX_SPI_H
21
22/*
23 * INTERFACES between SPI master-side drivers and SPI infrastructure.
24 * (There's no SPI slave support for Linux yet...)
25 */
26extern struct bus_type spi_bus_type;
27
28/**
29 * struct spi_device - Master side proxy for an SPI slave device
30 * @dev: Driver model representation of the device.
31 * @master: SPI controller used with the device.
32 * @max_speed_hz: Maximum clock rate to be used with this chip
33 * (on this board); may be changed by the device's driver.
34 * @chip-select: Chipselect, distinguishing chips handled by "master".
35 * @mode: The spi mode defines how data is clocked out and in.
36 * This may be changed by the device's driver.
37 * @bits_per_word: Data transfers involve one or more words; word sizes
38 * like eight or 12 bits are common. In-memory wordsizes are
39 * powers of two bytes (e.g. 20 bit samples use 32 bits).
40 * This may be changed by the device's driver.
41 * @irq: Negative, or the number passed to request_irq() to receive
42 * interrupts from this device.
43 * @controller_state: Controller's runtime state
44 * @controller_data: Board-specific definitions for controller, such as
45 * FIFO initialization parameters; from board_info.controller_data
46 *
47 * An spi_device is used to interchange data between an SPI slave
48 * (usually a discrete chip) and CPU memory.
49 *
50 * In "dev", the platform_data is used to hold information about this
51 * device that's meaningful to the device's protocol driver, but not
52 * to its controller. One example might be an identifier for a chip
53 * variant with slightly different functionality.
54 */
55struct spi_device {
56 struct device dev;
57 struct spi_master *master;
58 u32 max_speed_hz;
59 u8 chip_select;
60 u8 mode;
61#define SPI_CPHA 0x01 /* clock phase */
62#define SPI_CPOL 0x02 /* clock polarity */
63#define SPI_MODE_0 (0|0) /* (original MicroWire) */
64#define SPI_MODE_1 (0|SPI_CPHA)
65#define SPI_MODE_2 (SPI_CPOL|0)
66#define SPI_MODE_3 (SPI_CPOL|SPI_CPHA)
67#define SPI_CS_HIGH 0x04 /* chipselect active high? */
68 u8 bits_per_word;
69 int irq;
70 void *controller_state;
71 void *controller_data;
72 const char *modalias;
73
74 // likely need more hooks for more protocol options affecting how
75 // the controller talks to each chip, like:
76 // - bit order (default is wordwise msb-first)
77 // - memory packing (12 bit samples into low bits, others zeroed)
78 // - priority
79 // - drop chipselect after each word
80 // - chipselect delays
81 // - ...
82};
83
84static inline struct spi_device *to_spi_device(struct device *dev)
85{
86 return dev ? container_of(dev, struct spi_device, dev) : NULL;
87}
88
89/* most drivers won't need to care about device refcounting */
90static inline struct spi_device *spi_dev_get(struct spi_device *spi)
91{
92 return (spi && get_device(&spi->dev)) ? spi : NULL;
93}
94
95static inline void spi_dev_put(struct spi_device *spi)
96{
97 if (spi)
98 put_device(&spi->dev);
99}
100
101/* ctldata is for the bus_master driver's runtime state */
102static inline void *spi_get_ctldata(struct spi_device *spi)
103{
104 return spi->controller_state;
105}
106
107static inline void spi_set_ctldata(struct spi_device *spi, void *state)
108{
109 spi->controller_state = state;
110}
111
112
113struct spi_message;
114
115
116
117struct spi_driver {
118 int (*probe)(struct spi_device *spi);
119 int (*remove)(struct spi_device *spi);
120 void (*shutdown)(struct spi_device *spi);
121 int (*suspend)(struct spi_device *spi, pm_message_t mesg);
122 int (*resume)(struct spi_device *spi);
123 struct device_driver driver;
124};
125
126static inline struct spi_driver *to_spi_driver(struct device_driver *drv)
127{
128 return drv ? container_of(drv, struct spi_driver, driver) : NULL;
129}
130
131extern int spi_register_driver(struct spi_driver *sdrv);
132
133static inline void spi_unregister_driver(struct spi_driver *sdrv)
134{
135 if (!sdrv)
136 return;
137 driver_unregister(&sdrv->driver);
138}
139
140
141
142/**
143 * struct spi_master - interface to SPI master controller
144 * @cdev: class interface to this driver
145 * @bus_num: board-specific (and often SOC-specific) identifier for a
146 * given SPI controller.
147 * @num_chipselect: chipselects are used to distinguish individual
148 * SPI slaves, and are numbered from zero to num_chipselects.
149 * each slave has a chipselect signal, but it's common that not
150 * every chipselect is connected to a slave.
151 * @setup: updates the device mode and clocking records used by a
152 * device's SPI controller; protocol code may call this.
153 * @transfer: adds a message to the controller's transfer queue.
154 * @cleanup: frees controller-specific state
155 *
156 * Each SPI master controller can communicate with one or more spi_device
157 * children. These make a small bus, sharing MOSI, MISO and SCK signals
158 * but not chip select signals. Each device may be configured to use a
159 * different clock rate, since those shared signals are ignored unless
160 * the chip is selected.
161 *
162 * The driver for an SPI controller manages access to those devices through
163 * a queue of spi_message transactions, copyin data between CPU memory and
164 * an SPI slave device). For each such message it queues, it calls the
165 * message's completion function when the transaction completes.
166 */
167struct spi_master {
168 struct class_device cdev;
169
170 /* other than zero (== assign one dynamically), bus_num is fully
171 * board-specific. usually that simplifies to being SOC-specific.
172 * example: one SOC has three SPI controllers, numbered 1..3,
173 * and one board's schematics might show it using SPI-2. software
174 * would normally use bus_num=2 for that controller.
175 */
176 u16 bus_num;
177
178 /* chipselects will be integral to many controllers; some others
179 * might use board-specific GPIOs.
180 */
181 u16 num_chipselect;
182
183 /* setup mode and clock, etc (spi driver may call many times) */
184 int (*setup)(struct spi_device *spi);
185
186 /* bidirectional bulk transfers
187 *
188 * + The transfer() method may not sleep; its main role is
189 * just to add the message to the queue.
190 * + For now there's no remove-from-queue operation, or
191 * any other request management
192 * + To a given spi_device, message queueing is pure fifo
193 *
194 * + The master's main job is to process its message queue,
195 * selecting a chip then transferring data
196 * + If there are multiple spi_device children, the i/o queue
197 * arbitration algorithm is unspecified (round robin, fifo,
198 * priority, reservations, preemption, etc)
199 *
200 * + Chipselect stays active during the entire message
201 * (unless modified by spi_transfer.cs_change != 0).
202 * + The message transfers use clock and SPI mode parameters
203 * previously established by setup() for this device
204 */
205 int (*transfer)(struct spi_device *spi,
206 struct spi_message *mesg);
207
208 /* called on release() to free memory provided by spi_master */
209 void (*cleanup)(const struct spi_device *spi);
210};
211
212static inline void *spi_master_get_devdata(struct spi_master *master)
213{
214 return class_get_devdata(&master->cdev);
215}
216
217static inline void spi_master_set_devdata(struct spi_master *master, void *data)
218{
219 class_set_devdata(&master->cdev, data);
220}
221
222static inline struct spi_master *spi_master_get(struct spi_master *master)
223{
224 if (!master || !class_device_get(&master->cdev))
225 return NULL;
226 return master;
227}
228
229static inline void spi_master_put(struct spi_master *master)
230{
231 if (master)
232 class_device_put(&master->cdev);
233}
234
235
236/* the spi driver core manages memory for the spi_master classdev */
237extern struct spi_master *
238spi_alloc_master(struct device *host, unsigned size);
239
240extern int spi_register_master(struct spi_master *master);
241extern void spi_unregister_master(struct spi_master *master);
242
243extern struct spi_master *spi_busnum_to_master(u16 busnum);
244
245/*---------------------------------------------------------------------------*/
246
247/*
248 * I/O INTERFACE between SPI controller and protocol drivers
249 *
250 * Protocol drivers use a queue of spi_messages, each transferring data
251 * between the controller and memory buffers.
252 *
253 * The spi_messages themselves consist of a series of read+write transfer
254 * segments. Those segments always read the same number of bits as they
255 * write; but one or the other is easily ignored by passing a null buffer
256 * pointer. (This is unlike most types of I/O API, because SPI hardware
257 * is full duplex.)
258 *
259 * NOTE: Allocation of spi_transfer and spi_message memory is entirely
260 * up to the protocol driver, which guarantees the integrity of both (as
261 * well as the data buffers) for as long as the message is queued.
262 */
263
264/**
265 * struct spi_transfer - a read/write buffer pair
266 * @tx_buf: data to be written (dma-safe memory), or NULL
267 * @rx_buf: data to be read (dma-safe memory), or NULL
268 * @tx_dma: DMA address of tx_buf, if spi_message.is_dma_mapped
269 * @rx_dma: DMA address of rx_buf, if spi_message.is_dma_mapped
270 * @len: size of rx and tx buffers (in bytes)
271 * @cs_change: affects chipselect after this transfer completes
272 * @delay_usecs: microseconds to delay after this transfer before
273 * (optionally) changing the chipselect status, then starting
274 * the next transfer or completing this spi_message.
275 * @transfer_list: transfers are sequenced through spi_message.transfers
276 *
277 * SPI transfers always write the same number of bytes as they read.
278 * Protocol drivers should always provide rx_buf and/or tx_buf.
279 * In some cases, they may also want to provide DMA addresses for
280 * the data being transferred; that may reduce overhead, when the
281 * underlying driver uses dma.
282 *
283 * If the transmit buffer is null, undefined data will be shifted out
284 * while filling rx_buf. If the receive buffer is null, the data
285 * shifted in will be discarded. Only "len" bytes shift out (or in).
286 * It's an error to try to shift out a partial word. (For example, by
287 * shifting out three bytes with word size of sixteen or twenty bits;
288 * the former uses two bytes per word, the latter uses four bytes.)
289 *
290 * All SPI transfers start with the relevant chipselect active. Normally
291 * it stays selected until after the last transfer in a message. Drivers
292 * can affect the chipselect signal using cs_change:
293 *
294 * (i) If the transfer isn't the last one in the message, this flag is
295 * used to make the chipselect briefly go inactive in the middle of the
296 * message. Toggling chipselect in this way may be needed to terminate
297 * a chip command, letting a single spi_message perform all of group of
298 * chip transactions together.
299 *
300 * (ii) When the transfer is the last one in the message, the chip may
301 * stay selected until the next transfer. This is purely a performance
302 * hint; the controller driver may need to select a different device
303 * for the next message.
304 *
305 * The code that submits an spi_message (and its spi_transfers)
306 * to the lower layers is responsible for managing its memory.
307 * Zero-initialize every field you don't set up explicitly, to
308 * insulate against future API updates. After you submit a message
309 * and its transfers, ignore them until its completion callback.
310 */
311struct spi_transfer {
312 /* it's ok if tx_buf == rx_buf (right?)
313 * for MicroWire, one buffer must be null
314 * buffers must work with dma_*map_single() calls, unless
315 * spi_message.is_dma_mapped reports a pre-existing mapping
316 */
317 const void *tx_buf;
318 void *rx_buf;
319 unsigned len;
320
321 dma_addr_t tx_dma;
322 dma_addr_t rx_dma;
323
324 unsigned cs_change:1;
325 u16 delay_usecs;
326
327 struct list_head transfer_list;
328};
329
330/**
331 * struct spi_message - one multi-segment SPI transaction
332 * @transfers: list of transfer segments in this transaction
333 * @spi: SPI device to which the transaction is queued
334 * @is_dma_mapped: if true, the caller provided both dma and cpu virtual
335 * addresses for each transfer buffer
336 * @complete: called to report transaction completions
337 * @context: the argument to complete() when it's called
338 * @actual_length: the total number of bytes that were transferred in all
339 * successful segments
340 * @status: zero for success, else negative errno
341 * @queue: for use by whichever driver currently owns the message
342 * @state: for use by whichever driver currently owns the message
343 *
344 * An spi_message is used to execute an atomic sequence of data transfers,
345 * each represented by a struct spi_transfer. The sequence is "atomic"
346 * in the sense that no other spi_message may use that SPI bus until that
347 * sequence completes. On some systems, many such sequences can execute as
348 * as single programmed DMA transfer. On all systems, these messages are
349 * queued, and might complete after transactions to other devices. Messages
350 * sent to a given spi_device are alway executed in FIFO order.
351 *
352 * The code that submits an spi_message (and its spi_transfers)
353 * to the lower layers is responsible for managing its memory.
354 * Zero-initialize every field you don't set up explicitly, to
355 * insulate against future API updates. After you submit a message
356 * and its transfers, ignore them until its completion callback.
357 */
358struct spi_message {
359 struct list_head transfers;
360
361 struct spi_device *spi;
362
363 unsigned is_dma_mapped:1;
364
365 /* REVISIT: we might want a flag affecting the behavior of the
366 * last transfer ... allowing things like "read 16 bit length L"
367 * immediately followed by "read L bytes". Basically imposing
368 * a specific message scheduling algorithm.
369 *
370 * Some controller drivers (message-at-a-time queue processing)
371 * could provide that as their default scheduling algorithm. But
372 * others (with multi-message pipelines) could need a flag to
373 * tell them about such special cases.
374 */
375
376 /* completion is reported through a callback */
377 void (*complete)(void *context);
378 void *context;
379 unsigned actual_length;
380 int status;
381
382 /* for optional use by whatever driver currently owns the
383 * spi_message ... between calls to spi_async and then later
384 * complete(), that's the spi_master controller driver.
385 */
386 struct list_head queue;
387 void *state;
388};
389
390static inline void spi_message_init(struct spi_message *m)
391{
392 memset(m, 0, sizeof *m);
393 INIT_LIST_HEAD(&m->transfers);
394}
395
396static inline void
397spi_message_add_tail(struct spi_transfer *t, struct spi_message *m)
398{
399 list_add_tail(&t->transfer_list, &m->transfers);
400}
401
402static inline void
403spi_transfer_del(struct spi_transfer *t)
404{
405 list_del(&t->transfer_list);
406}
407
408/* It's fine to embed message and transaction structures in other data
409 * structures so long as you don't free them while they're in use.
410 */
411
412static inline struct spi_message *spi_message_alloc(unsigned ntrans, gfp_t flags)
413{
414 struct spi_message *m;
415
416 m = kzalloc(sizeof(struct spi_message)
417 + ntrans * sizeof(struct spi_transfer),
418 flags);
419 if (m) {
420 int i;
421 struct spi_transfer *t = (struct spi_transfer *)(m + 1);
422
423 INIT_LIST_HEAD(&m->transfers);
424 for (i = 0; i < ntrans; i++, t++)
425 spi_message_add_tail(t, m);
426 }
427 return m;
428}
429
430static inline void spi_message_free(struct spi_message *m)
431{
432 kfree(m);
433}
434
435/**
436 * spi_setup -- setup SPI mode and clock rate
437 * @spi: the device whose settings are being modified
438 *
439 * SPI protocol drivers may need to update the transfer mode if the
440 * device doesn't work with the mode 0 default. They may likewise need
441 * to update clock rates or word sizes from initial values. This function
442 * changes those settings, and must be called from a context that can sleep.
443 * The changes take effect the next time the device is selected and data
444 * is transferred to or from it.
445 */
446static inline int
447spi_setup(struct spi_device *spi)
448{
449 return spi->master->setup(spi);
450}
451
452
453/**
454 * spi_async -- asynchronous SPI transfer
455 * @spi: device with which data will be exchanged
456 * @message: describes the data transfers, including completion callback
457 *
458 * This call may be used in_irq and other contexts which can't sleep,
459 * as well as from task contexts which can sleep.
460 *
461 * The completion callback is invoked in a context which can't sleep.
462 * Before that invocation, the value of message->status is undefined.
463 * When the callback is issued, message->status holds either zero (to
464 * indicate complete success) or a negative error code. After that
465 * callback returns, the driver which issued the transfer request may
466 * deallocate the associated memory; it's no longer in use by any SPI
467 * core or controller driver code.
468 *
469 * Note that although all messages to a spi_device are handled in
470 * FIFO order, messages may go to different devices in other orders.
471 * Some device might be higher priority, or have various "hard" access
472 * time requirements, for example.
473 *
474 * On detection of any fault during the transfer, processing of
475 * the entire message is aborted, and the device is deselected.
476 * Until returning from the associated message completion callback,
477 * no other spi_message queued to that device will be processed.
478 * (This rule applies equally to all the synchronous transfer calls,
479 * which are wrappers around this core asynchronous primitive.)
480 */
481static inline int
482spi_async(struct spi_device *spi, struct spi_message *message)
483{
484 message->spi = spi;
485 return spi->master->transfer(spi, message);
486}
487
488/*---------------------------------------------------------------------------*/
489
490/* All these synchronous SPI transfer routines are utilities layered
491 * over the core async transfer primitive. Here, "synchronous" means
492 * they will sleep uninterruptibly until the async transfer completes.
493 */
494
495extern int spi_sync(struct spi_device *spi, struct spi_message *message);
496
497/**
498 * spi_write - SPI synchronous write
499 * @spi: device to which data will be written
500 * @buf: data buffer
501 * @len: data buffer size
502 *
503 * This writes the buffer and returns zero or a negative error code.
504 * Callable only from contexts that can sleep.
505 */
506static inline int
507spi_write(struct spi_device *spi, const u8 *buf, size_t len)
508{
509 struct spi_transfer t = {
510 .tx_buf = buf,
511 .len = len,
512 };
513 struct spi_message m;
514
515 spi_message_init(&m);
516 spi_message_add_tail(&t, &m);
517 return spi_sync(spi, &m);
518}
519
520/**
521 * spi_read - SPI synchronous read
522 * @spi: device from which data will be read
523 * @buf: data buffer
524 * @len: data buffer size
525 *
526 * This writes the buffer and returns zero or a negative error code.
527 * Callable only from contexts that can sleep.
528 */
529static inline int
530spi_read(struct spi_device *spi, u8 *buf, size_t len)
531{
532 struct spi_transfer t = {
533 .rx_buf = buf,
534 .len = len,
535 };
536 struct spi_message m;
537
538 spi_message_init(&m);
539 spi_message_add_tail(&t, &m);
540 return spi_sync(spi, &m);
541}
542
543/* this copies txbuf and rxbuf data; for small transfers only! */
544extern int spi_write_then_read(struct spi_device *spi,
545 const u8 *txbuf, unsigned n_tx,
546 u8 *rxbuf, unsigned n_rx);
547
548/**
549 * spi_w8r8 - SPI synchronous 8 bit write followed by 8 bit read
550 * @spi: device with which data will be exchanged
551 * @cmd: command to be written before data is read back
552 *
553 * This returns the (unsigned) eight bit number returned by the
554 * device, or else a negative error code. Callable only from
555 * contexts that can sleep.
556 */
557static inline ssize_t spi_w8r8(struct spi_device *spi, u8 cmd)
558{
559 ssize_t status;
560 u8 result;
561
562 status = spi_write_then_read(spi, &cmd, 1, &result, 1);
563
564 /* return negative errno or unsigned value */
565 return (status < 0) ? status : result;
566}
567
568/**
569 * spi_w8r16 - SPI synchronous 8 bit write followed by 16 bit read
570 * @spi: device with which data will be exchanged
571 * @cmd: command to be written before data is read back
572 *
573 * This returns the (unsigned) sixteen bit number returned by the
574 * device, or else a negative error code. Callable only from
575 * contexts that can sleep.
576 *
577 * The number is returned in wire-order, which is at least sometimes
578 * big-endian.
579 */
580static inline ssize_t spi_w8r16(struct spi_device *spi, u8 cmd)
581{
582 ssize_t status;
583 u16 result;
584
585 status = spi_write_then_read(spi, &cmd, 1, (u8 *) &result, 2);
586
587 /* return negative errno or unsigned value */
588 return (status < 0) ? status : result;
589}
590
591/*---------------------------------------------------------------------------*/
592
593/*
594 * INTERFACE between board init code and SPI infrastructure.
595 *
596 * No SPI driver ever sees these SPI device table segments, but
597 * it's how the SPI core (or adapters that get hotplugged) grows
598 * the driver model tree.
599 *
600 * As a rule, SPI devices can't be probed. Instead, board init code
601 * provides a table listing the devices which are present, with enough
602 * information to bind and set up the device's driver. There's basic
603 * support for nonstatic configurations too; enough to handle adding
604 * parport adapters, or microcontrollers acting as USB-to-SPI bridges.
605 */
606
607/* board-specific information about each SPI device */
608struct spi_board_info {
609 /* the device name and module name are coupled, like platform_bus;
610 * "modalias" is normally the driver name.
611 *
612 * platform_data goes to spi_device.dev.platform_data,
613 * controller_data goes to spi_device.controller_data,
614 * irq is copied too
615 */
616 char modalias[KOBJ_NAME_LEN];
617 const void *platform_data;
618 void *controller_data;
619 int irq;
620
621 /* slower signaling on noisy or low voltage boards */
622 u32 max_speed_hz;
623
624
625 /* bus_num is board specific and matches the bus_num of some
626 * spi_master that will probably be registered later.
627 *
628 * chip_select reflects how this chip is wired to that master;
629 * it's less than num_chipselect.
630 */
631 u16 bus_num;
632 u16 chip_select;
633
634 /* ... may need additional spi_device chip config data here.
635 * avoid stuff protocol drivers can set; but include stuff
636 * needed to behave without being bound to a driver:
637 * - chipselect polarity
638 * - quirks like clock rate mattering when not selected
639 */
640};
641
642#ifdef CONFIG_SPI
643extern int
644spi_register_board_info(struct spi_board_info const *info, unsigned n);
645#else
646/* board init code may ignore whether SPI is configured or not */
647static inline int
648spi_register_board_info(struct spi_board_info const *info, unsigned n)
649 { return 0; }
650#endif
651
652
653/* If you're hotplugging an adapter with devices (parport, usb, etc)
654 * use spi_new_device() to describe each device. You can also call
655 * spi_unregister_device() to start making that device vanish, but
656 * normally that would be handled by spi_unregister_master().
657 */
658extern struct spi_device *
659spi_new_device(struct spi_master *, struct spi_board_info *);
660
661static inline void
662spi_unregister_device(struct spi_device *spi)
663{
664 if (spi)
665 device_unregister(&spi->dev);
666}
667
668#endif /* __LINUX_SPI_H */
diff --git a/include/linux/spi/spi_bitbang.h b/include/linux/spi/spi_bitbang.h
new file mode 100644
index 000000000000..c961fe9bf3eb
--- /dev/null
+++ b/include/linux/spi/spi_bitbang.h
@@ -0,0 +1,135 @@
1#ifndef __SPI_BITBANG_H
2#define __SPI_BITBANG_H
3
4/*
5 * Mix this utility code with some glue code to get one of several types of
6 * simple SPI master driver. Two do polled word-at-a-time I/O:
7 *
8 * - GPIO/parport bitbangers. Provide chipselect() and txrx_word[](),
9 * expanding the per-word routines from the inline templates below.
10 *
11 * - Drivers for controllers resembling bare shift registers. Provide
12 * chipselect() and txrx_word[](), with custom setup()/cleanup() methods
13 * that use your controller's clock and chipselect registers.
14 *
15 * Some hardware works well with requests at spi_transfer scope:
16 *
17 * - Drivers leveraging smarter hardware, with fifos or DMA; or for half
18 * duplex (MicroWire) controllers. Provide chipslect() and txrx_bufs(),
19 * and custom setup()/cleanup() methods.
20 */
21struct spi_bitbang {
22 struct workqueue_struct *workqueue;
23 struct work_struct work;
24
25 spinlock_t lock;
26 struct list_head queue;
27 u8 busy;
28 u8 shutdown;
29 u8 use_dma;
30
31 struct spi_master *master;
32
33 void (*chipselect)(struct spi_device *spi, int is_on);
34#define BITBANG_CS_ACTIVE 1 /* normally nCS, active low */
35#define BITBANG_CS_INACTIVE 0
36
37 /* txrx_bufs() may handle dma mapping for transfers that don't
38 * already have one (transfer.{tx,rx}_dma is zero), or use PIO
39 */
40 int (*txrx_bufs)(struct spi_device *spi, struct spi_transfer *t);
41
42 /* txrx_word[SPI_MODE_*]() just looks like a shift register */
43 u32 (*txrx_word[4])(struct spi_device *spi,
44 unsigned nsecs,
45 u32 word, u8 bits);
46};
47
48/* you can call these default bitbang->master methods from your custom
49 * methods, if you like.
50 */
51extern int spi_bitbang_setup(struct spi_device *spi);
52extern void spi_bitbang_cleanup(const struct spi_device *spi);
53extern int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m);
54
55/* start or stop queue processing */
56extern int spi_bitbang_start(struct spi_bitbang *spi);
57extern int spi_bitbang_stop(struct spi_bitbang *spi);
58
59#endif /* __SPI_BITBANG_H */
60
61/*-------------------------------------------------------------------------*/
62
63#ifdef EXPAND_BITBANG_TXRX
64
65/*
66 * The code that knows what GPIO pins do what should have declared four
67 * functions, ideally as inlines, before #defining EXPAND_BITBANG_TXRX
68 * and including this header:
69 *
70 * void setsck(struct spi_device *, int is_on);
71 * void setmosi(struct spi_device *, int is_on);
72 * int getmiso(struct spi_device *);
73 * void spidelay(unsigned);
74 *
75 * A non-inlined routine would call bitbang_txrx_*() routines. The
76 * main loop could easily compile down to a handful of instructions,
77 * especially if the delay is a NOP (to run at peak speed).
78 *
79 * Since this is software, the timings may not be exactly what your board's
80 * chips need ... there may be several reasons you'd need to tweak timings
81 * in these routines, not just make to make it faster or slower to match a
82 * particular CPU clock rate.
83 */
84
85static inline u32
86bitbang_txrx_be_cpha0(struct spi_device *spi,
87 unsigned nsecs, unsigned cpol,
88 u32 word, u8 bits)
89{
90 /* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */
91
92 /* clock starts at inactive polarity */
93 for (word <<= (32 - bits); likely(bits); bits--) {
94
95 /* setup MSB (to slave) on trailing edge */
96 setmosi(spi, word & (1 << 31));
97 spidelay(nsecs); /* T(setup) */
98
99 setsck(spi, !cpol);
100 spidelay(nsecs);
101
102 /* sample MSB (from slave) on leading edge */
103 word <<= 1;
104 word |= getmiso(spi);
105 setsck(spi, cpol);
106 }
107 return word;
108}
109
110static inline u32
111bitbang_txrx_be_cpha1(struct spi_device *spi,
112 unsigned nsecs, unsigned cpol,
113 u32 word, u8 bits)
114{
115 /* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */
116
117 /* clock starts at inactive polarity */
118 for (word <<= (32 - bits); likely(bits); bits--) {
119
120 /* setup MSB (to slave) on leading edge */
121 setsck(spi, !cpol);
122 setmosi(spi, word & (1 << 31));
123 spidelay(nsecs); /* T(setup) */
124
125 setsck(spi, cpol);
126 spidelay(nsecs);
127
128 /* sample MSB (from slave) on trailing edge */
129 word <<= 1;
130 word |= getmiso(spi);
131 }
132 return word;
133}
134
135#endif /* EXPAND_BITBANG_TXRX */
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 389d1c382e20..e92054d6530b 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -180,6 +180,11 @@ extern int isolate_lru_page(struct page *p);
180extern int putback_lru_pages(struct list_head *l); 180extern int putback_lru_pages(struct list_head *l);
181extern int migrate_pages(struct list_head *l, struct list_head *t, 181extern int migrate_pages(struct list_head *l, struct list_head *t,
182 struct list_head *moved, struct list_head *failed); 182 struct list_head *moved, struct list_head *failed);
183#else
184static inline int isolate_lru_page(struct page *p) { return -ENOSYS; }
185static inline int putback_lru_pages(struct list_head *l) { return 0; }
186static inline int migrate_pages(struct list_head *l, struct list_head *t,
187 struct list_head *moved, struct list_head *failed) { return -ENOSYS; }
183#endif 188#endif
184 189
185#ifdef CONFIG_MMU 190#ifdef CONFIG_MMU
diff --git a/include/linux/tipc.h b/include/linux/tipc.h
new file mode 100644
index 000000000000..243a15f54002
--- /dev/null
+++ b/include/linux/tipc.h
@@ -0,0 +1,212 @@
1/*
2 * include/linux/tipc.h: Include file for TIPC socket interface
3 *
4 * Copyright (c) 2003-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#ifndef _LINUX_TIPC_H_
38#define _LINUX_TIPC_H_
39
40#include <linux/types.h>
41
42/*
43 * TIPC addressing primitives
44 */
45
46struct tipc_portid {
47 __u32 ref;
48 __u32 node;
49};
50
51struct tipc_name {
52 __u32 type;
53 __u32 instance;
54};
55
56struct tipc_name_seq {
57 __u32 type;
58 __u32 lower;
59 __u32 upper;
60};
61
62static inline __u32 tipc_addr(unsigned int zone,
63 unsigned int cluster,
64 unsigned int node)
65{
66 return (zone << 24) | (cluster << 12) | node;
67}
68
69static inline unsigned int tipc_zone(__u32 addr)
70{
71 return addr >> 24;
72}
73
74static inline unsigned int tipc_cluster(__u32 addr)
75{
76 return (addr >> 12) & 0xfff;
77}
78
79static inline unsigned int tipc_node(__u32 addr)
80{
81 return addr & 0xfff;
82}
83
84/*
85 * Application-accessible port name types
86 */
87
88#define TIPC_CFG_SRV 0 /* configuration service name type */
89#define TIPC_TOP_SRV 1 /* topology service name type */
90#define TIPC_RESERVED_TYPES 64 /* lowest user-publishable name type */
91
92/*
93 * Publication scopes when binding port names and port name sequences
94 */
95
96#define TIPC_ZONE_SCOPE 1
97#define TIPC_CLUSTER_SCOPE 2
98#define TIPC_NODE_SCOPE 3
99
100/*
101 * Limiting values for messages
102 */
103
104#define TIPC_MAX_USER_MSG_SIZE 66000
105
106/*
107 * Message importance levels
108 */
109
110#define TIPC_LOW_IMPORTANCE 0 /* default */
111#define TIPC_MEDIUM_IMPORTANCE 1
112#define TIPC_HIGH_IMPORTANCE 2
113#define TIPC_CRITICAL_IMPORTANCE 3
114
115/*
116 * Msg rejection/connection shutdown reasons
117 */
118
119#define TIPC_OK 0
120#define TIPC_ERR_NO_NAME 1
121#define TIPC_ERR_NO_PORT 2
122#define TIPC_ERR_NO_NODE 3
123#define TIPC_ERR_OVERLOAD 4
124#define TIPC_CONN_SHUTDOWN 5
125
126/*
127 * TIPC topology subscription service definitions
128 */
129
130#define TIPC_SUB_PORTS 0x01 /* filter for port availability */
131#define TIPC_SUB_SERVICE 0x02 /* filter for service availability */
132#if 0
133/* The following filter options are not currently implemented */
134#define TIPC_SUB_NO_BIND_EVTS 0x04 /* filter out "publish" events */
135#define TIPC_SUB_NO_UNBIND_EVTS 0x08 /* filter out "withdraw" events */
136#define TIPC_SUB_SINGLE_EVT 0x10 /* expire after first event */
137#endif
138
139#define TIPC_WAIT_FOREVER ~0 /* timeout for permanent subscription */
140
141struct tipc_subscr {
142 struct tipc_name_seq seq; /* name sequence of interest */
143 __u32 timeout; /* subscription duration (in ms) */
144 __u32 filter; /* bitmask of filter options */
145 char usr_handle[8]; /* available for subscriber use */
146};
147
148#define TIPC_PUBLISHED 1 /* publication event */
149#define TIPC_WITHDRAWN 2 /* withdraw event */
150#define TIPC_SUBSCR_TIMEOUT 3 /* subscription timeout event */
151
152struct tipc_event {
153 __u32 event; /* event type */
154 __u32 found_lower; /* matching name seq instances */
155 __u32 found_upper; /* " " " " */
156 struct tipc_portid port; /* associated port */
157 struct tipc_subscr s; /* associated subscription */
158};
159
160/*
161 * Socket API
162 */
163
164#ifndef AF_TIPC
165#define AF_TIPC 30
166#endif
167
168#ifndef PF_TIPC
169#define PF_TIPC AF_TIPC
170#endif
171
172#ifndef SOL_TIPC
173#define SOL_TIPC 271
174#endif
175
176#define TIPC_ADDR_NAMESEQ 1
177#define TIPC_ADDR_MCAST 1
178#define TIPC_ADDR_NAME 2
179#define TIPC_ADDR_ID 3
180
181struct sockaddr_tipc {
182 unsigned short family;
183 unsigned char addrtype;
184 signed char scope;
185 union {
186 struct tipc_portid id;
187 struct tipc_name_seq nameseq;
188 struct {
189 struct tipc_name name;
190 __u32 domain; /* 0: own zone */
191 } name;
192 } addr;
193};
194
195/*
196 * Ancillary data objects supported by recvmsg()
197 */
198
199#define TIPC_ERRINFO 1 /* error info */
200#define TIPC_RETDATA 2 /* returned data */
201#define TIPC_DESTNAME 3 /* destination name */
202
203/*
204 * TIPC-specific socket option values
205 */
206
207#define TIPC_IMPORTANCE 127 /* Default: TIPC_LOW_IMPORTANCE */
208#define TIPC_SRC_DROPPABLE 128 /* Default: 0 (resend congested msg) */
209#define TIPC_DEST_DROPPABLE 129 /* Default: based on socket type */
210#define TIPC_CONN_TIMEOUT 130 /* Default: 8000 (ms) */
211
212#endif
diff --git a/include/linux/tipc_config.h b/include/linux/tipc_config.h
new file mode 100644
index 000000000000..a52c8c64a5a3
--- /dev/null
+++ b/include/linux/tipc_config.h
@@ -0,0 +1,407 @@
1/*
2 * include/linux/tipc_config.h: Include file for TIPC configuration interface
3 *
4 * Copyright (c) 2003-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#ifndef _LINUX_TIPC_CONFIG_H_
38#define _LINUX_TIPC_CONFIG_H_
39
40#include <linux/types.h>
41#include <linux/string.h>
42#include <asm/byteorder.h>
43
44/*
45 * Configuration
46 *
47 * All configuration management messaging involves sending a request message
48 * to the TIPC configuration service on a node, which sends a reply message
49 * back. (In the future multi-message replies may be supported.)
50 *
51 * Both request and reply messages consist of a transport header and payload.
52 * The transport header contains info about the desired operation;
53 * the payload consists of zero or more type/length/value (TLV) items
54 * which specify parameters or results for the operation.
55 *
56 * For many operations, the request and reply messages have a fixed number
57 * of TLVs (usually zero or one); however, some reply messages may return
58 * a variable number of TLVs. A failed request is denoted by the presence
59 * of an "error string" TLV in the reply message instead of the TLV(s) the
60 * reply should contain if the request succeeds.
61 */
62
63/*
64 * Public commands:
65 * May be issued by any process.
66 * Accepted by own node, or by remote node only if remote management enabled.
67 */
68
69#define TIPC_CMD_NOOP 0x0000 /* tx none, rx none */
70#define TIPC_CMD_GET_NODES 0x0001 /* tx net_addr, rx node_info(s) */
71#define TIPC_CMD_GET_MEDIA_NAMES 0x0002 /* tx none, rx media_name(s) */
72#define TIPC_CMD_GET_BEARER_NAMES 0x0003 /* tx none, rx bearer_name(s) */
73#define TIPC_CMD_GET_LINKS 0x0004 /* tx net_addr, rx link_info(s) */
74#define TIPC_CMD_SHOW_NAME_TABLE 0x0005 /* tx name_tbl_query, rx ultra_string */
75#define TIPC_CMD_SHOW_PORTS 0x0006 /* tx none, rx ultra_string */
76#define TIPC_CMD_SHOW_LINK_STATS 0x000B /* tx link_name, rx ultra_string */
77
78#if 0
79#define TIPC_CMD_SHOW_PORT_STATS 0x0008 /* tx port_ref, rx ultra_string */
80#define TIPC_CMD_RESET_PORT_STATS 0x0009 /* tx port_ref, rx none */
81#define TIPC_CMD_GET_ROUTES 0x000A /* tx ?, rx ? */
82#define TIPC_CMD_GET_LINK_PEER 0x000D /* tx link_name, rx ? */
83#endif
84
85/*
86 * Protected commands:
87 * May only be issued by "network administration capable" process.
88 * Accepted by own node, or by remote node only if remote management enabled
89 * and this node is zone manager.
90 */
91
92#define TIPC_CMD_GET_REMOTE_MNG 0x4003 /* tx none, rx unsigned */
93#define TIPC_CMD_GET_MAX_PORTS 0x4004 /* tx none, rx unsigned */
94#define TIPC_CMD_GET_MAX_PUBL 0x4005 /* tx none, rx unsigned */
95#define TIPC_CMD_GET_MAX_SUBSCR 0x4006 /* tx none, rx unsigned */
96#define TIPC_CMD_GET_MAX_ZONES 0x4007 /* tx none, rx unsigned */
97#define TIPC_CMD_GET_MAX_CLUSTERS 0x4008 /* tx none, rx unsigned */
98#define TIPC_CMD_GET_MAX_NODES 0x4009 /* tx none, rx unsigned */
99#define TIPC_CMD_GET_MAX_SLAVES 0x400A /* tx none, rx unsigned */
100#define TIPC_CMD_GET_NETID 0x400B /* tx none, rx unsigned */
101
102#define TIPC_CMD_ENABLE_BEARER 0x4101 /* tx bearer_config, rx none */
103#define TIPC_CMD_DISABLE_BEARER 0x4102 /* tx bearer_name, rx none */
104#define TIPC_CMD_SET_LINK_TOL 0x4107 /* tx link_config, rx none */
105#define TIPC_CMD_SET_LINK_PRI 0x4108 /* tx link_config, rx none */
106#define TIPC_CMD_SET_LINK_WINDOW 0x4109 /* tx link_config, rx none */
107#define TIPC_CMD_SET_LOG_SIZE 0x410A /* tx unsigned, rx none */
108#define TIPC_CMD_DUMP_LOG 0x410B /* tx none, rx ultra_string */
109#define TIPC_CMD_RESET_LINK_STATS 0x410C /* tx link_name, rx none */
110
111#if 0
112#define TIPC_CMD_CREATE_LINK 0x4103 /* tx link_create, rx none */
113#define TIPC_CMD_REMOVE_LINK 0x4104 /* tx link_name, rx none */
114#define TIPC_CMD_BLOCK_LINK 0x4105 /* tx link_name, rx none */
115#define TIPC_CMD_UNBLOCK_LINK 0x4106 /* tx link_name, rx none */
116#endif
117
118/*
119 * Private commands:
120 * May only be issued by "network administration capable" process.
121 * Accepted by own node only; cannot be used on a remote node.
122 */
123
124#define TIPC_CMD_SET_NODE_ADDR 0x8001 /* tx net_addr, rx none */
125#if 0
126#define TIPC_CMD_SET_ZONE_MASTER 0x8002 /* tx none, rx none */
127#endif
128#define TIPC_CMD_SET_REMOTE_MNG 0x8003 /* tx unsigned, rx none */
129#define TIPC_CMD_SET_MAX_PORTS 0x8004 /* tx unsigned, rx none */
130#define TIPC_CMD_SET_MAX_PUBL 0x8005 /* tx unsigned, rx none */
131#define TIPC_CMD_SET_MAX_SUBSCR 0x8006 /* tx unsigned, rx none */
132#define TIPC_CMD_SET_MAX_ZONES 0x8007 /* tx unsigned, rx none */
133#define TIPC_CMD_SET_MAX_CLUSTERS 0x8008 /* tx unsigned, rx none */
134#define TIPC_CMD_SET_MAX_NODES 0x8009 /* tx unsigned, rx none */
135#define TIPC_CMD_SET_MAX_SLAVES 0x800A /* tx unsigned, rx none */
136#define TIPC_CMD_SET_NETID 0x800B /* tx unsigned, rx none */
137
138/*
139 * TLV types defined for TIPC
140 */
141
142#define TIPC_TLV_NONE 0 /* no TLV present */
143#define TIPC_TLV_VOID 1 /* empty TLV (0 data bytes)*/
144#define TIPC_TLV_UNSIGNED 2 /* 32-bit integer */
145#define TIPC_TLV_STRING 3 /* char[128] (max) */
146#define TIPC_TLV_LARGE_STRING 4 /* char[2048] (max) */
147#define TIPC_TLV_ULTRA_STRING 5 /* char[32768] (max) */
148
149#define TIPC_TLV_ERROR_STRING 16 /* char[128] containing "error code" */
150#define TIPC_TLV_NET_ADDR 17 /* 32-bit integer denoting <Z.C.N> */
151#define TIPC_TLV_MEDIA_NAME 18 /* char[TIPC_MAX_MEDIA_NAME] */
152#define TIPC_TLV_BEARER_NAME 19 /* char[TIPC_MAX_BEARER_NAME] */
153#define TIPC_TLV_LINK_NAME 20 /* char[TIPC_MAX_LINK_NAME] */
154#define TIPC_TLV_NODE_INFO 21 /* struct tipc_node_info */
155#define TIPC_TLV_LINK_INFO 22 /* struct tipc_link_info */
156#define TIPC_TLV_BEARER_CONFIG 23 /* struct tipc_bearer_config */
157#define TIPC_TLV_LINK_CONFIG 24 /* struct tipc_link_config */
158#define TIPC_TLV_NAME_TBL_QUERY 25 /* struct tipc_name_table_query */
159#define TIPC_TLV_PORT_REF 26 /* 32-bit port reference */
160
161/*
162 * Maximum sizes of TIPC bearer-related names (including terminating NUL)
163 */
164
165#define TIPC_MAX_MEDIA_NAME 16 /* format = media */
166#define TIPC_MAX_IF_NAME 16 /* format = interface */
167#define TIPC_MAX_BEARER_NAME 32 /* format = media:interface */
168#define TIPC_MAX_LINK_NAME 60 /* format = Z.C.N:interface-Z.C.N:interface */
169
170/*
171 * Link priority limits (range from 0 to # priorities - 1)
172 */
173
174#define TIPC_NUM_LINK_PRI 32
175
176/*
177 * Link tolerance limits (min, default, max), in ms
178 */
179
180#define TIPC_MIN_LINK_TOL 50
181#define TIPC_DEF_LINK_TOL 1500
182#define TIPC_MAX_LINK_TOL 30000
183
184/*
185 * Link window limits (min, default, max), in packets
186 */
187
188#define TIPC_MIN_LINK_WIN 16
189#define TIPC_DEF_LINK_WIN 50
190#define TIPC_MAX_LINK_WIN 150
191
192
193struct tipc_node_info {
194 __u32 addr; /* network address of node */
195 __u32 up; /* 0=down, 1= up */
196};
197
198struct tipc_link_info {
199 __u32 dest; /* network address of peer node */
200 __u32 up; /* 0=down, 1=up */
201 char str[TIPC_MAX_LINK_NAME]; /* link name */
202};
203
204struct tipc_bearer_config {
205 __u32 priority; /* Range [1,31]. Override per link */
206 __u32 detect_scope;
207 char name[TIPC_MAX_BEARER_NAME];
208};
209
210struct tipc_link_config {
211 __u32 value;
212 char name[TIPC_MAX_LINK_NAME];
213};
214
215#define TIPC_NTQ_ALLTYPES 0x80000000
216
217struct tipc_name_table_query {
218 __u32 depth; /* 1:type, 2:+name info, 3:+port info, 4+:+debug info */
219 __u32 type; /* {t,l,u} info ignored if high bit of "depth" is set */
220 __u32 lowbound; /* (i.e. displays all entries of name table) */
221 __u32 upbound;
222};
223
224/*
225 * The error string TLV is a null-terminated string describing the cause
226 * of the request failure. To simplify error processing (and to save space)
227 * the first character of the string can be a special error code character
228 * (lying by the range 0x80 to 0xFF) which represents a pre-defined reason.
229 */
230
231#define TIPC_CFG_TLV_ERROR "\x80" /* request contains incorrect TLV(s) */
232#define TIPC_CFG_NOT_NET_ADMIN "\x81" /* must be network administrator */
233#define TIPC_CFG_NOT_ZONE_MSTR "\x82" /* must be zone master */
234#define TIPC_CFG_NO_REMOTE "\x83" /* remote management not enabled */
235#define TIPC_CFG_NOT_SUPPORTED "\x84" /* request is not supported by TIPC */
236#define TIPC_CFG_INVALID_VALUE "\x85" /* request has invalid argument value */
237
238#if 0
239/* prototypes TLV structures for proposed commands */
240struct tipc_link_create {
241 __u32 domain;
242 struct tipc_media_addr peer_addr;
243 char bearer_name[TIPC_MAX_BEARER_NAME];
244};
245
246struct tipc_route_info {
247 __u32 dest;
248 __u32 router;
249};
250#endif
251
252/*
253 * A TLV consists of a descriptor, followed by the TLV value.
254 * TLV descriptor fields are stored in network byte order;
255 * TLV values must also be stored in network byte order (where applicable).
256 * TLV descriptors must be aligned to addresses which are multiple of 4,
257 * so up to 3 bytes of padding may exist at the end of the TLV value area.
258 * There must not be any padding between the TLV descriptor and its value.
259 */
260
261struct tlv_desc {
262 __u16 tlv_len; /* TLV length (descriptor + value) */
263 __u16 tlv_type; /* TLV identifier */
264};
265
266#define TLV_ALIGNTO 4
267
268#define TLV_ALIGN(datalen) (((datalen)+(TLV_ALIGNTO-1)) & ~(TLV_ALIGNTO-1))
269#define TLV_LENGTH(datalen) (sizeof(struct tlv_desc) + (datalen))
270#define TLV_SPACE(datalen) (TLV_ALIGN(TLV_LENGTH(datalen)))
271#define TLV_DATA(tlv) ((void *)((char *)(tlv) + TLV_LENGTH(0)))
272
273static inline int TLV_OK(const void *tlv, __u16 space)
274{
275 /*
276 * Would also like to check that "tlv" is a multiple of 4,
277 * but don't know how to do this in a portable way.
278 * - Tried doing (!(tlv & (TLV_ALIGNTO-1))), but GCC compiler
279 * won't allow binary "&" with a pointer.
280 * - Tried casting "tlv" to integer type, but causes warning about size
281 * mismatch when pointer is bigger than chosen type (int, long, ...).
282 */
283
284 return (space >= TLV_SPACE(0)) &&
285 (ntohs(((struct tlv_desc *)tlv)->tlv_len) <= space);
286}
287
288static inline int TLV_CHECK(const void *tlv, __u16 space, __u16 exp_type)
289{
290 return TLV_OK(tlv, space) &&
291 (ntohs(((struct tlv_desc *)tlv)->tlv_type) == exp_type);
292}
293
294static inline int TLV_SET(void *tlv, __u16 type, void *data, __u16 len)
295{
296 struct tlv_desc *tlv_ptr;
297 int tlv_len;
298
299 tlv_len = TLV_LENGTH(len);
300 tlv_ptr = (struct tlv_desc *)tlv;
301 tlv_ptr->tlv_type = htons(type);
302 tlv_ptr->tlv_len = htons(tlv_len);
303 if (len && data)
304 memcpy(TLV_DATA(tlv_ptr), data, tlv_len);
305 return TLV_SPACE(len);
306}
307
308/*
309 * A TLV list descriptor simplifies processing of messages
310 * containing multiple TLVs.
311 */
312
313struct tlv_list_desc {
314 struct tlv_desc *tlv_ptr; /* ptr to current TLV */
315 __u32 tlv_space; /* # bytes from curr TLV to list end */
316};
317
318static inline void TLV_LIST_INIT(struct tlv_list_desc *list,
319 void *data, __u32 space)
320{
321 list->tlv_ptr = (struct tlv_desc *)data;
322 list->tlv_space = space;
323}
324
325static inline int TLV_LIST_EMPTY(struct tlv_list_desc *list)
326{
327 return (list->tlv_space == 0);
328}
329
330static inline int TLV_LIST_CHECK(struct tlv_list_desc *list, __u16 exp_type)
331{
332 return TLV_CHECK(list->tlv_ptr, list->tlv_space, exp_type);
333}
334
335static inline void *TLV_LIST_DATA(struct tlv_list_desc *list)
336{
337 return TLV_DATA(list->tlv_ptr);
338}
339
340static inline void TLV_LIST_STEP(struct tlv_list_desc *list)
341{
342 __u16 tlv_space = TLV_ALIGN(ntohs(list->tlv_ptr->tlv_len));
343
344 list->tlv_ptr = (struct tlv_desc *)((char *)list->tlv_ptr + tlv_space);
345 list->tlv_space -= tlv_space;
346}
347
348/*
349 * Configuration messages exchanged via NETLINK_GENERIC use the following
350 * family id, name, version and command.
351 */
352#define TIPC_GENL_NAME "TIPC"
353#define TIPC_GENL_VERSION 0x1
354#define TIPC_GENL_CMD 0x1
355
356/*
357 * TIPC specific header used in NETLINK_GENERIC requests.
358 */
359struct tipc_genlmsghdr {
360 __u32 dest; /* Destination address */
361 __u16 cmd; /* Command */
362 __u16 reserved; /* Unused */
363};
364
365#define TIPC_GENL_HDRLEN NLMSG_ALIGN(sizeof(struct tipc_genlmsghdr))
366
367/*
368 * Configuration messages exchanged via TIPC sockets use the TIPC configuration
369 * message header, which is defined below. This structure is analogous
370 * to the Netlink message header, but fields are stored in network byte order
371 * and no padding is permitted between the header and the message data
372 * that follows.
373 */
374
375struct tipc_cfg_msg_hdr
376{
377 __u32 tcm_len; /* Message length (including header) */
378 __u16 tcm_type; /* Command type */
379 __u16 tcm_flags; /* Additional flags */
380 char tcm_reserved[8]; /* Unused */
381};
382
383#define TCM_F_REQUEST 0x1 /* Flag: Request message */
384#define TCM_F_MORE 0x2 /* Flag: Message to be continued */
385
386#define TCM_ALIGN(datalen) (((datalen)+3) & ~3)
387#define TCM_LENGTH(datalen) (sizeof(struct tipc_cfg_msg_hdr) + datalen)
388#define TCM_SPACE(datalen) (TCM_ALIGN(TCM_LENGTH(datalen)))
389#define TCM_DATA(tcm_hdr) ((void *)((char *)(tcm_hdr) + TCM_LENGTH(0)))
390
391static inline int TCM_SET(void *msg, __u16 cmd, __u16 flags,
392 void *data, __u16 data_len)
393{
394 struct tipc_cfg_msg_hdr *tcm_hdr;
395 int msg_len;
396
397 msg_len = TCM_LENGTH(data_len);
398 tcm_hdr = (struct tipc_cfg_msg_hdr *)msg;
399 tcm_hdr->tcm_len = htonl(msg_len);
400 tcm_hdr->tcm_type = htons(cmd);
401 tcm_hdr->tcm_flags = htons(flags);
402 if (data_len && data)
403 memcpy(TCM_DATA(msg), data, data_len);
404 return TCM_SPACE(data_len);
405}
406
407#endif
diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index c5b96b2b8155..805de50df00d 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -22,7 +22,6 @@ struct genl_family
22 char name[GENL_NAMSIZ]; 22 char name[GENL_NAMSIZ];
23 unsigned int version; 23 unsigned int version;
24 unsigned int maxattr; 24 unsigned int maxattr;
25 struct module * owner;
26 struct nlattr ** attrbuf; /* private */ 25 struct nlattr ** attrbuf; /* private */
27 struct list_head ops_list; /* private */ 26 struct list_head ops_list; /* private */
28 struct list_head family_list; /* private */ 27 struct list_head family_list; /* private */
diff --git a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
index 25b081a730e6..91684436af8e 100644
--- a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
+++ b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
@@ -37,7 +37,4 @@ struct nf_conntrack_ipv4 {
37struct sk_buff * 37struct sk_buff *
38nf_ct_ipv4_ct_gather_frags(struct sk_buff *skb); 38nf_ct_ipv4_ct_gather_frags(struct sk_buff *skb);
39 39
40/* call to create an explicit dependency on nf_conntrack_l3proto_ipv4. */
41extern void need_ip_conntrack(void);
42
43#endif /*_NF_CONNTRACK_IPV4_H*/ 40#endif /*_NF_CONNTRACK_IPV4_H*/
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index 64b82b74a650..6d075ca16e6e 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -221,9 +221,6 @@ extern void nf_ct_helper_put(struct nf_conntrack_helper *helper);
221extern struct nf_conntrack_helper * 221extern struct nf_conntrack_helper *
222__nf_conntrack_helper_find_byname(const char *name); 222__nf_conntrack_helper_find_byname(const char *name);
223 223
224/* call to create an explicit dependency on nf_conntrack. */
225extern void need_nf_conntrack(void);
226
227extern int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse, 224extern int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,
228 const struct nf_conntrack_tuple *orig); 225 const struct nf_conntrack_tuple *orig);
229 226
diff --git a/include/net/netfilter/nf_conntrack_tuple.h b/include/net/netfilter/nf_conntrack_tuple.h
index 14ce790e5c65..530ef1f75283 100644
--- a/include/net/netfilter/nf_conntrack_tuple.h
+++ b/include/net/netfilter/nf_conntrack_tuple.h
@@ -111,7 +111,7 @@ struct nf_conntrack_tuple
111#ifdef __KERNEL__ 111#ifdef __KERNEL__
112 112
113#define NF_CT_DUMP_TUPLE(tp) \ 113#define NF_CT_DUMP_TUPLE(tp) \
114DEBUGP("tuple %p: %u %u %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x %hu -> %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x %hu\n", \ 114DEBUGP("tuple %p: %u %u " NIP6_FMT " %hu -> " NIP6_FMT " %hu\n", \
115 (tp), (tp)->src.l3num, (tp)->dst.protonum, \ 115 (tp), (tp)->src.l3num, (tp)->dst.protonum, \
116 NIP6(*(struct in6_addr *)(tp)->src.u3.all), ntohs((tp)->src.u.all), \ 116 NIP6(*(struct in6_addr *)(tp)->src.u3.all), ntohs((tp)->src.u.all), \
117 NIP6(*(struct in6_addr *)(tp)->dst.u3.all), ntohs((tp)->dst.u.all)) 117 NIP6(*(struct in6_addr *)(tp)->dst.u3.all), ntohs((tp)->dst.u.all))
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 8f241216f46b..a553f39f6aee 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -225,13 +225,13 @@ extern int sctp_debug_flag;
225 if (sctp_debug_flag) { \ 225 if (sctp_debug_flag) { \
226 if (saddr->sa.sa_family == AF_INET6) { \ 226 if (saddr->sa.sa_family == AF_INET6) { \
227 printk(KERN_DEBUG \ 227 printk(KERN_DEBUG \
228 lead "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x" trail, \ 228 lead NIP6_FMT trail, \
229 leadparm, \ 229 leadparm, \
230 NIP6(saddr->v6.sin6_addr), \ 230 NIP6(saddr->v6.sin6_addr), \
231 otherparms); \ 231 otherparms); \
232 } else { \ 232 } else { \
233 printk(KERN_DEBUG \ 233 printk(KERN_DEBUG \
234 lead "%u.%u.%u.%u" trail, \ 234 lead NIPQUAD_FMT trail, \
235 leadparm, \ 235 leadparm, \
236 NIPQUAD(saddr->v4.sin_addr.s_addr), \ 236 NIPQUAD(saddr->v4.sin_addr.s_addr), \
237 otherparms); \ 237 otherparms); \
diff --git a/include/net/tipc/tipc.h b/include/net/tipc/tipc.h
new file mode 100644
index 000000000000..9566608c88cf
--- /dev/null
+++ b/include/net/tipc/tipc.h
@@ -0,0 +1,257 @@
1/*
2 * include/net/tipc/tipc.h: Main include file for TIPC users
3 *
4 * Copyright (c) 2003-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#ifndef _NET_TIPC_H_
38#define _NET_TIPC_H_
39
40#ifdef __KERNEL__
41
42#include <linux/tipc.h>
43#include <linux/skbuff.h>
44
45/*
46 * Native API
47 */
48
49/*
50 * TIPC operating mode routines
51 */
52
53u32 tipc_get_addr(void);
54
55#define TIPC_NOT_RUNNING 0
56#define TIPC_NODE_MODE 1
57#define TIPC_NET_MODE 2
58
59typedef void (*tipc_mode_event)(void *usr_handle, int mode, u32 addr);
60
61int tipc_attach(unsigned int *userref, tipc_mode_event, void *usr_handle);
62
63void tipc_detach(unsigned int userref);
64
65int tipc_get_mode(void);
66
67/*
68 * TIPC port manipulation routines
69 */
70
71typedef void (*tipc_msg_err_event) (void *usr_handle,
72 u32 portref,
73 struct sk_buff **buf,
74 unsigned char const *data,
75 unsigned int size,
76 int reason,
77 struct tipc_portid const *attmpt_destid);
78
79typedef void (*tipc_named_msg_err_event) (void *usr_handle,
80 u32 portref,
81 struct sk_buff **buf,
82 unsigned char const *data,
83 unsigned int size,
84 int reason,
85 struct tipc_name_seq const *attmpt_dest);
86
87typedef void (*tipc_conn_shutdown_event) (void *usr_handle,
88 u32 portref,
89 struct sk_buff **buf,
90 unsigned char const *data,
91 unsigned int size,
92 int reason);
93
94typedef void (*tipc_msg_event) (void *usr_handle,
95 u32 portref,
96 struct sk_buff **buf,
97 unsigned char const *data,
98 unsigned int size,
99 unsigned int importance,
100 struct tipc_portid const *origin);
101
102typedef void (*tipc_named_msg_event) (void *usr_handle,
103 u32 portref,
104 struct sk_buff **buf,
105 unsigned char const *data,
106 unsigned int size,
107 unsigned int importance,
108 struct tipc_portid const *orig,
109 struct tipc_name_seq const *dest);
110
111typedef void (*tipc_conn_msg_event) (void *usr_handle,
112 u32 portref,
113 struct sk_buff **buf,
114 unsigned char const *data,
115 unsigned int size);
116
117typedef void (*tipc_continue_event) (void *usr_handle,
118 u32 portref);
119
120int tipc_createport(unsigned int tipc_user,
121 void *usr_handle,
122 unsigned int importance,
123 tipc_msg_err_event error_cb,
124 tipc_named_msg_err_event named_error_cb,
125 tipc_conn_shutdown_event conn_error_cb,
126 tipc_msg_event message_cb,
127 tipc_named_msg_event named_message_cb,
128 tipc_conn_msg_event conn_message_cb,
129 tipc_continue_event continue_event_cb,/* May be zero */
130 u32 *portref);
131
132int tipc_deleteport(u32 portref);
133
134int tipc_ownidentity(u32 portref, struct tipc_portid *port);
135
136int tipc_portimportance(u32 portref, unsigned int *importance);
137int tipc_set_portimportance(u32 portref, unsigned int importance);
138
139int tipc_portunreliable(u32 portref, unsigned int *isunreliable);
140int tipc_set_portunreliable(u32 portref, unsigned int isunreliable);
141
142int tipc_portunreturnable(u32 portref, unsigned int *isunreturnable);
143int tipc_set_portunreturnable(u32 portref, unsigned int isunreturnable);
144
145int tipc_publish(u32 portref, unsigned int scope,
146 struct tipc_name_seq const *name_seq);
147int tipc_withdraw(u32 portref, unsigned int scope,
148 struct tipc_name_seq const *name_seq); /* 0: all */
149
150int tipc_connect2port(u32 portref, struct tipc_portid const *port);
151
152int tipc_disconnect(u32 portref);
153
154int tipc_shutdown(u32 ref); /* Sends SHUTDOWN msg */
155
156int tipc_isconnected(u32 portref, int *isconnected);
157
158int tipc_peer(u32 portref, struct tipc_portid *peer);
159
160int tipc_ref_valid(u32 portref);
161
162/*
163 * TIPC messaging routines
164 */
165
166#define TIPC_PORT_IMPORTANCE 100 /* send using current port setting */
167
168
169int tipc_send(u32 portref,
170 unsigned int num_sect,
171 struct iovec const *msg_sect);
172
173int tipc_send_buf(u32 portref,
174 struct sk_buff *buf,
175 unsigned int dsz);
176
177int tipc_send2name(u32 portref,
178 struct tipc_name const *name,
179 u32 domain, /* 0:own zone */
180 unsigned int num_sect,
181 struct iovec const *msg_sect);
182
183int tipc_send_buf2name(u32 portref,
184 struct tipc_name const *name,
185 u32 domain,
186 struct sk_buff *buf,
187 unsigned int dsz);
188
189int tipc_forward2name(u32 portref,
190 struct tipc_name const *name,
191 u32 domain, /*0: own zone */
192 unsigned int section_count,
193 struct iovec const *msg_sect,
194 struct tipc_portid const *origin,
195 unsigned int importance);
196
197int tipc_forward_buf2name(u32 portref,
198 struct tipc_name const *name,
199 u32 domain,
200 struct sk_buff *buf,
201 unsigned int dsz,
202 struct tipc_portid const *orig,
203 unsigned int importance);
204
205int tipc_send2port(u32 portref,
206 struct tipc_portid const *dest,
207 unsigned int num_sect,
208 struct iovec const *msg_sect);
209
210int tipc_send_buf2port(u32 portref,
211 struct tipc_portid const *dest,
212 struct sk_buff *buf,
213 unsigned int dsz);
214
215int tipc_forward2port(u32 portref,
216 struct tipc_portid const *dest,
217 unsigned int num_sect,
218 struct iovec const *msg_sect,
219 struct tipc_portid const *origin,
220 unsigned int importance);
221
222int tipc_forward_buf2port(u32 portref,
223 struct tipc_portid const *dest,
224 struct sk_buff *buf,
225 unsigned int dsz,
226 struct tipc_portid const *orig,
227 unsigned int importance);
228
229int tipc_multicast(u32 portref,
230 struct tipc_name_seq const *seq,
231 u32 domain, /* 0:own zone */
232 unsigned int section_count,
233 struct iovec const *msg);
234
235#if 0
236int tipc_multicast_buf(u32 portref,
237 struct tipc_name_seq const *seq,
238 u32 domain, /* 0:own zone */
239 void *buf,
240 unsigned int size);
241#endif
242
243/*
244 * TIPC subscription routines
245 */
246
247int tipc_ispublished(struct tipc_name const *name);
248
249/*
250 * Get number of available nodes within specified domain (excluding own node)
251 */
252
253unsigned int tipc_available_nodes(const u32 domain);
254
255#endif
256
257#endif
diff --git a/include/net/tipc/tipc_bearer.h b/include/net/tipc/tipc_bearer.h
new file mode 100644
index 000000000000..098607cd4b78
--- /dev/null
+++ b/include/net/tipc/tipc_bearer.h
@@ -0,0 +1,121 @@
1/*
2 * include/net/tipc/tipc_bearer.h: Include file for privileged access to TIPC bearers
3 *
4 * Copyright (c) 2003-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#ifndef _NET_TIPC_BEARER_H_
38#define _NET_TIPC_BEARER_H_
39
40#ifdef __KERNEL__
41
42#include <linux/tipc_config.h>
43#include <linux/skbuff.h>
44#include <linux/spinlock.h>
45
46/*
47 * Identifiers of supported TIPC media types
48 */
49
50#define TIPC_MEDIA_TYPE_ETH 1
51
52struct tipc_media_addr {
53 __u32 type;
54 union {
55 __u8 eth_addr[6]; /* Ethernet bearer */
56#if 0
57 /* Prototypes for other possible bearer types */
58
59 struct {
60 __u16 sin_family;
61 __u16 sin_port;
62 struct {
63 __u32 s_addr;
64 } sin_addr;
65 char pad[4];
66 } addr_in; /* IP-based bearer */
67 __u16 sock_descr; /* generic socket bearer */
68#endif
69 } dev_addr;
70};
71
72/**
73 * struct tipc_bearer - TIPC bearer info available to privileged users
74 * @usr_handle: pointer to additional user-defined information about bearer
75 * @mtu: max packet size bearer can support
76 * @blocked: non-zero if bearer is blocked
77 * @lock: spinlock for controlling access to bearer
78 * @addr: media-specific address associated with bearer
79 * @name: bearer name (format = media:interface)
80 *
81 * Note: TIPC initializes "name" and "lock" fields; user is responsible for
82 * initialization all other fields when a bearer is enabled.
83 */
84
85struct tipc_bearer {
86 void *usr_handle;
87 u32 mtu;
88 int blocked;
89 spinlock_t lock;
90 struct tipc_media_addr addr;
91 char name[TIPC_MAX_BEARER_NAME];
92};
93
94
95int tipc_register_media(u32 media_type,
96 char *media_name,
97 int (*enable)(struct tipc_bearer *),
98 void (*disable)(struct tipc_bearer *),
99 int (*send_msg)(struct sk_buff *,
100 struct tipc_bearer *,
101 struct tipc_media_addr *),
102 char *(*addr2str)(struct tipc_media_addr *a,
103 char *str_buf,
104 int str_size),
105 struct tipc_media_addr *bcast_addr,
106 const u32 bearer_priority,
107 const u32 link_tolerance, /* [ms] */
108 const u32 send_window_limit);
109
110void tipc_recv_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr);
111
112int tipc_block_bearer(const char *name);
113void tipc_continue(struct tipc_bearer *tb_ptr);
114
115int tipc_enable_bearer(const char *bearer_name, u32 bcast_scope, u32 priority);
116int tipc_disable_bearer(const char *name);
117
118
119#endif
120
121#endif
diff --git a/include/net/tipc/tipc_msg.h b/include/net/tipc/tipc_msg.h
new file mode 100644
index 000000000000..4d096eebc93f
--- /dev/null
+++ b/include/net/tipc/tipc_msg.h
@@ -0,0 +1,223 @@
1/*
2 * include/net/tipc/tipc_msg.h: Include file for privileged access to TIPC message headers
3 *
4 * Copyright (c) 2003-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#ifndef _NET_TIPC_MSG_H_
38#define _NET_TIPC_MSG_H_
39
40#ifdef __KERNEL__
41
42struct tipc_msg {
43 u32 hdr[15];
44};
45
46
47/*
48 TIPC user data message header format, version 2:
49
50
51 1 0 9 8 7 6 5 4|3 2 1 0 9 8 7 6|5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0
52 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
53 w0:|vers | user |hdr sz |n|d|s|-| message size |
54 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
55 w1:|mstyp| error |rer cnt|lsc|opt p| broadcast ack no |
56 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
57 w2:| link level ack no | broadcast/link level seq no |
58 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
59 w3:| previous node |
60 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
61 w4:| originating port |
62 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
63 w5:| destination port |
64 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
65 w6:| originating node |
66 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
67 w7:| destination node |
68 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
69 w8:| name type / transport sequence number |
70 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
71 w9:| name instance/multicast lower bound |
72 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
73 wA:| multicast upper bound |
74 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
75 / /
76 \ options \
77 / /
78 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
79
80*/
81
82#define TIPC_CONN_MSG 0
83#define TIPC_MCAST_MSG 1
84#define TIPC_NAMED_MSG 2
85#define TIPC_DIRECT_MSG 3
86
87
88static inline u32 msg_word(struct tipc_msg *m, u32 pos)
89{
90 return ntohl(m->hdr[pos]);
91}
92
93static inline u32 msg_bits(struct tipc_msg *m, u32 w, u32 pos, u32 mask)
94{
95 return (msg_word(m, w) >> pos) & mask;
96}
97
98static inline u32 msg_importance(struct tipc_msg *m)
99{
100 return msg_bits(m, 0, 25, 0xf);
101}
102
103static inline u32 msg_hdr_sz(struct tipc_msg *m)
104{
105 return msg_bits(m, 0, 21, 0xf) << 2;
106}
107
108static inline int msg_short(struct tipc_msg *m)
109{
110 return (msg_hdr_sz(m) == 24);
111}
112
113static inline u32 msg_size(struct tipc_msg *m)
114{
115 return msg_bits(m, 0, 0, 0x1ffff);
116}
117
118static inline u32 msg_data_sz(struct tipc_msg *m)
119{
120 return (msg_size(m) - msg_hdr_sz(m));
121}
122
123static inline unchar *msg_data(struct tipc_msg *m)
124{
125 return ((unchar *)m) + msg_hdr_sz(m);
126}
127
128static inline u32 msg_type(struct tipc_msg *m)
129{
130 return msg_bits(m, 1, 29, 0x7);
131}
132
133static inline u32 msg_direct(struct tipc_msg *m)
134{
135 return (msg_type(m) == TIPC_DIRECT_MSG);
136}
137
138static inline u32 msg_named(struct tipc_msg *m)
139{
140 return (msg_type(m) == TIPC_NAMED_MSG);
141}
142
143static inline u32 msg_mcast(struct tipc_msg *m)
144{
145 return (msg_type(m) == TIPC_MCAST_MSG);
146}
147
148static inline u32 msg_connected(struct tipc_msg *m)
149{
150 return (msg_type(m) == TIPC_CONN_MSG);
151}
152
153static inline u32 msg_errcode(struct tipc_msg *m)
154{
155 return msg_bits(m, 1, 25, 0xf);
156}
157
158static inline u32 msg_prevnode(struct tipc_msg *m)
159{
160 return msg_word(m, 3);
161}
162
163static inline u32 msg_origport(struct tipc_msg *m)
164{
165 return msg_word(m, 4);
166}
167
168static inline u32 msg_destport(struct tipc_msg *m)
169{
170 return msg_word(m, 5);
171}
172
173static inline u32 msg_mc_netid(struct tipc_msg *m)
174{
175 return msg_word(m, 5);
176}
177
178static inline u32 msg_orignode(struct tipc_msg *m)
179{
180 if (likely(msg_short(m)))
181 return msg_prevnode(m);
182 return msg_word(m, 6);
183}
184
185static inline u32 msg_destnode(struct tipc_msg *m)
186{
187 return msg_word(m, 7);
188}
189
190static inline u32 msg_nametype(struct tipc_msg *m)
191{
192 return msg_word(m, 8);
193}
194
195static inline u32 msg_nameinst(struct tipc_msg *m)
196{
197 return msg_word(m, 9);
198}
199
200static inline u32 msg_namelower(struct tipc_msg *m)
201{
202 return msg_nameinst(m);
203}
204
205static inline u32 msg_nameupper(struct tipc_msg *m)
206{
207 return msg_word(m, 10);
208}
209
210static inline char *msg_options(struct tipc_msg *m, u32 *len)
211{
212 u32 pos = msg_bits(m, 1, 16, 0x7);
213
214 if (!pos)
215 return 0;
216 pos = (pos * 4) + 28;
217 *len = msg_hdr_sz(m) - pos;
218 return (char *)&m->hdr[pos/4];
219}
220
221#endif
222
223#endif
diff --git a/include/net/tipc/tipc_port.h b/include/net/tipc/tipc_port.h
new file mode 100644
index 000000000000..333bba6dc522
--- /dev/null
+++ b/include/net/tipc/tipc_port.h
@@ -0,0 +1,108 @@
1/*
2 * include/net/tipc/tipc_port.h: Include file for privileged access to TIPC ports
3 *
4 * Copyright (c) 1994-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#ifndef _NET_TIPC_PORT_H_
38#define _NET_TIPC_PORT_H_
39
40#ifdef __KERNEL__
41
42#include <linux/tipc.h>
43#include <linux/skbuff.h>
44#include <net/tipc/tipc_msg.h>
45
46#define TIPC_FLOW_CONTROL_WIN 512
47
48/**
49 * struct tipc_port - native TIPC port info available to privileged users
50 * @usr_handle: pointer to additional user-defined information about port
51 * @lock: pointer to spinlock for controlling access to port
52 * @connected: non-zero if port is currently connected to a peer port
53 * @conn_type: TIPC type used when connection was established
54 * @conn_instance: TIPC instance used when connection was established
55 * @conn_unacked: number of unacknowledged messages received from peer port
56 * @published: non-zero if port has one or more associated names
57 * @congested: non-zero if cannot send because of link or port congestion
58 * @ref: unique reference to port in TIPC object registry
59 * @phdr: preformatted message header used when sending messages
60 */
61
62struct tipc_port {
63 void *usr_handle;
64 spinlock_t *lock;
65 int connected;
66 u32 conn_type;
67 u32 conn_instance;
68 u32 conn_unacked;
69 int published;
70 u32 congested;
71 u32 ref;
72 struct tipc_msg phdr;
73};
74
75
76/**
77 * tipc_createport_raw - create a native TIPC port and return it's reference
78 *
79 * Note: 'dispatcher' and 'wakeup' deliver a locked port.
80 */
81
82u32 tipc_createport_raw(void *usr_handle,
83 u32 (*dispatcher)(struct tipc_port *, struct sk_buff *),
84 void (*wakeup)(struct tipc_port *),
85 const u32 importance);
86
87/*
88 * tipc_set_msg_option(): port must be locked.
89 */
90int tipc_set_msg_option(struct tipc_port *tp_ptr,
91 const char *opt,
92 const u32 len);
93
94int tipc_reject_msg(struct sk_buff *buf, u32 err);
95
96int tipc_send_buf_fast(struct sk_buff *buf, u32 destnode);
97
98void tipc_acknowledge(u32 port_ref,u32 ack);
99
100struct tipc_port *tipc_get_port(const u32 ref);
101
102void *tipc_get_handle(const u32 ref);
103
104
105#endif
106
107#endif
108
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index a7f4c355a91f..22fc886b9695 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -88,7 +88,6 @@ enum ib_atomic_cap {
88 88
89struct ib_device_attr { 89struct ib_device_attr {
90 u64 fw_ver; 90 u64 fw_ver;
91 __be64 node_guid;
92 __be64 sys_image_guid; 91 __be64 sys_image_guid;
93 u64 max_mr_size; 92 u64 max_mr_size;
94 u64 page_size_cap; 93 u64 page_size_cap;
@@ -951,6 +950,7 @@ struct ib_device {
951 u64 uverbs_cmd_mask; 950 u64 uverbs_cmd_mask;
952 int uverbs_abi_ver; 951 int uverbs_abi_ver;
953 952
953 __be64 node_guid;
954 u8 node_type; 954 u8 node_type;
955 u8 phys_port_cnt; 955 u8 phys_port_cnt;
956}; 956};
diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
index be1bc792ab18..3e5cb5ab2d34 100644
--- a/include/scsi/iscsi_if.h
+++ b/include/scsi/iscsi_if.h
@@ -168,6 +168,12 @@ typedef uint64_t iscsi_connh_t; /* iSCSI Data-Path connection handle */
168 168
169#define iscsi_ptr(_handle) ((void*)(unsigned long)_handle) 169#define iscsi_ptr(_handle) ((void*)(unsigned long)_handle)
170#define iscsi_handle(_ptr) ((uint64_t)(unsigned long)_ptr) 170#define iscsi_handle(_ptr) ((uint64_t)(unsigned long)_ptr)
171#define hostdata_session(_hostdata) (iscsi_ptr(*(unsigned long *)_hostdata))
172
173/**
174 * iscsi_hostdata - get LLD hostdata from scsi_host
175 * @_hostdata: pointer to scsi host's hostdata
176 **/
171#define iscsi_hostdata(_hostdata) ((void*)_hostdata + sizeof(unsigned long)) 177#define iscsi_hostdata(_hostdata) ((void*)_hostdata + sizeof(unsigned long))
172 178
173/* 179/*
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index 6cb1e2788d8b..c60b8ff2f5e4 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -32,6 +32,12 @@ extern const unsigned char scsi_command_size[8];
32extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE]; 32extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE];
33 33
34/* 34/*
35 * Special value for scanning to specify scanning or rescanning of all
36 * possible channels, (target) ids, or luns on a given shost.
37 */
38#define SCAN_WILD_CARD ~0
39
40/*
35 * SCSI opcodes 41 * SCSI opcodes
36 */ 42 */
37 43
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index 41cfc29be899..7529f4388bb4 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -151,6 +151,5 @@ extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, gfp_t);
151extern void scsi_put_command(struct scsi_cmnd *); 151extern void scsi_put_command(struct scsi_cmnd *);
152extern void scsi_io_completion(struct scsi_cmnd *, unsigned int, unsigned int); 152extern void scsi_io_completion(struct scsi_cmnd *, unsigned int, unsigned int);
153extern void scsi_finish_command(struct scsi_cmnd *cmd); 153extern void scsi_finish_command(struct scsi_cmnd *cmd);
154extern void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd);
155 154
156#endif /* _SCSI_SCSI_CMND_H */ 155#endif /* _SCSI_SCSI_CMND_H */
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 230bc55c0bfa..467274a764d1 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -5,6 +5,7 @@
5#include <linux/list.h> 5#include <linux/list.h>
6#include <linux/types.h> 6#include <linux/types.h>
7#include <linux/workqueue.h> 7#include <linux/workqueue.h>
8#include <linux/mutex.h>
8 9
9struct block_device; 10struct block_device;
10struct completion; 11struct completion;
@@ -469,7 +470,7 @@ struct Scsi_Host {
469 spinlock_t default_lock; 470 spinlock_t default_lock;
470 spinlock_t *host_lock; 471 spinlock_t *host_lock;
471 472
472 struct semaphore scan_mutex;/* serialize scanning activity */ 473 struct mutex scan_mutex;/* serialize scanning activity */
473 474
474 struct list_head eh_cmd_q; 475 struct list_head eh_cmd_q;
475 struct task_struct * ehandler; /* Error recovery thread. */ 476 struct task_struct * ehandler; /* Error recovery thread. */
diff --git a/include/scsi/scsi_transport.h b/include/scsi/scsi_transport.h
index f6e0bb484c63..e7b1054adf86 100644
--- a/include/scsi/scsi_transport.h
+++ b/include/scsi/scsi_transport.h
@@ -30,12 +30,9 @@ struct scsi_transport_template {
30 struct transport_container device_attrs; 30 struct transport_container device_attrs;
31 31
32 /* 32 /*
33 * If set, call target_parent prior to allocating a scsi_target, 33 * If set, called from sysfs and legacy procfs rescanning code.
34 * so we get the appropriate parent for the target. This function
35 * is required for transports like FC and iSCSI that do not put the
36 * scsi_target under scsi_host.
37 */ 34 */
38 struct device *(*target_parent)(struct Scsi_Host *, int, uint); 35 int (*user_scan)(struct Scsi_Host *, uint, uint, uint);
39 36
40 /* The size of the specific transport attribute structure (a 37 /* The size of the specific transport attribute structure (a
41 * space of this size will be left at the end of the 38 * space of this size will be left at the end of the
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index 394f14a5b7cb..cf3fec8be1e3 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -303,6 +303,7 @@ struct fc_host_attrs {
303 /* Fixed Attributes */ 303 /* Fixed Attributes */
304 u64 node_name; 304 u64 node_name;
305 u64 port_name; 305 u64 port_name;
306 u64 permanent_port_name;
306 u32 supported_classes; 307 u32 supported_classes;
307 u8 supported_fc4s[FC_FC4_LIST_SIZE]; 308 u8 supported_fc4s[FC_FC4_LIST_SIZE];
308 char symbolic_name[FC_SYMBOLIC_NAME_SIZE]; 309 char symbolic_name[FC_SYMBOLIC_NAME_SIZE];
@@ -338,6 +339,8 @@ struct fc_host_attrs {
338 (((struct fc_host_attrs *)(x)->shost_data)->node_name) 339 (((struct fc_host_attrs *)(x)->shost_data)->node_name)
339#define fc_host_port_name(x) \ 340#define fc_host_port_name(x) \
340 (((struct fc_host_attrs *)(x)->shost_data)->port_name) 341 (((struct fc_host_attrs *)(x)->shost_data)->port_name)
342#define fc_host_permanent_port_name(x) \
343 (((struct fc_host_attrs *)(x)->shost_data)->permanent_port_name)
341#define fc_host_supported_classes(x) \ 344#define fc_host_supported_classes(x) \
342 (((struct fc_host_attrs *)(x)->shost_data)->supported_classes) 345 (((struct fc_host_attrs *)(x)->shost_data)->supported_classes)
343#define fc_host_supported_fc4s(x) \ 346#define fc_host_supported_fc4s(x) \
@@ -426,6 +429,7 @@ struct fc_function_template {
426 /* host fixed attributes */ 429 /* host fixed attributes */
427 unsigned long show_host_node_name:1; 430 unsigned long show_host_node_name:1;
428 unsigned long show_host_port_name:1; 431 unsigned long show_host_port_name:1;
432 unsigned long show_host_permanent_port_name:1;
429 unsigned long show_host_supported_classes:1; 433 unsigned long show_host_supported_classes:1;
430 unsigned long show_host_supported_fc4s:1; 434 unsigned long show_host_supported_fc4s:1;
431 unsigned long show_host_symbolic_name:1; 435 unsigned long show_host_symbolic_name:1;
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
index f25041c386ec..16602a547a63 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -23,8 +23,14 @@
23#ifndef SCSI_TRANSPORT_ISCSI_H 23#ifndef SCSI_TRANSPORT_ISCSI_H
24#define SCSI_TRANSPORT_ISCSI_H 24#define SCSI_TRANSPORT_ISCSI_H
25 25
26#include <linux/device.h>
26#include <scsi/iscsi_if.h> 27#include <scsi/iscsi_if.h>
27 28
29struct scsi_transport_template;
30struct Scsi_Host;
31struct mempool_zone;
32struct iscsi_cls_conn;
33
28/** 34/**
29 * struct iscsi_transport - iSCSI Transport template 35 * struct iscsi_transport - iSCSI Transport template
30 * 36 *
@@ -48,23 +54,31 @@ struct iscsi_transport {
48 char *name; 54 char *name;
49 unsigned int caps; 55 unsigned int caps;
50 struct scsi_host_template *host_template; 56 struct scsi_host_template *host_template;
57 /* LLD session/scsi_host data size */
51 int hostdata_size; 58 int hostdata_size;
59 /* LLD iscsi_host data size */
60 int ihostdata_size;
61 /* LLD connection data size */
62 int conndata_size;
52 int max_lun; 63 int max_lun;
53 unsigned int max_conn; 64 unsigned int max_conn;
54 unsigned int max_cmd_len; 65 unsigned int max_cmd_len;
55 iscsi_sessionh_t (*create_session) (uint32_t initial_cmdsn, 66 struct Scsi_Host *(*create_session) (struct scsi_transport_template *t,
56 struct Scsi_Host *shost); 67 uint32_t initial_cmdsn);
57 void (*destroy_session) (iscsi_sessionh_t session); 68 void (*destroy_session) (struct Scsi_Host *shost);
58 iscsi_connh_t (*create_conn) (iscsi_sessionh_t session, uint32_t cid); 69 struct iscsi_cls_conn *(*create_conn) (struct Scsi_Host *shost,
70 uint32_t cid);
59 int (*bind_conn) (iscsi_sessionh_t session, iscsi_connh_t conn, 71 int (*bind_conn) (iscsi_sessionh_t session, iscsi_connh_t conn,
60 uint32_t transport_fd, int is_leading); 72 uint32_t transport_fd, int is_leading);
61 int (*start_conn) (iscsi_connh_t conn); 73 int (*start_conn) (iscsi_connh_t conn);
62 void (*stop_conn) (iscsi_connh_t conn, int flag); 74 void (*stop_conn) (iscsi_connh_t conn, int flag);
63 void (*destroy_conn) (iscsi_connh_t conn); 75 void (*destroy_conn) (struct iscsi_cls_conn *conn);
64 int (*set_param) (iscsi_connh_t conn, enum iscsi_param param, 76 int (*set_param) (iscsi_connh_t conn, enum iscsi_param param,
65 uint32_t value); 77 uint32_t value);
66 int (*get_param) (iscsi_connh_t conn, enum iscsi_param param, 78 int (*get_conn_param) (void *conndata, enum iscsi_param param,
67 uint32_t *value); 79 uint32_t *value);
80 int (*get_session_param) (struct Scsi_Host *shost,
81 enum iscsi_param param, uint32_t *value);
68 int (*send_pdu) (iscsi_connh_t conn, struct iscsi_hdr *hdr, 82 int (*send_pdu) (iscsi_connh_t conn, struct iscsi_hdr *hdr,
69 char *data, uint32_t data_size); 83 char *data, uint32_t data_size);
70 void (*get_stats) (iscsi_connh_t conn, struct iscsi_stats *stats); 84 void (*get_stats) (iscsi_connh_t conn, struct iscsi_stats *stats);
@@ -73,7 +87,7 @@ struct iscsi_transport {
73/* 87/*
74 * transport registration upcalls 88 * transport registration upcalls
75 */ 89 */
76extern int iscsi_register_transport(struct iscsi_transport *tt); 90extern struct scsi_transport_template *iscsi_register_transport(struct iscsi_transport *tt);
77extern int iscsi_unregister_transport(struct iscsi_transport *tt); 91extern int iscsi_unregister_transport(struct iscsi_transport *tt);
78 92
79/* 93/*
@@ -83,4 +97,49 @@ extern void iscsi_conn_error(iscsi_connh_t conn, enum iscsi_err error);
83extern int iscsi_recv_pdu(iscsi_connh_t conn, struct iscsi_hdr *hdr, 97extern int iscsi_recv_pdu(iscsi_connh_t conn, struct iscsi_hdr *hdr,
84 char *data, uint32_t data_size); 98 char *data, uint32_t data_size);
85 99
100struct iscsi_cls_conn {
101 struct list_head conn_list; /* item in connlist */
102 void *dd_data; /* LLD private data */
103 struct iscsi_transport *transport;
104 iscsi_connh_t connh;
105 int active; /* must be accessed with the connlock */
106 struct device dev; /* sysfs transport/container device */
107 struct mempool_zone *z_error;
108 struct mempool_zone *z_pdu;
109 struct list_head freequeue;
110};
111
112#define iscsi_dev_to_conn(_dev) \
113 container_of(_dev, struct iscsi_cls_conn, dev)
114
115struct iscsi_cls_session {
116 struct list_head list; /* item in session_list */
117 struct iscsi_transport *transport;
118 struct device dev; /* sysfs transport/container device */
119};
120
121#define iscsi_dev_to_session(_dev) \
122 container_of(_dev, struct iscsi_cls_session, dev)
123
124#define iscsi_session_to_shost(_session) \
125 dev_to_shost(_session->dev.parent)
126
127/*
128 * session and connection functions that can be used by HW iSCSI LLDs
129 */
130extern struct iscsi_cls_session *iscsi_create_session(struct Scsi_Host *shost,
131 struct iscsi_transport *t);
132extern int iscsi_destroy_session(struct iscsi_cls_session *session);
133extern struct iscsi_cls_conn *iscsi_create_conn(struct iscsi_cls_session *sess,
134 uint32_t cid);
135extern int iscsi_destroy_conn(struct iscsi_cls_conn *conn);
136
137/*
138 * session functions used by software iscsi
139 */
140extern struct Scsi_Host *
141iscsi_transport_create_session(struct scsi_transport_template *scsit,
142 struct iscsi_transport *transport);
143extern int iscsi_transport_destroy_session(struct Scsi_Host *shost);
144
86#endif 145#endif
diff --git a/include/scsi/scsi_transport_spi.h b/include/scsi/scsi_transport_spi.h
index 54a89611e9c5..2b5930ba69ec 100644
--- a/include/scsi/scsi_transport_spi.h
+++ b/include/scsi/scsi_transport_spi.h
@@ -54,7 +54,7 @@ struct spi_transport_attrs {
54 unsigned int support_qas; /* supports quick arbitration and selection */ 54 unsigned int support_qas; /* supports quick arbitration and selection */
55 /* Private Fields */ 55 /* Private Fields */
56 unsigned int dv_pending:1; /* Internal flag */ 56 unsigned int dv_pending:1; /* Internal flag */
57 struct semaphore dv_sem; /* semaphore to serialise dv */ 57 struct mutex dv_mutex; /* semaphore to serialise dv */
58}; 58};
59 59
60enum spi_signal_type { 60enum spi_signal_type {
diff --git a/init/main.c b/init/main.c
index e092b1979a90..7c79da57d3a2 100644
--- a/init/main.c
+++ b/init/main.c
@@ -54,20 +54,18 @@
54#include <asm/sections.h> 54#include <asm/sections.h>
55#include <asm/cacheflush.h> 55#include <asm/cacheflush.h>
56 56
57/*
58 * This is one of the first .c files built. Error out early
59 * if we have compiler trouble..
60 */
61
62#ifdef CONFIG_X86_LOCAL_APIC 57#ifdef CONFIG_X86_LOCAL_APIC
63#include <asm/smp.h> 58#include <asm/smp.h>
64#endif 59#endif
65 60
66/* 61/*
67 * Versions of gcc older than that listed below may actually compile 62 * This is one of the first .c files built. Error out early if we have compiler
68 * and link okay, but the end product can have subtle run time bugs. 63 * trouble.
69 * To avoid associated bogus bug reports, we flatly refuse to compile 64 *
70 * with a gcc that is known to be too old from the very beginning. 65 * Versions of gcc older than that listed below may actually compile and link
66 * okay, but the end product can have subtle run time bugs. To avoid associated
67 * bogus bug reports, we flatly refuse to compile with a gcc that is known to be
68 * too old from the very beginning.
71 */ 69 */
72#if (__GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 2) 70#if (__GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 2)
73#error Sorry, your GCC is too old. It builds incorrect kernels. 71#error Sorry, your GCC is too old. It builds incorrect kernels.
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 4e776f9c80e7..59302fc3643b 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -599,15 +599,16 @@ static int mq_attr_ok(struct mq_attr *attr)
599static struct file *do_create(struct dentry *dir, struct dentry *dentry, 599static struct file *do_create(struct dentry *dir, struct dentry *dentry,
600 int oflag, mode_t mode, struct mq_attr __user *u_attr) 600 int oflag, mode_t mode, struct mq_attr __user *u_attr)
601{ 601{
602 struct file *filp;
603 struct mq_attr attr; 602 struct mq_attr attr;
604 int ret; 603 int ret;
605 604
606 if (u_attr != NULL) { 605 if (u_attr) {
606 ret = -EFAULT;
607 if (copy_from_user(&attr, u_attr, sizeof(attr))) 607 if (copy_from_user(&attr, u_attr, sizeof(attr)))
608 return ERR_PTR(-EFAULT); 608 goto out;
609 ret = -EINVAL;
609 if (!mq_attr_ok(&attr)) 610 if (!mq_attr_ok(&attr))
610 return ERR_PTR(-EINVAL); 611 goto out;
611 /* store for use during create */ 612 /* store for use during create */
612 dentry->d_fsdata = &attr; 613 dentry->d_fsdata = &attr;
613 } 614 }
@@ -616,13 +617,14 @@ static struct file *do_create(struct dentry *dir, struct dentry *dentry,
616 ret = vfs_create(dir->d_inode, dentry, mode, NULL); 617 ret = vfs_create(dir->d_inode, dentry, mode, NULL);
617 dentry->d_fsdata = NULL; 618 dentry->d_fsdata = NULL;
618 if (ret) 619 if (ret)
619 return ERR_PTR(ret); 620 goto out;
620 621
621 filp = dentry_open(dentry, mqueue_mnt, oflag); 622 return dentry_open(dentry, mqueue_mnt, oflag);
622 if (!IS_ERR(filp))
623 dget(dentry);
624 623
625 return filp; 624out:
625 dput(dentry);
626 mntput(mqueue_mnt);
627 return ERR_PTR(ret);
626} 628}
627 629
628/* Opens existing queue */ 630/* Opens existing queue */
@@ -630,20 +632,20 @@ static struct file *do_open(struct dentry *dentry, int oflag)
630{ 632{
631static int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE, 633static int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE,
632 MAY_READ | MAY_WRITE }; 634 MAY_READ | MAY_WRITE };
633 struct file *filp;
634 635
635 if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) 636 if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) {
637 dput(dentry);
638 mntput(mqueue_mnt);
636 return ERR_PTR(-EINVAL); 639 return ERR_PTR(-EINVAL);
640 }
637 641
638 if (permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE], NULL)) 642 if (permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE], NULL)) {
643 dput(dentry);
644 mntput(mqueue_mnt);
639 return ERR_PTR(-EACCES); 645 return ERR_PTR(-EACCES);
646 }
640 647
641 filp = dentry_open(dentry, mqueue_mnt, oflag); 648 return dentry_open(dentry, mqueue_mnt, oflag);
642
643 if (!IS_ERR(filp))
644 dget(dentry);
645
646 return filp;
647} 649}
648 650
649asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, 651asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
@@ -671,17 +673,20 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
671 673
672 if (oflag & O_CREAT) { 674 if (oflag & O_CREAT) {
673 if (dentry->d_inode) { /* entry already exists */ 675 if (dentry->d_inode) { /* entry already exists */
674 filp = (oflag & O_EXCL) ? ERR_PTR(-EEXIST) : 676 error = -EEXIST;
675 do_open(dentry, oflag); 677 if (oflag & O_EXCL)
678 goto out;
679 filp = do_open(dentry, oflag);
676 } else { 680 } else {
677 filp = do_create(mqueue_mnt->mnt_root, dentry, 681 filp = do_create(mqueue_mnt->mnt_root, dentry,
678 oflag, mode, u_attr); 682 oflag, mode, u_attr);
679 } 683 }
680 } else 684 } else {
681 filp = (dentry->d_inode) ? do_open(dentry, oflag) : 685 error = -ENOENT;
682 ERR_PTR(-ENOENT); 686 if (!dentry->d_inode)
683 687 goto out;
684 dput(dentry); 688 filp = do_open(dentry, oflag);
689 }
685 690
686 if (IS_ERR(filp)) { 691 if (IS_ERR(filp)) {
687 error = PTR_ERR(filp); 692 error = PTR_ERR(filp);
@@ -692,8 +697,10 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
692 fd_install(fd, filp); 697 fd_install(fd, filp);
693 goto out_upsem; 698 goto out_upsem;
694 699
695out_putfd: 700out:
701 dput(dentry);
696 mntput(mqueue_mnt); 702 mntput(mqueue_mnt);
703out_putfd:
697 put_unused_fd(fd); 704 put_unused_fd(fd);
698out_err: 705out_err:
699 fd = error; 706 fd = error;
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 2a75e44e1a41..fe2f71f92ae0 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -1554,7 +1554,7 @@ struct ctr_struct {
1554 * when reading out p->cpuset, as we don't really care if it changes 1554 * when reading out p->cpuset, as we don't really care if it changes
1555 * on the next cycle, and we are not going to try to dereference it. 1555 * on the next cycle, and we are not going to try to dereference it.
1556 */ 1556 */
1557static inline int pid_array_load(pid_t *pidarray, int npids, struct cpuset *cs) 1557static int pid_array_load(pid_t *pidarray, int npids, struct cpuset *cs)
1558{ 1558{
1559 int n = 0; 1559 int n = 0;
1560 struct task_struct *g, *p; 1560 struct task_struct *g, *p;
@@ -2150,6 +2150,33 @@ int __cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask)
2150} 2150}
2151 2151
2152/** 2152/**
2153 * cpuset_lock - lock out any changes to cpuset structures
2154 *
2155 * The out of memory (oom) code needs to lock down cpusets
2156 * from being changed while it scans the tasklist looking for a
2157 * task in an overlapping cpuset. Expose callback_sem via this
2158 * cpuset_lock() routine, so the oom code can lock it, before
2159 * locking the task list. The tasklist_lock is a spinlock, so
2160 * must be taken inside callback_sem.
2161 */
2162
2163void cpuset_lock(void)
2164{
2165 down(&callback_sem);
2166}
2167
2168/**
2169 * cpuset_unlock - release lock on cpuset changes
2170 *
2171 * Undo the lock taken in a previous cpuset_lock() call.
2172 */
2173
2174void cpuset_unlock(void)
2175{
2176 up(&callback_sem);
2177}
2178
2179/**
2153 * cpuset_excl_nodes_overlap - Do we overlap @p's mem_exclusive ancestors? 2180 * cpuset_excl_nodes_overlap - Do we overlap @p's mem_exclusive ancestors?
2154 * @p: pointer to task_struct of some other task. 2181 * @p: pointer to task_struct of some other task.
2155 * 2182 *
@@ -2158,7 +2185,7 @@ int __cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask)
2158 * determine if task @p's memory usage might impact the memory 2185 * determine if task @p's memory usage might impact the memory
2159 * available to the current task. 2186 * available to the current task.
2160 * 2187 *
2161 * Acquires callback_sem - not suitable for calling from a fast path. 2188 * Call while holding callback_sem.
2162 **/ 2189 **/
2163 2190
2164int cpuset_excl_nodes_overlap(const struct task_struct *p) 2191int cpuset_excl_nodes_overlap(const struct task_struct *p)
@@ -2166,8 +2193,6 @@ int cpuset_excl_nodes_overlap(const struct task_struct *p)
2166 const struct cpuset *cs1, *cs2; /* my and p's cpuset ancestors */ 2193 const struct cpuset *cs1, *cs2; /* my and p's cpuset ancestors */
2167 int overlap = 0; /* do cpusets overlap? */ 2194 int overlap = 0; /* do cpusets overlap? */
2168 2195
2169 down(&callback_sem);
2170
2171 task_lock(current); 2196 task_lock(current);
2172 if (current->flags & PF_EXITING) { 2197 if (current->flags & PF_EXITING) {
2173 task_unlock(current); 2198 task_unlock(current);
@@ -2186,8 +2211,6 @@ int cpuset_excl_nodes_overlap(const struct task_struct *p)
2186 2211
2187 overlap = nodes_intersects(cs1->mems_allowed, cs2->mems_allowed); 2212 overlap = nodes_intersects(cs1->mems_allowed, cs2->mems_allowed);
2188done: 2213done:
2189 up(&callback_sem);
2190
2191 return overlap; 2214 return overlap;
2192} 2215}
2193 2216
diff --git a/kernel/exit.c b/kernel/exit.c
index f8e609ff1893..93cee3671332 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -193,7 +193,7 @@ int is_orphaned_pgrp(int pgrp)
193 return retval; 193 return retval;
194} 194}
195 195
196static inline int has_stopped_jobs(int pgrp) 196static int has_stopped_jobs(int pgrp)
197{ 197{
198 int retval = 0; 198 int retval = 0;
199 struct task_struct *p; 199 struct task_struct *p;
@@ -230,7 +230,7 @@ static inline int has_stopped_jobs(int pgrp)
230 * 230 *
231 * NOTE that reparent_to_init() gives the caller full capabilities. 231 * NOTE that reparent_to_init() gives the caller full capabilities.
232 */ 232 */
233static inline void reparent_to_init(void) 233static void reparent_to_init(void)
234{ 234{
235 write_lock_irq(&tasklist_lock); 235 write_lock_irq(&tasklist_lock);
236 236
@@ -244,7 +244,9 @@ static inline void reparent_to_init(void)
244 /* Set the exit signal to SIGCHLD so we signal init on exit */ 244 /* Set the exit signal to SIGCHLD so we signal init on exit */
245 current->exit_signal = SIGCHLD; 245 current->exit_signal = SIGCHLD;
246 246
247 if ((current->policy == SCHED_NORMAL) && (task_nice(current) < 0)) 247 if ((current->policy == SCHED_NORMAL ||
248 current->policy == SCHED_BATCH)
249 && (task_nice(current) < 0))
248 set_user_nice(current, 0); 250 set_user_nice(current, 0);
249 /* cpus_allowed? */ 251 /* cpus_allowed? */
250 /* rt_priority? */ 252 /* rt_priority? */
@@ -367,7 +369,7 @@ void daemonize(const char *name, ...)
367 369
368EXPORT_SYMBOL(daemonize); 370EXPORT_SYMBOL(daemonize);
369 371
370static inline void close_files(struct files_struct * files) 372static void close_files(struct files_struct * files)
371{ 373{
372 int i, j; 374 int i, j;
373 struct fdtable *fdt; 375 struct fdtable *fdt;
@@ -541,7 +543,7 @@ static inline void choose_new_parent(task_t *p, task_t *reaper, task_t *child_re
541 p->real_parent = reaper; 543 p->real_parent = reaper;
542} 544}
543 545
544static inline void reparent_thread(task_t *p, task_t *father, int traced) 546static void reparent_thread(task_t *p, task_t *father, int traced)
545{ 547{
546 /* We don't want people slaying init. */ 548 /* We don't want people slaying init. */
547 if (p->exit_signal != -1) 549 if (p->exit_signal != -1)
@@ -605,7 +607,7 @@ static inline void reparent_thread(task_t *p, task_t *father, int traced)
605 * group, and if no such member exists, give it to 607 * group, and if no such member exists, give it to
606 * the global child reaper process (ie "init") 608 * the global child reaper process (ie "init")
607 */ 609 */
608static inline void forget_original_parent(struct task_struct * father, 610static void forget_original_parent(struct task_struct * father,
609 struct list_head *to_release) 611 struct list_head *to_release)
610{ 612{
611 struct task_struct *p, *reaper = father; 613 struct task_struct *p, *reaper = father;
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
index 9e66e614862a..197208b3aa2a 100644
--- a/kernel/posix-timers.c
+++ b/kernel/posix-timers.c
@@ -192,7 +192,7 @@ static inline int common_clock_set(const clockid_t which_clock,
192 return do_sys_settimeofday(tp, NULL); 192 return do_sys_settimeofday(tp, NULL);
193} 193}
194 194
195static inline int common_timer_create(struct k_itimer *new_timer) 195static int common_timer_create(struct k_itimer *new_timer)
196{ 196{
197 hrtimer_init(&new_timer->it.real.timer, new_timer->it_clock); 197 hrtimer_init(&new_timer->it.real.timer, new_timer->it_clock);
198 new_timer->it.real.timer.data = new_timer; 198 new_timer->it.real.timer.data = new_timer;
@@ -361,7 +361,7 @@ static int posix_timer_fn(void *data)
361 return ret; 361 return ret;
362} 362}
363 363
364static inline struct task_struct * good_sigevent(sigevent_t * event) 364static struct task_struct * good_sigevent(sigevent_t * event)
365{ 365{
366 struct task_struct *rtn = current->group_leader; 366 struct task_struct *rtn = current->group_leader;
367 367
@@ -687,7 +687,7 @@ sys_timer_getoverrun(timer_t timer_id)
687 687
688/* Set a POSIX.1b interval timer. */ 688/* Set a POSIX.1b interval timer. */
689/* timr->it_lock is taken. */ 689/* timr->it_lock is taken. */
690static inline int 690static int
691common_timer_set(struct k_itimer *timr, int flags, 691common_timer_set(struct k_itimer *timr, int flags,
692 struct itimerspec *new_setting, struct itimerspec *old_setting) 692 struct itimerspec *new_setting, struct itimerspec *old_setting)
693{ 693{
@@ -829,7 +829,7 @@ retry_delete:
829/* 829/*
830 * return timer owned by the process, used by exit_itimers 830 * return timer owned by the process, used by exit_itimers
831 */ 831 */
832static inline void itimer_delete(struct k_itimer *timer) 832static void itimer_delete(struct k_itimer *timer)
833{ 833{
834 unsigned long flags; 834 unsigned long flags;
835 835
diff --git a/kernel/sched.c b/kernel/sched.c
index c9dec2aa1976..788ecce1e0e4 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -521,7 +521,7 @@ static inline void sched_info_dequeued(task_t *t)
521 * long it was waiting to run. We also note when it began so that we 521 * long it was waiting to run. We also note when it began so that we
522 * can keep stats on how long its timeslice is. 522 * can keep stats on how long its timeslice is.
523 */ 523 */
524static inline void sched_info_arrive(task_t *t) 524static void sched_info_arrive(task_t *t)
525{ 525{
526 unsigned long now = jiffies, diff = 0; 526 unsigned long now = jiffies, diff = 0;
527 struct runqueue *rq = task_rq(t); 527 struct runqueue *rq = task_rq(t);
@@ -748,10 +748,14 @@ static int recalc_task_prio(task_t *p, unsigned long long now)
748 unsigned long long __sleep_time = now - p->timestamp; 748 unsigned long long __sleep_time = now - p->timestamp;
749 unsigned long sleep_time; 749 unsigned long sleep_time;
750 750
751 if (__sleep_time > NS_MAX_SLEEP_AVG) 751 if (unlikely(p->policy == SCHED_BATCH))
752 sleep_time = NS_MAX_SLEEP_AVG; 752 sleep_time = 0;
753 else 753 else {
754 sleep_time = (unsigned long)__sleep_time; 754 if (__sleep_time > NS_MAX_SLEEP_AVG)
755 sleep_time = NS_MAX_SLEEP_AVG;
756 else
757 sleep_time = (unsigned long)__sleep_time;
758 }
755 759
756 if (likely(sleep_time > 0)) { 760 if (likely(sleep_time > 0)) {
757 /* 761 /*
@@ -1003,7 +1007,7 @@ void kick_process(task_t *p)
1003 * We want to under-estimate the load of migration sources, to 1007 * We want to under-estimate the load of migration sources, to
1004 * balance conservatively. 1008 * balance conservatively.
1005 */ 1009 */
1006static inline unsigned long __source_load(int cpu, int type, enum idle_type idle) 1010static unsigned long __source_load(int cpu, int type, enum idle_type idle)
1007{ 1011{
1008 runqueue_t *rq = cpu_rq(cpu); 1012 runqueue_t *rq = cpu_rq(cpu);
1009 unsigned long running = rq->nr_running; 1013 unsigned long running = rq->nr_running;
@@ -1866,7 +1870,7 @@ void sched_exec(void)
1866 * pull_task - move a task from a remote runqueue to the local runqueue. 1870 * pull_task - move a task from a remote runqueue to the local runqueue.
1867 * Both runqueues must be locked. 1871 * Both runqueues must be locked.
1868 */ 1872 */
1869static inline 1873static
1870void pull_task(runqueue_t *src_rq, prio_array_t *src_array, task_t *p, 1874void pull_task(runqueue_t *src_rq, prio_array_t *src_array, task_t *p,
1871 runqueue_t *this_rq, prio_array_t *this_array, int this_cpu) 1875 runqueue_t *this_rq, prio_array_t *this_array, int this_cpu)
1872{ 1876{
@@ -1888,7 +1892,7 @@ void pull_task(runqueue_t *src_rq, prio_array_t *src_array, task_t *p,
1888/* 1892/*
1889 * can_migrate_task - may task p from runqueue rq be migrated to this_cpu? 1893 * can_migrate_task - may task p from runqueue rq be migrated to this_cpu?
1890 */ 1894 */
1891static inline 1895static
1892int can_migrate_task(task_t *p, runqueue_t *rq, int this_cpu, 1896int can_migrate_task(task_t *p, runqueue_t *rq, int this_cpu,
1893 struct sched_domain *sd, enum idle_type idle, 1897 struct sched_domain *sd, enum idle_type idle,
1894 int *all_pinned) 1898 int *all_pinned)
@@ -2374,7 +2378,7 @@ out_balanced:
2374 * idle_balance is called by schedule() if this_cpu is about to become 2378 * idle_balance is called by schedule() if this_cpu is about to become
2375 * idle. Attempts to pull tasks from other CPUs. 2379 * idle. Attempts to pull tasks from other CPUs.
2376 */ 2380 */
2377static inline void idle_balance(int this_cpu, runqueue_t *this_rq) 2381static void idle_balance(int this_cpu, runqueue_t *this_rq)
2378{ 2382{
2379 struct sched_domain *sd; 2383 struct sched_domain *sd;
2380 2384
@@ -2758,7 +2762,7 @@ static inline void wakeup_busy_runqueue(runqueue_t *rq)
2758 resched_task(rq->idle); 2762 resched_task(rq->idle);
2759} 2763}
2760 2764
2761static inline void wake_sleeping_dependent(int this_cpu, runqueue_t *this_rq) 2765static void wake_sleeping_dependent(int this_cpu, runqueue_t *this_rq)
2762{ 2766{
2763 struct sched_domain *tmp, *sd = NULL; 2767 struct sched_domain *tmp, *sd = NULL;
2764 cpumask_t sibling_map; 2768 cpumask_t sibling_map;
@@ -2812,7 +2816,7 @@ static inline unsigned long smt_slice(task_t *p, struct sched_domain *sd)
2812 return p->time_slice * (100 - sd->per_cpu_gain) / 100; 2816 return p->time_slice * (100 - sd->per_cpu_gain) / 100;
2813} 2817}
2814 2818
2815static inline int dependent_sleeper(int this_cpu, runqueue_t *this_rq) 2819static int dependent_sleeper(int this_cpu, runqueue_t *this_rq)
2816{ 2820{
2817 struct sched_domain *tmp, *sd = NULL; 2821 struct sched_domain *tmp, *sd = NULL;
2818 cpumask_t sibling_map; 2822 cpumask_t sibling_map;
@@ -3560,7 +3564,7 @@ void set_user_nice(task_t *p, long nice)
3560 * The RT priorities are set via sched_setscheduler(), but we still 3564 * The RT priorities are set via sched_setscheduler(), but we still
3561 * allow the 'normal' nice value to be set - but as expected 3565 * allow the 'normal' nice value to be set - but as expected
3562 * it wont have any effect on scheduling until the task is 3566 * it wont have any effect on scheduling until the task is
3563 * not SCHED_NORMAL: 3567 * not SCHED_NORMAL/SCHED_BATCH:
3564 */ 3568 */
3565 if (rt_task(p)) { 3569 if (rt_task(p)) {
3566 p->static_prio = NICE_TO_PRIO(nice); 3570 p->static_prio = NICE_TO_PRIO(nice);
@@ -3706,10 +3710,16 @@ static void __setscheduler(struct task_struct *p, int policy, int prio)
3706 BUG_ON(p->array); 3710 BUG_ON(p->array);
3707 p->policy = policy; 3711 p->policy = policy;
3708 p->rt_priority = prio; 3712 p->rt_priority = prio;
3709 if (policy != SCHED_NORMAL) 3713 if (policy != SCHED_NORMAL && policy != SCHED_BATCH) {
3710 p->prio = MAX_RT_PRIO-1 - p->rt_priority; 3714 p->prio = MAX_RT_PRIO-1 - p->rt_priority;
3711 else 3715 } else {
3712 p->prio = p->static_prio; 3716 p->prio = p->static_prio;
3717 /*
3718 * SCHED_BATCH tasks are treated as perpetual CPU hogs:
3719 */
3720 if (policy == SCHED_BATCH)
3721 p->sleep_avg = 0;
3722 }
3713} 3723}
3714 3724
3715/** 3725/**
@@ -3733,29 +3743,35 @@ recheck:
3733 if (policy < 0) 3743 if (policy < 0)
3734 policy = oldpolicy = p->policy; 3744 policy = oldpolicy = p->policy;
3735 else if (policy != SCHED_FIFO && policy != SCHED_RR && 3745 else if (policy != SCHED_FIFO && policy != SCHED_RR &&
3736 policy != SCHED_NORMAL) 3746 policy != SCHED_NORMAL && policy != SCHED_BATCH)
3737 return -EINVAL; 3747 return -EINVAL;
3738 /* 3748 /*
3739 * Valid priorities for SCHED_FIFO and SCHED_RR are 3749 * Valid priorities for SCHED_FIFO and SCHED_RR are
3740 * 1..MAX_USER_RT_PRIO-1, valid priority for SCHED_NORMAL is 0. 3750 * 1..MAX_USER_RT_PRIO-1, valid priority for SCHED_NORMAL and
3751 * SCHED_BATCH is 0.
3741 */ 3752 */
3742 if (param->sched_priority < 0 || 3753 if (param->sched_priority < 0 ||
3743 (p->mm && param->sched_priority > MAX_USER_RT_PRIO-1) || 3754 (p->mm && param->sched_priority > MAX_USER_RT_PRIO-1) ||
3744 (!p->mm && param->sched_priority > MAX_RT_PRIO-1)) 3755 (!p->mm && param->sched_priority > MAX_RT_PRIO-1))
3745 return -EINVAL; 3756 return -EINVAL;
3746 if ((policy == SCHED_NORMAL) != (param->sched_priority == 0)) 3757 if ((policy == SCHED_NORMAL || policy == SCHED_BATCH)
3758 != (param->sched_priority == 0))
3747 return -EINVAL; 3759 return -EINVAL;
3748 3760
3749 /* 3761 /*
3750 * Allow unprivileged RT tasks to decrease priority: 3762 * Allow unprivileged RT tasks to decrease priority:
3751 */ 3763 */
3752 if (!capable(CAP_SYS_NICE)) { 3764 if (!capable(CAP_SYS_NICE)) {
3753 /* can't change policy */ 3765 /*
3754 if (policy != p->policy && 3766 * can't change policy, except between SCHED_NORMAL
3755 !p->signal->rlim[RLIMIT_RTPRIO].rlim_cur) 3767 * and SCHED_BATCH:
3768 */
3769 if (((policy != SCHED_NORMAL && p->policy != SCHED_BATCH) &&
3770 (policy != SCHED_BATCH && p->policy != SCHED_NORMAL)) &&
3771 !p->signal->rlim[RLIMIT_RTPRIO].rlim_cur)
3756 return -EPERM; 3772 return -EPERM;
3757 /* can't increase priority */ 3773 /* can't increase priority */
3758 if (policy != SCHED_NORMAL && 3774 if ((policy != SCHED_NORMAL && policy != SCHED_BATCH) &&
3759 param->sched_priority > p->rt_priority && 3775 param->sched_priority > p->rt_priority &&
3760 param->sched_priority > 3776 param->sched_priority >
3761 p->signal->rlim[RLIMIT_RTPRIO].rlim_cur) 3777 p->signal->rlim[RLIMIT_RTPRIO].rlim_cur)
@@ -4233,6 +4249,7 @@ asmlinkage long sys_sched_get_priority_max(int policy)
4233 ret = MAX_USER_RT_PRIO-1; 4249 ret = MAX_USER_RT_PRIO-1;
4234 break; 4250 break;
4235 case SCHED_NORMAL: 4251 case SCHED_NORMAL:
4252 case SCHED_BATCH:
4236 ret = 0; 4253 ret = 0;
4237 break; 4254 break;
4238 } 4255 }
@@ -4256,6 +4273,7 @@ asmlinkage long sys_sched_get_priority_min(int policy)
4256 ret = 1; 4273 ret = 1;
4257 break; 4274 break;
4258 case SCHED_NORMAL: 4275 case SCHED_NORMAL:
4276 case SCHED_BATCH:
4259 ret = 0; 4277 ret = 0;
4260 } 4278 }
4261 return ret; 4279 return ret;
@@ -5990,7 +6008,7 @@ next_sg:
5990 * Detach sched domains from a group of cpus specified in cpu_map 6008 * Detach sched domains from a group of cpus specified in cpu_map
5991 * These cpus will now be attached to the NULL domain 6009 * These cpus will now be attached to the NULL domain
5992 */ 6010 */
5993static inline void detach_destroy_domains(const cpumask_t *cpu_map) 6011static void detach_destroy_domains(const cpumask_t *cpu_map)
5994{ 6012{
5995 int i; 6013 int i;
5996 6014
diff --git a/kernel/signal.c b/kernel/signal.c
index 1da2e74beb97..5dafbd36d62e 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -476,7 +476,7 @@ unblock_all_signals(void)
476 spin_unlock_irqrestore(&current->sighand->siglock, flags); 476 spin_unlock_irqrestore(&current->sighand->siglock, flags);
477} 477}
478 478
479static inline int collect_signal(int sig, struct sigpending *list, siginfo_t *info) 479static int collect_signal(int sig, struct sigpending *list, siginfo_t *info)
480{ 480{
481 struct sigqueue *q, *first = NULL; 481 struct sigqueue *q, *first = NULL;
482 int still_pending = 0; 482 int still_pending = 0;
@@ -1881,7 +1881,7 @@ do_signal_stop(int signr)
1881 * We return zero if we still hold the siglock and should look 1881 * We return zero if we still hold the siglock and should look
1882 * for another signal without checking group_stop_count again. 1882 * for another signal without checking group_stop_count again.
1883 */ 1883 */
1884static inline int handle_group_stop(void) 1884static int handle_group_stop(void)
1885{ 1885{
1886 int stop_count; 1886 int stop_count;
1887 1887
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 62d4d9566876..f5d69b6e29f5 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -648,7 +648,7 @@ static ctl_table kern_table[] = {
648 .mode = 0644, 648 .mode = 0644,
649 .proc_handler = &proc_dointvec, 649 .proc_handler = &proc_dointvec,
650 }, 650 },
651#if defined(CONFIG_S390) 651#if defined(CONFIG_S390) && defined(CONFIG_SMP)
652 { 652 {
653 .ctl_name = KERN_SPIN_RETRY, 653 .ctl_name = KERN_SPIN_RETRY,
654 .procname = "spin_retry", 654 .procname = "spin_retry",
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 82c4fa70595c..b052e2c4c710 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -147,7 +147,7 @@ int fastcall queue_delayed_work(struct workqueue_struct *wq,
147 return ret; 147 return ret;
148} 148}
149 149
150static inline void run_workqueue(struct cpu_workqueue_struct *cwq) 150static void run_workqueue(struct cpu_workqueue_struct *cwq)
151{ 151{
152 unsigned long flags; 152 unsigned long flags;
153 153
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index a609235a517f..a314e663d517 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -195,6 +195,20 @@ config FRAME_POINTER
195 some architectures or if you use external debuggers. 195 some architectures or if you use external debuggers.
196 If you don't debug the kernel, you can say N. 196 If you don't debug the kernel, you can say N.
197 197
198config FORCED_INLINING
199 bool "Force gcc to inline functions marked 'inline'"
200 depends on DEBUG_KERNEL
201 default y
202 help
203 This option determines if the kernel forces gcc to inline the functions
204 developers have marked 'inline'. Doing so takes away freedom from gcc to
205 do what it thinks is best, which is desirable for the gcc 3.x series of
206 compilers. The gcc 4.x series have a rewritten inlining algorithm and
207 disabling this option will generate a smaller kernel there. Hopefully
208 this algorithm is so good that allowing gcc4 to make the decision can
209 become the default in the future, until then this option is there to
210 test gcc for this.
211
198config RCU_TORTURE_TEST 212config RCU_TORTURE_TEST
199 tristate "torture tests for RCU" 213 tristate "torture tests for RCU"
200 depends on DEBUG_KERNEL 214 depends on DEBUG_KERNEL
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index b62cab575a84..3171f884d245 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -1359,6 +1359,30 @@ restart:
1359 return 0; 1359 return 0;
1360} 1360}
1361 1361
1362void mpol_shared_policy_init(struct shared_policy *info, int policy,
1363 nodemask_t *policy_nodes)
1364{
1365 info->root = RB_ROOT;
1366 spin_lock_init(&info->lock);
1367
1368 if (policy != MPOL_DEFAULT) {
1369 struct mempolicy *newpol;
1370
1371 /* Falls back to MPOL_DEFAULT on any error */
1372 newpol = mpol_new(policy, policy_nodes);
1373 if (!IS_ERR(newpol)) {
1374 /* Create pseudo-vma that contains just the policy */
1375 struct vm_area_struct pvma;
1376
1377 memset(&pvma, 0, sizeof(struct vm_area_struct));
1378 /* Policy covers entire file */
1379 pvma.vm_end = TASK_SIZE;
1380 mpol_set_shared_policy(info, &pvma, newpol);
1381 mpol_free(newpol);
1382 }
1383 }
1384}
1385
1362int mpol_set_shared_policy(struct shared_policy *info, 1386int mpol_set_shared_policy(struct shared_policy *info,
1363 struct vm_area_struct *vma, struct mempolicy *npol) 1387 struct vm_area_struct *vma, struct mempolicy *npol)
1364{ 1388{
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 4748b906aff2..14bd4ec79597 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -274,6 +274,7 @@ void out_of_memory(gfp_t gfp_mask, int order)
274 show_mem(); 274 show_mem();
275 } 275 }
276 276
277 cpuset_lock();
277 read_lock(&tasklist_lock); 278 read_lock(&tasklist_lock);
278retry: 279retry:
279 p = select_bad_process(); 280 p = select_bad_process();
@@ -284,6 +285,7 @@ retry:
284 /* Found nothing?!?! Either we hang forever, or we panic. */ 285 /* Found nothing?!?! Either we hang forever, or we panic. */
285 if (!p) { 286 if (!p) {
286 read_unlock(&tasklist_lock); 287 read_unlock(&tasklist_lock);
288 cpuset_unlock();
287 panic("Out of memory and no killable processes...\n"); 289 panic("Out of memory and no killable processes...\n");
288 } 290 }
289 291
@@ -293,6 +295,7 @@ retry:
293 295
294 out: 296 out:
295 read_unlock(&tasklist_lock); 297 read_unlock(&tasklist_lock);
298 cpuset_unlock();
296 if (mm) 299 if (mm)
297 mmput(mm); 300 mmput(mm);
298 301
diff --git a/mm/shmem.c b/mm/shmem.c
index 343b3c0937e5..ce501bce1c2e 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1316,7 +1316,8 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
1316 case S_IFREG: 1316 case S_IFREG:
1317 inode->i_op = &shmem_inode_operations; 1317 inode->i_op = &shmem_inode_operations;
1318 inode->i_fop = &shmem_file_operations; 1318 inode->i_fop = &shmem_file_operations;
1319 mpol_shared_policy_init(&info->policy); 1319 mpol_shared_policy_init(&info->policy, sbinfo->policy,
1320 &sbinfo->policy_nodes);
1320 break; 1321 break;
1321 case S_IFDIR: 1322 case S_IFDIR:
1322 inode->i_nlink++; 1323 inode->i_nlink++;
@@ -1330,7 +1331,8 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
1330 * Must not load anything in the rbtree, 1331 * Must not load anything in the rbtree,
1331 * mpol_free_shared_policy will not be called. 1332 * mpol_free_shared_policy will not be called.
1332 */ 1333 */
1333 mpol_shared_policy_init(&info->policy); 1334 mpol_shared_policy_init(&info->policy, MPOL_DEFAULT,
1335 NULL);
1334 break; 1336 break;
1335 } 1337 }
1336 } else if (sbinfo->max_inodes) { 1338 } else if (sbinfo->max_inodes) {
@@ -1843,7 +1845,9 @@ static struct inode_operations shmem_symlink_inode_operations = {
1843 .put_link = shmem_put_link, 1845 .put_link = shmem_put_link,
1844}; 1846};
1845 1847
1846static int shmem_parse_options(char *options, int *mode, uid_t *uid, gid_t *gid, unsigned long *blocks, unsigned long *inodes) 1848static int shmem_parse_options(char *options, int *mode, uid_t *uid,
1849 gid_t *gid, unsigned long *blocks, unsigned long *inodes,
1850 int *policy, nodemask_t *policy_nodes)
1847{ 1851{
1848 char *this_char, *value, *rest; 1852 char *this_char, *value, *rest;
1849 1853
@@ -1897,6 +1901,19 @@ static int shmem_parse_options(char *options, int *mode, uid_t *uid, gid_t *gid,
1897 *gid = simple_strtoul(value,&rest,0); 1901 *gid = simple_strtoul(value,&rest,0);
1898 if (*rest) 1902 if (*rest)
1899 goto bad_val; 1903 goto bad_val;
1904 } else if (!strcmp(this_char,"mpol")) {
1905 if (!strcmp(value,"default"))
1906 *policy = MPOL_DEFAULT;
1907 else if (!strcmp(value,"preferred"))
1908 *policy = MPOL_PREFERRED;
1909 else if (!strcmp(value,"bind"))
1910 *policy = MPOL_BIND;
1911 else if (!strcmp(value,"interleave"))
1912 *policy = MPOL_INTERLEAVE;
1913 else
1914 goto bad_val;
1915 } else if (!strcmp(this_char,"mpol_nodelist")) {
1916 nodelist_parse(value, *policy_nodes);
1900 } else { 1917 } else {
1901 printk(KERN_ERR "tmpfs: Bad mount option %s\n", 1918 printk(KERN_ERR "tmpfs: Bad mount option %s\n",
1902 this_char); 1919 this_char);
@@ -1917,12 +1934,14 @@ static int shmem_remount_fs(struct super_block *sb, int *flags, char *data)
1917 struct shmem_sb_info *sbinfo = SHMEM_SB(sb); 1934 struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
1918 unsigned long max_blocks = sbinfo->max_blocks; 1935 unsigned long max_blocks = sbinfo->max_blocks;
1919 unsigned long max_inodes = sbinfo->max_inodes; 1936 unsigned long max_inodes = sbinfo->max_inodes;
1937 int policy = sbinfo->policy;
1938 nodemask_t policy_nodes = sbinfo->policy_nodes;
1920 unsigned long blocks; 1939 unsigned long blocks;
1921 unsigned long inodes; 1940 unsigned long inodes;
1922 int error = -EINVAL; 1941 int error = -EINVAL;
1923 1942
1924 if (shmem_parse_options(data, NULL, NULL, NULL, 1943 if (shmem_parse_options(data, NULL, NULL, NULL, &max_blocks,
1925 &max_blocks, &max_inodes)) 1944 &max_inodes, &policy, &policy_nodes))
1926 return error; 1945 return error;
1927 1946
1928 spin_lock(&sbinfo->stat_lock); 1947 spin_lock(&sbinfo->stat_lock);
@@ -1948,6 +1967,8 @@ static int shmem_remount_fs(struct super_block *sb, int *flags, char *data)
1948 sbinfo->free_blocks = max_blocks - blocks; 1967 sbinfo->free_blocks = max_blocks - blocks;
1949 sbinfo->max_inodes = max_inodes; 1968 sbinfo->max_inodes = max_inodes;
1950 sbinfo->free_inodes = max_inodes - inodes; 1969 sbinfo->free_inodes = max_inodes - inodes;
1970 sbinfo->policy = policy;
1971 sbinfo->policy_nodes = policy_nodes;
1951out: 1972out:
1952 spin_unlock(&sbinfo->stat_lock); 1973 spin_unlock(&sbinfo->stat_lock);
1953 return error; 1974 return error;
@@ -1972,6 +1993,8 @@ static int shmem_fill_super(struct super_block *sb,
1972 struct shmem_sb_info *sbinfo; 1993 struct shmem_sb_info *sbinfo;
1973 unsigned long blocks = 0; 1994 unsigned long blocks = 0;
1974 unsigned long inodes = 0; 1995 unsigned long inodes = 0;
1996 int policy = MPOL_DEFAULT;
1997 nodemask_t policy_nodes = node_online_map;
1975 1998
1976#ifdef CONFIG_TMPFS 1999#ifdef CONFIG_TMPFS
1977 /* 2000 /*
@@ -1984,8 +2007,8 @@ static int shmem_fill_super(struct super_block *sb,
1984 inodes = totalram_pages - totalhigh_pages; 2007 inodes = totalram_pages - totalhigh_pages;
1985 if (inodes > blocks) 2008 if (inodes > blocks)
1986 inodes = blocks; 2009 inodes = blocks;
1987 if (shmem_parse_options(data, &mode, &uid, &gid, 2010 if (shmem_parse_options(data, &mode, &uid, &gid, &blocks,
1988 &blocks, &inodes)) 2011 &inodes, &policy, &policy_nodes))
1989 return -EINVAL; 2012 return -EINVAL;
1990 } 2013 }
1991#else 2014#else
@@ -2003,6 +2026,8 @@ static int shmem_fill_super(struct super_block *sb,
2003 sbinfo->free_blocks = blocks; 2026 sbinfo->free_blocks = blocks;
2004 sbinfo->max_inodes = inodes; 2027 sbinfo->max_inodes = inodes;
2005 sbinfo->free_inodes = inodes; 2028 sbinfo->free_inodes = inodes;
2029 sbinfo->policy = policy;
2030 sbinfo->policy_nodes = policy_nodes;
2006 2031
2007 sb->s_fs_info = sbinfo; 2032 sb->s_fs_info = sbinfo;
2008 sb->s_maxbytes = SHMEM_MAX_BYTES; 2033 sb->s_maxbytes = SHMEM_MAX_BYTES;
diff --git a/net/Kconfig b/net/Kconfig
index 60f6f321bd76..9296b269d675 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -159,6 +159,7 @@ source "net/ipx/Kconfig"
159source "drivers/net/appletalk/Kconfig" 159source "drivers/net/appletalk/Kconfig"
160source "net/x25/Kconfig" 160source "net/x25/Kconfig"
161source "net/lapb/Kconfig" 161source "net/lapb/Kconfig"
162source "net/tipc/Kconfig"
162 163
163config NET_DIVERT 164config NET_DIVERT
164 bool "Frame Diverter (EXPERIMENTAL)" 165 bool "Frame Diverter (EXPERIMENTAL)"
diff --git a/net/Makefile b/net/Makefile
index f5141b9d4f38..065796f5fb17 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -45,6 +45,7 @@ obj-$(CONFIG_VLAN_8021Q) += 8021q/
45obj-$(CONFIG_IP_DCCP) += dccp/ 45obj-$(CONFIG_IP_DCCP) += dccp/
46obj-$(CONFIG_IP_SCTP) += sctp/ 46obj-$(CONFIG_IP_SCTP) += sctp/
47obj-$(CONFIG_IEEE80211) += ieee80211/ 47obj-$(CONFIG_IEEE80211) += ieee80211/
48obj-$(CONFIG_TIPC) += tipc/
48 49
49ifeq ($(CONFIG_NET),y) 50ifeq ($(CONFIG_NET),y)
50obj-$(CONFIG_SYSCTL) += sysctl_net.o 51obj-$(CONFIG_SYSCTL) += sysctl_net.o
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c
index 9f6e0193ae10..a29c1232c420 100644
--- a/net/bridge/netfilter/ebt_log.c
+++ b/net/bridge/netfilter/ebt_log.c
@@ -15,6 +15,7 @@
15#include <linux/netfilter.h> 15#include <linux/netfilter.h>
16#include <linux/module.h> 16#include <linux/module.h>
17#include <linux/ip.h> 17#include <linux/ip.h>
18#include <linux/in.h>
18#include <linux/if_arp.h> 19#include <linux/if_arp.h>
19#include <linux/spinlock.h> 20#include <linux/spinlock.h>
20 21
diff --git a/net/core/filter.c b/net/core/filter.c
index 9eb9d0017a01..a52665f75224 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -287,7 +287,9 @@ load_b:
287 * no references or jumps that are out of range, no illegal 287 * no references or jumps that are out of range, no illegal
288 * instructions, and must end with a RET instruction. 288 * instructions, and must end with a RET instruction.
289 * 289 *
290 * Returns 0 if the rule set is legal or a negative errno code if not. 290 * All jumps are forward as they are not signed.
291 *
292 * Returns 0 if the rule set is legal or -EINVAL if not.
291 */ 293 */
292int sk_chk_filter(struct sock_filter *filter, int flen) 294int sk_chk_filter(struct sock_filter *filter, int flen)
293{ 295{
@@ -299,7 +301,6 @@ int sk_chk_filter(struct sock_filter *filter, int flen)
299 301
300 /* check the filter code now */ 302 /* check the filter code now */
301 for (pc = 0; pc < flen; pc++) { 303 for (pc = 0; pc < flen; pc++) {
302 /* all jumps are forward as they are not signed */
303 ftest = &filter[pc]; 304 ftest = &filter[pc];
304 305
305 /* Only allow valid instructions */ 306 /* Only allow valid instructions */
@@ -383,11 +384,6 @@ int sk_chk_filter(struct sock_filter *filter, int flen)
383 } 384 }
384 } 385 }
385 386
386 /*
387 * The program must end with a return. We don't care where they
388 * jumped within the script (its always forwards) but in the end
389 * they _will_ hit this.
390 */
391 return (BPF_CLASS(filter[flen - 1].code) == BPF_RET) ? 0 : -EINVAL; 387 return (BPF_CLASS(filter[flen - 1].code) == BPF_RET) ? 0 : -EINVAL;
392} 388}
393 389
diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c
index 321287bc887f..90d18b72da3d 100644
--- a/net/ieee80211/ieee80211_module.c
+++ b/net/ieee80211/ieee80211_module.c
@@ -62,7 +62,7 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION);
62MODULE_AUTHOR(DRV_COPYRIGHT); 62MODULE_AUTHOR(DRV_COPYRIGHT);
63MODULE_LICENSE("GPL"); 63MODULE_LICENSE("GPL");
64 64
65static inline int ieee80211_networks_allocate(struct ieee80211_device *ieee) 65static int ieee80211_networks_allocate(struct ieee80211_device *ieee)
66{ 66{
67 if (ieee->networks) 67 if (ieee->networks)
68 return 0; 68 return 0;
@@ -90,7 +90,7 @@ static inline void ieee80211_networks_free(struct ieee80211_device *ieee)
90 ieee->networks = NULL; 90 ieee->networks = NULL;
91} 91}
92 92
93static inline void ieee80211_networks_initialize(struct ieee80211_device *ieee) 93static void ieee80211_networks_initialize(struct ieee80211_device *ieee)
94{ 94{
95 int i; 95 int i;
96 96
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index 5e3380388046..7a121802faa9 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -35,7 +35,7 @@
35 35
36#include <net/ieee80211.h> 36#include <net/ieee80211.h>
37 37
38static inline void ieee80211_monitor_rx(struct ieee80211_device *ieee, 38static void ieee80211_monitor_rx(struct ieee80211_device *ieee,
39 struct sk_buff *skb, 39 struct sk_buff *skb,
40 struct ieee80211_rx_stats *rx_stats) 40 struct ieee80211_rx_stats *rx_stats)
41{ 41{
@@ -165,7 +165,7 @@ static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee,
165 * Responsible for handling management control frames 165 * Responsible for handling management control frames
166 * 166 *
167 * Called by ieee80211_rx */ 167 * Called by ieee80211_rx */
168static inline int 168static int
169ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb, 169ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb,
170 struct ieee80211_rx_stats *rx_stats, u16 type, 170 struct ieee80211_rx_stats *rx_stats, u16 type,
171 u16 stype) 171 u16 stype)
@@ -266,7 +266,7 @@ static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee,
266} 266}
267 267
268/* Called only as a tasklet (software IRQ), by ieee80211_rx */ 268/* Called only as a tasklet (software IRQ), by ieee80211_rx */
269static inline int 269static int
270ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb, 270ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb,
271 struct ieee80211_crypt_data *crypt) 271 struct ieee80211_crypt_data *crypt)
272{ 272{
@@ -297,7 +297,7 @@ ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb,
297} 297}
298 298
299/* Called only as a tasklet (software IRQ), by ieee80211_rx */ 299/* Called only as a tasklet (software IRQ), by ieee80211_rx */
300static inline int 300static int
301ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee, 301ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee,
302 struct sk_buff *skb, int keyidx, 302 struct sk_buff *skb, int keyidx,
303 struct ieee80211_crypt_data *crypt) 303 struct ieee80211_crypt_data *crypt)
@@ -1156,7 +1156,7 @@ static int ieee80211_handle_assoc_resp(struct ieee80211_device *ieee, struct iee
1156 1156
1157/***************************************************/ 1157/***************************************************/
1158 1158
1159static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct ieee80211_probe_response 1159static int ieee80211_network_init(struct ieee80211_device *ieee, struct ieee80211_probe_response
1160 *beacon, 1160 *beacon,
1161 struct ieee80211_network *network, 1161 struct ieee80211_network *network,
1162 struct ieee80211_rx_stats *stats) 1162 struct ieee80211_rx_stats *stats)
@@ -1235,7 +1235,7 @@ static inline int is_same_network(struct ieee80211_network *src,
1235 !memcmp(src->ssid, dst->ssid, src->ssid_len)); 1235 !memcmp(src->ssid, dst->ssid, src->ssid_len));
1236} 1236}
1237 1237
1238static inline void update_network(struct ieee80211_network *dst, 1238static void update_network(struct ieee80211_network *dst,
1239 struct ieee80211_network *src) 1239 struct ieee80211_network *src)
1240{ 1240{
1241 int qos_active; 1241 int qos_active;
@@ -1294,7 +1294,7 @@ static inline int is_beacon(int fc)
1294 return (WLAN_FC_GET_STYPE(le16_to_cpu(fc)) == IEEE80211_STYPE_BEACON); 1294 return (WLAN_FC_GET_STYPE(le16_to_cpu(fc)) == IEEE80211_STYPE_BEACON);
1295} 1295}
1296 1296
1297static inline void ieee80211_process_probe_response(struct ieee80211_device 1297static void ieee80211_process_probe_response(struct ieee80211_device
1298 *ieee, struct 1298 *ieee, struct
1299 ieee80211_probe_response 1299 ieee80211_probe_response
1300 *beacon, struct ieee80211_rx_stats 1300 *beacon, struct ieee80211_rx_stats
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index e5b33c8d5dbc..8fdd943ebe8e 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -127,7 +127,7 @@ payload of each frame is reduced to 492 bytes.
127static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 }; 127static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
128static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 }; 128static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
129 129
130static inline int ieee80211_copy_snap(u8 * data, u16 h_proto) 130static int ieee80211_copy_snap(u8 * data, u16 h_proto)
131{ 131{
132 struct ieee80211_snap_hdr *snap; 132 struct ieee80211_snap_hdr *snap;
133 u8 *oui; 133 u8 *oui;
@@ -150,7 +150,7 @@ static inline int ieee80211_copy_snap(u8 * data, u16 h_proto)
150 return SNAP_SIZE + sizeof(u16); 150 return SNAP_SIZE + sizeof(u16);
151} 151}
152 152
153static inline int ieee80211_encrypt_fragment(struct ieee80211_device *ieee, 153static int ieee80211_encrypt_fragment(struct ieee80211_device *ieee,
154 struct sk_buff *frag, int hdr_len) 154 struct sk_buff *frag, int hdr_len)
155{ 155{
156 struct ieee80211_crypt_data *crypt = ieee->crypt[ieee->tx_keyidx]; 156 struct ieee80211_crypt_data *crypt = ieee->crypt[ieee->tx_keyidx];
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index 406d5b964905..23e1630f50b7 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -42,7 +42,7 @@ static const char *ieee80211_modes[] = {
42}; 42};
43 43
44#define MAX_CUSTOM_LEN 64 44#define MAX_CUSTOM_LEN 64
45static inline char *ipw2100_translate_scan(struct ieee80211_device *ieee, 45static char *ipw2100_translate_scan(struct ieee80211_device *ieee,
46 char *start, char *stop, 46 char *start, char *stop,
47 struct ieee80211_network *network) 47 struct ieee80211_network *network)
48{ 48{
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index a9893ec03e02..db783036e4d8 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -182,6 +182,7 @@ config IP_NF_QUEUE
182 182
183config IP_NF_IPTABLES 183config IP_NF_IPTABLES
184 tristate "IP tables support (required for filtering/masq/NAT)" 184 tristate "IP tables support (required for filtering/masq/NAT)"
185 depends on NETFILTER_XTABLES
185 help 186 help
186 iptables is a general, extensible packet identification framework. 187 iptables is a general, extensible packet identification framework.
187 The packet filtering and full NAT (masquerading, port forwarding, 188 The packet filtering and full NAT (masquerading, port forwarding,
@@ -191,16 +192,6 @@ config IP_NF_IPTABLES
191 To compile it as a module, choose M here. If unsure, say N. 192 To compile it as a module, choose M here. If unsure, say N.
192 193
193# The matches. 194# The matches.
194config IP_NF_MATCH_LIMIT
195 tristate "limit match support"
196 depends on IP_NF_IPTABLES
197 help
198 limit matching allows you to control the rate at which a rule can be
199 matched: mainly useful in combination with the LOG target ("LOG
200 target support", below) and to avoid some Denial of Service attacks.
201
202 To compile it as a module, choose M here. If unsure, say N.
203
204config IP_NF_MATCH_IPRANGE 195config IP_NF_MATCH_IPRANGE
205 tristate "IP range match support" 196 tristate "IP range match support"
206 depends on IP_NF_IPTABLES 197 depends on IP_NF_IPTABLES
@@ -210,37 +201,6 @@ config IP_NF_MATCH_IPRANGE
210 201
211 To compile it as a module, choose M here. If unsure, say N. 202 To compile it as a module, choose M here. If unsure, say N.
212 203
213config IP_NF_MATCH_MAC
214 tristate "MAC address match support"
215 depends on IP_NF_IPTABLES
216 help
217 MAC matching allows you to match packets based on the source
218 Ethernet address of the packet.
219
220 To compile it as a module, choose M here. If unsure, say N.
221
222config IP_NF_MATCH_PKTTYPE
223 tristate "Packet type match support"
224 depends on IP_NF_IPTABLES
225 help
226 Packet type matching allows you to match a packet by
227 its "class", eg. BROADCAST, MULTICAST, ...
228
229 Typical usage:
230 iptables -A INPUT -m pkttype --pkt-type broadcast -j LOG
231
232 To compile it as a module, choose M here. If unsure, say N.
233
234config IP_NF_MATCH_MARK
235 tristate "netfilter MARK match support"
236 depends on IP_NF_IPTABLES
237 help
238 Netfilter mark matching allows you to match packets based on the
239 `nfmark' value in the packet. This can be set by the MARK target
240 (see below).
241
242 To compile it as a module, choose M here. If unsure, say N.
243
244config IP_NF_MATCH_MULTIPORT 204config IP_NF_MATCH_MULTIPORT
245 tristate "Multiple port match support" 205 tristate "Multiple port match support"
246 depends on IP_NF_IPTABLES 206 depends on IP_NF_IPTABLES
@@ -301,15 +261,6 @@ config IP_NF_MATCH_AH_ESP
301 261
302 To compile it as a module, choose M here. If unsure, say N. 262 To compile it as a module, choose M here. If unsure, say N.
303 263
304config IP_NF_MATCH_LENGTH
305 tristate "LENGTH match support"
306 depends on IP_NF_IPTABLES
307 help
308 This option allows you to match the length of a packet against a
309 specific value or range of values.
310
311 To compile it as a module, choose M here. If unsure, say N.
312
313config IP_NF_MATCH_TTL 264config IP_NF_MATCH_TTL
314 tristate "TTL match support" 265 tristate "TTL match support"
315 depends on IP_NF_IPTABLES 266 depends on IP_NF_IPTABLES
@@ -319,50 +270,6 @@ config IP_NF_MATCH_TTL
319 270
320 To compile it as a module, choose M here. If unsure, say N. 271 To compile it as a module, choose M here. If unsure, say N.
321 272
322config IP_NF_MATCH_TCPMSS
323 tristate "tcpmss match support"
324 depends on IP_NF_IPTABLES
325 help
326 This option adds a `tcpmss' match, which allows you to examine the
327 MSS value of TCP SYN packets, which control the maximum packet size
328 for that connection.
329
330 To compile it as a module, choose M here. If unsure, say N.
331
332config IP_NF_MATCH_HELPER
333 tristate "Helper match support"
334 depends on IP_NF_IPTABLES
335 depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4
336 help
337 Helper matching allows you to match packets in dynamic connections
338 tracked by a conntrack-helper, ie. ip_conntrack_ftp
339
340 To compile it as a module, choose M here. If unsure, say Y.
341
342config IP_NF_MATCH_STATE
343 tristate "Connection state match support"
344 depends on IP_NF_IPTABLES
345 depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4
346 help
347 Connection state matching allows you to match packets based on their
348 relationship to a tracked connection (ie. previous packets). This
349 is a powerful tool for packet classification.
350
351 To compile it as a module, choose M here. If unsure, say N.
352
353config IP_NF_MATCH_CONNTRACK
354 tristate "Connection tracking match support"
355 depends on IP_NF_IPTABLES
356 depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4
357 help
358 This is a general conntrack match module, a superset of the state match.
359
360 It allows matching on additional conntrack information, which is
361 useful in complex configurations, such as NAT gateways with multiple
362 internet links or tunnels.
363
364 To compile it as a module, choose M here. If unsure, say N.
365
366config IP_NF_MATCH_OWNER 273config IP_NF_MATCH_OWNER
367 tristate "Owner match support" 274 tristate "Owner match support"
368 depends on IP_NF_IPTABLES 275 depends on IP_NF_IPTABLES
@@ -372,15 +279,6 @@ config IP_NF_MATCH_OWNER
372 279
373 To compile it as a module, choose M here. If unsure, say N. 280 To compile it as a module, choose M here. If unsure, say N.
374 281
375config IP_NF_MATCH_PHYSDEV
376 tristate "Physdev match support"
377 depends on IP_NF_IPTABLES && BRIDGE_NETFILTER
378 help
379 Physdev packet matching matches against the physical bridge ports
380 the IP packet arrived on or will leave by.
381
382 To compile it as a module, choose M here. If unsure, say N.
383
384config IP_NF_MATCH_ADDRTYPE 282config IP_NF_MATCH_ADDRTYPE
385 tristate 'address type match support' 283 tristate 'address type match support'
386 depends on IP_NF_IPTABLES 284 depends on IP_NF_IPTABLES
@@ -391,75 +289,6 @@ config IP_NF_MATCH_ADDRTYPE
391 If you want to compile it as a module, say M here and read 289 If you want to compile it as a module, say M here and read
392 <file:Documentation/modules.txt>. If unsure, say `N'. 290 <file:Documentation/modules.txt>. If unsure, say `N'.
393 291
394config IP_NF_MATCH_REALM
395 tristate 'realm match support'
396 depends on IP_NF_IPTABLES
397 select NET_CLS_ROUTE
398 help
399 This option adds a `realm' match, which allows you to use the realm
400 key from the routing subsystem inside iptables.
401
402 This match pretty much resembles the CONFIG_NET_CLS_ROUTE4 option
403 in tc world.
404
405 If you want to compile it as a module, say M here and read
406 <file:Documentation/modules.txt>. If unsure, say `N'.
407
408config IP_NF_MATCH_SCTP
409 tristate 'SCTP protocol match support'
410 depends on IP_NF_IPTABLES
411 help
412 With this option enabled, you will be able to use the iptables
413 `sctp' match in order to match on SCTP source/destination ports
414 and SCTP chunk types.
415
416 If you want to compile it as a module, say M here and read
417 <file:Documentation/modules.txt>. If unsure, say `N'.
418
419config IP_NF_MATCH_DCCP
420 tristate 'DCCP protocol match support'
421 depends on IP_NF_IPTABLES
422 help
423 With this option enabled, you will be able to use the iptables
424 `dccp' match in order to match on DCCP source/destination ports
425 and DCCP flags.
426
427 If you want to compile it as a module, say M here and read
428 <file:Documentation/modules.txt>. If unsure, say `N'.
429
430config IP_NF_MATCH_COMMENT
431 tristate 'comment match support'
432 depends on IP_NF_IPTABLES
433 help
434 This option adds a `comment' dummy-match, which allows you to put
435 comments in your iptables ruleset.
436
437 If you want to compile it as a module, say M here and read
438 <file:Documentation/modules.txt>. If unsure, say `N'.
439
440config IP_NF_MATCH_CONNMARK
441 tristate 'Connection mark match support'
442 depends on IP_NF_IPTABLES
443 depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4)
444 help
445 This option adds a `connmark' match, which allows you to match the
446 connection mark value previously set for the session by `CONNMARK'.
447
448 If you want to compile it as a module, say M here and read
449 <file:Documentation/modules.txt>. The module will be called
450 ipt_connmark.o. If unsure, say `N'.
451
452config IP_NF_MATCH_CONNBYTES
453 tristate 'Connection byte/packet counter match support'
454 depends on IP_NF_IPTABLES
455 depends on (IP_NF_CONNTRACK && IP_NF_CT_ACCT) || (NF_CT_ACCT && NF_CONNTRACK_IPV4)
456 help
457 This option adds a `connbytes' match, which allows you to match the
458 number of bytes and/or packets for each direction within a connection.
459
460 If you want to compile it as a module, say M here and read
461 <file:Documentation/modules.txt>. If unsure, say `N'.
462
463config IP_NF_MATCH_HASHLIMIT 292config IP_NF_MATCH_HASHLIMIT
464 tristate 'hashlimit match support' 293 tristate 'hashlimit match support'
465 depends on IP_NF_IPTABLES 294 depends on IP_NF_IPTABLES
@@ -474,19 +303,6 @@ config IP_NF_MATCH_HASHLIMIT
474 destination IP' or `500pps from any given source IP' with a single 303 destination IP' or `500pps from any given source IP' with a single
475 IPtables rule. 304 IPtables rule.
476 305
477config IP_NF_MATCH_STRING
478 tristate 'string match support'
479 depends on IP_NF_IPTABLES
480 select TEXTSEARCH
481 select TEXTSEARCH_KMP
482 select TEXTSEARCH_BM
483 select TEXTSEARCH_FSM
484 help
485 This option adds a `string' match, which allows you to look for
486 pattern matchings in packets.
487
488 To compile it as a module, choose M here. If unsure, say N.
489
490config IP_NF_MATCH_POLICY 306config IP_NF_MATCH_POLICY
491 tristate "IPsec policy match support" 307 tristate "IPsec policy match support"
492 depends on IP_NF_IPTABLES && XFRM 308 depends on IP_NF_IPTABLES && XFRM
@@ -572,17 +388,6 @@ config IP_NF_TARGET_TCPMSS
572 388
573 To compile it as a module, choose M here. If unsure, say N. 389 To compile it as a module, choose M here. If unsure, say N.
574 390
575config IP_NF_TARGET_NFQUEUE
576 tristate "NFQUEUE Target Support"
577 depends on IP_NF_IPTABLES
578 help
579 This Target replaced the old obsolete QUEUE target.
580
581 As opposed to QUEUE, it supports 65535 different queues,
582 not just one.
583
584 To compile it as a module, choose M here. If unsure, say N.
585
586# NAT + specific targets 391# NAT + specific targets
587config IP_NF_NAT 392config IP_NF_NAT
588 tristate "Full NAT" 393 tristate "Full NAT"
@@ -735,31 +540,6 @@ config IP_NF_TARGET_DSCP
735 540
736 To compile it as a module, choose M here. If unsure, say N. 541 To compile it as a module, choose M here. If unsure, say N.
737 542
738config IP_NF_TARGET_MARK
739 tristate "MARK target support"
740 depends on IP_NF_MANGLE
741 help
742 This option adds a `MARK' target, which allows you to create rules
743 in the `mangle' table which alter the netfilter mark (nfmark) field
744 associated with the packet prior to routing. This can change
745 the routing method (see `Use netfilter MARK value as routing
746 key') and can also be used by other subsystems to change their
747 behavior.
748
749 To compile it as a module, choose M here. If unsure, say N.
750
751config IP_NF_TARGET_CLASSIFY
752 tristate "CLASSIFY target support"
753 depends on IP_NF_MANGLE
754 help
755 This option adds a `CLASSIFY' target, which enables the user to set
756 the priority of a packet. Some qdiscs can use this value for
757 classification, among these are:
758
759 atm, cbq, dsmark, pfifo_fast, htb, prio
760
761 To compile it as a module, choose M here. If unsure, say N.
762
763config IP_NF_TARGET_TTL 543config IP_NF_TARGET_TTL
764 tristate 'TTL target support' 544 tristate 'TTL target support'
765 depends on IP_NF_MANGLE 545 depends on IP_NF_MANGLE
@@ -774,19 +554,6 @@ config IP_NF_TARGET_TTL
774 554
775 To compile it as a module, choose M here. If unsure, say N. 555 To compile it as a module, choose M here. If unsure, say N.
776 556
777config IP_NF_TARGET_CONNMARK
778 tristate 'CONNMARK target support'
779 depends on IP_NF_MANGLE
780 depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4)
781 help
782 This option adds a `CONNMARK' target, which allows one to manipulate
783 the connection mark value. Similar to the MARK target, but
784 affects the connection mark value rather than the packet mark value.
785
786 If you want to compile it as a module, say M here and read
787 <file:Documentation/modules.txt>. The module will be called
788 ipt_CONNMARK.o. If unsure, say `N'.
789
790config IP_NF_TARGET_CLUSTERIP 557config IP_NF_TARGET_CLUSTERIP
791 tristate "CLUSTERIP target support (EXPERIMENTAL)" 558 tristate "CLUSTERIP target support (EXPERIMENTAL)"
792 depends on IP_NF_MANGLE && EXPERIMENTAL 559 depends on IP_NF_MANGLE && EXPERIMENTAL
@@ -810,23 +577,10 @@ config IP_NF_RAW
810 If you want to compile it as a module, say M here and read 577 If you want to compile it as a module, say M here and read
811 <file:Documentation/modules.txt>. If unsure, say `N'. 578 <file:Documentation/modules.txt>. If unsure, say `N'.
812 579
813config IP_NF_TARGET_NOTRACK
814 tristate 'NOTRACK target support'
815 depends on IP_NF_RAW
816 depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4
817 help
818 The NOTRACK target allows a select rule to specify
819 which packets *not* to enter the conntrack/NAT
820 subsystem with all the consequences (no ICMP error tracking,
821 no protocol helpers for the selected packets).
822
823 If you want to compile it as a module, say M here and read
824 <file:Documentation/modules.txt>. If unsure, say `N'.
825
826
827# ARP tables 580# ARP tables
828config IP_NF_ARPTABLES 581config IP_NF_ARPTABLES
829 tristate "ARP tables support" 582 tristate "ARP tables support"
583 depends on NETFILTER_XTABLES
830 help 584 help
831 arptables is a general, extensible packet identification framework. 585 arptables is a general, extensible packet identification framework.
832 The ARP packet filtering and mangling (manipulation)subsystems 586 The ARP packet filtering and mangling (manipulation)subsystems
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 549b01a648b3..bcefe64b9317 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -47,14 +47,8 @@ obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
47 47
48# matches 48# matches
49obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o 49obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
50obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
51obj-$(CONFIG_IP_NF_MATCH_HASHLIMIT) += ipt_hashlimit.o 50obj-$(CONFIG_IP_NF_MATCH_HASHLIMIT) += ipt_hashlimit.o
52obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
53obj-$(CONFIG_IP_NF_MATCH_DCCP) += ipt_dccp.o
54obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
55obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
56obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o 51obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
57obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
58obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o 52obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
59obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o 53obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
60obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o 54obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
@@ -62,40 +56,25 @@ obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
62obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o 56obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
63obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_dscp.o 57obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_dscp.o
64obj-$(CONFIG_IP_NF_MATCH_AH_ESP) += ipt_ah.o ipt_esp.o 58obj-$(CONFIG_IP_NF_MATCH_AH_ESP) += ipt_ah.o ipt_esp.o
65obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
66obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o 59obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
67obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
68obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
69obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
70obj-$(CONFIG_IP_NF_MATCH_CONNBYTES) += ipt_connbytes.o
71obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
72obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
73obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o 60obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
74obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
75obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o 61obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o
76obj-$(CONFIG_IP_NF_MATCH_COMMENT) += ipt_comment.o
77obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o
78 62
79# targets 63# targets
80obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o 64obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
81obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o 65obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o
82obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o 66obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
83obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o 67obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
84obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
85obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o 68obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
86obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o 69obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
87obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o 70obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
88obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o 71obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o
89obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
90obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o 72obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
91obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o 73obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
92obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
93obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o 74obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
94obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o 75obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
95obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
96obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o 76obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o
97obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o 77obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
98obj-$(CONFIG_IP_NF_TARGET_NFQUEUE) += ipt_NFQUEUE.o
99 78
100# generic ARP tables 79# generic ARP tables
101obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o 80obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index b6d5284c8020..afe3d8f8177d 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -24,6 +24,7 @@
24#include <asm/uaccess.h> 24#include <asm/uaccess.h>
25#include <asm/semaphore.h> 25#include <asm/semaphore.h>
26 26
27#include <linux/netfilter/x_tables.h>
27#include <linux/netfilter_arp/arp_tables.h> 28#include <linux/netfilter_arp/arp_tables.h>
28 29
29MODULE_LICENSE("GPL"); 30MODULE_LICENSE("GPL");
@@ -55,28 +56,9 @@ do { \
55#else 56#else
56#define ARP_NF_ASSERT(x) 57#define ARP_NF_ASSERT(x)
57#endif 58#endif
58#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
59 59
60static DECLARE_MUTEX(arpt_mutex);
61
62#define ASSERT_READ_LOCK(x) ARP_NF_ASSERT(down_trylock(&arpt_mutex) != 0)
63#define ASSERT_WRITE_LOCK(x) ARP_NF_ASSERT(down_trylock(&arpt_mutex) != 0)
64#include <linux/netfilter_ipv4/listhelp.h> 60#include <linux/netfilter_ipv4/listhelp.h>
65 61
66struct arpt_table_info {
67 unsigned int size;
68 unsigned int number;
69 unsigned int initial_entries;
70 unsigned int hook_entry[NF_ARP_NUMHOOKS];
71 unsigned int underflow[NF_ARP_NUMHOOKS];
72 void *entries[NR_CPUS];
73};
74
75static LIST_HEAD(arpt_target);
76static LIST_HEAD(arpt_tables);
77#define SET_COUNTER(c,b,p) do { (c).bcnt = (b); (c).pcnt = (p); } while(0)
78#define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0)
79
80static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap, 62static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap,
81 char *hdr_addr, int len) 63 char *hdr_addr, int len)
82{ 64{
@@ -223,9 +205,9 @@ static inline int arp_checkentry(const struct arpt_arp *arp)
223} 205}
224 206
225static unsigned int arpt_error(struct sk_buff **pskb, 207static unsigned int arpt_error(struct sk_buff **pskb,
226 unsigned int hooknum,
227 const struct net_device *in, 208 const struct net_device *in,
228 const struct net_device *out, 209 const struct net_device *out,
210 unsigned int hooknum,
229 const void *targinfo, 211 const void *targinfo,
230 void *userinfo) 212 void *userinfo)
231{ 213{
@@ -254,6 +236,7 @@ unsigned int arpt_do_table(struct sk_buff **pskb,
254 struct arpt_entry *e, *back; 236 struct arpt_entry *e, *back;
255 const char *indev, *outdev; 237 const char *indev, *outdev;
256 void *table_base; 238 void *table_base;
239 struct xt_table_info *private = table->private;
257 240
258 /* ARP header, plus 2 device addresses, plus 2 IP addresses. */ 241 /* ARP header, plus 2 device addresses, plus 2 IP addresses. */
259 if (!pskb_may_pull((*pskb), (sizeof(struct arphdr) + 242 if (!pskb_may_pull((*pskb), (sizeof(struct arphdr) +
@@ -265,9 +248,9 @@ unsigned int arpt_do_table(struct sk_buff **pskb,
265 outdev = out ? out->name : nulldevname; 248 outdev = out ? out->name : nulldevname;
266 249
267 read_lock_bh(&table->lock); 250 read_lock_bh(&table->lock);
268 table_base = (void *)table->private->entries[smp_processor_id()]; 251 table_base = (void *)private->entries[smp_processor_id()];
269 e = get_entry(table_base, table->private->hook_entry[hook]); 252 e = get_entry(table_base, private->hook_entry[hook]);
270 back = get_entry(table_base, table->private->underflow[hook]); 253 back = get_entry(table_base, private->underflow[hook]);
271 254
272 arp = (*pskb)->nh.arph; 255 arp = (*pskb)->nh.arph;
273 do { 256 do {
@@ -315,8 +298,8 @@ unsigned int arpt_do_table(struct sk_buff **pskb,
315 * abs. verdicts 298 * abs. verdicts
316 */ 299 */
317 verdict = t->u.kernel.target->target(pskb, 300 verdict = t->u.kernel.target->target(pskb,
318 hook,
319 in, out, 301 in, out,
302 hook,
320 t->data, 303 t->data,
321 userdata); 304 userdata);
322 305
@@ -341,106 +324,6 @@ unsigned int arpt_do_table(struct sk_buff **pskb,
341 return verdict; 324 return verdict;
342} 325}
343 326
344/*
345 * These are weird, but module loading must not be done with mutex
346 * held (since they will register), and we have to have a single
347 * function to use try_then_request_module().
348 */
349
350/* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */
351static inline struct arpt_table *find_table_lock(const char *name)
352{
353 struct arpt_table *t;
354
355 if (down_interruptible(&arpt_mutex) != 0)
356 return ERR_PTR(-EINTR);
357
358 list_for_each_entry(t, &arpt_tables, list)
359 if (strcmp(t->name, name) == 0 && try_module_get(t->me))
360 return t;
361 up(&arpt_mutex);
362 return NULL;
363}
364
365
366/* Find target, grabs ref. Returns ERR_PTR() on error. */
367static inline struct arpt_target *find_target(const char *name, u8 revision)
368{
369 struct arpt_target *t;
370 int err = 0;
371
372 if (down_interruptible(&arpt_mutex) != 0)
373 return ERR_PTR(-EINTR);
374
375 list_for_each_entry(t, &arpt_target, list) {
376 if (strcmp(t->name, name) == 0) {
377 if (t->revision == revision) {
378 if (try_module_get(t->me)) {
379 up(&arpt_mutex);
380 return t;
381 }
382 } else
383 err = -EPROTOTYPE; /* Found something. */
384 }
385 }
386 up(&arpt_mutex);
387 return ERR_PTR(err);
388}
389
390struct arpt_target *arpt_find_target(const char *name, u8 revision)
391{
392 struct arpt_target *target;
393
394 target = try_then_request_module(find_target(name, revision),
395 "arpt_%s", name);
396 if (IS_ERR(target) || !target)
397 return NULL;
398 return target;
399}
400
401static int target_revfn(const char *name, u8 revision, int *bestp)
402{
403 struct arpt_target *t;
404 int have_rev = 0;
405
406 list_for_each_entry(t, &arpt_target, list) {
407 if (strcmp(t->name, name) == 0) {
408 if (t->revision > *bestp)
409 *bestp = t->revision;
410 if (t->revision == revision)
411 have_rev =1;
412 }
413 }
414 return have_rev;
415}
416
417/* Returns true or false (if no such extension at all) */
418static inline int find_revision(const char *name, u8 revision,
419 int (*revfn)(const char *, u8, int *),
420 int *err)
421{
422 int have_rev, best = -1;
423
424 if (down_interruptible(&arpt_mutex) != 0) {
425 *err = -EINTR;
426 return 1;
427 }
428 have_rev = revfn(name, revision, &best);
429 up(&arpt_mutex);
430
431 /* Nothing at all? Return 0 to try loading module. */
432 if (best == -1) {
433 *err = -ENOENT;
434 return 0;
435 }
436
437 *err = best;
438 if (!have_rev)
439 *err = -EPROTONOSUPPORT;
440 return 1;
441}
442
443
444/* All zeroes == unconditional rule. */ 327/* All zeroes == unconditional rule. */
445static inline int unconditional(const struct arpt_arp *arp) 328static inline int unconditional(const struct arpt_arp *arp)
446{ 329{
@@ -456,7 +339,7 @@ static inline int unconditional(const struct arpt_arp *arp)
456/* Figures out from what hook each rule can be called: returns 0 if 339/* Figures out from what hook each rule can be called: returns 0 if
457 * there are loops. Puts hook bitmask in comefrom. 340 * there are loops. Puts hook bitmask in comefrom.
458 */ 341 */
459static int mark_source_chains(struct arpt_table_info *newinfo, 342static int mark_source_chains(struct xt_table_info *newinfo,
460 unsigned int valid_hooks, void *entry0) 343 unsigned int valid_hooks, void *entry0)
461{ 344{
462 unsigned int hook; 345 unsigned int hook;
@@ -587,8 +470,8 @@ static inline int check_entry(struct arpt_entry *e, const char *name, unsigned i
587 } 470 }
588 471
589 t = arpt_get_target(e); 472 t = arpt_get_target(e);
590 target = try_then_request_module(find_target(t->u.user.name, 473 target = try_then_request_module(xt_find_target(NF_ARP, t->u.user.name,
591 t->u.user.revision), 474 t->u.user.revision),
592 "arpt_%s", t->u.user.name); 475 "arpt_%s", t->u.user.name);
593 if (IS_ERR(target) || !target) { 476 if (IS_ERR(target) || !target) {
594 duprintf("check_entry: `%s' not found\n", t->u.user.name); 477 duprintf("check_entry: `%s' not found\n", t->u.user.name);
@@ -622,7 +505,7 @@ out:
622} 505}
623 506
624static inline int check_entry_size_and_hooks(struct arpt_entry *e, 507static inline int check_entry_size_and_hooks(struct arpt_entry *e,
625 struct arpt_table_info *newinfo, 508 struct xt_table_info *newinfo,
626 unsigned char *base, 509 unsigned char *base,
627 unsigned char *limit, 510 unsigned char *limit,
628 const unsigned int *hook_entries, 511 const unsigned int *hook_entries,
@@ -656,7 +539,7 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e,
656 < 0 (not ARPT_RETURN). --RR */ 539 < 0 (not ARPT_RETURN). --RR */
657 540
658 /* Clear counters and comefrom */ 541 /* Clear counters and comefrom */
659 e->counters = ((struct arpt_counters) { 0, 0 }); 542 e->counters = ((struct xt_counters) { 0, 0 });
660 e->comefrom = 0; 543 e->comefrom = 0;
661 544
662 (*i)++; 545 (*i)++;
@@ -683,7 +566,7 @@ static inline int cleanup_entry(struct arpt_entry *e, unsigned int *i)
683 */ 566 */
684static int translate_table(const char *name, 567static int translate_table(const char *name,
685 unsigned int valid_hooks, 568 unsigned int valid_hooks,
686 struct arpt_table_info *newinfo, 569 struct xt_table_info *newinfo,
687 void *entry0, 570 void *entry0,
688 unsigned int size, 571 unsigned int size,
689 unsigned int number, 572 unsigned int number,
@@ -764,34 +647,9 @@ static int translate_table(const char *name,
764 return ret; 647 return ret;
765} 648}
766 649
767static struct arpt_table_info *replace_table(struct arpt_table *table,
768 unsigned int num_counters,
769 struct arpt_table_info *newinfo,
770 int *error)
771{
772 struct arpt_table_info *oldinfo;
773
774 /* Do the substitution. */
775 write_lock_bh(&table->lock);
776 /* Check inside lock: is the old number correct? */
777 if (num_counters != table->private->number) {
778 duprintf("num_counters != table->private->number (%u/%u)\n",
779 num_counters, table->private->number);
780 write_unlock_bh(&table->lock);
781 *error = -EAGAIN;
782 return NULL;
783 }
784 oldinfo = table->private;
785 table->private = newinfo;
786 newinfo->initial_entries = oldinfo->initial_entries;
787 write_unlock_bh(&table->lock);
788
789 return oldinfo;
790}
791
792/* Gets counters. */ 650/* Gets counters. */
793static inline int add_entry_to_counter(const struct arpt_entry *e, 651static inline int add_entry_to_counter(const struct arpt_entry *e,
794 struct arpt_counters total[], 652 struct xt_counters total[],
795 unsigned int *i) 653 unsigned int *i)
796{ 654{
797 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); 655 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
@@ -801,7 +659,7 @@ static inline int add_entry_to_counter(const struct arpt_entry *e,
801} 659}
802 660
803static inline int set_entry_to_counter(const struct arpt_entry *e, 661static inline int set_entry_to_counter(const struct arpt_entry *e,
804 struct arpt_counters total[], 662 struct xt_counters total[],
805 unsigned int *i) 663 unsigned int *i)
806{ 664{
807 SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); 665 SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
@@ -810,8 +668,8 @@ static inline int set_entry_to_counter(const struct arpt_entry *e,
810 return 0; 668 return 0;
811} 669}
812 670
813static void get_counters(const struct arpt_table_info *t, 671static void get_counters(const struct xt_table_info *t,
814 struct arpt_counters counters[]) 672 struct xt_counters counters[])
815{ 673{
816 unsigned int cpu; 674 unsigned int cpu;
817 unsigned int i; 675 unsigned int i;
@@ -849,7 +707,8 @@ static int copy_entries_to_user(unsigned int total_size,
849{ 707{
850 unsigned int off, num, countersize; 708 unsigned int off, num, countersize;
851 struct arpt_entry *e; 709 struct arpt_entry *e;
852 struct arpt_counters *counters; 710 struct xt_counters *counters;
711 struct xt_table_info *private = table->private;
853 int ret = 0; 712 int ret = 0;
854 void *loc_cpu_entry; 713 void *loc_cpu_entry;
855 714
@@ -857,18 +716,18 @@ static int copy_entries_to_user(unsigned int total_size,
857 * (other than comefrom, which userspace doesn't care 716 * (other than comefrom, which userspace doesn't care
858 * about). 717 * about).
859 */ 718 */
860 countersize = sizeof(struct arpt_counters) * table->private->number; 719 countersize = sizeof(struct xt_counters) * private->number;
861 counters = vmalloc(countersize); 720 counters = vmalloc_node(countersize, numa_node_id());
862 721
863 if (counters == NULL) 722 if (counters == NULL)
864 return -ENOMEM; 723 return -ENOMEM;
865 724
866 /* First, sum counters... */ 725 /* First, sum counters... */
867 write_lock_bh(&table->lock); 726 write_lock_bh(&table->lock);
868 get_counters(table->private, counters); 727 get_counters(private, counters);
869 write_unlock_bh(&table->lock); 728 write_unlock_bh(&table->lock);
870 729
871 loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; 730 loc_cpu_entry = private->entries[raw_smp_processor_id()];
872 /* ... then copy entire thing ... */ 731 /* ... then copy entire thing ... */
873 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) { 732 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
874 ret = -EFAULT; 733 ret = -EFAULT;
@@ -911,75 +770,34 @@ static int get_entries(const struct arpt_get_entries *entries,
911 int ret; 770 int ret;
912 struct arpt_table *t; 771 struct arpt_table *t;
913 772
914 t = find_table_lock(entries->name); 773 t = xt_find_table_lock(NF_ARP, entries->name);
915 if (t || !IS_ERR(t)) { 774 if (t || !IS_ERR(t)) {
775 struct xt_table_info *private = t->private;
916 duprintf("t->private->number = %u\n", 776 duprintf("t->private->number = %u\n",
917 t->private->number); 777 private->number);
918 if (entries->size == t->private->size) 778 if (entries->size == private->size)
919 ret = copy_entries_to_user(t->private->size, 779 ret = copy_entries_to_user(private->size,
920 t, uptr->entrytable); 780 t, uptr->entrytable);
921 else { 781 else {
922 duprintf("get_entries: I've got %u not %u!\n", 782 duprintf("get_entries: I've got %u not %u!\n",
923 t->private->size, 783 private->size, entries->size);
924 entries->size);
925 ret = -EINVAL; 784 ret = -EINVAL;
926 } 785 }
927 module_put(t->me); 786 module_put(t->me);
928 up(&arpt_mutex); 787 xt_table_unlock(t);
929 } else 788 } else
930 ret = t ? PTR_ERR(t) : -ENOENT; 789 ret = t ? PTR_ERR(t) : -ENOENT;
931 790
932 return ret; 791 return ret;
933} 792}
934 793
935static void free_table_info(struct arpt_table_info *info)
936{
937 int cpu;
938 for_each_cpu(cpu) {
939 if (info->size <= PAGE_SIZE)
940 kfree(info->entries[cpu]);
941 else
942 vfree(info->entries[cpu]);
943 }
944 kfree(info);
945}
946
947static struct arpt_table_info *alloc_table_info(unsigned int size)
948{
949 struct arpt_table_info *newinfo;
950 int cpu;
951
952 newinfo = kzalloc(sizeof(struct arpt_table_info), GFP_KERNEL);
953 if (!newinfo)
954 return NULL;
955
956 newinfo->size = size;
957
958 for_each_cpu(cpu) {
959 if (size <= PAGE_SIZE)
960 newinfo->entries[cpu] = kmalloc_node(size,
961 GFP_KERNEL,
962 cpu_to_node(cpu));
963 else
964 newinfo->entries[cpu] = vmalloc_node(size,
965 cpu_to_node(cpu));
966
967 if (newinfo->entries[cpu] == NULL) {
968 free_table_info(newinfo);
969 return NULL;
970 }
971 }
972
973 return newinfo;
974}
975
976static int do_replace(void __user *user, unsigned int len) 794static int do_replace(void __user *user, unsigned int len)
977{ 795{
978 int ret; 796 int ret;
979 struct arpt_replace tmp; 797 struct arpt_replace tmp;
980 struct arpt_table *t; 798 struct arpt_table *t;
981 struct arpt_table_info *newinfo, *oldinfo; 799 struct xt_table_info *newinfo, *oldinfo;
982 struct arpt_counters *counters; 800 struct xt_counters *counters;
983 void *loc_cpu_entry, *loc_cpu_old_entry; 801 void *loc_cpu_entry, *loc_cpu_old_entry;
984 802
985 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 803 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
@@ -989,11 +807,7 @@ static int do_replace(void __user *user, unsigned int len)
989 if (len != sizeof(tmp) + tmp.size) 807 if (len != sizeof(tmp) + tmp.size)
990 return -ENOPROTOOPT; 808 return -ENOPROTOOPT;
991 809
992 /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */ 810 newinfo = xt_alloc_table_info(tmp.size);
993 if ((SMP_ALIGN(tmp.size) >> PAGE_SHIFT) + 2 > num_physpages)
994 return -ENOMEM;
995
996 newinfo = alloc_table_info(tmp.size);
997 if (!newinfo) 811 if (!newinfo)
998 return -ENOMEM; 812 return -ENOMEM;
999 813
@@ -1005,7 +819,7 @@ static int do_replace(void __user *user, unsigned int len)
1005 goto free_newinfo; 819 goto free_newinfo;
1006 } 820 }
1007 821
1008 counters = vmalloc(tmp.num_counters * sizeof(struct arpt_counters)); 822 counters = vmalloc(tmp.num_counters * sizeof(struct xt_counters));
1009 if (!counters) { 823 if (!counters) {
1010 ret = -ENOMEM; 824 ret = -ENOMEM;
1011 goto free_newinfo; 825 goto free_newinfo;
@@ -1019,7 +833,7 @@ static int do_replace(void __user *user, unsigned int len)
1019 833
1020 duprintf("arp_tables: Translated table\n"); 834 duprintf("arp_tables: Translated table\n");
1021 835
1022 t = try_then_request_module(find_table_lock(tmp.name), 836 t = try_then_request_module(xt_find_table_lock(NF_ARP, tmp.name),
1023 "arptable_%s", tmp.name); 837 "arptable_%s", tmp.name);
1024 if (!t || IS_ERR(t)) { 838 if (!t || IS_ERR(t)) {
1025 ret = t ? PTR_ERR(t) : -ENOENT; 839 ret = t ? PTR_ERR(t) : -ENOENT;
@@ -1034,7 +848,7 @@ static int do_replace(void __user *user, unsigned int len)
1034 goto put_module; 848 goto put_module;
1035 } 849 }
1036 850
1037 oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret); 851 oldinfo = xt_replace_table(t, tmp.num_counters, newinfo, &ret);
1038 if (!oldinfo) 852 if (!oldinfo)
1039 goto put_module; 853 goto put_module;
1040 854
@@ -1054,23 +868,23 @@ static int do_replace(void __user *user, unsigned int len)
1054 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; 868 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1055 ARPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL); 869 ARPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL);
1056 870
1057 free_table_info(oldinfo); 871 xt_free_table_info(oldinfo);
1058 if (copy_to_user(tmp.counters, counters, 872 if (copy_to_user(tmp.counters, counters,
1059 sizeof(struct arpt_counters) * tmp.num_counters) != 0) 873 sizeof(struct xt_counters) * tmp.num_counters) != 0)
1060 ret = -EFAULT; 874 ret = -EFAULT;
1061 vfree(counters); 875 vfree(counters);
1062 up(&arpt_mutex); 876 xt_table_unlock(t);
1063 return ret; 877 return ret;
1064 878
1065 put_module: 879 put_module:
1066 module_put(t->me); 880 module_put(t->me);
1067 up(&arpt_mutex); 881 xt_table_unlock(t);
1068 free_newinfo_counters_untrans: 882 free_newinfo_counters_untrans:
1069 ARPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL); 883 ARPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL);
1070 free_newinfo_counters: 884 free_newinfo_counters:
1071 vfree(counters); 885 vfree(counters);
1072 free_newinfo: 886 free_newinfo:
1073 free_table_info(newinfo); 887 xt_free_table_info(newinfo);
1074 return ret; 888 return ret;
1075} 889}
1076 890
@@ -1078,7 +892,7 @@ static int do_replace(void __user *user, unsigned int len)
1078 * and everything is OK. 892 * and everything is OK.
1079 */ 893 */
1080static inline int add_counter_to_entry(struct arpt_entry *e, 894static inline int add_counter_to_entry(struct arpt_entry *e,
1081 const struct arpt_counters addme[], 895 const struct xt_counters addme[],
1082 unsigned int *i) 896 unsigned int *i)
1083{ 897{
1084 898
@@ -1091,15 +905,16 @@ static inline int add_counter_to_entry(struct arpt_entry *e,
1091static int do_add_counters(void __user *user, unsigned int len) 905static int do_add_counters(void __user *user, unsigned int len)
1092{ 906{
1093 unsigned int i; 907 unsigned int i;
1094 struct arpt_counters_info tmp, *paddc; 908 struct xt_counters_info tmp, *paddc;
1095 struct arpt_table *t; 909 struct arpt_table *t;
910 struct xt_table_info *private;
1096 int ret = 0; 911 int ret = 0;
1097 void *loc_cpu_entry; 912 void *loc_cpu_entry;
1098 913
1099 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 914 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1100 return -EFAULT; 915 return -EFAULT;
1101 916
1102 if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct arpt_counters)) 917 if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct xt_counters))
1103 return -EINVAL; 918 return -EINVAL;
1104 919
1105 paddc = vmalloc(len); 920 paddc = vmalloc(len);
@@ -1111,29 +926,30 @@ static int do_add_counters(void __user *user, unsigned int len)
1111 goto free; 926 goto free;
1112 } 927 }
1113 928
1114 t = find_table_lock(tmp.name); 929 t = xt_find_table_lock(NF_ARP, tmp.name);
1115 if (!t || IS_ERR(t)) { 930 if (!t || IS_ERR(t)) {
1116 ret = t ? PTR_ERR(t) : -ENOENT; 931 ret = t ? PTR_ERR(t) : -ENOENT;
1117 goto free; 932 goto free;
1118 } 933 }
1119 934
1120 write_lock_bh(&t->lock); 935 write_lock_bh(&t->lock);
1121 if (t->private->number != paddc->num_counters) { 936 private = t->private;
937 if (private->number != paddc->num_counters) {
1122 ret = -EINVAL; 938 ret = -EINVAL;
1123 goto unlock_up_free; 939 goto unlock_up_free;
1124 } 940 }
1125 941
1126 i = 0; 942 i = 0;
1127 /* Choose the copy that is on our node */ 943 /* Choose the copy that is on our node */
1128 loc_cpu_entry = t->private->entries[smp_processor_id()]; 944 loc_cpu_entry = private->entries[smp_processor_id()];
1129 ARPT_ENTRY_ITERATE(loc_cpu_entry, 945 ARPT_ENTRY_ITERATE(loc_cpu_entry,
1130 t->private->size, 946 private->size,
1131 add_counter_to_entry, 947 add_counter_to_entry,
1132 paddc->counters, 948 paddc->counters,
1133 &i); 949 &i);
1134 unlock_up_free: 950 unlock_up_free:
1135 write_unlock_bh(&t->lock); 951 write_unlock_bh(&t->lock);
1136 up(&arpt_mutex); 952 xt_table_unlock(t);
1137 module_put(t->me); 953 module_put(t->me);
1138 free: 954 free:
1139 vfree(paddc); 955 vfree(paddc);
@@ -1190,25 +1006,26 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len
1190 } 1006 }
1191 name[ARPT_TABLE_MAXNAMELEN-1] = '\0'; 1007 name[ARPT_TABLE_MAXNAMELEN-1] = '\0';
1192 1008
1193 t = try_then_request_module(find_table_lock(name), 1009 t = try_then_request_module(xt_find_table_lock(NF_ARP, name),
1194 "arptable_%s", name); 1010 "arptable_%s", name);
1195 if (t && !IS_ERR(t)) { 1011 if (t && !IS_ERR(t)) {
1196 struct arpt_getinfo info; 1012 struct arpt_getinfo info;
1013 struct xt_table_info *private = t->private;
1197 1014
1198 info.valid_hooks = t->valid_hooks; 1015 info.valid_hooks = t->valid_hooks;
1199 memcpy(info.hook_entry, t->private->hook_entry, 1016 memcpy(info.hook_entry, private->hook_entry,
1200 sizeof(info.hook_entry)); 1017 sizeof(info.hook_entry));
1201 memcpy(info.underflow, t->private->underflow, 1018 memcpy(info.underflow, private->underflow,
1202 sizeof(info.underflow)); 1019 sizeof(info.underflow));
1203 info.num_entries = t->private->number; 1020 info.num_entries = private->number;
1204 info.size = t->private->size; 1021 info.size = private->size;
1205 strcpy(info.name, name); 1022 strcpy(info.name, name);
1206 1023
1207 if (copy_to_user(user, &info, *len) != 0) 1024 if (copy_to_user(user, &info, *len) != 0)
1208 ret = -EFAULT; 1025 ret = -EFAULT;
1209 else 1026 else
1210 ret = 0; 1027 ret = 0;
1211 up(&arpt_mutex); 1028 xt_table_unlock(t);
1212 module_put(t->me); 1029 module_put(t->me);
1213 } else 1030 } else
1214 ret = t ? PTR_ERR(t) : -ENOENT; 1031 ret = t ? PTR_ERR(t) : -ENOENT;
@@ -1233,7 +1050,7 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len
1233 } 1050 }
1234 1051
1235 case ARPT_SO_GET_REVISION_TARGET: { 1052 case ARPT_SO_GET_REVISION_TARGET: {
1236 struct arpt_get_revision rev; 1053 struct xt_get_revision rev;
1237 1054
1238 if (*len != sizeof(rev)) { 1055 if (*len != sizeof(rev)) {
1239 ret = -EINVAL; 1056 ret = -EINVAL;
@@ -1244,8 +1061,8 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len
1244 break; 1061 break;
1245 } 1062 }
1246 1063
1247 try_then_request_module(find_revision(rev.name, rev.revision, 1064 try_then_request_module(xt_find_revision(NF_ARP, rev.name,
1248 target_revfn, &ret), 1065 rev.revision, 1, &ret),
1249 "arpt_%s", rev.name); 1066 "arpt_%s", rev.name);
1250 break; 1067 break;
1251 } 1068 }
@@ -1258,38 +1075,16 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len
1258 return ret; 1075 return ret;
1259} 1076}
1260 1077
1261/* Registration hooks for targets. */
1262int arpt_register_target(struct arpt_target *target)
1263{
1264 int ret;
1265
1266 ret = down_interruptible(&arpt_mutex);
1267 if (ret != 0)
1268 return ret;
1269
1270 list_add(&target->list, &arpt_target);
1271 up(&arpt_mutex);
1272
1273 return ret;
1274}
1275
1276void arpt_unregister_target(struct arpt_target *target)
1277{
1278 down(&arpt_mutex);
1279 LIST_DELETE(&arpt_target, target);
1280 up(&arpt_mutex);
1281}
1282
1283int arpt_register_table(struct arpt_table *table, 1078int arpt_register_table(struct arpt_table *table,
1284 const struct arpt_replace *repl) 1079 const struct arpt_replace *repl)
1285{ 1080{
1286 int ret; 1081 int ret;
1287 struct arpt_table_info *newinfo; 1082 struct xt_table_info *newinfo;
1288 static struct arpt_table_info bootstrap 1083 static struct xt_table_info bootstrap
1289 = { 0, 0, 0, { 0 }, { 0 }, { } }; 1084 = { 0, 0, 0, { 0 }, { 0 }, { } };
1290 void *loc_cpu_entry; 1085 void *loc_cpu_entry;
1291 1086
1292 newinfo = alloc_table_info(repl->size); 1087 newinfo = xt_alloc_table_info(repl->size);
1293 if (!newinfo) { 1088 if (!newinfo) {
1294 ret = -ENOMEM; 1089 ret = -ENOMEM;
1295 return ret; 1090 return ret;
@@ -1304,60 +1099,33 @@ int arpt_register_table(struct arpt_table *table,
1304 repl->num_entries, 1099 repl->num_entries,
1305 repl->hook_entry, 1100 repl->hook_entry,
1306 repl->underflow); 1101 repl->underflow);
1102
1307 duprintf("arpt_register_table: translate table gives %d\n", ret); 1103 duprintf("arpt_register_table: translate table gives %d\n", ret);
1308 if (ret != 0) { 1104 if (ret != 0) {
1309 free_table_info(newinfo); 1105 xt_free_table_info(newinfo);
1310 return ret; 1106 return ret;
1311 } 1107 }
1312 1108
1313 ret = down_interruptible(&arpt_mutex); 1109 if (xt_register_table(table, &bootstrap, newinfo) != 0) {
1314 if (ret != 0) { 1110 xt_free_table_info(newinfo);
1315 free_table_info(newinfo);
1316 return ret; 1111 return ret;
1317 } 1112 }
1318 1113
1319 /* Don't autoload: we'd eat our tail... */ 1114 return 0;
1320 if (list_named_find(&arpt_tables, table->name)) {
1321 ret = -EEXIST;
1322 goto free_unlock;
1323 }
1324
1325 /* Simplifies replace_table code. */
1326 table->private = &bootstrap;
1327 if (!replace_table(table, 0, newinfo, &ret))
1328 goto free_unlock;
1329
1330 duprintf("table->private->number = %u\n",
1331 table->private->number);
1332
1333 /* save number of initial entries */
1334 table->private->initial_entries = table->private->number;
1335
1336 rwlock_init(&table->lock);
1337 list_prepend(&arpt_tables, table);
1338
1339 unlock:
1340 up(&arpt_mutex);
1341 return ret;
1342
1343 free_unlock:
1344 free_table_info(newinfo);
1345 goto unlock;
1346} 1115}
1347 1116
1348void arpt_unregister_table(struct arpt_table *table) 1117void arpt_unregister_table(struct arpt_table *table)
1349{ 1118{
1119 struct xt_table_info *private;
1350 void *loc_cpu_entry; 1120 void *loc_cpu_entry;
1351 1121
1352 down(&arpt_mutex); 1122 private = xt_unregister_table(table);
1353 LIST_DELETE(&arpt_tables, table);
1354 up(&arpt_mutex);
1355 1123
1356 /* Decrease module usage counts and free resources */ 1124 /* Decrease module usage counts and free resources */
1357 loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; 1125 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1358 ARPT_ENTRY_ITERATE(loc_cpu_entry, table->private->size, 1126 ARPT_ENTRY_ITERATE(loc_cpu_entry, private->size,
1359 cleanup_entry, NULL); 1127 cleanup_entry, NULL);
1360 free_table_info(table->private); 1128 xt_free_table_info(private);
1361} 1129}
1362 1130
1363/* The built-in targets: standard (NULL) and error. */ 1131/* The built-in targets: standard (NULL) and error. */
@@ -1380,52 +1148,15 @@ static struct nf_sockopt_ops arpt_sockopts = {
1380 .get = do_arpt_get_ctl, 1148 .get = do_arpt_get_ctl,
1381}; 1149};
1382 1150
1383#ifdef CONFIG_PROC_FS
1384static inline int print_name(const struct arpt_table *t,
1385 off_t start_offset, char *buffer, int length,
1386 off_t *pos, unsigned int *count)
1387{
1388 if ((*count)++ >= start_offset) {
1389 unsigned int namelen;
1390
1391 namelen = sprintf(buffer + *pos, "%s\n", t->name);
1392 if (*pos + namelen > length) {
1393 /* Stop iterating */
1394 return 1;
1395 }
1396 *pos += namelen;
1397 }
1398 return 0;
1399}
1400
1401static int arpt_get_tables(char *buffer, char **start, off_t offset, int length)
1402{
1403 off_t pos = 0;
1404 unsigned int count = 0;
1405
1406 if (down_interruptible(&arpt_mutex) != 0)
1407 return 0;
1408
1409 LIST_FIND(&arpt_tables, print_name, struct arpt_table *,
1410 offset, buffer, length, &pos, &count);
1411
1412 up(&arpt_mutex);
1413
1414 /* `start' hack - see fs/proc/generic.c line ~105 */
1415 *start=(char *)((unsigned long)count-offset);
1416 return pos;
1417}
1418#endif /*CONFIG_PROC_FS*/
1419
1420static int __init init(void) 1151static int __init init(void)
1421{ 1152{
1422 int ret; 1153 int ret;
1423 1154
1155 xt_proto_init(NF_ARP);
1156
1424 /* Noone else will be downing sem now, so we won't sleep */ 1157 /* Noone else will be downing sem now, so we won't sleep */
1425 down(&arpt_mutex); 1158 xt_register_target(NF_ARP, &arpt_standard_target);
1426 list_append(&arpt_target, &arpt_standard_target); 1159 xt_register_target(NF_ARP, &arpt_error_target);
1427 list_append(&arpt_target, &arpt_error_target);
1428 up(&arpt_mutex);
1429 1160
1430 /* Register setsockopt */ 1161 /* Register setsockopt */
1431 ret = nf_register_sockopt(&arpt_sockopts); 1162 ret = nf_register_sockopt(&arpt_sockopts);
@@ -1434,19 +1165,6 @@ static int __init init(void)
1434 return ret; 1165 return ret;
1435 } 1166 }
1436 1167
1437#ifdef CONFIG_PROC_FS
1438 {
1439 struct proc_dir_entry *proc;
1440
1441 proc = proc_net_create("arp_tables_names", 0, arpt_get_tables);
1442 if (!proc) {
1443 nf_unregister_sockopt(&arpt_sockopts);
1444 return -ENOMEM;
1445 }
1446 proc->owner = THIS_MODULE;
1447 }
1448#endif
1449
1450 printk("arp_tables: (C) 2002 David S. Miller\n"); 1168 printk("arp_tables: (C) 2002 David S. Miller\n");
1451 return 0; 1169 return 0;
1452} 1170}
@@ -1454,16 +1172,12 @@ static int __init init(void)
1454static void __exit fini(void) 1172static void __exit fini(void)
1455{ 1173{
1456 nf_unregister_sockopt(&arpt_sockopts); 1174 nf_unregister_sockopt(&arpt_sockopts);
1457#ifdef CONFIG_PROC_FS 1175 xt_proto_fini(NF_ARP);
1458 proc_net_remove("arp_tables_names");
1459#endif
1460} 1176}
1461 1177
1462EXPORT_SYMBOL(arpt_register_table); 1178EXPORT_SYMBOL(arpt_register_table);
1463EXPORT_SYMBOL(arpt_unregister_table); 1179EXPORT_SYMBOL(arpt_unregister_table);
1464EXPORT_SYMBOL(arpt_do_table); 1180EXPORT_SYMBOL(arpt_do_table);
1465EXPORT_SYMBOL(arpt_register_target);
1466EXPORT_SYMBOL(arpt_unregister_target);
1467 1181
1468module_init(init); 1182module_init(init);
1469module_exit(fini); 1183module_exit(fini);
diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c
index 3e592ec86482..c97650a16a5b 100644
--- a/net/ipv4/netfilter/arpt_mangle.c
+++ b/net/ipv4/netfilter/arpt_mangle.c
@@ -8,8 +8,9 @@ MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
8MODULE_DESCRIPTION("arptables arp payload mangle target"); 8MODULE_DESCRIPTION("arptables arp payload mangle target");
9 9
10static unsigned int 10static unsigned int
11target(struct sk_buff **pskb, unsigned int hooknum, const struct net_device *in, 11target(struct sk_buff **pskb, const struct net_device *in,
12 const struct net_device *out, const void *targinfo, void *userinfo) 12 const struct net_device *out, unsigned int hooknum, const void *targinfo,
13 void *userinfo)
13{ 14{
14 const struct arpt_mangle *mangle = targinfo; 15 const struct arpt_mangle *mangle = targinfo;
15 struct arphdr *arp; 16 struct arphdr *arp;
@@ -64,7 +65,7 @@ target(struct sk_buff **pskb, unsigned int hooknum, const struct net_device *in,
64} 65}
65 66
66static int 67static int
67checkentry(const char *tablename, const struct arpt_entry *e, void *targinfo, 68checkentry(const char *tablename, const void *e, void *targinfo,
68 unsigned int targinfosize, unsigned int hook_mask) 69 unsigned int targinfosize, unsigned int hook_mask)
69{ 70{
70 const struct arpt_mangle *mangle = targinfo; 71 const struct arpt_mangle *mangle = targinfo;
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c
index 0d759f5a4ef0..f6ab45f48681 100644
--- a/net/ipv4/netfilter/arptable_filter.c
+++ b/net/ipv4/netfilter/arptable_filter.c
@@ -145,6 +145,7 @@ static struct arpt_table packet_filter = {
145 .lock = RW_LOCK_UNLOCKED, 145 .lock = RW_LOCK_UNLOCKED,
146 .private = NULL, 146 .private = NULL,
147 .me = THIS_MODULE, 147 .me = THIS_MODULE,
148 .af = NF_ARP,
148}; 149};
149 150
150/* The work comes in here from netfilter.c */ 151/* The work comes in here from netfilter.c */
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index 9dec1293f67a..833fcb4be5e7 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -944,7 +944,7 @@ module_exit(fini);
944 944
945/* Some modules need us, but don't depend directly on any symbol. 945/* Some modules need us, but don't depend directly on any symbol.
946 They should call this. */ 946 They should call this. */
947void need_ip_conntrack(void) 947void need_conntrack(void)
948{ 948{
949} 949}
950 950
@@ -962,7 +962,7 @@ EXPORT_SYMBOL(ip_ct_get_tuple);
962EXPORT_SYMBOL(invert_tuplepr); 962EXPORT_SYMBOL(invert_tuplepr);
963EXPORT_SYMBOL(ip_conntrack_alter_reply); 963EXPORT_SYMBOL(ip_conntrack_alter_reply);
964EXPORT_SYMBOL(ip_conntrack_destroyed); 964EXPORT_SYMBOL(ip_conntrack_destroyed);
965EXPORT_SYMBOL(need_ip_conntrack); 965EXPORT_SYMBOL(need_conntrack);
966EXPORT_SYMBOL(ip_conntrack_helper_register); 966EXPORT_SYMBOL(ip_conntrack_helper_register);
967EXPORT_SYMBOL(ip_conntrack_helper_unregister); 967EXPORT_SYMBOL(ip_conntrack_helper_unregister);
968EXPORT_SYMBOL(ip_ct_iterate_cleanup); 968EXPORT_SYMBOL(ip_ct_iterate_cleanup);
diff --git a/net/ipv4/netfilter/ip_nat_rule.c b/net/ipv4/netfilter/ip_nat_rule.c
index cb66b8bddeb3..1de86282d232 100644
--- a/net/ipv4/netfilter/ip_nat_rule.c
+++ b/net/ipv4/netfilter/ip_nat_rule.c
@@ -95,6 +95,7 @@ static struct ipt_table nat_table = {
95 .valid_hooks = NAT_VALID_HOOKS, 95 .valid_hooks = NAT_VALID_HOOKS,
96 .lock = RW_LOCK_UNLOCKED, 96 .lock = RW_LOCK_UNLOCKED,
97 .me = THIS_MODULE, 97 .me = THIS_MODULE,
98 .af = AF_INET,
98}; 99};
99 100
100/* Source NAT */ 101/* Source NAT */
@@ -168,7 +169,7 @@ static unsigned int ipt_dnat_target(struct sk_buff **pskb,
168} 169}
169 170
170static int ipt_snat_checkentry(const char *tablename, 171static int ipt_snat_checkentry(const char *tablename,
171 const struct ipt_entry *e, 172 const void *entry,
172 void *targinfo, 173 void *targinfo,
173 unsigned int targinfosize, 174 unsigned int targinfosize,
174 unsigned int hook_mask) 175 unsigned int hook_mask)
@@ -201,7 +202,7 @@ static int ipt_snat_checkentry(const char *tablename,
201} 202}
202 203
203static int ipt_dnat_checkentry(const char *tablename, 204static int ipt_dnat_checkentry(const char *tablename,
204 const struct ipt_entry *e, 205 const void *entry,
205 void *targinfo, 206 void *targinfo,
206 unsigned int targinfosize, 207 unsigned int targinfosize,
207 unsigned int hook_mask) 208 unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index 8b8a1f00bbf4..ad438fb185b8 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -364,7 +364,7 @@ static int init_or_cleanup(int init)
364{ 364{
365 int ret = 0; 365 int ret = 0;
366 366
367 need_ip_conntrack(); 367 need_conntrack();
368 368
369 if (!init) goto cleanup; 369 if (!init) goto cleanup;
370 370
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 877bc96d3336..2371b2062c2d 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -2,7 +2,7 @@
2 * Packet matching code. 2 * Packet matching code.
3 * 3 *
4 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling 4 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
5 * Copyright (C) 2000-2004 Netfilter Core Team <coreteam@netfilter.org> 5 * Copyright (C) 2000-2005 Netfilter Core Team <coreteam@netfilter.org>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
@@ -11,6 +11,8 @@
11 * 19 Jan 2002 Harald Welte <laforge@gnumonks.org> 11 * 19 Jan 2002 Harald Welte <laforge@gnumonks.org>
12 * - increase module usage count as soon as we have rules inside 12 * - increase module usage count as soon as we have rules inside
13 * a table 13 * a table
14 * 08 Oct 2005 Harald Welte <lafore@netfilter.org>
15 * - Generalize into "x_tables" layer and "{ip,ip6,arp}_tables"
14 */ 16 */
15#include <linux/config.h> 17#include <linux/config.h>
16#include <linux/cache.h> 18#include <linux/cache.h>
@@ -20,8 +22,6 @@
20#include <linux/vmalloc.h> 22#include <linux/vmalloc.h>
21#include <linux/netdevice.h> 23#include <linux/netdevice.h>
22#include <linux/module.h> 24#include <linux/module.h>
23#include <linux/tcp.h>
24#include <linux/udp.h>
25#include <linux/icmp.h> 25#include <linux/icmp.h>
26#include <net/ip.h> 26#include <net/ip.h>
27#include <asm/uaccess.h> 27#include <asm/uaccess.h>
@@ -30,6 +30,7 @@
30#include <linux/err.h> 30#include <linux/err.h>
31#include <linux/cpumask.h> 31#include <linux/cpumask.h>
32 32
33#include <linux/netfilter/x_tables.h>
33#include <linux/netfilter_ipv4/ip_tables.h> 34#include <linux/netfilter_ipv4/ip_tables.h>
34 35
35MODULE_LICENSE("GPL"); 36MODULE_LICENSE("GPL");
@@ -62,14 +63,6 @@ do { \
62#else 63#else
63#define IP_NF_ASSERT(x) 64#define IP_NF_ASSERT(x)
64#endif 65#endif
65#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
66
67static DECLARE_MUTEX(ipt_mutex);
68
69/* Must have mutex */
70#define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0)
71#define ASSERT_WRITE_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0)
72#include <linux/netfilter_ipv4/listhelp.h>
73 66
74#if 0 67#if 0
75/* All the better to debug you with... */ 68/* All the better to debug you with... */
@@ -86,36 +79,6 @@ static DECLARE_MUTEX(ipt_mutex);
86 79
87 Hence the start of any table is given by get_table() below. */ 80 Hence the start of any table is given by get_table() below. */
88 81
89/* The table itself */
90struct ipt_table_info
91{
92 /* Size per table */
93 unsigned int size;
94 /* Number of entries: FIXME. --RR */
95 unsigned int number;
96 /* Initial number of entries. Needed for module usage count */
97 unsigned int initial_entries;
98
99 /* Entry points and underflows */
100 unsigned int hook_entry[NF_IP_NUMHOOKS];
101 unsigned int underflow[NF_IP_NUMHOOKS];
102
103 /* ipt_entry tables: one per CPU */
104 void *entries[NR_CPUS];
105};
106
107static LIST_HEAD(ipt_target);
108static LIST_HEAD(ipt_match);
109static LIST_HEAD(ipt_tables);
110#define SET_COUNTER(c,b,p) do { (c).bcnt = (b); (c).pcnt = (p); } while(0)
111#define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0)
112
113#if 0
114#define down(x) do { printk("DOWN:%u:" #x "\n", __LINE__); down(x); } while(0)
115#define down_interruptible(x) ({ int __r; printk("DOWNi:%u:" #x "\n", __LINE__); __r = down_interruptible(x); if (__r != 0) printk("ABORT-DOWNi:%u\n", __LINE__); __r; })
116#define up(x) do { printk("UP:%u:" #x "\n", __LINE__); up(x); } while(0)
117#endif
118
119/* Returns whether matches rule or not. */ 82/* Returns whether matches rule or not. */
120static inline int 83static inline int
121ip_packet_match(const struct iphdr *ip, 84ip_packet_match(const struct iphdr *ip,
@@ -234,7 +197,8 @@ int do_match(struct ipt_entry_match *m,
234 int *hotdrop) 197 int *hotdrop)
235{ 198{
236 /* Stop iteration if it doesn't match */ 199 /* Stop iteration if it doesn't match */
237 if (!m->u.kernel.match->match(skb, in, out, m->data, offset, hotdrop)) 200 if (!m->u.kernel.match->match(skb, in, out, m->data, offset,
201 skb->nh.iph->ihl*4, hotdrop))
238 return 1; 202 return 1;
239 else 203 else
240 return 0; 204 return 0;
@@ -265,6 +229,7 @@ ipt_do_table(struct sk_buff **pskb,
265 const char *indev, *outdev; 229 const char *indev, *outdev;
266 void *table_base; 230 void *table_base;
267 struct ipt_entry *e, *back; 231 struct ipt_entry *e, *back;
232 struct xt_table_info *private = table->private;
268 233
269 /* Initialization */ 234 /* Initialization */
270 ip = (*pskb)->nh.iph; 235 ip = (*pskb)->nh.iph;
@@ -281,24 +246,11 @@ ipt_do_table(struct sk_buff **pskb,
281 246
282 read_lock_bh(&table->lock); 247 read_lock_bh(&table->lock);
283 IP_NF_ASSERT(table->valid_hooks & (1 << hook)); 248 IP_NF_ASSERT(table->valid_hooks & (1 << hook));
284 table_base = (void *)table->private->entries[smp_processor_id()]; 249 table_base = (void *)private->entries[smp_processor_id()];
285 e = get_entry(table_base, table->private->hook_entry[hook]); 250 e = get_entry(table_base, private->hook_entry[hook]);
286
287#ifdef CONFIG_NETFILTER_DEBUG
288 /* Check noone else using our table */
289 if (((struct ipt_entry *)table_base)->comefrom != 0xdead57ac
290 && ((struct ipt_entry *)table_base)->comefrom != 0xeeeeeeec) {
291 printk("ASSERT: CPU #%u, %s comefrom(%p) = %X\n",
292 smp_processor_id(),
293 table->name,
294 &((struct ipt_entry *)table_base)->comefrom,
295 ((struct ipt_entry *)table_base)->comefrom);
296 }
297 ((struct ipt_entry *)table_base)->comefrom = 0x57acc001;
298#endif
299 251
300 /* For return from builtin chain */ 252 /* For return from builtin chain */
301 back = get_entry(table_base, table->private->underflow[hook]); 253 back = get_entry(table_base, private->underflow[hook]);
302 254
303 do { 255 do {
304 IP_NF_ASSERT(e); 256 IP_NF_ASSERT(e);
@@ -384,9 +336,6 @@ ipt_do_table(struct sk_buff **pskb,
384 } 336 }
385 } while (!hotdrop); 337 } while (!hotdrop);
386 338
387#ifdef CONFIG_NETFILTER_DEBUG
388 ((struct ipt_entry *)table_base)->comefrom = 0xdead57ac;
389#endif
390 read_unlock_bh(&table->lock); 339 read_unlock_bh(&table->lock);
391 340
392#ifdef DEBUG_ALLOW_ALL 341#ifdef DEBUG_ALLOW_ALL
@@ -398,145 +347,6 @@ ipt_do_table(struct sk_buff **pskb,
398#endif 347#endif
399} 348}
400 349
401/*
402 * These are weird, but module loading must not be done with mutex
403 * held (since they will register), and we have to have a single
404 * function to use try_then_request_module().
405 */
406
407/* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */
408static inline struct ipt_table *find_table_lock(const char *name)
409{
410 struct ipt_table *t;
411
412 if (down_interruptible(&ipt_mutex) != 0)
413 return ERR_PTR(-EINTR);
414
415 list_for_each_entry(t, &ipt_tables, list)
416 if (strcmp(t->name, name) == 0 && try_module_get(t->me))
417 return t;
418 up(&ipt_mutex);
419 return NULL;
420}
421
422/* Find match, grabs ref. Returns ERR_PTR() on error. */
423static inline struct ipt_match *find_match(const char *name, u8 revision)
424{
425 struct ipt_match *m;
426 int err = 0;
427
428 if (down_interruptible(&ipt_mutex) != 0)
429 return ERR_PTR(-EINTR);
430
431 list_for_each_entry(m, &ipt_match, list) {
432 if (strcmp(m->name, name) == 0) {
433 if (m->revision == revision) {
434 if (try_module_get(m->me)) {
435 up(&ipt_mutex);
436 return m;
437 }
438 } else
439 err = -EPROTOTYPE; /* Found something. */
440 }
441 }
442 up(&ipt_mutex);
443 return ERR_PTR(err);
444}
445
446/* Find target, grabs ref. Returns ERR_PTR() on error. */
447static inline struct ipt_target *find_target(const char *name, u8 revision)
448{
449 struct ipt_target *t;
450 int err = 0;
451
452 if (down_interruptible(&ipt_mutex) != 0)
453 return ERR_PTR(-EINTR);
454
455 list_for_each_entry(t, &ipt_target, list) {
456 if (strcmp(t->name, name) == 0) {
457 if (t->revision == revision) {
458 if (try_module_get(t->me)) {
459 up(&ipt_mutex);
460 return t;
461 }
462 } else
463 err = -EPROTOTYPE; /* Found something. */
464 }
465 }
466 up(&ipt_mutex);
467 return ERR_PTR(err);
468}
469
470struct ipt_target *ipt_find_target(const char *name, u8 revision)
471{
472 struct ipt_target *target;
473
474 target = try_then_request_module(find_target(name, revision),
475 "ipt_%s", name);
476 if (IS_ERR(target) || !target)
477 return NULL;
478 return target;
479}
480
481static int match_revfn(const char *name, u8 revision, int *bestp)
482{
483 struct ipt_match *m;
484 int have_rev = 0;
485
486 list_for_each_entry(m, &ipt_match, list) {
487 if (strcmp(m->name, name) == 0) {
488 if (m->revision > *bestp)
489 *bestp = m->revision;
490 if (m->revision == revision)
491 have_rev = 1;
492 }
493 }
494 return have_rev;
495}
496
497static int target_revfn(const char *name, u8 revision, int *bestp)
498{
499 struct ipt_target *t;
500 int have_rev = 0;
501
502 list_for_each_entry(t, &ipt_target, list) {
503 if (strcmp(t->name, name) == 0) {
504 if (t->revision > *bestp)
505 *bestp = t->revision;
506 if (t->revision == revision)
507 have_rev = 1;
508 }
509 }
510 return have_rev;
511}
512
513/* Returns true or false (if no such extension at all) */
514static inline int find_revision(const char *name, u8 revision,
515 int (*revfn)(const char *, u8, int *),
516 int *err)
517{
518 int have_rev, best = -1;
519
520 if (down_interruptible(&ipt_mutex) != 0) {
521 *err = -EINTR;
522 return 1;
523 }
524 have_rev = revfn(name, revision, &best);
525 up(&ipt_mutex);
526
527 /* Nothing at all? Return 0 to try loading module. */
528 if (best == -1) {
529 *err = -ENOENT;
530 return 0;
531 }
532
533 *err = best;
534 if (!have_rev)
535 *err = -EPROTONOSUPPORT;
536 return 1;
537}
538
539
540/* All zeroes == unconditional rule. */ 350/* All zeroes == unconditional rule. */
541static inline int 351static inline int
542unconditional(const struct ipt_ip *ip) 352unconditional(const struct ipt_ip *ip)
@@ -553,7 +363,7 @@ unconditional(const struct ipt_ip *ip)
553/* Figures out from what hook each rule can be called: returns 0 if 363/* Figures out from what hook each rule can be called: returns 0 if
554 there are loops. Puts hook bitmask in comefrom. */ 364 there are loops. Puts hook bitmask in comefrom. */
555static int 365static int
556mark_source_chains(struct ipt_table_info *newinfo, 366mark_source_chains(struct xt_table_info *newinfo,
557 unsigned int valid_hooks, void *entry0) 367 unsigned int valid_hooks, void *entry0)
558{ 368{
559 unsigned int hook; 369 unsigned int hook;
@@ -699,7 +509,7 @@ check_match(struct ipt_entry_match *m,
699{ 509{
700 struct ipt_match *match; 510 struct ipt_match *match;
701 511
702 match = try_then_request_module(find_match(m->u.user.name, 512 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
703 m->u.user.revision), 513 m->u.user.revision),
704 "ipt_%s", m->u.user.name); 514 "ipt_%s", m->u.user.name);
705 if (IS_ERR(match) || !match) { 515 if (IS_ERR(match) || !match) {
@@ -744,7 +554,8 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size,
744 goto cleanup_matches; 554 goto cleanup_matches;
745 555
746 t = ipt_get_target(e); 556 t = ipt_get_target(e);
747 target = try_then_request_module(find_target(t->u.user.name, 557 target = try_then_request_module(xt_find_target(AF_INET,
558 t->u.user.name,
748 t->u.user.revision), 559 t->u.user.revision),
749 "ipt_%s", t->u.user.name); 560 "ipt_%s", t->u.user.name);
750 if (IS_ERR(target) || !target) { 561 if (IS_ERR(target) || !target) {
@@ -781,7 +592,7 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size,
781 592
782static inline int 593static inline int
783check_entry_size_and_hooks(struct ipt_entry *e, 594check_entry_size_and_hooks(struct ipt_entry *e,
784 struct ipt_table_info *newinfo, 595 struct xt_table_info *newinfo,
785 unsigned char *base, 596 unsigned char *base,
786 unsigned char *limit, 597 unsigned char *limit,
787 const unsigned int *hook_entries, 598 const unsigned int *hook_entries,
@@ -815,7 +626,7 @@ check_entry_size_and_hooks(struct ipt_entry *e,
815 < 0 (not IPT_RETURN). --RR */ 626 < 0 (not IPT_RETURN). --RR */
816 627
817 /* Clear counters and comefrom */ 628 /* Clear counters and comefrom */
818 e->counters = ((struct ipt_counters) { 0, 0 }); 629 e->counters = ((struct xt_counters) { 0, 0 });
819 e->comefrom = 0; 630 e->comefrom = 0;
820 631
821 (*i)++; 632 (*i)++;
@@ -845,7 +656,7 @@ cleanup_entry(struct ipt_entry *e, unsigned int *i)
845static int 656static int
846translate_table(const char *name, 657translate_table(const char *name,
847 unsigned int valid_hooks, 658 unsigned int valid_hooks,
848 struct ipt_table_info *newinfo, 659 struct xt_table_info *newinfo,
849 void *entry0, 660 void *entry0,
850 unsigned int size, 661 unsigned int size,
851 unsigned int number, 662 unsigned int number,
@@ -922,48 +733,10 @@ translate_table(const char *name,
922 return ret; 733 return ret;
923} 734}
924 735
925static struct ipt_table_info *
926replace_table(struct ipt_table *table,
927 unsigned int num_counters,
928 struct ipt_table_info *newinfo,
929 int *error)
930{
931 struct ipt_table_info *oldinfo;
932
933#ifdef CONFIG_NETFILTER_DEBUG
934 {
935 int cpu;
936
937 for_each_cpu(cpu) {
938 struct ipt_entry *table_base = newinfo->entries[cpu];
939 if (table_base)
940 table_base->comefrom = 0xdead57ac;
941 }
942 }
943#endif
944
945 /* Do the substitution. */
946 write_lock_bh(&table->lock);
947 /* Check inside lock: is the old number correct? */
948 if (num_counters != table->private->number) {
949 duprintf("num_counters != table->private->number (%u/%u)\n",
950 num_counters, table->private->number);
951 write_unlock_bh(&table->lock);
952 *error = -EAGAIN;
953 return NULL;
954 }
955 oldinfo = table->private;
956 table->private = newinfo;
957 newinfo->initial_entries = oldinfo->initial_entries;
958 write_unlock_bh(&table->lock);
959
960 return oldinfo;
961}
962
963/* Gets counters. */ 736/* Gets counters. */
964static inline int 737static inline int
965add_entry_to_counter(const struct ipt_entry *e, 738add_entry_to_counter(const struct ipt_entry *e,
966 struct ipt_counters total[], 739 struct xt_counters total[],
967 unsigned int *i) 740 unsigned int *i)
968{ 741{
969 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); 742 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
@@ -984,8 +757,8 @@ set_entry_to_counter(const struct ipt_entry *e,
984} 757}
985 758
986static void 759static void
987get_counters(const struct ipt_table_info *t, 760get_counters(const struct xt_table_info *t,
988 struct ipt_counters counters[]) 761 struct xt_counters counters[])
989{ 762{
990 unsigned int cpu; 763 unsigned int cpu;
991 unsigned int i; 764 unsigned int i;
@@ -1024,14 +797,15 @@ copy_entries_to_user(unsigned int total_size,
1024{ 797{
1025 unsigned int off, num, countersize; 798 unsigned int off, num, countersize;
1026 struct ipt_entry *e; 799 struct ipt_entry *e;
1027 struct ipt_counters *counters; 800 struct xt_counters *counters;
801 struct xt_table_info *private = table->private;
1028 int ret = 0; 802 int ret = 0;
1029 void *loc_cpu_entry; 803 void *loc_cpu_entry;
1030 804
1031 /* We need atomic snapshot of counters: rest doesn't change 805 /* We need atomic snapshot of counters: rest doesn't change
1032 (other than comefrom, which userspace doesn't care 806 (other than comefrom, which userspace doesn't care
1033 about). */ 807 about). */
1034 countersize = sizeof(struct ipt_counters) * table->private->number; 808 countersize = sizeof(struct xt_counters) * private->number;
1035 counters = vmalloc_node(countersize, numa_node_id()); 809 counters = vmalloc_node(countersize, numa_node_id());
1036 810
1037 if (counters == NULL) 811 if (counters == NULL)
@@ -1039,14 +813,14 @@ copy_entries_to_user(unsigned int total_size,
1039 813
1040 /* First, sum counters... */ 814 /* First, sum counters... */
1041 write_lock_bh(&table->lock); 815 write_lock_bh(&table->lock);
1042 get_counters(table->private, counters); 816 get_counters(private, counters);
1043 write_unlock_bh(&table->lock); 817 write_unlock_bh(&table->lock);
1044 818
1045 /* choose the copy that is on our node/cpu, ... 819 /* choose the copy that is on our node/cpu, ...
1046 * This choice is lazy (because current thread is 820 * This choice is lazy (because current thread is
1047 * allowed to migrate to another cpu) 821 * allowed to migrate to another cpu)
1048 */ 822 */
1049 loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; 823 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1050 /* ... then copy entire thing ... */ 824 /* ... then copy entire thing ... */
1051 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) { 825 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
1052 ret = -EFAULT; 826 ret = -EFAULT;
@@ -1108,74 +882,36 @@ get_entries(const struct ipt_get_entries *entries,
1108 int ret; 882 int ret;
1109 struct ipt_table *t; 883 struct ipt_table *t;
1110 884
1111 t = find_table_lock(entries->name); 885 t = xt_find_table_lock(AF_INET, entries->name);
1112 if (t && !IS_ERR(t)) { 886 if (t && !IS_ERR(t)) {
887 struct xt_table_info *private = t->private;
1113 duprintf("t->private->number = %u\n", 888 duprintf("t->private->number = %u\n",
1114 t->private->number); 889 private->number);
1115 if (entries->size == t->private->size) 890 if (entries->size == private->size)
1116 ret = copy_entries_to_user(t->private->size, 891 ret = copy_entries_to_user(private->size,
1117 t, uptr->entrytable); 892 t, uptr->entrytable);
1118 else { 893 else {
1119 duprintf("get_entries: I've got %u not %u!\n", 894 duprintf("get_entries: I've got %u not %u!\n",
1120 t->private->size, 895 private->size,
1121 entries->size); 896 entries->size);
1122 ret = -EINVAL; 897 ret = -EINVAL;
1123 } 898 }
1124 module_put(t->me); 899 module_put(t->me);
1125 up(&ipt_mutex); 900 xt_table_unlock(t);
1126 } else 901 } else
1127 ret = t ? PTR_ERR(t) : -ENOENT; 902 ret = t ? PTR_ERR(t) : -ENOENT;
1128 903
1129 return ret; 904 return ret;
1130} 905}
1131 906
1132static void free_table_info(struct ipt_table_info *info)
1133{
1134 int cpu;
1135 for_each_cpu(cpu) {
1136 if (info->size <= PAGE_SIZE)
1137 kfree(info->entries[cpu]);
1138 else
1139 vfree(info->entries[cpu]);
1140 }
1141 kfree(info);
1142}
1143
1144static struct ipt_table_info *alloc_table_info(unsigned int size)
1145{
1146 struct ipt_table_info *newinfo;
1147 int cpu;
1148
1149 newinfo = kzalloc(sizeof(struct ipt_table_info), GFP_KERNEL);
1150 if (!newinfo)
1151 return NULL;
1152
1153 newinfo->size = size;
1154
1155 for_each_cpu(cpu) {
1156 if (size <= PAGE_SIZE)
1157 newinfo->entries[cpu] = kmalloc_node(size,
1158 GFP_KERNEL,
1159 cpu_to_node(cpu));
1160 else
1161 newinfo->entries[cpu] = vmalloc_node(size, cpu_to_node(cpu));
1162 if (newinfo->entries[cpu] == 0) {
1163 free_table_info(newinfo);
1164 return NULL;
1165 }
1166 }
1167
1168 return newinfo;
1169}
1170
1171static int 907static int
1172do_replace(void __user *user, unsigned int len) 908do_replace(void __user *user, unsigned int len)
1173{ 909{
1174 int ret; 910 int ret;
1175 struct ipt_replace tmp; 911 struct ipt_replace tmp;
1176 struct ipt_table *t; 912 struct ipt_table *t;
1177 struct ipt_table_info *newinfo, *oldinfo; 913 struct xt_table_info *newinfo, *oldinfo;
1178 struct ipt_counters *counters; 914 struct xt_counters *counters;
1179 void *loc_cpu_entry, *loc_cpu_old_entry; 915 void *loc_cpu_entry, *loc_cpu_old_entry;
1180 916
1181 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 917 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
@@ -1185,11 +921,7 @@ do_replace(void __user *user, unsigned int len)
1185 if (len != sizeof(tmp) + tmp.size) 921 if (len != sizeof(tmp) + tmp.size)
1186 return -ENOPROTOOPT; 922 return -ENOPROTOOPT;
1187 923
1188 /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */ 924 newinfo = xt_alloc_table_info(tmp.size);
1189 if ((SMP_ALIGN(tmp.size) >> PAGE_SHIFT) + 2 > num_physpages)
1190 return -ENOMEM;
1191
1192 newinfo = alloc_table_info(tmp.size);
1193 if (!newinfo) 925 if (!newinfo)
1194 return -ENOMEM; 926 return -ENOMEM;
1195 927
@@ -1201,7 +933,7 @@ do_replace(void __user *user, unsigned int len)
1201 goto free_newinfo; 933 goto free_newinfo;
1202 } 934 }
1203 935
1204 counters = vmalloc(tmp.num_counters * sizeof(struct ipt_counters)); 936 counters = vmalloc(tmp.num_counters * sizeof(struct xt_counters));
1205 if (!counters) { 937 if (!counters) {
1206 ret = -ENOMEM; 938 ret = -ENOMEM;
1207 goto free_newinfo; 939 goto free_newinfo;
@@ -1215,7 +947,7 @@ do_replace(void __user *user, unsigned int len)
1215 947
1216 duprintf("ip_tables: Translated table\n"); 948 duprintf("ip_tables: Translated table\n");
1217 949
1218 t = try_then_request_module(find_table_lock(tmp.name), 950 t = try_then_request_module(xt_find_table_lock(AF_INET, tmp.name),
1219 "iptable_%s", tmp.name); 951 "iptable_%s", tmp.name);
1220 if (!t || IS_ERR(t)) { 952 if (!t || IS_ERR(t)) {
1221 ret = t ? PTR_ERR(t) : -ENOENT; 953 ret = t ? PTR_ERR(t) : -ENOENT;
@@ -1230,7 +962,7 @@ do_replace(void __user *user, unsigned int len)
1230 goto put_module; 962 goto put_module;
1231 } 963 }
1232 964
1233 oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret); 965 oldinfo = xt_replace_table(t, tmp.num_counters, newinfo, &ret);
1234 if (!oldinfo) 966 if (!oldinfo)
1235 goto put_module; 967 goto put_module;
1236 968
@@ -1249,23 +981,23 @@ do_replace(void __user *user, unsigned int len)
1249 /* Decrease module usage counts and free resource */ 981 /* Decrease module usage counts and free resource */
1250 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; 982 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1251 IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL); 983 IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL);
1252 free_table_info(oldinfo); 984 xt_free_table_info(oldinfo);
1253 if (copy_to_user(tmp.counters, counters, 985 if (copy_to_user(tmp.counters, counters,
1254 sizeof(struct ipt_counters) * tmp.num_counters) != 0) 986 sizeof(struct xt_counters) * tmp.num_counters) != 0)
1255 ret = -EFAULT; 987 ret = -EFAULT;
1256 vfree(counters); 988 vfree(counters);
1257 up(&ipt_mutex); 989 xt_table_unlock(t);
1258 return ret; 990 return ret;
1259 991
1260 put_module: 992 put_module:
1261 module_put(t->me); 993 module_put(t->me);
1262 up(&ipt_mutex); 994 xt_table_unlock(t);
1263 free_newinfo_counters_untrans: 995 free_newinfo_counters_untrans:
1264 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL); 996 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL);
1265 free_newinfo_counters: 997 free_newinfo_counters:
1266 vfree(counters); 998 vfree(counters);
1267 free_newinfo: 999 free_newinfo:
1268 free_table_info(newinfo); 1000 xt_free_table_info(newinfo);
1269 return ret; 1001 return ret;
1270} 1002}
1271 1003
@@ -1273,7 +1005,7 @@ do_replace(void __user *user, unsigned int len)
1273 * and everything is OK. */ 1005 * and everything is OK. */
1274static inline int 1006static inline int
1275add_counter_to_entry(struct ipt_entry *e, 1007add_counter_to_entry(struct ipt_entry *e,
1276 const struct ipt_counters addme[], 1008 const struct xt_counters addme[],
1277 unsigned int *i) 1009 unsigned int *i)
1278{ 1010{
1279#if 0 1011#if 0
@@ -1295,15 +1027,16 @@ static int
1295do_add_counters(void __user *user, unsigned int len) 1027do_add_counters(void __user *user, unsigned int len)
1296{ 1028{
1297 unsigned int i; 1029 unsigned int i;
1298 struct ipt_counters_info tmp, *paddc; 1030 struct xt_counters_info tmp, *paddc;
1299 struct ipt_table *t; 1031 struct ipt_table *t;
1032 struct xt_table_info *private;
1300 int ret = 0; 1033 int ret = 0;
1301 void *loc_cpu_entry; 1034 void *loc_cpu_entry;
1302 1035
1303 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 1036 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1304 return -EFAULT; 1037 return -EFAULT;
1305 1038
1306 if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct ipt_counters)) 1039 if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct xt_counters))
1307 return -EINVAL; 1040 return -EINVAL;
1308 1041
1309 paddc = vmalloc_node(len, numa_node_id()); 1042 paddc = vmalloc_node(len, numa_node_id());
@@ -1315,29 +1048,30 @@ do_add_counters(void __user *user, unsigned int len)
1315 goto free; 1048 goto free;
1316 } 1049 }
1317 1050
1318 t = find_table_lock(tmp.name); 1051 t = xt_find_table_lock(AF_INET, tmp.name);
1319 if (!t || IS_ERR(t)) { 1052 if (!t || IS_ERR(t)) {
1320 ret = t ? PTR_ERR(t) : -ENOENT; 1053 ret = t ? PTR_ERR(t) : -ENOENT;
1321 goto free; 1054 goto free;
1322 } 1055 }
1323 1056
1324 write_lock_bh(&t->lock); 1057 write_lock_bh(&t->lock);
1325 if (t->private->number != paddc->num_counters) { 1058 private = t->private;
1059 if (private->number != paddc->num_counters) {
1326 ret = -EINVAL; 1060 ret = -EINVAL;
1327 goto unlock_up_free; 1061 goto unlock_up_free;
1328 } 1062 }
1329 1063
1330 i = 0; 1064 i = 0;
1331 /* Choose the copy that is on our node */ 1065 /* Choose the copy that is on our node */
1332 loc_cpu_entry = t->private->entries[raw_smp_processor_id()]; 1066 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1333 IPT_ENTRY_ITERATE(loc_cpu_entry, 1067 IPT_ENTRY_ITERATE(loc_cpu_entry,
1334 t->private->size, 1068 private->size,
1335 add_counter_to_entry, 1069 add_counter_to_entry,
1336 paddc->counters, 1070 paddc->counters,
1337 &i); 1071 &i);
1338 unlock_up_free: 1072 unlock_up_free:
1339 write_unlock_bh(&t->lock); 1073 write_unlock_bh(&t->lock);
1340 up(&ipt_mutex); 1074 xt_table_unlock(t);
1341 module_put(t->me); 1075 module_put(t->me);
1342 free: 1076 free:
1343 vfree(paddc); 1077 vfree(paddc);
@@ -1396,25 +1130,26 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1396 } 1130 }
1397 name[IPT_TABLE_MAXNAMELEN-1] = '\0'; 1131 name[IPT_TABLE_MAXNAMELEN-1] = '\0';
1398 1132
1399 t = try_then_request_module(find_table_lock(name), 1133 t = try_then_request_module(xt_find_table_lock(AF_INET, name),
1400 "iptable_%s", name); 1134 "iptable_%s", name);
1401 if (t && !IS_ERR(t)) { 1135 if (t && !IS_ERR(t)) {
1402 struct ipt_getinfo info; 1136 struct ipt_getinfo info;
1137 struct xt_table_info *private = t->private;
1403 1138
1404 info.valid_hooks = t->valid_hooks; 1139 info.valid_hooks = t->valid_hooks;
1405 memcpy(info.hook_entry, t->private->hook_entry, 1140 memcpy(info.hook_entry, private->hook_entry,
1406 sizeof(info.hook_entry)); 1141 sizeof(info.hook_entry));
1407 memcpy(info.underflow, t->private->underflow, 1142 memcpy(info.underflow, private->underflow,
1408 sizeof(info.underflow)); 1143 sizeof(info.underflow));
1409 info.num_entries = t->private->number; 1144 info.num_entries = private->number;
1410 info.size = t->private->size; 1145 info.size = private->size;
1411 memcpy(info.name, name, sizeof(info.name)); 1146 memcpy(info.name, name, sizeof(info.name));
1412 1147
1413 if (copy_to_user(user, &info, *len) != 0) 1148 if (copy_to_user(user, &info, *len) != 0)
1414 ret = -EFAULT; 1149 ret = -EFAULT;
1415 else 1150 else
1416 ret = 0; 1151 ret = 0;
1417 up(&ipt_mutex); 1152 xt_table_unlock(t);
1418 module_put(t->me); 1153 module_put(t->me);
1419 } else 1154 } else
1420 ret = t ? PTR_ERR(t) : -ENOENT; 1155 ret = t ? PTR_ERR(t) : -ENOENT;
@@ -1441,7 +1176,7 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1441 case IPT_SO_GET_REVISION_MATCH: 1176 case IPT_SO_GET_REVISION_MATCH:
1442 case IPT_SO_GET_REVISION_TARGET: { 1177 case IPT_SO_GET_REVISION_TARGET: {
1443 struct ipt_get_revision rev; 1178 struct ipt_get_revision rev;
1444 int (*revfn)(const char *, u8, int *); 1179 int target;
1445 1180
1446 if (*len != sizeof(rev)) { 1181 if (*len != sizeof(rev)) {
1447 ret = -EINVAL; 1182 ret = -EINVAL;
@@ -1453,12 +1188,13 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1453 } 1188 }
1454 1189
1455 if (cmd == IPT_SO_GET_REVISION_TARGET) 1190 if (cmd == IPT_SO_GET_REVISION_TARGET)
1456 revfn = target_revfn; 1191 target = 1;
1457 else 1192 else
1458 revfn = match_revfn; 1193 target = 0;
1459 1194
1460 try_then_request_module(find_revision(rev.name, rev.revision, 1195 try_then_request_module(xt_find_revision(AF_INET, rev.name,
1461 revfn, &ret), 1196 rev.revision,
1197 target, &ret),
1462 "ipt_%s", rev.name); 1198 "ipt_%s", rev.name);
1463 break; 1199 break;
1464 } 1200 }
@@ -1471,60 +1207,15 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1471 return ret; 1207 return ret;
1472} 1208}
1473 1209
1474/* Registration hooks for targets. */ 1210int ipt_register_table(struct xt_table *table, const struct ipt_replace *repl)
1475int
1476ipt_register_target(struct ipt_target *target)
1477{ 1211{
1478 int ret; 1212 int ret;
1479 1213 struct xt_table_info *newinfo;
1480 ret = down_interruptible(&ipt_mutex); 1214 static struct xt_table_info bootstrap
1481 if (ret != 0)
1482 return ret;
1483 list_add(&target->list, &ipt_target);
1484 up(&ipt_mutex);
1485 return ret;
1486}
1487
1488void
1489ipt_unregister_target(struct ipt_target *target)
1490{
1491 down(&ipt_mutex);
1492 LIST_DELETE(&ipt_target, target);
1493 up(&ipt_mutex);
1494}
1495
1496int
1497ipt_register_match(struct ipt_match *match)
1498{
1499 int ret;
1500
1501 ret = down_interruptible(&ipt_mutex);
1502 if (ret != 0)
1503 return ret;
1504
1505 list_add(&match->list, &ipt_match);
1506 up(&ipt_mutex);
1507
1508 return ret;
1509}
1510
1511void
1512ipt_unregister_match(struct ipt_match *match)
1513{
1514 down(&ipt_mutex);
1515 LIST_DELETE(&ipt_match, match);
1516 up(&ipt_mutex);
1517}
1518
1519int ipt_register_table(struct ipt_table *table, const struct ipt_replace *repl)
1520{
1521 int ret;
1522 struct ipt_table_info *newinfo;
1523 static struct ipt_table_info bootstrap
1524 = { 0, 0, 0, { 0 }, { 0 }, { } }; 1215 = { 0, 0, 0, { 0 }, { 0 }, { } };
1525 void *loc_cpu_entry; 1216 void *loc_cpu_entry;
1526 1217
1527 newinfo = alloc_table_info(repl->size); 1218 newinfo = xt_alloc_table_info(repl->size);
1528 if (!newinfo) 1219 if (!newinfo)
1529 return -ENOMEM; 1220 return -ENOMEM;
1530 1221
@@ -1540,246 +1231,29 @@ int ipt_register_table(struct ipt_table *table, const struct ipt_replace *repl)
1540 repl->hook_entry, 1231 repl->hook_entry,
1541 repl->underflow); 1232 repl->underflow);
1542 if (ret != 0) { 1233 if (ret != 0) {
1543 free_table_info(newinfo); 1234 xt_free_table_info(newinfo);
1544 return ret; 1235 return ret;
1545 } 1236 }
1546 1237
1547 ret = down_interruptible(&ipt_mutex); 1238 if (xt_register_table(table, &bootstrap, newinfo) != 0) {
1548 if (ret != 0) { 1239 xt_free_table_info(newinfo);
1549 free_table_info(newinfo);
1550 return ret; 1240 return ret;
1551 } 1241 }
1552 1242
1553 /* Don't autoload: we'd eat our tail... */ 1243 return 0;
1554 if (list_named_find(&ipt_tables, table->name)) {
1555 ret = -EEXIST;
1556 goto free_unlock;
1557 }
1558
1559 /* Simplifies replace_table code. */
1560 table->private = &bootstrap;
1561 if (!replace_table(table, 0, newinfo, &ret))
1562 goto free_unlock;
1563
1564 duprintf("table->private->number = %u\n",
1565 table->private->number);
1566
1567 /* save number of initial entries */
1568 table->private->initial_entries = table->private->number;
1569
1570 rwlock_init(&table->lock);
1571 list_prepend(&ipt_tables, table);
1572
1573 unlock:
1574 up(&ipt_mutex);
1575 return ret;
1576
1577 free_unlock:
1578 free_table_info(newinfo);
1579 goto unlock;
1580} 1244}
1581 1245
1582void ipt_unregister_table(struct ipt_table *table) 1246void ipt_unregister_table(struct ipt_table *table)
1583{ 1247{
1248 struct xt_table_info *private;
1584 void *loc_cpu_entry; 1249 void *loc_cpu_entry;
1585 1250
1586 down(&ipt_mutex); 1251 private = xt_unregister_table(table);
1587 LIST_DELETE(&ipt_tables, table);
1588 up(&ipt_mutex);
1589 1252
1590 /* Decrease module usage counts and free resources */ 1253 /* Decrease module usage counts and free resources */
1591 loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; 1254 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1592 IPT_ENTRY_ITERATE(loc_cpu_entry, table->private->size, 1255 IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL);
1593 cleanup_entry, NULL); 1256 xt_free_table_info(private);
1594 free_table_info(table->private);
1595}
1596
1597/* Returns 1 if the port is matched by the range, 0 otherwise */
1598static inline int
1599port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert)
1600{
1601 int ret;
1602
1603 ret = (port >= min && port <= max) ^ invert;
1604 return ret;
1605}
1606
1607static int
1608tcp_find_option(u_int8_t option,
1609 const struct sk_buff *skb,
1610 unsigned int optlen,
1611 int invert,
1612 int *hotdrop)
1613{
1614 /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
1615 u_int8_t _opt[60 - sizeof(struct tcphdr)], *op;
1616 unsigned int i;
1617
1618 duprintf("tcp_match: finding option\n");
1619
1620 if (!optlen)
1621 return invert;
1622
1623 /* If we don't have the whole header, drop packet. */
1624 op = skb_header_pointer(skb,
1625 skb->nh.iph->ihl*4 + sizeof(struct tcphdr),
1626 optlen, _opt);
1627 if (op == NULL) {
1628 *hotdrop = 1;
1629 return 0;
1630 }
1631
1632 for (i = 0; i < optlen; ) {
1633 if (op[i] == option) return !invert;
1634 if (op[i] < 2) i++;
1635 else i += op[i+1]?:1;
1636 }
1637
1638 return invert;
1639}
1640
1641static int
1642tcp_match(const struct sk_buff *skb,
1643 const struct net_device *in,
1644 const struct net_device *out,
1645 const void *matchinfo,
1646 int offset,
1647 int *hotdrop)
1648{
1649 struct tcphdr _tcph, *th;
1650 const struct ipt_tcp *tcpinfo = matchinfo;
1651
1652 if (offset) {
1653 /* To quote Alan:
1654
1655 Don't allow a fragment of TCP 8 bytes in. Nobody normal
1656 causes this. Its a cracker trying to break in by doing a
1657 flag overwrite to pass the direction checks.
1658 */
1659 if (offset == 1) {
1660 duprintf("Dropping evil TCP offset=1 frag.\n");
1661 *hotdrop = 1;
1662 }
1663 /* Must not be a fragment. */
1664 return 0;
1665 }
1666
1667#define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg))
1668
1669 th = skb_header_pointer(skb, skb->nh.iph->ihl*4,
1670 sizeof(_tcph), &_tcph);
1671 if (th == NULL) {
1672 /* We've been asked to examine this packet, and we
1673 can't. Hence, no choice but to drop. */
1674 duprintf("Dropping evil TCP offset=0 tinygram.\n");
1675 *hotdrop = 1;
1676 return 0;
1677 }
1678
1679 if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1],
1680 ntohs(th->source),
1681 !!(tcpinfo->invflags & IPT_TCP_INV_SRCPT)))
1682 return 0;
1683 if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1],
1684 ntohs(th->dest),
1685 !!(tcpinfo->invflags & IPT_TCP_INV_DSTPT)))
1686 return 0;
1687 if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask)
1688 == tcpinfo->flg_cmp,
1689 IPT_TCP_INV_FLAGS))
1690 return 0;
1691 if (tcpinfo->option) {
1692 if (th->doff * 4 < sizeof(_tcph)) {
1693 *hotdrop = 1;
1694 return 0;
1695 }
1696 if (!tcp_find_option(tcpinfo->option, skb,
1697 th->doff*4 - sizeof(_tcph),
1698 tcpinfo->invflags & IPT_TCP_INV_OPTION,
1699 hotdrop))
1700 return 0;
1701 }
1702 return 1;
1703}
1704
1705/* Called when user tries to insert an entry of this type. */
1706static int
1707tcp_checkentry(const char *tablename,
1708 const struct ipt_ip *ip,
1709 void *matchinfo,
1710 unsigned int matchsize,
1711 unsigned int hook_mask)
1712{
1713 const struct ipt_tcp *tcpinfo = matchinfo;
1714
1715 /* Must specify proto == TCP, and no unknown invflags */
1716 return ip->proto == IPPROTO_TCP
1717 && !(ip->invflags & IPT_INV_PROTO)
1718 && matchsize == IPT_ALIGN(sizeof(struct ipt_tcp))
1719 && !(tcpinfo->invflags & ~IPT_TCP_INV_MASK);
1720}
1721
1722static int
1723udp_match(const struct sk_buff *skb,
1724 const struct net_device *in,
1725 const struct net_device *out,
1726 const void *matchinfo,
1727 int offset,
1728 int *hotdrop)
1729{
1730 struct udphdr _udph, *uh;
1731 const struct ipt_udp *udpinfo = matchinfo;
1732
1733 /* Must not be a fragment. */
1734 if (offset)
1735 return 0;
1736
1737 uh = skb_header_pointer(skb, skb->nh.iph->ihl*4,
1738 sizeof(_udph), &_udph);
1739 if (uh == NULL) {
1740 /* We've been asked to examine this packet, and we
1741 can't. Hence, no choice but to drop. */
1742 duprintf("Dropping evil UDP tinygram.\n");
1743 *hotdrop = 1;
1744 return 0;
1745 }
1746
1747 return port_match(udpinfo->spts[0], udpinfo->spts[1],
1748 ntohs(uh->source),
1749 !!(udpinfo->invflags & IPT_UDP_INV_SRCPT))
1750 && port_match(udpinfo->dpts[0], udpinfo->dpts[1],
1751 ntohs(uh->dest),
1752 !!(udpinfo->invflags & IPT_UDP_INV_DSTPT));
1753}
1754
1755/* Called when user tries to insert an entry of this type. */
1756static int
1757udp_checkentry(const char *tablename,
1758 const struct ipt_ip *ip,
1759 void *matchinfo,
1760 unsigned int matchinfosize,
1761 unsigned int hook_mask)
1762{
1763 const struct ipt_udp *udpinfo = matchinfo;
1764
1765 /* Must specify proto == UDP, and no unknown invflags */
1766 if (ip->proto != IPPROTO_UDP || (ip->invflags & IPT_INV_PROTO)) {
1767 duprintf("ipt_udp: Protocol %u != %u\n", ip->proto,
1768 IPPROTO_UDP);
1769 return 0;
1770 }
1771 if (matchinfosize != IPT_ALIGN(sizeof(struct ipt_udp))) {
1772 duprintf("ipt_udp: matchsize %u != %u\n",
1773 matchinfosize, IPT_ALIGN(sizeof(struct ipt_udp)));
1774 return 0;
1775 }
1776 if (udpinfo->invflags & ~IPT_UDP_INV_MASK) {
1777 duprintf("ipt_udp: unknown flags %X\n",
1778 udpinfo->invflags);
1779 return 0;
1780 }
1781
1782 return 1;
1783} 1257}
1784 1258
1785/* Returns 1 if the type and code is matched by the range, 0 otherwise */ 1259/* Returns 1 if the type and code is matched by the range, 0 otherwise */
@@ -1798,6 +1272,7 @@ icmp_match(const struct sk_buff *skb,
1798 const struct net_device *out, 1272 const struct net_device *out,
1799 const void *matchinfo, 1273 const void *matchinfo,
1800 int offset, 1274 int offset,
1275 unsigned int protoff,
1801 int *hotdrop) 1276 int *hotdrop)
1802{ 1277{
1803 struct icmphdr _icmph, *ic; 1278 struct icmphdr _icmph, *ic;
@@ -1807,8 +1282,7 @@ icmp_match(const struct sk_buff *skb,
1807 if (offset) 1282 if (offset)
1808 return 0; 1283 return 0;
1809 1284
1810 ic = skb_header_pointer(skb, skb->nh.iph->ihl*4, 1285 ic = skb_header_pointer(skb, protoff, sizeof(_icmph), &_icmph);
1811 sizeof(_icmph), &_icmph);
1812 if (ic == NULL) { 1286 if (ic == NULL) {
1813 /* We've been asked to examine this packet, and we 1287 /* We've been asked to examine this packet, and we
1814 * can't. Hence, no choice but to drop. 1288 * can't. Hence, no choice but to drop.
@@ -1828,11 +1302,12 @@ icmp_match(const struct sk_buff *skb,
1828/* Called when user tries to insert an entry of this type. */ 1302/* Called when user tries to insert an entry of this type. */
1829static int 1303static int
1830icmp_checkentry(const char *tablename, 1304icmp_checkentry(const char *tablename,
1831 const struct ipt_ip *ip, 1305 const void *info,
1832 void *matchinfo, 1306 void *matchinfo,
1833 unsigned int matchsize, 1307 unsigned int matchsize,
1834 unsigned int hook_mask) 1308 unsigned int hook_mask)
1835{ 1309{
1310 const struct ipt_ip *ip = info;
1836 const struct ipt_icmp *icmpinfo = matchinfo; 1311 const struct ipt_icmp *icmpinfo = matchinfo;
1837 1312
1838 /* Must specify proto == ICMP, and no unknown invflags */ 1313 /* Must specify proto == ICMP, and no unknown invflags */
@@ -1862,123 +1337,22 @@ static struct nf_sockopt_ops ipt_sockopts = {
1862 .get = do_ipt_get_ctl, 1337 .get = do_ipt_get_ctl,
1863}; 1338};
1864 1339
1865static struct ipt_match tcp_matchstruct = {
1866 .name = "tcp",
1867 .match = &tcp_match,
1868 .checkentry = &tcp_checkentry,
1869};
1870
1871static struct ipt_match udp_matchstruct = {
1872 .name = "udp",
1873 .match = &udp_match,
1874 .checkentry = &udp_checkentry,
1875};
1876
1877static struct ipt_match icmp_matchstruct = { 1340static struct ipt_match icmp_matchstruct = {
1878 .name = "icmp", 1341 .name = "icmp",
1879 .match = &icmp_match, 1342 .match = &icmp_match,
1880 .checkentry = &icmp_checkentry, 1343 .checkentry = &icmp_checkentry,
1881}; 1344};
1882 1345
1883#ifdef CONFIG_PROC_FS
1884static inline int print_name(const char *i,
1885 off_t start_offset, char *buffer, int length,
1886 off_t *pos, unsigned int *count)
1887{
1888 if ((*count)++ >= start_offset) {
1889 unsigned int namelen;
1890
1891 namelen = sprintf(buffer + *pos, "%s\n",
1892 i + sizeof(struct list_head));
1893 if (*pos + namelen > length) {
1894 /* Stop iterating */
1895 return 1;
1896 }
1897 *pos += namelen;
1898 }
1899 return 0;
1900}
1901
1902static inline int print_target(const struct ipt_target *t,
1903 off_t start_offset, char *buffer, int length,
1904 off_t *pos, unsigned int *count)
1905{
1906 if (t == &ipt_standard_target || t == &ipt_error_target)
1907 return 0;
1908 return print_name((char *)t, start_offset, buffer, length, pos, count);
1909}
1910
1911static int ipt_get_tables(char *buffer, char **start, off_t offset, int length)
1912{
1913 off_t pos = 0;
1914 unsigned int count = 0;
1915
1916 if (down_interruptible(&ipt_mutex) != 0)
1917 return 0;
1918
1919 LIST_FIND(&ipt_tables, print_name, void *,
1920 offset, buffer, length, &pos, &count);
1921
1922 up(&ipt_mutex);
1923
1924 /* `start' hack - see fs/proc/generic.c line ~105 */
1925 *start=(char *)((unsigned long)count-offset);
1926 return pos;
1927}
1928
1929static int ipt_get_targets(char *buffer, char **start, off_t offset, int length)
1930{
1931 off_t pos = 0;
1932 unsigned int count = 0;
1933
1934 if (down_interruptible(&ipt_mutex) != 0)
1935 return 0;
1936
1937 LIST_FIND(&ipt_target, print_target, struct ipt_target *,
1938 offset, buffer, length, &pos, &count);
1939
1940 up(&ipt_mutex);
1941
1942 *start = (char *)((unsigned long)count - offset);
1943 return pos;
1944}
1945
1946static int ipt_get_matches(char *buffer, char **start, off_t offset, int length)
1947{
1948 off_t pos = 0;
1949 unsigned int count = 0;
1950
1951 if (down_interruptible(&ipt_mutex) != 0)
1952 return 0;
1953
1954 LIST_FIND(&ipt_match, print_name, void *,
1955 offset, buffer, length, &pos, &count);
1956
1957 up(&ipt_mutex);
1958
1959 *start = (char *)((unsigned long)count - offset);
1960 return pos;
1961}
1962
1963static const struct { char *name; get_info_t *get_info; } ipt_proc_entry[] =
1964{ { "ip_tables_names", ipt_get_tables },
1965 { "ip_tables_targets", ipt_get_targets },
1966 { "ip_tables_matches", ipt_get_matches },
1967 { NULL, NULL} };
1968#endif /*CONFIG_PROC_FS*/
1969
1970static int __init init(void) 1346static int __init init(void)
1971{ 1347{
1972 int ret; 1348 int ret;
1973 1349
1350 xt_proto_init(AF_INET);
1351
1974 /* Noone else will be downing sem now, so we won't sleep */ 1352 /* Noone else will be downing sem now, so we won't sleep */
1975 down(&ipt_mutex); 1353 xt_register_target(AF_INET, &ipt_standard_target);
1976 list_append(&ipt_target, &ipt_standard_target); 1354 xt_register_target(AF_INET, &ipt_error_target);
1977 list_append(&ipt_target, &ipt_error_target); 1355 xt_register_match(AF_INET, &icmp_matchstruct);
1978 list_append(&ipt_match, &tcp_matchstruct);
1979 list_append(&ipt_match, &udp_matchstruct);
1980 list_append(&ipt_match, &icmp_matchstruct);
1981 up(&ipt_mutex);
1982 1356
1983 /* Register setsockopt */ 1357 /* Register setsockopt */
1984 ret = nf_register_sockopt(&ipt_sockopts); 1358 ret = nf_register_sockopt(&ipt_sockopts);
@@ -1987,49 +1361,23 @@ static int __init init(void)
1987 return ret; 1361 return ret;
1988 } 1362 }
1989 1363
1990#ifdef CONFIG_PROC_FS 1364 printk("ip_tables: (C) 2000-2006 Netfilter Core Team\n");
1991 {
1992 struct proc_dir_entry *proc;
1993 int i;
1994
1995 for (i = 0; ipt_proc_entry[i].name; i++) {
1996 proc = proc_net_create(ipt_proc_entry[i].name, 0,
1997 ipt_proc_entry[i].get_info);
1998 if (!proc) {
1999 while (--i >= 0)
2000 proc_net_remove(ipt_proc_entry[i].name);
2001 nf_unregister_sockopt(&ipt_sockopts);
2002 return -ENOMEM;
2003 }
2004 proc->owner = THIS_MODULE;
2005 }
2006 }
2007#endif
2008
2009 printk("ip_tables: (C) 2000-2002 Netfilter core team\n");
2010 return 0; 1365 return 0;
2011} 1366}
2012 1367
2013static void __exit fini(void) 1368static void __exit fini(void)
2014{ 1369{
2015 nf_unregister_sockopt(&ipt_sockopts); 1370 nf_unregister_sockopt(&ipt_sockopts);
2016#ifdef CONFIG_PROC_FS 1371
2017 { 1372 xt_unregister_match(AF_INET, &icmp_matchstruct);
2018 int i; 1373 xt_unregister_target(AF_INET, &ipt_error_target);
2019 for (i = 0; ipt_proc_entry[i].name; i++) 1374 xt_unregister_target(AF_INET, &ipt_standard_target);
2020 proc_net_remove(ipt_proc_entry[i].name); 1375
2021 } 1376 xt_proto_fini(AF_INET);
2022#endif
2023} 1377}
2024 1378
2025EXPORT_SYMBOL(ipt_register_table); 1379EXPORT_SYMBOL(ipt_register_table);
2026EXPORT_SYMBOL(ipt_unregister_table); 1380EXPORT_SYMBOL(ipt_unregister_table);
2027EXPORT_SYMBOL(ipt_register_match);
2028EXPORT_SYMBOL(ipt_unregister_match);
2029EXPORT_SYMBOL(ipt_do_table); 1381EXPORT_SYMBOL(ipt_do_table);
2030EXPORT_SYMBOL(ipt_register_target);
2031EXPORT_SYMBOL(ipt_unregister_target);
2032EXPORT_SYMBOL(ipt_find_target);
2033
2034module_init(init); 1382module_init(init);
2035module_exit(fini); 1383module_exit(fini);
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 45c52d8f4d99..d9bc971f03af 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -379,12 +379,13 @@ target(struct sk_buff **pskb,
379 379
380static int 380static int
381checkentry(const char *tablename, 381checkentry(const char *tablename,
382 const struct ipt_entry *e, 382 const void *e_void,
383 void *targinfo, 383 void *targinfo,
384 unsigned int targinfosize, 384 unsigned int targinfosize,
385 unsigned int hook_mask) 385 unsigned int hook_mask)
386{ 386{
387 struct ipt_clusterip_tgt_info *cipinfo = targinfo; 387 struct ipt_clusterip_tgt_info *cipinfo = targinfo;
388 const struct ipt_entry *e = e_void;
388 389
389 struct clusterip_config *config; 390 struct clusterip_config *config;
390 391
diff --git a/net/ipv4/netfilter/ipt_DSCP.c b/net/ipv4/netfilter/ipt_DSCP.c
index 6e319570a28c..898cdf79ce18 100644
--- a/net/ipv4/netfilter/ipt_DSCP.c
+++ b/net/ipv4/netfilter/ipt_DSCP.c
@@ -57,7 +57,7 @@ target(struct sk_buff **pskb,
57 57
58static int 58static int
59checkentry(const char *tablename, 59checkentry(const char *tablename,
60 const struct ipt_entry *e, 60 const void *e_void,
61 void *targinfo, 61 void *targinfo,
62 unsigned int targinfosize, 62 unsigned int targinfosize,
63 unsigned int hook_mask) 63 unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c
index a1319693f648..706445426a6d 100644
--- a/net/ipv4/netfilter/ipt_ECN.c
+++ b/net/ipv4/netfilter/ipt_ECN.c
@@ -113,12 +113,13 @@ target(struct sk_buff **pskb,
113 113
114static int 114static int
115checkentry(const char *tablename, 115checkentry(const char *tablename,
116 const struct ipt_entry *e, 116 const void *e_void,
117 void *targinfo, 117 void *targinfo,
118 unsigned int targinfosize, 118 unsigned int targinfosize,
119 unsigned int hook_mask) 119 unsigned int hook_mask)
120{ 120{
121 const struct ipt_ECN_info *einfo = (struct ipt_ECN_info *)targinfo; 121 const struct ipt_ECN_info *einfo = (struct ipt_ECN_info *)targinfo;
122 const struct ipt_entry *e = e_void;
122 123
123 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ECN_info))) { 124 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ECN_info))) {
124 printk(KERN_WARNING "ECN: targinfosize %u != %Zu\n", 125 printk(KERN_WARNING "ECN: targinfosize %u != %Zu\n",
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
index 30be0f1dae37..6606ddb66a29 100644
--- a/net/ipv4/netfilter/ipt_LOG.c
+++ b/net/ipv4/netfilter/ipt_LOG.c
@@ -431,7 +431,7 @@ ipt_log_target(struct sk_buff **pskb,
431} 431}
432 432
433static int ipt_log_checkentry(const char *tablename, 433static int ipt_log_checkentry(const char *tablename,
434 const struct ipt_entry *e, 434 const void *e,
435 void *targinfo, 435 void *targinfo,
436 unsigned int targinfosize, 436 unsigned int targinfosize,
437 unsigned int hook_mask) 437 unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index 27860510ca6d..12c56d3343ca 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -40,7 +40,7 @@ static DEFINE_RWLOCK(masq_lock);
40/* FIXME: Multiple targets. --RR */ 40/* FIXME: Multiple targets. --RR */
41static int 41static int
42masquerade_check(const char *tablename, 42masquerade_check(const char *tablename,
43 const struct ipt_entry *e, 43 const void *e,
44 void *targinfo, 44 void *targinfo,
45 unsigned int targinfosize, 45 unsigned int targinfosize,
46 unsigned int hook_mask) 46 unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c
index e6e7b6095363..b074467fe67b 100644
--- a/net/ipv4/netfilter/ipt_NETMAP.c
+++ b/net/ipv4/netfilter/ipt_NETMAP.c
@@ -31,7 +31,7 @@ MODULE_DESCRIPTION("iptables 1:1 NAT mapping of IP networks target");
31 31
32static int 32static int
33check(const char *tablename, 33check(const char *tablename,
34 const struct ipt_entry *e, 34 const void *e,
35 void *targinfo, 35 void *targinfo,
36 unsigned int targinfosize, 36 unsigned int targinfosize,
37 unsigned int hook_mask) 37 unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_NFQUEUE.c b/net/ipv4/netfilter/ipt_NFQUEUE.c
deleted file mode 100644
index 3cedc9be8807..000000000000
--- a/net/ipv4/netfilter/ipt_NFQUEUE.c
+++ /dev/null
@@ -1,70 +0,0 @@
1/* iptables module for using new netfilter netlink queue
2 *
3 * (C) 2005 by Harald Welte <laforge@netfilter.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 */
10
11#include <linux/module.h>
12#include <linux/skbuff.h>
13
14#include <linux/netfilter.h>
15#include <linux/netfilter_ipv4/ip_tables.h>
16#include <linux/netfilter_ipv4/ipt_NFQUEUE.h>
17
18MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
19MODULE_DESCRIPTION("iptables NFQUEUE target");
20MODULE_LICENSE("GPL");
21
22static unsigned int
23target(struct sk_buff **pskb,
24 const struct net_device *in,
25 const struct net_device *out,
26 unsigned int hooknum,
27 const void *targinfo,
28 void *userinfo)
29{
30 const struct ipt_NFQ_info *tinfo = targinfo;
31
32 return NF_QUEUE_NR(tinfo->queuenum);
33}
34
35static int
36checkentry(const char *tablename,
37 const struct ipt_entry *e,
38 void *targinfo,
39 unsigned int targinfosize,
40 unsigned int hook_mask)
41{
42 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_NFQ_info))) {
43 printk(KERN_WARNING "NFQUEUE: targinfosize %u != %Zu\n",
44 targinfosize,
45 IPT_ALIGN(sizeof(struct ipt_NFQ_info)));
46 return 0;
47 }
48
49 return 1;
50}
51
52static struct ipt_target ipt_NFQ_reg = {
53 .name = "NFQUEUE",
54 .target = target,
55 .checkentry = checkentry,
56 .me = THIS_MODULE,
57};
58
59static int __init init(void)
60{
61 return ipt_register_target(&ipt_NFQ_reg);
62}
63
64static void __exit fini(void)
65{
66 ipt_unregister_target(&ipt_NFQ_reg);
67}
68
69module_init(init);
70module_exit(fini);
diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c
index 5245bfd33d52..140be51f2f01 100644
--- a/net/ipv4/netfilter/ipt_REDIRECT.c
+++ b/net/ipv4/netfilter/ipt_REDIRECT.c
@@ -33,7 +33,7 @@ MODULE_DESCRIPTION("iptables REDIRECT target module");
33/* FIXME: Take multiple ranges --RR */ 33/* FIXME: Take multiple ranges --RR */
34static int 34static int
35redirect_check(const char *tablename, 35redirect_check(const char *tablename,
36 const struct ipt_entry *e, 36 const void *e,
37 void *targinfo, 37 void *targinfo,
38 unsigned int targinfosize, 38 unsigned int targinfosize,
39 unsigned int hook_mask) 39 unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index 6693526ae128..3eb47aae78c5 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -282,12 +282,13 @@ static unsigned int reject(struct sk_buff **pskb,
282} 282}
283 283
284static int check(const char *tablename, 284static int check(const char *tablename,
285 const struct ipt_entry *e, 285 const void *e_void,
286 void *targinfo, 286 void *targinfo,
287 unsigned int targinfosize, 287 unsigned int targinfosize,
288 unsigned int hook_mask) 288 unsigned int hook_mask)
289{ 289{
290 const struct ipt_reject_info *rejinfo = targinfo; 290 const struct ipt_reject_info *rejinfo = targinfo;
291 const struct ipt_entry *e = e_void;
291 292
292 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_reject_info))) { 293 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_reject_info))) {
293 DEBUGP("REJECT: targinfosize %u != 0\n", targinfosize); 294 DEBUGP("REJECT: targinfosize %u != 0\n", targinfosize);
diff --git a/net/ipv4/netfilter/ipt_SAME.c b/net/ipv4/netfilter/ipt_SAME.c
index 7a0536d864ac..a22de59bba0e 100644
--- a/net/ipv4/netfilter/ipt_SAME.c
+++ b/net/ipv4/netfilter/ipt_SAME.c
@@ -49,7 +49,7 @@ MODULE_DESCRIPTION("iptables special SNAT module for consistent sourceip");
49 49
50static int 50static int
51same_check(const char *tablename, 51same_check(const char *tablename,
52 const struct ipt_entry *e, 52 const void *e,
53 void *targinfo, 53 void *targinfo,
54 unsigned int targinfosize, 54 unsigned int targinfosize,
55 unsigned int hook_mask) 55 unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_TCPMSS.c b/net/ipv4/netfilter/ipt_TCPMSS.c
index 8db70d6908c3..c122841e182c 100644
--- a/net/ipv4/netfilter/ipt_TCPMSS.c
+++ b/net/ipv4/netfilter/ipt_TCPMSS.c
@@ -210,12 +210,13 @@ static inline int find_syn_match(const struct ipt_entry_match *m)
210/* Must specify -p tcp --syn/--tcp-flags SYN */ 210/* Must specify -p tcp --syn/--tcp-flags SYN */
211static int 211static int
212ipt_tcpmss_checkentry(const char *tablename, 212ipt_tcpmss_checkentry(const char *tablename,
213 const struct ipt_entry *e, 213 const void *e_void,
214 void *targinfo, 214 void *targinfo,
215 unsigned int targinfosize, 215 unsigned int targinfosize,
216 unsigned int hook_mask) 216 unsigned int hook_mask)
217{ 217{
218 const struct ipt_tcpmss_info *tcpmssinfo = targinfo; 218 const struct ipt_tcpmss_info *tcpmssinfo = targinfo;
219 const struct ipt_entry *e = e_void;
219 220
220 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_tcpmss_info))) { 221 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_tcpmss_info))) {
221 DEBUGP("ipt_tcpmss_checkentry: targinfosize %u != %u\n", 222 DEBUGP("ipt_tcpmss_checkentry: targinfosize %u != %u\n",
diff --git a/net/ipv4/netfilter/ipt_TOS.c b/net/ipv4/netfilter/ipt_TOS.c
index deadb36d4428..3a44a56db239 100644
--- a/net/ipv4/netfilter/ipt_TOS.c
+++ b/net/ipv4/netfilter/ipt_TOS.c
@@ -52,7 +52,7 @@ target(struct sk_buff **pskb,
52 52
53static int 53static int
54checkentry(const char *tablename, 54checkentry(const char *tablename,
55 const struct ipt_entry *e, 55 const void *e_void,
56 void *targinfo, 56 void *targinfo,
57 unsigned int targinfosize, 57 unsigned int targinfosize,
58 unsigned int hook_mask) 58 unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_TTL.c b/net/ipv4/netfilter/ipt_TTL.c
index b9ae6a9382f3..b769eb231970 100644
--- a/net/ipv4/netfilter/ipt_TTL.c
+++ b/net/ipv4/netfilter/ipt_TTL.c
@@ -66,7 +66,7 @@ ipt_ttl_target(struct sk_buff **pskb, const struct net_device *in,
66} 66}
67 67
68static int ipt_ttl_checkentry(const char *tablename, 68static int ipt_ttl_checkentry(const char *tablename,
69 const struct ipt_entry *e, 69 const void *e,
70 void *targinfo, 70 void *targinfo,
71 unsigned int targinfosize, 71 unsigned int targinfosize,
72 unsigned int hook_mask) 72 unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index 38641cd06123..641dbc477650 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -330,7 +330,7 @@ static void ipt_logfn(unsigned int pf,
330} 330}
331 331
332static int ipt_ulog_checkentry(const char *tablename, 332static int ipt_ulog_checkentry(const char *tablename,
333 const struct ipt_entry *e, 333 const void *e,
334 void *targinfo, 334 void *targinfo,
335 unsigned int targinfosize, 335 unsigned int targinfosize,
336 unsigned int hookmask) 336 unsigned int hookmask)
diff --git a/net/ipv4/netfilter/ipt_addrtype.c b/net/ipv4/netfilter/ipt_addrtype.c
index e19c2a52d00c..d6b83a976518 100644
--- a/net/ipv4/netfilter/ipt_addrtype.c
+++ b/net/ipv4/netfilter/ipt_addrtype.c
@@ -29,7 +29,7 @@ static inline int match_type(u_int32_t addr, u_int16_t mask)
29 29
30static int match(const struct sk_buff *skb, const struct net_device *in, 30static int match(const struct sk_buff *skb, const struct net_device *in,
31 const struct net_device *out, const void *matchinfo, 31 const struct net_device *out, const void *matchinfo,
32 int offset, int *hotdrop) 32 int offset, unsigned int protoff, int *hotdrop)
33{ 33{
34 const struct ipt_addrtype_info *info = matchinfo; 34 const struct ipt_addrtype_info *info = matchinfo;
35 const struct iphdr *iph = skb->nh.iph; 35 const struct iphdr *iph = skb->nh.iph;
@@ -43,7 +43,7 @@ static int match(const struct sk_buff *skb, const struct net_device *in,
43 return ret; 43 return ret;
44} 44}
45 45
46static int checkentry(const char *tablename, const struct ipt_ip *ip, 46static int checkentry(const char *tablename, const void *ip,
47 void *matchinfo, unsigned int matchsize, 47 void *matchinfo, unsigned int matchsize,
48 unsigned int hook_mask) 48 unsigned int hook_mask)
49{ 49{
diff --git a/net/ipv4/netfilter/ipt_ah.c b/net/ipv4/netfilter/ipt_ah.c
index a0fea847cb72..144adfec13cc 100644
--- a/net/ipv4/netfilter/ipt_ah.c
+++ b/net/ipv4/netfilter/ipt_ah.c
@@ -41,6 +41,7 @@ match(const struct sk_buff *skb,
41 const struct net_device *out, 41 const struct net_device *out,
42 const void *matchinfo, 42 const void *matchinfo,
43 int offset, 43 int offset,
44 unsigned int protoff,
44 int *hotdrop) 45 int *hotdrop)
45{ 46{
46 struct ip_auth_hdr _ahdr, *ah; 47 struct ip_auth_hdr _ahdr, *ah;
@@ -50,7 +51,7 @@ match(const struct sk_buff *skb,
50 if (offset) 51 if (offset)
51 return 0; 52 return 0;
52 53
53 ah = skb_header_pointer(skb, skb->nh.iph->ihl * 4, 54 ah = skb_header_pointer(skb, protoff,
54 sizeof(_ahdr), &_ahdr); 55 sizeof(_ahdr), &_ahdr);
55 if (ah == NULL) { 56 if (ah == NULL) {
56 /* We've been asked to examine this packet, and we 57 /* We've been asked to examine this packet, and we
@@ -69,12 +70,13 @@ match(const struct sk_buff *skb,
69/* Called when user tries to insert an entry of this type. */ 70/* Called when user tries to insert an entry of this type. */
70static int 71static int
71checkentry(const char *tablename, 72checkentry(const char *tablename,
72 const struct ipt_ip *ip, 73 const void *ip_void,
73 void *matchinfo, 74 void *matchinfo,
74 unsigned int matchinfosize, 75 unsigned int matchinfosize,
75 unsigned int hook_mask) 76 unsigned int hook_mask)
76{ 77{
77 const struct ipt_ah *ahinfo = matchinfo; 78 const struct ipt_ah *ahinfo = matchinfo;
79 const struct ipt_ip *ip = ip_void;
78 80
79 /* Must specify proto == AH, and no unknown invflags */ 81 /* Must specify proto == AH, and no unknown invflags */
80 if (ip->proto != IPPROTO_AH || (ip->invflags & IPT_INV_PROTO)) { 82 if (ip->proto != IPPROTO_AH || (ip->invflags & IPT_INV_PROTO)) {
diff --git a/net/ipv4/netfilter/ipt_dscp.c b/net/ipv4/netfilter/ipt_dscp.c
index 5df52a64a5d4..92063b4f8602 100644
--- a/net/ipv4/netfilter/ipt_dscp.c
+++ b/net/ipv4/netfilter/ipt_dscp.c
@@ -21,7 +21,7 @@ MODULE_LICENSE("GPL");
21 21
22static int match(const struct sk_buff *skb, const struct net_device *in, 22static int match(const struct sk_buff *skb, const struct net_device *in,
23 const struct net_device *out, const void *matchinfo, 23 const struct net_device *out, const void *matchinfo,
24 int offset, int *hotdrop) 24 int offset, unsigned int protoff, int *hotdrop)
25{ 25{
26 const struct ipt_dscp_info *info = matchinfo; 26 const struct ipt_dscp_info *info = matchinfo;
27 const struct iphdr *iph = skb->nh.iph; 27 const struct iphdr *iph = skb->nh.iph;
@@ -31,7 +31,7 @@ static int match(const struct sk_buff *skb, const struct net_device *in,
31 return ((iph->tos&IPT_DSCP_MASK) == sh_dscp) ^ info->invert; 31 return ((iph->tos&IPT_DSCP_MASK) == sh_dscp) ^ info->invert;
32} 32}
33 33
34static int checkentry(const char *tablename, const struct ipt_ip *ip, 34static int checkentry(const char *tablename, const void *ip,
35 void *matchinfo, unsigned int matchsize, 35 void *matchinfo, unsigned int matchsize,
36 unsigned int hook_mask) 36 unsigned int hook_mask)
37{ 37{
diff --git a/net/ipv4/netfilter/ipt_ecn.c b/net/ipv4/netfilter/ipt_ecn.c
index b6f7181e89cc..e68b0c7981f0 100644
--- a/net/ipv4/netfilter/ipt_ecn.c
+++ b/net/ipv4/netfilter/ipt_ecn.c
@@ -67,7 +67,7 @@ static inline int match_tcp(const struct sk_buff *skb,
67 67
68static int match(const struct sk_buff *skb, const struct net_device *in, 68static int match(const struct sk_buff *skb, const struct net_device *in,
69 const struct net_device *out, const void *matchinfo, 69 const struct net_device *out, const void *matchinfo,
70 int offset, int *hotdrop) 70 int offset, unsigned int protoff, int *hotdrop)
71{ 71{
72 const struct ipt_ecn_info *info = matchinfo; 72 const struct ipt_ecn_info *info = matchinfo;
73 73
@@ -85,11 +85,12 @@ static int match(const struct sk_buff *skb, const struct net_device *in,
85 return 1; 85 return 1;
86} 86}
87 87
88static int checkentry(const char *tablename, const struct ipt_ip *ip, 88static int checkentry(const char *tablename, const void *ip_void,
89 void *matchinfo, unsigned int matchsize, 89 void *matchinfo, unsigned int matchsize,
90 unsigned int hook_mask) 90 unsigned int hook_mask)
91{ 91{
92 const struct ipt_ecn_info *info = matchinfo; 92 const struct ipt_ecn_info *info = matchinfo;
93 const struct ipt_ip *ip = ip_void;
93 94
94 if (matchsize != IPT_ALIGN(sizeof(struct ipt_ecn_info))) 95 if (matchsize != IPT_ALIGN(sizeof(struct ipt_ecn_info)))
95 return 0; 96 return 0;
diff --git a/net/ipv4/netfilter/ipt_esp.c b/net/ipv4/netfilter/ipt_esp.c
index e1d0dd31e117..9de191a8162d 100644
--- a/net/ipv4/netfilter/ipt_esp.c
+++ b/net/ipv4/netfilter/ipt_esp.c
@@ -42,6 +42,7 @@ match(const struct sk_buff *skb,
42 const struct net_device *out, 42 const struct net_device *out,
43 const void *matchinfo, 43 const void *matchinfo,
44 int offset, 44 int offset,
45 unsigned int protoff,
45 int *hotdrop) 46 int *hotdrop)
46{ 47{
47 struct ip_esp_hdr _esp, *eh; 48 struct ip_esp_hdr _esp, *eh;
@@ -51,7 +52,7 @@ match(const struct sk_buff *skb,
51 if (offset) 52 if (offset)
52 return 0; 53 return 0;
53 54
54 eh = skb_header_pointer(skb, skb->nh.iph->ihl * 4, 55 eh = skb_header_pointer(skb, protoff,
55 sizeof(_esp), &_esp); 56 sizeof(_esp), &_esp);
56 if (eh == NULL) { 57 if (eh == NULL) {
57 /* We've been asked to examine this packet, and we 58 /* We've been asked to examine this packet, and we
@@ -70,12 +71,13 @@ match(const struct sk_buff *skb,
70/* Called when user tries to insert an entry of this type. */ 71/* Called when user tries to insert an entry of this type. */
71static int 72static int
72checkentry(const char *tablename, 73checkentry(const char *tablename,
73 const struct ipt_ip *ip, 74 const void *ip_void,
74 void *matchinfo, 75 void *matchinfo,
75 unsigned int matchinfosize, 76 unsigned int matchinfosize,
76 unsigned int hook_mask) 77 unsigned int hook_mask)
77{ 78{
78 const struct ipt_esp *espinfo = matchinfo; 79 const struct ipt_esp *espinfo = matchinfo;
80 const struct ipt_ip *ip = ip_void;
79 81
80 /* Must specify proto == ESP, and no unknown invflags */ 82 /* Must specify proto == ESP, and no unknown invflags */
81 if (ip->proto != IPPROTO_ESP || (ip->invflags & IPT_INV_PROTO)) { 83 if (ip->proto != IPPROTO_ESP || (ip->invflags & IPT_INV_PROTO)) {
diff --git a/net/ipv4/netfilter/ipt_hashlimit.c b/net/ipv4/netfilter/ipt_hashlimit.c
index 2dd1cccbdab9..4fe48c1bd5f3 100644
--- a/net/ipv4/netfilter/ipt_hashlimit.c
+++ b/net/ipv4/netfilter/ipt_hashlimit.c
@@ -429,6 +429,7 @@ hashlimit_match(const struct sk_buff *skb,
429 const struct net_device *out, 429 const struct net_device *out,
430 const void *matchinfo, 430 const void *matchinfo,
431 int offset, 431 int offset,
432 unsigned int protoff,
432 int *hotdrop) 433 int *hotdrop)
433{ 434{
434 struct ipt_hashlimit_info *r = 435 struct ipt_hashlimit_info *r =
@@ -504,7 +505,7 @@ hashlimit_match(const struct sk_buff *skb,
504 505
505static int 506static int
506hashlimit_checkentry(const char *tablename, 507hashlimit_checkentry(const char *tablename,
507 const struct ipt_ip *ip, 508 const void *inf,
508 void *matchinfo, 509 void *matchinfo,
509 unsigned int matchsize, 510 unsigned int matchsize,
510 unsigned int hook_mask) 511 unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_iprange.c b/net/ipv4/netfilter/ipt_iprange.c
index b835b7b2e560..13fb16fb7892 100644
--- a/net/ipv4/netfilter/ipt_iprange.c
+++ b/net/ipv4/netfilter/ipt_iprange.c
@@ -28,7 +28,7 @@ match(const struct sk_buff *skb,
28 const struct net_device *in, 28 const struct net_device *in,
29 const struct net_device *out, 29 const struct net_device *out,
30 const void *matchinfo, 30 const void *matchinfo,
31 int offset, int *hotdrop) 31 int offset, unsigned int protoff, int *hotdrop)
32{ 32{
33 const struct ipt_iprange_info *info = matchinfo; 33 const struct ipt_iprange_info *info = matchinfo;
34 const struct iphdr *iph = skb->nh.iph; 34 const struct iphdr *iph = skb->nh.iph;
@@ -63,7 +63,7 @@ match(const struct sk_buff *skb,
63} 63}
64 64
65static int check(const char *tablename, 65static int check(const char *tablename,
66 const struct ipt_ip *ip, 66 const void *inf,
67 void *matchinfo, 67 void *matchinfo,
68 unsigned int matchsize, 68 unsigned int matchsize,
69 unsigned int hook_mask) 69 unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_length.c b/net/ipv4/netfilter/ipt_length.c
deleted file mode 100644
index 4eabcfbda9d1..000000000000
--- a/net/ipv4/netfilter/ipt_length.c
+++ /dev/null
@@ -1,64 +0,0 @@
1/* Kernel module to match packet length. */
2/* (C) 1999-2001 James Morris <jmorros@intercode.com.au>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/module.h>
10#include <linux/skbuff.h>
11
12#include <linux/netfilter_ipv4/ipt_length.h>
13#include <linux/netfilter_ipv4/ip_tables.h>
14
15MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
16MODULE_DESCRIPTION("IP tables packet length matching module");
17MODULE_LICENSE("GPL");
18
19static int
20match(const struct sk_buff *skb,
21 const struct net_device *in,
22 const struct net_device *out,
23 const void *matchinfo,
24 int offset,
25 int *hotdrop)
26{
27 const struct ipt_length_info *info = matchinfo;
28 u_int16_t pktlen = ntohs(skb->nh.iph->tot_len);
29
30 return (pktlen >= info->min && pktlen <= info->max) ^ info->invert;
31}
32
33static int
34checkentry(const char *tablename,
35 const struct ipt_ip *ip,
36 void *matchinfo,
37 unsigned int matchsize,
38 unsigned int hook_mask)
39{
40 if (matchsize != IPT_ALIGN(sizeof(struct ipt_length_info)))
41 return 0;
42
43 return 1;
44}
45
46static struct ipt_match length_match = {
47 .name = "length",
48 .match = &match,
49 .checkentry = &checkentry,
50 .me = THIS_MODULE,
51};
52
53static int __init init(void)
54{
55 return ipt_register_match(&length_match);
56}
57
58static void __exit fini(void)
59{
60 ipt_unregister_match(&length_match);
61}
62
63module_init(init);
64module_exit(fini);
diff --git a/net/ipv4/netfilter/ipt_multiport.c b/net/ipv4/netfilter/ipt_multiport.c
index 99e8188162e2..2d52326553f1 100644
--- a/net/ipv4/netfilter/ipt_multiport.c
+++ b/net/ipv4/netfilter/ipt_multiport.c
@@ -97,6 +97,7 @@ match(const struct sk_buff *skb,
97 const struct net_device *out, 97 const struct net_device *out,
98 const void *matchinfo, 98 const void *matchinfo,
99 int offset, 99 int offset,
100 unsigned int protoff,
100 int *hotdrop) 101 int *hotdrop)
101{ 102{
102 u16 _ports[2], *pptr; 103 u16 _ports[2], *pptr;
@@ -105,7 +106,7 @@ match(const struct sk_buff *skb,
105 if (offset) 106 if (offset)
106 return 0; 107 return 0;
107 108
108 pptr = skb_header_pointer(skb, skb->nh.iph->ihl * 4, 109 pptr = skb_header_pointer(skb, protoff,
109 sizeof(_ports), _ports); 110 sizeof(_ports), _ports);
110 if (pptr == NULL) { 111 if (pptr == NULL) {
111 /* We've been asked to examine this packet, and we 112 /* We've been asked to examine this packet, and we
@@ -128,6 +129,7 @@ match_v1(const struct sk_buff *skb,
128 const struct net_device *out, 129 const struct net_device *out,
129 const void *matchinfo, 130 const void *matchinfo,
130 int offset, 131 int offset,
132 unsigned int protoff,
131 int *hotdrop) 133 int *hotdrop)
132{ 134{
133 u16 _ports[2], *pptr; 135 u16 _ports[2], *pptr;
@@ -136,7 +138,7 @@ match_v1(const struct sk_buff *skb,
136 if (offset) 138 if (offset)
137 return 0; 139 return 0;
138 140
139 pptr = skb_header_pointer(skb, skb->nh.iph->ihl * 4, 141 pptr = skb_header_pointer(skb, protoff,
140 sizeof(_ports), _ports); 142 sizeof(_ports), _ports);
141 if (pptr == NULL) { 143 if (pptr == NULL) {
142 /* We've been asked to examine this packet, and we 144 /* We've been asked to examine this packet, and we
@@ -154,7 +156,7 @@ match_v1(const struct sk_buff *skb,
154/* Called when user tries to insert an entry of this type. */ 156/* Called when user tries to insert an entry of this type. */
155static int 157static int
156checkentry(const char *tablename, 158checkentry(const char *tablename,
157 const struct ipt_ip *ip, 159 const void *ip,
158 void *matchinfo, 160 void *matchinfo,
159 unsigned int matchsize, 161 unsigned int matchsize,
160 unsigned int hook_mask) 162 unsigned int hook_mask)
@@ -164,7 +166,7 @@ checkentry(const char *tablename,
164 166
165static int 167static int
166checkentry_v1(const char *tablename, 168checkentry_v1(const char *tablename,
167 const struct ipt_ip *ip, 169 const void *ip,
168 void *matchinfo, 170 void *matchinfo,
169 unsigned int matchsize, 171 unsigned int matchsize,
170 unsigned int hook_mask) 172 unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_owner.c b/net/ipv4/netfilter/ipt_owner.c
index 0cee2862ed85..4843d0c9734f 100644
--- a/net/ipv4/netfilter/ipt_owner.c
+++ b/net/ipv4/netfilter/ipt_owner.c
@@ -27,6 +27,7 @@ match(const struct sk_buff *skb,
27 const struct net_device *out, 27 const struct net_device *out,
28 const void *matchinfo, 28 const void *matchinfo,
29 int offset, 29 int offset,
30 unsigned int protoff,
30 int *hotdrop) 31 int *hotdrop)
31{ 32{
32 const struct ipt_owner_info *info = matchinfo; 33 const struct ipt_owner_info *info = matchinfo;
@@ -51,7 +52,7 @@ match(const struct sk_buff *skb,
51 52
52static int 53static int
53checkentry(const char *tablename, 54checkentry(const char *tablename,
54 const struct ipt_ip *ip, 55 const void *ip,
55 void *matchinfo, 56 void *matchinfo,
56 unsigned int matchsize, 57 unsigned int matchsize,
57 unsigned int hook_mask) 58 unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_physdev.c b/net/ipv4/netfilter/ipt_physdev.c
deleted file mode 100644
index 03f554857a4d..000000000000
--- a/net/ipv4/netfilter/ipt_physdev.c
+++ /dev/null
@@ -1,135 +0,0 @@
1/* Kernel module to match the bridge port in and
2 * out device for IP packets coming into contact with a bridge. */
3
4/* (C) 2001-2003 Bart De Schuymer <bdschuym@pandora.be>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/module.h>
12#include <linux/netdevice.h>
13#include <linux/skbuff.h>
14#include <linux/netfilter_ipv4/ipt_physdev.h>
15#include <linux/netfilter_ipv4/ip_tables.h>
16#include <linux/netfilter_bridge.h>
17#define MATCH 1
18#define NOMATCH 0
19
20MODULE_LICENSE("GPL");
21MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
22MODULE_DESCRIPTION("iptables bridge physical device match module");
23
24static int
25match(const struct sk_buff *skb,
26 const struct net_device *in,
27 const struct net_device *out,
28 const void *matchinfo,
29 int offset,
30 int *hotdrop)
31{
32 int i;
33 static const char nulldevname[IFNAMSIZ];
34 const struct ipt_physdev_info *info = matchinfo;
35 unsigned int ret;
36 const char *indev, *outdev;
37 struct nf_bridge_info *nf_bridge;
38
39 /* Not a bridged IP packet or no info available yet:
40 * LOCAL_OUT/mangle and LOCAL_OUT/nat don't know if
41 * the destination device will be a bridge. */
42 if (!(nf_bridge = skb->nf_bridge)) {
43 /* Return MATCH if the invert flags of the used options are on */
44 if ((info->bitmask & IPT_PHYSDEV_OP_BRIDGED) &&
45 !(info->invert & IPT_PHYSDEV_OP_BRIDGED))
46 return NOMATCH;
47 if ((info->bitmask & IPT_PHYSDEV_OP_ISIN) &&
48 !(info->invert & IPT_PHYSDEV_OP_ISIN))
49 return NOMATCH;
50 if ((info->bitmask & IPT_PHYSDEV_OP_ISOUT) &&
51 !(info->invert & IPT_PHYSDEV_OP_ISOUT))
52 return NOMATCH;
53 if ((info->bitmask & IPT_PHYSDEV_OP_IN) &&
54 !(info->invert & IPT_PHYSDEV_OP_IN))
55 return NOMATCH;
56 if ((info->bitmask & IPT_PHYSDEV_OP_OUT) &&
57 !(info->invert & IPT_PHYSDEV_OP_OUT))
58 return NOMATCH;
59 return MATCH;
60 }
61
62 /* This only makes sense in the FORWARD and POSTROUTING chains */
63 if ((info->bitmask & IPT_PHYSDEV_OP_BRIDGED) &&
64 (!!(nf_bridge->mask & BRNF_BRIDGED) ^
65 !(info->invert & IPT_PHYSDEV_OP_BRIDGED)))
66 return NOMATCH;
67
68 if ((info->bitmask & IPT_PHYSDEV_OP_ISIN &&
69 (!nf_bridge->physindev ^ !!(info->invert & IPT_PHYSDEV_OP_ISIN))) ||
70 (info->bitmask & IPT_PHYSDEV_OP_ISOUT &&
71 (!nf_bridge->physoutdev ^ !!(info->invert & IPT_PHYSDEV_OP_ISOUT))))
72 return NOMATCH;
73
74 if (!(info->bitmask & IPT_PHYSDEV_OP_IN))
75 goto match_outdev;
76 indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname;
77 for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) {
78 ret |= (((const unsigned int *)indev)[i]
79 ^ ((const unsigned int *)info->physindev)[i])
80 & ((const unsigned int *)info->in_mask)[i];
81 }
82
83 if ((ret == 0) ^ !(info->invert & IPT_PHYSDEV_OP_IN))
84 return NOMATCH;
85
86match_outdev:
87 if (!(info->bitmask & IPT_PHYSDEV_OP_OUT))
88 return MATCH;
89 outdev = nf_bridge->physoutdev ?
90 nf_bridge->physoutdev->name : nulldevname;
91 for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) {
92 ret |= (((const unsigned int *)outdev)[i]
93 ^ ((const unsigned int *)info->physoutdev)[i])
94 & ((const unsigned int *)info->out_mask)[i];
95 }
96
97 return (ret != 0) ^ !(info->invert & IPT_PHYSDEV_OP_OUT);
98}
99
100static int
101checkentry(const char *tablename,
102 const struct ipt_ip *ip,
103 void *matchinfo,
104 unsigned int matchsize,
105 unsigned int hook_mask)
106{
107 const struct ipt_physdev_info *info = matchinfo;
108
109 if (matchsize != IPT_ALIGN(sizeof(struct ipt_physdev_info)))
110 return 0;
111 if (!(info->bitmask & IPT_PHYSDEV_OP_MASK) ||
112 info->bitmask & ~IPT_PHYSDEV_OP_MASK)
113 return 0;
114 return 1;
115}
116
117static struct ipt_match physdev_match = {
118 .name = "physdev",
119 .match = &match,
120 .checkentry = &checkentry,
121 .me = THIS_MODULE,
122};
123
124static int __init init(void)
125{
126 return ipt_register_match(&physdev_match);
127}
128
129static void __exit fini(void)
130{
131 ipt_unregister_match(&physdev_match);
132}
133
134module_init(init);
135module_exit(fini);
diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c
index 5ddccb18c65e..44611d6d14f5 100644
--- a/net/ipv4/netfilter/ipt_recent.c
+++ b/net/ipv4/netfilter/ipt_recent.c
@@ -104,6 +104,7 @@ match(const struct sk_buff *skb,
104 const struct net_device *out, 104 const struct net_device *out,
105 const void *matchinfo, 105 const void *matchinfo,
106 int offset, 106 int offset,
107 unsigned int protoff,
107 int *hotdrop); 108 int *hotdrop);
108 109
109/* Function to hash a given address into the hash table of table_size size */ 110/* Function to hash a given address into the hash table of table_size size */
@@ -317,7 +318,7 @@ static int ip_recent_ctrl(struct file *file, const char __user *input, unsigned
317 skb->nh.iph->daddr = 0; 318 skb->nh.iph->daddr = 0;
318 /* Clear ttl since we have no way of knowing it */ 319 /* Clear ttl since we have no way of knowing it */
319 skb->nh.iph->ttl = 0; 320 skb->nh.iph->ttl = 0;
320 match(skb,NULL,NULL,info,0,NULL); 321 match(skb,NULL,NULL,info,0,0,NULL);
321 322
322 kfree(skb->nh.iph); 323 kfree(skb->nh.iph);
323out_free_skb: 324out_free_skb:
@@ -357,6 +358,7 @@ match(const struct sk_buff *skb,
357 const struct net_device *out, 358 const struct net_device *out,
358 const void *matchinfo, 359 const void *matchinfo,
359 int offset, 360 int offset,
361 unsigned int protoff,
360 int *hotdrop) 362 int *hotdrop)
361{ 363{
362 int pkt_count, hits_found, ans; 364 int pkt_count, hits_found, ans;
@@ -654,7 +656,7 @@ match(const struct sk_buff *skb,
654 */ 656 */
655static int 657static int
656checkentry(const char *tablename, 658checkentry(const char *tablename,
657 const struct ipt_ip *ip, 659 const void *ip,
658 void *matchinfo, 660 void *matchinfo,
659 unsigned int matchsize, 661 unsigned int matchsize,
660 unsigned int hook_mask) 662 unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_tos.c b/net/ipv4/netfilter/ipt_tos.c
index 086a1bb61e3e..9ab765e126f2 100644
--- a/net/ipv4/netfilter/ipt_tos.c
+++ b/net/ipv4/netfilter/ipt_tos.c
@@ -23,6 +23,7 @@ match(const struct sk_buff *skb,
23 const struct net_device *out, 23 const struct net_device *out,
24 const void *matchinfo, 24 const void *matchinfo,
25 int offset, 25 int offset,
26 unsigned int protoff,
26 int *hotdrop) 27 int *hotdrop)
27{ 28{
28 const struct ipt_tos_info *info = matchinfo; 29 const struct ipt_tos_info *info = matchinfo;
@@ -32,7 +33,7 @@ match(const struct sk_buff *skb,
32 33
33static int 34static int
34checkentry(const char *tablename, 35checkentry(const char *tablename,
35 const struct ipt_ip *ip, 36 const void *ip,
36 void *matchinfo, 37 void *matchinfo,
37 unsigned int matchsize, 38 unsigned int matchsize,
38 unsigned int hook_mask) 39 unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_ttl.c b/net/ipv4/netfilter/ipt_ttl.c
index 219aa9de88cc..82da53f430ab 100644
--- a/net/ipv4/netfilter/ipt_ttl.c
+++ b/net/ipv4/netfilter/ipt_ttl.c
@@ -21,7 +21,7 @@ MODULE_LICENSE("GPL");
21 21
22static int match(const struct sk_buff *skb, const struct net_device *in, 22static int match(const struct sk_buff *skb, const struct net_device *in,
23 const struct net_device *out, const void *matchinfo, 23 const struct net_device *out, const void *matchinfo,
24 int offset, int *hotdrop) 24 int offset, unsigned int protoff, int *hotdrop)
25{ 25{
26 const struct ipt_ttl_info *info = matchinfo; 26 const struct ipt_ttl_info *info = matchinfo;
27 27
@@ -47,7 +47,7 @@ static int match(const struct sk_buff *skb, const struct net_device *in,
47 return 0; 47 return 0;
48} 48}
49 49
50static int checkentry(const char *tablename, const struct ipt_ip *ip, 50static int checkentry(const char *tablename, const void *ip,
51 void *matchinfo, unsigned int matchsize, 51 void *matchinfo, unsigned int matchsize,
52 unsigned int hook_mask) 52 unsigned int hook_mask)
53{ 53{
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
index 260a4f0a2a90..212a3079085b 100644
--- a/net/ipv4/netfilter/iptable_filter.c
+++ b/net/ipv4/netfilter/iptable_filter.c
@@ -78,7 +78,8 @@ static struct ipt_table packet_filter = {
78 .name = "filter", 78 .name = "filter",
79 .valid_hooks = FILTER_VALID_HOOKS, 79 .valid_hooks = FILTER_VALID_HOOKS,
80 .lock = RW_LOCK_UNLOCKED, 80 .lock = RW_LOCK_UNLOCKED,
81 .me = THIS_MODULE 81 .me = THIS_MODULE,
82 .af = AF_INET,
82}; 83};
83 84
84/* The work comes in here from netfilter.c. */ 85/* The work comes in here from netfilter.c. */
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index 160eb11b6e2f..3212a5cc4b6b 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -109,6 +109,7 @@ static struct ipt_table packet_mangler = {
109 .valid_hooks = MANGLE_VALID_HOOKS, 109 .valid_hooks = MANGLE_VALID_HOOKS,
110 .lock = RW_LOCK_UNLOCKED, 110 .lock = RW_LOCK_UNLOCKED,
111 .me = THIS_MODULE, 111 .me = THIS_MODULE,
112 .af = AF_INET,
112}; 113};
113 114
114/* The work comes in here from netfilter.c. */ 115/* The work comes in here from netfilter.c. */
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
index 47449ba83eb9..fdb9e9c81e81 100644
--- a/net/ipv4/netfilter/iptable_raw.c
+++ b/net/ipv4/netfilter/iptable_raw.c
@@ -83,7 +83,8 @@ static struct ipt_table packet_raw = {
83 .name = "raw", 83 .name = "raw",
84 .valid_hooks = RAW_VALID_HOOKS, 84 .valid_hooks = RAW_VALID_HOOKS,
85 .lock = RW_LOCK_UNLOCKED, 85 .lock = RW_LOCK_UNLOCKED,
86 .me = THIS_MODULE 86 .me = THIS_MODULE,
87 .af = AF_INET,
87}; 88};
88 89
89/* The work comes in here from netfilter.c. */ 90/* The work comes in here from netfilter.c. */
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index 0c56c52a3831..167619f638c6 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -575,7 +575,7 @@ MODULE_LICENSE("GPL");
575 575
576static int __init init(void) 576static int __init init(void)
577{ 577{
578 need_nf_conntrack(); 578 need_conntrack();
579 return init_or_cleanup(1); 579 return init_or_cleanup(1);
580} 580}
581 581
@@ -587,9 +587,4 @@ static void __exit fini(void)
587module_init(init); 587module_init(init);
588module_exit(fini); 588module_exit(fini);
589 589
590void need_ip_conntrack(void)
591{
592}
593
594EXPORT_SYMBOL(need_ip_conntrack);
595EXPORT_SYMBOL(nf_ct_ipv4_gather_frags); 590EXPORT_SYMBOL(nf_ct_ipv4_gather_frags);
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c
index d23e07fc81fa..dbabf81a9b7b 100644
--- a/net/ipv4/xfrm4_state.c
+++ b/net/ipv4/xfrm4_state.c
@@ -42,6 +42,21 @@ __xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl,
42 x->props.saddr = tmpl->saddr; 42 x->props.saddr = tmpl->saddr;
43 if (x->props.saddr.a4 == 0) 43 if (x->props.saddr.a4 == 0)
44 x->props.saddr.a4 = saddr->a4; 44 x->props.saddr.a4 = saddr->a4;
45 if (tmpl->mode && x->props.saddr.a4 == 0) {
46 struct rtable *rt;
47 struct flowi fl_tunnel = {
48 .nl_u = {
49 .ip4_u = {
50 .daddr = x->id.daddr.a4,
51 }
52 }
53 };
54 if (!xfrm_dst_lookup((struct xfrm_dst **)&rt,
55 &fl_tunnel, AF_INET)) {
56 x->props.saddr.a4 = rt->rt_src;
57 dst_release(&rt->u.dst);
58 }
59 }
45 x->props.mode = tmpl->mode; 60 x->props.mode = tmpl->mode;
46 x->props.reqid = tmpl->reqid; 61 x->props.reqid = tmpl->reqid;
47 x->props.family = AF_INET; 62 x->props.family = AF_INET;
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 7129d4239755..dfb4f145a139 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -2644,7 +2644,7 @@ static int if6_seq_show(struct seq_file *seq, void *v)
2644{ 2644{
2645 struct inet6_ifaddr *ifp = (struct inet6_ifaddr *)v; 2645 struct inet6_ifaddr *ifp = (struct inet6_ifaddr *)v;
2646 seq_printf(seq, 2646 seq_printf(seq,
2647 "%04x%04x%04x%04x%04x%04x%04x%04x %02x %02x %02x %02x %8s\n", 2647 NIP6_FMT " %02x %02x %02x %02x %8s\n",
2648 NIP6(ifp->addr), 2648 NIP6(ifp->addr),
2649 ifp->idev->dev->ifindex, 2649 ifp->idev->dev->ifindex,
2650 ifp->prefix_len, 2650 ifp->prefix_len,
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index 13cc7f895583..c7932cb420a5 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -332,8 +332,7 @@ static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
332 if (!x) 332 if (!x)
333 return; 333 return;
334 334
335 NETDEBUG(KERN_DEBUG "pmtu discovery on SA AH/%08x/" 335 NETDEBUG(KERN_DEBUG "pmtu discovery on SA AH/%08x/" NIP6_FMT "\n",
336 "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
337 ntohl(ah->spi), NIP6(iph->daddr)); 336 ntohl(ah->spi), NIP6(iph->daddr));
338 337
339 xfrm_state_put(x); 338 xfrm_state_put(x);
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
index 65e73ac0d6d0..72bd08af2dfb 100644
--- a/net/ipv6/anycast.c
+++ b/net/ipv6/anycast.c
@@ -532,9 +532,7 @@ static int ac6_seq_show(struct seq_file *seq, void *v)
532 struct ac6_iter_state *state = ac6_seq_private(seq); 532 struct ac6_iter_state *state = ac6_seq_private(seq);
533 533
534 seq_printf(seq, 534 seq_printf(seq,
535 "%-4d %-15s " 535 "%-4d %-15s " NIP6_FMT " %5d\n",
536 "%04x%04x%04x%04x%04x%04x%04x%04x "
537 "%5d\n",
538 state->dev->ifindex, state->dev->name, 536 state->dev->ifindex, state->dev->name,
539 NIP6(im->aca_addr), 537 NIP6(im->aca_addr),
540 im->aca_users); 538 im->aca_users);
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 6de8ee1a5ad9..7b5b94f13902 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -266,8 +266,7 @@ static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
266 x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET6); 266 x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET6);
267 if (!x) 267 if (!x)
268 return; 268 return;
269 printk(KERN_DEBUG "pmtu discovery on SA ESP/%08x/" 269 printk(KERN_DEBUG "pmtu discovery on SA ESP/%08x/" NIP6_FMT "\n",
270 "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
271 ntohl(esph->spi), NIP6(iph->daddr)); 270 ntohl(esph->spi), NIP6(iph->daddr));
272 xfrm_state_put(x); 271 xfrm_state_put(x);
273} 272}
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 53c81fcd20ba..fcf883183cef 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -607,7 +607,7 @@ static int icmpv6_rcv(struct sk_buff **pskb)
607 skb->csum = ~csum_ipv6_magic(saddr, daddr, skb->len, 607 skb->csum = ~csum_ipv6_magic(saddr, daddr, skb->len,
608 IPPROTO_ICMPV6, 0); 608 IPPROTO_ICMPV6, 0);
609 if (__skb_checksum_complete(skb)) { 609 if (__skb_checksum_complete(skb)) {
610 LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x > %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]\n", 610 LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [" NIP6_FMT " > " NIP6_FMT "]\n",
611 NIP6(*saddr), NIP6(*daddr)); 611 NIP6(*saddr), NIP6(*daddr));
612 goto discard_it; 612 goto discard_it;
613 } 613 }
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index 964ad9d1276d..4183c8dac7f6 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -629,9 +629,7 @@ static void ip6fl_fl_seq_show(struct seq_file *seq, struct ip6_flowlabel *fl)
629{ 629{
630 while(fl) { 630 while(fl) {
631 seq_printf(seq, 631 seq_printf(seq,
632 "%05X %-1d %-6d %-6d %-6ld %-8ld " 632 "%05X %-1d %-6d %-6d %-6ld %-8ld " NIP6_FMT " %-4d\n",
633 "%02x%02x%02x%02x%02x%02x%02x%02x "
634 "%-4d\n",
635 (unsigned)ntohl(fl->label), 633 (unsigned)ntohl(fl->label),
636 fl->share, 634 fl->share,
637 (unsigned)fl->owner, 635 (unsigned)fl->owner,
@@ -647,8 +645,8 @@ static void ip6fl_fl_seq_show(struct seq_file *seq, struct ip6_flowlabel *fl)
647static int ip6fl_seq_show(struct seq_file *seq, void *v) 645static int ip6fl_seq_show(struct seq_file *seq, void *v)
648{ 646{
649 if (v == SEQ_START_TOKEN) 647 if (v == SEQ_START_TOKEN)
650 seq_puts(seq, "Label S Owner Users Linger Expires " 648 seq_printf(seq, "%-5s %-1s %-6s %-6s %-6s %-8s %-39s %s\n",
651 "Dst Opt\n"); 649 "Label", "S", "Owner", "Users", "Linger", "Expires", "Dst", "Opt");
652 else 650 else
653 ip6fl_fl_seq_show(seq, v); 651 ip6fl_fl_seq_show(seq, v);
654 return 0; 652 return 0;
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index 626dd39685f2..d511a884dad0 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -212,8 +212,7 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
212 if (!x) 212 if (!x)
213 return; 213 return;
214 214
215 printk(KERN_DEBUG "pmtu discovery on SA IPCOMP/%08x/" 215 printk(KERN_DEBUG "pmtu discovery on SA IPCOMP/%08x/" NIP6_FMT "\n",
216 "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
217 spi, NIP6(iph->daddr)); 216 spi, NIP6(iph->daddr));
218 xfrm_state_put(x); 217 xfrm_state_put(x);
219} 218}
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index cc3e9f560867..0e03eabfb9da 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -2373,7 +2373,7 @@ static int igmp6_mc_seq_show(struct seq_file *seq, void *v)
2373 struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq); 2373 struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq);
2374 2374
2375 seq_printf(seq, 2375 seq_printf(seq,
2376 "%-4d %-15s %04x%04x%04x%04x%04x%04x%04x%04x %5d %08X %ld\n", 2376 "%-4d %-15s " NIP6_FMT " %5d %08X %ld\n",
2377 state->dev->ifindex, state->dev->name, 2377 state->dev->ifindex, state->dev->name,
2378 NIP6(im->mca_addr), 2378 NIP6(im->mca_addr),
2379 im->mca_users, im->mca_flags, 2379 im->mca_users, im->mca_flags,
@@ -2542,15 +2542,12 @@ static int igmp6_mcf_seq_show(struct seq_file *seq, void *v)
2542 if (v == SEQ_START_TOKEN) { 2542 if (v == SEQ_START_TOKEN) {
2543 seq_printf(seq, 2543 seq_printf(seq,
2544 "%3s %6s " 2544 "%3s %6s "
2545 "%32s %32s %6s %6s\n", "Idx", 2545 "%39s %39s %6s %6s\n", "Idx",
2546 "Device", "Multicast Address", 2546 "Device", "Multicast Address",
2547 "Source Address", "INC", "EXC"); 2547 "Source Address", "INC", "EXC");
2548 } else { 2548 } else {
2549 seq_printf(seq, 2549 seq_printf(seq,
2550 "%3d %6.6s " 2550 "%3d %6.6s " NIP6_FMT " " NIP6_FMT " %6lu %6lu\n",
2551 "%04x%04x%04x%04x%04x%04x%04x%04x "
2552 "%04x%04x%04x%04x%04x%04x%04x%04x "
2553 "%6lu %6lu\n",
2554 state->dev->ifindex, state->dev->name, 2551 state->dev->ifindex, state->dev->name,
2555 NIP6(state->im->mca_addr), 2552 NIP6(state->im->mca_addr),
2556 NIP6(psf->sf_addr), 2553 NIP6(psf->sf_addr),
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 305d9ee6d7db..cb8856b1d951 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -692,7 +692,7 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)
692 if (!(neigh->nud_state & NUD_VALID)) { 692 if (!(neigh->nud_state & NUD_VALID)) {
693 ND_PRINTK1(KERN_DEBUG 693 ND_PRINTK1(KERN_DEBUG
694 "%s(): trying to ucast probe in NUD_INVALID: " 694 "%s(): trying to ucast probe in NUD_INVALID: "
695 "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", 695 NIP6_FMT "\n",
696 __FUNCTION__, 696 __FUNCTION__,
697 NIP6(*target)); 697 NIP6(*target));
698 } 698 }
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index 105dd69ee9fb..2d6f8ecbc27b 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -41,6 +41,7 @@ config IP6_NF_QUEUE
41 41
42config IP6_NF_IPTABLES 42config IP6_NF_IPTABLES
43 tristate "IP6 tables support (required for filtering/masq/NAT)" 43 tristate "IP6 tables support (required for filtering/masq/NAT)"
44 depends on NETFILTER_XTABLES
44 help 45 help
45 ip6tables is a general, extensible packet identification framework. 46 ip6tables is a general, extensible packet identification framework.
46 Currently only the packet filtering and packet mangling subsystem 47 Currently only the packet filtering and packet mangling subsystem
@@ -50,25 +51,6 @@ config IP6_NF_IPTABLES
50 To compile it as a module, choose M here. If unsure, say N. 51 To compile it as a module, choose M here. If unsure, say N.
51 52
52# The simple matches. 53# The simple matches.
53config IP6_NF_MATCH_LIMIT
54 tristate "limit match support"
55 depends on IP6_NF_IPTABLES
56 help
57 limit matching allows you to control the rate at which a rule can be
58 matched: mainly useful in combination with the LOG target ("LOG
59 target support", below) and to avoid some Denial of Service attacks.
60
61 To compile it as a module, choose M here. If unsure, say N.
62
63config IP6_NF_MATCH_MAC
64 tristate "MAC address match support"
65 depends on IP6_NF_IPTABLES
66 help
67 mac matching allows you to match packets based on the source
68 Ethernet address of the packet.
69
70 To compile it as a module, choose M here. If unsure, say N.
71
72config IP6_NF_MATCH_RT 54config IP6_NF_MATCH_RT
73 tristate "Routing header match support" 55 tristate "Routing header match support"
74 depends on IP6_NF_IPTABLES 56 depends on IP6_NF_IPTABLES
@@ -124,16 +106,6 @@ config IP6_NF_MATCH_OWNER
124 106
125 To compile it as a module, choose M here. If unsure, say N. 107 To compile it as a module, choose M here. If unsure, say N.
126 108
127config IP6_NF_MATCH_MARK
128 tristate "netfilter MARK match support"
129 depends on IP6_NF_IPTABLES
130 help
131 Netfilter mark matching allows you to match packets based on the
132 `nfmark' value in the packet. This can be set by the MARK target
133 (see below).
134
135 To compile it as a module, choose M here. If unsure, say N.
136
137config IP6_NF_MATCH_IPV6HEADER 109config IP6_NF_MATCH_IPV6HEADER
138 tristate "IPv6 Extension Headers Match" 110 tristate "IPv6 Extension Headers Match"
139 depends on IP6_NF_IPTABLES 111 depends on IP6_NF_IPTABLES
@@ -151,15 +123,6 @@ config IP6_NF_MATCH_AHESP
151 123
152 To compile it as a module, choose M here. If unsure, say N. 124 To compile it as a module, choose M here. If unsure, say N.
153 125
154config IP6_NF_MATCH_LENGTH
155 tristate "Packet Length match support"
156 depends on IP6_NF_IPTABLES
157 help
158 This option allows you to match the length of a packet against a
159 specific value or range of values.
160
161 To compile it as a module, choose M here. If unsure, say N.
162
163config IP6_NF_MATCH_EUI64 126config IP6_NF_MATCH_EUI64
164 tristate "EUI64 address check" 127 tristate "EUI64 address check"
165 depends on IP6_NF_IPTABLES 128 depends on IP6_NF_IPTABLES
@@ -170,15 +133,6 @@ config IP6_NF_MATCH_EUI64
170 133
171 To compile it as a module, choose M here. If unsure, say N. 134 To compile it as a module, choose M here. If unsure, say N.
172 135
173config IP6_NF_MATCH_PHYSDEV
174 tristate "Physdev match support"
175 depends on IP6_NF_IPTABLES && BRIDGE_NETFILTER
176 help
177 Physdev packet matching matches against the physical bridge ports
178 the IP packet arrived on or will leave by.
179
180 To compile it as a module, choose M here. If unsure, say N.
181
182config IP6_NF_MATCH_POLICY 136config IP6_NF_MATCH_POLICY
183 tristate "IPsec policy match support" 137 tristate "IPsec policy match support"
184 depends on IP6_NF_IPTABLES && XFRM 138 depends on IP6_NF_IPTABLES && XFRM
@@ -219,17 +173,6 @@ config IP6_NF_TARGET_REJECT
219 173
220 To compile it as a module, choose M here. If unsure, say N. 174 To compile it as a module, choose M here. If unsure, say N.
221 175
222config IP6_NF_TARGET_NFQUEUE
223 tristate "NFQUEUE Target Support"
224 depends on IP6_NF_IPTABLES
225 help
226 This Target replaced the old obsolete QUEUE target.
227
228 As opposed to QUEUE, it supports 65535 different queues,
229 not just one.
230
231 To compile it as a module, choose M here. If unsure, say N.
232
233config IP6_NF_MANGLE 176config IP6_NF_MANGLE
234 tristate "Packet mangling" 177 tristate "Packet mangling"
235 depends on IP6_NF_IPTABLES 178 depends on IP6_NF_IPTABLES
@@ -240,19 +183,6 @@ config IP6_NF_MANGLE
240 183
241 To compile it as a module, choose M here. If unsure, say N. 184 To compile it as a module, choose M here. If unsure, say N.
242 185
243config IP6_NF_TARGET_MARK
244 tristate "MARK target support"
245 depends on IP6_NF_MANGLE
246 help
247 This option adds a `MARK' target, which allows you to create rules
248 in the `mangle' table which alter the netfilter mark (nfmark) field
249 associated with the packet packet prior to routing. This can change
250 the routing method (see `Use netfilter MARK value as routing
251 key') and can also be used by other subsystems to change their
252 behavior.
253
254 To compile it as a module, choose M here. If unsure, say N.
255
256config IP6_NF_TARGET_HL 186config IP6_NF_TARGET_HL
257 tristate 'HL (hoplimit) target support' 187 tristate 'HL (hoplimit) target support'
258 depends on IP6_NF_MANGLE 188 depends on IP6_NF_MANGLE
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index c0c809b426e8..663b4749820d 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -4,10 +4,7 @@
4 4
5# Link order matters here. 5# Link order matters here.
6obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o 6obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o
7obj-$(CONFIG_IP6_NF_MATCH_LIMIT) += ip6t_limit.o
8obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o
9obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o 7obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o
10obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o
11obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o 8obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
12obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o 9obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
13obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o 10obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
@@ -17,12 +14,9 @@ obj-$(CONFIG_IP6_NF_MATCH_POLICY) += ip6t_policy.o
17obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o 14obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o
18obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o 15obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o
19obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o 16obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
20obj-$(CONFIG_IP6_NF_MATCH_PHYSDEV) += ip6t_physdev.o
21obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o 17obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
22obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o 18obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
23obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
24obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o 19obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
25obj-$(CONFIG_IP6_NF_TARGET_NFQUEUE) += ip6t_NFQUEUE.o
26obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o 20obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
27obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o 21obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
28obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o 22obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 1390370186d9..847068fd3367 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -13,6 +13,9 @@
13 * a table 13 * a table
14 * 06 Jun 2002 Andras Kis-Szabo <kisza@sch.bme.hu> 14 * 06 Jun 2002 Andras Kis-Szabo <kisza@sch.bme.hu>
15 * - new extension header parser code 15 * - new extension header parser code
16 * 15 Oct 2005 Harald Welte <laforge@netfilter.org>
17 * - Unification of {ip,ip6}_tables into x_tables
18 * - Removed tcp and udp code, since it's not ipv6 specific
16 */ 19 */
17 20
18#include <linux/capability.h> 21#include <linux/capability.h>
@@ -23,8 +26,6 @@
23#include <linux/vmalloc.h> 26#include <linux/vmalloc.h>
24#include <linux/netdevice.h> 27#include <linux/netdevice.h>
25#include <linux/module.h> 28#include <linux/module.h>
26#include <linux/tcp.h>
27#include <linux/udp.h>
28#include <linux/icmpv6.h> 29#include <linux/icmpv6.h>
29#include <net/ipv6.h> 30#include <net/ipv6.h>
30#include <asm/uaccess.h> 31#include <asm/uaccess.h>
@@ -33,6 +34,7 @@
33#include <linux/cpumask.h> 34#include <linux/cpumask.h>
34 35
35#include <linux/netfilter_ipv6/ip6_tables.h> 36#include <linux/netfilter_ipv6/ip6_tables.h>
37#include <linux/netfilter/x_tables.h>
36 38
37MODULE_LICENSE("GPL"); 39MODULE_LICENSE("GPL");
38MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); 40MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
@@ -67,13 +69,8 @@ do { \
67#else 69#else
68#define IP_NF_ASSERT(x) 70#define IP_NF_ASSERT(x)
69#endif 71#endif
70#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
71 72
72static DECLARE_MUTEX(ip6t_mutex);
73 73
74/* Must have mutex */
75#define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ip6t_mutex) != 0)
76#define ASSERT_WRITE_LOCK(x) IP_NF_ASSERT(down_trylock(&ip6t_mutex) != 0)
77#include <linux/netfilter_ipv4/listhelp.h> 74#include <linux/netfilter_ipv4/listhelp.h>
78 75
79#if 0 76#if 0
@@ -91,30 +88,6 @@ static DECLARE_MUTEX(ip6t_mutex);
91 88
92 Hence the start of any table is given by get_table() below. */ 89 Hence the start of any table is given by get_table() below. */
93 90
94/* The table itself */
95struct ip6t_table_info
96{
97 /* Size per table */
98 unsigned int size;
99 /* Number of entries: FIXME. --RR */
100 unsigned int number;
101 /* Initial number of entries. Needed for module usage count */
102 unsigned int initial_entries;
103
104 /* Entry points and underflows */
105 unsigned int hook_entry[NF_IP6_NUMHOOKS];
106 unsigned int underflow[NF_IP6_NUMHOOKS];
107
108 /* ip6t_entry tables: one per CPU */
109 void *entries[NR_CPUS];
110};
111
112static LIST_HEAD(ip6t_target);
113static LIST_HEAD(ip6t_match);
114static LIST_HEAD(ip6t_tables);
115#define SET_COUNTER(c,b,p) do { (c).bcnt = (b); (c).pcnt = (p); } while(0)
116#define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0)
117
118#if 0 91#if 0
119#define down(x) do { printk("DOWN:%u:" #x "\n", __LINE__); down(x); } while(0) 92#define down(x) do { printk("DOWN:%u:" #x "\n", __LINE__); down(x); } while(0)
120#define down_interruptible(x) ({ int __r; printk("DOWNi:%u:" #x "\n", __LINE__); __r = down_interruptible(x); if (__r != 0) printk("ABORT-DOWNi:%u\n", __LINE__); __r; }) 93#define down_interruptible(x) ({ int __r; printk("DOWNi:%u:" #x "\n", __LINE__); __r = down_interruptible(x); if (__r != 0) printk("ABORT-DOWNi:%u\n", __LINE__); __r; })
@@ -297,7 +270,7 @@ ip6t_do_table(struct sk_buff **pskb,
297 unsigned int hook, 270 unsigned int hook,
298 const struct net_device *in, 271 const struct net_device *in,
299 const struct net_device *out, 272 const struct net_device *out,
300 struct ip6t_table *table, 273 struct xt_table *table,
301 void *userdata) 274 void *userdata)
302{ 275{
303 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); 276 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
@@ -309,6 +282,7 @@ ip6t_do_table(struct sk_buff **pskb,
309 const char *indev, *outdev; 282 const char *indev, *outdev;
310 void *table_base; 283 void *table_base;
311 struct ip6t_entry *e, *back; 284 struct ip6t_entry *e, *back;
285 struct xt_table_info *private;
312 286
313 /* Initialization */ 287 /* Initialization */
314 indev = in ? in->name : nulldevname; 288 indev = in ? in->name : nulldevname;
@@ -321,9 +295,10 @@ ip6t_do_table(struct sk_buff **pskb,
321 * match it. */ 295 * match it. */
322 296
323 read_lock_bh(&table->lock); 297 read_lock_bh(&table->lock);
298 private = table->private;
324 IP_NF_ASSERT(table->valid_hooks & (1 << hook)); 299 IP_NF_ASSERT(table->valid_hooks & (1 << hook));
325 table_base = (void *)table->private->entries[smp_processor_id()]; 300 table_base = (void *)private->entries[smp_processor_id()];
326 e = get_entry(table_base, table->private->hook_entry[hook]); 301 e = get_entry(table_base, private->hook_entry[hook]);
327 302
328#ifdef CONFIG_NETFILTER_DEBUG 303#ifdef CONFIG_NETFILTER_DEBUG
329 /* Check noone else using our table */ 304 /* Check noone else using our table */
@@ -339,7 +314,7 @@ ip6t_do_table(struct sk_buff **pskb,
339#endif 314#endif
340 315
341 /* For return from builtin chain */ 316 /* For return from builtin chain */
342 back = get_entry(table_base, table->private->underflow[hook]); 317 back = get_entry(table_base, private->underflow[hook]);
343 318
344 do { 319 do {
345 IP_NF_ASSERT(e); 320 IP_NF_ASSERT(e);
@@ -439,145 +414,6 @@ ip6t_do_table(struct sk_buff **pskb,
439#endif 414#endif
440} 415}
441 416
442/*
443 * These are weird, but module loading must not be done with mutex
444 * held (since they will register), and we have to have a single
445 * function to use try_then_request_module().
446 */
447
448/* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */
449static inline struct ip6t_table *find_table_lock(const char *name)
450{
451 struct ip6t_table *t;
452
453 if (down_interruptible(&ip6t_mutex) != 0)
454 return ERR_PTR(-EINTR);
455
456 list_for_each_entry(t, &ip6t_tables, list)
457 if (strcmp(t->name, name) == 0 && try_module_get(t->me))
458 return t;
459 up(&ip6t_mutex);
460 return NULL;
461}
462
463/* Find match, grabs ref. Returns ERR_PTR() on error. */
464static inline struct ip6t_match *find_match(const char *name, u8 revision)
465{
466 struct ip6t_match *m;
467 int err = 0;
468
469 if (down_interruptible(&ip6t_mutex) != 0)
470 return ERR_PTR(-EINTR);
471
472 list_for_each_entry(m, &ip6t_match, list) {
473 if (strcmp(m->name, name) == 0) {
474 if (m->revision == revision) {
475 if (try_module_get(m->me)) {
476 up(&ip6t_mutex);
477 return m;
478 }
479 } else
480 err = -EPROTOTYPE; /* Found something. */
481 }
482 }
483 up(&ip6t_mutex);
484 return ERR_PTR(err);
485}
486
487/* Find target, grabs ref. Returns ERR_PTR() on error. */
488static inline struct ip6t_target *find_target(const char *name, u8 revision)
489{
490 struct ip6t_target *t;
491 int err = 0;
492
493 if (down_interruptible(&ip6t_mutex) != 0)
494 return ERR_PTR(-EINTR);
495
496 list_for_each_entry(t, &ip6t_target, list) {
497 if (strcmp(t->name, name) == 0) {
498 if (t->revision == revision) {
499 if (try_module_get(t->me)) {
500 up(&ip6t_mutex);
501 return t;
502 }
503 } else
504 err = -EPROTOTYPE; /* Found something. */
505 }
506 }
507 up(&ip6t_mutex);
508 return ERR_PTR(err);
509}
510
511struct ip6t_target *ip6t_find_target(const char *name, u8 revision)
512{
513 struct ip6t_target *target;
514
515 target = try_then_request_module(find_target(name, revision),
516 "ip6t_%s", name);
517 if (IS_ERR(target) || !target)
518 return NULL;
519 return target;
520}
521
522static int match_revfn(const char *name, u8 revision, int *bestp)
523{
524 struct ip6t_match *m;
525 int have_rev = 0;
526
527 list_for_each_entry(m, &ip6t_match, list) {
528 if (strcmp(m->name, name) == 0) {
529 if (m->revision > *bestp)
530 *bestp = m->revision;
531 if (m->revision == revision)
532 have_rev = 1;
533 }
534 }
535 return have_rev;
536}
537
538static int target_revfn(const char *name, u8 revision, int *bestp)
539{
540 struct ip6t_target *t;
541 int have_rev = 0;
542
543 list_for_each_entry(t, &ip6t_target, list) {
544 if (strcmp(t->name, name) == 0) {
545 if (t->revision > *bestp)
546 *bestp = t->revision;
547 if (t->revision == revision)
548 have_rev = 1;
549 }
550 }
551 return have_rev;
552}
553
554/* Returns true or fals (if no such extension at all) */
555static inline int find_revision(const char *name, u8 revision,
556 int (*revfn)(const char *, u8, int *),
557 int *err)
558{
559 int have_rev, best = -1;
560
561 if (down_interruptible(&ip6t_mutex) != 0) {
562 *err = -EINTR;
563 return 1;
564 }
565 have_rev = revfn(name, revision, &best);
566 up(&ip6t_mutex);
567
568 /* Nothing at all? Return 0 to try loading module. */
569 if (best == -1) {
570 *err = -ENOENT;
571 return 0;
572 }
573
574 *err = best;
575 if (!have_rev)
576 *err = -EPROTONOSUPPORT;
577 return 1;
578}
579
580
581/* All zeroes == unconditional rule. */ 417/* All zeroes == unconditional rule. */
582static inline int 418static inline int
583unconditional(const struct ip6t_ip6 *ipv6) 419unconditional(const struct ip6t_ip6 *ipv6)
@@ -594,7 +430,7 @@ unconditional(const struct ip6t_ip6 *ipv6)
594/* Figures out from what hook each rule can be called: returns 0 if 430/* Figures out from what hook each rule can be called: returns 0 if
595 there are loops. Puts hook bitmask in comefrom. */ 431 there are loops. Puts hook bitmask in comefrom. */
596static int 432static int
597mark_source_chains(struct ip6t_table_info *newinfo, 433mark_source_chains(struct xt_table_info *newinfo,
598 unsigned int valid_hooks, void *entry0) 434 unsigned int valid_hooks, void *entry0)
599{ 435{
600 unsigned int hook; 436 unsigned int hook;
@@ -740,11 +576,11 @@ check_match(struct ip6t_entry_match *m,
740{ 576{
741 struct ip6t_match *match; 577 struct ip6t_match *match;
742 578
743 match = try_then_request_module(find_match(m->u.user.name, 579 match = try_then_request_module(xt_find_match(AF_INET6, m->u.user.name,
744 m->u.user.revision), 580 m->u.user.revision),
745 "ip6t_%s", m->u.user.name); 581 "ip6t_%s", m->u.user.name);
746 if (IS_ERR(match) || !match) { 582 if (IS_ERR(match) || !match) {
747 duprintf("check_match: `%s' not found\n", m->u.user.name); 583 duprintf("check_match: `%s' not found\n", m->u.user.name);
748 return match ? PTR_ERR(match) : -ENOENT; 584 return match ? PTR_ERR(match) : -ENOENT;
749 } 585 }
750 m->u.kernel.match = match; 586 m->u.kernel.match = match;
@@ -785,8 +621,9 @@ check_entry(struct ip6t_entry *e, const char *name, unsigned int size,
785 goto cleanup_matches; 621 goto cleanup_matches;
786 622
787 t = ip6t_get_target(e); 623 t = ip6t_get_target(e);
788 target = try_then_request_module(find_target(t->u.user.name, 624 target = try_then_request_module(xt_find_target(AF_INET6,
789 t->u.user.revision), 625 t->u.user.name,
626 t->u.user.revision),
790 "ip6t_%s", t->u.user.name); 627 "ip6t_%s", t->u.user.name);
791 if (IS_ERR(target) || !target) { 628 if (IS_ERR(target) || !target) {
792 duprintf("check_entry: `%s' not found\n", t->u.user.name); 629 duprintf("check_entry: `%s' not found\n", t->u.user.name);
@@ -822,7 +659,7 @@ check_entry(struct ip6t_entry *e, const char *name, unsigned int size,
822 659
823static inline int 660static inline int
824check_entry_size_and_hooks(struct ip6t_entry *e, 661check_entry_size_and_hooks(struct ip6t_entry *e,
825 struct ip6t_table_info *newinfo, 662 struct xt_table_info *newinfo,
826 unsigned char *base, 663 unsigned char *base,
827 unsigned char *limit, 664 unsigned char *limit,
828 const unsigned int *hook_entries, 665 const unsigned int *hook_entries,
@@ -856,7 +693,7 @@ check_entry_size_and_hooks(struct ip6t_entry *e,
856 < 0 (not IP6T_RETURN). --RR */ 693 < 0 (not IP6T_RETURN). --RR */
857 694
858 /* Clear counters and comefrom */ 695 /* Clear counters and comefrom */
859 e->counters = ((struct ip6t_counters) { 0, 0 }); 696 e->counters = ((struct xt_counters) { 0, 0 });
860 e->comefrom = 0; 697 e->comefrom = 0;
861 698
862 (*i)++; 699 (*i)++;
@@ -886,7 +723,7 @@ cleanup_entry(struct ip6t_entry *e, unsigned int *i)
886static int 723static int
887translate_table(const char *name, 724translate_table(const char *name,
888 unsigned int valid_hooks, 725 unsigned int valid_hooks,
889 struct ip6t_table_info *newinfo, 726 struct xt_table_info *newinfo,
890 void *entry0, 727 void *entry0,
891 unsigned int size, 728 unsigned int size,
892 unsigned int number, 729 unsigned int number,
@@ -963,48 +800,10 @@ translate_table(const char *name,
963 return ret; 800 return ret;
964} 801}
965 802
966static struct ip6t_table_info *
967replace_table(struct ip6t_table *table,
968 unsigned int num_counters,
969 struct ip6t_table_info *newinfo,
970 int *error)
971{
972 struct ip6t_table_info *oldinfo;
973
974#ifdef CONFIG_NETFILTER_DEBUG
975 {
976 int cpu;
977
978 for_each_cpu(cpu) {
979 struct ip6t_entry *table_base = newinfo->entries[cpu];
980 if (table_base)
981 table_base->comefrom = 0xdead57ac;
982 }
983 }
984#endif
985
986 /* Do the substitution. */
987 write_lock_bh(&table->lock);
988 /* Check inside lock: is the old number correct? */
989 if (num_counters != table->private->number) {
990 duprintf("num_counters != table->private->number (%u/%u)\n",
991 num_counters, table->private->number);
992 write_unlock_bh(&table->lock);
993 *error = -EAGAIN;
994 return NULL;
995 }
996 oldinfo = table->private;
997 table->private = newinfo;
998 newinfo->initial_entries = oldinfo->initial_entries;
999 write_unlock_bh(&table->lock);
1000
1001 return oldinfo;
1002}
1003
1004/* Gets counters. */ 803/* Gets counters. */
1005static inline int 804static inline int
1006add_entry_to_counter(const struct ip6t_entry *e, 805add_entry_to_counter(const struct ip6t_entry *e,
1007 struct ip6t_counters total[], 806 struct xt_counters total[],
1008 unsigned int *i) 807 unsigned int *i)
1009{ 808{
1010 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); 809 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
@@ -1025,8 +824,8 @@ set_entry_to_counter(const struct ip6t_entry *e,
1025} 824}
1026 825
1027static void 826static void
1028get_counters(const struct ip6t_table_info *t, 827get_counters(const struct xt_table_info *t,
1029 struct ip6t_counters counters[]) 828 struct xt_counters counters[])
1030{ 829{
1031 unsigned int cpu; 830 unsigned int cpu;
1032 unsigned int i; 831 unsigned int i;
@@ -1060,19 +859,20 @@ get_counters(const struct ip6t_table_info *t,
1060 859
1061static int 860static int
1062copy_entries_to_user(unsigned int total_size, 861copy_entries_to_user(unsigned int total_size,
1063 struct ip6t_table *table, 862 struct xt_table *table,
1064 void __user *userptr) 863 void __user *userptr)
1065{ 864{
1066 unsigned int off, num, countersize; 865 unsigned int off, num, countersize;
1067 struct ip6t_entry *e; 866 struct ip6t_entry *e;
1068 struct ip6t_counters *counters; 867 struct xt_counters *counters;
868 struct xt_table_info *private = table->private;
1069 int ret = 0; 869 int ret = 0;
1070 void *loc_cpu_entry; 870 void *loc_cpu_entry;
1071 871
1072 /* We need atomic snapshot of counters: rest doesn't change 872 /* We need atomic snapshot of counters: rest doesn't change
1073 (other than comefrom, which userspace doesn't care 873 (other than comefrom, which userspace doesn't care
1074 about). */ 874 about). */
1075 countersize = sizeof(struct ip6t_counters) * table->private->number; 875 countersize = sizeof(struct xt_counters) * private->number;
1076 counters = vmalloc(countersize); 876 counters = vmalloc(countersize);
1077 877
1078 if (counters == NULL) 878 if (counters == NULL)
@@ -1080,11 +880,11 @@ copy_entries_to_user(unsigned int total_size,
1080 880
1081 /* First, sum counters... */ 881 /* First, sum counters... */
1082 write_lock_bh(&table->lock); 882 write_lock_bh(&table->lock);
1083 get_counters(table->private, counters); 883 get_counters(private, counters);
1084 write_unlock_bh(&table->lock); 884 write_unlock_bh(&table->lock);
1085 885
1086 /* choose the copy that is on ourc node/cpu */ 886 /* choose the copy that is on ourc node/cpu */
1087 loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; 887 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1088 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) { 888 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
1089 ret = -EFAULT; 889 ret = -EFAULT;
1090 goto free_counters; 890 goto free_counters;
@@ -1143,87 +943,42 @@ get_entries(const struct ip6t_get_entries *entries,
1143 struct ip6t_get_entries __user *uptr) 943 struct ip6t_get_entries __user *uptr)
1144{ 944{
1145 int ret; 945 int ret;
1146 struct ip6t_table *t; 946 struct xt_table *t;
1147 947
1148 t = find_table_lock(entries->name); 948 t = xt_find_table_lock(AF_INET6, entries->name);
1149 if (t && !IS_ERR(t)) { 949 if (t && !IS_ERR(t)) {
1150 duprintf("t->private->number = %u\n", 950 struct xt_table_info *private = t->private;
1151 t->private->number); 951 duprintf("t->private->number = %u\n", private->number);
1152 if (entries->size == t->private->size) 952 if (entries->size == private->size)
1153 ret = copy_entries_to_user(t->private->size, 953 ret = copy_entries_to_user(private->size,
1154 t, uptr->entrytable); 954 t, uptr->entrytable);
1155 else { 955 else {
1156 duprintf("get_entries: I've got %u not %u!\n", 956 duprintf("get_entries: I've got %u not %u!\n",
1157 t->private->size, 957 private->size, entries->size);
1158 entries->size);
1159 ret = -EINVAL; 958 ret = -EINVAL;
1160 } 959 }
1161 module_put(t->me); 960 module_put(t->me);
1162 up(&ip6t_mutex); 961 xt_table_unlock(t);
1163 } else 962 } else
1164 ret = t ? PTR_ERR(t) : -ENOENT; 963 ret = t ? PTR_ERR(t) : -ENOENT;
1165 964
1166 return ret; 965 return ret;
1167} 966}
1168 967
1169static void free_table_info(struct ip6t_table_info *info)
1170{
1171 int cpu;
1172 for_each_cpu(cpu) {
1173 if (info->size <= PAGE_SIZE)
1174 kfree(info->entries[cpu]);
1175 else
1176 vfree(info->entries[cpu]);
1177 }
1178 kfree(info);
1179}
1180
1181static struct ip6t_table_info *alloc_table_info(unsigned int size)
1182{
1183 struct ip6t_table_info *newinfo;
1184 int cpu;
1185
1186 newinfo = kzalloc(sizeof(struct ip6t_table_info), GFP_KERNEL);
1187 if (!newinfo)
1188 return NULL;
1189
1190 newinfo->size = size;
1191
1192 for_each_cpu(cpu) {
1193 if (size <= PAGE_SIZE)
1194 newinfo->entries[cpu] = kmalloc_node(size,
1195 GFP_KERNEL,
1196 cpu_to_node(cpu));
1197 else
1198 newinfo->entries[cpu] = vmalloc_node(size,
1199 cpu_to_node(cpu));
1200 if (newinfo->entries[cpu] == NULL) {
1201 free_table_info(newinfo);
1202 return NULL;
1203 }
1204 }
1205
1206 return newinfo;
1207}
1208
1209static int 968static int
1210do_replace(void __user *user, unsigned int len) 969do_replace(void __user *user, unsigned int len)
1211{ 970{
1212 int ret; 971 int ret;
1213 struct ip6t_replace tmp; 972 struct ip6t_replace tmp;
1214 struct ip6t_table *t; 973 struct xt_table *t;
1215 struct ip6t_table_info *newinfo, *oldinfo; 974 struct xt_table_info *newinfo, *oldinfo;
1216 struct ip6t_counters *counters; 975 struct xt_counters *counters;
1217 void *loc_cpu_entry, *loc_cpu_old_entry; 976 void *loc_cpu_entry, *loc_cpu_old_entry;
1218 977
1219 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 978 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1220 return -EFAULT; 979 return -EFAULT;
1221 980
1222 /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */ 981 newinfo = xt_alloc_table_info(tmp.size);
1223 if ((SMP_ALIGN(tmp.size) >> PAGE_SHIFT) + 2 > num_physpages)
1224 return -ENOMEM;
1225
1226 newinfo = alloc_table_info(tmp.size);
1227 if (!newinfo) 982 if (!newinfo)
1228 return -ENOMEM; 983 return -ENOMEM;
1229 984
@@ -1235,7 +990,7 @@ do_replace(void __user *user, unsigned int len)
1235 goto free_newinfo; 990 goto free_newinfo;
1236 } 991 }
1237 992
1238 counters = vmalloc(tmp.num_counters * sizeof(struct ip6t_counters)); 993 counters = vmalloc(tmp.num_counters * sizeof(struct xt_counters));
1239 if (!counters) { 994 if (!counters) {
1240 ret = -ENOMEM; 995 ret = -ENOMEM;
1241 goto free_newinfo; 996 goto free_newinfo;
@@ -1249,7 +1004,7 @@ do_replace(void __user *user, unsigned int len)
1249 1004
1250 duprintf("ip_tables: Translated table\n"); 1005 duprintf("ip_tables: Translated table\n");
1251 1006
1252 t = try_then_request_module(find_table_lock(tmp.name), 1007 t = try_then_request_module(xt_find_table_lock(AF_INET6, tmp.name),
1253 "ip6table_%s", tmp.name); 1008 "ip6table_%s", tmp.name);
1254 if (!t || IS_ERR(t)) { 1009 if (!t || IS_ERR(t)) {
1255 ret = t ? PTR_ERR(t) : -ENOENT; 1010 ret = t ? PTR_ERR(t) : -ENOENT;
@@ -1264,7 +1019,7 @@ do_replace(void __user *user, unsigned int len)
1264 goto put_module; 1019 goto put_module;
1265 } 1020 }
1266 1021
1267 oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret); 1022 oldinfo = xt_replace_table(t, tmp.num_counters, newinfo, &ret);
1268 if (!oldinfo) 1023 if (!oldinfo)
1269 goto put_module; 1024 goto put_module;
1270 1025
@@ -1283,23 +1038,23 @@ do_replace(void __user *user, unsigned int len)
1283 /* Decrease module usage counts and free resource */ 1038 /* Decrease module usage counts and free resource */
1284 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; 1039 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1285 IP6T_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL); 1040 IP6T_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL);
1286 free_table_info(oldinfo); 1041 xt_free_table_info(oldinfo);
1287 if (copy_to_user(tmp.counters, counters, 1042 if (copy_to_user(tmp.counters, counters,
1288 sizeof(struct ip6t_counters) * tmp.num_counters) != 0) 1043 sizeof(struct xt_counters) * tmp.num_counters) != 0)
1289 ret = -EFAULT; 1044 ret = -EFAULT;
1290 vfree(counters); 1045 vfree(counters);
1291 up(&ip6t_mutex); 1046 xt_table_unlock(t);
1292 return ret; 1047 return ret;
1293 1048
1294 put_module: 1049 put_module:
1295 module_put(t->me); 1050 module_put(t->me);
1296 up(&ip6t_mutex); 1051 xt_table_unlock(t);
1297 free_newinfo_counters_untrans: 1052 free_newinfo_counters_untrans:
1298 IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL); 1053 IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL);
1299 free_newinfo_counters: 1054 free_newinfo_counters:
1300 vfree(counters); 1055 vfree(counters);
1301 free_newinfo: 1056 free_newinfo:
1302 free_table_info(newinfo); 1057 xt_free_table_info(newinfo);
1303 return ret; 1058 return ret;
1304} 1059}
1305 1060
@@ -1307,7 +1062,7 @@ do_replace(void __user *user, unsigned int len)
1307 * and everything is OK. */ 1062 * and everything is OK. */
1308static inline int 1063static inline int
1309add_counter_to_entry(struct ip6t_entry *e, 1064add_counter_to_entry(struct ip6t_entry *e,
1310 const struct ip6t_counters addme[], 1065 const struct xt_counters addme[],
1311 unsigned int *i) 1066 unsigned int *i)
1312{ 1067{
1313#if 0 1068#if 0
@@ -1329,15 +1084,16 @@ static int
1329do_add_counters(void __user *user, unsigned int len) 1084do_add_counters(void __user *user, unsigned int len)
1330{ 1085{
1331 unsigned int i; 1086 unsigned int i;
1332 struct ip6t_counters_info tmp, *paddc; 1087 struct xt_counters_info tmp, *paddc;
1333 struct ip6t_table *t; 1088 struct xt_table_info *private;
1089 struct xt_table *t;
1334 int ret = 0; 1090 int ret = 0;
1335 void *loc_cpu_entry; 1091 void *loc_cpu_entry;
1336 1092
1337 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 1093 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1338 return -EFAULT; 1094 return -EFAULT;
1339 1095
1340 if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct ip6t_counters)) 1096 if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct xt_counters))
1341 return -EINVAL; 1097 return -EINVAL;
1342 1098
1343 paddc = vmalloc(len); 1099 paddc = vmalloc(len);
@@ -1349,29 +1105,30 @@ do_add_counters(void __user *user, unsigned int len)
1349 goto free; 1105 goto free;
1350 } 1106 }
1351 1107
1352 t = find_table_lock(tmp.name); 1108 t = xt_find_table_lock(AF_INET6, tmp.name);
1353 if (!t || IS_ERR(t)) { 1109 if (!t || IS_ERR(t)) {
1354 ret = t ? PTR_ERR(t) : -ENOENT; 1110 ret = t ? PTR_ERR(t) : -ENOENT;
1355 goto free; 1111 goto free;
1356 } 1112 }
1357 1113
1358 write_lock_bh(&t->lock); 1114 write_lock_bh(&t->lock);
1359 if (t->private->number != paddc->num_counters) { 1115 private = t->private;
1116 if (private->number != paddc->num_counters) {
1360 ret = -EINVAL; 1117 ret = -EINVAL;
1361 goto unlock_up_free; 1118 goto unlock_up_free;
1362 } 1119 }
1363 1120
1364 i = 0; 1121 i = 0;
1365 /* Choose the copy that is on our node */ 1122 /* Choose the copy that is on our node */
1366 loc_cpu_entry = t->private->entries[smp_processor_id()]; 1123 loc_cpu_entry = private->entries[smp_processor_id()];
1367 IP6T_ENTRY_ITERATE(loc_cpu_entry, 1124 IP6T_ENTRY_ITERATE(loc_cpu_entry,
1368 t->private->size, 1125 private->size,
1369 add_counter_to_entry, 1126 add_counter_to_entry,
1370 paddc->counters, 1127 paddc->counters,
1371 &i); 1128 &i);
1372 unlock_up_free: 1129 unlock_up_free:
1373 write_unlock_bh(&t->lock); 1130 write_unlock_bh(&t->lock);
1374 up(&ip6t_mutex); 1131 xt_table_unlock(t);
1375 module_put(t->me); 1132 module_put(t->me);
1376 free: 1133 free:
1377 vfree(paddc); 1134 vfree(paddc);
@@ -1415,7 +1172,7 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1415 switch (cmd) { 1172 switch (cmd) {
1416 case IP6T_SO_GET_INFO: { 1173 case IP6T_SO_GET_INFO: {
1417 char name[IP6T_TABLE_MAXNAMELEN]; 1174 char name[IP6T_TABLE_MAXNAMELEN];
1418 struct ip6t_table *t; 1175 struct xt_table *t;
1419 1176
1420 if (*len != sizeof(struct ip6t_getinfo)) { 1177 if (*len != sizeof(struct ip6t_getinfo)) {
1421 duprintf("length %u != %u\n", *len, 1178 duprintf("length %u != %u\n", *len,
@@ -1430,25 +1187,26 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1430 } 1187 }
1431 name[IP6T_TABLE_MAXNAMELEN-1] = '\0'; 1188 name[IP6T_TABLE_MAXNAMELEN-1] = '\0';
1432 1189
1433 t = try_then_request_module(find_table_lock(name), 1190 t = try_then_request_module(xt_find_table_lock(AF_INET6, name),
1434 "ip6table_%s", name); 1191 "ip6table_%s", name);
1435 if (t && !IS_ERR(t)) { 1192 if (t && !IS_ERR(t)) {
1436 struct ip6t_getinfo info; 1193 struct ip6t_getinfo info;
1194 struct xt_table_info *private = t->private;
1437 1195
1438 info.valid_hooks = t->valid_hooks; 1196 info.valid_hooks = t->valid_hooks;
1439 memcpy(info.hook_entry, t->private->hook_entry, 1197 memcpy(info.hook_entry, private->hook_entry,
1440 sizeof(info.hook_entry)); 1198 sizeof(info.hook_entry));
1441 memcpy(info.underflow, t->private->underflow, 1199 memcpy(info.underflow, private->underflow,
1442 sizeof(info.underflow)); 1200 sizeof(info.underflow));
1443 info.num_entries = t->private->number; 1201 info.num_entries = private->number;
1444 info.size = t->private->size; 1202 info.size = private->size;
1445 memcpy(info.name, name, sizeof(info.name)); 1203 memcpy(info.name, name, sizeof(info.name));
1446 1204
1447 if (copy_to_user(user, &info, *len) != 0) 1205 if (copy_to_user(user, &info, *len) != 0)
1448 ret = -EFAULT; 1206 ret = -EFAULT;
1449 else 1207 else
1450 ret = 0; 1208 ret = 0;
1451 up(&ip6t_mutex); 1209 xt_table_unlock(t);
1452 module_put(t->me); 1210 module_put(t->me);
1453 } else 1211 } else
1454 ret = t ? PTR_ERR(t) : -ENOENT; 1212 ret = t ? PTR_ERR(t) : -ENOENT;
@@ -1475,7 +1233,7 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1475 case IP6T_SO_GET_REVISION_MATCH: 1233 case IP6T_SO_GET_REVISION_MATCH:
1476 case IP6T_SO_GET_REVISION_TARGET: { 1234 case IP6T_SO_GET_REVISION_TARGET: {
1477 struct ip6t_get_revision rev; 1235 struct ip6t_get_revision rev;
1478 int (*revfn)(const char *, u8, int *); 1236 int target;
1479 1237
1480 if (*len != sizeof(rev)) { 1238 if (*len != sizeof(rev)) {
1481 ret = -EINVAL; 1239 ret = -EINVAL;
@@ -1487,12 +1245,13 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1487 } 1245 }
1488 1246
1489 if (cmd == IP6T_SO_GET_REVISION_TARGET) 1247 if (cmd == IP6T_SO_GET_REVISION_TARGET)
1490 revfn = target_revfn; 1248 target = 1;
1491 else 1249 else
1492 revfn = match_revfn; 1250 target = 0;
1493 1251
1494 try_then_request_module(find_revision(rev.name, rev.revision, 1252 try_then_request_module(xt_find_revision(AF_INET6, rev.name,
1495 revfn, &ret), 1253 rev.revision,
1254 target, &ret),
1496 "ip6t_%s", rev.name); 1255 "ip6t_%s", rev.name);
1497 break; 1256 break;
1498 } 1257 }
@@ -1505,61 +1264,16 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1505 return ret; 1264 return ret;
1506} 1265}
1507 1266
1508/* Registration hooks for targets. */ 1267int ip6t_register_table(struct xt_table *table,
1509int
1510ip6t_register_target(struct ip6t_target *target)
1511{
1512 int ret;
1513
1514 ret = down_interruptible(&ip6t_mutex);
1515 if (ret != 0)
1516 return ret;
1517 list_add(&target->list, &ip6t_target);
1518 up(&ip6t_mutex);
1519 return ret;
1520}
1521
1522void
1523ip6t_unregister_target(struct ip6t_target *target)
1524{
1525 down(&ip6t_mutex);
1526 LIST_DELETE(&ip6t_target, target);
1527 up(&ip6t_mutex);
1528}
1529
1530int
1531ip6t_register_match(struct ip6t_match *match)
1532{
1533 int ret;
1534
1535 ret = down_interruptible(&ip6t_mutex);
1536 if (ret != 0)
1537 return ret;
1538
1539 list_add(&match->list, &ip6t_match);
1540 up(&ip6t_mutex);
1541
1542 return ret;
1543}
1544
1545void
1546ip6t_unregister_match(struct ip6t_match *match)
1547{
1548 down(&ip6t_mutex);
1549 LIST_DELETE(&ip6t_match, match);
1550 up(&ip6t_mutex);
1551}
1552
1553int ip6t_register_table(struct ip6t_table *table,
1554 const struct ip6t_replace *repl) 1268 const struct ip6t_replace *repl)
1555{ 1269{
1556 int ret; 1270 int ret;
1557 struct ip6t_table_info *newinfo; 1271 struct xt_table_info *newinfo;
1558 static struct ip6t_table_info bootstrap 1272 static struct xt_table_info bootstrap
1559 = { 0, 0, 0, { 0 }, { 0 }, { } }; 1273 = { 0, 0, 0, { 0 }, { 0 }, { } };
1560 void *loc_cpu_entry; 1274 void *loc_cpu_entry;
1561 1275
1562 newinfo = alloc_table_info(repl->size); 1276 newinfo = xt_alloc_table_info(repl->size);
1563 if (!newinfo) 1277 if (!newinfo)
1564 return -ENOMEM; 1278 return -ENOMEM;
1565 1279
@@ -1573,244 +1287,29 @@ int ip6t_register_table(struct ip6t_table *table,
1573 repl->hook_entry, 1287 repl->hook_entry,
1574 repl->underflow); 1288 repl->underflow);
1575 if (ret != 0) { 1289 if (ret != 0) {
1576 free_table_info(newinfo); 1290 xt_free_table_info(newinfo);
1577 return ret; 1291 return ret;
1578 } 1292 }
1579 1293
1580 ret = down_interruptible(&ip6t_mutex); 1294 if (xt_register_table(table, &bootstrap, newinfo) != 0) {
1581 if (ret != 0) { 1295 xt_free_table_info(newinfo);
1582 free_table_info(newinfo);
1583 return ret; 1296 return ret;
1584 } 1297 }
1585 1298
1586 /* Don't autoload: we'd eat our tail... */ 1299 return 0;
1587 if (list_named_find(&ip6t_tables, table->name)) {
1588 ret = -EEXIST;
1589 goto free_unlock;
1590 }
1591
1592 /* Simplifies replace_table code. */
1593 table->private = &bootstrap;
1594 if (!replace_table(table, 0, newinfo, &ret))
1595 goto free_unlock;
1596
1597 duprintf("table->private->number = %u\n",
1598 table->private->number);
1599
1600 /* save number of initial entries */
1601 table->private->initial_entries = table->private->number;
1602
1603 rwlock_init(&table->lock);
1604 list_prepend(&ip6t_tables, table);
1605
1606 unlock:
1607 up(&ip6t_mutex);
1608 return ret;
1609
1610 free_unlock:
1611 free_table_info(newinfo);
1612 goto unlock;
1613} 1300}
1614 1301
1615void ip6t_unregister_table(struct ip6t_table *table) 1302void ip6t_unregister_table(struct xt_table *table)
1616{ 1303{
1304 struct xt_table_info *private;
1617 void *loc_cpu_entry; 1305 void *loc_cpu_entry;
1618 1306
1619 down(&ip6t_mutex); 1307 private = xt_unregister_table(table);
1620 LIST_DELETE(&ip6t_tables, table);
1621 up(&ip6t_mutex);
1622 1308
1623 /* Decrease module usage counts and free resources */ 1309 /* Decrease module usage counts and free resources */
1624 loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; 1310 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1625 IP6T_ENTRY_ITERATE(loc_cpu_entry, table->private->size, 1311 IP6T_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL);
1626 cleanup_entry, NULL); 1312 xt_free_table_info(private);
1627 free_table_info(table->private);
1628}
1629
1630/* Returns 1 if the port is matched by the range, 0 otherwise */
1631static inline int
1632port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert)
1633{
1634 int ret;
1635
1636 ret = (port >= min && port <= max) ^ invert;
1637 return ret;
1638}
1639
1640static int
1641tcp_find_option(u_int8_t option,
1642 const struct sk_buff *skb,
1643 unsigned int tcpoff,
1644 unsigned int optlen,
1645 int invert,
1646 int *hotdrop)
1647{
1648 /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
1649 u_int8_t _opt[60 - sizeof(struct tcphdr)], *op;
1650 unsigned int i;
1651
1652 duprintf("tcp_match: finding option\n");
1653 if (!optlen)
1654 return invert;
1655 /* If we don't have the whole header, drop packet. */
1656 op = skb_header_pointer(skb, tcpoff + sizeof(struct tcphdr), optlen,
1657 _opt);
1658 if (op == NULL) {
1659 *hotdrop = 1;
1660 return 0;
1661 }
1662
1663 for (i = 0; i < optlen; ) {
1664 if (op[i] == option) return !invert;
1665 if (op[i] < 2) i++;
1666 else i += op[i+1]?:1;
1667 }
1668
1669 return invert;
1670}
1671
1672static int
1673tcp_match(const struct sk_buff *skb,
1674 const struct net_device *in,
1675 const struct net_device *out,
1676 const void *matchinfo,
1677 int offset,
1678 unsigned int protoff,
1679 int *hotdrop)
1680{
1681 struct tcphdr _tcph, *th;
1682 const struct ip6t_tcp *tcpinfo = matchinfo;
1683
1684 if (offset) {
1685 /* To quote Alan:
1686
1687 Don't allow a fragment of TCP 8 bytes in. Nobody normal
1688 causes this. Its a cracker trying to break in by doing a
1689 flag overwrite to pass the direction checks.
1690 */
1691 if (offset == 1) {
1692 duprintf("Dropping evil TCP offset=1 frag.\n");
1693 *hotdrop = 1;
1694 }
1695 /* Must not be a fragment. */
1696 return 0;
1697 }
1698
1699#define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg))
1700
1701 th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
1702 if (th == NULL) {
1703 /* We've been asked to examine this packet, and we
1704 can't. Hence, no choice but to drop. */
1705 duprintf("Dropping evil TCP offset=0 tinygram.\n");
1706 *hotdrop = 1;
1707 return 0;
1708 }
1709
1710 if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1],
1711 ntohs(th->source),
1712 !!(tcpinfo->invflags & IP6T_TCP_INV_SRCPT)))
1713 return 0;
1714 if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1],
1715 ntohs(th->dest),
1716 !!(tcpinfo->invflags & IP6T_TCP_INV_DSTPT)))
1717 return 0;
1718 if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask)
1719 == tcpinfo->flg_cmp,
1720 IP6T_TCP_INV_FLAGS))
1721 return 0;
1722 if (tcpinfo->option) {
1723 if (th->doff * 4 < sizeof(_tcph)) {
1724 *hotdrop = 1;
1725 return 0;
1726 }
1727 if (!tcp_find_option(tcpinfo->option, skb, protoff,
1728 th->doff*4 - sizeof(*th),
1729 tcpinfo->invflags & IP6T_TCP_INV_OPTION,
1730 hotdrop))
1731 return 0;
1732 }
1733 return 1;
1734}
1735
1736/* Called when user tries to insert an entry of this type. */
1737static int
1738tcp_checkentry(const char *tablename,
1739 const struct ip6t_ip6 *ipv6,
1740 void *matchinfo,
1741 unsigned int matchsize,
1742 unsigned int hook_mask)
1743{
1744 const struct ip6t_tcp *tcpinfo = matchinfo;
1745
1746 /* Must specify proto == TCP, and no unknown invflags */
1747 return ipv6->proto == IPPROTO_TCP
1748 && !(ipv6->invflags & IP6T_INV_PROTO)
1749 && matchsize == IP6T_ALIGN(sizeof(struct ip6t_tcp))
1750 && !(tcpinfo->invflags & ~IP6T_TCP_INV_MASK);
1751}
1752
1753static int
1754udp_match(const struct sk_buff *skb,
1755 const struct net_device *in,
1756 const struct net_device *out,
1757 const void *matchinfo,
1758 int offset,
1759 unsigned int protoff,
1760 int *hotdrop)
1761{
1762 struct udphdr _udph, *uh;
1763 const struct ip6t_udp *udpinfo = matchinfo;
1764
1765 /* Must not be a fragment. */
1766 if (offset)
1767 return 0;
1768
1769 uh = skb_header_pointer(skb, protoff, sizeof(_udph), &_udph);
1770 if (uh == NULL) {
1771 /* We've been asked to examine this packet, and we
1772 can't. Hence, no choice but to drop. */
1773 duprintf("Dropping evil UDP tinygram.\n");
1774 *hotdrop = 1;
1775 return 0;
1776 }
1777
1778 return port_match(udpinfo->spts[0], udpinfo->spts[1],
1779 ntohs(uh->source),
1780 !!(udpinfo->invflags & IP6T_UDP_INV_SRCPT))
1781 && port_match(udpinfo->dpts[0], udpinfo->dpts[1],
1782 ntohs(uh->dest),
1783 !!(udpinfo->invflags & IP6T_UDP_INV_DSTPT));
1784}
1785
1786/* Called when user tries to insert an entry of this type. */
1787static int
1788udp_checkentry(const char *tablename,
1789 const struct ip6t_ip6 *ipv6,
1790 void *matchinfo,
1791 unsigned int matchinfosize,
1792 unsigned int hook_mask)
1793{
1794 const struct ip6t_udp *udpinfo = matchinfo;
1795
1796 /* Must specify proto == UDP, and no unknown invflags */
1797 if (ipv6->proto != IPPROTO_UDP || (ipv6->invflags & IP6T_INV_PROTO)) {
1798 duprintf("ip6t_udp: Protocol %u != %u\n", ipv6->proto,
1799 IPPROTO_UDP);
1800 return 0;
1801 }
1802 if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_udp))) {
1803 duprintf("ip6t_udp: matchsize %u != %u\n",
1804 matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_udp)));
1805 return 0;
1806 }
1807 if (udpinfo->invflags & ~IP6T_UDP_INV_MASK) {
1808 duprintf("ip6t_udp: unknown flags %X\n",
1809 udpinfo->invflags);
1810 return 0;
1811 }
1812
1813 return 1;
1814} 1313}
1815 1314
1816/* Returns 1 if the type and code is matched by the range, 0 otherwise */ 1315/* Returns 1 if the type and code is matched by the range, 0 otherwise */
@@ -1858,11 +1357,12 @@ icmp6_match(const struct sk_buff *skb,
1858/* Called when user tries to insert an entry of this type. */ 1357/* Called when user tries to insert an entry of this type. */
1859static int 1358static int
1860icmp6_checkentry(const char *tablename, 1359icmp6_checkentry(const char *tablename,
1861 const struct ip6t_ip6 *ipv6, 1360 const void *entry,
1862 void *matchinfo, 1361 void *matchinfo,
1863 unsigned int matchsize, 1362 unsigned int matchsize,
1864 unsigned int hook_mask) 1363 unsigned int hook_mask)
1865{ 1364{
1365 const struct ip6t_ip6 *ipv6 = entry;
1866 const struct ip6t_icmp *icmpinfo = matchinfo; 1366 const struct ip6t_icmp *icmpinfo = matchinfo;
1867 1367
1868 /* Must specify proto == ICMP, and no unknown invflags */ 1368 /* Must specify proto == ICMP, and no unknown invflags */
@@ -1892,164 +1392,42 @@ static struct nf_sockopt_ops ip6t_sockopts = {
1892 .get = do_ip6t_get_ctl, 1392 .get = do_ip6t_get_ctl,
1893}; 1393};
1894 1394
1895static struct ip6t_match tcp_matchstruct = {
1896 .name = "tcp",
1897 .match = &tcp_match,
1898 .checkentry = &tcp_checkentry,
1899};
1900
1901static struct ip6t_match udp_matchstruct = {
1902 .name = "udp",
1903 .match = &udp_match,
1904 .checkentry = &udp_checkentry,
1905};
1906
1907static struct ip6t_match icmp6_matchstruct = { 1395static struct ip6t_match icmp6_matchstruct = {
1908 .name = "icmp6", 1396 .name = "icmp6",
1909 .match = &icmp6_match, 1397 .match = &icmp6_match,
1910 .checkentry = &icmp6_checkentry, 1398 .checkentry = &icmp6_checkentry,
1911}; 1399};
1912 1400
1913#ifdef CONFIG_PROC_FS
1914static inline int print_name(const char *i,
1915 off_t start_offset, char *buffer, int length,
1916 off_t *pos, unsigned int *count)
1917{
1918 if ((*count)++ >= start_offset) {
1919 unsigned int namelen;
1920
1921 namelen = sprintf(buffer + *pos, "%s\n",
1922 i + sizeof(struct list_head));
1923 if (*pos + namelen > length) {
1924 /* Stop iterating */
1925 return 1;
1926 }
1927 *pos += namelen;
1928 }
1929 return 0;
1930}
1931
1932static inline int print_target(const struct ip6t_target *t,
1933 off_t start_offset, char *buffer, int length,
1934 off_t *pos, unsigned int *count)
1935{
1936 if (t == &ip6t_standard_target || t == &ip6t_error_target)
1937 return 0;
1938 return print_name((char *)t, start_offset, buffer, length, pos, count);
1939}
1940
1941static int ip6t_get_tables(char *buffer, char **start, off_t offset, int length)
1942{
1943 off_t pos = 0;
1944 unsigned int count = 0;
1945
1946 if (down_interruptible(&ip6t_mutex) != 0)
1947 return 0;
1948
1949 LIST_FIND(&ip6t_tables, print_name, char *,
1950 offset, buffer, length, &pos, &count);
1951
1952 up(&ip6t_mutex);
1953
1954 /* `start' hack - see fs/proc/generic.c line ~105 */
1955 *start=(char *)((unsigned long)count-offset);
1956 return pos;
1957}
1958
1959static int ip6t_get_targets(char *buffer, char **start, off_t offset, int length)
1960{
1961 off_t pos = 0;
1962 unsigned int count = 0;
1963
1964 if (down_interruptible(&ip6t_mutex) != 0)
1965 return 0;
1966
1967 LIST_FIND(&ip6t_target, print_target, struct ip6t_target *,
1968 offset, buffer, length, &pos, &count);
1969
1970 up(&ip6t_mutex);
1971
1972 *start = (char *)((unsigned long)count - offset);
1973 return pos;
1974}
1975
1976static int ip6t_get_matches(char *buffer, char **start, off_t offset, int length)
1977{
1978 off_t pos = 0;
1979 unsigned int count = 0;
1980
1981 if (down_interruptible(&ip6t_mutex) != 0)
1982 return 0;
1983
1984 LIST_FIND(&ip6t_match, print_name, char *,
1985 offset, buffer, length, &pos, &count);
1986
1987 up(&ip6t_mutex);
1988
1989 *start = (char *)((unsigned long)count - offset);
1990 return pos;
1991}
1992
1993static const struct { char *name; get_info_t *get_info; } ip6t_proc_entry[] =
1994{ { "ip6_tables_names", ip6t_get_tables },
1995 { "ip6_tables_targets", ip6t_get_targets },
1996 { "ip6_tables_matches", ip6t_get_matches },
1997 { NULL, NULL} };
1998#endif /*CONFIG_PROC_FS*/
1999
2000static int __init init(void) 1401static int __init init(void)
2001{ 1402{
2002 int ret; 1403 int ret;
2003 1404
1405 xt_proto_init(AF_INET6);
1406
2004 /* Noone else will be downing sem now, so we won't sleep */ 1407 /* Noone else will be downing sem now, so we won't sleep */
2005 down(&ip6t_mutex); 1408 xt_register_target(AF_INET6, &ip6t_standard_target);
2006 list_append(&ip6t_target, &ip6t_standard_target); 1409 xt_register_target(AF_INET6, &ip6t_error_target);
2007 list_append(&ip6t_target, &ip6t_error_target); 1410 xt_register_match(AF_INET6, &icmp6_matchstruct);
2008 list_append(&ip6t_match, &tcp_matchstruct);
2009 list_append(&ip6t_match, &udp_matchstruct);
2010 list_append(&ip6t_match, &icmp6_matchstruct);
2011 up(&ip6t_mutex);
2012 1411
2013 /* Register setsockopt */ 1412 /* Register setsockopt */
2014 ret = nf_register_sockopt(&ip6t_sockopts); 1413 ret = nf_register_sockopt(&ip6t_sockopts);
2015 if (ret < 0) { 1414 if (ret < 0) {
2016 duprintf("Unable to register sockopts.\n"); 1415 duprintf("Unable to register sockopts.\n");
1416 xt_proto_fini(AF_INET6);
2017 return ret; 1417 return ret;
2018 } 1418 }
2019 1419
2020#ifdef CONFIG_PROC_FS 1420 printk("ip6_tables: (C) 2000-2006 Netfilter Core Team\n");
2021 {
2022 struct proc_dir_entry *proc;
2023 int i;
2024
2025 for (i = 0; ip6t_proc_entry[i].name; i++) {
2026 proc = proc_net_create(ip6t_proc_entry[i].name, 0,
2027 ip6t_proc_entry[i].get_info);
2028 if (!proc) {
2029 while (--i >= 0)
2030 proc_net_remove(ip6t_proc_entry[i].name);
2031 nf_unregister_sockopt(&ip6t_sockopts);
2032 return -ENOMEM;
2033 }
2034 proc->owner = THIS_MODULE;
2035 }
2036 }
2037#endif
2038
2039 printk("ip6_tables: (C) 2000-2002 Netfilter core team\n");
2040 return 0; 1421 return 0;
2041} 1422}
2042 1423
2043static void __exit fini(void) 1424static void __exit fini(void)
2044{ 1425{
2045 nf_unregister_sockopt(&ip6t_sockopts); 1426 nf_unregister_sockopt(&ip6t_sockopts);
2046#ifdef CONFIG_PROC_FS 1427 xt_unregister_match(AF_INET6, &icmp6_matchstruct);
2047 { 1428 xt_unregister_target(AF_INET6, &ip6t_error_target);
2048 int i; 1429 xt_unregister_target(AF_INET6, &ip6t_standard_target);
2049 for (i = 0; ip6t_proc_entry[i].name; i++) 1430 xt_proto_fini(AF_INET6);
2050 proc_net_remove(ip6t_proc_entry[i].name);
2051 }
2052#endif
2053} 1431}
2054 1432
2055/* 1433/*
@@ -2128,10 +1506,6 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
2128EXPORT_SYMBOL(ip6t_register_table); 1506EXPORT_SYMBOL(ip6t_register_table);
2129EXPORT_SYMBOL(ip6t_unregister_table); 1507EXPORT_SYMBOL(ip6t_unregister_table);
2130EXPORT_SYMBOL(ip6t_do_table); 1508EXPORT_SYMBOL(ip6t_do_table);
2131EXPORT_SYMBOL(ip6t_register_match);
2132EXPORT_SYMBOL(ip6t_unregister_match);
2133EXPORT_SYMBOL(ip6t_register_target);
2134EXPORT_SYMBOL(ip6t_unregister_target);
2135EXPORT_SYMBOL(ip6t_ext_hdr); 1509EXPORT_SYMBOL(ip6t_ext_hdr);
2136EXPORT_SYMBOL(ipv6_find_hdr); 1510EXPORT_SYMBOL(ipv6_find_hdr);
2137EXPORT_SYMBOL(ip6_masked_addrcmp); 1511EXPORT_SYMBOL(ip6_masked_addrcmp);
diff --git a/net/ipv6/netfilter/ip6t_HL.c b/net/ipv6/netfilter/ip6t_HL.c
index 8f5549b72720..306200c35057 100644
--- a/net/ipv6/netfilter/ip6t_HL.c
+++ b/net/ipv6/netfilter/ip6t_HL.c
@@ -62,7 +62,7 @@ static unsigned int ip6t_hl_target(struct sk_buff **pskb,
62} 62}
63 63
64static int ip6t_hl_checkentry(const char *tablename, 64static int ip6t_hl_checkentry(const char *tablename,
65 const struct ip6t_entry *e, 65 const void *entry,
66 void *targinfo, 66 void *targinfo,
67 unsigned int targinfosize, 67 unsigned int targinfosize,
68 unsigned int hook_mask) 68 unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
index ae4653bfd654..77c725832dec 100644
--- a/net/ipv6/netfilter/ip6t_LOG.c
+++ b/net/ipv6/netfilter/ip6t_LOG.c
@@ -63,9 +63,8 @@ static void dump_packet(const struct nf_loginfo *info,
63 return; 63 return;
64 } 64 }
65 65
66 /* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000" */ 66 /* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000 " */
67 printk("SRC=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ih->saddr)); 67 printk("SRC=" NIP6_FMT " DST=" NIP6_FMT " ", NIP6(ih->saddr), NIP6(ih->daddr));
68 printk("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ih->daddr));
69 68
70 /* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */ 69 /* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */
71 printk("LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ", 70 printk("LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ",
@@ -444,7 +443,7 @@ ip6t_log_target(struct sk_buff **pskb,
444 443
445 444
446static int ip6t_log_checkentry(const char *tablename, 445static int ip6t_log_checkentry(const char *tablename,
447 const struct ip6t_entry *e, 446 const void *entry,
448 void *targinfo, 447 void *targinfo,
449 unsigned int targinfosize, 448 unsigned int targinfosize,
450 unsigned int hook_mask) 449 unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6t_MARK.c b/net/ipv6/netfilter/ip6t_MARK.c
deleted file mode 100644
index eab8fb864ee0..000000000000
--- a/net/ipv6/netfilter/ip6t_MARK.c
+++ /dev/null
@@ -1,81 +0,0 @@
1/* This is a module which is used for setting the NFMARK field of an skb. */
2
3/* (C) 1999-2001 Marc Boucher <marc@mbsi.ca>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10#include <linux/module.h>
11#include <linux/skbuff.h>
12#include <linux/ip.h>
13#include <net/checksum.h>
14
15#include <linux/netfilter_ipv6/ip6_tables.h>
16#include <linux/netfilter_ipv6/ip6t_MARK.h>
17
18MODULE_LICENSE("GPL");
19MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
20
21static unsigned int
22target(struct sk_buff **pskb,
23 const struct net_device *in,
24 const struct net_device *out,
25 unsigned int hooknum,
26 const void *targinfo,
27 void *userinfo)
28{
29 const struct ip6t_mark_target_info *markinfo = targinfo;
30
31 if((*pskb)->nfmark != markinfo->mark)
32 (*pskb)->nfmark = markinfo->mark;
33
34 return IP6T_CONTINUE;
35}
36
37static int
38checkentry(const char *tablename,
39 const struct ip6t_entry *e,
40 void *targinfo,
41 unsigned int targinfosize,
42 unsigned int hook_mask)
43{
44 if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_mark_target_info))) {
45 printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n",
46 targinfosize,
47 IP6T_ALIGN(sizeof(struct ip6t_mark_target_info)));
48 return 0;
49 }
50
51 if (strcmp(tablename, "mangle") != 0) {
52 printk(KERN_WARNING "MARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
53 return 0;
54 }
55
56 return 1;
57}
58
59static struct ip6t_target ip6t_mark_reg = {
60 .name = "MARK",
61 .target = target,
62 .checkentry = checkentry,
63 .me = THIS_MODULE
64};
65
66static int __init init(void)
67{
68 printk(KERN_DEBUG "registering ipv6 mark target\n");
69 if (ip6t_register_target(&ip6t_mark_reg))
70 return -EINVAL;
71
72 return 0;
73}
74
75static void __exit fini(void)
76{
77 ip6t_unregister_target(&ip6t_mark_reg);
78}
79
80module_init(init);
81module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_NFQUEUE.c b/net/ipv6/netfilter/ip6t_NFQUEUE.c
deleted file mode 100644
index c6e3730e7409..000000000000
--- a/net/ipv6/netfilter/ip6t_NFQUEUE.c
+++ /dev/null
@@ -1,70 +0,0 @@
1/* ip6tables module for using new netfilter netlink queue
2 *
3 * (C) 2005 by Harald Welte <laforge@netfilter.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 */
10
11#include <linux/module.h>
12#include <linux/skbuff.h>
13
14#include <linux/netfilter.h>
15#include <linux/netfilter_ipv6/ip6_tables.h>
16#include <linux/netfilter_ipv4/ipt_NFQUEUE.h>
17
18MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
19MODULE_DESCRIPTION("ip6tables NFQUEUE target");
20MODULE_LICENSE("GPL");
21
22static unsigned int
23target(struct sk_buff **pskb,
24 const struct net_device *in,
25 const struct net_device *out,
26 unsigned int hooknum,
27 const void *targinfo,
28 void *userinfo)
29{
30 const struct ipt_NFQ_info *tinfo = targinfo;
31
32 return NF_QUEUE_NR(tinfo->queuenum);
33}
34
35static int
36checkentry(const char *tablename,
37 const struct ip6t_entry *e,
38 void *targinfo,
39 unsigned int targinfosize,
40 unsigned int hook_mask)
41{
42 if (targinfosize != IP6T_ALIGN(sizeof(struct ipt_NFQ_info))) {
43 printk(KERN_WARNING "NFQUEUE: targinfosize %u != %Zu\n",
44 targinfosize,
45 IP6T_ALIGN(sizeof(struct ipt_NFQ_info)));
46 return 0;
47 }
48
49 return 1;
50}
51
52static struct ip6t_target ipt_NFQ_reg = {
53 .name = "NFQUEUE",
54 .target = target,
55 .checkentry = checkentry,
56 .me = THIS_MODULE,
57};
58
59static int __init init(void)
60{
61 return ip6t_register_target(&ipt_NFQ_reg);
62}
63
64static void __exit fini(void)
65{
66 ip6t_unregister_target(&ipt_NFQ_reg);
67}
68
69module_init(init);
70module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c
index b03e87adca93..c745717b4ce2 100644
--- a/net/ipv6/netfilter/ip6t_REJECT.c
+++ b/net/ipv6/netfilter/ip6t_REJECT.c
@@ -218,12 +218,13 @@ static unsigned int reject6_target(struct sk_buff **pskb,
218} 218}
219 219
220static int check(const char *tablename, 220static int check(const char *tablename,
221 const struct ip6t_entry *e, 221 const void *entry,
222 void *targinfo, 222 void *targinfo,
223 unsigned int targinfosize, 223 unsigned int targinfosize,
224 unsigned int hook_mask) 224 unsigned int hook_mask)
225{ 225{
226 const struct ip6t_reject_info *rejinfo = targinfo; 226 const struct ip6t_reject_info *rejinfo = targinfo;
227 const struct ip6t_entry *e = entry;
227 228
228 if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) { 229 if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) {
229 DEBUGP("ip6t_REJECT: targinfosize %u != 0\n", targinfosize); 230 DEBUGP("ip6t_REJECT: targinfosize %u != 0\n", targinfosize);
diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c
index f5c1a7ff4a1f..219a30365dff 100644
--- a/net/ipv6/netfilter/ip6t_ah.c
+++ b/net/ipv6/netfilter/ip6t_ah.c
@@ -98,7 +98,7 @@ match(const struct sk_buff *skb,
98/* Called when user tries to insert an entry of this type. */ 98/* Called when user tries to insert an entry of this type. */
99static int 99static int
100checkentry(const char *tablename, 100checkentry(const char *tablename,
101 const struct ip6t_ip6 *ip, 101 const void *entry,
102 void *matchinfo, 102 void *matchinfo,
103 unsigned int matchinfosize, 103 unsigned int matchinfosize,
104 unsigned int hook_mask) 104 unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6t_dst.c b/net/ipv6/netfilter/ip6t_dst.c
index 48cf5f9efc95..80fe82669ce2 100644
--- a/net/ipv6/netfilter/ip6t_dst.c
+++ b/net/ipv6/netfilter/ip6t_dst.c
@@ -178,7 +178,7 @@ match(const struct sk_buff *skb,
178/* Called when user tries to insert an entry of this type. */ 178/* Called when user tries to insert an entry of this type. */
179static int 179static int
180checkentry(const char *tablename, 180checkentry(const char *tablename,
181 const struct ip6t_ip6 *ip, 181 const void *info,
182 void *matchinfo, 182 void *matchinfo,
183 unsigned int matchinfosize, 183 unsigned int matchinfosize,
184 unsigned int hook_mask) 184 unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6t_esp.c b/net/ipv6/netfilter/ip6t_esp.c
index e1828f6d0a40..724285df8711 100644
--- a/net/ipv6/netfilter/ip6t_esp.c
+++ b/net/ipv6/netfilter/ip6t_esp.c
@@ -76,7 +76,7 @@ match(const struct sk_buff *skb,
76/* Called when user tries to insert an entry of this type. */ 76/* Called when user tries to insert an entry of this type. */
77static int 77static int
78checkentry(const char *tablename, 78checkentry(const char *tablename,
79 const struct ip6t_ip6 *ip, 79 const void *ip,
80 void *matchinfo, 80 void *matchinfo,
81 unsigned int matchinfosize, 81 unsigned int matchinfosize,
82 unsigned int hook_mask) 82 unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6t_eui64.c b/net/ipv6/netfilter/ip6t_eui64.c
index 616c2cbcd54d..ddf5f571909c 100644
--- a/net/ipv6/netfilter/ip6t_eui64.c
+++ b/net/ipv6/netfilter/ip6t_eui64.c
@@ -62,7 +62,7 @@ match(const struct sk_buff *skb,
62 62
63static int 63static int
64ip6t_eui64_checkentry(const char *tablename, 64ip6t_eui64_checkentry(const char *tablename,
65 const struct ip6t_ip6 *ip, 65 const void *ip,
66 void *matchinfo, 66 void *matchinfo,
67 unsigned int matchsize, 67 unsigned int matchsize,
68 unsigned int hook_mask) 68 unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c
index d1549b268669..a9964b946ed5 100644
--- a/net/ipv6/netfilter/ip6t_frag.c
+++ b/net/ipv6/netfilter/ip6t_frag.c
@@ -115,7 +115,7 @@ match(const struct sk_buff *skb,
115/* Called when user tries to insert an entry of this type. */ 115/* Called when user tries to insert an entry of this type. */
116static int 116static int
117checkentry(const char *tablename, 117checkentry(const char *tablename,
118 const struct ip6t_ip6 *ip, 118 const void *ip,
119 void *matchinfo, 119 void *matchinfo,
120 unsigned int matchinfosize, 120 unsigned int matchinfosize,
121 unsigned int hook_mask) 121 unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c
index e3bc8e2700e7..ed8ded18bbd4 100644
--- a/net/ipv6/netfilter/ip6t_hbh.c
+++ b/net/ipv6/netfilter/ip6t_hbh.c
@@ -178,7 +178,7 @@ match(const struct sk_buff *skb,
178/* Called when user tries to insert an entry of this type. */ 178/* Called when user tries to insert an entry of this type. */
179static int 179static int
180checkentry(const char *tablename, 180checkentry(const char *tablename,
181 const struct ip6t_ip6 *ip, 181 const void *entry,
182 void *matchinfo, 182 void *matchinfo,
183 unsigned int matchinfosize, 183 unsigned int matchinfosize,
184 unsigned int hook_mask) 184 unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6t_hl.c b/net/ipv6/netfilter/ip6t_hl.c
index 0beaff5471dd..c5d9079f2d9d 100644
--- a/net/ipv6/netfilter/ip6t_hl.c
+++ b/net/ipv6/netfilter/ip6t_hl.c
@@ -48,7 +48,7 @@ static int match(const struct sk_buff *skb, const struct net_device *in,
48 return 0; 48 return 0;
49} 49}
50 50
51static int checkentry(const char *tablename, const struct ip6t_ip6 *ip, 51static int checkentry(const char *tablename, const void *entry,
52 void *matchinfo, unsigned int matchsize, 52 void *matchinfo, unsigned int matchsize,
53 unsigned int hook_mask) 53 unsigned int hook_mask)
54{ 54{
diff --git a/net/ipv6/netfilter/ip6t_ipv6header.c b/net/ipv6/netfilter/ip6t_ipv6header.c
index 32e67f05845b..fda1ceaf5a29 100644
--- a/net/ipv6/netfilter/ip6t_ipv6header.c
+++ b/net/ipv6/netfilter/ip6t_ipv6header.c
@@ -124,7 +124,7 @@ ipv6header_match(const struct sk_buff *skb,
124 124
125static int 125static int
126ipv6header_checkentry(const char *tablename, 126ipv6header_checkentry(const char *tablename,
127 const struct ip6t_ip6 *ip, 127 const void *ip,
128 void *matchinfo, 128 void *matchinfo,
129 unsigned int matchsize, 129 unsigned int matchsize,
130 unsigned int hook_mask) 130 unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6t_length.c b/net/ipv6/netfilter/ip6t_length.c
deleted file mode 100644
index e0537d3811d5..000000000000
--- a/net/ipv6/netfilter/ip6t_length.c
+++ /dev/null
@@ -1,66 +0,0 @@
1/* Length Match - IPv6 Port */
2
3/* (C) 1999-2001 James Morris <jmorros@intercode.com.au>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10
11#include <linux/module.h>
12#include <linux/skbuff.h>
13#include <linux/netfilter_ipv6/ip6t_length.h>
14#include <linux/netfilter_ipv6/ip6_tables.h>
15
16MODULE_LICENSE("GPL");
17MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
18MODULE_DESCRIPTION("IPv6 packet length match");
19
20static int
21match(const struct sk_buff *skb,
22 const struct net_device *in,
23 const struct net_device *out,
24 const void *matchinfo,
25 int offset,
26 unsigned int protoff,
27 int *hotdrop)
28{
29 const struct ip6t_length_info *info = matchinfo;
30 u_int16_t pktlen = ntohs(skb->nh.ipv6h->payload_len) + sizeof(struct ipv6hdr);
31
32 return (pktlen >= info->min && pktlen <= info->max) ^ info->invert;
33}
34
35static int
36checkentry(const char *tablename,
37 const struct ip6t_ip6 *ip,
38 void *matchinfo,
39 unsigned int matchsize,
40 unsigned int hook_mask)
41{
42 if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_length_info)))
43 return 0;
44
45 return 1;
46}
47
48static struct ip6t_match length_match = {
49 .name = "length",
50 .match = &match,
51 .checkentry = &checkentry,
52 .me = THIS_MODULE,
53};
54
55static int __init init(void)
56{
57 return ip6t_register_match(&length_match);
58}
59
60static void __exit fini(void)
61{
62 ip6t_unregister_match(&length_match);
63}
64
65module_init(init);
66module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_limit.c b/net/ipv6/netfilter/ip6t_limit.c
deleted file mode 100644
index fb782f610be2..000000000000
--- a/net/ipv6/netfilter/ip6t_limit.c
+++ /dev/null
@@ -1,147 +0,0 @@
1/* Kernel module to control the rate
2 *
3 * 2 September 1999: Changed from the target RATE to the match
4 * `limit', removed logging. Did I mention that
5 * Alexey is a fucking genius?
6 * Rusty Russell (rusty@rustcorp.com.au). */
7
8/* (C) 1999 Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr>
9 * (C) 1999 Hervé Eychenne <eychenne@info.enserb.u-bordeaux.fr>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 */
15
16#include <linux/module.h>
17#include <linux/skbuff.h>
18#include <linux/spinlock.h>
19#include <linux/interrupt.h>
20
21#include <linux/netfilter_ipv6/ip6_tables.h>
22#include <linux/netfilter_ipv6/ip6t_limit.h>
23
24MODULE_LICENSE("GPL");
25MODULE_AUTHOR("Herve Eychenne <rv@wallfire.org>");
26MODULE_DESCRIPTION("rate limiting within ip6tables");
27
28/* The algorithm used is the Simple Token Bucket Filter (TBF)
29 * see net/sched/sch_tbf.c in the linux source tree
30 */
31
32static DEFINE_SPINLOCK(limit_lock);
33
34/* Rusty: This is my (non-mathematically-inclined) understanding of
35 this algorithm. The `average rate' in jiffies becomes your initial
36 amount of credit `credit' and the most credit you can ever have
37 `credit_cap'. The `peak rate' becomes the cost of passing the
38 test, `cost'.
39
40 `prev' tracks the last packet hit: you gain one credit per jiffy.
41 If you get credit balance more than this, the extra credit is
42 discarded. Every time the match passes, you lose `cost' credits;
43 if you don't have that many, the test fails.
44
45 See Alexey's formal explanation in net/sched/sch_tbf.c.
46
47 To avoid underflow, we multiply by 128 (ie. you get 128 credits per
48 jiffy). Hence a cost of 2^32-1, means one pass per 32768 seconds
49 at 1024HZ (or one every 9 hours). A cost of 1 means 12800 passes
50 per second at 100HZ. */
51
52#define CREDITS_PER_JIFFY 128
53
54static int
55ip6t_limit_match(const struct sk_buff *skb,
56 const struct net_device *in,
57 const struct net_device *out,
58 const void *matchinfo,
59 int offset,
60 unsigned int protoff,
61 int *hotdrop)
62{
63 struct ip6t_rateinfo *r = ((struct ip6t_rateinfo *)matchinfo)->master;
64 unsigned long now = jiffies;
65
66 spin_lock_bh(&limit_lock);
67 r->credit += (now - xchg(&r->prev, now)) * CREDITS_PER_JIFFY;
68 if (r->credit > r->credit_cap)
69 r->credit = r->credit_cap;
70
71 if (r->credit >= r->cost) {
72 /* We're not limited. */
73 r->credit -= r->cost;
74 spin_unlock_bh(&limit_lock);
75 return 1;
76 }
77
78 spin_unlock_bh(&limit_lock);
79 return 0;
80}
81
82/* Precision saver. */
83static u_int32_t
84user2credits(u_int32_t user)
85{
86 /* If multiplying would overflow... */
87 if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
88 /* Divide first. */
89 return (user / IP6T_LIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
90
91 return (user * HZ * CREDITS_PER_JIFFY) / IP6T_LIMIT_SCALE;
92}
93
94static int
95ip6t_limit_checkentry(const char *tablename,
96 const struct ip6t_ip6 *ip,
97 void *matchinfo,
98 unsigned int matchsize,
99 unsigned int hook_mask)
100{
101 struct ip6t_rateinfo *r = matchinfo;
102
103 if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_rateinfo)))
104 return 0;
105
106 /* Check for overflow. */
107 if (r->burst == 0
108 || user2credits(r->avg * r->burst) < user2credits(r->avg)) {
109 printk("Call rusty: overflow in ip6t_limit: %u/%u\n",
110 r->avg, r->burst);
111 return 0;
112 }
113
114 /* User avg in seconds * IP6T_LIMIT_SCALE: convert to jiffies *
115 128. */
116 r->prev = jiffies;
117 r->credit = user2credits(r->avg * r->burst); /* Credits full. */
118 r->credit_cap = user2credits(r->avg * r->burst); /* Credits full. */
119 r->cost = user2credits(r->avg);
120
121 /* For SMP, we only want to use one set of counters. */
122 r->master = r;
123
124 return 1;
125}
126
127static struct ip6t_match ip6t_limit_reg = {
128 .name = "limit",
129 .match = ip6t_limit_match,
130 .checkentry = ip6t_limit_checkentry,
131 .me = THIS_MODULE,
132};
133
134static int __init init(void)
135{
136 if (ip6t_register_match(&ip6t_limit_reg))
137 return -EINVAL;
138 return 0;
139}
140
141static void __exit fini(void)
142{
143 ip6t_unregister_match(&ip6t_limit_reg);
144}
145
146module_init(init);
147module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_mac.c b/net/ipv6/netfilter/ip6t_mac.c
deleted file mode 100644
index c848152315bc..000000000000
--- a/net/ipv6/netfilter/ip6t_mac.c
+++ /dev/null
@@ -1,81 +0,0 @@
1/* Kernel module to match MAC address parameters. */
2
3/* (C) 1999-2001 Paul `Rusty' Russell
4 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/module.h>
12#include <linux/skbuff.h>
13#include <linux/if_ether.h>
14#include <linux/etherdevice.h>
15
16#include <linux/netfilter_ipv6/ip6t_mac.h>
17#include <linux/netfilter_ipv6/ip6_tables.h>
18
19MODULE_LICENSE("GPL");
20MODULE_DESCRIPTION("MAC address matching module for IPv6");
21MODULE_AUTHOR("Netfilter Core Teaam <coreteam@netfilter.org>");
22
23static int
24match(const struct sk_buff *skb,
25 const struct net_device *in,
26 const struct net_device *out,
27 const void *matchinfo,
28 int offset,
29 unsigned int protoff,
30 int *hotdrop)
31{
32 const struct ip6t_mac_info *info = matchinfo;
33
34 /* Is mac pointer valid? */
35 return (skb->mac.raw >= skb->head
36 && (skb->mac.raw + ETH_HLEN) <= skb->data
37 /* If so, compare... */
38 && ((!compare_ether_addr(eth_hdr(skb)->h_source, info->srcaddr))
39 ^ info->invert));
40}
41
42static int
43ip6t_mac_checkentry(const char *tablename,
44 const struct ip6t_ip6 *ip,
45 void *matchinfo,
46 unsigned int matchsize,
47 unsigned int hook_mask)
48{
49 if (hook_mask
50 & ~((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_IN)
51 | (1 << NF_IP6_FORWARD))) {
52 printk("ip6t_mac: only valid for PRE_ROUTING, LOCAL_IN or"
53 " FORWARD\n");
54 return 0;
55 }
56
57 if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_mac_info)))
58 return 0;
59
60 return 1;
61}
62
63static struct ip6t_match mac_match = {
64 .name = "mac",
65 .match = &match,
66 .checkentry = &ip6t_mac_checkentry,
67 .me = THIS_MODULE,
68};
69
70static int __init init(void)
71{
72 return ip6t_register_match(&mac_match);
73}
74
75static void __exit fini(void)
76{
77 ip6t_unregister_match(&mac_match);
78}
79
80module_init(init);
81module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_mark.c b/net/ipv6/netfilter/ip6t_mark.c
deleted file mode 100644
index affc3de364fc..000000000000
--- a/net/ipv6/netfilter/ip6t_mark.c
+++ /dev/null
@@ -1,66 +0,0 @@
1/* Kernel module to match NFMARK values. */
2
3/* (C) 1999-2001 Marc Boucher <marc@mbsi.ca>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10
11#include <linux/module.h>
12#include <linux/skbuff.h>
13
14#include <linux/netfilter_ipv6/ip6t_mark.h>
15#include <linux/netfilter_ipv6/ip6_tables.h>
16
17MODULE_LICENSE("GPL");
18MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
19MODULE_DESCRIPTION("ip6tables mark match");
20
21static int
22match(const struct sk_buff *skb,
23 const struct net_device *in,
24 const struct net_device *out,
25 const void *matchinfo,
26 int offset,
27 unsigned int protoff,
28 int *hotdrop)
29{
30 const struct ip6t_mark_info *info = matchinfo;
31
32 return ((skb->nfmark & info->mask) == info->mark) ^ info->invert;
33}
34
35static int
36checkentry(const char *tablename,
37 const struct ip6t_ip6 *ip,
38 void *matchinfo,
39 unsigned int matchsize,
40 unsigned int hook_mask)
41{
42 if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_mark_info)))
43 return 0;
44
45 return 1;
46}
47
48static struct ip6t_match mark_match = {
49 .name = "mark",
50 .match = &match,
51 .checkentry = &checkentry,
52 .me = THIS_MODULE,
53};
54
55static int __init init(void)
56{
57 return ip6t_register_match(&mark_match);
58}
59
60static void __exit fini(void)
61{
62 ip6t_unregister_match(&mark_match);
63}
64
65module_init(init);
66module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_multiport.c b/net/ipv6/netfilter/ip6t_multiport.c
index 6e3246153fa3..49f7829dfbc2 100644
--- a/net/ipv6/netfilter/ip6t_multiport.c
+++ b/net/ipv6/netfilter/ip6t_multiport.c
@@ -84,11 +84,12 @@ match(const struct sk_buff *skb,
84/* Called when user tries to insert an entry of this type. */ 84/* Called when user tries to insert an entry of this type. */
85static int 85static int
86checkentry(const char *tablename, 86checkentry(const char *tablename,
87 const struct ip6t_ip6 *ip, 87 const void *info,
88 void *matchinfo, 88 void *matchinfo,
89 unsigned int matchsize, 89 unsigned int matchsize,
90 unsigned int hook_mask) 90 unsigned int hook_mask)
91{ 91{
92 const struct ip6t_ip6 *ip = info;
92 const struct ip6t_multiport *multiinfo = matchinfo; 93 const struct ip6t_multiport *multiinfo = matchinfo;
93 94
94 if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_multiport))) 95 if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_multiport)))
diff --git a/net/ipv6/netfilter/ip6t_owner.c b/net/ipv6/netfilter/ip6t_owner.c
index 4de4cdad4b7d..5409b375b512 100644
--- a/net/ipv6/netfilter/ip6t_owner.c
+++ b/net/ipv6/netfilter/ip6t_owner.c
@@ -53,7 +53,7 @@ match(const struct sk_buff *skb,
53 53
54static int 54static int
55checkentry(const char *tablename, 55checkentry(const char *tablename,
56 const struct ip6t_ip6 *ip, 56 const void *ip,
57 void *matchinfo, 57 void *matchinfo,
58 unsigned int matchsize, 58 unsigned int matchsize,
59 unsigned int hook_mask) 59 unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c
index c1e770e45543..8465b4375855 100644
--- a/net/ipv6/netfilter/ip6t_rt.c
+++ b/net/ipv6/netfilter/ip6t_rt.c
@@ -183,7 +183,7 @@ match(const struct sk_buff *skb,
183/* Called when user tries to insert an entry of this type. */ 183/* Called when user tries to insert an entry of this type. */
184static int 184static int
185checkentry(const char *tablename, 185checkentry(const char *tablename,
186 const struct ip6t_ip6 *ip, 186 const void *entry,
187 void *matchinfo, 187 void *matchinfo,
188 unsigned int matchinfosize, 188 unsigned int matchinfosize,
189 unsigned int hook_mask) 189 unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
index 4c0028671c20..ce4a968e1f70 100644
--- a/net/ipv6/netfilter/ip6table_filter.c
+++ b/net/ipv6/netfilter/ip6table_filter.c
@@ -97,6 +97,7 @@ static struct ip6t_table packet_filter = {
97 .valid_hooks = FILTER_VALID_HOOKS, 97 .valid_hooks = FILTER_VALID_HOOKS,
98 .lock = RW_LOCK_UNLOCKED, 98 .lock = RW_LOCK_UNLOCKED,
99 .me = THIS_MODULE, 99 .me = THIS_MODULE,
100 .af = AF_INET6,
100}; 101};
101 102
102/* The work comes in here from netfilter.c. */ 103/* The work comes in here from netfilter.c. */
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index 85c1e6eada19..30a4627e000d 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -127,6 +127,7 @@ static struct ip6t_table packet_mangler = {
127 .valid_hooks = MANGLE_VALID_HOOKS, 127 .valid_hooks = MANGLE_VALID_HOOKS,
128 .lock = RW_LOCK_UNLOCKED, 128 .lock = RW_LOCK_UNLOCKED,
129 .me = THIS_MODULE, 129 .me = THIS_MODULE,
130 .af = AF_INET6,
130}; 131};
131 132
132/* The work comes in here from netfilter.c. */ 133/* The work comes in here from netfilter.c. */
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index c2982efd14af..db28ba3855e2 100644
--- a/net/ipv6/netfilter/ip6table_raw.c
+++ b/net/ipv6/netfilter/ip6table_raw.c
@@ -106,11 +106,12 @@ static struct
106 } 106 }
107}; 107};
108 108
109static struct ip6t_table packet_raw = { 109static struct xt_table packet_raw = {
110 .name = "raw", 110 .name = "raw",
111 .valid_hooks = RAW_VALID_HOOKS, 111 .valid_hooks = RAW_VALID_HOOKS,
112 .lock = RW_LOCK_UNLOCKED, 112 .lock = RW_LOCK_UNLOCKED,
113 .me = THIS_MODULE 113 .me = THIS_MODULE,
114 .af = AF_INET6,
114}; 115};
115 116
116/* The work comes in here from netfilter.c. */ 117/* The work comes in here from netfilter.c. */
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index e57d6fc9957a..ac702a29dd16 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -74,7 +74,7 @@ static int ipv6_invert_tuple(struct nf_conntrack_tuple *tuple,
74static int ipv6_print_tuple(struct seq_file *s, 74static int ipv6_print_tuple(struct seq_file *s,
75 const struct nf_conntrack_tuple *tuple) 75 const struct nf_conntrack_tuple *tuple)
76{ 76{
77 return seq_printf(s, "src=%x:%x:%x:%x:%x:%x:%x:%x dst=%x:%x:%x:%x:%x:%x:%x:%x ", 77 return seq_printf(s, "src=" NIP6_FMT " dst=" NIP6_FMT " ",
78 NIP6(*((struct in6_addr *)tuple->src.u3.ip6)), 78 NIP6(*((struct in6_addr *)tuple->src.u3.ip6)),
79 NIP6(*((struct in6_addr *)tuple->dst.u3.ip6))); 79 NIP6(*((struct in6_addr *)tuple->dst.u3.ip6)));
80} 80}
@@ -584,7 +584,7 @@ MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>");
584 584
585static int __init init(void) 585static int __init init(void)
586{ 586{
587 need_nf_conntrack(); 587 need_conntrack();
588 return init_or_cleanup(1); 588 return init_or_cleanup(1);
589} 589}
590 590
@@ -595,9 +595,3 @@ static void __exit fini(void)
595 595
596module_init(init); 596module_init(init);
597module_exit(fini); 597module_exit(fini);
598
599void need_ip6_conntrack(void)
600{
601}
602
603EXPORT_SYMBOL(need_ip6_conntrack);
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index f3e5ffbd592f..84ef9a13108d 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -70,8 +70,8 @@ struct nf_ct_frag6_skb_cb
70 70
71struct nf_ct_frag6_queue 71struct nf_ct_frag6_queue
72{ 72{
73 struct nf_ct_frag6_queue *next; 73 struct hlist_node list;
74 struct list_head lru_list; /* lru list member */ 74 struct list_head lru_list; /* lru list member */
75 75
76 __u32 id; /* fragment id */ 76 __u32 id; /* fragment id */
77 struct in6_addr saddr; 77 struct in6_addr saddr;
@@ -90,14 +90,13 @@ struct nf_ct_frag6_queue
90#define FIRST_IN 2 90#define FIRST_IN 2
91#define LAST_IN 1 91#define LAST_IN 1
92 __u16 nhoffset; 92 __u16 nhoffset;
93 struct nf_ct_frag6_queue **pprev;
94}; 93};
95 94
96/* Hash table. */ 95/* Hash table. */
97 96
98#define FRAG6Q_HASHSZ 64 97#define FRAG6Q_HASHSZ 64
99 98
100static struct nf_ct_frag6_queue *nf_ct_frag6_hash[FRAG6Q_HASHSZ]; 99static struct hlist_head nf_ct_frag6_hash[FRAG6Q_HASHSZ];
101static DEFINE_RWLOCK(nf_ct_frag6_lock); 100static DEFINE_RWLOCK(nf_ct_frag6_lock);
102static u32 nf_ct_frag6_hash_rnd; 101static u32 nf_ct_frag6_hash_rnd;
103static LIST_HEAD(nf_ct_frag6_lru_list); 102static LIST_HEAD(nf_ct_frag6_lru_list);
@@ -105,9 +104,7 @@ int nf_ct_frag6_nqueues = 0;
105 104
106static __inline__ void __fq_unlink(struct nf_ct_frag6_queue *fq) 105static __inline__ void __fq_unlink(struct nf_ct_frag6_queue *fq)
107{ 106{
108 if (fq->next) 107 hlist_del(&fq->list);
109 fq->next->pprev = fq->pprev;
110 *fq->pprev = fq->next;
111 list_del(&fq->lru_list); 108 list_del(&fq->lru_list);
112 nf_ct_frag6_nqueues--; 109 nf_ct_frag6_nqueues--;
113} 110}
@@ -158,28 +155,18 @@ static void nf_ct_frag6_secret_rebuild(unsigned long dummy)
158 get_random_bytes(&nf_ct_frag6_hash_rnd, sizeof(u32)); 155 get_random_bytes(&nf_ct_frag6_hash_rnd, sizeof(u32));
159 for (i = 0; i < FRAG6Q_HASHSZ; i++) { 156 for (i = 0; i < FRAG6Q_HASHSZ; i++) {
160 struct nf_ct_frag6_queue *q; 157 struct nf_ct_frag6_queue *q;
158 struct hlist_node *p, *n;
161 159
162 q = nf_ct_frag6_hash[i]; 160 hlist_for_each_entry_safe(q, p, n, &nf_ct_frag6_hash[i], list) {
163 while (q) {
164 struct nf_ct_frag6_queue *next = q->next;
165 unsigned int hval = ip6qhashfn(q->id, 161 unsigned int hval = ip6qhashfn(q->id,
166 &q->saddr, 162 &q->saddr,
167 &q->daddr); 163 &q->daddr);
168
169 if (hval != i) { 164 if (hval != i) {
170 /* Unlink. */ 165 hlist_del(&q->list);
171 if (q->next)
172 q->next->pprev = q->pprev;
173 *q->pprev = q->next;
174
175 /* Relink to new hash chain. */ 166 /* Relink to new hash chain. */
176 if ((q->next = nf_ct_frag6_hash[hval]) != NULL) 167 hlist_add_head(&q->list,
177 q->next->pprev = &q->next; 168 &nf_ct_frag6_hash[hval]);
178 nf_ct_frag6_hash[hval] = q;
179 q->pprev = &nf_ct_frag6_hash[hval];
180 } 169 }
181
182 q = next;
183 } 170 }
184 } 171 }
185 write_unlock(&nf_ct_frag6_lock); 172 write_unlock(&nf_ct_frag6_lock);
@@ -314,15 +301,17 @@ out:
314 301
315/* Creation primitives. */ 302/* Creation primitives. */
316 303
317
318static struct nf_ct_frag6_queue *nf_ct_frag6_intern(unsigned int hash, 304static struct nf_ct_frag6_queue *nf_ct_frag6_intern(unsigned int hash,
319 struct nf_ct_frag6_queue *fq_in) 305 struct nf_ct_frag6_queue *fq_in)
320{ 306{
321 struct nf_ct_frag6_queue *fq; 307 struct nf_ct_frag6_queue *fq;
308#ifdef CONFIG_SMP
309 struct hlist_node *n;
310#endif
322 311
323 write_lock(&nf_ct_frag6_lock); 312 write_lock(&nf_ct_frag6_lock);
324#ifdef CONFIG_SMP 313#ifdef CONFIG_SMP
325 for (fq = nf_ct_frag6_hash[hash]; fq; fq = fq->next) { 314 hlist_for_each_entry(fq, n, &nf_ct_frag6_hash[hash], list) {
326 if (fq->id == fq_in->id && 315 if (fq->id == fq_in->id &&
327 !ipv6_addr_cmp(&fq_in->saddr, &fq->saddr) && 316 !ipv6_addr_cmp(&fq_in->saddr, &fq->saddr) &&
328 !ipv6_addr_cmp(&fq_in->daddr, &fq->daddr)) { 317 !ipv6_addr_cmp(&fq_in->daddr, &fq->daddr)) {
@@ -340,10 +329,7 @@ static struct nf_ct_frag6_queue *nf_ct_frag6_intern(unsigned int hash,
340 atomic_inc(&fq->refcnt); 329 atomic_inc(&fq->refcnt);
341 330
342 atomic_inc(&fq->refcnt); 331 atomic_inc(&fq->refcnt);
343 if ((fq->next = nf_ct_frag6_hash[hash]) != NULL) 332 hlist_add_head(&fq->list, &nf_ct_frag6_hash[hash]);
344 fq->next->pprev = &fq->next;
345 nf_ct_frag6_hash[hash] = fq;
346 fq->pprev = &nf_ct_frag6_hash[hash];
347 INIT_LIST_HEAD(&fq->lru_list); 333 INIT_LIST_HEAD(&fq->lru_list);
348 list_add_tail(&fq->lru_list, &nf_ct_frag6_lru_list); 334 list_add_tail(&fq->lru_list, &nf_ct_frag6_lru_list);
349 nf_ct_frag6_nqueues++; 335 nf_ct_frag6_nqueues++;
@@ -384,10 +370,11 @@ static __inline__ struct nf_ct_frag6_queue *
384fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst) 370fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst)
385{ 371{
386 struct nf_ct_frag6_queue *fq; 372 struct nf_ct_frag6_queue *fq;
373 struct hlist_node *n;
387 unsigned int hash = ip6qhashfn(id, src, dst); 374 unsigned int hash = ip6qhashfn(id, src, dst);
388 375
389 read_lock(&nf_ct_frag6_lock); 376 read_lock(&nf_ct_frag6_lock);
390 for (fq = nf_ct_frag6_hash[hash]; fq; fq = fq->next) { 377 hlist_for_each_entry(fq, n, &nf_ct_frag6_hash[hash], list) {
391 if (fq->id == id && 378 if (fq->id == id &&
392 !ipv6_addr_cmp(src, &fq->saddr) && 379 !ipv6_addr_cmp(src, &fq->saddr) &&
393 !ipv6_addr_cmp(dst, &fq->daddr)) { 380 !ipv6_addr_cmp(dst, &fq->daddr)) {
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
index bf0d0abc3871..a5723024d3b3 100644
--- a/net/ipv6/xfrm6_state.c
+++ b/net/ipv6/xfrm6_state.c
@@ -15,6 +15,7 @@
15#include <linux/pfkeyv2.h> 15#include <linux/pfkeyv2.h>
16#include <linux/ipsec.h> 16#include <linux/ipsec.h>
17#include <net/ipv6.h> 17#include <net/ipv6.h>
18#include <net/addrconf.h>
18 19
19static struct xfrm_state_afinfo xfrm6_state_afinfo; 20static struct xfrm_state_afinfo xfrm6_state_afinfo;
20 21
@@ -41,6 +42,22 @@ __xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl,
41 memcpy(&x->props.saddr, &tmpl->saddr, sizeof(x->props.saddr)); 42 memcpy(&x->props.saddr, &tmpl->saddr, sizeof(x->props.saddr));
42 if (ipv6_addr_any((struct in6_addr*)&x->props.saddr)) 43 if (ipv6_addr_any((struct in6_addr*)&x->props.saddr))
43 memcpy(&x->props.saddr, saddr, sizeof(x->props.saddr)); 44 memcpy(&x->props.saddr, saddr, sizeof(x->props.saddr));
45 if (tmpl->mode && ipv6_addr_any((struct in6_addr*)&x->props.saddr)) {
46 struct rt6_info *rt;
47 struct flowi fl_tunnel = {
48 .nl_u = {
49 .ip6_u = {
50 .daddr = *(struct in6_addr *)daddr,
51 }
52 }
53 };
54 if (!xfrm_dst_lookup((struct xfrm_dst **)&rt,
55 &fl_tunnel, AF_INET6)) {
56 ipv6_get_saddr(&rt->u.dst, (struct in6_addr *)daddr,
57 (struct in6_addr *)&x->props.saddr);
58 dst_release(&rt->u.dst);
59 }
60 }
44 x->props.mode = tmpl->mode; 61 x->props.mode = tmpl->mode;
45 x->props.reqid = tmpl->reqid; 62 x->props.reqid = tmpl->reqid;
46 x->props.family = AF_INET6; 63 x->props.family = AF_INET6;
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index da09ff258648..8cfc58b96fc2 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -259,8 +259,7 @@ try_next_2:;
259 spi = 0; 259 spi = 0;
260 goto out; 260 goto out;
261alloc_spi: 261alloc_spi:
262 X6TPRINTK3(KERN_DEBUG "%s(): allocate new spi for " 262 X6TPRINTK3(KERN_DEBUG "%s(): allocate new spi for " NIP6_FMT "\n",
263 "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
264 __FUNCTION__, 263 __FUNCTION__,
265 NIP6(*(struct in6_addr *)saddr)); 264 NIP6(*(struct in6_addr *)saddr));
266 x6spi = kmem_cache_alloc(xfrm6_tunnel_spi_kmem, SLAB_ATOMIC); 265 x6spi = kmem_cache_alloc(xfrm6_tunnel_spi_kmem, SLAB_ATOMIC);
@@ -323,9 +322,8 @@ void xfrm6_tunnel_free_spi(xfrm_address_t *saddr)
323 list_byaddr) 322 list_byaddr)
324 { 323 {
325 if (memcmp(&x6spi->addr, saddr, sizeof(x6spi->addr)) == 0) { 324 if (memcmp(&x6spi->addr, saddr, sizeof(x6spi->addr)) == 0) {
326 X6TPRINTK3(KERN_DEBUG "%s(): x6spi object " 325 X6TPRINTK3(KERN_DEBUG "%s(): x6spi object for " NIP6_FMT
327 "for %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x " 326 " found at %p\n",
328 "found at %p\n",
329 __FUNCTION__, 327 __FUNCTION__,
330 NIP6(*(struct in6_addr *)saddr), 328 NIP6(*(struct in6_addr *)saddr),
331 x6spi); 329 x6spi);
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 7d55f9cbd853..99c0a0fa4a97 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -103,3 +103,261 @@ config NF_CT_NETLINK
103 This option enables support for a netlink-based userspace interface 103 This option enables support for a netlink-based userspace interface
104 104
105endmenu 105endmenu
106
107config NETFILTER_XTABLES
108 tristate "Netfilter Xtables support (required for ip_tables)"
109 help
110 This is required if you intend to use any of ip_tables,
111 ip6_tables or arp_tables.
112
113# alphabetically ordered list of targets
114
115config NETFILTER_XT_TARGET_CLASSIFY
116 tristate '"CLASSIFY" target support'
117 depends on NETFILTER_XTABLES
118 help
119 This option adds a `CLASSIFY' target, which enables the user to set
120 the priority of a packet. Some qdiscs can use this value for
121 classification, among these are:
122
123 atm, cbq, dsmark, pfifo_fast, htb, prio
124
125 To compile it as a module, choose M here. If unsure, say N.
126
127config NETFILTER_XT_TARGET_CONNMARK
128 tristate '"CONNMARK" target support'
129 depends on NETFILTER_XTABLES
130 depends on IP_NF_MANGLE || IP6_NF_MANGLE
131 depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4)
132 help
133 This option adds a `CONNMARK' target, which allows one to manipulate
134 the connection mark value. Similar to the MARK target, but
135 affects the connection mark value rather than the packet mark value.
136
137 If you want to compile it as a module, say M here and read
138 <file:Documentation/modules.txt>. The module will be called
139 ipt_CONNMARK.o. If unsure, say `N'.
140
141config NETFILTER_XT_TARGET_MARK
142 tristate '"MARK" target support'
143 depends on NETFILTER_XTABLES
144 help
145 This option adds a `MARK' target, which allows you to create rules
146 in the `mangle' table which alter the netfilter mark (nfmark) field
147 associated with the packet prior to routing. This can change
148 the routing method (see `Use netfilter MARK value as routing
149 key') and can also be used by other subsystems to change their
150 behavior.
151
152 To compile it as a module, choose M here. If unsure, say N.
153
154config NETFILTER_XT_TARGET_NFQUEUE
155 tristate '"NFQUEUE" target Support'
156 depends on NETFILTER_XTABLES
157 help
158 This Target replaced the old obsolete QUEUE target.
159
160 As opposed to QUEUE, it supports 65535 different queues,
161 not just one.
162
163 To compile it as a module, choose M here. If unsure, say N.
164
165config NETFILTER_XT_TARGET_NOTRACK
166 tristate '"NOTRACK" target support'
167 depends on NETFILTER_XTABLES
168 depends on IP_NF_RAW || IP6_NF_RAW
169 depends on IP_NF_CONNTRACK || NF_CONNTRACK
170 help
171 The NOTRACK target allows a select rule to specify
172 which packets *not* to enter the conntrack/NAT
173 subsystem with all the consequences (no ICMP error tracking,
174 no protocol helpers for the selected packets).
175
176 If you want to compile it as a module, say M here and read
177 <file:Documentation/modules.txt>. If unsure, say `N'.
178
179config NETFILTER_XT_MATCH_COMMENT
180 tristate '"comment" match support'
181 depends on NETFILTER_XTABLES
182 help
183 This option adds a `comment' dummy-match, which allows you to put
184 comments in your iptables ruleset.
185
186 If you want to compile it as a module, say M here and read
187 <file:Documentation/modules.txt>. If unsure, say `N'.
188
189config NETFILTER_XT_MATCH_CONNBYTES
190 tristate '"connbytes" per-connection counter match support'
191 depends on NETFILTER_XTABLES
192 depends on (IP_NF_CONNTRACK && IP_NF_CT_ACCT) || NF_CT_ACCT
193 help
194 This option adds a `connbytes' match, which allows you to match the
195 number of bytes and/or packets for each direction within a connection.
196
197 If you want to compile it as a module, say M here and read
198 <file:Documentation/modules.txt>. If unsure, say `N'.
199
200config NETFILTER_XT_MATCH_CONNMARK
201 tristate '"connmark" connection mark match support'
202 depends on NETFILTER_XTABLES
203 depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || NF_CONNTRACK_MARK
204 help
205 This option adds a `connmark' match, which allows you to match the
206 connection mark value previously set for the session by `CONNMARK'.
207
208 If you want to compile it as a module, say M here and read
209 <file:Documentation/modules.txt>. The module will be called
210 ipt_connmark.o. If unsure, say `N'.
211
212config NETFILTER_XT_MATCH_CONNTRACK
213 tristate '"conntrack" connection tracking match support'
214 depends on NETFILTER_XTABLES
215 depends on IP_NF_CONNTRACK || NF_CONNTRACK
216 help
217 This is a general conntrack match module, a superset of the state match.
218
219 It allows matching on additional conntrack information, which is
220 useful in complex configurations, such as NAT gateways with multiple
221 internet links or tunnels.
222
223 To compile it as a module, choose M here. If unsure, say N.
224
225config NETFILTER_XT_MATCH_DCCP
226 tristate '"DCCP" protocol match support'
227 depends on NETFILTER_XTABLES
228 help
229 With this option enabled, you will be able to use the iptables
230 `dccp' match in order to match on DCCP source/destination ports
231 and DCCP flags.
232
233 If you want to compile it as a module, say M here and read
234 <file:Documentation/modules.txt>. If unsure, say `N'.
235
236config NETFILTER_XT_MATCH_HELPER
237 tristate '"helper" match support'
238 depends on NETFILTER_XTABLES
239 depends on IP_NF_CONNTRACK || NF_CONNTRACK
240 help
241 Helper matching allows you to match packets in dynamic connections
242 tracked by a conntrack-helper, ie. ip_conntrack_ftp
243
244 To compile it as a module, choose M here. If unsure, say Y.
245
246config NETFILTER_XT_MATCH_LENGTH
247 tristate '"length" match support'
248 depends on NETFILTER_XTABLES
249 help
250 This option allows you to match the length of a packet against a
251 specific value or range of values.
252
253 To compile it as a module, choose M here. If unsure, say N.
254
255config NETFILTER_XT_MATCH_LIMIT
256 tristate '"limit" match support'
257 depends on NETFILTER_XTABLES
258 help
259 limit matching allows you to control the rate at which a rule can be
260 matched: mainly useful in combination with the LOG target ("LOG
261 target support", below) and to avoid some Denial of Service attacks.
262
263 To compile it as a module, choose M here. If unsure, say N.
264
265config NETFILTER_XT_MATCH_MAC
266 tristate '"mac" address match support'
267 depends on NETFILTER_XTABLES
268 help
269 MAC matching allows you to match packets based on the source
270 Ethernet address of the packet.
271
272 To compile it as a module, choose M here. If unsure, say N.
273
274config NETFILTER_XT_MATCH_MARK
275 tristate '"mark" match support'
276 depends on NETFILTER_XTABLES
277 help
278 Netfilter mark matching allows you to match packets based on the
279 `nfmark' value in the packet. This can be set by the MARK target
280 (see below).
281
282 To compile it as a module, choose M here. If unsure, say N.
283
284config NETFILTER_XT_MATCH_PHYSDEV
285 tristate '"physdev" match support'
286 depends on NETFILTER_XTABLES && BRIDGE_NETFILTER
287 help
288 Physdev packet matching matches against the physical bridge ports
289 the IP packet arrived on or will leave by.
290
291 To compile it as a module, choose M here. If unsure, say N.
292
293config NETFILTER_XT_MATCH_PKTTYPE
294 tristate '"pkttype" packet type match support'
295 depends on NETFILTER_XTABLES
296 help
297 Packet type matching allows you to match a packet by
298 its "class", eg. BROADCAST, MULTICAST, ...
299
300 Typical usage:
301 iptables -A INPUT -m pkttype --pkt-type broadcast -j LOG
302
303 To compile it as a module, choose M here. If unsure, say N.
304
305config NETFILTER_XT_MATCH_REALM
306 tristate '"realm" match support'
307 depends on NETFILTER_XTABLES
308 select NET_CLS_ROUTE
309 help
310 This option adds a `realm' match, which allows you to use the realm
311 key from the routing subsystem inside iptables.
312
313 This match pretty much resembles the CONFIG_NET_CLS_ROUTE4 option
314 in tc world.
315
316 If you want to compile it as a module, say M here and read
317 <file:Documentation/modules.txt>. If unsure, say `N'.
318
319config NETFILTER_XT_MATCH_SCTP
320 tristate '"sctp" protocol match support'
321 depends on NETFILTER_XTABLES
322 help
323 With this option enabled, you will be able to use the
324 `sctp' match in order to match on SCTP source/destination ports
325 and SCTP chunk types.
326
327 If you want to compile it as a module, say M here and read
328 <file:Documentation/modules.txt>. If unsure, say `N'.
329
330config NETFILTER_XT_MATCH_STATE
331 tristate '"state" match support'
332 depends on NETFILTER_XTABLES
333 depends on IP_NF_CONNTRACK || NF_CONNTRACK
334 help
335 Connection state matching allows you to match packets based on their
336 relationship to a tracked connection (ie. previous packets). This
337 is a powerful tool for packet classification.
338
339 To compile it as a module, choose M here. If unsure, say N.
340
341config NETFILTER_XT_MATCH_STRING
342 tristate '"string" match support'
343 depends on NETFILTER_XTABLES
344 select TEXTSEARCH
345 select TEXTSEARCH_KMP
346 select TEXTSEARCH_BM
347 select TEXTSEARCH_FSM
348 help
349 This option adds a `string' match, which allows you to look for
350 pattern matchings in packets.
351
352 To compile it as a module, choose M here. If unsure, say N.
353
354config NETFILTER_XT_MATCH_TCPMSS
355 tristate '"tcpmss" match support'
356 depends on NETFILTER_XTABLES
357 help
358 This option adds a `tcpmss' match, which allows you to examine the
359 MSS value of TCP SYN packets, which control the maximum packet size
360 for that connection.
361
362 To compile it as a module, choose M here. If unsure, say N.
363
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index cb2183145c37..746172ebc91b 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -1,4 +1,5 @@
1netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o 1netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o
2nf_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
2 3
3obj-$(CONFIG_NETFILTER) = netfilter.o 4obj-$(CONFIG_NETFILTER) = netfilter.o
4 5
@@ -6,13 +7,43 @@ obj-$(CONFIG_NETFILTER_NETLINK) += nfnetlink.o
6obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o 7obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o
7obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o 8obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o
8 9
9nf_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 10# connection tracking
10
11obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o 11obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o
12obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o
13 12
14# SCTP protocol connection tracking 13# SCTP protocol connection tracking
15obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o 14obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o
16 15
17# netlink interface for nf_conntrack 16# netlink interface for nf_conntrack
18obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o 17obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o
18
19# connection tracking helpers
20obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o
21
22# generic X tables
23obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
24
25# targets
26obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIFY) += xt_CLASSIFY.o
27obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o
28obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o
29obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
30obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o
31
32# matches
33obj-$(CONFIG_NETFILTER_XT_MATCH_COMMENT) += xt_comment.o
34obj-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += xt_connbytes.o
35obj-$(CONFIG_NETFILTER_XT_MATCH_CONNMARK) += xt_connmark.o
36obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o
37obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o
38obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o
39obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o
40obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o
41obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o
42obj-$(CONFIG_NETFILTER_XT_MATCH_MARK) += xt_mark.o
43obj-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) += xt_pkttype.o
44obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o
45obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o
46obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o
47obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o
48obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o
49obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
index d5a6eaf4a1de..ab0c920f0d30 100644
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -545,11 +545,11 @@ static int help(struct sk_buff **pskb,
545 different IP address. Simply don't record it for 545 different IP address. Simply don't record it for
546 NAT. */ 546 NAT. */
547 if (cmd.l3num == PF_INET) { 547 if (cmd.l3num == PF_INET) {
548 DEBUGP("conntrack_ftp: NOT RECORDING: %u,%u,%u,%u != %u.%u.%u.%u\n", 548 DEBUGP("conntrack_ftp: NOT RECORDING: " NIPQUAD_FMT " != " NIPQUAD_FMT "\n",
549 NIPQUAD(cmd.u3.ip), 549 NIPQUAD(cmd.u3.ip),
550 NIPQUAD(ct->tuplehash[dir].tuple.src.u3.ip)); 550 NIPQUAD(ct->tuplehash[dir].tuple.src.u3.ip));
551 } else { 551 } else {
552 DEBUGP("conntrack_ftp: NOT RECORDING: %x:%x:%x:%x:%x:%x:%x:%x != %x:%x:%x:%x:%x:%x:%x:%x\n", 552 DEBUGP("conntrack_ftp: NOT RECORDING: " NIP6_FMT " != " NIP6_FMT "\n",
553 NIP6(*((struct in6_addr *)cmd.u3.ip6)), 553 NIP6(*((struct in6_addr *)cmd.u3.ip6)),
554 NIP6(*((struct in6_addr *)ct->tuplehash[dir] 554 NIP6(*((struct in6_addr *)ct->tuplehash[dir]
555 .tuple.src.u3.ip6))); 555 .tuple.src.u3.ip6)));
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 3531d142f693..617599aeeead 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -821,7 +821,7 @@ module_exit(fini);
821 821
822/* Some modules need us, but don't depend directly on any symbol. 822/* Some modules need us, but don't depend directly on any symbol.
823 They should call this. */ 823 They should call this. */
824void need_nf_conntrack(void) 824void need_conntrack(void)
825{ 825{
826} 826}
827 827
@@ -841,7 +841,7 @@ EXPORT_SYMBOL(nf_conntrack_protocol_unregister);
841EXPORT_SYMBOL(nf_ct_invert_tuplepr); 841EXPORT_SYMBOL(nf_ct_invert_tuplepr);
842EXPORT_SYMBOL(nf_conntrack_alter_reply); 842EXPORT_SYMBOL(nf_conntrack_alter_reply);
843EXPORT_SYMBOL(nf_conntrack_destroyed); 843EXPORT_SYMBOL(nf_conntrack_destroyed);
844EXPORT_SYMBOL(need_nf_conntrack); 844EXPORT_SYMBOL(need_conntrack);
845EXPORT_SYMBOL(nf_conntrack_helper_register); 845EXPORT_SYMBOL(nf_conntrack_helper_register);
846EXPORT_SYMBOL(nf_conntrack_helper_unregister); 846EXPORT_SYMBOL(nf_conntrack_helper_unregister);
847EXPORT_SYMBOL(nf_ct_iterate_cleanup); 847EXPORT_SYMBOL(nf_ct_iterate_cleanup);
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
index 95fdf04f1d88..f6063e8f0050 100644
--- a/net/netfilter/nfnetlink.c
+++ b/net/netfilter/nfnetlink.c
@@ -212,7 +212,7 @@ int nfnetlink_unicast(struct sk_buff *skb, u_int32_t pid, int flags)
212} 212}
213 213
214/* Process one complete nfnetlink message. */ 214/* Process one complete nfnetlink message. */
215static inline int nfnetlink_rcv_msg(struct sk_buff *skb, 215static int nfnetlink_rcv_msg(struct sk_buff *skb,
216 struct nlmsghdr *nlh, int *errp) 216 struct nlmsghdr *nlh, int *errp)
217{ 217{
218 struct nfnl_callback *nc; 218 struct nfnl_callback *nc;
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
new file mode 100644
index 000000000000..d7817afc6b96
--- /dev/null
+++ b/net/netfilter/x_tables.c
@@ -0,0 +1,624 @@
1/*
2 * x_tables core - Backend for {ip,ip6,arp}_tables
3 *
4 * Copyright (C) 2006-2006 Harald Welte <laforge@netfilter.org>
5 *
6 * Based on existing ip_tables code which is
7 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
8 * Copyright (C) 2000-2005 Netfilter Core Team <coreteam@netfilter.org>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 *
14 */
15
16#include <linux/config.h>
17#include <linux/kernel.h>
18#include <linux/socket.h>
19#include <linux/net.h>
20#include <linux/proc_fs.h>
21#include <linux/seq_file.h>
22#include <linux/string.h>
23#include <linux/vmalloc.h>
24
25#include <linux/netfilter/x_tables.h>
26#include <linux/netfilter_arp.h>
27
28MODULE_LICENSE("GPL");
29MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
30MODULE_DESCRIPTION("[ip,ip6,arp]_tables backend module");
31
32#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
33
34struct xt_af {
35 struct semaphore mutex;
36 struct list_head match;
37 struct list_head target;
38 struct list_head tables;
39};
40
41static struct xt_af *xt;
42
43#ifdef DEBUG_IP_FIREWALL_USER
44#define duprintf(format, args...) printk(format , ## args)
45#else
46#define duprintf(format, args...)
47#endif
48
49enum {
50 TABLE,
51 TARGET,
52 MATCH,
53};
54
55/* Registration hooks for targets. */
56int
57xt_register_target(int af, struct xt_target *target)
58{
59 int ret;
60
61 ret = down_interruptible(&xt[af].mutex);
62 if (ret != 0)
63 return ret;
64 list_add(&target->list, &xt[af].target);
65 up(&xt[af].mutex);
66 return ret;
67}
68EXPORT_SYMBOL(xt_register_target);
69
70void
71xt_unregister_target(int af, struct xt_target *target)
72{
73 down(&xt[af].mutex);
74 LIST_DELETE(&xt[af].target, target);
75 up(&xt[af].mutex);
76}
77EXPORT_SYMBOL(xt_unregister_target);
78
79int
80xt_register_match(int af, struct xt_match *match)
81{
82 int ret;
83
84 ret = down_interruptible(&xt[af].mutex);
85 if (ret != 0)
86 return ret;
87
88 list_add(&match->list, &xt[af].match);
89 up(&xt[af].mutex);
90
91 return ret;
92}
93EXPORT_SYMBOL(xt_register_match);
94
95void
96xt_unregister_match(int af, struct xt_match *match)
97{
98 down(&xt[af].mutex);
99 LIST_DELETE(&xt[af].match, match);
100 up(&xt[af].mutex);
101}
102EXPORT_SYMBOL(xt_unregister_match);
103
104
105/*
106 * These are weird, but module loading must not be done with mutex
107 * held (since they will register), and we have to have a single
108 * function to use try_then_request_module().
109 */
110
111/* Find match, grabs ref. Returns ERR_PTR() on error. */
112struct xt_match *xt_find_match(int af, const char *name, u8 revision)
113{
114 struct xt_match *m;
115 int err = 0;
116
117 if (down_interruptible(&xt[af].mutex) != 0)
118 return ERR_PTR(-EINTR);
119
120 list_for_each_entry(m, &xt[af].match, list) {
121 if (strcmp(m->name, name) == 0) {
122 if (m->revision == revision) {
123 if (try_module_get(m->me)) {
124 up(&xt[af].mutex);
125 return m;
126 }
127 } else
128 err = -EPROTOTYPE; /* Found something. */
129 }
130 }
131 up(&xt[af].mutex);
132 return ERR_PTR(err);
133}
134EXPORT_SYMBOL(xt_find_match);
135
136/* Find target, grabs ref. Returns ERR_PTR() on error. */
137struct xt_target *xt_find_target(int af, const char *name, u8 revision)
138{
139 struct xt_target *t;
140 int err = 0;
141
142 if (down_interruptible(&xt[af].mutex) != 0)
143 return ERR_PTR(-EINTR);
144
145 list_for_each_entry(t, &xt[af].target, list) {
146 if (strcmp(t->name, name) == 0) {
147 if (t->revision == revision) {
148 if (try_module_get(t->me)) {
149 up(&xt[af].mutex);
150 return t;
151 }
152 } else
153 err = -EPROTOTYPE; /* Found something. */
154 }
155 }
156 up(&xt[af].mutex);
157 return ERR_PTR(err);
158}
159EXPORT_SYMBOL(xt_find_target);
160
161static const char *xt_prefix[NPROTO] = {
162 [AF_INET] = "ipt_%s",
163 [AF_INET6] = "ip6t_%s",
164 [NF_ARP] = "arpt_%s",
165};
166
167struct xt_target *xt_request_find_target(int af, const char *name, u8 revision)
168{
169 struct xt_target *target;
170
171 target = try_then_request_module(xt_find_target(af, name, revision),
172 xt_prefix[af], name);
173 if (IS_ERR(target) || !target)
174 return NULL;
175 return target;
176}
177EXPORT_SYMBOL_GPL(xt_request_find_target);
178
179static int match_revfn(int af, const char *name, u8 revision, int *bestp)
180{
181 struct xt_match *m;
182 int have_rev = 0;
183
184 list_for_each_entry(m, &xt[af].match, list) {
185 if (strcmp(m->name, name) == 0) {
186 if (m->revision > *bestp)
187 *bestp = m->revision;
188 if (m->revision == revision)
189 have_rev = 1;
190 }
191 }
192 return have_rev;
193}
194
195static int target_revfn(int af, const char *name, u8 revision, int *bestp)
196{
197 struct xt_target *t;
198 int have_rev = 0;
199
200 list_for_each_entry(t, &xt[af].target, list) {
201 if (strcmp(t->name, name) == 0) {
202 if (t->revision > *bestp)
203 *bestp = t->revision;
204 if (t->revision == revision)
205 have_rev = 1;
206 }
207 }
208 return have_rev;
209}
210
211/* Returns true or false (if no such extension at all) */
212int xt_find_revision(int af, const char *name, u8 revision, int target,
213 int *err)
214{
215 int have_rev, best = -1;
216
217 if (down_interruptible(&xt[af].mutex) != 0) {
218 *err = -EINTR;
219 return 1;
220 }
221 if (target == 1)
222 have_rev = target_revfn(af, name, revision, &best);
223 else
224 have_rev = match_revfn(af, name, revision, &best);
225 up(&xt[af].mutex);
226
227 /* Nothing at all? Return 0 to try loading module. */
228 if (best == -1) {
229 *err = -ENOENT;
230 return 0;
231 }
232
233 *err = best;
234 if (!have_rev)
235 *err = -EPROTONOSUPPORT;
236 return 1;
237}
238EXPORT_SYMBOL_GPL(xt_find_revision);
239
240struct xt_table_info *xt_alloc_table_info(unsigned int size)
241{
242 struct xt_table_info *newinfo;
243 int cpu;
244
245 /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */
246 if ((SMP_ALIGN(size) >> PAGE_SHIFT) + 2 > num_physpages)
247 return NULL;
248
249 newinfo = kzalloc(sizeof(struct xt_table_info), GFP_KERNEL);
250 if (!newinfo)
251 return NULL;
252
253 newinfo->size = size;
254
255 for_each_cpu(cpu) {
256 if (size <= PAGE_SIZE)
257 newinfo->entries[cpu] = kmalloc_node(size,
258 GFP_KERNEL,
259 cpu_to_node(cpu));
260 else
261 newinfo->entries[cpu] = vmalloc_node(size,
262 cpu_to_node(cpu));
263
264 if (newinfo->entries[cpu] == NULL) {
265 xt_free_table_info(newinfo);
266 return NULL;
267 }
268 }
269
270 return newinfo;
271}
272EXPORT_SYMBOL(xt_alloc_table_info);
273
274void xt_free_table_info(struct xt_table_info *info)
275{
276 int cpu;
277
278 for_each_cpu(cpu) {
279 if (info->size <= PAGE_SIZE)
280 kfree(info->entries[cpu]);
281 else
282 vfree(info->entries[cpu]);
283 }
284 kfree(info);
285}
286EXPORT_SYMBOL(xt_free_table_info);
287
288/* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */
289struct xt_table *xt_find_table_lock(int af, const char *name)
290{
291 struct xt_table *t;
292
293 if (down_interruptible(&xt[af].mutex) != 0)
294 return ERR_PTR(-EINTR);
295
296 list_for_each_entry(t, &xt[af].tables, list)
297 if (strcmp(t->name, name) == 0 && try_module_get(t->me))
298 return t;
299 up(&xt[af].mutex);
300 return NULL;
301}
302EXPORT_SYMBOL_GPL(xt_find_table_lock);
303
304void xt_table_unlock(struct xt_table *table)
305{
306 up(&xt[table->af].mutex);
307}
308EXPORT_SYMBOL_GPL(xt_table_unlock);
309
310
311struct xt_table_info *
312xt_replace_table(struct xt_table *table,
313 unsigned int num_counters,
314 struct xt_table_info *newinfo,
315 int *error)
316{
317 struct xt_table_info *oldinfo, *private;
318
319 /* Do the substitution. */
320 write_lock_bh(&table->lock);
321 private = table->private;
322 /* Check inside lock: is the old number correct? */
323 if (num_counters != private->number) {
324 duprintf("num_counters != table->private->number (%u/%u)\n",
325 num_counters, private->number);
326 write_unlock_bh(&table->lock);
327 *error = -EAGAIN;
328 return NULL;
329 }
330 oldinfo = private;
331 table->private = newinfo;
332 newinfo->initial_entries = oldinfo->initial_entries;
333 write_unlock_bh(&table->lock);
334
335 return oldinfo;
336}
337EXPORT_SYMBOL_GPL(xt_replace_table);
338
339int xt_register_table(struct xt_table *table,
340 struct xt_table_info *bootstrap,
341 struct xt_table_info *newinfo)
342{
343 int ret;
344 struct xt_table_info *private;
345
346 ret = down_interruptible(&xt[table->af].mutex);
347 if (ret != 0)
348 return ret;
349
350 /* Don't autoload: we'd eat our tail... */
351 if (list_named_find(&xt[table->af].tables, table->name)) {
352 ret = -EEXIST;
353 goto unlock;
354 }
355
356 /* Simplifies replace_table code. */
357 table->private = bootstrap;
358 if (!xt_replace_table(table, 0, newinfo, &ret))
359 goto unlock;
360
361 private = table->private;
362 duprintf("table->private->number = %u\n", private->number);
363
364 /* save number of initial entries */
365 private->initial_entries = private->number;
366
367 rwlock_init(&table->lock);
368 list_prepend(&xt[table->af].tables, table);
369
370 ret = 0;
371 unlock:
372 up(&xt[table->af].mutex);
373 return ret;
374}
375EXPORT_SYMBOL_GPL(xt_register_table);
376
377void *xt_unregister_table(struct xt_table *table)
378{
379 struct xt_table_info *private;
380
381 down(&xt[table->af].mutex);
382 private = table->private;
383 LIST_DELETE(&xt[table->af].tables, table);
384 up(&xt[table->af].mutex);
385
386 return private;
387}
388EXPORT_SYMBOL_GPL(xt_unregister_table);
389
390#ifdef CONFIG_PROC_FS
391static char *xt_proto_prefix[NPROTO] = {
392 [AF_INET] = "ip",
393 [AF_INET6] = "ip6",
394 [NF_ARP] = "arp",
395};
396
397static struct list_head *xt_get_idx(struct list_head *list, struct seq_file *seq, loff_t pos)
398{
399 struct list_head *head = list->next;
400
401 if (!head || list_empty(list))
402 return NULL;
403
404 while (pos && (head = head->next)) {
405 if (head == list)
406 return NULL;
407 pos--;
408 }
409 return pos ? NULL : head;
410}
411
412static struct list_head *type2list(u_int16_t af, u_int16_t type)
413{
414 struct list_head *list;
415
416 switch (type) {
417 case TARGET:
418 list = &xt[af].target;
419 break;
420 case MATCH:
421 list = &xt[af].match;
422 break;
423 case TABLE:
424 list = &xt[af].tables;
425 break;
426 default:
427 list = NULL;
428 break;
429 }
430
431 return list;
432}
433
434static void *xt_tgt_seq_start(struct seq_file *seq, loff_t *pos)
435{
436 struct proc_dir_entry *pde = (struct proc_dir_entry *) seq->private;
437 u_int16_t af = (unsigned long)pde->data & 0xffff;
438 u_int16_t type = (unsigned long)pde->data >> 16;
439 struct list_head *list;
440
441 if (af >= NPROTO)
442 return NULL;
443
444 list = type2list(af, type);
445 if (!list)
446 return NULL;
447
448 if (down_interruptible(&xt[af].mutex) != 0)
449 return NULL;
450
451 return xt_get_idx(list, seq, *pos);
452}
453
454static void *xt_tgt_seq_next(struct seq_file *seq, void *v, loff_t *pos)
455{
456 struct proc_dir_entry *pde = seq->private;
457 u_int16_t af = (unsigned long)pde->data & 0xffff;
458 u_int16_t type = (unsigned long)pde->data >> 16;
459 struct list_head *list;
460
461 if (af >= NPROTO)
462 return NULL;
463
464 list = type2list(af, type);
465 if (!list)
466 return NULL;
467
468 (*pos)++;
469 return xt_get_idx(list, seq, *pos);
470}
471
472static void xt_tgt_seq_stop(struct seq_file *seq, void *v)
473{
474 struct proc_dir_entry *pde = seq->private;
475 u_int16_t af = (unsigned long)pde->data & 0xffff;
476
477 up(&xt[af].mutex);
478}
479
480static int xt_name_seq_show(struct seq_file *seq, void *v)
481{
482 char *name = (char *)v + sizeof(struct list_head);
483
484 if (strlen(name))
485 return seq_printf(seq, "%s\n", name);
486 else
487 return 0;
488}
489
490static struct seq_operations xt_tgt_seq_ops = {
491 .start = xt_tgt_seq_start,
492 .next = xt_tgt_seq_next,
493 .stop = xt_tgt_seq_stop,
494 .show = xt_name_seq_show,
495};
496
497static int xt_tgt_open(struct inode *inode, struct file *file)
498{
499 int ret;
500
501 ret = seq_open(file, &xt_tgt_seq_ops);
502 if (!ret) {
503 struct seq_file *seq = file->private_data;
504 struct proc_dir_entry *pde = PDE(inode);
505
506 seq->private = pde;
507 }
508
509 return ret;
510}
511
512static struct file_operations xt_file_ops = {
513 .owner = THIS_MODULE,
514 .open = xt_tgt_open,
515 .read = seq_read,
516 .llseek = seq_lseek,
517 .release = seq_release,
518};
519
520#define FORMAT_TABLES "_tables_names"
521#define FORMAT_MATCHES "_tables_matches"
522#define FORMAT_TARGETS "_tables_targets"
523
524#endif /* CONFIG_PROC_FS */
525
526int xt_proto_init(int af)
527{
528#ifdef CONFIG_PROC_FS
529 char buf[XT_FUNCTION_MAXNAMELEN];
530 struct proc_dir_entry *proc;
531#endif
532
533 if (af >= NPROTO)
534 return -EINVAL;
535
536
537#ifdef CONFIG_PROC_FS
538 strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
539 strlcat(buf, FORMAT_TABLES, sizeof(buf));
540 proc = proc_net_fops_create(buf, 0440, &xt_file_ops);
541 if (!proc)
542 goto out;
543 proc->data = (void *) ((unsigned long) af | (TABLE << 16));
544
545
546 strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
547 strlcat(buf, FORMAT_MATCHES, sizeof(buf));
548 proc = proc_net_fops_create(buf, 0440, &xt_file_ops);
549 if (!proc)
550 goto out_remove_tables;
551 proc->data = (void *) ((unsigned long) af | (MATCH << 16));
552
553 strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
554 strlcat(buf, FORMAT_TARGETS, sizeof(buf));
555 proc = proc_net_fops_create(buf, 0440, &xt_file_ops);
556 if (!proc)
557 goto out_remove_matches;
558 proc->data = (void *) ((unsigned long) af | (TARGET << 16));
559#endif
560
561 return 0;
562
563#ifdef CONFIG_PROC_FS
564out_remove_matches:
565 strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
566 strlcat(buf, FORMAT_MATCHES, sizeof(buf));
567 proc_net_remove(buf);
568
569out_remove_tables:
570 strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
571 strlcat(buf, FORMAT_TABLES, sizeof(buf));
572 proc_net_remove(buf);
573out:
574 return -1;
575#endif
576}
577EXPORT_SYMBOL_GPL(xt_proto_init);
578
579void xt_proto_fini(int af)
580{
581#ifdef CONFIG_PROC_FS
582 char buf[XT_FUNCTION_MAXNAMELEN];
583
584 strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
585 strlcat(buf, FORMAT_TABLES, sizeof(buf));
586 proc_net_remove(buf);
587
588 strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
589 strlcat(buf, FORMAT_TARGETS, sizeof(buf));
590 proc_net_remove(buf);
591
592 strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
593 strlcat(buf, FORMAT_MATCHES, sizeof(buf));
594 proc_net_remove(buf);
595#endif /*CONFIG_PROC_FS*/
596}
597EXPORT_SYMBOL_GPL(xt_proto_fini);
598
599
600static int __init xt_init(void)
601{
602 int i;
603
604 xt = kmalloc(sizeof(struct xt_af) * NPROTO, GFP_KERNEL);
605 if (!xt)
606 return -ENOMEM;
607
608 for (i = 0; i < NPROTO; i++) {
609 init_MUTEX(&xt[i].mutex);
610 INIT_LIST_HEAD(&xt[i].target);
611 INIT_LIST_HEAD(&xt[i].match);
612 INIT_LIST_HEAD(&xt[i].tables);
613 }
614 return 0;
615}
616
617static void __exit xt_fini(void)
618{
619 kfree(xt);
620}
621
622module_init(xt_init);
623module_exit(xt_fini);
624
diff --git a/net/ipv4/netfilter/ipt_CLASSIFY.c b/net/netfilter/xt_CLASSIFY.c
index dab78d8bd494..78ee266a12ee 100644
--- a/net/ipv4/netfilter/ipt_CLASSIFY.c
+++ b/net/netfilter/xt_CLASSIFY.c
@@ -15,12 +15,13 @@
15#include <linux/ip.h> 15#include <linux/ip.h>
16#include <net/checksum.h> 16#include <net/checksum.h>
17 17
18#include <linux/netfilter_ipv4/ip_tables.h> 18#include <linux/netfilter/x_tables.h>
19#include <linux/netfilter_ipv4/ipt_CLASSIFY.h> 19#include <linux/netfilter/xt_CLASSIFY.h>
20 20
21MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 21MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
22MODULE_LICENSE("GPL"); 22MODULE_LICENSE("GPL");
23MODULE_DESCRIPTION("iptables qdisc classification target module"); 23MODULE_DESCRIPTION("iptables qdisc classification target module");
24MODULE_ALIAS("ipt_CLASSIFY");
24 25
25static unsigned int 26static unsigned int
26target(struct sk_buff **pskb, 27target(struct sk_buff **pskb,
@@ -30,25 +31,25 @@ target(struct sk_buff **pskb,
30 const void *targinfo, 31 const void *targinfo,
31 void *userinfo) 32 void *userinfo)
32{ 33{
33 const struct ipt_classify_target_info *clinfo = targinfo; 34 const struct xt_classify_target_info *clinfo = targinfo;
34 35
35 if((*pskb)->priority != clinfo->priority) 36 if ((*pskb)->priority != clinfo->priority)
36 (*pskb)->priority = clinfo->priority; 37 (*pskb)->priority = clinfo->priority;
37 38
38 return IPT_CONTINUE; 39 return XT_CONTINUE;
39} 40}
40 41
41static int 42static int
42checkentry(const char *tablename, 43checkentry(const char *tablename,
43 const struct ipt_entry *e, 44 const void *e,
44 void *targinfo, 45 void *targinfo,
45 unsigned int targinfosize, 46 unsigned int targinfosize,
46 unsigned int hook_mask) 47 unsigned int hook_mask)
47{ 48{
48 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_classify_target_info))){ 49 if (targinfosize != XT_ALIGN(sizeof(struct xt_classify_target_info))){
49 printk(KERN_ERR "CLASSIFY: invalid size (%u != %Zu).\n", 50 printk(KERN_ERR "CLASSIFY: invalid size (%u != %Zu).\n",
50 targinfosize, 51 targinfosize,
51 IPT_ALIGN(sizeof(struct ipt_classify_target_info))); 52 XT_ALIGN(sizeof(struct xt_classify_target_info)));
52 return 0; 53 return 0;
53 } 54 }
54 55
@@ -69,21 +70,39 @@ checkentry(const char *tablename,
69 return 1; 70 return 1;
70} 71}
71 72
72static struct ipt_target ipt_classify_reg = { 73static struct xt_target classify_reg = {
74 .name = "CLASSIFY",
75 .target = target,
76 .checkentry = checkentry,
77 .me = THIS_MODULE,
78};
79static struct xt_target classify6_reg = {
73 .name = "CLASSIFY", 80 .name = "CLASSIFY",
74 .target = target, 81 .target = target,
75 .checkentry = checkentry, 82 .checkentry = checkentry,
76 .me = THIS_MODULE, 83 .me = THIS_MODULE,
77}; 84};
78 85
86
79static int __init init(void) 87static int __init init(void)
80{ 88{
81 return ipt_register_target(&ipt_classify_reg); 89 int ret;
90
91 ret = xt_register_target(AF_INET, &classify_reg);
92 if (ret)
93 return ret;
94
95 ret = xt_register_target(AF_INET6, &classify6_reg);
96 if (ret)
97 xt_unregister_target(AF_INET, &classify_reg);
98
99 return ret;
82} 100}
83 101
84static void __exit fini(void) 102static void __exit fini(void)
85{ 103{
86 ipt_unregister_target(&ipt_classify_reg); 104 xt_unregister_target(AF_INET, &classify_reg);
105 xt_unregister_target(AF_INET6, &classify6_reg);
87} 106}
88 107
89module_init(init); 108module_init(init);
diff --git a/net/ipv4/netfilter/ipt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c
index 8acac5a40a92..22506e376be5 100644
--- a/net/ipv4/netfilter/ipt_CONNMARK.c
+++ b/net/netfilter/xt_CONNMARK.c
@@ -26,9 +26,10 @@
26MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>"); 26MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
27MODULE_DESCRIPTION("IP tables CONNMARK matching module"); 27MODULE_DESCRIPTION("IP tables CONNMARK matching module");
28MODULE_LICENSE("GPL"); 28MODULE_LICENSE("GPL");
29MODULE_ALIAS("ipt_CONNMARK");
29 30
30#include <linux/netfilter_ipv4/ip_tables.h> 31#include <linux/netfilter/x_tables.h>
31#include <linux/netfilter_ipv4/ipt_CONNMARK.h> 32#include <linux/netfilter/xt_CONNMARK.h>
32#include <net/netfilter/nf_conntrack_compat.h> 33#include <net/netfilter/nf_conntrack_compat.h>
33 34
34static unsigned int 35static unsigned int
@@ -39,7 +40,7 @@ target(struct sk_buff **pskb,
39 const void *targinfo, 40 const void *targinfo,
40 void *userinfo) 41 void *userinfo)
41{ 42{
42 const struct ipt_connmark_target_info *markinfo = targinfo; 43 const struct xt_connmark_target_info *markinfo = targinfo;
43 u_int32_t diff; 44 u_int32_t diff;
44 u_int32_t nfmark; 45 u_int32_t nfmark;
45 u_int32_t newmark; 46 u_int32_t newmark;
@@ -48,17 +49,17 @@ target(struct sk_buff **pskb,
48 49
49 if (ctmark) { 50 if (ctmark) {
50 switch(markinfo->mode) { 51 switch(markinfo->mode) {
51 case IPT_CONNMARK_SET: 52 case XT_CONNMARK_SET:
52 newmark = (*ctmark & ~markinfo->mask) | markinfo->mark; 53 newmark = (*ctmark & ~markinfo->mask) | markinfo->mark;
53 if (newmark != *ctmark) 54 if (newmark != *ctmark)
54 *ctmark = newmark; 55 *ctmark = newmark;
55 break; 56 break;
56 case IPT_CONNMARK_SAVE: 57 case XT_CONNMARK_SAVE:
57 newmark = (*ctmark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask); 58 newmark = (*ctmark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask);
58 if (*ctmark != newmark) 59 if (*ctmark != newmark)
59 *ctmark = newmark; 60 *ctmark = newmark;
60 break; 61 break;
61 case IPT_CONNMARK_RESTORE: 62 case XT_CONNMARK_RESTORE:
62 nfmark = (*pskb)->nfmark; 63 nfmark = (*pskb)->nfmark;
63 diff = (*ctmark ^ nfmark) & markinfo->mask; 64 diff = (*ctmark ^ nfmark) & markinfo->mask;
64 if (diff != 0) 65 if (diff != 0)
@@ -67,25 +68,25 @@ target(struct sk_buff **pskb,
67 } 68 }
68 } 69 }
69 70
70 return IPT_CONTINUE; 71 return XT_CONTINUE;
71} 72}
72 73
73static int 74static int
74checkentry(const char *tablename, 75checkentry(const char *tablename,
75 const struct ipt_entry *e, 76 const void *entry,
76 void *targinfo, 77 void *targinfo,
77 unsigned int targinfosize, 78 unsigned int targinfosize,
78 unsigned int hook_mask) 79 unsigned int hook_mask)
79{ 80{
80 struct ipt_connmark_target_info *matchinfo = targinfo; 81 struct xt_connmark_target_info *matchinfo = targinfo;
81 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) { 82 if (targinfosize != XT_ALIGN(sizeof(struct xt_connmark_target_info))) {
82 printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n", 83 printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n",
83 targinfosize, 84 targinfosize,
84 IPT_ALIGN(sizeof(struct ipt_connmark_target_info))); 85 XT_ALIGN(sizeof(struct xt_connmark_target_info)));
85 return 0; 86 return 0;
86 } 87 }
87 88
88 if (matchinfo->mode == IPT_CONNMARK_RESTORE) { 89 if (matchinfo->mode == XT_CONNMARK_RESTORE) {
89 if (strcmp(tablename, "mangle") != 0) { 90 if (strcmp(tablename, "mangle") != 0) {
90 printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename); 91 printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename);
91 return 0; 92 return 0;
@@ -100,7 +101,13 @@ checkentry(const char *tablename,
100 return 1; 101 return 1;
101} 102}
102 103
103static struct ipt_target ipt_connmark_reg = { 104static struct xt_target connmark_reg = {
105 .name = "CONNMARK",
106 .target = &target,
107 .checkentry = &checkentry,
108 .me = THIS_MODULE
109};
110static struct xt_target connmark6_reg = {
104 .name = "CONNMARK", 111 .name = "CONNMARK",
105 .target = &target, 112 .target = &target,
106 .checkentry = &checkentry, 113 .checkentry = &checkentry,
@@ -109,13 +116,25 @@ static struct ipt_target ipt_connmark_reg = {
109 116
110static int __init init(void) 117static int __init init(void)
111{ 118{
112 need_ip_conntrack(); 119 int ret;
113 return ipt_register_target(&ipt_connmark_reg); 120
121 need_conntrack();
122
123 ret = xt_register_target(AF_INET, &connmark_reg);
124 if (ret)
125 return ret;
126
127 ret = xt_register_target(AF_INET6, &connmark6_reg);
128 if (ret)
129 xt_unregister_target(AF_INET, &connmark_reg);
130
131 return ret;
114} 132}
115 133
116static void __exit fini(void) 134static void __exit fini(void)
117{ 135{
118 ipt_unregister_target(&ipt_connmark_reg); 136 xt_unregister_target(AF_INET, &connmark_reg);
137 xt_unregister_target(AF_INET6, &connmark6_reg);
119} 138}
120 139
121module_init(init); 140module_init(init);
diff --git a/net/ipv4/netfilter/ipt_MARK.c b/net/netfilter/xt_MARK.c
index 52b4f2c296bf..0c11ee9550f3 100644
--- a/net/ipv4/netfilter/ipt_MARK.c
+++ b/net/netfilter/xt_MARK.c
@@ -12,12 +12,14 @@
12#include <linux/ip.h> 12#include <linux/ip.h>
13#include <net/checksum.h> 13#include <net/checksum.h>
14 14
15#include <linux/netfilter_ipv4/ip_tables.h> 15#include <linux/netfilter/x_tables.h>
16#include <linux/netfilter_ipv4/ipt_MARK.h> 16#include <linux/netfilter/xt_MARK.h>
17 17
18MODULE_LICENSE("GPL"); 18MODULE_LICENSE("GPL");
19MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); 19MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
20MODULE_DESCRIPTION("iptables MARK modification module"); 20MODULE_DESCRIPTION("ip[6]tables MARK modification module");
21MODULE_ALIAS("ipt_MARK");
22MODULE_ALIAS("ip6t_MARK");
21 23
22static unsigned int 24static unsigned int
23target_v0(struct sk_buff **pskb, 25target_v0(struct sk_buff **pskb,
@@ -27,12 +29,12 @@ target_v0(struct sk_buff **pskb,
27 const void *targinfo, 29 const void *targinfo,
28 void *userinfo) 30 void *userinfo)
29{ 31{
30 const struct ipt_mark_target_info *markinfo = targinfo; 32 const struct xt_mark_target_info *markinfo = targinfo;
31 33
32 if((*pskb)->nfmark != markinfo->mark) 34 if((*pskb)->nfmark != markinfo->mark)
33 (*pskb)->nfmark = markinfo->mark; 35 (*pskb)->nfmark = markinfo->mark;
34 36
35 return IPT_CONTINUE; 37 return XT_CONTINUE;
36} 38}
37 39
38static unsigned int 40static unsigned int
@@ -43,19 +45,19 @@ target_v1(struct sk_buff **pskb,
43 const void *targinfo, 45 const void *targinfo,
44 void *userinfo) 46 void *userinfo)
45{ 47{
46 const struct ipt_mark_target_info_v1 *markinfo = targinfo; 48 const struct xt_mark_target_info_v1 *markinfo = targinfo;
47 int mark = 0; 49 int mark = 0;
48 50
49 switch (markinfo->mode) { 51 switch (markinfo->mode) {
50 case IPT_MARK_SET: 52 case XT_MARK_SET:
51 mark = markinfo->mark; 53 mark = markinfo->mark;
52 break; 54 break;
53 55
54 case IPT_MARK_AND: 56 case XT_MARK_AND:
55 mark = (*pskb)->nfmark & markinfo->mark; 57 mark = (*pskb)->nfmark & markinfo->mark;
56 break; 58 break;
57 59
58 case IPT_MARK_OR: 60 case XT_MARK_OR:
59 mark = (*pskb)->nfmark | markinfo->mark; 61 mark = (*pskb)->nfmark | markinfo->mark;
60 break; 62 break;
61 } 63 }
@@ -63,23 +65,23 @@ target_v1(struct sk_buff **pskb,
63 if((*pskb)->nfmark != mark) 65 if((*pskb)->nfmark != mark)
64 (*pskb)->nfmark = mark; 66 (*pskb)->nfmark = mark;
65 67
66 return IPT_CONTINUE; 68 return XT_CONTINUE;
67} 69}
68 70
69 71
70static int 72static int
71checkentry_v0(const char *tablename, 73checkentry_v0(const char *tablename,
72 const struct ipt_entry *e, 74 const void *entry,
73 void *targinfo, 75 void *targinfo,
74 unsigned int targinfosize, 76 unsigned int targinfosize,
75 unsigned int hook_mask) 77 unsigned int hook_mask)
76{ 78{
77 struct ipt_mark_target_info *markinfo = targinfo; 79 struct xt_mark_target_info *markinfo = targinfo;
78 80
79 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_mark_target_info))) { 81 if (targinfosize != XT_ALIGN(sizeof(struct xt_mark_target_info))) {
80 printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n", 82 printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n",
81 targinfosize, 83 targinfosize,
82 IPT_ALIGN(sizeof(struct ipt_mark_target_info))); 84 XT_ALIGN(sizeof(struct xt_mark_target_info)));
83 return 0; 85 return 0;
84 } 86 }
85 87
@@ -98,17 +100,17 @@ checkentry_v0(const char *tablename,
98 100
99static int 101static int
100checkentry_v1(const char *tablename, 102checkentry_v1(const char *tablename,
101 const struct ipt_entry *e, 103 const void *entry,
102 void *targinfo, 104 void *targinfo,
103 unsigned int targinfosize, 105 unsigned int targinfosize,
104 unsigned int hook_mask) 106 unsigned int hook_mask)
105{ 107{
106 struct ipt_mark_target_info_v1 *markinfo = targinfo; 108 struct xt_mark_target_info_v1 *markinfo = targinfo;
107 109
108 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_mark_target_info_v1))){ 110 if (targinfosize != XT_ALIGN(sizeof(struct xt_mark_target_info_v1))){
109 printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n", 111 printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n",
110 targinfosize, 112 targinfosize,
111 IPT_ALIGN(sizeof(struct ipt_mark_target_info_v1))); 113 XT_ALIGN(sizeof(struct xt_mark_target_info_v1)));
112 return 0; 114 return 0;
113 } 115 }
114 116
@@ -117,9 +119,9 @@ checkentry_v1(const char *tablename,
117 return 0; 119 return 0;
118 } 120 }
119 121
120 if (markinfo->mode != IPT_MARK_SET 122 if (markinfo->mode != XT_MARK_SET
121 && markinfo->mode != IPT_MARK_AND 123 && markinfo->mode != XT_MARK_AND
122 && markinfo->mode != IPT_MARK_OR) { 124 && markinfo->mode != XT_MARK_OR) {
123 printk(KERN_WARNING "MARK: unknown mode %u\n", 125 printk(KERN_WARNING "MARK: unknown mode %u\n",
124 markinfo->mode); 126 markinfo->mode);
125 return 0; 127 return 0;
@@ -133,7 +135,7 @@ checkentry_v1(const char *tablename,
133 return 1; 135 return 1;
134} 136}
135 137
136static struct ipt_target ipt_mark_reg_v0 = { 138static struct xt_target ipt_mark_reg_v0 = {
137 .name = "MARK", 139 .name = "MARK",
138 .target = target_v0, 140 .target = target_v0,
139 .checkentry = checkentry_v0, 141 .checkentry = checkentry_v0,
@@ -141,7 +143,7 @@ static struct ipt_target ipt_mark_reg_v0 = {
141 .revision = 0, 143 .revision = 0,
142}; 144};
143 145
144static struct ipt_target ipt_mark_reg_v1 = { 146static struct xt_target ipt_mark_reg_v1 = {
145 .name = "MARK", 147 .name = "MARK",
146 .target = target_v1, 148 .target = target_v1,
147 .checkentry = checkentry_v1, 149 .checkentry = checkentry_v1,
@@ -149,23 +151,40 @@ static struct ipt_target ipt_mark_reg_v1 = {
149 .revision = 1, 151 .revision = 1,
150}; 152};
151 153
154static struct xt_target ip6t_mark_reg_v0 = {
155 .name = "MARK",
156 .target = target_v0,
157 .checkentry = checkentry_v0,
158 .me = THIS_MODULE,
159 .revision = 0,
160};
161
152static int __init init(void) 162static int __init init(void)
153{ 163{
154 int err; 164 int err;
155 165
156 err = ipt_register_target(&ipt_mark_reg_v0); 166 err = xt_register_target(AF_INET, &ipt_mark_reg_v0);
157 if (!err) { 167 if (err)
158 err = ipt_register_target(&ipt_mark_reg_v1); 168 return err;
159 if (err) 169
160 ipt_unregister_target(&ipt_mark_reg_v0); 170 err = xt_register_target(AF_INET, &ipt_mark_reg_v1);
171 if (err)
172 xt_unregister_target(AF_INET, &ipt_mark_reg_v0);
173
174 err = xt_register_target(AF_INET6, &ip6t_mark_reg_v0);
175 if (err) {
176 xt_unregister_target(AF_INET, &ipt_mark_reg_v0);
177 xt_unregister_target(AF_INET, &ipt_mark_reg_v1);
161 } 178 }
179
162 return err; 180 return err;
163} 181}
164 182
165static void __exit fini(void) 183static void __exit fini(void)
166{ 184{
167 ipt_unregister_target(&ipt_mark_reg_v0); 185 xt_unregister_target(AF_INET, &ipt_mark_reg_v0);
168 ipt_unregister_target(&ipt_mark_reg_v1); 186 xt_unregister_target(AF_INET, &ipt_mark_reg_v1);
187 xt_unregister_target(AF_INET6, &ip6t_mark_reg_v0);
169} 188}
170 189
171module_init(init); 190module_init(init);
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
new file mode 100644
index 000000000000..8b76b6f8d1e4
--- /dev/null
+++ b/net/netfilter/xt_NFQUEUE.c
@@ -0,0 +1,107 @@
1/* iptables module for using new netfilter netlink queue
2 *
3 * (C) 2005 by Harald Welte <laforge@netfilter.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 */
10
11#include <linux/module.h>
12#include <linux/skbuff.h>
13
14#include <linux/netfilter.h>
15#include <linux/netfilter_arp.h>
16#include <linux/netfilter/x_tables.h>
17#include <linux/netfilter/xt_NFQUEUE.h>
18
19MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
20MODULE_DESCRIPTION("[ip,ip6,arp]_tables NFQUEUE target");
21MODULE_LICENSE("GPL");
22MODULE_ALIAS("ipt_NFQUEUE");
23MODULE_ALIAS("ip6t_NFQUEUE");
24MODULE_ALIAS("arpt_NFQUEUE");
25
26static unsigned int
27target(struct sk_buff **pskb,
28 const struct net_device *in,
29 const struct net_device *out,
30 unsigned int hooknum,
31 const void *targinfo,
32 void *userinfo)
33{
34 const struct xt_NFQ_info *tinfo = targinfo;
35
36 return NF_QUEUE_NR(tinfo->queuenum);
37}
38
39static int
40checkentry(const char *tablename,
41 const void *entry,
42 void *targinfo,
43 unsigned int targinfosize,
44 unsigned int hook_mask)
45{
46 if (targinfosize != XT_ALIGN(sizeof(struct xt_NFQ_info))) {
47 printk(KERN_WARNING "NFQUEUE: targinfosize %u != %Zu\n",
48 targinfosize,
49 XT_ALIGN(sizeof(struct xt_NFQ_info)));
50 return 0;
51 }
52
53 return 1;
54}
55
56static struct xt_target ipt_NFQ_reg = {
57 .name = "NFQUEUE",
58 .target = target,
59 .checkentry = checkentry,
60 .me = THIS_MODULE,
61};
62
63static struct xt_target ip6t_NFQ_reg = {
64 .name = "NFQUEUE",
65 .target = target,
66 .checkentry = checkentry,
67 .me = THIS_MODULE,
68};
69
70static struct xt_target arpt_NFQ_reg = {
71 .name = "NFQUEUE",
72 .target = target,
73 .checkentry = checkentry,
74 .me = THIS_MODULE,
75};
76
77static int __init init(void)
78{
79 int ret;
80 ret = xt_register_target(AF_INET, &ipt_NFQ_reg);
81 if (ret)
82 return ret;
83 ret = xt_register_target(AF_INET6, &ip6t_NFQ_reg);
84 if (ret)
85 goto out_ip;
86 ret = xt_register_target(NF_ARP, &arpt_NFQ_reg);
87 if (ret)
88 goto out_ip6;
89
90 return ret;
91out_ip6:
92 xt_unregister_target(AF_INET6, &ip6t_NFQ_reg);
93out_ip:
94 xt_unregister_target(AF_INET, &ipt_NFQ_reg);
95
96 return ret;
97}
98
99static void __exit fini(void)
100{
101 xt_unregister_target(NF_ARP, &arpt_NFQ_reg);
102 xt_unregister_target(AF_INET6, &ip6t_NFQ_reg);
103 xt_unregister_target(AF_INET, &ipt_NFQ_reg);
104}
105
106module_init(init);
107module_exit(fini);
diff --git a/net/ipv4/netfilter/ipt_NOTRACK.c b/net/netfilter/xt_NOTRACK.c
index e3c69d072c6e..24d477afa939 100644
--- a/net/ipv4/netfilter/ipt_NOTRACK.c
+++ b/net/netfilter/xt_NOTRACK.c
@@ -4,9 +4,12 @@
4#include <linux/module.h> 4#include <linux/module.h>
5#include <linux/skbuff.h> 5#include <linux/skbuff.h>
6 6
7#include <linux/netfilter_ipv4/ip_tables.h> 7#include <linux/netfilter/x_tables.h>
8#include <net/netfilter/nf_conntrack_compat.h> 8#include <net/netfilter/nf_conntrack_compat.h>
9 9
10MODULE_LICENSE("GPL");
11MODULE_ALIAS("ipt_NOTRACK");
12
10static unsigned int 13static unsigned int
11target(struct sk_buff **pskb, 14target(struct sk_buff **pskb,
12 const struct net_device *in, 15 const struct net_device *in,
@@ -17,7 +20,7 @@ target(struct sk_buff **pskb,
17{ 20{
18 /* Previously seen (loopback)? Ignore. */ 21 /* Previously seen (loopback)? Ignore. */
19 if ((*pskb)->nfct != NULL) 22 if ((*pskb)->nfct != NULL)
20 return IPT_CONTINUE; 23 return XT_CONTINUE;
21 24
22 /* Attach fake conntrack entry. 25 /* Attach fake conntrack entry.
23 If there is a real ct entry correspondig to this packet, 26 If there is a real ct entry correspondig to this packet,
@@ -27,12 +30,12 @@ target(struct sk_buff **pskb,
27 (*pskb)->nfctinfo = IP_CT_NEW; 30 (*pskb)->nfctinfo = IP_CT_NEW;
28 nf_conntrack_get((*pskb)->nfct); 31 nf_conntrack_get((*pskb)->nfct);
29 32
30 return IPT_CONTINUE; 33 return XT_CONTINUE;
31} 34}
32 35
33static int 36static int
34checkentry(const char *tablename, 37checkentry(const char *tablename,
35 const struct ipt_entry *e, 38 const void *entry,
36 void *targinfo, 39 void *targinfo,
37 unsigned int targinfosize, 40 unsigned int targinfosize,
38 unsigned int hook_mask) 41 unsigned int hook_mask)
@@ -51,26 +54,39 @@ checkentry(const char *tablename,
51 return 1; 54 return 1;
52} 55}
53 56
54static struct ipt_target ipt_notrack_reg = { 57static struct xt_target notrack_reg = {
55 .name = "NOTRACK", 58 .name = "NOTRACK",
56 .target = target, 59 .target = target,
57 .checkentry = checkentry, 60 .checkentry = checkentry,
58 .me = THIS_MODULE 61 .me = THIS_MODULE,
62};
63static struct xt_target notrack6_reg = {
64 .name = "NOTRACK",
65 .target = target,
66 .checkentry = checkentry,
67 .me = THIS_MODULE,
59}; 68};
60 69
61static int __init init(void) 70static int __init init(void)
62{ 71{
63 if (ipt_register_target(&ipt_notrack_reg)) 72 int ret;
64 return -EINVAL; 73
74 ret = xt_register_target(AF_INET, &notrack_reg);
75 if (ret)
76 return ret;
65 77
66 return 0; 78 ret = xt_register_target(AF_INET6, &notrack6_reg);
79 if (ret)
80 xt_unregister_target(AF_INET, &notrack_reg);
81
82 return ret;
67} 83}
68 84
69static void __exit fini(void) 85static void __exit fini(void)
70{ 86{
71 ipt_unregister_target(&ipt_notrack_reg); 87 xt_unregister_target(AF_INET6, &notrack6_reg);
88 xt_unregister_target(AF_INET, &notrack_reg);
72} 89}
73 90
74module_init(init); 91module_init(init);
75module_exit(fini); 92module_exit(fini);
76MODULE_LICENSE("GPL");
diff --git a/net/ipv4/netfilter/ipt_comment.c b/net/netfilter/xt_comment.c
index 6b76a1ea5245..4ba6fd65c6e9 100644
--- a/net/ipv4/netfilter/ipt_comment.c
+++ b/net/netfilter/xt_comment.c
@@ -6,12 +6,14 @@
6 6
7#include <linux/module.h> 7#include <linux/module.h>
8#include <linux/skbuff.h> 8#include <linux/skbuff.h>
9#include <linux/netfilter_ipv4/ip_tables.h> 9#include <linux/netfilter/x_tables.h>
10#include <linux/netfilter_ipv4/ipt_comment.h> 10#include <linux/netfilter/xt_comment.h>
11 11
12MODULE_AUTHOR("Brad Fisher <brad@info-link.net>"); 12MODULE_AUTHOR("Brad Fisher <brad@info-link.net>");
13MODULE_DESCRIPTION("iptables comment match module"); 13MODULE_DESCRIPTION("iptables comment match module");
14MODULE_LICENSE("GPL"); 14MODULE_LICENSE("GPL");
15MODULE_ALIAS("ipt_comment");
16MODULE_ALIAS("ip6t_comment");
15 17
16static int 18static int
17match(const struct sk_buff *skb, 19match(const struct sk_buff *skb,
@@ -19,6 +21,7 @@ match(const struct sk_buff *skb,
19 const struct net_device *out, 21 const struct net_device *out,
20 const void *matchinfo, 22 const void *matchinfo,
21 int offset, 23 int offset,
24 unsigned int protooff,
22 int *hotdrop) 25 int *hotdrop)
23{ 26{
24 /* We always match */ 27 /* We always match */
@@ -27,18 +30,25 @@ match(const struct sk_buff *skb,
27 30
28static int 31static int
29checkentry(const char *tablename, 32checkentry(const char *tablename,
30 const struct ipt_ip *ip, 33 const void *ip,
31 void *matchinfo, 34 void *matchinfo,
32 unsigned int matchsize, 35 unsigned int matchsize,
33 unsigned int hook_mask) 36 unsigned int hook_mask)
34{ 37{
35 /* Check the size */ 38 /* Check the size */
36 if (matchsize != IPT_ALIGN(sizeof(struct ipt_comment_info))) 39 if (matchsize != XT_ALIGN(sizeof(struct xt_comment_info)))
37 return 0; 40 return 0;
38 return 1; 41 return 1;
39} 42}
40 43
41static struct ipt_match comment_match = { 44static struct xt_match comment_match = {
45 .name = "comment",
46 .match = match,
47 .checkentry = checkentry,
48 .me = THIS_MODULE
49};
50
51static struct xt_match comment6_match = {
42 .name = "comment", 52 .name = "comment",
43 .match = match, 53 .match = match,
44 .checkentry = checkentry, 54 .checkentry = checkentry,
@@ -47,12 +57,23 @@ static struct ipt_match comment_match = {
47 57
48static int __init init(void) 58static int __init init(void)
49{ 59{
50 return ipt_register_match(&comment_match); 60 int ret;
61
62 ret = xt_register_match(AF_INET, &comment_match);
63 if (ret)
64 return ret;
65
66 ret = xt_register_match(AF_INET6, &comment6_match);
67 if (ret)
68 xt_unregister_match(AF_INET, &comment_match);
69
70 return ret;
51} 71}
52 72
53static void __exit fini(void) 73static void __exit fini(void)
54{ 74{
55 ipt_unregister_match(&comment_match); 75 xt_unregister_match(AF_INET, &comment_match);
76 xt_unregister_match(AF_INET6, &comment6_match);
56} 77}
57 78
58module_init(init); 79module_init(init);
diff --git a/net/ipv4/netfilter/ipt_connbytes.c b/net/netfilter/xt_connbytes.c
index d68a048b7176..150d2a4b0f71 100644
--- a/net/ipv4/netfilter/ipt_connbytes.c
+++ b/net/netfilter/xt_connbytes.c
@@ -6,13 +6,15 @@
6 * - add functionality to match number of packets 6 * - add functionality to match number of packets
7 * - add functionality to match average packet size 7 * - add functionality to match average packet size
8 * - add support to match directions seperately 8 * - add support to match directions seperately
9 * 2005-10-16 Harald Welte <laforge@netfilter.org>
10 * - Port to x_tables
9 * 11 *
10 */ 12 */
11#include <linux/module.h> 13#include <linux/module.h>
12#include <linux/skbuff.h> 14#include <linux/skbuff.h>
13#include <net/netfilter/nf_conntrack_compat.h> 15#include <net/netfilter/nf_conntrack_compat.h>
14#include <linux/netfilter_ipv4/ip_tables.h> 16#include <linux/netfilter/x_tables.h>
15#include <linux/netfilter_ipv4/ipt_connbytes.h> 17#include <linux/netfilter/xt_connbytes.h>
16 18
17#include <asm/div64.h> 19#include <asm/div64.h>
18#include <asm/bitops.h> 20#include <asm/bitops.h>
@@ -20,6 +22,7 @@
20MODULE_LICENSE("GPL"); 22MODULE_LICENSE("GPL");
21MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); 23MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
22MODULE_DESCRIPTION("iptables match for matching number of pkts/bytes per connection"); 24MODULE_DESCRIPTION("iptables match for matching number of pkts/bytes per connection");
25MODULE_ALIAS("ipt_connbytes");
23 26
24/* 64bit divisor, dividend and result. dynamic precision */ 27/* 64bit divisor, dividend and result. dynamic precision */
25static u_int64_t div64_64(u_int64_t dividend, u_int64_t divisor) 28static u_int64_t div64_64(u_int64_t dividend, u_int64_t divisor)
@@ -43,9 +46,10 @@ match(const struct sk_buff *skb,
43 const struct net_device *out, 46 const struct net_device *out,
44 const void *matchinfo, 47 const void *matchinfo,
45 int offset, 48 int offset,
49 unsigned int protoff,
46 int *hotdrop) 50 int *hotdrop)
47{ 51{
48 const struct ipt_connbytes_info *sinfo = matchinfo; 52 const struct xt_connbytes_info *sinfo = matchinfo;
49 u_int64_t what = 0; /* initialize to make gcc happy */ 53 u_int64_t what = 0; /* initialize to make gcc happy */
50 const struct ip_conntrack_counter *counters; 54 const struct ip_conntrack_counter *counters;
51 55
@@ -53,45 +57,45 @@ match(const struct sk_buff *skb,
53 return 0; /* no match */ 57 return 0; /* no match */
54 58
55 switch (sinfo->what) { 59 switch (sinfo->what) {
56 case IPT_CONNBYTES_PKTS: 60 case XT_CONNBYTES_PKTS:
57 switch (sinfo->direction) { 61 switch (sinfo->direction) {
58 case IPT_CONNBYTES_DIR_ORIGINAL: 62 case XT_CONNBYTES_DIR_ORIGINAL:
59 what = counters[IP_CT_DIR_ORIGINAL].packets; 63 what = counters[IP_CT_DIR_ORIGINAL].packets;
60 break; 64 break;
61 case IPT_CONNBYTES_DIR_REPLY: 65 case XT_CONNBYTES_DIR_REPLY:
62 what = counters[IP_CT_DIR_REPLY].packets; 66 what = counters[IP_CT_DIR_REPLY].packets;
63 break; 67 break;
64 case IPT_CONNBYTES_DIR_BOTH: 68 case XT_CONNBYTES_DIR_BOTH:
65 what = counters[IP_CT_DIR_ORIGINAL].packets; 69 what = counters[IP_CT_DIR_ORIGINAL].packets;
66 what += counters[IP_CT_DIR_REPLY].packets; 70 what += counters[IP_CT_DIR_REPLY].packets;
67 break; 71 break;
68 } 72 }
69 break; 73 break;
70 case IPT_CONNBYTES_BYTES: 74 case XT_CONNBYTES_BYTES:
71 switch (sinfo->direction) { 75 switch (sinfo->direction) {
72 case IPT_CONNBYTES_DIR_ORIGINAL: 76 case XT_CONNBYTES_DIR_ORIGINAL:
73 what = counters[IP_CT_DIR_ORIGINAL].bytes; 77 what = counters[IP_CT_DIR_ORIGINAL].bytes;
74 break; 78 break;
75 case IPT_CONNBYTES_DIR_REPLY: 79 case XT_CONNBYTES_DIR_REPLY:
76 what = counters[IP_CT_DIR_REPLY].bytes; 80 what = counters[IP_CT_DIR_REPLY].bytes;
77 break; 81 break;
78 case IPT_CONNBYTES_DIR_BOTH: 82 case XT_CONNBYTES_DIR_BOTH:
79 what = counters[IP_CT_DIR_ORIGINAL].bytes; 83 what = counters[IP_CT_DIR_ORIGINAL].bytes;
80 what += counters[IP_CT_DIR_REPLY].bytes; 84 what += counters[IP_CT_DIR_REPLY].bytes;
81 break; 85 break;
82 } 86 }
83 break; 87 break;
84 case IPT_CONNBYTES_AVGPKT: 88 case XT_CONNBYTES_AVGPKT:
85 switch (sinfo->direction) { 89 switch (sinfo->direction) {
86 case IPT_CONNBYTES_DIR_ORIGINAL: 90 case XT_CONNBYTES_DIR_ORIGINAL:
87 what = div64_64(counters[IP_CT_DIR_ORIGINAL].bytes, 91 what = div64_64(counters[IP_CT_DIR_ORIGINAL].bytes,
88 counters[IP_CT_DIR_ORIGINAL].packets); 92 counters[IP_CT_DIR_ORIGINAL].packets);
89 break; 93 break;
90 case IPT_CONNBYTES_DIR_REPLY: 94 case XT_CONNBYTES_DIR_REPLY:
91 what = div64_64(counters[IP_CT_DIR_REPLY].bytes, 95 what = div64_64(counters[IP_CT_DIR_REPLY].bytes,
92 counters[IP_CT_DIR_REPLY].packets); 96 counters[IP_CT_DIR_REPLY].packets);
93 break; 97 break;
94 case IPT_CONNBYTES_DIR_BOTH: 98 case XT_CONNBYTES_DIR_BOTH:
95 { 99 {
96 u_int64_t bytes; 100 u_int64_t bytes;
97 u_int64_t pkts; 101 u_int64_t pkts;
@@ -117,30 +121,36 @@ match(const struct sk_buff *skb,
117} 121}
118 122
119static int check(const char *tablename, 123static int check(const char *tablename,
120 const struct ipt_ip *ip, 124 const void *ip,
121 void *matchinfo, 125 void *matchinfo,
122 unsigned int matchsize, 126 unsigned int matchsize,
123 unsigned int hook_mask) 127 unsigned int hook_mask)
124{ 128{
125 const struct ipt_connbytes_info *sinfo = matchinfo; 129 const struct xt_connbytes_info *sinfo = matchinfo;
126 130
127 if (matchsize != IPT_ALIGN(sizeof(struct ipt_connbytes_info))) 131 if (matchsize != XT_ALIGN(sizeof(struct xt_connbytes_info)))
128 return 0; 132 return 0;
129 133
130 if (sinfo->what != IPT_CONNBYTES_PKTS && 134 if (sinfo->what != XT_CONNBYTES_PKTS &&
131 sinfo->what != IPT_CONNBYTES_BYTES && 135 sinfo->what != XT_CONNBYTES_BYTES &&
132 sinfo->what != IPT_CONNBYTES_AVGPKT) 136 sinfo->what != XT_CONNBYTES_AVGPKT)
133 return 0; 137 return 0;
134 138
135 if (sinfo->direction != IPT_CONNBYTES_DIR_ORIGINAL && 139 if (sinfo->direction != XT_CONNBYTES_DIR_ORIGINAL &&
136 sinfo->direction != IPT_CONNBYTES_DIR_REPLY && 140 sinfo->direction != XT_CONNBYTES_DIR_REPLY &&
137 sinfo->direction != IPT_CONNBYTES_DIR_BOTH) 141 sinfo->direction != XT_CONNBYTES_DIR_BOTH)
138 return 0; 142 return 0;
139 143
140 return 1; 144 return 1;
141} 145}
142 146
143static struct ipt_match state_match = { 147static struct xt_match connbytes_match = {
148 .name = "connbytes",
149 .match = &match,
150 .checkentry = &check,
151 .me = THIS_MODULE
152};
153static struct xt_match connbytes6_match = {
144 .name = "connbytes", 154 .name = "connbytes",
145 .match = &match, 155 .match = &match,
146 .checkentry = &check, 156 .checkentry = &check,
@@ -149,12 +159,21 @@ static struct ipt_match state_match = {
149 159
150static int __init init(void) 160static int __init init(void)
151{ 161{
152 return ipt_register_match(&state_match); 162 int ret;
163 ret = xt_register_match(AF_INET, &connbytes_match);
164 if (ret)
165 return ret;
166
167 ret = xt_register_match(AF_INET6, &connbytes6_match);
168 if (ret)
169 xt_unregister_match(AF_INET, &connbytes_match);
170 return ret;
153} 171}
154 172
155static void __exit fini(void) 173static void __exit fini(void)
156{ 174{
157 ipt_unregister_match(&state_match); 175 xt_unregister_match(AF_INET, &connbytes_match);
176 xt_unregister_match(AF_INET6, &connbytes6_match);
158} 177}
159 178
160module_init(init); 179module_init(init);
diff --git a/net/ipv4/netfilter/ipt_connmark.c b/net/netfilter/xt_connmark.c
index 5306ef293b92..d06e925032da 100644
--- a/net/ipv4/netfilter/ipt_connmark.c
+++ b/net/netfilter/xt_connmark.c
@@ -25,9 +25,10 @@
25MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>"); 25MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
26MODULE_DESCRIPTION("IP tables connmark match module"); 26MODULE_DESCRIPTION("IP tables connmark match module");
27MODULE_LICENSE("GPL"); 27MODULE_LICENSE("GPL");
28MODULE_ALIAS("ipt_connmark");
28 29
29#include <linux/netfilter_ipv4/ip_tables.h> 30#include <linux/netfilter/x_tables.h>
30#include <linux/netfilter_ipv4/ipt_connmark.h> 31#include <linux/netfilter/xt_connmark.h>
31#include <net/netfilter/nf_conntrack_compat.h> 32#include <net/netfilter/nf_conntrack_compat.h>
32 33
33static int 34static int
@@ -36,9 +37,10 @@ match(const struct sk_buff *skb,
36 const struct net_device *out, 37 const struct net_device *out,
37 const void *matchinfo, 38 const void *matchinfo,
38 int offset, 39 int offset,
40 unsigned int protoff,
39 int *hotdrop) 41 int *hotdrop)
40{ 42{
41 const struct ipt_connmark_info *info = matchinfo; 43 const struct xt_connmark_info *info = matchinfo;
42 u_int32_t ctinfo; 44 u_int32_t ctinfo;
43 const u_int32_t *ctmark = nf_ct_get_mark(skb, &ctinfo); 45 const u_int32_t *ctmark = nf_ct_get_mark(skb, &ctinfo);
44 if (!ctmark) 46 if (!ctmark)
@@ -49,14 +51,14 @@ match(const struct sk_buff *skb,
49 51
50static int 52static int
51checkentry(const char *tablename, 53checkentry(const char *tablename,
52 const struct ipt_ip *ip, 54 const void *ip,
53 void *matchinfo, 55 void *matchinfo,
54 unsigned int matchsize, 56 unsigned int matchsize,
55 unsigned int hook_mask) 57 unsigned int hook_mask)
56{ 58{
57 struct ipt_connmark_info *cm = 59 struct xt_connmark_info *cm =
58 (struct ipt_connmark_info *)matchinfo; 60 (struct xt_connmark_info *)matchinfo;
59 if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info))) 61 if (matchsize != XT_ALIGN(sizeof(struct xt_connmark_info)))
60 return 0; 62 return 0;
61 63
62 if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) { 64 if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) {
@@ -67,21 +69,40 @@ checkentry(const char *tablename,
67 return 1; 69 return 1;
68} 70}
69 71
70static struct ipt_match connmark_match = { 72static struct xt_match connmark_match = {
73 .name = "connmark",
74 .match = &match,
75 .checkentry = &checkentry,
76 .me = THIS_MODULE
77};
78static struct xt_match connmark6_match = {
71 .name = "connmark", 79 .name = "connmark",
72 .match = &match, 80 .match = &match,
73 .checkentry = &checkentry, 81 .checkentry = &checkentry,
74 .me = THIS_MODULE 82 .me = THIS_MODULE
75}; 83};
76 84
85
77static int __init init(void) 86static int __init init(void)
78{ 87{
79 return ipt_register_match(&connmark_match); 88 int ret;
89
90 need_conntrack();
91
92 ret = xt_register_match(AF_INET, &connmark_match);
93 if (ret)
94 return ret;
95
96 ret = xt_register_match(AF_INET6, &connmark6_match);
97 if (ret)
98 xt_unregister_match(AF_INET, &connmark_match);
99 return ret;
80} 100}
81 101
82static void __exit fini(void) 102static void __exit fini(void)
83{ 103{
84 ipt_unregister_match(&connmark_match); 104 xt_unregister_match(AF_INET6, &connmark6_match);
105 xt_unregister_match(AF_INET, &connmark_match);
85} 106}
86 107
87module_init(init); 108module_init(init);
diff --git a/net/ipv4/netfilter/ipt_conntrack.c b/net/netfilter/xt_conntrack.c
index c8d18705469b..ffdebc95eb95 100644
--- a/net/ipv4/netfilter/ipt_conntrack.c
+++ b/net/netfilter/xt_conntrack.c
@@ -18,12 +18,13 @@
18#include <net/netfilter/nf_conntrack.h> 18#include <net/netfilter/nf_conntrack.h>
19#endif 19#endif
20 20
21#include <linux/netfilter_ipv4/ip_tables.h> 21#include <linux/netfilter/x_tables.h>
22#include <linux/netfilter_ipv4/ipt_conntrack.h> 22#include <linux/netfilter/xt_conntrack.h>
23 23
24MODULE_LICENSE("GPL"); 24MODULE_LICENSE("GPL");
25MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); 25MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
26MODULE_DESCRIPTION("iptables connection tracking match module"); 26MODULE_DESCRIPTION("iptables connection tracking match module");
27MODULE_ALIAS("ipt_conntrack");
27 28
28#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE) 29#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
29 30
@@ -33,9 +34,10 @@ match(const struct sk_buff *skb,
33 const struct net_device *out, 34 const struct net_device *out,
34 const void *matchinfo, 35 const void *matchinfo,
35 int offset, 36 int offset,
37 unsigned int protoff,
36 int *hotdrop) 38 int *hotdrop)
37{ 39{
38 const struct ipt_conntrack_info *sinfo = matchinfo; 40 const struct xt_conntrack_info *sinfo = matchinfo;
39 struct ip_conntrack *ct; 41 struct ip_conntrack *ct;
40 enum ip_conntrack_info ctinfo; 42 enum ip_conntrack_info ctinfo;
41 unsigned int statebit; 43 unsigned int statebit;
@@ -45,58 +47,58 @@ match(const struct sk_buff *skb,
45#define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg)) 47#define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg))
46 48
47 if (ct == &ip_conntrack_untracked) 49 if (ct == &ip_conntrack_untracked)
48 statebit = IPT_CONNTRACK_STATE_UNTRACKED; 50 statebit = XT_CONNTRACK_STATE_UNTRACKED;
49 else if (ct) 51 else if (ct)
50 statebit = IPT_CONNTRACK_STATE_BIT(ctinfo); 52 statebit = XT_CONNTRACK_STATE_BIT(ctinfo);
51 else 53 else
52 statebit = IPT_CONNTRACK_STATE_INVALID; 54 statebit = XT_CONNTRACK_STATE_INVALID;
53 55
54 if(sinfo->flags & IPT_CONNTRACK_STATE) { 56 if(sinfo->flags & XT_CONNTRACK_STATE) {
55 if (ct) { 57 if (ct) {
56 if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip != 58 if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip !=
57 ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip) 59 ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip)
58 statebit |= IPT_CONNTRACK_STATE_SNAT; 60 statebit |= XT_CONNTRACK_STATE_SNAT;
59 61
60 if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip != 62 if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip !=
61 ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip) 63 ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip)
62 statebit |= IPT_CONNTRACK_STATE_DNAT; 64 statebit |= XT_CONNTRACK_STATE_DNAT;
63 } 65 }
64 66
65 if (FWINV((statebit & sinfo->statemask) == 0, IPT_CONNTRACK_STATE)) 67 if (FWINV((statebit & sinfo->statemask) == 0, XT_CONNTRACK_STATE))
66 return 0; 68 return 0;
67 } 69 }
68 70
69 if(sinfo->flags & IPT_CONNTRACK_PROTO) { 71 if(sinfo->flags & XT_CONNTRACK_PROTO) {
70 if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, IPT_CONNTRACK_PROTO)) 72 if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, XT_CONNTRACK_PROTO))
71 return 0; 73 return 0;
72 } 74 }
73 75
74 if(sinfo->flags & IPT_CONNTRACK_ORIGSRC) { 76 if(sinfo->flags & XT_CONNTRACK_ORIGSRC) {
75 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, IPT_CONNTRACK_ORIGSRC)) 77 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, XT_CONNTRACK_ORIGSRC))
76 return 0; 78 return 0;
77 } 79 }
78 80
79 if(sinfo->flags & IPT_CONNTRACK_ORIGDST) { 81 if(sinfo->flags & XT_CONNTRACK_ORIGDST) {
80 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, IPT_CONNTRACK_ORIGDST)) 82 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, XT_CONNTRACK_ORIGDST))
81 return 0; 83 return 0;
82 } 84 }
83 85
84 if(sinfo->flags & IPT_CONNTRACK_REPLSRC) { 86 if(sinfo->flags & XT_CONNTRACK_REPLSRC) {
85 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, IPT_CONNTRACK_REPLSRC)) 87 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, XT_CONNTRACK_REPLSRC))
86 return 0; 88 return 0;
87 } 89 }
88 90
89 if(sinfo->flags & IPT_CONNTRACK_REPLDST) { 91 if(sinfo->flags & XT_CONNTRACK_REPLDST) {
90 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, IPT_CONNTRACK_REPLDST)) 92 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, XT_CONNTRACK_REPLDST))
91 return 0; 93 return 0;
92 } 94 }
93 95
94 if(sinfo->flags & IPT_CONNTRACK_STATUS) { 96 if(sinfo->flags & XT_CONNTRACK_STATUS) {
95 if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, IPT_CONNTRACK_STATUS)) 97 if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, XT_CONNTRACK_STATUS))
96 return 0; 98 return 0;
97 } 99 }
98 100
99 if(sinfo->flags & IPT_CONNTRACK_EXPIRES) { 101 if(sinfo->flags & XT_CONNTRACK_EXPIRES) {
100 unsigned long expires; 102 unsigned long expires;
101 103
102 if(!ct) 104 if(!ct)
@@ -104,7 +106,7 @@ match(const struct sk_buff *skb,
104 106
105 expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0; 107 expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0;
106 108
107 if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), IPT_CONNTRACK_EXPIRES)) 109 if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), XT_CONNTRACK_EXPIRES))
108 return 0; 110 return 0;
109 } 111 }
110 112
@@ -118,9 +120,10 @@ match(const struct sk_buff *skb,
118 const struct net_device *out, 120 const struct net_device *out,
119 const void *matchinfo, 121 const void *matchinfo,
120 int offset, 122 int offset,
123 unsigned int protoff,
121 int *hotdrop) 124 int *hotdrop)
122{ 125{
123 const struct ipt_conntrack_info *sinfo = matchinfo; 126 const struct xt_conntrack_info *sinfo = matchinfo;
124 struct nf_conn *ct; 127 struct nf_conn *ct;
125 enum ip_conntrack_info ctinfo; 128 enum ip_conntrack_info ctinfo;
126 unsigned int statebit; 129 unsigned int statebit;
@@ -130,58 +133,58 @@ match(const struct sk_buff *skb,
130#define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg)) 133#define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg))
131 134
132 if (ct == &nf_conntrack_untracked) 135 if (ct == &nf_conntrack_untracked)
133 statebit = IPT_CONNTRACK_STATE_UNTRACKED; 136 statebit = XT_CONNTRACK_STATE_UNTRACKED;
134 else if (ct) 137 else if (ct)
135 statebit = IPT_CONNTRACK_STATE_BIT(ctinfo); 138 statebit = XT_CONNTRACK_STATE_BIT(ctinfo);
136 else 139 else
137 statebit = IPT_CONNTRACK_STATE_INVALID; 140 statebit = XT_CONNTRACK_STATE_INVALID;
138 141
139 if(sinfo->flags & IPT_CONNTRACK_STATE) { 142 if(sinfo->flags & XT_CONNTRACK_STATE) {
140 if (ct) { 143 if (ct) {
141 if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip != 144 if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip !=
142 ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip) 145 ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip)
143 statebit |= IPT_CONNTRACK_STATE_SNAT; 146 statebit |= XT_CONNTRACK_STATE_SNAT;
144 147
145 if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip != 148 if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip !=
146 ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip) 149 ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip)
147 statebit |= IPT_CONNTRACK_STATE_DNAT; 150 statebit |= XT_CONNTRACK_STATE_DNAT;
148 } 151 }
149 152
150 if (FWINV((statebit & sinfo->statemask) == 0, IPT_CONNTRACK_STATE)) 153 if (FWINV((statebit & sinfo->statemask) == 0, XT_CONNTRACK_STATE))
151 return 0; 154 return 0;
152 } 155 }
153 156
154 if(sinfo->flags & IPT_CONNTRACK_PROTO) { 157 if(sinfo->flags & XT_CONNTRACK_PROTO) {
155 if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, IPT_CONNTRACK_PROTO)) 158 if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, XT_CONNTRACK_PROTO))
156 return 0; 159 return 0;
157 } 160 }
158 161
159 if(sinfo->flags & IPT_CONNTRACK_ORIGSRC) { 162 if(sinfo->flags & XT_CONNTRACK_ORIGSRC) {
160 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, IPT_CONNTRACK_ORIGSRC)) 163 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, XT_CONNTRACK_ORIGSRC))
161 return 0; 164 return 0;
162 } 165 }
163 166
164 if(sinfo->flags & IPT_CONNTRACK_ORIGDST) { 167 if(sinfo->flags & XT_CONNTRACK_ORIGDST) {
165 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, IPT_CONNTRACK_ORIGDST)) 168 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, XT_CONNTRACK_ORIGDST))
166 return 0; 169 return 0;
167 } 170 }
168 171
169 if(sinfo->flags & IPT_CONNTRACK_REPLSRC) { 172 if(sinfo->flags & XT_CONNTRACK_REPLSRC) {
170 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, IPT_CONNTRACK_REPLSRC)) 173 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, XT_CONNTRACK_REPLSRC))
171 return 0; 174 return 0;
172 } 175 }
173 176
174 if(sinfo->flags & IPT_CONNTRACK_REPLDST) { 177 if(sinfo->flags & XT_CONNTRACK_REPLDST) {
175 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, IPT_CONNTRACK_REPLDST)) 178 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, XT_CONNTRACK_REPLDST))
176 return 0; 179 return 0;
177 } 180 }
178 181
179 if(sinfo->flags & IPT_CONNTRACK_STATUS) { 182 if(sinfo->flags & XT_CONNTRACK_STATUS) {
180 if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, IPT_CONNTRACK_STATUS)) 183 if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, XT_CONNTRACK_STATUS))
181 return 0; 184 return 0;
182 } 185 }
183 186
184 if(sinfo->flags & IPT_CONNTRACK_EXPIRES) { 187 if(sinfo->flags & XT_CONNTRACK_EXPIRES) {
185 unsigned long expires; 188 unsigned long expires;
186 189
187 if(!ct) 190 if(!ct)
@@ -189,7 +192,7 @@ match(const struct sk_buff *skb,
189 192
190 expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0; 193 expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0;
191 194
192 if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), IPT_CONNTRACK_EXPIRES)) 195 if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), XT_CONNTRACK_EXPIRES))
193 return 0; 196 return 0;
194 } 197 }
195 198
@@ -199,18 +202,18 @@ match(const struct sk_buff *skb,
199#endif /* CONFIG_NF_IP_CONNTRACK */ 202#endif /* CONFIG_NF_IP_CONNTRACK */
200 203
201static int check(const char *tablename, 204static int check(const char *tablename,
202 const struct ipt_ip *ip, 205 const void *ip,
203 void *matchinfo, 206 void *matchinfo,
204 unsigned int matchsize, 207 unsigned int matchsize,
205 unsigned int hook_mask) 208 unsigned int hook_mask)
206{ 209{
207 if (matchsize != IPT_ALIGN(sizeof(struct ipt_conntrack_info))) 210 if (matchsize != XT_ALIGN(sizeof(struct xt_conntrack_info)))
208 return 0; 211 return 0;
209 212
210 return 1; 213 return 1;
211} 214}
212 215
213static struct ipt_match conntrack_match = { 216static struct xt_match conntrack_match = {
214 .name = "conntrack", 217 .name = "conntrack",
215 .match = &match, 218 .match = &match,
216 .checkentry = &check, 219 .checkentry = &check,
@@ -219,13 +222,16 @@ static struct ipt_match conntrack_match = {
219 222
220static int __init init(void) 223static int __init init(void)
221{ 224{
222 need_ip_conntrack(); 225 int ret;
223 return ipt_register_match(&conntrack_match); 226 need_conntrack();
227 ret = xt_register_match(AF_INET, &conntrack_match);
228
229 return ret;
224} 230}
225 231
226static void __exit fini(void) 232static void __exit fini(void)
227{ 233{
228 ipt_unregister_match(&conntrack_match); 234 xt_unregister_match(AF_INET, &conntrack_match);
229} 235}
230 236
231module_init(init); 237module_init(init);
diff --git a/net/ipv4/netfilter/ipt_dccp.c b/net/netfilter/xt_dccp.c
index ad3278bba6c1..779f42fc9524 100644
--- a/net/ipv4/netfilter/ipt_dccp.c
+++ b/net/netfilter/xt_dccp.c
@@ -14,8 +14,16 @@
14#include <net/ip.h> 14#include <net/ip.h>
15#include <linux/dccp.h> 15#include <linux/dccp.h>
16 16
17#include <linux/netfilter/x_tables.h>
18#include <linux/netfilter/xt_dccp.h>
19
17#include <linux/netfilter_ipv4/ip_tables.h> 20#include <linux/netfilter_ipv4/ip_tables.h>
18#include <linux/netfilter_ipv4/ipt_dccp.h> 21#include <linux/netfilter_ipv6/ip6_tables.h>
22
23MODULE_LICENSE("GPL");
24MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
25MODULE_DESCRIPTION("Match for DCCP protocol packets");
26MODULE_ALIAS("ipt_dccp");
19 27
20#define DCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \ 28#define DCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \
21 || (!!((invflag) & (option)) ^ (cond))) 29 || (!!((invflag) & (option)) ^ (cond)))
@@ -26,6 +34,7 @@ static DEFINE_SPINLOCK(dccp_buflock);
26static inline int 34static inline int
27dccp_find_option(u_int8_t option, 35dccp_find_option(u_int8_t option,
28 const struct sk_buff *skb, 36 const struct sk_buff *skb,
37 unsigned int protoff,
29 const struct dccp_hdr *dh, 38 const struct dccp_hdr *dh,
30 int *hotdrop) 39 int *hotdrop)
31{ 40{
@@ -44,9 +53,7 @@ dccp_find_option(u_int8_t option,
44 return 0; 53 return 0;
45 54
46 spin_lock_bh(&dccp_buflock); 55 spin_lock_bh(&dccp_buflock);
47 op = skb_header_pointer(skb, 56 op = skb_header_pointer(skb, protoff + optoff, optlen, dccp_optbuf);
48 skb->nh.iph->ihl*4 + optoff,
49 optlen, dccp_optbuf);
50 if (op == NULL) { 57 if (op == NULL) {
51 /* If we don't have the whole header, drop packet. */ 58 /* If we don't have the whole header, drop packet. */
52 spin_unlock_bh(&dccp_buflock); 59 spin_unlock_bh(&dccp_buflock);
@@ -78,10 +85,10 @@ match_types(const struct dccp_hdr *dh, u_int16_t typemask)
78} 85}
79 86
80static inline int 87static inline int
81match_option(u_int8_t option, const struct sk_buff *skb, 88match_option(u_int8_t option, const struct sk_buff *skb, unsigned int protoff,
82 const struct dccp_hdr *dh, int *hotdrop) 89 const struct dccp_hdr *dh, int *hotdrop)
83{ 90{
84 return dccp_find_option(option, skb, dh, hotdrop); 91 return dccp_find_option(option, skb, protoff, dh, hotdrop);
85} 92}
86 93
87static int 94static int
@@ -90,16 +97,17 @@ match(const struct sk_buff *skb,
90 const struct net_device *out, 97 const struct net_device *out,
91 const void *matchinfo, 98 const void *matchinfo,
92 int offset, 99 int offset,
100 unsigned int protoff,
93 int *hotdrop) 101 int *hotdrop)
94{ 102{
95 const struct ipt_dccp_info *info = 103 const struct xt_dccp_info *info =
96 (const struct ipt_dccp_info *)matchinfo; 104 (const struct xt_dccp_info *)matchinfo;
97 struct dccp_hdr _dh, *dh; 105 struct dccp_hdr _dh, *dh;
98 106
99 if (offset) 107 if (offset)
100 return 0; 108 return 0;
101 109
102 dh = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_dh), &_dh); 110 dh = skb_header_pointer(skb, protoff, sizeof(_dh), &_dh);
103 if (dh == NULL) { 111 if (dh == NULL) {
104 *hotdrop = 1; 112 *hotdrop = 1;
105 return 0; 113 return 0;
@@ -107,42 +115,73 @@ match(const struct sk_buff *skb,
107 115
108 return DCCHECK(((ntohs(dh->dccph_sport) >= info->spts[0]) 116 return DCCHECK(((ntohs(dh->dccph_sport) >= info->spts[0])
109 && (ntohs(dh->dccph_sport) <= info->spts[1])), 117 && (ntohs(dh->dccph_sport) <= info->spts[1])),
110 IPT_DCCP_SRC_PORTS, info->flags, info->invflags) 118 XT_DCCP_SRC_PORTS, info->flags, info->invflags)
111 && DCCHECK(((ntohs(dh->dccph_dport) >= info->dpts[0]) 119 && DCCHECK(((ntohs(dh->dccph_dport) >= info->dpts[0])
112 && (ntohs(dh->dccph_dport) <= info->dpts[1])), 120 && (ntohs(dh->dccph_dport) <= info->dpts[1])),
113 IPT_DCCP_DEST_PORTS, info->flags, info->invflags) 121 XT_DCCP_DEST_PORTS, info->flags, info->invflags)
114 && DCCHECK(match_types(dh, info->typemask), 122 && DCCHECK(match_types(dh, info->typemask),
115 IPT_DCCP_TYPE, info->flags, info->invflags) 123 XT_DCCP_TYPE, info->flags, info->invflags)
116 && DCCHECK(match_option(info->option, skb, dh, hotdrop), 124 && DCCHECK(match_option(info->option, skb, protoff, dh,
117 IPT_DCCP_OPTION, info->flags, info->invflags); 125 hotdrop),
126 XT_DCCP_OPTION, info->flags, info->invflags);
118} 127}
119 128
120static int 129static int
121checkentry(const char *tablename, 130checkentry(const char *tablename,
122 const struct ipt_ip *ip, 131 const void *inf,
123 void *matchinfo, 132 void *matchinfo,
124 unsigned int matchsize, 133 unsigned int matchsize,
125 unsigned int hook_mask) 134 unsigned int hook_mask)
126{ 135{
127 const struct ipt_dccp_info *info; 136 const struct ipt_ip *ip = inf;
137 const struct xt_dccp_info *info;
128 138
129 info = (const struct ipt_dccp_info *)matchinfo; 139 info = (const struct xt_dccp_info *)matchinfo;
130 140
131 return ip->proto == IPPROTO_DCCP 141 return ip->proto == IPPROTO_DCCP
132 && !(ip->invflags & IPT_INV_PROTO) 142 && !(ip->invflags & XT_INV_PROTO)
133 && matchsize == IPT_ALIGN(sizeof(struct ipt_dccp_info)) 143 && matchsize == XT_ALIGN(sizeof(struct xt_dccp_info))
134 && !(info->flags & ~IPT_DCCP_VALID_FLAGS) 144 && !(info->flags & ~XT_DCCP_VALID_FLAGS)
135 && !(info->invflags & ~IPT_DCCP_VALID_FLAGS) 145 && !(info->invflags & ~XT_DCCP_VALID_FLAGS)
136 && !(info->invflags & ~info->flags); 146 && !(info->invflags & ~info->flags);
137} 147}
138 148
139static struct ipt_match dccp_match = 149static int
150checkentry6(const char *tablename,
151 const void *inf,
152 void *matchinfo,
153 unsigned int matchsize,
154 unsigned int hook_mask)
155{
156 const struct ip6t_ip6 *ip = inf;
157 const struct xt_dccp_info *info;
158
159 info = (const struct xt_dccp_info *)matchinfo;
160
161 return ip->proto == IPPROTO_DCCP
162 && !(ip->invflags & XT_INV_PROTO)
163 && matchsize == XT_ALIGN(sizeof(struct xt_dccp_info))
164 && !(info->flags & ~XT_DCCP_VALID_FLAGS)
165 && !(info->invflags & ~XT_DCCP_VALID_FLAGS)
166 && !(info->invflags & ~info->flags);
167}
168
169
170static struct xt_match dccp_match =
140{ 171{
141 .name = "dccp", 172 .name = "dccp",
142 .match = &match, 173 .match = &match,
143 .checkentry = &checkentry, 174 .checkentry = &checkentry,
144 .me = THIS_MODULE, 175 .me = THIS_MODULE,
145}; 176};
177static struct xt_match dccp6_match =
178{
179 .name = "dccp",
180 .match = &match,
181 .checkentry = &checkentry6,
182 .me = THIS_MODULE,
183};
184
146 185
147static int __init init(void) 186static int __init init(void)
148{ 187{
@@ -154,23 +193,29 @@ static int __init init(void)
154 dccp_optbuf = kmalloc(256 * 4, GFP_KERNEL); 193 dccp_optbuf = kmalloc(256 * 4, GFP_KERNEL);
155 if (!dccp_optbuf) 194 if (!dccp_optbuf)
156 return -ENOMEM; 195 return -ENOMEM;
157 ret = ipt_register_match(&dccp_match); 196 ret = xt_register_match(AF_INET, &dccp_match);
158 if (ret) 197 if (ret)
159 kfree(dccp_optbuf); 198 goto out_kfree;
199 ret = xt_register_match(AF_INET6, &dccp6_match);
200 if (ret)
201 goto out_unreg;
202
203 return ret;
204
205out_unreg:
206 xt_unregister_match(AF_INET, &dccp_match);
207out_kfree:
208 kfree(dccp_optbuf);
160 209
161 return ret; 210 return ret;
162} 211}
163 212
164static void __exit fini(void) 213static void __exit fini(void)
165{ 214{
166 ipt_unregister_match(&dccp_match); 215 xt_unregister_match(AF_INET6, &dccp6_match);
216 xt_unregister_match(AF_INET, &dccp_match);
167 kfree(dccp_optbuf); 217 kfree(dccp_optbuf);
168} 218}
169 219
170module_init(init); 220module_init(init);
171module_exit(fini); 221module_exit(fini);
172
173MODULE_LICENSE("GPL");
174MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
175MODULE_DESCRIPTION("Match for DCCP protocol packets");
176
diff --git a/net/ipv4/netfilter/ipt_helper.c b/net/netfilter/xt_helper.c
index aef649e393af..38b6715e1db4 100644
--- a/net/ipv4/netfilter/ipt_helper.c
+++ b/net/netfilter/xt_helper.c
@@ -13,7 +13,6 @@
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/skbuff.h> 14#include <linux/skbuff.h>
15#include <linux/netfilter.h> 15#include <linux/netfilter.h>
16#include <linux/interrupt.h>
17#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE) 16#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
18#include <linux/netfilter_ipv4/ip_conntrack.h> 17#include <linux/netfilter_ipv4/ip_conntrack.h>
19#include <linux/netfilter_ipv4/ip_conntrack_core.h> 18#include <linux/netfilter_ipv4/ip_conntrack_core.h>
@@ -23,12 +22,14 @@
23#include <net/netfilter/nf_conntrack_core.h> 22#include <net/netfilter/nf_conntrack_core.h>
24#include <net/netfilter/nf_conntrack_helper.h> 23#include <net/netfilter/nf_conntrack_helper.h>
25#endif 24#endif
26#include <linux/netfilter_ipv4/ip_tables.h> 25#include <linux/netfilter/x_tables.h>
27#include <linux/netfilter_ipv4/ipt_helper.h> 26#include <linux/netfilter/xt_helper.h>
28 27
29MODULE_LICENSE("GPL"); 28MODULE_LICENSE("GPL");
30MODULE_AUTHOR("Martin Josefsson <gandalf@netfilter.org>"); 29MODULE_AUTHOR("Martin Josefsson <gandalf@netfilter.org>");
31MODULE_DESCRIPTION("iptables helper match module"); 30MODULE_DESCRIPTION("iptables helper match module");
31MODULE_ALIAS("ipt_helper");
32MODULE_ALIAS("ip6t_helper");
32 33
33#if 0 34#if 0
34#define DEBUGP printk 35#define DEBUGP printk
@@ -43,27 +44,28 @@ match(const struct sk_buff *skb,
43 const struct net_device *out, 44 const struct net_device *out,
44 const void *matchinfo, 45 const void *matchinfo,
45 int offset, 46 int offset,
47 unsigned int protoff,
46 int *hotdrop) 48 int *hotdrop)
47{ 49{
48 const struct ipt_helper_info *info = matchinfo; 50 const struct xt_helper_info *info = matchinfo;
49 struct ip_conntrack *ct; 51 struct ip_conntrack *ct;
50 enum ip_conntrack_info ctinfo; 52 enum ip_conntrack_info ctinfo;
51 int ret = info->invert; 53 int ret = info->invert;
52 54
53 ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo); 55 ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
54 if (!ct) { 56 if (!ct) {
55 DEBUGP("ipt_helper: Eek! invalid conntrack?\n"); 57 DEBUGP("xt_helper: Eek! invalid conntrack?\n");
56 return ret; 58 return ret;
57 } 59 }
58 60
59 if (!ct->master) { 61 if (!ct->master) {
60 DEBUGP("ipt_helper: conntrack %p has no master\n", ct); 62 DEBUGP("xt_helper: conntrack %p has no master\n", ct);
61 return ret; 63 return ret;
62 } 64 }
63 65
64 read_lock_bh(&ip_conntrack_lock); 66 read_lock_bh(&ip_conntrack_lock);
65 if (!ct->master->helper) { 67 if (!ct->master->helper) {
66 DEBUGP("ipt_helper: master ct %p has no helper\n", 68 DEBUGP("xt_helper: master ct %p has no helper\n",
67 exp->expectant); 69 exp->expectant);
68 goto out_unlock; 70 goto out_unlock;
69 } 71 }
@@ -89,27 +91,28 @@ match(const struct sk_buff *skb,
89 const struct net_device *out, 91 const struct net_device *out,
90 const void *matchinfo, 92 const void *matchinfo,
91 int offset, 93 int offset,
94 unsigned int protoff,
92 int *hotdrop) 95 int *hotdrop)
93{ 96{
94 const struct ipt_helper_info *info = matchinfo; 97 const struct xt_helper_info *info = matchinfo;
95 struct nf_conn *ct; 98 struct nf_conn *ct;
96 enum ip_conntrack_info ctinfo; 99 enum ip_conntrack_info ctinfo;
97 int ret = info->invert; 100 int ret = info->invert;
98 101
99 ct = nf_ct_get((struct sk_buff *)skb, &ctinfo); 102 ct = nf_ct_get((struct sk_buff *)skb, &ctinfo);
100 if (!ct) { 103 if (!ct) {
101 DEBUGP("ipt_helper: Eek! invalid conntrack?\n"); 104 DEBUGP("xt_helper: Eek! invalid conntrack?\n");
102 return ret; 105 return ret;
103 } 106 }
104 107
105 if (!ct->master) { 108 if (!ct->master) {
106 DEBUGP("ipt_helper: conntrack %p has no master\n", ct); 109 DEBUGP("xt_helper: conntrack %p has no master\n", ct);
107 return ret; 110 return ret;
108 } 111 }
109 112
110 read_lock_bh(&nf_conntrack_lock); 113 read_lock_bh(&nf_conntrack_lock);
111 if (!ct->master->helper) { 114 if (!ct->master->helper) {
112 DEBUGP("ipt_helper: master ct %p has no helper\n", 115 DEBUGP("xt_helper: master ct %p has no helper\n",
113 exp->expectant); 116 exp->expectant);
114 goto out_unlock; 117 goto out_unlock;
115 } 118 }
@@ -129,23 +132,29 @@ out_unlock:
129#endif 132#endif
130 133
131static int check(const char *tablename, 134static int check(const char *tablename,
132 const struct ipt_ip *ip, 135 const void *inf,
133 void *matchinfo, 136 void *matchinfo,
134 unsigned int matchsize, 137 unsigned int matchsize,
135 unsigned int hook_mask) 138 unsigned int hook_mask)
136{ 139{
137 struct ipt_helper_info *info = matchinfo; 140 struct xt_helper_info *info = matchinfo;
138 141
139 info->name[29] = '\0'; 142 info->name[29] = '\0';
140 143
141 /* verify size */ 144 /* verify size */
142 if (matchsize != IPT_ALIGN(sizeof(struct ipt_helper_info))) 145 if (matchsize != XT_ALIGN(sizeof(struct xt_helper_info)))
143 return 0; 146 return 0;
144 147
145 return 1; 148 return 1;
146} 149}
147 150
148static struct ipt_match helper_match = { 151static struct xt_match helper_match = {
152 .name = "helper",
153 .match = &match,
154 .checkentry = &check,
155 .me = THIS_MODULE,
156};
157static struct xt_match helper6_match = {
149 .name = "helper", 158 .name = "helper",
150 .match = &match, 159 .match = &match,
151 .checkentry = &check, 160 .checkentry = &check,
@@ -154,13 +163,24 @@ static struct ipt_match helper_match = {
154 163
155static int __init init(void) 164static int __init init(void)
156{ 165{
157 need_ip_conntrack(); 166 int ret;
158 return ipt_register_match(&helper_match); 167 need_conntrack();
168
169 ret = xt_register_match(AF_INET, &helper_match);
170 if (ret < 0)
171 return ret;
172
173 ret = xt_register_match(AF_INET6, &helper6_match);
174 if (ret < 0)
175 xt_unregister_match(AF_INET, &helper_match);
176
177 return ret;
159} 178}
160 179
161static void __exit fini(void) 180static void __exit fini(void)
162{ 181{
163 ipt_unregister_match(&helper_match); 182 xt_unregister_match(AF_INET, &helper_match);
183 xt_unregister_match(AF_INET6, &helper6_match);
164} 184}
165 185
166module_init(init); 186module_init(init);
diff --git a/net/netfilter/xt_length.c b/net/netfilter/xt_length.c
new file mode 100644
index 000000000000..39c8faea63de
--- /dev/null
+++ b/net/netfilter/xt_length.c
@@ -0,0 +1,99 @@
1/* Kernel module to match packet length. */
2/* (C) 1999-2001 James Morris <jmorros@intercode.com.au>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/module.h>
10#include <linux/skbuff.h>
11#include <linux/ipv6.h>
12#include <net/ip.h>
13
14#include <linux/netfilter/xt_length.h>
15#include <linux/netfilter/x_tables.h>
16
17MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
18MODULE_DESCRIPTION("IP tables packet length matching module");
19MODULE_LICENSE("GPL");
20MODULE_ALIAS("ipt_length");
21MODULE_ALIAS("ip6t_length");
22
23static int
24match(const struct sk_buff *skb,
25 const struct net_device *in,
26 const struct net_device *out,
27 const void *matchinfo,
28 int offset,
29 unsigned int protoff,
30 int *hotdrop)
31{
32 const struct xt_length_info *info = matchinfo;
33 u_int16_t pktlen = ntohs(skb->nh.iph->tot_len);
34
35 return (pktlen >= info->min && pktlen <= info->max) ^ info->invert;
36}
37
38static int
39match6(const struct sk_buff *skb,
40 const struct net_device *in,
41 const struct net_device *out,
42 const void *matchinfo,
43 int offset,
44 unsigned int protoff,
45 int *hotdrop)
46{
47 const struct xt_length_info *info = matchinfo;
48 u_int16_t pktlen = ntohs(skb->nh.ipv6h->payload_len) + sizeof(struct ipv6hdr);
49
50 return (pktlen >= info->min && pktlen <= info->max) ^ info->invert;
51}
52
53static int
54checkentry(const char *tablename,
55 const void *ip,
56 void *matchinfo,
57 unsigned int matchsize,
58 unsigned int hook_mask)
59{
60 if (matchsize != XT_ALIGN(sizeof(struct xt_length_info)))
61 return 0;
62
63 return 1;
64}
65
66static struct xt_match length_match = {
67 .name = "length",
68 .match = &match,
69 .checkentry = &checkentry,
70 .me = THIS_MODULE,
71};
72static struct xt_match length6_match = {
73 .name = "length",
74 .match = &match6,
75 .checkentry = &checkentry,
76 .me = THIS_MODULE,
77};
78
79static int __init init(void)
80{
81 int ret;
82 ret = xt_register_match(AF_INET, &length_match);
83 if (ret)
84 return ret;
85 ret = xt_register_match(AF_INET6, &length6_match);
86 if (ret)
87 xt_unregister_match(AF_INET, &length_match);
88
89 return ret;
90}
91
92static void __exit fini(void)
93{
94 xt_unregister_match(AF_INET, &length_match);
95 xt_unregister_match(AF_INET6, &length6_match);
96}
97
98module_init(init);
99module_exit(fini);
diff --git a/net/ipv4/netfilter/ipt_limit.c b/net/netfilter/xt_limit.c
index 0c24dcc703a5..15e40506bc3a 100644
--- a/net/ipv4/netfilter/ipt_limit.c
+++ b/net/netfilter/xt_limit.c
@@ -18,12 +18,14 @@
18#include <linux/spinlock.h> 18#include <linux/spinlock.h>
19#include <linux/interrupt.h> 19#include <linux/interrupt.h>
20 20
21#include <linux/netfilter_ipv4/ip_tables.h> 21#include <linux/netfilter/x_tables.h>
22#include <linux/netfilter_ipv4/ipt_limit.h> 22#include <linux/netfilter/xt_limit.h>
23 23
24MODULE_LICENSE("GPL"); 24MODULE_LICENSE("GPL");
25MODULE_AUTHOR("Herve Eychenne <rv@wallfire.org>"); 25MODULE_AUTHOR("Herve Eychenne <rv@wallfire.org>");
26MODULE_DESCRIPTION("iptables rate limit match"); 26MODULE_DESCRIPTION("iptables rate limit match");
27MODULE_ALIAS("ipt_limit");
28MODULE_ALIAS("ip6t_limit");
27 29
28/* The algorithm used is the Simple Token Bucket Filter (TBF) 30/* The algorithm used is the Simple Token Bucket Filter (TBF)
29 * see net/sched/sch_tbf.c in the linux source tree 31 * see net/sched/sch_tbf.c in the linux source tree
@@ -68,9 +70,10 @@ ipt_limit_match(const struct sk_buff *skb,
68 const struct net_device *out, 70 const struct net_device *out,
69 const void *matchinfo, 71 const void *matchinfo,
70 int offset, 72 int offset,
73 unsigned int protoff,
71 int *hotdrop) 74 int *hotdrop)
72{ 75{
73 struct ipt_rateinfo *r = ((struct ipt_rateinfo *)matchinfo)->master; 76 struct xt_rateinfo *r = ((struct xt_rateinfo *)matchinfo)->master;
74 unsigned long now = jiffies; 77 unsigned long now = jiffies;
75 78
76 spin_lock_bh(&limit_lock); 79 spin_lock_bh(&limit_lock);
@@ -96,32 +99,32 @@ user2credits(u_int32_t user)
96 /* If multiplying would overflow... */ 99 /* If multiplying would overflow... */
97 if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY)) 100 if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
98 /* Divide first. */ 101 /* Divide first. */
99 return (user / IPT_LIMIT_SCALE) * HZ * CREDITS_PER_JIFFY; 102 return (user / XT_LIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
100 103
101 return (user * HZ * CREDITS_PER_JIFFY) / IPT_LIMIT_SCALE; 104 return (user * HZ * CREDITS_PER_JIFFY) / XT_LIMIT_SCALE;
102} 105}
103 106
104static int 107static int
105ipt_limit_checkentry(const char *tablename, 108ipt_limit_checkentry(const char *tablename,
106 const struct ipt_ip *ip, 109 const void *inf,
107 void *matchinfo, 110 void *matchinfo,
108 unsigned int matchsize, 111 unsigned int matchsize,
109 unsigned int hook_mask) 112 unsigned int hook_mask)
110{ 113{
111 struct ipt_rateinfo *r = matchinfo; 114 struct xt_rateinfo *r = matchinfo;
112 115
113 if (matchsize != IPT_ALIGN(sizeof(struct ipt_rateinfo))) 116 if (matchsize != XT_ALIGN(sizeof(struct xt_rateinfo)))
114 return 0; 117 return 0;
115 118
116 /* Check for overflow. */ 119 /* Check for overflow. */
117 if (r->burst == 0 120 if (r->burst == 0
118 || user2credits(r->avg * r->burst) < user2credits(r->avg)) { 121 || user2credits(r->avg * r->burst) < user2credits(r->avg)) {
119 printk("Overflow in ipt_limit, try lower: %u/%u\n", 122 printk("Overflow in xt_limit, try lower: %u/%u\n",
120 r->avg, r->burst); 123 r->avg, r->burst);
121 return 0; 124 return 0;
122 } 125 }
123 126
124 /* User avg in seconds * IPT_LIMIT_SCALE: convert to jiffies * 127 /* User avg in seconds * XT_LIMIT_SCALE: convert to jiffies *
125 128. */ 128 128. */
126 r->prev = jiffies; 129 r->prev = jiffies;
127 r->credit = user2credits(r->avg * r->burst); /* Credits full. */ 130 r->credit = user2credits(r->avg * r->burst); /* Credits full. */
@@ -134,7 +137,13 @@ ipt_limit_checkentry(const char *tablename,
134 return 1; 137 return 1;
135} 138}
136 139
137static struct ipt_match ipt_limit_reg = { 140static struct xt_match ipt_limit_reg = {
141 .name = "limit",
142 .match = ipt_limit_match,
143 .checkentry = ipt_limit_checkentry,
144 .me = THIS_MODULE,
145};
146static struct xt_match limit6_reg = {
138 .name = "limit", 147 .name = "limit",
139 .match = ipt_limit_match, 148 .match = ipt_limit_match,
140 .checkentry = ipt_limit_checkentry, 149 .checkentry = ipt_limit_checkentry,
@@ -143,14 +152,23 @@ static struct ipt_match ipt_limit_reg = {
143 152
144static int __init init(void) 153static int __init init(void)
145{ 154{
146 if (ipt_register_match(&ipt_limit_reg)) 155 int ret;
147 return -EINVAL; 156
148 return 0; 157 ret = xt_register_match(AF_INET, &ipt_limit_reg);
158 if (ret)
159 return ret;
160
161 ret = xt_register_match(AF_INET6, &limit6_reg);
162 if (ret)
163 xt_unregister_match(AF_INET, &ipt_limit_reg);
164
165 return ret;
149} 166}
150 167
151static void __exit fini(void) 168static void __exit fini(void)
152{ 169{
153 ipt_unregister_match(&ipt_limit_reg); 170 xt_unregister_match(AF_INET, &ipt_limit_reg);
171 xt_unregister_match(AF_INET6, &limit6_reg);
154} 172}
155 173
156module_init(init); 174module_init(init);
diff --git a/net/ipv4/netfilter/ipt_mac.c b/net/netfilter/xt_mac.c
index 1b9bb4559f80..0461dcb5fc7a 100644
--- a/net/ipv4/netfilter/ipt_mac.c
+++ b/net/netfilter/xt_mac.c
@@ -13,12 +13,15 @@
13#include <linux/if_ether.h> 13#include <linux/if_ether.h>
14#include <linux/etherdevice.h> 14#include <linux/etherdevice.h>
15 15
16#include <linux/netfilter_ipv4/ipt_mac.h> 16#include <linux/netfilter_ipv4.h>
17#include <linux/netfilter_ipv4/ip_tables.h> 17#include <linux/netfilter/xt_mac.h>
18#include <linux/netfilter/x_tables.h>
18 19
19MODULE_LICENSE("GPL"); 20MODULE_LICENSE("GPL");
20MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); 21MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
21MODULE_DESCRIPTION("iptables mac matching module"); 22MODULE_DESCRIPTION("iptables mac matching module");
23MODULE_ALIAS("ipt_mac");
24MODULE_ALIAS("ip6t_mac");
22 25
23static int 26static int
24match(const struct sk_buff *skb, 27match(const struct sk_buff *skb,
@@ -26,9 +29,10 @@ match(const struct sk_buff *skb,
26 const struct net_device *out, 29 const struct net_device *out,
27 const void *matchinfo, 30 const void *matchinfo,
28 int offset, 31 int offset,
32 unsigned int protoff,
29 int *hotdrop) 33 int *hotdrop)
30{ 34{
31 const struct ipt_mac_info *info = matchinfo; 35 const struct xt_mac_info *info = matchinfo;
32 36
33 /* Is mac pointer valid? */ 37 /* Is mac pointer valid? */
34 return (skb->mac.raw >= skb->head 38 return (skb->mac.raw >= skb->head
@@ -40,7 +44,7 @@ match(const struct sk_buff *skb,
40 44
41static int 45static int
42ipt_mac_checkentry(const char *tablename, 46ipt_mac_checkentry(const char *tablename,
43 const struct ipt_ip *ip, 47 const void *inf,
44 void *matchinfo, 48 void *matchinfo,
45 unsigned int matchsize, 49 unsigned int matchsize,
46 unsigned int hook_mask) 50 unsigned int hook_mask)
@@ -49,17 +53,23 @@ ipt_mac_checkentry(const char *tablename,
49 if (hook_mask 53 if (hook_mask
50 & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) 54 & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN)
51 | (1 << NF_IP_FORWARD))) { 55 | (1 << NF_IP_FORWARD))) {
52 printk("ipt_mac: only valid for PRE_ROUTING, LOCAL_IN or FORWARD.\n"); 56 printk("xt_mac: only valid for PRE_ROUTING, LOCAL_IN or FORWARD.\n");
53 return 0; 57 return 0;
54 } 58 }
55 59
56 if (matchsize != IPT_ALIGN(sizeof(struct ipt_mac_info))) 60 if (matchsize != XT_ALIGN(sizeof(struct xt_mac_info)))
57 return 0; 61 return 0;
58 62
59 return 1; 63 return 1;
60} 64}
61 65
62static struct ipt_match mac_match = { 66static struct xt_match mac_match = {
67 .name = "mac",
68 .match = &match,
69 .checkentry = &ipt_mac_checkentry,
70 .me = THIS_MODULE,
71};
72static struct xt_match mac6_match = {
63 .name = "mac", 73 .name = "mac",
64 .match = &match, 74 .match = &match,
65 .checkentry = &ipt_mac_checkentry, 75 .checkentry = &ipt_mac_checkentry,
@@ -68,12 +78,22 @@ static struct ipt_match mac_match = {
68 78
69static int __init init(void) 79static int __init init(void)
70{ 80{
71 return ipt_register_match(&mac_match); 81 int ret;
82 ret = xt_register_match(AF_INET, &mac_match);
83 if (ret)
84 return ret;
85
86 ret = xt_register_match(AF_INET6, &mac6_match);
87 if (ret)
88 xt_unregister_match(AF_INET, &mac_match);
89
90 return ret;
72} 91}
73 92
74static void __exit fini(void) 93static void __exit fini(void)
75{ 94{
76 ipt_unregister_match(&mac_match); 95 xt_unregister_match(AF_INET, &mac_match);
96 xt_unregister_match(AF_INET6, &mac6_match);
77} 97}
78 98
79module_init(init); 99module_init(init);
diff --git a/net/ipv4/netfilter/ipt_mark.c b/net/netfilter/xt_mark.c
index 00bef6cdd3f8..2a0ac62b72c8 100644
--- a/net/ipv4/netfilter/ipt_mark.c
+++ b/net/netfilter/xt_mark.c
@@ -10,12 +10,14 @@
10#include <linux/module.h> 10#include <linux/module.h>
11#include <linux/skbuff.h> 11#include <linux/skbuff.h>
12 12
13#include <linux/netfilter_ipv4/ipt_mark.h> 13#include <linux/netfilter/xt_mark.h>
14#include <linux/netfilter_ipv4/ip_tables.h> 14#include <linux/netfilter/x_tables.h>
15 15
16MODULE_LICENSE("GPL"); 16MODULE_LICENSE("GPL");
17MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); 17MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
18MODULE_DESCRIPTION("iptables mark matching module"); 18MODULE_DESCRIPTION("iptables mark matching module");
19MODULE_ALIAS("ipt_mark");
20MODULE_ALIAS("ip6t_mark");
19 21
20static int 22static int
21match(const struct sk_buff *skb, 23match(const struct sk_buff *skb,
@@ -23,23 +25,24 @@ match(const struct sk_buff *skb,
23 const struct net_device *out, 25 const struct net_device *out,
24 const void *matchinfo, 26 const void *matchinfo,
25 int offset, 27 int offset,
28 unsigned int protoff,
26 int *hotdrop) 29 int *hotdrop)
27{ 30{
28 const struct ipt_mark_info *info = matchinfo; 31 const struct xt_mark_info *info = matchinfo;
29 32
30 return ((skb->nfmark & info->mask) == info->mark) ^ info->invert; 33 return ((skb->nfmark & info->mask) == info->mark) ^ info->invert;
31} 34}
32 35
33static int 36static int
34checkentry(const char *tablename, 37checkentry(const char *tablename,
35 const struct ipt_ip *ip, 38 const void *entry,
36 void *matchinfo, 39 void *matchinfo,
37 unsigned int matchsize, 40 unsigned int matchsize,
38 unsigned int hook_mask) 41 unsigned int hook_mask)
39{ 42{
40 struct ipt_mark_info *minfo = (struct ipt_mark_info *) matchinfo; 43 struct xt_mark_info *minfo = (struct xt_mark_info *) matchinfo;
41 44
42 if (matchsize != IPT_ALIGN(sizeof(struct ipt_mark_info))) 45 if (matchsize != XT_ALIGN(sizeof(struct xt_mark_info)))
43 return 0; 46 return 0;
44 47
45 if (minfo->mark > 0xffffffff || minfo->mask > 0xffffffff) { 48 if (minfo->mark > 0xffffffff || minfo->mask > 0xffffffff) {
@@ -50,7 +53,14 @@ checkentry(const char *tablename,
50 return 1; 53 return 1;
51} 54}
52 55
53static struct ipt_match mark_match = { 56static struct xt_match mark_match = {
57 .name = "mark",
58 .match = &match,
59 .checkentry = &checkentry,
60 .me = THIS_MODULE,
61};
62
63static struct xt_match mark6_match = {
54 .name = "mark", 64 .name = "mark",
55 .match = &match, 65 .match = &match,
56 .checkentry = &checkentry, 66 .checkentry = &checkentry,
@@ -59,12 +69,22 @@ static struct ipt_match mark_match = {
59 69
60static int __init init(void) 70static int __init init(void)
61{ 71{
62 return ipt_register_match(&mark_match); 72 int ret;
73 ret = xt_register_match(AF_INET, &mark_match);
74 if (ret)
75 return ret;
76
77 ret = xt_register_match(AF_INET6, &mark6_match);
78 if (ret)
79 xt_unregister_match(AF_INET, &mark_match);
80
81 return ret;
63} 82}
64 83
65static void __exit fini(void) 84static void __exit fini(void)
66{ 85{
67 ipt_unregister_match(&mark_match); 86 xt_unregister_match(AF_INET, &mark_match);
87 xt_unregister_match(AF_INET6, &mark6_match);
68} 88}
69 89
70module_init(init); 90module_init(init);
diff --git a/net/ipv6/netfilter/ip6t_physdev.c b/net/netfilter/xt_physdev.c
index 71515c86ece1..19bb57c14dfe 100644
--- a/net/ipv6/netfilter/ip6t_physdev.c
+++ b/net/netfilter/xt_physdev.c
@@ -10,8 +10,8 @@
10 10
11#include <linux/module.h> 11#include <linux/module.h>
12#include <linux/skbuff.h> 12#include <linux/skbuff.h>
13#include <linux/netfilter_ipv6/ip6t_physdev.h> 13#include <linux/netfilter/xt_physdev.h>
14#include <linux/netfilter_ipv6/ip6_tables.h> 14#include <linux/netfilter/x_tables.h>
15#include <linux/netfilter_bridge.h> 15#include <linux/netfilter_bridge.h>
16#define MATCH 1 16#define MATCH 1
17#define NOMATCH 0 17#define NOMATCH 0
@@ -19,6 +19,8 @@
19MODULE_LICENSE("GPL"); 19MODULE_LICENSE("GPL");
20MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>"); 20MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
21MODULE_DESCRIPTION("iptables bridge physical device match module"); 21MODULE_DESCRIPTION("iptables bridge physical device match module");
22MODULE_ALIAS("ipt_physdev");
23MODULE_ALIAS("ip6t_physdev");
22 24
23static int 25static int
24match(const struct sk_buff *skb, 26match(const struct sk_buff *skb,
@@ -31,7 +33,7 @@ match(const struct sk_buff *skb,
31{ 33{
32 int i; 34 int i;
33 static const char nulldevname[IFNAMSIZ]; 35 static const char nulldevname[IFNAMSIZ];
34 const struct ip6t_physdev_info *info = matchinfo; 36 const struct xt_physdev_info *info = matchinfo;
35 unsigned int ret; 37 unsigned int ret;
36 const char *indev, *outdev; 38 const char *indev, *outdev;
37 struct nf_bridge_info *nf_bridge; 39 struct nf_bridge_info *nf_bridge;
@@ -41,37 +43,37 @@ match(const struct sk_buff *skb,
41 * the destination device will be a bridge. */ 43 * the destination device will be a bridge. */
42 if (!(nf_bridge = skb->nf_bridge)) { 44 if (!(nf_bridge = skb->nf_bridge)) {
43 /* Return MATCH if the invert flags of the used options are on */ 45 /* Return MATCH if the invert flags of the used options are on */
44 if ((info->bitmask & IP6T_PHYSDEV_OP_BRIDGED) && 46 if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) &&
45 !(info->invert & IP6T_PHYSDEV_OP_BRIDGED)) 47 !(info->invert & XT_PHYSDEV_OP_BRIDGED))
46 return NOMATCH; 48 return NOMATCH;
47 if ((info->bitmask & IP6T_PHYSDEV_OP_ISIN) && 49 if ((info->bitmask & XT_PHYSDEV_OP_ISIN) &&
48 !(info->invert & IP6T_PHYSDEV_OP_ISIN)) 50 !(info->invert & XT_PHYSDEV_OP_ISIN))
49 return NOMATCH; 51 return NOMATCH;
50 if ((info->bitmask & IP6T_PHYSDEV_OP_ISOUT) && 52 if ((info->bitmask & XT_PHYSDEV_OP_ISOUT) &&
51 !(info->invert & IP6T_PHYSDEV_OP_ISOUT)) 53 !(info->invert & XT_PHYSDEV_OP_ISOUT))
52 return NOMATCH; 54 return NOMATCH;
53 if ((info->bitmask & IP6T_PHYSDEV_OP_IN) && 55 if ((info->bitmask & XT_PHYSDEV_OP_IN) &&
54 !(info->invert & IP6T_PHYSDEV_OP_IN)) 56 !(info->invert & XT_PHYSDEV_OP_IN))
55 return NOMATCH; 57 return NOMATCH;
56 if ((info->bitmask & IP6T_PHYSDEV_OP_OUT) && 58 if ((info->bitmask & XT_PHYSDEV_OP_OUT) &&
57 !(info->invert & IP6T_PHYSDEV_OP_OUT)) 59 !(info->invert & XT_PHYSDEV_OP_OUT))
58 return NOMATCH; 60 return NOMATCH;
59 return MATCH; 61 return MATCH;
60 } 62 }
61 63
62 /* This only makes sense in the FORWARD and POSTROUTING chains */ 64 /* This only makes sense in the FORWARD and POSTROUTING chains */
63 if ((info->bitmask & IP6T_PHYSDEV_OP_BRIDGED) && 65 if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) &&
64 (!!(nf_bridge->mask & BRNF_BRIDGED) ^ 66 (!!(nf_bridge->mask & BRNF_BRIDGED) ^
65 !(info->invert & IP6T_PHYSDEV_OP_BRIDGED))) 67 !(info->invert & XT_PHYSDEV_OP_BRIDGED)))
66 return NOMATCH; 68 return NOMATCH;
67 69
68 if ((info->bitmask & IP6T_PHYSDEV_OP_ISIN && 70 if ((info->bitmask & XT_PHYSDEV_OP_ISIN &&
69 (!nf_bridge->physindev ^ !!(info->invert & IP6T_PHYSDEV_OP_ISIN))) || 71 (!nf_bridge->physindev ^ !!(info->invert & XT_PHYSDEV_OP_ISIN))) ||
70 (info->bitmask & IP6T_PHYSDEV_OP_ISOUT && 72 (info->bitmask & XT_PHYSDEV_OP_ISOUT &&
71 (!nf_bridge->physoutdev ^ !!(info->invert & IP6T_PHYSDEV_OP_ISOUT)))) 73 (!nf_bridge->physoutdev ^ !!(info->invert & XT_PHYSDEV_OP_ISOUT))))
72 return NOMATCH; 74 return NOMATCH;
73 75
74 if (!(info->bitmask & IP6T_PHYSDEV_OP_IN)) 76 if (!(info->bitmask & XT_PHYSDEV_OP_IN))
75 goto match_outdev; 77 goto match_outdev;
76 indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname; 78 indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname;
77 for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) { 79 for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) {
@@ -80,11 +82,11 @@ match(const struct sk_buff *skb,
80 & ((const unsigned int *)info->in_mask)[i]; 82 & ((const unsigned int *)info->in_mask)[i];
81 } 83 }
82 84
83 if ((ret == 0) ^ !(info->invert & IP6T_PHYSDEV_OP_IN)) 85 if ((ret == 0) ^ !(info->invert & XT_PHYSDEV_OP_IN))
84 return NOMATCH; 86 return NOMATCH;
85 87
86match_outdev: 88match_outdev:
87 if (!(info->bitmask & IP6T_PHYSDEV_OP_OUT)) 89 if (!(info->bitmask & XT_PHYSDEV_OP_OUT))
88 return MATCH; 90 return MATCH;
89 outdev = nf_bridge->physoutdev ? 91 outdev = nf_bridge->physoutdev ?
90 nf_bridge->physoutdev->name : nulldevname; 92 nf_bridge->physoutdev->name : nulldevname;
@@ -94,27 +96,34 @@ match_outdev:
94 & ((const unsigned int *)info->out_mask)[i]; 96 & ((const unsigned int *)info->out_mask)[i];
95 } 97 }
96 98
97 return (ret != 0) ^ !(info->invert & IP6T_PHYSDEV_OP_OUT); 99 return (ret != 0) ^ !(info->invert & XT_PHYSDEV_OP_OUT);
98} 100}
99 101
100static int 102static int
101checkentry(const char *tablename, 103checkentry(const char *tablename,
102 const struct ip6t_ip6 *ip, 104 const void *ip,
103 void *matchinfo, 105 void *matchinfo,
104 unsigned int matchsize, 106 unsigned int matchsize,
105 unsigned int hook_mask) 107 unsigned int hook_mask)
106{ 108{
107 const struct ip6t_physdev_info *info = matchinfo; 109 const struct xt_physdev_info *info = matchinfo;
108 110
109 if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_physdev_info))) 111 if (matchsize != XT_ALIGN(sizeof(struct xt_physdev_info)))
110 return 0; 112 return 0;
111 if (!(info->bitmask & IP6T_PHYSDEV_OP_MASK) || 113 if (!(info->bitmask & XT_PHYSDEV_OP_MASK) ||
112 info->bitmask & ~IP6T_PHYSDEV_OP_MASK) 114 info->bitmask & ~XT_PHYSDEV_OP_MASK)
113 return 0; 115 return 0;
114 return 1; 116 return 1;
115} 117}
116 118
117static struct ip6t_match physdev_match = { 119static struct xt_match physdev_match = {
120 .name = "physdev",
121 .match = &match,
122 .checkentry = &checkentry,
123 .me = THIS_MODULE,
124};
125
126static struct xt_match physdev6_match = {
118 .name = "physdev", 127 .name = "physdev",
119 .match = &match, 128 .match = &match,
120 .checkentry = &checkentry, 129 .checkentry = &checkentry,
@@ -123,12 +132,23 @@ static struct ip6t_match physdev_match = {
123 132
124static int __init init(void) 133static int __init init(void)
125{ 134{
126 return ip6t_register_match(&physdev_match); 135 int ret;
136
137 ret = xt_register_match(AF_INET, &physdev_match);
138 if (ret < 0)
139 return ret;
140
141 ret = xt_register_match(AF_INET6, &physdev6_match);
142 if (ret < 0)
143 xt_unregister_match(AF_INET, &physdev_match);
144
145 return ret;
127} 146}
128 147
129static void __exit fini(void) 148static void __exit fini(void)
130{ 149{
131 ip6t_unregister_match(&physdev_match); 150 xt_unregister_match(AF_INET, &physdev_match);
151 xt_unregister_match(AF_INET6, &physdev6_match);
132} 152}
133 153
134module_init(init); 154module_init(init);
diff --git a/net/ipv4/netfilter/ipt_pkttype.c b/net/netfilter/xt_pkttype.c
index 8ddb1dc5e5ae..ab1b2630f97d 100644
--- a/net/ipv4/netfilter/ipt_pkttype.c
+++ b/net/netfilter/xt_pkttype.c
@@ -10,60 +10,72 @@
10#include <linux/if_ether.h> 10#include <linux/if_ether.h>
11#include <linux/if_packet.h> 11#include <linux/if_packet.h>
12 12
13#include <linux/netfilter_ipv4/ipt_pkttype.h> 13#include <linux/netfilter/xt_pkttype.h>
14#include <linux/netfilter_ipv4/ip_tables.h> 14#include <linux/netfilter/x_tables.h>
15 15
16MODULE_LICENSE("GPL"); 16MODULE_LICENSE("GPL");
17MODULE_AUTHOR("Michal Ludvig <michal@logix.cz>"); 17MODULE_AUTHOR("Michal Ludvig <michal@logix.cz>");
18MODULE_DESCRIPTION("IP tables match to match on linklayer packet type"); 18MODULE_DESCRIPTION("IP tables match to match on linklayer packet type");
19MODULE_ALIAS("ipt_pkttype");
20MODULE_ALIAS("ip6t_pkttype");
19 21
20static int match(const struct sk_buff *skb, 22static int match(const struct sk_buff *skb,
21 const struct net_device *in, 23 const struct net_device *in,
22 const struct net_device *out, 24 const struct net_device *out,
23 const void *matchinfo, 25 const void *matchinfo,
24 int offset, 26 int offset,
27 unsigned int protoff,
25 int *hotdrop) 28 int *hotdrop)
26{ 29{
27 const struct ipt_pkttype_info *info = matchinfo; 30 const struct xt_pkttype_info *info = matchinfo;
28 31
29 return (skb->pkt_type == info->pkttype) ^ info->invert; 32 return (skb->pkt_type == info->pkttype) ^ info->invert;
30} 33}
31 34
32static int checkentry(const char *tablename, 35static int checkentry(const char *tablename,
33 const struct ipt_ip *ip, 36 const void *ip,
34 void *matchinfo, 37 void *matchinfo,
35 unsigned int matchsize, 38 unsigned int matchsize,
36 unsigned int hook_mask) 39 unsigned int hook_mask)
37{ 40{
38/* 41 if (matchsize != XT_ALIGN(sizeof(struct xt_pkttype_info)))
39 if (hook_mask
40 & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN)
41 | (1 << NF_IP_FORWARD))) {
42 printk("ipt_pkttype: only valid for PRE_ROUTING, LOCAL_IN or FORWARD.\n");
43 return 0;
44 }
45*/
46 if (matchsize != IPT_ALIGN(sizeof(struct ipt_pkttype_info)))
47 return 0; 42 return 0;
48 43
49 return 1; 44 return 1;
50} 45}
51 46
52static struct ipt_match pkttype_match = { 47static struct xt_match pkttype_match = {
53 .name = "pkttype", 48 .name = "pkttype",
54 .match = &match, 49 .match = &match,
55 .checkentry = &checkentry, 50 .checkentry = &checkentry,
56 .me = THIS_MODULE, 51 .me = THIS_MODULE,
57}; 52};
53static struct xt_match pkttype6_match = {
54 .name = "pkttype",
55 .match = &match,
56 .checkentry = &checkentry,
57 .me = THIS_MODULE,
58};
59
58 60
59static int __init init(void) 61static int __init init(void)
60{ 62{
61 return ipt_register_match(&pkttype_match); 63 int ret;
64 ret = xt_register_match(AF_INET, &pkttype_match);
65 if (ret)
66 return ret;
67
68 ret = xt_register_match(AF_INET6, &pkttype6_match);
69 if (ret)
70 xt_unregister_match(AF_INET, &pkttype_match);
71
72 return ret;
62} 73}
63 74
64static void __exit fini(void) 75static void __exit fini(void)
65{ 76{
66 ipt_unregister_match(&pkttype_match); 77 xt_unregister_match(AF_INET, &pkttype_match);
78 xt_unregister_match(AF_INET6, &pkttype6_match);
67} 79}
68 80
69module_init(init); 81module_init(init);
diff --git a/net/ipv4/netfilter/ipt_realm.c b/net/netfilter/xt_realm.c
index 54a6897ebaa6..2b7e1781d34d 100644
--- a/net/ipv4/netfilter/ipt_realm.c
+++ b/net/netfilter/xt_realm.c
@@ -14,12 +14,14 @@
14#include <linux/netdevice.h> 14#include <linux/netdevice.h>
15#include <net/route.h> 15#include <net/route.h>
16 16
17#include <linux/netfilter_ipv4/ipt_realm.h> 17#include <linux/netfilter_ipv4.h>
18#include <linux/netfilter_ipv4/ip_tables.h> 18#include <linux/netfilter/xt_realm.h>
19#include <linux/netfilter/x_tables.h>
19 20
20MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>"); 21MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>");
21MODULE_LICENSE("GPL"); 22MODULE_LICENSE("GPL");
22MODULE_DESCRIPTION("iptables realm match"); 23MODULE_DESCRIPTION("X_tables realm match");
24MODULE_ALIAS("ipt_realm");
23 25
24static int 26static int
25match(const struct sk_buff *skb, 27match(const struct sk_buff *skb,
@@ -27,16 +29,17 @@ match(const struct sk_buff *skb,
27 const struct net_device *out, 29 const struct net_device *out,
28 const void *matchinfo, 30 const void *matchinfo,
29 int offset, 31 int offset,
32 unsigned int protoff,
30 int *hotdrop) 33 int *hotdrop)
31{ 34{
32 const struct ipt_realm_info *info = matchinfo; 35 const struct xt_realm_info *info = matchinfo;
33 struct dst_entry *dst = skb->dst; 36 struct dst_entry *dst = skb->dst;
34 37
35 return (info->id == (dst->tclassid & info->mask)) ^ info->invert; 38 return (info->id == (dst->tclassid & info->mask)) ^ info->invert;
36} 39}
37 40
38static int check(const char *tablename, 41static int check(const char *tablename,
39 const struct ipt_ip *ip, 42 const void *ip,
40 void *matchinfo, 43 void *matchinfo,
41 unsigned int matchsize, 44 unsigned int matchsize,
42 unsigned int hook_mask) 45 unsigned int hook_mask)
@@ -44,18 +47,18 @@ static int check(const char *tablename,
44 if (hook_mask 47 if (hook_mask
45 & ~((1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) | 48 & ~((1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) |
46 (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_LOCAL_IN))) { 49 (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_LOCAL_IN))) {
47 printk("ipt_realm: only valid for POST_ROUTING, LOCAL_OUT, " 50 printk("xt_realm: only valid for POST_ROUTING, LOCAL_OUT, "
48 "LOCAL_IN or FORWARD.\n"); 51 "LOCAL_IN or FORWARD.\n");
49 return 0; 52 return 0;
50 } 53 }
51 if (matchsize != IPT_ALIGN(sizeof(struct ipt_realm_info))) { 54 if (matchsize != XT_ALIGN(sizeof(struct xt_realm_info))) {
52 printk("ipt_realm: invalid matchsize.\n"); 55 printk("xt_realm: invalid matchsize.\n");
53 return 0; 56 return 0;
54 } 57 }
55 return 1; 58 return 1;
56} 59}
57 60
58static struct ipt_match realm_match = { 61static struct xt_match realm_match = {
59 .name = "realm", 62 .name = "realm",
60 .match = match, 63 .match = match,
61 .checkentry = check, 64 .checkentry = check,
@@ -64,12 +67,12 @@ static struct ipt_match realm_match = {
64 67
65static int __init init(void) 68static int __init init(void)
66{ 69{
67 return ipt_register_match(&realm_match); 70 return xt_register_match(AF_INET, &realm_match);
68} 71}
69 72
70static void __exit fini(void) 73static void __exit fini(void)
71{ 74{
72 ipt_unregister_match(&realm_match); 75 xt_unregister_match(AF_INET, &realm_match);
73} 76}
74 77
75module_init(init); 78module_init(init);
diff --git a/net/ipv4/netfilter/ipt_sctp.c b/net/netfilter/xt_sctp.c
index fe2b327bcaa4..10fbfc5ba758 100644
--- a/net/ipv4/netfilter/ipt_sctp.c
+++ b/net/netfilter/xt_sctp.c
@@ -1,10 +1,18 @@
1#include <linux/module.h> 1#include <linux/module.h>
2#include <linux/skbuff.h> 2#include <linux/skbuff.h>
3#include <net/ip.h> 3#include <net/ip.h>
4#include <net/ipv6.h>
4#include <linux/sctp.h> 5#include <linux/sctp.h>
5 6
7#include <linux/netfilter/x_tables.h>
8#include <linux/netfilter/xt_sctp.h>
6#include <linux/netfilter_ipv4/ip_tables.h> 9#include <linux/netfilter_ipv4/ip_tables.h>
7#include <linux/netfilter_ipv4/ipt_sctp.h> 10#include <linux/netfilter_ipv6/ip6_tables.h>
11
12MODULE_LICENSE("GPL");
13MODULE_AUTHOR("Kiran Kumar Immidi");
14MODULE_DESCRIPTION("Match for SCTP protocol packets");
15MODULE_ALIAS("ipt_sctp");
8 16
9#ifdef DEBUG_SCTP 17#ifdef DEBUG_SCTP
10#define duprintf(format, args...) printk(format , ## args) 18#define duprintf(format, args...) printk(format , ## args)
@@ -16,7 +24,7 @@
16 || (!!((invflag) & (option)) ^ (cond))) 24 || (!!((invflag) & (option)) ^ (cond)))
17 25
18static int 26static int
19match_flags(const struct ipt_sctp_flag_info *flag_info, 27match_flags(const struct xt_sctp_flag_info *flag_info,
20 const int flag_count, 28 const int flag_count,
21 u_int8_t chunktype, 29 u_int8_t chunktype,
22 u_int8_t chunkflags) 30 u_int8_t chunkflags)
@@ -32,15 +40,15 @@ match_flags(const struct ipt_sctp_flag_info *flag_info,
32 return 1; 40 return 1;
33} 41}
34 42
35static int 43static inline int
36match_packet(const struct sk_buff *skb, 44match_packet(const struct sk_buff *skb,
45 unsigned int offset,
37 const u_int32_t *chunkmap, 46 const u_int32_t *chunkmap,
38 int chunk_match_type, 47 int chunk_match_type,
39 const struct ipt_sctp_flag_info *flag_info, 48 const struct xt_sctp_flag_info *flag_info,
40 const int flag_count, 49 const int flag_count,
41 int *hotdrop) 50 int *hotdrop)
42{ 51{
43 int offset;
44 u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)]; 52 u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)];
45 sctp_chunkhdr_t _sch, *sch; 53 sctp_chunkhdr_t _sch, *sch;
46 54
@@ -52,7 +60,6 @@ match_packet(const struct sk_buff *skb,
52 SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap); 60 SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap);
53 } 61 }
54 62
55 offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t);
56 do { 63 do {
57 sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch); 64 sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch);
58 if (sch == NULL) { 65 if (sch == NULL) {
@@ -118,19 +125,20 @@ match(const struct sk_buff *skb,
118 const struct net_device *out, 125 const struct net_device *out,
119 const void *matchinfo, 126 const void *matchinfo,
120 int offset, 127 int offset,
128 unsigned int protoff,
121 int *hotdrop) 129 int *hotdrop)
122{ 130{
123 const struct ipt_sctp_info *info; 131 const struct xt_sctp_info *info;
124 sctp_sctphdr_t _sh, *sh; 132 sctp_sctphdr_t _sh, *sh;
125 133
126 info = (const struct ipt_sctp_info *)matchinfo; 134 info = (const struct xt_sctp_info *)matchinfo;
127 135
128 if (offset) { 136 if (offset) {
129 duprintf("Dropping non-first fragment.. FIXME\n"); 137 duprintf("Dropping non-first fragment.. FIXME\n");
130 return 0; 138 return 0;
131 } 139 }
132 140
133 sh = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_sh), &_sh); 141 sh = skb_header_pointer(skb, protoff, sizeof(_sh), &_sh);
134 if (sh == NULL) { 142 if (sh == NULL) {
135 duprintf("Dropping evil TCP offset=0 tinygram.\n"); 143 duprintf("Dropping evil TCP offset=0 tinygram.\n");
136 *hotdrop = 1; 144 *hotdrop = 1;
@@ -140,64 +148,103 @@ match(const struct sk_buff *skb,
140 148
141 return SCCHECK(((ntohs(sh->source) >= info->spts[0]) 149 return SCCHECK(((ntohs(sh->source) >= info->spts[0])
142 && (ntohs(sh->source) <= info->spts[1])), 150 && (ntohs(sh->source) <= info->spts[1])),
143 IPT_SCTP_SRC_PORTS, info->flags, info->invflags) 151 XT_SCTP_SRC_PORTS, info->flags, info->invflags)
144 && SCCHECK(((ntohs(sh->dest) >= info->dpts[0]) 152 && SCCHECK(((ntohs(sh->dest) >= info->dpts[0])
145 && (ntohs(sh->dest) <= info->dpts[1])), 153 && (ntohs(sh->dest) <= info->dpts[1])),
146 IPT_SCTP_DEST_PORTS, info->flags, info->invflags) 154 XT_SCTP_DEST_PORTS, info->flags, info->invflags)
147 && SCCHECK(match_packet(skb, info->chunkmap, info->chunk_match_type, 155 && SCCHECK(match_packet(skb, protoff,
156 info->chunkmap, info->chunk_match_type,
148 info->flag_info, info->flag_count, 157 info->flag_info, info->flag_count,
149 hotdrop), 158 hotdrop),
150 IPT_SCTP_CHUNK_TYPES, info->flags, info->invflags); 159 XT_SCTP_CHUNK_TYPES, info->flags, info->invflags);
151} 160}
152 161
153static int 162static int
154checkentry(const char *tablename, 163checkentry(const char *tablename,
155 const struct ipt_ip *ip, 164 const void *inf,
165 void *matchinfo,
166 unsigned int matchsize,
167 unsigned int hook_mask)
168{
169 const struct xt_sctp_info *info;
170 const struct ipt_ip *ip = inf;
171
172 info = (const struct xt_sctp_info *)matchinfo;
173
174 return ip->proto == IPPROTO_SCTP
175 && !(ip->invflags & XT_INV_PROTO)
176 && matchsize == XT_ALIGN(sizeof(struct xt_sctp_info))
177 && !(info->flags & ~XT_SCTP_VALID_FLAGS)
178 && !(info->invflags & ~XT_SCTP_VALID_FLAGS)
179 && !(info->invflags & ~info->flags)
180 && ((!(info->flags & XT_SCTP_CHUNK_TYPES)) ||
181 (info->chunk_match_type &
182 (SCTP_CHUNK_MATCH_ALL
183 | SCTP_CHUNK_MATCH_ANY
184 | SCTP_CHUNK_MATCH_ONLY)));
185}
186
187static int
188checkentry6(const char *tablename,
189 const void *inf,
156 void *matchinfo, 190 void *matchinfo,
157 unsigned int matchsize, 191 unsigned int matchsize,
158 unsigned int hook_mask) 192 unsigned int hook_mask)
159{ 193{
160 const struct ipt_sctp_info *info; 194 const struct xt_sctp_info *info;
195 const struct ip6t_ip6 *ip = inf;
161 196
162 info = (const struct ipt_sctp_info *)matchinfo; 197 info = (const struct xt_sctp_info *)matchinfo;
163 198
164 return ip->proto == IPPROTO_SCTP 199 return ip->proto == IPPROTO_SCTP
165 && !(ip->invflags & IPT_INV_PROTO) 200 && !(ip->invflags & XT_INV_PROTO)
166 && matchsize == IPT_ALIGN(sizeof(struct ipt_sctp_info)) 201 && matchsize == XT_ALIGN(sizeof(struct xt_sctp_info))
167 && !(info->flags & ~IPT_SCTP_VALID_FLAGS) 202 && !(info->flags & ~XT_SCTP_VALID_FLAGS)
168 && !(info->invflags & ~IPT_SCTP_VALID_FLAGS) 203 && !(info->invflags & ~XT_SCTP_VALID_FLAGS)
169 && !(info->invflags & ~info->flags) 204 && !(info->invflags & ~info->flags)
170 && ((!(info->flags & IPT_SCTP_CHUNK_TYPES)) || 205 && ((!(info->flags & XT_SCTP_CHUNK_TYPES)) ||
171 (info->chunk_match_type & 206 (info->chunk_match_type &
172 (SCTP_CHUNK_MATCH_ALL 207 (SCTP_CHUNK_MATCH_ALL
173 | SCTP_CHUNK_MATCH_ANY 208 | SCTP_CHUNK_MATCH_ANY
174 | SCTP_CHUNK_MATCH_ONLY))); 209 | SCTP_CHUNK_MATCH_ONLY)));
175} 210}
176 211
177static struct ipt_match sctp_match = 212
213static struct xt_match sctp_match =
178{ 214{
179 .list = { NULL, NULL},
180 .name = "sctp", 215 .name = "sctp",
181 .match = &match, 216 .match = &match,
182 .checkentry = &checkentry, 217 .checkentry = &checkentry,
183 .destroy = NULL, 218 .me = THIS_MODULE
219};
220static struct xt_match sctp6_match =
221{
222 .name = "sctp",
223 .match = &match,
224 .checkentry = &checkentry6,
184 .me = THIS_MODULE 225 .me = THIS_MODULE
185}; 226};
186 227
228
187static int __init init(void) 229static int __init init(void)
188{ 230{
189 return ipt_register_match(&sctp_match); 231 int ret;
232 ret = xt_register_match(AF_INET, &sctp_match);
233 if (ret)
234 return ret;
235
236 ret = xt_register_match(AF_INET6, &sctp6_match);
237 if (ret)
238 xt_unregister_match(AF_INET, &sctp_match);
239
240 return ret;
190} 241}
191 242
192static void __exit fini(void) 243static void __exit fini(void)
193{ 244{
194 ipt_unregister_match(&sctp_match); 245 xt_unregister_match(AF_INET6, &sctp6_match);
246 xt_unregister_match(AF_INET, &sctp_match);
195} 247}
196 248
197module_init(init); 249module_init(init);
198module_exit(fini); 250module_exit(fini);
199
200MODULE_LICENSE("GPL");
201MODULE_AUTHOR("Kiran Kumar Immidi");
202MODULE_DESCRIPTION("Match for SCTP protocol packets");
203
diff --git a/net/ipv4/netfilter/ipt_state.c b/net/netfilter/xt_state.c
index 4d7f16b70cec..39ce808d40ef 100644
--- a/net/ipv4/netfilter/ipt_state.c
+++ b/net/netfilter/xt_state.c
@@ -1,7 +1,7 @@
1/* Kernel module to match connection tracking information. */ 1/* Kernel module to match connection tracking information. */
2 2
3/* (C) 1999-2001 Paul `Rusty' Russell 3/* (C) 1999-2001 Paul `Rusty' Russell
4 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> 4 * (C) 2002-2005 Netfilter Core Team <coreteam@netfilter.org>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as 7 * it under the terms of the GNU General Public License version 2 as
@@ -11,12 +11,14 @@
11#include <linux/module.h> 11#include <linux/module.h>
12#include <linux/skbuff.h> 12#include <linux/skbuff.h>
13#include <net/netfilter/nf_conntrack_compat.h> 13#include <net/netfilter/nf_conntrack_compat.h>
14#include <linux/netfilter_ipv4/ip_tables.h> 14#include <linux/netfilter/x_tables.h>
15#include <linux/netfilter_ipv4/ipt_state.h> 15#include <linux/netfilter/xt_state.h>
16 16
17MODULE_LICENSE("GPL"); 17MODULE_LICENSE("GPL");
18MODULE_AUTHOR("Rusty Russell <rusty@rustcorp.com.au>"); 18MODULE_AUTHOR("Rusty Russell <rusty@rustcorp.com.au>");
19MODULE_DESCRIPTION("iptables connection tracking state match module"); 19MODULE_DESCRIPTION("ip[6]_tables connection tracking state match module");
20MODULE_ALIAS("ipt_state");
21MODULE_ALIAS("ip6t_state");
20 22
21static int 23static int
22match(const struct sk_buff *skb, 24match(const struct sk_buff *skb,
@@ -24,35 +26,43 @@ match(const struct sk_buff *skb,
24 const struct net_device *out, 26 const struct net_device *out,
25 const void *matchinfo, 27 const void *matchinfo,
26 int offset, 28 int offset,
29 unsigned int protoff,
27 int *hotdrop) 30 int *hotdrop)
28{ 31{
29 const struct ipt_state_info *sinfo = matchinfo; 32 const struct xt_state_info *sinfo = matchinfo;
30 enum ip_conntrack_info ctinfo; 33 enum ip_conntrack_info ctinfo;
31 unsigned int statebit; 34 unsigned int statebit;
32 35
33 if (nf_ct_is_untracked(skb)) 36 if (nf_ct_is_untracked(skb))
34 statebit = IPT_STATE_UNTRACKED; 37 statebit = XT_STATE_UNTRACKED;
35 else if (!nf_ct_get_ctinfo(skb, &ctinfo)) 38 else if (!nf_ct_get_ctinfo(skb, &ctinfo))
36 statebit = IPT_STATE_INVALID; 39 statebit = XT_STATE_INVALID;
37 else 40 else
38 statebit = IPT_STATE_BIT(ctinfo); 41 statebit = XT_STATE_BIT(ctinfo);
39 42
40 return (sinfo->statemask & statebit); 43 return (sinfo->statemask & statebit);
41} 44}
42 45
43static int check(const char *tablename, 46static int check(const char *tablename,
44 const struct ipt_ip *ip, 47 const void *ip,
45 void *matchinfo, 48 void *matchinfo,
46 unsigned int matchsize, 49 unsigned int matchsize,
47 unsigned int hook_mask) 50 unsigned int hook_mask)
48{ 51{
49 if (matchsize != IPT_ALIGN(sizeof(struct ipt_state_info))) 52 if (matchsize != XT_ALIGN(sizeof(struct xt_state_info)))
50 return 0; 53 return 0;
51 54
52 return 1; 55 return 1;
53} 56}
54 57
55static struct ipt_match state_match = { 58static struct xt_match state_match = {
59 .name = "state",
60 .match = &match,
61 .checkentry = &check,
62 .me = THIS_MODULE,
63};
64
65static struct xt_match state6_match = {
56 .name = "state", 66 .name = "state",
57 .match = &match, 67 .match = &match,
58 .checkentry = &check, 68 .checkentry = &check,
@@ -61,13 +71,25 @@ static struct ipt_match state_match = {
61 71
62static int __init init(void) 72static int __init init(void)
63{ 73{
64 need_ip_conntrack(); 74 int ret;
65 return ipt_register_match(&state_match); 75
76 need_conntrack();
77
78 ret = xt_register_match(AF_INET, &state_match);
79 if (ret < 0)
80 return ret;
81
82 ret = xt_register_match(AF_INET6, &state6_match);
83 if (ret < 0)
84 xt_unregister_match(AF_INET,&state_match);
85
86 return ret;
66} 87}
67 88
68static void __exit fini(void) 89static void __exit fini(void)
69{ 90{
70 ipt_unregister_match(&state_match); 91 xt_unregister_match(AF_INET, &state_match);
92 xt_unregister_match(AF_INET6, &state6_match);
71} 93}
72 94
73module_init(init); 95module_init(init);
diff --git a/net/ipv4/netfilter/ipt_string.c b/net/netfilter/xt_string.c
index b5def204d798..7c7d5c8807d6 100644
--- a/net/ipv4/netfilter/ipt_string.c
+++ b/net/netfilter/xt_string.c
@@ -11,23 +11,26 @@
11#include <linux/module.h> 11#include <linux/module.h>
12#include <linux/kernel.h> 12#include <linux/kernel.h>
13#include <linux/skbuff.h> 13#include <linux/skbuff.h>
14#include <linux/netfilter_ipv4/ip_tables.h> 14#include <linux/netfilter/x_tables.h>
15#include <linux/netfilter_ipv4/ipt_string.h> 15#include <linux/netfilter/xt_string.h>
16#include <linux/textsearch.h> 16#include <linux/textsearch.h>
17 17
18MODULE_AUTHOR("Pablo Neira Ayuso <pablo@eurodev.net>"); 18MODULE_AUTHOR("Pablo Neira Ayuso <pablo@eurodev.net>");
19MODULE_DESCRIPTION("IP tables string match module"); 19MODULE_DESCRIPTION("IP tables string match module");
20MODULE_LICENSE("GPL"); 20MODULE_LICENSE("GPL");
21MODULE_ALIAS("ipt_string");
22MODULE_ALIAS("ip6t_string");
21 23
22static int match(const struct sk_buff *skb, 24static int match(const struct sk_buff *skb,
23 const struct net_device *in, 25 const struct net_device *in,
24 const struct net_device *out, 26 const struct net_device *out,
25 const void *matchinfo, 27 const void *matchinfo,
26 int offset, 28 int offset,
29 unsigned int protoff,
27 int *hotdrop) 30 int *hotdrop)
28{ 31{
29 struct ts_state state; 32 struct ts_state state;
30 struct ipt_string_info *conf = (struct ipt_string_info *) matchinfo; 33 struct xt_string_info *conf = (struct xt_string_info *) matchinfo;
31 34
32 memset(&state, 0, sizeof(struct ts_state)); 35 memset(&state, 0, sizeof(struct ts_state));
33 36
@@ -36,18 +39,18 @@ static int match(const struct sk_buff *skb,
36 != UINT_MAX) && !conf->invert; 39 != UINT_MAX) && !conf->invert;
37} 40}
38 41
39#define STRING_TEXT_PRIV(m) ((struct ipt_string_info *) m) 42#define STRING_TEXT_PRIV(m) ((struct xt_string_info *) m)
40 43
41static int checkentry(const char *tablename, 44static int checkentry(const char *tablename,
42 const struct ipt_ip *ip, 45 const void *ip,
43 void *matchinfo, 46 void *matchinfo,
44 unsigned int matchsize, 47 unsigned int matchsize,
45 unsigned int hook_mask) 48 unsigned int hook_mask)
46{ 49{
47 struct ipt_string_info *conf = matchinfo; 50 struct xt_string_info *conf = matchinfo;
48 struct ts_config *ts_conf; 51 struct ts_config *ts_conf;
49 52
50 if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info))) 53 if (matchsize != XT_ALIGN(sizeof(struct xt_string_info)))
51 return 0; 54 return 0;
52 55
53 /* Damn, can't handle this case properly with iptables... */ 56 /* Damn, can't handle this case properly with iptables... */
@@ -69,7 +72,14 @@ static void destroy(void *matchinfo, unsigned int matchsize)
69 textsearch_destroy(STRING_TEXT_PRIV(matchinfo)->config); 72 textsearch_destroy(STRING_TEXT_PRIV(matchinfo)->config);
70} 73}
71 74
72static struct ipt_match string_match = { 75static struct xt_match string_match = {
76 .name = "string",
77 .match = match,
78 .checkentry = checkentry,
79 .destroy = destroy,
80 .me = THIS_MODULE
81};
82static struct xt_match string6_match = {
73 .name = "string", 83 .name = "string",
74 .match = match, 84 .match = match,
75 .checkentry = checkentry, 85 .checkentry = checkentry,
@@ -79,12 +89,22 @@ static struct ipt_match string_match = {
79 89
80static int __init init(void) 90static int __init init(void)
81{ 91{
82 return ipt_register_match(&string_match); 92 int ret;
93
94 ret = xt_register_match(AF_INET, &string_match);
95 if (ret)
96 return ret;
97 ret = xt_register_match(AF_INET6, &string6_match);
98 if (ret)
99 xt_unregister_match(AF_INET, &string_match);
100
101 return ret;
83} 102}
84 103
85static void __exit fini(void) 104static void __exit fini(void)
86{ 105{
87 ipt_unregister_match(&string_match); 106 xt_unregister_match(AF_INET, &string_match);
107 xt_unregister_match(AF_INET6, &string6_match);
88} 108}
89 109
90module_init(init); 110module_init(init);
diff --git a/net/ipv4/netfilter/ipt_tcpmss.c b/net/netfilter/xt_tcpmss.c
index 4dc9b16ab4a3..acf7f533e9f1 100644
--- a/net/ipv4/netfilter/ipt_tcpmss.c
+++ b/net/netfilter/xt_tcpmss.c
@@ -1,6 +1,7 @@
1/* Kernel module to match TCP MSS values. */ 1/* Kernel module to match TCP MSS values. */
2 2
3/* Copyright (C) 2000 Marc Boucher <marc@mbsi.ca> 3/* Copyright (C) 2000 Marc Boucher <marc@mbsi.ca>
4 * Portions (C) 2005 by Harald Welte <laforge@netfilter.org>
4 * 5 *
5 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as 7 * it under the terms of the GNU General Public License version 2 as
@@ -11,19 +12,24 @@
11#include <linux/skbuff.h> 12#include <linux/skbuff.h>
12#include <net/tcp.h> 13#include <net/tcp.h>
13 14
14#include <linux/netfilter_ipv4/ipt_tcpmss.h> 15#include <linux/netfilter/xt_tcpmss.h>
16#include <linux/netfilter/x_tables.h>
17
15#include <linux/netfilter_ipv4/ip_tables.h> 18#include <linux/netfilter_ipv4/ip_tables.h>
19#include <linux/netfilter_ipv6/ip6_tables.h>
16 20
17#define TH_SYN 0x02 21#define TH_SYN 0x02
18 22
19MODULE_LICENSE("GPL"); 23MODULE_LICENSE("GPL");
20MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); 24MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
21MODULE_DESCRIPTION("iptables TCP MSS match module"); 25MODULE_DESCRIPTION("iptables TCP MSS match module");
26MODULE_ALIAS("ipt_tcpmss");
22 27
23/* Returns 1 if the mss option is set and matched by the range, 0 otherwise */ 28/* Returns 1 if the mss option is set and matched by the range, 0 otherwise */
24static inline int 29static inline int
25mssoption_match(u_int16_t min, u_int16_t max, 30mssoption_match(u_int16_t min, u_int16_t max,
26 const struct sk_buff *skb, 31 const struct sk_buff *skb,
32 unsigned int protoff,
27 int invert, 33 int invert,
28 int *hotdrop) 34 int *hotdrop)
29{ 35{
@@ -33,8 +39,7 @@ mssoption_match(u_int16_t min, u_int16_t max,
33 unsigned int i, optlen; 39 unsigned int i, optlen;
34 40
35 /* If we don't have the whole header, drop packet. */ 41 /* If we don't have the whole header, drop packet. */
36 th = skb_header_pointer(skb, skb->nh.iph->ihl * 4, 42 th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
37 sizeof(_tcph), &_tcph);
38 if (th == NULL) 43 if (th == NULL)
39 goto dropit; 44 goto dropit;
40 45
@@ -47,8 +52,7 @@ mssoption_match(u_int16_t min, u_int16_t max,
47 goto out; 52 goto out;
48 53
49 /* Truncated options. */ 54 /* Truncated options. */
50 op = skb_header_pointer(skb, skb->nh.iph->ihl * 4 + sizeof(*th), 55 op = skb_header_pointer(skb, protoff + sizeof(*th), optlen, _opt);
51 optlen, _opt);
52 if (op == NULL) 56 if (op == NULL)
53 goto dropit; 57 goto dropit;
54 58
@@ -79,22 +83,24 @@ match(const struct sk_buff *skb,
79 const struct net_device *out, 83 const struct net_device *out,
80 const void *matchinfo, 84 const void *matchinfo,
81 int offset, 85 int offset,
86 unsigned int protoff,
82 int *hotdrop) 87 int *hotdrop)
83{ 88{
84 const struct ipt_tcpmss_match_info *info = matchinfo; 89 const struct xt_tcpmss_match_info *info = matchinfo;
85 90
86 return mssoption_match(info->mss_min, info->mss_max, skb, 91 return mssoption_match(info->mss_min, info->mss_max, skb, protoff,
87 info->invert, hotdrop); 92 info->invert, hotdrop);
88} 93}
89 94
90static int 95static int
91checkentry(const char *tablename, 96checkentry(const char *tablename,
92 const struct ipt_ip *ip, 97 const void *ipinfo,
93 void *matchinfo, 98 void *matchinfo,
94 unsigned int matchsize, 99 unsigned int matchsize,
95 unsigned int hook_mask) 100 unsigned int hook_mask)
96{ 101{
97 if (matchsize != IPT_ALIGN(sizeof(struct ipt_tcpmss_match_info))) 102 const struct ipt_ip *ip = ipinfo;
103 if (matchsize != XT_ALIGN(sizeof(struct xt_tcpmss_match_info)))
98 return 0; 104 return 0;
99 105
100 /* Must specify -p tcp */ 106 /* Must specify -p tcp */
@@ -106,21 +112,60 @@ checkentry(const char *tablename,
106 return 1; 112 return 1;
107} 113}
108 114
109static struct ipt_match tcpmss_match = { 115static int
116checkentry6(const char *tablename,
117 const void *ipinfo,
118 void *matchinfo,
119 unsigned int matchsize,
120 unsigned int hook_mask)
121{
122 const struct ip6t_ip6 *ip = ipinfo;
123
124 if (matchsize != XT_ALIGN(sizeof(struct xt_tcpmss_match_info)))
125 return 0;
126
127 /* Must specify -p tcp */
128 if (ip->proto != IPPROTO_TCP || (ip->invflags & XT_INV_PROTO)) {
129 printk("tcpmss: Only works on TCP packets\n");
130 return 0;
131 }
132
133 return 1;
134}
135
136static struct xt_match tcpmss_match = {
110 .name = "tcpmss", 137 .name = "tcpmss",
111 .match = &match, 138 .match = &match,
112 .checkentry = &checkentry, 139 .checkentry = &checkentry,
113 .me = THIS_MODULE, 140 .me = THIS_MODULE,
114}; 141};
115 142
143static struct xt_match tcpmss6_match = {
144 .name = "tcpmss",
145 .match = &match,
146 .checkentry = &checkentry6,
147 .me = THIS_MODULE,
148};
149
150
116static int __init init(void) 151static int __init init(void)
117{ 152{
118 return ipt_register_match(&tcpmss_match); 153 int ret;
154 ret = xt_register_match(AF_INET, &tcpmss_match);
155 if (ret)
156 return ret;
157
158 ret = xt_register_match(AF_INET6, &tcpmss6_match);
159 if (ret)
160 xt_unregister_match(AF_INET, &tcpmss_match);
161
162 return ret;
119} 163}
120 164
121static void __exit fini(void) 165static void __exit fini(void)
122{ 166{
123 ipt_unregister_match(&tcpmss_match); 167 xt_unregister_match(AF_INET6, &tcpmss6_match);
168 xt_unregister_match(AF_INET, &tcpmss_match);
124} 169}
125 170
126module_init(init); 171module_init(init);
diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c
new file mode 100644
index 000000000000..669c8113cc60
--- /dev/null
+++ b/net/netfilter/xt_tcpudp.c
@@ -0,0 +1,334 @@
1#include <linux/types.h>
2#include <linux/module.h>
3#include <net/ip.h>
4#include <linux/ipv6.h>
5#include <net/ipv6.h>
6#include <net/tcp.h>
7#include <net/udp.h>
8#include <linux/netfilter/x_tables.h>
9#include <linux/netfilter/xt_tcpudp.h>
10#include <linux/netfilter_ipv4/ip_tables.h>
11#include <linux/netfilter_ipv6/ip6_tables.h>
12
13MODULE_DESCRIPTION("x_tables match for TCP and UDP, supports IPv4 and IPv6");
14MODULE_LICENSE("GPL");
15MODULE_ALIAS("xt_tcp");
16MODULE_ALIAS("xt_udp");
17MODULE_ALIAS("ipt_udp");
18MODULE_ALIAS("ipt_tcp");
19MODULE_ALIAS("ip6t_udp");
20MODULE_ALIAS("ip6t_tcp");
21
22#ifdef DEBUG_IP_FIREWALL_USER
23#define duprintf(format, args...) printk(format , ## args)
24#else
25#define duprintf(format, args...)
26#endif
27
28
29/* Returns 1 if the port is matched by the range, 0 otherwise */
30static inline int
31port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert)
32{
33 int ret;
34
35 ret = (port >= min && port <= max) ^ invert;
36 return ret;
37}
38
39static int
40tcp_find_option(u_int8_t option,
41 const struct sk_buff *skb,
42 unsigned int protoff,
43 unsigned int optlen,
44 int invert,
45 int *hotdrop)
46{
47 /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
48 u_int8_t _opt[60 - sizeof(struct tcphdr)], *op;
49 unsigned int i;
50
51 duprintf("tcp_match: finding option\n");
52
53 if (!optlen)
54 return invert;
55
56 /* If we don't have the whole header, drop packet. */
57 op = skb_header_pointer(skb, protoff + sizeof(struct tcphdr),
58 optlen, _opt);
59 if (op == NULL) {
60 *hotdrop = 1;
61 return 0;
62 }
63
64 for (i = 0; i < optlen; ) {
65 if (op[i] == option) return !invert;
66 if (op[i] < 2) i++;
67 else i += op[i+1]?:1;
68 }
69
70 return invert;
71}
72
73static int
74tcp_match(const struct sk_buff *skb,
75 const struct net_device *in,
76 const struct net_device *out,
77 const void *matchinfo,
78 int offset,
79 unsigned int protoff,
80 int *hotdrop)
81{
82 struct tcphdr _tcph, *th;
83 const struct xt_tcp *tcpinfo = matchinfo;
84
85 if (offset) {
86 /* To quote Alan:
87
88 Don't allow a fragment of TCP 8 bytes in. Nobody normal
89 causes this. Its a cracker trying to break in by doing a
90 flag overwrite to pass the direction checks.
91 */
92 if (offset == 1) {
93 duprintf("Dropping evil TCP offset=1 frag.\n");
94 *hotdrop = 1;
95 }
96 /* Must not be a fragment. */
97 return 0;
98 }
99
100#define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg))
101
102 th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
103 if (th == NULL) {
104 /* We've been asked to examine this packet, and we
105 can't. Hence, no choice but to drop. */
106 duprintf("Dropping evil TCP offset=0 tinygram.\n");
107 *hotdrop = 1;
108 return 0;
109 }
110
111 if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1],
112 ntohs(th->source),
113 !!(tcpinfo->invflags & XT_TCP_INV_SRCPT)))
114 return 0;
115 if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1],
116 ntohs(th->dest),
117 !!(tcpinfo->invflags & XT_TCP_INV_DSTPT)))
118 return 0;
119 if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask)
120 == tcpinfo->flg_cmp,
121 XT_TCP_INV_FLAGS))
122 return 0;
123 if (tcpinfo->option) {
124 if (th->doff * 4 < sizeof(_tcph)) {
125 *hotdrop = 1;
126 return 0;
127 }
128 if (!tcp_find_option(tcpinfo->option, skb, protoff,
129 th->doff*4 - sizeof(_tcph),
130 tcpinfo->invflags & XT_TCP_INV_OPTION,
131 hotdrop))
132 return 0;
133 }
134 return 1;
135}
136
137/* Called when user tries to insert an entry of this type. */
138static int
139tcp_checkentry(const char *tablename,
140 const void *info,
141 void *matchinfo,
142 unsigned int matchsize,
143 unsigned int hook_mask)
144{
145 const struct ipt_ip *ip = info;
146 const struct xt_tcp *tcpinfo = matchinfo;
147
148 /* Must specify proto == TCP, and no unknown invflags */
149 return ip->proto == IPPROTO_TCP
150 && !(ip->invflags & XT_INV_PROTO)
151 && matchsize == XT_ALIGN(sizeof(struct xt_tcp))
152 && !(tcpinfo->invflags & ~XT_TCP_INV_MASK);
153}
154
155/* Called when user tries to insert an entry of this type. */
156static int
157tcp6_checkentry(const char *tablename,
158 const void *entry,
159 void *matchinfo,
160 unsigned int matchsize,
161 unsigned int hook_mask)
162{
163 const struct ip6t_ip6 *ipv6 = entry;
164 const struct xt_tcp *tcpinfo = matchinfo;
165
166 /* Must specify proto == TCP, and no unknown invflags */
167 return ipv6->proto == IPPROTO_TCP
168 && !(ipv6->invflags & XT_INV_PROTO)
169 && matchsize == XT_ALIGN(sizeof(struct xt_tcp))
170 && !(tcpinfo->invflags & ~XT_TCP_INV_MASK);
171}
172
173
174static int
175udp_match(const struct sk_buff *skb,
176 const struct net_device *in,
177 const struct net_device *out,
178 const void *matchinfo,
179 int offset,
180 unsigned int protoff,
181 int *hotdrop)
182{
183 struct udphdr _udph, *uh;
184 const struct xt_udp *udpinfo = matchinfo;
185
186 /* Must not be a fragment. */
187 if (offset)
188 return 0;
189
190 uh = skb_header_pointer(skb, protoff, sizeof(_udph), &_udph);
191 if (uh == NULL) {
192 /* We've been asked to examine this packet, and we
193 can't. Hence, no choice but to drop. */
194 duprintf("Dropping evil UDP tinygram.\n");
195 *hotdrop = 1;
196 return 0;
197 }
198
199 return port_match(udpinfo->spts[0], udpinfo->spts[1],
200 ntohs(uh->source),
201 !!(udpinfo->invflags & XT_UDP_INV_SRCPT))
202 && port_match(udpinfo->dpts[0], udpinfo->dpts[1],
203 ntohs(uh->dest),
204 !!(udpinfo->invflags & XT_UDP_INV_DSTPT));
205}
206
207/* Called when user tries to insert an entry of this type. */
208static int
209udp_checkentry(const char *tablename,
210 const void *info,
211 void *matchinfo,
212 unsigned int matchinfosize,
213 unsigned int hook_mask)
214{
215 const struct ipt_ip *ip = info;
216 const struct xt_udp *udpinfo = matchinfo;
217
218 /* Must specify proto == UDP, and no unknown invflags */
219 if (ip->proto != IPPROTO_UDP || (ip->invflags & XT_INV_PROTO)) {
220 duprintf("ipt_udp: Protocol %u != %u\n", ip->proto,
221 IPPROTO_UDP);
222 return 0;
223 }
224 if (matchinfosize != XT_ALIGN(sizeof(struct xt_udp))) {
225 duprintf("ipt_udp: matchsize %u != %u\n",
226 matchinfosize, XT_ALIGN(sizeof(struct xt_udp)));
227 return 0;
228 }
229 if (udpinfo->invflags & ~XT_UDP_INV_MASK) {
230 duprintf("ipt_udp: unknown flags %X\n",
231 udpinfo->invflags);
232 return 0;
233 }
234
235 return 1;
236}
237
238/* Called when user tries to insert an entry of this type. */
239static int
240udp6_checkentry(const char *tablename,
241 const void *entry,
242 void *matchinfo,
243 unsigned int matchinfosize,
244 unsigned int hook_mask)
245{
246 const struct ip6t_ip6 *ipv6 = entry;
247 const struct xt_udp *udpinfo = matchinfo;
248
249 /* Must specify proto == UDP, and no unknown invflags */
250 if (ipv6->proto != IPPROTO_UDP || (ipv6->invflags & XT_INV_PROTO)) {
251 duprintf("ip6t_udp: Protocol %u != %u\n", ipv6->proto,
252 IPPROTO_UDP);
253 return 0;
254 }
255 if (matchinfosize != XT_ALIGN(sizeof(struct xt_udp))) {
256 duprintf("ip6t_udp: matchsize %u != %u\n",
257 matchinfosize, XT_ALIGN(sizeof(struct xt_udp)));
258 return 0;
259 }
260 if (udpinfo->invflags & ~XT_UDP_INV_MASK) {
261 duprintf("ip6t_udp: unknown flags %X\n",
262 udpinfo->invflags);
263 return 0;
264 }
265
266 return 1;
267}
268
269static struct xt_match tcp_matchstruct = {
270 .name = "tcp",
271 .match = &tcp_match,
272 .checkentry = &tcp_checkentry,
273 .me = THIS_MODULE,
274};
275static struct xt_match tcp6_matchstruct = {
276 .name = "tcp",
277 .match = &tcp_match,
278 .checkentry = &tcp6_checkentry,
279 .me = THIS_MODULE,
280};
281
282static struct xt_match udp_matchstruct = {
283 .name = "udp",
284 .match = &udp_match,
285 .checkentry = &udp_checkentry,
286 .me = THIS_MODULE,
287};
288static struct xt_match udp6_matchstruct = {
289 .name = "udp",
290 .match = &udp_match,
291 .checkentry = &udp6_checkentry,
292 .me = THIS_MODULE,
293};
294
295static int __init init(void)
296{
297 int ret;
298 ret = xt_register_match(AF_INET, &tcp_matchstruct);
299 if (ret)
300 return ret;
301
302 ret = xt_register_match(AF_INET6, &tcp6_matchstruct);
303 if (ret)
304 goto out_unreg_tcp;
305
306 ret = xt_register_match(AF_INET, &udp_matchstruct);
307 if (ret)
308 goto out_unreg_tcp6;
309
310 ret = xt_register_match(AF_INET6, &udp6_matchstruct);
311 if (ret)
312 goto out_unreg_udp;
313
314 return ret;
315
316out_unreg_udp:
317 xt_unregister_match(AF_INET, &tcp_matchstruct);
318out_unreg_tcp6:
319 xt_unregister_match(AF_INET6, &tcp6_matchstruct);
320out_unreg_tcp:
321 xt_unregister_match(AF_INET, &tcp_matchstruct);
322 return ret;
323}
324
325static void __exit fini(void)
326{
327 xt_unregister_match(AF_INET6, &udp6_matchstruct);
328 xt_unregister_match(AF_INET, &udp_matchstruct);
329 xt_unregister_match(AF_INET6, &tcp6_matchstruct);
330 xt_unregister_match(AF_INET, &tcp_matchstruct);
331}
332
333module_init(init);
334module_exit(fini);
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 3b1378498d50..4ae1538c54a9 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -222,11 +222,6 @@ int genl_register_family(struct genl_family *family)
222 goto errout_locked; 222 goto errout_locked;
223 } 223 }
224 224
225 if (!try_module_get(family->owner)) {
226 err = -EBUSY;
227 goto errout_locked;
228 }
229
230 if (family->id == GENL_ID_GENERATE) { 225 if (family->id == GENL_ID_GENERATE) {
231 u16 newid = genl_generate_id(); 226 u16 newid = genl_generate_id();
232 227
@@ -283,7 +278,6 @@ int genl_unregister_family(struct genl_family *family)
283 INIT_LIST_HEAD(&family->ops_list); 278 INIT_LIST_HEAD(&family->ops_list);
284 genl_unlock(); 279 genl_unlock();
285 280
286 module_put(family->owner);
287 kfree(family->attrbuf); 281 kfree(family->attrbuf);
288 genl_ctrl_event(CTRL_CMD_DELFAMILY, family); 282 genl_ctrl_event(CTRL_CMD_DELFAMILY, family);
289 return 0; 283 return 0;
@@ -535,7 +529,6 @@ static struct genl_family genl_ctrl = {
535 .name = "nlctrl", 529 .name = "nlctrl",
536 .version = 0x1, 530 .version = 0x1,
537 .maxattr = CTRL_ATTR_MAX, 531 .maxattr = CTRL_ATTR_MAX,
538 .owner = THIS_MODULE,
539}; 532};
540 533
541static int __init genl_init(void) 534static int __init genl_init(void)
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index 8a260d43ceef..778b1e5a4b50 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -44,7 +44,7 @@ if NET_SCHED
44 44
45choice 45choice
46 prompt "Packet scheduler clock source" 46 prompt "Packet scheduler clock source"
47 default NET_SCH_CLK_JIFFIES 47 default NET_SCH_CLK_GETTIMEOFDAY
48 ---help--- 48 ---help---
49 Packet schedulers need a monotonic clock that increments at a static 49 Packet schedulers need a monotonic clock that increments at a static
50 rate. The kernel provides several suitable interfaces, each with 50 rate. The kernel provides several suitable interfaces, each with
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index b5001939b74b..39a22a3ffe78 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -62,7 +62,7 @@ ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook)
62 struct ipt_target *target; 62 struct ipt_target *target;
63 int ret = 0; 63 int ret = 0;
64 64
65 target = ipt_find_target(t->u.user.name, t->u.user.revision); 65 target = xt_find_target(AF_INET, t->u.user.name, t->u.user.revision);
66 if (!target) 66 if (!target)
67 return -ENOENT; 67 return -ENOENT;
68 68
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index 04c7fab4edc4..2e266129a764 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -180,8 +180,7 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport,
180 } 180 }
181 181
182 SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, " 182 SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, "
183 "src:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x " 183 "src:" NIP6_FMT " dst:" NIP6_FMT "\n",
184 "dst:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
185 __FUNCTION__, skb, skb->len, 184 __FUNCTION__, skb, skb->len,
186 NIP6(fl.fl6_src), NIP6(fl.fl6_dst)); 185 NIP6(fl.fl6_src), NIP6(fl.fl6_dst));
187 186
@@ -206,13 +205,13 @@ static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc,
206 fl.oif = daddr->v6.sin6_scope_id; 205 fl.oif = daddr->v6.sin6_scope_id;
207 206
208 207
209 SCTP_DEBUG_PRINTK("%s: DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", 208 SCTP_DEBUG_PRINTK("%s: DST=" NIP6_FMT " ",
210 __FUNCTION__, NIP6(fl.fl6_dst)); 209 __FUNCTION__, NIP6(fl.fl6_dst));
211 210
212 if (saddr) { 211 if (saddr) {
213 ipv6_addr_copy(&fl.fl6_src, &saddr->v6.sin6_addr); 212 ipv6_addr_copy(&fl.fl6_src, &saddr->v6.sin6_addr);
214 SCTP_DEBUG_PRINTK( 213 SCTP_DEBUG_PRINTK(
215 "SRC=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x - ", 214 "SRC=" NIP6_FMT " - ",
216 NIP6(fl.fl6_src)); 215 NIP6(fl.fl6_src));
217 } 216 }
218 217
@@ -221,8 +220,7 @@ static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc,
221 struct rt6_info *rt; 220 struct rt6_info *rt;
222 rt = (struct rt6_info *)dst; 221 rt = (struct rt6_info *)dst;
223 SCTP_DEBUG_PRINTK( 222 SCTP_DEBUG_PRINTK(
224 "rt6_dst:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x " 223 "rt6_dst:" NIP6_FMT " rt6_src:" NIP6_FMT "\n",
225 "rt6_src:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
226 NIP6(rt->rt6i_dst.addr), NIP6(rt->rt6i_src.addr)); 224 NIP6(rt->rt6i_dst.addr), NIP6(rt->rt6i_src.addr));
227 } else { 225 } else {
228 SCTP_DEBUG_PRINTK("NO ROUTE\n"); 226 SCTP_DEBUG_PRINTK("NO ROUTE\n");
@@ -271,13 +269,12 @@ static void sctp_v6_get_saddr(struct sctp_association *asoc,
271 __u8 bmatchlen; 269 __u8 bmatchlen;
272 270
273 SCTP_DEBUG_PRINTK("%s: asoc:%p dst:%p " 271 SCTP_DEBUG_PRINTK("%s: asoc:%p dst:%p "
274 "daddr:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", 272 "daddr:" NIP6_FMT " ",
275 __FUNCTION__, asoc, dst, NIP6(daddr->v6.sin6_addr)); 273 __FUNCTION__, asoc, dst, NIP6(daddr->v6.sin6_addr));
276 274
277 if (!asoc) { 275 if (!asoc) {
278 ipv6_get_saddr(dst, &daddr->v6.sin6_addr,&saddr->v6.sin6_addr); 276 ipv6_get_saddr(dst, &daddr->v6.sin6_addr,&saddr->v6.sin6_addr);
279 SCTP_DEBUG_PRINTK("saddr from ipv6_get_saddr: " 277 SCTP_DEBUG_PRINTK("saddr from ipv6_get_saddr: " NIP6_FMT "\n",
280 "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
281 NIP6(saddr->v6.sin6_addr)); 278 NIP6(saddr->v6.sin6_addr));
282 return; 279 return;
283 } 280 }
@@ -305,13 +302,11 @@ static void sctp_v6_get_saddr(struct sctp_association *asoc,
305 302
306 if (baddr) { 303 if (baddr) {
307 memcpy(saddr, baddr, sizeof(union sctp_addr)); 304 memcpy(saddr, baddr, sizeof(union sctp_addr));
308 SCTP_DEBUG_PRINTK("saddr: " 305 SCTP_DEBUG_PRINTK("saddr: " NIP6_FMT "\n",
309 "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
310 NIP6(saddr->v6.sin6_addr)); 306 NIP6(saddr->v6.sin6_addr));
311 } else { 307 } else {
312 printk(KERN_ERR "%s: asoc:%p Could not find a valid source " 308 printk(KERN_ERR "%s: asoc:%p Could not find a valid source "
313 "address for the " 309 "address for the dest:" NIP6_FMT "\n",
314 "dest:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
315 __FUNCTION__, asoc, NIP6(daddr->v6.sin6_addr)); 310 __FUNCTION__, asoc, NIP6(daddr->v6.sin6_addr));
316 } 311 }
317 312
@@ -675,8 +670,7 @@ static int sctp_v6_is_ce(const struct sk_buff *skb)
675/* Dump the v6 addr to the seq file. */ 670/* Dump the v6 addr to the seq file. */
676static void sctp_v6_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr) 671static void sctp_v6_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr)
677{ 672{
678 seq_printf(seq, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", 673 seq_printf(seq, NIP6_FMT " ", NIP6(addr->v6.sin6_addr));
679 NIP6(addr->v6.sin6_addr));
680} 674}
681 675
682/* Initialize a PF_INET6 socket msg_name. */ 676/* Initialize a PF_INET6 socket msg_name. */
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 557a7d90b92a..477d7f80dba6 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -1036,14 +1036,14 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep,
1036 if (from_addr.sa.sa_family == AF_INET6) { 1036 if (from_addr.sa.sa_family == AF_INET6) {
1037 printk(KERN_WARNING 1037 printk(KERN_WARNING
1038 "%s association %p could not find address " 1038 "%s association %p could not find address "
1039 "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", 1039 NIP6_FMT "\n",
1040 __FUNCTION__, 1040 __FUNCTION__,
1041 asoc, 1041 asoc,
1042 NIP6(from_addr.v6.sin6_addr)); 1042 NIP6(from_addr.v6.sin6_addr));
1043 } else { 1043 } else {
1044 printk(KERN_WARNING 1044 printk(KERN_WARNING
1045 "%s association %p could not find address " 1045 "%s association %p could not find address "
1046 "%u.%u.%u.%u\n", 1046 NIPQUAD_FMT "\n",
1047 __FUNCTION__, 1047 __FUNCTION__,
1048 asoc, 1048 asoc,
1049 NIPQUAD(from_addr.v4.sin_addr.s_addr)); 1049 NIPQUAD(from_addr.v4.sin_addr.s_addr));
diff --git a/net/tipc/Kconfig b/net/tipc/Kconfig
new file mode 100644
index 000000000000..05ab18e62dee
--- /dev/null
+++ b/net/tipc/Kconfig
@@ -0,0 +1,112 @@
1#
2# TIPC configuration
3#
4
5menu "TIPC Configuration (EXPERIMENTAL)"
6 depends on INET && EXPERIMENTAL
7
8config TIPC
9 tristate "The TIPC Protocol (EXPERIMENTAL)"
10 ---help---
11 TBD.
12
13 This protocol support is also available as a module ( = code which
14 can be inserted in and removed from the running kernel whenever you
15 want). The module will be called tipc. If you want to compile it
16 as a module, say M here and read <file:Documentation/modules.txt>.
17
18 If in doubt, say N.
19
20config TIPC_ADVANCED
21 bool "TIPC: Advanced configuration"
22 depends on TIPC
23 default n
24 help
25 Saying Y here will open some advanced configuration
26 for TIPC. Most users do not need to bother, so if
27 unsure, just say N.
28
29config TIPC_ZONES
30 int "Maximum number of zones in network"
31 depends on TIPC && TIPC_ADVANCED
32 default "3"
33 help
34 Max number of zones inside TIPC network. Max supported value
35 is 255 zones, minimum is 1
36
37 Default is 3 zones in a network; setting this to higher
38 allows more zones but might use more memory.
39
40config TIPC_CLUSTERS
41 int "Maximum number of clusters in a zone"
42 depends on TIPC && TIPC_ADVANCED
43 default "1"
44 help
45 ***Only 1 (one cluster in a zone) is supported by current code.
46 Any value set here will be overridden.***
47
48 (Max number of clusters inside TIPC zone. Max supported
49 value is 4095 clusters, minimum is 1.
50
51 Default is 1; setting this to smaller value might save
52 some memory, setting it to higher
53 allows more clusters and might consume more memory.)
54
55config TIPC_NODES
56 int "Maximum number of nodes in cluster"
57 depends on TIPC && TIPC_ADVANCED
58 default "255"
59 help
60 Maximum number of nodes inside a TIPC cluster. Maximum
61 supported value is 2047 nodes, minimum is 8.
62
63 Setting this to a smaller value saves some memory,
64 setting it to higher allows more nodes.
65
66config TIPC_SLAVE_NODES
67 int "Maximum number of slave nodes in cluster"
68 depends on TIPC && TIPC_ADVANCED
69 default "0"
70 help
71 ***This capability is not supported by current code.***
72
73 Maximum number of slave nodes inside a TIPC cluster. Maximum
74 supported value is 2047 nodes, minimum is 0.
75
76 Setting this to a smaller value saves some memory,
77 setting it to higher allows more nodes.
78
79config TIPC_PORTS
80 int "Maximum number of ports in a node"
81 depends on TIPC && TIPC_ADVANCED
82 default "8191"
83 help
84 Maximum number of ports within a node. Maximum
85 supported value is 64535 nodes, minimum is 127.
86
87 Setting this to a smaller value saves some memory,
88 setting it to higher allows more ports.
89
90config TIPC_LOG
91 int "Size of log buffer"
92 depends on TIPC && TIPC_ADVANCED
93 default 0
94 help
95 Size (in bytes) of TIPC's internal log buffer, which records the
96 occurrence of significant events. Maximum supported value
97 is 32768 bytes, minimum is 0.
98
99 There is no need to enable the log buffer unless the node will be
100 managed remotely via TIPC.
101
102config TIPC_DEBUG
103 bool "Enable debugging support"
104 depends on TIPC
105 default n
106 help
107 This will enable debugging of TIPC.
108
109 Only say Y here if you are having trouble with TIPC. It will
110 enable the display of detailed information about what is going on.
111
112endmenu
diff --git a/net/tipc/Makefile b/net/tipc/Makefile
new file mode 100644
index 000000000000..dceb7027946c
--- /dev/null
+++ b/net/tipc/Makefile
@@ -0,0 +1,13 @@
1#
2# Makefile for the Linux TIPC layer
3#
4
5obj-$(CONFIG_TIPC) := tipc.o
6
7tipc-y += addr.o bcast.o bearer.o config.o cluster.o \
8 core.o handler.o link.o discover.o msg.o \
9 name_distr.o subscr.o name_table.o net.o \
10 netlink.o node.o node_subscr.o port.o ref.o \
11 socket.o user_reg.o zone.o dbg.o eth_media.o
12
13# End of file
diff --git a/net/tipc/addr.c b/net/tipc/addr.c
new file mode 100644
index 000000000000..eca22260c98c
--- /dev/null
+++ b/net/tipc/addr.c
@@ -0,0 +1,94 @@
1/*
2 * net/tipc/addr.c: TIPC address utility routines
3 *
4 * Copyright (c) 2000-2006, Ericsson AB
5 * Copyright (c) 2004-2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include "core.h"
38#include "dbg.h"
39#include "addr.h"
40#include "zone.h"
41#include "cluster.h"
42#include "net.h"
43
44u32 tipc_get_addr(void)
45{
46 return tipc_own_addr;
47}
48
49/**
50 * addr_domain_valid - validates a network domain address
51 *
52 * Accepts <Z.C.N>, <Z.C.0>, <Z.0.0>, and <0.0.0>,
53 * where Z, C, and N are non-zero and do not exceed the configured limits.
54 *
55 * Returns 1 if domain address is valid, otherwise 0
56 */
57
58int addr_domain_valid(u32 addr)
59{
60 u32 n = tipc_node(addr);
61 u32 c = tipc_cluster(addr);
62 u32 z = tipc_zone(addr);
63 u32 max_nodes = tipc_max_nodes;
64
65 if (is_slave(addr))
66 max_nodes = LOWEST_SLAVE + tipc_max_slaves;
67 if (n > max_nodes)
68 return 0;
69 if (c > tipc_max_clusters)
70 return 0;
71 if (z > tipc_max_zones)
72 return 0;
73
74 if (n && (!z || !c))
75 return 0;
76 if (c && !z)
77 return 0;
78 return 1;
79}
80
81/**
82 * addr_node_valid - validates a proposed network address for this node
83 *
84 * Accepts <Z.C.N>, where Z, C, and N are non-zero and do not exceed
85 * the configured limits.
86 *
87 * Returns 1 if address can be used, otherwise 0
88 */
89
90int addr_node_valid(u32 addr)
91{
92 return (addr_domain_valid(addr) && tipc_node(addr));
93}
94
diff --git a/net/tipc/addr.h b/net/tipc/addr.h
new file mode 100644
index 000000000000..02ca71783e2e
--- /dev/null
+++ b/net/tipc/addr.h
@@ -0,0 +1,128 @@
1/*
2 * net/tipc/addr.h: Include file for TIPC address utility routines
3 *
4 * Copyright (c) 2000-2006, Ericsson AB
5 * Copyright (c) 2004-2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#ifndef _TIPC_ADDR_H
38#define _TIPC_ADDR_H
39
40static inline u32 own_node(void)
41{
42 return tipc_node(tipc_own_addr);
43}
44
45static inline u32 own_cluster(void)
46{
47 return tipc_cluster(tipc_own_addr);
48}
49
50static inline u32 own_zone(void)
51{
52 return tipc_zone(tipc_own_addr);
53}
54
55static inline int in_own_cluster(u32 addr)
56{
57 return !((addr ^ tipc_own_addr) >> 12);
58}
59
60static inline int in_own_zone(u32 addr)
61{
62 return !((addr ^ tipc_own_addr) >> 24);
63}
64
65static inline int is_slave(u32 addr)
66{
67 return addr & 0x800;
68}
69
70static inline int may_route(u32 addr)
71{
72 return(addr ^ tipc_own_addr) >> 11;
73}
74
75static inline int in_scope(u32 domain, u32 addr)
76{
77 if (!domain || (domain == addr))
78 return 1;
79 if (domain == (addr & 0xfffff000u)) /* domain <Z.C.0> */
80 return 1;
81 if (domain == (addr & 0xff000000u)) /* domain <Z.0.0> */
82 return 1;
83 return 0;
84}
85
86/**
87 * addr_scope - convert message lookup domain to equivalent 2-bit scope value
88 */
89
90static inline int addr_scope(u32 domain)
91{
92 if (likely(!domain))
93 return TIPC_ZONE_SCOPE;
94 if (tipc_node(domain))
95 return TIPC_NODE_SCOPE;
96 if (tipc_cluster(domain))
97 return TIPC_CLUSTER_SCOPE;
98 return TIPC_ZONE_SCOPE;
99}
100
101/**
102 * addr_domain - convert 2-bit scope value to equivalent message lookup domain
103 *
104 * Needed when address of a named message must be looked up a second time
105 * after a network hop.
106 */
107
108static inline int addr_domain(int sc)
109{
110 if (likely(sc == TIPC_NODE_SCOPE))
111 return tipc_own_addr;
112 if (sc == TIPC_CLUSTER_SCOPE)
113 return tipc_addr(tipc_zone(tipc_own_addr),
114 tipc_cluster(tipc_own_addr), 0);
115 return tipc_addr(tipc_zone(tipc_own_addr), 0, 0);
116}
117
118static inline char *addr_string_fill(char *string, u32 addr)
119{
120 snprintf(string, 16, "<%u.%u.%u>",
121 tipc_zone(addr), tipc_cluster(addr), tipc_node(addr));
122 return string;
123}
124
125int addr_domain_valid(u32);
126int addr_node_valid(u32 addr);
127
128#endif
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
new file mode 100644
index 000000000000..9713d622efb8
--- /dev/null
+++ b/net/tipc/bcast.c
@@ -0,0 +1,806 @@
1/*
2 * net/tipc/bcast.c: TIPC broadcast code
3 *
4 * Copyright (c) 2004-2006, Ericsson AB
5 * Copyright (c) 2004, Intel Corporation.
6 * Copyright (c) 2005, Wind River Systems
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the names of the copyright holders nor the names of its
18 * contributors may be used to endorse or promote products derived from
19 * this software without specific prior written permission.
20 *
21 * Alternatively, this software may be distributed under the terms of the
22 * GNU General Public License ("GPL") version 2 as published by the Free
23 * Software Foundation.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#include "core.h"
39#include "msg.h"
40#include "dbg.h"
41#include "link.h"
42#include "net.h"
43#include "node.h"
44#include "port.h"
45#include "addr.h"
46#include "node_subscr.h"
47#include "name_distr.h"
48#include "bearer.h"
49#include "name_table.h"
50#include "bcast.h"
51
52
53#define MAX_PKT_DEFAULT_MCAST 1500 /* bcast link max packet size (fixed) */
54
55#define BCLINK_WIN_DEFAULT 20 /* bcast link window size (default) */
56
57#define BCLINK_LOG_BUF_SIZE 0
58
59/**
60 * struct bcbearer_pair - a pair of bearers used by broadcast link
61 * @primary: pointer to primary bearer
62 * @secondary: pointer to secondary bearer
63 *
64 * Bearers must have same priority and same set of reachable destinations
65 * to be paired.
66 */
67
68struct bcbearer_pair {
69 struct bearer *primary;
70 struct bearer *secondary;
71};
72
73/**
74 * struct bcbearer - bearer used by broadcast link
75 * @bearer: (non-standard) broadcast bearer structure
76 * @media: (non-standard) broadcast media structure
77 * @bpairs: array of bearer pairs
78 * @bpairs_temp: array of bearer pairs used during creation of "bpairs"
79 */
80
81struct bcbearer {
82 struct bearer bearer;
83 struct media media;
84 struct bcbearer_pair bpairs[MAX_BEARERS];
85 struct bcbearer_pair bpairs_temp[TIPC_NUM_LINK_PRI];
86};
87
88/**
89 * struct bclink - link used for broadcast messages
90 * @link: (non-standard) broadcast link structure
91 * @node: (non-standard) node structure representing b'cast link's peer node
92 *
93 * Handles sequence numbering, fragmentation, bundling, etc.
94 */
95
96struct bclink {
97 struct link link;
98 struct node node;
99};
100
101
102static struct bcbearer *bcbearer = NULL;
103static struct bclink *bclink = NULL;
104static struct link *bcl = NULL;
105static spinlock_t bc_lock = SPIN_LOCK_UNLOCKED;
106
107char bc_link_name[] = "multicast-link";
108
109
110static inline u32 buf_seqno(struct sk_buff *buf)
111{
112 return msg_seqno(buf_msg(buf));
113}
114
115static inline u32 bcbuf_acks(struct sk_buff *buf)
116{
117 return (u32)(unsigned long)TIPC_SKB_CB(buf)->handle;
118}
119
120static inline void bcbuf_set_acks(struct sk_buff *buf, u32 acks)
121{
122 TIPC_SKB_CB(buf)->handle = (void *)(unsigned long)acks;
123}
124
125static inline void bcbuf_decr_acks(struct sk_buff *buf)
126{
127 bcbuf_set_acks(buf, bcbuf_acks(buf) - 1);
128}
129
130
131/**
132 * bclink_set_gap - set gap according to contents of current deferred pkt queue
133 *
134 * Called with 'node' locked, bc_lock unlocked
135 */
136
137static inline void bclink_set_gap(struct node *n_ptr)
138{
139 struct sk_buff *buf = n_ptr->bclink.deferred_head;
140
141 n_ptr->bclink.gap_after = n_ptr->bclink.gap_to =
142 mod(n_ptr->bclink.last_in);
143 if (unlikely(buf != NULL))
144 n_ptr->bclink.gap_to = mod(buf_seqno(buf) - 1);
145}
146
147/**
148 * bclink_ack_allowed - test if ACK or NACK message can be sent at this moment
149 *
150 * This mechanism endeavours to prevent all nodes in network from trying
151 * to ACK or NACK at the same time.
152 *
153 * Note: TIPC uses a different trigger to distribute ACKs than it does to
154 * distribute NACKs, but tries to use the same spacing (divide by 16).
155 */
156
157static inline int bclink_ack_allowed(u32 n)
158{
159 return((n % TIPC_MIN_LINK_WIN) == tipc_own_tag);
160}
161
162
163/**
164 * bclink_retransmit_pkt - retransmit broadcast packets
165 * @after: sequence number of last packet to *not* retransmit
166 * @to: sequence number of last packet to retransmit
167 *
168 * Called with 'node' locked, bc_lock unlocked
169 */
170
171static void bclink_retransmit_pkt(u32 after, u32 to)
172{
173 struct sk_buff *buf;
174
175 spin_lock_bh(&bc_lock);
176 buf = bcl->first_out;
177 while (buf && less_eq(buf_seqno(buf), after)) {
178 buf = buf->next;
179 }
180 if (buf != NULL)
181 link_retransmit(bcl, buf, mod(to - after));
182 spin_unlock_bh(&bc_lock);
183}
184
185/**
186 * bclink_acknowledge - handle acknowledgement of broadcast packets
187 * @n_ptr: node that sent acknowledgement info
188 * @acked: broadcast sequence # that has been acknowledged
189 *
190 * Node is locked, bc_lock unlocked.
191 */
192
193void bclink_acknowledge(struct node *n_ptr, u32 acked)
194{
195 struct sk_buff *crs;
196 struct sk_buff *next;
197 unsigned int released = 0;
198
199 if (less_eq(acked, n_ptr->bclink.acked))
200 return;
201
202 spin_lock_bh(&bc_lock);
203
204 /* Skip over packets that node has previously acknowledged */
205
206 crs = bcl->first_out;
207 while (crs && less_eq(buf_seqno(crs), n_ptr->bclink.acked)) {
208 crs = crs->next;
209 }
210
211 /* Update packets that node is now acknowledging */
212
213 while (crs && less_eq(buf_seqno(crs), acked)) {
214 next = crs->next;
215 bcbuf_decr_acks(crs);
216 if (bcbuf_acks(crs) == 0) {
217 bcl->first_out = next;
218 bcl->out_queue_size--;
219 buf_discard(crs);
220 released = 1;
221 }
222 crs = next;
223 }
224 n_ptr->bclink.acked = acked;
225
226 /* Try resolving broadcast link congestion, if necessary */
227
228 if (unlikely(bcl->next_out))
229 link_push_queue(bcl);
230 if (unlikely(released && !list_empty(&bcl->waiting_ports)))
231 link_wakeup_ports(bcl, 0);
232 spin_unlock_bh(&bc_lock);
233}
234
235/**
236 * bclink_send_ack - unicast an ACK msg
237 *
238 * net_lock and node lock set
239 */
240
241static void bclink_send_ack(struct node *n_ptr)
242{
243 struct link *l_ptr = n_ptr->active_links[n_ptr->addr & 1];
244
245 if (l_ptr != NULL)
246 link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0);
247}
248
249/**
250 * bclink_send_nack- broadcast a NACK msg
251 *
252 * net_lock and node lock set
253 */
254
255static void bclink_send_nack(struct node *n_ptr)
256{
257 struct sk_buff *buf;
258 struct tipc_msg *msg;
259
260 if (!less(n_ptr->bclink.gap_after, n_ptr->bclink.gap_to))
261 return;
262
263 buf = buf_acquire(INT_H_SIZE);
264 if (buf) {
265 msg = buf_msg(buf);
266 msg_init(msg, BCAST_PROTOCOL, STATE_MSG,
267 TIPC_OK, INT_H_SIZE, n_ptr->addr);
268 msg_set_mc_netid(msg, tipc_net_id);
269 msg_set_bcast_ack(msg, mod(n_ptr->bclink.last_in));
270 msg_set_bcgap_after(msg, n_ptr->bclink.gap_after);
271 msg_set_bcgap_to(msg, n_ptr->bclink.gap_to);
272 msg_set_bcast_tag(msg, tipc_own_tag);
273
274 if (bearer_send(&bcbearer->bearer, buf, 0)) {
275 bcl->stats.sent_nacks++;
276 buf_discard(buf);
277 } else {
278 bearer_schedule(bcl->b_ptr, bcl);
279 bcl->proto_msg_queue = buf;
280 bcl->stats.bearer_congs++;
281 }
282
283 /*
284 * Ensure we doesn't send another NACK msg to the node
285 * until 16 more deferred messages arrive from it
286 * (i.e. helps prevent all nodes from NACK'ing at same time)
287 */
288
289 n_ptr->bclink.nack_sync = tipc_own_tag;
290 }
291}
292
293/**
294 * bclink_check_gap - send a NACK if a sequence gap exists
295 *
296 * net_lock and node lock set
297 */
298
299void bclink_check_gap(struct node *n_ptr, u32 last_sent)
300{
301 if (!n_ptr->bclink.supported ||
302 less_eq(last_sent, mod(n_ptr->bclink.last_in)))
303 return;
304
305 bclink_set_gap(n_ptr);
306 if (n_ptr->bclink.gap_after == n_ptr->bclink.gap_to)
307 n_ptr->bclink.gap_to = last_sent;
308 bclink_send_nack(n_ptr);
309}
310
311/**
312 * bclink_peek_nack - process a NACK msg meant for another node
313 *
314 * Only net_lock set.
315 */
316
317void bclink_peek_nack(u32 dest, u32 sender_tag, u32 gap_after, u32 gap_to)
318{
319 struct node *n_ptr = node_find(dest);
320 u32 my_after, my_to;
321
322 if (unlikely(!n_ptr || !node_is_up(n_ptr)))
323 return;
324 node_lock(n_ptr);
325 /*
326 * Modify gap to suppress unnecessary NACKs from this node
327 */
328 my_after = n_ptr->bclink.gap_after;
329 my_to = n_ptr->bclink.gap_to;
330
331 if (less_eq(gap_after, my_after)) {
332 if (less(my_after, gap_to) && less(gap_to, my_to))
333 n_ptr->bclink.gap_after = gap_to;
334 else if (less_eq(my_to, gap_to))
335 n_ptr->bclink.gap_to = n_ptr->bclink.gap_after;
336 } else if (less_eq(gap_after, my_to)) {
337 if (less_eq(my_to, gap_to))
338 n_ptr->bclink.gap_to = gap_after;
339 } else {
340 /*
341 * Expand gap if missing bufs not in deferred queue:
342 */
343 struct sk_buff *buf = n_ptr->bclink.deferred_head;
344 u32 prev = n_ptr->bclink.gap_to;
345
346 for (; buf; buf = buf->next) {
347 u32 seqno = buf_seqno(buf);
348
349 if (mod(seqno - prev) != 1)
350 buf = NULL;
351 if (seqno == gap_after)
352 break;
353 prev = seqno;
354 }
355 if (buf == NULL)
356 n_ptr->bclink.gap_to = gap_after;
357 }
358 /*
359 * Some nodes may send a complementary NACK now:
360 */
361 if (bclink_ack_allowed(sender_tag + 1)) {
362 if (n_ptr->bclink.gap_to != n_ptr->bclink.gap_after) {
363 bclink_send_nack(n_ptr);
364 bclink_set_gap(n_ptr);
365 }
366 }
367 node_unlock(n_ptr);
368}
369
370/**
371 * bclink_send_msg - broadcast a packet to all nodes in cluster
372 */
373
374int bclink_send_msg(struct sk_buff *buf)
375{
376 int res;
377
378 spin_lock_bh(&bc_lock);
379
380 res = link_send_buf(bcl, buf);
381 if (unlikely(res == -ELINKCONG))
382 buf_discard(buf);
383 else
384 bcl->stats.sent_info++;
385
386 if (bcl->out_queue_size > bcl->stats.max_queue_sz)
387 bcl->stats.max_queue_sz = bcl->out_queue_size;
388 bcl->stats.queue_sz_counts++;
389 bcl->stats.accu_queue_sz += bcl->out_queue_size;
390
391 spin_unlock_bh(&bc_lock);
392 return res;
393}
394
395/**
396 * bclink_recv_pkt - receive a broadcast packet, and deliver upwards
397 *
398 * net_lock is read_locked, no other locks set
399 */
400
401void bclink_recv_pkt(struct sk_buff *buf)
402{
403 struct tipc_msg *msg = buf_msg(buf);
404 struct node* node = node_find(msg_prevnode(msg));
405 u32 next_in;
406 u32 seqno;
407 struct sk_buff *deferred;
408
409 msg_dbg(msg, "<BC<<<");
410
411 if (unlikely(!node || !node_is_up(node) || !node->bclink.supported ||
412 (msg_mc_netid(msg) != tipc_net_id))) {
413 buf_discard(buf);
414 return;
415 }
416
417 if (unlikely(msg_user(msg) == BCAST_PROTOCOL)) {
418 msg_dbg(msg, "<BCNACK<<<");
419 if (msg_destnode(msg) == tipc_own_addr) {
420 node_lock(node);
421 bclink_acknowledge(node, msg_bcast_ack(msg));
422 node_unlock(node);
423 bcl->stats.recv_nacks++;
424 bclink_retransmit_pkt(msg_bcgap_after(msg),
425 msg_bcgap_to(msg));
426 } else {
427 bclink_peek_nack(msg_destnode(msg),
428 msg_bcast_tag(msg),
429 msg_bcgap_after(msg),
430 msg_bcgap_to(msg));
431 }
432 buf_discard(buf);
433 return;
434 }
435
436 node_lock(node);
437receive:
438 deferred = node->bclink.deferred_head;
439 next_in = mod(node->bclink.last_in + 1);
440 seqno = msg_seqno(msg);
441
442 if (likely(seqno == next_in)) {
443 bcl->stats.recv_info++;
444 node->bclink.last_in++;
445 bclink_set_gap(node);
446 if (unlikely(bclink_ack_allowed(seqno))) {
447 bclink_send_ack(node);
448 bcl->stats.sent_acks++;
449 }
450 if (likely(msg_isdata(msg))) {
451 node_unlock(node);
452 port_recv_mcast(buf, NULL);
453 } else if (msg_user(msg) == MSG_BUNDLER) {
454 bcl->stats.recv_bundles++;
455 bcl->stats.recv_bundled += msg_msgcnt(msg);
456 node_unlock(node);
457 link_recv_bundle(buf);
458 } else if (msg_user(msg) == MSG_FRAGMENTER) {
459 bcl->stats.recv_fragments++;
460 if (link_recv_fragment(&node->bclink.defragm,
461 &buf, &msg))
462 bcl->stats.recv_fragmented++;
463 node_unlock(node);
464 net_route_msg(buf);
465 } else {
466 node_unlock(node);
467 net_route_msg(buf);
468 }
469 if (deferred && (buf_seqno(deferred) == mod(next_in + 1))) {
470 node_lock(node);
471 buf = deferred;
472 msg = buf_msg(buf);
473 node->bclink.deferred_head = deferred->next;
474 goto receive;
475 }
476 return;
477 } else if (less(next_in, seqno)) {
478 u32 gap_after = node->bclink.gap_after;
479 u32 gap_to = node->bclink.gap_to;
480
481 if (link_defer_pkt(&node->bclink.deferred_head,
482 &node->bclink.deferred_tail,
483 buf)) {
484 node->bclink.nack_sync++;
485 bcl->stats.deferred_recv++;
486 if (seqno == mod(gap_after + 1))
487 node->bclink.gap_after = seqno;
488 else if (less(gap_after, seqno) && less(seqno, gap_to))
489 node->bclink.gap_to = seqno;
490 }
491 if (bclink_ack_allowed(node->bclink.nack_sync)) {
492 if (gap_to != gap_after)
493 bclink_send_nack(node);
494 bclink_set_gap(node);
495 }
496 } else {
497 bcl->stats.duplicates++;
498 buf_discard(buf);
499 }
500 node_unlock(node);
501}
502
503u32 bclink_get_last_sent(void)
504{
505 u32 last_sent = mod(bcl->next_out_no - 1);
506
507 if (bcl->next_out)
508 last_sent = mod(buf_seqno(bcl->next_out) - 1);
509 return last_sent;
510}
511
512u32 bclink_acks_missing(struct node *n_ptr)
513{
514 return (n_ptr->bclink.supported &&
515 (bclink_get_last_sent() != n_ptr->bclink.acked));
516}
517
518
519/**
520 * bcbearer_send - send a packet through the broadcast pseudo-bearer
521 *
522 * Send through as many bearers as necessary to reach all nodes
523 * that support TIPC multicasting.
524 *
525 * Returns 0 if packet sent successfully, non-zero if not
526 */
527
528int bcbearer_send(struct sk_buff *buf,
529 struct tipc_bearer *unused1,
530 struct tipc_media_addr *unused2)
531{
532 static int send_count = 0;
533
534 struct node_map remains;
535 struct node_map remains_new;
536 int bp_index;
537 int swap_time;
538
539 /* Prepare buffer for broadcasting (if first time trying to send it) */
540
541 if (likely(!msg_non_seq(buf_msg(buf)))) {
542 struct tipc_msg *msg;
543
544 assert(cluster_bcast_nodes.count != 0);
545 bcbuf_set_acks(buf, cluster_bcast_nodes.count);
546 msg = buf_msg(buf);
547 msg_set_non_seq(msg);
548 msg_set_mc_netid(msg, tipc_net_id);
549 }
550
551 /* Determine if bearer pairs should be swapped following this attempt */
552
553 if ((swap_time = (++send_count >= 10)))
554 send_count = 0;
555
556 /* Send buffer over bearers until all targets reached */
557
558 remains = cluster_bcast_nodes;
559
560 for (bp_index = 0; bp_index < MAX_BEARERS; bp_index++) {
561 struct bearer *p = bcbearer->bpairs[bp_index].primary;
562 struct bearer *s = bcbearer->bpairs[bp_index].secondary;
563
564 if (!p)
565 break; /* no more bearers to try */
566
567 nmap_diff(&remains, &p->nodes, &remains_new);
568 if (remains_new.count == remains.count)
569 continue; /* bearer pair doesn't add anything */
570
571 if (!p->publ.blocked &&
572 !p->media->send_msg(buf, &p->publ, &p->media->bcast_addr)) {
573 if (swap_time && s && !s->publ.blocked)
574 goto swap;
575 else
576 goto update;
577 }
578
579 if (!s || s->publ.blocked ||
580 s->media->send_msg(buf, &s->publ, &s->media->bcast_addr))
581 continue; /* unable to send using bearer pair */
582swap:
583 bcbearer->bpairs[bp_index].primary = s;
584 bcbearer->bpairs[bp_index].secondary = p;
585update:
586 if (remains_new.count == 0)
587 return TIPC_OK;
588
589 remains = remains_new;
590 }
591
592 /* Unable to reach all targets */
593
594 bcbearer->bearer.publ.blocked = 1;
595 bcl->stats.bearer_congs++;
596 return ~TIPC_OK;
597}
598
599/**
600 * bcbearer_sort - create sets of bearer pairs used by broadcast bearer
601 */
602
603void bcbearer_sort(void)
604{
605 struct bcbearer_pair *bp_temp = bcbearer->bpairs_temp;
606 struct bcbearer_pair *bp_curr;
607 int b_index;
608 int pri;
609
610 spin_lock_bh(&bc_lock);
611
612 /* Group bearers by priority (can assume max of two per priority) */
613
614 memset(bp_temp, 0, sizeof(bcbearer->bpairs_temp));
615
616 for (b_index = 0; b_index < MAX_BEARERS; b_index++) {
617 struct bearer *b = &bearers[b_index];
618
619 if (!b->active || !b->nodes.count)
620 continue;
621
622 if (!bp_temp[b->priority].primary)
623 bp_temp[b->priority].primary = b;
624 else
625 bp_temp[b->priority].secondary = b;
626 }
627
628 /* Create array of bearer pairs for broadcasting */
629
630 bp_curr = bcbearer->bpairs;
631 memset(bcbearer->bpairs, 0, sizeof(bcbearer->bpairs));
632
633 for (pri = (TIPC_NUM_LINK_PRI - 1); pri >= 0; pri--) {
634
635 if (!bp_temp[pri].primary)
636 continue;
637
638 bp_curr->primary = bp_temp[pri].primary;
639
640 if (bp_temp[pri].secondary) {
641 if (nmap_equal(&bp_temp[pri].primary->nodes,
642 &bp_temp[pri].secondary->nodes)) {
643 bp_curr->secondary = bp_temp[pri].secondary;
644 } else {
645 bp_curr++;
646 bp_curr->primary = bp_temp[pri].secondary;
647 }
648 }
649
650 bp_curr++;
651 }
652
653 spin_unlock_bh(&bc_lock);
654}
655
656/**
657 * bcbearer_push - resolve bearer congestion
658 *
659 * Forces bclink to push out any unsent packets, until all packets are gone
660 * or congestion reoccurs.
661 * No locks set when function called
662 */
663
664void bcbearer_push(void)
665{
666 struct bearer *b_ptr;
667
668 spin_lock_bh(&bc_lock);
669 b_ptr = &bcbearer->bearer;
670 if (b_ptr->publ.blocked) {
671 b_ptr->publ.blocked = 0;
672 bearer_lock_push(b_ptr);
673 }
674 spin_unlock_bh(&bc_lock);
675}
676
677
678int bclink_stats(char *buf, const u32 buf_size)
679{
680 struct print_buf pb;
681
682 if (!bcl)
683 return 0;
684
685 printbuf_init(&pb, buf, buf_size);
686
687 spin_lock_bh(&bc_lock);
688
689 tipc_printf(&pb, "Link <%s>\n"
690 " Window:%u packets\n",
691 bcl->name, bcl->queue_limit[0]);
692 tipc_printf(&pb, " RX packets:%u fragments:%u/%u bundles:%u/%u\n",
693 bcl->stats.recv_info,
694 bcl->stats.recv_fragments,
695 bcl->stats.recv_fragmented,
696 bcl->stats.recv_bundles,
697 bcl->stats.recv_bundled);
698 tipc_printf(&pb, " TX packets:%u fragments:%u/%u bundles:%u/%u\n",
699 bcl->stats.sent_info,
700 bcl->stats.sent_fragments,
701 bcl->stats.sent_fragmented,
702 bcl->stats.sent_bundles,
703 bcl->stats.sent_bundled);
704 tipc_printf(&pb, " RX naks:%u defs:%u dups:%u\n",
705 bcl->stats.recv_nacks,
706 bcl->stats.deferred_recv,
707 bcl->stats.duplicates);
708 tipc_printf(&pb, " TX naks:%u acks:%u dups:%u\n",
709 bcl->stats.sent_nacks,
710 bcl->stats.sent_acks,
711 bcl->stats.retransmitted);
712 tipc_printf(&pb, " Congestion bearer:%u link:%u Send queue max:%u avg:%u\n",
713 bcl->stats.bearer_congs,
714 bcl->stats.link_congs,
715 bcl->stats.max_queue_sz,
716 bcl->stats.queue_sz_counts
717 ? (bcl->stats.accu_queue_sz / bcl->stats.queue_sz_counts)
718 : 0);
719
720 spin_unlock_bh(&bc_lock);
721 return printbuf_validate(&pb);
722}
723
724int bclink_reset_stats(void)
725{
726 if (!bcl)
727 return -ENOPROTOOPT;
728
729 spin_lock_bh(&bc_lock);
730 memset(&bcl->stats, 0, sizeof(bcl->stats));
731 spin_unlock_bh(&bc_lock);
732 return TIPC_OK;
733}
734
735int bclink_set_queue_limits(u32 limit)
736{
737 if (!bcl)
738 return -ENOPROTOOPT;
739 if ((limit < TIPC_MIN_LINK_WIN) || (limit > TIPC_MAX_LINK_WIN))
740 return -EINVAL;
741
742 spin_lock_bh(&bc_lock);
743 link_set_queue_limits(bcl, limit);
744 spin_unlock_bh(&bc_lock);
745 return TIPC_OK;
746}
747
748int bclink_init(void)
749{
750 bcbearer = kmalloc(sizeof(*bcbearer), GFP_ATOMIC);
751 bclink = kmalloc(sizeof(*bclink), GFP_ATOMIC);
752 if (!bcbearer || !bclink) {
753 nomem:
754 warn("Memory squeeze; Failed to create multicast link\n");
755 kfree(bcbearer);
756 bcbearer = NULL;
757 kfree(bclink);
758 bclink = NULL;
759 return -ENOMEM;
760 }
761
762 memset(bcbearer, 0, sizeof(struct bcbearer));
763 INIT_LIST_HEAD(&bcbearer->bearer.cong_links);
764 bcbearer->bearer.media = &bcbearer->media;
765 bcbearer->media.send_msg = bcbearer_send;
766 sprintf(bcbearer->media.name, "tipc-multicast");
767
768 bcl = &bclink->link;
769 memset(bclink, 0, sizeof(struct bclink));
770 INIT_LIST_HEAD(&bcl->waiting_ports);
771 bcl->next_out_no = 1;
772 bclink->node.lock = SPIN_LOCK_UNLOCKED;
773 bcl->owner = &bclink->node;
774 bcl->max_pkt = MAX_PKT_DEFAULT_MCAST;
775 link_set_queue_limits(bcl, BCLINK_WIN_DEFAULT);
776 bcl->b_ptr = &bcbearer->bearer;
777 bcl->state = WORKING_WORKING;
778 sprintf(bcl->name, bc_link_name);
779
780 if (BCLINK_LOG_BUF_SIZE) {
781 char *pb = kmalloc(BCLINK_LOG_BUF_SIZE, GFP_ATOMIC);
782
783 if (!pb)
784 goto nomem;
785 printbuf_init(&bcl->print_buf, pb, BCLINK_LOG_BUF_SIZE);
786 }
787
788 return TIPC_OK;
789}
790
791void bclink_stop(void)
792{
793 spin_lock_bh(&bc_lock);
794 if (bcbearer) {
795 link_stop(bcl);
796 if (BCLINK_LOG_BUF_SIZE)
797 kfree(bcl->print_buf.buf);
798 bcl = NULL;
799 kfree(bclink);
800 bclink = NULL;
801 kfree(bcbearer);
802 bcbearer = NULL;
803 }
804 spin_unlock_bh(&bc_lock);
805}
806
diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h
new file mode 100644
index 000000000000..5430e524b4f9
--- /dev/null
+++ b/net/tipc/bcast.h
@@ -0,0 +1,223 @@
1/*
2 * net/tipc/bcast.h: Include file for TIPC broadcast code
3 *
4 * Copyright (c) 2003-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#ifndef _TIPC_BCAST_H
38#define _TIPC_BCAST_H
39
40#define MAX_NODES 4096
41#define WSIZE 32
42
43/**
44 * struct node_map - set of node identifiers
45 * @count: # of nodes in set
46 * @map: bitmap of node identifiers that are in the set
47 */
48
49struct node_map {
50 u32 count;
51 u32 map[MAX_NODES / WSIZE];
52};
53
54
55#define PLSIZE 32
56
57/**
58 * struct port_list - set of node local destination ports
59 * @count: # of ports in set (only valid for first entry in list)
60 * @next: pointer to next entry in list
61 * @ports: array of port references
62 */
63
64struct port_list {
65 int count;
66 struct port_list *next;
67 u32 ports[PLSIZE];
68};
69
70
71struct node;
72
73extern char bc_link_name[];
74
75
76/**
77 * nmap_get - determine if node exists in a node map
78 */
79
80static inline int nmap_get(struct node_map *nm_ptr, u32 node)
81{
82 int n = tipc_node(node);
83 int w = n / WSIZE;
84 int b = n % WSIZE;
85
86 return nm_ptr->map[w] & (1 << b);
87}
88
89/**
90 * nmap_add - add a node to a node map
91 */
92
93static inline void nmap_add(struct node_map *nm_ptr, u32 node)
94{
95 int n = tipc_node(node);
96 int w = n / WSIZE;
97 u32 mask = (1 << (n % WSIZE));
98
99 if ((nm_ptr->map[w] & mask) == 0) {
100 nm_ptr->count++;
101 nm_ptr->map[w] |= mask;
102 }
103}
104
105/**
106 * nmap_remove - remove a node from a node map
107 */
108
109static inline void nmap_remove(struct node_map *nm_ptr, u32 node)
110{
111 int n = tipc_node(node);
112 int w = n / WSIZE;
113 u32 mask = (1 << (n % WSIZE));
114
115 if ((nm_ptr->map[w] & mask) != 0) {
116 nm_ptr->map[w] &= ~mask;
117 nm_ptr->count--;
118 }
119}
120
121/**
122 * nmap_equal - test for equality of node maps
123 */
124
125static inline int nmap_equal(struct node_map *nm_a, struct node_map *nm_b)
126{
127 return !memcmp(nm_a, nm_b, sizeof(*nm_a));
128}
129
130/**
131 * nmap_diff - find differences between node maps
132 * @nm_a: input node map A
133 * @nm_b: input node map B
134 * @nm_diff: output node map A-B (i.e. nodes of A that are not in B)
135 */
136
137static inline void nmap_diff(struct node_map *nm_a, struct node_map *nm_b,
138 struct node_map *nm_diff)
139{
140 int stop = sizeof(nm_a->map) / sizeof(u32);
141 int w;
142 int b;
143 u32 map;
144
145 memset(nm_diff, 0, sizeof(*nm_diff));
146 for (w = 0; w < stop; w++) {
147 map = nm_a->map[w] ^ (nm_a->map[w] & nm_b->map[w]);
148 nm_diff->map[w] = map;
149 if (map != 0) {
150 for (b = 0 ; b < WSIZE; b++) {
151 if (map & (1 << b))
152 nm_diff->count++;
153 }
154 }
155 }
156}
157
158/**
159 * port_list_add - add a port to a port list, ensuring no duplicates
160 */
161
162static inline void port_list_add(struct port_list *pl_ptr, u32 port)
163{
164 struct port_list *item = pl_ptr;
165 int i;
166 int item_sz = PLSIZE;
167 int cnt = pl_ptr->count;
168
169 for (; ; cnt -= item_sz, item = item->next) {
170 if (cnt < PLSIZE)
171 item_sz = cnt;
172 for (i = 0; i < item_sz; i++)
173 if (item->ports[i] == port)
174 return;
175 if (i < PLSIZE) {
176 item->ports[i] = port;
177 pl_ptr->count++;
178 return;
179 }
180 if (!item->next) {
181 item->next = kmalloc(sizeof(*item), GFP_ATOMIC);
182 if (!item->next) {
183 warn("Memory squeeze: multicast destination port list is incomplete\n");
184 return;
185 }
186 item->next->next = NULL;
187 }
188 }
189}
190
191/**
192 * port_list_free - free dynamically created entries in port_list chain
193 *
194 * Note: First item is on stack, so it doesn't need to be released
195 */
196
197static inline void port_list_free(struct port_list *pl_ptr)
198{
199 struct port_list *item;
200 struct port_list *next;
201
202 for (item = pl_ptr->next; item; item = next) {
203 next = item->next;
204 kfree(item);
205 }
206}
207
208
209int bclink_init(void);
210void bclink_stop(void);
211void bclink_acknowledge(struct node *n_ptr, u32 acked);
212int bclink_send_msg(struct sk_buff *buf);
213void bclink_recv_pkt(struct sk_buff *buf);
214u32 bclink_get_last_sent(void);
215u32 bclink_acks_missing(struct node *n_ptr);
216void bclink_check_gap(struct node *n_ptr, u32 seqno);
217int bclink_stats(char *stats_buf, const u32 buf_size);
218int bclink_reset_stats(void);
219int bclink_set_queue_limits(u32 limit);
220void bcbearer_sort(void);
221void bcbearer_push(void);
222
223#endif
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
new file mode 100644
index 000000000000..3dd19fdc5a2c
--- /dev/null
+++ b/net/tipc/bearer.c
@@ -0,0 +1,692 @@
1/*
2 * net/tipc/bearer.c: TIPC bearer code
3 *
4 * Copyright (c) 1996-2006, Ericsson AB
5 * Copyright (c) 2004-2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include "core.h"
38#include "config.h"
39#include "dbg.h"
40#include "bearer.h"
41#include "link.h"
42#include "port.h"
43#include "discover.h"
44#include "bcast.h"
45
46#define MAX_ADDR_STR 32
47
48static struct media *media_list = 0;
49static u32 media_count = 0;
50
51struct bearer *bearers = 0;
52
53/**
54 * media_name_valid - validate media name
55 *
56 * Returns 1 if media name is valid, otherwise 0.
57 */
58
59static int media_name_valid(const char *name)
60{
61 u32 len;
62
63 len = strlen(name);
64 if ((len + 1) > TIPC_MAX_MEDIA_NAME)
65 return 0;
66 return (strspn(name, tipc_alphabet) == len);
67}
68
69/**
70 * media_find - locates specified media object by name
71 */
72
73static struct media *media_find(const char *name)
74{
75 struct media *m_ptr;
76 u32 i;
77
78 for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) {
79 if (!strcmp(m_ptr->name, name))
80 return m_ptr;
81 }
82 return 0;
83}
84
85/**
86 * tipc_register_media - register a media type
87 *
88 * Bearers for this media type must be activated separately at a later stage.
89 */
90
91int tipc_register_media(u32 media_type,
92 char *name,
93 int (*enable)(struct tipc_bearer *),
94 void (*disable)(struct tipc_bearer *),
95 int (*send_msg)(struct sk_buff *,
96 struct tipc_bearer *,
97 struct tipc_media_addr *),
98 char *(*addr2str)(struct tipc_media_addr *a,
99 char *str_buf, int str_size),
100 struct tipc_media_addr *bcast_addr,
101 const u32 bearer_priority,
102 const u32 link_tolerance, /* [ms] */
103 const u32 send_window_limit)
104{
105 struct media *m_ptr;
106 u32 media_id;
107 u32 i;
108 int res = -EINVAL;
109
110 write_lock_bh(&net_lock);
111 if (!media_list)
112 goto exit;
113
114 if (!media_name_valid(name)) {
115 warn("Media registration error: illegal name <%s>\n", name);
116 goto exit;
117 }
118 if (!bcast_addr) {
119 warn("Media registration error: no broadcast address supplied\n");
120 goto exit;
121 }
122 if (bearer_priority >= TIPC_NUM_LINK_PRI) {
123 warn("Media registration error: priority %u\n", bearer_priority);
124 goto exit;
125 }
126 if ((link_tolerance < TIPC_MIN_LINK_TOL) ||
127 (link_tolerance > TIPC_MAX_LINK_TOL)) {
128 warn("Media registration error: tolerance %u\n", link_tolerance);
129 goto exit;
130 }
131
132 media_id = media_count++;
133 if (media_id >= MAX_MEDIA) {
134 warn("Attempt to register more than %u media\n", MAX_MEDIA);
135 media_count--;
136 goto exit;
137 }
138 for (i = 0; i < media_id; i++) {
139 if (media_list[i].type_id == media_type) {
140 warn("Attempt to register second media with type %u\n",
141 media_type);
142 media_count--;
143 goto exit;
144 }
145 if (!strcmp(name, media_list[i].name)) {
146 warn("Attempt to re-register media name <%s>\n", name);
147 media_count--;
148 goto exit;
149 }
150 }
151
152 m_ptr = &media_list[media_id];
153 m_ptr->type_id = media_type;
154 m_ptr->send_msg = send_msg;
155 m_ptr->enable_bearer = enable;
156 m_ptr->disable_bearer = disable;
157 m_ptr->addr2str = addr2str;
158 memcpy(&m_ptr->bcast_addr, bcast_addr, sizeof(*bcast_addr));
159 m_ptr->bcast = 1;
160 strcpy(m_ptr->name, name);
161 m_ptr->priority = bearer_priority;
162 m_ptr->tolerance = link_tolerance;
163 m_ptr->window = send_window_limit;
164 dbg("Media <%s> registered\n", name);
165 res = 0;
166exit:
167 write_unlock_bh(&net_lock);
168 return res;
169}
170
171/**
172 * media_addr_printf - record media address in print buffer
173 */
174
175void media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a)
176{
177 struct media *m_ptr;
178 u32 media_type;
179 u32 i;
180
181 media_type = ntohl(a->type);
182 for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) {
183 if (m_ptr->type_id == media_type)
184 break;
185 }
186
187 if ((i < media_count) && (m_ptr->addr2str != NULL)) {
188 char addr_str[MAX_ADDR_STR];
189
190 tipc_printf(pb, "%s(%s) ", m_ptr->name,
191 m_ptr->addr2str(a, addr_str, sizeof(addr_str)));
192 } else {
193 unchar *addr = (unchar *)&a->dev_addr;
194
195 tipc_printf(pb, "UNKNOWN(%u):", media_type);
196 for (i = 0; i < (sizeof(*a) - sizeof(a->type)); i++) {
197 tipc_printf(pb, "%02x ", addr[i]);
198 }
199 }
200}
201
202/**
203 * media_get_names - record names of registered media in buffer
204 */
205
206struct sk_buff *media_get_names(void)
207{
208 struct sk_buff *buf;
209 struct media *m_ptr;
210 int i;
211
212 buf = cfg_reply_alloc(MAX_MEDIA * TLV_SPACE(TIPC_MAX_MEDIA_NAME));
213 if (!buf)
214 return NULL;
215
216 read_lock_bh(&net_lock);
217 for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) {
218 cfg_append_tlv(buf, TIPC_TLV_MEDIA_NAME, m_ptr->name,
219 strlen(m_ptr->name) + 1);
220 }
221 read_unlock_bh(&net_lock);
222 return buf;
223}
224
225/**
226 * bearer_name_validate - validate & (optionally) deconstruct bearer name
227 * @name - ptr to bearer name string
228 * @name_parts - ptr to area for bearer name components (or NULL if not needed)
229 *
230 * Returns 1 if bearer name is valid, otherwise 0.
231 */
232
233static int bearer_name_validate(const char *name,
234 struct bearer_name *name_parts)
235{
236 char name_copy[TIPC_MAX_BEARER_NAME];
237 char *media_name;
238 char *if_name;
239 u32 media_len;
240 u32 if_len;
241
242 /* copy bearer name & ensure length is OK */
243
244 name_copy[TIPC_MAX_BEARER_NAME - 1] = 0;
245 /* need above in case non-Posix strncpy() doesn't pad with nulls */
246 strncpy(name_copy, name, TIPC_MAX_BEARER_NAME);
247 if (name_copy[TIPC_MAX_BEARER_NAME - 1] != 0)
248 return 0;
249
250 /* ensure all component parts of bearer name are present */
251
252 media_name = name_copy;
253 if ((if_name = strchr(media_name, ':')) == NULL)
254 return 0;
255 *(if_name++) = 0;
256 media_len = if_name - media_name;
257 if_len = strlen(if_name) + 1;
258
259 /* validate component parts of bearer name */
260
261 if ((media_len <= 1) || (media_len > TIPC_MAX_MEDIA_NAME) ||
262 (if_len <= 1) || (if_len > TIPC_MAX_IF_NAME) ||
263 (strspn(media_name, tipc_alphabet) != (media_len - 1)) ||
264 (strspn(if_name, tipc_alphabet) != (if_len - 1)))
265 return 0;
266
267 /* return bearer name components, if necessary */
268
269 if (name_parts) {
270 strcpy(name_parts->media_name, media_name);
271 strcpy(name_parts->if_name, if_name);
272 }
273 return 1;
274}
275
276/**
277 * bearer_find - locates bearer object with matching bearer name
278 */
279
280static struct bearer *bearer_find(const char *name)
281{
282 struct bearer *b_ptr;
283 u32 i;
284
285 for (i = 0, b_ptr = bearers; i < MAX_BEARERS; i++, b_ptr++) {
286 if (b_ptr->active && (!strcmp(b_ptr->publ.name, name)))
287 return b_ptr;
288 }
289 return 0;
290}
291
292/**
293 * bearer_find - locates bearer object with matching interface name
294 */
295
296struct bearer *bearer_find_interface(const char *if_name)
297{
298 struct bearer *b_ptr;
299 char *b_if_name;
300 u32 i;
301
302 for (i = 0, b_ptr = bearers; i < MAX_BEARERS; i++, b_ptr++) {
303 if (!b_ptr->active)
304 continue;
305 b_if_name = strchr(b_ptr->publ.name, ':') + 1;
306 if (!strcmp(b_if_name, if_name))
307 return b_ptr;
308 }
309 return 0;
310}
311
312/**
313 * bearer_get_names - record names of bearers in buffer
314 */
315
316struct sk_buff *bearer_get_names(void)
317{
318 struct sk_buff *buf;
319 struct media *m_ptr;
320 struct bearer *b_ptr;
321 int i, j;
322
323 buf = cfg_reply_alloc(MAX_BEARERS * TLV_SPACE(TIPC_MAX_BEARER_NAME));
324 if (!buf)
325 return NULL;
326
327 read_lock_bh(&net_lock);
328 for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) {
329 for (j = 0; j < MAX_BEARERS; j++) {
330 b_ptr = &bearers[j];
331 if (b_ptr->active && (b_ptr->media == m_ptr)) {
332 cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME,
333 b_ptr->publ.name,
334 strlen(b_ptr->publ.name) + 1);
335 }
336 }
337 }
338 read_unlock_bh(&net_lock);
339 return buf;
340}
341
342void bearer_add_dest(struct bearer *b_ptr, u32 dest)
343{
344 nmap_add(&b_ptr->nodes, dest);
345 disc_update_link_req(b_ptr->link_req);
346 bcbearer_sort();
347}
348
349void bearer_remove_dest(struct bearer *b_ptr, u32 dest)
350{
351 nmap_remove(&b_ptr->nodes, dest);
352 disc_update_link_req(b_ptr->link_req);
353 bcbearer_sort();
354}
355
356/*
357 * bearer_push(): Resolve bearer congestion. Force the waiting
358 * links to push out their unsent packets, one packet per link
359 * per iteration, until all packets are gone or congestion reoccurs.
360 * 'net_lock' is read_locked when this function is called
361 * bearer.lock must be taken before calling
362 * Returns binary true(1) ore false(0)
363 */
364static int bearer_push(struct bearer *b_ptr)
365{
366 u32 res = TIPC_OK;
367 struct link *ln, *tln;
368
369 if (b_ptr->publ.blocked)
370 return 0;
371
372 while (!list_empty(&b_ptr->cong_links) && (res != PUSH_FAILED)) {
373 list_for_each_entry_safe(ln, tln, &b_ptr->cong_links, link_list) {
374 res = link_push_packet(ln);
375 if (res == PUSH_FAILED)
376 break;
377 if (res == PUSH_FINISHED)
378 list_move_tail(&ln->link_list, &b_ptr->links);
379 }
380 }
381 return list_empty(&b_ptr->cong_links);
382}
383
384void bearer_lock_push(struct bearer *b_ptr)
385{
386 int res;
387
388 spin_lock_bh(&b_ptr->publ.lock);
389 res = bearer_push(b_ptr);
390 spin_unlock_bh(&b_ptr->publ.lock);
391 if (res)
392 bcbearer_push();
393}
394
395
396/*
397 * Interrupt enabling new requests after bearer congestion or blocking:
398 * See bearer_send().
399 */
400void tipc_continue(struct tipc_bearer *tb_ptr)
401{
402 struct bearer *b_ptr = (struct bearer *)tb_ptr;
403
404 spin_lock_bh(&b_ptr->publ.lock);
405 b_ptr->continue_count++;
406 if (!list_empty(&b_ptr->cong_links))
407 k_signal((Handler)bearer_lock_push, (unsigned long)b_ptr);
408 b_ptr->publ.blocked = 0;
409 spin_unlock_bh(&b_ptr->publ.lock);
410}
411
412/*
413 * Schedule link for sending of messages after the bearer
414 * has been deblocked by 'continue()'. This method is called
415 * when somebody tries to send a message via this link while
416 * the bearer is congested. 'net_lock' is in read_lock here
417 * bearer.lock is busy
418 */
419
420static void bearer_schedule_unlocked(struct bearer *b_ptr, struct link *l_ptr)
421{
422 list_move_tail(&l_ptr->link_list, &b_ptr->cong_links);
423}
424
425/*
426 * Schedule link for sending of messages after the bearer
427 * has been deblocked by 'continue()'. This method is called
428 * when somebody tries to send a message via this link while
429 * the bearer is congested. 'net_lock' is in read_lock here,
430 * bearer.lock is free
431 */
432
433void bearer_schedule(struct bearer *b_ptr, struct link *l_ptr)
434{
435 spin_lock_bh(&b_ptr->publ.lock);
436 bearer_schedule_unlocked(b_ptr, l_ptr);
437 spin_unlock_bh(&b_ptr->publ.lock);
438}
439
440
441/*
442 * bearer_resolve_congestion(): Check if there is bearer congestion,
443 * and if there is, try to resolve it before returning.
444 * 'net_lock' is read_locked when this function is called
445 */
446int bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr)
447{
448 int res = 1;
449
450 if (list_empty(&b_ptr->cong_links))
451 return 1;
452 spin_lock_bh(&b_ptr->publ.lock);
453 if (!bearer_push(b_ptr)) {
454 bearer_schedule_unlocked(b_ptr, l_ptr);
455 res = 0;
456 }
457 spin_unlock_bh(&b_ptr->publ.lock);
458 return res;
459}
460
461
462/**
463 * tipc_enable_bearer - enable bearer with the given name
464 */
465
466int tipc_enable_bearer(const char *name, u32 bcast_scope, u32 priority)
467{
468 struct bearer *b_ptr;
469 struct media *m_ptr;
470 struct bearer_name b_name;
471 char addr_string[16];
472 u32 bearer_id;
473 u32 with_this_prio;
474 u32 i;
475 int res = -EINVAL;
476
477 if (tipc_mode != TIPC_NET_MODE)
478 return -ENOPROTOOPT;
479 if (!bearer_name_validate(name, &b_name) ||
480 !addr_domain_valid(bcast_scope) ||
481 !in_scope(bcast_scope, tipc_own_addr) ||
482 (priority > TIPC_NUM_LINK_PRI))
483 return -EINVAL;
484
485 write_lock_bh(&net_lock);
486 if (!bearers)
487 goto failed;
488
489 m_ptr = media_find(b_name.media_name);
490 if (!m_ptr) {
491 warn("No media <%s>\n", b_name.media_name);
492 goto failed;
493 }
494 if (priority == TIPC_NUM_LINK_PRI)
495 priority = m_ptr->priority;
496
497restart:
498 bearer_id = MAX_BEARERS;
499 with_this_prio = 1;
500 for (i = MAX_BEARERS; i-- != 0; ) {
501 if (!bearers[i].active) {
502 bearer_id = i;
503 continue;
504 }
505 if (!strcmp(name, bearers[i].publ.name)) {
506 warn("Bearer <%s> already enabled\n", name);
507 goto failed;
508 }
509 if ((bearers[i].priority == priority) &&
510 (++with_this_prio > 2)) {
511 if (priority-- == 0) {
512 warn("Third bearer <%s> with priority %u, unable to lower to %u\n",
513 name, priority + 1, priority);
514 goto failed;
515 }
516 warn("Third bearer <%s> with priority %u, lowering to %u\n",
517 name, priority + 1, priority);
518 goto restart;
519 }
520 }
521 if (bearer_id >= MAX_BEARERS) {
522 warn("Attempt to enable more than %d bearers\n", MAX_BEARERS);
523 goto failed;
524 }
525
526 b_ptr = &bearers[bearer_id];
527 memset(b_ptr, 0, sizeof(struct bearer));
528
529 strcpy(b_ptr->publ.name, name);
530 res = m_ptr->enable_bearer(&b_ptr->publ);
531 if (res) {
532 warn("Failed to enable bearer <%s>\n", name);
533 goto failed;
534 }
535
536 b_ptr->identity = bearer_id;
537 b_ptr->media = m_ptr;
538 b_ptr->net_plane = bearer_id + 'A';
539 b_ptr->active = 1;
540 b_ptr->detect_scope = bcast_scope;
541 b_ptr->priority = priority;
542 INIT_LIST_HEAD(&b_ptr->cong_links);
543 INIT_LIST_HEAD(&b_ptr->links);
544 if (m_ptr->bcast) {
545 b_ptr->link_req = disc_init_link_req(b_ptr, &m_ptr->bcast_addr,
546 bcast_scope, 2);
547 }
548 b_ptr->publ.lock = SPIN_LOCK_UNLOCKED;
549 write_unlock_bh(&net_lock);
550 info("Enabled bearer <%s>, discovery domain %s\n",
551 name, addr_string_fill(addr_string, bcast_scope));
552 return 0;
553failed:
554 write_unlock_bh(&net_lock);
555 return res;
556}
557
558/**
559 * tipc_block_bearer(): Block the bearer with the given name,
560 * and reset all its links
561 */
562
563int tipc_block_bearer(const char *name)
564{
565 struct bearer *b_ptr = 0;
566 struct link *l_ptr;
567 struct link *temp_l_ptr;
568
569 if (tipc_mode != TIPC_NET_MODE)
570 return -ENOPROTOOPT;
571
572 read_lock_bh(&net_lock);
573 b_ptr = bearer_find(name);
574 if (!b_ptr) {
575 warn("Attempt to block unknown bearer <%s>\n", name);
576 read_unlock_bh(&net_lock);
577 return -EINVAL;
578 }
579
580 spin_lock_bh(&b_ptr->publ.lock);
581 b_ptr->publ.blocked = 1;
582 list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) {
583 struct node *n_ptr = l_ptr->owner;
584
585 spin_lock_bh(&n_ptr->lock);
586 link_reset(l_ptr);
587 spin_unlock_bh(&n_ptr->lock);
588 }
589 spin_unlock_bh(&b_ptr->publ.lock);
590 read_unlock_bh(&net_lock);
591 info("Blocked bearer <%s>\n", name);
592 return TIPC_OK;
593}
594
595/**
596 * bearer_disable -
597 *
598 * Note: This routine assumes caller holds net_lock.
599 */
600
601static int bearer_disable(const char *name)
602{
603 struct bearer *b_ptr;
604 struct link *l_ptr;
605 struct link *temp_l_ptr;
606
607 if (tipc_mode != TIPC_NET_MODE)
608 return -ENOPROTOOPT;
609
610 b_ptr = bearer_find(name);
611 if (!b_ptr) {
612 warn("Attempt to disable unknown bearer <%s>\n", name);
613 return -EINVAL;
614 }
615
616 disc_stop_link_req(b_ptr->link_req);
617 spin_lock_bh(&b_ptr->publ.lock);
618 b_ptr->link_req = NULL;
619 b_ptr->publ.blocked = 1;
620 if (b_ptr->media->disable_bearer) {
621 spin_unlock_bh(&b_ptr->publ.lock);
622 write_unlock_bh(&net_lock);
623 b_ptr->media->disable_bearer(&b_ptr->publ);
624 write_lock_bh(&net_lock);
625 spin_lock_bh(&b_ptr->publ.lock);
626 }
627 list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) {
628 link_delete(l_ptr);
629 }
630 spin_unlock_bh(&b_ptr->publ.lock);
631 info("Disabled bearer <%s>\n", name);
632 memset(b_ptr, 0, sizeof(struct bearer));
633 return TIPC_OK;
634}
635
636int tipc_disable_bearer(const char *name)
637{
638 int res;
639
640 write_lock_bh(&net_lock);
641 res = bearer_disable(name);
642 write_unlock_bh(&net_lock);
643 return res;
644}
645
646
647
648int bearer_init(void)
649{
650 int res;
651
652 write_lock_bh(&net_lock);
653 bearers = kmalloc(MAX_BEARERS * sizeof(struct bearer), GFP_ATOMIC);
654 media_list = kmalloc(MAX_MEDIA * sizeof(struct media), GFP_ATOMIC);
655 if (bearers && media_list) {
656 memset(bearers, 0, MAX_BEARERS * sizeof(struct bearer));
657 memset(media_list, 0, MAX_MEDIA * sizeof(struct media));
658 res = TIPC_OK;
659 } else {
660 kfree(bearers);
661 kfree(media_list);
662 bearers = 0;
663 media_list = 0;
664 res = -ENOMEM;
665 }
666 write_unlock_bh(&net_lock);
667 return res;
668}
669
670void bearer_stop(void)
671{
672 u32 i;
673
674 if (!bearers)
675 return;
676
677 for (i = 0; i < MAX_BEARERS; i++) {
678 if (bearers[i].active)
679 bearers[i].publ.blocked = 1;
680 }
681 for (i = 0; i < MAX_BEARERS; i++) {
682 if (bearers[i].active)
683 bearer_disable(bearers[i].publ.name);
684 }
685 kfree(bearers);
686 kfree(media_list);
687 bearers = 0;
688 media_list = 0;
689 media_count = 0;
690}
691
692
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h
new file mode 100644
index 000000000000..21e63d3f0183
--- /dev/null
+++ b/net/tipc/bearer.h
@@ -0,0 +1,172 @@
1/*
2 * net/tipc/bearer.h: Include file for TIPC bearer code
3 *
4 * Copyright (c) 1996-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#ifndef _TIPC_BEARER_H
38#define _TIPC_BEARER_H
39
40#include <net/tipc/tipc_bearer.h>
41#include "bcast.h"
42
43#define MAX_BEARERS 8
44#define MAX_MEDIA 4
45
46
47/**
48 * struct media - TIPC media information available to internal users
49 * @send_msg: routine which handles buffer transmission
50 * @enable_bearer: routine which enables a bearer
51 * @disable_bearer: routine which disables a bearer
52 * @addr2str: routine which converts bearer's address to string form
53 * @bcast_addr: media address used in broadcasting
54 * @bcast: non-zero if media supports broadcasting [currently mandatory]
55 * @priority: default link (and bearer) priority
56 * @tolerance: default time (in ms) before declaring link failure
57 * @window: default window (in packets) before declaring link congestion
58 * @type_id: TIPC media identifier [defined in tipc_bearer.h]
59 * @name: media name
60 */
61
62struct media {
63 int (*send_msg)(struct sk_buff *buf,
64 struct tipc_bearer *b_ptr,
65 struct tipc_media_addr *dest);
66 int (*enable_bearer)(struct tipc_bearer *b_ptr);
67 void (*disable_bearer)(struct tipc_bearer *b_ptr);
68 char *(*addr2str)(struct tipc_media_addr *a,
69 char *str_buf, int str_size);
70 struct tipc_media_addr bcast_addr;
71 int bcast;
72 u32 priority;
73 u32 tolerance;
74 u32 window;
75 u32 type_id;
76 char name[TIPC_MAX_MEDIA_NAME];
77};
78
79/**
80 * struct bearer - TIPC bearer information available to internal users
81 * @publ: bearer information available to privileged users
82 * @media: ptr to media structure associated with bearer
83 * @priority: default link priority for bearer
84 * @detect_scope: network address mask used during automatic link creation
85 * @identity: array index of this bearer within TIPC bearer array
86 * @link_req: ptr to (optional) structure making periodic link setup requests
87 * @links: list of non-congested links associated with bearer
88 * @cong_links: list of congested links associated with bearer
89 * @continue_count: # of times bearer has resumed after congestion or blocking
90 * @active: non-zero if bearer structure is represents a bearer
91 * @net_plane: network plane ('A' through 'H') currently associated with bearer
92 * @nodes: indicates which nodes in cluster can be reached through bearer
93 */
94
95struct bearer {
96 struct tipc_bearer publ;
97 struct media *media;
98 u32 priority;
99 u32 detect_scope;
100 u32 identity;
101 struct link_req *link_req;
102 struct list_head links;
103 struct list_head cong_links;
104 u32 continue_count;
105 int active;
106 char net_plane;
107 struct node_map nodes;
108};
109
110struct bearer_name {
111 char media_name[TIPC_MAX_MEDIA_NAME];
112 char if_name[TIPC_MAX_IF_NAME];
113};
114
115struct link;
116
117extern struct bearer *bearers;
118
119void media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a);
120struct sk_buff *media_get_names(void);
121
122struct sk_buff *bearer_get_names(void);
123void bearer_add_dest(struct bearer *b_ptr, u32 dest);
124void bearer_remove_dest(struct bearer *b_ptr, u32 dest);
125void bearer_schedule(struct bearer *b_ptr, struct link *l_ptr);
126struct bearer *bearer_find_interface(const char *if_name);
127int bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr);
128int bearer_init(void);
129void bearer_stop(void);
130int bearer_broadcast(struct sk_buff *buf, struct tipc_bearer *b_ptr,
131 struct tipc_media_addr *dest);
132void bearer_lock_push(struct bearer *b_ptr);
133
134
135/**
136 * bearer_send- sends buffer to destination over bearer
137 *
138 * Returns true (1) if successful, or false (0) if unable to send
139 *
140 * IMPORTANT:
141 * The media send routine must not alter the buffer being passed in
142 * as it may be needed for later retransmission!
143 *
144 * If the media send routine returns a non-zero value (indicating that
145 * it was unable to send the buffer), it must:
146 * 1) mark the bearer as blocked,
147 * 2) call tipc_continue() once the bearer is able to send again.
148 * Media types that are unable to meet these two critera must ensure their
149 * send routine always returns success -- even if the buffer was not sent --
150 * and let TIPC's link code deal with the undelivered message.
151 */
152
153static inline int bearer_send(struct bearer *b_ptr, struct sk_buff *buf,
154 struct tipc_media_addr *dest)
155{
156 return !b_ptr->media->send_msg(buf, &b_ptr->publ, dest);
157}
158
159/**
160 * bearer_congested - determines if bearer is currently congested
161 */
162
163static inline int bearer_congested(struct bearer *b_ptr, struct link *l_ptr)
164{
165 if (unlikely(b_ptr->publ.blocked))
166 return 1;
167 if (likely(list_empty(&b_ptr->cong_links)))
168 return 0;
169 return !bearer_resolve_congestion(b_ptr, l_ptr);
170}
171
172#endif
diff --git a/net/tipc/cluster.c b/net/tipc/cluster.c
new file mode 100644
index 000000000000..f0f7bac51d41
--- /dev/null
+++ b/net/tipc/cluster.c
@@ -0,0 +1,576 @@
1/*
2 * net/tipc/cluster.c: TIPC cluster management routines
3 *
4 * Copyright (c) 2000-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include "core.h"
38#include "cluster.h"
39#include "addr.h"
40#include "node_subscr.h"
41#include "link.h"
42#include "node.h"
43#include "net.h"
44#include "msg.h"
45#include "bearer.h"
46
47void cluster_multicast(struct cluster *c_ptr, struct sk_buff *buf,
48 u32 lower, u32 upper);
49struct sk_buff *cluster_prepare_routing_msg(u32 data_size, u32 dest);
50
51struct node **local_nodes = 0;
52struct node_map cluster_bcast_nodes = {0,{0,}};
53u32 highest_allowed_slave = 0;
54
55struct cluster *cluster_create(u32 addr)
56{
57 struct _zone *z_ptr;
58 struct cluster *c_ptr;
59 int max_nodes;
60 int alloc;
61
62 c_ptr = (struct cluster *)kmalloc(sizeof(*c_ptr), GFP_ATOMIC);
63 if (c_ptr == NULL)
64 return 0;
65 memset(c_ptr, 0, sizeof(*c_ptr));
66
67 c_ptr->addr = tipc_addr(tipc_zone(addr), tipc_cluster(addr), 0);
68 if (in_own_cluster(addr))
69 max_nodes = LOWEST_SLAVE + tipc_max_slaves;
70 else
71 max_nodes = tipc_max_nodes + 1;
72 alloc = sizeof(void *) * (max_nodes + 1);
73 c_ptr->nodes = (struct node **)kmalloc(alloc, GFP_ATOMIC);
74 if (c_ptr->nodes == NULL) {
75 kfree(c_ptr);
76 return 0;
77 }
78 memset(c_ptr->nodes, 0, alloc);
79 if (in_own_cluster(addr))
80 local_nodes = c_ptr->nodes;
81 c_ptr->highest_slave = LOWEST_SLAVE - 1;
82 c_ptr->highest_node = 0;
83
84 z_ptr = zone_find(tipc_zone(addr));
85 if (z_ptr == NULL) {
86 z_ptr = zone_create(addr);
87 }
88 if (z_ptr != NULL) {
89 zone_attach_cluster(z_ptr, c_ptr);
90 c_ptr->owner = z_ptr;
91 }
92 else {
93 kfree(c_ptr);
94 c_ptr = 0;
95 }
96
97 return c_ptr;
98}
99
100void cluster_delete(struct cluster *c_ptr)
101{
102 u32 n_num;
103
104 if (!c_ptr)
105 return;
106 for (n_num = 1; n_num <= c_ptr->highest_node; n_num++) {
107 node_delete(c_ptr->nodes[n_num]);
108 }
109 for (n_num = LOWEST_SLAVE; n_num <= c_ptr->highest_slave; n_num++) {
110 node_delete(c_ptr->nodes[n_num]);
111 }
112 kfree(c_ptr->nodes);
113 kfree(c_ptr);
114}
115
116u32 cluster_next_node(struct cluster *c_ptr, u32 addr)
117{
118 struct node *n_ptr;
119 u32 n_num = tipc_node(addr) + 1;
120
121 if (!c_ptr)
122 return addr;
123 for (; n_num <= c_ptr->highest_node; n_num++) {
124 n_ptr = c_ptr->nodes[n_num];
125 if (n_ptr && node_has_active_links(n_ptr))
126 return n_ptr->addr;
127 }
128 for (n_num = 1; n_num < tipc_node(addr); n_num++) {
129 n_ptr = c_ptr->nodes[n_num];
130 if (n_ptr && node_has_active_links(n_ptr))
131 return n_ptr->addr;
132 }
133 return 0;
134}
135
136void cluster_attach_node(struct cluster *c_ptr, struct node *n_ptr)
137{
138 u32 n_num = tipc_node(n_ptr->addr);
139 u32 max_n_num = tipc_max_nodes;
140
141 if (in_own_cluster(n_ptr->addr))
142 max_n_num = highest_allowed_slave;
143 assert(n_num > 0);
144 assert(n_num <= max_n_num);
145 assert(c_ptr->nodes[n_num] == 0);
146 c_ptr->nodes[n_num] = n_ptr;
147 if (n_num > c_ptr->highest_node)
148 c_ptr->highest_node = n_num;
149}
150
151/**
152 * cluster_select_router - select router to a cluster
153 *
154 * Uses deterministic and fair algorithm.
155 */
156
157u32 cluster_select_router(struct cluster *c_ptr, u32 ref)
158{
159 u32 n_num;
160 u32 ulim = c_ptr->highest_node;
161 u32 mask;
162 u32 tstart;
163
164 assert(!in_own_cluster(c_ptr->addr));
165 if (!ulim)
166 return 0;
167
168 /* Start entry must be random */
169 mask = tipc_max_nodes;
170 while (mask > ulim)
171 mask >>= 1;
172 tstart = ref & mask;
173 n_num = tstart;
174
175 /* Lookup upwards with wrap-around */
176 do {
177 if (node_is_up(c_ptr->nodes[n_num]))
178 break;
179 } while (++n_num <= ulim);
180 if (n_num > ulim) {
181 n_num = 1;
182 do {
183 if (node_is_up(c_ptr->nodes[n_num]))
184 break;
185 } while (++n_num < tstart);
186 if (n_num == tstart)
187 return 0;
188 }
189 assert(n_num <= ulim);
190 return node_select_router(c_ptr->nodes[n_num], ref);
191}
192
193/**
194 * cluster_select_node - select destination node within a remote cluster
195 *
196 * Uses deterministic and fair algorithm.
197 */
198
199struct node *cluster_select_node(struct cluster *c_ptr, u32 selector)
200{
201 u32 n_num;
202 u32 mask = tipc_max_nodes;
203 u32 start_entry;
204
205 assert(!in_own_cluster(c_ptr->addr));
206 if (!c_ptr->highest_node)
207 return 0;
208
209 /* Start entry must be random */
210 while (mask > c_ptr->highest_node) {
211 mask >>= 1;
212 }
213 start_entry = (selector & mask) ? selector & mask : 1u;
214 assert(start_entry <= c_ptr->highest_node);
215
216 /* Lookup upwards with wrap-around */
217 for (n_num = start_entry; n_num <= c_ptr->highest_node; n_num++) {
218 if (node_has_active_links(c_ptr->nodes[n_num]))
219 return c_ptr->nodes[n_num];
220 }
221 for (n_num = 1; n_num < start_entry; n_num++) {
222 if (node_has_active_links(c_ptr->nodes[n_num]))
223 return c_ptr->nodes[n_num];
224 }
225 return 0;
226}
227
228/*
229 * Routing table management: See description in node.c
230 */
231
232struct sk_buff *cluster_prepare_routing_msg(u32 data_size, u32 dest)
233{
234 u32 size = INT_H_SIZE + data_size;
235 struct sk_buff *buf = buf_acquire(size);
236 struct tipc_msg *msg;
237
238 if (buf) {
239 msg = buf_msg(buf);
240 memset((char *)msg, 0, size);
241 msg_init(msg, ROUTE_DISTRIBUTOR, 0, TIPC_OK, INT_H_SIZE, dest);
242 }
243 return buf;
244}
245
246void cluster_bcast_new_route(struct cluster *c_ptr, u32 dest,
247 u32 lower, u32 upper)
248{
249 struct sk_buff *buf = cluster_prepare_routing_msg(0, c_ptr->addr);
250 struct tipc_msg *msg;
251
252 if (buf) {
253 msg = buf_msg(buf);
254 msg_set_remote_node(msg, dest);
255 msg_set_type(msg, ROUTE_ADDITION);
256 cluster_multicast(c_ptr, buf, lower, upper);
257 } else {
258 warn("Memory squeeze: broadcast of new route failed\n");
259 }
260}
261
262void cluster_bcast_lost_route(struct cluster *c_ptr, u32 dest,
263 u32 lower, u32 upper)
264{
265 struct sk_buff *buf = cluster_prepare_routing_msg(0, c_ptr->addr);
266 struct tipc_msg *msg;
267
268 if (buf) {
269 msg = buf_msg(buf);
270 msg_set_remote_node(msg, dest);
271 msg_set_type(msg, ROUTE_REMOVAL);
272 cluster_multicast(c_ptr, buf, lower, upper);
273 } else {
274 warn("Memory squeeze: broadcast of lost route failed\n");
275 }
276}
277
278void cluster_send_slave_routes(struct cluster *c_ptr, u32 dest)
279{
280 struct sk_buff *buf;
281 struct tipc_msg *msg;
282 u32 highest = c_ptr->highest_slave;
283 u32 n_num;
284 int send = 0;
285
286 assert(!is_slave(dest));
287 assert(in_own_cluster(dest));
288 assert(in_own_cluster(c_ptr->addr));
289 if (highest <= LOWEST_SLAVE)
290 return;
291 buf = cluster_prepare_routing_msg(highest - LOWEST_SLAVE + 1,
292 c_ptr->addr);
293 if (buf) {
294 msg = buf_msg(buf);
295 msg_set_remote_node(msg, c_ptr->addr);
296 msg_set_type(msg, SLAVE_ROUTING_TABLE);
297 for (n_num = LOWEST_SLAVE; n_num <= highest; n_num++) {
298 if (c_ptr->nodes[n_num] &&
299 node_has_active_links(c_ptr->nodes[n_num])) {
300 send = 1;
301 msg_set_dataoctet(msg, n_num);
302 }
303 }
304 if (send)
305 link_send(buf, dest, dest);
306 else
307 buf_discard(buf);
308 } else {
309 warn("Memory squeeze: broadcast of lost route failed\n");
310 }
311}
312
313void cluster_send_ext_routes(struct cluster *c_ptr, u32 dest)
314{
315 struct sk_buff *buf;
316 struct tipc_msg *msg;
317 u32 highest = c_ptr->highest_node;
318 u32 n_num;
319 int send = 0;
320
321 if (in_own_cluster(c_ptr->addr))
322 return;
323 assert(!is_slave(dest));
324 assert(in_own_cluster(dest));
325 highest = c_ptr->highest_node;
326 buf = cluster_prepare_routing_msg(highest + 1, c_ptr->addr);
327 if (buf) {
328 msg = buf_msg(buf);
329 msg_set_remote_node(msg, c_ptr->addr);
330 msg_set_type(msg, EXT_ROUTING_TABLE);
331 for (n_num = 1; n_num <= highest; n_num++) {
332 if (c_ptr->nodes[n_num] &&
333 node_has_active_links(c_ptr->nodes[n_num])) {
334 send = 1;
335 msg_set_dataoctet(msg, n_num);
336 }
337 }
338 if (send)
339 link_send(buf, dest, dest);
340 else
341 buf_discard(buf);
342 } else {
343 warn("Memory squeeze: broadcast of external route failed\n");
344 }
345}
346
347void cluster_send_local_routes(struct cluster *c_ptr, u32 dest)
348{
349 struct sk_buff *buf;
350 struct tipc_msg *msg;
351 u32 highest = c_ptr->highest_node;
352 u32 n_num;
353 int send = 0;
354
355 assert(is_slave(dest));
356 assert(in_own_cluster(c_ptr->addr));
357 buf = cluster_prepare_routing_msg(highest, c_ptr->addr);
358 if (buf) {
359 msg = buf_msg(buf);
360 msg_set_remote_node(msg, c_ptr->addr);
361 msg_set_type(msg, LOCAL_ROUTING_TABLE);
362 for (n_num = 1; n_num <= highest; n_num++) {
363 if (c_ptr->nodes[n_num] &&
364 node_has_active_links(c_ptr->nodes[n_num])) {
365 send = 1;
366 msg_set_dataoctet(msg, n_num);
367 }
368 }
369 if (send)
370 link_send(buf, dest, dest);
371 else
372 buf_discard(buf);
373 } else {
374 warn("Memory squeeze: broadcast of local route failed\n");
375 }
376}
377
378void cluster_recv_routing_table(struct sk_buff *buf)
379{
380 struct tipc_msg *msg = buf_msg(buf);
381 struct cluster *c_ptr;
382 struct node *n_ptr;
383 unchar *node_table;
384 u32 table_size;
385 u32 router;
386 u32 rem_node = msg_remote_node(msg);
387 u32 z_num;
388 u32 c_num;
389 u32 n_num;
390
391 c_ptr = cluster_find(rem_node);
392 if (!c_ptr) {
393 c_ptr = cluster_create(rem_node);
394 if (!c_ptr) {
395 buf_discard(buf);
396 return;
397 }
398 }
399
400 node_table = buf->data + msg_hdr_sz(msg);
401 table_size = msg_size(msg) - msg_hdr_sz(msg);
402 router = msg_prevnode(msg);
403 z_num = tipc_zone(rem_node);
404 c_num = tipc_cluster(rem_node);
405
406 switch (msg_type(msg)) {
407 case LOCAL_ROUTING_TABLE:
408 assert(is_slave(tipc_own_addr));
409 case EXT_ROUTING_TABLE:
410 for (n_num = 1; n_num < table_size; n_num++) {
411 if (node_table[n_num]) {
412 u32 addr = tipc_addr(z_num, c_num, n_num);
413 n_ptr = c_ptr->nodes[n_num];
414 if (!n_ptr) {
415 n_ptr = node_create(addr);
416 }
417 if (n_ptr)
418 node_add_router(n_ptr, router);
419 }
420 }
421 break;
422 case SLAVE_ROUTING_TABLE:
423 assert(!is_slave(tipc_own_addr));
424 assert(in_own_cluster(c_ptr->addr));
425 for (n_num = 1; n_num < table_size; n_num++) {
426 if (node_table[n_num]) {
427 u32 slave_num = n_num + LOWEST_SLAVE;
428 u32 addr = tipc_addr(z_num, c_num, slave_num);
429 n_ptr = c_ptr->nodes[slave_num];
430 if (!n_ptr) {
431 n_ptr = node_create(addr);
432 }
433 if (n_ptr)
434 node_add_router(n_ptr, router);
435 }
436 }
437 break;
438 case ROUTE_ADDITION:
439 if (!is_slave(tipc_own_addr)) {
440 assert(!in_own_cluster(c_ptr->addr)
441 || is_slave(rem_node));
442 } else {
443 assert(in_own_cluster(c_ptr->addr)
444 && !is_slave(rem_node));
445 }
446 n_ptr = c_ptr->nodes[tipc_node(rem_node)];
447 if (!n_ptr)
448 n_ptr = node_create(rem_node);
449 if (n_ptr)
450 node_add_router(n_ptr, router);
451 break;
452 case ROUTE_REMOVAL:
453 if (!is_slave(tipc_own_addr)) {
454 assert(!in_own_cluster(c_ptr->addr)
455 || is_slave(rem_node));
456 } else {
457 assert(in_own_cluster(c_ptr->addr)
458 && !is_slave(rem_node));
459 }
460 n_ptr = c_ptr->nodes[tipc_node(rem_node)];
461 if (n_ptr)
462 node_remove_router(n_ptr, router);
463 break;
464 default:
465 assert(!"Illegal routing manager message received\n");
466 }
467 buf_discard(buf);
468}
469
470void cluster_remove_as_router(struct cluster *c_ptr, u32 router)
471{
472 u32 start_entry;
473 u32 tstop;
474 u32 n_num;
475
476 if (is_slave(router))
477 return; /* Slave nodes can not be routers */
478
479 if (in_own_cluster(c_ptr->addr)) {
480 start_entry = LOWEST_SLAVE;
481 tstop = c_ptr->highest_slave;
482 } else {
483 start_entry = 1;
484 tstop = c_ptr->highest_node;
485 }
486
487 for (n_num = start_entry; n_num <= tstop; n_num++) {
488 if (c_ptr->nodes[n_num]) {
489 node_remove_router(c_ptr->nodes[n_num], router);
490 }
491 }
492}
493
494/**
495 * cluster_multicast - multicast message to local nodes
496 */
497
498void cluster_multicast(struct cluster *c_ptr, struct sk_buff *buf,
499 u32 lower, u32 upper)
500{
501 struct sk_buff *buf_copy;
502 struct node *n_ptr;
503 u32 n_num;
504 u32 tstop;
505
506 assert(lower <= upper);
507 assert(((lower >= 1) && (lower <= tipc_max_nodes)) ||
508 ((lower >= LOWEST_SLAVE) && (lower <= highest_allowed_slave)));
509 assert(((upper >= 1) && (upper <= tipc_max_nodes)) ||
510 ((upper >= LOWEST_SLAVE) && (upper <= highest_allowed_slave)));
511 assert(in_own_cluster(c_ptr->addr));
512
513 tstop = is_slave(upper) ? c_ptr->highest_slave : c_ptr->highest_node;
514 if (tstop > upper)
515 tstop = upper;
516 for (n_num = lower; n_num <= tstop; n_num++) {
517 n_ptr = c_ptr->nodes[n_num];
518 if (n_ptr && node_has_active_links(n_ptr)) {
519 buf_copy = skb_copy(buf, GFP_ATOMIC);
520 if (buf_copy == NULL)
521 break;
522 msg_set_destnode(buf_msg(buf_copy), n_ptr->addr);
523 link_send(buf_copy, n_ptr->addr, n_ptr->addr);
524 }
525 }
526 buf_discard(buf);
527}
528
529/**
530 * cluster_broadcast - broadcast message to all nodes within cluster
531 */
532
533void cluster_broadcast(struct sk_buff *buf)
534{
535 struct sk_buff *buf_copy;
536 struct cluster *c_ptr;
537 struct node *n_ptr;
538 u32 n_num;
539 u32 tstart;
540 u32 tstop;
541 u32 node_type;
542
543 if (tipc_mode == TIPC_NET_MODE) {
544 c_ptr = cluster_find(tipc_own_addr);
545 assert(in_own_cluster(c_ptr->addr)); /* For now */
546
547 /* Send to standard nodes, then repeat loop sending to slaves */
548 tstart = 1;
549 tstop = c_ptr->highest_node;
550 for (node_type = 1; node_type <= 2; node_type++) {
551 for (n_num = tstart; n_num <= tstop; n_num++) {
552 n_ptr = c_ptr->nodes[n_num];
553 if (n_ptr && node_has_active_links(n_ptr)) {
554 buf_copy = skb_copy(buf, GFP_ATOMIC);
555 if (buf_copy == NULL)
556 goto exit;
557 msg_set_destnode(buf_msg(buf_copy),
558 n_ptr->addr);
559 link_send(buf_copy, n_ptr->addr,
560 n_ptr->addr);
561 }
562 }
563 tstart = LOWEST_SLAVE;
564 tstop = c_ptr->highest_slave;
565 }
566 }
567exit:
568 buf_discard(buf);
569}
570
571int cluster_init(void)
572{
573 highest_allowed_slave = LOWEST_SLAVE + tipc_max_slaves;
574 return cluster_create(tipc_own_addr) ? TIPC_OK : -ENOMEM;
575}
576
diff --git a/net/tipc/cluster.h b/net/tipc/cluster.h
new file mode 100644
index 000000000000..1ffb095991df
--- /dev/null
+++ b/net/tipc/cluster.h
@@ -0,0 +1,92 @@
1/*
2 * net/tipc/cluster.h: Include file for TIPC cluster management routines
3 *
4 * Copyright (c) 2000-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#ifndef _TIPC_CLUSTER_H
38#define _TIPC_CLUSTER_H
39
40#include "addr.h"
41#include "zone.h"
42
43#define LOWEST_SLAVE 2048u
44
45/**
46 * struct cluster - TIPC cluster structure
47 * @addr: network address of cluster
48 * @owner: pointer to zone that cluster belongs to
49 * @nodes: array of pointers to all nodes within cluster
50 * @highest_node: id of highest numbered node within cluster
51 * @highest_slave: (used for secondary node support)
52 */
53
54struct cluster {
55 u32 addr;
56 struct _zone *owner;
57 struct node **nodes;
58 u32 highest_node;
59 u32 highest_slave;
60};
61
62
63extern struct node **local_nodes;
64extern u32 highest_allowed_slave;
65extern struct node_map cluster_bcast_nodes;
66
67void cluster_remove_as_router(struct cluster *c_ptr, u32 router);
68void cluster_send_ext_routes(struct cluster *c_ptr, u32 dest);
69struct node *cluster_select_node(struct cluster *c_ptr, u32 selector);
70u32 cluster_select_router(struct cluster *c_ptr, u32 ref);
71void cluster_recv_routing_table(struct sk_buff *buf);
72struct cluster *cluster_create(u32 addr);
73void cluster_delete(struct cluster *c_ptr);
74void cluster_attach_node(struct cluster *c_ptr, struct node *n_ptr);
75void cluster_send_slave_routes(struct cluster *c_ptr, u32 dest);
76void cluster_broadcast(struct sk_buff *buf);
77int cluster_init(void);
78u32 cluster_next_node(struct cluster *c_ptr, u32 addr);
79void cluster_bcast_new_route(struct cluster *c_ptr, u32 dest, u32 lo, u32 hi);
80void cluster_send_local_routes(struct cluster *c_ptr, u32 dest);
81void cluster_bcast_lost_route(struct cluster *c_ptr, u32 dest, u32 lo, u32 hi);
82
83static inline struct cluster *cluster_find(u32 addr)
84{
85 struct _zone *z_ptr = zone_find(addr);
86
87 if (z_ptr)
88 return z_ptr->clusters[1];
89 return 0;
90}
91
92#endif
diff --git a/net/tipc/config.c b/net/tipc/config.c
new file mode 100644
index 000000000000..8ddef4fce2c2
--- /dev/null
+++ b/net/tipc/config.c
@@ -0,0 +1,718 @@
1/*
2 * net/tipc/config.c: TIPC configuration management code
3 *
4 * Copyright (c) 2002-2006, Ericsson AB
5 * Copyright (c) 2004-2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include "core.h"
38#include "dbg.h"
39#include "bearer.h"
40#include "port.h"
41#include "link.h"
42#include "zone.h"
43#include "addr.h"
44#include "name_table.h"
45#include "node.h"
46#include "config.h"
47#include "discover.h"
48
49struct subscr_data {
50 char usr_handle[8];
51 u32 domain;
52 u32 port_ref;
53 struct list_head subd_list;
54};
55
56struct manager {
57 u32 user_ref;
58 u32 port_ref;
59 u32 subscr_ref;
60 u32 link_subscriptions;
61 struct list_head link_subscribers;
62};
63
64static struct manager mng = { 0};
65
66static spinlock_t config_lock = SPIN_LOCK_UNLOCKED;
67
68static const void *req_tlv_area; /* request message TLV area */
69static int req_tlv_space; /* request message TLV area size */
70static int rep_headroom; /* reply message headroom to use */
71
72
73void cfg_link_event(u32 addr, char *name, int up)
74{
75 /* TIPC DOESN'T HANDLE LINK EVENT SUBSCRIPTIONS AT THE MOMENT */
76}
77
78
79struct sk_buff *cfg_reply_alloc(int payload_size)
80{
81 struct sk_buff *buf;
82
83 buf = alloc_skb(rep_headroom + payload_size, GFP_ATOMIC);
84 if (buf)
85 skb_reserve(buf, rep_headroom);
86 return buf;
87}
88
89int cfg_append_tlv(struct sk_buff *buf, int tlv_type,
90 void *tlv_data, int tlv_data_size)
91{
92 struct tlv_desc *tlv = (struct tlv_desc *)buf->tail;
93 int new_tlv_space = TLV_SPACE(tlv_data_size);
94
95 if (skb_tailroom(buf) < new_tlv_space) {
96 dbg("cfg_append_tlv unable to append TLV\n");
97 return 0;
98 }
99 skb_put(buf, new_tlv_space);
100 tlv->tlv_type = htons(tlv_type);
101 tlv->tlv_len = htons(TLV_LENGTH(tlv_data_size));
102 if (tlv_data_size && tlv_data)
103 memcpy(TLV_DATA(tlv), tlv_data, tlv_data_size);
104 return 1;
105}
106
107struct sk_buff *cfg_reply_unsigned_type(u16 tlv_type, u32 value)
108{
109 struct sk_buff *buf;
110 u32 value_net;
111
112 buf = cfg_reply_alloc(TLV_SPACE(sizeof(value)));
113 if (buf) {
114 value_net = htonl(value);
115 cfg_append_tlv(buf, tlv_type, &value_net,
116 sizeof(value_net));
117 }
118 return buf;
119}
120
121struct sk_buff *cfg_reply_string_type(u16 tlv_type, char *string)
122{
123 struct sk_buff *buf;
124 int string_len = strlen(string) + 1;
125
126 buf = cfg_reply_alloc(TLV_SPACE(string_len));
127 if (buf)
128 cfg_append_tlv(buf, tlv_type, string, string_len);
129 return buf;
130}
131
132
133
134
135#if 0
136
137/* Now obsolete code for handling commands not yet implemented the new way */
138
139int tipc_cfg_cmd(const struct tipc_cmd_msg * msg,
140 char *data,
141 u32 sz,
142 u32 *ret_size,
143 struct tipc_portid *orig)
144{
145 int rv = -EINVAL;
146 u32 cmd = msg->cmd;
147
148 *ret_size = 0;
149 switch (cmd) {
150 case TIPC_REMOVE_LINK:
151 case TIPC_CMD_BLOCK_LINK:
152 case TIPC_CMD_UNBLOCK_LINK:
153 if (!cfg_check_connection(orig))
154 rv = link_control(msg->argv.link_name, msg->cmd, 0);
155 break;
156 case TIPC_ESTABLISH:
157 {
158 int connected;
159
160 tipc_isconnected(mng.conn_port_ref, &connected);
161 if (connected || !orig) {
162 rv = TIPC_FAILURE;
163 break;
164 }
165 rv = tipc_connect2port(mng.conn_port_ref, orig);
166 if (rv == TIPC_OK)
167 orig = 0;
168 break;
169 }
170 case TIPC_GET_PEER_ADDRESS:
171 *ret_size = link_peer_addr(msg->argv.link_name, data, sz);
172 break;
173 case TIPC_GET_ROUTES:
174 rv = TIPC_OK;
175 break;
176 default: {}
177 }
178 if (*ret_size)
179 rv = TIPC_OK;
180 return rv;
181}
182
183static void cfg_cmd_event(struct tipc_cmd_msg *msg,
184 char *data,
185 u32 sz,
186 struct tipc_portid const *orig)
187{
188 int rv = -EINVAL;
189 struct tipc_cmd_result_msg rmsg;
190 struct iovec msg_sect[2];
191 int *arg;
192
193 msg->cmd = ntohl(msg->cmd);
194
195 cfg_prepare_res_msg(msg->cmd, msg->usr_handle, rv, &rmsg, msg_sect,
196 data, 0);
197 if (ntohl(msg->magic) != TIPC_MAGIC)
198 goto exit;
199
200 switch (msg->cmd) {
201 case TIPC_CREATE_LINK:
202 if (!cfg_check_connection(orig))
203 rv = disc_create_link(&msg->argv.create_link);
204 break;
205 case TIPC_LINK_SUBSCRIBE:
206 {
207 struct subscr_data *sub;
208
209 if (mng.link_subscriptions > 64)
210 break;
211 sub = (struct subscr_data *)kmalloc(sizeof(*sub),
212 GFP_ATOMIC);
213 if (sub == NULL) {
214 warn("Memory squeeze; dropped remote link subscription\n");
215 break;
216 }
217 INIT_LIST_HEAD(&sub->subd_list);
218 tipc_createport(mng.user_ref,
219 (void *)sub,
220 TIPC_HIGH_IMPORTANCE,
221 0,
222 0,
223 (tipc_conn_shutdown_event)cfg_linksubscr_cancel,
224 0,
225 0,
226 (tipc_conn_msg_event)cfg_linksubscr_cancel,
227 0,
228 &sub->port_ref);
229 if (!sub->port_ref) {
230 kfree(sub);
231 break;
232 }
233 memcpy(sub->usr_handle,msg->usr_handle,
234 sizeof(sub->usr_handle));
235 sub->domain = msg->argv.domain;
236 list_add_tail(&sub->subd_list, &mng.link_subscribers);
237 tipc_connect2port(sub->port_ref, orig);
238 rmsg.retval = TIPC_OK;
239 tipc_send(sub->port_ref, 2u, msg_sect);
240 mng.link_subscriptions++;
241 return;
242 }
243 default:
244 rv = tipc_cfg_cmd(msg, data, sz, (u32 *)&msg_sect[1].iov_len, orig);
245 }
246 exit:
247 rmsg.result_len = htonl(msg_sect[1].iov_len);
248 rmsg.retval = htonl(rv);
249 cfg_respond(msg_sect, 2u, orig);
250}
251#endif
252
253static struct sk_buff *cfg_enable_bearer(void)
254{
255 struct tipc_bearer_config *args;
256
257 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_CONFIG))
258 return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
259
260 args = (struct tipc_bearer_config *)TLV_DATA(req_tlv_area);
261 if (tipc_enable_bearer(args->name,
262 ntohl(args->detect_scope),
263 ntohl(args->priority)))
264 return cfg_reply_error_string("unable to enable bearer");
265
266 return cfg_reply_none();
267}
268
269static struct sk_buff *cfg_disable_bearer(void)
270{
271 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_NAME))
272 return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
273
274 if (tipc_disable_bearer((char *)TLV_DATA(req_tlv_area)))
275 return cfg_reply_error_string("unable to disable bearer");
276
277 return cfg_reply_none();
278}
279
280static struct sk_buff *cfg_set_own_addr(void)
281{
282 u32 addr;
283
284 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
285 return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
286
287 addr = *(u32 *)TLV_DATA(req_tlv_area);
288 addr = ntohl(addr);
289 if (addr == tipc_own_addr)
290 return cfg_reply_none();
291 if (!addr_node_valid(addr))
292 return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
293 " (node address)");
294 if (tipc_own_addr)
295 return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
296 " (cannot change node address once assigned)");
297
298 spin_unlock_bh(&config_lock);
299 stop_net();
300 tipc_own_addr = addr;
301 start_net();
302 spin_lock_bh(&config_lock);
303 return cfg_reply_none();
304}
305
306static struct sk_buff *cfg_set_remote_mng(void)
307{
308 u32 value;
309
310 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
311 return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
312
313 value = *(u32 *)TLV_DATA(req_tlv_area);
314 value = ntohl(value);
315 tipc_remote_management = (value != 0);
316 return cfg_reply_none();
317}
318
319static struct sk_buff *cfg_set_max_publications(void)
320{
321 u32 value;
322
323 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
324 return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
325
326 value = *(u32 *)TLV_DATA(req_tlv_area);
327 value = ntohl(value);
328 if (value != delimit(value, 1, 65535))
329 return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
330 " (max publications must be 1-65535)");
331 tipc_max_publications = value;
332 return cfg_reply_none();
333}
334
335static struct sk_buff *cfg_set_max_subscriptions(void)
336{
337 u32 value;
338
339 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
340 return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
341
342 value = *(u32 *)TLV_DATA(req_tlv_area);
343 value = ntohl(value);
344 if (value != delimit(value, 1, 65535))
345 return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
346 " (max subscriptions must be 1-65535");
347 tipc_max_subscriptions = value;
348 return cfg_reply_none();
349}
350
351static struct sk_buff *cfg_set_max_ports(void)
352{
353 int orig_mode;
354 u32 value;
355
356 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
357 return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
358 value = *(u32 *)TLV_DATA(req_tlv_area);
359 value = ntohl(value);
360 if (value != delimit(value, 127, 65535))
361 return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
362 " (max ports must be 127-65535)");
363
364 if (value == tipc_max_ports)
365 return cfg_reply_none();
366
367 if (atomic_read(&tipc_user_count) > 2)
368 return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
369 " (cannot change max ports while TIPC users exist)");
370
371 spin_unlock_bh(&config_lock);
372 orig_mode = tipc_get_mode();
373 if (orig_mode == TIPC_NET_MODE)
374 stop_net();
375 stop_core();
376 tipc_max_ports = value;
377 start_core();
378 if (orig_mode == TIPC_NET_MODE)
379 start_net();
380 spin_lock_bh(&config_lock);
381 return cfg_reply_none();
382}
383
384static struct sk_buff *set_net_max(int value, int *parameter)
385{
386 int orig_mode;
387
388 if (value != *parameter) {
389 orig_mode = tipc_get_mode();
390 if (orig_mode == TIPC_NET_MODE)
391 stop_net();
392 *parameter = value;
393 if (orig_mode == TIPC_NET_MODE)
394 start_net();
395 }
396
397 return cfg_reply_none();
398}
399
400static struct sk_buff *cfg_set_max_zones(void)
401{
402 u32 value;
403
404 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
405 return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
406 value = *(u32 *)TLV_DATA(req_tlv_area);
407 value = ntohl(value);
408 if (value != delimit(value, 1, 255))
409 return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
410 " (max zones must be 1-255)");
411 return set_net_max(value, &tipc_max_zones);
412}
413
414static struct sk_buff *cfg_set_max_clusters(void)
415{
416 u32 value;
417
418 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
419 return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
420 value = *(u32 *)TLV_DATA(req_tlv_area);
421 value = ntohl(value);
422 if (value != 1)
423 return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
424 " (max clusters fixed at 1)");
425 return cfg_reply_none();
426}
427
428static struct sk_buff *cfg_set_max_nodes(void)
429{
430 u32 value;
431
432 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
433 return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
434 value = *(u32 *)TLV_DATA(req_tlv_area);
435 value = ntohl(value);
436 if (value != delimit(value, 8, 2047))
437 return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
438 " (max nodes must be 8-2047)");
439 return set_net_max(value, &tipc_max_nodes);
440}
441
442static struct sk_buff *cfg_set_max_slaves(void)
443{
444 u32 value;
445
446 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
447 return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
448 value = *(u32 *)TLV_DATA(req_tlv_area);
449 value = ntohl(value);
450 if (value != 0)
451 return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
452 " (max secondary nodes fixed at 0)");
453 return cfg_reply_none();
454}
455
456static struct sk_buff *cfg_set_netid(void)
457{
458 u32 value;
459
460 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
461 return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
462 value = *(u32 *)TLV_DATA(req_tlv_area);
463 value = ntohl(value);
464 if (value != delimit(value, 1, 9999))
465 return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
466 " (network id must be 1-9999)");
467
468 if (tipc_own_addr)
469 return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
470 " (cannot change network id once part of network)");
471
472 return set_net_max(value, &tipc_net_id);
473}
474
475struct sk_buff *cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area,
476 int request_space, int reply_headroom)
477{
478 struct sk_buff *rep_tlv_buf;
479
480 spin_lock_bh(&config_lock);
481
482 /* Save request and reply details in a well-known location */
483
484 req_tlv_area = request_area;
485 req_tlv_space = request_space;
486 rep_headroom = reply_headroom;
487
488 /* Check command authorization */
489
490 if (likely(orig_node == tipc_own_addr)) {
491 /* command is permitted */
492 } else if (cmd >= 0x8000) {
493 rep_tlv_buf = cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
494 " (cannot be done remotely)");
495 goto exit;
496 } else if (!tipc_remote_management) {
497 rep_tlv_buf = cfg_reply_error_string(TIPC_CFG_NO_REMOTE);
498 goto exit;
499 }
500 else if (cmd >= 0x4000) {
501 u32 domain = 0;
502
503 if ((nametbl_translate(TIPC_ZM_SRV, 0, &domain) == 0) ||
504 (domain != orig_node)) {
505 rep_tlv_buf = cfg_reply_error_string(TIPC_CFG_NOT_ZONE_MSTR);
506 goto exit;
507 }
508 }
509
510 /* Call appropriate processing routine */
511
512 switch (cmd) {
513 case TIPC_CMD_NOOP:
514 rep_tlv_buf = cfg_reply_none();
515 break;
516 case TIPC_CMD_GET_NODES:
517 rep_tlv_buf = node_get_nodes(req_tlv_area, req_tlv_space);
518 break;
519 case TIPC_CMD_GET_LINKS:
520 rep_tlv_buf = node_get_links(req_tlv_area, req_tlv_space);
521 break;
522 case TIPC_CMD_SHOW_LINK_STATS:
523 rep_tlv_buf = link_cmd_show_stats(req_tlv_area, req_tlv_space);
524 break;
525 case TIPC_CMD_RESET_LINK_STATS:
526 rep_tlv_buf = link_cmd_reset_stats(req_tlv_area, req_tlv_space);
527 break;
528 case TIPC_CMD_SHOW_NAME_TABLE:
529 rep_tlv_buf = nametbl_get(req_tlv_area, req_tlv_space);
530 break;
531 case TIPC_CMD_GET_BEARER_NAMES:
532 rep_tlv_buf = bearer_get_names();
533 break;
534 case TIPC_CMD_GET_MEDIA_NAMES:
535 rep_tlv_buf = media_get_names();
536 break;
537 case TIPC_CMD_SHOW_PORTS:
538 rep_tlv_buf = port_get_ports();
539 break;
540#if 0
541 case TIPC_CMD_SHOW_PORT_STATS:
542 rep_tlv_buf = port_show_stats(req_tlv_area, req_tlv_space);
543 break;
544 case TIPC_CMD_RESET_PORT_STATS:
545 rep_tlv_buf = cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED);
546 break;
547#endif
548 case TIPC_CMD_SET_LOG_SIZE:
549 rep_tlv_buf = log_resize(req_tlv_area, req_tlv_space);
550 break;
551 case TIPC_CMD_DUMP_LOG:
552 rep_tlv_buf = log_dump();
553 break;
554 case TIPC_CMD_SET_LINK_TOL:
555 case TIPC_CMD_SET_LINK_PRI:
556 case TIPC_CMD_SET_LINK_WINDOW:
557 rep_tlv_buf = link_cmd_config(req_tlv_area, req_tlv_space, cmd);
558 break;
559 case TIPC_CMD_ENABLE_BEARER:
560 rep_tlv_buf = cfg_enable_bearer();
561 break;
562 case TIPC_CMD_DISABLE_BEARER:
563 rep_tlv_buf = cfg_disable_bearer();
564 break;
565 case TIPC_CMD_SET_NODE_ADDR:
566 rep_tlv_buf = cfg_set_own_addr();
567 break;
568 case TIPC_CMD_SET_REMOTE_MNG:
569 rep_tlv_buf = cfg_set_remote_mng();
570 break;
571 case TIPC_CMD_SET_MAX_PORTS:
572 rep_tlv_buf = cfg_set_max_ports();
573 break;
574 case TIPC_CMD_SET_MAX_PUBL:
575 rep_tlv_buf = cfg_set_max_publications();
576 break;
577 case TIPC_CMD_SET_MAX_SUBSCR:
578 rep_tlv_buf = cfg_set_max_subscriptions();
579 break;
580 case TIPC_CMD_SET_MAX_ZONES:
581 rep_tlv_buf = cfg_set_max_zones();
582 break;
583 case TIPC_CMD_SET_MAX_CLUSTERS:
584 rep_tlv_buf = cfg_set_max_clusters();
585 break;
586 case TIPC_CMD_SET_MAX_NODES:
587 rep_tlv_buf = cfg_set_max_nodes();
588 break;
589 case TIPC_CMD_SET_MAX_SLAVES:
590 rep_tlv_buf = cfg_set_max_slaves();
591 break;
592 case TIPC_CMD_SET_NETID:
593 rep_tlv_buf = cfg_set_netid();
594 break;
595 case TIPC_CMD_GET_REMOTE_MNG:
596 rep_tlv_buf = cfg_reply_unsigned(tipc_remote_management);
597 break;
598 case TIPC_CMD_GET_MAX_PORTS:
599 rep_tlv_buf = cfg_reply_unsigned(tipc_max_ports);
600 break;
601 case TIPC_CMD_GET_MAX_PUBL:
602 rep_tlv_buf = cfg_reply_unsigned(tipc_max_publications);
603 break;
604 case TIPC_CMD_GET_MAX_SUBSCR:
605 rep_tlv_buf = cfg_reply_unsigned(tipc_max_subscriptions);
606 break;
607 case TIPC_CMD_GET_MAX_ZONES:
608 rep_tlv_buf = cfg_reply_unsigned(tipc_max_zones);
609 break;
610 case TIPC_CMD_GET_MAX_CLUSTERS:
611 rep_tlv_buf = cfg_reply_unsigned(tipc_max_clusters);
612 break;
613 case TIPC_CMD_GET_MAX_NODES:
614 rep_tlv_buf = cfg_reply_unsigned(tipc_max_nodes);
615 break;
616 case TIPC_CMD_GET_MAX_SLAVES:
617 rep_tlv_buf = cfg_reply_unsigned(tipc_max_slaves);
618 break;
619 case TIPC_CMD_GET_NETID:
620 rep_tlv_buf = cfg_reply_unsigned(tipc_net_id);
621 break;
622 default:
623 rep_tlv_buf = NULL;
624 break;
625 }
626
627 /* Return reply buffer */
628exit:
629 spin_unlock_bh(&config_lock);
630 return rep_tlv_buf;
631}
632
633static void cfg_named_msg_event(void *userdata,
634 u32 port_ref,
635 struct sk_buff **buf,
636 const unchar *msg,
637 u32 size,
638 u32 importance,
639 struct tipc_portid const *orig,
640 struct tipc_name_seq const *dest)
641{
642 struct tipc_cfg_msg_hdr *req_hdr;
643 struct tipc_cfg_msg_hdr *rep_hdr;
644 struct sk_buff *rep_buf;
645
646 /* Validate configuration message header (ignore invalid message) */
647
648 req_hdr = (struct tipc_cfg_msg_hdr *)msg;
649 if ((size < sizeof(*req_hdr)) ||
650 (size != TCM_ALIGN(ntohl(req_hdr->tcm_len))) ||
651 (ntohs(req_hdr->tcm_flags) != TCM_F_REQUEST)) {
652 warn("discarded invalid configuration message\n");
653 return;
654 }
655
656 /* Generate reply for request (if can't, return request) */
657
658 rep_buf = cfg_do_cmd(orig->node,
659 ntohs(req_hdr->tcm_type),
660 msg + sizeof(*req_hdr),
661 size - sizeof(*req_hdr),
662 BUF_HEADROOM + MAX_H_SIZE + sizeof(*rep_hdr));
663 if (rep_buf) {
664 skb_push(rep_buf, sizeof(*rep_hdr));
665 rep_hdr = (struct tipc_cfg_msg_hdr *)rep_buf->data;
666 memcpy(rep_hdr, req_hdr, sizeof(*rep_hdr));
667 rep_hdr->tcm_len = htonl(rep_buf->len);
668 rep_hdr->tcm_flags &= htons(~TCM_F_REQUEST);
669 } else {
670 rep_buf = *buf;
671 *buf = NULL;
672 }
673
674 /* NEED TO ADD CODE TO HANDLE FAILED SEND (SUCH AS CONGESTION) */
675 tipc_send_buf2port(port_ref, orig, rep_buf, rep_buf->len);
676}
677
678int cfg_init(void)
679{
680 struct tipc_name_seq seq;
681 int res;
682
683 memset(&mng, 0, sizeof(mng));
684 INIT_LIST_HEAD(&mng.link_subscribers);
685
686 res = tipc_attach(&mng.user_ref, 0, 0);
687 if (res)
688 goto failed;
689
690 res = tipc_createport(mng.user_ref, 0, TIPC_CRITICAL_IMPORTANCE,
691 NULL, NULL, NULL,
692 NULL, cfg_named_msg_event, NULL,
693 NULL, &mng.port_ref);
694 if (res)
695 goto failed;
696
697 seq.type = TIPC_CFG_SRV;
698 seq.lower = seq.upper = tipc_own_addr;
699 res = nametbl_publish_rsv(mng.port_ref, TIPC_ZONE_SCOPE, &seq);
700 if (res)
701 goto failed;
702
703 return 0;
704
705failed:
706 err("Unable to create configuration service\n");
707 tipc_detach(mng.user_ref);
708 mng.user_ref = 0;
709 return res;
710}
711
712void cfg_stop(void)
713{
714 if (mng.user_ref) {
715 tipc_detach(mng.user_ref);
716 mng.user_ref = 0;
717 }
718}
diff --git a/net/tipc/config.h b/net/tipc/config.h
new file mode 100644
index 000000000000..646377d40454
--- /dev/null
+++ b/net/tipc/config.h
@@ -0,0 +1,80 @@
1/*
2 * net/tipc/config.h: Include file for TIPC configuration service code
3 *
4 * Copyright (c) 2003-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#ifndef _TIPC_CONFIG_H
38#define _TIPC_CONFIG_H
39
40/* ---------------------------------------------------------------------- */
41
42#include <linux/tipc.h>
43#include <linux/tipc_config.h>
44#include "link.h"
45
46struct sk_buff *cfg_reply_alloc(int payload_size);
47int cfg_append_tlv(struct sk_buff *buf, int tlv_type,
48 void *tlv_data, int tlv_data_size);
49struct sk_buff *cfg_reply_unsigned_type(u16 tlv_type, u32 value);
50struct sk_buff *cfg_reply_string_type(u16 tlv_type, char *string);
51
52static inline struct sk_buff *cfg_reply_none(void)
53{
54 return cfg_reply_alloc(0);
55}
56
57static inline struct sk_buff *cfg_reply_unsigned(u32 value)
58{
59 return cfg_reply_unsigned_type(TIPC_TLV_UNSIGNED, value);
60}
61
62static inline struct sk_buff *cfg_reply_error_string(char *string)
63{
64 return cfg_reply_string_type(TIPC_TLV_ERROR_STRING, string);
65}
66
67static inline struct sk_buff *cfg_reply_ultra_string(char *string)
68{
69 return cfg_reply_string_type(TIPC_TLV_ULTRA_STRING, string);
70}
71
72struct sk_buff *cfg_do_cmd(u32 orig_node, u16 cmd,
73 const void *req_tlv_area, int req_tlv_space,
74 int headroom);
75
76void cfg_link_event(u32 addr, char *name, int up);
77int cfg_init(void);
78void cfg_stop(void);
79
80#endif
diff --git a/net/tipc/core.c b/net/tipc/core.c
new file mode 100644
index 000000000000..e83ac06e31ba
--- /dev/null
+++ b/net/tipc/core.c
@@ -0,0 +1,285 @@
1/*
2 * net/tipc/core.c: TIPC module code
3 *
4 * Copyright (c) 2003-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include <linux/init.h>
38#include <linux/module.h>
39#include <linux/kernel.h>
40#include <linux/version.h>
41#include <linux/random.h>
42
43#include "core.h"
44#include "dbg.h"
45#include "ref.h"
46#include "net.h"
47#include "user_reg.h"
48#include "name_table.h"
49#include "subscr.h"
50#include "config.h"
51
52int eth_media_start(void);
53void eth_media_stop(void);
54int handler_start(void);
55void handler_stop(void);
56int socket_init(void);
57void socket_stop(void);
58int netlink_start(void);
59void netlink_stop(void);
60
61#define MOD_NAME "tipc_start: "
62
63#ifndef CONFIG_TIPC_ZONES
64#define CONFIG_TIPC_ZONES 3
65#endif
66
67#ifndef CONFIG_TIPC_CLUSTERS
68#define CONFIG_TIPC_CLUSTERS 1
69#endif
70
71#ifndef CONFIG_TIPC_NODES
72#define CONFIG_TIPC_NODES 255
73#endif
74
75#ifndef CONFIG_TIPC_SLAVE_NODES
76#define CONFIG_TIPC_SLAVE_NODES 0
77#endif
78
79#ifndef CONFIG_TIPC_PORTS
80#define CONFIG_TIPC_PORTS 8191
81#endif
82
83#ifndef CONFIG_TIPC_LOG
84#define CONFIG_TIPC_LOG 0
85#endif
86
87/* global variables used by multiple sub-systems within TIPC */
88
89int tipc_mode = TIPC_NOT_RUNNING;
90int tipc_random;
91atomic_t tipc_user_count = ATOMIC_INIT(0);
92
93const char tipc_alphabet[] =
94 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
95
96/* configurable TIPC parameters */
97
98u32 tipc_own_addr;
99int tipc_max_zones;
100int tipc_max_clusters;
101int tipc_max_nodes;
102int tipc_max_slaves;
103int tipc_max_ports;
104int tipc_max_subscriptions;
105int tipc_max_publications;
106int tipc_net_id;
107int tipc_remote_management;
108
109
110int tipc_get_mode(void)
111{
112 return tipc_mode;
113}
114
115/**
116 * stop_net - shut down TIPC networking sub-systems
117 */
118
119void stop_net(void)
120{
121 eth_media_stop();
122 tipc_stop_net();
123}
124
125/**
126 * start_net - start TIPC networking sub-systems
127 */
128
129int start_net(void)
130{
131 int res;
132
133 if ((res = tipc_start_net()) ||
134 (res = eth_media_start())) {
135 stop_net();
136 }
137 return res;
138}
139
140/**
141 * stop_core - switch TIPC from SINGLE NODE to NOT RUNNING mode
142 */
143
144void stop_core(void)
145{
146 if (tipc_mode != TIPC_NODE_MODE)
147 return;
148
149 tipc_mode = TIPC_NOT_RUNNING;
150
151 netlink_stop();
152 handler_stop();
153 cfg_stop();
154 subscr_stop();
155 reg_stop();
156 nametbl_stop();
157 ref_table_stop();
158 socket_stop();
159}
160
161/**
162 * start_core - switch TIPC from NOT RUNNING to SINGLE NODE mode
163 */
164
165int start_core(void)
166{
167 int res;
168
169 if (tipc_mode != TIPC_NOT_RUNNING)
170 return -ENOPROTOOPT;
171
172 get_random_bytes(&tipc_random, sizeof(tipc_random));
173 tipc_mode = TIPC_NODE_MODE;
174
175 if ((res = handler_start()) ||
176 (res = ref_table_init(tipc_max_ports + tipc_max_subscriptions,
177 tipc_random)) ||
178 (res = reg_start()) ||
179 (res = nametbl_init()) ||
180 (res = k_signal((Handler)subscr_start, 0)) ||
181 (res = k_signal((Handler)cfg_init, 0)) ||
182 (res = netlink_start()) ||
183 (res = socket_init())) {
184 stop_core();
185 }
186 return res;
187}
188
189
190static int __init tipc_init(void)
191{
192 int res;
193
194 log_reinit(CONFIG_TIPC_LOG);
195 info("Activated (compiled " __DATE__ " " __TIME__ ")\n");
196
197 tipc_own_addr = 0;
198 tipc_remote_management = 1;
199 tipc_max_publications = 10000;
200 tipc_max_subscriptions = 2000;
201 tipc_max_ports = delimit(CONFIG_TIPC_PORTS, 127, 65536);
202 tipc_max_zones = delimit(CONFIG_TIPC_ZONES, 1, 511);
203 tipc_max_clusters = delimit(CONFIG_TIPC_CLUSTERS, 1, 1);
204 tipc_max_nodes = delimit(CONFIG_TIPC_NODES, 8, 2047);
205 tipc_max_slaves = delimit(CONFIG_TIPC_SLAVE_NODES, 0, 2047);
206 tipc_net_id = 4711;
207
208 if ((res = start_core()))
209 err("Unable to start in single node mode\n");
210 else
211 info("Started in single node mode\n");
212 return res;
213}
214
215static void __exit tipc_exit(void)
216{
217 stop_net();
218 stop_core();
219 info("Deactivated\n");
220 log_stop();
221}
222
223module_init(tipc_init);
224module_exit(tipc_exit);
225
226MODULE_DESCRIPTION("TIPC: Transparent Inter Process Communication");
227MODULE_LICENSE("Dual BSD/GPL");
228
229/* Native TIPC API for kernel-space applications (see tipc.h) */
230
231EXPORT_SYMBOL(tipc_attach);
232EXPORT_SYMBOL(tipc_detach);
233EXPORT_SYMBOL(tipc_get_addr);
234EXPORT_SYMBOL(tipc_get_mode);
235EXPORT_SYMBOL(tipc_createport);
236EXPORT_SYMBOL(tipc_deleteport);
237EXPORT_SYMBOL(tipc_ownidentity);
238EXPORT_SYMBOL(tipc_portimportance);
239EXPORT_SYMBOL(tipc_set_portimportance);
240EXPORT_SYMBOL(tipc_portunreliable);
241EXPORT_SYMBOL(tipc_set_portunreliable);
242EXPORT_SYMBOL(tipc_portunreturnable);
243EXPORT_SYMBOL(tipc_set_portunreturnable);
244EXPORT_SYMBOL(tipc_publish);
245EXPORT_SYMBOL(tipc_withdraw);
246EXPORT_SYMBOL(tipc_connect2port);
247EXPORT_SYMBOL(tipc_disconnect);
248EXPORT_SYMBOL(tipc_shutdown);
249EXPORT_SYMBOL(tipc_isconnected);
250EXPORT_SYMBOL(tipc_peer);
251EXPORT_SYMBOL(tipc_ref_valid);
252EXPORT_SYMBOL(tipc_send);
253EXPORT_SYMBOL(tipc_send_buf);
254EXPORT_SYMBOL(tipc_send2name);
255EXPORT_SYMBOL(tipc_forward2name);
256EXPORT_SYMBOL(tipc_send_buf2name);
257EXPORT_SYMBOL(tipc_forward_buf2name);
258EXPORT_SYMBOL(tipc_send2port);
259EXPORT_SYMBOL(tipc_forward2port);
260EXPORT_SYMBOL(tipc_send_buf2port);
261EXPORT_SYMBOL(tipc_forward_buf2port);
262EXPORT_SYMBOL(tipc_multicast);
263/* EXPORT_SYMBOL(tipc_multicast_buf); not available yet */
264EXPORT_SYMBOL(tipc_ispublished);
265EXPORT_SYMBOL(tipc_available_nodes);
266
267/* TIPC API for external bearers (see tipc_bearer.h) */
268
269EXPORT_SYMBOL(tipc_block_bearer);
270EXPORT_SYMBOL(tipc_continue);
271EXPORT_SYMBOL(tipc_disable_bearer);
272EXPORT_SYMBOL(tipc_enable_bearer);
273EXPORT_SYMBOL(tipc_recv_msg);
274EXPORT_SYMBOL(tipc_register_media);
275
276/* TIPC API for external APIs (see tipc_port.h) */
277
278EXPORT_SYMBOL(tipc_createport_raw);
279EXPORT_SYMBOL(tipc_set_msg_option);
280EXPORT_SYMBOL(tipc_reject_msg);
281EXPORT_SYMBOL(tipc_send_buf_fast);
282EXPORT_SYMBOL(tipc_acknowledge);
283EXPORT_SYMBOL(tipc_get_port);
284EXPORT_SYMBOL(tipc_get_handle);
285
diff --git a/net/tipc/core.h b/net/tipc/core.h
new file mode 100644
index 000000000000..b69b60b2cc86
--- /dev/null
+++ b/net/tipc/core.h
@@ -0,0 +1,316 @@
1/*
2 * net/tipc/core.h: Include file for TIPC global declarations
3 *
4 * Copyright (c) 2005-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#ifndef _TIPC_CORE_H
38#define _TIPC_CORE_H
39
40#include <net/tipc/tipc.h>
41#include <linux/types.h>
42#include <linux/kernel.h>
43#include <linux/errno.h>
44#include <linux/mm.h>
45#include <linux/timer.h>
46#include <linux/string.h>
47#include <asm/uaccess.h>
48#include <linux/interrupt.h>
49#include <asm/atomic.h>
50#include <asm/hardirq.h>
51#include <linux/netdevice.h>
52#include <linux/in.h>
53#include <linux/list.h>
54#include <linux/vmalloc.h>
55
56/*
57 * TIPC debugging code
58 */
59
60#define assert(i) BUG_ON(!(i))
61
62struct tipc_msg;
63extern struct print_buf *CONS, *LOG;
64extern struct print_buf *TEE(struct print_buf *, struct print_buf *);
65void msg_print(struct print_buf*,struct tipc_msg *,const char*);
66void tipc_printf(struct print_buf *, const char *fmt, ...);
67void tipc_dump(struct print_buf*,const char *fmt, ...);
68
69#ifdef CONFIG_TIPC_DEBUG
70
71/*
72 * TIPC debug support included:
73 * - system messages are printed to TIPC_OUTPUT print buffer
74 * - debug messages are printed to DBG_OUTPUT print buffer
75 */
76
77#define err(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_ERR "TIPC: " fmt, ## arg)
78#define warn(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_WARNING "TIPC: " fmt, ## arg)
79#define info(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_NOTICE "TIPC: " fmt, ## arg)
80
81#define dbg(fmt, arg...) do {if (DBG_OUTPUT) tipc_printf(DBG_OUTPUT, fmt, ## arg);} while(0)
82#define msg_dbg(msg, txt) do {if (DBG_OUTPUT) msg_print(DBG_OUTPUT, msg, txt);} while(0)
83#define dump(fmt, arg...) do {if (DBG_OUTPUT) tipc_dump(DBG_OUTPUT, fmt, ##arg);} while(0)
84
85
86/*
87 * By default, TIPC_OUTPUT is defined to be system console and TIPC log buffer,
88 * while DBG_OUTPUT is the null print buffer. These defaults can be changed
89 * here, or on a per .c file basis, by redefining these symbols. The following
90 * print buffer options are available:
91 *
92 * NULL : Output to null print buffer (i.e. print nowhere)
93 * CONS : Output to system console
94 * LOG : Output to TIPC log buffer
95 * &buf : Output to user-defined buffer (struct print_buf *)
96 * TEE(&buf_a,&buf_b) : Output to two print buffers (eg. TEE(CONS,LOG) )
97 */
98
99#ifndef TIPC_OUTPUT
100#define TIPC_OUTPUT TEE(CONS,LOG)
101#endif
102
103#ifndef DBG_OUTPUT
104#define DBG_OUTPUT NULL
105#endif
106
107#else
108
109#ifndef DBG_OUTPUT
110#define DBG_OUTPUT NULL
111#endif
112
113/*
114 * TIPC debug support not included:
115 * - system messages are printed to system console
116 * - debug messages are not printed
117 */
118
119#define err(fmt, arg...) printk(KERN_ERR "TIPC: " fmt , ## arg)
120#define info(fmt, arg...) printk(KERN_INFO "TIPC: " fmt , ## arg)
121#define warn(fmt, arg...) printk(KERN_WARNING "TIPC: " fmt , ## arg)
122
123#define dbg(fmt, arg...) do {} while (0)
124#define msg_dbg(msg,txt) do {} while (0)
125#define dump(fmt,arg...) do {} while (0)
126
127#endif
128
129
130/*
131 * TIPC-specific error codes
132 */
133
134#define ELINKCONG EAGAIN /* link congestion <=> resource unavailable */
135
136/*
137 * Global configuration variables
138 */
139
140extern u32 tipc_own_addr;
141extern int tipc_max_zones;
142extern int tipc_max_clusters;
143extern int tipc_max_nodes;
144extern int tipc_max_slaves;
145extern int tipc_max_ports;
146extern int tipc_max_subscriptions;
147extern int tipc_max_publications;
148extern int tipc_net_id;
149extern int tipc_remote_management;
150
151/*
152 * Other global variables
153 */
154
155extern int tipc_mode;
156extern int tipc_random;
157extern const char tipc_alphabet[];
158extern atomic_t tipc_user_count;
159
160
161/*
162 * Routines available to privileged subsystems
163 */
164
165extern int start_core(void);
166extern void stop_core(void);
167extern int start_net(void);
168extern void stop_net(void);
169
170static inline int delimit(int val, int min, int max)
171{
172 if (val > max)
173 return max;
174 if (val < min)
175 return min;
176 return val;
177}
178
179
180/*
181 * TIPC timer and signal code
182 */
183
184typedef void (*Handler) (unsigned long);
185
186u32 k_signal(Handler routine, unsigned long argument);
187
188/**
189 * k_init_timer - initialize a timer
190 * @timer: pointer to timer structure
191 * @routine: pointer to routine to invoke when timer expires
192 * @argument: value to pass to routine when timer expires
193 *
194 * Timer must be initialized before use (and terminated when no longer needed).
195 */
196
197static inline void k_init_timer(struct timer_list *timer, Handler routine,
198 unsigned long argument)
199{
200 dbg("initializing timer %p\n", timer);
201 init_timer(timer);
202 timer->function = routine;
203 timer->data = argument;
204}
205
206/**
207 * k_start_timer - start a timer
208 * @timer: pointer to timer structure
209 * @msec: time to delay (in ms)
210 *
211 * Schedules a previously initialized timer for later execution.
212 * If timer is already running, the new timeout overrides the previous request.
213 *
214 * To ensure the timer doesn't expire before the specified delay elapses,
215 * the amount of delay is rounded up when converting to the jiffies
216 * then an additional jiffy is added to account for the fact that
217 * the starting time may be in the middle of the current jiffy.
218 */
219
220static inline void k_start_timer(struct timer_list *timer, unsigned long msec)
221{
222 dbg("starting timer %p for %u\n", timer, msec);
223 mod_timer(timer, jiffies + msecs_to_jiffies(msec) + 1);
224}
225
226/**
227 * k_cancel_timer - cancel a timer
228 * @timer: pointer to timer structure
229 *
230 * Cancels a previously initialized timer.
231 * Can be called safely even if the timer is already inactive.
232 *
233 * WARNING: Must not be called when holding locks required by the timer's
234 * timeout routine, otherwise deadlock can occur on SMP systems!
235 */
236
237static inline void k_cancel_timer(struct timer_list *timer)
238{
239 dbg("cancelling timer %p\n", timer);
240 del_timer_sync(timer);
241}
242
243/**
244 * k_term_timer - terminate a timer
245 * @timer: pointer to timer structure
246 *
247 * Prevents further use of a previously initialized timer.
248 *
249 * WARNING: Caller must ensure timer isn't currently running.
250 *
251 * (Do not "enhance" this routine to automatically cancel an active timer,
252 * otherwise deadlock can arise when a timeout routine calls k_term_timer.)
253 */
254
255static inline void k_term_timer(struct timer_list *timer)
256{
257 dbg("terminating timer %p\n", timer);
258}
259
260
261/*
262 * TIPC message buffer code
263 *
264 * TIPC message buffer headroom leaves room for 14 byte Ethernet header,
265 * while ensuring TIPC header is word aligned for quicker access
266 */
267
268#define BUF_HEADROOM 16u
269
270struct tipc_skb_cb {
271 void *handle;
272};
273
274#define TIPC_SKB_CB(__skb) ((struct tipc_skb_cb *)&((__skb)->cb[0]))
275
276
277static inline struct tipc_msg *buf_msg(struct sk_buff *skb)
278{
279 return (struct tipc_msg *)skb->data;
280}
281
282/**
283 * buf_acquire - creates a TIPC message buffer
284 * @size: message size (including TIPC header)
285 *
286 * Returns a new buffer. Space is reserved for a data link header.
287 */
288
289static inline struct sk_buff *buf_acquire(u32 size)
290{
291 struct sk_buff *skb;
292 unsigned int buf_size = (BUF_HEADROOM + size + 3) & ~3u;
293
294 skb = alloc_skb(buf_size, GFP_ATOMIC);
295 if (skb) {
296 skb_reserve(skb, BUF_HEADROOM);
297 skb_put(skb, size);
298 skb->next = NULL;
299 }
300 return skb;
301}
302
303/**
304 * buf_discard - frees a TIPC message buffer
305 * @skb: message buffer
306 *
307 * Frees a new buffer. If passed NULL, just returns.
308 */
309
310static inline void buf_discard(struct sk_buff *skb)
311{
312 if (likely(skb != NULL))
313 kfree_skb(skb);
314}
315
316#endif
diff --git a/net/tipc/dbg.c b/net/tipc/dbg.c
new file mode 100644
index 000000000000..7ed60a1cfbb8
--- /dev/null
+++ b/net/tipc/dbg.c
@@ -0,0 +1,395 @@
1/*
2 * net/tipc/dbg.c: TIPC print buffer routines for debuggign
3 *
4 * Copyright (c) 1996-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include "core.h"
38#include "config.h"
39#include "dbg.h"
40
41#define MAX_STRING 512
42
43static char print_string[MAX_STRING];
44static spinlock_t print_lock = SPIN_LOCK_UNLOCKED;
45
46static struct print_buf cons_buf = { NULL, 0, NULL, NULL };
47struct print_buf *CONS = &cons_buf;
48
49static struct print_buf log_buf = { NULL, 0, NULL, NULL };
50struct print_buf *LOG = &log_buf;
51
52
53#define FORMAT(PTR,LEN,FMT) \
54{\
55 va_list args;\
56 va_start(args, FMT);\
57 LEN = vsprintf(PTR, FMT, args);\
58 va_end(args);\
59 *(PTR + LEN) = '\0';\
60}
61
62/*
63 * Locking policy when using print buffers.
64 *
65 * 1) Routines of the form printbuf_XXX() rely on the caller to prevent
66 * simultaneous use of the print buffer(s) being manipulated.
67 * 2) tipc_printf() uses 'print_lock' to prevent simultaneous use of
68 * 'print_string' and to protect its print buffer(s).
69 * 3) TEE() uses 'print_lock' to protect its print buffer(s).
70 * 4) Routines of the form log_XXX() uses 'print_lock' to protect LOG.
71 */
72
73/**
74 * printbuf_init - initialize print buffer to empty
75 */
76
77void printbuf_init(struct print_buf *pb, char *raw, u32 sz)
78{
79 if (!pb || !raw || (sz < (MAX_STRING + 1)))
80 return;
81
82 pb->crs = pb->buf = raw;
83 pb->size = sz;
84 pb->next = 0;
85 pb->buf[0] = 0;
86 pb->buf[sz-1] = ~0;
87}
88
89/**
90 * printbuf_reset - reinitialize print buffer to empty state
91 */
92
93void printbuf_reset(struct print_buf *pb)
94{
95 if (pb && pb->buf)
96 printbuf_init(pb, pb->buf, pb->size);
97}
98
99/**
100 * printbuf_empty - test if print buffer is in empty state
101 */
102
103int printbuf_empty(struct print_buf *pb)
104{
105 return (!pb || !pb->buf || (pb->crs == pb->buf));
106}
107
108/**
109 * printbuf_validate - check for print buffer overflow
110 *
111 * Verifies that a print buffer has captured all data written to it.
112 * If data has been lost, linearize buffer and prepend an error message
113 *
114 * Returns length of print buffer data string (including trailing NULL)
115 */
116
117int printbuf_validate(struct print_buf *pb)
118{
119 char *err = " *** PRINT BUFFER WRAPPED AROUND ***\n";
120 char *cp_buf;
121 struct print_buf cb;
122
123 if (!pb || !pb->buf)
124 return 0;
125
126 if (pb->buf[pb->size - 1] == '\0') {
127 cp_buf = kmalloc(pb->size, GFP_ATOMIC);
128 if (cp_buf != NULL){
129 printbuf_init(&cb, cp_buf, pb->size);
130 printbuf_move(&cb, pb);
131 printbuf_move(pb, &cb);
132 kfree(cp_buf);
133 memcpy(pb->buf, err, strlen(err));
134 } else {
135 printbuf_reset(pb);
136 tipc_printf(pb, err);
137 }
138 }
139 return (pb->crs - pb->buf + 1);
140}
141
142/**
143 * printbuf_move - move print buffer contents to another print buffer
144 *
145 * Current contents of destination print buffer (if any) are discarded.
146 * Source print buffer becomes empty if a successful move occurs.
147 */
148
149void printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from)
150{
151 int len;
152
153 /* Handle the cases where contents can't be moved */
154
155 if (!pb_to || !pb_to->buf)
156 return;
157
158 if (!pb_from || !pb_from->buf) {
159 printbuf_reset(pb_to);
160 return;
161 }
162
163 if (pb_to->size < pb_from->size) {
164 printbuf_reset(pb_to);
165 tipc_printf(pb_to, "*** PRINT BUFFER OVERFLOW ***");
166 return;
167 }
168
169 /* Copy data from char after cursor to end (if used) */
170 len = pb_from->buf + pb_from->size - pb_from->crs - 2;
171 if ((pb_from->buf[pb_from->size-1] == 0) && (len > 0)) {
172 strcpy(pb_to->buf, pb_from->crs + 1);
173 pb_to->crs = pb_to->buf + len;
174 } else
175 pb_to->crs = pb_to->buf;
176
177 /* Copy data from start to cursor (always) */
178 len = pb_from->crs - pb_from->buf;
179 strcpy(pb_to->crs, pb_from->buf);
180 pb_to->crs += len;
181
182 printbuf_reset(pb_from);
183}
184
185/**
186 * tipc_printf - append formatted output to print buffer chain
187 */
188
189void tipc_printf(struct print_buf *pb, const char *fmt, ...)
190{
191 int chars_to_add;
192 int chars_left;
193 char save_char;
194 struct print_buf *pb_next;
195
196 spin_lock_bh(&print_lock);
197 FORMAT(print_string, chars_to_add, fmt);
198 if (chars_to_add >= MAX_STRING)
199 strcpy(print_string, "*** STRING TOO LONG ***");
200
201 while (pb) {
202 if (pb == CONS)
203 printk(print_string);
204 else if (pb->buf) {
205 chars_left = pb->buf + pb->size - pb->crs - 1;
206 if (chars_to_add <= chars_left) {
207 strcpy(pb->crs, print_string);
208 pb->crs += chars_to_add;
209 } else {
210 strcpy(pb->buf, print_string + chars_left);
211 save_char = print_string[chars_left];
212 print_string[chars_left] = 0;
213 strcpy(pb->crs, print_string);
214 print_string[chars_left] = save_char;
215 pb->crs = pb->buf + chars_to_add - chars_left;
216 }
217 }
218 pb_next = pb->next;
219 pb->next = 0;
220 pb = pb_next;
221 }
222 spin_unlock_bh(&print_lock);
223}
224
225/**
226 * TEE - perform next output operation on both print buffers
227 */
228
229struct print_buf *TEE(struct print_buf *b0, struct print_buf *b1)
230{
231 struct print_buf *pb = b0;
232
233 if (!b0 || (b0 == b1))
234 return b1;
235 if (!b1)
236 return b0;
237
238 spin_lock_bh(&print_lock);
239 while (pb->next) {
240 if ((pb->next == b1) || (pb->next == b0))
241 pb->next = pb->next->next;
242 else
243 pb = pb->next;
244 }
245 pb->next = b1;
246 spin_unlock_bh(&print_lock);
247 return b0;
248}
249
250/**
251 * print_to_console - write string of bytes to console in multiple chunks
252 */
253
254static void print_to_console(char *crs, int len)
255{
256 int rest = len;
257
258 while (rest > 0) {
259 int sz = rest < MAX_STRING ? rest : MAX_STRING;
260 char c = crs[sz];
261
262 crs[sz] = 0;
263 printk((const char *)crs);
264 crs[sz] = c;
265 rest -= sz;
266 crs += sz;
267 }
268}
269
270/**
271 * printbuf_dump - write print buffer contents to console
272 */
273
274static void printbuf_dump(struct print_buf *pb)
275{
276 int len;
277
278 /* Dump print buffer from char after cursor to end (if used) */
279 len = pb->buf + pb->size - pb->crs - 2;
280 if ((pb->buf[pb->size - 1] == 0) && (len > 0))
281 print_to_console(pb->crs + 1, len);
282
283 /* Dump print buffer from start to cursor (always) */
284 len = pb->crs - pb->buf;
285 print_to_console(pb->buf, len);
286}
287
288/**
289 * tipc_dump - dump non-console print buffer(s) to console
290 */
291
292void tipc_dump(struct print_buf *pb, const char *fmt, ...)
293{
294 int len;
295
296 spin_lock_bh(&print_lock);
297 FORMAT(CONS->buf, len, fmt);
298 printk(CONS->buf);
299
300 for (; pb; pb = pb->next) {
301 if (pb == CONS)
302 continue;
303 printk("\n---- Start of dump,%s log ----\n\n",
304 (pb == LOG) ? "global" : "local");
305 printbuf_dump(pb);
306 printbuf_reset(pb);
307 printk("\n-------- End of dump --------\n");
308 }
309 spin_unlock_bh(&print_lock);
310}
311
312/**
313 * log_stop - free up TIPC log print buffer
314 */
315
316void log_stop(void)
317{
318 spin_lock_bh(&print_lock);
319 if (LOG->buf) {
320 kfree(LOG->buf);
321 LOG->buf = NULL;
322 }
323 spin_unlock_bh(&print_lock);
324}
325
326/**
327 * log_reinit - set TIPC log print buffer to specified size
328 */
329
330void log_reinit(int log_size)
331{
332 log_stop();
333
334 if (log_size) {
335 if (log_size <= MAX_STRING)
336 log_size = MAX_STRING + 1;
337 spin_lock_bh(&print_lock);
338 printbuf_init(LOG, kmalloc(log_size, GFP_ATOMIC), log_size);
339 spin_unlock_bh(&print_lock);
340 }
341}
342
343/**
344 * log_resize - reconfigure size of TIPC log buffer
345 */
346
347struct sk_buff *log_resize(const void *req_tlv_area, int req_tlv_space)
348{
349 u32 value;
350
351 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
352 return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
353
354 value = *(u32 *)TLV_DATA(req_tlv_area);
355 value = ntohl(value);
356 if (value != delimit(value, 0, 32768))
357 return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
358 " (log size must be 0-32768)");
359 log_reinit(value);
360 return cfg_reply_none();
361}
362
363/**
364 * log_dump - capture TIPC log buffer contents in configuration message
365 */
366
367struct sk_buff *log_dump(void)
368{
369 struct sk_buff *reply;
370
371 spin_lock_bh(&print_lock);
372 if (!LOG->buf)
373 reply = cfg_reply_ultra_string("log not activated\n");
374 else if (printbuf_empty(LOG))
375 reply = cfg_reply_ultra_string("log is empty\n");
376 else {
377 struct tlv_desc *rep_tlv;
378 struct print_buf pb;
379 int str_len;
380
381 str_len = min(LOG->size, 32768u);
382 reply = cfg_reply_alloc(TLV_SPACE(str_len));
383 if (reply) {
384 rep_tlv = (struct tlv_desc *)reply->data;
385 printbuf_init(&pb, TLV_DATA(rep_tlv), str_len);
386 printbuf_move(&pb, LOG);
387 str_len = strlen(TLV_DATA(rep_tlv)) + 1;
388 skb_put(reply, TLV_SPACE(str_len));
389 TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
390 }
391 }
392 spin_unlock_bh(&print_lock);
393 return reply;
394}
395
diff --git a/net/tipc/dbg.h b/net/tipc/dbg.h
new file mode 100644
index 000000000000..c6b2a64c224f
--- /dev/null
+++ b/net/tipc/dbg.h
@@ -0,0 +1,59 @@
1/*
2 * net/tipc/dbg.h: Include file for TIPC print buffer routines
3 *
4 * Copyright (c) 1997-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#ifndef _TIPC_DBG_H
38#define _TIPC_DBG_H
39
40struct print_buf {
41 char *buf;
42 u32 size;
43 char *crs;
44 struct print_buf *next;
45};
46
47void printbuf_init(struct print_buf *pb, char *buf, u32 sz);
48void printbuf_reset(struct print_buf *pb);
49int printbuf_empty(struct print_buf *pb);
50int printbuf_validate(struct print_buf *pb);
51void printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from);
52
53void log_reinit(int log_size);
54void log_stop(void);
55
56struct sk_buff *log_resize(const void *req_tlv_area, int req_tlv_space);
57struct sk_buff *log_dump(void);
58
59#endif
diff --git a/net/tipc/discover.c b/net/tipc/discover.c
new file mode 100644
index 000000000000..b106ef1621cc
--- /dev/null
+++ b/net/tipc/discover.c
@@ -0,0 +1,318 @@
1/*
2 * net/tipc/discover.c
3 *
4 * Copyright (c) 2003-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include "core.h"
38#include "dbg.h"
39#include "link.h"
40#include "zone.h"
41#include "discover.h"
42#include "port.h"
43#include "name_table.h"
44
45#define TIPC_LINK_REQ_INIT 125 /* min delay during bearer start up */
46#define TIPC_LINK_REQ_FAST 2000 /* normal delay if bearer has no links */
47#define TIPC_LINK_REQ_SLOW 600000 /* normal delay if bearer has links */
48
49#if 0
50#define GET_NODE_INFO 300
51#define GET_NODE_INFO_RESULT 301
52#define FORWARD_LINK_PROBE 302
53#define LINK_REQUEST_REJECTED 303
54#define LINK_REQUEST_ACCEPTED 304
55#define DROP_LINK_REQUEST 305
56#define CHECK_LINK_COUNT 306
57#endif
58
59/*
60 * TODO: Most of the inter-cluster setup stuff should be
61 * rewritten, and be made conformant with specification.
62 */
63
64
65/**
66 * struct link_req - information about an ongoing link setup request
67 * @bearer: bearer issuing requests
68 * @dest: destination address for request messages
69 * @buf: request message to be (repeatedly) sent
70 * @timer: timer governing period between requests
71 * @timer_intv: current interval between requests (in ms)
72 */
73struct link_req {
74 struct bearer *bearer;
75 struct tipc_media_addr dest;
76 struct sk_buff *buf;
77 struct timer_list timer;
78 unsigned int timer_intv;
79};
80
81
82#if 0
83int disc_create_link(const struct tipc_link_create *argv)
84{
85 /*
86 * Code for inter cluster link setup here
87 */
88 return TIPC_OK;
89}
90#endif
91
92/*
93 * disc_lost_link(): A link has lost contact
94 */
95
96void disc_link_event(u32 addr, char *name, int up)
97{
98 if (in_own_cluster(addr))
99 return;
100 /*
101 * Code for inter cluster link setup here
102 */
103}
104
105/**
106 * disc_init_msg - initialize a link setup message
107 * @type: message type (request or response)
108 * @req_links: number of links associated with message
109 * @dest_domain: network domain of node(s) which should respond to message
110 * @b_ptr: ptr to bearer issuing message
111 */
112
113struct sk_buff *disc_init_msg(u32 type,
114 u32 req_links,
115 u32 dest_domain,
116 struct bearer *b_ptr)
117{
118 struct sk_buff *buf = buf_acquire(DSC_H_SIZE);
119 struct tipc_msg *msg;
120
121 if (buf) {
122 msg = buf_msg(buf);
123 msg_init(msg, LINK_CONFIG, type, TIPC_OK, DSC_H_SIZE,
124 dest_domain);
125 msg_set_non_seq(msg);
126 msg_set_req_links(msg, req_links);
127 msg_set_dest_domain(msg, dest_domain);
128 msg_set_bc_netid(msg, tipc_net_id);
129 msg_set_media_addr(msg, &b_ptr->publ.addr);
130 }
131 return buf;
132}
133
134/**
135 * disc_recv_msg - handle incoming link setup message (request or response)
136 * @buf: buffer containing message
137 */
138
139void disc_recv_msg(struct sk_buff *buf)
140{
141 struct bearer *b_ptr = (struct bearer *)TIPC_SKB_CB(buf)->handle;
142 struct link *link;
143 struct tipc_media_addr media_addr;
144 struct tipc_msg *msg = buf_msg(buf);
145 u32 dest = msg_dest_domain(msg);
146 u32 orig = msg_prevnode(msg);
147 u32 net_id = msg_bc_netid(msg);
148 u32 type = msg_type(msg);
149
150 msg_get_media_addr(msg,&media_addr);
151 msg_dbg(msg, "RECV:");
152 buf_discard(buf);
153
154 if (net_id != tipc_net_id)
155 return;
156 if (!addr_domain_valid(dest))
157 return;
158 if (!addr_node_valid(orig))
159 return;
160 if (orig == tipc_own_addr)
161 return;
162 if (!in_scope(dest, tipc_own_addr))
163 return;
164 if (is_slave(tipc_own_addr) && is_slave(orig))
165 return;
166 if (is_slave(orig) && !in_own_cluster(orig))
167 return;
168 if (in_own_cluster(orig)) {
169 /* Always accept link here */
170 struct sk_buff *rbuf;
171 struct tipc_media_addr *addr;
172 struct node *n_ptr = node_find(orig);
173 int link_up;
174 dbg(" in own cluster\n");
175 if (n_ptr == NULL) {
176 n_ptr = node_create(orig);
177 }
178 if (n_ptr == NULL) {
179 warn("Memory squeeze; Failed to create node\n");
180 return;
181 }
182 spin_lock_bh(&n_ptr->lock);
183 link = n_ptr->links[b_ptr->identity];
184 if (!link) {
185 dbg("creating link\n");
186 link = link_create(b_ptr, orig, &media_addr);
187 if (!link) {
188 spin_unlock_bh(&n_ptr->lock);
189 return;
190 }
191 }
192 addr = &link->media_addr;
193 if (memcmp(addr, &media_addr, sizeof(*addr))) {
194 char addr_string[16];
195
196 warn("New bearer address for %s\n",
197 addr_string_fill(addr_string, orig));
198 memcpy(addr, &media_addr, sizeof(*addr));
199 link_reset(link);
200 }
201 link_up = link_is_up(link);
202 spin_unlock_bh(&n_ptr->lock);
203 if ((type == DSC_RESP_MSG) || link_up)
204 return;
205 rbuf = disc_init_msg(DSC_RESP_MSG, 1, orig, b_ptr);
206 if (rbuf != NULL) {
207 msg_dbg(buf_msg(rbuf),"SEND:");
208 b_ptr->media->send_msg(rbuf, &b_ptr->publ, &media_addr);
209 buf_discard(rbuf);
210 }
211 }
212}
213
214/**
215 * disc_stop_link_req - stop sending periodic link setup requests
216 * @req: ptr to link request structure
217 */
218
219void disc_stop_link_req(struct link_req *req)
220{
221 if (!req)
222 return;
223
224 k_cancel_timer(&req->timer);
225 k_term_timer(&req->timer);
226 buf_discard(req->buf);
227 kfree(req);
228}
229
230/**
231 * disc_update_link_req - update frequency of periodic link setup requests
232 * @req: ptr to link request structure
233 */
234
235void disc_update_link_req(struct link_req *req)
236{
237 if (!req)
238 return;
239
240 if (req->timer_intv == TIPC_LINK_REQ_SLOW) {
241 if (!req->bearer->nodes.count) {
242 req->timer_intv = TIPC_LINK_REQ_FAST;
243 k_start_timer(&req->timer, req->timer_intv);
244 }
245 } else if (req->timer_intv == TIPC_LINK_REQ_FAST) {
246 if (req->bearer->nodes.count) {
247 req->timer_intv = TIPC_LINK_REQ_SLOW;
248 k_start_timer(&req->timer, req->timer_intv);
249 }
250 } else {
251 /* leave timer "as is" if haven't yet reached a "normal" rate */
252 }
253}
254
255/**
256 * disc_timeout - send a periodic link setup request
257 * @req: ptr to link request structure
258 *
259 * Called whenever a link setup request timer associated with a bearer expires.
260 */
261
262static void disc_timeout(struct link_req *req)
263{
264 spin_lock_bh(&req->bearer->publ.lock);
265
266 req->bearer->media->send_msg(req->buf, &req->bearer->publ, &req->dest);
267
268 if ((req->timer_intv == TIPC_LINK_REQ_SLOW) ||
269 (req->timer_intv == TIPC_LINK_REQ_FAST)) {
270 /* leave timer interval "as is" if already at a "normal" rate */
271 } else {
272 req->timer_intv *= 2;
273 if (req->timer_intv > TIPC_LINK_REQ_SLOW)
274 req->timer_intv = TIPC_LINK_REQ_SLOW;
275 if ((req->timer_intv == TIPC_LINK_REQ_FAST) &&
276 (req->bearer->nodes.count))
277 req->timer_intv = TIPC_LINK_REQ_SLOW;
278 }
279 k_start_timer(&req->timer, req->timer_intv);
280
281 spin_unlock_bh(&req->bearer->publ.lock);
282}
283
284/**
285 * disc_init_link_req - start sending periodic link setup requests
286 * @b_ptr: ptr to bearer issuing requests
287 * @dest: destination address for request messages
288 * @dest_domain: network domain of node(s) which should respond to message
289 * @req_links: max number of desired links
290 *
291 * Returns pointer to link request structure, or NULL if unable to create.
292 */
293
294struct link_req *disc_init_link_req(struct bearer *b_ptr,
295 const struct tipc_media_addr *dest,
296 u32 dest_domain,
297 u32 req_links)
298{
299 struct link_req *req;
300
301 req = (struct link_req *)kmalloc(sizeof(*req), GFP_ATOMIC);
302 if (!req)
303 return NULL;
304
305 req->buf = disc_init_msg(DSC_REQ_MSG, req_links, dest_domain, b_ptr);
306 if (!req->buf) {
307 kfree(req);
308 return NULL;
309 }
310
311 memcpy(&req->dest, dest, sizeof(*dest));
312 req->bearer = b_ptr;
313 req->timer_intv = TIPC_LINK_REQ_INIT;
314 k_init_timer(&req->timer, (Handler)disc_timeout, (unsigned long)req);
315 k_start_timer(&req->timer, req->timer_intv);
316 return req;
317}
318
diff --git a/net/tipc/discover.h b/net/tipc/discover.h
new file mode 100644
index 000000000000..2a6114d91626
--- /dev/null
+++ b/net/tipc/discover.h
@@ -0,0 +1,58 @@
1/*
2 * net/tipc/discover.h
3 *
4 * Copyright (c) 2003-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#ifndef _TIPC_DISCOVER_H
38#define _TIPC_DISCOVER_H
39
40#include <linux/tipc.h>
41
42struct link_req;
43
44struct link_req *disc_init_link_req(struct bearer *b_ptr,
45 const struct tipc_media_addr *dest,
46 u32 dest_domain,
47 u32 req_links);
48void disc_update_link_req(struct link_req *req);
49void disc_stop_link_req(struct link_req *req);
50
51void disc_recv_msg(struct sk_buff *buf);
52
53void disc_link_event(u32 addr, char *name, int up);
54#if 0
55int disc_create_link(const struct tipc_link_create *argv);
56#endif
57
58#endif
diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c
new file mode 100644
index 000000000000..34d0462db3aa
--- /dev/null
+++ b/net/tipc/eth_media.c
@@ -0,0 +1,299 @@
1/*
2 * net/tipc/eth_media.c: Ethernet bearer support for TIPC
3 *
4 * Copyright (c) 2001-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include <net/tipc/tipc.h>
38#include <net/tipc/tipc_bearer.h>
39#include <net/tipc/tipc_msg.h>
40#include <linux/netdevice.h>
41#include <linux/version.h>
42
43#define MAX_ETH_BEARERS 2
44#define TIPC_PROTOCOL 0x88ca
45#define ETH_LINK_PRIORITY 10
46#define ETH_LINK_TOLERANCE TIPC_DEF_LINK_TOL
47
48
49/**
50 * struct eth_bearer - Ethernet bearer data structure
51 * @bearer: ptr to associated "generic" bearer structure
52 * @dev: ptr to associated Ethernet network device
53 * @tipc_packet_type: used in binding TIPC to Ethernet driver
54 */
55
56struct eth_bearer {
57 struct tipc_bearer *bearer;
58 struct net_device *dev;
59 struct packet_type tipc_packet_type;
60};
61
62static struct eth_bearer eth_bearers[MAX_ETH_BEARERS];
63static int eth_started = 0;
64static struct notifier_block notifier;
65
66/**
67 * send_msg - send a TIPC message out over an Ethernet interface
68 */
69
70static int send_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr,
71 struct tipc_media_addr *dest)
72{
73 struct sk_buff *clone;
74 struct net_device *dev;
75
76 clone = skb_clone(buf, GFP_ATOMIC);
77 if (clone) {
78 clone->nh.raw = clone->data;
79 dev = ((struct eth_bearer *)(tb_ptr->usr_handle))->dev;
80 clone->dev = dev;
81 dev->hard_header(clone, dev, TIPC_PROTOCOL,
82 &dest->dev_addr.eth_addr,
83 dev->dev_addr, clone->len);
84 dev_queue_xmit(clone);
85 }
86 return TIPC_OK;
87}
88
89/**
90 * recv_msg - handle incoming TIPC message from an Ethernet interface
91 *
92 * Routine truncates any Ethernet padding/CRC appended to the message,
93 * and ensures message size matches actual length
94 */
95
96static int recv_msg(struct sk_buff *buf, struct net_device *dev,
97 struct packet_type *pt, struct net_device *orig_dev)
98{
99 struct eth_bearer *eb_ptr = (struct eth_bearer *)pt->af_packet_priv;
100 u32 size;
101
102 if (likely(eb_ptr->bearer)) {
103 size = msg_size((struct tipc_msg *)buf->data);
104 skb_trim(buf, size);
105 if (likely(buf->len == size)) {
106 buf->next = NULL;
107 tipc_recv_msg(buf, eb_ptr->bearer);
108 } else {
109 kfree_skb(buf);
110 }
111 } else {
112 kfree_skb(buf);
113 }
114 return TIPC_OK;
115}
116
117/**
118 * enable_bearer - attach TIPC bearer to an Ethernet interface
119 */
120
121static int enable_bearer(struct tipc_bearer *tb_ptr)
122{
123 struct net_device *dev = dev_base;
124 struct eth_bearer *eb_ptr = &eth_bearers[0];
125 struct eth_bearer *stop = &eth_bearers[MAX_ETH_BEARERS];
126 char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1;
127
128 /* Find device with specified name */
129
130 while (dev && dev->name &&
131 (memcmp(dev->name, driver_name, strlen(dev->name)))) {
132 dev = dev->next;
133 }
134 if (!dev)
135 return -ENODEV;
136
137 /* Find Ethernet bearer for device (or create one) */
138
139 for (;(eb_ptr != stop) && eb_ptr->dev && (eb_ptr->dev != dev); eb_ptr++);
140 if (eb_ptr == stop)
141 return -EDQUOT;
142 if (!eb_ptr->dev) {
143 eb_ptr->dev = dev;
144 eb_ptr->tipc_packet_type.type = __constant_htons(TIPC_PROTOCOL);
145 eb_ptr->tipc_packet_type.dev = dev;
146 eb_ptr->tipc_packet_type.func = recv_msg;
147 eb_ptr->tipc_packet_type.af_packet_priv = eb_ptr;
148 INIT_LIST_HEAD(&(eb_ptr->tipc_packet_type.list));
149 dev_hold(dev);
150 dev_add_pack(&eb_ptr->tipc_packet_type);
151 }
152
153 /* Associate TIPC bearer with Ethernet bearer */
154
155 eb_ptr->bearer = tb_ptr;
156 tb_ptr->usr_handle = (void *)eb_ptr;
157 tb_ptr->mtu = dev->mtu;
158 tb_ptr->blocked = 0;
159 tb_ptr->addr.type = htonl(TIPC_MEDIA_TYPE_ETH);
160 memcpy(&tb_ptr->addr.dev_addr, &dev->dev_addr, ETH_ALEN);
161 return 0;
162}
163
164/**
165 * disable_bearer - detach TIPC bearer from an Ethernet interface
166 *
167 * We really should do dev_remove_pack() here, but this function can not be
168 * called at tasklet level. => Use eth_bearer->bearer as a flag to throw away
169 * incoming buffers, & postpone dev_remove_pack() to eth_media_stop() on exit.
170 */
171
172static void disable_bearer(struct tipc_bearer *tb_ptr)
173{
174 ((struct eth_bearer *)tb_ptr->usr_handle)->bearer = 0;
175}
176
177/**
178 * recv_notification - handle device updates from OS
179 *
180 * Change the state of the Ethernet bearer (if any) associated with the
181 * specified device.
182 */
183
184static int recv_notification(struct notifier_block *nb, unsigned long evt,
185 void *dv)
186{
187 struct net_device *dev = (struct net_device *)dv;
188 struct eth_bearer *eb_ptr = &eth_bearers[0];
189 struct eth_bearer *stop = &eth_bearers[MAX_ETH_BEARERS];
190
191 while ((eb_ptr->dev != dev)) {
192 if (++eb_ptr == stop)
193 return NOTIFY_DONE; /* couldn't find device */
194 }
195 if (!eb_ptr->bearer)
196 return NOTIFY_DONE; /* bearer had been disabled */
197
198 eb_ptr->bearer->mtu = dev->mtu;
199
200 switch (evt) {
201 case NETDEV_CHANGE:
202 if (netif_carrier_ok(dev))
203 tipc_continue(eb_ptr->bearer);
204 else
205 tipc_block_bearer(eb_ptr->bearer->name);
206 break;
207 case NETDEV_UP:
208 tipc_continue(eb_ptr->bearer);
209 break;
210 case NETDEV_DOWN:
211 tipc_block_bearer(eb_ptr->bearer->name);
212 break;
213 case NETDEV_CHANGEMTU:
214 case NETDEV_CHANGEADDR:
215 tipc_block_bearer(eb_ptr->bearer->name);
216 tipc_continue(eb_ptr->bearer);
217 break;
218 case NETDEV_UNREGISTER:
219 case NETDEV_CHANGENAME:
220 tipc_disable_bearer(eb_ptr->bearer->name);
221 break;
222 }
223 return NOTIFY_OK;
224}
225
226/**
227 * eth_addr2str - convert Ethernet address to string
228 */
229
230static char *eth_addr2str(struct tipc_media_addr *a, char *str_buf, int str_size)
231{
232 unchar *addr = (unchar *)&a->dev_addr;
233
234 if (str_size < 18)
235 *str_buf = '\0';
236 else
237 sprintf(str_buf, "%02x:%02x:%02x:%02x:%02x:%02x",
238 addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
239 return str_buf;
240}
241
242/**
243 * eth_media_start - activate Ethernet bearer support
244 *
245 * Register Ethernet media type with TIPC bearer code. Also register
246 * with OS for notifications about device state changes.
247 */
248
249int eth_media_start(void)
250{
251 struct tipc_media_addr bcast_addr;
252 int res;
253
254 if (eth_started)
255 return -EINVAL;
256
257 memset(&bcast_addr, 0xff, sizeof(bcast_addr));
258 memset(eth_bearers, 0, sizeof(eth_bearers));
259
260 res = tipc_register_media(TIPC_MEDIA_TYPE_ETH, "eth",
261 enable_bearer, disable_bearer, send_msg,
262 eth_addr2str, &bcast_addr, ETH_LINK_PRIORITY,
263 ETH_LINK_TOLERANCE, TIPC_DEF_LINK_WIN);
264 if (res)
265 return res;
266
267 notifier.notifier_call = &recv_notification;
268 notifier.priority = 0;
269 res = register_netdevice_notifier(&notifier);
270 if (!res)
271 eth_started = 1;
272 return res;
273}
274
275/**
276 * eth_media_stop - deactivate Ethernet bearer support
277 */
278
279void eth_media_stop(void)
280{
281 int i;
282
283 if (!eth_started)
284 return;
285
286 unregister_netdevice_notifier(&notifier);
287 for (i = 0; i < MAX_ETH_BEARERS ; i++) {
288 if (eth_bearers[i].bearer) {
289 eth_bearers[i].bearer->blocked = 1;
290 eth_bearers[i].bearer = 0;
291 }
292 if (eth_bearers[i].dev) {
293 dev_remove_pack(&eth_bearers[i].tipc_packet_type);
294 dev_put(eth_bearers[i].dev);
295 }
296 }
297 memset(&eth_bearers, 0, sizeof(eth_bearers));
298 eth_started = 0;
299}
diff --git a/net/tipc/handler.c b/net/tipc/handler.c
new file mode 100644
index 000000000000..f320010f8a65
--- /dev/null
+++ b/net/tipc/handler.c
@@ -0,0 +1,132 @@
1/*
2 * net/tipc/handler.c: TIPC signal handling
3 *
4 * Copyright (c) 2000-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include "core.h"
38
39struct queue_item {
40 struct list_head next_signal;
41 void (*handler) (unsigned long);
42 unsigned long data;
43};
44
45static kmem_cache_t *tipc_queue_item_cache;
46static struct list_head signal_queue_head;
47static spinlock_t qitem_lock = SPIN_LOCK_UNLOCKED;
48static int handler_enabled = 0;
49
50static void process_signal_queue(unsigned long dummy);
51
52static DECLARE_TASKLET_DISABLED(tipc_tasklet, process_signal_queue, 0);
53
54
55unsigned int k_signal(Handler routine, unsigned long argument)
56{
57 struct queue_item *item;
58
59 if (!handler_enabled) {
60 err("Signal request ignored by handler\n");
61 return -ENOPROTOOPT;
62 }
63
64 spin_lock_bh(&qitem_lock);
65 item = kmem_cache_alloc(tipc_queue_item_cache, GFP_ATOMIC);
66 if (!item) {
67 err("Signal queue out of memory\n");
68 spin_unlock_bh(&qitem_lock);
69 return -ENOMEM;
70 }
71 item->handler = routine;
72 item->data = argument;
73 list_add_tail(&item->next_signal, &signal_queue_head);
74 spin_unlock_bh(&qitem_lock);
75 tasklet_schedule(&tipc_tasklet);
76 return 0;
77}
78
79static void process_signal_queue(unsigned long dummy)
80{
81 struct queue_item *__volatile__ item;
82 struct list_head *l, *n;
83
84 spin_lock_bh(&qitem_lock);
85 list_for_each_safe(l, n, &signal_queue_head) {
86 item = list_entry(l, struct queue_item, next_signal);
87 list_del(&item->next_signal);
88 spin_unlock_bh(&qitem_lock);
89 item->handler(item->data);
90 spin_lock_bh(&qitem_lock);
91 kmem_cache_free(tipc_queue_item_cache, item);
92 }
93 spin_unlock_bh(&qitem_lock);
94}
95
96int handler_start(void)
97{
98 tipc_queue_item_cache =
99 kmem_cache_create("tipc_queue_items", sizeof(struct queue_item),
100 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
101 if (!tipc_queue_item_cache)
102 return -ENOMEM;
103
104 INIT_LIST_HEAD(&signal_queue_head);
105 tasklet_enable(&tipc_tasklet);
106 handler_enabled = 1;
107 return 0;
108}
109
110void handler_stop(void)
111{
112 struct list_head *l, *n;
113 struct queue_item *item;
114
115 if (!handler_enabled)
116 return;
117
118 handler_enabled = 0;
119 tasklet_disable(&tipc_tasklet);
120 tasklet_kill(&tipc_tasklet);
121
122 spin_lock_bh(&qitem_lock);
123 list_for_each_safe(l, n, &signal_queue_head) {
124 item = list_entry(l, struct queue_item, next_signal);
125 list_del(&item->next_signal);
126 kmem_cache_free(tipc_queue_item_cache, item);
127 }
128 spin_unlock_bh(&qitem_lock);
129
130 kmem_cache_destroy(tipc_queue_item_cache);
131}
132
diff --git a/net/tipc/link.c b/net/tipc/link.c
new file mode 100644
index 000000000000..7265f4be4766
--- /dev/null
+++ b/net/tipc/link.c
@@ -0,0 +1,3167 @@
1/*
2 * net/tipc/link.c: TIPC link code
3 *
4 * Copyright (c) 1996-2006, Ericsson AB
5 * Copyright (c) 2004-2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include "core.h"
38#include "dbg.h"
39#include "link.h"
40#include "net.h"
41#include "node.h"
42#include "port.h"
43#include "addr.h"
44#include "node_subscr.h"
45#include "name_distr.h"
46#include "bearer.h"
47#include "name_table.h"
48#include "discover.h"
49#include "config.h"
50#include "bcast.h"
51
52
53/*
54 * Limit for deferred reception queue:
55 */
56
57#define DEF_QUEUE_LIMIT 256u
58
59/*
60 * Link state events:
61 */
62
63#define STARTING_EVT 856384768 /* link processing trigger */
64#define TRAFFIC_MSG_EVT 560815u /* rx'd ??? */
65#define TIMEOUT_EVT 560817u /* link timer expired */
66
67/*
68 * The following two 'message types' is really just implementation
69 * data conveniently stored in the message header.
70 * They must not be considered part of the protocol
71 */
72#define OPEN_MSG 0
73#define CLOSED_MSG 1
74
75/*
76 * State value stored in 'exp_msg_count'
77 */
78
79#define START_CHANGEOVER 100000u
80
81/**
82 * struct link_name - deconstructed link name
83 * @addr_local: network address of node at this end
84 * @if_local: name of interface at this end
85 * @addr_peer: network address of node at far end
86 * @if_peer: name of interface at far end
87 */
88
89struct link_name {
90 u32 addr_local;
91 char if_local[TIPC_MAX_IF_NAME];
92 u32 addr_peer;
93 char if_peer[TIPC_MAX_IF_NAME];
94};
95
96#if 0
97
98/* LINK EVENT CODE IS NOT SUPPORTED AT PRESENT */
99
100/**
101 * struct link_event - link up/down event notification
102 */
103
104struct link_event {
105 u32 addr;
106 int up;
107 void (*fcn)(u32, char *, int);
108 char name[TIPC_MAX_LINK_NAME];
109};
110
111#endif
112
113static void link_handle_out_of_seq_msg(struct link *l_ptr,
114 struct sk_buff *buf);
115static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf);
116static int link_recv_changeover_msg(struct link **l_ptr, struct sk_buff **buf);
117static void link_set_supervision_props(struct link *l_ptr, u32 tolerance);
118static int link_send_sections_long(struct port *sender,
119 struct iovec const *msg_sect,
120 u32 num_sect, u32 destnode);
121static void link_check_defragm_bufs(struct link *l_ptr);
122static void link_state_event(struct link *l_ptr, u32 event);
123static void link_reset_statistics(struct link *l_ptr);
124static void link_print(struct link *l_ptr, struct print_buf *buf,
125 const char *str);
126
127/*
128 * Debugging code used by link routines only
129 *
130 * When debugging link problems on a system that has multiple links,
131 * the standard TIPC debugging routines may not be useful since they
132 * allow the output from multiple links to be intermixed. For this reason
133 * routines of the form "dbg_link_XXX()" have been created that will capture
134 * debug info into a link's personal print buffer, which can then be dumped
135 * into the TIPC system log (LOG) upon request.
136 *
137 * To enable per-link debugging, use LINK_LOG_BUF_SIZE to specify the size
138 * of the print buffer used by each link. If LINK_LOG_BUF_SIZE is set to 0,
139 * the dbg_link_XXX() routines simply send their output to the standard
140 * debug print buffer (DBG_OUTPUT), if it has been defined; this can be useful
141 * when there is only a single link in the system being debugged.
142 *
143 * Notes:
144 * - When enabled, LINK_LOG_BUF_SIZE should be set to at least 1000 (bytes)
145 * - "l_ptr" must be valid when using dbg_link_XXX() macros
146 */
147
148#define LINK_LOG_BUF_SIZE 0
149
150#define dbg_link(fmt, arg...) do {if (LINK_LOG_BUF_SIZE) tipc_printf(&l_ptr->print_buf, fmt, ## arg); } while(0)
151#define dbg_link_msg(msg, txt) do {if (LINK_LOG_BUF_SIZE) msg_print(&l_ptr->print_buf, msg, txt); } while(0)
152#define dbg_link_state(txt) do {if (LINK_LOG_BUF_SIZE) link_print(l_ptr, &l_ptr->print_buf, txt); } while(0)
153#define dbg_link_dump() do { \
154 if (LINK_LOG_BUF_SIZE) { \
155 tipc_printf(LOG, "\n\nDumping link <%s>:\n", l_ptr->name); \
156 printbuf_move(LOG, &l_ptr->print_buf); \
157 } \
158} while (0)
159
160static inline void dbg_print_link(struct link *l_ptr, const char *str)
161{
162 if (DBG_OUTPUT)
163 link_print(l_ptr, DBG_OUTPUT, str);
164}
165
166static inline void dbg_print_buf_chain(struct sk_buff *root_buf)
167{
168 if (DBG_OUTPUT) {
169 struct sk_buff *buf = root_buf;
170
171 while (buf) {
172 msg_dbg(buf_msg(buf), "In chain: ");
173 buf = buf->next;
174 }
175 }
176}
177
178/*
179 * Simple inlined link routines
180 */
181
182static inline unsigned int align(unsigned int i)
183{
184 return (i + 3) & ~3u;
185}
186
187static inline int link_working_working(struct link *l_ptr)
188{
189 return (l_ptr->state == WORKING_WORKING);
190}
191
192static inline int link_working_unknown(struct link *l_ptr)
193{
194 return (l_ptr->state == WORKING_UNKNOWN);
195}
196
197static inline int link_reset_unknown(struct link *l_ptr)
198{
199 return (l_ptr->state == RESET_UNKNOWN);
200}
201
202static inline int link_reset_reset(struct link *l_ptr)
203{
204 return (l_ptr->state == RESET_RESET);
205}
206
207static inline int link_blocked(struct link *l_ptr)
208{
209 return (l_ptr->exp_msg_count || l_ptr->blocked);
210}
211
212static inline int link_congested(struct link *l_ptr)
213{
214 return (l_ptr->out_queue_size >= l_ptr->queue_limit[0]);
215}
216
217static inline u32 link_max_pkt(struct link *l_ptr)
218{
219 return l_ptr->max_pkt;
220}
221
222static inline void link_init_max_pkt(struct link *l_ptr)
223{
224 u32 max_pkt;
225
226 max_pkt = (l_ptr->b_ptr->publ.mtu & ~3);
227 if (max_pkt > MAX_MSG_SIZE)
228 max_pkt = MAX_MSG_SIZE;
229
230 l_ptr->max_pkt_target = max_pkt;
231 if (l_ptr->max_pkt_target < MAX_PKT_DEFAULT)
232 l_ptr->max_pkt = l_ptr->max_pkt_target;
233 else
234 l_ptr->max_pkt = MAX_PKT_DEFAULT;
235
236 l_ptr->max_pkt_probes = 0;
237}
238
239static inline u32 link_next_sent(struct link *l_ptr)
240{
241 if (l_ptr->next_out)
242 return msg_seqno(buf_msg(l_ptr->next_out));
243 return mod(l_ptr->next_out_no);
244}
245
246static inline u32 link_last_sent(struct link *l_ptr)
247{
248 return mod(link_next_sent(l_ptr) - 1);
249}
250
251/*
252 * Simple non-inlined link routines (i.e. referenced outside this file)
253 */
254
255int link_is_up(struct link *l_ptr)
256{
257 if (!l_ptr)
258 return 0;
259 return (link_working_working(l_ptr) || link_working_unknown(l_ptr));
260}
261
262int link_is_active(struct link *l_ptr)
263{
264 return ((l_ptr->owner->active_links[0] == l_ptr) ||
265 (l_ptr->owner->active_links[1] == l_ptr));
266}
267
268/**
269 * link_name_validate - validate & (optionally) deconstruct link name
270 * @name - ptr to link name string
271 * @name_parts - ptr to area for link name components (or NULL if not needed)
272 *
273 * Returns 1 if link name is valid, otherwise 0.
274 */
275
276static int link_name_validate(const char *name, struct link_name *name_parts)
277{
278 char name_copy[TIPC_MAX_LINK_NAME];
279 char *addr_local;
280 char *if_local;
281 char *addr_peer;
282 char *if_peer;
283 char dummy;
284 u32 z_local, c_local, n_local;
285 u32 z_peer, c_peer, n_peer;
286 u32 if_local_len;
287 u32 if_peer_len;
288
289 /* copy link name & ensure length is OK */
290
291 name_copy[TIPC_MAX_LINK_NAME - 1] = 0;
292 /* need above in case non-Posix strncpy() doesn't pad with nulls */
293 strncpy(name_copy, name, TIPC_MAX_LINK_NAME);
294 if (name_copy[TIPC_MAX_LINK_NAME - 1] != 0)
295 return 0;
296
297 /* ensure all component parts of link name are present */
298
299 addr_local = name_copy;
300 if ((if_local = strchr(addr_local, ':')) == NULL)
301 return 0;
302 *(if_local++) = 0;
303 if ((addr_peer = strchr(if_local, '-')) == NULL)
304 return 0;
305 *(addr_peer++) = 0;
306 if_local_len = addr_peer - if_local;
307 if ((if_peer = strchr(addr_peer, ':')) == NULL)
308 return 0;
309 *(if_peer++) = 0;
310 if_peer_len = strlen(if_peer) + 1;
311
312 /* validate component parts of link name */
313
314 if ((sscanf(addr_local, "%u.%u.%u%c",
315 &z_local, &c_local, &n_local, &dummy) != 3) ||
316 (sscanf(addr_peer, "%u.%u.%u%c",
317 &z_peer, &c_peer, &n_peer, &dummy) != 3) ||
318 (z_local > 255) || (c_local > 4095) || (n_local > 4095) ||
319 (z_peer > 255) || (c_peer > 4095) || (n_peer > 4095) ||
320 (if_local_len <= 1) || (if_local_len > TIPC_MAX_IF_NAME) ||
321 (if_peer_len <= 1) || (if_peer_len > TIPC_MAX_IF_NAME) ||
322 (strspn(if_local, tipc_alphabet) != (if_local_len - 1)) ||
323 (strspn(if_peer, tipc_alphabet) != (if_peer_len - 1)))
324 return 0;
325
326 /* return link name components, if necessary */
327
328 if (name_parts) {
329 name_parts->addr_local = tipc_addr(z_local, c_local, n_local);
330 strcpy(name_parts->if_local, if_local);
331 name_parts->addr_peer = tipc_addr(z_peer, c_peer, n_peer);
332 strcpy(name_parts->if_peer, if_peer);
333 }
334 return 1;
335}
336
337/**
338 * link_timeout - handle expiration of link timer
339 * @l_ptr: pointer to link
340 *
341 * This routine must not grab "net_lock" to avoid a potential deadlock conflict
342 * with link_delete(). (There is no risk that the node will be deleted by
343 * another thread because link_delete() always cancels the link timer before
344 * node_delete() is called.)
345 */
346
347static void link_timeout(struct link *l_ptr)
348{
349 node_lock(l_ptr->owner);
350
351 /* update counters used in statistical profiling of send traffic */
352
353 l_ptr->stats.accu_queue_sz += l_ptr->out_queue_size;
354 l_ptr->stats.queue_sz_counts++;
355
356 if (l_ptr->out_queue_size > l_ptr->stats.max_queue_sz)
357 l_ptr->stats.max_queue_sz = l_ptr->out_queue_size;
358
359 if (l_ptr->first_out) {
360 struct tipc_msg *msg = buf_msg(l_ptr->first_out);
361 u32 length = msg_size(msg);
362
363 if ((msg_user(msg) == MSG_FRAGMENTER)
364 && (msg_type(msg) == FIRST_FRAGMENT)) {
365 length = msg_size(msg_get_wrapped(msg));
366 }
367 if (length) {
368 l_ptr->stats.msg_lengths_total += length;
369 l_ptr->stats.msg_length_counts++;
370 if (length <= 64)
371 l_ptr->stats.msg_length_profile[0]++;
372 else if (length <= 256)
373 l_ptr->stats.msg_length_profile[1]++;
374 else if (length <= 1024)
375 l_ptr->stats.msg_length_profile[2]++;
376 else if (length <= 4096)
377 l_ptr->stats.msg_length_profile[3]++;
378 else if (length <= 16384)
379 l_ptr->stats.msg_length_profile[4]++;
380 else if (length <= 32768)
381 l_ptr->stats.msg_length_profile[5]++;
382 else
383 l_ptr->stats.msg_length_profile[6]++;
384 }
385 }
386
387 /* do all other link processing performed on a periodic basis */
388
389 link_check_defragm_bufs(l_ptr);
390
391 link_state_event(l_ptr, TIMEOUT_EVT);
392
393 if (l_ptr->next_out)
394 link_push_queue(l_ptr);
395
396 node_unlock(l_ptr->owner);
397}
398
399static inline void link_set_timer(struct link *l_ptr, u32 time)
400{
401 k_start_timer(&l_ptr->timer, time);
402}
403
404/**
405 * link_create - create a new link
406 * @b_ptr: pointer to associated bearer
407 * @peer: network address of node at other end of link
408 * @media_addr: media address to use when sending messages over link
409 *
410 * Returns pointer to link.
411 */
412
413struct link *link_create(struct bearer *b_ptr, const u32 peer,
414 const struct tipc_media_addr *media_addr)
415{
416 struct link *l_ptr;
417 struct tipc_msg *msg;
418 char *if_name;
419
420 l_ptr = (struct link *)kmalloc(sizeof(*l_ptr), GFP_ATOMIC);
421 if (!l_ptr) {
422 warn("Memory squeeze; Failed to create link\n");
423 return NULL;
424 }
425 memset(l_ptr, 0, sizeof(*l_ptr));
426
427 l_ptr->addr = peer;
428 if_name = strchr(b_ptr->publ.name, ':') + 1;
429 sprintf(l_ptr->name, "%u.%u.%u:%s-%u.%u.%u:",
430 tipc_zone(tipc_own_addr), tipc_cluster(tipc_own_addr),
431 tipc_node(tipc_own_addr),
432 if_name,
433 tipc_zone(peer), tipc_cluster(peer), tipc_node(peer));
434 /* note: peer i/f is appended to link name by reset/activate */
435 memcpy(&l_ptr->media_addr, media_addr, sizeof(*media_addr));
436 k_init_timer(&l_ptr->timer, (Handler)link_timeout, (unsigned long)l_ptr);
437 list_add_tail(&l_ptr->link_list, &b_ptr->links);
438 l_ptr->checkpoint = 1;
439 l_ptr->b_ptr = b_ptr;
440 link_set_supervision_props(l_ptr, b_ptr->media->tolerance);
441 l_ptr->state = RESET_UNKNOWN;
442
443 l_ptr->pmsg = (struct tipc_msg *)&l_ptr->proto_msg;
444 msg = l_ptr->pmsg;
445 msg_init(msg, LINK_PROTOCOL, RESET_MSG, TIPC_OK, INT_H_SIZE, l_ptr->addr);
446 msg_set_size(msg, sizeof(l_ptr->proto_msg));
447 msg_set_session(msg, tipc_random);
448 msg_set_bearer_id(msg, b_ptr->identity);
449 strcpy((char *)msg_data(msg), if_name);
450
451 l_ptr->priority = b_ptr->priority;
452 link_set_queue_limits(l_ptr, b_ptr->media->window);
453
454 link_init_max_pkt(l_ptr);
455
456 l_ptr->next_out_no = 1;
457 INIT_LIST_HEAD(&l_ptr->waiting_ports);
458
459 link_reset_statistics(l_ptr);
460
461 l_ptr->owner = node_attach_link(l_ptr);
462 if (!l_ptr->owner) {
463 kfree(l_ptr);
464 return NULL;
465 }
466
467 if (LINK_LOG_BUF_SIZE) {
468 char *pb = kmalloc(LINK_LOG_BUF_SIZE, GFP_ATOMIC);
469
470 if (!pb) {
471 kfree(l_ptr);
472 warn("Memory squeeze; Failed to create link\n");
473 return NULL;
474 }
475 printbuf_init(&l_ptr->print_buf, pb, LINK_LOG_BUF_SIZE);
476 }
477
478 k_signal((Handler)link_start, (unsigned long)l_ptr);
479
480 dbg("link_create(): tolerance = %u,cont intv = %u, abort_limit = %u\n",
481 l_ptr->tolerance, l_ptr->continuity_interval, l_ptr->abort_limit);
482
483 return l_ptr;
484}
485
486/**
487 * link_delete - delete a link
488 * @l_ptr: pointer to link
489 *
490 * Note: 'net_lock' is write_locked, bearer is locked.
491 * This routine must not grab the node lock until after link timer cancellation
492 * to avoid a potential deadlock situation.
493 */
494
495void link_delete(struct link *l_ptr)
496{
497 if (!l_ptr) {
498 err("Attempt to delete non-existent link\n");
499 return;
500 }
501
502 dbg("link_delete()\n");
503
504 k_cancel_timer(&l_ptr->timer);
505
506 node_lock(l_ptr->owner);
507 link_reset(l_ptr);
508 node_detach_link(l_ptr->owner, l_ptr);
509 link_stop(l_ptr);
510 list_del_init(&l_ptr->link_list);
511 if (LINK_LOG_BUF_SIZE)
512 kfree(l_ptr->print_buf.buf);
513 node_unlock(l_ptr->owner);
514 k_term_timer(&l_ptr->timer);
515 kfree(l_ptr);
516}
517
518void link_start(struct link *l_ptr)
519{
520 dbg("link_start %x\n", l_ptr);
521 link_state_event(l_ptr, STARTING_EVT);
522}
523
524/**
525 * link_schedule_port - schedule port for deferred sending
526 * @l_ptr: pointer to link
527 * @origport: reference to sending port
528 * @sz: amount of data to be sent
529 *
530 * Schedules port for renewed sending of messages after link congestion
531 * has abated.
532 */
533
534static int link_schedule_port(struct link *l_ptr, u32 origport, u32 sz)
535{
536 struct port *p_ptr;
537
538 spin_lock_bh(&port_list_lock);
539 p_ptr = port_lock(origport);
540 if (p_ptr) {
541 if (!p_ptr->wakeup)
542 goto exit;
543 if (!list_empty(&p_ptr->wait_list))
544 goto exit;
545 p_ptr->congested_link = l_ptr;
546 p_ptr->publ.congested = 1;
547 p_ptr->waiting_pkts = 1 + ((sz - 1) / link_max_pkt(l_ptr));
548 list_add_tail(&p_ptr->wait_list, &l_ptr->waiting_ports);
549 l_ptr->stats.link_congs++;
550exit:
551 port_unlock(p_ptr);
552 }
553 spin_unlock_bh(&port_list_lock);
554 return -ELINKCONG;
555}
556
557void link_wakeup_ports(struct link *l_ptr, int all)
558{
559 struct port *p_ptr;
560 struct port *temp_p_ptr;
561 int win = l_ptr->queue_limit[0] - l_ptr->out_queue_size;
562
563 if (all)
564 win = 100000;
565 if (win <= 0)
566 return;
567 if (!spin_trylock_bh(&port_list_lock))
568 return;
569 if (link_congested(l_ptr))
570 goto exit;
571 list_for_each_entry_safe(p_ptr, temp_p_ptr, &l_ptr->waiting_ports,
572 wait_list) {
573 if (win <= 0)
574 break;
575 list_del_init(&p_ptr->wait_list);
576 p_ptr->congested_link = 0;
577 assert(p_ptr->wakeup);
578 spin_lock_bh(p_ptr->publ.lock);
579 p_ptr->publ.congested = 0;
580 p_ptr->wakeup(&p_ptr->publ);
581 win -= p_ptr->waiting_pkts;
582 spin_unlock_bh(p_ptr->publ.lock);
583 }
584
585exit:
586 spin_unlock_bh(&port_list_lock);
587}
588
589/**
590 * link_release_outqueue - purge link's outbound message queue
591 * @l_ptr: pointer to link
592 */
593
594static void link_release_outqueue(struct link *l_ptr)
595{
596 struct sk_buff *buf = l_ptr->first_out;
597 struct sk_buff *next;
598
599 while (buf) {
600 next = buf->next;
601 buf_discard(buf);
602 buf = next;
603 }
604 l_ptr->first_out = NULL;
605 l_ptr->out_queue_size = 0;
606}
607
608/**
609 * link_reset_fragments - purge link's inbound message fragments queue
610 * @l_ptr: pointer to link
611 */
612
613void link_reset_fragments(struct link *l_ptr)
614{
615 struct sk_buff *buf = l_ptr->defragm_buf;
616 struct sk_buff *next;
617
618 while (buf) {
619 next = buf->next;
620 buf_discard(buf);
621 buf = next;
622 }
623 l_ptr->defragm_buf = NULL;
624}
625
626/**
627 * link_stop - purge all inbound and outbound messages associated with link
628 * @l_ptr: pointer to link
629 */
630
631void link_stop(struct link *l_ptr)
632{
633 struct sk_buff *buf;
634 struct sk_buff *next;
635
636 buf = l_ptr->oldest_deferred_in;
637 while (buf) {
638 next = buf->next;
639 buf_discard(buf);
640 buf = next;
641 }
642
643 buf = l_ptr->first_out;
644 while (buf) {
645 next = buf->next;
646 buf_discard(buf);
647 buf = next;
648 }
649
650 link_reset_fragments(l_ptr);
651
652 buf_discard(l_ptr->proto_msg_queue);
653 l_ptr->proto_msg_queue = NULL;
654}
655
656#if 0
657
658/* LINK EVENT CODE IS NOT SUPPORTED AT PRESENT */
659
660static void link_recv_event(struct link_event *ev)
661{
662 ev->fcn(ev->addr, ev->name, ev->up);
663 kfree(ev);
664}
665
666static void link_send_event(void (*fcn)(u32 a, char *n, int up),
667 struct link *l_ptr, int up)
668{
669 struct link_event *ev;
670
671 ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
672 if (!ev) {
673 warn("Link event allocation failure\n");
674 return;
675 }
676 ev->addr = l_ptr->addr;
677 ev->up = up;
678 ev->fcn = fcn;
679 memcpy(ev->name, l_ptr->name, TIPC_MAX_LINK_NAME);
680 k_signal((Handler)link_recv_event, (unsigned long)ev);
681}
682
683#else
684
685#define link_send_event(fcn, l_ptr, up) do { } while (0)
686
687#endif
688
689void link_reset(struct link *l_ptr)
690{
691 struct sk_buff *buf;
692 u32 prev_state = l_ptr->state;
693 u32 checkpoint = l_ptr->next_in_no;
694
695 msg_set_session(l_ptr->pmsg, msg_session(l_ptr->pmsg) + 1);
696
697 /* Link is down, accept any session: */
698 l_ptr->peer_session = 0;
699
700 /* Prepare for max packet size negotiation */
701 link_init_max_pkt(l_ptr);
702
703 l_ptr->state = RESET_UNKNOWN;
704 dbg_link_state("Resetting Link\n");
705
706 if ((prev_state == RESET_UNKNOWN) || (prev_state == RESET_RESET))
707 return;
708
709 node_link_down(l_ptr->owner, l_ptr);
710 bearer_remove_dest(l_ptr->b_ptr, l_ptr->addr);
711#if 0
712 tipc_printf(CONS, "\nReset link <%s>\n", l_ptr->name);
713 dbg_link_dump();
714#endif
715 if (node_has_active_links(l_ptr->owner) &&
716 l_ptr->owner->permit_changeover) {
717 l_ptr->reset_checkpoint = checkpoint;
718 l_ptr->exp_msg_count = START_CHANGEOVER;
719 }
720
721 /* Clean up all queues: */
722
723 link_release_outqueue(l_ptr);
724 buf_discard(l_ptr->proto_msg_queue);
725 l_ptr->proto_msg_queue = NULL;
726 buf = l_ptr->oldest_deferred_in;
727 while (buf) {
728 struct sk_buff *next = buf->next;
729 buf_discard(buf);
730 buf = next;
731 }
732 if (!list_empty(&l_ptr->waiting_ports))
733 link_wakeup_ports(l_ptr, 1);
734
735 l_ptr->retransm_queue_head = 0;
736 l_ptr->retransm_queue_size = 0;
737 l_ptr->last_out = NULL;
738 l_ptr->first_out = NULL;
739 l_ptr->next_out = NULL;
740 l_ptr->unacked_window = 0;
741 l_ptr->checkpoint = 1;
742 l_ptr->next_out_no = 1;
743 l_ptr->deferred_inqueue_sz = 0;
744 l_ptr->oldest_deferred_in = NULL;
745 l_ptr->newest_deferred_in = NULL;
746 l_ptr->fsm_msg_cnt = 0;
747 l_ptr->stale_count = 0;
748 link_reset_statistics(l_ptr);
749
750 link_send_event(cfg_link_event, l_ptr, 0);
751 if (!in_own_cluster(l_ptr->addr))
752 link_send_event(disc_link_event, l_ptr, 0);
753}
754
755
756static void link_activate(struct link *l_ptr)
757{
758 l_ptr->next_in_no = 1;
759 node_link_up(l_ptr->owner, l_ptr);
760 bearer_add_dest(l_ptr->b_ptr, l_ptr->addr);
761 link_send_event(cfg_link_event, l_ptr, 1);
762 if (!in_own_cluster(l_ptr->addr))
763 link_send_event(disc_link_event, l_ptr, 1);
764}
765
766/**
767 * link_state_event - link finite state machine
768 * @l_ptr: pointer to link
769 * @event: state machine event to process
770 */
771
772static void link_state_event(struct link *l_ptr, unsigned event)
773{
774 struct link *other;
775 u32 cont_intv = l_ptr->continuity_interval;
776
777 if (!l_ptr->started && (event != STARTING_EVT))
778 return; /* Not yet. */
779
780 if (link_blocked(l_ptr)) {
781 if (event == TIMEOUT_EVT) {
782 link_set_timer(l_ptr, cont_intv);
783 }
784 return; /* Changeover going on */
785 }
786 dbg_link("STATE_EV: <%s> ", l_ptr->name);
787
788 switch (l_ptr->state) {
789 case WORKING_WORKING:
790 dbg_link("WW/");
791 switch (event) {
792 case TRAFFIC_MSG_EVT:
793 dbg_link("TRF-");
794 /* fall through */
795 case ACTIVATE_MSG:
796 dbg_link("ACT\n");
797 break;
798 case TIMEOUT_EVT:
799 dbg_link("TIM ");
800 if (l_ptr->next_in_no != l_ptr->checkpoint) {
801 l_ptr->checkpoint = l_ptr->next_in_no;
802 if (bclink_acks_missing(l_ptr->owner)) {
803 link_send_proto_msg(l_ptr, STATE_MSG,
804 0, 0, 0, 0, 0);
805 l_ptr->fsm_msg_cnt++;
806 } else if (l_ptr->max_pkt < l_ptr->max_pkt_target) {
807 link_send_proto_msg(l_ptr, STATE_MSG,
808 1, 0, 0, 0, 0);
809 l_ptr->fsm_msg_cnt++;
810 }
811 link_set_timer(l_ptr, cont_intv);
812 break;
813 }
814 dbg_link(" -> WU\n");
815 l_ptr->state = WORKING_UNKNOWN;
816 l_ptr->fsm_msg_cnt = 0;
817 link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0);
818 l_ptr->fsm_msg_cnt++;
819 link_set_timer(l_ptr, cont_intv / 4);
820 break;
821 case RESET_MSG:
822 dbg_link("RES -> RR\n");
823 link_reset(l_ptr);
824 l_ptr->state = RESET_RESET;
825 l_ptr->fsm_msg_cnt = 0;
826 link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0);
827 l_ptr->fsm_msg_cnt++;
828 link_set_timer(l_ptr, cont_intv);
829 break;
830 default:
831 err("Unknown link event %u in WW state\n", event);
832 }
833 break;
834 case WORKING_UNKNOWN:
835 dbg_link("WU/");
836 switch (event) {
837 case TRAFFIC_MSG_EVT:
838 dbg_link("TRF-");
839 case ACTIVATE_MSG:
840 dbg_link("ACT -> WW\n");
841 l_ptr->state = WORKING_WORKING;
842 l_ptr->fsm_msg_cnt = 0;
843 link_set_timer(l_ptr, cont_intv);
844 break;
845 case RESET_MSG:
846 dbg_link("RES -> RR\n");
847 link_reset(l_ptr);
848 l_ptr->state = RESET_RESET;
849 l_ptr->fsm_msg_cnt = 0;
850 link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0);
851 l_ptr->fsm_msg_cnt++;
852 link_set_timer(l_ptr, cont_intv);
853 break;
854 case TIMEOUT_EVT:
855 dbg_link("TIM ");
856 if (l_ptr->next_in_no != l_ptr->checkpoint) {
857 dbg_link("-> WW \n");
858 l_ptr->state = WORKING_WORKING;
859 l_ptr->fsm_msg_cnt = 0;
860 l_ptr->checkpoint = l_ptr->next_in_no;
861 if (bclink_acks_missing(l_ptr->owner)) {
862 link_send_proto_msg(l_ptr, STATE_MSG,
863 0, 0, 0, 0, 0);
864 l_ptr->fsm_msg_cnt++;
865 }
866 link_set_timer(l_ptr, cont_intv);
867 } else if (l_ptr->fsm_msg_cnt < l_ptr->abort_limit) {
868 dbg_link("Probing %u/%u,timer = %u ms)\n",
869 l_ptr->fsm_msg_cnt, l_ptr->abort_limit,
870 cont_intv / 4);
871 link_send_proto_msg(l_ptr, STATE_MSG,
872 1, 0, 0, 0, 0);
873 l_ptr->fsm_msg_cnt++;
874 link_set_timer(l_ptr, cont_intv / 4);
875 } else { /* Link has failed */
876 dbg_link("-> RU (%u probes unanswered)\n",
877 l_ptr->fsm_msg_cnt);
878 link_reset(l_ptr);
879 l_ptr->state = RESET_UNKNOWN;
880 l_ptr->fsm_msg_cnt = 0;
881 link_send_proto_msg(l_ptr, RESET_MSG,
882 0, 0, 0, 0, 0);
883 l_ptr->fsm_msg_cnt++;
884 link_set_timer(l_ptr, cont_intv);
885 }
886 break;
887 default:
888 err("Unknown link event %u in WU state\n", event);
889 }
890 break;
891 case RESET_UNKNOWN:
892 dbg_link("RU/");
893 switch (event) {
894 case TRAFFIC_MSG_EVT:
895 dbg_link("TRF-\n");
896 break;
897 case ACTIVATE_MSG:
898 other = l_ptr->owner->active_links[0];
899 if (other && link_working_unknown(other)) {
900 dbg_link("ACT\n");
901 break;
902 }
903 dbg_link("ACT -> WW\n");
904 l_ptr->state = WORKING_WORKING;
905 l_ptr->fsm_msg_cnt = 0;
906 link_activate(l_ptr);
907 link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0);
908 l_ptr->fsm_msg_cnt++;
909 link_set_timer(l_ptr, cont_intv);
910 break;
911 case RESET_MSG:
912 dbg_link("RES \n");
913 dbg_link(" -> RR\n");
914 l_ptr->state = RESET_RESET;
915 l_ptr->fsm_msg_cnt = 0;
916 link_send_proto_msg(l_ptr, ACTIVATE_MSG, 1, 0, 0, 0, 0);
917 l_ptr->fsm_msg_cnt++;
918 link_set_timer(l_ptr, cont_intv);
919 break;
920 case STARTING_EVT:
921 dbg_link("START-");
922 l_ptr->started = 1;
923 /* fall through */
924 case TIMEOUT_EVT:
925 dbg_link("TIM \n");
926 link_send_proto_msg(l_ptr, RESET_MSG, 0, 0, 0, 0, 0);
927 l_ptr->fsm_msg_cnt++;
928 link_set_timer(l_ptr, cont_intv);
929 break;
930 default:
931 err("Unknown link event %u in RU state\n", event);
932 }
933 break;
934 case RESET_RESET:
935 dbg_link("RR/ ");
936 switch (event) {
937 case TRAFFIC_MSG_EVT:
938 dbg_link("TRF-");
939 /* fall through */
940 case ACTIVATE_MSG:
941 other = l_ptr->owner->active_links[0];
942 if (other && link_working_unknown(other)) {
943 dbg_link("ACT\n");
944 break;
945 }
946 dbg_link("ACT -> WW\n");
947 l_ptr->state = WORKING_WORKING;
948 l_ptr->fsm_msg_cnt = 0;
949 link_activate(l_ptr);
950 link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0);
951 l_ptr->fsm_msg_cnt++;
952 link_set_timer(l_ptr, cont_intv);
953 break;
954 case RESET_MSG:
955 dbg_link("RES\n");
956 break;
957 case TIMEOUT_EVT:
958 dbg_link("TIM\n");
959 link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0);
960 l_ptr->fsm_msg_cnt++;
961 link_set_timer(l_ptr, cont_intv);
962 dbg_link("fsm_msg_cnt %u\n", l_ptr->fsm_msg_cnt);
963 break;
964 default:
965 err("Unknown link event %u in RR state\n", event);
966 }
967 break;
968 default:
969 err("Unknown link state %u/%u\n", l_ptr->state, event);
970 }
971}
972
973/*
974 * link_bundle_buf(): Append contents of a buffer to
975 * the tail of an existing one.
976 */
977
978static int link_bundle_buf(struct link *l_ptr,
979 struct sk_buff *bundler,
980 struct sk_buff *buf)
981{
982 struct tipc_msg *bundler_msg = buf_msg(bundler);
983 struct tipc_msg *msg = buf_msg(buf);
984 u32 size = msg_size(msg);
985 u32 to_pos = align(msg_size(bundler_msg));
986 u32 rest = link_max_pkt(l_ptr) - to_pos;
987
988 if (msg_user(bundler_msg) != MSG_BUNDLER)
989 return 0;
990 if (msg_type(bundler_msg) != OPEN_MSG)
991 return 0;
992 if (rest < align(size))
993 return 0;
994
995 skb_put(bundler, (to_pos - msg_size(bundler_msg)) + size);
996 memcpy(bundler->data + to_pos, buf->data, size);
997 msg_set_size(bundler_msg, to_pos + size);
998 msg_set_msgcnt(bundler_msg, msg_msgcnt(bundler_msg) + 1);
999 dbg("Packed msg # %u(%u octets) into pos %u in buf(#%u)\n",
1000 msg_msgcnt(bundler_msg), size, to_pos, msg_seqno(bundler_msg));
1001 msg_dbg(msg, "PACKD:");
1002 buf_discard(buf);
1003 l_ptr->stats.sent_bundled++;
1004 return 1;
1005}
1006
1007static inline void link_add_to_outqueue(struct link *l_ptr,
1008 struct sk_buff *buf,
1009 struct tipc_msg *msg)
1010{
1011 u32 ack = mod(l_ptr->next_in_no - 1);
1012 u32 seqno = mod(l_ptr->next_out_no++);
1013
1014 msg_set_word(msg, 2, ((ack << 16) | seqno));
1015 msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in);
1016 buf->next = NULL;
1017 if (l_ptr->first_out) {
1018 l_ptr->last_out->next = buf;
1019 l_ptr->last_out = buf;
1020 } else
1021 l_ptr->first_out = l_ptr->last_out = buf;
1022 l_ptr->out_queue_size++;
1023}
1024
1025/*
1026 * link_send_buf() is the 'full path' for messages, called from
1027 * inside TIPC when the 'fast path' in tipc_send_buf
1028 * has failed, and from link_send()
1029 */
1030
1031int link_send_buf(struct link *l_ptr, struct sk_buff *buf)
1032{
1033 struct tipc_msg *msg = buf_msg(buf);
1034 u32 size = msg_size(msg);
1035 u32 dsz = msg_data_sz(msg);
1036 u32 queue_size = l_ptr->out_queue_size;
1037 u32 imp = msg_tot_importance(msg);
1038 u32 queue_limit = l_ptr->queue_limit[imp];
1039 u32 max_packet = link_max_pkt(l_ptr);
1040
1041 msg_set_prevnode(msg, tipc_own_addr); /* If routed message */
1042
1043 /* Match msg importance against queue limits: */
1044
1045 if (unlikely(queue_size >= queue_limit)) {
1046 if (imp <= TIPC_CRITICAL_IMPORTANCE) {
1047 return link_schedule_port(l_ptr, msg_origport(msg),
1048 size);
1049 }
1050 msg_dbg(msg, "TIPC: Congestion, throwing away\n");
1051 buf_discard(buf);
1052 if (imp > CONN_MANAGER) {
1053 warn("Resetting <%s>, send queue full", l_ptr->name);
1054 link_reset(l_ptr);
1055 }
1056 return dsz;
1057 }
1058
1059 /* Fragmentation needed ? */
1060
1061 if (size > max_packet)
1062 return link_send_long_buf(l_ptr, buf);
1063
1064 /* Packet can be queued or sent: */
1065
1066 if (queue_size > l_ptr->stats.max_queue_sz)
1067 l_ptr->stats.max_queue_sz = queue_size;
1068
1069 if (likely(!bearer_congested(l_ptr->b_ptr, l_ptr) &&
1070 !link_congested(l_ptr))) {
1071 link_add_to_outqueue(l_ptr, buf, msg);
1072
1073 if (likely(bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr))) {
1074 l_ptr->unacked_window = 0;
1075 } else {
1076 bearer_schedule(l_ptr->b_ptr, l_ptr);
1077 l_ptr->stats.bearer_congs++;
1078 l_ptr->next_out = buf;
1079 }
1080 return dsz;
1081 }
1082 /* Congestion: can message be bundled ?: */
1083
1084 if ((msg_user(msg) != CHANGEOVER_PROTOCOL) &&
1085 (msg_user(msg) != MSG_FRAGMENTER)) {
1086
1087 /* Try adding message to an existing bundle */
1088
1089 if (l_ptr->next_out &&
1090 link_bundle_buf(l_ptr, l_ptr->last_out, buf)) {
1091 bearer_resolve_congestion(l_ptr->b_ptr, l_ptr);
1092 return dsz;
1093 }
1094
1095 /* Try creating a new bundle */
1096
1097 if (size <= max_packet * 2 / 3) {
1098 struct sk_buff *bundler = buf_acquire(max_packet);
1099 struct tipc_msg bundler_hdr;
1100
1101 if (bundler) {
1102 msg_init(&bundler_hdr, MSG_BUNDLER, OPEN_MSG,
1103 TIPC_OK, INT_H_SIZE, l_ptr->addr);
1104 memcpy(bundler->data, (unchar *)&bundler_hdr,
1105 INT_H_SIZE);
1106 skb_trim(bundler, INT_H_SIZE);
1107 link_bundle_buf(l_ptr, bundler, buf);
1108 buf = bundler;
1109 msg = buf_msg(buf);
1110 l_ptr->stats.sent_bundles++;
1111 }
1112 }
1113 }
1114 if (!l_ptr->next_out)
1115 l_ptr->next_out = buf;
1116 link_add_to_outqueue(l_ptr, buf, msg);
1117 bearer_resolve_congestion(l_ptr->b_ptr, l_ptr);
1118 return dsz;
1119}
1120
1121/*
1122 * link_send(): same as link_send_buf(), but the link to use has
1123 * not been selected yet, and the the owner node is not locked
1124 * Called by TIPC internal users, e.g. the name distributor
1125 */
1126
1127int link_send(struct sk_buff *buf, u32 dest, u32 selector)
1128{
1129 struct link *l_ptr;
1130 struct node *n_ptr;
1131 int res = -ELINKCONG;
1132
1133 read_lock_bh(&net_lock);
1134 n_ptr = node_select(dest, selector);
1135 if (n_ptr) {
1136 node_lock(n_ptr);
1137 l_ptr = n_ptr->active_links[selector & 1];
1138 dbg("link_send: found link %x for dest %x\n", l_ptr, dest);
1139 if (l_ptr) {
1140 res = link_send_buf(l_ptr, buf);
1141 }
1142 node_unlock(n_ptr);
1143 } else {
1144 dbg("Attempt to send msg to unknown node:\n");
1145 msg_dbg(buf_msg(buf),">>>");
1146 buf_discard(buf);
1147 }
1148 read_unlock_bh(&net_lock);
1149 return res;
1150}
1151
1152/*
1153 * link_send_buf_fast: Entry for data messages where the
1154 * destination link is known and the header is complete,
1155 * inclusive total message length. Very time critical.
1156 * Link is locked. Returns user data length.
1157 */
1158
1159static inline int link_send_buf_fast(struct link *l_ptr, struct sk_buff *buf,
1160 u32 *used_max_pkt)
1161{
1162 struct tipc_msg *msg = buf_msg(buf);
1163 int res = msg_data_sz(msg);
1164
1165 if (likely(!link_congested(l_ptr))) {
1166 if (likely(msg_size(msg) <= link_max_pkt(l_ptr))) {
1167 if (likely(list_empty(&l_ptr->b_ptr->cong_links))) {
1168 link_add_to_outqueue(l_ptr, buf, msg);
1169 if (likely(bearer_send(l_ptr->b_ptr, buf,
1170 &l_ptr->media_addr))) {
1171 l_ptr->unacked_window = 0;
1172 msg_dbg(msg,"SENT_FAST:");
1173 return res;
1174 }
1175 dbg("failed sent fast...\n");
1176 bearer_schedule(l_ptr->b_ptr, l_ptr);
1177 l_ptr->stats.bearer_congs++;
1178 l_ptr->next_out = buf;
1179 return res;
1180 }
1181 }
1182 else
1183 *used_max_pkt = link_max_pkt(l_ptr);
1184 }
1185 return link_send_buf(l_ptr, buf); /* All other cases */
1186}
1187
1188/*
1189 * tipc_send_buf_fast: Entry for data messages where the
1190 * destination node is known and the header is complete,
1191 * inclusive total message length.
1192 * Returns user data length.
1193 */
1194int tipc_send_buf_fast(struct sk_buff *buf, u32 destnode)
1195{
1196 struct link *l_ptr;
1197 struct node *n_ptr;
1198 int res;
1199 u32 selector = msg_origport(buf_msg(buf)) & 1;
1200 u32 dummy;
1201
1202 if (destnode == tipc_own_addr)
1203 return port_recv_msg(buf);
1204
1205 read_lock_bh(&net_lock);
1206 n_ptr = node_select(destnode, selector);
1207 if (likely(n_ptr)) {
1208 node_lock(n_ptr);
1209 l_ptr = n_ptr->active_links[selector];
1210 dbg("send_fast: buf %x selected %x, destnode = %x\n",
1211 buf, l_ptr, destnode);
1212 if (likely(l_ptr)) {
1213 res = link_send_buf_fast(l_ptr, buf, &dummy);
1214 node_unlock(n_ptr);
1215 read_unlock_bh(&net_lock);
1216 return res;
1217 }
1218 node_unlock(n_ptr);
1219 }
1220 read_unlock_bh(&net_lock);
1221 res = msg_data_sz(buf_msg(buf));
1222 tipc_reject_msg(buf, TIPC_ERR_NO_NODE);
1223 return res;
1224}
1225
1226
1227/*
1228 * link_send_sections_fast: Entry for messages where the
1229 * destination processor is known and the header is complete,
1230 * except for total message length.
1231 * Returns user data length or errno.
1232 */
1233int link_send_sections_fast(struct port *sender,
1234 struct iovec const *msg_sect,
1235 const u32 num_sect,
1236 u32 destaddr)
1237{
1238 struct tipc_msg *hdr = &sender->publ.phdr;
1239 struct link *l_ptr;
1240 struct sk_buff *buf;
1241 struct node *node;
1242 int res;
1243 u32 selector = msg_origport(hdr) & 1;
1244
1245 assert(destaddr != tipc_own_addr);
1246
1247again:
1248 /*
1249 * Try building message using port's max_pkt hint.
1250 * (Must not hold any locks while building message.)
1251 */
1252
1253 res = msg_build(hdr, msg_sect, num_sect, sender->max_pkt,
1254 !sender->user_port, &buf);
1255
1256 read_lock_bh(&net_lock);
1257 node = node_select(destaddr, selector);
1258 if (likely(node)) {
1259 node_lock(node);
1260 l_ptr = node->active_links[selector];
1261 if (likely(l_ptr)) {
1262 if (likely(buf)) {
1263 res = link_send_buf_fast(l_ptr, buf,
1264 &sender->max_pkt);
1265 if (unlikely(res < 0))
1266 buf_discard(buf);
1267exit:
1268 node_unlock(node);
1269 read_unlock_bh(&net_lock);
1270 return res;
1271 }
1272
1273 /* Exit if build request was invalid */
1274
1275 if (unlikely(res < 0))
1276 goto exit;
1277
1278 /* Exit if link (or bearer) is congested */
1279
1280 if (link_congested(l_ptr) ||
1281 !list_empty(&l_ptr->b_ptr->cong_links)) {
1282 res = link_schedule_port(l_ptr,
1283 sender->publ.ref, res);
1284 goto exit;
1285 }
1286
1287 /*
1288 * Message size exceeds max_pkt hint; update hint,
1289 * then re-try fast path or fragment the message
1290 */
1291
1292 sender->max_pkt = link_max_pkt(l_ptr);
1293 node_unlock(node);
1294 read_unlock_bh(&net_lock);
1295
1296
1297 if ((msg_hdr_sz(hdr) + res) <= sender->max_pkt)
1298 goto again;
1299
1300 return link_send_sections_long(sender, msg_sect,
1301 num_sect, destaddr);
1302 }
1303 node_unlock(node);
1304 }
1305 read_unlock_bh(&net_lock);
1306
1307 /* Couldn't find a link to the destination node */
1308
1309 if (buf)
1310 return tipc_reject_msg(buf, TIPC_ERR_NO_NODE);
1311 if (res >= 0)
1312 return port_reject_sections(sender, hdr, msg_sect, num_sect,
1313 TIPC_ERR_NO_NODE);
1314 return res;
1315}
1316
1317/*
1318 * link_send_sections_long(): Entry for long messages where the
1319 * destination node is known and the header is complete,
1320 * inclusive total message length.
1321 * Link and bearer congestion status have been checked to be ok,
1322 * and are ignored if they change.
1323 *
1324 * Note that fragments do not use the full link MTU so that they won't have
1325 * to undergo refragmentation if link changeover causes them to be sent
1326 * over another link with an additional tunnel header added as prefix.
1327 * (Refragmentation will still occur if the other link has a smaller MTU.)
1328 *
1329 * Returns user data length or errno.
1330 */
1331static int link_send_sections_long(struct port *sender,
1332 struct iovec const *msg_sect,
1333 u32 num_sect,
1334 u32 destaddr)
1335{
1336 struct link *l_ptr;
1337 struct node *node;
1338 struct tipc_msg *hdr = &sender->publ.phdr;
1339 u32 dsz = msg_data_sz(hdr);
1340 u32 max_pkt,fragm_sz,rest;
1341 struct tipc_msg fragm_hdr;
1342 struct sk_buff *buf,*buf_chain,*prev;
1343 u32 fragm_crs,fragm_rest,hsz,sect_rest;
1344 const unchar *sect_crs;
1345 int curr_sect;
1346 u32 fragm_no;
1347
1348again:
1349 fragm_no = 1;
1350 max_pkt = sender->max_pkt - INT_H_SIZE;
1351 /* leave room for tunnel header in case of link changeover */
1352 fragm_sz = max_pkt - INT_H_SIZE;
1353 /* leave room for fragmentation header in each fragment */
1354 rest = dsz;
1355 fragm_crs = 0;
1356 fragm_rest = 0;
1357 sect_rest = 0;
1358 sect_crs = 0;
1359 curr_sect = -1;
1360
1361 /* Prepare reusable fragment header: */
1362
1363 msg_dbg(hdr, ">FRAGMENTING>");
1364 msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT,
1365 TIPC_OK, INT_H_SIZE, msg_destnode(hdr));
1366 msg_set_link_selector(&fragm_hdr, sender->publ.ref);
1367 msg_set_size(&fragm_hdr, max_pkt);
1368 msg_set_fragm_no(&fragm_hdr, 1);
1369
1370 /* Prepare header of first fragment: */
1371
1372 buf_chain = buf = buf_acquire(max_pkt);
1373 if (!buf)
1374 return -ENOMEM;
1375 buf->next = NULL;
1376 memcpy(buf->data, (unchar *)&fragm_hdr, INT_H_SIZE);
1377 hsz = msg_hdr_sz(hdr);
1378 memcpy(buf->data + INT_H_SIZE, (unchar *)hdr, hsz);
1379 msg_dbg(buf_msg(buf), ">BUILD>");
1380
1381 /* Chop up message: */
1382
1383 fragm_crs = INT_H_SIZE + hsz;
1384 fragm_rest = fragm_sz - hsz;
1385
1386 do { /* For all sections */
1387 u32 sz;
1388
1389 if (!sect_rest) {
1390 sect_rest = msg_sect[++curr_sect].iov_len;
1391 sect_crs = (const unchar *)msg_sect[curr_sect].iov_base;
1392 }
1393
1394 if (sect_rest < fragm_rest)
1395 sz = sect_rest;
1396 else
1397 sz = fragm_rest;
1398
1399 if (likely(!sender->user_port)) {
1400 if (copy_from_user(buf->data + fragm_crs, sect_crs, sz)) {
1401error:
1402 for (; buf_chain; buf_chain = buf) {
1403 buf = buf_chain->next;
1404 buf_discard(buf_chain);
1405 }
1406 return -EFAULT;
1407 }
1408 } else
1409 memcpy(buf->data + fragm_crs, sect_crs, sz);
1410
1411 sect_crs += sz;
1412 sect_rest -= sz;
1413 fragm_crs += sz;
1414 fragm_rest -= sz;
1415 rest -= sz;
1416
1417 if (!fragm_rest && rest) {
1418
1419 /* Initiate new fragment: */
1420 if (rest <= fragm_sz) {
1421 fragm_sz = rest;
1422 msg_set_type(&fragm_hdr,LAST_FRAGMENT);
1423 } else {
1424 msg_set_type(&fragm_hdr, FRAGMENT);
1425 }
1426 msg_set_size(&fragm_hdr, fragm_sz + INT_H_SIZE);
1427 msg_set_fragm_no(&fragm_hdr, ++fragm_no);
1428 prev = buf;
1429 buf = buf_acquire(fragm_sz + INT_H_SIZE);
1430 if (!buf)
1431 goto error;
1432
1433 buf->next = NULL;
1434 prev->next = buf;
1435 memcpy(buf->data, (unchar *)&fragm_hdr, INT_H_SIZE);
1436 fragm_crs = INT_H_SIZE;
1437 fragm_rest = fragm_sz;
1438 msg_dbg(buf_msg(buf)," >BUILD>");
1439 }
1440 }
1441 while (rest > 0);
1442
1443 /*
1444 * Now we have a buffer chain. Select a link and check
1445 * that packet size is still OK
1446 */
1447 node = node_select(destaddr, sender->publ.ref & 1);
1448 if (likely(node)) {
1449 node_lock(node);
1450 l_ptr = node->active_links[sender->publ.ref & 1];
1451 if (!l_ptr) {
1452 node_unlock(node);
1453 goto reject;
1454 }
1455 if (link_max_pkt(l_ptr) < max_pkt) {
1456 sender->max_pkt = link_max_pkt(l_ptr);
1457 node_unlock(node);
1458 for (; buf_chain; buf_chain = buf) {
1459 buf = buf_chain->next;
1460 buf_discard(buf_chain);
1461 }
1462 goto again;
1463 }
1464 } else {
1465reject:
1466 for (; buf_chain; buf_chain = buf) {
1467 buf = buf_chain->next;
1468 buf_discard(buf_chain);
1469 }
1470 return port_reject_sections(sender, hdr, msg_sect, num_sect,
1471 TIPC_ERR_NO_NODE);
1472 }
1473
1474 /* Append whole chain to send queue: */
1475
1476 buf = buf_chain;
1477 l_ptr->long_msg_seq_no = mod(l_ptr->long_msg_seq_no + 1);
1478 if (!l_ptr->next_out)
1479 l_ptr->next_out = buf_chain;
1480 l_ptr->stats.sent_fragmented++;
1481 while (buf) {
1482 struct sk_buff *next = buf->next;
1483 struct tipc_msg *msg = buf_msg(buf);
1484
1485 l_ptr->stats.sent_fragments++;
1486 msg_set_long_msgno(msg, l_ptr->long_msg_seq_no);
1487 link_add_to_outqueue(l_ptr, buf, msg);
1488 msg_dbg(msg, ">ADD>");
1489 buf = next;
1490 }
1491
1492 /* Send it, if possible: */
1493
1494 link_push_queue(l_ptr);
1495 node_unlock(node);
1496 return dsz;
1497}
1498
1499/*
1500 * link_push_packet: Push one unsent packet to the media
1501 */
1502u32 link_push_packet(struct link *l_ptr)
1503{
1504 struct sk_buff *buf = l_ptr->first_out;
1505 u32 r_q_size = l_ptr->retransm_queue_size;
1506 u32 r_q_head = l_ptr->retransm_queue_head;
1507
1508 /* Step to position where retransmission failed, if any, */
1509 /* consider that buffers may have been released in meantime */
1510
1511 if (r_q_size && buf) {
1512 u32 last = lesser(mod(r_q_head + r_q_size),
1513 link_last_sent(l_ptr));
1514 u32 first = msg_seqno(buf_msg(buf));
1515
1516 while (buf && less(first, r_q_head)) {
1517 first = mod(first + 1);
1518 buf = buf->next;
1519 }
1520 l_ptr->retransm_queue_head = r_q_head = first;
1521 l_ptr->retransm_queue_size = r_q_size = mod(last - first);
1522 }
1523
1524 /* Continue retransmission now, if there is anything: */
1525
1526 if (r_q_size && buf && !skb_cloned(buf)) {
1527 msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1));
1528 msg_set_bcast_ack(buf_msg(buf), l_ptr->owner->bclink.last_in);
1529 if (bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
1530 msg_dbg(buf_msg(buf), ">DEF-RETR>");
1531 l_ptr->retransm_queue_head = mod(++r_q_head);
1532 l_ptr->retransm_queue_size = --r_q_size;
1533 l_ptr->stats.retransmitted++;
1534 return TIPC_OK;
1535 } else {
1536 l_ptr->stats.bearer_congs++;
1537 msg_dbg(buf_msg(buf), "|>DEF-RETR>");
1538 return PUSH_FAILED;
1539 }
1540 }
1541
1542 /* Send deferred protocol message, if any: */
1543
1544 buf = l_ptr->proto_msg_queue;
1545 if (buf) {
1546 msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1));
1547 msg_set_bcast_ack(buf_msg(buf),l_ptr->owner->bclink.last_in);
1548 if (bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
1549 msg_dbg(buf_msg(buf), ">DEF-PROT>");
1550 l_ptr->unacked_window = 0;
1551 buf_discard(buf);
1552 l_ptr->proto_msg_queue = 0;
1553 return TIPC_OK;
1554 } else {
1555 msg_dbg(buf_msg(buf), "|>DEF-PROT>");
1556 l_ptr->stats.bearer_congs++;
1557 return PUSH_FAILED;
1558 }
1559 }
1560
1561 /* Send one deferred data message, if send window not full: */
1562
1563 buf = l_ptr->next_out;
1564 if (buf) {
1565 struct tipc_msg *msg = buf_msg(buf);
1566 u32 next = msg_seqno(msg);
1567 u32 first = msg_seqno(buf_msg(l_ptr->first_out));
1568
1569 if (mod(next - first) < l_ptr->queue_limit[0]) {
1570 msg_set_ack(msg, mod(l_ptr->next_in_no - 1));
1571 msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in);
1572 if (bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
1573 if (msg_user(msg) == MSG_BUNDLER)
1574 msg_set_type(msg, CLOSED_MSG);
1575 msg_dbg(msg, ">PUSH-DATA>");
1576 l_ptr->next_out = buf->next;
1577 return TIPC_OK;
1578 } else {
1579 msg_dbg(msg, "|PUSH-DATA|");
1580 l_ptr->stats.bearer_congs++;
1581 return PUSH_FAILED;
1582 }
1583 }
1584 }
1585 return PUSH_FINISHED;
1586}
1587
1588/*
1589 * push_queue(): push out the unsent messages of a link where
1590 * congestion has abated. Node is locked
1591 */
1592void link_push_queue(struct link *l_ptr)
1593{
1594 u32 res;
1595
1596 if (bearer_congested(l_ptr->b_ptr, l_ptr))
1597 return;
1598
1599 do {
1600 res = link_push_packet(l_ptr);
1601 }
1602 while (res == TIPC_OK);
1603 if (res == PUSH_FAILED)
1604 bearer_schedule(l_ptr->b_ptr, l_ptr);
1605}
1606
1607void link_retransmit(struct link *l_ptr, struct sk_buff *buf,
1608 u32 retransmits)
1609{
1610 struct tipc_msg *msg;
1611
1612 dbg("Retransmitting %u in link %x\n", retransmits, l_ptr);
1613
1614 if (bearer_congested(l_ptr->b_ptr, l_ptr) && buf && !skb_cloned(buf)) {
1615 msg_dbg(buf_msg(buf), ">NO_RETR->BCONG>");
1616 dbg_print_link(l_ptr, " ");
1617 l_ptr->retransm_queue_head = msg_seqno(buf_msg(buf));
1618 l_ptr->retransm_queue_size = retransmits;
1619 return;
1620 }
1621 while (retransmits && (buf != l_ptr->next_out) && buf && !skb_cloned(buf)) {
1622 msg = buf_msg(buf);
1623 msg_set_ack(msg, mod(l_ptr->next_in_no - 1));
1624 msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in);
1625 if (bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
1626 /* Catch if retransmissions fail repeatedly: */
1627 if (l_ptr->last_retransmitted == msg_seqno(msg)) {
1628 if (++l_ptr->stale_count > 100) {
1629 msg_print(CONS, buf_msg(buf), ">RETR>");
1630 info("...Retransmitted %u times\n",
1631 l_ptr->stale_count);
1632 link_print(l_ptr, CONS, "Resetting Link\n");;
1633 link_reset(l_ptr);
1634 break;
1635 }
1636 } else {
1637 l_ptr->stale_count = 0;
1638 }
1639 l_ptr->last_retransmitted = msg_seqno(msg);
1640
1641 msg_dbg(buf_msg(buf), ">RETR>");
1642 buf = buf->next;
1643 retransmits--;
1644 l_ptr->stats.retransmitted++;
1645 } else {
1646 bearer_schedule(l_ptr->b_ptr, l_ptr);
1647 l_ptr->stats.bearer_congs++;
1648 l_ptr->retransm_queue_head = msg_seqno(buf_msg(buf));
1649 l_ptr->retransm_queue_size = retransmits;
1650 return;
1651 }
1652 }
1653 l_ptr->retransm_queue_head = l_ptr->retransm_queue_size = 0;
1654}
1655
1656/*
1657 * link_recv_non_seq: Receive packets which are outside
1658 * the link sequence flow
1659 */
1660
1661static void link_recv_non_seq(struct sk_buff *buf)
1662{
1663 struct tipc_msg *msg = buf_msg(buf);
1664
1665 if (msg_user(msg) == LINK_CONFIG)
1666 disc_recv_msg(buf);
1667 else
1668 bclink_recv_pkt(buf);
1669}
1670
1671/**
1672 * link_insert_deferred_queue - insert deferred messages back into receive chain
1673 */
1674
1675static struct sk_buff *link_insert_deferred_queue(struct link *l_ptr,
1676 struct sk_buff *buf)
1677{
1678 u32 seq_no;
1679
1680 if (l_ptr->oldest_deferred_in == NULL)
1681 return buf;
1682
1683 seq_no = msg_seqno(buf_msg(l_ptr->oldest_deferred_in));
1684 if (seq_no == mod(l_ptr->next_in_no)) {
1685 l_ptr->newest_deferred_in->next = buf;
1686 buf = l_ptr->oldest_deferred_in;
1687 l_ptr->oldest_deferred_in = NULL;
1688 l_ptr->deferred_inqueue_sz = 0;
1689 }
1690 return buf;
1691}
1692
1693void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr)
1694{
1695 read_lock_bh(&net_lock);
1696 while (head) {
1697 struct bearer *b_ptr;
1698 struct node *n_ptr;
1699 struct link *l_ptr;
1700 struct sk_buff *crs;
1701 struct sk_buff *buf = head;
1702 struct tipc_msg *msg = buf_msg(buf);
1703 u32 seq_no = msg_seqno(msg);
1704 u32 ackd = msg_ack(msg);
1705 u32 released = 0;
1706 int type;
1707
1708 b_ptr = (struct bearer *)tb_ptr;
1709 TIPC_SKB_CB(buf)->handle = b_ptr;
1710
1711 head = head->next;
1712 if (unlikely(msg_version(msg) != TIPC_VERSION))
1713 goto cont;
1714#if 0
1715 if (msg_user(msg) != LINK_PROTOCOL)
1716#endif
1717 msg_dbg(msg,"<REC<");
1718
1719 if (unlikely(msg_non_seq(msg))) {
1720 link_recv_non_seq(buf);
1721 continue;
1722 }
1723 n_ptr = node_find(msg_prevnode(msg));
1724 if (unlikely(!n_ptr))
1725 goto cont;
1726
1727 node_lock(n_ptr);
1728 l_ptr = n_ptr->links[b_ptr->identity];
1729 if (unlikely(!l_ptr)) {
1730 node_unlock(n_ptr);
1731 goto cont;
1732 }
1733 /*
1734 * Release acked messages
1735 */
1736 if (less(n_ptr->bclink.acked, msg_bcast_ack(msg))) {
1737 if (node_is_up(n_ptr) && n_ptr->bclink.supported)
1738 bclink_acknowledge(n_ptr, msg_bcast_ack(msg));
1739 }
1740
1741 crs = l_ptr->first_out;
1742 while ((crs != l_ptr->next_out) &&
1743 less_eq(msg_seqno(buf_msg(crs)), ackd)) {
1744 struct sk_buff *next = crs->next;
1745
1746 buf_discard(crs);
1747 crs = next;
1748 released++;
1749 }
1750 if (released) {
1751 l_ptr->first_out = crs;
1752 l_ptr->out_queue_size -= released;
1753 }
1754 if (unlikely(l_ptr->next_out))
1755 link_push_queue(l_ptr);
1756 if (unlikely(!list_empty(&l_ptr->waiting_ports)))
1757 link_wakeup_ports(l_ptr, 0);
1758 if (unlikely(++l_ptr->unacked_window >= TIPC_MIN_LINK_WIN)) {
1759 l_ptr->stats.sent_acks++;
1760 link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0);
1761 }
1762
1763protocol_check:
1764 if (likely(link_working_working(l_ptr))) {
1765 if (likely(seq_no == mod(l_ptr->next_in_no))) {
1766 l_ptr->next_in_no++;
1767 if (unlikely(l_ptr->oldest_deferred_in))
1768 head = link_insert_deferred_queue(l_ptr,
1769 head);
1770 if (likely(msg_is_dest(msg, tipc_own_addr))) {
1771deliver:
1772 if (likely(msg_isdata(msg))) {
1773 node_unlock(n_ptr);
1774 port_recv_msg(buf);
1775 continue;
1776 }
1777 switch (msg_user(msg)) {
1778 case MSG_BUNDLER:
1779 l_ptr->stats.recv_bundles++;
1780 l_ptr->stats.recv_bundled +=
1781 msg_msgcnt(msg);
1782 node_unlock(n_ptr);
1783 link_recv_bundle(buf);
1784 continue;
1785 case ROUTE_DISTRIBUTOR:
1786 node_unlock(n_ptr);
1787 cluster_recv_routing_table(buf);
1788 continue;
1789 case NAME_DISTRIBUTOR:
1790 node_unlock(n_ptr);
1791 named_recv(buf);
1792 continue;
1793 case CONN_MANAGER:
1794 node_unlock(n_ptr);
1795 port_recv_proto_msg(buf);
1796 continue;
1797 case MSG_FRAGMENTER:
1798 l_ptr->stats.recv_fragments++;
1799 if (link_recv_fragment(
1800 &l_ptr->defragm_buf,
1801 &buf, &msg)) {
1802 l_ptr->stats.recv_fragmented++;
1803 goto deliver;
1804 }
1805 break;
1806 case CHANGEOVER_PROTOCOL:
1807 type = msg_type(msg);
1808 if (link_recv_changeover_msg(
1809 &l_ptr, &buf)) {
1810 msg = buf_msg(buf);
1811 seq_no = msg_seqno(msg);
1812 TIPC_SKB_CB(buf)->handle
1813 = b_ptr;
1814 if (type == ORIGINAL_MSG)
1815 goto deliver;
1816 goto protocol_check;
1817 }
1818 break;
1819 }
1820 }
1821 node_unlock(n_ptr);
1822 net_route_msg(buf);
1823 continue;
1824 }
1825 link_handle_out_of_seq_msg(l_ptr, buf);
1826 head = link_insert_deferred_queue(l_ptr, head);
1827 node_unlock(n_ptr);
1828 continue;
1829 }
1830
1831 if (msg_user(msg) == LINK_PROTOCOL) {
1832 link_recv_proto_msg(l_ptr, buf);
1833 head = link_insert_deferred_queue(l_ptr, head);
1834 node_unlock(n_ptr);
1835 continue;
1836 }
1837 msg_dbg(msg,"NSEQ<REC<");
1838 link_state_event(l_ptr, TRAFFIC_MSG_EVT);
1839
1840 if (link_working_working(l_ptr)) {
1841 /* Re-insert in front of queue */
1842 msg_dbg(msg,"RECV-REINS:");
1843 buf->next = head;
1844 head = buf;
1845 node_unlock(n_ptr);
1846 continue;
1847 }
1848 node_unlock(n_ptr);
1849cont:
1850 buf_discard(buf);
1851 }
1852 read_unlock_bh(&net_lock);
1853}
1854
1855/*
1856 * link_defer_buf(): Sort a received out-of-sequence packet
1857 * into the deferred reception queue.
1858 * Returns the increase of the queue length,i.e. 0 or 1
1859 */
1860
1861u32 link_defer_pkt(struct sk_buff **head,
1862 struct sk_buff **tail,
1863 struct sk_buff *buf)
1864{
1865 struct sk_buff *prev = 0;
1866 struct sk_buff *crs = *head;
1867 u32 seq_no = msg_seqno(buf_msg(buf));
1868
1869 buf->next = NULL;
1870
1871 /* Empty queue ? */
1872 if (*head == NULL) {
1873 *head = *tail = buf;
1874 return 1;
1875 }
1876
1877 /* Last ? */
1878 if (less(msg_seqno(buf_msg(*tail)), seq_no)) {
1879 (*tail)->next = buf;
1880 *tail = buf;
1881 return 1;
1882 }
1883
1884 /* Scan through queue and sort it in */
1885 do {
1886 struct tipc_msg *msg = buf_msg(crs);
1887
1888 if (less(seq_no, msg_seqno(msg))) {
1889 buf->next = crs;
1890 if (prev)
1891 prev->next = buf;
1892 else
1893 *head = buf;
1894 return 1;
1895 }
1896 if (seq_no == msg_seqno(msg)) {
1897 break;
1898 }
1899 prev = crs;
1900 crs = crs->next;
1901 }
1902 while (crs);
1903
1904 /* Message is a duplicate of an existing message */
1905
1906 buf_discard(buf);
1907 return 0;
1908}
1909
1910/**
1911 * link_handle_out_of_seq_msg - handle arrival of out-of-sequence packet
1912 */
1913
1914static void link_handle_out_of_seq_msg(struct link *l_ptr,
1915 struct sk_buff *buf)
1916{
1917 u32 seq_no = msg_seqno(buf_msg(buf));
1918
1919 if (likely(msg_user(buf_msg(buf)) == LINK_PROTOCOL)) {
1920 link_recv_proto_msg(l_ptr, buf);
1921 return;
1922 }
1923
1924 dbg("rx OOS msg: seq_no %u, expecting %u (%u)\n",
1925 seq_no, mod(l_ptr->next_in_no), l_ptr->next_in_no);
1926
1927 /* Record OOS packet arrival (force mismatch on next timeout) */
1928
1929 l_ptr->checkpoint--;
1930
1931 /*
1932 * Discard packet if a duplicate; otherwise add it to deferred queue
1933 * and notify peer of gap as per protocol specification
1934 */
1935
1936 if (less(seq_no, mod(l_ptr->next_in_no))) {
1937 l_ptr->stats.duplicates++;
1938 buf_discard(buf);
1939 return;
1940 }
1941
1942 if (link_defer_pkt(&l_ptr->oldest_deferred_in,
1943 &l_ptr->newest_deferred_in, buf)) {
1944 l_ptr->deferred_inqueue_sz++;
1945 l_ptr->stats.deferred_recv++;
1946 if ((l_ptr->deferred_inqueue_sz % 16) == 1)
1947 link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0);
1948 } else
1949 l_ptr->stats.duplicates++;
1950}
1951
1952/*
1953 * Send protocol message to the other endpoint.
1954 */
1955void link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int probe_msg,
1956 u32 gap, u32 tolerance, u32 priority, u32 ack_mtu)
1957{
1958 struct sk_buff *buf = 0;
1959 struct tipc_msg *msg = l_ptr->pmsg;
1960 u32 msg_size = sizeof(l_ptr->proto_msg);
1961
1962 if (link_blocked(l_ptr))
1963 return;
1964 msg_set_type(msg, msg_typ);
1965 msg_set_net_plane(msg, l_ptr->b_ptr->net_plane);
1966 msg_set_bcast_ack(msg, mod(l_ptr->owner->bclink.last_in));
1967 msg_set_last_bcast(msg, bclink_get_last_sent());
1968
1969 if (msg_typ == STATE_MSG) {
1970 u32 next_sent = mod(l_ptr->next_out_no);
1971
1972 if (!link_is_up(l_ptr))
1973 return;
1974 if (l_ptr->next_out)
1975 next_sent = msg_seqno(buf_msg(l_ptr->next_out));
1976 msg_set_next_sent(msg, next_sent);
1977 if (l_ptr->oldest_deferred_in) {
1978 u32 rec = msg_seqno(buf_msg(l_ptr->oldest_deferred_in));
1979 gap = mod(rec - mod(l_ptr->next_in_no));
1980 }
1981 msg_set_seq_gap(msg, gap);
1982 if (gap)
1983 l_ptr->stats.sent_nacks++;
1984 msg_set_link_tolerance(msg, tolerance);
1985 msg_set_linkprio(msg, priority);
1986 msg_set_max_pkt(msg, ack_mtu);
1987 msg_set_ack(msg, mod(l_ptr->next_in_no - 1));
1988 msg_set_probe(msg, probe_msg != 0);
1989 if (probe_msg) {
1990 u32 mtu = l_ptr->max_pkt;
1991
1992 if ((mtu < l_ptr->max_pkt_target) &&
1993 link_working_working(l_ptr) &&
1994 l_ptr->fsm_msg_cnt) {
1995 msg_size = (mtu + (l_ptr->max_pkt_target - mtu)/2 + 2) & ~3;
1996 if (l_ptr->max_pkt_probes == 10) {
1997 l_ptr->max_pkt_target = (msg_size - 4);
1998 l_ptr->max_pkt_probes = 0;
1999 msg_size = (mtu + (l_ptr->max_pkt_target - mtu)/2 + 2) & ~3;
2000 }
2001 l_ptr->max_pkt_probes++;
2002 }
2003
2004 l_ptr->stats.sent_probes++;
2005 }
2006 l_ptr->stats.sent_states++;
2007 } else { /* RESET_MSG or ACTIVATE_MSG */
2008 msg_set_ack(msg, mod(l_ptr->reset_checkpoint - 1));
2009 msg_set_seq_gap(msg, 0);
2010 msg_set_next_sent(msg, 1);
2011 msg_set_link_tolerance(msg, l_ptr->tolerance);
2012 msg_set_linkprio(msg, l_ptr->priority);
2013 msg_set_max_pkt(msg, l_ptr->max_pkt_target);
2014 }
2015
2016 if (node_has_redundant_links(l_ptr->owner)) {
2017 msg_set_redundant_link(msg);
2018 } else {
2019 msg_clear_redundant_link(msg);
2020 }
2021 msg_set_linkprio(msg, l_ptr->priority);
2022
2023 /* Ensure sequence number will not fit : */
2024
2025 msg_set_seqno(msg, mod(l_ptr->next_out_no + (0xffff/2)));
2026
2027 /* Congestion? */
2028
2029 if (bearer_congested(l_ptr->b_ptr, l_ptr)) {
2030 if (!l_ptr->proto_msg_queue) {
2031 l_ptr->proto_msg_queue =
2032 buf_acquire(sizeof(l_ptr->proto_msg));
2033 }
2034 buf = l_ptr->proto_msg_queue;
2035 if (!buf)
2036 return;
2037 memcpy(buf->data, (unchar *)msg, sizeof(l_ptr->proto_msg));
2038 return;
2039 }
2040 msg_set_timestamp(msg, jiffies_to_msecs(jiffies));
2041
2042 /* Message can be sent */
2043
2044 msg_dbg(msg, ">>");
2045
2046 buf = buf_acquire(msg_size);
2047 if (!buf)
2048 return;
2049
2050 memcpy(buf->data, (unchar *)msg, sizeof(l_ptr->proto_msg));
2051 msg_set_size(buf_msg(buf), msg_size);
2052
2053 if (bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
2054 l_ptr->unacked_window = 0;
2055 buf_discard(buf);
2056 return;
2057 }
2058
2059 /* New congestion */
2060 bearer_schedule(l_ptr->b_ptr, l_ptr);
2061 l_ptr->proto_msg_queue = buf;
2062 l_ptr->stats.bearer_congs++;
2063}
2064
2065/*
2066 * Receive protocol message :
2067 * Note that network plane id propagates through the network, and may
2068 * change at any time. The node with lowest address rules
2069 */
2070
2071static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf)
2072{
2073 u32 rec_gap = 0;
2074 u32 max_pkt_info;
2075 u32 max_pkt_ack;
2076 u32 msg_tol;
2077 struct tipc_msg *msg = buf_msg(buf);
2078
2079 dbg("AT(%u):", jiffies_to_msecs(jiffies));
2080 msg_dbg(msg, "<<");
2081 if (link_blocked(l_ptr))
2082 goto exit;
2083
2084 /* record unnumbered packet arrival (force mismatch on next timeout) */
2085
2086 l_ptr->checkpoint--;
2087
2088 if (l_ptr->b_ptr->net_plane != msg_net_plane(msg))
2089 if (tipc_own_addr > msg_prevnode(msg))
2090 l_ptr->b_ptr->net_plane = msg_net_plane(msg);
2091
2092 l_ptr->owner->permit_changeover = msg_redundant_link(msg);
2093
2094 switch (msg_type(msg)) {
2095
2096 case RESET_MSG:
2097 if (!link_working_unknown(l_ptr) && l_ptr->peer_session) {
2098 if (msg_session(msg) == l_ptr->peer_session) {
2099 dbg("Duplicate RESET: %u<->%u\n",
2100 msg_session(msg), l_ptr->peer_session);
2101 break; /* duplicate: ignore */
2102 }
2103 }
2104 /* fall thru' */
2105 case ACTIVATE_MSG:
2106 /* Update link settings according other endpoint's values */
2107
2108 strcpy((strrchr(l_ptr->name, ':') + 1), (char *)msg_data(msg));
2109
2110 if ((msg_tol = msg_link_tolerance(msg)) &&
2111 (msg_tol > l_ptr->tolerance))
2112 link_set_supervision_props(l_ptr, msg_tol);
2113
2114 if (msg_linkprio(msg) > l_ptr->priority)
2115 l_ptr->priority = msg_linkprio(msg);
2116
2117 max_pkt_info = msg_max_pkt(msg);
2118 if (max_pkt_info) {
2119 if (max_pkt_info < l_ptr->max_pkt_target)
2120 l_ptr->max_pkt_target = max_pkt_info;
2121 if (l_ptr->max_pkt > l_ptr->max_pkt_target)
2122 l_ptr->max_pkt = l_ptr->max_pkt_target;
2123 } else {
2124 l_ptr->max_pkt = l_ptr->max_pkt_target;
2125 }
2126 l_ptr->owner->bclink.supported = (max_pkt_info != 0);
2127
2128 link_state_event(l_ptr, msg_type(msg));
2129
2130 l_ptr->peer_session = msg_session(msg);
2131 l_ptr->peer_bearer_id = msg_bearer_id(msg);
2132
2133 /* Synchronize broadcast sequence numbers */
2134 if (!node_has_redundant_links(l_ptr->owner)) {
2135 l_ptr->owner->bclink.last_in = mod(msg_last_bcast(msg));
2136 }
2137 break;
2138 case STATE_MSG:
2139
2140 if ((msg_tol = msg_link_tolerance(msg)))
2141 link_set_supervision_props(l_ptr, msg_tol);
2142
2143 if (msg_linkprio(msg) &&
2144 (msg_linkprio(msg) != l_ptr->priority)) {
2145 warn("Changing prio <%s>: %u->%u\n",
2146 l_ptr->name, l_ptr->priority, msg_linkprio(msg));
2147 l_ptr->priority = msg_linkprio(msg);
2148 link_reset(l_ptr); /* Enforce change to take effect */
2149 break;
2150 }
2151 link_state_event(l_ptr, TRAFFIC_MSG_EVT);
2152 l_ptr->stats.recv_states++;
2153 if (link_reset_unknown(l_ptr))
2154 break;
2155
2156 if (less_eq(mod(l_ptr->next_in_no), msg_next_sent(msg))) {
2157 rec_gap = mod(msg_next_sent(msg) -
2158 mod(l_ptr->next_in_no));
2159 }
2160
2161 max_pkt_ack = msg_max_pkt(msg);
2162 if (max_pkt_ack > l_ptr->max_pkt) {
2163 dbg("Link <%s> updated MTU %u -> %u\n",
2164 l_ptr->name, l_ptr->max_pkt, max_pkt_ack);
2165 l_ptr->max_pkt = max_pkt_ack;
2166 l_ptr->max_pkt_probes = 0;
2167 }
2168
2169 max_pkt_ack = 0;
2170 if (msg_probe(msg)) {
2171 l_ptr->stats.recv_probes++;
2172 if (msg_size(msg) > sizeof(l_ptr->proto_msg)) {
2173 max_pkt_ack = msg_size(msg);
2174 }
2175 }
2176
2177 /* Protocol message before retransmits, reduce loss risk */
2178
2179 bclink_check_gap(l_ptr->owner, msg_last_bcast(msg));
2180
2181 if (rec_gap || (msg_probe(msg))) {
2182 link_send_proto_msg(l_ptr, STATE_MSG,
2183 0, rec_gap, 0, 0, max_pkt_ack);
2184 }
2185 if (msg_seq_gap(msg)) {
2186 msg_dbg(msg, "With Gap:");
2187 l_ptr->stats.recv_nacks++;
2188 link_retransmit(l_ptr, l_ptr->first_out,
2189 msg_seq_gap(msg));
2190 }
2191 break;
2192 default:
2193 msg_dbg(buf_msg(buf), "<DISCARDING UNKNOWN<");
2194 }
2195exit:
2196 buf_discard(buf);
2197}
2198
2199
2200/*
2201 * link_tunnel(): Send one message via a link belonging to
2202 * another bearer. Owner node is locked.
2203 */
2204void link_tunnel(struct link *l_ptr,
2205 struct tipc_msg *tunnel_hdr,
2206 struct tipc_msg *msg,
2207 u32 selector)
2208{
2209 struct link *tunnel;
2210 struct sk_buff *buf;
2211 u32 length = msg_size(msg);
2212
2213 tunnel = l_ptr->owner->active_links[selector & 1];
2214 if (!link_is_up(tunnel))
2215 return;
2216 msg_set_size(tunnel_hdr, length + INT_H_SIZE);
2217 buf = buf_acquire(length + INT_H_SIZE);
2218 if (!buf)
2219 return;
2220 memcpy(buf->data, (unchar *)tunnel_hdr, INT_H_SIZE);
2221 memcpy(buf->data + INT_H_SIZE, (unchar *)msg, length);
2222 dbg("%c->%c:", l_ptr->b_ptr->net_plane, tunnel->b_ptr->net_plane);
2223 msg_dbg(buf_msg(buf), ">SEND>");
2224 assert(tunnel);
2225 link_send_buf(tunnel, buf);
2226}
2227
2228
2229
2230/*
2231 * changeover(): Send whole message queue via the remaining link
2232 * Owner node is locked.
2233 */
2234
2235void link_changeover(struct link *l_ptr)
2236{
2237 u32 msgcount = l_ptr->out_queue_size;
2238 struct sk_buff *crs = l_ptr->first_out;
2239 struct link *tunnel = l_ptr->owner->active_links[0];
2240 int split_bundles = node_has_redundant_links(l_ptr->owner);
2241 struct tipc_msg tunnel_hdr;
2242
2243 if (!tunnel)
2244 return;
2245
2246 if (!l_ptr->owner->permit_changeover)
2247 return;
2248
2249 msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL,
2250 ORIGINAL_MSG, TIPC_OK, INT_H_SIZE, l_ptr->addr);
2251 msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id);
2252 msg_set_msgcnt(&tunnel_hdr, msgcount);
2253 if (!l_ptr->first_out) {
2254 struct sk_buff *buf;
2255
2256 assert(!msgcount);
2257 buf = buf_acquire(INT_H_SIZE);
2258 if (buf) {
2259 memcpy(buf->data, (unchar *)&tunnel_hdr, INT_H_SIZE);
2260 msg_set_size(&tunnel_hdr, INT_H_SIZE);
2261 dbg("%c->%c:", l_ptr->b_ptr->net_plane,
2262 tunnel->b_ptr->net_plane);
2263 msg_dbg(&tunnel_hdr, "EMPTY>SEND>");
2264 link_send_buf(tunnel, buf);
2265 } else {
2266 warn("Memory squeeze; link changeover failed\n");
2267 }
2268 return;
2269 }
2270 while (crs) {
2271 struct tipc_msg *msg = buf_msg(crs);
2272
2273 if ((msg_user(msg) == MSG_BUNDLER) && split_bundles) {
2274 u32 msgcount = msg_msgcnt(msg);
2275 struct tipc_msg *m = msg_get_wrapped(msg);
2276 unchar* pos = (unchar*)m;
2277
2278 while (msgcount--) {
2279 msg_set_seqno(m,msg_seqno(msg));
2280 link_tunnel(l_ptr, &tunnel_hdr, m,
2281 msg_link_selector(m));
2282 pos += align(msg_size(m));
2283 m = (struct tipc_msg *)pos;
2284 }
2285 } else {
2286 link_tunnel(l_ptr, &tunnel_hdr, msg,
2287 msg_link_selector(msg));
2288 }
2289 crs = crs->next;
2290 }
2291}
2292
2293void link_send_duplicate(struct link *l_ptr, struct link *tunnel)
2294{
2295 struct sk_buff *iter;
2296 struct tipc_msg tunnel_hdr;
2297
2298 msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL,
2299 DUPLICATE_MSG, TIPC_OK, INT_H_SIZE, l_ptr->addr);
2300 msg_set_msgcnt(&tunnel_hdr, l_ptr->out_queue_size);
2301 msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id);
2302 iter = l_ptr->first_out;
2303 while (iter) {
2304 struct sk_buff *outbuf;
2305 struct tipc_msg *msg = buf_msg(iter);
2306 u32 length = msg_size(msg);
2307
2308 if (msg_user(msg) == MSG_BUNDLER)
2309 msg_set_type(msg, CLOSED_MSG);
2310 msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); /* Update */
2311 msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in);
2312 msg_set_size(&tunnel_hdr, length + INT_H_SIZE);
2313 outbuf = buf_acquire(length + INT_H_SIZE);
2314 if (outbuf == NULL) {
2315 warn("Memory squeeze; buffer duplication failed\n");
2316 return;
2317 }
2318 memcpy(outbuf->data, (unchar *)&tunnel_hdr, INT_H_SIZE);
2319 memcpy(outbuf->data + INT_H_SIZE, iter->data, length);
2320 dbg("%c->%c:", l_ptr->b_ptr->net_plane,
2321 tunnel->b_ptr->net_plane);
2322 msg_dbg(buf_msg(outbuf), ">SEND>");
2323 link_send_buf(tunnel, outbuf);
2324 if (!link_is_up(l_ptr))
2325 return;
2326 iter = iter->next;
2327 }
2328}
2329
2330
2331
2332/**
2333 * buf_extract - extracts embedded TIPC message from another message
2334 * @skb: encapsulating message buffer
2335 * @from_pos: offset to extract from
2336 *
2337 * Returns a new message buffer containing an embedded message. The
2338 * encapsulating message itself is left unchanged.
2339 */
2340
2341static struct sk_buff *buf_extract(struct sk_buff *skb, u32 from_pos)
2342{
2343 struct tipc_msg *msg = (struct tipc_msg *)(skb->data + from_pos);
2344 u32 size = msg_size(msg);
2345 struct sk_buff *eb;
2346
2347 eb = buf_acquire(size);
2348 if (eb)
2349 memcpy(eb->data, (unchar *)msg, size);
2350 return eb;
2351}
2352
2353/*
2354 * link_recv_changeover_msg(): Receive tunneled packet sent
2355 * via other link. Node is locked. Return extracted buffer.
2356 */
2357
2358static int link_recv_changeover_msg(struct link **l_ptr,
2359 struct sk_buff **buf)
2360{
2361 struct sk_buff *tunnel_buf = *buf;
2362 struct link *dest_link;
2363 struct tipc_msg *msg;
2364 struct tipc_msg *tunnel_msg = buf_msg(tunnel_buf);
2365 u32 msg_typ = msg_type(tunnel_msg);
2366 u32 msg_count = msg_msgcnt(tunnel_msg);
2367
2368 dest_link = (*l_ptr)->owner->links[msg_bearer_id(tunnel_msg)];
2369 assert(dest_link != *l_ptr);
2370 if (!dest_link) {
2371 msg_dbg(tunnel_msg, "NOLINK/<REC<");
2372 goto exit;
2373 }
2374 dbg("%c<-%c:", dest_link->b_ptr->net_plane,
2375 (*l_ptr)->b_ptr->net_plane);
2376 *l_ptr = dest_link;
2377 msg = msg_get_wrapped(tunnel_msg);
2378
2379 if (msg_typ == DUPLICATE_MSG) {
2380 if (less(msg_seqno(msg), mod(dest_link->next_in_no))) {
2381 msg_dbg(tunnel_msg, "DROP/<REC<");
2382 goto exit;
2383 }
2384 *buf = buf_extract(tunnel_buf,INT_H_SIZE);
2385 if (*buf == NULL) {
2386 warn("Memory squeeze; failed to extract msg\n");
2387 goto exit;
2388 }
2389 msg_dbg(tunnel_msg, "TNL<REC<");
2390 buf_discard(tunnel_buf);
2391 return 1;
2392 }
2393
2394 /* First original message ?: */
2395
2396 if (link_is_up(dest_link)) {
2397 msg_dbg(tunnel_msg, "UP/FIRST/<REC<");
2398 link_reset(dest_link);
2399 dest_link->exp_msg_count = msg_count;
2400 if (!msg_count)
2401 goto exit;
2402 } else if (dest_link->exp_msg_count == START_CHANGEOVER) {
2403 msg_dbg(tunnel_msg, "BLK/FIRST/<REC<");
2404 dest_link->exp_msg_count = msg_count;
2405 if (!msg_count)
2406 goto exit;
2407 }
2408
2409 /* Receive original message */
2410
2411 if (dest_link->exp_msg_count == 0) {
2412 msg_dbg(tunnel_msg, "OVERDUE/DROP/<REC<");
2413 dbg_print_link(dest_link, "LINK:");
2414 goto exit;
2415 }
2416 dest_link->exp_msg_count--;
2417 if (less(msg_seqno(msg), dest_link->reset_checkpoint)) {
2418 msg_dbg(tunnel_msg, "DROP/DUPL/<REC<");
2419 goto exit;
2420 } else {
2421 *buf = buf_extract(tunnel_buf, INT_H_SIZE);
2422 if (*buf != NULL) {
2423 msg_dbg(tunnel_msg, "TNL<REC<");
2424 buf_discard(tunnel_buf);
2425 return 1;
2426 } else {
2427 warn("Memory squeeze; dropped incoming msg\n");
2428 }
2429 }
2430exit:
2431 *buf = 0;
2432 buf_discard(tunnel_buf);
2433 return 0;
2434}
2435
2436/*
2437 * Bundler functionality:
2438 */
2439void link_recv_bundle(struct sk_buff *buf)
2440{
2441 u32 msgcount = msg_msgcnt(buf_msg(buf));
2442 u32 pos = INT_H_SIZE;
2443 struct sk_buff *obuf;
2444
2445 msg_dbg(buf_msg(buf), "<BNDL<: ");
2446 while (msgcount--) {
2447 obuf = buf_extract(buf, pos);
2448 if (obuf == NULL) {
2449 char addr_string[16];
2450
2451 warn("Buffer allocation failure;\n");
2452 warn(" incoming message(s) from %s lost\n",
2453 addr_string_fill(addr_string,
2454 msg_orignode(buf_msg(buf))));
2455 return;
2456 };
2457 pos += align(msg_size(buf_msg(obuf)));
2458 msg_dbg(buf_msg(obuf), " /");
2459 net_route_msg(obuf);
2460 }
2461 buf_discard(buf);
2462}
2463
2464/*
2465 * Fragmentation/defragmentation:
2466 */
2467
2468
2469/*
2470 * link_send_long_buf: Entry for buffers needing fragmentation.
2471 * The buffer is complete, inclusive total message length.
2472 * Returns user data length.
2473 */
2474int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf)
2475{
2476 struct tipc_msg *inmsg = buf_msg(buf);
2477 struct tipc_msg fragm_hdr;
2478 u32 insize = msg_size(inmsg);
2479 u32 dsz = msg_data_sz(inmsg);
2480 unchar *crs = buf->data;
2481 u32 rest = insize;
2482 u32 pack_sz = link_max_pkt(l_ptr);
2483 u32 fragm_sz = pack_sz - INT_H_SIZE;
2484 u32 fragm_no = 1;
2485 u32 destaddr = msg_destnode(inmsg);
2486
2487 if (msg_short(inmsg))
2488 destaddr = l_ptr->addr;
2489
2490 if (msg_routed(inmsg))
2491 msg_set_prevnode(inmsg, tipc_own_addr);
2492
2493 /* Prepare reusable fragment header: */
2494
2495 msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT,
2496 TIPC_OK, INT_H_SIZE, destaddr);
2497 msg_set_link_selector(&fragm_hdr, msg_link_selector(inmsg));
2498 msg_set_long_msgno(&fragm_hdr, mod(l_ptr->long_msg_seq_no++));
2499 msg_set_fragm_no(&fragm_hdr, fragm_no);
2500 l_ptr->stats.sent_fragmented++;
2501
2502 /* Chop up message: */
2503
2504 while (rest > 0) {
2505 struct sk_buff *fragm;
2506
2507 if (rest <= fragm_sz) {
2508 fragm_sz = rest;
2509 msg_set_type(&fragm_hdr, LAST_FRAGMENT);
2510 }
2511 fragm = buf_acquire(fragm_sz + INT_H_SIZE);
2512 if (fragm == NULL) {
2513 warn("Memory squeeze; failed to fragment msg\n");
2514 dsz = -ENOMEM;
2515 goto exit;
2516 }
2517 msg_set_size(&fragm_hdr, fragm_sz + INT_H_SIZE);
2518 memcpy(fragm->data, (unchar *)&fragm_hdr, INT_H_SIZE);
2519 memcpy(fragm->data + INT_H_SIZE, crs, fragm_sz);
2520
2521 /* Send queued messages first, if any: */
2522
2523 l_ptr->stats.sent_fragments++;
2524 link_send_buf(l_ptr, fragm);
2525 if (!link_is_up(l_ptr))
2526 return dsz;
2527 msg_set_fragm_no(&fragm_hdr, ++fragm_no);
2528 rest -= fragm_sz;
2529 crs += fragm_sz;
2530 msg_set_type(&fragm_hdr, FRAGMENT);
2531 }
2532exit:
2533 buf_discard(buf);
2534 return dsz;
2535}
2536
2537/*
2538 * A pending message being re-assembled must store certain values
2539 * to handle subsequent fragments correctly. The following functions
2540 * help storing these values in unused, available fields in the
2541 * pending message. This makes dynamic memory allocation unecessary.
2542 */
2543
2544static inline u32 get_long_msg_seqno(struct sk_buff *buf)
2545{
2546 return msg_seqno(buf_msg(buf));
2547}
2548
2549static inline void set_long_msg_seqno(struct sk_buff *buf, u32 seqno)
2550{
2551 msg_set_seqno(buf_msg(buf), seqno);
2552}
2553
2554static inline u32 get_fragm_size(struct sk_buff *buf)
2555{
2556 return msg_ack(buf_msg(buf));
2557}
2558
2559static inline void set_fragm_size(struct sk_buff *buf, u32 sz)
2560{
2561 msg_set_ack(buf_msg(buf), sz);
2562}
2563
2564static inline u32 get_expected_frags(struct sk_buff *buf)
2565{
2566 return msg_bcast_ack(buf_msg(buf));
2567}
2568
2569static inline void set_expected_frags(struct sk_buff *buf, u32 exp)
2570{
2571 msg_set_bcast_ack(buf_msg(buf), exp);
2572}
2573
2574static inline u32 get_timer_cnt(struct sk_buff *buf)
2575{
2576 return msg_reroute_cnt(buf_msg(buf));
2577}
2578
2579static inline void incr_timer_cnt(struct sk_buff *buf)
2580{
2581 msg_incr_reroute_cnt(buf_msg(buf));
2582}
2583
2584/*
2585 * link_recv_fragment(): Called with node lock on. Returns
2586 * the reassembled buffer if message is complete.
2587 */
2588int link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb,
2589 struct tipc_msg **m)
2590{
2591 struct sk_buff *prev = 0;
2592 struct sk_buff *fbuf = *fb;
2593 struct tipc_msg *fragm = buf_msg(fbuf);
2594 struct sk_buff *pbuf = *pending;
2595 u32 long_msg_seq_no = msg_long_msgno(fragm);
2596
2597 *fb = 0;
2598 msg_dbg(fragm,"FRG<REC<");
2599
2600 /* Is there an incomplete message waiting for this fragment? */
2601
2602 while (pbuf && ((msg_seqno(buf_msg(pbuf)) != long_msg_seq_no)
2603 || (msg_orignode(fragm) != msg_orignode(buf_msg(pbuf))))) {
2604 prev = pbuf;
2605 pbuf = pbuf->next;
2606 }
2607
2608 if (!pbuf && (msg_type(fragm) == FIRST_FRAGMENT)) {
2609 struct tipc_msg *imsg = (struct tipc_msg *)msg_data(fragm);
2610 u32 msg_sz = msg_size(imsg);
2611 u32 fragm_sz = msg_data_sz(fragm);
2612 u32 exp_fragm_cnt = msg_sz/fragm_sz + !!(msg_sz % fragm_sz);
2613 u32 max = TIPC_MAX_USER_MSG_SIZE + LONG_H_SIZE;
2614 if (msg_type(imsg) == TIPC_MCAST_MSG)
2615 max = TIPC_MAX_USER_MSG_SIZE + MCAST_H_SIZE;
2616 if (msg_size(imsg) > max) {
2617 msg_dbg(fragm,"<REC<Oversized: ");
2618 buf_discard(fbuf);
2619 return 0;
2620 }
2621 pbuf = buf_acquire(msg_size(imsg));
2622 if (pbuf != NULL) {
2623 pbuf->next = *pending;
2624 *pending = pbuf;
2625 memcpy(pbuf->data, (unchar *)imsg, msg_data_sz(fragm));
2626
2627 /* Prepare buffer for subsequent fragments. */
2628
2629 set_long_msg_seqno(pbuf, long_msg_seq_no);
2630 set_fragm_size(pbuf,fragm_sz);
2631 set_expected_frags(pbuf,exp_fragm_cnt - 1);
2632 } else {
2633 warn("Memory squeeze; got no defragmenting buffer\n");
2634 }
2635 buf_discard(fbuf);
2636 return 0;
2637 } else if (pbuf && (msg_type(fragm) != FIRST_FRAGMENT)) {
2638 u32 dsz = msg_data_sz(fragm);
2639 u32 fsz = get_fragm_size(pbuf);
2640 u32 crs = ((msg_fragm_no(fragm) - 1) * fsz);
2641 u32 exp_frags = get_expected_frags(pbuf) - 1;
2642 memcpy(pbuf->data + crs, msg_data(fragm), dsz);
2643 buf_discard(fbuf);
2644
2645 /* Is message complete? */
2646
2647 if (exp_frags == 0) {
2648 if (prev)
2649 prev->next = pbuf->next;
2650 else
2651 *pending = pbuf->next;
2652 msg_reset_reroute_cnt(buf_msg(pbuf));
2653 *fb = pbuf;
2654 *m = buf_msg(pbuf);
2655 return 1;
2656 }
2657 set_expected_frags(pbuf,exp_frags);
2658 return 0;
2659 }
2660 dbg(" Discarding orphan fragment %x\n",fbuf);
2661 msg_dbg(fragm,"ORPHAN:");
2662 dbg("Pending long buffers:\n");
2663 dbg_print_buf_chain(*pending);
2664 buf_discard(fbuf);
2665 return 0;
2666}
2667
2668/**
2669 * link_check_defragm_bufs - flush stale incoming message fragments
2670 * @l_ptr: pointer to link
2671 */
2672
2673static void link_check_defragm_bufs(struct link *l_ptr)
2674{
2675 struct sk_buff *prev = 0;
2676 struct sk_buff *next = 0;
2677 struct sk_buff *buf = l_ptr->defragm_buf;
2678
2679 if (!buf)
2680 return;
2681 if (!link_working_working(l_ptr))
2682 return;
2683 while (buf) {
2684 u32 cnt = get_timer_cnt(buf);
2685
2686 next = buf->next;
2687 if (cnt < 4) {
2688 incr_timer_cnt(buf);
2689 prev = buf;
2690 } else {
2691 dbg(" Discarding incomplete long buffer\n");
2692 msg_dbg(buf_msg(buf), "LONG:");
2693 dbg_print_link(l_ptr, "curr:");
2694 dbg("Pending long buffers:\n");
2695 dbg_print_buf_chain(l_ptr->defragm_buf);
2696 if (prev)
2697 prev->next = buf->next;
2698 else
2699 l_ptr->defragm_buf = buf->next;
2700 buf_discard(buf);
2701 }
2702 buf = next;
2703 }
2704}
2705
2706
2707
2708static void link_set_supervision_props(struct link *l_ptr, u32 tolerance)
2709{
2710 l_ptr->tolerance = tolerance;
2711 l_ptr->continuity_interval =
2712 ((tolerance / 4) > 500) ? 500 : tolerance / 4;
2713 l_ptr->abort_limit = tolerance / (l_ptr->continuity_interval / 4);
2714}
2715
2716
2717void link_set_queue_limits(struct link *l_ptr, u32 window)
2718{
2719 /* Data messages from this node, inclusive FIRST_FRAGM */
2720 l_ptr->queue_limit[DATA_LOW] = window;
2721 l_ptr->queue_limit[DATA_MEDIUM] = (window / 3) * 4;
2722 l_ptr->queue_limit[DATA_HIGH] = (window / 3) * 5;
2723 l_ptr->queue_limit[DATA_CRITICAL] = (window / 3) * 6;
2724 /* Transiting data messages,inclusive FIRST_FRAGM */
2725 l_ptr->queue_limit[DATA_LOW + 4] = 300;
2726 l_ptr->queue_limit[DATA_MEDIUM + 4] = 600;
2727 l_ptr->queue_limit[DATA_HIGH + 4] = 900;
2728 l_ptr->queue_limit[DATA_CRITICAL + 4] = 1200;
2729 l_ptr->queue_limit[CONN_MANAGER] = 1200;
2730 l_ptr->queue_limit[ROUTE_DISTRIBUTOR] = 1200;
2731 l_ptr->queue_limit[CHANGEOVER_PROTOCOL] = 2500;
2732 l_ptr->queue_limit[NAME_DISTRIBUTOR] = 3000;
2733 /* FRAGMENT and LAST_FRAGMENT packets */
2734 l_ptr->queue_limit[MSG_FRAGMENTER] = 4000;
2735}
2736
2737/**
2738 * link_find_link - locate link by name
2739 * @name - ptr to link name string
2740 * @node - ptr to area to be filled with ptr to associated node
2741 *
2742 * Caller must hold 'net_lock' to ensure node and bearer are not deleted;
2743 * this also prevents link deletion.
2744 *
2745 * Returns pointer to link (or 0 if invalid link name).
2746 */
2747
2748static struct link *link_find_link(const char *name, struct node **node)
2749{
2750 struct link_name link_name_parts;
2751 struct bearer *b_ptr;
2752 struct link *l_ptr;
2753
2754 if (!link_name_validate(name, &link_name_parts))
2755 return 0;
2756
2757 b_ptr = bearer_find_interface(link_name_parts.if_local);
2758 if (!b_ptr)
2759 return 0;
2760
2761 *node = node_find(link_name_parts.addr_peer);
2762 if (!*node)
2763 return 0;
2764
2765 l_ptr = (*node)->links[b_ptr->identity];
2766 if (!l_ptr || strcmp(l_ptr->name, name))
2767 return 0;
2768
2769 return l_ptr;
2770}
2771
2772struct sk_buff *link_cmd_config(const void *req_tlv_area, int req_tlv_space,
2773 u16 cmd)
2774{
2775 struct tipc_link_config *args;
2776 u32 new_value;
2777 struct link *l_ptr;
2778 struct node *node;
2779 int res;
2780
2781 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_CONFIG))
2782 return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
2783
2784 args = (struct tipc_link_config *)TLV_DATA(req_tlv_area);
2785 new_value = ntohl(args->value);
2786
2787 if (!strcmp(args->name, bc_link_name)) {
2788 if ((cmd == TIPC_CMD_SET_LINK_WINDOW) &&
2789 (bclink_set_queue_limits(new_value) == 0))
2790 return cfg_reply_none();
2791 return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
2792 " (cannot change setting on broadcast link)");
2793 }
2794
2795 read_lock_bh(&net_lock);
2796 l_ptr = link_find_link(args->name, &node);
2797 if (!l_ptr) {
2798 read_unlock_bh(&net_lock);
2799 return cfg_reply_error_string("link not found");
2800 }
2801
2802 node_lock(node);
2803 res = -EINVAL;
2804 switch (cmd) {
2805 case TIPC_CMD_SET_LINK_TOL:
2806 if ((new_value >= TIPC_MIN_LINK_TOL) &&
2807 (new_value <= TIPC_MAX_LINK_TOL)) {
2808 link_set_supervision_props(l_ptr, new_value);
2809 link_send_proto_msg(l_ptr, STATE_MSG,
2810 0, 0, new_value, 0, 0);
2811 res = TIPC_OK;
2812 }
2813 break;
2814 case TIPC_CMD_SET_LINK_PRI:
2815 if (new_value < TIPC_NUM_LINK_PRI) {
2816 l_ptr->priority = new_value;
2817 link_send_proto_msg(l_ptr, STATE_MSG,
2818 0, 0, 0, new_value, 0);
2819 res = TIPC_OK;
2820 }
2821 break;
2822 case TIPC_CMD_SET_LINK_WINDOW:
2823 if ((new_value >= TIPC_MIN_LINK_WIN) &&
2824 (new_value <= TIPC_MAX_LINK_WIN)) {
2825 link_set_queue_limits(l_ptr, new_value);
2826 res = TIPC_OK;
2827 }
2828 break;
2829 }
2830 node_unlock(node);
2831
2832 read_unlock_bh(&net_lock);
2833 if (res)
2834 return cfg_reply_error_string("cannot change link setting");
2835
2836 return cfg_reply_none();
2837}
2838
2839/**
2840 * link_reset_statistics - reset link statistics
2841 * @l_ptr: pointer to link
2842 */
2843
2844static void link_reset_statistics(struct link *l_ptr)
2845{
2846 memset(&l_ptr->stats, 0, sizeof(l_ptr->stats));
2847 l_ptr->stats.sent_info = l_ptr->next_out_no;
2848 l_ptr->stats.recv_info = l_ptr->next_in_no;
2849}
2850
2851struct sk_buff *link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_space)
2852{
2853 char *link_name;
2854 struct link *l_ptr;
2855 struct node *node;
2856
2857 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME))
2858 return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
2859
2860 link_name = (char *)TLV_DATA(req_tlv_area);
2861 if (!strcmp(link_name, bc_link_name)) {
2862 if (bclink_reset_stats())
2863 return cfg_reply_error_string("link not found");
2864 return cfg_reply_none();
2865 }
2866
2867 read_lock_bh(&net_lock);
2868 l_ptr = link_find_link(link_name, &node);
2869 if (!l_ptr) {
2870 read_unlock_bh(&net_lock);
2871 return cfg_reply_error_string("link not found");
2872 }
2873
2874 node_lock(node);
2875 link_reset_statistics(l_ptr);
2876 node_unlock(node);
2877 read_unlock_bh(&net_lock);
2878 return cfg_reply_none();
2879}
2880
2881/**
2882 * percent - convert count to a percentage of total (rounding up or down)
2883 */
2884
2885static u32 percent(u32 count, u32 total)
2886{
2887 return (count * 100 + (total / 2)) / total;
2888}
2889
2890/**
2891 * link_stats - print link statistics
2892 * @name: link name
2893 * @buf: print buffer area
2894 * @buf_size: size of print buffer area
2895 *
2896 * Returns length of print buffer data string (or 0 if error)
2897 */
2898
2899static int link_stats(const char *name, char *buf, const u32 buf_size)
2900{
2901 struct print_buf pb;
2902 struct link *l_ptr;
2903 struct node *node;
2904 char *status;
2905 u32 profile_total = 0;
2906
2907 if (!strcmp(name, bc_link_name))
2908 return bclink_stats(buf, buf_size);
2909
2910 printbuf_init(&pb, buf, buf_size);
2911
2912 read_lock_bh(&net_lock);
2913 l_ptr = link_find_link(name, &node);
2914 if (!l_ptr) {
2915 read_unlock_bh(&net_lock);
2916 return 0;
2917 }
2918 node_lock(node);
2919
2920 if (link_is_active(l_ptr))
2921 status = "ACTIVE";
2922 else if (link_is_up(l_ptr))
2923 status = "STANDBY";
2924 else
2925 status = "DEFUNCT";
2926 tipc_printf(&pb, "Link <%s>\n"
2927 " %s MTU:%u Priority:%u Tolerance:%u ms"
2928 " Window:%u packets\n",
2929 l_ptr->name, status, link_max_pkt(l_ptr),
2930 l_ptr->priority, l_ptr->tolerance, l_ptr->queue_limit[0]);
2931 tipc_printf(&pb, " RX packets:%u fragments:%u/%u bundles:%u/%u\n",
2932 l_ptr->next_in_no - l_ptr->stats.recv_info,
2933 l_ptr->stats.recv_fragments,
2934 l_ptr->stats.recv_fragmented,
2935 l_ptr->stats.recv_bundles,
2936 l_ptr->stats.recv_bundled);
2937 tipc_printf(&pb, " TX packets:%u fragments:%u/%u bundles:%u/%u\n",
2938 l_ptr->next_out_no - l_ptr->stats.sent_info,
2939 l_ptr->stats.sent_fragments,
2940 l_ptr->stats.sent_fragmented,
2941 l_ptr->stats.sent_bundles,
2942 l_ptr->stats.sent_bundled);
2943 profile_total = l_ptr->stats.msg_length_counts;
2944 if (!profile_total)
2945 profile_total = 1;
2946 tipc_printf(&pb, " TX profile sample:%u packets average:%u octets\n"
2947 " 0-64:%u%% -256:%u%% -1024:%u%% -4096:%u%% "
2948 "-16354:%u%% -32768:%u%% -66000:%u%%\n",
2949 l_ptr->stats.msg_length_counts,
2950 l_ptr->stats.msg_lengths_total / profile_total,
2951 percent(l_ptr->stats.msg_length_profile[0], profile_total),
2952 percent(l_ptr->stats.msg_length_profile[1], profile_total),
2953 percent(l_ptr->stats.msg_length_profile[2], profile_total),
2954 percent(l_ptr->stats.msg_length_profile[3], profile_total),
2955 percent(l_ptr->stats.msg_length_profile[4], profile_total),
2956 percent(l_ptr->stats.msg_length_profile[5], profile_total),
2957 percent(l_ptr->stats.msg_length_profile[6], profile_total));
2958 tipc_printf(&pb, " RX states:%u probes:%u naks:%u defs:%u dups:%u\n",
2959 l_ptr->stats.recv_states,
2960 l_ptr->stats.recv_probes,
2961 l_ptr->stats.recv_nacks,
2962 l_ptr->stats.deferred_recv,
2963 l_ptr->stats.duplicates);
2964 tipc_printf(&pb, " TX states:%u probes:%u naks:%u acks:%u dups:%u\n",
2965 l_ptr->stats.sent_states,
2966 l_ptr->stats.sent_probes,
2967 l_ptr->stats.sent_nacks,
2968 l_ptr->stats.sent_acks,
2969 l_ptr->stats.retransmitted);
2970 tipc_printf(&pb, " Congestion bearer:%u link:%u Send queue max:%u avg:%u\n",
2971 l_ptr->stats.bearer_congs,
2972 l_ptr->stats.link_congs,
2973 l_ptr->stats.max_queue_sz,
2974 l_ptr->stats.queue_sz_counts
2975 ? (l_ptr->stats.accu_queue_sz / l_ptr->stats.queue_sz_counts)
2976 : 0);
2977
2978 node_unlock(node);
2979 read_unlock_bh(&net_lock);
2980 return printbuf_validate(&pb);
2981}
2982
2983#define MAX_LINK_STATS_INFO 2000
2984
2985struct sk_buff *link_cmd_show_stats(const void *req_tlv_area, int req_tlv_space)
2986{
2987 struct sk_buff *buf;
2988 struct tlv_desc *rep_tlv;
2989 int str_len;
2990
2991 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME))
2992 return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
2993
2994 buf = cfg_reply_alloc(TLV_SPACE(MAX_LINK_STATS_INFO));
2995 if (!buf)
2996 return NULL;
2997
2998 rep_tlv = (struct tlv_desc *)buf->data;
2999
3000 str_len = link_stats((char *)TLV_DATA(req_tlv_area),
3001 (char *)TLV_DATA(rep_tlv), MAX_LINK_STATS_INFO);
3002 if (!str_len) {
3003 buf_discard(buf);
3004 return cfg_reply_error_string("link not found");
3005 }
3006
3007 skb_put(buf, TLV_SPACE(str_len));
3008 TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
3009
3010 return buf;
3011}
3012
3013#if 0
3014int link_control(const char *name, u32 op, u32 val)
3015{
3016 int res = -EINVAL;
3017 struct link *l_ptr;
3018 u32 bearer_id;
3019 struct node * node;
3020 u32 a;
3021
3022 a = link_name2addr(name, &bearer_id);
3023 read_lock_bh(&net_lock);
3024 node = node_find(a);
3025 if (node) {
3026 node_lock(node);
3027 l_ptr = node->links[bearer_id];
3028 if (l_ptr) {
3029 if (op == TIPC_REMOVE_LINK) {
3030 struct bearer *b_ptr = l_ptr->b_ptr;
3031 spin_lock_bh(&b_ptr->publ.lock);
3032 link_delete(l_ptr);
3033 spin_unlock_bh(&b_ptr->publ.lock);
3034 }
3035 if (op == TIPC_CMD_BLOCK_LINK) {
3036 link_reset(l_ptr);
3037 l_ptr->blocked = 1;
3038 }
3039 if (op == TIPC_CMD_UNBLOCK_LINK) {
3040 l_ptr->blocked = 0;
3041 }
3042 res = TIPC_OK;
3043 }
3044 node_unlock(node);
3045 }
3046 read_unlock_bh(&net_lock);
3047 return res;
3048}
3049#endif
3050
3051/**
3052 * link_get_max_pkt - get maximum packet size to use when sending to destination
3053 * @dest: network address of destination node
3054 * @selector: used to select from set of active links
3055 *
3056 * If no active link can be found, uses default maximum packet size.
3057 */
3058
3059u32 link_get_max_pkt(u32 dest, u32 selector)
3060{
3061 struct node *n_ptr;
3062 struct link *l_ptr;
3063 u32 res = MAX_PKT_DEFAULT;
3064
3065 if (dest == tipc_own_addr)
3066 return MAX_MSG_SIZE;
3067
3068 read_lock_bh(&net_lock);
3069 n_ptr = node_select(dest, selector);
3070 if (n_ptr) {
3071 node_lock(n_ptr);
3072 l_ptr = n_ptr->active_links[selector & 1];
3073 if (l_ptr)
3074 res = link_max_pkt(l_ptr);
3075 node_unlock(n_ptr);
3076 }
3077 read_unlock_bh(&net_lock);
3078 return res;
3079}
3080
3081#if 0
3082static void link_dump_rec_queue(struct link *l_ptr)
3083{
3084 struct sk_buff *crs;
3085
3086 if (!l_ptr->oldest_deferred_in) {
3087 info("Reception queue empty\n");
3088 return;
3089 }
3090 info("Contents of Reception queue:\n");
3091 crs = l_ptr->oldest_deferred_in;
3092 while (crs) {
3093 if (crs->data == (void *)0x0000a3a3) {
3094 info("buffer %x invalid\n", crs);
3095 return;
3096 }
3097 msg_dbg(buf_msg(crs), "In rec queue: \n");
3098 crs = crs->next;
3099 }
3100}
3101#endif
3102
3103static void link_dump_send_queue(struct link *l_ptr)
3104{
3105 if (l_ptr->next_out) {
3106 info("\nContents of unsent queue:\n");
3107 dbg_print_buf_chain(l_ptr->next_out);
3108 }
3109 info("\nContents of send queue:\n");
3110 if (l_ptr->first_out) {
3111 dbg_print_buf_chain(l_ptr->first_out);
3112 }
3113 info("Empty send queue\n");
3114}
3115
3116static void link_print(struct link *l_ptr, struct print_buf *buf,
3117 const char *str)
3118{
3119 tipc_printf(buf, str);
3120 if (link_reset_reset(l_ptr) || link_reset_unknown(l_ptr))
3121 return;
3122 tipc_printf(buf, "Link %x<%s>:",
3123 l_ptr->addr, l_ptr->b_ptr->publ.name);
3124 tipc_printf(buf, ": NXO(%u):", mod(l_ptr->next_out_no));
3125 tipc_printf(buf, "NXI(%u):", mod(l_ptr->next_in_no));
3126 tipc_printf(buf, "SQUE");
3127 if (l_ptr->first_out) {
3128 tipc_printf(buf, "[%u..", msg_seqno(buf_msg(l_ptr->first_out)));
3129 if (l_ptr->next_out)
3130 tipc_printf(buf, "%u..",
3131 msg_seqno(buf_msg(l_ptr->next_out)));
3132 tipc_printf(buf, "%u]",
3133 msg_seqno(buf_msg
3134 (l_ptr->last_out)), l_ptr->out_queue_size);
3135 if ((mod(msg_seqno(buf_msg(l_ptr->last_out)) -
3136 msg_seqno(buf_msg(l_ptr->first_out)))
3137 != (l_ptr->out_queue_size - 1))
3138 || (l_ptr->last_out->next != 0)) {
3139 tipc_printf(buf, "\nSend queue inconsistency\n");
3140 tipc_printf(buf, "first_out= %x ", l_ptr->first_out);
3141 tipc_printf(buf, "next_out= %x ", l_ptr->next_out);
3142 tipc_printf(buf, "last_out= %x ", l_ptr->last_out);
3143 link_dump_send_queue(l_ptr);
3144 }
3145 } else
3146 tipc_printf(buf, "[]");
3147 tipc_printf(buf, "SQSIZ(%u)", l_ptr->out_queue_size);
3148 if (l_ptr->oldest_deferred_in) {
3149 u32 o = msg_seqno(buf_msg(l_ptr->oldest_deferred_in));
3150 u32 n = msg_seqno(buf_msg(l_ptr->newest_deferred_in));
3151 tipc_printf(buf, ":RQUE[%u..%u]", o, n);
3152 if (l_ptr->deferred_inqueue_sz != mod((n + 1) - o)) {
3153 tipc_printf(buf, ":RQSIZ(%u)",
3154 l_ptr->deferred_inqueue_sz);
3155 }
3156 }
3157 if (link_working_unknown(l_ptr))
3158 tipc_printf(buf, ":WU");
3159 if (link_reset_reset(l_ptr))
3160 tipc_printf(buf, ":RR");
3161 if (link_reset_unknown(l_ptr))
3162 tipc_printf(buf, ":RU");
3163 if (link_working_working(l_ptr))
3164 tipc_printf(buf, ":WW");
3165 tipc_printf(buf, "\n");
3166}
3167
diff --git a/net/tipc/link.h b/net/tipc/link.h
new file mode 100644
index 000000000000..c2553f073757
--- /dev/null
+++ b/net/tipc/link.h
@@ -0,0 +1,296 @@
1/*
2 * net/tipc/link.h: Include file for TIPC link code
3 *
4 * Copyright (c) 1995-2006, Ericsson AB
5 * Copyright (c) 2004-2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#ifndef _TIPC_LINK_H
38#define _TIPC_LINK_H
39
40#include "dbg.h"
41#include "msg.h"
42#include "bearer.h"
43#include "node.h"
44
45#define PUSH_FAILED 1
46#define PUSH_FINISHED 2
47
48/*
49 * Link states
50 */
51
52#define WORKING_WORKING 560810u
53#define WORKING_UNKNOWN 560811u
54#define RESET_UNKNOWN 560812u
55#define RESET_RESET 560813u
56
57/*
58 * Starting value for maximum packet size negotiation on unicast links
59 * (unless bearer MTU is less)
60 */
61
62#define MAX_PKT_DEFAULT 1500
63
64/**
65 * struct link - TIPC link data structure
66 * @addr: network address of link's peer node
67 * @name: link name character string
68 * @media_addr: media address to use when sending messages over link
69 * @timer: link timer
70 * @owner: pointer to peer node
71 * @link_list: adjacent links in bearer's list of links
72 * @started: indicates if link has been started
73 * @checkpoint: reference point for triggering link continuity checking
74 * @peer_session: link session # being used by peer end of link
75 * @peer_bearer_id: bearer id used by link's peer endpoint
76 * @b_ptr: pointer to bearer used by link
77 * @tolerance: minimum link continuity loss needed to reset link [in ms]
78 * @continuity_interval: link continuity testing interval [in ms]
79 * @abort_limit: # of unacknowledged continuity probes needed to reset link
80 * @state: current state of link FSM
81 * @blocked: indicates if link has been administratively blocked
82 * @fsm_msg_cnt: # of protocol messages link FSM has sent in current state
83 * @proto_msg: template for control messages generated by link
84 * @pmsg: convenience pointer to "proto_msg" field
85 * @priority: current link priority
86 * @queue_limit: outbound message queue congestion thresholds (indexed by user)
87 * @exp_msg_count: # of tunnelled messages expected during link changeover
88 * @reset_checkpoint: seq # of last acknowledged message at time of link reset
89 * @max_pkt: current maximum packet size for this link
90 * @max_pkt_target: desired maximum packet size for this link
91 * @max_pkt_probes: # of probes based on current (max_pkt, max_pkt_target)
92 * @out_queue_size: # of messages in outbound message queue
93 * @first_out: ptr to first outbound message in queue
94 * @last_out: ptr to last outbound message in queue
95 * @next_out_no: next sequence number to use for outbound messages
96 * @last_retransmitted: sequence number of most recently retransmitted message
97 * @stale_count: # of identical retransmit requests made by peer
98 * @next_in_no: next sequence number to expect for inbound messages
99 * @deferred_inqueue_sz: # of messages in inbound message queue
100 * @oldest_deferred_in: ptr to first inbound message in queue
101 * @newest_deferred_in: ptr to last inbound message in queue
102 * @unacked_window: # of inbound messages rx'd without ack'ing back to peer
103 * @proto_msg_queue: ptr to (single) outbound control message
104 * @retransm_queue_size: number of messages to retransmit
105 * @retransm_queue_head: sequence number of first message to retransmit
106 * @next_out: ptr to first unsent outbound message in queue
107 * @waiting_ports: linked list of ports waiting for link congestion to abate
108 * @long_msg_seq_no: next identifier to use for outbound fragmented messages
109 * @defragm_buf: list of partially reassembled inbound message fragments
110 * @stats: collects statistics regarding link activity
111 * @print_buf: print buffer used to log link activity
112 */
113
114struct link {
115 u32 addr;
116 char name[TIPC_MAX_LINK_NAME];
117 struct tipc_media_addr media_addr;
118 struct timer_list timer;
119 struct node *owner;
120 struct list_head link_list;
121
122 /* Management and link supervision data */
123 int started;
124 u32 checkpoint;
125 u32 peer_session;
126 u32 peer_bearer_id;
127 struct bearer *b_ptr;
128 u32 tolerance;
129 u32 continuity_interval;
130 u32 abort_limit;
131 int state;
132 int blocked;
133 u32 fsm_msg_cnt;
134 struct {
135 unchar hdr[INT_H_SIZE];
136 unchar body[TIPC_MAX_IF_NAME];
137 } proto_msg;
138 struct tipc_msg *pmsg;
139 u32 priority;
140 u32 queue_limit[15]; /* queue_limit[0]==window limit */
141
142 /* Changeover */
143 u32 exp_msg_count;
144 u32 reset_checkpoint;
145
146 /* Max packet negotiation */
147 u32 max_pkt;
148 u32 max_pkt_target;
149 u32 max_pkt_probes;
150
151 /* Sending */
152 u32 out_queue_size;
153 struct sk_buff *first_out;
154 struct sk_buff *last_out;
155 u32 next_out_no;
156 u32 last_retransmitted;
157 u32 stale_count;
158
159 /* Reception */
160 u32 next_in_no;
161 u32 deferred_inqueue_sz;
162 struct sk_buff *oldest_deferred_in;
163 struct sk_buff *newest_deferred_in;
164 u32 unacked_window;
165
166 /* Congestion handling */
167 struct sk_buff *proto_msg_queue;
168 u32 retransm_queue_size;
169 u32 retransm_queue_head;
170 struct sk_buff *next_out;
171 struct list_head waiting_ports;
172
173 /* Fragmentation/defragmentation */
174 u32 long_msg_seq_no;
175 struct sk_buff *defragm_buf;
176
177 /* Statistics */
178 struct {
179 u32 sent_info; /* used in counting # sent packets */
180 u32 recv_info; /* used in counting # recv'd packets */
181 u32 sent_states;
182 u32 recv_states;
183 u32 sent_probes;
184 u32 recv_probes;
185 u32 sent_nacks;
186 u32 recv_nacks;
187 u32 sent_acks;
188 u32 sent_bundled;
189 u32 sent_bundles;
190 u32 recv_bundled;
191 u32 recv_bundles;
192 u32 retransmitted;
193 u32 sent_fragmented;
194 u32 sent_fragments;
195 u32 recv_fragmented;
196 u32 recv_fragments;
197 u32 link_congs; /* # port sends blocked by congestion */
198 u32 bearer_congs;
199 u32 deferred_recv;
200 u32 duplicates;
201
202 /* for statistical profiling of send queue size */
203
204 u32 max_queue_sz;
205 u32 accu_queue_sz;
206 u32 queue_sz_counts;
207
208 /* for statistical profiling of message lengths */
209
210 u32 msg_length_counts;
211 u32 msg_lengths_total;
212 u32 msg_length_profile[7];
213#if 0
214 u32 sent_tunneled;
215 u32 recv_tunneled;
216#endif
217 } stats;
218
219 struct print_buf print_buf;
220};
221
222struct port;
223
224struct link *link_create(struct bearer *b_ptr, const u32 peer,
225 const struct tipc_media_addr *media_addr);
226void link_delete(struct link *l_ptr);
227void link_changeover(struct link *l_ptr);
228void link_send_duplicate(struct link *l_ptr, struct link *dest);
229void link_reset_fragments(struct link *l_ptr);
230int link_is_up(struct link *l_ptr);
231int link_is_active(struct link *l_ptr);
232void link_start(struct link *l_ptr);
233u32 link_push_packet(struct link *l_ptr);
234void link_stop(struct link *l_ptr);
235struct sk_buff *link_cmd_config(const void *req_tlv_area, int req_tlv_space, u16 cmd);
236struct sk_buff *link_cmd_show_stats(const void *req_tlv_area, int req_tlv_space);
237struct sk_buff *link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_space);
238void link_reset(struct link *l_ptr);
239int link_send(struct sk_buff *buf, u32 dest, u32 selector);
240int link_send_buf(struct link *l_ptr, struct sk_buff *buf);
241u32 link_get_max_pkt(u32 dest,u32 selector);
242int link_send_sections_fast(struct port* sender,
243 struct iovec const *msg_sect,
244 const u32 num_sect,
245 u32 destnode);
246
247int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf);
248void link_tunnel(struct link *l_ptr, struct tipc_msg *tnl_hdr,
249 struct tipc_msg *msg, u32 selector);
250void link_recv_bundle(struct sk_buff *buf);
251int link_recv_fragment(struct sk_buff **pending,
252 struct sk_buff **fb,
253 struct tipc_msg **msg);
254void link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int prob, u32 gap,
255 u32 tolerance, u32 priority, u32 acked_mtu);
256void link_push_queue(struct link *l_ptr);
257u32 link_defer_pkt(struct sk_buff **head, struct sk_buff **tail,
258 struct sk_buff *buf);
259void link_wakeup_ports(struct link *l_ptr, int all);
260void link_set_queue_limits(struct link *l_ptr, u32 window);
261void link_retransmit(struct link *l_ptr, struct sk_buff *start, u32 retransmits);
262
263/*
264 * Link sequence number manipulation routines (uses modulo 2**16 arithmetic)
265 */
266
267static inline u32 mod(u32 x)
268{
269 return x & 0xffffu;
270}
271
272static inline int between(u32 lower, u32 upper, u32 n)
273{
274 if ((lower < n) && (n < upper))
275 return 1;
276 if ((upper < lower) && ((n > lower) || (n < upper)))
277 return 1;
278 return 0;
279}
280
281static inline int less_eq(u32 left, u32 right)
282{
283 return (mod(right - left) < 32768u);
284}
285
286static inline int less(u32 left, u32 right)
287{
288 return (less_eq(left, right) && (mod(right) != mod(left)));
289}
290
291static inline u32 lesser(u32 left, u32 right)
292{
293 return less_eq(left, right) ? left : right;
294}
295
296#endif
diff --git a/net/tipc/msg.c b/net/tipc/msg.c
new file mode 100644
index 000000000000..03dbc55cb04c
--- /dev/null
+++ b/net/tipc/msg.c
@@ -0,0 +1,334 @@
1/*
2 * net/tipc/msg.c: TIPC message header routines
3 *
4 * Copyright (c) 2000-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include "core.h"
38#include "addr.h"
39#include "dbg.h"
40#include "msg.h"
41#include "bearer.h"
42
43
44void msg_set_media_addr(struct tipc_msg *m, struct tipc_media_addr *a)
45{
46 memcpy(&((int *)m)[5], a, sizeof(*a));
47}
48
49void msg_get_media_addr(struct tipc_msg *m, struct tipc_media_addr *a)
50{
51 memcpy(a, &((int*)m)[5], sizeof(*a));
52}
53
54
55void msg_print(struct print_buf *buf, struct tipc_msg *msg, const char *str)
56{
57 u32 usr = msg_user(msg);
58 tipc_printf(buf, str);
59
60 switch (usr) {
61 case MSG_BUNDLER:
62 tipc_printf(buf, "BNDL::");
63 tipc_printf(buf, "MSGS(%u):", msg_msgcnt(msg));
64 break;
65 case BCAST_PROTOCOL:
66 tipc_printf(buf, "BCASTP::");
67 break;
68 case MSG_FRAGMENTER:
69 tipc_printf(buf, "FRAGM::");
70 switch (msg_type(msg)) {
71 case FIRST_FRAGMENT:
72 tipc_printf(buf, "FIRST:");
73 break;
74 case FRAGMENT:
75 tipc_printf(buf, "BODY:");
76 break;
77 case LAST_FRAGMENT:
78 tipc_printf(buf, "LAST:");
79 break;
80 default:
81 tipc_printf(buf, "UNKNOWN:%x",msg_type(msg));
82
83 }
84 tipc_printf(buf, "NO(%u/%u):",msg_long_msgno(msg),
85 msg_fragm_no(msg));
86 break;
87 case DATA_LOW:
88 case DATA_MEDIUM:
89 case DATA_HIGH:
90 case DATA_CRITICAL:
91 tipc_printf(buf, "DAT%u:", msg_user(msg));
92 if (msg_short(msg)) {
93 tipc_printf(buf, "CON:");
94 break;
95 }
96 switch (msg_type(msg)) {
97 case TIPC_CONN_MSG:
98 tipc_printf(buf, "CON:");
99 break;
100 case TIPC_MCAST_MSG:
101 tipc_printf(buf, "MCST:");
102 break;
103 case TIPC_NAMED_MSG:
104 tipc_printf(buf, "NAM:");
105 break;
106 case TIPC_DIRECT_MSG:
107 tipc_printf(buf, "DIR:");
108 break;
109 default:
110 tipc_printf(buf, "UNKNOWN TYPE %u",msg_type(msg));
111 }
112 if (msg_routed(msg) && !msg_non_seq(msg))
113 tipc_printf(buf, "ROUT:");
114 if (msg_reroute_cnt(msg))
115 tipc_printf(buf, "REROUTED(%u):",
116 msg_reroute_cnt(msg));
117 break;
118 case NAME_DISTRIBUTOR:
119 tipc_printf(buf, "NMD::");
120 switch (msg_type(msg)) {
121 case PUBLICATION:
122 tipc_printf(buf, "PUBL(%u):", (msg_size(msg) - msg_hdr_sz(msg)) / 20); /* Items */
123 break;
124 case WITHDRAWAL:
125 tipc_printf(buf, "WDRW:");
126 break;
127 default:
128 tipc_printf(buf, "UNKNOWN:%x",msg_type(msg));
129 }
130 if (msg_routed(msg))
131 tipc_printf(buf, "ROUT:");
132 if (msg_reroute_cnt(msg))
133 tipc_printf(buf, "REROUTED(%u):",
134 msg_reroute_cnt(msg));
135 break;
136 case CONN_MANAGER:
137 tipc_printf(buf, "CONN_MNG:");
138 switch (msg_type(msg)) {
139 case CONN_PROBE:
140 tipc_printf(buf, "PROBE:");
141 break;
142 case CONN_PROBE_REPLY:
143 tipc_printf(buf, "PROBE_REPLY:");
144 break;
145 case CONN_ACK:
146 tipc_printf(buf, "CONN_ACK:");
147 tipc_printf(buf, "ACK(%u):",msg_msgcnt(msg));
148 break;
149 default:
150 tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg));
151 }
152 if (msg_routed(msg))
153 tipc_printf(buf, "ROUT:");
154 if (msg_reroute_cnt(msg))
155 tipc_printf(buf, "REROUTED(%u):",msg_reroute_cnt(msg));
156 break;
157 case LINK_PROTOCOL:
158 tipc_printf(buf, "PROT:TIM(%u):",msg_timestamp(msg));
159 switch (msg_type(msg)) {
160 case STATE_MSG:
161 tipc_printf(buf, "STATE:");
162 tipc_printf(buf, "%s:",msg_probe(msg) ? "PRB" :"");
163 tipc_printf(buf, "NXS(%u):",msg_next_sent(msg));
164 tipc_printf(buf, "GAP(%u):",msg_seq_gap(msg));
165 tipc_printf(buf, "LSTBC(%u):",msg_last_bcast(msg));
166 break;
167 case RESET_MSG:
168 tipc_printf(buf, "RESET:");
169 if (msg_size(msg) != msg_hdr_sz(msg))
170 tipc_printf(buf, "BEAR:%s:",msg_data(msg));
171 break;
172 case ACTIVATE_MSG:
173 tipc_printf(buf, "ACTIVATE:");
174 break;
175 default:
176 tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg));
177 }
178 tipc_printf(buf, "PLANE(%c):",msg_net_plane(msg));
179 tipc_printf(buf, "SESS(%u):",msg_session(msg));
180 break;
181 case CHANGEOVER_PROTOCOL:
182 tipc_printf(buf, "TUNL:");
183 switch (msg_type(msg)) {
184 case DUPLICATE_MSG:
185 tipc_printf(buf, "DUPL:");
186 break;
187 case ORIGINAL_MSG:
188 tipc_printf(buf, "ORIG:");
189 tipc_printf(buf, "EXP(%u)",msg_msgcnt(msg));
190 break;
191 default:
192 tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg));
193 }
194 break;
195 case ROUTE_DISTRIBUTOR:
196 tipc_printf(buf, "ROUTING_MNG:");
197 switch (msg_type(msg)) {
198 case EXT_ROUTING_TABLE:
199 tipc_printf(buf, "EXT_TBL:");
200 tipc_printf(buf, "TO:%x:",msg_remote_node(msg));
201 break;
202 case LOCAL_ROUTING_TABLE:
203 tipc_printf(buf, "LOCAL_TBL:");
204 tipc_printf(buf, "TO:%x:",msg_remote_node(msg));
205 break;
206 case SLAVE_ROUTING_TABLE:
207 tipc_printf(buf, "DP_TBL:");
208 tipc_printf(buf, "TO:%x:",msg_remote_node(msg));
209 break;
210 case ROUTE_ADDITION:
211 tipc_printf(buf, "ADD:");
212 tipc_printf(buf, "TO:%x:",msg_remote_node(msg));
213 break;
214 case ROUTE_REMOVAL:
215 tipc_printf(buf, "REMOVE:");
216 tipc_printf(buf, "TO:%x:",msg_remote_node(msg));
217 break;
218 default:
219 tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg));
220 }
221 break;
222 case LINK_CONFIG:
223 tipc_printf(buf, "CFG:");
224 switch (msg_type(msg)) {
225 case DSC_REQ_MSG:
226 tipc_printf(buf, "DSC_REQ:");
227 break;
228 case DSC_RESP_MSG:
229 tipc_printf(buf, "DSC_RESP:");
230 break;
231 default:
232 tipc_printf(buf, "UNKNOWN TYPE:%x:",msg_type(msg));
233 break;
234 }
235 break;
236 default:
237 tipc_printf(buf, "UNKNOWN USER:");
238 }
239
240 switch (usr) {
241 case CONN_MANAGER:
242 case NAME_DISTRIBUTOR:
243 case DATA_LOW:
244 case DATA_MEDIUM:
245 case DATA_HIGH:
246 case DATA_CRITICAL:
247 if (msg_short(msg))
248 break; /* No error */
249 switch (msg_errcode(msg)) {
250 case TIPC_OK:
251 break;
252 case TIPC_ERR_NO_NAME:
253 tipc_printf(buf, "NO_NAME:");
254 break;
255 case TIPC_ERR_NO_PORT:
256 tipc_printf(buf, "NO_PORT:");
257 break;
258 case TIPC_ERR_NO_NODE:
259 tipc_printf(buf, "NO_PROC:");
260 break;
261 case TIPC_ERR_OVERLOAD:
262 tipc_printf(buf, "OVERLOAD:");
263 break;
264 case TIPC_CONN_SHUTDOWN:
265 tipc_printf(buf, "SHUTDOWN:");
266 break;
267 default:
268 tipc_printf(buf, "UNKNOWN ERROR(%x):",
269 msg_errcode(msg));
270 }
271 default:{}
272 }
273
274 tipc_printf(buf, "HZ(%u):", msg_hdr_sz(msg));
275 tipc_printf(buf, "SZ(%u):", msg_size(msg));
276 tipc_printf(buf, "SQNO(%u):", msg_seqno(msg));
277
278 if (msg_non_seq(msg))
279 tipc_printf(buf, "NOSEQ:");
280 else {
281 tipc_printf(buf, "ACK(%u):", msg_ack(msg));
282 }
283 tipc_printf(buf, "BACK(%u):", msg_bcast_ack(msg));
284 tipc_printf(buf, "PRND(%x)", msg_prevnode(msg));
285
286 if (msg_isdata(msg)) {
287 if (msg_named(msg)) {
288 tipc_printf(buf, "NTYP(%u):", msg_nametype(msg));
289 tipc_printf(buf, "NINST(%u)", msg_nameinst(msg));
290 }
291 }
292
293 if ((usr != LINK_PROTOCOL) && (usr != LINK_CONFIG) &&
294 (usr != MSG_BUNDLER)) {
295 if (!msg_short(msg)) {
296 tipc_printf(buf, ":ORIG(%x:%u):",
297 msg_orignode(msg), msg_origport(msg));
298 tipc_printf(buf, ":DEST(%x:%u):",
299 msg_destnode(msg), msg_destport(msg));
300 } else {
301 tipc_printf(buf, ":OPRT(%u):", msg_origport(msg));
302 tipc_printf(buf, ":DPRT(%u):", msg_destport(msg));
303 }
304 if (msg_routed(msg) && !msg_non_seq(msg))
305 tipc_printf(buf, ":TSEQN(%u)", msg_transp_seqno(msg));
306 }
307 if (msg_user(msg) == NAME_DISTRIBUTOR) {
308 tipc_printf(buf, ":ONOD(%x):", msg_orignode(msg));
309 tipc_printf(buf, ":DNOD(%x):", msg_destnode(msg));
310 if (msg_routed(msg)) {
311 tipc_printf(buf, ":CSEQN(%u)", msg_transp_seqno(msg));
312 }
313 }
314
315 if (msg_user(msg) == LINK_CONFIG) {
316 u32* raw = (u32*)msg;
317 struct tipc_media_addr* orig = (struct tipc_media_addr*)&raw[5];
318 tipc_printf(buf, ":REQL(%u):", msg_req_links(msg));
319 tipc_printf(buf, ":DDOM(%x):", msg_dest_domain(msg));
320 tipc_printf(buf, ":NETID(%u):", msg_bc_netid(msg));
321 media_addr_printf(buf, orig);
322 }
323 if (msg_user(msg) == BCAST_PROTOCOL) {
324 tipc_printf(buf, "BCNACK:AFTER(%u):", msg_bcgap_after(msg));
325 tipc_printf(buf, "TO(%u):", msg_bcgap_to(msg));
326 }
327 tipc_printf(buf, "\n");
328 if ((usr == CHANGEOVER_PROTOCOL) && (msg_msgcnt(msg))) {
329 msg_print(buf,msg_get_wrapped(msg)," /");
330 }
331 if ((usr == MSG_FRAGMENTER) && (msg_type(msg) == FIRST_FRAGMENT)) {
332 msg_print(buf,msg_get_wrapped(msg)," /");
333 }
334}
diff --git a/net/tipc/msg.h b/net/tipc/msg.h
new file mode 100644
index 000000000000..662c81862a0c
--- /dev/null
+++ b/net/tipc/msg.h
@@ -0,0 +1,818 @@
1/*
2 * net/tipc/msg.h: Include file for TIPC message header routines
3 *
4 * Copyright (c) 2000-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#ifndef _TIPC_MSG_H
38#define _TIPC_MSG_H
39
40#include <net/tipc/tipc_msg.h>
41
42#define TIPC_VERSION 2
43#define DATA_LOW TIPC_LOW_IMPORTANCE
44#define DATA_MEDIUM TIPC_MEDIUM_IMPORTANCE
45#define DATA_HIGH TIPC_HIGH_IMPORTANCE
46#define DATA_CRITICAL TIPC_CRITICAL_IMPORTANCE
47#define SHORT_H_SIZE 24 /* Connected,in cluster */
48#define DIR_MSG_H_SIZE 32 /* Directly addressed messages */
49#define CONN_MSG_H_SIZE 36 /* Routed connected msgs*/
50#define LONG_H_SIZE 40 /* Named Messages */
51#define MCAST_H_SIZE 44 /* Multicast messages */
52#define MAX_H_SIZE 60 /* Inclusive full options */
53#define MAX_MSG_SIZE (MAX_H_SIZE + TIPC_MAX_USER_MSG_SIZE)
54#define LINK_CONFIG 13
55
56
57/*
58 TIPC user data message header format, version 2
59
60 - Fundamental definitions available to privileged TIPC users
61 are located in tipc_msg.h.
62 - Remaining definitions available to TIPC internal users appear below.
63*/
64
65
66static inline void msg_set_word(struct tipc_msg *m, u32 w, u32 val)
67{
68 m->hdr[w] = htonl(val);
69}
70
71static inline void msg_set_bits(struct tipc_msg *m, u32 w,
72 u32 pos, u32 mask, u32 val)
73{
74 u32 word = msg_word(m,w) & ~(mask << pos);
75 msg_set_word(m, w, (word |= (val << pos)));
76}
77
78/*
79 * Word 0
80 */
81
82static inline u32 msg_version(struct tipc_msg *m)
83{
84 return msg_bits(m, 0, 29, 7);
85}
86
87static inline void msg_set_version(struct tipc_msg *m)
88{
89 msg_set_bits(m, 0, 29, 0xf, TIPC_VERSION);
90}
91
92static inline u32 msg_user(struct tipc_msg *m)
93{
94 return msg_bits(m, 0, 25, 0xf);
95}
96
97static inline u32 msg_isdata(struct tipc_msg *m)
98{
99 return (msg_user(m) <= DATA_CRITICAL);
100}
101
102static inline void msg_set_user(struct tipc_msg *m, u32 n)
103{
104 msg_set_bits(m, 0, 25, 0xf, n);
105}
106
107static inline void msg_set_importance(struct tipc_msg *m, u32 i)
108{
109 msg_set_user(m, i);
110}
111
112static inline void msg_set_hdr_sz(struct tipc_msg *m,u32 n)
113{
114 msg_set_bits(m, 0, 21, 0xf, n>>2);
115}
116
117static inline int msg_non_seq(struct tipc_msg *m)
118{
119 return msg_bits(m, 0, 20, 1);
120}
121
122static inline void msg_set_non_seq(struct tipc_msg *m)
123{
124 msg_set_bits(m, 0, 20, 1, 1);
125}
126
127static inline int msg_dest_droppable(struct tipc_msg *m)
128{
129 return msg_bits(m, 0, 19, 1);
130}
131
132static inline void msg_set_dest_droppable(struct tipc_msg *m, u32 d)
133{
134 msg_set_bits(m, 0, 19, 1, d);
135}
136
137static inline int msg_src_droppable(struct tipc_msg *m)
138{
139 return msg_bits(m, 0, 18, 1);
140}
141
142static inline void msg_set_src_droppable(struct tipc_msg *m, u32 d)
143{
144 msg_set_bits(m, 0, 18, 1, d);
145}
146
147static inline void msg_set_size(struct tipc_msg *m, u32 sz)
148{
149 m->hdr[0] = htonl((msg_word(m, 0) & ~0x1ffff) | sz);
150}
151
152
153/*
154 * Word 1
155 */
156
157static inline void msg_set_type(struct tipc_msg *m, u32 n)
158{
159 msg_set_bits(m, 1, 29, 0x7, n);
160}
161
162static inline void msg_set_errcode(struct tipc_msg *m, u32 err)
163{
164 msg_set_bits(m, 1, 25, 0xf, err);
165}
166
167static inline u32 msg_reroute_cnt(struct tipc_msg *m)
168{
169 return msg_bits(m, 1, 21, 0xf);
170}
171
172static inline void msg_incr_reroute_cnt(struct tipc_msg *m)
173{
174 msg_set_bits(m, 1, 21, 0xf, msg_reroute_cnt(m) + 1);
175}
176
177static inline void msg_reset_reroute_cnt(struct tipc_msg *m)
178{
179 msg_set_bits(m, 1, 21, 0xf, 0);
180}
181
182static inline u32 msg_lookup_scope(struct tipc_msg *m)
183{
184 return msg_bits(m, 1, 19, 0x3);
185}
186
187static inline void msg_set_lookup_scope(struct tipc_msg *m, u32 n)
188{
189 msg_set_bits(m, 1, 19, 0x3, n);
190}
191
192static inline void msg_set_options(struct tipc_msg *m, const char *opt, u32 sz)
193{
194 u32 hsz = msg_hdr_sz(m);
195 char *to = (char *)&m->hdr[hsz/4];
196
197 if ((hsz < DIR_MSG_H_SIZE) || ((hsz + sz) > MAX_H_SIZE))
198 return;
199 msg_set_bits(m, 1, 16, 0x7, (hsz - 28)/4);
200 msg_set_hdr_sz(m, hsz + sz);
201 memcpy(to, opt, sz);
202}
203
204static inline u32 msg_bcast_ack(struct tipc_msg *m)
205{
206 return msg_bits(m, 1, 0, 0xffff);
207}
208
209static inline void msg_set_bcast_ack(struct tipc_msg *m, u32 n)
210{
211 msg_set_bits(m, 1, 0, 0xffff, n);
212}
213
214
215/*
216 * Word 2
217 */
218
219static inline u32 msg_ack(struct tipc_msg *m)
220{
221 return msg_bits(m, 2, 16, 0xffff);
222}
223
224static inline void msg_set_ack(struct tipc_msg *m, u32 n)
225{
226 msg_set_bits(m, 2, 16, 0xffff, n);
227}
228
229static inline u32 msg_seqno(struct tipc_msg *m)
230{
231 return msg_bits(m, 2, 0, 0xffff);
232}
233
234static inline void msg_set_seqno(struct tipc_msg *m, u32 n)
235{
236 msg_set_bits(m, 2, 0, 0xffff, n);
237}
238
239
240/*
241 * Words 3-10
242 */
243
244
245static inline void msg_set_prevnode(struct tipc_msg *m, u32 a)
246{
247 msg_set_word(m, 3, a);
248}
249
250static inline void msg_set_origport(struct tipc_msg *m, u32 p)
251{
252 msg_set_word(m, 4, p);
253}
254
255static inline void msg_set_destport(struct tipc_msg *m, u32 p)
256{
257 msg_set_word(m, 5, p);
258}
259
260static inline void msg_set_mc_netid(struct tipc_msg *m, u32 p)
261{
262 msg_set_word(m, 5, p);
263}
264
265static inline void msg_set_orignode(struct tipc_msg *m, u32 a)
266{
267 msg_set_word(m, 6, a);
268}
269
270static inline void msg_set_destnode(struct tipc_msg *m, u32 a)
271{
272 msg_set_word(m, 7, a);
273}
274
275static inline int msg_is_dest(struct tipc_msg *m, u32 d)
276{
277 return(msg_short(m) || (msg_destnode(m) == d));
278}
279
280static inline u32 msg_routed(struct tipc_msg *m)
281{
282 if (likely(msg_short(m)))
283 return 0;
284 return(msg_destnode(m) ^ msg_orignode(m)) >> 11;
285}
286
287static inline void msg_set_nametype(struct tipc_msg *m, u32 n)
288{
289 msg_set_word(m, 8, n);
290}
291
292static inline u32 msg_transp_seqno(struct tipc_msg *m)
293{
294 return msg_word(m, 8);
295}
296
297static inline void msg_set_timestamp(struct tipc_msg *m, u32 n)
298{
299 msg_set_word(m, 8, n);
300}
301
302static inline u32 msg_timestamp(struct tipc_msg *m)
303{
304 return msg_word(m, 8);
305}
306
307static inline void msg_set_transp_seqno(struct tipc_msg *m, u32 n)
308{
309 msg_set_word(m, 8, n);
310}
311
312static inline void msg_set_namelower(struct tipc_msg *m, u32 n)
313{
314 msg_set_word(m, 9, n);
315}
316
317static inline void msg_set_nameinst(struct tipc_msg *m, u32 n)
318{
319 msg_set_namelower(m, n);
320}
321
322static inline void msg_set_nameupper(struct tipc_msg *m, u32 n)
323{
324 msg_set_word(m, 10, n);
325}
326
327static inline struct tipc_msg *msg_get_wrapped(struct tipc_msg *m)
328{
329 return (struct tipc_msg *)msg_data(m);
330}
331
332static inline void msg_expand(struct tipc_msg *m, u32 destnode)
333{
334 if (!msg_short(m))
335 return;
336 msg_set_hdr_sz(m, LONG_H_SIZE);
337 msg_set_orignode(m, msg_prevnode(m));
338 msg_set_destnode(m, destnode);
339 memset(&m->hdr[8], 0, 12);
340}
341
342
343
344/*
345 TIPC internal message header format, version 2
346
347 1 0 9 8 7 6 5 4|3 2 1 0 9 8 7 6|5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0
348 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
349 w0:|vers |msg usr|hdr sz |n|resrv| packet size |
350 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
351 w1:|m typ|rsv=0| sequence gap | broadcast ack no |
352 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
353 w2:| link level ack no/bc_gap_from | seq no / bcast_gap_to |
354 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
355 w3:| previous node |
356 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
357 w4:| next sent broadcast/fragm no | next sent pkt/ fragm msg no |
358 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
359 w5:| session no |rsv=0|r|berid|link prio|netpl|p|
360 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
361 w6:| originating node |
362 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
363 w7:| destination node |
364 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
365 w8:| transport sequence number |
366 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
367 w9:| msg count / bcast tag | link tolerance |
368 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
369 \ \
370 / User Specific Data /
371 \ \
372 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
373
374 NB: CONN_MANAGER use data message format. LINK_CONFIG has own format.
375*/
376
377/*
378 * Internal users
379 */
380
381#define BCAST_PROTOCOL 5
382#define MSG_BUNDLER 6
383#define LINK_PROTOCOL 7
384#define CONN_MANAGER 8
385#define ROUTE_DISTRIBUTOR 9
386#define CHANGEOVER_PROTOCOL 10
387#define NAME_DISTRIBUTOR 11
388#define MSG_FRAGMENTER 12
389#define LINK_CONFIG 13
390#define INT_H_SIZE 40
391#define DSC_H_SIZE 40
392
393/*
394 * Connection management protocol messages
395 */
396
397#define CONN_PROBE 0
398#define CONN_PROBE_REPLY 1
399#define CONN_ACK 2
400
401/*
402 * Name distributor messages
403 */
404
405#define PUBLICATION 0
406#define WITHDRAWAL 1
407
408
409/*
410 * Word 1
411 */
412
413static inline u32 msg_seq_gap(struct tipc_msg *m)
414{
415 return msg_bits(m, 1, 16, 0xff);
416}
417
418static inline void msg_set_seq_gap(struct tipc_msg *m, u32 n)
419{
420 msg_set_bits(m, 1, 16, 0xff, n);
421}
422
423static inline u32 msg_req_links(struct tipc_msg *m)
424{
425 return msg_bits(m, 1, 16, 0xfff);
426}
427
428static inline void msg_set_req_links(struct tipc_msg *m, u32 n)
429{
430 msg_set_bits(m, 1, 16, 0xfff, n);
431}
432
433
434/*
435 * Word 2
436 */
437
438static inline u32 msg_dest_domain(struct tipc_msg *m)
439{
440 return msg_word(m, 2);
441}
442
443static inline void msg_set_dest_domain(struct tipc_msg *m, u32 n)
444{
445 msg_set_word(m, 2, n);
446}
447
448static inline u32 msg_bcgap_after(struct tipc_msg *m)
449{
450 return msg_bits(m, 2, 16, 0xffff);
451}
452
453static inline void msg_set_bcgap_after(struct tipc_msg *m, u32 n)
454{
455 msg_set_bits(m, 2, 16, 0xffff, n);
456}
457
458static inline u32 msg_bcgap_to(struct tipc_msg *m)
459{
460 return msg_bits(m, 2, 0, 0xffff);
461}
462
463static inline void msg_set_bcgap_to(struct tipc_msg *m, u32 n)
464{
465 msg_set_bits(m, 2, 0, 0xffff, n);
466}
467
468
469/*
470 * Word 4
471 */
472
473static inline u32 msg_last_bcast(struct tipc_msg *m)
474{
475 return msg_bits(m, 4, 16, 0xffff);
476}
477
478static inline void msg_set_last_bcast(struct tipc_msg *m, u32 n)
479{
480 msg_set_bits(m, 4, 16, 0xffff, n);
481}
482
483
484static inline u32 msg_fragm_no(struct tipc_msg *m)
485{
486 return msg_bits(m, 4, 16, 0xffff);
487}
488
489static inline void msg_set_fragm_no(struct tipc_msg *m, u32 n)
490{
491 msg_set_bits(m, 4, 16, 0xffff, n);
492}
493
494
495static inline u32 msg_next_sent(struct tipc_msg *m)
496{
497 return msg_bits(m, 4, 0, 0xffff);
498}
499
500static inline void msg_set_next_sent(struct tipc_msg *m, u32 n)
501{
502 msg_set_bits(m, 4, 0, 0xffff, n);
503}
504
505
506static inline u32 msg_long_msgno(struct tipc_msg *m)
507{
508 return msg_bits(m, 4, 0, 0xffff);
509}
510
511static inline void msg_set_long_msgno(struct tipc_msg *m, u32 n)
512{
513 msg_set_bits(m, 4, 0, 0xffff, n);
514}
515
516static inline u32 msg_bc_netid(struct tipc_msg *m)
517{
518 return msg_word(m, 4);
519}
520
521static inline void msg_set_bc_netid(struct tipc_msg *m, u32 id)
522{
523 msg_set_word(m, 4, id);
524}
525
526static inline u32 msg_link_selector(struct tipc_msg *m)
527{
528 return msg_bits(m, 4, 0, 1);
529}
530
531static inline void msg_set_link_selector(struct tipc_msg *m, u32 n)
532{
533 msg_set_bits(m, 4, 0, 1, (n & 1));
534}
535
536/*
537 * Word 5
538 */
539
540static inline u32 msg_session(struct tipc_msg *m)
541{
542 return msg_bits(m, 5, 16, 0xffff);
543}
544
545static inline void msg_set_session(struct tipc_msg *m, u32 n)
546{
547 msg_set_bits(m, 5, 16, 0xffff, n);
548}
549
550static inline u32 msg_probe(struct tipc_msg *m)
551{
552 return msg_bits(m, 5, 0, 1);
553}
554
555static inline void msg_set_probe(struct tipc_msg *m, u32 val)
556{
557 msg_set_bits(m, 5, 0, 1, (val & 1));
558}
559
560static inline char msg_net_plane(struct tipc_msg *m)
561{
562 return msg_bits(m, 5, 1, 7) + 'A';
563}
564
565static inline void msg_set_net_plane(struct tipc_msg *m, char n)
566{
567 msg_set_bits(m, 5, 1, 7, (n - 'A'));
568}
569
570static inline u32 msg_linkprio(struct tipc_msg *m)
571{
572 return msg_bits(m, 5, 4, 0x1f);
573}
574
575static inline void msg_set_linkprio(struct tipc_msg *m, u32 n)
576{
577 msg_set_bits(m, 5, 4, 0x1f, n);
578}
579
580static inline u32 msg_bearer_id(struct tipc_msg *m)
581{
582 return msg_bits(m, 5, 9, 0x7);
583}
584
585static inline void msg_set_bearer_id(struct tipc_msg *m, u32 n)
586{
587 msg_set_bits(m, 5, 9, 0x7, n);
588}
589
590static inline u32 msg_redundant_link(struct tipc_msg *m)
591{
592 return msg_bits(m, 5, 12, 0x1);
593}
594
595static inline void msg_set_redundant_link(struct tipc_msg *m)
596{
597 msg_set_bits(m, 5, 12, 0x1, 1);
598}
599
600static inline void msg_clear_redundant_link(struct tipc_msg *m)
601{
602 msg_set_bits(m, 5, 12, 0x1, 0);
603}
604
605
606/*
607 * Word 9
608 */
609
610static inline u32 msg_msgcnt(struct tipc_msg *m)
611{
612 return msg_bits(m, 9, 16, 0xffff);
613}
614
615static inline void msg_set_msgcnt(struct tipc_msg *m, u32 n)
616{
617 msg_set_bits(m, 9, 16, 0xffff, n);
618}
619
620static inline u32 msg_bcast_tag(struct tipc_msg *m)
621{
622 return msg_bits(m, 9, 16, 0xffff);
623}
624
625static inline void msg_set_bcast_tag(struct tipc_msg *m, u32 n)
626{
627 msg_set_bits(m, 9, 16, 0xffff, n);
628}
629
630static inline u32 msg_max_pkt(struct tipc_msg *m)
631{
632 return (msg_bits(m, 9, 16, 0xffff) * 4);
633}
634
635static inline void msg_set_max_pkt(struct tipc_msg *m, u32 n)
636{
637 msg_set_bits(m, 9, 16, 0xffff, (n / 4));
638}
639
640static inline u32 msg_link_tolerance(struct tipc_msg *m)
641{
642 return msg_bits(m, 9, 0, 0xffff);
643}
644
645static inline void msg_set_link_tolerance(struct tipc_msg *m, u32 n)
646{
647 msg_set_bits(m, 9, 0, 0xffff, n);
648}
649
650/*
651 * Routing table message data
652 */
653
654
655static inline u32 msg_remote_node(struct tipc_msg *m)
656{
657 return msg_word(m, msg_hdr_sz(m)/4);
658}
659
660static inline void msg_set_remote_node(struct tipc_msg *m, u32 a)
661{
662 msg_set_word(m, msg_hdr_sz(m)/4, a);
663}
664
665static inline int msg_dataoctet(struct tipc_msg *m, u32 pos)
666{
667 return(msg_data(m)[pos + 4] != 0);
668}
669
670static inline void msg_set_dataoctet(struct tipc_msg *m, u32 pos)
671{
672 msg_data(m)[pos + 4] = 1;
673}
674
675/*
676 * Segmentation message types
677 */
678
679#define FIRST_FRAGMENT 0
680#define FRAGMENT 1
681#define LAST_FRAGMENT 2
682
683/*
684 * Link management protocol message types
685 */
686
687#define STATE_MSG 0
688#define RESET_MSG 1
689#define ACTIVATE_MSG 2
690
691/*
692 * Changeover tunnel message types
693 */
694#define DUPLICATE_MSG 0
695#define ORIGINAL_MSG 1
696
697/*
698 * Routing table message types
699 */
700#define EXT_ROUTING_TABLE 0
701#define LOCAL_ROUTING_TABLE 1
702#define SLAVE_ROUTING_TABLE 2
703#define ROUTE_ADDITION 3
704#define ROUTE_REMOVAL 4
705
706/*
707 * Config protocol message types
708 */
709
710#define DSC_REQ_MSG 0
711#define DSC_RESP_MSG 1
712
713static inline u32 msg_tot_importance(struct tipc_msg *m)
714{
715 if (likely(msg_isdata(m))) {
716 if (likely(msg_orignode(m) == tipc_own_addr))
717 return msg_importance(m);
718 return msg_importance(m) + 4;
719 }
720 if ((msg_user(m) == MSG_FRAGMENTER) &&
721 (msg_type(m) == FIRST_FRAGMENT))
722 return msg_importance(msg_get_wrapped(m));
723 return msg_importance(m);
724}
725
726
727static inline void msg_init(struct tipc_msg *m, u32 user, u32 type,
728 u32 err, u32 hsize, u32 destnode)
729{
730 memset(m, 0, hsize);
731 msg_set_version(m);
732 msg_set_user(m, user);
733 msg_set_hdr_sz(m, hsize);
734 msg_set_size(m, hsize);
735 msg_set_prevnode(m, tipc_own_addr);
736 msg_set_type(m, type);
737 msg_set_errcode(m, err);
738 if (!msg_short(m)) {
739 msg_set_orignode(m, tipc_own_addr);
740 msg_set_destnode(m, destnode);
741 }
742}
743
744/**
745 * msg_calc_data_size - determine total data size for message
746 */
747
748static inline int msg_calc_data_size(struct iovec const *msg_sect, u32 num_sect)
749{
750 int dsz = 0;
751 int i;
752
753 for (i = 0; i < num_sect; i++)
754 dsz += msg_sect[i].iov_len;
755 return dsz;
756}
757
758/**
759 * msg_build - create message using specified header and data
760 *
761 * Note: Caller must not hold any locks in case copy_from_user() is interrupted!
762 *
763 * Returns message data size or errno
764 */
765
766static inline int msg_build(struct tipc_msg *hdr,
767 struct iovec const *msg_sect, u32 num_sect,
768 int max_size, int usrmem, struct sk_buff** buf)
769{
770 int dsz, sz, hsz, pos, res, cnt;
771
772 dsz = msg_calc_data_size(msg_sect, num_sect);
773 if (unlikely(dsz > TIPC_MAX_USER_MSG_SIZE)) {
774 *buf = NULL;
775 return -EINVAL;
776 }
777
778 pos = hsz = msg_hdr_sz(hdr);
779 sz = hsz + dsz;
780 msg_set_size(hdr, sz);
781 if (unlikely(sz > max_size)) {
782 *buf = NULL;
783 return dsz;
784 }
785
786 *buf = buf_acquire(sz);
787 if (!(*buf))
788 return -ENOMEM;
789 memcpy((*buf)->data, (unchar *)hdr, hsz);
790 for (res = 1, cnt = 0; res && (cnt < num_sect); cnt++) {
791 if (likely(usrmem))
792 res = !copy_from_user((*buf)->data + pos,
793 msg_sect[cnt].iov_base,
794 msg_sect[cnt].iov_len);
795 else
796 memcpy((*buf)->data + pos, msg_sect[cnt].iov_base,
797 msg_sect[cnt].iov_len);
798 pos += msg_sect[cnt].iov_len;
799 }
800 if (likely(res))
801 return dsz;
802
803 buf_discard(*buf);
804 *buf = NULL;
805 return -EFAULT;
806}
807
808
809struct tipc_media_addr;
810
811extern void msg_set_media_addr(struct tipc_msg *m,
812 struct tipc_media_addr *a);
813
814extern void msg_get_media_addr(struct tipc_msg *m,
815 struct tipc_media_addr *a);
816
817
818#endif
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c
new file mode 100644
index 000000000000..41cbaf1a4a73
--- /dev/null
+++ b/net/tipc/name_distr.c
@@ -0,0 +1,309 @@
1/*
2 * net/tipc/name_distr.c: TIPC name distribution code
3 *
4 * Copyright (c) 2000-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include "core.h"
38#include "cluster.h"
39#include "dbg.h"
40#include "link.h"
41#include "msg.h"
42#include "name_distr.h"
43
44#undef DBG_OUTPUT
45#define DBG_OUTPUT NULL
46
47#define ITEM_SIZE sizeof(struct distr_item)
48
49/**
50 * struct distr_item - publication info distributed to other nodes
51 * @type: name sequence type
52 * @lower: name sequence lower bound
53 * @upper: name sequence upper bound
54 * @ref: publishing port reference
55 * @key: publication key
56 *
57 * ===> All fields are stored in network byte order. <===
58 *
59 * First 3 fields identify (name or) name sequence being published.
60 * Reference field uniquely identifies port that published name sequence.
61 * Key field uniquely identifies publication, in the event a port has
62 * multiple publications of the same name sequence.
63 *
64 * Note: There is no field that identifies the publishing node because it is
65 * the same for all items contained within a publication message.
66 */
67
68struct distr_item {
69 u32 type;
70 u32 lower;
71 u32 upper;
72 u32 ref;
73 u32 key;
74};
75
76/**
77 * List of externally visible publications by this node --
78 * that is, all publications having scope > TIPC_NODE_SCOPE.
79 */
80
81static LIST_HEAD(publ_root);
82static u32 publ_cnt = 0;
83
84/**
85 * publ_to_item - add publication info to a publication message
86 */
87
88static void publ_to_item(struct distr_item *i, struct publication *p)
89{
90 i->type = htonl(p->type);
91 i->lower = htonl(p->lower);
92 i->upper = htonl(p->upper);
93 i->ref = htonl(p->ref);
94 i->key = htonl(p->key);
95 dbg("publ_to_item: %u, %u, %u\n", p->type, p->lower, p->upper);
96}
97
98/**
99 * named_prepare_buf - allocate & initialize a publication message
100 */
101
102static struct sk_buff *named_prepare_buf(u32 type, u32 size, u32 dest)
103{
104 struct sk_buff *buf = buf_acquire(LONG_H_SIZE + size);
105 struct tipc_msg *msg;
106
107 if (buf != NULL) {
108 msg = buf_msg(buf);
109 msg_init(msg, NAME_DISTRIBUTOR, type, TIPC_OK,
110 LONG_H_SIZE, dest);
111 msg_set_size(msg, LONG_H_SIZE + size);
112 }
113 return buf;
114}
115
116/**
117 * named_publish - tell other nodes about a new publication by this node
118 */
119
120void named_publish(struct publication *publ)
121{
122 struct sk_buff *buf;
123 struct distr_item *item;
124
125 list_add(&publ->local_list, &publ_root);
126 publ_cnt++;
127
128 buf = named_prepare_buf(PUBLICATION, ITEM_SIZE, 0);
129 if (!buf) {
130 warn("Memory squeeze; failed to distribute publication\n");
131 return;
132 }
133
134 item = (struct distr_item *)msg_data(buf_msg(buf));
135 publ_to_item(item, publ);
136 dbg("named_withdraw: broadcasting publish msg\n");
137 cluster_broadcast(buf);
138}
139
140/**
141 * named_withdraw - tell other nodes about a withdrawn publication by this node
142 */
143
144void named_withdraw(struct publication *publ)
145{
146 struct sk_buff *buf;
147 struct distr_item *item;
148
149 list_del(&publ->local_list);
150 publ_cnt--;
151
152 buf = named_prepare_buf(WITHDRAWAL, ITEM_SIZE, 0);
153 if (!buf) {
154 warn("Memory squeeze; failed to distribute withdrawal\n");
155 return;
156 }
157
158 item = (struct distr_item *)msg_data(buf_msg(buf));
159 publ_to_item(item, publ);
160 dbg("named_withdraw: broadcasting withdraw msg\n");
161 cluster_broadcast(buf);
162}
163
164/**
165 * named_node_up - tell specified node about all publications by this node
166 */
167
168void named_node_up(unsigned long node)
169{
170 struct publication *publ;
171 struct distr_item *item = 0;
172 struct sk_buff *buf = 0;
173 u32 left = 0;
174 u32 rest;
175 u32 max_item_buf;
176
177 assert(in_own_cluster(node));
178 read_lock_bh(&nametbl_lock);
179 max_item_buf = TIPC_MAX_USER_MSG_SIZE / ITEM_SIZE;
180 max_item_buf *= ITEM_SIZE;
181 rest = publ_cnt * ITEM_SIZE;
182
183 list_for_each_entry(publ, &publ_root, local_list) {
184 if (!buf) {
185 left = (rest <= max_item_buf) ? rest : max_item_buf;
186 rest -= left;
187 buf = named_prepare_buf(PUBLICATION, left, node);
188 if (buf == NULL) {
189 warn("Memory Squeeze; could not send publication\n");
190 goto exit;
191 }
192 item = (struct distr_item *)msg_data(buf_msg(buf));
193 }
194 publ_to_item(item, publ);
195 item++;
196 left -= ITEM_SIZE;
197 if (!left) {
198 msg_set_link_selector(buf_msg(buf), node);
199 dbg("named_node_up: sending publish msg to "
200 "<%u.%u.%u>\n", tipc_zone(node),
201 tipc_cluster(node), tipc_node(node));
202 link_send(buf, node, node);
203 buf = 0;
204 }
205 }
206exit:
207 read_unlock_bh(&nametbl_lock);
208}
209
210/**
211 * node_is_down - remove publication associated with a failed node
212 *
213 * Invoked for each publication issued by a newly failed node.
214 * Removes publication structure from name table & deletes it.
215 * In rare cases the link may have come back up again when this
216 * function is called, and we have two items representing the same
217 * publication. Nudge this item's key to distinguish it from the other.
218 * (Note: Publication's node subscription is already unsubscribed.)
219 */
220
221static void node_is_down(struct publication *publ)
222{
223 struct publication *p;
224 write_lock_bh(&nametbl_lock);
225 dbg("node_is_down: withdrawing %u, %u, %u\n",
226 publ->type, publ->lower, publ->upper);
227 publ->key += 1222345;
228 p = nametbl_remove_publ(publ->type, publ->lower,
229 publ->node, publ->ref, publ->key);
230 assert(p == publ);
231 write_unlock_bh(&nametbl_lock);
232 if (publ)
233 kfree(publ);
234}
235
236/**
237 * named_recv - process name table update message sent by another node
238 */
239
240void named_recv(struct sk_buff *buf)
241{
242 struct publication *publ;
243 struct tipc_msg *msg = buf_msg(buf);
244 struct distr_item *item = (struct distr_item *)msg_data(msg);
245 u32 count = msg_data_sz(msg) / ITEM_SIZE;
246
247 write_lock_bh(&nametbl_lock);
248 while (count--) {
249 if (msg_type(msg) == PUBLICATION) {
250 dbg("named_recv: got publication for %u, %u, %u\n",
251 ntohl(item->type), ntohl(item->lower),
252 ntohl(item->upper));
253 publ = nametbl_insert_publ(ntohl(item->type),
254 ntohl(item->lower),
255 ntohl(item->upper),
256 TIPC_CLUSTER_SCOPE,
257 msg_orignode(msg),
258 ntohl(item->ref),
259 ntohl(item->key));
260 if (publ) {
261 nodesub_subscribe(&publ->subscr,
262 msg_orignode(msg),
263 publ,
264 (net_ev_handler)node_is_down);
265 }
266 } else if (msg_type(msg) == WITHDRAWAL) {
267 dbg("named_recv: got withdrawl for %u, %u, %u\n",
268 ntohl(item->type), ntohl(item->lower),
269 ntohl(item->upper));
270 publ = nametbl_remove_publ(ntohl(item->type),
271 ntohl(item->lower),
272 msg_orignode(msg),
273 ntohl(item->ref),
274 ntohl(item->key));
275
276 if (publ) {
277 nodesub_unsubscribe(&publ->subscr);
278 kfree(publ);
279 }
280 } else {
281 warn("named_recv: unknown msg\n");
282 }
283 item++;
284 }
285 write_unlock_bh(&nametbl_lock);
286 buf_discard(buf);
287}
288
289/**
290 * named_reinit - re-initialize local publication list
291 *
292 * This routine is called whenever TIPC networking is (re)enabled.
293 * All existing publications by this node that have "cluster" or "zone" scope
294 * are updated to reflect the node's current network address.
295 * (If the node's address is unchanged, the update loop terminates immediately.)
296 */
297
298void named_reinit(void)
299{
300 struct publication *publ;
301
302 write_lock_bh(&nametbl_lock);
303 list_for_each_entry(publ, &publ_root, local_list) {
304 if (publ->node == tipc_own_addr)
305 break;
306 publ->node = tipc_own_addr;
307 }
308 write_unlock_bh(&nametbl_lock);
309}
diff --git a/net/tipc/name_distr.h b/net/tipc/name_distr.h
new file mode 100644
index 000000000000..a04bdeac84ea
--- /dev/null
+++ b/net/tipc/name_distr.h
@@ -0,0 +1,48 @@
1/*
2 * net/tipc/name_distr.h: Include file for TIPC name distribution code
3 *
4 * Copyright (c) 2000-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#ifndef _TIPC_NAME_DISTR_H
38#define _TIPC_NAME_DISTR_H
39
40#include "name_table.h"
41
42void named_publish(struct publication *publ);
43void named_withdraw(struct publication *publ);
44void named_node_up(unsigned long node);
45void named_recv(struct sk_buff *buf);
46void named_reinit(void);
47
48#endif
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c
new file mode 100644
index 000000000000..972c83eb83b4
--- /dev/null
+++ b/net/tipc/name_table.c
@@ -0,0 +1,1079 @@
1/*
2 * net/tipc/name_table.c: TIPC name table code
3 *
4 * Copyright (c) 2000-2006, Ericsson AB
5 * Copyright (c) 2004-2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include "core.h"
38#include "config.h"
39#include "dbg.h"
40#include "name_table.h"
41#include "name_distr.h"
42#include "addr.h"
43#include "node_subscr.h"
44#include "subscr.h"
45#include "port.h"
46#include "cluster.h"
47#include "bcast.h"
48
49int tipc_nametbl_size = 1024; /* must be a power of 2 */
50
51/**
52 * struct sub_seq - container for all published instances of a name sequence
53 * @lower: name sequence lower bound
54 * @upper: name sequence upper bound
55 * @node_list: circular list of matching publications with >= node scope
56 * @cluster_list: circular list of matching publications with >= cluster scope
57 * @zone_list: circular list of matching publications with >= zone scope
58 */
59
60struct sub_seq {
61 u32 lower;
62 u32 upper;
63 struct publication *node_list;
64 struct publication *cluster_list;
65 struct publication *zone_list;
66};
67
68/**
69 * struct name_seq - container for all published instances of a name type
70 * @type: 32 bit 'type' value for name sequence
71 * @sseq: pointer to dynamically-sized array of sub-sequences of this 'type';
72 * sub-sequences are sorted in ascending order
73 * @alloc: number of sub-sequences currently in array
74 * @first_free: upper bound of highest sub-sequence + 1
75 * @ns_list: links to adjacent name sequences in hash chain
76 * @subscriptions: list of subscriptions for this 'type'
77 * @lock: spinlock controlling access to name sequence structure
78 */
79
80struct name_seq {
81 u32 type;
82 struct sub_seq *sseqs;
83 u32 alloc;
84 u32 first_free;
85 struct hlist_node ns_list;
86 struct list_head subscriptions;
87 spinlock_t lock;
88};
89
90/**
91 * struct name_table - table containing all existing port name publications
92 * @types: pointer to fixed-sized array of name sequence lists,
93 * accessed via hashing on 'type'; name sequence lists are *not* sorted
94 * @local_publ_count: number of publications issued by this node
95 */
96
97struct name_table {
98 struct hlist_head *types;
99 u32 local_publ_count;
100};
101
102struct name_table table = { NULL } ;
103static atomic_t rsv_publ_ok = ATOMIC_INIT(0);
104rwlock_t nametbl_lock = RW_LOCK_UNLOCKED;
105
106
107static inline int hash(int x)
108{
109 return(x & (tipc_nametbl_size - 1));
110}
111
112/**
113 * publ_create - create a publication structure
114 */
115
116static struct publication *publ_create(u32 type, u32 lower, u32 upper,
117 u32 scope, u32 node, u32 port_ref,
118 u32 key)
119{
120 struct publication *publ =
121 (struct publication *)kmalloc(sizeof(*publ), GFP_ATOMIC);
122 if (publ == NULL) {
123 warn("Memory squeeze; failed to create publication\n");
124 return 0;
125 }
126
127 memset(publ, 0, sizeof(*publ));
128 publ->type = type;
129 publ->lower = lower;
130 publ->upper = upper;
131 publ->scope = scope;
132 publ->node = node;
133 publ->ref = port_ref;
134 publ->key = key;
135 INIT_LIST_HEAD(&publ->local_list);
136 INIT_LIST_HEAD(&publ->pport_list);
137 INIT_LIST_HEAD(&publ->subscr.nodesub_list);
138 return publ;
139}
140
141/**
142 * subseq_alloc - allocate a specified number of sub-sequence structures
143 */
144
145struct sub_seq *subseq_alloc(u32 cnt)
146{
147 u32 sz = cnt * sizeof(struct sub_seq);
148 struct sub_seq *sseq = (struct sub_seq *)kmalloc(sz, GFP_ATOMIC);
149
150 if (sseq)
151 memset(sseq, 0, sz);
152 return sseq;
153}
154
155/**
156 * nameseq_create - create a name sequence structure for the specified 'type'
157 *
158 * Allocates a single sub-sequence structure and sets it to all 0's.
159 */
160
161struct name_seq *nameseq_create(u32 type, struct hlist_head *seq_head)
162{
163 struct name_seq *nseq =
164 (struct name_seq *)kmalloc(sizeof(*nseq), GFP_ATOMIC);
165 struct sub_seq *sseq = subseq_alloc(1);
166
167 if (!nseq || !sseq) {
168 warn("Memory squeeze; failed to create name sequence\n");
169 kfree(nseq);
170 kfree(sseq);
171 return 0;
172 }
173
174 memset(nseq, 0, sizeof(*nseq));
175 nseq->lock = SPIN_LOCK_UNLOCKED;
176 nseq->type = type;
177 nseq->sseqs = sseq;
178 dbg("nameseq_create() nseq = %x type %u, ssseqs %x, ff: %u\n",
179 nseq, type, nseq->sseqs, nseq->first_free);
180 nseq->alloc = 1;
181 INIT_HLIST_NODE(&nseq->ns_list);
182 INIT_LIST_HEAD(&nseq->subscriptions);
183 hlist_add_head(&nseq->ns_list, seq_head);
184 return nseq;
185}
186
187/**
188 * nameseq_find_subseq - find sub-sequence (if any) matching a name instance
189 *
190 * Very time-critical, so binary searches through sub-sequence array.
191 */
192
193static inline struct sub_seq *nameseq_find_subseq(struct name_seq *nseq,
194 u32 instance)
195{
196 struct sub_seq *sseqs = nseq->sseqs;
197 int low = 0;
198 int high = nseq->first_free - 1;
199 int mid;
200
201 while (low <= high) {
202 mid = (low + high) / 2;
203 if (instance < sseqs[mid].lower)
204 high = mid - 1;
205 else if (instance > sseqs[mid].upper)
206 low = mid + 1;
207 else
208 return &sseqs[mid];
209 }
210 return 0;
211}
212
213/**
214 * nameseq_locate_subseq - determine position of name instance in sub-sequence
215 *
216 * Returns index in sub-sequence array of the entry that contains the specified
217 * instance value; if no entry contains that value, returns the position
218 * where a new entry for it would be inserted in the array.
219 *
220 * Note: Similar to binary search code for locating a sub-sequence.
221 */
222
223static u32 nameseq_locate_subseq(struct name_seq *nseq, u32 instance)
224{
225 struct sub_seq *sseqs = nseq->sseqs;
226 int low = 0;
227 int high = nseq->first_free - 1;
228 int mid;
229
230 while (low <= high) {
231 mid = (low + high) / 2;
232 if (instance < sseqs[mid].lower)
233 high = mid - 1;
234 else if (instance > sseqs[mid].upper)
235 low = mid + 1;
236 else
237 return mid;
238 }
239 return low;
240}
241
242/**
243 * nameseq_insert_publ -
244 */
245
246struct publication *nameseq_insert_publ(struct name_seq *nseq,
247 u32 type, u32 lower, u32 upper,
248 u32 scope, u32 node, u32 port, u32 key)
249{
250 struct subscription *s;
251 struct subscription *st;
252 struct publication *publ;
253 struct sub_seq *sseq;
254 int created_subseq = 0;
255
256 assert(nseq->first_free <= nseq->alloc);
257 sseq = nameseq_find_subseq(nseq, lower);
258 dbg("nameseq_ins: for seq %x,<%u,%u>, found sseq %x\n",
259 nseq, type, lower, sseq);
260 if (sseq) {
261
262 /* Lower end overlaps existing entry => need an exact match */
263
264 if ((sseq->lower != lower) || (sseq->upper != upper)) {
265 warn("Overlapping publ <%u,%u,%u>\n", type, lower, upper);
266 return 0;
267 }
268 } else {
269 u32 inspos;
270 struct sub_seq *freesseq;
271
272 /* Find where lower end should be inserted */
273
274 inspos = nameseq_locate_subseq(nseq, lower);
275
276 /* Fail if upper end overlaps into an existing entry */
277
278 if ((inspos < nseq->first_free) &&
279 (upper >= nseq->sseqs[inspos].lower)) {
280 warn("Overlapping publ <%u,%u,%u>\n", type, lower, upper);
281 return 0;
282 }
283
284 /* Ensure there is space for new sub-sequence */
285
286 if (nseq->first_free == nseq->alloc) {
287 struct sub_seq *sseqs = nseq->sseqs;
288 nseq->sseqs = subseq_alloc(nseq->alloc * 2);
289 if (nseq->sseqs != NULL) {
290 memcpy(nseq->sseqs, sseqs,
291 nseq->alloc * sizeof (struct sub_seq));
292 kfree(sseqs);
293 dbg("Allocated %u sseqs\n", nseq->alloc);
294 nseq->alloc *= 2;
295 } else {
296 warn("Memory squeeze; failed to create sub-sequence\n");
297 return 0;
298 }
299 }
300 dbg("Have %u sseqs for type %u\n", nseq->alloc, type);
301
302 /* Insert new sub-sequence */
303
304 dbg("ins in pos %u, ff = %u\n", inspos, nseq->first_free);
305 sseq = &nseq->sseqs[inspos];
306 freesseq = &nseq->sseqs[nseq->first_free];
307 memmove(sseq + 1, sseq, (freesseq - sseq) * sizeof (*sseq));
308 memset(sseq, 0, sizeof (*sseq));
309 nseq->first_free++;
310 sseq->lower = lower;
311 sseq->upper = upper;
312 created_subseq = 1;
313 }
314 dbg("inserting (%u %u %u) from %x:%u into sseq %x(%u,%u) of seq %x\n",
315 type, lower, upper, node, port, sseq,
316 sseq->lower, sseq->upper, nseq);
317
318 /* Insert a publication: */
319
320 publ = publ_create(type, lower, upper, scope, node, port, key);
321 if (!publ)
322 return 0;
323 dbg("inserting publ %x, node=%x publ->node=%x, subscr->node=%x\n",
324 publ, node, publ->node, publ->subscr.node);
325
326 if (!sseq->zone_list)
327 sseq->zone_list = publ->zone_list_next = publ;
328 else {
329 publ->zone_list_next = sseq->zone_list->zone_list_next;
330 sseq->zone_list->zone_list_next = publ;
331 }
332
333 if (in_own_cluster(node)) {
334 if (!sseq->cluster_list)
335 sseq->cluster_list = publ->cluster_list_next = publ;
336 else {
337 publ->cluster_list_next =
338 sseq->cluster_list->cluster_list_next;
339 sseq->cluster_list->cluster_list_next = publ;
340 }
341 }
342
343 if (node == tipc_own_addr) {
344 if (!sseq->node_list)
345 sseq->node_list = publ->node_list_next = publ;
346 else {
347 publ->node_list_next = sseq->node_list->node_list_next;
348 sseq->node_list->node_list_next = publ;
349 }
350 }
351
352 /*
353 * Any subscriptions waiting for notification?
354 */
355 list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) {
356 dbg("calling report_overlap()\n");
357 subscr_report_overlap(s,
358 publ->lower,
359 publ->upper,
360 TIPC_PUBLISHED,
361 publ->ref,
362 publ->node,
363 created_subseq);
364 }
365 return publ;
366}
367
368/**
369 * nameseq_remove_publ -
370 */
371
372struct publication *nameseq_remove_publ(struct name_seq *nseq, u32 inst,
373 u32 node, u32 ref, u32 key)
374{
375 struct publication *publ;
376 struct publication *prev;
377 struct sub_seq *sseq = nameseq_find_subseq(nseq, inst);
378 struct sub_seq *free;
379 struct subscription *s, *st;
380 int removed_subseq = 0;
381
382 assert(nseq);
383
384 if (!sseq) {
385 int i;
386
387 warn("Withdraw unknown <%u,%u>?\n", nseq->type, inst);
388 assert(nseq->sseqs);
389 dbg("Dumping subseqs %x for %x, alloc = %u,ff=%u\n",
390 nseq->sseqs, nseq, nseq->alloc,
391 nseq->first_free);
392 for (i = 0; i < nseq->first_free; i++) {
393 dbg("Subseq %u(%x): lower = %u,upper = %u\n",
394 i, &nseq->sseqs[i], nseq->sseqs[i].lower,
395 nseq->sseqs[i].upper);
396 }
397 return 0;
398 }
399 dbg("nameseq_remove: seq: %x, sseq %x, <%u,%u> key %u\n",
400 nseq, sseq, nseq->type, inst, key);
401
402 prev = sseq->zone_list;
403 publ = sseq->zone_list->zone_list_next;
404 while ((publ->key != key) || (publ->ref != ref) ||
405 (publ->node && (publ->node != node))) {
406 prev = publ;
407 publ = publ->zone_list_next;
408 assert(prev != sseq->zone_list);
409 }
410 if (publ != sseq->zone_list)
411 prev->zone_list_next = publ->zone_list_next;
412 else if (publ->zone_list_next != publ) {
413 prev->zone_list_next = publ->zone_list_next;
414 sseq->zone_list = publ->zone_list_next;
415 } else {
416 sseq->zone_list = 0;
417 }
418
419 if (in_own_cluster(node)) {
420 prev = sseq->cluster_list;
421 publ = sseq->cluster_list->cluster_list_next;
422 while ((publ->key != key) || (publ->ref != ref) ||
423 (publ->node && (publ->node != node))) {
424 prev = publ;
425 publ = publ->cluster_list_next;
426 assert(prev != sseq->cluster_list);
427 }
428 if (publ != sseq->cluster_list)
429 prev->cluster_list_next = publ->cluster_list_next;
430 else if (publ->cluster_list_next != publ) {
431 prev->cluster_list_next = publ->cluster_list_next;
432 sseq->cluster_list = publ->cluster_list_next;
433 } else {
434 sseq->cluster_list = 0;
435 }
436 }
437
438 if (node == tipc_own_addr) {
439 prev = sseq->node_list;
440 publ = sseq->node_list->node_list_next;
441 while ((publ->key != key) || (publ->ref != ref) ||
442 (publ->node && (publ->node != node))) {
443 prev = publ;
444 publ = publ->node_list_next;
445 assert(prev != sseq->node_list);
446 }
447 if (publ != sseq->node_list)
448 prev->node_list_next = publ->node_list_next;
449 else if (publ->node_list_next != publ) {
450 prev->node_list_next = publ->node_list_next;
451 sseq->node_list = publ->node_list_next;
452 } else {
453 sseq->node_list = 0;
454 }
455 }
456 assert(!publ->node || (publ->node == node));
457 assert(publ->ref == ref);
458 assert(publ->key == key);
459
460 /*
461 * Contract subseq list if no more publications:
462 */
463 if (!sseq->node_list && !sseq->cluster_list && !sseq->zone_list) {
464 free = &nseq->sseqs[nseq->first_free--];
465 memmove(sseq, sseq + 1, (free - (sseq + 1)) * sizeof (*sseq));
466 removed_subseq = 1;
467 }
468
469 /*
470 * Any subscriptions waiting ?
471 */
472 list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) {
473 subscr_report_overlap(s,
474 publ->lower,
475 publ->upper,
476 TIPC_WITHDRAWN,
477 publ->ref,
478 publ->node,
479 removed_subseq);
480 }
481 return publ;
482}
483
484/**
485 * nameseq_subscribe: attach a subscription, and issue
486 * the prescribed number of events if there is any sub-
487 * sequence overlapping with the requested sequence
488 */
489
490void nameseq_subscribe(struct name_seq *nseq, struct subscription *s)
491{
492 struct sub_seq *sseq = nseq->sseqs;
493
494 list_add(&s->nameseq_list, &nseq->subscriptions);
495
496 if (!sseq)
497 return;
498
499 while (sseq != &nseq->sseqs[nseq->first_free]) {
500 struct publication *zl = sseq->zone_list;
501 if (zl && subscr_overlap(s,sseq->lower,sseq->upper)) {
502 struct publication *crs = zl;
503 int must_report = 1;
504
505 do {
506 subscr_report_overlap(s,
507 sseq->lower,
508 sseq->upper,
509 TIPC_PUBLISHED,
510 crs->ref,
511 crs->node,
512 must_report);
513 must_report = 0;
514 crs = crs->zone_list_next;
515 } while (crs != zl);
516 }
517 sseq++;
518 }
519}
520
521static struct name_seq *nametbl_find_seq(u32 type)
522{
523 struct hlist_head *seq_head;
524 struct hlist_node *seq_node;
525 struct name_seq *ns;
526
527 dbg("find_seq %u,(%u,0x%x) table = %p, hash[type] = %u\n",
528 type, ntohl(type), type, table.types, hash(type));
529
530 seq_head = &table.types[hash(type)];
531 hlist_for_each_entry(ns, seq_node, seq_head, ns_list) {
532 if (ns->type == type) {
533 dbg("found %x\n", ns);
534 return ns;
535 }
536 }
537
538 return 0;
539};
540
541struct publication *nametbl_insert_publ(u32 type, u32 lower, u32 upper,
542 u32 scope, u32 node, u32 port, u32 key)
543{
544 struct name_seq *seq = nametbl_find_seq(type);
545
546 dbg("ins_publ: <%u,%x,%x> found %x\n", type, lower, upper, seq);
547 if (lower > upper) {
548 warn("Failed to publish illegal <%u,%u,%u>\n",
549 type, lower, upper);
550 return 0;
551 }
552
553 dbg("Publishing <%u,%u,%u> from %x\n", type, lower, upper, node);
554 if (!seq) {
555 seq = nameseq_create(type, &table.types[hash(type)]);
556 dbg("nametbl_insert_publ: created %x\n", seq);
557 }
558 if (!seq)
559 return 0;
560
561 assert(seq->type == type);
562 return nameseq_insert_publ(seq, type, lower, upper,
563 scope, node, port, key);
564}
565
566struct publication *nametbl_remove_publ(u32 type, u32 lower,
567 u32 node, u32 ref, u32 key)
568{
569 struct publication *publ;
570 struct name_seq *seq = nametbl_find_seq(type);
571
572 if (!seq)
573 return 0;
574
575 dbg("Withdrawing <%u,%u> from %x\n", type, lower, node);
576 publ = nameseq_remove_publ(seq, lower, node, ref, key);
577
578 if (!seq->first_free && list_empty(&seq->subscriptions)) {
579 hlist_del_init(&seq->ns_list);
580 kfree(seq->sseqs);
581 kfree(seq);
582 }
583 return publ;
584}
585
586/*
587 * nametbl_translate(): Translate tipc_name -> tipc_portid.
588 * Very time-critical.
589 *
590 * Note: on entry 'destnode' is the search domain used during translation;
591 * on exit it passes back the node address of the matching port (if any)
592 */
593
594u32 nametbl_translate(u32 type, u32 instance, u32 *destnode)
595{
596 struct sub_seq *sseq;
597 struct publication *publ = 0;
598 struct name_seq *seq;
599 u32 ref;
600
601 if (!in_scope(*destnode, tipc_own_addr))
602 return 0;
603
604 read_lock_bh(&nametbl_lock);
605 seq = nametbl_find_seq(type);
606 if (unlikely(!seq))
607 goto not_found;
608 sseq = nameseq_find_subseq(seq, instance);
609 if (unlikely(!sseq))
610 goto not_found;
611 spin_lock_bh(&seq->lock);
612
613 /* Closest-First Algorithm: */
614 if (likely(!*destnode)) {
615 publ = sseq->node_list;
616 if (publ) {
617 sseq->node_list = publ->node_list_next;
618found:
619 ref = publ->ref;
620 *destnode = publ->node;
621 spin_unlock_bh(&seq->lock);
622 read_unlock_bh(&nametbl_lock);
623 return ref;
624 }
625 publ = sseq->cluster_list;
626 if (publ) {
627 sseq->cluster_list = publ->cluster_list_next;
628 goto found;
629 }
630 publ = sseq->zone_list;
631 if (publ) {
632 sseq->zone_list = publ->zone_list_next;
633 goto found;
634 }
635 }
636
637 /* Round-Robin Algorithm: */
638 else if (*destnode == tipc_own_addr) {
639 publ = sseq->node_list;
640 if (publ) {
641 sseq->node_list = publ->node_list_next;
642 goto found;
643 }
644 } else if (in_own_cluster(*destnode)) {
645 publ = sseq->cluster_list;
646 if (publ) {
647 sseq->cluster_list = publ->cluster_list_next;
648 goto found;
649 }
650 } else {
651 publ = sseq->zone_list;
652 if (publ) {
653 sseq->zone_list = publ->zone_list_next;
654 goto found;
655 }
656 }
657 spin_unlock_bh(&seq->lock);
658not_found:
659 *destnode = 0;
660 read_unlock_bh(&nametbl_lock);
661 return 0;
662}
663
664/**
665 * nametbl_mc_translate - find multicast destinations
666 *
667 * Creates list of all local ports that overlap the given multicast address;
668 * also determines if any off-node ports overlap.
669 *
670 * Note: Publications with a scope narrower than 'limit' are ignored.
671 * (i.e. local node-scope publications mustn't receive messages arriving
672 * from another node, even if the multcast link brought it here)
673 *
674 * Returns non-zero if any off-node ports overlap
675 */
676
677int nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit,
678 struct port_list *dports)
679{
680 struct name_seq *seq;
681 struct sub_seq *sseq;
682 struct sub_seq *sseq_stop;
683 int res = 0;
684
685 read_lock_bh(&nametbl_lock);
686 seq = nametbl_find_seq(type);
687 if (!seq)
688 goto exit;
689
690 spin_lock_bh(&seq->lock);
691
692 sseq = seq->sseqs + nameseq_locate_subseq(seq, lower);
693 sseq_stop = seq->sseqs + seq->first_free;
694 for (; sseq != sseq_stop; sseq++) {
695 struct publication *publ;
696
697 if (sseq->lower > upper)
698 break;
699 publ = sseq->cluster_list;
700 if (publ && (publ->scope <= limit))
701 do {
702 if (publ->node == tipc_own_addr)
703 port_list_add(dports, publ->ref);
704 else
705 res = 1;
706 publ = publ->cluster_list_next;
707 } while (publ != sseq->cluster_list);
708 }
709
710 spin_unlock_bh(&seq->lock);
711exit:
712 read_unlock_bh(&nametbl_lock);
713 return res;
714}
715
716/**
717 * nametbl_publish_rsv - publish port name using a reserved name type
718 */
719
720int nametbl_publish_rsv(u32 ref, unsigned int scope,
721 struct tipc_name_seq const *seq)
722{
723 int res;
724
725 atomic_inc(&rsv_publ_ok);
726 res = tipc_publish(ref, scope, seq);
727 atomic_dec(&rsv_publ_ok);
728 return res;
729}
730
731/**
732 * nametbl_publish - add name publication to network name tables
733 */
734
735struct publication *nametbl_publish(u32 type, u32 lower, u32 upper,
736 u32 scope, u32 port_ref, u32 key)
737{
738 struct publication *publ;
739
740 if (table.local_publ_count >= tipc_max_publications) {
741 warn("Failed publish: max %u local publication\n",
742 tipc_max_publications);
743 return 0;
744 }
745 if ((type < TIPC_RESERVED_TYPES) && !atomic_read(&rsv_publ_ok)) {
746 warn("Failed to publish reserved name <%u,%u,%u>\n",
747 type, lower, upper);
748 return 0;
749 }
750
751 write_lock_bh(&nametbl_lock);
752 table.local_publ_count++;
753 publ = nametbl_insert_publ(type, lower, upper, scope,
754 tipc_own_addr, port_ref, key);
755 if (publ && (scope != TIPC_NODE_SCOPE)) {
756 named_publish(publ);
757 }
758 write_unlock_bh(&nametbl_lock);
759 return publ;
760}
761
762/**
763 * nametbl_withdraw - withdraw name publication from network name tables
764 */
765
766int nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key)
767{
768 struct publication *publ;
769
770 dbg("nametbl_withdraw:<%d,%d,%d>\n", type, lower, key);
771 write_lock_bh(&nametbl_lock);
772 publ = nametbl_remove_publ(type, lower, tipc_own_addr, ref, key);
773 if (publ) {
774 table.local_publ_count--;
775 if (publ->scope != TIPC_NODE_SCOPE)
776 named_withdraw(publ);
777 write_unlock_bh(&nametbl_lock);
778 list_del_init(&publ->pport_list);
779 kfree(publ);
780 return 1;
781 }
782 write_unlock_bh(&nametbl_lock);
783 return 0;
784}
785
786/**
787 * nametbl_subscribe - add a subscription object to the name table
788 */
789
790void
791nametbl_subscribe(struct subscription *s)
792{
793 u32 type = s->seq.type;
794 struct name_seq *seq;
795
796 write_lock_bh(&nametbl_lock);
797 seq = nametbl_find_seq(type);
798 if (!seq) {
799 seq = nameseq_create(type, &table.types[hash(type)]);
800 }
801 if (seq){
802 spin_lock_bh(&seq->lock);
803 dbg("nametbl_subscribe:found %x for <%u,%u,%u>\n",
804 seq, type, s->seq.lower, s->seq.upper);
805 assert(seq->type == type);
806 nameseq_subscribe(seq, s);
807 spin_unlock_bh(&seq->lock);
808 }
809 write_unlock_bh(&nametbl_lock);
810}
811
812/**
813 * nametbl_unsubscribe - remove a subscription object from name table
814 */
815
816void
817nametbl_unsubscribe(struct subscription *s)
818{
819 struct name_seq *seq;
820
821 write_lock_bh(&nametbl_lock);
822 seq = nametbl_find_seq(s->seq.type);
823 if (seq != NULL){
824 spin_lock_bh(&seq->lock);
825 list_del_init(&s->nameseq_list);
826 spin_unlock_bh(&seq->lock);
827 if ((seq->first_free == 0) && list_empty(&seq->subscriptions)) {
828 hlist_del_init(&seq->ns_list);
829 kfree(seq->sseqs);
830 kfree(seq);
831 }
832 }
833 write_unlock_bh(&nametbl_lock);
834}
835
836
837/**
838 * subseq_list: print specified sub-sequence contents into the given buffer
839 */
840
841static void subseq_list(struct sub_seq *sseq, struct print_buf *buf, u32 depth,
842 u32 index)
843{
844 char portIdStr[27];
845 char *scopeStr;
846 struct publication *publ = sseq->zone_list;
847
848 tipc_printf(buf, "%-10u %-10u ", sseq->lower, sseq->upper);
849
850 if (depth == 2 || !publ) {
851 tipc_printf(buf, "\n");
852 return;
853 }
854
855 do {
856 sprintf (portIdStr, "<%u.%u.%u:%u>",
857 tipc_zone(publ->node), tipc_cluster(publ->node),
858 tipc_node(publ->node), publ->ref);
859 tipc_printf(buf, "%-26s ", portIdStr);
860 if (depth > 3) {
861 if (publ->node != tipc_own_addr)
862 scopeStr = "";
863 else if (publ->scope == TIPC_NODE_SCOPE)
864 scopeStr = "node";
865 else if (publ->scope == TIPC_CLUSTER_SCOPE)
866 scopeStr = "cluster";
867 else
868 scopeStr = "zone";
869 tipc_printf(buf, "%-10u %s", publ->key, scopeStr);
870 }
871
872 publ = publ->zone_list_next;
873 if (publ == sseq->zone_list)
874 break;
875
876 tipc_printf(buf, "\n%33s", " ");
877 } while (1);
878
879 tipc_printf(buf, "\n");
880}
881
882/**
883 * nameseq_list: print specified name sequence contents into the given buffer
884 */
885
886static void nameseq_list(struct name_seq *seq, struct print_buf *buf, u32 depth,
887 u32 type, u32 lowbound, u32 upbound, u32 index)
888{
889 struct sub_seq *sseq;
890 char typearea[11];
891
892 sprintf(typearea, "%-10u", seq->type);
893
894 if (depth == 1) {
895 tipc_printf(buf, "%s\n", typearea);
896 return;
897 }
898
899 for (sseq = seq->sseqs; sseq != &seq->sseqs[seq->first_free]; sseq++) {
900 if ((lowbound <= sseq->upper) && (upbound >= sseq->lower)) {
901 tipc_printf(buf, "%s ", typearea);
902 subseq_list(sseq, buf, depth, index);
903 sprintf(typearea, "%10s", " ");
904 }
905 }
906}
907
908/**
909 * nametbl_header - print name table header into the given buffer
910 */
911
912static void nametbl_header(struct print_buf *buf, u32 depth)
913{
914 tipc_printf(buf, "Type ");
915
916 if (depth > 1)
917 tipc_printf(buf, "Lower Upper ");
918 if (depth > 2)
919 tipc_printf(buf, "Port Identity ");
920 if (depth > 3)
921 tipc_printf(buf, "Publication");
922
923 tipc_printf(buf, "\n-----------");
924
925 if (depth > 1)
926 tipc_printf(buf, "--------------------- ");
927 if (depth > 2)
928 tipc_printf(buf, "-------------------------- ");
929 if (depth > 3)
930 tipc_printf(buf, "------------------");
931
932 tipc_printf(buf, "\n");
933}
934
935/**
936 * nametbl_list - print specified name table contents into the given buffer
937 */
938
939static void nametbl_list(struct print_buf *buf, u32 depth_info,
940 u32 type, u32 lowbound, u32 upbound)
941{
942 struct hlist_head *seq_head;
943 struct hlist_node *seq_node;
944 struct name_seq *seq;
945 int all_types;
946 u32 depth;
947 u32 i;
948
949 all_types = (depth_info & TIPC_NTQ_ALLTYPES);
950 depth = (depth_info & ~TIPC_NTQ_ALLTYPES);
951
952 if (depth == 0)
953 return;
954
955 if (all_types) {
956 /* display all entries in name table to specified depth */
957 nametbl_header(buf, depth);
958 lowbound = 0;
959 upbound = ~0;
960 for (i = 0; i < tipc_nametbl_size; i++) {
961 seq_head = &table.types[i];
962 hlist_for_each_entry(seq, seq_node, seq_head, ns_list) {
963 nameseq_list(seq, buf, depth, seq->type,
964 lowbound, upbound, i);
965 }
966 }
967 } else {
968 /* display only the sequence that matches the specified type */
969 if (upbound < lowbound) {
970 tipc_printf(buf, "invalid name sequence specified\n");
971 return;
972 }
973 nametbl_header(buf, depth);
974 i = hash(type);
975 seq_head = &table.types[i];
976 hlist_for_each_entry(seq, seq_node, seq_head, ns_list) {
977 if (seq->type == type) {
978 nameseq_list(seq, buf, depth, type,
979 lowbound, upbound, i);
980 break;
981 }
982 }
983 }
984}
985
986void nametbl_print(struct print_buf *buf, const char *str)
987{
988 tipc_printf(buf, str);
989 read_lock_bh(&nametbl_lock);
990 nametbl_list(buf, 0, 0, 0, 0);
991 read_unlock_bh(&nametbl_lock);
992}
993
994#define MAX_NAME_TBL_QUERY 32768
995
996struct sk_buff *nametbl_get(const void *req_tlv_area, int req_tlv_space)
997{
998 struct sk_buff *buf;
999 struct tipc_name_table_query *argv;
1000 struct tlv_desc *rep_tlv;
1001 struct print_buf b;
1002 int str_len;
1003
1004 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NAME_TBL_QUERY))
1005 return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
1006
1007 buf = cfg_reply_alloc(TLV_SPACE(MAX_NAME_TBL_QUERY));
1008 if (!buf)
1009 return NULL;
1010
1011 rep_tlv = (struct tlv_desc *)buf->data;
1012 printbuf_init(&b, TLV_DATA(rep_tlv), MAX_NAME_TBL_QUERY);
1013 argv = (struct tipc_name_table_query *)TLV_DATA(req_tlv_area);
1014 read_lock_bh(&nametbl_lock);
1015 nametbl_list(&b, ntohl(argv->depth), ntohl(argv->type),
1016 ntohl(argv->lowbound), ntohl(argv->upbound));
1017 read_unlock_bh(&nametbl_lock);
1018 str_len = printbuf_validate(&b);
1019
1020 skb_put(buf, TLV_SPACE(str_len));
1021 TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
1022
1023 return buf;
1024}
1025
1026void nametbl_dump(void)
1027{
1028 nametbl_list(CONS, 0, 0, 0, 0);
1029}
1030
1031int nametbl_init(void)
1032{
1033 int array_size = sizeof(struct hlist_head) * tipc_nametbl_size;
1034
1035 table.types = (struct hlist_head *)kmalloc(array_size, GFP_ATOMIC);
1036 if (!table.types)
1037 return -ENOMEM;
1038
1039 write_lock_bh(&nametbl_lock);
1040 memset(table.types, 0, array_size);
1041 table.local_publ_count = 0;
1042 write_unlock_bh(&nametbl_lock);
1043 return 0;
1044}
1045
1046void nametbl_stop(void)
1047{
1048 struct hlist_head *seq_head;
1049 struct hlist_node *seq_node;
1050 struct hlist_node *tmp;
1051 struct name_seq *seq;
1052 u32 i;
1053
1054 if (!table.types)
1055 return;
1056
1057 write_lock_bh(&nametbl_lock);
1058 for (i = 0; i < tipc_nametbl_size; i++) {
1059 seq_head = &table.types[i];
1060 hlist_for_each_entry_safe(seq, seq_node, tmp, seq_head, ns_list) {
1061 struct sub_seq *sseq = seq->sseqs;
1062
1063 for (; sseq != &seq->sseqs[seq->first_free]; sseq++) {
1064 struct publication *publ = sseq->zone_list;
1065 assert(publ);
1066 do {
1067 struct publication *next =
1068 publ->zone_list_next;
1069 kfree(publ);
1070 publ = next;
1071 }
1072 while (publ != sseq->zone_list);
1073 }
1074 }
1075 }
1076 kfree(table.types);
1077 table.types = NULL;
1078 write_unlock_bh(&nametbl_lock);
1079}
diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h
new file mode 100644
index 000000000000..f82693384f60
--- /dev/null
+++ b/net/tipc/name_table.h
@@ -0,0 +1,108 @@
1/*
2 * net/tipc/name_table.h: Include file for TIPC name table code
3 *
4 * Copyright (c) 2000-2006, Ericsson AB
5 * Copyright (c) 2004-2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#ifndef _TIPC_NAME_TABLE_H
38#define _TIPC_NAME_TABLE_H
39
40#include "node_subscr.h"
41
42struct subscription;
43struct port_list;
44
45/*
46 * TIPC name types reserved for internal TIPC use (both current and planned)
47 */
48
49#define TIPC_ZM_SRV 3 /* zone master service name type */
50
51
52/**
53 * struct publication - info about a published (name or) name sequence
54 * @type: name sequence type
55 * @lower: name sequence lower bound
56 * @upper: name sequence upper bound
57 * @scope: scope of publication
58 * @node: network address of publishing port's node
59 * @ref: publishing port
60 * @key: publication key
61 * @subscr: subscription to "node down" event (for off-node publications only)
62 * @local_list: adjacent entries in list of publications made by this node
63 * @pport_list: adjacent entries in list of publications made by this port
64 * @node_list: next matching name seq publication with >= node scope
65 * @cluster_list: next matching name seq publication with >= cluster scope
66 * @zone_list: next matching name seq publication with >= zone scope
67 *
68 * Note that the node list, cluster list, and zone list are circular lists.
69 */
70
71struct publication {
72 u32 type;
73 u32 lower;
74 u32 upper;
75 u32 scope;
76 u32 node;
77 u32 ref;
78 u32 key;
79 struct node_subscr subscr;
80 struct list_head local_list;
81 struct list_head pport_list;
82 struct publication *node_list_next;
83 struct publication *cluster_list_next;
84 struct publication *zone_list_next;
85};
86
87
88extern rwlock_t nametbl_lock;
89
90struct sk_buff *nametbl_get(const void *req_tlv_area, int req_tlv_space);
91u32 nametbl_translate(u32 type, u32 instance, u32 *node);
92int nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit,
93 struct port_list *dports);
94int nametbl_publish_rsv(u32 ref, unsigned int scope,
95 struct tipc_name_seq const *seq);
96struct publication *nametbl_publish(u32 type, u32 lower, u32 upper,
97 u32 scope, u32 port_ref, u32 key);
98int nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key);
99struct publication *nametbl_insert_publ(u32 type, u32 lower, u32 upper,
100 u32 scope, u32 node, u32 ref, u32 key);
101struct publication *nametbl_remove_publ(u32 type, u32 lower,
102 u32 node, u32 ref, u32 key);
103void nametbl_subscribe(struct subscription *s);
104void nametbl_unsubscribe(struct subscription *s);
105int nametbl_init(void);
106void nametbl_stop(void);
107
108#endif
diff --git a/net/tipc/net.c b/net/tipc/net.c
new file mode 100644
index 000000000000..6826b493c1d6
--- /dev/null
+++ b/net/tipc/net.c
@@ -0,0 +1,311 @@
1/*
2 * net/tipc/net.c: TIPC network routing code
3 *
4 * Copyright (c) 1995-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include "core.h"
38#include "bearer.h"
39#include "net.h"
40#include "zone.h"
41#include "addr.h"
42#include "name_table.h"
43#include "name_distr.h"
44#include "subscr.h"
45#include "link.h"
46#include "msg.h"
47#include "port.h"
48#include "bcast.h"
49#include "discover.h"
50#include "config.h"
51
52/*
53 * The TIPC locking policy is designed to ensure a very fine locking
54 * granularity, permitting complete parallel access to individual
55 * port and node/link instances. The code consists of three major
56 * locking domains, each protected with their own disjunct set of locks.
57 *
58 * 1: The routing hierarchy.
59 * Comprises the structures 'zone', 'cluster', 'node', 'link'
60 * and 'bearer'. The whole hierarchy is protected by a big
61 * read/write lock, net_lock, to enssure that nothing is added
62 * or removed while code is accessing any of these structures.
63 * This layer must not be called from the two others while they
64 * hold any of their own locks.
65 * Neither must it itself do any upcalls to the other two before
66 * it has released net_lock and other protective locks.
67 *
68 * Within the net_lock domain there are two sub-domains;'node' and
69 * 'bearer', where local write operations are permitted,
70 * provided that those are protected by individual spin_locks
71 * per instance. Code holding net_lock(read) and a node spin_lock
72 * is permitted to poke around in both the node itself and its
73 * subordinate links. I.e, it can update link counters and queues,
74 * change link state, send protocol messages, and alter the
75 * "active_links" array in the node; but it can _not_ remove a link
76 * or a node from the overall structure.
77 * Correspondingly, individual bearers may change status within a
78 * net_lock(read), protected by an individual spin_lock ber bearer
79 * instance, but it needs net_lock(write) to remove/add any bearers.
80 *
81 *
82 * 2: The transport level of the protocol.
83 * This consists of the structures port, (and its user level
84 * representations, such as user_port and tipc_sock), reference and
85 * tipc_user (port.c, reg.c, socket.c).
86 *
87 * This layer has four different locks:
88 * - The tipc_port spin_lock. This is protecting each port instance
89 * from parallel data access and removal. Since we can not place
90 * this lock in the port itself, it has been placed in the
91 * corresponding reference table entry, which has the same life
92 * cycle as the module. This entry is difficult to access from
93 * outside the TIPC core, however, so a pointer to the lock has
94 * been added in the port instance, -to be used for unlocking
95 * only.
96 * - A read/write lock to protect the reference table itself (teg.c).
97 * (Nobody is using read-only access to this, so it can just as
98 * well be changed to a spin_lock)
99 * - A spin lock to protect the registry of kernel/driver users (reg.c)
100 * - A global spin_lock (port_lock), which only task is to ensure
101 * consistency where more than one port is involved in an operation,
102 * i.e., whe a port is part of a linked list of ports.
103 * There are two such lists; 'port_list', which is used for management,
104 * and 'wait_list', which is used to queue ports during congestion.
105 *
106 * 3: The name table (name_table.c, name_distr.c, subscription.c)
107 * - There is one big read/write-lock (nametbl_lock) protecting the
108 * overall name table structure. Nothing must be added/removed to
109 * this structure without holding write access to it.
110 * - There is one local spin_lock per sub_sequence, which can be seen
111 * as a sub-domain to the nametbl_lock domain. It is used only
112 * for translation operations, and is needed because a translation
113 * steps the root of the 'publication' linked list between each lookup.
114 * This is always used within the scope of a nametbl_lock(read).
115 * - A local spin_lock protecting the queue of subscriber events.
116*/
117
118rwlock_t net_lock = RW_LOCK_UNLOCKED;
119struct network net = { 0 };
120
121struct node *net_select_remote_node(u32 addr, u32 ref)
122{
123 return zone_select_remote_node(net.zones[tipc_zone(addr)], addr, ref);
124}
125
126u32 net_select_router(u32 addr, u32 ref)
127{
128 return zone_select_router(net.zones[tipc_zone(addr)], addr, ref);
129}
130
131
132u32 net_next_node(u32 a)
133{
134 if (net.zones[tipc_zone(a)])
135 return zone_next_node(a);
136 return 0;
137}
138
139void net_remove_as_router(u32 router)
140{
141 u32 z_num;
142
143 for (z_num = 1; z_num <= tipc_max_zones; z_num++) {
144 if (!net.zones[z_num])
145 continue;
146 zone_remove_as_router(net.zones[z_num], router);
147 }
148}
149
150void net_send_external_routes(u32 dest)
151{
152 u32 z_num;
153
154 for (z_num = 1; z_num <= tipc_max_zones; z_num++) {
155 if (net.zones[z_num])
156 zone_send_external_routes(net.zones[z_num], dest);
157 }
158}
159
160int net_init(void)
161{
162 u32 sz = sizeof(struct _zone *) * (tipc_max_zones + 1);
163
164 memset(&net, 0, sizeof(net));
165 net.zones = (struct _zone **)kmalloc(sz, GFP_ATOMIC);
166 if (!net.zones) {
167 return -ENOMEM;
168 }
169 memset(net.zones, 0, sz);
170 return TIPC_OK;
171}
172
173void net_stop(void)
174{
175 u32 z_num;
176
177 if (!net.zones)
178 return;
179
180 for (z_num = 1; z_num <= tipc_max_zones; z_num++) {
181 zone_delete(net.zones[z_num]);
182 }
183 kfree(net.zones);
184 net.zones = 0;
185}
186
187static void net_route_named_msg(struct sk_buff *buf)
188{
189 struct tipc_msg *msg = buf_msg(buf);
190 u32 dnode;
191 u32 dport;
192
193 if (!msg_named(msg)) {
194 msg_dbg(msg, "net->drop_nam:");
195 buf_discard(buf);
196 return;
197 }
198
199 dnode = addr_domain(msg_lookup_scope(msg));
200 dport = nametbl_translate(msg_nametype(msg), msg_nameinst(msg), &dnode);
201 dbg("net->lookup<%u,%u>-><%u,%x>\n",
202 msg_nametype(msg), msg_nameinst(msg), dport, dnode);
203 if (dport) {
204 msg_set_destnode(msg, dnode);
205 msg_set_destport(msg, dport);
206 net_route_msg(buf);
207 return;
208 }
209 msg_dbg(msg, "net->rej:NO NAME: ");
210 tipc_reject_msg(buf, TIPC_ERR_NO_NAME);
211}
212
213void net_route_msg(struct sk_buff *buf)
214{
215 struct tipc_msg *msg;
216 u32 dnode;
217
218 if (!buf)
219 return;
220 msg = buf_msg(buf);
221
222 msg_incr_reroute_cnt(msg);
223 if (msg_reroute_cnt(msg) > 6) {
224 if (msg_errcode(msg)) {
225 msg_dbg(msg, "NET>DISC>:");
226 buf_discard(buf);
227 } else {
228 msg_dbg(msg, "NET>REJ>:");
229 tipc_reject_msg(buf, msg_destport(msg) ?
230 TIPC_ERR_NO_PORT : TIPC_ERR_NO_NAME);
231 }
232 return;
233 }
234
235 msg_dbg(msg, "net->rout: ");
236
237 /* Handle message for this node */
238 dnode = msg_short(msg) ? tipc_own_addr : msg_destnode(msg);
239 if (in_scope(dnode, tipc_own_addr)) {
240 if (msg_isdata(msg)) {
241 if (msg_mcast(msg))
242 port_recv_mcast(buf, NULL);
243 else if (msg_destport(msg))
244 port_recv_msg(buf);
245 else
246 net_route_named_msg(buf);
247 return;
248 }
249 switch (msg_user(msg)) {
250 case ROUTE_DISTRIBUTOR:
251 cluster_recv_routing_table(buf);
252 break;
253 case NAME_DISTRIBUTOR:
254 named_recv(buf);
255 break;
256 case CONN_MANAGER:
257 port_recv_proto_msg(buf);
258 break;
259 default:
260 msg_dbg(msg,"DROP/NET/<REC<");
261 buf_discard(buf);
262 }
263 return;
264 }
265
266 /* Handle message for another node */
267 msg_dbg(msg, "NET>SEND>: ");
268 link_send(buf, dnode, msg_link_selector(msg));
269}
270
271int tipc_start_net(void)
272{
273 char addr_string[16];
274 int res;
275
276 if (tipc_mode != TIPC_NODE_MODE)
277 return -ENOPROTOOPT;
278
279 tipc_mode = TIPC_NET_MODE;
280 named_reinit();
281 port_reinit();
282
283 if ((res = bearer_init()) ||
284 (res = net_init()) ||
285 (res = cluster_init()) ||
286 (res = bclink_init())) {
287 return res;
288 }
289 subscr_stop();
290 cfg_stop();
291 k_signal((Handler)subscr_start, 0);
292 k_signal((Handler)cfg_init, 0);
293 info("Started in network mode\n");
294 info("Own node address %s, network identity %u\n",
295 addr_string_fill(addr_string, tipc_own_addr), tipc_net_id);
296 return TIPC_OK;
297}
298
299void tipc_stop_net(void)
300{
301 if (tipc_mode != TIPC_NET_MODE)
302 return;
303 write_lock_bh(&net_lock);
304 bearer_stop();
305 tipc_mode = TIPC_NODE_MODE;
306 bclink_stop();
307 net_stop();
308 write_unlock_bh(&net_lock);
309 info("Left network mode \n");
310}
311
diff --git a/net/tipc/net.h b/net/tipc/net.h
new file mode 100644
index 000000000000..948c6d42102c
--- /dev/null
+++ b/net/tipc/net.h
@@ -0,0 +1,66 @@
1/*
2 * net/tipc/net.h: Include file for TIPC network routing code
3 *
4 * Copyright (c) 1995-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#ifndef _TIPC_NET_H
38#define _TIPC_NET_H
39
40struct _zone;
41
42/**
43 * struct network - TIPC network structure
44 * @zones: array of pointers to all zones within network
45 */
46
47struct network {
48 struct _zone **zones;
49};
50
51
52extern struct network net;
53extern rwlock_t net_lock;
54
55int net_init(void);
56void net_stop(void);
57void net_remove_as_router(u32 router);
58void net_send_external_routes(u32 dest);
59void net_route_msg(struct sk_buff *buf);
60struct node *net_select_remote_node(u32 addr, u32 ref);
61u32 net_select_router(u32 addr, u32 ref);
62
63int tipc_start_net(void);
64void tipc_stop_net(void);
65
66#endif
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
new file mode 100644
index 000000000000..19b3f4022532
--- /dev/null
+++ b/net/tipc/netlink.c
@@ -0,0 +1,112 @@
1/*
2 * net/tipc/netlink.c: TIPC configuration handling
3 *
4 * Copyright (c) 2005-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include "core.h"
38#include "config.h"
39#include <net/genetlink.h>
40
41static int handle_cmd(struct sk_buff *skb, struct genl_info *info)
42{
43 struct sk_buff *rep_buf;
44 struct nlmsghdr *rep_nlh;
45 struct nlmsghdr *req_nlh = info->nlhdr;
46 struct tipc_genlmsghdr *req_userhdr = info->userhdr;
47 int hdr_space = NLMSG_SPACE(GENL_HDRLEN + TIPC_GENL_HDRLEN);
48
49 if ((req_userhdr->cmd & 0xC000) && (!capable(CAP_NET_ADMIN)))
50 rep_buf = cfg_reply_error_string(TIPC_CFG_NOT_NET_ADMIN);
51 else
52 rep_buf = cfg_do_cmd(req_userhdr->dest,
53 req_userhdr->cmd,
54 NLMSG_DATA(req_nlh) + GENL_HDRLEN + TIPC_GENL_HDRLEN,
55 NLMSG_PAYLOAD(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN),
56 hdr_space);
57
58 if (rep_buf) {
59 skb_push(rep_buf, hdr_space);
60 rep_nlh = (struct nlmsghdr *)rep_buf->data;
61 memcpy(rep_nlh, req_nlh, hdr_space);
62 rep_nlh->nlmsg_len = rep_buf->len;
63 genlmsg_unicast(rep_buf, req_nlh->nlmsg_pid);
64 }
65
66 return 0;
67}
68
69static struct genl_family family = {
70 .id = GENL_ID_GENERATE,
71 .name = TIPC_GENL_NAME,
72 .version = TIPC_GENL_VERSION,
73 .hdrsize = TIPC_GENL_HDRLEN,
74 .maxattr = 0,
75};
76
77static struct genl_ops ops = {
78 .cmd = TIPC_GENL_CMD,
79 .doit = handle_cmd,
80};
81
82static int family_registered = 0;
83
84int netlink_start(void)
85{
86
87
88 if (genl_register_family(&family))
89 goto err;
90
91 family_registered = 1;
92
93 if (genl_register_ops(&family, &ops))
94 goto err_unregister;
95
96 return 0;
97
98 err_unregister:
99 genl_unregister_family(&family);
100 family_registered = 0;
101 err:
102 err("Failed to register netlink interface\n");
103 return -EFAULT;
104}
105
106void netlink_stop(void)
107{
108 if (family_registered) {
109 genl_unregister_family(&family);
110 family_registered = 0;
111 }
112}
diff --git a/net/tipc/node.c b/net/tipc/node.c
new file mode 100644
index 000000000000..05688d01138b
--- /dev/null
+++ b/net/tipc/node.c
@@ -0,0 +1,679 @@
1/*
2 * net/tipc/node.c: TIPC node management routines
3 *
4 * Copyright (c) 2000-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include "core.h"
38#include "config.h"
39#include "node.h"
40#include "cluster.h"
41#include "net.h"
42#include "addr.h"
43#include "node_subscr.h"
44#include "link.h"
45#include "port.h"
46#include "bearer.h"
47#include "name_distr.h"
48#include "net.h"
49
50void node_print(struct print_buf *buf, struct node *n_ptr, char *str);
51static void node_lost_contact(struct node *n_ptr);
52static void node_established_contact(struct node *n_ptr);
53
54struct node *nodes = NULL; /* sorted list of nodes within cluster */
55
56u32 tipc_own_tag = 0;
57
58struct node *node_create(u32 addr)
59{
60 struct cluster *c_ptr;
61 struct node *n_ptr;
62 struct node **curr_node;
63
64 n_ptr = kmalloc(sizeof(*n_ptr),GFP_ATOMIC);
65 if (n_ptr != NULL) {
66 memset(n_ptr, 0, sizeof(*n_ptr));
67 n_ptr->addr = addr;
68 n_ptr->lock = SPIN_LOCK_UNLOCKED;
69 INIT_LIST_HEAD(&n_ptr->nsub);
70
71 c_ptr = cluster_find(addr);
72 if (c_ptr == NULL)
73 c_ptr = cluster_create(addr);
74 if (c_ptr != NULL) {
75 n_ptr->owner = c_ptr;
76 cluster_attach_node(c_ptr, n_ptr);
77 n_ptr->last_router = -1;
78
79 /* Insert node into ordered list */
80 for (curr_node = &nodes; *curr_node;
81 curr_node = &(*curr_node)->next) {
82 if (addr < (*curr_node)->addr) {
83 n_ptr->next = *curr_node;
84 break;
85 }
86 }
87 (*curr_node) = n_ptr;
88 } else {
89 kfree(n_ptr);
90 n_ptr = NULL;
91 }
92 }
93 return n_ptr;
94}
95
96void node_delete(struct node *n_ptr)
97{
98 if (!n_ptr)
99 return;
100
101#if 0
102 /* Not needed because links are already deleted via bearer_stop() */
103
104 u32 l_num;
105
106 for (l_num = 0; l_num < MAX_BEARERS; l_num++) {
107 link_delete(n_ptr->links[l_num]);
108 }
109#endif
110
111 dbg("node %x deleted\n", n_ptr->addr);
112 kfree(n_ptr);
113}
114
115
116/**
117 * node_link_up - handle addition of link
118 *
119 * Link becomes active (alone or shared) or standby, depending on its priority.
120 */
121
122void node_link_up(struct node *n_ptr, struct link *l_ptr)
123{
124 struct link **active = &n_ptr->active_links[0];
125
126 info("Established link <%s> on network plane %c\n",
127 l_ptr->name, l_ptr->b_ptr->net_plane);
128
129 if (!active[0]) {
130 dbg(" link %x into %x/%x\n", l_ptr, &active[0], &active[1]);
131 active[0] = active[1] = l_ptr;
132 node_established_contact(n_ptr);
133 return;
134 }
135 if (l_ptr->priority < active[0]->priority) {
136 info("Link is standby\n");
137 return;
138 }
139 link_send_duplicate(active[0], l_ptr);
140 if (l_ptr->priority == active[0]->priority) {
141 active[0] = l_ptr;
142 return;
143 }
144 info("Link <%s> on network plane %c becomes standby\n",
145 active[0]->name, active[0]->b_ptr->net_plane);
146 active[0] = active[1] = l_ptr;
147}
148
149/**
150 * node_select_active_links - select active link
151 */
152
153static void node_select_active_links(struct node *n_ptr)
154{
155 struct link **active = &n_ptr->active_links[0];
156 u32 i;
157 u32 highest_prio = 0;
158
159 active[0] = active[1] = 0;
160
161 for (i = 0; i < MAX_BEARERS; i++) {
162 struct link *l_ptr = n_ptr->links[i];
163
164 if (!l_ptr || !link_is_up(l_ptr) ||
165 (l_ptr->priority < highest_prio))
166 continue;
167
168 if (l_ptr->priority > highest_prio) {
169 highest_prio = l_ptr->priority;
170 active[0] = active[1] = l_ptr;
171 } else {
172 active[1] = l_ptr;
173 }
174 }
175}
176
177/**
178 * node_link_down - handle loss of link
179 */
180
181void node_link_down(struct node *n_ptr, struct link *l_ptr)
182{
183 struct link **active;
184
185 if (!link_is_active(l_ptr)) {
186 info("Lost standby link <%s> on network plane %c\n",
187 l_ptr->name, l_ptr->b_ptr->net_plane);
188 return;
189 }
190 info("Lost link <%s> on network plane %c\n",
191 l_ptr->name, l_ptr->b_ptr->net_plane);
192
193 active = &n_ptr->active_links[0];
194 if (active[0] == l_ptr)
195 active[0] = active[1];
196 if (active[1] == l_ptr)
197 active[1] = active[0];
198 if (active[0] == l_ptr)
199 node_select_active_links(n_ptr);
200 if (node_is_up(n_ptr))
201 link_changeover(l_ptr);
202 else
203 node_lost_contact(n_ptr);
204}
205
206int node_has_active_links(struct node *n_ptr)
207{
208 return (n_ptr &&
209 ((n_ptr->active_links[0]) || (n_ptr->active_links[1])));
210}
211
212int node_has_redundant_links(struct node *n_ptr)
213{
214 return (node_has_active_links(n_ptr) &&
215 (n_ptr->active_links[0] != n_ptr->active_links[1]));
216}
217
218int node_has_active_routes(struct node *n_ptr)
219{
220 return (n_ptr && (n_ptr->last_router >= 0));
221}
222
223int node_is_up(struct node *n_ptr)
224{
225 return (node_has_active_links(n_ptr) || node_has_active_routes(n_ptr));
226}
227
228struct node *node_attach_link(struct link *l_ptr)
229{
230 struct node *n_ptr = node_find(l_ptr->addr);
231
232 if (!n_ptr)
233 n_ptr = node_create(l_ptr->addr);
234 if (n_ptr) {
235 u32 bearer_id = l_ptr->b_ptr->identity;
236 char addr_string[16];
237
238 assert(bearer_id < MAX_BEARERS);
239 if (n_ptr->link_cnt >= 2) {
240 char addr_string[16];
241
242 err("Attempt to create third link to %s\n",
243 addr_string_fill(addr_string, n_ptr->addr));
244 return 0;
245 }
246
247 if (!n_ptr->links[bearer_id]) {
248 n_ptr->links[bearer_id] = l_ptr;
249 net.zones[tipc_zone(l_ptr->addr)]->links++;
250 n_ptr->link_cnt++;
251 return n_ptr;
252 }
253 err("Attempt to establish second link on <%s> to <%s> \n",
254 l_ptr->b_ptr->publ.name,
255 addr_string_fill(addr_string, l_ptr->addr));
256 }
257 return 0;
258}
259
260void node_detach_link(struct node *n_ptr, struct link *l_ptr)
261{
262 n_ptr->links[l_ptr->b_ptr->identity] = 0;
263 net.zones[tipc_zone(l_ptr->addr)]->links--;
264 n_ptr->link_cnt--;
265}
266
267/*
268 * Routing table management - five cases to handle:
269 *
270 * 1: A link towards a zone/cluster external node comes up.
271 * => Send a multicast message updating routing tables of all
272 * system nodes within own cluster that the new destination
273 * can be reached via this node.
274 * (node.establishedContact()=>cluster.multicastNewRoute())
275 *
276 * 2: A link towards a slave node comes up.
277 * => Send a multicast message updating routing tables of all
278 * system nodes within own cluster that the new destination
279 * can be reached via this node.
280 * (node.establishedContact()=>cluster.multicastNewRoute())
281 * => Send a message to the slave node about existence
282 * of all system nodes within cluster:
283 * (node.establishedContact()=>cluster.sendLocalRoutes())
284 *
285 * 3: A new cluster local system node becomes available.
286 * => Send message(s) to this particular node containing
287 * information about all cluster external and slave
288 * nodes which can be reached via this node.
289 * (node.establishedContact()==>network.sendExternalRoutes())
290 * (node.establishedContact()==>network.sendSlaveRoutes())
291 * => Send messages to all directly connected slave nodes
292 * containing information about the existence of the new node
293 * (node.establishedContact()=>cluster.multicastNewRoute())
294 *
295 * 4: The link towards a zone/cluster external node or slave
296 * node goes down.
297 * => Send a multcast message updating routing tables of all
298 * nodes within cluster that the new destination can not any
299 * longer be reached via this node.
300 * (node.lostAllLinks()=>cluster.bcastLostRoute())
301 *
302 * 5: A cluster local system node becomes unavailable.
303 * => Remove all references to this node from the local
304 * routing tables. Note: This is a completely node
305 * local operation.
306 * (node.lostAllLinks()=>network.removeAsRouter())
307 * => Send messages to all directly connected slave nodes
308 * containing information about loss of the node
309 * (node.establishedContact()=>cluster.multicastLostRoute())
310 *
311 */
312
313static void node_established_contact(struct node *n_ptr)
314{
315 struct cluster *c_ptr;
316
317 dbg("node_established_contact:-> %x\n", n_ptr->addr);
318 if (!node_has_active_routes(n_ptr)) {
319 k_signal((Handler)named_node_up, n_ptr->addr);
320 }
321
322 /* Syncronize broadcast acks */
323 n_ptr->bclink.acked = bclink_get_last_sent();
324
325 if (is_slave(tipc_own_addr))
326 return;
327 if (!in_own_cluster(n_ptr->addr)) {
328 /* Usage case 1 (see above) */
329 c_ptr = cluster_find(tipc_own_addr);
330 if (!c_ptr)
331 c_ptr = cluster_create(tipc_own_addr);
332 if (c_ptr)
333 cluster_bcast_new_route(c_ptr, n_ptr->addr, 1,
334 tipc_max_nodes);
335 return;
336 }
337
338 c_ptr = n_ptr->owner;
339 if (is_slave(n_ptr->addr)) {
340 /* Usage case 2 (see above) */
341 cluster_bcast_new_route(c_ptr, n_ptr->addr, 1, tipc_max_nodes);
342 cluster_send_local_routes(c_ptr, n_ptr->addr);
343 return;
344 }
345
346 if (n_ptr->bclink.supported) {
347 nmap_add(&cluster_bcast_nodes, n_ptr->addr);
348 if (n_ptr->addr < tipc_own_addr)
349 tipc_own_tag++;
350 }
351
352 /* Case 3 (see above) */
353 net_send_external_routes(n_ptr->addr);
354 cluster_send_slave_routes(c_ptr, n_ptr->addr);
355 cluster_bcast_new_route(c_ptr, n_ptr->addr, LOWEST_SLAVE,
356 highest_allowed_slave);
357}
358
359static void node_lost_contact(struct node *n_ptr)
360{
361 struct cluster *c_ptr;
362 struct node_subscr *ns, *tns;
363 char addr_string[16];
364 u32 i;
365
366 /* Clean up broadcast reception remains */
367 n_ptr->bclink.gap_after = n_ptr->bclink.gap_to = 0;
368 while (n_ptr->bclink.deferred_head) {
369 struct sk_buff* buf = n_ptr->bclink.deferred_head;
370 n_ptr->bclink.deferred_head = buf->next;
371 buf_discard(buf);
372 }
373 if (n_ptr->bclink.defragm) {
374 buf_discard(n_ptr->bclink.defragm);
375 n_ptr->bclink.defragm = NULL;
376 }
377 if (in_own_cluster(n_ptr->addr) && n_ptr->bclink.supported) {
378 bclink_acknowledge(n_ptr, mod(n_ptr->bclink.acked + 10000));
379 }
380
381 /* Update routing tables */
382 if (is_slave(tipc_own_addr)) {
383 net_remove_as_router(n_ptr->addr);
384 } else {
385 if (!in_own_cluster(n_ptr->addr)) {
386 /* Case 4 (see above) */
387 c_ptr = cluster_find(tipc_own_addr);
388 cluster_bcast_lost_route(c_ptr, n_ptr->addr, 1,
389 tipc_max_nodes);
390 } else {
391 /* Case 5 (see above) */
392 c_ptr = cluster_find(n_ptr->addr);
393 if (is_slave(n_ptr->addr)) {
394 cluster_bcast_lost_route(c_ptr, n_ptr->addr, 1,
395 tipc_max_nodes);
396 } else {
397 if (n_ptr->bclink.supported) {
398 nmap_remove(&cluster_bcast_nodes,
399 n_ptr->addr);
400 if (n_ptr->addr < tipc_own_addr)
401 tipc_own_tag--;
402 }
403 net_remove_as_router(n_ptr->addr);
404 cluster_bcast_lost_route(c_ptr, n_ptr->addr,
405 LOWEST_SLAVE,
406 highest_allowed_slave);
407 }
408 }
409 }
410 if (node_has_active_routes(n_ptr))
411 return;
412
413 info("Lost contact with %s\n",
414 addr_string_fill(addr_string, n_ptr->addr));
415
416 /* Abort link changeover */
417 for (i = 0; i < MAX_BEARERS; i++) {
418 struct link *l_ptr = n_ptr->links[i];
419 if (!l_ptr)
420 continue;
421 l_ptr->reset_checkpoint = l_ptr->next_in_no;
422 l_ptr->exp_msg_count = 0;
423 link_reset_fragments(l_ptr);
424 }
425
426 /* Notify subscribers */
427 list_for_each_entry_safe(ns, tns, &n_ptr->nsub, nodesub_list) {
428 ns->node = 0;
429 list_del_init(&ns->nodesub_list);
430 k_signal((Handler)ns->handle_node_down,
431 (unsigned long)ns->usr_handle);
432 }
433}
434
435/**
436 * node_select_next_hop - find the next-hop node for a message
437 *
438 * Called by when cluster local lookup has failed.
439 */
440
441struct node *node_select_next_hop(u32 addr, u32 selector)
442{
443 struct node *n_ptr;
444 u32 router_addr;
445
446 if (!addr_domain_valid(addr))
447 return 0;
448
449 /* Look for direct link to destination processsor */
450 n_ptr = node_find(addr);
451 if (n_ptr && node_has_active_links(n_ptr))
452 return n_ptr;
453
454 /* Cluster local system nodes *must* have direct links */
455 if (!is_slave(addr) && in_own_cluster(addr))
456 return 0;
457
458 /* Look for cluster local router with direct link to node */
459 router_addr = node_select_router(n_ptr, selector);
460 if (router_addr)
461 return node_select(router_addr, selector);
462
463 /* Slave nodes can only be accessed within own cluster via a
464 known router with direct link -- if no router was found,give up */
465 if (is_slave(addr))
466 return 0;
467
468 /* Inter zone/cluster -- find any direct link to remote cluster */
469 addr = tipc_addr(tipc_zone(addr), tipc_cluster(addr), 0);
470 n_ptr = net_select_remote_node(addr, selector);
471 if (n_ptr && node_has_active_links(n_ptr))
472 return n_ptr;
473
474 /* Last resort -- look for any router to anywhere in remote zone */
475 router_addr = net_select_router(addr, selector);
476 if (router_addr)
477 return node_select(router_addr, selector);
478
479 return 0;
480}
481
482/**
483 * node_select_router - select router to reach specified node
484 *
485 * Uses a deterministic and fair algorithm for selecting router node.
486 */
487
488u32 node_select_router(struct node *n_ptr, u32 ref)
489{
490 u32 ulim;
491 u32 mask;
492 u32 start;
493 u32 r;
494
495 if (!n_ptr)
496 return 0;
497
498 if (n_ptr->last_router < 0)
499 return 0;
500 ulim = ((n_ptr->last_router + 1) * 32) - 1;
501
502 /* Start entry must be random */
503 mask = tipc_max_nodes;
504 while (mask > ulim)
505 mask >>= 1;
506 start = ref & mask;
507 r = start;
508
509 /* Lookup upwards with wrap-around */
510 do {
511 if (((n_ptr->routers[r / 32]) >> (r % 32)) & 1)
512 break;
513 } while (++r <= ulim);
514 if (r > ulim) {
515 r = 1;
516 do {
517 if (((n_ptr->routers[r / 32]) >> (r % 32)) & 1)
518 break;
519 } while (++r < start);
520 assert(r != start);
521 }
522 assert(r && (r <= ulim));
523 return tipc_addr(own_zone(), own_cluster(), r);
524}
525
526void node_add_router(struct node *n_ptr, u32 router)
527{
528 u32 r_num = tipc_node(router);
529
530 n_ptr->routers[r_num / 32] =
531 ((1 << (r_num % 32)) | n_ptr->routers[r_num / 32]);
532 n_ptr->last_router = tipc_max_nodes / 32;
533 while ((--n_ptr->last_router >= 0) &&
534 !n_ptr->routers[n_ptr->last_router]);
535}
536
537void node_remove_router(struct node *n_ptr, u32 router)
538{
539 u32 r_num = tipc_node(router);
540
541 if (n_ptr->last_router < 0)
542 return; /* No routes */
543
544 n_ptr->routers[r_num / 32] =
545 ((~(1 << (r_num % 32))) & (n_ptr->routers[r_num / 32]));
546 n_ptr->last_router = tipc_max_nodes / 32;
547 while ((--n_ptr->last_router >= 0) &&
548 !n_ptr->routers[n_ptr->last_router]);
549
550 if (!node_is_up(n_ptr))
551 node_lost_contact(n_ptr);
552}
553
554#if 0
555void node_print(struct print_buf *buf, struct node *n_ptr, char *str)
556{
557 u32 i;
558
559 tipc_printf(buf, "\n\n%s", str);
560 for (i = 0; i < MAX_BEARERS; i++) {
561 if (!n_ptr->links[i])
562 continue;
563 tipc_printf(buf, "Links[%u]: %x, ", i, n_ptr->links[i]);
564 }
565 tipc_printf(buf, "Active links: [%x,%x]\n",
566 n_ptr->active_links[0], n_ptr->active_links[1]);
567}
568#endif
569
570u32 tipc_available_nodes(const u32 domain)
571{
572 struct node *n_ptr;
573 u32 cnt = 0;
574
575 for (n_ptr = nodes; n_ptr; n_ptr = n_ptr->next) {
576 if (!in_scope(domain, n_ptr->addr))
577 continue;
578 if (node_is_up(n_ptr))
579 cnt++;
580 }
581 return cnt;
582}
583
584struct sk_buff *node_get_nodes(const void *req_tlv_area, int req_tlv_space)
585{
586 u32 domain;
587 struct sk_buff *buf;
588 struct node *n_ptr;
589 struct tipc_node_info node_info;
590
591 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
592 return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
593
594 domain = *(u32 *)TLV_DATA(req_tlv_area);
595 domain = ntohl(domain);
596 if (!addr_domain_valid(domain))
597 return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
598 " (network address)");
599
600 if (!nodes)
601 return cfg_reply_none();
602
603 /* For now, get space for all other nodes
604 (will need to modify this when slave nodes are supported */
605
606 buf = cfg_reply_alloc(TLV_SPACE(sizeof(node_info)) *
607 (tipc_max_nodes - 1));
608 if (!buf)
609 return NULL;
610
611 /* Add TLVs for all nodes in scope */
612
613 for (n_ptr = nodes; n_ptr; n_ptr = n_ptr->next) {
614 if (!in_scope(domain, n_ptr->addr))
615 continue;
616 node_info.addr = htonl(n_ptr->addr);
617 node_info.up = htonl(node_is_up(n_ptr));
618 cfg_append_tlv(buf, TIPC_TLV_NODE_INFO,
619 &node_info, sizeof(node_info));
620 }
621
622 return buf;
623}
624
625struct sk_buff *node_get_links(const void *req_tlv_area, int req_tlv_space)
626{
627 u32 domain;
628 struct sk_buff *buf;
629 struct node *n_ptr;
630 struct tipc_link_info link_info;
631
632 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
633 return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
634
635 domain = *(u32 *)TLV_DATA(req_tlv_area);
636 domain = ntohl(domain);
637 if (!addr_domain_valid(domain))
638 return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
639 " (network address)");
640
641 if (!nodes)
642 return cfg_reply_none();
643
644 /* For now, get space for 2 links to all other nodes + bcast link
645 (will need to modify this when slave nodes are supported */
646
647 buf = cfg_reply_alloc(TLV_SPACE(sizeof(link_info)) *
648 (2 * (tipc_max_nodes - 1) + 1));
649 if (!buf)
650 return NULL;
651
652 /* Add TLV for broadcast link */
653
654 link_info.dest = tipc_own_addr & 0xfffff00;
655 link_info.dest = htonl(link_info.dest);
656 link_info.up = htonl(1);
657 sprintf(link_info.str, bc_link_name);
658 cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info));
659
660 /* Add TLVs for any other links in scope */
661
662 for (n_ptr = nodes; n_ptr; n_ptr = n_ptr->next) {
663 u32 i;
664
665 if (!in_scope(domain, n_ptr->addr))
666 continue;
667 for (i = 0; i < MAX_BEARERS; i++) {
668 if (!n_ptr->links[i])
669 continue;
670 link_info.dest = htonl(n_ptr->addr);
671 link_info.up = htonl(link_is_up(n_ptr->links[i]));
672 strcpy(link_info.str, n_ptr->links[i]->name);
673 cfg_append_tlv(buf, TIPC_TLV_LINK_INFO,
674 &link_info, sizeof(link_info));
675 }
676 }
677
678 return buf;
679}
diff --git a/net/tipc/node.h b/net/tipc/node.h
new file mode 100644
index 000000000000..b39442badccf
--- /dev/null
+++ b/net/tipc/node.h
@@ -0,0 +1,144 @@
1/*
2 * net/tipc/node.h: Include file for TIPC node management routines
3 *
4 * Copyright (c) 2000-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#ifndef _TIPC_NODE_H
38#define _TIPC_NODE_H
39
40#include "node_subscr.h"
41#include "addr.h"
42#include "cluster.h"
43#include "bearer.h"
44
45/**
46 * struct node - TIPC node structure
47 * @addr: network address of node
48 * @lock: spinlock governing access to structure
49 * @owner: pointer to cluster that node belongs to
50 * @next: pointer to next node in sorted list of cluster's nodes
51 * @nsub: list of "node down" subscriptions monitoring node
52 * @active_links: pointers to active links to node
53 * @links: pointers to all links to node
54 * @link_cnt: number of links to node
55 * @permit_changeover: non-zero if node has redundant links to this system
56 * @routers: bitmap (used for multicluster communication)
57 * @last_router: (used for multicluster communication)
58 * @bclink: broadcast-related info
59 * @supported: non-zero if node supports TIPC b'cast capability
60 * @acked: sequence # of last outbound b'cast message acknowledged by node
61 * @last_in: sequence # of last in-sequence b'cast message received from node
62 * @gap_after: sequence # of last message not requiring a NAK request
63 * @gap_to: sequence # of last message requiring a NAK request
64 * @nack_sync: counter that determines when NAK requests should be sent
65 * @deferred_head: oldest OOS b'cast message received from node
66 * @deferred_tail: newest OOS b'cast message received from node
67 * @defragm: list of partially reassembled b'cast message fragments from node
68 */
69
70struct node {
71 u32 addr;
72 spinlock_t lock;
73 struct cluster *owner;
74 struct node *next;
75 struct list_head nsub;
76 struct link *active_links[2];
77 struct link *links[MAX_BEARERS];
78 int link_cnt;
79 int permit_changeover;
80 u32 routers[512/32];
81 int last_router;
82 struct {
83 int supported;
84 u32 acked;
85 u32 last_in;
86 u32 gap_after;
87 u32 gap_to;
88 u32 nack_sync;
89 struct sk_buff *deferred_head;
90 struct sk_buff *deferred_tail;
91 struct sk_buff *defragm;
92 } bclink;
93};
94
95extern struct node *nodes;
96extern u32 tipc_own_tag;
97
98struct node *node_create(u32 addr);
99void node_delete(struct node *n_ptr);
100struct node *node_attach_link(struct link *l_ptr);
101void node_detach_link(struct node *n_ptr, struct link *l_ptr);
102void node_link_down(struct node *n_ptr, struct link *l_ptr);
103void node_link_up(struct node *n_ptr, struct link *l_ptr);
104int node_has_active_links(struct node *n_ptr);
105int node_has_redundant_links(struct node *n_ptr);
106u32 node_select_router(struct node *n_ptr, u32 ref);
107struct node *node_select_next_hop(u32 addr, u32 selector);
108int node_is_up(struct node *n_ptr);
109void node_add_router(struct node *n_ptr, u32 router);
110void node_remove_router(struct node *n_ptr, u32 router);
111struct sk_buff *node_get_links(const void *req_tlv_area, int req_tlv_space);
112struct sk_buff *node_get_nodes(const void *req_tlv_area, int req_tlv_space);
113
114static inline struct node *node_find(u32 addr)
115{
116 if (likely(in_own_cluster(addr)))
117 return local_nodes[tipc_node(addr)];
118 else if (addr_domain_valid(addr)) {
119 struct cluster *c_ptr = cluster_find(addr);
120
121 if (c_ptr)
122 return c_ptr->nodes[tipc_node(addr)];
123 }
124 return 0;
125}
126
127static inline struct node *node_select(u32 addr, u32 selector)
128{
129 if (likely(in_own_cluster(addr)))
130 return local_nodes[tipc_node(addr)];
131 return node_select_next_hop(addr, selector);
132}
133
134static inline void node_lock(struct node *n_ptr)
135{
136 spin_lock_bh(&n_ptr->lock);
137}
138
139static inline void node_unlock(struct node *n_ptr)
140{
141 spin_unlock_bh(&n_ptr->lock);
142}
143
144#endif
diff --git a/net/tipc/node_subscr.c b/net/tipc/node_subscr.c
new file mode 100644
index 000000000000..79375927916f
--- /dev/null
+++ b/net/tipc/node_subscr.c
@@ -0,0 +1,79 @@
1/*
2 * net/tipc/node_subscr.c: TIPC "node down" subscription handling
3 *
4 * Copyright (c) 1995-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include "core.h"
38#include "dbg.h"
39#include "node_subscr.h"
40#include "node.h"
41#include "addr.h"
42
43/**
44 * nodesub_subscribe - create "node down" subscription for specified node
45 */
46
47void nodesub_subscribe(struct node_subscr *node_sub, u32 addr,
48 void *usr_handle, net_ev_handler handle_down)
49{
50 node_sub->node = 0;
51 if (addr == tipc_own_addr)
52 return;
53 if (!addr_node_valid(addr)) {
54 warn("node_subscr with illegal %x\n", addr);
55 return;
56 }
57
58 node_sub->handle_node_down = handle_down;
59 node_sub->usr_handle = usr_handle;
60 node_sub->node = node_find(addr);
61 assert(node_sub->node);
62 node_lock(node_sub->node);
63 list_add_tail(&node_sub->nodesub_list, &node_sub->node->nsub);
64 node_unlock(node_sub->node);
65}
66
67/**
68 * nodesub_unsubscribe - cancel "node down" subscription (if any)
69 */
70
71void nodesub_unsubscribe(struct node_subscr *node_sub)
72{
73 if (!node_sub->node)
74 return;
75
76 node_lock(node_sub->node);
77 list_del_init(&node_sub->nodesub_list);
78 node_unlock(node_sub->node);
79}
diff --git a/net/tipc/node_subscr.h b/net/tipc/node_subscr.h
new file mode 100644
index 000000000000..a3b87ac4859b
--- /dev/null
+++ b/net/tipc/node_subscr.h
@@ -0,0 +1,63 @@
1/*
2 * net/tipc/node_subscr.h: Include file for TIPC "node down" subscription handling
3 *
4 * Copyright (c) 1995-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#ifndef _TIPC_NODE_SUBSCR_H
38#define _TIPC_NODE_SUBSCR_H
39
40#include "addr.h"
41
42typedef void (*net_ev_handler) (void *usr_handle);
43
44/**
45 * struct node_subscr - "node down" subscription entry
46 * @node: ptr to node structure of interest (or NULL, if none)
47 * @handle_node_down: routine to invoke when node fails
48 * @usr_handle: argument to pass to routine when node fails
49 * @nodesub_list: adjacent entries in list of subscriptions for the node
50 */
51
52struct node_subscr {
53 struct node *node;
54 net_ev_handler handle_node_down;
55 void *usr_handle;
56 struct list_head nodesub_list;
57};
58
59void nodesub_subscribe(struct node_subscr *node_sub, u32 addr,
60 void *usr_handle, net_ev_handler handle_down);
61void nodesub_unsubscribe(struct node_subscr *node_sub);
62
63#endif
diff --git a/net/tipc/port.c b/net/tipc/port.c
new file mode 100644
index 000000000000..66caca7abe92
--- /dev/null
+++ b/net/tipc/port.c
@@ -0,0 +1,1708 @@
1/*
2 * net/tipc/port.c: TIPC port code
3 *
4 * Copyright (c) 1992-2006, Ericsson AB
5 * Copyright (c) 2004-2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include "core.h"
38#include "config.h"
39#include "dbg.h"
40#include "port.h"
41#include "addr.h"
42#include "link.h"
43#include "node.h"
44#include "port.h"
45#include "name_table.h"
46#include "user_reg.h"
47#include "msg.h"
48#include "bcast.h"
49
50/* Connection management: */
51#define PROBING_INTERVAL 3600000 /* [ms] => 1 h */
52#define CONFIRMED 0
53#define PROBING 1
54
55#define MAX_REJECT_SIZE 1024
56
57static struct sk_buff *msg_queue_head = 0;
58static struct sk_buff *msg_queue_tail = 0;
59
60spinlock_t port_list_lock = SPIN_LOCK_UNLOCKED;
61static spinlock_t queue_lock = SPIN_LOCK_UNLOCKED;
62
63LIST_HEAD(ports);
64static void port_handle_node_down(unsigned long ref);
65static struct sk_buff* port_build_self_abort_msg(struct port *,u32 err);
66static struct sk_buff* port_build_peer_abort_msg(struct port *,u32 err);
67static void port_timeout(unsigned long ref);
68
69
70static inline u32 port_peernode(struct port *p_ptr)
71{
72 return msg_destnode(&p_ptr->publ.phdr);
73}
74
75static inline u32 port_peerport(struct port *p_ptr)
76{
77 return msg_destport(&p_ptr->publ.phdr);
78}
79
80static inline u32 port_out_seqno(struct port *p_ptr)
81{
82 return msg_transp_seqno(&p_ptr->publ.phdr);
83}
84
85static inline void port_set_out_seqno(struct port *p_ptr, u32 seqno)
86{
87 msg_set_transp_seqno(&p_ptr->publ.phdr,seqno);
88}
89
90static inline void port_incr_out_seqno(struct port *p_ptr)
91{
92 struct tipc_msg *m = &p_ptr->publ.phdr;
93
94 if (likely(!msg_routed(m)))
95 return;
96 msg_set_transp_seqno(m, (msg_transp_seqno(m) + 1));
97}
98
99/**
100 * tipc_multicast - send a multicast message to local and remote destinations
101 */
102
103int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, u32 domain,
104 u32 num_sect, struct iovec const *msg_sect)
105{
106 struct tipc_msg *hdr;
107 struct sk_buff *buf;
108 struct sk_buff *ibuf = NULL;
109 struct port_list dports = {0, NULL, };
110 struct port *oport = port_deref(ref);
111 int ext_targets;
112 int res;
113
114 if (unlikely(!oport))
115 return -EINVAL;
116
117 /* Create multicast message */
118
119 hdr = &oport->publ.phdr;
120 msg_set_type(hdr, TIPC_MCAST_MSG);
121 msg_set_nametype(hdr, seq->type);
122 msg_set_namelower(hdr, seq->lower);
123 msg_set_nameupper(hdr, seq->upper);
124 msg_set_hdr_sz(hdr, MCAST_H_SIZE);
125 res = msg_build(hdr, msg_sect, num_sect, MAX_MSG_SIZE,
126 !oport->user_port, &buf);
127 if (unlikely(!buf))
128 return res;
129
130 /* Figure out where to send multicast message */
131
132 ext_targets = nametbl_mc_translate(seq->type, seq->lower, seq->upper,
133 TIPC_NODE_SCOPE, &dports);
134
135 /* Send message to destinations (duplicate it only if necessary) */
136
137 if (ext_targets) {
138 if (dports.count != 0) {
139 ibuf = skb_copy(buf, GFP_ATOMIC);
140 if (ibuf == NULL) {
141 port_list_free(&dports);
142 buf_discard(buf);
143 return -ENOMEM;
144 }
145 }
146 res = bclink_send_msg(buf);
147 if ((res < 0) && (dports.count != 0)) {
148 buf_discard(ibuf);
149 }
150 } else {
151 ibuf = buf;
152 }
153
154 if (res >= 0) {
155 if (ibuf)
156 port_recv_mcast(ibuf, &dports);
157 } else {
158 port_list_free(&dports);
159 }
160 return res;
161}
162
163/**
164 * port_recv_mcast - deliver multicast message to all destination ports
165 *
166 * If there is no port list, perform a lookup to create one
167 */
168
169void port_recv_mcast(struct sk_buff *buf, struct port_list *dp)
170{
171 struct tipc_msg* msg;
172 struct port_list dports = {0, NULL, };
173 struct port_list *item = dp;
174 int cnt = 0;
175
176 assert(buf);
177 msg = buf_msg(buf);
178
179 /* Create destination port list, if one wasn't supplied */
180
181 if (dp == NULL) {
182 nametbl_mc_translate(msg_nametype(msg),
183 msg_namelower(msg),
184 msg_nameupper(msg),
185 TIPC_CLUSTER_SCOPE,
186 &dports);
187 item = dp = &dports;
188 }
189
190 /* Deliver a copy of message to each destination port */
191
192 if (dp->count != 0) {
193 if (dp->count == 1) {
194 msg_set_destport(msg, dp->ports[0]);
195 port_recv_msg(buf);
196 port_list_free(dp);
197 return;
198 }
199 for (; cnt < dp->count; cnt++) {
200 int index = cnt % PLSIZE;
201 struct sk_buff *b = skb_clone(buf, GFP_ATOMIC);
202
203 if (b == NULL) {
204 warn("Buffer allocation failure\n");
205 msg_dbg(msg, "LOST:");
206 goto exit;
207 }
208 if ((index == 0) && (cnt != 0)) {
209 item = item->next;
210 }
211 msg_set_destport(buf_msg(b),item->ports[index]);
212 port_recv_msg(b);
213 }
214 }
215exit:
216 buf_discard(buf);
217 port_list_free(dp);
218}
219
220/**
221 * tipc_createport_raw - create a native TIPC port
222 *
223 * Returns local port reference
224 */
225
226u32 tipc_createport_raw(void *usr_handle,
227 u32 (*dispatcher)(struct tipc_port *, struct sk_buff *),
228 void (*wakeup)(struct tipc_port *),
229 const u32 importance)
230{
231 struct port *p_ptr;
232 struct tipc_msg *msg;
233 u32 ref;
234
235 p_ptr = kmalloc(sizeof(*p_ptr), GFP_ATOMIC);
236 if (p_ptr == NULL) {
237 warn("Memory squeeze; failed to create port\n");
238 return 0;
239 }
240 memset(p_ptr, 0, sizeof(*p_ptr));
241 ref = ref_acquire(p_ptr, &p_ptr->publ.lock);
242 if (!ref) {
243 warn("Reference Table Exhausted\n");
244 kfree(p_ptr);
245 return 0;
246 }
247
248 port_lock(ref);
249 p_ptr->publ.ref = ref;
250 msg = &p_ptr->publ.phdr;
251 msg_init(msg, DATA_LOW, TIPC_NAMED_MSG, TIPC_OK, LONG_H_SIZE, 0);
252 msg_set_orignode(msg, tipc_own_addr);
253 msg_set_prevnode(msg, tipc_own_addr);
254 msg_set_origport(msg, ref);
255 msg_set_importance(msg,importance);
256 p_ptr->last_in_seqno = 41;
257 p_ptr->sent = 1;
258 p_ptr->publ.usr_handle = usr_handle;
259 INIT_LIST_HEAD(&p_ptr->wait_list);
260 INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list);
261 p_ptr->congested_link = 0;
262 p_ptr->max_pkt = MAX_PKT_DEFAULT;
263 p_ptr->dispatcher = dispatcher;
264 p_ptr->wakeup = wakeup;
265 p_ptr->user_port = 0;
266 k_init_timer(&p_ptr->timer, (Handler)port_timeout, ref);
267 spin_lock_bh(&port_list_lock);
268 INIT_LIST_HEAD(&p_ptr->publications);
269 INIT_LIST_HEAD(&p_ptr->port_list);
270 list_add_tail(&p_ptr->port_list, &ports);
271 spin_unlock_bh(&port_list_lock);
272 port_unlock(p_ptr);
273 return ref;
274}
275
276int tipc_deleteport(u32 ref)
277{
278 struct port *p_ptr;
279 struct sk_buff *buf = 0;
280
281 tipc_withdraw(ref, 0, 0);
282 p_ptr = port_lock(ref);
283 if (!p_ptr)
284 return -EINVAL;
285
286 ref_discard(ref);
287 port_unlock(p_ptr);
288
289 k_cancel_timer(&p_ptr->timer);
290 if (p_ptr->publ.connected) {
291 buf = port_build_peer_abort_msg(p_ptr, TIPC_ERR_NO_PORT);
292 nodesub_unsubscribe(&p_ptr->subscription);
293 }
294 if (p_ptr->user_port) {
295 reg_remove_port(p_ptr->user_port);
296 kfree(p_ptr->user_port);
297 }
298
299 spin_lock_bh(&port_list_lock);
300 list_del(&p_ptr->port_list);
301 list_del(&p_ptr->wait_list);
302 spin_unlock_bh(&port_list_lock);
303 k_term_timer(&p_ptr->timer);
304 kfree(p_ptr);
305 dbg("Deleted port %u\n", ref);
306 net_route_msg(buf);
307 return TIPC_OK;
308}
309
310/**
311 * tipc_get_port() - return port associated with 'ref'
312 *
313 * Note: Port is not locked.
314 */
315
316struct tipc_port *tipc_get_port(const u32 ref)
317{
318 return (struct tipc_port *)ref_deref(ref);
319}
320
321/**
322 * tipc_get_handle - return user handle associated to port 'ref'
323 */
324
325void *tipc_get_handle(const u32 ref)
326{
327 struct port *p_ptr;
328 void * handle;
329
330 p_ptr = port_lock(ref);
331 if (!p_ptr)
332 return 0;
333 handle = p_ptr->publ.usr_handle;
334 port_unlock(p_ptr);
335 return handle;
336}
337
338static inline int port_unreliable(struct port *p_ptr)
339{
340 return msg_src_droppable(&p_ptr->publ.phdr);
341}
342
343int tipc_portunreliable(u32 ref, unsigned int *isunreliable)
344{
345 struct port *p_ptr;
346
347 p_ptr = port_lock(ref);
348 if (!p_ptr)
349 return -EINVAL;
350 *isunreliable = port_unreliable(p_ptr);
351 spin_unlock_bh(p_ptr->publ.lock);
352 return TIPC_OK;
353}
354
355int tipc_set_portunreliable(u32 ref, unsigned int isunreliable)
356{
357 struct port *p_ptr;
358
359 p_ptr = port_lock(ref);
360 if (!p_ptr)
361 return -EINVAL;
362 msg_set_src_droppable(&p_ptr->publ.phdr, (isunreliable != 0));
363 port_unlock(p_ptr);
364 return TIPC_OK;
365}
366
367static inline int port_unreturnable(struct port *p_ptr)
368{
369 return msg_dest_droppable(&p_ptr->publ.phdr);
370}
371
372int tipc_portunreturnable(u32 ref, unsigned int *isunrejectable)
373{
374 struct port *p_ptr;
375
376 p_ptr = port_lock(ref);
377 if (!p_ptr)
378 return -EINVAL;
379 *isunrejectable = port_unreturnable(p_ptr);
380 spin_unlock_bh(p_ptr->publ.lock);
381 return TIPC_OK;
382}
383
384int tipc_set_portunreturnable(u32 ref, unsigned int isunrejectable)
385{
386 struct port *p_ptr;
387
388 p_ptr = port_lock(ref);
389 if (!p_ptr)
390 return -EINVAL;
391 msg_set_dest_droppable(&p_ptr->publ.phdr, (isunrejectable != 0));
392 port_unlock(p_ptr);
393 return TIPC_OK;
394}
395
396/*
397 * port_build_proto_msg(): build a port level protocol
398 * or a connection abortion message. Called with
399 * tipc_port lock on.
400 */
401static struct sk_buff *port_build_proto_msg(u32 destport, u32 destnode,
402 u32 origport, u32 orignode,
403 u32 usr, u32 type, u32 err,
404 u32 seqno, u32 ack)
405{
406 struct sk_buff *buf;
407 struct tipc_msg *msg;
408
409 buf = buf_acquire(LONG_H_SIZE);
410 if (buf) {
411 msg = buf_msg(buf);
412 msg_init(msg, usr, type, err, LONG_H_SIZE, destnode);
413 msg_set_destport(msg, destport);
414 msg_set_origport(msg, origport);
415 msg_set_destnode(msg, destnode);
416 msg_set_orignode(msg, orignode);
417 msg_set_transp_seqno(msg, seqno);
418 msg_set_msgcnt(msg, ack);
419 msg_dbg(msg, "PORT>SEND>:");
420 }
421 return buf;
422}
423
424int tipc_set_msg_option(struct tipc_port *tp_ptr, const char *opt, const u32 sz)
425{
426 msg_expand(&tp_ptr->phdr, msg_destnode(&tp_ptr->phdr));
427 msg_set_options(&tp_ptr->phdr, opt, sz);
428 return TIPC_OK;
429}
430
431int tipc_reject_msg(struct sk_buff *buf, u32 err)
432{
433 struct tipc_msg *msg = buf_msg(buf);
434 struct sk_buff *rbuf;
435 struct tipc_msg *rmsg;
436 int hdr_sz;
437 u32 imp = msg_importance(msg);
438 u32 data_sz = msg_data_sz(msg);
439
440 if (data_sz > MAX_REJECT_SIZE)
441 data_sz = MAX_REJECT_SIZE;
442 if (msg_connected(msg) && (imp < TIPC_CRITICAL_IMPORTANCE))
443 imp++;
444 msg_dbg(msg, "port->rej: ");
445
446 /* discard rejected message if it shouldn't be returned to sender */
447 if (msg_errcode(msg) || msg_dest_droppable(msg)) {
448 buf_discard(buf);
449 return data_sz;
450 }
451
452 /* construct rejected message */
453 if (msg_mcast(msg))
454 hdr_sz = MCAST_H_SIZE;
455 else
456 hdr_sz = LONG_H_SIZE;
457 rbuf = buf_acquire(data_sz + hdr_sz);
458 if (rbuf == NULL) {
459 buf_discard(buf);
460 return data_sz;
461 }
462 rmsg = buf_msg(rbuf);
463 msg_init(rmsg, imp, msg_type(msg), err, hdr_sz, msg_orignode(msg));
464 msg_set_destport(rmsg, msg_origport(msg));
465 msg_set_prevnode(rmsg, tipc_own_addr);
466 msg_set_origport(rmsg, msg_destport(msg));
467 if (msg_short(msg))
468 msg_set_orignode(rmsg, tipc_own_addr);
469 else
470 msg_set_orignode(rmsg, msg_destnode(msg));
471 msg_set_size(rmsg, data_sz + hdr_sz);
472 msg_set_nametype(rmsg, msg_nametype(msg));
473 msg_set_nameinst(rmsg, msg_nameinst(msg));
474 memcpy(rbuf->data + hdr_sz, msg_data(msg), data_sz);
475
476 /* send self-abort message when rejecting on a connected port */
477 if (msg_connected(msg)) {
478 struct sk_buff *abuf = 0;
479 struct port *p_ptr = port_lock(msg_destport(msg));
480
481 if (p_ptr) {
482 if (p_ptr->publ.connected)
483 abuf = port_build_self_abort_msg(p_ptr, err);
484 port_unlock(p_ptr);
485 }
486 net_route_msg(abuf);
487 }
488
489 /* send rejected message */
490 buf_discard(buf);
491 net_route_msg(rbuf);
492 return data_sz;
493}
494
495int port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr,
496 struct iovec const *msg_sect, u32 num_sect,
497 int err)
498{
499 struct sk_buff *buf;
500 int res;
501
502 res = msg_build(hdr, msg_sect, num_sect, MAX_MSG_SIZE,
503 !p_ptr->user_port, &buf);
504 if (!buf)
505 return res;
506
507 return tipc_reject_msg(buf, err);
508}
509
510static void port_timeout(unsigned long ref)
511{
512 struct port *p_ptr = port_lock(ref);
513 struct sk_buff *buf = 0;
514
515 if (!p_ptr || !p_ptr->publ.connected)
516 return;
517
518 /* Last probe answered ? */
519 if (p_ptr->probing_state == PROBING) {
520 buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_PORT);
521 } else {
522 buf = port_build_proto_msg(port_peerport(p_ptr),
523 port_peernode(p_ptr),
524 p_ptr->publ.ref,
525 tipc_own_addr,
526 CONN_MANAGER,
527 CONN_PROBE,
528 TIPC_OK,
529 port_out_seqno(p_ptr),
530 0);
531 port_incr_out_seqno(p_ptr);
532 p_ptr->probing_state = PROBING;
533 k_start_timer(&p_ptr->timer, p_ptr->probing_interval);
534 }
535 port_unlock(p_ptr);
536 net_route_msg(buf);
537}
538
539
540static void port_handle_node_down(unsigned long ref)
541{
542 struct port *p_ptr = port_lock(ref);
543 struct sk_buff* buf = 0;
544
545 if (!p_ptr)
546 return;
547 buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_NODE);
548 port_unlock(p_ptr);
549 net_route_msg(buf);
550}
551
552
553static struct sk_buff *port_build_self_abort_msg(struct port *p_ptr, u32 err)
554{
555 u32 imp = msg_importance(&p_ptr->publ.phdr);
556
557 if (!p_ptr->publ.connected)
558 return 0;
559 if (imp < TIPC_CRITICAL_IMPORTANCE)
560 imp++;
561 return port_build_proto_msg(p_ptr->publ.ref,
562 tipc_own_addr,
563 port_peerport(p_ptr),
564 port_peernode(p_ptr),
565 imp,
566 TIPC_CONN_MSG,
567 err,
568 p_ptr->last_in_seqno + 1,
569 0);
570}
571
572
573static struct sk_buff *port_build_peer_abort_msg(struct port *p_ptr, u32 err)
574{
575 u32 imp = msg_importance(&p_ptr->publ.phdr);
576
577 if (!p_ptr->publ.connected)
578 return 0;
579 if (imp < TIPC_CRITICAL_IMPORTANCE)
580 imp++;
581 return port_build_proto_msg(port_peerport(p_ptr),
582 port_peernode(p_ptr),
583 p_ptr->publ.ref,
584 tipc_own_addr,
585 imp,
586 TIPC_CONN_MSG,
587 err,
588 port_out_seqno(p_ptr),
589 0);
590}
591
592void port_recv_proto_msg(struct sk_buff *buf)
593{
594 struct tipc_msg *msg = buf_msg(buf);
595 struct port *p_ptr = port_lock(msg_destport(msg));
596 u32 err = TIPC_OK;
597 struct sk_buff *r_buf = 0;
598 struct sk_buff *abort_buf = 0;
599
600 msg_dbg(msg, "PORT<RECV<:");
601
602 if (!p_ptr) {
603 err = TIPC_ERR_NO_PORT;
604 } else if (p_ptr->publ.connected) {
605 if (port_peernode(p_ptr) != msg_orignode(msg))
606 err = TIPC_ERR_NO_PORT;
607 if (port_peerport(p_ptr) != msg_origport(msg))
608 err = TIPC_ERR_NO_PORT;
609 if (!err && msg_routed(msg)) {
610 u32 seqno = msg_transp_seqno(msg);
611 u32 myno = ++p_ptr->last_in_seqno;
612 if (seqno != myno) {
613 err = TIPC_ERR_NO_PORT;
614 abort_buf = port_build_self_abort_msg(p_ptr, err);
615 }
616 }
617 if (msg_type(msg) == CONN_ACK) {
618 int wakeup = port_congested(p_ptr) &&
619 p_ptr->publ.congested &&
620 p_ptr->wakeup;
621 p_ptr->acked += msg_msgcnt(msg);
622 if (port_congested(p_ptr))
623 goto exit;
624 p_ptr->publ.congested = 0;
625 if (!wakeup)
626 goto exit;
627 p_ptr->wakeup(&p_ptr->publ);
628 goto exit;
629 }
630 } else if (p_ptr->publ.published) {
631 err = TIPC_ERR_NO_PORT;
632 }
633 if (err) {
634 r_buf = port_build_proto_msg(msg_origport(msg),
635 msg_orignode(msg),
636 msg_destport(msg),
637 tipc_own_addr,
638 DATA_HIGH,
639 TIPC_CONN_MSG,
640 err,
641 0,
642 0);
643 goto exit;
644 }
645
646 /* All is fine */
647 if (msg_type(msg) == CONN_PROBE) {
648 r_buf = port_build_proto_msg(msg_origport(msg),
649 msg_orignode(msg),
650 msg_destport(msg),
651 tipc_own_addr,
652 CONN_MANAGER,
653 CONN_PROBE_REPLY,
654 TIPC_OK,
655 port_out_seqno(p_ptr),
656 0);
657 }
658 p_ptr->probing_state = CONFIRMED;
659 port_incr_out_seqno(p_ptr);
660exit:
661 if (p_ptr)
662 port_unlock(p_ptr);
663 net_route_msg(r_buf);
664 net_route_msg(abort_buf);
665 buf_discard(buf);
666}
667
668static void port_print(struct port *p_ptr, struct print_buf *buf, int full_id)
669{
670 struct publication *publ;
671
672 if (full_id)
673 tipc_printf(buf, "<%u.%u.%u:%u>:",
674 tipc_zone(tipc_own_addr), tipc_cluster(tipc_own_addr),
675 tipc_node(tipc_own_addr), p_ptr->publ.ref);
676 else
677 tipc_printf(buf, "%-10u:", p_ptr->publ.ref);
678
679 if (p_ptr->publ.connected) {
680 u32 dport = port_peerport(p_ptr);
681 u32 destnode = port_peernode(p_ptr);
682
683 tipc_printf(buf, " connected to <%u.%u.%u:%u>",
684 tipc_zone(destnode), tipc_cluster(destnode),
685 tipc_node(destnode), dport);
686 if (p_ptr->publ.conn_type != 0)
687 tipc_printf(buf, " via {%u,%u}",
688 p_ptr->publ.conn_type,
689 p_ptr->publ.conn_instance);
690 }
691 else if (p_ptr->publ.published) {
692 tipc_printf(buf, " bound to");
693 list_for_each_entry(publ, &p_ptr->publications, pport_list) {
694 if (publ->lower == publ->upper)
695 tipc_printf(buf, " {%u,%u}", publ->type,
696 publ->lower);
697 else
698 tipc_printf(buf, " {%u,%u,%u}", publ->type,
699 publ->lower, publ->upper);
700 }
701 }
702 tipc_printf(buf, "\n");
703}
704
705#define MAX_PORT_QUERY 32768
706
707struct sk_buff *port_get_ports(void)
708{
709 struct sk_buff *buf;
710 struct tlv_desc *rep_tlv;
711 struct print_buf pb;
712 struct port *p_ptr;
713 int str_len;
714
715 buf = cfg_reply_alloc(TLV_SPACE(MAX_PORT_QUERY));
716 if (!buf)
717 return NULL;
718 rep_tlv = (struct tlv_desc *)buf->data;
719
720 printbuf_init(&pb, TLV_DATA(rep_tlv), MAX_PORT_QUERY);
721 spin_lock_bh(&port_list_lock);
722 list_for_each_entry(p_ptr, &ports, port_list) {
723 spin_lock_bh(p_ptr->publ.lock);
724 port_print(p_ptr, &pb, 0);
725 spin_unlock_bh(p_ptr->publ.lock);
726 }
727 spin_unlock_bh(&port_list_lock);
728 str_len = printbuf_validate(&pb);
729
730 skb_put(buf, TLV_SPACE(str_len));
731 TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
732
733 return buf;
734}
735
736#if 0
737
738#define MAX_PORT_STATS 2000
739
740struct sk_buff *port_show_stats(const void *req_tlv_area, int req_tlv_space)
741{
742 u32 ref;
743 struct port *p_ptr;
744 struct sk_buff *buf;
745 struct tlv_desc *rep_tlv;
746 struct print_buf pb;
747 int str_len;
748
749 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_PORT_REF))
750 return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
751
752 ref = *(u32 *)TLV_DATA(req_tlv_area);
753 ref = ntohl(ref);
754
755 p_ptr = port_lock(ref);
756 if (!p_ptr)
757 return cfg_reply_error_string("port not found");
758
759 buf = cfg_reply_alloc(TLV_SPACE(MAX_PORT_STATS));
760 if (!buf) {
761 port_unlock(p_ptr);
762 return NULL;
763 }
764 rep_tlv = (struct tlv_desc *)buf->data;
765
766 printbuf_init(&pb, TLV_DATA(rep_tlv), MAX_PORT_STATS);
767 port_print(p_ptr, &pb, 1);
768 /* NEED TO FILL IN ADDITIONAL PORT STATISTICS HERE */
769 port_unlock(p_ptr);
770 str_len = printbuf_validate(&pb);
771
772 skb_put(buf, TLV_SPACE(str_len));
773 TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
774
775 return buf;
776}
777
778#endif
779
780void port_reinit(void)
781{
782 struct port *p_ptr;
783 struct tipc_msg *msg;
784
785 spin_lock_bh(&port_list_lock);
786 list_for_each_entry(p_ptr, &ports, port_list) {
787 msg = &p_ptr->publ.phdr;
788 if (msg_orignode(msg) == tipc_own_addr)
789 break;
790 msg_set_orignode(msg, tipc_own_addr);
791 }
792 spin_unlock_bh(&port_list_lock);
793}
794
795
796/*
797 * port_dispatcher_sigh(): Signal handler for messages destinated
798 * to the tipc_port interface.
799 */
800
801static void port_dispatcher_sigh(void *dummy)
802{
803 struct sk_buff *buf;
804
805 spin_lock_bh(&queue_lock);
806 buf = msg_queue_head;
807 msg_queue_head = 0;
808 spin_unlock_bh(&queue_lock);
809
810 while (buf) {
811 struct port *p_ptr;
812 struct user_port *up_ptr;
813 struct tipc_portid orig;
814 struct tipc_name_seq dseq;
815 void *usr_handle;
816 int connected;
817 int published;
818
819 struct sk_buff *next = buf->next;
820 struct tipc_msg *msg = buf_msg(buf);
821 u32 dref = msg_destport(msg);
822
823 p_ptr = port_lock(dref);
824 if (!p_ptr) {
825 /* Port deleted while msg in queue */
826 tipc_reject_msg(buf, TIPC_ERR_NO_PORT);
827 buf = next;
828 continue;
829 }
830 orig.ref = msg_origport(msg);
831 orig.node = msg_orignode(msg);
832 up_ptr = p_ptr->user_port;
833 usr_handle = up_ptr->usr_handle;
834 connected = p_ptr->publ.connected;
835 published = p_ptr->publ.published;
836
837 if (unlikely(msg_errcode(msg)))
838 goto err;
839
840 switch (msg_type(msg)) {
841
842 case TIPC_CONN_MSG:{
843 tipc_conn_msg_event cb = up_ptr->conn_msg_cb;
844 u32 peer_port = port_peerport(p_ptr);
845 u32 peer_node = port_peernode(p_ptr);
846
847 spin_unlock_bh(p_ptr->publ.lock);
848 if (unlikely(!connected)) {
849 if (unlikely(published))
850 goto reject;
851 tipc_connect2port(dref,&orig);
852 }
853 if (unlikely(msg_origport(msg) != peer_port))
854 goto reject;
855 if (unlikely(msg_orignode(msg) != peer_node))
856 goto reject;
857 if (unlikely(!cb))
858 goto reject;
859 if (unlikely(++p_ptr->publ.conn_unacked >=
860 TIPC_FLOW_CONTROL_WIN))
861 tipc_acknowledge(dref,
862 p_ptr->publ.conn_unacked);
863 skb_pull(buf, msg_hdr_sz(msg));
864 cb(usr_handle, dref, &buf, msg_data(msg),
865 msg_data_sz(msg));
866 break;
867 }
868 case TIPC_DIRECT_MSG:{
869 tipc_msg_event cb = up_ptr->msg_cb;
870
871 spin_unlock_bh(p_ptr->publ.lock);
872 if (unlikely(connected))
873 goto reject;
874 if (unlikely(!cb))
875 goto reject;
876 skb_pull(buf, msg_hdr_sz(msg));
877 cb(usr_handle, dref, &buf, msg_data(msg),
878 msg_data_sz(msg), msg_importance(msg),
879 &orig);
880 break;
881 }
882 case TIPC_NAMED_MSG:{
883 tipc_named_msg_event cb = up_ptr->named_msg_cb;
884
885 spin_unlock_bh(p_ptr->publ.lock);
886 if (unlikely(connected))
887 goto reject;
888 if (unlikely(!cb))
889 goto reject;
890 if (unlikely(!published))
891 goto reject;
892 dseq.type = msg_nametype(msg);
893 dseq.lower = msg_nameinst(msg);
894 dseq.upper = dseq.lower;
895 skb_pull(buf, msg_hdr_sz(msg));
896 cb(usr_handle, dref, &buf, msg_data(msg),
897 msg_data_sz(msg), msg_importance(msg),
898 &orig, &dseq);
899 break;
900 }
901 }
902 if (buf)
903 buf_discard(buf);
904 buf = next;
905 continue;
906err:
907 switch (msg_type(msg)) {
908
909 case TIPC_CONN_MSG:{
910 tipc_conn_shutdown_event cb =
911 up_ptr->conn_err_cb;
912 u32 peer_port = port_peerport(p_ptr);
913 u32 peer_node = port_peernode(p_ptr);
914
915 spin_unlock_bh(p_ptr->publ.lock);
916 if (!connected || !cb)
917 break;
918 if (msg_origport(msg) != peer_port)
919 break;
920 if (msg_orignode(msg) != peer_node)
921 break;
922 tipc_disconnect(dref);
923 skb_pull(buf, msg_hdr_sz(msg));
924 cb(usr_handle, dref, &buf, msg_data(msg),
925 msg_data_sz(msg), msg_errcode(msg));
926 break;
927 }
928 case TIPC_DIRECT_MSG:{
929 tipc_msg_err_event cb = up_ptr->err_cb;
930
931 spin_unlock_bh(p_ptr->publ.lock);
932 if (connected || !cb)
933 break;
934 skb_pull(buf, msg_hdr_sz(msg));
935 cb(usr_handle, dref, &buf, msg_data(msg),
936 msg_data_sz(msg), msg_errcode(msg), &orig);
937 break;
938 }
939 case TIPC_NAMED_MSG:{
940 tipc_named_msg_err_event cb =
941 up_ptr->named_err_cb;
942
943 spin_unlock_bh(p_ptr->publ.lock);
944 if (connected || !cb)
945 break;
946 dseq.type = msg_nametype(msg);
947 dseq.lower = msg_nameinst(msg);
948 dseq.upper = dseq.lower;
949 skb_pull(buf, msg_hdr_sz(msg));
950 cb(usr_handle, dref, &buf, msg_data(msg),
951 msg_data_sz(msg), msg_errcode(msg), &dseq);
952 break;
953 }
954 }
955 if (buf)
956 buf_discard(buf);
957 buf = next;
958 continue;
959reject:
960 tipc_reject_msg(buf, TIPC_ERR_NO_PORT);
961 buf = next;
962 }
963}
964
965/*
966 * port_dispatcher(): Dispatcher for messages destinated
967 * to the tipc_port interface. Called with port locked.
968 */
969
970static u32 port_dispatcher(struct tipc_port *dummy, struct sk_buff *buf)
971{
972 buf->next = NULL;
973 spin_lock_bh(&queue_lock);
974 if (msg_queue_head) {
975 msg_queue_tail->next = buf;
976 msg_queue_tail = buf;
977 } else {
978 msg_queue_tail = msg_queue_head = buf;
979 k_signal((Handler)port_dispatcher_sigh, 0);
980 }
981 spin_unlock_bh(&queue_lock);
982 return TIPC_OK;
983}
984
985/*
986 * Wake up port after congestion: Called with port locked,
987 *
988 */
989
990static void port_wakeup_sh(unsigned long ref)
991{
992 struct port *p_ptr;
993 struct user_port *up_ptr;
994 tipc_continue_event cb = 0;
995 void *uh = 0;
996
997 p_ptr = port_lock(ref);
998 if (p_ptr) {
999 up_ptr = p_ptr->user_port;
1000 if (up_ptr) {
1001 cb = up_ptr->continue_event_cb;
1002 uh = up_ptr->usr_handle;
1003 }
1004 port_unlock(p_ptr);
1005 }
1006 if (cb)
1007 cb(uh, ref);
1008}
1009
1010
1011static void port_wakeup(struct tipc_port *p_ptr)
1012{
1013 k_signal((Handler)port_wakeup_sh, p_ptr->ref);
1014}
1015
1016void tipc_acknowledge(u32 ref, u32 ack)
1017{
1018 struct port *p_ptr;
1019 struct sk_buff *buf = 0;
1020
1021 p_ptr = port_lock(ref);
1022 if (!p_ptr)
1023 return;
1024 if (p_ptr->publ.connected) {
1025 p_ptr->publ.conn_unacked -= ack;
1026 buf = port_build_proto_msg(port_peerport(p_ptr),
1027 port_peernode(p_ptr),
1028 ref,
1029 tipc_own_addr,
1030 CONN_MANAGER,
1031 CONN_ACK,
1032 TIPC_OK,
1033 port_out_seqno(p_ptr),
1034 ack);
1035 }
1036 port_unlock(p_ptr);
1037 net_route_msg(buf);
1038}
1039
1040/*
1041 * tipc_createport(): user level call. Will add port to
1042 * registry if non-zero user_ref.
1043 */
1044
1045int tipc_createport(u32 user_ref,
1046 void *usr_handle,
1047 unsigned int importance,
1048 tipc_msg_err_event error_cb,
1049 tipc_named_msg_err_event named_error_cb,
1050 tipc_conn_shutdown_event conn_error_cb,
1051 tipc_msg_event msg_cb,
1052 tipc_named_msg_event named_msg_cb,
1053 tipc_conn_msg_event conn_msg_cb,
1054 tipc_continue_event continue_event_cb,/* May be zero */
1055 u32 *portref)
1056{
1057 struct user_port *up_ptr;
1058 struct port *p_ptr;
1059 u32 ref;
1060
1061 up_ptr = (struct user_port *)kmalloc(sizeof(*up_ptr), GFP_ATOMIC);
1062 if (up_ptr == NULL) {
1063 return -ENOMEM;
1064 }
1065 ref = tipc_createport_raw(0, port_dispatcher, port_wakeup, importance);
1066 p_ptr = port_lock(ref);
1067 if (!p_ptr) {
1068 kfree(up_ptr);
1069 return -ENOMEM;
1070 }
1071
1072 p_ptr->user_port = up_ptr;
1073 up_ptr->user_ref = user_ref;
1074 up_ptr->usr_handle = usr_handle;
1075 up_ptr->ref = p_ptr->publ.ref;
1076 up_ptr->err_cb = error_cb;
1077 up_ptr->named_err_cb = named_error_cb;
1078 up_ptr->conn_err_cb = conn_error_cb;
1079 up_ptr->msg_cb = msg_cb;
1080 up_ptr->named_msg_cb = named_msg_cb;
1081 up_ptr->conn_msg_cb = conn_msg_cb;
1082 up_ptr->continue_event_cb = continue_event_cb;
1083 INIT_LIST_HEAD(&up_ptr->uport_list);
1084 reg_add_port(up_ptr);
1085 *portref = p_ptr->publ.ref;
1086 dbg(" tipc_createport: %x with ref %u\n", p_ptr, p_ptr->publ.ref);
1087 port_unlock(p_ptr);
1088 return TIPC_OK;
1089}
1090
1091int tipc_ownidentity(u32 ref, struct tipc_portid *id)
1092{
1093 id->ref = ref;
1094 id->node = tipc_own_addr;
1095 return TIPC_OK;
1096}
1097
1098int tipc_portimportance(u32 ref, unsigned int *importance)
1099{
1100 struct port *p_ptr;
1101
1102 p_ptr = port_lock(ref);
1103 if (!p_ptr)
1104 return -EINVAL;
1105 *importance = (unsigned int)msg_importance(&p_ptr->publ.phdr);
1106 spin_unlock_bh(p_ptr->publ.lock);
1107 return TIPC_OK;
1108}
1109
1110int tipc_set_portimportance(u32 ref, unsigned int imp)
1111{
1112 struct port *p_ptr;
1113
1114 if (imp > TIPC_CRITICAL_IMPORTANCE)
1115 return -EINVAL;
1116
1117 p_ptr = port_lock(ref);
1118 if (!p_ptr)
1119 return -EINVAL;
1120 msg_set_importance(&p_ptr->publ.phdr, (u32)imp);
1121 spin_unlock_bh(p_ptr->publ.lock);
1122 return TIPC_OK;
1123}
1124
1125
1126int tipc_publish(u32 ref, unsigned int scope, struct tipc_name_seq const *seq)
1127{
1128 struct port *p_ptr;
1129 struct publication *publ;
1130 u32 key;
1131 int res = -EINVAL;
1132
1133 p_ptr = port_lock(ref);
1134 dbg("tipc_publ %u, p_ptr = %x, conn = %x, scope = %x, "
1135 "lower = %u, upper = %u\n",
1136 ref, p_ptr, p_ptr->publ.connected, scope, seq->lower, seq->upper);
1137 if (!p_ptr)
1138 return -EINVAL;
1139 if (p_ptr->publ.connected)
1140 goto exit;
1141 if (seq->lower > seq->upper)
1142 goto exit;
1143 if ((scope < TIPC_ZONE_SCOPE) || (scope > TIPC_NODE_SCOPE))
1144 goto exit;
1145 key = ref + p_ptr->pub_count + 1;
1146 if (key == ref) {
1147 res = -EADDRINUSE;
1148 goto exit;
1149 }
1150 publ = nametbl_publish(seq->type, seq->lower, seq->upper,
1151 scope, p_ptr->publ.ref, key);
1152 if (publ) {
1153 list_add(&publ->pport_list, &p_ptr->publications);
1154 p_ptr->pub_count++;
1155 p_ptr->publ.published = 1;
1156 res = TIPC_OK;
1157 }
1158exit:
1159 port_unlock(p_ptr);
1160 return res;
1161}
1162
1163int tipc_withdraw(u32 ref, unsigned int scope, struct tipc_name_seq const *seq)
1164{
1165 struct port *p_ptr;
1166 struct publication *publ;
1167 struct publication *tpubl;
1168 int res = -EINVAL;
1169
1170 p_ptr = port_lock(ref);
1171 if (!p_ptr)
1172 return -EINVAL;
1173 if (!p_ptr->publ.published)
1174 goto exit;
1175 if (!seq) {
1176 list_for_each_entry_safe(publ, tpubl,
1177 &p_ptr->publications, pport_list) {
1178 nametbl_withdraw(publ->type, publ->lower,
1179 publ->ref, publ->key);
1180 }
1181 res = TIPC_OK;
1182 } else {
1183 list_for_each_entry_safe(publ, tpubl,
1184 &p_ptr->publications, pport_list) {
1185 if (publ->scope != scope)
1186 continue;
1187 if (publ->type != seq->type)
1188 continue;
1189 if (publ->lower != seq->lower)
1190 continue;
1191 if (publ->upper != seq->upper)
1192 break;
1193 nametbl_withdraw(publ->type, publ->lower,
1194 publ->ref, publ->key);
1195 res = TIPC_OK;
1196 break;
1197 }
1198 }
1199 if (list_empty(&p_ptr->publications))
1200 p_ptr->publ.published = 0;
1201exit:
1202 port_unlock(p_ptr);
1203 return res;
1204}
1205
1206int tipc_connect2port(u32 ref, struct tipc_portid const *peer)
1207{
1208 struct port *p_ptr;
1209 struct tipc_msg *msg;
1210 int res = -EINVAL;
1211
1212 p_ptr = port_lock(ref);
1213 if (!p_ptr)
1214 return -EINVAL;
1215 if (p_ptr->publ.published || p_ptr->publ.connected)
1216 goto exit;
1217 if (!peer->ref)
1218 goto exit;
1219
1220 msg = &p_ptr->publ.phdr;
1221 msg_set_destnode(msg, peer->node);
1222 msg_set_destport(msg, peer->ref);
1223 msg_set_orignode(msg, tipc_own_addr);
1224 msg_set_origport(msg, p_ptr->publ.ref);
1225 msg_set_transp_seqno(msg, 42);
1226 msg_set_type(msg, TIPC_CONN_MSG);
1227 if (!may_route(peer->node))
1228 msg_set_hdr_sz(msg, SHORT_H_SIZE);
1229 else
1230 msg_set_hdr_sz(msg, LONG_H_SIZE);
1231
1232 p_ptr->probing_interval = PROBING_INTERVAL;
1233 p_ptr->probing_state = CONFIRMED;
1234 p_ptr->publ.connected = 1;
1235 k_start_timer(&p_ptr->timer, p_ptr->probing_interval);
1236
1237 nodesub_subscribe(&p_ptr->subscription,peer->node,
1238 (void *)(unsigned long)ref,
1239 (net_ev_handler)port_handle_node_down);
1240 res = TIPC_OK;
1241exit:
1242 port_unlock(p_ptr);
1243 p_ptr->max_pkt = link_get_max_pkt(peer->node, ref);
1244 return res;
1245}
1246
1247/*
1248 * tipc_disconnect(): Disconnect port form peer.
1249 * This is a node local operation.
1250 */
1251
1252int tipc_disconnect(u32 ref)
1253{
1254 struct port *p_ptr;
1255 int res = -ENOTCONN;
1256
1257 p_ptr = port_lock(ref);
1258 if (!p_ptr)
1259 return -EINVAL;
1260 if (p_ptr->publ.connected) {
1261 p_ptr->publ.connected = 0;
1262 /* let timer expire on it's own to avoid deadlock! */
1263 nodesub_unsubscribe(&p_ptr->subscription);
1264 res = TIPC_OK;
1265 }
1266 port_unlock(p_ptr);
1267 return res;
1268}
1269
1270/*
1271 * tipc_shutdown(): Send a SHUTDOWN msg to peer and disconnect
1272 */
1273int tipc_shutdown(u32 ref)
1274{
1275 struct port *p_ptr;
1276 struct sk_buff *buf = 0;
1277
1278 p_ptr = port_lock(ref);
1279 if (!p_ptr)
1280 return -EINVAL;
1281
1282 if (p_ptr->publ.connected) {
1283 u32 imp = msg_importance(&p_ptr->publ.phdr);
1284 if (imp < TIPC_CRITICAL_IMPORTANCE)
1285 imp++;
1286 buf = port_build_proto_msg(port_peerport(p_ptr),
1287 port_peernode(p_ptr),
1288 ref,
1289 tipc_own_addr,
1290 imp,
1291 TIPC_CONN_MSG,
1292 TIPC_CONN_SHUTDOWN,
1293 port_out_seqno(p_ptr),
1294 0);
1295 }
1296 port_unlock(p_ptr);
1297 net_route_msg(buf);
1298 return tipc_disconnect(ref);
1299}
1300
1301int tipc_isconnected(u32 ref, int *isconnected)
1302{
1303 struct port *p_ptr;
1304
1305 p_ptr = port_lock(ref);
1306 if (!p_ptr)
1307 return -EINVAL;
1308 *isconnected = p_ptr->publ.connected;
1309 port_unlock(p_ptr);
1310 return TIPC_OK;
1311}
1312
1313int tipc_peer(u32 ref, struct tipc_portid *peer)
1314{
1315 struct port *p_ptr;
1316 int res;
1317
1318 p_ptr = port_lock(ref);
1319 if (!p_ptr)
1320 return -EINVAL;
1321 if (p_ptr->publ.connected) {
1322 peer->ref = port_peerport(p_ptr);
1323 peer->node = port_peernode(p_ptr);
1324 res = TIPC_OK;
1325 } else
1326 res = -ENOTCONN;
1327 port_unlock(p_ptr);
1328 return res;
1329}
1330
1331int tipc_ref_valid(u32 ref)
1332{
1333 /* Works irrespective of type */
1334 return !!ref_deref(ref);
1335}
1336
1337
1338/*
1339 * port_recv_sections(): Concatenate and deliver sectioned
1340 * message for this node.
1341 */
1342
1343int port_recv_sections(struct port *sender, unsigned int num_sect,
1344 struct iovec const *msg_sect)
1345{
1346 struct sk_buff *buf;
1347 int res;
1348
1349 res = msg_build(&sender->publ.phdr, msg_sect, num_sect,
1350 MAX_MSG_SIZE, !sender->user_port, &buf);
1351 if (likely(buf))
1352 port_recv_msg(buf);
1353 return res;
1354}
1355
1356/**
1357 * tipc_send - send message sections on connection
1358 */
1359
1360int tipc_send(u32 ref, unsigned int num_sect, struct iovec const *msg_sect)
1361{
1362 struct port *p_ptr;
1363 u32 destnode;
1364 int res;
1365
1366 p_ptr = port_deref(ref);
1367 if (!p_ptr || !p_ptr->publ.connected)
1368 return -EINVAL;
1369
1370 p_ptr->publ.congested = 1;
1371 if (!port_congested(p_ptr)) {
1372 destnode = port_peernode(p_ptr);
1373 if (likely(destnode != tipc_own_addr))
1374 res = link_send_sections_fast(p_ptr, msg_sect, num_sect,
1375 destnode);
1376 else
1377 res = port_recv_sections(p_ptr, num_sect, msg_sect);
1378
1379 if (likely(res != -ELINKCONG)) {
1380 port_incr_out_seqno(p_ptr);
1381 p_ptr->publ.congested = 0;
1382 p_ptr->sent++;
1383 return res;
1384 }
1385 }
1386 if (port_unreliable(p_ptr)) {
1387 p_ptr->publ.congested = 0;
1388 /* Just calculate msg length and return */
1389 return msg_calc_data_size(msg_sect, num_sect);
1390 }
1391 return -ELINKCONG;
1392}
1393
1394/**
1395 * tipc_send_buf - send message buffer on connection
1396 */
1397
1398int tipc_send_buf(u32 ref, struct sk_buff *buf, unsigned int dsz)
1399{
1400 struct port *p_ptr;
1401 struct tipc_msg *msg;
1402 u32 destnode;
1403 u32 hsz;
1404 u32 sz;
1405 u32 res;
1406
1407 p_ptr = port_deref(ref);
1408 if (!p_ptr || !p_ptr->publ.connected)
1409 return -EINVAL;
1410
1411 msg = &p_ptr->publ.phdr;
1412 hsz = msg_hdr_sz(msg);
1413 sz = hsz + dsz;
1414 msg_set_size(msg, sz);
1415 if (skb_cow(buf, hsz))
1416 return -ENOMEM;
1417
1418 skb_push(buf, hsz);
1419 memcpy(buf->data, (unchar *)msg, hsz);
1420 destnode = msg_destnode(msg);
1421 p_ptr->publ.congested = 1;
1422 if (!port_congested(p_ptr)) {
1423 if (likely(destnode != tipc_own_addr))
1424 res = tipc_send_buf_fast(buf, destnode);
1425 else {
1426 port_recv_msg(buf);
1427 res = sz;
1428 }
1429 if (likely(res != -ELINKCONG)) {
1430 port_incr_out_seqno(p_ptr);
1431 p_ptr->sent++;
1432 p_ptr->publ.congested = 0;
1433 return res;
1434 }
1435 }
1436 if (port_unreliable(p_ptr)) {
1437 p_ptr->publ.congested = 0;
1438 return dsz;
1439 }
1440 return -ELINKCONG;
1441}
1442
1443/**
1444 * tipc_forward2name - forward message sections to port name
1445 */
1446
1447int tipc_forward2name(u32 ref,
1448 struct tipc_name const *name,
1449 u32 domain,
1450 u32 num_sect,
1451 struct iovec const *msg_sect,
1452 struct tipc_portid const *orig,
1453 unsigned int importance)
1454{
1455 struct port *p_ptr;
1456 struct tipc_msg *msg;
1457 u32 destnode = domain;
1458 u32 destport = 0;
1459 int res;
1460
1461 p_ptr = port_deref(ref);
1462 if (!p_ptr || p_ptr->publ.connected)
1463 return -EINVAL;
1464
1465 msg = &p_ptr->publ.phdr;
1466 msg_set_type(msg, TIPC_NAMED_MSG);
1467 msg_set_orignode(msg, orig->node);
1468 msg_set_origport(msg, orig->ref);
1469 msg_set_hdr_sz(msg, LONG_H_SIZE);
1470 msg_set_nametype(msg, name->type);
1471 msg_set_nameinst(msg, name->instance);
1472 msg_set_lookup_scope(msg, addr_scope(domain));
1473 if (importance <= TIPC_CRITICAL_IMPORTANCE)
1474 msg_set_importance(msg,importance);
1475 destport = nametbl_translate(name->type, name->instance, &destnode);
1476 msg_set_destnode(msg, destnode);
1477 msg_set_destport(msg, destport);
1478
1479 if (likely(destport || destnode)) {
1480 p_ptr->sent++;
1481 if (likely(destnode == tipc_own_addr))
1482 return port_recv_sections(p_ptr, num_sect, msg_sect);
1483 res = link_send_sections_fast(p_ptr, msg_sect, num_sect,
1484 destnode);
1485 if (likely(res != -ELINKCONG))
1486 return res;
1487 if (port_unreliable(p_ptr)) {
1488 /* Just calculate msg length and return */
1489 return msg_calc_data_size(msg_sect, num_sect);
1490 }
1491 return -ELINKCONG;
1492 }
1493 return port_reject_sections(p_ptr, msg, msg_sect, num_sect,
1494 TIPC_ERR_NO_NAME);
1495}
1496
1497/**
1498 * tipc_send2name - send message sections to port name
1499 */
1500
1501int tipc_send2name(u32 ref,
1502 struct tipc_name const *name,
1503 unsigned int domain,
1504 unsigned int num_sect,
1505 struct iovec const *msg_sect)
1506{
1507 struct tipc_portid orig;
1508
1509 orig.ref = ref;
1510 orig.node = tipc_own_addr;
1511 return tipc_forward2name(ref, name, domain, num_sect, msg_sect, &orig,
1512 TIPC_PORT_IMPORTANCE);
1513}
1514
1515/**
1516 * tipc_forward_buf2name - forward message buffer to port name
1517 */
1518
1519int tipc_forward_buf2name(u32 ref,
1520 struct tipc_name const *name,
1521 u32 domain,
1522 struct sk_buff *buf,
1523 unsigned int dsz,
1524 struct tipc_portid const *orig,
1525 unsigned int importance)
1526{
1527 struct port *p_ptr;
1528 struct tipc_msg *msg;
1529 u32 destnode = domain;
1530 u32 destport = 0;
1531 int res;
1532
1533 p_ptr = (struct port *)ref_deref(ref);
1534 if (!p_ptr || p_ptr->publ.connected)
1535 return -EINVAL;
1536
1537 msg = &p_ptr->publ.phdr;
1538 if (importance <= TIPC_CRITICAL_IMPORTANCE)
1539 msg_set_importance(msg, importance);
1540 msg_set_type(msg, TIPC_NAMED_MSG);
1541 msg_set_orignode(msg, orig->node);
1542 msg_set_origport(msg, orig->ref);
1543 msg_set_nametype(msg, name->type);
1544 msg_set_nameinst(msg, name->instance);
1545 msg_set_lookup_scope(msg, addr_scope(domain));
1546 msg_set_hdr_sz(msg, LONG_H_SIZE);
1547 msg_set_size(msg, LONG_H_SIZE + dsz);
1548 destport = nametbl_translate(name->type, name->instance, &destnode);
1549 msg_set_destnode(msg, destnode);
1550 msg_set_destport(msg, destport);
1551 msg_dbg(msg, "forw2name ==> ");
1552 if (skb_cow(buf, LONG_H_SIZE))
1553 return -ENOMEM;
1554 skb_push(buf, LONG_H_SIZE);
1555 memcpy(buf->data, (unchar *)msg, LONG_H_SIZE);
1556 msg_dbg(buf_msg(buf),"PREP:");
1557 if (likely(destport || destnode)) {
1558 p_ptr->sent++;
1559 if (destnode == tipc_own_addr)
1560 return port_recv_msg(buf);
1561 res = tipc_send_buf_fast(buf, destnode);
1562 if (likely(res != -ELINKCONG))
1563 return res;
1564 if (port_unreliable(p_ptr))
1565 return dsz;
1566 return -ELINKCONG;
1567 }
1568 return tipc_reject_msg(buf, TIPC_ERR_NO_NAME);
1569}
1570
1571/**
1572 * tipc_send_buf2name - send message buffer to port name
1573 */
1574
1575int tipc_send_buf2name(u32 ref,
1576 struct tipc_name const *dest,
1577 u32 domain,
1578 struct sk_buff *buf,
1579 unsigned int dsz)
1580{
1581 struct tipc_portid orig;
1582
1583 orig.ref = ref;
1584 orig.node = tipc_own_addr;
1585 return tipc_forward_buf2name(ref, dest, domain, buf, dsz, &orig,
1586 TIPC_PORT_IMPORTANCE);
1587}
1588
1589/**
1590 * tipc_forward2port - forward message sections to port identity
1591 */
1592
1593int tipc_forward2port(u32 ref,
1594 struct tipc_portid const *dest,
1595 unsigned int num_sect,
1596 struct iovec const *msg_sect,
1597 struct tipc_portid const *orig,
1598 unsigned int importance)
1599{
1600 struct port *p_ptr;
1601 struct tipc_msg *msg;
1602 int res;
1603
1604 p_ptr = port_deref(ref);
1605 if (!p_ptr || p_ptr->publ.connected)
1606 return -EINVAL;
1607
1608 msg = &p_ptr->publ.phdr;
1609 msg_set_type(msg, TIPC_DIRECT_MSG);
1610 msg_set_orignode(msg, orig->node);
1611 msg_set_origport(msg, orig->ref);
1612 msg_set_destnode(msg, dest->node);
1613 msg_set_destport(msg, dest->ref);
1614 msg_set_hdr_sz(msg, DIR_MSG_H_SIZE);
1615 if (importance <= TIPC_CRITICAL_IMPORTANCE)
1616 msg_set_importance(msg, importance);
1617 p_ptr->sent++;
1618 if (dest->node == tipc_own_addr)
1619 return port_recv_sections(p_ptr, num_sect, msg_sect);
1620 res = link_send_sections_fast(p_ptr, msg_sect, num_sect, dest->node);
1621 if (likely(res != -ELINKCONG))
1622 return res;
1623 if (port_unreliable(p_ptr)) {
1624 /* Just calculate msg length and return */
1625 return msg_calc_data_size(msg_sect, num_sect);
1626 }
1627 return -ELINKCONG;
1628}
1629
1630/**
1631 * tipc_send2port - send message sections to port identity
1632 */
1633
1634int tipc_send2port(u32 ref,
1635 struct tipc_portid const *dest,
1636 unsigned int num_sect,
1637 struct iovec const *msg_sect)
1638{
1639 struct tipc_portid orig;
1640
1641 orig.ref = ref;
1642 orig.node = tipc_own_addr;
1643 return tipc_forward2port(ref, dest, num_sect, msg_sect, &orig,
1644 TIPC_PORT_IMPORTANCE);
1645}
1646
1647/**
1648 * tipc_forward_buf2port - forward message buffer to port identity
1649 */
1650int tipc_forward_buf2port(u32 ref,
1651 struct tipc_portid const *dest,
1652 struct sk_buff *buf,
1653 unsigned int dsz,
1654 struct tipc_portid const *orig,
1655 unsigned int importance)
1656{
1657 struct port *p_ptr;
1658 struct tipc_msg *msg;
1659 int res;
1660
1661 p_ptr = (struct port *)ref_deref(ref);
1662 if (!p_ptr || p_ptr->publ.connected)
1663 return -EINVAL;
1664
1665 msg = &p_ptr->publ.phdr;
1666 msg_set_type(msg, TIPC_DIRECT_MSG);
1667 msg_set_orignode(msg, orig->node);
1668 msg_set_origport(msg, orig->ref);
1669 msg_set_destnode(msg, dest->node);
1670 msg_set_destport(msg, dest->ref);
1671 msg_set_hdr_sz(msg, DIR_MSG_H_SIZE);
1672 if (importance <= TIPC_CRITICAL_IMPORTANCE)
1673 msg_set_importance(msg, importance);
1674 msg_set_size(msg, DIR_MSG_H_SIZE + dsz);
1675 if (skb_cow(buf, DIR_MSG_H_SIZE))
1676 return -ENOMEM;
1677
1678 skb_push(buf, DIR_MSG_H_SIZE);
1679 memcpy(buf->data, (unchar *)msg, DIR_MSG_H_SIZE);
1680 msg_dbg(msg, "buf2port: ");
1681 p_ptr->sent++;
1682 if (dest->node == tipc_own_addr)
1683 return port_recv_msg(buf);
1684 res = tipc_send_buf_fast(buf, dest->node);
1685 if (likely(res != -ELINKCONG))
1686 return res;
1687 if (port_unreliable(p_ptr))
1688 return dsz;
1689 return -ELINKCONG;
1690}
1691
1692/**
1693 * tipc_send_buf2port - send message buffer to port identity
1694 */
1695
1696int tipc_send_buf2port(u32 ref,
1697 struct tipc_portid const *dest,
1698 struct sk_buff *buf,
1699 unsigned int dsz)
1700{
1701 struct tipc_portid orig;
1702
1703 orig.ref = ref;
1704 orig.node = tipc_own_addr;
1705 return tipc_forward_buf2port(ref, dest, buf, dsz, &orig,
1706 TIPC_PORT_IMPORTANCE);
1707}
1708
diff --git a/net/tipc/port.h b/net/tipc/port.h
new file mode 100644
index 000000000000..e829a99d3b7f
--- /dev/null
+++ b/net/tipc/port.h
@@ -0,0 +1,209 @@
1/*
2 * net/tipc/port.h: Include file for TIPC port code
3 *
4 * Copyright (c) 1994-2006, Ericsson AB
5 * Copyright (c) 2004-2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#ifndef _TIPC_PORT_H
38#define _TIPC_PORT_H
39
40#include <net/tipc/tipc_port.h>
41#include "ref.h"
42#include "net.h"
43#include "msg.h"
44#include "dbg.h"
45#include "node_subscr.h"
46
47/**
48 * struct user_port - TIPC user port (used with native API)
49 * @user_ref: id of user who created user port
50 * @usr_handle: user-specified field
51 * @ref: object reference to associated TIPC port
52 * <various callback routines>
53 * @uport_list: adjacent user ports in list of ports held by user
54 */
55
56struct user_port {
57 u32 user_ref;
58 void *usr_handle;
59 u32 ref;
60 tipc_msg_err_event err_cb;
61 tipc_named_msg_err_event named_err_cb;
62 tipc_conn_shutdown_event conn_err_cb;
63 tipc_msg_event msg_cb;
64 tipc_named_msg_event named_msg_cb;
65 tipc_conn_msg_event conn_msg_cb;
66 tipc_continue_event continue_event_cb;
67 struct list_head uport_list;
68};
69
70/**
71 * struct port - TIPC port structure
72 * @publ: TIPC port info available to privileged users
73 * @port_list: adjacent ports in TIPC's global list of ports
74 * @dispatcher: ptr to routine which handles received messages
75 * @wakeup: ptr to routine to call when port is no longer congested
76 * @user_port: ptr to user port associated with port (if any)
77 * @wait_list: adjacent ports in list of ports waiting on link congestion
78 * @congested_link: ptr to congested link port is waiting on
79 * @waiting_pkts:
80 * @sent:
81 * @acked:
82 * @publications: list of publications for port
83 * @pub_count: total # of publications port has made during its lifetime
84 * @max_pkt: maximum packet size "hint" used when building messages sent by port
85 * @probing_state:
86 * @probing_interval:
87 * @last_in_seqno:
88 * @timer_ref:
89 * @subscription: "node down" subscription used to terminate failed connections
90 */
91
92struct port {
93 struct tipc_port publ;
94 struct list_head port_list;
95 u32 (*dispatcher)(struct tipc_port *, struct sk_buff *);
96 void (*wakeup)(struct tipc_port *);
97 struct user_port *user_port;
98 struct list_head wait_list;
99 struct link *congested_link;
100 u32 waiting_pkts;
101 u32 sent;
102 u32 acked;
103 struct list_head publications;
104 u32 pub_count;
105 u32 max_pkt;
106 u32 probing_state;
107 u32 probing_interval;
108 u32 last_in_seqno;
109 struct timer_list timer;
110 struct node_subscr subscription;
111};
112
113extern spinlock_t port_list_lock;
114struct port_list;
115
116int port_recv_sections(struct port *p_ptr, u32 num_sect,
117 struct iovec const *msg_sect);
118int port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr,
119 struct iovec const *msg_sect, u32 num_sect,
120 int err);
121struct sk_buff *port_get_ports(void);
122struct sk_buff *port_show_stats(const void *req_tlv_area, int req_tlv_space);
123void port_recv_proto_msg(struct sk_buff *buf);
124void port_recv_mcast(struct sk_buff *buf, struct port_list *dp);
125void port_reinit(void);
126
127/**
128 * port_lock - lock port instance referred to and return its pointer
129 */
130
131static inline struct port *port_lock(u32 ref)
132{
133 return (struct port *)ref_lock(ref);
134}
135
136/**
137 * port_unlock - unlock a port instance
138 *
139 * Can use pointer instead of ref_unlock() since port is already locked.
140 */
141
142static inline void port_unlock(struct port *p_ptr)
143{
144 spin_unlock_bh(p_ptr->publ.lock);
145}
146
147static inline struct port* port_deref(u32 ref)
148{
149 return (struct port *)ref_deref(ref);
150}
151
152static inline u32 peer_port(struct port *p_ptr)
153{
154 return msg_destport(&p_ptr->publ.phdr);
155}
156
157static inline u32 peer_node(struct port *p_ptr)
158{
159 return msg_destnode(&p_ptr->publ.phdr);
160}
161
162static inline int port_congested(struct port *p_ptr)
163{
164 return((p_ptr->sent - p_ptr->acked) >= (TIPC_FLOW_CONTROL_WIN * 2));
165}
166
167/**
168 * port_recv_msg - receive message from lower layer and deliver to port user
169 */
170
171static inline int port_recv_msg(struct sk_buff *buf)
172{
173 struct port *p_ptr;
174 struct tipc_msg *msg = buf_msg(buf);
175 u32 destport = msg_destport(msg);
176 u32 dsz = msg_data_sz(msg);
177 u32 err;
178
179 /* forward unresolved named message */
180 if (unlikely(!destport)) {
181 net_route_msg(buf);
182 return dsz;
183 }
184
185 /* validate destination & pass to port, otherwise reject message */
186 p_ptr = port_lock(destport);
187 if (likely(p_ptr)) {
188 if (likely(p_ptr->publ.connected)) {
189 if ((unlikely(msg_origport(msg) != peer_port(p_ptr))) ||
190 (unlikely(msg_orignode(msg) != peer_node(p_ptr))) ||
191 (unlikely(!msg_connected(msg)))) {
192 err = TIPC_ERR_NO_PORT;
193 port_unlock(p_ptr);
194 goto reject;
195 }
196 }
197 err = p_ptr->dispatcher(&p_ptr->publ, buf);
198 port_unlock(p_ptr);
199 if (likely(!err))
200 return dsz;
201 } else {
202 err = TIPC_ERR_NO_PORT;
203 }
204reject:
205 dbg("port->rejecting, err = %x..\n",err);
206 return tipc_reject_msg(buf, err);
207}
208
209#endif
diff --git a/net/tipc/ref.c b/net/tipc/ref.c
new file mode 100644
index 000000000000..944093fe246f
--- /dev/null
+++ b/net/tipc/ref.c
@@ -0,0 +1,189 @@
1/*
2 * net/tipc/ref.c: TIPC object registry code
3 *
4 * Copyright (c) 1991-2006, Ericsson AB
5 * Copyright (c) 2004-2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include "core.h"
38#include "ref.h"
39#include "port.h"
40#include "subscr.h"
41#include "name_distr.h"
42#include "name_table.h"
43#include "config.h"
44#include "discover.h"
45#include "bearer.h"
46#include "node.h"
47#include "bcast.h"
48
49/*
50 * Object reference table consists of 2**N entries.
51 *
52 * A used entry has object ptr != 0, reference == XXXX|own index
53 * (XXXX changes each time entry is acquired)
54 * A free entry has object ptr == 0, reference == YYYY|next free index
55 * (YYYY is one more than last used XXXX)
56 *
57 * Free list is initially chained from entry (2**N)-1 to entry 1.
58 * Entry 0 is not used to allow index 0 to indicate the end of the free list.
59 *
60 * Note: Any accidental reference of the form XXXX|0--0 won't match entry 0
61 * because entry 0's reference field has the form XXXX|1--1.
62 */
63
64struct ref_table ref_table = { 0 };
65
66rwlock_t reftbl_lock = RW_LOCK_UNLOCKED;
67
68/**
69 * ref_table_init - create reference table for objects
70 */
71
72int ref_table_init(u32 requested_size, u32 start)
73{
74 struct reference *table;
75 u32 sz = 1 << 4;
76 u32 index_mask;
77 int i;
78
79 while (sz < requested_size) {
80 sz <<= 1;
81 }
82 table = (struct reference *)vmalloc(sz * sizeof(struct reference));
83 if (table == NULL)
84 return -ENOMEM;
85
86 write_lock_bh(&reftbl_lock);
87 index_mask = sz - 1;
88 for (i = sz - 1; i >= 0; i--) {
89 table[i].object = 0;
90 table[i].lock = SPIN_LOCK_UNLOCKED;
91 table[i].data.next_plus_upper = (start & ~index_mask) + i - 1;
92 }
93 ref_table.entries = table;
94 ref_table.index_mask = index_mask;
95 ref_table.first_free = sz - 1;
96 ref_table.last_free = 1;
97 write_unlock_bh(&reftbl_lock);
98 return TIPC_OK;
99}
100
101/**
102 * ref_table_stop - destroy reference table for objects
103 */
104
105void ref_table_stop(void)
106{
107 if (!ref_table.entries)
108 return;
109
110 vfree(ref_table.entries);
111 ref_table.entries = 0;
112}
113
114/**
115 * ref_acquire - create reference to an object
116 *
117 * Return a unique reference value which can be translated back to the pointer
118 * 'object' at a later time. Also, pass back a pointer to the lock protecting
119 * the object, but without locking it.
120 */
121
122u32 ref_acquire(void *object, spinlock_t **lock)
123{
124 struct reference *entry;
125 u32 index;
126 u32 index_mask;
127 u32 next_plus_upper;
128 u32 reference = 0;
129
130 assert(ref_table.entries && object);
131
132 write_lock_bh(&reftbl_lock);
133 if (ref_table.first_free) {
134 index = ref_table.first_free;
135 entry = &(ref_table.entries[index]);
136 index_mask = ref_table.index_mask;
137 /* take lock in case a previous user of entry still holds it */
138 spin_lock_bh(&entry->lock);
139 next_plus_upper = entry->data.next_plus_upper;
140 ref_table.first_free = next_plus_upper & index_mask;
141 reference = (next_plus_upper & ~index_mask) + index;
142 entry->data.reference = reference;
143 entry->object = object;
144 if (lock != 0)
145 *lock = &entry->lock;
146 spin_unlock_bh(&entry->lock);
147 }
148 write_unlock_bh(&reftbl_lock);
149 return reference;
150}
151
152/**
153 * ref_discard - invalidate references to an object
154 *
155 * Disallow future references to an object and free up the entry for re-use.
156 * Note: The entry's spin_lock may still be busy after discard
157 */
158
159void ref_discard(u32 ref)
160{
161 struct reference *entry;
162 u32 index;
163 u32 index_mask;
164
165 assert(ref_table.entries);
166 assert(ref != 0);
167
168 write_lock_bh(&reftbl_lock);
169 index_mask = ref_table.index_mask;
170 index = ref & index_mask;
171 entry = &(ref_table.entries[index]);
172 assert(entry->object != 0);
173 assert(entry->data.reference == ref);
174
175 /* mark entry as unused */
176 entry->object = 0;
177 if (ref_table.first_free == 0)
178 ref_table.first_free = index;
179 else
180 /* next_plus_upper is always XXXX|0--0 for last free entry */
181 ref_table.entries[ref_table.last_free].data.next_plus_upper
182 |= index;
183 ref_table.last_free = index;
184
185 /* increment upper bits of entry to invalidate subsequent references */
186 entry->data.next_plus_upper = (ref & ~index_mask) + (index_mask + 1);
187 write_unlock_bh(&reftbl_lock);
188}
189
diff --git a/net/tipc/ref.h b/net/tipc/ref.h
new file mode 100644
index 000000000000..429cde57228a
--- /dev/null
+++ b/net/tipc/ref.h
@@ -0,0 +1,131 @@
1/*
2 * net/tipc/ref.h: Include file for TIPC object registry code
3 *
4 * Copyright (c) 1991-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#ifndef _TIPC_REF_H
38#define _TIPC_REF_H
39
40/**
41 * struct reference - TIPC object reference entry
42 * @object: pointer to object associated with reference entry
43 * @lock: spinlock controlling access to object
44 * @data: reference value associated with object (or link to next unused entry)
45 */
46
47struct reference {
48 void *object;
49 spinlock_t lock;
50 union {
51 u32 next_plus_upper;
52 u32 reference;
53 } data;
54};
55
56/**
57 * struct ref_table - table of TIPC object reference entries
58 * @entries: pointer to array of reference entries
59 * @index_mask: bitmask for array index portion of reference values
60 * @first_free: array index of first unused object reference entry
61 * @last_free: array index of last unused object reference entry
62 */
63
64struct ref_table {
65 struct reference *entries;
66 u32 index_mask;
67 u32 first_free;
68 u32 last_free;
69};
70
71extern struct ref_table ref_table;
72
73int ref_table_init(u32 requested_size, u32 start);
74void ref_table_stop(void);
75
76u32 ref_acquire(void *object, spinlock_t **lock);
77void ref_discard(u32 ref);
78
79
80/**
81 * ref_lock - lock referenced object and return pointer to it
82 */
83
84static inline void *ref_lock(u32 ref)
85{
86 if (likely(ref_table.entries)) {
87 struct reference *r =
88 &ref_table.entries[ref & ref_table.index_mask];
89
90 spin_lock_bh(&r->lock);
91 if (likely(r->data.reference == ref))
92 return r->object;
93 spin_unlock_bh(&r->lock);
94 }
95 return 0;
96}
97
98/**
99 * ref_unlock - unlock referenced object
100 */
101
102static inline void ref_unlock(u32 ref)
103{
104 if (likely(ref_table.entries)) {
105 struct reference *r =
106 &ref_table.entries[ref & ref_table.index_mask];
107
108 if (likely(r->data.reference == ref))
109 spin_unlock_bh(&r->lock);
110 else
111 err("ref_unlock() invoked using obsolete reference\n");
112 }
113}
114
115/**
116 * ref_deref - return pointer referenced object (without locking it)
117 */
118
119static inline void *ref_deref(u32 ref)
120{
121 if (likely(ref_table.entries)) {
122 struct reference *r =
123 &ref_table.entries[ref & ref_table.index_mask];
124
125 if (likely(r->data.reference == ref))
126 return r->object;
127 }
128 return 0;
129}
130
131#endif
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
new file mode 100644
index 000000000000..d21f8c0cd25a
--- /dev/null
+++ b/net/tipc/socket.c
@@ -0,0 +1,1726 @@
1/*
2 * net/tipc/socket.c: TIPC socket API
3 *
4 * Copyright (c) 2001-2006, Ericsson AB
5 * Copyright (c) 2004-2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include <linux/module.h>
38#include <linux/types.h>
39#include <linux/net.h>
40#include <linux/socket.h>
41#include <linux/errno.h>
42#include <linux/mm.h>
43#include <linux/slab.h>
44#include <linux/poll.h>
45#include <linux/version.h>
46#include <linux/fcntl.h>
47#include <linux/version.h>
48#include <asm/semaphore.h>
49#include <asm/string.h>
50#include <asm/atomic.h>
51#include <net/sock.h>
52
53#include <linux/tipc.h>
54#include <linux/tipc_config.h>
55#include <net/tipc/tipc_msg.h>
56#include <net/tipc/tipc_port.h>
57
58#include "core.h"
59
60#define SS_LISTENING -1 /* socket is listening */
61#define SS_READY -2 /* socket is connectionless */
62
63#define OVERLOAD_LIMIT_BASE 5000
64
65struct tipc_sock {
66 struct sock sk;
67 struct tipc_port *p;
68 struct semaphore sem;
69};
70
71#define tipc_sk(sk) ((struct tipc_sock*)sk)
72
73static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf);
74static void wakeupdispatch(struct tipc_port *tport);
75
76static struct proto_ops packet_ops;
77static struct proto_ops stream_ops;
78static struct proto_ops msg_ops;
79
80static struct proto tipc_proto;
81
82static int sockets_enabled = 0;
83
84static atomic_t tipc_queue_size = ATOMIC_INIT(0);
85
86
87/*
88 * sock_lock(): Lock a port/socket pair. lock_sock() can
89 * not be used here, since the same lock must protect ports
90 * with non-socket interfaces.
91 * See net.c for description of locking policy.
92 */
93static inline void sock_lock(struct tipc_sock* tsock)
94{
95 spin_lock_bh(tsock->p->lock);
96}
97
98/*
99 * sock_unlock(): Unlock a port/socket pair
100 */
101static inline void sock_unlock(struct tipc_sock* tsock)
102{
103 spin_unlock_bh(tsock->p->lock);
104}
105
106/**
107 * pollmask - determine the current set of poll() events for a socket
108 * @sock: socket structure
109 *
110 * TIPC sets the returned events as follows:
111 * a) POLLRDNORM and POLLIN are set if the socket's receive queue is non-empty
112 * or if a connection-oriented socket is does not have an active connection
113 * (i.e. a read operation will not block).
114 * b) POLLOUT is set except when a socket's connection has been terminated
115 * (i.e. a write operation will not block).
116 * c) POLLHUP is set when a socket's connection has been terminated.
117 *
118 * IMPORTANT: The fact that a read or write operation will not block does NOT
119 * imply that the operation will succeed!
120 *
121 * Returns pollmask value
122 */
123
124static inline u32 pollmask(struct socket *sock)
125{
126 u32 mask;
127
128 if ((skb_queue_len(&sock->sk->sk_receive_queue) != 0) ||
129 (sock->state == SS_UNCONNECTED) ||
130 (sock->state == SS_DISCONNECTING))
131 mask = (POLLRDNORM | POLLIN);
132 else
133 mask = 0;
134
135 if (sock->state == SS_DISCONNECTING)
136 mask |= POLLHUP;
137 else
138 mask |= POLLOUT;
139
140 return mask;
141}
142
143
144/**
145 * advance_queue - discard first buffer in queue
146 * @tsock: TIPC socket
147 */
148
149static inline void advance_queue(struct tipc_sock *tsock)
150{
151 sock_lock(tsock);
152 buf_discard(skb_dequeue(&tsock->sk.sk_receive_queue));
153 sock_unlock(tsock);
154 atomic_dec(&tipc_queue_size);
155}
156
157/**
158 * tipc_create - create a TIPC socket
159 * @sock: pre-allocated socket structure
160 * @protocol: protocol indicator (must be 0)
161 *
162 * This routine creates and attaches a 'struct sock' to the 'struct socket',
163 * then create and attaches a TIPC port to the 'struct sock' part.
164 *
165 * Returns 0 on success, errno otherwise
166 */
167static int tipc_create(struct socket *sock, int protocol)
168{
169 struct tipc_sock *tsock;
170 struct tipc_port *port;
171 struct sock *sk;
172 u32 ref;
173
174 if ((sock->type != SOCK_STREAM) &&
175 (sock->type != SOCK_SEQPACKET) &&
176 (sock->type != SOCK_DGRAM) &&
177 (sock->type != SOCK_RDM))
178 return -EPROTOTYPE;
179
180 if (unlikely(protocol != 0))
181 return -EPROTONOSUPPORT;
182
183 ref = tipc_createport_raw(0, &dispatch, &wakeupdispatch, TIPC_LOW_IMPORTANCE);
184 if (unlikely(!ref))
185 return -ENOMEM;
186
187 sock->state = SS_UNCONNECTED;
188
189 switch (sock->type) {
190 case SOCK_STREAM:
191 sock->ops = &stream_ops;
192 break;
193 case SOCK_SEQPACKET:
194 sock->ops = &packet_ops;
195 break;
196 case SOCK_DGRAM:
197 tipc_set_portunreliable(ref, 1);
198 /* fall through */
199 case SOCK_RDM:
200 tipc_set_portunreturnable(ref, 1);
201 sock->ops = &msg_ops;
202 sock->state = SS_READY;
203 break;
204 }
205
206 sk = sk_alloc(AF_TIPC, GFP_KERNEL, &tipc_proto, 1);
207 if (!sk) {
208 tipc_deleteport(ref);
209 return -ENOMEM;
210 }
211
212 sock_init_data(sock, sk);
213 init_waitqueue_head(sk->sk_sleep);
214 sk->sk_rcvtimeo = 8 * HZ; /* default connect timeout = 8s */
215
216 tsock = tipc_sk(sk);
217 port = tipc_get_port(ref);
218
219 tsock->p = port;
220 port->usr_handle = tsock;
221
222 init_MUTEX(&tsock->sem);
223
224 dbg("sock_create: %x\n",tsock);
225
226 atomic_inc(&tipc_user_count);
227
228 return 0;
229}
230
231/**
232 * release - destroy a TIPC socket
233 * @sock: socket to destroy
234 *
235 * This routine cleans up any messages that are still queued on the socket.
236 * For DGRAM and RDM socket types, all queued messages are rejected.
237 * For SEQPACKET and STREAM socket types, the first message is rejected
238 * and any others are discarded. (If the first message on a STREAM socket
239 * is partially-read, it is discarded and the next one is rejected instead.)
240 *
241 * NOTE: Rejected messages are not necessarily returned to the sender! They
242 * are returned or discarded according to the "destination droppable" setting
243 * specified for the message by the sender.
244 *
245 * Returns 0 on success, errno otherwise
246 */
247
248static int release(struct socket *sock)
249{
250 struct tipc_sock *tsock = tipc_sk(sock->sk);
251 struct sock *sk = sock->sk;
252 int res = TIPC_OK;
253 struct sk_buff *buf;
254
255 dbg("sock_delete: %x\n",tsock);
256 if (!tsock)
257 return 0;
258 down_interruptible(&tsock->sem);
259 if (!sock->sk) {
260 up(&tsock->sem);
261 return 0;
262 }
263
264 /* Reject unreceived messages, unless no longer connected */
265
266 while (sock->state != SS_DISCONNECTING) {
267 sock_lock(tsock);
268 buf = skb_dequeue(&sk->sk_receive_queue);
269 if (!buf)
270 tsock->p->usr_handle = 0;
271 sock_unlock(tsock);
272 if (!buf)
273 break;
274 if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf)))
275 buf_discard(buf);
276 else
277 tipc_reject_msg(buf, TIPC_ERR_NO_PORT);
278 atomic_dec(&tipc_queue_size);
279 }
280
281 /* Delete TIPC port */
282
283 res = tipc_deleteport(tsock->p->ref);
284 sock->sk = NULL;
285
286 /* Discard any remaining messages */
287
288 while ((buf = skb_dequeue(&sk->sk_receive_queue))) {
289 buf_discard(buf);
290 atomic_dec(&tipc_queue_size);
291 }
292
293 up(&tsock->sem);
294
295 sock_put(sk);
296
297 atomic_dec(&tipc_user_count);
298 return res;
299}
300
301/**
302 * bind - associate or disassocate TIPC name(s) with a socket
303 * @sock: socket structure
304 * @uaddr: socket address describing name(s) and desired operation
305 * @uaddr_len: size of socket address data structure
306 *
307 * Name and name sequence binding is indicated using a positive scope value;
308 * a negative scope value unbinds the specified name. Specifying no name
309 * (i.e. a socket address length of 0) unbinds all names from the socket.
310 *
311 * Returns 0 on success, errno otherwise
312 */
313
314static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len)
315{
316 struct tipc_sock *tsock = tipc_sk(sock->sk);
317 struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr;
318 int res;
319
320 if (down_interruptible(&tsock->sem))
321 return -ERESTARTSYS;
322
323 if (unlikely(!uaddr_len)) {
324 res = tipc_withdraw(tsock->p->ref, 0, 0);
325 goto exit;
326 }
327
328 if (uaddr_len < sizeof(struct sockaddr_tipc)) {
329 res = -EINVAL;
330 goto exit;
331 }
332
333 if (addr->family != AF_TIPC) {
334 res = -EAFNOSUPPORT;
335 goto exit;
336 }
337 if (addr->addrtype == TIPC_ADDR_NAME)
338 addr->addr.nameseq.upper = addr->addr.nameseq.lower;
339 else if (addr->addrtype != TIPC_ADDR_NAMESEQ) {
340 res = -EAFNOSUPPORT;
341 goto exit;
342 }
343
344 if (addr->scope > 0)
345 res = tipc_publish(tsock->p->ref, addr->scope,
346 &addr->addr.nameseq);
347 else
348 res = tipc_withdraw(tsock->p->ref, -addr->scope,
349 &addr->addr.nameseq);
350exit:
351 up(&tsock->sem);
352 return res;
353}
354
355/**
356 * get_name - get port ID of socket or peer socket
357 * @sock: socket structure
358 * @uaddr: area for returned socket address
359 * @uaddr_len: area for returned length of socket address
360 * @peer: 0 to obtain socket name, 1 to obtain peer socket name
361 *
362 * Returns 0 on success, errno otherwise
363 */
364
365static int get_name(struct socket *sock, struct sockaddr *uaddr,
366 int *uaddr_len, int peer)
367{
368 struct tipc_sock *tsock = tipc_sk(sock->sk);
369 struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr;
370 u32 res;
371
372 if (down_interruptible(&tsock->sem))
373 return -ERESTARTSYS;
374
375 *uaddr_len = sizeof(*addr);
376 addr->addrtype = TIPC_ADDR_ID;
377 addr->family = AF_TIPC;
378 addr->scope = 0;
379 if (peer)
380 res = tipc_peer(tsock->p->ref, &addr->addr.id);
381 else
382 res = tipc_ownidentity(tsock->p->ref, &addr->addr.id);
383 addr->addr.name.domain = 0;
384
385 up(&tsock->sem);
386 return res;
387}
388
389/**
390 * poll - read and possibly block on pollmask
391 * @file: file structure associated with the socket
392 * @sock: socket for which to calculate the poll bits
393 * @wait: ???
394 *
395 * Returns the pollmask
396 */
397
398static unsigned int poll(struct file *file, struct socket *sock,
399 poll_table *wait)
400{
401 poll_wait(file, sock->sk->sk_sleep, wait);
402 /* NEED LOCK HERE? */
403 return pollmask(sock);
404}
405
406/**
407 * dest_name_check - verify user is permitted to send to specified port name
408 * @dest: destination address
409 * @m: descriptor for message to be sent
410 *
411 * Prevents restricted configuration commands from being issued by
412 * unauthorized users.
413 *
414 * Returns 0 if permission is granted, otherwise errno
415 */
416
417static inline int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m)
418{
419 struct tipc_cfg_msg_hdr hdr;
420
421 if (likely(dest->addr.name.name.type >= TIPC_RESERVED_TYPES))
422 return 0;
423 if (likely(dest->addr.name.name.type == TIPC_TOP_SRV))
424 return 0;
425
426 if (likely(dest->addr.name.name.type != TIPC_CFG_SRV))
427 return -EACCES;
428
429 if (copy_from_user(&hdr, m->msg_iov[0].iov_base, sizeof(hdr)))
430 return -EFAULT;
431 if ((ntohs(hdr.tcm_type) & 0xC000) & (!capable(CAP_NET_ADMIN)))
432 return -EACCES;
433
434 return 0;
435}
436
437/**
438 * send_msg - send message in connectionless manner
439 * @iocb: (unused)
440 * @sock: socket structure
441 * @m: message to send
442 * @total_len: (unused)
443 *
444 * Message must have an destination specified explicitly.
445 * Used for SOCK_RDM and SOCK_DGRAM messages,
446 * and for 'SYN' messages on SOCK_SEQPACKET and SOCK_STREAM connections.
447 * (Note: 'SYN+' is prohibited on SOCK_STREAM.)
448 *
449 * Returns the number of bytes sent on success, or errno otherwise
450 */
451
452static int send_msg(struct kiocb *iocb, struct socket *sock,
453 struct msghdr *m, size_t total_len)
454{
455 struct tipc_sock *tsock = tipc_sk(sock->sk);
456 struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name;
457 struct sk_buff *buf;
458 int needs_conn;
459 int res = -EINVAL;
460
461 if (unlikely(!dest))
462 return -EDESTADDRREQ;
463 if (unlikely(dest->family != AF_TIPC))
464 return -EINVAL;
465
466 needs_conn = (sock->state != SS_READY);
467 if (unlikely(needs_conn)) {
468 if (sock->state == SS_LISTENING)
469 return -EPIPE;
470 if (sock->state != SS_UNCONNECTED)
471 return -EISCONN;
472 if ((tsock->p->published) ||
473 ((sock->type == SOCK_STREAM) && (total_len != 0)))
474 return -EOPNOTSUPP;
475 }
476
477 if (down_interruptible(&tsock->sem))
478 return -ERESTARTSYS;
479
480 if (needs_conn) {
481
482 /* Abort any pending connection attempts (very unlikely) */
483
484 while ((buf = skb_dequeue(&sock->sk->sk_receive_queue))) {
485 tipc_reject_msg(buf, TIPC_ERR_NO_PORT);
486 atomic_dec(&tipc_queue_size);
487 }
488
489 sock->state = SS_CONNECTING;
490 }
491
492 do {
493 if (dest->addrtype == TIPC_ADDR_NAME) {
494 if ((res = dest_name_check(dest, m)))
495 goto exit;
496 res = tipc_send2name(tsock->p->ref,
497 &dest->addr.name.name,
498 dest->addr.name.domain,
499 m->msg_iovlen,
500 m->msg_iov);
501 }
502 else if (dest->addrtype == TIPC_ADDR_ID) {
503 res = tipc_send2port(tsock->p->ref,
504 &dest->addr.id,
505 m->msg_iovlen,
506 m->msg_iov);
507 }
508 else if (dest->addrtype == TIPC_ADDR_MCAST) {
509 if (needs_conn) {
510 res = -EOPNOTSUPP;
511 goto exit;
512 }
513 if ((res = dest_name_check(dest, m)))
514 goto exit;
515 res = tipc_multicast(tsock->p->ref,
516 &dest->addr.nameseq,
517 0,
518 m->msg_iovlen,
519 m->msg_iov);
520 }
521 if (likely(res != -ELINKCONG)) {
522exit:
523 up(&tsock->sem);
524 return res;
525 }
526 if (m->msg_flags & MSG_DONTWAIT) {
527 res = -EWOULDBLOCK;
528 goto exit;
529 }
530 if (wait_event_interruptible(*sock->sk->sk_sleep,
531 !tsock->p->congested)) {
532 res = -ERESTARTSYS;
533 goto exit;
534 }
535 } while (1);
536}
537
538/**
539 * send_packet - send a connection-oriented message
540 * @iocb: (unused)
541 * @sock: socket structure
542 * @m: message to send
543 * @total_len: (unused)
544 *
545 * Used for SOCK_SEQPACKET messages and SOCK_STREAM data.
546 *
547 * Returns the number of bytes sent on success, or errno otherwise
548 */
549
550static int send_packet(struct kiocb *iocb, struct socket *sock,
551 struct msghdr *m, size_t total_len)
552{
553 struct tipc_sock *tsock = tipc_sk(sock->sk);
554 struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name;
555 int res;
556
557 /* Handle implied connection establishment */
558
559 if (unlikely(dest))
560 return send_msg(iocb, sock, m, total_len);
561
562 if (down_interruptible(&tsock->sem)) {
563 return -ERESTARTSYS;
564 }
565
566 if (unlikely(sock->state != SS_CONNECTED)) {
567 if (sock->state == SS_DISCONNECTING)
568 res = -EPIPE;
569 else
570 res = -ENOTCONN;
571 goto exit;
572 }
573
574 do {
575 res = tipc_send(tsock->p->ref, m->msg_iovlen, m->msg_iov);
576 if (likely(res != -ELINKCONG)) {
577exit:
578 up(&tsock->sem);
579 return res;
580 }
581 if (m->msg_flags & MSG_DONTWAIT) {
582 res = -EWOULDBLOCK;
583 goto exit;
584 }
585 if (wait_event_interruptible(*sock->sk->sk_sleep,
586 !tsock->p->congested)) {
587 res = -ERESTARTSYS;
588 goto exit;
589 }
590 } while (1);
591}
592
593/**
594 * send_stream - send stream-oriented data
595 * @iocb: (unused)
596 * @sock: socket structure
597 * @m: data to send
598 * @total_len: total length of data to be sent
599 *
600 * Used for SOCK_STREAM data.
601 *
602 * Returns the number of bytes sent on success, or errno otherwise
603 */
604
605
606static int send_stream(struct kiocb *iocb, struct socket *sock,
607 struct msghdr *m, size_t total_len)
608{
609 struct msghdr my_msg;
610 struct iovec my_iov;
611 struct iovec *curr_iov;
612 int curr_iovlen;
613 char __user *curr_start;
614 int curr_left;
615 int bytes_to_send;
616 int res;
617
618 if (likely(total_len <= TIPC_MAX_USER_MSG_SIZE))
619 return send_packet(iocb, sock, m, total_len);
620
621 /* Can only send large data streams if already connected */
622
623 if (unlikely(sock->state != SS_CONNECTED)) {
624 if (sock->state == SS_DISCONNECTING)
625 return -EPIPE;
626 else
627 return -ENOTCONN;
628 }
629
630 /*
631 * Send each iovec entry using one or more messages
632 *
633 * Note: This algorithm is good for the most likely case
634 * (i.e. one large iovec entry), but could be improved to pass sets
635 * of small iovec entries into send_packet().
636 */
637
638 my_msg = *m;
639 curr_iov = my_msg.msg_iov;
640 curr_iovlen = my_msg.msg_iovlen;
641 my_msg.msg_iov = &my_iov;
642 my_msg.msg_iovlen = 1;
643
644 while (curr_iovlen--) {
645 curr_start = curr_iov->iov_base;
646 curr_left = curr_iov->iov_len;
647
648 while (curr_left) {
649 bytes_to_send = (curr_left < TIPC_MAX_USER_MSG_SIZE)
650 ? curr_left : TIPC_MAX_USER_MSG_SIZE;
651 my_iov.iov_base = curr_start;
652 my_iov.iov_len = bytes_to_send;
653 if ((res = send_packet(iocb, sock, &my_msg, 0)) < 0)
654 return res;
655 curr_left -= bytes_to_send;
656 curr_start += bytes_to_send;
657 }
658
659 curr_iov++;
660 }
661
662 return total_len;
663}
664
665/**
666 * auto_connect - complete connection setup to a remote port
667 * @sock: socket structure
668 * @tsock: TIPC-specific socket structure
669 * @msg: peer's response message
670 *
671 * Returns 0 on success, errno otherwise
672 */
673
674static int auto_connect(struct socket *sock, struct tipc_sock *tsock,
675 struct tipc_msg *msg)
676{
677 struct tipc_portid peer;
678
679 if (msg_errcode(msg)) {
680 sock->state = SS_DISCONNECTING;
681 return -ECONNREFUSED;
682 }
683
684 peer.ref = msg_origport(msg);
685 peer.node = msg_orignode(msg);
686 tipc_connect2port(tsock->p->ref, &peer);
687 tipc_set_portimportance(tsock->p->ref, msg_importance(msg));
688 sock->state = SS_CONNECTED;
689 return 0;
690}
691
692/**
693 * set_orig_addr - capture sender's address for received message
694 * @m: descriptor for message info
695 * @msg: received message header
696 *
697 * Note: Address is not captured if not requested by receiver.
698 */
699
700static inline void set_orig_addr(struct msghdr *m, struct tipc_msg *msg)
701{
702 struct sockaddr_tipc *addr = (struct sockaddr_tipc *)m->msg_name;
703
704 if (addr) {
705 addr->family = AF_TIPC;
706 addr->addrtype = TIPC_ADDR_ID;
707 addr->addr.id.ref = msg_origport(msg);
708 addr->addr.id.node = msg_orignode(msg);
709 addr->addr.name.domain = 0; /* could leave uninitialized */
710 addr->scope = 0; /* could leave uninitialized */
711 m->msg_namelen = sizeof(struct sockaddr_tipc);
712 }
713}
714
715/**
716 * anc_data_recv - optionally capture ancillary data for received message
717 * @m: descriptor for message info
718 * @msg: received message header
719 * @tport: TIPC port associated with message
720 *
721 * Note: Ancillary data is not captured if not requested by receiver.
722 *
723 * Returns 0 if successful, otherwise errno
724 */
725
726static inline int anc_data_recv(struct msghdr *m, struct tipc_msg *msg,
727 struct tipc_port *tport)
728{
729 u32 anc_data[3];
730 u32 err;
731 u32 dest_type;
732 int res;
733
734 if (likely(m->msg_controllen == 0))
735 return 0;
736
737 /* Optionally capture errored message object(s) */
738
739 err = msg ? msg_errcode(msg) : 0;
740 if (unlikely(err)) {
741 anc_data[0] = err;
742 anc_data[1] = msg_data_sz(msg);
743 if ((res = put_cmsg(m, SOL_SOCKET, TIPC_ERRINFO, 8, anc_data)))
744 return res;
745 if (anc_data[1] &&
746 (res = put_cmsg(m, SOL_SOCKET, TIPC_RETDATA, anc_data[1],
747 msg_data(msg))))
748 return res;
749 }
750
751 /* Optionally capture message destination object */
752
753 dest_type = msg ? msg_type(msg) : TIPC_DIRECT_MSG;
754 switch (dest_type) {
755 case TIPC_NAMED_MSG:
756 anc_data[0] = msg_nametype(msg);
757 anc_data[1] = msg_namelower(msg);
758 anc_data[2] = msg_namelower(msg);
759 break;
760 case TIPC_MCAST_MSG:
761 anc_data[0] = msg_nametype(msg);
762 anc_data[1] = msg_namelower(msg);
763 anc_data[2] = msg_nameupper(msg);
764 break;
765 case TIPC_CONN_MSG:
766 anc_data[0] = tport->conn_type;
767 anc_data[1] = tport->conn_instance;
768 anc_data[2] = tport->conn_instance;
769 break;
770 default:
771 anc_data[0] = 0;
772 }
773 if (anc_data[0] &&
774 (res = put_cmsg(m, SOL_SOCKET, TIPC_DESTNAME, 12, anc_data)))
775 return res;
776
777 return 0;
778}
779
780/**
781 * recv_msg - receive packet-oriented message
782 * @iocb: (unused)
783 * @m: descriptor for message info
784 * @buf_len: total size of user buffer area
785 * @flags: receive flags
786 *
787 * Used for SOCK_DGRAM, SOCK_RDM, and SOCK_SEQPACKET messages.
788 * If the complete message doesn't fit in user area, truncate it.
789 *
790 * Returns size of returned message data, errno otherwise
791 */
792
793static int recv_msg(struct kiocb *iocb, struct socket *sock,
794 struct msghdr *m, size_t buf_len, int flags)
795{
796 struct tipc_sock *tsock = tipc_sk(sock->sk);
797 struct sk_buff *buf;
798 struct tipc_msg *msg;
799 unsigned int q_len;
800 unsigned int sz;
801 u32 err;
802 int res;
803
804 /* Currently doesn't support receiving into multiple iovec entries */
805
806 if (m->msg_iovlen != 1)
807 return -EOPNOTSUPP;
808
809 /* Catch invalid receive attempts */
810
811 if (unlikely(!buf_len))
812 return -EINVAL;
813
814 if (sock->type == SOCK_SEQPACKET) {
815 if (unlikely(sock->state == SS_UNCONNECTED))
816 return -ENOTCONN;
817 if (unlikely((sock->state == SS_DISCONNECTING) &&
818 (skb_queue_len(&sock->sk->sk_receive_queue) == 0)))
819 return -ENOTCONN;
820 }
821
822 /* Look for a message in receive queue; wait if necessary */
823
824 if (unlikely(down_interruptible(&tsock->sem)))
825 return -ERESTARTSYS;
826
827restart:
828 if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) &&
829 (flags & MSG_DONTWAIT))) {
830 res = -EWOULDBLOCK;
831 goto exit;
832 }
833
834 if ((res = wait_event_interruptible(
835 *sock->sk->sk_sleep,
836 ((q_len = skb_queue_len(&sock->sk->sk_receive_queue)) ||
837 (sock->state == SS_DISCONNECTING))) )) {
838 goto exit;
839 }
840
841 /* Catch attempt to receive on an already terminated connection */
842 /* [THIS CHECK MAY OVERLAP WITH AN EARLIER CHECK] */
843
844 if (!q_len) {
845 res = -ENOTCONN;
846 goto exit;
847 }
848
849 /* Get access to first message in receive queue */
850
851 buf = skb_peek(&sock->sk->sk_receive_queue);
852 msg = buf_msg(buf);
853 sz = msg_data_sz(msg);
854 err = msg_errcode(msg);
855
856 /* Complete connection setup for an implied connect */
857
858 if (unlikely(sock->state == SS_CONNECTING)) {
859 if ((res = auto_connect(sock, tsock, msg)))
860 goto exit;
861 }
862
863 /* Discard an empty non-errored message & try again */
864
865 if ((!sz) && (!err)) {
866 advance_queue(tsock);
867 goto restart;
868 }
869
870 /* Capture sender's address (optional) */
871
872 set_orig_addr(m, msg);
873
874 /* Capture ancillary data (optional) */
875
876 if ((res = anc_data_recv(m, msg, tsock->p)))
877 goto exit;
878
879 /* Capture message data (if valid) & compute return value (always) */
880
881 if (!err) {
882 if (unlikely(buf_len < sz)) {
883 sz = buf_len;
884 m->msg_flags |= MSG_TRUNC;
885 }
886 if (unlikely(copy_to_user(m->msg_iov->iov_base, msg_data(msg),
887 sz))) {
888 res = -EFAULT;
889 goto exit;
890 }
891 res = sz;
892 } else {
893 if ((sock->state == SS_READY) ||
894 ((err == TIPC_CONN_SHUTDOWN) || m->msg_control))
895 res = 0;
896 else
897 res = -ECONNRESET;
898 }
899
900 /* Consume received message (optional) */
901
902 if (likely(!(flags & MSG_PEEK))) {
903 if (unlikely(++tsock->p->conn_unacked >= TIPC_FLOW_CONTROL_WIN))
904 tipc_acknowledge(tsock->p->ref, tsock->p->conn_unacked);
905 advance_queue(tsock);
906 }
907exit:
908 up(&tsock->sem);
909 return res;
910}
911
912/**
913 * recv_stream - receive stream-oriented data
914 * @iocb: (unused)
915 * @m: descriptor for message info
916 * @buf_len: total size of user buffer area
917 * @flags: receive flags
918 *
919 * Used for SOCK_STREAM messages only. If not enough data is available
920 * will optionally wait for more; never truncates data.
921 *
922 * Returns size of returned message data, errno otherwise
923 */
924
925static int recv_stream(struct kiocb *iocb, struct socket *sock,
926 struct msghdr *m, size_t buf_len, int flags)
927{
928 struct tipc_sock *tsock = tipc_sk(sock->sk);
929 struct sk_buff *buf;
930 struct tipc_msg *msg;
931 unsigned int q_len;
932 unsigned int sz;
933 int sz_to_copy;
934 int sz_copied = 0;
935 int needed;
936 char *crs = m->msg_iov->iov_base;
937 unsigned char *buf_crs;
938 u32 err;
939 int res;
940
941 /* Currently doesn't support receiving into multiple iovec entries */
942
943 if (m->msg_iovlen != 1)
944 return -EOPNOTSUPP;
945
946 /* Catch invalid receive attempts */
947
948 if (unlikely(!buf_len))
949 return -EINVAL;
950
951 if (unlikely(sock->state == SS_DISCONNECTING)) {
952 if (skb_queue_len(&sock->sk->sk_receive_queue) == 0)
953 return -ENOTCONN;
954 } else if (unlikely(sock->state != SS_CONNECTED))
955 return -ENOTCONN;
956
957 /* Look for a message in receive queue; wait if necessary */
958
959 if (unlikely(down_interruptible(&tsock->sem)))
960 return -ERESTARTSYS;
961
962restart:
963 if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) &&
964 (flags & MSG_DONTWAIT))) {
965 res = (sz_copied == 0) ? -EWOULDBLOCK : 0;
966 goto exit;
967 }
968
969 if ((res = wait_event_interruptible(
970 *sock->sk->sk_sleep,
971 ((q_len = skb_queue_len(&sock->sk->sk_receive_queue)) ||
972 (sock->state == SS_DISCONNECTING))) )) {
973 goto exit;
974 }
975
976 /* Catch attempt to receive on an already terminated connection */
977 /* [THIS CHECK MAY OVERLAP WITH AN EARLIER CHECK] */
978
979 if (!q_len) {
980 res = -ENOTCONN;
981 goto exit;
982 }
983
984 /* Get access to first message in receive queue */
985
986 buf = skb_peek(&sock->sk->sk_receive_queue);
987 msg = buf_msg(buf);
988 sz = msg_data_sz(msg);
989 err = msg_errcode(msg);
990
991 /* Discard an empty non-errored message & try again */
992
993 if ((!sz) && (!err)) {
994 advance_queue(tsock);
995 goto restart;
996 }
997
998 /* Optionally capture sender's address & ancillary data of first msg */
999
1000 if (sz_copied == 0) {
1001 set_orig_addr(m, msg);
1002 if ((res = anc_data_recv(m, msg, tsock->p)))
1003 goto exit;
1004 }
1005
1006 /* Capture message data (if valid) & compute return value (always) */
1007
1008 if (!err) {
1009 buf_crs = (unsigned char *)(TIPC_SKB_CB(buf)->handle);
1010 sz = buf->tail - buf_crs;
1011
1012 needed = (buf_len - sz_copied);
1013 sz_to_copy = (sz <= needed) ? sz : needed;
1014 if (unlikely(copy_to_user(crs, buf_crs, sz_to_copy))) {
1015 res = -EFAULT;
1016 goto exit;
1017 }
1018 sz_copied += sz_to_copy;
1019
1020 if (sz_to_copy < sz) {
1021 if (!(flags & MSG_PEEK))
1022 TIPC_SKB_CB(buf)->handle = buf_crs + sz_to_copy;
1023 goto exit;
1024 }
1025
1026 crs += sz_to_copy;
1027 } else {
1028 if (sz_copied != 0)
1029 goto exit; /* can't add error msg to valid data */
1030
1031 if ((err == TIPC_CONN_SHUTDOWN) || m->msg_control)
1032 res = 0;
1033 else
1034 res = -ECONNRESET;
1035 }
1036
1037 /* Consume received message (optional) */
1038
1039 if (likely(!(flags & MSG_PEEK))) {
1040 if (unlikely(++tsock->p->conn_unacked >= TIPC_FLOW_CONTROL_WIN))
1041 tipc_acknowledge(tsock->p->ref, tsock->p->conn_unacked);
1042 advance_queue(tsock);
1043 }
1044
1045 /* Loop around if more data is required */
1046
1047 if ((sz_copied < buf_len) /* didn't get all requested data */
1048 && (flags & MSG_WAITALL) /* ... and need to wait for more */
1049 && (!(flags & MSG_PEEK)) /* ... and aren't just peeking at data */
1050 && (!err) /* ... and haven't reached a FIN */
1051 )
1052 goto restart;
1053
1054exit:
1055 up(&tsock->sem);
1056 return res ? res : sz_copied;
1057}
1058
1059/**
1060 * queue_overloaded - test if queue overload condition exists
1061 * @queue_size: current size of queue
1062 * @base: nominal maximum size of queue
1063 * @msg: message to be added to queue
1064 *
1065 * Returns 1 if queue is currently overloaded, 0 otherwise
1066 */
1067
1068static int queue_overloaded(u32 queue_size, u32 base, struct tipc_msg *msg)
1069{
1070 u32 threshold;
1071 u32 imp = msg_importance(msg);
1072
1073 if (imp == TIPC_LOW_IMPORTANCE)
1074 threshold = base;
1075 else if (imp == TIPC_MEDIUM_IMPORTANCE)
1076 threshold = base * 2;
1077 else if (imp == TIPC_HIGH_IMPORTANCE)
1078 threshold = base * 100;
1079 else
1080 return 0;
1081
1082 if (msg_connected(msg))
1083 threshold *= 4;
1084
1085 return (queue_size > threshold);
1086}
1087
1088/**
1089 * async_disconnect - wrapper function used to disconnect port
1090 * @portref: TIPC port reference (passed as pointer-sized value)
1091 */
1092
1093static void async_disconnect(unsigned long portref)
1094{
1095 tipc_disconnect((u32)portref);
1096}
1097
1098/**
1099 * dispatch - handle arriving message
1100 * @tport: TIPC port that received message
1101 * @buf: message
1102 *
1103 * Called with port locked. Must not take socket lock to avoid deadlock risk.
1104 *
1105 * Returns TIPC error status code (TIPC_OK if message is not to be rejected)
1106 */
1107
1108static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf)
1109{
1110 struct tipc_msg *msg = buf_msg(buf);
1111 struct tipc_sock *tsock = (struct tipc_sock *)tport->usr_handle;
1112 struct socket *sock;
1113 u32 recv_q_len;
1114
1115 /* Reject message if socket is closing */
1116
1117 if (!tsock)
1118 return TIPC_ERR_NO_PORT;
1119
1120 /* Reject message if it is wrong sort of message for socket */
1121
1122 /*
1123 * WOULD IT BE BETTER TO JUST DISCARD THESE MESSAGES INSTEAD?
1124 * "NO PORT" ISN'T REALLY THE RIGHT ERROR CODE, AND THERE MAY
1125 * BE SECURITY IMPLICATIONS INHERENT IN REJECTING INVALID TRAFFIC
1126 */
1127 sock = tsock->sk.sk_socket;
1128 if (sock->state == SS_READY) {
1129 if (msg_connected(msg)) {
1130 msg_dbg(msg, "dispatch filter 1\n");
1131 return TIPC_ERR_NO_PORT;
1132 }
1133 } else {
1134 if (msg_mcast(msg)) {
1135 msg_dbg(msg, "dispatch filter 2\n");
1136 return TIPC_ERR_NO_PORT;
1137 }
1138 if (sock->state == SS_CONNECTED) {
1139 if (!msg_connected(msg)) {
1140 msg_dbg(msg, "dispatch filter 3\n");
1141 return TIPC_ERR_NO_PORT;
1142 }
1143 }
1144 else if (sock->state == SS_CONNECTING) {
1145 if (!msg_connected(msg) && (msg_errcode(msg) == 0)) {
1146 msg_dbg(msg, "dispatch filter 4\n");
1147 return TIPC_ERR_NO_PORT;
1148 }
1149 }
1150 else if (sock->state == SS_LISTENING) {
1151 if (msg_connected(msg) || msg_errcode(msg)) {
1152 msg_dbg(msg, "dispatch filter 5\n");
1153 return TIPC_ERR_NO_PORT;
1154 }
1155 }
1156 else if (sock->state == SS_DISCONNECTING) {
1157 msg_dbg(msg, "dispatch filter 6\n");
1158 return TIPC_ERR_NO_PORT;
1159 }
1160 else /* (sock->state == SS_UNCONNECTED) */ {
1161 if (msg_connected(msg) || msg_errcode(msg)) {
1162 msg_dbg(msg, "dispatch filter 7\n");
1163 return TIPC_ERR_NO_PORT;
1164 }
1165 }
1166 }
1167
1168 /* Reject message if there isn't room to queue it */
1169
1170 if (unlikely((u32)atomic_read(&tipc_queue_size) >
1171 OVERLOAD_LIMIT_BASE)) {
1172 if (queue_overloaded(atomic_read(&tipc_queue_size),
1173 OVERLOAD_LIMIT_BASE, msg))
1174 return TIPC_ERR_OVERLOAD;
1175 }
1176 recv_q_len = skb_queue_len(&tsock->sk.sk_receive_queue);
1177 if (unlikely(recv_q_len > (OVERLOAD_LIMIT_BASE / 2))) {
1178 if (queue_overloaded(recv_q_len,
1179 OVERLOAD_LIMIT_BASE / 2, msg))
1180 return TIPC_ERR_OVERLOAD;
1181 }
1182
1183 /* Initiate connection termination for an incoming 'FIN' */
1184
1185 if (unlikely(msg_errcode(msg) && (sock->state == SS_CONNECTED))) {
1186 sock->state = SS_DISCONNECTING;
1187 /* Note: Use signal since port lock is already taken! */
1188 k_signal((Handler)async_disconnect, tport->ref);
1189 }
1190
1191 /* Enqueue message (finally!) */
1192
1193 msg_dbg(msg,"<DISP<: ");
1194 TIPC_SKB_CB(buf)->handle = msg_data(msg);
1195 atomic_inc(&tipc_queue_size);
1196 skb_queue_tail(&sock->sk->sk_receive_queue, buf);
1197
1198 wake_up_interruptible(sock->sk->sk_sleep);
1199 return TIPC_OK;
1200}
1201
1202/**
1203 * wakeupdispatch - wake up port after congestion
1204 * @tport: port to wakeup
1205 *
1206 * Called with port lock on.
1207 */
1208
1209static void wakeupdispatch(struct tipc_port *tport)
1210{
1211 struct tipc_sock *tsock = (struct tipc_sock *)tport->usr_handle;
1212
1213 wake_up_interruptible(tsock->sk.sk_sleep);
1214}
1215
1216/**
1217 * connect - establish a connection to another TIPC port
1218 * @sock: socket structure
1219 * @dest: socket address for destination port
1220 * @destlen: size of socket address data structure
1221 * @flags: (unused)
1222 *
1223 * Returns 0 on success, errno otherwise
1224 */
1225
1226static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
1227 int flags)
1228{
1229 struct tipc_sock *tsock = tipc_sk(sock->sk);
1230 struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest;
1231 struct msghdr m = {0,};
1232 struct sk_buff *buf;
1233 struct tipc_msg *msg;
1234 int res;
1235
1236 /* For now, TIPC does not allow use of connect() with DGRAM or RDM types */
1237
1238 if (sock->state == SS_READY)
1239 return -EOPNOTSUPP;
1240
1241 /* MOVE THE REST OF THIS ERROR CHECKING TO send_msg()? */
1242 if (sock->state == SS_LISTENING)
1243 return -EOPNOTSUPP;
1244 if (sock->state == SS_CONNECTING)
1245 return -EALREADY;
1246 if (sock->state != SS_UNCONNECTED)
1247 return -EISCONN;
1248
1249 if ((dst->family != AF_TIPC) ||
1250 ((dst->addrtype != TIPC_ADDR_NAME) && (dst->addrtype != TIPC_ADDR_ID)))
1251 return -EINVAL;
1252
1253 /* Send a 'SYN-' to destination */
1254
1255 m.msg_name = dest;
1256 if ((res = send_msg(0, sock, &m, 0)) < 0) {
1257 sock->state = SS_DISCONNECTING;
1258 return res;
1259 }
1260
1261 if (down_interruptible(&tsock->sem))
1262 return -ERESTARTSYS;
1263
1264 /* Wait for destination's 'ACK' response */
1265
1266 res = wait_event_interruptible_timeout(*sock->sk->sk_sleep,
1267 skb_queue_len(&sock->sk->sk_receive_queue),
1268 sock->sk->sk_rcvtimeo);
1269 buf = skb_peek(&sock->sk->sk_receive_queue);
1270 if (res > 0) {
1271 msg = buf_msg(buf);
1272 res = auto_connect(sock, tsock, msg);
1273 if (!res) {
1274 if (dst->addrtype == TIPC_ADDR_NAME) {
1275 tsock->p->conn_type = dst->addr.name.name.type;
1276 tsock->p->conn_instance = dst->addr.name.name.instance;
1277 }
1278 if (!msg_data_sz(msg))
1279 advance_queue(tsock);
1280 }
1281 } else {
1282 if (res == 0) {
1283 res = -ETIMEDOUT;
1284 } else
1285 { /* leave "res" unchanged */ }
1286 sock->state = SS_DISCONNECTING;
1287 }
1288
1289 up(&tsock->sem);
1290 return res;
1291}
1292
1293/**
1294 * listen - allow socket to listen for incoming connections
1295 * @sock: socket structure
1296 * @len: (unused)
1297 *
1298 * Returns 0 on success, errno otherwise
1299 */
1300
1301static int listen(struct socket *sock, int len)
1302{
1303 /* REQUIRES SOCKET LOCKING OF SOME SORT? */
1304
1305 if (sock->state == SS_READY)
1306 return -EOPNOTSUPP;
1307 if (sock->state != SS_UNCONNECTED)
1308 return -EINVAL;
1309 sock->state = SS_LISTENING;
1310 return 0;
1311}
1312
1313/**
1314 * accept - wait for connection request
1315 * @sock: listening socket
1316 * @newsock: new socket that is to be connected
1317 * @flags: file-related flags associated with socket
1318 *
1319 * Returns 0 on success, errno otherwise
1320 */
1321
1322static int accept(struct socket *sock, struct socket *newsock, int flags)
1323{
1324 struct tipc_sock *tsock = tipc_sk(sock->sk);
1325 struct sk_buff *buf;
1326 int res = -EFAULT;
1327
1328 if (sock->state == SS_READY)
1329 return -EOPNOTSUPP;
1330 if (sock->state != SS_LISTENING)
1331 return -EINVAL;
1332
1333 if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) &&
1334 (flags & O_NONBLOCK)))
1335 return -EWOULDBLOCK;
1336
1337 if (down_interruptible(&tsock->sem))
1338 return -ERESTARTSYS;
1339
1340 if (wait_event_interruptible(*sock->sk->sk_sleep,
1341 skb_queue_len(&sock->sk->sk_receive_queue))) {
1342 res = -ERESTARTSYS;
1343 goto exit;
1344 }
1345 buf = skb_peek(&sock->sk->sk_receive_queue);
1346
1347 res = tipc_create(newsock, 0);
1348 if (!res) {
1349 struct tipc_sock *new_tsock = tipc_sk(newsock->sk);
1350 struct tipc_portid id;
1351 struct tipc_msg *msg = buf_msg(buf);
1352 u32 new_ref = new_tsock->p->ref;
1353
1354 id.ref = msg_origport(msg);
1355 id.node = msg_orignode(msg);
1356 tipc_connect2port(new_ref, &id);
1357 newsock->state = SS_CONNECTED;
1358
1359 tipc_set_portimportance(new_ref, msg_importance(msg));
1360 if (msg_named(msg)) {
1361 new_tsock->p->conn_type = msg_nametype(msg);
1362 new_tsock->p->conn_instance = msg_nameinst(msg);
1363 }
1364
1365 /*
1366 * Respond to 'SYN-' by discarding it & returning 'ACK'-.
1367 * Respond to 'SYN+' by queuing it on new socket.
1368 */
1369
1370 msg_dbg(msg,"<ACC<: ");
1371 if (!msg_data_sz(msg)) {
1372 struct msghdr m = {0,};
1373
1374 send_packet(0, newsock, &m, 0);
1375 advance_queue(tsock);
1376 } else {
1377 sock_lock(tsock);
1378 skb_dequeue(&sock->sk->sk_receive_queue);
1379 sock_unlock(tsock);
1380 skb_queue_head(&newsock->sk->sk_receive_queue, buf);
1381 }
1382 }
1383exit:
1384 up(&tsock->sem);
1385 return res;
1386}
1387
1388/**
1389 * shutdown - shutdown socket connection
1390 * @sock: socket structure
1391 * @how: direction to close (always treated as read + write)
1392 *
1393 * Terminates connection (if necessary), then purges socket's receive queue.
1394 *
1395 * Returns 0 on success, errno otherwise
1396 */
1397
1398static int shutdown(struct socket *sock, int how)
1399{
1400 struct tipc_sock* tsock = tipc_sk(sock->sk);
1401 struct sk_buff *buf;
1402 int res;
1403
1404 /* Could return -EINVAL for an invalid "how", but why bother? */
1405
1406 if (down_interruptible(&tsock->sem))
1407 return -ERESTARTSYS;
1408
1409 sock_lock(tsock);
1410
1411 switch (sock->state) {
1412 case SS_CONNECTED:
1413
1414 /* Send 'FIN+' or 'FIN-' message to peer */
1415
1416 sock_unlock(tsock);
1417restart:
1418 if ((buf = skb_dequeue(&sock->sk->sk_receive_queue))) {
1419 atomic_dec(&tipc_queue_size);
1420 if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf))) {
1421 buf_discard(buf);
1422 goto restart;
1423 }
1424 tipc_reject_msg(buf, TIPC_CONN_SHUTDOWN);
1425 }
1426 else {
1427 tipc_shutdown(tsock->p->ref);
1428 }
1429 sock_lock(tsock);
1430
1431 /* fall through */
1432
1433 case SS_DISCONNECTING:
1434
1435 /* Discard any unreceived messages */
1436
1437 while ((buf = skb_dequeue(&sock->sk->sk_receive_queue))) {
1438 atomic_dec(&tipc_queue_size);
1439 buf_discard(buf);
1440 }
1441 tsock->p->conn_unacked = 0;
1442
1443 /* fall through */
1444
1445 case SS_CONNECTING:
1446 sock->state = SS_DISCONNECTING;
1447 res = 0;
1448 break;
1449
1450 default:
1451 res = -ENOTCONN;
1452 }
1453
1454 sock_unlock(tsock);
1455
1456 up(&tsock->sem);
1457 return res;
1458}
1459
1460/**
1461 * setsockopt - set socket option
1462 * @sock: socket structure
1463 * @lvl: option level
1464 * @opt: option identifier
1465 * @ov: pointer to new option value
1466 * @ol: length of option value
1467 *
1468 * For stream sockets only, accepts and ignores all IPPROTO_TCP options
1469 * (to ease compatibility).
1470 *
1471 * Returns 0 on success, errno otherwise
1472 */
1473
1474static int setsockopt(struct socket *sock, int lvl, int opt, char *ov, int ol)
1475{
1476 struct tipc_sock *tsock = tipc_sk(sock->sk);
1477 u32 value;
1478 int res;
1479
1480 if ((lvl == IPPROTO_TCP) && (sock->type == SOCK_STREAM))
1481 return 0;
1482 if (lvl != SOL_TIPC)
1483 return -ENOPROTOOPT;
1484 if (ol < sizeof(value))
1485 return -EINVAL;
1486 if ((res = get_user(value, (u32 *)ov)))
1487 return res;
1488
1489 if (down_interruptible(&tsock->sem))
1490 return -ERESTARTSYS;
1491
1492 switch (opt) {
1493 case TIPC_IMPORTANCE:
1494 res = tipc_set_portimportance(tsock->p->ref, value);
1495 break;
1496 case TIPC_SRC_DROPPABLE:
1497 if (sock->type != SOCK_STREAM)
1498 res = tipc_set_portunreliable(tsock->p->ref, value);
1499 else
1500 res = -ENOPROTOOPT;
1501 break;
1502 case TIPC_DEST_DROPPABLE:
1503 res = tipc_set_portunreturnable(tsock->p->ref, value);
1504 break;
1505 case TIPC_CONN_TIMEOUT:
1506 sock->sk->sk_rcvtimeo = (value * HZ / 1000);
1507 break;
1508 default:
1509 res = -EINVAL;
1510 }
1511
1512 up(&tsock->sem);
1513 return res;
1514}
1515
1516/**
1517 * getsockopt - get socket option
1518 * @sock: socket structure
1519 * @lvl: option level
1520 * @opt: option identifier
1521 * @ov: receptacle for option value
1522 * @ol: receptacle for length of option value
1523 *
1524 * For stream sockets only, returns 0 length result for all IPPROTO_TCP options
1525 * (to ease compatibility).
1526 *
1527 * Returns 0 on success, errno otherwise
1528 */
1529
1530static int getsockopt(struct socket *sock, int lvl, int opt, char *ov, int *ol)
1531{
1532 struct tipc_sock *tsock = tipc_sk(sock->sk);
1533 int len;
1534 u32 value;
1535 int res;
1536
1537 if ((lvl == IPPROTO_TCP) && (sock->type == SOCK_STREAM))
1538 return put_user(0, ol);
1539 if (lvl != SOL_TIPC)
1540 return -ENOPROTOOPT;
1541 if ((res = get_user(len, ol)))
1542 return res;
1543
1544 if (down_interruptible(&tsock->sem))
1545 return -ERESTARTSYS;
1546
1547 switch (opt) {
1548 case TIPC_IMPORTANCE:
1549 res = tipc_portimportance(tsock->p->ref, &value);
1550 break;
1551 case TIPC_SRC_DROPPABLE:
1552 res = tipc_portunreliable(tsock->p->ref, &value);
1553 break;
1554 case TIPC_DEST_DROPPABLE:
1555 res = tipc_portunreturnable(tsock->p->ref, &value);
1556 break;
1557 case TIPC_CONN_TIMEOUT:
1558 value = (sock->sk->sk_rcvtimeo * 1000) / HZ;
1559 break;
1560 default:
1561 res = -EINVAL;
1562 }
1563
1564 if (res) {
1565 /* "get" failed */
1566 }
1567 else if (len < sizeof(value)) {
1568 res = -EINVAL;
1569 }
1570 else if ((res = copy_to_user(ov, &value, sizeof(value)))) {
1571 /* couldn't return value */
1572 }
1573 else {
1574 res = put_user(sizeof(value), ol);
1575 }
1576
1577 up(&tsock->sem);
1578 return res;
1579}
1580
1581/**
1582 * Placeholders for non-implemented functionality
1583 *
1584 * Returns error code (POSIX-compliant where defined)
1585 */
1586
1587static int ioctl(struct socket *s, u32 cmd, unsigned long arg)
1588{
1589 return -EINVAL;
1590}
1591
1592static int no_mmap(struct file *file, struct socket *sock,
1593 struct vm_area_struct *vma)
1594{
1595 return -EINVAL;
1596}
1597static ssize_t no_sendpage(struct socket *sock, struct page *page,
1598 int offset, size_t size, int flags)
1599{
1600 return -EINVAL;
1601}
1602
1603static int no_skpair(struct socket *s1, struct socket *s2)
1604{
1605 return -EOPNOTSUPP;
1606}
1607
1608/**
1609 * Protocol switches for the various types of TIPC sockets
1610 */
1611
1612static struct proto_ops msg_ops = {
1613 .owner = THIS_MODULE,
1614 .family = AF_TIPC,
1615 .release = release,
1616 .bind = bind,
1617 .connect = connect,
1618 .socketpair = no_skpair,
1619 .accept = accept,
1620 .getname = get_name,
1621 .poll = poll,
1622 .ioctl = ioctl,
1623 .listen = listen,
1624 .shutdown = shutdown,
1625 .setsockopt = setsockopt,
1626 .getsockopt = getsockopt,
1627 .sendmsg = send_msg,
1628 .recvmsg = recv_msg,
1629 .mmap = no_mmap,
1630 .sendpage = no_sendpage
1631};
1632
1633static struct proto_ops packet_ops = {
1634 .owner = THIS_MODULE,
1635 .family = AF_TIPC,
1636 .release = release,
1637 .bind = bind,
1638 .connect = connect,
1639 .socketpair = no_skpair,
1640 .accept = accept,
1641 .getname = get_name,
1642 .poll = poll,
1643 .ioctl = ioctl,
1644 .listen = listen,
1645 .shutdown = shutdown,
1646 .setsockopt = setsockopt,
1647 .getsockopt = getsockopt,
1648 .sendmsg = send_packet,
1649 .recvmsg = recv_msg,
1650 .mmap = no_mmap,
1651 .sendpage = no_sendpage
1652};
1653
1654static struct proto_ops stream_ops = {
1655 .owner = THIS_MODULE,
1656 .family = AF_TIPC,
1657 .release = release,
1658 .bind = bind,
1659 .connect = connect,
1660 .socketpair = no_skpair,
1661 .accept = accept,
1662 .getname = get_name,
1663 .poll = poll,
1664 .ioctl = ioctl,
1665 .listen = listen,
1666 .shutdown = shutdown,
1667 .setsockopt = setsockopt,
1668 .getsockopt = getsockopt,
1669 .sendmsg = send_stream,
1670 .recvmsg = recv_stream,
1671 .mmap = no_mmap,
1672 .sendpage = no_sendpage
1673};
1674
1675static struct net_proto_family tipc_family_ops = {
1676 .owner = THIS_MODULE,
1677 .family = AF_TIPC,
1678 .create = tipc_create
1679};
1680
1681static struct proto tipc_proto = {
1682 .name = "TIPC",
1683 .owner = THIS_MODULE,
1684 .obj_size = sizeof(struct tipc_sock)
1685};
1686
1687/**
1688 * socket_init - initialize TIPC socket interface
1689 *
1690 * Returns 0 on success, errno otherwise
1691 */
1692int socket_init(void)
1693{
1694 int res;
1695
1696 res = proto_register(&tipc_proto, 1);
1697 if (res) {
1698 err("Failed to register TIPC protocol type\n");
1699 goto out;
1700 }
1701
1702 res = sock_register(&tipc_family_ops);
1703 if (res) {
1704 err("Failed to register TIPC socket type\n");
1705 proto_unregister(&tipc_proto);
1706 goto out;
1707 }
1708
1709 sockets_enabled = 1;
1710 out:
1711 return res;
1712}
1713
1714/**
1715 * sock_stop - stop TIPC socket interface
1716 */
1717void socket_stop(void)
1718{
1719 if (!sockets_enabled)
1720 return;
1721
1722 sockets_enabled = 0;
1723 sock_unregister(tipc_family_ops.family);
1724 proto_unregister(&tipc_proto);
1725}
1726
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c
new file mode 100644
index 000000000000..80e219ba527d
--- /dev/null
+++ b/net/tipc/subscr.c
@@ -0,0 +1,527 @@
1/*
2 * net/tipc/subscr.c: TIPC subscription service
3 *
4 * Copyright (c) 2000-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include "core.h"
38#include "dbg.h"
39#include "subscr.h"
40#include "name_table.h"
41#include "ref.h"
42
43/**
44 * struct subscriber - TIPC network topology subscriber
45 * @ref: object reference to subscriber object itself
46 * @lock: pointer to spinlock controlling access to subscriber object
47 * @subscriber_list: adjacent subscribers in top. server's list of subscribers
48 * @subscription_list: list of subscription objects for this subscriber
49 * @port_ref: object reference to port used to communicate with subscriber
50 * @swap: indicates if subscriber uses opposite endianness in its messages
51 */
52
53struct subscriber {
54 u32 ref;
55 spinlock_t *lock;
56 struct list_head subscriber_list;
57 struct list_head subscription_list;
58 u32 port_ref;
59 int swap;
60};
61
62/**
63 * struct top_srv - TIPC network topology subscription service
64 * @user_ref: TIPC userid of subscription service
65 * @setup_port: reference to TIPC port that handles subscription requests
66 * @subscription_count: number of active subscriptions (not subscribers!)
67 * @subscriber_list: list of ports subscribing to service
68 * @lock: spinlock govering access to subscriber list
69 */
70
71struct top_srv {
72 u32 user_ref;
73 u32 setup_port;
74 atomic_t subscription_count;
75 struct list_head subscriber_list;
76 spinlock_t lock;
77};
78
79static struct top_srv topsrv = { 0 };
80
81/**
82 * htohl - convert value to endianness used by destination
83 * @in: value to convert
84 * @swap: non-zero if endianness must be reversed
85 *
86 * Returns converted value
87 */
88
89static inline u32 htohl(u32 in, int swap)
90{
91 char *c = (char *)&in;
92
93 return swap ? ((c[3] << 3) + (c[2] << 2) + (c[1] << 1) + c[0]) : in;
94}
95
96/**
97 * subscr_send_event - send a message containing a tipc_event to the subscriber
98 */
99
100static void subscr_send_event(struct subscription *sub,
101 u32 found_lower,
102 u32 found_upper,
103 u32 event,
104 u32 port_ref,
105 u32 node)
106{
107 struct iovec msg_sect;
108
109 msg_sect.iov_base = (void *)&sub->evt;
110 msg_sect.iov_len = sizeof(struct tipc_event);
111
112 sub->evt.event = htohl(event, sub->owner->swap);
113 sub->evt.found_lower = htohl(found_lower, sub->owner->swap);
114 sub->evt.found_upper = htohl(found_upper, sub->owner->swap);
115 sub->evt.port.ref = htohl(port_ref, sub->owner->swap);
116 sub->evt.port.node = htohl(node, sub->owner->swap);
117 tipc_send(sub->owner->port_ref, 1, &msg_sect);
118}
119
120/**
121 * subscr_overlap - test for subscription overlap with the given values
122 *
123 * Returns 1 if there is overlap, otherwise 0.
124 */
125
126int subscr_overlap(struct subscription *sub,
127 u32 found_lower,
128 u32 found_upper)
129
130{
131 if (found_lower < sub->seq.lower)
132 found_lower = sub->seq.lower;
133 if (found_upper > sub->seq.upper)
134 found_upper = sub->seq.upper;
135 if (found_lower > found_upper)
136 return 0;
137 return 1;
138}
139
140/**
141 * subscr_report_overlap - issue event if there is subscription overlap
142 *
143 * Protected by nameseq.lock in name_table.c
144 */
145
146void subscr_report_overlap(struct subscription *sub,
147 u32 found_lower,
148 u32 found_upper,
149 u32 event,
150 u32 port_ref,
151 u32 node,
152 int must)
153{
154 dbg("Rep overlap %u:%u,%u<->%u,%u\n", sub->seq.type, sub->seq.lower,
155 sub->seq.upper, found_lower, found_upper);
156 if (!subscr_overlap(sub, found_lower, found_upper))
157 return;
158 if (!must && (sub->filter != TIPC_SUB_PORTS))
159 return;
160 subscr_send_event(sub, found_lower, found_upper, event, port_ref, node);
161}
162
163/**
164 * subscr_timeout - subscription timeout has occurred
165 */
166
167static void subscr_timeout(struct subscription *sub)
168{
169 struct subscriber *subscriber;
170 u32 subscriber_ref;
171
172 /* Validate subscriber reference (in case subscriber is terminating) */
173
174 subscriber_ref = sub->owner->ref;
175 subscriber = (struct subscriber *)ref_lock(subscriber_ref);
176 if (subscriber == NULL)
177 return;
178
179 /* Unlink subscription from name table */
180
181 nametbl_unsubscribe(sub);
182
183 /* Notify subscriber of timeout, then unlink subscription */
184
185 subscr_send_event(sub,
186 sub->evt.s.seq.lower,
187 sub->evt.s.seq.upper,
188 TIPC_SUBSCR_TIMEOUT,
189 0,
190 0);
191 list_del(&sub->subscription_list);
192
193 /* Now destroy subscription */
194
195 ref_unlock(subscriber_ref);
196 k_term_timer(&sub->timer);
197 kfree(sub);
198 atomic_dec(&topsrv.subscription_count);
199}
200
201/**
202 * subscr_terminate - terminate communication with a subscriber
203 *
204 * Called with subscriber locked. Routine must temporarily release this lock
205 * to enable subscription timeout routine(s) to finish without deadlocking;
206 * the lock is then reclaimed to allow caller to release it upon return.
207 * (This should work even in the unlikely event some other thread creates
208 * a new object reference in the interim that uses this lock; this routine will
209 * simply wait for it to be released, then claim it.)
210 */
211
212static void subscr_terminate(struct subscriber *subscriber)
213{
214 struct subscription *sub;
215 struct subscription *sub_temp;
216
217 /* Invalidate subscriber reference */
218
219 ref_discard(subscriber->ref);
220 spin_unlock_bh(subscriber->lock);
221
222 /* Destroy any existing subscriptions for subscriber */
223
224 list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list,
225 subscription_list) {
226 if (sub->timeout != TIPC_WAIT_FOREVER) {
227 k_cancel_timer(&sub->timer);
228 k_term_timer(&sub->timer);
229 }
230 nametbl_unsubscribe(sub);
231 list_del(&sub->subscription_list);
232 dbg("Term: Removed sub %u,%u,%u from subscriber %x list\n",
233 sub->seq.type, sub->seq.lower, sub->seq.upper, subscriber);
234 kfree(sub);
235 atomic_dec(&topsrv.subscription_count);
236 }
237
238 /* Sever connection to subscriber */
239
240 tipc_shutdown(subscriber->port_ref);
241 tipc_deleteport(subscriber->port_ref);
242
243 /* Remove subscriber from topology server's subscriber list */
244
245 spin_lock_bh(&topsrv.lock);
246 list_del(&subscriber->subscriber_list);
247 spin_unlock_bh(&topsrv.lock);
248
249 /* Now destroy subscriber */
250
251 spin_lock_bh(subscriber->lock);
252 kfree(subscriber);
253}
254
255/**
256 * subscr_subscribe - create subscription for subscriber
257 *
258 * Called with subscriber locked
259 */
260
261static void subscr_subscribe(struct tipc_subscr *s,
262 struct subscriber *subscriber)
263{
264 struct subscription *sub;
265
266 /* Refuse subscription if global limit exceeded */
267
268 if (atomic_read(&topsrv.subscription_count) >= tipc_max_subscriptions) {
269 warn("Failed: max %u subscriptions\n", tipc_max_subscriptions);
270 subscr_terminate(subscriber);
271 return;
272 }
273
274 /* Allocate subscription object */
275
276 sub = kmalloc(sizeof(*sub), GFP_ATOMIC);
277 if (sub == NULL) {
278 warn("Memory squeeze; ignoring subscription\n");
279 subscr_terminate(subscriber);
280 return;
281 }
282
283 /* Determine/update subscriber's endianness */
284
285 if ((s->filter == TIPC_SUB_PORTS) || (s->filter == TIPC_SUB_SERVICE))
286 subscriber->swap = 0;
287 else
288 subscriber->swap = 1;
289
290 /* Initialize subscription object */
291
292 memset(sub, 0, sizeof(*sub));
293 sub->seq.type = htohl(s->seq.type, subscriber->swap);
294 sub->seq.lower = htohl(s->seq.lower, subscriber->swap);
295 sub->seq.upper = htohl(s->seq.upper, subscriber->swap);
296 sub->timeout = htohl(s->timeout, subscriber->swap);
297 sub->filter = htohl(s->filter, subscriber->swap);
298 if ((((sub->filter != TIPC_SUB_PORTS)
299 && (sub->filter != TIPC_SUB_SERVICE)))
300 || (sub->seq.lower > sub->seq.upper)) {
301 warn("Rejecting illegal subscription %u,%u,%u\n",
302 sub->seq.type, sub->seq.lower, sub->seq.upper);
303 kfree(sub);
304 subscr_terminate(subscriber);
305 return;
306 }
307 memcpy(&sub->evt.s, s, sizeof(struct tipc_subscr));
308 INIT_LIST_HEAD(&sub->subscription_list);
309 INIT_LIST_HEAD(&sub->nameseq_list);
310 list_add(&sub->subscription_list, &subscriber->subscription_list);
311 atomic_inc(&topsrv.subscription_count);
312 if (sub->timeout != TIPC_WAIT_FOREVER) {
313 k_init_timer(&sub->timer,
314 (Handler)subscr_timeout, (unsigned long)sub);
315 k_start_timer(&sub->timer, sub->timeout);
316 }
317 sub->owner = subscriber;
318 nametbl_subscribe(sub);
319}
320
321/**
322 * subscr_conn_shutdown_event - handle termination request from subscriber
323 */
324
325static void subscr_conn_shutdown_event(void *usr_handle,
326 u32 portref,
327 struct sk_buff **buf,
328 unsigned char const *data,
329 unsigned int size,
330 int reason)
331{
332 struct subscriber *subscriber;
333 spinlock_t *subscriber_lock;
334
335 subscriber = ref_lock((u32)(unsigned long)usr_handle);
336 if (subscriber == NULL)
337 return;
338
339 subscriber_lock = subscriber->lock;
340 subscr_terminate(subscriber);
341 spin_unlock_bh(subscriber_lock);
342}
343
344/**
345 * subscr_conn_msg_event - handle new subscription request from subscriber
346 */
347
348static void subscr_conn_msg_event(void *usr_handle,
349 u32 port_ref,
350 struct sk_buff **buf,
351 const unchar *data,
352 u32 size)
353{
354 struct subscriber *subscriber;
355 spinlock_t *subscriber_lock;
356
357 subscriber = ref_lock((u32)(unsigned long)usr_handle);
358 if (subscriber == NULL)
359 return;
360
361 subscriber_lock = subscriber->lock;
362 if (size != sizeof(struct tipc_subscr))
363 subscr_terminate(subscriber);
364 else
365 subscr_subscribe((struct tipc_subscr *)data, subscriber);
366
367 spin_unlock_bh(subscriber_lock);
368}
369
370/**
371 * subscr_named_msg_event - handle request to establish a new subscriber
372 */
373
374static void subscr_named_msg_event(void *usr_handle,
375 u32 port_ref,
376 struct sk_buff **buf,
377 const unchar *data,
378 u32 size,
379 u32 importance,
380 struct tipc_portid const *orig,
381 struct tipc_name_seq const *dest)
382{
383 struct subscriber *subscriber;
384 struct iovec msg_sect = {0, 0};
385 spinlock_t *subscriber_lock;
386
387 dbg("subscr_named_msg_event: orig = %x own = %x,\n",
388 orig->node, tipc_own_addr);
389 if (size && (size != sizeof(struct tipc_subscr))) {
390 warn("Received tipc_subscr of invalid size\n");
391 return;
392 }
393
394 /* Create subscriber object */
395
396 subscriber = kmalloc(sizeof(struct subscriber), GFP_ATOMIC);
397 if (subscriber == NULL) {
398 warn("Memory squeeze; ignoring subscriber setup\n");
399 return;
400 }
401 memset(subscriber, 0, sizeof(struct subscriber));
402 INIT_LIST_HEAD(&subscriber->subscription_list);
403 INIT_LIST_HEAD(&subscriber->subscriber_list);
404 subscriber->ref = ref_acquire(subscriber, &subscriber->lock);
405 if (subscriber->ref == 0) {
406 warn("Failed to acquire subscriber reference\n");
407 kfree(subscriber);
408 return;
409 }
410
411 /* Establish a connection to subscriber */
412
413 tipc_createport(topsrv.user_ref,
414 (void *)(unsigned long)subscriber->ref,
415 importance,
416 0,
417 0,
418 subscr_conn_shutdown_event,
419 0,
420 0,
421 subscr_conn_msg_event,
422 0,
423 &subscriber->port_ref);
424 if (subscriber->port_ref == 0) {
425 warn("Memory squeeze; failed to create subscription port\n");
426 ref_discard(subscriber->ref);
427 kfree(subscriber);
428 return;
429 }
430 tipc_connect2port(subscriber->port_ref, orig);
431
432
433 /* Add subscriber to topology server's subscriber list */
434
435 ref_lock(subscriber->ref);
436 spin_lock_bh(&topsrv.lock);
437 list_add(&subscriber->subscriber_list, &topsrv.subscriber_list);
438 spin_unlock_bh(&topsrv.lock);
439
440 /*
441 * Subscribe now if message contains a subscription,
442 * otherwise send an empty response to complete connection handshaking
443 */
444
445 subscriber_lock = subscriber->lock;
446 if (size)
447 subscr_subscribe((struct tipc_subscr *)data, subscriber);
448 else
449 tipc_send(subscriber->port_ref, 1, &msg_sect);
450
451 spin_unlock_bh(subscriber_lock);
452}
453
454int subscr_start(void)
455{
456 struct tipc_name_seq seq = {TIPC_TOP_SRV, TIPC_TOP_SRV, TIPC_TOP_SRV};
457 int res = -1;
458
459 memset(&topsrv, 0, sizeof (topsrv));
460 topsrv.lock = SPIN_LOCK_UNLOCKED;
461 INIT_LIST_HEAD(&topsrv.subscriber_list);
462
463 spin_lock_bh(&topsrv.lock);
464 res = tipc_attach(&topsrv.user_ref, 0, 0);
465 if (res) {
466 spin_unlock_bh(&topsrv.lock);
467 return res;
468 }
469
470 res = tipc_createport(topsrv.user_ref,
471 0,
472 TIPC_CRITICAL_IMPORTANCE,
473 0,
474 0,
475 0,
476 0,
477 subscr_named_msg_event,
478 0,
479 0,
480 &topsrv.setup_port);
481 if (res)
482 goto failed;
483
484 res = nametbl_publish_rsv(topsrv.setup_port, TIPC_NODE_SCOPE, &seq);
485 if (res)
486 goto failed;
487
488 spin_unlock_bh(&topsrv.lock);
489 return 0;
490
491failed:
492 err("Failed to create subscription service\n");
493 tipc_detach(topsrv.user_ref);
494 topsrv.user_ref = 0;
495 spin_unlock_bh(&topsrv.lock);
496 return res;
497}
498
499void subscr_stop(void)
500{
501 struct subscriber *subscriber;
502 struct subscriber *subscriber_temp;
503 spinlock_t *subscriber_lock;
504
505 if (topsrv.user_ref) {
506 tipc_deleteport(topsrv.setup_port);
507 list_for_each_entry_safe(subscriber, subscriber_temp,
508 &topsrv.subscriber_list,
509 subscriber_list) {
510 ref_lock(subscriber->ref);
511 subscriber_lock = subscriber->lock;
512 subscr_terminate(subscriber);
513 spin_unlock_bh(subscriber_lock);
514 }
515 tipc_detach(topsrv.user_ref);
516 topsrv.user_ref = 0;
517 }
518}
519
520
521int tipc_ispublished(struct tipc_name const *name)
522{
523 u32 domain = 0;
524
525 return(nametbl_translate(name->type, name->instance,&domain) != 0);
526}
527
diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h
new file mode 100644
index 000000000000..ccff4efcb755
--- /dev/null
+++ b/net/tipc/subscr.h
@@ -0,0 +1,80 @@
1/*
2 * net/tipc/subscr.h: Include file for TIPC subscription service
3 *
4 * Copyright (c) 2003-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#ifndef _TIPC_SUBSCR_H
38#define _TIPC_SUBSCR_H
39
40/**
41 * struct subscription - TIPC network topology subscription object
42 * @seq: name sequence associated with subscription
43 * @timeout: duration of subscription (in ms)
44 * @filter: event filtering to be done for subscription
45 * @evt: template for events generated by subscription
46 * @subscription_list: adjacent subscriptions in subscriber's subscription list
47 * @nameseq_list: adjacent subscriptions in name sequence's subscription list
48 * @timer_ref: reference to timer governing subscription duration (may be NULL)
49 * @owner: pointer to subscriber object associated with this subscription
50 */
51
52struct subscription {
53 struct tipc_name_seq seq;
54 u32 timeout;
55 u32 filter;
56 struct tipc_event evt;
57 struct list_head subscription_list;
58 struct list_head nameseq_list;
59 struct timer_list timer;
60 struct subscriber *owner;
61};
62
63int subscr_overlap(struct subscription * sub,
64 u32 found_lower,
65 u32 found_upper);
66
67void subscr_report_overlap(struct subscription * sub,
68 u32 found_lower,
69 u32 found_upper,
70 u32 event,
71 u32 port_ref,
72 u32 node,
73 int must_report);
74
75int subscr_start(void);
76
77void subscr_stop(void);
78
79
80#endif
diff --git a/net/tipc/user_reg.c b/net/tipc/user_reg.c
new file mode 100644
index 000000000000..35ec7dc8211d
--- /dev/null
+++ b/net/tipc/user_reg.c
@@ -0,0 +1,265 @@
1/*
2 * net/tipc/user_reg.c: TIPC user registry code
3 *
4 * Copyright (c) 2000-2006, Ericsson AB
5 * Copyright (c) 2004-2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include "core.h"
38#include "user_reg.h"
39
40/*
41 * TIPC user registry keeps track of users of the tipc_port interface.
42 *
43 * The registry utilizes an array of "TIPC user" entries;
44 * a user's ID is the index of their associated array entry.
45 * Array entry 0 is not used, so userid 0 is not valid;
46 * TIPC sometimes uses this value to denote an anonymous user.
47 * The list of free entries is initially chained from last entry to entry 1.
48 */
49
50/**
51 * struct tipc_user - registered TIPC user info
52 * @next: index of next free registry entry (or -1 for an allocated entry)
53 * @callback: ptr to routine to call when TIPC mode changes (NULL if none)
54 * @usr_handle: user-defined value passed to callback routine
55 * @ports: list of user ports owned by the user
56 */
57
58struct tipc_user {
59 int next;
60 tipc_mode_event callback;
61 void *usr_handle;
62 struct list_head ports;
63};
64
65#define MAX_USERID 64
66#define USER_LIST_SIZE ((MAX_USERID + 1) * sizeof(struct tipc_user))
67
68static struct tipc_user *users = 0;
69static u32 next_free_user = MAX_USERID + 1;
70static spinlock_t reg_lock = SPIN_LOCK_UNLOCKED;
71
72/**
73 * reg_init - create TIPC user registry (but don't activate it)
74 *
75 * If registry has been pre-initialized it is left "as is".
76 * NOTE: This routine may be called when TIPC is inactive.
77 */
78
79static int reg_init(void)
80{
81 u32 i;
82
83 spin_lock_bh(&reg_lock);
84 if (!users) {
85 users = (struct tipc_user *)kmalloc(USER_LIST_SIZE, GFP_ATOMIC);
86 if (users) {
87 memset(users, 0, USER_LIST_SIZE);
88 for (i = 1; i <= MAX_USERID; i++) {
89 users[i].next = i - 1;
90 }
91 next_free_user = MAX_USERID;
92 }
93 }
94 spin_unlock_bh(&reg_lock);
95 return users ? TIPC_OK : -ENOMEM;
96}
97
98/**
99 * reg_callback - inform TIPC user about current operating mode
100 */
101
102static void reg_callback(struct tipc_user *user_ptr)
103{
104 tipc_mode_event cb;
105 void *arg;
106
107 spin_lock_bh(&reg_lock);
108 cb = user_ptr->callback;
109 arg = user_ptr->usr_handle;
110 spin_unlock_bh(&reg_lock);
111
112 if (cb)
113 cb(arg, tipc_mode, tipc_own_addr);
114}
115
116/**
117 * reg_start - activate TIPC user registry
118 */
119
120int reg_start(void)
121{
122 u32 u;
123 int res;
124
125 if ((res = reg_init()))
126 return res;
127
128 for (u = 1; u <= MAX_USERID; u++) {
129 if (users[u].callback)
130 k_signal((Handler)reg_callback,
131 (unsigned long)&users[u]);
132 }
133 return TIPC_OK;
134}
135
136/**
137 * reg_stop - shut down & delete TIPC user registry
138 */
139
140void reg_stop(void)
141{
142 int id;
143
144 if (!users)
145 return;
146
147 for (id = 1; id <= MAX_USERID; id++) {
148 if (users[id].callback)
149 reg_callback(&users[id]);
150 }
151 kfree(users);
152 users = 0;
153}
154
155/**
156 * tipc_attach - register a TIPC user
157 *
158 * NOTE: This routine may be called when TIPC is inactive.
159 */
160
161int tipc_attach(u32 *userid, tipc_mode_event cb, void *usr_handle)
162{
163 struct tipc_user *user_ptr;
164
165 if ((tipc_mode == TIPC_NOT_RUNNING) && !cb)
166 return -ENOPROTOOPT;
167 if (!users)
168 reg_init();
169
170 spin_lock_bh(&reg_lock);
171 if (!next_free_user) {
172 spin_unlock_bh(&reg_lock);
173 return -EBUSY;
174 }
175 user_ptr = &users[next_free_user];
176 *userid = next_free_user;
177 next_free_user = user_ptr->next;
178 user_ptr->next = -1;
179 spin_unlock_bh(&reg_lock);
180
181 user_ptr->callback = cb;
182 user_ptr->usr_handle = usr_handle;
183 INIT_LIST_HEAD(&user_ptr->ports);
184 atomic_inc(&tipc_user_count);
185
186 if (cb && (tipc_mode != TIPC_NOT_RUNNING))
187 k_signal((Handler)reg_callback, (unsigned long)user_ptr);
188 return TIPC_OK;
189}
190
191/**
192 * tipc_detach - deregister a TIPC user
193 */
194
195void tipc_detach(u32 userid)
196{
197 struct tipc_user *user_ptr;
198 struct list_head ports_temp;
199 struct user_port *up_ptr, *temp_up_ptr;
200
201 if ((userid == 0) || (userid > MAX_USERID))
202 return;
203
204 spin_lock_bh(&reg_lock);
205 if ((!users) || (users[userid].next >= 0)) {
206 spin_unlock_bh(&reg_lock);
207 return;
208 }
209
210 user_ptr = &users[userid];
211 user_ptr->callback = NULL;
212 INIT_LIST_HEAD(&ports_temp);
213 list_splice(&user_ptr->ports, &ports_temp);
214 user_ptr->next = next_free_user;
215 next_free_user = userid;
216 spin_unlock_bh(&reg_lock);
217
218 atomic_dec(&tipc_user_count);
219
220 list_for_each_entry_safe(up_ptr, temp_up_ptr, &ports_temp, uport_list) {
221 tipc_deleteport(up_ptr->ref);
222 }
223}
224
225/**
226 * reg_add_port - register a user's driver port
227 */
228
229int reg_add_port(struct user_port *up_ptr)
230{
231 struct tipc_user *user_ptr;
232
233 if (up_ptr->user_ref == 0)
234 return TIPC_OK;
235 if (up_ptr->user_ref > MAX_USERID)
236 return -EINVAL;
237 if ((tipc_mode == TIPC_NOT_RUNNING) || !users )
238 return -ENOPROTOOPT;
239
240 spin_lock_bh(&reg_lock);
241 user_ptr = &users[up_ptr->user_ref];
242 list_add(&up_ptr->uport_list, &user_ptr->ports);
243 spin_unlock_bh(&reg_lock);
244 return TIPC_OK;
245}
246
247/**
248 * reg_remove_port - deregister a user's driver port
249 */
250
251int reg_remove_port(struct user_port *up_ptr)
252{
253 if (up_ptr->user_ref == 0)
254 return TIPC_OK;
255 if (up_ptr->user_ref > MAX_USERID)
256 return -EINVAL;
257 if (!users )
258 return -ENOPROTOOPT;
259
260 spin_lock_bh(&reg_lock);
261 list_del_init(&up_ptr->uport_list);
262 spin_unlock_bh(&reg_lock);
263 return TIPC_OK;
264}
265
diff --git a/net/tipc/user_reg.h b/net/tipc/user_reg.h
new file mode 100644
index 000000000000..122ca9be3671
--- /dev/null
+++ b/net/tipc/user_reg.h
@@ -0,0 +1,48 @@
1/*
2 * net/tipc/user_reg.h: Include file for TIPC user registry code
3 *
4 * Copyright (c) 2000-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#ifndef _TIPC_USER_REG_H
38#define _TIPC_USER_REG_H
39
40#include "port.h"
41
42int reg_start(void);
43void reg_stop(void);
44
45int reg_add_port(struct user_port *up_ptr);
46int reg_remove_port(struct user_port *up_ptr);
47
48#endif
diff --git a/net/tipc/zone.c b/net/tipc/zone.c
new file mode 100644
index 000000000000..4eaef662d568
--- /dev/null
+++ b/net/tipc/zone.c
@@ -0,0 +1,169 @@
1/*
2 * net/tipc/zone.c: TIPC zone management routines
3 *
4 * Copyright (c) 2000-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include "core.h"
38#include "zone.h"
39#include "net.h"
40#include "addr.h"
41#include "node_subscr.h"
42#include "cluster.h"
43#include "node.h"
44
45struct _zone *zone_create(u32 addr)
46{
47 struct _zone *z_ptr = 0;
48 u32 z_num;
49
50 if (!addr_domain_valid(addr))
51 return 0;
52
53 z_ptr = (struct _zone *)kmalloc(sizeof(*z_ptr), GFP_ATOMIC);
54 if (z_ptr != NULL) {
55 memset(z_ptr, 0, sizeof(*z_ptr));
56 z_num = tipc_zone(addr);
57 z_ptr->addr = tipc_addr(z_num, 0, 0);
58 net.zones[z_num] = z_ptr;
59 }
60 return z_ptr;
61}
62
63void zone_delete(struct _zone *z_ptr)
64{
65 u32 c_num;
66
67 if (!z_ptr)
68 return;
69 for (c_num = 1; c_num <= tipc_max_clusters; c_num++) {
70 cluster_delete(z_ptr->clusters[c_num]);
71 }
72 kfree(z_ptr);
73}
74
75void zone_attach_cluster(struct _zone *z_ptr, struct cluster *c_ptr)
76{
77 u32 c_num = tipc_cluster(c_ptr->addr);
78
79 assert(c_ptr->addr);
80 assert(c_num <= tipc_max_clusters);
81 assert(z_ptr->clusters[c_num] == 0);
82 z_ptr->clusters[c_num] = c_ptr;
83}
84
85void zone_remove_as_router(struct _zone *z_ptr, u32 router)
86{
87 u32 c_num;
88
89 for (c_num = 1; c_num <= tipc_max_clusters; c_num++) {
90 if (z_ptr->clusters[c_num]) {
91 cluster_remove_as_router(z_ptr->clusters[c_num],
92 router);
93 }
94 }
95}
96
97void zone_send_external_routes(struct _zone *z_ptr, u32 dest)
98{
99 u32 c_num;
100
101 for (c_num = 1; c_num <= tipc_max_clusters; c_num++) {
102 if (z_ptr->clusters[c_num]) {
103 if (in_own_cluster(z_ptr->addr))
104 continue;
105 cluster_send_ext_routes(z_ptr->clusters[c_num], dest);
106 }
107 }
108}
109
110struct node *zone_select_remote_node(struct _zone *z_ptr, u32 addr, u32 ref)
111{
112 struct cluster *c_ptr;
113 struct node *n_ptr;
114 u32 c_num;
115
116 if (!z_ptr)
117 return 0;
118 c_ptr = z_ptr->clusters[tipc_cluster(addr)];
119 if (!c_ptr)
120 return 0;
121 n_ptr = cluster_select_node(c_ptr, ref);
122 if (n_ptr)
123 return n_ptr;
124
125 /* Links to any other clusters within this zone ? */
126 for (c_num = 1; c_num <= tipc_max_clusters; c_num++) {
127 c_ptr = z_ptr->clusters[c_num];
128 if (!c_ptr)
129 return 0;
130 n_ptr = cluster_select_node(c_ptr, ref);
131 if (n_ptr)
132 return n_ptr;
133 }
134 return 0;
135}
136
137u32 zone_select_router(struct _zone *z_ptr, u32 addr, u32 ref)
138{
139 struct cluster *c_ptr;
140 u32 c_num;
141 u32 router;
142
143 if (!z_ptr)
144 return 0;
145 c_ptr = z_ptr->clusters[tipc_cluster(addr)];
146 router = c_ptr ? cluster_select_router(c_ptr, ref) : 0;
147 if (router)
148 return router;
149
150 /* Links to any other clusters within the zone? */
151 for (c_num = 1; c_num <= tipc_max_clusters; c_num++) {
152 c_ptr = z_ptr->clusters[c_num];
153 router = c_ptr ? cluster_select_router(c_ptr, ref) : 0;
154 if (router)
155 return router;
156 }
157 return 0;
158}
159
160
161u32 zone_next_node(u32 addr)
162{
163 struct cluster *c_ptr = cluster_find(addr);
164
165 if (c_ptr)
166 return cluster_next_node(c_ptr, addr);
167 return 0;
168}
169
diff --git a/net/tipc/zone.h b/net/tipc/zone.h
new file mode 100644
index 000000000000..4326f78d8292
--- /dev/null
+++ b/net/tipc/zone.h
@@ -0,0 +1,71 @@
1/*
2 * net/tipc/zone.h: Include file for TIPC zone management routines
3 *
4 * Copyright (c) 2000-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#ifndef _TIPC_ZONE_H
38#define _TIPC_ZONE_H
39
40#include "node_subscr.h"
41#include "net.h"
42
43
44/**
45 * struct _zone - TIPC zone structure
46 * @addr: network address of zone
47 * @clusters: array of pointers to all clusters within zone
48 * @links: (used for inter-zone communication)
49 */
50
51struct _zone {
52 u32 addr;
53 struct cluster *clusters[2]; /* currently limited to just 1 cluster */
54 u32 links;
55};
56
57struct node *zone_select_remote_node(struct _zone *z_ptr, u32 addr, u32 ref);
58u32 zone_select_router(struct _zone *z_ptr, u32 addr, u32 ref);
59void zone_remove_as_router(struct _zone *z_ptr, u32 router);
60void zone_send_external_routes(struct _zone *z_ptr, u32 dest);
61struct _zone *zone_create(u32 addr);
62void zone_delete(struct _zone *z_ptr);
63void zone_attach_cluster(struct _zone *z_ptr, struct cluster *c_ptr);
64u32 zone_next_node(u32 addr);
65
66static inline struct _zone *zone_find(u32 addr)
67{
68 return net.zones[tipc_zone(addr)];
69}
70
71#endif
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 12e4fb72bf0f..53d6c7bbf564 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -494,8 +494,7 @@ static inline void avc_print_ipv6_addr(struct audit_buffer *ab,
494 char *name1, char *name2) 494 char *name1, char *name2)
495{ 495{
496 if (!ipv6_addr_any(addr)) 496 if (!ipv6_addr_any(addr))
497 audit_log_format(ab, " %s=%04x:%04x:%04x:%04x:%04x:" 497 audit_log_format(ab, " %s=" NIP6_FMT, name1, NIP6(*addr));
498 "%04x:%04x:%04x", name1, NIP6(*addr));
499 if (port) 498 if (port)
500 audit_log_format(ab, " %s=%d", name2, ntohs(port)); 499 audit_log_format(ab, " %s=%d", name2, ntohs(port));
501} 500}
@@ -504,7 +503,7 @@ static inline void avc_print_ipv4_addr(struct audit_buffer *ab, u32 addr,
504 __be16 port, char *name1, char *name2) 503 __be16 port, char *name1, char *name2)
505{ 504{
506 if (addr) 505 if (addr)
507 audit_log_format(ab, " %s=%d.%d.%d.%d", name1, NIPQUAD(addr)); 506 audit_log_format(ab, " %s=" NIPQUAD_FMT, name1, NIPQUAD(addr));
508 if (port) 507 if (port)
509 audit_log_format(ab, " %s=%d", name2, ntohs(port)); 508 audit_log_format(ab, " %s=%d", name2, ntohs(port));
510} 509}
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 6647204e4636..b9f8d9731c3d 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1019,7 +1019,7 @@ static inline int dentry_has_perm(struct task_struct *tsk,
1019 has the same SID as the process. If av is zero, then 1019 has the same SID as the process. If av is zero, then
1020 access to the file is not checked, e.g. for cases 1020 access to the file is not checked, e.g. for cases
1021 where only the descriptor is affected like seek. */ 1021 where only the descriptor is affected like seek. */
1022static inline int file_has_perm(struct task_struct *tsk, 1022static int file_has_perm(struct task_struct *tsk,
1023 struct file *file, 1023 struct file *file,
1024 u32 av) 1024 u32 av)
1025{ 1025{
diff --git a/sound/oss/esssolo1.c b/sound/oss/esssolo1.c
index a4ecab2f0522..849b59f67ef5 100644
--- a/sound/oss/esssolo1.c
+++ b/sound/oss/esssolo1.c
@@ -515,7 +515,7 @@ static inline int prog_dmabuf_adc(struct solo1_state *s)
515 return 0; 515 return 0;
516} 516}
517 517
518static inline int prog_dmabuf_dac(struct solo1_state *s) 518static int prog_dmabuf_dac(struct solo1_state *s)
519{ 519{
520 unsigned long va; 520 unsigned long va;
521 int c; 521 int c;
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index 9ffb600321cb..3747a436f0cd 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -727,7 +727,7 @@ static void __apu_set_register(struct es1968 *chip, u16 channel, u8 reg, u16 dat
727 apu_data_set(chip, data); 727 apu_data_set(chip, data);
728} 728}
729 729
730static inline void apu_set_register(struct es1968 *chip, u16 channel, u8 reg, u16 data) 730static void apu_set_register(struct es1968 *chip, u16 channel, u8 reg, u16 data)
731{ 731{
732 unsigned long flags; 732 unsigned long flags;
733 spin_lock_irqsave(&chip->reg_lock, flags); 733 spin_lock_irqsave(&chip->reg_lock, flags);
@@ -743,7 +743,7 @@ static u16 __apu_get_register(struct es1968 *chip, u16 channel, u8 reg)
743 return __maestro_read(chip, IDR0_DATA_PORT); 743 return __maestro_read(chip, IDR0_DATA_PORT);
744} 744}
745 745
746static inline u16 apu_get_register(struct es1968 *chip, u16 channel, u8 reg) 746static u16 apu_get_register(struct es1968 *chip, u16 channel, u8 reg)
747{ 747{
748 unsigned long flags; 748 unsigned long flags;
749 u16 v; 749 u16 v;